[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\nlabels: bug\n---\n\n- Netron app and version: <!-- For example: 3.8.2 Desktop app, 2.9.0 Website or 3.9.2 Python Server -->\n- OS and browser version: <!-- For example macOS 10.15.6 (19G73) + Chrome 84.0.4147.89 -->\n\nSteps to Reproduce:\n\n1.\n2.\n\nPlease attach or link model files to reproduce the issue.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\nlabels: feature\n---\n<!-- Please search existing issues to avoid creating duplicates. -->\n<!-- Describe the feature you'd like. -->\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "\nname: Build\n\non:\n  push:\n    branches: [ '**' ]\n    tags-ignore: [ '**' ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  build:\n    name: Build\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        os: [ macos-latest, ubuntu-latest, windows-latest ]\n\n    steps:\n      - name: Clone Git repository\n        uses: actions/checkout@v4\n\n      - name: Install Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: latest\n\n      - name: Install Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: 3.x\n\n      - name: Install Packages\n        run: npm run install\n\n      - name: Validate\n        run: npm run validate\n\n      - name: Build Python Server\n        run: npm run build python\n\n      - name: Build Electron\n        shell: bash\n        run: |\n          npx electron-builder install-app-deps\n          case \"${{ matrix.os }}\" in\n            macos*)\n              npm run build electron mac\n              ;;\n            ubuntu*)\n              sudo apt-get install rpm --yes\n              npm run build electron linux\n              ;;\n            windows*)\n              npm run build electron windows\n              ;;\n          esac\n\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n\n    permissions:\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript', 'python' ]\n\n    steps:\n      - name: Clone Git repository\n        uses: actions/checkout@v4\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v3\n        with:\n          languages: ${{ matrix.language }}\n\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v3\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v3\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "\nname: Publish\n\non:\n  push:\n    tags: [ 'v**' ]\n\njobs:\n  publish:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        os: [ macos-latest, ubuntu-latest, windows-latest ]\n\n    steps:\n      - name: Check out Git repository\n        uses: actions/checkout@v4\n\n      - name: Git credentials\n        run: |\n          git config --global user.name ${{ secrets.PUBLISH_GITHUB_USER_NAME }}\n          git config --global user.email ${{ secrets.PUBLISH_GITHUB_USER_EMAIL }}\n\n      - name: Install Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: latest\n\n      - name: Install Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: 3.x\n\n      - name: Install Packages\n        run: npm run install\n\n      - name: Publish Electron\n        shell: bash\n        env:\n          GITHUB_TOKEN: ${{ secrets.PUBLISH_GITHUB_TOKEN }}\n          APPLE_API_KEY: ~/.private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8\n          APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}\n          APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}\n          CSC_LINK: ${{ secrets.CSC_LINK }}\n          CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}\n          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}\n          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}\n          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}\n        run: |\n          npx electron-builder install-app-deps\n          case \"${{ matrix.os }}\" in\n            macos*)\n              mkdir -p ~/.private_keys\n              echo '${{ secrets.APPLE_API_KEY }}' > ~/.private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8\n              npm run publish electron mac\n              ;;\n            ubuntu*)\n              sudo apt-get install rpm --yes\n              npm run publish electron linux\n              ;;\n            windows*)\n              unset CSC_LINK;\n              unset CSC_KEY_PASSWORD;\n              npm run publish electron windows\n              ;;\n          esac\n\n      - if: startsWith(matrix.os, 'ubuntu')\n        name: Publish Python\n        env:\n          TWINE_USERNAME: __token__\n          TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}\n        run: npm run publish python\n\n      - if: startsWith(matrix.os, 'ubuntu')\n        name: Publish Web\n        env:\n          GITHUB_TOKEN: ${{ secrets.PUBLISH_GITHUB_TOKEN }}\n          GITHUB_USER: ${{ secrets.PUBLISH_GITHUB_USER }}\n        run: git push origin HEAD:release --force\n\n      - if: false # startsWith(matrix.os, 'macos')\n        name: Publish cask\n        env:\n          GITHUB_TOKEN: ${{ secrets.PUBLISH_GITHUB_TOKEN }}\n          GITHUB_USER: ${{ secrets.PUBLISH_GITHUB_USER }}\n        run: npm run publish cask\n\n      - if: startsWith(matrix.os, 'windows')\n        name: Publish winget\n        env:\n          GITHUB_USER: ${{ secrets.PUBLISH_GITHUB_USER }}\n          GITHUB_TOKEN: ${{ secrets.PUBLISH_GITHUB_TOKEN }}\n          WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }}\n        run: npm run publish winget\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.DS_Store?\n.claude\n.eslintcache\n.ruff_cache\n.specify\n.yarn\ndist/*\nnode_modules/*\ntest-results/*\nthird_party/*\nyarn.lock\n*.pyc\n"
  },
  {
    "path": ".npmrc",
    "content": "loglevel=silent"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Desktop View\",\n            \"type\": \"chrome\",\n            \"request\": \"launch\",\n            \"runtimeExecutable\": \"${workspaceRoot}/node_modules/.bin/electron\",\n            \"windows\": {\n                \"runtimeExecutable\": \"${workspaceRoot}/node_modules/.bin/electron.cmd\"\n            },\n            \"osx\": {\n                \"runtimeExecutable\": \"${workspaceFolder}/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron\"\n            },\n            \"runtimeArgs\": [\n                \"${workspaceRoot}\",\n                \"--enable-logging\",\n                \"--remote-debugging-port=9222\"\n            ],\n            \"webRoot\": \"${workspaceRoot}\"\n        },\n        {\n            \"name\": \"Desktop App\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceFolder}/source/app.js\",\n            \"runtimeExecutable\": \"electron\",\n            \"osx\": {\n                \"runtimeExecutable\": \"${workspaceFolder}/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron\"\n            }\n        },\n        {\n            \"name\": \"Browser\",\n            \"type\": \"debugpy\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceFolder}/package.py\",\n            \"args\": [ \"build\", \"start\" ],\n            \"justMyCode\": true,\n            \"pathMappings\": [\n                {\n                    \"localRoot\": \"${workspaceFolder}/source\",\n                    \"remoteRoot\": \"${workspaceFolder}/dist/pypi/netron\",\n                }\n            ],\n            \"serverReadyAction\": {\n                \"action\": \"debugWithChrome\",\n                \"pattern\": \"Serving .*at http://localhost:([0-9]+)\",\n                \"uriFormat\": \"http://localhost:%s\",\n                \"webRoot\": \"${workspaceFolder}/source\",\n            },\n        },\n        {\n            \"name\": \"Test Models\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceFolder}/test/models.js\",\n            \"args\": [ \"tag:validation\" ],\n            \"console\": \"integratedTerminal\",\n        },\n        {\n            \"name\": \"Test Desktop\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"runtimeExecutable\": \"npm\",\n            \"runtimeArgs\": [\"run\", \"test\", \"desktop\"],\n            \"console\": \"integratedTerminal\",\n        },\n        {\n            \"name\": \"Test Browser\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"runtimeExecutable\": \"npm\",\n            \"runtimeArgs\": [\"run\", \"test\", \"browser\"],\n            \"console\": \"integratedTerminal\",\n        },\n        {\n            \"name\": \"Test Backend\",\n            \"type\": \"debugpy\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceFolder}/test/backend.py\",\n            \"args\": [],\n            \"console\": \"integratedTerminal\",\n            \"justMyCode\": true,\n            \"serverReadyAction\": {\n                \"action\": \"debugWithChrome\",\n                \"pattern\": \"Serving .*at http://localhost:([0-9]+)\",\n                \"uriFormat\": \"http://localhost:%s\",\n                \"webRoot\": \"${workspaceFolder}/source\",\n            },\n        },\n        {\n            \"name\": \"Tools Python\",\n            \"type\": \"debugpy\",\n            \"request\": \"launch\",\n            \"program\": \"${file}\",\n            \"args\": [],\n            \"console\": \"integratedTerminal\",\n            \"justMyCode\": true\n        },\n        {\n            \"name\": \"Tools JavaScript\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"program\": \"${file}\",\n            \"args\": [],\n            \"console\": \"integratedTerminal\",\n        }\n    ]\n}"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"eslint.lintTask.enable\": true,\n    \"files.exclude\": {\n        \"dist\": true,\n        \"node_modules\": true,\n        \"third_party\": true\n    },\n    \"search.exclude\": {\n        \"dist\": true,\n        \"node_modules\": true,\n        \"third_party\": true\n    }\n}"
  },
  {
    "path": "CITATION.cff",
    "content": "cff-version: 1.2.0\ntitle: \"Netron, Visualizer for neural network, deep learning, and machine learning models\"\nauthors:\n- family-names: \"Roeder\"\n  given-names: \"Lutz\"\n  orcid: \"https://orcid.org/0000-0003-4994-7839\"\ndoi: \"10.5281/zenodo.5854962\"\ndate-released: 2017-12-04\nlicense: \"MIT\"\nurl: \"https://github.com/lutzroeder/netron\"\nrepository-code: \"https://github.com/lutzroeder/netron\"\nmessage: \"If you use Netron in your research, please cite it using these metadata.\"\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to Develop Netron\n\n## Debugging\n\nNetron can run as both an [Electron](https://electronjs.org) app or a web app.\n\nTo start the Electron app, install [Node.js](https://nodejs.org) and run: \n\n```bash\ngit clone https://github.com/lutzroeder/netron\ncd netron\nnpm install\nnpm start\n```\n\nTo debug the Electron app, open the folder in [Visual Studio Code](https://code.visualstudio.com) and press <kbd>F5</kbd>. To attach the debugger to the render process select the `Debug` tab and pick `Desktop View` before launching.\n\nTo build and launch the web app, pick `Browser` in the `Debug` tab or run this command:\n\n```bash\npython package.py build start --browse\n```\n\n## Validation\n\nTo validate changes run:\n\n```bash\nnpm run lint\nnpm test [format] # e.g. npm test onnx\n```\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Lutz Roeder\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n<img width=\"400px\" height=\"100px\" src=\"https://github.com/lutzroeder/netron/raw/main/.github/logo-light.svg#gh-light-mode-only\">\n<img width=\"400px\" height=\"100px\" src=\"https://github.com/lutzroeder/netron/raw/main/.github/logo-dark.svg#gh-dark-mode-only\">\n</div>\n\nNetron is a viewer for neural network, deep learning and machine learning models.\n\nNetron supports ONNX, TensorFlow Lite, PyTorch, torch.export, ExecuTorch, Core ML, Keras, Caffe, Darknet, TensorFlow.js, Safetensors and NumPy.\n\nNetron has experimental support for TorchScript, MLIR, TensorFlow, OpenVINO, RKNN, ncnn, MNN, PaddlePaddle, GGUF and scikit-learn.\n\n<p align='center'><a href='https://www.lutzroeder.com/ai'><img src='.github/screenshot.png' width='800'></a></p>\n\n## Install\n\n**Browser**: [**Start**](https://netron.app) the browser version.\n\n**macOS**: [**Download**](https://github.com/lutzroeder/netron/releases/latest) the `.dmg` file or run `brew install --cask netron`.\n\n**Linux**: [**Download**](https://github.com/lutzroeder/netron/releases/latest) the `.deb` or `.rpm` file.\n\n**Windows**: [**Download**](https://github.com/lutzroeder/netron/releases/latest) the `.exe` installer or run `winget install -s winget netron`.\n\n**Python**: `pip install netron`, then run `netron [FILE]` or `netron.start('[FILE]')`.\n\n## Models\n\nSample model files to download or open using the browser version:\n\n * **ONNX**: [squeezenet](https://github.com/onnx/models/raw/main/validated/vision/classification/squeezenet/model/squeezenet1.0-3.onnx) [[open](https://netron.app?url=https://github.com/onnx/models/raw/main/validated/vision/classification/squeezenet/model/squeezenet1.0-3.onnx)]\n * **TorchScript**: [traced_online_pred_layer](https://github.com/ApolloAuto/apollo/raw/master/modules/prediction/data/traced_online_pred_layer.pt) [[open](https://netron.app?url=https://github.com/ApolloAuto/apollo/raw/master/modules/prediction/data/traced_online_pred_layer.pt)]\n * **TensorFlow Lite**: [yamnet](https://huggingface.co/thelou1s/yamnet/resolve/main/lite-model_yamnet_tflite_1.tflite) [[open](https://netron.app?url=https://huggingface.co/thelou1s/yamnet/blob/main/lite-model_yamnet_tflite_1.tflite)]\n * **TensorFlow**: [chessbot](https://github.com/srom/chessbot/raw/master/model/chessbot.pb) [[open](https://netron.app?url=https://github.com/srom/chessbot/raw/master/model/chessbot.pb)]\n * **Keras**: [mobilenet](https://github.com/aio-libs/aiohttp-demos/raw/master/demos/imagetagger/tests/data/mobilenet.h5) [[open](https://netron.app?url=https://github.com/aio-libs/aiohttp-demos/raw/master/demos/imagetagger/tests/data/mobilenet.h5)]\n\n* **MLIR**: [edge_detection](https://github.com/iree-org/iree/raw/main/tests/e2e/stablehlo_models/edge_detection.mlir) [[open](https://netron.app?url=https://github.com/iree-org/iree/blob/main/tests/e2e/stablehlo_models/edge_detection.mlir)]\n\n * **Core ML**: [exermote](https://github.com/Lausbert/Exermote/raw/master/ExermoteInference/ExermoteCoreML/ExermoteCoreML/Model/Exermote.mlmodel) [[open](https://netron.app?url=https://github.com/Lausbert/Exermote/raw/master/ExermoteInference/ExermoteCoreML/ExermoteCoreML/Model/Exermote.mlmodel)]\n * **Darknet**: [yolo](https://github.com/AlexeyAB/darknet/raw/master/cfg/yolo.cfg) [[open](https://netron.app?url=https://github.com/AlexeyAB/darknet/raw/master/cfg/yolo.cfg)]\n"
  },
  {
    "path": "eslint.config.js",
    "content": "\nexport default [\n    {\n        ignores: [\n            'dist/**',\n            'third_party/**',\n        ]\n    },\n    {\n        languageOptions: {\n            globals: {\n                atob: 'readonly',\n                BigInt: 'readonly',\n                console: 'readonly',\n                global: 'readonly',\n                process: 'readonly',\n                self: 'readonly',\n                TextDecoder: 'readonly',\n                TextEncoder: 'readonly',\n                window: 'readonly',\n            },\n            sourceType: 'module'\n        },\n        rules: {\n            'accessor-pairs': 'error',\n            'array-bracket-spacing': 'error',\n            'array-callback-return': 'error',\n            // 'arrow-body-style': 'error',\n            'arrow-parens': 'error',\n            'block-scoped-var': 'error',\n            'brace-style': 'error',\n            // 'camelcase': 'error',\n            // 'capitalized-comments': 'error',\n            // 'class-methods-use-this': 'error',\n            // 'complexity': 'error',\n            'computed-property-spacing': 'error',\n            'consistent-return': 'error',\n            'consistent-this': 'error',\n            'constructor-super': 'error',\n            'curly': 'error',\n            'default-case': 'error',\n            'default-case-last': 'error',\n            'default-param-last': 'error',\n            'dot-notation': 'error',\n            'eqeqeq': 'error',\n            'for-direction': 'error',\n            'func-name-matching': 'error',\n            // 'func-names': 'error',\n            'func-style': 'error',\n            'getter-return': 'error',\n            'grouped-accessor-pairs': 'error',\n            'guard-for-in': 'error',\n            'id-denylist': 'error',\n            // 'id-length': 'error',\n            'id-match': 'error',\n            'indent': ['error', 4, { 'SwitchCase': 1 }],\n            'init-declarations': 'error',\n            'keyword-spacing': 'error',\n            // 'line-comment-position': 'error',\n            // 'logical-assignment-operators': 'error',\n            // 'max-classes-per-file': 'error',\n            // 'max-depth': 'error',\n            // 'max-lines': 'error',\n            // 'max-lines-per-function': 'error',\n            'max-nested-callbacks': 'error',\n            // 'max-params': 'error',\n            // 'max-statements': 'error',\n            // 'multiline-comment-style': 'error',\n            // 'new-cap': 'error',\n            'no-alert': 'error',\n            'no-array-constructor': 'error',\n            'no-async-promise-executor': 'error',\n            'no-await-in-loop': 'error',\n            // 'no-bitwise': 'error',\n            'no-caller': 'error',\n            'no-case-declarations': 'error',\n            'no-class-assign': 'error',\n            'no-compare-neg-zero': 'error',\n            'no-cond-assign': 'error',\n            'no-console': 'error',\n            'no-const-assign': 'error',\n            'no-constant-binary-expression': 'error',\n            'no-constant-condition': 'error',\n            'no-constructor-return': 'error',\n            // 'no-continue': 'error',\n            'no-control-regex': 'error',\n            'no-debugger': 'error',\n            'no-delete-var': 'error',\n            'no-div-regex': 'error',\n            'no-dupe-args': 'error',\n            'no-dupe-class-members': 'error',\n            'no-dupe-else-if': 'error',\n            'no-dupe-keys': 'error',\n            'no-duplicate-case': 'error',\n            'no-duplicate-imports': 'error',\n            'no-else-return': 'error',\n            'no-empty': 'error',\n            'no-empty-character-class': 'error',\n            // 'no-empty-function': 'error',\n            'no-empty-pattern': 'error',\n            'no-empty-static-block': 'error',\n            'no-eq-null': 'error',\n            'no-eval': 'error',\n            'no-ex-assign': 'error',\n            'no-extend-native': 'error',\n            'no-extra-bind': 'error',\n            'no-extra-boolean-cast': 'error',\n            'no-extra-label': 'error',\n            'no-extra-semi': 'error',\n            'no-fallthrough': 'error',\n            'no-func-assign': 'error',\n            'no-global-assign': 'error',\n            'no-implicit-coercion': 'error',\n            'no-implicit-globals': 'error',\n            'no-implied-eval': 'error',\n            'no-import-assign': 'error',\n            // 'no-inline-comments': 'error',\n            'no-inner-declarations': 'error',\n            'no-invalid-regexp': 'error',\n            'no-invalid-this': 'error',\n            'no-irregular-whitespace': 'error',\n            'no-iterator': 'error',\n            'no-label-var': 'error',\n            'no-labels': 'error',\n            'no-lone-blocks': 'error',\n            'no-lonely-if': 'error',\n            'no-loop-func': 'error',\n            'no-loss-of-precision': 'error',\n            // 'no-magic-numbers': 'error',\n            'no-misleading-character-class': 'error',\n            'no-multi-assign': 'error',\n            'no-multi-str': 'error',\n            'no-multiple-empty-lines': ['error', { 'max': 1 }],\n            'no-negated-condition': 'error',\n            'no-nested-ternary': 'error',\n            'no-new': 'error',\n            'no-new-func': 'error',\n            'no-new-native-nonconstructor': 'error',\n            'no-new-wrappers': 'error',\n            'no-nonoctal-decimal-escape': 'error',\n            'no-obj-calls': 'error',\n            'no-object-constructor': 'error',\n            'no-octal': 'error',\n            'no-octal-escape': 'error',\n            // 'no-param-reassign': 'error',\n            // 'no-plusplus': 'error',\n            'no-promise-executor-return': 'error',\n            'no-proto': 'error',\n            'no-prototype-builtins': 'error',\n            'no-redeclare': 'error',\n            'no-regex-spaces': 'error',\n            'no-restricted-exports': 'error',\n            'no-restricted-globals': 'error',\n            'no-restricted-imports': 'error',\n            'no-restricted-properties': 'error',\n            'no-restricted-syntax': 'error',\n            'no-return-assign': 'error',\n            'no-script-url': 'error',\n            'no-self-assign': 'error',\n            'no-self-compare': 'error',\n            'no-sequences': 'error',\n            'no-setter-return': 'error',\n            // 'no-shadow': 'error',\n            'no-shadow-restricted-names': 'error',\n            'no-sparse-arrays': 'error',\n            'no-template-curly-in-string': 'error',\n            // 'no-ternary': 'error',\n            'no-this-before-super': 'error',\n            'no-throw-literal': 'error',\n            'no-trailing-spaces': 'error',\n            'no-undef': 'error',\n            'no-undef-init': 'error',\n            // 'no-undefined': 'error',\n            // 'no-underscore-dangle': 'error',\n            'no-unexpected-multiline': 'error',\n            'no-unmodified-loop-condition': 'error',\n            // 'no-unneeded-ternary': 'error',\n            'no-unreachable': 'error',\n            'no-unreachable-loop': 'error',\n            'no-unsafe-finally': 'error',\n            'no-unsafe-negation': 'error',\n            'no-unsafe-optional-chaining': 'error',\n            'no-unused-expressions': 'error',\n            'no-unused-labels': 'error',\n            'no-unused-private-class-members': 'error',\n            'no-unused-vars': 'error',\n            'no-use-before-define': 'error',\n            // 'no-useless-assignment': 'error',\n            'no-useless-backreference': 'error',\n            'no-useless-call': 'error',\n            'no-useless-catch': 'error',\n            'no-useless-computed-key': 'error',\n            'no-useless-concat': 'error',\n            'no-useless-constructor': 'error',\n            'no-useless-escape': 'error',\n            'no-useless-rename': 'error',\n            'no-useless-return': 'error',\n            'no-var': 'error',\n            'no-void': 'error',\n            'no-warning-comments': 'error',\n            'no-with': 'error',\n            'object-curly-spacing': ['error', 'always'],\n            'object-shorthand': 'error',\n            // 'one-var': 'error',\n            'operator-assignment': 'error',\n            'prefer-arrow-callback': 'error',\n            'prefer-const': 'error',\n            'prefer-destructuring': ['error', { 'array': false }],\n            // 'prefer-exponentiation-operator': 'error',\n            // 'prefer-named-capture-group': 'error',\n            'prefer-numeric-literals': 'error',\n            // 'prefer-object-has-own': 'error',\n            'prefer-object-spread': 'error',\n            'prefer-promise-reject-errors': 'error',\n            'prefer-regex-literals': 'error',\n            'prefer-rest-params': 'error',\n            'prefer-spread': 'error',\n            'prefer-template': 'error',\n            'radix': 'error',\n            'require-atomic-updates': 'error',\n            // 'require-await': 'error',\n            // 'require-unicode-regexp': 'error',\n            'require-yield': 'error',\n            'semi': ['error', 'always'],\n            'sort-imports': 'error',\n            // 'sort-keys': 'error',\n            'sort-vars': 'error',\n            'space-before-blocks': 'error',\n            'space-in-parens': 'error',\n            'space-infix-ops': 'error',\n            'strict': 'error',\n            'symbol-description': 'error',\n            'template-curly-spacing': 'error',\n            'unicode-bom': 'error',\n            'use-isnan': 'error',\n            'valid-typeof': 'error',\n            'vars-on-top': 'error',\n            'yoda': 'error'\n        }\n    },\n    {\n        files: ['source/index.js'],\n        languageOptions: {\n            sourceType: 'script',\n            ecmaVersion: 2015\n        },\n        rules: {\n            'no-var': 'off',\n            'prefer-arrow-callback': 'off',\n            'prefer-template': 'off',\n            'prefer-destructuring': 'off',\n            'vars-on-top': 'off',\n            'strict': 'off'\n        }\n    }\n];\n"
  },
  {
    "path": "package.js",
    "content": "\nimport * as child_process from 'child_process';\nimport * as crypto from 'crypto';\nimport * as fs from 'fs/promises';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as url from 'url';\n\nconst args = process.argv.slice(2);\n\nconst read = (match) => {\n    if (args.length > 0 && (!match || args[0] === match)) {\n        return args.shift();\n    }\n    return null;\n};\n\nlet configuration = null;\n\nconst dirname = (...args) => {\n    const file = url.fileURLToPath(import.meta.url);\n    const dir = path.dirname(file);\n    return path.join(dir, ...args);\n};\n\nconst load = async () => {\n    const file = dirname('package.json');\n    const content = await fs.readFile(file, 'utf-8');\n    configuration = JSON.parse(content);\n};\n\nconst clearLine = () => {\n    if (process.stdout.clearLine) {\n        process.stdout.clearLine();\n    }\n};\n\nconst write = (message) => {\n    if (process.stdout.write) {\n        process.stdout.write(message);\n    }\n};\n\nconst writeLine = (message) => {\n    write(message + os.EOL);\n};\n\nconst access = async (path) => {\n    try {\n        await fs.access(path);\n        return true;\n    } catch {\n        return false;\n    }\n};\n\nconst rm = async (...args) => {\n    const dir = dirname(...args);\n    const exists = await access(dir);\n    if (exists) {\n        const paths = path.join(...args);\n        writeLine(`rm ${paths}`);\n        const options = { recursive: true, force: true };\n        await fs.rm(dir, options);\n    }\n};\n\nconst mkdir = async (...args) => {\n    const dir = dirname(...args);\n    const exists = await access(dir);\n    if (!exists) {\n        const paths = path.join(...args);\n        writeLine(`mkdir ${paths}`);\n        const options = { recursive: true };\n        await fs.mkdir(dir, options);\n    }\n    return dir;\n};\n\nconst copy = async (source, target, filter) => {\n    let files = await fs.readdir(source);\n    files = filter ? files.filter((file) => filter(file)) : files;\n    const promises = files.map((file) => fs.copyFile(path.join(source, file), path.join(target, file)));\n    await Promise.all(promises);\n};\n\nconst unlink = async (dir, filter) => {\n    let files = await fs.readdir(dir);\n    files = filter ? files.filter((file) => filter(file)) : files;\n    const promises = files.map((file) => fs.unlink(path.join(dir, file)));\n    await Promise.all(promises);\n};\n\nconst exec = async (command, encoding, cwd) => {\n    cwd = cwd || dirname();\n    if (encoding) {\n        return child_process.spawnSync(command, { shell: true, cwd, encoding });\n    }\n    child_process.execSync(command, { cwd, stdio: [0,1,2] });\n    return '';\n};\n\nconst sleep = (delay) => {\n    return new Promise((resolve) => {\n        global.setTimeout(resolve, delay);\n    });\n};\n\nconst request = async (url, init, status) => {\n    const response = await global.fetch(url, init);\n    if (status !== false && !response.ok) {\n        throw new Error(`${response.status.toString()} ${response.statusText}`);\n    }\n    if (response.body) {\n        const reader = response.body.getReader();\n        let position = 0;\n        const stream = new global.ReadableStream({\n            start(controller) {\n                const read = async () => {\n                    try {\n                        const result = await reader.read();\n                        if (result.done) {\n                            clearLine();\n                            controller.close();\n                        } else {\n                            position += result.value.length;\n                            write(`  ${position} bytes\\r`);\n                            controller.enqueue(result.value);\n                            read();\n                        }\n                    } catch (error) {\n                        controller.error(error);\n                    }\n                };\n                read();\n            }\n        });\n        return new global.Response(stream, {\n            status: response.status,\n            statusText: response.statusText,\n            headers: response.headers\n        });\n    }\n    return response;\n};\n\nconst download = async (url) => {\n    writeLine(`download ${url}`);\n    const response = await request(url);\n    return response.arrayBuffer().then((buffer) => new Uint8Array(buffer));\n};\n\nconst hash = async (url, algorithm) => {\n    const data = await download(url);\n    const hash = crypto.createHash(algorithm);\n    hash.update(data);\n    return hash.digest('hex');\n};\n\nconst fork = async (organization, repository) => {\n    const headers = {\n        Authorization: `Bearer ${process.env.GITHUB_TOKEN}`\n    };\n    writeLine(`github delete ${repository}`);\n    await request(`https://api.github.com/repos/${process.env.GITHUB_USER}/${repository}`, {\n        method: 'DELETE',\n        headers\n    }, false);\n    await sleep(4000);\n    writeLine(`github fork ${repository}`);\n    await request(`https://api.github.com/repos/${organization}/${repository}/forks`, {\n        method: 'POST',\n        headers,\n        body: ''\n    });\n    await sleep(4000);\n    await rm('dist', repository);\n    writeLine(`github clone ${repository}`);\n    await exec(`git clone --depth=2 https://x-access-token:${process.env.GITHUB_TOKEN}@github.com/${process.env.GITHUB_USER}/${repository}.git dist/${repository}`);\n};\n\nconst pullrequest = async (organization, repository, token, body) => {\n    writeLine(`github push ${repository}`);\n    await exec(`git -C dist/${repository} push`);\n    writeLine(`github pullrequest ${repository}`);\n    const headers = {\n        Authorization: `Bearer ${token}`\n    };\n    await request(`https://api.github.com/repos/${organization}/${repository}/pulls`, {\n        method: 'POST',\n        headers,\n        body: JSON.stringify(body)\n    });\n};\n\nconst clean = async () => {\n    await rm('dist');\n    await rm('node_modules');\n    await rm('package-lock.json');\n    await rm('yarn.lock');\n    if (read('purge')) {\n        await rm('third_party');\n    }\n};\n\nconst install = async () => {\n    const node_modules = dirname('node_modules');\n    let exists = await access(node_modules);\n    if (exists) {\n        const dependencies = { ...configuration.dependencies, ...configuration.devDependencies };\n        const matches = await Promise.all(Object.entries(dependencies).map(async ([name, version]) => {\n            const file = path.join('node_modules', name, 'package.json');\n            const exists = await access(file);\n            if (exists) {\n                const content = await fs.readFile(file, 'utf8');\n                const obj = JSON.parse(content);\n                return obj.version === version;\n            }\n            return false;\n        }));\n        exists = matches.every((match) => match);\n        if (!exists) {\n            await clean();\n        }\n    }\n    exists = await access(node_modules);\n    if (!exists) {\n        await exec('npm install');\n    }\n    try {\n        await exec('python --version', 'utf-8');\n        await exec('python -m pip install --upgrade --quiet setuptools ruff');\n    } catch {\n        // continue regardless of error\n    }\n};\n\nconst start = async () => {\n    await install();\n    await exec('npx electron .');\n};\n\nconst build = async (target) => {\n    switch (target || read()) {\n        case 'web': {\n            writeLine('build web');\n            await rm('dist', 'web');\n            await mkdir('dist', 'web');\n            writeLine('cp source/dir dist/dir');\n            const source_dir = dirname('source');\n            const dist_dir = dirname('dist', 'web');\n            const extensions = new Set(['html', 'css', 'js', 'json', 'ico', 'png']);\n            await copy(source_dir, dist_dir, (file) => extensions.has(file.split('.').pop()));\n            await rm('dist', 'web', 'app.js');\n            await rm('dist', 'web', 'node.js');\n            await rm('dist', 'web', 'desktop.mjs');\n            const contentFile = dirname('dist', 'web', 'index.html');\n            let content = await fs.readFile(contentFile, 'utf-8');\n            content = content.replace(/(<meta\\s*name=\"version\"\\s*content=\")(.*)(\">)/m, (match, p1, p2, p3) => {\n                return p1 + configuration.version + p3;\n            });\n            content = content.replace(/(<meta\\s*name=\"date\"\\s*content=\")(.*)(\">)/m, (match, p1, p2, p3) => {\n                return p1 + configuration.date + p3;\n            });\n            await fs.writeFile(contentFile, content, 'utf-8');\n            break;\n        }\n        case 'electron': {\n            const key = read();\n            const target = key ? `electron ${key}` : 'electron';\n            writeLine(`build ${target}`);\n            await install();\n            await exec('npx electron-builder install-app-deps');\n            const table = new Map([\n                ['mac',     'npx electron-builder --mac --universal --publish never --config.mac.identity=null'],\n                ['windows', 'npx electron-builder --win --x64 --arm64 --publish never --config.win.azureSignOptions='],\n                ['linux',   'npx electron-builder --linux --publish never']\n            ]);\n            const targets = table.has(key) ? [table.get(key)] : Array.from(table.values());\n            for (const target of targets) {\n                /* eslint-disable no-await-in-loop */\n                await exec(target);\n                /* eslint-enable no-await-in-loop */\n            }\n            break;\n        }\n        case 'python': {\n            writeLine('build python');\n            await exec('python package.py build version');\n            await exec('python -m pip install --user build wheel --quiet');\n            await exec('python -m build --wheel --outdir dist/pypi dist/pypi');\n            if (read('install')) {\n                await exec('python -m pip install --force-reinstall dist/pypi/*.whl');\n            }\n            break;\n        }\n        default: {\n            writeLine('build');\n            await rm('dist');\n            await install();\n            await build('web');\n            await build('electron');\n            await build('python');\n            break;\n        }\n    }\n};\n\nconst publish = async (target) => {\n    const GITHUB_TOKEN = process.env.GITHUB_TOKEN;\n    const GITHUB_USER = process.env.GITHUB_USER;\n    switch (target || read()) {\n        case 'web': {\n            writeLine('publish web');\n            await build('web');\n            await rm('dist', 'gh-pages');\n            const url = `https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_USER}/netron.git`;\n            await exec(`git clone --depth=1 ${url} --branch gh-pages ./dist/gh-pages 2>&1 > /dev/null`);\n            writeLine('cp dist/web dist/gh-pages');\n            const source_dir = dirname('dist', 'web');\n            const target_dir = dirname('dist', 'gh-pages');\n            await unlink(target_dir, (file) => file !== '.git');\n            await copy(source_dir, target_dir);\n            await exec('git -C dist/gh-pages add --all');\n            await exec('git -C dist/gh-pages commit --amend --no-edit');\n            await exec('git -C dist/gh-pages push --force origin gh-pages');\n            break;\n        }\n        case 'electron': {\n            const key = read();\n            const target = key ? ` ${key}` : '';\n            writeLine(`publish electron ${target}`);\n            await install();\n            await exec('npx electron-builder install-app-deps');\n            const table = new Map([\n                ['mac',     'npx electron-builder --mac --universal --publish always'],\n                ['windows', 'npx electron-builder --win --x64 --arm64 --publish always'],\n                ['linux',   'npx electron-builder --linux --publish always']\n            ]);\n            const targets = table.has(key) ? [table.get(key)] : Array.from(table.values());\n            for (const target of targets) {\n                /* eslint-disable no-await-in-loop */\n                await exec(target);\n                /* eslint-enable no-await-in-loop */\n            }\n            break;\n        }\n        case 'python': {\n            writeLine('publish python');\n            await build('python');\n            await exec('python -m pip install --user twine');\n            await exec('python -m twine upload --non-interactive --skip-existing --verbose dist/pypi/*.whl');\n            break;\n        }\n        case 'cask': {\n            writeLine('publish cask');\n            await fork('Homebrew', 'homebrew-cask');\n            const repository = `https://github.com/${configuration.repository}`;\n            const url = `${repository}/releases/download/v#{version}/${configuration.productName}-#{version}-mac.zip`;\n            const sha256 = await hash(url.replace(/#{version}/g, configuration.version), 'sha256');\n            writeLine('update manifest');\n            const dir = await mkdir('dist', 'homebrew-cask', 'Casks', 'n');\n            const file = path.join(dir, 'netron.rb');\n            await fs.writeFile(file, [\n                `cask \"${configuration.name}\" do`,\n                `  version \"${configuration.version}\"`,\n                `  sha256 \"${sha256.toLowerCase()}\"`,\n                '',\n                `  url \"${url}\"`,\n                `  name \"${configuration.productName}\"`,\n                `  desc \"${configuration.description.replace('Visualizer', 'Visualiser')}\"`,\n                `  homepage \"${repository}\"`,\n                '',\n                '  auto_updates true',\n                '',\n                `  app \"${configuration.productName}.app\"`,\n                '',\n                '  zap trash: [',\n                `    \"~/Library/Application Support/${configuration.productName}\",`,\n                `    \"~/Library/Preferences/${configuration.build.appId}.plist\",`,\n                `    \"~/Library/Saved Application State/${configuration.build.appId}.savedState\",`,\n                '  ]',\n                'end',\n                ''\n            ].join('\\n'));\n            writeLine('git push homebrew-cask');\n            await exec('git -C dist/homebrew-cask add --all');\n            await exec(`git -C dist/homebrew-cask commit -m \"${configuration.name} ${configuration.version}\"`);\n            await pullrequest('Homebrew', 'homebrew-cask', process.env.GITHUB_TOKEN, {\n                title: `${configuration.name} ${configuration.version}`,\n                body: 'Update version and sha256',\n                head: `${process.env.GITHUB_USER}:master`,\n                base: 'master'\n            });\n            await rm('dist', 'homebrew-cask');\n            break;\n        }\n        case 'winget': {\n            writeLine('publish winget');\n            await fork('microsoft', 'winget-pkgs');\n            const name = configuration.name;\n            const version = configuration.version;\n            const product = configuration.productName;\n            const publisher = configuration.author.name;\n            const identifier = `${publisher.replace(' ', '')}.${product}`;\n            const copyright = `Copyright (c) ${publisher}`;\n            const repository = `https://github.com/${configuration.repository}`;\n            const url = `${repository}/releases/download/v${version}/${product}-Setup-${version}.exe`;\n            const content = await fs.readFile(configuration.build.extends, 'utf-8');\n            const builder = JSON.parse(content);\n            const extensions = builder.fileAssociations.map((entry) => `- ${entry.ext}`).sort().join('\\n');\n            const sha256 = await hash(url, 'sha256');\n            const paths = ['dist', 'winget-pkgs', 'manifests', publisher[0].toLowerCase(), publisher.replace(' ', ''), product, version];\n            await mkdir(...paths);\n            writeLine('update manifest');\n            const manifestFile = dirname(...paths, identifier);\n            await fs.writeFile(`${manifestFile}.yaml`, [\n                '# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.6.0.schema.json',\n                `PackageIdentifier: ${identifier}`,\n                `PackageVersion: ${version}`,\n                'DefaultLocale: en-US',\n                'ManifestType: version',\n                'ManifestVersion: 1.6.0',\n                ''\n            ].join('\\n'));\n            await fs.writeFile(`${manifestFile}.installer.yaml`, [\n                '# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.6.0.schema.json',\n                `PackageIdentifier: ${identifier}`,\n                `PackageVersion: ${version}`,\n                'Platform:',\n                '- Windows.Desktop',\n                'InstallModes:',\n                '- silent',\n                '- silentWithProgress',\n                'Installers:',\n                '- Architecture: x86',\n                '  Scope: user',\n                '  InstallerType: nullsoft',\n                `  InstallerUrl: ${url}`,\n                `  InstallerSha256: ${sha256.toUpperCase()}`,\n                '  InstallerLocale: en-US',\n                '  InstallerSwitches:',\n                '    Custom: /NORESTART',\n                '  UpgradeBehavior: install',\n                '- Architecture: arm64',\n                '  Scope: user',\n                '  InstallerType: nullsoft',\n                `  InstallerUrl: ${url}`,\n                `  InstallerSha256: ${sha256.toUpperCase()}`,\n                '  InstallerLocale: en-US',\n                '  InstallerSwitches:',\n                '    Custom: /NORESTART',\n                '  UpgradeBehavior: install',\n                'FileExtensions:',\n                extensions,\n                'ManifestType: installer',\n                'ManifestVersion: 1.6.0',\n                ''\n            ].join('\\n'));\n            await fs.writeFile(`${manifestFile}.locale.en-US.yaml`, [\n                '# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.6.0.schema.json',\n                `PackageIdentifier: ${identifier}`,\n                `PackageVersion: ${version}`,\n                `PackageName: ${product}`,\n                'PackageLocale: en-US',\n                `PackageUrl: ${repository}`,\n                `Publisher: ${publisher}`,\n                `PublisherUrl: ${repository}`,\n                `PublisherSupportUrl: ${repository}/issues`,\n                `Author: ${publisher}`,\n                `License: ${configuration.license}`,\n                `Copyright: ${copyright}`,\n                `CopyrightUrl: ${repository}/blob/main/LICENSE`,\n                `ShortDescription: ${configuration.description}`,\n                `Description: ${configuration.description}`,\n                `Moniker: ${name}`,\n                'Tags:',\n                '- machine-learning',\n                '- deep-learning',\n                '- neural-network',\n                'ManifestType: defaultLocale',\n                'ManifestVersion: 1.6.0',\n                ''\n            ].join('\\n'));\n            writeLine('git push winget-pkgs');\n            await exec('git -C dist/winget-pkgs add --all');\n            await exec(`git -C dist/winget-pkgs commit -m \"Update ${configuration.name} to ${configuration.version}\"`);\n            await pullrequest('microsoft', 'winget-pkgs', process.env.WINGET_TOKEN, {\n                title: `Update ${configuration.productName} to ${configuration.version}`,\n                body: '',\n                head: `${process.env.GITHUB_USER}:master`,\n                base: 'master'\n            });\n            await rm('dist', 'winget-pkgs');\n            break;\n        }\n        default: {\n            writeLine('publish');\n            await rm('dist');\n            await install();\n            await publish('web');\n            await publish('electron');\n            await publish('python');\n            await publish('cask');\n            await publish('winget');\n            break;\n        }\n    }\n};\n\nconst lint = async () => {\n    await install();\n    writeLine('eslint');\n    await exec('npx eslint --cache --cache-location ./dist/lint/.eslintcache');\n    writeLine('ruff');\n    await exec('python -m ruff check . --quiet');\n};\n\nconst test = async (target) => {\n    let models = true;\n    while (true) {\n        /* eslint-disable no-await-in-loop */\n        if (target === 'desktop' || read('desktop')) {\n            target = null;\n            models = false;\n            await exec('npx playwright install --with-deps');\n            const host = process.platform === 'linux' && (process.env.GITHUB_ACTIONS || process.env.CI) ? 'xvfb-run -a ' : '';\n            await exec(`${host}npx playwright test --config=test/playwright.config.js --project=desktop`);\n            continue;\n        }\n        if (target === 'browser' || read('browser')) {\n            target = null;\n            models = false;\n            if (process.platform !== 'win32') {\n                await exec('npx playwright install --with-deps');\n                const headed = process.env.GITHUB_ACTIONS || process.env.CI ? '' :  ' --headed';\n                await exec(`npx playwright test --config=test/playwright.config.js --project=browser${headed}`);\n            }\n            continue;\n        }\n        break;\n        /* eslint-enable no-await-in-loop */\n    }\n    if (models) {\n        target = target || args.join(' ');\n        await exec(`node test/models.js ${target}`);\n    }\n};\n\nconst validate = async () => {\n    writeLine('lint');\n    await lint();\n    writeLine('test');\n    await test('tag:validation');\n    writeLine('test desktop');\n    await test('desktop');\n    writeLine('test browser');\n    await test('browser');\n};\n\nconst update = async () => {\n    const filter = new Set(process.argv.length > 3 ? process.argv.slice(3) : []);\n    if (filter.size === 0) {\n        const output = await exec('npm outdated --json', 'utf-8');\n        const entries = JSON.parse(output.stdout);\n        const compare = (a, b) => {\n            const regex = /^\\d+\\.\\d+\\.\\d+$/;\n            if (!regex.test(a)) {\n                throw new Error(`Invalid version format '${a}'.`);\n            }\n            if (!regex.test(b)) {\n                throw new Error(`Invalid version format '${b}'.`);\n            }\n            a = a.split('.').map((v) => Number(v));\n            b = b.split('.').map((v) => Number(v));\n            if (a.length !== b.length) {\n                throw new Error(`Invalid version a=${a.join('.')} b=${b.join('.')}`);\n            }\n            for (let i = 0; i < 3; i++) {\n                if ((a[i] || 0) > (b[i] || 0)) {\n                    return 1;\n                }\n                if ((a[i] || 0) < (b[i] || 0)) {\n                    return -1;\n                }\n            }\n            return 0;\n        };\n        for (const [name, entry] of Object.entries(entries)) {\n            if (compare(entry.wanted, entry.latest) < 0) {\n                writeLine(name);\n                /* eslint-disable no-await-in-loop */\n                await exec(`npm install --quiet --no-progress --silent --save-exact ${name}@latest`);\n                /* eslint-enable no-await-in-loop */\n            }\n        }\n    }\n    let targets = [\n        'armnn',\n        'bigdl',\n        'caffe', 'circle', 'cntk', 'coreml',\n        'dlc', 'dnn',\n        'espdl', 'executorch',\n        'gguf',\n        'kann', 'keras',\n        'mlir', 'mnn', 'mslite', 'megengine',\n        'nnabla',\n        'onnx', 'om',\n        'paddle', 'pytorch',\n        'rknn',\n        'sentencepiece', 'sklearn',\n        'tf', 'tosa',\n        'uff',\n        'xmodel'\n    ];\n    let commands = [\n        'sync',\n        'install',\n        'schema',\n        'metadata'\n    ];\n    if (filter.size > 0 && targets.some((target) => filter.has(target))) {\n        targets = targets.filter((target) => filter.has(target));\n    }\n    if (filter.size > 0 && commands.some((target) => filter.has(target))) {\n        commands = commands.filter((command) => filter.has(command));\n    }\n    commands = commands.join(' ');\n    for (const target of targets) {\n        /* eslint-disable no-await-in-loop */\n        await exec(`tools/${target} ${commands}`);\n        /* eslint-enable no-await-in-loop */\n    }\n};\n\nconst pull = async () => {\n    await exec('git fetch --prune origin \"refs/tags/*:refs/tags/*\"');\n    let before = await exec('git rev-parse HEAD', 'utf-8');\n    if (before.status !== 0) {\n        throw new Error(before.stderr.trim());\n    }\n    try {\n        await exec('git pull --prune --rebase --autostash');\n    } catch (error) {\n        writeLine(error.message);\n    }\n    let after = await exec('git rev-parse HEAD', 'utf-8');\n    if (after.status !== 0) {\n        throw new Error(after.stderr.trim());\n    }\n    before = before.stdout.trim();\n    after = after.stdout.trim();\n    if (before !== after) {\n        const output = await exec(`git diff --name-only ${before} ${after}`, 'utf-8');\n        const files = new Set(output.stdout.split('\\n'));\n        if (files.has('package.json')) {\n            await clean();\n            await install();\n        }\n    }\n};\n\nconst coverage = async () => {\n    switch (read()) {\n        case 'desktop': {\n            await rm('dist', 'nyc');\n            await mkdir('dist', 'nyc');\n            await exec('cp package.json dist/nyc');\n            await exec('cp -R source dist/nyc');\n            await exec('nyc instrument --compact false source dist/nyc/source');\n            const file = dirname('dist', 'nyc', 'source', 'index.html');\n            let content = await fs.readFile(file, 'utf-8');\n            content = content.replace(`\"script-src 'self'\"`, `\"script-src 'self' 'unsafe-eval'\"`);\n            await fs.writeFile(file, content, 'utf-8');\n            await exec('nyc --instrument npx electron ./dist/nyc');\n            await exec('nyc report');\n            break;\n        }\n        case 'test': {\n            const target = args.join(' ');\n            await rm('dist', 'c8');\n            await exec(`npx c8 --reporter=html --report-dir=dist/c8/report node test/models.js ${target}`);\n            break;\n        }\n        default: {\n            throw new Error('Unsupported coverage target.');\n        }\n    }\n};\n\nconst analyze = async () => {\n    const exists = await access('third_party/tools/codeql');\n    if (!exists) {\n        await exec('git clone --depth=1 https://github.com/github/codeql.git third_party/tools/codeql');\n    }\n    await rm('dist', 'codeql');\n    await mkdir('dist', 'codeql', 'netron');\n    await exec('cp -r publish source test tools dist/codeql/netron/');\n    await exec('codeql database create dist/codeql/database --source-root dist/codeql/netron --language=javascript --threads=3');\n    await exec('codeql database analyze dist/codeql/database ./third_party/tools/codeql/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls --format=csv --output=dist/codeql/results.csv --threads=3');\n    await exec('cat dist/codeql/results.csv');\n};\n\nconst version = async () => {\n    await pull();\n    const file = dirname('package.json');\n    let content = await fs.readFile(file, 'utf-8');\n    content = content.replace(/(\\s*\"version\":\\s\")(\\d\\.\\d\\.\\d)(\",)/m, (match, p1, p2, p3) => {\n        const version = Array.from((parseInt(p2.split('.').join(''), 10) + 1).toString()).join('.');\n        return p1 + version + p3;\n    });\n    content = content.replace(/(\\s*\"date\":\\s\")(.*)(\",)/m, (match, p1, p2, p3) => {\n        const date = new Date().toISOString().split('.').shift().split('T').join(' ');\n        return p1 + date + p3;\n    });\n    await fs.writeFile(file, content, 'utf-8');\n    await exec('npm install --package-lock-only');\n    await load();\n    await exec('git add package.json');\n    await exec('git add package-lock.json');\n    await exec(`git commit -m \"Update to ${configuration.version}\"`);\n    await exec(`git tag v${configuration.version}`);\n    await exec('git push');\n    await exec('git push --tags');\n};\n\nconst main = async () => {\n    await load();\n    try {\n        const task = read();\n        switch (task) {\n            case 'start': await start(); break;\n            case 'clean': await clean(); break;\n            case 'install': await install(); break;\n            case 'build': await build(); break;\n            case 'publish': await publish(); break;\n            case 'version': await version(); break;\n            case 'lint': await lint(); break;\n            case 'test': await test(); break;\n            case 'validate': await validate(); break;\n            case 'update': await update(); break;\n            case 'pull': await pull(); break;\n            case 'analyze': await analyze(); break;\n            case 'coverage': await coverage(); break;\n            default: throw new Error(`Unsupported task '${task}'.`);\n        }\n    } catch (error) {\n        if (process.stdout.write) {\n            process.stdout.write(error.message + os.EOL);\n        }\n        process.exit(1);\n    }\n};\n\nawait main();\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"netron\",\n    \"productName\": \"Netron\",\n    \"author\": {\n        \"name\": \"Lutz Roeder\",\n        \"email\": \"lutzroeder@users.noreply.github.com\",\n        \"url\": \"https://www.lutzroeder.com\"\n    },\n    \"version\": \"8.9.5\",\n    \"date\": \"2026-03-13 14:03:12\",\n    \"description\": \"Visualizer for neural network, deep learning, and machine learning models\",\n    \"license\": \"MIT\",\n    \"repository\": \"lutzroeder/netron\",\n    \"type\": \"module\",\n    \"main\": \"source/app.js\",\n    \"scripts\": {\n        \"start\": \"node package.js start\",\n        \"server\": \"python package.py build start\",\n        \"clean\": \"node package.js clean\",\n        \"install\": \"node package.js install\",\n        \"lint\": \"node package.js lint\",\n        \"build\": \"node package.js build\",\n        \"publish\": \"node package.js publish\",\n        \"version\": \"node package.js version\",\n        \"test\": \"node package.js test\",\n        \"validate\": \"node package.js validate\",\n        \"coverage\": \"node package.js coverage\",\n        \"analyze\": \"node package.js analyze\",\n        \"update\": \"node package.js update\",\n        \"pull\": \"node package.js pull\"\n    },\n    \"dependencies\": {\n        \"electron-updater\": \"6.8.3\"\n    },\n    \"devDependencies\": {\n        \"@electron/notarize\": \"3.1.1\",\n        \"@playwright/test\": \"1.58.2\",\n        \"electron\": \"41.0.3\",\n        \"electron-builder\": \"26.8.1\",\n        \"eslint\": \"10.0.3\"\n    },\n    \"build\": {\n        \"extends\": \"publish/electron-builder.json\"\n    },\n    \"nyc\": {\n        \"reporter\": [\n            \"lcov\",\n            \"html\"\n        ],\n        \"report-dir\": \"dist/nyc/report\",\n        \"temp-dir\": \"dist/nyc/.nyc_output\"\n    }\n}\n"
  },
  {
    "path": "package.py",
    "content": "import os\nimport sys\n\nargv = sys.argv[1:]\n\nroot_dir = os.path.dirname(os.path.abspath(__file__))\ndist_dir = os.path.join(root_dir, \"dist\")\ndist_pypi_dir = os.path.join(dist_dir, \"pypi\")\n\ndef _build():\n    import shutil\n    source_dir = os.path.join(root_dir, \"source\")\n    shutil.rmtree(os.path.join(source_dir, \"__pycache__\"), ignore_errors=True)\n    shutil.rmtree(dist_pypi_dir, ignore_errors=True)\n    shutil.copytree(source_dir, os.path.join(dist_pypi_dir, \"netron\"))\n    shutil.copyfile(\n        os.path.join(root_dir, \"pyproject.toml\"),\n        os.path.join(dist_pypi_dir, \"pyproject.toml\"))\n    os.remove(os.path.join(dist_pypi_dir, \"netron\", \"desktop.mjs\"))\n    os.remove(os.path.join(dist_pypi_dir, \"netron\", \"app.js\"))\n\ndef _install():\n    import pip._internal.cli.main\n    pip._internal.cli.main.main([\"install\", dist_pypi_dir])\n\ndef _version():\n    import json\n    import re\n    path = os.path.join(root_dir, \"package.json\")\n    with open(path, encoding=\"utf-8\") as file:\n        package = json.load(file)\n    version = package[\"version\"]\n    date = package[\"date\"]\n    entries = [\n        (\"pyproject.toml\", '(version\\\\s*=\\\\s*\")(.*)(\")', version),\n        (\"netron/server.py\", '(__version__\\\\s=\\\\s\")(.*)(\")', version),\n        (\"netron/index.html\", '(<meta name=\"version\" content=\")(.*)(\">)', version),\n        (\"netron/index.html\", '(<meta name=\"date\" content=\")(.*)(\">)', date)\n    ]\n    for path, regex, value in entries:\n        path = os.path.join(dist_pypi_dir, path)\n        with open(path, encoding=\"utf-8\") as file:\n            content = file.read()\n        content, count = re.subn(regex, rf\"\\g<1>{value}\\g<3>\", content)\n        if count == 0:\n            raise ValueError(f\"Failed to update '{path}' with '{value}'.\")\n        with open(path, \"w\", encoding=\"utf-8\") as file:\n            file.write(content)\n\ndef _start():\n    \"\"\" Start server \"\"\"\n    sys.path.insert(0, os.path.join(root_dir, \"dist\", \"pypi\"))\n    __import__(\"netron\").main()\n    argv.clear()\n\ndef main():\n    table = {\n        \"build\": _build,\n        \"install\": _install,\n        \"version\": _version,\n        \"start\": _start\n    }\n    while len(argv) > 0:\n        command = argv.pop(0)\n        del sys.argv[1]\n        table[command]()\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "publish/electron-builder.json",
    "content": "{\n    \"appId\": \"com.lutzroeder.netron\",\n    \"productName\": \"Netron\",\n    \"files\": [ \"source/**/*\" ],\n    \"directories\": { \"buildResources\": \"./publish\" },\n    \"fileAssociations\": [\n        { \"ext\": \"armnn\",       \"name\": \"Arm NN Model\"             },\n        { \"ext\": \"caffemodel\",  \"name\": \"Caffe Model\"              },\n        { \"ext\": \"circle\",      \"name\": \"Circle Model\"             },\n        { \"ext\": \"ckpt\",        \"name\": \"Model Checkpoint\"         },\n        { \"ext\": \"cmf\",         \"name\": \"CNTK Model\"               },\n        { \"ext\": \"dlc\",         \"name\": \"DLC Model\"                },\n        { \"ext\": \"dnn\",         \"name\": \"CNTK Model\"               },\n        { \"ext\": \"espdl\",       \"name\": \"ESP-DL Model\"              },\n        { \"ext\": \"gguf\",        \"name\": \"GGUF Model\"               },\n        { \"ext\": \"h5\",          \"name\": \"Keras Model\"              },\n        { \"ext\": \"hd5\",         \"name\": \"Keras Model\"              },\n        { \"ext\": \"hdf5\",        \"name\": \"Keras Model\"              },\n        { \"ext\": \"hn\",          \"name\": \"Hailo Model\"              },\n        { \"ext\": \"kann\",        \"name\": \"KaNN Model\"               },\n        { \"ext\": \"kgraph\",      \"name\": \"KaNN Model\"               },\n        { \"ext\": \"keras\",       \"name\": \"Keras Model\"              },\n        { \"ext\": \"kmodel\",      \"name\": \"Kendryte Model\"           },\n        { \"ext\": \"lite\",        \"name\": \"TensorFlow Lite Model\"    },\n        { \"ext\": \"mar\",         \"name\": \"MXNet Model\"              },\n        { \"ext\": \"maxviz\",      \"name\": \"Modular Model\"            },\n        { \"ext\": \"meta\",        \"name\": \"TensorFlow Meta Graph\"    },\n        { \"ext\": \"mge\",         \"name\": \"MegEngine Mge Model\"      },\n        { \"ext\": \"mlmodel\",     \"name\": \"Core ML Model\"            },\n        { \"ext\": \"mlir\",        \"name\": \"MLIR Model\"               },\n        { \"ext\": \"mlirbc\",      \"name\": \"MLIR Bytecode Model\"      },\n        { \"ext\": \"mlnet\",       \"name\": \"ML.NET Model\"             },\n        { \"ext\": \"mlpackage\",   \"name\": \"Core ML Model Package\", \"isPackage\": true },\n        { \"ext\": \"mnn\",         \"name\": \"MNN Model\"                },\n        { \"ext\": \"model\",       \"name\": \"Model\"                    },\n        { \"ext\": \"nb\",          \"name\": \"Paddle Lite Model\"        },\n        { \"ext\": \"ngf\",         \"name\": \"ONNX Model\"               },\n        { \"ext\": \"nn\",          \"name\": \"Barracuda Model\"          },\n        { \"ext\": \"nnp\",         \"name\": \"Neural Network Libraries\" },\n        { \"ext\": \"npy\",         \"name\": \"NumPy Array\"              },\n        { \"ext\": \"npz\",         \"name\": \"NumPy Archive\"            },\n        { \"ext\": \"om\",          \"name\": \"DaVinci OM Model\"         },\n        { \"ext\": \"onnx\",        \"name\": \"ONNX Model\"               },\n        { \"ext\": \"ort\",         \"name\": \"ONNX Runtime Model\"       },\n        { \"ext\": \"paddle\",      \"name\": \"PaddlePaddle Model\"       },\n        { \"ext\": \"param\",       \"name\": \"NCNN Model\"               },\n        { \"ext\": \"pb\",          \"name\": \"Protocol Buffer\"          },\n        { \"ext\": \"pbtxt\",       \"name\": \"Text Protocol Buffer\"     },\n        { \"ext\": \"pdiparams\",   \"name\": \"PaddlePaddle Model\"       },\n        { \"ext\": \"pdmodel\",     \"name\": \"PaddlePaddle Model\"       },\n        { \"ext\": \"pdopt\",       \"name\": \"PaddlePaddle Model\"       },\n        { \"ext\": \"pdparams\",    \"name\": \"PaddlePaddle Model\"       },\n        { \"ext\": \"pickle\",      \"name\": \"Python Pickle File\"       },\n        { \"ext\": \"pkl\",         \"name\": \"Python Pickle File\"       },\n        { \"ext\": \"prototxt\",    \"name\": \"Text Protocol Buffer\"     },\n        { \"ext\": \"pt\",          \"name\": \"PyTorch Model\"            },\n        { \"ext\": \"pt2\",         \"name\": \"PyTorch Model\"            },\n        { \"ext\": \"pte\",         \"name\": \"ExecuTorch Model\"         },\n        { \"ext\": \"pth\",         \"name\": \"PyTorch Model\"            },\n        { \"ext\": \"ptl\",         \"name\": \"PyTorch Model\"            },\n        { \"ext\": \"rknn\",        \"name\": \"RKNN Model\"               },\n        { \"ext\": \"safetensors\", \"name\": \"Safetensors Checkpoint\"   },\n        { \"ext\": \"t7\",          \"name\": \"Torch Model\"              },\n        { \"ext\": \"tfl\",         \"name\": \"TensorFlow Lite Model\"    },\n        { \"ext\": \"tflite\",      \"name\": \"TensorFlow Lite Model\"    },\n        { \"ext\": \"tmfile\",      \"name\": \"Tengine Model\"            },\n        { \"ext\": \"tm\",          \"name\": \"MegEngine Traced Model\"   },\n        { \"ext\": \"tnnproto\",    \"name\": \"TNN Model\"                },\n        { \"ext\": \"tosa\",        \"name\": \"TOSA Model\"               },\n        { \"ext\": \"torchscript\", \"name\": \"PyTorch Model\"            },\n        { \"ext\": \"uff\",         \"name\": \"UFF Model\"                },\n        { \"ext\": \"xmodel\",      \"name\": \"Vitis AI Model\"           }\n    ],\n    \"publish\": [\n        { \"provider\": \"github\", \"releaseType\": \"release\" }\n    ],\n    \"linux\": {\n        \"artifactName\":\"${productName}-${version}-${arch}.${ext}\",\n        \"executableName\": \"netron\",\n        \"target\": [ \n            { \"target\": \"deb\", \"arch\": [\"x64\"] },\n            { \"target\": \"rpm\", \"arch\": [\"x64\"] }\n        ]\n    },\n    \"mac\": {\n        \"artifactName\": \"${productName}-${version}-mac.${ext}\",\n        \"category\": \"public.app-category.developer-tools\",\n        \"darkModeSupport\": true,\n        \"gatekeeperAssess\": false,\n        \"hardenedRuntime\": true,\n        \"notarize\": true,\n        \"target\": [ \"dmg\", \"zip\" ]\n    },\n    \"win\": {\n        \"target\": [ \"nsis\" ],\n        \"azureSignOptions\" : {\n            \"publisherName\": \"Lutz Roeder\",\n            \"endpoint\": \"https://eus.codesigning.azure.net/\",\n            \"codeSigningAccountName\": \"lutzroeder\",\n            \"certificateProfileName\": \"lutzroeder\"\n        }\n    },\n    \"dmg\": {\n        \"artifactName\": \"${productName}-${version}.${ext}\",\n        \"title\": \"${productName} ${version}\",\n        \"writeUpdateInfo\": false,\n        \"iconSize\": 160,\n        \"contents\": [\n            { \"x\": 180, \"y\": 170 },\n            { \"x\": 480, \"y\": 170, \"type\": \"link\", \"path\": \"/Applications\" }\n        ]\n    },\n    \"nsis\": {\n        \"differentialPackage\": false\n    }\n}\n"
  },
  {
    "path": "publish/icon.html",
    "content": "<!DOCTYPE html>\n<html>\n<body>\n<div style=\"height: 400px;\">\n<div style=\"background: #f6f6f6; width: 400px; height: 400px; float: left;\"> \n<img src=\"icon.svg\" width=\"300\" style=\"position: relative; top: 50px; left: 50px;\">\n</div>\n<div style=\"background: #d8d8d8; width: 400px; height: 400px; float: left;\"> \n<img src=\"icon.svg\" width=\"300\" style=\"position: relative; top: 50px; left: 50px;\">\n</div>\n<div style=\"background: #1e1e1e; width: 400px; height: 400px; float: left;\"> \n<img src=\"icon.svg\" width=\"300\" style=\"position: relative; top: 50px; left: 50px;\">\n</div>\n</div>\n<div style=\"height: 400px;\">\n<div style=\"background: #f6f6f6; width: 400px; height: 400px; float: left;\"> \n<img src=\"icon.icns.svg\" width=\"300\" style=\"position: relative; top: 50px; left: 50px;\">\n</div>\n<div style=\"background: #d8d8d8; width: 400px; height: 400px; float: left;\">\n<img src=\"icon.icns.svg\" width=\"300\" style=\"position: relative; top: 50px; left: 50px;\">\n</div>\n<div style=\"background: #1e1e1e; width: 400px; height: 400px; float: left;\"> \n<img src=\"icon.icns.svg\" width=\"300\" style=\"position: relative; top: 50px; left: 50px;\">\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "pyproject.toml",
    "content": "\n[build-system]\nrequires = [\"setuptools>=42\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"netron\"\nversion = \"0.0.0\"\ndescription = \"Viewer for neural network, deep learning and machine learning models.\"\nauthors = [\n    { name = \"Lutz Roeder\", email = \"lutzroeder@users.noreply.github.com\" }\n]\nkeywords = [\n    \"onnx\", \"keras\", \"tensorflow\", \"tflite\", \"coreml\", \"mxnet\", \"caffe\", \"caffe2\",\n    \"torchscript\", \"pytorch\", \"ncnn\", \"mnn\", \"openvino\", \"darknet\", \"paddlepaddle\", \"chainer\",\n    \"artificial intelligence\", \"machine learning\", \"deep learning\", \"neural network\",\n    \"visualizer\", \"viewer\"\n]\nclassifiers = [\n    \"Intended Audience :: Developers\",\n    \"Intended Audience :: Education\",\n    \"Intended Audience :: Science/Research\",\n    \"Programming Language :: Python :: 3\",\n    \"Programming Language :: Python :: 3.6\",\n    \"Topic :: Software Development\",\n    \"Topic :: Software Development :: Libraries\",\n    \"Topic :: Software Development :: Libraries :: Python Modules\",\n    \"Topic :: Scientific/Engineering\",\n    \"Topic :: Scientific/Engineering :: Mathematics\",\n    \"Topic :: Scientific/Engineering :: Artificial Intelligence\",\n    \"Topic :: Scientific/Engineering :: Visualization\"\n]\n\n[project.urls]\nhomepage = \"https://github.com/lutzroeder/netron\"\n\n[project.readme]\ntext = \"\"\"\nNetron is a viewer for neural network, deep learning and machine learning models.\n\nNetron supports ONNX, TensorFlow Lite, Core ML, Keras, Caffe, Darknet, PyTorch, TensorFlow.js, Safetensors and NumPy.\n\nNetron has experimental support for TorchScript, torch.export, ExecuTorch, TensorFlow, OpenVINO, RKNN, ncnn, MNN, PaddlePaddle, GGUF and scikit-learn.\n\"\"\"\ncontent-type = \"text/markdown\"\n\n[project.license]\ntext = \"MIT\"\n\n[project.scripts]\nnetron = \"netron:main\"\n\n[tool.setuptools]\npackage-dir = { \"netron\" = \"netron\" }\n\n[tool.setuptools.packages.find]\nnamespaces = false\n\n[tool.setuptools.package-data]\nnetron = [\"*.*\"]\n\n[tool.setuptools.exclude-package-data]\nnetron = [\"app.js\", \"electron.*\"]\n\n[tool.ruff]\nlint.select = [\"B\", \"E\", \"F\", \"I\", \"UP\", \"W\", \"Q\"]\ncache-dir = \"./dist/lint/.ruff_cache\""
  },
  {
    "path": "source/__init__.py",
    "content": "\"\"\" Python Server entry point \"\"\"\n\nimport argparse\nimport logging\nimport os\nimport sys\n\nfrom .server import __version__, serve, start, status, stop, wait, widget\n\n__all__ = [\"start\", \"stop\", \"status\", \"wait\", \"serve\", \"widget\", \"__version__\"]\n\ndef main():\n    \"\"\" main entry point \"\"\"\n    parser = argparse.ArgumentParser(description=\n        \"Viewer for neural network, deep learning and machine learning models.\")\n    parser.add_argument(\"file\",\n        metavar=\"MODEL_FILE\", help=\"model file to serve\", nargs=\"?\", default=None)\n    parser.add_argument(\"-b\", \"--browse\",\n        help=\"launch web browser\", action=\"store_true\")\n    parser.add_argument(\"-p\", \"--port\", help=\"port to serve\", type=int)\n    parser.add_argument(\"--host\",\n        metavar=\"ADDR\", help=\"host to serve\", default=\"localhost\")\n    parser.add_argument(\"--verbosity\",\n        metavar=\"LEVEL\", help=\"log verbosity (quiet, default, debug)\",\n        choices=[ \"quiet\", \"debug\", \"default\" ], default=\"default\")\n    parser.add_argument(\"--version\", help=\"print version\", action=\"store_true\")\n    args = parser.parse_args()\n    levels = {\n        \"quiet\": logging.CRITICAL,\n        \"default\": logging.INFO,\n        \"debug\": logging.DEBUG,\n    }\n    logging.basicConfig(level=levels[args.verbosity], format=\"%(message)s\")\n    logger = logging.getLogger(__name__)\n    if args.file and not os.path.exists(args.file):\n        logger.error(f\"Model file '{args.file}' does not exist.\")\n        sys.exit(2)\n    if args.version:\n        logger.info(__version__)\n        sys.exit(0)\n    address = (args.host, args.port) if args.host else args.port if args.port else None\n    start(args.file, address=address, browse=args.browse)\n    wait()\n    sys.exit(0)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "source/acuity-metadata.json",
    "content": "[\n  {\n    \"name\": \"a_times_b_plus_c\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" },\n      { \"name\": \"C\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"abs\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"acosh\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"activity_regularization\",\n    \"attributes\": [\n      { \"name\": \"l1\", \"default\": 0.0 },\n      { \"name\": \"l2\", \"default\": 0.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"add\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"addn\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"additive_attention\",\n    \"category\": \"Attention\",\n    \"attributes\": [\n      { \"name\": \"use_scale\", \"default\": true },\n      { \"name\": \"dropout\", \"default\": 0.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"alpha_dropout\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"rate\", \"default\": 0.1 },\n      { \"name\": \"seed\", \"default\": 0.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"argmin\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": -1 },\n      { \"name\": \"keepdims\", \"default\": false },\n      { \"name\": \"select_last_index\", \"default\": false },\n      { \"name\": \"output_type\", \"default\": \"int64\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"atan\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"atan2\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"atanh\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"attention\",\n    \"category\": \"Attention\",\n    \"attributes\": [\n      { \"name\": \"use_scale\", \"default\": true },\n      { \"name\": \"dropout\", \"default\": 0.0 },\n      { \"name\": \"score_mode\", \"default\": \"dot\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"average\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"base_input_layer\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"batch2space\",\n    \"attributes\": [\n      { \"name\": \"block_shape\", \"default\": [2, 2] },\n      { \"name\": \"block_crops\", \"default\": [[0, 0], [0, 0]] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"batch2space_op\",\n    \"attributes\": [\n      { \"name\": \"block_shape\", \"default\": [2] },\n      { \"name\": \"block_crops\", \"default\": [[0, 1]] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"batchnorm_single\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"default\": 0.0001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"constants\": [\n      { \"name\": \"bias\" },\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"batchnormalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"default\": 0.0001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"beta\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"bitwise_and\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"bitwise_or\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"bitwise_xor\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"broadcast_args\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"bucketize\",\n    \"attributes\": [\n      { \"name\": \"right\", \"default\": false },\n      { \"name\": \"out_type\", \"default\": \"uint32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ctc_loss_layer\",\n    \"attributes\": [\n      { \"name\": \"time_major\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"capsule_norm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"cast\",\n    \"category\": \"Quantization\",\n    \"attributes\": [\n      { \"name\": \"in_data_type\", \"default\": 0 },\n      { \"name\": \"out_data_type\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ceil\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"celu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"center_crop_pad\",\n    \"attributes\": [\n      { \"name\": \"shape\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"clipbyvalue\",\n    \"attributes\": [\n      { \"name\": \"clip_value_min\", \"default\": 0 },\n      { \"name\": \"clip_value_max\", \"default\": 255 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"col2im\",\n    \"attributes\": [\n      { \"name\": \"image_shape\", \"default\": [] },\n      { \"name\": \"block_shape\", \"default\": [] },\n      { \"name\": \"pads\", \"default\": [[0, 0], [0, 0]] },\n      { \"name\": \"strides\", \"default\": [1, 1] },\n      { \"name\": \"dilations\", \"default\": [1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"concat\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"dim\", \"default\": 1 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"concatshift\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"dim\", \"default\": 1 },\n      { \"name\": \"keep_size\", \"default\": 1 }\n    ],\n    \"outputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"shifted_data\" }\n    ]\n  },\n  {\n    \"name\": \"continuationindicator\",\n    \"attributes\": [\n      { \"name\": \"time_step\", \"default\": 0 },\n      { \"name\": \"batch_size\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"conv1d\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"ksize\", \"default\": 1 },\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0] },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"conv1d_winograd\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"ksize\", \"default\": 1 },\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0] },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1] },\n      { \"name\": \"wino_n\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"AT\" },\n      { \"name\": \"G\" },\n      { \"name\": \"BT\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"conv2d_lstm\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"filters\", \"default\": 1 },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"data_format\", \"default\": \"channels_last\" },\n      { \"name\": \"return_sequences\", \"default\": true },\n      { \"name\": \"recurrent_activation\", \"default\": \"hard_sigmoid\" },\n      { \"name\": \"activation\", \"default\": \"tanh\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"constants\": [\n      { \"name\": \"ki\" },\n      { \"name\": \"kf\" },\n      { \"name\": \"kc\" },\n      { \"name\": \"ko\" },\n      { \"name\": \"ri\" },\n      { \"name\": \"rf\" },\n      { \"name\": \"rc\" },\n      { \"name\": \"ro\" },\n      { \"name\": \"bi\" },\n      { \"name\": \"bf\" },\n      { \"name\": \"bc\" },\n      { \"name\": \"bo\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" },\n      { \"name\": \"output2\" }\n    ]\n  },\n  {\n    \"name\": \"conv2d_op\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"conv3d\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": false },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"ksize_d\", \"default\": 1 },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_d\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0, 0, 0] },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"convolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"regularize\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"multiplier\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"cos\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"cropandresize\",\n    \"attributes\": [\n      { \"name\": \"num_crop_boxes\", \"default\": 0 },\n      { \"name\": \"crop_size\", \"default\": [] },\n      { \"name\": \"resize_method\", \"default\": \"bilinear\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"boxes\" },\n      { \"name\": \"box_ind\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"crop_image\",\n    \"attributes\": [\n      { \"name\": \"crop_size\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"cumsum\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 0 },\n      { \"name\": \"exclusive\", \"default\": false },\n      { \"name\": \"reverse\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"customlayer\"\n  },\n  {\n    \"name\": \"dft\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": \"1\" },\n      { \"name\": \"inverse\", \"default\": \"0\" },\n      { \"name\": \"onesided\", \"default\": \"0\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"deconvolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"regularize\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"output_shape\", \"default\": [] },\n      { \"name\": \"output_padding_h\", \"default\": 0 },\n      { \"name\": \"output_padding_w\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"deconvolution1d\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"ksize\", \"default\": 1 },\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0] },\n      { \"name\": \"dilation\", \"default\": [1] },\n      { \"name\": \"output_shape\", \"default\": [] },\n      { \"name\": \"output_padding\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"deconvolution_op\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"regularize\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0,  0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"output_shape\", \"default\": [] },\n      { \"name\": \"output_padding_h\", \"default\": 0 },\n      { \"name\": \"output_padding_w\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"output_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"deconvolution3d\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": false },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"ksize_d\", \"default\": 1 },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_d\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0, 0, 0] },\n      { \"name\": \"pad_d_d\", \"default\": 0 },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"output_shape\", \"default\": [] },\n      { \"name\": \"output_padding_d\", \"default\": 0 },\n      { \"name\": \"output_padding_h\", \"default\": 0 },\n      { \"name\": \"output_padding_w\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"output_shape\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"depth2space\",\n    \"attributes\": [\n      { \"name\": \"block_size\", \"default\": 2 },\n      { \"name\": \"mode\", \"default\": \"DCR\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"depthwise_conv1d\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 2 },\n      { \"name\": \"ksize\", \"default\": 1 },\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0] },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1] },\n      { \"name\": \"multiplier\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"depthwise_conv2d_op\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] },\n      { \"name\": \"multiplier\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"depthwise_convolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"regularize\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] },\n      { \"name\": \"multiplier\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"dequantize\",\n    \"category\": \"Quantization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"detectionevaluate\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" },\n      { \"name\": \"output2\" },\n      { \"name\": \"output3\" },\n      { \"name\": \"output4\" }\n    ]\n  },\n  {\n    \"name\": \"detectionoutput\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"digit_capsule\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 1 },\n      { \"name\": \"vec_len\", \"default\": 1 },\n      { \"name\": \"iterations\", \"default\": 3 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Divide\",\n    \"inputs\": [\n      { \"name\": \"dividend\" },\n      { \"name\": \"divisor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"dropout\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"ratio\", \"default\": 0.5 },\n      { \"name\": \"scale_train\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"dropout2\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"ratio\", \"default\": 0.5 },\n      { \"name\": \"scale_train\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"dtype_converter\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"einsum\",\n    \"attributes\": [\n      { \"name\": \"equation\", \"default\": \"\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"eltwise\",\n    \"attributes\": [\n      { \"name\": \"operation\", \"default\": \"SUM\" },\n      { \"name\": \"coeff\", \"default\": \"1.0\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"elu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"embedding_lookup\",\n    \"attributes\": [\n      { \"name\": \"partition_strategy\", \"default\": \"mod\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"embedding_params\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"equal\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"erf\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"exp\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"expand_broadcast\",\n    \"attributes\": [\n      { \"name\": \"shape\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"dim\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"fill\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"fill_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"flatten\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"floor\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"floor_div\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"fullconnect\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"regularize\", \"default\": false },\n      { \"name\": \"axis\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"fullconnect_op\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"axis\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ],\n    \"constants\": [\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"gru\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_units\", \"default\": 1 },\n      { \"name\": \"time_major\", \"default\": true },\n      { \"name\": \"activation\", \"default\": \"tanh\" },\n      { \"name\": \"recurrent_activation\", \"default\": \"sigmoid\" },\n      { \"name\": \"return_sequences\", \"default\": true },\n      { \"name\": \"reset_after\", \"default\": true },\n      { \"name\": \"implementation\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"hidden_states\" }\n    ],\n    \"constants\": [\n      { \"name\": \"k_iz\" },\n      { \"name\": \"k_ir\" },\n      { \"name\": \"k_ih\" },\n      { \"name\": \"k_rz\" },\n      { \"name\": \"k_rr\" },\n      { \"name\": \"k_rh\" },\n      { \"name\": \"b_iz\" },\n      { \"name\": \"b_ir\" },\n      { \"name\": \"b_ih\" },\n      { \"name\": \"b_rz\" },\n      { \"name\": \"b_rr\" },\n      { \"name\": \"b_rh\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hidden_states\" }\n    ]\n  },\n  {\n    \"name\": \"gru_cell\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_units\", \"default\": 1 },\n      { \"name\": \"activation\", \"default\": \"tanh\" },\n      { \"name\": \"recurrent_activation\", \"default\": \"sigmoid\" },\n      { \"name\": \"reset_after\", \"default\": true },\n      { \"name\": \"implementation\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"hidden_states\" }\n    ],\n    \"constants\": [\n      { \"name\": \"k_iz\" },\n      { \"name\": \"k_ir\" },\n      { \"name\": \"k_ih\" },\n      { \"name\": \"k_rz\" },\n      { \"name\": \"k_rr\" },\n      { \"name\": \"k_rh\" },\n      { \"name\": \"b_iz\" },\n      { \"name\": \"b_ir\" },\n      { \"name\": \"b_ih\" },\n      { \"name\": \"b_rz\" },\n      { \"name\": \"b_rr\" },\n      { \"name\": \"b_rh\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hidden_states\" }\n    ]\n  },\n  {\n    \"name\": \"gather\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 0 },\n      { \"name\": \"batch_dims\", \"default\": null }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"gather_elements\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"gathernd\",\n    \"attributes\": [\n      { \"name\": \"batch_dims\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"gelu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"approximate\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"greater\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"greater_equal\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"gridsample\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"default\": \"bilinear\" },\n      { \"name\": \"padding_mode\", \"default\": \"zeros\" },\n      { \"name\": \"align_corners\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"group_conv1d\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 2 },\n      { \"name\": \"ksize\", \"default\": 1 },\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0] },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"groupnormalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"default\": 0.0001 },\n      { \"name\": \"num_groups\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"bias\" },\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"hammingwindow\",\n    \"attributes\": [\n      { \"name\": \"out_data_type\", \"default\": 1 },\n      { \"name\": \"periodic\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"hannwindow\",\n    \"attributes\": [\n      { \"name\": \"out_data_type\", \"default\": 1 },\n      { \"name\": \"periodic\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"hard_sigmoid\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"default\": 0.2 },\n      { \"name\": \"beta\", \"default\": 0.5 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"hard_swish\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"image_resize\",\n    \"attributes\": [\n      { \"name\": \"type\", \"default\": \"bilinear\" },\n      { \"name\": \"new_size\", \"default\": [] },\n      { \"name\": \"align_corners\", \"default\": false },\n      { \"name\": \"half_pixel\", \"default\": false },\n      { \"name\": \"size_factors\", \"default\": null },\n      { \"name\": \"layout\", \"default\": null }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"image_transform\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"in_topk\",\n    \"attributes\": [\n      { \"name\": \"topk\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"input\",\n    \"attributes\": [\n      { \"name\": \"size\", \"default\": \"\" },\n      { \"name\": \"channels\", \"default\": 1 },\n      { \"name\": \"shape\", \"default\": [] },\n      { \"name\": \"is_scalar\", \"default\": false },\n      { \"name\": \"type\", \"default\": \"float32\" },\n      { \"name\": \"merge_permute\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"instancenormalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"default\": 0.0001 },\n      { \"name\": \"axis\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"bias\" },\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"inverse_sigmoid\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"default\": 1e-05 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"keras_rnn_lstm\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"cell\", \"default\": null },\n      { \"name\": \"go_backwards\", \"default\": false },\n      { \"name\": \"return_sequences\", \"default\": false },\n      { \"name\": \"return_state\", \"default\": false },\n      { \"name\": \"stateful\", \"default\": false },\n      { \"name\": \"unroll\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"kernel\" },\n      { \"name\": \"recurrent_kernel\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"l1_layernormalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": -1 },\n      { \"name\": \"eps\", \"default\": 0.0001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"gamma\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"l2normalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"l2n_dim\", \"default\": null },\n      { \"name\": \"eps\", \"default\": 1e-12 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"l2normalizescale\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"l2n_dim\", \"default\": null },\n      { \"name\": \"eps\", \"default\": 1e-12 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"l2pooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"type\", \"default\": \"MAX\" },\n      { \"name\": \"global_pooling\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"round_type\", \"default\": \"ceil\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"count_include_pad\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"lstm\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"time_major\", \"default\": true },\n      { \"name\": \"forget_bias\", \"default\": 1.0 },\n      { \"name\": \"activation\", \"default\": \"tanh\" },\n      { \"name\": \"use_layer_norm_lstm\", \"default\": false },\n      { \"name\": \"use_cifg\", \"default\": false },\n      { \"name\": \"use_peepholes\", \"default\": false },\n      { \"name\": \"num_proj\", \"default\": null },\n      { \"name\": \"cell_clip\", \"default\": 0.0 },\n      { \"name\": \"proj_clip\", \"default\": 0.0 },\n      { \"name\": \"recurrent_activation\", \"default\": \"sigmoid\" },\n      { \"name\": \"return_sequences\", \"default\": true },\n      { \"name\": \"peephole\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"hidden_states\" },\n      { \"name\": \"cell_states\" }\n    ],\n    \"constants\": [\n      { \"name\": \"wi\" },\n      { \"name\": \"wf\" },\n      { \"name\": \"wc\" },\n      { \"name\": \"wo\" },\n      { \"name\": \"hi\" },\n      { \"name\": \"hf\" },\n      { \"name\": \"hc\" },\n      { \"name\": \"ho\" },\n      { \"name\": \"bi\" },\n      { \"name\": \"bf\" },\n      { \"name\": \"bc\" },\n      { \"name\": \"bo\" },\n      { \"name\": \"wp\" },\n      { \"name\": \"bp\" },\n      { \"name\": \"ci\" },\n      { \"name\": \"cf\" },\n      { \"name\": \"co\" },\n      { \"name\": \"ln_i\" },\n      { \"name\": \"ln_f\" },\n      { \"name\": \"ln_c\" },\n      { \"name\": \"ln_o\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hidden_states\" },\n      { \"name\": \"cell_states\" }\n    ]\n  },\n  {\n    \"name\": \"lstm_base\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"hidden_states\" },\n      { \"name\": \"cell_states\" }\n    ],\n    \"constants\": [\n      { \"name\": \"wi\" },\n      { \"name\": \"wf\" },\n      { \"name\": \"wc\" },\n      { \"name\": \"wo\" },\n      { \"name\": \"hi\" },\n      { \"name\": \"hf\" },\n      { \"name\": \"hc\" },\n      { \"name\": \"ho\" },\n      { \"name\": \"bi\" },\n      { \"name\": \"bf\" },\n      { \"name\": \"bc\" },\n      { \"name\": \"bo\" },\n      { \"name\": \"wp\" },\n      { \"name\": \"bp\" },\n      { \"name\": \"ci\" },\n      { \"name\": \"cf\" },\n      { \"name\": \"co\" },\n      { \"name\": \"ln_i\" },\n      { \"name\": \"ln_f\" },\n      { \"name\": \"ln_c\" },\n      { \"name\": \"ln_o\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hidden_states\" },\n      { \"name\": \"cell_states\" }\n    ]\n  },\n  {\n    \"name\": \"lstmunit\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"num_proj\", \"default\": null },\n      { \"name\": \"forget_bias\", \"default\": 1.0 },\n      { \"name\": \"cell_clip\", \"default\": 0.0 },\n      { \"name\": \"proj_clip\", \"default\": 0.0 },\n      { \"name\": \"activation\", \"default\": \"tanh\" },\n      { \"name\": \"use_layer_norm_lstm\", \"default\": false },\n      { \"name\": \"use_cifg\", \"default\": false },\n      { \"name\": \"use_peepholes\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"hidden_states\" },\n      { \"name\": \"cell_states\" }\n    ],\n    \"constants\": [\n      { \"name\": \"wi\" },\n      { \"name\": \"wf\" },\n      { \"name\": \"wc\" },\n      { \"name\": \"wo\" },\n      { \"name\": \"hi\" },\n      { \"name\": \"hf\" },\n      { \"name\": \"hc\" },\n      { \"name\": \"ho\" },\n      { \"name\": \"bi\" },\n      { \"name\": \"bf\" },\n      { \"name\": \"bc\" },\n      { \"name\": \"bo\" },\n      { \"name\": \"wp\" },\n      { \"name\": \"bp\" },\n      { \"name\": \"ci\" },\n      { \"name\": \"cf\" },\n      { \"name\": \"co\" },\n      { \"name\": \"ln_i\" },\n      { \"name\": \"ln_f\" },\n      { \"name\": \"ln_c\" },\n      { \"name\": \"ln_o\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hidden_states\" },\n      { \"name\": \"cell_states\" }\n    ]\n  },\n  {\n    \"name\": \"lstm_keras\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"units\", \"default\": 1 },\n      { \"name\": \"activation\", \"default\": \"tanh\" },\n      { \"name\": \"recurrent_activation\", \"default\": \"hard_sigmoid\" },\n      { \"name\": \"use_bias\", \"default\": true },\n      { \"name\": \"return_sequences\", \"default\": false },\n      { \"name\": \"return_state\", \"default\": false },\n      { \"name\": \"go_backwards\", \"default\": false },\n      { \"name\": \"stateful\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"kernel\" },\n      { \"name\": \"recurrent_kernel\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"layernormalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": [-1] },\n      { \"name\": \"eps\", \"default\": 0.0001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"bias\" },\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"leakyrelu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"leaky_ratio\", \"default\": 0.1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"less\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"less_equal\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LocalResponseNormalization\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"local_size\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": 2.0 },\n      { \"name\": \"alpha\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"default\": 0.75 },\n      { \"name\": \"type\", \"default\": \"NORM_ACROSS_CHANNELS\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LocalResponseNormalization_tf\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"local_size\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": 2.0 },\n      { \"name\": \"alpha\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"default\": 0.75 },\n      { \"name\": \"type\", \"default\": \"NORM_ACROSS_CHANNELS\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"log\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"log_softmax\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"sf_axis\", \"default\": -1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"logical_and\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"logical_not\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"logical_or\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"logical_xor\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"loop\",\n    \"attributes\": [\n      { \"name\": \"body\", \"default\": null },\n      { \"name\": \"max_iterations\", \"default\": null }\n    ]\n  },\n  {\n    \"name\": \"margin_loss_layer\",\n    \"attributes\": [\n      { \"name\": \"margin\", \"default\": 0.4 },\n      { \"name\": \"downweight\", \"default\": 0.5 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"mat_inverse\",\n    \"attributes\": [\n      { \"name\": \"adjoint\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"matmul\",\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"default\": false },\n      { \"name\": \"transpose_b\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"a\" },\n      { \"name\": \"b\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"c\" }\n    ]\n  },\n  {\n    \"name\": \"minimum\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"minimum_with_clip\",\n    \"attributes\": [\n      { \"name\": \"clip\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"mish\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"mod\",\n    \"attributes\": [\n      { \"name\": \"fmod\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"mod\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"moments\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": [] },\n      { \"name\": \"keep_dims\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ]\n  },\n  {\n    \"name\": \"multiply\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 1 },\n      { \"name\": \"bias\", \"default\": false }\n    ],\n    \"constants\": [\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"nms\",\n    \"attributes\": [\n      { \"name\": \"max_output_size\", \"default\": 100 },\n      { \"name\": \"iou_threshold\", \"default\": 0.5 },\n      { \"name\": \"score_threshold\", \"default\": 0.5 },\n      { \"name\": \"soft_nms_sigma\", \"default\": 0.0 },\n      { \"name\": \"pad_to_max_output_size\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" },\n      { \"name\": \"output2\" }\n    ]\n  },\n  {\n    \"name\": \"noop\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"nce_loss\",\n    \"attributes\": [\n      { \"name\": \"num_sampled\", \"default\": 1 },\n      { \"name\": \"num_classes\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"neg\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"nonzero\",\n    \"attributes\": [\n      { \"name\": \"output_type\", \"default\": \"int64\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"noop_multi_out\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"norm_with_channel_mean\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"mean\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"norm_with_min_max\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"min_value\", \"default\": 0.0 },\n      { \"name\": \"max_value\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"norm_with_scale\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"scale\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"not_equal\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"one_hot\",\n    \"attributes\": [\n      { \"name\": \"depth\", \"default\": 1 },\n      { \"name\": \"on_value\", \"default\": 1 },\n      { \"name\": \"off_value\", \"default\": 0 },\n      { \"name\": \"axis\", \"default\": -1 },\n      { \"name\": \"dtype\", \"default\": \"float32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"output\",\n    \"attributes\": [\n      { \"name\": \"merge_permute\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"prelu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"a\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"pad\",\n    \"attributes\": [\n      { \"name\": \"padding_value\", \"default\": [] },\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"padding_const\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"pad_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"permute\",\n    \"attributes\": [\n      { \"name\": \"perm\", \"default\": [0] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"pooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"type\", \"default\": \"MAX\" },\n      { \"name\": \"global_pooling\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"round_type\", \"default\": \"ceil\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"count_include_pad\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"pool1d\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"type\", \"default\": \"MAX\" },\n      { \"name\": \"global_pooling\", \"default\": false },\n      { \"name\": \"ksize\", \"default\": 1 },\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"round_type\", \"default\": \"ceil\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0] },\n      { \"name\": \"dilation\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"pool3d\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"type\", \"default\": \"MAX\" },\n      { \"name\": \"global_pooling\", \"default\": false },\n      { \"name\": \"ksize_d\", \"default\": 1 },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_d\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_d\", \"default\": 0 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"round_type\", \"default\": \"floor\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0, 0, 0] },\n      { \"name\": \"count_include_pad\", \"default\": 0 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"poolwithargmax\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"type\", \"default\": \"MAX\" },\n      { \"name\": \"global_pooling\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"round_type\", \"default\": \"ceil\" },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"count_include_pad\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" }\n    ]\n  },\n  {\n    \"name\": \"pow\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"preprocess\",\n    \"attributes\": [\n      { \"name\": \"type\", \"default\": \"VSI_NN_OP_PRE_PROCESS_RGB\" },\n      { \"name\": \"left\", \"default\": 0 },\n      { \"name\": \"top\", \"default\": 0 },\n      { \"name\": \"width\", \"default\": 244 },\n      { \"name\": \"height\", \"default\": 224 },\n      { \"name\": \"mean\", \"default\": [0, 0, 0] },\n      { \"name\": \"scale\", \"default\": 1 },\n      { \"name\": \"perm\", \"default\": [0, 1, 2, 3] },\n      { \"name\": \"in_dim_num\", \"default\": 4 },\n      { \"name\": \"out_dim_num\", \"default\": 4 },\n      { \"name\": \"out_size\", \"default\": [224, 224, 3, 1] },\n      { \"name\": \"reverse_channel\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"primary_capsule\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 1 },\n      { \"name\": \"vec_len\", \"default\": 1 },\n      { \"name\": \"strides\", \"default\": [1, 1] },\n      { \"name\": \"ksize\", \"default\": [1, 1] },\n      { \"name\": \"padding\", \"default\": \"SAME\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"priorbox\",\n    \"attributes\": [\n      { \"name\": \"mini_size\", \"default\": \"\" },\n      { \"name\": \"max_size\", \"default\": \"\" },\n      { \"name\": \"aspect_ratio\", \"default\": \"\" },\n      { \"name\": \"flip\", \"default\": \"\" },\n      { \"name\": \"clip\", \"default\": \"\" },\n      { \"name\": \"variance\", \"default\": \"0.1\" },\n      { \"name\": \"image_size\", \"default\": 0 },\n      { \"name\": \"image_h\", \"default\": 0 },\n      { \"name\": \"image_w\", \"default\": 0 },\n      { \"name\": \"step\", \"default\": 0.0 },\n      { \"name\": \"step_h\", \"default\": 0.0 },\n      { \"name\": \"step_w\", \"default\": 0.0 },\n      { \"name\": \"offset\", \"default\": 0.5 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Proposal\",\n    \"attributes\": [\n      { \"name\": \"feat_stride\", \"default\": 16 },\n      { \"name\": \"anchor_scales\", \"default\": \"8 16 32\" },\n      { \"name\": \"anchor_ratios\", \"default\": \"0.5 1 2\" },\n      { \"name\": \"anchor_base_size\", \"default\": 16 },\n      { \"name\": \"pre_nms_top_n\", \"default\": 6000 },\n      { \"name\": \"post_nms_top_n\", \"default\": 300 },\n      { \"name\": \"nms_thresh\", \"default\": 0.7 },\n      { \"name\": \"min_size\", \"default\": 16 },\n      { \"name\": \"im_info\", \"default\": \"800 600 1 1\" },\n      { \"name\": \"has_bg\", \"default\": true },\n      { \"name\": \"dynamic\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" }\n    ]\n  },\n  {\n    \"name\": \"quantize\",\n    \"category\": \"Quantization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"rmsnormalize\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": -1 },\n      { \"name\": \"eps\", \"default\": 0.0001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"roipooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"pooled_h\", \"default\": 6 },\n      { \"name\": \"pooled_w\", \"default\": 6 },\n      { \"name\": \"spatial_scale\", \"default\": 0.0625 },\n      { \"name\": \"sampling_ratio\", \"default\": 0.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"range\",\n    \"attributes\": [\n      { \"name\": \"start\", \"default\": 0 },\n      { \"name\": \"limit\", \"default\": -1 },\n      { \"name\": \"delta\", \"default\": 1 },\n      { \"name\": \"dtype\", \"default\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"rank\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reorg\",\n    \"attributes\": [\n      { \"name\": \"stride\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"real_div\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reconstruction_loss\",\n    \"attributes\": [\n      { \"name\": \"balance_factor\", \"default\": 0.0005 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"recurrent\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reduceany\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": null },\n      { \"name\": \"keep_dims\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reducel2\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": [] },\n      { \"name\": \"keep_dims\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reducemax\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": null },\n      { \"name\": \"keep_dims\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reducemean\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": null },\n      { \"name\": \"keep_dims\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reducemin\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": null },\n      { \"name\": \"keep_dims\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reduceprod\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": [] },\n      { \"name\": \"keep_dims\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reducesum\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": [] },\n      { \"name\": \"keep_dims\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"region\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"relu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"relun\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"relu_clamp_top\", \"default\": \"inf\" },\n      { \"name\": \"relu_clamp_bottom\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"relu_keras\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"default\": 0.0 },\n      { \"name\": \"max_value\", \"default\": \"inf\" },\n      { \"name\": \"threshold\", \"default\": 0.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"repeat\",\n    \"attributes\": [\n      { \"name\": \"maxlen\", \"default\": 0 },\n      { \"name\": \"axis\", \"default\": null }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"times\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reshape\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"shape\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"new_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"resizebilinear_image\",\n    \"attributes\": [\n      { \"name\": \"new_size\", \"default\": [] },\n      { \"name\": \"align_corners\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"resizenearest_image\",\n    \"attributes\": [\n      { \"name\": \"new_size\", \"default\": [] },\n      { \"name\": \"align_corners\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reverse\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"reverse_sequence\",\n    \"attributes\": [\n      { \"name\": \"seq_axis\", \"default\": 1 },\n      { \"name\": \"batch_axis\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"seq_lengths\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"round\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"route_train\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"rsqrt\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"stft\",\n    \"attributes\": [\n      { \"name\": \"onesided\", \"default\": \"1\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"signal\" },\n      { \"name\": \"step\" },\n      { \"name\": \"window\" },\n      { \"name\": \"length\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"svdf\",\n    \"attributes\": [\n      { \"name\": \"rank\", \"default\": 1 },\n      { \"name\": \"num_units\", \"default\": 1 },\n      { \"name\": \"spectrogram_length\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"state\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weights_feature\" },\n      { \"name\": \"weights_time\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"space2batch\",\n    \"attributes\": [\n      { \"name\": \"block_shape\", \"default\": [2, 2] },\n      { \"name\": \"block_paddings\", \"default\": [[0, 0], [0, 0]] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"space2batch_op\",\n    \"attributes\": [\n      { \"name\": \"block_shape\", \"default\": [2] },\n      { \"name\": \"block_paddings\", \"default\": [[0, 1]] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"block_paddings\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"space2depth\",\n    \"attributes\": [\n      { \"name\": \"block_size\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"scatter_elements\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 0 },\n      { \"name\": \"reduction\", \"default\": \"none\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"updates\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"scatternd\",\n    \"attributes\": [\n      { \"name\": \"shape\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"indices\" },\n      { \"name\": \"updates\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"scatter_nd_update\",\n    \"attributes\": [\n      { \"name\": \"reduction\", \"default\": \"none\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"updates\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"segment_sum\",\n    \"attributes\": [\n      { \"name\": \"segment_ids\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"selu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"default\": 1.68 },\n      { \"name\": \"gamma\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"sequence_mask\",\n    \"attributes\": [\n      { \"name\": \"maxlen\", \"default\": 50 },\n      { \"name\": \"dtype\", \"default\": \"bool\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"seq\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"shapelayer\",\n    \"attributes\": [\n      { \"name\": \"out_type\", \"default\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"shuffle\",\n    \"attributes\": [\n      { \"name\": \"group_number\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"sigmoid\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"sign\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"signalframe\",\n    \"attributes\": [\n      { \"name\": \"frame_length\", \"default\": 0 },\n      { \"name\": \"frame_step\", \"default\": 0 },\n      { \"name\": \"pad_end\", \"default\": false },\n      { \"name\": \"pad_value\", \"default\": 0 },\n      { \"name\": \"axis\", \"default\": -1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"simplernn_keras\",\n    \"attributes\": [\n      { \"name\": \"units\", \"default\": 1 },\n      { \"name\": \"activation\", \"default\": \"tanh\" },\n      { \"name\": \"use_bias\", \"default\": true },\n      { \"name\": \"return_sequences\", \"default\": false },\n      { \"name\": \"return_state\", \"default\": false },\n      { \"name\": \"go_backwards\", \"default\": false },\n      { \"name\": \"stateful\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"kernel\" },\n      { \"name\": \"recurrent_kernel\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"sin\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"size\",\n    \"attributes\": [\n      { \"name\": \"out_type\", \"default\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"slice\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"begin\", \"default\": [] },\n      { \"name\": \"size\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"slice_op\",\n    \"attributes\": [\n      { \"name\": \"axes\", \"default\": [] },\n      { \"name\": \"steps\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"starts\" },\n      { \"name\": \"ends\" },\n      { \"name\": \"axes\" },\n      { \"name\": \"steps\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"sf_axis\", \"default\": -1 },\n      { \"name\": \"beta\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"softrelu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"softmax_with_logits_loss_layer\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"sparse_to_dense\",\n    \"attributes\": [\n      { \"name\": \"output_shape\", \"default\": [] },\n      { \"name\": \"default_value\", \"default\": 0 },\n      { \"name\": \"validate_indices\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"sparse_indices\" },\n      { \"name\": \"sparse_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"split\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"dim\", \"default\": 1 },\n      { \"name\": \"slices\", \"default\": [] },\n      { \"name\": \"slices_tf\", \"default\": [] },\n      { \"name\": \"unstack\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"sqrt\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"square\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"squared_difference\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"squashing\",\n    \"category\": \"Reduce\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"squeeze\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"axis_list\", \"default\": null },\n      { \"name\": \"name\", \"default\": null }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"stack\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"stack_concat\",\n    \"attributes\": [\n      { \"name\": \"shape\", \"default\": [1, 32, 256] },\n      { \"name\": \"axis\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"index\" },\n      { \"name\": \"state\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"state\" }\n    ]\n  },\n  {\n    \"name\": \"stridedslice\",\n    \"attributes\": [\n      { \"name\": \"slice_begin_mask\", \"default\": 0 },\n      { \"name\": \"slice_end_mask\", \"default\": 0 },\n      { \"name\": \"slice_ellipsis_mask\", \"default\": 0 },\n      { \"name\": \"slice_new_axis_mask\", \"default\": 0 },\n      { \"name\": \"slice_shrink_axis_mask\", \"default\": 0 },\n      { \"name\": \"slice_begin\", \"default\": [] },\n      { \"name\": \"slice_end\", \"default\": [] },\n      { \"name\": \"slice_strides\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"slice_begin\" },\n      { \"name\": \"slice_end\" },\n      { \"name\": \"slice_strides\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"subgraph\",\n    \"attributes\": [\n      { \"name\": \"sg_argv\", \"default\": \"\" },\n      { \"name\": \"sg_func\", \"default\": \"\" },\n      { \"name\": \"sg_out_shapes\", \"default\": \"\" },\n      { \"name\": \"sg_graph_buffer\", \"default\": \"\" },\n      { \"name\": \"sg_input_nodes\", \"default\": \"\" },\n      { \"name\": \"sg_output_nodes\", \"default\": \"\" }\n    ]\n  },\n  {\n    \"name\": \"Subtract\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"swish\",\n    \"attributes\": [\n      { \"name\": \"beta\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"tan\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"tanh\",\n    \"attributes\": [\n      { \"name\": \"hyperbolic_tan_scale_a\", \"default\": 1.0 },\n      { \"name\": \"hyperbolic_tan_scale_b\", \"default\": 1.0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"tile\",\n    \"attributes\": [\n      { \"name\": \"multiples\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"repeats\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"topk\",\n    \"attributes\": [\n      { \"name\": \"k\", \"default\": 1 },\n      { \"name\": \"axis\", \"default\": -1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"k\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" }\n    ]\n  },\n  {\n    \"name\": \"topk_score\",\n    \"attributes\": [\n      { \"name\": \"topk\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" }\n    ]\n  },\n  {\n    \"name\": \"transform_unit\",\n    \"attributes\": [\n      { \"name\": \"heads_num\", \"default\": 1 },\n      { \"name\": \"axis_list\", \"default\": [-1] },\n      { \"name\": \"eps\", \"default\": 0.0001 },\n      { \"name\": \"shape\", \"default\": [] },\n      { \"name\": \"fc_weights\", \"default\": 1 },\n      { \"name\": \"fc_bias\", \"default\": true },\n      { \"name\": \"fc_regularize\", \"default\": false },\n      { \"name\": \"fc_axis\", \"default\": 1 },\n      { \"name\": \"shape_1\", \"default\": [] },\n      { \"name\": \"dim\", \"default\": 1 },\n      { \"name\": \"slices\", \"default\": [] },\n      { \"name\": \"slices_tf\", \"default\": [] },\n      { \"name\": \"unstack\", \"default\": false },\n      { \"name\": \"shape_Q\", \"default\": [] },\n      { \"name\": \"shape_K\", \"default\": [] },\n      { \"name\": \"shape_V\", \"default\": [] },\n      { \"name\": \"perm_Q\", \"default\": [0] },\n      { \"name\": \"perm_K\", \"default\": [0] },\n      { \"name\": \"perm_V\", \"default\": [0] },\n      { \"name\": \"transpose_a\", \"default\": false },\n      { \"name\": \"transpose_b\", \"default\": false },\n      { \"name\": \"mul_axis\", \"default\": 1 },\n      { \"name\": \"mul_bias\", \"default\": true },\n      { \"name\": \"sf_axis\", \"default\": -1 },\n      { \"name\": \"beta\", \"default\": 1.0 },\n      { \"name\": \"transpose_a_1\", \"default\": false },\n      { \"name\": \"transpose_b_1\", \"default\": false },\n      { \"name\": \"perm\", \"default\": [0] },\n      { \"name\": \"shape_2\", \"default\": [] },\n      { \"name\": \"shape_3\", \"default\": [] },\n      { \"name\": \"fc2_weights\", \"default\": 1 },\n      { \"name\": \"fc2_bias\", \"default\": true },\n      { \"name\": \"fc2_regularize\", \"default\": false },\n      { \"name\": \"fc2_axis\", \"default\": 1 },\n      { \"name\": \"shape_4\", \"default\": [] },\n      { \"name\": \"ln2_axis_list\", \"default\": [-1] },\n      { \"name\": \"ln2_eps\", \"default\": 0.0001 },\n      { \"name\": \"shape_5\", \"default\": [] },\n      { \"name\": \"fc3_weights\", \"default\": 1 },\n      { \"name\": \"fc3_bias\", \"default\": true },\n      { \"name\": \"fc3_regularize\", \"default\": false },\n      { \"name\": \"fc3_axis\", \"default\": 1 },\n      { \"name\": \"shape_6\", \"default\": [] },\n      { \"name\": \"approximate\", \"default\": false },\n      { \"name\": \"shape_7\", \"default\": [] },\n      { \"name\": \"fc4_weights\", \"default\": 1 },\n      { \"name\": \"fc4_bias\", \"default\": true },\n      { \"name\": \"fc4_regularize\", \"default\": false },\n      { \"name\": \"fc4_axis\", \"default\": 1 },\n      { \"name\": \"shape_8\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" }\n    ],\n    \"constants\": [\n      { \"name\": \"ln_scale\" },\n      { \"name\": \"ln_bias\" },\n      { \"name\": \"fc_weight\" },\n      { \"name\": \"fc_bias\" },\n      { \"name\": \"fc2_weight\" },\n      { \"name\": \"fc2_bias\" },\n      { \"name\": \"ln2_scale\" },\n      { \"name\": \"ln2_bias\" },\n      { \"name\": \"fc3_weight\" },\n      { \"name\": \"fc3_bias\" },\n      { \"name\": \"fc4_weight\" },\n      { \"name\": \"fc4_bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"unstack\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"upsampling3d\",\n    \"attributes\": [\n      { \"name\": \"size\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"upsampling\",\n    \"attributes\": [\n      { \"name\": \"factor\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"variable\",\n    \"category\": \"Data\",\n    \"attributes\": [\n      { \"name\": \"shape\", \"default\": [1] },\n      { \"name\": \"is_scalar\", \"default\": false },\n      { \"name\": \"type\", \"default\": \"float32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"data\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"where\",\n    \"inputs\": [\n      { \"name\": \"input0\" },\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"while_loop\",\n    \"attributes\": [\n      { \"name\": \"cond\", \"default\": null },\n      { \"name\": \"body\", \"default\": null },\n      { \"name\": \"max_iterations\", \"default\": null }\n    ]\n  },\n  {\n    \"name\": \"yolo\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"yoloprocess\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"zeros_like\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"conv2d_winograd\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding_mode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"weights\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": \"VALID\" },\n      { \"name\": \"bias\", \"default\": true },\n      { \"name\": \"group_number\", \"default\": 1 },\n      { \"name\": \"regularize\", \"default\": false },\n      { \"name\": \"ksize_h\", \"default\": 1 },\n      { \"name\": \"ksize_w\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_h\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"dilation\", \"default\": [1, 1, 1, 1] },\n      { \"name\": \"pad_method\", \"default\": \"auto\" },\n      { \"name\": \"pad\", \"default\": [0, 0, 0, 0] },\n      { \"name\": \"pad_h_b\", \"default\": 0 },\n      { \"name\": \"pad_w_r\", \"default\": 0 },\n      { \"name\": \"multiplier\", \"default\": 0 },\n      { \"name\": \"wino_n\", \"default\": 2 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"constants\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"AT\" },\n      { \"name\": \"G\" },\n      { \"name\": \"BT\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"postprocess\",\n    \"attributes\": [\n      { \"name\": \"perm\", \"default\": [0, 1, 2, 3] },\n      { \"name\": \"dim_num\", \"default\": 4 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/acuity.js",
    "content": "\nconst acuity = {};\n\nacuity.ModelFactory = class {\n\n    async match(context) {\n        const obj = await context.peek('json');\n        if (obj && obj.MetaData && obj.Layers && Object.keys(obj).length < 256) {\n            return context.set('acuity', obj);\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('acuity-metadata.json');\n        return new acuity.Model(metadata, context.value);\n    }\n};\n\nacuity.Model = class {\n\n    constructor(metadata, model, data, quantization) {\n        this.name = model.MetaData.Name;\n        this.format = `Acuity${model.MetaData && model.MetaData.AcuityVersion ? ` v${model.MetaData.AcuityVersion}` : ''}`;\n        this.runtime = model.MetaData.Platform;\n        this.modules = [new acuity.Graph(metadata, model, data, quantization)];\n    }\n};\n\nacuity.Graph = class {\n\n    constructor(metadata, model) {\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.metrics = [];\n        const values = new Map();\n        const value = (name) => {\n            if (!values.has(name)) {\n                values.set(name, { name, shape: null });\n            }\n            return values.get(name);\n        };\n        let totalFlops = 0;\n        for (const [name, layer] of Object.entries(model.Layers)) {\n            layer.inputs = layer.inputs.map((input) => {\n                return value(input);\n            });\n            layer.outputs = layer.outputs.map((port) => {\n                const output = value(`@${name}:${port}`);\n                let shape = null;\n                if (layer.op.toLowerCase() === 'input' ||\n                    layer.op.toLowerCase() === 'variable') {\n                    if (Object.prototype.hasOwnProperty.call(layer.parameters, 'shape') && layer.parameters.shape.length > 0) {\n                        shape = layer.parameters.shape;\n                    } else if (Object.prototype.hasOwnProperty.call(layer.parameters, 'size') && Object.prototype.hasOwnProperty.call(layer.parameters, 'channels')) {\n                        const sizes = layer.parameters.size.split(' ');\n                        shape = [0, parseInt(sizes[0], 10), parseInt(sizes[1], 10), layer.parameters.channels];\n                    } else if (Object.prototype.hasOwnProperty.call(layer.parameters, 'is_scalar')) {\n                        shape = [1];\n                    }\n                    if (shape && shape.length === 4 && shape[0] === 0) {\n                        shape[0] = 1;\n                    }\n                }\n                output.shape = shape;\n                return output;\n            });\n            // Add other layer types (e.g., pooling, batch norm, etc.) as needed.\n            if (layer.type === 'Conv2D') {\n                const { kernelShape, inputShape, outputShape } = layer;\n                const [kH, kW] = kernelShape;\n                const [inC] = inputShape;\n                const [outC, oH, oW] = outputShape;\n                totalFlops += kH * kW * inC * oH * oW * outC;\n            } else if (layer.type === 'Dense') {\n                const { inputSize, outputSize } = layer;\n                totalFlops += inputSize * outputSize;\n            }\n        }\n        this.metrics.push(new acuity.Argument('flops', totalFlops));\n        acuity.Inference.infer(model.Layers);\n        for (const [name, obj] of values) {\n            const type = new acuity.TensorType(null, new acuity.TensorShape(obj.shape));\n            const value = new acuity.Value(name, type, null, null);\n            values.set(name, value);\n        }\n        for (const [name, layer] of Object.entries(model.Layers)) {\n            switch (layer.op.toLowerCase()) {\n                case 'input': {\n                    const value = values.get(layer.outputs[0].name);\n                    const argument = new acuity.Argument(name, [value]);\n                    this.inputs.push(argument);\n                    break;\n                }\n                case 'output': {\n                    const value = values.get(layer.inputs[0].name);\n                    const argument = new acuity.Argument(name, [value]);\n                    this.outputs.push(argument);\n                    break;\n                }\n                default: {\n                    const node = new acuity.Node(metadata, name, layer, values);\n                    this.nodes.push(node);\n                    break;\n                }\n            }\n        }\n    }\n};\n\nacuity.Node = class {\n\n    constructor(metadata, name, layer, values) {\n        const op = layer.op;\n        this.name = name;\n        this.type = metadata.type(op) || { name: op };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (this.type) {\n            if (layer.parameters) {\n                for (const [name, value] of Object.entries(layer.parameters)) {\n                    const meta = metadata.attribute(op, name);\n                    const type = meta && meta.type ? meta.type : null;\n                    const visible = meta && meta.default !== undefined && meta.default === value ? false : true;\n                    const attribute = new acuity.Argument(name, value, type, visible);\n                    this.attributes.push(attribute);\n                }\n            }\n        }\n        for (let i = 0; i < layer.inputs.length; i++) {\n            const input = layer.inputs[i];\n            const value = values.get(input.name);\n            const name = this.type && this.type.inputs && i < this.type.inputs.length ? this.type.inputs[i].name : `input${i}`;\n            const argument = new acuity.Argument(name, [value]);\n            this.inputs.push(argument);\n        }\n\n        if (this.type && this.type.constants) {\n            for (const constant of this.type.constants) {\n                // const name = \"@\" + this.name + \":\" + constant.name;\n                const type = new acuity.TensorType(null, new acuity.TensorShape(null));\n                const value = new acuity.Value('', type, null, new acuity.Tensor(type));\n                const argument = new acuity.Argument(constant.name, [value]);\n                this.inputs.push(argument);\n            }\n        }\n\n        for (let i = 0; i < layer.outputs.length; i++) {\n            const output = layer.outputs[i];\n            const value = values.get(output.name);\n            const name = this.type && this.type.outputs && i < this.type.outputs.length ? this.type.outputs[i].name : `output${i}`;\n            const argument = new acuity.Argument(name, [value]);\n            this.outputs.push(argument);\n        }\n    }\n};\n\nacuity.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nacuity.Value = class {\n\n    constructor(name, type = null, quantization = null, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new acuity.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = type;\n        this.quantization = quantization;\n        this.initializer = initializer;\n    }\n};\n\nacuity.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = shape;\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\nacuity.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.isArray(dimensions) && dimensions.length === 1 && dimensions[0] === 0 ? [] : dimensions;\n    }\n\n    toString() {\n        if (!Array.isArray(this.dimensions) || this.dimensions.length === 0 || (this.dimensions.length === 1 && this.dimensions[0] === 0)) {\n            return '';\n        }\n        return `[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`;\n    }\n};\n\nacuity.Tensor = class {\n\n    constructor(type) {\n        this.type = type;\n        this.Category = 'Constant';\n    }\n};\n\nacuity.Inference = class {\n\n    static infer(layers) {\n        const outputs = new Map();\n        const outputLayers = [];\n        for (const [, layer] of Object.entries(layers)) {\n            if (layer.op.toLowerCase() === 'output') {\n                outputLayers.push(layer);\n            }\n            for (const output of layer.outputs) {\n                outputs.set(output.name, layer);\n            }\n        }\n        const broadcasts = new Set([\n            'add', 'equal', 'fllor_mod', 'floor_div', 'greater', 'greater_equal', 'less', 'less_equal',\n            'logical_and', 'logical_or', 'minimum', 'multiply', 'not_equal', 'pow', 'real_div',\n            'squared_difference', 'subtract', 'divide', 'addn', 'Divide', 'bitwise_and', 'bitwise_or',\n            'bitwise_xor', 'average', 'logical_not', 'logical_xor'\n        ]);\n        const passthroughs = new Set([\n            'LocalResponseNormalization', 'a_times_b_plus_c', 'abs', 'batchnorm_single', 'batchnormalize',\n            'cast', 'cast', 'clipbyvalue', 'dequantize', 'dtype_converter', 'elu', 'exp', 'floor',\n            'groupnormalize', 'hard_sigmoid', 'hard_swish', 'instancenormalize', 'l2normalize', 'l2normalizescale',\n            'layernormalize', 'leakyrelu', 'log', 'log_softmax', 'mish', 'neg', 'norm_with_channel_mean',\n            'norm_with_min_max', 'norm_with_scale', 'pow', 'prelu', 'quantize', 'relu', 'relu_keras',\n            'relun', 'reverse', 'round', 'rsqrt', 'sigmoid', 'sin', 'softmax', 'softrelu', 'sqrt', 'square', 'tanh',\n            'swish', 'gelu', 'dropout', 'eltwise', 'cos', 'l1_layernormalize', 'inverse_sigmoid', 'selu', 'mod',\n            'mish', 'minimum_with_clip', 'celu', 'cumsum', 'dft', 'dropout2', 'erf', 'noop', 'squashing', 'tan', 'ceil',\n            'atan', 'atan2', 'atanh', 'alpha_dropout', 'acosh', 'rmsnormalize', 'sign'\n        ]);\n        const reduces = new Set([\n            'reduceany', 'reducemax', 'reducemean', 'reducemin', 'reduceprod', 'reducesum'\n        ]);\n        const poolings = new Set([\n            'pooling', 'l2pooling'\n        ]);\n        const operators = new Map();\n        operators.set('broadcast', ([a, b]) => {\n            const longer = a.length >= b.length ? a.slice() : b.slice();\n            const shorter = a.length < b.length ? a.slice() : b.slice();\n            const remain = longer.length - shorter.length;\n            for (let i = 0; i < remain; i++) {\n                shorter.splice(0, 0, 1);\n            }\n            for (let i = 0; i < longer.length; i++) {\n                longer[i] = longer[i] > shorter[i] ? longer[i] : shorter[i];\n            }\n            return [longer];\n        });\n        operators.set('concat', (inputs, params) => {\n            const outputShape = inputs[0].slice();\n            outputShape[params.dim] = 0;\n            for (const shape of inputs) {\n                outputShape[params.dim] += shape[params.dim];\n            }\n            return [outputShape];\n        });\n        operators.set('conv1d', (inputs, params) => {\n            if (params.padding === 'VALID') {\n                const out_h = ~~((inputs[0][1] + params.stride - params.ksize) / params.stride);\n                return [[inputs[0][0], out_h, params.weights]];\n            } else if (params.padding === 'SAME') {\n                const out_h = ~~((inputs[0][1] + params.stride - 1) / params.stride);\n                return [[inputs[0][0], out_h, params.weights]];\n            }\n            return null;\n        });\n        operators.set('convolution', (inputs, params) => {\n            if (params.padding === 'VALID') {\n                const out_h = Math.floor((inputs[0][1] + params.stride_h + 2 * params.pad_h - params.ksize_h) / params.stride_h);\n                const out_w = Math.floor((inputs[0][2] + params.stride_w + 2 * params.pad_w - params.ksize_w) / params.stride_w);\n                return [[inputs[0][0], out_h, out_w, params.weights]];\n            } else if (params.padding === 'SAME') {\n                const out_h = Math.floor((inputs[0][1] + params.stride_h - 1) / params.stride_h);\n                const out_w = Math.floor((inputs[0][2] + params.stride_w - 1) / params.stride_w);\n                return [[inputs[0][0], out_h, out_w, params.weights]];\n            }\n            return null;\n        });\n        operators.set('depthwise_conv1d', (inputs, params) => {\n            if (params.padding === 'VALID') {\n                const out_h = ~~((inputs[0][1] + params.stride + params.pad[0] + params.pad[1] - params.ksize) / params.stride);\n                return [[inputs[0][0], out_h, inputs[0][2] * params.multiplier]];\n            } else if (params.padding === 'SAME') {\n                const out_h = ~~((inputs[0][1] + params.stride - 1) / params.stride);\n                return [[inputs[0][0], out_h, inputs[0][2] * params.multiplier]];\n            }\n            return null;\n        });\n        operators.set('depthwise_convolution', (inputs, params) => {\n            if (params.padding === 'VALID') {\n                const out_h = ~~((inputs[0][1] + params.stride_h + params.pad[0] + params.pad[1] - params.ksize_h) / params.stride_h);\n                const out_w = ~~((inputs[0][2] + params.stride_w + params.pad[2] + params.pad[3] - params.ksize_w) / params.stride_w);\n                return [[inputs[0][0], out_h, out_w, inputs[0][3] * params.multiplier]];\n            } else if (params.padding === 'SAME') {\n                const out_h = ~~((inputs[0][1] + params.stride_h - 1) / params.stride_h);\n                const out_w = ~~((inputs[0][2] + params.stride_w - 1) / params.stride_w);\n                return [[inputs[0][0], out_h, out_w, inputs[0][3] * params.multiplier]];\n            }\n            return null;\n        });\n        operators.set('deconvolution', (inputs, params) => {\n            return [params.output_shape.map((item, index) => item === 0 ? inputs[0][index] : item)];\n        });\n        operators.set('deconvolution1d', (inputs, params) => {\n            return [params.output_shape.map((item, index) => item === 0 ? inputs[0][index] : item)];\n        });\n        operators.set('fullconnect', (inputs, params) => {\n            return [inputs[0].slice(0, params.axis).concat([params.weights])];\n        });\n        operators.set('gather', (inputs, params) => {\n            const prefix = inputs[1].slice();\n            const suffix = inputs[0].slice(params.axis + 1);\n            return [prefix.concat(suffix)];\n        });\n        operators.set('lstm', (inputs, params) => {\n            const [input] = inputs;\n            const [a, b] = input;\n            let batch = a;\n            const output = params.num_proj === null ? params.weights : params.num_proj;\n            if (params.time_major) {\n                batch = b;\n            }\n            const newShape = params.return_sequences ? [a, b, output] : [batch, output];\n            return [newShape, [batch, output], [batch, params.weights]];\n        });\n        operators.set('matmul', ([a, b], params) => {\n            let newShape = a.slice(0, -2);\n            if (params.transpose_a) {\n                newShape = newShape.concat(a.slice(-1));\n            } else {\n                newShape = newShape.concat(a.slice(-2, -1));\n            }\n            if (params.transpose_b) {\n                newShape = newShape.concat(b.slice(-2, -1));\n            } else {\n                newShape = newShape.concat(b.slice(-1));\n            }\n            return [newShape];\n        });\n        operators.set('pad', (inputs, params) => {\n            return [inputs[0].map((item, index) => item + params.padding_value[index][0] + params.padding_value[index][1])];\n        });\n        operators.set('permute', (inputs, params) => {\n            return [inputs[0].map((item, index) => inputs[0][params.perm[index]])];\n        });\n        operators.set('pooling', (inputs, params) => {\n            if (params.padding === 'VALID') {\n                const out_h = ~~((inputs[0][1] + params.stride_h - params.ksize_h) / params.stride_h);\n                const out_w = ~~((inputs[0][2] + params.stride_w - params.ksize_w) / params.stride_w);\n                return [[inputs[0][0], out_h, out_w, inputs[0][3]]];\n            } else if (params.padding === 'SAME') {\n                const out_h = ~~((inputs[0][1] + params.stride_h - 1) / params.stride_h);\n                const out_w = ~~((inputs[0][2] + params.stride_w - 1) / params.stride_w);\n                return [[inputs[0][0], out_h, out_w, inputs[0][3]]];\n            }\n            return null;\n        });\n        operators.set('reduce', (inputs, params) => {\n            const newShape = inputs[0].slice();\n            const axis_list = params.axis_list.map((item) => {\n                return item < 0 ? newShape.length + item : item;\n            });\n            axis_list.sort((a, b) => {\n                return b - a;\n            });\n            axis_list.forEach((i) => {\n                newShape[i] = 1;\n            });\n            if (!params.keep_dims) {\n                axis_list.forEach((i) => {\n                    newShape.splice(i, 1);\n                });\n                if (!newShape.length) {\n                    newShape.splice(0, 0, 0);\n                }\n            }\n            return [newShape];\n        });\n        operators.set('repeat', (inputs, params) => {\n            const newShape = inputs[0].slice();\n            newShape[params.axis] = params.maxlen;\n            return [newShape];\n        });\n        operators.set('reshape', (inputs, params) => {\n            const negativeIndexs = [];\n            let shape = params.shape;\n            if (typeof params.shape === 'string') {\n                shape = params.shape.split(/\\s+/).map((item) => {\n                    return parseInt(item, 10);\n                });\n            }\n            const newShape = shape.map((item, index) => {\n                if (item === 0) {\n                    return inputs[0][index];\n                }\n                if (item === -1) {\n                    negativeIndexs.push(index);\n                    return 1;\n                }\n                return item;\n            });\n            if (negativeIndexs.length > 0) {\n                newShape[negativeIndexs[0]] = inputs[0].reduce((a, c) => a * c) / newShape.reduce((a, c) => a * c);\n            }\n            return [newShape];\n        });\n        operators.set('sequence_mask', (inputs, params) => {\n            return [inputs[0].slice().concat([params.maxlen])];\n        });\n        operators.set('slice', (inputs, params) => {\n            return [params.size.map((item, index) => item === -1 ? inputs[0][index] : item)];\n        });\n        operators.set('squeeze', (inputs, params) => {\n            const newShape = inputs[0].slice();\n            const axis_list = [...new Set(params.axis_list)].sort((a, b) => b - a);\n            for (const item of axis_list) {\n                newShape.splice(item, 1);\n            }\n            return [newShape];\n        });\n        operators.set('space2depth', (inputs, params) => {\n            const h = inputs[0][1] / params.block_size[0];\n            const w = inputs[0][2] / params.block_size[1];\n            const c = inputs[0][3] * params.block_size[1] * params.block_size[1];\n            return [[inputs[0][0], h, w, c]];\n        });\n        operators.set('depth2space', (inputs, params) => {\n            const h = inputs[0][1] * params.block_size;\n            const w = inputs[0][2] * params.block_size;\n            const c = inputs[0][3] / (params.block_size * params.block_size);\n            return [[inputs[0][0], h, w, c]];\n        });\n        operators.set('upsampling', (inputs, params) => {\n            const h = inputs[0][1] * params.factor;\n            const w = inputs[0][2] * params.factor;\n            return [[inputs[0][0], h, w, inputs[0][3]]];\n        });\n        operators.set('crop_image', (inputs, params) => {\n            return [[inputs[0][0], params.crop_size[0], params.crop_size[1], inputs[0][3]]];\n        });\n        operators.set('split', (inputs, params) => {\n            const sizes = [];\n            const slices = params.slices.slice();\n            slices.splice(0, 0, 0);\n            slices.push(inputs[0][params.dim]);\n            slices.reduce((a, b) => {\n                sizes.push(b - a);\n                return b;\n            });\n            return sizes.map((item) => {\n                const shape = inputs[0].slice();\n                shape[params.dim] = item;\n                return shape;\n            });\n        });\n        operators.set('stack', (inputs, params) => {\n            const newShape = inputs[0].slice();\n            if (newShape.length === 1 && newShape[0] === 0) {\n                newShape[0] = 1;\n            } else {\n                newShape.splice(params.axis, 0, inputs.length);\n            }\n            return [newShape];\n        });\n        operators.set('stridedslice', (inputs, params) => {\n            const input_shape = inputs[0].slice();\n            const begin = params.slice_begin.slice();\n            const end = params.slice_end.slice();\n            if (params.slice_begin_mask > 0) {\n                for (let i = 0; i < begin.length; i++) {\n                    if ((params.slice_begin_mask >>> i) & 0x1) {\n                        begin[i] = -1;\n                    }\n                }\n            }\n            if (params.slice_end_mask > 0) {\n                for (let i = 0; i < end.length; i++) {\n                    if ((params.slice_end_mask >>> i) & 0x1) {\n                        end[i] = -1;\n                    }\n                }\n            }\n            for (let i = 0; i < begin.length; i++) {\n                if (begin[i] === -1) {\n                    begin[i] = 0;\n                }\n            }\n            if (inputs[0].length === end.length) {\n                for (let i = 0; i < end.length; i++) {\n                    if (end[i] === -1 || end[i] > input_shape[i]) {\n                        end[i] = input_shape[i];\n                    }\n                }\n            } else if (inputs[0].length < end.length) {\n                if (params.slice_new_axis_mask) {\n                    const len = (params.slice_new_axis_mask >>> 0).toString(2).length;\n                    for (let i = 0; i < len; i++) {\n                        if ((params.slice_new_axis_mask >>> i) & 0x1) {\n                            input_shape.splice(i, 0, 1);\n                        }\n                    }\n                    for (let i = 0; i < end.length; i++) {\n                        if (end[i] === -1) {\n                            end[i] = input_shape[i];\n                        }\n                    }\n                }\n            }\n            let newShape = [];\n            for (let i = 0; i < begin.length; i++) {\n                newShape = newShape.concat([(end[i] - begin[i]) / params.slice_strides[i]]);\n            }\n            if (params.slice_shrink_axis_mask) {\n                const len = (params.slice_shrink_axis_mask >>> 0).toString(2).length;\n                for (let i = 0; i < len; i++) {\n                    if ((params.slice_shrink_axis_mask >>> i) & 0x1) {\n                        newShape.splice(i, 1);\n                    }\n                }\n            }\n            if (params.slice_new_axis_mask) {\n                const len = (params.slice_new_axis_mask >>> 0).toString(2).length;\n                for (let i = 0; i < len; i++) {\n                    if ((params.slice_new_axis_mask >>> i) & 0x1) {\n                        if (inputs[0].length === begin.length) {\n                            newShape.splice(i, 0, 1);\n                        } else if (inputs[0].length < begin.length) {\n                            newShape[i] = 1;\n                        }\n                    }\n                }\n            }\n            return [newShape];\n        });\n        operators.set('image_resize', (inputs, params) => {\n            const newShape = inputs[0].slice();\n            newShape[1] = params.new_size[0];\n            newShape[2] = params.new_size[1];\n            return [newShape];\n        });\n        operators.set('argmax', (inputs, params) => {\n            const newShape = inputs[0].slice();\n            if (params.keepdims) {\n                newShape[params.axis] = 1;\n            } else {\n                newShape.splice(params.axis, 1);\n                if (!newShape.length) {\n                    newShape.splice(0, 0, 0);\n                }\n            }\n            return [newShape];\n        });\n        operators.set('argmin', operators.get('argmax'));\n        /* eslint-disable no-unused-vars */\n        operators.set('shapelayer', (inputs, params) => {\n            return [[inputs[0].length]];\n        });\n        operators.set('capsule_norm', (inputs, params) => {\n            return [[inputs[0][0], inputs[0][inputs[0].length - 1]]];\n        });\n        operators.set('size', (inputs, params) => {\n            return [[1]];\n        });\n        /* eslint-enable no-unused-vars */\n        operators.set('einsum', ((operators, inputs, params) => {\n            const identifyOperation = (inputs, equation) => {\n                const identifyFuncs = new Map();\n                identifyFuncs.set('matmul', (inputs, equation) => {\n                    if (inputs.length !== 2) {\n                        return { found: false };\n                    }\n\n                    const parts = equation.replace(/\\s+/g, '').split(/,|->/);\n                    if (parts.length !== 3) {\n                        return { found: false };\n                    }\n\n                    const [first, second, output] = parts.map((p) => p.split(''));\n                    if (!(first.length === output.length || second.length === output.length)) {\n                        return { found: false };\n                    }\n\n                    let a = first.slice(-2);\n                    const b = second.slice(-2);\n                    const c = output.slice(-2);\n                    let transpose_a = false;\n                    let transpose_b = false;\n                    if (a[0] === c[0]) {\n                        transpose_a = false;\n                    } else if (a[1] === c[0]) {\n                        transpose_a = true;\n                        a = [].concat(a.reverse());\n                    } else {\n                        return { found: false };\n                    }\n\n                    if (a[1] === b[0]) {\n                        transpose_b = false;\n                    } else if (a[1] === b[1]) {\n                        transpose_b = true;\n                    } else {\n                        return { found: false };\n                    }\n                    return { found: true, op: 'matmul', params: { transpose_a, transpose_b } };\n                });\n\n                /* eslint-disable no-unused-vars */\n                for (const [name, func] of identifyFuncs.entries()) {\n                    const result = func(inputs, equation);\n                    if (result.found) {\n                        return result;\n                    }\n                }\n                /* eslint-enable no-unused-vars */\n                return { found: false };\n            };\n\n            const result = identifyOperation(inputs, params.equation);\n            if (result.found) {\n                if (operators.has(result.op)) {\n                    return operators.get(result.op)(inputs, result.params);\n                }\n            }\n            return [];\n        }).bind(undefined, operators));\n        const infer = (output) => {\n            if (outputs.has(output.name)) {\n                let ready = true;\n                const layer = outputs.get(output.name);\n                for (const input of layer.inputs) {\n                    if (input.shape === null) {\n                        infer(input);\n                        if (input.shape === null) {\n                            ready = false;\n                            break;\n                        }\n                    }\n                }\n                if (ready) {\n                    let callback = null;\n                    if (operators.has(layer.op)) {\n                        callback = operators.get(layer.op);\n                    } else if (passthroughs.has(layer.op)) {\n                        callback = (inputs) => [inputs[0].slice()];\n                    } else if (broadcasts.has(layer.op)) {\n                        callback = operators.get('broadcast');\n                    } else if (reduces.has(layer.op)) {\n                        callback = operators.get('reduce');\n                    } else if (poolings.has(layer.op)) {\n                        callback = operators.get('pooling');\n                    }\n                    if (!callback) {\n                        callback = () => [];\n                    }\n                    const parameters = layer.parameters;\n                    const inputs = layer.inputs.map((input) => input.shape);\n                    const outputs = callback(inputs, parameters);\n                    for (let i = 0; i < outputs.length; i++) {\n                        if (i < layer.outputs.length) {\n                            layer.outputs[i].shape = outputs[i];\n                        }\n                    }\n                }\n            }\n        };\n        for (const layer of outputLayers) {\n            for (const output of layer.outputs) {\n                infer(output);\n            }\n        }\n    }\n};\n\nacuity.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Acuity model.';\n    }\n};\n\nexport const ModelFactory = acuity.ModelFactory;"
  },
  {
    "path": "source/app.js",
    "content": "\nimport * as base from './base.js';\nimport * as electron from 'electron';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as process from 'process';\nimport * as updater from 'electron-updater';\nimport * as url from 'url';\n\nconst app = {};\n\napp.Application = class {\n\n    constructor() {\n        this._views = new app.ViewCollection(this);\n        this._configuration = new app.ConfigurationService();\n        this._menu = new app.MenuService(this._views);\n        this._openQueue = [];\n        this._package = {};\n    }\n\n    async start() {\n        const dirname = path.dirname(url.fileURLToPath(import.meta.url));\n        const packageFile = path.join(path.dirname(dirname), 'package.json');\n        const packageContent =  fs.readFileSync(packageFile, 'utf-8');\n        this._package = JSON.parse(packageContent);\n\n        electron.app.setAppUserModelId('com.lutzroeder.netron');\n        electron.app.allowRendererProcessReuse = true;\n\n        if (!electron.app.requestSingleInstanceLock()) {\n            electron.app.quit();\n            return;\n        }\n\n        electron.app.on('second-instance', (event, commandLine, workingDirectory) => {\n            const currentDirectory = process.cwd();\n            process.chdir(workingDirectory);\n            const open = this._parseCommandLine(commandLine);\n            process.chdir(currentDirectory);\n            if (!open && !this._views.empty) {\n                const view = this._views.first();\n                if (view) {\n                    view.restore();\n                }\n            }\n        });\n        electron.ipcMain.on('get-environment', (event) => {\n            event.returnValue = this.environment;\n        });\n        electron.ipcMain.on('get-configuration', (event, obj) => {\n            event.returnValue = this._configuration.has(obj.name) ? this._configuration.get(obj.name) : undefined;\n        });\n        electron.ipcMain.on('set-configuration', (event, obj) => {\n            this._configuration.set(obj.name, obj.value);\n            this._configuration.save();\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('delete-configuration', (event, obj) => {\n            this._configuration.delete(obj.name);\n            this._configuration.save();\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('drop-paths', (event, data) => {\n            const paths = data.paths.filter((path) => {\n                if (fs.existsSync(path)) {\n                    const stat = fs.statSync(path);\n                    return stat.isFile() || stat.isDirectory();\n                }\n                return false;\n            });\n            this._dropPaths(event.sender, paths);\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('update-recents', (event, data) => {\n            this._updateRecents(data.path);\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('show-save-dialog', async (event, options) => {\n            const owner = event.sender.getOwnerBrowserWindow();\n            const argument = {};\n            try {\n                const { filePath, canceled } = await electron.dialog.showSaveDialog(owner, options);\n                argument.filePath = filePath;\n                argument.canceled = canceled;\n            } catch (error) {\n                argument.error = error.message;\n            }\n            event.sender.send('show-save-dialog-complete', argument);\n        });\n        electron.ipcMain.on('execute', async (event, data) => {\n            const owner = event.sender.getOwnerBrowserWindow();\n            const argument = {};\n            try {\n                argument.value = await this.execute(data.name, data.value || null, owner);\n            } catch (error) {\n                argument.error = error.message;\n            }\n            event.sender.send('execute-complete', argument);\n        });\n\n        electron.app.on('will-finish-launching', () => {\n            electron.app.on('open-file', (event, path) => {\n                this._openPath(path);\n            });\n        });\n\n        electron.app.on('ready', () => {\n            this._ready();\n        });\n\n        electron.app.on('window-all-closed', () => {\n            if (process.platform !== 'darwin') {\n                electron.app.quit();\n            }\n        });\n\n        electron.app.on('will-quit', () => {\n            this._configuration.save();\n        });\n\n        this._parseCommandLine(process.argv);\n        await this._checkForUpdates();\n    }\n\n    get environment() {\n        this._environment = this._environment || {\n            packaged: electron.app.isPackaged,\n            name: this._package.productName,\n            version: this._package.version,\n            date: this._package.date,\n            repository: `https://github.com/${this._package.repository}`,\n            platform: process.platform,\n            separator: path.sep,\n            titlebar: true // process.platform === 'darwin'\n        };\n        return this._environment;\n    }\n\n    _parseCommandLine(argv) {\n        let open = false;\n        if (argv.length > 1) {\n            for (const arg of argv.slice(1)) {\n                const dirname = path.dirname(url.fileURLToPath(import.meta.url));\n                if (!arg.startsWith('-') && arg !== path.dirname(dirname)) {\n                    const extension = path.extname(arg).toLowerCase();\n                    if (extension !== '' && extension !== '.js' && fs.existsSync(arg)) {\n                        const stat = fs.statSync(arg);\n                        if (stat.isFile() || stat.isDirectory()) {\n                            this._openPath(arg);\n                            open = true;\n                        }\n                    }\n                }\n            }\n        }\n        return open;\n    }\n\n    _ready() {\n        this._configuration.open();\n        if (this._openQueue) {\n            const queue = this._openQueue;\n            this._openQueue = null;\n            while (queue.length > 0) {\n                const file = queue.shift();\n                this._openPath(file);\n            }\n        }\n        if (this._views.empty) {\n            this._views.openView();\n        }\n        this._updateMenu();\n        this._views.on('active-view-changed', () => {\n            this._menu.update();\n        });\n        this._views.on('active-view-updated', () => {\n            this._menu.update();\n        });\n    }\n\n    _open(path) {\n        let paths = path ? [path] : [];\n        if (paths.length === 0) {\n            const extensions = new base.Metadata().extensions;\n            const options = {\n                properties: ['openFile'],\n                filters: [{ name: 'All Model Files', extensions }]\n            };\n            const owner = electron.BrowserWindow.getFocusedWindow();\n            paths = electron.dialog.showOpenDialogSync(owner, options);\n        }\n        if (Array.isArray(paths) && paths.length > 0) {\n            for (const path of paths) {\n                this._openPath(path);\n            }\n        }\n    }\n\n    _openPath(path) {\n        if (this._openQueue) {\n            this._openQueue.push(path);\n            return;\n        }\n        if (path && path.length > 0) {\n            const exists = fs.existsSync(path);\n            if (exists) {\n                const stat = fs.statSync(path);\n                if (stat.isFile() || stat.isDirectory()) {\n                    const views = Array.from(this._views.views);\n                    // find existing view for this file\n                    let view = views.find((view) => view.match(path));\n                    // find empty welcome window\n                    if (!view) {\n                        view = views.find((view) => view.match(null));\n                    }\n                    // create new window\n                    if (!view) {\n                        view = this._views.openView();\n                    }\n                    view.open(path);\n                }\n            }\n            this._updateRecents(exists ? path : undefined);\n        }\n    }\n\n    _dropPaths(sender, paths) {\n        const window = sender.getOwnerBrowserWindow();\n        let view = this._views.get(window);\n        for (const path of paths) {\n            if (view) {\n                view.open(path);\n                view = null;\n            } else {\n                this._openPath(path);\n            }\n        }\n    }\n\n    async _export() {\n        const view = this._views.activeView;\n        if (view && view.path) {\n            let defaultPath = 'Untitled';\n            const file = view.path;\n            const lastIndex = file.lastIndexOf('.');\n            if (lastIndex !== -1) {\n                defaultPath = file.substring(0, lastIndex);\n            }\n            const owner = electron.BrowserWindow.getFocusedWindow();\n            const options = {\n                title: 'Export',\n                defaultPath,\n                buttonLabel: 'Export',\n                filters: [\n                    { name: 'PNG', extensions: ['png'] },\n                    { name: 'SVG', extensions: ['svg'] }\n                ]\n            };\n            const { filePath, canceled } = await electron.dialog.showSaveDialog(owner, options);\n            if (filePath && !canceled) {\n                view.execute('export', { 'file': filePath });\n            }\n        }\n    }\n\n    async execute(command, value, window) {\n        switch (command) {\n            case 'open': this._open(value); break;\n            case 'export': await this._export(); break;\n            case 'close': window.close(); break;\n            case 'quit': electron.app.quit(); break;\n            case 'reload': this._reload(); break;\n            case 'report-issue': electron.shell.openExternal(`https://github.com/${this._package.repository}/issues/new`); break;\n            case 'about': this._about(); break;\n            default: {\n                const view = this._views.get(window) || this._views.activeView;\n                if (view && view.get(`${command}.enabled`) !== false) {\n                    view.execute(command, value || {});\n                }\n                this._menu.update();\n            }\n        }\n    }\n\n    _reload() {\n        const view = this._views.activeView;\n        if (view && view.path) {\n            view.open(view.path);\n        }\n    }\n\n    async _checkForUpdates() {\n        if (!electron.app.isPackaged) {\n            return;\n        }\n        const autoUpdater = updater.default.autoUpdater;\n        if (autoUpdater.app && autoUpdater.app.appUpdateConfigPath && !fs.existsSync(autoUpdater.app.appUpdateConfigPath)) {\n            return;\n        }\n        const promise = autoUpdater.checkForUpdates();\n        if (promise) {\n            promise.catch((error) => {\n                /* eslint-disable no-console */\n                console.log(error.message);\n                /* eslint-enable no-console */\n            });\n        }\n    }\n\n    _about() {\n        let view = this._views.activeView;\n        if (!view) {\n            view = this._views.openView();\n        }\n        view.execute('about');\n    }\n\n    _updateRecents(path) {\n        let updated = false;\n        let recents = this._configuration.has('recents') ? this._configuration.get('recents') : [];\n        if (path && (recents.length === 0 || recents[0] !== path)) {\n            recents = recents.filter((recent) => path !== recent);\n            recents.unshift(path);\n            updated = true;\n        }\n        const value = [];\n        for (const recent of recents) {\n            if (value.length >= 9) {\n                updated = true;\n                break;\n            }\n            if (!fs.existsSync(recent)) {\n                updated = true;\n                continue;\n            }\n            const stat = fs.statSync(recent);\n            if (!stat.isFile() && !stat.isDirectory()) {\n                updated = true;\n                continue;\n            }\n            value.push(recent);\n        }\n        if (updated) {\n            this._configuration.set('recents', value);\n            this._updateMenu();\n        }\n    }\n\n    _updateMenu() {\n\n        let recents = [];\n        if (this._configuration.has('recents')) {\n            const value = this._configuration.get('recents');\n            recents = value.map((recent) => app.Application.location(recent));\n        }\n\n        if (this.environment.titlebar && recents.length > 0) {\n            for (const view of this._views.views) {\n                view.execute('recents', recents);\n            }\n        }\n\n        const darwin = process.platform === 'darwin';\n        if (!this.environment.titlebar || darwin) {\n            const menuRecentsTemplate = [];\n            for (let i = 0; i < recents.length; i++) {\n                const recent = recents[i];\n                menuRecentsTemplate.push({\n                    path: recent.path,\n                    label: recent.label,\n                    accelerator: (darwin ? 'Cmd+' : 'Ctrl+') + (i + 1).toString(),\n                    click: (item) => this._openPath(item.path)\n                });\n            }\n\n            const menuTemplate = [];\n\n            if (darwin) {\n                menuTemplate.unshift({\n                    label: electron.app.name,\n                    submenu: [\n                        {\n                            label: `About ${electron.app.name}`,\n                            click: () => /* this.execute('about', null) */ this._about()\n                        },\n                        { type: 'separator' },\n                        { role: 'hide' },\n                        { role: 'hideothers' },\n                        { role: 'unhide' },\n                        { type: 'separator' },\n                        { role: 'quit' }\n                    ]\n                });\n            }\n\n            const fileSubmenu = [\n                {\n                    label: '&Open...',\n                    accelerator: 'CmdOrCtrl+O',\n                    click: () => this._open(null)\n                },\n                {\n                    label: 'Open &Recent',\n                    submenu: menuRecentsTemplate\n                },\n                { type: 'separator' },\n                {\n                    id: 'file.export',\n                    label: '&Export...',\n                    accelerator: 'CmdOrCtrl+Shift+E',\n                    click: async () => await this.execute('export', null)\n                },\n                { type: 'separator' },\n                { role: 'close' },\n            ];\n\n            if (!darwin) {\n                fileSubmenu.push(\n                    { type: 'separator' },\n                    { role: 'quit' }\n                );\n            }\n\n            menuTemplate.push({\n                label: '&File',\n                submenu: fileSubmenu\n            });\n\n            if (darwin) {\n                electron.systemPreferences.setUserDefault('NSDisabledDictationMenuItem', 'boolean', true);\n                electron.systemPreferences.setUserDefault('NSDisabledCharacterPaletteMenuItem', 'boolean', true);\n            }\n\n            menuTemplate.push({\n                label: '&Edit',\n                submenu: [\n                    {\n                        id: 'edit.cut',\n                        label: 'Cu&t',\n                        accelerator: 'CmdOrCtrl+X',\n                        click: async () => await this.execute('cut', null),\n                    },\n                    {\n                        id: 'edit.copy',\n                        label: '&Copy',\n                        accelerator: 'CmdOrCtrl+C',\n                        click: async () => await this.execute('copy', null),\n                    },\n                    {\n                        id: 'edit.paste',\n                        label: '&Paste',\n                        accelerator: 'CmdOrCtrl+V',\n                        click: async () => await this.execute('paste', null),\n                    },\n                    {\n                        id: 'edit.select-all',\n                        label: 'Select &All',\n                        accelerator: 'CmdOrCtrl+A',\n                        click: async () => await this.execute('selectall', null),\n                    },\n                    { type: 'separator' },\n                    {\n                        id: 'edit.find',\n                        label: '&Find...',\n                        accelerator: 'CmdOrCtrl+F',\n                        click: async () => await this.execute('find', null),\n                    }\n                ]\n            });\n\n            const viewTemplate = {\n                label: '&View',\n                submenu: [\n                    {\n                        id: 'view.toggle-attributes',\n                        accelerator: 'CmdOrCtrl+D',\n                        click: async () => await this.execute('toggle', 'attributes'),\n                    },\n                    {\n                        id: 'view.toggle-weights',\n                        accelerator: 'CmdOrCtrl+I',\n                        click: async () => await this.execute('toggle', 'weights'),\n                    },\n                    {\n                        id: 'view.toggle-names',\n                        accelerator: 'CmdOrCtrl+U',\n                        click: async () => await this.execute('toggle', 'names'),\n                    },\n                    {\n                        id: 'view.toggle-direction',\n                        accelerator: 'CmdOrCtrl+K',\n                        click: async () => await this.execute('toggle', 'direction')\n                    },\n                    {\n                        id: 'view.toggle-mousewheel',\n                        accelerator: 'CmdOrCtrl+M',\n                        click: async () => await this.execute('toggle', 'mousewheel'),\n                    },\n                    { type: 'separator' },\n                    {\n                        id: 'view.reload',\n                        label: '&Reload',\n                        accelerator: darwin ? 'Cmd+R' : 'F5',\n                        click: async () => await this._reload(),\n                    },\n                    { type: 'separator' },\n                    {\n                        id: 'view.zoom-reset',\n                        label: 'Actual &Size',\n                        accelerator: 'Shift+Backspace',\n                        click: async () => await this.execute('zoom-reset', null),\n                    },\n                    {\n                        id: 'view.zoom-in',\n                        label: 'Zoom &In',\n                        accelerator: 'Shift+Up',\n                        click: async () => await this.execute('zoom-in', null),\n                    },\n                    {\n                        id: 'view.zoom-out',\n                        label: 'Zoom &Out',\n                        accelerator: 'Shift+Down',\n                        click: async () => await this.execute('zoom-out', null),\n                    },\n                    { type: 'separator' },\n                    {\n                        id: 'view.show-properties',\n                        label: '&Properties...',\n                        accelerator: 'CmdOrCtrl+Enter',\n                        click: async () => await this.execute('show-properties', null),\n                    }\n                ]\n            };\n            if (!electron.app.isPackaged) {\n                viewTemplate.submenu.push({ type: 'separator' });\n                viewTemplate.submenu.push({ role: 'toggledevtools' });\n            }\n            menuTemplate.push(viewTemplate);\n\n            if (darwin) {\n                menuTemplate.push({\n                    role: 'window',\n                    submenu: [\n                        { role: 'minimize' },\n                        { role: 'zoom' },\n                        { type: 'separator' },\n                        { role: 'front' }\n                    ]\n                });\n            }\n\n            const helpSubmenu = [\n                {\n                    label: 'Report &Issue',\n                    click: async () => await this.execute('report-issue', null)\n                }\n            ];\n\n            if (!darwin) {\n                helpSubmenu.push({ type: 'separator' });\n                helpSubmenu.push({\n                    label: `&About ${electron.app.name}`,\n                    click: async () => await this.execute('about', null)\n                });\n            }\n\n            menuTemplate.push({\n                role: 'help',\n                submenu: helpSubmenu\n            });\n\n            const commandTable = new Map();\n            commandTable.set('file.export', {\n                enabled: (view) => view && view.path ? true : false\n            });\n            commandTable.set('edit.cut', {\n                enabled: (view) => view && view.path ? true : false\n            });\n            commandTable.set('edit.copy', {\n                enabled: (view) => view && (view.path || view.get('copy.enabled')) ? true : false\n            });\n            commandTable.set('edit.paste', {\n                enabled: (view) => view && view.path ? true : false\n            });\n            commandTable.set('edit.select-all', {\n                enabled: (view) => view && view.path ? true : false\n            });\n            commandTable.set('edit.find', {\n                enabled: (view) => view && view.path ? true : false\n            });\n            commandTable.set('view.toggle-attributes', {\n                enabled: (view) => view && view.path ? true : false,\n                label: (view) => !view || view.get('attributes') ? 'Hide &Attributes' : 'Show &Attributes'\n            });\n            commandTable.set('view.toggle-weights', {\n                enabled: (view) => view && view.path ? true : false,\n                label: (view) => !view || view.get('weights') ? 'Hide &Weights' : 'Show &Weights'\n            });\n            commandTable.set('view.toggle-names', {\n                enabled: (view) => view && view.path ? true : false,\n                label: (view) => !view || view.get('names') ? 'Hide &Names' : 'Show &Names'\n            });\n            commandTable.set('view.toggle-direction', {\n                enabled: (view) => view && view.path ? true : false,\n                label: (view) => !view || view.get('direction') === 'vertical' ? 'Show &Horizontal' : 'Show &Vertical'\n            });\n            commandTable.set('view.toggle-mousewheel', {\n                enabled: (view) => view && view.path ? true : false,\n                label: (view) => !view || view.get('mousewheel') === 'scroll' ? '&Mouse Wheel: Zoom' : '&Mouse Wheel: Scroll'\n            });\n            commandTable.set('view.reload', {\n                enabled: (view) => view && view.path ? true : false\n            });\n            commandTable.set('view.zoom-reset', {\n                enabled: (view) => view && view.path && view.get('zoom-reset.enabled') ? true : false\n            });\n            commandTable.set('view.zoom-in', {\n                enabled: (view) => view && view.path && view.get('zoom-in.enabled') ? true : false\n            });\n            commandTable.set('view.zoom-out', {\n                enabled: (view) => view && view.path && view.get('zoom-out.enabled') ? true : false\n            });\n            commandTable.set('view.show-properties', {\n                enabled: (view) => view && view.path ? true : false\n            });\n\n            this._menu.build(menuTemplate, commandTable);\n            this._menu.update();\n        }\n    }\n\n    static location(path) {\n        if (process.platform !== 'win32') {\n            const homeDir = os.homedir();\n            if (path.startsWith(homeDir)) {\n                return { path, label: `~${path.substring(homeDir.length)}` };\n            }\n        }\n        return { path, label: path };\n    }\n};\n\napp.View = class {\n\n    constructor(owner) {\n        this._owner = owner;\n        this._ready = false;\n        this._path = null;\n        this._properties = new Map();\n        this._dispatch = [];\n        const dirname = path.dirname(url.fileURLToPath(import.meta.url));\n        const size = electron.screen.getPrimaryDisplay().workAreaSize;\n        const options = {\n            show: false,\n            title: electron.app.name,\n            backgroundColor: electron.nativeTheme.shouldUseDarkColors ? '#1e1e1e' : '#ececec',\n            icon: electron.nativeImage.createFromPath(path.join(dirname, 'icon.png')),\n            minWidth: 600,\n            minHeight: 600,\n            width: size.width > 1024 ? 1024 : size.width,\n            height: size.height > 768 ? 768 : size.height,\n            webPreferences: {\n                preload: path.join(dirname, 'desktop.mjs'),\n                contextIsolation: true,\n                nodeIntegration: true,\n                enableDeprecatedPaste: true\n            }\n        };\n        if (owner.application.environment.titlebar) {\n            options.frame = false;\n            options.thickFrame = true;\n            options.titleBarStyle = 'hiddenInset';\n        }\n        if (!this._owner.empty && app.View._position && app.View._position.length === 2) {\n            options.x = app.View._position[0] + 30;\n            options.y = app.View._position[1] + 30;\n            if (options.x + options.width > size.width) {\n                options.x = 0;\n            }\n            if (options.y + options.height > size.height) {\n                options.y = 0;\n            }\n        }\n        this._window = new electron.BrowserWindow(options);\n        app.View._position = this._window.getPosition();\n        this._window.on('close', () => this._owner.closeView(this));\n        this._window.on('focus', () => this.emit('activated'));\n        this._window.on('blur', () => this.emit('deactivated'));\n        this._window.on('minimize', () => this.state());\n        this._window.on('restore', () => this.state());\n        this._window.on('maximize', () => this.state());\n        this._window.on('unmaximize', () => this.state());\n        this._window.on('enter-full-screen', () => this.state('enter-full-screen'));\n        this._window.on('leave-full-screen', () => this.state('leave-full-screen'));\n        this._window.webContents.once('did-finish-load', () => {\n            this._didFinishLoad = true;\n        });\n        this._window.webContents.setWindowOpenHandler((detail) => {\n            const url = detail.url;\n            if (url.startsWith('http://') || url.startsWith('https://')) {\n                electron.shell.openExternal(url);\n            }\n            return { action: 'deny' };\n        });\n        this._window.once('ready-to-show', () => {\n            this._window.show();\n        });\n        if (owner.application.environment.titlebar && process.platform !== 'darwin') {\n            this._window.removeMenu();\n        }\n        const pathname = path.join(dirname, 'index.html');\n        let content = fs.readFileSync(pathname, 'utf-8');\n        content = content.replace(/<\\s*script[^>]*>[\\s\\S]*?(<\\s*\\/script[^>]*>|$)/ig, '');\n        const data = `data:text/html;charset=utf-8,${encodeURIComponent(content)}`;\n        this._window.loadURL(data, {\n            baseURLForDataURL: url.pathToFileURL(pathname).toString()\n        });\n    }\n\n    get window() {\n        return this._window;\n    }\n\n    get path() {\n        return this._path;\n    }\n\n    async open(path) {\n        this._openPath = path;\n        const location = app.Application.location(path);\n        await new Promise((resolve) => {\n            if (this._didFinishLoad) {\n                resolve();\n            } else {\n                this._window.webContents.once('did-finish-load', resolve);\n            }\n        });\n        await new Promise((resolve) => {\n            if (this._window.isVisible()) {\n                resolve();\n            } else {\n                this._window.once('ready-to-show', resolve);\n            }\n        });\n        this._window.webContents.send('open', location);\n    }\n\n    restore() {\n        if (this._window) {\n            if (this._window.isMinimized()) {\n                this._window.restore();\n            }\n            this._window.show();\n        }\n    }\n\n    match(path) {\n        if (this._openPath) {\n            return this._openPath === path;\n        }\n        return this._path === path;\n    }\n\n    execute(command, data) {\n        if (this._dispatch) {\n            this._dispatch.push({ command, data });\n        } else if (this._window && this._window.webContents) {\n            const window = this._window;\n            const contents = window.webContents;\n            switch (command) {\n                case 'toggle-developer-tools':\n                    if (contents.isDevToolsOpened()) {\n                        contents.closeDevTools();\n                    } else {\n                        contents.openDevTools();\n                    }\n                    break;\n                case 'fullscreen':\n                    window.setFullScreen(!window.isFullScreen());\n                    break;\n                default:\n                    contents.send(command, data);\n                    break;\n            }\n        }\n    }\n\n    update(data) {\n        for (const [name, value] of Object.entries(data)) {\n            switch (name) {\n                case 'path': {\n                    if (value) {\n                        this._path = value;\n                        const location = app.Application.location(this._path);\n                        const title = process.platform === 'darwin' ? location.label : `${location.label} - ${electron.app.name}`;\n                        this._window.setTitle(title);\n                        this._window.focus();\n                    }\n                    delete this._openPath;\n                    break;\n                }\n                default: {\n                    this._properties.set(name, value);\n                }\n            }\n        }\n        this.emit('updated');\n    }\n\n    get(name) {\n        return this._properties.get(name);\n    }\n\n    on(event, callback) {\n        this._events = this._events || {};\n        this._events[event] = this._events[event] || [];\n        this._events[event].push(callback);\n    }\n\n    emit(event, data) {\n        if (this._events && this._events[event]) {\n            for (const callback of this._events[event]) {\n                callback(this, data);\n            }\n        }\n    }\n\n    state(event) {\n        let fullscreen = false;\n        switch (event) {\n            case 'enter-full-screen': fullscreen = true; break;\n            case 'leave-full-screen': fullscreen = false; break;\n            default: fullscreen = this._window.isFullScreen(); break;\n        }\n        this.execute('window-state', {\n            minimized: this._window.isMinimized(),\n            maximized: this._window.isMaximized(),\n            fullscreen\n        });\n        if (this._dispatch) {\n            const dispatch = this._dispatch;\n            delete this._dispatch;\n            for (const obj of dispatch) {\n                this.execute(obj.command, obj.data);\n            }\n        }\n    }\n};\n\napp.ViewCollection = class {\n\n    constructor(application) {\n        this._application = application;\n        this._views = new Map();\n        electron.ipcMain.on('window-close', (event) => {\n            const window = event.sender.getOwnerBrowserWindow();\n            window.close();\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('window-toggle', (event) => {\n            const window = event.sender.getOwnerBrowserWindow();\n            if (window.isFullScreen()) {\n                window.setFullScreen(false);\n            } else if (window.isMaximized()) {\n                window.unmaximize();\n            } else {\n                window.maximize();\n            }\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('window-minimize', (event) => {\n            const window = event.sender.getOwnerBrowserWindow();\n            window.minimize();\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('window-update', (event, data) => {\n            const window = event.sender.getOwnerBrowserWindow();\n            if (this._views.has(window)) {\n                const view = this._views.get(window);\n                view.update(data);\n            }\n            event.returnValue = null;\n        });\n        electron.ipcMain.on('update-window-state', (event) => {\n            const window = event.sender.getOwnerBrowserWindow();\n            if (this._views.has(window)) {\n                this._views.get(window).state();\n            }\n            event.returnValue = null;\n        });\n    }\n\n    get application() {\n        return this._application;\n    }\n\n    get views() {\n        return this._views.values();\n    }\n\n    get empty() {\n        return this._views.size === 0;\n    }\n\n    get(window) {\n        return this._views.get(window);\n    }\n\n    openView() {\n        const view = new app.View(this);\n        view.on('activated', (view) => {\n            this._activeView = view;\n            this.emit('active-view-changed', { activeView: this._activeView });\n        });\n        view.on('updated', () => {\n            this.emit('active-view-updated', { activeView: this._activeView });\n        });\n        view.on('deactivated', () => {\n            this._activeView = null;\n            this.emit('active-view-changed', { activeView: this._activeView });\n        });\n        this._views.set(view.window, view);\n        this._updateActiveView();\n        return view;\n    }\n\n    closeView(view) {\n        this._views.delete(view.window);\n        this._updateActiveView();\n    }\n\n    first() {\n        return this.empty ? null : this._views.values().next().value;\n    }\n\n    get activeView() {\n        return this._activeView;\n    }\n\n    on(event, callback) {\n        this._events = this._events || {};\n        this._events[event] = this._events[event] || [];\n        this._events[event].push(callback);\n    }\n\n    emit(event, data) {\n        if (this._events && this._events[event]) {\n            for (const callback of this._events[event]) {\n                callback(this, data);\n            }\n        }\n    }\n\n    _updateActiveView() {\n        const window = electron.BrowserWindow.getFocusedWindow();\n        const view = window && this._views.has(window) ? this._views.get(window) : null;\n        if (view !== this._activeView) {\n            this._activeView = view;\n            this.emit('active-view-changed', { activeView: this._activeView });\n        }\n    }\n};\n\napp.ConfigurationService = class {\n\n    constructor() {\n        this._content = { 'recents': [] };\n        const dir = electron.app.getPath('userData');\n        if (dir && dir.length > 0) {\n            this._file = path.join(dir, 'configuration.json');\n        }\n    }\n\n    open() {\n        if (this._file && fs.existsSync(this._file)) {\n            const data = fs.readFileSync(this._file, 'utf-8');\n            if (data) {\n                try {\n                    const content = JSON.parse(data);\n                    if (Array.isArray(content.recents)) {\n                        content.recents = content.recents.map((recent) => typeof recent !== 'string' && recent && recent.path ? recent.path : recent);\n                    }\n                    this._content = content;\n                } catch {\n                    // Silently ignore parsing errors and use empty config\n                }\n            }\n        }\n    }\n\n    save() {\n        if (this._content && this._file) {\n            const data = JSON.stringify(this._content, null, 2);\n            fs.writeFileSync(this._file, data);\n        }\n    }\n\n    has(name) {\n        return this._content && Object.prototype.hasOwnProperty.call(this._content, name);\n    }\n\n    set(name, value) {\n        this._content[name] = value;\n    }\n\n    get(name) {\n        return this._content[name];\n    }\n\n    delete(name) {\n        delete this._content[name];\n    }\n};\n\napp.MenuService = class {\n\n    constructor(views) {\n        this._views = views;\n    }\n\n    build(menuTemplate, commandTable) {\n        this._menuTemplate = menuTemplate;\n        this._commandTable = commandTable;\n        this._itemTable = new Map();\n        for (const menu of menuTemplate) {\n            for (const item of menu.submenu) {\n                if (item.id) {\n                    if (!item.label) {\n                        item.label = '';\n                    }\n                    this._itemTable.set(item.id, item);\n                }\n            }\n        }\n        this._rebuild();\n    }\n\n    update() {\n        if (!this._menu && !this._commandTable) {\n            return;\n        }\n        const view = this._views.activeView;\n        if (this._updateLabel(view)) {\n            this._rebuild();\n        }\n        this._updateEnabled(view);\n    }\n\n    _rebuild() {\n        if (process.platform === 'darwin') {\n            this._menu = electron.Menu.buildFromTemplate(this._menuTemplate);\n            electron.Menu.setApplicationMenu(this._menu);\n        } else if (!this._views.application.environment.titlebar) {\n            this._menu = electron.Menu.buildFromTemplate(this._menuTemplate);\n            for (const view of this._views.views) {\n                view.window.setMenu(this._menu);\n            }\n        }\n    }\n\n    _updateLabel(view) {\n        let rebuild = false;\n        for (const [name, command] of this._commandTable.entries()) {\n            if (this._menu) {\n                const item = this._menu.getMenuItemById(name);\n                if (command && command.label) {\n                    const label = command.label(view);\n                    if (label !== item.label) {\n                        if (this._itemTable.has(name)) {\n                            this._itemTable.get(name).label = label;\n                            rebuild = true;\n                        }\n                    }\n                }\n            }\n        }\n        return rebuild;\n    }\n\n    _updateEnabled(view) {\n        for (const [name, command] of this._commandTable.entries()) {\n            if (this._menu) {\n                const item = this._menu.getMenuItemById(name);\n                if (item && command.enabled) {\n                    item.enabled = command.enabled(view);\n                }\n            }\n        }\n    }\n};\n\ntry {\n    global.application = new app.Application();\n    await global.application.start();\n} catch (error) {\n    /* eslint-disable no-console */\n    console.error(error.message);\n    /* eslint-enable no-console */\n}\n"
  },
  {
    "path": "source/armnn-metadata.json",
    "content": "[\n  {\n    \"name\": \"ActivationLayer\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"activationFunction\", \"type\": \"ActivationFunction\" },\n      { \"name\": \"a\", \"type\": \"float32\" },\n      { \"name\": \"b\", \"type\": \"float32\" }\n    ]\n  },\n  {\n    \"name\": \"AdditionLayer\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormalizationLayer\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"float32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"gamma\" }\n    ]\n  },\n  {\n    \"name\": \"BatchToSpaceNdLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"blockShape\", \"type\": \"string\" },\n      { \"name\": \"crops\", \"type\": \"string\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"ConcatLayer\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"concatAxis\", \"type\": \"uint32\" },\n      { \"name\": \"numViews\", \"type\": \"uint32\" },\n      { \"name\": \"numDimensions\", \"type\": \"uint32\" }\n    ]\n  },\n  {\n    \"name\": \"ConstantLayer\",\n    \"category\": \"Constant\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution2dLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padTop\", \"type\": \"uint32\" },\n      { \"name\": \"padRight\", \"type\": \"uint32\" },\n      { \"name\": \"padBottom\", \"type\": \"uint32\" },\n      { \"name\": \"padLeft\", \"type\": \"uint32\" },\n      { \"name\": \"strideX\", \"type\": \"uint32\" },\n      { \"name\": \"strideY\", \"type\": \"uint32\" },\n      { \"name\": \"dilationX\", \"type\": \"uint32\" },\n      { \"name\": \"dilationY\", \"type\": \"uint32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"DepthwiseConvolution2dLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padTop\", \"type\": \"uint32\" },\n      { \"name\": \"padRight\", \"type\": \"uint32\" },\n      { \"name\": \"padBottom\", \"type\": \"uint32\" },\n      { \"name\": \"padLeft\", \"type\": \"uint32\" },\n      { \"name\": \"strideX\", \"type\": \"uint32\" },\n      { \"name\": \"strideY\", \"type\": \"uint32\" },\n      { \"name\": \"dilationX\", \"type\": \"uint32\" },\n      { \"name\": \"dilationY\", \"type\": \"uint32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"DequantizeLayer\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"DetectionPostProcessLayer\",\n    \"attributes\": [\n      { \"name\": \"maxDetections\", \"type\": \"uint32\" },\n      { \"name\": \"maxClassesPerDetection\", \"type\": \"uint32\" },\n      { \"name\": \"detectionsPerClass\", \"type\": \"uint32\" },\n      { \"name\": \"nmsScoreThreshold\", \"type\": \"float32\" },\n      { \"name\": \"numIouThreshold\", \"type\": \"float32\" },\n      { \"name\": \"numClasses\", \"type\": \"uint32\" },\n      { \"name\": \"useRegularNms\", \"type\": \"boolean\" },\n      { \"name\": \"scaleX\", \"type\": \"float32\" },\n      { \"name\": \"scaleY\", \"type\": \"float32\" },\n      { \"name\": \"scaleW\", \"type\": \"float32\" },\n      { \"name\": \"scaleH\", \"type\": \"float32\" }\n    ]\n  },\n  {\n    \"name\": \"DivisionLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"EqualLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"FloorLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"FullyConnectedLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"transposeWeightsMatrix\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"GatherLayer\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"GreaterLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"InputLayer\"\n  },\n  {\n    \"name\": \"L2NormalizationLayer\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"float32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"LstmLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"activationFunc\", \"type\": \"uint32\" },\n      { \"name\": \"clippingThresCell\", \"type\": \"float32\" },\n      { \"name\": \"clippingThresProj\", \"type\": \"float32\" },\n      { \"name\": \"cifgEnabled\", \"type\": \"boolean\" },\n      { \"name\": \"peepholeEnabled\", \"type\": \"boolean\" },\n      { \"name\": \"projectionEnabled\", \"type\": \"boolean\" },\n      { \"name\": \"layerNormEnabled\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"inputToForgetWeights1\" },\n      { \"name\": \"inputToCellWeights1\" },\n      { \"name\": \"inputToOutputWeights1\" },\n      { \"name\": \"recurrentToForgetWeights1\" },\n      { \"name\": \"recurrentToCellWeights1\" },\n      { \"name\": \"recurrentToOutputWeights1\" },\n      { \"name\": \"forgetGateBias1\" },\n      { \"name\": \"cellBias1\" },\n      { \"name\": \"outputGateBias1\" },\n      { \"name\": \"inputToInputWeights1\" },\n      { \"name\": \"recurrentToInputWeights1\" },\n      { \"name\": \"cellToInputWeights1\" },\n      { \"name\": \"inputGateBias1\" },\n      { \"name\": \"projectionWeights1\" },\n      { \"name\": \"projectionBias1\" },\n      { \"name\": \"cellToForgetWeights1\" },\n      { \"name\": \"cellToOutputWeights1\" },\n      { \"name\": \"inputLayerNormWeights1\" },\n      { \"name\": \"forgetLayerNormWeights1\" },\n      { \"name\": \"cellLayerNormWeights1\" },\n      { \"name\": \"outputLayerNormWeights1\" }\n    ]\n  },\n  {\n    \"name\": \"MaximumLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"MeanLayer\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"uint32\" },\n      { \"name\": \"keepDims\", \"type\": \"boolean\" }\n    ]\n  },\n  {\n    \"name\": \"MergeLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"MergerLayer\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"MinimumLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"MultiplicationLayer\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"NormalizationLayer\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"normChannelType\", \"type\": \"NormalizationAlgorithmChannel\" },\n      { \"name\": \"normMethodType\", \"type\": \"NormalizationAlgorithmMethod\" },\n      { \"name\": \"normSize\", \"type\": \"uint32\" },\n      { \"name\": \"alpha\", \"type\": \"float32\" },\n      { \"name\": \"beta\", \"type\": \"float32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"OutputLayer\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"PadLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padList\", \"type\": \"uint32\" },\n      { \"name\": \"padValue\", \"type\": \"float32\" }\n    ]\n  },\n  {\n    \"name\": \"PermuteLayer\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"dimMappings\", \"type\": \"string\" }\n    ]\n  },\n  {\n    \"name\": \"Pooling2dLayer\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"poolType\", \"type\": \"PoolingAlgorithm\" },\n      { \"name\": \"padTop\", \"type\": \"uint32\" },\n      { \"name\": \"padRight\", \"type\": \"uint32\" },\n      { \"name\": \"padBottom\", \"type\": \"uint32\" },\n      { \"name\": \"padLeft\", \"type\": \"uint32\" },\n      { \"name\": \"poolWidth\", \"type\": \"uint32\" },\n      { \"name\": \"poolHeight\", \"type\": \"uint32\" },\n      { \"name\": \"strideX\", \"type\": \"uint32\" },\n      { \"name\": \"strideY\", \"type\": \"uint32\" },\n      { \"name\": \"outputShapeRounding\", \"type\": \"OutputShapeRounding\" },\n      { \"name\": \"paddingMethod\", \"type\": \"PaddingMethod\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"PreluLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"QuantizedLstmLayer\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"inputToInputWeights1\" },\n      { \"name\": \"inputToForgetWeights1\" },\n      { \"name\": \"inputToCellWeights1\" },\n      { \"name\": \"inputToOutputWeights1\" },\n      { \"name\": \"recurrentToInputWeights1\" },\n      { \"name\": \"recurrentToForgetWeights1\" },\n      { \"name\": \"recurrentToCellWeights1\" },\n      { \"name\": \"recurrentToOutputWeights1\" },\n      { \"name\": \"inputGateBias1\" },\n      { \"name\": \"forgetGateBias1\" },\n      { \"name\": \"cellBias1\" },\n      { \"name\": \"outputGateBias1\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizeLayer\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"ReshapeLayer\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"targetShape\", \"type\": \"uint32[]\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeBilinearLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"targetWidth\", \"type\": \"uint32\" },\n      { \"name\": \"targetHeight\", \"type\": \"uint32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"targetWidth\", \"type\": \"uint32\" },\n      { \"name\": \"targetHeight\", \"type\": \"uint32\" },\n      { \"name\": \"method\", \"type\": \"ResizeMethod\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"RsqrtLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"SoftmaxLayer\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"beta\", \"type\": \"float32\" }\n    ]\n  },\n  {\n    \"name\": \"SpaceToBatchNdLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"blockShape\", \"type\": \"string\" },\n      { \"name\": \"padList\", \"type\": \"string\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"SpaceToDepthLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"blockSize\", \"type\": \"uint32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"SplitterLayer\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"concatAxis\", \"type\": \"uint32\" },\n      { \"name\": \"numViews\", \"type\": \"uint32\" },\n      { \"name\": \"numDimensions\", \"type\": \"uint32\" }\n    ]\n  },\n  {\n    \"name\": \"StackLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"uint32\" },\n      { \"name\": \"numInputs\", \"type\": \"uint32\" },\n      { \"name\": \"inputShape\", \"type\": \"uint32\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSliceLayer\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"begin\", \"type\": \"int32\" },\n      { \"name\": \"end\", \"type\": \"int32\" },\n      { \"name\": \"stride\", \"type\": \"int32\" },\n      { \"name\": \"beginMask\", \"type\": \"int32\" },\n      { \"name\": \"endMask\", \"type\": \"int32\" },\n      { \"name\": \"shrinkAxisMask\", \"type\": \"int32\" },\n      { \"name\": \"ellipsisMask\", \"type\": \"int32\" },\n      { \"name\": \"newAxisMask\", \"type\": \"int32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ]\n  },\n  {\n    \"name\": \"SubtractionLayer\"\n  },\n  {\n    \"name\": \"SwitchLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"TransposeConvolution2dLayer\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padTop\", \"type\": \"uint32\" },\n      { \"name\": \"padRight\", \"type\": \"uint32\" },\n      { \"name\": \"padBottom\", \"type\": \"uint32\" },\n      { \"name\": \"padLeft\", \"type\": \"uint32\" },\n      { \"name\": \"strideX\", \"type\": \"uint32\" },\n      { \"name\": \"strideY\", \"type\": \"uint32\" },\n      { \"name\": \"dataLayout\", \"type\": \"DataLayout\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/armnn-schema.js",
    "content": "\nexport const armnnSerializer = {};\n\narmnnSerializer.ActivationFunction = {\n    Sigmoid: 0, '0': 'Sigmoid',\n    TanH: 1, '1': 'TanH',\n    Linear: 2, '2': 'Linear',\n    ReLu: 3, '3': 'ReLu',\n    BoundedReLu: 4, '4': 'BoundedReLu',\n    SoftReLu: 5, '5': 'SoftReLu',\n    LeakyReLu: 6, '6': 'LeakyReLu',\n    Abs: 7, '7': 'Abs',\n    Sqrt: 8, '8': 'Sqrt',\n    Square: 9, '9': 'Square',\n    Elu: 10, '10': 'Elu',\n    HardSwish: 11, '11': 'HardSwish',\n    Gelu: 12, '12': 'Gelu'\n};\n\narmnnSerializer.ArgMinMaxFunction = {\n    Min: 0, '0': 'Min',\n    Max: 1, '1': 'Max'\n};\n\narmnnSerializer.DataType = {\n    Float16: 0, '0': 'Float16',\n    Float32: 1, '1': 'Float32',\n    QuantisedAsymm8: 2, '2': 'QuantisedAsymm8',\n    Signed32: 3, '3': 'Signed32',\n    Boolean: 4, '4': 'Boolean',\n    QuantisedSymm16: 5, '5': 'QuantisedSymm16',\n    QAsymmU8: 6, '6': 'QAsymmU8',\n    QSymmS16: 7, '7': 'QSymmS16',\n    QAsymmS8: 8, '8': 'QAsymmS8',\n    QSymmS8: 9, '9': 'QSymmS8',\n    Signed64: 10, '10': 'Signed64'\n};\n\narmnnSerializer.DataLayout = {\n    NHWC: 0, '0': 'NHWC',\n    NCHW: 1, '1': 'NCHW',\n    NDHWC: 2, '2': 'NDHWC',\n    NCDHW: 3, '3': 'NCDHW'\n};\n\narmnnSerializer.ReduceOperation = {\n    Sum: 0, '0': 'Sum',\n    Max: 1, '1': 'Max',\n    Mean: 2, '2': 'Mean',\n    Min: 3, '3': 'Min',\n    Prod: 4, '4': 'Prod'\n};\n\narmnnSerializer.ResizeMethod = {\n    NearestNeighbor: 0, '0': 'NearestNeighbor',\n    Bilinear: 1, '1': 'Bilinear'\n};\n\narmnnSerializer.ScatterNdFunction = {\n    Update: 0, '0': 'Update',\n    Add: 1, '1': 'Add',\n    Sub: 2, '2': 'Sub',\n    Max: 3, '3': 'Max',\n    Min: 4, '4': 'Min'\n};\n\narmnnSerializer.TensorInfo = class TensorInfo {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TensorInfo();\n        $.dimensions = reader.array(position, 4, Uint32Array);\n        $.dataType = reader.int8_(position, 6, 0);\n        $.quantizationScale = reader.float32_(position, 8, 1);\n        $.quantizationOffset = reader.int32_(position, 10, 0);\n        $.quantizationScales = reader.array(position, 12, Float32Array);\n        $.quantizationDim = reader.uint32_(position, 14, 0);\n        $.dimensionality = reader.uint32_(position, 16, 1);\n        $.dimensionSpecificity = reader.bools_(position, 18);\n        $.isConstant = reader.bool_(position, 20, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TensorInfo();\n        $.dimensions = reader.array(json.dimensions, Uint32Array);\n        $.dataType = armnnSerializer.DataType[json.dataType];\n        $.quantizationScale = reader.value(json.quantizationScale, 1);\n        $.quantizationOffset = reader.value(json.quantizationOffset, 0);\n        $.quantizationScales = reader.array(json.quantizationScales, Float32Array);\n        $.quantizationDim = reader.value(json.quantizationDim, 0);\n        $.dimensionality = reader.value(json.dimensionality, 1);\n        $.dimensionSpecificity = reader.array(json.dimensionSpecificity);\n        $.isConstant = reader.value(json.isConstant, false);\n        return $;\n    }\n};\n\narmnnSerializer.Connection = class Connection {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Connection();\n        $.sourceLayerIndex = reader.uint32(position + 0);\n        $.outputSlotIndex = reader.uint32(position + 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Connection();\n        $.sourceLayerIndex = json.sourceLayerIndex;\n        $.outputSlotIndex = json.outputSlotIndex;\n        return $;\n    }\n};\n\narmnnSerializer.ByteData = class ByteData {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ByteData();\n        $.data = reader.array(position, 4, Int8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ByteData();\n        $.data = reader.array(json.data, Int8Array);\n        return $;\n    }\n};\n\narmnnSerializer.ShortData = class ShortData {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ShortData();\n        $.data = reader.array(position, 4, Int16Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ShortData();\n        $.data = reader.array(json.data, Int16Array);\n        return $;\n    }\n};\n\narmnnSerializer.IntData = class IntData {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.IntData();\n        $.data = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.IntData();\n        $.data = reader.array(json.data, Int32Array);\n        return $;\n    }\n};\n\narmnnSerializer.LongData = class LongData {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LongData();\n        $.data = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LongData();\n        $.data = reader.array(json.data);\n        return $;\n    }\n};\n\narmnnSerializer.ConstTensorData = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return armnnSerializer.ByteData.decode(reader, position);\n            case 2: return armnnSerializer.ShortData.decode(reader, position);\n            case 3: return armnnSerializer.IntData.decode(reader, position);\n            case 4: return armnnSerializer.LongData.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'ByteData': return armnnSerializer.ByteData.decodeText(reader, json);\n            case 'ShortData': return armnnSerializer.ShortData.decodeText(reader, json);\n            case 'IntData': return armnnSerializer.IntData.decodeText(reader, json);\n            case 'LongData': return armnnSerializer.LongData.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\narmnnSerializer.ConstTensor = class ConstTensor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ConstTensor();\n        $.info = reader.table(position, 4, armnnSerializer.TensorInfo);\n        $.data = reader.union(position, 6, armnnSerializer.ConstTensorData);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ConstTensor();\n        $.info = reader.object(json.info, armnnSerializer.TensorInfo);\n        $.data = armnnSerializer.ConstTensorData.decodeText(reader, json.data, json.data_type);\n        return $;\n    }\n};\n\narmnnSerializer.InputSlot = class InputSlot {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.InputSlot();\n        $.index = reader.uint32_(position, 4, 0);\n        $.connection = reader.struct(position, 6, armnnSerializer.Connection);\n        $.isOverridden = reader.bool_(position, 8, false);\n        $.overriddenTensorInfo = reader.table(position, 10, armnnSerializer.TensorInfo);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.InputSlot();\n        $.index = reader.value(json.index, 0);\n        $.connection = reader.object(json.connection, armnnSerializer.Connection);\n        $.isOverridden = reader.value(json.isOverridden, false);\n        $.overriddenTensorInfo = reader.object(json.overriddenTensorInfo, armnnSerializer.TensorInfo);\n        return $;\n    }\n};\n\narmnnSerializer.OutputSlot = class OutputSlot {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.OutputSlot();\n        $.index = reader.uint32_(position, 4, 0);\n        $.tensorInfo = reader.table(position, 6, armnnSerializer.TensorInfo);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.OutputSlot();\n        $.index = reader.value(json.index, 0);\n        $.tensorInfo = reader.object(json.tensorInfo, armnnSerializer.TensorInfo);\n        return $;\n    }\n};\n\narmnnSerializer.LayerType = {\n    Addition: 0, '0': 'Addition',\n    Input: 1, '1': 'Input',\n    Multiplication: 2, '2': 'Multiplication',\n    Output: 3, '3': 'Output',\n    Pooling2d: 4, '4': 'Pooling2d',\n    Reshape: 5, '5': 'Reshape',\n    Softmax: 6, '6': 'Softmax',\n    Convolution2d: 7, '7': 'Convolution2d',\n    DepthwiseConvolution2d: 8, '8': 'DepthwiseConvolution2d',\n    Activation: 9, '9': 'Activation',\n    Permute: 10, '10': 'Permute',\n    FullyConnected: 11, '11': 'FullyConnected',\n    Constant: 12, '12': 'Constant',\n    SpaceToBatchNd: 13, '13': 'SpaceToBatchNd',\n    BatchToSpaceNd: 14, '14': 'BatchToSpaceNd',\n    Division: 15, '15': 'Division',\n    Minimum: 16, '16': 'Minimum',\n    Equal: 17, '17': 'Equal',\n    Maximum: 18, '18': 'Maximum',\n    Normalization: 19, '19': 'Normalization',\n    Pad: 20, '20': 'Pad',\n    Rsqrt: 21, '21': 'Rsqrt',\n    Floor: 22, '22': 'Floor',\n    BatchNormalization: 23, '23': 'BatchNormalization',\n    Greater: 24, '24': 'Greater',\n    ResizeBilinear: 25, '25': 'ResizeBilinear',\n    Subtraction: 26, '26': 'Subtraction',\n    StridedSlice: 27, '27': 'StridedSlice',\n    Gather: 28, '28': 'Gather',\n    Mean: 29, '29': 'Mean',\n    Merger: 30, '30': 'Merger',\n    L2Normalization: 31, '31': 'L2Normalization',\n    Splitter: 32, '32': 'Splitter',\n    DetectionPostProcess: 33, '33': 'DetectionPostProcess',\n    Lstm: 34, '34': 'Lstm',\n    Quantize: 35, '35': 'Quantize',\n    Dequantize: 36, '36': 'Dequantize',\n    Merge: 37, '37': 'Merge',\n    Switch: 38, '38': 'Switch',\n    Concat: 39, '39': 'Concat',\n    SpaceToDepth: 40, '40': 'SpaceToDepth',\n    Prelu: 41, '41': 'Prelu',\n    TransposeConvolution2d: 42, '42': 'TransposeConvolution2d',\n    Resize: 43, '43': 'Resize',\n    Stack: 44, '44': 'Stack',\n    QuantizedLstm: 45, '45': 'QuantizedLstm',\n    Abs: 46, '46': 'Abs',\n    ArgMinMax: 47, '47': 'ArgMinMax',\n    Slice: 48, '48': 'Slice',\n    DepthToSpace: 49, '49': 'DepthToSpace',\n    InstanceNormalization: 50, '50': 'InstanceNormalization',\n    LogSoftmax: 51, '51': 'LogSoftmax',\n    Comparison: 52, '52': 'Comparison',\n    StandIn: 53, '53': 'StandIn',\n    ElementwiseUnary: 54, '54': 'ElementwiseUnary',\n    Transpose: 55, '55': 'Transpose',\n    QLstm: 56, '56': 'QLstm',\n    Fill: 57, '57': 'Fill',\n    Rank: 58, '58': 'Rank',\n    LogicalBinary: 59, '59': 'LogicalBinary',\n    Reduce: 60, '60': 'Reduce',\n    Cast: 61, '61': 'Cast',\n    Shape: 62, '62': 'Shape',\n    UnidirectionalSequenceLstm: 63, '63': 'UnidirectionalSequenceLstm',\n    ChannelShuffle: 64, '64': 'ChannelShuffle',\n    Convolution3d: 65, '65': 'Convolution3d',\n    Pooling3d: 66, '66': 'Pooling3d',\n    GatherNd: 67, '67': 'GatherNd',\n    BatchMatMul: 68, '68': 'BatchMatMul',\n    ElementwiseBinary: 69, '69': 'ElementwiseBinary',\n    ReverseV2: 70, '70': 'ReverseV2',\n    Tile: 71, '71': 'Tile',\n    ScatterNd: 72, '72': 'ScatterNd'\n};\n\narmnnSerializer.LayerBase = class LayerBase {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LayerBase();\n        $.index = reader.uint32_(position, 4, 0);\n        $.layerName = reader.string_(position, 6, null);\n        $.layerType = reader.uint32_(position, 8, 0);\n        $.inputSlots = reader.tables(position, 10, armnnSerializer.InputSlot);\n        $.outputSlots = reader.tables(position, 12, armnnSerializer.OutputSlot);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LayerBase();\n        $.index = reader.value(json.index, 0);\n        $.layerName = reader.value(json.layerName, null);\n        $.layerType = armnnSerializer.LayerType[json.layerType];\n        $.inputSlots = reader.objects(json.inputSlots, armnnSerializer.InputSlot);\n        $.outputSlots = reader.objects(json.outputSlots, armnnSerializer.OutputSlot);\n        return $;\n    }\n};\n\narmnnSerializer.BindableLayerBase = class BindableLayerBase {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BindableLayerBase();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.layerBindingId = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BindableLayerBase();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.layerBindingId = reader.value(json.layerBindingId, 0);\n        return $;\n    }\n};\n\narmnnSerializer.AbsLayer = class AbsLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.AbsLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.AbsLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.ActivationLayer = class ActivationLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ActivationLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ActivationDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ActivationLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ActivationDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ActivationDescriptor = class ActivationDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ActivationDescriptor();\n        $.activationFunction = reader.int8_(position, 4, 0);\n        $.a = reader.float32_(position, 6, 0);\n        $.b = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ActivationDescriptor();\n        $.activationFunction = armnnSerializer.ActivationFunction[json.activationFunction];\n        $.a = reader.value(json.a, 0);\n        $.b = reader.value(json.b, 0);\n        return $;\n    }\n};\n\narmnnSerializer.AdditionLayer = class AdditionLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.AdditionLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.AdditionLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.ArgMinMaxLayer = class ArgMinMaxLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ArgMinMaxLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ArgMinMaxDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ArgMinMaxLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ArgMinMaxDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ArgMinMaxDescriptor = class ArgMinMaxDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ArgMinMaxDescriptor();\n        $.argMinMaxFunction = reader.int8_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ArgMinMaxDescriptor();\n        $.argMinMaxFunction = armnnSerializer.ArgMinMaxFunction[json.argMinMaxFunction];\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\narmnnSerializer.CastLayer = class CastLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.CastLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.CastLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.ChannelShuffleLayer = class ChannelShuffleLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ChannelShuffleLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ChannelShuffleDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ChannelShuffleLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ChannelShuffleDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ChannelShuffleDescriptor = class ChannelShuffleDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ChannelShuffleDescriptor();\n        $.axis = reader.uint32_(position, 4, 0);\n        $.numGroups = reader.uint32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ChannelShuffleDescriptor();\n        $.axis = reader.value(json.axis, 0);\n        $.numGroups = reader.value(json.numGroups, 0);\n        return $;\n    }\n};\n\narmnnSerializer.ComparisonOperation = {\n    Equal: 0, '0': 'Equal',\n    Greater: 1, '1': 'Greater',\n    GreaterOrEqual: 2, '2': 'GreaterOrEqual',\n    Less: 3, '3': 'Less',\n    LessOrEqual: 4, '4': 'LessOrEqual',\n    NotEqual: 5, '5': 'NotEqual'\n};\n\narmnnSerializer.ComparisonDescriptor = class ComparisonDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ComparisonDescriptor();\n        $.operation = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ComparisonDescriptor();\n        $.operation = armnnSerializer.ComparisonOperation[json.operation];\n        return $;\n    }\n};\n\narmnnSerializer.ComparisonLayer = class ComparisonLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ComparisonLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ComparisonDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ComparisonLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ComparisonDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ConstantLayer = class ConstantLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ConstantLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.input = reader.table(position, 6, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ConstantLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.input = reader.object(json.input, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.Convolution2dLayer = class Convolution2dLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Convolution2dLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.Convolution2dDescriptor);\n        $.weights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.biases = reader.table(position, 10, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Convolution2dLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.Convolution2dDescriptor);\n        $.weights = reader.object(json.weights, armnnSerializer.ConstTensor);\n        $.biases = reader.object(json.biases, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.Convolution2dDescriptor = class Convolution2dDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Convolution2dDescriptor();\n        $.padLeft = reader.uint32_(position, 4, 0);\n        $.padRight = reader.uint32_(position, 6, 0);\n        $.padTop = reader.uint32_(position, 8, 0);\n        $.padBottom = reader.uint32_(position, 10, 0);\n        $.strideX = reader.uint32_(position, 12, 0);\n        $.strideY = reader.uint32_(position, 14, 0);\n        $.dilationX = reader.uint32_(position, 16, 1);\n        $.dilationY = reader.uint32_(position, 18, 1);\n        $.biasEnabled = reader.bool_(position, 20, false);\n        $.dataLayout = reader.int8_(position, 22, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Convolution2dDescriptor();\n        $.padLeft = reader.value(json.padLeft, 0);\n        $.padRight = reader.value(json.padRight, 0);\n        $.padTop = reader.value(json.padTop, 0);\n        $.padBottom = reader.value(json.padBottom, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.dilationX = reader.value(json.dilationX, 1);\n        $.dilationY = reader.value(json.dilationY, 1);\n        $.biasEnabled = reader.value(json.biasEnabled, false);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.Convolution3dLayer = class Convolution3dLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Convolution3dLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.Convolution3dDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Convolution3dLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.Convolution3dDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.Convolution3dDescriptor = class Convolution3dDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Convolution3dDescriptor();\n        $.padLeft = reader.uint32_(position, 4, 0);\n        $.padRight = reader.uint32_(position, 6, 0);\n        $.padTop = reader.uint32_(position, 8, 0);\n        $.padBottom = reader.uint32_(position, 10, 0);\n        $.padFront = reader.uint32_(position, 12, 0);\n        $.padBack = reader.uint32_(position, 14, 0);\n        $.strideX = reader.uint32_(position, 16, 0);\n        $.strideY = reader.uint32_(position, 18, 0);\n        $.strideZ = reader.uint32_(position, 20, 0);\n        $.dilationX = reader.uint32_(position, 22, 1);\n        $.dilationY = reader.uint32_(position, 24, 1);\n        $.dilationZ = reader.uint32_(position, 26, 1);\n        $.biasEnabled = reader.bool_(position, 28, false);\n        $.dataLayout = reader.int8_(position, 30, 2);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Convolution3dDescriptor();\n        $.padLeft = reader.value(json.padLeft, 0);\n        $.padRight = reader.value(json.padRight, 0);\n        $.padTop = reader.value(json.padTop, 0);\n        $.padBottom = reader.value(json.padBottom, 0);\n        $.padFront = reader.value(json.padFront, 0);\n        $.padBack = reader.value(json.padBack, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.strideZ = reader.value(json.strideZ, 0);\n        $.dilationX = reader.value(json.dilationX, 1);\n        $.dilationY = reader.value(json.dilationY, 1);\n        $.dilationZ = reader.value(json.dilationZ, 1);\n        $.biasEnabled = reader.value(json.biasEnabled, false);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.DepthToSpaceLayer = class DepthToSpaceLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DepthToSpaceLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.DepthToSpaceDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DepthToSpaceLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.DepthToSpaceDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.DepthToSpaceDescriptor = class DepthToSpaceDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DepthToSpaceDescriptor();\n        $.blockSize = reader.uint32_(position, 4, 0);\n        $.dataLayout = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DepthToSpaceDescriptor();\n        $.blockSize = reader.value(json.blockSize, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.DivisionLayer = class DivisionLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DivisionLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DivisionLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.BinaryOperation = {\n    Add: 0, '0': 'Add',\n    Div: 1, '1': 'Div',\n    Maximum: 2, '2': 'Maximum',\n    Minimum: 3, '3': 'Minimum',\n    Mul: 4, '4': 'Mul',\n    Sub: 5, '5': 'Sub',\n    SqDiff: 6, '6': 'SqDiff',\n    Power: 7, '7': 'Power',\n    FloorDiv: 8, '8': 'FloorDiv'\n};\n\narmnnSerializer.ElementwiseBinaryDescriptor = class ElementwiseBinaryDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ElementwiseBinaryDescriptor();\n        $.operation = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ElementwiseBinaryDescriptor();\n        $.operation = armnnSerializer.BinaryOperation[json.operation];\n        return $;\n    }\n};\n\narmnnSerializer.ElementwiseBinaryLayer = class ElementwiseBinaryLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ElementwiseBinaryLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ElementwiseBinaryDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ElementwiseBinaryLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ElementwiseBinaryDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.UnaryOperation = {\n    Abs: 0, '0': 'Abs',\n    Rsqrt: 1, '1': 'Rsqrt',\n    Sqrt: 2, '2': 'Sqrt',\n    Exp: 3, '3': 'Exp',\n    Neg: 4, '4': 'Neg',\n    LogicalNot: 5, '5': 'LogicalNot',\n    Log: 6, '6': 'Log',\n    Sin: 7, '7': 'Sin',\n    Ceil: 8, '8': 'Ceil'\n};\n\narmnnSerializer.ElementwiseUnaryDescriptor = class ElementwiseUnaryDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ElementwiseUnaryDescriptor();\n        $.operation = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ElementwiseUnaryDescriptor();\n        $.operation = armnnSerializer.UnaryOperation[json.operation];\n        return $;\n    }\n};\n\narmnnSerializer.ElementwiseUnaryLayer = class ElementwiseUnaryLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ElementwiseUnaryLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ElementwiseUnaryDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ElementwiseUnaryLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ElementwiseUnaryDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.EqualLayer = class EqualLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.EqualLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.EqualLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.FillLayer = class FillLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.FillLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.FillDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.FillLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.FillDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.FillDescriptor = class FillDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.FillDescriptor();\n        $.value = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.FillDescriptor();\n        $.value = reader.value(json.value, 0);\n        return $;\n    }\n};\n\narmnnSerializer.FloorLayer = class FloorLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.FloorLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.FloorLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.FullyConnectedLayer = class FullyConnectedLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.FullyConnectedLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.FullyConnectedDescriptor);\n        $.weights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.biases = reader.table(position, 10, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.FullyConnectedLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.FullyConnectedDescriptor);\n        $.weights = reader.object(json.weights, armnnSerializer.ConstTensor);\n        $.biases = reader.object(json.biases, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.FullyConnectedDescriptor = class FullyConnectedDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.FullyConnectedDescriptor();\n        $.biasEnabled = reader.bool_(position, 4, false);\n        $.transposeWeightsMatrix = reader.bool_(position, 6, false);\n        $.constantWeights = reader.bool_(position, 8, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.FullyConnectedDescriptor();\n        $.biasEnabled = reader.value(json.biasEnabled, false);\n        $.transposeWeightsMatrix = reader.value(json.transposeWeightsMatrix, false);\n        $.constantWeights = reader.value(json.constantWeights, true);\n        return $;\n    }\n};\n\narmnnSerializer.GatherLayer = class GatherLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.GatherLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.GatherDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.GatherLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.GatherDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.GatherDescriptor = class GatherDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.GatherDescriptor();\n        $.axis = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.GatherDescriptor();\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\narmnnSerializer.GatherNdLayer = class GatherNdLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.GatherNdLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.GatherNdLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.GreaterLayer = class GreaterLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.GreaterLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.GreaterLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.InputLayer = class InputLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.InputLayer();\n        $.base = reader.table(position, 4, armnnSerializer.BindableLayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.InputLayer();\n        $.base = reader.object(json.base, armnnSerializer.BindableLayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.InstanceNormalizationLayer = class InstanceNormalizationLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.InstanceNormalizationLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.InstanceNormalizationDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.InstanceNormalizationLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.InstanceNormalizationDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.InstanceNormalizationDescriptor = class InstanceNormalizationDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.InstanceNormalizationDescriptor();\n        $.gamma = reader.float32_(position, 4, 0);\n        $.beta = reader.float32_(position, 6, 0);\n        $.eps = reader.float32_(position, 8, 0);\n        $.dataLayout = reader.int8_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.InstanceNormalizationDescriptor();\n        $.gamma = reader.value(json.gamma, 0);\n        $.beta = reader.value(json.beta, 0);\n        $.eps = reader.value(json.eps, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.LogSoftmaxLayer = class LogSoftmaxLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LogSoftmaxLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.LogSoftmaxDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LogSoftmaxLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.LogSoftmaxDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.LogSoftmaxDescriptor = class LogSoftmaxDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LogSoftmaxDescriptor();\n        $.beta = reader.float32_(position, 4, 1);\n        $.axis = reader.int32_(position, 6, -1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LogSoftmaxDescriptor();\n        $.beta = reader.value(json.beta, 1);\n        $.axis = reader.value(json.axis, -1);\n        return $;\n    }\n};\n\narmnnSerializer.L2NormalizationLayer = class L2NormalizationLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.L2NormalizationLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.L2NormalizationDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.L2NormalizationLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.L2NormalizationDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.L2NormalizationDescriptor = class L2NormalizationDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.L2NormalizationDescriptor();\n        $.dataLayout = reader.int8_(position, 4, 1);\n        $.eps = reader.float32_(position, 6, 1e-12);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.L2NormalizationDescriptor();\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        $.eps = reader.value(json.eps, 1e-12);\n        return $;\n    }\n};\n\narmnnSerializer.LogicalBinaryOperation = {\n    LogicalAnd: 0, '0': 'LogicalAnd',\n    LogicalOr: 1, '1': 'LogicalOr'\n};\n\narmnnSerializer.LogicalBinaryDescriptor = class LogicalBinaryDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LogicalBinaryDescriptor();\n        $.operation = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LogicalBinaryDescriptor();\n        $.operation = armnnSerializer.LogicalBinaryOperation[json.operation];\n        return $;\n    }\n};\n\narmnnSerializer.LogicalBinaryLayer = class LogicalBinaryLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LogicalBinaryLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.LogicalBinaryDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LogicalBinaryLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.LogicalBinaryDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.MinimumLayer = class MinimumLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MinimumLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MinimumLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.MaximumLayer = class MaximumLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MaximumLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MaximumLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.MultiplicationLayer = class MultiplicationLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MultiplicationLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MultiplicationLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.Pooling2dLayer = class Pooling2dLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Pooling2dLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.Pooling2dDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Pooling2dLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.Pooling2dDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.Pooling3dLayer = class Pooling3dLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Pooling3dLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.Pooling3dDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Pooling3dLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.Pooling3dDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.PoolingAlgorithm = {\n    Max: 0, '0': 'Max',\n    Average: 1, '1': 'Average',\n    L2: 2, '2': 'L2'\n};\n\narmnnSerializer.OutputShapeRounding = {\n    Floor: 0, '0': 'Floor',\n    Ceiling: 1, '1': 'Ceiling'\n};\n\narmnnSerializer.PaddingMethod = {\n    IgnoreValue: 0, '0': 'IgnoreValue',\n    Exclude: 1, '1': 'Exclude'\n};\n\narmnnSerializer.Pooling2dDescriptor = class Pooling2dDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Pooling2dDescriptor();\n        $.poolType = reader.int8_(position, 4, 0);\n        $.padLeft = reader.uint32_(position, 6, 0);\n        $.padRight = reader.uint32_(position, 8, 0);\n        $.padTop = reader.uint32_(position, 10, 0);\n        $.padBottom = reader.uint32_(position, 12, 0);\n        $.poolWidth = reader.uint32_(position, 14, 0);\n        $.poolHeight = reader.uint32_(position, 16, 0);\n        $.strideX = reader.uint32_(position, 18, 0);\n        $.strideY = reader.uint32_(position, 20, 0);\n        $.outputShapeRounding = reader.int8_(position, 22, 0);\n        $.paddingMethod = reader.int8_(position, 24, 0);\n        $.dataLayout = reader.int8_(position, 26, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Pooling2dDescriptor();\n        $.poolType = armnnSerializer.PoolingAlgorithm[json.poolType];\n        $.padLeft = reader.value(json.padLeft, 0);\n        $.padRight = reader.value(json.padRight, 0);\n        $.padTop = reader.value(json.padTop, 0);\n        $.padBottom = reader.value(json.padBottom, 0);\n        $.poolWidth = reader.value(json.poolWidth, 0);\n        $.poolHeight = reader.value(json.poolHeight, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.outputShapeRounding = armnnSerializer.OutputShapeRounding[json.outputShapeRounding];\n        $.paddingMethod = armnnSerializer.PaddingMethod[json.paddingMethod];\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.Pooling3dDescriptor = class Pooling3dDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.Pooling3dDescriptor();\n        $.poolType = reader.int8_(position, 4, 0);\n        $.padLeft = reader.uint32_(position, 6, 0);\n        $.padRight = reader.uint32_(position, 8, 0);\n        $.padTop = reader.uint32_(position, 10, 0);\n        $.padBottom = reader.uint32_(position, 12, 0);\n        $.padFront = reader.uint32_(position, 14, 0);\n        $.padBack = reader.uint32_(position, 16, 0);\n        $.poolWidth = reader.uint32_(position, 18, 0);\n        $.poolHeight = reader.uint32_(position, 20, 0);\n        $.poolDepth = reader.uint32_(position, 22, 0);\n        $.strideX = reader.uint32_(position, 24, 0);\n        $.strideY = reader.uint32_(position, 26, 0);\n        $.strideZ = reader.uint32_(position, 28, 0);\n        $.outputShapeRounding = reader.int8_(position, 30, 0);\n        $.paddingMethod = reader.int8_(position, 32, 0);\n        $.dataLayout = reader.int8_(position, 34, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.Pooling3dDescriptor();\n        $.poolType = armnnSerializer.PoolingAlgorithm[json.poolType];\n        $.padLeft = reader.value(json.padLeft, 0);\n        $.padRight = reader.value(json.padRight, 0);\n        $.padTop = reader.value(json.padTop, 0);\n        $.padBottom = reader.value(json.padBottom, 0);\n        $.padFront = reader.value(json.padFront, 0);\n        $.padBack = reader.value(json.padBack, 0);\n        $.poolWidth = reader.value(json.poolWidth, 0);\n        $.poolHeight = reader.value(json.poolHeight, 0);\n        $.poolDepth = reader.value(json.poolDepth, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.strideZ = reader.value(json.strideZ, 0);\n        $.outputShapeRounding = armnnSerializer.OutputShapeRounding[json.outputShapeRounding];\n        $.paddingMethod = armnnSerializer.PaddingMethod[json.paddingMethod];\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.QuantizeLayer = class QuantizeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.QuantizeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.QuantizeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.SoftmaxLayer = class SoftmaxLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SoftmaxLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.SoftmaxDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SoftmaxLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.SoftmaxDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.SoftmaxDescriptor = class SoftmaxDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SoftmaxDescriptor();\n        $.beta = reader.float32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, -1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SoftmaxDescriptor();\n        $.beta = reader.value(json.beta, 0);\n        $.axis = reader.value(json.axis, -1);\n        return $;\n    }\n};\n\narmnnSerializer.DepthwiseConvolution2dLayer = class DepthwiseConvolution2dLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DepthwiseConvolution2dLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.DepthwiseConvolution2dDescriptor);\n        $.weights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.biases = reader.table(position, 10, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DepthwiseConvolution2dLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.DepthwiseConvolution2dDescriptor);\n        $.weights = reader.object(json.weights, armnnSerializer.ConstTensor);\n        $.biases = reader.object(json.biases, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.DepthwiseConvolution2dDescriptor = class DepthwiseConvolution2dDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DepthwiseConvolution2dDescriptor();\n        $.padLeft = reader.uint32_(position, 4, 0);\n        $.padRight = reader.uint32_(position, 6, 0);\n        $.padTop = reader.uint32_(position, 8, 0);\n        $.padBottom = reader.uint32_(position, 10, 0);\n        $.strideX = reader.uint32_(position, 12, 0);\n        $.strideY = reader.uint32_(position, 14, 0);\n        $.dilationX = reader.uint32_(position, 16, 1);\n        $.dilationY = reader.uint32_(position, 18, 1);\n        $.biasEnabled = reader.bool_(position, 20, false);\n        $.dataLayout = reader.int8_(position, 22, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DepthwiseConvolution2dDescriptor();\n        $.padLeft = reader.value(json.padLeft, 0);\n        $.padRight = reader.value(json.padRight, 0);\n        $.padTop = reader.value(json.padTop, 0);\n        $.padBottom = reader.value(json.padBottom, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.dilationX = reader.value(json.dilationX, 1);\n        $.dilationY = reader.value(json.dilationY, 1);\n        $.biasEnabled = reader.value(json.biasEnabled, false);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.OutputLayer = class OutputLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.OutputLayer();\n        $.base = reader.table(position, 4, armnnSerializer.BindableLayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.OutputLayer();\n        $.base = reader.object(json.base, armnnSerializer.BindableLayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.ReshapeLayer = class ReshapeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ReshapeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ReshapeDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ReshapeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ReshapeDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ReshapeDescriptor = class ReshapeDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ReshapeDescriptor();\n        $.targetShape = reader.array(position, 4, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ReshapeDescriptor();\n        $.targetShape = reader.array(json.targetShape, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.PermuteLayer = class PermuteLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.PermuteLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.PermuteDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.PermuteLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.PermuteDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.PermuteDescriptor = class PermuteDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.PermuteDescriptor();\n        $.dimMappings = reader.array(position, 4, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.PermuteDescriptor();\n        $.dimMappings = reader.array(json.dimMappings, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.ShapeLayer = class ShapeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ShapeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ShapeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.SpaceToBatchNdLayer = class SpaceToBatchNdLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SpaceToBatchNdLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.SpaceToBatchNdDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SpaceToBatchNdLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.SpaceToBatchNdDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.SpaceToBatchNdDescriptor = class SpaceToBatchNdDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SpaceToBatchNdDescriptor();\n        $.blockShape = reader.array(position, 4, Uint32Array);\n        $.padList = reader.array(position, 6, Uint32Array);\n        $.dataLayout = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SpaceToBatchNdDescriptor();\n        $.blockShape = reader.array(json.blockShape, Uint32Array);\n        $.padList = reader.array(json.padList, Uint32Array);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.SpaceToDepthLayer = class SpaceToDepthLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SpaceToDepthLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.SpaceToDepthDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SpaceToDepthLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.SpaceToDepthDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.SpaceToDepthDescriptor = class SpaceToDepthDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SpaceToDepthDescriptor();\n        $.blockSize = reader.uint32_(position, 4, 0);\n        $.dataLayout = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SpaceToDepthDescriptor();\n        $.blockSize = reader.value(json.blockSize, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.SubtractionLayer = class SubtractionLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SubtractionLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SubtractionLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.BatchToSpaceNdLayer = class BatchToSpaceNdLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BatchToSpaceNdLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.BatchToSpaceNdDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BatchToSpaceNdLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.BatchToSpaceNdDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.BatchToSpaceNdDescriptor = class BatchToSpaceNdDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BatchToSpaceNdDescriptor();\n        $.blockShape = reader.array(position, 4, Uint32Array);\n        $.crops = reader.array(position, 6, Uint32Array);\n        $.dataLayout = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BatchToSpaceNdDescriptor();\n        $.blockShape = reader.array(json.blockShape, Uint32Array);\n        $.crops = reader.array(json.crops, Uint32Array);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.NormalizationAlgorithmChannel = {\n    Across: 0, '0': 'Across',\n    Within: 1, '1': 'Within'\n};\n\narmnnSerializer.NormalizationAlgorithmMethod = {\n    LocalBrightness: 0, '0': 'LocalBrightness',\n    LocalContrast: 1, '1': 'LocalContrast'\n};\n\narmnnSerializer.NormalizationLayer = class NormalizationLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.NormalizationLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.NormalizationDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.NormalizationLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.NormalizationDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.NormalizationDescriptor = class NormalizationDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.NormalizationDescriptor();\n        $.normChannelType = reader.int8_(position, 4, 0);\n        $.normMethodType = reader.int8_(position, 6, 0);\n        $.normSize = reader.uint32_(position, 8, 0);\n        $.alpha = reader.float32_(position, 10, 0);\n        $.beta = reader.float32_(position, 12, 0);\n        $.k = reader.float32_(position, 14, 0);\n        $.dataLayout = reader.int8_(position, 16, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.NormalizationDescriptor();\n        $.normChannelType = armnnSerializer.NormalizationAlgorithmChannel[json.normChannelType];\n        $.normMethodType = armnnSerializer.NormalizationAlgorithmMethod[json.normMethodType];\n        $.normSize = reader.value(json.normSize, 0);\n        $.alpha = reader.value(json.alpha, 0);\n        $.beta = reader.value(json.beta, 0);\n        $.k = reader.value(json.k, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.MeanLayer = class MeanLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MeanLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.MeanDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MeanLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.MeanDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.MeanDescriptor = class MeanDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MeanDescriptor();\n        $.axis = reader.array(position, 4, Uint32Array);\n        $.keepDims = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MeanDescriptor();\n        $.axis = reader.array(json.axis, Uint32Array);\n        $.keepDims = reader.value(json.keepDims, false);\n        return $;\n    }\n};\n\narmnnSerializer.PadLayer = class PadLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.PadLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.PadDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.PadLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.PadDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.PaddingMode = {\n    Constant: 0, '0': 'Constant',\n    Reflect: 1, '1': 'Reflect',\n    Symmetric: 2, '2': 'Symmetric'\n};\n\narmnnSerializer.PadDescriptor = class PadDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.PadDescriptor();\n        $.padList = reader.array(position, 4, Uint32Array);\n        $.padValue = reader.float32_(position, 6, 0);\n        $.paddingMode = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.PadDescriptor();\n        $.padList = reader.array(json.padList, Uint32Array);\n        $.padValue = reader.value(json.padValue, 0);\n        $.paddingMode = armnnSerializer.PaddingMode[json.paddingMode];\n        return $;\n    }\n};\n\narmnnSerializer.RsqrtLayer = class RsqrtLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.RsqrtLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.RsqrtLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.BatchNormalizationLayer = class BatchNormalizationLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BatchNormalizationLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.BatchNormalizationDescriptor);\n        $.mean = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.variance = reader.table(position, 10, armnnSerializer.ConstTensor);\n        $.beta = reader.table(position, 12, armnnSerializer.ConstTensor);\n        $.gamma = reader.table(position, 14, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BatchNormalizationLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.BatchNormalizationDescriptor);\n        $.mean = reader.object(json.mean, armnnSerializer.ConstTensor);\n        $.variance = reader.object(json.variance, armnnSerializer.ConstTensor);\n        $.beta = reader.object(json.beta, armnnSerializer.ConstTensor);\n        $.gamma = reader.object(json.gamma, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.BatchNormalizationDescriptor = class BatchNormalizationDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BatchNormalizationDescriptor();\n        $.eps = reader.float32_(position, 4, 0);\n        $.dataLayout = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BatchNormalizationDescriptor();\n        $.eps = reader.value(json.eps, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.ResizeBilinearLayer = class ResizeBilinearLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ResizeBilinearLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ResizeBilinearDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ResizeBilinearLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ResizeBilinearDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ResizeBilinearDescriptor = class ResizeBilinearDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ResizeBilinearDescriptor();\n        $.targetWidth = reader.uint32_(position, 4, 0);\n        $.targetHeight = reader.uint32_(position, 6, 0);\n        $.dataLayout = reader.int8_(position, 8, 0);\n        $.alignCorners = reader.bool_(position, 10, false);\n        $.halfPixelCenters = reader.bool_(position, 12, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ResizeBilinearDescriptor();\n        $.targetWidth = reader.value(json.targetWidth, 0);\n        $.targetHeight = reader.value(json.targetHeight, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        $.alignCorners = reader.value(json.alignCorners, false);\n        $.halfPixelCenters = reader.value(json.halfPixelCenters, false);\n        return $;\n    }\n};\n\narmnnSerializer.SliceLayer = class SliceLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SliceLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.SliceDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SliceLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.SliceDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.SliceDescriptor = class SliceDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SliceDescriptor();\n        $.begin = reader.array(position, 4, Uint32Array);\n        $.size = reader.array(position, 6, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SliceDescriptor();\n        $.begin = reader.array(json.begin, Uint32Array);\n        $.size = reader.array(json.size, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.StridedSliceLayer = class StridedSliceLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.StridedSliceLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.StridedSliceDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.StridedSliceLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.StridedSliceDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.StridedSliceDescriptor = class StridedSliceDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.StridedSliceDescriptor();\n        $.begin = reader.array(position, 4, Int32Array);\n        $.end = reader.array(position, 6, Int32Array);\n        $.stride = reader.array(position, 8, Int32Array);\n        $.beginMask = reader.int32_(position, 10, 0);\n        $.endMask = reader.int32_(position, 12, 0);\n        $.shrinkAxisMask = reader.int32_(position, 14, 0);\n        $.ellipsisMask = reader.int32_(position, 16, 0);\n        $.newAxisMask = reader.int32_(position, 18, 0);\n        $.dataLayout = reader.int8_(position, 20, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.StridedSliceDescriptor();\n        $.begin = reader.array(json.begin, Int32Array);\n        $.end = reader.array(json.end, Int32Array);\n        $.stride = reader.array(json.stride, Int32Array);\n        $.beginMask = reader.value(json.beginMask, 0);\n        $.endMask = reader.value(json.endMask, 0);\n        $.shrinkAxisMask = reader.value(json.shrinkAxisMask, 0);\n        $.ellipsisMask = reader.value(json.ellipsisMask, 0);\n        $.newAxisMask = reader.value(json.newAxisMask, 0);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.ConcatLayer = class ConcatLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ConcatLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.OriginsDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ConcatLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.OriginsDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.MergerLayer = class MergerLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MergerLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.OriginsDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MergerLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.OriginsDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.UintVector = class UintVector {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.UintVector();\n        $.data = reader.array(position, 4, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.UintVector();\n        $.data = reader.array(json.data, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.OriginsDescriptor = class OriginsDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.OriginsDescriptor();\n        $.concatAxis = reader.uint32_(position, 4, 0);\n        $.numViews = reader.uint32_(position, 6, 0);\n        $.numDimensions = reader.uint32_(position, 8, 0);\n        $.viewOrigins = reader.tables(position, 10, armnnSerializer.UintVector);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.OriginsDescriptor();\n        $.concatAxis = reader.value(json.concatAxis, 0);\n        $.numViews = reader.value(json.numViews, 0);\n        $.numDimensions = reader.value(json.numDimensions, 0);\n        $.viewOrigins = reader.objects(json.viewOrigins, armnnSerializer.UintVector);\n        return $;\n    }\n};\n\narmnnSerializer.ViewsDescriptor = class ViewsDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ViewsDescriptor();\n        $.origins = reader.table(position, 4, armnnSerializer.OriginsDescriptor);\n        $.viewSizes = reader.tables(position, 6, armnnSerializer.UintVector);\n        $.hasAxis = reader.bool_(position, 8, false);\n        $.axis = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ViewsDescriptor();\n        $.origins = reader.object(json.origins, armnnSerializer.OriginsDescriptor);\n        $.viewSizes = reader.objects(json.viewSizes, armnnSerializer.UintVector);\n        $.hasAxis = reader.value(json.hasAxis, false);\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\narmnnSerializer.SplitterLayer = class SplitterLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SplitterLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ViewsDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SplitterLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ViewsDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.DetectionPostProcessLayer = class DetectionPostProcessLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DetectionPostProcessLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.DetectionPostProcessDescriptor);\n        $.anchors = reader.table(position, 8, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DetectionPostProcessLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.DetectionPostProcessDescriptor);\n        $.anchors = reader.object(json.anchors, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.DetectionPostProcessDescriptor = class DetectionPostProcessDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DetectionPostProcessDescriptor();\n        $.maxDetections = reader.uint32_(position, 4, 0);\n        $.maxClassesPerDetection = reader.uint32_(position, 6, 0);\n        $.detectionsPerClass = reader.uint32_(position, 8, 0);\n        $.nmsScoreThreshold = reader.float32_(position, 10, 0);\n        $.nmsIouThreshold = reader.float32_(position, 12, 0);\n        $.numClasses = reader.uint32_(position, 14, 0);\n        $.useRegularNms = reader.bool_(position, 16, false);\n        $.scaleX = reader.float32_(position, 18, 0);\n        $.scaleY = reader.float32_(position, 20, 0);\n        $.scaleW = reader.float32_(position, 22, 0);\n        $.scaleH = reader.float32_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DetectionPostProcessDescriptor();\n        $.maxDetections = reader.value(json.maxDetections, 0);\n        $.maxClassesPerDetection = reader.value(json.maxClassesPerDetection, 0);\n        $.detectionsPerClass = reader.value(json.detectionsPerClass, 0);\n        $.nmsScoreThreshold = reader.value(json.nmsScoreThreshold, 0);\n        $.nmsIouThreshold = reader.value(json.nmsIouThreshold, 0);\n        $.numClasses = reader.value(json.numClasses, 0);\n        $.useRegularNms = reader.value(json.useRegularNms, false);\n        $.scaleX = reader.value(json.scaleX, 0);\n        $.scaleY = reader.value(json.scaleY, 0);\n        $.scaleW = reader.value(json.scaleW, 0);\n        $.scaleH = reader.value(json.scaleH, 0);\n        return $;\n    }\n};\n\narmnnSerializer.LstmInputParams = class LstmInputParams {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LstmInputParams();\n        $.inputToForgetWeights = reader.table(position, 4, armnnSerializer.ConstTensor);\n        $.inputToCellWeights = reader.table(position, 6, armnnSerializer.ConstTensor);\n        $.inputToOutputWeights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.recurrentToForgetWeights = reader.table(position, 10, armnnSerializer.ConstTensor);\n        $.recurrentToCellWeights = reader.table(position, 12, armnnSerializer.ConstTensor);\n        $.recurrentToOutputWeights = reader.table(position, 14, armnnSerializer.ConstTensor);\n        $.forgetGateBias = reader.table(position, 16, armnnSerializer.ConstTensor);\n        $.cellBias = reader.table(position, 18, armnnSerializer.ConstTensor);\n        $.outputGateBias = reader.table(position, 20, armnnSerializer.ConstTensor);\n        $.inputToInputWeights = reader.table(position, 22, armnnSerializer.ConstTensor);\n        $.recurrentToInputWeights = reader.table(position, 24, armnnSerializer.ConstTensor);\n        $.cellToInputWeights = reader.table(position, 26, armnnSerializer.ConstTensor);\n        $.inputGateBias = reader.table(position, 28, armnnSerializer.ConstTensor);\n        $.projectionWeights = reader.table(position, 30, armnnSerializer.ConstTensor);\n        $.projectionBias = reader.table(position, 32, armnnSerializer.ConstTensor);\n        $.cellToForgetWeights = reader.table(position, 34, armnnSerializer.ConstTensor);\n        $.cellToOutputWeights = reader.table(position, 36, armnnSerializer.ConstTensor);\n        $.inputLayerNormWeights = reader.table(position, 38, armnnSerializer.ConstTensor);\n        $.forgetLayerNormWeights = reader.table(position, 40, armnnSerializer.ConstTensor);\n        $.cellLayerNormWeights = reader.table(position, 42, armnnSerializer.ConstTensor);\n        $.outputLayerNormWeights = reader.table(position, 44, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LstmInputParams();\n        $.inputToForgetWeights = reader.object(json.inputToForgetWeights, armnnSerializer.ConstTensor);\n        $.inputToCellWeights = reader.object(json.inputToCellWeights, armnnSerializer.ConstTensor);\n        $.inputToOutputWeights = reader.object(json.inputToOutputWeights, armnnSerializer.ConstTensor);\n        $.recurrentToForgetWeights = reader.object(json.recurrentToForgetWeights, armnnSerializer.ConstTensor);\n        $.recurrentToCellWeights = reader.object(json.recurrentToCellWeights, armnnSerializer.ConstTensor);\n        $.recurrentToOutputWeights = reader.object(json.recurrentToOutputWeights, armnnSerializer.ConstTensor);\n        $.forgetGateBias = reader.object(json.forgetGateBias, armnnSerializer.ConstTensor);\n        $.cellBias = reader.object(json.cellBias, armnnSerializer.ConstTensor);\n        $.outputGateBias = reader.object(json.outputGateBias, armnnSerializer.ConstTensor);\n        $.inputToInputWeights = reader.object(json.inputToInputWeights, armnnSerializer.ConstTensor);\n        $.recurrentToInputWeights = reader.object(json.recurrentToInputWeights, armnnSerializer.ConstTensor);\n        $.cellToInputWeights = reader.object(json.cellToInputWeights, armnnSerializer.ConstTensor);\n        $.inputGateBias = reader.object(json.inputGateBias, armnnSerializer.ConstTensor);\n        $.projectionWeights = reader.object(json.projectionWeights, armnnSerializer.ConstTensor);\n        $.projectionBias = reader.object(json.projectionBias, armnnSerializer.ConstTensor);\n        $.cellToForgetWeights = reader.object(json.cellToForgetWeights, armnnSerializer.ConstTensor);\n        $.cellToOutputWeights = reader.object(json.cellToOutputWeights, armnnSerializer.ConstTensor);\n        $.inputLayerNormWeights = reader.object(json.inputLayerNormWeights, armnnSerializer.ConstTensor);\n        $.forgetLayerNormWeights = reader.object(json.forgetLayerNormWeights, armnnSerializer.ConstTensor);\n        $.cellLayerNormWeights = reader.object(json.cellLayerNormWeights, armnnSerializer.ConstTensor);\n        $.outputLayerNormWeights = reader.object(json.outputLayerNormWeights, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.LstmDescriptor = class LstmDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LstmDescriptor();\n        $.activationFunc = reader.uint32_(position, 4, 0);\n        $.clippingThresCell = reader.float32_(position, 6, 0);\n        $.clippingThresProj = reader.float32_(position, 8, 0);\n        $.cifgEnabled = reader.bool_(position, 10, true);\n        $.peepholeEnabled = reader.bool_(position, 12, false);\n        $.projectionEnabled = reader.bool_(position, 14, false);\n        $.layerNormEnabled = reader.bool_(position, 16, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LstmDescriptor();\n        $.activationFunc = reader.value(json.activationFunc, 0);\n        $.clippingThresCell = reader.value(json.clippingThresCell, 0);\n        $.clippingThresProj = reader.value(json.clippingThresProj, 0);\n        $.cifgEnabled = reader.value(json.cifgEnabled, true);\n        $.peepholeEnabled = reader.value(json.peepholeEnabled, false);\n        $.projectionEnabled = reader.value(json.projectionEnabled, false);\n        $.layerNormEnabled = reader.value(json.layerNormEnabled, false);\n        return $;\n    }\n};\n\narmnnSerializer.LstmLayer = class LstmLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.LstmLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.LstmDescriptor);\n        $.inputParams = reader.table(position, 8, armnnSerializer.LstmInputParams);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.LstmLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.LstmDescriptor);\n        $.inputParams = reader.object(json.inputParams, armnnSerializer.LstmInputParams);\n        return $;\n    }\n};\n\narmnnSerializer.QLstmInputParams = class QLstmInputParams {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.QLstmInputParams();\n        $.inputToForgetWeights = reader.table(position, 4, armnnSerializer.ConstTensor);\n        $.inputToCellWeights = reader.table(position, 6, armnnSerializer.ConstTensor);\n        $.inputToOutputWeights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.recurrentToForgetWeights = reader.table(position, 10, armnnSerializer.ConstTensor);\n        $.recurrentToCellWeights = reader.table(position, 12, armnnSerializer.ConstTensor);\n        $.recurrentToOutputWeights = reader.table(position, 14, armnnSerializer.ConstTensor);\n        $.forgetGateBias = reader.table(position, 16, armnnSerializer.ConstTensor);\n        $.cellBias = reader.table(position, 18, armnnSerializer.ConstTensor);\n        $.outputGateBias = reader.table(position, 20, armnnSerializer.ConstTensor);\n        $.inputToInputWeights = reader.table(position, 22, armnnSerializer.ConstTensor);\n        $.recurrentToInputWeights = reader.table(position, 24, armnnSerializer.ConstTensor);\n        $.inputGateBias = reader.table(position, 26, armnnSerializer.ConstTensor);\n        $.projectionWeights = reader.table(position, 28, armnnSerializer.ConstTensor);\n        $.projectionBias = reader.table(position, 30, armnnSerializer.ConstTensor);\n        $.cellToInputWeights = reader.table(position, 32, armnnSerializer.ConstTensor);\n        $.cellToForgetWeights = reader.table(position, 34, armnnSerializer.ConstTensor);\n        $.cellToOutputWeights = reader.table(position, 36, armnnSerializer.ConstTensor);\n        $.inputLayerNormWeights = reader.table(position, 38, armnnSerializer.ConstTensor);\n        $.forgetLayerNormWeights = reader.table(position, 40, armnnSerializer.ConstTensor);\n        $.cellLayerNormWeights = reader.table(position, 42, armnnSerializer.ConstTensor);\n        $.outputLayerNormWeights = reader.table(position, 44, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.QLstmInputParams();\n        $.inputToForgetWeights = reader.object(json.inputToForgetWeights, armnnSerializer.ConstTensor);\n        $.inputToCellWeights = reader.object(json.inputToCellWeights, armnnSerializer.ConstTensor);\n        $.inputToOutputWeights = reader.object(json.inputToOutputWeights, armnnSerializer.ConstTensor);\n        $.recurrentToForgetWeights = reader.object(json.recurrentToForgetWeights, armnnSerializer.ConstTensor);\n        $.recurrentToCellWeights = reader.object(json.recurrentToCellWeights, armnnSerializer.ConstTensor);\n        $.recurrentToOutputWeights = reader.object(json.recurrentToOutputWeights, armnnSerializer.ConstTensor);\n        $.forgetGateBias = reader.object(json.forgetGateBias, armnnSerializer.ConstTensor);\n        $.cellBias = reader.object(json.cellBias, armnnSerializer.ConstTensor);\n        $.outputGateBias = reader.object(json.outputGateBias, armnnSerializer.ConstTensor);\n        $.inputToInputWeights = reader.object(json.inputToInputWeights, armnnSerializer.ConstTensor);\n        $.recurrentToInputWeights = reader.object(json.recurrentToInputWeights, armnnSerializer.ConstTensor);\n        $.inputGateBias = reader.object(json.inputGateBias, armnnSerializer.ConstTensor);\n        $.projectionWeights = reader.object(json.projectionWeights, armnnSerializer.ConstTensor);\n        $.projectionBias = reader.object(json.projectionBias, armnnSerializer.ConstTensor);\n        $.cellToInputWeights = reader.object(json.cellToInputWeights, armnnSerializer.ConstTensor);\n        $.cellToForgetWeights = reader.object(json.cellToForgetWeights, armnnSerializer.ConstTensor);\n        $.cellToOutputWeights = reader.object(json.cellToOutputWeights, armnnSerializer.ConstTensor);\n        $.inputLayerNormWeights = reader.object(json.inputLayerNormWeights, armnnSerializer.ConstTensor);\n        $.forgetLayerNormWeights = reader.object(json.forgetLayerNormWeights, armnnSerializer.ConstTensor);\n        $.cellLayerNormWeights = reader.object(json.cellLayerNormWeights, armnnSerializer.ConstTensor);\n        $.outputLayerNormWeights = reader.object(json.outputLayerNormWeights, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.QLstmDescriptor = class QLstmDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.QLstmDescriptor();\n        $.cifgEnabled = reader.bool_(position, 4, true);\n        $.peepholeEnabled = reader.bool_(position, 6, false);\n        $.projectionEnabled = reader.bool_(position, 8, false);\n        $.layerNormEnabled = reader.bool_(position, 10, false);\n        $.cellClip = reader.float32_(position, 12, 0);\n        $.projectionClip = reader.float32_(position, 14, 0);\n        $.inputIntermediateScale = reader.float32_(position, 16, 0);\n        $.forgetIntermediateScale = reader.float32_(position, 18, 0);\n        $.cellIntermediateScale = reader.float32_(position, 20, 0);\n        $.outputIntermediateScale = reader.float32_(position, 22, 0);\n        $.hiddenStateZeroPoint = reader.int32_(position, 24, 0);\n        $.hiddenStateScale = reader.float32_(position, 26, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.QLstmDescriptor();\n        $.cifgEnabled = reader.value(json.cifgEnabled, true);\n        $.peepholeEnabled = reader.value(json.peepholeEnabled, false);\n        $.projectionEnabled = reader.value(json.projectionEnabled, false);\n        $.layerNormEnabled = reader.value(json.layerNormEnabled, false);\n        $.cellClip = reader.value(json.cellClip, 0);\n        $.projectionClip = reader.value(json.projectionClip, 0);\n        $.inputIntermediateScale = reader.value(json.inputIntermediateScale, 0);\n        $.forgetIntermediateScale = reader.value(json.forgetIntermediateScale, 0);\n        $.cellIntermediateScale = reader.value(json.cellIntermediateScale, 0);\n        $.outputIntermediateScale = reader.value(json.outputIntermediateScale, 0);\n        $.hiddenStateZeroPoint = reader.value(json.hiddenStateZeroPoint, 0);\n        $.hiddenStateScale = reader.value(json.hiddenStateScale, 0);\n        return $;\n    }\n};\n\narmnnSerializer.QLstmLayer = class QLstmLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.QLstmLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.QLstmDescriptor);\n        $.inputParams = reader.table(position, 8, armnnSerializer.QLstmInputParams);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.QLstmLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.QLstmDescriptor);\n        $.inputParams = reader.object(json.inputParams, armnnSerializer.QLstmInputParams);\n        return $;\n    }\n};\n\narmnnSerializer.QuantizedLstmInputParams = class QuantizedLstmInputParams {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.QuantizedLstmInputParams();\n        $.inputToInputWeights = reader.table(position, 4, armnnSerializer.ConstTensor);\n        $.inputToForgetWeights = reader.table(position, 6, armnnSerializer.ConstTensor);\n        $.inputToCellWeights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.inputToOutputWeights = reader.table(position, 10, armnnSerializer.ConstTensor);\n        $.recurrentToInputWeights = reader.table(position, 12, armnnSerializer.ConstTensor);\n        $.recurrentToForgetWeights = reader.table(position, 14, armnnSerializer.ConstTensor);\n        $.recurrentToCellWeights = reader.table(position, 16, armnnSerializer.ConstTensor);\n        $.recurrentToOutputWeights = reader.table(position, 18, armnnSerializer.ConstTensor);\n        $.inputGateBias = reader.table(position, 20, armnnSerializer.ConstTensor);\n        $.forgetGateBias = reader.table(position, 22, armnnSerializer.ConstTensor);\n        $.cellBias = reader.table(position, 24, armnnSerializer.ConstTensor);\n        $.outputGateBias = reader.table(position, 26, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.QuantizedLstmInputParams();\n        $.inputToInputWeights = reader.object(json.inputToInputWeights, armnnSerializer.ConstTensor);\n        $.inputToForgetWeights = reader.object(json.inputToForgetWeights, armnnSerializer.ConstTensor);\n        $.inputToCellWeights = reader.object(json.inputToCellWeights, armnnSerializer.ConstTensor);\n        $.inputToOutputWeights = reader.object(json.inputToOutputWeights, armnnSerializer.ConstTensor);\n        $.recurrentToInputWeights = reader.object(json.recurrentToInputWeights, armnnSerializer.ConstTensor);\n        $.recurrentToForgetWeights = reader.object(json.recurrentToForgetWeights, armnnSerializer.ConstTensor);\n        $.recurrentToCellWeights = reader.object(json.recurrentToCellWeights, armnnSerializer.ConstTensor);\n        $.recurrentToOutputWeights = reader.object(json.recurrentToOutputWeights, armnnSerializer.ConstTensor);\n        $.inputGateBias = reader.object(json.inputGateBias, armnnSerializer.ConstTensor);\n        $.forgetGateBias = reader.object(json.forgetGateBias, armnnSerializer.ConstTensor);\n        $.cellBias = reader.object(json.cellBias, armnnSerializer.ConstTensor);\n        $.outputGateBias = reader.object(json.outputGateBias, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.QuantizedLstmLayer = class QuantizedLstmLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.QuantizedLstmLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.inputParams = reader.table(position, 6, armnnSerializer.QuantizedLstmInputParams);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.QuantizedLstmLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.inputParams = reader.object(json.inputParams, armnnSerializer.QuantizedLstmInputParams);\n        return $;\n    }\n};\n\narmnnSerializer.DequantizeLayer = class DequantizeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.DequantizeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.DequantizeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.MergeLayer = class MergeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.MergeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.MergeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.SwitchLayer = class SwitchLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SwitchLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SwitchLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.PreluLayer = class PreluLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.PreluLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.PreluLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.TransposeConvolution2dLayer = class TransposeConvolution2dLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TransposeConvolution2dLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.TransposeConvolution2dDescriptor);\n        $.weights = reader.table(position, 8, armnnSerializer.ConstTensor);\n        $.biases = reader.table(position, 10, armnnSerializer.ConstTensor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TransposeConvolution2dLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.TransposeConvolution2dDescriptor);\n        $.weights = reader.object(json.weights, armnnSerializer.ConstTensor);\n        $.biases = reader.object(json.biases, armnnSerializer.ConstTensor);\n        return $;\n    }\n};\n\narmnnSerializer.TransposeConvolution2dDescriptor = class TransposeConvolution2dDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TransposeConvolution2dDescriptor();\n        $.padLeft = reader.uint32_(position, 4, 0);\n        $.padRight = reader.uint32_(position, 6, 0);\n        $.padTop = reader.uint32_(position, 8, 0);\n        $.padBottom = reader.uint32_(position, 10, 0);\n        $.strideX = reader.uint32_(position, 12, 0);\n        $.strideY = reader.uint32_(position, 14, 0);\n        $.biasEnabled = reader.bool_(position, 16, false);\n        $.dataLayout = reader.int8_(position, 18, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TransposeConvolution2dDescriptor();\n        $.padLeft = reader.value(json.padLeft, 0);\n        $.padRight = reader.value(json.padRight, 0);\n        $.padTop = reader.value(json.padTop, 0);\n        $.padBottom = reader.value(json.padBottom, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.biasEnabled = reader.value(json.biasEnabled, false);\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        return $;\n    }\n};\n\narmnnSerializer.TransposeLayer = class TransposeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TransposeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.TransposeDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TransposeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.TransposeDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.TransposeDescriptor = class TransposeDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TransposeDescriptor();\n        $.dimMappings = reader.array(position, 4, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TransposeDescriptor();\n        $.dimMappings = reader.array(json.dimMappings, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.ResizeLayer = class ResizeLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ResizeLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ResizeDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ResizeLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ResizeDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ResizeDescriptor = class ResizeDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ResizeDescriptor();\n        $.targetHeight = reader.uint32_(position, 4, 0);\n        $.targetWidth = reader.uint32_(position, 6, 0);\n        $.method = reader.int8_(position, 8, 0);\n        $.dataLayout = reader.int8_(position, 10, 0);\n        $.alignCorners = reader.bool_(position, 12, false);\n        $.halfPixelCenters = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ResizeDescriptor();\n        $.targetHeight = reader.value(json.targetHeight, 0);\n        $.targetWidth = reader.value(json.targetWidth, 0);\n        $.method = armnnSerializer.ResizeMethod[json.method];\n        $.dataLayout = armnnSerializer.DataLayout[json.dataLayout];\n        $.alignCorners = reader.value(json.alignCorners, false);\n        $.halfPixelCenters = reader.value(json.halfPixelCenters, false);\n        return $;\n    }\n};\n\narmnnSerializer.ReverseV2Layer = class ReverseV2Layer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ReverseV2Layer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ReverseV2Layer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.StackLayer = class StackLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.StackLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.StackDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.StackLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.StackDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.StackDescriptor = class StackDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.StackDescriptor();\n        $.axis = reader.uint32_(position, 4, 0);\n        $.numInputs = reader.uint32_(position, 6, 0);\n        $.inputShape = reader.array(position, 8, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.StackDescriptor();\n        $.axis = reader.value(json.axis, 0);\n        $.numInputs = reader.value(json.numInputs, 0);\n        $.inputShape = reader.array(json.inputShape, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.StandInDescriptor = class StandInDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.StandInDescriptor();\n        $.numInputs = reader.uint32_(position, 4, 0);\n        $.numOutputs = reader.uint32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.StandInDescriptor();\n        $.numInputs = reader.value(json.numInputs, 0);\n        $.numOutputs = reader.value(json.numOutputs, 0);\n        return $;\n    }\n};\n\narmnnSerializer.StandInLayer = class StandInLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.StandInLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.StandInDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.StandInLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.StandInDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.RankLayer = class RankLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.RankLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.RankLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        return $;\n    }\n};\n\narmnnSerializer.ReduceLayer = class ReduceLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ReduceLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ReduceDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ReduceLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ReduceDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ReduceDescriptor = class ReduceDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ReduceDescriptor();\n        $.keepDims = reader.bool_(position, 4, false);\n        $.axis = reader.array(position, 6, Uint32Array);\n        $.reduceOperation = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ReduceDescriptor();\n        $.keepDims = reader.value(json.keepDims, false);\n        $.axis = reader.array(json.axis, Uint32Array);\n        $.reduceOperation = armnnSerializer.ReduceOperation[json.reduceOperation];\n        return $;\n    }\n};\n\narmnnSerializer.UnidirectionalSequenceLstmDescriptor = class UnidirectionalSequenceLstmDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.UnidirectionalSequenceLstmDescriptor();\n        $.activationFunc = reader.uint32_(position, 4, 0);\n        $.clippingThresCell = reader.float32_(position, 6, 0);\n        $.clippingThresProj = reader.float32_(position, 8, 0);\n        $.cifgEnabled = reader.bool_(position, 10, true);\n        $.peepholeEnabled = reader.bool_(position, 12, false);\n        $.projectionEnabled = reader.bool_(position, 14, false);\n        $.layerNormEnabled = reader.bool_(position, 16, false);\n        $.timeMajor = reader.bool_(position, 18, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.UnidirectionalSequenceLstmDescriptor();\n        $.activationFunc = reader.value(json.activationFunc, 0);\n        $.clippingThresCell = reader.value(json.clippingThresCell, 0);\n        $.clippingThresProj = reader.value(json.clippingThresProj, 0);\n        $.cifgEnabled = reader.value(json.cifgEnabled, true);\n        $.peepholeEnabled = reader.value(json.peepholeEnabled, false);\n        $.projectionEnabled = reader.value(json.projectionEnabled, false);\n        $.layerNormEnabled = reader.value(json.layerNormEnabled, false);\n        $.timeMajor = reader.value(json.timeMajor, false);\n        return $;\n    }\n};\n\narmnnSerializer.UnidirectionalSequenceLstmLayer = class UnidirectionalSequenceLstmLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.UnidirectionalSequenceLstmLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.UnidirectionalSequenceLstmDescriptor);\n        $.inputParams = reader.table(position, 8, armnnSerializer.LstmInputParams);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.UnidirectionalSequenceLstmLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.UnidirectionalSequenceLstmDescriptor);\n        $.inputParams = reader.object(json.inputParams, armnnSerializer.LstmInputParams);\n        return $;\n    }\n};\n\narmnnSerializer.BatchMatMulDescriptor = class BatchMatMulDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BatchMatMulDescriptor();\n        $.transposeX = reader.bool_(position, 4, false);\n        $.transposeY = reader.bool_(position, 6, false);\n        $.adjointX = reader.bool_(position, 8, false);\n        $.adjointY = reader.bool_(position, 10, false);\n        $.dataLayoutX = reader.int8_(position, 12, 1);\n        $.dataLayoutY = reader.int8_(position, 14, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BatchMatMulDescriptor();\n        $.transposeX = reader.value(json.transposeX, false);\n        $.transposeY = reader.value(json.transposeY, false);\n        $.adjointX = reader.value(json.adjointX, false);\n        $.adjointY = reader.value(json.adjointY, false);\n        $.dataLayoutX = armnnSerializer.DataLayout[json.dataLayoutX];\n        $.dataLayoutY = armnnSerializer.DataLayout[json.dataLayoutY];\n        return $;\n    }\n};\n\narmnnSerializer.BatchMatMulLayer = class BatchMatMulLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.BatchMatMulLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.BatchMatMulDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.BatchMatMulLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.BatchMatMulDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.TileDescriptor = class TileDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TileDescriptor();\n        $.m_Multiples = reader.array(position, 4, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TileDescriptor();\n        $.m_Multiples = reader.array(json.m_Multiples, Uint32Array);\n        return $;\n    }\n};\n\narmnnSerializer.TileLayer = class TileLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.TileLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.TileDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.TileLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.TileDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.ScatterNdDescriptor = class ScatterNdDescriptor {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ScatterNdDescriptor();\n        $.m_Function = reader.int8_(position, 4, 0);\n        $.m_InputEnabled = reader.bool_(position, 6, true);\n        $.m_Axis = reader.int32_(position, 8, 0);\n        $.m_AxisEnabled = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ScatterNdDescriptor();\n        $.m_Function = armnnSerializer.ScatterNdFunction[json.m_Function];\n        $.m_InputEnabled = reader.value(json.m_InputEnabled, true);\n        $.m_Axis = reader.value(json.m_Axis, 0);\n        $.m_AxisEnabled = reader.value(json.m_AxisEnabled, false);\n        return $;\n    }\n};\n\narmnnSerializer.ScatterNdLayer = class ScatterNdLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.ScatterNdLayer();\n        $.base = reader.table(position, 4, armnnSerializer.LayerBase);\n        $.descriptor = reader.table(position, 6, armnnSerializer.ScatterNdDescriptor);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.ScatterNdLayer();\n        $.base = reader.object(json.base, armnnSerializer.LayerBase);\n        $.descriptor = reader.object(json.descriptor, armnnSerializer.ScatterNdDescriptor);\n        return $;\n    }\n};\n\narmnnSerializer.Layer = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return armnnSerializer.ActivationLayer.decode(reader, position);\n            case 2: return armnnSerializer.AdditionLayer.decode(reader, position);\n            case 3: return armnnSerializer.BatchToSpaceNdLayer.decode(reader, position);\n            case 4: return armnnSerializer.BatchNormalizationLayer.decode(reader, position);\n            case 5: return armnnSerializer.ConstantLayer.decode(reader, position);\n            case 6: return armnnSerializer.Convolution2dLayer.decode(reader, position);\n            case 7: return armnnSerializer.DepthwiseConvolution2dLayer.decode(reader, position);\n            case 8: return armnnSerializer.FullyConnectedLayer.decode(reader, position);\n            case 9: return armnnSerializer.InputLayer.decode(reader, position);\n            case 10: return armnnSerializer.MultiplicationLayer.decode(reader, position);\n            case 11: return armnnSerializer.OutputLayer.decode(reader, position);\n            case 12: return armnnSerializer.PermuteLayer.decode(reader, position);\n            case 13: return armnnSerializer.Pooling2dLayer.decode(reader, position);\n            case 14: return armnnSerializer.ReshapeLayer.decode(reader, position);\n            case 15: return armnnSerializer.SoftmaxLayer.decode(reader, position);\n            case 16: return armnnSerializer.SpaceToBatchNdLayer.decode(reader, position);\n            case 17: return armnnSerializer.DivisionLayer.decode(reader, position);\n            case 18: return armnnSerializer.MinimumLayer.decode(reader, position);\n            case 19: return armnnSerializer.EqualLayer.decode(reader, position);\n            case 20: return armnnSerializer.MaximumLayer.decode(reader, position);\n            case 21: return armnnSerializer.NormalizationLayer.decode(reader, position);\n            case 22: return armnnSerializer.PadLayer.decode(reader, position);\n            case 23: return armnnSerializer.RsqrtLayer.decode(reader, position);\n            case 24: return armnnSerializer.FloorLayer.decode(reader, position);\n            case 25: return armnnSerializer.GreaterLayer.decode(reader, position);\n            case 26: return armnnSerializer.ResizeBilinearLayer.decode(reader, position);\n            case 27: return armnnSerializer.SubtractionLayer.decode(reader, position);\n            case 28: return armnnSerializer.StridedSliceLayer.decode(reader, position);\n            case 29: return armnnSerializer.GatherLayer.decode(reader, position);\n            case 30: return armnnSerializer.MeanLayer.decode(reader, position);\n            case 31: return armnnSerializer.MergerLayer.decode(reader, position);\n            case 32: return armnnSerializer.L2NormalizationLayer.decode(reader, position);\n            case 33: return armnnSerializer.SplitterLayer.decode(reader, position);\n            case 34: return armnnSerializer.DetectionPostProcessLayer.decode(reader, position);\n            case 35: return armnnSerializer.LstmLayer.decode(reader, position);\n            case 36: return armnnSerializer.QuantizedLstmLayer.decode(reader, position);\n            case 37: return armnnSerializer.QuantizeLayer.decode(reader, position);\n            case 38: return armnnSerializer.DequantizeLayer.decode(reader, position);\n            case 39: return armnnSerializer.MergeLayer.decode(reader, position);\n            case 40: return armnnSerializer.SwitchLayer.decode(reader, position);\n            case 41: return armnnSerializer.ConcatLayer.decode(reader, position);\n            case 42: return armnnSerializer.SpaceToDepthLayer.decode(reader, position);\n            case 43: return armnnSerializer.PreluLayer.decode(reader, position);\n            case 44: return armnnSerializer.TransposeConvolution2dLayer.decode(reader, position);\n            case 45: return armnnSerializer.ResizeLayer.decode(reader, position);\n            case 46: return armnnSerializer.StackLayer.decode(reader, position);\n            case 47: return armnnSerializer.AbsLayer.decode(reader, position);\n            case 48: return armnnSerializer.ArgMinMaxLayer.decode(reader, position);\n            case 49: return armnnSerializer.SliceLayer.decode(reader, position);\n            case 50: return armnnSerializer.DepthToSpaceLayer.decode(reader, position);\n            case 51: return armnnSerializer.InstanceNormalizationLayer.decode(reader, position);\n            case 52: return armnnSerializer.LogSoftmaxLayer.decode(reader, position);\n            case 53: return armnnSerializer.ComparisonLayer.decode(reader, position);\n            case 54: return armnnSerializer.StandInLayer.decode(reader, position);\n            case 55: return armnnSerializer.ElementwiseUnaryLayer.decode(reader, position);\n            case 56: return armnnSerializer.TransposeLayer.decode(reader, position);\n            case 57: return armnnSerializer.QLstmLayer.decode(reader, position);\n            case 58: return armnnSerializer.FillLayer.decode(reader, position);\n            case 59: return armnnSerializer.RankLayer.decode(reader, position);\n            case 60: return armnnSerializer.LogicalBinaryLayer.decode(reader, position);\n            case 61: return armnnSerializer.ReduceLayer.decode(reader, position);\n            case 62: return armnnSerializer.CastLayer.decode(reader, position);\n            case 63: return armnnSerializer.ShapeLayer.decode(reader, position);\n            case 64: return armnnSerializer.UnidirectionalSequenceLstmLayer.decode(reader, position);\n            case 65: return armnnSerializer.ChannelShuffleLayer.decode(reader, position);\n            case 66: return armnnSerializer.Convolution3dLayer.decode(reader, position);\n            case 67: return armnnSerializer.Pooling3dLayer.decode(reader, position);\n            case 68: return armnnSerializer.GatherNdLayer.decode(reader, position);\n            case 69: return armnnSerializer.BatchMatMulLayer.decode(reader, position);\n            case 70: return armnnSerializer.ElementwiseBinaryLayer.decode(reader, position);\n            case 71: return armnnSerializer.ReverseV2Layer.decode(reader, position);\n            case 72: return armnnSerializer.TileLayer.decode(reader, position);\n            case 73: return armnnSerializer.ScatterNdLayer.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'ActivationLayer': return armnnSerializer.ActivationLayer.decodeText(reader, json);\n            case 'AdditionLayer': return armnnSerializer.AdditionLayer.decodeText(reader, json);\n            case 'BatchToSpaceNdLayer': return armnnSerializer.BatchToSpaceNdLayer.decodeText(reader, json);\n            case 'BatchNormalizationLayer': return armnnSerializer.BatchNormalizationLayer.decodeText(reader, json);\n            case 'ConstantLayer': return armnnSerializer.ConstantLayer.decodeText(reader, json);\n            case 'Convolution2dLayer': return armnnSerializer.Convolution2dLayer.decodeText(reader, json);\n            case 'DepthwiseConvolution2dLayer': return armnnSerializer.DepthwiseConvolution2dLayer.decodeText(reader, json);\n            case 'FullyConnectedLayer': return armnnSerializer.FullyConnectedLayer.decodeText(reader, json);\n            case 'InputLayer': return armnnSerializer.InputLayer.decodeText(reader, json);\n            case 'MultiplicationLayer': return armnnSerializer.MultiplicationLayer.decodeText(reader, json);\n            case 'OutputLayer': return armnnSerializer.OutputLayer.decodeText(reader, json);\n            case 'PermuteLayer': return armnnSerializer.PermuteLayer.decodeText(reader, json);\n            case 'Pooling2dLayer': return armnnSerializer.Pooling2dLayer.decodeText(reader, json);\n            case 'ReshapeLayer': return armnnSerializer.ReshapeLayer.decodeText(reader, json);\n            case 'SoftmaxLayer': return armnnSerializer.SoftmaxLayer.decodeText(reader, json);\n            case 'SpaceToBatchNdLayer': return armnnSerializer.SpaceToBatchNdLayer.decodeText(reader, json);\n            case 'DivisionLayer': return armnnSerializer.DivisionLayer.decodeText(reader, json);\n            case 'MinimumLayer': return armnnSerializer.MinimumLayer.decodeText(reader, json);\n            case 'EqualLayer': return armnnSerializer.EqualLayer.decodeText(reader, json);\n            case 'MaximumLayer': return armnnSerializer.MaximumLayer.decodeText(reader, json);\n            case 'NormalizationLayer': return armnnSerializer.NormalizationLayer.decodeText(reader, json);\n            case 'PadLayer': return armnnSerializer.PadLayer.decodeText(reader, json);\n            case 'RsqrtLayer': return armnnSerializer.RsqrtLayer.decodeText(reader, json);\n            case 'FloorLayer': return armnnSerializer.FloorLayer.decodeText(reader, json);\n            case 'GreaterLayer': return armnnSerializer.GreaterLayer.decodeText(reader, json);\n            case 'ResizeBilinearLayer': return armnnSerializer.ResizeBilinearLayer.decodeText(reader, json);\n            case 'SubtractionLayer': return armnnSerializer.SubtractionLayer.decodeText(reader, json);\n            case 'StridedSliceLayer': return armnnSerializer.StridedSliceLayer.decodeText(reader, json);\n            case 'GatherLayer': return armnnSerializer.GatherLayer.decodeText(reader, json);\n            case 'MeanLayer': return armnnSerializer.MeanLayer.decodeText(reader, json);\n            case 'MergerLayer': return armnnSerializer.MergerLayer.decodeText(reader, json);\n            case 'L2NormalizationLayer': return armnnSerializer.L2NormalizationLayer.decodeText(reader, json);\n            case 'SplitterLayer': return armnnSerializer.SplitterLayer.decodeText(reader, json);\n            case 'DetectionPostProcessLayer': return armnnSerializer.DetectionPostProcessLayer.decodeText(reader, json);\n            case 'LstmLayer': return armnnSerializer.LstmLayer.decodeText(reader, json);\n            case 'QuantizedLstmLayer': return armnnSerializer.QuantizedLstmLayer.decodeText(reader, json);\n            case 'QuantizeLayer': return armnnSerializer.QuantizeLayer.decodeText(reader, json);\n            case 'DequantizeLayer': return armnnSerializer.DequantizeLayer.decodeText(reader, json);\n            case 'MergeLayer': return armnnSerializer.MergeLayer.decodeText(reader, json);\n            case 'SwitchLayer': return armnnSerializer.SwitchLayer.decodeText(reader, json);\n            case 'ConcatLayer': return armnnSerializer.ConcatLayer.decodeText(reader, json);\n            case 'SpaceToDepthLayer': return armnnSerializer.SpaceToDepthLayer.decodeText(reader, json);\n            case 'PreluLayer': return armnnSerializer.PreluLayer.decodeText(reader, json);\n            case 'TransposeConvolution2dLayer': return armnnSerializer.TransposeConvolution2dLayer.decodeText(reader, json);\n            case 'ResizeLayer': return armnnSerializer.ResizeLayer.decodeText(reader, json);\n            case 'StackLayer': return armnnSerializer.StackLayer.decodeText(reader, json);\n            case 'AbsLayer': return armnnSerializer.AbsLayer.decodeText(reader, json);\n            case 'ArgMinMaxLayer': return armnnSerializer.ArgMinMaxLayer.decodeText(reader, json);\n            case 'SliceLayer': return armnnSerializer.SliceLayer.decodeText(reader, json);\n            case 'DepthToSpaceLayer': return armnnSerializer.DepthToSpaceLayer.decodeText(reader, json);\n            case 'InstanceNormalizationLayer': return armnnSerializer.InstanceNormalizationLayer.decodeText(reader, json);\n            case 'LogSoftmaxLayer': return armnnSerializer.LogSoftmaxLayer.decodeText(reader, json);\n            case 'ComparisonLayer': return armnnSerializer.ComparisonLayer.decodeText(reader, json);\n            case 'StandInLayer': return armnnSerializer.StandInLayer.decodeText(reader, json);\n            case 'ElementwiseUnaryLayer': return armnnSerializer.ElementwiseUnaryLayer.decodeText(reader, json);\n            case 'TransposeLayer': return armnnSerializer.TransposeLayer.decodeText(reader, json);\n            case 'QLstmLayer': return armnnSerializer.QLstmLayer.decodeText(reader, json);\n            case 'FillLayer': return armnnSerializer.FillLayer.decodeText(reader, json);\n            case 'RankLayer': return armnnSerializer.RankLayer.decodeText(reader, json);\n            case 'LogicalBinaryLayer': return armnnSerializer.LogicalBinaryLayer.decodeText(reader, json);\n            case 'ReduceLayer': return armnnSerializer.ReduceLayer.decodeText(reader, json);\n            case 'CastLayer': return armnnSerializer.CastLayer.decodeText(reader, json);\n            case 'ShapeLayer': return armnnSerializer.ShapeLayer.decodeText(reader, json);\n            case 'UnidirectionalSequenceLstmLayer': return armnnSerializer.UnidirectionalSequenceLstmLayer.decodeText(reader, json);\n            case 'ChannelShuffleLayer': return armnnSerializer.ChannelShuffleLayer.decodeText(reader, json);\n            case 'Convolution3dLayer': return armnnSerializer.Convolution3dLayer.decodeText(reader, json);\n            case 'Pooling3dLayer': return armnnSerializer.Pooling3dLayer.decodeText(reader, json);\n            case 'GatherNdLayer': return armnnSerializer.GatherNdLayer.decodeText(reader, json);\n            case 'BatchMatMulLayer': return armnnSerializer.BatchMatMulLayer.decodeText(reader, json);\n            case 'ElementwiseBinaryLayer': return armnnSerializer.ElementwiseBinaryLayer.decodeText(reader, json);\n            case 'ReverseV2Layer': return armnnSerializer.ReverseV2Layer.decodeText(reader, json);\n            case 'TileLayer': return armnnSerializer.TileLayer.decodeText(reader, json);\n            case 'ScatterNdLayer': return armnnSerializer.ScatterNdLayer.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\narmnnSerializer.AnyLayer = class AnyLayer {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.AnyLayer();\n        $.layer = reader.union(position, 4, armnnSerializer.Layer);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.AnyLayer();\n        $.layer = armnnSerializer.Layer.decodeText(reader, json.layer, json.layer_type);\n        return $;\n    }\n};\n\narmnnSerializer.FeatureCompatibilityVersions = class FeatureCompatibilityVersions {\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.FeatureCompatibilityVersions();\n        $.bindingIdsScheme = reader.uint32_(position, 4, 0);\n        $.weightsLayoutScheme = reader.uint32_(position, 6, 0);\n        $.constantTensorsAsInputs = reader.uint32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.FeatureCompatibilityVersions();\n        $.bindingIdsScheme = reader.value(json.bindingIdsScheme, 0);\n        $.weightsLayoutScheme = reader.value(json.weightsLayoutScheme, 0);\n        $.constantTensorsAsInputs = reader.value(json.constantTensorsAsInputs, 0);\n        return $;\n    }\n};\n\narmnnSerializer.SerializedGraph = class SerializedGraph {\n\n    static identifier(reader) {\n        return reader.identifier === 'ARMN';\n    }\n\n    static create(reader) {\n        return armnnSerializer.SerializedGraph.decode(reader, reader.root);\n    }\n\n    static createText(reader) {\n        return armnnSerializer.SerializedGraph.decodeText(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new armnnSerializer.SerializedGraph();\n        $.layers = reader.tables(position, 4, armnnSerializer.AnyLayer);\n        $.inputIds = reader.array(position, 6, Int32Array);\n        $.outputIds = reader.array(position, 8, Int32Array);\n        $.featureVersions = reader.table(position, 10, armnnSerializer.FeatureCompatibilityVersions);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new armnnSerializer.SerializedGraph();\n        $.layers = reader.objects(json.layers, armnnSerializer.AnyLayer);\n        $.inputIds = reader.array(json.inputIds, Int32Array);\n        $.outputIds = reader.array(json.outputIds, Int32Array);\n        $.featureVersions = reader.object(json.featureVersions, armnnSerializer.FeatureCompatibilityVersions);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/armnn.js",
    "content": "\nconst armnn = {};\n\narmnn.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        if (extension === 'armnn') {\n            const reader = await context.peek('flatbuffers.binary');\n            if (reader) {\n                return context.set('armnn.flatbuffers', reader);\n            }\n        }\n        if (extension === 'json') {\n            const obj = await context.peek('json');\n            if (obj && obj.layers && obj.inputIds && obj.outputIds) {\n                return context.set('armnn.flatbuffers.json', obj);\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        armnn.schema = await context.require('./armnn-schema');\n        armnn.schema = armnn.schema.armnnSerializer;\n        let model = null;\n        switch (context.type) {\n            case 'armnn.flatbuffers': {\n                try {\n                    const reader = await context.read('flatbuffers.binary');\n                    model = armnn.schema.SerializedGraph.create(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new armnn.Error(`File format is not armnn.SerializedGraph (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            case 'armnn.flatbuffers.json': {\n                try {\n                    const reader = await context.read('flatbuffers.text');\n                    model = armnn.schema.SerializedGraph.createText(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new armnn.Error(`File text format is not armnn.SerializedGraph (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            default: {\n                throw new armnn.Error(`Unsupported Arm NN format '${context.type}'.`);\n            }\n        }\n        const metadata = await context.metadata('armnn-metadata.json');\n        return new armnn.Model(metadata, model);\n    }\n};\n\narmnn.Model = class {\n\n    constructor(metadata, model) {\n        this.format = 'Arm NN';\n        this.modules = [new armnn.Graph(metadata, model)];\n    }\n};\n\narmnn.Graph = class {\n\n    constructor(metadata, graph) {\n        this.name = '';\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const counts = new Map();\n        for (const layer of graph.layers) {\n            const base = armnn.Node.getBase(layer);\n            for (const slot of base.inputSlots) {\n                const name = `${slot.connection.sourceLayerIndex}:${slot.connection.outputSlotIndex}`;\n                counts.set(name, counts.has(name) ? counts.get(name) + 1 : 1);\n            }\n        }\n        const values = new Map();\n        const value = (layerIndex, slotIndex, tensor) => {\n            const name = `${layerIndex}:${slotIndex}`;\n            if (!values.has(name)) {\n                const layer = graph.layers[layerIndex];\n                const base = layerIndex < graph.layers.length ? armnn.Node.getBase(layer) : null;\n                const tensorInfo = base && slotIndex < base.outputSlots.length ? base.outputSlots[slotIndex].tensorInfo : null;\n                values.set(name, new armnn.Value(name, tensorInfo, tensor));\n            }\n            return values.get(name);\n        };\n        const layers = graph.layers.filter((layer) => {\n            const base = armnn.Node.getBase(layer);\n            if (base.layerType === armnn.schema.LayerType.Constant && base.outputSlots.length === 1 && layer.layer.input) {\n                const [slot] = base.outputSlots;\n                const name = `${base.index}:${slot.index}`;\n                if (counts.get(name) === 1) {\n                    const tensor = new armnn.Tensor(layer.layer.input, 'Constant');\n                    value(base.index, slot.index, tensor);\n                    return false;\n                }\n            }\n            return true;\n        });\n        for (const layer of layers) {\n            const base = armnn.Node.getBase(layer);\n            for (const slot of base.inputSlots) {\n                value(slot.connection.sourceLayerIndex, slot.connection.outputSlotIndex);\n            }\n        }\n        for (const layer of layers) {\n            const base = armnn.Node.getBase(layer);\n            switch (base.layerType) {\n                case armnn.schema.LayerType.Input: {\n                    const name = base ? base.layerName : '';\n                    for (const slot of base.outputSlots) {\n                        const argument = new armnn.Argument(name, [value(base.index, slot.index)]);\n                        this.inputs.push(argument);\n                    }\n                    break;\n                }\n                case armnn.schema.LayerType.Output: {\n                    const base = armnn.Node.getBase(layer);\n                    const name = base ? base.layerName : '';\n                    for (const slot of base.inputSlots) {\n                        const argument = new armnn.Argument(name, [value(slot.connection.sourceLayerIndex, slot.connection.outputSlotIndex)]);\n                        this.outputs.push(argument);\n                    }\n                    break;\n                }\n                default:\n                    this.nodes.push(new armnn.Node(metadata, layer, value));\n                    break;\n            }\n        }\n    }\n};\n\narmnn.Node = class {\n\n    constructor(metadata, layer, value) {\n        const name = layer.layer.constructor.name;\n        const type = metadata.type(name);\n        this.type = type ? { ...type } : { name };\n        this.type.name = this.type.name.replace(/Layer$/, '');\n        this.name = '';\n        this.outputs = [];\n        this.inputs = [];\n        this.attributes = [];\n        const inputSchemas = (this.type && this.type.inputs) ? [...this.type.inputs] : [{ name: 'input' }];\n        const outputSchemas = (this.type && this.type.outputs) ? [...this.type.outputs] : [{ name: 'output' }];\n        const base = armnn.Node.getBase(layer);\n        if (base) {\n            this.name = base.layerName;\n            const inputs = [...base.inputSlots];\n            while (inputs.length > 0) {\n                const schema = inputSchemas.length > 0 ? inputSchemas.shift() : { name: '?' };\n                const count = schema.list ? inputs.length : 1;\n                const argument = new armnn.Argument(schema.name, inputs.splice(0, count).map((inputSlot) => {\n                    return value(inputSlot.connection.sourceLayerIndex, inputSlot.connection.outputSlotIndex);\n                }));\n                this.inputs.push(argument);\n            }\n            const outputs = [...base.outputSlots];\n            while (outputs.length > 0) {\n                const schema = outputSchemas.length > 0 ? outputSchemas.shift() : { name: '?' };\n                const count = schema.list ? outputs.length : 1;\n                this.outputs.push(new armnn.Argument(schema.name, outputs.splice(0, count).map((outputSlot) => {\n                    return value(base.index, outputSlot.index);\n                })));\n            }\n        }\n        if (layer.layer) {\n            if (layer.layer.descriptor && this.type.attributes) {\n                for (const [key, obj] of Object.entries(layer.layer.descriptor)) {\n                    const schema = metadata.attribute(name, key);\n                    const type = schema ? schema.type : null;\n                    let value = ArrayBuffer.isView(obj) ? Array.from(obj) : obj;\n                    const enumType = armnn.schema[type];\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                    const attribute = new armnn.Argument(key, value, type);\n                    this.attributes.push(attribute);\n                }\n            }\n            for (const [name, tensor] of Object.entries(layer.layer).filter(([, value]) => value instanceof armnn.schema.ConstTensor)) {\n                const value = new armnn.Value('', tensor.info, new armnn.Tensor(tensor));\n                const argument = new armnn.Argument(name, [value]);\n                this.inputs.push(argument);\n            }\n        }\n    }\n\n    static getBase(layer) {\n        return layer.layer.base.base ? layer.layer.base.base : layer.layer.base;\n    }\n\n    static makeKey(layer_id, index) {\n        return `${layer_id}_${index}`;\n    }\n};\n\narmnn.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\narmnn.Value = class {\n\n    constructor(name, tensorInfo, initializer) {\n        if (typeof name !== 'string') {\n            throw new armnn.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = new armnn.TensorType(tensorInfo);\n        this.initializer = initializer;\n        if (tensorInfo.quantizationScale !== 0 ||\n            tensorInfo.quantizationOffset !== 0 ||\n            tensorInfo.quantizationScales.length > 0 ||\n            tensorInfo.quantizationDim !== 0) {\n            this.quantization = {\n                type: 'linear',\n                dimension: tensorInfo.quantizationDim,\n                scale: [tensorInfo.quantizationScale],\n                offset: [tensorInfo.quantizationOffset]\n            };\n        }\n    }\n};\n\narmnn.Tensor = class {\n\n    constructor(tensor, category = '') {\n        this.type = new armnn.TensorType(tensor.info);\n        this.category = category;\n        const data = tensor.data.data.slice(0);\n        this.values = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n    }\n};\n\narmnn.TensorType = class {\n\n    constructor(tensorInfo) {\n        const dataType = tensorInfo.dataType;\n        switch (dataType) {\n            case 0: this.dataType = 'float16'; break;\n            case 1: this.dataType = 'float32'; break;\n            case 2: this.dataType = 'quint8'; break; // QuantisedAsymm8\n            case 3: this.dataType = 'int32'; break;\n            case 4: this.dataType = 'boolean'; break;\n            case 5: this.dataType = 'qint16'; break; // QuantisedSymm16\n            case 6: this.dataType = 'quint8'; break; // QAsymmU8\n            case 7: this.dataType = 'qint16'; break; // QSymmS16\n            case 8: this.dataType = 'qint8'; break; // QAsymmS8\n            case 9: this.dataType = 'qint8'; break; // QSymmS8\n            default:\n                throw new armnn.Error(`Unsupported data type '${JSON.stringify(dataType)}'.`);\n        }\n        this.shape = new armnn.TensorShape(tensorInfo.dimensions);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\narmnn.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.from(dimensions);\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n    }\n};\n\narmnn.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Arm NN model.';\n    }\n};\n\nexport const ModelFactory = armnn.ModelFactory;\n"
  },
  {
    "path": "source/barracuda.js",
    "content": "\n// Experimental\n\nconst barracuda = {};\n\nbarracuda.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        if (stream && stream.length > 12) {\n            const buffer = stream.peek(12);\n            if (buffer[0] <= 0x20 && buffer.subarray(1, 8).every((value) => value === 0x00)) {\n                return context.set('barracuda');\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = barracuda.Metadata.open();\n        const reader = await context.read('binary');\n        const model = new barracuda.NNModel(reader);\n        return new barracuda.Model(metadata, model);\n    }\n};\n\nbarracuda.Model = class {\n\n    constructor(metadata, model) {\n        const version = model.version.toString();\n        this.format = `Barracuda v${version}`;\n        this.modules = [new barracuda.Graph(metadata, model)];\n    }\n};\n\nbarracuda.Graph = class {\n\n    constructor(metadata, model) {\n        this.name = '';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (!values.has(name)) {\n                type = tensor ? tensor.type : type;\n                values.set(name, new barracuda.Value(name, type, tensor));\n            } else if (type || tensor) {\n                throw new barracuda.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const layers = [];\n        for (const layer of model.layers) {\n            if (layer.type !== 255 || layer.inputs.length > 0) {\n                layers.push(layer);\n            } else {\n                for (const tensor of layer.tensors) {\n                    values.map(tensor.name, null, new barracuda.Tensor(tensor));\n                }\n            }\n        }\n        for (const input of model.inputs) {\n            const shape = new barracuda.TensorShape(input.shape);\n            const type = new barracuda.TensorType(4, shape);\n            const argument = new barracuda.Argument(input.name, [values.map(input.name, type)]);\n            this.inputs.push(argument);\n        }\n        for (const output of model.outputs) {\n            const argument = new barracuda.Argument(output, [values.map(output)]);\n            this.outputs.push(argument);\n        }\n        for (const layer of layers) {\n            const node = new barracuda.Node(metadata, layer, null, values);\n            this.nodes.push(node);\n        }\n    }\n};\n\nbarracuda.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nbarracuda.Value = class {\n\n    constructor(name, type = null, initializer = null) {\n        this.name = name;\n        this.type = type;\n        this.initializer = initializer;\n    }\n};\n\nbarracuda.Node = class {\n\n    constructor(metadata, layer, type, values) {\n        this.name = layer.name || '';\n        this.type = type ? type : metadata.type(layer.type);\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const inputs = Array.prototype.slice.call(this.type.inputs || ['input']);\n        if (this.type.inputs && this.type.inputs.length === 1 && this.type.inputs[0].name === 'inputs') {\n            const argument = new barracuda.Argument('inputs', layer.inputs.map((input) => values.map(input)));\n            this.inputs.push(argument);\n        } else if (layer.inputs) {\n            for (let i = 0; i < layer.inputs.length; i++) {\n                const input = layer.inputs[i];\n                const name = inputs.length > 0 && inputs[0] ? inputs.shift().name : i.toString();\n                const argument = new barracuda.Argument(name, [values.map(input)]);\n                this.inputs.push(argument);\n            }\n        }\n        if (layer.tensors) {\n            for (let i = 0; i < layer.tensors.length; i++) {\n                const tensor = layer.tensors[i];\n                const initializer = new barracuda.Tensor(tensor);\n                const name = inputs.length > 0 && inputs[0] ? inputs.shift().name : i.toString();\n                const argument = new barracuda.Argument(name, [values.map(tensor.name, initializer.type, initializer)]);\n                this.inputs.push(argument);\n            }\n        }\n        if (layer.inputs !== undefined) {\n            const argument = new barracuda.Argument('output', [values.map(this.name)]);\n            this.outputs.push(argument);\n        }\n        if (layer.activation !== undefined && (layer.type === 50 || layer.activation !== 0)) {\n            const type = barracuda.Activation[layer.activation];\n            if (!type) {\n                throw new barracuda.Error(`Unsupported activation '${layer.activation}'.`);\n            }\n            const node = new barracuda.Node(metadata, {}, { name: type, category: 'Activation' }, values);\n            this.chain = [node];\n        }\n        const attributes = [\n            ['strides', 'int32[]', []],\n            ['pads', 'int32[]', (value) => Array.isArray(value) && (value.every((v) => v === 0) || value.every((v) => v === -1))],\n            ['pool_size', 'int32[]', []],\n            ['alpha', 'float32', 1],\n            ['beta', 'float32', 0],\n            ['axis', 'int32', -1]\n        ];\n        for (const [name, type, defaultValue] of attributes) {\n            const value = layer[name];\n            if ((value === undefined) ||\n                (Array.isArray(defaultValue) && Array.isArray(value) && value.length === defaultValue.length && value.every((v, i) => v === defaultValue[i])) ||\n                (typeof defaultValue === 'function' && defaultValue(value)) ||\n                (defaultValue === value)) {\n                continue;\n            }\n            const attribute = new barracuda.Argument(name, value, type);\n            this.attributes.push(attribute);\n        }\n    }\n};\n\nbarracuda.Tensor = class {\n\n    constructor(tensor) {\n        this.type = new barracuda.TensorType(tensor.itemsize, new barracuda.TensorShape(tensor.shape));\n        this.values = tensor.data;\n    }\n};\n\nbarracuda.TensorType = class {\n\n    constructor(itemsize, shape) {\n        switch (itemsize) {\n            case 4: this.dataType = 'float32'; break;\n            default: throw new barracuda.Error(`Unsupported data type size '${itemsize}'.`);\n        }\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nbarracuda.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`) : '';\n    }\n};\n\nbarracuda.NNModel = class {\n\n    constructor(reader) {\n        // https://github.com/Unity-Technologies/barracuda-release/blob/release/1.3.2/Barracuda/Runtime/Core/Model.cs\n        reader = new barracuda.BinaryReader(reader);\n        this.version = reader.int32();\n        reader.int32();\n        this.inputs = new Array(reader.int32());\n        for (let i = 0; i < this.inputs.length; i++) {\n            this.inputs[i] = {\n                name: reader.string(),\n                shape: reader.shape()\n            };\n        }\n        this.outputs = reader.strings();\n        this.memories = new Array(reader.int32());\n        for (let i = 0; i < this.memories.length; i++) {\n            this.memories[i] = {\n                shape: reader.shape(),\n                in: reader.string(),\n                out: reader.string()\n            };\n        }\n        this.layers = new Array(reader.int32());\n        for (let i = 0; i < this.layers.length; i++) {\n            const layer = {};\n            layer.name = reader.string();\n            layer.type = reader.int32();\n            layer.activation = reader.int32();\n            reader.int32();\n            reader.int32();\n            layer.pads = reader.int32s();\n            layer.strides = reader.int32s();\n            layer.pool_size = reader.int32s();\n            layer.axis = reader.int32();\n            layer.alpha = reader.float32();\n            layer.beta = reader.float32();\n            reader.int32();\n            layer.inputs = reader.strings();\n            layer.tensors = [];\n            const tensorsLength = reader.int32();\n            for (let j = 0; j < tensorsLength; j++) {\n                layer.tensors.push({\n                    name: reader.string(),\n                    shape: reader.shape(),\n                    offset: reader.int64().toNumber(),\n                    itemsize: reader.int32(),\n                    length: reader.int32()\n                });\n            }\n            this.layers[i] = layer;\n        }\n        const position = reader.position;\n        for (const layer of this.layers) {\n            for (const tensor of layer.tensors) {\n                const offset = tensor.offset;\n                reader.seek(position + (offset * tensor.itemsize));\n                tensor.data = reader.read(tensor.length * tensor.itemsize);\n            }\n        }\n    }\n};\n\nbarracuda.Activation = {\n    0: \"Linear\", 1: \"Relu\", 2: \"Softmax\", 3: \"Tanh\", 4: \"Sigmoid\", 5: \"Elu\", 6: \"Relu6\", 7: \"LeakyRelu\", 8: \"Selu\", 9: \"Swish\",\n    10: \"LogSoftmax\", 11: \"Softplus\", 12: \"Softsign\", 13: \"PRelu\",\n    20: \"Hardmax\", 21: \"HardSigmoid\",\n    100: \"Abs\", 101: \"Neg\", 102: \"Ceil\", 103: \"Clip\", 104: \"Floor\", 105: \"Round\",\n    110: \"Reciprocal\", 111: \"Sqrt\", 113: \"Exp\", 114: \"Log\",\n    200: \"Acos\", 201: \"Acosh\", 202: \"Asin\", 203: \"Asinh\", 204: \"Atan\", 205: \"Atanh\", 206: \"Cos\", 207: \"Cosh\", 208: \"Sin\", 209: \"Sinh\", 210: \"Tan\"\n};\n\nbarracuda.BinaryReader = class {\n\n    constructor(reader) {\n        this._reader = reader;\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    seek(position) {\n        this._reader.seek(position);\n    }\n\n    skip(offset) {\n        this._reader.skip(offset);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    byte() {\n        return this._reader.byte();\n    }\n\n    int32() {\n        return this._reader.int32();\n    }\n\n    int32s() {\n        const values = new Array(this.int32());\n        for (let i = 0; i < values.length; i++) {\n            values[i] = this.int32();\n        }\n        return values;\n    }\n\n    int64() {\n        return this._reader.int64();\n    }\n\n    float32() {\n        return this._reader.float32();\n    }\n\n    string() {\n        let content = '';\n        const size = this.int32();\n        for (let i = 0; i < size; i++) {\n            const c = this.byte();\n            content += String.fromCharCode(c);\n        }\n        return content;\n    }\n\n    strings() {\n        const values = [];\n        const length = this.int32();\n        for (let i = 0; i < length; i++) {\n            values.push(this.string());\n        }\n        return values;\n    }\n\n    shape() {\n        return this.int32s();\n    }\n};\n\nbarracuda.Metadata = class {\n\n    static open() {\n        barracuda.Metadata._metadata = barracuda.Metadata._metadata || new barracuda.Metadata();\n        return barracuda.Metadata._metadata;\n    }\n\n    constructor() {\n        this._types = new Map();\n        const register = (id, name, category, inputs) => {\n            this._types.set(id, { name, category, inputs: (inputs || []).map((input) => {\n                return { name: input };\n            }) });\n        };\n        register(0, 'Nop', '');\n        register(1, 'Dense', 'Layer', ['input', 'kernel', 'bias']);\n        register(2, 'MatMul', '', ['input', 'kernel', 'bias']);\n        register(20, 'Conv2D', 'Layer', ['input', 'kernel', 'bias']);\n        register(21, 'DepthwiseConv2D', 'Layer', ['input', 'kernel', 'bias']);\n        register(22, 'Conv2DTrans', 'Layer', ['input', 'kernel', 'bias']);\n        register(23, 'Upsample2D', 'Data');\n        register(25, 'MaxPool2D', 'Pool');\n        register(26, 'AvgPool2D', 'Pool');\n        register(27, 'GlobalMaxPool2D', 'Pool');\n        register(28, 'GlobalAvgPool2D', 'Pool');\n        register(29, 'Border2D', '');\n        register(30, 'Conv3D', 'Layer');\n        register(32, 'Conv3DTrans', 'Layer');\n        register(33, 'Upsample3D', 'Data');\n        register(35, 'MaxPool3D', 'Pool');\n        register(36, 'AvgPool3D', 'Pool');\n        register(37, 'GlobalMaxPool3D', 'Pool');\n        register(38, 'GlobalAvgPool3D', 'Pool');\n        register(39, 'Border3D', '');\n        register(50, 'Activation', '', ['input']);\n        register(51, 'ScaleBias', 'Normalization', ['input', 'scale', 'bias']);\n        register(52, 'Normalization', 'Normalization');\n        register(53, 'LRN', 'Normalization');\n        register(60, 'Dropout', 'Dropout');\n        register(64, 'RandomNormal', '');\n        register(65, 'RandomUniform', '');\n        register(66, 'Multinomial', '');\n        register(67, 'OneHot', '');\n        register(68, 'TopKIndices', '');\n        register(69, 'TopKValues', '');\n        register(100, 'Add', '', ['inputs']);\n        register(101, 'Sub', '', ['inputs']);\n        register(102, 'Mul', '', ['inputs']);\n        register(103, 'RealDiv', '', ['inputs']);\n        register(104, 'Pow', '', ['inputs']);\n        register(110, 'Minimum', '', ['inputs']);\n        register(111, 'Maximum', '', ['inputs']);\n        register(112, 'Mean', '', ['inputs']);\n        register(120, 'ReduceL1', '', ['inputs']);\n        register(121, 'ReduceL2', '', ['inputs']);\n        register(122, 'ReduceLogSum', '', ['inputs']);\n        register(123, 'ReduceLogSumExp', '', ['inputs']);\n        register(124, 'ReduceMax', '', ['inputs']);\n        register(125, 'ReduceMean', '', ['inputs']);\n        register(126, 'ReduceMin', '', ['inputs']);\n        register(127, 'ReduceProd', '', ['inputs']);\n        register(128, 'ReduceSum', '', ['inputs']);\n        register(129, 'ReduceSumSquare', '', ['inputs']);\n        register(140, 'Greater', '');\n        register(141, 'GreaterEqual', '');\n        register(142, 'Less', '');\n        register(143, 'LessEqual', '');\n        register(144, 'Equal', '');\n        register(145, 'LogicalOr', '');\n        register(146, 'LogicalAnd', '');\n        register(147, 'LogicalNot', '');\n        register(148, 'LogicalXor', '');\n        register(160, 'Pad2DReflect', '');\n        register(161, 'Pad2DSymmetric', '');\n        register(162, 'Pad2DEdge', '');\n        register(200, 'Flatten', 'Shape');\n        register(201, 'Reshape', 'Shape');\n        register(202, 'Transpose', '');\n        register(203, 'Squeeze', '');\n        register(204, 'Unsqueeze', '');\n        register(205, 'Gather', '');\n        register(206, 'DepthToSpace', '');\n        register(207, 'SpaceToDepth', '');\n        register(208, 'Expand', '');\n        register(209, 'Resample2D', '');\n        register(210, 'Concat', 'Tensor', ['inputs']);\n        register(211, 'StridedSlice', 'Shape');\n        register(212, 'Tile', '');\n        register(213, 'Shape', '');\n        register(214, 'NonMaxSuppression', '');\n        register(215, 'LSTM', '');\n        register(255, 'Load', '');\n    }\n\n    type(name) {\n        if (!this._types.has(name)) {\n            this._types.set(name, { name: name.toString() });\n        }\n        return this._types.get(name);\n    }\n};\n\nbarracuda.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Barracuda model.';\n    }\n};\n\nexport const ModelFactory = barracuda.ModelFactory;\n\n"
  },
  {
    "path": "source/base.js",
    "content": "\nconst base = {};\n\nbase.Complex = class Complex {\n\n    constructor(real, imaginary) {\n        this.real = real;\n        this.imaginary = imaginary;\n    }\n\n    toString(/* radix */) {\n        const sign = this.imaginary < 0 ? '-' : '+';\n        const imaginary = Math.abs(this.imaginary);\n        return `${this.real} ${sign} ${imaginary}i`;\n    }\n};\n\n/* eslint-disable no-extend-native */\n\nBigInt.prototype.toNumber = function() {\n    if (this > Number.MAX_SAFE_INTEGER || this < Number.MIN_SAFE_INTEGER) {\n        throw new Error(`64-bit value 0x${this.toString(16)} exceeds safe integer.`);\n    }\n    return Number(this);\n};\n\nif (!DataView.prototype.getFloat16) {\n    DataView.prototype.getFloat16 = function(byteOffset, littleEndian) {\n        const value = this.getUint16(byteOffset, littleEndian);\n        const e = (value & 0x7C00) >> 10;\n        let f = value & 0x03FF;\n        if (e === 0) {\n            f = 0.00006103515625 * (f / 1024);\n        } else if (e === 0x1F) {\n            f = f ? NaN : Infinity;\n        } else {\n            f = DataView.__float16_pow[e] * (1 + (f / 1024));\n        }\n        return value & 0x8000 ? -f : f;\n    };\n    DataView.__float16_pow = {\n        1: 1 / 16384, 2: 1 / 8192, 3: 1 / 4096, 4: 1 / 2048, 5: 1 / 1024, 6: 1 / 512, 7: 1 / 256, 8: 1 / 128,\n        9: 1 / 64, 10: 1 / 32, 11: 1 / 16, 12: 1 / 8, 13: 1 / 4, 14: 1 / 2, 15: 1, 16: 2,\n        17: 4, 18: 8, 19: 16, 20: 32, 21: 64, 22: 128, 23: 256, 24: 512,\n        25: 1024, 26: 2048, 27: 4096, 28: 8192, 29: 16384, 30: 32768, 31: 65536\n    };\n}\n\nif (!DataView.prototype.setFloat16) {\n    DataView.prototype.setFloat16 = function(byteOffset, value, littleEndian) {\n        DataView.__float16_float[0] = value;\n        [value] = DataView.__float16_int;\n        const s = (value >>> 16) & 0x8000;\n        const e = (value >>> 23) & 0xff;\n        const f = value & 0x7fffff;\n        const v = s | DataView.__float16_base[e] | (f >> DataView.__float16_shift[e]);\n        this.setUint16(byteOffset, v, littleEndian);\n    };\n    DataView.__float16_float = new Float32Array(1);\n    DataView.__float16_int = new Uint32Array(DataView.__float16_float.buffer, 0, DataView.__float16_float.length);\n    DataView.__float16_base = new Uint32Array(256);\n    DataView.__float16_shift = new Uint32Array(256);\n    for (let i = 0; i < 256; ++i) {\n        const e = i - 127;\n        if (e < -27) {\n            DataView.__float16_base[i] = 0x0000;\n            DataView.__float16_shift[i] = 24;\n        } else if (e < -14) {\n            DataView.__float16_base[i] = 0x0400 >> -e - 14;\n            DataView.__float16_shift[i] = -e - 1;\n        } else if (e <= 15) {\n            DataView.__float16_base[i] = e + 15 << 10;\n            DataView.__float16_shift[i] = 13;\n        } else if (e < 128) {\n            DataView.__float16_base[i] = 0x7c00;\n            DataView.__float16_shift[i] = 24;\n        } else {\n            DataView.__float16_base[i] = 0x7c00;\n            DataView.__float16_shift[i] = 13;\n        }\n    }\n}\n\nif (!DataView.prototype.getBfloat16) {\n    DataView.prototype.getBfloat16 = function(byteOffset, littleEndian) {\n        const value = this.getUint16(byteOffset, littleEndian);\n        DataView.__bfloat16_get_u32[0] = (value << 16) >>> 0;\n        return DataView.__bfloat16_get_f32[0];\n    };\n    DataView.__bfloat16_get_f32 = new Float32Array(1);\n    DataView.__bfloat16_get_u32 = new Uint32Array(DataView.__bfloat16_get_f32.buffer);\n}\n\nif (!DataView.prototype.getFloat4e2m1) {\n    DataView.__float4e2m1_float32 = new Float32Array([0, 0.5, 1, 1.5, 2, 3, 4, 6, -0, -0.5, -1, -1.5, -2, -3, -4, -6]);\n    DataView.prototype.getFloat4e2m1 = function(byteOffset) {\n        let value = this.getUint8(byteOffset >> 1);\n        value = byteOffset & 1 ? value >> 4 : value & 0x0F;\n        return DataView.__float4e2m1_float32[value];\n    };\n}\n\nif (!DataView.prototype.getFloat8e4m3) {\n    DataView.__float8e4m3_float32 = new Float32Array(1);\n    DataView.__float8e4m3_uint32 = new Uint32Array(DataView.__float8e4m3_float32.buffer, DataView.__float8e4m3_float32.byteOffset, 1);\n    DataView.prototype.getFloat8e4m3 = function(byteOffset, fn, uz, bias) {\n        const value = this.getUint8(byteOffset);\n        const exponent_bias = bias || (uz ? 8 : 7);\n        if (uz) {\n            if (value === 0x80) {\n                return NaN;\n            }\n        } else if (fn) {\n            if (value === 255) {\n                return -NaN;\n            } else if (value === 0x7f) {\n                return NaN;\n            }\n        } else {\n            const expo = (value & 0x78) >> 3;\n            const mant = value & 0x07;\n            if (expo === 15) {\n                if (mant === 0) {\n                    return (value & 0x80) ? -Infinity : Infinity;\n                }\n                return NaN;\n            }\n        }\n        let expo = (value & 0x78) >> 3;\n        let mant = value & 0x07;\n        const sign = value & 0x80;\n        let res = sign << 24;\n        if (expo === 0) {\n            if (mant > 0) {\n                expo = 0x7F - exponent_bias;\n                if ((mant & 0x4) === 0) {\n                    mant &= 0x3;\n                    mant <<= 1;\n                    expo -= 1;\n                }\n                if ((mant & 0x4) === 0) {\n                    mant &= 0x3;\n                    mant <<= 1;\n                    expo -= 1;\n                }\n                res |= (mant & 0x3) << 21;\n                res |= expo << 23;\n            }\n        } else {\n            res |= mant << 20;\n            expo += 0x7F - exponent_bias;\n            res |= expo << 23;\n        }\n        DataView.__float8e4m3_uint32[0] = res;\n        return DataView.__float8e4m3_float32[0];\n    };\n}\n\nif (!DataView.prototype.getFloat8e5m2) {\n    DataView.__float8e5m2_float32 = new Float32Array(1);\n    DataView.__float8e5m2_uint32 = new Uint32Array(DataView.__float8e5m2_float32.buffer, DataView.__float8e5m2_float32.byteOffset, 1);\n    DataView.prototype.getFloat8e5m2 = function(byteOffset, fn, uz) {\n        const value = this.getUint8(byteOffset);\n        let exponent_bias = NaN;\n        if (fn && uz) {\n            if (value === 0x80) {\n                return NaN;\n            }\n            exponent_bias = 16;\n        } else if (!fn && !uz) {\n            if (value >= 253 && value <= 255) {\n                return -NaN;\n            }\n            if (value >= 126 && value <= 127) {\n                return NaN;\n            }\n            if (value === 252) {\n                return -Infinity;\n            }\n            if (value === 124) {\n                return Infinity;\n            }\n            exponent_bias = 15;\n        }\n        let expo = (value & 0x7C) >> 2;\n        let mant = value & 0x03;\n        let res = (value & 0x80) << 24;\n        if (expo === 0) {\n            if (mant > 0) {\n                expo = 0x7F - exponent_bias;\n                if ((mant & 0x2) === 0) {\n                    mant &= 0x1;\n                    mant <<= 1;\n                    expo -= 1;\n                }\n                res |= (mant & 0x1) << 22;\n                res |= expo << 23;\n            }\n        } else {\n            res |= mant << 21;\n            expo += 0x7F - exponent_bias;\n            res |= expo << 23;\n        }\n        DataView.__float8e5m2_uint32[0] = res;\n        return DataView.__float8e5m2_float32[0];\n    };\n}\n\nif (!DataView.prototype.getFloat8e3m4) {\n    DataView.__float8e3m4_float32 = new Float32Array(1);\n    DataView.__float8e3m4_uint32 = new Uint32Array(DataView.__float8e3m4_float32.buffer, DataView.__float8e3m4_float32.byteOffset, 1);\n    DataView.prototype.getFloat8e3m4 = function(byteOffset) {\n        const value = this.getUint8(byteOffset);\n        const exponent_bias = 3;\n        if (value === 0x7f) {\n            return NaN;\n        }\n        if (value === 0xff) {\n            return -NaN;\n        }\n        let expo = (value & 0x70) >> 4;\n        let mant = value & 0x0F;\n        const sign = value & 0x80;\n        let res = sign << 24;\n        if (expo === 0) {\n            if (mant > 0) {\n                expo = 0x7F - exponent_bias;\n                if ((mant & 0x8) === 0) {\n                    mant &= 0x7;\n                    mant <<= 1;\n                    expo -= 1;\n                }\n                if ((mant & 0x8) === 0) {\n                    mant &= 0x7;\n                    mant <<= 1;\n                    expo -= 1;\n                }\n                if ((mant & 0x8) === 0) {\n                    mant &= 0x7;\n                    mant <<= 1;\n                    expo -= 1;\n                }\n                res |= (mant & 0x7) << 20;\n                res |= expo << 23;\n            }\n        } else {\n            res |= mant << 19;\n            expo += 0x7F - exponent_bias;\n            res |= expo << 23;\n        }\n        DataView.__float8e3m4_uint32[0] = res;\n        return DataView.__float8e3m4_float32[0];\n    };\n}\n\nif (!DataView.prototype.getFloat8e8m0fnu) {\n    DataView.__float8e8m0fnu_float32 = new Float32Array(1);\n    DataView.__float8e8m0fnu_uint32 = new Uint32Array(DataView.__float8e8m0fnu_float32.buffer, DataView.__float8e8m0fnu_float32.byteOffset, 1);\n    DataView.prototype.getFloat8e8m0fnu = function(byteOffset) {\n        const value = this.getUint8(byteOffset);\n        if (value === 255) {\n            return NaN;\n        }\n        DataView.__float8e8m0fnu_uint32[0] = value << 23;\n        return DataView.__float8e8m0fnu_float32[0];\n    };\n}\n\nDataView.prototype.getInt48 = DataView.prototype.getInt48 || function(offset, littleEndian) {\n    let value = 0;\n    if (littleEndian) {\n        const low = this.getUint32(offset, true);\n        const high = this.getUint16(offset + 4, true);\n        value = low + high * 0x100000000;\n    } else {\n        const high = this.getUint16(offset, false);\n        const low = this.getUint32(offset + 2, false);\n        value = high * 0x100000000 + low;\n    }\n    if (value >= 0x800000000000) {\n        value -= 0x1000000000000;\n    }\n    return value;\n};\n\nDataView.prototype.getIntBits = DataView.prototype.getUintBits || function(offset, bits, littleEndian) {\n    offset *= bits;\n    const position = Math.floor(offset / 8);\n    const remainder = offset % 8;\n    let value = 0;\n    if ((remainder + bits) <= 8) {\n        value = littleEndian ? this.getUint8(position) >> remainder : this.getUint8(position) >> (8 - remainder - bits);\n    } else {\n        value = littleEndian ? this.getUint16(position, true) >> remainder : this.getUint16(position, false) >> (16 - remainder - bits);\n    }\n    value &= (1 << bits) - 1;\n    if (value & (1 << (bits - 1))) {\n        value -= 1 << bits;\n    }\n    return value;\n};\n\nDataView.prototype.getUintBits = DataView.prototype.getUintBits || function(offset, bits, littleEndian) {\n    offset *= bits;\n    const position = Math.floor(offset / 8);\n    const remainder = offset % 8;\n    let value = 0;\n    if ((remainder + bits) <= 8) {\n        value = littleEndian ? this.getUint8(position) >> remainder : this.getUint8(position) >> (8 - remainder - bits);\n    } else {\n        value = littleEndian ? this.getUint16(position, true) >> remainder : this.getUint16(position, false) >> (16 - remainder - bits);\n    }\n    return value & ((1 << bits) - 1);\n};\n\nDataView.prototype.getComplexInt32 = DataView.prototype.getComplexInt32 || function(byteOffset, littleEndian) {\n    const real = littleEndian ? this.getInt32(byteOffset, littleEndian) : this.getInt32(byteOffset + 4, littleEndian);\n    const imaginary = littleEndian ? this.getInt32(byteOffset + 4, littleEndian) : this.getInt32(byteOffset, littleEndian);\n    return new base.Complex(real, imaginary);\n};\n\nDataView.prototype.getComplexFloat16 = DataView.prototype.getComplexFloat16 || function(byteOffset, littleEndian) {\n    const real = littleEndian ? this.getFloat16(byteOffset, littleEndian) : this.getFloat16(byteOffset + 2, littleEndian);\n    const imaginary = littleEndian ? this.getFloat16(byteOffset + 2, littleEndian) : this.getFloat16(byteOffset, littleEndian);\n    return new base.Complex(real, imaginary);\n};\n\nDataView.prototype.setComplexFloat16 = DataView.prototype.setComplexFloat16 || function(byteOffset, value, littleEndian) {\n    if (littleEndian) {\n        this.setFloat16(byteOffset, value.real, littleEndian);\n        this.setFloat16(byteOffset + 2, value.imaginary, littleEndian);\n    } else {\n        this.setFloat16(byteOffset + 2, value.real, littleEndian);\n        this.setFloat16(byteOffset, value.imaginary, littleEndian);\n    }\n};\n\nDataView.prototype.getComplexFloat32 = DataView.prototype.getComplexFloat32 || function(byteOffset, littleEndian) {\n    const real = littleEndian ? this.getFloat32(byteOffset, littleEndian) : this.getFloat32(byteOffset + 4, littleEndian);\n    const imaginary = littleEndian ? this.getFloat32(byteOffset + 4, littleEndian) : this.getFloat32(byteOffset, littleEndian);\n    return new base.Complex(real, imaginary);\n};\n\nDataView.prototype.setComplexFloat32 = DataView.prototype.setComplexFloat32 || function(byteOffset, value, littleEndian) {\n    if (littleEndian) {\n        this.setFloat32(byteOffset, value.real, littleEndian);\n        this.setFloat32(byteOffset + 4, value.imaginary, littleEndian);\n    } else {\n        this.setFloat32(byteOffset + 4, value.real, littleEndian);\n        this.setFloat32(byteOffset, value.imaginary, littleEndian);\n    }\n};\n\nDataView.prototype.getComplexFloat64 = DataView.prototype.getComplexFloat64 || function(byteOffset, littleEndian) {\n    const real = littleEndian ? this.getFloat64(byteOffset, littleEndian) : this.getFloat64(byteOffset + 8, littleEndian);\n    const imaginary = littleEndian ? this.getFloat64(byteOffset + 8, littleEndian) : this.getFloat64(byteOffset, littleEndian);\n    return new base.Complex(real, imaginary);\n};\n\nDataView.prototype.setComplexFloat64 = DataView.prototype.setComplexFloat64 || function(byteOffset, value, littleEndian) {\n    if (littleEndian) {\n        this.setFloat64(byteOffset, value.real, littleEndian);\n        this.setFloat64(byteOffset + 8, value.imaginary, littleEndian);\n    } else {\n        this.setFloat64(byteOffset + 8, value.real, littleEndian);\n        this.setFloat64(byteOffset, value.imaginary, littleEndian);\n    }\n};\n\n/* eslint-enable no-extend-native */\n\nbase.BinaryStream = class {\n\n    constructor(buffer) {\n        this._buffer = buffer;\n        this._length = buffer.length;\n        this._position = 0;\n    }\n\n    get position() {\n        return this._position;\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    stream(length) {\n        const buffer = this.read(length);\n        return new base.BinaryStream(buffer.slice(0));\n    }\n\n    seek(position) {\n        this._position = position >= 0 ? position : this._length + position;\n        if (this._position > this._buffer.length || this._position < 0) {\n            throw new Error(`Expected ${this._position - this._buffer.length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position > this._buffer.length || this._position < 0) {\n            throw new Error(`Expected ${this._position - this._buffer.length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    peek(length) {\n        if (this._position === 0 && length === undefined) {\n            return this._buffer;\n        }\n        const position = this._position;\n        this.skip(length === undefined ? this._length - this._position : length);\n        const end = this._position;\n        this.seek(position);\n        return this._buffer.subarray(position, end);\n    }\n\n    read(length) {\n        if (this._position === 0 && length === undefined) {\n            this._position = this._length;\n            return this._buffer;\n        }\n        const position = this._position;\n        this.skip(length === undefined ? this._length - this._position : length);\n        return this._buffer.subarray(position, this._position);\n    }\n};\n\nbase.BinaryReader = class {\n\n    static open(data, littleEndian) {\n        if (data instanceof Uint8Array || data.length <= 0x20000000) {\n            return new base.BufferReader(data, littleEndian);\n        }\n        return new base.StreamReader(data, littleEndian);\n    }\n};\n\nbase.BufferReader = class {\n\n    constructor(data, littleEndian) {\n        this._buffer = data instanceof Uint8Array ? data : data.peek();\n        this._littleEndian = littleEndian !== false;\n        this._position = 0;\n        this._length = this._buffer.length;\n        this._view = new DataView(this._buffer.buffer, this._buffer.byteOffset, this._buffer.byteLength);\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    get position() {\n        return this._position;\n    }\n\n    seek(position) {\n        this._position = position >= 0 ? position : this._length + position;\n        if (this._position > this._length || this._position < 0) {\n            throw new Error(`Expected ${this._position - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position > this._length) {\n            throw new Error(`Expected ${this._position - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    align(size) {\n        const remainder = this.position % size;\n        if (remainder !== 0) {\n            this.skip(size - remainder);\n        }\n    }\n\n    stream(length) {\n        const buffer = this.read(length);\n        return new base.BinaryStream(buffer);\n    }\n\n    peek(length) {\n        if (this._position === 0 && length === undefined) {\n            return this._buffer;\n        }\n        const position = this._position;\n        this.skip(length === undefined ? this._length - this._position : length);\n        const end = this._position;\n        this._position = position;\n        return this._buffer.slice(position, end);\n    }\n\n    read(length) {\n        if (this._position === 0 && length === undefined) {\n            this._position = this._length;\n            return this._buffer;\n        }\n        const position = this._position;\n        this.skip(length === undefined ? this._length - this._position : length);\n        return this._buffer.slice(position, this._position);\n    }\n\n    byte() {\n        const position = this._position;\n        this.skip(1);\n        return this._buffer[position];\n    }\n\n    int8() {\n        const position = this._position;\n        this.skip(1);\n        return this._view.getInt8(position, this._littleEndian);\n    }\n\n    int16() {\n        const position = this._position;\n        this.skip(2);\n        return this._view.getInt16(position, this._littleEndian);\n    }\n\n    int32() {\n        const position = this._position;\n        this.skip(4);\n        return this._view.getInt32(position, this._littleEndian);\n    }\n\n    int64() {\n        const position = this._position;\n        this.skip(8);\n        return this._view.getBigInt64(position, this._littleEndian);\n    }\n\n    uint16() {\n        const position = this._position;\n        this.skip(2);\n        return this._view.getUint16(position, this._littleEndian);\n    }\n\n    uint32() {\n        const position = this._position;\n        this.skip(4);\n        return this._view.getUint32(position, this._littleEndian);\n    }\n\n    uint64() {\n        const position = this._position;\n        this.skip(8);\n        return this._view.getBigUint64(position, this._littleEndian);\n    }\n\n    float32() {\n        const position = this._position;\n        this.skip(4);\n        return this._view.getFloat32(position, this._littleEndian);\n    }\n\n    float64() {\n        const position = this._position;\n        this.skip(8);\n        return this._view.getFloat64(position, this._littleEndian);\n    }\n\n    string() {\n        const length = this.uint32();\n        const position = this._position;\n        this.skip(length);\n        const data = this._buffer.subarray(position, this._position);\n        this._decoder = this._decoder || new TextDecoder('utf-8');\n        return this._decoder.decode(data);\n    }\n\n    boolean() {\n        return this.byte() === 0 ? false : true;\n    }\n};\n\nbase.StreamReader = class {\n\n    constructor(stream, littleEndian) {\n        this._stream = stream;\n        this._littleEndian = littleEndian !== false;\n        this._buffer = new Uint8Array(8);\n        this._view = new DataView(this._buffer.buffer, this._buffer.byteOffset, this._buffer.byteLength);\n    }\n\n    get position() {\n        return this._stream.position;\n    }\n\n    get length() {\n        return this._stream.length;\n    }\n\n    seek(position) {\n        this._stream.seek(position);\n    }\n\n    skip(offset) {\n        this._stream.skip(offset);\n    }\n\n    align(size) {\n        const remainder = this.position % size;\n        if (remainder !== 0) {\n            this.skip(size - remainder);\n        }\n    }\n\n    stream(length) {\n        return this._stream.stream(length);\n    }\n\n    peek(length) {\n        return this._stream.peek(length).slice(0);\n    }\n\n    read(length) {\n        return this._stream.read(length).slice(0);\n    }\n\n    byte() {\n        return this._stream.read(1)[0];\n    }\n\n    int8() {\n        const buffer = this._stream.read(1);\n        this._buffer.set(buffer, 0);\n        return this._view.getInt8(0);\n    }\n\n    int16() {\n        const buffer = this._stream.read(2);\n        this._buffer.set(buffer, 0);\n        return this._view.getInt16(0, this._littleEndian);\n    }\n\n    int32() {\n        const buffer = this._stream.read(4);\n        this._buffer.set(buffer, 0);\n        return this._view.getInt32(0, this._littleEndian);\n    }\n\n    int64() {\n        const buffer = this._stream.read(8);\n        this._buffer.set(buffer, 0);\n        return this._view.getBigInt64(0, this._littleEndian);\n    }\n\n    uint16() {\n        const buffer = this._stream.read(2);\n        this._buffer.set(buffer, 0);\n        return this._view.getUint16(0, this._littleEndian);\n    }\n\n    uint32() {\n        const buffer = this._stream.read(4);\n        this._buffer.set(buffer, 0);\n        return this._view.getUint32(0, this._littleEndian);\n    }\n\n    uint64() {\n        const buffer = this._stream.read(8);\n        this._buffer.set(buffer, 0);\n        return this._view.getBigUint64(0, this._littleEndian);\n    }\n\n    float32() {\n        const buffer = this._stream.read(4);\n        this._buffer.set(buffer, 0);\n        return this._view.getFloat32(0, this._littleEndian);\n    }\n\n    float64() {\n        const buffer = this._stream.read(8);\n        this._buffer.set(buffer, 0);\n        return this._view.getFloat64(0, this._littleEndian);\n    }\n\n    boolean() {\n        return this.byte() === 0 ? false : true;\n    }\n};\n\nbase.Tensor = class {\n\n    constructor(tensor) {\n        this._tensor = tensor;\n        this.name = tensor.name || '';\n        this.encoding = tensor.encoding;\n        this.encoding = this.encoding === '' || this.encoding === undefined ? '<' : this.encoding;\n        this.type = tensor.type;\n        this.layout = tensor.type.layout;\n        this.stride = tensor.stride;\n        base.Tensor._dataTypes = base.Tensor._dataTypes || new Map([\n            ['boolean', 1],\n            ['qint8', 1], ['qint16', 2], ['qint32', 4],\n            ['quint8', 1], ['quint16', 2], ['quint32', 4],\n            ['xint8', 1],\n            ['int8', 1], ['int16', 2], ['int32', 4], ['int48', 6], ['int64', 8], ['int128', 16],\n            ['uint8', 1], ['uint16', 2], ['uint32', 4,], ['uint64', 8],\n            ['float16', 2], ['float32', 4], ['float64', 8], ['bfloat16', 2],\n            ['complex<float32>', 8], ['complex<float64>', 16], ['complex<int32>', 8],\n            ['float8e4m3fn', 1], ['float8e4m3fnuz', 1], ['float8e5m2', 1], ['float8e5m2fnuz', 1], ['float8e4m3b11fnuz', 1], ['float8e3m4', 1], ['float8e4m3', 1], ['float4e2m1fn', 1], ['float6e2m3fn', 1], ['float6e3m2fn', 1], ['float8e8m0fnu', 1]\n        ]);\n    }\n\n    get values() {\n        this._read();\n        return this._values;\n    }\n\n    get indices() {\n        this._read();\n        return this._indices;\n    }\n\n    get data() {\n        this._read();\n        if (this._data && this._data.peek) {\n            this._data = this._data.peek();\n        }\n        return this._data;\n    }\n\n    get metrics() {\n        return this._tensor.metrics;\n    }\n\n    get empty() {\n        switch (this.layout) {\n            case 'sparse':\n            case 'sparse.coo': {\n                return !this.values || !this.indices || this.values.values === null || this.values.values.length === 0;\n            }\n            default: {\n                switch (this.encoding) {\n                    case '<':\n                    case '>':\n                        return !(Array.isArray(this.data) || this.data instanceof Uint8Array || this.data instanceof Int8Array) || this.data.length === 0;\n                    case '|':\n                        return !(Array.isArray(this.values) || ArrayBuffer.isView(this.values)) || this.values.length === 0;\n                    default:\n                        throw new Error(`Unsupported tensor encoding '${this.encoding}'.`);\n                }\n            }\n        }\n    }\n\n    get value() {\n        const context = this._context();\n        context.limit = Number.MAX_SAFE_INTEGER;\n        switch (context.encoding) {\n            case '<':\n            case '>': {\n                return this._decodeData(context, 0, 0);\n            }\n            case '|': {\n                return this._decodeValues(context, 0, 0);\n            }\n            default: {\n                throw new Error(`Unsupported tensor encoding '${context.encoding}'.`);\n            }\n        }\n    }\n\n    toString() {\n        const context = this._context();\n        context.limit = 10000;\n        switch (context.encoding) {\n            case '<':\n            case '>': {\n                const value = this._decodeData(context, 0, 0);\n                return base.Tensor._stringify(value, '', '    ');\n            }\n            case '|': {\n                const value = this._decodeValues(context, 0, 0);\n                return base.Tensor._stringify(value, '', '    ');\n            }\n            default: {\n                throw new Error(`Unsupported tensor encoding '${context.encoding}'.`);\n            }\n        }\n    }\n\n    _context() {\n        this._read();\n        if (this.encoding !== '<' && this.encoding !== '>' && this.encoding !== '|') {\n            throw new Error(`Tensor encoding '${this.encoding}' is not supported.`);\n        }\n        if (this.layout && (this.layout !== 'sparse' && this.layout !== 'sparse.coo')) {\n            throw new Error(`Tensor layout '${this.layout}' is not supported.`);\n        }\n        const dataType = this.type.dataType;\n        const context = {};\n        context.encoding = this.encoding;\n        context.dimensions = this.type.shape.dimensions.map((value) => typeof value === 'bigint' ? value.toNumber() : value);\n        context.dataType = dataType;\n        const shape = context.dimensions;\n        context.stride = this.stride;\n        if (!Array.isArray(context.stride) ||\n            (Array.isArray(context.stride) && context.stride.length === 0 && shape.length === 0)) {\n            const length = shape.length === 0 ? 1 : shape.length;\n            context.stride = new Array(length);\n            let value = 1;\n            for (let i = length - 1; i >= 0; i--) {\n                context.stride[i] = value;\n                value *= shape[i];\n            }\n        }\n        switch (this.layout) {\n            case 'sparse': {\n                const indices = new base.Tensor(this.indices).value;\n                const values = new base.Tensor(this.values).value;\n                context.data = this._decodeSparse(dataType, context.dimensions, indices, values);\n                context.encoding = '|';\n                break;\n            }\n            case 'sparse.coo': {\n                const values = new base.Tensor(this.values).value;\n                const data = new base.Tensor(this.indices).value;\n                const dimensions = context.dimensions.length;\n                let stride = 1;\n                const strides = context.dimensions.slice().reverse().map((dim) => {\n                    const value = stride;\n                    stride *= dim;\n                    return value;\n                }).reverse();\n                const indices = new Uint32Array(values.length);\n                for (let i = 0; i < dimensions; i++) {\n                    const stride = strides[i];\n                    const dimension = data[i];\n                    for (let j = 0; j < indices.length; j++) {\n                        indices[j] += dimension[j].toNumber() * stride;\n                    }\n                }\n                context.data = this._decodeSparse(dataType, context.dimensions, indices, values);\n                context.encoding = '|';\n                break;\n            }\n            default: {\n                switch (this.encoding) {\n                    case '<':\n                    case '>': {\n                        context.data = (this.data instanceof Uint8Array || this.data instanceof Int8Array) ? this.data : this.data.peek();\n                        context.view = new DataView(context.data.buffer, context.data.byteOffset, context.data.byteLength);\n                        if (base.Tensor._dataTypes.has(dataType)) {\n                            const itemsize = base.Tensor._dataTypes.get(dataType);\n                            const length = context.data.length;\n                            const stride = context.stride;\n                            if (length < (itemsize * shape.reduce((a, v) => a * v, 1))) {\n                                const max = stride.reduce((a, v, i) => v > stride[i] ? i : a, 0);\n                                if (length !== (itemsize * stride[max] * shape[max])) {\n                                    throw new Error('Invalid tensor data size.');\n                                }\n                            }\n                            context.itemsize = itemsize;\n                            context.stride = stride.map((v) => v * itemsize);\n                        } else if (dataType.startsWith('uint') && !isNaN(parseInt(dataType.substring(4), 10))) {\n                            context.dataType = 'uint';\n                            context.bits = parseInt(dataType.substring(4), 10);\n                            context.itemsize = 1;\n                        } else if (dataType.startsWith('int') && !isNaN(parseInt(dataType.substring(3), 10))) {\n                            context.dataType = 'int';\n                            context.bits = parseInt(dataType.substring(3), 10);\n                            context.itemsize = 1;\n                        } else if (dataType === 'float4e2m1') {\n                            context.dataType = 'float4e2m1';\n                            context.bits = 4;\n                            context.itemsize = 1;\n                        } else {\n                            throw new Error(`Tensor data type '${dataType}' is not implemented.`);\n                        }\n                        break;\n                    }\n                    case '|': {\n                        context.data = this.values;\n                        const integer = (dataType.startsWith('int') && !isNaN(parseInt(dataType.substring(3), 10))) || (dataType.startsWith('uint') && !isNaN(parseInt(dataType.substring(4), 10)));\n                        if (!base.Tensor._dataTypes.has(dataType) && dataType !== 'string' && dataType !== 'object' && dataType !== 'datetime' && dataType !== 'void' && !integer) {\n                            throw new Error(`Tensor data type '${dataType}' is not implemented.`);\n                        }\n                        const size = context.dimensions.reduce((a, v) => a * v, 1);\n                        if (size !== this.values.length) {\n                            throw new Error('Invalid tensor data length.');\n                        }\n                        break;\n                    }\n                    default: {\n                        throw new Error(`Unsupported tensor encoding '${this.encoding}'.`);\n                    }\n                }\n            }\n        }\n        context.index = 0;\n        context.count = 0;\n        return context;\n    }\n\n    _decodeSparse(dataType, dimensions, indices, values) {\n        const size = dimensions.reduce((a, b) => a * b, 1);\n        const array = new Array(size);\n        switch (dataType) {\n            case 'boolean':\n                array.fill(false);\n                break;\n            default:\n                array.fill(0);\n                break;\n        }\n        if (indices.length > 0) {\n            if (Object.prototype.hasOwnProperty.call(indices[0], 'low')) {\n                for (let i = 0; i < indices.length; i++) {\n                    const index = indices[i].toNumber();\n                    array[index] = values[i];\n                }\n            } else {\n                for (let i = 0; i < indices.length; i++) {\n                    array[indices[i]] = values[i];\n                }\n            }\n        }\n        return array;\n    }\n\n    _decodeData(context, dimension, offset) {\n        const results = [];\n        const shape = context.dimensions.length === 0 ? [1] : context.dimensions;\n        const size = shape[dimension];\n        const dataType = context.dataType;\n        const view = context.view;\n        const stride = context.stride[dimension];\n        if (dimension === shape.length - 1) {\n            const ellipsis = (context.count + size) > context.limit;\n            const length = ellipsis ? context.limit - context.count : size;\n            const max = offset + (length * stride);\n            switch (dataType) {\n                case 'boolean':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getUint8(offset) !== 0);\n                    }\n                    break;\n                case 'qint8':\n                case 'xint8':\n                case 'int8':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getInt8(offset));\n                    }\n                    break;\n                case 'qint16':\n                case 'int16':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getInt16(offset, this._littleEndian));\n                    }\n                    break;\n                case 'qint32':\n                case 'int32':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getInt32(offset, this._littleEndian));\n                    }\n                    break;\n                case 'int48':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getInt48(offset, this._littleEndian));\n                    }\n                    break;\n                case 'int64':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getBigInt64(offset, this._littleEndian));\n                    }\n                    break;\n                case 'int':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getIntBits(offset, context.bits, this._littleEndian));\n                    }\n                    break;\n                case 'quint8':\n                case 'uint8':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getUint8(offset));\n                    }\n                    break;\n                case 'quint16':\n                case 'uint16':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getUint16(offset, this._littleEndian));\n                    }\n                    break;\n                case 'quint32':\n                case 'uint32':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getUint32(offset, this._littleEndian));\n                    }\n                    break;\n                case 'uint64':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getBigUint64(offset, this._littleEndian));\n                    }\n                    break;\n                case 'uint':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getUintBits(offset, context.bits, this._littleEndian));\n                    }\n                    break;\n                case 'float16':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat16(offset, this._littleEndian));\n                    }\n                    break;\n                case 'float32':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat32(offset, this._littleEndian));\n                    }\n                    break;\n                case 'float64':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat64(offset, this._littleEndian));\n                    }\n                    break;\n                case 'bfloat16':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getBfloat16(offset, this._littleEndian));\n                    }\n                    break;\n                case 'complex<int32>':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getComplexInt32(offset, this._littleEndian));\n                    }\n                    break;\n                case 'complex<float16>':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getComplexFloat16(offset, this._littleEndian));\n                    }\n                    break;\n                case 'complex<float32>':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getComplexFloat32(offset, this._littleEndian));\n                    }\n                    break;\n                case 'complex<float64>':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getComplexFloat64(offset, this._littleEndian));\n                    }\n                    break;\n                case 'float4e2m1':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat4e2m1(offset));\n                    }\n                    break;\n                case 'float8e3m4':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e3m4(offset));\n                    }\n                    break;\n                case 'float8e4m3':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e4m3(offset, false, false));\n                    }\n                    break;\n                case 'float8e4m3fn':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e4m3(offset, true, false));\n                    }\n                    break;\n                case 'float8e4m3fnuz':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e4m3(offset, true, true));\n                    }\n                    break;\n                case 'float8e4m3b11fnuz':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e4m3(offset, true, true, 11));\n                    }\n                    break;\n                case 'float8e5m2':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e5m2(offset, false, false));\n                    }\n                    break;\n                case 'float8e5m2fnuz':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e5m2(offset, true, true));\n                    }\n                    break;\n                case 'float8e8m0fnu':\n                    for (; offset < max; offset += stride) {\n                        results.push(view.getFloat8e8m0fnu(offset));\n                    }\n                    break;\n                default:\n                    throw new Error(`Unsupported tensor data type '${dataType}'.`);\n            }\n            context.count += length;\n            if (ellipsis) {\n                results.push('...');\n            }\n        } else {\n            for (let j = 0; j < size; j++) {\n                if (context.count >= context.limit) {\n                    results.push('...');\n                    return results;\n                }\n                const nextOffset = offset + (j * stride);\n                results.push(this._decodeData(context, dimension + 1, nextOffset));\n            }\n        }\n        if (context.dimensions.length === 0) {\n            return results[0];\n        }\n        return results;\n    }\n\n    _decodeValues(context, dimension, position) {\n        const results = [];\n        const shape = (context.dimensions.length === 0) ? [1] : context.dimensions;\n        const size = shape[dimension];\n        const dataType = context.dataType;\n        const stride = context.stride[dimension];\n        if (dimension === shape.length - 1) {\n            const ellipsis = (context.count + size) > context.limit;\n            const length = ellipsis ? context.limit - context.count : size;\n            const data = context.data;\n            for (let i = 0; i < length; i++) {\n                if (context.count > context.limit) {\n                    results.push('...');\n                    return results;\n                }\n                switch (dataType) {\n                    case 'boolean':\n                        results.push(data[position] === 0 || data[position] === false ? false : true);\n                        break;\n                    default:\n                        results.push(data[position]);\n                        break;\n                }\n                position += stride;\n                context.count++;\n            }\n        } else {\n            for (let i = 0; i < size; i++) {\n                if (context.count >= context.limit) {\n                    results.push('...');\n                    return results;\n                }\n                const nextPosition = position + (i * stride);\n                results.push(this._decodeValues(context, dimension + 1, nextPosition));\n            }\n        }\n        if (context.dimensions.length === 0) {\n            return results[0];\n        }\n        return results;\n    }\n\n    static _stringify(value, indentation, indent) {\n        if (Array.isArray(value)) {\n            const length = value.length;\n            if (length > 0) {\n                const array = new Array(length);\n                const space = indentation + indent;\n                for (let i = 0; i < length; i++) {\n                    array[i] = base.Tensor._stringify(value[i], space, indent);\n                }\n                return `${indentation}[\\n${array.join(',\\n')}\\n${indentation}]`;\n            }\n            return `${indentation}[\\n${indentation}]`;\n        }\n        if (value === null) {\n            return `${indentation}null`;\n        }\n        switch (typeof value) {\n            case 'boolean':\n            case 'number':\n            case 'bigint':\n                return `${indentation}${value}`;\n            case 'string':\n                return `${indentation}\"${value}\"`;\n            default:\n                if (value instanceof Uint8Array) {\n                    let content = '';\n                    for (let i = 0; i < value.length; i++) {\n                        const x = value[i];\n                        content += x >= 32 && x <= 126 ? String.fromCharCode(x) : `\\\\x${x.toString(16).padStart(2, '0')}`;\n                    }\n                    return `${indentation}\"${content}\"`;\n                }\n                if (value && value.toString) {\n                    return `${indentation}${value.toString()}`;\n                }\n                return `${indentation}(undefined)`;\n        }\n    }\n\n    _read() {\n        if (this._values === undefined) {\n            this._values = null;\n            switch (this.encoding) {\n                case undefined:\n                case '<': {\n                    this._data = this._tensor.values;\n                    this._littleEndian = true;\n                    break;\n                }\n                case '>': {\n                    this._data = this._tensor.values;\n                    this._littleEndian = false;\n                    break;\n                }\n                case '|': {\n                    this._values = this._tensor.values;\n                    break;\n                }\n                default: {\n                    throw new Error(`Unsupported tensor encoding '${this.encoding}'.`);\n                }\n            }\n            switch (this.layout) {\n                case 'sparse':\n                case 'sparse.coo': {\n                    this._indices = this._tensor.indices;\n                    this._values = this._tensor.values;\n                    break;\n                }\n                default: {\n                    break;\n                }\n            }\n        }\n    }\n};\n\nbase.Telemetry = class {\n\n    constructor(window) {\n        this._window = window;\n        this._navigator = window.navigator;\n        this._config = new Map();\n        this._metadata = {};\n        this._schema = new Map([\n            ['protocol_version', 'v'],\n            ['tracking_id', 'tid'],\n            ['hash_info', 'gtm'],\n            ['_page_id', '_p'],\n            ['client_id', 'cid'],\n            ['language', 'ul'],\n            ['screen_resolution', 'sr'],\n            ['_user_agent_architecture', 'uaa'],\n            ['_user_agent_bitness', 'uab'],\n            ['_user_agent_full_version_list', 'uafvl'],\n            ['_user_agent_mobile', 'uamb'],\n            ['_user_agent_model', 'uam'],\n            ['_user_agent_platform', 'uap'],\n            ['_user_agent_platform_version', 'uapv'],\n            ['_user_agent_wow64', 'uaw'],\n            ['hit_count', '_s'],\n            ['session_id', 'sid'],\n            ['session_number', 'sct'],\n            ['session_engaged', 'seg'],\n            ['engagement_time_msec', '_et'],\n            ['page_location', 'dl'],\n            ['page_title', 'dt'],\n            ['page_referrer', 'dr'],\n            ['is_first_visit', '_fv'],\n            ['is_external_event', '_ee'],\n            ['is_new_to_site', '_nsi'],\n            ['is_session_start', '_ss'],\n            ['event_name', 'en']\n        ]);\n    }\n\n    async start(measurement_id, client_id, session) {\n        this._session = session && typeof session === 'string' ? session.replace(/^GS1\\.1\\./, '').split('.') : null;\n        this._session = Array.isArray(this._session) && this._session.length >= 7 ? this._session : ['0', '0', '0', '0', '0', '0', '0'];\n        this._session[0] = Date.now();\n        this._session[1] = parseInt(this._session[1], 10) + 1;\n        this._engagement_time_msec = 0;\n        if (this._config.size > 0) {\n            throw new Error('Invalid session state.');\n        }\n        this.set('protocol_version', 2);\n        this.set('tracking_id', measurement_id);\n        this.set('hash_info', '2oebu0');\n        this.set('_page_id', Math.floor(Math.random() * 2147483648));\n        client_id = client_id ? client_id.replace(/^(GA1\\.\\d\\.)*/, '') : null;\n        if (client_id && client_id.indexOf('.') !== 1) {\n            this.set('client_id', client_id);\n        } else {\n            const random = String(Math.round(0x7FFFFFFF * Math.random()));\n            const time = Date.now();\n            const value = [random, Math.round(time / 1e3)].join('.');\n            this.set('client_id', value);\n            this._metadata.is_first_visit = 1;\n            this._metadata.is_new_to_site = 1;\n        }\n        this.set('language', ((this._navigator && (this._navigator.language || this._navigator.browserLanguage)) || '').toLowerCase());\n        this.set('screen_resolution', `${window.screen ? window.screen.width : 0}x${window.screen ? window.screen.height : 0}`);\n        if (this._navigator && this._navigator.userAgentData && this._navigator.userAgentData.getHighEntropyValues) {\n            const values = await this._navigator.userAgentData.getHighEntropyValues(['platform', 'platformVersion', 'architecture', 'model', 'uaFullVersion', 'bitness', 'fullVersionList', 'wow64']);\n            if (values) {\n                this.set('_user_agent_architecture', values.architecture);\n                this.set('_user_agent_bitness', values.bitness);\n                this.set('_user_agent_full_version_list', Array.isArray(values.fullVersionList) ? values.fullVersionList.map((h) => `${encodeURIComponent(h.brand || '')};${encodeURIComponent(h.version || '')}`).join('|') : '');\n                this.set('_user_agent_mobile', values.mobile ? 1 : 0);\n                this.set('_user_agent_model', values.model);\n                this.set('_user_agent_platform', values.platform);\n                this.set('_user_agent_platform_version', values.platformVersion);\n                this.set('_user_agent_wow64', values.wow64 ? 1 : 0);\n            }\n        }\n        this.set('hit_count', 1);\n        this.set('session_id', this._session[0]);\n        this.set('session_number', this._session[1]);\n        this.set('session_engaged', 0);\n        this._metadata.is_session_start = 1;\n        this._metadata.is_external_event = 1;\n        window.addEventListener('focus', () => this._update(true, undefined, undefined));\n        window.addEventListener('blur', () => this._update(false, undefined, undefined));\n        window.addEventListener('pageshow', () => this._update(undefined, true, undefined));\n        window.addEventListener('pagehide', () => this._update(undefined, false, undefined));\n        window.addEventListener('visibilitychange', () => this._update(undefined, undefined, window.document.visibilityState !== 'hidden'));\n        window.addEventListener('beforeunload', () => this._update() && this.send('user_engagement', {}));\n    }\n\n    get session() {\n        return this._session ? this._session.join('.') : null;\n    }\n\n    set(name, value) {\n        const key = this._schema.get(name);\n        if (value !== undefined && value !== null) {\n            this._config.set(key, value);\n        } else if (this._config.has(key)) {\n            this._config.delete(key);\n        }\n        this._cache = null;\n    }\n\n    get(name) {\n        const key = this._schema.get(name);\n        return this._config.get(key);\n    }\n\n    send(name, params) {\n        if (this._session) {\n            try {\n                params = { event_name: name, ...this._metadata, ...params };\n                this._metadata = {};\n                if (this._update()) {\n                    params.engagement_time_msec = this._engagement_time_msec;\n                    this._engagement_time_msec = 0;\n                }\n                const build = (entries) => entries.map(([name, value]) => `${name}=${encodeURIComponent(value)}`).join('&');\n                this._cache = this._cache || build(Array.from(this._config));\n                const key = (name, value) => this._schema.get(name) || (typeof value === 'number' && !isNaN(value) ? 'epn.' : 'ep.') + name;\n                const body = build(Object.entries(params).map(([name, value]) => [key(name, value), value]));\n                const url = `https://analytics.google.com/g/collect?${this._cache}`;\n                this._navigator.sendBeacon(url, body);\n                this._session[2] = this.get('session_engaged') || '0';\n                this.set('hit_count', this.get('hit_count') + 1);\n            } catch {\n                // continue regardless of error\n            }\n        }\n    }\n\n    _update(focused, page, visible) {\n        this._focused = focused === true || focused === false ? focused : this._focused;\n        this._page = page === true || page === false ? page : this._page;\n        this._visible = visible === true || visible === false ? visible : this._visible;\n        const time = Date.now();\n        if (this._start_time) {\n            this._engagement_time_msec += (time - this._start_time);\n            this._start_time = 0;\n        }\n        if (this._focused !== false && this._page !== false && this._visible !== false) {\n            this._start_time = time;\n        }\n        return this._engagement_time_msec > 20;\n    }\n};\n\nbase.Metadata = class {\n\n    get extensions() {\n        return [\n            'onnx', 'tflite', 'pb', 'pt', 'pt2', 'pte', 'pth', 'h5', 'pbtxt', 'prototxt', 'caffemodel', 'mlmodel', 'mlpackage',\n            'model', 'json', 'xml', 'cfg', 'weights', 'bin',\n            'ort',\n            'dnn', 'cmf',\n            'gguf',\n            'hd5', 'hdf5', 'keras',\n            'tfl', 'circle', 'lite',\n            'mlir', 'mlirbc', 'mlnet', 'mar', 'maxviz', 'meta', 'nn', 'ngf', 'hn',\n            'param', 'params',\n            'paddle', 'pdiparams', 'pdmodel', 'pdopt', 'pdparams', 'nb',\n            'pkl', 'pickle', 'joblib', 'safetensors',\n            'ptl', 't7',\n            'dlc', 'uff', 'armnn', 'kann', 'kgraph', 'tosa',\n            'mnn', 'ms', 'ncnn', 'om', 'tm', 'mge', 'tmfile', 'tnnproto', 'xmodel', 'kmodel', 'rknn', 'espdl',\n            'tar', 'zip'\n        ];\n    }\n};\n\nexport const Complex = base.Complex;\nexport const BinaryStream = base.BinaryStream;\nexport const BinaryReader = base.BinaryReader;\nexport const Tensor = base.Tensor;\nexport const Telemetry = base.Telemetry;\nexport const Metadata = base.Metadata;\n"
  },
  {
    "path": "source/bigdl-metadata.json",
    "content": "[\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.Dropout\",\n    \"category\": \"Dropout\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.InferReshape\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.JoinTable\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"list\": true }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.Linear\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.NormalizeScale\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"w\" }\n    ]\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.ReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Scale\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"SoftMax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.SpatialAveragePooling\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.SpatialBatchNormalization\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.quantized.SpatialConvolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.SpatialCrossMapLRN\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.SpatialDilatedConvolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.SpatialMaxPooling\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.Transpose\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"com.intel.analytics.bigdl.nn.View\"\n  }\n]"
  },
  {
    "path": "source/bigdl-proto.js",
    "content": "\nexport const com = {};\nexport const google = {};\n\ncom.intel = {};\n\ncom.intel.analytics = {};\n\ncom.intel.analytics.bigdl = {};\n\ncom.intel.analytics.bigdl.serialization = {};\n\ncom.intel.analytics.bigdl.serialization.BigDLModule = class BigDLModule {\n\n    constructor() {\n        this.subModules = [];\n        this.preModules = [];\n        this.nextModules = [];\n        this.attr = {};\n        this.parameters = [];\n        this.inputScales = [];\n        this.outputScales = [];\n        this.weightScales = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.BigDLModule();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.subModules.push(com.intel.analytics.bigdl.serialization.BigDLModule.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.weight = com.intel.analytics.bigdl.serialization.BigDLTensor.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.bias = com.intel.analytics.bigdl.serialization.BigDLTensor.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.preModules.push(reader.string());\n                    break;\n                case 6:\n                    message.nextModules.push(reader.string());\n                    break;\n                case 7:\n                    message.moduleType = reader.string();\n                    break;\n                case 8:\n                    reader.entry(message.attr, () => reader.string(), () => com.intel.analytics.bigdl.serialization.AttrValue.decode(reader, reader.uint32()));\n                    break;\n                case 9:\n                    message.version = reader.string();\n                    break;\n                case 10:\n                    message.train = reader.bool();\n                    break;\n                case 11:\n                    message.namePostfix = reader.string();\n                    break;\n                case 12:\n                    message.id = reader.int32();\n                    break;\n                case 13:\n                    message.inputShape = com.intel.analytics.bigdl.serialization.Shape.decode(reader, reader.uint32());\n                    break;\n                case 14:\n                    message.outputShape = com.intel.analytics.bigdl.serialization.Shape.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.hasParameters = reader.bool();\n                    break;\n                case 16:\n                    message.parameters.push(com.intel.analytics.bigdl.serialization.BigDLTensor.decode(reader, reader.uint32()));\n                    break;\n                case 17:\n                    message.isMklInt8Enabled = reader.bool();\n                    break;\n                case 18:\n                    message.inputDimMasks = reader.int32();\n                    break;\n                case 19:\n                    message.inputScales.push(com.intel.analytics.bigdl.serialization.AttrValue.decode(reader, reader.uint32()));\n                    break;\n                case 20:\n                    message.outputDimMasks = reader.int32();\n                    break;\n                case 21:\n                    message.outputScales.push(com.intel.analytics.bigdl.serialization.AttrValue.decode(reader, reader.uint32()));\n                    break;\n                case 22:\n                    message.weightDimMasks = reader.int32();\n                    break;\n                case 23:\n                    message.weightScales.push(com.intel.analytics.bigdl.serialization.AttrValue.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.name = \"\";\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.weight = null;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.bias = null;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.moduleType = \"\";\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.version = \"\";\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.train = false;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.namePostfix = \"\";\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.id = 0;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.inputShape = null;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.outputShape = null;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.hasParameters = false;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.isMklInt8Enabled = false;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.inputDimMasks = 0;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.outputDimMasks = 0;\ncom.intel.analytics.bigdl.serialization.BigDLModule.prototype.weightDimMasks = 0;\n\ncom.intel.analytics.bigdl.serialization.VarFormat = {\n    \"EMPTY_FORMAT\": 0,\n    \"DEFAULT\": 1,\n    \"ONE_D\": 2,\n    \"IN_OUT\": 3,\n    \"OUT_IN\": 4,\n    \"IN_OUT_KW_KH\": 5,\n    \"OUT_IN_KW_KH\": 6,\n    \"GP_OUT_IN_KW_KH\": 7,\n    \"GP_IN_OUT_KW_KH\": 8,\n    \"OUT_IN_KT_KH_KW\": 9\n};\n\ncom.intel.analytics.bigdl.serialization.InitMethodType = {\n    \"EMPTY_INITIALIZATION\": 0,\n    \"RANDOM_UNIFORM\": 1,\n    \"RANDOM_UNIFORM_PARAM\": 2,\n    \"RANDOM_NORMAL\": 3,\n    \"ZEROS\": 4,\n    \"ONES\": 5,\n    \"CONST\": 6,\n    \"XAVIER\": 7,\n    \"BILINEARFILLER\": 8\n};\n\ncom.intel.analytics.bigdl.serialization.RegularizerType = {\n    \"L1L2Regularizer\": 0,\n    \"L1Regularizer\": 1,\n    \"L2Regularizer\": 2\n};\n\ncom.intel.analytics.bigdl.serialization.InputDataFormat = {\n    \"NCHW\": 0,\n    \"NHWC\": 1\n};\n\ncom.intel.analytics.bigdl.serialization.TensorType = {\n    \"DENSE\": 0,\n    \"QUANT\": 1\n};\n\ncom.intel.analytics.bigdl.serialization.InitMethod = class InitMethod {\n\n    constructor() {\n        this.data = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.InitMethod();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.methodType = reader.int32();\n                    break;\n                case 2:\n                    message.data = reader.doubles(message.data, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.InitMethod.prototype.methodType = 0;\n\ncom.intel.analytics.bigdl.serialization.BigDLTensor = class BigDLTensor {\n\n    constructor() {\n        this.size = [];\n        this.stride = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.BigDLTensor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.datatype = reader.int32();\n                    break;\n                case 2:\n                    message.size = reader.array(message.size, () => reader.int32(), tag);\n                    break;\n                case 3:\n                    message.stride = reader.array(message.stride, () => reader.int32(), tag);\n                    break;\n                case 4:\n                    message.offset = reader.int32();\n                    break;\n                case 5:\n                    message.dimension = reader.int32();\n                    break;\n                case 6:\n                    message.nElements = reader.int32();\n                    break;\n                case 7:\n                    message.isScalar = reader.bool();\n                    break;\n                case 8:\n                    message.storage = com.intel.analytics.bigdl.serialization.TensorStorage.decode(reader, reader.uint32());\n                    break;\n                case 9:\n                    message.id = reader.int32();\n                    break;\n                case 10:\n                    message.tensorType = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.datatype = 0;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.offset = 0;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.dimension = 0;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.nElements = 0;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.isScalar = false;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.storage = null;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.id = 0;\ncom.intel.analytics.bigdl.serialization.BigDLTensor.prototype.tensorType = 0;\n\ncom.intel.analytics.bigdl.serialization.TensorStorage = class TensorStorage {\n\n    constructor() {\n        this.float_data = [];\n        this.double_data = [];\n        this.bool_data = [];\n        this.string_data = [];\n        this.int_data = [];\n        this.long_data = [];\n        this.bytes_data = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.TensorStorage();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.datatype = reader.int32();\n                    break;\n                case 2:\n                    message.float_data = reader.floats(message.float_data, tag);\n                    break;\n                case 3:\n                    message.double_data = reader.doubles(message.double_data, tag);\n                    break;\n                case 4:\n                    message.bool_data = reader.array(message.bool_data, () => reader.bool(), tag);\n                    break;\n                case 5:\n                    message.string_data.push(reader.string());\n                    break;\n                case 6:\n                    message.int_data = reader.array(message.int_data, () => reader.int32(), tag);\n                    break;\n                case 7:\n                    message.long_data = reader.array(message.long_data, () => reader.int64(), tag);\n                    break;\n                case 8:\n                    message.bytes_data.push(reader.bytes());\n                    break;\n                case 9:\n                    message.id = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.TensorStorage.prototype.datatype = 0;\ncom.intel.analytics.bigdl.serialization.TensorStorage.prototype.id = 0;\n\ncom.intel.analytics.bigdl.serialization.Regularizer = class Regularizer {\n\n    constructor() {\n        this.regularData = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.Regularizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.regularizerType = reader.int32();\n                    break;\n                case 2:\n                    message.regularData = reader.doubles(message.regularData, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.Regularizer.prototype.regularizerType = 0;\n\ncom.intel.analytics.bigdl.serialization.DataType = {\n    \"INT32\": 0,\n    \"INT64\": 1,\n    \"FLOAT\": 2,\n    \"DOUBLE\": 3,\n    \"STRING\": 4,\n    \"BOOL\": 5,\n    \"CHAR\": 6,\n    \"SHORT\": 7,\n    \"BYTES\": 8,\n    \"REGULARIZER\": 9,\n    \"TENSOR\": 10,\n    \"VARIABLE_FORMAT\": 11,\n    \"INITMETHOD\": 12,\n    \"MODULE\": 13,\n    \"NAME_ATTR_LIST\": 14,\n    \"ARRAY_VALUE\": 15,\n    \"DATA_FORMAT\": 16,\n    \"CUSTOM\": 17,\n    \"SHAPE\": 18\n};\n\ncom.intel.analytics.bigdl.serialization.AttrValue = class AttrValue {\n\n    get value() {\n        com.intel.analytics.bigdl.serialization.AttrValue.valueSet = com.intel.analytics.bigdl.serialization.AttrValue.valueSet || new Set([\"int32Value\", \"int64Value\", \"floatValue\", \"doubleValue\", \"stringValue\", \"boolValue\", \"regularizerValue\", \"tensorValue\", \"variableFormatValue\", \"initMethodValue\", \"bigDLModuleValue\", \"nameAttrListValue\", \"arrayValue\", \"dataFormatValue\", \"customValue\", \"shape\"]);\n        return Object.keys(this).find((key) => com.intel.analytics.bigdl.serialization.AttrValue.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.AttrValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dataType = reader.int32();\n                    break;\n                case 2:\n                    message.subType = reader.string();\n                    break;\n                case 3:\n                    message.int32Value = reader.int32();\n                    break;\n                case 4:\n                    message.int64Value = reader.int64();\n                    break;\n                case 5:\n                    message.floatValue = reader.float();\n                    break;\n                case 6:\n                    message.doubleValue = reader.double();\n                    break;\n                case 7:\n                    message.stringValue = reader.string();\n                    break;\n                case 8:\n                    message.boolValue = reader.bool();\n                    break;\n                case 9:\n                    message.regularizerValue = com.intel.analytics.bigdl.serialization.Regularizer.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.tensorValue = com.intel.analytics.bigdl.serialization.BigDLTensor.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.variableFormatValue = reader.int32();\n                    break;\n                case 12:\n                    message.initMethodValue = com.intel.analytics.bigdl.serialization.InitMethod.decode(reader, reader.uint32());\n                    break;\n                case 13:\n                    message.bigDLModuleValue = com.intel.analytics.bigdl.serialization.BigDLModule.decode(reader, reader.uint32());\n                    break;\n                case 14:\n                    message.nameAttrListValue = com.intel.analytics.bigdl.serialization.NameAttrList.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.arrayValue = com.intel.analytics.bigdl.serialization.AttrValue.ArrayValue.decode(reader, reader.uint32());\n                    break;\n                case 16:\n                    message.dataFormatValue = reader.int32();\n                    break;\n                case 17:\n                    message.customValue = google.protobuf.Any.decode(reader, reader.uint32());\n                    break;\n                case 18:\n                    message.shape = com.intel.analytics.bigdl.serialization.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.AttrValue.prototype.dataType = 0;\ncom.intel.analytics.bigdl.serialization.AttrValue.prototype.subType = \"\";\n\ncom.intel.analytics.bigdl.serialization.AttrValue.ArrayValue = class ArrayValue {\n\n    constructor() {\n        this.i32 = [];\n        this.i64 = [];\n        this.flt = [];\n        this.dbl = [];\n        this.str = [];\n        this.boolean = [];\n        this.Regularizer = [];\n        this.tensor = [];\n        this.variableFormat = [];\n        this.initMethod = [];\n        this.bigDLModule = [];\n        this.nameAttrList = [];\n        this.dataFormat = [];\n        this.custom = [];\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.AttrValue.ArrayValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.size = reader.int32();\n                    break;\n                case 2:\n                    message.datatype = reader.int32();\n                    break;\n                case 3:\n                    message.i32 = reader.array(message.i32, () => reader.int32(), tag);\n                    break;\n                case 4:\n                    message.i64 = reader.array(message.i64, () => reader.int64(), tag);\n                    break;\n                case 5:\n                    message.flt = reader.floats(message.flt, tag);\n                    break;\n                case 6:\n                    message.dbl = reader.doubles(message.dbl, tag);\n                    break;\n                case 7:\n                    message.str.push(reader.string());\n                    break;\n                case 8:\n                    message.boolean = reader.array(message.boolean, () => reader.bool(), tag);\n                    break;\n                case 9:\n                    message.Regularizer.push(com.intel.analytics.bigdl.serialization.Regularizer.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.tensor.push(com.intel.analytics.bigdl.serialization.BigDLTensor.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    message.variableFormat = reader.array(message.variableFormat, () => reader.int32(), tag);\n                    break;\n                case 12:\n                    message.initMethod.push(com.intel.analytics.bigdl.serialization.InitMethod.decode(reader, reader.uint32()));\n                    break;\n                case 13:\n                    message.bigDLModule.push(com.intel.analytics.bigdl.serialization.BigDLModule.decode(reader, reader.uint32()));\n                    break;\n                case 14:\n                    message.nameAttrList.push(com.intel.analytics.bigdl.serialization.NameAttrList.decode(reader, reader.uint32()));\n                    break;\n                case 15:\n                    message.dataFormat = reader.array(message.dataFormat, () => reader.int32(), tag);\n                    break;\n                case 16:\n                    message.custom.push(google.protobuf.Any.decode(reader, reader.uint32()));\n                    break;\n                case 17:\n                    message.shape.push(com.intel.analytics.bigdl.serialization.Shape.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.AttrValue.ArrayValue.prototype.size = 0;\ncom.intel.analytics.bigdl.serialization.AttrValue.ArrayValue.prototype.datatype = 0;\n\ncom.intel.analytics.bigdl.serialization.NameAttrList = class NameAttrList {\n\n    constructor() {\n        this.attr = {};\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.NameAttrList();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    reader.entry(message.attr, () => reader.string(), () => com.intel.analytics.bigdl.serialization.AttrValue.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.NameAttrList.prototype.name = \"\";\n\ncom.intel.analytics.bigdl.serialization.Shape = class Shape {\n\n    constructor() {\n        this.shapeValue = [];\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new com.intel.analytics.bigdl.serialization.Shape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shapeType = reader.int32();\n                    break;\n                case 2:\n                    message.ssize = reader.int32();\n                    break;\n                case 3:\n                    message.shapeValue = reader.array(message.shapeValue, () => reader.int32(), tag);\n                    break;\n                case 4:\n                    message.shape.push(com.intel.analytics.bigdl.serialization.Shape.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncom.intel.analytics.bigdl.serialization.Shape.prototype.shapeType = 0;\ncom.intel.analytics.bigdl.serialization.Shape.prototype.ssize = 0;\n\ncom.intel.analytics.bigdl.serialization.Shape.ShapeType = {\n    \"SINGLE\": 0,\n    \"MULTI\": 1\n};\n\ngoogle.protobuf = {};\n\ngoogle.protobuf.Any = class Any {\n\n    static decode(reader, length) {\n        const message = new google.protobuf.Any();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type_url = reader.string();\n                    break;\n                case 2:\n                    message.value = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ngoogle.protobuf.Any.prototype.type_url = \"\";\ngoogle.protobuf.Any.prototype.value = new Uint8Array([]);\n"
  },
  {
    "path": "source/bigdl.js",
    "content": "\n// Experimental\n\nconst bigdl = {};\n\nbigdl.ModelFactory = class {\n\n    async match(context) {\n        const tags = await context.tags('pb');\n        if (tags.has(2) && tags.has(7) && tags.has(8) &&\n            tags.has(9) && tags.has(10) && tags.has(11) && tags.has(12)) {\n            return context.set('bigdl');\n        }\n        return null;\n    }\n\n    async open(context) {\n        bigdl.proto = await context.require('./bigdl-proto');\n        bigdl.proto = bigdl.proto.com.intel.analytics.bigdl.serialization;\n        let module = null;\n        try {\n            // https://github.com/intel-analytics/BigDL/blob/master/spark/dl/src/main/resources/serialization/bigdl.proto\n            const reader = await context.read('protobuf.binary');\n            module = bigdl.proto.BigDLModule.decode(reader);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new bigdl.Error(`File format is not bigdl.BigDLModule (${message.replace(/\\.$/, '')}).`);\n        }\n        const metadata = await context.metadata('bigdl-metadata.json');\n        return new bigdl.Model(metadata, module);\n    }\n};\n\nbigdl.Model = class {\n\n    constructor(metadata, module) {\n        const version = module && module.version ? module.version : '';\n        this.format = `BigDL${version ? ` v${version}` : ''}`;\n        this.modules = [new bigdl.Graph(metadata, module)];\n    }\n};\n\nbigdl.Graph = class {\n\n    constructor(metadata, module) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        this.description = module.moduleType;\n        const tensors = module.attr && module.attr.global_storage && module.attr.global_storage.nameAttrListValue && module.attr.global_storage.nameAttrListValue.attr ? module.attr.global_storage.nameAttrListValue.attr : {};\n        const values = new Map();\n        values.map = (name) => {\n            if (!values.has(name)) {\n                values.set(name, new bigdl.Value(name));\n            }\n            return values.get(name);\n        };\n        const loadModule = (metadata, module, tensors) => {\n            switch (module.moduleType) {\n                case 'com.intel.analytics.bigdl.nn.StaticGraph':\n                case 'com.intel.analytics.bigdl.nn.Sequential': {\n                    for (const submodule of module.subModules) {\n                        loadModule(metadata, submodule, tensors);\n                    }\n                    break;\n                }\n                case 'com.intel.analytics.bigdl.nn.Input': {\n                    const argument = new bigdl.Argument(module.name, [values.map(module.name)]);\n                    this.inputs.push(argument);\n                    break;\n                }\n                default: {\n                    const node = new bigdl.Node(metadata, module, tensors, values);\n                    this.nodes.push(node);\n                    break;\n                }\n            }\n        };\n        loadModule(metadata, module, tensors);\n    }\n};\n\nbigdl.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nbigdl.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new bigdl.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nbigdl.Node = class {\n\n    constructor(metadata, module, tensors, values) {\n        const type = module.moduleType;\n        this.name = module.name;\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.inputs.push(new bigdl.Argument('input', module.preModules.map((id) => values.map(id))));\n        this.type =  metadata.type(type) || { name: type };\n        const inputs = this.type && this.type.inputs ? this.type.inputs.slice() : [];\n        inputs.shift();\n        if (module.weight) {\n            inputs.shift();\n            this.inputs.push(new bigdl.Argument('weight', [\n                new bigdl.Value('', null, new bigdl.Tensor(module.weight, tensors))\n            ]));\n        }\n        if (module.bias) {\n            inputs.shift();\n            this.inputs.push(new bigdl.Argument('bias', [\n                new bigdl.Value('', null, new bigdl.Tensor(module.bias, tensors))\n            ]));\n        }\n        if (module.parameters && module.parameters.length > 0) {\n            for (const parameter of module.parameters) {\n                const input = inputs.shift();\n                const inputName = input ? input.name : this.inputs.length.toString();\n                this.inputs.push(new bigdl.Argument(inputName, [\n                    new bigdl.Value('', null, new bigdl.Tensor(parameter, tensors))\n                ]));\n            }\n        }\n        for (const [key, obj] of Object.entries(module.attr)) {\n            if (key === 'module_numerics' || key === 'module_tags') {\n                continue;\n            }\n            if (obj.dataType === bigdl.proto.DataType.TENSOR) {\n                if (obj.value) {\n                    this.inputs.push(new bigdl.Argument(key, [new bigdl.Value('', null, new bigdl.Tensor(obj.tensorValue, tensors))]));\n                }\n                continue;\n            }\n            if (obj.dataType === bigdl.proto.DataType.REGULARIZER && obj.value === undefined) {\n                continue;\n            }\n            if (obj.dataType === bigdl.proto.DataType.ARRAY_VALUE && obj.arrayValue.datatype === bigdl.proto.DataType.TENSOR) {\n                this.inputs.push(new bigdl.Argument(key, obj.arrayValue.tensor.map((tensor) => new bigdl.Value('', null, new bigdl.Tensor(tensor, tensors)))));\n                continue;\n            }\n            let type = null;\n            let value = null;\n            switch (obj.dataType) {\n                case bigdl.proto.DataType.INT32: {\n                    type = 'int32';\n                    value = obj.int32Value;\n                    break;\n                }\n                case bigdl.proto.DataType.FLOAT: {\n                    type = 'float32';\n                    value = obj.floatValue;\n                    break;\n                }\n                case bigdl.proto.DataType.DOUBLE: {\n                    type = 'float64';\n                    value = obj.doubleValue;\n                    break;\n                }\n                case bigdl.proto.DataType.BOOL: {\n                    type = 'boolean';\n                    value = obj.boolValue;\n                    break;\n                }\n                case bigdl.proto.DataType.REGULARIZER: {\n                    value = obj.value;\n                    break;\n                }\n                case bigdl.proto.DataType.MODULE: {\n                    value = obj.bigDLModule;\n                    break;\n                }\n                case bigdl.proto.DataType.NAME_ATTR_LIST: {\n                    value = value.nameAttrListValue;\n                    break;\n                }\n                case bigdl.proto.DataType.ARRAY_VALUE: {\n                    switch (obj.arrayValue.datatype) {\n                        case bigdl.proto.DataType.INT32: {\n                            type = 'int32[]';\n                            value = obj.arrayValue.i32;\n                            break;\n                        }\n                        case bigdl.proto.DataType.FLOAT: {\n                            type = 'float32[]';\n                            value = obj.arrayValue.flt;\n                            break;\n                        }\n                        case bigdl.proto.DataType.STRING: {\n                            type = 'string[]';\n                            value = obj.arrayValue.str;\n                            break;\n                        }\n                        case bigdl.proto.DataType.TENSOR: {\n                            type = 'tensor[]';\n                            value = obj.arrayValue.tensor;\n                            break;\n                        }\n                        default: {\n                            throw new bigdl.Error(`Unsupported attribute array data type '${obj.arrayValue.datatype}'.`);\n                        }\n                    }\n                    break;\n                }\n                case bigdl.proto.DataType.DATA_FORMAT: {\n                    switch (obj.dataFormatValue) {\n                        case 0: value = 'NCHW'; break;\n                        case 1: value = 'NHWC'; break;\n                        default: throw new bigdl.Error(`Unsupported data format '${obj.dataFormatValue}'.`);\n                    }\n                    break;\n                }\n                default: {\n                    throw new bigdl.Error(`Unsupported attribute data type '${obj.dataType}'.`);\n                }\n            }\n            const argument = new bigdl.Argument(key, value, type);\n            this.attributes.push(argument);\n        }\n        const output = this.name || this.type + module.namePostfix;\n        this.outputs.push(new bigdl.Argument('output', [values.map(output)]));\n    }\n};\n\nbigdl.Tensor = class {\n\n    constructor(tensor /*, tensors */) {\n        this.type = new bigdl.TensorType(tensor.datatype, new bigdl.TensorShape(tensor.size));\n        /*\n        if (tensor && tensor.id && tensors && tensors[tensor.id] && tensors[tensor.id].tensorValue && tensors[tensor.id].tensorValue.storage) {\n            const storage = tensors[tensor.id].tensorValue.storage;\n            switch (this.type.dataType) {\n                case 'float32':\n                    if (storage.bytes_data && storage.bytes_data.length > 0) {\n                        this.values = storage.bytes_data[0];\n                        this.encoding = '<';\n                    }\n                    else if (storage.float_data && storage.float_data.length > 0) {\n                        this.values = storage.float_data;\n                        this.encoding = '|';\n                    }\n                    break;\n                default:\n                    break;\n            }\n        }\n        */\n    }\n};\n\nbigdl.TensorType = class {\n\n    constructor(dataType, shape) {\n        switch (dataType) {\n            case bigdl.proto.DataType.FLOAT: this.dataType = 'float32'; break;\n            case bigdl.proto.DataType.DOUBLE: this.dataType = 'float64'; break;\n            default: throw new bigdl.Error(`Unsupported tensor type '${dataType}'.`);\n        }\n        this.shape = shape;\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\nbigdl.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n        if (!dimensions.every((dimension) => Number.isInteger(dimension))) {\n            throw new bigdl.Error(`Invalid tensor shape '${JSON.stringify(dimensions)}'.`);\n        }\n    }\n\n    toString() {\n        return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`) : '';\n    }\n};\n\nbigdl.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading BigDL model.';\n    }\n};\n\nexport const ModelFactory = bigdl.ModelFactory;\n\n"
  },
  {
    "path": "source/browser.js",
    "content": "\nimport * as base from './base.js';\n\nconst browser = {};\n\nbrowser.Host = class {\n\n    constructor() {\n        this._window = window;\n        this._navigator = window.navigator;\n        this._document = window.document;\n        this._telemetry = new base.Telemetry(this._window);\n        this._window.eval = () => {\n            throw new Error('window.eval() not supported.');\n        };\n        this._meta = {};\n        for (const element of Array.from(this._document.getElementsByTagName('meta'))) {\n            if (element.name !== undefined && element.name !== '' && element.content !== undefined) {\n                this._meta[element.name] = this._meta[element.name] || [];\n                this._meta[element.name].push(element.content);\n            }\n        }\n        this._environment = {\n            name: this._document.title,\n            type: this._meta.type ? this._meta.type[0] : 'Browser',\n            version: this._meta.version ? this._meta.version[0] : null,\n            date: Array.isArray(this._meta.date) && this._meta.date.length > 0 && this._meta.date[0] ? new Date(`${this._meta.date[0].split(' ').join('T')}Z`) : new Date(),\n            packaged: this._meta.version && this._meta.version[0] !== '0.0.0',\n            platform: /(Mac|iPhone|iPod|iPad)/i.test(this._navigator.platform) ? 'darwin' : undefined,\n            agent: this._navigator.userAgent.toLowerCase().indexOf('safari') !== -1 && this._navigator.userAgent.toLowerCase().indexOf('chrome') === -1 ? 'safari' : '',\n            repository: this._element('logo-github').getAttribute('href'),\n            menu: true\n        };\n        if (this.version && !/^\\d+\\.\\d+\\.\\d+$/.test(this.version)) {\n            throw new Error('Invalid version.');\n        }\n    }\n\n    get window() {\n        return this._window;\n    }\n\n    get document() {\n        return this._document;\n    }\n\n    get version() {\n        return this._environment.version;\n    }\n\n    get type() {\n        return this._environment.type;\n    }\n\n    async view(view) {\n        const window = this.window;\n        const document = this.document;\n        this._view = view;\n        const age = async () => {\n            const days = (new Date() - new Date(this._environment.date)) / (24 * 60 * 60 * 1000);\n            if (days > 180) {\n                const link = this._element('logo-github').href;\n                document.body.classList.remove('spinner');\n                for (;;) {\n                    /* eslint-disable no-await-in-loop */\n                    await this.message('Please update to the newest version.', null, 'Update');\n                    /* eslint-enable no-await-in-loop */\n                    this.openURL(link);\n                }\n            }\n            return Promise.resolve();\n        };\n        const consent = async () => {\n            if (this._getCookie('consent') || this._getCookie('_ga')) {\n                return;\n            }\n            let consent = true;\n            try {\n                const text = await this._request('https://ipinfo.io/json', { 'Content-Type': 'application/json' }, 'utf-8', null, 2000);\n                const json = JSON.parse(text);\n                const countries = ['AT', 'BE', 'BG', 'HR', 'CZ', 'CY', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'SK', 'ES', 'SE', 'GB', 'UK', 'GR', 'EU', 'RO'];\n                if (json && json.country && countries.indexOf(json.country) === -1) {\n                    consent = false;\n                }\n            } catch {\n                // continue regardless of error\n            }\n            if (consent) {\n                document.body.classList.remove('spinner');\n                await this.message('This app uses cookies to report errors and anonymous usage information.', null, 'Accept');\n            }\n            this._setCookie('consent', Date.now().toString(), 30);\n        };\n        const telemetry = async () => {\n            if (this._environment.packaged) {\n                window.addEventListener('error', (event) => {\n                    if (event instanceof window.ErrorEvent && event.error && event.error instanceof Error) {\n                        this.exception(event.error, true);\n                    } else {\n                        const message = event && event.message ? event.message : JSON.stringify(event);\n                        const error = new Error(message);\n                        this.exception(error, true);\n                    }\n                });\n                const measurement_id = '848W2NVWVH';\n                const user = this._getCookie('_ga').replace(/^(GA1\\.\\d\\.)*/, '');\n                const session = this._getCookie(`_ga${measurement_id}`);\n                await this._telemetry.start(`G-${measurement_id}`, user, session);\n                this._telemetry.set('page_location', document.location && document.location.href ? document.location.href : null);\n                this._telemetry.set('page_title', document.title ? document.title : null);\n                this._telemetry.set('page_referrer', document.referrer ? document.referrer : null);\n                this._telemetry.send('page_view', {\n                    app_name: this.type,\n                    app_version: this.version,\n                });\n                this._telemetry.send('scroll', {\n                    percent_scrolled: 90,\n                    app_name: this.type,\n                    app_version: this.version\n                });\n                this._setCookie('_ga', `GA1.2.${this._telemetry.get('client_id')}`, 1200);\n                this._setCookie(`_ga${measurement_id}`, `GS1.1.${this._telemetry.session}`, 1200);\n            }\n        };\n        const capabilities = async () => {\n            const filter = (list) => {\n                return list.filter((capability) => {\n                    const path = capability.split('.').reverse();\n                    let obj = window[path.pop()];\n                    while (obj && path.length > 0) {\n                        obj = obj[path.pop()];\n                    }\n                    return obj;\n                });\n            };\n            const capabilities = filter(['fetch', 'DataView.prototype.getBigInt64', 'Worker', 'Array.prototype.flat']);\n            this.event('browser_open', {\n                browser_capabilities: capabilities.map((capability) => capability.split('.').pop()).join(',')\n            });\n            return Promise.resolve();\n        };\n        await age();\n        await consent();\n        await telemetry();\n        await capabilities();\n    }\n\n    async start() {\n        if (this._meta.file) {\n            const [url] = this._meta.file;\n            if (this._view.accept(url)) {\n                const identifier = Array.isArray(this._meta.identifier) && this._meta.identifier.length === 1 ? this._meta.identifier[0] : null;\n                const name = this._meta.name || null;\n                const status = await this._openModel(this._url(url), identifier || null, name);\n                if (status === '') {\n                    return;\n                }\n            }\n        }\n        const window = this.window;\n        const document = this.document;\n        const search = window.location.search;\n        const params = new Map(search ? new window.URLSearchParams(window.location.search) : []);\n        const hash = window.location.hash ? window.location.hash.replace(/^#/, '') : '';\n        const url = hash ? hash : params.get('url');\n        if (url) {\n            const identifier = params.get('identifier') || null;\n            const location = url\n                .replace(/^https:\\/\\/github\\.com\\/([\\w-]*\\/[\\w-]*)\\/blob\\/([\\w/\\-_.]*)(\\?raw=true)?$/, 'https://raw.githubusercontent.com/$1/$2')\n                .replace(/^https:\\/\\/github\\.com\\/([\\w-]*\\/[\\w-]*)\\/raw\\/([\\w/\\-_.]*)$/, 'https://raw.githubusercontent.com/$1/$2')\n                .replace(/^https:\\/\\/huggingface.co\\/(.*)\\/blob\\/(.*)$/, 'https://huggingface.co/$1/resolve/$2');\n            if (this._view.accept(identifier || location) && location.indexOf('*') === -1) {\n                const status = await this._openModel(location, identifier);\n                if (status === '') {\n                    return;\n                }\n            }\n        }\n        const gist = params.get('gist');\n        if (gist) {\n            this._openGist(gist);\n            return;\n        }\n        const openFileButton = this._element('open-file-button');\n        const openFileDialog = this._element('open-file-dialog');\n        if (openFileButton && openFileDialog) {\n            openFileButton.addEventListener('click', () => {\n                this.execute('open');\n            });\n            const mobileSafari = this.environment('platform') === 'darwin' && window.navigator.maxTouchPoints && window.navigator.maxTouchPoints > 1;\n            if (!mobileSafari) {\n                const extensions = new base.Metadata().extensions.map((extension) => `.${extension}`);\n                openFileDialog.setAttribute('accept', extensions.join(', '));\n            }\n            openFileDialog.addEventListener('change', (e) => {\n                if (e.target && e.target.files && e.target.files.length > 0) {\n                    const files = Array.from(e.target.files);\n                    const file = files.find((file) => this._view.accept(file.name, file.size));\n                    if (file) {\n                        this._open(file, files);\n                    }\n                }\n            });\n        }\n        document.addEventListener('dragover', (e) => {\n            e.preventDefault();\n        });\n        document.addEventListener('drop', (e) => {\n            e.preventDefault();\n        });\n        document.body.addEventListener('drop', (e) => {\n            e.preventDefault();\n            if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n                const files = Array.from(e.dataTransfer.files);\n                const file = files.find((file) => this._view.accept(file.name, file.size));\n                if (file) {\n                    this._open(file, files);\n                }\n            }\n        });\n        this._view.show('welcome');\n    }\n\n    environment(name) {\n        return this._environment[name];\n    }\n\n    async require(id) {\n        return import(`${id}.js`);\n    }\n\n    worker(id) {\n        const window = this.window;\n        return new window.Worker(`${id}.js`, { type: 'module' });\n    }\n\n    async save(name, extension, defaultPath) {\n        return `${defaultPath}.${extension}`;\n    }\n\n    async export(file, blob) {\n        const window = this.window;\n        const document = this.document;\n        const element = document.createElement('a');\n        element.download = file;\n        const url = window.URL.createObjectURL(blob);\n        element.href = url;\n        document.body.appendChild(element);\n        element.click();\n        document.body.removeChild(element);\n        window.URL.revokeObjectURL(url);\n    }\n\n    async execute(name /*, value */) {\n        switch (name) {\n            case 'open': {\n                const openFileDialog = this._element('open-file-dialog');\n                if (openFileDialog) {\n                    openFileDialog.value = '';\n                    openFileDialog.click();\n                }\n                break;\n            }\n            case 'report-issue': {\n                this.openURL(`${this.environment('repository')}/issues/new`);\n                break;\n            }\n            case 'about': {\n                this._view.about();\n                break;\n            }\n            default: {\n                break;\n            }\n        }\n    }\n\n    async request(file, encoding, base) {\n        const url = base ? `${base}/${file}` : this._url(file);\n        if (base === null) {\n            this._requests = this._requests || new Map();\n            const key = `${url}:${encoding}`;\n            if (!this._requests.has(key)) {\n                const promise = this._request(url, null, encoding);\n                this._requests.set(key, promise);\n            }\n            return this._requests.get(key);\n        }\n        return this._request(url, null, encoding);\n    }\n\n    openURL(url) {\n        const window = this.window;\n        window.location = url;\n    }\n\n    exception(error, fatal) {\n        if (this._telemetry && error) {\n            const name = error.name ? `${error.name}: ` : '';\n            const message = error.message ? error.message : JSON.stringify(error);\n            let context = '';\n            let stack = '';\n            if (error.stack) {\n                const format = (file, line, column) => {\n                    return `${file.split('\\\\').join('/').split('/').pop()}:${line}:${column}`;\n                };\n                const match = error.stack.match(/\\n {4}at (.*) \\((.*):(\\d*):(\\d*)\\)/);\n                if (match) {\n                    stack = `${match[1]} (${format(match[2], match[3], match[4])})`;\n                } else {\n                    const match = error.stack.match(/\\n {4}at (.*):(\\d*):(\\d*)/);\n                    if (match) {\n                        stack = `(${format(match[1], match[2], match[3])})`;\n                    } else {\n                        const match = error.stack.match(/\\n {4}at (.*)\\((.*)\\)/);\n                        if (match) {\n                            stack = `(${format(match[1], match[2], match[3])})`;\n                        } else {\n                            const match = error.stack.match(/\\s*@\\s*(.*):(.*):(.*)/);\n                            if (match) {\n                                stack = `(${format(match[1], match[2], match[3])})`;\n                            } else {\n                                const match = error.stack.match(/.*\\n\\s*(.*)\\s*/);\n                                if (match) {\n                                    [, stack] = match;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            if (error.context) {\n                context = typeof error.context === 'string' ? error.context : JSON.stringify(error.context);\n            }\n            this._telemetry.send('exception', {\n                app_name: this.type,\n                app_version: this.version,\n                error_name: name,\n                error_message: message,\n                error_context: context,\n                error_stack: stack,\n                error_fatal: fatal ? true : false\n            });\n        }\n    }\n\n    event(name, params) {\n        if (name && params) {\n            params.app_name = this.type;\n            params.app_version = this.version;\n            this._telemetry.send(name, params);\n        }\n    }\n\n    async _request(url, headers, encoding, callback, timeout) {\n        const window = this.window;\n        if (!url.startsWith('data:')) {\n            const date = new Date().getTime();\n            const separator = (/\\?/).test(url) ? '&' : '?';\n            url = `${url}${separator}cb=${date}`;\n        }\n        return new Promise((resolve, reject) => {\n            const request = new window.XMLHttpRequest();\n            if (!encoding) {\n                request.responseType = 'arraybuffer';\n            }\n            if (timeout) {\n                request.timeout = timeout;\n            }\n            const progress = (value) => {\n                if (callback) {\n                    callback(value);\n                }\n            };\n            request.onload = () => {\n                progress(0);\n                if (request.status === 200) {\n                    let value = null;\n                    if (request.responseType === 'arraybuffer') {\n                        const buffer = new Uint8Array(request.response);\n                        value = new base.BinaryStream(buffer);\n                    } else {\n                        value = request.responseText;\n                    }\n                    resolve(value);\n                } else {\n                    const error = new Error(`The web request failed with status code '${request.status}'.`);\n                    error.context = url;\n                    reject(error);\n                }\n            };\n            request.onerror = () => {\n                progress(0);\n                const error = new Error(`The web request failed.`);\n                error.context = url;\n                reject(error);\n            };\n            request.ontimeout = () => {\n                progress(0);\n                request.abort();\n                const error = new Error('The web request timed out.', 'timeout', url);\n                error.context = url;\n                reject(error);\n            };\n            request.onprogress = (e) => {\n                if (e && e.lengthComputable) {\n                    progress(e.loaded / e.total * 100);\n                }\n            };\n            request.open('GET', url, true);\n            if (headers) {\n                for (const [name, value] of Object.entries(headers)) {\n                    request.setRequestHeader(name, value);\n                }\n            }\n            request.send();\n        });\n    }\n\n    _url(file) {\n        if (file.startsWith('./')) {\n            file = file.substring(2);\n        } else if (file.startsWith('/')) {\n            file = file.substring(1);\n        }\n        const window = this.window;\n        const location = window.location;\n        const pathname = location.pathname.endsWith('/') ? location.pathname : `${location.pathname.split('/').slice(0, -1).join('/')}/`;\n        return `${location.protocol}//${location.host}${pathname}${file}`;\n    }\n\n    async _openModel(url, identifier, name) {\n        this._view.show('welcome spinner');\n        let context = null;\n        try {\n            const progress = (value) => {\n                this._view.progress(value);\n            };\n            let stream = await this._request(url, null, null, progress);\n            if (url.startsWith('https://raw.githubusercontent.com/') && stream.length < 150) {\n                const buffer = stream.peek();\n                const content = Array.from(buffer).map((c) => String.fromCodePoint(c)).join('');\n                if (content.split('\\n')[0] === 'version https://git-lfs.github.com/spec/v1') {\n                    url = url.replace('https://raw.githubusercontent.com/', 'https://media.githubusercontent.com/media/');\n                    stream = await this._request(url, null, null, progress);\n                }\n            }\n            context = new browser.Context(this, url, identifier, name, stream);\n            this._telemetry.set('session_engaged', 1);\n        } catch (error) {\n            await this._view.error(error, 'Model load request failed.');\n            this._view.show('welcome');\n            return null;\n        }\n        return await this._openContext(context);\n    }\n\n    async _open(file, files) {\n        this._view.show('welcome spinner');\n        const context = new browser.BrowserFileContext(this, file, files);\n        try {\n            await context.open();\n            await this._openContext(context);\n        } catch (error) {\n            await this._view.error(error);\n        }\n    }\n\n    async _openGist(gist) {\n        this._view.show('welcome spinner');\n        const url = `https://api.github.com/gists/${gist}`;\n        try {\n            const text = await this._request(url, { 'Content-Type': 'application/json' }, 'utf-8');\n            const json = JSON.parse(text);\n            let message = json.message;\n            let file = null;\n            if (!message) {\n                file = Object.values(json.files).find((file) => this._view.accept(file.filename));\n                if (!file) {\n                    message = 'Gist does not contain a model file.';\n                }\n            }\n            if (message) {\n                const error = new Error(message);\n                error.name = 'Error while loading Gist.';\n                throw error;\n            }\n            const identifier = file.filename;\n            const encoder = new TextEncoder();\n            const buffer = encoder.encode(file.content);\n            const stream = new base.BinaryStream(buffer);\n            const context = new browser.Context(this, '', identifier, null, stream);\n            await this._openContext(context);\n        } catch (error) {\n            await this._view.error(error, 'Error while loading Gist.');\n            this._view.show('welcome');\n        }\n    }\n\n    async _openContext(context) {\n        const document = this.document;\n        this._telemetry.set('session_engaged', 1);\n        try {\n            const attachment = await this._view.attach(context);\n            if (attachment) {\n                this._view.show(null);\n                return 'context-open-attachment';\n            }\n            const model = await this._view.open(context);\n            if (model) {\n                this._view.show(null);\n                document.title = context.name || context.identifier;\n                return '';\n            }\n            document.title = '';\n            return 'context-open-failed';\n        } catch (error) {\n            await this._view.error(error, error.name);\n            return 'context-open-error';\n        }\n    }\n\n    _setCookie(name, value, days) {\n        const window = this.window;\n        const document = this.document;\n        document.cookie = `${name}=; Max-Age=0`;\n        const location = window.location;\n        const domain = location && location.hostname && location.hostname.indexOf('.') !== -1 ? `;domain=.${location.hostname.split('.').slice(-2).join('.')}` : '';\n        const date = new Date();\n        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));\n        document.cookie = `${name}=${value}${domain};path=/;expires=${date.toUTCString()}`;\n    }\n\n    _getCookie(name) {\n        const document = this.document;\n        for (const cookie of document.cookie.split(';')) {\n            const entry = cookie.split('=');\n            if (entry[0].trim() === name) {\n                return entry[1].trim();\n            }\n        }\n        return '';\n    }\n\n    get(name) {\n        const window = this.window;\n        try {\n            if (typeof window.localStorage !== 'undefined') {\n                const content = window.localStorage.getItem(name);\n                return JSON.parse(content);\n            }\n        } catch {\n            // continue regardless of error\n        }\n        return undefined;\n    }\n\n    set(name, value) {\n        const window = this.window;\n        try {\n            if (typeof window.localStorage !== 'undefined') {\n                window.localStorage.setItem(name, JSON.stringify(value));\n            }\n        } catch {\n            // continue regardless of error\n        }\n    }\n\n    delete(name) {\n        const window = this.window;\n        try {\n            if (typeof window.localStorage !== 'undefined') {\n                window.localStorage.removeItem(name);\n            }\n        } catch {\n            // continue regardless of error\n        }\n    }\n\n    _element(id) {\n        const document = this.document;\n        return document.getElementById(id);\n    }\n\n    update() {\n    }\n\n    async message(message, alert, action) {\n        return new Promise((resolve) => {\n            const document = this.document;\n            const type = document.body.getAttribute('class');\n            this._element('message-text').innerText = message || '';\n            const button = this._element('message-button');\n            if (action) {\n                button.style.removeProperty('display');\n                button.innerText = action;\n                button.onclick = () => {\n                    button.onclick = null;\n                    document.body.setAttribute('class', type);\n                    resolve(0);\n                };\n            } else {\n                button.style.display = 'none';\n                button.onclick = null;\n            }\n            if (alert) {\n                document.body.setAttribute('class', 'alert');\n            } else {\n                document.body.classList.add('notification');\n                document.body.classList.remove('default');\n            }\n            if (action) {\n                button.focus();\n            }\n        });\n    }\n};\n\nbrowser.BrowserFileContext = class {\n\n    constructor(host, file, blobs) {\n        this._host = host;\n        this._file = file;\n        this._blobs = {};\n        for (const blob of blobs) {\n            this._blobs[blob.name] = blob;\n        }\n    }\n\n    get identifier() {\n        return this._file.name;\n    }\n\n    get stream() {\n        return this._stream;\n    }\n\n    async request(file, encoding, basename) {\n        if (basename !== undefined) {\n            return this._host.request(file, encoding, basename);\n        }\n        const blob = this._blobs[file];\n        if (!blob) {\n            throw new Error(`File not found '${file}'.`);\n        }\n        return new Promise((resolve, reject) => {\n            const window = this._host.window;\n            const reader = new window.FileReader();\n            const size = 0x10000000;\n            let position = 0;\n            const chunks = [];\n            reader.onload = (e) => {\n                if (encoding) {\n                    resolve(e.target.result);\n                } else {\n                    const buffer = new Uint8Array(e.target.result);\n                    if (position === 0 && buffer.length === blob.size) {\n                        const stream = new base.BinaryStream(buffer);\n                        resolve(stream);\n                    } else {\n                        chunks.push(buffer);\n                        position += buffer.length;\n                        if (position < blob.size) {\n                            const slice = blob.slice(position, Math.min(position + size, blob.size));\n                            reader.readAsArrayBuffer(slice);\n                        } else {\n                            const stream = new browser.FileStream(chunks, size, 0, position);\n                            resolve(stream);\n                        }\n                    }\n                }\n            };\n            reader.onerror = (event) => {\n                event = event || this._host.window.event;\n                let message = '';\n                const error = event.target.error;\n                switch (error.code) {\n                    case error.NOT_FOUND_ERR:\n                        message = `File not found '${file}'.`;\n                        break;\n                    case error.NOT_READABLE_ERR:\n                        message = `File not readable '${file}'.`;\n                        break;\n                    case error.SECURITY_ERR:\n                        message = `File access denied '${file}'.`;\n                        break;\n                    default:\n                        message = error.message ? error.message : `File read '${error.code}' error '${file}'.`;\n                        break;\n                }\n                reject(new Error(message));\n            };\n            if (encoding === 'utf-8') {\n                reader.readAsText(blob, encoding);\n            } else {\n                const slice = blob.slice(position, Math.min(position + size, blob.size));\n                reader.readAsArrayBuffer(slice);\n            }\n        });\n    }\n\n    async require(id) {\n        return this._host.require(id);\n    }\n\n    error(error, fatal) {\n        this._host.exception(error, fatal);\n    }\n\n    async open() {\n        this._stream = await this.request(this._file.name, null);\n    }\n};\n\nbrowser.FileStream = class {\n\n    constructor(chunks, size, start, length) {\n        this._chunks = chunks;\n        this._size = size;\n        this._start = start;\n        this._length = length;\n        this._position = 0;\n    }\n\n    get position() {\n        return this._position;\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    stream(length) {\n        const file = new browser.FileStream(this._chunks, this._size, this._start + this._position, length);\n        this.skip(length);\n        return file;\n    }\n\n    seek(position) {\n        this._position = position >= 0 ? position : this._length + position;\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position > this._length) {\n            throw new Error(`Expected ${this._position - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    peek(length) {\n        length = length === undefined ? this._length - this._position : length;\n        if (length < 0x10000000) {\n            const position = this._fill(length);\n            this._position -= length;\n            return this._buffer.subarray(position, position + length);\n        }\n        const position = this._start + this._position;\n        if (position % this._size === 0) {\n            const index = Math.floor(position / this._size);\n            const chunk = this._chunks[index];\n            if (chunk && chunk.length === length) {\n                return chunk;\n            }\n        }\n        const buffer = new Uint8Array(length);\n        this._read(buffer, position);\n        return buffer;\n    }\n\n    read(length) {\n        length = length === undefined ? this._length - this._position : length;\n        if (length < 0x10000000) {\n            const position = this._fill(length);\n            return this._buffer.slice(position, position + length);\n        }\n        const position = this._start + this._position;\n        this.skip(length);\n        if (position % this._size === 0) {\n            const index = Math.floor(position / this._size);\n            const chunk = this._chunks[index];\n            if (chunk && chunk.length === length) {\n                return chunk;\n            }\n        }\n        const buffer = new Uint8Array(length);\n        this._read(buffer, position);\n        return buffer;\n    }\n\n    _fill(length) {\n        if (this._position + length > this._length) {\n            throw new Error(`Expected ${this._position + length - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n        if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {\n            this._offset = this._start + this._position;\n            const length = Math.min(0x10000000, this._start + this._length - this._offset);\n            if (!this._buffer || length !== this._buffer.length) {\n                this._buffer = new Uint8Array(length);\n            }\n            this._read(this._buffer, this._offset);\n        }\n        const position = this._start + this._position - this._offset;\n        this._position += length;\n        return position;\n    }\n\n    _read(buffer, offset) {\n        let index = Math.floor(offset / this._size);\n        offset -= index * this._size;\n        const chunk = this._chunks[index++];\n        let destination = Math.min(chunk.length - offset, buffer.length);\n        buffer.set(chunk.subarray(offset, offset + destination), 0);\n        while (destination < buffer.length) {\n            const chunk = this._chunks[index++];\n            const size = Math.min(this._size, buffer.length - destination);\n            buffer.set(chunk.subarray(0, size), destination);\n            destination += size;\n        }\n    }\n};\n\nbrowser.Context = class {\n\n    constructor(host, url, identifier, name, stream) {\n        this._host = host;\n        this._name = name;\n        this._stream = stream;\n        const parts = url.split('?')[0].split('/');\n        this._identifier = parts.pop();\n        this._base = parts.join('/');\n        if (identifier) {\n            this._identifier = identifier;\n        }\n    }\n\n    get identifier() {\n        return this._identifier;\n    }\n\n    get name() {\n        return this._name;\n    }\n\n    get stream() {\n        return this._stream;\n    }\n\n    async request(file, encoding, base) {\n        base = base === undefined ? this._base : base;\n        return this._host.request(file, encoding, base);\n    }\n\n    async require(id) {\n        return this._host.require(id);\n    }\n\n    error(error, fatal) {\n        this._host.exception(error, fatal);\n    }\n};\n\nif (!('scrollBehavior' in window.document.documentElement.style)) {\n    const __scrollTo__ = window.Element.prototype.scrollTo;\n    window.Element.prototype.scrollTo = function(...args) {\n        const [options] = args;\n        if (options !== undefined) {\n            if (options === null || typeof options !== 'object' || options.behavior === undefined || options.behavior === 'auto' || options.behavior === 'instant') {\n                if (__scrollTo__) {\n                    __scrollTo__.apply(this, args);\n                }\n            } else {\n                const now = () =>  window.performance && window.performance.now ? window.performance.now() : Date.now();\n                const ease = (k) => 0.5 * (1 - Math.cos(Math.PI * k));\n                const step = (context) => {\n                    const value = ease(Math.min((now() - context.startTime) / 468, 1));\n                    const x = context.startX + (context.x - context.startX) * value;\n                    const y = context.startY + (context.y - context.startY) * value;\n                    context.element.scrollLeft = x;\n                    context.element.scrollTop = y;\n                    if (x !== context.x || y !== context.y) {\n                        window.requestAnimationFrame(step.bind(window, context));\n                    }\n                };\n                const context = {\n                    element: this,\n                    x: typeof options.left === 'undefined' ? this.scrollLeft : ~~options.left,\n                    y: typeof options.top === 'undefined' ? this.scrollTop : ~~options.top,\n                    startX: this.scrollLeft,\n                    startY: this.scrollTop,\n                    startTime: now()\n                };\n                step(context);\n            }\n        }\n    };\n}\n\nif (typeof window !== 'undefined' && window.exports) {\n    window.exports.browser = browser;\n}\n\nexport const Host = browser.Host;\n"
  },
  {
    "path": "source/caffe-metadata.json",
    "content": "[\n  {\n    \"name\": \"Accuracy\",\n    \"inputs\": [\n      { \"name\": \"predictions\" },\n      { \"name\": \"labels\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"AnnotatedData\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"data\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"use_global_stats\", \"type\": \"boolean\", \"visible\": false },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.00001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BN\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ColorConv\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"option\": \"variadic\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ContrastiveLossParameter\",\n    \"attributes\": [\n      { \"name\": \"margin\", \"default\": 1 },\n      { \"name\": \"legacy_version\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"bias_term\", \"visible\": false },\n      { \"name\": \"weight_filler\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false },\n      { \"name\": \"num_output\", \"visible\": false },\n      { \"name\": \"pad\", \"default\": [   0 ] },\n      { \"name\": \"kernel_size\", \"default\": [] },\n      { \"name\": \"stride\", \"default\": [   1 ] },\n      { \"name\": \"dilation\", \"default\": [] },\n      { \"name\": \"group\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionDepthwise\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"pad\", \"default\": [   0 ] },\n      { \"name\": \"kernel_size\", \"default\": [] },\n      { \"name\": \"stride\", \"default\": [   1 ] },\n      { \"name\": \"bias_term\", \"visible\": false },\n      { \"name\": \"weight_filler\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false },\n      { \"name\": \"num_output\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Crop\",\n    \"category\": \"Data\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Data\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"label\" }\n    ]\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"bias_term\", \"visible\": false },\n      { \"name\": \"weight_filler\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false },\n      { \"name\": \"num_output\", \"visible\": false },\n      { \"name\": \"pad\", \"default\": [] },\n      { \"name\": \"kernel_size\", \"default\": [] },\n      { \"name\": \"stride\", \"default\": [] },\n      { \"name\": \"dilation\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DepthwiseConvolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"bias_term\", \"visible\": false },\n      { \"name\": \"weight_filler\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false },\n      { \"name\": \"num_output\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"dropout_ratio\", \"default\": 0.5 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DummyData\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"data\" }\n    ]\n  },\n  {\n    \"name\": \"Eltwise\",\n    \"attributes\": [\n      { \"name\": \"operation\", \"type\": \"EltwiseParameter.EltwiseOp\", \"default\": 1 },\n      { \"name\": \"coeff\", \"type\": \"float32[]\", \"default\": [] },\n      { \"name\": \"stable_prod_grad\", \"type\": \"boolean\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"inputs\", \"option\": \"variadic\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"EuclideanLoss\",\n    \"inputs\": [\n      { \"name\": \"predictions\" },\n      { \"name\": \"targets\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Flatten\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"HDF5Data\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"data\" }\n    ]\n  },\n  {\n    \"name\": \"ImageData\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"label\" }\n    ]\n  },\n  {\n    \"name\": \"InnerProduct\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"bias_term\", \"visible\": false },\n      { \"name\": \"weight_filler\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false },\n      { \"name\": \"num_output\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"local_size\", \"type\": \"uint32\", \"default\": 5 },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.75 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"weight_filler\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false },\n      { \"name\": \"num_output\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"h_0\" },\n      { \"name\": \"c_0\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"h_T\" },\n      { \"name\": \"c_T\" }\n    ]\n  },\n  {\n    \"name\": \"Parameter\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Permute\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"pool\", \"type\": \"PoolingParameter.PoolMethod\", \"default\": 0 },\n      { \"name\": \"engine\", \"type\": \"PoolingParameter.Engine\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"PReLU\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"slope\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Python\"\n  },\n  {\n    \"name\": \"ReLU\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReLU6\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"data\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"reshaped\" }\n    ]\n  },\n  {\n    \"name\": \"Scale\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"filler\", \"visible\": false },\n      { \"name\": \"bias_term\", \"visible\": false },\n      { \"name\": \"bias_filler\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Slice\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"outputs\", \"option\": \"variadic\" }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxLoss\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"labels\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxWithLoss\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"labels\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Split\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"outputs\", \"option\": \"variadic\" }\n    ]\n  },\n  {\n    \"name\": \"WindowData\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"label\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/caffe-proto.js",
    "content": "\nexport const caffe = {};\n\ncaffe.BlobShape = class BlobShape {\n\n    constructor() {\n        this.dim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.BlobShape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim = reader.array(message.dim, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.BlobShape();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim\":\n                    reader.array(message.dim, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.BlobProto = class BlobProto {\n\n    constructor() {\n        this.data = [];\n        this.diff = [];\n        this.double_data = [];\n        this.double_diff = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.BlobProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 7:\n                    message.shape = caffe.BlobShape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.data = reader.floats(message.data, tag);\n                    break;\n                case 6:\n                    message.diff = reader.floats(message.diff, tag);\n                    break;\n                case 8:\n                    message.double_data = reader.doubles(message.double_data, tag);\n                    break;\n                case 9:\n                    message.double_diff = reader.doubles(message.double_diff, tag);\n                    break;\n                case 1:\n                    message.num = reader.int32();\n                    break;\n                case 2:\n                    message.channels = reader.int32();\n                    break;\n                case 3:\n                    message.height = reader.int32();\n                    break;\n                case 4:\n                    message.width = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.BlobProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = caffe.BlobShape.decodeText(reader);\n                    break;\n                case \"data\":\n                    reader.array(message.data, () => reader.float());\n                    break;\n                case \"diff\":\n                    reader.array(message.diff, () => reader.float());\n                    break;\n                case \"double_data\":\n                    reader.array(message.double_data, () => reader.double());\n                    break;\n                case \"double_diff\":\n                    reader.array(message.double_diff, () => reader.double());\n                    break;\n                case \"num\":\n                    message.num = reader.int32();\n                    break;\n                case \"channels\":\n                    message.channels = reader.int32();\n                    break;\n                case \"height\":\n                    message.height = reader.int32();\n                    break;\n                case \"width\":\n                    message.width = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.BlobProto.prototype.shape = null;\ncaffe.BlobProto.prototype.num = 0;\ncaffe.BlobProto.prototype.channels = 0;\ncaffe.BlobProto.prototype.height = 0;\ncaffe.BlobProto.prototype.width = 0;\n\ncaffe.BlobProtoVector = class BlobProtoVector {\n\n    constructor() {\n        this.blobs = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.BlobProtoVector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.blobs.push(caffe.BlobProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.BlobProtoVector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"blobs\":\n                    message.blobs.push(caffe.BlobProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.Datum = class Datum {\n\n    constructor() {\n        this.float_data = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.Datum();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.channels = reader.int32();\n                    break;\n                case 2:\n                    message.height = reader.int32();\n                    break;\n                case 3:\n                    message.width = reader.int32();\n                    break;\n                case 4:\n                    message.data = reader.bytes();\n                    break;\n                case 5:\n                    message.label = reader.int32();\n                    break;\n                case 6:\n                    message.float_data = reader.floats(message.float_data, tag);\n                    break;\n                case 7:\n                    message.encoded = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.Datum();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"channels\":\n                    message.channels = reader.int32();\n                    break;\n                case \"height\":\n                    message.height = reader.int32();\n                    break;\n                case \"width\":\n                    message.width = reader.int32();\n                    break;\n                case \"data\":\n                    message.data = reader.bytes();\n                    break;\n                case \"label\":\n                    message.label = reader.int32();\n                    break;\n                case \"float_data\":\n                    reader.array(message.float_data, () => reader.float());\n                    break;\n                case \"encoded\":\n                    message.encoded = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.Datum.prototype.channels = 0;\ncaffe.Datum.prototype.height = 0;\ncaffe.Datum.prototype.width = 0;\ncaffe.Datum.prototype.data = new Uint8Array([]);\ncaffe.Datum.prototype.label = 0;\ncaffe.Datum.prototype.encoded = false;\n\ncaffe.FillerParameter = class FillerParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.FillerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = reader.string();\n                    break;\n                case 2:\n                    message.value = reader.float();\n                    break;\n                case 3:\n                    message.min = reader.float();\n                    break;\n                case 4:\n                    message.max = reader.float();\n                    break;\n                case 5:\n                    message.mean = reader.float();\n                    break;\n                case 6:\n                    message.std = reader.float();\n                    break;\n                case 7:\n                    message.sparse = reader.int32();\n                    break;\n                case 8:\n                    message.variance_norm = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.FillerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                case \"min\":\n                    message.min = reader.float();\n                    break;\n                case \"max\":\n                    message.max = reader.float();\n                    break;\n                case \"mean\":\n                    message.mean = reader.float();\n                    break;\n                case \"std\":\n                    message.std = reader.float();\n                    break;\n                case \"sparse\":\n                    message.sparse = reader.int32();\n                    break;\n                case \"variance_norm\":\n                    message.variance_norm = reader.enum(caffe.FillerParameter.VarianceNorm);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.FillerParameter.prototype.type = \"constant\";\ncaffe.FillerParameter.prototype.value = 0;\ncaffe.FillerParameter.prototype.min = 0;\ncaffe.FillerParameter.prototype.max = 1;\ncaffe.FillerParameter.prototype.mean = 0;\ncaffe.FillerParameter.prototype.std = 1;\ncaffe.FillerParameter.prototype.sparse = -1;\ncaffe.FillerParameter.prototype.variance_norm = 0;\n\ncaffe.FillerParameter.VarianceNorm = {\n    \"FAN_IN\": 0,\n    \"FAN_OUT\": 1,\n    \"AVERAGE\": 2\n};\n\ncaffe.NetParameter = class NetParameter {\n\n    constructor() {\n        this.input = [];\n        this.input_shape = [];\n        this.input_dim = [];\n        this.layer = [];\n        this.layers = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.NetParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 3:\n                    message.input.push(reader.string());\n                    break;\n                case 8:\n                    message.input_shape.push(caffe.BlobShape.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    message.input_dim = reader.array(message.input_dim, () => reader.int32(), tag);\n                    break;\n                case 5:\n                    message.force_backward = reader.bool();\n                    break;\n                case 6:\n                    message.state = caffe.NetState.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.debug_info = reader.bool();\n                    break;\n                case 100:\n                    message.layer.push(caffe.LayerParameter.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.layers.push(caffe.V1LayerParameter.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.NetParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"input_shape\":\n                    message.input_shape.push(caffe.BlobShape.decodeText(reader));\n                    break;\n                case \"input_dim\":\n                    reader.array(message.input_dim, () => reader.int32());\n                    break;\n                case \"force_backward\":\n                    message.force_backward = reader.bool();\n                    break;\n                case \"state\":\n                    message.state = caffe.NetState.decodeText(reader);\n                    break;\n                case \"debug_info\":\n                    message.debug_info = reader.bool();\n                    break;\n                case \"layer\":\n                    message.layer.push(caffe.LayerParameter.decodeText(reader));\n                    break;\n                case \"layers\":\n                    message.layers.push(caffe.V1LayerParameter.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.NetParameter.prototype.name = \"\";\ncaffe.NetParameter.prototype.force_backward = false;\ncaffe.NetParameter.prototype.state = null;\ncaffe.NetParameter.prototype.debug_info = false;\n\ncaffe.SolverParameter = class SolverParameter {\n\n    constructor() {\n        this.test_net = [];\n        this.test_net_param = [];\n        this.test_state = [];\n        this.test_iter = [];\n        this.stepvalue = [];\n        this.weights = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.SolverParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 24:\n                    message.net = reader.string();\n                    break;\n                case 25:\n                    message.net_param = caffe.NetParameter.decode(reader, reader.uint32());\n                    break;\n                case 1:\n                    message.train_net = reader.string();\n                    break;\n                case 2:\n                    message.test_net.push(reader.string());\n                    break;\n                case 21:\n                    message.train_net_param = caffe.NetParameter.decode(reader, reader.uint32());\n                    break;\n                case 22:\n                    message.test_net_param.push(caffe.NetParameter.decode(reader, reader.uint32()));\n                    break;\n                case 26:\n                    message.train_state = caffe.NetState.decode(reader, reader.uint32());\n                    break;\n                case 27:\n                    message.test_state.push(caffe.NetState.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.test_iter = reader.array(message.test_iter, () => reader.int32(), tag);\n                    break;\n                case 4:\n                    message.test_interval = reader.int32();\n                    break;\n                case 19:\n                    message.test_compute_loss = reader.bool();\n                    break;\n                case 32:\n                    message.test_initialization = reader.bool();\n                    break;\n                case 5:\n                    message.base_lr = reader.float();\n                    break;\n                case 6:\n                    message.display = reader.int32();\n                    break;\n                case 33:\n                    message.average_loss = reader.int32();\n                    break;\n                case 7:\n                    message.max_iter = reader.int32();\n                    break;\n                case 36:\n                    message.iter_size = reader.int32();\n                    break;\n                case 8:\n                    message.lr_policy = reader.string();\n                    break;\n                case 9:\n                    message.gamma = reader.float();\n                    break;\n                case 10:\n                    message.power = reader.float();\n                    break;\n                case 11:\n                    message.momentum = reader.float();\n                    break;\n                case 12:\n                    message.weight_decay = reader.float();\n                    break;\n                case 29:\n                    message.regularization_type = reader.string();\n                    break;\n                case 13:\n                    message.stepsize = reader.int32();\n                    break;\n                case 34:\n                    message.stepvalue = reader.array(message.stepvalue, () => reader.int32(), tag);\n                    break;\n                case 35:\n                    message.clip_gradients = reader.float();\n                    break;\n                case 14:\n                    message.snapshot = reader.int32();\n                    break;\n                case 15:\n                    message.snapshot_prefix = reader.string();\n                    break;\n                case 16:\n                    message.snapshot_diff = reader.bool();\n                    break;\n                case 37:\n                    message.snapshot_format = reader.int32();\n                    break;\n                case 17:\n                    message.solver_mode = reader.int32();\n                    break;\n                case 18:\n                    message.device_id = reader.int32();\n                    break;\n                case 20:\n                    message.random_seed = reader.int64();\n                    break;\n                case 40:\n                    message.type = reader.string();\n                    break;\n                case 31:\n                    message.delta = reader.float();\n                    break;\n                case 39:\n                    message.momentum2 = reader.float();\n                    break;\n                case 38:\n                    message.rms_decay = reader.float();\n                    break;\n                case 23:\n                    message.debug_info = reader.bool();\n                    break;\n                case 28:\n                    message.snapshot_after_train = reader.bool();\n                    break;\n                case 30:\n                    message.solver_type = reader.int32();\n                    break;\n                case 41:\n                    message.layer_wise_reduce = reader.bool();\n                    break;\n                case 42:\n                    message.weights.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SolverParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"net\":\n                    message.net = reader.string();\n                    break;\n                case \"net_param\":\n                    message.net_param = caffe.NetParameter.decodeText(reader);\n                    break;\n                case \"train_net\":\n                    message.train_net = reader.string();\n                    break;\n                case \"test_net\":\n                    reader.array(message.test_net, () => reader.string());\n                    break;\n                case \"train_net_param\":\n                    message.train_net_param = caffe.NetParameter.decodeText(reader);\n                    break;\n                case \"test_net_param\":\n                    message.test_net_param.push(caffe.NetParameter.decodeText(reader));\n                    break;\n                case \"train_state\":\n                    message.train_state = caffe.NetState.decodeText(reader);\n                    break;\n                case \"test_state\":\n                    message.test_state.push(caffe.NetState.decodeText(reader));\n                    break;\n                case \"test_iter\":\n                    reader.array(message.test_iter, () => reader.int32());\n                    break;\n                case \"test_interval\":\n                    message.test_interval = reader.int32();\n                    break;\n                case \"test_compute_loss\":\n                    message.test_compute_loss = reader.bool();\n                    break;\n                case \"test_initialization\":\n                    message.test_initialization = reader.bool();\n                    break;\n                case \"base_lr\":\n                    message.base_lr = reader.float();\n                    break;\n                case \"display\":\n                    message.display = reader.int32();\n                    break;\n                case \"average_loss\":\n                    message.average_loss = reader.int32();\n                    break;\n                case \"max_iter\":\n                    message.max_iter = reader.int32();\n                    break;\n                case \"iter_size\":\n                    message.iter_size = reader.int32();\n                    break;\n                case \"lr_policy\":\n                    message.lr_policy = reader.string();\n                    break;\n                case \"gamma\":\n                    message.gamma = reader.float();\n                    break;\n                case \"power\":\n                    message.power = reader.float();\n                    break;\n                case \"momentum\":\n                    message.momentum = reader.float();\n                    break;\n                case \"weight_decay\":\n                    message.weight_decay = reader.float();\n                    break;\n                case \"regularization_type\":\n                    message.regularization_type = reader.string();\n                    break;\n                case \"stepsize\":\n                    message.stepsize = reader.int32();\n                    break;\n                case \"stepvalue\":\n                    reader.array(message.stepvalue, () => reader.int32());\n                    break;\n                case \"clip_gradients\":\n                    message.clip_gradients = reader.float();\n                    break;\n                case \"snapshot\":\n                    message.snapshot = reader.int32();\n                    break;\n                case \"snapshot_prefix\":\n                    message.snapshot_prefix = reader.string();\n                    break;\n                case \"snapshot_diff\":\n                    message.snapshot_diff = reader.bool();\n                    break;\n                case \"snapshot_format\":\n                    message.snapshot_format = reader.enum(caffe.SolverParameter.SnapshotFormat);\n                    break;\n                case \"solver_mode\":\n                    message.solver_mode = reader.enum(caffe.SolverParameter.SolverMode);\n                    break;\n                case \"device_id\":\n                    message.device_id = reader.int32();\n                    break;\n                case \"random_seed\":\n                    message.random_seed = reader.int64();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"delta\":\n                    message.delta = reader.float();\n                    break;\n                case \"momentum2\":\n                    message.momentum2 = reader.float();\n                    break;\n                case \"rms_decay\":\n                    message.rms_decay = reader.float();\n                    break;\n                case \"debug_info\":\n                    message.debug_info = reader.bool();\n                    break;\n                case \"snapshot_after_train\":\n                    message.snapshot_after_train = reader.bool();\n                    break;\n                case \"solver_type\":\n                    message.solver_type = reader.enum(caffe.SolverParameter.SolverType);\n                    break;\n                case \"layer_wise_reduce\":\n                    message.layer_wise_reduce = reader.bool();\n                    break;\n                case \"weights\":\n                    reader.array(message.weights, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SolverParameter.prototype.net = \"\";\ncaffe.SolverParameter.prototype.net_param = null;\ncaffe.SolverParameter.prototype.train_net = \"\";\ncaffe.SolverParameter.prototype.train_net_param = null;\ncaffe.SolverParameter.prototype.train_state = null;\ncaffe.SolverParameter.prototype.test_interval = 0;\ncaffe.SolverParameter.prototype.test_compute_loss = false;\ncaffe.SolverParameter.prototype.test_initialization = true;\ncaffe.SolverParameter.prototype.base_lr = 0;\ncaffe.SolverParameter.prototype.display = 0;\ncaffe.SolverParameter.prototype.average_loss = 1;\ncaffe.SolverParameter.prototype.max_iter = 0;\ncaffe.SolverParameter.prototype.iter_size = 1;\ncaffe.SolverParameter.prototype.lr_policy = \"\";\ncaffe.SolverParameter.prototype.gamma = 0;\ncaffe.SolverParameter.prototype.power = 0;\ncaffe.SolverParameter.prototype.momentum = 0;\ncaffe.SolverParameter.prototype.weight_decay = 0;\ncaffe.SolverParameter.prototype.regularization_type = \"L2\";\ncaffe.SolverParameter.prototype.stepsize = 0;\ncaffe.SolverParameter.prototype.clip_gradients = -1;\ncaffe.SolverParameter.prototype.snapshot = 0;\ncaffe.SolverParameter.prototype.snapshot_prefix = \"\";\ncaffe.SolverParameter.prototype.snapshot_diff = false;\ncaffe.SolverParameter.prototype.snapshot_format = 1;\ncaffe.SolverParameter.prototype.solver_mode = 1;\ncaffe.SolverParameter.prototype.device_id = 0;\ncaffe.SolverParameter.prototype.random_seed = -1n;\ncaffe.SolverParameter.prototype.type = \"SGD\";\ncaffe.SolverParameter.prototype.delta = 1e-8;\ncaffe.SolverParameter.prototype.momentum2 = 0.999;\ncaffe.SolverParameter.prototype.rms_decay = 0.99;\ncaffe.SolverParameter.prototype.debug_info = false;\ncaffe.SolverParameter.prototype.snapshot_after_train = true;\ncaffe.SolverParameter.prototype.solver_type = 0;\ncaffe.SolverParameter.prototype.layer_wise_reduce = true;\n\ncaffe.SolverParameter.SnapshotFormat = {\n    \"HDF5\": 0,\n    \"BINARYPROTO\": 1\n};\n\ncaffe.SolverParameter.SolverMode = {\n    \"CPU\": 0,\n    \"GPU\": 1\n};\n\ncaffe.SolverParameter.SolverType = {\n    \"SGD\": 0,\n    \"NESTEROV\": 1,\n    \"ADAGRAD\": 2,\n    \"RMSPROP\": 3,\n    \"ADADELTA\": 4,\n    \"ADAM\": 5\n};\n\ncaffe.SolverState = class SolverState {\n\n    constructor() {\n        this.history = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.SolverState();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.iter = reader.int32();\n                    break;\n                case 2:\n                    message.learned_net = reader.string();\n                    break;\n                case 3:\n                    message.history.push(caffe.BlobProto.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    message.current_step = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SolverState();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"iter\":\n                    message.iter = reader.int32();\n                    break;\n                case \"learned_net\":\n                    message.learned_net = reader.string();\n                    break;\n                case \"history\":\n                    message.history.push(caffe.BlobProto.decodeText(reader));\n                    break;\n                case \"current_step\":\n                    message.current_step = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SolverState.prototype.iter = 0;\ncaffe.SolverState.prototype.learned_net = \"\";\ncaffe.SolverState.prototype.current_step = 0;\n\ncaffe.Phase = {\n    \"TRAIN\": 0,\n    \"TEST\": 1\n};\n\ncaffe.NetState = class NetState {\n\n    constructor() {\n        this.stage = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.NetState();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.phase = reader.int32();\n                    break;\n                case 2:\n                    message.level = reader.int32();\n                    break;\n                case 3:\n                    message.stage.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.NetState();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"phase\":\n                    message.phase = reader.enum(caffe.Phase);\n                    break;\n                case \"level\":\n                    message.level = reader.int32();\n                    break;\n                case \"stage\":\n                    reader.array(message.stage, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.NetState.prototype.phase = 1;\ncaffe.NetState.prototype.level = 0;\n\ncaffe.NetStateRule = class NetStateRule {\n\n    constructor() {\n        this.stage = [];\n        this.not_stage = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.NetStateRule();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.phase = reader.int32();\n                    break;\n                case 2:\n                    message.min_level = reader.int32();\n                    break;\n                case 3:\n                    message.max_level = reader.int32();\n                    break;\n                case 4:\n                    message.stage.push(reader.string());\n                    break;\n                case 5:\n                    message.not_stage.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.NetStateRule();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"phase\":\n                    message.phase = reader.enum(caffe.Phase);\n                    break;\n                case \"min_level\":\n                    message.min_level = reader.int32();\n                    break;\n                case \"max_level\":\n                    message.max_level = reader.int32();\n                    break;\n                case \"stage\":\n                    reader.array(message.stage, () => reader.string());\n                    break;\n                case \"not_stage\":\n                    reader.array(message.not_stage, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.NetStateRule.prototype.phase = 0;\ncaffe.NetStateRule.prototype.min_level = 0;\ncaffe.NetStateRule.prototype.max_level = 0;\n\ncaffe.ParamSpec = class ParamSpec {\n\n    static decode(reader, length) {\n        const message = new caffe.ParamSpec();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.share_mode = reader.int32();\n                    break;\n                case 3:\n                    message.lr_mult = reader.float();\n                    break;\n                case 4:\n                    message.decay_mult = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ParamSpec();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"share_mode\":\n                    message.share_mode = reader.enum(caffe.ParamSpec.DimCheckMode);\n                    break;\n                case \"lr_mult\":\n                    message.lr_mult = reader.float();\n                    break;\n                case \"decay_mult\":\n                    message.decay_mult = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ParamSpec.prototype.name = \"\";\ncaffe.ParamSpec.prototype.share_mode = 0;\ncaffe.ParamSpec.prototype.lr_mult = 1;\ncaffe.ParamSpec.prototype.decay_mult = 1;\n\ncaffe.ParamSpec.DimCheckMode = {\n    \"STRICT\": 0,\n    \"PERMISSIVE\": 1\n};\n\ncaffe.LayerParameter = class LayerParameter {\n\n    constructor() {\n        this.bottom = [];\n        this.top = [];\n        this.loss_weight = [];\n        this.param = [];\n        this.blobs = [];\n        this.propagate_down = [];\n        this.include = [];\n        this.exclude = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.LayerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.bottom.push(reader.string());\n                    break;\n                case 4:\n                    message.top.push(reader.string());\n                    break;\n                case 10:\n                    message.phase = reader.int32();\n                    break;\n                case 5:\n                    message.loss_weight = reader.floats(message.loss_weight, tag);\n                    break;\n                case 6:\n                    message.param.push(caffe.ParamSpec.decode(reader, reader.uint32()));\n                    break;\n                case 7:\n                    message.blobs.push(caffe.BlobProto.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    message.propagate_down = reader.array(message.propagate_down, () => reader.bool(), tag);\n                    break;\n                case 8:\n                    message.include.push(caffe.NetStateRule.decode(reader, reader.uint32()));\n                    break;\n                case 9:\n                    message.exclude.push(caffe.NetStateRule.decode(reader, reader.uint32()));\n                    break;\n                case 100:\n                    message.transform_param = caffe.TransformationParameter.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.loss_param = caffe.LossParameter.decode(reader, reader.uint32());\n                    break;\n                case 102:\n                    message.accuracy_param = caffe.AccuracyParameter.decode(reader, reader.uint32());\n                    break;\n                case 103:\n                    message.argmax_param = caffe.ArgMaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 139:\n                    message.batch_norm_param = caffe.BatchNormParameter.decode(reader, reader.uint32());\n                    break;\n                case 141:\n                    message.bias_param = caffe.BiasParameter.decode(reader, reader.uint32());\n                    break;\n                case 148:\n                    message.clip_param = caffe.ClipParameter.decode(reader, reader.uint32());\n                    break;\n                case 104:\n                    message.concat_param = caffe.ConcatParameter.decode(reader, reader.uint32());\n                    break;\n                case 105:\n                    message.contrastive_loss_param = caffe.ContrastiveLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 106:\n                    message.convolution_param = caffe.ConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 144:\n                    message.crop_param = caffe.CropParameter.decode(reader, reader.uint32());\n                    break;\n                case 107:\n                    message.data_param = caffe.DataParameter.decode(reader, reader.uint32());\n                    break;\n                case 108:\n                    message.dropout_param = caffe.DropoutParameter.decode(reader, reader.uint32());\n                    break;\n                case 109:\n                    message.dummy_data_param = caffe.DummyDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 110:\n                    message.eltwise_param = caffe.EltwiseParameter.decode(reader, reader.uint32());\n                    break;\n                case 140:\n                    message.elu_param = caffe.ELUParameter.decode(reader, reader.uint32());\n                    break;\n                case 137:\n                    message.embed_param = caffe.EmbedParameter.decode(reader, reader.uint32());\n                    break;\n                case 111:\n                    message.exp_param = caffe.ExpParameter.decode(reader, reader.uint32());\n                    break;\n                case 135:\n                    message.flatten_param = caffe.FlattenParameter.decode(reader, reader.uint32());\n                    break;\n                case 112:\n                    message.hdf5_data_param = caffe.HDF5DataParameter.decode(reader, reader.uint32());\n                    break;\n                case 113:\n                    message.hdf5_output_param = caffe.HDF5OutputParameter.decode(reader, reader.uint32());\n                    break;\n                case 114:\n                    message.hinge_loss_param = caffe.HingeLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 115:\n                    message.image_data_param = caffe.ImageDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 116:\n                    message.infogain_loss_param = caffe.InfogainLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 117:\n                    message.inner_product_param = caffe.InnerProductParameter.decode(reader, reader.uint32());\n                    break;\n                case 143:\n                    message.input_param = caffe.InputParameter.decode(reader, reader.uint32());\n                    break;\n                case 134:\n                    message.log_param = caffe.LogParameter.decode(reader, reader.uint32());\n                    break;\n                case 118:\n                    message.lrn_param = caffe.LRNParameter.decode(reader, reader.uint32());\n                    break;\n                case 119:\n                    message.memory_data_param = caffe.MemoryDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 120:\n                    message.mvn_param = caffe.MVNParameter.decode(reader, reader.uint32());\n                    break;\n                case 145:\n                    message.parameter_param = caffe.ParameterParameter.decode(reader, reader.uint32());\n                    break;\n                case 121:\n                    message.pooling_param = caffe.PoolingParameter.decode(reader, reader.uint32());\n                    break;\n                case 122:\n                    message.power_param = caffe.PowerParameter.decode(reader, reader.uint32());\n                    break;\n                case 131:\n                    message.prelu_param = caffe.PReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 130:\n                    message.python_param = caffe.PythonParameter.decode(reader, reader.uint32());\n                    break;\n                case 146:\n                    message.recurrent_param = caffe.RecurrentParameter.decode(reader, reader.uint32());\n                    break;\n                case 136:\n                    message.reduction_param = caffe.ReductionParameter.decode(reader, reader.uint32());\n                    break;\n                case 123:\n                    message.relu_param = caffe.ReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 133:\n                    message.reshape_param = caffe.ReshapeParameter.decode(reader, reader.uint32());\n                    break;\n                case 142:\n                    message.scale_param = caffe.ScaleParameter.decode(reader, reader.uint32());\n                    break;\n                case 124:\n                    message.sigmoid_param = caffe.SigmoidParameter.decode(reader, reader.uint32());\n                    break;\n                case 125:\n                    message.softmax_param = caffe.SoftmaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 132:\n                    message.spp_param = caffe.SPPParameter.decode(reader, reader.uint32());\n                    break;\n                case 126:\n                    message.slice_param = caffe.SliceParameter.decode(reader, reader.uint32());\n                    break;\n                case 147:\n                    message.swish_param = caffe.SwishParameter.decode(reader, reader.uint32());\n                    break;\n                case 127:\n                    message.tanh_param = caffe.TanHParameter.decode(reader, reader.uint32());\n                    break;\n                case 128:\n                    message.threshold_param = caffe.ThresholdParameter.decode(reader, reader.uint32());\n                    break;\n                case 138:\n                    message.tile_param = caffe.TileParameter.decode(reader, reader.uint32());\n                    break;\n                case 129:\n                    message.window_data_param = caffe.WindowDataParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.LayerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"bottom\":\n                    reader.array(message.bottom, () => reader.string());\n                    break;\n                case \"top\":\n                    reader.array(message.top, () => reader.string());\n                    break;\n                case \"phase\":\n                    message.phase = reader.enum(caffe.Phase);\n                    break;\n                case \"loss_weight\":\n                    reader.array(message.loss_weight, () => reader.float());\n                    break;\n                case \"param\":\n                    message.param.push(caffe.ParamSpec.decodeText(reader));\n                    break;\n                case \"blobs\":\n                    message.blobs.push(caffe.BlobProto.decodeText(reader));\n                    break;\n                case \"propagate_down\":\n                    reader.array(message.propagate_down, () => reader.bool());\n                    break;\n                case \"include\":\n                    message.include.push(caffe.NetStateRule.decodeText(reader));\n                    break;\n                case \"exclude\":\n                    message.exclude.push(caffe.NetStateRule.decodeText(reader));\n                    break;\n                case \"transform_param\":\n                    message.transform_param = caffe.TransformationParameter.decodeText(reader);\n                    break;\n                case \"loss_param\":\n                    message.loss_param = caffe.LossParameter.decodeText(reader);\n                    break;\n                case \"accuracy_param\":\n                    message.accuracy_param = caffe.AccuracyParameter.decodeText(reader);\n                    break;\n                case \"argmax_param\":\n                    message.argmax_param = caffe.ArgMaxParameter.decodeText(reader);\n                    break;\n                case \"batch_norm_param\":\n                    message.batch_norm_param = caffe.BatchNormParameter.decodeText(reader);\n                    break;\n                case \"bias_param\":\n                    message.bias_param = caffe.BiasParameter.decodeText(reader);\n                    break;\n                case \"clip_param\":\n                    message.clip_param = caffe.ClipParameter.decodeText(reader);\n                    break;\n                case \"concat_param\":\n                    message.concat_param = caffe.ConcatParameter.decodeText(reader);\n                    break;\n                case \"contrastive_loss_param\":\n                    message.contrastive_loss_param = caffe.ContrastiveLossParameter.decodeText(reader);\n                    break;\n                case \"convolution_param\":\n                    message.convolution_param = caffe.ConvolutionParameter.decodeText(reader);\n                    break;\n                case \"crop_param\":\n                    message.crop_param = caffe.CropParameter.decodeText(reader);\n                    break;\n                case \"data_param\":\n                    message.data_param = caffe.DataParameter.decodeText(reader);\n                    break;\n                case \"dropout_param\":\n                    message.dropout_param = caffe.DropoutParameter.decodeText(reader);\n                    break;\n                case \"dummy_data_param\":\n                    message.dummy_data_param = caffe.DummyDataParameter.decodeText(reader);\n                    break;\n                case \"eltwise_param\":\n                    message.eltwise_param = caffe.EltwiseParameter.decodeText(reader);\n                    break;\n                case \"elu_param\":\n                    message.elu_param = caffe.ELUParameter.decodeText(reader);\n                    break;\n                case \"embed_param\":\n                    message.embed_param = caffe.EmbedParameter.decodeText(reader);\n                    break;\n                case \"exp_param\":\n                    message.exp_param = caffe.ExpParameter.decodeText(reader);\n                    break;\n                case \"flatten_param\":\n                    message.flatten_param = caffe.FlattenParameter.decodeText(reader);\n                    break;\n                case \"hdf5_data_param\":\n                    message.hdf5_data_param = caffe.HDF5DataParameter.decodeText(reader);\n                    break;\n                case \"hdf5_output_param\":\n                    message.hdf5_output_param = caffe.HDF5OutputParameter.decodeText(reader);\n                    break;\n                case \"hinge_loss_param\":\n                    message.hinge_loss_param = caffe.HingeLossParameter.decodeText(reader);\n                    break;\n                case \"image_data_param\":\n                    message.image_data_param = caffe.ImageDataParameter.decodeText(reader);\n                    break;\n                case \"infogain_loss_param\":\n                    message.infogain_loss_param = caffe.InfogainLossParameter.decodeText(reader);\n                    break;\n                case \"inner_product_param\":\n                    message.inner_product_param = caffe.InnerProductParameter.decodeText(reader);\n                    break;\n                case \"input_param\":\n                    message.input_param = caffe.InputParameter.decodeText(reader);\n                    break;\n                case \"log_param\":\n                    message.log_param = caffe.LogParameter.decodeText(reader);\n                    break;\n                case \"lrn_param\":\n                    message.lrn_param = caffe.LRNParameter.decodeText(reader);\n                    break;\n                case \"memory_data_param\":\n                    message.memory_data_param = caffe.MemoryDataParameter.decodeText(reader);\n                    break;\n                case \"mvn_param\":\n                    message.mvn_param = caffe.MVNParameter.decodeText(reader);\n                    break;\n                case \"parameter_param\":\n                    message.parameter_param = caffe.ParameterParameter.decodeText(reader);\n                    break;\n                case \"pooling_param\":\n                    message.pooling_param = caffe.PoolingParameter.decodeText(reader);\n                    break;\n                case \"power_param\":\n                    message.power_param = caffe.PowerParameter.decodeText(reader);\n                    break;\n                case \"prelu_param\":\n                    message.prelu_param = caffe.PReLUParameter.decodeText(reader);\n                    break;\n                case \"python_param\":\n                    message.python_param = caffe.PythonParameter.decodeText(reader);\n                    break;\n                case \"recurrent_param\":\n                    message.recurrent_param = caffe.RecurrentParameter.decodeText(reader);\n                    break;\n                case \"reduction_param\":\n                    message.reduction_param = caffe.ReductionParameter.decodeText(reader);\n                    break;\n                case \"relu_param\":\n                    message.relu_param = caffe.ReLUParameter.decodeText(reader);\n                    break;\n                case \"reshape_param\":\n                    message.reshape_param = caffe.ReshapeParameter.decodeText(reader);\n                    break;\n                case \"scale_param\":\n                    message.scale_param = caffe.ScaleParameter.decodeText(reader);\n                    break;\n                case \"sigmoid_param\":\n                    message.sigmoid_param = caffe.SigmoidParameter.decodeText(reader);\n                    break;\n                case \"softmax_param\":\n                    message.softmax_param = caffe.SoftmaxParameter.decodeText(reader);\n                    break;\n                case \"spp_param\":\n                    message.spp_param = caffe.SPPParameter.decodeText(reader);\n                    break;\n                case \"slice_param\":\n                    message.slice_param = caffe.SliceParameter.decodeText(reader);\n                    break;\n                case \"swish_param\":\n                    message.swish_param = caffe.SwishParameter.decodeText(reader);\n                    break;\n                case \"tanh_param\":\n                    message.tanh_param = caffe.TanHParameter.decodeText(reader);\n                    break;\n                case \"threshold_param\":\n                    message.threshold_param = caffe.ThresholdParameter.decodeText(reader);\n                    break;\n                case \"tile_param\":\n                    message.tile_param = caffe.TileParameter.decodeText(reader);\n                    break;\n                case \"window_data_param\":\n                    message.window_data_param = caffe.WindowDataParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.LayerParameter.prototype.name = \"\";\ncaffe.LayerParameter.prototype.type = \"\";\ncaffe.LayerParameter.prototype.phase = 0;\ncaffe.LayerParameter.prototype.transform_param = null;\ncaffe.LayerParameter.prototype.loss_param = null;\ncaffe.LayerParameter.prototype.accuracy_param = null;\ncaffe.LayerParameter.prototype.argmax_param = null;\ncaffe.LayerParameter.prototype.batch_norm_param = null;\ncaffe.LayerParameter.prototype.bias_param = null;\ncaffe.LayerParameter.prototype.clip_param = null;\ncaffe.LayerParameter.prototype.concat_param = null;\ncaffe.LayerParameter.prototype.contrastive_loss_param = null;\ncaffe.LayerParameter.prototype.convolution_param = null;\ncaffe.LayerParameter.prototype.crop_param = null;\ncaffe.LayerParameter.prototype.data_param = null;\ncaffe.LayerParameter.prototype.dropout_param = null;\ncaffe.LayerParameter.prototype.dummy_data_param = null;\ncaffe.LayerParameter.prototype.eltwise_param = null;\ncaffe.LayerParameter.prototype.elu_param = null;\ncaffe.LayerParameter.prototype.embed_param = null;\ncaffe.LayerParameter.prototype.exp_param = null;\ncaffe.LayerParameter.prototype.flatten_param = null;\ncaffe.LayerParameter.prototype.hdf5_data_param = null;\ncaffe.LayerParameter.prototype.hdf5_output_param = null;\ncaffe.LayerParameter.prototype.hinge_loss_param = null;\ncaffe.LayerParameter.prototype.image_data_param = null;\ncaffe.LayerParameter.prototype.infogain_loss_param = null;\ncaffe.LayerParameter.prototype.inner_product_param = null;\ncaffe.LayerParameter.prototype.input_param = null;\ncaffe.LayerParameter.prototype.log_param = null;\ncaffe.LayerParameter.prototype.lrn_param = null;\ncaffe.LayerParameter.prototype.memory_data_param = null;\ncaffe.LayerParameter.prototype.mvn_param = null;\ncaffe.LayerParameter.prototype.parameter_param = null;\ncaffe.LayerParameter.prototype.pooling_param = null;\ncaffe.LayerParameter.prototype.power_param = null;\ncaffe.LayerParameter.prototype.prelu_param = null;\ncaffe.LayerParameter.prototype.python_param = null;\ncaffe.LayerParameter.prototype.recurrent_param = null;\ncaffe.LayerParameter.prototype.reduction_param = null;\ncaffe.LayerParameter.prototype.relu_param = null;\ncaffe.LayerParameter.prototype.reshape_param = null;\ncaffe.LayerParameter.prototype.scale_param = null;\ncaffe.LayerParameter.prototype.sigmoid_param = null;\ncaffe.LayerParameter.prototype.softmax_param = null;\ncaffe.LayerParameter.prototype.spp_param = null;\ncaffe.LayerParameter.prototype.slice_param = null;\ncaffe.LayerParameter.prototype.swish_param = null;\ncaffe.LayerParameter.prototype.tanh_param = null;\ncaffe.LayerParameter.prototype.threshold_param = null;\ncaffe.LayerParameter.prototype.tile_param = null;\ncaffe.LayerParameter.prototype.window_data_param = null;\n\ncaffe.TransformationParameter = class TransformationParameter {\n\n    constructor() {\n        this.mean_value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.TransformationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.scale = reader.float();\n                    break;\n                case 2:\n                    message.mirror = reader.bool();\n                    break;\n                case 3:\n                    message.crop_size = reader.uint32();\n                    break;\n                case 4:\n                    message.mean_file = reader.string();\n                    break;\n                case 5:\n                    message.mean_value = reader.floats(message.mean_value, tag);\n                    break;\n                case 6:\n                    message.force_color = reader.bool();\n                    break;\n                case 7:\n                    message.force_gray = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.TransformationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"mirror\":\n                    message.mirror = reader.bool();\n                    break;\n                case \"crop_size\":\n                    message.crop_size = reader.uint32();\n                    break;\n                case \"mean_file\":\n                    message.mean_file = reader.string();\n                    break;\n                case \"mean_value\":\n                    reader.array(message.mean_value, () => reader.float());\n                    break;\n                case \"force_color\":\n                    message.force_color = reader.bool();\n                    break;\n                case \"force_gray\":\n                    message.force_gray = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.TransformationParameter.prototype.scale = 1;\ncaffe.TransformationParameter.prototype.mirror = false;\ncaffe.TransformationParameter.prototype.crop_size = 0;\ncaffe.TransformationParameter.prototype.mean_file = \"\";\ncaffe.TransformationParameter.prototype.force_color = false;\ncaffe.TransformationParameter.prototype.force_gray = false;\n\ncaffe.LossParameter = class LossParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.LossParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.ignore_label = reader.int32();\n                    break;\n                case 3:\n                    message.normalization = reader.int32();\n                    break;\n                case 2:\n                    message.normalize = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.LossParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"ignore_label\":\n                    message.ignore_label = reader.int32();\n                    break;\n                case \"normalization\":\n                    message.normalization = reader.enum(caffe.LossParameter.NormalizationMode);\n                    break;\n                case \"normalize\":\n                    message.normalize = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.LossParameter.prototype.ignore_label = 0;\ncaffe.LossParameter.prototype.normalization = 1;\ncaffe.LossParameter.prototype.normalize = false;\n\ncaffe.LossParameter.NormalizationMode = {\n    \"FULL\": 0,\n    \"VALID\": 1,\n    \"BATCH_SIZE\": 2,\n    \"NONE\": 3\n};\n\ncaffe.AccuracyParameter = class AccuracyParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.AccuracyParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.top_k = reader.uint32();\n                    break;\n                case 2:\n                    message.axis = reader.int32();\n                    break;\n                case 3:\n                    message.ignore_label = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.AccuracyParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"top_k\":\n                    message.top_k = reader.uint32();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"ignore_label\":\n                    message.ignore_label = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.AccuracyParameter.prototype.top_k = 1;\ncaffe.AccuracyParameter.prototype.axis = 1;\ncaffe.AccuracyParameter.prototype.ignore_label = 0;\n\ncaffe.ArgMaxParameter = class ArgMaxParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ArgMaxParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.out_max_val = reader.bool();\n                    break;\n                case 2:\n                    message.top_k = reader.uint32();\n                    break;\n                case 3:\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ArgMaxParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"out_max_val\":\n                    message.out_max_val = reader.bool();\n                    break;\n                case \"top_k\":\n                    message.top_k = reader.uint32();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ArgMaxParameter.prototype.out_max_val = false;\ncaffe.ArgMaxParameter.prototype.top_k = 1;\ncaffe.ArgMaxParameter.prototype.axis = 0;\n\ncaffe.ClipParameter = class ClipParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ClipParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.min = reader.float();\n                    break;\n                case 2:\n                    message.max = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ClipParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"min\":\n                    message.min = reader.float();\n                    break;\n                case \"max\":\n                    message.max = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ClipParameter.prototype.min = 0;\ncaffe.ClipParameter.prototype.max = 0;\n\ncaffe.ConcatParameter = class ConcatParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ConcatParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.axis = reader.int32();\n                    break;\n                case 1:\n                    message.concat_dim = reader.uint32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ConcatParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"concat_dim\":\n                    message.concat_dim = reader.uint32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ConcatParameter.prototype.axis = 1;\ncaffe.ConcatParameter.prototype.concat_dim = 1;\n\ncaffe.BatchNormParameter = class BatchNormParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.BatchNormParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.use_global_stats = reader.bool();\n                    break;\n                case 2:\n                    message.moving_average_fraction = reader.float();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.BatchNormParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"use_global_stats\":\n                    message.use_global_stats = reader.bool();\n                    break;\n                case \"moving_average_fraction\":\n                    message.moving_average_fraction = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.BatchNormParameter.prototype.use_global_stats = false;\ncaffe.BatchNormParameter.prototype.moving_average_fraction = 0.999;\ncaffe.BatchNormParameter.prototype.eps = 0.00001;\n\ncaffe.BiasParameter = class BiasParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.BiasParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int32();\n                    break;\n                case 2:\n                    message.num_axes = reader.int32();\n                    break;\n                case 3:\n                    message.filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.BiasParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"num_axes\":\n                    message.num_axes = reader.int32();\n                    break;\n                case \"filler\":\n                    message.filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.BiasParameter.prototype.axis = 1;\ncaffe.BiasParameter.prototype.num_axes = 1;\ncaffe.BiasParameter.prototype.filler = null;\n\ncaffe.ContrastiveLossParameter = class ContrastiveLossParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ContrastiveLossParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.margin = reader.float();\n                    break;\n                case 2:\n                    message.legacy_version = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ContrastiveLossParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"margin\":\n                    message.margin = reader.float();\n                    break;\n                case \"legacy_version\":\n                    message.legacy_version = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ContrastiveLossParameter.prototype.margin = 1;\ncaffe.ContrastiveLossParameter.prototype.legacy_version = false;\n\ncaffe.ConvolutionParameter = class ConvolutionParameter {\n\n    constructor() {\n        this.pad = [];\n        this.kernel_size = [];\n        this.stride = [];\n        this.dilation = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.ConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_output = reader.uint32();\n                    break;\n                case 2:\n                    message.bias_term = reader.bool();\n                    break;\n                case 3:\n                    message.pad = reader.array(message.pad, () => reader.uint32(), tag);\n                    break;\n                case 4:\n                    message.kernel_size = reader.array(message.kernel_size, () => reader.uint32(), tag);\n                    break;\n                case 6:\n                    message.stride = reader.array(message.stride, () => reader.uint32(), tag);\n                    break;\n                case 18:\n                    message.dilation = reader.array(message.dilation, () => reader.uint32(), tag);\n                    break;\n                case 9:\n                    message.pad_h = reader.uint32();\n                    break;\n                case 10:\n                    message.pad_w = reader.uint32();\n                    break;\n                case 11:\n                    message.kernel_h = reader.uint32();\n                    break;\n                case 12:\n                    message.kernel_w = reader.uint32();\n                    break;\n                case 13:\n                    message.stride_h = reader.uint32();\n                    break;\n                case 14:\n                    message.stride_w = reader.uint32();\n                    break;\n                case 5:\n                    message.group = reader.uint32();\n                    break;\n                case 7:\n                    message.weight_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 8:\n                    message.bias_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.engine = reader.int32();\n                    break;\n                case 16:\n                    message.axis = reader.int32();\n                    break;\n                case 17:\n                    message.force_nd_im2col = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_output\":\n                    message.num_output = reader.uint32();\n                    break;\n                case \"bias_term\":\n                    message.bias_term = reader.bool();\n                    break;\n                case \"pad\":\n                    reader.array(message.pad, () => reader.uint32());\n                    break;\n                case \"kernel_size\":\n                    reader.array(message.kernel_size, () => reader.uint32());\n                    break;\n                case \"stride\":\n                    reader.array(message.stride, () => reader.uint32());\n                    break;\n                case \"dilation\":\n                    reader.array(message.dilation, () => reader.uint32());\n                    break;\n                case \"pad_h\":\n                    message.pad_h = reader.uint32();\n                    break;\n                case \"pad_w\":\n                    message.pad_w = reader.uint32();\n                    break;\n                case \"kernel_h\":\n                    message.kernel_h = reader.uint32();\n                    break;\n                case \"kernel_w\":\n                    message.kernel_w = reader.uint32();\n                    break;\n                case \"stride_h\":\n                    message.stride_h = reader.uint32();\n                    break;\n                case \"stride_w\":\n                    message.stride_w = reader.uint32();\n                    break;\n                case \"group\":\n                    message.group = reader.uint32();\n                    break;\n                case \"weight_filler\":\n                    message.weight_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"bias_filler\":\n                    message.bias_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"engine\":\n                    message.engine = reader.enum(caffe.ConvolutionParameter.Engine);\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"force_nd_im2col\":\n                    message.force_nd_im2col = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ConvolutionParameter.prototype.num_output = 0;\ncaffe.ConvolutionParameter.prototype.bias_term = true;\ncaffe.ConvolutionParameter.prototype.pad_h = 0;\ncaffe.ConvolutionParameter.prototype.pad_w = 0;\ncaffe.ConvolutionParameter.prototype.kernel_h = 0;\ncaffe.ConvolutionParameter.prototype.kernel_w = 0;\ncaffe.ConvolutionParameter.prototype.stride_h = 0;\ncaffe.ConvolutionParameter.prototype.stride_w = 0;\ncaffe.ConvolutionParameter.prototype.group = 1;\ncaffe.ConvolutionParameter.prototype.weight_filler = null;\ncaffe.ConvolutionParameter.prototype.bias_filler = null;\ncaffe.ConvolutionParameter.prototype.engine = 0;\ncaffe.ConvolutionParameter.prototype.axis = 1;\ncaffe.ConvolutionParameter.prototype.force_nd_im2col = false;\n\ncaffe.ConvolutionParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.CropParameter = class CropParameter {\n\n    constructor() {\n        this.offset = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.CropParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int32();\n                    break;\n                case 2:\n                    message.offset = reader.array(message.offset, () => reader.uint32(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.CropParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"offset\":\n                    reader.array(message.offset, () => reader.uint32());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.CropParameter.prototype.axis = 2;\n\ncaffe.DataParameter = class DataParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.DataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.source = reader.string();\n                    break;\n                case 4:\n                    message.batch_size = reader.uint32();\n                    break;\n                case 7:\n                    message.rand_skip = reader.uint32();\n                    break;\n                case 8:\n                    message.backend = reader.int32();\n                    break;\n                case 2:\n                    message.scale = reader.float();\n                    break;\n                case 3:\n                    message.mean_file = reader.string();\n                    break;\n                case 5:\n                    message.crop_size = reader.uint32();\n                    break;\n                case 6:\n                    message.mirror = reader.bool();\n                    break;\n                case 9:\n                    message.force_encoded_color = reader.bool();\n                    break;\n                case 10:\n                    message.prefetch = reader.uint32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.DataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"batch_size\":\n                    message.batch_size = reader.uint32();\n                    break;\n                case \"rand_skip\":\n                    message.rand_skip = reader.uint32();\n                    break;\n                case \"backend\":\n                    message.backend = reader.enum(caffe.DataParameter.DB);\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"mean_file\":\n                    message.mean_file = reader.string();\n                    break;\n                case \"crop_size\":\n                    message.crop_size = reader.uint32();\n                    break;\n                case \"mirror\":\n                    message.mirror = reader.bool();\n                    break;\n                case \"force_encoded_color\":\n                    message.force_encoded_color = reader.bool();\n                    break;\n                case \"prefetch\":\n                    message.prefetch = reader.uint32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.DataParameter.prototype.source = \"\";\ncaffe.DataParameter.prototype.batch_size = 0;\ncaffe.DataParameter.prototype.rand_skip = 0;\ncaffe.DataParameter.prototype.backend = 0;\ncaffe.DataParameter.prototype.scale = 1;\ncaffe.DataParameter.prototype.mean_file = \"\";\ncaffe.DataParameter.prototype.crop_size = 0;\ncaffe.DataParameter.prototype.mirror = false;\ncaffe.DataParameter.prototype.force_encoded_color = false;\ncaffe.DataParameter.prototype.prefetch = 4;\n\ncaffe.DataParameter.DB = {\n    \"LEVELDB\": 0,\n    \"LMDB\": 1\n};\n\ncaffe.DropoutParameter = class DropoutParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.DropoutParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dropout_ratio = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.DropoutParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dropout_ratio\":\n                    message.dropout_ratio = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.DropoutParameter.prototype.dropout_ratio = 0.5;\n\ncaffe.DummyDataParameter = class DummyDataParameter {\n\n    constructor() {\n        this.data_filler = [];\n        this.shape = [];\n        this.num = [];\n        this.channels = [];\n        this.height = [];\n        this.width = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.DummyDataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.data_filler.push(caffe.FillerParameter.decode(reader, reader.uint32()));\n                    break;\n                case 6:\n                    message.shape.push(caffe.BlobShape.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.num = reader.array(message.num, () => reader.uint32(), tag);\n                    break;\n                case 3:\n                    message.channels = reader.array(message.channels, () => reader.uint32(), tag);\n                    break;\n                case 4:\n                    message.height = reader.array(message.height, () => reader.uint32(), tag);\n                    break;\n                case 5:\n                    message.width = reader.array(message.width, () => reader.uint32(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.DummyDataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"data_filler\":\n                    message.data_filler.push(caffe.FillerParameter.decodeText(reader));\n                    break;\n                case \"shape\":\n                    message.shape.push(caffe.BlobShape.decodeText(reader));\n                    break;\n                case \"num\":\n                    reader.array(message.num, () => reader.uint32());\n                    break;\n                case \"channels\":\n                    reader.array(message.channels, () => reader.uint32());\n                    break;\n                case \"height\":\n                    reader.array(message.height, () => reader.uint32());\n                    break;\n                case \"width\":\n                    reader.array(message.width, () => reader.uint32());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.EltwiseParameter = class EltwiseParameter {\n\n    constructor() {\n        this.coeff = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.EltwiseParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.operation = reader.int32();\n                    break;\n                case 2:\n                    message.coeff = reader.floats(message.coeff, tag);\n                    break;\n                case 3:\n                    message.stable_prod_grad = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.EltwiseParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"operation\":\n                    message.operation = reader.enum(caffe.EltwiseParameter.EltwiseOp);\n                    break;\n                case \"coeff\":\n                    reader.array(message.coeff, () => reader.float());\n                    break;\n                case \"stable_prod_grad\":\n                    message.stable_prod_grad = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.EltwiseParameter.prototype.operation = 1;\ncaffe.EltwiseParameter.prototype.stable_prod_grad = true;\n\ncaffe.EltwiseParameter.EltwiseOp = {\n    \"PROD\": 0,\n    \"SUM\": 1,\n    \"MAX\": 2\n};\n\ncaffe.ELUParameter = class ELUParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ELUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ELUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ELUParameter.prototype.alpha = 1;\n\ncaffe.EmbedParameter = class EmbedParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.EmbedParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_output = reader.uint32();\n                    break;\n                case 2:\n                    message.input_dim = reader.uint32();\n                    break;\n                case 3:\n                    message.bias_term = reader.bool();\n                    break;\n                case 4:\n                    message.weight_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.bias_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.EmbedParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_output\":\n                    message.num_output = reader.uint32();\n                    break;\n                case \"input_dim\":\n                    message.input_dim = reader.uint32();\n                    break;\n                case \"bias_term\":\n                    message.bias_term = reader.bool();\n                    break;\n                case \"weight_filler\":\n                    message.weight_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"bias_filler\":\n                    message.bias_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.EmbedParameter.prototype.num_output = 0;\ncaffe.EmbedParameter.prototype.input_dim = 0;\ncaffe.EmbedParameter.prototype.bias_term = true;\ncaffe.EmbedParameter.prototype.weight_filler = null;\ncaffe.EmbedParameter.prototype.bias_filler = null;\n\ncaffe.ExpParameter = class ExpParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ExpParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base = reader.float();\n                    break;\n                case 2:\n                    message.scale = reader.float();\n                    break;\n                case 3:\n                    message.shift = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ExpParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base\":\n                    message.base = reader.float();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"shift\":\n                    message.shift = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ExpParameter.prototype.base = -1;\ncaffe.ExpParameter.prototype.scale = 1;\ncaffe.ExpParameter.prototype.shift = 0;\n\ncaffe.FlattenParameter = class FlattenParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.FlattenParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int32();\n                    break;\n                case 2:\n                    message.end_axis = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.FlattenParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"end_axis\":\n                    message.end_axis = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.FlattenParameter.prototype.axis = 1;\ncaffe.FlattenParameter.prototype.end_axis = -1;\n\ncaffe.HDF5DataParameter = class HDF5DataParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.HDF5DataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.source = reader.string();\n                    break;\n                case 2:\n                    message.batch_size = reader.uint32();\n                    break;\n                case 3:\n                    message.shuffle = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.HDF5DataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"batch_size\":\n                    message.batch_size = reader.uint32();\n                    break;\n                case \"shuffle\":\n                    message.shuffle = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.HDF5DataParameter.prototype.source = \"\";\ncaffe.HDF5DataParameter.prototype.batch_size = 0;\ncaffe.HDF5DataParameter.prototype.shuffle = false;\n\ncaffe.HDF5OutputParameter = class HDF5OutputParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.HDF5OutputParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.file_name = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.HDF5OutputParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"file_name\":\n                    message.file_name = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.HDF5OutputParameter.prototype.file_name = \"\";\n\ncaffe.HingeLossParameter = class HingeLossParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.HingeLossParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.norm = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.HingeLossParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"norm\":\n                    message.norm = reader.enum(caffe.HingeLossParameter.Norm);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.HingeLossParameter.prototype.norm = 1;\n\ncaffe.HingeLossParameter.Norm = {\n    \"L1\": 1,\n    \"L2\": 2\n};\n\ncaffe.ImageDataParameter = class ImageDataParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ImageDataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.source = reader.string();\n                    break;\n                case 4:\n                    message.batch_size = reader.uint32();\n                    break;\n                case 7:\n                    message.rand_skip = reader.uint32();\n                    break;\n                case 8:\n                    message.shuffle = reader.bool();\n                    break;\n                case 9:\n                    message.new_height = reader.uint32();\n                    break;\n                case 10:\n                    message.new_width = reader.uint32();\n                    break;\n                case 11:\n                    message.is_color = reader.bool();\n                    break;\n                case 2:\n                    message.scale = reader.float();\n                    break;\n                case 3:\n                    message.mean_file = reader.string();\n                    break;\n                case 5:\n                    message.crop_size = reader.uint32();\n                    break;\n                case 6:\n                    message.mirror = reader.bool();\n                    break;\n                case 12:\n                    message.root_folder = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ImageDataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"batch_size\":\n                    message.batch_size = reader.uint32();\n                    break;\n                case \"rand_skip\":\n                    message.rand_skip = reader.uint32();\n                    break;\n                case \"shuffle\":\n                    message.shuffle = reader.bool();\n                    break;\n                case \"new_height\":\n                    message.new_height = reader.uint32();\n                    break;\n                case \"new_width\":\n                    message.new_width = reader.uint32();\n                    break;\n                case \"is_color\":\n                    message.is_color = reader.bool();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"mean_file\":\n                    message.mean_file = reader.string();\n                    break;\n                case \"crop_size\":\n                    message.crop_size = reader.uint32();\n                    break;\n                case \"mirror\":\n                    message.mirror = reader.bool();\n                    break;\n                case \"root_folder\":\n                    message.root_folder = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ImageDataParameter.prototype.source = \"\";\ncaffe.ImageDataParameter.prototype.batch_size = 1;\ncaffe.ImageDataParameter.prototype.rand_skip = 0;\ncaffe.ImageDataParameter.prototype.shuffle = false;\ncaffe.ImageDataParameter.prototype.new_height = 0;\ncaffe.ImageDataParameter.prototype.new_width = 0;\ncaffe.ImageDataParameter.prototype.is_color = true;\ncaffe.ImageDataParameter.prototype.scale = 1;\ncaffe.ImageDataParameter.prototype.mean_file = \"\";\ncaffe.ImageDataParameter.prototype.crop_size = 0;\ncaffe.ImageDataParameter.prototype.mirror = false;\ncaffe.ImageDataParameter.prototype.root_folder = \"\";\n\ncaffe.InfogainLossParameter = class InfogainLossParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.InfogainLossParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.source = reader.string();\n                    break;\n                case 2:\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.InfogainLossParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.InfogainLossParameter.prototype.source = \"\";\ncaffe.InfogainLossParameter.prototype.axis = 1;\n\ncaffe.InnerProductParameter = class InnerProductParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.InnerProductParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_output = reader.uint32();\n                    break;\n                case 2:\n                    message.bias_term = reader.bool();\n                    break;\n                case 3:\n                    message.weight_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.bias_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.axis = reader.int32();\n                    break;\n                case 6:\n                    message.transpose = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.InnerProductParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_output\":\n                    message.num_output = reader.uint32();\n                    break;\n                case \"bias_term\":\n                    message.bias_term = reader.bool();\n                    break;\n                case \"weight_filler\":\n                    message.weight_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"bias_filler\":\n                    message.bias_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"transpose\":\n                    message.transpose = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.InnerProductParameter.prototype.num_output = 0;\ncaffe.InnerProductParameter.prototype.bias_term = true;\ncaffe.InnerProductParameter.prototype.weight_filler = null;\ncaffe.InnerProductParameter.prototype.bias_filler = null;\ncaffe.InnerProductParameter.prototype.axis = 1;\ncaffe.InnerProductParameter.prototype.transpose = false;\n\ncaffe.InputParameter = class InputParameter {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.InputParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape.push(caffe.BlobShape.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.InputParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape.push(caffe.BlobShape.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.LogParameter = class LogParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.LogParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base = reader.float();\n                    break;\n                case 2:\n                    message.scale = reader.float();\n                    break;\n                case 3:\n                    message.shift = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.LogParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base\":\n                    message.base = reader.float();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"shift\":\n                    message.shift = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.LogParameter.prototype.base = -1;\ncaffe.LogParameter.prototype.scale = 1;\ncaffe.LogParameter.prototype.shift = 0;\n\ncaffe.LRNParameter = class LRNParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.LRNParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.local_size = reader.uint32();\n                    break;\n                case 2:\n                    message.alpha = reader.float();\n                    break;\n                case 3:\n                    message.beta = reader.float();\n                    break;\n                case 4:\n                    message.norm_region = reader.int32();\n                    break;\n                case 5:\n                    message.k = reader.float();\n                    break;\n                case 6:\n                    message.engine = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.LRNParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"local_size\":\n                    message.local_size = reader.uint32();\n                    break;\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                case \"norm_region\":\n                    message.norm_region = reader.enum(caffe.LRNParameter.NormRegion);\n                    break;\n                case \"k\":\n                    message.k = reader.float();\n                    break;\n                case \"engine\":\n                    message.engine = reader.enum(caffe.LRNParameter.Engine);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.LRNParameter.prototype.local_size = 5;\ncaffe.LRNParameter.prototype.alpha = 1;\ncaffe.LRNParameter.prototype.beta = 0.75;\ncaffe.LRNParameter.prototype.norm_region = 0;\ncaffe.LRNParameter.prototype.k = 1;\ncaffe.LRNParameter.prototype.engine = 0;\n\ncaffe.LRNParameter.NormRegion = {\n    \"ACROSS_CHANNELS\": 0,\n    \"WITHIN_CHANNEL\": 1\n};\n\ncaffe.LRNParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.MemoryDataParameter = class MemoryDataParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.MemoryDataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.batch_size = reader.uint32();\n                    break;\n                case 2:\n                    message.channels = reader.uint32();\n                    break;\n                case 3:\n                    message.height = reader.uint32();\n                    break;\n                case 4:\n                    message.width = reader.uint32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.MemoryDataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"batch_size\":\n                    message.batch_size = reader.uint32();\n                    break;\n                case \"channels\":\n                    message.channels = reader.uint32();\n                    break;\n                case \"height\":\n                    message.height = reader.uint32();\n                    break;\n                case \"width\":\n                    message.width = reader.uint32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.MemoryDataParameter.prototype.batch_size = 0;\ncaffe.MemoryDataParameter.prototype.channels = 0;\ncaffe.MemoryDataParameter.prototype.height = 0;\ncaffe.MemoryDataParameter.prototype.width = 0;\n\ncaffe.MVNParameter = class MVNParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.MVNParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.normalize_variance = reader.bool();\n                    break;\n                case 2:\n                    message.across_channels = reader.bool();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.MVNParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"normalize_variance\":\n                    message.normalize_variance = reader.bool();\n                    break;\n                case \"across_channels\":\n                    message.across_channels = reader.bool();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.MVNParameter.prototype.normalize_variance = true;\ncaffe.MVNParameter.prototype.across_channels = false;\ncaffe.MVNParameter.prototype.eps = 1e-9;\n\ncaffe.ParameterParameter = class ParameterParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ParameterParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = caffe.BlobShape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ParameterParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = caffe.BlobShape.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ParameterParameter.prototype.shape = null;\n\ncaffe.PoolingParameter = class PoolingParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.PoolingParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.pool = reader.int32();\n                    break;\n                case 4:\n                    message.pad = reader.uint32();\n                    break;\n                case 9:\n                    message.pad_h = reader.uint32();\n                    break;\n                case 10:\n                    message.pad_w = reader.uint32();\n                    break;\n                case 2:\n                    message.kernel_size = reader.uint32();\n                    break;\n                case 5:\n                    message.kernel_h = reader.uint32();\n                    break;\n                case 6:\n                    message.kernel_w = reader.uint32();\n                    break;\n                case 3:\n                    message.stride = reader.uint32();\n                    break;\n                case 7:\n                    message.stride_h = reader.uint32();\n                    break;\n                case 8:\n                    message.stride_w = reader.uint32();\n                    break;\n                case 11:\n                    message.engine = reader.int32();\n                    break;\n                case 12:\n                    message.global_pooling = reader.bool();\n                    break;\n                case 13:\n                    message.round_mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.PoolingParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"pool\":\n                    message.pool = reader.enum(caffe.PoolingParameter.PoolMethod);\n                    break;\n                case \"pad\":\n                    message.pad = reader.uint32();\n                    break;\n                case \"pad_h\":\n                    message.pad_h = reader.uint32();\n                    break;\n                case \"pad_w\":\n                    message.pad_w = reader.uint32();\n                    break;\n                case \"kernel_size\":\n                    message.kernel_size = reader.uint32();\n                    break;\n                case \"kernel_h\":\n                    message.kernel_h = reader.uint32();\n                    break;\n                case \"kernel_w\":\n                    message.kernel_w = reader.uint32();\n                    break;\n                case \"stride\":\n                    message.stride = reader.uint32();\n                    break;\n                case \"stride_h\":\n                    message.stride_h = reader.uint32();\n                    break;\n                case \"stride_w\":\n                    message.stride_w = reader.uint32();\n                    break;\n                case \"engine\":\n                    message.engine = reader.enum(caffe.PoolingParameter.Engine);\n                    break;\n                case \"global_pooling\":\n                    message.global_pooling = reader.bool();\n                    break;\n                case \"round_mode\":\n                    message.round_mode = reader.enum(caffe.PoolingParameter.RoundMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.PoolingParameter.prototype.pool = 0;\ncaffe.PoolingParameter.prototype.pad = 0;\ncaffe.PoolingParameter.prototype.pad_h = 0;\ncaffe.PoolingParameter.prototype.pad_w = 0;\ncaffe.PoolingParameter.prototype.kernel_size = 0;\ncaffe.PoolingParameter.prototype.kernel_h = 0;\ncaffe.PoolingParameter.prototype.kernel_w = 0;\ncaffe.PoolingParameter.prototype.stride = 1;\ncaffe.PoolingParameter.prototype.stride_h = 0;\ncaffe.PoolingParameter.prototype.stride_w = 0;\ncaffe.PoolingParameter.prototype.engine = 0;\ncaffe.PoolingParameter.prototype.global_pooling = false;\ncaffe.PoolingParameter.prototype.round_mode = 0;\n\ncaffe.PoolingParameter.PoolMethod = {\n    \"MAX\": 0,\n    \"AVE\": 1,\n    \"STOCHASTIC\": 2\n};\n\ncaffe.PoolingParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.PoolingParameter.RoundMode = {\n    \"CEIL\": 0,\n    \"FLOOR\": 1\n};\n\ncaffe.PowerParameter = class PowerParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.PowerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.power = reader.float();\n                    break;\n                case 2:\n                    message.scale = reader.float();\n                    break;\n                case 3:\n                    message.shift = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.PowerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"power\":\n                    message.power = reader.float();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"shift\":\n                    message.shift = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.PowerParameter.prototype.power = 1;\ncaffe.PowerParameter.prototype.scale = 1;\ncaffe.PowerParameter.prototype.shift = 0;\n\ncaffe.PythonParameter = class PythonParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.PythonParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.module = reader.string();\n                    break;\n                case 2:\n                    message.layer = reader.string();\n                    break;\n                case 3:\n                    message.param_str = reader.string();\n                    break;\n                case 4:\n                    message.share_in_parallel = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.PythonParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"module\":\n                    message.module = reader.string();\n                    break;\n                case \"layer\":\n                    message.layer = reader.string();\n                    break;\n                case \"param_str\":\n                    message.param_str = reader.string();\n                    break;\n                case \"share_in_parallel\":\n                    message.share_in_parallel = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.PythonParameter.prototype.module = \"\";\ncaffe.PythonParameter.prototype.layer = \"\";\ncaffe.PythonParameter.prototype.param_str = \"\";\ncaffe.PythonParameter.prototype.share_in_parallel = false;\n\ncaffe.RecurrentParameter = class RecurrentParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.RecurrentParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_output = reader.uint32();\n                    break;\n                case 2:\n                    message.weight_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.bias_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.debug_info = reader.bool();\n                    break;\n                case 5:\n                    message.expose_hidden = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.RecurrentParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_output\":\n                    message.num_output = reader.uint32();\n                    break;\n                case \"weight_filler\":\n                    message.weight_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"bias_filler\":\n                    message.bias_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"debug_info\":\n                    message.debug_info = reader.bool();\n                    break;\n                case \"expose_hidden\":\n                    message.expose_hidden = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.RecurrentParameter.prototype.num_output = 0;\ncaffe.RecurrentParameter.prototype.weight_filler = null;\ncaffe.RecurrentParameter.prototype.bias_filler = null;\ncaffe.RecurrentParameter.prototype.debug_info = false;\ncaffe.RecurrentParameter.prototype.expose_hidden = false;\n\ncaffe.ReductionParameter = class ReductionParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ReductionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.operation = reader.int32();\n                    break;\n                case 2:\n                    message.axis = reader.int32();\n                    break;\n                case 3:\n                    message.coeff = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ReductionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"operation\":\n                    message.operation = reader.enum(caffe.ReductionParameter.ReductionOp);\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"coeff\":\n                    message.coeff = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ReductionParameter.prototype.operation = 1;\ncaffe.ReductionParameter.prototype.axis = 0;\ncaffe.ReductionParameter.prototype.coeff = 1;\n\ncaffe.ReductionParameter.ReductionOp = {\n    \"SUM\": 1,\n    \"ASUM\": 2,\n    \"SUMSQ\": 3,\n    \"MEAN\": 4\n};\n\ncaffe.ReLUParameter = class ReLUParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ReLUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.negative_slope = reader.float();\n                    break;\n                case 2:\n                    message.engine = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ReLUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"negative_slope\":\n                    message.negative_slope = reader.float();\n                    break;\n                case \"engine\":\n                    message.engine = reader.enum(caffe.ReLUParameter.Engine);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ReLUParameter.prototype.negative_slope = 0;\ncaffe.ReLUParameter.prototype.engine = 0;\n\ncaffe.ReLUParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.ReshapeParameter = class ReshapeParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ReshapeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = caffe.BlobShape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.axis = reader.int32();\n                    break;\n                case 3:\n                    message.num_axes = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ReshapeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = caffe.BlobShape.decodeText(reader);\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"num_axes\":\n                    message.num_axes = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ReshapeParameter.prototype.shape = null;\ncaffe.ReshapeParameter.prototype.axis = 0;\ncaffe.ReshapeParameter.prototype.num_axes = -1;\n\ncaffe.ScaleParameter = class ScaleParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ScaleParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int32();\n                    break;\n                case 2:\n                    message.num_axes = reader.int32();\n                    break;\n                case 3:\n                    message.filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.bias_term = reader.bool();\n                    break;\n                case 5:\n                    message.bias_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ScaleParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"num_axes\":\n                    message.num_axes = reader.int32();\n                    break;\n                case \"filler\":\n                    message.filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"bias_term\":\n                    message.bias_term = reader.bool();\n                    break;\n                case \"bias_filler\":\n                    message.bias_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ScaleParameter.prototype.axis = 1;\ncaffe.ScaleParameter.prototype.num_axes = 1;\ncaffe.ScaleParameter.prototype.filler = null;\ncaffe.ScaleParameter.prototype.bias_term = false;\ncaffe.ScaleParameter.prototype.bias_filler = null;\n\ncaffe.SigmoidParameter = class SigmoidParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.SigmoidParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.engine = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SigmoidParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"engine\":\n                    message.engine = reader.enum(caffe.SigmoidParameter.Engine);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SigmoidParameter.prototype.engine = 0;\n\ncaffe.SigmoidParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.SliceParameter = class SliceParameter {\n\n    constructor() {\n        this.slice_point = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.SliceParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 3:\n                    message.axis = reader.int32();\n                    break;\n                case 2:\n                    message.slice_point = reader.array(message.slice_point, () => reader.uint32(), tag);\n                    break;\n                case 1:\n                    message.slice_dim = reader.uint32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SliceParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"slice_point\":\n                    reader.array(message.slice_point, () => reader.uint32());\n                    break;\n                case \"slice_dim\":\n                    message.slice_dim = reader.uint32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SliceParameter.prototype.axis = 1;\ncaffe.SliceParameter.prototype.slice_dim = 1;\n\ncaffe.SoftmaxParameter = class SoftmaxParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.SoftmaxParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.engine = reader.int32();\n                    break;\n                case 2:\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SoftmaxParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"engine\":\n                    message.engine = reader.enum(caffe.SoftmaxParameter.Engine);\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SoftmaxParameter.prototype.engine = 0;\ncaffe.SoftmaxParameter.prototype.axis = 1;\n\ncaffe.SoftmaxParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.SwishParameter = class SwishParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.SwishParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SwishParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SwishParameter.prototype.beta = 1;\n\ncaffe.TanHParameter = class TanHParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.TanHParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.engine = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.TanHParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"engine\":\n                    message.engine = reader.enum(caffe.TanHParameter.Engine);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.TanHParameter.prototype.engine = 0;\n\ncaffe.TanHParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.TileParameter = class TileParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.TileParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int32();\n                    break;\n                case 2:\n                    message.tiles = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.TileParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"tiles\":\n                    message.tiles = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.TileParameter.prototype.axis = 1;\ncaffe.TileParameter.prototype.tiles = 0;\n\ncaffe.ThresholdParameter = class ThresholdParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.ThresholdParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.threshold = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.ThresholdParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"threshold\":\n                    message.threshold = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.ThresholdParameter.prototype.threshold = 0;\n\ncaffe.WindowDataParameter = class WindowDataParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.WindowDataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.source = reader.string();\n                    break;\n                case 2:\n                    message.scale = reader.float();\n                    break;\n                case 3:\n                    message.mean_file = reader.string();\n                    break;\n                case 4:\n                    message.batch_size = reader.uint32();\n                    break;\n                case 5:\n                    message.crop_size = reader.uint32();\n                    break;\n                case 6:\n                    message.mirror = reader.bool();\n                    break;\n                case 7:\n                    message.fg_threshold = reader.float();\n                    break;\n                case 8:\n                    message.bg_threshold = reader.float();\n                    break;\n                case 9:\n                    message.fg_fraction = reader.float();\n                    break;\n                case 10:\n                    message.context_pad = reader.uint32();\n                    break;\n                case 11:\n                    message.crop_mode = reader.string();\n                    break;\n                case 12:\n                    message.cache_images = reader.bool();\n                    break;\n                case 13:\n                    message.root_folder = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.WindowDataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"mean_file\":\n                    message.mean_file = reader.string();\n                    break;\n                case \"batch_size\":\n                    message.batch_size = reader.uint32();\n                    break;\n                case \"crop_size\":\n                    message.crop_size = reader.uint32();\n                    break;\n                case \"mirror\":\n                    message.mirror = reader.bool();\n                    break;\n                case \"fg_threshold\":\n                    message.fg_threshold = reader.float();\n                    break;\n                case \"bg_threshold\":\n                    message.bg_threshold = reader.float();\n                    break;\n                case \"fg_fraction\":\n                    message.fg_fraction = reader.float();\n                    break;\n                case \"context_pad\":\n                    message.context_pad = reader.uint32();\n                    break;\n                case \"crop_mode\":\n                    message.crop_mode = reader.string();\n                    break;\n                case \"cache_images\":\n                    message.cache_images = reader.bool();\n                    break;\n                case \"root_folder\":\n                    message.root_folder = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.WindowDataParameter.prototype.source = \"\";\ncaffe.WindowDataParameter.prototype.scale = 1;\ncaffe.WindowDataParameter.prototype.mean_file = \"\";\ncaffe.WindowDataParameter.prototype.batch_size = 0;\ncaffe.WindowDataParameter.prototype.crop_size = 0;\ncaffe.WindowDataParameter.prototype.mirror = false;\ncaffe.WindowDataParameter.prototype.fg_threshold = 0.5;\ncaffe.WindowDataParameter.prototype.bg_threshold = 0.5;\ncaffe.WindowDataParameter.prototype.fg_fraction = 0.25;\ncaffe.WindowDataParameter.prototype.context_pad = 0;\ncaffe.WindowDataParameter.prototype.crop_mode = \"warp\";\ncaffe.WindowDataParameter.prototype.cache_images = false;\ncaffe.WindowDataParameter.prototype.root_folder = \"\";\n\ncaffe.SPPParameter = class SPPParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.SPPParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.pyramid_height = reader.uint32();\n                    break;\n                case 2:\n                    message.pool = reader.int32();\n                    break;\n                case 6:\n                    message.engine = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.SPPParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"pyramid_height\":\n                    message.pyramid_height = reader.uint32();\n                    break;\n                case \"pool\":\n                    message.pool = reader.enum(caffe.SPPParameter.PoolMethod);\n                    break;\n                case \"engine\":\n                    message.engine = reader.enum(caffe.SPPParameter.Engine);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.SPPParameter.prototype.pyramid_height = 0;\ncaffe.SPPParameter.prototype.pool = 0;\ncaffe.SPPParameter.prototype.engine = 0;\n\ncaffe.SPPParameter.PoolMethod = {\n    \"MAX\": 0,\n    \"AVE\": 1,\n    \"STOCHASTIC\": 2\n};\n\ncaffe.SPPParameter.Engine = {\n    \"DEFAULT\": 0,\n    \"CAFFE\": 1,\n    \"CUDNN\": 2\n};\n\ncaffe.V1LayerParameter = class V1LayerParameter {\n\n    constructor() {\n        this.bottom = [];\n        this.top = [];\n        this.include = [];\n        this.exclude = [];\n        this.blobs = [];\n        this.param = [];\n        this.blob_share_mode = [];\n        this.blobs_lr = [];\n        this.weight_decay = [];\n        this.loss_weight = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.V1LayerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.bottom.push(reader.string());\n                    break;\n                case 3:\n                    message.top.push(reader.string());\n                    break;\n                case 4:\n                    message.name = reader.string();\n                    break;\n                case 32:\n                    message.include.push(caffe.NetStateRule.decode(reader, reader.uint32()));\n                    break;\n                case 33:\n                    message.exclude.push(caffe.NetStateRule.decode(reader, reader.uint32()));\n                    break;\n                case 5:\n                    message.type = reader.int32();\n                    break;\n                case 6:\n                    message.blobs.push(caffe.BlobProto.decode(reader, reader.uint32()));\n                    break;\n                case 1001:\n                    message.param.push(reader.string());\n                    break;\n                case 1002:\n                    message.blob_share_mode = reader.array(message.blob_share_mode, () => reader.int32(), tag);\n                    break;\n                case 7:\n                    message.blobs_lr = reader.floats(message.blobs_lr, tag);\n                    break;\n                case 8:\n                    message.weight_decay = reader.floats(message.weight_decay, tag);\n                    break;\n                case 35:\n                    message.loss_weight = reader.floats(message.loss_weight, tag);\n                    break;\n                case 27:\n                    message.accuracy_param = caffe.AccuracyParameter.decode(reader, reader.uint32());\n                    break;\n                case 23:\n                    message.argmax_param = caffe.ArgMaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 9:\n                    message.concat_param = caffe.ConcatParameter.decode(reader, reader.uint32());\n                    break;\n                case 40:\n                    message.contrastive_loss_param = caffe.ContrastiveLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.convolution_param = caffe.ConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.data_param = caffe.DataParameter.decode(reader, reader.uint32());\n                    break;\n                case 12:\n                    message.dropout_param = caffe.DropoutParameter.decode(reader, reader.uint32());\n                    break;\n                case 26:\n                    message.dummy_data_param = caffe.DummyDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 24:\n                    message.eltwise_param = caffe.EltwiseParameter.decode(reader, reader.uint32());\n                    break;\n                case 41:\n                    message.exp_param = caffe.ExpParameter.decode(reader, reader.uint32());\n                    break;\n                case 13:\n                    message.hdf5_data_param = caffe.HDF5DataParameter.decode(reader, reader.uint32());\n                    break;\n                case 14:\n                    message.hdf5_output_param = caffe.HDF5OutputParameter.decode(reader, reader.uint32());\n                    break;\n                case 29:\n                    message.hinge_loss_param = caffe.HingeLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.image_data_param = caffe.ImageDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 16:\n                    message.infogain_loss_param = caffe.InfogainLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 17:\n                    message.inner_product_param = caffe.InnerProductParameter.decode(reader, reader.uint32());\n                    break;\n                case 18:\n                    message.lrn_param = caffe.LRNParameter.decode(reader, reader.uint32());\n                    break;\n                case 22:\n                    message.memory_data_param = caffe.MemoryDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 34:\n                    message.mvn_param = caffe.MVNParameter.decode(reader, reader.uint32());\n                    break;\n                case 19:\n                    message.pooling_param = caffe.PoolingParameter.decode(reader, reader.uint32());\n                    break;\n                case 21:\n                    message.power_param = caffe.PowerParameter.decode(reader, reader.uint32());\n                    break;\n                case 30:\n                    message.relu_param = caffe.ReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 38:\n                    message.sigmoid_param = caffe.SigmoidParameter.decode(reader, reader.uint32());\n                    break;\n                case 39:\n                    message.softmax_param = caffe.SoftmaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.slice_param = caffe.SliceParameter.decode(reader, reader.uint32());\n                    break;\n                case 37:\n                    message.tanh_param = caffe.TanHParameter.decode(reader, reader.uint32());\n                    break;\n                case 25:\n                    message.threshold_param = caffe.ThresholdParameter.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.window_data_param = caffe.WindowDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 36:\n                    message.transform_param = caffe.TransformationParameter.decode(reader, reader.uint32());\n                    break;\n                case 42:\n                    message.loss_param = caffe.LossParameter.decode(reader, reader.uint32());\n                    break;\n                case 1:\n                    message.layer = caffe.V0LayerParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.V1LayerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"bottom\":\n                    reader.array(message.bottom, () => reader.string());\n                    break;\n                case \"top\":\n                    reader.array(message.top, () => reader.string());\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"include\":\n                    message.include.push(caffe.NetStateRule.decodeText(reader));\n                    break;\n                case \"exclude\":\n                    message.exclude.push(caffe.NetStateRule.decodeText(reader));\n                    break;\n                case \"type\":\n                    message.type = reader.enum(caffe.V1LayerParameter.LayerType);\n                    break;\n                case \"blobs\":\n                    message.blobs.push(caffe.BlobProto.decodeText(reader));\n                    break;\n                case \"param\":\n                    reader.array(message.param, () => reader.string());\n                    break;\n                case \"blob_share_mode\":\n                    reader.array(message.blob_share_mode, () => reader.enum(caffe.V1LayerParameter.DimCheckMode));\n                    break;\n                case \"blobs_lr\":\n                    reader.array(message.blobs_lr, () => reader.float());\n                    break;\n                case \"weight_decay\":\n                    reader.array(message.weight_decay, () => reader.float());\n                    break;\n                case \"loss_weight\":\n                    reader.array(message.loss_weight, () => reader.float());\n                    break;\n                case \"accuracy_param\":\n                    message.accuracy_param = caffe.AccuracyParameter.decodeText(reader);\n                    break;\n                case \"argmax_param\":\n                    message.argmax_param = caffe.ArgMaxParameter.decodeText(reader);\n                    break;\n                case \"concat_param\":\n                    message.concat_param = caffe.ConcatParameter.decodeText(reader);\n                    break;\n                case \"contrastive_loss_param\":\n                    message.contrastive_loss_param = caffe.ContrastiveLossParameter.decodeText(reader);\n                    break;\n                case \"convolution_param\":\n                    message.convolution_param = caffe.ConvolutionParameter.decodeText(reader);\n                    break;\n                case \"data_param\":\n                    message.data_param = caffe.DataParameter.decodeText(reader);\n                    break;\n                case \"dropout_param\":\n                    message.dropout_param = caffe.DropoutParameter.decodeText(reader);\n                    break;\n                case \"dummy_data_param\":\n                    message.dummy_data_param = caffe.DummyDataParameter.decodeText(reader);\n                    break;\n                case \"eltwise_param\":\n                    message.eltwise_param = caffe.EltwiseParameter.decodeText(reader);\n                    break;\n                case \"exp_param\":\n                    message.exp_param = caffe.ExpParameter.decodeText(reader);\n                    break;\n                case \"hdf5_data_param\":\n                    message.hdf5_data_param = caffe.HDF5DataParameter.decodeText(reader);\n                    break;\n                case \"hdf5_output_param\":\n                    message.hdf5_output_param = caffe.HDF5OutputParameter.decodeText(reader);\n                    break;\n                case \"hinge_loss_param\":\n                    message.hinge_loss_param = caffe.HingeLossParameter.decodeText(reader);\n                    break;\n                case \"image_data_param\":\n                    message.image_data_param = caffe.ImageDataParameter.decodeText(reader);\n                    break;\n                case \"infogain_loss_param\":\n                    message.infogain_loss_param = caffe.InfogainLossParameter.decodeText(reader);\n                    break;\n                case \"inner_product_param\":\n                    message.inner_product_param = caffe.InnerProductParameter.decodeText(reader);\n                    break;\n                case \"lrn_param\":\n                    message.lrn_param = caffe.LRNParameter.decodeText(reader);\n                    break;\n                case \"memory_data_param\":\n                    message.memory_data_param = caffe.MemoryDataParameter.decodeText(reader);\n                    break;\n                case \"mvn_param\":\n                    message.mvn_param = caffe.MVNParameter.decodeText(reader);\n                    break;\n                case \"pooling_param\":\n                    message.pooling_param = caffe.PoolingParameter.decodeText(reader);\n                    break;\n                case \"power_param\":\n                    message.power_param = caffe.PowerParameter.decodeText(reader);\n                    break;\n                case \"relu_param\":\n                    message.relu_param = caffe.ReLUParameter.decodeText(reader);\n                    break;\n                case \"sigmoid_param\":\n                    message.sigmoid_param = caffe.SigmoidParameter.decodeText(reader);\n                    break;\n                case \"softmax_param\":\n                    message.softmax_param = caffe.SoftmaxParameter.decodeText(reader);\n                    break;\n                case \"slice_param\":\n                    message.slice_param = caffe.SliceParameter.decodeText(reader);\n                    break;\n                case \"tanh_param\":\n                    message.tanh_param = caffe.TanHParameter.decodeText(reader);\n                    break;\n                case \"threshold_param\":\n                    message.threshold_param = caffe.ThresholdParameter.decodeText(reader);\n                    break;\n                case \"window_data_param\":\n                    message.window_data_param = caffe.WindowDataParameter.decodeText(reader);\n                    break;\n                case \"transform_param\":\n                    message.transform_param = caffe.TransformationParameter.decodeText(reader);\n                    break;\n                case \"loss_param\":\n                    message.loss_param = caffe.LossParameter.decodeText(reader);\n                    break;\n                case \"layer\":\n                    message.layer = caffe.V0LayerParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.V1LayerParameter.prototype.name = \"\";\ncaffe.V1LayerParameter.prototype.type = 0;\ncaffe.V1LayerParameter.prototype.accuracy_param = null;\ncaffe.V1LayerParameter.prototype.argmax_param = null;\ncaffe.V1LayerParameter.prototype.concat_param = null;\ncaffe.V1LayerParameter.prototype.contrastive_loss_param = null;\ncaffe.V1LayerParameter.prototype.convolution_param = null;\ncaffe.V1LayerParameter.prototype.data_param = null;\ncaffe.V1LayerParameter.prototype.dropout_param = null;\ncaffe.V1LayerParameter.prototype.dummy_data_param = null;\ncaffe.V1LayerParameter.prototype.eltwise_param = null;\ncaffe.V1LayerParameter.prototype.exp_param = null;\ncaffe.V1LayerParameter.prototype.hdf5_data_param = null;\ncaffe.V1LayerParameter.prototype.hdf5_output_param = null;\ncaffe.V1LayerParameter.prototype.hinge_loss_param = null;\ncaffe.V1LayerParameter.prototype.image_data_param = null;\ncaffe.V1LayerParameter.prototype.infogain_loss_param = null;\ncaffe.V1LayerParameter.prototype.inner_product_param = null;\ncaffe.V1LayerParameter.prototype.lrn_param = null;\ncaffe.V1LayerParameter.prototype.memory_data_param = null;\ncaffe.V1LayerParameter.prototype.mvn_param = null;\ncaffe.V1LayerParameter.prototype.pooling_param = null;\ncaffe.V1LayerParameter.prototype.power_param = null;\ncaffe.V1LayerParameter.prototype.relu_param = null;\ncaffe.V1LayerParameter.prototype.sigmoid_param = null;\ncaffe.V1LayerParameter.prototype.softmax_param = null;\ncaffe.V1LayerParameter.prototype.slice_param = null;\ncaffe.V1LayerParameter.prototype.tanh_param = null;\ncaffe.V1LayerParameter.prototype.threshold_param = null;\ncaffe.V1LayerParameter.prototype.window_data_param = null;\ncaffe.V1LayerParameter.prototype.transform_param = null;\ncaffe.V1LayerParameter.prototype.loss_param = null;\ncaffe.V1LayerParameter.prototype.layer = null;\n\ncaffe.V1LayerParameter.LayerType = {\n    \"NONE\": 0,\n    \"ABSVAL\": 35,\n    \"ACCURACY\": 1,\n    \"ARGMAX\": 30,\n    \"BNLL\": 2,\n    \"CONCAT\": 3,\n    \"CONTRASTIVE_LOSS\": 37,\n    \"CONVOLUTION\": 4,\n    \"DATA\": 5,\n    \"DECONVOLUTION\": 39,\n    \"DROPOUT\": 6,\n    \"DUMMY_DATA\": 32,\n    \"EUCLIDEAN_LOSS\": 7,\n    \"ELTWISE\": 25,\n    \"EXP\": 38,\n    \"FLATTEN\": 8,\n    \"HDF5_DATA\": 9,\n    \"HDF5_OUTPUT\": 10,\n    \"HINGE_LOSS\": 28,\n    \"IM2COL\": 11,\n    \"IMAGE_DATA\": 12,\n    \"INFOGAIN_LOSS\": 13,\n    \"INNER_PRODUCT\": 14,\n    \"LRN\": 15,\n    \"MEMORY_DATA\": 29,\n    \"MULTINOMIAL_LOGISTIC_LOSS\": 16,\n    \"MVN\": 34,\n    \"POOLING\": 17,\n    \"POWER\": 26,\n    \"RELU\": 18,\n    \"SIGMOID\": 19,\n    \"SIGMOID_CROSS_ENTROPY_LOSS\": 27,\n    \"SILENCE\": 36,\n    \"SOFTMAX\": 20,\n    \"SOFTMAX_LOSS\": 21,\n    \"SPLIT\": 22,\n    \"SLICE\": 33,\n    \"TANH\": 23,\n    \"WINDOW_DATA\": 24,\n    \"THRESHOLD\": 31\n};\n\ncaffe.V1LayerParameter.DimCheckMode = {\n    \"STRICT\": 0,\n    \"PERMISSIVE\": 1\n};\n\ncaffe.V0LayerParameter = class V0LayerParameter {\n\n    constructor() {\n        this.blobs = [];\n        this.blobs_lr = [];\n        this.weight_decay = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe.V0LayerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.num_output = reader.uint32();\n                    break;\n                case 4:\n                    message.biasterm = reader.bool();\n                    break;\n                case 5:\n                    message.weight_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.bias_filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.pad = reader.uint32();\n                    break;\n                case 8:\n                    message.kernelsize = reader.uint32();\n                    break;\n                case 9:\n                    message.group = reader.uint32();\n                    break;\n                case 10:\n                    message.stride = reader.uint32();\n                    break;\n                case 11:\n                    message.pool = reader.int32();\n                    break;\n                case 12:\n                    message.dropout_ratio = reader.float();\n                    break;\n                case 13:\n                    message.local_size = reader.uint32();\n                    break;\n                case 14:\n                    message.alpha = reader.float();\n                    break;\n                case 15:\n                    message.beta = reader.float();\n                    break;\n                case 22:\n                    message.k = reader.float();\n                    break;\n                case 16:\n                    message.source = reader.string();\n                    break;\n                case 17:\n                    message.scale = reader.float();\n                    break;\n                case 18:\n                    message.meanfile = reader.string();\n                    break;\n                case 19:\n                    message.batchsize = reader.uint32();\n                    break;\n                case 20:\n                    message.cropsize = reader.uint32();\n                    break;\n                case 21:\n                    message.mirror = reader.bool();\n                    break;\n                case 50:\n                    message.blobs.push(caffe.BlobProto.decode(reader, reader.uint32()));\n                    break;\n                case 51:\n                    message.blobs_lr = reader.floats(message.blobs_lr, tag);\n                    break;\n                case 52:\n                    message.weight_decay = reader.floats(message.weight_decay, tag);\n                    break;\n                case 53:\n                    message.rand_skip = reader.uint32();\n                    break;\n                case 54:\n                    message.det_fg_threshold = reader.float();\n                    break;\n                case 55:\n                    message.det_bg_threshold = reader.float();\n                    break;\n                case 56:\n                    message.det_fg_fraction = reader.float();\n                    break;\n                case 58:\n                    message.det_context_pad = reader.uint32();\n                    break;\n                case 59:\n                    message.det_crop_mode = reader.string();\n                    break;\n                case 60:\n                    message.new_num = reader.int32();\n                    break;\n                case 61:\n                    message.new_channels = reader.int32();\n                    break;\n                case 62:\n                    message.new_height = reader.int32();\n                    break;\n                case 63:\n                    message.new_width = reader.int32();\n                    break;\n                case 64:\n                    message.shuffle_images = reader.bool();\n                    break;\n                case 65:\n                    message.concat_dim = reader.uint32();\n                    break;\n                case 1001:\n                    message.hdf5_output_param = caffe.HDF5OutputParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.V0LayerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"num_output\":\n                    message.num_output = reader.uint32();\n                    break;\n                case \"biasterm\":\n                    message.biasterm = reader.bool();\n                    break;\n                case \"weight_filler\":\n                    message.weight_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"bias_filler\":\n                    message.bias_filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"pad\":\n                    message.pad = reader.uint32();\n                    break;\n                case \"kernelsize\":\n                    message.kernelsize = reader.uint32();\n                    break;\n                case \"group\":\n                    message.group = reader.uint32();\n                    break;\n                case \"stride\":\n                    message.stride = reader.uint32();\n                    break;\n                case \"pool\":\n                    message.pool = reader.enum(caffe.V0LayerParameter.PoolMethod);\n                    break;\n                case \"dropout_ratio\":\n                    message.dropout_ratio = reader.float();\n                    break;\n                case \"local_size\":\n                    message.local_size = reader.uint32();\n                    break;\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                case \"k\":\n                    message.k = reader.float();\n                    break;\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                case \"meanfile\":\n                    message.meanfile = reader.string();\n                    break;\n                case \"batchsize\":\n                    message.batchsize = reader.uint32();\n                    break;\n                case \"cropsize\":\n                    message.cropsize = reader.uint32();\n                    break;\n                case \"mirror\":\n                    message.mirror = reader.bool();\n                    break;\n                case \"blobs\":\n                    message.blobs.push(caffe.BlobProto.decodeText(reader));\n                    break;\n                case \"blobs_lr\":\n                    reader.array(message.blobs_lr, () => reader.float());\n                    break;\n                case \"weight_decay\":\n                    reader.array(message.weight_decay, () => reader.float());\n                    break;\n                case \"rand_skip\":\n                    message.rand_skip = reader.uint32();\n                    break;\n                case \"det_fg_threshold\":\n                    message.det_fg_threshold = reader.float();\n                    break;\n                case \"det_bg_threshold\":\n                    message.det_bg_threshold = reader.float();\n                    break;\n                case \"det_fg_fraction\":\n                    message.det_fg_fraction = reader.float();\n                    break;\n                case \"det_context_pad\":\n                    message.det_context_pad = reader.uint32();\n                    break;\n                case \"det_crop_mode\":\n                    message.det_crop_mode = reader.string();\n                    break;\n                case \"new_num\":\n                    message.new_num = reader.int32();\n                    break;\n                case \"new_channels\":\n                    message.new_channels = reader.int32();\n                    break;\n                case \"new_height\":\n                    message.new_height = reader.int32();\n                    break;\n                case \"new_width\":\n                    message.new_width = reader.int32();\n                    break;\n                case \"shuffle_images\":\n                    message.shuffle_images = reader.bool();\n                    break;\n                case \"concat_dim\":\n                    message.concat_dim = reader.uint32();\n                    break;\n                case \"hdf5_output_param\":\n                    message.hdf5_output_param = caffe.HDF5OutputParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.V0LayerParameter.prototype.name = \"\";\ncaffe.V0LayerParameter.prototype.type = \"\";\ncaffe.V0LayerParameter.prototype.num_output = 0;\ncaffe.V0LayerParameter.prototype.biasterm = true;\ncaffe.V0LayerParameter.prototype.weight_filler = null;\ncaffe.V0LayerParameter.prototype.bias_filler = null;\ncaffe.V0LayerParameter.prototype.pad = 0;\ncaffe.V0LayerParameter.prototype.kernelsize = 0;\ncaffe.V0LayerParameter.prototype.group = 1;\ncaffe.V0LayerParameter.prototype.stride = 1;\ncaffe.V0LayerParameter.prototype.pool = 0;\ncaffe.V0LayerParameter.prototype.dropout_ratio = 0.5;\ncaffe.V0LayerParameter.prototype.local_size = 5;\ncaffe.V0LayerParameter.prototype.alpha = 1;\ncaffe.V0LayerParameter.prototype.beta = 0.75;\ncaffe.V0LayerParameter.prototype.k = 1;\ncaffe.V0LayerParameter.prototype.source = \"\";\ncaffe.V0LayerParameter.prototype.scale = 1;\ncaffe.V0LayerParameter.prototype.meanfile = \"\";\ncaffe.V0LayerParameter.prototype.batchsize = 0;\ncaffe.V0LayerParameter.prototype.cropsize = 0;\ncaffe.V0LayerParameter.prototype.mirror = false;\ncaffe.V0LayerParameter.prototype.rand_skip = 0;\ncaffe.V0LayerParameter.prototype.det_fg_threshold = 0.5;\ncaffe.V0LayerParameter.prototype.det_bg_threshold = 0.5;\ncaffe.V0LayerParameter.prototype.det_fg_fraction = 0.25;\ncaffe.V0LayerParameter.prototype.det_context_pad = 0;\ncaffe.V0LayerParameter.prototype.det_crop_mode = \"warp\";\ncaffe.V0LayerParameter.prototype.new_num = 0;\ncaffe.V0LayerParameter.prototype.new_channels = 0;\ncaffe.V0LayerParameter.prototype.new_height = 0;\ncaffe.V0LayerParameter.prototype.new_width = 0;\ncaffe.V0LayerParameter.prototype.shuffle_images = false;\ncaffe.V0LayerParameter.prototype.concat_dim = 1;\ncaffe.V0LayerParameter.prototype.hdf5_output_param = null;\n\ncaffe.V0LayerParameter.PoolMethod = {\n    \"MAX\": 0,\n    \"AVE\": 1,\n    \"STOCHASTIC\": 2\n};\n\ncaffe.PReLUParameter = class PReLUParameter {\n\n    static decode(reader, length) {\n        const message = new caffe.PReLUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.filler = caffe.FillerParameter.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.channel_shared = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe.PReLUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"filler\":\n                    message.filler = caffe.FillerParameter.decodeText(reader);\n                    break;\n                case \"channel_shared\":\n                    message.channel_shared = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.PReLUParameter.prototype.filler = null;\ncaffe.PReLUParameter.prototype.channel_shared = false;\n"
  },
  {
    "path": "source/caffe.js",
    "content": "\nconst caffe = {};\n\ncaffe.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        if (extension === 'caffemodel') {\n            return context.set('caffe.pb');\n        }\n        if (identifier === 'saved_model.pbtxt' || identifier === 'saved_model.prototxt' ||\n            identifier.endsWith('predict_net.pbtxt') || identifier.endsWith('predict_net.prototxt') ||\n            identifier.endsWith('init_net.pbtxt') || identifier.endsWith('init_net.prototxt')) {\n            return null;\n        }\n        const tags = await context.tags('pbtxt');\n        if (tags.has('layer') || tags.has('layers')) {\n            return context.set('caffe.pbtxt');\n        } else if (tags.has('net') || tags.has('train_net') || tags.has('net_param')) {\n            return context.set('caffe.pbtxt.solver');\n        }\n        return null;\n    }\n\n    async open(context) {\n        caffe.proto = await context.require('./caffe-proto');\n        caffe.proto = caffe.proto.caffe;\n        const openModel = async (context, netParameter) => {\n            const metadata = await context.metadata('caffe-metadata.json');\n            return new caffe.Model(metadata, netParameter);\n        };\n        const openNetParameterText = async (context, identifier, content) => {\n            let netParameter = null;\n            try {\n                const reader = await content.read('protobuf.text');\n                reader.field = function(tag, message) {\n                    const type = message.constructor.name;\n                    if (tag.endsWith('_param') && (type === 'LayerParameter' || type === 'V1LayerParameter' || type === 'V0LayerParameter')) {\n                        message[tag] = caffe.ModelFactory._decodeText(reader);\n                        return;\n                    } else if (message.constructor.name.endsWith('Parameter') || message.constructor.name === 'ParamSpec') {\n                        if (message[tag]) {\n                            if (!Array.isArray(message[tag])) {\n                                message[tag] = [message[tag]];\n                            }\n                            message[tag].push(this.read());\n                        } else {\n                            message[tag] = this.read();\n                        }\n                        return;\n                    }\n                    throw new Error(`Unknown field '${tag}' ${this.location()}`);\n                };\n                reader.enum = function(type) {\n                    const token = this.token();\n                    this.next();\n                    this.semicolon();\n                    if (!Object.prototype.hasOwnProperty.call(type, token)) {\n                        const value = Number.parseInt(token, 10);\n                        if (!Number.isNaN(token - value)) {\n                            return value;\n                        }\n                        return token;\n                    }\n                    return type[token];\n                };\n                if (/MobileNetSSD_train_template.prototxt/.exec(identifier)) {\n                    reader.integer = function() {\n                        const token = this.token();\n                        const value = Number.parseInt(token, 10);\n                        this.next();\n                        this.semicolon();\n                        if (Number.isNaN(token - value)) {\n                            return token;\n                        }\n                        return value;\n                    };\n                }\n                netParameter = caffe.proto.NetParameter.decodeText(reader);\n            } catch (error) {\n                const message = error && error.message ? error.message : error.toString();\n                throw new caffe.Error(`File text format is not caffe.NetParameter (${message.replace(/\\.$/, '')}).`);\n            }\n            return openModel(context, netParameter);\n        };\n        switch (context.type) {\n            case 'caffe.pbtxt.solver': {\n                const reader = await context.read('protobuf.text');\n                reader.field = function(tag, message) {\n                    if (message instanceof caffe.proto.SolverParameter) {\n                        message[tag] = this.read();\n                        return;\n                    }\n                    throw new Error(`Unknown field '${tag}'${this.location()}`);\n                };\n                const solver = caffe.proto.SolverParameter.decodeText(reader);\n                if (solver.net_param) {\n                    return openModel(context, solver.net_param);\n                }\n                let name = solver.net || solver.train_net;\n                name = name.split('/').pop();\n                try {\n                    const content = await context.fetch(name);\n                    return await openNetParameterText(context, name, content);\n                } catch (error) {\n                    const message = error.message ? error.message : error.toString();\n                    throw new caffe.Error(`Failed to load '${name}' (${message.replace(/\\.$/, '')}).`);\n                }\n            }\n            case 'caffe.pbtxt': {\n                return await openNetParameterText(context, context.identifier, context);\n            }\n            case 'caffe.pb': {\n                let netParameter = null;\n                try {\n                    const reader = await context.read('protobuf.binary');\n                    netParameter = caffe.proto.NetParameter.decode(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new caffe.Error(`File format is not caffe.NetParameter (${message.replace(/\\.$/, '')}).`);\n                }\n                return await openModel(context, netParameter);\n            }\n            default: {\n                throw new caffe.Error(`Unsupported Caffe format '${context.type}'.`);\n            }\n        }\n    }\n\n    static _decodeText(reader) {\n        const message = {};\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            const value = reader.read();\n            if (message[tag]) {\n                if (!Array.isArray(message[tag])) {\n                    message[tag] = [message[tag]];\n                }\n                message[tag].push(value);\n            } else {\n                message[tag] = value;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe.Model = class {\n\n    constructor(metadata, net) {\n        this.name = net.name;\n        this.format = 'Caffe';\n        this.modules = [];\n        let version = -1;\n        if (net.layers && net.layers.length > 0) {\n            if (net.layers.every((layer) => Object.prototype.hasOwnProperty.call(layer, 'layer'))) {\n                version = 0;\n                net.layer = net.layers;\n            } else {\n                version = 1;\n                net.layer = net.layers;\n            }\n        } else if (net.layer && net.layer.length > 0) {\n            version = 2;\n        }\n        this.format = `Caffe v${version}`;\n        const phases = new Set();\n        for (const layer of net.layer) {\n            for (const include of layer.include) {\n                if (include.phase !== undefined) {\n                    phases.add(include.phase);\n                }\n            }\n        }\n        if (phases.size === 0) {\n            phases.add(-1);\n        }\n        for (const phase of phases) {\n            const graph = new caffe.Graph(metadata, phase, net, version);\n            this.modules.push(graph);\n        }\n    }\n};\n\ncaffe.Graph = class {\n\n    constructor(metadata, phase, net, version) {\n        switch (phase) {\n            case 0: this.name = 'TRAIN'; break;\n            case 1: this.name = 'TEST'; break;\n            case -1: this.name = ''; break;\n            default: this.name = phase.toString(); break;\n        }\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        for (const layer of net.layer) {\n            layer.input = layer.bottom.slice(0);\n            layer.output = layer.top.slice(0);\n            layer.chain = [];\n        }\n        const layers = [];\n        for (const layer of net.layer) {\n            if (phase === -1 || layer.include.every((include) => include.phase === phase)) {\n                layers.push(layer);\n            }\n        }\n        const scopes = new Map();\n        for (let i = 0; i < layers.length; i++) {\n            const layer = layers[i];\n            layer.input = layer.input.map((input) => scopes.has(input) ? scopes.get(input) : input);\n            layer.output = layer.output.map((output) => {\n                const value = scopes.has(output) ? `${output}\\n${i}` : output;\n                scopes.set(output, value);\n                return value;\n            });\n        }\n        // Graph Inputs\n        const usedOutputs = new Set();\n        for (const layer of layers) {\n            for (const output of layer.output) {\n                usedOutputs.add(output);\n            }\n        }\n        const unusedInputs = [];\n        for (const layer of layers) {\n            for (const input of layer.input) {\n                if (!usedOutputs.has(input)) {\n                    unusedInputs.push(input);\n                }\n            }\n        }\n        const values = new Map();\n        const value = (name, type) => {\n            if (!values.has(name)) {\n                values.set(name, new caffe.Value(name, type));\n            } else if (type) {\n                throw new caffe.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const nodes = [];\n        let lastLayer = null;\n        let lastTop = null;\n        while (layers.length > 0) {\n            let layer = layers.shift();\n            if (layer.output.length === 1 && layer.input.length === 1 &&\n                layer.output[0].split('\\n').shift() === layer.input[0].split('\\n').shift() &&\n                lastLayer &&\n                lastTop === layer.output[0].split('\\n').shift()) {\n                lastLayer.chain = lastLayer.chain || [];\n                lastLayer.chain.push(layer);\n            } else {\n                if (layer.type === 'Input' && layer.input.length === 0) {\n                    for (let i = 0; i < layer.output.length; i++) {\n                        const output = layer.output[i];\n                        const dim = layer.input_param && layer.input_param.shape && i < layer.input_param.shape.length ? layer.input_param.shape[i].dim : null;\n                        const shape = dim ? new caffe.TensorShape(dim.map((dim) => dim.toNumber())) : null;\n                        const type = shape ? new caffe.TensorType(null, shape) : null;\n                        const argument = new caffe.Argument(output, [value(output, type)]);\n                        this.inputs.push(argument);\n                    }\n                    layer = null;\n                }\n                if (layer) {\n                    nodes.push(layer);\n                    lastLayer = null;\n                    lastTop = null;\n                    if (layer.output.length === 1) {\n                        lastLayer = layer;\n                        lastTop = layer.output[0].split('\\n').shift();\n                    }\n                }\n            }\n        }\n        if (net.input) {\n            for (let i = 0; i < net.input.length; i++) {\n                const input = net.input[i];\n                if (this.inputs.some((item) => item.name === input)) {\n                    continue;\n                }\n                let inputType = null;\n                if (net.input_shape && i < net.input_shape.length) {\n                    const blobShape = net.input_shape[i];\n                    if (blobShape && blobShape.dim) {\n                        const shape = new caffe.TensorShape(blobShape.dim.map((dim) => dim.toNumber()));\n                        inputType = new caffe.TensorType(null, shape);\n                    }\n                }\n                const dim = i * 4;\n                if (!inputType && net.input_dim && net.input_dim.length >= dim) {\n                    const shape = new caffe.TensorShape(net.input_dim.slice(dim, dim + 4));\n                    inputType = new caffe.TensorType(null, shape);\n                }\n                this.inputs.push(new caffe.Argument(input, [value(input, inputType, null)]));\n            }\n        }\n\n        for (const layer of nodes) {\n            const node = new caffe.Node(metadata, layer, version, value);\n            if (layer.chain && layer.chain.length > 0) {\n                for (const chain of layer.chain) {\n                    node.chain.push(new caffe.Node(metadata, chain, version, value));\n                }\n            }\n            this.nodes.push(node);\n        }\n\n        if (this.inputs.length === 0 && unusedInputs.length === 1) {\n            this.inputs.push(new caffe.Argument(unusedInputs[0], [value(unusedInputs[0], null)]));\n        }\n    }\n};\n\ncaffe.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\ncaffe.Value = class {\n\n    constructor(name, type = null, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new caffe.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = type;\n        this.initializer = initializer;\n    }\n};\n\ncaffe.Node = class {\n\n    constructor(metadata, layer, version, value) {\n        this.attributes = [];\n        this.chain = [];\n        let type = '';\n        switch (version) {\n            case 0: {\n                this.name = layer.layer.name;\n                type = layer.layer.type;\n                break;\n            }\n            case 1: {\n                this.name = layer.name;\n                type = caffe.Utility.layerType(layer.type);\n                break;\n            }\n            case 2: {\n                this.name = layer.name;\n                type = layer.type;\n                break;\n            }\n            default: {\n                throw new caffe.Error(`Unsupported Caffe version '${version}'.`);\n            }\n        }\n        this.type = metadata.type(type) || { name: type };\n        let initializers = [];\n        const attributes = [];\n        switch (version) {\n            case 0: {\n                for (const name of Object.keys(layer.layer)) {\n                    if (name !== 'type' && name !== 'name' && name !== 'blobs' && name !== 'blobs_lr') {\n                        const value = layer.layer[name];\n                        const schema = metadata.attribute(type, name);\n                        attributes.push([schema, name, value]);\n                    }\n                }\n                initializers = layer.layer.blobs.map((blob) => new caffe.Tensor(blob));\n                break;\n            }\n            case 1:\n            case 2: {\n                for (const layer_kind of Object.keys(layer)) {\n                    if (layer_kind.endsWith('_param') || layer_kind === 'transform_param') {\n                        const param = layer[layer_kind];\n                        if (type === 'Deconvolution') {\n                            type = 'Convolution';\n                        }\n                        const prototype = Object.getPrototypeOf(param);\n                        for (const name of Object.keys(param)) {\n                            const defaultValue = prototype[name];\n                            const value = param[name];\n                            const schema = metadata.attribute(type, name);\n                            attributes.push([schema, name, value, defaultValue]);\n                        }\n                    }\n                }\n                if (layer.include && layer.include.length > 0) {\n                    const schema = metadata.attribute(type, 'include');\n                    attributes.push([schema, 'include', layer.include]);\n                }\n                if (layer.exclude && layer.exclude.length > 0) {\n                    const schema = metadata.attribute(type, 'exclude');\n                    attributes.push([schema, 'exclude', layer.exclude]);\n                }\n                if (this.type === 'Data' && layer.input_param && layer.input_param.shape) {\n                    const schema = metadata.attribute(type, 'shape');\n                    attributes.push([schema, 'shape', layer.input_param.shape]);\n                }\n                initializers = layer.blobs.map((blob) => new caffe.Tensor(blob));\n                break;\n            }\n            default: {\n                throw new caffe.Error(`Unsupported Caffe version '${version}'.`);\n            }\n        }\n        this.inputs = [];\n        const inputs = layer.input.concat(initializers);\n        let inputIndex = 0;\n        if (this.type && this.type.inputs) {\n            for (const inputDef of this.type.inputs) {\n                if (inputIndex < inputs.length || inputDef.option !== 'optional') {\n                    const count = inputDef.option === 'variadic' ? inputs.length - inputIndex : 1;\n                    const values = inputs.slice(inputIndex, inputIndex + count).filter((input) => input !== '' || inputDef.option !== 'optional').map((input) => {\n                        return input instanceof caffe.Tensor ? new caffe.Value('', input.type, input) : value(input, null, null);\n                    });\n                    const argument = new caffe.Argument(inputDef.name, values);\n                    this.inputs.push(argument);\n                    inputIndex += count;\n                }\n            }\n        }\n        this.inputs.push(...inputs.slice(inputIndex).map((input) => {\n            return new caffe.Argument(inputIndex.toString(), [\n                input instanceof caffe.Tensor ? new caffe.Value('', input.type, input) : value(input, null, null)\n            ]);\n        }));\n\n        this.outputs = [];\n        const outputs = layer.output;\n        let outputIndex = 0;\n        if (this.type && this.type.outputs) {\n            for (const outputDef of this.type.outputs) {\n                if (outputIndex < outputs.length) {\n                    const count = (outputDef.option === 'variadic') ? (outputs.length - outputIndex) : 1;\n                    const values = outputs.slice(outputIndex, outputIndex + count).map((output) => value(output, null, null));\n                    const argument = new caffe.Argument(outputDef.name, values);\n                    this.outputs.push(argument);\n                    outputIndex += count;\n                }\n            }\n        }\n        this.outputs.push(...outputs.slice(outputIndex).map((output, index) => {\n            return new caffe.Argument((outputIndex + index).toString(), [value(output, null, null)]);\n        }));\n        this.attributes = attributes.map(([metadata, name, value, defaultValue]) => {\n            let visible = true;\n            let type = null;\n            if (metadata && metadata.type) {\n                type = metadata.type;\n            }\n            if (value instanceof caffe.proto.BlobShape) {\n                value = new caffe.TensorShape(value.dim.map((dim) => dim.toNumber()));\n                type = 'shape';\n            }\n            if (metadata && metadata.visible === false) {\n                visible = false;\n            }\n            if (metadata && metadata.default !== undefined) {\n                defaultValue = metadata.default;\n            }\n            if (defaultValue !== undefined) {\n                if (value === defaultValue) {\n                    visible = false;\n                } else if (Array.isArray(value) && Array.isArray(defaultValue)) {\n                    if (value.length === defaultValue.length && value.every((item, index) => item === defaultValue[index])) {\n                        visible = false;\n                    }\n                }\n            }\n            value = type ? caffe.Utility.enum(type, value) : value;\n            return new caffe.Argument(name, value, type, visible);\n        });\n    }\n};\n\ncaffe.Tensor = class {\n\n    constructor(blob) {\n        let shape = [];\n        if (Object.prototype.hasOwnProperty.call(blob, 'num') &&\n            Object.prototype.hasOwnProperty.call(blob, 'channels') &&\n            Object.prototype.hasOwnProperty.call(blob, 'width') &&\n            Object.prototype.hasOwnProperty.call(blob, 'height')) {\n            if (blob.num !== 1) {\n                shape.push(blob.num);\n            }\n            if (blob.channels !== 1) {\n                shape.push(blob.channels);\n            }\n            if (blob.height !== 1) {\n                shape.push(blob.height);\n            }\n            if (blob.width !== 1) {\n                shape.push(blob.width);\n            }\n        } else if (Object.prototype.hasOwnProperty.call(blob, 'shape')) {\n            shape = blob.shape.dim.map((dim) => Number(dim));\n        }\n        let dataType = '?';\n        if (blob.data.length > 0) {\n            dataType = 'float32';\n            this.values = blob.data;\n        } else if (blob.double_data.length > 0) {\n            dataType = 'float64';\n            this.values = blob.double_data;\n        }\n        this.category = 'Blob';\n        this.encoding = '|';\n        this.type = new caffe.TensorType(dataType, new caffe.TensorShape(shape));\n    }\n};\n\ncaffe.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\ncaffe.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`) : '';\n    }\n};\n\ncaffe.Utility = class {\n\n    static layerType(type) {\n        type = type || 0;\n        if (!caffe.Utility._layerTypeMap) {\n            caffe.Utility._layerTypeMap = new Map();\n            const known = { 'BNLL': 'BNLL', 'HDF5': 'HDF5', 'LRN': 'LRN', 'RELU': 'ReLU', 'TANH': 'TanH', 'ARGMAX': 'ArgMax', 'MVN': 'MVN', 'ABSVAL': 'AbsVal' };\n            for (const key of Object.keys(caffe.proto.V1LayerParameter.LayerType)) {\n                const value = caffe.proto.V1LayerParameter.LayerType[key];\n                caffe.Utility._layerTypeMap.set(value, key.split('_').map((item) => known[item] || item.substring(0, 1) + item.substring(1).toLowerCase()).join(''));\n            }\n        }\n        return caffe.Utility._layerTypeMap.has(type) ? caffe.Utility._layerTypeMap.get(type) : type.toString();\n    }\n\n    static enum(name, value) {\n        let type = caffe.proto;\n        const parts = name.split('.');\n        while (type && parts.length > 0) {\n            type = type[parts.shift()];\n        }\n        if (type) {\n            caffe.Utility._enumKeyMap = caffe.Utility._enumKeyMap || new Map();\n            if (!caffe.Utility._enumKeyMap.has(name)) {\n                const map = new Map(Object.entries(type).map(([name, value]) => [value, name]));\n                caffe.Utility._enumKeyMap.set(name, map);\n            }\n            const map = caffe.Utility._enumKeyMap.get(name);\n            if (map.has(value)) {\n                return map.get(value);\n            }\n        }\n        return value;\n    }\n};\n\ncaffe.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Caffe model.';\n    }\n};\n\nexport const ModelFactory = caffe.ModelFactory;\n"
  },
  {
    "path": "source/caffe2-metadata.json",
    "content": "[\n  {\n    \"name\": \"Abs\",\n    \"description\": \"\\nCalculates the absolute value of the given input tensor, element-wise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/abs_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Abs\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(5).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX: [ 0.3005476   1.551666   -1.3591481   0.39191285 -0.21866608]\\nY: [0.3005476  1.551666   1.3591481  0.39191285 0.21866608]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor<float>)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Absolute value of input element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AbsGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Accumulate\",\n    \"description\": \"\\nAccumulate operator accumulates the input tensor to the output tensor. If the\\noutput tensor already has the right size, we add to it; otherwise, we first\\ninitialize the output tensor to all zeros, and then do accumulation. Any\\nfurther calls to the operator, given that no one else fiddles with the output\\nin the interim, will do simple accumulations.\\nAccumulation is done using Axpby operation as shown:\\n  Y = 1*X + gamma*Y\\nwhere X is the input tensor, Y is the output tensor and gamma is the multiplier\\nargument.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float, default 1.0) Accumulation multiplier\",\n        \"name\": \"gamma\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input tensor that has to be accumulated to the output tensor. If the output size is not the same as input size, the output tensor is first reshaped and initialized to zero, and only then, accumulation is done.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Accumulated output tensor\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AccumulateHistogram\",\n    \"description\": \"\\nThis operator calculate thes histogram of values in input tensor.\\nThere're 2 outputs, one for histogram of current input tensor, and another\\nfor histogram of the all input tensors accumulated through history.\\nThe output would contain num_buckets + 2 values. index[1 ... num_buckets]\\nfor values in [lower_bound, upper_bound) interval. And the rest 2 for values\\nsmaller than lower_bound or greater than upper_bound respectively.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the lower bound value\",\n        \"name\": \"lower_bound\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"the upper bound value\",\n        \"name\": \"upper_bound\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"number of buckets to use in [lower_bound, upper_bound)\",\n        \"name\": \"num_buckets\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output histogram of the current tensor.\",\n        \"name\": \"CurHist\"\n      },\n      {\n        \"description\": \"Accumulated histogram of the history tensor.\",\n        \"name\": \"AccHist\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Accuracy\",\n    \"description\": \"\\nAccuracy takes two inputs- predictions and labels, and returns a float\\naccuracy value for the batch. Predictions are expected in the form of 2-D tensor\\ncontaining a batch of scores for various classes, and labels are expected in the\\n form of 1-D tensor containing true label indices of samples in the batch. If\\nthe score for the label index in the predictions is the highest among all\\nclasses, it is considered a correct prediction.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Count as correct by comparing the true label to the top k scoring classes (default 1: only compare to the top scoring class i.e. argmax)\",\n        \"name\": \"top_k\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2-D tensor (Tensor<float>) of size (num_batches x num_classes) containing scores\",\n        \"name\": \"predictions\"\n      },\n      {\n        \"description\": \"1-D tensor (Tensor<float>) of size (num_batches) having the indices of true labels\",\n        \"name\": \"labels\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor (Tensor<float>) of size 1 containing accuracy\",\n        \"name\": \"accuracy\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Acos\",\n    \"description\": \"\\nCalculates the arccosine of the given input tensor, element-wise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The arccosine of the input tensor computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AcosGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Adadelta\",\n    \"description\": \"\\n\\nComputes the AdaDelta update (https://arxiv.org/abs/1212.5701) for an input\\ngradient and accumulated history of squared gradients. Concretely, given\\ninputs (param, moment, moment_delta, grad, learning_rate), computes:\\n\\n    new_moment = moment * decay + square(grad) * (1 - decay)\\n    new_grad = sqrt(moment_delta + epsilon) / sqrt(new_moment + epsilon) * grad\\n    new_param = param + learning_rate * new_grad\\n    new_moment_delta = moment_delta * decay + square(new_grad) * (1 - decay)\\n\\nand returns (new_param, new_moment, new_moment_delta).\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 0.95, the squared gradient sum is decayed by this factor.\",\n        \"name\": \"decay\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Average of squared gradients\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Average of squared parameter updates\",\n        \"name\": \"moment_delta\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"Learning rate\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated average squared gradient\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Updated average of squared parameter updates\",\n        \"name\": \"output_moment_delta\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Adagrad\",\n    \"description\": \"\\n\\nComputes the AdaGrad update for an input gradient and accumulated\\nhistory. Concretely, given inputs (param, grad, moment, learning_rate),\\ncomputes\\n\\n    new_moment = moment + square(grad)\\n    effective_lr = learning_rate / (sqrt(new_moment) + epsilon)\\n    update = learning_rate * grad / (sqrt(new_moment) + epsilon)\\n    new_param = param + update\\nand returns (new_param, new_moment).\\n\\nOptionally returns effective_lr and update as well.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1. If it is in (0, 1), the gradient square sum is decayed by this factor.\",\n        \"name\": \"decay\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"(optional) Effective learning rate\",\n        \"name\": \"output_effective_lr\"\n      },\n      {\n        \"description\": \"(optional) Actual update that is applied.\",\n        \"name\": \"output_update\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Adam\",\n    \"description\": \"\\n\\nComputes the Adam update (https://arxiv.org/abs/1412.6980) for an\\ninput gradient and momentum parameters. Concretely, given inputs\\n(param, m1, m2, grad, lr, iters),\\n\\n    t = iters + 1\\n    correction_multiplier = sqrt(1 - power(beta2, t)) /\\n      (1 - power(beta1, t))\\n    m1_o = (beta1 * m1) + (1 - beta1) * grad\\n    m2_o = (beta2 * m2) + (1 - beta2) * np.square(grad)\\n    grad_o = correction_multiplier * m1_o / \\\\\\n        (sqrt(m2_o) + epsilon)\\n    param_o = param + lr * grad_o\\n\\nand returns (param_o, m1_o, m2_o, grad_o), in which grad_o is an optional output\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 0.9\",\n        \"name\": \"beta1\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 0.999\",\n        \"name\": \"beta2\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"First moment history\",\n        \"name\": \"moment_1\"\n      },\n      {\n        \"description\": \"Second moment history\",\n        \"name\": \"moment_2\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"iteration number\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated first moment\",\n        \"name\": \"output_moment_1\"\n      },\n      {\n        \"description\": \"Updated second moment\",\n        \"name\": \"output_moment_2\"\n      },\n      {\n        \"description\": \"Optional Effective gradient\",\n        \"name\": \"output_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Add\",\n    \"description\": \"\\nPerforms element-wise binary addition (with limited broadcast support).\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Add\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([[1,2],[3,4]]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([[5,6],[7,8]]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[1 2]\\n [3 4]]\\nB:\\n[[5 6]\\n [7 8]]\\nC:\\n[[ 6  8]\\n [10 12]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Second operand. With broadcasting can be of smaller size than A. If broadcasting is disabled it should be of the same size as A.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor with same dimensions and type as A.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AddGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AddPadding\",\n    \"description\": \"\\nGiven a partitioned tensor $T<N, D_1, ..., D_n>$, where the partitions are\\ndefined as ranges on its outer-most (slowest varying) dimension $N$,\\nreturn a tensor $T<(N + 2 * padding\\\\_width), D_1, ..., D_n>$ with paddings\\nadded to the start and end of each range.\\n\\nOptionally, different paddings can be provided for beginning and end.\\nPaddings provided must be a tensor $T<D_1, ..., D_n>$. If no padding is\\nprovided, add zero padding. If no lengths vector is provided, add padding\\nonly once, at the start and end of data.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sequence_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"AddPadding\\\",\\n    [\\\"X\\\", \\\"lengths\\\"],\\n    [\\\"Y\\\", \\\"lengths_out\\\"],\\n    padding_width=1\\n\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,2,2).astype(np.float32)))\\nworkspace.FeedBlob(\\\"lengths\\\", np.array([3]).astype(np.int32))\\n\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"lengths_out:\\\", workspace.FetchBlob(\\\"lengths_out\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[[0.2531572  0.4588472 ]\\n  [0.45140603 0.61161053]]\\n\\n [[0.92500854 0.8045306 ]\\n  [0.03356671 0.30233648]]\\n\\n [[0.4660227  0.6287745 ]\\n  [0.79372746 0.08609265]]]\\nY: [[[0.         0.        ]\\n  [0.         0.        ]]\\n\\n [[0.2531572  0.4588472 ]\\n  [0.45140603 0.61161053]]\\n\\n [[0.92500854 0.8045306 ]\\n  [0.03356671 0.30233648]]\\n\\n [[0.4660227  0.6287745 ]\\n  [0.79372746 0.08609265]]\\n\\n [[0.         0.        ]\\n  [0.         0.        ]]]\\nlengths_out: [5]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of copies of padding to add around each range.\",\n        \"name\": \"padding_width\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"[OPTIONAL] Specifies a different end-padding width. If this is not set, will use same as `padding_width`.\",\n        \"name\": \"end_padding_width\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input data ($T<N, D_1, ..., D_n>$).\",\n        \"name\": \"data_in\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* Number of elements in each range. sum(lengths) = N.\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* [OPTIONAL] Padding data for range start ($T<D_1, ..., D_n>$).\",\n        \"name\": \"start_padding\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* [OPTIONAL] Padding for range end. If not provided, `start_padding` is used ($T<D_1, ..., D_n>$).\",\n        \"name\": \"end_padding\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Padded data tensor ($T<N + 2*padding_width, D_1, ..., D_n>$).\",\n        \"name\": \"data_out\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* [OPTIONAL] Lengths for each padded range.\",\n        \"name\": \"lengths_out\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AffineChannel\",\n    \"category\": \"Normalization\",\n    \"description\": \"\\nApplies a separate affine transformation to each channel of the input. Useful\\nfor replacing spatial batch norm with its equivalent fixed transformation.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Feature map input with order NCHW or NHWC.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D input of shape (C); the c-th element is the scale factor of the affine transformation for the c-th channel of the input.\",\n        \"name\": \"scale\"\n      },\n      {\n        \"description\": \"1D input of shape (C); the c-th element is the bias of the affine transformation for the c-th channel of the input.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output with the same order of Input.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AffineChannelGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Alias\",\n    \"description\": \"\\nMakes the output and the input share the same underlying storage.\\n\\nWARNING: in general, in caffe2's operator interface different tensors should\\nhave different underlying storage, which is the assumption made by\\ncomponents such as the dependency engine and memory optimization. Thus, in\\nnormal situations you should not use the AliasOp, especially in a normal\\nforward-backward pass.\\n\\nThe Alias op is provided so one can achieve true asynchrony, such as\\nHogwild, in a graph. But make sure you understand all the implications\\nsimilar to multi-thread computation before you use it explicitly.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor whose storage will be shared.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of same shape as input, sharing its storage.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AliasWithName\",\n    \"description\": \"\\nSimilar with AliasOp, storing the alias name as operator argument.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"name of the aliasing\",\n        \"name\": \"name\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"weather or not to alias forward or backward\",\n        \"name\": \"is_backward\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor whose storage will be shared.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of same shape as input, sharing its storage.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Allgather\",\n    \"description\": \"\\nDoes an allgather operation among the nodes.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"A tensor to be allgathered.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The allgathered tensor, same on all nodes.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Allreduce\",\n    \"description\": \"\\nDoes an allreduce operation among the nodes. Currently only Sum is supported.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"A tensor to be allreduced.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The allreduced tensor, same on all nodes.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"And\",\n    \"description\": \"\\nPerforms element-wise logical operation **and** (with limited broadcast support).\\nBoth input operands should be of type `bool`.\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"And\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", (np.random.rand(3, 3) > 0.5))\\nworkspace.FeedBlob(\\\"B\\\", (np.random.rand(3, 3) > 0.5))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n [[ True False False]\\n [False  True False]\\n [False False  True]]\\nB:\\n [[ True False  True]\\n [False False False]\\n [False False False]]\\nC:\\n [[ True False False]\\n [False False False]\\n [False False False]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor of booleans. Has same dimensions as input `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"APMeter\",\n    \"description\": \"\\nAPMeter computes Average Precision for binary or multi-class classification.\\nIt takes two inputs: prediction scores P of size (n_samples x n_classes), and\\ntrue labels Y of size (n_samples x n_classes). It returns a single float number\\nper class for the average precision of that class.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int32_t) indicates how many predictions should the op buffer. defaults to 1000\",\n        \"name\": \"buffer_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2-D tensor (Tensor<float>) of size (num_samples xnum_classes) containing prediction scores\",\n        \"name\": \"predictions\"\n      },\n      {\n        \"description\": \"2-D tensor (Tensor<float>) of size (num_samples) containing true labels for each sample\",\n        \"name\": \"labels\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor (Tensor<float>) of size num_classes containing average precision for each class\",\n        \"name\": \"AP\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Append\",\n    \"description\": \"\\nAppend input `B` to the end of input `A`.\\n\\n- It is required that this operation run in-place, meaning that the input `A` blob must match the output blob.\\n- All except the outer-most dimension must be the same between `A` and `B`.\\n- Input `A` may have to be re-allocated in order for accommodate to the new size. Currently, an exponential growth ratio is used in order to ensure amortized constant time complexity.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/dataset_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Append\\\",\\n    [\\\"A\\\", \\\"B\\\"],\\n    [\\\"A\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.random.randint(10, size=(1,3,3)))\\nworkspace.FeedBlob(\\\"B\\\", np.random.randint(10, size=(2,3,3)))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[[3 8 7]\\n  [1 6 6]\\n  [5 0 6]]]\\nB:\\n[[[4 3 1]\\n  [7 9 6]\\n  [9 4 5]]\\n\\n [[7 7 4]\\n  [9 8 7]\\n  [1 6 6]]]\\nA:\\n[[[3 8 7]\\n  [1 6 6]\\n  [5 0 6]]\\n\\n [[4 3 1]\\n  [7 9 6]\\n  [9 4 5]]\\n\\n [[7 7 4]\\n  [9 8 7]\\n  [1 6 6]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): base input tensor of shape $(N, d_1, d_2, ..., d_n)$\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"(*Tensor*): second input tensor of shape $(M, d_1, d_2, ..., d_n)$ to be appended to the base\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): output tensor of shape $(N+M, d_1, d_2, ..., d_n)$\",\n        \"name\": \"A\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"description\": \"\\nRetrieve the argmax of an axis dimension specified by the `axis`\\nargument. Given an input tensor and two arguments (`axis` and\\n`keepdims`), returns a tensor containing the indices of the largest\\nelement along the given axis. If the `keepdims` arg is *True* (default),\\nthe shape of the output tensor matches the input tensor except the\\n`axis` dimension equals 1. Else, the `axis` dimension of the output\\ntensor is removed.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/arg_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ArgMax\\\",\\n    [\\\"X\\\"],\\n    [\\\"Indices\\\"],\\n    axis=2,\\n    keepdims=False\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(3,3,3))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Indices:\\\", workspace.FetchBlob(\\\"Indices\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\nX: [[[4. 9. 6.]\\n  [6. 6. 1.]\\n  [9. 5. 4.]]\\n\\n [[6. 7. 4.]\\n  [7. 9. 1.]\\n  [3. 2. 8.]]\\n\\n [[3. 4. 6.]\\n  [5. 2. 7.]\\n  [1. 5. 7.]]]\\nIndices: [[1 0 0]\\n [1 1 2]\\n [2 2 2]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"default\": -1,\n        \"description\": \"The axis to get argmax.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"If True (default), the output tensor shape will match the input tensor shape except the `axis` dimension equals 1. Else, the `axis` dimension of the output tensor is removed.\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Tensor of indices for the largest values.\",\n        \"name\": \"Indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ArgMin\",\n    \"description\": \"\\nRetrieve the argmin of an axis dimension specified by the `axis`\\nargument. Given an input tensor and two arguments (`axis` and\\n`keepdims`), returns a tensor containing the indices of the smallest\\nelement along the given axis. If the `keepdims` arg is *True* (default),\\nthe shape of the output tensor matches the input tensor except the\\n`axis` dimension equals 1. Else, the `axis` dimension of the output\\ntensor is removed.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/arg_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ArgMin\\\",\\n    [\\\"X\\\"],\\n    [\\\"Indices\\\"],\\n    axis=1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(5,5))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Indices:\\\", workspace.FetchBlob(\\\"Indices\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX: [[9. 4. 6. 4. 1.]\\n  [5. 9. 8. 3. 4.]\\n  [6. 1. 0. 2. 9.]\\n  [7. 8. 2. 4. 9.]\\n  [3. 9. 4. 9. 4.]]\\nIndices: [[4]\\n  [3]\\n  [2]\\n  [2]\\n  [0]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"default\": -1,\n        \"description\": \"The axis to get argmin.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"If True (default), the output tensor shape will match the input tensor shape except the `axis` dimension equals 1. Else, the `axis` dimension of the output tensor is removed.\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Tensor of indices for the smallest values.\",\n        \"name\": \"Indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Asin\",\n    \"description\": \"\\nCalculates the arcsine of the given input tensor, element-wise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The arcsine of the input tensor computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AsinGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Assert\",\n    \"description\": \"\\nTakes in a tensor of type *bool*, *int*, *long*, or *long long* and checks if all values are True when coerced into a boolean. In other words, for non-bool types this asserts that all values in the tensor are non-zero. If a value is False after coerced into a boolean, the operator throws an error. Else, if all values are True, nothing is returned. For tracability, a custom error message can be set using the `error_msg` argument.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/assert_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Assert\\\",\\n    [\\\"A\\\"],\\n    [],\\n    error_msg=\\\"Failed assertion from Assert operator\\\"\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.random.randint(10, size=(3,3)).astype(np.int32))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\ntry:\\n    workspace.RunOperatorOnce(op)\\nexcept RuntimeError:\\n    print(\\\"Assertion Failed!\\\")\\nelse:\\n    print(\\\"Assertion Passed!\\\")\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[7 5 6]\\n [1 2 4]\\n [5 3 7]]\\nAssertion Passed!\\n\\n```\\n\\n</details>\\n\\n        \",\n    \"attributes\": [\n      {\n        \"description\": \"(*string*): custom error message to be thrown when the input does not pass assertion\",\n        \"name\": \"error_msg\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AsyncNetBarrier\",\n    \"description\": \"\\nThis is a pretty much no-op operator, since it's only purposes is make sure that\\nasync_scheduling will schedule certian operations earlier than others.\\n\\nExaple where this operator can work well - mixture of data-parallel and model-\\nparallel training, where one wants to force that all copies are started before\\ndata-parallel part starts.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Specifies either inputs should be across different devices in dev inference options\",\n        \"name\": \"cross_device\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Atan\",\n    \"description\": \"\\nCalculates the arctangent of the given input tensor, element-wise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The arctangent of the input tensor computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AtanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ATen\",\n    \"status\": \"contribution\"\n  },\n  {\n    \"name\": \"AtomicAppend\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AtomicFetchAdd\",\n    \"description\": \"\\nGiven a mutex and two int32 scalar tensors, performs an atomic fetch add\\nby mutating the first argument and adding it to the second input\\nargument. Returns the updated integer and the value prior to the update.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Blob containing to a unique_ptr<mutex>\",\n        \"name\": \"mutex_ptr\"\n      },\n      {\n        \"description\": \"Value to be mutated after the sum.\",\n        \"name\": \"mut_value\"\n      },\n      {\n        \"description\": \"Value to add to the first operand.\",\n        \"name\": \"increment\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Mutated value after sum. Usually same as input 1.\",\n        \"name\": \"mut_value\"\n      },\n      {\n        \"description\": \"Value of the first operand before sum.\",\n        \"name\": \"fetched_value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AtomicFetchAdd64\",\n    \"description\": \"\\nLike, AtomicFetchAdd but with int64_t scalar tensors,\\nperforms an atomic fetch add\\nby mutating the first argument and adding it to the second input\\nargument. Returns the updated integer and the value prior to the update.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Blob containing to a unique_ptr<mutex>\",\n        \"name\": \"mutex_ptr\"\n      },\n      {\n        \"description\": \"Value to be mutated after the sum.\",\n        \"name\": \"mut_value\"\n      },\n      {\n        \"description\": \"Value to add to the first operand.\",\n        \"name\": \"increment\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Mutated value after sum. Usually same as input 1.\",\n        \"name\": \"mut_value\"\n      },\n      {\n        \"description\": \"Value of the first operand before sum.\",\n        \"name\": \"fetched_value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AtomicIter\",\n    \"description\": \"\\nSimilar to Iter, but takes a mutex as the first input to make sure that\\nupdates are carried out atomically. This can be used in e.g. Hogwild sgd\\nalgorithms.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The mutex used to do atomic increment.\",\n        \"name\": \"mutex\"\n      },\n      {\n        \"description\": \"The iter counter as an int64_t TensorCPU.\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragedLoss\",\n    \"description\": \"\\nThe *AveragedLoss* op takes a single 1-D input tensor *input* and returns a single output float value *output*. The output represents the average of the values in *input*. This op is commonly used for averaging losses, hence the name, however it does not exclusively operate on losses.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/loss_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/loss_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"AveragedLoss\\\",\\n    [\\\"input\\\"],\\n    [\\\"output\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.array([8, 10, 12]).astype(np.float32))\\nprint(\\\"input:\\\\n\\\", workspace.FetchBlob(\\\"input\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output: \\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput:\\n [ 8. 10. 12.]\\noutput:\\n 10.0\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input data as Tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor of size 1 containing the averaged value.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragedLossGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool\",\n    \"category\": \"Pool\",\n    \"description\": \"AveragePool \\nconsumes an input blob and applies average pooling across the the blob according\\nto kernel sizes, stride sizes, pad lengths and dilation. Average pooling consists\\nof taking the average value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"AveragePool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-0.2883434   0.43498734  0.05417408  1.912558    0.09390241\\n    -0.33173105]\\n   [ 1.633709    1.2047161   0.36964908  0.99961185  0.4184147\\n     0.9989975 ]\\n   [ 1.7644193   0.1789665   1.5812988  -0.6038542  -0.36090398\\n     0.33195344]\\n   [ 0.9457722  -0.95174325 -0.78124577  1.2062047   1.1903144\\n     0.2586746 ]\\n   [ 1.252104    0.32645547  1.8073524  -0.78397465  0.9978303\\n    -0.97614396]\\n   [ 0.5440196   1.5778259  -0.76750124  0.5051756   0.8838398\\n    -0.37085298]]]]\\n\\nY:\\n [[[[0.7462672  0.83399826 0.2948959 ]\\n   [0.4843537  0.3506009  0.35500962]\\n   [0.9251013  0.19026303 0.13366827]]]]\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool1D\",\n    \"description\": \"AveragePool1D \\nconsumes an input blob and applies average pooling across the the blob according\\nto kernel sizes, stride sizes, pad lengths and dilation. Average pooling consists\\nof taking the average value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"AveragePool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-0.2883434   0.43498734  0.05417408  1.912558    0.09390241\\n    -0.33173105]\\n   [ 1.633709    1.2047161   0.36964908  0.99961185  0.4184147\\n     0.9989975 ]\\n   [ 1.7644193   0.1789665   1.5812988  -0.6038542  -0.36090398\\n     0.33195344]\\n   [ 0.9457722  -0.95174325 -0.78124577  1.2062047   1.1903144\\n     0.2586746 ]\\n   [ 1.252104    0.32645547  1.8073524  -0.78397465  0.9978303\\n    -0.97614396]\\n   [ 0.5440196   1.5778259  -0.76750124  0.5051756   0.8838398\\n    -0.37085298]]]]\\n\\nY:\\n [[[[0.7462672  0.83399826 0.2948959 ]\\n   [0.4843537  0.3506009  0.35500962]\\n   [0.9251013  0.19026303 0.13366827]]]]\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool1DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool2D\",\n    \"description\": \"AveragePool2D \\nconsumes an input blob and applies average pooling across the the blob according\\nto kernel sizes, stride sizes, pad lengths and dilation. Average pooling consists\\nof taking the average value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"AveragePool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-0.2883434   0.43498734  0.05417408  1.912558    0.09390241\\n    -0.33173105]\\n   [ 1.633709    1.2047161   0.36964908  0.99961185  0.4184147\\n     0.9989975 ]\\n   [ 1.7644193   0.1789665   1.5812988  -0.6038542  -0.36090398\\n     0.33195344]\\n   [ 0.9457722  -0.95174325 -0.78124577  1.2062047   1.1903144\\n     0.2586746 ]\\n   [ 1.252104    0.32645547  1.8073524  -0.78397465  0.9978303\\n    -0.97614396]\\n   [ 0.5440196   1.5778259  -0.76750124  0.5051756   0.8838398\\n    -0.37085298]]]]\\n\\nY:\\n [[[[0.7462672  0.83399826 0.2948959 ]\\n   [0.4843537  0.3506009  0.35500962]\\n   [0.9251013  0.19026303 0.13366827]]]]\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool2DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool3D\",\n    \"description\": \"AveragePool3D \\nconsumes an input blob and applies average pooling across the the blob according\\nto kernel sizes, stride sizes, pad lengths and dilation. Average pooling consists\\nof taking the average value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"AveragePool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-0.2883434   0.43498734  0.05417408  1.912558    0.09390241\\n    -0.33173105]\\n   [ 1.633709    1.2047161   0.36964908  0.99961185  0.4184147\\n     0.9989975 ]\\n   [ 1.7644193   0.1789665   1.5812988  -0.6038542  -0.36090398\\n     0.33195344]\\n   [ 0.9457722  -0.95174325 -0.78124577  1.2062047   1.1903144\\n     0.2586746 ]\\n   [ 1.252104    0.32645547  1.8073524  -0.78397465  0.9978303\\n    -0.97614396]\\n   [ 0.5440196   1.5778259  -0.76750124  0.5051756   0.8838398\\n    -0.37085298]]]]\\n\\nY:\\n [[[[0.7462672  0.83399826 0.2948959 ]\\n   [0.4843537  0.3506009  0.35500962]\\n   [0.9251013  0.19026303 0.13366827]]]]\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePool3DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePoolGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"AveragePut\",\n    \"description\": \"\\n    Consume a value and pushes it to the global stat registry as an average.\\n\\n    Github Links:\\n    - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_put_ops.cc\\n\\n        \",\n    \"attributes\": [\n      {\n        \"description\": \"(*str*): name of the stat. If not present, then uses name of input blob\",\n        \"name\": \"name\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int64_t*): number to multiply input values by (used when inputting floats, as stats can only receive integers\",\n        \"name\": \"magnitude_expand\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*boolean*): whether or not to clamp inputs to the max inputs allowed\",\n        \"name\": \"bound\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*float*): Optionally provide a default value for receiving empty tensors\",\n        \"name\": \"default_value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<number>`*): A scalar tensor, representing any numeric value\",\n        \"name\": \"value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Barrier\",\n    \"description\": \"\\nDoes a barrier operation among the nodes.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchBoxCox\",\n    \"description\": \"\\nInput `data` is a N * D matrix. Apply box-cox transform for each column.\\n`lambda1` and `lambda2` is of size D that defines the hyper-parameters for\\nthe transform of each column `x` of the input `data`:\\n\\n    ln(x + lambda2), if lambda1 == 0\\n    ((x + lambda2)^lambda1 - 1)/lambda1, if lambda1 != 0\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"input float or double N * D matrix\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"tensor of size D with the same type as data\",\n        \"name\": \"lambda1\"\n      },\n      {\n        \"description\": \"tensor of size D with the same type as data\",\n        \"name\": \"lambda2\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output matrix that applied box-cox transform\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchBucketize\",\n    \"description\": \"\\nBucketize the float_features into sparse features.\\nThe float_features is a N * D tensor where N is the batch_size, and D is the feature_dim.\\nThe indices is a 1D tensor containing the indices of the features that need to be bucketized.\\nThe lengths is a 1D tensor that splits the following 'boundaries' argument.\\nThe boundaries is a 1D tensor containing the border list for each feature.\\n\\nWith in each batch, `indices` should not have duplicate number,\\nand the number of elements in `indices` should be less than or equal to `D`.\\nEach element in `lengths` vector (lengths[`i`]) represents\\nthe number of boundaries in the sub border list.\\nThe sum of all elements in `lengths` must be equal to the size of  `boundaries`.\\nIf lengths[0] = 2, the first sub border list is [0.5, 1.0], which separate the\\nvalue to (-inf, 0.5], (0,5, 1.0], (1.0, inf). The bucketized feature will have\\nthree possible values (i.e. 0, 1, 2).\\n\\n\\nFor example, with input:\\n\\n  float_features = [[1.42, 2.07, 3.19, 0.55, 4.32],\\n                    [4.57, 2.30, 0.84, 4.48, 3.09],\\n                    [0.89, 0.26, 2.41, 0.47, 1.05],\\n                    [0.03, 2.97, 2.43, 4.36, 3.11],\\n                    [2.74, 5.77, 0.90, 2.63, 0.38]]\\n  indices = [0, 1, 4]\\n  lengths = [2, 3, 1]\\n  boundaries =  [0.5, 1.0, 1.5, 2.5, 3.5, 2.5]\\n\\nThe output is:\\n\\n  output =[[2, 1, 1],\\n           [2, 1, 1],\\n           [1, 0, 0],\\n           [0, 2, 1],\\n           [2, 3, 0]]\\n\\nafter running this operator.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"2-D dense tensor, the second dimension must be greater or equal to the indices dimension\",\n        \"name\": \"float_features\"\n      },\n      {\n        \"description\": \"Flatten tensor, containing the indices of `float_features` to be bucketized. The datatype must be int32.\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Flatten tensor, the size must be equal to that of `indices`. The datatype must be int32.\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"Flatten tensor, dimension has to match the sum of lengths\",\n        \"name\": \"boundaries\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2-D dense tensor, with 1st dim = float_features.dim(0), 2nd dim = size(indices)in the arg list, the tensor is of the same data type as `feature`.\",\n        \"name\": \"bucktized_feat\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchBucketOneHot\",\n    \"description\": \"\\nInput is a matrix tensor. Its first dimension is the batch\\nsize. For each column, bucketize it based on the boundary values and then do\\none hot encoding. The `lengths` specifies the number of boundary values for each\\ncolumn. The final number of buckets is this number plus 1. This would also be\\nthe expanded feature size. `boundaries` specifies all the boundary values.\\nNote that each bucket is right-inclusive. That is, given boundary values\\n[b1, b2, b3], the buckets are defined as (-int, b1], (b1, b2], (b2, b3], (b3, inf).\\nFor example\\n\\n  data = [[2, 3], [4, 1], [2, 5]], lengths = [2, 3],\\n  If boundaries = [0.1, 2.5, 1, 3.1, 4.5], then\\n  output = [[0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 1]]\\n\\n  If boundaries = [0.1, 2.5, 1, 1, 3.1], then\\n  output = [[0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 1]]\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"input tensor matrix\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"the size is the same as the width of the `data`\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"bucket boundaries\",\n        \"name\": \"boundaries\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output matrix that expands each input column with one hot encodingbased on the bucketization\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchDenseToSparse\",\n    \"description\": \"\\nThis Op is a inverse of BatchSparseToDenseOp.\\nBasically, given a `lengths` vector, a `indices` vector,\\nand a dense matrix `dense`, output `value` vector so that, along with\\n`lengths` vector and `indices` vector, forms a sparse representation\\nof the dense matrix.\\n\\nA sparse matrix is represented by `lengths` vector, `indices` vector,\\nand `values` vector. Each element in `lengths` vector (lengths[`i`]) represents\\nthe number of indices in this batch (batch `i`).\\nWith in each batch, `indices` should not have duplicate number.\\n\\nFor example, with input:\\n\\n  lengths = [2, 3, 1]\\n  indices = [0, 1, 2, 3, 4, 5]\\n  output = [[6, 7, 0, 0, 0,  0],\\n            [0, 0, 8, 9, 10, 0],\\n            [0, 0, 0, 0, 0, 11]]\\n\\nThe output is:\\n\\n  values = [6, 7, 8, 9, 10, 11]\\n\\nafter running this operator.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Flatten lengths, Used to break down indices into per batch indices\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"Flatten indices, tensor of total size = \\\\sum lengths, containing the indices \",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"dense 2-D tensor, first dim = len(lengths), last dim > Any(indices)\",\n        \"name\": \"dense\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Values, tensor of the same size as `indices` and same data type as dense tensor.\",\n        \"name\": \"values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchGather\",\n    \"description\": \"\\nBatch gather operation, first dimension in DATA is the batch size.\\nGiven DATA tensor of rank r >= 2, and INDICES tensor of rank q >= 1, gather\\nentries of the second outer dimension (axis == 1) of DATA indexed by INDICES,\\nand concatenate them in an output tensor of rank q + (r - 1).\\n\\nExample:\\n  DATA  = [\\n      [1.0, 1.2, 2.4, 4.5],\\n      [2.3, 3.4, 3.6, 2.3],\\n      [4.5, 5.7, 1.2, 4.5],\\n  ]\\n  INDICES = [0, 2]\\n\\n  OUTPUT = [\\n      [1.0, 2.4],\\n      [2.3, 3.6],\\n      [4.5, 1.2],\\n  ]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of rank r >= 2.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Tensor of int32/int64 indices, of any rank q.\",\n        \"name\": \"INDICES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of rank q + (r - 1).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchGatherGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchMatMul\",\n    \"description\": \"\\nBatch Matrix multiplication Yi = Ai * Bi, where A has shape (dim0, dim1, ... M, K),\\nB has shape (dim0, dim1, ... K, N), Y has shape (dim0, dim1, ... M, N) and i ranges\\nfrom 0 to (dim0 * dim1 ...) - 1. rank(A) == rank(B) >= 2. In case of A and B being\\ntwo dimensional, it behaves like normal matrix multiplication.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Pass 1 to transpose the last two dimensions of A before doing multiplication\",\n        \"name\": \"trans_a\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Pass 1 to transpose the last two dimensions of B before doing multiplication\",\n        \"name\": \"trans_b\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Pass 1 to allow broadcasting of dimensions. Behavior is the same as numpy.matmul. Gradient is currently not supported when running in broadcast mode.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"tensor of shape (dim0, dim1 ... M, K)\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"tensor of shape (dim0, dim1 ... K, N)\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"tensor of shape (dim0, dim1 ... M, N)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchMoments\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchMomentsGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchOneHot\",\n    \"description\": \"\\nInput is a matrix tensor. Its first dimension is the batch\\nsize. Expand each column of it using one hot encoding. The `lengths` specifies\\nthe size of each column after encoding, and the `values` is the dictionary value\\nof one-hot encoding for each column. For example\\n\\n  If data = [[2, 3], [4, 1], [2, 5]], lengths = [2, 3],\\n  and values = [2, 4, 1, 3, 5], then\\n\\n  output = [[1, 0, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 0, 0, 1]]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"input tensor matrix\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"the size is the same as the width of the `data`\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"one hot encoding dictionary values\",\n        \"name\": \"values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output matrix that expands each input column with one hot encoding\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchPermutation\",\n    \"description\": \"\\nBatch permutation of an input tensor X given input indices. First dimension of\\nX equals batch size N. The indices stores a be permutation of N.\\nThe output Y is a tensor of same shape as X, with data re-ordered according to\\nthe indices within the batch size.\\n\\nExample of batch permutation on a 2-D tensor with batch size 4:\\n  X = [\\n    [1, 5, 2, 3, 4, 6, 0],\\n    [4, 3, 3, 5, 2, 3, 1],\\n    [2, 2, 3, 6, 0, 0, 1],\\n    [0, 0, 1, 1, 2, 2, 3]\\n  ]\\n  indices = [2, 0, 1, 3]\\n  Y = [\\n    [2, 2, 3, 6, 0, 0, 1],\\n    [1, 5, 2, 3, 4, 6, 0],\\n    [4, 3, 3, 5, 2, 3, 1],\\n    [0, 0, 1, 1, 2, 2, 3]\\n  ]\\n\\nExample of batch permutation on a 3-D tensor with batch size 4:\\n  X = [\\n    [[1, 5, 2], [3, 4, 6, 0]],\\n    [[4, 3, 3], [5, 2, 3, 1]],\\n    [[2, 2, 3], [6, 0, 0, 1]],\\n    [[0, 0, 1], [1, 2, 2, 3]]\\n  ]\\n  indices = [2, 0, 1, 3]\\n  Y = [\\n    [[2, 2, 3], [6, 0, 0, 1]],\\n    [[1, 5, 2], [3, 4, 6, 0]],\\n    [[4, 3, 3], [5, 2, 3, 1]],\\n    [[0, 0, 1], [1, 2, 2, 3]]\\n  ]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, where 1st dimension equals batch size\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Input indices of batch to permute\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output permuted tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchPermutationGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchSparseToDense\",\n    \"description\": \"\\nConvert sparse matrix representation into dense matrix.\\n\\nA sparse matrix is represented by `lengths` vector, `indices` vector,\\nand `values` vector. Each element in `lengths` vector (lengths[`i`]) represents\\nthe number of indices in this batch (batch `i`).\\nWith in each batch, `indices` should not have duplicate number.\\n\\nFor example, with input:\\n\\n  lengths = [2, 3, 1]\\n  indices = [0, 1, 2, 3, 4, 5]\\n  values =  [6, 7, 8, 9, 10, 11]\\n  dense_dim = 6\\n  default_value = 0\\n\\nThe output is:\\n\\n  output = [[6, 7, 0, 0, 0,  0],\\n            [0, 0, 8, 9, 10, 0],\\n            [0, 0, 0, 0, 0, 11]]\\n\\nafter running this operator.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Optional, output dense last dimension. If both this argument and output_shape_inference are set, it should be consistent with output_shape_inference's last dim\",\n        \"name\": \"dense_last_dim\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Optional, missing values are filled with this value.default_value = 0 when not set\",\n        \"name\": \"default_value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Flatten tensor, used to break down indices and values into per batch indices and values.\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"Flatten tensor of total size = \\\\sum lengths, containing the indices \",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Data tensor, dimension has to match `indices`\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"Optional, a dense tensor whose shape define the output shape\",\n        \"name\": \"output_shape_inference\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2-D dense tensor, with 1st dim = len(lengths), 2nd dim = dense_last_dimin the arg list, the tensor is of the same data type as `values`.Missing values are filled with default_value\",\n        \"name\": \"dense\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchToSpace\",\n    \"description\": \"\\nRearranges (permutes) data from batch into blocks of spatial data, followed by cropping. This is the reverse transformation of `SpaceToBatch`. More specifically, this op outputs a copy of the input tensor where values from the batch dimension are moved in spatial blocks to the height and width dimensions, followed by cropping along the height and width dimensions. Only \\\"NCHW\\\" order is currently supported.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/space_batch_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"BatchToSpace\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    pad=3\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(10,3,32,32).astype(np.float32))\\nprint(\\\"X.shape:\\\", workspace.FetchBlob(\\\"X\\\").shape)\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y.shape:\\\", workspace.FetchBlob(\\\"Y\\\").shape)\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX.shape: (10, 3, 32, 32)\\nY.shape: (2, 3, 58, 58)\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): exclusive axis that divides the first and second dimension of matrix `A` (default=0)\",\n        \"name\": \"pad\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): height/width of spatial blocks to be moved (default=2)\",\n        \"name\": \"block_size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*string*): order of dimensions of input and output blobs; only \\\"NCHW\\\" order is currently supported (default=\\\"NCHW\\\")\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor (NCHW order)\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): output tensor (NCHW order)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BBoxTransform\",\n    \"description\": \"\\nTransform proposal bounding boxes to target bounding box using bounding box\\n    regression deltas.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"vector<float> weights [wx, wy, ww, wh] for the deltas\",\n        \"name\": \"weights\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default true), transform the boxes to the scaled image space after applying the bbox deltas.Set to false to match the detectron code, set to true for keypoint models and for backward compatibility\",\n        \"name\": \"apply_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default false), Correct bounding box transform coordates, see bbox_transform() in boxes.py Set to true to match the detectron code, set to false for backward compatibility\",\n        \"name\": \"correct_transform_coords\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default false). If true, then boxes (rois and deltas) include angle info to handle rotation. The format will be [ctr_x, ctr_y, width, height, angle (in degrees)].\",\n        \"name\": \"rotated\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default true). If set, for rotated boxes, angle is normalized to be within [angle_bound_lo, angle_bound_hi].\",\n        \"name\": \"angle_bound_on\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int (default -90 degrees). If set, for rotated boxes, angle is normalized to be within [angle_bound_lo, angle_bound_hi].\",\n        \"name\": \"angle_bound_lo\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int (default 90 degrees). If set, for rotated boxes, angle is normalized to be within [angle_bound_lo, angle_bound_hi].\",\n        \"name\": \"angle_bound_hi\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"float (default 1.0 degrees). For RRPN, clip almost horizontal boxes within this threshold of tolerance for backward compatibility. Set to negative value for no clipping.\",\n        \"name\": \"clip_angle_thresh\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Bounding box proposals in pixel coordinates, Size (M, 4), format [x1, y1, x2, y2], orSize (M, 5), format [batch_index, x1, y1, x2, y2]. If proposals from multiple images in a batch are present, they should be grouped sequentially and in incremental order.For rotated boxes, this would have an additional angle (in degrees) in the format [<optionaal_batch_id>, ctr_x, ctr_y, w, h, angle].\",\n        \"name\": \"rois\"\n      },\n      {\n        \"description\": \"bounding box translations and scales,size (M, 4*K), format [dx, dy, dw, dh], K = # classes. For rotated boxes, size (M, 5*K, format [dx, dy, dw, dh, da].\",\n        \"name\": \"deltas\"\n      },\n      {\n        \"description\": \"Image dimensions, size (batch_size, 3), format [img_height, img_width, img_scale]\",\n        \"name\": \"im_info\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Pixel coordinates of the transformed bounding boxes,Size (M, 4*K), format [x1, y1, x2, y2]. For rotated boxes, size (M, 5*K), format [ctr_x, ctr_y, w, h, angle].\",\n        \"name\": \"box_out\"\n      },\n      {\n        \"description\": \"Tensor of shape (batch_size) with each element denoting the number of RoIs belonging to the corresponding image in batch\",\n        \"name\": \"roi_batch_splits\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BernoulliJSD\",\n    \"description\": \"\\nComputes the Jensen-Shannon divergence (JSD) between two Bernoulli distributions\\nwhere each is parametrized by a single probability.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"array of probabilities for target\",\n        \"name\": \"T\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"array of JSD losses\",\n        \"name\": \"L\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BernoulliJSDGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BisectPercentile\",\n    \"description\": \"\\n    This operator is to map raw feature values into the percentile\\n    representations based on Bisection for more than one feature.\\n\\n    The input is the bath of input feature values, with the size of (batch_size,\\n    num_feature), where num_feature = F (F >= 1).\\n\\n    For each feature, we also need additional information regarding the feature\\n    value distribution.\\n    There are several vectors to keep data to percentile mappping information\\n    as arguments (context):\\n    1. feature raw values (R)\\n    2. feature percentile mapping (P)\\n    3. feature percentile lower bound (L)\\n    4. feature percentile upper bound (U)\\n\\n    A toy example:\\n    Suppose the sampled data distribution is as follows:\\n    1, 1, 2, 2, 2, 2, 2, 2, 3, 4\\n    We have the mapping vectors as follows:\\n    R = [1, 2, 3, 4]\\n    P = [0.15, 0.55, 0.9, 1.0]\\n    L = [0.1, 0.3, 0.9, 1.0]\\n    U = [0.2, 0.8, 0.9, 1.0]\\n    Where P is computed as (L + U) / 2.\\n\\n    For a given list of feature values, X = [x_0, x_1, ..., x_i, ...], for each\\n    feature value (x_i) we first apply bisection to find the right index (t),\\n    such that R[t] <= x_i < R[t+1].\\n    If x_i = R[t], P[t] is returned;\\n    otherwise, the interpolation is apply by (R[t], R[t+1]) and (U[t] and L[t]).\\n\\n    As there are F features (F >= 1), we concate all the R_f, P_f, L_f, and\\n    U_f for each feature f and use an additional input length to keep track of\\n    the number of points for each set of raw feature value to percentile mapping.\\n    For example, there are two features:\\n    R_1 =[0.1, 0.4, 0.5];\\n    R_2 = [0.3, 1.2];\\n    We will build R = [0.1, 0.4, 0.5, 0.3, 1.2]; besides, we have\\n    lengths = [3, 2]\\n    to indicate the boundaries of the percentile information.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"1D tensor, which is the concatenation of all sorted raw feature values for all features.\",\n        \"name\": \"percentile_raw\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor. There is one-one mapping between percentile_mapping and percentile_raw such that each element in percentile_mapping corresponds to the percentile value of the corresponding raw feature value.\",\n        \"name\": \"percentile_mapping\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor. There is one-one mapping between percentile_upper and percentile_raw such that each element in percentile_mapping corresponds to the percentile lower bound of the corresponding raw feature value.\",\n        \"name\": \"percentile_lower\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor. There is one-one mapping between percentile_upper and percentile_raw such that each element in percentile_mapping corresponds to the percentile upper bound of the corresponding raw feature value.\",\n        \"name\": \"percentile_upper\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor. There is one-one mapping between percentile_upper and percentile_raw such that each element in percentile_mapping corresponds to the percentile upper bound of the corresponding raw feature value.\",\n        \"name\": \"lengths\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input 2D tensor of floats of size (N, D), where N is the batch size and D is the feature dimension.\",\n        \"name\": \"raw_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2D tensor of output with the same dimensions as the input raw_values.\",\n        \"name\": \"percentile\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BitwiseAnd\",\n    \"description\": \"\\nPerforms element-wise bitwise operation `bitwise_and` (with limited broadcast support).\\nBoth input operands should be of type `bool`.\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* First operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Output tensor. Has same dimensions as input `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BitwiseOr\",\n    \"description\": \"\\nPerforms element-wise bitwise operation `bitwise_or` (with limited broadcast support).\\nBoth input operands should be of type `bool`.\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* First operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Output tensor. Has same dimensions as input `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BitwiseXor\",\n    \"description\": \"\\nPerforms element-wise bitwise operation `bitwise_xor` (with limited broadcast support).\\nBoth input operands should be of type `bool`.\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* First operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Output tensor. Has same dimensions as input `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BooleanMask\",\n    \"description\": \"\\nGiven a 1D `data` tensor and a boolean `mask` tensor of the same shape, returns a `masked_data` tensor containing only the elements corresponding to positions where the `mask` is True, and a `masked_indices` tensor containing the indices of the True elements.\\n\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/boolean_mask_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"BooleanMask\\\",\\n    [\\\"data\\\", \\\"mask\\\"],\\n    [\\\"masked_data\\\", \\\"masked_indices\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"data\\\", np.array([1,2,3,4,5,6]))\\nworkspace.FeedBlob(\\\"mask\\\", np.array([True,False,False,True,True,False]))\\nprint(\\\"data:\\\", workspace.FetchBlob(\\\"data\\\"))\\nprint(\\\"mask:\\\", workspace.FetchBlob(\\\"mask\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"masked_data:\\\", workspace.FetchBlob(\\\"masked_data\\\"))\\nprint(\\\"masked_indices:\\\", workspace.FetchBlob(\\\"masked_indices\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ndata: [1 2 3 4 5 6]\\nmask: [ True False False  True  True False]\\nmasked_data: [1 4 5]\\nmasked_indices: [0 3 4]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): 1D input tensor\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"(*Tensor`<bool>`*): tensor of bools which determines the input elements that will be left in the `masked_data` output tensor; same shape as `data`\",\n        \"name\": \"mask\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): 1D tensor of same type as `data` input that contains the masked input tensor\",\n        \"name\": \"masked_data\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): 1D tensor of indices of the True elements in the `mask` tensor\",\n        \"name\": \"masked_indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BooleanMaskGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BooleanMaskLengths\",\n    \"description\": \"\\nGiven a tensor of int32 `lengths` tensor representing segment lengths and a `mask` (boolean) tensor, return the segment lengths of the corresponding segmented tensor after **BooleanMask** is applied.\\n\\nIf `lengths` tensor is $[a_1, a_2, ..., a_n]$, then length of `mask` tensor must be $a_1 + a_2 + ... + a_n$.\\n\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/boolean_mask_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"BooleanMaskLengths\\\",\\n    [\\\"lengths\\\", \\\"mask\\\"],\\n    [\\\"masked_lengths\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"lengths\\\", np.array([1,3,2], dtype=np.int32))\\nworkspace.FeedBlob(\\\"mask\\\", np.array([False,True,True,False,True,True]))\\nprint(\\\"lengths:\\\", workspace.FetchBlob(\\\"lengths\\\"))\\nprint(\\\"mask:\\\", workspace.FetchBlob(\\\"mask\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"masked_lengths:\\\", workspace.FetchBlob(\\\"masked_lengths\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nlengths: [1 3 2]\\nmask: [False  True  True False  True  True]\\nmasked_lengths: [0 2 2]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<int>`*): input tensor containing segment lengths\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"(*Tensor`<bool>`*): A 1D bool tensor of values to keep.\",\n        \"name\": \"mask\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<int>`*): 1D tensor of same type as inputs that contains the sequence\",\n        \"name\": \"masked_lengths\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BooleanUnmask\",\n    \"description\": \"\\nGiven a series of masks and values, reconstruct values together according to masks. A comprehensive example:\\n```\\nmask1   = True, False, True, False, False\\nvalues1 = 1.0, 3.0\\nmask2   = False, True, False, False, False\\nvalues2 = 2.0\\nmask3   = False, False, False, True, True\\nvalues3 = 4.0, 5.0\\n```\\n\\nReconstruct by:\\n\\n```\\noutput = net.BooleanUnmask([mask1, values1, mask2, values2, mask3, values3], [\\\"output\\\"])\\noutput = 1.0, 2.0, 3.0, 4.0, 5.0\\n```\\n\\nNote that for all mask positions, there must be at least one True. This is not allowed:\\n\\n```\\nmask1   = True, False\\nvalues1 = 1.0\\nmask2   = False, False\\nvalues2 =\\n\\noutput = net.BooleanUnmask([mask1, values1, mask2, values2], [\\\"output\\\"])\\n```\\n\\nIf there are multiple True values for a field, we accept the first value, and no longer expect a value for that location:\\n\\n```\\nmask1   = True, False\\nvalues1 = 1.0\\nmask2   = True, True\\nvalues2 = 2.0\\n\\noutput = net.BooleanUnmask([mask1, values1, mask2, values2], [\\\"output\\\"])\\noutput = 1.0, 2.0\\n```\\n\\n*** Note that we alternate `data` and `mask` inputs\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/boolean_unmask_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"BooleanUnmask\\\",\\n    [\\\"mask1\\\", \\\"data1\\\", \\\"mask2\\\", \\\"data2\\\"],\\n    [\\\"unmasked_data\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"mask1\\\", np.array([True,False,False,True,True,False]))\\nworkspace.FeedBlob(\\\"data1\\\", np.array([1,4,5]))\\nworkspace.FeedBlob(\\\"mask2\\\", np.array([False,True,True,False,False,True]))\\nworkspace.FeedBlob(\\\"data2\\\", np.array([2,3,6]))\\n\\nprint(\\\"data1:\\\", workspace.FetchBlob(\\\"data1\\\"))\\nprint(\\\"mask1:\\\", workspace.FetchBlob(\\\"mask1\\\"))\\nprint(\\\"data2:\\\", workspace.FetchBlob(\\\"data2\\\"))\\nprint(\\\"mask2:\\\", workspace.FetchBlob(\\\"mask2\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"unmasked_data:\\\", workspace.FetchBlob(\\\"unmasked_data\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ndata1: [1 4 5]\\nmask1: [ True False False  True  True False]\\ndata2: [2 3 6]\\nmask2: [False  True  True False False  True]\\nunmasked_data: [1 2 3 4 5 6]\\n\\n```\\n\\n</details>\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): 1D input tensor(s)\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"(*Tensor`<bool>`*): 1D boolean mask tensor(s)\",\n        \"name\": \"mask\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): 1D tensor of same type as `data` input that contains the unmasked input tensor\",\n        \"name\": \"unmasked_data\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BoxWithNMSLimit\",\n    \"description\": \"\\nApply NMS to each class (except background) and limit the number of\\nreturned boxes.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float) TEST.SCORE_THRESH\",\n        \"name\": \"score_thresh\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) TEST.NMS\",\n        \"name\": \"nms\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) TEST.DEECTIONS_PER_IM\",\n        \"name\": \"detections_per_im\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(bool) TEST.SOFT_NMS.ENABLED\",\n        \"name\": \"soft_nms_enabled\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(string) TEST.SOFT_NMS.METHOD\",\n        \"name\": \"soft_nms_method\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) TEST.SOFT_NMS.SIGMA\",\n        \"name\": \"soft_nms_sigma\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) Lower bound on updated scores to discard boxes\",\n        \"name\": \"soft_nms_min_score_thres\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default false). If true, then boxes (rois and deltas) include angle info to handle rotation. The format will be [ctr_x, ctr_y, width, height, angle (in degrees)].\",\n        \"name\": \"rotated\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Scores, size (count, num_classes)\",\n        \"name\": \"scores\"\n      },\n      {\n        \"description\": \"Bounding box for each class, size (count, num_classes * 4). For rotated boxes, this would have an additional angle (in degrees) in the format [<optionaal_batch_id>, ctr_x, ctr_y, w, h, angle]. Size: (count, num_classes * 5).\",\n        \"name\": \"boxes\"\n      },\n      {\n        \"description\": \"Tensor of shape (batch_size) with each element denoting the number of RoIs/boxes belonging to the corresponding image in batch. Sum should add up to total count of scores/boxes.\",\n        \"name\": \"batch_splits\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Filtered scores, size (n)\",\n        \"name\": \"scores\"\n      },\n      {\n        \"description\": \"Filtered boxes, size (n, 4). For rotated boxes, size (n, 5), format [ctr_x, ctr_y, w, h, angle].\",\n        \"name\": \"boxes\"\n      },\n      {\n        \"description\": \"Class id for each filtered score/box, size (n)\",\n        \"name\": \"classes\"\n      },\n      {\n        \"description\": \"Output batch splits for scores/boxes after applying NMS\",\n        \"name\": \"batch_splits\"\n      },\n      {\n        \"description\": \"Optional filtered indices, size (n)\",\n        \"name\": \"keeps\"\n      },\n      {\n        \"description\": \"Optional number of filtered indices per class, size (num_classes)\",\n        \"name\": \"keeps_size\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BRGNCHWCToPackedInt8BGRAStylizerDeprocess\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Broadcast\",\n    \"description\": \"\\nDoes a broadcast operation from the root node to every other node. The tensor\\non each node should have been pre-created with the same shape and data type.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) the root to run broadcast from.\",\n        \"name\": \"root\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"A tensor to be broadcasted.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"In-place as input 1.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Bucketize\",\n    \"description\": \"\\nThis operator works as bucketize in tensorflow and digitize\\nin numpy. It bucketizes the input 'X' based on argument 'boundaries'.\\nFor each value x in input 'data', the operator returns index i given\\nboundaries[i-1] < x <= boundaries[i].\\nIf values in 'data' are beyond the bounds of boundaries, 0 or\\nlen(boundaries) is returned as appropriate.\\nThe boundaries need to be monotonically increasing.\\nFor example\\n\\nIf data = [2, 4, 1] and boundaries = [0.1, 2.5], then\\n\\noutput = [1, 2, 1]\\n\\nIf data = [[2, 3], [4, 1], [2, 5]] and boundaries = [0.1, 2.5], then\\n\\noutput = [[1, 2], [2, 1], [1, 2]]\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"bucketization boundaries\",\n        \"name\": \"boundaries\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"input tensor\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"indices of bins given by boundaries to which each valuein data belongs\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ByteWeightDequant\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Cast\",\n    \"description\": \"\\nCasts the elements of a given input tensor to a data type specified by the `to`\\nargument and returns an output tensor of the same size in the converted type.\\nThe `to` argument must be one of the data types specified in the *DataType*\\nenum field in the TensorProto message (see below). If the `to` argument is not\\nprovided or is not one of the enumerated types in *DataType*, Caffe2 throws an\\nEnforce error.\\n\\nNOTE: Casting from strings is not supported, and casting to strings is only\\nsupported on CPU.\\n\\nTensorProto *DataType* field:\\n```\\nmessage TensorProto {\\n  ...\\n  enum DataType {\\n    UNDEFINED = 0;\\n    FLOAT = 1;  // float\\n    INT32 = 2;  // int\\n    BYTE = 3;  // BYTE, when deserialized, is going to be restored as uint8.\\n    STRING = 4;  // string\\n    BOOL = 5;  // bool\\n    UINT8 = 6;  // uint8_t\\n    INT8 = 7;  // int8_t\\n    UINT16 = 8;  // uint16_t\\n    INT16 = 9;  // int16_t\\n    INT64 = 10;  // int64_t\\n    FLOAT16 = 12;  // at::Half\\n    DOUBLE = 13;  // double\\n  }\\n```\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/cast_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Cast\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    to=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,3)).astype(np.float32)*10)\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[9.436466   5.8529844  0.54932857]\\n [1.1583444  2.9936118  0.22950427]\\n [3.9143739  3.4040766  8.905341  ]]\\nY: [[9 5 0]\\n [1 2 0]\\n [3 3 8]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Data type to which the elements of the input tensor are cast. Strictly must be one of the types from *DataType* enum in TensorProto.\",\n        \"name\": \"to\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input tensor to be cast.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<'to' type>`)* Output tensor with the same shape as input with type specified by the `to` argument.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Cbrt\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor calculated as the cbrt of the input tensor, element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CbrtGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Ceil\",\n    \"description\": \"\\nElement-wise application of the ceil function ($y=ceil(x)$) to the input tensor\\n`X`. Output tensor shape is the same as the input tensor.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/ceil_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Ceil\\\",\\n    [\\\"X\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.uniform(-10, 10, (5,5))).astype(np.float32))\\nprint(\\\"X before running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X after running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX before running op:\\n[[ 8.44598    -6.5098248  -2.2993476  -7.6859694   0.58566964]\\n [-7.846551   -0.03689406  6.9362907  -4.0521703   4.4969673 ]\\n [ 0.33355865 -7.895527   -8.393201    9.374202   -2.3930092 ]\\n [-6.3061996   3.1403487   3.782099   -8.516556   -2.8387244 ]\\n [-2.0164998   4.7663913  -3.422966    0.3636999   8.75713   ]]\\nX after running op:\\n[[ 9. -6. -2. -7.  1.]\\n [-7. -0.  7. -4.  5.]\\n [ 1. -7. -8. 10. -2.]\\n [-6.  4.  4. -8. -2.]\\n [-2.  5. -3.  1.  9.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ChannelBackpropStats\",\n    \"description\": \"\\nGiven an input tensor in NCHW format, the gradient for the output of SpatialBN\\nand the per-channel mean and inverse std var vectors for the input, computes the\\nper-channel bias and scale gradient to be used during the backward pass for\\nsubsequent spatial batch normalization gradient calculation. Typically, the\\nresults of this op are subsequently reduced over multiple devices to obtain\\nstatistics over a larger batch size in cases where the batch size for a single\\nmodel copy is too low to yield the full benefit of batch normalization. The\\nresulting bias and scale can then be plugged back into SpatialBNGradient to get\\nresults over the larger batch size \",\n    \"inputs\": [\n      {\n        \"description\": \"The input 4-dimensional tensor of shape NCHW\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The mean saved from the forward pass as a 1-dimensional tensor of size C.\",\n        \"name\": \"mean\"\n      },\n      {\n        \"description\": \"The saved inverse standard deviation as a 1-dimensional tensor of size C.\",\n        \"name\": \"inv_std\"\n      },\n      {\n        \"description\": \"Gradient for the output layer of SpatialBN, here used as input because we are on the backward pass\",\n        \"name\": \"output_grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Gradient for the scale vector\",\n        \"name\": \"scale_grad\"\n      },\n      {\n        \"description\": \"Gradient for the bias vector\",\n        \"name\": \"bias_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ChannelShuffle\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ChannelShuffleGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ChannelStats\",\n    \"description\": \"\\nGiven an input tensor in NCHW format, computes the sum of all elements per\\nchannel and the sum of all elements squared per channel. These values can be\\nreduced across multiple batches and used to obtain the mean and variance across\\nthe full set of batches. Using the new mean and variance as input to SpatialBN\\nhas the effect of changing the batch size over which SpatialBN is applied.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input 4-dimensional tensor of shape NCHW\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output 1-dimensional tensor of size C containing the sum of elements of X per channel.\",\n        \"name\": \"sum\"\n      },\n      {\n        \"description\": \"The output 1-dimensional tensor of size C containing the sum of elements squared per channel.\",\n        \"name\": \"sumsq\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CheckAtomicBool\",\n    \"description\": \"Copy the value of an atomic<bool> to a bool\",\n    \"inputs\": [\n      {\n        \"description\": \"Blob containing a unique_ptr<atomic<bool>>\",\n        \"name\": \"atomic_bool\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Copy of the value for the atomic<bool>\",\n        \"name\": \"value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CheckCounterDone\",\n    \"description\": \"\\nIf the internal count value <= 0, outputs true, otherwise outputs false.\\n\\n  Github Links:\\n  - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/counter_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\ncreatecounter_op = core.CreateOperator(\\n    \\\"CreateCounter\\\",\\n    [],\\n    [\\\"counter\\\"],\\n    init_count=5\\n)\\n\\nretrievecount_op = core.CreateOperator(\\n    \\\"RetrieveCount\\\",\\n    [\\\"counter\\\"],\\n    [\\\"count\\\"]\\n)\\n\\ncheckcounterdone_op = core.CreateOperator(\\n    \\\"CheckCounterDone\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"]\\n)\\n\\ncountup_op = core.CreateOperator(\\n    \\\"CountUp\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n)\\n\\ncountdown_op = core.CreateOperator(\\n    \\\"CountDown\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"],\\n)\\n\\nresetcounter_op = core.CreateOperator(\\n    \\\"ResetCounter\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n    init_count=3\\n)\\n\\n\\n// Create counter\\nworkspace.RunOperatorOnce(createcounter_op)\\nprint(\\\"'counter' pointer:\\\", workspace.FetchBlob(\\\"counter\\\"))\\n\\n\\n// Retrieve initial counter value\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"Initial 'count':\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Check if counter is done\\nworkspace.RunOperatorOnce(checkcounterdone_op)\\nprint(\\\"Initial 'done' value:\\\", workspace.FetchBlob(\\\"done\\\"))\\n\\n\\n// Test CountUp operator\\nprint(\\\"\\\\nTesting CountUp operator...\\\")\\nfor i in range(5):\\n    workspace.RunOperatorOnce(countup_op)\\n    print(\\\"'previous_count' after CountUp:\\\", workspace.FetchBlob(\\\"previous_count\\\"))\\n\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"'count' value after CountUp test:\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Test CountDown operator\\nprint(\\\"\\\\nTesting CountDown operator...\\\")\\nfor i in range(11):\\n    workspace.RunOperatorOnce(countdown_op)\\n    workspace.RunOperatorOnce(retrievecount_op)\\n    print(\\\"'count' value after CountDown: {}\\\\t'done' value: {}\\\".format(workspace.FetchBlob(\\\"count\\\"), workspace.FetchBlob(\\\"done\\\")))\\n```\\n\\n**Result**\\n\\n```\\n'counter' pointer: counter, a C++ native class of type std::__1::unique_ptr<caffe2::Counter<long long>, std::__1::default_delete<caffe2::Counter<long long> > >.\\nInitial 'count': 5\\nInitial 'done' value: False\\n\\nTesting CountUp operator...\\n'previous_count' after CountUp: 5\\n'previous_count' after CountUp: 6\\n'previous_count' after CountUp: 7\\n'previous_count' after CountUp: 8\\n'previous_count' after CountUp: 9\\n'count' value after CountUp test: 10\\n\\nTesting CountDown operator...\\n'count' value after CountDown: 9        'done' value: False\\n'count' value after CountDown: 8        'done' value: False\\n'count' value after CountDown: 7        'done' value: False\\n'count' value after CountDown: 6        'done' value: False\\n'count' value after CountDown: 5        'done' value: False\\n'count' value after CountDown: 4        'done' value: False\\n'count' value after CountDown: 3        'done' value: False\\n'count' value after CountDown: 2        'done' value: False\\n'count' value after CountDown: 1        'done' value: False\\n'count' value after CountDown: 0        'done' value: False\\n'count' value after CountDown: -1        'done' value: True\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<ptr>`)* A blob pointing to an instance of a counter.\",\n        \"name\": \"counter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: bool)* True if the internal count is zero or negative, otherwise False.\",\n        \"name\": \"done\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CheckDatasetConsistency\",\n    \"description\": \"\\nChecks that the given data fields represents a consistent dataset under\\nthe schema specified by the `fields` argument. Operator fails if the fields\\nare not consistent. If data is consistent, each field's data can be safely\\nappended to an existing dataset, keeping it consistent.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of strings representing the string names in the formatspecified in the doc for CreateTreeCursor.\",\n        \"name\": \"fields\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Data for field 0.\",\n        \"name\": \"field_0\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Checkpoint\",\n    \"description\": \"\\nThe Checkpoint operator is similar to the Save operator, but allows one to save\\nto db every few iterations, with a db name that is appended with the iteration\\ncount. It takes [1, infinity) number of inputs and has no output. The first\\ninput has to be a TensorCPU of type int and has size 1 (i.e. the iteration\\ncounter). This is determined whether we need to do checkpointing.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) if set, use the db path directly and do not prepend the current root folder of the workspace.\",\n        \"name\": \"absolute_path\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(string) a template string that one can combine with the iteration to create the final db name. For example, \\\"/home/lonestarr/checkpoint_%08d.db\\\"\",\n        \"name\": \"db\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(string) the type of the db.\",\n        \"name\": \"db_type\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int, default 1) the checkpointing is carried out when (iter mod every) is zero.\",\n        \"name\": \"every\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Clip\",\n    \"description\": \"\\nThis operator limits the given input within an interval. The interval is\\nspecified by the `min` and `max` arguments. They default to\\n*numeric_limits::lowest()* and *numeric_limits::max()* respectively. The\\nclipping operation can be done in an in-place fashion by using the same output\\nblob as the input blob.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/clip_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Clip\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    min=20.0,\\n    max=60.0\\n\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(100, size=(5,5))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\nX: [[45. 16. 59. 99. 48.]\\n [12. 44. 46. 82. 28.]\\n [ 1. 91. 18.  9. 71.]\\n [24. 37. 61. 12. 81.]\\n [36. 38. 30. 84. 40.]]\\nY: [[45. 20. 59. 60. 48.]\\n [20. 44. 46. 60. 28.]\\n [20. 60. 20. 20. 60.]\\n [24. 37. 60. 20. 60.]\\n [36. 38. 30. 60. 40.]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Minimum value, under which element is replaced by min (default=*numeric_limits::lowest()*).\",\n        \"name\": \"min\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"description\": \"Maximum value, under which element is replaced by max (default=*numeric_limits::max()*).\",\n        \"name\": \"max\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(Tensor`<float>`)* Input tensor within range [*numeric_limits::lowest()*, *numeric_limits::max()*].\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(Tensor`<float>`)* Output tensor clipped within range [`min`, `max`].\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ClipGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ClipTensorByScaling\",\n    \"description\": \"\\n    Clips the input tensor by scaling based on the input value and the threshold.\\n    The value is usually the (pre-computed) norm of the tensor. If the value is\\n    larger than the threshold, scaling would be performed in this way:\\n\\n          tensor *= (threshold / value).\\n\\n    An optional input called additional_threshold can be provided which\\n    will scale the original threshold before it is used. That is,\\n    the final threshold will become threshold * additional_threshold.\\n    This op could be used for gradient clipping.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Threshold to determine whether to scale down the tensor\",\n        \"name\": \"threshold\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of floats to be clipped.\",\n        \"name\": \"input_tensor\"\n      },\n      {\n        \"description\": \"Value to be compared against the threshold\",\n        \"name\": \"val\"\n      },\n      {\n        \"description\": \"An optional additional threshold to scale the original threshold\",\n        \"name\": \"additional_threshold\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of floats, which is the same size as the input tensor, representing the clipped tensor.\",\n        \"name\": \"clipped\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CloneCommonWorld\",\n    \"description\": \"\\nClones existing common world.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Existing common world to clone.\",\n        \"name\": \"existing_comm_world\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"A common world for collective operations.\",\n        \"name\": \"comm_world\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CloseBlobsQueue\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CloseRebatchingQueue\",\n    \"description\": \"\\nCloses the Queue.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"object representing the queue\",\n        \"name\": \"queue\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Col2Im\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CollectAndDistributeFpnRpnProposals\",\n    \"description\": \"\\nMerge RPN proposals generated at multiple FPN levels and then\\ndistribute those proposals to their appropriate FPN levels for Faster RCNN.\\nAn anchor at one FPN level may predict an RoI that will map to another level,\\nhence the need to redistribute the proposals.\\n\\nOnly inference is supported. To train, please use the original Python\\noperator in Detectron.\\n\\nInputs and outputs are examples only; if min/max levels change,\\nthe number of inputs and outputs, as well as their level numbering,\\nwill change.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) ROI_CANONICAL_SCALE\",\n        \"name\": \"roi_canonical_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) ROI_CANONICAL_LEVEL\",\n        \"name\": \"roi_canonical_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) ROI_MAX_LEVEL\",\n        \"name\": \"roi_max_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) ROI_MIN_LEVEL\",\n        \"name\": \"roi_min_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_MAX_LEVEL\",\n        \"name\": \"rpn_max_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_MIN_LEVEL\",\n        \"name\": \"rpn_min_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_POST_NMS_TOP_N\",\n        \"name\": \"rpn_post_nms_topN\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"RPN proposals for FPN level 2, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn2\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 3, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn3\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 4, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn4\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 5, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn5\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 6, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn6\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 2. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn2\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 3. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn3\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 4. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn4\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 5. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn5\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 6. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn6\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Top proposals limited to rpn_post_nms_topN total, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 2, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn2\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 3, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn3\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 4, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn4\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 5, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn5\"\n      },\n      {\n        \"description\": \"Permutation on the concatenation of all rois_fpni, i=min...max, such that when applied the RPN RoIs are restored to their original order in the input blobs.\",\n        \"name\": \"rois_idx_restore\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CollectRpnProposals\",\n    \"description\": \"\\n...\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) RPN_MAX_LEVEL\",\n        \"name\": \"rpn_max_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_MIN_LEVEL\",\n        \"name\": \"rpn_min_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_POST_NMS_TOP_N\",\n        \"name\": \"rpn_post_nms_topN\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"RPN proposals for FPN level 2, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn2\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 3, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn3\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 4, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn4\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 5, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn5\"\n      },\n      {\n        \"description\": \"RPN proposals for FPN level 6, format (image_index, x1, y1, x2, y2). See rpn_rois documentation from GenerateProposals.\",\n        \"name\": \"rpn_rois_fpn6\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 2. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn2\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 3. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn3\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 4. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn4\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 5. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn5\"\n      },\n      {\n        \"description\": \"RPN objectness probabilities for FPN level 6. See rpn_roi_probs documentation from GenerateProposals.\",\n        \"name\": \"rpn_roi_probs_fpn6\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Top proposals limited to rpn_post_nms_topN total, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CollectTensor\",\n    \"description\": \"\\nCollect tensor into tensor vector by reservoir sampling,\\nargument num_to_collect indicates the max number of tensors that will be\\ncollected. The first half of the inputs are tensor vectors, which are also the\\noutputs. The second half of the inputs are the tensors to be collected into each\\nvector (in the same order). The input tensors are collected in all-or-none\\nmanner. If they are collected, they will be placed at the same index in the\\noutput vectors.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The max number of tensors to collect\",\n        \"name\": \"num_to_collect\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ColwiseMax\",\n    \"description\": \"\\nCompute column-wise max reduction of the input tensor. This op takes one input, $X$, of shape $BxMxN$, where $B$ is the batch size, $M$ is number of rows, and $N$ is number of columns. The output of this op, $Y$, is a matrix of shape $BxN$, with one row for each element of the batch, and the same number of columns as the input tensor.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduction_ops.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduction_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ColwiseMax\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X, simulating a batch of 2, 4x4 matricies\\nX = np.random.randint(0,high=20,size=(2,4,4))\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Feed X into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[[17 15  2  6]\\n  [ 8 12  6  0]\\n  [ 6  9  7  3]\\n  [ 4 13 16 13]]\\n\\n [[ 0  3  4 12]\\n  [18  1 17 12]\\n  [ 7 17 13 14]\\n  [12 17  2  1]]]\\nY:\\n [[17. 15. 16. 13.]\\n [18. 17. 17. 14.]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"A tensor of dimensions $B x M x N$ to compute columnwise-max. Here, $B$ is batch size, and $M$ and $N$ are the number of rows and columns of each element of the batch, respectively.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor of shape $B x N$, where each row represents the column-wise maximums for that element of the input batch.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ColwiseMaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ComputeOffset\",\n    \"description\": \"\\nCompute the offsets matrix given cursor and data blobs. Need to be ran at\\nbeginning or after reseting cursor\\n\\nInput(0) is a blob pointing to a TreeCursor, and\\n[Input(1),... Input(num_fields)] a list of tensors containing the data for\\neach field of the dataset.\\n\\nComputeOffset is thread safe.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the cursor.\",\n        \"name\": \"cursor\"\n      },\n      {\n        \"description\": \"First dataset field\",\n        \"name\": \"dataset_field_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing offset info for this chunk.\",\n        \"name\": \"field_0\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\",\n    \"description\": \"\\nConcatenate a list of tensors into a single tensor. Similar functionality to\\nNumpy's [concatenate](https://docs.scipy.org/doc/numpy/reference/generated/numpy.concatenate.html)\\nfunction. The `axis` argument specifies what axis along which the arrays will be concatenated.\\nWhen set to non-zero (default=0), the `add_axis` argument adds the axis specified in `axis` to\\nall input tensors.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/concat_split_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/concat_split_op.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Concat\\\",\\n    [\\\"X1\\\",  \\\"X2\\\"],\\n    [\\\"Y\\\", \\\"split_info\\\"],\\n    axis=0\\n)\\n\\nworkspace.FeedBlob(\\\"X1\\\", np.array([[1,2],[3,4]]))\\nworkspace.FeedBlob(\\\"X2\\\", np.array([[5,6]]))\\nprint(\\\"X1:\\\", workspace.FetchBlob(\\\"X1\\\"))\\nprint(\\\"X2:\\\", workspace.FetchBlob(\\\"X2\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"split_info:\\\", workspace.FetchBlob(\\\"split_info\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX1: [[1 2]\\n [3 4]]\\nX2: [[5 6]]\\nY: [[1 2]\\n [3 4]\\n [5 6]]\\nsplit_info: [2 1]\\n\\n```\\n\\n</details>\\n\\n<details>\\n\\n<summary> <b>Example 2</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Concat\\\",\\n    [\\\"X1\\\",  \\\"X2\\\"],\\n    [\\\"Y\\\", \\\"split_info\\\"],\\n    add_axis=1,\\n    axis=3\\n)\\n\\nworkspace.FeedBlob(\\\"X1\\\", np.random.randint(10, size=(1, 1, 5, 5))) // NCHW\\nworkspace.FeedBlob(\\\"X2\\\", np.random.randint(10, size=(1, 1, 5, 5))) // NCHW\\nprint(\\\"X1:\\\", workspace.FetchBlob(\\\"X1\\\"))\\nprint(\\\"X2:\\\", workspace.FetchBlob(\\\"X2\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"split_info:\\\", workspace.FetchBlob(\\\"split_info\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX1: [[[[1 8 3 9 0]\\n   [6 4 6 5 6]\\n   [3 9 1 9 9]\\n   [5 1 0 7 7]\\n   [9 4 0 0 9]]]]\\nX2: [[[[7 0 2 6 1]\\n   [3 9 4 0 3]\\n   [5 3 8 9 4]\\n   [3 4 2 1 0]\\n   [0 8 8 8 1]]]]\\nY: [[[[[1 8 3 9 0]\\n    [7 0 2 6 1]]\\n\\n   [[6 4 6 5 6]\\n    [3 9 4 0 3]]\\n\\n   [[3 9 1 9 9]\\n    [5 3 8 9 4]]\\n\\n   [[5 1 0 7 7]\\n    [3 4 2 1 0]]\\n\\n   [[9 4 0 0 9]\\n    [0 8 8 8 1]]]]]\\nsplit_info: [1 1]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"Order of blob dimensions. Concats on the C dimension.\",\n        \"name\": \"order\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"description\": \"Pass non-zero integer to add the axis specified in `axis` to all input tensors.\",\n        \"name\": \"add_axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"option\": \"variadic\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* List of input tensors.\",\n        \"name\": \"X1, X2, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Concatenated tensor.\",\n        \"name\": \"concat_result\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* The dimensions of the inputs.\",\n        \"name\": \"split_info\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConcatBatchMatMulBatchGatherOp\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConcatTensorVector\",\n    \"description\": \"\\nConcat Tensors in the std::unique_ptr<std::vector<Tensor> >\\nalong the first dimension.\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"std::unique_ptr<std::vector<Tensor> >\",\n        \"name\": \"vector of Tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"tensor after concatenating\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conditional\",\n    \"description\": \"\\nGiven a 1-D tensor of boolean values, apply conditional operator along the first\\ndimension of DataT and DataF and return DataO. Note, DataT and DataF must\\nhave the exact same shape and type.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Boolean tensor to select DataT or DataF\",\n        \"name\": \"Condition\"\n      },\n      {\n        \"description\": \"Data to use when True\",\n        \"name\": \"DataT\"\n      },\n      {\n        \"description\": \"Data to use when False\",\n        \"name\": \"DataF\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data after applying ConditionalOp\",\n        \"name\": \"DataO\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConditionalSetAtomicBool\",\n    \"description\": \"\\nSet an atomic<bool> to true if the given condition bool variable is true\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"Blob containing a unique_ptr<atomic<bool>>\",\n        \"name\": \"atomic_bool\"\n      },\n      {\n        \"description\": \"Blob containing a bool\",\n        \"name\": \"condition\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConstantFill\",\n    \"description\": \"\\nThis operator fills the elements of the output tensor with a constant value\\nspecified by the `value` argument.\\n\\n- The data type is specified by the `dtype` argument\\n\\n- Currently, the data types supported are *float*, *int32*, *int64*, and *bool*\\n\\n- If the `dtype` argument is not provided, the data type of `value` is used\\n\\n- The output tensor shape is either specified by the `shape` argument or will\\nmatch the shape of the input tensor if one is provided (if an input tensor is\\nprovided, a shape argument should not be set)\\n\\n- Optional additional dimensions can be appended at the end as specified by\\n`extra_shape` argument\\n\\n- If `input_as_shape` is set to True, the input should be a 1D tensor\\ncontaining the desired output shape (the dimensions specified in `extra_shape`\\nwill also be appended)\\n\\n- If a second input V is passed, fill the output with the first element of V\\n\\nWhen specifying `dtype` argument, use the integer keys from the *DataType* enum\\nin TensorProto:\\n\\n```\\nmessage TensorProto {\\n  ...\\n  enum DataType {\\n    UNDEFINED = 0;\\n    FLOAT = 1;  // float\\n    INT32 = 2;  // int\\n    BYTE = 3;  // BYTE, when deserialized, is going to be restored as uint8.\\n    STRING = 4;  // string\\n    BOOL = 5;  // bool\\n    UINT8 = 6;  // uint8_t\\n    INT8 = 7;  // int8_t\\n    UINT16 = 8;  // uint16_t\\n    INT16 = 9;  // int16_t\\n    INT64 = 10;  // int64_t\\n    FLOAT16 = 12;  // at::Half\\n    DOUBLE = 13;  // double\\n  }\\n```\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/filler_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ConstantFill\\\",\\n    [],\\n    [\\\"Y\\\"],\\n    shape=(1,5,5)\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nY: [[[0. 0. 0. 0. 0.]\\n  [0. 0. 0. 0. 0.]\\n  [0. 0. 0. 0. 0.]\\n  [0. 0. 0. 0. 0.]\\n  [0. 0. 0. 0. 0.]]]\\n```\\n</details>\\n\\n<details>\\n<summary> <b>Example 2</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ConstantFill\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    value=4.0,\\n    dtype=1,\\n    extra_shape=(1,2)\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(100, size=(3,3))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[86. 30. 84.]\\n [34. 51.  9.]\\n [29. 86. 59.]]\\nY: [[[[4. 4.]]\\n\\n  [[4. 4.]]\\n\\n  [[4. 4.]]]\\n\\n\\n [[[4. 4.]]\\n\\n  [[4. 4.]]\\n\\n  [[4. 4.]]]\\n\\n\\n [[[4. 4.]]\\n\\n  [[4. 4.]]\\n\\n  [[4. 4.]]]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"value to populate output tensor with.\",\n        \"name\": \"value\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The data type for the elements of the output tensor. Strictly must be one of the types from *DataType* enum in TensorProto.\",\n        \"name\": \"dtype\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"Shape of the output tensor. Cannot pass an input blob and this arg at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Additional dimensions appended at the end of the shape indicated by the input blob. Cannot set thisargument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* [OPTIONAL] Input tensor to provide shape information.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Output tensor of constant values.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv\",\n    \"category\": \"Layer\",\n    \"description\": \"\\nThe convolution operator consumes an input vector, a filter blob\\nand a bias blob and computes the output. \\nThe Conv2D operator computes a 2D convolution operation over an input blob $(X)$, with a filter blob $(filter)$ and a bias blob $(bias)$, and outputs a single output blob $(Y)$. Although there are several options for order, the convention is that the input $(X)$ is a blob of shape $(N,C_{in},H_{in},W_{in})$ and the output $(Y)$ is a blob of shape $(N,C_{out},H_{out},W_{out})$. Here, $N$ is the batch size, $C$ is the number of channels, $H$ is the spatial height, and $W$ is the spatial width. For example, if your input data was a batch of five, 100x120pixel RGB images, $X$ would have shape $(5,3,120,100)$.\\n\\nThe $filter$ input blob may contain multiple filters and has shape $(M, C_{in}, K_H, K_W)$. Here, $M$ is the number of individual filters contained in the blob, $C_{in}$ is the number of channels of each filter (by convention in 2D convolution it is the same as the number of channels in the input), $K_H$ is the spatial height of the kernel, and $K_W$ is the spatial width of the kernel. The $bias$ blob is a vector of length $M$, where there is one bias for each filter in the $filter$ blob.\\n\\nGiven the shape of the input blob and the filter blob, we can calculate the shape of the output blob as follows. The number of items in the batch $N$ will stay the same. The number of channels in the output will equal the number of kernels in the filter blob, so $C_{out} = M.$ With stride and pad defined below, the spatial height and width of the output ($H_{out}$ and $W_{out}$) are calculated as\\n\\n$$H_{out} = \\\\left \\\\lfloor{\\\\frac{H_{in} - K_H + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\n$$W_{out} = \\\\left \\\\lfloor{\\\\frac{W_{in} - K_W + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Conv\\\",\\n    [\\\"X\\\", \\\"filter\\\", \\\"bias\\\"],\\n    [\\\"Y\\\"],\\n    kernel=5,\\n    pad=1,\\n    stride=2\\n)\\n\\n// Create X: (N,C,H,W)\\ndata = np.random.randn(1,1,8,8).astype(np.float32)\\nprint(\\\"Data shape: \\\",data.shape)\\n\\n// Create W: (M,C,Kh,Kw)\\nfilters = np.random.randn(3,1,5,5).astype(np.float32)\\nprint(\\\"Filter shape: \\\",filters.shape)\\n\\n// Create b: M\\nbias = np.array([1.,1.,1.]).astype(np.float32)\\nprint(\\\"Bias shape: \\\",bias.shape)\\n\\n// Put the inputs into the workspace\\nworkspace.FeedBlob(\\\"X\\\", data)\\nworkspace.FeedBlob(\\\"filter\\\", filters)\\nworkspace.FeedBlob(\\\"bias\\\", bias)\\n\\n// Run the operator\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nData shape:  (1, 1, 8, 8)\\nFilter shape:  (3, 1, 5, 5)\\nBias shape:  (3,)\\nY:\\n [[[[  0.6406407    0.8620521    0.56461596]\\n   [ -1.5042953   -0.79549205 -10.683343  ]\\n   [ -0.5240259    3.4538248   -3.9564204 ]]\\n\\n  [[  0.6876496    4.8328524   -1.9525816 ]\\n   [  1.2995434   -2.3895378    7.2670045 ]\\n   [  3.9929862    1.8126237    5.4699917 ]]\\n\\n  [[  3.55949      4.7934155    0.76086235]\\n   [  3.9588015   -1.3251319    4.413117  ]\\n   [ -1.5296054   -1.4924102   -3.2552304 ]]]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"pad\"\n      },\n      {\n        \"default\": 1,\n        \"name\": \"stride\"\n      },\n      {\n        \"name\": \"exhaustive_search\",\n        \"type\": \"boolean\",\n        \"visible\": false\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob, of shape $(N, C_{in}, H_{in}, W_{in})$, to be convolved with the kernels in the filter blob.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob, of shape $(M, C_{in}, K_H, K_W)$, containing the filters to be convolved with the data.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The bias blob, of length $M$, containing the biases for the convolution, one bias per filter.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob, of shape $(N, C_{out}, H_{out}, W_{out})$, that contains the result of the convolution.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv1D\",\n    \"description\": \"\\nThe convolution operator consumes an input vector, a 1D filter blob\\nand a bias blob and computes the output. \\nThe Conv2D operator computes a 2D convolution operation over an input blob $(X)$, with a filter blob $(filter)$ and a bias blob $(bias)$, and outputs a single output blob $(Y)$. Although there are several options for order, the convention is that the input $(X)$ is a blob of shape $(N,C_{in},H_{in},W_{in})$ and the output $(Y)$ is a blob of shape $(N,C_{out},H_{out},W_{out})$. Here, $N$ is the batch size, $C$ is the number of channels, $H$ is the spatial height, and $W$ is the spatial width. For example, if your input data was a batch of five, 100x120pixel RGB images, $X$ would have shape $(5,3,120,100)$.\\n\\nThe $filter$ input blob may contain multiple filters and has shape $(M, C_{in}, K_H, K_W)$. Here, $M$ is the number of individual filters contained in the blob, $C_{in}$ is the number of channels of each filter (by convention in 2D convolution it is the same as the number of channels in the input), $K_H$ is the spatial height of the kernel, and $K_W$ is the spatial width of the kernel. The $bias$ blob is a vector of length $M$, where there is one bias for each filter in the $filter$ blob.\\n\\nGiven the shape of the input blob and the filter blob, we can calculate the shape of the output blob as follows. The number of items in the batch $N$ will stay the same. The number of channels in the output will equal the number of kernels in the filter blob, so $C_{out} = M.$ With stride and pad defined below, the spatial height and width of the output ($H_{out}$ and $W_{out}$) are calculated as\\n\\n$$H_{out} = \\\\left \\\\lfloor{\\\\frac{H_{in} - K_H + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\n$$W_{out} = \\\\left \\\\lfloor{\\\\frac{W_{in} - K_W + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Conv\\\",\\n    [\\\"X\\\", \\\"filter\\\", \\\"bias\\\"],\\n    [\\\"Y\\\"],\\n    kernel=5,\\n    pad=1,\\n    stride=2\\n)\\n\\n// Create X: (N,C,H,W)\\ndata = np.random.randn(1,1,8,8).astype(np.float32)\\nprint(\\\"Data shape: \\\",data.shape)\\n\\n// Create W: (M,C,Kh,Kw)\\nfilters = np.random.randn(3,1,5,5).astype(np.float32)\\nprint(\\\"Filter shape: \\\",filters.shape)\\n\\n// Create b: M\\nbias = np.array([1.,1.,1.]).astype(np.float32)\\nprint(\\\"Bias shape: \\\",bias.shape)\\n\\n// Put the inputs into the workspace\\nworkspace.FeedBlob(\\\"X\\\", data)\\nworkspace.FeedBlob(\\\"filter\\\", filters)\\nworkspace.FeedBlob(\\\"bias\\\", bias)\\n\\n// Run the operator\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nData shape:  (1, 1, 8, 8)\\nFilter shape:  (3, 1, 5, 5)\\nBias shape:  (3,)\\nY:\\n [[[[  0.6406407    0.8620521    0.56461596]\\n   [ -1.5042953   -0.79549205 -10.683343  ]\\n   [ -0.5240259    3.4538248   -3.9564204 ]]\\n\\n  [[  0.6876496    4.8328524   -1.9525816 ]\\n   [  1.2995434   -2.3895378    7.2670045 ]\\n   [  3.9929862    1.8126237    5.4699917 ]]\\n\\n  [[  3.55949      4.7934155    0.76086235]\\n   [  3.9588015   -1.3251319    4.413117  ]\\n   [ -1.5296054   -1.4924102   -3.2552304 ]]]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob, of shape $(N, C_{in}, H_{in}, W_{in})$, to be convolved with the kernels in the filter blob.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob, of shape $(M, C_{in}, K_H, K_W)$, containing the filters to be convolved with the data.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The bias blob, of length $M$, containing the biases for the convolution, one bias per filter.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob, of shape $(N, C_{out}, H_{out}, W_{out})$, that contains the result of the convolution.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv1DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv2D\",\n    \"description\": \"\\nThe convolution operator consumes an input vector, a 2D filter blob\\nand a bias blob and computes the output. \\nThe Conv2D operator computes a 2D convolution operation over an input blob $(X)$, with a filter blob $(filter)$ and a bias blob $(bias)$, and outputs a single output blob $(Y)$. Although there are several options for order, the convention is that the input $(X)$ is a blob of shape $(N,C_{in},H_{in},W_{in})$ and the output $(Y)$ is a blob of shape $(N,C_{out},H_{out},W_{out})$. Here, $N$ is the batch size, $C$ is the number of channels, $H$ is the spatial height, and $W$ is the spatial width. For example, if your input data was a batch of five, 100x120pixel RGB images, $X$ would have shape $(5,3,120,100)$.\\n\\nThe $filter$ input blob may contain multiple filters and has shape $(M, C_{in}, K_H, K_W)$. Here, $M$ is the number of individual filters contained in the blob, $C_{in}$ is the number of channels of each filter (by convention in 2D convolution it is the same as the number of channels in the input), $K_H$ is the spatial height of the kernel, and $K_W$ is the spatial width of the kernel. The $bias$ blob is a vector of length $M$, where there is one bias for each filter in the $filter$ blob.\\n\\nGiven the shape of the input blob and the filter blob, we can calculate the shape of the output blob as follows. The number of items in the batch $N$ will stay the same. The number of channels in the output will equal the number of kernels in the filter blob, so $C_{out} = M.$ With stride and pad defined below, the spatial height and width of the output ($H_{out}$ and $W_{out}$) are calculated as\\n\\n$$H_{out} = \\\\left \\\\lfloor{\\\\frac{H_{in} - K_H + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\n$$W_{out} = \\\\left \\\\lfloor{\\\\frac{W_{in} - K_W + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Conv\\\",\\n    [\\\"X\\\", \\\"filter\\\", \\\"bias\\\"],\\n    [\\\"Y\\\"],\\n    kernel=5,\\n    pad=1,\\n    stride=2\\n)\\n\\n// Create X: (N,C,H,W)\\ndata = np.random.randn(1,1,8,8).astype(np.float32)\\nprint(\\\"Data shape: \\\",data.shape)\\n\\n// Create W: (M,C,Kh,Kw)\\nfilters = np.random.randn(3,1,5,5).astype(np.float32)\\nprint(\\\"Filter shape: \\\",filters.shape)\\n\\n// Create b: M\\nbias = np.array([1.,1.,1.]).astype(np.float32)\\nprint(\\\"Bias shape: \\\",bias.shape)\\n\\n// Put the inputs into the workspace\\nworkspace.FeedBlob(\\\"X\\\", data)\\nworkspace.FeedBlob(\\\"filter\\\", filters)\\nworkspace.FeedBlob(\\\"bias\\\", bias)\\n\\n// Run the operator\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nData shape:  (1, 1, 8, 8)\\nFilter shape:  (3, 1, 5, 5)\\nBias shape:  (3,)\\nY:\\n [[[[  0.6406407    0.8620521    0.56461596]\\n   [ -1.5042953   -0.79549205 -10.683343  ]\\n   [ -0.5240259    3.4538248   -3.9564204 ]]\\n\\n  [[  0.6876496    4.8328524   -1.9525816 ]\\n   [  1.2995434   -2.3895378    7.2670045 ]\\n   [  3.9929862    1.8126237    5.4699917 ]]\\n\\n  [[  3.55949      4.7934155    0.76086235]\\n   [  3.9588015   -1.3251319    4.413117  ]\\n   [ -1.5296054   -1.4924102   -3.2552304 ]]]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob, of shape $(N, C_{in}, H_{in}, W_{in})$, to be convolved with the kernels in the filter blob.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob, of shape $(M, C_{in}, K_H, K_W)$, containing the filters to be convolved with the data.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The bias blob, of length $M$, containing the biases for the convolution, one bias per filter.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob, of shape $(N, C_{out}, H_{out}, W_{out})$, that contains the result of the convolution.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv2DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv3D\",\n    \"description\": \"\\nThe convolution operator consumes an input vector, a 3D filter blob\\nand a bias blob and computes the output. \\nThe Conv2D operator computes a 2D convolution operation over an input blob $(X)$, with a filter blob $(filter)$ and a bias blob $(bias)$, and outputs a single output blob $(Y)$. Although there are several options for order, the convention is that the input $(X)$ is a blob of shape $(N,C_{in},H_{in},W_{in})$ and the output $(Y)$ is a blob of shape $(N,C_{out},H_{out},W_{out})$. Here, $N$ is the batch size, $C$ is the number of channels, $H$ is the spatial height, and $W$ is the spatial width. For example, if your input data was a batch of five, 100x120pixel RGB images, $X$ would have shape $(5,3,120,100)$.\\n\\nThe $filter$ input blob may contain multiple filters and has shape $(M, C_{in}, K_H, K_W)$. Here, $M$ is the number of individual filters contained in the blob, $C_{in}$ is the number of channels of each filter (by convention in 2D convolution it is the same as the number of channels in the input), $K_H$ is the spatial height of the kernel, and $K_W$ is the spatial width of the kernel. The $bias$ blob is a vector of length $M$, where there is one bias for each filter in the $filter$ blob.\\n\\nGiven the shape of the input blob and the filter blob, we can calculate the shape of the output blob as follows. The number of items in the batch $N$ will stay the same. The number of channels in the output will equal the number of kernels in the filter blob, so $C_{out} = M.$ With stride and pad defined below, the spatial height and width of the output ($H_{out}$ and $W_{out}$) are calculated as\\n\\n$$H_{out} = \\\\left \\\\lfloor{\\\\frac{H_{in} - K_H + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\n$$W_{out} = \\\\left \\\\lfloor{\\\\frac{W_{in} - K_W + 2*pad}{stride}+1}\\\\right \\\\rfloor$$\\n\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Conv\\\",\\n    [\\\"X\\\", \\\"filter\\\", \\\"bias\\\"],\\n    [\\\"Y\\\"],\\n    kernel=5,\\n    pad=1,\\n    stride=2\\n)\\n\\n// Create X: (N,C,H,W)\\ndata = np.random.randn(1,1,8,8).astype(np.float32)\\nprint(\\\"Data shape: \\\",data.shape)\\n\\n// Create W: (M,C,Kh,Kw)\\nfilters = np.random.randn(3,1,5,5).astype(np.float32)\\nprint(\\\"Filter shape: \\\",filters.shape)\\n\\n// Create b: M\\nbias = np.array([1.,1.,1.]).astype(np.float32)\\nprint(\\\"Bias shape: \\\",bias.shape)\\n\\n// Put the inputs into the workspace\\nworkspace.FeedBlob(\\\"X\\\", data)\\nworkspace.FeedBlob(\\\"filter\\\", filters)\\nworkspace.FeedBlob(\\\"bias\\\", bias)\\n\\n// Run the operator\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nData shape:  (1, 1, 8, 8)\\nFilter shape:  (3, 1, 5, 5)\\nBias shape:  (3,)\\nY:\\n [[[[  0.6406407    0.8620521    0.56461596]\\n   [ -1.5042953   -0.79549205 -10.683343  ]\\n   [ -0.5240259    3.4538248   -3.9564204 ]]\\n\\n  [[  0.6876496    4.8328524   -1.9525816 ]\\n   [  1.2995434   -2.3895378    7.2670045 ]\\n   [  3.9929862    1.8126237    5.4699917 ]]\\n\\n  [[  3.55949      4.7934155    0.76086235]\\n   [  3.9588015   -1.3251319    4.413117  ]\\n   [ -1.5296054   -1.4924102   -3.2552304 ]]]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob, of shape $(N, C_{in}, H_{in}, W_{in})$, to be convolved with the kernels in the filter blob.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob, of shape $(M, C_{in}, K_H, K_W)$, containing the filters to be convolved with the data.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The bias blob, of length $M$, containing the biases for the convolution, one bias per filter.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob, of shape $(N, C_{out}, H_{out}, W_{out})$, that contains the result of the convolution.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Conv3DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConvGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConvRelu\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConvTranspose\",\n    \"category\": \"Layer\",\n    \"description\": \"\\nThe ConvTranspose op takes an input data tensor $X$, an input weight tensor $filter$, and optionally an input bias tensor $bias$. It then computes the transposed convolution, sometimes referred to as deconvolution, and produces a single output tensor $Y$. The hyperparameters of the op such as kernel size, stride, and padding are specified as args. At each stride, the filter is deconvolved with a subset of $X$ and the $bias$ is added. This is done throughout the input data until the output computation is complete.\\n\\nThe output shapes are computed as follows. The number of channels in the output feature map is the number of kernels specified in the filter blob. The spatial height and width are computed as:\\n\\n$$H_{out} = (H_{in}-1)*strides[0] - 2*pads[0] + kernels[0]$$\\n\\n\\n$$W_{out} = (W_{in}-1)*strides[1] - 2*pads[1] + kernels[1]$$\\n\\nNote on the implementation layout: conv_transpose_op_impl.h is the templated implementation of the conv_transpose_op.h file, which is why they are separate files. Also, in the implementation this operator inherits from the *ConvTransposeUnpoolOpBase* operator.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/tree/master/caffe2/operators/conv_transpose_op.h\\n- https://github.com/pytorch/pytorch/tree/master/caffe2/operators/conv_transpose_op.cc\\n- https://github.com/pytorch/pytorch/tree/master/caffe2/operators/conv_transpose_unpool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ConvTranspose\\\",\\n    [\\\"X\\\", \\\"filter\\\", \\\"bias\\\"],\\n    [\\\"Y\\\"],\\n    kernels=[2,2],\\n    pads=[4,4,4,4],\\n    strides=[2,2]\\n)\\n\\n// Create X: (N,C,H,W)\\ndata = np.random.randn(2,3,5,5).astype(np.float32)\\nprint(\\\"Data shape: \\\",data.shape)\\n\\n// Create filter: (M,C,Kh,Kw)\\nfilters = np.random.randn(3,1,2,2).astype(np.float32)\\nprint(\\\"Filter shape: \\\",filters.shape)\\n\\n// Create b: M\\nbias = np.array([1.]).astype(np.float32)\\nprint(\\\"Bias shape: \\\",bias.shape)\\n\\n// Put the inputs into the workspace\\nworkspace.FeedBlob(\\\"X\\\", data)\\nworkspace.FeedBlob(\\\"filter\\\", filters)\\nworkspace.FeedBlob(\\\"bias\\\", bias)\\n\\n// Run the operator\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nData shape:  (2, 3, 5, 5)\\nFilter shape:  (3, 1, 2, 2)\\nBias shape:  (1,)\\nY:\\n [[[[0.53606427 0.5775447 ]\\n   [0.40148795 1.5188271 ]]]\\n\\n\\n [[[1.9903406  3.2794335 ]\\n   [0.09960175 0.31917763]]]]\\n\\n```\\n\\n</details>\\n\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Should the legacy padding be VALID or SAME. When used, pads should not be used.\",\n        \"name\": \"legacy_pad\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"Desired kernel size. If left at default the kernel size will be inferred from the input $filter$ blob.\",\n        \"name\": \"kernels\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"description\": \"Controls the stride of the kernel as it traverses the input blob.\",\n        \"name\": \"strides\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"description\": \"Controls the amount of padding applied to the input feature map before computation.\",\n        \"name\": \"pads\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"adjs\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"default\": \"NCHW\",\n        \"description\": \"Specifies the order of the input data blob, where $N$ is batch size, $C$ is number of channels, $H$ is spatial height, and $W$ is spatial width. The only other valid option is \\\"NHWC\\\".\",\n        \"name\": \"order\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"\",\n        \"name\": \"shared_buffer\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"\",\n        \"name\": \"no_bias\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob, of shape $(N, C_{in}, H_{in}, W_{in})$, to be operated on.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob, of shape $(M, C_{out}, K_H, K_W)$, containing the filters to be used in the transposed convolution.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The bias blob, of length $C_{out}$, containing the biases for the operation, one bias per output channel. If not passed, biases assumed to be zeros.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob, of shape $(N, C_{out}, H_{out}, W_{out})$, that contains the result of the operation.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ConvTransposeGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Copy\",\n    \"description\": \"\\nCopy input tensor into output, potentially across devices.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/copy_op.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/copy_op.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Copy\\\",\\n    [\\\"input\\\"],\\n    [\\\"output\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.random.rand(3,3))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"input\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output:\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput:\\n[[0.16826761 0.68168217 0.55196001]\\n [0.19735483 0.34837823 0.69015595]\\n [0.09448514 0.57390828 0.37097193]]\\noutput:\\n[[0.16826761 0.68168217 0.55196001]\\n [0.19735483 0.34837823 0.69015595]\\n [0.09448514 0.57390828 0.37097193]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): input tensor to copy\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): copy of input tensor\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CopyFromCPUInput\",\n    \"description\": \"\\nTake a CPU input tensor and copy it to an output in the current\\nContext (GPU or CPU). This may involves cross-device MemCpy.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input CPU tensor.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"either a TensorCUDA or a TensorCPU\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CopyOnDeviceLike\",\n    \"description\": \"Copy input tensor into output to the specific device.\",\n    \"inputs\": [\n      {\n        \"description\": \"The input tensor.\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"Tensor, on which device the copy will be performed.\",\n        \"name\": \"dst\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor that will contain a copy of the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CopyRowsToTensor\",\n    \"description\": \"\\n      This operator takes in a 2d tensor, a list of indices, and a 1d tensor\\n      with the same width of the 2d tensor. It will replace the rows in 2d\\n      tensor specified in indices with the 2d tensor. The operator does an\\n      in-place change to the input tensor.\\n      Example:\\n        INPUT_TENSOR = [[1, 2], [3, 4], [5, 6]]\\n        INDICES = [1]\\n        ROW = [9, 0]\\n        OUTPUT_TENSOR = [[1, 2], [9, 0], [5, 6]]\\n      \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor needs to be modified.\",\n        \"name\": \"input_tensor\"\n      },\n      {\n        \"description\": \"Indices of rows need to be copied\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"1-d tensor that is going to replace the rows\",\n        \"name\": \"row\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"updated tensor\",\n        \"name\": \"output_tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CopyRowsToTensorGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Cos\",\n    \"description\": \"\\nCalculates the cosine of the given input tensor, element-wise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/cos_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Cos\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(5).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX: [0.6816719  0.76771533 0.933932   0.01404487 0.11862425]\\nY: [0.7765203  0.71949923 0.5946774  0.99990135 0.9929724 ]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor calculated as the cosine of the input tensor, element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CosGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Cosh\",\n    \"description\": \"\\nCalculates the hyperbolic cosine of the given input tensor, element-wise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/cosh_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Cosh\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(5).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX: [0.66423494 0.32074615 0.81523746 0.90423071 0.39275789]\\nY: [1.22883528 1.05188156 1.35112322 1.43744212 1.07812598]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The hyperbolic cosine values of the input tensor, computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CoshGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CosineEmbeddingCriterion\",\n    \"description\": \"\\nCosineEmbeddingCriterion takes two inputs: the similarity value and\\nthe label, and computes the elementwise criterion output as\\n\\n  output = 1 - s,               if y == 1\\n           max(0, s - margin),  if y == -1\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The cosine similarity as a 1-dim TensorCPU.\",\n        \"name\": \"S\"\n      },\n      {\n        \"description\": \"The label as a 1-dim TensorCPU with int value of 1 or -1.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output loss with the same dimensionality as S.\",\n        \"name\": \"loss\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CosineEmbeddingCriterionGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CosineSimilarity\",\n    \"description\": \"\\nThis op takes two input float tensors of the same size, $X$ and $Y$, and produces one output float tensor , $Z$, calculated as the cosine similarity between $X$ and $Y$. Recall, the cosine similarity between two tensors $X$ and $Y$ is defined as:\\n\\n$$\\\\mathbf{Z}=CosineSimilarity(\\\\mathbf{X},\\\\mathbf{Y}) = \\\\frac{\\\\mathbf{X}\\\\cdot\\\\mathbf{Y}}{\\\\|\\\\mathbf{X}\\\\|\\\\|\\\\mathbf{Y}\\\\|} = \\\\frac{\\\\sum_n^{i=1}X_iY_i}{\\\\sqrt{\\\\sum_n^{i=1}X_i^2}\\\\sqrt{\\\\sum_n^{i=1}Y_i^2}}$$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/distance_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/distance_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"CosineSimilarity\\\",\\n    [\\\"X\\\", \\\"Y\\\"],\\n    [\\\"Z\\\"]\\n)\\n\\n// Create X\\nX = np.random.randn(3, 3)\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Create Y\\nY = np.random.randn(3, 3)\\nprint(\\\"Y:\\\\n\\\",Y)\\n\\n// Feed X & Y into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", Y.astype(np.float32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Z:\\\\n\\\", workspace.FetchBlob(\\\"Z\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[-0.42635564 -0.23831588 -0.25515547]\\n [ 1.43914719 -1.05613228  1.01717373]\\n [ 0.06883105  0.33386519 -1.46648334]]\\nY:\\n [[-0.90648691 -0.14241514 -1.1070837 ]\\n [ 0.92152729 -0.28115511 -0.17756722]\\n [-0.88394254  1.34654037 -0.80080998]]\\nZ:\\n [-1.7849885e-23  1.7849885e-23 -1.0842022e-07]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D or 2D input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D or 2D input tensor (must have the same shape as X)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CosineSimilarityGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CountDown\",\n    \"description\": \"\\nIf the internal count value > 0, decreases count value by 1 and outputs False,\\notherwise outputs True.\\n\\n  Github Links:\\n  - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/counter_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\ncreatecounter_op = core.CreateOperator(\\n    \\\"CreateCounter\\\",\\n    [],\\n    [\\\"counter\\\"],\\n    init_count=5\\n)\\n\\nretrievecount_op = core.CreateOperator(\\n    \\\"RetrieveCount\\\",\\n    [\\\"counter\\\"],\\n    [\\\"count\\\"]\\n)\\n\\ncheckcounterdone_op = core.CreateOperator(\\n    \\\"CheckCounterDone\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"]\\n)\\n\\ncountup_op = core.CreateOperator(\\n    \\\"CountUp\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n)\\n\\ncountdown_op = core.CreateOperator(\\n    \\\"CountDown\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"],\\n)\\n\\nresetcounter_op = core.CreateOperator(\\n    \\\"ResetCounter\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n    init_count=3\\n)\\n\\n\\n// Create counter\\nworkspace.RunOperatorOnce(createcounter_op)\\nprint(\\\"'counter' pointer:\\\", workspace.FetchBlob(\\\"counter\\\"))\\n\\n\\n// Retrieve initial counter value\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"Initial 'count':\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Check if counter is done\\nworkspace.RunOperatorOnce(checkcounterdone_op)\\nprint(\\\"Initial 'done' value:\\\", workspace.FetchBlob(\\\"done\\\"))\\n\\n\\n// Test CountUp operator\\nprint(\\\"\\\\nTesting CountUp operator...\\\")\\nfor i in range(5):\\n    workspace.RunOperatorOnce(countup_op)\\n    print(\\\"'previous_count' after CountUp:\\\", workspace.FetchBlob(\\\"previous_count\\\"))\\n\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"'count' value after CountUp test:\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Test CountDown operator\\nprint(\\\"\\\\nTesting CountDown operator...\\\")\\nfor i in range(11):\\n    workspace.RunOperatorOnce(countdown_op)\\n    workspace.RunOperatorOnce(retrievecount_op)\\n    print(\\\"'count' value after CountDown: {}\\\\t'done' value: {}\\\".format(workspace.FetchBlob(\\\"count\\\"), workspace.FetchBlob(\\\"done\\\")))\\n```\\n\\n**Result**\\n\\n```\\n'counter' pointer: counter, a C++ native class of type std::__1::unique_ptr<caffe2::Counter<long long>, std::__1::default_delete<caffe2::Counter<long long> > >.\\nInitial 'count': 5\\nInitial 'done' value: False\\n\\nTesting CountUp operator...\\n'previous_count' after CountUp: 5\\n'previous_count' after CountUp: 6\\n'previous_count' after CountUp: 7\\n'previous_count' after CountUp: 8\\n'previous_count' after CountUp: 9\\n'count' value after CountUp test: 10\\n\\nTesting CountDown operator...\\n'count' value after CountDown: 9        'done' value: False\\n'count' value after CountDown: 8        'done' value: False\\n'count' value after CountDown: 7        'done' value: False\\n'count' value after CountDown: 6        'done' value: False\\n'count' value after CountDown: 5        'done' value: False\\n'count' value after CountDown: 4        'done' value: False\\n'count' value after CountDown: 3        'done' value: False\\n'count' value after CountDown: 2        'done' value: False\\n'count' value after CountDown: 1        'done' value: False\\n'count' value after CountDown: 0        'done' value: False\\n'count' value after CountDown: -1        'done' value: True\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<ptr>`)* A blob pointing to an instance of a counter.\",\n        \"name\": \"counter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: bool)* False unless the internal count is zero.\",\n        \"name\": \"done\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CountUp\",\n    \"description\": \"\\nIncreases count value by 1 and outputs the previous value atomically.\\n\\n  Github Links:\\n  - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/counter_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\ncreatecounter_op = core.CreateOperator(\\n    \\\"CreateCounter\\\",\\n    [],\\n    [\\\"counter\\\"],\\n    init_count=5\\n)\\n\\nretrievecount_op = core.CreateOperator(\\n    \\\"RetrieveCount\\\",\\n    [\\\"counter\\\"],\\n    [\\\"count\\\"]\\n)\\n\\ncheckcounterdone_op = core.CreateOperator(\\n    \\\"CheckCounterDone\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"]\\n)\\n\\ncountup_op = core.CreateOperator(\\n    \\\"CountUp\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n)\\n\\ncountdown_op = core.CreateOperator(\\n    \\\"CountDown\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"],\\n)\\n\\nresetcounter_op = core.CreateOperator(\\n    \\\"ResetCounter\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n    init_count=3\\n)\\n\\n\\n// Create counter\\nworkspace.RunOperatorOnce(createcounter_op)\\nprint(\\\"'counter' pointer:\\\", workspace.FetchBlob(\\\"counter\\\"))\\n\\n\\n// Retrieve initial counter value\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"Initial 'count':\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Check if counter is done\\nworkspace.RunOperatorOnce(checkcounterdone_op)\\nprint(\\\"Initial 'done' value:\\\", workspace.FetchBlob(\\\"done\\\"))\\n\\n\\n// Test CountUp operator\\nprint(\\\"\\\\nTesting CountUp operator...\\\")\\nfor i in range(5):\\n    workspace.RunOperatorOnce(countup_op)\\n    print(\\\"'previous_count' after CountUp:\\\", workspace.FetchBlob(\\\"previous_count\\\"))\\n\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"'count' value after CountUp test:\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Test CountDown operator\\nprint(\\\"\\\\nTesting CountDown operator...\\\")\\nfor i in range(11):\\n    workspace.RunOperatorOnce(countdown_op)\\n    workspace.RunOperatorOnce(retrievecount_op)\\n    print(\\\"'count' value after CountDown: {}\\\\t'done' value: {}\\\".format(workspace.FetchBlob(\\\"count\\\"), workspace.FetchBlob(\\\"done\\\")))\\n```\\n\\n**Result**\\n\\n```\\n'counter' pointer: counter, a C++ native class of type std::__1::unique_ptr<caffe2::Counter<long long>, std::__1::default_delete<caffe2::Counter<long long> > >.\\nInitial 'count': 5\\nInitial 'done' value: False\\n\\nTesting CountUp operator...\\n'previous_count' after CountUp: 5\\n'previous_count' after CountUp: 6\\n'previous_count' after CountUp: 7\\n'previous_count' after CountUp: 8\\n'previous_count' after CountUp: 9\\n'count' value after CountUp test: 10\\n\\nTesting CountDown operator...\\n'count' value after CountDown: 9        'done' value: False\\n'count' value after CountDown: 8        'done' value: False\\n'count' value after CountDown: 7        'done' value: False\\n'count' value after CountDown: 6        'done' value: False\\n'count' value after CountDown: 5        'done' value: False\\n'count' value after CountDown: 4        'done' value: False\\n'count' value after CountDown: 3        'done' value: False\\n'count' value after CountDown: 2        'done' value: False\\n'count' value after CountDown: 1        'done' value: False\\n'count' value after CountDown: 0        'done' value: False\\n'count' value after CountDown: -1        'done' value: True\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<ptr>`)* A blob pointing to an instance of a counter.\",\n        \"name\": \"counter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: int)* Count value BEFORE this operation.\",\n        \"name\": \"previous_count\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateAtomicBool\",\n    \"description\": \"Create an unique_ptr blob to hold an atomic<bool>\",\n    \"outputs\": [\n      {\n        \"description\": \"Blob containing a unique_ptr<atomic<bool>>\",\n        \"name\": \"atomic_bool\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateBlobsQueue\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateBlobsQueueDB\",\n    \"description\": \"Create a DBReader from a BlobsQueue\",\n    \"attributes\": [\n      {\n        \"description\": \"(default: -1 (no key)) index of blob for DB key in the BlobsQueue.\",\n        \"name\": \"key_blob_index\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(default: 0) index of blob for DB value in the BlobsQueue.\",\n        \"name\": \"value_blob_index\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(default: 0.0 (no timeout)) Timeout in seconds for reading from the BlobsQueue.\",\n        \"name\": \"timeout_secs\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The shared pointer to a queue containing Blobs.\",\n        \"name\": \"queue\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The DBReader for the given BlobsQueue\",\n        \"name\": \"reader\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateCommonWorld\",\n    \"description\": \"\\nCreates a common world for communication operators.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) size of the common world.\",\n        \"name\": \"size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) rank of this node in the common world.\",\n        \"name\": \"rank\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Key/value handler for rendezvous (optional).\",\n        \"name\": \"kv_handler\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"A common world for collective operations.\",\n        \"name\": \"comm_world\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateCounter\",\n    \"description\": \"\\nCreates a count-down counter with initial value specified by the `init_count`\\nargument.\\n\\n\\n  Github Links:\\n  - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/counter_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\ncreatecounter_op = core.CreateOperator(\\n    \\\"CreateCounter\\\",\\n    [],\\n    [\\\"counter\\\"],\\n    init_count=5\\n)\\n\\nretrievecount_op = core.CreateOperator(\\n    \\\"RetrieveCount\\\",\\n    [\\\"counter\\\"],\\n    [\\\"count\\\"]\\n)\\n\\ncheckcounterdone_op = core.CreateOperator(\\n    \\\"CheckCounterDone\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"]\\n)\\n\\ncountup_op = core.CreateOperator(\\n    \\\"CountUp\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n)\\n\\ncountdown_op = core.CreateOperator(\\n    \\\"CountDown\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"],\\n)\\n\\nresetcounter_op = core.CreateOperator(\\n    \\\"ResetCounter\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n    init_count=3\\n)\\n\\n\\n// Create counter\\nworkspace.RunOperatorOnce(createcounter_op)\\nprint(\\\"'counter' pointer:\\\", workspace.FetchBlob(\\\"counter\\\"))\\n\\n\\n// Retrieve initial counter value\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"Initial 'count':\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Check if counter is done\\nworkspace.RunOperatorOnce(checkcounterdone_op)\\nprint(\\\"Initial 'done' value:\\\", workspace.FetchBlob(\\\"done\\\"))\\n\\n\\n// Test CountUp operator\\nprint(\\\"\\\\nTesting CountUp operator...\\\")\\nfor i in range(5):\\n    workspace.RunOperatorOnce(countup_op)\\n    print(\\\"'previous_count' after CountUp:\\\", workspace.FetchBlob(\\\"previous_count\\\"))\\n\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"'count' value after CountUp test:\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Test CountDown operator\\nprint(\\\"\\\\nTesting CountDown operator...\\\")\\nfor i in range(11):\\n    workspace.RunOperatorOnce(countdown_op)\\n    workspace.RunOperatorOnce(retrievecount_op)\\n    print(\\\"'count' value after CountDown: {}\\\\t'done' value: {}\\\".format(workspace.FetchBlob(\\\"count\\\"), workspace.FetchBlob(\\\"done\\\")))\\n```\\n\\n**Result**\\n\\n```\\n'counter' pointer: counter, a C++ native class of type std::__1::unique_ptr<caffe2::Counter<long long>, std::__1::default_delete<caffe2::Counter<long long> > >.\\nInitial 'count': 5\\nInitial 'done' value: False\\n\\nTesting CountUp operator...\\n'previous_count' after CountUp: 5\\n'previous_count' after CountUp: 6\\n'previous_count' after CountUp: 7\\n'previous_count' after CountUp: 8\\n'previous_count' after CountUp: 9\\n'count' value after CountUp test: 10\\n\\nTesting CountDown operator...\\n'count' value after CountDown: 9        'done' value: False\\n'count' value after CountDown: 8        'done' value: False\\n'count' value after CountDown: 7        'done' value: False\\n'count' value after CountDown: 6        'done' value: False\\n'count' value after CountDown: 5        'done' value: False\\n'count' value after CountDown: 4        'done' value: False\\n'count' value after CountDown: 3        'done' value: False\\n'count' value after CountDown: 2        'done' value: False\\n'count' value after CountDown: 1        'done' value: False\\n'count' value after CountDown: 0        'done' value: False\\n'count' value after CountDown: -1        'done' value: True\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Initial count for the counter, must be >= 0.\",\n        \"name\": \"init_count\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<ptr>`)* A blob pointing to an instance of a new counter.\",\n        \"name\": \"counter\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateDB\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateMap\",\n    \"description\": \"Create an empty map blob\",\n    \"attributes\": [\n      {\n        \"description\": \"Key's TensorProto::DataType (default INT32)\",\n        \"name\": \"key_dtype\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Value's TensorProto::DataType (default INT32)\",\n        \"name\": \"value_dtype\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Blob reference to the map\",\n        \"name\": \"map blob\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateMutex\",\n    \"description\": \"Creates an unlocked mutex and returns it in a unique_ptr blob.\",\n    \"outputs\": [\n      {\n        \"description\": \"Blob containing a std::unique_ptr<mutex>.\",\n        \"name\": \"mutex_ptr\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateRebatchingQueue\",\n    \"description\": \"\\nCreates the Queue.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of input tensors the queue will support\",\n        \"name\": \"num_blobs\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Maximal number of elements the queue can hold at any given point\",\n        \"name\": \"capacity\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"object representing the queue\",\n        \"name\": \"queue\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateScope\",\n    \"description\": \"\\n'CreateScope' operator initializes and outputs empty scope that is used\\nby Do operator to store local blobs\\n    \",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateTensorVector\",\n    \"description\": \"Create a std::unique_ptr<std::vector<Tensor> >\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateTextFileReader\",\n    \"description\": \"Create a text file reader. Fields are delimited by <TAB>.\",\n    \"attributes\": [\n      {\n        \"description\": \"Path to the file.\",\n        \"name\": \"filename\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Number of passes over the file.\",\n        \"name\": \"num_passes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"List with type of each field. Type enum is found at core.DataType.\",\n        \"name\": \"field_types\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Pointer to the created TextFileReaderInstance.\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CreateTreeCursor\",\n    \"description\": \"\\nCreates a cursor to iterate through a list of tensors, where some of those\\ntensors contain the lengths in a nested schema. The schema is determined by\\nthe `fields` arguments.\\n\\nFor example, to represent the following schema:\\n\\n  Struct(\\n      a=Int(),\\n      b=List(List(Int)),\\n      c=List(\\n          Struct(\\n             c1=String,\\n             c2=List(Int),\\n          ),\\n      ),\\n  )\\n\\nthe field list will be:\\n  [\\n      \\\"a\\\",\\n      \\\"b:lengths\\\",\\n      \\\"b:values:lengths\\\",\\n      \\\"b:values:values\\\",\\n      \\\"c:lengths\\\",\\n      \\\"c:c1\\\",\\n      \\\"c:c2:lengths\\\",\\n      \\\"c:c2:values\\\",\\n  ]\\n\\nAnd for the following instance of the struct:\\n\\n  Struct(\\n      a=3,\\n      b=[[4, 5], [6, 7, 8], [], [9]],\\n      c=[\\n          Struct(c1='alex', c2=[10, 11]),\\n          Struct(c1='bob', c2=[12]),\\n      ],\\n  )\\n\\nThe values of the fields will be:\\n  {\\n      \\\"a\\\": [3],\\n      \\\"b:lengths\\\": [4],\\n      \\\"b:values:lengths\\\": [2, 3, 0, 1],\\n      \\\"b:values:values\\\": [4, 5, 6, 7, 8, 9],\\n      \\\"c:lengths\\\": [2],\\n      \\\"c:c1\\\": [\\\"alex\\\", \\\"bob\\\"],\\n      \\\"c:c2:lengths\\\": [2, 1],\\n      \\\"c:c2:values\\\", [10, 11, 12],\\n  }\\n\\nIn general, every field name in the format \\\"{prefix}:lengths\\\" defines a domain\\n\\\"{prefix}\\\", and every subsequent field in the format \\\"{prefix}:{field}\\\" will\\nbe in that domain, and the length of the domain is provided for each entry of\\nthe parent domain. In the example, \\\"b:lengths\\\" defines a domain of length 4, so\\nevery field under domain \\\"b\\\" will have 4 entries.\\nThe \\\"lengths\\\" field for a given domain must appear before any reference to\\nthat domain.\\n\\nReturns a pointer to an instance of the Cursor, which keeps the current offset\\non each of the domains defined by `fields`. Cursor also ensures thread-safety\\nsuch that ReadNextBatch and ResetCursor can be used safely in parallel.\\n\\nA cursor does not contain data per se, so calls to ReadNextBatch actually need\\nto pass a list of blobs containing the data to read for each one of the fields.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"A list of strings each one representing a field of the dataset.\",\n        \"name\": \"fields\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"A blob pointing to an instance of a new TreeCursor.\",\n        \"name\": \"cursor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CrossEntropy\",\n    \"description\": \"\\nThis operator computes the cross entropy between a $NxD$ dimensional input data tensor $X$  and a $NxD$ dimensional input label tensor $label$. The op produces a single length $N$ output tensor $Y$. Here, $N$ is considered the batch size and $D$ is the size of each element in the batch. In practice, it is most commonly used at the end of models as a part of the loss computation, after the SoftMax operator and before the AveragedLoss operator. The cross entropy operation is defined as follows\\n\\n$$Y_i = \\\\sum_j (label_{ij} * log(X_{ij}))$$\\n\\nwhere ($i$, $j$) is the classifier's prediction of the $j$th class (the correct one), and $i$ is the batch size. Each log has a lower limit for numerical stability.\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/cross_entropy_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/cross_entropy_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"CrossEntropy\\\",\\n    [\\\"X\\\", \\\"label\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X: Sample softmax output for 5-class model\\nX = np.array([[.01, .05, .02, .02, .9],[.03, .1, .42, .05, .4]])\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Create label: Sample 1-hot ground truth label vectors\\nlabel = np.array([[0.,0.,0.,0.,1.],[0.,0.,1.,0.,0.]])\\nprint(\\\"label:\\\\n\\\",label)\\n\\n// Feed X & label into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\nworkspace.FeedBlob(\\\"label\\\", label.astype(np.float32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[0.01 0.05 0.02 0.02 0.9 ]\\n [0.03 0.1  0.42 0.05 0.4 ]]\\nlabel:\\n [[0. 0. 0. 0. 1.]\\n [0. 0. 1. 0. 0.]]\\nY:\\n [0.10536055 0.8675006 ]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor which is almost always the result of a softmax operation. $X$ is a 2D array of size $NxD$, where $N$ is the batch size and $D$ is the number of classes.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Blob containing the labels used to compare the input. $label$ is the same shape as $X$.\",\n        \"name\": \"label\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output blob from the cross entropy computation. $Y$ is 1D length $N$ tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CrossEntropyGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CTCBeamSearchDecoder\",\n    \"description\": \"Prefix beam search decoder for connectionist temporal classification.\",\n    \"attributes\": [\n      {\n        \"description\": \"Maximum number of candidates to carry over to next activation step.\",\n        \"name\": \"beam_width\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Probability threshold below which outputs are ignored.\",\n        \"name\": \"prune_threshold\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D float Tensor sized [max_activation_length, batch_size, alphabet_size] of network logits (before softmax application).\",\n        \"name\": \"INPUTS\"\n      },\n      {\n        \"description\": \"(optional) 1D int vector containing sequence lengths, having size [batch_size] seq_len will be set to max_time if not provided.\",\n        \"name\": \"SEQ_LEN\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output_len matrix size (batch_size * num_candidates). Each index stores lengths of candidates for its corresponding batch item.\",\n        \"name\": \"OUTPUT_LEN\"\n      },\n      {\n        \"description\": \"Values vector, size (total_decoded_outputs). The flattened vector of final output sequences, in batch order.\",\n        \"name\": \"VALUES\"\n      },\n      {\n        \"description\": \"Probability vector, size (total_decoded_outputs). Each index stores final output probability of its corresponding batch item.\",\n        \"name\": \"OUTPUT_PROB\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CTCGreedyDecoder\",\n    \"description\": \"Greedy decoder for connectionist temporal classification.\",\n    \"attributes\": [\n      {\n        \"description\": \"When merge_repeated is true, merge repeated classes in output.\",\n        \"name\": \"merge_repeated\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D float Tensor sized [max_time, batch_size, num_classes]\",\n        \"name\": \"INPUTS\"\n      },\n      {\n        \"description\": \"(optional) 1D int vector containing sequence lengths, having size [batch_size]seq_len will be set to max_time if not provided\",\n        \"name\": \"SEQ_LEN\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output_len matrix size (batch). The row store: [decoded_length]\",\n        \"name\": \"OUTPUT_LEN\"\n      },\n      {\n        \"description\": \"Values vector, size (total_decoded_outputs). The vector stores the decoded classes\",\n        \"name\": \"VALUES\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Cube\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor calculated as the cube of the input tensor, element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CubeGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DataCouple\",\n    \"description\": \"\\n\\nA one to one operator that takes an arbitrary number of input and output blobs\\nsuch that each input blob is inplace with it's matching output blob. It then proceedes\\nto do nothing with each of these operators. This serves two purposes. It can make it\\nappear as if a blob has been written to, as well as can tie together different blobs\\nin a data dependency\\n\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DBExists\",\n    \"description\": \"\\nChecks if the db described by the arguments exists.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/load_save_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"DBExists\\\",\\n    [],\\n    [\\\"exists\\\"],\\n    db_name=\\\"test_db\\\",\\n    db_type=\\\"leveldb\\\",\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"exists:\\\", workspace.FetchBlob(\\\"exists\\\"))\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"If set to non-zero, save the db directly to the path specified by the `db` arg. If not set (default), prepend the path of the current root folder of the workspace to the path specified by the `db` arg.\",\n        \"name\": \"absolute_path\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"Path to the db in question; see the `absolute_path` arg details for options regarding the current root folder of the workspace.\",\n        \"name\": \"db_name\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"description\": \"Type of db to save (options: \\\"lmdb\\\", \\\"leveldb\\\", \\\"minidb\\\").\",\n        \"name\": \"db_type\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Scalar boolean output tensor. True if the db exists, else false.\",\n        \"name\": \"exists\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DenseVectorToIdList\",\n    \"description\": \"\\nDenseVectorToIdList: Convert a blob with dense feature into a ID_LIST.\\n\\nAn ID_LIST is a list of IDs (may be ints, often longs) that represents a single\\nfeature. As described in https://caffe2.ai/docs/sparse-operations.html, a batch\\nof ID_LIST examples is represented as a pair of lengths and values where the\\n`lengths` (int32) segment the `values` or ids (int32/int64) into examples.\\n\\nInput is a single blob where the first dimension is the batch size and the\\nsecond dimension is the length of dense vectors. This operator produces a\\nID_LIST where out_values are the indices of non-zero entries\\nand out_lengths are the number of non-zeros entries in each row.\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A data blob of dense vectors\",\n        \"name\": \"values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Lengths of the sparse feature\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \"Values of the sparse feature\",\n        \"name\": \"out_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DepthConcat\",\n    \"description\": \"Backward compatible operator name for Concat.\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DepthSplit\",\n    \"description\": \"Backward compatible operator name for Split.\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DequeueBlobs\",\n    \"description\": \"\\n  Dequeue the blobs from queue.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Timeout in secs, default: no timeout\",\n        \"name\": \"timeout_secs\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The shared pointer for the BlobsQueue\",\n        \"name\": \"queue\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The blob to store the dequeued data\",\n        \"name\": \"blob\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DequeueRebatchingQueue\",\n    \"description\": \"\\nDequeue Tensors from the Queue.\\nIf the Queue is closed this might return less elements than asked.\\nIf num_elements > 1 the returned elements will be concatenated into one\\ntensor per component.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of elements to dequeue. By default we dequeue one element.\",\n        \"name\": \"num_elements\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"object representing the queue\",\n        \"name\": \"rebatching_queue\"\n      },\n      {\n        \"description\": \"First tensor to enqueue\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DestroyCommonWorld\",\n    \"description\": \"Closes all connections managed by a common world.\",\n    \"inputs\": [\n      {\n        \"description\": \"The common world to be destroyed.\",\n        \"name\": \"common_world\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DiagonalFill\",\n    \"description\": \"\\nThe operator fills the diagonal elements of the output tensor (>= 2D)\\nwith a constant value specified by the 'value' argument, and others 0. If\\nnumber of dimensions of the output tensor is greater than 2, all dimensions\\nmust be equal.\\n\\nThe data type is specified by the 'dtype' argument. The 'dtype' argument must\\nbe one of the data types specified in the 'DataType' enum field in the\\nTensorProto message. If the 'dtype' argument is not provided, the data type of\\n'value' is used.\\n\\nThe output tensor shape is specified by the 'shape' argument. If the number of\\ninput is 1, the shape will be identical to that of the input at run time with\\noptional additional dimensions appended at the end as specified by 'extra_shape'\\nargument. In that case the 'shape' argument should not be set.\\n\\nIf input_as_shape is set to true, then the input should be a 1D tensor\\ncontaining the desired output shape (the dimensions specified in extra_shape\\nwill also be appended)\\n\\nNOTE: Currently, it supports data type of float, int32, int64, and bool.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"value\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The data type for the elements of the output tensor.Strictly must be one of the types from DataType enum in TensorProto.\",\n        \"name\": \"dtype\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor (optional) to provide shape information.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensorargument and its type is specified by the 'dtype' argument\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DistributeFpnProposals\",\n    \"description\": \"\\n...\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) ROI_CANONICAL_SCALE\",\n        \"name\": \"roi_canonical_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) ROI_CANONICAL_LEVEL\",\n        \"name\": \"roi_canonical_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) ROI_MAX_LEVEL\",\n        \"name\": \"roi_max_level\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) ROI_MIN_LEVEL\",\n        \"name\": \"roi_min_level\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Top proposals limited to rpn_post_nms_topN total, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"RPN proposals for ROI level 2, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn2\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 3, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn3\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 4, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn4\"\n      },\n      {\n        \"description\": \"RPN proposals for ROI level 5, format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois_fpn5\"\n      },\n      {\n        \"description\": \"Permutation on the concatenation of all rois_fpni, i=min...max, such that when applied the RPN RoIs are restored to their original order in the input blobs.\",\n        \"name\": \"rois_idx_restore\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Div\",\n    \"description\": \"\\nPerforms element-wise binary division (with limited broadcast support).\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Div\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([[18,8],[2,9]]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([[9,2],[3,2]]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[18  8]\\n [ 2  9]]\\nB:\\n[[9 2]\\n [3 2]]\\nC:\\n[[2 4]\\n [0 4]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Second operand. With broadcasting can be of smaller size than A. If broadcasting is disabled it should be of the same size as A.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor with same dimensions and type as A.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DivGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Do\",\n    \"description\": \"\\n'Do' control operator, executes a subnet in a separate workspace.\\nLast blobs in the input and output lists should be the same blob created with\\nCreateScope op. Arguments 'inner_blobs' and 'outer_blobs_idx' provide a mapping\\nbetween selected inner blob names and corresponding outer blob indices.\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"Subnet with blob bindings\",\n        \"name\": \"net\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"List of inner net blob names to bind to outer workspace\",\n        \"name\": \"inner_blobs\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Indices of corresponding outer workspace blobs, in order: operator inputs, operator outputs (skipping workspace blobs)\",\n        \"name\": \"outer_blobs_idx\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"List of blobs from the forward Do operator workspace needed in backward pass, used in gradient Do operator\",\n        \"name\": \"saved_fwd_blobs\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Whether to reuse workspace or create a new one in a given scope\",\n        \"name\": \"reuse_workspace\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DotProduct\",\n    \"description\": \"\\nComputes and outputs the dot product of the two input float tensors `X` and `Y`.\\nNote that `X` and `Y` must be either 1D or 2D, and they must be the same shape.\\nThe output tensor is 1D, which represents either the product of each element in\\na respective dimension if the inputs are 1D, or the sum of the products in a\\ngiven dimension if the inputs are 2D matrices. Note that the actual dot product\\nis a scalar value, which is effectively the sum of the elements in the 1D\\noutput tensor.\\n\\nFor 1D inputs:\\nGiven two vectors $X = [x_0, x_1, x_2]$ and $Y = [y_0, y_1, y_2]$; $Z = [x_0 * y_0, x_1 * y_1, x_2 * y_2]$\\n\\nFor 2D inputs:\\nGiven two matrices:\\n$$X = [[x_0^0, x_1^0, x_2^0], \\\\\\\\ [x_0^1, x_1^1, x_2^1], \\\\\\\\ [x_0^2, x_1^2, x_2^2], \\\\\\\\ ..., \\\\\\\\ [x_0^n, x_1^n, x_2^n]]$$\\n\\nand\\n\\n$$Y = [[y_0^0, y_1^0, y_2^0], \\\\\\\\ [y_0^1, y_1^1, y_2^1], \\\\\\\\ [y_0^2, y_1^2, y_2^2], \\\\\\\\ ..., \\\\\\\\ [y_0^n, y_1^n, y_2^n]]$$\\n\\nthen\\n\\n$$Z =  \\\\biggl[\\\\Big((x_0^0 * y_0^0) + (x_1^0 * y_1^0) + (x_2^0 * y_2^0)\\\\Big), \\\\\\\\ \\\\Big((x_0^1 * y_0^1) + (x_1^1 * y_1^1) + (x_2^1 * y_2^1)\\\\Big), \\\\\\\\ \\\\Big((x_0^2 * y_0^2) + (x_1^2 * y_1^2) + (x_2^2 * y_2^2)\\\\Big), \\\\\\\\ ..., \\\\\\\\ \\\\Big((x_0^n * y_0^n) + (x_1^n * y_1^n) + (x_2^n * y_2^n)\\\\Big)\\\\biggr]$$\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/distance_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"DotProduct\\\",\\n    [\\\"X\\\",  \\\"Y\\\"],\\n    [\\\"Z\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(20, size=(5)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", np.random.randint(20, size=(5)).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Z:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n\\nworkspace.ResetWorkspace()\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(3,3)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", np.random.randint(10, size=(3,3)).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Z:\\\\n\\\", workspace.FetchBlob(\\\"Z\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [ 2. 15.  2.  7. 12.]\\nY:\\n [ 3. 12.  9.  3. 18.]\\nZ:\\n [ 2. 15.  2.  7. 12.]\\nX:\\n [[2. 0. 4.]\\n [7. 7. 4.]\\n [7. 9. 9.]]\\nY:\\n [[2. 0. 8.]\\n [9. 6. 1.]\\n [7. 8. 0.]]\\nZ:\\n [ 36. 109. 121.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 1D or 2D input tensor.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 1D or 2D input tensor (must have the same shape as X).\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 1D output tensor.\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DotProductGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DotProductWithPadding\",\n    \"description\": \"\\nGiven two input float tensors X, Y with different shapes and produces one\\noutput float tensor of the dot product between X and Y. We currently support\\ntwo kinds of strategies to achieve this. Before doing normal dot_product 1)\\npad the smaller tensor (using pad_value) to the same shape as the other one.\\n2) replicate the smaller tensor to the same shape as the other one. Note the\\nfirst dimension of X, Y must be equal. Only the second dimension of X or Y\\ncan be padded.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the padding value for tensors with smaller dimension\",\n        \"name\": \"pad_value\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"whether to replicate the smaller tensor or not\",\n        \"name\": \"replicate\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D or 2D input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D or 2D input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DotProductWithPaddingGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Dropout\",\n    \"category\": \"Dropout\",\n    \"description\": \"\\n\\n`Dropout` takes one input data tensor (`X`) and produces two tensor outputs, `Y` and\\n`mask`. If the `is_test` argument is zero (default=0), the output `Y` will be the input\\nwith random elements zeroed. The probability that a given element is zeroed is\\ndetermined by the `ratio` argument.\\n\\nIf the `is_test` argument is set to non-zero, the output `Y` is exactly the same as the\\ninput `X`. Note that outputs are scaled by a factor of $\\\\frac{1}{1-ratio}$ during\\ntraining, so that during test time, we can simply compute an identity function. This\\nscaling is important because we want the output at test time to equal the expected value\\nat training time. Dropout has been proven to be an effective regularization technique to\\nprevent overfitting during training.\\n\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/dropout_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/dropout_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Dropout\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"] + [\\\"mask\\\"],\\n    ratio=0.5,\\n    is_test=0\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(5, 5)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"mask:\\\", workspace.FetchBlob(\\\"mask\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[5. 4. 3. 6. 9.]\\n [2. 1. 8. 0. 9.]\\n [7. 3. 0. 6. 3.]\\n [1. 8. 2. 6. 4.]\\n [6. 2. 6. 4. 0.]]\\nY: [[ 0.  0.  0. 12. 18.]\\n [ 0.  0. 16.  0.  0.]\\n [ 0.  0.  0. 12.  6.]\\n [ 0.  0.  4.  0.  0.]\\n [12.  0.  0.  0.  0.]]\\nmask: [[False False False  True  True]\\n [False False  True  True False]\\n [False False  True  True  True]\\n [False False  True False False]\\n [ True False False False False]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0.5,\n        \"description\": \"Probability of an element to be zeroed.\",\n        \"name\": \"ratio\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"If zero (train mode), perform dropout. If non-zero(test mode), Y = X.\",\n        \"name\": \"is_test\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input data as Tensor.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output.\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* The output mask containing boolean values foreach element, signifying which elements are dropped out. If `is_test` isnonzero, this output is not filled.\",\n        \"name\": \"mask\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DropoutGrad\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ElementwiseLinear\",\n    \"description\": \"\\nThis op computes the elementwise linear combination of a batch of input vectors with a weight vector and bias vector. As input, the op takes an input tensor $X$ of shape $NxD$, a weight vector $w$ of length $D$, and a bias vector $b$ of length $D$. Here, $N$ represents the batch size and $D$ represents the length of the feature vectors. The output, $Y$, is a tensor of shape $NxD$ and is calculated as\\n\\n$$Y_{ij} = X_{ij}w_j + b_j \\\\ for \\\\ i\\\\in{N}, j\\\\in{D}$$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_linear_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_linear_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ElementwiseLinear\\\",\\n    [\\\"X\\\", \\\"w\\\", \\\"b\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X\\nX = np.array([[1,2,3,4,5],[6,8,9,16,10]])\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Create w\\nw = np.array([1,1/2.,1/3.,1/4.,1/5.])\\nprint(\\\"w:\\\\n\\\",w)\\n\\n// Create b\\nb = np.array([1.,1.,1.,1.,1.])\\nprint(\\\"b:\\\\n\\\",b)\\n\\n\\n// Feed X & w & b into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\nworkspace.FeedBlob(\\\"w\\\", w.astype(np.float32))\\nworkspace.FeedBlob(\\\"b\\\", b.astype(np.float32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[ 1  2  3  4  5]\\n [ 6  8  9 16 10]]\\nw:\\n [1.  0.5  0.33333333 0.25  0.2]\\nb:\\n [1. 1. 1. 1. 1.]\\nY:\\n [[2. 2. 2. 2. 2.]\\n [7. 5. 4. 5. 3.]]\\n\\n```\\n\\n</details>\\n\\n  \",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Describes the axis of the inputs; defaults to one because the 0th axis most likely describes the batch size.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2D input tensor of size $NxD$. This input represents the input data to be operated on.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D scaling factors, or weights, of size $D$. This input contains the weights that will be multiplied by the data.\",\n        \"name\": \"w\"\n      },\n      {\n        \"description\": \"1D biases of size $D$. This input contains the biases that will be added to the products of the weights and data.\",\n        \"name\": \"b\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2D output tensor of size $NxD$. Calculated as described above.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ElementwiseLinearGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Elu\",\n    \"description\": \"\\n\\nThis op implements the exponential linear unit (ELU) activation function as described in [Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)](https://arxiv.org/abs/1511.07289). The op takes an input tensor $X$ of arbitrary shape, computes the elementwise elu operation, and returns a vector $Y$ of the same shape as output. The alpha parameter may be passed as an argument, but defaults to 1. The elu operation is defined as\\n\\n$$y=f(x) =\\\\begin{cases}\\\\alpha(e^x-1) & x < 0 \\\\\\\\ x & otherwise\\\\end{cases}$$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elu_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elu_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Elu\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    alpha=1.1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[ 0.35339102  1.1860217  -0.10710736]\\n [-3.1173866  -0.1889988  -0.20330353]\\n [ 1.8525308  -0.368949    0.506277  ]]\\n\\nY:\\n [[ 0.35339102  1.1860217  -0.11172786]\\n [-1.0513     -0.18943374 -0.20236646]\\n [ 1.8525308  -0.33939326  0.506277  ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1.0,\n        \"description\": \"Defines alpha parameter used in calculation.\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor of data to be operated on.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D input tensor, calculated as described above.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EluGradient\",\n    \"description\": \"\\nEluGradient takes both Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the rectified linear function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EnforceFinite\",\n    \"description\": \"\\nRaise if there is NaN or Inf values in the input tensor.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EnqueueBlobs\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EnqueueRebatchingQueue\",\n    \"description\": \"\\nEnqueues Tensors into the queue.\\nNumber of input tensors should be equal to the number of components passed\\nduring creation of the queue.\\nIf the Queue is closed this operation will fail.\\nIf enqueue_batch argument is set. We will split the input tensors by the\\nfirst dimension to produce single queue elements.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Are we enqueuing a batch or just a single element.         By default we enqueue single element.\",\n        \"name\": \"enqueue_batch\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"object representing the queue\",\n        \"name\": \"queue\"\n      },\n      {\n        \"description\": \"First tensor to enque. \",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EnsureClipped\",\n    \"description\": \"\\nGiven a tensor, apply clip after gradient is applied; when the param is sparse as\\nindicated by valid indices and grad, in-place is required\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be normalized\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Sparse indices, only needed for sparse param\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed, only needed for sparse param\",\n        \"name\": \"grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"param ensured to be clipped within range\",\n        \"name\": \"output_param\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EnsureCPUOutput\",\n    \"description\": \"\\nThis Op always create TensorCPU output, and may involves cross-device MemCpy.\\nUnder CPU Context, this Op takes TensorCPU as input. Under the CUDA Context,\\nthis Op accepts either CUDA or CPU Tensor input.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input CUDA or CPU tensor.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"TensorCPU that is a copy of the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EnsureDense\",\n    \"description\": \"\\nThis operator converts dense or sparse gradients to dense ones.\\nTherefore, sparse gradient can be back propagated to Operators that consume\\ndense gradients only (e.g., FCGradient).\\n\\nThe operator's behaviors:\\n\\n- In forward, simply pass in place or copy input to the output.\\n- In backward, if the gradient passed-in is sparse gradient, change it to dense gradient in linear time; otherwise, simply pass the dense gradient.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensors.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor. Same dimension as inputs.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EQ\",\n    \"description\": \"\\nPerforms element-wise equal to comparison **==** (with limited broadcast support).\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"EQ\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([1, 5, 2, 9, 12, 3]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([1, 3, 4, 9, 12, 8]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\nA: [ 1  5  2  9 12  3]\\nB: [ 1  3  4  9 12  8]\\nC: [ True False False  True  True False]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor with same dimensions as `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Erf\",\n    \"description\": \"\\nCalculates the arcsine of the given input tensor, element-wise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The arcsine of the input tensor computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ErfGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Exp\",\n    \"description\": \"\\nCalculates the exponential of the given input tensor ($exp(x)$), element-wise. This\\noperation can be done in an in-place fashion too, by providing the same input\\nand output blobs.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/exp_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Exp\\\",\\n    [\\\"X\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,3)).astype(np.float32))\\nprint(\\\"X before running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X after running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX before running op:\\n[[0.5821691  0.07719802 0.50159824]\\n [0.40952456 0.36788362 0.84887683]\\n [0.02472685 0.65730894 0.9066397 ]]\\nX after running op:\\n[[1.7899168 1.080256  1.6513585]\\n [1.5061016 1.4446739 2.3370204]\\n [1.0250351 1.9295927 2.4759884]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* The exponential of the input tensor computed element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Expand\",\n    \"description\": \"\\n        Broadcast the input tensor to a materialized new tensor using given shape.\\n        Broadcast rule is similar to \\\"numpy.array(input) * numpy.ones(shape)\\\":\\n        Dimensions are right alignment;\\n        Two corresponding dimensions must have the same value, or one of them\\n        equals to 1.\\n        In order to align with PyTorch's `expand`, `shape` is allowed to have entries\\n        equal to -1, which means to preserve the size of the corresponding dimension\\n        in `X` (so it's actually equivalent to equal to 1).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<NumericType>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): expand shape\",\n        \"name\": \"shape\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<NumericType>`*): expanded tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"description\": \"\\nThe *ExpandDims* op inserts single-dimensional entries into the shape of the input tensor *data,* and produces a single output tensor *expanded*. The op also takes an argument *dims* with a list of dimensions for where to add the single dimensional entries. If the same blob is provided as input and output, the operation is copy-free. This is the exact inverse operation of *Squeeze*.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ExpandDims\\\",\\n    [\\\"data\\\"],\\n    [\\\"expanded\\\"],\\n    dims=[0,1],\\n)\\n\\nworkspace.FeedBlob(\\\"data\\\", np.zeros((100,100)).astype(np.float32))\\nprint(\\\"data.shape:\\\", workspace.FetchBlob(\\\"data\\\").shape)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"expanded.shape:\\\", workspace.FetchBlob(\\\"expanded\\\").shape)\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ndata.shape: (100, 100)\\nexpanded.shape: (1, 1, 100, 100)\\n\\n```\\n\\n</details>\\n\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of dimensions of *data* to add single dimensional entry.\",\n        \"name\": \"dims\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor of data to be operated on.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reshaped tensor with same data as input.\",\n        \"name\": \"expanded\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ExpandGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fail\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FbFCPacked\",\n    \"description\": \"Same as FC,\\n      but the weight is prepacked as a fbgemm::PackedGemmMatrixFP16\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FbGemmPack\",\n    \"description\": \"Prepack weight for fbgemm\",\n    \"inputs\": [\n      {\n        \"description\": \"row major format weight matrix\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Block row major packed format weight matrix\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FbGemmPackTranspose\",\n    \"description\": \"Prepack weight for fbgemm\",\n    \"inputs\": [\n      {\n        \"description\": \"col major format weight matrix\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Block col major packed format weight matrix\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FC\",\n    \"category\": \"Layer\",\n    \"description\": \"\\nThe FC operator computes an output $(Y)$ as a linear combination of the input data blob $(X)$ with a weight blob $(W)$ and bias blob $(b)$. More formally,\\n\\n$$Y = XW^T+b$$\\n\\nHere, $X$ is a matrix of shape $(M,K)$, $W$ is a matrix of shape $(N,K)$, $b$ is a vector of length $N$, and $Y$ is a matrix of shape $(M,N)$. $N$ can be thought of as the number of nodes in the layer, $M$ is the batch size, and $K$ is the number of features in an input observation.\\n\\n*NOTE: $X$ does not need to explicitly be a 2-dimensional matrix, however, if it is not it will be coerced into one. For an arbitrary $n$-dimensional tensor $X$, e.g. $[a_0, a_1, \\\\ldots ,a_{k-1}, a_k, \\\\ldots , a_{n-1}]$, where $a_i$ in $N$, and $k$ is the $axis$ arg provided, then $X$ will be coerced into a 2-dimensional tensor with dimensions $[a_0 * \\\\ldots * a_{k-1}, a_k * \\\\ldots * a_{n-1}]$. For the default case where axis=1, this means the $X$ tensor will be coerced into a 2D tensor of dimensions $[a_0, a_1 * \\\\ldots * a_{n-1}]$, where $a_0$ is often the batch size. In this situation, we must have $a_0 = M$ and $a_1 * \\\\ldots * a_{n-1} = K$. Lastly, even though $b$ is a vector of length $N$, it is copied and resized to shape $(M x N)$ implicitly, then added to each vector in the batch.*\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/fully_connected_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/fully_connected_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\n// In this example, our batch size is 1 (M=1), the input observation will have\\n//   6 features (K=6), and the layer will have one hidden node (N=1). The\\n//   expected output is Y=7.\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"FC\\\",\\n    [\\\"X\\\", \\\"W\\\", \\\"b\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X: MxK\\ndata = np.array([1,2,3,4,5,6]).astype(np.float32)\\ndata = data[np.newaxis,:]\\n\\n// Create W: NxK\\nweights = np.array(np.array([1,1/2.,1/3.,1/4.,1/5.,1/6.])).astype(np.float32)\\nweights = weights[np.newaxis,:]\\n\\n// Create b: N\\nbias = np.array([1.]).astype(np.float32)\\n\\n// Put the inputs into the workspace\\nworkspace.FeedBlob(\\\"X\\\", data)\\nworkspace.FeedBlob(\\\"W\\\", weights)\\nworkspace.FeedBlob(\\\"b\\\", bias)\\n\\n// Run the operator\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nY:\\n [[7.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Describes the axis of the input data $X$. Defaults to one because in the common case when the input $X$ has shape $(M,K)$, the first axis encodes the batch size.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"Describes the axis of the input weight matrix $W$. Defaults to one because the first axis most likely describes the batch_size.\",\n        \"name\": \"axis_w\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Whether to use float-16 compute kernel.\",\n        \"name\": \"float16_compute\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input blob to be coerced into a 2D matrix of shape $(M,K)$, where $M$ is the batch size and $K$ is the number of features in a single observation.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Input blob to be coerced into a 2D matrix of shape $(N,K)$ describing a fully connected weight matrix. Here, $K$ is the number of features in a single observation and $N$ is the number of nodes in the FC layer.\",\n        \"name\": \"W\"\n      },\n      {\n        \"description\": \"Input blob containing vector of length $N$ which describes one bias for each node in the layer.\",\n        \"name\": \"b\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output blob containing a 2D output matrix of shape $(M,N)$, where $M$ is the batch size and $N$ is the number of nodes in the layer. The output is calculated as $Y=XW^T+b$.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FCGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FCTransposed\",\n    \"description\": \"\\nSame as FC, but weight matrix is supposed to be already pretransposed.\\nFCTransposed stands for calling blass with no noTrans, noTrans\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FCTransposedGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FeedBlob\",\n    \"description\": \"\\nFeedBlobs the content of the blobs. The input and output blobs should be\\none-to-one inplace.\",\n    \"attributes\": [\n      {\n        \"description\": \"(string) if provided then we will use this string as the value for theprovided output tensor\",\n        \"name\": \"value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FileStoreHandlerCreate\",\n    \"description\": \"\\nCreates a unique_ptr<StoreHandler> that uses the filesystem as backing\\nstore (typically a filesystem shared between many nodes, such as NFS).\\nThis store handler is not built to be fast. Its recommended use is for\\nintegration tests and prototypes where extra dependencies are\\ncumbersome. Use an ephemeral path to ensure multiple processes or runs\\ndon't interfere.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"base path used by the FileStoreHandler\",\n        \"name\": \"path\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"prefix for all keys used by this store\",\n        \"name\": \"prefix\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"unique_ptr<StoreHandler>\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Find\",\n    \"description\": \"\\nFinds elements of second input from first input,\\noutputting the last (max) index for each query.\\nIf query not find, inserts missing_value.\\nSee IndexGet() for a version that modifies the index when\\nvalues are not found.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Placeholder for items that are not found\",\n        \"name\": \"missing_value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Index (integers)\",\n        \"name\": \"index\"\n      },\n      {\n        \"description\": \"Needles / query\",\n        \"name\": \"query\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Indices of the needles in index or 'missing value'\",\n        \"name\": \"query_indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FindDuplicateElements\",\n    \"description\": \"\\nThe *FindDuplicateElements* op takes a single 1-D tensor *data* as input and returns a single 1-D output tensor *indices*. The output tensor contains the indices of the duplicate elements of the input, excluding the first occurrences. If all elements of *data* are unique, *indices* will be empty.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/find_duplicate_elements_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/find_duplicate_elements_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"FindDuplicateElements\\\",\\n    [\\\"data\\\"],\\n    [\\\"indices\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"data\\\", np.array([8,2,1,1,7,8,1]).astype(np.float32))\\nprint(\\\"data:\\\\n\\\", workspace.FetchBlob(\\\"data\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"indices: \\\\n\\\", workspace.FetchBlob(\\\"indices\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ndata:\\n [8. 2. 1. 1. 7. 8. 1.]\\nindices:\\n [3 5 6]\\n\\n```\\n\\n</details>\\n\\n\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"a 1-D tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Indices of duplicate elements in data, excluding first occurrences.\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Flatten\",\n    \"description\": \"\\nFlattens the input tensor into a 2D matrix. If input tensor has shape\\n$(d_0, d_1, ..., d_n)$ then the output will have shape\\n$\\\\bigl((d_0 * d_1 * ... * d_{(axis-1)}), (d_{axis} * d_{(axis+1)} * ... * d_n)\\\\bigr)$.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/flatten_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Flatten\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    axis=1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(1,3,2,2))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[[[0.53432311 0.23734561]\\n   [0.56481598 0.52152617]]\\n\\n  [[0.33662627 0.32472711]\\n   [0.17939016 0.97175851]]\\n\\n  [[0.87226421 0.49045439]\\n   [0.92470531 0.30935077]]]]\\nY: [[0.53432311 0.23734561 0.56481598 0.52152617 0.33662627 0.32472711\\n  0.17939016 0.97175851 0.87226421 0.49045439 0.92470531 0.30935077]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Indicates up to which input dimensions (exclusive) should be flattened to the outer dimension of the output.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input Tensor of rank >= axis.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* A 2D tensor with the contents of the input tensor, with input dimensions up to `axis` flattened to the outer dimension of the output and the remaining input dimensions flattened into the inner dimension of the output.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FlattenToVec\",\n    \"description\": \"\\n\\nThe *FlattenToVec* op flattens the input tensor into a 1-D vector. The op accepts a single input tensor and returns a single output tensor.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"FlattenToVec\\\",\\n    [\\\"input\\\"],\\n    [\\\"output\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]]).astype(np.float32))\\nprint(\\\"input:\\\\n\\\", workspace.FetchBlob(\\\"input\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output: \\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput:\\n [[ 1.  2.  3.]\\n [ 4.  5.  6.]\\n [ 7.  8.  9.]\\n [10. 11. 12.]]\\noutput:\\n [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A tensor of rank >= 1.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"A tensor of rank 1 (vector) with the contents of the input tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FlexibleTopK\",\n    \"description\": \"\\nGiven two tensors: X and K,\\nretrieve the top K[..., 1] elements from X on the last dimension.\\nX is an input tensor of shape [a_1, a_2, ..., a_n, r].\\nK is an input tensor of shape [a_1, a_2, ..., a_n, 1],\\nwhere for each element, r >= K[..., 1] > 0\\nOutput two outputs:\\n-Flatten values tensor of shape [ \\\\sum_i K[i, 1] ] which contains the values of\\n the top K[..., 1]  elements along the last dimension\\n-Flatten indices tensor of shape [ \\\\sum_i K[i, 1] ] which contains the indices\\n of the top K[..., 1]  elements, flatten indices from the input tensor).\\nThese two outputs should be used with the input K, so that we know which indices\\nin X are picked.\\n\\nGiven two equivalent values, this operator uses the indices along the last dim-\\nension as a tiebreaker. That is, the element with the lower index will appear\\nfirst.\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of shape [a_1, a_2, ..., a_n, r]\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Tensor of shape [a_1, a_2, ..., a_n, 1]\",\n        \"name\": \"K\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of shape [ \\\\sum_i K[i, 1] ] containing top K[..., 1] values from the input tensor\",\n        \"name\": \"Flatten values\"\n      },\n      {\n        \"description\": \"Tensor of shape [ \\\\sum_i K[i, 1] ] containing the indices into the flatten input\",\n        \"name\": \"Flatten indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FlexibleTopKGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Float16ConstantFill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"value\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of constant values specified by 'value'\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Float16SparseNormalize\",\n    \"description\": \"\\nGiven a sparse matrix, apply max_norm or constant_norm sparse regularization.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"A bool variable to control whether to use max norm     or constant norm. When use_max_norm = false, constant norm is used so that     all the embedding vectors are scaled to have a L2 norm equals to A     (see blow argument norm=A). If use_max_norm = true,     max norm is used so that embedding is scaled so that its l2 norm is no larger     than A. If an embedding's norm is less than A originally,     the embedding is left unchanged.    The default is True.\",\n        \"name\": \"use_max_norm\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"L2 norm of the embedding. The default is 1.0.\",\n        \"name\": \"norm\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be normalized\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed (optional - not used, this argument is for backwards compatibility)\",\n        \"name\": \"grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Normalized parameters\",\n        \"name\": \"output_param\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Float16UniformFill\",\n    \"description\": \"Fills a half float tensor of a specified shape with values from a uniform distribution[min,max]\",\n    \"attributes\": [\n      {\n        \"description\": \"Shape of the tensor\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Minimim value to generate\",\n        \"name\": \"min\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Maximum value to generate\",\n        \"name\": \"max\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFused2BitFakeRowwiseQuantized\",\n    \"description\": \"\\nApplies 2-bit row-wise fake quantization to a tensor of floats.\\nThe output looks like an int8 rowwise quantized blob with\\nscale and biases in half float.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFused2BitRowwiseQuantized\",\n    \"description\": \"\\nApplies 2-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 2-bit number between 0 and\\n3. To later de-quantize values, the scale (range / 3) and zero_point\\nare stored alongside the data. More precisely, each row first has quantized\\nvalues, and then 2-byte fp16 scale and 2-byte zero_offset.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFused4BitFakeRowwiseQuantized\",\n    \"description\": \"\\nApplies 4-bit row-wise fake quantization to a tensor of floats.\\nThe output looks like an int8 rowwise quantized blob with\\nscale and biases in half float.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFused4BitRowwiseQuantized\",\n    \"description\": \"\\nApplies 4-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 4-bit number between 0 and\\n15. To later de-quantize values, the scale (range / 15) and zero_point\\nare stored alongside the data. More precisely, each row first has quantized\\nvalues, and then 2-byte fp16 scale and 2-byte zero_offset.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFused8BitRowwiseQuantized\",\n    \"description\": \"\\nApplies 8-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 8-bit number between 0 and\\n255. To later de-quantize values, the scale (range / 255) and offset\\n(bias) are stored alongside the data. More precisely, each row contains\\nint8 elements for each quantized element, and the last 8 bytes\\nof each row in the output matrix are a float storing the scale\\nfollowed by another float containing the scale.\\nFor N-dimensional input tensor, the first N-1 dimensions are interpreted as\\nrows and the last dimension is interpreted as a column. For example, an\\ninput tensor with dimension 5x2x4 is interpreted as 10 rows and 4 columns.\\n)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFused8BitRowwiseQuantizedHalfScaleBias\",\n    \"description\": \"\\nApplies 8-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 8-bit number between 0 and\\n255. To later de-quantize values, the scale (range / 255) and offset\\n(bias) are stored alongside the data. More precisely, each row contains\\nint8 elements for each quantized element, and the last 4 bytes\\nof each row in the output matrix are a half float storing the scale\\nfollowed by another half float containing the scale.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToFusedRandRowwiseQuantized\",\n    \"description\": \"\\nApplies row-wise stochastic/random quantization by determining the range of\\neach row in the input matrix, and then quantize each element to one of two\\nclosest discrete levels by randomly drawing Bernoulli distribution.\\nThe method is extended from TernGrad [1],\\nwhich randomly quantizes gradients to three levels to reduce communication in distributed training.\\nThe format of each row (x) in the output matrix is [bitwidth][tail][min][max][data]:\\nbitwidth[1 Byte]: bitwidth per data [1, 2, 4 or 8];\\ntail[1 Byte]: the number of unused buckets [1-8] (One byte is split to 8/bitwidth buckets and each bucket stores one low-precision data in bitwidth bits);\\nmin[4 Bytes]: the minimum floating value min(x);\\nmax[4 Bytes]: the maximum floating value max(x);\\ndata: quantized data.\\nThe quantization is uniform with levels q = min + (max-min)/(2^bitwidth - 1)*[0:1:2^bitwidth].\\nDuring stochastic/random quantization x'=Quantize(x), for q_j < x_i <= q_{j+1}, we draw quantization x'_i from Bernoulli distributions with\\nP(x'_i = q_{j+1}) = (x_i - q_j)/(q_{j+1} - q_j), and\\nP(x'_i = q_j) = (q_{j+1} - x_i)/(q_{j+1} - q_j) where x'_i is the quantized value of x_i.\\n[1] proved E{x'_i}=x_i, which is an unbiased approximation. More details are in the paper.\\nFor example, suppose targeted bitwidth = 2 and x = [0.3, -1.4, -0.6, 0.9, 1.0],\\nthen tail = 3, min = -1.4, max = 1.0 and q = [-1.4, -0.6, 0.2, 1.0].\\nx_1 = 0.3 will be quantized to x'_1 = 0.2 with probability 7/8 and to x'_1 = 1.0 with probability 1/8.\\nThe storage format of quantized data is: [x'_1|x'_3|x'_5|xxx]-[x'_2|x'_4|xxx|xxx].\\nIn general, a input row is split to multiple segments. One segment is a continuous subarray of the row,\\nand its length is the number of bytes storing quantized data in the output matrix.\\nThe b-th bucket of the i-th byte stores the i-th data of the b-th segment of input row.\\n\\n[1] Wen, Wei, Cong Xu, Feng Yan, Chunpeng Wu, Yandan Wang, Yiran Chen, and Hai Li.\\n\\\"Terngrad: Ternary gradients to reduce communication in distributed deep learning.\\\"\\nIn Advances in Neural Information Processing Systems, pp. 1508-1518. 2017.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"How many bits to quantize per data (defaults to 8).\",\n        \"name\": \"bitwidth\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"random or not (True). False is set up for unittest.\",\n        \"name\": \"random\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Float32 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused bitwidth, tail, min, max and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToHalf\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FloatToRowwiseQuantized8Bits\",\n    \"description\": \"\\nThis operator applies 8Bit row-wise quantization to\\ninput tensor and returns quantized tensor. Row wise quantization of\\ninput tensor is the following process. We take tensor of size\\n(m_1, m_2,...,m_n), n >= 2, reshape it into matrix of size\\n(m_1, m_2 x... x m_n) and apply row-wise quantization. After this,\\nwe compute scale_i= (min_i - max_i) / 255 and  bias_i = min_i for\\ni-th row r_i of reshaped matrix, where min_i and max_i --  minimum\\nand maximum elements of i-th row, and quantize each element r_{ij} as\\n0 <= round(r_ij - bias_i) / scale_i) < 256. Instead of input tensor\\nwe obtain uint8 tensor and auxiliary information as scale and bias to\\nrestore input tensor (with losses).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"input\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"quantized_input\",\n        \"name\": \"quantized_input\"\n      },\n      {\n        \"description\": \"Matrix of floats, each row r_i of which stores a pair s_i, b_i\",\n        \"name\": \"scale_bias\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Floor\",\n    \"description\": \"\\nElement-wise application of the floor function ($y=floor(x)$) to the input\\ntensor `X`. Output tensor shape is the same as the input tensor. This\\noperator can be used in an in-place fashion by using the same input blob as the\\noutput blob.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/floor_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Floor\\\",\\n    [\\\"X\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.uniform(-10, 10, (5,5))).astype(np.float32))\\nprint(\\\"X before running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X after running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX before running op:\\n[[ 3.813361   -1.319647    5.2089314  -4.931328    0.6218652 ]\\n [ 7.2757645   5.5552588   5.785643   -2.4790506  -0.41400087]\\n [ 1.1541046  -6.933266    3.3754056   1.6569928  -1.7670316 ]\\n [-3.4932013   4.891472    1.5530115  -3.2443287  -4.605099  ]\\n [-4.574543   -7.360948    5.91305    -8.196495   -5.357458  ]]\\nX after running op:\\n[[ 3. -2.  5. -5.  0.]\\n [ 7.  5.  5. -3. -1.]\\n [ 1. -7.  3.  1. -2.]\\n [-4.  4.  1. -4. -5.]\\n [-5. -8.  5. -9. -6.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Free\",\n    \"description\": \"\\nFrees the content of the blobs. The input and output blobs should be\\none-to-one inplace.\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Ftrl\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused2BitRowwiseQuantizedToFloat\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused2BitRowwiseQuantized operator. The input is expected to first have\\nquantized values, then 2-byte fp16 scale and 1-byte zero_offset. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and zero_point\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float32 data\",\n        \"name\": \"float_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused2BitRowwiseQuantizedToHalf\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused2BitRowwiseQuantized operator. The input is expected to first have\\nquantized values, then 2-byte fp16 scale and 1-byte zero_offset. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and zero_point\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float16 data\",\n        \"name\": \"float16_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused4BitRowwiseQuantizedToFloat\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused4BitRowwiseQuantized operator. The input is expected to first have\\nquantized values, then 2-byte fp16 scale and 1-byte zero_offset. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and zero_point\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float32 data\",\n        \"name\": \"float_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused4BitRowwiseQuantizedToHalf\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused4BitRowwiseQuantized operator. The input is expected to first have\\nquantized values, then 2-byte fp16 scale and 1-byte zero_offset. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and zero_point\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float16 data\",\n        \"name\": \"float16_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused8BitRowwiseQuantizedHalfScaleBiasToFloat\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused8BitRowwiseQuantized operator. The input is expected to\\nencode the scale as a 16-bit float in the second to the last 2 bytes of each\\nrow, followed by the bias as a 16-bit float in the next 2 bytes, and the\\nquantized values in the preceding bytes of the row. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and bias\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float32 data\",\n        \"name\": \"float_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused8BitRowwiseQuantizedHalfScaleBiasToHalfFloat\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused8BitRowwiseQuantized operator. The input is expected to\\nencode the scale as a 16-bit float in the second to the last 2 bytes of each\\nrow, followed by the bias as a 16-bit float in the next 2 bytes, and the\\nquantized values in the preceding bytes of the row. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and bias\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float32 data\",\n        \"name\": \"float_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused8BitRowwiseQuantizedToFloat\",\n    \"description\": \"\\nDe-quantizes the result of the\\nFloatToFused8BitRowwiseQuantized operator. The input is expected to\\nencode the scale as a 32-bit float in the second to the last 4 bytes of each\\nrow, followed by the bias as a 32-bit float in the next 4 bytes, and the\\nquantized values in the preceding bytes of the row. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and bias\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float32 data\",\n        \"name\": \"float_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Fused8BitRowwiseQuantizedToHalfFloat\",\n    \"description\": \"\\nDe-quantizes the result of the\\nHalfFloatToFused8BitRowwiseQuantized operator. The input is expected to\\nencode the scale as a 32-bit float in the second to the last 4 bytes of each\\nrow, followed by the bias as a 32-bit float in the next 4 bytes, and the\\nquantized values in the preceding bytes of the row. The output is a\\nmatrix containing only the values, but de-quantized. De-quantization is\\nperformed by multiplying each value by its row's scale and bias\\nparameters. The de-quantized values will thus not be exactly equal to\\nthe original, un-quantized floating point values.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"scale_bias_quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float16 data\",\n        \"name\": \"float16_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"FusedRandRowwiseQuantizedToFloat\",\n    \"description\": \"\\nDe-quantizes the result of the FloatToFusedRandRowwiseQuantized operator.\\nRefer FloatToFusedRandRowwiseQuantized operator for details.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Fused bitwidth, tail, min, max and quantized data\",\n        \"name\": \"quantized_input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Float32 data\",\n        \"name\": \"float_input\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Gather\",\n    \"category\": \"Transform\",\n    \"description\": \"\\n\\nThe *Gather* op accepts a *DATA* tensor of rank $r >= 1$ and *INDICES* tensor of rank $q$ as inputs. It then gathers entries of the outer-most dimension of *DATA*, indexed by *INDICES*, and concatenate them in an output tensor of rank $q + (r - 1)$.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/gather_op.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/gather_op.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Gather\\\",\\n    [\\\"DATA\\\", \\\"INDICES\\\"],\\n    [\\\"OUTPUT\\\"]\\n)\\ndata = np.array([[1., 1.2],[2.3, 3.4],[4.5, 5.7]])\\nprint(\\\"DATA:\\\\n\\\",data)\\n\\ninds = np.array([[0, 1],[1, 2]])\\nprint(\\\"INDICES:\\\\n\\\",inds)\\n\\n// Feed X into workspace\\nworkspace.FeedBlob(\\\"DATA\\\", data.astype(np.float32))\\nworkspace.FeedBlob(\\\"INDICES\\\", inds.astype(np.int32))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"OUTPUT:\\\\n\\\", workspace.FetchBlob(\\\"OUTPUT\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nDATA:\\n [[1.  1.2]\\n [2.3 3.4]\\n [4.5 5.7]]\\nINDICES:\\n [[0 1]\\n [1 2]]\\nOUTPUT:\\n [[[1.  1.2]\\n  [2.3 3.4]]\\n\\n [[2.3 3.4]\\n  [4.5 5.7]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor of rank $r>=1$\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Input indices tensor of rank $q$. This tensor must contain integers.\",\n        \"name\": \"INDICES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of rank $q+(r-1)$\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GatherByKey\",\n    \"description\": \"\\nInverse operation of Partition.\\n\\nTakes the original, full 'keys' tensor followed by sharded value tensors,\\nand returns the full value tensor, combined using the same hash used in\\nPartition.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The first input is the full keys tensor (same as the first input of Partition).\",\n        \"name\": \"keys\"\n      },\n      {\n        \"description\": \"Subsequented inputs are sharded values tensors.\",\n        \"name\": \"sharded_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reconstructed values tensor.\",\n        \"name\": \"values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GatherFused8BitRowwise\",\n    \"description\": \"\\nPerform the same operation as Gather, but operating on 8-bit rowwise quantized\\nmatrices with fused storage (where each row stores quantized values, and then\\nthe scale and offset).\\nDATA needs to have rank 2 and INDICES needs to have rank 1.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor with rank 2 obtained with operator FloatToFused8BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA forthe rows that are being gathered\",\n        \"name\": \"INDICES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GatherPadding\",\n    \"description\": \"\\nGather the sum of start and end paddings in a padded input sequence. Used in\\norder to compute the gradients of AddPadding w.r.t the padding tensors.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Outer-size of padding present around each range.\",\n        \"name\": \"padding_width\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(Optional) Specifies a different end-padding width.\",\n        \"name\": \"end_padding_width\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"T<N, D1..., Dn> Padded input data\",\n        \"name\": \"data_in\"\n      },\n      {\n        \"description\": \"(i64) Num of elements in each range. sum(lengths) = N. If not provided, considers all data as a single segment.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Sum of all start paddings, or of all paddings if end_padding_sum is not provided.\",\n        \"name\": \"padding_sum\"\n      },\n      {\n        \"description\": \"T<D1..., Dn> Sum of all end paddings, if provided.\",\n        \"name\": \"end_padding_sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GatherRanges\",\n    \"description\": \"\\nGiven DATA tensor of rank 1, and RANGES tensor of rank 3, gather\\ncorresponding ranges into a 1-D tensor OUTPUT.\\n\\nRANGES dimentions description:\\n1: represents list of examples within a batch\\n2: represents list features\\n3: two values which are start and length or a range (to be applied on DATA)\\n\\nAnother output LENGTHS represents each example length within OUTPUT\\n\\nExample:\\n  DATA  = [1, 2, 3, 4, 5, 6]\\n  RANGES = [\\n    [\\n      [0, 1],\\n      [2, 2],\\n    ],\\n    [\\n      [4, 1],\\n      [5, 1],\\n    ]\\n  ]\\n  OUTPUT = [1, 3, 4, 5, 6]\\n  LENGTHS = [3, 2]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of rank 1.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Tensor of int32/int64 ranges, of dims (N, M, 2). Where N is number of examples and M is a size of each example. Last dimension represents a range in the format (start, lengths)\",\n        \"name\": \"RANGES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor of size sum of range lengths\",\n        \"name\": \"OUTPUT\"\n      },\n      {\n        \"description\": \"1-D tensor of size N with lengths over gathered data for each row in a batch. sum(LENGTHS) == OUTPUT.size()\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GatherRangesToDense\",\n    \"description\": \"\\nGiven DATA tensor of rank 1, and RANGES tensor of rank 3, gather values\\ncorresponding to each range into a separate output tensor. If the optional input\\nKEY tensor is also given, the output will be sorted by KEY for each example.\\n\\nRANGES dimensions description:\\n1: represents list of examples within a batch\\n2: represents list features\\n3: two values which are start and length or a range (to be applied on DATA)\\n\\nEach feature has fixed lengths which are passed as lengths argument and a\\nseparate tensor will be produced for each feature.\\ni.e. DATA.dim(1) = len(lengths) = NumOuptuts.\\n\\nMissing features (represented by empty ranges) filled with default_value.\\n\\nExample 1:\\n  DATA  = [1, 2, 3, 4, 5, 6, 7, 8]\\n  RANGES = [\\n    [\\n      [2, 4],\\n      [0, 2],\\n    ],\\n    [\\n      [0, 0],\\n      [6, 2],\\n    ]\\n  ]\\n  lengths = [4, 2]\\n  OUTPUT[0] = [[3, 4, 5, 6], [0, 0, 0, 0]]\\n  OUTPUT[1] = [[1, 2], [7, 8]]\\n\\nExample 2 (with KEY):\\nDATA  = [1, 2, 3, 4, 5, 6, 7, 8]\\nKEY   = [0, 1, 3, 2, 1, 0, 1, 0]\\nRANGES = [\\n  [\\n    [2, 4],\\n    [0, 2],\\n  ],\\n  [\\n    [0, 0],\\n    [6, 2],\\n  ]\\n]\\nlengths = [4, 2]\\nOUTPUT[0] = [[6, 5, 4, 3], [0, 0, 0, 0]]\\nOUTPUT[1] = [[1, 2], [8, 7]]\\n\\nContrast Example 2 with Example 1. For each data point per feature, the values\\nare sorted by the corresponding KEY.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Expected lengths for ranges\",\n        \"name\": \"lengths\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The number of observations needed before deciding that the ratio of mismatched ranges is alarming, also determines whether an info sumarizing the empty and mismatch ratio will be printed at the end.\",\n        \"name\": \"min_observation\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"An error is raised when ratio of empty ranges exceeds this (default is 1, which means by default no error will be triggered).\",\n        \"name\": \"max_empty_ratio\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"An error is raised when ratio of mismatched ranges exceeds this.\",\n        \"name\": \"max_mismatched_ratio\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"A log is recorded only after an error is triggered every n times.\",\n        \"name\": \"log_every_n\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of rank 1.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Tensor of int32/int64 ranges, of dims (N, M, 2). Where N is number of examples and M is a size of each example. Last dimension represents a range in the format (start, lengths)\",\n        \"name\": \"RANGES\"\n      },\n      {\n        \"description\": \"Tensor of rank 1 and type int64.\",\n        \"name\": \"KEY\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor of size sum of range lengths\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GaussianFill\",\n    \"description\": \"\\nThis op fills an output tensor with samples drawn from a normal distribution specified by the mean and standard deviation arguments. The output tensor shape is specified by the *shape* argument. However, if *input_as_shape* is set to *true*, then the *input* should be a 1D tensor containing the desired output shape (the dimensions specified in *extra_shape* will also be appended). In this case, the *shape* argument should **not** be set.\\n\\n*Note: cannot set the shape argument and pass in an input at the same time.*\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"GaussianFill\\\",\\n    [],\\n    [\\\"out\\\"],\\n    shape=[3,3],\\n    mean=2.0,\\n    std=1.1\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Out:\\\\n\\\", workspace.FetchBlob(\\\"out\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nOut:\\n [[1.2084167  2.3336504  2.827349  ]\\n [2.7108908  0.9374752  1.7173369 ]\\n [0.03320992 2.1775863  1.0894578 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0.0,\n        \"description\": \"Mean of the distribution to draw from.\",\n        \"name\": \"mean\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1.0,\n        \"description\": \"Standard deviation of the distribution to draw from.\",\n        \"name\": \"std\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"description\": \"Desired shape of the *output* tensor.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the *shape* indicated by the input blob. Cannot set the *extra_shape* argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"set to *True* to use the *input* as shape. First, input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(Optional) 1D tensor specifying the shape of the output. Must be used with *input_as_shape=True*\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of random values drawn from a normal distribution. If the shape argument is set, this is the shape specified, and if the *input* exists and *input_as_shape=True*, it is the shape specified by the *input* tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GE\",\n    \"description\": \"\\nPerforms element-wise greater or equal than comparison **>=** (with limited broadcast support).\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"GE\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([1, 5, 2, 9, 12, 3]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([1, 3, 4, 9, 12, 8]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA: [ 1  5  2  9 12  3]\\nB: [ 1  3  4  9 12  8]\\nC: [ True  True False  True  True False]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor with same dimensions as `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Gelu\",\n    \"description\": \"\\nRelu takes one input data (Tensor) and produces one output data\\n(Tensor) where the rectified linear function, y = xP(X <= x) where X ~ N(0, 1),\\nis applied to the tensor elementwise.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"If true, use y = 0.5x * (1 + tanh(sqrt(2/Pi) * (x + 0.044715x^3))).\",\n        \"name\": \"fast_gelu\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GeluGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GenerateProposals\",\n    \"description\": \"\\nGenerate bounding box proposals for Faster RCNN. The propoasls are generated for\\na list of images based on image score 'score', bounding box regression result\\n'deltas' as well as predefined bounding box shapes 'anchors'. Greedy\\nnon-maximum suppression is applied to generate the final bounding boxes.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float) spatial scale\",\n        \"name\": \"spatial_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_PRE_NMS_TOP_N\",\n        \"name\": \"pre_nms_topN\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) RPN_POST_NMS_TOP_N\",\n        \"name\": \"post_nms_topN\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) RPN_NMS_THRESH\",\n        \"name\": \"nms_thresh\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) RPN_MIN_SIZE\",\n        \"name\": \"min_size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default false), Correct bounding box transform coordates, see bbox_transform() in boxes.py Set to true to match the detectron code, set to false for backward compatibility\",\n        \"name\": \"correct_transform_coords\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool (default true). If set, for rotated boxes, angle is normalized to be within [angle_bound_lo, angle_bound_hi].\",\n        \"name\": \"angle_bound_on\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int (default -90 degrees). If set, for rotated boxes, angle is normalized to be within [angle_bound_lo, angle_bound_hi].\",\n        \"name\": \"angle_bound_lo\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int (default 90 degrees). If set, for rotated boxes, angle is normalized to be within [angle_bound_lo, angle_bound_hi].\",\n        \"name\": \"angle_bound_hi\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"float (default 1.0 degrees). For RRPN, clip almost horizontal boxes within this threshold of tolerance for backward compatibility. Set to negative value for no clipping.\",\n        \"name\": \"clip_angle_thresh\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Scores from conv layer, size (img_count, A, H, W)\",\n        \"name\": \"scores\"\n      },\n      {\n        \"description\": \"Bounding box deltas from conv layer, size (img_count, 4 * A, H, W)\",\n        \"name\": \"bbox_deltas\"\n      },\n      {\n        \"description\": \"Image info, size (img_count, 3), format (height, width, scale)\",\n        \"name\": \"im_info\"\n      },\n      {\n        \"description\": \"Bounding box anchors, size (A, 4)\",\n        \"name\": \"anchors\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Proposals, size (n x 5), format (image_index, x1, y1, x2, y2)\",\n        \"name\": \"rois\"\n      },\n      {\n        \"description\": \"scores of proposals, size (n)\",\n        \"name\": \"rois_probs\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GenerateProposalsCPP\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GetAllBlobNames\",\n    \"description\": \"\\nReturn a 1D tensor of strings containing the names\\nof each blob in the active workspace.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(bool, default true) Whether to include blobs inherited from parent workspaces.\",\n        \"name\": \"include_shared\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of strings containing blob names.\",\n        \"name\": \"blob_names\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GetCursorOffset\",\n    \"description\": \"Get the current offset in the cursor.\",\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the cursor.\",\n        \"name\": \"cursor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing the offsets for the cursor.\",\n        \"name\": \"offsets\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GFtrl\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorBoolFill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorByteStringToUInt8Fill\",\n    \"description\": \"\\nThis op fills a uint8 output tensor with the data specified by the *value* argument. The data must previously be serialized as a byte string. The output tensor shape is specified by the *shape* argument. Beware, when using this argument *value* should have a value for every element of the *output*, as missing values will not be initialized automatically. If *input_as_shape* is set to *true*, then the *input* should be a 1D tensor containing the desired output shape (the dimensions specified in *extra_shape* will also be appended). In this case, the *shape* argument should **not** be set.\\n\\nThis op allows us to write uint8 tensors to Protobuf as byte strings and read them back as uint8 tensors in order to avoid the Protobuf uint32_t varint encoding size penalty.\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nval = np.array([1, 2, 3], dtype=np.uint8)\\nop = core.CreateOperator(\\n    \\\"GivenTensorByteStringToUInt8Fill\\\",\\n    [],\\n    [\\\"out\\\"],\\n    values=[val.tobytes()],\\n    shape=val.shape,\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Out:\\\\n\\\", workspace.FetchBlob(\\\"out\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nOut:\\n [1 2 3]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorDoubleFill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorFill\",\n    \"description\": \"\\nThis op fills an output tensor with the data specified by the *value* and *dtype* arguments.  The output tensor shape is specified by the *shape* argument. Beware, when using this argument *value* should have a value for every element of the *output*, as missing values will not be initialized automatically. If *input_as_shape* is set to *true*, then the *input* should be a 1D tensor containing the desired output shape (the dimensions specified in *extra_shape* will also be appended). In this case, the *shape* argument should **not** be set.\\n\\n*Note: Do not set the shape argument and pass in an input at the same time.*\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/given_tensor_fill_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/given_tensor_fill_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"GivenTensorFill\\\",\\n    [],\\n    [\\\"out\\\"],\\n    values=[1., 2., 3.],\\n    shape=[3],\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Out:\\\\n\\\", workspace.FetchBlob(\\\"out\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nOut:\\n [1. 2. 3.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The value of the elements to go in the *output* tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The data type for the elements of the output tensor. Strictly must be one of the types from DataType enum in TensorProto.\",\n        \"name\": \"dtype\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Desired shape of the *output* tensor.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the *shape* indicated by the input blob. Cannot set the *extra_shape* argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"set to *True* to use the *input* as shape. First, input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(Optional) 1D tensor specifying the shape of the output. Must be used with *input_as_shape=True*\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor with desired dimension filled with specified data. If the shape argument is set, this is the shape specified, and if the *input* exists and *input_as_shape=True*, it is the shape specified by the *input* tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorInt16Fill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorInt64Fill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorIntFill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GivenTensorStringFill\",\n    \"attributes\": [\n      {\n        \"description\": \"The value for the elements of the output tensor.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob.Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Glu\",\n    \"description\": \"\\nApplies gated linear unit to the input Tensor X. The output Y is half the size\\nof the input X, so if the shape of X is [d1, d2, ..., N] shape of Y will be\\n[d1, d2, ..., dn/2] and Y(:dn-1, i) = GLU(X(:dn-1, i), X(:dn-1, i+N/2)) =\\nX(dn-1, i) * sigmoid(X(dn-1, i+N/2))\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GroupNorm\",\n    \"description\": \"\\nGroup Normalization (GN) operation: https://arxiv.org/abs/1803.08494\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) default 32; number of groups used by GN.\",\n        \"name\": \"num_groups\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) default 1e-5; small constant added to var.\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \">=4D feature map input of shape (N, C, H, W) or (N, C, T, H, W)\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The scale as a 1-dimensional tensor of size C to be applied to the output.\",\n        \"name\": \"gamma\"\n      },\n      {\n        \"description\": \"The bias as a 1-dimensional tensor of size C to be applied to the output.\",\n        \"name\": \"beta\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output >=4-dimensional tensor of the same shape as X.\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"The mean of shape (N, G). For backward usage or reference. Cannot be used as activations.\",\n        \"name\": \"mean\"\n      },\n      {\n        \"description\": \"The std of shape (N, G). For backward usage or reference. Cannot be used as activations.\",\n        \"name\": \"std\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GroupNormGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GRUUnit\",\n    \"description\": \"\\nGRUUnit computes the activations of a standard GRU,\\nin a sequence-length aware fashion.\\n\\nConcretely, given the (fused) inputs X (TxNxD), the previous hidden\\nstate (NxD), and the sequence lengths (N), computes the GRU\\nactivations, avoiding computation if the input is invalid (as in, the\\nvalue at X[t][n] >= seqLengths[n].\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Bool to determine if hidden state is zeroes or passed along for timesteps past the given sequence_length.\",\n        \"name\": \"drop_states\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"When false, the sequence lengths input is left out, and all following inputs are shifted left by one.\",\n        \"name\": \"sequence_lengths\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The new GRU hidden state calculated by this op.\",\n        \"name\": \"hidden\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GRUUnitGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"When false, the sequence lengths input is left out, and all following inputs are shifted left by one.\",\n        \"name\": \"sequence_lengths\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GT\",\n    \"description\": \"\\nPerforms element-wise greater than comparison **>** (with limited broadcast support).\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"GT\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([1, 5, 2, 9, 12, 3]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([1, 3, 4, 9, 12, 8]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA: [ 1  5  2  9 12  3]\\nB: [ 1  3  4  9 12  8]\\nC: [False  True False False False False]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor with same dimensions as `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfFloatToFused8BitRowwiseQuantized\",\n    \"description\": \"\\nApplies 8-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 8-bit number between 0 and\\n255. To later de-quantize values, the scale (range / 255) and offset\\n(bias) are stored alongside the data. More precisely, each row contains\\nint8 elements for each quantized element, and the last 8 bytes\\nof each row in the output matrix are a float storing the scale\\nfollowed by another float containing the scale.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float16 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfFloatToFused8BitRowwiseQuantizedHalfScaleBias\",\n    \"description\": \"\\nApplies 8-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 8-bit number between 0 and\\n255. To later de-quantize values, the scale (range / 255) and offset\\n(bias) are stored alongside the data. More precisely, each row contains\\nint8 elements for each quantized element, and the last 4 bytes\\nof each row in the output matrix are a float storing the scale\\nfollowed by another float containing the scale.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float16 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfToFloat\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfToFused2BitFakeRowwiseQuantized\",\n    \"description\": \"\\nApplies 2-bit row-wise fake quantization to a tensor of half floats.\\nThe output looks like an int8 rowwise quantized blob with\\nscale and biases in half float.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float16 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfToFused2BitRowwiseQuantized\",\n    \"description\": \"\\nApplies 2-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 2-bit number between 0 and\\n3. To later de-quantize values, the scale (range / 3) and zero_point\\nare stored alongside the data. More precisely, each row first has quantized\\nvalues, and then 2-byte fp16 scale and 2-byte zero_offset.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float16 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfToFused4BitFakeRowwiseQuantized\",\n    \"description\": \"\\nApplies 4-bit row-wise fake quantization to a tensor of half floats.\\nThe output looks like an int8 rowwise quantized blob with\\nscale and biases in half float.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float16 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HalfToFused4BitRowwiseQuantized\",\n    \"description\": \"\\nApplies 4-bit row-wise quantization by determining the range\\n(maximum - minimum) and offset (minimum value) of each row in the input\\nmatrix, and then scaling each element to an 4-bit number between 0 and\\n15. To later de-quantize values, the scale (range / 15) and zero_point\\nare stored alongside the data. More precisely, each row first has quantized\\nvalues, and then 2-byte fp16 scale and 2-byte zero_offset.)\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Float16 input data\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Fused scale, bias and quantized data\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HardSigmoid\",\n    \"description\": \"\\nApplies hard sigmoid operation to the input data element-wise.\\nThe HardSigmoid operation takes one input $X$, produces one output $Y$, and is defined as:\\n\\n$$Y = max(0,min(1,x * alpha + beta))$$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/hard_sigmoid_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/hard_sigmoid_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"HardSigmoid\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    alpha = 0.2,\\n    beta = 0.5,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(5).astype(np.float32))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"sigmoid:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput: [ 1.5744036   0.31632107  1.7842269   1.4450722  -2.1726978 ]\\nhard_sigmoid: [ 0.81488073,  0.56326419,  0.85684538,  0.78901446,  0.06546044]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"float: the slope of the function. Defaults to 0.2\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"float: the bias value of the function. Defaults to 0.5\",\n        \"name\": \"beta\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor with same shape as input\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HardSigmoidGradient\",\n    \"description\": \"\\nHardSigmoidGradient takes both Y and dY as well as an argument alpha and uses\\nthis to update dX according to the chain rule and derivatives of the hard\\nsigmoid function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HasElements\",\n    \"description\": \"\\nThe *HasElements* op accepts a single or multiple input tensors, and produces a single boolean output $has\\\\_elements$. The output is *True* if and only if any of the input tensor has size > 0. Note, this op is the opposite of the *IsEmpty* op.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"HasElements\\\",\\n    [\\\"tensor\\\"],\\n    [\\\"has_elements\\\"],\\n)\\n\\n// Use a not-empty tensor\\nworkspace.FeedBlob(\\\"tensor\\\", np.random.randn(2, 2).astype(np.float32))\\nprint(\\\"tensor:\\\\n\\\", workspace.FetchBlob(\\\"tensor\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"has_elements: \\\", workspace.FetchBlob(\\\"has_elements\\\"),\\\"\\\\n\\\")\\n\\n// Use an empty tensor\\nworkspace.FeedBlob(\\\"tensor\\\", np.empty(0))\\nprint(\\\"tensor:\\\\n\\\", workspace.FetchBlob(\\\"tensor\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"has_elements: \\\", workspace.FetchBlob(\\\"has_elements\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ntensor:\\n [[ 0.6116506  -0.54433197]\\n [ 0.19406661 -0.7338629 ]]\\nhas_elements:  True\\n\\ntensor:\\n []\\nhas_elements:  False\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor to check for elements.\",\n        \"name\": \"tensor\"\n      },\n      {\n        \"description\": \"List of input data tensors to check for elements.\",\n        \"name\": \"X1, X2, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output scalar boolean tensor. True if input has size > 0.\",\n        \"name\": \"has_elements\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HasScope\",\n    \"description\": \"\\nChecks whether scope blob has any saved scopes left\\n    \",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HeatmapMaxKeypoint\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Histogram\",\n    \"description\": \"\\n            Computes a histogram for values in the given list of tensors.\\n            For logging activation histograms for post-hoc analyses, consider using the\\n            HistogramObserver observer.\\n            For iteratively computing a histogram for all input tensors encountered through\\n            history, consider using the AccumulateHistogram operator.\\n            \",\n    \"attributes\": [\n      {\n        \"description\": \"length-(k + 1) sequence of float values wherein the i-th element represents the inclusive left boundary of the i-th bin for i in [0, k - 1] and the exclusive right boundary of the (i-1)-th bin for i in [1, k].\",\n        \"name\": \"bin_edges\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* List of input tensors.\",\n        \"name\": \"X1, X2, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of length k, wherein the i-th element expresses the count of tensor values that fall within range [bin_edges[i], bin_edges[i + 1])\",\n        \"name\": \"histogram\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HSoftmax\",\n    \"description\": \"\\nHierarchical softmax is an operator which approximates the softmax operator\\nwhile giving significant training speed gains and reasonably comparable\\nperformance. In this operator, instead of calculating the probabilities of all\\nthe classes, we calculate the probability of each step in the path from root to\\nthe target word in the hierarchy.\\n\\nThe operator takes a 2-D tensor (Tensor) containing a batch of layers, a\\nset of parameters represented by the weight matrix and bias terms, and a 1-D\\ntensor (Tensor) holding labels, or the indices of the target class. The\\nhierarchy has to be specified as an argument to the operator.\\n\\nThe operator returns a 1-D tensor holding the computed log probability of the\\ntarget class and a 2-D tensor of intermediate outputs (from the weight matrix\\nand softmax from each step in the path from root to target class) which will be\\nused by the gradient operator to compute gradients for all samples in the batch.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Serialized HierarchyProto string containing list of vocabulary words and their paths from root of hierarchy to the leaf\",\n        \"name\": \"hierarchy\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data from previous layer\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"2D blob containing 'stacked' fully connected weight matrices. Each node in the hierarchy contributes one FC weight matrix if it has children nodes. Dimension is N*D, D is input dimension of data (X), N is sum of all output dimensions, or total number of nodes (excl root)\",\n        \"name\": \"W\"\n      },\n      {\n        \"description\": \"1D blob with N parameters\",\n        \"name\": \"b\"\n      },\n      {\n        \"description\": \"int word_id of the target word\",\n        \"name\": \"labels\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D of log probability outputs, one per sample\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"Extra blob to store the intermediate FC and softmax outputs for each node in the hierarchical path of a word. The outputs from samples are stored in consecutive blocks in the forward pass and are used in reverse order in the backward gradientOp pass\",\n        \"name\": \"intermediate_output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HSoftmaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HSoftmaxSearch\",\n    \"description\": \"\\nHSoftmaxSearch is an operator to generate the most possible paths given a\\nwell-trained model and input vector. Greedy algorithm is used for pruning the\\nsearch tree.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Serialized TreeProto string containing a tree including all intermidate nodes and leafs. All nodes must have names for correct outputs\",\n        \"name\": \"tree\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"beam used for pruning tree. The pruning algorithm is that only children, whose score is smaller than parent's score puls beam, will be propagated.\",\n        \"name\": \"beam\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Number of nodes in outputs\",\n        \"name\": \"topN\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data from previous layer\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The matrix trained from Softmax Ops\",\n        \"name\": \"W\"\n      },\n      {\n        \"description\": \"The bias trained from Softmax Ops\",\n        \"name\": \"b\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The name of selected nodes and leafs. For nodes, it will be the name defined in the tree. For leafs, it will be the index of the word in the tree.\",\n        \"name\": \"Y_names\"\n      },\n      {\n        \"description\": \"The corresponding scores of Y_names\",\n        \"name\": \"Y_scores\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"HuffmanTreeHierarchy\",\n    \"description\": \"\\nHuffmanTreeHierarchy is an operator to generate huffman tree hierarchy given\\nthe input labels. It returns the tree as serialized HierarchyProto\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The number of classes used to build the hierarchy.\",\n        \"name\": \"num_classes\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The labels vector\",\n        \"name\": \"Labels\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Huffman coding hierarchy of the labels\",\n        \"name\": \"Hierarch\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"If\",\n    \"description\": \"\\n'If' control operator, first input is a scalar boolean blob that stores condition\\nvalue. Accepts 'then_net' (required) and 'else_net' (optional) arguments for 'then' and\\n'else' subnets respectively. Subnets are executed in the same workspace as 'If'.\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"Net executed when condition is true\",\n        \"name\": \"then_net\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Net executed when condition is false (optional)\",\n        \"name\": \"else_net\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Scalar boolean condition\",\n        \"name\": \"condition\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Im2Col\",\n    \"description\": \"The Im2Col operator from Matlab.\",\n    \"inputs\": [\n      {\n        \"description\": \"4-tensor in NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4-tensor. For NCHW: N x (C x kH x kW) x outH x outW.For NHWC: N x outH x outW x (kH x kW x C\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IncrementPut\",\n    \"description\": \"\\n    Consume a value and pushes it to the global stat registry as an sum.\\n\\n    Github Links:\\n    - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_put_ops.cc\\n\\n        \",\n    \"attributes\": [\n      {\n        \"description\": \"(*str*): name of the stat. If not present, then uses name of input blob\",\n        \"name\": \"name\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int64_t*): number to multiply input values by (used when inputting floats, as stats can only receive integers\",\n        \"name\": \"magnitude_expand\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*boolean*): whether or not to clamp inputs to the max inputs allowed\",\n        \"name\": \"bound\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*float*): Optionally provide a default value for receiving empty tensors\",\n        \"name\": \"default_value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<number>`*): A scalar tensor, representing any numeric value\",\n        \"name\": \"value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IndexFreeze\",\n    \"description\": \"\\nFreezes the given index, disallowing creation of new index entries.\\nShould not be called concurrently with IndexGet.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The input handle.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IndexGet\",\n    \"description\": \"\\nGiven an index handle and a tensor of keys, return an Int tensor of same shape\\ncontaining the indices for each of the keys. If the index is frozen, unknown\\nentries are given index 0. Otherwise, new entries are added into the index.\\nIf an insert is necessary but max_elements has been reached, fail.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handle\"\n      },\n      {\n        \"description\": \"Tensor of keys to be looked up.\",\n        \"name\": \"keys\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Indices for each of the keys.\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IndexHash\",\n    \"description\": \"\\nThis operator translates a list of indices into a list of hashed indices.\\nA seed can be fed as an argument to change the behavior of the hash function.\\nIf a modulo is specified, all the hashed indices will be modulo the\\nspecified number. All input and output indices are enforced to be positive.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"seed for the hash function\",\n        \"name\": \"seed\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"must be > 0, hashed ids will be modulo this number\",\n        \"name\": \"modulo\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input feature indices.\",\n        \"name\": \"Indices\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Hashed feature indices.\",\n        \"name\": \"HashedIndices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IndexLoad\",\n    \"description\": \"\\nLoads the index from the given 1-D tensor. Elements in the tensor will be given\\nconsecutive indexes starting at 1. Fails if tensor contains repeated elements.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"If set, skips the first entry of the tensor. This allows to load tensors that are aligned with an embedding, where the first entry corresponds to the default 0 index entry.\",\n        \"name\": \"skip_first_entry\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handle\"\n      },\n      {\n        \"description\": \"1-D tensor with elements starting with index 1.\",\n        \"name\": \"items\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The input handle.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IndexSize\",\n    \"description\": \"\\nReturns the number of entries currently present in the index.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Scalar int64 tensor with number of entries.\",\n        \"name\": \"items\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IndexStore\",\n    \"description\": \"\\nStores the keys of this index in a 1-D tensor. Since element 0 is reserved\\nfor unknowns, the first element of the output tensor will be element of index 1.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor with elements starting with index 1.\",\n        \"name\": \"items\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"InferenceLSTM\",\n    \"attributes\": [\n      {\n        \"description\": \"(*long*): number of layers in the lstm stack\",\n        \"name\": \"num_layers\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*bool*): whether the cells have biases or not\",\n        \"name\": \"has_biases\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*bool*): whether the batch is at dim 0\",\n        \"name\": \"batch_first\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*bool*): if bidirectional\",\n        \"name\": \"bidirectional\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"the output of the last layer of lstm\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"hidden state at t = seq_len\",\n        \"name\": \"hidden\"\n      },\n      {\n        \"description\": \"cell state at t = seq_len\",\n        \"name\": \"cell\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"InstanceNorm\",\n    \"description\": \"\\nThe *InstanceNorm* op applies Instance Normalization over a 4D input as described in [Instance Normalization: The Missing Ingredient for Fast Stylization](https://arxiv.org/abs/1607.08022).\\n\\n$$output = \\\\frac{input-\\\\mu_{input}}{\\\\sqrt{\\\\sigma_{input}^2} + \\\\epsilon}*scale + bias$$\\n\\nNotice, two of the outputs are optional so there are three output cases for this op. Case 1: output; Case 2: output, saved_mean; Case 3: output, saved_mean, saved_inv_stdev.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/instance_norm_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/instance_norm_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"InstanceNorm\\\",\\n    [\\\"input\\\", \\\"scale\\\", \\\"bias\\\"],\\n    [\\\"output\\\"],\\n    epsilon=1e-5,\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.random.randn(2, 1, 3, 3).astype(np.float32))\\nprint(\\\"input:\\\\n\\\", workspace.FetchBlob(\\\"input\\\"), \\\"\\\\n\\\")\\n\\nworkspace.FeedBlob(\\\"scale\\\", np.array([1.5]).astype(np.float32))\\nprint(\\\"scale: \\\", workspace.FetchBlob(\\\"scale\\\"))\\n\\nworkspace.FeedBlob(\\\"bias\\\", np.array([1.]).astype(np.float32))\\nprint(\\\"bias: \\\", workspace.FetchBlob(\\\"bias\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output:\\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput:\\n [[[[ 0.97856593 -1.1832817  -0.2540021 ]\\n   [-1.3315694  -0.7485018   0.3787225 ]\\n   [-0.6826597  -1.4637762   0.57116514]]]\\n\\n\\n [[[-0.44948956  0.85544354 -0.9315333 ]\\n   [-0.37202677 -0.22266895 -0.27194235]\\n   [ 0.4948163  -0.7296504   1.3393803 ]]]]\\n\\nscale:  [1.5]\\nbias:  [1.]\\noutput:\\n [[[[ 3.5017493  -0.3791256   1.2890853 ]\\n   [-0.6453266   0.40137637  2.4249308 ]\\n   [ 0.5195738  -0.8826599   2.7703972 ]]]\\n\\n\\n [[[ 0.12639964  2.856744   -0.8821926 ]\\n   [ 0.28847694  0.60098207  0.49788612]\\n   [ 2.1021945  -0.45978796  3.869297  ]]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1e-05,\n        \"description\": \"The epsilon value to use to avoid division by zero.\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": \"NCHW\",\n        \"description\": \"Specifies the order of the input data blob, where $N$ is batch size, $C$ is number of channels, $H$ is spatial height, and $W$ is spatial width. The only other valid option is \\\"NHWC\\\".\",\n        \"name\": \"order\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input 4-dimensional NCHW tensor to be operated on.\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"The input 1-dimensional scale tensor of size *C*.\",\n        \"name\": \"scale\"\n      },\n      {\n        \"description\": \"The input 1-dimensional bias tensor of size *C*.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output 4-dimensional tensor of the same shape as input.\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"(Optional) Saved mean used during training to speed up gradient computation. Should not be used for testing.\",\n        \"name\": \"saved_mean\"\n      },\n      {\n        \"description\": \"(Optional) Saved inverse stdev used during training to speed up gradient computation. Should not be used for testing.\",\n        \"name\": \"saved_inv_stdev\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"InstanceNormGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Add\",\n    \"description\": \"\\n    Performs element-wise binary Add (with no broadcast support).\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"Second operand. It should be of the same size as A.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Result, has same dimensions and type as A\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8AddRelu\",\n    \"description\": \"\\n    Performs element-wise binary Add (with no broadcast support). \\\"\\n    \\\"Output will go through rectified linear \\\"\\n    \\\"function, where y = max(0, x).\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"Second operand. It should be of the same size as A.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Result, has same dimensions and type as A\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8AveragePool\",\n    \"category\": \"Pool\",\n    \"description\": \"AveragePool \\nconsumes an input blob X and applies average pooling across the\\nthe blob according to kernel sizes, stride sizes, and pad lengths defined by the\\nConvPoolOpBase operator. Average pooling consisting of averaging all values of a\\nsubset of the input tensor according to the kernel size and downsampling the\\ndata into the output blob Y for further processing.\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor from the previous operator; dimensions depend on whether the NCHW or NHWC operators are being used. For example, in the former, the input has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. The corresponding permutation of dimensions is used in the latter case.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data tensor from average pooling across the input tensor. Dimensions will vary based on various kernel, stride, and pad sizes.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8AveragePoolRelu\",\n    \"description\": \"AveragePool \\nconsumes an input blob X and applies average pooling across the\\nthe blob according to kernel sizes, stride sizes, and pad lengths defined by the\\nConvPoolOpBase operator. Average pooling consisting of averaging all values of a\\nsubset of the input tensor according to the kernel size and downsampling the\\ndata into the output blob Y for further processing.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor from the previous operator; dimensions depend on whether the NCHW or NHWC operators are being used. For example, in the former, the input has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. The corresponding permutation of dimensions is used in the latter case.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data tensor from average pooling across the input tensor. Dimensions will vary based on various kernel, stride, and pad sizes. Output will go through rectified linear function, where y = max(0, x).\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8ChannelShuffle\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Concat\",\n    \"description\": \"Concatenate a list of tensors into a single tensor\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Which axis to concat on\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Pass 1 to add the axis specified in arg 'axis' to all input tensors\",\n        \"name\": \"add_axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Concatenated tensor\",\n        \"name\": \"concat_result\"\n      },\n      {\n        \"description\": \"The dimensions of the inputs.\",\n        \"name\": \"split_info\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Conv\",\n    \"category\": \"Layer\",\n    \"description\": \"\\nThe convolution operator consumes an input vector, a filter blob\\nand a bias blob and computes the output. \\n[Only NHWC order is supported now]Note that other parameters, such as the stride and\\nkernel size, or the pads' sizes in each direction are not necessary for input\\nbecause they are provided by the ConvPoolOpBase operator. Various dimension\\nchecks are done implicitly, and the sizes are specified in the Input docs for\\nthis operator. As is expected, the filter is convolved with a subset of the\\nimage and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nconv_op_impl.h is the templated implementation of the conv_op.h file, which is\\nwhy they are separate files.\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"name\": \"pad\"\n      },\n      {\n        \"default\": 1,\n        \"name\": \"stride\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob from previous layer; has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and width. Note that this is for the NCHW usage. On the other hand, the NHWC Op has a different set of dimension constraints. \",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob that will be used in the convolutions; has size (M x C x kH x kW), where C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the convolution; has size (M).\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the convolution. The output dimensions are functions of the kernel size, stride size, and pad lengths.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8ConvRelu\",\n    \"description\": \"\\nThe convolution operator consumes an input vector, a filter blob\\nand a bias blob and computes the output. \\n[Only NHWC order is supported now]Note that other parameters, such as the stride and\\nkernel size, or the pads' sizes in each direction are not necessary for input\\nbecause they are provided by the ConvPoolOpBase operator. Various dimension\\nchecks are done implicitly, and the sizes are specified in the Input docs for\\nthis operator. As is expected, the filter is convolved with a subset of the\\nimage and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nconv_op_impl.h is the templated implementation of the conv_op.h file, which is\\nwhy they are separate files.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob from previous layer; has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and width. Note that this is for the NCHW usage. On the other hand, the NHWC Op has a different set of dimension constraints. \",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob that will be used in the convolutions; has size (M x C x kH x kW), where C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the convolution; has size (M).\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the convolution. The output dimensions are functions of the kernel size, stride size, and pad lengths. Output will go through rectified linear function, where y = max(0, x).\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8ConvTranspose\",\n    \"description\": \"\\nThe transposed convolution consumes an input vector, the filter blob, and\\nthe bias blob, and computes the output. Note that other parameters, such as\\nthe stride and kernel size, or the pads' sizes in each direction are not\\nnecessary for input because they are provided by the\\nConvTransposeUnpoolOpBase operator. Various dimension checks are done\\nimplicitly, and the sizes are specified in the Input docs for this operator.\\nAs is expected, the filter is deconvolved with a subset of the\\nimage and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nconv_transpose_op_impl.h is the templated implementation of the\\nconv_transpose_op.h file, which is why they are separate files.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob from previous layer; has size (N x H x W x C), where N is the batch size, C is the number of channels, and H and W are the height and width. Note that NHWC is supported now\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"The filter blob that will be used in the transposed convolution; has size (M x kH x kW x C), where C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the convolution;has size (C). Optional, if not passed, will treat it as all 0.\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the transposed convolution. The output dimensions are functions of the kernel size, stride size, and pad lengths.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Dequantize\",\n    \"inputs\": [\n      {\n        \"description\": \"Int8 Tensor qX.\",\n        \"name\": \"qX\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"FP32 Tensor that represents mapped real value of qX.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8FC\",\n    \"category\": \"Layer\",\n    \"description\": \"\\nComputes the result of passing an input vector X into a fully\\nconnected layer with 2D weight matrix W and 1D bias vector b. That is,\\nthe layer computes Y = X * W^T + b, where X has size (M x K),\\nW has size (N x K), b has size (N), and Y has size (M x N),\\nwhere M is often the batch size.\\n\\n\\nNOTE: X does not need to explicitly be a 2D vector; rather, it will be\\ncoerced into one. For an arbitrary n-dimensional tensor\\nX \\\\in [a_0, a_1 * ... * a_{n-1}]. Only this case is supported!\\nLastly, even though b is a 1D vector of size N, it is copied/resized to\\nbe size (M x N) implicitly and added to each vector in the batch.\\nEach of these dimensions must be matched correctly, or else the operator\\nwill throw errors.\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"input tensor that's coerced into a 2D matrix of size (MxK) as described above\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"A tensor that is coerced into a 2D blob of size (KxN) containing fully connected weight matrix\",\n        \"name\": \"W\"\n      },\n      {\n        \"description\": \"1D blob containing bias vector\",\n        \"name\": \"b\"\n      },\n      {\n        \"description\": \"Optional scale quantization param computed on activation histogram dataWill overwrite Y_scale argument if specified\",\n        \"name\": \"Scale qparam\"\n      },\n      {\n        \"description\": \"Optionsl zero-point quantization param computed on activation dataWill overwrite Y_zero_point argument if specified\",\n        \"name\": \"Zero-point qparam\"\n      },\n      {\n        \"description\": \"Optional Qparam blob that contains quant param computed on activation histogram dataWill overwrite Y_scale and Y_zero_point argument if specified\",\n        \"name\": \"Qparam\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2D output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8FCPackWeight\",\n    \"description\": \"Prepack weight for Int8FC\",\n    \"attributes\": [\n      {\n        \"description\": \"See FC operator\",\n        \"name\": \"axis_w\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default false. Per output channel quantization\",\n        \"name\": \"quantize_channelwise\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default false. Store unpacked quantized weights to W_q.original_tensor\",\n        \"name\": \"save_unpacked_weights\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The scale of input activation tensor. Only meaningful when bias is provided (NOTE: this is not the scale of weight\",\n        \"name\": \"in_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Weight tensor in KRSC layout\",\n        \"name\": \"W\"\n      },\n      {\n        \"description\": \"Bias tensor\",\n        \"name\": \"b\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Weight/bias tensor in a packed format with type Int8FCDNNLowPPackedWeightBlob\",\n        \"name\": \"W_q\"\n      },\n      {\n        \"description\": \"Bias int32 quantized tensor\",\n        \"name\": \"B_q\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Flatten\",\n    \"description\": \"\\nFlattens the input tensor into a 2D matrix. If input tensor has shape\\n(d_0, d_1, ... d_n) then the output will have shape\\n(d_0 X d_1 ... d_(axis-1), d_axis X d_(axis+1) ... X dn)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(Default to 1) Indicate up to which input dimensions (exclusive) should be flattened to the outer dimension of the output\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"A Int8 tensor of rank >= axis.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"A 2D Int8 tensor with the contents of the input tensor, with input dimensions up to axis flattened to the outer dimension of the output and remaining input dimensions flattened into the inner dimension of the output.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8GenQuantParams\",\n    \"description\": \"Operator wrapper for generating int8 tensor quantization parameters given the input data and quant scheme\",\n    \"inputs\": [\n      {\n        \"description\": \"The input data, or last N samples of the output activations.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Int8QuantSchemeBlob that specifies the quantization kind and preserve_sparsity options when generating the quant params.\",\n        \"name\": \"quant_scheme\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Int8QuantParamsBlob that contains the scale and zero_point info in TensorQuantizationParams type.\",\n        \"name\": \"quant_param\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8GivenIntTensorFill\",\n    \"description\": \"\\n    Creates quantized tensor of type int32 with scale and zero point info.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Input array of type int32\",\n        \"name\": \"values\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Input tensor shape\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"An Int8TensorCPU with scale and zero point info\",\n        \"name\": \"Tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8GivenTensorFill\",\n    \"description\": \"\\n    Creates quantized tensor of type char(byte) with scale and zero point info.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Input array of type char(byte)\",\n        \"name\": \"values\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Input tensor shape\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"An Int8TensorCPU with scale and zero point info\",\n        \"name\": \"Tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8LeakyRelu\",\n    \"description\": \"\\nLeakyRelu takes input data (Tensor<T>) and an argument alpha, and produces one\\noutput data (Tensor<T>) where the function `f(x) = alpha * x for x < 0`,\\n`f(x) = x for x >= 0`, is applied to the data tensor elementwise.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Coefficient of leakage, default value is 0.01\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8MaxPool\",\n    \"description\": \"MaxPool \\nconsumes an input blob X and applies max pooling across the\\nthe blob according to kernel sizes, stride sizes, and pad lengths defined by the\\nConvPoolOpBase operator. Max pooling consisting of taking the maximum value of a\\nsubset of the input tensor according to the kernel size and downsampling the\\ndata into the output blob Y for further processing.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor from the previous operator; dimensions depend on whether the NCHW or NHWC operators are being used. For example, in the former, the input has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. The corresponding permutation of dimensions is used in the latter case.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data tensor from max pooling across the input tensor. Dimensions will vary based on various kernel, stride, and pad sizes. Output will go through rectified linear\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8MaxPoolRelu\",\n    \"description\": \"MaxPool \\nconsumes an input blob X and applies max pooling across the\\nthe blob according to kernel sizes, stride sizes, and pad lengths defined by the\\nConvPoolOpBase operator. Max pooling consisting of taking the maximum value of a\\nsubset of the input tensor according to the kernel size and downsampling the\\ndata into the output blob Y for further processing.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor from the previous operator; dimensions depend on whether the NCHW or NHWC operators are being used. For example, in the former, the input has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. The corresponding permutation of dimensions is used in the latter case.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data tensor from max pooling across the input tensor. Dimensions will vary based on various kernel, stride, and pad sizes. Output will go through rectified linearfunction, where y = max(0, x).\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Quantize\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"FP32 Tensor X.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Optional scale quantization param computed on activation histogram dataWill overwrite Y_scale argument if specified\",\n        \"name\": \"Scale qparam\"\n      },\n      {\n        \"description\": \"Optionsl zero-point quantization param computed on activation dataWill overwrite Y_zero_point argument if specified\",\n        \"name\": \"Zero-point qparam\"\n      },\n      {\n        \"description\": \"Optional Qparam blob that contains quant param computed on activation histogram dataWill overwrite Y_scale and Y_zero_point argument if specified\",\n        \"name\": \"Qparam\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Int8 Tensor qX representing X with linear quantization.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Relu\",\n    \"category\": \"Activation\",\n    \"description\": \"\\nRelu takes one input data (Tensor<T>) and produces one output data\\n(Tensor<T>) where the rectified linear function, y = max(0, x), is applied to\\nthe tensor elementwise.\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Reshape\",\n    \"description\": \"\\nReshape the input tensor similar to numpy.reshape.\\n\\nIt takes a tensor as input and an optional tensor specifying the new shape.\\nWhen the second input is absent, an extra argument `shape` must be specified.\\nIt outputs the reshaped tensor as well as the original shape.\\n\\nAt most one dimension of the new shape can be -1. In this case, the value is\\ninferred from the size of the tensor and the remaining dimensions. A dimension\\ncould also be 0, in which case the actual dimension value is going to be copied\\nfrom the input tensor.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"New shape\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"An input tensor.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"New shape.\",\n        \"name\": \"new_shape\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reshaped data.\",\n        \"name\": \"reshaped\"\n      },\n      {\n        \"description\": \"Original shape.\",\n        \"name\": \"old_shape\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8ResizeNearest\",\n    \"description\": \"\\nResizes the spatial dimensions of the input using nearest neighbor\\ninterpolation. The `width_scale` and `height_scale` arguments\\ncontrol the size of the output, which is given by:\\noutput_width = floor(input_width * width_scale)\\noutput_height = floor(output_height * height_scale)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output dimensions (HxW). If specified this takes precedence over scale values.\",\n        \"name\": \"output_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input Int8 tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output Int8 tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8RoIAlign\",\n    \"description\": \"\\nRegion of Interest (RoI) align operation as used in Mask R-CNN.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) default 1.0; Spatial scale of the input feature map X relative to the input image. E.g., 0.0625 if X has a stride of 16 w.r.t. the input image.\",\n        \"name\": \"spatial_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default 1; Pooled output Y's height.\",\n        \"name\": \"pooled_h\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default 1; Pooled output Y's width.\",\n        \"name\": \"pooled_w\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default -1; number of sampling points in the interpolation grid used to compute the output value of each pooled output bin. If > 0, then exactly sampling_ratio x sampling_ratio grid points are used. If <= 0, then an adaptive number of grid points are used (computed as ceil(roi_width / pooled_w), and likewise for height).\",\n        \"name\": \"sampling_ratio\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D Int8 Tensor feature map input of shape (N, C, H, W).\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"2D input of shape (R, 4 or 5) specifying R RoIs representing: batch index in [0, N - 1], x1, y1, x2, y2. The RoI coordinates are in the coordinate system of the input image. For inputs corresponding to a single image, batch index can be excluded to have just 4 columns.\",\n        \"name\": \"RoIs\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D Int8 Tensor output of shape (R, C, pooled_h, pooled_w). The r-th batch element is a pooled feature map cooresponding to the r-th RoI.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Sigmoid\",\n    \"description\": \"\\nApply the Sigmoid function element-wise to the input tensor. This is often used\\nas a non-linear activation function in a neural network. The sigmoid function is\\ndefined as:\\n\\n$$Sigmoid(x) = \\\\frac{1}{1+\\\\exp(-x)}$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sigmoid_op.cc\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input tensor that's coerced into a 2D matrix of size (NxD) as described above.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The sigmoid normalized output values with the same shape as input tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Slice\",\n    \"description\": \"\\nProduces a slice of the input Int8 tensor. Currently, only slicing in a single\\ndimension is supported.\\nSlices are passed as 2 1D vectors or as two keyword argument lists with starting\\nand end indices for each dimension of the input `data` tensor. If a negative\\nvalue is passed for any of the start or end indices, it represents the number of\\nelements before the end of that dimension. End indices are non-inclusive unless\\nnegative (end index -1 means up to and including the last element).\\n\\n\\nExample:\\n\\n  data = [\\n      [1, 2, 3, 4],\\n      [5, 6, 7, 8],\\n  ]\\n  starts = [0, 1]\\n  ends = [-1, 3]\\n\\n  result = [\\n      [2, 3],\\n      [6, 7],\\n  ]\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"List of starting indices\",\n        \"name\": \"starts\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"List of ending indices\",\n        \"name\": \"ends\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(Optional) The dimension to slice over. If specified start_idx and end_idx should also be given and it takes precedence over starts and ends\",\n        \"name\": \"dim\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(Optional) The dimension to start slice from. Default is 0\",\n        \"name\": \"start_idx\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(Optional) The dimension to end the slice. Default is -1\",\n        \"name\": \"end_idx\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Int8 Tensor of data to extract slices from.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"1D tensor: start-indices for each dimension of data.\",\n        \"name\": \"starts\"\n      },\n      {\n        \"description\": \"1D tensor: end-indices for each dimension of data.\",\n        \"name\": \"ends\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Sliced Int8 data tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Softmax\",\n    \"category\": \"Activation\",\n    \"description\": \"\\nThe operator computes the softmax normalized values for each layer in the batch\\n of the given input. The input is a 2-D tensor (Tensor<float>) of size\\n(batch_size x input_feature_dimensions). The output tensor has the same shape\\nand contains the softmax normalized values of the corresponding input.\\n\\nX does not need to explicitly be a 2D vector; rather, it will be\\ncoerced into one. For an arbitrary n-dimensional tensor\\nX \\\\in [a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1}] and k is\\nthe axis provided, then X will be coerced into a 2-dimensional tensor with\\ndimensions [a_0 * ... * a_{k-1}, a_k * ... * a_{n-1}]. For the default\\ncase where axis=1, this means the X tensor will be coerced into a 2D tensor\\nof dimensions [a_0, a_1 * ... * a_{n-1}], where a_0 is often the batch size.\\nIn this situation, we must have a_0 = N and a_1 * ... * a_{n-1} = D.\\nEach of these dimensions must be matched correctly, or else the operator\\nwill throw errors.\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default to 1; describes the axis of the inputs when coerced to 2D; defaults to one because the 0th axis most likely describes the batch_size\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input tensor that's coerced into a 2D matrix of size (NxD) as described above.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The softmax normalized output values with the same shape as input tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Sum\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8SumRelu\",\n    \"attributes\": [\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Int8Transpose\",\n    \"description\": \"\\nTranspose the input tensor by permuting the axes of the input according\\nto the `axes` argument. Similar to numpy's\\n[transpose](https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html)\\nfunction.\\n\\nFor example, when axes=(1, 0, 2), given an input tensor of shape\\n(1, 2, 3), the output shape will be (2, 1, 3).\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Order to permute axes of input tensor. Reverses the dimensions by default.\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization scale\",\n        \"name\": \"Y_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Output tensor quantization offset\",\n        \"name\": \"Y_zero_point\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Transposed output\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IntegralImage\",\n    \"description\": \"\\nComputes an integral image, which contains the sum of pixel values within\\nan image vertically and horizontally. This integral image can then be used\\nwith other detection and tracking techniques.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Images tensor of the form (N, C, H, W)\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Integrated image of the form (N, C, H+1, W+1)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IntegralImageGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IntIndexCreate\",\n    \"description\": \"\\nCreates a dictionary that maps int32 keys to consecutive integers\\nfrom 1 to max_elements. Zero is reserved for unknown keys.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Max number of elements, including the zero entry.\",\n        \"name\": \"max_elements\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IsEmpty\",\n    \"description\": \"\\nThe *IsEmpty* op accepts a single input $tensor$, and produces a single boolean output $is\\\\_empty$. The output is *True* if and only if $tensor$ has size == 0.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"IsEmpty\\\",\\n    [\\\"tensor\\\"],\\n    [\\\"is_empty\\\"],\\n)\\n\\n// Use a not-empty tensor\\nworkspace.FeedBlob(\\\"tensor\\\", np.random.randn(2, 2).astype(np.float32))\\nprint(\\\"tensor:\\\\n\\\", workspace.FetchBlob(\\\"tensor\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"is_empty: \\\", workspace.FetchBlob(\\\"is_empty\\\"),\\\"\\\\n\\\")\\n\\n// Use an empty tensor\\nworkspace.FeedBlob(\\\"tensor\\\", np.empty(0))\\nprint(\\\"tensor:\\\\n\\\", workspace.FetchBlob(\\\"tensor\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"is_empty: \\\", workspace.FetchBlob(\\\"is_empty\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ntensor:\\n [[ 0.26018378  0.6778789 ]\\n [-1.3097627  -0.40083608]]\\nis_empty:  False\\n\\ntensor:\\n []\\nis_empty:  True\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor to check if empty.\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output scalar boolean tensor. True if input has size == 0.\",\n        \"name\": \"is_empty\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IsMemberOf\",\n    \"description\": \"\\nThe *IsMemberOf* op takes an input tensor *X* and a list of values as argument, and produces one output data tensor *Y*. The output tensor is the same shape as *X* and contains booleans. The output is calculated as the function *f(x) = x in value* and is applied to *X* elementwise.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/elementwise_logical_ops.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/elementwise_logical_ops.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"IsMemberOf\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    value=[0,2,4,6,8],\\n)\\n\\n// Use a not-empty tensor\\nworkspace.FeedBlob(\\\"X\\\", np.array([0,1,2,3,4,5,6,7,8]).astype(np.int32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y: \\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n// value=[0,2,4,6,8]\\n\\nX:\\n [0 1 2 3 4 5 6 7 8]\\nY:\\n [ True False  True False  True False  True False  True]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of values to check for membership.\",\n        \"name\": \"value\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The data type for the elements of the output tensor. Strictly must be one of the types from DataType enum in TensorProto.\",\n        \"name\": \"dtype\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor of any shape\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor (same size as X containing booleans)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"IsNaN\",\n    \"description\": \"Returns a new tensor with boolean elements representing if each element is NaN or not.\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to check for nan\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing a 1 at each location of NaN elements.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Iter\",\n    \"description\": \"\\nStores a singe integer, that gets incremented on each call to Run().\\nUseful for tracking the iteration count during SGD, for example.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"KeySplit\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"KeyValueToMap\",\n    \"description\": \"Convert key and value blob pairs into a map blob\",\n    \"inputs\": [\n      {\n        \"description\": \"Blob reference to the key\",\n        \"name\": \"key blob\"\n      },\n      {\n        \"description\": \"Blob reference to the value\",\n        \"name\": \"value blob\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Blob reference to the map\",\n        \"name\": \"map blob\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"L1Distance\",\n    \"description\": \"\\nComputes the row-wise L1 Distance between the two input tensors $X$ and $Y$, which is defined as\\n\\n$$L1Distance(\\\\mathbf{x},\\\\mathbf{y}) = \\\\sum_{i}\\\\mid x_i - y_i\\\\mid$$\\n\\nNote, both inputs must either be 1-dimensional or 2-dimensional and both must have the same shape. The output $Z$ will be 1-dimensional regardless and its length will equal the number of rows in the inputs.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/distance_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/distance_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"L1Distance\\\",\\n    [\\\"X\\\", \\\"Y\\\"],\\n    [\\\"Z\\\"]\\n)\\n\\n// Create X\\nX = 5*np.ones((1, 4))\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Create Y\\nY = np.ones((1, 4))\\nprint(\\\"Y:\\\\n\\\",Y)\\n\\n// Feed X & Y into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", Y.astype(np.float32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Z:\\\\n\\\", workspace.FetchBlob(\\\"Z\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[5. 5. 5. 5.]]\\nY:\\n [[1. 1. 1. 1.]]\\nZ:\\n [16.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"First input tensor. (1D or 2D)\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Second input tensor. (must have the same shape as $X$)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor. One value for each row of the inputs.\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"L1DistanceGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LabelCrossEntropy\",\n    \"description\": \"\\nThis operator computes the cross entropy between a $NxD$ dimensional input data tensor $X$  and a one dimensional input label tensor $label$. The op produces a single length $N$ output tensor $Y$. Here, $N$ is considered the batch size and $D$ is the size of each element in the batch. In practice, it is most commonly used at the end of models as a part of the loss computation, after the SoftMax operator and before the AveragedLoss operator. The cross entropy operation is defined as follows\\n\\n$$Y_i = -log(X_{ij})$$\\n\\nwhere ($i$, $j$) is the classifier's prediction of the $j$th class (the correct one), and $i$ is the batch size. Each log has a lower limit for numerical stability.\\n\\nThe difference between *LabelCrossEntropy* and *CrossEntropy* is how the labels are specified. Here, the labels are a length $N$ list of integers, whereas in CrossEntropy the labels are a $NxD$ dimensional matrix of one hot label vectors. However, the results of computation should be the same, as shown in the two examples where ($i$, $j$) is the classifier's prediction of the $j$th class (the correct one), and $i$ is the batch size. Each log has a lower limit for numerical stability.\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/cross_entropy_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/cross_entropy_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LabelCrossEntropy\\\",\\n    [\\\"X\\\", \\\"label\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X: Sample softmax output for 5-class model\\nX = np.array([[.01, .05, .02, .02, .9],[.03, .1, .42, .05, .4]])\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Create label: Sample 1-hot ground truth label vectors\\nlabel = np.array([4,2])\\nprint(\\\"label:\\\\n\\\",label)\\n\\n// Feed X & label into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\nworkspace.FeedBlob(\\\"label\\\", label.astype(np.int32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[0.01 0.05 0.02 0.02 0.9 ]\\n [0.03 0.1  0.42 0.05 0.4 ]]\\nlabel:\\n [4 2]\\nY:\\n [0.10536055 0.8675006 ]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor which is almost always the result of a softmax operation. $X$ is a 2D array of size $NxD$, where $N$ is the batch size and $D$ is the number of classes.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Blob containing the labels used to compare the input. $label$ is a length $N$ list of integers, where each element is the integer label for the $n$th element of the batch.\",\n        \"name\": \"label\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output blob from the cross entropy computation. $Y$ is 1D length $N$ tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LabelCrossEntropyGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LambdaRankNdcg\",\n    \"description\": \"\\nIt implements the LambdaRank as appeared in Wu, Qiang, et al. \\\"Adapting boosting\\nfor information retrieval measures.\\\" Information Retrieval 13.3 (2010): 254-270.\\n\\nThis method heuristically optimizes the NDCG.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LambdaRankNdcgGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Lars\",\n    \"description\": \"\\nImplement Layer-wise Adaptive Rate Scaling (LARS) with clipping. Before adding weight\\ndecay, given a parameter tensor X and its gradient dX, the local learning rate\\nfor X will be\\n\\nlocal_lr = trust * norm(X) / ( norm(dX) + wd * norm(X) + offset * norm(X) )\\n\\n      = trust / ( norm(dX) / norm(X) + wd + offset ),\\n\\nwhere offset is a preset hyper-parameter to avoid numerical issue and trust\\nindicates how much we trust the layer to change its parameters during one update.\\nIn this implementation, we uses l2 norm and the computed local learning rate is\\nclipped based on the upper bound lr_max and the lower bound lr_min:\\n\\nlocal_lr = min(local_lr, lr_max) and local_lr = max(local_lr, lr_min)\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"rescaling offset parameter\",\n        \"name\": \"offset\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"minimum learning rate for clipping\",\n        \"name\": \"lr_min\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameter tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Gradient tensor\",\n        \"name\": \"dX\"\n      },\n      {\n        \"description\": \"Weight decay\",\n        \"name\": \"wd\"\n      },\n      {\n        \"description\": \"Trust\",\n        \"name\": \"trust\"\n      },\n      {\n        \"description\": \"Upper bound of learning rate\",\n        \"name\": \"lr_max\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Rescaled local learning rate\",\n        \"name\": \"lr_rescaled\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LastNWindowCollector\",\n    \"description\": \"\\nCollect the last N rows from input data. The purpose is to keep track of data\\naccross batches, so for example suppose the LastNWindowCollector is called\\nsuccessively with the following input data\\n\\n  [1, 2, 3, 4]\\n  [5, 6, 7]\\n  [8, 9, 10, 11]\\n\\nAnd the number of items is set to 6, then the output after the 3rd call\\nwill contain the following elements:\\n\\n  [6, 7, 8, 9, 10, 11]\\n\\nNo guarantee is made on the ordering of elements in input. So a valid value for\\noutput could have been\\n\\n  [11, 10, 9, 8, 7, 6]\\n\\nAlso, this method works for any order tensor, treating the first dimension as\\ninput rows and keeping the last N rows seen as input. So for instance:\\n\\n  [[1, 2], [2, 3], [3, 4], [4, 5]]\\n  [[5, 6], [6, 7], [7, 8]]\\n  [[8, 9], [9, 10], [10, 11], [11, 12]]\\n\\nA possible output would be\\n\\n  [[6, 7], [7, 8], [8, 9], [9, 10], [10, 11], [11, 12]]\\n\\nThis is not thread safe unless a mutex is given.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The number of random samples to append for each positive samples\",\n        \"name\": \"num_to_collect\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The buffer for last-N record. Should be initialized to empty tensor\",\n        \"name\": \"last-N buffer\"\n      },\n      {\n        \"description\": \"The cursor pointing to the next position that should be replaced. Should be initialized to 0.\",\n        \"name\": \"next cursor\"\n      },\n      {\n        \"description\": \"tensor to collect from\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"(optional) mutex to use to make this thread-safe\",\n        \"name\": \"MUTEX\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"NUM_VISITED\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Data stored in sessions\",\n        \"name\": \"last-N buffer\"\n      },\n      {\n        \"description\": \"Updated input cursor\",\n        \"name\": \"next cursor\"\n      },\n      {\n        \"description\": \"number of records seen so far\",\n        \"name\": \"NUM_VISITED\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"description\": \"\\nComputes layer normalization as described in https://arxiv.org/pdf/1607.06450.pdf.\\nGiven an input vector x \\\\in [a_0, a_1, ...,a_{k-1}, a_k, ..., a_{n-1}],\\nthis op treats dimensions a_k through a_{n-1} as feature vectors. For each\\nfeature vector, the op contains the mean and standard deviation. Then,\\nit returns the normalized values (with respect to the feature vector).\\n\\nNote that this op does not contain the scale an bias terms described in the\\npaper. Simply follow this op with an FC op to add those. Concretely, this op\\nimplements:\\n\\nh = \\\\frac{1}{\\\\sigma}(a - \\\\mu)\\nwhere \\\\mu = \\\\frac{1}{H}\\\\sum_{i=1}^{H} a_i\\nand \\\\sigma = \\\\sqrt{\\\\frac{1}{H}\\\\sum_{i=1}^{H}(a_i - \\\\mu)^2}\\nwhere H is the number of hidden units (i.e. product of dimensions from 'axis'\\nto the end.)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) default to 1; Describes axis of the inputs. Defaults to one because the 0th axis most likely describes the batch size\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) default to 0.001. Small value to be added to the stdev when dividing out by that value. This prevents division by zero.\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(bool) default to False; If true, this op will do affine transformation after normalization.\",\n        \"name\": \"elementwise_affine\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor which layer normalization will be applied to\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"scale tensor for elementwise_affine, the shape should be the same as the dimensions of X begin from axis\",\n        \"name\": \"gamma\"\n      },\n      {\n        \"description\": \"bias tensor for elementwise_affine, the shape should be the same as the dimensions of X begin from axis\",\n        \"name\": \"beta\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Normalized values\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"Mean values for each feature vector\",\n        \"name\": \"mean\"\n      },\n      {\n        \"description\": \"Standard deviations for each feature vector\",\n        \"name\": \"stddev\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LayerNormGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC\",\n    \"description\": \"\\nThe locally connected operator consumes an input vector, a filter blob\\nand a bias blob and computes the output. \\nNote that other parameters, such as the stride and\\nkernel size, or the pads' sizes in each direction are not necessary for input\\nbecause they are provided by the ConvPoolOpBase operator. Various dimension\\nchecks are done implicitly, and the sizes are specified in the Input docs for\\nthis operator. As is expected, the filter is locally connected with a subset of\\nthe image and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nlocally_connected_op_impl.h is the templated implementation of the\\nlocally_connected_op.h file, which is why they are separate files.\\n\",\n    \"inputs\": [\n      {\n        \"name\": null\n      },\n      {\n        \"description\": \"The filter blob that will be used in the locally connected op; has size (YH * YW * M x C x kH x kW) if order == NCHW else (YH * YW * M  * KH * KW * C), where YH and YW are the height and width of the output image, C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the locally connected op; has size (YH * YW * M).\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the locally connected op.The output dimensions are functions of the kernel size, stride size, and pad lengths.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC1D\",\n    \"description\": \"\\nThe locally connected operator consumes an input vector, a 1D filter blob\\nand a bias blob and computes the output. \\nNote that other parameters, such as the stride and\\nkernel size, or the pads' sizes in each direction are not necessary for input\\nbecause they are provided by the ConvPoolOpBase operator. Various dimension\\nchecks are done implicitly, and the sizes are specified in the Input docs for\\nthis operator. As is expected, the filter is locally connected with a subset of\\nthe image and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nlocally_connected_op_impl.h is the templated implementation of the\\nlocally_connected_op.h file, which is why they are separate files.\\n\",\n    \"inputs\": [\n      {\n        \"name\": null\n      },\n      {\n        \"description\": \"The filter blob that will be used in the locally connected op; has size (YH * YW * M x C x kH x kW) if order == NCHW else (YH * YW * M  * KH * KW * C), where YH and YW are the height and width of the output image, C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the locally connected op; has size (YH * YW * M).\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the locally connected op.The output dimensions are functions of the kernel size, stride size, and pad lengths.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC1DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC2D\",\n    \"description\": \"\\nThe locally connected operator consumes an input vector, a 2D filter blob\\nand a bias blob and computes the output. \\nNote that other parameters, such as the stride and\\nkernel size, or the pads' sizes in each direction are not necessary for input\\nbecause they are provided by the ConvPoolOpBase operator. Various dimension\\nchecks are done implicitly, and the sizes are specified in the Input docs for\\nthis operator. As is expected, the filter is locally connected with a subset of\\nthe image and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nlocally_connected_op_impl.h is the templated implementation of the\\nlocally_connected_op.h file, which is why they are separate files.\\n\",\n    \"inputs\": [\n      {\n        \"name\": null\n      },\n      {\n        \"description\": \"The filter blob that will be used in the locally connected op; has size (YH * YW * M x C x kH x kW) if order == NCHW else (YH * YW * M  * KH * KW * C), where YH and YW are the height and width of the output image, C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the locally connected op; has size (YH * YW * M).\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the locally connected op.The output dimensions are functions of the kernel size, stride size, and pad lengths.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC2DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC3D\",\n    \"description\": \"\\nThe locally connected operator consumes an input vector, a 3D filter blob\\nand a bias blob and computes the output. \\nNote that other parameters, such as the stride and\\nkernel size, or the pads' sizes in each direction are not necessary for input\\nbecause they are provided by the ConvPoolOpBase operator. Various dimension\\nchecks are done implicitly, and the sizes are specified in the Input docs for\\nthis operator. As is expected, the filter is locally connected with a subset of\\nthe image and the bias is added; this is done throughout the image data and the\\noutput is computed. As a side note on the implementation layout:\\nlocally_connected_op_impl.h is the templated implementation of the\\nlocally_connected_op.h file, which is why they are separate files.\\n\",\n    \"inputs\": [\n      {\n        \"name\": null\n      },\n      {\n        \"description\": \"The filter blob that will be used in the locally connected op; has size (YH * YW * M x C x kH x kW) if order == NCHW else (YH * YW * M  * KH * KW * C), where YH and YW are the height and width of the output image, C is the number of channels, and kH and kW are the height and width of the kernel.\",\n        \"name\": \"filter\"\n      },\n      {\n        \"description\": \"The 1D bias blob that is added through the locally connected op; has size (YH * YW * M).\",\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob that contains the result of the locally connected op.The output dimensions are functions of the kernel size, stride size, and pad lengths.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LC3DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LCGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LE\",\n    \"description\": \"\\nPerforms element-wise less or equal than comparison **<=** (with limited broadcast support).\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LE\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([1, 5, 2, 9, 12, 3]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([1, 3, 4, 9, 12, 8]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA: [ 1  5  2  9 12  3]\\nB: [ 1  3  4  9 12  8]\\nC: [ True False  True  True  True  True]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor with same dimensions as `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LeakyRelu\",\n    \"description\": \"\\nThe *LeakyRelu* op takes one input tensor $X$ and an argument $alpha$, and produces one output tensor $Y$ of the same shape as $X.$ The op performs the element wise leaky relu operation, defined as\\n\\n$$y=LeakyRelu(x) =\\\\begin{cases}\\\\alpha x & x < 0\\\\\\\\x & otherwise\\\\end{cases}$$\\n\\nThe default value of *alpha* is 0.01.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/leaky_relu_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/leaky_relu_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LeakyRelu\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    alpha=0.01\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[-0.91060215  0.09374836  2.1429708 ]\\n [-0.748983    0.19164062 -1.5130422 ]\\n [-0.29539835 -0.8530696   0.7673204 ]]\\n\\nY:\\n [[-0.00910602  0.09374836  2.1429708 ]\\n [-0.00748983  0.19164062 -0.01513042]\\n [-0.00295398 -0.0085307   0.7673204 ]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0.01,\n        \"description\": \"Coefficient of leakage.\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor of data to be operated on.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor, calculated as described above.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LeakyReluGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"Coefficient of leakage\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LearningRate\",\n    \"description\": \"\\nLearning rate is a decreasing function of time. With low learning rates the\\nimprovements will be linear. With high learning rates they will start to look\\nmore exponential. Learning rate is controlled by the following arguments:\\n\\n\\nRequired:\\n `iterations`\\n `base_lr`: base learning rate\\n `policy`: this controls how the learning rate is applied, options are:\\n   `fixed`\\n   `step`: uses `stepsize`, `gamma`\\n   `exp`: uses `gamma`\\n   `gate`: uses 'multiplier_1', 'multiplier_2', `num_iter``\\n   `inv`: uses `gamma`, `power`\\n   `linearWarmup`: uses `start_multiplier`, `num_iter`\\n   `constantWarmup`: uses `multiplier`, `num_iter`\\n   `alter`: uses  `active_first`, `active_period`, `inactive_period`\\n   `hill`: uses those in both `linearWarmup` and `inv`, plus `end_multiplier`\\n   `composite`: uses `sub_policy_num_iters` and additional args with format\\n   `cyclic`: uses `max_lr`, `stepsize`\\n   `cosine`: uses `min_lr`, `max_lr`, `period`, `t_mult`, `lr_shrink`\\n   `constantThenLinearWarmup`: uses `start_warmup_multiplier`, `constant_warmup_num_iter`, `linear_warmup_num_iter`\\n   `compositeCyclical`: uses `start_warmup_multiplier`, `constant_warmup_num_iter`, `linear_warmup_num_iter`, `cyclical_max_lr`, `cyclical_step_size`, `cyclical_decay`\\n   `compositeCosine`: uses `start_warmup_multiplier`, `constant_warmup_num_iter`, `linear_warmup_num_iter`, `cosine_max_lr`, `cosine_period`, `cosine_t_mult`, `cosine_lr_shrink`\\n   sub_policy_{sub_policy_index}_{sub_policy_arg}, for example:\\n   sub_policy_0_policy: \\\"exp\\\", sub_policy_0_gamma: 0.99,\\n   sub_policy_0_lr_scale: 1.2\\n   sub_policy_0_policy: \\\"fixed\\\", sub_policy_0_lr_scale: 1.0\\n   sub_policy_num_iters: [1000, 1000]\\n\\nOptional:\\n  `stepsize`: defaults to 0\\n  `max_lr`: defaults to 0.005\\n  `gamma`: defaults to 0\\n  `power`: defaults to 0\\n  `num_iter`: defaults to 0\\n  `start_multiplier`: defaults to 0\\n  `multiplier`: defaults to 0.5\\n  `multiplier_1`: defaults to 1\\n  `multiplier_2`: defaults to 1\\n  `m1`: defaults to 0.5, the first piece lr of piece warmup\\n  `n1`: defaults to 0, iter threshold of the first piece lr\\n  `m2`: defaults to 0.5, the second piece lr of piece warmup\\n  `n2`: defaults to 0, iter threshold of the second piece lr\\n  `m3`: defaults to 0.5, the third piece lr of piece warmup\\n  `start_warmup_multiplier`: defaults to 0.1, part of constantThenLinearWarmup\\n  `constant_warmup_num_iter`: defaults to 10000000, part of constantThenLinearWarmup and constantThenLinearWarmup\\n  `linear_warmup_num_iter`: defaults to 10000000, part of constantThenLinearWarmup, CompositeCyclicalLRPolicy, CompositeCosineLRPolicy\\n  `cyclical_max_lr`: defaults to 0.05, part of CompositeCyclicalLRPolicy\\n  `cyclical_step_size`: defaults to 1000000, part of CompositeCyclicalLRPolicy\\n  `cyclical_decay`: defaults to 1.0, part of CompositeCyclicalLRPolicy\\n  `cosine_min_lr`:defaults to 0.01, part of CompositeCosineLRPolicy\\n  `cosine_max_lr`:defaults to 0.05, part of CompositeCosineLRPolicy\\n  `cosine_period`:defaults to 50, part of CompositeCosineLRPolicy\\n  `cosine_t_mult`:defaults to 1.0, part of CompositeCosineLRPolicy\\n  `cosine_lr_shrink`:defaults to 0.99, part of CompositeCosineLRPolicy\\n\\nUsage:\\n  train_net.LearningRate(*iterations*, \\\"*label*\\\", base_lr=*float*,\\n                         policy=\\\"policy_name\\\", stepsize=*int*, gamma=*float*)\\n\\n\\nExample usage:\\n  train_net.LearningRate(200, \\\"LR\\\", base_lr=-0.1,\\n                         policy=\\\"step\\\", stepsize=20, gamma=0.9)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float, required) base learning rate\",\n        \"name\": \"base_lr\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 1.0) strategy for gamma enforcement\",\n        \"name\": \"policy\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 1.0) used only for inv policy type\",\n        \"name\": \"power\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 1.0) momentum of change\",\n        \"name\": \"gamma\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 1.0) sampling rate on iterations\",\n        \"name\": \"stepsize\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(boolean, default True) in alter policy\",\n        \"name\": \"active_first\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int64_t, required) in alter policy\",\n        \"name\": \"active_period\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int64_t, required) in alter policy\",\n        \"name\": \"inactive_period\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int, default -1) maximum iterations in this training run\",\n        \"name\": \"max_iter\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int, default 0) number of iterations over which to warmup lr\",\n        \"name\": \"num_iter\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 0) starting multiplier for learning rate\",\n        \"name\": \"start_multiplier\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 0) end multiplier for learning rate\",\n        \"name\": \"end_multiplier\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 0.5) constant multiplier for learning rate\",\n        \"name\": \"multiplier\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 1) start multiplier for learning rate\",\n        \"name\": \"multiplier_1\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 1) end multiplier for learning rate\",\n        \"name\": \"multiplier_2\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int array, default empty) number of iterations for each sub learning rate policy in composite policy\",\n        \"name\": \"sub_policy_num_iters\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"m1\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"n1\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"m2\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"n2\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"\",\n        \"name\": \"m3\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float, default 0.005) max learning rate\",\n        \"name\": \"max_lr\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 0.1\",\n        \"name\": \"start_warmup_multiplier\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 10000000\",\n        \"name\": \"constant_warmup_num_iter\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 10000000\",\n        \"name\": \"linear_warmup_num_iter\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 0.05, part of CompositeCyclicalLRPolicy\",\n        \"name\": \"cyclical_max_lr\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 1000000, part of CompositeCyclicalLRPolicy\",\n        \"name\": \"cyclical_step_size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 0.999, part of CompositeCyclicalLRPolicy\",\n        \"name\": \"cyclical_decay\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 0.01, part of CompositeCosineLRPolicy\",\n        \"name\": \"cosine_min_lr\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 0.05, part of CompositeCosineLRPolicy\",\n        \"name\": \"cosine_max_lr\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 50, part of CompositeCosineLRPolicy\",\n        \"name\": \"cosine_period\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 1,0, part of CompositeCosineLRPolicy\",\n        \"name\": \"cosine_t_mult\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"defaults to 0.99, part of CompositeCosineLRPolicy\",\n        \"name\": \"cosine_lr_shrink\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"description needed\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"description needed\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LearningRateAdaption\",\n    \"description\": \"\\n      Learning Rate Adaption is an operation that perform one iteration of\\n      gradient descent based on learning rate:\\n        lr(k) = lr(k-1) - lr_alpha * df(k-1)/dlr,\\n      where df(k-1)/dlr is the gradient of objective function f on lr, and\\n      lr_alpha is a learning rate hyperparameter. It can be prove that\\n      df(k-1)/dlr equals INNERPRODUCT(grad(k-1), -grad(k-2)), where grad(k-1) is\\n      the grad of f(k-1) on parameters. When the argument\\n      \\\"normalized_lr_adaption\\\" is false, we simply perform the\\n      following update:\\n      lr(k) = lr(k-1) - lr_alpha * INNERPRODUCT(grad(k-1), grad(k-2)).\\n      If we set \\\"normalized_lr_adaption\\\" to be true, we do not directly apply\\n      INNERPRODUCT(grad(k-1), -grad(k-2)) as the grad. Instead, we perform the\\n      following update:\\n      lr(k) = lr(k-1) + lr_alpha * cosineSimilarity(grad(k-1), grad(k-2)).\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the learning rate for performing gradient descent on learning rate lr\",\n        \"name\": \"lr_alpha\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"whether to apply normalized lr adaption or not\",\n        \"name\": \"normalized_lr_adaption\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"The effective grad\",\n        \"name\": \"effgrad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated learning rate\",\n        \"name\": \"output_lr\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsGather\",\n    \"description\": \"\\nGather items from sparse tensor. Sparse tensor is described by items and\\nlengths. This operator gathers items corresponding to lengths at the given\\nindices. This deliberately doesn't return lengths of OUTPUTS so that both lists\\nand maps can be supported without special cases. If you need lengths tensor for\\n OUTPUT, use `Gather`.\\n\\nExample:\\n  ITEMS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\\n  LENGTHS = [0, 2, 3, 1, 4]\\n  INDICES = [0, 2, 4]\\n\\n  OUTPUT = [2, 3, 4, 6, 7, 8, 9]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"items tensor\",\n        \"name\": \"ITEMS\"\n      },\n      {\n        \"description\": \"lengths tensor\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"indices into LENGTHS where items should be gathered\",\n        \"name\": \"INDICES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor containing gathered items\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsIndicesInGradientMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsIndicesInGradientSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsMax\",\n    \"description\": \"\\nApplies 'Max' to each segment of the input tensor. Segments are defined\\nby their *LENGTHS*. *LENGTHS* is a vector that maps each of the slices of\\n*DATA* to a particular segment. Values belonging to the same segment are\\naggregated together and considered for the 'Max' operation.\\n\\nFor example *LENGTHS = [2, 1]* stands for segments *DATA[0..1]* and *DATA[2]*\\n\\nThe sum of elements in *LENGTHS* must equal the number of elements in the first\\ndimension of *DATA*. The length of *OUTPUT* is equal to the number of input\\nsegments, i.e. len(*LENGTHS*).\\n\\nMax computes the element-wise max of the input slices. Operation doesn't change the shape of the individual blocks.\\n\\n\\nThe *LengthsMax* op takes two inputs *DATA* and *LENGTHS*, and produces a single output *OUTPUT*. The op finds the maximum value in each of the segments of *DATA*, where segments are defined by their lengths.\\nFor example, if $DATA = [2,4,3,1,2,10]$ and $LENGTHS = [2,3,1]$ then $OUTPUT = [max([2,4]), max([3,1,2]), max([10])] = [4,3,10]$.\\n\\nGithub Link:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/segment_reduction_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsMax\\\",\\n    [\\\"DATA\\\", \\\"LENGTHS\\\"],\\n    [\\\"OUTPUT\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"DATA\\\", np.array([2,4,3,1,2,10]).astype(np.float32))\\nprint(\\\"DATA:\\\\n\\\", workspace.FetchBlob(\\\"DATA\\\"))\\n\\nworkspace.FeedBlob(\\\"LENGTHS\\\", np.array([2,3,1]).astype(np.int32))\\nprint(\\\"LENGTHS:\\\\n\\\", workspace.FetchBlob(\\\"LENGTHS\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"OUTPUT: \\\\n\\\", workspace.FetchBlob(\\\"OUTPUT\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nDATA:\\n [ 2.  4.  3.  1.  2. 10.]\\nLENGTHS:\\n [2 3 1]\\nOUTPUT:\\n [ 4.  3. 10.]\\n\\n```\\n\\n</details>\\n\\n\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of len(LENGTHS) \",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsMaxWithMainInputAndForwardOutputGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsMean\",\n    \"description\": \"\\nApplies 'Mean' to each segment of the input tensor. Segments are defined\\nby their *LENGTHS*. *LENGTHS* is a vector that maps each of the slices of\\n*DATA* to a particular segment. Values belonging to the same segment are\\naggregated together and considered for the 'Mean' operation.\\n\\nFor example *LENGTHS = [2, 1]* stands for segments *DATA[0..1]* and *DATA[2]*\\n\\nThe sum of elements in *LENGTHS* must equal the number of elements in the first\\ndimension of *DATA*. The length of *OUTPUT* is equal to the number of input\\nsegments, i.e. len(*LENGTHS*).\\n\\nMean computes the element-wise mean of the input slices. Operation doesn't change the shape of the individual blocks.\\n\\n\\nThe *LengthsMean* op takes two inputs *DATA* and *LENGTHS*, and produces a single output *OUTPUT*. The op finds the mean value in each of the segments of *DATA*, where segments are defined by their lengths.\\nFor example, if $DATA = [2,4,3,1,2,10]$ and $LENGTHS = [2,3,1]$ then $OUTPUT = [mean([2,4]), mean([3,1,2]), mean([10])] = [3,2,10]$.\\n\\nGithub Link:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/segment_reduction_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsMean\\\",\\n    [\\\"DATA\\\", \\\"LENGTHS\\\"],\\n    [\\\"OUTPUT\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"DATA\\\", np.array([2,4,3,1,2,10]).astype(np.float32))\\nprint(\\\"DATA:\\\\n\\\", workspace.FetchBlob(\\\"DATA\\\"))\\n\\nworkspace.FeedBlob(\\\"LENGTHS\\\", np.array([2,3,1]).astype(np.int32))\\nprint(\\\"LENGTHS:\\\\n\\\", workspace.FetchBlob(\\\"LENGTHS\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"OUTPUT: \\\\n\\\", workspace.FetchBlob(\\\"OUTPUT\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nDATA:\\n [ 2.  4.  3.  1.  2. 10.]\\nLENGTHS:\\n [2 3 1]\\nOUTPUT:\\n [ 3.  2. 10.]\\n\\n```\\n\\n</details>\\n\\n\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of len(LENGTHS) \",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsPad\",\n    \"description\": \"\\nGiven DATA tensor of rank r >= 1, and LENGTHS tensor of rank 1, pad each\\nsegment in DATA with `value`, so that each segment's length is `target_length`.\\nIf will throw, if there is segment of length larger than `target_length`.\\n\\nExample:\\n  DATA  = [\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n      [6.8, 7.9],\\n  ]\\n  LENGTHS = [0, 1, 1, 1]\\n  and target_length = 2, padding value = -1.0\\n  OUTPUT = [\\n    [-1.0, -1.0],\\n    [-1.0, -1.0],\\n    [2.3, 3.4],\\n    [-1.0, -1.0],\\n    [4.5, 5.7],\\n    [-1.0, -1.0],\\n    [6.8, 7.9],\\n    [-1.0, -1.0],\\n  ]\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The value to pad the data\",\n        \"name\": \"padding_value\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The target length of each segment\",\n        \"name\": \"target_length\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of rank r >= 1. First dimension must be equal to the size of lengths\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Tensor of int32 lengths of rank 1\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Padded DATA tensor\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsPartition\",\n    \"description\": \"\\nLengthsPartition splits the input int tensor into multiple ones according to the\\nsecond tensor. The first dimension is expected to be the tensor that describes\\nlengths of the elements.\\n\\nTakes the second input and partitions it to shards according to the remainder of\\nvalues modulo the number of partitions. It requires the second tensor to be\\na 1D-tensor of the integral type. The first tensor should be 1D-tensor of int32\\nthat would represent the lengths of the elements in the input. The number of\\npartitions is derived as (num_output / num_input).\\n\\nIf additional inputs are present they must have the same shape as the first\\ninput, optionally with extra trailing dimensions. They will be partitioned\\naccordingly to the first input.\\n\\nOptional arg 'pack_first_input' transforms the first tensor values as\\nX_ij / num_partitions.\\n\\nOutputs are ordered as\\nX_0_part_0, X_1_part_0, ..., X_N-1_part_0, X_0_part_1, ..., X_N-1_part_K-1\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) If set, the operator transforms the first tensor values as floor(X_ij / num_partitions)\",\n        \"name\": \"pack_first_input\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor containing data to be partitioned. The number of input tensors might be greater than 1 but must have the same shape as the previous tensors.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output Partitions. The number of output tensors has to be a multiple of the number of input tensors.\",\n        \"name\": \"partitions\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsRangeFill\",\n    \"description\": \"\\nThe *LengthsRangeFill* op takes a single input *lengths* and outputs a single tensor *range_sequence*. For each element of *lengths*, the op appends the range(0,lengths) vector to the end of *range_sequence*. For example, if input=[2,4,1], the output would be [0,1,0,1,2,3,0].\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsRangeFill\\\",\\n    [\\\"lengths\\\"],\\n    [\\\"range_sequence\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"lengths\\\", np.array([2,4,1]).astype(np.int32))\\nprint(\\\"lengths:\\\\n\\\", workspace.FetchBlob(\\\"lengths\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"range_sequence: \\\\n\\\", workspace.FetchBlob(\\\"range_sequence\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nlengths:\\n [2 4 1]\\nrange_sequence:\\n [0 1 0 1 2 3 0]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D tensor of int32 or int64 segment lengths.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor whose size is the sum of *lengths*\",\n        \"name\": \"range_sequence\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsSplit\",\n    \"description\": \"\\nGiven input vector LENGTHS, and input n_split, LengthsSplit returns\\na single output vector. It \\\"splits\\\" each length into n_split values which add\\nup to the original length. It will attempt to do equal splits, and if not possible,\\nit orders larger values first. If the n_split is larger than the length, zero\\npadding will be applied.\\n\\ne.g. LENGTHS = [9 4 5]\\n     n_split = 3\\n     Y = [3 3 3 2 1 1 2 2 1]\\n\\ne.g. LENGTHS = [2, 1, 2]\\n     n_split = 3\\n     Y = [1 1 0 1 0 0 1 1 0]\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of splits for each element in LENGTHS\",\n        \"name\": \"n_split\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Mx1 Input tensor denoting INT32 lengths\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"(Optional) Number of splits for each element in LENGTHS (overrides argument)\",\n        \"name\": \"n_split\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(M*n_split)x1 Output vector denoting split lengths\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsSum\",\n    \"description\": \"\\nApplies 'Sum' to each segment of the input tensor. Segments are defined\\nby their *LENGTHS*. *LENGTHS* is a vector that maps each of the slices of\\n*DATA* to a particular segment. Values belonging to the same segment are\\naggregated together and considered for the 'Sum' operation.\\n\\nFor example *LENGTHS = [2, 1]* stands for segments *DATA[0..1]* and *DATA[2]*\\n\\nThe sum of elements in *LENGTHS* must equal the number of elements in the first\\ndimension of *DATA*. The length of *OUTPUT* is equal to the number of input\\nsegments, i.e. len(*LENGTHS*).\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n\\n\\nThe *LengthsSum* op takes two inputs *DATA* and *LENGTHS*, and produces a single output *OUTPUT*. The op finds the sum in each of the segments of *DATA*, where segments are defined by their lengths.\\nFor example, if $DATA = [2,4,3,1,2,10]$ and $LENGTHS = [2,3,1]$ then $OUTPUT = [sum([2,4]), sum([3,1,2]), sum([10])] = [6,6,10]$.\\n\\nGithub Link:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/segment_reduction_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsSum\\\",\\n    [\\\"DATA\\\", \\\"LENGTHS\\\"],\\n    [\\\"OUTPUT\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"DATA\\\", np.array([2,4,3,1,2,10]).astype(np.float32))\\nprint(\\\"DATA:\\\\n\\\", workspace.FetchBlob(\\\"DATA\\\"))\\n\\nworkspace.FeedBlob(\\\"LENGTHS\\\", np.array([2,3,1]).astype(np.int32))\\nprint(\\\"LENGTHS:\\\\n\\\", workspace.FetchBlob(\\\"LENGTHS\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"OUTPUT: \\\\n\\\", workspace.FetchBlob(\\\"OUTPUT\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nDATA:\\n [ 2.  4.  3.  1.  2. 10.]\\nLENGTHS:\\n [2 3 1]\\nOUTPUT:\\n [ 6.  6. 10.]\\n\\n```\\n\\n</details>\\n\\n\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of len(LENGTHS) \",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsTile\",\n    \"description\": \"\\nGiven DATA tensor of rank r >= 1, and LENGTHS tensor of rank 1, duplicate each\\nentry of the outer-most dimension of DATA according to LENGTHS, and concatenate\\nthem in an output tensor of rank r.\\n\\nExample:\\n  DATA  = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n      [6.8, 7.9],\\n  ]\\n  LENGTHS = [0, 1, 3, 2]\\n  OUTPUT = [\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n      [4.5, 5.7],\\n      [4.5, 5.7],\\n      [6.8, 7.9],\\n      [6.8, 7.9],\\n  ]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of rank r >= 1. First dimension must be equal to the size of lengths\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Tensor of int32 lengths of rank 1\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of rank r\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsToOffsets\",\n    \"description\": \"\\nGiven a vector of segment lengths, returns a vector of offsets from these lengths,\\nwhich will have the same size as the input vector. Output is going to have\\nthe same type as input. For long tensors explicit casting from int32 to int64\\nmight be necessary prior to this op.\\n\\nFor example, `[1, 3, 0, 2]` transforms into `[0, 1, 4, 4]`.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D tensor of int32 or int64 segment lengths.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of the same shape and type as `lengths`\",\n        \"name\": \"offsets\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsTopK\",\n    \"description\": \"\\nApply TopK to each segment of the input tensor, where segments are defined by\\ntheir LENGTHS, and concatenate them in an output tensor of\\nshape=(SIZE(LENGTHs), k). In case there's less than k values in a segment,\\nthe output value will be padded by 0, and the corresponding output indices will\\nbe padded by -1.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the number of top values to return for each segment, if the number of values is smaller than k, the values would be padded with 0 and indices would be padded with -1.\",\n        \"name\": \"k\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of rank 1. First dimension must be equal to the sum of lengths\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Tensor of int32 lengths of rank 1\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output top k elements for each segment, withshape=(SIZE(lengths), k)\",\n        \"name\": \"TopKValue\"\n      },\n      {\n        \"description\": \"Output indices in DATA corresponding to value in TopKValue\",\n        \"name\": \"TopKIndices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsTopKGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsToRanges\",\n    \"description\": \"\\nGiven a vector of segment lengths, calculates offsets of each segment and packs\\nthem next to the lengths. For the input vector of length N the output is a Nx2\\nmatrix with (offset, lengths) packaged for each segment.\\n\\nFor example, `[1, 3, 0, 2]` transforms into `[[0, 1], [1, 3], [4, 0], [4, 2]]`.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D tensor of int32 segment lengths.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2D tensor of shape len(lengths) X 2 and the same type as `lengths`\",\n        \"name\": \"ranges\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsToSegmentIds\",\n    \"description\": \"\\nGiven a vector of segment lengths (*lengths*) the *LengthsToSegmentIds* op returns a zero-based, consecutive vector of segment ids (*segment_ids*). For example, *lengths=[1, 3, 0, 2]* will produce *segment_ids=[0, 1, 1, 1, 3, 3]*. In general, the inverse operation is *SegmentIdsToLengths*. Notice though that trailing empty sequence lengths can't be properly recovered from segment ids.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.cc\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/utility_ops.h\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsToSegmentIds\\\",\\n    [\\\"lengths\\\"],\\n    [\\\"segment_ids\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"lengths\\\", np.array([1, 3, 0, 2]).astype(np.int32))\\nprint(\\\"lengths:\\\\n\\\", workspace.FetchBlob(\\\"lengths\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"segment_ids: \\\\n\\\", workspace.FetchBlob(\\\"segment_ids\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nlengths:\\n [1 3 0 2]\\nsegment_ids:\\n [0 1 1 1 3 3]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D tensor of int32 or int64 segment lengths.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of length *sum(lengths)*\",\n        \"name\": \"segment_ids\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsToShape\",\n    \"description\": \"\\nThis operator takes a list of $N$ equal integers as input which represent the lengths of $N$ vectors. The output is the calculated shape of the matrix if the $N$ integers were combined into a single matrix.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/utility_ops.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/utility_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsToShape\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X: Sample softmax output for 5-class model\\nX = np.array([2,2,2,2,2,2,2,2,2,2])\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Feed X into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.int32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [2 2 2 2 2 2 2 2 2 2]\\nY:\\n [10  2]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"List, of length $N$, of equal integers representing the lengths of several vectors.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Vector of length 2 describing the dimensions of the data if the $N$ vectors from the input were combined to a single matrix.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsToWeights\",\n    \"description\": \"\\nSimilar as LengthsToSegmentIds but output vector of segment\\nweights derived by lengths. i.e 1/pow(length, power)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"n of 1/pow(length,n) for normalization\",\n        \"name\": \"power\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1-D int32_t or int64_t tensor of lengths\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D float tensor of weights by length\",\n        \"name\": \"a vector of weights\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsWeightedSum\",\n    \"description\": \"\\nApplies 'WeightedSum' to each segment of the input tensor. Segments are defined\\nby their *LENGTHS*. *LENGTHS* is a vector that maps each of the slices of\\n*DATA* to a particular segment. Values belonging to the same segment are\\naggregated together and considered for the 'WeightedSum' operation.\\n\\nFor example *LENGTHS = [2, 1]* stands for segments *DATA[0..1]* and *DATA[2]*\\n\\nThe sum of elements in *LENGTHS* must equal the number of elements in the first\\ndimension of *DATA*. The length of *OUTPUT* is equal to the number of input\\nsegments, i.e. len(*LENGTHS*).\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n\\n\\nThe *LengthsWeightedSum* op takes three inputs *DATA*, *LENGTHS*, and *SCALARS*, and produces a single output *OUTPUT*. The op finds the weighted sum in each of the segments of *DATA*, where segments are defined by their lengths. Before calculating the sums, the input *DATA* is weighted by the contents of *SCALARS*.\\nFor example, if $DATA = [2,4,3,1,2,10]$, $SCALARS = [8, 2, 1, 4, 1, 0.6]$, and $LENGTHS = [2,3,1]$, then $OUTPUT = [sum([8*2,2*4]), sum([1*3,4*1,1*2]), sum([0.6*10])] = [24,9,6]$.\\n\\nGithub Link:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/segment_reduction_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LengthsWeightedSum\\\",\\n    [\\\"DATA\\\", \\\"SCALARS\\\",\\\"LENGTHS\\\"],\\n    [\\\"OUTPUT\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"DATA\\\", np.array([2,4,3,1,2,10]).astype(np.float32))\\nprint(\\\"DATA:\\\\n\\\", workspace.FetchBlob(\\\"DATA\\\"))\\n\\nworkspace.FeedBlob(\\\"SCALARS\\\", np.array([8, 2, 1, 4, 1, 0.6]).astype(np.float32))\\nprint(\\\"SCALARS:\\\\n\\\", workspace.FetchBlob(\\\"SCALARS\\\"))\\n\\nworkspace.FeedBlob(\\\"LENGTHS\\\", np.array([2,3,1]).astype(np.int32))\\nprint(\\\"LENGTHS:\\\\n\\\", workspace.FetchBlob(\\\"LENGTHS\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"OUTPUT: \\\\n\\\", workspace.FetchBlob(\\\"OUTPUT\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nDATA:\\n [ 2.  4.  3.  1.  2. 10.]\\nSCALARS:\\n [8.  2.  1.  4.  1.  0.6]\\nLENGTHS:\\n [2 3 1]\\nOUTPUT:\\n [24.  9.  6.]\\n\\n```\\n\\n</details>\\n\\n\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of len(LENGTHS) \",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LengthsWeightedSumWithMainInputGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Load\",\n    \"description\": \"\\nThe Load operator loads a set of serialized blobs from a db or multiple dbs. It\\ntakes $[0, \\\\infty)$ number of inputs and $[0, \\\\infty)$ number of outputs, using\\nthe db keys to match the db entries with the outputs.\\n\\nIf at least one input is passed, then it is assumed that that input blobs are a\\nset of DBReaders to load from. Otherwise the `db` or `dbs` argument is used to load\\nblobs from one single db or multiple dbs respectively. `db_type` argument is used\\nto specify the type of the input db/dbs.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/load_save_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Load\\\",\\n    [],\\n    [\\\"X\\\", \\\"Y\\\"],\\n    db=\\\"test_db\\\",\\n    db_type=\\\"lmdb\\\"\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"If set to non-zero, save the db directly to the path specified by the `db` arg. If not set (default), prepend the path of the current root folder of the workspace to the path specified by the `db` arg.\",\n        \"name\": \"absolute_path\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": \"\",\n        \"description\": \"Blobs will be prefixed with this when loading. Useful for avoiding collisions with blobs existing in the workspace. The output blob names specified to this op should include this prefix.\",\n        \"name\": \"add_prefix\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"default\": \"\",\n        \"description\": \"Characters in the provided blob names that match `strip_prefix` will be removed prior to saving. Also, characters that precede `strip_prefix` will be removed. Useful for removing device scope from blob names.\",\n        \"name\": \"strip_prefix\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"description\": \"The output path of the db. See the `absolute_path` arg details for options regarding the current root folder of the workspace.\",\n        \"name\": \"db\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"description\": \"List of paths to dbs to load blobs from. See the `absolute_path` arg details for options regarding the current root folder of the workspace.\",\n        \"name\": \"dbs\",\n        \"option\": \"optional\",\n        \"type\": \"string[]\"\n      },\n      {\n        \"description\": \"(type: string)* Type of db to save (options: \\\"lmdb\\\", \\\"leveldb\\\", \\\"minidb\\\").\",\n        \"name\": \"db_type\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"If nonzero, the blobs are loaded into the device that is specified in the serialized `BlobProto`. Otherwise, the device will be set as the one that the `Load` operator is being run under.\",\n        \"name\": \"keep_device\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"If nonzero, will load all blobs pointed to by the db to the workspace overwriting/creating blobs as needed.\",\n        \"name\": \"load_all\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"If True, will allow not loading all the output blobs specified in the outputs.\",\n        \"name\": \"allow_incomplete\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"description\": \"If set, used instead of output blob names to specify which blobs in the db shall be loaded. Must be the same length as number of output blobs.\",\n        \"name\": \"source_blob_names\",\n        \"option\": \"optional\",\n        \"type\": \"string[]\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: List(DBReader))* [OPTIONAL] List of DBReaders to load from. Can use this instead of the `db`/`dbs` args.\",\n        \"name\": \"X, Y, ...\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Log\",\n    \"description\": \"\\nCalculates the natural log of the given input tensor ($ln(x)$), element-wise. This\\noperation can be done in an in-place fashion too, by providing the same input\\nand output blobs.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/log_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Log\\\",\\n    [\\\"X\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,3)).astype(np.float32))\\nprint(\\\"X before running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X after running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX before running op:\\n[[0.07341351 0.15404125 0.386613  ]\\n [0.34090295 0.99727786 0.24141751]\\n [0.32016268 0.8724168  0.93515724]]\\nX after running op:\\n[[-2.6116474  -1.8705349  -0.9503311 ]\\n [-1.0761575  -0.00272586 -1.4212275 ]\\n [-1.138926   -0.13648799 -0.06704059]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor computed as the natural log of the input tensor computed, element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LogFatal\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Logit\",\n    \"description\": \"\\nElementwise logit transform: logit(x) = log(x / (1 - x)), where x is the\\ninput data clampped in (eps, 1-eps).\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"small positive epsilon value, the default is 1e-6.\",\n        \"name\": \"eps (optional)\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"input float tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output float tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LogitGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"small positive epsilon value, the default is 1e-6.\",\n        \"name\": \"eps\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"input float tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"input float tensor\",\n        \"name\": \"dY\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output float tensor\",\n        \"name\": \"dX\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LongIndexCreate\",\n    \"description\": \"\\nCreates a dictionary that maps int64 keys to consecutive integers\\nfrom 1 to max_elements. Zero is reserved for unknown keys.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Max number of elements, including the zero entry.\",\n        \"name\": \"max_elements\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LpNorm\",\n    \"description\": \"\\nThis op computes the $L_p$ norm of the one dimensional input tensor $X$, and outputs a one dimensional output tensor $Y$. Here, the $L_p$ norm is calculated as\\n\\n$$L_p(\\\\mathbf{x}) = \\\\sum_i x_i^p$$\\n\\nThis op supports $p$ values of 1 or 2. If the average argument is set, the norm is calculated as Lp_averaged_norm(x) is defined as Lp_averaged_norm(x) = LpNorm(x) / size(x).\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/lpnorm_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/lpnorm_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LpNorm\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    p=2\\n)\\nX = np.array([5., 2.])\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Feed X into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [5. 2.]\\nY:\\n [29.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 2,\n        \"description\": \"Order of the norm in p-norm.\",\n        \"name\": \"p\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Whether we calculate norm or averaged_norm.The Lp_averaged_norm(x) is defined as Lp_averaged_norm(x) = LpNorm(x) / size(x)\",\n        \"name\": \"average\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D Input tensor of data to be operated on.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LpNormGradient\",\n    \"description\": \"\\nGiven one input float tensor X, derivative dout, and produces one output\\nfloat tensor dX. dX is the derivative of the Lp norm of tensor X, computed as\\ndx = d(sum over |x^p|)/dx, in which p is either 1 or 2(currently only\\nsupports l1 and l2 norm) determined by the argument p.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Order of the norm in p-norm\",\n        \"name\": \"p\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"whehther we calculate norm or averaged_norm.The Lp_averaged_norm(x) is defined asLp_averaged_normgradient(x) = LpNormGradient(x) / size(x)\",\n        \"name\": \"average\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"dout\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"dx\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LpPool\",\n    \"description\": \"\\n`LpPool` consumes an input blob and applies max pooling across the the blob according to kernel sizes, stride sizes, pad lengths and dilation. $L_p$ pooling consists of taking the $L_p$ norm of a subset of the input tensor according to the kernel size and downsampling the data into the output blob for further processing.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the output blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/lp_pool_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LpPool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n    p=2.0\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[[[-1.1113514  -1.1173418  -0.1504435   0.1327146  -1.2221841  -0.5654315 ]\\n   [-1.9209646  -0.04675794  0.8604731   1.2042469   0.28154245   0.38656202]\\n   [-0.8772837  -0.03264008  0.26222762  0.28526652  0.321102    -2.5891325 ]\\n   [-0.9248281   1.440776   -0.56832    -0.6017927   1.2262512   -2.1443934 ]\\n   [ 0.5194415  -1.6858683   0.45221648  0.65029615 -0.8574544    0.8121054 ]\\n   [ 0.25902653  0.4934758   0.49870652 -0.48134378 -0.9178449   -0.07626943]]]]\\n\\nY:\\n [[[[2.4851248 1.49361   1.4290358]\\n   [1.9240153 0.9139378 3.5928857]\\n   [1.8500228 1.0525136 1.4976646]]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*float*): type of $L_p$ norm to use (default=2.0)\",\n        \"name\": \"p\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): the size of the window to take a max over\",\n        \"name\": \"kernel\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): the stride of the window\",\n        \"name\": \"stride\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): implicit zero padding to be added on both sides\",\n        \"name\": \"pad\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): parameter that controls the stride of elements in the window\",\n        \"name\": \"dilation\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*string*): order of blob dimensions (default=\\\"NCHW\\\")\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LpPoolGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LRN\",\n    \"category\": \"Normalization\",\n    \"description\": \"\\n\\n`LRN` applies Local Response Normalization to an input blob. This operation performs\\na kind of \\\"lateral inhibition\\\" by normalizing over local input regions, where\\nnormalization is applied across channels. This operator is typically used to\\nnormalize an unbounded activation (such as ReLU). The output shape is the same as\\nthe input shape. The `brew` module has a wrapper for this operator for use in a\\n`ModelHelper` object.\\n\\nThe formula for LRN is as follows:\\n\\n$$b_{c} = a_{c}(bias + \\\\frac{\\\\alpha}{n}\\\\sum_{c'=max(0,c-n/2)}^{min(N-1,c+n/2)} a_{c'}^2 )^{-\\\\beta}$$\\n\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/local_response_normalization_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/local_response_normalization_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\\"LRN\\\",\\n     [\\\"X\\\"],\\n     [\\\"Y\\\", \\\"Y_scale\\\"],\\n     size=11,\\n     alpha=0.001,\\n     beta=0.5,\\n     bias=2.0,\\n     order=\\\"NHWC\\\"\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 6, 6, 1).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"Y_scale:\\\\n\\\", workspace.FetchBlob(\\\"Y_scale\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[ 0.72985137]\\n   [-0.3753357 ]\\n   [ 2.7344604 ]\\n   [-0.5937792 ]\\n   [ 0.38440478]\\n   [-2.1659644 ]]\\n\\n  [[-0.92846817]\\n   [-0.9996144 ]\\n   [ 0.212943  ]\\n   [-1.968045  ]\\n   [-0.77839696]\\n   [ 0.45492038]]\\n\\n  [[-0.11263168]\\n   [ 1.9901097 ]\\n   [ 0.19275683]\\n   [ 0.15630436]\\n   [ 0.7536298 ]\\n   [-0.77339894]]\\n\\n  [[ 0.8353551 ]\\n   [-0.7784452 ]\\n   [ 1.779317  ]\\n   [ 0.22421335]\\n   [ 1.3846219 ]\\n   [-3.0546608 ]]\\n\\n  [[ 0.09977621]\\n   [ 2.2071757 ]\\n   [ 0.79971045]\\n   [ 3.563886  ]\\n   [-0.7169287 ]\\n   [ 0.77170426]]\\n\\n  [[-1.4296649 ]\\n   [ 0.19181213]\\n   [ 0.45961624]\\n   [-1.0201577 ]\\n   [ 0.62854475]\\n   [-0.6395456 ]]]]\\n\\nY:\\n [[[[ 0.5160766 ]\\n   [-0.26540157]\\n   [ 1.9332271 ]\\n   [-0.41986194]\\n   [ 0.27181432]\\n   [-1.5314047 ]]\\n\\n  [[-0.6565133 ]\\n   [-0.7068181 ]\\n   [ 0.15057328]\\n   [-1.3914955 ]\\n   [-0.5504022 ]\\n   [ 0.32167578]]\\n\\n  [[-0.0796426 ]\\n   [ 1.4070934 ]\\n   [ 0.13629955]\\n   [ 0.11052381]\\n   [ 0.53288984]\\n   [-0.5468682 ]]\\n\\n  [[ 0.5906759 ]\\n   [-0.5504363 ]\\n   [ 1.2580767 ]\\n   [ 0.1585426 ]\\n   [ 0.9790328 ]\\n   [-2.1595135 ]]\\n\\n  [[ 0.07055242]\\n   [ 1.5605361 ]\\n   [ 0.5654725 ]\\n   [ 2.5193207 ]\\n   [-0.50693923]\\n   [ 0.54567   ]]\\n\\n  [[-1.0108787 ]\\n   [ 0.13563155]\\n   [ 0.3249962 ]\\n   [-0.72134334]\\n   [ 0.44444424]\\n   [-0.45222285]]]]\\nY_scale:\\n [[[[2.0000484]\\n   [2.0000129]\\n   [2.0006797]\\n   [2.000032 ]\\n   [2.0000134]\\n   [2.0004265]]\\n\\n  [[2.0000784]\\n   [2.0000908]\\n   [2.000004 ]\\n   [2.0003521]\\n   [2.000055 ]\\n   [2.0000188]]\\n\\n  [[2.0000012]\\n   [2.00036  ]\\n   [2.0000033]\\n   [2.0000021]\\n   [2.0000517]\\n   [2.0000544]]\\n\\n  [[2.0000634]\\n   [2.000055 ]\\n   [2.0002878]\\n   [2.0000045]\\n   [2.0001743]\\n   [2.0008483]]\\n\\n  [[2.000001 ]\\n   [2.000443 ]\\n   [2.0000582]\\n   [2.0011547]\\n   [2.0000467]\\n   [2.0000541]]\\n\\n  [[2.0001857]\\n   [2.0000033]\\n   [2.0000193]\\n   [2.0000947]\\n   [2.000036 ]\\n   [2.0000372]]]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Amount of neighboring channels to sum over for normalization\",\n        \"name\": \"size\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 0.0,\n        \"description\": \"Multiplicative (scaling) factor.\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 0.0,\n        \"description\": \"Exponent.\",\n        \"name\": \"beta\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1.0,\n        \"description\": \"Additive factor.\",\n        \"name\": \"bias\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Order of blob dimensions.\",\n        \"name\": \"order\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor (ReLU output).\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output scale.\",\n        \"name\": \"Y_scale\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LRNGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LSTMUnit\",\n    \"description\": \"\\nLSTMUnit computes the activations of a standard LSTM (without peephole\\nconnections), in a sequence-length aware fashion.\\n\\nConcretely, given the (fused) inputs X (TxNxD), the previous cell\\nstate (NxD), and the sequence lengths (N), computes the LSTM\\nactivations, avoiding computation if the input is invalid (as in, the\\nvalue at X{t][n] >= seqLengths[n].\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Bias term to add in while calculating forget gate\",\n        \"name\": \"forget_bias\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"When false, the sequence lengths input is left out, and all following inputs are shifted left by one.\",\n        \"name\": \"sequence_lengths\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LSTMUnitGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"When false, the sequence lengths input is left out, and all following inputs are shifted left by one.\",\n        \"name\": \"sequence_lengths\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"LT\",\n    \"description\": \"\\nPerforms element-wise less than comparison **<** (with limited broadcast support).\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"LT\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([1, 5, 2, 9, 12, 3]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([1, 3, 4, 9, 12, 8]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA: [ 1  5  2  9 12  3]\\nB: [ 1  3  4  9 12  8]\\nC: [False False  True False False  True]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor with same dimensions as `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MakeTwoClass\",\n    \"description\": \"\\nGiven a vector of probabilities, this operator transforms this into a 2-column\\n matrix with complimentary probabilities for binary classification. In explicit\\n terms, given the vector X, the output Y is vstack(1 - X, X).\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input vector of probabilities\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2-column matrix with complimentary probabilities of X for binary classification\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MakeTwoClassGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MapToKeyValue\",\n    \"description\": \"Convert a map blob into key and value blob pairs\",\n    \"inputs\": [\n      {\n        \"description\": \"Blob reference to the map\",\n        \"name\": \"map blob\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Blob reference to the key\",\n        \"name\": \"key blob\"\n      },\n      {\n        \"description\": \"Blob reference to the value\",\n        \"name\": \"value blob\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MarginRankingCriterion\",\n    \"description\": \"\\nMarginRankingCriterion takes two input data X1 (Tensor),\\nX2 (Tensor), and label Y (Tensor) to produce the\\nloss (Tensor) where the loss function,\\nloss(X1, X2, Y) = max(0, -Y * (X1 - X2) + margin), is applied to\\nthe tensor elementwise.\\n\\nIf y == 1 then it assumed the first input should be ranked higher\\n(have a larger value) than the second input, and vice-versa for\\ny == -1.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The margin value as a float. Default is 1.0.\",\n        \"name\": \"margin\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The left input vector as a 1-dim TensorCPU.\",\n        \"name\": \"X1\"\n      },\n      {\n        \"description\": \"The right input vector as a 1-dim TensorCPU.\",\n        \"name\": \"X2\"\n      },\n      {\n        \"description\": \"The label as a 1-dim TensorCPU with int value of 1 or -1.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output loss with the same dimensionality as X1.\",\n        \"name\": \"loss\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MarginRankingCriterionGradient\",\n    \"description\": \"\\nMarginRankingCriterionGradient takes both X1, X2, Y and dY and\\nuses them to update dX1, and dX2 according to the chain rule\\nand derivatives of the loss function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MatMul\",\n    \"description\": \"\\nMatrix multiplication $Y = A * B$, where `A` has size (M x K), `B` has size\\n(K x N), and `Y` will have a size (M x N). To transpose `A` or `B` before\\nmultiplication, pass 1 to the `trans_a` and/or `trans_b` arguments, which\\nseparate the first and second dimensions of the respective matrices using\\n`axis_a` and `axis_b`.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/matmul_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"MatMul\\\",\\n    [\\\"A\\\", \\\"B\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.random.randint(10, size=(3,3)).astype(np.float32))\\nworkspace.FeedBlob(\\\"B\\\", np.random.randint(10, size=(3,3)).astype(np.float32))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nA: [[1. 8. 3.]\\n [6. 4. 4.]\\n [5. 4. 7.]]\\nB: [[4. 0. 3.]\\n [3. 1. 1.]\\n [8. 5. 8.]]\\nY: [[52. 23. 35.]\\n [68. 24. 54.]\\n [88. 39. 75.]]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Exclusive axis that divides the first and second dimension of matrix `A`.\",\n        \"name\": \"axis_a\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"Exclusive axis that divides the first and second dimension of matrix `B`.\",\n        \"name\": \"axis_b\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to transpose `A` before multiplication and after the dimension adjustment using `axis_a`.\",\n        \"name\": \"trans_a\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to transpose `B` before multiplication and after the dimension adjustment using `axis_b`.\",\n        \"name\": \"trans_b\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 2D matrix of size (M x K).\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 2D matrix of size (K x N).\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 2D matrix of size (M x N).\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Max\",\n    \"description\": \"\\nElement-wise max of an arbitrary number of input tensors. This operation can be\\nperformed in-place, by using the first input blob as the output blob. All inputs\\nmust have the same shape and data type, and the output will have the same shape\\nas the inputs.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/minmax_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Max\\\",\\n    [\\\"X\\\", \\\"Y\\\", \\\"Z\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,3)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", (np.random.rand(3,3)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Z\\\", (np.random.rand(3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"Z:\\\", workspace.FetchBlob(\\\"Z\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Max:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[0.4496477  0.07061381 0.7139333 ]\\n [0.83203    0.05970785 0.72786295]\\n [0.75988126 0.04601283 0.32820013]]\\nY:\\n[[0.05683139 0.16872478 0.671098  ]\\n [0.70739156 0.09878621 0.03416285]\\n [0.34087983 0.94986707 0.67263436]]\\nZ:\\n[[0.48051122 0.07141234 0.85264146]\\n [0.77086854 0.22082241 0.13154659]\\n [0.42401117 0.995431   0.4263775 ]]\\nMax:\\n[[0.48051122 0.16872478 0.85264146]\\n [0.83203    0.22082241 0.72786295]\\n [0.75988126 0.995431   0.67263436]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<Ord>`)* List of input tensors with the same shape.\",\n        \"name\": \"X, Y, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<Ord>`)* Output tensor with same dimensions as input(s).Contains the maximum valued element at each location.\",\n        \"name\": \"M\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool\",\n    \"category\": \"Pool\",\n    \"description\": \"MaxPool \\nconsumes an input blob and applies max pooling across the the blob according to\\nkernel sizes, stride sizes, pad lengths and dilation. Max pooling consists of\\ntaking the maximum value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"MaxPool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-2.8534958e-01 -1.7719941e+00 -8.2277227e-04  1.1088650e+00\\n    -2.1476576e+00 -3.5070452e-01]\\n   [-9.0058845e-01 -3.0070004e-01 -1.7907504e+00 -7.1746534e-01\\n     1.2798511e+00 -3.2214901e-01]\\n   [ 1.5806322e+00  1.6845188e+00 -2.6633200e-01 -3.8576153e-01\\n    -9.6424848e-02 -3.9696163e-01]\\n   [ 1.2572408e-01  6.3612902e-01 -3.9554062e-01 -6.9735396e-01\\n    -9.1898698e-01 -1.9609968e-01]\\n   [-1.1587460e+00  2.4605224e+00 -1.5497679e+00  1.3020347e-01\\n    -8.1293899e-01 -7.8803545e-01]\\n   [ 1.4323474e+00  1.3618395e+00  9.8975077e-02 -1.1307785e-01\\n     7.2035044e-01  2.7642491e-01]]]]\\n\\nY:\\n [[[[-0.28534958  1.108865    1.2798511 ]\\n   [ 1.6845188  -0.266332   -0.09642485]\\n   [ 2.4605224   0.13020347  0.72035044]]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"name\": \"order\"\n      },\n      {\n        \"default\": 0,\n        \"name\": \"pad\"\n      },\n      {\n        \"name\": \"cudnn_exhaustive_search\",\n        \"type\": \"boolean\",\n        \"visible\": false\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool1D\",\n    \"description\": \"MaxPool1D \\nconsumes an input blob and applies max pooling across the the blob according to\\nkernel sizes, stride sizes, pad lengths and dilation. Max pooling consists of\\ntaking the maximum value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"MaxPool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-2.8534958e-01 -1.7719941e+00 -8.2277227e-04  1.1088650e+00\\n    -2.1476576e+00 -3.5070452e-01]\\n   [-9.0058845e-01 -3.0070004e-01 -1.7907504e+00 -7.1746534e-01\\n     1.2798511e+00 -3.2214901e-01]\\n   [ 1.5806322e+00  1.6845188e+00 -2.6633200e-01 -3.8576153e-01\\n    -9.6424848e-02 -3.9696163e-01]\\n   [ 1.2572408e-01  6.3612902e-01 -3.9554062e-01 -6.9735396e-01\\n    -9.1898698e-01 -1.9609968e-01]\\n   [-1.1587460e+00  2.4605224e+00 -1.5497679e+00  1.3020347e-01\\n    -8.1293899e-01 -7.8803545e-01]\\n   [ 1.4323474e+00  1.3618395e+00  9.8975077e-02 -1.1307785e-01\\n     7.2035044e-01  2.7642491e-01]]]]\\n\\nY:\\n [[[[-0.28534958  1.108865    1.2798511 ]\\n   [ 1.6845188  -0.266332   -0.09642485]\\n   [ 2.4605224   0.13020347  0.72035044]]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool1DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool2D\",\n    \"description\": \"MaxPool2D \\nconsumes an input blob and applies max pooling across the the blob according to\\nkernel sizes, stride sizes, pad lengths and dilation. Max pooling consists of\\ntaking the maximum value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"MaxPool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-2.8534958e-01 -1.7719941e+00 -8.2277227e-04  1.1088650e+00\\n    -2.1476576e+00 -3.5070452e-01]\\n   [-9.0058845e-01 -3.0070004e-01 -1.7907504e+00 -7.1746534e-01\\n     1.2798511e+00 -3.2214901e-01]\\n   [ 1.5806322e+00  1.6845188e+00 -2.6633200e-01 -3.8576153e-01\\n    -9.6424848e-02 -3.9696163e-01]\\n   [ 1.2572408e-01  6.3612902e-01 -3.9554062e-01 -6.9735396e-01\\n    -9.1898698e-01 -1.9609968e-01]\\n   [-1.1587460e+00  2.4605224e+00 -1.5497679e+00  1.3020347e-01\\n    -8.1293899e-01 -7.8803545e-01]\\n   [ 1.4323474e+00  1.3618395e+00  9.8975077e-02 -1.1307785e-01\\n     7.2035044e-01  2.7642491e-01]]]]\\n\\nY:\\n [[[[-0.28534958  1.108865    1.2798511 ]\\n   [ 1.6845188  -0.266332   -0.09642485]\\n   [ 2.4605224   0.13020347  0.72035044]]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool2DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool3D\",\n    \"description\": \"MaxPool3D \\nconsumes an input blob and applies max pooling across the the blob according to\\nkernel sizes, stride sizes, pad lengths and dilation. Max pooling consists of\\ntaking the maximum value of a subset of the input tensor according to the kernel\\nsize and downsampling the data into the output blob for further processing. The\\n`brew` module has a wrapper for this operator for use in a `ModelHelper` object.\\n\\nPooling layers reduce the spatial dimensionality of the input blob. Each of the\\noutput blob's dimensions will reduce according to:\\n\\n$$dim_{out}=\\\\frac{dim_{in}-kernel+2*pad}{stride}+1$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pool_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"MaxPool\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    kernel=2,\\n    stride=2,\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 1, 6, 6).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX:\\n [[[[-2.8534958e-01 -1.7719941e+00 -8.2277227e-04  1.1088650e+00\\n    -2.1476576e+00 -3.5070452e-01]\\n   [-9.0058845e-01 -3.0070004e-01 -1.7907504e+00 -7.1746534e-01\\n     1.2798511e+00 -3.2214901e-01]\\n   [ 1.5806322e+00  1.6845188e+00 -2.6633200e-01 -3.8576153e-01\\n    -9.6424848e-02 -3.9696163e-01]\\n   [ 1.2572408e-01  6.3612902e-01 -3.9554062e-01 -6.9735396e-01\\n    -9.1898698e-01 -1.9609968e-01]\\n   [-1.1587460e+00  2.4605224e+00 -1.5497679e+00  1.3020347e-01\\n    -8.1293899e-01 -7.8803545e-01]\\n   [ 1.4323474e+00  1.3618395e+00  9.8975077e-02 -1.1307785e-01\\n     7.2035044e-01  2.7642491e-01]]]]\\n\\nY:\\n [[[[-0.28534958  1.108865    1.2798511 ]\\n   [ 1.6845188  -0.266332   -0.09642485]\\n   [ 2.4605224   0.13020347  0.72035044]]]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor of shape NCHW or NHWC.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output data tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPool3DGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MaxPoolGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Mean\",\n    \"description\": \"\\nElement-wise mean of an arbitrary number of input tensors. This operation can be\\nperformed in-place, by using the first input blob as the output blob. All inputs\\nmust have the same shape and data type, and the output will have the same shape\\nas the inputs.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/mean_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Mean\\\",\\n    [\\\"X\\\", \\\"Y\\\", \\\"Z\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,3)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", (np.random.rand(3,3)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Z\\\", (np.random.rand(3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"Z:\\\", workspace.FetchBlob(\\\"Z\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Mean:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[0.6035237  0.5305746  0.6298913 ]\\n [0.9169737  0.01280353 0.16286302]\\n [0.6017664  0.9946255  0.05128575]]\\nY:\\n[[0.07544111 0.45371833 0.08460239]\\n [0.9708728  0.7422064  0.7933344 ]\\n [0.97671497 0.3411384  0.73818344]]\\nZ:\\n[[0.08837954 0.90187573 0.46734726]\\n [0.6308827  0.8719029  0.39888734]\\n [0.90059936 0.92883426 0.5695987 ]]\\nMean:\\n[[0.25578147 0.6287229  0.39394698]\\n [0.8395764  0.5423043  0.45169494]\\n [0.8263602  0.75486606 0.45302266]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<Ord>`)* List of input tensors with the same shape.\",\n        \"name\": \"X, Y, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<Ord>`)* Output tensor with the same dimensions as inputs. Contains the mean values of the input tensors calculated element-wise.\",\n        \"name\": \"M\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeDenseFeatureTensors\",\n    \"description\": \"Merge given multi-feature dense tensors  into one multi-feature tensor.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"feature ids\",\n        \"name\": \"feature_ids\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"\",\n        \"name\": \"in1\"\n      },\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values\",\n        \"name\": \"out_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeDim\",\n    \"description\": \"\\nMerge first two dimensions in a single dimension with size dim(0) * dim(1).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"An input tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reshaped tensor.\",\n        \"name\": \"reshaped\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeIdLists\",\n    \"description\": \"\\nMergeIdLists: Merge multiple ID_LISTs into a single ID_LIST.\\n\\nAn ID_LIST is a list of IDs (may be ints, often longs) that represents a single\\nfeature. As described in https://caffe2.ai/docs/sparse-operations.html, a batch\\nof ID_LIST examples is represented as a pair of lengths and values where the\\n`lengths` (int32) segment the `values` or ids (int32/int64) into examples.\\n\\nGiven multiple inputs of the form lengths_0, values_0, lengths_1, values_1, ...\\nwhich correspond to lengths and values of ID_LISTs of different features, this\\noperator produces a merged ID_LIST that combines the ID_LIST features. The\\nfinal merged output is described by a lengths and values vector.\\n\\nWARNING: The merge makes no guarantee about the relative order of ID_LISTs\\nwithin a batch. This can be an issue if ID_LIST are order sensitive.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Lengths of the ID_LISTs batch for first feature\",\n        \"name\": \"lengths_0\"\n      },\n      {\n        \"description\": \"Values of the ID_LISTs batch for first feature\",\n        \"name\": \"values_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Lengths of the merged ID_LISTs batch\",\n        \"name\": \"merged_lengths\"\n      },\n      {\n        \"description\": \"Values of the merged ID_LISTs batch\",\n        \"name\": \"merged_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeMultiListFeatureTensors\",\n    \"description\": \"Merge given multi-feature tensors with list features into one.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"in1_keys\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"in1_values_lengths\"\n      },\n      {\n        \"description\": \".values.values\",\n        \"name\": \"in1_values_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"out_values_lengths\"\n      },\n      {\n        \"description\": \".values.values\",\n        \"name\": \"out_values_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeMultiListFeatureTensorsGradient\",\n    \"description\": \"Explode given multi-feature tensors with list features into many.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"in1_values_lengths\"\n      },\n      {\n        \"description\": \".values.values_grad\",\n        \"name\": \"out_values_values_grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".values.values_grad\",\n        \"name\": \"in1_values_values_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeMultiMapFeatureTensors\",\n    \"description\": \"Merge given multi-feature tensors with map features into one.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"in1_keys\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"in1_values_lengths\"\n      },\n      {\n        \"description\": \".values.keys\",\n        \"name\": \"in1_values_keys\"\n      },\n      {\n        \"description\": \".values.values\",\n        \"name\": \"in1_values_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values_lengths\",\n        \"name\": \"out_values_lengths\"\n      },\n      {\n        \"description\": \".values.keys\",\n        \"name\": \"out_values_keys\"\n      },\n      {\n        \"description\": \".values.values\",\n        \"name\": \"out_values_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeMultiMapFeatureTensorsGradient\",\n    \"description\": \"Explode given multi-feature tensors with map features into many.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"in1_values_lengths\"\n      },\n      {\n        \"description\": \".values.values_grad\",\n        \"name\": \"out_values_values_grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".values.values_grad\",\n        \"name\": \"in1_values_values_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeMultiScalarFeatureTensors\",\n    \"description\": \"Merge given multi-feature tensors with scalar features into one.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"in1_keys\"\n      },\n      {\n        \"description\": \".values\",\n        \"name\": \"in1_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values\",\n        \"name\": \"out_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeMultiScalarFeatureTensorsGradient\",\n    \"description\": \"Explode given multi-feature tensors with scalar features into many.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".values_grad\",\n        \"name\": \"out_values_grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".values_grad\",\n        \"name\": \"in1_values_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeSingleListFeatureTensors\",\n    \"description\": \"Merge given single-feature tensors with list features into one multi-feature tensor.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"feature ids\",\n        \"name\": \"feature_ids\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".values\",\n        \"name\": \"in1_values\"\n      },\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"out_values_lengths\"\n      },\n      {\n        \"description\": \".values.values\",\n        \"name\": \"out_values_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeSingleListFeatureTensorsGradient\",\n    \"description\": \"Explode multi-feature tensors with list features into single-feature tensors.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      },\n      {\n        \"description\": \".values.values_grad\",\n        \"name\": \"out_values_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".values_grad\",\n        \"name\": \"out1_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeSingleMapFeatureTensors\",\n    \"description\": \"Merge given single-feature tensors with map features into one multi-feature tensor.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"feature ids\",\n        \"name\": \"feature_ids\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"in1_keys\"\n      },\n      {\n        \"description\": \".values\",\n        \"name\": \"in1_values\"\n      },\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values.lengths\",\n        \"name\": \"out_values_lengths\"\n      },\n      {\n        \"description\": \".values.keys\",\n        \"name\": \"out_values_keys\"\n      },\n      {\n        \"description\": \".values.values\",\n        \"name\": \"out_values_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeSingleMapFeatureTensorsGradient\",\n    \"description\": \"Explode given multi-feature tensors with map features into multiple single-feature tensor.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"in1_lengths\"\n      },\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      },\n      {\n        \"description\": \".values.values_grad\",\n        \"name\": \"out_values_values_grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".values_grad\",\n        \"name\": \"in1_values_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeSingleScalarFeatureTensors\",\n    \"description\": \"Merge given single-feature tensors with scalar features into one multi-feature tensor.\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"feature ids\",\n        \"name\": \"feature_ids\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"\",\n        \"name\": \"in1\"\n      },\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \".lengths\",\n        \"name\": \"out_lengths\"\n      },\n      {\n        \"description\": \".keys\",\n        \"name\": \"out_keys\"\n      },\n      {\n        \"description\": \".values\",\n        \"name\": \"out_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MergeSingleScalarFeatureTensorsGradient\",\n    \"description\": \"Explode multi-feature tensor of scalar features into one or moresingle-feature tensors\\n  Single-feature representation:\\n  - scalar features:\\n    <feature full name> T\\n  - list features:\\n    <feature full name>.lengths int32\\n    <feature full name>.values T\\n  - map features:\\n    <feature full name>.lengths int32\\n    <feature full name>.keys K\\n    <feature full name>.values V\\n\\n  Missing values are set to zero, and value presence flag is set accordingly:\\n    <feature full name>.presence bool\\n\\n  Multi-feature representation:\\n  - scalar features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values T\\n  - list features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.values T\\n  - map features:\\n    <feature type>.lengths int32\\n    <feature type>.keys int64\\n    <feature type>.values.lengths int32\\n    <feature type>.values.keys K\\n    <feature type>.values.values V\\n\\n  You can read more about representing batches of lists and maps here:\\n  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/\\n\",\n    \"inputs\": [\n      {\n        \"description\": \".presence\",\n        \"name\": \"in1_presence\"\n      },\n      {\n        \"description\": \".values_grad\",\n        \"name\": \".values_grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"_grad of inputs\",\n        \"name\": \"in1_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Min\",\n    \"description\": \"\\nElement-wise min of an arbitrary number of input tensors. This operation can be performed in-place, by using the first input blob as the output blob. All inputs must have the same shape and data type, and the output will have the same shape as the inputs.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/minmax_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Min\\\",\\n    [\\\"X\\\", \\\"Y\\\", \\\"Z\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(2,2)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Y\\\", (np.random.rand(2,2)).astype(np.float32))\\nworkspace.FeedBlob(\\\"Z\\\", (np.random.rand(2,2)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"Z:\\\", workspace.FetchBlob(\\\"Z\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Min:\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[0.32731926 0.4939747 ]\\n [0.29242373 0.43460014]]\\nY:\\n[[0.40928316 0.916115  ]\\n [0.77526504 0.29339448]]\\nZ:\\n[[0.7899794  0.90335774]\\n [0.82599413 0.2843068 ]]\\nMin:\\n[[0.32731926 0.4939747 ]\\n [0.29242373 0.2843068 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<Ord>`)* List of input tensors with the same shape.\",\n        \"name\": \"X, Y, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<Ord>`)* Output tensor with same dimensions as input(s).Contains the minimum valued element at each location.\",\n        \"name\": \"M\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MinGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Mish\",\n    \"description\": \"\\nMish takes one input data (Tensor) and produces one output data\\n(Tensor) where the Mish function, y = x * tanh(ln(1 + exp(x))), is applied to the\\ntensor elementwise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MishGradient\",\n    \"description\": \"\\nMishGradient takes X, Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the Mish function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Mod\",\n    \"description\": \"\\nElement-wise modulo operation. Each element in the output is the modulo result\\nof the corresponding element in the input data. The divisor of the modulo is\\nprovided by the `divisor` argument.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/mod_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Mod\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    divisor=10\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(100, size=(5,5))))\\nprint(\\\"X before running op:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X after running op:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX before running op:\\n[[56 22 43 13 60]\\n [ 4 55 58 10 45]\\n [64 66  4  3 66]\\n [10 36 47 52 78]\\n [91  4 36 47 95]]\\nX after running op:\\n[[6 2 3 3 0]\\n [4 5 8 0 5]\\n [4 6 4 3 6]\\n [0 6 7 2 8]\\n [1 4 6 7 5]]\\n\\n ```\\n\\n </details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Divisor of the modulo operation (must be >= 1).\",\n        \"name\": \"divisor\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"If true, sign of output matches divisor, else if false, sign follows dividend.\",\n        \"name\": \"sign_follow_divisor\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<int>`)* Input tensor with int32 or int64 data.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<int>`)* Output tensor of data with modulo operation applied.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Moments\",\n    \"description\": \"\\n  Computes the mean and variance of the input tensor's element along the\\n  provided axes. The resulted tensor has the same rank as the input if keepdims\\n  equals True.\\n  If keepdims equals False, then the resulted tensor have the reduced dimension\\n  pruned.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"A list of integers, along which to reduce. If axes is not provided, the op computes the element-wise mean and variance.\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Keep the reduced dimension(s) or not, default True keeps the reduced dimension(s).\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"An input tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reduced mean tensor.\",\n        \"name\": \"mean\"\n      },\n      {\n        \"description\": \"Reduced variance tensor.\",\n        \"name\": \"variance\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MomentsGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MomentumSGD\",\n    \"description\": \"\\n\\nComputes a momentum SGD update for an input gradient and momentum\\nparameters. Concretely, given inputs (grad, m, lr) and parameters\\n(momentum, nesterov), computes:\\n\\n    if not nesterov:\\n        adjusted_gradient = lr * grad + momentum * m\\n        return (adjusted_gradient, adjusted_gradient)\\n    else:\\n        m_new = momentum * m + lr * grad\\n        return ((1 + momentum) * m_new - momentum * m, m_new)\\n\\nOutput is (grad, momentum)\\n\\nNote the difference to MomemtumSGDUpdate, which actually performs the\\nparameter update (and is thus faster).\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MomentumSGDUpdate\",\n    \"description\": \"\\n\\nPerforms a momentum SGD update for an input gradient and momentum\\nparameters. Concretely, given inputs (grad, m, lr, param) and arguments\\n(momentum, nesterov), computes:\\n\\n    if not nesterov:\\n        adjusted_gradient = lr * grad + momentum * m\\n        param = param - adjusted_gradient\\n        return (adjusted_gradient, adjusted_gradient, param)\\n    else:\\n        m_new = momentum * m + lr * grad\\n        param = param - ((1 + momentum) * m_new - momentum * m),\\n        return ((1 + momentum) * m_new - momentum * m, m_new, param)\\n\\nOutput is (grad, momentum, parameter).\\n\\nNote the difference to MomentumSGD, which returns a new gradient\\nbut does not perform the parameter update.\\n\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MSRAFill\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Mul\",\n    \"description\": \"\\nPerforms element-wise binary multiplication (with limited broadcast support).\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Mul\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([[1,2],[3,4]]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([[5,6],[7,8]]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[1 2]\\n [3 4]]\\nB:\\n[[5 6]\\n [7 8]]\\nC:\\n[[ 5 12]\\n [21 32]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Second operand. With broadcasting can be of smaller size than A. If broadcasting is disabled it should be of the same size as A.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor with same dimensions and type as A.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MulGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"MultiClassAccuracy\",\n    \"description\": \"\\nRespectively compute accuracy score for each class given a number of instances\\nand predicted scores of each class for each instance.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"2-D float tensor (N,D,) of predicted scores of each class for each data. N is the number of instances, i.e., batch size. D is number of possible classes/labels.\",\n        \"name\": \"prediction\"\n      },\n      {\n        \"description\": \"1-D int tensor (N,) of labels for each instance.\",\n        \"name\": \"labels\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D float tensor (D,) of accuracy for each class. If a class has no instance in the batch, its accuracy score is set to zero.\",\n        \"name\": \"accuracies\"\n      },\n      {\n        \"description\": \"1-D int tensor (D,) of number of instances for each class in the batch.\",\n        \"name\": \"amounts\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NanCheck\",\n    \"description\": \"Identity operator, but checks all values for nan or inf\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to check for nan/inf\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor to copy input into if no NaNs or inf. Can be in-place\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NCHW2NHWC\",\n    \"description\": \"\\nThe operator switches the order of data in a tensor from NCHW- sample index N,\\nchannels C, height H and width W, to the NHWC order (this is for 2D images).\\nIn general, this operator switches the order of data in a tensor from N C H_1\\n... H_k to N H_1 ... H_k C for k-dimensional features, and currently supports\\nk=1, 2, and 3.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input data (Tensor) in the NCHW order.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor (Tensor) in the NHWC order.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NE\",\n    \"description\": \"\\nPerforms element-wise not equal to comparison **!=** (with limited broadcast support).\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"NE\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([1, 5, 2, 9, 12, 3]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([1, 3, 4, 9, 12, 8]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\nA: [ 1  5  2  9 12  3]\\nB: [ 1  3  4  9 12  8]\\nC: [False  True  True False False  True]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor with same dimensions as `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NegateGradient\",\n    \"description\": \"\\nNegagteGradient operator in forward pass simply copies input to the\\noutput, and in backward pass, flips the sign of the output gradient\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Negative\",\n    \"description\": \"\\nComputes the element-wise negative of the input.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/negative_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Negative\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3,3).astype(np.float32)))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[0.83296907 0.61407167 0.32562155]\\n [0.59304523 0.03111175 0.29365504]\\n [0.09478621 0.5424558  0.73940724]]\\nY: [[-0.83296907 -0.61407167 -0.32562155]\\n [-0.59304523 -0.03111175 -0.29365504]\\n [-0.09478621 -0.5424558  -0.73940724]]\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 1D input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* 1D output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NGramFromCategorical\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NHWC2NCHW\",\n    \"description\": \"\\nThe operator switches the order of data in a tensor from NHWC- sample index N,\\nheight H, width H and channels C, to the NCHW order (this is for 2D images).\\nIn general, this operator switches the order of data in a tensor from N H_1 ...\\nH_k C to N C H_1 ... H_k for k-dimensional features, and currently supports\\nk=1, 2, and 3.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input data (Tensor) in the NHWC order.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor (Tensor) in the NCHW order.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Normalize\",\n    \"description\": \"\\nGiven a matrix, apply L2-normalization along the specified dimension.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"axis to normalize\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NormalizeGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"axis to normalize\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NormalizeL1\",\n    \"description\": \"\\nGiven a matrix, apply L1-normalization along the specified axis.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"axis to normalize\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NormalizePlanarYUV\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Not\",\n    \"description\": \"\\nPerforms element-wise negation on input tensor `X`.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n\\\"Not\\\",\\n[\\\"X\\\"],\\n[\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3, 3) > 0.5))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[ True False False]\\n[False False False]\\n[ True  True  True]]\\nY:\\n[[False  True  True]\\n[ True  True  True]\\n[False False False]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"*(Tensor`<bool>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(Tensor`<bool>`)* Negated output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NumpyTile\",\n    \"inputs\": [\n      {\n        \"description\": \"The input tensor.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"1-D Tensor specifying how many times to repeat each axis.\",\n        \"name\": \"repeats\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor that will contain input replicated along the given axis.\",\n        \"name\": \"tiled_data\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"OneHot\",\n    \"description\": \"\\nThe *OneHot* op accepts two inputs *indices* and *index_size_tensor*, and produces a single output *one_hots*.  For each index in *indices* the op creates a one-hot row in *one_hots* of length *index_size_tensor* where all entries are zero except the entry at the index is 1. The size of *one_hots* is *len(indices)* x *index_size_tensor*.\\n\\nGithub Links:\\n\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/one_hot_ops.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/one_hot_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"OneHot\\\",\\n    [\\\"indices\\\", \\\"index_size_tensor\\\"],\\n    [\\\"one_hots\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"indices\\\", np.array([0,1,2,3,4]).astype(np.long))\\nprint(\\\"indices:\\\\n\\\", workspace.FetchBlob(\\\"indices\\\"))\\n\\nworkspace.FeedBlob(\\\"index_size_tensor\\\", np.array([5]).astype(np.long))\\nprint(\\\"index_size_tensor:\\\\n\\\", workspace.FetchBlob(\\\"index_size_tensor\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"one_hots: \\\\n\\\", workspace.FetchBlob(\\\"one_hots\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nindices:\\n [0 1 2 3 4]\\nindex_size_tensor:\\n [5]\\none_hots:\\n [[1. 0. 0. 0. 0.]\\n [0. 1. 0. 0. 0.]\\n [0. 0. 1. 0. 0.]\\n [0. 0. 0. 1. 0.]\\n [0. 0. 0. 0. 1.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The active index for each example in the batch.\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Scalar with the size of the index. Must be in CPU context\",\n        \"name\": \"index_size_tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Matrix of size len(indices) x index_size\",\n        \"name\": \"one_hots\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Onnxifi\",\n    \"description\": \"\\n    The Onnxifi operator is a black-box operator to lower the computation to Onnxifi backend\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"(string default=\\\"\\\") Serialized ONNX model to be converted to backend representation\",\n        \"name\": \"onnx_model\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Initialization pair indicating the mapping of the name between NetDef and ONNX model\",\n        \"name\": \"initializers\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"A list of key/value pairs indicating which input index to look up for real batch size for the given max output batch size\",\n        \"name\": \"output_resize_hints\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ONNXWhile\",\n    \"description\": \"\\n*** EXPERIMENTAL. This operator is a work-in-progress. No assumption should be\\nmade about the stability or correctness of this op. ***\\n\\nGeneric Looping construct confirming to the ONNX Loop operator spec. This loop\\nhas multiple termination conditions:\\n\\n1. Trip count. Iteration count specified at runtime. Set by specifying the\\n    input M. Optional. Set to empty string to omit. Note that a static trip\\n    count (specified at graph construction time) can be specified by passing\\n    in a constant node for input M.\\n2. Loop termination condition. This is an input to the op that determines\\n    whether to run the first interation and also a loop-carried dependency for\\n    the body graph. The body graph must yield a value for the condition\\n    variable, whether this input is provided or not.\\n\\nThis table summarizes the operating modes of this operator with equivalent\\nC-style code:\\n\\nOperator inputs defined as (max_trip_count, condition_var). Omitted optional\\ninputs are represented as empty string. Concretely, in this caffe2 op an input\\nis marked as omitted by setting its 'has_{name}' argument to False.\\n\\n    input (\\\"\\\", \\\"\\\"):\\n        for (int i=0; ; ++i) {\\n          cond = ... // Note this value is ignored, but is required in the body\\n        }\\n\\n    input (\\\"\\\", cond) // Note this is analogous to a while loop\\n        bool cond = ...;\\n        for (int i=0; cond; ++i) {\\n          cond = ...;\\n        }\\n\\n    input (\\\"\\\", 1) // Note this is analogous to a do-while loop\\n        bool cond = true\\n        for (int i=0; cond; ++i) {\\n          cond = ...;\\n        }\\n\\n    input (trip_count, \\\"\\\") // Note this is analogous to a for loop\\n        int trip_count = ...\\n        for (int i=0; i < trip_count; ++i) {\\n          cond = ...; // ignored\\n        }\\n\\n    input (trip_count, cond)\\n        int trip_count = ...;\\n        bool cond = ...;\\n        for (int i=0; i < trip_count && cond; ++i) {\\n          cond = ...;\\n        }\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"Net executed on each iteration\",\n        \"name\": \"body\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Whether to use the trip count input\",\n        \"name\": \"has_trip_count\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Whether to use the condition input\",\n        \"name\": \"has_cond\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Whether to save the scopes across iterations, as in for backprop\",\n        \"name\": \"save_scopes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Do not create new scopes. Use this only if you're certain there will be no name collision, for example if you're converting from a fully-SSA IR\",\n        \"name\": \"disable_scopes\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Number of iterations to go out to. Used if the flag has_trip_count is True.\",\n        \"name\": \"max_trip_count\"\n      },\n      {\n        \"name\": \"condition\"\n      },\n      {\n        \"name\": \"initial\",\n        \"option\": \"variadic\"\n      },\n      {\n        \"description\": \"Dynamic condition value for the first iteration. For all subsequent iterations, the condition from the body graph is used. This input is used if the flag has_cond is true.\",\n        \"name\": \"first_iter_condition\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"final_and_scan_outputs\",\n        \"option\": \"variadic\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Or\",\n    \"description\": \"\\nPerforms element-wise logical operation **or** (with limited broadcast support).\\nBoth input operands should be of type `bool`.\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Or\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", (np.random.rand(3, 3) > 0.5))\\nworkspace.FeedBlob(\\\"B\\\", (np.random.rand(3, 3) > 0.5))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[False  True  True]\\n [False  True  True]\\n [ True  True  True]]\\nB:\\n[[False  True False]\\n [ True  True  True]\\n [False  True False]]\\nC:\\n[[False  True  True]\\n [ True  True  True]\\n [ True  True  True]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor of booleans. Has same dimensions as input `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PackedInt8BGRANHWCToNCHWCStylizerPreprocess\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PackRecords\",\n    \"description\": \"\\nGiven a dataset under a schema specified by the `fields` argument, pack all\\nthe input tensors into one, where each tensor element represents a row of data\\n(batch of size 1). This format allows easier use with the rest of Caffe2\\noperators.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of strings representing the string names in the formatspecified in the doc for CreateTreeCursor.\",\n        \"name\": \"fields\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"One dimensional tensor having a complex type of SharedTensorVectorPtr. In order to reverse it back to the original input it has to be inserted into UnPackRecordsOp.\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PackRNNSequence\",\n    \"description\": \"\\nPack values based on the length blob. Each number from length blob represents\\nthe corresponding values that need to be packed. The dimension for each pack\\nis the same as the maximum number from the length blob (padding with zero is\\nimplemented for smaller length value). The overall output dimension is:\\nT * N * D, where T is the max number of lengths, N is the size of lengths,\\nand D is the dimension of each feature value. The following example shows\\nthe input and output of this operator:\\n\\n\\nGiven:\\n  values = [v1, v2, v3, v4, v5, v6, v7, v8]\\n  lengths = [2, 3, 1, 2];\\n\\n\\nOutput:\\n  output = [\\n    [v1, v3, v6, v7],\\n    [v2, v4, 0,  v8],\\n    [0,  v5, 0,  0 ],\\n  ]\\n\\n\\nOne application for this operator is the transfer data into the format that is\\nused for RNN models. Note that the gradient operator of PackRNNSequence is\\nUnpackRNNSequence.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Data tensor, contains a sequence of features\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"lengths with each number representing the pack size.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor after packing\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PackSegments\",\n    \"description\": \"Map N dim tensor to N+1 dim based on length blob. Sequences that     are shorter than the longest sequence are padded with zeros.\",\n    \"attributes\": [\n      {\n        \"description\": \"The pre-defined max_length for the packed segments\",\n        \"name\": \"max_length\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Padding number in the packed segments. Use true to pad     -infinity, otherwise pad zeros\",\n        \"name\": \"pad_minf\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool whether to return presence mask, false by default\",\n        \"name\": \"return_presence_mask\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1-d int/long tensor contains the length in each of the output.\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"N dim Tensor.\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"N + 1 dim Tensorwhere dim(1) is the max length, dim(0) is the batch size.\",\n        \"name\": \"packed_tensor\"\n      },\n      {\n        \"description\": \"2 dim boolean tensor, false where packed_tensor is padded, true otherwise.\",\n        \"name\": \"presence_mask\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PadEmptySamples\",\n    \"description\": \"\\nPad empty field given lengths and index features,\\n\\nInput(0) is a blob pointing to the lengths of samples in one batch,\\n[Input(1),... Input(num_fields)] a list of tensors containing the data for\\neach field of the features.\\n\\nPadEmptySamples is thread safe.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the lengths.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing lengths with empty sample padded.\",\n        \"name\": \"out_lengths\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PadImage\",\n    \"description\": \"\\nPadImage pads values around the boundary of an image according to the pad\\nvalues and stride sizes defined by the ConvPoolOpBase operator.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input data tensor from the previous operator; dimensions depend on whether the NCHW or NHWC operators are being used. For example, in the former, the input has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. The corresponding permutation of dimensions is used in the latter case. \",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data tensor from padding the H and W dimensions on the tensor. Dimensions will vary based on various pad and stride sizes.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PadImageGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PairWiseLoss\",\n    \"description\": \"\\nOperator computes the pair wise loss between all pairs within a batch\\n using the logit loss function on the difference in scores between pairs\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input blob from the previous layer, which is almost always the result of a softmax operation; X is a 2D array of size N x 1where N is the batch size. For more info: D. Sculley, Large Scale Learning to Rank. https://www.eecs.tufts.edu/~dsculley/papers/large-scale-rank.pdf\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Blob containing the labels used to compare the input\",\n        \"name\": \"label\"\n      },\n      {\n        \"description\": \"Optional input blob that contains the lengthsof multiple sessions. The summation of this blob must be equalto the size of blob X. If lengths blob is provided, the outputblob has the same size as lengths blob, and the cross entropyis computed within each session.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output blob after the cross entropy computation\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PairWiseLossGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Partition\",\n    \"description\": \"\\nSplits the input int tensor into multiple ones according to the first tensor.\\n\\nTakes the first input and partitions it to shards according to the remainder of\\nvalues modulo the number of partitions. It requires that the first tensor is of\\nintegral type. The number of partitions is derived as (num_output / num_input).\\n\\nIf additional inputs are present they must have the same shape as the first\\ninput, optionally with extra trailing dimensions. They will be partitioned\\naccordingly to the first input.\\n\\nOptional arg 'pack_first_input' transforms the first tensor values as\\nX_ij / num_partitions.\\n\\nOutputs are ordered as\\nX_0_part_0, X_1_part_0, ..., X_N-1_part_0, X_0_part_1, ..., X_N-1_part_K-1\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) If set, the operator transforms the first tensor values as floor(X_ij / num_partitions)\",\n        \"name\": \"pack_first_input\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor containing data to be partitioned. The number of input tensors might be greater than 1 but must have the same shape as the previous tensors.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output Partitions. The number of output tensors has to be a multiple of the number of input tensors.\",\n        \"name\": \"partitions\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Percentile\",\n    \"description\": \"\\n    This operator is used to find percentile representations for raw values, given a sample\\n    set of raw values, labeled with their corresponding percentiles from the same distribution.\\n    In particular, this operator takes as input a tensor of floats to find the percentile values\\n    for, a 2D tensor of floats, where the first column of the tensor represents sampled values,\\n    and the second column represents the percentile labels, and a tensor  of integers lengths.\\n\\n    This lengths tensor is used because the operator works on multiple sets of raw values at the same time. For\\n    example, for an input:\\n    original_values=[[3, 5, 3],[5, 1, 6]], lengths = [2, 1, 1], value_to_pct = [[3, 0.2], [5, 0.5], [1, 0.3], [3. 0.6]]\\n\\n    Our operator expects that each column i of the input tensor is sampled from distribution i. Lengths tells\\n    us that the first two elements in value_to_pct are sampled from distribution 1, the next is from distribution two,\\n    and the last is from distribution 3. We expect the output of our operator to give us [[0.2, 1.0, 0.6], [0.5, 0.3, 1.0]].\\n\\n    To calculate the percentile of an element, we check to see if its value is already mapped to\\n    a percentile in value_to_pct. If so, we return that value. If not, we linearly interpolate between\\n    the two closest values in value_to_pct. If the value is larger than all values in value_to_pct, we\\n    return 1. If it's smaller than all the values, we return 0.\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input 2D tensor of floats, representing the original, raw data to calculate percentiles for.\",\n        \"name\": \"original_values\"\n      },\n      {\n        \"description\": \"Sorted 2D tensor, with 2 columns. Each element in the first column is a float representing the raw value of a sample. Its corresponding element in the next column represents the percentile it maps to.\",\n        \"name\": \"value_to_pct\"\n      },\n      {\n        \"description\": \"1D tensor, representing the length of each distribution. We expect that the sum of elements of this tensor is equal to the total length of value_to_pct.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of floats, with the same dimensions as the flattened input tensor. Each element of this tensor, percentile_values[i], corresponds to the percentile calculated for original_values[i].\",\n        \"name\": \"percentile_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Perplexity\",\n    \"description\": \"\\nPerplexity calculates how well a probability distribution predicts a sample.\\nPerplexity takes a 1-D tensor containing a batch of probabilities. Each value\\nin the tensor belongs to a different sample and represents the probability of\\nthe model predicting the true label for that sample. The operator returns a\\nsingle (float) perplexity value for the batch.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The input data as Tensor. It contains a batch oftrue label or target probabilities\",\n        \"name\": \"probabilities\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output- a single (float) perplexity value for the batch\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PiecewiseLinearTransform\",\n    \"description\": \"\\nPiecewiseLinearTransform takes inputs -- predictions, a 2-D or 1-D tensor\\n(Tensor) of size (batch_size x prediction_dimensions). The piecewise\\nlinear functions are stored in bounds, slopes and intercepts. The output tensor\\nhas the same shape of input `predictions` and contains the predictions\\ntransformed by the piecewise linear functions. Each column of predictions has\\nits own piecewise linear transformation functions. Therefore the size of\\npiecewise function parameters are pieces x prediction_dimensions, except for\\nbinary predictions where only the positive prediction needs them. Note that in\\neach piece, low bound is excluded while high bound is included. Also the\\npiecewise linear function must be continuous.\\n\\nNotes\\n- If the input is binary predictions (Nx2 or Nx1 tensor), set the binary arg\\nto true so that one group of piecewise linear functions is needed (see\\ndetails below).\\n- The transform parameters (bounds, slopes, intercepts) can be passed either\\nthrough args or through input blobs.\\n- If we have multiple groups of piecewise linear functions, each group has the\\nsame number of pieces.\\n- If a prediction is out of the bounds, it is capped to the smallest or largest\\nbound.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"1-D vector of size (prediction_dimensions x (pieces+1)) contain the upper bounds of each piece of linear function. One special case is the first bound is the lower bound of whole piecewise function and we treat it the same as the left most functions. (bounds, slopes, intercepts) can be passed through either arg or input blobs.\",\n        \"name\": \"bounds\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1-D vector of size (prediction_dimensions x pieces) containing the slopes of linear function\",\n        \"name\": \"slopes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1-D vector of size (prediction_dimensions x pieces) containing the intercepts of linear function\",\n        \"name\": \"intercepts\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"If set true, we assume the input is a Nx1 or Nx2 tensor. If it is Nx1 tensor, it is positive predictions. If the input is Nx2 tensor, its first column is negative predictions and second column is positive and negative + positive = 1. We just need one group of piecewise linear functions for the positive predictions.\",\n        \"name\": \"binary\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2-D tensor (Tensor) of size (num_batches x num_classes) containing scores\",\n        \"name\": \"predictions\"\n      },\n      {\n        \"description\": \"See bounds in Arg. (bounds, slopes, intercepts) can be passed through either arg or input blobs.\",\n        \"name\": \"bounds (optional)\"\n      },\n      {\n        \"description\": \"See slopes in Arg. (bounds, slopes, intercepts) can be passed through either arg or input blobs.\",\n        \"name\": \"slopes (optional)\"\n      },\n      {\n        \"description\": \"See intercepts in Arg. (bounds, slopes, intercepts) can be passed through either arg or input blobs.\",\n        \"name\": \"intercepts (optional)\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"2-D tensor (Tensor) of size (num_batches x num_classes) containing transformed predictions\",\n        \"name\": \"transforms\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Pow\",\n    \"description\": \"\\nThe *Pow* op takes an input data tensor $X$ and an exponent parameter *exponent*, which can be a scalar or another tensor. As output, it produces a single output data tensor $Y$, where the function $f(x) = x^{exponent}$ has been applied to $X$ elementwise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pow_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/pow_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Pow\\\",\\n    [\\\"X\\\", \\\"exponent\\\"],\\n    [\\\"Y\\\"],\\n    broadcast=1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.array([1,2,3,4,5,6]).astype(np.float32))\\nprint(\\\"X: \\\", workspace.FetchBlob(\\\"X\\\"))\\n\\nworkspace.FeedBlob(\\\"exponent\\\", np.array([2]).astype(np.float32))\\nprint(\\\"exponent: \\\", workspace.FetchBlob(\\\"exponent\\\"))\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y: \\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:  [1. 2. 3. 4. 5. 6.]\\nexponent:  [2.]\\nY:  [ 1.  4.  9. 16. 25. 36.]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The exponent of the power function. Do not use if setting exponent via input.\",\n        \"name\": \"exponent\",\n        \"option\": \"optional\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob to be operated on.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"Exponent blob containing the exponent(s) for calculation. Do not use if setting exponent via argument.\",\n        \"name\": \"exponent\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob with the same shape as the input.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PRelu\",\n    \"category\": \"Activation\",\n    \"description\": \"\\n\\nThe *PRelu* op takes input data tensor $X$, an input slope tensor $slope$, and produces one output tensor $Y$ of the same shape as $X.$ The op performs the element wise *PRelu* operation, defined as\\n\\n$$y=prelu(x) =\\\\begin{cases}slope * x & x < 0\\\\\\\\x & otherwise\\\\end{cases}$$\\n\\nNote, is slope is size 1, the value is shared across the channels, otherwise $X$ and $slope$ must be the same shape. See [Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification](https://arxiv.org/abs/1502.01852) for more information.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/prelu_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/prelu_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"PRelu\\\",\\n    [\\\"X\\\",\\\"Slope\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.FeedBlob(\\\"Slope\\\", np.array([0.1]).astype(np.float32))\\nprint(\\\"Slope:\\\\n\\\", workspace.FetchBlob(\\\"Slope\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[ 0.3957382  -0.19725518 -0.26991343]\\n [ 1.5513182  -0.27427664 -0.14584002]\\n [-0.4121164   0.9292345   0.96426094]]\\n\\nSlope:\\n [0.1]\\n\\nY:\\n [[ 0.3957382  -0.01972552 -0.02699134]\\n [ 1.5513182  -0.02742766 -0.014584  ]\\n [-0.04121164  0.9292345   0.96426094]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor of data to be operated on.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D input slope tensor. If `Slope` is of size 1, the value is shared across different channels\",\n        \"name\": \"Slope\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor, with same shape as $X$.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PReluGradient\",\n    \"description\": \"\\n\\nPReluGradient takes both Y and dY and uses this to update dX and dW according\\nto the chain rule and derivatives of the rectified linear function.\\n\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PrependDim\",\n    \"description\": \"\\nReshape the tensor by prepending a dimension of fixed size and dividing the\\nsize of the next dimension by that amount.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Size of the dimension to prepend.\",\n        \"name\": \"dim_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"An input tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reshaped tensor.\",\n        \"name\": \"reshaped\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Print\",\n    \"description\": \"Logs shape and contents of input tensor to stderr or to a file.\",\n    \"attributes\": [\n      {\n        \"description\": \"(bool) if 1, saves contents to the root folder of the current workspace, appending the tensor contents to a file named after the blob name. Otherwise, logs to stderr.\",\n        \"name\": \"to_file\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int, default 0) If set, prints the first `limit` elements of tensor. If 0, prints the first `k_limit_default`(1000) elements of tensor\",\n        \"name\": \"limit\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int, default 1) Print tensor every `every_n` runs\",\n        \"name\": \"every_n\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The tensor to print.\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Python\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PythonDLPack\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PythonDLPackGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PythonGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"QuantDecode\",\n    \"description\": \"\\nDecode inputs using codebook. This is a general LUT operator that returns\\ntensors with values from codebook (input 0) based on given indices in\\ncodes (input 1 ~ n).\\n\\n\\nExample:\\n\\n\\nInput:\\n  codebook = [1.5, 2.5, 3.5]\\n  codes_0 = [0, 1, 1, 2]\\n  codes_1 = [2, 0, 0]\\n\\n\\nOutput:\\n  decoded_0 = [1.5, 2.5, 2.5, 3.5]\\n  decoded_1 = [3.5, 1.5, 1.5]\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Codebook in 1d tensor (float)\",\n        \"name\": \"codebook\"\n      },\n      {\n        \"description\": \"Encoded codes 0 (uint8/uint16/int32)\",\n        \"name\": \"codes_0\"\n      },\n      {\n        \"description\": \"Encoded codes 1 if existed (uint8/uint16/int32)\",\n        \"name\": \"codes_1\"\n      },\n      {\n        \"description\": \"Encoded codes n if existed (uint8/uint16/int32)\",\n        \"name\": \"codes_n\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Decoded tensor for codes_0 (float)\",\n        \"name\": \"decoded_0\"\n      },\n      {\n        \"description\": \"Decoded tensor for codes_1 (float)\",\n        \"name\": \"decoded_1\"\n      },\n      {\n        \"description\": \"Decoded tensor for codes_n (float)\",\n        \"name\": \"decoded_n\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"QuantDecodeGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Quantile\",\n    \"description\": \"\\n    Calculate the quantile for the value in the given list of tensors.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"If true (default), apply abs() on the tensor values.\",\n        \"name\": \"abs\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"multiplicative tolerance of the quantile_value.\",\n        \"name\": \"tol\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* List of input tensors.\",\n        \"name\": \"X1, X2, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Value at the given quantile\",\n        \"name\": \"quantile_value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Range\",\n    \"description\": \"\\nGenerates an output tensor within the half-open interval $[start, stop)$ (the interval including start but excluding stop).\\n- The `start` input is optional, and defaults to 0 when not set.\\n- The `step` input is optional, and defaults to 1 when not set.\\n- The type of the `output` tensor is determined by the types of inputs used.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/utility_ops.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/utility_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Range\\\",\\n    [\\\"start\\\", \\\"stop\\\", \\\"step\\\"],\\n    [\\\"output\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"start\\\", np.array(4, dtype=np.int32))\\nworkspace.FeedBlob(\\\"stop\\\", np.array(17, dtype=np.int32))\\nworkspace.FeedBlob(\\\"step\\\", np.array(2, dtype=np.int32))\\nprint(\\\"start:\\\", workspace.FetchBlob(\\\"start\\\"))\\nprint(\\\"stop:\\\", workspace.FetchBlob(\\\"stop\\\"))\\nprint(\\\"step:\\\", workspace.FetchBlob(\\\"step\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output:\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nstart: 4\\nstop: 17\\nstep: 2\\noutput: [ 4  6  8 10 12 14 16]\\n\\n```\\n\\n</details>\\n        \",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): [OPTIONAL] scalar or 1-element tensor containing the start of the interval (inclusive) (default=0)\",\n        \"name\": \"start\"\n      },\n      {\n        \"description\": \"(*Tensor*): scalar or 1-element tensor containing the end of the interval (exclusive)\",\n        \"name\": \"stop\"\n      },\n      {\n        \"description\": \"(*Tensor*): [OPTIONAL] scalar or 1-element tensor specifying the spacing between values (default=1)\",\n        \"name\": \"step\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): 1D tensor of same type as inputs that contains the sequence\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RangeFill\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReadNextBatch\",\n    \"description\": \"\\nRead the next batch of examples out of the given cursor and data blobs.\\n\\nInput(0) is a blob pointing to a TreeCursor, and\\n[Input(1),... Input(num_fields)] a list of tensors containing the data for\\neach field of the dataset.\\n\\nReadNextBatch is thread safe.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of top-level entries to read.\",\n        \"name\": \"batch_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the cursor.\",\n        \"name\": \"cursor\"\n      },\n      {\n        \"description\": \"First dataset field\",\n        \"name\": \"dataset_field_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing the next batch for field 0.\",\n        \"name\": \"field_0\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReadRandomBatch\",\n    \"description\": \"\\nRead the next batch of examples out of the given cursor,\\nidx blob, offset matrix and data blobs.\\n\\nInput(0) is a blob pointing to a TreeCursor,\\nInput(1) is a blob pointing to the shuffled idx\\nInput(2) is a blob pointing to the offset matrix and\\n[Input(3),... Input(num_fields)] a list of tensors containing the data for\\neach field of the dataset.\\n\\nReadRandomBatch is thread safe.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of top-level entries to read.\",\n        \"name\": \"batch_size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(bool) Repeat the dataset indefinitely\",\n        \"name\": \"loop_over\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the cursor.\",\n        \"name\": \"cursor\"\n      },\n      {\n        \"description\": \"idx with a shuffled order.\",\n        \"name\": \"idx\"\n      },\n      {\n        \"description\": \"offset matrix containing length offset info.\",\n        \"name\": \"offsetsmat\"\n      },\n      {\n        \"description\": \"First dataset field\",\n        \"name\": \"dataset_field_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing the next batch for field 0.\",\n        \"name\": \"field_0\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReceiveTensor\",\n    \"description\": \"\\nReceives the tensor from another node.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) he rank to receive the tensor from.\",\n        \"name\": \"src\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) a tag to receive the tensor with.\",\n        \"name\": \"tag\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(bool) if set, only send the content and assume that the receiver has already known the tensor's shape and information.\",\n        \"name\": \"raw_buffer\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"In-place output. If raw_buffer is specified, Y should have pre-allocated data and type..\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"An int CPUtensor of size 1 specifying the rank. If given, this overrides the 'from' argument of the op.\",\n        \"name\": \"src\"\n      },\n      {\n        \"description\": \"An int CPUtensor of size 1 specifying the tag to send the tensor with. This overrides the 'tag' argument of the op.\",\n        \"name\": \"tag\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The received tensor.\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"The sender that sent the message as a CPUTensor of size 1 and of type int.\",\n        \"name\": \"src\"\n      },\n      {\n        \"description\": \"The tag that the message is sent with as a CPUTensor of size 1 and of type int.\",\n        \"name\": \"tag\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Reciprocal\",\n    \"description\": \"\\nPerforms element-wise reciprocal ($\\\\1/x$) of input tensor $X$.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reciprocal_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Reciprocal\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(3,3))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[8. 3. 3.]\\n [4. 0. 0.]\\n [1. 2. 5.]]\\nY:\\n[[0.125 0.3333333  0.3333333 ]\\n [0.25  inf        inf       ]\\n [1     0.5        0.2       ]]\\n\\n```\\n\\n</details>\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReciprocalGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RecurrentNetwork\",\n    \"description\": \"\\nRun the input network in a recurrent fashion. This can be used to\\nimplement fairly general recurrent neural networks (RNNs).\\n\\nThe operator proceeds as follows.\\n\\n- First, initialized the states from the input recurrent states\\n- For each timestep T, apply the links (that map offsets from input/output\\ntensors into the inputs/outputs for the `step` network)\\n- Finally, alias the recurrent states to the specified output blobs.\\n\\nThis is a fairly special-case meta-operator, and so the implementation\\nis somewhat complex. It trades of generality (and frankly usability)\\nagainst performance and control (compared to e.g. TF\\ndynamic_rnn, Theano scan, etc).\\n\\nSee the usage examples for a flavor of how to use it.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RecurrentNetworkBlobFetcher\",\n    \"description\": \"\\nRetrieves blobs from scratch workspaces (which contain intermediate recurrent\\nnetwork computation for each timestep) and puts them in the global\\nworkspace under CPUContext.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Prefix string to prepend extracted blobs.\",\n        \"name\": \"prefix\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Name of scratch workspace blob returned by recurrent network.\",\n        \"name\": \"ScratchWorkspaceBlob\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of strings containing extracted blob names.\",\n        \"name\": \"blob_names\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RecurrentNetworkGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Reduce\",\n    \"description\": \"\\nDoes a reduce operation from every node to the root node. Currently only\\nSum is supported.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) the root to run reduce into.\",\n        \"name\": \"root\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"A tensor to be reduced.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The reduced result on root, not set for other nodes.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceBackMax\",\n    \"description\": \"\\nReduces the input tensor along the last dimension of the by applying **max**.\\n\\nCan reduce more than one of the \\\"last\\\" dimensions by setting `num_reduce_dim`.\\n\\nA second (optional) input, `lengths`, can be passed, which enforces that only a subset of the elements are considered in the max operation.\\n- If input tensor `X` has shape $(d_0, d_1, d_2, ..., d_n)$, `lengths` must have shape $(d_0 * d_1 * d_2 * ... * d_{n-1})$.\\n- The values of the `lengths` tensor determine how many of the values to consider for each vector in the $d_{n-1}$ dimension.\\n\\nFor example if $X = [[1,5,2,9],[4,1,8,2],[2,7,0,3]]$ and $lengths = [2,3,1]$, then $Y = [max(1,5), max(4,1,8), max(2)] = [5, 8, 2]$\\n\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_front_back_max_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceBackMax\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    num_reduce_dim=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[2. 5. 1.]\\n   [6. 1. 9.]\\n   [8. 5. 9.]]\\n\\n  [[5. 7. 8.]\\n   [9. 9. 6.]\\n   [6. 5. 0.]]]]\\nY: [[9. 9.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of dimensions to reduce (default=1)\",\n        \"name\": \"num_reduce_dims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): number of elements in each sample\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceBackMaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceBackMean\",\n    \"description\": \"\\nReduces the input tensor along the last dimension of the by applying **mean**.\\n\\nCan reduce more than one of the \\\"last\\\" dimensions by setting `num_reduce_dim`.\\n\\nA second (optional) input, `lengths`, can be passed, which enforces that only a subset of the elements are considered in the mean operation.\\n- If input tensor `X` has shape $(d_0, d_1, d_2, ..., d_n)$, `lengths` must have shape $(d_0 * d_1 * d_2 * ... * d_{n-1})$.\\n- The values of the `lengths` tensor determine how many of the values to consider for each vector in the $d_{n-1}$ dimension.\\n\\nFor example if $X = [[1,5,2,9],[4,1,8,2],[2,7,0,3]]$ and $lengths = [2,3,1]$, then $Y = [mean(1,5), mean(4,1,8), mean(2)] = [3, 4.333, 2]$\\n\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_front_back_mean_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceBackMean\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    num_reduce_dim=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[5. 9. 0.]\\n   [8. 4. 0.]\\n   [2. 2. 4.]]\\n\\n  [[9. 0. 9.]\\n   [7. 9. 7.]\\n   [1. 0. 2.]]]]\\nY: [[3.7777777 4.888889 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of dimensions to reduce (default=1)\",\n        \"name\": \"num_reduce_dims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): number of elements in each sample\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceBackMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceBackSum\",\n    \"description\": \"\\nReduces the input tensor along the last dimension of the by applying **sum**.\\n\\nCan reduce more than one of the \\\"last\\\" dimensions by setting `num_reduce_dim`.\\n\\nA second (optional) input, `lengths`, can be passed, which enforces that only a subset of the elements are considered in the sum operation.\\n- If input tensor `X` has shape $(d_0, d_1, d_2, ..., d_n)$, `lengths` must have shape $(d_0 * d_1 * d_2 * ... * d_{n-1})$.\\n- The values of the `lengths` tensor determine how many of the values to consider for each vector in the $d_{n-1}$ dimension.\\n\\nFor example if $X = [[1,5,2,9],[4,1,8,2],[2,7,0,3]]$ and $lengths = [2,3,1]$, then $Y = [sum(1,5), sum(4,1,8), sum(2)] = [6, 13, 2]$\\n\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_front_back_sum_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceBackSum\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    num_reduce_dim=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[2. 7. 7.]\\n   [1. 1. 0.]\\n   [9. 7. 2.]]\\n\\n  [[6. 6. 4.]\\n   [1. 2. 6.]\\n   [6. 6. 3.]]]]\\nY: [[36. 40.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of dimensions to reduce (default=1)\",\n        \"name\": \"num_reduce_dims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): number of elements in each sample\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceBackSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontMax\",\n    \"description\": \"\\nReduces the input tensor along the last dimension of the by applying **max**.\\n\\nCan reduce more than one of the \\\"first\\\" dimensions by setting `num_reduce_dim`.\\n\\nA second (optional) input, `lengths`, can be passed, which enforces that only a subset of the elements are considered in the max operation.\\n- If input tensor `X` has shape $(d_0, d_1, d_2, ..., d_n)$, `lengths` must have shape $(d_1 * d_2 * ... * d_{n})$.\\n- The values of the `lengths` tensor determine how many of the values to consider for each vector in the $d_{0}$ dimension.\\n\\nFor example if $X = [[1,5,2,9],[4,1,8,2],[2,7,0,3]]$ and $lengths = [2,3,1,2]$, then $Y = [max(1,4), max(5,1,7), max(2), max(9,2)] = [4, 7, 2, 9]$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_front_back_max_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceFrontMax\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    num_reduce_dim=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(2,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[2. 8. 1.]\\n  [9. 6. 6.]\\n  [7. 7. 0.]]\\n\\n [[4. 3. 9.]\\n  [9. 2. 7.]\\n  [6. 4. 7.]]]\\nY: [9. 8. 9.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of dimensions to reduce (default=1)\",\n        \"name\": \"num_reduce_dims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): number of elements in each sample\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontMaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontMean\",\n    \"description\": \"\\nReduces the input tensor along the last dimension of the by applying **mean**.\\n\\nCan reduce more than one of the \\\"first\\\" dimensions by setting `num_reduce_dim`.\\n\\nA second (optional) input, `lengths`, can be passed, which enforces that only a subset of the elements are considered in the mean operation.\\n- If input tensor `X` has shape $(d_0, d_1, d_2, ..., d_n)$, `lengths` must have shape $(d_1 * d_2 * ... * d_{n})$.\\n- The values of the `lengths` tensor determine how many of the values to consider for each vector in the $d_{0}$ dimension.\\n\\nFor example if $X = [[1,5,2,9],[4,1,8,2],[2,7,0,3]]$ and $lengths = [2,3,1,2]$, then $Y = [mean(1,4), mean(5,1,7), mean(2), mean(9,2)] = [2.5, 4.333, 2, 5.5]$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_front_back_mean_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceFrontMean\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    num_reduce_dim=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(2,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[5. 0. 9.]\\n  [4. 1. 1.]\\n  [9. 0. 8.]]\\n\\n [[2. 6. 7.]\\n  [6. 2. 6.]\\n  [0. 4. 5.]]]\\nY: [4.3333335    2.1666667     6.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of dimensions to reduce (default=1)\",\n        \"name\": \"num_reduce_dims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): number of elements in each sample\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontSum\",\n    \"description\": \"\\nReduces the input tensor along the last dimension of the by applying **sum**.\\n\\nCan reduce more than one of the \\\"first\\\" dimensions by setting `num_reduce_dim`.\\n\\nA second (optional) input, `lengths`, can be passed, which enforces that only a subset of the elements are considered in the sum operation.\\n- If input tensor `X` has shape $(d_0, d_1, d_2, ..., d_n)$, `lengths` must have shape $(d_1 * d_2 * ... * d_{n})$.\\n- The values of the `lengths` tensor determine how many of the values to consider for each vector in the $d_{0}$ dimension.\\n\\nFor example, if $X = [[1,5,2,9],[4,1,8,2],[2,7,0,3]]$ and $lengths = [2,3,1,2]$, then $Y = [sum(1,4), sum(5,1,7), sum(2), sum(9,2)] = [2.5, 4.333, 2, 5.5]$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_front_back_sum_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceFrontSum\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    num_reduce_dim=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(2,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[4. 1. 1.]\\n  [0. 6. 7.]\\n  [7. 8. 6.]]\\n\\n [[5. 7. 7.]\\n  [0. 1. 6.]\\n  [2. 9. 0.]]]\\nY: [18. 32. 27.]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of dimensions to reduce (default=1)\",\n        \"name\": \"num_reduce_dims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): number of elements in each sample\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontWeightedSum\",\n    \"description\": \"\\nReduces the input tensor along the first dimension of the input tensor by\\napplying 'WeightedSum'. This op acts in a similar way to SortedSegmentWeightedSum and\\nUnsortedSegmentWeightedSum but as if all input slices belong to a single segment.\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceFrontWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceL1\",\n    \"description\": \"\\nComputes the **L1 norm** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceL1\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    axes=(0,1),\\n    keepdims=0\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,5,5)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[ 2.  7.  6.  4.  5.]\\n   [ 2.  1.  9.  8.  7.]\\n   [ 4.  9.  1.  0.  0.]\\n   [ 6.  4.  0.  8.  1.]\\n   [ 1.  7.  1.  0.  2.]]\\n\\n  [[ 5.  8.  1.  7.  7.]\\n   [ 4.  5.  6.  5.  4.]\\n   [ 1.  9.  6.  6.  3.]\\n   [ 6.  6.  8.  8.  4.]\\n   [ 2.  3.  5.  8.  1.]]]]\\n\\nY:\\n[[  7.  15.   7.  11.  12.]\\n [  6.   6.  15.  13.  11.]\\n [  5.  18.   7.   6.   3.]\\n [ 12.  10.   8.  16.   5.]\\n [  3.  10.   6.   8.   3.]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*Tuple(int)*): list of axes to reduce\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceL1Gradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceL2\",\n    \"description\": \"\\nComputes the **L2 norm** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceL2\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    axes=(0,1),\\n    keepdims=0\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,5,5)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[ 8.  0.  2.  5.  1.]\\n   [ 1.  3.  0.  4.  0.]\\n   [ 1.  3.  6.  7.  7.]\\n   [ 6.  9.  8.  4.  6.]\\n   [ 6.  1.  5.  7.  3.]]\\n\\n  [[ 2.  4.  6.  2.  8.]\\n   [ 1.  1.  8.  0.  8.]\\n   [ 5.  9.  0.  3.  2.]\\n   [ 1.  7.  3.  7.  3.]\\n   [ 6.  8.  9.  8.  7.]]]]\\n\\nY:\\n[[  8.24621105   4.           6.3245554    5.38516474   8.06225777]\\n [  1.41421354   3.1622777    8.           4.           8.        ]\\n [  5.09901953   9.48683262   6.           7.6157732    7.28010988]\\n [  6.08276272  11.40175438   8.54400349   8.06225777   6.70820379]\\n [  8.48528099   8.06225777  10.29563046  10.63014603   7.6157732 ]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*Tuple(int)*): list of axes to reduce\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceL2Gradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMax\",\n    \"description\": \"\\n  Computes the max of the input tensor's element along the provided axes.\\n  The resulted tensor has the same rank as the input if keepdims equal True.\\n  If keepdims equal false, then the resulted tensor have the reduced dimension\\n  pruned.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"A list of integers, along which to reduce.\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Keep the reduced dimension(s) or not, default True keeps the reduced dimension(s).\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"An input tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reduced output tensor.\",\n        \"name\": \"reduced\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMean\",\n    \"description\": \"\\nComputes the **mean** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceMean\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    axes=(0,1),\\n    keepdims=0\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,5,5)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[9. 0. 3. 6. 0.]\\n   [3. 4. 5. 0. 9.]\\n   [6. 9. 1. 1. 5.]\\n   [6. 2. 3. 7. 7.]\\n   [3. 1. 1. 0. 1.]]\\n\\n  [[4. 3. 9. 8. 1.]\\n   [8. 2. 0. 4. 0.]\\n   [8. 9. 9. 0. 2.]\\n   [7. 2. 5. 8. 9.]\\n   [5. 9. 1. 9. 0.]]]]\\nY:\\n[[6.5 1.5 6.  7.  0.5]\\n [5.5 3.  2.5 2.  4.5]\\n [7.  9.  5.  0.5 3.5]\\n [6.5 2.  4.  7.5 8. ]\\n [4.  5.  1.  4.5 0.5]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*Tuple(int)*): list of axes to reduce\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMin\",\n    \"description\": \"\\n  Computes the min of the input tensor's element along the provided axes.\\n  The resulted tensor has the same rank as the input if keepdims equal True.\\n  If keepdims equal false, then the resulted tensor have the reduced dimension\\n  pruned.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"A list of integers, along which to reduce.\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Keep the reduced dimension(s) or not, default True keeps the reduced dimension(s).\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"An input tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reduced output tensor.\",\n        \"name\": \"reduced\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMinGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceScatter\",\n    \"description\": \"\\nDoes reduce-scatter operation among the nodes. Currently only Sum is supported.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"A tensor to be reduce-scattered.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The reduced tensor, scattered on all nodes.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceSum\",\n    \"description\": \"\\nComputes the **sum** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"ReduceSum\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    axes=(0,1),\\n    keepdims=0\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(1,2,5,5)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[[5. 3. 7. 9. 5.]\\n   [4. 5. 1. 8. 3.]\\n   [1. 0. 9. 7. 6.]\\n   [7. 5. 0. 3. 1.]\\n   [6. 4. 4. 8. 3.]]\\n\\n  [[8. 9. 6. 7. 7.]\\n   [5. 5. 4. 7. 0.]\\n   [9. 7. 6. 6. 7.]\\n   [7. 5. 2. 4. 2.]\\n   [4. 5. 1. 9. 4.]]]]\\nY:\\n[[13. 12. 13. 16. 12.]\\n [ 9. 10.  5. 15.  3.]\\n [10.  7. 15. 13. 13.]\\n [14. 10.  2.  7.  3.]\\n [10.  9.  5. 17.  7.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*Tuple(int)*): list of axes to reduce\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)\",\n        \"name\": \"keepdims\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): reduced tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceTailSum\",\n    \"description\": \"\\nReduce the tailing dimensions\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The matrix\",\n        \"name\": \"mat\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Relu\",\n    \"category\": \"Activation\",\n    \"description\": \"\\nApplies rectified linear unit operation to the input data element-wise. The Relu operation takes one input $X$, produces one output $Y$, and is defined as:\\n\\n$$Y = max(0,X)$$\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/relu_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/relu_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n  \\\"Relu\\\",\\n  [\\\"X\\\"],\\n  [\\\"Y\\\"]\\n  )\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(4, 4).astype(np.float32)) // NCHW\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[-1.4655551   0.64575136  0.7921748   0.4150579 ]\\n [ 0.41085166 -0.2837964   0.9881425  -1.9300346 ]\\n [ 0.39705405  0.44639114  0.9940703   0.2926532 ]\\n [-0.6726489   0.01330667  1.101319    0.33858967]]\\n\\nY:\\n [[0.         0.64575136 0.7921748  0.4150579 ]\\n [0.41085166 0.         0.9881425  0.        ]\\n [0.39705405 0.44639114 0.9940703  0.2926532 ]\\n [0.         0.01330667 1.101319   0.33858967]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"name\": \"cudnn_exhaustive_search\",\n        \"type\": \"boolean\",\n        \"visible\": false\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor with same shape as input\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReluGradient\",\n    \"description\": \"\\nReluGradient takes both Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the rectified linear function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReluN\",\n    \"description\": \"\\nRelu takes one input data (Tensor) and produces one output data\\n(Tensor) where the rectified linear function, y = min(max(0, x), n),\\nis applied to the tensor elementwise.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the cap of output\",\n        \"name\": \"n\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReluNGradient\",\n    \"description\": \"\\nReluGradient takes both Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the rectified linear function.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the cap of forward op output\",\n        \"name\": \"n\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RemoveDataBlocks\",\n    \"description\": \"\\nShrink the data tensor by removing data blocks with given zero-based indices in\\nthe outermost dimension of the tensor. Indices are not assumed in any order or\\nunique but with the range [0, blocks_size). Indices could be empty.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"a N-D data tensor, N >= 1\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"zero-based indices of blocks to be removed\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"data after removing data blocks indexed by 'indices'\",\n        \"name\": \"shrunk data\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RemovePadding\",\n    \"description\": \"\\nRemove padding around the edges of each segment of the input data. This is the\\nreverse operation of **AddPadding**, and uses the same arguments and conventions\\nfor input and output data format.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sequence_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\naddpad_op = core.CreateOperator(\\n    \\\"AddPadding\\\",\\n    [\\\"X\\\", \\\"lengths_add\\\"],\\n    [\\\"Y\\\", \\\"lengths_out_add\\\"],\\n    padding_width=1\\n)\\n\\nrmpad_op = core.CreateOperator(\\n    \\\"RemovePadding\\\",\\n    [\\\"Y\\\", \\\"lengths_rm\\\"],\\n    [\\\"Z\\\", \\\"lengths_out_rm\\\"],\\n    padding_width=1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(20, size=(3,5))))\\nworkspace.FeedBlob(\\\"lengths_add\\\", np.array([3]).astype(np.int32))\\nworkspace.FeedBlob(\\\"lengths_rm\\\", np.array([5]).astype(np.int32))\\n\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(addpad_op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"lengths_out_add:\\\", workspace.FetchBlob(\\\"lengths_out_add\\\"))\\n\\nworkspace.RunOperatorOnce(rmpad_op)\\nprint(\\\"Z:\\\", workspace.FetchBlob(\\\"Z\\\"))\\nprint(\\\"lengths_out_rm:\\\", workspace.FetchBlob(\\\"lengths_out_rm\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [[17 19  1  9  1]\\n [19  3  5 19  1]\\n [16  0  0  0  4]]\\nY: [[ 0  0  0  0  0]\\n [17 19  1  9  1]\\n [19  3  5 19  1]\\n [16  0  0  0  4]\\n [ 0  0  0  0  0]]\\nlengths_out_add: [5]\\nZ: [[17 19  1  9  1]\\n [19  3  5 19  1]\\n [16  0  0  0  4]]\\nlengths_out_rm: [3]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Outer-size of padding to remove around each range.\",\n        \"name\": \"padding_width\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"[OPTIONAL] Specifies a different end-padding width. If this is not set, will use same as `padding_width`.\",\n        \"name\": \"end_padding_width\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor ($T<N, D_1, ..., D_n>$).\",\n        \"name\": \"data_in\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* Number of elements in each range. sum(lengths) = N. If not provided, considers all data as a single segment.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Padded data tensor ($T<N + 2*padding_width, D_1, ..., D_n>$).\",\n        \"name\": \"data_out\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* [OPTIONAL] Lengths for each padded range.\",\n        \"name\": \"lengths_out\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReplaceNaN\",\n    \"description\": \"\\nReplace the NaN (not a number) element in the input tensor with argument `value`\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"the value to replace NaN, the default is 0\",\n        \"name\": \"value (optional)\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"Output tensor\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReservoirSampling\",\n    \"description\": \"\\nCollect `DATA` tensor into `RESERVOIR` of size `num_to_collect`. `DATA` is\\nassumed to be a batch.\\n\\nIn case where 'objects' may be repeated in data and you only want at most one\\ninstance of each 'object' in the reservoir, `OBJECT_ID` can be given for\\ndeduplication. If `OBJECT_ID` is given, then you also need to supply additional\\nbook-keeping tensors. See input blob documentation for details.\\n\\nThis operator is thread-safe.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The number of random samples to append for each positive samples\",\n        \"name\": \"num_to_collect\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The reservoir; should be initialized to empty tensor\",\n        \"name\": \"RESERVOIR\"\n      },\n      {\n        \"description\": \"Number of examples seen so far; should be initialized to 0\",\n        \"name\": \"NUM_VISITED\"\n      },\n      {\n        \"description\": \"Tensor to collect from. The first dimension is assumed to be batch size. If the object to be collected is represented by multiple tensors, use `PackRecords` to pack them into single tensor.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Mutex to prevent data race\",\n        \"name\": \"MUTEX\"\n      },\n      {\n        \"description\": \"(Optional, int64) If provided, used for deduplicating object in the reservoir\",\n        \"name\": \"OBJECT_ID\"\n      },\n      {\n        \"description\": \"(Optional) Auxiliary bookkeeping map. This should be created from  `CreateMap` with keys of type int64 and values of type int32\",\n        \"name\": \"OBJECT_TO_POS_MAP_IN\"\n      },\n      {\n        \"description\": \"(Optional) Tensor of type int64 used for bookkeeping in deduplication\",\n        \"name\": \"POS_TO_OBJECT_IN\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same as the input\",\n        \"name\": \"RESERVOIR\"\n      },\n      {\n        \"description\": \"Same as the input\",\n        \"name\": \"NUM_VISITED\"\n      },\n      {\n        \"description\": \"(Optional) Same as the input\",\n        \"name\": \"OBJECT_TO_POS_MAP\"\n      },\n      {\n        \"description\": \"(Optional) Same as the input\",\n        \"name\": \"POS_TO_OBJECT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResetCounter\",\n    \"description\": \"\\nResets a count-down counter with initial value specified by the `init_count`\\nargument.\\n\\n  Github Links:\\n  - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/counter_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\ncreatecounter_op = core.CreateOperator(\\n    \\\"CreateCounter\\\",\\n    [],\\n    [\\\"counter\\\"],\\n    init_count=5\\n)\\n\\nretrievecount_op = core.CreateOperator(\\n    \\\"RetrieveCount\\\",\\n    [\\\"counter\\\"],\\n    [\\\"count\\\"]\\n)\\n\\ncheckcounterdone_op = core.CreateOperator(\\n    \\\"CheckCounterDone\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"]\\n)\\n\\ncountup_op = core.CreateOperator(\\n    \\\"CountUp\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n)\\n\\ncountdown_op = core.CreateOperator(\\n    \\\"CountDown\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"],\\n)\\n\\nresetcounter_op = core.CreateOperator(\\n    \\\"ResetCounter\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n    init_count=3\\n)\\n\\n\\n// Create counter\\nworkspace.RunOperatorOnce(createcounter_op)\\nprint(\\\"'counter' pointer:\\\", workspace.FetchBlob(\\\"counter\\\"))\\n\\n\\n// Retrieve initial counter value\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"Initial 'count':\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Check if counter is done\\nworkspace.RunOperatorOnce(checkcounterdone_op)\\nprint(\\\"Initial 'done' value:\\\", workspace.FetchBlob(\\\"done\\\"))\\n\\n\\n// Test CountUp operator\\nprint(\\\"\\\\nTesting CountUp operator...\\\")\\nfor i in range(5):\\n    workspace.RunOperatorOnce(countup_op)\\n    print(\\\"'previous_count' after CountUp:\\\", workspace.FetchBlob(\\\"previous_count\\\"))\\n\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"'count' value after CountUp test:\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Test CountDown operator\\nprint(\\\"\\\\nTesting CountDown operator...\\\")\\nfor i in range(11):\\n    workspace.RunOperatorOnce(countdown_op)\\n    workspace.RunOperatorOnce(retrievecount_op)\\n    print(\\\"'count' value after CountDown: {}\\\\t'done' value: {}\\\".format(workspace.FetchBlob(\\\"count\\\"), workspace.FetchBlob(\\\"done\\\")))\\n```\\n\\n**Result**\\n\\n```\\n'counter' pointer: counter, a C++ native class of type std::__1::unique_ptr<caffe2::Counter<long long>, std::__1::default_delete<caffe2::Counter<long long> > >.\\nInitial 'count': 5\\nInitial 'done' value: False\\n\\nTesting CountUp operator...\\n'previous_count' after CountUp: 5\\n'previous_count' after CountUp: 6\\n'previous_count' after CountUp: 7\\n'previous_count' after CountUp: 8\\n'previous_count' after CountUp: 9\\n'count' value after CountUp test: 10\\n\\nTesting CountDown operator...\\n'count' value after CountDown: 9        'done' value: False\\n'count' value after CountDown: 8        'done' value: False\\n'count' value after CountDown: 7        'done' value: False\\n'count' value after CountDown: 6        'done' value: False\\n'count' value after CountDown: 5        'done' value: False\\n'count' value after CountDown: 4        'done' value: False\\n'count' value after CountDown: 3        'done' value: False\\n'count' value after CountDown: 2        'done' value: False\\n'count' value after CountDown: 1        'done' value: False\\n'count' value after CountDown: 0        'done' value: False\\n'count' value after CountDown: -1        'done' value: True\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Resets counter to this value, must be >= 0.\",\n        \"name\": \"init_count\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<ptr>`)* A blob pointing to an instance of a counter.\",\n        \"name\": \"counter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: int)* [OPTIONAL] count value BEFORE this operation.\",\n        \"name\": \"previous_value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResetCursor\",\n    \"description\": \"\\nResets the offsets for the given TreeCursor. This operation is thread safe.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the cursor.\",\n        \"name\": \"cursor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"description\": \"\\nReshape the input tensor similar to numpy's\\n[reshape](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html).\\n\\nTakes a tensor as input and an optional tensor specifying the new shape. When\\nthe second input is absent, an extra argument shape must be specified. Outputs\\nthe reshaped tensor as well as the original shape.\\n\\nAt most one dimension of the new shape can be -1. In this case, the value is\\ninferred from the size of the tensor and the remaining dimensions. A dimension\\ncould also be 0, in which case the actual dimension value is going to be copied\\nfrom the input tensor.\\n\\nFor empty tensor, we will set the -1 dimension to be 0 (if one dimension is -1).\\nWhen the tensor is empty, dimension of 0 will remain to be 0.\\nE.g: data=np.empty(shape=[4, 0]), shape=[0, -1], the output tensor will be\\nnp.emtpy(shape=[0, 0])\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reshape_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Reshape\\\",\\n    [\\\"data\\\"],\\n    [\\\"reshaped\\\", \\\"old_shape\\\"],\\n    shape=(3,2)\\n)\\n\\nworkspace.FeedBlob(\\\"data\\\", (np.random.randint(100, size=(6))))\\nprint(\\\"data:\\\", workspace.FetchBlob(\\\"data\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"reshaped:\\\", workspace.FetchBlob(\\\"reshaped\\\"))\\nprint(\\\"old_shape:\\\", workspace.FetchBlob(\\\"old_shape\\\"))\\n```\\n\\n**Result**\\n\\n```\\ndata: [86 60 85 96  7 37]\\nreshaped: [[86 60]\\n          [85 96]\\n          [ 7 37]]\\nold_shape: [6]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"New shape. Do not set if using `new_shape` input.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input tensor.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* [OPTIONAL] Tensor containing new shape.\",\n        \"name\": \"new_shape\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Reshaped output tensor.\",\n        \"name\": \"reshaped\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int>`)* Tensor containing old shape of `data`.\",\n        \"name\": \"old_shape\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResizeLike\",\n    \"description\": \"\\nProduces tensor containing data of first input and shape of second input.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor whose data will be copied into the output.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"Tensor whose shape will be applied to output.\",\n        \"name\": \"shape_tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor with data of input 0 and shape of input 1.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResizeNearest\",\n    \"description\": \"\\nResizes the spatial dimensions of the input using nearest neighbor\\ninterpolation. The `width_scale` and `height_scale` arguments\\ncontrol the size of the output, which is given by:\\noutput_width = floor(input_width * width_scale)\\noutput_height = floor(output_height * height_scale)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D, 2-element, Scales tensor, [height_scale, width_scale]\",\n        \"name\": \"scales\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResizeNearest3D\",\n    \"description\": \"\\nResizes the spatial dimensions of the input tensor using nearest neighbor\\ninterpolation. The `width_scale` and `height_scale` arguments\\ncontrol the size of the output, which is given by:\\noutput_width = floor(input_width * width_scale)\\noutput_height = floor(output_height * height_scale)\\nAssumptions:\\n  - Only resize height and width\\n  - Both width_scale and height_scale scale are 2\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Scale along temporal dimension\",\n        \"name\": \"temporal_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResizeNearest3DGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"Scale along temporal dimension\",\n        \"name\": \"temporal_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ResizeNearestGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RetrieveCount\",\n    \"description\": \"\\nRetrieve the current value from the counter as an integer.\\n\\n  Github Links:\\n  - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/counter_ops.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\ncreatecounter_op = core.CreateOperator(\\n    \\\"CreateCounter\\\",\\n    [],\\n    [\\\"counter\\\"],\\n    init_count=5\\n)\\n\\nretrievecount_op = core.CreateOperator(\\n    \\\"RetrieveCount\\\",\\n    [\\\"counter\\\"],\\n    [\\\"count\\\"]\\n)\\n\\ncheckcounterdone_op = core.CreateOperator(\\n    \\\"CheckCounterDone\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"]\\n)\\n\\ncountup_op = core.CreateOperator(\\n    \\\"CountUp\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n)\\n\\ncountdown_op = core.CreateOperator(\\n    \\\"CountDown\\\",\\n    [\\\"counter\\\"],\\n    [\\\"done\\\"],\\n)\\n\\nresetcounter_op = core.CreateOperator(\\n    \\\"ResetCounter\\\",\\n    [\\\"counter\\\"],\\n    [\\\"previous_count\\\"],\\n    init_count=3\\n)\\n\\n\\n// Create counter\\nworkspace.RunOperatorOnce(createcounter_op)\\nprint(\\\"'counter' pointer:\\\", workspace.FetchBlob(\\\"counter\\\"))\\n\\n\\n// Retrieve initial counter value\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"Initial 'count':\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Check if counter is done\\nworkspace.RunOperatorOnce(checkcounterdone_op)\\nprint(\\\"Initial 'done' value:\\\", workspace.FetchBlob(\\\"done\\\"))\\n\\n\\n// Test CountUp operator\\nprint(\\\"\\\\nTesting CountUp operator...\\\")\\nfor i in range(5):\\n    workspace.RunOperatorOnce(countup_op)\\n    print(\\\"'previous_count' after CountUp:\\\", workspace.FetchBlob(\\\"previous_count\\\"))\\n\\nworkspace.RunOperatorOnce(retrievecount_op)\\nprint(\\\"'count' value after CountUp test:\\\", workspace.FetchBlob(\\\"count\\\"))\\n\\n\\n// Test CountDown operator\\nprint(\\\"\\\\nTesting CountDown operator...\\\")\\nfor i in range(11):\\n    workspace.RunOperatorOnce(countdown_op)\\n    workspace.RunOperatorOnce(retrievecount_op)\\n    print(\\\"'count' value after CountDown: {}\\\\t'done' value: {}\\\".format(workspace.FetchBlob(\\\"count\\\"), workspace.FetchBlob(\\\"done\\\")))\\n```\\n\\n**Result**\\n\\n```\\n'counter' pointer: counter, a C++ native class of type std::__1::unique_ptr<caffe2::Counter<long long>, std::__1::default_delete<caffe2::Counter<long long> > >.\\nInitial 'count': 5\\nInitial 'done' value: False\\n\\nTesting CountUp operator...\\n'previous_count' after CountUp: 5\\n'previous_count' after CountUp: 6\\n'previous_count' after CountUp: 7\\n'previous_count' after CountUp: 8\\n'previous_count' after CountUp: 9\\n'count' value after CountUp test: 10\\n\\nTesting CountDown operator...\\n'count' value after CountDown: 9        'done' value: False\\n'count' value after CountDown: 8        'done' value: False\\n'count' value after CountDown: 7        'done' value: False\\n'count' value after CountDown: 6        'done' value: False\\n'count' value after CountDown: 5        'done' value: False\\n'count' value after CountDown: 4        'done' value: False\\n'count' value after CountDown: 3        'done' value: False\\n'count' value after CountDown: 2        'done' value: False\\n'count' value after CountDown: 1        'done' value: False\\n'count' value after CountDown: 0        'done' value: False\\n'count' value after CountDown: -1        'done' value: True\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<ptr>`)* A blob pointing to an instance of a counter.\",\n        \"name\": \"counter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: int)* Current count value.\",\n        \"name\": \"count\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReversePackedSegs\",\n    \"description\": \"\\nReverse segments in a 3-D tensor (lengths, segments, embeddings,), leaving\\npaddings unchanged. This operator is used to reverse input of a recurrent neural\\nnetwork to make it a BRNN.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"a 3-D (lengths, segments, embeddings,) tensor.\",\n        \"name\": \"data\"\n      },\n      {\n        \"description\": \"length of each segment.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"a (lengths, segments, embeddings,) tensor with each segment reversedand paddings unchanged.\",\n        \"name\": \"reversed data\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RMACRegions\",\n    \"description\": \"\\nComputes a fixed-grid of RMAC region coordinates at various levels\\nas described in https://arxiv.org/abs/1511.05879.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of scales to sample regions at.\",\n        \"name\": \"scales\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Overlap between consecutive regions.\",\n        \"name\": \"overlap\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input 4D tensor of shape NCHW.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output RMAC regions for all items in the batch. Tensor of shape (N x 5) following the ROIPoolOp format - each row is of the format (batch_index x1 y1 x2 y2) where x1, y1, x2, y2 are the region co-ordinates. Each region is repeated N times corresponding to each item in the batch.\",\n        \"name\": \"RMAC_REGIONS\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RMSNorm\",\n    \"attributes\": [\n      {\n        \"description\": \"(int) default to 1; Describes axis of the inputs. Defaults to one because the 0th axis most likely describes the batch size\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) default to 0.001. Small value to be added to the stdev when dividing out by that value. This prevents division by zero.\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor which layer normalization will be applied to\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"scale tensor for elementwise_affine, the shape should be the same as the dimensions of X begin from axis\",\n        \"name\": \"gamma\"\n      },\n      {\n        \"description\": \"bias tensor for elementwise_affine, the shape should be the same as the dimensions of X begin from axis\",\n        \"name\": \"beta\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Normalized values\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"Reciprocal of root mean square for each feature vector\",\n        \"name\": \"rrms\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RMSNormGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RmsProp\",\n    \"description\": \"\\nComputes the RMSProp update\\n(http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf).\\nConcretely, given inputs (grad, mean_squares, mom, lr), computes:\\n\\n    mean_squares_o = mean_squares + (1 - decay) * (square(grad) - mean_squares)\\n    mom_o = momentum * mom + lr * grad / sqrt(epsilon + mean_squares_o)\\n    grad_o = mom_o\\n\\nReturns (grad_o, mean_squares_o, mom_o).\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"rnn_internal_accumulate_gradient_input\",\n    \"description\": \"\\nInternal RNN operator.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"rnn_internal_apply_link\",\n    \"description\": \"\\nInternal RNN operator.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RoIAlign\",\n    \"description\": \"\\nRegion of Interest (RoI) align operation as used in Mask R-CNN.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float) default 1.0; Spatial scale of the input feature map X relative to the input image. E.g., 0.0625 if X has a stride of 16 w.r.t. the input image.\",\n        \"name\": \"spatial_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default 1; Pooled output Y's height.\",\n        \"name\": \"pooled_h\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default 1; Pooled output Y's width.\",\n        \"name\": \"pooled_w\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default -1; number of sampling points in the interpolation grid used to compute the output value of each pooled output bin. If > 0, then exactly sampling_ratio x sampling_ratio grid points are used. If <= 0, then an adaptive number of grid points are used (computed as ceil(roi_width / pooled_w), and likewise for height).\",\n        \"name\": \"sampling_ratio\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D feature map input of shape (N, C, H, W).\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"2D input of shape (R, 4 or 5) specifying R RoIs representing: batch index in [0, N - 1], x1, y1, x2, y2. The RoI coordinates are in the coordinate system of the input image. For inputs corresponding to a single image, batch index can be excluded to have just 4 columns.\",\n        \"name\": \"RoIs\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D output of shape (R, C, pooled_h, pooled_w). The r-th batch element is a pooled feature map cooresponding to the r-th RoI.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RoIAlignGradient\",\n    \"inputs\": [\n      {\n        \"description\": \"See RoIPoolF.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"See RoIPoolF.\",\n        \"name\": \"RoIs\"\n      },\n      {\n        \"description\": \"Gradient of forward output 0 (Y)\",\n        \"name\": \"dY\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Gradient of forward input 0 (X)\",\n        \"name\": \"dX\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RoIAlignRotated\",\n    \"description\": \"\\nSimilar to RoIAlign but can handle rotated region proposals.\\nBased on https://arxiv.org/abs/1703.01086.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float) default 1.0; Spatial scale of the input feature map X relative to the input image. E.g., 0.0625 if X has a stride of 16 w.r.t. the input image.\",\n        \"name\": \"spatial_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default 1; Pooled output Y's height.\",\n        \"name\": \"pooled_h\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default 1; Pooled output Y's width.\",\n        \"name\": \"pooled_w\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) default -1; number of sampling points in the interpolation grid used to compute the output value of each pooled output bin. If > 0, then exactly sampling_ratio x sampling_ratio grid points are used. If <= 0, then an adaptive number of grid points are used (computed as ceil(roi_width / pooled_w), and likewise for height).\",\n        \"name\": \"sampling_ratio\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D feature map input of shape (N, C, H, W).\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"2D input of shape (R, 5 or 6) specifying R RoIs representing: batch index in [0, N - 1], center_x, center_y, width, height, angle. The RoI coordinates are in the coordinate system of the input image. `angle` should be specified in degrees and represents the RoI rotated counter-clockwise. For inputs corresponding to a single image, batch index can be excluded to have just 5 columns.\",\n        \"name\": \"RoIs\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D output of shape (R, C, pooled_h, pooled_w). The r-th batch element is a pooled feature map cooresponding to the r-th RoI.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RoIPool\",\n    \"description\": \"\\nCarries out ROI Pooling for Faster-RCNN.\\nDepending on the mode, there are multiple output cases:\\n\\n  Output case #1: Y, argmaxes (train mode)\\n  Output case #2: Y           (test mode)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"If set, run in test mode and skip computation of argmaxes (used for gradient computation). Only one output tensor is produced. (Default: false).\",\n        \"name\": \"is_test\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"A StorageOrder string (Default: \\\"NCHW\\\").\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The pooled output height (Default: 1).\",\n        \"name\": \"pooled_h\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The pooled output width (Default: 1).\",\n        \"name\": \"pooled_w\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Multiplicative spatial scale factor to translate ROI coords from their input scale to the scale used when pooling (Default: 1.0).\",\n        \"name\": \"spatial_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input 4-D tensor of data. Only NCHW order is currently supported.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"RoIs (Regions of Interest) to pool over. Should be a 2-D tensor of shape (num_rois, 5) given as [[batch_id, x1, y1, x2, y2], ...].\",\n        \"name\": \"rois\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"RoI pooled output 4-D tensor of shape (num_rois, channels, pooled_h, pooled_w).\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"Argmaxes corresponding to indices in X used for gradient computation. Only output if arg \\\"is_test\\\" is false.\",\n        \"name\": \"argmaxes\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RoIPoolGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowMul\",\n    \"description\": \"\\nGiven a matrix A and column vector w, the output is the multiplication of row i\\nof A and element i of w, e.g. C[i][j] = A[i][j] * w[i]. This operator should be\\ndeprecated when the gradient operator of Mul with broadcast is implemented.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The matrix\",\n        \"name\": \"mat\"\n      },\n      {\n        \"description\": \"The column vector\",\n        \"name\": \"w\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Rowwise8BitQuantizedToFloat\",\n    \"description\": \"\\nGiven uint8 tensor, quantized using 8bit row-wise\\nquantization, and auxiliary scales and biases, this operator\\nrestores float tensor in the following way. We take input 8bits tensor\\nof size  (m_1, m_2, ..., m_n), n >= 2, reshape it  into matrix of size\\n(m_1, m_2 x... x m_n). We compute element r_{ij} of output matrix as\\nr_{ij} * s_i + b_i and after this we reshape this output matrix into\\noutput tensor of size (m_1, m_2, ..., m_n).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"quantized_input\",\n        \"name\": \"quantized_input\"\n      },\n      {\n        \"description\": \"Matrix of floats, each row r_i of which stores a pair s_i, b_i -- scale and bias for i-th row\",\n        \"name\": \"scale_bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": null\n      },\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseCounter\",\n    \"description\": \"\\n    Count the number recent update on rows. Exponential decay is\\n    applied on the counter with decay rate r, such that\\n    r^{counter_halflife} = 0.5; If counter_halflife is nonpositive,\\n    this operator is turned off.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default -1: off\",\n        \"name\": \"counter_halflife\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Iter at last update\",\n        \"name\": \"prev_iter\"\n      },\n      {\n        \"description\": \"update counter\",\n        \"name\": \"update_counter\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"current iteration\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated iter at last update\",\n        \"name\": \"output_prev_iter\"\n      },\n      {\n        \"description\": \"Output update counter\",\n        \"name\": \"output_update_counter\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowwiseMax\",\n    \"description\": \"\\nCompute row-wise max reduction of the input tensor. This op takes one input, $X$, of shape $BxMxN$, where $B$ is the batch size, $M$ is number of rows, and $N$ is number of columns. The output of this op, $Y$, is a matrix of shape $BxM$, with one row for each element of the batch, and the same number of columns as the number of rows of the input tensor.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduction_ops.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduction_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"RowwiseMax\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\n// Create X, simulating a batch of 2, 4x4 matricies\\nX = np.random.randint(0,high=20,size=(2,4,4))\\nprint(\\\"X:\\\\n\\\",X)\\n\\n// Feed X into workspace\\nworkspace.FeedBlob(\\\"X\\\", X.astype(np.float32))\\n\\n// Run op\\nworkspace.RunOperatorOnce(op)\\n\\n// Collect Output\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[[ 5 12 10  1]\\n  [ 4 16  2 15]\\n  [ 5 11 12 15]\\n  [15  4 17 19]]\\n\\n [[16  5  5 13]\\n  [17  2  1 17]\\n  [18  3 19  5]\\n  [14 16 10 16]]]\\nY:\\n [[12. 16. 15. 19.]\\n [16. 17. 19. 16.]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"A tensor of dimensions $B x M x N$ to compute rowwise-max. Here, $B$ is batch size, and $M$ and $N$ are the number of rows and columns of each element of the batch, respectively.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor of shape $B x M$, where each row represents the row-wise maximums for that element of the input batch.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowwiseMaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagrad\",\n    \"description\": \"\\n\\nGiven inputs (param, moment, indices, grad, lr), runs a modified sparse Adagrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_momwnr), where moment is a 1D tensor with length equal to the number of\\nrows in param: shape(moment) == shape(param)[0]. Each element of moment is\\napplied to an entire row of param, and the new moment is calculated by adding\\nthe average squared sum of gradients across each row. Note that indices must\\nalso be a 1D tensor indexing into the rows of param.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"weight_decay\",\n        \"description\": \"Default 0\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"counter_halflife\",\n        \"description\": \"Optional arg when weight_decay is adjusted by frequency (default -1)\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment_1\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagradFusedWithSparseLengthsMeanGradient\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientMeanGradient (gradient of SparseLengthsMean) +\\nRowWiseSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the row-wise sparse\\nAdaGrad update on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsMeanGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagradFusedWithSparseLengthsMeanGradientApprox\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientMeanGradient (gradient of SparseLengthsMean) +\\nRowWiseSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the row-wise sparse\\nAdaGrad update on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsMeanGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"rounding option: 0 for nearest rounding, 1 for stochastic rounding\",\n        \"name\": \"round_option\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagradFusedWithSparseLengthsSumGradient\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientSumGradient (gradient of SparseLengthsSum) +\\nRowWiseSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the row-wise sparse\\nAdaGrad update on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsSumGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"rounding option: 0 for nearest rounding, 1 for stochastic rounding\",\n        \"name\": \"round_option\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagradFusedWithSparseLengthsSumGradientApprox\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientSumGradient (gradient of SparseLengthsSum) +\\nRowWiseSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the row-wise sparse\\nAdaGrad update on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsSumGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"rounding option: 0 for nearest rounding, 1 for stochastic rounding\",\n        \"name\": \"round_option\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagradFusedWithSparseLengthsWeightedSumGradient\",\n    \"description\": \"\\n\\nFused operator of SparseLengthsIndicesInGradientWeightedSumWithMainInputGradient\\n(gradient of SparseLengthsWeightedSum) + RowWiseSparseAdagrad, where weights are\\npositional weights computed with LengthsRangeFill + Gather pattern.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the row-wise sparse\\nAdaGrad update on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case.\\nThere're auxiliary inputs (aux_param) for which gradient is computed and\\nreturns (aux_grad).\\nYet additional input (lengths) is for fused SparseLengthsWeightedSumGradient\\noperator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Auxiliary parameters to be updated\",\n        \"name\": \"aux_param\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Auxiliary gradient\",\n        \"name\": \"aux_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdagradFusedWithSparseLengthsWeightedSumGradientApprox\",\n    \"description\": \"\\n\\nApproximately fused operator of\\nSparseLengthsIndicesInGradientWeightedSumWithMainInputGradient\\n(gradient of SparseLengthsWeightedSum) + RowWiseSparseAdagrad, where weights are\\npositional weights computed with LengthsRangeFill + Gather pattern.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the row-wise sparse\\nAdaGrad update on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case.\\nThere's race condition w.r.t. ordering between reading params and writing to\\nparam, hence the name Approx.\\nThere're auxiliary inputs (aux_param) for which gradient is computed\\nand returns (aux_grad).\\nYet additional input (lengths) is for fused SparseLengthsWeightedSumGradient\\noperator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Auxiliary parameters to be updated\",\n        \"name\": \"aux_param\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"name\": \"counter\",\n        \"description\": \"Optional input when weight_decay is adjusted by frequency ignored when counter_halflife == -1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Auxiliary gradient\",\n        \"name\": \"aux_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RowWiseSparseAdam\",\n    \"description\": \"\\n\\n    Computes a modified Adam Update for the sparse case.\\n    Given inputs (param, moment1, moment2, indices, grad, lr, iter), runs the\\n    Adam update on (param, moment1[indices], moment2[indices], lr, iter) and returns\\n    (new_param, new_moment1, new_moment2), where moment2 is a 1D tensor\\n    with length equal to the number of rows in param:\\n    shape(moment2) == shape(param)[0]. Each element of  moment2 is\\n    applied to an entire row of param, and the new moment2 values are\\n    calculated by averaging across the row.\\n\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"Default 0.9\",\n        \"name\": \"beta1\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 0.999\",\n        \"name\": \"beta2\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"First moment history\",\n        \"name\": \"moment_1\"\n      },\n      {\n        \"description\": \"Second moment history\",\n        \"name\": \"moment_2\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"iteration number\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated first moment\",\n        \"name\": \"output_moment_1\"\n      },\n      {\n        \"description\": \"Updated second moment\",\n        \"name\": \"output_moment_2\"\n      },\n      {\n        \"description\": \"Optional Effective gradient\",\n        \"name\": \"output_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Rsqrt\",\n    \"description\": \"Computes the element-wise rsqrt of the input.\",\n    \"inputs\": [\n      {\n        \"description\": \"ND input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"ND output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"RsqrtGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SafeDequeueBlobs\",\n    \"description\": \"\\nDequeue the blobs from queue. When the queue is closed and empty, the output\\nstatus will be set to true which can be used as exit criteria for execution\\nstep.\\nThe 1st input is the queue and the last output is the status. The rest are\\ndata blobs.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(default 1) If > 1, multiple records will be dequeued and tensors for each column will be concatenated. This requires all tensors in the records to be at least 1D, and to have the same inner dimensions.\",\n        \"name\": \"num_records\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The shared pointer for the BlobsQueue\",\n        \"name\": \"queue\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The blob to store the dequeued data\",\n        \"name\": \"blob\"\n      },\n      {\n        \"description\": \"Is set to 0/1 depending on the success of dequeue\",\n        \"name\": \"status\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SafeEnqueueBlobs\",\n    \"description\": \"\\nEnqueue the blobs into queue. When the queue is closed and full, the output\\nstatus will be set to true which can be used as exit criteria for execution\\nstep.\\nThe 1st input is the queue and the last output is the status. The rest are\\ndata blobs.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"The shared pointer for the BlobsQueue\",\n        \"name\": \"queue\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Save\",\n    \"description\": \"\\nSaves a set of blobs to a db. It takes $[1, \\\\infty)$ number of inputs and has\\nno output. The contents of the inputs are written into the db using the\\nsettings specified by the arguments.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/load_save_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Save\\\",\\n    [\\\"X\\\", \\\"Y\\\", \\\"Z\\\"],\\n    [],\\n    db=\\\"test_db2\\\",\\n    db_type=\\\"leveldb\\\",\\n    blob_name_overrides=[\\\"x_scores\\\", \\\"y_scores\\\", \\\"z_scores\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(20, size=(5,5)))\\nworkspace.FeedBlob(\\\"Y\\\", np.random.randint(20, size=(5,5)))\\nworkspace.FeedBlob(\\\"Z\\\", np.random.randint(20, size=(5,5)))\\nworkspace.RunOperatorOnce(op)\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"If set to non-zero, save the db directly to the path specified by the `db` arg. If not set (default), prepend the path of the current root folder of the workspace to the path specified by the `db` arg.\",\n        \"name\": \"absolute_path\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": \"\",\n        \"description\": \"Characters in the provided blob names that match `strip_prefix` will be removed prior to saving. Also, characters that precede `strip_prefix` will be removed. Useful for removing device scope from blob names.\",\n        \"name\": \"strip_prefix\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"description\": \"If set, used as blob names instead of original blob names. Must be same length as number of blobs.\",\n        \"name\": \"blob_name_overrides\",\n        \"option\": \"optional\",\n        \"type\": \"string[]\"\n      },\n      {\n        \"description\": \"The output path of the db. See the `absolute_path` arg details for options regarding the current root folder of the workspace.\",\n        \"name\": \"db\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"description\": \"Type of db to save (options: \\\"lmdb\\\", \\\"leveldb\\\", \\\"minidb\\\").\",\n        \"name\": \"db_type\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"default\": \"kDefaultChunkSize\",\n        \"description\": \"The chunk size to split tensor data into. If not set, caffe2_tensor_chunk_size will be used\",\n        \"name\": \"chunk_size\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input tensor(s).\",\n        \"name\": \"X\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Scale\",\n    \"description\": \"\\nScale takes one input data (Tensor) and produces one output data\\n(Tensor) whose value is the input data tensor scaled element-wise.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float, default 1.0) the scale to apply.\",\n        \"name\": \"scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ScaleBlobs\",\n    \"description\": \"\\nScaleBlobs takes one or more input data (Tensor) and produces one\\nor more output data (Tensor) whose value is the input data tensor\\nscaled element-wise.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float, default 1.0) the scale to apply.\",\n        \"name\": \"scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Scatter\",\n    \"description\": \"\\nUpdate values of the tensor by overriding current value specified by indices.\\n\\nWrites all values from the tensor UPDATES into DATA at the indices specified in the INDICES tensor.\\nFor each value in DATA, its output index is specified by its index in UPDATES and by the corresponding value in INDICES for the specified axis.\\n\\nFor a 3-D tensor, DATA is updated as:\\n\\nDATA[INDICES[i][j][k]][j][k] = UPDATES[i][j][k]  # if axis == 0\\nDATA[i][INDICES[i][j][k]][k] = UPDATES[i][j][k]  # if axis == 1\\nDATA[i][j][INDICES[i][j][k]] = UPDATES[i][j][k]  # if axis == 2\\n\\nCurrently only works on CPU because of access to INDICES.\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Which dimension to scatter on.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to be updated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"1-D list of indices on the first dimensionof X_0 that need to be updated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Update slices, with shape len(INDICES) + shape(X_0)[1:]\",\n        \"name\": \"UPDATES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The updated output.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ScatterAssign\",\n    \"description\": \"\\nUpdate slices of the tensor in-place by overriding current value.\\n\\nNote: The op pretty much ignores the exact shapes of the input arguments and\\ncares only about sizes. It's done for performance consideration to avoid\\nunnecessary reshapes. Only first dimension of X_0 is important, let's call it\\nN. If M is the total size of X_0 and K is the size of INDICES then X_i is\\nassumed to be of shape K x (M / N) regardless of the real shape.\\n\\nNote: Each update in INDICES is applied independently which means that if\\nduplicated elements are present in INDICES arbitrary one will win.\\n\\nCurrently only works on CPU because of access to INDICES.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to be updated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"1-D list of indices on the first dimensionof X_0 that need to be updated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Update slices, with shape len(INDICES) + shape(X_0)[1:]\",\n        \"name\": \"SLICES\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Has to be exactly the same tensor as the input 0\",\n        \"name\": \"DATA\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ScatterWeightedSum\",\n    \"description\": \"\\nSimilar to WeightedSum, computes the weighted sum of several tensors, with\\nthe difference that inputs are sliced tensors. The first tensor has to be\\nin-place and only slices of it on the first dimension as indexed by INDICES\\nwill be updated.\\n\\nNote: The op pretty much ignores the exact shapes of the input arguments and\\ncares only about sizes. It's done for performance consideration to avoid\\nunnecessary reshapes. Only first dimension of X_0 is important, let's call it\\nN. If M is the total size of X_0 and K is the size of INDICES then X_i is\\nassumed to be of shape K x (M / N) regardless of the real shape.\\n\\nNote: Each update in INDICES is applied independently which means that if\\nduplicated elements are present in INDICES the corresponding slice of X_0\\nwill be scaled multiple times. Manual collapsing of INDICES is required\\nbeforehand if necessary.\\n\\nNote: Updates are applied sequentially by inputs which might have undesired\\nconsequences if the input tensor is accessed concurrently by different op\\n(e.g. when doing Hogwild). Other threads might see intermediate results even\\non individual slice level, e.g. X_0 scaled by weight_0 but without any\\nupdates applied.\\n\\nCurrently only works on CPU because of access to INDICES.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to be updated.\",\n        \"name\": \"X_0\"\n      },\n      {\n        \"description\": \"Scalar weight for X_0, applied only to slices affected.\",\n        \"name\": \"Weight_0\"\n      },\n      {\n        \"description\": \"1-D list of indices on the first dimension of X_0 that need to be updated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Update slices, with shape len(INDICES) + shape(X_0)[1:]\",\n        \"name\": \"X_1\"\n      },\n      {\n        \"description\": \"Scalar weight for X_1 update\",\n        \"name\": \"Weight_1\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Has to be exactly the same tensor as the input 0\",\n        \"name\": \"X_0\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SegmentIdsToLengths\",\n    \"description\": \"\\nTransfers a vector of segment ids to a vector of segment lengths. This operation\\nsupports non-consecutive segment ids. Segments not appearing in the input vector\\nwill have length 0. If the second input is provided, the number of segments =\\nthe size of its first dimension. Otherwise, the number of segments = the last\\nindex in the first input vector + 1.\\n\\nIn general, for consecutive, zero-based segment IDs, this is the inverse\\noperation of LengthsToSegmentIds, except that a vector of segment IDs\\ncannot represent empty segments at the end (if the second input is absent).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1-D int32_t or int64_t tensor of segment ids\",\n        \"name\": \"segment_ids\"\n      },\n      {\n        \"description\": \"if provided, number of segments = the size of its first dimension\",\n        \"name\": \"data (optional)\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D int64_t tensor of segment lengths\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SegmentIdsToRanges\",\n    \"description\": \"\\nTransfers a vector of segment ids to a vector of segment ranges. This operation\\nsupports non-consecutive segment ids. Segments not appearing in the input vector\\nwill have length 0. If the second input is provided, the number of segments =\\nthe size of its first dimension. Otherwise, the number of segments = the last\\nindex in the first input vector + 1.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1-D int32_t or int64_t tensor of segment ids\",\n        \"name\": \"segment_ids\"\n      },\n      {\n        \"description\": \"if provided, number of segments = the size of its first dimension\",\n        \"name\": \"data (optional)\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D int64_t tensor of segment lengths\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SegmentOneHot\",\n    \"description\": \"\\nGiven a sequence of indices, segmented by the lengths tensor, returns a matrix\\nthat has the elements in each sequence set to 1.0, and 0.0 everywhere else.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Size of each segment.\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"Active indices, of size sum(lengths)\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Size of the index\",\n        \"name\": \"index_size_tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Matrix of size len(lengths) x index_size\",\n        \"name\": \"one_hots\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SelfBinningHistogram\",\n    \"description\": \"\\n            Computes a histogram for values in the given list of tensors.\\n            For logging activation histograms for post-hoc analyses, consider using the\\n            HistogramObserver observer.\\n            For iteratively computing a histogram for all input tensors encountered through\\n            history, consider using the AccumulateHistogram operator.\\n            \",\n    \"attributes\": [\n      {\n        \"description\": \"Number of bins to use for the histogram. Must be >= 1.\",\n        \"name\": \"num_bins\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"A string indicating 'linear' or 'logarithmic' spacing for the bins.\",\n        \"name\": \"bin_spacing\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"A float that's used as the starting point for logarithmic spacing. Since logarithmic spacing cannot contain <=0 values this value will be used to represent all such values.\",\n        \"name\": \"logspace_start\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Apply abs() on every input value.\",\n        \"name\": \"abs\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* List of input tensors.\",\n        \"name\": \"X1, X2, ...\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of edges of the bins, of dimension [num_bins+1]. The range appears as: [first, ..., last), wherein the i-th element expresses the start of a bin and i+1-th value represents the exclusive end of that bin.\",\n        \"name\": \"histogram_values\"\n      },\n      {\n        \"description\": \"1D tensor of counts of each bin, of dimension [num_bins+1]. It is guaranteed to end with a 0 since the last edge is exclusive.\",\n        \"name\": \"histogram_counts\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Selu\",\n    \"description\": \"\\n\\nThe *Selu* op takes one input tensor $X$, an argument $alpha$, an argument $scale$, and produces one output tensor $Y$ of the same shape as $X.$ The op performs the element wise *Selu* operation, defined as\\n\\n$$y=selu(x) =\\\\begin{cases}scale (\\\\alpha e^{x} - \\\\alpha) & x < 0\\\\\\\\scale * x & otherwise\\\\end{cases}$$\\n\\nThe default value of *alpha* is 1.6732632423543772848170429916717 and the default value of *scale* is 1.0507009873554804934193349852946. See [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515) for more information.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/selu_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/selu_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Selu\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[ 1.1613879  -0.27111396 -1.2076733 ]\\n [ 1.3442237  -1.0701777   1.2070968 ]\\n [ 0.23810555  0.9740916  -1.7872391 ]]\\n\\nY:\\n [[ 1.2202715  -0.4174965  -1.2326177 ]\\n [ 1.4123772  -1.1551634   1.2682979 ]\\n [ 0.25017774  1.023479   -1.4637551 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1.673263,\n        \"description\": \"Alpha constant in equation.\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1.0507,\n        \"description\": \"Scale constant in equation.\",\n        \"name\": \"scale\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor of data to be operated on.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor with same shape as input.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SeluGradient\",\n    \"description\": \"\\nSeluGradient takes both Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the selu function.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float) default to 1.6732~; affects the activation function itself.This should go with the weight initialization in the paper.  See https://arxiv.org/abs/1706.02515\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(float) default to 1.0507~; affects the activation function itself.\",\n        \"name\": \"scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"input tensor\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"input tensor\",\n        \"name\": \"dY\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SendTensor\",\n    \"description\": \"\\nSends the tensor to another node.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The rank to send the tensor to.\",\n        \"name\": \"dst\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) a tag to send the tensor with.\",\n        \"name\": \"tag\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(bool) if set, only send the content and assume that the receiver has already known the tensor's shape and information.\",\n        \"name\": \"raw_buffer\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The common world.\",\n        \"name\": \"comm_world\"\n      },\n      {\n        \"description\": \"A tensor to be allgathered.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"An int CPUtensor of size 1 specifying the rank. If given, this overrides the 'to' argument of the op.\",\n        \"name\": \"dst\"\n      },\n      {\n        \"description\": \"An int CPUtensor of size 1 specifying the tag to send the tensor with. This overrides the 'tag' argument of the op.\",\n        \"name\": \"tag\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SequenceMask\",\n    \"description\": \"\\nMask op designed for use in attention mechanisms for sequence modeling tasks.\\nSupports batching: given batch_dim, collapses dims 0 through batch_dim into a\\nsingle dimension, e.g. if tensor dims are [4,2,1,3,4] and batch_dim=2, first\\ncollapse tensor to [4*2*1,3,4], then mask each batch [i,:,:].\\n\\n\\nTwo current operating modes:\\n\\n\\n1) Given a 2D input tensor and 1D tensor of sequence lengths, for each row i in\\nthe input tensor, set elements in that row to -inf if their column index\\nj >= sequence_lengths[i]. This mode takes two inputs and argument mode =\\n'sequence'\\n\\n\\n2) Triangular mask. Given row index i and column index j, set elements to -inf\\ngiven the following conditions:\\n\\n      mode='upper', x_ij = -inf if j < i\\n      mode='lower', x_ij = -inf if j > i\\n      mode='upperdiag', x_ij = -inf if j <= i\\n      mode='lowerdiag', x_ij = -inf if j >= i\\n\\nThis mode takes one input.\\n\\n\\n3) Window Mask. Given a 2D input tensor and 1D tensor of window centers,\\nfor each row i in the input tensor, set elements in that row to -inf\\nif their column index j outside [center - radius, center + radius].\\nThis mode takes two inputs and argument mode = 'sequence'.\\nArgument 'radius' should be provided.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(string) Mode selection. Possible values: 'sequence', 'upper', 'lower', 'upperdiag', 'lowerdiag'\",\n        \"name\": \"mode\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) Beginning axis of row elements. All dimensions to the left will be treated as row indices and those to the right (inclusive) will be treated as column indices in the 2D mask\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(bool) operate in gradient mode\",\n        \"name\": \"grad\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) radius of windows in window mode\",\n        \"name\": \"radius\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) batch dimension of tensor (optional)\",\n        \"name\": \"batch\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int) used when mask should be repeated for one or more data dimensions (beginning at this axis).  (currently only supported for sequence mode without batch argument)\",\n        \"name\": \"repeat_from_axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to apply masking to\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"1D Tensor of sequence lengths for mode #1\",\n        \"name\": \"sequence_lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Input tensor with masking applied\",\n        \"name\": \"masked_tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Shape\",\n    \"description\": \"\\nProduce a 1D int64 tensor with the shape of the input tensor.\\nIf called with an optional argument `axes`, the result will only\\ncontain the dimensions of specified axes.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/shape_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Shape\\\",\\n    [\\\"X\\\"],\\n    [\\\"shape\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(2,3))))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"shape:\\\", workspace.FetchBlob(\\\"shape\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[3 2 5]\\n [5 7 3]]\\nshape: [2 3]\\n\\n```\\n\\n</details>\\n\\n      \",\n    \"attributes\": [\n      {\n        \"description\": \"Array of interested axes.If given, this operator only returns the dimensions of the given axes.Otherwise, the operator returns the dimensions of all axes.\",\n        \"name\": \"axes\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Output tensor containing shape of input tensor.\",\n        \"name\": \"shape\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\",\n    \"description\": \"\\nApply the Sigmoid function element-wise to the input tensor. This is often used\\nas a non-linear activation function in a neural network. The sigmoid function is\\ndefined as:\\n\\n$$Sigmoid(x) = \\\\frac{1}{1+\\\\exp(-x)}$$\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sigmoid_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sigmoid\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(5).astype(np.float32))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"sigmoid:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput: [ 1.5744036   0.31632107  1.7842269   1.4450722  -2.1726978 ]\\nsigmoid: [0.8284105  0.57842743 0.85621804 0.80923885 0.10222916]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SigmoidCrossEntropyWithLogits\",\n    \"description\": \"\\nGiven two matrices logits and targets, of same shape,\\n(batch_size, num_classes), computes the sigmoid cross entropy between the two.\\nReturns a tensor of shape (batch_size,) of losses for each example.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"default is false; if enabled, will use the log d trick to avoid the vanishing\\ngradients early on; see Goodfellow et. al (2014)\",\n        \"name\": \"log_D_trick\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"default is false; if enabled, the model will be allowed to train on an unjoined\\ndataset, where some examples might be false negative and might appear\\nin the dataset later as (true) positive example.\",\n        \"name\": \"unjoined_lr_loss\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"matrix of logits for each example and class.\",\n        \"name\": \"logits\"\n      },\n      {\n        \"description\": \"matrix of targets, same shape as logits.\",\n        \"name\": \"targets\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Vector with the total xentropy for each example.\",\n        \"name\": \"xentropy\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SigmoidCrossEntropyWithLogitsGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SigmoidGradient\",\n    \"description\": \"\\nSigmoidGradient takes both Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the sigmoid function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sign\",\n    \"description\": \"\\nComputes sign for each element of the input: -1, 0 or 1.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n\\\"Sign\\\",\\n[\\\"X\\\"],\\n[\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(3, 3).astype(np.float32) - np.random.rand(3, 3).astype(np.float32)))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[ 0.02816287  0.22408086 -0.30342305]\\n[-0.18481976  0.03948995  0.39698976]\\n[-0.63304734 -0.6919183  -0.31524038]]\\nY:\\n[[ 1.  1. -1.]\\n[-1.  1.  1.]\\n[-1. -1. -1.]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sin\",\n    \"description\": \"\\nCalculates the sine of the given input tensor, element-wise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sin_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sin\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(5).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX: [0.8466114  0.1803606  0.5601509  0.04959291 0.64770824]\\nY: [0.74903965 0.17938434 0.5313141  0.04957259 0.60336035]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor calculated as the sine of the input tensor, element-wise.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SinGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sinh\",\n    \"description\": \"\\nCalculates the hyperbolic sine of the given input tensor, element-wise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sinh_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sinh\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(5).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX: [0.98907769 0.52907848 0.03216429 0.94983935 0.47881418]\\nY: [1.15841695 0.5541099  0.03216984 1.09924557 0.49732079]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The hyperbolic sine values of the input tensor, computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SinhGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SinusoidPositionEncoding\",\n    \"description\": \"\\nCalculates a sinusoid position encoding tensor as described\\nin https://arxiv.org/abs/1706.03762. Takes a 2-D tensor\\n(of size M x K) of positions as input, the embedding size\\nas an argument, and outputs a position encoding tensor of\\nsize (M x K x embedding_size). Here M is typically the max\\nsequence length and K is typically the batch size.\\nThe input tensor must satisfy input[m, 0] == input[m, k] for all k.\\n\\nEncoded as amplitude * SIN(pos/alpha^(i/embedding_size)) if i is even,\\nelse amplitude * COS(pos/alpha^(i/embedding_size)). Here, pos is the position,\\nalpha and amplitude are tuning parameters, i is the current dimension for\\nthe embedding, and embedding_size is the number of total dimensions in\\nthe embedding.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Desired embedding size/number of dimensions -- defaults to 100\",\n        \"name\": \"embedding_size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Sinusoid tuning parameter -- defaults to 10000\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Amplitude of Sin/Cos output\",\n        \"name\": \"amplitude\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2-D tensor of positions to be encoded\",\n        \"name\": \"positions\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3-D tensor representing the positional encoding\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Size\",\n    \"description\": \"\\nReturn a 1D tensor of type *int64* that contains the number of elements of the input tensor.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/utility_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Size\\\",\\n    [\\\"X\\\"],\\n    [\\\"size\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(3,3))))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"size:\\\", workspace.FetchBlob(\\\"size\\\"))\\n\\nworkspace.ResetWorkspace()\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.rand(6,4)))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"size:\\\", workspace.FetchBlob(\\\"size\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[3 7 0]\\n [0 1 6]\\n [5 0 8]]\\nsize: 9\\nX:\\n[[0.92017884 0.32115368 0.68692035 0.64135016]\\n [0.8723328  0.77830265 0.80688656 0.25524236]\\n [0.37970216 0.76407047 0.85689564 0.30692883]\\n [0.69352573 0.42531502 0.16415212 0.59209324]\\n [0.52684188 0.37094846 0.60670079 0.6489272 ]\\n [0.94715906 0.34800557 0.61898769 0.28947359]]\\nsize: 24\\n\\n```\\n\\n</details>\\n\\n      \",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input tensor to calculate number of elements.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* 1D tensor of type int64 that contains the number of elements in the input tensor *X*.\",\n        \"name\": \"size\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Slice\",\n    \"category\": \"Tensor\",\n    \"description\": \"\\nProduces a slice of the input tensor.\\n\\n- Currently, only slicing in a single dimension is supported.\\n\\n- Start and end indices are either passed as two 1D input tensors or using the `starts` and `ends` arguments.\\n\\n- If a negative value is passed for any of the start or end indices, it represents |value| - 1 elements before the end of that dimension. End indices are non-inclusive unless negative (end index -1 means up to and including the last element).\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/slice_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Slice\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    starts=(0,1),\\n    ends=(-1,3)\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.array([[1,2,3,4],[5,6,7,8]]))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[1 2 3 4]\\n [5 6 7 8]]\\nY:\\n[[2 3]\\n [6 7]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*Tuple(int)*): list of starting indices\",\n        \"name\": \"starts\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*Tuple(int)*): list of ending indices\",\n        \"name\": \"ends\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): tensor to extract slices from\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): 1D tensor of start-indices for each dimension of data (dimensions following the sliced one might be omitted)\",\n        \"name\": \"starts\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): 1D tensor of end-indices for each dimension of data (dimensions following the sliced one might be omitted)\",\n        \"name\": \"ends\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): sliced output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SliceGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Snapshot\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\",\n    \"description\": \"\\n\\nApplies the Softmax function to an n-dimensional input Tensor rescaling them so\\nthat the elements of the n-dimensional output Tensor lie in the range (0,1) and\\nsum to 1. The softmax operator is typically the last layer in a classifier network,\\nas its output can be interpreted as confidence probabilities of an input belonging\\nto each class. The input is a 2-D tensor (Tensor) of size (batch_size x\\ninput_feature_dimensions). The output tensor has the same shape and contains the\\nsoftmax normalized values of the corresponding input. The softmax function is\\ndefined as follows:\\n\\n$$softmax(x_i) = \\\\frac{\\\\exp(x_i)}{\\\\sum_{j} \\\\exp(x_j)}$$\\n\\nThe input does not need to explicitly be a 2D vector; rather, it will be coerced\\ninto one. For an arbitrary n-dimensional tensor `X` in\\n$[a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1}]$, where k is the `axis` provided,\\nthen `X` will be coerced into a 2-dimensional tensor with dimensions\\n$[(a_0 * ... * a_{k-1}), (a_k * ... * a_{n-1})]$. For the default case where\\n`axis`=1, the `X` tensor will be coerced into a 2D tensor of dimensions\\n$[a_0, (a_1 * ... * a_{n-1})]$, where $a_0$ is often the batch size. In this\\nsituation, we must have $a_0 = N$ and $a_1 * ... * a_{n-1} = D$. Each of these\\ndimensions must be matched correctly, or else the operator will throw errors.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/softmax_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/softmax_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Softmax\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(1, 5).astype(np.float32))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"softmax:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\ninput: [[ 0.0417839   0.61960053 -0.23150268 -0.64389366 -3.0000346 ]]\\nsoftmax: [[0.24422921 0.43525138 0.18582782 0.12303016 0.01166145]]\\n\\n```\\n\\n</details>\\n\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Axis of the inputs when coerced to 2D matrix.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input tensor that's coerced into a 2D matrix of size (NxD) as described above.\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor that's coerced into a 2D matrix of size (NxD) as described above.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The softmax normalized output values with the same shape as input tensor.\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* The softmax normalized output tensor with the same shape as input tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SoftmaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SoftmaxWithLoss\",\n    \"description\": \"\\nCombined Softmax and Cross-Entropy loss operator. The operator first computes the softmax normalized values for each layer in the batch of the given input, then computes cross-entropy loss. This operator is numerically more stable than separate `Softmax` and `CrossEntropy` ops. The inputs are a 2-D tensor `logits` of size (batch_size x input_feature_dimensions), which represents the unscaled log probabilities, and a 1-dimensional integer `labels` tensor for ground truth. An optional third input blob (`weight_tensor`) can be used to weight the samples for the loss, which is useful if the training set is unbalanced. This operator outputs a `softmax` tensor which contains the probability for each label for each example (same shape is `logits` input), and a scalar `loss` value, which is the averaged cross-entropy loss between the softmax probabilities and the ground truth values. Use parameter `label_prob`=1 to enable inputting labels as a probability distribution.\\n\\nSoftmax cross-entropy loss function:\\n\\n$$loss(x, class) = -\\\\log{\\\\biggl(\\\\frac{\\\\exp(x[class])}{\\\\sum_{j} \\\\exp(x[j])}\\\\biggr)} = -x[class] + \\\\log{\\\\biggl(\\\\sum_{j} \\\\exp(x[j])\\\\biggr)}$$\\n\\nor if the `weight_tensor` has been passed:\\n\\n$$loss(x, class) = weight[class]\\\\biggl(-x[class] + \\\\log{\\\\biggl(\\\\sum_{j} \\\\exp(x[j])\\\\biggr)}\\\\biggr)$$\\n\\nThe `logits` input does not need to explicitly be a 2D vector; rather, it will be coerced into one. For an arbitrary n-dimensional tensor `X` in $[a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1}]$, where k is the `axis` provided, then `X` will be coerced into a 2-dimensional tensor with dimensions $[(a_0 * ... * a_{k-1}), (a_k * ... * a_{n-1})]$. For the default case where `axis`=1, the `X` tensor will be coerced into a 2D tensor of dimensions $[a_0, (a_1 * ... * a_{n-1})]$, where $a_0$ is often the batch size. In this situation, we must have $a_0 = N$ and $a_1 * ... * a_{n-1} = D$. Each of these dimensions must be matched correctly, or else the operator will throw errors.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/softmax_with_loss_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SoftmaxWithLoss\\\",\\n    [\\\"logits\\\", \\\"labels\\\"],\\n    [\\\"softmax\\\", \\\"avgloss\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"logits\\\", np.random.randn(1, 5).astype(np.float32))\\nworkspace.FeedBlob(\\\"labels\\\", np.asarray([4]).astype(np.int32))\\nprint(\\\"logits:\\\", workspace.FetchBlob(\\\"logits\\\"))\\nprint(\\\"labels:\\\", workspace.FetchBlob(\\\"labels\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"softmax:\\\", workspace.FetchBlob(\\\"softmax\\\"))\\nprint(\\\"avgloss:\\\", workspace.FetchBlob(\\\"avgloss\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nlogits: [[-0.3429451  -0.80375195  0.23104447  1.4569176  -0.5268362 ]]\\nlabels: [4]\\nsoftmax: [[0.09721052 0.0613179  0.17258129 0.58800864 0.0808817 ]]\\navgloss: 2.5147676\\n\\n```\\n\\n</details>\\n\\n<details>\\n\\n<summary> <b>Example 2</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SoftmaxWithLoss\\\",\\n    [\\\"logits\\\", \\\"labels\\\"],\\n    [\\\"softmax\\\", \\\"avgloss\\\"],\\n    scale=5.0\\n)\\n\\nworkspace.FeedBlob(\\\"logits\\\", np.asarray([[.1, .4, .7, 1.5, .2]]).astype(np.float32))\\nworkspace.FeedBlob(\\\"labels\\\", np.asarray([4]).astype(np.int32))\\nprint(\\\"logits:\\\", workspace.FetchBlob(\\\"logits\\\"))\\nprint(\\\"labels:\\\", workspace.FetchBlob(\\\"labels\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"softmax:\\\", workspace.FetchBlob(\\\"softmax\\\"))\\nprint(\\\"avgloss:\\\", workspace.FetchBlob(\\\"avgloss\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nlogits: [[0.1 0.4 0.7 1.5 0.2]]\\nlabels: [4]\\nsoftmax: [[0.10715417 0.144643   0.19524762 0.4345316  0.11842369]]\\navgloss: 10.667433\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Setting to 1 enables inputting labels as probability distribution.\",\n        \"name\": \"label_prob\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"Axis of the inputs when coerced to 2D.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"Average loss output scaling factor (must be >= 0).\",\n        \"name\": \"scale\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": \"'NCHW'\",\n        \"description\": \"Order of blob dimensions (only 'NCHW' is supported currently).\",\n        \"name\": \"order\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input tensor.\",\n        \"name\": \"logits\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Ground truth label tensor.\",\n        \"name\": \"labels\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* [OPTIONAL] Blob used to weight the samples for the loss.\",\n        \"name\": \"weight_tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Softmax output tensor.\",\n        \"name\": \"softmax\"\n      },\n      {\n        \"description\": \"*(type: float)* Averaged cross-entropy loss output.\",\n        \"name\": \"loss\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SoftmaxWithLossGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Softplus\",\n    \"description\": \"\\nSoftplus takes one input data tensor $X$ and produces one output data tensor $Y,$ where the softplus function, $y = ln(e^x + 1)$, is applied to $X$ elementwise.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/softplus_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/softplus_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Softplus\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[-0.5380011   0.65190786  0.55673236]\\n [-0.16272168  0.5451048   0.30880353]\\n [-0.76606876 -0.6238556  -0.40444514]]\\n\\nY:\\n [[0.4598992  1.0713093  1.0097669 ]\\n [0.61509246 1.0023911  0.8594219 ]\\n [0.38174385 0.42909983 0.5112337 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob to be operated on.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob with same shape as input.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SoftplusGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Softsign\",\n    \"description\": \"\\n*Softsign* takes one input data tensor $X$ and produces one output data $Y,$ where the softsign function, $y = \\\\frac{x}{1+ |x|}$, is applied to $X$ elementwise. This operation can be done in an in-place fashion too, by providing the same input and output blobs.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/softsign_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Softsign\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\\n\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[-1.3060539   0.7242748  -1.9907674 ]\\n [-0.64802396 -0.03244735  0.7455406 ]\\n [-0.298492   -0.5774271   2.8364444 ]]\\n\\nY:\\n [[-0.5663588   0.420046   -0.6656376 ]\\n [-0.39321268 -0.03142761  0.4271116 ]\\n [-0.2298759  -0.36605626  0.739342  ]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input data blob to be operated on.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output data blob with same shape as input\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SoftsignGradient\",\n    \"description\": \"\\nCalculates the softsign gradient (sgn(x)/(1+|x|)^2) of the given input tensor\\nelement-wise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1-D input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The softsign gradient (sgn(x)/(1+|x|)^2) values of the input tensor computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortAndShuffle\",\n    \"description\": \"\\nCompute the sorted indices given a field index to sort by and break the sorted\\nindices into chunks of shuffle_size * batch_size and shuffle each chunk,\\nfinally we shuffle between batches. If sort_by_field_idx is -1 we skip sort.\\n\\nFor example, we have data sorted as\\n1,2,3,4,5,6,7,8,9,10,11,12\\n\\nand batchSize = 2 and shuffleSize = 3, when we shuffle we get:\\n[3,1,4,6,5,2] [12,10,11,8,9,7]\\n\\nAfter this we will shuffle among different batches with size 2\\n[3,1],[4,6],[5,2],[12,10],[11,8],[9,7]\\n\\nWe may end up with something like\\n[9,7],[5,2],[12,10],[4,6],[3,1],[11,8]\\n\\nInput(0) is a blob pointing to a TreeCursor, and\\n[Input(1),... Input(num_fields)] a list of tensors containing the data for\\neach field of the dataset.\\n\\nSortAndShuffle is thread safe.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A blob containing a pointer to the cursor.\",\n        \"name\": \"cursor\"\n      },\n      {\n        \"description\": \"First dataset field\",\n        \"name\": \"dataset_field_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor containing sorted indices.\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentMean\",\n    \"description\": \"\\nApplies 'Mean' to each segment of input tensor. Segments need to be sorted and\\ncontiguous. See also UnsortedSegmentMean that doesn't have this requirement.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nMean computes the element-wise mean of the input slices. Operation doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeLogMeanExp\",\n    \"description\": \"\\nApplies 'LogMeanExp' to each segment of input tensor. In order to allow for more\\nefficient implementation of 'LogMeanExp', the input segments have to be contiguous\\nand non-empty.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nLogMeanExp computes the element-wise log of the mean of exponentials of input slices. Operation doesn't change the shape of individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor to be aggregated\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor with the first dimension of K and the other dimentsions inherited from DATA\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeLogMeanExpGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeLogSumExp\",\n    \"description\": \"\\nApplies 'LogSumExp' to each segment of input tensor. In order to allow for more\\nefficient implementation of 'LogSumExp', the input segments have to be contiguous\\nand non-empty.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nLogSumExp computes the element-wise log of the sum of exponentials of input slices. Operation doesn't change the shape of individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor to be aggregated\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor with the first dimension of K and the other dimentsions inherited from DATA\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeLogSumExpGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeMax\",\n    \"description\": \"\\nApplies 'Max' to each segment of input tensor. In order to allow for more\\nefficient implementation of 'Max', the input segments have to be contiguous\\nand non-empty.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nMax computation is done element-wise, so that each element of the output slice corresponds to the max value of the respective elements in the input slices. Operation doesn't change the shape of individual blocks. This implementation imitates torch nn.Max operator. If the maximum value occurs more than once, the operator will return the first occurrence of value. When computing the gradient using the backward propagation, the gradient input corresponding to the first occurrence of the maximum value will be used.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor to be aggregated\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor with the first dimension of K and the other dimentsions inherited from DATA\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeMaxGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeMean\",\n    \"description\": \"\\nApplies 'Mean' to each segment of input tensor. In order to allow for more\\nefficient implementation of 'Mean', the input segments have to be contiguous\\nand non-empty.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nMean computation is done element-wise, so that each element of the output slice corresponds to the average value of the respective elements in the input slices. Operation doesn't change the shape of individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor to be aggregated\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor with the first dimension of K and the other dimentsions inherited from DATA\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeSum\",\n    \"description\": \"\\nApplies 'Sum' to each segment of input tensor. In order to allow for more\\nefficient implementation of 'Sum', the input segments have to be contiguous\\nand non-empty.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor to be aggregated\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor with the first dimension of K and the other dimentsions inherited from DATA\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentRangeSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentSum\",\n    \"description\": \"\\nApplies 'Sum' to each segment of input tensor. Segments need to be sorted and\\ncontiguous. See also UnsortedSegmentSum that doesn't have this requirement.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentWeightedSum\",\n    \"description\": \"\\nApplies 'WeightedSum' to each segment of input tensor. Segments need to be sorted and\\ncontiguous. See also UnsortedSegmentWeightedSum that doesn't have this requirement.\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Vector with the same length as the first dimension of DATA and values in the range 0..K-1 and in increasing order that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SortedSegmentWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SpaceToBatch\",\n    \"description\": \"\\nZero-pads and then rearranges (permutes) blocks of spatial data into batch. More specifically, this op outputs a copy of the input tensor where values from the height and width dimensions are moved to the batch dimension. After the zero-padding is according to the `pad` argument, both height and width of the input must be divisible by the `block_size`. Only \\\"NCHW\\\" order is currently supported.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/space_batch_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SpaceToBatch\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    pad=2,\\n    block_size=3\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.rand(1,3,5,5).astype(np.float32))\\nprint(\\\"X.shape:\\\", workspace.FetchBlob(\\\"X\\\").shape)\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y.shape:\\\", workspace.FetchBlob(\\\"Y\\\").shape)\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX.shape: (1, 3, 5, 5)\\nY.shape: (9, 3, 3, 3)\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): exclusive axis that divides the first and second dimension of matrix `A` (default=0)\",\n        \"name\": \"pad\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): height/width of spatial blocks to be moved (default=2)\",\n        \"name\": \"block_size\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*string*): order of dimensions of input and output blobs; only \\\"NCHW\\\" order is currently supported (default=\\\"NCHW\\\")\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor (NCHW order)\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): output tensor (NCHW order)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdadelta\",\n    \"description\": \"\\n\\nGiven inputs (param, moment, moment_delta, indices, grad, lr),\\nruns the dense AdaDelta update on (param, grad, moment[indices],\\n moment_delta[indices], lr), and returns (new_param, new_moment,\\n new_moment_delta) as in the dense case.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 0.95, the squared gradient sum is decayed by this factor.\",\n        \"name\": \"decay\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Average of squared gradients\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Average of squared parameter updates\",\n        \"name\": \"moment_delta\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated average squared gradient\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Updated average of squared parameter updates\",\n        \"name\": \"output_moment_delta\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagrad\",\n    \"description\": \"\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the dense AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment_1\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagradFusedWithSparseLengthsMeanGradient\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientMeanGradient (gradient of SparseLengthsMean) +\\nSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the sparse AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsIndicesInGradientMeanGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagradFusedWithSparseLengthsMeanGradientApprox\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientMeanGradient (gradient of SparseLengthsMean) +\\nSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the sparse AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsIndicesInGradientMeanGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagradFusedWithSparseLengthsSumGradient\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientSumGradient (gradient of SparseLengthsSum) +\\nSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the sparse AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsIndicesInGradientSumGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagradFusedWithSparseLengthsSumGradientApprox\",\n    \"description\": \"\\n\\nFused operator of\\nSparseLengthsIndicesInGradientSumGradient (gradient of SparseLengthsSum) +\\nSparseAdagrad.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the sparse AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case. Additional input (lengths) is for fused\\nSparseLengthsIndicesInGradientSumGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagradFusedWithSparseLengthsWeightedSumGradient\",\n    \"description\": \"\\n\\nFused operator of SparseLengthsIndicesInGradientWeightedSumWithMainInputGradient\\n(gradient of SparseLengthsWeightedSum) + SparseAdagrad, where weights are\\npositional weights computed with LengthsRangeFill + Gather pattern.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the sparse AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case.\\nThere're auxiliary inputs (aux_param) for which gradient is computed\\nand returns (aux_grad).\\nYet additional input (lengths) is for fused\\nSparseLengthsIndicesInGradientWeightedSumWithMainInputGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Auxiliary parameters to be updated\",\n        \"name\": \"aux_param\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Auxiliary gradient\",\n        \"name\": \"aux_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdagradFusedWithSparseLengthsWeightedSumGradientApprox\",\n    \"description\": \"\\n\\nApproximately fused operator of\\nSparseLengthsIndicesInGradientWeightedSumWithMainInputGradient\\n(gradient of SparseLengthsWeightedSum) + SparseAdagrad, where weights are\\npositional weights computed with LengthsRangeFill + Gather pattern.\\n\\nGiven inputs (param, moment, indices, grad, lr), runs the sparse AdaGrad\\nupdate on (param, grad, moment[indices], lr), and returns (new_param,\\nnew_moment) as in the dense case.\\nThere's race condition w.r.t. ordering between reading params and writing to\\nparam, hence the name Approx.\\nThere're auxiliary inputs (aux_param) for which gradient is computed and\\nreturns (aux_grad).\\nYet additional input (lengths) is for fused\\nSparseLengthsIndicesInGradientWeightedSumWithMainInputGradient operator.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Auxiliary parameters to be updated\",\n        \"name\": \"aux_param\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of param for the slices that are being updated\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to indices length\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Auxiliary gradients\",\n        \"name\": \"aux_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseAdam\",\n    \"description\": \"\\n\\n    Computes the Adam Update for the sparse case.\\n    Given inputs (param, moment1, moment2, indices, grad, lr, iter), runs the dense\\n    Adam on (param, moment1[indices], momemnt2[indices], lr, iter) and returns\\n    (new_param, new_moment1, new_moment2) as in dense case.\\n    Adam can be customized as Rectified Adam (RAdam) by setting enableRAdam = true.\\n\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"Default 0.9\",\n        \"name\": \"beta1\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 0.999\",\n        \"name\": \"beta2\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default false\",\n        \"name\": \"enableRAdam\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"First moment history\",\n        \"name\": \"moment_1\"\n      },\n      {\n        \"description\": \"Second moment history\",\n        \"name\": \"moment_2\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"iteration number\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated first moment\",\n        \"name\": \"output_moment_1\"\n      },\n      {\n        \"description\": \"Updated second moment\",\n        \"name\": \"output_moment_2\"\n      },\n      {\n        \"description\": \"Optional Effective gradient\",\n        \"name\": \"output_grad\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseDropoutWithReplacement\",\n    \"description\": \"\\n\\n`SparseDropoutWithReplacement` takes a 1-d input tensor and a lengths tensor.\\nValues in the Lengths tensor represent how many input elements consitute each\\nexample in a given batch.  The set of input values for an example will be\\nreplaced with the single dropout value with probability given by the `ratio`\\nargument.\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SparseDropoutWithReplacement\\\",\\n    [\\\"X\\\", \\\"Lengths\\\"],\\n    [\\\"Y\\\", \\\"OutputLengths\\\"],\\n    ratio=0.5,\\n    replacement_value=-1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.array([1, 2, 3, 4, 5]).astype(np.int64))\\nworkspace.FeedBlob(\\\"Lengths\\\", np.array([2, 3]).astype(np.int32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Lengths:\\\", workspace.FetchBlob(\\\"Lengths\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"OutputLengths:\\\", workspace.FetchBlob(\\\"OutputLengths\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [1, 2, 3, 4, 5]\\nLengths: [2, 3]\\nY: [1, 2, -1]\\nOutputLengths: [2, 1]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0.0,\n        \"description\": \"Probability of an element to be replaced.\",\n        \"name\": \"ratio\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Value elements are replaced with.\",\n        \"name\": \"replacement_value\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<int64_t>`)* Input data tensor.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int32_t>`)* Lengths tensor for input.\",\n        \"name\": \"Lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<int64_t>`)* Output tensor.\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<int32_t>`)* Output tensor.\",\n        \"name\": \"OutputLengths\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseFtrl\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsIndicesInGradientMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsIndicesInGradientSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsIndicesInGradientWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsIndicesInGradientWeightedSumWithMainInputGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMean\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'Mean' to each segment. Segments are defined by their LENGTHS.\\n\\nThis op is basically Gather and LengthsMean fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nLENGTHS is a vector that defines slice sizes by first dimension of DATA. Values\\nbelonging to the same segment are aggregated together. sum(LENGTHS) has\\nto match INDICES size.\\n\\nThe first dimension of the output is equal to the number of input segment,\\ni.e. `len(LENGTHS)`. Other dimensions are inherited from the input tensor.\\n\\nMean computes the element-wise mean of the input slices. Operation doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to INDICES length\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMean2BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsMean, but operating on 2-bit rowwise quantized matrices\\nwith fused storage (where each row stores quantized values, and then 2-byte\\nfp16 scale and bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused2BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMean4BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsMean, but operating on 4-bit rowwise quantized matrices\\nwith fused storage (where each row stores quantized values, and then 2-byte\\nfp16 scale and bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMean8BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsMean, but operating on 8-bit rowwise quantized matrices\\nwith fused storage (where each row stores quantized values, and then 4-byte\\nfp32 scale and bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMean8BitsRowwise\",\n    \"description\": \"\\nVariation of SparseLengthsMean operator, where DATA is\\nstored using 8bits. DATA was quantized with 8Bit row-wise\\nquantization (see doc to FloatToRowwiseQuantized8Bits operator). To\\nrestore DATA from 8Bit, we use additional input that stores scales\\nand biases.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToRowwiseQuantized8Bits\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Matrix of floats, each row r_i of which stores a pair s_i, b_i -- scale and bias for i-th row\",\n        \"name\": \"scale_bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMeanFused2BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsMean, but\\noperating on 2-bit rowwise quantized matrices with fused storage\\n(where each row stores quantized values, and then 2-byte fp16 scale and bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused2BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMeanFused4BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsMean, but\\noperating on 4-bit rowwise quantized matrices with fused storage\\n(where each row stores quantized values, and then 2-byte fp16 scale and bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMeanFused8BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsMean, but\\noperating on 8-bit rowwise quantized matrices with fused storage\\n(where each row stores quantized values, and then 4-byte scale and 4-byte bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused8BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsPositionalWeightedSum\",\n    \"description\": \"\\nVariation of SparseLengthsWeightedSum operator, where, for each row,\\nweights are accessed by indices [0..L-1], where L is the length of given row.\\nThis is basically a fused operator of LengthsRangeFill + Gather +\\nSparseWeightedSum\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToRowwiseQuantized8Bits\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the length of DATA\",\n        \"name\": \"WEIGHT\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSum\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'Sum' to each segment. Segments are defined by their LENGTHS.\\n\\nThis op is basically Gather and LengthsSum fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nLENGTHS is a vector that defines slice sizes by first dimension of DATA. Values\\nbelonging to the same segment are aggregated together. sum(LENGTHS) has\\nto match INDICES size.\\n\\nThe first dimension of the output is equal to the number of input segment,\\ni.e. `len(LENGTHS)`. Other dimensions are inherited from the input tensor.\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to INDICES length\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSum2BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsSum, but operating on 2-bit rowwise quantized matrices\\nwith fused storage (where each row stores quantized values, and then 2-byte\\nfp16 scale and 2-byte fp16 bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused2BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSum4BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsSum, but operating on 4-bit rowwise quantized matrices\\nwith fused storage (where each row stores quantized values, and then 2-byte\\nfp16 scale and 2-byte fp16 bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSum8BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsSum, but operating on 8-bit rowwise quantized matrices\\nwith fused storage (where each row stores quantized values, and then 4-byte\\nfp32 scale and 4-byte fp32 bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSum8BitsRowwise\",\n    \"description\": \"\\nVariation of SparseLengthsSum operator, where DATA is\\nstored using 8bits. DATA was quantized with 8Bit row-wise\\nquantization (see doc to FloatToRowwiseQuantized8Bits operator). To\\nrestore DATA from 8Bit, we use additional input that stores scales\\nand biases.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToRowwiseQuantized8Bits\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Matrix of floats, each row r_i of which stores a pair s_i, b_i -- scale and bias for i-th row\",\n        \"name\": \"scale_bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSumFused2BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsSum, but operating on\\n2-bit rowwise quantized matrices with fused storage (where each row\\nstores quantized values, and then 2-byte fp16 scale and bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused2BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSumFused4BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsSum, but operating on\\n4-bit rowwise quantized matrices with fused storage (where each row\\nstores quantized values, and then 2-byte fp16 scale and bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSumFused8BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsSum, but operating on\\n8-bit rowwise quantized matrices with fused storage (where each row\\nstores quantized values, and then 4-byte scale and 4-byte bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused8BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsSumSparseLookup\",\n    \"description\": \"\\nThis op converts compressed indices of SparseLengthsSum*Sparse to\\nuncompressed indices of SparseLengthsSum*. For compressed indices that maps\\nto -1. It means it will correspond to a zero row in the uncompressed data.\\nTherefore we will remove this indices and adjust the lengths.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Integer vector containing compressed indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of INDICES\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction. Same size as INDICES.\",\n        \"name\": \"WEIGHTS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Uncompressed indices\",\n        \"name\": \"output_indices\"\n      },\n      {\n        \"description\": \"Adjusted lengths\",\n        \"name\": \"output_lengths\"\n      },\n      {\n        \"description\": \"Adjusted weights\",\n        \"name\": \"output_weights\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedMean8BitsRowwise\",\n    \"description\": \"\\nVariation of SparseLengthsWeightedMean operator, where\\nDATA is stored using 8bits. DATA was quantized with 8Bit row-wise\\nquantization (see doc to FloatToRowwiseQuantized8Bits operator). To\\nrestore DATA from 8Bit, we use additional input that stores scales\\nand biases.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToRowwiseQuantized8Bits\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the length of INDICES\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Matrix of floats, each row r_i of which stores a pair s_i, b_i -- scale and bias for i-th row\",\n        \"name\": \"scale_bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSum\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'WeightedSum' to each segment. Segments are defined by their LENGTHS.\\n\\nThis op is basically Gather and LengthsWeightedSum fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nLENGTHS is a vector that defines slice sizes by first dimension of DATA. Values\\nbelonging to the same segment are aggregated together. sum(LENGTHS) has\\nto match INDICES size.\\n\\nThe first dimension of the output is equal to the number of input segment,\\ni.e. `len(LENGTHS)`. Other dimensions are inherited from the input tensor.\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Non negative vector with sum of elements equal to INDICES length\",\n        \"name\": \"LENGTHS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSum2BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsWeightedSum, but operating on 2-bit rowwise quantized\\nmatrices with fused storage (where each row stores quantized values, and then\\n2-byte fp16 scale and bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused2BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction\",\n        \"name\": \"WEIGHTS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSum4BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsWeightedSum, but operating on 4-bit rowwise quantized\\nmatrices with fused storage (where each row stores quantized values, and then\\n2-byte fp16 scale and bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction\",\n        \"name\": \"WEIGHTS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSum8BitRowwiseSparse\",\n    \"description\": \"\\nPerforms SparseLengthsWeightedSum, but operating on 8-bit rowwise quantized\\nmatrices with fused storage (where each row stores quantized values, and then\\n4-byte fp32 scale and bias), and where rows are pruned.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction\",\n        \"name\": \"WEIGHTS\"\n      },\n      {\n        \"description\": \"Integer vector mapping uncompressed indices to compressed indices\",\n        \"name\": \"COMPRESSED_INDICES_MAPPING\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSum8BitsRowwise\",\n    \"description\": \"\\nVariation of SparseLengthsWeightedSum operator, where\\nDATA is stored using 8bits. DATA was quantized with 8Bit row-wise\\nquantization (see doc to FloatToRowwiseQuantized8Bits operator). To\\nrestore DATA from 8Bit, we use additional input that stores scales\\nand biases.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToRowwiseQuantized8Bits\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the length of INDICES\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Matrix of floats, each row r_i of which stores a pair s_i, b_i -- scale and bias for i-th row\",\n        \"name\": \"scale_bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSumFused2BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsWeightedSum,\\nbut operating on 2-bit rowwise quantized matrices with fused storage\\n(where each row stores quantized values, and then 2-byte fp16 scale and bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused2BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction\",\n        \"name\": \"WEIGHTS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSumFused4BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsWeightedSum,\\nbut operating on 4-bit rowwise quantized matrices with fused storage\\n(where each row stores quantized values, and then 2-byte fp16 scale and bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused4BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction\",\n        \"name\": \"WEIGHTS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSumFused8BitRowwise\",\n    \"description\": \"\\nPerforms the same operation as SparseLengthsWeightedSum,\\nbut operating on 8-bit rowwise quantized matrices with fused storage\\n(where each row stores quantized values, and then 4-byte scale and 4-byte bias).\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"uint8 tensor obtained with operator FloatToFused8BitRowwiseQuantized\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same sum of elements as the first dimension of DATA\",\n        \"name\": \"LENGTHS\"\n      },\n      {\n        \"description\": \"Vector of weights to scale rows of DATA with before reduction\",\n        \"name\": \"WEIGHTS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLengthsWeightedSumWithMainInputGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseLpRegularizer\",\n    \"description\": \"\\nGiven a sparse matrix, apply Lp regularization.  Currently only L1 and L2 are implemented.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Value of p in the Lp regularization to use. The default is 2.0.\",\n        \"name\": \"p\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Value of lambda (multiplier for the regularization term). The default is 1e-5.\",\n        \"name\": \"reg_lambda\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be regularized\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed (optional - not used, this argument is for backwards compatibility)\",\n        \"name\": \"grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Regularized parameters\",\n        \"name\": \"output_param\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseMomentumSGDUpdate\",\n    \"description\": \"\\n\\nPerforms a momentum SGD update analogous to MomentumSGDUpdate, but using a\\nGradientSlice and indices into the full param and momentum tables. Both param\\nand momentum should be in-place (corresponding inputs and outputs should be the\\nsame blobs).\\n\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Momentum hyperparameter.\",\n        \"name\": \"momentum\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(boolean) Whether to use Nesterov Accelerated Gradient.\",\n        \"name\": \"nesterov\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"GradientSlice with gradients for updated indices.\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"Momentum blob, same shape as param.\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Learning rate.\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Full parameter blob.\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Indices (in first dimension of param) where updates are performed.\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Adjusted gradient.\",\n        \"name\": \"output_grad\"\n      },\n      {\n        \"description\": \"Updated momentum.\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Updated parameter\",\n        \"name\": \"output_param\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseNormalize\",\n    \"description\": \"\\nGiven a sparse matrix, apply max_norm or constant_norm sparse regularization.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"A bool variable to control whether to use max norm     or constant norm. When use_max_norm = false, constant norm is used so that     all the embedding vectors are scaled to have a L2 norm equals to A     (see blow argument norm=A). If use_max_norm = true,     max norm is used so that embedding is scaled so that its l2 norm is no larger     than A. If an embedding's norm is less than A originally,     the embedding is left unchanged.    The default is True.\",\n        \"name\": \"use_max_norm\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"L2 norm of the embedding. The default is 1.0.\",\n        \"name\": \"norm\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be normalized\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed (optional - not used, this argument is for backwards compatibility)\",\n        \"name\": \"grad\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Normalized parameters\",\n        \"name\": \"output_param\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseSortedSegmentMean\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'Mean' to each segment. Segments need to be sorted and contiguous. See also\\nSparseUnsortedSegmentMean that doesn't have this requirement.\\n\\nThis op is basically Gather and SortedSegmentMean fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nSEGMENT_IDS is a vector that maps each referenced slice of the DATA to a\\nparticular group (segment). Values belonging to the same segment are aggregated\\ntogether. SEGMENT_IDS should have the same dimension as INDICES.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nMean computes the element-wise mean of the input slices. Operation doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same length as INDICES and values in the range 0..K-1 and in increasing order that maps each slice of DATA referenced by INDICES to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseSortedSegmentMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseSortedSegmentSum\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'Sum' to each segment. Segments need to be sorted and contiguous. See also\\nSparseUnsortedSegmentSum that doesn't have this requirement.\\n\\nThis op is basically Gather and SortedSegmentSum fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nSEGMENT_IDS is a vector that maps each referenced slice of the DATA to a\\nparticular group (segment). Values belonging to the same segment are aggregated\\ntogether. SEGMENT_IDS should have the same dimension as INDICES.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same length as INDICES and values in the range 0..K-1 and in increasing order that maps each slice of DATA referenced by INDICES to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseSortedSegmentSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseSortedSegmentWeightedSum\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'WeightedSum' to each segment. Segments need to be sorted and contiguous. See also\\nSparseUnsortedSegmentWeightedSum that doesn't have this requirement.\\n\\nThis op is basically Gather and SortedSegmentWeightedSum fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nSEGMENT_IDS is a vector that maps each referenced slice of the DATA to a\\nparticular group (segment). Values belonging to the same segment are aggregated\\ntogether. SEGMENT_IDS should have the same dimension as INDICES.\\n\\nThe first dimension of the output is equal to the number of input segments,\\ni.e. `SEGMENT_IDS[-1]+1`. Other dimensions are inherited from the input tensor.\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Vector with the same length as INDICES and values in the range 0..K-1 and in increasing order that maps each slice of DATA referenced by INDICES to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of K (the number of segments).\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseSortedSegmentWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseStorm\",\n    \"description\": \"\\n\\nThis operator implement the STORM (https://arxiv.org/abs/1905.10018)\\noptimization algorithm. Given inputs (param, moment, grad_sq_sum, grad,\\nindices, lr), computes the dense STORM update on (param, moment[indices],\\ngrad_sq_sum, grad, lr), and returns (new_param, new_moment, new_grad_sq_sum)\\nas in the dense case.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Momentum hyperparameter, c in the original paper.\",\n        \"name\": \"momentum\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"denominator in adaptive learning rate, w in the original paper.\",\n        \"name\": \"beta\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated.\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history.\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Sum of observed squared gradients.\",\n        \"name\": \"grad_sq_sum\"\n      },\n      {\n        \"description\": \"Gradients computed.\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"Sparse indices.\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Learning rate, k in the original paper.\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters.\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment.\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Updated sum of squared gradients.\",\n        \"name\": \"output_grad_sq_sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseToDense\",\n    \"description\": \"\\nConvert sparse representations to dense with given indices.\\n\\nTransforms a sparse representation of map<id, value> represented as `indices`\\nvector and `values` tensor into a compacted tensor where the first dimension\\nis determined by the first dimension of the 3rd input if it is given or the\\nmax index. Missing values are filled with zeros.\\n\\nThe op supports duplicated indices and performs summation over corresponding\\nvalues. This behavior is useful for converting GradientSlices into dense\\nrepresentation.\\n\\nAfter running this op:\\n\\n  output[indices[i], :] += values[i]  // sum over all indices[i] equal to the index\\n  output[j, ...] = 0 if j not in indices\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1-D int32/int64 tensor of concatenated ids of data\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Data tensor, first dimension has to match `indices`, basic numeric types are supported\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"Optional: if provided, the first dimension of output is the first dimension of this tensor.\",\n        \"name\": \"data_to_infer_dim\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of the same type as `values` of shape `[len(lengths), len(mask)] + shape(default_value)` (if `lengths` is not provided the first dimension is omitted)\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseToDenseMask\",\n    \"description\": \"\\nConvert sparse representations to dense with given indices.\\n\\nTransforms a sparse representation of map<id, value> represented as `indices`\\nvector and `values` tensor into a compacted tensor where the first dimension\\ncorresponds to each id provided in the mask argument. Missing values are filled\\nwith the value of `default_value`. After running this op:\\n\\n  output[j, :] = values[i] // where mask[j] == indices[i]\\n  output[j, ...] = default_value // when mask[j] doesn't appear in indices\\n\\nIf `lengths` is provided and not empty, an extra \\\"batch\\\" dimension is prepended\\nto the output.\\n\\n`values` and `default_value` can have additional matching dimensions\\n(the operation is performed on the entire subtensor in this case).\\n\\nFor example, if `lengths` is supplied and `values` is a 1-D vector of floats\\nand `default_value` is a float scalar, the output is going to be a float\\nmatrix of size `len(lengths) X len(mask)`.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"list(int) argument with desired ids on the 'dense' output dimension\",\n        \"name\": \"mask\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"bool whether to return presence mask, false by default\",\n        \"name\": \"return_presence_mask\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int argument representing the maximum number of invalid row ids that can be skipped before returning an error. 50 by default\",\n        \"name\": \"max_skipped_indices\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1-D int32/int64 tensor of concatenated ids of data\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Data tensor, first dimension has to match `indices`\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"Default value for the output if the id is not present in `indices`. Must have the same type as `values` and the same shape, but without the first dimension\",\n        \"name\": \"default_value\"\n      },\n      {\n        \"description\": \"Optional lengths to represent a batch of `indices` and `values`.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of the same type as `values` of shape `[len(lengths), len(mask)] + shape(default_value)` (if `lengths` is not provided the first dimension is omitted)\",\n        \"name\": \"output\"\n      },\n      {\n        \"description\": \"Bool tensor of shape `[len(lengths), len(mask)]` (if `lengths` is not provided the first dimension is omitted). True when a value for given id was present, false otherwise.\",\n        \"name\": \"presence_mask\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseToDenseMaskGradient\",\n    \"description\": \"\\nThe output is the gradient of the input value from SparseToDenseMask. The\\ngradient for default_value has not been implemented.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseUnsortedSegmentMean\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'Mean' to each segment. Segments ids can appear in arbitrary order (unlike in\\nSparseSortedSegmentMean).\\n\\nThis op is basically Gather and UnsortedSegmentMean fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nSEGMENT_IDS is a vector that maps each referenced slice of the DATA to a\\nparticular group (segment). Values belonging to the same segment are aggregated\\ntogether. SEGMENT_IDS should have the same dimension as INDICES.\\n\\nIf `num_segments` argument is passed it would be used as a first dimension for\\nthe output. Otherwise, it'd be dynamically calculated from as the max value of\\nSEGMENT_IDS plus one. Other output dimensions are inherited from the input\\ntensor.\\n\\nMean computes the element-wise mean of the input slices. Operation doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Integer vector with the same length as INDICES that maps each slice of DATA referenced by INDICES to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of equal to the number of segments.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseUnsortedSegmentMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseUnsortedSegmentSum\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'Sum' to each segment. Segments ids can appear in arbitrary order (unlike in\\nSparseSortedSegmentSum).\\n\\nThis op is basically Gather and UnsortedSegmentSum fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nSEGMENT_IDS is a vector that maps each referenced slice of the DATA to a\\nparticular group (segment). Values belonging to the same segment are aggregated\\ntogether. SEGMENT_IDS should have the same dimension as INDICES.\\n\\nIf `num_segments` argument is passed it would be used as a first dimension for\\nthe output. Otherwise, it'd be dynamically calculated from as the max value of\\nSEGMENT_IDS plus one. Other output dimensions are inherited from the input\\ntensor.\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Integer vector with the same length as INDICES that maps each slice of DATA referenced by INDICES to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of equal to the number of segments.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseUnsortedSegmentSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseUnsortedSegmentWeightedSum\",\n    \"description\": \"\\nPulls in slices of the input tensor, groups them into segments and applies\\n'WeightedSum' to each segment. Segments ids can appear in arbitrary order (unlike in\\nSparseSortedSegmentWeightedSum).\\n\\nThis op is basically Gather and UnsortedSegmentWeightedSum fused together.\\n\\nINDICES should contain integers in range 0..N-1 where N is the first dimension\\nof DATA. INDICES represent which slices of DATA need to be pulled in.\\n\\nSEGMENT_IDS is a vector that maps each referenced slice of the DATA to a\\nparticular group (segment). Values belonging to the same segment are aggregated\\ntogether. SEGMENT_IDS should have the same dimension as INDICES.\\n\\nIf `num_segments` argument is passed it would be used as a first dimension for\\nthe output. Otherwise, it'd be dynamically calculated from as the max value of\\nSEGMENT_IDS plus one. Other output dimensions are inherited from the input\\ntensor.\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated\",\n        \"name\": \"INDICES\"\n      },\n      {\n        \"description\": \"Integer vector with the same length as INDICES that maps each slice of DATA referenced by INDICES to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of equal to the number of segments.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseUnsortedSegmentWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseWngrad\",\n    \"description\": \"\\n\\nThis operator implement the optimization algorithm\\nin https://arxiv.org/abs/1803.02865 by Wu, Ward and Bottou.\\nGiven inputs (param, seq_b, indices, grad, lr), runs the dense WnGrad\\nupdate on (param, grad, seq_b, lr), and returns (new_param,\\nnew_seq_b) as in the dense case.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"seq_b history\",\n        \"name\": \"seq_b\"\n      },\n      {\n        \"description\": \"Sparse indices\",\n        \"name\": \"indices\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated seq_b\",\n        \"name\": \"output_seq_b\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SpatialBN\",\n    \"category\": \"Normalization\",\n    \"description\": \"\\nApplies spatial batch normalization to the input tensor as described in the original paper, [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](https://arxiv.org/abs/1502.03167). Be aware, this operator has two different output sets, depending on the value of *is_test*. According to the paper, the primary operation of spatial batch normalization is:\\n\\n$$Y = \\\\frac{X - \\\\mu_x}{\\\\sqrt{\\\\sigma^2_{x} + \\\\epsilon}}*\\\\gamma + b$$\\n\\nIn the equation, $\\\\mu_x$ is the *mean*, $X$ is the input data, $\\\\sigma^2_{x}$ is the *var*, $\\\\epsilon$ is *epsilon*, $\\\\gamma$ is the *scale*, $b$ is the *bias*, and $Y$ is the output data. The *momentum* arg also affects this calculation in the computation of the running mean and variance. The influence of *momentum* is as follows:\\n\\n$$running\\\\_mean = running\\\\_mean * momentum + mean * (1 - momentum)$$\\n\\n$$running\\\\_var = running\\\\_var * momentum + var * (1 - momentum)$$\\n\\nOutput when is_test = 0 (train mode): *Y, mean, var, saved_mean, saved_var*\\n\\nOutput when is_test = 1 (test mode): *Y*\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/spatial_batch_norm_op.cc\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/spatial_batch_norm_op.h\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"If set to nonzero, run spatial batch normalization in test mode.\",\n        \"name\": \"is_test\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": 1e-05,\n        \"description\": \"The epsilon value to use to avoid division by zero.\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": \"NCHW\",\n        \"description\": \"Specifies the order of the input data blob, where $N$ is batch size, $C$ is number of channels, $H$ is spatial height, and $W$ is spatial width. The only other valid option is \\\"NHWC\\\".\",\n        \"name\": \"order\",\n        \"option\": \"optional\",\n        \"type\": \"string\"\n      },\n      {\n        \"default\": 0.9,\n        \"description\": \"Factor used in computing the running mean and variance. e.g., running_mean = running_mean x momentum + mean x (1 - momentum)\",\n        \"name\": \"momentum\",\n        \"option\": \"optional\",\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"Specifies the number of batches to apply normalization on. Requires specifying the optional sums and sumsq inputs that provide statistics across multiple batches from which mean and variance can be determined.\",\n        \"name\": \"num_batches\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"The scale as a 1-dimensional tensor of size $C$ to be applied to the output.\",\n        \"name\": \"scale\"\n      },\n      {\n        \"description\": \"The bias as a 1-dimensional tensor of size $C$ to be applied to the output.\",\n        \"name\": \"bias\"\n      },\n      {\n        \"description\": \"The running mean (training) or the estimated mean (testing) as a 1-dimensional tensor of size $C$.\",\n        \"name\": \"mean\"\n      },\n      {\n        \"description\": \"The running variance (training) or the estimated variance (testing) as a 1-dimensional tensor of size $C$.\",\n        \"name\": \"var\"\n      },\n      {\n        \"description\": \"The input 4-dimensional tensor of shape $NCHW$ or $NHWC$ depending on the order parameter.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"*(optional)* Per-channel sums of elements to be used to determine the mean and variance for this batch.\",\n        \"name\": \"sums\"\n      },\n      {\n        \"description\": \"*(optional)* Per-channel sum of elements squared per channel to be used to determine the variance for this batch.\",\n        \"name\": \"sumsq\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output 4-dimensional tensor of the same shape as $X$.\",\n        \"name\": \"Y\"\n      },\n      {\n        \"description\": \"The running mean after the spatial BN operator. Must be in-place with the input *mean*. Should not be used for testing.\",\n        \"name\": \"mean\"\n      },\n      {\n        \"description\": \"The running variance after the spatial BN operator. Must be in-place with the input *var*. Should not be used for testing.\",\n        \"name\": \"var\"\n      },\n      {\n        \"description\": \"Saved mean used during training to speed up gradient computation. Should not be used for testing.\",\n        \"name\": \"saved_mean\"\n      },\n      {\n        \"description\": \"Saved variance used during training to speed up gradient computation. Should not be used for testing.\",\n        \"name\": \"saved_var\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SpatialBNGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SpatialSoftmaxWithLoss\",\n    \"description\": \"\\nCombined Spatial Softmax and Cross-Entropy loss operator.\\nSimilar to SoftmaxWithLoss, this operator computes the spatial softmax\\nnormalized values for each layer in the batch of the given input, after which\\ncross-entropy loss is computed. This operator is numerically more stable than\\nseparate Softmax and CrossEntropy ops. The inputs are a 2-D tensor\\n(Tensor) of size (batch_size x input_feature_dimensions) and tensor of\\nlabels (ground truth).\\nOutput is tensor with the probability for each label in a pixel for each example\\n(N x D x W x H) and averaged loss (scalar).\\nFor spatial softmax, weighting is by x,y position of the input.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Unscaled log probabilities\",\n        \"name\": \"logits\"\n      },\n      {\n        \"description\": \"Ground truth\",\n        \"name\": \"labels\"\n      },\n      {\n        \"description\": \"Optional blob to be used to weight the samples for the loss. With        spatial set, weighting is by x,y of the input\",\n        \"name\": \"weight_tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor with softmax cross entropy loss\",\n        \"name\": \"softmax\"\n      },\n      {\n        \"description\": \"Average loss\",\n        \"name\": \"loss\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SpatialSoftmaxWithLossGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Split\",\n    \"description\": \"\\nSplit an `input` tensor into a list of tensors, along the axis specified by the `axis` dimension. The lengths of the split can be specified using argument `split` or optional second input blob to the operator. Otherwise, the tensor is split to equal sized parts.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/concat_split_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Split\\\",\\n    [\\\"input\\\"],\\n    [\\\"output_0\\\",\\\"output_1\\\",\\\"output_2\\\"],\\n    split=(3,2,4),\\n    axis=0\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.random.randint(10, size=(9)))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"input\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output_0:\\\", workspace.FetchBlob(\\\"output_0\\\"))\\nprint(\\\"output_1:\\\", workspace.FetchBlob(\\\"output_1\\\"))\\nprint(\\\"output_2:\\\", workspace.FetchBlob(\\\"output_2\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput: [2 2 6 6 6 0 5 7 4]\\noutput_0: [2 2 6]\\noutput_1: [6 6]\\noutput_2: [0 5 7 4]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): axis to split on\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Pass non-zero integer to remove the axis specified in `axis` to all input tensors.\",\n        \"name\": \"add_axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"description\": \"(*Tuple(int)*): length of each output\",\n        \"name\": \"split\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*string*): order of dimensions of input and output blobs; either \\\"NCHW\\\" or \\\"NHWC\\\"\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): tensor to split\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): [OPTIONAL] list of output lengths (see also arg `split`)\",\n        \"name\": \"split\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): output tensor\",\n        \"name\": \"[output_0, output_1, ...]\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SplitByLengths\",\n    \"description\": \"\\nSplit a tensor into a list of tensors, given a lengths input, along the specified\\n'axis'. If `K` outputs are provided, the op assumes `len(lengths) % K == 0`.\\nThe `input` will be split into `K` parts. Each part of length\\n`sum(lengths[i*k:i*k+k))`\\n\\n<details>\\n\\n<summary> <b>Example 1</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SplitByLengths\\\",\\n    [\\\"input\\\", \\\"lengths\\\"],\\n    [\\\"output_0\\\",\\\"output_1\\\",\\\"output_2\\\"],\\n    axis=0\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.random.randint(10, size=(9)))\\nworkspace.FeedBlob(\\\"lengths\\\", np.array([3,2,4], dtype=np.int32))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"input\\\"))\\nprint(\\\"lengths:\\\", workspace.FetchBlob(\\\"lengths\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"output_0:\\\", workspace.FetchBlob(\\\"output_0\\\"))\\nprint(\\\"output_1:\\\", workspace.FetchBlob(\\\"output_1\\\"))\\nprint(\\\"output_2:\\\", workspace.FetchBlob(\\\"output_2\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput: [2 2 6 6 6 0 5 7 4]\\nlengths: [3 2 4]\\noutput_0: [2 2 6]\\noutput_1: [6 6]\\noutput_2: [0 5 7 4]\\n\\n```\\n\\n<summary> <b>Example 2</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SplitByLengths\\\",\\n    [\\\"input\\\", \\\"lengths\\\"],\\n    [\\\"output_0\\\",\\\"output_1\\\",\\\"output_2\\\"],\\n    axis=0,\\n    use_scaling_lengths=true,\\n)\\n\\nworkspace.FeedBlob(\\\"input\\\", np.random.randint(10, size=(9)))\\nworkspace.FeedBlob(\\\"lengths\\\", np.array([1,1,1], dtype=np.int32))\\nprint(\\\"input:\\\", workspace.FetchBlob(\\\"input\\\"))\\nprint(\\\"lengths:\\\", workspace.FetchBlob(\\\"lengths\\\"))\\nprint(\\\"output_0:\\\", workspace.FetchBlob(\\\"output_0\\\"))\\nprint(\\\"output_1:\\\", workspace.FetchBlob(\\\"output_1\\\"))\\nprint(\\\"output_2:\\\", workspace.FetchBlob(\\\"output_2\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ninput: [2 2 6 6 6 0 5 7 4]\\nlengths: [1 1 1]\\noutput_0: [2 2 6]\\noutput_1: [6 6 6]\\noutput_2: [5 7 4]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Which axis to split on\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Either NHWC or NCWH, will split on C axis, defaults to NCHW\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*bool*): Enables automatic scaling of the lengths values. When enabled will automatically find a value K >= 1, such that sum(lengths) * K == len(input).\",\n        \"name\": \"use_scaling_lengths\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The tensor to split\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"The tensor `l_i` indicates the logic block of input.\",\n        \"name\": \"legnths\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sqr\",\n    \"description\": \"\\nPerforms element-wise squaring ($x^2$) of input tensor.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sqr_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sqr\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(3,3))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[4. 6. 2.]\\n [0. 1. 6.]\\n [9. 2. 7.]]\\nY:\\n[[16. 36.  4.]\\n [ 0.  1. 36.]\\n [81.  4. 49.]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sqrt\",\n    \"description\": \"\\nPerforms element-wise square-root ($\\\\sqrt{x}$) of input tensor $X$.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/sqrt_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sqrt\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", (np.random.randint(10, size=(3,3))).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[8. 3. 3.]\\n [4. 0. 0.]\\n [1. 2. 5.]]\\nY:\\n[[2.8284268  1.7320508  1.7320508 ]\\n [1.9999999  0.         0.        ]\\n [0.99999994 1.4142134  2.236068  ]]\\n\\n```\\n\\n</details>\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Input data tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SquaredL2Distance\",\n    \"description\": \"\\nGiven two input float tensors X, Y, and produces one output float tensor\\nof the L2 difference between X and Y that is computed as ||(X - Y)^2 / 2||.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D or 2D input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D or 2D input tensor (must have the same shape as X)\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SquaredL2DistanceGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SquareRootDivide\",\n    \"description\": \"\\nGiven DATA tensor with first dimension N and SCALE vector of the same size N\\nproduces an output tensor with same dimensions as DATA. Which consists of DATA\\nslices. i-th slice is divided by sqrt(SCALE[i]) elementwise. If SCALE[i] == 0\\noutput slice is identical to the input one (no scaling)\\n\\nExample:\\n\\n  Data = [\\n    [2.0, 4.0],\\n    [9.0, 12.0]\\n  ]\\n\\n  SCALE = [4, 9]\\n\\n  OUTPUT = [\\n    [1.0, 2.0],\\n    [3.0, 4.0]\\n  ]\\n\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"category\": \"Transform\",\n    \"description\": \"\\nThe *Squeeze* op removes single-dimensional entries from the shape of the input tensor *data,* and produces a single output tensor *squeezed*. The op also takes an argument *dims* with a list of dimensions to squeeze. If the same blob is provided as input and output, the operation is copy-free. This is the exact inverse operation of *ExpandDims* given the same *dims* argument.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.h\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Squeeze\\\",\\n    [\\\"data\\\"],\\n    [\\\"squeezed\\\"],\\n    dims=[0,1],\\n)\\n\\nworkspace.FeedBlob(\\\"data\\\", np.zeros((1,1,100,100)).astype(np.float32))\\nprint(\\\"data.shape:\\\", workspace.FetchBlob(\\\"data\\\").shape)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"squeezed.shape:\\\", workspace.FetchBlob(\\\"squeezed\\\").shape)\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ndata.shape: (1, 1, 100, 100)\\nsqueezed.shape: (100, 100)\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of dimensions of *data* to squeeze out.\",\n        \"name\": \"dims\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor of data to be operated on.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Reshaped tensor with same data as input.\",\n        \"name\": \"squeezed\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StatRegistryCreate\",\n    \"description\": \"\\nCreate a StatRegistry object that will contain a map of performance counters\\nkeyed by name. A StatRegistry is used to gather and retrieve performance\\ncounts throughout the caffe2 codebase.\\n\",\n    \"outputs\": [\n      {\n        \"description\": \"A Blob pointing to the newly created StatRegistry.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StatRegistryExport\",\n    \"attributes\": [\n      {\n        \"description\": \"(default true) Whether to atomically reset the counters afterwards.\",\n        \"name\": \"reset\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"If provided, export values from given StatRegistry.Otherwise, export values from the global singleton StatRegistry.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D string tensor with exported key names\",\n        \"name\": \"keys\"\n      },\n      {\n        \"description\": \"1D int64 tensor with exported values\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"The unix timestamp at counter retrieval.\",\n        \"name\": \"timestamps\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StatRegistryUpdate\",\n    \"description\": \"\\nUpdate the given StatRegistry, or the global StatRegistry,\\nwith the values of counters for the given keys.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D string tensor with the key names to update.\",\n        \"name\": \"keys\"\n      },\n      {\n        \"description\": \"1D int64 tensor with the values to update.\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"If provided, update the given StatRegistry. Otherwise, update the global singleton.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StdDevPut\",\n    \"description\": \"\\n      Consume a value and pushes it to the global stat registry as an standard deviation.\\n\\n      Github Links:\\n      - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_put_ops.cc\\n\\n        \",\n    \"attributes\": [\n      {\n        \"description\": \"(*str*): name of the stat. If not present, then uses name of input blob\",\n        \"name\": \"name\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int64_t*): number to multiply input values by (used when inputting floats, as stats can only receive integers\",\n        \"name\": \"magnitude_expand\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*boolean*): whether or not to clamp inputs to the max inputs allowed\",\n        \"name\": \"bound\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*float*): Optionally provide a default value for receiving empty tensors\",\n        \"name\": \"default_value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<number>`*): A scalar tensor, representing any numeric value\",\n        \"name\": \"value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StopGradient\",\n    \"description\": \"\\nStopGradient is a helper operator that does no actual numerical computation,\\nand in the gradient computation phase stops the gradient from being computed\\nthrough it.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StoreAdd\",\n    \"description\": \"\\nAdd a value to a remote counter. If the key is not set, the store\\ninitializes it to 0 and then performs the add operation. The operation\\nreturns the resulting counter value.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"key of the counter (required)\",\n        \"name\": \"blob_name\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"value that is added (optional, default: 1)\",\n        \"name\": \"add_value\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"unique_ptr<StoreHandler>\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"the current value of the counter\",\n        \"name\": \"value\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StoreGet\",\n    \"description\": \"\\nGet a blob from a store. The key is the output blob's name. The key\\ncan be overridden by specifying the 'blob_name' argument.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"alternative key for the blob (optional)\",\n        \"name\": \"blob_name\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"unique_ptr<StoreHandler>\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"data blob\",\n        \"name\": \"data\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StoreSet\",\n    \"description\": \"\\nSet a blob in a store. The key is the input blob's name and the value\\nis the data in that blob. The key can be overridden by specifying the\\n'blob_name' argument.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"alternative key for the blob (optional)\",\n        \"name\": \"blob_name\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"unique_ptr<StoreHandler>\",\n        \"name\": \"handler\"\n      },\n      {\n        \"description\": \"data blob\",\n        \"name\": \"data\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StoreWait\",\n    \"description\": \"\\nWait for the specified blob names to be set. The blob names can be passed\\neither as an input blob with blob names or as an argument.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"names of the blobs to wait for (optional)\",\n        \"name\": \"blob_names\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"unique_ptr<StoreHandler>\",\n        \"name\": \"handler\"\n      },\n      {\n        \"description\": \"names of the blobs to wait for (optional)\",\n        \"name\": \"names\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Storm\",\n    \"description\": \"\\n\\nComputes the STORM (https://arxiv.org/abs/1905.10018) update for an input\\ngradient and accumulated history of gradients. Concretely, given inputs\\n(param, moment, grad_sq_sum, grad, lr), computes:\\n\\n    new_grad_sq_sum = grad_sq_sum + norm(grad)^2\\n    effective_lr = lr / (beta + new_grad_sq_sum)^1/3\\n    alpha = momentum * square(effective_lr)\\n    new_moment = grad + (1 - alpha) * (moment - grad)\\n    new_param = param + effective_lr * new_moment\\n\\nand returns (new_param, new_moment, new_grad_sq_sum).\\n\\nNote that due to caffe2 limitation, it is difficult to re-calculate gradient\\nin the previous iteration using the current example. We simplied calculation\\nfor new_moment by using the gradient from the current iteration.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Momentum hyperparameter, c in the original paper.\",\n        \"name\": \"momentum\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"denominator in adaptive learning rate, w in the original paper.\",\n        \"name\": \"beta\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated.\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Moment history.\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Sum of observed squared gradients.\",\n        \"name\": \"grad_sq_sum\"\n      },\n      {\n        \"description\": \"Gradients computed.\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"Learning rate, k in the original paper.\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters.\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated moment.\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Updated sum of squared gradients.\",\n        \"name\": \"output_grad_sq_sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringEndsWith\",\n    \"description\": \"\\nPerforms the ends-with check on each string in the input tensor.\\nReturns tensor of boolean of the same dimension of input.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The suffix to check input strings against.\",\n        \"name\": \"suffix\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of std::string.\",\n        \"name\": \"strings\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of bools of same shape as input.\",\n        \"name\": \"bools\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringEquals\",\n    \"description\": \"\\nPerforms equality check on each string in the input tensor.\\nReturns tensor of booleans of the same dimension as input.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The text to check input strings equality against.\",\n        \"name\": \"text\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of std::string.\",\n        \"name\": \"strings\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of bools of same shape as input.\",\n        \"name\": \"bools\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringIndexCreate\",\n    \"description\": \"\\nCreates a dictionary that maps string keys to consecutive integers\\nfrom 1 to max_elements. Zero is reserved for unknown keys.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Max number of elements, including the zero entry.\",\n        \"name\": \"max_elements\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Pointer to an Index instance.\",\n        \"name\": \"handle\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringJoin\",\n    \"description\": \"\\nTakes a 1-D or a 2-D tensor as input and joins elements in each row with the\\nprovided delimiter. Output is a 1-D tensor of size equal to the first dimension\\nof the input. Each element in the output tensor is a string of concatenated\\nelements corresponding to each row in the input tensor. For 1-D input, each\\nelement is treated as a row.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Delimiter for join (Default: \\\",\\\").\",\n        \"name\": \"delimiter\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Axis for the join (either 0 or 1)\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1-D or 2-D tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor of strings created by joining row elements from the input tensor.\",\n        \"name\": \"strings\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringPrefix\",\n    \"description\": \"\\nComputes the element-wise string prefix of the string tensor.\\nInput strings that are shorter than prefix length will be returned unchanged.\\nNOTE: Prefix is computed on number of bytes, which may lead to wrong behavior\\nand potentially invalid strings for variable-length encodings such as utf-8.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Maximum size of the prefix, in bytes.\",\n        \"name\": \"length\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of std::string.\",\n        \"name\": \"strings\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of std::string containing prefixes for each input.\",\n        \"name\": \"prefixes\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringStartsWith\",\n    \"description\": \"\\nPerforms the starts-with check on each string in the input tensor.\\nReturns tensor of boolean of the same dimension of input.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"The prefix to check input strings against.\",\n        \"name\": \"prefix\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of std::string.\",\n        \"name\": \"strings\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of bools of same shape as input.\",\n        \"name\": \"bools\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StringSuffix\",\n    \"description\": \"\\nComputes the element-wise string suffix of the string tensor.\\nInput strings that are shorter than suffix length will be returned unchanged.\\nNOTE: Prefix is computed on number of bytes, which may lead to wrong behavior\\nand potentially invalid strings for variable-length encodings such as utf-8.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Maximum size of the suffix, in bytes.\",\n        \"name\": \"length\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor of std::string.\",\n        \"name\": \"strings\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Tensor of std::string containing suffixes for each output.\",\n        \"name\": \"suffixes\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StumpFunc\",\n    \"description\": \"\\nConverts each input element into either high_ or low_value\\nbased on the given threshold.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"tensor of float\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"tensor of float\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"StumpFuncIndex\",\n    \"description\": \"\\nSplit the elements and return the indices based on the given threshold.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"tensor of float\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"tensor of int64 indices for elements below/equal threshold\",\n        \"name\": \"Index_Low\"\n      },\n      {\n        \"description\": \"tensor of int64 indices for elements above threshold\",\n        \"name\": \"Index_High\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sub\",\n    \"description\": \"\\nPerforms element-wise binary subtraction (with limited broadcast support).\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sub\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([[10,12],[4,14]]))\\nworkspace.FeedBlob(\\\"B\\\", np.array([[5,16],[1,19]]))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[10 12]\\n [ 4 14]]\\nB:\\n[[ 5 16]\\n [ 1 19]]\\nC:\\n[[ 5 -4]\\n [ 3 -5]]\\n\\n```\\n\\n</details>\\n\\n\\n\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Second operand. With broadcasting can be of smaller size than A. If broadcasting is disabled it should be of the same size as A.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Output tensor with same dimensions and type as A.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SubGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sum\",\n    \"description\": \"\\nElement-wise sum of each of the input tensors. The first input tensor can be used\\nin-place as the output tensor, in which case the sum will be done in place and\\nresults will be accumulated the first input tensor. All inputs and outputs must\\nhave the same shape and data type.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_sum_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sum\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([[1,2],[3,4]]).astype(np.float32))\\nworkspace.FeedBlob(\\\"B\\\", np.array([[5,6],[7,8]]).astype(np.float32))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"A\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA: [[1. 2.]\\n [3. 4.]]\\nB: [[5. 6.]\\n [7. 8.]]\\nC: [[1. 2.]\\n [3. 4.]]\\n\\n```\\n\\n</details>\\n\\n<details>\\n\\n<summary> <b>Example 2</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Sum\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"A\\\"],  // inplace\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", np.array([[1,2,5],[8,3,4]]).astype(np.float32))\\nworkspace.FeedBlob(\\\"B\\\", np.array([[9,5,6],[6,7,8]]).astype(np.float32))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"A after Sum:\\\", workspace.FetchBlob(\\\"A\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA: [[1. 2. 5.]\\n [8. 3. 4.]]\\nB: [[9. 5. 6.]\\n [6. 7. 8.]]\\nA after Sum: [[10.  7. 11.]\\n [14. 10. 12.]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* First tensor to be added element-wise.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Second tensor to be added element-wise.\",\n        \"name\": \"B\"\n      },\n      {\n        \"description\": \"First of the input tensors. Can be inplace.\",\n        \"name\": \"data_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<float>`)* Sum of A and B.\",\n        \"name\": \"C\"\n      },\n      {\n        \"description\": \"Output tensor. Same dimension as inputs.\",\n        \"name\": \"sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumElements\",\n    \"description\": \"\\nSums the elements of the input tensor. Tensor type must be float32.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduction_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nsum_op = core.CreateOperator(\\n    \\\"SumElements\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\navg_op = core.CreateOperator(\\n    \\\"SumElements\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    average=True\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(3,3)).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(sum_op)\\nprint(\\\"Y (sum_op):\\\", workspace.FetchBlob(\\\"Y\\\"))\\nworkspace.RunOperatorOnce(avg_op)\\nprint(\\\"Y (avg_op):\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[7. 2. 5.]\\n [9. 4. 2.]\\n [1. 2. 5.]]\\nY (sum_op): 37.0\\nY (avg_op): 4.111111\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"(*bool*): set to True to compute the average of the elements rather than the sum\",\n        \"name\": \"average\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): blob pointing to an instance of a counter\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): Scalar tensor containing the sum (or average)\",\n        \"name\": \"sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumElementsGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumElementsInt\",\n    \"description\": \"Sums the integer elements of the input tensor.\",\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to sum up\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Scalar sum\",\n        \"name\": \"sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumInt\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Summarize\",\n    \"description\": \"\\nSummarize computes four statistics of the input tensor (Tensor)- min,\\nmax, mean and standard deviation. The output will be written to a 1-D tensor of\\nsize 4 if an output tensor is provided. Else, if the argument 'to_file' is\\ngreater than 0, the values are written to a log file in the root folder.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) flag to indicate if the summarized statistics have to be written to a log file.\",\n        \"name\": \"to_file\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The input data as Tensor.\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1-D tensor (Tensor) of size 4 containing min, max, mean and standard deviation\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumReduceLike\",\n    \"description\": \"\\nSumReduceLike operator takes 2 tensors as input. It performs reduce sum to the\\nfirst input so that the output looks like the second one.\\nIt assumes that the first input\\nhas more dimensions than the second, and the dimensions of the second input is\\nthe contiguous subset of the dimensions of the first.\\nFor example, the following tensor shapes are supported:\\n\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 2, 5), shape(B) = (2), with axis=0\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"If set, defines the starting dimension for reduction. Args `axis` and `axis_str` cannot be used simultaneously.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"If set, it could only be N or C or H or W. `order` arg should also be provided. It defines the reduction dimensions on NCHW or NHWC. Args `axis` and `axis_str` cannot be used simultaneously.\",\n        \"name\": \"axis_str\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Either NHWC or HCWH\",\n        \"name\": \"order\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"First operand, should share the type with the second operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"Second operand. With broadcasting can be of smaller size than A. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Result, has same dimensions and type as B\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumRelu\",\n    \"inputs\": [\n      {\n        \"description\": \"First of the input tensors. Can be inplace.\",\n        \"name\": \"data_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor. Same dimension as inputs.\",\n        \"name\": \"sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SumSqrElements\",\n    \"description\": \"Sums the squares elements of the input tensor.\",\n    \"attributes\": [\n      {\n        \"description\": \"whether to average or not\",\n        \"name\": \"average\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Tensor to sum up\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Scalar sum of squares\",\n        \"name\": \"sum\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SwapBestPath\",\n    \"description\": \"\\nGiven a sequence of indices and a matrix, enforce that these indices have the\\nbest columnwise scores\\nscore\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"N*D predictions matrix\",\n        \"name\": \"predictions\"\n      },\n      {\n        \"description\": \"N*1 vector holds the best path indices \",\n        \"name\": \"bestPath\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"N*D updated predictions matrix\",\n        \"name\": \"new_predictions\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Swish\",\n    \"description\": \"\\nSwish takes one input data (Tensor) and produces one output data\\n(Tensor) where the swish function, y = x / (1 + exp(-x)), is applied to the\\ntensor elementwise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SwishGradient\",\n    \"description\": \"\\nSwishGradient takes X, Y and dY and uses this to update dX according to the\\nchain rule and derivatives of the swish function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Tan\",\n    \"description\": \"\\nCalculates the tangent of the given input tensor, element-wise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The tangent of the input tensor computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Tanh\",\n    \"description\": \"\\nCalculates the hyperbolic tangent of the given input tensor element-wise. This\\noperation can be done in an in-place fashion too, by providing the same input\\nand output blobs.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/tanh_op.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Tanh\\\",\\n    [\\\"X\\\"],\\n    [\\\"X\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randn(3, 3).astype(np.float32))\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"), \\\"\\\\n\\\")\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"X:\\\\n\\\", workspace.FetchBlob(\\\"X\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n [[ 2.032603   -2.3556721  -0.14955314]\\n [ 0.39309832 -1.1020128  -0.92951244]\\n [-0.62815386  0.21342885  1.4002231 ]]\\n\\nX:\\n [[ 0.9662601  -0.982175   -0.14844811]\\n [ 0.3740282  -0.8012209  -0.73036647]\\n [-0.55677974  0.21024609  0.8853999 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1-D input tensor\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The hyperbolic tangent values of the input tensor, computed element-wise\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TanhGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TensorProtosDBInput\",\n    \"description\": \"\\nTensorProtosDBInput is a simple input operator that basically reads things\\nfrom a db where each key-value pair stores an index as key, and a TensorProtos\\nobject as value. These TensorProtos objects should have the same size, and they\\nwill be grouped into batches of the given size. The DB Reader is provided as\\ninput to the operator and it returns as many output tensors as the size of the\\nTensorProtos object. Each output will simply be a tensor containing a batch of\\ndata with size specified by the 'batch_size' argument containing data from the\\ncorresponding index in the TensorProtos objects in the DB.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int, default 0) the number of samples in a batch. The default value of 0 means that the operator will attempt to insert the entire data in a single output blob.\",\n        \"name\": \"batch_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"A pre-initialized DB reader. Typically, this is obtained by calling CreateDB operator with a db_name and a db_type. The resulting output blob is a DB Reader tensor\",\n        \"name\": \"data\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor in which the batches of data are returned. The number of output tensors is equal to the size of (number of TensorProto's in) the TensorProtos objects stored in the DB as values. Each output tensor will be of size specified by the 'batch_size' argument of the operator\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TensorVectorSize\",\n    \"description\": \"Get the size of the input vector\",\n    \"inputs\": [\n      {\n        \"description\": \"std::unique_ptr<std::vector<Tensor> >\",\n        \"name\": \"tensor vector\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"int32_t size\",\n        \"name\": \"size\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TextFileReaderRead\",\n    \"description\": \"Read a batch of rows from the given text file reader instance. Expects the number of fields to be equal to the number of outputs. Each output is a 1D tensor containing the values for the given field for each row. When end of file is reached, returns empty tensors.\",\n    \"attributes\": [\n      {\n        \"description\": \"Maximum number of rows to read.\",\n        \"name\": \"batch_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Pointer to an existing TextFileReaderInstance.\",\n        \"name\": \"handler\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ThresholdedRelu\",\n    \"description\": \"\\nThresholdedRelu takes one input data (Tensor) and produces one output data\\n(Tensor) where the rectified linear function, y = x for x > alpha, y = 0\\notherwise, is applied to the tensor elementwise.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(float) defaults to 1.0.\",\n        \"name\": \"alpha\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ThresholdedReluGradient\",\n    \"description\": \"\\nThresholdedReluGradient takes both Y and dY and uses this to update dX\\naccording to the chain rule and derivatives of the rectified linear function.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ThrowChildThreadException\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ThrowException\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Tile\",\n    \"description\": \"\\nConstructs a tensor by tiling a given tensor along a specified axis. This operation creates a new tensor by replicating the input tensor a number of times specified by the `tiles` argument along the `axis` dimension. The output tensor's `axis` dimension has $(X.dims(axis) * tiles)$ elements.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/tile_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Tile\\\",\\n    [\\\"X\\\", \\\"tiles\\\", \\\"axis\\\"],\\n    [\\\"Y\\\"]\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(5,5)))\\nworkspace.FeedBlob(\\\"tiles\\\", np.array([5]).astype(np.int32))\\nworkspace.FeedBlob(\\\"axis\\\", np.array([1]).astype(np.int32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[9 1 7 1 3]\\n [2 3 6 2 5]\\n [0 9 2 6 4]\\n [5 8 1 5 9]\\n [2 0 1 3 7]]\\nY:\\n[[9 1 7 1 3 9 1 7 1 3 9 1 7 1 3 9 1 7 1 3 9 1 7 1 3]\\n [2 3 6 2 5 2 3 6 2 5 2 3 6 2 5 2 3 6 2 5 2 3 6 2 5]\\n [0 9 2 6 4 0 9 2 6 4 0 9 2 6 4 0 9 2 6 4 0 9 2 6 4]\\n [5 8 1 5 9 5 8 1 5 9 5 8 1 5 9 5 8 1 5 9 5 8 1 5 9]\\n [2 0 1 3 7 2 0 1 3 7 2 0 1 3 7 2 0 1 3 7 2 0 1 3 7]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): number of replicas\",\n        \"name\": \"tiles\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): axis to replicate along\",\n        \"name\": \"axis\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor*): input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): [OPTIONAL] number of replicas (overrides `tiles` argument)\",\n        \"name\": \"tiles\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): [OPTIONAL] axis to replicate along (overrides `axis` argument)\",\n        \"name\": \"axis\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor*): output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TileGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TimerBegin\",\n    \"description\": \"\\nStart a wallclock timer, returning a scalar tensor containing a pointer to it. The timer is stopped by calling **TimerEnd**.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_ops.cc\\n\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"(*str*): name of the timer object; if not set use output name\",\n        \"name\": \"counter_name\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<ptr>`*): pointer to a timer object\",\n        \"name\": \"timer\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TimerEnd\",\n    \"description\": \"\\nStop a timer started with **TimerBegin**. Publishes a CAFFE_EVENT.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_ops.cc\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<ptr>`*): pointer to a timer object; obtained from **TimerBegin** op\",\n        \"name\": \"timer\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TimerGet\",\n    \"description\": \"\\nQueries the current time of a timer object in nanoseconds.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_ops.cc\\n\\n    \",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<ptr>`*): pointer to a timer object; obtained from **TimerBegin** op\",\n        \"name\": \"timer\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<int64>`*): scalar containing time in nanoseconds\",\n        \"name\": \"nanos\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TimerGetAndEnd\",\n    \"description\": \"\\nQueries the current time of a timer in nanos, stops the timer publishing a CAFFE_EVENT.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/stats_ops.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\ntimerbegin_op = core.CreateOperator(\\n    \\\"TimerBegin\\\",\\n    [],\\n    [\\\"timer\\\"]\\n)\\n\\ntimerget_op = core.CreateOperator(\\n    \\\"TimerGet\\\",\\n    [\\\"timer\\\"],\\n    [\\\"nanos\\\"]\\n)\\n\\ntimerend_op = core.CreateOperator(\\n    \\\"TimerEnd\\\",\\n    [\\\"timer\\\"],\\n    []\\n)\\n\\ntimergetandend_op = core.CreateOperator(\\n    \\\"TimerGetAndEnd\\\",\\n    [\\\"timer\\\"],\\n    [\\\"nanos\\\"]\\n)\\n\\n// Test TimerBegin/TimerGet/TimerEnd\\nworkspace.RunOperatorOnce(timerbegin_op)\\nprint(\\\"timer:\\\", workspace.FetchBlob(\\\"timer\\\"))\\nworkspace.RunOperatorOnce(timerget_op)\\nprint(\\\"nanos:\\\", workspace.FetchBlob(\\\"nanos\\\"))\\nworkspace.RunOperatorOnce(timerend_op)\\n\\n\\n// Test TimerBegin/TimerGetAndEnd\\nworkspace.RunOperatorOnce(timerbegin_op)\\nprint(\\\"timer:\\\", workspace.FetchBlob(\\\"timer\\\"))\\nworkspace.RunOperatorOnce(timergetandend_op)\\nprint(\\\"nanos:\\\", workspace.FetchBlob(\\\"nanos\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\ntimer: b'timer, a C++ native class of type caffe2::TimerInstance*.'\\nnanos: 361140\\ntimer: b'timer, a C++ native class of type caffe2::TimerInstance*.'\\nnanos: [252250]\\n\\n```\\n\\n</details>\\n\\n      \",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<ptr>`*): pointer to a timer object; obtained from **TimerBegin** op\",\n        \"name\": \"timer\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<int64>`*): scalar tensor containing time in nanoseconds\",\n        \"name\": \"nanos\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TopK\",\n    \"description\": \"\\nRetrieve the top-K elements of the last dimension.\\nGiven an input tensor of shape $(a_1, a_2, ..., a_n, r)$. `k` can be passed as an integer argument or a 1D tensor containing a single integer.\\nReturns up to three outputs:\\n\\n1. Value tensor of shape $(a_1, a_2, ..., a_n, k)$ which contains the values of the top k elements along the last dimension\\n2. Index tensor of shape $(a_1, a_2, ..., a_n, k)$ which contains the indices of the top k elements (original indices from the input tensor).\\n3. [OPTIONAL] Flattened index tensor of shape $(a_1 * a_2 * ... * a_n * k,)$.\\n\\nGiven two equivalent values, this operator uses the indices along the last dimension as a tiebreaker. That is, the element with the lower index will appear first.\\n\\nGithub Links:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/top_k.cc\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"TopK\\\",\\n    [\\\"X\\\"],\\n    [\\\"Values\\\", \\\"Indices\\\", \\\"Flattened_indices\\\"],\\n    k=2\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.random.randint(10, size=(3,3,3)).astype(np.float32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Values:\\\", workspace.FetchBlob(\\\"Values\\\"))\\nprint(\\\"Indices:\\\", workspace.FetchBlob(\\\"Indices\\\"))\\nprint(\\\"Flattened_indices:\\\", workspace.FetchBlob(\\\"Flattened_indices\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nX:\\n[[[6. 7. 0.]\\n  [8. 7. 7.]\\n  [1. 5. 6.]]\\n\\n [[0. 6. 1.]\\n  [2. 8. 4.]\\n  [1. 2. 9.]]\\n\\n [[4. 3. 7.]\\n  [0. 1. 7.]\\n  [0. 1. 8.]]]\\nValues:\\n[[[7. 6.]\\n  [8. 7.]\\n  [6. 5.]]\\n\\n [[6. 1.]\\n  [8. 4.]\\n  [9. 2.]]\\n\\n [[7. 4.]\\n  [7. 1.]\\n  [8. 1.]]]\\nIndices:\\n[[[1 0]\\n  [0 1]\\n  [2 1]]\\n\\n [[1 2]\\n  [1 2]\\n  [2 1]]\\n\\n [[2 0]\\n  [2 1]\\n  [2 1]]]\\nFlattened_indices: [ 1  0  3  4  8  7 10 11 13 14 17 16 20 18 23 22 26 25]\\n\\n```\\n\\n</details>\\n\\n  \",\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): input tensor of shape $(a_1, a_2, ..., a_n, r)$\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"(*int*): number of top elements to retrieve\",\n        \"name\": \"k\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): output tensor of shape $(a_1, a_2, ..., a_n, k)$\",\n        \"name\": \"Values\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): tensor of indices of shape $(a_1, a_2, ..., a_n, k)$; indices values refer to each element's index in the last dimension of the `X` input tensor\",\n        \"name\": \"Indices\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): tensor of indices of shape $(a_1 * a_2 * ... * a_n * k,)$; indices values refer to each element's index in the flattened input tensor `X`\",\n        \"name\": \"Flattened_indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TopKGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Transpose\",\n    \"category\": \"Transform\",\n    \"description\": \"\\nTranspose the input tensor by permuting the axes of the input according\\nto the `axes` argument. Similar to numpy's\\n[transpose](https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html)\\nfunction.\\n\\nFor example, when axes=(1, 0, 2), given an input tensor of shape\\n(1, 2, 3), the output shape will be (2, 1, 3).\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/transpose_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Transpose\\\",\\n    [\\\"X\\\"],\\n    [\\\"Y\\\"],\\n    axes=(0,3,1,2)\\n)\\n\\nx = np.random.rand(1,32,32,3)\\nworkspace.FeedBlob(\\\"X\\\", x)\\nprint(\\\"X.shape (NHWC order):\\\", workspace.FetchBlob(\\\"X\\\").shape)\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y.shape (NCHW order):\\\", workspace.FetchBlob(\\\"Y\\\").shape)\\n```\\n\\n**Result**\\n\\n```\\nX.shape (NHWC order): (1, 32, 32, 3)\\nY.shape (NCHW order): (1, 3, 32, 32)\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Order to permute axes of input tensor. Reverses the dimensions by default.\",\n        \"name\": \"axes\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Input tensor.\",\n        \"name\": \"X\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor)* Transposed output.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TrimDataset\",\n    \"description\": \"\\nTrim the given dataset inplace, given the dataset blobs and the field specs.\\nTrimming happens such that the dataset will contain the largest possible number\\nof records that is a multiple of the 'multiple_of' argument.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of strings representing the string names in the formatspecified in the doc for CreateTreeCursor.\",\n        \"name\": \"fields\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TT\",\n    \"description\": \"\\nThe TT-layer serves as a low-rank decomposition of a fully connected layer. The\\ninputs are the same as to a fully connected layer, but the number of parameters\\nare greatly reduced and forward computation time can be drastically reduced\\nespecially for layers with large weight matrices. The multiplication is computed\\nas a product of the input vector with each of the cores that make up the TT\\nlayer. Given the input sizes (inp_sizes), output sizes(out_sizes), and the ranks\\nof each of the cores (tt_ranks), the ith core will have size:\\n\\n    inp_sizes[i] * tt_ranks[i] * tt_ranks[i + 1] * out_sizes[i].\\n\\nThe complexity of the computation is dictated by the sizes of inp_sizes,\\nout_sizes, and tt_ranks, where there is the trade off between accuracy of the\\nlow-rank decomposition and the speed of the computation.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(int[]) Input sizes of cores. Indicates the input size of the individual cores; the size of the input vector X must match the product of the inp_sizes array.\",\n        \"name\": \"inp_sizes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int[]) Output sizes of cores. Indicates the output size of the individual cores; the size of the output vector Y must match the product of the out_sizes array.\",\n        \"name\": \"out_sizes\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(int[]) Ranks of cores. Indicates the ranks of the individual cores; lower rank means larger compression, faster computation but reduce accuracy.\",\n        \"name\": \"tt_ranks\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor from previous layer with size (M x K), where M is the batch size and K is the input size.\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D blob containing the bias vector\",\n        \"name\": \"b\"\n      },\n      {\n        \"description\": \"1D blob containing each individual cores with sizes specified above.\",\n        \"name\": \"cores\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor from previous layer with size (M x N), where M is the batch size and N is the output size.\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TTLinearGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TTSparseLengthsSum\",\n    \"description\": \"\\nThis operator introduce a new, parameter efficient embedding layer, termed TT embedding, which\\ncan be plugged in into any model and trained end-to-end. The benefits of our compressed TT layer\\nare twofold. Firstly, instead of storing huge embedding matrix, it stores a sequence of much smaller\\n2-dimensional and 3-dimensional tensors, necessary for reconstructing the required embeddings,\\nwhich allows compressing the model significantly at the cost of a negligible performance drop.\\nSecondly, the overall number of parameters can be relatively small (and constant) during the whole\\ntraining stage, which allows to use larger batches or train efficiently in a case of limited resources.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"vector<int>: factorization of voc size\",\n        \"name\": \"factor_i\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"vector<int>: factorization of emb size\",\n        \"name\": \"factor_j\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int[] Ranks of cores\",\n        \"name\": \"ranks\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"int: the size of each embedding entry\",\n        \"name\": \"emb_size\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"tensor core 0\",\n        \"name\": \"core0\"\n      },\n      {\n        \"description\": \"tensor core 1\",\n        \"name\": \"core1\"\n      },\n      {\n        \"description\": \"tensor core 2\",\n        \"name\": \"core2\"\n      },\n      {\n        \"description\": \"index for embedding\",\n        \"name\": \"index\"\n      },\n      {\n        \"description\": \"segment lengths\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated tensor\",\n        \"name\": \"OUTPUT\"\n      },\n      {\n        \"description\": \"intermediate mm result from core0 for backward path\",\n        \"name\": \"core0_output\"\n      },\n      {\n        \"description\": \"intermediate mm result from core1 for backward path\",\n        \"name\": \"core1_output\"\n      },\n      {\n        \"description\": \"the index for each core\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"TTSparseLengthsSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UniformFill\",\n    \"description\": \"\\nFill the output tensor with float samples from uniform distribution [`min`, `max`].\\n\\n- The range can be defined either by arguments or input blobs. `min` and `max` are inclusive.\\n    - If the range is given by input blobs, you also need to give the shape as input.\\n    - When the range is given as arguments, this operator enforces min <= max. When the range is given as inputs, the constraint is not enforced.\\n    - When the range is given as inputs and max < min, the first dimension of the output is set to 0. This behavior is allowed so that dynamically sampling indices into a dynamically sized tensor is possible.\\n- The shape of the output can be given as argument or input.\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop_1 = core.CreateOperator(\\n    \\\"UniformFill\\\",\\n    [],\\n    [\\\"output\\\"],\\n    min=5.5,\\n    max=10.5,\\n    shape=(3,3)\\n)\\n\\nop_2 = core.CreateOperator(\\n    \\\"UniformFill\\\",\\n    [\\\"shape\\\", \\\"min\\\", \\\"max\\\"],\\n    [\\\"output\\\"],\\n    input_as_shape=1\\n)\\n\\n// Test arg-based op\\nworkspace.RunOperatorOnce(op_1)\\nprint(\\\"output (op_1):\\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n// Test input-based op\\nworkspace.ResetWorkspace()\\nworkspace.FeedBlob(\\\"shape\\\", np.array([5,5]))\\nworkspace.FeedBlob(\\\"min\\\", np.array(13.8, dtype=np.float32))\\nworkspace.FeedBlob(\\\"max\\\", np.array(19.3, dtype=np.float32))\\nworkspace.RunOperatorOnce(op_2)\\nprint(\\\"output (op_2):\\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\noutput (op_1):\\n [[8.894862  8.225005  6.7890406]\\n [9.588293  7.1072135 7.7234955]\\n [8.210596  6.0202913 9.665462 ]]\\noutput (op_2):\\n [[18.965155 15.603871 15.038921 17.14872  18.134571]\\n [18.84237  17.845276 19.214737 16.970337 15.494069]\\n [18.754795 16.724329 15.311974 16.962536 18.60965 ]\\n [15.186268 15.264773 18.73341  19.077969 14.237255]\\n [15.917589 15.844325 16.248466 17.006554 17.502048]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"(*float*): minimum value, inclusive\",\n        \"name\": \"min\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*float*): maximum value, inclusive\",\n        \"name\": \"max\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*Tuple(int)*): shape of the output, do not set when `input_as_shape`=1\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): set to 1 to use the first input as shape; `shape` input must be in CPU context\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<int>`*): 1-D tensor of the shape of the output, must be used with `input_as_shape` argument\",\n        \"name\": \"shape\"\n      },\n      {\n        \"description\": \"(*Tensor`<float>`*): scalar tensor containing minimum value, inclusive\",\n        \"name\": \"min\"\n      },\n      {\n        \"description\": \"(*Tensor`<float>`*): scalar tensor containing maximum value, inclusive\",\n        \"name\": \"max\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<float>`*): filled output tensor\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UniformIntFill\",\n    \"description\": \"\\nFill the output tensor with int32 samples from uniform distribution [`min`, `max`].\\n\\n- The range can be defined either by arguments or input blobs. `min` and `max` are inclusive.\\n    - If the range is given by input blobs, you also need to give the shape as input.\\n    - When the range is given as arguments, this operator enforces min <= max. When the range is given as inputs, the constraint is not enforced.\\n    - When the range is given as inputs and max < min, the first dimension of the output is set to 0. This behavior is allowed so that dynamically sampling indices into a dynamically sized tensor is possible.\\n- The shape of the output can be given as argument or input.\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop_1 = core.CreateOperator(\\n    \\\"UniformIntFill\\\",\\n    [],\\n    [\\\"output\\\"],\\n    min=5,\\n    max=10,\\n    shape=(3,3)\\n)\\n\\nop_2 = core.CreateOperator(\\n    \\\"UniformIntFill\\\",\\n    [\\\"shape\\\", \\\"min\\\", \\\"max\\\"],\\n    [\\\"output\\\"],\\n    input_as_shape=1\\n)\\n\\n// Test arg-based op\\nworkspace.RunOperatorOnce(op_1)\\nprint(\\\"output (op_1):\\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n// Test input-based op\\nworkspace.ResetWorkspace()\\nworkspace.FeedBlob(\\\"shape\\\", np.array([5,5]))\\nworkspace.FeedBlob(\\\"min\\\", np.array(13, dtype=np.int32))\\nworkspace.FeedBlob(\\\"max\\\", np.array(19, dtype=np.int32))\\nworkspace.RunOperatorOnce(op_2)\\nprint(\\\"output (op_2):\\\\n\\\", workspace.FetchBlob(\\\"output\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\noutput (op_1):\\n [[ 6 10  7]\\n [ 5 10  6]\\n [ 7  5 10]]\\noutput (op_2):\\n [[19 13 15 13 13]\\n [14 17 14 15 15]\\n [17 14 19 13 13]\\n [17 18 16 13 18]\\n [14 15 16 18 16]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"(*int*): minimum value, inclusive\",\n        \"name\": \"min\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): maximum value, inclusive\",\n        \"name\": \"max\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*Tuple(int)*): shape of the output, do not set when `input_as_shape`=1\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"(*int*): set to 1 to use the first input as shape; `shape` input must be in CPU context\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(*Tensor`<int>`*): 1-D tensor of the shape of the output, must be used with `input_as_shape` argument\",\n        \"name\": \"shape\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): scalar tensor containing minimum value, inclusive\",\n        \"name\": \"min\"\n      },\n      {\n        \"description\": \"(*Tensor`<int>`*): scalar tensor containing maximum value, inclusive\",\n        \"name\": \"max\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"(*Tensor`<int>`*): filled output tensor\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Unique\",\n    \"description\": \"\\nDeduplicates input indices vector and optionally produces reverse remapping.\\nThere's no guarantees on the ordering of the output indices.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"1D tensor of int32 or int64 indices.\",\n        \"name\": \"indices\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"1D tensor of deduped entries.\",\n        \"name\": \"unique_indices\"\n      },\n      {\n        \"description\": \"(optional) mapping from `indices` to `unique_indices`. This has the same shape as `indices`. Its elements are the indices into `unique_indices` such that `Gather(['unique_indices', 'remapping'])` yields `indices`.\",\n        \"name\": \"remapping\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UniqueUniformFill\",\n    \"description\": \"\\nFill the output tensor with uniform samples between min and max (inclusive).\\nIf the second input is given, its elements will be excluded from uniform\\nsampling. Using the second input will require you to provide shape via the first\\ninput.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Minimum value, inclusive\",\n        \"name\": \"min\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Maximum value, inclusive\",\n        \"name\": \"max\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The data type for the elements of the output tensor.Strictly must be one of the types from DataType enum in TensorProto.This only supports INT32 and INT64 now. If not set, assume INT32\",\n        \"name\": \"dtype\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The shape of the output tensor.Cannot set the shape argument and pass in an input at the same time.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the shape indicatedby the input blob. Cannot set the extra_shape argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"1D tensor containing the desired output shape. First input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor to provide shape information\",\n        \"name\": \"input\"\n      },\n      {\n        \"description\": \"(optional) Avoid elements in this tensor. Elements must be unique.\",\n        \"name\": \"avoid\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of unique uniform samples\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnPackRecords\",\n    \"description\": \"\\nGiven a packed dataset (packed by the PackRecordsOp) and the `fields` argument\\ndescribing the datasets schema, return the original dataset format. Number of\\nreturned tensors is equal to the number of fields in the `fields` argument.\\n\\nThe first input is the packed tensor to be unpacked. Optionally, you can provide\\nprototype tensors to give the expected shapes of the output tensors. This is\\nhelpful when you expected to unpack empty tensor, e.g., output of a sampling\\nprocess.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"List of strings representing the string names in the formatspecified in the doc for CreateTreeCursor.\",\n        \"name\": \"fields\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"The tensor to be unpacked\",\n        \"name\": \"packed_tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnpackRNNSequence\",\n    \"description\": \"\\nThis is the reverse operator for PackRNNSequence. It maps the packed values\\nback to sequence values based on the length blob. Each number from length blob\\nrepresents the corresponding values that has been grouped. The dimension\\nfor each pack is the same as the maximum number from the length blob (padding\\nwith zero was implemented for smaller length value). The overall output\\ndimension is: M * D, where M is the sum of lengths, and D is the dimension of\\neach feature value. The following example shows the input and output of\\nthis operator:\\n\\n\\nGiven:\\n  values = [\\n    [v1, v3, v6, v7],\\n    [v2, v4, 0,  v8],\\n    [0,  v5, 0,  0 ],\\n  ]\\n  lengths = [2, 3, 1, 2]\\n\\n\\nOutput:\\n  output = [v1, v2, v3, v4, v5, v6, v7, v8];\\n\\n\\nOne application for this operator is the transfer data from the format of RNN\\nback to sequence values. Note that the gradient operator of\\nUnpackRNNSequence is PackRNNSequence.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Data tensor, contains the packed features\",\n        \"name\": \"values\"\n      },\n      {\n        \"description\": \"lengths with each number representing the pack size.\",\n        \"name\": \"lengths\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor before packing\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnpackSegments\",\n    \"description\": \"Map N+1 dim tensor to N dim based on length blob\",\n    \"attributes\": [\n      {\n        \"description\": \"The pre-defined max_length for the packed segments\",\n        \"name\": \"max_length\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"1-d int/long tensor contains the length in each of the input.\",\n        \"name\": \"lengths\"\n      },\n      {\n        \"description\": \"N+1 dim Tensor.\",\n        \"name\": \"tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"N dim Tensor\",\n        \"name\": \"packed_tensor\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsafeCoalesce\",\n    \"description\": \"\\nCoalesce the N inputs into N outputs and a single coalesced output blob.\\nThis allows operations that operate over multiple small kernels (e.g.\\nbiases in a deep CNN) to be coalesced into a single larger operation,\\namortizing the kernel launch overhead, synchronization costs for\\ndistributed computation, etc.\\nThe operator:\\n- computes the total size of the coalesced blob by summing the input sizes\\n- allocates the coalesced output blob as the total size\\n- copies the input vectors into the coalesced blob, at the correct offset.\\n- aliases each Output(i) to- point into the coalesced blob, at the corresponding offset for Input(i).\\nThis is 'unsafe' as the output vectors are aliased, so use with\\ncaution.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsortedSegmentMean\",\n    \"description\": \"\\nApplies 'Mean' to each segment of input tensor. Segments ids can appear in\\narbitrary order (unlike in SortedSegmentMean).\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nIf `num_segments` argument is passed it would be used as a first dimension for\\nthe output. Otherwise, it'd be dynamically calculated from as the max value of\\nSEGMENT_IDS plus one. Other output dimensions are inherited from the input\\ntensor.\\n\\nMean computes the element-wise mean of the input slices. Operation doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Optional int argument specifying the number of output segments and thus the first dimension of the output\",\n        \"name\": \"num_segments\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector with the same length as the first dimension of DATA that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of equal to the number of segments.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsortedSegmentMeanGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsortedSegmentSum\",\n    \"description\": \"\\nApplies 'Sum' to each segment of input tensor. Segments ids can appear in\\narbitrary order (unlike in SortedSegmentSum).\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nIf `num_segments` argument is passed it would be used as a first dimension for\\nthe output. Otherwise, it'd be dynamically calculated from as the max value of\\nSEGMENT_IDS plus one. Other output dimensions are inherited from the input\\ntensor.\\n\\nSummation is done element-wise across slices of the input tensor and doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Optional int argument specifying the number of output segments and thus the first dimension of the output\",\n        \"name\": \"num_segments\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor, slices of which are aggregated.\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Integer vector with the same length as the first dimension of DATA that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of equal to the number of segments.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsortedSegmentSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsortedSegmentWeightedSum\",\n    \"description\": \"\\nApplies 'WeightedSum' to each segment of input tensor. Segments ids can appear in\\narbitrary order (unlike in SortedSegmentWeightedSum).\\n\\nSEGMENT_IDS is a vector that maps each of the first dimension slices of the\\nDATA to a particular group (segment). Values belonging to the same segment are\\naggregated together.\\n\\nIf `num_segments` argument is passed it would be used as a first dimension for\\nthe output. Otherwise, it'd be dynamically calculated from as the max value of\\nSEGMENT_IDS plus one. Other output dimensions are inherited from the input\\ntensor.\\n\\nInput slices are first scaled by SCALARS and then summed element-wise. It doesn't change the shape of the individual blocks.\\n  \",\n    \"attributes\": [\n      {\n        \"description\": \"Optional int argument specifying the number of output segments and thus the first dimension of the output\",\n        \"name\": \"num_segments\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Produce also gradient for `weights`. For now it's only supported in `Lengths`-based operators\",\n        \"name\": \"grad_on_weights\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor for the summation\",\n        \"name\": \"DATA\"\n      },\n      {\n        \"description\": \"Scalar multipliers for the input slices. Must be a vector with the length matching the number of slices\",\n        \"name\": \"SCALARS\"\n      },\n      {\n        \"description\": \"Integer vector with the same length as the first dimension of DATA that maps each slice of DATA to one of the segments\",\n        \"name\": \"SEGMENT_IDS\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Aggregated output tensor. Has the first dimension of equal to the number of segments.\",\n        \"name\": \"OUTPUT\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UnsortedSegmentWeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UpsampleBilinear\",\n    \"description\": \"\\nResizes the spatial dimensions of the input using bilinear\\ninterpolation. The `width_scale` and `height_scale` arguments\\ncontrol the size of the output, which is given by:\\noutput_width = floor(input_width * width_scale)\\noutput_height = floor(output_height * height_scale)\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"1D, 2-element, Scales tensor, [height_scale, width_scale]\",\n        \"name\": \"scales\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"UpsampleBilinearGradient\",\n    \"attributes\": [\n      {\n        \"description\": \"Scale along width dimension\",\n        \"name\": \"width_scale\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Scale along height dimension\",\n        \"name\": \"height_scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"VariableLengthSequencePadding\",\n    \"description\": \"\\nSuper special-case operator. Used to pad a tensor to mimic pytorch's\\npad_packed_sequence.\\n\\nGiven an input tensor INPUT of size NxBxM and an input tensor LENS\\nof size B, where\\n\\nN = maximum sequence length\\nB = batch size\\nM = hidden size\\n\\nset each element of INPUT to zero if it is is past the end of the\\ncorresponding sequence (i.e. if LENS[j] > i for an index (i,j,k)).\\n\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ViterbiPath\",\n    \"description\": \"\\nGiven a predictions matrix and a transitions matrix, get the path with the best\\nscore\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"N*D predictions matrix\",\n        \"name\": \"predictions\"\n      },\n      {\n        \"description\": \"D*D transitions matrix\",\n        \"name\": \"transitions\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"N*1 vector holds the best path indices\",\n        \"name\": \"viterbi_path\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WallClockTime\",\n    \"description\": \"Time since epoch in nanoseconds.\",\n    \"outputs\": [\n      {\n        \"description\": \"The time in nanoseconds.\",\n        \"name\": \"time\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedMultiSampling\",\n    \"description\": \"\\nThe operator performs sampling based on the input sampling weights.\\nAll weights are cummulative probability thus sorted. The output is\\na 1-D tensor (Tensor). If two inputs are given, the second input\\nis used to provide shape of the output sample tensor. Otherwise, we use\\nargument `num_samples` to determine the number of samples to generate.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"number of samples to sample from the input data\",\n        \"name\": \"num_samples\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"An optional 1-D Tensor.Input cumulative sampling probability (such as [0.2, 0.5, 0.8, 1.5]). All weights must be non-negative numbers. Note that the last value of CDF is not necessary 1. If the last value is not 1, all values in sampling_cdf will be scaled by this number.\",\n        \"name\": \"sampling_cdf\"\n      },\n      {\n        \"description\": \"Tensor whose shape will be applied to output.\",\n        \"name\": \"shape_tensor (optional)\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor contains indices sampled from distribution givenby the weight vector in the input tensorThe output is a 1-D Tensor of size determined by argument`num_samples` or the second input tensor.\",\n        \"name\": \"sampled_indexes\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedSample\",\n    \"description\": \"\\nThe operator performs sampling based on the input sampling weights for\\neach batch. All weights must be non-negative numbers.\\nThe input is a 2-D tensor (Tensor) of size (batch_size x weights_dim).\\nFor each batch, an index is randomly sampled from the distribution given by\\nthe weights of the corresponding batch.\\nThe output is a 1-D tensor (Tensor) of size (batch_size x 1) and\\ncontains the index(es) of the sampled output.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"A 2-D Tensor of size (batch_size x weights_dim).All weights must be non-negative numbers.\",\n        \"name\": \"sampling_weights\"\n      },\n      {\n        \"description\": \"An optional 2-D Tensor of size (batch_size x weights_dim).Its values correspond to the sampling weights.\",\n        \"name\": \"sampling_values\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"The output tensor contains index(es) sampled from distribution givenby the weight vector(s) in the input tensorThe output is a 1-D Tensor of size (batch_size x 1)\",\n        \"name\": \"sampled_indexes\"\n      },\n      {\n        \"description\": \"The output tensor contains value(s) selected by the sampled index(es)It is a 1-D Tensor of size (batch_size x 1)\",\n        \"name\": \"sampled_values\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedSampleDequeueBlobs\",\n    \"description\": \"\\nDequeue the blobs from multiple queues. When one of queues is closed and empty,\\nthe output status will be set to true which can be used as exit criteria for\\nexecution step.\\nThe 1st input is the queue and the last output is the status. The rest are\\ndata blobs.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Weights for sampling from multiple queues\",\n        \"name\": \"weights\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The index of the blob (among the output blob list) that will be used to store the index of the table chosen to read the current batch.\",\n        \"name\": \"table_idx_blob\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedSigmoidCrossEntropyWithLogits\",\n    \"description\": \"\\nGiven three matrices: logits, targets, weights, all of the same shape,\\n(batch_size, num_classes), computes the weighted sigmoid cross entropy between\\nlogits and targets. Specifically, at each position r,c, this computes\\nweights[r, c] * crossentropy(sigmoid(logits[r, c]), targets[r, c]), and then\\naverages over each row.\\nReturns a tensor of shape (batch_size,) of losses for each example.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"matrix of logits for each example and class.\",\n        \"name\": \"logits\"\n      },\n      {\n        \"description\": \"matrix of targets, same shape as logits.\",\n        \"name\": \"targets\"\n      },\n      {\n        \"description\": \"matrix of weights, same shape as logits.\",\n        \"name\": \"weights\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Vector with the total xentropy for each example.\",\n        \"name\": \"xentropy\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedSigmoidCrossEntropyWithLogitsGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedSum\",\n    \"description\": \"\\nElement-wise weighted sum of several data, weight tensor pairs.\\nInput should be in the form X_0, weight_0, X_1, weight_1, ... where X_i all\\nhave the same shape, and weight_i are size 1 tensors that specifies the weight\\nof each vector. Note that if one wants to do in-place computation, it could\\nonly be done with X_0 also as the output, but not other X_i.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"Weight of the first input in the sum.\",\n        \"name\": \"weight_0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Result containing weighted elem-wise sum of inputs.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightedSumGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"WeightScale\",\n    \"description\": \"\\nEvery `stepsize` iterations, multiply the weights by a constant `scale`:\\n    nw = w * scale\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Every iteration number to do weight scaling\",\n        \"name\": \"stepsize\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"After iter passes this bound, do not perform the weight rescaling\",\n        \"name\": \"upper_bound_iter\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"The multiplicative factor applied to weights.\",\n        \"name\": \"scale\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Current weights\",\n        \"name\": \"w\"\n      },\n      {\n        \"description\": \"Training Iteration\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated weights\",\n        \"name\": \"nw\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Where\",\n    \"description\": \"\\nOperator Where takes three input data (Tensor, Tensor, Tensor) and\\nproduces one output data (Tensor) where z = c ? x : y is applied elementwise.\\n\",\n    \"inputs\": [\n      {\n        \"description\": \"input tensor containing booleans\",\n        \"name\": \"C\"\n      },\n      {\n        \"description\": \"input tensor\",\n        \"name\": \"X\"\n      },\n      {\n        \"description\": \"input tensor\",\n        \"name\": \"Y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"output tensor\",\n        \"name\": \"Z\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"While\",\n    \"description\": \"\\n'While' control operator, first input is a scalar boolean blob that stores loop's\\ncondition value. Accepts 'loop_net' (required) and 'cond_net' (optional) arguments for\\nloop's body and condition subnets respectively. If condition subnet is specified,\\nit is executed before the first and after each iteration. Subnets are executed in\\nthe same workspace as 'While'.\\n    \",\n    \"attributes\": [\n      {\n        \"description\": \"Net executed on each iteration\",\n        \"name\": \"loop_net\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Net to (re)compute condition value\",\n        \"name\": \"cond_net\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Scalar boolean condition\",\n        \"name\": \"condition\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Wngrad\",\n    \"description\": \"\\n\\nComputes the WnGrad update for an input gradient and accumulated\\nhistory. This operator implement the optimization algorithm\\nin https://arxiv.org/abs/1803.02865 by Wu, Ward and Bottou.\\nConcretely, given inputs (param, grad, seq_b, learning_rate),\\ncomputes\\n\\n    new_seq_b = seq_b + 1 / seq_b * norm(grad)^2\\n    effective_lr = learning_rate / (new_seq_b + epsilon)\\n    update = learning_rate * grad / (new_seq_b + epsilon)\\n    new_param = param + update\\nand returns (new_param, new_seq_b).\\n\\nOptionally returns effective_lr and update as well.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 1e-5\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Seq_b history\",\n        \"name\": \"seq_b\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"learning rate\",\n        \"name\": \"lr\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Updated parameters\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Updated seq_b\",\n        \"name\": \"output_seq_b\"\n      },\n      {\n        \"description\": \"(optional) Effective learning rate\",\n        \"name\": \"output_effective_lr\"\n      },\n      {\n        \"description\": \"(optional) Actual update that is applied.\",\n        \"name\": \"output_update\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"XavierFill\",\n    \"description\": \"\\nThis op fills an output tensor with values sampled from a uniform distribution with the range determined by the desired shape of the output. Rather, than specifying the range of values manually, the novelty of Xavier Fill is that it automatically scales the range of the distribution it draws from based on the size of the desired output tensor. For more information check out the paper [Understanding the difficulty of training deep feedforward neural networks](http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf). The output tensor shape is specified by the *shape* argument. However, if *input_as_shape* is set to *true*, then the *input* should be a 1D tensor containing the desired output shape (the dimensions specified in *extra_shape* will also be appended). In this case, the *shape* argument should **not** be set.\\n\\n*Note: Do not set the shape argument and pass in an input at the same time.*\\n\\nGithub Links:\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.h\\n- https://github.com/caffe2/caffe2/blob/master/caffe2/operators/filler_op.cc\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"XavierFill\\\",\\n    [],\\n    [\\\"out\\\"],\\n    shape=[3,3],\\n)\\n\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Out:\\\\n\\\", workspace.FetchBlob(\\\"out\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nOut:\\n [[-0.8412168   0.33207083 -0.88418937]\\n [ 0.43059897 -0.8340702   0.07781601]\\n [ 0.93261135 -0.24542928 -0.3980782 ]]\\n\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Desired shape of the *output* tensor.\",\n        \"name\": \"shape\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"description\": \"The additional dimensions appended at the end of the *shape* indicated by the input blob. Cannot set the *extra_shape* argument when there is no input blob.\",\n        \"name\": \"extra_shape\",\n        \"option\": \"optional\",\n        \"type\": \"int64[]\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"set to *True* to use the *input* as shape. First, input must be in CPU context.\",\n        \"name\": \"input_as_shape\",\n        \"option\": \"optional\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"(Optional) 1D tensor specifying the shape of the output. Must be used with *input_as_shape=True*\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Output tensor of random values drawn from an automatically scaled uniform distribution, based on the size of the output tensor. If the shape argument is set, this is the shape specified by the shape argument, and if the *input* exists and *input_as_shape=True*, it is the shape specified by the *input* tensor.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Xor\",\n    \"description\": \"\\nPerforms element-wise logical operation **xor** (with limited broadcast support).\\nBoth input operands should be of type `bool`.\\n\\n\\nIf necessary the right-hand-side argument will be broadcasted to match the\\nshape of left-hand-side argument. When broadcasting is specified, the second\\ntensor can either be of size 1 (a scalar value), or having its shape as a\\ncontiguous subset of the first tensor's shape. The starting of the mutually\\nequal shape is specified by the argument \\\"axis\\\", and if it is not set, suffix\\nmatching is assumed. 1-dim expansion doesn't work yet.\\n\\nFor example, the following tensor shapes are supported (with broadcast=1):\\n```\\n  shape(A) = (2, 3, 4, 5), shape(B) = (,), i.e. B is a scalar\\n  shape(A) = (2, 3, 4, 5), shape(B) = (5,)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (4, 5)\\n  shape(A) = (2, 3, 4, 5), shape(B) = (3, 4), with axis=1\\n  shape(A) = (2, 3, 4, 5), shape(B) = (2), with axis=0\\n```\\nArgument `broadcast=1` needs to be passed to enable broadcasting.\\n\\nGithub Links:\\n\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/elementwise_ops_schema.cc\\n\\n\\n\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\n\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"Xor\\\",\\n    [\\\"A\\\",  \\\"B\\\"],\\n    [\\\"C\\\"],\\n)\\n\\nworkspace.FeedBlob(\\\"A\\\", (np.random.rand(3, 3) > 0.5))\\nworkspace.FeedBlob(\\\"B\\\", (np.random.rand(3, 3) > 0.5))\\nprint(\\\"A:\\\", workspace.FetchBlob(\\\"A\\\"))\\nprint(\\\"B:\\\", workspace.FetchBlob(\\\"B\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"C:\\\", workspace.FetchBlob(\\\"C\\\"))\\n\\n```\\n\\n**Result**\\n\\n```\\n\\nA:\\n[[ True  True  True]\\n [False False  True]\\n [False  True False]]\\nB:\\n[[False False False]\\n [ True  True  True]\\n [False False False]]\\nC:\\n[[ True  True  True]\\n [ True  True False]\\n [False  True False]]\\n\\n```\\n\\n</details>\\n\\n    \",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"Pass 1 to enable broadcasting.\",\n        \"name\": \"broadcast\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      },\n      {\n        \"default\": -1,\n        \"description\": \"Axis to concatenate on. If set, defines the broadcast dimensions.\",\n        \"name\": \"axis\",\n        \"option\": \"optional\",\n        \"type\": \"int64\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* First operand.\",\n        \"name\": \"A\"\n      },\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Second operand. With broadcasting can be of smaller size than `A`. If broadcasting is disabled it should be of the same size.\",\n        \"name\": \"B\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"*(type: Tensor`<bool>`)* Output tensor of booleans. Has same dimensions as input `A`.\",\n        \"name\": \"C\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"YellowFin\",\n    \"description\": \"\\n\\nComputes the YellowFin update (https://arxiv.org/abs/1706.03471) and performs\\nmomentum SGD optimization step. lr and mu are not being shared between\\nparameters. curv_win, g_avg, g2_avg and scalars_memory are just auxiliary\\nmemory for computing moving averages (see the publication). Takes arguments\\nbeta: coefficient for moving averages,\\ncurv_win_width: timeframe when average squared gradient is being stored,\\nepsilon: for numerical purposes,\\nnesterov and zero_debias for debias of moving average.\\n\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Default 0.999\",\n        \"name\": \"beta\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 20\",\n        \"name\": \"curv_win_width\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default 1e-6\",\n        \"name\": \"epsilon\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default false\",\n        \"name\": \"nesterov\",\n        \"option\": \"optional\"\n      },\n      {\n        \"description\": \"Default true\",\n        \"name\": \"zero_debias\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"param\"\n      },\n      {\n        \"description\": \"Momentum\",\n        \"name\": \"moment\"\n      },\n      {\n        \"description\": \"Learning rate\",\n        \"name\": \"lr\"\n      },\n      {\n        \"description\": \"Momentum coefficient\",\n        \"name\": \"mu\"\n      },\n      {\n        \"description\": \"Memory for latest curvature ranges\",\n        \"name\": \"curv_win\"\n      },\n      {\n        \"description\": \"Moving average of gradient\",\n        \"name\": \"g_avg\"\n      },\n      {\n        \"description\": \"Moving average of squared gradient\",\n        \"name\": \"g2_avg\"\n      },\n      {\n        \"description\": \"Memory for stateful scalars\",\n        \"name\": \"scalars_memory\"\n      },\n      {\n        \"description\": \"Gradient computed\",\n        \"name\": \"grad\"\n      },\n      {\n        \"description\": \"Iteration number\",\n        \"name\": \"iter\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Parameters to be updated\",\n        \"name\": \"output_param\"\n      },\n      {\n        \"description\": \"Momentum\",\n        \"name\": \"output_moment\"\n      },\n      {\n        \"description\": \"Output learning rate\",\n        \"name\": \"output_lr\"\n      },\n      {\n        \"description\": \"Output momentum coefficient\",\n        \"name\": \"output_mu\"\n      },\n      {\n        \"description\": \"Output memory for latest curvature ranges\",\n        \"name\": \"output_curv_win\"\n      },\n      {\n        \"description\": \"Output moving average of gradient\",\n        \"name\": \"output_g_avg\"\n      },\n      {\n        \"description\": \"Output moving average of squared gradient\",\n        \"name\": \"output_g2_avg\"\n      },\n      {\n        \"description\": \"Output memory for stateful scalars\",\n        \"name\": \"output_scalars_memory\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ZeroGradient\",\n    \"description\": \"\\nZeroGradient operators doesn't produce any output blobs. One can use\\nthis operator to produce 0 gradient for the input blob.\\n\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DecayAdagrad\",\n    \"description\": \"\\n\\nComputes the DecayAdagrad update for an\\ninput gradient and momentum parameters. Concretely, given inputs\\n(param, m1, m2, c, grad, lr, iters),\\n\\n    t = iters + 1\\n    m1_o = (beta1 * m1) + (1 - beta1) * grad\\n    m2_o = m2 + np.square(grad)\\n    c = 1.0 or (1 - power(beta1, t))\\n    grad_o = m1_o / c / (sqrt(m2_o) + epsilon)\\n    param_o = param + lr * (grad_o + weight_decay * param)\\n\\nand returns (param_o, m1_o, m2_o)\\n\\n\",\n    \"attributes\": [\n      {\n        \"name\": \"beta1\",\n        \"description\": \"Default 0.9\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"beta2\",\n        \"description\": \"Default 0.999\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"epsilon\",\n        \"description\": \"Default 1e-5\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"weight_decay\",\n        \"description\": \"Default 0.0\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"bias_correction_first\",\n        \"description\": \"Default True\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"param\",\n        \"description\": \"Parameters to be updated\"\n      },\n      {\n        \"name\": \"moment_1\",\n        \"description\": \"First moment history\"\n      },\n      {\n        \"name\": \"moment_2\",\n        \"description\": \"Second moment history\"\n      },\n      {\n        \"name\": \"grad\",\n        \"description\": \"Gradient computed\"\n      },\n      {\n        \"name\": \"lr\",\n        \"description\": \"learning rate\"\n      },\n      {\n        \"name\": \"iter\",\n        \"description\": \"iteration number\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output_param\",\n        \"description\": \"Updated parameters\"\n      },\n      {\n        \"name\": \"output_moment_1\",\n        \"description\": \"Updated first moment\"\n      },\n      {\n        \"name\": \"output_moment_2\",\n        \"description\": \"Updated second moment\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Log1p\",\n    \"description\": \"\\nCalculates Log1p of the given input tensor element-wise. This\\noperation can be done in an in-place fashion too, by providing the same input\\nand output blobs.\\n\\nGithub Link:\\n- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/log1p_op.cc\\n\",\n    \"inputs\": [\n      {\n        \"name\": \"input\",\n        \"description\": \"Input data blob to be operated on.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"description\": \"Output data blob with same shape as input\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Log1pGradient\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SparseItemwiseDropoutWithReplacement\",\n    \"description\": \"\\n\\n`SparseItemwiseDropoutWithReplacement` takes a 1-d input tensor and a lengths tensor.\\nValues in the Lengths tensor represent how many input elements consitute each\\nexample in a given batch.  The each input value in the tensor of an example can be\\nreplaced with the replacement value with probability given by the `ratio`\\nargument.\\n\\n<details>\\n\\n<summary> <b>Example</b> </summary>\\n\\n**Code**\\n\\n```\\nworkspace.ResetWorkspace()\\n\\nop = core.CreateOperator(\\n    \\\"SparseItemwiseDropoutWithReplacement\\\",\\n    [\\\"X\\\", \\\"Lengths\\\"],\\n    [\\\"Y\\\", \\\"OutputLengths\\\"],\\n    ratio=0.5,\\n    replacement_value=-1\\n)\\n\\nworkspace.FeedBlob(\\\"X\\\", np.array([1, 2, 3, 4, 5]).astype(np.int64))\\nworkspace.FeedBlob(\\\"Lengths\\\", np.array([2, 3]).astype(np.int32))\\nprint(\\\"X:\\\", workspace.FetchBlob(\\\"X\\\"))\\nprint(\\\"Lengths:\\\", workspace.FetchBlob(\\\"Lengths\\\"))\\nworkspace.RunOperatorOnce(op)\\nprint(\\\"Y:\\\", workspace.FetchBlob(\\\"Y\\\"))\\nprint(\\\"OutputLengths:\\\", workspace.FetchBlob(\\\"OutputLengths\\\"))\\n```\\n\\n**Result**\\n\\n```\\nX: [1, 2, 3, 4, 5]\\nLengths: [2, 3]\\nY: [1, 2, -1]\\nOutputLengths: [2, 1]\\n```\\n\\n</details>\\n\\n\",\n    \"attributes\": [\n      {\n        \"name\": \"ratio\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Probability of an element to be replaced.\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"replacement_value\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Value elements are replaced with.\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"X\",\n        \"description\": \"*(type: Tensor`<int64_t>`)* Input data tensor.\"\n      },\n      {\n        \"name\": \"Lengths\",\n        \"description\": \"*(type: Tensor`<int32_t>`)* Lengths tensor for input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"Y\",\n        \"description\": \"*(type: Tensor`<int64_t>`)* Output tensor.\"\n      },\n      {\n        \"name\": \"OutputLengths\",\n        \"description\": \"*(type: Tensor`<int32_t>`)* Output tensor.\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"EstimateAllBlobSizes\",\n    \"description\": \"\\nReturns two outputs: a 1D tensor of strings containing the names\\nof each blob in the active workspace, and a 1D tensor of integers containing the\\nestimated serialized size of each blob (in bytes).\\n\",\n    \"attributes\": [\n      {\n        \"name\": \"include_shared\",\n        \"description\": \"(bool, default true) Whether to include blobs inherited from parent workspaces.\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"options\",\n        \"description\": \"(string, default empty) A BlobSerializationOptions message specifying options for how specific blobs should be serialized.\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"blob_names\",\n        \"description\": \"1D tensor of strings containing blob names.\"\n      },\n      {\n        \"name\": \"blob_sizes\",\n        \"description\": \"1D tensor of int64_t containing blob sizes.\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"SmartDecaySparseAdam\",\n    \"description\": \"\\n\\n    Computes the Adam Update for the sparse case.\\n    Given inputs (param, moment1, moment2, indices, grad, lr, iter), runs the dense\\n    Adam on (param, moment1[indices], momemnt2[indices], lr, iter) and returns\\n    (new_param, new_moment1, new_moment2) as in dense case.\\n    Adam can be customized as Rectified Adam (RAdam) by setting enableRAdam = true.\\n\\n    \",\n    \"attributes\": [\n      {\n        \"name\": \"beta1\",\n        \"description\": \"Default 0.9\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"beta2\",\n        \"description\": \"Default 0.999\",\n        \"option\": \"optional\"\n      },\n      {\n        \"name\": \"epsilon\",\n        \"description\": \"Default 1e-5\",\n        \"option\": \"optional\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"param\",\n        \"description\": \"Parameters to be updated\"\n      },\n      {\n        \"name\": \"moment_1\",\n        \"description\": \"First moment history\"\n      },\n      {\n        \"name\": \"moment_2\",\n        \"description\": \"Second moment history\"\n      },\n      {\n        \"name\": \"last_seen\",\n        \"description\": \"Minibatch index when each weight was last seen\"\n      },\n      {\n        \"name\": \"indices\",\n        \"description\": \"Sparse indices\"\n      },\n      {\n        \"name\": \"grad\",\n        \"description\": \"Gradient computed\"\n      },\n      {\n        \"name\": \"lr\",\n        \"description\": \"learning rate\"\n      },\n      {\n        \"name\": \"iter\",\n        \"description\": \"iteration number\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output_param\",\n        \"description\": \"Updated parameters\"\n      },\n      {\n        \"name\": \"output_moment_1\",\n        \"description\": \"Updated first moment\"\n      },\n      {\n        \"name\": \"output_moment_2\",\n        \"description\": \"Updated second moment\"\n      },\n      {\n        \"name\": \"output_last_seen\",\n        \"description\": \"Updated minibatch index when each weight was last seen\"\n      }\n    ],\n    \"status\": \"default\"\n  }\n]\n"
  },
  {
    "path": "source/caffe2-proto.js",
    "content": "\nexport const caffe2 = {};\n\ncaffe2.TensorProto = class TensorProto {\n\n    constructor() {\n        this.dims = [];\n        this.float_data = [];\n        this.int32_data = [];\n        this.string_data = [];\n        this.double_data = [];\n        this.int64_data = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dims = reader.array(message.dims, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.data_type = reader.int32();\n                    break;\n                case 15:\n                    message.data_format = reader.uint32();\n                    break;\n                case 3:\n                    message.float_data = reader.floats(message.float_data, tag);\n                    break;\n                case 4:\n                    message.int32_data = reader.array(message.int32_data, () => reader.int32(), tag);\n                    break;\n                case 5:\n                    message.byte_data = reader.bytes();\n                    break;\n                case 6:\n                    message.string_data.push(reader.bytes());\n                    break;\n                case 9:\n                    message.double_data = reader.doubles(message.double_data, tag);\n                    break;\n                case 10:\n                    message.int64_data = reader.array(message.int64_data, () => reader.int64(), tag);\n                    break;\n                case 13:\n                    message.raw_data = reader.bytes();\n                    break;\n                case 7:\n                    message.name = reader.string();\n                    break;\n                case 8:\n                    message.device_detail = caffe2.DeviceOption.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.segment = caffe2.TensorProto.Segment.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dims\":\n                    reader.array(message.dims, () => reader.int64());\n                    break;\n                case \"data_type\":\n                    message.data_type = reader.enum(caffe2.TensorProto.DataType);\n                    break;\n                case \"data_format\":\n                    message.data_format = reader.uint32();\n                    break;\n                case \"float_data\":\n                    reader.array(message.float_data, () => reader.float());\n                    break;\n                case \"int32_data\":\n                    reader.array(message.int32_data, () => reader.int32());\n                    break;\n                case \"byte_data\":\n                    message.byte_data = reader.bytes();\n                    break;\n                case \"string_data\":\n                    reader.array(message.string_data, () => reader.bytes());\n                    break;\n                case \"double_data\":\n                    reader.array(message.double_data, () => reader.double());\n                    break;\n                case \"int64_data\":\n                    reader.array(message.int64_data, () => reader.int64());\n                    break;\n                case \"raw_data\":\n                    message.raw_data = reader.bytes();\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"device_detail\":\n                    message.device_detail = caffe2.DeviceOption.decodeText(reader);\n                    break;\n                case \"segment\":\n                    message.segment = caffe2.TensorProto.Segment.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorProto.prototype.data_type = 1;\ncaffe2.TensorProto.prototype.data_format = 0;\ncaffe2.TensorProto.prototype.byte_data = new Uint8Array([]);\ncaffe2.TensorProto.prototype.raw_data = new Uint8Array([]);\ncaffe2.TensorProto.prototype.name = \"\";\ncaffe2.TensorProto.prototype.device_detail = null;\ncaffe2.TensorProto.prototype.segment = null;\n\ncaffe2.TensorProto.DataType = {\n    \"UNDEFINED\": 0,\n    \"FLOAT\": 1,\n    \"INT32\": 2,\n    \"BYTE\": 3,\n    \"STRING\": 4,\n    \"BOOL\": 5,\n    \"UINT8\": 6,\n    \"INT8\": 7,\n    \"UINT16\": 8,\n    \"INT16\": 9,\n    \"INT64\": 10,\n    \"FLOAT16\": 12,\n    \"DOUBLE\": 13,\n    \"ZERO_COLLISION_HASH\": 14,\n    \"REBATCHING_BUFFER\": 15\n};\n\ncaffe2.TensorProto.SerializationFormat = {\n    \"FMT_PROTOBUF\": 0,\n    \"FMT_BFLOAT16\": 1\n};\n\ncaffe2.TensorProto.Segment = class Segment {\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorProto.Segment();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.begin = reader.int64();\n                    break;\n                case 2:\n                    message.end = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'begin')) {\n            throw new Error(\"Expected 'begin'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'end')) {\n            throw new Error(\"Expected 'end'.\");\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorProto.Segment();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"begin\":\n                    message.begin = reader.int64();\n                    break;\n                case \"end\":\n                    message.end = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"begin\")) {\n            throw new Error(\"Expected 'begin'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"end\")) {\n            throw new Error(\"Expected 'end'.\");\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorProto.Segment.prototype.begin = 0n;\ncaffe2.TensorProto.Segment.prototype.end = 0n;\n\ncaffe2.QTensorProto = class QTensorProto {\n\n    constructor() {\n        this.dims = [];\n        this.data = [];\n        this.scales = [];\n        this.biases = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.QTensorProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dims = reader.array(message.dims, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.precision = reader.int32();\n                    break;\n                case 3:\n                    message.scale = reader.double();\n                    break;\n                case 4:\n                    message.bias = reader.double();\n                    break;\n                case 5:\n                    message.is_signed = reader.bool();\n                    break;\n                case 6:\n                    message.data = reader.array(message.data, () => reader.int32(), tag);\n                    break;\n                case 7:\n                    message.name = reader.string();\n                    break;\n                case 8:\n                    message.data_type = reader.int32();\n                    break;\n                case 9:\n                    message.scales = reader.doubles(message.scales, tag);\n                    break;\n                case 10:\n                    message.biases = reader.doubles(message.biases, tag);\n                    break;\n                case 11:\n                    message.axis = reader.int32();\n                    break;\n                case 12:\n                    message.is_multiparam = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'precision')) {\n            throw new Error(\"Expected 'precision'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'scale')) {\n            throw new Error(\"Expected 'scale'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'bias')) {\n            throw new Error(\"Expected 'bias'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'is_signed')) {\n            throw new Error(\"Expected 'is_signed'.\");\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.QTensorProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dims\":\n                    reader.array(message.dims, () => reader.int64());\n                    break;\n                case \"precision\":\n                    message.precision = reader.int32();\n                    break;\n                case \"scale\":\n                    message.scale = reader.double();\n                    break;\n                case \"bias\":\n                    message.bias = reader.double();\n                    break;\n                case \"is_signed\":\n                    message.is_signed = reader.bool();\n                    break;\n                case \"data\":\n                    reader.array(message.data, () => reader.int32());\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"data_type\":\n                    message.data_type = reader.enum(caffe2.TensorProto.DataType);\n                    break;\n                case \"scales\":\n                    reader.array(message.scales, () => reader.double());\n                    break;\n                case \"biases\":\n                    reader.array(message.biases, () => reader.double());\n                    break;\n                case \"axis\":\n                    message.axis = reader.int32();\n                    break;\n                case \"is_multiparam\":\n                    message.is_multiparam = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"precision\")) {\n            throw new Error(\"Expected 'precision'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"scale\")) {\n            throw new Error(\"Expected 'scale'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"bias\")) {\n            throw new Error(\"Expected 'bias'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"is_signed\")) {\n            throw new Error(\"Expected 'is_signed'.\");\n        }\n        return message;\n    }\n};\n\ncaffe2.QTensorProto.prototype.precision = 0;\ncaffe2.QTensorProto.prototype.scale = 0;\ncaffe2.QTensorProto.prototype.bias = 0;\ncaffe2.QTensorProto.prototype.is_signed = false;\ncaffe2.QTensorProto.prototype.name = \"\";\ncaffe2.QTensorProto.prototype.data_type = 2;\ncaffe2.QTensorProto.prototype.axis = 0;\ncaffe2.QTensorProto.prototype.is_multiparam = false;\n\ncaffe2.TensorProtos = class TensorProtos {\n\n    constructor() {\n        this.protos = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorProtos();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.protos.push(caffe2.TensorProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorProtos();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"protos\":\n                    message.protos.push(caffe2.TensorProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorShape = class TensorShape {\n\n    constructor() {\n        this.dims = [];\n        this.unknown_dims = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorShape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dims = reader.array(message.dims, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.data_type = reader.int32();\n                    break;\n                case 3:\n                    message.unknown_dims = reader.array(message.unknown_dims, () => reader.int32(), tag);\n                    break;\n                case 4:\n                    message.unknown_shape = reader.bool();\n                    break;\n                case 5:\n                    message.name = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorShape();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dims\":\n                    reader.array(message.dims, () => reader.int64());\n                    break;\n                case \"data_type\":\n                    message.data_type = reader.enum(caffe2.TensorProto.DataType);\n                    break;\n                case \"unknown_dims\":\n                    reader.array(message.unknown_dims, () => reader.int32());\n                    break;\n                case \"unknown_shape\":\n                    message.unknown_shape = reader.bool();\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorShape.prototype.data_type = 1;\ncaffe2.TensorShape.prototype.unknown_shape = false;\ncaffe2.TensorShape.prototype.name = \"\";\n\ncaffe2.TensorShapes = class TensorShapes {\n\n    constructor() {\n        this.shapes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorShapes();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shapes.push(caffe2.TensorShape.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorShapes();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shapes\":\n                    message.shapes.push(caffe2.TensorShape.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorBoundShape = class TensorBoundShape {\n\n    constructor() {\n        this.dim_type = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorBoundShape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = caffe2.TensorShape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.dim_type = reader.array(message.dim_type, () => reader.int32(), tag);\n                    break;\n                case 3:\n                    message.name = reader.string();\n                    break;\n                case 4:\n                    message.shape_is_final = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorBoundShape();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = caffe2.TensorShape.decodeText(reader);\n                    break;\n                case \"dim_type\":\n                    reader.array(message.dim_type, () => reader.enum(caffe2.TensorBoundShape.DimType));\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"shape_is_final\":\n                    message.shape_is_final = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorBoundShape.prototype.shape = null;\ncaffe2.TensorBoundShape.prototype.name = \"\";\ncaffe2.TensorBoundShape.prototype.shape_is_final = false;\n\ncaffe2.TensorBoundShape.DimType = {\n    \"UNKNOWN\": 0,\n    \"CONSTANT\": 1,\n    \"BATCH\": 2,\n    \"BATCH_OF_FEATURE_MAX\": 3,\n    \"BATCH_OF_FEATURE_MAX_DEFAULT\": 4,\n    \"FEATURE_MAX\": 5,\n    \"FEATURE_MAX_DEFAULT\": 6\n};\n\ncaffe2.TensorBoundShapes = class TensorBoundShapes {\n\n    constructor() {\n        this.shapes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.TensorBoundShapes();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shapes.push(caffe2.TensorBoundShape.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.max_batch_size = reader.int64();\n                    break;\n                case 3:\n                    message.max_feature_len = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.TensorBoundShapes();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shapes\":\n                    message.shapes.push(caffe2.TensorBoundShape.decodeText(reader));\n                    break;\n                case \"max_batch_size\":\n                    message.max_batch_size = reader.int64();\n                    break;\n                case \"max_feature_len\":\n                    message.max_feature_len = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.TensorBoundShapes.prototype.max_batch_size = 0n;\ncaffe2.TensorBoundShapes.prototype.max_feature_len = 0n;\n\ncaffe2.AOTConfig = class AOTConfig {\n\n    static decode(reader, length) {\n        const message = new caffe2.AOTConfig();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.max_batch_size = reader.int64();\n                    break;\n                case 2:\n                    message.max_seq_size = reader.int64();\n                    break;\n                case 3:\n                    message.in_batch_broadcast = reader.bool();\n                    break;\n                case 4:\n                    message.onnxifi_blacklist_ops = reader.string();\n                    break;\n                case 5:\n                    message.onnxifi_min_ops = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'max_batch_size')) {\n            throw new Error(\"Expected 'max_batch_size'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'max_seq_size')) {\n            throw new Error(\"Expected 'max_seq_size'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'in_batch_broadcast')) {\n            throw new Error(\"Expected 'in_batch_broadcast'.\");\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.AOTConfig();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"max_batch_size\":\n                    message.max_batch_size = reader.int64();\n                    break;\n                case \"max_seq_size\":\n                    message.max_seq_size = reader.int64();\n                    break;\n                case \"in_batch_broadcast\":\n                    message.in_batch_broadcast = reader.bool();\n                    break;\n                case \"onnxifi_blacklist_ops\":\n                    message.onnxifi_blacklist_ops = reader.string();\n                    break;\n                case \"onnxifi_min_ops\":\n                    message.onnxifi_min_ops = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"max_batch_size\")) {\n            throw new Error(\"Expected 'max_batch_size'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"max_seq_size\")) {\n            throw new Error(\"Expected 'max_seq_size'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"in_batch_broadcast\")) {\n            throw new Error(\"Expected 'in_batch_broadcast'.\");\n        }\n        return message;\n    }\n};\n\ncaffe2.AOTConfig.prototype.max_batch_size = 0n;\ncaffe2.AOTConfig.prototype.max_seq_size = 0n;\ncaffe2.AOTConfig.prototype.in_batch_broadcast = false;\ncaffe2.AOTConfig.prototype.onnxifi_blacklist_ops = \"\";\ncaffe2.AOTConfig.prototype.onnxifi_min_ops = 0;\n\ncaffe2.Argument = class Argument {\n\n    constructor() {\n        this.floats = [];\n        this.ints = [];\n        this.strings = [];\n        this.tensors = [];\n        this.nets = [];\n        this.qtensors = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.Argument();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.f = reader.float();\n                    break;\n                case 3:\n                    message.i = reader.int64();\n                    break;\n                case 4:\n                    message.s = reader.bytes();\n                    break;\n                case 10:\n                    message.t = caffe2.TensorProto.decode(reader, reader.uint32());\n                    break;\n                case 8:\n                    message.n = caffe2.NetDef.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.floats = reader.floats(message.floats, tag);\n                    break;\n                case 6:\n                    message.ints = reader.array(message.ints, () => reader.int64(), tag);\n                    break;\n                case 7:\n                    message.strings.push(reader.bytes());\n                    break;\n                case 11:\n                    message.tensors.push(caffe2.TensorProto.decode(reader, reader.uint32()));\n                    break;\n                case 9:\n                    message.nets.push(caffe2.NetDef.decode(reader, reader.uint32()));\n                    break;\n                case 12:\n                    message.qtensors.push(caffe2.QTensorProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.Argument();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"f\":\n                    message.f = reader.float();\n                    break;\n                case \"i\":\n                    message.i = reader.int64();\n                    break;\n                case \"s\":\n                    message.s = reader.bytes();\n                    break;\n                case \"t\":\n                    message.t = caffe2.TensorProto.decodeText(reader);\n                    break;\n                case \"n\":\n                    message.n = caffe2.NetDef.decodeText(reader);\n                    break;\n                case \"floats\":\n                    reader.array(message.floats, () => reader.float());\n                    break;\n                case \"ints\":\n                    reader.array(message.ints, () => reader.int64());\n                    break;\n                case \"strings\":\n                    reader.array(message.strings, () => reader.bytes());\n                    break;\n                case \"tensors\":\n                    message.tensors.push(caffe2.TensorProto.decodeText(reader));\n                    break;\n                case \"nets\":\n                    message.nets.push(caffe2.NetDef.decodeText(reader));\n                    break;\n                case \"qtensors\":\n                    message.qtensors.push(caffe2.QTensorProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.Argument.prototype.name = \"\";\ncaffe2.Argument.prototype.f = 0;\ncaffe2.Argument.prototype.i = 0n;\ncaffe2.Argument.prototype.s = new Uint8Array([]);\ncaffe2.Argument.prototype.t = null;\ncaffe2.Argument.prototype.n = null;\n\ncaffe2.DeviceTypeProto = {\n    \"PROTO_CPU\": 0,\n    \"PROTO_CUDA\": 1,\n    \"PROTO_MKLDNN\": 2,\n    \"PROTO_OPENGL\": 3,\n    \"PROTO_OPENCL\": 4,\n    \"PROTO_IDEEP\": 5,\n    \"PROTO_HIP\": 6,\n    \"PROTO_FPGA\": 7,\n    \"PROTO_MAIA\": 8,\n    \"PROTO_XLA\": 9,\n    \"PROTO_MPS\": 10,\n    \"PROTO_COMPILE_TIME_MAX_DEVICE_TYPES\": 11\n};\n\ncaffe2.DeviceOption = class DeviceOption {\n\n    constructor() {\n        this.extra_info = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.DeviceOption();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.device_type = reader.int32();\n                    break;\n                case 2:\n                    message.device_id = reader.int32();\n                    break;\n                case 3:\n                    message.random_seed = reader.uint32();\n                    break;\n                case 4:\n                    message.node_name = reader.string();\n                    break;\n                case 5:\n                    message.numa_node_id = reader.int32();\n                    break;\n                case 6:\n                    message.extra_info.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.DeviceOption();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"device_type\":\n                    message.device_type = reader.int32();\n                    break;\n                case \"device_id\":\n                    message.device_id = reader.int32();\n                    break;\n                case \"random_seed\":\n                    message.random_seed = reader.uint32();\n                    break;\n                case \"node_name\":\n                    message.node_name = reader.string();\n                    break;\n                case \"numa_node_id\":\n                    message.numa_node_id = reader.int32();\n                    break;\n                case \"extra_info\":\n                    reader.array(message.extra_info, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.DeviceOption.prototype.device_type = 0;\ncaffe2.DeviceOption.prototype.device_id = 0;\ncaffe2.DeviceOption.prototype.random_seed = 0;\ncaffe2.DeviceOption.prototype.node_name = \"\";\ncaffe2.DeviceOption.prototype.numa_node_id = 0;\n\ncaffe2.OperatorDef = class OperatorDef {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n        this.arg = [];\n        this.control_input = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.OperatorDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.input.push(reader.string());\n                    break;\n                case 2:\n                    message.output.push(reader.string());\n                    break;\n                case 3:\n                    message.name = reader.string();\n                    break;\n                case 4:\n                    message.type = reader.string();\n                    break;\n                case 5:\n                    message.arg.push(caffe2.Argument.decode(reader, reader.uint32()));\n                    break;\n                case 6:\n                    message.device_option = caffe2.DeviceOption.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.engine = reader.string();\n                    break;\n                case 8:\n                    message.control_input.push(reader.string());\n                    break;\n                case 9:\n                    message.is_gradient_op = reader.bool();\n                    break;\n                case 10:\n                    message.debug_info = reader.string();\n                    break;\n                case 11:\n                    message.domain = reader.string();\n                    break;\n                case 12:\n                    message.op_version = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.OperatorDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"arg\":\n                    message.arg.push(caffe2.Argument.decodeText(reader));\n                    break;\n                case \"device_option\":\n                    message.device_option = caffe2.DeviceOption.decodeText(reader);\n                    break;\n                case \"engine\":\n                    message.engine = reader.string();\n                    break;\n                case \"control_input\":\n                    reader.array(message.control_input, () => reader.string());\n                    break;\n                case \"is_gradient_op\":\n                    message.is_gradient_op = reader.bool();\n                    break;\n                case \"debug_info\":\n                    message.debug_info = reader.string();\n                    break;\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"op_version\":\n                    message.op_version = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.OperatorDef.prototype.name = \"\";\ncaffe2.OperatorDef.prototype.type = \"\";\ncaffe2.OperatorDef.prototype.device_option = null;\ncaffe2.OperatorDef.prototype.engine = \"\";\ncaffe2.OperatorDef.prototype.is_gradient_op = false;\ncaffe2.OperatorDef.prototype.debug_info = \"\";\ncaffe2.OperatorDef.prototype.domain = \"\";\ncaffe2.OperatorDef.prototype.op_version = 0n;\n\ncaffe2.MapFieldEntry = class MapFieldEntry {\n\n    static decode(reader, length) {\n        const message = new caffe2.MapFieldEntry();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.key = reader.string();\n                    break;\n                case 2:\n                    message.val = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'key')) {\n            throw new Error(\"Expected 'key'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'val')) {\n            throw new Error(\"Expected 'val'.\");\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.MapFieldEntry();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"key\":\n                    message.key = reader.string();\n                    break;\n                case \"val\":\n                    message.val = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"key\")) {\n            throw new Error(\"Expected 'key'.\");\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"val\")) {\n            throw new Error(\"Expected 'val'.\");\n        }\n        return message;\n    }\n};\n\ncaffe2.MapFieldEntry.prototype.key = \"\";\ncaffe2.MapFieldEntry.prototype.val = \"\";\n\ncaffe2.BackendOptions = class BackendOptions {\n\n    constructor() {\n        this.option = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.BackendOptions();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.backend_name = reader.string();\n                    break;\n                case 2:\n                    message.option.push(caffe2.MapFieldEntry.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'backend_name')) {\n            throw new Error(\"Expected 'backend_name'.\");\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.BackendOptions();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"backend_name\":\n                    message.backend_name = reader.string();\n                    break;\n                case \"option\":\n                    message.option.push(caffe2.MapFieldEntry.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"backend_name\")) {\n            throw new Error(\"Expected 'backend_name'.\");\n        }\n        return message;\n    }\n};\n\ncaffe2.BackendOptions.prototype.backend_name = \"\";\n\ncaffe2.PartitionInfo = class PartitionInfo {\n\n    constructor() {\n        this.device_id = [];\n        this.backend_options = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.PartitionInfo();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.device_id = reader.array(message.device_id, () => reader.int32(), tag);\n                    break;\n                case 3:\n                    message.extra_info = reader.string();\n                    break;\n                case 4:\n                    message.backend_options.push(caffe2.BackendOptions.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, 'name')) {\n            throw new Error(\"Expected 'name'.\");\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.PartitionInfo();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"device_id\":\n                    reader.array(message.device_id, () => reader.int32());\n                    break;\n                case \"extra_info\":\n                    message.extra_info = reader.string();\n                    break;\n                case \"backend_options\":\n                    message.backend_options.push(caffe2.BackendOptions.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        if (!Object.prototype.hasOwnProperty.call(message, \"name\")) {\n            throw new Error(\"Expected 'name'.\");\n        }\n        return message;\n    }\n};\n\ncaffe2.PartitionInfo.prototype.name = \"\";\ncaffe2.PartitionInfo.prototype.extra_info = \"\";\n\ncaffe2.NetDef = class NetDef {\n\n    constructor() {\n        this.op = [];\n        this.arg = [];\n        this.external_input = [];\n        this.external_output = [];\n        this.partition_info = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.NetDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.op.push(caffe2.OperatorDef.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.type = reader.string();\n                    break;\n                case 4:\n                    message.num_workers = reader.int32();\n                    break;\n                case 5:\n                    message.device_option = caffe2.DeviceOption.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.arg.push(caffe2.Argument.decode(reader, reader.uint32()));\n                    break;\n                case 7:\n                    message.external_input.push(reader.string());\n                    break;\n                case 8:\n                    message.external_output.push(reader.string());\n                    break;\n                case 9:\n                    message.partition_info.push(caffe2.PartitionInfo.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.NetDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"op\":\n                    message.op.push(caffe2.OperatorDef.decodeText(reader));\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"num_workers\":\n                    message.num_workers = reader.int32();\n                    break;\n                case \"device_option\":\n                    message.device_option = caffe2.DeviceOption.decodeText(reader);\n                    break;\n                case \"arg\":\n                    message.arg.push(caffe2.Argument.decodeText(reader));\n                    break;\n                case \"external_input\":\n                    reader.array(message.external_input, () => reader.string());\n                    break;\n                case \"external_output\":\n                    reader.array(message.external_output, () => reader.string());\n                    break;\n                case \"partition_info\":\n                    message.partition_info.push(caffe2.PartitionInfo.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.NetDef.prototype.name = \"\";\ncaffe2.NetDef.prototype.type = \"\";\ncaffe2.NetDef.prototype.num_workers = 0;\ncaffe2.NetDef.prototype.device_option = null;\n\ncaffe2.ExecutionStep = class ExecutionStep {\n\n    constructor() {\n        this.substep = [];\n        this.network = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.ExecutionStep();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.substep.push(caffe2.ExecutionStep.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.network.push(reader.string());\n                    break;\n                case 4:\n                    message.num_iter = reader.int64();\n                    break;\n                case 5:\n                    message.criteria_network = reader.string();\n                    break;\n                case 7:\n                    message.report_net = reader.string();\n                    break;\n                case 8:\n                    message.report_interval = reader.int32();\n                    break;\n                case 11:\n                    message.run_every_ms = reader.int64();\n                    break;\n                case 6:\n                    message.concurrent_substeps = reader.bool();\n                    break;\n                case 9:\n                    message.should_stop_blob = reader.string();\n                    break;\n                case 10:\n                    message.only_once = reader.bool();\n                    break;\n                case 12:\n                    message.create_workspace = reader.bool();\n                    break;\n                case 13:\n                    message.num_concurrent_instances = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.ExecutionStep();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"substep\":\n                    message.substep.push(caffe2.ExecutionStep.decodeText(reader));\n                    break;\n                case \"network\":\n                    reader.array(message.network, () => reader.string());\n                    break;\n                case \"num_iter\":\n                    message.num_iter = reader.int64();\n                    break;\n                case \"criteria_network\":\n                    message.criteria_network = reader.string();\n                    break;\n                case \"report_net\":\n                    message.report_net = reader.string();\n                    break;\n                case \"report_interval\":\n                    message.report_interval = reader.int32();\n                    break;\n                case \"run_every_ms\":\n                    message.run_every_ms = reader.int64();\n                    break;\n                case \"concurrent_substeps\":\n                    message.concurrent_substeps = reader.bool();\n                    break;\n                case \"should_stop_blob\":\n                    message.should_stop_blob = reader.string();\n                    break;\n                case \"only_once\":\n                    message.only_once = reader.bool();\n                    break;\n                case \"create_workspace\":\n                    message.create_workspace = reader.bool();\n                    break;\n                case \"num_concurrent_instances\":\n                    message.num_concurrent_instances = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.ExecutionStep.prototype.name = \"\";\ncaffe2.ExecutionStep.prototype.num_iter = 0n;\ncaffe2.ExecutionStep.prototype.criteria_network = \"\";\ncaffe2.ExecutionStep.prototype.report_net = \"\";\ncaffe2.ExecutionStep.prototype.report_interval = 0;\ncaffe2.ExecutionStep.prototype.run_every_ms = 0n;\ncaffe2.ExecutionStep.prototype.concurrent_substeps = false;\ncaffe2.ExecutionStep.prototype.should_stop_blob = \"\";\ncaffe2.ExecutionStep.prototype.only_once = false;\ncaffe2.ExecutionStep.prototype.create_workspace = false;\ncaffe2.ExecutionStep.prototype.num_concurrent_instances = 0;\n\ncaffe2.PlanDef = class PlanDef {\n\n    constructor() {\n        this.network = [];\n        this.execution_step = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.PlanDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.network.push(caffe2.NetDef.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.execution_step.push(caffe2.ExecutionStep.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.PlanDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"network\":\n                    message.network.push(caffe2.NetDef.decodeText(reader));\n                    break;\n                case \"execution_step\":\n                    message.execution_step.push(caffe2.ExecutionStep.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.PlanDef.prototype.name = \"\";\n\ncaffe2.BlobProto = class BlobProto {\n\n    static decode(reader, length) {\n        const message = new caffe2.BlobProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.tensor = caffe2.TensorProto.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.content = reader.bytes();\n                    break;\n                case 5:\n                    message.qtensor = caffe2.QTensorProto.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.content_num_chunks = reader.int32();\n                    break;\n                case 7:\n                    message.content_chunk_id = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.BlobProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"tensor\":\n                    message.tensor = caffe2.TensorProto.decodeText(reader);\n                    break;\n                case \"content\":\n                    message.content = reader.bytes();\n                    break;\n                case \"qtensor\":\n                    message.qtensor = caffe2.QTensorProto.decodeText(reader);\n                    break;\n                case \"content_num_chunks\":\n                    message.content_num_chunks = reader.int32();\n                    break;\n                case \"content_chunk_id\":\n                    message.content_chunk_id = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.BlobProto.prototype.name = \"\";\ncaffe2.BlobProto.prototype.type = \"\";\ncaffe2.BlobProto.prototype.tensor = null;\ncaffe2.BlobProto.prototype.content = new Uint8Array([]);\ncaffe2.BlobProto.prototype.qtensor = null;\ncaffe2.BlobProto.prototype.content_num_chunks = 0;\ncaffe2.BlobProto.prototype.content_chunk_id = 0;\n\ncaffe2.DBReaderProto = class DBReaderProto {\n\n    static decode(reader, length) {\n        const message = new caffe2.DBReaderProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.source = reader.string();\n                    break;\n                case 3:\n                    message.db_type = reader.string();\n                    break;\n                case 4:\n                    message.key = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.DBReaderProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"source\":\n                    message.source = reader.string();\n                    break;\n                case \"db_type\":\n                    message.db_type = reader.string();\n                    break;\n                case \"key\":\n                    message.key = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.DBReaderProto.prototype.name = \"\";\ncaffe2.DBReaderProto.prototype.source = \"\";\ncaffe2.DBReaderProto.prototype.db_type = \"\";\ncaffe2.DBReaderProto.prototype.key = \"\";\n\ncaffe2.BlobSerializationOptions = class BlobSerializationOptions {\n\n    static decode(reader, length) {\n        const message = new caffe2.BlobSerializationOptions();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.blob_name_regex = reader.string();\n                    break;\n                case 2:\n                    message.chunk_size = reader.int64();\n                    break;\n                case 3:\n                    message.float_format = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.BlobSerializationOptions();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"blob_name_regex\":\n                    message.blob_name_regex = reader.string();\n                    break;\n                case \"chunk_size\":\n                    message.chunk_size = reader.int64();\n                    break;\n                case \"float_format\":\n                    message.float_format = reader.enum(caffe2.BlobSerializationOptions.FloatFormat);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ncaffe2.BlobSerializationOptions.prototype.blob_name_regex = \"\";\ncaffe2.BlobSerializationOptions.prototype.chunk_size = 0n;\ncaffe2.BlobSerializationOptions.prototype.float_format = 0;\n\ncaffe2.BlobSerializationOptions.FloatFormat = {\n    \"FLOAT_DEFAULT\": 0,\n    \"FLOAT_PROTOBUF\": 1,\n    \"FLOAT_BFLOAT16\": 2\n};\n\ncaffe2.SerializationOptions = class SerializationOptions {\n\n    constructor() {\n        this.options = [];\n    }\n\n    static decode(reader, length) {\n        const message = new caffe2.SerializationOptions();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.options.push(caffe2.BlobSerializationOptions.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new caffe2.SerializationOptions();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"options\":\n                    message.options.push(caffe2.BlobSerializationOptions.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n"
  },
  {
    "path": "source/caffe2.js",
    "content": "\nconst caffe2 = {};\n\ncaffe2.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier.toLowerCase();\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        switch (extension) {\n            case 'pbtxt':\n            case 'prototxt': {\n                const tags = await context.tags('pbtxt');\n                if (tags.has('op') && !tags.has('op.attr') && !tags.has('op.graph_op_name') && !tags.has('op.endpoint')) {\n                    return context.set('caffe2.pbtxt');\n                }\n                break;\n            }\n            case 'pb': {\n                const tags = await context.tags('pb');\n                if (tags.size > 0 &&\n                    Array.from(tags.keys()).every((tag) => tag <= 9) &&\n                    Array.from(tags.values()).every((type) => type <= 4)) {\n                    if (tags.size === 1 && tags.get(2) === 2 && identifier.endsWith('saved_model.pb')) {\n                        return null;\n                    }\n                    const schema = [[1,2],[2,2],[3,2],[4,0],[5,2],[6,2],[7,2],[8,2],[9,2]];\n                    if (schema.every(([key, value]) => !tags.has(key) || tags.get(key) === value)) {\n                        const stream = context.stream;\n                        if (stream.length > 3) {\n                            const buffer = stream.peek(Math.min(stream.length, 67));\n                            const [signature, size] = buffer;\n                            switch (signature) {\n                                case 0x0A:\n                                    if (size < 64 &&\n                                        buffer.length > 2 + size + 1 &&\n                                        buffer.slice(2, 2 + size).every((c) => c >= 32 && c <= 127) &&\n                                        buffer[2 + size] === 0x12) {\n                                        return context.set('caffe2.pb');\n                                    }\n                                    break;\n                                case 0x12:\n                                    return context.set('caffe2.pb');\n                                default:\n                                    break;\n                            }\n                        }\n                    }\n                }\n                break;\n            }\n            default: {\n                break;\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        caffe2.proto = await context.require('./caffe2-proto');\n        caffe2.proto = caffe2.proto.caffe2;\n        const metadata = await context.metadata('caffe2-metadata.json');\n        const identifier = context.identifier;\n        const parts = identifier.split('.');\n        const extension = parts.pop().toLowerCase();\n        const base = parts.join('.');\n        let predict = null;\n        let init = null;\n        switch (context.type) {\n            case 'caffe2.pbtxt': {\n                if (base.toLowerCase().endsWith('init_net') || base.toLowerCase().startsWith('init_net')) {\n                    init = context;\n                    try {\n                        const name = identifier.replace('init_net', 'predict_net');\n                        predict = await context.fetch(name);\n                        predict.set(context.type);\n                    } catch {\n                        // continue regardless of error\n                    }\n                } else if (base.toLowerCase().endsWith('predict_net') || base.toLowerCase().startsWith('predict_net')) {\n                    predict = context;\n                    const name = identifier.replace('predict_net', 'init_net');\n                    try {\n                        init = await context.fetch(name.replace(/\\.pbtxt/, '.pb'));\n                        init.set('caffe2.pb');\n                    } catch {\n                        try {\n                            init = await context.fetch(name);\n                            init.set('caffe2.pbtxt');\n                        } catch {\n                            // continue regardless of error\n                        }\n                    }\n                } else {\n                    predict = context;\n                    try {\n                        init = await context.fetch(`${base}_init.pb`);\n                        init.set('caffe2.pb');\n                    } catch {\n                        // continue regardless of error\n                    }\n                }\n                break;\n            }\n            case 'caffe2.pb': {\n                if (base.toLowerCase().endsWith('init_net')) {\n                    init = context;\n                    const extensions = new Set([extension, 'pb', 'pbtxt']);\n                    for (const extension of extensions) {\n                        try {\n                            const name = `${base.replace(/init_net$/, '')}predict_net.${extension}`;\n                            /* eslint-disable no-await-in-loop */\n                            predict = await context.fetch(name);\n                            /* eslint-enable no-await-in-loop */\n                            predict.set(`caffe2.${extension}`);\n                            break;\n                        } catch {\n                            // continue regardless of error\n                        }\n                    }\n                } else if (base.toLowerCase().endsWith('_init')) {\n                    try {\n                        const name = `${base.replace(/_init$/, '')}.${extension}`;\n                        predict = await context.fetch(name);\n                        predict.set(context.type);\n                    } catch {\n                        // continue regardless of error\n                    }\n                } else if (base.toLowerCase().endsWith('predict_net') || base.toLowerCase().startsWith('predict_net')) {\n                    predict = context;\n                    try {\n                        const name = identifier.replace('predict_net', 'init_net');\n                        init = await context.fetch(name);\n                        init.set(context.type);\n                    } catch {\n                        // continue regardless of error\n                    }\n                } else {\n                    predict = context;\n                    try {\n                        const file = `${base}_init.${extension}`;\n                        init = await context.fetch(file, null);\n                        init.set(context.type);\n                    } catch {\n                        // continue regardless of error\n                    }\n                }\n                break;\n            }\n            default: {\n                throw new caffe2.Error(`Unsupported Caffe2 format '${context.type}'.`);\n            }\n        }\n        if (!predict && !init) {\n            throw new caffe2.Error(`Caffe2 model does not contain predict or init data.`);\n        }\n        const open = async (context) => {\n            if (context) {\n                switch (context.type) {\n                    case 'caffe2.pb':\n                        try {\n                            const reader = await context.read('protobuf.binary');\n                            return caffe2.proto.NetDef.decode(reader);\n                        } catch (error) {\n                            const message = error && error.message ? error.message : error.toString();\n                            throw new caffe2.Error(`File format is not caffe2.NetDef (${message.replace(/\\.$/, '')}).`);\n                        }\n                    case 'caffe2.pbtxt':\n                        try {\n                            const reader = await context.read('protobuf.text');\n                            reader.field = function(tag, message) {\n                                if (message instanceof caffe2.proto.DeviceOption) {\n                                    message[tag] = this.read();\n                                    return;\n                                }\n                                throw new Error(`Unknown field '${tag}' ${this.location()}`);\n                            };\n                            return caffe2.proto.NetDef.decodeText(reader);\n                        } catch (error) {\n                            const message = error && error.message ? error.message : error.toString();\n                            throw new caffe2.Error(`File format is not caffe2.NetDef (${message.replace(/\\.$/, '')}).`);\n                        }\n                    default:\n                        throw new caffe2.Error(`Unsupported Caffe2 predict format '${context.type}'.`);\n                }\n            }\n            return null;\n        };\n        const predict_net = await open(predict);\n        const init_net = await open(init);\n        return new caffe2.Model(metadata, predict_net, init_net);\n    }\n};\n\ncaffe2.Model = class {\n\n    constructor(metadata, predict_net, init_net) {\n        const net = predict_net || init_net;\n        this.format = 'Caffe2';\n        this.domain = net.domain || null;\n        this.modules = [new caffe2.Graph(metadata, predict_net, init_net)];\n    }\n};\n\ncaffe2.Graph = class {\n\n    constructor(metadata, predict_net, init_net) {\n        const net = predict_net || init_net;\n        init_net = predict_net ? init_net : null;\n        this.name = net.name || '';\n        this.nodes = [];\n        this.description = net.type;\n        const initializers = new Set();\n        const tensors = new Map();\n        for (const name of net.external_input) {\n            tensors.set(name, new caffe2.Tensor(name, {}));\n        }\n        if (init_net) {\n            const dataTypes = new Map([\n                ['GivenTensorFill', 'float32'],\n                ['GivenTensorDoubleFill', 'float64'],\n                ['GivenTensorBoolFill', 'boolean'],\n                ['GivenTensorByteStringToUInt8Fill', 'uint8'],\n                ['GivenTensorInt16Fill', 'int16'],\n                ['GivenTensorSInt16Fill', 'int16'],\n                ['GivenTensorIntFill', 'int32'],\n                ['GivenTensorInt64Fill', 'int64'],\n                ['GivenTensorStringFill', 'string'],\n                ['Int8GivenIntTensorFill', 'int32'],\n                ['Int8GivenTensorFill', 'int8'],\n                ['XavierFill', null],\n                ['ConstantFill', null]\n            ]);\n            for (const op of init_net.op) {\n                if (op.output && op.output.length === 1) {\n                    const [name] = op.output;\n                    const tensor = {};\n                    for (const arg of op.arg) {\n                        tensor[arg.name] = arg;\n                    }\n                    if (!dataTypes.has(op.type)) {\n                        throw new caffe2.Error(`Unsupported init op '${op.type}'.`);\n                    }\n                    tensor.dataType = dataTypes.get(op.type);\n                    if (tensor.values && tensor.values.floats && (tensor.values.floats.length !== 1 || tensor.values.floats[0] !== 0)) {\n                        initializers.add(name);\n                    }\n                    tensors.set(name, new caffe2.Tensor(name, tensor));\n                }\n            }\n        }\n        const scope = {};\n        for (let i = 0; i < net.op.length; i++) {\n            const op = net.op[i];\n            op.input = op.input.map((input) => scope[input] ? scope[input] : input);\n            op.output = op.output.map((output) => {\n                if (scope[output]) {\n                    const next = `${output}\\n${i}`; // custom argument id\n                    scope[output] = next;\n                    return next;\n                }\n                scope[output] = output;\n                return output;\n            });\n        }\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (!values.has(name)) {\n                values.set(name, new caffe2.Value(name, type || null, tensor || null));\n            } else if (type || tensor) {\n                throw new caffe2.Value(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        for (const op of net.op) {\n            let index = 0;\n            for (const name of op.input) {\n                if (index > 0 && tensors.has(name)) {\n                    if (!values.has(name)) {\n                        values.set(name, new caffe2.Value(name, null, tensors.get(name)));\n                    }\n                    initializers.add(name);\n                }\n                index++;\n            }\n        }\n        for (const op of net.op) {\n            for (const name of op.output) {\n                if (tensors.has(name)) {\n                    initializers.add(name);\n                }\n            }\n        }\n        let lastNode = null;\n        let lastOutput = null;\n        for (const op of net.op) {\n            const node = new caffe2.Node(metadata, op, values);\n            if (op.input.length === 1 &&\n                op.output.length >= 1 &&\n                op.input[0].split('\\n').shift() === op.output[0].split('\\n').shift() &&\n                lastNode &&\n                lastOutput === op.input[0].split('\\n').shift()) {\n                lastNode.chain.push(node);\n            } else {\n                this.nodes.push(node);\n                lastNode = null;\n                lastOutput = null;\n                if (op.output.length === 1) {\n                    lastNode = node;\n                    lastOutput = op.output[0].split('\\n').shift();\n                }\n            }\n        }\n        this.inputs = [];\n        for (const input of net.external_input) {\n            if (net.external_input.length > 1 && initializers.has(input)) {\n                continue;\n            }\n            const argument = new caffe2.Argument(input, [values.map(input)]);\n            this.inputs.push(argument);\n        }\n        this.outputs = [];\n        for (const output of net.external_output) {\n            const argument = new caffe2.Argument(output, [values.map(output)]);\n            this.outputs.push(argument);\n        }\n    }\n};\n\ncaffe2.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\ncaffe2.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new caffe2.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.quantization = initializer && initializer.quantization ? initializer.quantization : null;\n        this.initializer = initializer;\n    }\n};\n\ncaffe2.Node = class {\n\n    constructor(metadata, op, values) {\n        this.name = op.name || '';\n        this.device = op.engine || '';\n        this.chain = [];\n        this.type = metadata.type(op.type);\n        this.attributes = op.arg.map((arg) => {\n            const schema = metadata.attribute(op.type, arg.name);\n            const name = arg.name;\n            let value = null;\n            let type = null;\n            let visible = true;\n            if (arg.floats && arg.floats.length > 0) {\n                value = arg.floats;\n            } else if (arg.ints && arg.ints.length > 0) {\n                value = arg.ints;\n            } else if (arg.nets && arg.nets.length > 0) {\n                value = arg.nets.map((net) => new caffe2.Graph(metadata, net, null));\n                type = 'graph[]';\n            } else if (arg.n) {\n                value = new caffe2.Graph(metadata, arg.n, null);\n                type = 'graph';\n            } else {\n                value = arg.i;\n            }\n            if (schema) {\n                type = !type && schema.type ? schema.type : type;\n                if (type === 'boolean') {\n                    value = value !== 0 && value.toString() !== '0' ? true : false;\n                }\n                if (schema.visible === false) {\n                    visible = false;\n                } else if (schema.default !== undefined) {\n                    if (value === metadata.default || (value && value.toString() === schema.default.toString())) {\n                        visible = false;\n                    }\n                }\n            }\n            return new caffe2.Argument(name, value, type, visible);\n        });\n        const inputs = op.input;\n        const outputs = op.output;\n        this.inputs = [];\n        let inputIndex = 0;\n        if (this.type && this.type.inputs) {\n            for (const inputDef of this.type.inputs) {\n                if (inputIndex < inputs.length || inputDef.option !== 'optional') {\n                    const inputCount = (inputDef.option === 'variadic') ? (inputs.length - inputIndex) : 1;\n                    const inputArguments = inputs.slice(inputIndex, inputIndex + inputCount).filter((id) => id !== '' || inputDef.option !== 'optional').map((id) => values.map(id));\n                    this.inputs.push(new caffe2.Argument(inputDef.name, inputArguments));\n                    inputIndex += inputCount;\n                }\n            }\n        } else {\n            this.inputs.push(...inputs.slice(inputIndex).map((input, index) => {\n                const inputName = ((inputIndex + index) === 0) ? 'input' : (inputIndex + index).toString();\n                return new caffe2.Argument(inputName, [values.map(input)]);\n            }));\n        }\n        this.outputs = [];\n        let outputIndex = 0;\n        if (this.type && this.type.outputs) {\n            for (const outputDef of this.type.outputs) {\n                if (outputIndex < outputs.length || outputDef.option !== 'optional') {\n                    const outputCount = (outputDef.option === 'variadic') ? (outputs.length - outputIndex) : 1;\n                    const outputArguments = outputs.slice(outputIndex, outputIndex + outputCount).map((id) => values.map(id));\n                    this.outputs.push(new caffe2.Argument(outputDef.name, outputArguments));\n                    outputIndex += outputCount;\n                }\n            }\n        } else {\n            this.outputs.push(...outputs.slice(outputIndex).map((output, index) => {\n                const outputName = ((outputIndex + index) === 0) ? 'output' : (outputIndex + index).toString();\n                return new caffe2.Argument(outputName, [values.map(output)]);\n            }));\n        }\n    }\n};\n\ncaffe2.Tensor = class {\n\n    constructor(name, tensor) {\n        this.name = name;\n        const shape = tensor.shape && tensor.shape.ints ? tensor.shape.ints : null;\n        this.type = new caffe2.TensorType(tensor.dataType, new caffe2.TensorShape(shape));\n        this.values = null;\n        this.category = 'Initializer';\n        this.encoding = '|';\n        if (tensor.Y_scale !== undefined || tensor.Y_zero_point !== undefined) {\n            this.quantization = {\n                type: 'linear',\n                scale: [tensor.Y_scale ? tensor.Y_scale.f : 0],\n                offset: [tensor.Y_zero_point && typeof tensor.Y_zero_point.i === 'bigint' ? tensor.Y_zero_point.i.toNumber() : 0]\n            };\n        }\n        if (tensor.values) {\n            switch (this.type.dataType) {\n                case 'float32': this.values = tensor.values.floats; break;\n                case 'boolean': this.values = tensor.values.ints; break;\n                case 'int8': this.values = new Int8Array(tensor.values.s); break;\n                case 'int32': this.values = tensor.values.ints; break;\n                default: break;\n            }\n        }\n    }\n};\n\ncaffe2.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ncaffe2.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.isArray(dimensions) ? dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim) : dimensions;\n    }\n\n    toString() {\n        if (Array.isArray(this.dimensions) && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dim) => dim.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\ncaffe2.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Caffe2 model.';\n    }\n};\n\nexport const ModelFactory = caffe2.ModelFactory;\n"
  },
  {
    "path": "source/catboost-schema.js",
    "content": "\nexport const NCatBoostFbs = {};\n\nNCatBoostFbs.TGuid = class TGuid {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TGuid();\n        $.dw0 = reader.uint32(position + 0);\n        $.dw1 = reader.uint32(position + 4);\n        $.dw2 = reader.uint32(position + 8);\n        $.dw3 = reader.uint32(position + 12);\n        return $;\n    }\n};\n\nNCatBoostFbs.ENanValueTreatment = {\n    AsIs: 0, '0': 'AsIs',\n    AsFalse: 1, '1': 'AsFalse',\n    AsTrue: 2, '2': 'AsTrue'\n};\n\nNCatBoostFbs.TFloatFeature = class TFloatFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TFloatFeature();\n        $.HasNans = reader.bool_(position, 4, false);\n        $.Index = reader.int32_(position, 6, -1);\n        $.FlatIndex = reader.int32_(position, 8, -1);\n        $.Borders = reader.array(position, 10, Float32Array);\n        $.FeatureId = reader.string_(position, 12, null);\n        $.NanValueTreatment = reader.int8_(position, 14, 0);\n        return $;\n    }\n};\n\nNCatBoostFbs.TCatFeature = class TCatFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TCatFeature();\n        $.Index = reader.int32_(position, 4, -1);\n        $.FlatIndex = reader.int32_(position, 6, -1);\n        $.FeatureId = reader.string_(position, 8, null);\n        $.UsedInModel = reader.bool_(position, 10, true);\n        return $;\n    }\n};\n\nNCatBoostFbs.TTextFeature = class TTextFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TTextFeature();\n        $.Index = reader.int32_(position, 4, -1);\n        $.FlatIndex = reader.int32_(position, 6, -1);\n        $.FeatureId = reader.string_(position, 8, null);\n        $.UsedInModel = reader.bool_(position, 10, true);\n        return $;\n    }\n};\n\nNCatBoostFbs.TEmbeddingFeature = class TEmbeddingFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TEmbeddingFeature();\n        $.Index = reader.int32_(position, 4, -1);\n        $.FlatIndex = reader.int32_(position, 6, -1);\n        $.FeatureId = reader.string_(position, 8, null);\n        $.Dimension = reader.int32_(position, 10, 0);\n        $.UsedInModel = reader.bool_(position, 12, true);\n        return $;\n    }\n};\n\nNCatBoostFbs.ESourceFeatureType = {\n    Text: 0, '0': 'Text',\n    Embedding: 1, '1': 'Embedding'\n};\n\nNCatBoostFbs.TEstimatedFeature = class TEstimatedFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TEstimatedFeature();\n        $.SourceFeatureIndex = reader.int32_(position, 4, -1);\n        $.CalcerId = reader.struct(position, 6, NCatBoostFbs.TGuid);\n        $.LocalIndex = reader.int32_(position, 8, -1);\n        $.Borders = reader.array(position, 10, Float32Array);\n        $.SourceFeatureType = reader.int8_(position, 12, 0);\n        return $;\n    }\n};\n\nNCatBoostFbs.TOneHotFeature = class TOneHotFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TOneHotFeature();\n        $.Index = reader.int32_(position, 4, -1);\n        $.Values = reader.array(position, 6, Int32Array);\n        $.StringValues = reader.strings_(position, 8);\n        return $;\n    }\n};\n\nNCatBoostFbs.TFloatSplit = class TFloatSplit {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TFloatSplit();\n        $.Index = reader.int32(position + 0);\n        $.Border = reader.float32(position + 4);\n        return $;\n    }\n};\n\nNCatBoostFbs.TOneHotSplit = class TOneHotSplit {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TOneHotSplit();\n        $.Index = reader.int32(position + 0);\n        $.Value = reader.int32(position + 4);\n        return $;\n    }\n};\n\nNCatBoostFbs.TFeatureCombination = class TFeatureCombination {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TFeatureCombination();\n        $.CatFeatures = reader.array(position, 4, Int32Array);\n        $.FloatSplits = reader.structs(position, 6, NCatBoostFbs.TFloatSplit, 8);\n        $.OneHotSplits = reader.structs(position, 8, NCatBoostFbs.TOneHotSplit, 8);\n        return $;\n    }\n};\n\nNCatBoostFbs.ECtrType = {\n    Borders: 0, '0': 'Borders',\n    Buckets: 1, '1': 'Buckets',\n    BinarizedTargetMeanValue: 2, '2': 'BinarizedTargetMeanValue',\n    FloatTargetMeanValue: 3, '3': 'FloatTargetMeanValue',\n    Counter: 4, '4': 'Counter',\n    FeatureFreq: 5, '5': 'FeatureFreq'\n};\n\nNCatBoostFbs.TModelCtrBase = class TModelCtrBase {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TModelCtrBase();\n        $.FeatureCombination = reader.table(position, 4, NCatBoostFbs.TFeatureCombination);\n        $.CtrType = reader.int8_(position, 6, 0);\n        $.TargetBorderClassifierIdx = reader.int32_(position, 8, 0);\n        return $;\n    }\n};\n\nNCatBoostFbs.TModelCtr = class TModelCtr {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TModelCtr();\n        $.Base = reader.table(position, 4, NCatBoostFbs.TModelCtrBase);\n        $.TargetBorderIdx = reader.int32_(position, 6, 0);\n        $.PriorNum = reader.float32_(position, 8, 0);\n        $.PriorDenom = reader.float32_(position, 10, 1);\n        $.Shift = reader.float32_(position, 12, 0);\n        $.Scale = reader.float32_(position, 14, 1);\n        return $;\n    }\n};\n\nNCatBoostFbs.TCtrFeature = class TCtrFeature {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TCtrFeature();\n        $.Ctr = reader.table(position, 4, NCatBoostFbs.TModelCtr);\n        $.Borders = reader.array(position, 6, Float32Array);\n        return $;\n    }\n};\n\nNCatBoostFbs.TCtrValueTable = class TCtrValueTable {\n\n    static create(reader) {\n        return NCatBoostFbs.TCtrValueTable.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TCtrValueTable();\n        $.ModelCtrBase = reader.table(position, 4, NCatBoostFbs.TModelCtrBase);\n        $.IndexHashRaw = reader.array(position, 6, Uint8Array);\n        $.CTRBlob = reader.array(position, 8, Uint8Array);\n        $.CounterDenominator = reader.int32_(position, 10, 0);\n        $.TargetClassesCount = reader.int32_(position, 12, 0);\n        return $;\n    }\n};\n\nNCatBoostFbs.TKeyValue = class TKeyValue {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TKeyValue();\n        $.Key = reader.string_(position, 4, null);\n        $.Value = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nNCatBoostFbs.TNonSymmetricTreeStepNode = class TNonSymmetricTreeStepNode {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TNonSymmetricTreeStepNode();\n        $.LeftSubtreeDiff = reader.uint16(position + 0);\n        $.RightSubtreeDiff = reader.uint16(position + 2);\n        return $;\n    }\n};\n\nNCatBoostFbs.TRepackedBin = class TRepackedBin {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TRepackedBin();\n        $.FeatureIndex = reader.uint16(position + 0);\n        $.XorMask = reader.uint8(position + 2);\n        $.SplitIdx = reader.uint8(position + 3);\n        return $;\n    }\n};\n\nNCatBoostFbs.TModelTrees = class TModelTrees {\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TModelTrees();\n        $.ApproxDimension = reader.int32_(position, 4, 0);\n        $.TreeSplits = reader.array(position, 6, Int32Array);\n        $.TreeSizes = reader.array(position, 8, Int32Array);\n        $.TreeStartOffsets = reader.array(position, 10, Int32Array);\n        $.CatFeatures = reader.tables(position, 12, NCatBoostFbs.TCatFeature);\n        $.FloatFeatures = reader.tables(position, 14, NCatBoostFbs.TFloatFeature);\n        $.OneHotFeatures = reader.tables(position, 16, NCatBoostFbs.TOneHotFeature);\n        $.CtrFeatures = reader.tables(position, 18, NCatBoostFbs.TCtrFeature);\n        $.LeafValues = reader.array(position, 20, Float64Array);\n        $.LeafWeights = reader.array(position, 22, Float64Array);\n        $.NonSymmetricStepNodes = reader.structs(position, 24, NCatBoostFbs.TNonSymmetricTreeStepNode, 4);\n        $.NonSymmetricNodeIdToLeafId = reader.array(position, 26, Uint32Array);\n        $.TextFeatures = reader.tables(position, 28, NCatBoostFbs.TTextFeature);\n        $.EstimatedFeatures = reader.tables(position, 30, NCatBoostFbs.TEstimatedFeature);\n        $.Scale = reader.float64_(position, 32, 1);\n        $.Bias = reader.float64_(position, 34, 0);\n        $.MultiBias = reader.array(position, 36, Float64Array);\n        $.RepackedBins = reader.structs(position, 38, NCatBoostFbs.TRepackedBin, 4);\n        $.EmbeddingFeatures = reader.tables(position, 40, NCatBoostFbs.TEmbeddingFeature);\n        return $;\n    }\n};\n\nNCatBoostFbs.TModelCore = class TModelCore {\n\n    static create(reader) {\n        return NCatBoostFbs.TModelCore.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new NCatBoostFbs.TModelCore();\n        $.FormatVersion = reader.string_(position, 4, null);\n        $.ModelTrees = reader.table(position, 6, NCatBoostFbs.TModelTrees);\n        $.InfoMap = reader.tables(position, 8, NCatBoostFbs.TKeyValue);\n        $.ModelPartIds = reader.strings_(position, 10);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/catboost.js",
    "content": "\nimport * as flatbuffers from './flatbuffers.js';\nimport * as python from './python.js';\n\nconst catboost = {};\n\ncatboost.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        if (stream && stream.length > 4) {\n            const buffer = stream.peek(4);\n            const signature = Array.from(buffer).map((c) => String.fromCharCode(c)).join('');\n            if (signature === 'CBM1') {\n                return context.set('catboost.flatbuffers');\n            }\n        }\n        const obj = await context.peek('pkl');\n        if (obj && obj.__class__ && obj.__class__.__module__) {\n            const name = `${obj.__class__.__module__}.${obj.__class__.__name__}`;\n            if (name.startsWith('catboost.') || name.startsWith('autogluon.tabular.models.catboost.')) {\n                return context.set('catboost.pickle', obj);\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        switch (context.type) {\n            case 'catboost.flatbuffers': {\n                const stream = context.stream;\n                const buffer = stream.peek();\n                const execution = new python.Execution();\n                const obj = execution.invoke('catboost.CatBoostClassifier', []);\n                obj._object.flatbuffers = flatbuffers;\n                obj._object.schema = await context.require('./catboost-schema');\n                obj.load_model(buffer);\n                return new catboost.Model(obj._object);\n            }\n            case 'catboost.pickle': {\n                let obj = context.value;\n                const name = obj && obj.__class__ && obj.__class__.__module__ && obj.__class__.__name__ ? `${obj.__class__.__module__}.${obj.__class__.__name__}` : '';\n                if (name === 'autogluon.tabular.models.catboost.catboost_model.CatBoostModel') {\n                    obj = obj.model;\n                }\n                obj._object.flatbuffers = flatbuffers;\n                obj._object.schema = await context.require('./catboost-schema');\n                obj.load_model();\n                return new catboost.Model(obj._object);\n            }\n            default: {\n                throw new catboost.Error(`Unsupported CatBoost format '${context.type}'.`);\n            }\n        }\n    }\n};\n\ncatboost.Model = class {\n\n    constructor(obj) {\n        this.format = 'CatBoost';\n        this.metadata = [];\n        for (const [name, value] of obj._get_info_map()) {\n            this.metadata.push({ name, value });\n        }\n        this.modules = [new catboost.Graph(obj)];\n    }\n};\n\ncatboost.Graph = class {\n\n    constructor(obj) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const features = [];\n        for (const feature of obj._get_float_features()) {\n            const name = feature.FeatureId || `float_feature_${feature.FlatIndex}`;\n            const value = new catboost.Value(name, new catboost.TensorType('float32'));\n            features.push(value);\n            this.inputs.push(new catboost.Argument(name, [value]));\n        }\n        for (const feature of obj._get_cat_features()) {\n            const name = feature.FeatureId || `cat_feature_${feature.FlatIndex}`;\n            const value = new catboost.Value(name, new catboost.TensorType('int32'));\n            features.push(value);\n            this.inputs.push(new catboost.Argument(name, [value]));\n        }\n        for (const feature of obj._get_text_features()) {\n            const name = feature.FeatureId || `text_feature_${feature.FlatIndex}`;\n            const value = new catboost.Value(name, new catboost.TensorType('string'));\n            features.push(value);\n            this.inputs.push(new catboost.Argument(name, [value]));\n        }\n        for (const feature of obj._get_embedding_features()) {\n            const name = feature.FeatureId || `embedding_feature_${feature.FlatIndex}`;\n            const value = new catboost.Value(name, new catboost.TensorType('float32[]'));\n            features.push(value);\n            this.inputs.push(new catboost.Argument(name, [value]));\n        }\n        const node = new catboost.Node(obj, features);\n        this.nodes.push(node);\n    }\n};\n\ncatboost.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\ncatboost.Value = class {\n\n    constructor(name, type) {\n        this.name = name;\n        this.type = type || null;\n    }\n};\n\ncatboost.TensorType = class {\n\n    constructor(dataType) {\n        this.dataType = dataType;\n        this.shape = null;\n    }\n\n    toString() {\n        return this.dataType;\n    }\n};\n\ncatboost.Node = class {\n\n    constructor(obj, features) {\n        this.name = '';\n        this.type = { name: 'CatBoost' };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (features.length > 0) {\n            this.inputs.push(new catboost.Argument('features', features));\n        }\n        const treeCount = obj._get_tree_count();\n        if (treeCount > 0) {\n            this.attributes.push(new catboost.Argument('tree_count', treeCount));\n        }\n        const treeSizes = obj._get_tree_sizes();\n        if (treeSizes.length > 0) {\n            this.attributes.push(new catboost.Argument('tree_sizes', Array.from(treeSizes)));\n        }\n        const treeSplits = obj._get_tree_splits();\n        if (treeSplits.length > 0) {\n            this.attributes.push(new catboost.Argument('tree_splits', Array.from(treeSplits)));\n        }\n        const leafValues = obj._get_leaf_values();\n        if (leafValues.length > 0) {\n            this.attributes.push(new catboost.Argument('leaf_values', Array.from(leafValues)));\n        }\n        const leafWeights = obj._get_leaf_weights();\n        if (leafWeights.length > 0) {\n            this.attributes.push(new catboost.Argument('leaf_weights', Array.from(leafWeights)));\n        }\n        const borders = obj._get_borders();\n        if (borders.length > 0) {\n            this.attributes.push(new catboost.Argument('borders', borders));\n        }\n        const [scale, bias] = obj._get_scale_and_bias();\n        if (scale !== undefined && scale !== 1) {\n            this.attributes.push(new catboost.Argument('scale', scale));\n        }\n        if (bias !== undefined && bias !== 0) {\n            this.attributes.push(new catboost.Argument('bias', bias));\n        }\n    }\n};\n\ncatboost.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading CatBoost model.';\n    }\n};\n\nexport const ModelFactory = catboost.ModelFactory;\n"
  },
  {
    "path": "source/circle-metadata.json",
    "content": "[\n  {\n    \"name\": \"Add\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"pot_scale_int16\", \"type\": \"boolean\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\", \"type\": \"T\" },\n      { \"name\": \"B\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"attributes\": [\n      { \"name\": \"output_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"dimension\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMin\",\n    \"attributes\": [\n      { \"name\": \"output_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ]\n  },\n  {\n    \"name\": \"AveragePool2D\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"Padding\", \"default\": \"SAME\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"stride_w\", \"type\": \"int32\" },\n      { \"name\": \"stride_h\", \"type\": \"int32\" },\n      { \"name\": \"filter_width\", \"type\": \"int32\" },\n      { \"name\": \"filter_height\", \"type\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"BatchMatMul\",\n    \"attributes\": [\n      { \"name\": \"adjoint_lhs\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"adjoint_rhs\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"BidirectionalSequenceLSTM\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"cell_clip\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"proj_clip\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"merge_outputs\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"time_major\", \"type\": \"boolean\", \"default\": true },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"BidirectionalSequenceRNN\",\n    \"attributes\": [\n      { \"name\": \"time_major\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"merge_outputs\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Bucketize\",\n    \"attributes\": [\n      { \"name\": \"boundaries\", \"type\": \"float32[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Call\",\n    \"attributes\": [\n      { \"name\": \"subgraph\", \"type\": \"uint32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"CallOnce\",\n    \"attributes\": [\n      { \"name\": \"init_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Cast\",\n    \"attributes\": [\n      { \"name\": \"in_data_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" },\n      { \"name\": \"out_data_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConcatEmbeddings\",\n    \"attributes\": [\n      { \"name\": \"num_channels\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"num_columns_per_channel\", \"type\": \"int32[]\", \"default\": 0 },\n      { \"name\": \"embedding_dim_per_channel\", \"type\": \"int32[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Concatenation\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"inputs\", \"list\": true }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"Padding\", \"default\": \"SAME\", \"description\": \"`SAME`|`VALID`\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\", \"description\": \"`NONE`|`RELU`|`RELU6`\" },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 0, \"description\": \"stride of the filter window\" },\n      { \"name\": \"stride_h\", \"type\": \"int32\", \"default\": 0, \"description\": \"stride of the filter window\" },\n      { \"name\": \"dilation_w_factor\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"dilation_h_factor\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"quantized_bias_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"4D tensor\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\", \"description\": \"(optional)\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"result of 2D convolution of the input tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Cumsum\",\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"reverse\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Densify\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DepthToSpace\",\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"DepthwiseConv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"Padding\", \"default\": \"SAME\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"depth_multiplier\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_w_factor\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"dilation_h_factor\", \"type\": \"int32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"weights\", \"type\": \"T\" },\n      { \"name\": \"bias\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Dequantize\",\n    \"category\": \"Quantization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Div\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\", \"type\": \"T\" },\n      { \"name\": \"B\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"EmbeddingLookupSparse\",\n    \"attributes\": [\n      { \"name\": \"combiner\", \"type\": \"CombinerType\", \"default\": \"SUM\" }\n    ]\n  },\n  {\n    \"name\": \"Exp\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"axis_param\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ExtractFeatures\",\n    \"inputs\": [\n      { \"name\": \"ngrams\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"features\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuant\",\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"max\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"num_bits\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"narrow_range\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Fill\",\n    \"inputs\": [\n      { \"name\": \"dims\", \"type\": \"T\" },\n      { \"name\": \"value\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"FullyConnected\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"weights_format\", \"type\": \"FullyConnectedOptionsWeightsFormat\", \"default\": \"DEFAULT\" },\n      { \"name\": \"keep_num_dims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"quantized_bias_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"weights\", \"type\": \"T\" },\n      { \"name\": \"bias\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Gather\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"default\": 0, \"type\": \"int32\" },\n      { \"name\": \"batch_dims\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"positions\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Gelu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"approximate\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"HardSwish\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Hashtable\",\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"key_dtype\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" },\n      { \"name\": \"value_dtype\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ]\n  },\n  {\n    \"name\": \"HashtableLookup\",\n    \"inputs\": [\n      { \"name\": \"key\" },\n      { \"name\": \"keys\" },\n      { \"name\": \"values\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"value\" },\n      { \"name\": \"hits\" }\n    ]\n  },\n  {\n    \"name\": \"If\",\n    \"attributes\": [\n      { \"name\": \"then_subgraph_index\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"else_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"InstanceNorm\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" }\n    ]\n  },\n  {\n    \"name\": \"LeakyRelu\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LocalResponseNormalization\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"radius\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalOr\",\n    \"inputs\": [\n      { \"name\": \"A\", \"type\": \"T\" },\n      { \"name\": \"B\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Logistic\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LogSoftmax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"LSHProjection\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"LSHProjectionType\", \"default\": \"UNKNOWN\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"hash\" },\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"cell_clip\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"proj_clip\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"kernel_type\", \"type\": \"LSTMKernelType\", \"default\": \"FULL\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\", \"description\": \"Input tensor.\" },\n      { \"name\": \"input_input_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Input to input weights tensor.\", \"visible\": false },\n      { \"name\": \"input_forget_weights\", \"type\": \"T\", \"description\": \"Input to forget weights tensor.\", \"visible\": false },\n      { \"name\": \"input_cell_weights\", \"type\": \"T\", \"description\": \"Input to cell weights tensor.\", \"visible\": false },\n      { \"name\": \"input_output_weights\", \"type\": \"T\", \"description\": \"Input to output weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_input_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Recurrent to input weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_forget_weights\", \"type\": \"T\", \"description\": \"Recurrent to forget weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_cell_weights\", \"type\": \"T\", \"description\": \"Recurrent to cell weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_output_weights\", \"type\": \"T\", \"description\": \"Recurrent to output weights tensor.\", \"visible\": false },\n      { \"name\": \"cell_input_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Cell to input weights tensor.\", \"visible\": false },\n      { \"name\": \"cell_forget_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Cell to forget weights tensor.\", \"visible\": false },\n      { \"name\": \"cell_output_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Cell to output weights tensor.\", \"visible\": false },\n      { \"name\": \"input_gate_bias\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Input gate bias tensor.\", \"visible\": false },\n      { \"name\": \"forget_gate_bias\", \"type\": \"T\", \"description\": \"Forget gate bias tensor.\", \"visible\": false },\n      { \"name\": \"cell_gate_bias\", \"type\": \"T\", \"description\": \"Cell gate bias tensor.\", \"visible\": false },\n      { \"name\": \"output_gate_bias\", \"type\": \"T\", \"description\": \"Output gate bias tensor.\", \"visible\": false },\n      { \"name\": \"projection_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Projection weights tensor.\", \"visible\": false },\n      { \"name\": \"projection_bias\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Projection bias tensor.\", \"visible\": false }\n    ],\n    \"outputs\": [\n      { \"name\": \"scratch\", \"type\": \"T\" },\n      { \"name\": \"output_state\", \"type\": \"T\" },\n      { \"name\": \"cell_state\", \"type\": \"T\" },\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Maximum\",\n    \"inputs\": [\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"MaxPool2D\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"Padding\", \"default\": \"SAME\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"stride_w\", \"type\": \"int32\" },\n      { \"name\": \"stride_h\", \"type\": \"int32\" },\n      { \"name\": \"filter_width\", \"type\": \"int32\" },\n      { \"name\": \"filter_height\", \"type\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Mean\",\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"axis\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Minimum\",\n    \"inputs\": [\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"MirrorPad\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"MirrorPadMode\", \"default\": \"REFLECT\" }\n    ]\n  },\n  {\n    \"name\": \"Mul\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\", \"type\": \"T\" },\n      { \"name\": \"B\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Normalize\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NotEqual\",\n    \"inputs\": [\n      { \"name\": \"A\", \"type\": \"T\" },\n      { \"name\": \"B\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"OneHot\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Pack\",\n    \"attributes\": [\n      { \"name\": \"values_count\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Pad\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"paddings\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Predict\",\n    \"inputs\": [\n      { \"name\": \"hashes\" },\n      { \"name\": \"keys\" },\n      { \"name\": \"labels\" },\n      { \"name\": \"weights\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"label\" },\n      { \"name\": \"weight\" }\n    ]\n  },\n  {\n    \"name\": \"Prelu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"slope\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Quantize\",\n    \"category\": \"Quantization\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Range\",\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"start\", \"type\": \"T\" },\n      { \"name\": \"limit\", \"type\": \"T\" },\n      { \"name\": \"delta\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceMax\",\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"axis\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceMin\",\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"axis\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceWindow\",\n    \"attributes\": [\n      { \"name\": \"reduce_function\", \"type\": \"ReduceWindowFunction\", \"default\": \"UNSUPPORTED\" }\n    ]\n  },\n  {\n    \"name\": \"Relu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Relu6\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"new_shape\", \"type\": \"int32[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"data\", \"type\": \"T\" },\n      { \"name\": \"shape\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"reshaped\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeBilinear\",\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"default\": false, \"type\": \"boolean\" },\n      { \"name\": \"new_height\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"new_width\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"half_pixel_centers\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeNearestNeighbor\",\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"half_pixel_centers\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"ReverseSequence\",\n    \"attributes\": [\n      { \"name\": \"seq_dim\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"batch_dim\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"RmsNorm\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" }\n    ]\n  },\n  {\n    \"name\": \"RNN\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"X\", \"type\": \"T\" },\n      { \"name\": \"W\", \"type\": \"T\" },\n      { \"name\": \"R\", \"type\": \"T\" },\n      { \"name\": \"b\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"hidden\", \"type\": \"T\" },\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Rsqrt\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"RunModel\",\n    \"attributes\": [\n      { \"name\": \"location\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"signature\", \"type\": \"string\", \"default\": null }\n    ]\n  },\n  {\n    \"name\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"out_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ]\n  },\n  {\n    \"name\": \"Sin\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SkipGram\",\n    \"inputs\": [\n      { \"name\": \"inputs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"ngrams\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ngram_size\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"max_skip_size\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"include_all_ngrams\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Slice\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SpaceToDepth\",\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SparseToDense\",\n    \"attributes\": [\n      { \"name\": \"validate_indices\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Split\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_splits\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SplitV\",\n    \"attributes\": [\n      { \"name\": \"num_splits\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"squeeze_dims\", \"type\": \"int32[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloBroadcastInDim\",\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloCase\",\n    \"attributes\": [\n      { \"name\": \"branch_subgraph_indices\", \"type\": \"int32[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloCompare\",\n    \"attributes\": [\n      { \"name\": \"comparison_direction\", \"type\": \"StablehloComparisonDirection\", \"default\": \"STABLEHLO_COMPARISON_DIRECTION_EQ\" },\n      { \"name\": \"compare_type\", \"type\": \"StablehloComparisonType\", \"default\": \"STABLEHLO_COMPARISON_TYPE_NOTYPE\" }\n    ]\n  },\n  {\n    \"name\": \"StablehloConcatenate\",\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloConvolution\",\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"padding\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"lhs_dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"rhs_dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"window_reversal\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"input_batch_dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"input_feature_dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"input_spatial_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"kernel_input_feature_dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"kernel_output_feature_dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"kernel_spatial_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"output_batch_dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"output_feature_dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"output_spatial_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"feature_group_count\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"batch_group_count\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"precision_config\", \"type\": \"StablehloPrecisionConfig[]\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"StablehloCustomCall\",\n    \"attributes\": [\n      { \"name\": \"call_target_name\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"has_side_effect\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"backend_config\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"api_version\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"called_computations\", \"type\": \"int32[]\", \"default\": 0 },\n      { \"name\": \"custom_attributes\", \"type\": \"uint8[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloDotGeneral\",\n    \"attributes\": [\n      { \"name\": \"lhs_batching_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"rhs_batching_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"lhs_contracting_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"rhs_contracting_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"precision_config\", \"type\": \"StablehloPrecisionConfig[]\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"StablehloDynamicSlice\",\n    \"attributes\": [\n      { \"name\": \"slice_sizes\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloGather\",\n    \"attributes\": [\n      { \"name\": \"offset_dims\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"collapsed_slice_dims\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"start_index_map\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"index_vector_dim\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"slice_sizes\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"indices_are_sorted\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"StablehloIota\",\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloPad\",\n    \"attributes\": [\n      { \"name\": \"edge_padding_low\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"edge_padding_high\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"interior_padding\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloReduce\",\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"body_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloReduceWindow\",\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"window_strides\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"base_dilations\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"window_dilations\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"padding\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"body_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloRngBitGenerator\",\n    \"attributes\": [\n      { \"name\": \"algorithm\", \"type\": \"RngAlgorithm\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"StablehloScatter\",\n    \"attributes\": [\n      { \"name\": \"indices_are_sorted\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"update_window_dims\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"inserted_window_dims\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"scatter_dims_to_operand_dims\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"index_vector_dim\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"unique_indices\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"update_computation_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloSlice\",\n    \"attributes\": [\n      { \"name\": \"start_indices\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"limit_indices\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"strides\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloSort\",\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"is_stable\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"comparator_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloTranspose\",\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StablehloWhile\",\n    \"attributes\": [\n      { \"name\": \"cond_subgraph_index\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"body_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"StridedSlice\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"end\" },\n      { \"name\": \"strides\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"end_mask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"ellipsis_mask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"new_axis_mask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"offset\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Sub\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"pot_scale_int16\", \"type\": \"boolean\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\", \"type\": \"T\" },\n      { \"name\": \"B\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Sum\",\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"boolean\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"axis\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"SVDF\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"rank\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" },\n      { \"name\": \"feature\", \"type\": \"T\" },\n      { \"name\": \"time\", \"type\": \"T\" },\n      { \"name\": \"bias\", \"type\": \"T\" },\n      { \"name\": \"state\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"state_out\", \"type\": \"T\" },\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Tanh\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"T\" }\n    ]\n  },\n  {\n    \"name\": \"Tile\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"multipliers\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Transpose\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"perm\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"TransposeConv\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"Padding\", \"default\": \"SAME\" },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"quantized_bias_type\", \"type\": \"TensorType\", \"default\": \"FLOAT32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"output_shape\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"input\" },\n      { \"name\": \"bias\", \"optional\": true }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"UnidirectionalSequenceLSTM\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"ActivationFunctionType\", \"default\": \"NONE\" },\n      { \"name\": \"cell_clip\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"proj_clip\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"time_major\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"diagonal_recurrent_tensors\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"T\", \"description\": \"Input tensor.\" },\n      { \"name\": \"input_input_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Input to input weights tensor.\", \"visible\": false },\n      { \"name\": \"input_forget_weights\", \"type\": \"T\", \"description\": \"Input to forget weights tensor.\", \"visible\": false },\n      { \"name\": \"input_cell_weights\", \"type\": \"T\", \"description\": \"Input to cell weights tensor.\", \"visible\": false },\n      { \"name\": \"input_output_weights\", \"type\": \"T\", \"description\": \"Input to output weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_input_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Recurrent to input weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_forget_weights\", \"type\": \"T\", \"description\": \"Recurrent to forget weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_cell_weights\", \"type\": \"T\", \"description\": \"Recurrent to cell weights tensor.\", \"visible\": false },\n      { \"name\": \"recurrent_output_weights\", \"type\": \"T\", \"description\": \"Recurrent to output weights tensor.\", \"visible\": false },\n      { \"name\": \"cell_input_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Cell to input weights tensor.\", \"visible\": false },\n      { \"name\": \"cell_forget_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Cell to forget weights tensor.\", \"visible\": false },\n      { \"name\": \"cell_output_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Cell to output weights tensor.\", \"visible\": false },\n      { \"name\": \"input_gate_bias\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Input gate bias tensor.\", \"visible\": false },\n      { \"name\": \"forget_gate_bias\", \"type\": \"T\", \"description\": \"Forget gate bias tensor.\", \"visible\": false },\n      { \"name\": \"cell_gate_bias\", \"type\": \"T\", \"description\": \"Cell gate bias tensor.\", \"visible\": false },\n      { \"name\": \"output_gate_bias\", \"type\": \"T\", \"description\": \"Output gate bias tensor.\", \"visible\": false },\n      { \"name\": \"projection_weights\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Projection weights tensor.\", \"visible\": false },\n      { \"name\": \"projection_bias\", \"type\": \"T\", \"option\": \"optional\", \"description\": \"Projection bias tensor.\", \"visible\": false },\n      { \"name\": \"output_state_in\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"cell_state_in\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"activation\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"cell_clip\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"proj_clip\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"time_major\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"input_layer_norm_weights\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"forget_layer_norm_weights\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"cell_layer_norm_weights\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false },\n      { \"name\": \"output_layer_norm_weights\", \"type\": \"T\", \"option\": \"optional\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"Unique\",\n    \"attributes\": [\n      { \"name\": \"idx_out_type\", \"type\": \"TensorType\", \"default\": \"INT32\" }\n    ]\n  },\n  {\n    \"name\": \"Unpack\",\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"UnsortedSegmentProd\",\n    \"attributes\": [\n      { \"name\": \"num_segments\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"VarHandle\",\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"shared_name\", \"type\": \"string\", \"default\": null }\n    ]\n  },\n  {\n    \"name\": \"While\",\n    \"attributes\": [\n      { \"name\": \"cond_subgraph_index\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"body_subgraph_index\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  }\n]"
  },
  {
    "path": "source/circle-schema.js",
    "content": "\nexport const circle = {};\n\ncircle.TensorType = {\n    FLOAT32: 0, '0': 'FLOAT32',\n    FLOAT16: 1, '1': 'FLOAT16',\n    INT32: 2, '2': 'INT32',\n    UINT8: 3, '3': 'UINT8',\n    INT64: 4, '4': 'INT64',\n    STRING: 5, '5': 'STRING',\n    BOOL: 6, '6': 'BOOL',\n    INT16: 7, '7': 'INT16',\n    COMPLEX64: 8, '8': 'COMPLEX64',\n    INT8: 9, '9': 'INT8',\n    FLOAT64: 10, '10': 'FLOAT64',\n    COMPLEX128: 11, '11': 'COMPLEX128',\n    UINT64: 12, '12': 'UINT64',\n    RESOURCE: 13, '13': 'RESOURCE',\n    VARIANT: 14, '14': 'VARIANT',\n    UINT32: 15, '15': 'UINT32',\n    UINT16: 16, '16': 'UINT16',\n    INT4: 17, '17': 'INT4',\n    BFLOAT16: 18, '18': 'BFLOAT16',\n    UINT4: -1, '-1': 'UINT4',\n    GGML_Q4_0: -2, '-2': 'GGML_Q4_0',\n    GGML_Q4_1: -3, '-3': 'GGML_Q4_1',\n    GGML_Q8_0: -4, '-4': 'GGML_Q8_0',\n    GGML_Q8_1: -5, '-5': 'GGML_Q8_1',\n    MXFP4: -6, '-6': 'MXFP4',\n    MXINT8: -7, '-7': 'MXINT8'\n};\n\ncircle.CustomQuantization = class CustomQuantization {\n\n    static decode(reader, position) {\n        const $ = new circle.CustomQuantization();\n        $.custom = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.CustomQuantization();\n        $.custom = reader.array(json.custom, Uint8Array);\n        return $;\n    }\n};\n\ncircle.MXQuantization = class MXQuantization {\n\n    static decode(reader, position) {\n        const $ = new circle.MXQuantization();\n        $.axis = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.MXQuantization();\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\ncircle.QuantizationDetails = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return circle.CustomQuantization.decode(reader, position);\n            case 2: return circle.MXQuantization.decode(reader, position);\n            case 3: return circle.BlockwiseQuantization.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'CustomQuantization': return circle.CustomQuantization.decodeText(reader, json);\n            case 'MXQuantization': return circle.MXQuantization.decodeText(reader, json);\n            case 'BlockwiseQuantization': return circle.BlockwiseQuantization.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\ncircle.BlockwiseQuantization = class BlockwiseQuantization {\n\n    static decode(reader, position) {\n        const $ = new circle.BlockwiseQuantization();\n        $.scales = reader.int32_(position, 4, 0);\n        $.zero_points = reader.int32_(position, 6, 0);\n        $.block_size = reader.int32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BlockwiseQuantization();\n        $.scales = reader.value(json.scales, 0);\n        $.zero_points = reader.value(json.zero_points, 0);\n        $.block_size = reader.value(json.block_size, 0);\n        return $;\n    }\n};\n\ncircle.QuantizationParameters = class QuantizationParameters {\n\n    static decode(reader, position) {\n        const $ = new circle.QuantizationParameters();\n        $.min = reader.array(position, 4, Float32Array);\n        $.max = reader.array(position, 6, Float32Array);\n        $.scale = reader.array(position, 8, Float32Array);\n        $.zero_point = reader.int64s_(position, 10);\n        $.details = reader.union(position, 12, circle.QuantizationDetails);\n        $.quantized_dimension = reader.int32_(position, 16, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.QuantizationParameters();\n        $.min = reader.array(json.min, Float32Array);\n        $.max = reader.array(json.max, Float32Array);\n        $.scale = reader.array(json.scale, Float32Array);\n        $.zero_point = reader.array(json.zero_point);\n        $.details = circle.QuantizationDetails.decodeText(reader, json.details, json.details_type);\n        $.quantized_dimension = reader.value(json.quantized_dimension, 0);\n        return $;\n    }\n};\n\ncircle.DimensionType = {\n    DENSE: 0, '0': 'DENSE',\n    SPARSE_CSR: 1, '1': 'SPARSE_CSR'\n};\n\ncircle.Int32Vector = class Int32Vector {\n\n    static decode(reader, position) {\n        const $ = new circle.Int32Vector();\n        $.values = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Int32Vector();\n        $.values = reader.array(json.values, Int32Array);\n        return $;\n    }\n};\n\ncircle.Uint16Vector = class Uint16Vector {\n\n    static decode(reader, position) {\n        const $ = new circle.Uint16Vector();\n        $.values = reader.array(position, 4, Uint16Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Uint16Vector();\n        $.values = reader.array(json.values, Uint16Array);\n        return $;\n    }\n};\n\ncircle.Uint8Vector = class Uint8Vector {\n\n    static decode(reader, position) {\n        const $ = new circle.Uint8Vector();\n        $.values = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Uint8Vector();\n        $.values = reader.array(json.values, Uint8Array);\n        return $;\n    }\n};\n\ncircle.SparseIndexVector = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return circle.Int32Vector.decode(reader, position);\n            case 2: return circle.Uint16Vector.decode(reader, position);\n            case 3: return circle.Uint8Vector.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'Int32Vector': return circle.Int32Vector.decodeText(reader, json);\n            case 'Uint16Vector': return circle.Uint16Vector.decodeText(reader, json);\n            case 'Uint8Vector': return circle.Uint8Vector.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\ncircle.DimensionMetadata = class DimensionMetadata {\n\n    static decode(reader, position) {\n        const $ = new circle.DimensionMetadata();\n        $.format = reader.int8_(position, 4, 0);\n        $.dense_size = reader.int32_(position, 6, 0);\n        $.array_segments = reader.union(position, 8, circle.SparseIndexVector);\n        $.array_indices = reader.union(position, 12, circle.SparseIndexVector);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.DimensionMetadata();\n        $.format = circle.DimensionType[json.format];\n        $.dense_size = reader.value(json.dense_size, 0);\n        $.array_segments = circle.SparseIndexVector.decodeText(reader, json.array_segments, json.array_segments_type);\n        $.array_indices = circle.SparseIndexVector.decodeText(reader, json.array_indices, json.array_indices_type);\n        return $;\n    }\n};\n\ncircle.SparsityParameters = class SparsityParameters {\n\n    static decode(reader, position) {\n        const $ = new circle.SparsityParameters();\n        $.traversal_order = reader.array(position, 4, Int32Array);\n        $.block_map = reader.array(position, 6, Int32Array);\n        $.dim_metadata = reader.tables(position, 8, circle.DimensionMetadata);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SparsityParameters();\n        $.traversal_order = reader.array(json.traversal_order, Int32Array);\n        $.block_map = reader.array(json.block_map, Int32Array);\n        $.dim_metadata = reader.objects(json.dim_metadata, circle.DimensionMetadata);\n        return $;\n    }\n};\n\ncircle.VariantSubType = class VariantSubType {\n\n    static decode(reader, position) {\n        const $ = new circle.VariantSubType();\n        $.shape = reader.array(position, 4, Int32Array);\n        $.type = reader.int8_(position, 6, 0);\n        $.has_rank = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.VariantSubType();\n        $.shape = reader.array(json.shape, Int32Array);\n        $.type = circle.TensorType[json.type];\n        $.has_rank = reader.value(json.has_rank, false);\n        return $;\n    }\n};\n\ncircle.CompressionType = {\n    NONE: 0, '0': 'NONE',\n    HUFFMAN: 1, '1': 'HUFFMAN'\n};\n\ncircle.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new circle.Tensor();\n        $.shape = reader.array(position, 4, Int32Array);\n        $.type = reader.int8_(position, 6, 0);\n        $.buffer = reader.uint32_(position, 8, 0);\n        $.name = reader.string_(position, 10, null);\n        $.quantization = reader.table(position, 12, circle.QuantizationParameters);\n        $.is_variable = reader.bool_(position, 14, false);\n        $.sparsity = reader.table(position, 16, circle.SparsityParameters);\n        $.shape_signature = reader.array(position, 18, Int32Array);\n        $.has_rank = reader.bool_(position, 20, false);\n        $.variant_tensors = reader.tables(position, 22, circle.VariantSubType);\n        $.compression_type = reader.int8_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Tensor();\n        $.shape = reader.array(json.shape, Int32Array);\n        $.type = circle.TensorType[json.type];\n        $.buffer = reader.value(json.buffer, 0);\n        $.name = reader.value(json.name, null);\n        $.quantization = reader.object(json.quantization, circle.QuantizationParameters);\n        $.is_variable = reader.value(json.is_variable, false);\n        $.sparsity = reader.object(json.sparsity, circle.SparsityParameters);\n        $.shape_signature = reader.array(json.shape_signature, Int32Array);\n        $.has_rank = reader.value(json.has_rank, false);\n        $.variant_tensors = reader.objects(json.variant_tensors, circle.VariantSubType);\n        $.compression_type = circle.CompressionType[json.compression_type];\n        return $;\n    }\n};\n\ncircle.BuiltinOperator = {\n    ATTENTION: -9, '-9': 'ATTENTION',\n    RUN_MODEL: -8, '-8': 'RUN_MODEL',\n    ROPE: -7, '-7': 'ROPE',\n    RMS_NORM: -6, '-6': 'RMS_NORM',\n    GRU: -5, '-5': 'GRU',\n    BCQ_GATHER: -4, '-4': 'BCQ_GATHER',\n    BCQ_FULLY_CONNECTED: -3, '-3': 'BCQ_FULLY_CONNECTED',\n    INSTANCE_NORM: -2, '-2': 'INSTANCE_NORM',\n    ADD: 0, '0': 'ADD',\n    AVERAGE_POOL_2D: 1, '1': 'AVERAGE_POOL_2D',\n    CONCATENATION: 2, '2': 'CONCATENATION',\n    CONV_2D: 3, '3': 'CONV_2D',\n    DEPTHWISE_CONV_2D: 4, '4': 'DEPTHWISE_CONV_2D',\n    DEPTH_TO_SPACE: 5, '5': 'DEPTH_TO_SPACE',\n    DEQUANTIZE: 6, '6': 'DEQUANTIZE',\n    EMBEDDING_LOOKUP: 7, '7': 'EMBEDDING_LOOKUP',\n    FLOOR: 8, '8': 'FLOOR',\n    FULLY_CONNECTED: 9, '9': 'FULLY_CONNECTED',\n    HASHTABLE_LOOKUP: 10, '10': 'HASHTABLE_LOOKUP',\n    L2_NORMALIZATION: 11, '11': 'L2_NORMALIZATION',\n    L2_POOL_2D: 12, '12': 'L2_POOL_2D',\n    LOCAL_RESPONSE_NORMALIZATION: 13, '13': 'LOCAL_RESPONSE_NORMALIZATION',\n    LOGISTIC: 14, '14': 'LOGISTIC',\n    LSH_PROJECTION: 15, '15': 'LSH_PROJECTION',\n    LSTM: 16, '16': 'LSTM',\n    MAX_POOL_2D: 17, '17': 'MAX_POOL_2D',\n    MUL: 18, '18': 'MUL',\n    RELU: 19, '19': 'RELU',\n    RELU_N1_TO_1: 20, '20': 'RELU_N1_TO_1',\n    RELU6: 21, '21': 'RELU6',\n    RESHAPE: 22, '22': 'RESHAPE',\n    RESIZE_BILINEAR: 23, '23': 'RESIZE_BILINEAR',\n    RNN: 24, '24': 'RNN',\n    SOFTMAX: 25, '25': 'SOFTMAX',\n    SPACE_TO_DEPTH: 26, '26': 'SPACE_TO_DEPTH',\n    SVDF: 27, '27': 'SVDF',\n    TANH: 28, '28': 'TANH',\n    CONCAT_EMBEDDINGS: 29, '29': 'CONCAT_EMBEDDINGS',\n    SKIP_GRAM: 30, '30': 'SKIP_GRAM',\n    CALL: 31, '31': 'CALL',\n    CUSTOM: 32, '32': 'CUSTOM',\n    EMBEDDING_LOOKUP_SPARSE: 33, '33': 'EMBEDDING_LOOKUP_SPARSE',\n    PAD: 34, '34': 'PAD',\n    UNIDIRECTIONAL_SEQUENCE_RNN: 35, '35': 'UNIDIRECTIONAL_SEQUENCE_RNN',\n    GATHER: 36, '36': 'GATHER',\n    BATCH_TO_SPACE_ND: 37, '37': 'BATCH_TO_SPACE_ND',\n    SPACE_TO_BATCH_ND: 38, '38': 'SPACE_TO_BATCH_ND',\n    TRANSPOSE: 39, '39': 'TRANSPOSE',\n    MEAN: 40, '40': 'MEAN',\n    SUB: 41, '41': 'SUB',\n    DIV: 42, '42': 'DIV',\n    SQUEEZE: 43, '43': 'SQUEEZE',\n    UNIDIRECTIONAL_SEQUENCE_LSTM: 44, '44': 'UNIDIRECTIONAL_SEQUENCE_LSTM',\n    STRIDED_SLICE: 45, '45': 'STRIDED_SLICE',\n    BIDIRECTIONAL_SEQUENCE_RNN: 46, '46': 'BIDIRECTIONAL_SEQUENCE_RNN',\n    EXP: 47, '47': 'EXP',\n    TOPK_V2: 48, '48': 'TOPK_V2',\n    SPLIT: 49, '49': 'SPLIT',\n    LOG_SOFTMAX: 50, '50': 'LOG_SOFTMAX',\n    DELEGATE: 51, '51': 'DELEGATE',\n    BIDIRECTIONAL_SEQUENCE_LSTM: 52, '52': 'BIDIRECTIONAL_SEQUENCE_LSTM',\n    CAST: 53, '53': 'CAST',\n    PRELU: 54, '54': 'PRELU',\n    MAXIMUM: 55, '55': 'MAXIMUM',\n    ARG_MAX: 56, '56': 'ARG_MAX',\n    MINIMUM: 57, '57': 'MINIMUM',\n    LESS: 58, '58': 'LESS',\n    NEG: 59, '59': 'NEG',\n    PADV2: 60, '60': 'PADV2',\n    GREATER: 61, '61': 'GREATER',\n    GREATER_EQUAL: 62, '62': 'GREATER_EQUAL',\n    LESS_EQUAL: 63, '63': 'LESS_EQUAL',\n    SELECT: 64, '64': 'SELECT',\n    SLICE: 65, '65': 'SLICE',\n    SIN: 66, '66': 'SIN',\n    TRANSPOSE_CONV: 67, '67': 'TRANSPOSE_CONV',\n    SPARSE_TO_DENSE: 68, '68': 'SPARSE_TO_DENSE',\n    TILE: 69, '69': 'TILE',\n    EXPAND_DIMS: 70, '70': 'EXPAND_DIMS',\n    EQUAL: 71, '71': 'EQUAL',\n    NOT_EQUAL: 72, '72': 'NOT_EQUAL',\n    LOG: 73, '73': 'LOG',\n    SUM: 74, '74': 'SUM',\n    SQRT: 75, '75': 'SQRT',\n    RSQRT: 76, '76': 'RSQRT',\n    SHAPE: 77, '77': 'SHAPE',\n    POW: 78, '78': 'POW',\n    ARG_MIN: 79, '79': 'ARG_MIN',\n    FAKE_QUANT: 80, '80': 'FAKE_QUANT',\n    REDUCE_PROD: 81, '81': 'REDUCE_PROD',\n    REDUCE_MAX: 82, '82': 'REDUCE_MAX',\n    PACK: 83, '83': 'PACK',\n    LOGICAL_OR: 84, '84': 'LOGICAL_OR',\n    ONE_HOT: 85, '85': 'ONE_HOT',\n    LOGICAL_AND: 86, '86': 'LOGICAL_AND',\n    LOGICAL_NOT: 87, '87': 'LOGICAL_NOT',\n    UNPACK: 88, '88': 'UNPACK',\n    REDUCE_MIN: 89, '89': 'REDUCE_MIN',\n    FLOOR_DIV: 90, '90': 'FLOOR_DIV',\n    REDUCE_ANY: 91, '91': 'REDUCE_ANY',\n    SQUARE: 92, '92': 'SQUARE',\n    ZEROS_LIKE: 93, '93': 'ZEROS_LIKE',\n    FILL: 94, '94': 'FILL',\n    FLOOR_MOD: 95, '95': 'FLOOR_MOD',\n    RANGE: 96, '96': 'RANGE',\n    RESIZE_NEAREST_NEIGHBOR: 97, '97': 'RESIZE_NEAREST_NEIGHBOR',\n    LEAKY_RELU: 98, '98': 'LEAKY_RELU',\n    SQUARED_DIFFERENCE: 99, '99': 'SQUARED_DIFFERENCE',\n    MIRROR_PAD: 100, '100': 'MIRROR_PAD',\n    ABS: 101, '101': 'ABS',\n    SPLIT_V: 102, '102': 'SPLIT_V',\n    UNIQUE: 103, '103': 'UNIQUE',\n    CEIL: 104, '104': 'CEIL',\n    REVERSE_V2: 105, '105': 'REVERSE_V2',\n    ADD_N: 106, '106': 'ADD_N',\n    GATHER_ND: 107, '107': 'GATHER_ND',\n    COS: 108, '108': 'COS',\n    WHERE: 109, '109': 'WHERE',\n    RANK: 110, '110': 'RANK',\n    ELU: 111, '111': 'ELU',\n    REVERSE_SEQUENCE: 112, '112': 'REVERSE_SEQUENCE',\n    MATRIX_DIAG: 113, '113': 'MATRIX_DIAG',\n    QUANTIZE: 114, '114': 'QUANTIZE',\n    MATRIX_SET_DIAG: 115, '115': 'MATRIX_SET_DIAG',\n    ROUND: 116, '116': 'ROUND',\n    HARD_SWISH: 117, '117': 'HARD_SWISH',\n    IF: 118, '118': 'IF',\n    WHILE: 119, '119': 'WHILE',\n    NON_MAX_SUPPRESSION_V4: 120, '120': 'NON_MAX_SUPPRESSION_V4',\n    NON_MAX_SUPPRESSION_V5: 121, '121': 'NON_MAX_SUPPRESSION_V5',\n    SCATTER_ND: 122, '122': 'SCATTER_ND',\n    SELECT_V2: 123, '123': 'SELECT_V2',\n    DENSIFY: 124, '124': 'DENSIFY',\n    SEGMENT_SUM: 125, '125': 'SEGMENT_SUM',\n    BATCH_MATMUL: 126, '126': 'BATCH_MATMUL',\n    PLACEHOLDER_FOR_GREATER_OP_CODES: 127, '127': 'PLACEHOLDER_FOR_GREATER_OP_CODES',\n    CUMSUM: 128, '128': 'CUMSUM',\n    CALL_ONCE: 129, '129': 'CALL_ONCE',\n    BROADCAST_TO: 130, '130': 'BROADCAST_TO',\n    RFFT2D: 131, '131': 'RFFT2D',\n    CONV_3D: 132, '132': 'CONV_3D',\n    IMAG: 133, '133': 'IMAG',\n    REAL: 134, '134': 'REAL',\n    COMPLEX_ABS: 135, '135': 'COMPLEX_ABS',\n    HASHTABLE: 136, '136': 'HASHTABLE',\n    HASHTABLE_FIND: 137, '137': 'HASHTABLE_FIND',\n    HASHTABLE_IMPORT: 138, '138': 'HASHTABLE_IMPORT',\n    HASHTABLE_SIZE: 139, '139': 'HASHTABLE_SIZE',\n    REDUCE_ALL: 140, '140': 'REDUCE_ALL',\n    CONV_3D_TRANSPOSE: 141, '141': 'CONV_3D_TRANSPOSE',\n    VAR_HANDLE: 142, '142': 'VAR_HANDLE',\n    READ_VARIABLE: 143, '143': 'READ_VARIABLE',\n    ASSIGN_VARIABLE: 144, '144': 'ASSIGN_VARIABLE',\n    BROADCAST_ARGS: 145, '145': 'BROADCAST_ARGS',\n    RANDOM_STANDARD_NORMAL: 146, '146': 'RANDOM_STANDARD_NORMAL',\n    BUCKETIZE: 147, '147': 'BUCKETIZE',\n    RANDOM_UNIFORM: 148, '148': 'RANDOM_UNIFORM',\n    MULTINOMIAL: 149, '149': 'MULTINOMIAL',\n    GELU: 150, '150': 'GELU',\n    DYNAMIC_UPDATE_SLICE: 151, '151': 'DYNAMIC_UPDATE_SLICE',\n    RELU_0_TO_1: 152, '152': 'RELU_0_TO_1',\n    UNSORTED_SEGMENT_PROD: 153, '153': 'UNSORTED_SEGMENT_PROD',\n    UNSORTED_SEGMENT_MAX: 154, '154': 'UNSORTED_SEGMENT_MAX',\n    UNSORTED_SEGMENT_SUM: 155, '155': 'UNSORTED_SEGMENT_SUM',\n    ATAN2: 156, '156': 'ATAN2',\n    UNSORTED_SEGMENT_MIN: 157, '157': 'UNSORTED_SEGMENT_MIN',\n    SIGN: 158, '158': 'SIGN',\n    BITCAST: 159, '159': 'BITCAST',\n    BITWISE_XOR: 160, '160': 'BITWISE_XOR',\n    RIGHT_SHIFT: 161, '161': 'RIGHT_SHIFT',\n    STABLEHLO_LOGISTIC: 162, '162': 'STABLEHLO_LOGISTIC',\n    STABLEHLO_ADD: 163, '163': 'STABLEHLO_ADD',\n    STABLEHLO_DIVIDE: 164, '164': 'STABLEHLO_DIVIDE',\n    STABLEHLO_MULTIPLY: 165, '165': 'STABLEHLO_MULTIPLY',\n    STABLEHLO_MAXIMUM: 166, '166': 'STABLEHLO_MAXIMUM',\n    STABLEHLO_RESHAPE: 167, '167': 'STABLEHLO_RESHAPE',\n    STABLEHLO_CLAMP: 168, '168': 'STABLEHLO_CLAMP',\n    STABLEHLO_CONCATENATE: 169, '169': 'STABLEHLO_CONCATENATE',\n    STABLEHLO_BROADCAST_IN_DIM: 170, '170': 'STABLEHLO_BROADCAST_IN_DIM',\n    STABLEHLO_CONVOLUTION: 171, '171': 'STABLEHLO_CONVOLUTION',\n    STABLEHLO_SLICE: 172, '172': 'STABLEHLO_SLICE',\n    STABLEHLO_CUSTOM_CALL: 173, '173': 'STABLEHLO_CUSTOM_CALL',\n    STABLEHLO_REDUCE: 174, '174': 'STABLEHLO_REDUCE',\n    STABLEHLO_ABS: 175, '175': 'STABLEHLO_ABS',\n    STABLEHLO_AND: 176, '176': 'STABLEHLO_AND',\n    STABLEHLO_COSINE: 177, '177': 'STABLEHLO_COSINE',\n    STABLEHLO_EXPONENTIAL: 178, '178': 'STABLEHLO_EXPONENTIAL',\n    STABLEHLO_FLOOR: 179, '179': 'STABLEHLO_FLOOR',\n    STABLEHLO_LOG: 180, '180': 'STABLEHLO_LOG',\n    STABLEHLO_MINIMUM: 181, '181': 'STABLEHLO_MINIMUM',\n    STABLEHLO_NEGATE: 182, '182': 'STABLEHLO_NEGATE',\n    STABLEHLO_OR: 183, '183': 'STABLEHLO_OR',\n    STABLEHLO_POWER: 184, '184': 'STABLEHLO_POWER',\n    STABLEHLO_REMAINDER: 185, '185': 'STABLEHLO_REMAINDER',\n    STABLEHLO_RSQRT: 186, '186': 'STABLEHLO_RSQRT',\n    STABLEHLO_SELECT: 187, '187': 'STABLEHLO_SELECT',\n    STABLEHLO_SUBTRACT: 188, '188': 'STABLEHLO_SUBTRACT',\n    STABLEHLO_TANH: 189, '189': 'STABLEHLO_TANH',\n    STABLEHLO_SCATTER: 190, '190': 'STABLEHLO_SCATTER',\n    STABLEHLO_COMPARE: 191, '191': 'STABLEHLO_COMPARE',\n    STABLEHLO_CONVERT: 192, '192': 'STABLEHLO_CONVERT',\n    STABLEHLO_DYNAMIC_SLICE: 193, '193': 'STABLEHLO_DYNAMIC_SLICE',\n    STABLEHLO_DYNAMIC_UPDATE_SLICE: 194, '194': 'STABLEHLO_DYNAMIC_UPDATE_SLICE',\n    STABLEHLO_PAD: 195, '195': 'STABLEHLO_PAD',\n    STABLEHLO_IOTA: 196, '196': 'STABLEHLO_IOTA',\n    STABLEHLO_DOT_GENERAL: 197, '197': 'STABLEHLO_DOT_GENERAL',\n    STABLEHLO_REDUCE_WINDOW: 198, '198': 'STABLEHLO_REDUCE_WINDOW',\n    STABLEHLO_SORT: 199, '199': 'STABLEHLO_SORT',\n    STABLEHLO_WHILE: 200, '200': 'STABLEHLO_WHILE',\n    STABLEHLO_GATHER: 201, '201': 'STABLEHLO_GATHER',\n    STABLEHLO_TRANSPOSE: 202, '202': 'STABLEHLO_TRANSPOSE',\n    DILATE: 203, '203': 'DILATE',\n    STABLEHLO_RNG_BIT_GENERATOR: 204, '204': 'STABLEHLO_RNG_BIT_GENERATOR',\n    REDUCE_WINDOW: 205, '205': 'REDUCE_WINDOW',\n    STABLEHLO_COMPOSITE: 206, '206': 'STABLEHLO_COMPOSITE',\n    STABLEHLO_SHIFT_LEFT: 207, '207': 'STABLEHLO_SHIFT_LEFT',\n    STABLEHLO_CBRT: 208, '208': 'STABLEHLO_CBRT',\n    STABLEHLO_CASE: 209, '209': 'STABLEHLO_CASE'\n};\n\ncircle.BuiltinOptions = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return circle.Conv2DOptions.decode(reader, position);\n            case 2: return circle.DepthwiseConv2DOptions.decode(reader, position);\n            case 3: return circle.ConcatEmbeddingsOptions.decode(reader, position);\n            case 4: return circle.LSHProjectionOptions.decode(reader, position);\n            case 5: return circle.Pool2DOptions.decode(reader, position);\n            case 6: return circle.SVDFOptions.decode(reader, position);\n            case 7: return circle.RNNOptions.decode(reader, position);\n            case 8: return circle.FullyConnectedOptions.decode(reader, position);\n            case 9: return circle.SoftmaxOptions.decode(reader, position);\n            case 10: return circle.ConcatenationOptions.decode(reader, position);\n            case 11: return circle.AddOptions.decode(reader, position);\n            case 12: return circle.L2NormOptions.decode(reader, position);\n            case 13: return circle.LocalResponseNormalizationOptions.decode(reader, position);\n            case 14: return circle.LSTMOptions.decode(reader, position);\n            case 15: return circle.ResizeBilinearOptions.decode(reader, position);\n            case 16: return circle.CallOptions.decode(reader, position);\n            case 17: return circle.ReshapeOptions.decode(reader, position);\n            case 18: return circle.SkipGramOptions.decode(reader, position);\n            case 19: return circle.SpaceToDepthOptions.decode(reader, position);\n            case 20: return circle.EmbeddingLookupSparseOptions.decode(reader, position);\n            case 21: return circle.MulOptions.decode(reader, position);\n            case 22: return circle.PadOptions.decode(reader, position);\n            case 23: return circle.GatherOptions.decode(reader, position);\n            case 24: return circle.BatchToSpaceNDOptions.decode(reader, position);\n            case 25: return circle.SpaceToBatchNDOptions.decode(reader, position);\n            case 26: return circle.TransposeOptions.decode(reader, position);\n            case 27: return circle.ReducerOptions.decode(reader, position);\n            case 28: return circle.SubOptions.decode(reader, position);\n            case 29: return circle.DivOptions.decode(reader, position);\n            case 30: return circle.SqueezeOptions.decode(reader, position);\n            case 31: return circle.SequenceRNNOptions.decode(reader, position);\n            case 32: return circle.StridedSliceOptions.decode(reader, position);\n            case 33: return circle.ExpOptions.decode(reader, position);\n            case 34: return circle.TopKV2Options.decode(reader, position);\n            case 35: return circle.SplitOptions.decode(reader, position);\n            case 36: return circle.LogSoftmaxOptions.decode(reader, position);\n            case 37: return circle.CastOptions.decode(reader, position);\n            case 38: return circle.DequantizeOptions.decode(reader, position);\n            case 39: return circle.MaximumMinimumOptions.decode(reader, position);\n            case 40: return circle.ArgMaxOptions.decode(reader, position);\n            case 41: return circle.LessOptions.decode(reader, position);\n            case 42: return circle.NegOptions.decode(reader, position);\n            case 43: return circle.PadV2Options.decode(reader, position);\n            case 44: return circle.GreaterOptions.decode(reader, position);\n            case 45: return circle.GreaterEqualOptions.decode(reader, position);\n            case 46: return circle.LessEqualOptions.decode(reader, position);\n            case 47: return circle.SelectOptions.decode(reader, position);\n            case 48: return circle.SliceOptions.decode(reader, position);\n            case 49: return circle.TransposeConvOptions.decode(reader, position);\n            case 50: return circle.SparseToDenseOptions.decode(reader, position);\n            case 51: return circle.TileOptions.decode(reader, position);\n            case 52: return circle.ExpandDimsOptions.decode(reader, position);\n            case 53: return circle.EqualOptions.decode(reader, position);\n            case 54: return circle.NotEqualOptions.decode(reader, position);\n            case 55: return circle.ShapeOptions.decode(reader, position);\n            case 56: return circle.PowOptions.decode(reader, position);\n            case 57: return circle.ArgMinOptions.decode(reader, position);\n            case 58: return circle.FakeQuantOptions.decode(reader, position);\n            case 59: return circle.PackOptions.decode(reader, position);\n            case 60: return circle.LogicalOrOptions.decode(reader, position);\n            case 61: return circle.OneHotOptions.decode(reader, position);\n            case 62: return circle.LogicalAndOptions.decode(reader, position);\n            case 63: return circle.LogicalNotOptions.decode(reader, position);\n            case 64: return circle.UnpackOptions.decode(reader, position);\n            case 65: return circle.FloorDivOptions.decode(reader, position);\n            case 66: return circle.SquareOptions.decode(reader, position);\n            case 67: return circle.ZerosLikeOptions.decode(reader, position);\n            case 68: return circle.FillOptions.decode(reader, position);\n            case 69: return circle.BidirectionalSequenceLSTMOptions.decode(reader, position);\n            case 70: return circle.BidirectionalSequenceRNNOptions.decode(reader, position);\n            case 71: return circle.UnidirectionalSequenceLSTMOptions.decode(reader, position);\n            case 72: return circle.FloorModOptions.decode(reader, position);\n            case 73: return circle.RangeOptions.decode(reader, position);\n            case 74: return circle.ResizeNearestNeighborOptions.decode(reader, position);\n            case 75: return circle.LeakyReluOptions.decode(reader, position);\n            case 76: return circle.SquaredDifferenceOptions.decode(reader, position);\n            case 77: return circle.MirrorPadOptions.decode(reader, position);\n            case 78: return circle.AbsOptions.decode(reader, position);\n            case 79: return circle.SplitVOptions.decode(reader, position);\n            case 80: return circle.UniqueOptions.decode(reader, position);\n            case 81: return circle.ReverseV2Options.decode(reader, position);\n            case 82: return circle.AddNOptions.decode(reader, position);\n            case 83: return circle.GatherNdOptions.decode(reader, position);\n            case 84: return circle.CosOptions.decode(reader, position);\n            case 85: return circle.WhereOptions.decode(reader, position);\n            case 86: return circle.RankOptions.decode(reader, position);\n            case 87: return circle.ReverseSequenceOptions.decode(reader, position);\n            case 88: return circle.MatrixDiagOptions.decode(reader, position);\n            case 89: return circle.QuantizeOptions.decode(reader, position);\n            case 90: return circle.MatrixSetDiagOptions.decode(reader, position);\n            case 91: return circle.HardSwishOptions.decode(reader, position);\n            case 92: return circle.IfOptions.decode(reader, position);\n            case 93: return circle.WhileOptions.decode(reader, position);\n            case 94: return circle.DepthToSpaceOptions.decode(reader, position);\n            case 95: return circle.NonMaxSuppressionV4Options.decode(reader, position);\n            case 96: return circle.NonMaxSuppressionV5Options.decode(reader, position);\n            case 97: return circle.ScatterNdOptions.decode(reader, position);\n            case 98: return circle.SelectV2Options.decode(reader, position);\n            case 99: return circle.DensifyOptions.decode(reader, position);\n            case 100: return circle.SegmentSumOptions.decode(reader, position);\n            case 101: return circle.BatchMatMulOptions.decode(reader, position);\n            case 102: return circle.CumsumOptions.decode(reader, position);\n            case 103: return circle.CallOnceOptions.decode(reader, position);\n            case 104: return circle.BroadcastToOptions.decode(reader, position);\n            case 105: return circle.Rfft2dOptions.decode(reader, position);\n            case 106: return circle.Conv3DOptions.decode(reader, position);\n            case 107: return circle.HashtableOptions.decode(reader, position);\n            case 108: return circle.HashtableFindOptions.decode(reader, position);\n            case 109: return circle.HashtableImportOptions.decode(reader, position);\n            case 110: return circle.HashtableSizeOptions.decode(reader, position);\n            case 111: return circle.VarHandleOptions.decode(reader, position);\n            case 112: return circle.ReadVariableOptions.decode(reader, position);\n            case 113: return circle.AssignVariableOptions.decode(reader, position);\n            case 114: return circle.RandomOptions.decode(reader, position);\n            case 115: return circle.BucketizeOptions.decode(reader, position);\n            case 116: return circle.GeluOptions.decode(reader, position);\n            case 117: return circle.DynamicUpdateSliceOptions.decode(reader, position);\n            case 118: return circle.UnsortedSegmentProdOptions.decode(reader, position);\n            case 119: return circle.UnsortedSegmentMaxOptions.decode(reader, position);\n            case 120: return circle.UnsortedSegmentMinOptions.decode(reader, position);\n            case 121: return circle.UnsortedSegmentSumOptions.decode(reader, position);\n            case 122: return circle.ATan2Options.decode(reader, position);\n            case 123: return circle.SignOptions.decode(reader, position);\n            case 124: return circle.BitcastOptions.decode(reader, position);\n            case 125: return circle.BitwiseXorOptions.decode(reader, position);\n            case 126: return circle.RightShiftOptions.decode(reader, position);\n            case 247: return circle.AttentionOptions.decode(reader, position);\n            case 248: return circle.RunModelOptions.decode(reader, position);\n            case 249: return circle.RoPEOptions.decode(reader, position);\n            case 250: return circle.RmsNormOptions.decode(reader, position);\n            case 251: return circle.GRUOptions.decode(reader, position);\n            case 252: return circle.BCQGatherOptions.decode(reader, position);\n            case 253: return circle.BCQFullyConnectedOptions.decode(reader, position);\n            case 254: return circle.InstanceNormOptions.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'Conv2DOptions': return circle.Conv2DOptions.decodeText(reader, json);\n            case 'DepthwiseConv2DOptions': return circle.DepthwiseConv2DOptions.decodeText(reader, json);\n            case 'ConcatEmbeddingsOptions': return circle.ConcatEmbeddingsOptions.decodeText(reader, json);\n            case 'LSHProjectionOptions': return circle.LSHProjectionOptions.decodeText(reader, json);\n            case 'Pool2DOptions': return circle.Pool2DOptions.decodeText(reader, json);\n            case 'SVDFOptions': return circle.SVDFOptions.decodeText(reader, json);\n            case 'RNNOptions': return circle.RNNOptions.decodeText(reader, json);\n            case 'FullyConnectedOptions': return circle.FullyConnectedOptions.decodeText(reader, json);\n            case 'SoftmaxOptions': return circle.SoftmaxOptions.decodeText(reader, json);\n            case 'ConcatenationOptions': return circle.ConcatenationOptions.decodeText(reader, json);\n            case 'AddOptions': return circle.AddOptions.decodeText(reader, json);\n            case 'L2NormOptions': return circle.L2NormOptions.decodeText(reader, json);\n            case 'LocalResponseNormalizationOptions': return circle.LocalResponseNormalizationOptions.decodeText(reader, json);\n            case 'LSTMOptions': return circle.LSTMOptions.decodeText(reader, json);\n            case 'ResizeBilinearOptions': return circle.ResizeBilinearOptions.decodeText(reader, json);\n            case 'CallOptions': return circle.CallOptions.decodeText(reader, json);\n            case 'ReshapeOptions': return circle.ReshapeOptions.decodeText(reader, json);\n            case 'SkipGramOptions': return circle.SkipGramOptions.decodeText(reader, json);\n            case 'SpaceToDepthOptions': return circle.SpaceToDepthOptions.decodeText(reader, json);\n            case 'EmbeddingLookupSparseOptions': return circle.EmbeddingLookupSparseOptions.decodeText(reader, json);\n            case 'MulOptions': return circle.MulOptions.decodeText(reader, json);\n            case 'PadOptions': return circle.PadOptions.decodeText(reader, json);\n            case 'GatherOptions': return circle.GatherOptions.decodeText(reader, json);\n            case 'BatchToSpaceNDOptions': return circle.BatchToSpaceNDOptions.decodeText(reader, json);\n            case 'SpaceToBatchNDOptions': return circle.SpaceToBatchNDOptions.decodeText(reader, json);\n            case 'TransposeOptions': return circle.TransposeOptions.decodeText(reader, json);\n            case 'ReducerOptions': return circle.ReducerOptions.decodeText(reader, json);\n            case 'SubOptions': return circle.SubOptions.decodeText(reader, json);\n            case 'DivOptions': return circle.DivOptions.decodeText(reader, json);\n            case 'SqueezeOptions': return circle.SqueezeOptions.decodeText(reader, json);\n            case 'SequenceRNNOptions': return circle.SequenceRNNOptions.decodeText(reader, json);\n            case 'StridedSliceOptions': return circle.StridedSliceOptions.decodeText(reader, json);\n            case 'ExpOptions': return circle.ExpOptions.decodeText(reader, json);\n            case 'TopKV2Options': return circle.TopKV2Options.decodeText(reader, json);\n            case 'SplitOptions': return circle.SplitOptions.decodeText(reader, json);\n            case 'LogSoftmaxOptions': return circle.LogSoftmaxOptions.decodeText(reader, json);\n            case 'CastOptions': return circle.CastOptions.decodeText(reader, json);\n            case 'DequantizeOptions': return circle.DequantizeOptions.decodeText(reader, json);\n            case 'MaximumMinimumOptions': return circle.MaximumMinimumOptions.decodeText(reader, json);\n            case 'ArgMaxOptions': return circle.ArgMaxOptions.decodeText(reader, json);\n            case 'LessOptions': return circle.LessOptions.decodeText(reader, json);\n            case 'NegOptions': return circle.NegOptions.decodeText(reader, json);\n            case 'PadV2Options': return circle.PadV2Options.decodeText(reader, json);\n            case 'GreaterOptions': return circle.GreaterOptions.decodeText(reader, json);\n            case 'GreaterEqualOptions': return circle.GreaterEqualOptions.decodeText(reader, json);\n            case 'LessEqualOptions': return circle.LessEqualOptions.decodeText(reader, json);\n            case 'SelectOptions': return circle.SelectOptions.decodeText(reader, json);\n            case 'SliceOptions': return circle.SliceOptions.decodeText(reader, json);\n            case 'TransposeConvOptions': return circle.TransposeConvOptions.decodeText(reader, json);\n            case 'SparseToDenseOptions': return circle.SparseToDenseOptions.decodeText(reader, json);\n            case 'TileOptions': return circle.TileOptions.decodeText(reader, json);\n            case 'ExpandDimsOptions': return circle.ExpandDimsOptions.decodeText(reader, json);\n            case 'EqualOptions': return circle.EqualOptions.decodeText(reader, json);\n            case 'NotEqualOptions': return circle.NotEqualOptions.decodeText(reader, json);\n            case 'ShapeOptions': return circle.ShapeOptions.decodeText(reader, json);\n            case 'PowOptions': return circle.PowOptions.decodeText(reader, json);\n            case 'ArgMinOptions': return circle.ArgMinOptions.decodeText(reader, json);\n            case 'FakeQuantOptions': return circle.FakeQuantOptions.decodeText(reader, json);\n            case 'PackOptions': return circle.PackOptions.decodeText(reader, json);\n            case 'LogicalOrOptions': return circle.LogicalOrOptions.decodeText(reader, json);\n            case 'OneHotOptions': return circle.OneHotOptions.decodeText(reader, json);\n            case 'LogicalAndOptions': return circle.LogicalAndOptions.decodeText(reader, json);\n            case 'LogicalNotOptions': return circle.LogicalNotOptions.decodeText(reader, json);\n            case 'UnpackOptions': return circle.UnpackOptions.decodeText(reader, json);\n            case 'FloorDivOptions': return circle.FloorDivOptions.decodeText(reader, json);\n            case 'SquareOptions': return circle.SquareOptions.decodeText(reader, json);\n            case 'ZerosLikeOptions': return circle.ZerosLikeOptions.decodeText(reader, json);\n            case 'FillOptions': return circle.FillOptions.decodeText(reader, json);\n            case 'BidirectionalSequenceLSTMOptions': return circle.BidirectionalSequenceLSTMOptions.decodeText(reader, json);\n            case 'BidirectionalSequenceRNNOptions': return circle.BidirectionalSequenceRNNOptions.decodeText(reader, json);\n            case 'UnidirectionalSequenceLSTMOptions': return circle.UnidirectionalSequenceLSTMOptions.decodeText(reader, json);\n            case 'FloorModOptions': return circle.FloorModOptions.decodeText(reader, json);\n            case 'RangeOptions': return circle.RangeOptions.decodeText(reader, json);\n            case 'ResizeNearestNeighborOptions': return circle.ResizeNearestNeighborOptions.decodeText(reader, json);\n            case 'LeakyReluOptions': return circle.LeakyReluOptions.decodeText(reader, json);\n            case 'SquaredDifferenceOptions': return circle.SquaredDifferenceOptions.decodeText(reader, json);\n            case 'MirrorPadOptions': return circle.MirrorPadOptions.decodeText(reader, json);\n            case 'AbsOptions': return circle.AbsOptions.decodeText(reader, json);\n            case 'SplitVOptions': return circle.SplitVOptions.decodeText(reader, json);\n            case 'UniqueOptions': return circle.UniqueOptions.decodeText(reader, json);\n            case 'ReverseV2Options': return circle.ReverseV2Options.decodeText(reader, json);\n            case 'AddNOptions': return circle.AddNOptions.decodeText(reader, json);\n            case 'GatherNdOptions': return circle.GatherNdOptions.decodeText(reader, json);\n            case 'CosOptions': return circle.CosOptions.decodeText(reader, json);\n            case 'WhereOptions': return circle.WhereOptions.decodeText(reader, json);\n            case 'RankOptions': return circle.RankOptions.decodeText(reader, json);\n            case 'ReverseSequenceOptions': return circle.ReverseSequenceOptions.decodeText(reader, json);\n            case 'MatrixDiagOptions': return circle.MatrixDiagOptions.decodeText(reader, json);\n            case 'QuantizeOptions': return circle.QuantizeOptions.decodeText(reader, json);\n            case 'MatrixSetDiagOptions': return circle.MatrixSetDiagOptions.decodeText(reader, json);\n            case 'HardSwishOptions': return circle.HardSwishOptions.decodeText(reader, json);\n            case 'IfOptions': return circle.IfOptions.decodeText(reader, json);\n            case 'WhileOptions': return circle.WhileOptions.decodeText(reader, json);\n            case 'DepthToSpaceOptions': return circle.DepthToSpaceOptions.decodeText(reader, json);\n            case 'NonMaxSuppressionV4Options': return circle.NonMaxSuppressionV4Options.decodeText(reader, json);\n            case 'NonMaxSuppressionV5Options': return circle.NonMaxSuppressionV5Options.decodeText(reader, json);\n            case 'ScatterNdOptions': return circle.ScatterNdOptions.decodeText(reader, json);\n            case 'SelectV2Options': return circle.SelectV2Options.decodeText(reader, json);\n            case 'DensifyOptions': return circle.DensifyOptions.decodeText(reader, json);\n            case 'SegmentSumOptions': return circle.SegmentSumOptions.decodeText(reader, json);\n            case 'BatchMatMulOptions': return circle.BatchMatMulOptions.decodeText(reader, json);\n            case 'CumsumOptions': return circle.CumsumOptions.decodeText(reader, json);\n            case 'CallOnceOptions': return circle.CallOnceOptions.decodeText(reader, json);\n            case 'BroadcastToOptions': return circle.BroadcastToOptions.decodeText(reader, json);\n            case 'Rfft2dOptions': return circle.Rfft2dOptions.decodeText(reader, json);\n            case 'Conv3DOptions': return circle.Conv3DOptions.decodeText(reader, json);\n            case 'HashtableOptions': return circle.HashtableOptions.decodeText(reader, json);\n            case 'HashtableFindOptions': return circle.HashtableFindOptions.decodeText(reader, json);\n            case 'HashtableImportOptions': return circle.HashtableImportOptions.decodeText(reader, json);\n            case 'HashtableSizeOptions': return circle.HashtableSizeOptions.decodeText(reader, json);\n            case 'VarHandleOptions': return circle.VarHandleOptions.decodeText(reader, json);\n            case 'ReadVariableOptions': return circle.ReadVariableOptions.decodeText(reader, json);\n            case 'AssignVariableOptions': return circle.AssignVariableOptions.decodeText(reader, json);\n            case 'RandomOptions': return circle.RandomOptions.decodeText(reader, json);\n            case 'BucketizeOptions': return circle.BucketizeOptions.decodeText(reader, json);\n            case 'GeluOptions': return circle.GeluOptions.decodeText(reader, json);\n            case 'DynamicUpdateSliceOptions': return circle.DynamicUpdateSliceOptions.decodeText(reader, json);\n            case 'UnsortedSegmentProdOptions': return circle.UnsortedSegmentProdOptions.decodeText(reader, json);\n            case 'UnsortedSegmentMaxOptions': return circle.UnsortedSegmentMaxOptions.decodeText(reader, json);\n            case 'UnsortedSegmentMinOptions': return circle.UnsortedSegmentMinOptions.decodeText(reader, json);\n            case 'UnsortedSegmentSumOptions': return circle.UnsortedSegmentSumOptions.decodeText(reader, json);\n            case 'ATan2Options': return circle.ATan2Options.decodeText(reader, json);\n            case 'SignOptions': return circle.SignOptions.decodeText(reader, json);\n            case 'BitcastOptions': return circle.BitcastOptions.decodeText(reader, json);\n            case 'BitwiseXorOptions': return circle.BitwiseXorOptions.decodeText(reader, json);\n            case 'RightShiftOptions': return circle.RightShiftOptions.decodeText(reader, json);\n            case 'AttentionOptions': return circle.AttentionOptions.decodeText(reader, json);\n            case 'RunModelOptions': return circle.RunModelOptions.decodeText(reader, json);\n            case 'RoPEOptions': return circle.RoPEOptions.decodeText(reader, json);\n            case 'RmsNormOptions': return circle.RmsNormOptions.decodeText(reader, json);\n            case 'GRUOptions': return circle.GRUOptions.decodeText(reader, json);\n            case 'BCQGatherOptions': return circle.BCQGatherOptions.decodeText(reader, json);\n            case 'BCQFullyConnectedOptions': return circle.BCQFullyConnectedOptions.decodeText(reader, json);\n            case 'InstanceNormOptions': return circle.InstanceNormOptions.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\ncircle.BuiltinOptions2 = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return circle.StablehloConcatenateOptions.decode(reader, position);\n            case 2: return circle.StablehloBroadcastInDimOptions.decode(reader, position);\n            case 3: return circle.StablehloSliceOptions.decode(reader, position);\n            case 4: return circle.StablehloConvolutionOptions.decode(reader, position);\n            case 5: return circle.StablehloCustomCallOptions.decode(reader, position);\n            case 6: return circle.StablehloReduceOptions.decode(reader, position);\n            case 7: return circle.StablehloScatterOptions.decode(reader, position);\n            case 8: return circle.StablehloCompareOptions.decode(reader, position);\n            case 9: return circle.StablehloDynamicSliceOptions.decode(reader, position);\n            case 10: return circle.StablehloPadOptions.decode(reader, position);\n            case 11: return circle.StablehloIotaOptions.decode(reader, position);\n            case 12: return circle.StablehloDotGeneralOptions.decode(reader, position);\n            case 13: return circle.StablehloReduceWindowOptions.decode(reader, position);\n            case 14: return circle.StablehloSortOptions.decode(reader, position);\n            case 15: return circle.StablehloWhileOptions.decode(reader, position);\n            case 16: return circle.StablehloGatherOptions.decode(reader, position);\n            case 17: return circle.StablehloTransposeOptions.decode(reader, position);\n            case 18: return circle.DilateOptions.decode(reader, position);\n            case 19: return circle.StablehloRngBitGeneratorOptions.decode(reader, position);\n            case 20: return circle.ReduceWindowOptions.decode(reader, position);\n            case 21: return circle.StableHLOCompositeOptions.decode(reader, position);\n            case 22: return circle.StablehloShiftLeftOptions.decode(reader, position);\n            case 23: return circle.StablehloCaseOptions.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'StablehloConcatenateOptions': return circle.StablehloConcatenateOptions.decodeText(reader, json);\n            case 'StablehloBroadcastInDimOptions': return circle.StablehloBroadcastInDimOptions.decodeText(reader, json);\n            case 'StablehloSliceOptions': return circle.StablehloSliceOptions.decodeText(reader, json);\n            case 'StablehloConvolutionOptions': return circle.StablehloConvolutionOptions.decodeText(reader, json);\n            case 'StablehloCustomCallOptions': return circle.StablehloCustomCallOptions.decodeText(reader, json);\n            case 'StablehloReduceOptions': return circle.StablehloReduceOptions.decodeText(reader, json);\n            case 'StablehloScatterOptions': return circle.StablehloScatterOptions.decodeText(reader, json);\n            case 'StablehloCompareOptions': return circle.StablehloCompareOptions.decodeText(reader, json);\n            case 'StablehloDynamicSliceOptions': return circle.StablehloDynamicSliceOptions.decodeText(reader, json);\n            case 'StablehloPadOptions': return circle.StablehloPadOptions.decodeText(reader, json);\n            case 'StablehloIotaOptions': return circle.StablehloIotaOptions.decodeText(reader, json);\n            case 'StablehloDotGeneralOptions': return circle.StablehloDotGeneralOptions.decodeText(reader, json);\n            case 'StablehloReduceWindowOptions': return circle.StablehloReduceWindowOptions.decodeText(reader, json);\n            case 'StablehloSortOptions': return circle.StablehloSortOptions.decodeText(reader, json);\n            case 'StablehloWhileOptions': return circle.StablehloWhileOptions.decodeText(reader, json);\n            case 'StablehloGatherOptions': return circle.StablehloGatherOptions.decodeText(reader, json);\n            case 'StablehloTransposeOptions': return circle.StablehloTransposeOptions.decodeText(reader, json);\n            case 'DilateOptions': return circle.DilateOptions.decodeText(reader, json);\n            case 'StablehloRngBitGeneratorOptions': return circle.StablehloRngBitGeneratorOptions.decodeText(reader, json);\n            case 'ReduceWindowOptions': return circle.ReduceWindowOptions.decodeText(reader, json);\n            case 'StableHLOCompositeOptions': return circle.StableHLOCompositeOptions.decodeText(reader, json);\n            case 'StablehloShiftLeftOptions': return circle.StablehloShiftLeftOptions.decodeText(reader, json);\n            case 'StablehloCaseOptions': return circle.StablehloCaseOptions.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\ncircle.StablehloGatherOptions = class StablehloGatherOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloGatherOptions();\n        $.offset_dims = reader.int64s_(position, 4);\n        $.collapsed_slice_dims = reader.int64s_(position, 6);\n        $.start_index_map = reader.int64s_(position, 8);\n        $.index_vector_dim = reader.int64_(position, 10, 0n);\n        $.slice_sizes = reader.int64s_(position, 12);\n        $.indices_are_sorted = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloGatherOptions();\n        $.offset_dims = reader.array(json.offset_dims);\n        $.collapsed_slice_dims = reader.array(json.collapsed_slice_dims);\n        $.start_index_map = reader.array(json.start_index_map);\n        $.index_vector_dim = reader.int64(json.index_vector_dim, 0n);\n        $.slice_sizes = reader.array(json.slice_sizes);\n        $.indices_are_sorted = reader.value(json.indices_are_sorted, false);\n        return $;\n    }\n};\n\ncircle.StablehloTransposeOptions = class StablehloTransposeOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloTransposeOptions();\n        $.permutation = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloTransposeOptions();\n        $.permutation = reader.array(json.permutation);\n        return $;\n    }\n};\n\ncircle.StablehloPrecisionConfig = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    HIGH: 1, '1': 'HIGH',\n    HIGHEST: 2, '2': 'HIGHEST'\n};\n\ncircle.StablehloDotGeneralOptions = class StablehloDotGeneralOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloDotGeneralOptions();\n        $.lhs_batching_dimensions = reader.int64s_(position, 4);\n        $.rhs_batching_dimensions = reader.int64s_(position, 6);\n        $.lhs_contracting_dimensions = reader.int64s_(position, 8);\n        $.rhs_contracting_dimensions = reader.int64s_(position, 10);\n        $.precision_config = reader.array(position, 12, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloDotGeneralOptions();\n        $.lhs_batching_dimensions = reader.array(json.lhs_batching_dimensions);\n        $.rhs_batching_dimensions = reader.array(json.rhs_batching_dimensions);\n        $.lhs_contracting_dimensions = reader.array(json.lhs_contracting_dimensions);\n        $.rhs_contracting_dimensions = reader.array(json.rhs_contracting_dimensions);\n        $.precision_config = reader.objects(json.precision_config, circle.StablehloPrecisionConfig);\n        return $;\n    }\n};\n\ncircle.StablehloReduceWindowOptions = class StablehloReduceWindowOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloReduceWindowOptions();\n        $.window_dimensions = reader.int64s_(position, 4);\n        $.window_strides = reader.int64s_(position, 6);\n        $.base_dilations = reader.int64s_(position, 8);\n        $.window_dilations = reader.int64s_(position, 10);\n        $.padding = reader.int64s_(position, 12);\n        $.body_subgraph_index = reader.int32_(position, 14, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloReduceWindowOptions();\n        $.window_dimensions = reader.array(json.window_dimensions);\n        $.window_strides = reader.array(json.window_strides);\n        $.base_dilations = reader.array(json.base_dilations);\n        $.window_dilations = reader.array(json.window_dilations);\n        $.padding = reader.array(json.padding);\n        $.body_subgraph_index = reader.value(json.body_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.StablehloWhileOptions = class StablehloWhileOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloWhileOptions();\n        $.cond_subgraph_index = reader.int32_(position, 4, 0);\n        $.body_subgraph_index = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloWhileOptions();\n        $.cond_subgraph_index = reader.value(json.cond_subgraph_index, 0);\n        $.body_subgraph_index = reader.value(json.body_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.StablehloSortOptions = class StablehloSortOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloSortOptions();\n        $.dimension = reader.int64_(position, 4, 0n);\n        $.is_stable = reader.bool_(position, 6, false);\n        $.comparator_subgraph_index = reader.int32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloSortOptions();\n        $.dimension = reader.int64(json.dimension, 0n);\n        $.is_stable = reader.value(json.is_stable, false);\n        $.comparator_subgraph_index = reader.value(json.comparator_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.StablehloConcatenateOptions = class StablehloConcatenateOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloConcatenateOptions();\n        $.dimension = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloConcatenateOptions();\n        $.dimension = reader.int64(json.dimension, 0n);\n        return $;\n    }\n};\n\ncircle.StablehloBroadcastInDimOptions = class StablehloBroadcastInDimOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloBroadcastInDimOptions();\n        $.broadcast_dimensions = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloBroadcastInDimOptions();\n        $.broadcast_dimensions = reader.array(json.broadcast_dimensions);\n        return $;\n    }\n};\n\ncircle.StablehloComparisonDirection = {\n    STABLEHLO_COMPARISON_DIRECTION_EQ: 0, '0': 'STABLEHLO_COMPARISON_DIRECTION_EQ',\n    STABLEHLO_COMPARISON_DIRECTION_NE: 1, '1': 'STABLEHLO_COMPARISON_DIRECTION_NE',\n    STABLEHLO_COMPARISON_DIRECTION_GE: 2, '2': 'STABLEHLO_COMPARISON_DIRECTION_GE',\n    STABLEHLO_COMPARISON_DIRECTION_GT: 3, '3': 'STABLEHLO_COMPARISON_DIRECTION_GT',\n    STABLEHLO_COMPARISON_DIRECTION_LE: 4, '4': 'STABLEHLO_COMPARISON_DIRECTION_LE',\n    STABLEHLO_COMPARISON_DIRECTION_LT: 5, '5': 'STABLEHLO_COMPARISON_DIRECTION_LT'\n};\n\ncircle.StablehloComparisonType = {\n    STABLEHLO_COMPARISON_TYPE_NOTYPE: 0, '0': 'STABLEHLO_COMPARISON_TYPE_NOTYPE',\n    STABLEHLO_COMPARISON_TYPE_FLOAT: 1, '1': 'STABLEHLO_COMPARISON_TYPE_FLOAT',\n    STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER: 2, '2': 'STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER',\n    STABLEHLO_COMPARISON_TYPE_SIGNED: 3, '3': 'STABLEHLO_COMPARISON_TYPE_SIGNED',\n    STABLEHLO_COMPARISON_TYPE_UNSIGNED: 4, '4': 'STABLEHLO_COMPARISON_TYPE_UNSIGNED'\n};\n\ncircle.StablehloCompareOptions = class StablehloCompareOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloCompareOptions();\n        $.comparison_direction = reader.uint32_(position, 4, 0);\n        $.compare_type = reader.uint32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloCompareOptions();\n        $.comparison_direction = circle.StablehloComparisonDirection[json.comparison_direction];\n        $.compare_type = circle.StablehloComparisonType[json.compare_type];\n        return $;\n    }\n};\n\ncircle.StablehloDynamicSliceOptions = class StablehloDynamicSliceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloDynamicSliceOptions();\n        $.slice_sizes = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloDynamicSliceOptions();\n        $.slice_sizes = reader.array(json.slice_sizes);\n        return $;\n    }\n};\n\ncircle.StablehloPadOptions = class StablehloPadOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloPadOptions();\n        $.edge_padding_low = reader.int64s_(position, 4);\n        $.edge_padding_high = reader.int64s_(position, 6);\n        $.interior_padding = reader.int64s_(position, 8);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloPadOptions();\n        $.edge_padding_low = reader.array(json.edge_padding_low);\n        $.edge_padding_high = reader.array(json.edge_padding_high);\n        $.interior_padding = reader.array(json.interior_padding);\n        return $;\n    }\n};\n\ncircle.StablehloIotaOptions = class StablehloIotaOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloIotaOptions();\n        $.iota_dimension = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloIotaOptions();\n        $.iota_dimension = reader.int64(json.iota_dimension, 0n);\n        return $;\n    }\n};\n\ncircle.StablehloCustomCallOptions = class StablehloCustomCallOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloCustomCallOptions();\n        $.call_target_name = reader.string_(position, 4, null);\n        $.has_side_effect = reader.bool_(position, 6, false);\n        $.backend_config = reader.string_(position, 8, null);\n        $.api_version = reader.int32_(position, 10, 0);\n        $.called_computations = reader.array(position, 12, Int32Array);\n        $.custom_attributes = reader.array(position, 14, Uint8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloCustomCallOptions();\n        $.call_target_name = reader.value(json.call_target_name, null);\n        $.has_side_effect = reader.value(json.has_side_effect, false);\n        $.backend_config = reader.value(json.backend_config, null);\n        $.api_version = reader.value(json.api_version, 0);\n        $.called_computations = reader.array(json.called_computations, Int32Array);\n        $.custom_attributes = reader.array(json.custom_attributes, Uint8Array);\n        return $;\n    }\n};\n\ncircle.StablehloReduceOptions = class StablehloReduceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloReduceOptions();\n        $.dimensions = reader.int64s_(position, 4);\n        $.body_subgraph_index = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloReduceOptions();\n        $.dimensions = reader.array(json.dimensions);\n        $.body_subgraph_index = reader.value(json.body_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.StablehloSliceOptions = class StablehloSliceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloSliceOptions();\n        $.start_indices = reader.int64s_(position, 4);\n        $.limit_indices = reader.int64s_(position, 6);\n        $.strides = reader.int64s_(position, 8);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloSliceOptions();\n        $.start_indices = reader.array(json.start_indices);\n        $.limit_indices = reader.array(json.limit_indices);\n        $.strides = reader.array(json.strides);\n        return $;\n    }\n};\n\ncircle.StablehloConvolutionOptions = class StablehloConvolutionOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloConvolutionOptions();\n        $.window_strides = reader.int64s_(position, 4);\n        $.padding = reader.int64s_(position, 6);\n        $.lhs_dilation = reader.int64s_(position, 8);\n        $.rhs_dilation = reader.int64s_(position, 10);\n        $.window_reversal = reader.bools_(position, 12);\n        $.input_batch_dimension = reader.int64_(position, 14, 0n);\n        $.input_feature_dimension = reader.int64_(position, 16, 0n);\n        $.input_spatial_dimensions = reader.int64s_(position, 18);\n        $.kernel_input_feature_dimension = reader.int64_(position, 20, 0n);\n        $.kernel_output_feature_dimension = reader.int64_(position, 22, 0n);\n        $.kernel_spatial_dimensions = reader.int64s_(position, 24);\n        $.output_batch_dimension = reader.int64_(position, 26, 0n);\n        $.output_feature_dimension = reader.int64_(position, 28, 0n);\n        $.output_spatial_dimensions = reader.int64s_(position, 30);\n        $.feature_group_count = reader.int64_(position, 32, 0n);\n        $.batch_group_count = reader.int64_(position, 34, 0n);\n        $.precision_config = reader.array(position, 36, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloConvolutionOptions();\n        $.window_strides = reader.array(json.window_strides);\n        $.padding = reader.array(json.padding);\n        $.lhs_dilation = reader.array(json.lhs_dilation);\n        $.rhs_dilation = reader.array(json.rhs_dilation);\n        $.window_reversal = reader.array(json.window_reversal);\n        $.input_batch_dimension = reader.int64(json.input_batch_dimension, 0n);\n        $.input_feature_dimension = reader.int64(json.input_feature_dimension, 0n);\n        $.input_spatial_dimensions = reader.array(json.input_spatial_dimensions);\n        $.kernel_input_feature_dimension = reader.int64(json.kernel_input_feature_dimension, 0n);\n        $.kernel_output_feature_dimension = reader.int64(json.kernel_output_feature_dimension, 0n);\n        $.kernel_spatial_dimensions = reader.array(json.kernel_spatial_dimensions);\n        $.output_batch_dimension = reader.int64(json.output_batch_dimension, 0n);\n        $.output_feature_dimension = reader.int64(json.output_feature_dimension, 0n);\n        $.output_spatial_dimensions = reader.array(json.output_spatial_dimensions);\n        $.feature_group_count = reader.int64(json.feature_group_count, 0n);\n        $.batch_group_count = reader.int64(json.batch_group_count, 0n);\n        $.precision_config = reader.objects(json.precision_config, circle.StablehloPrecisionConfig);\n        return $;\n    }\n};\n\ncircle.StablehloScatterOptions = class StablehloScatterOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloScatterOptions();\n        $.indices_are_sorted = reader.bool_(position, 4, false);\n        $.update_window_dims = reader.int64s_(position, 6);\n        $.inserted_window_dims = reader.int64s_(position, 8);\n        $.scatter_dims_to_operand_dims = reader.int64s_(position, 10);\n        $.index_vector_dim = reader.int64_(position, 12, 0n);\n        $.unique_indices = reader.bool_(position, 14, false);\n        $.update_computation_subgraph_index = reader.int32_(position, 16, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloScatterOptions();\n        $.indices_are_sorted = reader.value(json.indices_are_sorted, false);\n        $.update_window_dims = reader.array(json.update_window_dims);\n        $.inserted_window_dims = reader.array(json.inserted_window_dims);\n        $.scatter_dims_to_operand_dims = reader.array(json.scatter_dims_to_operand_dims);\n        $.index_vector_dim = reader.int64(json.index_vector_dim, 0n);\n        $.unique_indices = reader.value(json.unique_indices, false);\n        $.update_computation_subgraph_index = reader.value(json.update_computation_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.StablehloCaseOptions = class StablehloCaseOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloCaseOptions();\n        $.branch_subgraph_indices = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloCaseOptions();\n        $.branch_subgraph_indices = reader.array(json.branch_subgraph_indices, Int32Array);\n        return $;\n    }\n};\n\ncircle.RngAlgorithm = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    PHILOX: 1, '1': 'PHILOX',\n    THREEFRY: 2, '2': 'THREEFRY'\n};\n\ncircle.StablehloRngBitGeneratorOptions = class StablehloRngBitGeneratorOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StablehloRngBitGeneratorOptions();\n        $.algorithm = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StablehloRngBitGeneratorOptions();\n        $.algorithm = circle.RngAlgorithm[json.algorithm];\n        return $;\n    }\n};\n\ncircle.Padding = {\n    SAME: 0, '0': 'SAME',\n    VALID: 1, '1': 'VALID'\n};\n\ncircle.ActivationFunctionType = {\n    NONE: 0, '0': 'NONE',\n    RELU: 1, '1': 'RELU',\n    RELU_N1_TO_1: 2, '2': 'RELU_N1_TO_1',\n    RELU6: 3, '3': 'RELU6',\n    TANH: 4, '4': 'TANH',\n    SIGN_BIT: 5, '5': 'SIGN_BIT'\n};\n\ncircle.Conv2DOptions = class Conv2DOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.Conv2DOptions();\n        $.padding = reader.int8_(position, 4, 0);\n        $.stride_w = reader.int32_(position, 6, 0);\n        $.stride_h = reader.int32_(position, 8, 0);\n        $.fused_activation_function = reader.int8_(position, 10, 0);\n        $.dilation_w_factor = reader.int32_(position, 12, 1);\n        $.dilation_h_factor = reader.int32_(position, 14, 1);\n        $.quantized_bias_type = reader.int8_(position, 16, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Conv2DOptions();\n        $.padding = circle.Padding[json.padding];\n        $.stride_w = reader.value(json.stride_w, 0);\n        $.stride_h = reader.value(json.stride_h, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.dilation_w_factor = reader.value(json.dilation_w_factor, 1);\n        $.dilation_h_factor = reader.value(json.dilation_h_factor, 1);\n        $.quantized_bias_type = circle.TensorType[json.quantized_bias_type];\n        return $;\n    }\n};\n\ncircle.Conv3DOptions = class Conv3DOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.Conv3DOptions();\n        $.padding = reader.int8_(position, 4, 0);\n        $.stride_d = reader.int32_(position, 6, 0);\n        $.stride_w = reader.int32_(position, 8, 0);\n        $.stride_h = reader.int32_(position, 10, 0);\n        $.fused_activation_function = reader.int8_(position, 12, 0);\n        $.dilation_d_factor = reader.int32_(position, 14, 1);\n        $.dilation_w_factor = reader.int32_(position, 16, 1);\n        $.dilation_h_factor = reader.int32_(position, 18, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Conv3DOptions();\n        $.padding = circle.Padding[json.padding];\n        $.stride_d = reader.value(json.stride_d, 0);\n        $.stride_w = reader.value(json.stride_w, 0);\n        $.stride_h = reader.value(json.stride_h, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.dilation_d_factor = reader.value(json.dilation_d_factor, 1);\n        $.dilation_w_factor = reader.value(json.dilation_w_factor, 1);\n        $.dilation_h_factor = reader.value(json.dilation_h_factor, 1);\n        return $;\n    }\n};\n\ncircle.Pool2DOptions = class Pool2DOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.Pool2DOptions();\n        $.padding = reader.int8_(position, 4, 0);\n        $.stride_w = reader.int32_(position, 6, 0);\n        $.stride_h = reader.int32_(position, 8, 0);\n        $.filter_width = reader.int32_(position, 10, 0);\n        $.filter_height = reader.int32_(position, 12, 0);\n        $.fused_activation_function = reader.int8_(position, 14, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Pool2DOptions();\n        $.padding = circle.Padding[json.padding];\n        $.stride_w = reader.value(json.stride_w, 0);\n        $.stride_h = reader.value(json.stride_h, 0);\n        $.filter_width = reader.value(json.filter_width, 0);\n        $.filter_height = reader.value(json.filter_height, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.DepthwiseConv2DOptions = class DepthwiseConv2DOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.DepthwiseConv2DOptions();\n        $.padding = reader.int8_(position, 4, 0);\n        $.stride_w = reader.int32_(position, 6, 0);\n        $.stride_h = reader.int32_(position, 8, 0);\n        $.depth_multiplier = reader.int32_(position, 10, 0);\n        $.fused_activation_function = reader.int8_(position, 12, 0);\n        $.dilation_w_factor = reader.int32_(position, 14, 1);\n        $.dilation_h_factor = reader.int32_(position, 16, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.DepthwiseConv2DOptions();\n        $.padding = circle.Padding[json.padding];\n        $.stride_w = reader.value(json.stride_w, 0);\n        $.stride_h = reader.value(json.stride_h, 0);\n        $.depth_multiplier = reader.value(json.depth_multiplier, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.dilation_w_factor = reader.value(json.dilation_w_factor, 1);\n        $.dilation_h_factor = reader.value(json.dilation_h_factor, 1);\n        return $;\n    }\n};\n\ncircle.ConcatEmbeddingsOptions = class ConcatEmbeddingsOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ConcatEmbeddingsOptions();\n        $.num_channels = reader.int32_(position, 4, 0);\n        $.num_columns_per_channel = reader.array(position, 6, Int32Array);\n        $.embedding_dim_per_channel = reader.array(position, 8, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ConcatEmbeddingsOptions();\n        $.num_channels = reader.value(json.num_channels, 0);\n        $.num_columns_per_channel = reader.array(json.num_columns_per_channel, Int32Array);\n        $.embedding_dim_per_channel = reader.array(json.embedding_dim_per_channel, Int32Array);\n        return $;\n    }\n};\n\ncircle.LSHProjectionType = {\n    UNKNOWN: 0, '0': 'UNKNOWN',\n    SPARSE: 1, '1': 'SPARSE',\n    DENSE: 2, '2': 'DENSE'\n};\n\ncircle.LSHProjectionOptions = class LSHProjectionOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.LSHProjectionOptions();\n        $.type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.LSHProjectionOptions();\n        $.type = circle.LSHProjectionType[json.type];\n        return $;\n    }\n};\n\ncircle.SVDFOptions = class SVDFOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SVDFOptions();\n        $.rank = reader.int32_(position, 4, 0);\n        $.fused_activation_function = reader.int8_(position, 6, 0);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SVDFOptions();\n        $.rank = reader.value(json.rank, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.RNNOptions = class RNNOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.RNNOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.RNNOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.SequenceRNNOptions = class SequenceRNNOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SequenceRNNOptions();\n        $.time_major = reader.bool_(position, 4, false);\n        $.fused_activation_function = reader.int8_(position, 6, 0);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SequenceRNNOptions();\n        $.time_major = reader.value(json.time_major, false);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.BidirectionalSequenceRNNOptions = class BidirectionalSequenceRNNOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.BidirectionalSequenceRNNOptions();\n        $.time_major = reader.bool_(position, 4, false);\n        $.fused_activation_function = reader.int8_(position, 6, 0);\n        $.merge_outputs = reader.bool_(position, 8, false);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BidirectionalSequenceRNNOptions();\n        $.time_major = reader.value(json.time_major, false);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.merge_outputs = reader.value(json.merge_outputs, false);\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.FullyConnectedOptionsWeightsFormat = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    SHUFFLED4x16INT8: 1, '1': 'SHUFFLED4x16INT8',\n    SHUFFLED16x1FLOAT32: 127, '127': 'SHUFFLED16x1FLOAT32'\n};\n\ncircle.FullyConnectedOptions = class FullyConnectedOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.FullyConnectedOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.weights_format = reader.int8_(position, 6, 0);\n        $.keep_num_dims = reader.bool_(position, 8, false);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 10, false);\n        $.quantized_bias_type = reader.int8_(position, 12, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.FullyConnectedOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.weights_format = circle.FullyConnectedOptionsWeightsFormat[json.weights_format];\n        $.keep_num_dims = reader.value(json.keep_num_dims, false);\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        $.quantized_bias_type = circle.TensorType[json.quantized_bias_type];\n        return $;\n    }\n};\n\ncircle.SoftmaxOptions = class SoftmaxOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SoftmaxOptions();\n        $.beta = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SoftmaxOptions();\n        $.beta = reader.value(json.beta, 0);\n        return $;\n    }\n};\n\ncircle.ConcatenationOptions = class ConcatenationOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ConcatenationOptions();\n        $.axis = reader.int32_(position, 4, 0);\n        $.fused_activation_function = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ConcatenationOptions();\n        $.axis = reader.value(json.axis, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.AddOptions = class AddOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.AddOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.pot_scale_int16 = reader.bool_(position, 6, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.AddOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.pot_scale_int16 = reader.value(json.pot_scale_int16, true);\n        return $;\n    }\n};\n\ncircle.MulOptions = class MulOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.MulOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.MulOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.L2NormOptions = class L2NormOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.L2NormOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.L2NormOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.LocalResponseNormalizationOptions = class LocalResponseNormalizationOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.LocalResponseNormalizationOptions();\n        $.radius = reader.int32_(position, 4, 0);\n        $.bias = reader.float32_(position, 6, 0);\n        $.alpha = reader.float32_(position, 8, 0);\n        $.beta = reader.float32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.LocalResponseNormalizationOptions();\n        $.radius = reader.value(json.radius, 0);\n        $.bias = reader.value(json.bias, 0);\n        $.alpha = reader.value(json.alpha, 0);\n        $.beta = reader.value(json.beta, 0);\n        return $;\n    }\n};\n\ncircle.LSTMKernelType = {\n    FULL: 0, '0': 'FULL',\n    BASIC: 1, '1': 'BASIC'\n};\n\ncircle.LSTMOptions = class LSTMOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.LSTMOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.cell_clip = reader.float32_(position, 6, 0);\n        $.proj_clip = reader.float32_(position, 8, 0);\n        $.kernel_type = reader.int8_(position, 10, 0);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 12, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.LSTMOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.cell_clip = reader.value(json.cell_clip, 0);\n        $.proj_clip = reader.value(json.proj_clip, 0);\n        $.kernel_type = circle.LSTMKernelType[json.kernel_type];\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.UnidirectionalSequenceLSTMOptions = class UnidirectionalSequenceLSTMOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.UnidirectionalSequenceLSTMOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.cell_clip = reader.float32_(position, 6, 0);\n        $.proj_clip = reader.float32_(position, 8, 0);\n        $.time_major = reader.bool_(position, 10, false);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 12, false);\n        $.diagonal_recurrent_tensors = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.UnidirectionalSequenceLSTMOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.cell_clip = reader.value(json.cell_clip, 0);\n        $.proj_clip = reader.value(json.proj_clip, 0);\n        $.time_major = reader.value(json.time_major, false);\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        $.diagonal_recurrent_tensors = reader.value(json.diagonal_recurrent_tensors, false);\n        return $;\n    }\n};\n\ncircle.BidirectionalSequenceLSTMOptions = class BidirectionalSequenceLSTMOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.BidirectionalSequenceLSTMOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.cell_clip = reader.float32_(position, 6, 0);\n        $.proj_clip = reader.float32_(position, 8, 0);\n        $.merge_outputs = reader.bool_(position, 10, false);\n        $.time_major = reader.bool_(position, 12, true);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BidirectionalSequenceLSTMOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.cell_clip = reader.value(json.cell_clip, 0);\n        $.proj_clip = reader.value(json.proj_clip, 0);\n        $.merge_outputs = reader.value(json.merge_outputs, false);\n        $.time_major = reader.value(json.time_major, true);\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.ResizeBilinearOptions = class ResizeBilinearOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ResizeBilinearOptions();\n        $.new_height = reader.int32_(position, 4, 0);\n        $.new_width = reader.int32_(position, 6, 0);\n        $.align_corners = reader.bool_(position, 8, false);\n        $.half_pixel_centers = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ResizeBilinearOptions();\n        $.new_height = reader.value(json.new_height, 0);\n        $.new_width = reader.value(json.new_width, 0);\n        $.align_corners = reader.value(json.align_corners, false);\n        $.half_pixel_centers = reader.value(json.half_pixel_centers, false);\n        return $;\n    }\n};\n\ncircle.ResizeNearestNeighborOptions = class ResizeNearestNeighborOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ResizeNearestNeighborOptions();\n        $.align_corners = reader.bool_(position, 4, false);\n        $.half_pixel_centers = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ResizeNearestNeighborOptions();\n        $.align_corners = reader.value(json.align_corners, false);\n        $.half_pixel_centers = reader.value(json.half_pixel_centers, false);\n        return $;\n    }\n};\n\ncircle.CallOptions = class CallOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.CallOptions();\n        $.subgraph = reader.uint32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.CallOptions();\n        $.subgraph = reader.value(json.subgraph, 0);\n        return $;\n    }\n};\n\ncircle.PadOptions = class PadOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.PadOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.PadOptions();\n        return $;\n    }\n};\n\ncircle.PadV2Options = class PadV2Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.PadV2Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.PadV2Options();\n        return $;\n    }\n};\n\ncircle.ReshapeOptions = class ReshapeOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ReshapeOptions();\n        $.new_shape = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ReshapeOptions();\n        $.new_shape = reader.array(json.new_shape, Int32Array);\n        return $;\n    }\n};\n\ncircle.SpaceToBatchNDOptions = class SpaceToBatchNDOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SpaceToBatchNDOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SpaceToBatchNDOptions();\n        return $;\n    }\n};\n\ncircle.BatchToSpaceNDOptions = class BatchToSpaceNDOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.BatchToSpaceNDOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.BatchToSpaceNDOptions();\n        return $;\n    }\n};\n\ncircle.SkipGramOptions = class SkipGramOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SkipGramOptions();\n        $.ngram_size = reader.int32_(position, 4, 0);\n        $.max_skip_size = reader.int32_(position, 6, 0);\n        $.include_all_ngrams = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SkipGramOptions();\n        $.ngram_size = reader.value(json.ngram_size, 0);\n        $.max_skip_size = reader.value(json.max_skip_size, 0);\n        $.include_all_ngrams = reader.value(json.include_all_ngrams, false);\n        return $;\n    }\n};\n\ncircle.SpaceToDepthOptions = class SpaceToDepthOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SpaceToDepthOptions();\n        $.block_size = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SpaceToDepthOptions();\n        $.block_size = reader.value(json.block_size, 0);\n        return $;\n    }\n};\n\ncircle.DepthToSpaceOptions = class DepthToSpaceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.DepthToSpaceOptions();\n        $.block_size = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.DepthToSpaceOptions();\n        $.block_size = reader.value(json.block_size, 0);\n        return $;\n    }\n};\n\ncircle.SubOptions = class SubOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SubOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.pot_scale_int16 = reader.bool_(position, 6, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SubOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.pot_scale_int16 = reader.value(json.pot_scale_int16, true);\n        return $;\n    }\n};\n\ncircle.DivOptions = class DivOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.DivOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.DivOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.TopKV2Options = class TopKV2Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.TopKV2Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.TopKV2Options();\n        return $;\n    }\n};\n\ncircle.CombinerType = {\n    SUM: 0, '0': 'SUM',\n    MEAN: 1, '1': 'MEAN',\n    SQRTN: 2, '2': 'SQRTN'\n};\n\ncircle.EmbeddingLookupSparseOptions = class EmbeddingLookupSparseOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.EmbeddingLookupSparseOptions();\n        $.combiner = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.EmbeddingLookupSparseOptions();\n        $.combiner = circle.CombinerType[json.combiner];\n        return $;\n    }\n};\n\ncircle.GatherOptions = class GatherOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.GatherOptions();\n        $.axis = reader.int32_(position, 4, 0);\n        $.batch_dims = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.GatherOptions();\n        $.axis = reader.value(json.axis, 0);\n        $.batch_dims = reader.value(json.batch_dims, 0);\n        return $;\n    }\n};\n\ncircle.TransposeOptions = class TransposeOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.TransposeOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.TransposeOptions();\n        return $;\n    }\n};\n\ncircle.ExpOptions = class ExpOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ExpOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ExpOptions();\n        return $;\n    }\n};\n\ncircle.CosOptions = class CosOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.CosOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.CosOptions();\n        return $;\n    }\n};\n\ncircle.ReducerOptions = class ReducerOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ReducerOptions();\n        $.keep_dims = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ReducerOptions();\n        $.keep_dims = reader.value(json.keep_dims, false);\n        return $;\n    }\n};\n\ncircle.SqueezeOptions = class SqueezeOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SqueezeOptions();\n        $.squeeze_dims = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SqueezeOptions();\n        $.squeeze_dims = reader.array(json.squeeze_dims, Int32Array);\n        return $;\n    }\n};\n\ncircle.SplitOptions = class SplitOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SplitOptions();\n        $.num_splits = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SplitOptions();\n        $.num_splits = reader.value(json.num_splits, 0);\n        return $;\n    }\n};\n\ncircle.SplitVOptions = class SplitVOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SplitVOptions();\n        $.num_splits = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SplitVOptions();\n        $.num_splits = reader.value(json.num_splits, 0);\n        return $;\n    }\n};\n\ncircle.StridedSliceOptions = class StridedSliceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StridedSliceOptions();\n        $.begin_mask = reader.int32_(position, 4, 0);\n        $.end_mask = reader.int32_(position, 6, 0);\n        $.ellipsis_mask = reader.int32_(position, 8, 0);\n        $.new_axis_mask = reader.int32_(position, 10, 0);\n        $.shrink_axis_mask = reader.int32_(position, 12, 0);\n        $.offset = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StridedSliceOptions();\n        $.begin_mask = reader.value(json.begin_mask, 0);\n        $.end_mask = reader.value(json.end_mask, 0);\n        $.ellipsis_mask = reader.value(json.ellipsis_mask, 0);\n        $.new_axis_mask = reader.value(json.new_axis_mask, 0);\n        $.shrink_axis_mask = reader.value(json.shrink_axis_mask, 0);\n        $.offset = reader.value(json.offset, false);\n        return $;\n    }\n};\n\ncircle.LogSoftmaxOptions = class LogSoftmaxOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.LogSoftmaxOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.LogSoftmaxOptions();\n        return $;\n    }\n};\n\ncircle.CastOptions = class CastOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.CastOptions();\n        $.in_data_type = reader.int8_(position, 4, 0);\n        $.out_data_type = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.CastOptions();\n        $.in_data_type = circle.TensorType[json.in_data_type];\n        $.out_data_type = circle.TensorType[json.out_data_type];\n        return $;\n    }\n};\n\ncircle.DequantizeOptions = class DequantizeOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.DequantizeOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.DequantizeOptions();\n        return $;\n    }\n};\n\ncircle.MaximumMinimumOptions = class MaximumMinimumOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.MaximumMinimumOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.MaximumMinimumOptions();\n        return $;\n    }\n};\n\ncircle.TileOptions = class TileOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.TileOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.TileOptions();\n        return $;\n    }\n};\n\ncircle.ArgMaxOptions = class ArgMaxOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ArgMaxOptions();\n        $.output_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ArgMaxOptions();\n        $.output_type = circle.TensorType[json.output_type];\n        return $;\n    }\n};\n\ncircle.ArgMinOptions = class ArgMinOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ArgMinOptions();\n        $.output_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ArgMinOptions();\n        $.output_type = circle.TensorType[json.output_type];\n        return $;\n    }\n};\n\ncircle.GreaterOptions = class GreaterOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.GreaterOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.GreaterOptions();\n        return $;\n    }\n};\n\ncircle.GreaterEqualOptions = class GreaterEqualOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.GreaterEqualOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.GreaterEqualOptions();\n        return $;\n    }\n};\n\ncircle.LessOptions = class LessOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.LessOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.LessOptions();\n        return $;\n    }\n};\n\ncircle.LessEqualOptions = class LessEqualOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.LessEqualOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.LessEqualOptions();\n        return $;\n    }\n};\n\ncircle.NegOptions = class NegOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.NegOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.NegOptions();\n        return $;\n    }\n};\n\ncircle.SelectOptions = class SelectOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SelectOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SelectOptions();\n        return $;\n    }\n};\n\ncircle.SliceOptions = class SliceOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SliceOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SliceOptions();\n        return $;\n    }\n};\n\ncircle.TransposeConvOptions = class TransposeConvOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.TransposeConvOptions();\n        $.padding = reader.int8_(position, 4, 0);\n        $.stride_w = reader.int32_(position, 6, 0);\n        $.stride_h = reader.int32_(position, 8, 0);\n        $.fused_activation_function = reader.int8_(position, 10, 0);\n        $.quantized_bias_type = reader.int8_(position, 12, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.TransposeConvOptions();\n        $.padding = circle.Padding[json.padding];\n        $.stride_w = reader.value(json.stride_w, 0);\n        $.stride_h = reader.value(json.stride_h, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.quantized_bias_type = circle.TensorType[json.quantized_bias_type];\n        return $;\n    }\n};\n\ncircle.ExpandDimsOptions = class ExpandDimsOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ExpandDimsOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ExpandDimsOptions();\n        return $;\n    }\n};\n\ncircle.SparseToDenseOptions = class SparseToDenseOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.SparseToDenseOptions();\n        $.validate_indices = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SparseToDenseOptions();\n        $.validate_indices = reader.value(json.validate_indices, false);\n        return $;\n    }\n};\n\ncircle.EqualOptions = class EqualOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.EqualOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.EqualOptions();\n        return $;\n    }\n};\n\ncircle.NotEqualOptions = class NotEqualOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.NotEqualOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.NotEqualOptions();\n        return $;\n    }\n};\n\ncircle.ShapeOptions = class ShapeOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ShapeOptions();\n        $.out_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ShapeOptions();\n        $.out_type = circle.TensorType[json.out_type];\n        return $;\n    }\n};\n\ncircle.RankOptions = class RankOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.RankOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.RankOptions();\n        return $;\n    }\n};\n\ncircle.PowOptions = class PowOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.PowOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.PowOptions();\n        return $;\n    }\n};\n\ncircle.FakeQuantOptions = class FakeQuantOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.FakeQuantOptions();\n        $.min = reader.float32_(position, 4, 0);\n        $.max = reader.float32_(position, 6, 0);\n        $.num_bits = reader.int32_(position, 8, 0);\n        $.narrow_range = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.FakeQuantOptions();\n        $.min = reader.value(json.min, 0);\n        $.max = reader.value(json.max, 0);\n        $.num_bits = reader.value(json.num_bits, 0);\n        $.narrow_range = reader.value(json.narrow_range, false);\n        return $;\n    }\n};\n\ncircle.PackOptions = class PackOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.PackOptions();\n        $.values_count = reader.int32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.PackOptions();\n        $.values_count = reader.value(json.values_count, 0);\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\ncircle.LogicalOrOptions = class LogicalOrOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.LogicalOrOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.LogicalOrOptions();\n        return $;\n    }\n};\n\ncircle.OneHotOptions = class OneHotOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.OneHotOptions();\n        $.axis = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.OneHotOptions();\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\ncircle.AbsOptions = class AbsOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.AbsOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.AbsOptions();\n        return $;\n    }\n};\n\ncircle.HardSwishOptions = class HardSwishOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.HardSwishOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.HardSwishOptions();\n        return $;\n    }\n};\n\ncircle.LogicalAndOptions = class LogicalAndOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.LogicalAndOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.LogicalAndOptions();\n        return $;\n    }\n};\n\ncircle.LogicalNotOptions = class LogicalNotOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.LogicalNotOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.LogicalNotOptions();\n        return $;\n    }\n};\n\ncircle.UnpackOptions = class UnpackOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.UnpackOptions();\n        $.num = reader.int32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.UnpackOptions();\n        $.num = reader.value(json.num, 0);\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\ncircle.FloorDivOptions = class FloorDivOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.FloorDivOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.FloorDivOptions();\n        return $;\n    }\n};\n\ncircle.SquareOptions = class SquareOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SquareOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SquareOptions();\n        return $;\n    }\n};\n\ncircle.ZerosLikeOptions = class ZerosLikeOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ZerosLikeOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ZerosLikeOptions();\n        return $;\n    }\n};\n\ncircle.FillOptions = class FillOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.FillOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.FillOptions();\n        return $;\n    }\n};\n\ncircle.FloorModOptions = class FloorModOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.FloorModOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.FloorModOptions();\n        return $;\n    }\n};\n\ncircle.RangeOptions = class RangeOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.RangeOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.RangeOptions();\n        return $;\n    }\n};\n\ncircle.LeakyReluOptions = class LeakyReluOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.LeakyReluOptions();\n        $.alpha = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.LeakyReluOptions();\n        $.alpha = reader.value(json.alpha, 0);\n        return $;\n    }\n};\n\ncircle.SquaredDifferenceOptions = class SquaredDifferenceOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SquaredDifferenceOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SquaredDifferenceOptions();\n        return $;\n    }\n};\n\ncircle.MirrorPadMode = {\n    REFLECT: 0, '0': 'REFLECT',\n    SYMMETRIC: 1, '1': 'SYMMETRIC'\n};\n\ncircle.MirrorPadOptions = class MirrorPadOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.MirrorPadOptions();\n        $.mode = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.MirrorPadOptions();\n        $.mode = circle.MirrorPadMode[json.mode];\n        return $;\n    }\n};\n\ncircle.UniqueOptions = class UniqueOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.UniqueOptions();\n        $.idx_out_type = reader.int8_(position, 4, 2);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.UniqueOptions();\n        $.idx_out_type = circle.TensorType[json.idx_out_type];\n        return $;\n    }\n};\n\ncircle.ReverseV2Options = class ReverseV2Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ReverseV2Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ReverseV2Options();\n        return $;\n    }\n};\n\ncircle.AddNOptions = class AddNOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.AddNOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.AddNOptions();\n        return $;\n    }\n};\n\ncircle.GatherNdOptions = class GatherNdOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.GatherNdOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.GatherNdOptions();\n        return $;\n    }\n};\n\ncircle.WhereOptions = class WhereOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.WhereOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.WhereOptions();\n        return $;\n    }\n};\n\ncircle.ReverseSequenceOptions = class ReverseSequenceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ReverseSequenceOptions();\n        $.seq_dim = reader.int32_(position, 4, 0);\n        $.batch_dim = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ReverseSequenceOptions();\n        $.seq_dim = reader.value(json.seq_dim, 0);\n        $.batch_dim = reader.value(json.batch_dim, 0);\n        return $;\n    }\n};\n\ncircle.MatrixDiagOptions = class MatrixDiagOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.MatrixDiagOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.MatrixDiagOptions();\n        return $;\n    }\n};\n\ncircle.QuantizeOptions = class QuantizeOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.QuantizeOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.QuantizeOptions();\n        return $;\n    }\n};\n\ncircle.MatrixSetDiagOptions = class MatrixSetDiagOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.MatrixSetDiagOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.MatrixSetDiagOptions();\n        return $;\n    }\n};\n\ncircle.IfOptions = class IfOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.IfOptions();\n        $.then_subgraph_index = reader.int32_(position, 4, 0);\n        $.else_subgraph_index = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.IfOptions();\n        $.then_subgraph_index = reader.value(json.then_subgraph_index, 0);\n        $.else_subgraph_index = reader.value(json.else_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.CallOnceOptions = class CallOnceOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.CallOnceOptions();\n        $.init_subgraph_index = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.CallOnceOptions();\n        $.init_subgraph_index = reader.value(json.init_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.WhileOptions = class WhileOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.WhileOptions();\n        $.cond_subgraph_index = reader.int32_(position, 4, 0);\n        $.body_subgraph_index = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.WhileOptions();\n        $.cond_subgraph_index = reader.value(json.cond_subgraph_index, 0);\n        $.body_subgraph_index = reader.value(json.body_subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.NonMaxSuppressionV4Options = class NonMaxSuppressionV4Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.NonMaxSuppressionV4Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.NonMaxSuppressionV4Options();\n        return $;\n    }\n};\n\ncircle.NonMaxSuppressionV5Options = class NonMaxSuppressionV5Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.NonMaxSuppressionV5Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.NonMaxSuppressionV5Options();\n        return $;\n    }\n};\n\ncircle.ScatterNdOptions = class ScatterNdOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ScatterNdOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ScatterNdOptions();\n        return $;\n    }\n};\n\ncircle.SelectV2Options = class SelectV2Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SelectV2Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SelectV2Options();\n        return $;\n    }\n};\n\ncircle.DensifyOptions = class DensifyOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.DensifyOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.DensifyOptions();\n        return $;\n    }\n};\n\ncircle.SegmentSumOptions = class SegmentSumOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SegmentSumOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SegmentSumOptions();\n        return $;\n    }\n};\n\ncircle.BatchMatMulOptions = class BatchMatMulOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.BatchMatMulOptions();\n        $.adjoint_lhs = reader.bool_(position, 4, false);\n        $.adjoint_rhs = reader.bool_(position, 6, false);\n        $.asymmetric_quantize_inputs = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BatchMatMulOptions();\n        $.adjoint_lhs = reader.value(json.adjoint_lhs, false);\n        $.adjoint_rhs = reader.value(json.adjoint_rhs, false);\n        $.asymmetric_quantize_inputs = reader.value(json.asymmetric_quantize_inputs, false);\n        return $;\n    }\n};\n\ncircle.CumsumOptions = class CumsumOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.CumsumOptions();\n        $.exclusive = reader.bool_(position, 4, false);\n        $.reverse = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.CumsumOptions();\n        $.exclusive = reader.value(json.exclusive, false);\n        $.reverse = reader.value(json.reverse, false);\n        return $;\n    }\n};\n\ncircle.BroadcastToOptions = class BroadcastToOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.BroadcastToOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.BroadcastToOptions();\n        return $;\n    }\n};\n\ncircle.Rfft2dOptions = class Rfft2dOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.Rfft2dOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.Rfft2dOptions();\n        return $;\n    }\n};\n\ncircle.HashtableOptions = class HashtableOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.HashtableOptions();\n        $.table_id = reader.int32_(position, 4, 0);\n        $.key_dtype = reader.int8_(position, 6, 0);\n        $.value_dtype = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.HashtableOptions();\n        $.table_id = reader.value(json.table_id, 0);\n        $.key_dtype = circle.TensorType[json.key_dtype];\n        $.value_dtype = circle.TensorType[json.value_dtype];\n        return $;\n    }\n};\n\ncircle.HashtableFindOptions = class HashtableFindOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.HashtableFindOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.HashtableFindOptions();\n        return $;\n    }\n};\n\ncircle.HashtableImportOptions = class HashtableImportOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.HashtableImportOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.HashtableImportOptions();\n        return $;\n    }\n};\n\ncircle.HashtableSizeOptions = class HashtableSizeOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.HashtableSizeOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.HashtableSizeOptions();\n        return $;\n    }\n};\n\ncircle.VarHandleOptions = class VarHandleOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.VarHandleOptions();\n        $.container = reader.string_(position, 4, null);\n        $.shared_name = reader.string_(position, 6, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.VarHandleOptions();\n        $.container = reader.value(json.container, null);\n        $.shared_name = reader.value(json.shared_name, null);\n        return $;\n    }\n};\n\ncircle.ReadVariableOptions = class ReadVariableOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ReadVariableOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ReadVariableOptions();\n        return $;\n    }\n};\n\ncircle.AssignVariableOptions = class AssignVariableOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.AssignVariableOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.AssignVariableOptions();\n        return $;\n    }\n};\n\ncircle.RandomOptions = class RandomOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.RandomOptions();\n        $.seed = reader.int64_(position, 4, 0n);\n        $.seed2 = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.RandomOptions();\n        $.seed = reader.int64(json.seed, 0n);\n        $.seed2 = reader.int64(json.seed2, 0n);\n        return $;\n    }\n};\n\ncircle.BucketizeOptions = class BucketizeOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.BucketizeOptions();\n        $.boundaries = reader.array(position, 4, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BucketizeOptions();\n        $.boundaries = reader.array(json.boundaries, Float32Array);\n        return $;\n    }\n};\n\ncircle.GeluOptions = class GeluOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.GeluOptions();\n        $.approximate = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.GeluOptions();\n        $.approximate = reader.value(json.approximate, false);\n        return $;\n    }\n};\n\ncircle.DynamicUpdateSliceOptions = class DynamicUpdateSliceOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.DynamicUpdateSliceOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.DynamicUpdateSliceOptions();\n        return $;\n    }\n};\n\ncircle.UnsortedSegmentProdOptions = class UnsortedSegmentProdOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.UnsortedSegmentProdOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.UnsortedSegmentProdOptions();\n        return $;\n    }\n};\n\ncircle.UnsortedSegmentMaxOptions = class UnsortedSegmentMaxOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.UnsortedSegmentMaxOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.UnsortedSegmentMaxOptions();\n        return $;\n    }\n};\n\ncircle.UnsortedSegmentSumOptions = class UnsortedSegmentSumOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.UnsortedSegmentSumOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.UnsortedSegmentSumOptions();\n        return $;\n    }\n};\n\ncircle.ATan2Options = class ATan2Options {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.ATan2Options();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.ATan2Options();\n        return $;\n    }\n};\n\ncircle.UnsortedSegmentMinOptions = class UnsortedSegmentMinOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.UnsortedSegmentMinOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.UnsortedSegmentMinOptions();\n        return $;\n    }\n};\n\ncircle.SignOptions = class SignOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.SignOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.SignOptions();\n        return $;\n    }\n};\n\ncircle.BitcastOptions = class BitcastOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.BitcastOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.BitcastOptions();\n        return $;\n    }\n};\n\ncircle.BitwiseXorOptions = class BitwiseXorOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.BitwiseXorOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.BitwiseXorOptions();\n        return $;\n    }\n};\n\ncircle.RightShiftOptions = class RightShiftOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.RightShiftOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.RightShiftOptions();\n        return $;\n    }\n};\n\ncircle.DilateOptions = class DilateOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.DilateOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.DilateOptions();\n        return $;\n    }\n};\n\ncircle.ReduceWindowFunction = {\n    UNSUPPORTED: 0, '0': 'UNSUPPORTED',\n    ADD: 1, '1': 'ADD',\n    MUL: 2, '2': 'MUL',\n    MINIMUM: 3, '3': 'MINIMUM',\n    MAXIMUM: 4, '4': 'MAXIMUM',\n    ALL: 5, '5': 'ALL',\n    ANY: 6, '6': 'ANY'\n};\n\ncircle.ReduceWindowOptions = class ReduceWindowOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.ReduceWindowOptions();\n        $.reduce_function = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.ReduceWindowOptions();\n        $.reduce_function = circle.ReduceWindowFunction[json.reduce_function];\n        return $;\n    }\n};\n\ncircle.GRUOptions = class GRUOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.GRUOptions();\n        $.fused_activation_function = reader.int8_(position, 4, 0);\n        $.return_sequences = reader.bool_(position, 6, false);\n        $.time_major = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.GRUOptions();\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        $.return_sequences = reader.value(json.return_sequences, false);\n        $.time_major = reader.value(json.time_major, false);\n        return $;\n    }\n};\n\ncircle.BCQGatherOptions = class BCQGatherOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.BCQGatherOptions();\n        $.input_hidden_size = reader.int32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BCQGatherOptions();\n        $.input_hidden_size = reader.value(json.input_hidden_size, 0);\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\ncircle.BCQFullyConnectedOptions = class BCQFullyConnectedOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.BCQFullyConnectedOptions();\n        $.weights_hidden_size = reader.int32_(position, 4, 0);\n        $.fused_activation_function = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.BCQFullyConnectedOptions();\n        $.weights_hidden_size = reader.value(json.weights_hidden_size, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.InstanceNormOptions = class InstanceNormOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.InstanceNormOptions();\n        $.epsilon = reader.float32_(position, 4, 0);\n        $.fused_activation_function = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.InstanceNormOptions();\n        $.epsilon = reader.value(json.epsilon, 0);\n        $.fused_activation_function = circle.ActivationFunctionType[json.fused_activation_function];\n        return $;\n    }\n};\n\ncircle.RmsNormOptions = class RmsNormOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.RmsNormOptions();\n        $.epsilon = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.RmsNormOptions();\n        $.epsilon = reader.value(json.epsilon, 0);\n        return $;\n    }\n};\n\ncircle.RoPEMode = {\n    GPT_NEOX: 0, '0': 'GPT_NEOX',\n    GPT_J: 1, '1': 'GPT_J'\n};\n\ncircle.RoPEOptions = class RoPEOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.RoPEOptions();\n        $.mode = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.RoPEOptions();\n        $.mode = circle.RoPEMode[json.mode];\n        return $;\n    }\n};\n\ncircle.RunModelOptions = class RunModelOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.RunModelOptions();\n        $.location = reader.string_(position, 4, null);\n        $.signature = reader.string_(position, 6, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.RunModelOptions();\n        $.location = reader.value(json.location, null);\n        $.signature = reader.value(json.signature, null);\n        return $;\n    }\n};\n\ncircle.AttentionOptions = class AttentionOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.AttentionOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.AttentionOptions();\n        return $;\n    }\n};\n\ncircle.OperatorCode = class OperatorCode {\n\n    static decode(reader, position) {\n        const $ = new circle.OperatorCode();\n        $.deprecated_builtin_code = reader.int8_(position, 4, 0);\n        $.custom_code = reader.string_(position, 6, null);\n        $.version = reader.int32_(position, 8, 1);\n        $.builtin_code = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.OperatorCode();\n        $.deprecated_builtin_code = reader.value(json.deprecated_builtin_code, 0);\n        $.custom_code = reader.value(json.custom_code, null);\n        $.version = reader.value(json.version, 1);\n        $.builtin_code = circle.BuiltinOperator[json.builtin_code];\n        return $;\n    }\n};\n\ncircle.CustomOptionsFormat = {\n    FLEXBUFFERS: 0, '0': 'FLEXBUFFERS'\n};\n\ncircle.DataFormat = {\n    CHANNELS_LAST: 0, '0': 'CHANNELS_LAST',\n    CHANNELS_FIRST: 1, '1': 'CHANNELS_FIRST'\n};\n\ncircle.StableHLOCompositeOptions = class StableHLOCompositeOptions {\n\n    static decode(reader, position) {\n        const $ = new circle.StableHLOCompositeOptions();\n        $.name = reader.string_(position, 4, null);\n        $.decomposition_subgraph_index = reader.int32_(position, 6, 0);\n        $.composite_attributes = reader.array(position, 8, Uint8Array);\n        $.composite_attributes_format = reader.int8_(position, 10, 0);\n        $.version = reader.int32_(position, 12, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.StableHLOCompositeOptions();\n        $.name = reader.value(json.name, null);\n        $.decomposition_subgraph_index = reader.value(json.decomposition_subgraph_index, 0);\n        $.composite_attributes = reader.array(json.composite_attributes, Uint8Array);\n        $.composite_attributes_format = circle.CustomOptionsFormat[json.composite_attributes_format];\n        $.version = reader.value(json.version, 0);\n        return $;\n    }\n};\n\ncircle.StablehloShiftLeftOptions = class StablehloShiftLeftOptions {\n\n    static decode(/* reader, position */) {\n        const $ = new circle.StablehloShiftLeftOptions();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new circle.StablehloShiftLeftOptions();\n        return $;\n    }\n};\n\ncircle.Operator = class Operator {\n\n    static decode(reader, position) {\n        const $ = new circle.Operator();\n        $.opcode_index = reader.uint32_(position, 4, 0);\n        $.inputs = reader.array(position, 6, Int32Array);\n        $.outputs = reader.array(position, 8, Int32Array);\n        $.builtin_options = reader.union(position, 10, circle.BuiltinOptions);\n        $.custom_options = reader.array(position, 14, Uint8Array);\n        $.custom_options_format = reader.int8_(position, 16, 0);\n        $.mutating_variable_inputs = reader.bools_(position, 18);\n        $.intermediates = reader.array(position, 20, Int32Array);\n        $.large_custom_options_offset = reader.uint64_(position, 22, 0n);\n        $.large_custom_options_size = reader.uint64_(position, 24, 0n);\n        $.builtin_options_2 = reader.union(position, 26, circle.BuiltinOptions2);\n        $.debug_metadata_index = reader.int32_(position, 30, -1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Operator();\n        $.opcode_index = reader.value(json.opcode_index, 0);\n        $.inputs = reader.array(json.inputs, Int32Array);\n        $.outputs = reader.array(json.outputs, Int32Array);\n        $.builtin_options = circle.BuiltinOptions.decodeText(reader, json.builtin_options, json.builtin_options_type);\n        $.custom_options = reader.array(json.custom_options, Uint8Array);\n        $.custom_options_format = circle.CustomOptionsFormat[json.custom_options_format];\n        $.mutating_variable_inputs = reader.array(json.mutating_variable_inputs);\n        $.intermediates = reader.array(json.intermediates, Int32Array);\n        $.large_custom_options_offset = reader.uint64(json.large_custom_options_offset, 0n);\n        $.large_custom_options_size = reader.uint64(json.large_custom_options_size, 0n);\n        $.builtin_options_2 = circle.BuiltinOptions2.decodeText(reader, json.builtin_options_2, json.builtin_options_2_type);\n        $.debug_metadata_index = reader.value(json.debug_metadata_index, -1);\n        return $;\n    }\n};\n\ncircle.SubGraph = class SubGraph {\n\n    static decode(reader, position) {\n        const $ = new circle.SubGraph();\n        $.tensors = reader.tables(position, 4, circle.Tensor);\n        $.inputs = reader.array(position, 6, Int32Array);\n        $.outputs = reader.array(position, 8, Int32Array);\n        $.operators = reader.tables(position, 10, circle.Operator);\n        $.name = reader.string_(position, 12, null);\n        $.deprecated_data_format = reader.int8_(position, 14, 0);\n        $.debug_metadata_index = reader.int32_(position, 16, -1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SubGraph();\n        $.tensors = reader.objects(json.tensors, circle.Tensor);\n        $.inputs = reader.array(json.inputs, Int32Array);\n        $.outputs = reader.array(json.outputs, Int32Array);\n        $.operators = reader.objects(json.operators, circle.Operator);\n        $.name = reader.value(json.name, null);\n        $.deprecated_data_format = circle.DataFormat[json.deprecated_data_format];\n        $.debug_metadata_index = reader.value(json.debug_metadata_index, -1);\n        return $;\n    }\n};\n\ncircle.Buffer = class Buffer {\n\n    static decode(reader, position) {\n        const $ = new circle.Buffer();\n        $.data = reader.array(position, 4, Uint8Array);\n        $.offset = reader.uint64_(position, 6, 0n);\n        $.size = reader.uint64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Buffer();\n        $.data = reader.array(json.data, Uint8Array);\n        $.offset = reader.uint64(json.offset, 0n);\n        $.size = reader.uint64(json.size, 0n);\n        return $;\n    }\n};\n\ncircle.Metadata = class Metadata {\n\n    static decode(reader, position) {\n        const $ = new circle.Metadata();\n        $.name = reader.string_(position, 4, null);\n        $.buffer = reader.uint32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Metadata();\n        $.name = reader.value(json.name, null);\n        $.buffer = reader.value(json.buffer, 0);\n        return $;\n    }\n};\n\ncircle.TensorMap = class TensorMap {\n\n    static decode(reader, position) {\n        const $ = new circle.TensorMap();\n        $.name = reader.string_(position, 4, null);\n        $.tensor_index = reader.uint32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.TensorMap();\n        $.name = reader.value(json.name, null);\n        $.tensor_index = reader.value(json.tensor_index, 0);\n        return $;\n    }\n};\n\ncircle.SignatureDef = class SignatureDef {\n\n    static decode(reader, position) {\n        const $ = new circle.SignatureDef();\n        $.inputs = reader.tables(position, 4, circle.TensorMap);\n        $.outputs = reader.tables(position, 6, circle.TensorMap);\n        $.signature_key = reader.string_(position, 8, null);\n        $.deprecated_tag = reader.string_(position, 10, null);\n        $.subgraph_index = reader.uint32_(position, 12, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.SignatureDef();\n        $.inputs = reader.objects(json.inputs, circle.TensorMap);\n        $.outputs = reader.objects(json.outputs, circle.TensorMap);\n        $.signature_key = reader.value(json.signature_key, null);\n        $.deprecated_tag = reader.value(json.deprecated_tag, null);\n        $.subgraph_index = reader.value(json.subgraph_index, 0);\n        return $;\n    }\n};\n\ncircle.Model = class Model {\n\n    static identifier(reader) {\n        return reader.identifier === 'CIR0';\n    }\n\n    static create(reader) {\n        return circle.Model.decode(reader, reader.root);\n    }\n\n    static createText(reader) {\n        return circle.Model.decodeText(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new circle.Model();\n        $.version = reader.uint32_(position, 4, 0);\n        $.operator_codes = reader.tables(position, 6, circle.OperatorCode);\n        $.subgraphs = reader.tables(position, 8, circle.SubGraph);\n        $.description = reader.string_(position, 10, null);\n        $.buffers = reader.tables(position, 12, circle.Buffer);\n        $.metadata_buffer = reader.array(position, 14, Int32Array);\n        $.metadata = reader.tables(position, 16, circle.Metadata);\n        $.signature_defs = reader.tables(position, 18, circle.SignatureDef);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new circle.Model();\n        $.version = reader.value(json.version, 0);\n        $.operator_codes = reader.objects(json.operator_codes, circle.OperatorCode);\n        $.subgraphs = reader.objects(json.subgraphs, circle.SubGraph);\n        $.description = reader.value(json.description, null);\n        $.buffers = reader.objects(json.buffers, circle.Buffer);\n        $.metadata_buffer = reader.array(json.metadata_buffer, Int32Array);\n        $.metadata = reader.objects(json.metadata, circle.Metadata);\n        $.signature_defs = reader.objects(json.signature_defs, circle.SignatureDef);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/circle.js",
    "content": "\nimport * as flatbuffers from './flatbuffers.js';\nimport * as flexbuffers from './flexbuffers.js';\nimport * as zip from './zip.js';\n\nconst circle = {};\n\ncircle.ModelFactory = class {\n\n    async match(context) {\n        const reader = await context.peek('flatbuffers.binary');\n        if (reader && reader.identifier === 'CIR0') {\n            return context.set('circle.flatbuffers', reader);\n        }\n        const obj = await context.peek('json');\n        if (obj && obj.subgraphs && obj.operator_codes) {\n            return context.set('circle.flatbuffers.json', obj);\n        }\n        return null;\n    }\n\n    async open(context) {\n        circle.schema = await context.require('./circle-schema');\n        circle.schema = circle.schema.circle;\n        let model = null;\n        const attachments = new Map();\n        switch (context.type) {\n            case 'circle.flatbuffers.json': {\n                try {\n                    const reader = await context.read('flatbuffers.text');\n                    model = circle.schema.Model.createText(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new circle.Error(`File text format is not circle.Model (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            case 'circle.flatbuffers': {\n                try {\n                    const reader = context.value;\n                    model = circle.schema.Model.create(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new circle.Error(`File format is not circle.Model (${message.replace(/\\.$/, '')}).`);\n                }\n                try {\n                    const stream = context.stream;\n                    const archive = zip.Archive.open(stream);\n                    if (archive) {\n                        for (const [name, value] of archive.entries) {\n                            attachments.set(name, value);\n                        }\n                    }\n                } catch {\n                    // continue regardless of error\n                }\n                break;\n            }\n            default: {\n                throw new circle.Error(`Unsupported Circle format '${context.type}'.`);\n            }\n        }\n        const stream = context.stream;\n        const metadata = await context.metadata('circle-metadata.json');\n        return new circle.Model(metadata, model, stream);\n    }\n};\n\ncircle.Model = class {\n\n    constructor(metadata, model, stream) {\n        this.format = 'Circle';\n        this.format = `${this.format} v${model.version}`;\n        this.description = model.description || '';\n        this.modules = [];\n        this.metadata = [];\n        const builtinOperators = new Map();\n        const upperCase = new Set(['2D', 'LSH', 'SVDF', 'RNN', 'L2', 'LSTM']);\n        for (const key of Object.keys(circle.schema.BuiltinOperator)) {\n            const value = key === 'BATCH_MATMUL' ? 'BATCH_MAT_MUL' : key;\n            const name = value.split('_').map((s) => (s.length < 1 || upperCase.has(s)) ? s : s[0] + s.substring(1).toLowerCase()).join('');\n            const index = circle.schema.BuiltinOperator[key];\n            builtinOperators.set(index, name);\n        }\n        const operators = model.operator_codes.map((operator) => {\n            const code = Math.max(operator.deprecated_builtin_code, operator.builtin_code || 0);\n            const value = {};\n            if (code === circle.schema.BuiltinOperator.CUSTOM) {\n                value.name = operator.custom_code ? operator.custom_code : 'Custom';\n                value.version = operator.version;\n                value.custom = true;\n            } else {\n                value.name = builtinOperators.has(code) ? builtinOperators.get(code) : code.toString();\n                value.version = operator.version;\n                value.custom = false;\n            }\n            return value;\n        });\n        let modelMetadata = null;\n        for (const metadata of model.metadata) {\n            const buffer = model.buffers[metadata.buffer];\n            let data = null;\n            const position = stream.position;\n            if (buffer && buffer.data && buffer.data.length > 0) {\n                data = buffer.data;\n            } else if (buffer && buffer.offset !== 0n && buffer.size !== 0n) {\n                const offset = buffer.offset.toNumber();\n                const size = buffer.size.toNumber();\n                stream.seek(offset);\n                data = stream.read(size);\n            }\n            stream.seek(position);\n            if (data) {\n                switch (metadata.name) {\n                    case 'min_runtime_version': {\n                        const decoder = new TextDecoder('utf-8');\n                        this.runtime = decoder.decode(data);\n                        break;\n                    }\n                    case 'TFLITE_METADATA': {\n                        const reader = flatbuffers.BinaryReader.open(data);\n                        if (!reader || !circle.schema.ModelMetadata.identifier(reader)) {\n                            throw new circle.Error('Invalid TensorFlow Lite metadata.');\n                        }\n                        modelMetadata = circle.schema.ModelMetadata.create(reader);\n                        if (modelMetadata.name) {\n                            this.name = modelMetadata.name;\n                        }\n                        if (modelMetadata.version) {\n                            this.version = modelMetadata.version;\n                        }\n                        if (modelMetadata.description) {\n                            this.description = this.description ? [this.description, modelMetadata.description].join(' ') : modelMetadata.description;\n                        }\n                        if (modelMetadata.author) {\n                            this.metadata.push(new circle.Argument('author', modelMetadata.author));\n                        }\n                        if (modelMetadata.license) {\n                            this.metadata.push(new circle.Argument('license', modelMetadata.license));\n                        }\n                        break;\n                    }\n                    default: {\n                        const value = data.length < 256 && data.every((c) => c >= 32 && c < 128) ? String.fromCharCode.apply(null, data) : '?';\n                        const argument = new circle.Argument(metadata.name, value);\n                        this.metadata.push(argument);\n                        break;\n                    }\n                }\n            }\n        }\n        const subgraphs = model.subgraphs;\n        const subgraphsMetadata = modelMetadata ? modelMetadata.subgraph_metadata : null;\n        for (let i = 0; i < subgraphs.length; i++) {\n            const subgraph = subgraphs[i];\n            const name = subgraphs.length > 1 ? i.toString() : '';\n            const subgraphMetadata = subgraphsMetadata && i < subgraphsMetadata.length ? subgraphsMetadata[i] : null;\n            const signatures = model.signature_defs.filter((signature) => signature.subgraph_index === i);\n            const graph = new circle.Graph(metadata, subgraph, signatures, subgraphMetadata, name, operators, model, stream);\n            this.modules.push(graph);\n        }\n    }\n};\n\ncircle.Graph = class {\n\n    constructor(metadata, subgraph, signatures, subgraphMetadata, name, operators, model, stream) {\n        this.name = subgraph.name || name;\n        if (subgraph.operators.length === 0 && subgraph.tensors.length > 0 && operators.length === 0) {\n            operators.push({ name: 'Weights', custom: true });\n            const layers = new Map();\n            for (let i = 0; i < subgraph.tensors.length; i++) {\n                const tensor = subgraph.tensors[i];\n                const parts = tensor.name.split('.');\n                parts.pop();\n                const key = parts.join('.');\n                if (!layers.has(key)) {\n                    const operator = { opcode_index: 0, inputs: [], outputs: [] };\n                    layers.set(key, operator);\n                    subgraph.operators.push(operator);\n                }\n                const operator = layers.get(key);\n                operator.inputs.push(i);\n            }\n        }\n        const tensors = new Map();\n        tensors.map = (index, metadata) => {\n            if (index === -1) {\n                return null;\n            }\n            if (!tensors.has(index)) {\n                let tensor = { name: '' };\n                let initializer = null;\n                let description = '';\n                let denotation = '';\n                if (index < subgraph.tensors.length) {\n                    tensor = subgraph.tensors[index];\n                    const buffer = model.buffers[tensor.buffer];\n                    const is_variable = tensor.is_variable;\n                    const variable = is_variable || (buffer && buffer.data && buffer.data.length > 0) || (buffer && buffer.offset !== 0n && buffer.size !== 0n);\n                    initializer = variable ? new circle.Tensor(index, tensor, buffer, stream, is_variable) : null;\n                }\n                if (metadata) {\n                    description = metadata.description;\n                    const content = metadata.content;\n                    if (content) {\n                        const contentProperties = content.content_properties;\n                        if (contentProperties instanceof circle.schema.FeatureProperties) {\n                            denotation = 'Feature';\n                        } else if (contentProperties instanceof circle.schema.ImageProperties) {\n                            denotation = 'Image';\n                            switch (contentProperties.color_space) {\n                                case 0: denotation += '(Unknown)'; break;\n                                case 1: denotation += '(RGB)'; break;\n                                case 2: denotation += '(Grayscale)'; break;\n                                default: throw circle.Error(`Unsupported image color space '${contentProperties.color_space}'.`);\n                            }\n                        } else if (contentProperties instanceof circle.schema.BoundingBoxProperties) {\n                            denotation = 'BoundingBox';\n                        } else if (contentProperties instanceof circle.schema.AudioProperties) {\n                            denotation = `Audio(${contentProperties.sample_rate},${contentProperties.channels})`;\n                        }\n                    }\n                }\n                const value = new circle.Value(index, tensor, initializer, description, denotation);\n                tensors.set(index, value);\n            }\n            return tensors.get(index);\n        };\n        this.inputs = Array.from(subgraph.inputs).map((tensor_index, index) => {\n            const metadata = subgraphMetadata && index < subgraphMetadata.input_tensor_metadata.length ? subgraphMetadata.input_tensor_metadata[index] : null;\n            const value = tensors.map(tensor_index, metadata);\n            const values = value ? [value] : [];\n            const name = value ? value.name.split('\\n')[0] : '?';\n            return new circle.Argument(name, values);\n        });\n        this.outputs = Array.from(subgraph.outputs).map((tensor_index, index) => {\n            const metadata = subgraphMetadata && index < subgraphMetadata.output_tensor_metadata.length ? subgraphMetadata.output_tensor_metadata[index] : null;\n            const value = tensors.map(tensor_index, metadata);\n            const values = value ? [value] : [];\n            const name = value ? value.name.split('\\n')[0] : '?';\n            return new circle.Argument(name, values);\n        });\n        this.signatures = signatures.map((signature) => {\n            return new circle.Signature(signature, tensors);\n        });\n        this.nodes = Array.from(subgraph.operators).map((operator, index) => {\n            const opcode_index = operator.opcode_index;\n            const opcode = opcode_index < operators.length ? operators[opcode_index] : { name: `(${opcode_index})` };\n            return new circle.Node(metadata, operator, opcode, index.toString(), tensors);\n        });\n    }\n};\n\ncircle.Signature = class {\n\n    constructor(signature, tensors) {\n        this.name = signature.signature_key;\n        this.inputs = signature.inputs.map((input) => {\n            const value = tensors.map(input.tensor_index);\n            const values = value ? [value] : [];\n            return new circle.Argument(input.name, values);\n        });\n        this.outputs = signature.outputs.map((output) => {\n            const value = tensors.map(output.tensor_index);\n            const values = value ? [value] : [];\n            return new circle.Argument(output.name, values);\n        });\n    }\n};\n\ncircle.Node = class {\n\n    constructor(metadata, node, type, identifier, tensors) {\n        this.name = '';\n        this.identifier = identifier;\n        this.type = type.custom ? { name: type.name } : metadata.type(type.name);\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (node) {\n            const attributes = [];\n            const inputs = Array.from(node.inputs || new Int32Array(0));\n            for (let i = 0; i < inputs.length;) {\n                let count = 1;\n                let name = null;\n                let visible = true;\n                const values = [];\n                if (this.type && this.type.inputs && i < this.type.inputs.length) {\n                    const input = this.type.inputs[i];\n                    name = input.name;\n                    if (input.list) {\n                        count = inputs.length - i;\n                    }\n                    if (input.visible === false) {\n                        visible = false;\n                    }\n                }\n                for (const index of inputs.slice(i, i + count)) {\n                    const value = tensors.map(index);\n                    if (value) {\n                        values.push(value);\n                    }\n                }\n                name = name ? name : (i + 1).toString();\n                i += count;\n                const argument = new circle.Argument(name, values, null, visible);\n                this.inputs.push(argument);\n            }\n            const outputs = Array.from(node.outputs || new Int32Array(0));\n            for (let i = 0; i < outputs.length; i++) {\n                const index = outputs[i];\n                const value = tensors.map(index);\n                const values = value ? [value] : [];\n                let name = (i + 1).toString();\n                if (this.type && this.type.outputs && i < this.type.outputs.length) {\n                    const output = this.type.outputs[i];\n                    if (output && output.name) {\n                        name = output.name;\n                    }\n                }\n                const argument = new circle.Argument(name, values);\n                this.outputs.push(argument);\n            }\n            if (type.custom && node.custom_options && node.custom_options.length > 0) {\n                let decoded = false;\n                if (node.custom_options_format === circle.schema.CustomOptionsFormat.FLEXBUFFERS) {\n                    try {\n                        const reader = flexbuffers.BinaryReader.open(node.custom_options);\n                        if (reader) {\n                            const custom_options = reader.read();\n                            if (Array.isArray(custom_options)) {\n                                attributes.push([null, 'custom_options', custom_options]);\n                                decoded = true;\n                            } else if (custom_options) {\n                                for (const [key, value] of Object.entries(custom_options)) {\n                                    const schema = metadata.attribute(type.name, key);\n                                    attributes.push([schema, key, value]);\n                                }\n                                decoded = true;\n                            }\n                        }\n                    } catch {\n                        // continue regardless of error\n                    }\n                }\n                if (!decoded) {\n                    const schema = metadata.attribute(type.name, 'custom');\n                    attributes.push([schema, 'custom', Array.from(node.custom_options)]);\n                }\n            }\n            const options = node.builtin_options;\n            if (options) {\n                for (const [name, value] of Object.entries(options)) {\n                    if (name === 'fused_activation_function' && value) {\n                        const ActivationFunctionType = circle.schema.ActivationFunctionType;\n                        let type = '';\n                        switch (value) {\n                            case ActivationFunctionType.RELU: type = 'Relu'; break;\n                            case ActivationFunctionType.RELU_N1_TO_1: type = 'ReluN1To1'; break;\n                            case ActivationFunctionType.RELU6: type = 'Relu6'; break;\n                            case ActivationFunctionType.TANH: type = 'Tanh'; break;\n                            case ActivationFunctionType.SIGN_BIT: type = 'SignBit'; break;\n                            case 6: type = 'Sigmoid'; break;\n                            default: type = value.toString(); break;\n                        }\n                        const node = new circle.Node(metadata, null, { name: type }, null, []);\n                        this.chain = [node];\n                    }\n                    const schema = metadata.attribute(type.name, name);\n                    attributes.push([schema, name, value]);\n                }\n            }\n            this.attributes = attributes.map(([metadata, name, value]) => {\n                const type = metadata && metadata.type ? metadata.type : null;\n                value = ArrayBuffer.isView(value) ? Array.from(value) : value;\n                let visible = true;\n                if (name === 'fused_activation_function') {\n                    visible = false;\n                }\n                if (type) {\n                    const enumType = circle.schema[type];\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                }\n                if (metadata) {\n                    if (metadata.visible === false) {\n                        visible = false;\n                    } else if (metadata.default !== undefined) {\n                        if (typeof value === 'function') {\n                            value = value();\n                        }\n                        if (value === metadata.default) {\n                            visible = false;\n                        }\n                    }\n                }\n                return new circle.Argument(name, value, type, visible);\n            });\n        }\n    }\n};\n\ncircle.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\ncircle.Value = class {\n\n    constructor(index, tensor, initializer, description, denotation) {\n        const name = tensor.name || '';\n        this.name = `${name}\\n${index}`;\n        this.identifier = index.toString();\n        this.type = tensor.type !== undefined && tensor.shape !== undefined ? new circle.TensorType(tensor, denotation) : null;\n        this.initializer = initializer;\n        this.description = description;\n        const quantization = tensor.quantization;\n        if (quantization && (quantization.scale.length > 0 || quantization.zero_point.length > 0 || quantization.min.length > 0 || quantization.max.length)) {\n            this.quantization = {\n                type: 'linear',\n                dimension: quantization.quantized_dimension,\n                scale: quantization.scale,\n                offset: quantization.zero_point,\n                min: quantization.min,\n                max: quantization.max\n            };\n        }\n    }\n};\n\ncircle.Tensor = class {\n\n    constructor(index, tensor, buffer, stream, is_variable) {\n        this.identifier = index.toString();\n        this.name = tensor.name;\n        this.type = new circle.TensorType(tensor);\n        this.category = is_variable ? 'Variable' : '';\n        this.encoding = this.type.dataType === 'string' ? '|' : '<';\n        if (buffer && buffer.data && buffer.data.length > 0) {\n            this._data = buffer.data.slice(0);\n        } else if (buffer && buffer.offset !== 0n && buffer.size !== 0n) {\n            const offset = buffer.offset.toNumber();\n            const size = buffer.size.toNumber();\n            stream.seek(offset);\n            this._data = stream.stream(size);\n        } else {\n            this._data = null;\n        }\n    }\n\n    get values() {\n        switch (this.type.dataType) {\n            case 'string': {\n                let offset = 0;\n                const data = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);\n                const count = data.getInt32(0, true);\n                offset += 4;\n                const offsetTable = [];\n                for (let j = 0; j < count; j++) {\n                    offsetTable.push(data.getInt32(offset, true));\n                    offset += 4;\n                }\n                offsetTable.push(this._data.length);\n                const stringTable = [];\n                const utf8Decoder = new TextDecoder('utf-8');\n                for (let k = 0; k < count; k++) {\n                    const textArray = this._data.subarray(offsetTable[k], offsetTable[k + 1]);\n                    stringTable.push(utf8Decoder.decode(textArray));\n                }\n                return stringTable;\n            }\n            default: {\n                if (this._data instanceof Uint8Array) {\n                    return this._data;\n                }\n                if (this._data && this._data.peek) {\n                    return this._data.peek();\n                }\n                return null;\n            }\n        }\n    }\n};\n\ncircle.TensorType = class {\n\n    constructor(tensor, denotation) {\n        const shape = tensor.shape_signature && tensor.shape_signature.length > 0 ? tensor.shape_signature : tensor.shape;\n        switch (tensor.type) {\n            case circle.schema.TensorType.BOOL: this.dataType = 'boolean'; break;\n            default: {\n                const name = circle.schema.TensorType[tensor.type];\n                this.dataType = name ? name.toLowerCase() : '?';\n                break;\n            }\n        }\n        this.shape = new circle.TensorShape(Array.from(shape || []));\n        this.denotation = denotation;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ncircle.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n    }\n};\n\ncircle.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Circle model.';\n    }\n};\n\nexport const ModelFactory = circle.ModelFactory;\n"
  },
  {
    "path": "source/cntk-metadata.json",
    "content": "[\n  {\n    \"name\": \"Abs\",\n    \"identifier\": 8\n  },\n  {\n    \"name\": \"Acos\",\n    \"identifier\": 82\n  },\n  {\n    \"name\": \"Asin\",\n    \"identifier\": 81\n  },\n  {\n    \"name\": \"Asinh\",\n    \"identifier\": 86\n  },\n  {\n    \"name\": \"Assign\",\n    \"identifier\": 73\n  },\n  {\n    \"name\": \"Atan\",\n    \"identifier\": 96\n  },\n  {\n    \"name\": \"Atanh\",\n    \"identifier\": 85\n  },\n  {\n    \"name\": \"AveragePooling\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormalization\",\n    \"identifier\": 40,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"disableRegularization\", \"default\": false },\n      { \"name\": \"useCuDNNEngine\", \"visible\": false },\n      { \"name\": \"useCntkEngine\", \"visible\": false },\n      { \"name\": \"runCountUntied\", \"visible\": false },\n      { \"name\": \"epsilon\", \"default\": 0.00001 },\n      { \"name\": \"normalizationTimeConstant\", \"default\": 0 },\n      { \"name\": \"disableRegularization\", \"default\": false },\n      { \"name\": \"blendTimeConstant\", \"default\": 0 },\n      { \"name\": \"imageLayoutKind\", \"type\": \"ImageLayoutKind\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"count\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Block\",\n    \"identifier\": 57\n  },\n  {\n    \"name\": \"Cast\",\n    \"identifier\": 91\n  },\n  {\n    \"name\": \"ClassificationError\",\n    \"identifier\": 36,\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Clip\",\n    \"identifier\": 41\n  },\n  {\n    \"name\": \"Combine\",\n    \"identifier\": 44,\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConstantOp\",\n    \"identifier\": 89\n  },\n  {\n    \"name\": \"Convolution\",\n    \"identifier\": 33,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"transpose\", \"default\": false },\n      { \"name\": \"maxTempMemSizeInSamples\", \"default\": 0 },\n      { \"name\": \"dilation\", \"default\": [   1,   null ] },\n      { \"name\": \"outputShape\", \"default\": 0 },\n      { \"name\": \"sharing\", \"default\": [   true,   null ] },\n      { \"name\": \"strides\", \"default\": [   1,   null ] },\n      { \"name\": \"includePad\", \"default\": false },\n      { \"name\": \"ceilOutDim\", \"default\": false },\n      { \"name\": \"autoPadding\", \"default\": [   true,   null ] },\n      { \"name\": \"lowerPad\", \"default\": [   0,   null ] },\n      { \"name\": \"upperPad\", \"default\": [   0,   null ] },\n      { \"name\": \"convolution2D\", \"visible\": false },\n      { \"name\": \"poolKind\", \"type\": \"PoolKind\", \"default\": \"None\" },\n      { \"name\": \"imageLayoutKind\", \"type\": \"ImageLayoutKind\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"W\" },\n      { \"name\": \"b\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionSequenceShape\",\n    \"identifier\": 97\n  },\n  {\n    \"name\": \"Cos\",\n    \"identifier\": 55\n  },\n  {\n    \"name\": \"CosDistance\",\n    \"identifier\": 53\n  },\n  {\n    \"name\": \"CosDistanceWithNegativeSamples\",\n    \"identifier\": 67\n  },\n  {\n    \"name\": \"Cosh\",\n    \"identifier\": 78\n  },\n  {\n    \"name\": \"Crop\",\n    \"identifier\": 84,\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"CrossEntropyWithSoftmax\",\n    \"identifier\": 35,\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"CustomProxyOp\",\n    \"identifier\": 93\n  },\n  {\n    \"name\": \"Dropout\",\n    \"identifier\": 15,\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"rngSeed\", \"visible\": false },\n      { \"name\": \"rngOffset\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"EditDistanceError\",\n    \"identifier\": 61\n  },\n  {\n    \"name\": \"ElementTimes\",\n    \"identifier\": 21,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"ELU\",\n    \"identifier\": 65\n  },\n  {\n    \"name\": \"Equal\",\n    \"identifier\": 22,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"Exp\",\n    \"identifier\": 4,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"EyeLikeOp\",\n    \"identifier\": 92\n  },\n  {\n    \"name\": \"Floor\",\n    \"identifier\": 7,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ForwardBackward\",\n    \"identifier\": 66\n  },\n  {\n    \"name\": \"FutureValue\",\n    \"identifier\": 38,\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"uint32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"initialState\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Gather\",\n    \"identifier\": 74,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"GatherPacked\",\n    \"identifier\": 29,\n    \"inputs\": [\n      { \"name\": \"index\" },\n      { \"name\": \"source\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Greater\",\n    \"identifier\": 26,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"GreaterEqual\",\n    \"identifier\": 27,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"Hardmax\",\n    \"identifier\": 11,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"InvStdDev\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LabelsToGraph\",\n    \"identifier\": 63\n  },\n  {\n    \"name\": \"LambdaRank\",\n    \"identifier\": 59\n  },\n  {\n    \"name\": \"LatticeSequenceWithSoftmax\",\n    \"identifier\": 90\n  },\n  {\n    \"name\": \"Less\",\n    \"identifier\": 24,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"LessEqual\",\n    \"identifier\": 25,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"Log\",\n    \"identifier\": 5,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Logistic\",\n    \"identifier\": 48\n  },\n  {\n    \"name\": \"LogPlus\",\n    \"identifier\": 52\n  },\n  {\n    \"name\": \"LogSoftmax\",\n    \"identifier\": 51\n  },\n  {\n    \"name\": \"MaxPooling\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Mean\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Minus\",\n    \"identifier\": 20,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"NDCG\",\n    \"identifier\": 60\n  },\n  {\n    \"name\": \"Negate\",\n    \"identifier\": 0,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NoOp\",\n    \"identifier\": 62,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NotEqual\",\n    \"identifier\": 23,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"OneHot\",\n    \"identifier\": 68\n  },\n  {\n    \"name\": \"OptimizedRNNStack\",\n    \"identifier\": 49\n  },\n  {\n    \"name\": \"PackedIndex\",\n    \"identifier\": 28,\n    \"inputs\": [\n      { \"name\": \"source\" },\n      { \"name\": \"index\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Pad\",\n    \"identifier\": 83,\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Pass\",\n    \"identifier\": 56\n  },\n  {\n    \"name\": \"PastValue\",\n    \"identifier\": 37,\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"uint32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"initialState\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Plus\",\n    \"identifier\": 19,\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"Pooling\",\n    \"identifier\": 17,\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"transpose\", \"default\": false },\n      { \"name\": \"includePad\", \"default\": false },\n      { \"name\": \"ceilOutDim\", \"default\": false },\n      { \"name\": \"autoPadding\", \"default\": [   false,   null ] },\n      { \"name\": \"sharing\", \"default\": [   true,   null ] },\n      { \"name\": \"strides\", \"default\": [   1,   null ] },\n      { \"name\": \"lowerPad\", \"default\": [   0,   null ] },\n      { \"name\": \"upperPad\", \"default\": [   0,   null ] },\n      { \"name\": \"outputShape\", \"default\": 0 },\n      { \"name\": \"maxTempMemSizeInSamples\", \"default\": 0 },\n      { \"name\": \"poolingType\", \"type\": \"PoolingType\", \"default\": \"Max\" },\n      { \"name\": \"poolKind\", \"type\": \"PoolKind\", \"default\": \"None\" },\n      { \"name\": \"imageLayoutKind\", \"type\": \"ImageLayoutKind\", \"visible\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Pow\",\n    \"identifier\": 69\n  },\n  {\n    \"name\": \"RandomDistribution\",\n    \"identifier\": 76\n  },\n  {\n    \"name\": \"RandomSample\",\n    \"identifier\": 45\n  },\n  {\n    \"name\": \"RandomSampleInclusionFrequency\",\n    \"identifier\": 46\n  },\n  {\n    \"name\": \"Reciprocal\",\n    \"identifier\": 9,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReconcileDynamicAxis\",\n    \"identifier\": 50\n  },\n  {\n    \"name\": \"RectifiedLinear\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceElements\",\n    \"identifier\": 39,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReLU\",\n    \"identifier\": 3,\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"identifier\": 16,\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"identifier\": 47,\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"spatialScale\", \"default\": 0.0625 },\n      { \"name\": \"poolKind\", \"type\": \"PoolKind\", \"default\": \"None\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"ROIs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"outputs\" }\n    ]\n  },\n  {\n    \"name\": \"ScatterPacked\",\n    \"identifier\": 30\n  },\n  {\n    \"name\": \"Select\",\n    \"identifier\": 42\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"identifier\": 1,\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Sin\",\n    \"identifier\": 54\n  },\n  {\n    \"name\": \"Sinh\",\n    \"identifier\": 77\n  },\n  {\n    \"name\": \"Slice\",\n    \"identifier\": 14,\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"end\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"identifier\": 10,\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Splice\",\n    \"identifier\": 43,\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Sqrt\",\n    \"identifier\": 6,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SquaredError\",\n    \"identifier\": 34\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"identifier\": 88,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"StableSigmoid\",\n    \"identifier\": 75,\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"StopGradient\",\n    \"identifier\": 64\n  },\n  {\n    \"name\": \"StraightThrough\",\n    \"identifier\": 94\n  },\n  {\n    \"name\": \"SumAll\",\n    \"identifier\": 18\n  },\n  {\n    \"name\": \"Tan\",\n    \"identifier\": 95\n  },\n  {\n    \"name\": \"Tanh\",\n    \"identifier\": 2,\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Times\",\n    \"identifier\": 31,\n    \"attributes\": [\n      { \"name\": \"outputRank\", \"default\": 1 },\n      { \"name\": \"inferInputRankToMap\", \"visible\": false, \"default\": -1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"ToBatch\",\n    \"identifier\": 80\n  },\n  {\n    \"name\": \"TopK\",\n    \"identifier\": 87,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ToSequence\",\n    \"identifier\": 70\n  },\n  {\n    \"name\": \"ToSequenceLike\",\n    \"identifier\": 71\n  },\n  {\n    \"name\": \"TransposeAxes\",\n    \"identifier\": 12,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"TransposeDimensions\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"TransposeTimes\",\n    \"identifier\": 32\n  },\n  {\n    \"name\": \"UnpackBatch\",\n    \"identifier\": 79\n  },\n  {\n    \"name\": \"UnpackSequence\",\n    \"identifier\": 72\n  },\n  {\n    \"name\": \"Unpooling\",\n    \"identifier\": 58\n  },\n  {\n    \"name\": \"Where\",\n    \"identifier\": 13,\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/cntk-proto.js",
    "content": "\nexport const CNTK = {};\n\nCNTK.proto = {};\n\nCNTK.proto.NDShape = class NDShape {\n\n    constructor() {\n        this.shape_dim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.NDShape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape_dim = reader.array(message.shape_dim, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.Axis = class Axis {\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.Axis();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.static_axis_idx = reader.int32();\n                    break;\n                case 2:\n                    message.name = reader.string();\n                    break;\n                case 3:\n                    message.is_ordered_dynamic_axis = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.Axis.prototype.static_axis_idx = 0;\nCNTK.proto.Axis.prototype.name = \"\";\nCNTK.proto.Axis.prototype.is_ordered_dynamic_axis = false;\n\nCNTK.proto.NDArrayView = class NDArrayView {\n\n    get values() {\n        CNTK.proto.NDArrayView.valuesSet = CNTK.proto.NDArrayView.valuesSet || new Set([\"float_values\", \"double_values\", \"bytes_value\", \"sint32_values\"]);\n        return Object.keys(this).find((key) => CNTK.proto.NDArrayView.valuesSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.NDArrayView();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.data_type = reader.int32();\n                    break;\n                case 2:\n                    message.storage_format = reader.int32();\n                    break;\n                case 3:\n                    message.shape = CNTK.proto.NDShape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.float_values = CNTK.proto.NDArrayView.FloatValues.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.double_values = CNTK.proto.NDArrayView.DoubleValues.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.bytes_value = CNTK.proto.NDArrayView.BytesValue.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.sint32_values = CNTK.proto.NDArrayView.IntValues.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.NDArrayView.prototype.data_type = 0;\nCNTK.proto.NDArrayView.prototype.storage_format = 0;\nCNTK.proto.NDArrayView.prototype.shape = null;\n\nCNTK.proto.NDArrayView.DataType = {\n    \"Unknown\": 0,\n    \"Float\": 1,\n    \"Double\": 2,\n    \"Float16\": 4,\n    \"Int8\": 5,\n    \"Int16\": 6\n};\n\nCNTK.proto.NDArrayView.StorageFormat = {\n    \"Dense\": 0,\n    \"SparseCSC\": 1,\n    \"SparseBlockCol\": 2\n};\n\nCNTK.proto.NDArrayView.FloatValues = class FloatValues {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.NDArrayView.FloatValues();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.floats(message.value, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.NDArrayView.DoubleValues = class DoubleValues {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.NDArrayView.DoubleValues();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.doubles(message.value, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.NDArrayView.BytesValue = class BytesValue {\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.NDArrayView.BytesValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.NDArrayView.BytesValue.prototype.value = new Uint8Array([]);\n\nCNTK.proto.NDArrayView.IntValues = class IntValues {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.NDArrayView.IntValues();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.array(message.value, () => reader.sint32(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.Vector = class Vector {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.Vector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value.push(CNTK.proto.DictionaryValue.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.Dictionary = class Dictionary {\n\n    constructor() {\n        this.data = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.Dictionary();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.uint64();\n                    break;\n                case 2:\n                    reader.entry(message.data, () => reader.string(), () => CNTK.proto.DictionaryValue.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.Dictionary.prototype.version = 0n;\n\nCNTK.proto.DictionaryValue = class DictionaryValue {\n\n    get value() {\n        CNTK.proto.DictionaryValue.valueSet = CNTK.proto.DictionaryValue.valueSet || new Set([\"bool_value\", \"int_value\", \"size_t_value\", \"float_value\", \"double_value\", \"string_value\", \"nd_shape_value\", \"axis_value\", \"vector_value\", \"dictionary_value\", \"nd_array_view_value\"]);\n        return Object.keys(this).find((key) => CNTK.proto.DictionaryValue.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CNTK.proto.DictionaryValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.uint64();\n                    break;\n                case 2:\n                    message.value_type = reader.int32();\n                    break;\n                case 3:\n                    message.bool_value = reader.bool();\n                    break;\n                case 4:\n                    message.int_value = reader.int32();\n                    break;\n                case 5:\n                    message.size_t_value = reader.uint64();\n                    break;\n                case 6:\n                    message.float_value = reader.float();\n                    break;\n                case 7:\n                    message.double_value = reader.double();\n                    break;\n                case 8:\n                    message.string_value = reader.string();\n                    break;\n                case 9:\n                    message.nd_shape_value = CNTK.proto.NDShape.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.axis_value = CNTK.proto.Axis.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.vector_value = CNTK.proto.Vector.decode(reader, reader.uint32());\n                    break;\n                case 12:\n                    message.dictionary_value = CNTK.proto.Dictionary.decode(reader, reader.uint32());\n                    break;\n                case 13:\n                    message.nd_array_view_value = CNTK.proto.NDArrayView.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCNTK.proto.DictionaryValue.prototype.version = 0n;\nCNTK.proto.DictionaryValue.prototype.value_type = 0;\n\nCNTK.proto.DictionaryValue.Type = {\n    \"None\": 0,\n    \"Bool\": 1,\n    \"Int\": 2,\n    \"SizeT\": 3,\n    \"Float\": 4,\n    \"Double\": 5,\n    \"String\": 6,\n    \"NDShape\": 7,\n    \"Axis\": 8,\n    \"Vector\": 9,\n    \"Dictionary\": 10,\n    \"NDArrayView\": 11\n};\n"
  },
  {
    "path": "source/cntk.js",
    "content": "\nconst cntk = {};\n\ncntk.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        // CNTK v1\n        const signature = [0x42, 0x00, 0x43, 0x00, 0x4e, 0x00, 0x00, 0x00];\n        if (stream && signature.length <= stream.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {\n            return context.set('cntk.v1');\n        }\n        // CNTK v2\n        const tags = await context.tags('pb');\n        if (tags.get(1) === 0 && tags.get(2) === 2) {\n            return context.set('cntk.v2');\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('cntk-metadata.json');\n        switch (context.type) {\n            case 'cntk.v1': {\n                let obj = null;\n                try {\n                    const reader = await context.read('binary');\n                    obj = new cntk.ComputationNetwork(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new cntk.Error(`File format is not CNTK v1 (${message.replace(/\\.$/, '')}).`);\n                }\n                return new cntk.Model(metadata, 1, obj);\n            }\n            case 'cntk.v2': {\n                cntk.proto = await context.require('./cntk-proto');\n                cntk.proto = cntk.proto.CNTK.proto;\n                cntk.proto.PoolingType = { 0: 'Max', 1: 'Average' };\n                let obj = null;\n                try {\n                    const reader = await context.read('protobuf.binary');\n                    const dictionary = cntk.proto.Dictionary.decode(reader);\n                    obj = cntk.ModelFactory._convertDictionary(dictionary);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new cntk.Error(`File format is not cntk.Dictionary (${message.replace(/\\.$/, '')}).`);\n                }\n                return new cntk.Model(metadata, 2, obj);\n            }\n            default: {\n                throw new cntk.Error(`Unsupported CNTK format '${context.type}'.`);\n            }\n        }\n    }\n\n    static _convertDictionary(dictionary) {\n        const target = {};\n        for (const key of Object.keys(dictionary.data).filter((key) => key !== 'version')) {\n            target[key] = cntk.ModelFactory._convertDictionaryValue(dictionary.data[key]);\n        }\n        return target;\n    }\n\n    static _convertDictionaryValue(dictionaryValue) {\n        switch (dictionaryValue.value_type) {\n            case cntk.proto.DictionaryValue.Type.Bool:\n                return dictionaryValue.bool_value;\n            case cntk.proto.DictionaryValue.Type.Int:\n                return dictionaryValue.int_value;\n            case cntk.proto.DictionaryValue.Type.SizeT:\n                return dictionaryValue.size_t_value;\n            case cntk.proto.DictionaryValue.Type.Float:\n                return dictionaryValue.float_value;\n            case cntk.proto.DictionaryValue.Type.Double:\n                return dictionaryValue.double_value;\n            case cntk.proto.DictionaryValue.Type.String:\n                return dictionaryValue.string_value;\n            case cntk.proto.DictionaryValue.Type.Vector:\n                return cntk.ModelFactory._convertVectorValue(dictionaryValue.vector_value);\n            case cntk.proto.DictionaryValue.Type.NDShape:\n                return dictionaryValue.nd_shape_value;\n            case cntk.proto.DictionaryValue.Type.Axis:\n                return dictionaryValue.axis_value;\n            case cntk.proto.DictionaryValue.Type.Dictionary:\n                return cntk.ModelFactory._convertDictionary(dictionaryValue.dictionary_value);\n            case cntk.proto.DictionaryValue.Type.NDArrayView:\n                return dictionaryValue.nd_array_view_value;\n            default:\n                throw new cntk.Error(`Unsupported dictionary value type '${dictionaryValue.value_type}'.`);\n        }\n    }\n\n    static _convertVectorValue(vectorValue) {\n        return vectorValue.value.map((item) => {\n            return cntk.ModelFactory._convertDictionaryValue(item);\n        });\n    }\n};\n\ncntk.Model = class {\n\n    constructor(metadata, version, obj) {\n        switch (version) {\n            case 1:\n                this.format = `CNTK v1${obj.version ? (`.${obj.version}`) : ''}`;\n                break;\n            case 2:\n                this.format = 'CNTK v2';\n                break;\n            default:\n                throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n        }\n        this.modules = [new cntk.Graph(metadata, version, obj)];\n    }\n};\n\ncntk.Graph = class {\n\n    constructor(metadata, version, obj) {\n        metadata = new cntk.GraphMetadata(metadata);\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.map = (name, version, obj) => {\n            if (obj && values.has(name)) {\n                throw new cntk.Error(`Duplicate value '${name}'.`);\n            }\n            if (!values.has(name)) {\n                switch (version) {\n                    case 1:\n                        values.set(name, new cntk.Value(version, obj ? obj : { name }));\n                        break;\n                    case 2:\n                        values.set(name, new cntk.Value(version, obj ? obj : { uid: name }));\n                        break;\n                    default:\n                        throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n                }\n            }\n            return values.get(name);\n        };\n        switch (version) {\n            case 1: {\n                for (const name of Object.keys(obj.nodes)) {\n                    const node = obj.nodes[name];\n                    switch (node.__type__) {\n                        case 'InputValue': {\n                            const argument = new cntk.Argument(node.name, [values.map(node.name, version, node)]);\n                            this.inputs.push(argument);\n                            break;\n                        }\n                        case 'LearnableParameter': {\n                            values.map(node.name, version, node);\n                            break;\n                        }\n                        default:\n                            break;\n                    }\n                }\n                for (const name of Object.keys(obj.nodes)) {\n                    const node = obj.nodes[name];\n                    if (node.__type__ !== 'InputValue' && node.__type__ !== 'LearnableParameter') {\n                        this.nodes.push(new cntk.Node(metadata, version, node, values));\n                    }\n                }\n                if (obj.output) {\n                    for (const output of obj.output) {\n                        const argument = new cntk.Argument(output, [values.map(output, version)]);\n                        this.outputs.push(argument);\n                    }\n                }\n                break;\n            }\n            case 2: {\n                const map = new Map(obj.primitive_functions.map((node) => [node.uid, node]));\n                for (const input of obj.inputs) {\n                    const value = values.map(input.uid, version, input);\n                    // VariableKind { 0: 'input', 1: 'output', 2: 'parameter', 3: 'constant', 4: 'placeholder' }\n                    if (input.kind === 0n) {\n                        const inputName = input.name || input.uid;\n                        this.inputs.push(new cntk.Argument(inputName, [value]));\n                    }\n                }\n                for (const block of obj.primitive_functions) {\n                    if (block.op === 57n && block.block_function_composite) {\n                        const list = [block.block_function_composite.root];\n                        const output = map.get(block.block_function_composite.root);\n                        const keys = block.block_function_composite_arguments_map_keys;\n                        const args = block.block_function_composite_arguments_map_values;\n                        block.inputs = args;\n                        if (!Array.isArray(keys) || !Array.isArray(args) || keys.length !== args.length) {\n                            throw new cntk.Error('Invalid block function composite arguments.');\n                        }\n                        const inputs = keys.map((key) => new cntk.Argument(key, [values.map(key, version)]));\n                        const outputs = [new cntk.Argument('output', [values.map(`${output.uid}_Output_0`, version)])];\n                        const nodes = [];\n                        while (list.length > 0) {\n                            const name = list.shift();\n                            if (map.has(name)) {\n                                const node = map.get(name);\n                                nodes.push(new cntk.Node(metadata, version, node, values));\n                                map.delete(name);\n                                for (let i = 0; i < node.inputs.length; i++) {\n                                    const parts = node.inputs[i].split('_');\n                                    if (parts.length >= 3) {\n                                        parts.pop();\n                                        if (parts.pop() === 'Output') {\n                                            list.push(parts.join('_'));\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        const func = new cntk.Function(block.block_function_op_name, nodes, inputs, outputs);\n                        metadata.add(block.uid, func);\n                    }\n                }\n                for (const node of map.values()) {\n                    this.nodes.push(new cntk.Node(metadata, version, node, values));\n                }\n                break;\n            }\n            default: {\n                throw new cntk.Error(`Unsupported graph version '${version}'.`);\n            }\n        }\n    }\n};\n\ncntk.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\ncntk.Value = class {\n\n    constructor(version, obj) {\n        switch (version) {\n            case 1:\n                switch (obj.__type__) {\n                    case 'InputValue':\n                        this.name = obj.name;\n                        this.type = new cntk.TensorType(version, obj.precision, obj.sampleLayout);\n                        this.initializer = null;\n                        break;\n                    case 'LearnableParameter':\n                        this.name = obj.name;\n                        this.initializer = new cntk.Tensor(version, obj);\n                        this.type = this.initializer.type;\n                        break;\n                    default:\n                        this.name = obj.name;\n                        this.type = null;\n                        this.initializer = null;\n                        break;\n                }\n                break;\n            case 2:\n                if (obj.value) {\n                    this.name = obj.name || obj.uid;\n                    this.initializer = new cntk.Tensor(version, obj);\n                    this.type = this.initializer.type;\n                } else {\n                    this.name = obj.uid;\n                    if (obj.data_type && obj.shape) {\n                        this.type = new cntk.TensorType(version, obj.data_type, obj.shape);\n                    }\n                    this.initializer = null;\n                }\n                break;\n            default:\n                throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n        }\n    }\n};\n\ncntk.Node = class {\n\n    constructor(metadata, version, obj, values) {\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        let inputs = [];\n        let outputs = [];\n        const attributes = [];\n        switch (version) {\n            case 1: {\n                const type = obj.__type__;\n                this.type = { name: type, ...metadata.type(type) };\n                delete this.type.identifier;\n                this.name = obj.name;\n                for (const [name, value] of Object.entries(obj)) {\n                    if (name !== '__type__' && name !== 'name' && name !== 'inputs' && name !== 'precision') {\n                        const schema = metadata.attribute(type, name);\n                        attributes.push([schema, name, value]);\n                    }\n                }\n                inputs = obj.inputs.map((input) => values.map(input, version));\n                outputs = [values.map(this.name, version)];\n                break;\n            }\n            case 2: {\n                this.name = obj.name || obj.uid || null;\n                const output = obj.uid;\n                if (obj.op === 57n) {\n                    this.type = { name: obj.uid, ...metadata.type(obj.uid) };\n                    delete this.type.identifier;\n                } else if (Object.prototype.hasOwnProperty.call(obj, 'op')) {\n                    // cntk/Source/CNTKv2LibraryDll/API/Internals/PrimitiveOpType.h\n                    const op = obj.op.toNumber();\n                    this.type = { ...metadata.type(op) };\n                    delete this.type.identifier;\n                } else {\n                    const type = obj.type;\n                    this.type = { name: type, ...metadata.type(type) };\n                    delete this.type.identifier;\n                    if (obj.user_defined_state) {\n                        for (const [name, value] of Object.entries(obj.user_defined_state)) {\n                            const schema = metadata.attribute(type, name);\n                            attributes.push([schema, name, value]);\n                        }\n                    }\n                }\n                if (obj.attributes) {\n                    for (const [name, value] of Object.entries(obj.attributes)) {\n                        const schema = metadata.attribute(this.type, name);\n                        attributes.push([schema, name, value]);\n                    }\n                }\n                inputs = obj.inputs.map((input) => values.map(input, version));\n                outputs.push(values.map(`${output}_Output_0`, version));\n                break;\n            }\n            default: {\n                throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n            }\n        }\n        let inputIndex = 0;\n        if (this.type && this.type.inputs) {\n            for (const schema of this.type.inputs) {\n                if (inputIndex < inputs.length || schema.option !== 'optional') {\n                    const count = schema.type === 'Tensor[]' ? (inputs.length - inputIndex) : 1;\n                    const values = [];\n                    for (const value of inputs.slice(inputIndex, inputIndex + count)) {\n                        if (value.name !== '' || schema.option !== 'optional') {\n                            values.push(value);\n                        }\n                    }\n                    const argument = new cntk.Argument(schema.name, values);\n                    this.inputs.push(argument);\n                    inputIndex += count;\n                }\n            }\n        }\n        this.inputs.push(...inputs.slice(inputIndex).map((argument, index) => {\n            return new cntk.Argument((inputIndex + index).toString(), [argument]);\n        }));\n        let outputIndex = 0;\n        if (this.type && this.type.outputs) {\n            for (const schema of this.type.outputs) {\n                if (outputIndex < outputs.length || !schema.optional) {\n                    const count = schema.type === 'Tensor[]' ? (outputs.length - outputIndex) : 1;\n                    const values = outputs.slice(outputIndex, outputIndex + count);\n                    const argument = new cntk.Argument(schema.name, values);\n                    this.outputs.push(argument);\n                    outputIndex += count;\n                }\n            }\n        }\n        this.outputs.push(...outputs.slice(outputIndex).map((argument) => {\n            return new cntk.Argument(outputIndex.toString(), [argument]);\n        }));\n        this.attributes = attributes.map(([metadata, name, value]) => {\n            let type = null;\n            let visible = true;\n            if (value && value.__type__ === 'shape') {\n                value = new cntk.TensorShape(1, value);\n                type = 'shape';\n            }\n            if (cntk.proto && value instanceof cntk.proto.NDShape) {\n                value = new cntk.TensorShape(2, value);\n                type = 'shape';\n            }\n            if (cntk.proto && value instanceof cntk.proto.Axis) {\n                const axis = { __type__: 'Axis' };\n                for (const key of Object.keys(value).filter((key) => key !== 'name')) {\n                    axis[key] = value[key];\n                }\n                value = axis;\n            }\n            if (metadata) {\n                if (metadata.type) {\n                    type = metadata.type;\n                    const table = cntk[type] || cntk.proto[type];\n                    if (table && table[value]) {\n                        value = table[value];\n                    }\n                }\n                if (metadata.visible === false) {\n                    visible = false;\n                } else if (metadata.default !== undefined) {\n                    const defaultValue = metadata.default;\n                    if (typeof value === 'function') {\n                        value = value();\n                    }\n                    if (type === 'shape') {\n                        value = value.dimensions;\n                    }\n                    if (value === defaultValue) {\n                        visible = false;\n                    } else if (Array.isArray(value) && Array.isArray(defaultValue)) {\n                        const repeat = defaultValue.length > 1 && defaultValue[defaultValue.length - 1] === null;\n                        if (value.every((item, index) => item === (repeat && index >= defaultValue.length - 1 ? defaultValue[defaultValue.length - 2] : defaultValue[index]))) {\n                            visible = false;\n                        }\n                    }\n                }\n            }\n            return new cntk.Argument(name, value, type, visible);\n        });\n    }\n};\n\ncntk.Tensor = class {\n\n    constructor(version, tensor) {\n        this.encoding = '|';\n        this.values = null;\n        switch (version) {\n            case 1: {\n                if (tensor.__type__ === 'LearnableParameter') {\n                    this.name = tensor.name || null;\n                    this.type = new cntk.TensorType(version, tensor.precision, tensor.sampleLayout);\n                }\n                break;\n            }\n            case 2: {\n                this.name = tensor.name || tensor.uid || null;\n                this.type = new cntk.TensorType(version, tensor.data_type, tensor.shape);\n                const value = tensor.value;\n                if (this.type.dataType === 'float32' && value && value.float_values && value.float_values.value && value.float_values.value.length > 0) {\n                    this.values = value.float_values.value;\n                }\n                break;\n            }\n            default:\n                throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n        }\n    }\n};\n\ncntk.TensorType = class {\n\n    constructor(version, dataType, shape) {\n        this.dataType = '?';\n        switch (version) {\n            case 1:\n                switch (dataType) {\n                    case 'float': this.dataType = 'float32'; break;\n                    case 'double': this.dataType = 'float64'; break;\n                    case 'half': this.dataType = 'float16'; break;\n                    case '': this.dataType = 'float32'; break;\n                    default: throw new cntk.Error(`Unsupported tensor data type '${dataType}'.`);\n                }\n                this.shape = new cntk.TensorShape(version, shape);\n                break;\n            case 2:\n                switch (dataType) {\n                    case 1n: this.dataType = 'float32'; break;\n                    default: throw new cntk.Error(`Unsupported tensor data type '${dataType}'.`);\n                }\n                this.shape = new cntk.TensorShape(version, shape);\n                break;\n            default:\n                throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n        }\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ncntk.TensorShape = class {\n\n    constructor(version, shape) {\n        switch (version) {\n            case 1:\n                this.dimensions = shape.dims;\n                break;\n            case 2:\n                this.dimensions = shape.shape_dim.map((dimension) => dimension.toNumber());\n                break;\n            default:\n                throw new cntk.Error(`Unsupported CNTK version '${version}'.`);\n        }\n    }\n\n    toString() {\n        return (this.dimensions && this.dimensions.length) ? (`[${this.dimensions.join(',')}]`) : '';\n    }\n};\n\ncntk.Function = class {\n\n    constructor(name, nodes, inputs, outputs) {\n        this.type = 'function';\n        this.name = name;\n        this.inputs = inputs;\n        this.outputs = outputs;\n        this.nodes = nodes;\n        switch (this.name) {\n            case 'PReLU':\n            case 'Softmax':\n                this.category = 'Activation';\n                break;\n            case 'Dropout':\n                this.category = 'Dropout';\n                break;\n            case 'Convolution':\n            case 'ConvolutionTranspose':\n            case 'Dense':\n            case 'linear':\n            case 'LSTM':\n                this.category = 'Layer';\n                break;\n            case 'BatchNormalization':\n            case 'lrn':\n                this.category = 'Normalization';\n                break;\n            case 'AveragePooling':\n            case 'MaxPooling':\n                this.category = 'Pool';\n                break;\n            default:\n                this.category = null;\n                break;\n        }\n    }\n};\n\ncntk.GraphMetadata = class {\n\n    constructor(metadata) {\n        this._metadata = metadata;\n        this._functions = new Map();\n        this._attributes = new Map();\n    }\n\n    add(name, func) {\n        if (this._functions.has(name)) {\n            throw new cntk.Error(`Duplicate function identifier '${func.name}'.`);\n        }\n        this._functions.set(name, func);\n    }\n\n    name(code) {\n        // cntk/Source/CNTKv2LibraryDll/API/Internals/PrimitiveOpType.h\n        return this._metadata.name(code);\n    }\n\n    type(name) {\n        if (this._functions.has(name)) {\n            return this._functions.get(name);\n        }\n        return this._metadata.type(name);\n    }\n\n    attribute(type, name) {\n        const key = `${type}:${name}`;\n        if (!this._attributes.has(key)) {\n            const metadata = this.type(type);\n            if (metadata && metadata.attributes && metadata.attributes.length > 0) {\n                for (const attribute of metadata.attributes) {\n                    this._attributes.set(`${type}:${attribute.name}`, attribute);\n                }\n            }\n            if (!this._attributes.has(key)) {\n                this._attributes.set(key, null);\n            }\n        }\n        return this._attributes.get(key);\n    }\n};\n\ncntk.ComputationNetwork = class {\n\n    constructor(reader) {\n        reader = new cntk.BinaryReader(reader);\n        const shape = (dims) => {\n            return { __type__: 'shape', dims };\n        };\n        reader.assert('BCN');\n        reader.assert('BVersion');\n        this.version = reader.uint64().toNumber();\n        reader.assert('EVersion');\n        const numNodes = reader.uint64().toNumber();\n        reader.assert('BNodeList');\n        const op = {};\n        op.Minus = function() {};\n        op.Plus = function() {};\n        op.GreaterEqual = function() {};\n        op.Equal = function() {};\n        op.NotEqual = function() {};\n        op.GreaterEqual = function() {};\n        op.Exp = function() {};\n        op.Log = function() {};\n        op.Reciprocal = function() {};\n        op.ElementTimes = function() {};\n        op.ClassificationError = function() {};\n        op.RectifiedLinear = function() {};\n        op.InputValue = function(reader, version) {\n            this.rows = reader.uint64().toNumber();\n            this.cols = reader.uint64().toNumber();\n            this.sampleLayout = reader.shape(true);\n            this.dynamicAxisNodeName = '';\n            if (version >= 8) {\n                const nrAxes = reader.uint32();\n                if (nrAxes === 1) {\n                    this.dynamicAxisNodeName = reader.string();\n                }\n            }\n            this.learningRateMultiplier = 0;\n            if (version >= 10) {\n                this.learningRateMultiplier = reader.float32();\n            }\n        };\n        op.LearnableParameter = function(reader, version) {\n            if (version >= 3) {\n                this.learningRateMultiplier = reader.float32();\n                this.sampleLayout = reader.shape(false);\n            } else {\n                throw new cntk.Error('LeanableParameter reader implemented.');\n            }\n            this.value = reader.matrix();\n        };\n        op.CrossEntropyWithSoftmax = function(reader) {\n            this.evalMode = reader.uint32();\n            if (this.evalMode > 2) {\n                this.evalMode = 0;\n                reader.skip(-4);\n            }\n        };\n        op.Times = function(reader, version) {\n            this.outputRank = (version >= 3) ? reader.uint64().toNumber() : 1;\n            this.inferInputRankToMap = (version >= 12) ? reader.int32() : -1;\n        };\n        op.Dropout = function(reader, version) {\n            if (version >= 16) {\n                this.rngSeed = (version === 16) ? reader.uint32() : reader.uint64().toNumber();\n                this.rngOffset = reader.uint64().toNumber();\n            }\n        };\n        op.ConvolutionBase = function(reader, version) {\n            if (version >= 5) {\n                this.kernelShape = reader.shape(false);\n                this.mapCount = reader.shape(false);\n                this.strides = reader.shape(false);\n                this.sharing = reader.booleans();\n                this.autoPadding = reader.booleans();\n                this.lowerPad = reader.shape(false);\n                this.upperPad = reader.shape(false);\n                this.poolKind = reader.int32();\n                this.imageLayoutKind = reader.int32();\n                this.maxTempMemSizeInSamples = reader.uint64().toNumber();\n            }\n            if (version >= 9) {\n                this.transpose = reader.boolean();\n            }\n            if (version >= 20) {\n                this.outputShape = reader.shape(false);\n            }\n            if (version >= 21) {\n                this.ceilOutDim = reader.boolean();\n            }\n            if (version >= 23) {\n                this.includePad = reader.boolean();\n            }\n        };\n        op.Convolution = function(reader, version) {\n            op.ConvolutionBase.apply(this, [reader, version]);\n            if (version < 5) {\n                this.kernelShape = shape([reader.uint64().toNumber(), reader.uint64().toNumber(), 1]);\n                this.strides = shape([reader.uint64().toNumber(), reader.uint64().toNumber(), 1]);\n                this.mapCount = shape([reader.uint32()]);\n                this.imageLayoutKind = reader.int32();\n                this.autoPadding = [reader.boolean()];\n                this.maxTempMemSizeInSamples = reader.uint64().toNumber();\n                this.poolKind = 'None';\n                this.convolution2D = true;\n                this.sharing = [true];\n                this.lowerPad = shape([0]);\n                this.upperPad = shape([0]);\n            } else {\n                this.convolution2D = reader.boolean();\n                if (version >= 18) {\n                    this.dilation = reader.shape();\n                } else {\n                    this.dilation = shape([1]);\n                }\n            }\n        };\n        op.Pooling = function(reader, version) {\n            op.ConvolutionBase.apply(this, [reader, version]);\n        };\n        op.PoolingBase = function(reader) {\n            this.imageLayoutKind = reader.int32();\n            this.windowWidth = reader.uint32();\n            this.windowHeight = reader.uint64().toNumber();\n            this.horizontalSubsample = reader.uint64().toNumber();\n            this.verticalSubsample = reader.uint64().toNumber();\n        };\n        op.MaxPooling = function(reader, version) {\n            op.PoolingBase.apply(this, [reader, version]);\n        };\n        op.ROIPooling = function(reader, version) {\n            this.roiOutputShape = reader.shape(false);\n            this.poolKind = (version < 26) ? 'Max' : reader.int32();\n            this.spatialScale = (version < 26) ? 0.0625 : reader.float64();\n        };\n        op.Reshape = function(reader) {\n            this.beginDimParameter = reader.uint32();\n            this.endDimParameter = reader.uint32();\n            this.replacementSampleLayout = reader.shape(false);\n        };\n        op.ReduceElements = function(reader, version) {\n            let num_axes = 1;\n            if (version >= 27) {\n                num_axes = reader.uint32();\n            }\n            this.axes = [];\n            for (let i = 0; i < num_axes; i++) {\n                this.axes.push(reader.uint32());\n            }\n            this.operation = reader.string();\n            if (version >= 24) {\n                this.keepDimensions = reader.boolean();\n            }\n        };\n        op.BatchNormalization = function(reader, version) {\n            let mbCount = 0;\n            if (version >= 6) {\n                this.spatial = reader.boolean();\n                this.normalizationTimeConstant = reader.float64();\n                this.blendTimeConstant = reader.float64();\n                this.imageLayoutKind = reader.int32();\n                if (version >= 13) {\n                    if (version === 19) {\n                        this.runCountUntied = reader.boolean() ? 0 : 'SIZE_MAX';\n                    } else {\n                        this.runCountUntied = reader.uint64().toNumber();\n                    }\n                } else {\n                    mbCount = reader.uint64().toNumber();\n                }\n                this.epsilon = reader.float64();\n                this.useCntkEngine = reader.boolean();\n            } else {\n                const verWritten = reader.int32();\n                const verReadable = reader.int32();\n                if (verReadable > verWritten || verWritten < 0x00010001 || verReadable > 0x00010004) {\n                    throw new cntk.Error('BatchNormalization version not supported.');\n                }\n                this.eval = reader.boolean();\n                this.spatial = reader.boolean();\n                if (verWritten >= 0x00010004) {\n                    this.normalizationTimeConstant = reader.float64();\n                } else {\n                    reader.float64(); // expAvgFactor\n                }\n                if (verWritten >= 0x00010002) {\n                    this.imageLayoutKind = reader.int32();\n                    mbCount = reader.uint64().toNumber();\n                }\n                if (verWritten >= 0x00010003) {\n                    this.epsilon = reader.float64();\n                    this.useCntkEngine = reader.boolean();\n                }\n            }\n            if (version < 13) {\n                this.runCountUntied = 16 * mbCount;\n                this.convertRunningVariancePending = true;\n            }\n        };\n        op.Tanh = function() {};\n        op.Sigmoid = function() {};\n        op.Logistic = function() {};\n        op.SquareError = function() {};\n        op.ErrorPrediction = function() {};\n        op.RowStack = function(reader, version) {\n            this.spliceDim = (version >= 3) ? reader.int32() : 1;\n        };\n        op.Slice = function(reader, version) {\n            let num = 1;\n            if (version >= 22) {\n                num = reader.int32();\n            }\n            this.index = [];\n            this.axis = [];\n            this.strideMultiplier = [];\n            for (let i = 0; i < num; i++) {\n                this.index.push([[reader.uint64().toNumber(), reader.uint64().toNumber()]]);\n                if (version >= 3) {\n                    this.axis.push(reader.int32());\n                }\n                if (version >= 27) {\n                    this.strideMultiplier.push(reader.int32());\n                }\n            }\n        };\n        op.PastValue = function(reader, version) {\n            this.timeStep = reader.int32();\n            if (version > 3) {\n                this.sampleLayout = reader.shape(false);\n            } else {\n                const rows = reader.uint64().toNumber();\n                reader.uint64();\n                this.sampleLayout = shape([rows], true);\n            }\n            if (version >= 2) {\n                this.initialStateValue = reader.int32();\n            }\n        };\n        op.FutureValue = function(reader, version) {\n            this.timeStep = reader.int32();\n            if (version > 3) {\n                this.sampleLayout = reader.shape(false);\n            } else {\n                const rows = reader.uint64().toNumber();\n                reader.uint64();\n                this.sampleLayout = shape([rows], true);\n            }\n            if (version >= 2) {\n                this.initialStateValue = reader.int32();\n            }\n        };\n        op.TransposeDimensions = function(reader, version) {\n            if (version >= 3) {\n                this.axis1 = reader.int32();\n                this.axis2 = reader.int32();\n                if (version >= 25 && this.axis1 === 0 && this.axis2 === 0) {\n                    const size = reader.uint64().toNumber();\n                    this.perm = [];\n                    for (let i = 0; i < size; i++) {\n                        this.perm.push(reader.uint64().toNumber());\n                    }\n                }\n            } else {\n                this.axis1 = 1;\n                this.axis2 = 2;\n            }\n        };\n        op.AveragePooling = function(reader, version) {\n            op.PoolingBase.apply(this, [reader, version]);\n        };\n        op.InvStdDev = function(reader) {\n            this.hasComputed = reader.boolean();\n            this.value = reader.matrix();\n        };\n        op.Mean = function(reader) {\n            this.hasComputed = reader.boolean();\n            this.value = reader.matrix();\n        };\n        op.PerDimMeanVarNormalization = function() {};\n        op.Softmax = function() {};\n        op.DynamicAxis = function() {};\n\n        const nodes = [];\n        this.nodes = {};\n        for (let i = 0; i < numNodes; i++) {\n            const precision = this.version >= 7 ? reader.string() : '';\n            if (precision !== 'float' && precision !== 'double' && precision !== 'half' && precision !== '') {\n                throw new cntk.Error(`Invalid precision format '${precision}'.`);\n            }\n            const obj = { __type__: reader.string() };\n            obj.name = reader.string();\n            obj.precision = precision;\n            const constructor = op[obj.__type__];\n            if (!constructor) {\n                throw new cntk.Error(`Unsupported node type '${obj.__type__}'.`);\n            }\n            constructor.apply(obj, [reader, this.version]);\n            nodes.push(obj);\n            this.nodes[obj.name] = obj;\n        }\n        reader.assert('ENodeList');\n        reader.assert('BRelation');\n        for (let j = 0; j < numNodes; j++) {\n            const nodeName = reader.string();\n            const node = this.nodes[nodeName];\n            const numChildren = reader.uint64().toNumber();\n            const children = [];\n            for (let k = 0; k < numChildren; k++) {\n                children.push(reader.string());\n            }\n            if (this.version < 19 && node.__type__ === 'BatchNormalization') {\n                const runSampleCount = {\n                    __type__: 'LearnableParameter',\n                    name: `${nodeName}.run_sample_count`,\n                    precision: node.precision,\n                    sampleLayout: shape([1]),\n                    learningRateMultiplier: 0\n                };\n                nodes.push(runSampleCount);\n                this.nodes[runSampleCount.name] = runSampleCount;\n                children.push(runSampleCount.name);\n            }\n            if (node.__type__ === 'Convolution' && children.length > 1) {\n                children.splice(0, 0, children.pop());\n            }\n            node.inputs = children;\n        }\n        reader.assert('ERelation');\n        reader.assert('BRootNodes');\n        if (reader.match('BFeatureNodes')) {\n            this.feature = reader.strings();\n            reader.assert('EFeatureNodes');\n        }\n        if (reader.match('BLabelNodes')) {\n            this.label = reader.strings();\n            reader.assert('ELabelNodes');\n        }\n        if (reader.match('BCriterionNodes')) {\n            this.criterion = reader.strings();\n            reader.assert('ECriterionNodes');\n        }\n        if (this.criterion.length === 0) {\n            if (reader.match('BCriteriaNodes')) {\n                this.criterion = reader.strings();\n                reader.assert('ECriteriaNodes');\n            }\n        }\n        if (reader.match('BNodesReqMultiSeqHandling')) {\n            reader.strings();\n            reader.assert('ENodesReqMultiSeqHandling');\n        }\n        if (reader.match('BEvalNodes')) {\n            this.eval = reader.strings();\n            reader.assert('EEvalNodes');\n        }\n        if (reader.match('BOutputNodes')) {\n            this.output = reader.strings();\n            reader.assert('EOutputNodes');\n        }\n        if (reader.match('BPairNodes')) {\n            this.pair = reader.strings();\n            reader.assert('EPairNodes');\n        }\n        reader.assert('ERootNodes');\n        reader.assert('ECN');\n    }\n};\n\ncntk.BinaryReader = class {\n\n    constructor(reader) {\n        this._reader = reader;\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    seek(offset) {\n        this._reader.seek(offset);\n    }\n\n    skip(offset) {\n        this._reader.skip(offset);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    boolean() {\n        return this._reader.boolean();\n    }\n\n    byte() {\n        return this._reader.byte();\n    }\n\n    int32() {\n        return this._reader.int32();\n    }\n\n    uint16() {\n        return this._reader.uint16();\n    }\n\n    uint32() {\n        return this._reader.uint32();\n    }\n\n    uint64() {\n        return this._reader.uint64();\n    }\n\n    float32() {\n        return this._reader.float32();\n    }\n\n    float64() {\n        return this._reader.float64();\n    }\n\n    match(text) {\n        const position = this.position;\n        for (let i = 0; i < text.length; i++) {\n            if (this.uint16() !== text.charCodeAt(i)) {\n                this.seek(position);\n                return false;\n            }\n        }\n        if (this.uint16() !== 0) {\n            this.seek(position);\n            return false;\n        }\n        return true;\n    }\n\n    assert(text) {\n        if (!this.match(text)) {\n            throw new cntk.Error(`Invalid '${text}' signature.`);\n        }\n    }\n\n    string() {\n        const content = [];\n        let c = this.uint16();\n        while (c !== 0) {\n            content.push(String.fromCharCode(c));\n            c = this.uint16();\n        }\n        return content.join('');\n    }\n\n    strings() {\n        const size = this.uint64().toNumber();\n        const array = new Array(size);\n        for (let i = 0; i < size; i++) {\n            array[i] = this.string();\n        }\n        return array;\n    }\n\n    booleans() {\n        const size = this.uint64().toNumber();\n        const array = new Array(size);\n        for (let i = 0; i < size; i++) {\n            array[i] = this.boolean();\n        }\n        return array;\n    }\n\n    matrix() {\n        const type = this.byte();\n        switch (type) {\n            case 100: {\n                // dense\n                this.assert('BMAT');\n                const elsize = this.uint64().toNumber();\n                const value = {};\n                value.name = this.string();\n                value.format = this.uint32();\n                value.rows = this.uint64().toNumber();\n                value.columns = this.uint64().toNumber();\n                this.read(elsize * value.rows * value.columns);\n                this.assert('EMAT');\n                return value;\n            }\n            case 115: // sparse\n                throw new cntk.Error('Matrix sparse type not implemented.');\n            default:\n                throw new cntk.Error(`Matrix type '${type}' not implemented.`);\n        }\n    }\n\n    shape(acceptLegacyFormat) {\n        const dims = [];\n        const rank = this.uint32();\n        let dim0 = 0;\n        if (rank > 0) {\n            dim0 = this.uint32();\n        }\n        if (!acceptLegacyFormat || dim0 !== 0) {\n            if (rank > 0) {\n                dims.push(dim0);\n            }\n            for (let i = 1; i < rank; i++) {\n                dims.push(this.uint32());\n            }\n        } else {\n            const dim = this.uint32();\n            dims.push(this.uint32());\n            dims.push(rank);\n            dims.push(dim);\n        }\n        return { __type__: 'shape', dims };\n    }\n};\n\ncntk.ImageLayoutKind = {\n    0: 'CHW',\n    1: 'HWC'\n};\n\ncntk.PoolKind = {\n    0: 'None',\n    1: 'Max',\n    2: 'Average'\n};\n\ncntk.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading CNTK model.';\n    }\n};\n\nexport const ModelFactory = cntk.ModelFactory;\n"
  },
  {
    "path": "source/coreml-metadata.json",
    "content": "[\n  {\n    \"name\": \"activation\",\n    \"category\": \"Activation\",\n    \"description\": \"Applies specified type of activation function to input.\"\n  },\n  {\n    \"name\": \"add\",\n    \"description\": \"A layer that performs elementwise addition.\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"average\",\n    \"description\": \"A layer that computes the elementwise average of the inputs.\"\n  },\n  {\n    \"name\": \"batchnorm\",\n    \"category\": \"Normalization\",\n    \"description\": \"A layer that performs batch normalization, which is performed along the channel axis, and repeated along the other axes, if present.\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"default\": 0.000009999999747378752 },\n      { \"name\": \"computeMeanVar\", \"visible\": false },\n      { \"name\": \"instanceNormalization\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"bias\",\n    \"category\": \"Layer\",\n    \"description\": \"A layer that performs elementwise addition of a bias, which is broadcasted to match the input shape.\"\n  },\n  {\n    \"name\": \"biDirectionalLSTM\",\n    \"category\": \"Layer\",\n    \"description\": \"Bidirectional long short-term memory (LSTM) layer. The first LSTM operates on the input sequence in the forward direction. The second LSTM operates on the input sequence in the reverse direction.\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"h\" },\n      { \"name\": \"c\" },\n      { \"name\": \"h_rev\" },\n      { \"name\": \"c_rev\" },\n      { \"name\": \"inputGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"forgetGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"blockInputWeightMatrix\", \"visible\": false },\n      { \"name\": \"outputGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"inputGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"forgetGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"blockInputRecursionMatrix\", \"visible\": false },\n      { \"name\": \"outputGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"inputGateBiasVector\", \"visible\": false },\n      { \"name\": \"forgetGateBiasVector\", \"visible\": false },\n      { \"name\": \"blockInputBiasVector\", \"visible\": false },\n      { \"name\": \"outputGateBiasVector\", \"visible\": false },\n      { \"name\": \"inputGateWeightMatrix_rev\", \"visible\": false },\n      { \"name\": \"forgetGateWeightMatrix_rev\", \"visible\": false },\n      { \"name\": \"blockInputWeightMatrix_rev\", \"visible\": false },\n      { \"name\": \"outputGateWeightMatrix_rev\", \"visible\": false },\n      { \"name\": \"inputGateRecursionMatrix_rev\", \"visible\": false },\n      { \"name\": \"forgetGateRecursionMatrix_rev\", \"visible\": false },\n      { \"name\": \"blockInputRecursionMatrix_rev\", \"visible\": false },\n      { \"name\": \"outputGateRecursionMatrix_rev\", \"visible\": false },\n      { \"name\": \"inputGateBiasVector_rev\", \"visible\": false },\n      { \"name\": \"forgetGateBiasVector_rev\", \"visible\": false },\n      { \"name\": \"blockInputBiasVector_rev\", \"visible\": false },\n      { \"name\": \"outputGateBiasVector_rev\", \"visible\": false }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"h\" },\n      { \"name\": \"c\" },\n      { \"name\": \"h_rev\" },\n      { \"name\": \"c_rev\" }\n    ]\n  },\n  {\n    \"name\": \"concat\",\n    \"category\": \"Tensor\",\n    \"description\": \"A layer that concatenates along the channel axis (default) or sequence axis.\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"convolution\",\n    \"category\": \"Layer\",\n    \"description\": \"A layer that performs spatial convolution or deconvolution.\",\n    \"attributes\": [\n      { \"name\": \"outputShape\", \"type\": \"uint64[]\", \"description\": \"Either None or a 2-tuple, specifying the output shape (output_height, output_width). Used only when is_deconv == True. When is_deconv == False, this parameter is ignored. If it is None, the output shape is calculated automatically using the border_mode. Kindly refer to NeuralNetwork.proto for details.\", \"visible\": false },\n      { \"name\": \"outputChannels\", \"type\": \"uint64\", \"description\": \"The number of kernels. Same as ``C_out`` used in the layer description.\", \"visible\": false },\n      { \"name\": \"kernelChannels\", \"type\": \"uint64\", \"description\": \"Channel dimension of the kernels. Must be equal to ``inputChannels / nGroups``, if isDeconvolution == False. Must be equal to ``inputChannels``, if isDeconvolution == True.\", \"visible\": false },\n      { \"name\": \"nGroups\", \"type\": \"uint64\", \"description\": \"Group convolution, i.e. weight reuse along channel axis. Input and kernels are divided into g groups and convolution / deconvolution is applied within the groups independently. If not set or 0, it is set to the default value 1.\", \"default\": 1 },\n      { \"name\": \"isDeconvolution\", \"type\": \"boolean\", \"description\": \"Flag to specify whether it is a deconvolution layer.\" },\n      { \"name\": \"valid\", \"type\": \"ValidPadding\", \"visible\": false },\n      { \"name\": \"same\", \"type\": \"SamePadding\", \"visible\": false },\n      { \"name\": \"dilationFactor\", \"type\": \"uint64[]\", \"default\": [   1,   1 ] },\n      { \"name\": \"stride\", \"type\": \"uint64[]\", \"default\": [   1,   1 ] },\n      { \"name\": \"kernelSize\", \"type\": \"uint64[]\", \"default\": [   3,   3 ] },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"description\": \"Flag to specify whether a bias is to be added or not.\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"crop\",\n    \"category\": \"Data\",\n    \"description\": \"A layer that crops the spatial dimensions of an input. If two inputs are provided, the shape of the second input is used as the reference shape.\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"dot\",\n    \"description\": \"If true, inputs are normalized first, thereby computing the cosine similarity.\"\n  },\n  {\n    \"name\": \"embedding\",\n    \"category\": \"Transform\",\n    \"description\": \"A layer that performs a matrix lookup and optionally adds a bias.\"\n  },\n  {\n    \"name\": \"featureVectorizer\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"flatten\",\n    \"category\": \"Shape\",\n    \"description\": \"A layer that flattens the input.\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"FlattenLayerParams.FlattenOrder\" }\n    ]\n  },\n  {\n    \"name\": \"gather\",\n    \"category\": \"Transform\",\n    \"description\": \"Gather layer that gathers elements from the first input, along a specified axis, at indices specified in the second input.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"Tensor\" },\n      { \"name\": \"indices\", \"type\": \"Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"gelu\",\n    \"category\": \"Activation\",\n    \"description\": \"Gaussian error linear unit activation.\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"GeluLayerParams.GeluMode\" }\n    ]\n  },\n  {\n    \"name\": \"gru\",\n    \"category\": \"Layer\",\n    \"description\": \"Gated-Recurrent Unit (GRU) Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"h\" },\n      { \"name\": \"updateGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"resetGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"outputGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"updateGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"resetGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"outputGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"updateGateBiasVector\", \"visible\": false },\n      { \"name\": \"resetGateBiasVector\", \"visible\": false },\n      { \"name\": \"outputGateBiasVector\", \"visible\": false }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"h\" }\n    ]\n  },\n  {\n    \"name\": \"innerProduct\",\n    \"category\": \"Layer\",\n    \"description\": \"A layer that performs a matrix vector product. This is equivalent to a fully-connected, or dense layer.\",\n    \"attributes\": [\n      { \"name\": \"inputChannels\", \"type\": \"uint64\", \"visible\": false },\n      { \"name\": \"outputChannels\", \"type\": \"uint64\", \"visible\": false },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"int64ClassLabels\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"probabilities\" },\n      { \"name\": \"feature\" }\n    ]\n  },\n  {\n    \"name\": \"itemSimilarityRecommender\",\n    \"inputs\": [\n      { \"name\": \"item\" },\n      { \"name\": \"numRecommendations\" },\n      { \"name\": \"itemRestriction\" },\n      { \"name\": \"itemExclusion\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"recommendedItemList\" },\n      { \"name\": \"recommendedItemScore\" }\n    ]\n  },\n  {\n    \"name\": \"l2normalize\",\n    \"category\": \"Normalization\",\n    \"description\": \"A layer that performs L2 normalization, i.e. divides by the the square root of the sum of squares of all elements of input.\"\n  },\n  {\n    \"name\": \"loadConstant\",\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"lrn\",\n    \"category\": \"Normalization\",\n    \"description\": \"A layer that performs local response normalization (LRN).\",\n    \"attributes\": [\n      { \"name\": \"k\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"max\",\n    \"description\": \"A layer that computes the elementwise maximum over the inputs.\"\n  },\n  {\n    \"name\": \"min\",\n    \"description\": \"A layer that computes the elementwise minimum over the inputs.\"\n  },\n  {\n    \"name\": \"multiply\",\n    \"description\": \"A layer that performs elementwise multiplication.\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"mvn\",\n    \"category\": \"Normalization\",\n    \"description\": \"A layer that performs mean variance normalization, along axis = -3.\"\n  },\n  {\n    \"name\": \"nonMaximumSuppression\",\n    \"attributes\": [\n      { \"name\": \"iouThreshold\" },\n      { \"name\": \"confidenceThreshold\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"confidence\" },\n      { \"name\": \"coordinates\" },\n      { \"name\": \"iouThreshold\" },\n      { \"name\": \"confidenceThreshold\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"confidence\" },\n      { \"name\": \"coordinates\" }\n    ]\n  },\n  {\n    \"name\": \"padding\",\n    \"category\": \"Shape\",\n    \"description\": \"Fill a constant value in the padded region.\",\n    \"attributes\": [\n      { \"name\": \"paddingAmounts\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"permute\",\n    \"category\": \"Shape\",\n    \"description\": \"A layer that rearranges the dimensions and data of an input.\"\n  },\n  {\n    \"name\": \"pooling\",\n    \"category\": \"Pool\",\n    \"description\": \"Spatial Pooling layer to reduce dimensions of input using the specified kernel size and type.\",\n    \"attributes\": [\n      { \"name\": \"includeLastPixel\", \"type\": \"ValidCompletePadding\", \"visible\": false },\n      { \"name\": \"same\", \"type\": \"SamePadding\", \"visible\": false },\n      { \"name\": \"valid\", \"type\": \"ValidCompletePadding\", \"visible\": false },\n      { \"name\": \"type\", \"type\": \"PoolingLayerParams.PoolingType\" },\n      { \"name\": \"globalPooling\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"stride\", \"type\": \"uint64\", \"default\": [   1,   1 ] },\n      { \"name\": \"kernelSize\", \"type\": \"uint64[]\", \"default\": [   3,   3 ] },\n      { \"name\": \"avgPoolExcludePadding\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"reduce\",\n    \"description\": \"A layer that reduces the input using a specified operation.\"\n  },\n  {\n    \"name\": \"reorganizeData\",\n    \"category\": \"Shape\",\n    \"description\": \"A layer that reorganizes data in the input in: 1. SPACE_TO_DEPTH, 2. DEPTH_TO_SPACE.\"\n  },\n  {\n    \"name\": \"reshape\",\n    \"category\": \"Shape\",\n    \"description\": \"A layer that recasts the input into a new shape.\"\n  },\n  {\n    \"name\": \"scale\",\n    \"category\": \"Layer\",\n    \"description\": \"A layer that performs elmentwise multiplication by a scale factor and optionally adds a bias.\",\n    \"attributes\": [\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"scaler\",\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"sequenceRepeat\",\n    \"category\": \"Shape\",\n    \"description\": \"A layer that repeats a sequence.\"\n  },\n  {\n    \"name\": \"slice\",\n    \"description\": \"A layer that uniformly splits across the channel dimension to produce a specified number of outputs.\"\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\",\n    \"description\": \"A layer that performs softmax normalization. Normalization is done along the channel axis.\"\n  },\n  {\n    \"name\": \"softmaxND\",\n    \"category\": \"Activation\",\n    \"description\": \"A layer that performs softmax normalization along a specified axis.\"\n  },\n  {\n    \"name\": \"squeeze\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"stringClassLabels\",\n    \"category\": \"Data\",\n    \"outputs\": [\n      { \"name\": \"probabilities\" },\n      { \"name\": \"feature\" }\n    ]\n  },\n  {\n    \"name\": \"textClassifier\",\n    \"attributes\": [\n      { \"name\": \"revision\", \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"unary\",\n    \"description\": \"A layer that applies a unary function.\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"UnaryFunctionLayerParams.Operation\" },\n      { \"name\": \"alpha\", \"default\": 1 },\n      { \"name\": \"scale\", \"default\": 1 },\n      { \"name\": \"epsilon\", \"default\": 9.999999974752427e-7 }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"uniDirectionalLSTM\",\n    \"category\": \"Layer\",\n    \"description\": \"A unidirectional long short-term memory (LSTM) layer.\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"h\" },\n      { \"name\": \"c\" },\n      { \"name\": \"inputGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"forgetGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"blockInputWeightMatrix\", \"visible\": false },\n      { \"name\": \"outputGateWeightMatrix\", \"visible\": false },\n      { \"name\": \"inputGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"forgetGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"blockInputRecursionMatrix\", \"visible\": false },\n      { \"name\": \"outputGateRecursionMatrix\", \"visible\": false },\n      { \"name\": \"inputGateBiasVector\", \"visible\": false },\n      { \"name\": \"forgetGateBiasVector\", \"visible\": false },\n      { \"name\": \"blockInputBiasVector\", \"visible\": false },\n      { \"name\": \"outputGateBiasVector\", \"visible\": false }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"h\" },\n      { \"name\": \"c\" }\n    ]\n  },\n  {\n    \"name\": \"upsample\",\n    \"category\": \"Data\",\n    \"description\": \"A layer that scales up spatial dimensions. It supports two modes: nearest neighbour (default) and bilinear.\"\n  },\n  {\n    \"name\": \"transpose\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"wordTagger\",\n    \"attributes\": [\n      { \"name\": \"revision\", \"visible\": false }\n    ],\n    \"outputs\": [\n      { \"name\": \"tokens\" },\n      { \"name\": \"tags\" },\n      { \"name\": \"locations\" },\n      { \"name\": \"lengths\" }\n    ]\n  },\n  {\n    \"name\": \"program:conv\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"program:batch_norm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ]\n  },\n  {\n    \"name\": \"program:linear\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"program:pad\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"program:transpose\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"program:sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"program:softmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"program:relu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"program:relu6\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"program:reshape\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"program:concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"program:layer_norm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"program:max_pool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"program:gather\",\n    \"category\": \"Transform\"\n  }\n]"
  },
  {
    "path": "source/coreml-proto.js",
    "content": "\nexport const CoreML = {};\n\nCoreML.Specification = {};\n\nCoreML.Specification.Pipeline = class Pipeline {\n\n    constructor() {\n        this.models = [];\n        this.names = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Pipeline();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.models.push(CoreML.Specification.Model.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.names.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Pipeline();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"models\":\n                    message.models.push(CoreML.Specification.Model.decodeText(reader));\n                    break;\n                case \"names\":\n                    reader.array(message.names, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PipelineClassifier = class PipelineClassifier {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PipelineClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.pipeline = CoreML.Specification.Pipeline.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PipelineClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"pipeline\":\n                    message.pipeline = CoreML.Specification.Pipeline.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PipelineClassifier.prototype.pipeline = null;\n\nCoreML.Specification.PipelineRegressor = class PipelineRegressor {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PipelineRegressor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.pipeline = CoreML.Specification.Pipeline.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PipelineRegressor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"pipeline\":\n                    message.pipeline = CoreML.Specification.Pipeline.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PipelineRegressor.prototype.pipeline = null;\n\nCoreML.Specification.FeatureDescription = class FeatureDescription {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FeatureDescription();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.shortDescription = reader.string();\n                    break;\n                case 3:\n                    message.type = CoreML.Specification.FeatureType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FeatureDescription();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"shortDescription\":\n                    message.shortDescription = reader.string();\n                    break;\n                case \"type\":\n                    message.type = CoreML.Specification.FeatureType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FeatureDescription.prototype.name = \"\";\nCoreML.Specification.FeatureDescription.prototype.shortDescription = \"\";\nCoreML.Specification.FeatureDescription.prototype.type = null;\n\nCoreML.Specification.Metadata = class Metadata {\n\n    constructor() {\n        this.userDefined = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Metadata();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shortDescription = reader.string();\n                    break;\n                case 2:\n                    message.versionString = reader.string();\n                    break;\n                case 3:\n                    message.author = reader.string();\n                    break;\n                case 4:\n                    message.license = reader.string();\n                    break;\n                case 100:\n                    reader.entry(message.userDefined, () => reader.string(), () => reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Metadata();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shortDescription\":\n                    message.shortDescription = reader.string();\n                    break;\n                case \"versionString\":\n                    message.versionString = reader.string();\n                    break;\n                case \"author\":\n                    message.author = reader.string();\n                    break;\n                case \"license\":\n                    message.license = reader.string();\n                    break;\n                case \"userDefined\":\n                    reader.entry(message.userDefined, () => reader.string(), () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Metadata.prototype.shortDescription = \"\";\nCoreML.Specification.Metadata.prototype.versionString = \"\";\nCoreML.Specification.Metadata.prototype.author = \"\";\nCoreML.Specification.Metadata.prototype.license = \"\";\n\nCoreML.Specification.FunctionDescription = class FunctionDescription {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n        this.state = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FunctionDescription();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.input.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.output.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                case 6:\n                    message.state.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    message.predictedFeatureName = reader.string();\n                    break;\n                case 5:\n                    message.predictedProbabilitiesName = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FunctionDescription();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"input\":\n                    message.input.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                case \"output\":\n                    message.output.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                case \"state\":\n                    message.state.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                case \"predictedFeatureName\":\n                    message.predictedFeatureName = reader.string();\n                    break;\n                case \"predictedProbabilitiesName\":\n                    message.predictedProbabilitiesName = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FunctionDescription.prototype.name = \"\";\nCoreML.Specification.FunctionDescription.prototype.predictedFeatureName = \"\";\nCoreML.Specification.FunctionDescription.prototype.predictedProbabilitiesName = \"\";\n\nCoreML.Specification.ModelDescription = class ModelDescription {\n\n    constructor() {\n        this.functions = [];\n        this.input = [];\n        this.output = [];\n        this.state = [];\n        this.trainingInput = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ModelDescription();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 20:\n                    message.functions.push(CoreML.Specification.FunctionDescription.decode(reader, reader.uint32()));\n                    break;\n                case 21:\n                    message.defaultFunctionName = reader.string();\n                    break;\n                case 100:\n                    message.metadata = CoreML.Specification.Metadata.decode(reader, reader.uint32());\n                    break;\n                case 1:\n                    message.input.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.output.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                case 13:\n                    message.state.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    message.predictedFeatureName = reader.string();\n                    break;\n                case 12:\n                    message.predictedProbabilitiesName = reader.string();\n                    break;\n                case 50:\n                    message.trainingInput.push(CoreML.Specification.FeatureDescription.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ModelDescription();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"functions\":\n                    message.functions.push(CoreML.Specification.FunctionDescription.decodeText(reader));\n                    break;\n                case \"defaultFunctionName\":\n                    message.defaultFunctionName = reader.string();\n                    break;\n                case \"metadata\":\n                    message.metadata = CoreML.Specification.Metadata.decodeText(reader);\n                    break;\n                case \"input\":\n                    message.input.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                case \"output\":\n                    message.output.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                case \"state\":\n                    message.state.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                case \"predictedFeatureName\":\n                    message.predictedFeatureName = reader.string();\n                    break;\n                case \"predictedProbabilitiesName\":\n                    message.predictedProbabilitiesName = reader.string();\n                    break;\n                case \"trainingInput\":\n                    message.trainingInput.push(CoreML.Specification.FeatureDescription.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ModelDescription.prototype.defaultFunctionName = \"\";\nCoreML.Specification.ModelDescription.prototype.metadata = null;\nCoreML.Specification.ModelDescription.prototype.predictedFeatureName = \"\";\nCoreML.Specification.ModelDescription.prototype.predictedProbabilitiesName = \"\";\n\nCoreML.Specification.SerializedModel = class SerializedModel {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SerializedModel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.identifier = reader.string();\n                    break;\n                case 2:\n                    message.model = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SerializedModel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"identifier\":\n                    message.identifier = reader.string();\n                    break;\n                case \"model\":\n                    message.model = reader.bytes();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SerializedModel.prototype.identifier = \"\";\nCoreML.Specification.SerializedModel.prototype.model = new Uint8Array([]);\n\nCoreML.Specification.Model = class Model {\n\n    get Type() {\n        CoreML.Specification.Model.TypeSet = CoreML.Specification.Model.TypeSet || new Set([\"pipelineClassifier\", \"pipelineRegressor\", \"pipeline\", \"glmRegressor\", \"supportVectorRegressor\", \"treeEnsembleRegressor\", \"neuralNetworkRegressor\", \"bayesianProbitRegressor\", \"glmClassifier\", \"supportVectorClassifier\", \"treeEnsembleClassifier\", \"neuralNetworkClassifier\", \"kNearestNeighborsClassifier\", \"neuralNetwork\", \"itemSimilarityRecommender\", \"mlProgram\", \"customModel\", \"linkedModel\", \"classConfidenceThresholding\", \"oneHotEncoder\", \"imputer\", \"featureVectorizer\", \"dictVectorizer\", \"scaler\", \"categoricalMapping\", \"normalizer\", \"arrayFeatureExtractor\", \"nonMaximumSuppression\", \"identity\", \"textClassifier\", \"wordTagger\", \"visionFeaturePrint\", \"soundAnalysisPreprocessing\", \"gazetteer\", \"wordEmbedding\", \"audioFeaturePrint\", \"serializedModel\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.Model.TypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Model();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.specificationVersion = reader.int32();\n                    break;\n                case 2:\n                    message.description = CoreML.Specification.ModelDescription.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.isUpdatable = reader.bool();\n                    break;\n                case 200:\n                    message.pipelineClassifier = CoreML.Specification.PipelineClassifier.decode(reader, reader.uint32());\n                    break;\n                case 201:\n                    message.pipelineRegressor = CoreML.Specification.PipelineRegressor.decode(reader, reader.uint32());\n                    break;\n                case 202:\n                    message.pipeline = CoreML.Specification.Pipeline.decode(reader, reader.uint32());\n                    break;\n                case 300:\n                    message.glmRegressor = CoreML.Specification.GLMRegressor.decode(reader, reader.uint32());\n                    break;\n                case 301:\n                    message.supportVectorRegressor = CoreML.Specification.SupportVectorRegressor.decode(reader, reader.uint32());\n                    break;\n                case 302:\n                    message.treeEnsembleRegressor = CoreML.Specification.TreeEnsembleRegressor.decode(reader, reader.uint32());\n                    break;\n                case 303:\n                    message.neuralNetworkRegressor = CoreML.Specification.NeuralNetworkRegressor.decode(reader, reader.uint32());\n                    break;\n                case 304:\n                    message.bayesianProbitRegressor = CoreML.Specification.BayesianProbitRegressor.decode(reader, reader.uint32());\n                    break;\n                case 400:\n                    message.glmClassifier = CoreML.Specification.GLMClassifier.decode(reader, reader.uint32());\n                    break;\n                case 401:\n                    message.supportVectorClassifier = CoreML.Specification.SupportVectorClassifier.decode(reader, reader.uint32());\n                    break;\n                case 402:\n                    message.treeEnsembleClassifier = CoreML.Specification.TreeEnsembleClassifier.decode(reader, reader.uint32());\n                    break;\n                case 403:\n                    message.neuralNetworkClassifier = CoreML.Specification.NeuralNetworkClassifier.decode(reader, reader.uint32());\n                    break;\n                case 404:\n                    message.kNearestNeighborsClassifier = CoreML.Specification.KNearestNeighborsClassifier.decode(reader, reader.uint32());\n                    break;\n                case 500:\n                    message.neuralNetwork = CoreML.Specification.NeuralNetwork.decode(reader, reader.uint32());\n                    break;\n                case 501:\n                    message.itemSimilarityRecommender = CoreML.Specification.ItemSimilarityRecommender.decode(reader, reader.uint32());\n                    break;\n                case 502:\n                    message.mlProgram = CoreML.Specification.MILSpec.Program.decode(reader, reader.uint32());\n                    break;\n                case 555:\n                    message.customModel = CoreML.Specification.CustomModel.decode(reader, reader.uint32());\n                    break;\n                case 556:\n                    message.linkedModel = CoreML.Specification.LinkedModel.decode(reader, reader.uint32());\n                    break;\n                case 560:\n                    message.classConfidenceThresholding = CoreML.Specification.ClassConfidenceThresholding.decode(reader, reader.uint32());\n                    break;\n                case 600:\n                    message.oneHotEncoder = CoreML.Specification.OneHotEncoder.decode(reader, reader.uint32());\n                    break;\n                case 601:\n                    message.imputer = CoreML.Specification.Imputer.decode(reader, reader.uint32());\n                    break;\n                case 602:\n                    message.featureVectorizer = CoreML.Specification.FeatureVectorizer.decode(reader, reader.uint32());\n                    break;\n                case 603:\n                    message.dictVectorizer = CoreML.Specification.DictVectorizer.decode(reader, reader.uint32());\n                    break;\n                case 604:\n                    message.scaler = CoreML.Specification.Scaler.decode(reader, reader.uint32());\n                    break;\n                case 606:\n                    message.categoricalMapping = CoreML.Specification.CategoricalMapping.decode(reader, reader.uint32());\n                    break;\n                case 607:\n                    message.normalizer = CoreML.Specification.Normalizer.decode(reader, reader.uint32());\n                    break;\n                case 609:\n                    message.arrayFeatureExtractor = CoreML.Specification.ArrayFeatureExtractor.decode(reader, reader.uint32());\n                    break;\n                case 610:\n                    message.nonMaximumSuppression = CoreML.Specification.NonMaximumSuppression.decode(reader, reader.uint32());\n                    break;\n                case 900:\n                    message.identity = CoreML.Specification.Identity.decode(reader, reader.uint32());\n                    break;\n                case 2000:\n                    message.textClassifier = CoreML.Specification.CoreMLModels.TextClassifier.decode(reader, reader.uint32());\n                    break;\n                case 2001:\n                    message.wordTagger = CoreML.Specification.CoreMLModels.WordTagger.decode(reader, reader.uint32());\n                    break;\n                case 2002:\n                    message.visionFeaturePrint = CoreML.Specification.CoreMLModels.VisionFeaturePrint.decode(reader, reader.uint32());\n                    break;\n                case 2003:\n                    message.soundAnalysisPreprocessing = CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.decode(reader, reader.uint32());\n                    break;\n                case 2004:\n                    message.gazetteer = CoreML.Specification.CoreMLModels.Gazetteer.decode(reader, reader.uint32());\n                    break;\n                case 2005:\n                    message.wordEmbedding = CoreML.Specification.CoreMLModels.WordEmbedding.decode(reader, reader.uint32());\n                    break;\n                case 2006:\n                    message.audioFeaturePrint = CoreML.Specification.CoreMLModels.AudioFeaturePrint.decode(reader, reader.uint32());\n                    break;\n                case 3000:\n                    message.serializedModel = CoreML.Specification.SerializedModel.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Model();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"specificationVersion\":\n                    message.specificationVersion = reader.int32();\n                    break;\n                case \"description\":\n                    message.description = CoreML.Specification.ModelDescription.decodeText(reader);\n                    break;\n                case \"isUpdatable\":\n                    message.isUpdatable = reader.bool();\n                    break;\n                case \"pipelineClassifier\":\n                    message.pipelineClassifier = CoreML.Specification.PipelineClassifier.decodeText(reader);\n                    break;\n                case \"pipelineRegressor\":\n                    message.pipelineRegressor = CoreML.Specification.PipelineRegressor.decodeText(reader);\n                    break;\n                case \"pipeline\":\n                    message.pipeline = CoreML.Specification.Pipeline.decodeText(reader);\n                    break;\n                case \"glmRegressor\":\n                    message.glmRegressor = CoreML.Specification.GLMRegressor.decodeText(reader);\n                    break;\n                case \"supportVectorRegressor\":\n                    message.supportVectorRegressor = CoreML.Specification.SupportVectorRegressor.decodeText(reader);\n                    break;\n                case \"treeEnsembleRegressor\":\n                    message.treeEnsembleRegressor = CoreML.Specification.TreeEnsembleRegressor.decodeText(reader);\n                    break;\n                case \"neuralNetworkRegressor\":\n                    message.neuralNetworkRegressor = CoreML.Specification.NeuralNetworkRegressor.decodeText(reader);\n                    break;\n                case \"bayesianProbitRegressor\":\n                    message.bayesianProbitRegressor = CoreML.Specification.BayesianProbitRegressor.decodeText(reader);\n                    break;\n                case \"glmClassifier\":\n                    message.glmClassifier = CoreML.Specification.GLMClassifier.decodeText(reader);\n                    break;\n                case \"supportVectorClassifier\":\n                    message.supportVectorClassifier = CoreML.Specification.SupportVectorClassifier.decodeText(reader);\n                    break;\n                case \"treeEnsembleClassifier\":\n                    message.treeEnsembleClassifier = CoreML.Specification.TreeEnsembleClassifier.decodeText(reader);\n                    break;\n                case \"neuralNetworkClassifier\":\n                    message.neuralNetworkClassifier = CoreML.Specification.NeuralNetworkClassifier.decodeText(reader);\n                    break;\n                case \"kNearestNeighborsClassifier\":\n                    message.kNearestNeighborsClassifier = CoreML.Specification.KNearestNeighborsClassifier.decodeText(reader);\n                    break;\n                case \"neuralNetwork\":\n                    message.neuralNetwork = CoreML.Specification.NeuralNetwork.decodeText(reader);\n                    break;\n                case \"itemSimilarityRecommender\":\n                    message.itemSimilarityRecommender = CoreML.Specification.ItemSimilarityRecommender.decodeText(reader);\n                    break;\n                case \"mlProgram\":\n                    message.mlProgram = CoreML.Specification.MILSpec.Program.decodeText(reader);\n                    break;\n                case \"customModel\":\n                    message.customModel = CoreML.Specification.CustomModel.decodeText(reader);\n                    break;\n                case \"linkedModel\":\n                    message.linkedModel = CoreML.Specification.LinkedModel.decodeText(reader);\n                    break;\n                case \"classConfidenceThresholding\":\n                    message.classConfidenceThresholding = CoreML.Specification.ClassConfidenceThresholding.decodeText(reader);\n                    break;\n                case \"oneHotEncoder\":\n                    message.oneHotEncoder = CoreML.Specification.OneHotEncoder.decodeText(reader);\n                    break;\n                case \"imputer\":\n                    message.imputer = CoreML.Specification.Imputer.decodeText(reader);\n                    break;\n                case \"featureVectorizer\":\n                    message.featureVectorizer = CoreML.Specification.FeatureVectorizer.decodeText(reader);\n                    break;\n                case \"dictVectorizer\":\n                    message.dictVectorizer = CoreML.Specification.DictVectorizer.decodeText(reader);\n                    break;\n                case \"scaler\":\n                    message.scaler = CoreML.Specification.Scaler.decodeText(reader);\n                    break;\n                case \"categoricalMapping\":\n                    message.categoricalMapping = CoreML.Specification.CategoricalMapping.decodeText(reader);\n                    break;\n                case \"normalizer\":\n                    message.normalizer = CoreML.Specification.Normalizer.decodeText(reader);\n                    break;\n                case \"arrayFeatureExtractor\":\n                    message.arrayFeatureExtractor = CoreML.Specification.ArrayFeatureExtractor.decodeText(reader);\n                    break;\n                case \"nonMaximumSuppression\":\n                    message.nonMaximumSuppression = CoreML.Specification.NonMaximumSuppression.decodeText(reader);\n                    break;\n                case \"identity\":\n                    message.identity = CoreML.Specification.Identity.decodeText(reader);\n                    break;\n                case \"textClassifier\":\n                    message.textClassifier = CoreML.Specification.CoreMLModels.TextClassifier.decodeText(reader);\n                    break;\n                case \"wordTagger\":\n                    message.wordTagger = CoreML.Specification.CoreMLModels.WordTagger.decodeText(reader);\n                    break;\n                case \"visionFeaturePrint\":\n                    message.visionFeaturePrint = CoreML.Specification.CoreMLModels.VisionFeaturePrint.decodeText(reader);\n                    break;\n                case \"soundAnalysisPreprocessing\":\n                    message.soundAnalysisPreprocessing = CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.decodeText(reader);\n                    break;\n                case \"gazetteer\":\n                    message.gazetteer = CoreML.Specification.CoreMLModels.Gazetteer.decodeText(reader);\n                    break;\n                case \"wordEmbedding\":\n                    message.wordEmbedding = CoreML.Specification.CoreMLModels.WordEmbedding.decodeText(reader);\n                    break;\n                case \"audioFeaturePrint\":\n                    message.audioFeaturePrint = CoreML.Specification.CoreMLModels.AudioFeaturePrint.decodeText(reader);\n                    break;\n                case \"serializedModel\":\n                    message.serializedModel = CoreML.Specification.SerializedModel.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Model.prototype.specificationVersion = 0;\nCoreML.Specification.Model.prototype.description = null;\nCoreML.Specification.Model.prototype.isUpdatable = false;\n\nCoreML.Specification.CoreMLModels = {};\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint = class VisionFeaturePrint {\n\n    get VisionFeaturePrintType() {\n        CoreML.Specification.CoreMLModels.VisionFeaturePrint.VisionFeaturePrintTypeSet = CoreML.Specification.CoreMLModels.VisionFeaturePrint.VisionFeaturePrintTypeSet || new Set([\"scene\", \"objects\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CoreMLModels.VisionFeaturePrint.VisionFeaturePrintTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.VisionFeaturePrint();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 20:\n                    message.scene = CoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene.decode(reader, reader.uint32());\n                    break;\n                case 21:\n                    message.objects = CoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.VisionFeaturePrint();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"scene\":\n                    message.scene = CoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene.decodeText(reader);\n                    break;\n                case \"objects\":\n                    message.objects = CoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene = class Scene {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"version\":\n                    message.version = reader.enum(CoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene.SceneVersion);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene.prototype.version = 0;\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint.Scene.SceneVersion = {\n    \"SCENE_VERSION_INVALID\": 0,\n    \"SCENE_VERSION_1\": 1,\n    \"SCENE_VERSION_2\": 2\n};\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects = class Objects {\n\n    constructor() {\n        this.output = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.int32();\n                    break;\n                case 100:\n                    message.output.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"version\":\n                    message.version = reader.enum(CoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects.ObjectsVersion);\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects.prototype.version = 0;\n\nCoreML.Specification.CoreMLModels.VisionFeaturePrint.Objects.ObjectsVersion = {\n    \"OBJECTS_VERSION_INVALID\": 0,\n    \"OBJECTS_VERSION_1\": 1\n};\n\nCoreML.Specification.CoreMLModels.AudioFeaturePrint = class AudioFeaturePrint {\n\n    get AudioFeaturePrintType() {\n        CoreML.Specification.CoreMLModels.AudioFeaturePrint.AudioFeaturePrintTypeSet = CoreML.Specification.CoreMLModels.AudioFeaturePrint.AudioFeaturePrintTypeSet || new Set([\"sound\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CoreMLModels.AudioFeaturePrint.AudioFeaturePrintTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.AudioFeaturePrint();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 20:\n                    message.sound = CoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.AudioFeaturePrint();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sound\":\n                    message.sound = CoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound = class Sound {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"version\":\n                    message.version = reader.enum(CoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound.SoundVersion);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound.prototype.version = 0;\n\nCoreML.Specification.CoreMLModels.AudioFeaturePrint.Sound.SoundVersion = {\n    \"SOUND_VERSION_INVALID\": 0,\n    \"SOUND_VERSION_1\": 1\n};\n\nCoreML.Specification.CoreMLModels.TextClassifier = class TextClassifier {\n\n    get ClassLabels() {\n        CoreML.Specification.CoreMLModels.TextClassifier.ClassLabelsSet = CoreML.Specification.CoreMLModels.TextClassifier.ClassLabelsSet || new Set([\"stringClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CoreMLModels.TextClassifier.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.TextClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.revision = reader.uint32();\n                    break;\n                case 10:\n                    message.language = reader.string();\n                    break;\n                case 100:\n                    message.modelParameterData = reader.bytes();\n                    break;\n                case 200:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.TextClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"revision\":\n                    message.revision = reader.uint32();\n                    break;\n                case \"language\":\n                    message.language = reader.string();\n                    break;\n                case \"modelParameterData\":\n                    message.modelParameterData = reader.bytes();\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.TextClassifier.prototype.revision = 0;\nCoreML.Specification.CoreMLModels.TextClassifier.prototype.language = \"\";\nCoreML.Specification.CoreMLModels.TextClassifier.prototype.modelParameterData = new Uint8Array([]);\n\nCoreML.Specification.CoreMLModels.WordTagger = class WordTagger {\n\n    get Tags() {\n        CoreML.Specification.CoreMLModels.WordTagger.TagsSet = CoreML.Specification.CoreMLModels.WordTagger.TagsSet || new Set([\"stringTags\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CoreMLModels.WordTagger.TagsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.WordTagger();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.revision = reader.uint32();\n                    break;\n                case 10:\n                    message.language = reader.string();\n                    break;\n                case 20:\n                    message.tokensOutputFeatureName = reader.string();\n                    break;\n                case 21:\n                    message.tokenTagsOutputFeatureName = reader.string();\n                    break;\n                case 22:\n                    message.tokenLocationsOutputFeatureName = reader.string();\n                    break;\n                case 23:\n                    message.tokenLengthsOutputFeatureName = reader.string();\n                    break;\n                case 100:\n                    message.modelParameterData = reader.bytes();\n                    break;\n                case 200:\n                    message.stringTags = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.WordTagger();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"revision\":\n                    message.revision = reader.uint32();\n                    break;\n                case \"language\":\n                    message.language = reader.string();\n                    break;\n                case \"tokensOutputFeatureName\":\n                    message.tokensOutputFeatureName = reader.string();\n                    break;\n                case \"tokenTagsOutputFeatureName\":\n                    message.tokenTagsOutputFeatureName = reader.string();\n                    break;\n                case \"tokenLocationsOutputFeatureName\":\n                    message.tokenLocationsOutputFeatureName = reader.string();\n                    break;\n                case \"tokenLengthsOutputFeatureName\":\n                    message.tokenLengthsOutputFeatureName = reader.string();\n                    break;\n                case \"modelParameterData\":\n                    message.modelParameterData = reader.bytes();\n                    break;\n                case \"stringTags\":\n                    message.stringTags = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.WordTagger.prototype.revision = 0;\nCoreML.Specification.CoreMLModels.WordTagger.prototype.language = \"\";\nCoreML.Specification.CoreMLModels.WordTagger.prototype.tokensOutputFeatureName = \"\";\nCoreML.Specification.CoreMLModels.WordTagger.prototype.tokenTagsOutputFeatureName = \"\";\nCoreML.Specification.CoreMLModels.WordTagger.prototype.tokenLocationsOutputFeatureName = \"\";\nCoreML.Specification.CoreMLModels.WordTagger.prototype.tokenLengthsOutputFeatureName = \"\";\nCoreML.Specification.CoreMLModels.WordTagger.prototype.modelParameterData = new Uint8Array([]);\n\nCoreML.Specification.CoreMLModels.Gazetteer = class Gazetteer {\n\n    get ClassLabels() {\n        CoreML.Specification.CoreMLModels.Gazetteer.ClassLabelsSet = CoreML.Specification.CoreMLModels.Gazetteer.ClassLabelsSet || new Set([\"stringClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CoreMLModels.Gazetteer.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.Gazetteer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.revision = reader.uint32();\n                    break;\n                case 10:\n                    message.language = reader.string();\n                    break;\n                case 100:\n                    message.modelParameterData = reader.bytes();\n                    break;\n                case 200:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.Gazetteer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"revision\":\n                    message.revision = reader.uint32();\n                    break;\n                case \"language\":\n                    message.language = reader.string();\n                    break;\n                case \"modelParameterData\":\n                    message.modelParameterData = reader.bytes();\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.Gazetteer.prototype.revision = 0;\nCoreML.Specification.CoreMLModels.Gazetteer.prototype.language = \"\";\nCoreML.Specification.CoreMLModels.Gazetteer.prototype.modelParameterData = new Uint8Array([]);\n\nCoreML.Specification.CoreMLModels.WordEmbedding = class WordEmbedding {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.WordEmbedding();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.revision = reader.uint32();\n                    break;\n                case 10:\n                    message.language = reader.string();\n                    break;\n                case 100:\n                    message.modelParameterData = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.WordEmbedding();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"revision\":\n                    message.revision = reader.uint32();\n                    break;\n                case \"language\":\n                    message.language = reader.string();\n                    break;\n                case \"modelParameterData\":\n                    message.modelParameterData = reader.bytes();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.WordEmbedding.prototype.revision = 0;\nCoreML.Specification.CoreMLModels.WordEmbedding.prototype.language = \"\";\nCoreML.Specification.CoreMLModels.WordEmbedding.prototype.modelParameterData = new Uint8Array([]);\n\nCoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing = class SoundAnalysisPreprocessing {\n\n    get SoundAnalysisPreprocessingType() {\n        CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.SoundAnalysisPreprocessingTypeSet = CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.SoundAnalysisPreprocessingTypeSet || new Set([\"vggish\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.SoundAnalysisPreprocessingTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 20:\n                    message.vggish = CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.Vggish.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vggish\":\n                    message.vggish = CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.Vggish.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.Vggish = class Vggish {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.Vggish();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoreMLModels.SoundAnalysisPreprocessing.Vggish();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.StringToInt64Map = class StringToInt64Map {\n\n    constructor() {\n        this.map = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StringToInt64Map();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    reader.entry(message.map, () => reader.string(), () => reader.int64());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StringToInt64Map();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"map\":\n                    reader.entry(message.map, () => reader.string(), () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64ToStringMap = class Int64ToStringMap {\n\n    constructor() {\n        this.map = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64ToStringMap();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    reader.entry(message.map, () => reader.int64(), () => reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64ToStringMap();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"map\":\n                    reader.entry(message.map, () => reader.int64(), () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.StringToDoubleMap = class StringToDoubleMap {\n\n    constructor() {\n        this.map = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StringToDoubleMap();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    reader.entry(message.map, () => reader.string(), () => reader.double());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StringToDoubleMap();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"map\":\n                    reader.entry(message.map, () => reader.string(), () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64ToDoubleMap = class Int64ToDoubleMap {\n\n    constructor() {\n        this.map = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64ToDoubleMap();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    reader.entry(message.map, () => reader.int64(), () => reader.double());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64ToDoubleMap();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"map\":\n                    reader.entry(message.map, () => reader.int64(), () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.StringVector = class StringVector {\n\n    constructor() {\n        this.vector = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StringVector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vector.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StringVector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vector\":\n                    reader.array(message.vector, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64Vector = class Int64Vector {\n\n    constructor() {\n        this.vector = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64Vector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vector = reader.array(message.vector, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64Vector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vector\":\n                    reader.array(message.vector, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FloatVector = class FloatVector {\n\n    constructor() {\n        this.vector = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FloatVector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vector = reader.floats(message.vector, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FloatVector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vector\":\n                    reader.array(message.vector, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DoubleVector = class DoubleVector {\n\n    constructor() {\n        this.vector = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DoubleVector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vector = reader.doubles(message.vector, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DoubleVector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vector\":\n                    reader.array(message.vector, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64Range = class Int64Range {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64Range();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.minValue = reader.int64();\n                    break;\n                case 2:\n                    message.maxValue = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64Range();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"minValue\":\n                    message.minValue = reader.int64();\n                    break;\n                case \"maxValue\":\n                    message.maxValue = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64Range.prototype.minValue = 0n;\nCoreML.Specification.Int64Range.prototype.maxValue = 0n;\n\nCoreML.Specification.Int64Set = class Int64Set {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64Set();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.array(message.values, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64Set();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DoubleRange = class DoubleRange {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DoubleRange();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.minValue = reader.double();\n                    break;\n                case 2:\n                    message.maxValue = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DoubleRange();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"minValue\":\n                    message.minValue = reader.double();\n                    break;\n                case \"maxValue\":\n                    message.maxValue = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DoubleRange.prototype.minValue = 0;\nCoreML.Specification.DoubleRange.prototype.maxValue = 0;\n\nCoreML.Specification.PrecisionRecallCurve = class PrecisionRecallCurve {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PrecisionRecallCurve();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.precisionValues = CoreML.Specification.FloatVector.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.precisionConfidenceThresholds = CoreML.Specification.FloatVector.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.recallValues = CoreML.Specification.FloatVector.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.recallConfidenceThresholds = CoreML.Specification.FloatVector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PrecisionRecallCurve();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"precisionValues\":\n                    message.precisionValues = CoreML.Specification.FloatVector.decodeText(reader);\n                    break;\n                case \"precisionConfidenceThresholds\":\n                    message.precisionConfidenceThresholds = CoreML.Specification.FloatVector.decodeText(reader);\n                    break;\n                case \"recallValues\":\n                    message.recallValues = CoreML.Specification.FloatVector.decodeText(reader);\n                    break;\n                case \"recallConfidenceThresholds\":\n                    message.recallConfidenceThresholds = CoreML.Specification.FloatVector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PrecisionRecallCurve.prototype.precisionValues = null;\nCoreML.Specification.PrecisionRecallCurve.prototype.precisionConfidenceThresholds = null;\nCoreML.Specification.PrecisionRecallCurve.prototype.recallValues = null;\nCoreML.Specification.PrecisionRecallCurve.prototype.recallConfidenceThresholds = null;\n\nCoreML.Specification.Int64FeatureType = class Int64FeatureType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64FeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64FeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DoubleFeatureType = class DoubleFeatureType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DoubleFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DoubleFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.StringFeatureType = class StringFeatureType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StringFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StringFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SizeRange = class SizeRange {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SizeRange();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lowerBound = reader.uint64();\n                    break;\n                case 2:\n                    message.upperBound = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SizeRange();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lowerBound\":\n                    message.lowerBound = reader.uint64();\n                    break;\n                case \"upperBound\":\n                    message.upperBound = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SizeRange.prototype.lowerBound = 0n;\nCoreML.Specification.SizeRange.prototype.upperBound = 0n;\n\nCoreML.Specification.ImageFeatureType = class ImageFeatureType {\n\n    get SizeFlexibility() {\n        CoreML.Specification.ImageFeatureType.SizeFlexibilitySet = CoreML.Specification.ImageFeatureType.SizeFlexibilitySet || new Set([\"enumeratedSizes\", \"imageSizeRange\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.ImageFeatureType.SizeFlexibilitySet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ImageFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.width = reader.int64();\n                    break;\n                case 2:\n                    message.height = reader.int64();\n                    break;\n                case 21:\n                    message.enumeratedSizes = CoreML.Specification.ImageFeatureType.EnumeratedImageSizes.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.imageSizeRange = CoreML.Specification.ImageFeatureType.ImageSizeRange.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.colorSpace = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ImageFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"width\":\n                    message.width = reader.int64();\n                    break;\n                case \"height\":\n                    message.height = reader.int64();\n                    break;\n                case \"enumeratedSizes\":\n                    message.enumeratedSizes = CoreML.Specification.ImageFeatureType.EnumeratedImageSizes.decodeText(reader);\n                    break;\n                case \"imageSizeRange\":\n                    message.imageSizeRange = CoreML.Specification.ImageFeatureType.ImageSizeRange.decodeText(reader);\n                    break;\n                case \"colorSpace\":\n                    message.colorSpace = reader.enum(CoreML.Specification.ImageFeatureType.ColorSpace);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ImageFeatureType.prototype.width = 0n;\nCoreML.Specification.ImageFeatureType.prototype.height = 0n;\nCoreML.Specification.ImageFeatureType.prototype.colorSpace = 0;\n\nCoreML.Specification.ImageFeatureType.ColorSpace = {\n    \"INVALID_COLOR_SPACE\": 0,\n    \"GRAYSCALE\": 10,\n    \"RGB\": 20,\n    \"BGR\": 30,\n    \"GRAYSCALE_FLOAT16\": 40\n};\n\nCoreML.Specification.ImageFeatureType.ImageSize = class ImageSize {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ImageFeatureType.ImageSize();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.width = reader.uint64();\n                    break;\n                case 2:\n                    message.height = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ImageFeatureType.ImageSize();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"width\":\n                    message.width = reader.uint64();\n                    break;\n                case \"height\":\n                    message.height = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ImageFeatureType.ImageSize.prototype.width = 0n;\nCoreML.Specification.ImageFeatureType.ImageSize.prototype.height = 0n;\n\nCoreML.Specification.ImageFeatureType.EnumeratedImageSizes = class EnumeratedImageSizes {\n\n    constructor() {\n        this.sizes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ImageFeatureType.EnumeratedImageSizes();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.sizes.push(CoreML.Specification.ImageFeatureType.ImageSize.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ImageFeatureType.EnumeratedImageSizes();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sizes\":\n                    message.sizes.push(CoreML.Specification.ImageFeatureType.ImageSize.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ImageFeatureType.ImageSizeRange = class ImageSizeRange {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ImageFeatureType.ImageSizeRange();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.widthRange = CoreML.Specification.SizeRange.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.heightRange = CoreML.Specification.SizeRange.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ImageFeatureType.ImageSizeRange();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"widthRange\":\n                    message.widthRange = CoreML.Specification.SizeRange.decodeText(reader);\n                    break;\n                case \"heightRange\":\n                    message.heightRange = CoreML.Specification.SizeRange.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ImageFeatureType.ImageSizeRange.prototype.widthRange = null;\nCoreML.Specification.ImageFeatureType.ImageSizeRange.prototype.heightRange = null;\n\nCoreML.Specification.ArrayFeatureType = class ArrayFeatureType {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    get ShapeFlexibility() {\n        CoreML.Specification.ArrayFeatureType.ShapeFlexibilitySet = CoreML.Specification.ArrayFeatureType.ShapeFlexibilitySet || new Set([\"enumeratedShapes\", \"shapeRange\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.ArrayFeatureType.ShapeFlexibilitySet.has(key) && this[key] !== null);\n    }\n\n    get defaultOptionalValue() {\n        CoreML.Specification.ArrayFeatureType.defaultOptionalValueSet = CoreML.Specification.ArrayFeatureType.defaultOptionalValueSet || new Set([\"intDefaultValue\", \"floatDefaultValue\", \"doubleDefaultValue\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.ArrayFeatureType.defaultOptionalValueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArrayFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = reader.array(message.shape, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.dataType = reader.int32();\n                    break;\n                case 21:\n                    message.enumeratedShapes = CoreML.Specification.ArrayFeatureType.EnumeratedShapes.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.shapeRange = CoreML.Specification.ArrayFeatureType.ShapeRange.decode(reader, reader.uint32());\n                    break;\n                case 41:\n                    message.intDefaultValue = reader.int32();\n                    break;\n                case 51:\n                    message.floatDefaultValue = reader.float();\n                    break;\n                case 61:\n                    message.doubleDefaultValue = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArrayFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    reader.array(message.shape, () => reader.int64());\n                    break;\n                case \"dataType\":\n                    message.dataType = reader.enum(CoreML.Specification.ArrayFeatureType.ArrayDataType);\n                    break;\n                case \"enumeratedShapes\":\n                    message.enumeratedShapes = CoreML.Specification.ArrayFeatureType.EnumeratedShapes.decodeText(reader);\n                    break;\n                case \"shapeRange\":\n                    message.shapeRange = CoreML.Specification.ArrayFeatureType.ShapeRange.decodeText(reader);\n                    break;\n                case \"intDefaultValue\":\n                    message.intDefaultValue = reader.int32();\n                    break;\n                case \"floatDefaultValue\":\n                    message.floatDefaultValue = reader.float();\n                    break;\n                case \"doubleDefaultValue\":\n                    message.doubleDefaultValue = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ArrayFeatureType.prototype.dataType = 0;\n\nCoreML.Specification.ArrayFeatureType.ArrayDataType = {\n    \"INVALID_ARRAY_DATA_TYPE\": 0,\n    \"FLOAT32\": 65568,\n    \"DOUBLE\": 65600,\n    \"INT32\": 131104,\n    \"INT8\": 131080,\n    \"FLOAT16\": 65552\n};\n\nCoreML.Specification.ArrayFeatureType.Shape = class Shape {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArrayFeatureType.Shape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = reader.array(message.shape, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArrayFeatureType.Shape();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    reader.array(message.shape, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ArrayFeatureType.EnumeratedShapes = class EnumeratedShapes {\n\n    constructor() {\n        this.shapes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArrayFeatureType.EnumeratedShapes();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shapes.push(CoreML.Specification.ArrayFeatureType.Shape.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArrayFeatureType.EnumeratedShapes();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shapes\":\n                    message.shapes.push(CoreML.Specification.ArrayFeatureType.Shape.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ArrayFeatureType.ShapeRange = class ShapeRange {\n\n    constructor() {\n        this.sizeRanges = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArrayFeatureType.ShapeRange();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.sizeRanges.push(CoreML.Specification.SizeRange.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArrayFeatureType.ShapeRange();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sizeRanges\":\n                    message.sizeRanges.push(CoreML.Specification.SizeRange.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DictionaryFeatureType = class DictionaryFeatureType {\n\n    get KeyType() {\n        CoreML.Specification.DictionaryFeatureType.KeyTypeSet = CoreML.Specification.DictionaryFeatureType.KeyTypeSet || new Set([\"int64KeyType\", \"stringKeyType\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.DictionaryFeatureType.KeyTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DictionaryFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.int64KeyType = CoreML.Specification.Int64FeatureType.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.stringKeyType = CoreML.Specification.StringFeatureType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DictionaryFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"int64KeyType\":\n                    message.int64KeyType = CoreML.Specification.Int64FeatureType.decodeText(reader);\n                    break;\n                case \"stringKeyType\":\n                    message.stringKeyType = CoreML.Specification.StringFeatureType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SequenceFeatureType = class SequenceFeatureType {\n\n    get Type() {\n        CoreML.Specification.SequenceFeatureType.TypeSet = CoreML.Specification.SequenceFeatureType.TypeSet || new Set([\"int64Type\", \"stringType\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.SequenceFeatureType.TypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SequenceFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.int64Type = CoreML.Specification.Int64FeatureType.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stringType = CoreML.Specification.StringFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.sizeRange = CoreML.Specification.SizeRange.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SequenceFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"int64Type\":\n                    message.int64Type = CoreML.Specification.Int64FeatureType.decodeText(reader);\n                    break;\n                case \"stringType\":\n                    message.stringType = CoreML.Specification.StringFeatureType.decodeText(reader);\n                    break;\n                case \"sizeRange\":\n                    message.sizeRange = CoreML.Specification.SizeRange.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SequenceFeatureType.prototype.sizeRange = null;\n\nCoreML.Specification.StateFeatureType = class StateFeatureType {\n\n    get Type() {\n        CoreML.Specification.StateFeatureType.TypeSet = CoreML.Specification.StateFeatureType.TypeSet || new Set([\"arrayType\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.StateFeatureType.TypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StateFeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.arrayType = CoreML.Specification.ArrayFeatureType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StateFeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"arrayType\":\n                    message.arrayType = CoreML.Specification.ArrayFeatureType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FeatureType = class FeatureType {\n\n    get Type() {\n        CoreML.Specification.FeatureType.TypeSet = CoreML.Specification.FeatureType.TypeSet || new Set([\"int64Type\", \"doubleType\", \"stringType\", \"imageType\", \"multiArrayType\", \"dictionaryType\", \"sequenceType\", \"stateType\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.FeatureType.TypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FeatureType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.int64Type = CoreML.Specification.Int64FeatureType.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.doubleType = CoreML.Specification.DoubleFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stringType = CoreML.Specification.StringFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.imageType = CoreML.Specification.ImageFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.multiArrayType = CoreML.Specification.ArrayFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.dictionaryType = CoreML.Specification.DictionaryFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.sequenceType = CoreML.Specification.SequenceFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 8:\n                    message.stateType = CoreML.Specification.StateFeatureType.decode(reader, reader.uint32());\n                    break;\n                case 1000:\n                    message.isOptional = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FeatureType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"int64Type\":\n                    message.int64Type = CoreML.Specification.Int64FeatureType.decodeText(reader);\n                    break;\n                case \"doubleType\":\n                    message.doubleType = CoreML.Specification.DoubleFeatureType.decodeText(reader);\n                    break;\n                case \"stringType\":\n                    message.stringType = CoreML.Specification.StringFeatureType.decodeText(reader);\n                    break;\n                case \"imageType\":\n                    message.imageType = CoreML.Specification.ImageFeatureType.decodeText(reader);\n                    break;\n                case \"multiArrayType\":\n                    message.multiArrayType = CoreML.Specification.ArrayFeatureType.decodeText(reader);\n                    break;\n                case \"dictionaryType\":\n                    message.dictionaryType = CoreML.Specification.DictionaryFeatureType.decodeText(reader);\n                    break;\n                case \"sequenceType\":\n                    message.sequenceType = CoreML.Specification.SequenceFeatureType.decodeText(reader);\n                    break;\n                case \"stateType\":\n                    message.stateType = CoreML.Specification.StateFeatureType.decodeText(reader);\n                    break;\n                case \"isOptional\":\n                    message.isOptional = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FeatureType.prototype.isOptional = false;\n\nCoreML.Specification.ArrayFeatureExtractor = class ArrayFeatureExtractor {\n\n    constructor() {\n        this.extractIndex = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArrayFeatureExtractor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.extractIndex = reader.array(message.extractIndex, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArrayFeatureExtractor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"extractIndex\":\n                    reader.array(message.extractIndex, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BayesianProbitRegressor = class BayesianProbitRegressor {\n\n    constructor() {\n        this.features = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BayesianProbitRegressor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.numberOfFeatures = reader.uint32();\n                    break;\n                case 2:\n                    message.bias = CoreML.Specification.BayesianProbitRegressor.Gaussian.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.features.push(CoreML.Specification.BayesianProbitRegressor.FeatureWeight.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.regressionInputFeatureName = reader.string();\n                    break;\n                case 11:\n                    message.optimismInputFeatureName = reader.string();\n                    break;\n                case 12:\n                    message.samplingScaleInputFeatureName = reader.string();\n                    break;\n                case 13:\n                    message.samplingTruncationInputFeatureName = reader.string();\n                    break;\n                case 20:\n                    message.meanOutputFeatureName = reader.string();\n                    break;\n                case 21:\n                    message.varianceOutputFeatureName = reader.string();\n                    break;\n                case 22:\n                    message.pessimisticProbabilityOutputFeatureName = reader.string();\n                    break;\n                case 23:\n                    message.sampledProbabilityOutputFeatureName = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BayesianProbitRegressor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"numberOfFeatures\":\n                    message.numberOfFeatures = reader.uint32();\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.BayesianProbitRegressor.Gaussian.decodeText(reader);\n                    break;\n                case \"features\":\n                    message.features.push(CoreML.Specification.BayesianProbitRegressor.FeatureWeight.decodeText(reader));\n                    break;\n                case \"regressionInputFeatureName\":\n                    message.regressionInputFeatureName = reader.string();\n                    break;\n                case \"optimismInputFeatureName\":\n                    message.optimismInputFeatureName = reader.string();\n                    break;\n                case \"samplingScaleInputFeatureName\":\n                    message.samplingScaleInputFeatureName = reader.string();\n                    break;\n                case \"samplingTruncationInputFeatureName\":\n                    message.samplingTruncationInputFeatureName = reader.string();\n                    break;\n                case \"meanOutputFeatureName\":\n                    message.meanOutputFeatureName = reader.string();\n                    break;\n                case \"varianceOutputFeatureName\":\n                    message.varianceOutputFeatureName = reader.string();\n                    break;\n                case \"pessimisticProbabilityOutputFeatureName\":\n                    message.pessimisticProbabilityOutputFeatureName = reader.string();\n                    break;\n                case \"sampledProbabilityOutputFeatureName\":\n                    message.sampledProbabilityOutputFeatureName = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BayesianProbitRegressor.prototype.numberOfFeatures = 0;\nCoreML.Specification.BayesianProbitRegressor.prototype.bias = null;\nCoreML.Specification.BayesianProbitRegressor.prototype.regressionInputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.optimismInputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.samplingScaleInputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.samplingTruncationInputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.meanOutputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.varianceOutputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.pessimisticProbabilityOutputFeatureName = \"\";\nCoreML.Specification.BayesianProbitRegressor.prototype.sampledProbabilityOutputFeatureName = \"\";\n\nCoreML.Specification.BayesianProbitRegressor.Gaussian = class Gaussian {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BayesianProbitRegressor.Gaussian();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mean = reader.double();\n                    break;\n                case 2:\n                    message.precision = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BayesianProbitRegressor.Gaussian();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mean\":\n                    message.mean = reader.double();\n                    break;\n                case \"precision\":\n                    message.precision = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BayesianProbitRegressor.Gaussian.prototype.mean = 0;\nCoreML.Specification.BayesianProbitRegressor.Gaussian.prototype.precision = 0;\n\nCoreML.Specification.BayesianProbitRegressor.FeatureValueWeight = class FeatureValueWeight {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BayesianProbitRegressor.FeatureValueWeight();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.featureValue = reader.uint32();\n                    break;\n                case 2:\n                    message.featureWeight = CoreML.Specification.BayesianProbitRegressor.Gaussian.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BayesianProbitRegressor.FeatureValueWeight();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"featureValue\":\n                    message.featureValue = reader.uint32();\n                    break;\n                case \"featureWeight\":\n                    message.featureWeight = CoreML.Specification.BayesianProbitRegressor.Gaussian.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BayesianProbitRegressor.FeatureValueWeight.prototype.featureValue = 0;\nCoreML.Specification.BayesianProbitRegressor.FeatureValueWeight.prototype.featureWeight = null;\n\nCoreML.Specification.BayesianProbitRegressor.FeatureWeight = class FeatureWeight {\n\n    constructor() {\n        this.weights = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BayesianProbitRegressor.FeatureWeight();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.featureId = reader.uint32();\n                    break;\n                case 2:\n                    message.weights.push(CoreML.Specification.BayesianProbitRegressor.FeatureValueWeight.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BayesianProbitRegressor.FeatureWeight();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"featureId\":\n                    message.featureId = reader.uint32();\n                    break;\n                case \"weights\":\n                    message.weights.push(CoreML.Specification.BayesianProbitRegressor.FeatureValueWeight.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BayesianProbitRegressor.FeatureWeight.prototype.featureId = 0;\n\nCoreML.Specification.CategoricalMapping = class CategoricalMapping {\n\n    get MappingType() {\n        CoreML.Specification.CategoricalMapping.MappingTypeSet = CoreML.Specification.CategoricalMapping.MappingTypeSet || new Set([\"stringToInt64Map\", \"int64ToStringMap\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CategoricalMapping.MappingTypeSet.has(key) && this[key] !== null);\n    }\n\n    get ValueOnUnknown() {\n        CoreML.Specification.CategoricalMapping.ValueOnUnknownSet = CoreML.Specification.CategoricalMapping.ValueOnUnknownSet || new Set([\"strValue\", \"int64Value\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CategoricalMapping.ValueOnUnknownSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CategoricalMapping();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.stringToInt64Map = CoreML.Specification.StringToInt64Map.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.int64ToStringMap = CoreML.Specification.Int64ToStringMap.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.strValue = reader.string();\n                    break;\n                case 102:\n                    message.int64Value = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CategoricalMapping();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"stringToInt64Map\":\n                    message.stringToInt64Map = CoreML.Specification.StringToInt64Map.decodeText(reader);\n                    break;\n                case \"int64ToStringMap\":\n                    message.int64ToStringMap = CoreML.Specification.Int64ToStringMap.decodeText(reader);\n                    break;\n                case \"strValue\":\n                    message.strValue = reader.string();\n                    break;\n                case \"int64Value\":\n                    message.int64Value = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CustomModel = class CustomModel {\n\n    constructor() {\n        this.parameters = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CustomModel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.className = reader.string();\n                    break;\n                case 30:\n                    reader.entry(message.parameters, () => reader.string(), () => CoreML.Specification.CustomModel.CustomModelParamValue.decode(reader, reader.uint32()));\n                    break;\n                case 40:\n                    message.description = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CustomModel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"className\":\n                    message.className = reader.string();\n                    break;\n                case \"parameters\":\n                    reader.entry(message.parameters, () => reader.string(), () => CoreML.Specification.CustomModel.CustomModelParamValue.decodeText(reader));\n                    break;\n                case \"description\":\n                    message.description = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CustomModel.prototype.className = \"\";\nCoreML.Specification.CustomModel.prototype.description = \"\";\n\nCoreML.Specification.CustomModel.CustomModelParamValue = class CustomModelParamValue {\n\n    get value() {\n        CoreML.Specification.CustomModel.CustomModelParamValue.valueSet = CoreML.Specification.CustomModel.CustomModelParamValue.valueSet || new Set([\"doubleValue\", \"stringValue\", \"intValue\", \"longValue\", \"boolValue\", \"bytesValue\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CustomModel.CustomModelParamValue.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CustomModel.CustomModelParamValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.doubleValue = reader.double();\n                    break;\n                case 20:\n                    message.stringValue = reader.string();\n                    break;\n                case 30:\n                    message.intValue = reader.int32();\n                    break;\n                case 40:\n                    message.longValue = reader.int64();\n                    break;\n                case 50:\n                    message.boolValue = reader.bool();\n                    break;\n                case 60:\n                    message.bytesValue = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CustomModel.CustomModelParamValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"doubleValue\":\n                    message.doubleValue = reader.double();\n                    break;\n                case \"stringValue\":\n                    message.stringValue = reader.string();\n                    break;\n                case \"intValue\":\n                    message.intValue = reader.int32();\n                    break;\n                case \"longValue\":\n                    message.longValue = reader.int64();\n                    break;\n                case \"boolValue\":\n                    message.boolValue = reader.bool();\n                    break;\n                case \"bytesValue\":\n                    message.bytesValue = reader.bytes();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DictVectorizer = class DictVectorizer {\n\n    get Map() {\n        CoreML.Specification.DictVectorizer.MapSet = CoreML.Specification.DictVectorizer.MapSet || new Set([\"stringToIndex\", \"int64ToIndex\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.DictVectorizer.MapSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DictVectorizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.stringToIndex = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.int64ToIndex = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DictVectorizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"stringToIndex\":\n                    message.stringToIndex = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ToIndex\":\n                    message.int64ToIndex = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FeatureVectorizer = class FeatureVectorizer {\n\n    constructor() {\n        this.inputList = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FeatureVectorizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputList.push(CoreML.Specification.FeatureVectorizer.InputColumn.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FeatureVectorizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputList\":\n                    message.inputList.push(CoreML.Specification.FeatureVectorizer.InputColumn.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FeatureVectorizer.InputColumn = class InputColumn {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FeatureVectorizer.InputColumn();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputColumn = reader.string();\n                    break;\n                case 2:\n                    message.inputDimensions = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FeatureVectorizer.InputColumn();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputColumn\":\n                    message.inputColumn = reader.string();\n                    break;\n                case \"inputDimensions\":\n                    message.inputDimensions = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FeatureVectorizer.InputColumn.prototype.inputColumn = \"\";\nCoreML.Specification.FeatureVectorizer.InputColumn.prototype.inputDimensions = 0n;\n\nCoreML.Specification.GLMRegressor = class GLMRegressor {\n\n    constructor() {\n        this.weights = [];\n        this.offset = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GLMRegressor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.weights.push(CoreML.Specification.GLMRegressor.DoubleArray.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.offset = reader.doubles(message.offset, tag);\n                    break;\n                case 3:\n                    message.postEvaluationTransform = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GLMRegressor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"weights\":\n                    message.weights.push(CoreML.Specification.GLMRegressor.DoubleArray.decodeText(reader));\n                    break;\n                case \"offset\":\n                    reader.array(message.offset, () => reader.double());\n                    break;\n                case \"postEvaluationTransform\":\n                    message.postEvaluationTransform = reader.enum(CoreML.Specification.GLMRegressor.PostEvaluationTransform);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GLMRegressor.prototype.postEvaluationTransform = 0;\n\nCoreML.Specification.GLMRegressor.DoubleArray = class DoubleArray {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GLMRegressor.DoubleArray();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.doubles(message.value, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GLMRegressor.DoubleArray();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    reader.array(message.value, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GLMRegressor.PostEvaluationTransform = {\n    \"NoTransform\": 0,\n    \"Logit\": 1,\n    \"Probit\": 2\n};\n\nCoreML.Specification.GLMClassifier = class GLMClassifier {\n\n    constructor() {\n        this.weights = [];\n        this.offset = [];\n    }\n\n    get ClassLabels() {\n        CoreML.Specification.GLMClassifier.ClassLabelsSet = CoreML.Specification.GLMClassifier.ClassLabelsSet || new Set([\"stringClassLabels\", \"int64ClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.GLMClassifier.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GLMClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.weights.push(CoreML.Specification.GLMClassifier.DoubleArray.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.offset = reader.doubles(message.offset, tag);\n                    break;\n                case 3:\n                    message.postEvaluationTransform = reader.int32();\n                    break;\n                case 4:\n                    message.classEncoding = reader.int32();\n                    break;\n                case 100:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GLMClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"weights\":\n                    message.weights.push(CoreML.Specification.GLMClassifier.DoubleArray.decodeText(reader));\n                    break;\n                case \"offset\":\n                    reader.array(message.offset, () => reader.double());\n                    break;\n                case \"postEvaluationTransform\":\n                    message.postEvaluationTransform = reader.enum(CoreML.Specification.GLMClassifier.PostEvaluationTransform);\n                    break;\n                case \"classEncoding\":\n                    message.classEncoding = reader.enum(CoreML.Specification.GLMClassifier.ClassEncoding);\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ClassLabels\":\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GLMClassifier.prototype.postEvaluationTransform = 0;\nCoreML.Specification.GLMClassifier.prototype.classEncoding = 0;\n\nCoreML.Specification.GLMClassifier.DoubleArray = class DoubleArray {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GLMClassifier.DoubleArray();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.doubles(message.value, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GLMClassifier.DoubleArray();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    reader.array(message.value, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GLMClassifier.PostEvaluationTransform = {\n    \"Logit\": 0,\n    \"Probit\": 1\n};\n\nCoreML.Specification.GLMClassifier.ClassEncoding = {\n    \"ReferenceClass\": 0,\n    \"OneVsRest\": 1\n};\n\nCoreML.Specification.KNearestNeighborsClassifier = class KNearestNeighborsClassifier {\n\n    get ClassLabels() {\n        CoreML.Specification.KNearestNeighborsClassifier.ClassLabelsSet = CoreML.Specification.KNearestNeighborsClassifier.ClassLabelsSet || new Set([\"stringClassLabels\", \"int64ClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.KNearestNeighborsClassifier.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    get DefaultClassLabel() {\n        CoreML.Specification.KNearestNeighborsClassifier.DefaultClassLabelSet = CoreML.Specification.KNearestNeighborsClassifier.DefaultClassLabelSet || new Set([\"defaultStringLabel\", \"defaultInt64Label\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.KNearestNeighborsClassifier.DefaultClassLabelSet.has(key) && this[key] !== null);\n    }\n\n    get WeightingScheme() {\n        CoreML.Specification.KNearestNeighborsClassifier.WeightingSchemeSet = CoreML.Specification.KNearestNeighborsClassifier.WeightingSchemeSet || new Set([\"uniformWeighting\", \"inverseDistanceWeighting\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.KNearestNeighborsClassifier.WeightingSchemeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.KNearestNeighborsClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.nearestNeighborsIndex = CoreML.Specification.NearestNeighborsIndex.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.numberOfNeighbors = CoreML.Specification.Int64Parameter.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                case 110:\n                    message.defaultStringLabel = reader.string();\n                    break;\n                case 111:\n                    message.defaultInt64Label = reader.int64();\n                    break;\n                case 200:\n                    message.uniformWeighting = CoreML.Specification.UniformWeighting.decode(reader, reader.uint32());\n                    break;\n                case 210:\n                    message.inverseDistanceWeighting = CoreML.Specification.InverseDistanceWeighting.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.KNearestNeighborsClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"nearestNeighborsIndex\":\n                    message.nearestNeighborsIndex = CoreML.Specification.NearestNeighborsIndex.decodeText(reader);\n                    break;\n                case \"numberOfNeighbors\":\n                    message.numberOfNeighbors = CoreML.Specification.Int64Parameter.decodeText(reader);\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ClassLabels\":\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                case \"defaultStringLabel\":\n                    message.defaultStringLabel = reader.string();\n                    break;\n                case \"defaultInt64Label\":\n                    message.defaultInt64Label = reader.int64();\n                    break;\n                case \"uniformWeighting\":\n                    message.uniformWeighting = CoreML.Specification.UniformWeighting.decodeText(reader);\n                    break;\n                case \"inverseDistanceWeighting\":\n                    message.inverseDistanceWeighting = CoreML.Specification.InverseDistanceWeighting.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.KNearestNeighborsClassifier.prototype.nearestNeighborsIndex = null;\nCoreML.Specification.KNearestNeighborsClassifier.prototype.numberOfNeighbors = null;\n\nCoreML.Specification.NearestNeighborsIndex = class NearestNeighborsIndex {\n\n    constructor() {\n        this.floatSamples = [];\n    }\n\n    get IndexType() {\n        CoreML.Specification.NearestNeighborsIndex.IndexTypeSet = CoreML.Specification.NearestNeighborsIndex.IndexTypeSet || new Set([\"linearIndex\", \"singleKdTreeIndex\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NearestNeighborsIndex.IndexTypeSet.has(key) && this[key] !== null);\n    }\n\n    get DistanceFunction() {\n        CoreML.Specification.NearestNeighborsIndex.DistanceFunctionSet = CoreML.Specification.NearestNeighborsIndex.DistanceFunctionSet || new Set([\"squaredEuclideanDistance\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NearestNeighborsIndex.DistanceFunctionSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NearestNeighborsIndex();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.numberOfDimensions = reader.int32();\n                    break;\n                case 2:\n                    message.floatSamples.push(CoreML.Specification.FloatVector.decode(reader, reader.uint32()));\n                    break;\n                case 100:\n                    message.linearIndex = CoreML.Specification.LinearIndex.decode(reader, reader.uint32());\n                    break;\n                case 110:\n                    message.singleKdTreeIndex = CoreML.Specification.SingleKdTreeIndex.decode(reader, reader.uint32());\n                    break;\n                case 200:\n                    message.squaredEuclideanDistance = CoreML.Specification.SquaredEuclideanDistance.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NearestNeighborsIndex();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"numberOfDimensions\":\n                    message.numberOfDimensions = reader.int32();\n                    break;\n                case \"floatSamples\":\n                    message.floatSamples.push(CoreML.Specification.FloatVector.decodeText(reader));\n                    break;\n                case \"linearIndex\":\n                    message.linearIndex = CoreML.Specification.LinearIndex.decodeText(reader);\n                    break;\n                case \"singleKdTreeIndex\":\n                    message.singleKdTreeIndex = CoreML.Specification.SingleKdTreeIndex.decodeText(reader);\n                    break;\n                case \"squaredEuclideanDistance\":\n                    message.squaredEuclideanDistance = CoreML.Specification.SquaredEuclideanDistance.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NearestNeighborsIndex.prototype.numberOfDimensions = 0;\n\nCoreML.Specification.UniformWeighting = class UniformWeighting {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.UniformWeighting();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.UniformWeighting();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.InverseDistanceWeighting = class InverseDistanceWeighting {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.InverseDistanceWeighting();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.InverseDistanceWeighting();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LinearIndex = class LinearIndex {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LinearIndex();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LinearIndex();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SingleKdTreeIndex = class SingleKdTreeIndex {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SingleKdTreeIndex();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.leafSize = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SingleKdTreeIndex();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"leafSize\":\n                    message.leafSize = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SingleKdTreeIndex.prototype.leafSize = 0;\n\nCoreML.Specification.SquaredEuclideanDistance = class SquaredEuclideanDistance {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SquaredEuclideanDistance();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SquaredEuclideanDistance();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64Parameter = class Int64Parameter {\n\n    get AllowedValues() {\n        CoreML.Specification.Int64Parameter.AllowedValuesSet = CoreML.Specification.Int64Parameter.AllowedValuesSet || new Set([\"range\", \"set\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.Int64Parameter.AllowedValuesSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Int64Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.defaultValue = reader.int64();\n                    break;\n                case 10:\n                    message.range = CoreML.Specification.Int64Range.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.set = CoreML.Specification.Int64Set.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Int64Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"defaultValue\":\n                    message.defaultValue = reader.int64();\n                    break;\n                case \"range\":\n                    message.range = CoreML.Specification.Int64Range.decodeText(reader);\n                    break;\n                case \"set\":\n                    message.set = CoreML.Specification.Int64Set.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Int64Parameter.prototype.defaultValue = 0n;\n\nCoreML.Specification.DoubleParameter = class DoubleParameter {\n\n    get AllowedValues() {\n        CoreML.Specification.DoubleParameter.AllowedValuesSet = CoreML.Specification.DoubleParameter.AllowedValuesSet || new Set([\"range\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.DoubleParameter.AllowedValuesSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DoubleParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.defaultValue = reader.double();\n                    break;\n                case 10:\n                    message.range = CoreML.Specification.DoubleRange.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DoubleParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"defaultValue\":\n                    message.defaultValue = reader.double();\n                    break;\n                case \"range\":\n                    message.range = CoreML.Specification.DoubleRange.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DoubleParameter.prototype.defaultValue = 0;\n\nCoreML.Specification.StringParameter = class StringParameter {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StringParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.defaultValue = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StringParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"defaultValue\":\n                    message.defaultValue = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.StringParameter.prototype.defaultValue = \"\";\n\nCoreML.Specification.BoolParameter = class BoolParameter {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BoolParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.defaultValue = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BoolParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"defaultValue\":\n                    message.defaultValue = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BoolParameter.prototype.defaultValue = false;\n\nCoreML.Specification.Identity = class Identity {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Identity();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Identity();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Imputer = class Imputer {\n\n    get ImputedValue() {\n        CoreML.Specification.Imputer.ImputedValueSet = CoreML.Specification.Imputer.ImputedValueSet || new Set([\"imputedDoubleValue\", \"imputedInt64Value\", \"imputedStringValue\", \"imputedDoubleArray\", \"imputedInt64Array\", \"imputedStringDictionary\", \"imputedInt64Dictionary\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.Imputer.ImputedValueSet.has(key) && this[key] !== null);\n    }\n\n    get ReplaceValue() {\n        CoreML.Specification.Imputer.ReplaceValueSet = CoreML.Specification.Imputer.ReplaceValueSet || new Set([\"replaceDoubleValue\", \"replaceInt64Value\", \"replaceStringValue\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.Imputer.ReplaceValueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Imputer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.imputedDoubleValue = reader.double();\n                    break;\n                case 2:\n                    message.imputedInt64Value = reader.int64();\n                    break;\n                case 3:\n                    message.imputedStringValue = reader.string();\n                    break;\n                case 4:\n                    message.imputedDoubleArray = CoreML.Specification.DoubleVector.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.imputedInt64Array = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.imputedStringDictionary = CoreML.Specification.StringToDoubleMap.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.imputedInt64Dictionary = CoreML.Specification.Int64ToDoubleMap.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.replaceDoubleValue = reader.double();\n                    break;\n                case 12:\n                    message.replaceInt64Value = reader.int64();\n                    break;\n                case 13:\n                    message.replaceStringValue = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Imputer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"imputedDoubleValue\":\n                    message.imputedDoubleValue = reader.double();\n                    break;\n                case \"imputedInt64Value\":\n                    message.imputedInt64Value = reader.int64();\n                    break;\n                case \"imputedStringValue\":\n                    message.imputedStringValue = reader.string();\n                    break;\n                case \"imputedDoubleArray\":\n                    message.imputedDoubleArray = CoreML.Specification.DoubleVector.decodeText(reader);\n                    break;\n                case \"imputedInt64Array\":\n                    message.imputedInt64Array = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                case \"imputedStringDictionary\":\n                    message.imputedStringDictionary = CoreML.Specification.StringToDoubleMap.decodeText(reader);\n                    break;\n                case \"imputedInt64Dictionary\":\n                    message.imputedInt64Dictionary = CoreML.Specification.Int64ToDoubleMap.decodeText(reader);\n                    break;\n                case \"replaceDoubleValue\":\n                    message.replaceDoubleValue = reader.double();\n                    break;\n                case \"replaceInt64Value\":\n                    message.replaceInt64Value = reader.int64();\n                    break;\n                case \"replaceStringValue\":\n                    message.replaceStringValue = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec = {};\n\nCoreML.Specification.MILSpec.Program = class Program {\n\n    constructor() {\n        this.functions = {};\n        this.attributes = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Program();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.int64();\n                    break;\n                case 2:\n                    reader.entry(message.functions, () => reader.string(), () => CoreML.Specification.MILSpec.Function.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.docString = reader.string();\n                    break;\n                case 4:\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Program();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"version\":\n                    message.version = reader.int64();\n                    break;\n                case \"functions\":\n                    reader.entry(message.functions, () => reader.string(), () => CoreML.Specification.MILSpec.Function.decodeText(reader));\n                    break;\n                case \"docString\":\n                    message.docString = reader.string();\n                    break;\n                case \"attributes\":\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Program.prototype.version = 0n;\nCoreML.Specification.MILSpec.Program.prototype.docString = \"\";\n\nCoreML.Specification.MILSpec.Function = class Function {\n\n    constructor() {\n        this.inputs = [];\n        this.block_specializations = {};\n        this.attributes = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Function();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputs.push(CoreML.Specification.MILSpec.NamedValueType.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.opset = reader.string();\n                    break;\n                case 3:\n                    reader.entry(message.block_specializations, () => reader.string(), () => CoreML.Specification.MILSpec.Block.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Function();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputs\":\n                    message.inputs.push(CoreML.Specification.MILSpec.NamedValueType.decodeText(reader));\n                    break;\n                case \"opset\":\n                    message.opset = reader.string();\n                    break;\n                case \"block_specializations\":\n                    reader.entry(message.block_specializations, () => reader.string(), () => CoreML.Specification.MILSpec.Block.decodeText(reader));\n                    break;\n                case \"attributes\":\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Function.prototype.opset = \"\";\n\nCoreML.Specification.MILSpec.Block = class Block {\n\n    constructor() {\n        this.inputs = [];\n        this.outputs = [];\n        this.operations = [];\n        this.attributes = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Block();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputs.push(CoreML.Specification.MILSpec.NamedValueType.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.outputs.push(reader.string());\n                    break;\n                case 3:\n                    message.operations.push(CoreML.Specification.MILSpec.Operation.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Block();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputs\":\n                    message.inputs.push(CoreML.Specification.MILSpec.NamedValueType.decodeText(reader));\n                    break;\n                case \"outputs\":\n                    reader.array(message.outputs, () => reader.string());\n                    break;\n                case \"operations\":\n                    message.operations.push(CoreML.Specification.MILSpec.Operation.decodeText(reader));\n                    break;\n                case \"attributes\":\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Argument = class Argument {\n\n    constructor() {\n        this.arguments = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Argument();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.arguments.push(CoreML.Specification.MILSpec.Argument.Binding.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Argument();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"arguments\":\n                    message.arguments.push(CoreML.Specification.MILSpec.Argument.Binding.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Argument.Binding = class Binding {\n\n    get binding() {\n        CoreML.Specification.MILSpec.Argument.Binding.bindingSet = CoreML.Specification.MILSpec.Argument.Binding.bindingSet || new Set([\"name\", \"value\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.MILSpec.Argument.Binding.bindingSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Argument.Binding();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.value = CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Argument.Binding();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"value\":\n                    message.value = CoreML.Specification.MILSpec.Value.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Operation = class Operation {\n\n    constructor() {\n        this.inputs = {};\n        this.outputs = [];\n        this.blocks = [];\n        this.attributes = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Operation();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = reader.string();\n                    break;\n                case 2:\n                    reader.entry(message.inputs, () => reader.string(), () => CoreML.Specification.MILSpec.Argument.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.outputs.push(CoreML.Specification.MILSpec.NamedValueType.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    message.blocks.push(CoreML.Specification.MILSpec.Block.decode(reader, reader.uint32()));\n                    break;\n                case 5:\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Operation();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"inputs\":\n                    reader.entry(message.inputs, () => reader.string(), () => CoreML.Specification.MILSpec.Argument.decodeText(reader));\n                    break;\n                case \"outputs\":\n                    message.outputs.push(CoreML.Specification.MILSpec.NamedValueType.decodeText(reader));\n                    break;\n                case \"blocks\":\n                    message.blocks.push(CoreML.Specification.MILSpec.Block.decodeText(reader));\n                    break;\n                case \"attributes\":\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Operation.prototype.type = \"\";\n\nCoreML.Specification.MILSpec.NamedValueType = class NamedValueType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.NamedValueType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.NamedValueType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = CoreML.Specification.MILSpec.ValueType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.NamedValueType.prototype.name = \"\";\nCoreML.Specification.MILSpec.NamedValueType.prototype.type = null;\n\nCoreML.Specification.MILSpec.ValueType = class ValueType {\n\n    get type() {\n        CoreML.Specification.MILSpec.ValueType.typeSet = CoreML.Specification.MILSpec.ValueType.typeSet || new Set([\"tensorType\", \"listType\", \"tupleType\", \"dictionaryType\", \"stateType\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.MILSpec.ValueType.typeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.ValueType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.tensorType = CoreML.Specification.MILSpec.TensorType.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.listType = CoreML.Specification.MILSpec.ListType.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.tupleType = CoreML.Specification.MILSpec.TupleType.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dictionaryType = CoreML.Specification.MILSpec.DictionaryType.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.stateType = CoreML.Specification.MILSpec.StateType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.ValueType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"tensorType\":\n                    message.tensorType = CoreML.Specification.MILSpec.TensorType.decodeText(reader);\n                    break;\n                case \"listType\":\n                    message.listType = CoreML.Specification.MILSpec.ListType.decodeText(reader);\n                    break;\n                case \"tupleType\":\n                    message.tupleType = CoreML.Specification.MILSpec.TupleType.decodeText(reader);\n                    break;\n                case \"dictionaryType\":\n                    message.dictionaryType = CoreML.Specification.MILSpec.DictionaryType.decodeText(reader);\n                    break;\n                case \"stateType\":\n                    message.stateType = CoreML.Specification.MILSpec.StateType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.DataType = {\n    \"UNUSED_TYPE\": 0,\n    \"BOOL\": 1,\n    \"STRING\": 2,\n    \"FLOAT8E4M3FN\": 40,\n    \"FLOAT8E5M2\": 41,\n    \"FLOAT16\": 10,\n    \"FLOAT32\": 11,\n    \"FLOAT64\": 12,\n    \"BFLOAT16\": 13,\n    \"INT8\": 21,\n    \"INT16\": 22,\n    \"INT32\": 23,\n    \"INT64\": 24,\n    \"INT4\": 25,\n    \"UINT8\": 31,\n    \"UINT16\": 32,\n    \"UINT32\": 33,\n    \"UINT64\": 34,\n    \"UINT4\": 35,\n    \"UINT2\": 36,\n    \"UINT1\": 37,\n    \"UINT6\": 38,\n    \"UINT3\": 39\n};\n\nCoreML.Specification.MILSpec.TensorType = class TensorType {\n\n    constructor() {\n        this.dimensions = [];\n        this.attributes = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dataType = reader.int32();\n                    break;\n                case 2:\n                    message.rank = reader.int64();\n                    break;\n                case 3:\n                    message.dimensions.push(CoreML.Specification.MILSpec.Dimension.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dataType\":\n                    message.dataType = reader.enum(CoreML.Specification.MILSpec.DataType);\n                    break;\n                case \"rank\":\n                    message.rank = reader.int64();\n                    break;\n                case \"dimensions\":\n                    message.dimensions.push(CoreML.Specification.MILSpec.Dimension.decodeText(reader));\n                    break;\n                case \"attributes\":\n                    reader.entry(message.attributes, () => reader.string(), () => CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorType.prototype.dataType = 0;\nCoreML.Specification.MILSpec.TensorType.prototype.rank = 0n;\n\nCoreML.Specification.MILSpec.TupleType = class TupleType {\n\n    constructor() {\n        this.types = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TupleType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.types.push(CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TupleType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"types\":\n                    message.types.push(CoreML.Specification.MILSpec.ValueType.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.ListType = class ListType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.ListType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.length = CoreML.Specification.MILSpec.Dimension.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.ListType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = CoreML.Specification.MILSpec.ValueType.decodeText(reader);\n                    break;\n                case \"length\":\n                    message.length = CoreML.Specification.MILSpec.Dimension.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.ListType.prototype.type = null;\nCoreML.Specification.MILSpec.ListType.prototype.length = null;\n\nCoreML.Specification.MILSpec.DictionaryType = class DictionaryType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.DictionaryType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.keyType = CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.valueType = CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.DictionaryType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"keyType\":\n                    message.keyType = CoreML.Specification.MILSpec.ValueType.decodeText(reader);\n                    break;\n                case \"valueType\":\n                    message.valueType = CoreML.Specification.MILSpec.ValueType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.DictionaryType.prototype.keyType = null;\nCoreML.Specification.MILSpec.DictionaryType.prototype.valueType = null;\n\nCoreML.Specification.MILSpec.StateType = class StateType {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.StateType();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.wrappedType = CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.StateType();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"wrappedType\":\n                    message.wrappedType = CoreML.Specification.MILSpec.ValueType.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.StateType.prototype.wrappedType = null;\n\nCoreML.Specification.MILSpec.Dimension = class Dimension {\n\n    get dimension() {\n        CoreML.Specification.MILSpec.Dimension.dimensionSet = CoreML.Specification.MILSpec.Dimension.dimensionSet || new Set([\"constant\", \"unknown\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.MILSpec.Dimension.dimensionSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Dimension();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.constant = CoreML.Specification.MILSpec.Dimension.ConstantDimension.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.unknown = CoreML.Specification.MILSpec.Dimension.UnknownDimension.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Dimension();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"constant\":\n                    message.constant = CoreML.Specification.MILSpec.Dimension.ConstantDimension.decodeText(reader);\n                    break;\n                case \"unknown\":\n                    message.unknown = CoreML.Specification.MILSpec.Dimension.UnknownDimension.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Dimension.ConstantDimension = class ConstantDimension {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Dimension.ConstantDimension();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.size = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Dimension.ConstantDimension();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"size\":\n                    message.size = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Dimension.ConstantDimension.prototype.size = 0n;\n\nCoreML.Specification.MILSpec.Dimension.UnknownDimension = class UnknownDimension {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Dimension.UnknownDimension();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variadic = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Dimension.UnknownDimension();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variadic\":\n                    message.variadic = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Dimension.UnknownDimension.prototype.variadic = false;\n\nCoreML.Specification.MILSpec.Value = class Value {\n\n    get value() {\n        CoreML.Specification.MILSpec.Value.valueSet = CoreML.Specification.MILSpec.Value.valueSet || new Set([\"immediateValue\", \"blobFileValue\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.MILSpec.Value.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Value();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.docString = reader.string();\n                    break;\n                case 2:\n                    message.type = CoreML.Specification.MILSpec.ValueType.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.immediateValue = CoreML.Specification.MILSpec.Value.ImmediateValue.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.blobFileValue = CoreML.Specification.MILSpec.Value.BlobFileValue.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Value();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"docString\":\n                    message.docString = reader.string();\n                    break;\n                case \"type\":\n                    message.type = CoreML.Specification.MILSpec.ValueType.decodeText(reader);\n                    break;\n                case \"immediateValue\":\n                    message.immediateValue = CoreML.Specification.MILSpec.Value.ImmediateValue.decodeText(reader);\n                    break;\n                case \"blobFileValue\":\n                    message.blobFileValue = CoreML.Specification.MILSpec.Value.BlobFileValue.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Value.prototype.docString = \"\";\nCoreML.Specification.MILSpec.Value.prototype.type = null;\n\nCoreML.Specification.MILSpec.Value.ImmediateValue = class ImmediateValue {\n\n    get value() {\n        CoreML.Specification.MILSpec.Value.ImmediateValue.valueSet = CoreML.Specification.MILSpec.Value.ImmediateValue.valueSet || new Set([\"tensor\", \"tuple\", \"list\", \"dictionary\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.MILSpec.Value.ImmediateValue.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Value.ImmediateValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.tensor = CoreML.Specification.MILSpec.TensorValue.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.tuple = CoreML.Specification.MILSpec.TupleValue.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.list = CoreML.Specification.MILSpec.ListValue.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dictionary = CoreML.Specification.MILSpec.DictionaryValue.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Value.ImmediateValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"tensor\":\n                    message.tensor = CoreML.Specification.MILSpec.TensorValue.decodeText(reader);\n                    break;\n                case \"tuple\":\n                    message.tuple = CoreML.Specification.MILSpec.TupleValue.decodeText(reader);\n                    break;\n                case \"list\":\n                    message.list = CoreML.Specification.MILSpec.ListValue.decodeText(reader);\n                    break;\n                case \"dictionary\":\n                    message.dictionary = CoreML.Specification.MILSpec.DictionaryValue.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Value.BlobFileValue = class BlobFileValue {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.Value.BlobFileValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.fileName = reader.string();\n                    break;\n                case 2:\n                    message.offset = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.Value.BlobFileValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"fileName\":\n                    message.fileName = reader.string();\n                    break;\n                case \"offset\":\n                    message.offset = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.Value.BlobFileValue.prototype.fileName = \"\";\nCoreML.Specification.MILSpec.Value.BlobFileValue.prototype.offset = 0n;\n\nCoreML.Specification.MILSpec.TensorValue = class TensorValue {\n\n    get value() {\n        CoreML.Specification.MILSpec.TensorValue.valueSet = CoreML.Specification.MILSpec.TensorValue.valueSet || new Set([\"floats\", \"ints\", \"bools\", \"strings\", \"longInts\", \"doubles\", \"bytes\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.MILSpec.TensorValue.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.floats = CoreML.Specification.MILSpec.TensorValue.RepeatedFloats.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.ints = CoreML.Specification.MILSpec.TensorValue.RepeatedInts.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.bools = CoreML.Specification.MILSpec.TensorValue.RepeatedBools.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.strings = CoreML.Specification.MILSpec.TensorValue.RepeatedStrings.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.longInts = CoreML.Specification.MILSpec.TensorValue.RepeatedLongInts.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.doubles = CoreML.Specification.MILSpec.TensorValue.RepeatedDoubles.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.bytes = CoreML.Specification.MILSpec.TensorValue.RepeatedBytes.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"floats\":\n                    message.floats = CoreML.Specification.MILSpec.TensorValue.RepeatedFloats.decodeText(reader);\n                    break;\n                case \"ints\":\n                    message.ints = CoreML.Specification.MILSpec.TensorValue.RepeatedInts.decodeText(reader);\n                    break;\n                case \"bools\":\n                    message.bools = CoreML.Specification.MILSpec.TensorValue.RepeatedBools.decodeText(reader);\n                    break;\n                case \"strings\":\n                    message.strings = CoreML.Specification.MILSpec.TensorValue.RepeatedStrings.decodeText(reader);\n                    break;\n                case \"longInts\":\n                    message.longInts = CoreML.Specification.MILSpec.TensorValue.RepeatedLongInts.decodeText(reader);\n                    break;\n                case \"doubles\":\n                    message.doubles = CoreML.Specification.MILSpec.TensorValue.RepeatedDoubles.decodeText(reader);\n                    break;\n                case \"bytes\":\n                    message.bytes = CoreML.Specification.MILSpec.TensorValue.RepeatedBytes.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedFloats = class RepeatedFloats {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedFloats();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.floats(message.values, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedFloats();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedDoubles = class RepeatedDoubles {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedDoubles();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.doubles(message.values, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedDoubles();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedInts = class RepeatedInts {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedInts();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.array(message.values, () => reader.int32(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedInts();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.int32());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedLongInts = class RepeatedLongInts {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedLongInts();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.array(message.values, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedLongInts();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedBools = class RepeatedBools {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedBools();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.array(message.values, () => reader.bool(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedBools();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.bool());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedStrings = class RepeatedStrings {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedStrings();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedStrings();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedBytes = class RepeatedBytes {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedBytes();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TensorValue.RepeatedBytes();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    message.values = reader.bytes();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.TensorValue.RepeatedBytes.prototype.values = new Uint8Array([]);\n\nCoreML.Specification.MILSpec.TupleValue = class TupleValue {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.TupleValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values.push(CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.TupleValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    message.values.push(CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.ListValue = class ListValue {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.ListValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values.push(CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.ListValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    message.values.push(CoreML.Specification.MILSpec.Value.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.DictionaryValue = class DictionaryValue {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.DictionaryValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values.push(CoreML.Specification.MILSpec.DictionaryValue.KeyValuePair.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.DictionaryValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    message.values.push(CoreML.Specification.MILSpec.DictionaryValue.KeyValuePair.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.DictionaryValue.KeyValuePair = class KeyValuePair {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MILSpec.DictionaryValue.KeyValuePair();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.key = CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.value = CoreML.Specification.MILSpec.Value.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MILSpec.DictionaryValue.KeyValuePair();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"key\":\n                    message.key = CoreML.Specification.MILSpec.Value.decodeText(reader);\n                    break;\n                case \"value\":\n                    message.value = CoreML.Specification.MILSpec.Value.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MILSpec.DictionaryValue.KeyValuePair.prototype.key = null;\nCoreML.Specification.MILSpec.DictionaryValue.KeyValuePair.prototype.value = null;\n\nCoreML.Specification.NeuralNetworkMultiArrayShapeMapping = {\n    \"RANK5_ARRAY_MAPPING\": 0,\n    \"EXACT_ARRAY_MAPPING\": 1\n};\n\nCoreML.Specification.NeuralNetworkImageShapeMapping = {\n    \"RANK5_IMAGE_MAPPING\": 0,\n    \"RANK4_IMAGE_MAPPING\": 1\n};\n\nCoreML.Specification.NeuralNetwork = class NeuralNetwork {\n\n    constructor() {\n        this.layers = [];\n        this.preprocessing = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetwork();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.layers.push(CoreML.Specification.NeuralNetworkLayer.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.preprocessing.push(CoreML.Specification.NeuralNetworkPreprocessing.decode(reader, reader.uint32()));\n                    break;\n                case 5:\n                    message.arrayInputShapeMapping = reader.int32();\n                    break;\n                case 6:\n                    message.imageInputShapeMapping = reader.int32();\n                    break;\n                case 10:\n                    message.updateParams = CoreML.Specification.NetworkUpdateParameters.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetwork();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"layers\":\n                    message.layers.push(CoreML.Specification.NeuralNetworkLayer.decodeText(reader));\n                    break;\n                case \"preprocessing\":\n                    message.preprocessing.push(CoreML.Specification.NeuralNetworkPreprocessing.decodeText(reader));\n                    break;\n                case \"arrayInputShapeMapping\":\n                    message.arrayInputShapeMapping = reader.enum(CoreML.Specification.NeuralNetworkMultiArrayShapeMapping);\n                    break;\n                case \"imageInputShapeMapping\":\n                    message.imageInputShapeMapping = reader.enum(CoreML.Specification.NeuralNetworkImageShapeMapping);\n                    break;\n                case \"updateParams\":\n                    message.updateParams = CoreML.Specification.NetworkUpdateParameters.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetwork.prototype.arrayInputShapeMapping = 0;\nCoreML.Specification.NeuralNetwork.prototype.imageInputShapeMapping = 0;\nCoreML.Specification.NeuralNetwork.prototype.updateParams = null;\n\nCoreML.Specification.NeuralNetworkImageScaler = class NeuralNetworkImageScaler {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetworkImageScaler();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.channelScale = reader.float();\n                    break;\n                case 20:\n                    message.blueBias = reader.float();\n                    break;\n                case 21:\n                    message.greenBias = reader.float();\n                    break;\n                case 22:\n                    message.redBias = reader.float();\n                    break;\n                case 30:\n                    message.grayBias = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetworkImageScaler();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"channelScale\":\n                    message.channelScale = reader.float();\n                    break;\n                case \"blueBias\":\n                    message.blueBias = reader.float();\n                    break;\n                case \"greenBias\":\n                    message.greenBias = reader.float();\n                    break;\n                case \"redBias\":\n                    message.redBias = reader.float();\n                    break;\n                case \"grayBias\":\n                    message.grayBias = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetworkImageScaler.prototype.channelScale = 0;\nCoreML.Specification.NeuralNetworkImageScaler.prototype.blueBias = 0;\nCoreML.Specification.NeuralNetworkImageScaler.prototype.greenBias = 0;\nCoreML.Specification.NeuralNetworkImageScaler.prototype.redBias = 0;\nCoreML.Specification.NeuralNetworkImageScaler.prototype.grayBias = 0;\n\nCoreML.Specification.NeuralNetworkMeanImage = class NeuralNetworkMeanImage {\n\n    constructor() {\n        this.meanImage = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetworkMeanImage();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.meanImage = reader.floats(message.meanImage, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetworkMeanImage();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"meanImage\":\n                    reader.array(message.meanImage, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetworkPreprocessing = class NeuralNetworkPreprocessing {\n\n    get preprocessor() {\n        CoreML.Specification.NeuralNetworkPreprocessing.preprocessorSet = CoreML.Specification.NeuralNetworkPreprocessing.preprocessorSet || new Set([\"scaler\", \"meanImage\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NeuralNetworkPreprocessing.preprocessorSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetworkPreprocessing();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.featureName = reader.string();\n                    break;\n                case 10:\n                    message.scaler = CoreML.Specification.NeuralNetworkImageScaler.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.meanImage = CoreML.Specification.NeuralNetworkMeanImage.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetworkPreprocessing();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"featureName\":\n                    message.featureName = reader.string();\n                    break;\n                case \"scaler\":\n                    message.scaler = CoreML.Specification.NeuralNetworkImageScaler.decodeText(reader);\n                    break;\n                case \"meanImage\":\n                    message.meanImage = CoreML.Specification.NeuralNetworkMeanImage.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetworkPreprocessing.prototype.featureName = \"\";\n\nCoreML.Specification.ActivationReLU = class ActivationReLU {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationReLU();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationReLU();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationLeakyReLU = class ActivationLeakyReLU {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationLeakyReLU();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationLeakyReLU();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationLeakyReLU.prototype.alpha = 0;\n\nCoreML.Specification.ActivationTanh = class ActivationTanh {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationTanh();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationTanh();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationScaledTanh = class ActivationScaledTanh {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationScaledTanh();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationScaledTanh();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationScaledTanh.prototype.alpha = 0;\nCoreML.Specification.ActivationScaledTanh.prototype.beta = 0;\n\nCoreML.Specification.ActivationSigmoid = class ActivationSigmoid {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationSigmoid();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationSigmoid();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationLinear = class ActivationLinear {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationLinear();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationLinear();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationLinear.prototype.alpha = 0;\nCoreML.Specification.ActivationLinear.prototype.beta = 0;\n\nCoreML.Specification.ActivationSigmoidHard = class ActivationSigmoidHard {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationSigmoidHard();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationSigmoidHard();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationSigmoidHard.prototype.alpha = 0;\nCoreML.Specification.ActivationSigmoidHard.prototype.beta = 0;\n\nCoreML.Specification.ActivationPReLU = class ActivationPReLU {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationPReLU();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationPReLU();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationPReLU.prototype.alpha = null;\n\nCoreML.Specification.ActivationELU = class ActivationELU {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationELU();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationELU();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationELU.prototype.alpha = 0;\n\nCoreML.Specification.ActivationThresholdedReLU = class ActivationThresholdedReLU {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationThresholdedReLU();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationThresholdedReLU();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationThresholdedReLU.prototype.alpha = 0;\n\nCoreML.Specification.ActivationSoftsign = class ActivationSoftsign {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationSoftsign();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationSoftsign();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationSoftplus = class ActivationSoftplus {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationSoftplus();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationSoftplus();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationParametricSoftplus = class ActivationParametricSoftplus {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationParametricSoftplus();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.beta = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationParametricSoftplus();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"beta\":\n                    message.beta = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ActivationParametricSoftplus.prototype.alpha = null;\nCoreML.Specification.ActivationParametricSoftplus.prototype.beta = null;\n\nCoreML.Specification.ActivationParams = class ActivationParams {\n\n    get NonlinearityType() {\n        CoreML.Specification.ActivationParams.NonlinearityTypeSet = CoreML.Specification.ActivationParams.NonlinearityTypeSet || new Set([\"linear\", \"ReLU\", \"leakyReLU\", \"thresholdedReLU\", \"PReLU\", \"tanh\", \"scaledTanh\", \"sigmoid\", \"sigmoidHard\", \"ELU\", \"softsign\", \"softplus\", \"parametricSoftplus\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.ActivationParams.NonlinearityTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ActivationParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 5:\n                    message.linear = CoreML.Specification.ActivationLinear.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.ReLU = CoreML.Specification.ActivationReLU.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.leakyReLU = CoreML.Specification.ActivationLeakyReLU.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.thresholdedReLU = CoreML.Specification.ActivationThresholdedReLU.decode(reader, reader.uint32());\n                    break;\n                case 25:\n                    message.PReLU = CoreML.Specification.ActivationPReLU.decode(reader, reader.uint32());\n                    break;\n                case 30:\n                    message.tanh = CoreML.Specification.ActivationTanh.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.scaledTanh = CoreML.Specification.ActivationScaledTanh.decode(reader, reader.uint32());\n                    break;\n                case 40:\n                    message.sigmoid = CoreML.Specification.ActivationSigmoid.decode(reader, reader.uint32());\n                    break;\n                case 41:\n                    message.sigmoidHard = CoreML.Specification.ActivationSigmoidHard.decode(reader, reader.uint32());\n                    break;\n                case 50:\n                    message.ELU = CoreML.Specification.ActivationELU.decode(reader, reader.uint32());\n                    break;\n                case 60:\n                    message.softsign = CoreML.Specification.ActivationSoftsign.decode(reader, reader.uint32());\n                    break;\n                case 70:\n                    message.softplus = CoreML.Specification.ActivationSoftplus.decode(reader, reader.uint32());\n                    break;\n                case 71:\n                    message.parametricSoftplus = CoreML.Specification.ActivationParametricSoftplus.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ActivationParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"linear\":\n                    message.linear = CoreML.Specification.ActivationLinear.decodeText(reader);\n                    break;\n                case \"ReLU\":\n                    message.ReLU = CoreML.Specification.ActivationReLU.decodeText(reader);\n                    break;\n                case \"leakyReLU\":\n                    message.leakyReLU = CoreML.Specification.ActivationLeakyReLU.decodeText(reader);\n                    break;\n                case \"thresholdedReLU\":\n                    message.thresholdedReLU = CoreML.Specification.ActivationThresholdedReLU.decodeText(reader);\n                    break;\n                case \"PReLU\":\n                    message.PReLU = CoreML.Specification.ActivationPReLU.decodeText(reader);\n                    break;\n                case \"tanh\":\n                    message.tanh = CoreML.Specification.ActivationTanh.decodeText(reader);\n                    break;\n                case \"scaledTanh\":\n                    message.scaledTanh = CoreML.Specification.ActivationScaledTanh.decodeText(reader);\n                    break;\n                case \"sigmoid\":\n                    message.sigmoid = CoreML.Specification.ActivationSigmoid.decodeText(reader);\n                    break;\n                case \"sigmoidHard\":\n                    message.sigmoidHard = CoreML.Specification.ActivationSigmoidHard.decodeText(reader);\n                    break;\n                case \"ELU\":\n                    message.ELU = CoreML.Specification.ActivationELU.decodeText(reader);\n                    break;\n                case \"softsign\":\n                    message.softsign = CoreML.Specification.ActivationSoftsign.decodeText(reader);\n                    break;\n                case \"softplus\":\n                    message.softplus = CoreML.Specification.ActivationSoftplus.decodeText(reader);\n                    break;\n                case \"parametricSoftplus\":\n                    message.parametricSoftplus = CoreML.Specification.ActivationParametricSoftplus.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Tensor = class Tensor {\n\n    constructor() {\n        this.dimValue = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Tensor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.rank = reader.uint32();\n                    break;\n                case 2:\n                    message.dimValue = reader.array(message.dimValue, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Tensor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"rank\":\n                    message.rank = reader.uint32();\n                    break;\n                case \"dimValue\":\n                    reader.array(message.dimValue, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Tensor.prototype.rank = 0;\n\nCoreML.Specification.NeuralNetworkLayer = class NeuralNetworkLayer {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n        this.inputTensor = [];\n        this.outputTensor = [];\n    }\n\n    get layer() {\n        CoreML.Specification.NeuralNetworkLayer.layerSet = CoreML.Specification.NeuralNetworkLayer.layerSet || new Set([\"convolution\", \"pooling\", \"activation\", \"innerProduct\", \"embedding\", \"batchnorm\", \"mvn\", \"l2normalize\", \"softmax\", \"lrn\", \"crop\", \"padding\", \"upsample\", \"resizeBilinear\", \"cropResize\", \"unary\", \"add\", \"multiply\", \"average\", \"scale\", \"bias\", \"max\", \"min\", \"dot\", \"reduce\", \"loadConstant\", \"reshape\", \"flatten\", \"permute\", \"concat\", \"split\", \"sequenceRepeat\", \"reorganizeData\", \"slice\", \"simpleRecurrent\", \"gru\", \"uniDirectionalLSTM\", \"biDirectionalLSTM\", \"custom\", \"copy\", \"branch\", \"loop\", \"loopBreak\", \"loopContinue\", \"rangeStatic\", \"rangeDynamic\", \"clip\", \"ceil\", \"floor\", \"sign\", \"round\", \"exp2\", \"sin\", \"cos\", \"tan\", \"asin\", \"acos\", \"atan\", \"sinh\", \"cosh\", \"tanh\", \"asinh\", \"acosh\", \"atanh\", \"erf\", \"gelu\", \"equal\", \"notEqual\", \"lessThan\", \"lessEqual\", \"greaterThan\", \"greaterEqual\", \"logicalOr\", \"logicalXor\", \"logicalNot\", \"logicalAnd\", \"modBroadcastable\", \"minBroadcastable\", \"maxBroadcastable\", \"addBroadcastable\", \"powBroadcastable\", \"divideBroadcastable\", \"floorDivBroadcastable\", \"multiplyBroadcastable\", \"subtractBroadcastable\", \"tile\", \"stack\", \"gather\", \"scatter\", \"gatherND\", \"scatterND\", \"softmaxND\", \"gatherAlongAxis\", \"scatterAlongAxis\", \"reverse\", \"reverseSeq\", \"splitND\", \"concatND\", \"transpose\", \"sliceStatic\", \"sliceDynamic\", \"slidingWindows\", \"topK\", \"argMin\", \"argMax\", \"embeddingND\", \"batchedMatmul\", \"getShape\", \"loadConstantND\", \"fillLike\", \"fillStatic\", \"fillDynamic\", \"broadcastToLike\", \"broadcastToStatic\", \"broadcastToDynamic\", \"squeeze\", \"expandDims\", \"flattenTo2D\", \"reshapeLike\", \"reshapeStatic\", \"reshapeDynamic\", \"rankPreservingReshape\", \"constantPad\", \"randomNormalLike\", \"randomNormalStatic\", \"randomNormalDynamic\", \"randomUniformLike\", \"randomUniformStatic\", \"randomUniformDynamic\", \"randomBernoulliLike\", \"randomBernoulliStatic\", \"randomBernoulliDynamic\", \"categoricalDistribution\", \"reduceL1\", \"reduceL2\", \"reduceMax\", \"reduceMin\", \"reduceSum\", \"reduceProd\", \"reduceMean\", \"reduceLogSum\", \"reduceSumSquare\", \"reduceLogSumExp\", \"whereNonZero\", \"matrixBandPart\", \"lowerTriangular\", \"upperTriangular\", \"whereBroadcastable\", \"layerNormalization\", \"NonMaximumSuppression\", \"oneHot\", \"cumSum\", \"clampedReLU\", \"argSort\", \"pooling3d\", \"globalPooling3d\", \"sliceBySize\", \"convolution3d\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NeuralNetworkLayer.layerSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetworkLayer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.input.push(reader.string());\n                    break;\n                case 3:\n                    message.output.push(reader.string());\n                    break;\n                case 4:\n                    message.inputTensor.push(CoreML.Specification.Tensor.decode(reader, reader.uint32()));\n                    break;\n                case 5:\n                    message.outputTensor.push(CoreML.Specification.Tensor.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.isUpdatable = reader.bool();\n                    break;\n                case 100:\n                    message.convolution = CoreML.Specification.ConvolutionLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 120:\n                    message.pooling = CoreML.Specification.PoolingLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 130:\n                    message.activation = CoreML.Specification.ActivationParams.decode(reader, reader.uint32());\n                    break;\n                case 140:\n                    message.innerProduct = CoreML.Specification.InnerProductLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 150:\n                    message.embedding = CoreML.Specification.EmbeddingLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 160:\n                    message.batchnorm = CoreML.Specification.BatchnormLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 165:\n                    message.mvn = CoreML.Specification.MeanVarianceNormalizeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 170:\n                    message.l2normalize = CoreML.Specification.L2NormalizeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 175:\n                    message.softmax = CoreML.Specification.SoftmaxLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 180:\n                    message.lrn = CoreML.Specification.LRNLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 190:\n                    message.crop = CoreML.Specification.CropLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 200:\n                    message.padding = CoreML.Specification.PaddingLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 210:\n                    message.upsample = CoreML.Specification.UpsampleLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 211:\n                    message.resizeBilinear = CoreML.Specification.ResizeBilinearLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 212:\n                    message.cropResize = CoreML.Specification.CropResizeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 220:\n                    message.unary = CoreML.Specification.UnaryFunctionLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 230:\n                    message.add = CoreML.Specification.AddLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 231:\n                    message.multiply = CoreML.Specification.MultiplyLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 240:\n                    message.average = CoreML.Specification.AverageLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 245:\n                    message.scale = CoreML.Specification.ScaleLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 250:\n                    message.bias = CoreML.Specification.BiasLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 260:\n                    message.max = CoreML.Specification.MaxLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 261:\n                    message.min = CoreML.Specification.MinLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 270:\n                    message.dot = CoreML.Specification.DotProductLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 280:\n                    message.reduce = CoreML.Specification.ReduceLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 290:\n                    message.loadConstant = CoreML.Specification.LoadConstantLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 300:\n                    message.reshape = CoreML.Specification.ReshapeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 301:\n                    message.flatten = CoreML.Specification.FlattenLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 310:\n                    message.permute = CoreML.Specification.PermuteLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 320:\n                    message.concat = CoreML.Specification.ConcatLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 330:\n                    message.split = CoreML.Specification.SplitLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 340:\n                    message.sequenceRepeat = CoreML.Specification.SequenceRepeatLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 345:\n                    message.reorganizeData = CoreML.Specification.ReorganizeDataLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 350:\n                    message.slice = CoreML.Specification.SliceLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 400:\n                    message.simpleRecurrent = CoreML.Specification.SimpleRecurrentLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 410:\n                    message.gru = CoreML.Specification.GRULayerParams.decode(reader, reader.uint32());\n                    break;\n                case 420:\n                    message.uniDirectionalLSTM = CoreML.Specification.UniDirectionalLSTMLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 430:\n                    message.biDirectionalLSTM = CoreML.Specification.BiDirectionalLSTMLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 500:\n                    message.custom = CoreML.Specification.CustomLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 600:\n                    message.copy = CoreML.Specification.CopyLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 605:\n                    message.branch = CoreML.Specification.BranchLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 615:\n                    message.loop = CoreML.Specification.LoopLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 620:\n                    message.loopBreak = CoreML.Specification.LoopBreakLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 625:\n                    message.loopContinue = CoreML.Specification.LoopContinueLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 635:\n                    message.rangeStatic = CoreML.Specification.RangeStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 640:\n                    message.rangeDynamic = CoreML.Specification.RangeDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 660:\n                    message.clip = CoreML.Specification.ClipLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 665:\n                    message.ceil = CoreML.Specification.CeilLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 670:\n                    message.floor = CoreML.Specification.FloorLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 680:\n                    message.sign = CoreML.Specification.SignLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 685:\n                    message.round = CoreML.Specification.RoundLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 700:\n                    message.exp2 = CoreML.Specification.Exp2LayerParams.decode(reader, reader.uint32());\n                    break;\n                case 710:\n                    message.sin = CoreML.Specification.SinLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 715:\n                    message.cos = CoreML.Specification.CosLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 720:\n                    message.tan = CoreML.Specification.TanLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 730:\n                    message.asin = CoreML.Specification.AsinLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 735:\n                    message.acos = CoreML.Specification.AcosLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 740:\n                    message.atan = CoreML.Specification.AtanLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 750:\n                    message.sinh = CoreML.Specification.SinhLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 755:\n                    message.cosh = CoreML.Specification.CoshLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 760:\n                    message.tanh = CoreML.Specification.TanhLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 770:\n                    message.asinh = CoreML.Specification.AsinhLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 775:\n                    message.acosh = CoreML.Specification.AcoshLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 780:\n                    message.atanh = CoreML.Specification.AtanhLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 790:\n                    message.erf = CoreML.Specification.ErfLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 795:\n                    message.gelu = CoreML.Specification.GeluLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 815:\n                    message.equal = CoreML.Specification.EqualLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 820:\n                    message.notEqual = CoreML.Specification.NotEqualLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 825:\n                    message.lessThan = CoreML.Specification.LessThanLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 827:\n                    message.lessEqual = CoreML.Specification.LessEqualLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 830:\n                    message.greaterThan = CoreML.Specification.GreaterThanLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 832:\n                    message.greaterEqual = CoreML.Specification.GreaterEqualLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 840:\n                    message.logicalOr = CoreML.Specification.LogicalOrLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 845:\n                    message.logicalXor = CoreML.Specification.LogicalXorLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 850:\n                    message.logicalNot = CoreML.Specification.LogicalNotLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 855:\n                    message.logicalAnd = CoreML.Specification.LogicalAndLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 865:\n                    message.modBroadcastable = CoreML.Specification.ModBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 870:\n                    message.minBroadcastable = CoreML.Specification.MinBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 875:\n                    message.maxBroadcastable = CoreML.Specification.MaxBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 880:\n                    message.addBroadcastable = CoreML.Specification.AddBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 885:\n                    message.powBroadcastable = CoreML.Specification.PowBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 890:\n                    message.divideBroadcastable = CoreML.Specification.DivideBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 895:\n                    message.floorDivBroadcastable = CoreML.Specification.FloorDivBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 900:\n                    message.multiplyBroadcastable = CoreML.Specification.MultiplyBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 905:\n                    message.subtractBroadcastable = CoreML.Specification.SubtractBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 920:\n                    message.tile = CoreML.Specification.TileLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 925:\n                    message.stack = CoreML.Specification.StackLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 930:\n                    message.gather = CoreML.Specification.GatherLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 935:\n                    message.scatter = CoreML.Specification.ScatterLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 940:\n                    message.gatherND = CoreML.Specification.GatherNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 945:\n                    message.scatterND = CoreML.Specification.ScatterNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 950:\n                    message.softmaxND = CoreML.Specification.SoftmaxNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 952:\n                    message.gatherAlongAxis = CoreML.Specification.GatherAlongAxisLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 954:\n                    message.scatterAlongAxis = CoreML.Specification.ScatterAlongAxisLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 960:\n                    message.reverse = CoreML.Specification.ReverseLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 965:\n                    message.reverseSeq = CoreML.Specification.ReverseSeqLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 975:\n                    message.splitND = CoreML.Specification.SplitNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 980:\n                    message.concatND = CoreML.Specification.ConcatNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 985:\n                    message.transpose = CoreML.Specification.TransposeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 995:\n                    message.sliceStatic = CoreML.Specification.SliceStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1000:\n                    message.sliceDynamic = CoreML.Specification.SliceDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1005:\n                    message.slidingWindows = CoreML.Specification.SlidingWindowsLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1015:\n                    message.topK = CoreML.Specification.TopKLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1020:\n                    message.argMin = CoreML.Specification.ArgMinLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1025:\n                    message.argMax = CoreML.Specification.ArgMaxLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1040:\n                    message.embeddingND = CoreML.Specification.EmbeddingNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1045:\n                    message.batchedMatmul = CoreML.Specification.BatchedMatMulLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1065:\n                    message.getShape = CoreML.Specification.GetShapeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1070:\n                    message.loadConstantND = CoreML.Specification.LoadConstantNDLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1080:\n                    message.fillLike = CoreML.Specification.FillLikeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1085:\n                    message.fillStatic = CoreML.Specification.FillStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1090:\n                    message.fillDynamic = CoreML.Specification.FillDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1100:\n                    message.broadcastToLike = CoreML.Specification.BroadcastToLikeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1105:\n                    message.broadcastToStatic = CoreML.Specification.BroadcastToStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1110:\n                    message.broadcastToDynamic = CoreML.Specification.BroadcastToDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1120:\n                    message.squeeze = CoreML.Specification.SqueezeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1125:\n                    message.expandDims = CoreML.Specification.ExpandDimsLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1130:\n                    message.flattenTo2D = CoreML.Specification.FlattenTo2DLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1135:\n                    message.reshapeLike = CoreML.Specification.ReshapeLikeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1140:\n                    message.reshapeStatic = CoreML.Specification.ReshapeStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1145:\n                    message.reshapeDynamic = CoreML.Specification.ReshapeDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1150:\n                    message.rankPreservingReshape = CoreML.Specification.RankPreservingReshapeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1155:\n                    message.constantPad = CoreML.Specification.ConstantPaddingLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1170:\n                    message.randomNormalLike = CoreML.Specification.RandomNormalLikeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1175:\n                    message.randomNormalStatic = CoreML.Specification.RandomNormalStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1180:\n                    message.randomNormalDynamic = CoreML.Specification.RandomNormalDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1190:\n                    message.randomUniformLike = CoreML.Specification.RandomUniformLikeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1195:\n                    message.randomUniformStatic = CoreML.Specification.RandomUniformStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1200:\n                    message.randomUniformDynamic = CoreML.Specification.RandomUniformDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1210:\n                    message.randomBernoulliLike = CoreML.Specification.RandomBernoulliLikeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1215:\n                    message.randomBernoulliStatic = CoreML.Specification.RandomBernoulliStaticLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1220:\n                    message.randomBernoulliDynamic = CoreML.Specification.RandomBernoulliDynamicLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1230:\n                    message.categoricalDistribution = CoreML.Specification.CategoricalDistributionLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1250:\n                    message.reduceL1 = CoreML.Specification.ReduceL1LayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1255:\n                    message.reduceL2 = CoreML.Specification.ReduceL2LayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1260:\n                    message.reduceMax = CoreML.Specification.ReduceMaxLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1265:\n                    message.reduceMin = CoreML.Specification.ReduceMinLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1270:\n                    message.reduceSum = CoreML.Specification.ReduceSumLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1275:\n                    message.reduceProd = CoreML.Specification.ReduceProdLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1280:\n                    message.reduceMean = CoreML.Specification.ReduceMeanLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1285:\n                    message.reduceLogSum = CoreML.Specification.ReduceLogSumLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1290:\n                    message.reduceSumSquare = CoreML.Specification.ReduceSumSquareLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1295:\n                    message.reduceLogSumExp = CoreML.Specification.ReduceLogSumExpLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1313:\n                    message.whereNonZero = CoreML.Specification.WhereNonZeroLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1315:\n                    message.matrixBandPart = CoreML.Specification.MatrixBandPartLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1320:\n                    message.lowerTriangular = CoreML.Specification.LowerTriangularLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1325:\n                    message.upperTriangular = CoreML.Specification.UpperTriangularLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1330:\n                    message.whereBroadcastable = CoreML.Specification.WhereBroadcastableLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1350:\n                    message.layerNormalization = CoreML.Specification.LayerNormalizationLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1400:\n                    message.NonMaximumSuppression = CoreML.Specification.NonMaximumSuppressionLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1450:\n                    message.oneHot = CoreML.Specification.OneHotLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1455:\n                    message.cumSum = CoreML.Specification.CumSumLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1460:\n                    message.clampedReLU = CoreML.Specification.ClampedReLULayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1461:\n                    message.argSort = CoreML.Specification.ArgSortLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1465:\n                    message.pooling3d = CoreML.Specification.Pooling3DLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1466:\n                    message.globalPooling3d = CoreML.Specification.GlobalPooling3DLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1470:\n                    message.sliceBySize = CoreML.Specification.SliceBySizeLayerParams.decode(reader, reader.uint32());\n                    break;\n                case 1471:\n                    message.convolution3d = CoreML.Specification.Convolution3DLayerParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetworkLayer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                case \"inputTensor\":\n                    message.inputTensor.push(CoreML.Specification.Tensor.decodeText(reader));\n                    break;\n                case \"outputTensor\":\n                    message.outputTensor.push(CoreML.Specification.Tensor.decodeText(reader));\n                    break;\n                case \"isUpdatable\":\n                    message.isUpdatable = reader.bool();\n                    break;\n                case \"convolution\":\n                    message.convolution = CoreML.Specification.ConvolutionLayerParams.decodeText(reader);\n                    break;\n                case \"pooling\":\n                    message.pooling = CoreML.Specification.PoolingLayerParams.decodeText(reader);\n                    break;\n                case \"activation\":\n                    message.activation = CoreML.Specification.ActivationParams.decodeText(reader);\n                    break;\n                case \"innerProduct\":\n                    message.innerProduct = CoreML.Specification.InnerProductLayerParams.decodeText(reader);\n                    break;\n                case \"embedding\":\n                    message.embedding = CoreML.Specification.EmbeddingLayerParams.decodeText(reader);\n                    break;\n                case \"batchnorm\":\n                    message.batchnorm = CoreML.Specification.BatchnormLayerParams.decodeText(reader);\n                    break;\n                case \"mvn\":\n                    message.mvn = CoreML.Specification.MeanVarianceNormalizeLayerParams.decodeText(reader);\n                    break;\n                case \"l2normalize\":\n                    message.l2normalize = CoreML.Specification.L2NormalizeLayerParams.decodeText(reader);\n                    break;\n                case \"softmax\":\n                    message.softmax = CoreML.Specification.SoftmaxLayerParams.decodeText(reader);\n                    break;\n                case \"lrn\":\n                    message.lrn = CoreML.Specification.LRNLayerParams.decodeText(reader);\n                    break;\n                case \"crop\":\n                    message.crop = CoreML.Specification.CropLayerParams.decodeText(reader);\n                    break;\n                case \"padding\":\n                    message.padding = CoreML.Specification.PaddingLayerParams.decodeText(reader);\n                    break;\n                case \"upsample\":\n                    message.upsample = CoreML.Specification.UpsampleLayerParams.decodeText(reader);\n                    break;\n                case \"resizeBilinear\":\n                    message.resizeBilinear = CoreML.Specification.ResizeBilinearLayerParams.decodeText(reader);\n                    break;\n                case \"cropResize\":\n                    message.cropResize = CoreML.Specification.CropResizeLayerParams.decodeText(reader);\n                    break;\n                case \"unary\":\n                    message.unary = CoreML.Specification.UnaryFunctionLayerParams.decodeText(reader);\n                    break;\n                case \"add\":\n                    message.add = CoreML.Specification.AddLayerParams.decodeText(reader);\n                    break;\n                case \"multiply\":\n                    message.multiply = CoreML.Specification.MultiplyLayerParams.decodeText(reader);\n                    break;\n                case \"average\":\n                    message.average = CoreML.Specification.AverageLayerParams.decodeText(reader);\n                    break;\n                case \"scale\":\n                    message.scale = CoreML.Specification.ScaleLayerParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.BiasLayerParams.decodeText(reader);\n                    break;\n                case \"max\":\n                    message.max = CoreML.Specification.MaxLayerParams.decodeText(reader);\n                    break;\n                case \"min\":\n                    message.min = CoreML.Specification.MinLayerParams.decodeText(reader);\n                    break;\n                case \"dot\":\n                    message.dot = CoreML.Specification.DotProductLayerParams.decodeText(reader);\n                    break;\n                case \"reduce\":\n                    message.reduce = CoreML.Specification.ReduceLayerParams.decodeText(reader);\n                    break;\n                case \"loadConstant\":\n                    message.loadConstant = CoreML.Specification.LoadConstantLayerParams.decodeText(reader);\n                    break;\n                case \"reshape\":\n                    message.reshape = CoreML.Specification.ReshapeLayerParams.decodeText(reader);\n                    break;\n                case \"flatten\":\n                    message.flatten = CoreML.Specification.FlattenLayerParams.decodeText(reader);\n                    break;\n                case \"permute\":\n                    message.permute = CoreML.Specification.PermuteLayerParams.decodeText(reader);\n                    break;\n                case \"concat\":\n                    message.concat = CoreML.Specification.ConcatLayerParams.decodeText(reader);\n                    break;\n                case \"split\":\n                    message.split = CoreML.Specification.SplitLayerParams.decodeText(reader);\n                    break;\n                case \"sequenceRepeat\":\n                    message.sequenceRepeat = CoreML.Specification.SequenceRepeatLayerParams.decodeText(reader);\n                    break;\n                case \"reorganizeData\":\n                    message.reorganizeData = CoreML.Specification.ReorganizeDataLayerParams.decodeText(reader);\n                    break;\n                case \"slice\":\n                    message.slice = CoreML.Specification.SliceLayerParams.decodeText(reader);\n                    break;\n                case \"simpleRecurrent\":\n                    message.simpleRecurrent = CoreML.Specification.SimpleRecurrentLayerParams.decodeText(reader);\n                    break;\n                case \"gru\":\n                    message.gru = CoreML.Specification.GRULayerParams.decodeText(reader);\n                    break;\n                case \"uniDirectionalLSTM\":\n                    message.uniDirectionalLSTM = CoreML.Specification.UniDirectionalLSTMLayerParams.decodeText(reader);\n                    break;\n                case \"biDirectionalLSTM\":\n                    message.biDirectionalLSTM = CoreML.Specification.BiDirectionalLSTMLayerParams.decodeText(reader);\n                    break;\n                case \"custom\":\n                    message.custom = CoreML.Specification.CustomLayerParams.decodeText(reader);\n                    break;\n                case \"copy\":\n                    message.copy = CoreML.Specification.CopyLayerParams.decodeText(reader);\n                    break;\n                case \"branch\":\n                    message.branch = CoreML.Specification.BranchLayerParams.decodeText(reader);\n                    break;\n                case \"loop\":\n                    message.loop = CoreML.Specification.LoopLayerParams.decodeText(reader);\n                    break;\n                case \"loopBreak\":\n                    message.loopBreak = CoreML.Specification.LoopBreakLayerParams.decodeText(reader);\n                    break;\n                case \"loopContinue\":\n                    message.loopContinue = CoreML.Specification.LoopContinueLayerParams.decodeText(reader);\n                    break;\n                case \"rangeStatic\":\n                    message.rangeStatic = CoreML.Specification.RangeStaticLayerParams.decodeText(reader);\n                    break;\n                case \"rangeDynamic\":\n                    message.rangeDynamic = CoreML.Specification.RangeDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"clip\":\n                    message.clip = CoreML.Specification.ClipLayerParams.decodeText(reader);\n                    break;\n                case \"ceil\":\n                    message.ceil = CoreML.Specification.CeilLayerParams.decodeText(reader);\n                    break;\n                case \"floor\":\n                    message.floor = CoreML.Specification.FloorLayerParams.decodeText(reader);\n                    break;\n                case \"sign\":\n                    message.sign = CoreML.Specification.SignLayerParams.decodeText(reader);\n                    break;\n                case \"round\":\n                    message.round = CoreML.Specification.RoundLayerParams.decodeText(reader);\n                    break;\n                case \"exp2\":\n                    message.exp2 = CoreML.Specification.Exp2LayerParams.decodeText(reader);\n                    break;\n                case \"sin\":\n                    message.sin = CoreML.Specification.SinLayerParams.decodeText(reader);\n                    break;\n                case \"cos\":\n                    message.cos = CoreML.Specification.CosLayerParams.decodeText(reader);\n                    break;\n                case \"tan\":\n                    message.tan = CoreML.Specification.TanLayerParams.decodeText(reader);\n                    break;\n                case \"asin\":\n                    message.asin = CoreML.Specification.AsinLayerParams.decodeText(reader);\n                    break;\n                case \"acos\":\n                    message.acos = CoreML.Specification.AcosLayerParams.decodeText(reader);\n                    break;\n                case \"atan\":\n                    message.atan = CoreML.Specification.AtanLayerParams.decodeText(reader);\n                    break;\n                case \"sinh\":\n                    message.sinh = CoreML.Specification.SinhLayerParams.decodeText(reader);\n                    break;\n                case \"cosh\":\n                    message.cosh = CoreML.Specification.CoshLayerParams.decodeText(reader);\n                    break;\n                case \"tanh\":\n                    message.tanh = CoreML.Specification.TanhLayerParams.decodeText(reader);\n                    break;\n                case \"asinh\":\n                    message.asinh = CoreML.Specification.AsinhLayerParams.decodeText(reader);\n                    break;\n                case \"acosh\":\n                    message.acosh = CoreML.Specification.AcoshLayerParams.decodeText(reader);\n                    break;\n                case \"atanh\":\n                    message.atanh = CoreML.Specification.AtanhLayerParams.decodeText(reader);\n                    break;\n                case \"erf\":\n                    message.erf = CoreML.Specification.ErfLayerParams.decodeText(reader);\n                    break;\n                case \"gelu\":\n                    message.gelu = CoreML.Specification.GeluLayerParams.decodeText(reader);\n                    break;\n                case \"equal\":\n                    message.equal = CoreML.Specification.EqualLayerParams.decodeText(reader);\n                    break;\n                case \"notEqual\":\n                    message.notEqual = CoreML.Specification.NotEqualLayerParams.decodeText(reader);\n                    break;\n                case \"lessThan\":\n                    message.lessThan = CoreML.Specification.LessThanLayerParams.decodeText(reader);\n                    break;\n                case \"lessEqual\":\n                    message.lessEqual = CoreML.Specification.LessEqualLayerParams.decodeText(reader);\n                    break;\n                case \"greaterThan\":\n                    message.greaterThan = CoreML.Specification.GreaterThanLayerParams.decodeText(reader);\n                    break;\n                case \"greaterEqual\":\n                    message.greaterEqual = CoreML.Specification.GreaterEqualLayerParams.decodeText(reader);\n                    break;\n                case \"logicalOr\":\n                    message.logicalOr = CoreML.Specification.LogicalOrLayerParams.decodeText(reader);\n                    break;\n                case \"logicalXor\":\n                    message.logicalXor = CoreML.Specification.LogicalXorLayerParams.decodeText(reader);\n                    break;\n                case \"logicalNot\":\n                    message.logicalNot = CoreML.Specification.LogicalNotLayerParams.decodeText(reader);\n                    break;\n                case \"logicalAnd\":\n                    message.logicalAnd = CoreML.Specification.LogicalAndLayerParams.decodeText(reader);\n                    break;\n                case \"modBroadcastable\":\n                    message.modBroadcastable = CoreML.Specification.ModBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"minBroadcastable\":\n                    message.minBroadcastable = CoreML.Specification.MinBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"maxBroadcastable\":\n                    message.maxBroadcastable = CoreML.Specification.MaxBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"addBroadcastable\":\n                    message.addBroadcastable = CoreML.Specification.AddBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"powBroadcastable\":\n                    message.powBroadcastable = CoreML.Specification.PowBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"divideBroadcastable\":\n                    message.divideBroadcastable = CoreML.Specification.DivideBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"floorDivBroadcastable\":\n                    message.floorDivBroadcastable = CoreML.Specification.FloorDivBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"multiplyBroadcastable\":\n                    message.multiplyBroadcastable = CoreML.Specification.MultiplyBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"subtractBroadcastable\":\n                    message.subtractBroadcastable = CoreML.Specification.SubtractBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"tile\":\n                    message.tile = CoreML.Specification.TileLayerParams.decodeText(reader);\n                    break;\n                case \"stack\":\n                    message.stack = CoreML.Specification.StackLayerParams.decodeText(reader);\n                    break;\n                case \"gather\":\n                    message.gather = CoreML.Specification.GatherLayerParams.decodeText(reader);\n                    break;\n                case \"scatter\":\n                    message.scatter = CoreML.Specification.ScatterLayerParams.decodeText(reader);\n                    break;\n                case \"gatherND\":\n                    message.gatherND = CoreML.Specification.GatherNDLayerParams.decodeText(reader);\n                    break;\n                case \"scatterND\":\n                    message.scatterND = CoreML.Specification.ScatterNDLayerParams.decodeText(reader);\n                    break;\n                case \"softmaxND\":\n                    message.softmaxND = CoreML.Specification.SoftmaxNDLayerParams.decodeText(reader);\n                    break;\n                case \"gatherAlongAxis\":\n                    message.gatherAlongAxis = CoreML.Specification.GatherAlongAxisLayerParams.decodeText(reader);\n                    break;\n                case \"scatterAlongAxis\":\n                    message.scatterAlongAxis = CoreML.Specification.ScatterAlongAxisLayerParams.decodeText(reader);\n                    break;\n                case \"reverse\":\n                    message.reverse = CoreML.Specification.ReverseLayerParams.decodeText(reader);\n                    break;\n                case \"reverseSeq\":\n                    message.reverseSeq = CoreML.Specification.ReverseSeqLayerParams.decodeText(reader);\n                    break;\n                case \"splitND\":\n                    message.splitND = CoreML.Specification.SplitNDLayerParams.decodeText(reader);\n                    break;\n                case \"concatND\":\n                    message.concatND = CoreML.Specification.ConcatNDLayerParams.decodeText(reader);\n                    break;\n                case \"transpose\":\n                    message.transpose = CoreML.Specification.TransposeLayerParams.decodeText(reader);\n                    break;\n                case \"sliceStatic\":\n                    message.sliceStatic = CoreML.Specification.SliceStaticLayerParams.decodeText(reader);\n                    break;\n                case \"sliceDynamic\":\n                    message.sliceDynamic = CoreML.Specification.SliceDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"slidingWindows\":\n                    message.slidingWindows = CoreML.Specification.SlidingWindowsLayerParams.decodeText(reader);\n                    break;\n                case \"topK\":\n                    message.topK = CoreML.Specification.TopKLayerParams.decodeText(reader);\n                    break;\n                case \"argMin\":\n                    message.argMin = CoreML.Specification.ArgMinLayerParams.decodeText(reader);\n                    break;\n                case \"argMax\":\n                    message.argMax = CoreML.Specification.ArgMaxLayerParams.decodeText(reader);\n                    break;\n                case \"embeddingND\":\n                    message.embeddingND = CoreML.Specification.EmbeddingNDLayerParams.decodeText(reader);\n                    break;\n                case \"batchedMatmul\":\n                    message.batchedMatmul = CoreML.Specification.BatchedMatMulLayerParams.decodeText(reader);\n                    break;\n                case \"getShape\":\n                    message.getShape = CoreML.Specification.GetShapeLayerParams.decodeText(reader);\n                    break;\n                case \"loadConstantND\":\n                    message.loadConstantND = CoreML.Specification.LoadConstantNDLayerParams.decodeText(reader);\n                    break;\n                case \"fillLike\":\n                    message.fillLike = CoreML.Specification.FillLikeLayerParams.decodeText(reader);\n                    break;\n                case \"fillStatic\":\n                    message.fillStatic = CoreML.Specification.FillStaticLayerParams.decodeText(reader);\n                    break;\n                case \"fillDynamic\":\n                    message.fillDynamic = CoreML.Specification.FillDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"broadcastToLike\":\n                    message.broadcastToLike = CoreML.Specification.BroadcastToLikeLayerParams.decodeText(reader);\n                    break;\n                case \"broadcastToStatic\":\n                    message.broadcastToStatic = CoreML.Specification.BroadcastToStaticLayerParams.decodeText(reader);\n                    break;\n                case \"broadcastToDynamic\":\n                    message.broadcastToDynamic = CoreML.Specification.BroadcastToDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"squeeze\":\n                    message.squeeze = CoreML.Specification.SqueezeLayerParams.decodeText(reader);\n                    break;\n                case \"expandDims\":\n                    message.expandDims = CoreML.Specification.ExpandDimsLayerParams.decodeText(reader);\n                    break;\n                case \"flattenTo2D\":\n                    message.flattenTo2D = CoreML.Specification.FlattenTo2DLayerParams.decodeText(reader);\n                    break;\n                case \"reshapeLike\":\n                    message.reshapeLike = CoreML.Specification.ReshapeLikeLayerParams.decodeText(reader);\n                    break;\n                case \"reshapeStatic\":\n                    message.reshapeStatic = CoreML.Specification.ReshapeStaticLayerParams.decodeText(reader);\n                    break;\n                case \"reshapeDynamic\":\n                    message.reshapeDynamic = CoreML.Specification.ReshapeDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"rankPreservingReshape\":\n                    message.rankPreservingReshape = CoreML.Specification.RankPreservingReshapeLayerParams.decodeText(reader);\n                    break;\n                case \"constantPad\":\n                    message.constantPad = CoreML.Specification.ConstantPaddingLayerParams.decodeText(reader);\n                    break;\n                case \"randomNormalLike\":\n                    message.randomNormalLike = CoreML.Specification.RandomNormalLikeLayerParams.decodeText(reader);\n                    break;\n                case \"randomNormalStatic\":\n                    message.randomNormalStatic = CoreML.Specification.RandomNormalStaticLayerParams.decodeText(reader);\n                    break;\n                case \"randomNormalDynamic\":\n                    message.randomNormalDynamic = CoreML.Specification.RandomNormalDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"randomUniformLike\":\n                    message.randomUniformLike = CoreML.Specification.RandomUniformLikeLayerParams.decodeText(reader);\n                    break;\n                case \"randomUniformStatic\":\n                    message.randomUniformStatic = CoreML.Specification.RandomUniformStaticLayerParams.decodeText(reader);\n                    break;\n                case \"randomUniformDynamic\":\n                    message.randomUniformDynamic = CoreML.Specification.RandomUniformDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"randomBernoulliLike\":\n                    message.randomBernoulliLike = CoreML.Specification.RandomBernoulliLikeLayerParams.decodeText(reader);\n                    break;\n                case \"randomBernoulliStatic\":\n                    message.randomBernoulliStatic = CoreML.Specification.RandomBernoulliStaticLayerParams.decodeText(reader);\n                    break;\n                case \"randomBernoulliDynamic\":\n                    message.randomBernoulliDynamic = CoreML.Specification.RandomBernoulliDynamicLayerParams.decodeText(reader);\n                    break;\n                case \"categoricalDistribution\":\n                    message.categoricalDistribution = CoreML.Specification.CategoricalDistributionLayerParams.decodeText(reader);\n                    break;\n                case \"reduceL1\":\n                    message.reduceL1 = CoreML.Specification.ReduceL1LayerParams.decodeText(reader);\n                    break;\n                case \"reduceL2\":\n                    message.reduceL2 = CoreML.Specification.ReduceL2LayerParams.decodeText(reader);\n                    break;\n                case \"reduceMax\":\n                    message.reduceMax = CoreML.Specification.ReduceMaxLayerParams.decodeText(reader);\n                    break;\n                case \"reduceMin\":\n                    message.reduceMin = CoreML.Specification.ReduceMinLayerParams.decodeText(reader);\n                    break;\n                case \"reduceSum\":\n                    message.reduceSum = CoreML.Specification.ReduceSumLayerParams.decodeText(reader);\n                    break;\n                case \"reduceProd\":\n                    message.reduceProd = CoreML.Specification.ReduceProdLayerParams.decodeText(reader);\n                    break;\n                case \"reduceMean\":\n                    message.reduceMean = CoreML.Specification.ReduceMeanLayerParams.decodeText(reader);\n                    break;\n                case \"reduceLogSum\":\n                    message.reduceLogSum = CoreML.Specification.ReduceLogSumLayerParams.decodeText(reader);\n                    break;\n                case \"reduceSumSquare\":\n                    message.reduceSumSquare = CoreML.Specification.ReduceSumSquareLayerParams.decodeText(reader);\n                    break;\n                case \"reduceLogSumExp\":\n                    message.reduceLogSumExp = CoreML.Specification.ReduceLogSumExpLayerParams.decodeText(reader);\n                    break;\n                case \"whereNonZero\":\n                    message.whereNonZero = CoreML.Specification.WhereNonZeroLayerParams.decodeText(reader);\n                    break;\n                case \"matrixBandPart\":\n                    message.matrixBandPart = CoreML.Specification.MatrixBandPartLayerParams.decodeText(reader);\n                    break;\n                case \"lowerTriangular\":\n                    message.lowerTriangular = CoreML.Specification.LowerTriangularLayerParams.decodeText(reader);\n                    break;\n                case \"upperTriangular\":\n                    message.upperTriangular = CoreML.Specification.UpperTriangularLayerParams.decodeText(reader);\n                    break;\n                case \"whereBroadcastable\":\n                    message.whereBroadcastable = CoreML.Specification.WhereBroadcastableLayerParams.decodeText(reader);\n                    break;\n                case \"layerNormalization\":\n                    message.layerNormalization = CoreML.Specification.LayerNormalizationLayerParams.decodeText(reader);\n                    break;\n                case \"NonMaximumSuppression\":\n                    message.NonMaximumSuppression = CoreML.Specification.NonMaximumSuppressionLayerParams.decodeText(reader);\n                    break;\n                case \"oneHot\":\n                    message.oneHot = CoreML.Specification.OneHotLayerParams.decodeText(reader);\n                    break;\n                case \"cumSum\":\n                    message.cumSum = CoreML.Specification.CumSumLayerParams.decodeText(reader);\n                    break;\n                case \"clampedReLU\":\n                    message.clampedReLU = CoreML.Specification.ClampedReLULayerParams.decodeText(reader);\n                    break;\n                case \"argSort\":\n                    message.argSort = CoreML.Specification.ArgSortLayerParams.decodeText(reader);\n                    break;\n                case \"pooling3d\":\n                    message.pooling3d = CoreML.Specification.Pooling3DLayerParams.decodeText(reader);\n                    break;\n                case \"globalPooling3d\":\n                    message.globalPooling3d = CoreML.Specification.GlobalPooling3DLayerParams.decodeText(reader);\n                    break;\n                case \"sliceBySize\":\n                    message.sliceBySize = CoreML.Specification.SliceBySizeLayerParams.decodeText(reader);\n                    break;\n                case \"convolution3d\":\n                    message.convolution3d = CoreML.Specification.Convolution3DLayerParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetworkLayer.prototype.name = \"\";\nCoreML.Specification.NeuralNetworkLayer.prototype.isUpdatable = false;\n\nCoreML.Specification.BranchLayerParams = class BranchLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BranchLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.ifBranch = CoreML.Specification.NeuralNetwork.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.elseBranch = CoreML.Specification.NeuralNetwork.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BranchLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"ifBranch\":\n                    message.ifBranch = CoreML.Specification.NeuralNetwork.decodeText(reader);\n                    break;\n                case \"elseBranch\":\n                    message.elseBranch = CoreML.Specification.NeuralNetwork.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BranchLayerParams.prototype.ifBranch = null;\nCoreML.Specification.BranchLayerParams.prototype.elseBranch = null;\n\nCoreML.Specification.LoopLayerParams = class LoopLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LoopLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.maxLoopIterations = reader.uint64();\n                    break;\n                case 2:\n                    message.conditionVar = reader.string();\n                    break;\n                case 3:\n                    message.conditionNetwork = CoreML.Specification.NeuralNetwork.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.bodyNetwork = CoreML.Specification.NeuralNetwork.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LoopLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"maxLoopIterations\":\n                    message.maxLoopIterations = reader.uint64();\n                    break;\n                case \"conditionVar\":\n                    message.conditionVar = reader.string();\n                    break;\n                case \"conditionNetwork\":\n                    message.conditionNetwork = CoreML.Specification.NeuralNetwork.decodeText(reader);\n                    break;\n                case \"bodyNetwork\":\n                    message.bodyNetwork = CoreML.Specification.NeuralNetwork.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LoopLayerParams.prototype.maxLoopIterations = 0n;\nCoreML.Specification.LoopLayerParams.prototype.conditionVar = \"\";\nCoreML.Specification.LoopLayerParams.prototype.conditionNetwork = null;\nCoreML.Specification.LoopLayerParams.prototype.bodyNetwork = null;\n\nCoreML.Specification.LoopBreakLayerParams = class LoopBreakLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LoopBreakLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LoopBreakLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LoopContinueLayerParams = class LoopContinueLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LoopContinueLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LoopContinueLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CopyLayerParams = class CopyLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CopyLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CopyLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GreaterThanLayerParams = class GreaterThanLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GreaterThanLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GreaterThanLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GreaterThanLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.GreaterEqualLayerParams = class GreaterEqualLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GreaterEqualLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GreaterEqualLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GreaterEqualLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.LessThanLayerParams = class LessThanLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LessThanLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LessThanLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LessThanLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.LessEqualLayerParams = class LessEqualLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LessEqualLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LessEqualLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LessEqualLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.EqualLayerParams = class EqualLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.EqualLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.EqualLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.EqualLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.NotEqualLayerParams = class NotEqualLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NotEqualLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NotEqualLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NotEqualLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.LogicalAndLayerParams = class LogicalAndLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LogicalAndLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LogicalAndLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LogicalOrLayerParams = class LogicalOrLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LogicalOrLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LogicalOrLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LogicalXorLayerParams = class LogicalXorLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LogicalXorLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LogicalXorLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LogicalNotLayerParams = class LogicalNotLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LogicalNotLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LogicalNotLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BorderAmounts = class BorderAmounts {\n\n    constructor() {\n        this.borderAmounts = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BorderAmounts();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.borderAmounts.push(CoreML.Specification.BorderAmounts.EdgeSizes.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BorderAmounts();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"borderAmounts\":\n                    message.borderAmounts.push(CoreML.Specification.BorderAmounts.EdgeSizes.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BorderAmounts.EdgeSizes = class EdgeSizes {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BorderAmounts.EdgeSizes();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.startEdgeSize = reader.uint64();\n                    break;\n                case 2:\n                    message.endEdgeSize = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BorderAmounts.EdgeSizes();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"startEdgeSize\":\n                    message.startEdgeSize = reader.uint64();\n                    break;\n                case \"endEdgeSize\":\n                    message.endEdgeSize = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BorderAmounts.EdgeSizes.prototype.startEdgeSize = 0n;\nCoreML.Specification.BorderAmounts.EdgeSizes.prototype.endEdgeSize = 0n;\n\nCoreML.Specification.ValidPadding = class ValidPadding {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ValidPadding();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.paddingAmounts = CoreML.Specification.BorderAmounts.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ValidPadding();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"paddingAmounts\":\n                    message.paddingAmounts = CoreML.Specification.BorderAmounts.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ValidPadding.prototype.paddingAmounts = null;\n\nCoreML.Specification.SamePadding = class SamePadding {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SamePadding();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.asymmetryMode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SamePadding();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"asymmetryMode\":\n                    message.asymmetryMode = reader.enum(CoreML.Specification.SamePadding.SamePaddingMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SamePadding.prototype.asymmetryMode = 0;\n\nCoreML.Specification.SamePadding.SamePaddingMode = {\n    \"BOTTOM_RIGHT_HEAVY\": 0,\n    \"TOP_LEFT_HEAVY\": 1\n};\n\nCoreML.Specification.SamplingMode = class SamplingMode {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SamplingMode();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.samplingMethod = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SamplingMode();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"samplingMethod\":\n                    message.samplingMethod = reader.enum(CoreML.Specification.SamplingMode.Method);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SamplingMode.prototype.samplingMethod = 0;\n\nCoreML.Specification.SamplingMode.Method = {\n    \"STRICT_ALIGN_ENDPOINTS_MODE\": 0,\n    \"ALIGN_ENDPOINTS_MODE\": 1,\n    \"UPSAMPLE_MODE\": 2,\n    \"ROI_ALIGN_MODE\": 3\n};\n\nCoreML.Specification.BoxCoordinatesMode = class BoxCoordinatesMode {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BoxCoordinatesMode();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.boxMode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BoxCoordinatesMode();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"boxMode\":\n                    message.boxMode = reader.enum(CoreML.Specification.BoxCoordinatesMode.Coordinates);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BoxCoordinatesMode.prototype.boxMode = 0;\n\nCoreML.Specification.BoxCoordinatesMode.Coordinates = {\n    \"CORNERS_HEIGHT_FIRST\": 0,\n    \"CORNERS_WIDTH_FIRST\": 1,\n    \"CENTER_SIZE_HEIGHT_FIRST\": 2,\n    \"CENTER_SIZE_WIDTH_FIRST\": 3\n};\n\nCoreML.Specification.WeightParams = class WeightParams {\n\n    constructor() {\n        this.floatValue = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.WeightParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.floatValue = reader.floats(message.floatValue, tag);\n                    break;\n                case 2:\n                    message.float16Value = reader.bytes();\n                    break;\n                case 30:\n                    message.rawValue = reader.bytes();\n                    break;\n                case 31:\n                    message.int8RawValue = reader.bytes();\n                    break;\n                case 40:\n                    message.quantization = CoreML.Specification.QuantizationParams.decode(reader, reader.uint32());\n                    break;\n                case 50:\n                    message.isUpdatable = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.WeightParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"floatValue\":\n                    reader.array(message.floatValue, () => reader.float());\n                    break;\n                case \"float16Value\":\n                    message.float16Value = reader.bytes();\n                    break;\n                case \"rawValue\":\n                    message.rawValue = reader.bytes();\n                    break;\n                case \"int8RawValue\":\n                    message.int8RawValue = reader.bytes();\n                    break;\n                case \"quantization\":\n                    message.quantization = CoreML.Specification.QuantizationParams.decodeText(reader);\n                    break;\n                case \"isUpdatable\":\n                    message.isUpdatable = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.WeightParams.prototype.float16Value = new Uint8Array([]);\nCoreML.Specification.WeightParams.prototype.rawValue = new Uint8Array([]);\nCoreML.Specification.WeightParams.prototype.int8RawValue = new Uint8Array([]);\nCoreML.Specification.WeightParams.prototype.quantization = null;\nCoreML.Specification.WeightParams.prototype.isUpdatable = false;\n\nCoreML.Specification.QuantizationParams = class QuantizationParams {\n\n    get QuantizationType() {\n        CoreML.Specification.QuantizationParams.QuantizationTypeSet = CoreML.Specification.QuantizationParams.QuantizationTypeSet || new Set([\"linearQuantization\", \"lookupTableQuantization\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.QuantizationParams.QuantizationTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.QuantizationParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.numberOfBits = reader.uint64();\n                    break;\n                case 101:\n                    message.linearQuantization = CoreML.Specification.LinearQuantizationParams.decode(reader, reader.uint32());\n                    break;\n                case 102:\n                    message.lookupTableQuantization = CoreML.Specification.LookUpTableQuantizationParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.QuantizationParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"numberOfBits\":\n                    message.numberOfBits = reader.uint64();\n                    break;\n                case \"linearQuantization\":\n                    message.linearQuantization = CoreML.Specification.LinearQuantizationParams.decodeText(reader);\n                    break;\n                case \"lookupTableQuantization\":\n                    message.lookupTableQuantization = CoreML.Specification.LookUpTableQuantizationParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.QuantizationParams.prototype.numberOfBits = 0n;\n\nCoreML.Specification.LinearQuantizationParams = class LinearQuantizationParams {\n\n    constructor() {\n        this.scale = [];\n        this.bias = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LinearQuantizationParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.scale = reader.floats(message.scale, tag);\n                    break;\n                case 2:\n                    message.bias = reader.floats(message.bias, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LinearQuantizationParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"scale\":\n                    reader.array(message.scale, () => reader.float());\n                    break;\n                case \"bias\":\n                    reader.array(message.bias, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LookUpTableQuantizationParams = class LookUpTableQuantizationParams {\n\n    constructor() {\n        this.floatValue = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LookUpTableQuantizationParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.floatValue = reader.floats(message.floatValue, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LookUpTableQuantizationParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"floatValue\":\n                    reader.array(message.floatValue, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConvolutionLayerParams = class ConvolutionLayerParams {\n\n    constructor() {\n        this.kernelSize = [];\n        this.stride = [];\n        this.dilationFactor = [];\n        this.outputShape = [];\n    }\n\n    get ConvolutionPaddingType() {\n        CoreML.Specification.ConvolutionLayerParams.ConvolutionPaddingTypeSet = CoreML.Specification.ConvolutionLayerParams.ConvolutionPaddingTypeSet || new Set([\"valid\", \"same\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.ConvolutionLayerParams.ConvolutionPaddingTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ConvolutionLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.outputChannels = reader.uint64();\n                    break;\n                case 2:\n                    message.kernelChannels = reader.uint64();\n                    break;\n                case 10:\n                    message.nGroups = reader.uint64();\n                    break;\n                case 20:\n                    message.kernelSize = reader.array(message.kernelSize, () => reader.uint64(), tag);\n                    break;\n                case 30:\n                    message.stride = reader.array(message.stride, () => reader.uint64(), tag);\n                    break;\n                case 40:\n                    message.dilationFactor = reader.array(message.dilationFactor, () => reader.uint64(), tag);\n                    break;\n                case 50:\n                    message.valid = CoreML.Specification.ValidPadding.decode(reader, reader.uint32());\n                    break;\n                case 51:\n                    message.same = CoreML.Specification.SamePadding.decode(reader, reader.uint32());\n                    break;\n                case 60:\n                    message.isDeconvolution = reader.bool();\n                    break;\n                case 70:\n                    message.hasBias = reader.bool();\n                    break;\n                case 90:\n                    message.weights = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 91:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.outputShape = reader.array(message.outputShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ConvolutionLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"outputChannels\":\n                    message.outputChannels = reader.uint64();\n                    break;\n                case \"kernelChannels\":\n                    message.kernelChannels = reader.uint64();\n                    break;\n                case \"nGroups\":\n                    message.nGroups = reader.uint64();\n                    break;\n                case \"kernelSize\":\n                    reader.array(message.kernelSize, () => reader.uint64());\n                    break;\n                case \"stride\":\n                    reader.array(message.stride, () => reader.uint64());\n                    break;\n                case \"dilationFactor\":\n                    reader.array(message.dilationFactor, () => reader.uint64());\n                    break;\n                case \"valid\":\n                    message.valid = CoreML.Specification.ValidPadding.decodeText(reader);\n                    break;\n                case \"same\":\n                    message.same = CoreML.Specification.SamePadding.decodeText(reader);\n                    break;\n                case \"isDeconvolution\":\n                    message.isDeconvolution = reader.bool();\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"weights\":\n                    message.weights = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputShape\":\n                    reader.array(message.outputShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConvolutionLayerParams.prototype.outputChannels = 0n;\nCoreML.Specification.ConvolutionLayerParams.prototype.kernelChannels = 0n;\nCoreML.Specification.ConvolutionLayerParams.prototype.nGroups = 0n;\nCoreML.Specification.ConvolutionLayerParams.prototype.isDeconvolution = false;\nCoreML.Specification.ConvolutionLayerParams.prototype.hasBias = false;\nCoreML.Specification.ConvolutionLayerParams.prototype.weights = null;\nCoreML.Specification.ConvolutionLayerParams.prototype.bias = null;\n\nCoreML.Specification.Convolution3DLayerParams = class Convolution3DLayerParams {\n\n    constructor() {\n        this.outputShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Convolution3DLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.outputChannels = reader.int32();\n                    break;\n                case 2:\n                    message.inputChannels = reader.int32();\n                    break;\n                case 10:\n                    message.nGroups = reader.int32();\n                    break;\n                case 20:\n                    message.kernelDepth = reader.int32();\n                    break;\n                case 21:\n                    message.kernelHeight = reader.int32();\n                    break;\n                case 22:\n                    message.kernelWidth = reader.int32();\n                    break;\n                case 31:\n                    message.strideDepth = reader.int32();\n                    break;\n                case 32:\n                    message.strideHeight = reader.int32();\n                    break;\n                case 33:\n                    message.strideWidth = reader.int32();\n                    break;\n                case 40:\n                    message.dilationDepth = reader.int32();\n                    break;\n                case 41:\n                    message.dilationHeight = reader.int32();\n                    break;\n                case 42:\n                    message.dilationWidth = reader.int32();\n                    break;\n                case 50:\n                    message.hasBias = reader.bool();\n                    break;\n                case 60:\n                    message.weights = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 61:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 70:\n                    message.paddingType = reader.int32();\n                    break;\n                case 80:\n                    message.customPaddingFront = reader.int32();\n                    break;\n                case 81:\n                    message.customPaddingBack = reader.int32();\n                    break;\n                case 82:\n                    message.customPaddingTop = reader.int32();\n                    break;\n                case 83:\n                    message.customPaddingBottom = reader.int32();\n                    break;\n                case 84:\n                    message.customPaddingLeft = reader.int32();\n                    break;\n                case 85:\n                    message.customPaddingRight = reader.int32();\n                    break;\n                case 86:\n                    message.isDeconvolution = reader.bool();\n                    break;\n                case 87:\n                    message.outputShape = reader.array(message.outputShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Convolution3DLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"outputChannels\":\n                    message.outputChannels = reader.int32();\n                    break;\n                case \"inputChannels\":\n                    message.inputChannels = reader.int32();\n                    break;\n                case \"nGroups\":\n                    message.nGroups = reader.int32();\n                    break;\n                case \"kernelDepth\":\n                    message.kernelDepth = reader.int32();\n                    break;\n                case \"kernelHeight\":\n                    message.kernelHeight = reader.int32();\n                    break;\n                case \"kernelWidth\":\n                    message.kernelWidth = reader.int32();\n                    break;\n                case \"strideDepth\":\n                    message.strideDepth = reader.int32();\n                    break;\n                case \"strideHeight\":\n                    message.strideHeight = reader.int32();\n                    break;\n                case \"strideWidth\":\n                    message.strideWidth = reader.int32();\n                    break;\n                case \"dilationDepth\":\n                    message.dilationDepth = reader.int32();\n                    break;\n                case \"dilationHeight\":\n                    message.dilationHeight = reader.int32();\n                    break;\n                case \"dilationWidth\":\n                    message.dilationWidth = reader.int32();\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"weights\":\n                    message.weights = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"paddingType\":\n                    message.paddingType = reader.enum(CoreML.Specification.Convolution3DLayerParams.PaddingType);\n                    break;\n                case \"customPaddingFront\":\n                    message.customPaddingFront = reader.int32();\n                    break;\n                case \"customPaddingBack\":\n                    message.customPaddingBack = reader.int32();\n                    break;\n                case \"customPaddingTop\":\n                    message.customPaddingTop = reader.int32();\n                    break;\n                case \"customPaddingBottom\":\n                    message.customPaddingBottom = reader.int32();\n                    break;\n                case \"customPaddingLeft\":\n                    message.customPaddingLeft = reader.int32();\n                    break;\n                case \"customPaddingRight\":\n                    message.customPaddingRight = reader.int32();\n                    break;\n                case \"isDeconvolution\":\n                    message.isDeconvolution = reader.bool();\n                    break;\n                case \"outputShape\":\n                    reader.array(message.outputShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Convolution3DLayerParams.prototype.outputChannels = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.inputChannels = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.nGroups = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.kernelDepth = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.kernelHeight = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.kernelWidth = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.strideDepth = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.strideHeight = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.strideWidth = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.dilationDepth = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.dilationHeight = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.dilationWidth = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.hasBias = false;\nCoreML.Specification.Convolution3DLayerParams.prototype.weights = null;\nCoreML.Specification.Convolution3DLayerParams.prototype.bias = null;\nCoreML.Specification.Convolution3DLayerParams.prototype.paddingType = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.customPaddingFront = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.customPaddingBack = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.customPaddingTop = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.customPaddingBottom = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.customPaddingLeft = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.customPaddingRight = 0;\nCoreML.Specification.Convolution3DLayerParams.prototype.isDeconvolution = false;\n\nCoreML.Specification.Convolution3DLayerParams.PaddingType = {\n    \"CUSTOM\": 0,\n    \"VALID\": 1,\n    \"SAME\": 2\n};\n\nCoreML.Specification.InnerProductLayerParams = class InnerProductLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.InnerProductLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputChannels = reader.uint64();\n                    break;\n                case 2:\n                    message.outputChannels = reader.uint64();\n                    break;\n                case 10:\n                    message.hasBias = reader.bool();\n                    break;\n                case 20:\n                    message.weights = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 21:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 22:\n                    message.int8DynamicQuantize = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.InnerProductLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputChannels\":\n                    message.inputChannels = reader.uint64();\n                    break;\n                case \"outputChannels\":\n                    message.outputChannels = reader.uint64();\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"weights\":\n                    message.weights = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"int8DynamicQuantize\":\n                    message.int8DynamicQuantize = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.InnerProductLayerParams.prototype.inputChannels = 0n;\nCoreML.Specification.InnerProductLayerParams.prototype.outputChannels = 0n;\nCoreML.Specification.InnerProductLayerParams.prototype.hasBias = false;\nCoreML.Specification.InnerProductLayerParams.prototype.weights = null;\nCoreML.Specification.InnerProductLayerParams.prototype.bias = null;\nCoreML.Specification.InnerProductLayerParams.prototype.int8DynamicQuantize = false;\n\nCoreML.Specification.EmbeddingLayerParams = class EmbeddingLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.EmbeddingLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputDim = reader.uint64();\n                    break;\n                case 2:\n                    message.outputChannels = reader.uint64();\n                    break;\n                case 10:\n                    message.hasBias = reader.bool();\n                    break;\n                case 20:\n                    message.weights = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 21:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.EmbeddingLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputDim\":\n                    message.inputDim = reader.uint64();\n                    break;\n                case \"outputChannels\":\n                    message.outputChannels = reader.uint64();\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"weights\":\n                    message.weights = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.EmbeddingLayerParams.prototype.inputDim = 0n;\nCoreML.Specification.EmbeddingLayerParams.prototype.outputChannels = 0n;\nCoreML.Specification.EmbeddingLayerParams.prototype.hasBias = false;\nCoreML.Specification.EmbeddingLayerParams.prototype.weights = null;\nCoreML.Specification.EmbeddingLayerParams.prototype.bias = null;\n\nCoreML.Specification.EmbeddingNDLayerParams = class EmbeddingNDLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.EmbeddingNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vocabSize = reader.uint64();\n                    break;\n                case 2:\n                    message.embeddingSize = reader.uint64();\n                    break;\n                case 3:\n                    message.hasBias = reader.bool();\n                    break;\n                case 20:\n                    message.weights = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 21:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.EmbeddingNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vocabSize\":\n                    message.vocabSize = reader.uint64();\n                    break;\n                case \"embeddingSize\":\n                    message.embeddingSize = reader.uint64();\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"weights\":\n                    message.weights = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.EmbeddingNDLayerParams.prototype.vocabSize = 0n;\nCoreML.Specification.EmbeddingNDLayerParams.prototype.embeddingSize = 0n;\nCoreML.Specification.EmbeddingNDLayerParams.prototype.hasBias = false;\nCoreML.Specification.EmbeddingNDLayerParams.prototype.weights = null;\nCoreML.Specification.EmbeddingNDLayerParams.prototype.bias = null;\n\nCoreML.Specification.BatchnormLayerParams = class BatchnormLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BatchnormLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.channels = reader.uint64();\n                    break;\n                case 5:\n                    message.computeMeanVar = reader.bool();\n                    break;\n                case 6:\n                    message.instanceNormalization = reader.bool();\n                    break;\n                case 10:\n                    message.epsilon = reader.float();\n                    break;\n                case 15:\n                    message.gamma = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 16:\n                    message.beta = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 17:\n                    message.mean = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 18:\n                    message.variance = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BatchnormLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"channels\":\n                    message.channels = reader.uint64();\n                    break;\n                case \"computeMeanVar\":\n                    message.computeMeanVar = reader.bool();\n                    break;\n                case \"instanceNormalization\":\n                    message.instanceNormalization = reader.bool();\n                    break;\n                case \"epsilon\":\n                    message.epsilon = reader.float();\n                    break;\n                case \"gamma\":\n                    message.gamma = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"beta\":\n                    message.beta = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"mean\":\n                    message.mean = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"variance\":\n                    message.variance = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BatchnormLayerParams.prototype.channels = 0n;\nCoreML.Specification.BatchnormLayerParams.prototype.computeMeanVar = false;\nCoreML.Specification.BatchnormLayerParams.prototype.instanceNormalization = false;\nCoreML.Specification.BatchnormLayerParams.prototype.epsilon = 0;\nCoreML.Specification.BatchnormLayerParams.prototype.gamma = null;\nCoreML.Specification.BatchnormLayerParams.prototype.beta = null;\nCoreML.Specification.BatchnormLayerParams.prototype.mean = null;\nCoreML.Specification.BatchnormLayerParams.prototype.variance = null;\n\nCoreML.Specification.PoolingLayerParams = class PoolingLayerParams {\n\n    constructor() {\n        this.kernelSize = [];\n        this.stride = [];\n    }\n\n    get PoolingPaddingType() {\n        CoreML.Specification.PoolingLayerParams.PoolingPaddingTypeSet = CoreML.Specification.PoolingLayerParams.PoolingPaddingTypeSet || new Set([\"valid\", \"same\", \"includeLastPixel\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.PoolingLayerParams.PoolingPaddingTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PoolingLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = reader.int32();\n                    break;\n                case 10:\n                    message.kernelSize = reader.array(message.kernelSize, () => reader.uint64(), tag);\n                    break;\n                case 20:\n                    message.stride = reader.array(message.stride, () => reader.uint64(), tag);\n                    break;\n                case 30:\n                    message.valid = CoreML.Specification.ValidPadding.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.same = CoreML.Specification.SamePadding.decode(reader, reader.uint32());\n                    break;\n                case 32:\n                    message.includeLastPixel = CoreML.Specification.PoolingLayerParams.ValidCompletePadding.decode(reader, reader.uint32());\n                    break;\n                case 50:\n                    message.avgPoolExcludePadding = reader.bool();\n                    break;\n                case 60:\n                    message.globalPooling = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PoolingLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.enum(CoreML.Specification.PoolingLayerParams.PoolingType);\n                    break;\n                case \"kernelSize\":\n                    reader.array(message.kernelSize, () => reader.uint64());\n                    break;\n                case \"stride\":\n                    reader.array(message.stride, () => reader.uint64());\n                    break;\n                case \"valid\":\n                    message.valid = CoreML.Specification.ValidPadding.decodeText(reader);\n                    break;\n                case \"same\":\n                    message.same = CoreML.Specification.SamePadding.decodeText(reader);\n                    break;\n                case \"includeLastPixel\":\n                    message.includeLastPixel = CoreML.Specification.PoolingLayerParams.ValidCompletePadding.decodeText(reader);\n                    break;\n                case \"avgPoolExcludePadding\":\n                    message.avgPoolExcludePadding = reader.bool();\n                    break;\n                case \"globalPooling\":\n                    message.globalPooling = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PoolingLayerParams.prototype.type = 0;\nCoreML.Specification.PoolingLayerParams.prototype.avgPoolExcludePadding = false;\nCoreML.Specification.PoolingLayerParams.prototype.globalPooling = false;\n\nCoreML.Specification.PoolingLayerParams.PoolingType = {\n    \"MAX\": 0,\n    \"AVERAGE\": 1,\n    \"L2\": 2\n};\n\nCoreML.Specification.PoolingLayerParams.ValidCompletePadding = class ValidCompletePadding {\n\n    constructor() {\n        this.paddingAmounts = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PoolingLayerParams.ValidCompletePadding();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.paddingAmounts = reader.array(message.paddingAmounts, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PoolingLayerParams.ValidCompletePadding();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"paddingAmounts\":\n                    reader.array(message.paddingAmounts, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Pooling3DLayerParams = class Pooling3DLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Pooling3DLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = reader.int32();\n                    break;\n                case 2:\n                    message.kernelDepth = reader.int32();\n                    break;\n                case 3:\n                    message.kernelHeight = reader.int32();\n                    break;\n                case 4:\n                    message.kernelWidth = reader.int32();\n                    break;\n                case 5:\n                    message.strideDepth = reader.int32();\n                    break;\n                case 6:\n                    message.strideHeight = reader.int32();\n                    break;\n                case 7:\n                    message.strideWidth = reader.int32();\n                    break;\n                case 15:\n                    message.paddingType = reader.int32();\n                    break;\n                case 8:\n                    message.customPaddingFront = reader.int32();\n                    break;\n                case 9:\n                    message.customPaddingBack = reader.int32();\n                    break;\n                case 10:\n                    message.customPaddingTop = reader.int32();\n                    break;\n                case 11:\n                    message.customPaddingBottom = reader.int32();\n                    break;\n                case 12:\n                    message.customPaddingLeft = reader.int32();\n                    break;\n                case 13:\n                    message.customPaddingRight = reader.int32();\n                    break;\n                case 14:\n                    message.countExcludePadding = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Pooling3DLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.enum(CoreML.Specification.Pooling3DLayerParams.PoolingType3D);\n                    break;\n                case \"kernelDepth\":\n                    message.kernelDepth = reader.int32();\n                    break;\n                case \"kernelHeight\":\n                    message.kernelHeight = reader.int32();\n                    break;\n                case \"kernelWidth\":\n                    message.kernelWidth = reader.int32();\n                    break;\n                case \"strideDepth\":\n                    message.strideDepth = reader.int32();\n                    break;\n                case \"strideHeight\":\n                    message.strideHeight = reader.int32();\n                    break;\n                case \"strideWidth\":\n                    message.strideWidth = reader.int32();\n                    break;\n                case \"paddingType\":\n                    message.paddingType = reader.enum(CoreML.Specification.Pooling3DLayerParams.Pooling3DPaddingType);\n                    break;\n                case \"customPaddingFront\":\n                    message.customPaddingFront = reader.int32();\n                    break;\n                case \"customPaddingBack\":\n                    message.customPaddingBack = reader.int32();\n                    break;\n                case \"customPaddingTop\":\n                    message.customPaddingTop = reader.int32();\n                    break;\n                case \"customPaddingBottom\":\n                    message.customPaddingBottom = reader.int32();\n                    break;\n                case \"customPaddingLeft\":\n                    message.customPaddingLeft = reader.int32();\n                    break;\n                case \"customPaddingRight\":\n                    message.customPaddingRight = reader.int32();\n                    break;\n                case \"countExcludePadding\":\n                    message.countExcludePadding = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Pooling3DLayerParams.prototype.type = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.kernelDepth = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.kernelHeight = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.kernelWidth = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.strideDepth = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.strideHeight = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.strideWidth = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.paddingType = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.customPaddingFront = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.customPaddingBack = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.customPaddingTop = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.customPaddingBottom = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.customPaddingLeft = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.customPaddingRight = 0;\nCoreML.Specification.Pooling3DLayerParams.prototype.countExcludePadding = false;\n\nCoreML.Specification.Pooling3DLayerParams.PoolingType3D = {\n    \"MAX\": 0,\n    \"AVERAGE\": 1\n};\n\nCoreML.Specification.Pooling3DLayerParams.Pooling3DPaddingType = {\n    \"CUSTOM\": 0,\n    \"VALID\": 1,\n    \"SAME\": 2\n};\n\nCoreML.Specification.GlobalPooling3DLayerParams = class GlobalPooling3DLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GlobalPooling3DLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GlobalPooling3DLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.enum(CoreML.Specification.GlobalPooling3DLayerParams.GlobalPoolingType3D);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GlobalPooling3DLayerParams.prototype.type = 0;\n\nCoreML.Specification.GlobalPooling3DLayerParams.GlobalPoolingType3D = {\n    \"MAX\": 0,\n    \"AVERAGE\": 1\n};\n\nCoreML.Specification.PaddingLayerParams = class PaddingLayerParams {\n\n    get PaddingType() {\n        CoreML.Specification.PaddingLayerParams.PaddingTypeSet = CoreML.Specification.PaddingLayerParams.PaddingTypeSet || new Set([\"constant\", \"reflection\", \"replication\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.PaddingLayerParams.PaddingTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PaddingLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.constant = CoreML.Specification.PaddingLayerParams.PaddingConstant.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.reflection = CoreML.Specification.PaddingLayerParams.PaddingReflection.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.replication = CoreML.Specification.PaddingLayerParams.PaddingReplication.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.paddingAmounts = CoreML.Specification.BorderAmounts.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PaddingLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"constant\":\n                    message.constant = CoreML.Specification.PaddingLayerParams.PaddingConstant.decodeText(reader);\n                    break;\n                case \"reflection\":\n                    message.reflection = CoreML.Specification.PaddingLayerParams.PaddingReflection.decodeText(reader);\n                    break;\n                case \"replication\":\n                    message.replication = CoreML.Specification.PaddingLayerParams.PaddingReplication.decodeText(reader);\n                    break;\n                case \"paddingAmounts\":\n                    message.paddingAmounts = CoreML.Specification.BorderAmounts.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PaddingLayerParams.prototype.paddingAmounts = null;\n\nCoreML.Specification.PaddingLayerParams.PaddingConstant = class PaddingConstant {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PaddingLayerParams.PaddingConstant();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PaddingLayerParams.PaddingConstant();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PaddingLayerParams.PaddingConstant.prototype.value = 0;\n\nCoreML.Specification.PaddingLayerParams.PaddingReflection = class PaddingReflection {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PaddingLayerParams.PaddingReflection();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PaddingLayerParams.PaddingReflection();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PaddingLayerParams.PaddingReplication = class PaddingReplication {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PaddingLayerParams.PaddingReplication();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PaddingLayerParams.PaddingReplication();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConcatLayerParams = class ConcatLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ConcatLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 100:\n                    message.sequenceConcat = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ConcatLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sequenceConcat\":\n                    message.sequenceConcat = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConcatLayerParams.prototype.sequenceConcat = false;\n\nCoreML.Specification.LRNLayerParams = class LRNLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LRNLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta = reader.float();\n                    break;\n                case 3:\n                    message.localSize = reader.uint64();\n                    break;\n                case 4:\n                    message.k = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LRNLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                case \"localSize\":\n                    message.localSize = reader.uint64();\n                    break;\n                case \"k\":\n                    message.k = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LRNLayerParams.prototype.alpha = 0;\nCoreML.Specification.LRNLayerParams.prototype.beta = 0;\nCoreML.Specification.LRNLayerParams.prototype.localSize = 0n;\nCoreML.Specification.LRNLayerParams.prototype.k = 0;\n\nCoreML.Specification.SoftmaxLayerParams = class SoftmaxLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SoftmaxLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SoftmaxLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SplitLayerParams = class SplitLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SplitLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.nOutputs = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SplitLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"nOutputs\":\n                    message.nOutputs = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SplitLayerParams.prototype.nOutputs = 0n;\n\nCoreML.Specification.AddLayerParams = class AddLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AddLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AddLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AddLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.MultiplyLayerParams = class MultiplyLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MultiplyLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MultiplyLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MultiplyLayerParams.prototype.alpha = 0;\n\nCoreML.Specification.UnaryFunctionLayerParams = class UnaryFunctionLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.UnaryFunctionLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.type = reader.int32();\n                    break;\n                case 2:\n                    message.alpha = reader.float();\n                    break;\n                case 3:\n                    message.epsilon = reader.float();\n                    break;\n                case 4:\n                    message.shift = reader.float();\n                    break;\n                case 5:\n                    message.scale = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.UnaryFunctionLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.enum(CoreML.Specification.UnaryFunctionLayerParams.Operation);\n                    break;\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"epsilon\":\n                    message.epsilon = reader.float();\n                    break;\n                case \"shift\":\n                    message.shift = reader.float();\n                    break;\n                case \"scale\":\n                    message.scale = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.UnaryFunctionLayerParams.prototype.type = 0;\nCoreML.Specification.UnaryFunctionLayerParams.prototype.alpha = 0;\nCoreML.Specification.UnaryFunctionLayerParams.prototype.epsilon = 0;\nCoreML.Specification.UnaryFunctionLayerParams.prototype.shift = 0;\nCoreML.Specification.UnaryFunctionLayerParams.prototype.scale = 0;\n\nCoreML.Specification.UnaryFunctionLayerParams.Operation = {\n    \"SQRT\": 0,\n    \"RSQRT\": 1,\n    \"INVERSE\": 2,\n    \"POWER\": 3,\n    \"EXP\": 4,\n    \"LOG\": 5,\n    \"ABS\": 6,\n    \"THRESHOLD\": 7\n};\n\nCoreML.Specification.UpsampleLayerParams = class UpsampleLayerParams {\n\n    constructor() {\n        this.scalingFactor = [];\n        this.fractionalScalingFactor = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.UpsampleLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.scalingFactor = reader.array(message.scalingFactor, () => reader.uint64(), tag);\n                    break;\n                case 7:\n                    message.fractionalScalingFactor = reader.floats(message.fractionalScalingFactor, tag);\n                    break;\n                case 5:\n                    message.mode = reader.int32();\n                    break;\n                case 6:\n                    message.linearUpsampleMode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.UpsampleLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"scalingFactor\":\n                    reader.array(message.scalingFactor, () => reader.uint64());\n                    break;\n                case \"fractionalScalingFactor\":\n                    reader.array(message.fractionalScalingFactor, () => reader.float());\n                    break;\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.UpsampleLayerParams.InterpolationMode);\n                    break;\n                case \"linearUpsampleMode\":\n                    message.linearUpsampleMode = reader.enum(CoreML.Specification.UpsampleLayerParams.LinearUpsampleMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.UpsampleLayerParams.prototype.mode = 0;\nCoreML.Specification.UpsampleLayerParams.prototype.linearUpsampleMode = 0;\n\nCoreML.Specification.UpsampleLayerParams.InterpolationMode = {\n    \"NN\": 0,\n    \"BILINEAR\": 1\n};\n\nCoreML.Specification.UpsampleLayerParams.LinearUpsampleMode = {\n    \"DEFAULT\": 0,\n    \"ALIGN_CORNERS_TRUE\": 1,\n    \"ALIGN_CORNERS_FALSE\": 2\n};\n\nCoreML.Specification.ResizeBilinearLayerParams = class ResizeBilinearLayerParams {\n\n    constructor() {\n        this.targetSize = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ResizeBilinearLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.targetSize = reader.array(message.targetSize, () => reader.uint64(), tag);\n                    break;\n                case 2:\n                    message.mode = CoreML.Specification.SamplingMode.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ResizeBilinearLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"targetSize\":\n                    reader.array(message.targetSize, () => reader.uint64());\n                    break;\n                case \"mode\":\n                    message.mode = CoreML.Specification.SamplingMode.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ResizeBilinearLayerParams.prototype.mode = null;\n\nCoreML.Specification.CropResizeLayerParams = class CropResizeLayerParams {\n\n    constructor() {\n        this.targetSize = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CropResizeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.targetSize = reader.array(message.targetSize, () => reader.uint64(), tag);\n                    break;\n                case 2:\n                    message.normalizedCoordinates = reader.bool();\n                    break;\n                case 3:\n                    message.mode = CoreML.Specification.SamplingMode.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.boxIndicesMode = CoreML.Specification.BoxCoordinatesMode.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.spatialScale = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CropResizeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"targetSize\":\n                    reader.array(message.targetSize, () => reader.uint64());\n                    break;\n                case \"normalizedCoordinates\":\n                    message.normalizedCoordinates = reader.bool();\n                    break;\n                case \"mode\":\n                    message.mode = CoreML.Specification.SamplingMode.decodeText(reader);\n                    break;\n                case \"boxIndicesMode\":\n                    message.boxIndicesMode = CoreML.Specification.BoxCoordinatesMode.decodeText(reader);\n                    break;\n                case \"spatialScale\":\n                    message.spatialScale = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CropResizeLayerParams.prototype.normalizedCoordinates = false;\nCoreML.Specification.CropResizeLayerParams.prototype.mode = null;\nCoreML.Specification.CropResizeLayerParams.prototype.boxIndicesMode = null;\nCoreML.Specification.CropResizeLayerParams.prototype.spatialScale = 0;\n\nCoreML.Specification.BiasLayerParams = class BiasLayerParams {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BiasLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = reader.array(message.shape, () => reader.uint64(), tag);\n                    break;\n                case 2:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BiasLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    reader.array(message.shape, () => reader.uint64());\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BiasLayerParams.prototype.bias = null;\n\nCoreML.Specification.ScaleLayerParams = class ScaleLayerParams {\n\n    constructor() {\n        this.shapeScale = [];\n        this.shapeBias = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ScaleLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shapeScale = reader.array(message.shapeScale, () => reader.uint64(), tag);\n                    break;\n                case 2:\n                    message.scale = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.hasBias = reader.bool();\n                    break;\n                case 4:\n                    message.shapeBias = reader.array(message.shapeBias, () => reader.uint64(), tag);\n                    break;\n                case 5:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ScaleLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shapeScale\":\n                    reader.array(message.shapeScale, () => reader.uint64());\n                    break;\n                case \"scale\":\n                    message.scale = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"shapeBias\":\n                    reader.array(message.shapeBias, () => reader.uint64());\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ScaleLayerParams.prototype.scale = null;\nCoreML.Specification.ScaleLayerParams.prototype.hasBias = false;\nCoreML.Specification.ScaleLayerParams.prototype.bias = null;\n\nCoreML.Specification.LoadConstantLayerParams = class LoadConstantLayerParams {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LoadConstantLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = reader.array(message.shape, () => reader.uint64(), tag);\n                    break;\n                case 2:\n                    message.data = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LoadConstantLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    reader.array(message.shape, () => reader.uint64());\n                    break;\n                case \"data\":\n                    message.data = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LoadConstantLayerParams.prototype.data = null;\n\nCoreML.Specification.L2NormalizeLayerParams = class L2NormalizeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.L2NormalizeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.epsilon = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.L2NormalizeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"epsilon\":\n                    message.epsilon = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.L2NormalizeLayerParams.prototype.epsilon = 0;\n\nCoreML.Specification.FlattenLayerParams = class FlattenLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FlattenLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FlattenLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.FlattenLayerParams.FlattenOrder);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FlattenLayerParams.prototype.mode = 0;\n\nCoreML.Specification.FlattenLayerParams.FlattenOrder = {\n    \"CHANNEL_FIRST\": 0,\n    \"CHANNEL_LAST\": 1\n};\n\nCoreML.Specification.ReshapeLayerParams = class ReshapeLayerParams {\n\n    constructor() {\n        this.targetShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReshapeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.targetShape = reader.array(message.targetShape, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReshapeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"targetShape\":\n                    reader.array(message.targetShape, () => reader.int64());\n                    break;\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.ReshapeLayerParams.ReshapeOrder);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReshapeLayerParams.prototype.mode = 0;\n\nCoreML.Specification.ReshapeLayerParams.ReshapeOrder = {\n    \"CHANNEL_FIRST\": 0,\n    \"CHANNEL_LAST\": 1\n};\n\nCoreML.Specification.PermuteLayerParams = class PermuteLayerParams {\n\n    constructor() {\n        this.axis = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PermuteLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.array(message.axis, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PermuteLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    reader.array(message.axis, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReorganizeDataLayerParams = class ReorganizeDataLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReorganizeDataLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mode = reader.int32();\n                    break;\n                case 2:\n                    message.blockSize = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReorganizeDataLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.ReorganizeDataLayerParams.ReorganizationType);\n                    break;\n                case \"blockSize\":\n                    message.blockSize = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReorganizeDataLayerParams.prototype.mode = 0;\nCoreML.Specification.ReorganizeDataLayerParams.prototype.blockSize = 0n;\n\nCoreML.Specification.ReorganizeDataLayerParams.ReorganizationType = {\n    \"SPACE_TO_DEPTH\": 0,\n    \"DEPTH_TO_SPACE\": 1,\n    \"PIXEL_SHUFFLE\": 2\n};\n\nCoreML.Specification.SliceLayerParams = class SliceLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SliceLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.startIndex = reader.int64();\n                    break;\n                case 2:\n                    message.endIndex = reader.int64();\n                    break;\n                case 3:\n                    message.stride = reader.uint64();\n                    break;\n                case 4:\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SliceLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"startIndex\":\n                    message.startIndex = reader.int64();\n                    break;\n                case \"endIndex\":\n                    message.endIndex = reader.int64();\n                    break;\n                case \"stride\":\n                    message.stride = reader.uint64();\n                    break;\n                case \"axis\":\n                    message.axis = reader.enum(CoreML.Specification.SliceLayerParams.SliceAxis);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SliceLayerParams.prototype.startIndex = 0n;\nCoreML.Specification.SliceLayerParams.prototype.endIndex = 0n;\nCoreML.Specification.SliceLayerParams.prototype.stride = 0n;\nCoreML.Specification.SliceLayerParams.prototype.axis = 0;\n\nCoreML.Specification.SliceLayerParams.SliceAxis = {\n    \"CHANNEL_AXIS\": 0,\n    \"HEIGHT_AXIS\": 1,\n    \"WIDTH_AXIS\": 2\n};\n\nCoreML.Specification.ReduceLayerParams = class ReduceLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mode = reader.int32();\n                    break;\n                case 2:\n                    message.epsilon = reader.float();\n                    break;\n                case 3:\n                    message.axis = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.ReduceLayerParams.ReduceOperation);\n                    break;\n                case \"epsilon\":\n                    message.epsilon = reader.float();\n                    break;\n                case \"axis\":\n                    message.axis = reader.enum(CoreML.Specification.ReduceLayerParams.ReduceAxis);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceLayerParams.prototype.mode = 0;\nCoreML.Specification.ReduceLayerParams.prototype.epsilon = 0;\nCoreML.Specification.ReduceLayerParams.prototype.axis = 0;\n\nCoreML.Specification.ReduceLayerParams.ReduceOperation = {\n    \"SUM\": 0,\n    \"AVG\": 1,\n    \"PROD\": 2,\n    \"LOGSUM\": 3,\n    \"SUMSQUARE\": 4,\n    \"L1\": 5,\n    \"L2\": 6,\n    \"MAX\": 7,\n    \"MIN\": 8,\n    \"ARGMAX\": 9\n};\n\nCoreML.Specification.ReduceLayerParams.ReduceAxis = {\n    \"CHW\": 0,\n    \"HW\": 1,\n    \"C\": 2,\n    \"H\": 3,\n    \"W\": 4\n};\n\nCoreML.Specification.CropLayerParams = class CropLayerParams {\n\n    constructor() {\n        this.offset = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CropLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.cropAmounts = CoreML.Specification.BorderAmounts.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.offset = reader.array(message.offset, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CropLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"cropAmounts\":\n                    message.cropAmounts = CoreML.Specification.BorderAmounts.decodeText(reader);\n                    break;\n                case \"offset\":\n                    reader.array(message.offset, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CropLayerParams.prototype.cropAmounts = null;\n\nCoreML.Specification.AverageLayerParams = class AverageLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AverageLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AverageLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MaxLayerParams = class MaxLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MaxLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MaxLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MinLayerParams = class MinLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MinLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MinLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DotProductLayerParams = class DotProductLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DotProductLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.cosineSimilarity = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DotProductLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"cosineSimilarity\":\n                    message.cosineSimilarity = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DotProductLayerParams.prototype.cosineSimilarity = false;\n\nCoreML.Specification.MeanVarianceNormalizeLayerParams = class MeanVarianceNormalizeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MeanVarianceNormalizeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.acrossChannels = reader.bool();\n                    break;\n                case 2:\n                    message.normalizeVariance = reader.bool();\n                    break;\n                case 3:\n                    message.epsilon = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MeanVarianceNormalizeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"acrossChannels\":\n                    message.acrossChannels = reader.bool();\n                    break;\n                case \"normalizeVariance\":\n                    message.normalizeVariance = reader.bool();\n                    break;\n                case \"epsilon\":\n                    message.epsilon = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MeanVarianceNormalizeLayerParams.prototype.acrossChannels = false;\nCoreML.Specification.MeanVarianceNormalizeLayerParams.prototype.normalizeVariance = false;\nCoreML.Specification.MeanVarianceNormalizeLayerParams.prototype.epsilon = 0;\n\nCoreML.Specification.SequenceRepeatLayerParams = class SequenceRepeatLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SequenceRepeatLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.nRepetitions = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SequenceRepeatLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"nRepetitions\":\n                    message.nRepetitions = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SequenceRepeatLayerParams.prototype.nRepetitions = 0n;\n\nCoreML.Specification.SimpleRecurrentLayerParams = class SimpleRecurrentLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SimpleRecurrentLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case 2:\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case 10:\n                    message.activation = CoreML.Specification.ActivationParams.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.sequenceOutput = reader.bool();\n                    break;\n                case 20:\n                    message.hasBiasVector = reader.bool();\n                    break;\n                case 30:\n                    message.weightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.recursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 32:\n                    message.biasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.reverseInput = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SimpleRecurrentLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputVectorSize\":\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case \"outputVectorSize\":\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case \"activation\":\n                    message.activation = CoreML.Specification.ActivationParams.decodeText(reader);\n                    break;\n                case \"sequenceOutput\":\n                    message.sequenceOutput = reader.bool();\n                    break;\n                case \"hasBiasVector\":\n                    message.hasBiasVector = reader.bool();\n                    break;\n                case \"weightMatrix\":\n                    message.weightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"recursionMatrix\":\n                    message.recursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"biasVector\":\n                    message.biasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"reverseInput\":\n                    message.reverseInput = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.inputVectorSize = 0n;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.outputVectorSize = 0n;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.activation = null;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.sequenceOutput = false;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.hasBiasVector = false;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.weightMatrix = null;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.recursionMatrix = null;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.biasVector = null;\nCoreML.Specification.SimpleRecurrentLayerParams.prototype.reverseInput = false;\n\nCoreML.Specification.GRULayerParams = class GRULayerParams {\n\n    constructor() {\n        this.activations = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GRULayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case 2:\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case 10:\n                    message.activations.push(CoreML.Specification.ActivationParams.decode(reader, reader.uint32()));\n                    break;\n                case 15:\n                    message.sequenceOutput = reader.bool();\n                    break;\n                case 20:\n                    message.hasBiasVectors = reader.bool();\n                    break;\n                case 30:\n                    message.updateGateWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 31:\n                    message.resetGateWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 32:\n                    message.outputGateWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 50:\n                    message.updateGateRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 51:\n                    message.resetGateRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 52:\n                    message.outputGateRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 70:\n                    message.updateGateBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 71:\n                    message.resetGateBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 72:\n                    message.outputGateBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.reverseInput = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GRULayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputVectorSize\":\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case \"outputVectorSize\":\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case \"activations\":\n                    message.activations.push(CoreML.Specification.ActivationParams.decodeText(reader));\n                    break;\n                case \"sequenceOutput\":\n                    message.sequenceOutput = reader.bool();\n                    break;\n                case \"hasBiasVectors\":\n                    message.hasBiasVectors = reader.bool();\n                    break;\n                case \"updateGateWeightMatrix\":\n                    message.updateGateWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"resetGateWeightMatrix\":\n                    message.resetGateWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGateWeightMatrix\":\n                    message.outputGateWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"updateGateRecursionMatrix\":\n                    message.updateGateRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"resetGateRecursionMatrix\":\n                    message.resetGateRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGateRecursionMatrix\":\n                    message.outputGateRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"updateGateBiasVector\":\n                    message.updateGateBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"resetGateBiasVector\":\n                    message.resetGateBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGateBiasVector\":\n                    message.outputGateBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"reverseInput\":\n                    message.reverseInput = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GRULayerParams.prototype.inputVectorSize = 0n;\nCoreML.Specification.GRULayerParams.prototype.outputVectorSize = 0n;\nCoreML.Specification.GRULayerParams.prototype.sequenceOutput = false;\nCoreML.Specification.GRULayerParams.prototype.hasBiasVectors = false;\nCoreML.Specification.GRULayerParams.prototype.updateGateWeightMatrix = null;\nCoreML.Specification.GRULayerParams.prototype.resetGateWeightMatrix = null;\nCoreML.Specification.GRULayerParams.prototype.outputGateWeightMatrix = null;\nCoreML.Specification.GRULayerParams.prototype.updateGateRecursionMatrix = null;\nCoreML.Specification.GRULayerParams.prototype.resetGateRecursionMatrix = null;\nCoreML.Specification.GRULayerParams.prototype.outputGateRecursionMatrix = null;\nCoreML.Specification.GRULayerParams.prototype.updateGateBiasVector = null;\nCoreML.Specification.GRULayerParams.prototype.resetGateBiasVector = null;\nCoreML.Specification.GRULayerParams.prototype.outputGateBiasVector = null;\nCoreML.Specification.GRULayerParams.prototype.reverseInput = false;\n\nCoreML.Specification.LSTMParams = class LSTMParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LSTMParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.sequenceOutput = reader.bool();\n                    break;\n                case 20:\n                    message.hasBiasVectors = reader.bool();\n                    break;\n                case 30:\n                    message.forgetBias = reader.bool();\n                    break;\n                case 40:\n                    message.hasPeepholeVectors = reader.bool();\n                    break;\n                case 50:\n                    message.coupledInputAndForgetGate = reader.bool();\n                    break;\n                case 60:\n                    message.cellClipThreshold = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LSTMParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sequenceOutput\":\n                    message.sequenceOutput = reader.bool();\n                    break;\n                case \"hasBiasVectors\":\n                    message.hasBiasVectors = reader.bool();\n                    break;\n                case \"forgetBias\":\n                    message.forgetBias = reader.bool();\n                    break;\n                case \"hasPeepholeVectors\":\n                    message.hasPeepholeVectors = reader.bool();\n                    break;\n                case \"coupledInputAndForgetGate\":\n                    message.coupledInputAndForgetGate = reader.bool();\n                    break;\n                case \"cellClipThreshold\":\n                    message.cellClipThreshold = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LSTMParams.prototype.sequenceOutput = false;\nCoreML.Specification.LSTMParams.prototype.hasBiasVectors = false;\nCoreML.Specification.LSTMParams.prototype.forgetBias = false;\nCoreML.Specification.LSTMParams.prototype.hasPeepholeVectors = false;\nCoreML.Specification.LSTMParams.prototype.coupledInputAndForgetGate = false;\nCoreML.Specification.LSTMParams.prototype.cellClipThreshold = 0;\n\nCoreML.Specification.LSTMWeightParams = class LSTMWeightParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LSTMWeightParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputGateWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.forgetGateWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.blockInputWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.outputGateWeightMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.inputGateRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 21:\n                    message.forgetGateRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 22:\n                    message.blockInputRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 23:\n                    message.outputGateRecursionMatrix = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 40:\n                    message.inputGateBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 41:\n                    message.forgetGateBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 42:\n                    message.blockInputBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 43:\n                    message.outputGateBiasVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 60:\n                    message.inputGatePeepholeVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 61:\n                    message.forgetGatePeepholeVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 62:\n                    message.outputGatePeepholeVector = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LSTMWeightParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputGateWeightMatrix\":\n                    message.inputGateWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"forgetGateWeightMatrix\":\n                    message.forgetGateWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"blockInputWeightMatrix\":\n                    message.blockInputWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGateWeightMatrix\":\n                    message.outputGateWeightMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"inputGateRecursionMatrix\":\n                    message.inputGateRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"forgetGateRecursionMatrix\":\n                    message.forgetGateRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"blockInputRecursionMatrix\":\n                    message.blockInputRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGateRecursionMatrix\":\n                    message.outputGateRecursionMatrix = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"inputGateBiasVector\":\n                    message.inputGateBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"forgetGateBiasVector\":\n                    message.forgetGateBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"blockInputBiasVector\":\n                    message.blockInputBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGateBiasVector\":\n                    message.outputGateBiasVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"inputGatePeepholeVector\":\n                    message.inputGatePeepholeVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"forgetGatePeepholeVector\":\n                    message.forgetGatePeepholeVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"outputGatePeepholeVector\":\n                    message.outputGatePeepholeVector = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LSTMWeightParams.prototype.inputGateWeightMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.forgetGateWeightMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.blockInputWeightMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.outputGateWeightMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.inputGateRecursionMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.forgetGateRecursionMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.blockInputRecursionMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.outputGateRecursionMatrix = null;\nCoreML.Specification.LSTMWeightParams.prototype.inputGateBiasVector = null;\nCoreML.Specification.LSTMWeightParams.prototype.forgetGateBiasVector = null;\nCoreML.Specification.LSTMWeightParams.prototype.blockInputBiasVector = null;\nCoreML.Specification.LSTMWeightParams.prototype.outputGateBiasVector = null;\nCoreML.Specification.LSTMWeightParams.prototype.inputGatePeepholeVector = null;\nCoreML.Specification.LSTMWeightParams.prototype.forgetGatePeepholeVector = null;\nCoreML.Specification.LSTMWeightParams.prototype.outputGatePeepholeVector = null;\n\nCoreML.Specification.UniDirectionalLSTMLayerParams = class UniDirectionalLSTMLayerParams {\n\n    constructor() {\n        this.activations = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.UniDirectionalLSTMLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case 2:\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case 10:\n                    message.activations.push(CoreML.Specification.ActivationParams.decode(reader, reader.uint32()));\n                    break;\n                case 15:\n                    message.params = CoreML.Specification.LSTMParams.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.weightParams = CoreML.Specification.LSTMWeightParams.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.reverseInput = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.UniDirectionalLSTMLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputVectorSize\":\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case \"outputVectorSize\":\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case \"activations\":\n                    message.activations.push(CoreML.Specification.ActivationParams.decodeText(reader));\n                    break;\n                case \"params\":\n                    message.params = CoreML.Specification.LSTMParams.decodeText(reader);\n                    break;\n                case \"weightParams\":\n                    message.weightParams = CoreML.Specification.LSTMWeightParams.decodeText(reader);\n                    break;\n                case \"reverseInput\":\n                    message.reverseInput = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.UniDirectionalLSTMLayerParams.prototype.inputVectorSize = 0n;\nCoreML.Specification.UniDirectionalLSTMLayerParams.prototype.outputVectorSize = 0n;\nCoreML.Specification.UniDirectionalLSTMLayerParams.prototype.params = null;\nCoreML.Specification.UniDirectionalLSTMLayerParams.prototype.weightParams = null;\nCoreML.Specification.UniDirectionalLSTMLayerParams.prototype.reverseInput = false;\n\nCoreML.Specification.BiDirectionalLSTMLayerParams = class BiDirectionalLSTMLayerParams {\n\n    constructor() {\n        this.activationsForwardLSTM = [];\n        this.activationsBackwardLSTM = [];\n        this.weightParams = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BiDirectionalLSTMLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case 2:\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case 10:\n                    message.activationsForwardLSTM.push(CoreML.Specification.ActivationParams.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    message.activationsBackwardLSTM.push(CoreML.Specification.ActivationParams.decode(reader, reader.uint32()));\n                    break;\n                case 15:\n                    message.params = CoreML.Specification.LSTMParams.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.weightParams.push(CoreML.Specification.LSTMWeightParams.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BiDirectionalLSTMLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inputVectorSize\":\n                    message.inputVectorSize = reader.uint64();\n                    break;\n                case \"outputVectorSize\":\n                    message.outputVectorSize = reader.uint64();\n                    break;\n                case \"activationsForwardLSTM\":\n                    message.activationsForwardLSTM.push(CoreML.Specification.ActivationParams.decodeText(reader));\n                    break;\n                case \"activationsBackwardLSTM\":\n                    message.activationsBackwardLSTM.push(CoreML.Specification.ActivationParams.decodeText(reader));\n                    break;\n                case \"params\":\n                    message.params = CoreML.Specification.LSTMParams.decodeText(reader);\n                    break;\n                case \"weightParams\":\n                    message.weightParams.push(CoreML.Specification.LSTMWeightParams.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BiDirectionalLSTMLayerParams.prototype.inputVectorSize = 0n;\nCoreML.Specification.BiDirectionalLSTMLayerParams.prototype.outputVectorSize = 0n;\nCoreML.Specification.BiDirectionalLSTMLayerParams.prototype.params = null;\n\nCoreML.Specification.CustomLayerParams = class CustomLayerParams {\n\n    constructor() {\n        this.weights = [];\n        this.parameters = {};\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CustomLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.className = reader.string();\n                    break;\n                case 20:\n                    message.weights.push(CoreML.Specification.WeightParams.decode(reader, reader.uint32()));\n                    break;\n                case 30:\n                    reader.entry(message.parameters, () => reader.string(), () => CoreML.Specification.CustomLayerParams.CustomLayerParamValue.decode(reader, reader.uint32()));\n                    break;\n                case 40:\n                    message.description = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CustomLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"className\":\n                    message.className = reader.string();\n                    break;\n                case \"weights\":\n                    message.weights.push(CoreML.Specification.WeightParams.decodeText(reader));\n                    break;\n                case \"parameters\":\n                    reader.entry(message.parameters, () => reader.string(), () => CoreML.Specification.CustomLayerParams.CustomLayerParamValue.decodeText(reader));\n                    break;\n                case \"description\":\n                    message.description = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CustomLayerParams.prototype.className = \"\";\nCoreML.Specification.CustomLayerParams.prototype.description = \"\";\n\nCoreML.Specification.CustomLayerParams.CustomLayerParamValue = class CustomLayerParamValue {\n\n    get value() {\n        CoreML.Specification.CustomLayerParams.CustomLayerParamValue.valueSet = CoreML.Specification.CustomLayerParams.CustomLayerParamValue.valueSet || new Set([\"doubleValue\", \"stringValue\", \"intValue\", \"longValue\", \"boolValue\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.CustomLayerParams.CustomLayerParamValue.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CustomLayerParams.CustomLayerParamValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.doubleValue = reader.double();\n                    break;\n                case 20:\n                    message.stringValue = reader.string();\n                    break;\n                case 30:\n                    message.intValue = reader.int32();\n                    break;\n                case 40:\n                    message.longValue = reader.int64();\n                    break;\n                case 50:\n                    message.boolValue = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CustomLayerParams.CustomLayerParamValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"doubleValue\":\n                    message.doubleValue = reader.double();\n                    break;\n                case \"stringValue\":\n                    message.stringValue = reader.string();\n                    break;\n                case \"intValue\":\n                    message.intValue = reader.int32();\n                    break;\n                case \"longValue\":\n                    message.longValue = reader.int64();\n                    break;\n                case \"boolValue\":\n                    message.boolValue = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TransposeLayerParams = class TransposeLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TransposeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TransposeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BatchedMatMulLayerParams = class BatchedMatMulLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BatchedMatMulLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.transposeA = reader.bool();\n                    break;\n                case 2:\n                    message.transposeB = reader.bool();\n                    break;\n                case 5:\n                    message.weightMatrixFirstDimension = reader.uint64();\n                    break;\n                case 6:\n                    message.weightMatrixSecondDimension = reader.uint64();\n                    break;\n                case 7:\n                    message.hasBias = reader.bool();\n                    break;\n                case 8:\n                    message.weights = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 9:\n                    message.bias = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.int8DynamicQuantize = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BatchedMatMulLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"transposeA\":\n                    message.transposeA = reader.bool();\n                    break;\n                case \"transposeB\":\n                    message.transposeB = reader.bool();\n                    break;\n                case \"weightMatrixFirstDimension\":\n                    message.weightMatrixFirstDimension = reader.uint64();\n                    break;\n                case \"weightMatrixSecondDimension\":\n                    message.weightMatrixSecondDimension = reader.uint64();\n                    break;\n                case \"hasBias\":\n                    message.hasBias = reader.bool();\n                    break;\n                case \"weights\":\n                    message.weights = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"bias\":\n                    message.bias = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"int8DynamicQuantize\":\n                    message.int8DynamicQuantize = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BatchedMatMulLayerParams.prototype.transposeA = false;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.transposeB = false;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.weightMatrixFirstDimension = 0n;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.weightMatrixSecondDimension = 0n;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.hasBias = false;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.weights = null;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.bias = null;\nCoreML.Specification.BatchedMatMulLayerParams.prototype.int8DynamicQuantize = false;\n\nCoreML.Specification.ConcatNDLayerParams = class ConcatNDLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ConcatNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.interleave = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ConcatNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"interleave\":\n                    message.interleave = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConcatNDLayerParams.prototype.axis = 0n;\nCoreML.Specification.ConcatNDLayerParams.prototype.interleave = false;\n\nCoreML.Specification.SoftmaxNDLayerParams = class SoftmaxNDLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SoftmaxNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SoftmaxNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SoftmaxNDLayerParams.prototype.axis = 0n;\n\nCoreML.Specification.ReverseLayerParams = class ReverseLayerParams {\n\n    constructor() {\n        this.reverseDim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReverseLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.reverseDim = reader.array(message.reverseDim, () => reader.bool(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReverseLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"reverseDim\":\n                    reader.array(message.reverseDim, () => reader.bool());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReverseSeqLayerParams = class ReverseSeqLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReverseSeqLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.batchAxis = reader.int64();\n                    break;\n                case 2:\n                    message.sequenceAxis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReverseSeqLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"batchAxis\":\n                    message.batchAxis = reader.int64();\n                    break;\n                case \"sequenceAxis\":\n                    message.sequenceAxis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReverseSeqLayerParams.prototype.batchAxis = 0n;\nCoreML.Specification.ReverseSeqLayerParams.prototype.sequenceAxis = 0n;\n\nCoreML.Specification.LoadConstantNDLayerParams = class LoadConstantNDLayerParams {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LoadConstantNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = reader.array(message.shape, () => reader.uint64(), tag);\n                    break;\n                case 2:\n                    message.data = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LoadConstantNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    reader.array(message.shape, () => reader.uint64());\n                    break;\n                case \"data\":\n                    message.data = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LoadConstantNDLayerParams.prototype.data = null;\n\nCoreML.Specification.FillLikeLayerParams = class FillLikeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FillLikeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FillLikeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FillLikeLayerParams.prototype.value = 0;\n\nCoreML.Specification.FillStaticLayerParams = class FillStaticLayerParams {\n\n    constructor() {\n        this.targetShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FillStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.float();\n                    break;\n                case 2:\n                    message.targetShape = reader.array(message.targetShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FillStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                case \"targetShape\":\n                    reader.array(message.targetShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FillStaticLayerParams.prototype.value = 0;\n\nCoreML.Specification.FillDynamicLayerParams = class FillDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FillDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FillDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FillDynamicLayerParams.prototype.value = 0;\n\nCoreML.Specification.WhereBroadcastableLayerParams = class WhereBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.WhereBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.WhereBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SinLayerParams = class SinLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SinLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SinLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CosLayerParams = class CosLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CosLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CosLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TanLayerParams = class TanLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TanLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TanLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AsinLayerParams = class AsinLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AsinLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AsinLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AcosLayerParams = class AcosLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AcosLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AcosLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AtanLayerParams = class AtanLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AtanLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AtanLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SinhLayerParams = class SinhLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SinhLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SinhLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CoshLayerParams = class CoshLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CoshLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CoshLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TanhLayerParams = class TanhLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TanhLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TanhLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AsinhLayerParams = class AsinhLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AsinhLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AsinhLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AcoshLayerParams = class AcoshLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AcoshLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AcoshLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AtanhLayerParams = class AtanhLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AtanhLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AtanhLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PowBroadcastableLayerParams = class PowBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PowBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PowBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Exp2LayerParams = class Exp2LayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Exp2LayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Exp2LayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.WhereNonZeroLayerParams = class WhereNonZeroLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.WhereNonZeroLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.WhereNonZeroLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MatrixBandPartLayerParams = class MatrixBandPartLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MatrixBandPartLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.numLower = reader.int64();\n                    break;\n                case 2:\n                    message.numUpper = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MatrixBandPartLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"numLower\":\n                    message.numLower = reader.int64();\n                    break;\n                case \"numUpper\":\n                    message.numUpper = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MatrixBandPartLayerParams.prototype.numLower = 0n;\nCoreML.Specification.MatrixBandPartLayerParams.prototype.numUpper = 0n;\n\nCoreML.Specification.UpperTriangularLayerParams = class UpperTriangularLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.UpperTriangularLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.UpperTriangularLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.UpperTriangularLayerParams.prototype.k = 0n;\n\nCoreML.Specification.LowerTriangularLayerParams = class LowerTriangularLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LowerTriangularLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LowerTriangularLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LowerTriangularLayerParams.prototype.k = 0n;\n\nCoreML.Specification.BroadcastToLikeLayerParams = class BroadcastToLikeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BroadcastToLikeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BroadcastToLikeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BroadcastToStaticLayerParams = class BroadcastToStaticLayerParams {\n\n    constructor() {\n        this.targetShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BroadcastToStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.targetShape = reader.array(message.targetShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BroadcastToStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"targetShape\":\n                    reader.array(message.targetShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.BroadcastToDynamicLayerParams = class BroadcastToDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.BroadcastToDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.BroadcastToDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AddBroadcastableLayerParams = class AddBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AddBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AddBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MaxBroadcastableLayerParams = class MaxBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MaxBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MaxBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MinBroadcastableLayerParams = class MinBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MinBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MinBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ModBroadcastableLayerParams = class ModBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ModBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ModBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FloorDivBroadcastableLayerParams = class FloorDivBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FloorDivBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FloorDivBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SubtractBroadcastableLayerParams = class SubtractBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SubtractBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SubtractBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MultiplyBroadcastableLayerParams = class MultiplyBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MultiplyBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MultiplyBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DivideBroadcastableLayerParams = class DivideBroadcastableLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DivideBroadcastableLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DivideBroadcastableLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GatherLayerParams = class GatherLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GatherLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GatherLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GatherLayerParams.prototype.axis = 0n;\n\nCoreML.Specification.ScatterMode = {\n    \"SCATTER_UPDATE\": 0,\n    \"SCATTER_ADD\": 1,\n    \"SCATTER_SUB\": 2,\n    \"SCATTER_MUL\": 3,\n    \"SCATTER_DIV\": 4,\n    \"SCATTER_MAX\": 5,\n    \"SCATTER_MIN\": 6\n};\n\nCoreML.Specification.ScatterLayerParams = class ScatterLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ScatterLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ScatterLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.ScatterMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ScatterLayerParams.prototype.axis = 0n;\nCoreML.Specification.ScatterLayerParams.prototype.mode = 0;\n\nCoreML.Specification.GatherNDLayerParams = class GatherNDLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GatherNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GatherNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ScatterNDLayerParams = class ScatterNDLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ScatterNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ScatterNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.ScatterMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ScatterNDLayerParams.prototype.mode = 0;\n\nCoreML.Specification.GatherAlongAxisLayerParams = class GatherAlongAxisLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GatherAlongAxisLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GatherAlongAxisLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GatherAlongAxisLayerParams.prototype.axis = 0n;\n\nCoreML.Specification.ScatterAlongAxisLayerParams = class ScatterAlongAxisLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ScatterAlongAxisLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ScatterAlongAxisLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.ScatterMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ScatterAlongAxisLayerParams.prototype.axis = 0n;\nCoreML.Specification.ScatterAlongAxisLayerParams.prototype.mode = 0;\n\nCoreML.Specification.StackLayerParams = class StackLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.StackLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.StackLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.StackLayerParams.prototype.axis = 0n;\n\nCoreML.Specification.RankPreservingReshapeLayerParams = class RankPreservingReshapeLayerParams {\n\n    constructor() {\n        this.targetShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RankPreservingReshapeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.targetShape = reader.array(message.targetShape, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RankPreservingReshapeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"targetShape\":\n                    reader.array(message.targetShape, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConstantPaddingLayerParams = class ConstantPaddingLayerParams {\n\n    constructor() {\n        this.padAmounts = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ConstantPaddingLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.float();\n                    break;\n                case 2:\n                    message.padAmounts = reader.array(message.padAmounts, () => reader.uint64(), tag);\n                    break;\n                case 3:\n                    message.padToGivenOutputSizeMode = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ConstantPaddingLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                case \"padAmounts\":\n                    reader.array(message.padAmounts, () => reader.uint64());\n                    break;\n                case \"padToGivenOutputSizeMode\":\n                    message.padToGivenOutputSizeMode = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ConstantPaddingLayerParams.prototype.value = 0;\nCoreML.Specification.ConstantPaddingLayerParams.prototype.padToGivenOutputSizeMode = false;\n\nCoreML.Specification.RandomNormalLikeLayerParams = class RandomNormalLikeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomNormalLikeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.mean = reader.float();\n                    break;\n                case 3:\n                    message.stdDev = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomNormalLikeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"mean\":\n                    message.mean = reader.float();\n                    break;\n                case \"stdDev\":\n                    message.stdDev = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomNormalLikeLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomNormalLikeLayerParams.prototype.mean = 0;\nCoreML.Specification.RandomNormalLikeLayerParams.prototype.stdDev = 0;\n\nCoreML.Specification.RandomNormalStaticLayerParams = class RandomNormalStaticLayerParams {\n\n    constructor() {\n        this.outputShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomNormalStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.mean = reader.float();\n                    break;\n                case 3:\n                    message.stdDev = reader.float();\n                    break;\n                case 4:\n                    message.outputShape = reader.array(message.outputShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomNormalStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"mean\":\n                    message.mean = reader.float();\n                    break;\n                case \"stdDev\":\n                    message.stdDev = reader.float();\n                    break;\n                case \"outputShape\":\n                    reader.array(message.outputShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomNormalStaticLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomNormalStaticLayerParams.prototype.mean = 0;\nCoreML.Specification.RandomNormalStaticLayerParams.prototype.stdDev = 0;\n\nCoreML.Specification.RandomNormalDynamicLayerParams = class RandomNormalDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomNormalDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.mean = reader.float();\n                    break;\n                case 3:\n                    message.stdDev = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomNormalDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"mean\":\n                    message.mean = reader.float();\n                    break;\n                case \"stdDev\":\n                    message.stdDev = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomNormalDynamicLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomNormalDynamicLayerParams.prototype.mean = 0;\nCoreML.Specification.RandomNormalDynamicLayerParams.prototype.stdDev = 0;\n\nCoreML.Specification.RandomUniformLikeLayerParams = class RandomUniformLikeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomUniformLikeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.minVal = reader.float();\n                    break;\n                case 3:\n                    message.maxVal = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomUniformLikeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"minVal\":\n                    message.minVal = reader.float();\n                    break;\n                case \"maxVal\":\n                    message.maxVal = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomUniformLikeLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomUniformLikeLayerParams.prototype.minVal = 0;\nCoreML.Specification.RandomUniformLikeLayerParams.prototype.maxVal = 0;\n\nCoreML.Specification.RandomUniformStaticLayerParams = class RandomUniformStaticLayerParams {\n\n    constructor() {\n        this.outputShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomUniformStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.minVal = reader.float();\n                    break;\n                case 3:\n                    message.maxVal = reader.float();\n                    break;\n                case 4:\n                    message.outputShape = reader.array(message.outputShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomUniformStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"minVal\":\n                    message.minVal = reader.float();\n                    break;\n                case \"maxVal\":\n                    message.maxVal = reader.float();\n                    break;\n                case \"outputShape\":\n                    reader.array(message.outputShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomUniformStaticLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomUniformStaticLayerParams.prototype.minVal = 0;\nCoreML.Specification.RandomUniformStaticLayerParams.prototype.maxVal = 0;\n\nCoreML.Specification.RandomUniformDynamicLayerParams = class RandomUniformDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomUniformDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.minVal = reader.float();\n                    break;\n                case 3:\n                    message.maxVal = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomUniformDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"minVal\":\n                    message.minVal = reader.float();\n                    break;\n                case \"maxVal\":\n                    message.maxVal = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomUniformDynamicLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomUniformDynamicLayerParams.prototype.minVal = 0;\nCoreML.Specification.RandomUniformDynamicLayerParams.prototype.maxVal = 0;\n\nCoreML.Specification.RandomBernoulliLikeLayerParams = class RandomBernoulliLikeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomBernoulliLikeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.prob = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomBernoulliLikeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"prob\":\n                    message.prob = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomBernoulliLikeLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomBernoulliLikeLayerParams.prototype.prob = 0;\n\nCoreML.Specification.RandomBernoulliStaticLayerParams = class RandomBernoulliStaticLayerParams {\n\n    constructor() {\n        this.outputShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomBernoulliStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.prob = reader.float();\n                    break;\n                case 3:\n                    message.outputShape = reader.array(message.outputShape, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomBernoulliStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"prob\":\n                    message.prob = reader.float();\n                    break;\n                case \"outputShape\":\n                    reader.array(message.outputShape, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomBernoulliStaticLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomBernoulliStaticLayerParams.prototype.prob = 0;\n\nCoreML.Specification.RandomBernoulliDynamicLayerParams = class RandomBernoulliDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RandomBernoulliDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.prob = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RandomBernoulliDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"prob\":\n                    message.prob = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RandomBernoulliDynamicLayerParams.prototype.seed = 0n;\nCoreML.Specification.RandomBernoulliDynamicLayerParams.prototype.prob = 0;\n\nCoreML.Specification.CategoricalDistributionLayerParams = class CategoricalDistributionLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CategoricalDistributionLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.seed = reader.int64();\n                    break;\n                case 2:\n                    message.numSamples = reader.int64();\n                    break;\n                case 3:\n                    message.isLogits = reader.bool();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.temperature = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CategoricalDistributionLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"numSamples\":\n                    message.numSamples = reader.int64();\n                    break;\n                case \"isLogits\":\n                    message.isLogits = reader.bool();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"temperature\":\n                    message.temperature = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CategoricalDistributionLayerParams.prototype.seed = 0n;\nCoreML.Specification.CategoricalDistributionLayerParams.prototype.numSamples = 0n;\nCoreML.Specification.CategoricalDistributionLayerParams.prototype.isLogits = false;\nCoreML.Specification.CategoricalDistributionLayerParams.prototype.eps = 0;\nCoreML.Specification.CategoricalDistributionLayerParams.prototype.temperature = 0;\n\nCoreML.Specification.ReduceL1LayerParams = class ReduceL1LayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceL1LayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceL1LayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceL1LayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceL1LayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceL2LayerParams = class ReduceL2LayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceL2LayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceL2LayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceL2LayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceL2LayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceMaxLayerParams = class ReduceMaxLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceMaxLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceMaxLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceMaxLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceMaxLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceMinLayerParams = class ReduceMinLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceMinLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceMinLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceMinLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceMinLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceSumLayerParams = class ReduceSumLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceSumLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceSumLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceSumLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceSumLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceProdLayerParams = class ReduceProdLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceProdLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceProdLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceProdLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceProdLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceMeanLayerParams = class ReduceMeanLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceMeanLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceMeanLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceMeanLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceMeanLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceLogSumLayerParams = class ReduceLogSumLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceLogSumLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceLogSumLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceLogSumLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceLogSumLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceSumSquareLayerParams = class ReduceSumSquareLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceSumSquareLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceSumSquareLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceSumSquareLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceSumSquareLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ReduceLogSumExpLayerParams = class ReduceLogSumExpLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReduceLogSumExpLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keepDims = reader.bool();\n                    break;\n                case 3:\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReduceLogSumExpLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keepDims\":\n                    message.keepDims = reader.bool();\n                    break;\n                case \"reduceAll\":\n                    message.reduceAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReduceLogSumExpLayerParams.prototype.keepDims = false;\nCoreML.Specification.ReduceLogSumExpLayerParams.prototype.reduceAll = false;\n\nCoreML.Specification.ExpandDimsLayerParams = class ExpandDimsLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ExpandDimsLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ExpandDimsLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FlattenTo2DLayerParams = class FlattenTo2DLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FlattenTo2DLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FlattenTo2DLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FlattenTo2DLayerParams.prototype.axis = 0n;\n\nCoreML.Specification.ReshapeStaticLayerParams = class ReshapeStaticLayerParams {\n\n    constructor() {\n        this.targetShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReshapeStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.targetShape = reader.array(message.targetShape, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReshapeStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"targetShape\":\n                    reader.array(message.targetShape, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReshapeLikeLayerParams = class ReshapeLikeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReshapeLikeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReshapeLikeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ReshapeDynamicLayerParams = class ReshapeDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ReshapeDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ReshapeDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SqueezeLayerParams = class SqueezeLayerParams {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SqueezeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.squeezeAll = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SqueezeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"squeezeAll\":\n                    message.squeezeAll = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SqueezeLayerParams.prototype.squeezeAll = false;\n\nCoreML.Specification.TopKLayerParams = class TopKLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TopKLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.K = reader.uint64();\n                    break;\n                case 3:\n                    message.useBottomK = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TopKLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"K\":\n                    message.K = reader.uint64();\n                    break;\n                case \"useBottomK\":\n                    message.useBottomK = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TopKLayerParams.prototype.axis = 0n;\nCoreML.Specification.TopKLayerParams.prototype.K = 0n;\nCoreML.Specification.TopKLayerParams.prototype.useBottomK = false;\n\nCoreML.Specification.ArgMaxLayerParams = class ArgMaxLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArgMaxLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.removeDim = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArgMaxLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"removeDim\":\n                    message.removeDim = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ArgMaxLayerParams.prototype.axis = 0n;\nCoreML.Specification.ArgMaxLayerParams.prototype.removeDim = false;\n\nCoreML.Specification.ArgMinLayerParams = class ArgMinLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArgMinLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.removeDim = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArgMinLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"removeDim\":\n                    message.removeDim = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ArgMinLayerParams.prototype.axis = 0n;\nCoreML.Specification.ArgMinLayerParams.prototype.removeDim = false;\n\nCoreML.Specification.SplitNDLayerParams = class SplitNDLayerParams {\n\n    constructor() {\n        this.splitSizes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SplitNDLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.numSplits = reader.uint64();\n                    break;\n                case 3:\n                    message.splitSizes = reader.array(message.splitSizes, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SplitNDLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"numSplits\":\n                    message.numSplits = reader.uint64();\n                    break;\n                case \"splitSizes\":\n                    reader.array(message.splitSizes, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SplitNDLayerParams.prototype.axis = 0n;\nCoreML.Specification.SplitNDLayerParams.prototype.numSplits = 0n;\n\nCoreML.Specification.CeilLayerParams = class CeilLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CeilLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CeilLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RoundLayerParams = class RoundLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RoundLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RoundLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.FloorLayerParams = class FloorLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.FloorLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.FloorLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SignLayerParams = class SignLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SignLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SignLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ClipLayerParams = class ClipLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ClipLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.minVal = reader.float();\n                    break;\n                case 2:\n                    message.maxVal = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ClipLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"minVal\":\n                    message.minVal = reader.float();\n                    break;\n                case \"maxVal\":\n                    message.maxVal = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ClipLayerParams.prototype.minVal = 0;\nCoreML.Specification.ClipLayerParams.prototype.maxVal = 0;\n\nCoreML.Specification.SliceStaticLayerParams = class SliceStaticLayerParams {\n\n    constructor() {\n        this.beginIds = [];\n        this.beginMasks = [];\n        this.endIds = [];\n        this.endMasks = [];\n        this.strides = [];\n        this.squeezeMasks = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SliceStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.beginIds = reader.array(message.beginIds, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.beginMasks = reader.array(message.beginMasks, () => reader.bool(), tag);\n                    break;\n                case 3:\n                    message.endIds = reader.array(message.endIds, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.endMasks = reader.array(message.endMasks, () => reader.bool(), tag);\n                    break;\n                case 5:\n                    message.strides = reader.array(message.strides, () => reader.int64(), tag);\n                    break;\n                case 6:\n                    message.squeezeMasks = reader.array(message.squeezeMasks, () => reader.bool(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SliceStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"beginIds\":\n                    reader.array(message.beginIds, () => reader.int64());\n                    break;\n                case \"beginMasks\":\n                    reader.array(message.beginMasks, () => reader.bool());\n                    break;\n                case \"endIds\":\n                    reader.array(message.endIds, () => reader.int64());\n                    break;\n                case \"endMasks\":\n                    reader.array(message.endMasks, () => reader.bool());\n                    break;\n                case \"strides\":\n                    reader.array(message.strides, () => reader.int64());\n                    break;\n                case \"squeezeMasks\":\n                    reader.array(message.squeezeMasks, () => reader.bool());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SliceDynamicLayerParams = class SliceDynamicLayerParams {\n\n    constructor() {\n        this.beginMasks = [];\n        this.endIds = [];\n        this.endMasks = [];\n        this.strides = [];\n        this.squeezeMasks = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SliceDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.beginMasks = reader.array(message.beginMasks, () => reader.bool(), tag);\n                    break;\n                case 3:\n                    message.endIds = reader.array(message.endIds, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.endMasks = reader.array(message.endMasks, () => reader.bool(), tag);\n                    break;\n                case 5:\n                    message.strides = reader.array(message.strides, () => reader.int64(), tag);\n                    break;\n                case 6:\n                    message.squeezeMasks = reader.array(message.squeezeMasks, () => reader.bool(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SliceDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"beginMasks\":\n                    reader.array(message.beginMasks, () => reader.bool());\n                    break;\n                case \"endIds\":\n                    reader.array(message.endIds, () => reader.int64());\n                    break;\n                case \"endMasks\":\n                    reader.array(message.endMasks, () => reader.bool());\n                    break;\n                case \"strides\":\n                    reader.array(message.strides, () => reader.int64());\n                    break;\n                case \"squeezeMasks\":\n                    reader.array(message.squeezeMasks, () => reader.bool());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TileLayerParams = class TileLayerParams {\n\n    constructor() {\n        this.reps = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TileLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.reps = reader.array(message.reps, () => reader.uint64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TileLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"reps\":\n                    reader.array(message.reps, () => reader.uint64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GetShapeLayerParams = class GetShapeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GetShapeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GetShapeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ErfLayerParams = class ErfLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ErfLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ErfLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GeluLayerParams = class GeluLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.GeluLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mode = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.GeluLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mode\":\n                    message.mode = reader.enum(CoreML.Specification.GeluLayerParams.GeluMode);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.GeluLayerParams.prototype.mode = 0;\n\nCoreML.Specification.GeluLayerParams.GeluMode = {\n    \"EXACT\": 0,\n    \"TANH_APPROXIMATION\": 1,\n    \"SIGMOID_APPROXIMATION\": 2\n};\n\nCoreML.Specification.RangeStaticLayerParams = class RangeStaticLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RangeStaticLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.endValue = reader.float();\n                    break;\n                case 2:\n                    message.startValue = reader.float();\n                    break;\n                case 3:\n                    message.stepSizeValue = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RangeStaticLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"endValue\":\n                    message.endValue = reader.float();\n                    break;\n                case \"startValue\":\n                    message.startValue = reader.float();\n                    break;\n                case \"stepSizeValue\":\n                    message.stepSizeValue = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RangeStaticLayerParams.prototype.endValue = 0;\nCoreML.Specification.RangeStaticLayerParams.prototype.startValue = 0;\nCoreML.Specification.RangeStaticLayerParams.prototype.stepSizeValue = 0;\n\nCoreML.Specification.RangeDynamicLayerParams = class RangeDynamicLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RangeDynamicLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.startValue = reader.float();\n                    break;\n                case 3:\n                    message.stepSizeValue = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RangeDynamicLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"startValue\":\n                    message.startValue = reader.float();\n                    break;\n                case \"stepSizeValue\":\n                    message.stepSizeValue = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RangeDynamicLayerParams.prototype.startValue = 0;\nCoreML.Specification.RangeDynamicLayerParams.prototype.stepSizeValue = 0;\n\nCoreML.Specification.SlidingWindowsLayerParams = class SlidingWindowsLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SlidingWindowsLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.windowSize = reader.uint64();\n                    break;\n                case 3:\n                    message.step = reader.uint64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SlidingWindowsLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"windowSize\":\n                    message.windowSize = reader.uint64();\n                    break;\n                case \"step\":\n                    message.step = reader.uint64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SlidingWindowsLayerParams.prototype.axis = 0n;\nCoreML.Specification.SlidingWindowsLayerParams.prototype.windowSize = 0n;\nCoreML.Specification.SlidingWindowsLayerParams.prototype.step = 0n;\n\nCoreML.Specification.LayerNormalizationLayerParams = class LayerNormalizationLayerParams {\n\n    constructor() {\n        this.normalizedShape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LayerNormalizationLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.normalizedShape = reader.array(message.normalizedShape, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                case 3:\n                    message.gamma = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.beta = CoreML.Specification.WeightParams.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LayerNormalizationLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"normalizedShape\":\n                    reader.array(message.normalizedShape, () => reader.int64());\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"gamma\":\n                    message.gamma = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                case \"beta\":\n                    message.beta = CoreML.Specification.WeightParams.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LayerNormalizationLayerParams.prototype.eps = 0;\nCoreML.Specification.LayerNormalizationLayerParams.prototype.gamma = null;\nCoreML.Specification.LayerNormalizationLayerParams.prototype.beta = null;\n\nCoreML.Specification.NonMaximumSuppressionLayerParams = class NonMaximumSuppressionLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NonMaximumSuppressionLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.iouThreshold = reader.float();\n                    break;\n                case 2:\n                    message.scoreThreshold = reader.float();\n                    break;\n                case 3:\n                    message.maxBoxes = reader.uint64();\n                    break;\n                case 4:\n                    message.perClassSuppression = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NonMaximumSuppressionLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"iouThreshold\":\n                    message.iouThreshold = reader.float();\n                    break;\n                case \"scoreThreshold\":\n                    message.scoreThreshold = reader.float();\n                    break;\n                case \"maxBoxes\":\n                    message.maxBoxes = reader.uint64();\n                    break;\n                case \"perClassSuppression\":\n                    message.perClassSuppression = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NonMaximumSuppressionLayerParams.prototype.iouThreshold = 0;\nCoreML.Specification.NonMaximumSuppressionLayerParams.prototype.scoreThreshold = 0;\nCoreML.Specification.NonMaximumSuppressionLayerParams.prototype.maxBoxes = 0n;\nCoreML.Specification.NonMaximumSuppressionLayerParams.prototype.perClassSuppression = false;\n\nCoreML.Specification.ClampedReLULayerParams = class ClampedReLULayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ClampedReLULayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ClampedReLULayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ClampedReLULayerParams.prototype.alpha = 0;\nCoreML.Specification.ClampedReLULayerParams.prototype.beta = 0;\n\nCoreML.Specification.ArgSortLayerParams = class ArgSortLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ArgSortLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.descending = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ArgSortLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"descending\":\n                    message.descending = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ArgSortLayerParams.prototype.axis = 0n;\nCoreML.Specification.ArgSortLayerParams.prototype.descending = false;\n\nCoreML.Specification.SliceBySizeLayerParams = class SliceBySizeLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SliceBySizeLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.size = reader.int64();\n                    break;\n                case 3:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SliceBySizeLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"size\":\n                    message.size = reader.int64();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SliceBySizeLayerParams.prototype.size = 0n;\nCoreML.Specification.SliceBySizeLayerParams.prototype.axis = 0n;\n\nCoreML.Specification.NeuralNetworkClassifier = class NeuralNetworkClassifier {\n\n    constructor() {\n        this.layers = [];\n        this.preprocessing = [];\n    }\n\n    get ClassLabels() {\n        CoreML.Specification.NeuralNetworkClassifier.ClassLabelsSet = CoreML.Specification.NeuralNetworkClassifier.ClassLabelsSet || new Set([\"stringClassLabels\", \"int64ClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NeuralNetworkClassifier.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetworkClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.layers.push(CoreML.Specification.NeuralNetworkLayer.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.preprocessing.push(CoreML.Specification.NeuralNetworkPreprocessing.decode(reader, reader.uint32()));\n                    break;\n                case 5:\n                    message.arrayInputShapeMapping = reader.int32();\n                    break;\n                case 6:\n                    message.imageInputShapeMapping = reader.int32();\n                    break;\n                case 10:\n                    message.updateParams = CoreML.Specification.NetworkUpdateParameters.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                case 200:\n                    message.labelProbabilityLayerName = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetworkClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"layers\":\n                    message.layers.push(CoreML.Specification.NeuralNetworkLayer.decodeText(reader));\n                    break;\n                case \"preprocessing\":\n                    message.preprocessing.push(CoreML.Specification.NeuralNetworkPreprocessing.decodeText(reader));\n                    break;\n                case \"arrayInputShapeMapping\":\n                    message.arrayInputShapeMapping = reader.enum(CoreML.Specification.NeuralNetworkMultiArrayShapeMapping);\n                    break;\n                case \"imageInputShapeMapping\":\n                    message.imageInputShapeMapping = reader.enum(CoreML.Specification.NeuralNetworkImageShapeMapping);\n                    break;\n                case \"updateParams\":\n                    message.updateParams = CoreML.Specification.NetworkUpdateParameters.decodeText(reader);\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ClassLabels\":\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                case \"labelProbabilityLayerName\":\n                    message.labelProbabilityLayerName = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetworkClassifier.prototype.arrayInputShapeMapping = 0;\nCoreML.Specification.NeuralNetworkClassifier.prototype.imageInputShapeMapping = 0;\nCoreML.Specification.NeuralNetworkClassifier.prototype.updateParams = null;\nCoreML.Specification.NeuralNetworkClassifier.prototype.labelProbabilityLayerName = \"\";\n\nCoreML.Specification.OneHotLayerParams = class OneHotLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.OneHotLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.oneHotVectorSize = reader.uint64();\n                    break;\n                case 2:\n                    message.axis = reader.int64();\n                    break;\n                case 3:\n                    message.onValue = reader.float();\n                    break;\n                case 4:\n                    message.offValue = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.OneHotLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"oneHotVectorSize\":\n                    message.oneHotVectorSize = reader.uint64();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"onValue\":\n                    message.onValue = reader.float();\n                    break;\n                case \"offValue\":\n                    message.offValue = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.OneHotLayerParams.prototype.oneHotVectorSize = 0n;\nCoreML.Specification.OneHotLayerParams.prototype.axis = 0n;\nCoreML.Specification.OneHotLayerParams.prototype.onValue = 0;\nCoreML.Specification.OneHotLayerParams.prototype.offValue = 0;\n\nCoreML.Specification.CumSumLayerParams = class CumSumLayerParams {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CumSumLayerParams();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.excludeFinalSum = reader.bool();\n                    break;\n                case 3:\n                    message.reverse = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CumSumLayerParams();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"excludeFinalSum\":\n                    message.excludeFinalSum = reader.bool();\n                    break;\n                case \"reverse\":\n                    message.reverse = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CumSumLayerParams.prototype.axis = 0n;\nCoreML.Specification.CumSumLayerParams.prototype.excludeFinalSum = false;\nCoreML.Specification.CumSumLayerParams.prototype.reverse = false;\n\nCoreML.Specification.NeuralNetworkRegressor = class NeuralNetworkRegressor {\n\n    constructor() {\n        this.layers = [];\n        this.preprocessing = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NeuralNetworkRegressor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.layers.push(CoreML.Specification.NeuralNetworkLayer.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.preprocessing.push(CoreML.Specification.NeuralNetworkPreprocessing.decode(reader, reader.uint32()));\n                    break;\n                case 5:\n                    message.arrayInputShapeMapping = reader.int32();\n                    break;\n                case 6:\n                    message.imageInputShapeMapping = reader.int32();\n                    break;\n                case 10:\n                    message.updateParams = CoreML.Specification.NetworkUpdateParameters.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NeuralNetworkRegressor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"layers\":\n                    message.layers.push(CoreML.Specification.NeuralNetworkLayer.decodeText(reader));\n                    break;\n                case \"preprocessing\":\n                    message.preprocessing.push(CoreML.Specification.NeuralNetworkPreprocessing.decodeText(reader));\n                    break;\n                case \"arrayInputShapeMapping\":\n                    message.arrayInputShapeMapping = reader.enum(CoreML.Specification.NeuralNetworkMultiArrayShapeMapping);\n                    break;\n                case \"imageInputShapeMapping\":\n                    message.imageInputShapeMapping = reader.enum(CoreML.Specification.NeuralNetworkImageShapeMapping);\n                    break;\n                case \"updateParams\":\n                    message.updateParams = CoreML.Specification.NetworkUpdateParameters.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NeuralNetworkRegressor.prototype.arrayInputShapeMapping = 0;\nCoreML.Specification.NeuralNetworkRegressor.prototype.imageInputShapeMapping = 0;\nCoreML.Specification.NeuralNetworkRegressor.prototype.updateParams = null;\n\nCoreML.Specification.NetworkUpdateParameters = class NetworkUpdateParameters {\n\n    constructor() {\n        this.lossLayers = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NetworkUpdateParameters();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lossLayers.push(CoreML.Specification.LossLayer.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.optimizer = CoreML.Specification.Optimizer.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.epochs = CoreML.Specification.Int64Parameter.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.shuffle = CoreML.Specification.BoolParameter.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.seed = CoreML.Specification.Int64Parameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NetworkUpdateParameters();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lossLayers\":\n                    message.lossLayers.push(CoreML.Specification.LossLayer.decodeText(reader));\n                    break;\n                case \"optimizer\":\n                    message.optimizer = CoreML.Specification.Optimizer.decodeText(reader);\n                    break;\n                case \"epochs\":\n                    message.epochs = CoreML.Specification.Int64Parameter.decodeText(reader);\n                    break;\n                case \"shuffle\":\n                    message.shuffle = CoreML.Specification.BoolParameter.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = CoreML.Specification.Int64Parameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NetworkUpdateParameters.prototype.optimizer = null;\nCoreML.Specification.NetworkUpdateParameters.prototype.epochs = null;\nCoreML.Specification.NetworkUpdateParameters.prototype.shuffle = null;\nCoreML.Specification.NetworkUpdateParameters.prototype.seed = null;\n\nCoreML.Specification.LossLayer = class LossLayer {\n\n    get LossLayerType() {\n        CoreML.Specification.LossLayer.LossLayerTypeSet = CoreML.Specification.LossLayer.LossLayerTypeSet || new Set([\"categoricalCrossEntropyLossLayer\", \"meanSquaredErrorLossLayer\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.LossLayer.LossLayerTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LossLayer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 10:\n                    message.categoricalCrossEntropyLossLayer = CoreML.Specification.CategoricalCrossEntropyLossLayer.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.meanSquaredErrorLossLayer = CoreML.Specification.MeanSquaredErrorLossLayer.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LossLayer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"categoricalCrossEntropyLossLayer\":\n                    message.categoricalCrossEntropyLossLayer = CoreML.Specification.CategoricalCrossEntropyLossLayer.decodeText(reader);\n                    break;\n                case \"meanSquaredErrorLossLayer\":\n                    message.meanSquaredErrorLossLayer = CoreML.Specification.MeanSquaredErrorLossLayer.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LossLayer.prototype.name = \"\";\n\nCoreML.Specification.CategoricalCrossEntropyLossLayer = class CategoricalCrossEntropyLossLayer {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.CategoricalCrossEntropyLossLayer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.input = reader.string();\n                    break;\n                case 2:\n                    message.target = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.CategoricalCrossEntropyLossLayer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"input\":\n                    message.input = reader.string();\n                    break;\n                case \"target\":\n                    message.target = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.CategoricalCrossEntropyLossLayer.prototype.input = \"\";\nCoreML.Specification.CategoricalCrossEntropyLossLayer.prototype.target = \"\";\n\nCoreML.Specification.MeanSquaredErrorLossLayer = class MeanSquaredErrorLossLayer {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.MeanSquaredErrorLossLayer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.input = reader.string();\n                    break;\n                case 2:\n                    message.target = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.MeanSquaredErrorLossLayer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"input\":\n                    message.input = reader.string();\n                    break;\n                case \"target\":\n                    message.target = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.MeanSquaredErrorLossLayer.prototype.input = \"\";\nCoreML.Specification.MeanSquaredErrorLossLayer.prototype.target = \"\";\n\nCoreML.Specification.Optimizer = class Optimizer {\n\n    get OptimizerType() {\n        CoreML.Specification.Optimizer.OptimizerTypeSet = CoreML.Specification.Optimizer.OptimizerTypeSet || new Set([\"sgdOptimizer\", \"adamOptimizer\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.Optimizer.OptimizerTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Optimizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 10:\n                    message.sgdOptimizer = CoreML.Specification.SGDOptimizer.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.adamOptimizer = CoreML.Specification.AdamOptimizer.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Optimizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sgdOptimizer\":\n                    message.sgdOptimizer = CoreML.Specification.SGDOptimizer.decodeText(reader);\n                    break;\n                case \"adamOptimizer\":\n                    message.adamOptimizer = CoreML.Specification.AdamOptimizer.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SGDOptimizer = class SGDOptimizer {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SGDOptimizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.learningRate = CoreML.Specification.DoubleParameter.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.miniBatchSize = CoreML.Specification.Int64Parameter.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.momentum = CoreML.Specification.DoubleParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SGDOptimizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"learningRate\":\n                    message.learningRate = CoreML.Specification.DoubleParameter.decodeText(reader);\n                    break;\n                case \"miniBatchSize\":\n                    message.miniBatchSize = CoreML.Specification.Int64Parameter.decodeText(reader);\n                    break;\n                case \"momentum\":\n                    message.momentum = CoreML.Specification.DoubleParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SGDOptimizer.prototype.learningRate = null;\nCoreML.Specification.SGDOptimizer.prototype.miniBatchSize = null;\nCoreML.Specification.SGDOptimizer.prototype.momentum = null;\n\nCoreML.Specification.AdamOptimizer = class AdamOptimizer {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.AdamOptimizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.learningRate = CoreML.Specification.DoubleParameter.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.miniBatchSize = CoreML.Specification.Int64Parameter.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.beta1 = CoreML.Specification.DoubleParameter.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.beta2 = CoreML.Specification.DoubleParameter.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.eps = CoreML.Specification.DoubleParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.AdamOptimizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"learningRate\":\n                    message.learningRate = CoreML.Specification.DoubleParameter.decodeText(reader);\n                    break;\n                case \"miniBatchSize\":\n                    message.miniBatchSize = CoreML.Specification.Int64Parameter.decodeText(reader);\n                    break;\n                case \"beta1\":\n                    message.beta1 = CoreML.Specification.DoubleParameter.decodeText(reader);\n                    break;\n                case \"beta2\":\n                    message.beta2 = CoreML.Specification.DoubleParameter.decodeText(reader);\n                    break;\n                case \"eps\":\n                    message.eps = CoreML.Specification.DoubleParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.AdamOptimizer.prototype.learningRate = null;\nCoreML.Specification.AdamOptimizer.prototype.miniBatchSize = null;\nCoreML.Specification.AdamOptimizer.prototype.beta1 = null;\nCoreML.Specification.AdamOptimizer.prototype.beta2 = null;\nCoreML.Specification.AdamOptimizer.prototype.eps = null;\n\nCoreML.Specification.Normalizer = class Normalizer {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Normalizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.normType = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Normalizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"normType\":\n                    message.normType = reader.enum(CoreML.Specification.Normalizer.NormType);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Normalizer.prototype.normType = 0;\n\nCoreML.Specification.Normalizer.NormType = {\n    \"LMax\": 0,\n    \"L1\": 1,\n    \"L2\": 2\n};\n\nCoreML.Specification.OneHotEncoder = class OneHotEncoder {\n\n    get CategoryType() {\n        CoreML.Specification.OneHotEncoder.CategoryTypeSet = CoreML.Specification.OneHotEncoder.CategoryTypeSet || new Set([\"stringCategories\", \"int64Categories\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.OneHotEncoder.CategoryTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.OneHotEncoder();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.stringCategories = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.int64Categories = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.outputSparse = reader.bool();\n                    break;\n                case 11:\n                    message.handleUnknown = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.OneHotEncoder();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"stringCategories\":\n                    message.stringCategories = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64Categories\":\n                    message.int64Categories = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                case \"outputSparse\":\n                    message.outputSparse = reader.bool();\n                    break;\n                case \"handleUnknown\":\n                    message.handleUnknown = reader.enum(CoreML.Specification.OneHotEncoder.HandleUnknown);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.OneHotEncoder.prototype.outputSparse = false;\nCoreML.Specification.OneHotEncoder.prototype.handleUnknown = 0;\n\nCoreML.Specification.OneHotEncoder.HandleUnknown = {\n    \"ErrorOnUnknown\": 0,\n    \"IgnoreUnknown\": 1\n};\n\nCoreML.Specification.Scaler = class Scaler {\n\n    constructor() {\n        this.shiftValue = [];\n        this.scaleValue = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Scaler();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shiftValue = reader.doubles(message.shiftValue, tag);\n                    break;\n                case 2:\n                    message.scaleValue = reader.doubles(message.scaleValue, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Scaler();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shiftValue\":\n                    reader.array(message.shiftValue, () => reader.double());\n                    break;\n                case \"scaleValue\":\n                    reader.array(message.scaleValue, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NonMaximumSuppression = class NonMaximumSuppression {\n\n    get SuppressionMethod() {\n        CoreML.Specification.NonMaximumSuppression.SuppressionMethodSet = CoreML.Specification.NonMaximumSuppression.SuppressionMethodSet || new Set([\"pickTop\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NonMaximumSuppression.SuppressionMethodSet.has(key) && this[key] !== null);\n    }\n\n    get ClassLabels() {\n        CoreML.Specification.NonMaximumSuppression.ClassLabelsSet = CoreML.Specification.NonMaximumSuppression.ClassLabelsSet || new Set([\"stringClassLabels\", \"int64ClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.NonMaximumSuppression.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NonMaximumSuppression();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.pickTop = CoreML.Specification.NonMaximumSuppression.PickTop.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                case 110:\n                    message.iouThreshold = reader.double();\n                    break;\n                case 111:\n                    message.confidenceThreshold = reader.double();\n                    break;\n                case 200:\n                    message.confidenceInputFeatureName = reader.string();\n                    break;\n                case 201:\n                    message.coordinatesInputFeatureName = reader.string();\n                    break;\n                case 202:\n                    message.iouThresholdInputFeatureName = reader.string();\n                    break;\n                case 203:\n                    message.confidenceThresholdInputFeatureName = reader.string();\n                    break;\n                case 210:\n                    message.confidenceOutputFeatureName = reader.string();\n                    break;\n                case 211:\n                    message.coordinatesOutputFeatureName = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NonMaximumSuppression();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"pickTop\":\n                    message.pickTop = CoreML.Specification.NonMaximumSuppression.PickTop.decodeText(reader);\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ClassLabels\":\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                case \"iouThreshold\":\n                    message.iouThreshold = reader.double();\n                    break;\n                case \"confidenceThreshold\":\n                    message.confidenceThreshold = reader.double();\n                    break;\n                case \"confidenceInputFeatureName\":\n                    message.confidenceInputFeatureName = reader.string();\n                    break;\n                case \"coordinatesInputFeatureName\":\n                    message.coordinatesInputFeatureName = reader.string();\n                    break;\n                case \"iouThresholdInputFeatureName\":\n                    message.iouThresholdInputFeatureName = reader.string();\n                    break;\n                case \"confidenceThresholdInputFeatureName\":\n                    message.confidenceThresholdInputFeatureName = reader.string();\n                    break;\n                case \"confidenceOutputFeatureName\":\n                    message.confidenceOutputFeatureName = reader.string();\n                    break;\n                case \"coordinatesOutputFeatureName\":\n                    message.coordinatesOutputFeatureName = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NonMaximumSuppression.prototype.iouThreshold = 0;\nCoreML.Specification.NonMaximumSuppression.prototype.confidenceThreshold = 0;\nCoreML.Specification.NonMaximumSuppression.prototype.confidenceInputFeatureName = \"\";\nCoreML.Specification.NonMaximumSuppression.prototype.coordinatesInputFeatureName = \"\";\nCoreML.Specification.NonMaximumSuppression.prototype.iouThresholdInputFeatureName = \"\";\nCoreML.Specification.NonMaximumSuppression.prototype.confidenceThresholdInputFeatureName = \"\";\nCoreML.Specification.NonMaximumSuppression.prototype.confidenceOutputFeatureName = \"\";\nCoreML.Specification.NonMaximumSuppression.prototype.coordinatesOutputFeatureName = \"\";\n\nCoreML.Specification.NonMaximumSuppression.PickTop = class PickTop {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.NonMaximumSuppression.PickTop();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.perClass = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.NonMaximumSuppression.PickTop();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"perClass\":\n                    message.perClass = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.NonMaximumSuppression.PickTop.prototype.perClass = false;\n\nCoreML.Specification.LinearKernel = class LinearKernel {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LinearKernel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LinearKernel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RBFKernel = class RBFKernel {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.RBFKernel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.gamma = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.RBFKernel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"gamma\":\n                    message.gamma = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.RBFKernel.prototype.gamma = 0;\n\nCoreML.Specification.PolyKernel = class PolyKernel {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.PolyKernel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.degree = reader.int32();\n                    break;\n                case 2:\n                    message.c = reader.double();\n                    break;\n                case 3:\n                    message.gamma = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.PolyKernel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"degree\":\n                    message.degree = reader.int32();\n                    break;\n                case \"c\":\n                    message.c = reader.double();\n                    break;\n                case \"gamma\":\n                    message.gamma = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.PolyKernel.prototype.degree = 0;\nCoreML.Specification.PolyKernel.prototype.c = 0;\nCoreML.Specification.PolyKernel.prototype.gamma = 0;\n\nCoreML.Specification.SigmoidKernel = class SigmoidKernel {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SigmoidKernel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.gamma = reader.double();\n                    break;\n                case 2:\n                    message.c = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SigmoidKernel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"gamma\":\n                    message.gamma = reader.double();\n                    break;\n                case \"c\":\n                    message.c = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SigmoidKernel.prototype.gamma = 0;\nCoreML.Specification.SigmoidKernel.prototype.c = 0;\n\nCoreML.Specification.Kernel = class Kernel {\n\n    get kernel() {\n        CoreML.Specification.Kernel.kernelSet = CoreML.Specification.Kernel.kernelSet || new Set([\"linearKernel\", \"rbfKernel\", \"polyKernel\", \"sigmoidKernel\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.Kernel.kernelSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Kernel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.linearKernel = CoreML.Specification.LinearKernel.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.rbfKernel = CoreML.Specification.RBFKernel.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.polyKernel = CoreML.Specification.PolyKernel.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.sigmoidKernel = CoreML.Specification.SigmoidKernel.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Kernel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"linearKernel\":\n                    message.linearKernel = CoreML.Specification.LinearKernel.decodeText(reader);\n                    break;\n                case \"rbfKernel\":\n                    message.rbfKernel = CoreML.Specification.RBFKernel.decodeText(reader);\n                    break;\n                case \"polyKernel\":\n                    message.polyKernel = CoreML.Specification.PolyKernel.decodeText(reader);\n                    break;\n                case \"sigmoidKernel\":\n                    message.sigmoidKernel = CoreML.Specification.SigmoidKernel.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SparseNode = class SparseNode {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SparseNode();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.index = reader.int32();\n                    break;\n                case 2:\n                    message.value = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SparseNode();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"index\":\n                    message.index = reader.int32();\n                    break;\n                case \"value\":\n                    message.value = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SparseNode.prototype.index = 0;\nCoreML.Specification.SparseNode.prototype.value = 0;\n\nCoreML.Specification.SparseVector = class SparseVector {\n\n    constructor() {\n        this.nodes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SparseVector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.nodes.push(CoreML.Specification.SparseNode.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SparseVector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"nodes\":\n                    message.nodes.push(CoreML.Specification.SparseNode.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SparseSupportVectors = class SparseSupportVectors {\n\n    constructor() {\n        this.vectors = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SparseSupportVectors();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vectors.push(CoreML.Specification.SparseVector.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SparseSupportVectors();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vectors\":\n                    message.vectors.push(CoreML.Specification.SparseVector.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DenseVector = class DenseVector {\n\n    constructor() {\n        this.values = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DenseVector();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = reader.doubles(message.values, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DenseVector();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    reader.array(message.values, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.DenseSupportVectors = class DenseSupportVectors {\n\n    constructor() {\n        this.vectors = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.DenseSupportVectors();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.vectors.push(CoreML.Specification.DenseVector.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.DenseSupportVectors();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"vectors\":\n                    message.vectors.push(CoreML.Specification.DenseVector.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.Coefficients = class Coefficients {\n\n    constructor() {\n        this.alpha = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.Coefficients();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.doubles(message.alpha, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.Coefficients();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    reader.array(message.alpha, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SupportVectorRegressor = class SupportVectorRegressor {\n\n    get supportVectors() {\n        CoreML.Specification.SupportVectorRegressor.supportVectorsSet = CoreML.Specification.SupportVectorRegressor.supportVectorsSet || new Set([\"sparseSupportVectors\", \"denseSupportVectors\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.SupportVectorRegressor.supportVectorsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SupportVectorRegressor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = CoreML.Specification.Kernel.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.sparseSupportVectors = CoreML.Specification.SparseSupportVectors.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.denseSupportVectors = CoreML.Specification.DenseSupportVectors.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.coefficients = CoreML.Specification.Coefficients.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.rho = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SupportVectorRegressor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = CoreML.Specification.Kernel.decodeText(reader);\n                    break;\n                case \"sparseSupportVectors\":\n                    message.sparseSupportVectors = CoreML.Specification.SparseSupportVectors.decodeText(reader);\n                    break;\n                case \"denseSupportVectors\":\n                    message.denseSupportVectors = CoreML.Specification.DenseSupportVectors.decodeText(reader);\n                    break;\n                case \"coefficients\":\n                    message.coefficients = CoreML.Specification.Coefficients.decodeText(reader);\n                    break;\n                case \"rho\":\n                    message.rho = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SupportVectorRegressor.prototype.kernel = null;\nCoreML.Specification.SupportVectorRegressor.prototype.coefficients = null;\nCoreML.Specification.SupportVectorRegressor.prototype.rho = 0;\n\nCoreML.Specification.SupportVectorClassifier = class SupportVectorClassifier {\n\n    constructor() {\n        this.numberOfSupportVectorsPerClass = [];\n        this.coefficients = [];\n        this.rho = [];\n        this.probA = [];\n        this.probB = [];\n    }\n\n    get supportVectors() {\n        CoreML.Specification.SupportVectorClassifier.supportVectorsSet = CoreML.Specification.SupportVectorClassifier.supportVectorsSet || new Set([\"sparseSupportVectors\", \"denseSupportVectors\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.SupportVectorClassifier.supportVectorsSet.has(key) && this[key] !== null);\n    }\n\n    get ClassLabels() {\n        CoreML.Specification.SupportVectorClassifier.ClassLabelsSet = CoreML.Specification.SupportVectorClassifier.ClassLabelsSet || new Set([\"stringClassLabels\", \"int64ClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.SupportVectorClassifier.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.SupportVectorClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = CoreML.Specification.Kernel.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.numberOfSupportVectorsPerClass = reader.array(message.numberOfSupportVectorsPerClass, () => reader.int32(), tag);\n                    break;\n                case 3:\n                    message.sparseSupportVectors = CoreML.Specification.SparseSupportVectors.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.denseSupportVectors = CoreML.Specification.DenseSupportVectors.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.coefficients.push(CoreML.Specification.Coefficients.decode(reader, reader.uint32()));\n                    break;\n                case 6:\n                    message.rho = reader.doubles(message.rho, tag);\n                    break;\n                case 7:\n                    message.probA = reader.doubles(message.probA, tag);\n                    break;\n                case 8:\n                    message.probB = reader.doubles(message.probB, tag);\n                    break;\n                case 100:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.SupportVectorClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = CoreML.Specification.Kernel.decodeText(reader);\n                    break;\n                case \"numberOfSupportVectorsPerClass\":\n                    reader.array(message.numberOfSupportVectorsPerClass, () => reader.int32());\n                    break;\n                case \"sparseSupportVectors\":\n                    message.sparseSupportVectors = CoreML.Specification.SparseSupportVectors.decodeText(reader);\n                    break;\n                case \"denseSupportVectors\":\n                    message.denseSupportVectors = CoreML.Specification.DenseSupportVectors.decodeText(reader);\n                    break;\n                case \"coefficients\":\n                    message.coefficients.push(CoreML.Specification.Coefficients.decodeText(reader));\n                    break;\n                case \"rho\":\n                    reader.array(message.rho, () => reader.double());\n                    break;\n                case \"probA\":\n                    reader.array(message.probA, () => reader.double());\n                    break;\n                case \"probB\":\n                    reader.array(message.probB, () => reader.double());\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ClassLabels\":\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.SupportVectorClassifier.prototype.kernel = null;\n\nCoreML.Specification.TreeEnsemblePostEvaluationTransform = {\n    \"NoTransform\": 0,\n    \"Classification_SoftMax\": 1,\n    \"Regression_Logistic\": 2,\n    \"Classification_SoftMaxWithZeroClassReference\": 3\n};\n\nCoreML.Specification.TreeEnsembleParameters = class TreeEnsembleParameters {\n\n    constructor() {\n        this.nodes = [];\n        this.basePredictionValue = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TreeEnsembleParameters();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.nodes.push(CoreML.Specification.TreeEnsembleParameters.TreeNode.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.numPredictionDimensions = reader.uint64();\n                    break;\n                case 3:\n                    message.basePredictionValue = reader.doubles(message.basePredictionValue, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TreeEnsembleParameters();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"nodes\":\n                    message.nodes.push(CoreML.Specification.TreeEnsembleParameters.TreeNode.decodeText(reader));\n                    break;\n                case \"numPredictionDimensions\":\n                    message.numPredictionDimensions = reader.uint64();\n                    break;\n                case \"basePredictionValue\":\n                    reader.array(message.basePredictionValue, () => reader.double());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TreeEnsembleParameters.prototype.numPredictionDimensions = 0n;\n\nCoreML.Specification.TreeEnsembleParameters.TreeNode = class TreeNode {\n\n    constructor() {\n        this.evaluationInfo = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TreeEnsembleParameters.TreeNode();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.treeId = reader.uint64();\n                    break;\n                case 2:\n                    message.nodeId = reader.uint64();\n                    break;\n                case 3:\n                    message.nodeBehavior = reader.int32();\n                    break;\n                case 10:\n                    message.branchFeatureIndex = reader.uint64();\n                    break;\n                case 11:\n                    message.branchFeatureValue = reader.double();\n                    break;\n                case 12:\n                    message.trueChildNodeId = reader.uint64();\n                    break;\n                case 13:\n                    message.falseChildNodeId = reader.uint64();\n                    break;\n                case 14:\n                    message.missingValueTracksTrueChild = reader.bool();\n                    break;\n                case 20:\n                    message.evaluationInfo.push(CoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo.decode(reader, reader.uint32()));\n                    break;\n                case 30:\n                    message.relativeHitRate = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TreeEnsembleParameters.TreeNode();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"treeId\":\n                    message.treeId = reader.uint64();\n                    break;\n                case \"nodeId\":\n                    message.nodeId = reader.uint64();\n                    break;\n                case \"nodeBehavior\":\n                    message.nodeBehavior = reader.enum(CoreML.Specification.TreeEnsembleParameters.TreeNode.TreeNodeBehavior);\n                    break;\n                case \"branchFeatureIndex\":\n                    message.branchFeatureIndex = reader.uint64();\n                    break;\n                case \"branchFeatureValue\":\n                    message.branchFeatureValue = reader.double();\n                    break;\n                case \"trueChildNodeId\":\n                    message.trueChildNodeId = reader.uint64();\n                    break;\n                case \"falseChildNodeId\":\n                    message.falseChildNodeId = reader.uint64();\n                    break;\n                case \"missingValueTracksTrueChild\":\n                    message.missingValueTracksTrueChild = reader.bool();\n                    break;\n                case \"evaluationInfo\":\n                    message.evaluationInfo.push(CoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo.decodeText(reader));\n                    break;\n                case \"relativeHitRate\":\n                    message.relativeHitRate = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.treeId = 0n;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.nodeId = 0n;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.nodeBehavior = 0;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.branchFeatureIndex = 0n;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.branchFeatureValue = 0;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.trueChildNodeId = 0n;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.falseChildNodeId = 0n;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.missingValueTracksTrueChild = false;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.prototype.relativeHitRate = 0;\n\nCoreML.Specification.TreeEnsembleParameters.TreeNode.TreeNodeBehavior = {\n    \"BranchOnValueLessThanEqual\": 0,\n    \"BranchOnValueLessThan\": 1,\n    \"BranchOnValueGreaterThanEqual\": 2,\n    \"BranchOnValueGreaterThan\": 3,\n    \"BranchOnValueEqual\": 4,\n    \"BranchOnValueNotEqual\": 5,\n    \"LeafNode\": 6\n};\n\nCoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo = class EvaluationInfo {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.evaluationIndex = reader.uint64();\n                    break;\n                case 2:\n                    message.evaluationValue = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"evaluationIndex\":\n                    message.evaluationIndex = reader.uint64();\n                    break;\n                case \"evaluationValue\":\n                    message.evaluationValue = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo.prototype.evaluationIndex = 0n;\nCoreML.Specification.TreeEnsembleParameters.TreeNode.EvaluationInfo.prototype.evaluationValue = 0;\n\nCoreML.Specification.TreeEnsembleClassifier = class TreeEnsembleClassifier {\n\n    get ClassLabels() {\n        CoreML.Specification.TreeEnsembleClassifier.ClassLabelsSet = CoreML.Specification.TreeEnsembleClassifier.ClassLabelsSet || new Set([\"stringClassLabels\", \"int64ClassLabels\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.TreeEnsembleClassifier.ClassLabelsSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TreeEnsembleClassifier();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.treeEnsemble = CoreML.Specification.TreeEnsembleParameters.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.postEvaluationTransform = reader.int32();\n                    break;\n                case 100:\n                    message.stringClassLabels = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TreeEnsembleClassifier();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"treeEnsemble\":\n                    message.treeEnsemble = CoreML.Specification.TreeEnsembleParameters.decodeText(reader);\n                    break;\n                case \"postEvaluationTransform\":\n                    message.postEvaluationTransform = reader.enum(CoreML.Specification.TreeEnsemblePostEvaluationTransform);\n                    break;\n                case \"stringClassLabels\":\n                    message.stringClassLabels = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"int64ClassLabels\":\n                    message.int64ClassLabels = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TreeEnsembleClassifier.prototype.treeEnsemble = null;\nCoreML.Specification.TreeEnsembleClassifier.prototype.postEvaluationTransform = 0;\n\nCoreML.Specification.TreeEnsembleRegressor = class TreeEnsembleRegressor {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.TreeEnsembleRegressor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.treeEnsemble = CoreML.Specification.TreeEnsembleParameters.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.postEvaluationTransform = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.TreeEnsembleRegressor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"treeEnsemble\":\n                    message.treeEnsemble = CoreML.Specification.TreeEnsembleParameters.decodeText(reader);\n                    break;\n                case \"postEvaluationTransform\":\n                    message.postEvaluationTransform = reader.enum(CoreML.Specification.TreeEnsemblePostEvaluationTransform);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.TreeEnsembleRegressor.prototype.treeEnsemble = null;\nCoreML.Specification.TreeEnsembleRegressor.prototype.postEvaluationTransform = 0;\n\nCoreML.Specification.ItemSimilarityRecommender = class ItemSimilarityRecommender {\n\n    constructor() {\n        this.itemItemSimilarities = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ItemSimilarityRecommender();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.itemItemSimilarities.push(CoreML.Specification.ItemSimilarityRecommender.SimilarItems.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.itemStringIds = CoreML.Specification.StringVector.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.itemInt64Ids = CoreML.Specification.Int64Vector.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.itemInputFeatureName = reader.string();\n                    break;\n                case 11:\n                    message.numRecommendationsInputFeatureName = reader.string();\n                    break;\n                case 12:\n                    message.itemRestrictionInputFeatureName = reader.string();\n                    break;\n                case 13:\n                    message.itemExclusionInputFeatureName = reader.string();\n                    break;\n                case 20:\n                    message.recommendedItemListOutputFeatureName = reader.string();\n                    break;\n                case 21:\n                    message.recommendedItemScoreOutputFeatureName = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ItemSimilarityRecommender();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"itemItemSimilarities\":\n                    message.itemItemSimilarities.push(CoreML.Specification.ItemSimilarityRecommender.SimilarItems.decodeText(reader));\n                    break;\n                case \"itemStringIds\":\n                    message.itemStringIds = CoreML.Specification.StringVector.decodeText(reader);\n                    break;\n                case \"itemInt64Ids\":\n                    message.itemInt64Ids = CoreML.Specification.Int64Vector.decodeText(reader);\n                    break;\n                case \"itemInputFeatureName\":\n                    message.itemInputFeatureName = reader.string();\n                    break;\n                case \"numRecommendationsInputFeatureName\":\n                    message.numRecommendationsInputFeatureName = reader.string();\n                    break;\n                case \"itemRestrictionInputFeatureName\":\n                    message.itemRestrictionInputFeatureName = reader.string();\n                    break;\n                case \"itemExclusionInputFeatureName\":\n                    message.itemExclusionInputFeatureName = reader.string();\n                    break;\n                case \"recommendedItemListOutputFeatureName\":\n                    message.recommendedItemListOutputFeatureName = reader.string();\n                    break;\n                case \"recommendedItemScoreOutputFeatureName\":\n                    message.recommendedItemScoreOutputFeatureName = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ItemSimilarityRecommender.prototype.itemStringIds = null;\nCoreML.Specification.ItemSimilarityRecommender.prototype.itemInt64Ids = null;\nCoreML.Specification.ItemSimilarityRecommender.prototype.itemInputFeatureName = \"\";\nCoreML.Specification.ItemSimilarityRecommender.prototype.numRecommendationsInputFeatureName = \"\";\nCoreML.Specification.ItemSimilarityRecommender.prototype.itemRestrictionInputFeatureName = \"\";\nCoreML.Specification.ItemSimilarityRecommender.prototype.itemExclusionInputFeatureName = \"\";\nCoreML.Specification.ItemSimilarityRecommender.prototype.recommendedItemListOutputFeatureName = \"\";\nCoreML.Specification.ItemSimilarityRecommender.prototype.recommendedItemScoreOutputFeatureName = \"\";\n\nCoreML.Specification.ItemSimilarityRecommender.ConnectedItem = class ConnectedItem {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ItemSimilarityRecommender.ConnectedItem();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.itemId = reader.uint64();\n                    break;\n                case 2:\n                    message.similarityScore = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ItemSimilarityRecommender.ConnectedItem();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"itemId\":\n                    message.itemId = reader.uint64();\n                    break;\n                case \"similarityScore\":\n                    message.similarityScore = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ItemSimilarityRecommender.ConnectedItem.prototype.itemId = 0n;\nCoreML.Specification.ItemSimilarityRecommender.ConnectedItem.prototype.similarityScore = 0;\n\nCoreML.Specification.ItemSimilarityRecommender.SimilarItems = class SimilarItems {\n\n    constructor() {\n        this.similarItemList = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ItemSimilarityRecommender.SimilarItems();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.itemId = reader.uint64();\n                    break;\n                case 2:\n                    message.similarItemList.push(CoreML.Specification.ItemSimilarityRecommender.ConnectedItem.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.itemScoreAdjustment = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ItemSimilarityRecommender.SimilarItems();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"itemId\":\n                    message.itemId = reader.uint64();\n                    break;\n                case \"similarItemList\":\n                    message.similarItemList.push(CoreML.Specification.ItemSimilarityRecommender.ConnectedItem.decodeText(reader));\n                    break;\n                case \"itemScoreAdjustment\":\n                    message.itemScoreAdjustment = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.ItemSimilarityRecommender.SimilarItems.prototype.itemId = 0n;\nCoreML.Specification.ItemSimilarityRecommender.SimilarItems.prototype.itemScoreAdjustment = 0;\n\nCoreML.Specification.LinkedModel = class LinkedModel {\n\n    get LinkType() {\n        CoreML.Specification.LinkedModel.LinkTypeSet = CoreML.Specification.LinkedModel.LinkTypeSet || new Set([\"linkedModelFile\"]);\n        return Object.keys(this).find((key) => CoreML.Specification.LinkedModel.LinkTypeSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LinkedModel();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.linkedModelFile = CoreML.Specification.LinkedModelFile.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LinkedModel();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"linkedModelFile\":\n                    message.linkedModelFile = CoreML.Specification.LinkedModelFile.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LinkedModelFile = class LinkedModelFile {\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.LinkedModelFile();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.linkedModelFileName = CoreML.Specification.StringParameter.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.linkedModelSearchPath = CoreML.Specification.StringParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.LinkedModelFile();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"linkedModelFileName\":\n                    message.linkedModelFileName = CoreML.Specification.StringParameter.decodeText(reader);\n                    break;\n                case \"linkedModelSearchPath\":\n                    message.linkedModelSearchPath = CoreML.Specification.StringParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nCoreML.Specification.LinkedModelFile.prototype.linkedModelFileName = null;\nCoreML.Specification.LinkedModelFile.prototype.linkedModelSearchPath = null;\n\nCoreML.Specification.ClassConfidenceThresholding = class ClassConfidenceThresholding {\n\n    constructor() {\n        this.precisionRecallCurves = [];\n    }\n\n    static decode(reader, length) {\n        const message = new CoreML.Specification.ClassConfidenceThresholding();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 100:\n                    message.precisionRecallCurves.push(CoreML.Specification.PrecisionRecallCurve.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new CoreML.Specification.ClassConfidenceThresholding();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"precisionRecallCurves\":\n                    message.precisionRecallCurves.push(CoreML.Specification.PrecisionRecallCurve.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n"
  },
  {
    "path": "source/coreml.js",
    "content": "\nimport * as base from './base.js';\n\nconst coreml = {};\n\ncoreml.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        const identifier = context.identifier.toLowerCase();\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        const tags = await context.tags('pb');\n        if (tags.get(1) === 0 && tags.get(2) === 2) {\n            const match = (key) =>\n                (key >= 200 && key < 220) || (key >= 300 && key < 320) || (key >= 400 && key < 420) ||\n                (key >= 500 && key < 520) || (key >= 550 && key < 560) || (key >= 600 && key < 620) ||\n                (key === 900) ||\n                (key >= 2000 && key < 2010) || (key === 3000);\n            if (extension === 'pb' && Array.from(tags.keys()).every((key) => !match(key))) {\n                return null;\n            }\n            return context.set('coreml.pb');\n        }\n        if (extension === 'pbtxt') {\n            const tags = await context.tags('pbtxt');\n            if (tags.has('specificationVersion') && tags.has('description')) {\n                return context.set('coreml.pbtxt');\n            }\n        }\n        if (identifier === 'manifest.json') {\n            const obj = await context.peek('json');\n            if (obj && obj.rootModelIdentifier && obj.itemInfoEntries) {\n                const entries = Object.keys(obj.itemInfoEntries).map((key) => obj.itemInfoEntries[key]);\n                if (entries.filter((entry) => entry.path.toLowerCase().endsWith('.mlmodel').length === 1)) {\n                    return context.set('coreml.manifest');\n                }\n            }\n        }\n        if (identifier === 'model.mil') {\n            try {\n                const reader = await context.read('text', 2048);\n                const signature = reader.read('\\n');\n                if (signature && signature.trim().startsWith('program')) {\n                    return context.set('coreml.mil');\n                }\n            } catch {\n                // continue regardless of error\n            }\n        }\n        if (identifier === 'featuredescriptions.json') {\n            const obj = await context.peek('json');\n            if (obj && (obj.Inputs || obj.Outputs)) {\n                return context.set('coreml.featuredescriptions');\n            }\n        }\n        if (identifier === 'metadata.json') {\n            const obj = await context.peek('json');\n            if (obj && obj.rootModelIdentifier && obj.itemInfoEntries) {\n                return context.set('coreml.metadata');\n            }\n            if (Array.isArray(obj) && obj.some((item) => item && item.metadataOutputVersion && item.specificationVersion)) {\n                return context.set('coreml.metadata.mlmodelc');\n            }\n        }\n        if (extension === 'bin' && stream.length > 16) {\n            const buffer = stream.peek(Math.min(256, stream.length));\n            for (let i = 0; i < buffer.length - 4; i++) {\n                const signature = (buffer[i] | buffer[i + 1] << 8 | buffer[i + 2] << 16 | buffer [i + 3] << 24) >>> 0;\n                if (signature === 0xdeadbeef) {\n                    return context.set('coreml.weights');\n                }\n            }\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        if (context.type === 'coreml.metadata.mlmodelc' && (match.type === 'coreml.mil')) {\n            return false;\n        }\n        return true;\n    }\n\n    async open(context) {\n        coreml.proto = await context.require('./coreml-proto');\n        coreml.proto = coreml.proto.CoreML.Specification;\n        const metadata = await context.metadata('coreml-metadata.json');\n        const openBinary = async (content, context, path, format) => {\n            let model = null;\n            try {\n                const reader = await content.read('protobuf.binary');\n                model = coreml.proto.Model.decode(reader);\n            } catch (error) {\n                const message = error && error.message ? error.message : error.toString();\n                throw new coreml.Error(`File format is not coreml.Model (${message.replace(/\\.$/, '')}).`);\n            }\n            const weightPaths = new Set();\n            const walkProgram = (program) => {\n                for (const func of Object.values(program.functions)) {\n                    for (const block of Object.values(func.block_specializations)) {\n                        for (const operation of block.operations) {\n                            for (const value of Object.values(operation.attributes)) {\n                                if (value.blobFileValue && value.blobFileValue.fileName) {\n                                    weightPaths.add(value.blobFileValue.fileName);\n                                }\n                            }\n                        }\n                    }\n                }\n            };\n            const walkModel = (model) => {\n                if (model.mlProgram) {\n                    walkProgram(model.mlProgram);\n                }\n                if (model.pipeline && model.pipeline.models) {\n                    for (const node of model.pipeline.models) {\n                        walkModel(node);\n                    }\n                }\n                if (model.pipelineClassifier && model.pipelineClassifier.pipeline && model.pipelineClassifier.pipeline.models) {\n                    for (const node of model.pipelineClassifier.pipeline.models) {\n                        walkModel(node);\n                    }\n                }\n                if (model.pipelineRegressor && model.pipelineRegressor.pipeline && model.pipelineRegressor.pipeline.models) {\n                    for (const node of model.pipelineRegressor.pipeline.models) {\n                        walkModel(node);\n                    }\n                }\n            };\n            walkModel(model);\n            const weights = new Map();\n            if (weightPaths.size > 0) {\n                const folder = path.replace(/\\/[^/]*$/, '');\n                const keys = Array.from(weightPaths);\n                const paths = keys.map((path) => path.replace(/^@model_path\\//, `${folder}/`));\n                try {\n                    const contexts = await Promise.all(paths.map((path) => context.fetch(path)));\n                    for (let i = 0; i < keys.length; i++) {\n                        weights.set(keys[i], contexts[i].stream);\n                    }\n                } catch {\n                    // continue regardless of error\n                }\n            }\n            format = format || 'Core ML';\n            format = `${format} v${model.specificationVersion}`;\n            context = new coreml.Context(metadata, format, model, weights);\n            return new coreml.Model(context);\n        };\n        const openText = async (context) => {\n            let model = null;\n            try {\n                const reader = await context.read('protobuf.text');\n                model = coreml.proto.Model.decodeText(reader);\n            } catch (error) {\n                const message = error && error.message ? error.message : error.toString();\n                throw new coreml.Error(`File format is not coreml.Model (${message.replace(/\\.$/, '')}).`);\n            }\n            const format = `Core ML v${model.specificationVersion}`;\n            context = new coreml.Context(metadata, format, model);\n            return new coreml.Model(context, null);\n        };\n        const openManifest = async (obj, context, path) => {\n            const entries = Object.values(obj.itemInfoEntries).filter((entry) => entry.path.toLowerCase().endsWith('.mlmodel'));\n            if (entries.length !== 1) {\n                throw new coreml.Error('Manifest does not contain Core ML model.');\n            }\n            const name = `${path}Data/${entries[0].path}`;\n            const content = await context.fetch(name);\n            return openBinary(content, context, name, 'Core ML Package');\n        };\n        const openManifestStream = async (context, path) => {\n            const name = `${path}Manifest.json`;\n            const content = await context.fetch(name);\n            const obj = await content.read('json');\n            return openManifest(obj, context, path);\n        };\n        switch (context.type) {\n            case 'coreml.pb': {\n                return openBinary(context, context, '');\n            }\n            case 'coreml.pbtxt': {\n                return openText(context, context, '');\n            }\n            case 'coreml.manifest': {\n                const obj = await context.peek('json');\n                return openManifest(obj, context, '');\n            }\n            case 'coreml.featuredescriptions':\n            case 'coreml.metadata': {\n                return openManifestStream(context, '../../');\n            }\n            case 'coreml.metadata.mlmodelc': {\n                throw new coreml.Error('Core ML Model Archive format is not supported.');\n            }\n            case 'coreml.mil': {\n                throw new coreml.Error('Core ML MIL format is not supported.');\n            }\n            case 'coreml.weights': {\n                return openManifestStream(context, '../../../');\n            }\n            default: {\n                throw new coreml.Error(`Unsupported Core ML format '${context.type}'.`);\n            }\n        }\n    }\n};\n\ncoreml.Model = class {\n\n    constructor(context) {\n        this.format = context.format;\n        this.metadata = Array.from(context.metadata);\n        this.modules = context.graphs.map((context) => new coreml.Graph(context));\n        this.functions = context.functions.map((context) => new coreml.Graph(context));\n        if (context.version) {\n            this.version = context.version;\n        }\n        if (context.description) {\n            this.description = context.description;\n        }\n    }\n};\n\ncoreml.Graph = class {\n\n    constructor(context) {\n        this.name = context.name || '';\n        this.type = context.type || '';\n        this.description = context.description;\n        this.groups = context.groups;\n        for (const value of context.values.values()) {\n            const name = value.name;\n            const type = value.type;\n            const description = value.description;\n            const initializer = value.initializer;\n            if (!value.value) {\n                value.value = new coreml.Value(name, type, description, initializer);\n            }\n        }\n        this.inputs = context.inputs.map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new coreml.Argument(argument.name, values, null, argument.visible);\n        });\n        this.outputs = context.outputs.map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new coreml.Argument(argument.name, values, null, argument.visible);\n        });\n        for (const obj of context.nodes) {\n            const attributes = obj.attributes;\n            switch (obj.type) {\n                case 'loop':\n                    attributes.conditionNetwork = new coreml.Graph(attributes.conditionNetwork);\n                    attributes.bodyNetwork = new coreml.Graph(attributes.bodyNetwork);\n                    break;\n                case 'branch':\n                    attributes.ifBranch = new coreml.Graph(attributes.ifBranch);\n                    attributes.elseBranch = new coreml.Graph(attributes.elseBranch);\n                    break;\n                default:\n                    break;\n            }\n        }\n        this.nodes = context.nodes.map((obj) => new coreml.Node(context, obj));\n    }\n};\n\ncoreml.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\ncoreml.Value = class {\n\n    constructor(name, type, description = null, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new coreml.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.description = description;\n        this.initializer = initializer;\n        this.quantization = initializer ? initializer.quantization : null;\n    }\n};\n\ncoreml.Node = class {\n\n    constructor(context, obj) {\n        if (!obj.type) {\n            throw new Error('Undefined node type.');\n        }\n        if (obj.group) {\n            this.group = obj.group || null;\n        }\n        const type = context.metadata.type(obj.type);\n        this.type = type ? { ...type } : { name: obj.type };\n        this.type.name = obj.type.split(':').pop();\n        this.name = obj.name || '';\n        this.description = obj.description || '';\n        this.inputs = (obj.inputs || []).map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new coreml.Argument(argument.name, values, null, argument.visible);\n        });\n        this.outputs = (obj.outputs || []).map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new coreml.Argument(argument.name, values, null, argument.visible);\n        });\n        this.attributes = Object.entries(obj.attributes || []).map(([name, value]) => {\n            const metadata = context.metadata.attribute(obj.type, name);\n            let type = null;\n            let visible = true;\n            if (value instanceof coreml.Tensor) {\n                type = 'tensor';\n            }\n            if (value instanceof coreml.Graph) {\n                type = 'graph';\n            }\n            if (metadata) {\n                type = metadata.type ? metadata.type : type;\n                if (type && coreml.proto) {\n                    value = coreml.Utility.enum(type, value);\n                }\n                if (metadata.visible === false) {\n                    visible = false;\n                } else if (metadata.default !== undefined) {\n                    if (Array.isArray(value)) {\n                        value = value.map((item) => Number(item));\n                    }\n                    if (typeof value === 'bigint') {\n                        value = Number(value);\n                    }\n                    if (JSON.stringify(metadata.default) === JSON.stringify(value)) {\n                        visible = false;\n                    }\n                }\n            }\n            return new coreml.Argument(name, value, type, visible);\n        });\n        if (Array.isArray(obj.chain)) {\n            this.chain = obj.chain.map((obj) => new coreml.Node(context, obj));\n        }\n    }\n};\n\ncoreml.Tensor = class {\n\n    constructor(type, values, quantization, category) {\n        this.type = type;\n        this.values = values;\n        this.category = category;\n        if (type.dataType === 'float32') {\n            this.encoding = '|';\n        } else if ((type.dataType.startsWith('uint') && type.dataType.length === 5) ||\n                   (type.dataType.startsWith('int')  && type.dataType.length === 4)) {\n            this.encoding = '>';\n        } else {\n            this.encoding = '<';\n        }\n        if (quantization &&\n            quantization.linearQuantization &&\n            Array.isArray(quantization.linearQuantization.scale) &&\n            Array.isArray(quantization.linearQuantization.bias)) {\n            this.quantization = {\n                type: 'linear',\n                scale: quantization.linearQuantization.scale,\n                bias: quantization.linearQuantization.bias\n            };\n        }\n        if (quantization &&\n            quantization.lookupTableQuantization &&\n            quantization.lookupTableQuantization.floatValue &&\n            quantization.lookupTableQuantization.floatValue.length > 0) {\n            this.quantization = {\n                type: 'lookup',\n                value: quantization.lookupTableQuantization.floatValue\n            };\n        }\n    }\n};\n\ncoreml.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape || new coreml.TensorShape([]);\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ncoreml.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim);\n    }\n\n    equals(obj) {\n        return obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions) &&\n            this.dimensions.length === obj.dimensions.length &&\n            obj.dimensions.every((value, index) => this.dimensions[index] === value);\n    }\n\n    toString() {\n        return Array.isArray(this.dimensions) && this.dimensions.length > 0 ?\n            `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]` : '';\n    }\n};\n\ncoreml.ListType = class {\n\n    constructor(elementType) {\n        this.elementType = elementType;\n    }\n\n    equals(obj) {\n        return obj instanceof coreml.ListType && this.elementType.equals(obj.elementType);\n    }\n\n    toString() {\n        return `list<${this.elementType}>`;\n    }\n};\n\ncoreml.MapType = class {\n\n    constructor(keyType, valueType) {\n        this.keyType = keyType;\n        this.valueType = valueType;\n    }\n\n    equals(obj) {\n        return obj instanceof coreml.MapType && this.keyType.equals(obj.keyType) && this.valueType.equals(obj.valueType);\n    }\n\n    toString() {\n        return `map<${this.keyType},${this.valueType}>`;\n    }\n};\n\ncoreml.SequenceType = class {\n\n    constructor(type) {\n        this.type = type;\n    }\n\n    equals(obj) {\n        return obj instanceof coreml.SequenceType && this.type.equals(obj.type);\n    }\n\n    toString() {\n        return `sequence<${this.type}>`;\n    }\n};\n\ncoreml.ImageType = class {\n\n    constructor(colorSpace, width, height) {\n        this.width = width;\n        this.height = height;\n        switch (colorSpace) {\n            case coreml.proto.ImageFeatureType.ColorSpace.GRAYSCALE:\n                this.colorSpace = 'grayscale';\n                break;\n            case coreml.proto.ImageFeatureType.ColorSpace.RGB:\n                this.colorSpace = 'RGB';\n                break;\n            case coreml.proto.ImageFeatureType.ColorSpace.BGR:\n                this.colorSpace = 'BGR';\n                break;\n            case coreml.proto.ImageFeatureType.ColorSpace.GRAYSCALE_FLOAT16:\n                this.colorSpace = 'grayscale:float16';\n                break;\n            default:\n                throw new coreml.Error(`Unsupported image color space '${colorSpace}'.`);\n        }\n    }\n\n    equals(obj) {\n        return obj instanceof coreml.ImageType && this.width === obj.width && this.height === obj.height && this.colorSpace === obj.colorSpace;\n    }\n\n    toString() {\n        return `image<${this.colorSpace},${this.width.toString()}x${this.height}>`;\n    }\n};\n\ncoreml.OptionalType = class {\n\n    constructor(type) {\n        this.type = type;\n    }\n\n    equals(obj) {\n        return obj instanceof coreml.OptionalType && this.type.equals(obj.type);\n    }\n\n    toString() {\n        return `optional<${this.type}>`;\n    }\n};\n\ncoreml.StateType = class {\n\n    constructor(type) {\n        this.type = type;\n    }\n\n    equals(obj) {\n        return obj instanceof coreml.StateType && this.type.equals(obj.type);\n    }\n\n    toString() {\n        return `state<${this.type}>`;\n    }\n};\n\ncoreml.Context = class {\n\n    constructor(metadata, format, model, weights, values) {\n        this.format = format;\n        this.metadata = [];\n        this.graphs = [];\n        this.functions = [];\n        const description = model.description;\n        for (const func of description.functions) {\n            const graph = new coreml.Context.Graph(metadata, func.name, 'function', model, func, weights, values);\n            this.functions.push(graph);\n        }\n        if (description && description.defaultFunctionName) {\n            const graph = this.graphs.find((graph) => graph.name === description.defaultFunctionName);\n            if (graph) {\n                this.functions.splice(this.graphs.indexOf(graph), 1);\n                this.functions.unshift(graph);\n            }\n        }\n        if (model && !model.mlProgram || (model.mlProgram.functions && model.mlProgram.functions.main)) {\n            const graph = new coreml.Context.Graph(metadata, '', 'graph', model, description, weights, values);\n            this.graphs.push(graph);\n        }\n        if (description && description.metadata) {\n            const metadata = description.metadata;\n            if (metadata.versionString) {\n                this.version = metadata.versionString;\n            }\n            if (metadata.shortDescription) {\n                this.description = metadata.shortDescription;\n            }\n            if (metadata.author) {\n                this.metadata.push(new coreml.Argument('author', metadata.author));\n            }\n            if (metadata.license) {\n                this.metadata.push(new coreml.Argument('license', metadata.license));\n            }\n            if (metadata.userDefined && Object.keys(metadata.userDefined).length > 0) {\n                /* empty */\n            }\n        }\n    }\n};\n\ncoreml.Context.Graph = class {\n\n    constructor(metadata, name, type, model, description, weights, values) {\n        this.metadata = metadata;\n        this.name = name;\n        this.type = type;\n        this.weights = weights || new Map();\n        this.values = values || new Map();\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        if (description) {\n            const inputs = description && Array.isArray(description.input) ? description.input : [];\n            for (const description of inputs) {\n                const value = this.output(description.name);\n                this.update(value, description);\n                this.inputs.push({ name: description.name, visible: true, value: [value] });\n            }\n            const state = description && Array.isArray(description.state) ? description.state : [];\n            for (const description of state) {\n                const value = this.output(description.name);\n                this.update(value, description);\n                this.inputs.push({ name: description.name, visible: true, value: [value] });\n            }\n            this.description = this.model(model, '', description);\n            const outputs = description && Array.isArray(description.output) ? description.output : [];\n            for (const description of outputs) {\n                const value = this.input(description.name);\n                this.update(value, description);\n                this.outputs.push({ name: description.name, visible: true, value: [value] });\n            }\n        }\n    }\n\n    context() {\n        return new coreml.Context.Graph(this.metadata, '', 'graph', null, null, this.weights, this.values);\n    }\n\n    network(obj) {\n        const context = this.context();\n        for (const layer of obj.layers) {\n            const type = layer.layer;\n            context.node(context.groups, type, layer.name, '', layer[type], layer.input, layer.output, layer.inputTensor, layer.outputTensor);\n        }\n        context.updatePreprocessing('', obj.preprocessing, null);\n        context.description = 'Neural Network';\n        return context;\n    }\n\n    input(name) {\n        if (!this.values.has(name)) {\n            this.values.set(name, { counter: 0, name, to: [], from: [] });\n        }\n        return this.values.get(name);\n    }\n\n    output(name) {\n        if (this.values.has(name)) {\n            const value = { ...this.values.get(name) };\n            value.counter++;\n            value.name = `${name}|${value.counter}`; // custom argument id\n            this.values.set(name, value);\n            this.values.set(value.name, value);\n        } else {\n            const value = { counter: 0, name, to: [], from: [] };\n            this.values.set(name, value);\n            const key = `${name}|${value.counter}`;\n            this.values.set(key, value);\n        }\n        return this.values.get(name);\n    }\n\n    update(value, description) {\n        if (!value.type) {\n            value.type = coreml.Utility.featureType(description.type);\n        }\n        if (!value.description && description.shortDescription) {\n            value.description = description.shortDescription;\n        }\n    }\n\n    node(group, type, name, description, data, inputs, outputs, inputTensors, outputTensors) {\n        const obj = {\n            group,\n            type,\n            name,\n            description,\n            attributes: {},\n            inputs: [],\n            outputs: []\n        };\n        inputs = inputs.map((input, index) => {\n            const value = this.input(input);\n            if (!value.type && inputTensors && index < inputTensors.length) {\n                const tensor = inputTensors[index];\n                const shape = tensor && tensor.dimValue ? new coreml.TensorShape(tensor.dimValue) : null;\n                value.type = new coreml.TensorType('?', shape);\n            }\n            return value;\n        });\n        outputs = outputs.map((output, index) => {\n            const value = this.output(output);\n            if (!value.type && outputTensors && index < outputTensors.length) {\n                const tensor = outputTensors[index];\n                const shape = tensor && tensor.dimValue ? new coreml.TensorShape(tensor.dimValue) : null;\n                value.type = new coreml.TensorType('?', shape);\n            }\n            return value;\n        });\n        const initializers = [];\n        const initializer = (type, name, shape, data) => {\n            let dataType = '?';\n            let quantization = null;\n            let values = null;\n            if (data) {\n                if (data.floatValue && data.floatValue.length > 0) {\n                    values = data.floatValue;\n                    dataType = 'float32';\n                } else if (data.float16Value && data.float16Value.length > 0) {\n                    values = data.float16Value; // byte[]\n                    dataType = 'float16';\n                } else if (data.rawValue && data.rawValue.length > 0) {\n                    if (data.quantization) {\n                        values = data.rawValue;\n                        dataType = `uint${data.quantization.numberOfBits}`;\n                    } else {\n                        shape = [];\n                    }\n                }\n                quantization = data.quantization || null;\n            }\n            const tensorType = new coreml.TensorType(dataType, new coreml.TensorShape(shape));\n            const tensor = new coreml.Tensor(tensorType, values, quantization, 'Weights');\n            const input = this.metadata.input(type, name);\n            const visible = input && input.visible === false ? false : true;\n            const value = { value: new coreml.Value('', null, null, tensor) };\n            initializers.push({ name, visible, value: [value] });\n        };\n        const vector = (value) => {\n            return (value && Object.keys(value).length === 1 && value.vector) ? value.vector : value;\n        };\n        const weights = (type, data) => {\n            switch (type) {\n                case 'convolution': {\n                    const weightsShape = [data.outputChannels, data.kernelChannels, data.kernelSize[0], data.kernelSize[1]];\n                    if (data.isDeconvolution) {\n                        weightsShape[0] = data.kernelChannels;\n                        weightsShape[1] = Math.floor(Number(data.outputChannels / (data.nGroups === 0 ? 1 : data.nGroups)));\n                    }\n                    initializer(type, 'weights', weightsShape, data.weights);\n                    if (data.hasBias) {\n                        initializer(type, 'bias', [data.outputChannels], data.bias);\n                    }\n                    return { 'weights': true, 'bias': data.hasBias };\n                }\n                case 'innerProduct':\n                    initializer(type, 'weights', [data.outputChannels, data.inputChannels], data.weights);\n                    if (data.hasBias) {\n                        initializer(type, 'bias', [data.outputChannels], data.bias);\n                    }\n                    return { 'weights': true, 'bias': data.hasBias };\n                case 'batchnorm':\n                    initializer(type, 'gamma', [data.channels], data.gamma);\n                    initializer(type, 'beta', [data.channels], data.beta);\n                    if (data.mean) {\n                        initializer(type, 'mean', [data.channels], data.mean);\n                    }\n                    if (data.variance) {\n                        initializer(type, 'variance', [data.channels], data.variance);\n                    }\n                    return { 'gamma': true, 'beta': true, 'mean': true, 'variance': true };\n                case 'embedding':\n                    initializer(type, 'weights', [data.inputDim, data.outputChannels], data.weights);\n                    return { 'weights': true };\n                case 'loadConstant':\n                case 'loadConstantND':\n                    initializer(type, 'data', data.shape, data.data);\n                    return { 'data': true };\n                case 'scale':\n                    initializer(type, 'scale', data.shapeScale, data.scale);\n                    if (data.hasBias) {\n                        initializer(type, 'bias', data.shapeBias, data.bias);\n                    }\n                    return { 'scale': true, 'bias': data.hasBias };\n                case 'bias':\n                    initializer(type, 'bias', data.shape, data.bias);\n                    return { 'bias': true };\n                case 'simpleRecurrent':\n                    initializer(type, 'weights', [data.outputVectorSize, data.inputVectorSize], data.weightMatrix);\n                    initializer(type, 'recurrent', [data.outputVectorSize, data.inputVectorSize], data.recursionMatrix);\n                    if (data.hasBiasVectors) {\n                        initializer(type, 'bias', [data.outputVectorSize], data.biasVector);\n                    }\n                    return { 'weightMatrix': true, 'recursionMatrix': true, 'biasVector': data.hasBiasVectors };\n                case 'gru': {\n                    const recursionMatrixShape = [data.outputVectorSize, data.outputVectorSize];\n                    const weightMatrixShape = [data.outputVectorSize, data.inputVectorSize];\n                    const biasVectorShape = [data.outputVectorSize];\n                    initializer(type, 'updateGateWeightMatrix', weightMatrixShape, data.updateGateWeightMatrix);\n                    initializer(type, 'resetGateWeightMatrix', weightMatrixShape, data.resetGateWeightMatrix);\n                    initializer(type, 'outputGateWeightMatrix', weightMatrixShape, data.outputGateWeightMatrix);\n                    initializer(type, 'updateGateRecursionMatrix', recursionMatrixShape, data.updateGateRecursionMatrix);\n                    initializer(type, 'resetGateRecursionMatrix', recursionMatrixShape, data.resetGateRecursionMatrix);\n                    initializer(type, 'outputGateRecursionMatrix', recursionMatrixShape, data.outputGateRecursionMatrix);\n                    if (data.hasBiasVectors) {\n                        initializer(type, 'updateGateBiasVector', biasVectorShape, data.updateGateBiasVector);\n                        initializer(type, 'resetGateBiasVector', biasVectorShape, data.resetGateBiasVector);\n                        initializer(type, 'outputGateBiasVector', biasVectorShape, data.outputGateBiasVector);\n                    }\n                    return {\n                        'updateGateWeightMatrix': true, 'resetGateWeightMatrix': true, 'outputGateWeightMatrix': true,\n                        'updateGateRecursionMatrix': true, 'resetGateRecursionMatrix': true, 'outputGateRecursionMatrix': true,\n                        'updateGateBiasVector': data.hasBiasVectors, 'resetGateBiasVector': data.hasBiasVectors, 'outputGateBiasVector': data.hasBiasVectors\n                    };\n                }\n                case 'uniDirectionalLSTM':\n                case 'biDirectionalLSTM': {\n                    const count = (type === 'uniDirectionalLSTM') ? 1 : 2;\n                    const h = data.outputVectorSize;\n                    const x = data.inputVectorSize;\n                    for (let i = 0; i < count; i++) {\n                        const weights = count === 1 ? data.weightParams : data.weightParams[i];\n                        const suffix = (i === 0) ? '' : '_rev';\n                        initializer(type, `inputGateWeightMatrix${suffix}`, [h,x], weights.inputGateWeightMatrix);\n                        initializer(type, `forgetGateWeightMatrix${suffix}`, [h,x], weights.forgetGateWeightMatrix);\n                        initializer(type, `blockInputWeightMatrix${suffix}`, [h,x], weights.blockInputWeightMatrix);\n                        initializer(type, `outputGateWeightMatrix${suffix}`, [h,x], weights.outputGateWeightMatrix);\n                        initializer(type, `inputGateRecursionMatrix${suffix}`, [h,h], weights.inputGateRecursionMatrix);\n                        initializer(type, `forgetGateRecursionMatrix${suffix}`, [h,h],weights.forgetGateRecursionMatrix);\n                        initializer(type, `blockInputRecursionMatrix${suffix}`, [h,h], weights.blockInputRecursionMatrix);\n                        initializer(type, `outputGateRecursionMatrix${suffix}`, [h,h], weights.outputGateRecursionMatrix);\n                        if (data.params.hasBiasVectors) {\n                            initializer(type, `inputGateBiasVector${suffix}`, [h], weights.inputGateBiasVector);\n                            initializer(type, `forgetGateBiasVector${suffix}`, [h], weights.forgetGateBiasVector);\n                            initializer(type, `blockInputBiasVector${suffix}`, [h], weights.blockInputBiasVector);\n                            initializer(type, `outputGateBiasVector${suffix}`, [h], weights.outputGateBiasVector);\n                        }\n                        if (data.params.hasPeepholeVectors) {\n                            initializer(type, `inputGatePeepholeVector${suffix}`, [h], weights.inputGatePeepholeVector);\n                            initializer(type, `forgetGatePeepholeVector${suffix}`, [h], weights.forgetGatePeepholeVector);\n                            initializer(type, `outputGatePeepholeVector${suffix}`, [h], weights.outputGatePeepholeVector);\n                        }\n                    }\n                    return { 'weightParams': true };\n                }\n                case 'dictVectorizer':\n                    data.stringToIndex = vector(data.stringToIndex);\n                    return {};\n                case 'wordTagger':\n                    data.modelParameterData = Array.from(data.modelParameterData);\n                    data.stringTags = vector(data.stringTags);\n                    return { tokensOutputFeatureName: true, tokenTagsOutputFeatureName: true, tokenLengthsOutputFeatureName: true, tokenLocationsOutputFeatureName: true };\n                case 'textClassifier':\n                    data.modelParameterData = Array.from(data.modelParameterData);\n                    data.stringClassLabels = vector(data.stringClassLabels);\n                    return {};\n                case 'nonMaximumSuppression':\n                    data.stringClassLabels = vector(data.stringClassLabels);\n                    return {};\n                default:\n                    return {};\n            }\n        };\n        if (data) {\n            const attributes = obj.attributes;\n            const map = weights(type, data, initializers);\n            for (const [name, value] of Object.entries(data)) {\n                if (!map[name]) {\n                    attributes[name] = value;\n                }\n            }\n            switch (obj.type) {\n                case 'loop':\n                    attributes.bodyNetwork = this.network(attributes.bodyNetwork);\n                    attributes.conditionNetwork = this.network(attributes.conditionNetwork);\n                    break;\n                case 'branch':\n                    attributes.ifBranch = this.network(attributes.ifBranch);\n                    attributes.elseBranch = this.network(attributes.elseBranch);\n                    break;\n                default:\n                    break;\n            }\n        }\n        const metadata = this.metadata.type(type);\n        for (let i = 0; i < inputs.length;) {\n            const input = metadata && metadata.inputs && i < metadata.inputs.length ? metadata.inputs[i] : { name: i === 0 ? 'input' : i.toString() };\n            const count = input.type === 'Tensor[]' ? inputs.length - i : 1;\n            const values = inputs.slice(i, i + count);\n            obj.inputs.push({ name: input.name, visible: true, value: values });\n            i += count;\n        }\n        obj.inputs.push(...initializers);\n        for (let i = 0; i < outputs.length;) {\n            const output = metadata && metadata.outputs && i < metadata.outputs.length ? metadata.outputs[i] : { name: i === 0 ? 'output' : i.toString() };\n            const count = output.type === 'Tensor[]' ? outputs.length - i : 1;\n            const args = outputs.slice(i, i + count);\n            obj.outputs.push({ name: output.name, visible: true, value: args });\n            i += count;\n        }\n        this.nodes.push(obj);\n        return obj;\n    }\n\n    model(model, group, description) {\n        this.groups |= group.length > 0;\n        const shortDescription = model && model.description && model.description.metadata && model.description.metadata.shortDescription ? model.description.metadata.shortDescription : '';\n        switch (model.Type) {\n            case 'neuralNetworkClassifier': {\n                const neuralNetworkClassifier = model.neuralNetworkClassifier;\n                for (const layer of neuralNetworkClassifier.layers) {\n                    const type = layer.layer;\n                    this.node(group, type, layer.name, group === '' ? '' : shortDescription, layer[type], layer.input, layer.output, layer.inputTensor, layer.outputTensor);\n                }\n                this.updateClassifierOutput(group, neuralNetworkClassifier, description);\n                this.updatePreprocessing(group, neuralNetworkClassifier.preprocessing, description);\n                return 'Neural Network Classifier';\n            }\n            case 'neuralNetwork': {\n                const neuralNetwork = model.neuralNetwork;\n                for (const layer of neuralNetwork.layers) {\n                    this.node(group, layer.layer, layer.name, group === '' ? '' : shortDescription, layer[layer.layer], layer.input, layer.output, layer.inputTensor, layer.outputTensor);\n                }\n                this.updatePreprocessing(group, neuralNetwork.preprocessing, description);\n                return 'Neural Network';\n            }\n            case 'neuralNetworkRegressor': {\n                const neuralNetworkRegressor = model.neuralNetworkRegressor;\n                for (const layer of neuralNetworkRegressor.layers) {\n                    this.node(group, layer.layer, layer.name, shortDescription, layer[layer.layer], layer.input, layer.output);\n                }\n                this.updatePreprocessing(group, neuralNetworkRegressor, description);\n                return 'Neural Network Regressor';\n            }\n            case 'pipeline': {\n                for (let i = 0; i < model.pipeline.models.length; i++) {\n                    this.model(model.pipeline.models[i], `${group ? (`${group}/`) : ''}pipeline[${i}]`, description);\n                }\n                return 'Pipeline';\n            }\n            case 'pipelineClassifier': {\n                for (let i = 0; i < model.pipelineClassifier.pipeline.models.length; i++) {\n                    this.model(model.pipelineClassifier.pipeline.models[i], `${group ? (`${group}/`) : ''}pipelineClassifier[${i}]`, description);\n                }\n                return 'Pipeline Classifier';\n            }\n            case 'pipelineRegressor': {\n                for (let i = 0; i < model.pipelineRegressor.pipeline.models.length; i++) {\n                    this.model(model.pipelineRegressor.pipeline.models[i], `${group ? (`${group}/`) : ''}pipelineRegressor[${i}]`, description);\n                }\n                return 'Pipeline Regressor';\n            }\n            case 'glmClassifier': {\n                this.node(group, 'glmClassifier', null, shortDescription,\n                    {\n                        classEncoding: model.glmClassifier.classEncoding,\n                        offset: model.glmClassifier.offset,\n                        weights: model.glmClassifier.weights\n                    },\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                this.updateClassifierOutput(group, model.glmClassifier, description);\n                return 'Generalized Linear Classifier';\n            }\n            case 'glmRegressor': {\n                this.node(group, 'glmRegressor', null, shortDescription,\n                    model.glmRegressor,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Generalized Linear Regressor';\n            }\n            case 'treeEnsembleClassifier': {\n                this.node(group, 'treeEnsembleClassifier', null, shortDescription,\n                    model.treeEnsembleClassifier.treeEnsemble,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                this.updateClassifierOutput(group, model.treeEnsembleClassifier, description);\n                return 'Tree Ensemble Classifier';\n            }\n            case 'treeEnsembleRegressor': {\n                this.node(group, 'treeEnsembleRegressor', null, shortDescription,\n                    model.treeEnsembleRegressor.treeEnsemble,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Tree Ensemble Regressor';\n            }\n            case 'supportVectorClassifier': {\n                this.node(group, 'supportVectorClassifier', null, shortDescription,\n                    {\n                        coefficients: model.supportVectorClassifier.coefficients,\n                        denseSupportVectors: model.supportVectorClassifier.denseSupportVectors,\n                        kernel: model.supportVectorClassifier.kernel,\n                        numberOfSupportVectorsPerClass: model.supportVectorClassifier.numberOfSupportVectorsPerClass,\n                        probA: model.supportVectorClassifier.probA,\n                        probB: model.supportVectorClassifier.probB,\n                        rho: model.supportVectorClassifier.rho,\n                        supportVectors: model.supportVectorClassifier.supportVectors\n                    },\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                this.updateClassifierOutput(group, model.supportVectorClassifier, description);\n                return 'Support Vector Classifier';\n            }\n            case 'supportVectorRegressor': {\n                this.node(group, 'supportVectorRegressor', null, shortDescription,\n                    {\n                        coefficients: model.supportVectorRegressor.coefficients,\n                        kernel: model.supportVectorRegressor.kernel,\n                        rho: model.supportVectorRegressor.rho,\n                        supportVectors: model.supportVectorRegressor.supportVectors\n                    },\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Support Vector Regressor';\n            }\n            case 'oneHotEncoder': {\n                const categoryType = model.oneHotEncoder.CategoryType;\n                const oneHotEncoderParams = { outputSparse: model.oneHotEncoder.outputSparse };\n                oneHotEncoderParams[categoryType] = model.oneHotEncoder[categoryType];\n                this.node(group, 'oneHotEncoder', null, shortDescription,\n                    oneHotEncoderParams,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'One Hot Encoder';\n            }\n            case 'imputer': {\n                const imputedValue = model.imputer.ImputedValue;\n                const replaceValue = model.imputer.ReplaceValue;\n                const imputerParams = {};\n                imputerParams[imputedValue] = model.imputer[imputedValue];\n                imputerParams[replaceValue] = model.imputer[replaceValue];\n                this.node(group, 'oneHotEncoder', null, shortDescription,\n                    imputerParams,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Imputer';\n            }\n            case 'featureVectorizer': {\n                this.node(group, 'featureVectorizer', null, shortDescription,\n                    model.featureVectorizer,\n                    model.description.input.map((item) => item.name),\n                    [model.description.output[0].name]);\n                return 'Feature Vectorizer';\n            }\n            case 'dictVectorizer': {\n                this.node(group, 'dictVectorizer', null, shortDescription,\n                    model.dictVectorizer,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Dictionary Vectorizer';\n            }\n            case 'scaler': {\n                this.node(group, 'scaler', null, shortDescription,\n                    model.scaler,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Scaler';\n            }\n            case 'categoricalMapping': {\n                this.node(group, 'categoricalMapping', null, shortDescription,\n                    model.categoricalMapping,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Categorical Mapping';\n            }\n            case 'normalizer': {\n                this.node(group, 'normalizer', null, shortDescription,\n                    model.normalizer,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Normalizer';\n            }\n            case 'arrayFeatureExtractor': {\n                this.node(group, 'arrayFeatureExtractor', null, shortDescription,\n                    { extractIndex: model.arrayFeatureExtractor.extractIndex },\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Array Feature Extractor';\n            }\n            case 'nonMaximumSuppression': {\n                const nonMaximumSuppressionParams = {\n                    pickTop: model.nonMaximumSuppression.pickTop,\n                    stringClassLabels: model.nonMaximumSuppression.stringClassLabels,\n                    iouThreshold: model.nonMaximumSuppression.iouThreshold,\n                    confidenceThreshold: model.nonMaximumSuppression.confidenceThreshold\n                };\n                this.node(group, 'nonMaximumSuppression', null, shortDescription,\n                    nonMaximumSuppressionParams,\n                    [\n                        model.nonMaximumSuppression.confidenceInputFeatureName,\n                        model.nonMaximumSuppression.coordinatesInputFeatureName,\n                        model.nonMaximumSuppression.iouThresholdInputFeatureName,\n                        model.nonMaximumSuppression.confidenceThresholdInputFeatureName,\n                    ],\n                    [\n                        model.nonMaximumSuppression.confidenceOutputFeatureName,\n                        model.nonMaximumSuppression.coordinatesOutputFeatureName\n                    ]);\n                return 'Non Maximum Suppression';\n            }\n            case 'wordTagger': {\n                this.node(group, 'wordTagger', null, shortDescription,\n                    model.wordTagger,\n                    [model.description.input[0].name],\n                    [\n                        model.wordTagger.tokensOutputFeatureName,\n                        model.wordTagger.tokenTagsOutputFeatureName,\n                        model.wordTagger.tokenLocationsOutputFeatureName,\n                        model.wordTagger.tokenLengthsOutputFeatureName\n                    ]);\n                return 'Word Tagger';\n            }\n            case 'textClassifier': {\n                this.node(group, 'textClassifier', null, shortDescription,\n                    model.textClassifier,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Text Classifier';\n            }\n            case 'visionFeaturePrint': {\n                const visionFeaturePrintParams = {\n                    scene: model.visionFeaturePrint.scene\n                };\n                this.node(group, 'visionFeaturePrint', null, shortDescription,\n                    visionFeaturePrintParams,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Vision Feature Print';\n            }\n            case 'soundAnalysisPreprocessing': {\n                this.node(group, 'soundAnalysisPreprocessing', null, shortDescription,\n                    model.soundAnalysisPreprocessing,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Sound Analysis Preprocessing';\n            }\n            case 'kNearestNeighborsClassifier': {\n                this.node(group, 'kNearestNeighborsClassifier', null, shortDescription,\n                    model.kNearestNeighborsClassifier,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                this.updateClassifierOutput(group, model.kNearestNeighborsClassifier, description);\n                return 'Nearest Neighbors Classifier';\n            }\n            case 'itemSimilarityRecommender': {\n                this.node(group, 'itemSimilarityRecommender', null, shortDescription,\n                    {\n                        itemStringIds: model.itemSimilarityRecommender.itemStringIds.vector,\n                        itemItemSimilarities: model.itemSimilarityRecommender.itemItemSimilarities\n                    },\n                    model.description.input.map((feature) => feature.name),\n                    model.description.output.map((feature) => feature.name));\n                return 'Item Similarity Recommender';\n            }\n            case 'audioFeaturePrint': {\n                this.node(group, 'audioFeaturePrint', null, shortDescription,\n                    model.audioFeaturePrint,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Audio Feature Print';\n            }\n            case 'linkedModel': {\n                this.node(group, 'linkedModel', null, shortDescription,\n                    model.linkedModel.linkedModelFile,\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'Linked Model';\n            }\n            case 'customModel': {\n                this.node(group, 'customModel', null, shortDescription,\n                    { className: model.customModel.className, parameters: model.customModel.parameters },\n                    [model.description.input[0].name],\n                    [model.description.output[0].name]);\n                return 'customModel';\n            }\n            case 'mlProgram': {\n                return this.program(model.mlProgram, group);\n            }\n            default: {\n                throw new coreml.Error(`Unsupported model type '${JSON.stringify(Object.keys(model))}'.`);\n            }\n        }\n    }\n\n    updateClassifierOutput(group, classifier, description) {\n        let labelProbabilityLayerName = classifier.labelProbabilityLayerName;\n        if (!labelProbabilityLayerName && this.nodes.length > 0) {\n            const node = this.nodes.slice(-1).pop();\n            if (node && node.outputs.length === 1 && node.outputs[0].value.length === 1) {\n                labelProbabilityLayerName = node.outputs[0].value[0].name;\n            }\n        }\n        let predictedFeatureName = description.predictedFeatureName;\n        let predictedProbabilitiesName = description.predictedProbabilitiesName;\n        if ((predictedFeatureName || predictedProbabilitiesName) && labelProbabilityLayerName && classifier.ClassLabels) {\n            predictedFeatureName = predictedFeatureName ? predictedFeatureName : '?';\n            predictedProbabilitiesName = predictedProbabilitiesName ? predictedProbabilitiesName : '?';\n            const labelProbabilityInput = `${labelProbabilityLayerName}:labelProbabilityLayerName`;\n            const values = new Set();\n            for (const node of this.nodes) {\n                for (const output of node.outputs) {\n                    for (const value of output.value) {\n                        if (value.name === labelProbabilityLayerName) {\n                            value.name = labelProbabilityInput;\n                            values.add(value);\n                        }\n                    }\n                }\n            }\n            this.values.set(labelProbabilityInput, this.values.get(labelProbabilityLayerName));\n            this.values.delete(labelProbabilityLayerName);\n            const type = classifier.ClassLabels;\n            const node = {\n                // group: this._group,\n                type,\n                name: null,\n                description: '',\n                attributes: classifier[type] || {}\n            };\n            node.inputs = [\n                { name: 'input', visible: true, value: Array.from(values) }\n            ];\n            node.outputs = [\n                { name: 'probabilities', visible: true, value: [this.output(predictedProbabilitiesName)] },\n                { name: 'feature', visible: true, value: [this.output(predictedFeatureName)] }\n            ];\n            this.nodes.push(node);\n        }\n    }\n\n    updatePreprocessing(group, preprocessings, description) {\n        if (preprocessings && preprocessings.length > 0) {\n            const preprocessingInput = description.input[0].name;\n            const inputNodes = [];\n            for (const node of this.nodes) {\n                if (node.inputs.some((input) => Array.isArray(input.value) && input.value.some((arg) => arg.name === preprocessingInput))) {\n                    inputNodes.push(node);\n                }\n            }\n            let currentOutput = preprocessingInput;\n            let preprocessorOutput = null;\n            let preprocessorIndex = 0;\n            for (const preprocessing of preprocessings) {\n                const input = preprocessing.featureName ? preprocessing.featureName : currentOutput;\n                currentOutput = `${preprocessingInput}:${preprocessorIndex}`;\n                const preprocessor = preprocessing.preprocessor;\n                const node = this.node(group, preprocessor, null, '', preprocessing[preprocessor], [input], [currentOutput]);\n                [preprocessorOutput] = node.outputs[0].value;\n                preprocessorIndex++;\n            }\n            for (const node of inputNodes) {\n                for (const input of node.inputs) {\n                    if (Array.isArray(input.value)) {\n                        for (let i = 0; i < input.value.length; i++) {\n                            if (input.value[i].name === preprocessingInput) {\n                                input.value[i] = preprocessorOutput;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    program(program, group) {\n        // need to handle functions other than main?\n        const name = this.name || 'main';\n        const main = program.functions[name];\n        // need to handle more than one block specialization?\n        const block_specializations = main.block_specializations;\n        const key = Object.keys(block_specializations).filter((key) => key.startsWith('CoreML')).shift();\n        const block = block_specializations[key];\n        const convertValue = (value) => {\n            switch (value.value) {\n                case 'immediateValue': {\n                    const tensor = value.immediateValue.tensor;\n                    const type = coreml.Utility.valueType(value.type);\n                    let values = null;\n                    switch (tensor.value) {\n                        case 'ints':\n                            values = tensor.ints.values;\n                            break;\n                        case 'strings':\n                            values = tensor.strings.values;\n                            break;\n                        case 'bools':\n                            values = tensor.bools.values;\n                            break;\n                        case 'floats':\n                            values = tensor.floats.values;\n                            break;\n                        case 'bytes':\n                            values = tensor.bytes.values;\n                            break;\n                        default:\n                            throw new coreml.Error(`Unsupported tensor value '${tensor.value}'.`);\n                    }\n                    if (type.shape.dimensions.length === 0) {\n                        [values] = values;\n                    }\n                    return values;\n                }\n                case 'blobFileValue': {\n                    const type = coreml.Utility.valueType(value.type);\n                    const blob = value.blobFileValue;\n                    const offset = Number(blob.offset);\n                    const file = blob.fileName;\n                    let data = null;\n                    const stream = this.weights.get(file);\n                    if (stream) {\n                        stream.seek(offset);\n                        const buffer = stream.read(32);\n                        const reader = base.BinaryReader.open(buffer);\n                        const signature = reader.uint32();\n                        if (signature === 0xdeadbeef) {\n                            reader.uint32(); // dataType\n                            const size = reader.uint64().toNumber();\n                            const offset = reader.uint64().toNumber();\n                            stream.seek(offset);\n                            const length = (type.shape.dimensions || []).reduce((a, b) => a * b, 1);\n                            switch (type.dataType) {\n                                case 'float32': {\n                                    const buffer = stream.read(size);\n                                    data = new Float32Array(buffer.buffer, buffer.byteOffset, length).slice();\n                                    break;\n                                }\n                                case 'float16':\n                                case 'int1': case 'int2': case 'int3': case 'int4': case 'int6': case 'int8': case 'int32':\n                                case 'uint1': case 'uint2': case 'uint3': case 'uint4': case 'uint6': case 'uint8': case 'uint16': {\n                                    data = stream.read(size);\n                                    break;\n                                }\n                                default:\n                                    throw new coreml.Error(`Unsupported blob data type '${type.dataType}'.`);\n                            }\n                        }\n                    }\n                    return new coreml.Tensor(type, data, null, 'Blob');\n                }\n                default: {\n                    throw new coreml.Error(`Unsupported value '${value.value}'.`);\n                }\n            }\n        };\n        const operations = block.operations.map((op) => {\n            const operation = {\n                type: op.type,\n                attributes: {}\n            };\n            for (const [key, value] of Object.entries(op.attributes)) {\n                operation.attributes[key] = convertValue(value);\n            }\n            operation.inputs = Object.entries(op.inputs).map(([name, input]) => {\n                const value = input.arguments.map((argument) => {\n                    if (argument.value && argument.value.value && argument.value.blobFileValue) {\n                        return { name: '', value: convertValue(argument.value) };\n                    }\n                    if (argument.name) {\n                        const value = this.input(argument.name);\n                        value.to.push(operation);\n                        return value;\n                    }\n                    return { value: argument.value };\n                });\n                return { name, value };\n            });\n            operation.outputs = op.outputs.map((output) => {\n                const value = this.input(output.name);\n                value.type = coreml.Utility.valueType(output.type);\n                value.from.push(operation);\n                return { name: 'output', value: [value] };\n            });\n            return operation;\n        });\n        for (const op of operations) {\n            if (op.type === 'const' && op.inputs.length === 0 &&\n                op.outputs.length === 1 && op.outputs[0].value.length === 1) {\n                const [value] = op.outputs[0].value;\n                if (op.attributes && op.attributes.val) {\n                    const type = value.type;\n                    const data = op.attributes.val;\n                    if (data instanceof Uint8Array && data.length === 2 &&\n                        type.dataType === 'float16' && type.shape.dimensions.length === 0) {\n                        const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                        value.value = view.getFloat16(0, true);\n                    } else {\n                        value.value = data;\n                    }\n                    value.const = true;\n                    op.delete = true;\n                }\n            }\n        }\n        for (const op of operations) {\n            for (const input of op.inputs) {\n                if (input.value.length > 1 && input.value.some((argument) => argument.const)) {\n                    if (!input.value.every((argument) => argument.value instanceof coreml.Tensor)) {\n                        for (const value of input.value) {\n                            for (const from of value.from) {\n                                from.delete = false;\n                            }\n                            delete value.value;\n                        }\n                    }\n                }\n            }\n        }\n        for (const op of operations.filter((op) => !op.delete)) {\n            op.inputs = op.inputs.filter((input) => {\n                if (input.value.every((value) => value.value === undefined || value.value instanceof coreml.Tensor)) {\n                    return true;\n                }\n                op.attributes[input.name] = input.value.length === 1 ?\n                    input.value[0].value :\n                    input.value.map((argument) => argument.value[0]);\n                return false;\n            });\n        }\n        const mapValue = (name, value) => {\n            if (value.value instanceof coreml.Tensor) {\n                value.initializer = value.value;\n                delete value.value;\n                if (name === '') {\n                    this.values.set(value, value);\n                    return value;\n                }\n            }\n            if (!this.values.has(name)) {\n                this.values.set(name, value);\n            } else if ((value.type && !value.type.equals(this.values.get(name).type)) ||\n                       (value.initializer && value.initializer !== this.values.get(name).initializer)) {\n                throw new coreml.Error(`Duplicate value '${name}'.`);\n            }\n            return this.values.get(name);\n        };\n        for (const op of operations.filter((op) => !op.delete)) {\n            for (const argument of op.inputs) {\n                for (const value of argument.value) {\n                    mapValue(value.name, value);\n                }\n            }\n            for (const argument of op.outputs) {\n                for (const value of argument.value) {\n                    mapValue(value.name, value);\n                }\n            }\n        }\n        for (const op of operations.filter((op) => !op.delete)) {\n            op.group = group;\n            op.type = `program:${op.type}`;\n            const metadata = this.metadata.type(op.type);\n            if (metadata && Array.isArray(metadata.inputs)) {\n                const map = new Map(metadata.inputs.map((input, index) => [input.name, index + 1]));\n                op.inputs.sort((a, b) => (map.get(a.name) || map.size) - (map.get(b.name) || map.size));\n            }\n            this.nodes.push(op);\n        }\n        return 'ML Program';\n    }\n};\n\ncoreml.Utility = class {\n\n    static enum(name, value) {\n        let type = coreml.proto;\n        const parts = name.split('.');\n        while (type && parts.length > 0) {\n            type = type[parts.shift()];\n        }\n        if (type) {\n            coreml.Utility._enumKeyMap = coreml.Utility._enumKeyMap || new Map();\n            if (!coreml.Utility._enumKeyMap.has(name)) {\n                const map = new Map(Object.entries(type).map(([key, value]) => [value, key]));\n                coreml.Utility._enumKeyMap.set(name, map);\n            }\n            const map = coreml.Utility._enumKeyMap.get(name);\n            if (map.has(value)) {\n                return map.get(value);\n            }\n        }\n        return value;\n    }\n\n    static featureType(type) {\n        let result = '?';\n        if (type) {\n            switch (type.Type) {\n                case 'arrayType':\n                case 'multiArrayType': {\n                    const arrayType = type[type.Type];\n                    let shape = new coreml.TensorShape([]);\n                    if (arrayType.shape && arrayType.shape.length > 0) {\n                        shape = new coreml.TensorShape(arrayType.shape.map((dim) => Number(dim)));\n                    }\n                    let dataType = '';\n                    const ArrayDataType = coreml.proto.ArrayFeatureType.ArrayDataType;\n                    switch (arrayType.dataType) {\n                        case ArrayDataType.INVALID_ARRAY_DATA_TYPE:\n                            dataType = '?';\n                            break;\n                        case ArrayDataType.FLOAT16:\n                            dataType = 'float16';\n                            break;\n                        case ArrayDataType.FLOAT32:\n                            dataType = 'float32';\n                            break;\n                        case ArrayDataType.DOUBLE:\n                            dataType = 'float64';\n                            break;\n                        case ArrayDataType.INT32:\n                            dataType = 'int32';\n                            break;\n                        case ArrayDataType.INT8:\n                            dataType = 'int8';\n                            break;\n                        default:\n                            throw new coreml.Error(`Unsupported array data type '${arrayType.dataType}'.`);\n                    }\n                    result = new coreml.TensorType(dataType, shape);\n                    break;\n                }\n                case 'stringType': {\n                    result = new coreml.TensorType('string');\n                    break;\n                }\n                case 'doubleType': {\n                    result = new coreml.TensorType('float64');\n                    break;\n                }\n                case 'int64Type': {\n                    result = new coreml.TensorType('int64');\n                    break;\n                }\n                case 'dictionaryType': {\n                    result = new coreml.MapType(type.dictionaryType.KeyType.replace('KeyType', ''), 'float64');\n                    break;\n                }\n                case 'sequenceType': {\n                    result = new coreml.SequenceType(coreml.Utility.featureType(type[type.Type]));\n                    break;\n                }\n                case 'imageType': {\n                    result = new coreml.ImageType(type.imageType.colorSpace, type.imageType.width, type.imageType.height);\n                    break;\n                }\n                case 'stateType': {\n                    result = new coreml.StateType(coreml.Utility.featureType(type.stateType));\n                    break;\n                }\n                default: {\n                    throw new coreml.Error(`Unsupported feature type '${type.Type}'.`);\n                }\n            }\n            if (type.isOptional) {\n                result = new coreml.OptionalType(result);\n            }\n        }\n        return result;\n    }\n\n    static tensorType(type) {\n        if (!coreml.Utility._dataTypes) {\n            coreml.Utility._dataTypes = new Map(Object.entries(coreml.proto.MILSpec.DataType).map((([key, value]) => [value, key.toLowerCase()])));\n            coreml.Utility._dataTypes.delete(0);\n            coreml.Utility._dataTypes.set(1, 'boolean');\n        }\n        const shape = type.dimensions.map((dim) => dim.constant ? dim.constant.size : '?');\n        const dataType = coreml.Utility._dataTypes.get(type.dataType);\n        if (!dataType) {\n            throw new coreml.Error(`Unsupported data type '${type.dataType}'.`);\n        }\n        return new coreml.TensorType(dataType, new coreml.TensorShape(shape));\n    }\n\n    static valueType(type) {\n        switch (type.type) {\n            case 'tensorType':\n                return coreml.Utility.tensorType(type.tensorType);\n            case 'listType':\n                return new coreml.ListType(coreml.Utility.valueType(type.listType.type));\n            case 'dictionaryType':\n                return new coreml.MapType(coreml.Utility.valueType(type.dictionaryType.keyType), coreml.Utility.valueType(type.dictionaryType.valueType));\n            default:\n                throw new coreml.Error(`Unsupported value type '${type.type}'.`);\n        }\n    }\n};\n\ncoreml.Error = class extends Error {\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Core ML model.';\n    }\n};\n\nexport const ModelFactory = coreml.ModelFactory;\n"
  },
  {
    "path": "source/dagre.js",
    "content": "\nconst dagre = {};\n\n// Dagre graph layout\n// https://github.com/dagrejs/dagre\n// https://github.com/dagrejs/graphlib\n\ndagre.layout = (nodes, edges, layout, state) => {\n\n    let uniqueIdCounter = 0;\n    const uniqueId = (prefix) => {\n        const id = ++uniqueIdCounter;\n        return prefix + id;\n    };\n\n    const flat = (list) => {\n        if (Array.isArray(list) && list.every((item) => !Array.isArray(item))) {\n            return list;\n        }\n        const target = [];\n        for (const item of list) {\n            if (!Array.isArray(item)) {\n                target.push(item);\n                continue;\n            }\n            for (const entry of item) {\n                target.push(entry);\n            }\n        }\n        return target;\n    };\n\n    // Adds a dummy node to the graph and return v.\n    const addDummyNode = (g, type, label, name) => {\n        let v = '';\n        do {\n            v = uniqueId(name);\n        } while (g.hasNode(v));\n        label.dummy = type;\n        g.setNode(v, label);\n        return v;\n    };\n\n    const asNonCompoundGraph = (g) => {\n        const graph = new dagre.Graph(true, false);\n        for (const node of g.nodes.values()) {\n            const v = node.v;\n            if (!g.hasChildren(v)) {\n                graph.setNode(v, node.label);\n            }\n        }\n        for (const e of g.edges.values()) {\n            graph.setEdge(e.v, e.w, e.label);\n        }\n        return graph;\n    };\n\n    const maxRank = (g) => {\n        let rank = Number.NEGATIVE_INFINITY;\n        for (const node of g.nodes.values()) {\n            const x = node.label.rank;\n            if (x !== undefined && x > rank) {\n                rank = x;\n            }\n        }\n        return rank === Number.NEGATIVE_INFINITY ? undefined : rank;\n    };\n\n    // Given a DAG with each node assigned 'rank' and 'order' properties, this function will produce a matrix with the ids of each node.\n    const buildLayerMatrix = (g) => {\n        const rank = maxRank(g);\n        const length = rank === undefined ? 0 : rank + 1;\n        const layering = Array.from(new Array(length), () => []);\n        for (const node of g.nodes.values()) {\n            const label = node.label;\n            const rank = label.rank;\n            if (rank !== undefined) {\n                layering[rank][label.order] = node.v;\n            }\n        }\n        return layering;\n    };\n\n    // This idea comes from the Gansner paper: to account for edge labels in our layout we split each rank in half by doubling minlen and halving ranksep.\n    // Then we can place labels at these mid-points between nodes.\n    // We also add some minimal padding to the width to push the label for the edge away from the edge itself a bit.\n    const makeSpaceForEdgeLabels = (g, state, layout) => {\n        layout.ranksep /= 2;\n        const rankdir = layout.rankdir;\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            edge.minlen *= 2;\n            if (edge.labelpos.toLowerCase() !== 'c') {\n                if (rankdir === 'TB' || rankdir === 'BT') {\n                    edge.width += edge.labeloffset;\n                } else {\n                    edge.height += edge.labeloffset;\n                }\n            }\n        }\n    };\n\n    const removeSelfEdges = (g) => {\n        for (const e of g.edges.values()) {\n            if (e.v === e.w) {\n                const label = e.vNode.label;\n                if (!label.selfEdges) {\n                    label.selfEdges = [];\n                }\n                label.selfEdges.push({ e, label: e.label });\n                g.removeEdge(e);\n            }\n        }\n    };\n\n    const acyclic_run = (g) => {\n        const edges = [];\n        const visited = new Set();\n        const path = new Set();\n        const stack = Array.from(g.nodes.keys()).reverse();\n        while (stack.length > 0) {\n            const v = stack.pop();\n            if (Array.isArray(v)) {\n                path.delete(v[0]);\n            } else if (!visited.has(v)) {\n                visited.add(v);\n                path.add(v);\n                stack.push([v]);\n                const out = g.node(v).out;\n                for (let i = out.length - 1; i >= 0; i--) {\n                    const e = out[i];\n                    if (path.has(e.w)) {\n                        edges.push(e);\n                    }\n                    stack.push(e.w);\n                }\n            }\n        }\n        for (const e of edges) {\n            const label = e.label;\n            g.removeEdge(e);\n            label.forwardName = e.name;\n            label.reversed = true;\n            g.setEdge(e.w, e.v, label, uniqueId('rev'));\n        }\n    };\n    const acyclic_undo = (g) => {\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            if (edge.reversed) {\n                edge.points.reverse();\n                g.removeEdge(e);\n                const forwardName = edge.forwardName;\n                delete edge.reversed;\n                delete edge.forwardName;\n                g.setEdge(e.w, e.v, edge, forwardName);\n            }\n        }\n    };\n\n    // Returns the amount of slack for the given edge.\n    // The slack is defined as the difference between the length of the edge and its minimum length.\n    const slack = (g, e) => {\n        return e.wNode.label.rank - e.vNode.label.rank - e.label.minlen;\n    };\n\n    // Assigns a rank to each node in the input graph that respects the 'minlen' constraint specified on edges between nodes.\n    // This basic structure is derived from Gansner, et al., 'A Technique for Drawing Directed Graphs.'\n    //\n    // Pre-conditions:\n    //    1. Graph must be a connected DAG\n    //    2. Graph nodes must be objects\n    //    3. Graph edges must have 'weight' and 'minlen' attributes\n    //\n    // Post-conditions:\n    //    1. Graph nodes will have a 'rank' attribute based on the results of the\n    //       algorithm. Ranks can start at any index (including negative), we'll\n    //       fix them up later.\n    const rank = (g) => {\n        g = asNonCompoundGraph(g);\n        // Constructs a spanning tree with tight edges and adjusted the input node's ranks to achieve this.\n        // A tight edge is one that is has a length that matches its 'minlen' attribute.\n        // The basic structure for this function is derived from Gansner, et al., 'A Technique for Drawing Directed Graphs.'\n        //\n        // Pre-conditions:\n        //    1. Graph must be a DAG.\n        //    2. Graph must be connected.\n        //    3. Graph must have at least one node.\n        //    5. Graph nodes must have been previously assigned a 'rank' property that respects the 'minlen' property of incident edges.\n        //    6. Graph edges must have a 'minlen' property.\n        //\n        // Post-conditions:\n        //    - Graph nodes will have their rank adjusted to ensure that all edges are tight.\n        //\n        // Returns a tree (undirected graph) that is constructed using only 'tight' edges.\n        const feasibleTree = (g) => {\n            const t = new dagre.Graph(false, false);\n            // Choose arbitrary node from which to start our tree\n            const start = g.nodes.keys().next().value;\n            const size = g.nodes.size;\n            t.setNode(start, {});\n            // Finds a maximal tree of tight edges and returns the number of nodes in the tree.\n            const tightTree = (t, g) => {\n                const stack = Array.from(t.nodes.keys()).reverse();\n                while (stack.length > 0) {\n                    const v = stack.pop();\n                    const node = g.node(v);\n                    for (const e of node.in.concat(node.out)) {\n                        const edgeV = e.v;\n                        const w = (v === edgeV) ? e.w : edgeV;\n                        if (!t.hasNode(w) && !slack(g, e)) {\n                            t.setNode(w, {});\n                            t.setEdge(v, w, {});\n                            stack.push(w);\n                        }\n                    }\n                }\n                return t.nodes.size;\n            };\n            while (tightTree(t, g) < size) {\n                // Finds the edge with the smallest slack that is incident on tree and returns it.\n                let minKey = Number.MAX_SAFE_INTEGER;\n                let edge = null;\n                for (const e of g.edges.values()) {\n                    if (t.hasNode(e.v) !== t.hasNode(e.w)) {\n                        const key = slack(g, e);\n                        if (key < minKey) {\n                            minKey = key;\n                            edge = e;\n                        }\n                    }\n                }\n                const delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);\n                for (const v of t.nodes.keys()) {\n                    g.node(v).label.rank += delta;\n                }\n            }\n            return t;\n        };\n        // Initializes ranks for the input graph using the longest path algorithm.\n        // This algorithm scales well and is fast in practice, it yields rather poor solutions.\n        // Nodes are pushed to the lowest layer possible, leaving the bottom ranks wide and leaving edges longer than necessary.\n        // However, due to its speed, this algorithm is good for getting an initial ranking that can be fed into other algorithms.\n        //\n        // This algorithm does not normalize layers because it will be used by other algorithms in most cases.\n        // If using this algorithm directly, be sure to run normalize at the end.\n        //\n        // Pre-conditions:\n        //    1. Input graph is a DAG.\n        //    2. Input graph node labels can be assigned properties.\n        //\n        // Post-conditions:\n        //    1. Each node will be assign an (unnormalized) 'rank' property.\n        const longestPath = (g) => {\n            const visited = new Set();\n            const stack = [Array.from(g.nodes.values()).filter((node) => node.in.length === 0).reverse()];\n            while (stack.length > 0) {\n                const current = stack[stack.length - 1];\n                if (Array.isArray(current)) {\n                    const node = current.pop();\n                    if (current.length === 0) {\n                        stack.pop();\n                    }\n                    if (!visited.has(node)) {\n                        visited.add(node);\n                        const children = node.out.map((e) => e.wNode);\n                        if (children.length > 0) {\n                            stack.push(node);\n                            stack.push(children.reverse());\n                        } else {\n                            node.label.rank = 0;\n                        }\n                    }\n                } else {\n                    stack.pop();\n                    let rank = Number.MAX_SAFE_INTEGER;\n                    for (const e of current.out) {\n                        rank = Math.min(rank, e.wNode.label.rank - e.label.minlen);\n                    }\n                    current.label.rank = rank;\n                }\n            }\n        };\n        // The network simplex algorithm assigns ranks to each node in the input graph\n        // and iteratively improves the ranking to reduce the length of edges.\n        //\n        // Preconditions:\n        //    1. The input graph must be a DAG.\n        //    2. All nodes in the graph must have an object value.\n        //    3. All edges in the graph must have 'minlen' and 'weight' attributes.\n        //\n        // Postconditions:\n        //    1. All nodes in the graph will have an assigned 'rank' attribute that has\n        //       been optimized by the network simplex algorithm. Ranks start at 0.\n        //\n        // A rough sketch of the algorithm is as follows:\n        //    1. Assign initial ranks to each node. We use the longest path algorithm,\n        //       which assigns ranks to the lowest position possible. In general this\n        //       leads to very wide bottom ranks and unnecessarily long edges.\n        //    2. Construct a feasible tight tree. A tight tree is one such that all\n        //       edges in the tree have no slack (difference between length of edge\n        //       and minlen for the edge). This by itself greatly improves the assigned\n        //       rankings by shorting edges.\n        //    3. Iteratively find edges that have negative cut values. Generally a\n        //       negative cut value indicates that the edge could be removed and a new\n        //       tree edge could be added to produce a more compact graph.\n        //\n        // Much of the algorithms here are derived from Gansner, et al., 'A Technique\n        // for Drawing Directed Graphs.' The structure of the file roughly follows the\n        // structure of the overall algorithm.\n        const networkSimplex = (g) => {\n            // Returns a new graph with only simple edges. Handles aggregation of data associated with multi-edges.\n            const simplify = (g) => {\n                const graph = new dagre.Graph(true, false);\n                for (const node of g.nodes.values()) {\n                    graph.setNode(node.v, node.label);\n                }\n                for (const e of g.edges.values()) {\n                    const simpleEdge =  graph.edge(e.v, e.w);\n                    const simpleLabel = simpleEdge ? simpleEdge.label : { weight: 0, minlen: 1 };\n                    const label = e.label;\n                    graph.setEdge(e.v, e.w, {\n                        weight: simpleLabel.weight + label.weight,\n                        minlen: Math.max(simpleLabel.minlen, label.minlen)\n                    });\n                }\n                return graph;\n            };\n            const initLowLimValues = (tree, root) => {\n                const dfs = (tree, visited, start) => {\n                    let nextLim = 1;\n                    const nodes = new Map();\n                    const stack = [[start, null, 0]];\n                    while (stack.length > 0) {\n                        const [v, parent, state] = stack.pop();\n                        if (state === 0) {\n                            if (!visited.has(v)) {\n                                visited.add(v);\n                                const label = tree.node(v).label;\n                                const low = nextLim;\n                                nodes.set(v, { label, low, parent, lim: null });\n                                stack.push([v, parent, 1]);\n                                for (const w of tree.neighbors(v)) {\n                                    if (!visited.has(w)) {\n                                        stack.push([w, v, 0]);\n                                    }\n                                }\n                            }\n                        } else {\n                            const data = nodes.get(v);\n                            const label = data.label;\n                            label.low = data.low;\n                            label.lim = nextLim++;\n                            if (data.parent) {\n                                label.parent = data.parent;\n                            } else {\n                                delete label.parent;\n                            }\n                        }\n                    }\n                };\n                root = tree.nodes.keys().next().value;\n                const visited = new Set();\n                dfs(tree, visited, root);\n            };\n            // Initializes cut values for all edges in the tree.\n            const initCutValues = (t, g) => {\n                const vs = [];\n                const visited = new Set();\n                const stack = [Array.from(t.nodes.keys()).reverse()];\n                while (stack.length > 0) {\n                    const current = stack[stack.length - 1];\n                    if (Array.isArray(current)) {\n                        const v = current.pop();\n                        if (current.length === 0) {\n                            stack.pop();\n                        }\n                        if (!visited.has(v)) {\n                            visited.add(v);\n                            const children = t.neighbors(v);\n                            if (children.size > 0) {\n                                stack.push(v);\n                                stack.push(Array.from(children).reverse());\n                            } else {\n                                vs.push(v);\n                            }\n                        }\n                    } else {\n                        vs.push(stack.pop());\n                    }\n                }\n                for (const v of vs.slice(0, vs.length - 1)) {\n                    // Given the tight tree, its graph, and a child in the graph calculate and\n                    // return the cut value for the edge between the child and its parent.\n                    const childLabel = t.node(v).label;\n                    const parent = childLabel.parent;\n                    // The graph's view of the tree edge we're inspecting\n                    const edge = g.edge(v, parent);\n                    // True if the child is on the tail end of the edge in the directed graph\n                    const childIsTail = edge ? true : false;\n                    // The accumulated cut value for the edge between this node and its parent\n                    const graphEdge = edge ? edge.label : g.edge(parent, v).label;\n                    let cutValue = graphEdge.weight;\n                    const node = g.node(v);\n                    for (const e of node.in.concat(node.out)) {\n                        const isOutEdge = e.v === v;\n                        const other = isOutEdge ? e.w : e.v;\n                        if (other !== parent) {\n                            const pointsToHead = isOutEdge === childIsTail;\n                            cutValue += pointsToHead ? e.label.weight : -e.label.weight;\n                            const edge = t.edge(v, other);\n                            if (edge) {\n                                const otherCutValue = edge.label.cutvalue;\n                                cutValue += pointsToHead ? -otherCutValue : otherCutValue;\n                            }\n                        }\n                    }\n                    t.edge(v, parent).label.cutvalue = cutValue;\n                }\n            };\n            const leaveEdge = (tree) => {\n                return Array.from(tree.edges.values()).find((e) => e.label.cutvalue < 0);\n            };\n            const enterEdge = (t, g, edge) => {\n                let v = edge.v;\n                let w = edge.w;\n                // For the rest of this function we assume that v is the tail and w is the\n                // head, so if we don't have this edge in the graph we should flip it to\n                // match the correct orientation.\n                if (!g.edge(v, w)) {\n                    v = edge.w;\n                    w = edge.v;\n                }\n                const vLabel = t.node(v).label;\n                const wLabel = t.node(w).label;\n                let tailLabel = vLabel;\n                let flip = false;\n                // If the root is in the tail of the edge then we need to flip the logic that\n                // checks for the head and tail nodes in the candidates function below.\n                if (vLabel.lim > wLabel.lim) {\n                    tailLabel = wLabel;\n                    flip = true;\n                }\n                // Returns true if the specified node is descendant of the root node per the assigned low and lim attributes in the tree.\n                const isDescendant = (vLabel, rootLabel) => {\n                    return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;\n                };\n                let minKey = Number.POSITIVE_INFINITY;\n                let minValue = null;\n                for (const edge of g.edges.values()) {\n                    if (flip === isDescendant(t.node(edge.v).label, tailLabel) &&\n                        flip !== isDescendant(t.node(edge.w).label, tailLabel)) {\n                        const key = slack(g, edge);\n                        if (key < minKey) {\n                            minKey = key;\n                            minValue = edge;\n                        }\n                    }\n                }\n                return minValue;\n            };\n            const exchangeEdges = (t, g, e, f) => {\n                t.removeEdge(e);\n                t.setEdge(f.v, f.w, {});\n                initLowLimValues(t);\n                initCutValues(t, g);\n                // update ranks\n                const root = Array.from(t.nodes.keys()).find((v) => !g.node(v).label.parent);\n                const stack = [root];\n                const visited = new Set();\n                while (stack.length > 0) {\n                    const v = stack.pop();\n                    if (!visited.has(v)) {\n                        visited.add(v);\n                        const neighbors = Array.from(t.neighbors(v));\n                        for (let i = neighbors.length - 1; i >= 0; i--) {\n                            stack.push(neighbors[i]);\n                        }\n                    }\n                }\n                const vs = Array.from(visited);\n                for (const v of vs.slice(1)) {\n                    const parent = t.node(v).label.parent;\n                    let edge = g.edge(v, parent);\n                    let flipped = false;\n                    if (!edge) {\n                        edge = g.edge(parent, v);\n                        flipped = true;\n                    }\n                    g.node(v).label.rank = g.node(parent).label.rank + (flipped ? edge.label.minlen : -edge.label.minlen);\n                }\n            };\n            g = simplify(g);\n            longestPath(g);\n            const t = feasibleTree(g);\n            initLowLimValues(t);\n            initCutValues(t, g);\n            let e = null;\n            let f = null;\n            while ((e = leaveEdge(t))) {\n                f = enterEdge(t, g, e);\n                exchangeEdges(t, g, e, f);\n            }\n        };\n        switch (layout.ranker) {\n            case 'tight-tree':\n                longestPath(g);\n                feasibleTree(g);\n                break;\n            case 'longest-path':\n                longestPath(g);\n                break;\n            default:\n                networkSimplex(g);\n                break;\n        }\n    };\n\n    // Creates temporary dummy nodes that capture the rank in which each edge's label is going to, if it has one of non-zero width and height.\n    // We do this so that we can safely remove empty ranks while preserving balance for the label's position.\n    const injectEdgeLabelProxies = (g) => {\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            if (edge.width && edge.height) {\n                const v = e.vNode.label;\n                const w = e.wNode.label;\n                addDummyNode(g, 'edge-proxy', { rank: (w.rank - v.rank) / 2 + v.rank, e }, '_ep');\n            }\n        }\n    };\n\n    const removeEmptyRanks = (g, state) => {\n        // Ranks may not start at 0, so we need to offset them\n        if (g.nodes.size > 0) {\n            let minRank = Number.MAX_SAFE_INTEGER;\n            let maxRank = Number.MIN_SAFE_INTEGER;\n            const nodes = Array.from(g.nodes.values());\n            for (const node of nodes) {\n                const label = node.label;\n                if (label.rank !== undefined) {\n                    minRank = Math.min(minRank, label.rank);\n                    maxRank = Math.max(maxRank, label.rank);\n                }\n            }\n            const size = maxRank - minRank;\n            if (size > 0) {\n                const layers = new Array(size);\n                for (const node of nodes) {\n                    const label = node.label;\n                    if (label.rank !== undefined) {\n                        const rank = label.rank - minRank;\n                        if (!layers[rank]) {\n                            layers[rank] = [];\n                        }\n                        layers[rank].push(node.v);\n                    }\n                }\n                let delta = 0;\n                const nodeRankFactor = state.nodeRankFactor;\n                for (let i = 0; i < layers.length; i++) {\n                    const vs = layers[i];\n                    if (vs === undefined && i % nodeRankFactor !== 0) {\n                        delta--;\n                    } else if (delta && vs) {\n                        for (const v of vs) {\n                            g.node(v).label.rank += delta;\n                        }\n                    }\n                }\n            }\n        }\n    };\n\n    // A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,\n    // adds appropriate edges to ensure that all cluster nodes are placed between\n    // these boundries, and ensures that the graph is connected.\n    // In addition we ensure, through the use of the minlen property, that nodes\n    // and subgraph border nodes do not end up on the same rank.\n    //\n    // Preconditions:\n    //    1. Input graph is a DAG\n    //    2. Nodes in the input graph has a minlen attribute\n    //\n    // Postconditions:\n    //   1. Input graph is connected.\n    //   2. Dummy nodes are added for the tops and bottoms of subgraphs.\n    //   3. The minlen attribute for nodes is adjusted to ensure nodes do not\n    //      get placed on the same rank as subgraph border nodes.\n    //\n    // The nesting graph idea comes from Sander, 'Layout of Compound Directed Graphs.'\n    const nestingGraph_run = (g, state) => {\n        const root = addDummyNode(g, 'root', {}, '_root');\n        const treeDepths = (g) => {\n            const depths = {};\n            const dfs = (v, depth) => {\n                for (const child of g.children(v)) {\n                    dfs(child, depth + 1);\n                }\n                depths[v] = depth;\n            };\n            for (const v of g.children()) {\n                dfs(v, 1);\n            }\n            return depths;\n        };\n        const dfs = (g, root, nodeSep, weight, height, depths, v) => {\n            const children = Array.from(g.children(v));\n            if (!children.length) {\n                if (v !== root) {\n                    g.setEdge(root, v, { weight: 0, minlen: nodeSep });\n                }\n                return;\n            }\n            const top = addDummyNode(g, 'border', { width: 0, height: 0 }, '_bt');\n            const bottom = addDummyNode(g, 'border', { width: 0, height: 0 }, '_bb');\n            const label = g.node(v).label;\n            g.hasBorder = true;\n            g.setParent(top, v);\n            label.borderTop = top;\n            g.setParent(bottom, v);\n            label.borderBottom = bottom;\n            for (const child of children) {\n                dfs(g, root, nodeSep, weight, height, depths, child);\n                const childNode = g.node(child).label;\n                const childTop = childNode.borderTop ? childNode.borderTop : child;\n                const childBottom = childNode.borderBottom ? childNode.borderBottom : child;\n                const thisWeight = childNode.borderTop ? weight : 2 * weight;\n                const minlen = childTop === childBottom ? height - depths[v] + 1 : 1;\n                g.setEdge(top, childTop, { weight: thisWeight, minlen, nestingEdge: true });\n                g.setEdge(childBottom, bottom, { weight: thisWeight, minlen, nestingEdge: true });\n            }\n            if (!g.parent(v)) {\n                g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });\n            }\n        };\n        const depths = treeDepths(g);\n        let height = 0;\n        for (const value of Object.values(depths)) {\n            if (value > height) {\n                height = value;\n            }\n        }\n        height -= 1;\n        const nodeSep = 2 * height + 1;\n        state.nestingRoot = root;\n        // Multiply minlen by nodeSep to align nodes on non-border ranks.\n        for (const e of g.edges.values()) {\n            e.label.minlen *= nodeSep;\n        }\n        // Calculate a weight that is sufficient to keep subgraphs vertically compact\n        const weight = Array.from(g.edges.values()).reduce((acc, e) => acc + e.label.weight, 0) + 1;\n        // Create border nodes and link them up\n        for (const child of g.children()) {\n            dfs(g, root, nodeSep, weight, height, depths, child);\n        }\n        // Save the multiplier for node layers for later removal of empty border layers.\n        state.nodeRankFactor = nodeSep;\n    };\n\n    const nestingGraph_cleanup = (g, state) => {\n        g.removeNode(state.nestingRoot);\n        delete state.nestingRoot;\n        for (const e of g.edges.values()) {\n            if (e.label.nestingEdge) {\n                g.removeEdge(e);\n            }\n        }\n    };\n\n    const assignRankMinMax = (g, state) => {\n        // Adjusts the ranks for all nodes in the graph such that all nodes v have rank(v) >= 0 and at least one node w has rank(w) = 0.\n        let min = Number.POSITIVE_INFINITY;\n        for (const node of g.nodes.values()) {\n            const rank = node.label.rank;\n            if (rank !== undefined && rank < min) {\n                min = rank;\n            }\n        }\n        for (const node of g.nodes.values()) {\n            const label = node.label;\n            if (label.rank !== undefined) {\n                label.rank -= min;\n            }\n        }\n        let maxRank = 0;\n        if (g.hasBorder) {\n            for (const node of g.nodes.values()) {\n                const label = node.label;\n                if (label.borderTop) {\n                    label.minRank = g.node(label.borderTop).label.rank;\n                    label.maxRank = g.node(label.borderBottom).label.rank;\n                    maxRank = Math.max(maxRank, label.maxRank);\n                }\n            }\n        }\n        state.maxRank = maxRank;\n    };\n\n    // Breaks any long edges in the graph into short segments that span 1 layer each.\n    // This operation is undoable with the denormalize function.\n    //\n    // Pre-conditions:\n    //   1. The input graph is a DAG.\n    //   2. Each node in the graph has a 'rank' property.\n    //\n    // Post-condition:\n    //   1. All edges in the graph have a length of 1.\n    //   2. Dummy nodes are added where edges have been split into segments.\n    //   3. The graph is augmented with a 'dummyChains' attribute which contains\n    //      the first dummy in each chain of dummy nodes produced.\n    const normalize = (g, state) => {\n        state.dummyChains = [];\n        for (const e of g.edges.values()) {\n            let v = e.v;\n            const w = e.w;\n            const name = e.name;\n            const edgeLabel = e.label;\n            const labelRank = edgeLabel.labelRank;\n            let vRank = g.node(v).label.rank;\n            const wRank = g.node(w).label.rank;\n            if (wRank !== vRank + 1) {\n                g.removeEdge(e);\n                let first = true;\n                vRank++;\n                while (vRank < wRank) {\n                    edgeLabel.points = [];\n                    delete e.key;\n                    const attrs = {\n                        width: 0, height: 0,\n                        edgeLabel,\n                        edgeObj: e,\n                        rank: vRank\n                    };\n                    const dummy = addDummyNode(g, 'edge', attrs, '_d');\n                    if (vRank === labelRank) {\n                        attrs.width = edgeLabel.width;\n                        attrs.height = edgeLabel.height;\n                        attrs.dummy = 'edge-label';\n                        attrs.labelpos = edgeLabel.labelpos;\n                    }\n                    g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);\n                    if (first) {\n                        state.dummyChains.push(dummy);\n                        first = false;\n                    }\n                    v = dummy;\n                    vRank++;\n                }\n                g.setEdge(v, w, { weight: edgeLabel.weight }, name);\n            }\n        }\n    };\n\n    const denormalize = (g, state) => {\n        for (let v of state.dummyChains) {\n            let label = g.node(v).label;\n            const edgeLabel = label.edgeLabel;\n            const e = label.edgeObj;\n            g.setEdge(e.v, e.w, edgeLabel, e.name);\n            while (label.dummy) {\n                const w = g.successors(v).keys().next().value;\n                g.removeNode(v);\n                edgeLabel.points.push({ x: label.x, y: label.y });\n                if (label.dummy === 'edge-label') {\n                    edgeLabel.x = label.x;\n                    edgeLabel.y = label.y;\n                    edgeLabel.width = label.width;\n                    edgeLabel.height = label.height;\n                }\n                v = w;\n                label = g.node(v).label;\n            }\n        }\n    };\n\n    const removeEdgeLabelProxies = (g) => {\n        for (const node of g.nodes.values()) {\n            const label = node.label;\n            if (label.dummy === 'edge-proxy') {\n                label.e.label.labelRank = label.rank;\n                g.removeNode(node.v);\n            }\n        }\n    };\n\n    const parentDummyChains = (g, state) => {\n        // Find a path from v to w through the lowest common ancestor (LCA). Return the full path and the LCA.\n        const findPath = (g, postorderNums, v, w) => {\n            const low = Math.min(postorderNums[v].low, postorderNums[w].low);\n            const lim = Math.max(postorderNums[v].lim, postorderNums[w].lim);\n            // Traverse up from v to find the LCA\n            let parent = v;\n            const vPath = [];\n            do {\n                parent = g.parent(parent);\n                vPath.push(parent);\n            }\n            while (parent && (postorderNums[parent].low > low || lim > postorderNums[parent].lim));\n            const lca = parent;\n            // Traverse from w to LCA\n            parent = w;\n            const wPath = [];\n            while ((parent = g.parent(parent)) !== lca) {\n                wPath.push(parent);\n            }\n            return { path: vPath.concat(wPath.reverse()), lca };\n        };\n        const postorder = (g) => {\n            const result = {};\n            let lim = 0;\n            const dfs = (v) => {\n                const low = lim;\n                for (const u of g.children(v)) {\n                    dfs(u);\n                }\n                result[v] = { low, lim: lim++ };\n            };\n            for (const v of g.children()) {\n                dfs(v);\n            }\n            return result;\n        };\n        const postorderNums = postorder(g);\n        for (let v of state.dummyChains || []) {\n            const node = g.node(v).label;\n            const edgeObj = node.edgeObj;\n            const pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w);\n            const path = pathData.path;\n            const lca = pathData.lca;\n            let pathIdx = 0;\n            let pathV = path[pathIdx];\n            let ascending = true;\n            while (v !== edgeObj.w) {\n                const node = g.node(v).label;\n                if (ascending) {\n                    while ((pathV = path[pathIdx]) !== lca && g.node(pathV).label.maxRank < node.rank) {\n                        pathIdx++;\n                    }\n                    if (pathV === lca) {\n                        ascending = false;\n                    }\n                }\n                if (!ascending) {\n                    while (pathIdx < path.length - 1 && g.node(path[pathIdx + 1]).label.minRank <= node.rank) {\n                        pathIdx++;\n                    }\n                    pathV = path[pathIdx];\n                }\n                g.setParent(v, pathV);\n                v = g.successors(v).keys().next().value;\n            }\n        }\n    };\n\n    const addBorderSegments = (g) => {\n        const addBorderNode = (g, prop, prefix, sg, sgNode, rank) => {\n            const label = { width: 0, height: 0, rank, borderType: prop };\n            const prev = sgNode[prop][rank - 1];\n            const curr = addDummyNode(g, 'border', label, prefix);\n            sgNode[prop][rank] = curr;\n            g.setParent(curr, sg);\n            if (prev) {\n                g.setEdge(prev, curr, { weight: 1 });\n            }\n        };\n        const queue = Array.from(g.children());\n        for (let i = 0; i < queue.length; i++) {\n            const v = queue[i];\n            const node = g.node(v).label;\n            if ('minRank' in node) {\n                node.borderLeft = [];\n                node.borderRight = [];\n                const maxRank = node.maxRank + 1;\n                for (let rank = node.minRank; rank < maxRank; rank++) {\n                    addBorderNode(g, 'borderLeft', '_bl', v, node, rank);\n                    addBorderNode(g, 'borderRight', '_br', v, node, rank);\n                }\n            }\n            const children = g.children(v);\n            for (const v of children) {\n                queue.push(v);\n            }\n        }\n    };\n\n    // Applies heuristics to minimize edge crossings in the graph and sets the best order solution as an order attribute on each node.\n    //\n    // Pre-conditions:\n    //    1. Graph must be DAG\n    //    2. Graph nodes must have the 'rank' attribute\n    //    3. Graph edges must have the 'weight' attribute\n    //\n    // Post-conditions:\n    //    1. Graph nodes will have an 'order' attribute based on the results of the algorithm.\n    const order = (g) => {\n        const sortSubgraph = (g, v, cg, biasRight) => {\n            // Given a list of entries of the form {v, barycenter, weight} and a constraint graph this function will resolve any conflicts between the constraint graph and the barycenters for the entries.\n            // If the barycenters for an entry would violate a constraint in the constraint graph then we coalesce the nodes in the conflict into a new node that respects the contraint and aggregates barycenter and weight information.\n            // This implementation is based on the description in Forster, 'A Fast and Simple Hueristic for Constrained Two-Level Crossing Reduction,' thought it differs in some specific details.\n            //\n            // Pre-conditions:\n            //    1. Each entry has the form {v, barycenter, weight}, or if the node has no barycenter, then {v}.\n            //\n            // Returns:\n            //    A new list of entries of the form {vs, i, barycenter, weight}.\n            //    The list `vs` may either be a singleton or it may be an aggregation of nodes ordered such that they do not violate constraints from the constraint graph.\n            //    The property `i` is the lowest original index of any of the elements in `vs`.\n            const resolveConflicts = (entries, cg) => {\n                const mappedEntries = new Map();\n                for (let i = 0; i < entries.length; i++) {\n                    const entry = entries[i];\n                    const tmp = { indegree: 0, 'in': [], out: [], vs: [entry.v], i };\n                    if (entry.barycenter !== undefined) {\n                        tmp.barycenter = entry.barycenter;\n                        tmp.weight = entry.weight;\n                    }\n                    mappedEntries.set(entry.v, tmp);\n                }\n                for (const e of cg.edges.values()) {\n                    const entryV = mappedEntries.get(e.v);\n                    const entryW = mappedEntries.get(e.w);\n                    if (entryV && entryW) {\n                        entryW.indegree++;\n                        entryV.out.push(entryW);\n                    }\n                }\n                const sourceSet = Array.from(mappedEntries.values()).filter((entry) => !entry.indegree);\n                const results = [];\n                const handleIn = function(vEntry) {\n                    return function(uEntry) {\n                        if (uEntry.merged) {\n                            return;\n                        }\n                        if (uEntry.barycenter === undefined || vEntry.barycenter === undefined || uEntry.barycenter >= vEntry.barycenter) {\n                            let sum = 0;\n                            let weight = 0;\n                            if (vEntry.weight) {\n                                sum += vEntry.barycenter * vEntry.weight;\n                                weight += vEntry.weight;\n                            }\n                            if (uEntry.weight) {\n                                sum += uEntry.barycenter * uEntry.weight;\n                                weight += uEntry.weight;\n                            }\n                            vEntry.vs = uEntry.vs.concat(vEntry.vs);\n                            vEntry.barycenter = sum / weight;\n                            vEntry.weight = weight;\n                            vEntry.i = Math.min(uEntry.i, vEntry.i);\n                            uEntry.merged = true;\n                        }\n                    };\n                };\n                const handleOut = (vEntry) => {\n                    return function(wEntry) {\n                        wEntry.in.push(vEntry);\n                        if (--wEntry.indegree === 0) {\n                            sourceSet.push(wEntry);\n                        }\n                    };\n                };\n                while (sourceSet.length) {\n                    const entry = sourceSet.pop();\n                    results.push(entry);\n                    entry.in.reverse().forEach(handleIn(entry));\n                    entry.out.forEach(handleOut(entry));\n                }\n                return results.filter((entry) => !entry.merged).map((entry) => {\n                    const value = {\n                        vs: entry.vs,\n                        i: entry.i\n                    };\n                    if (entry.barycenter !== undefined) {\n                        value.barycenter = entry.barycenter;\n                    }\n                    if (entry.weight !== undefined) {\n                        value.weight = entry.weight;\n                    }\n                    return value;\n                });\n            };\n            const barycenter = (g, movable) => {\n                return Array.from(movable).map((v) => {\n                    const inV = g.node(v).in;\n                    if (!inV.length) {\n                        return { v };\n                    }\n                    const result = inV.reduce((acc, e) => {\n                        const edge = e.label;\n                        const nodeU = e.vNode.label;\n                        return {\n                            sum: acc.sum + (edge.weight * nodeU.order),\n                            weight: acc.weight + edge.weight\n                        };\n                    }, { sum: 0, weight: 0 });\n                    return {\n                        v,\n                        barycenter: result.sum / result.weight,\n                        weight: result.weight\n                    };\n                });\n            };\n            const sort = (entries, biasRight) => {\n                const consumeUnsortable = (vs, unsortable, index) => {\n                    let last = null;\n                    while (unsortable.length && (last = unsortable[unsortable.length - 1]).i <= index) {\n                        unsortable.pop();\n                        vs.push(last.vs);\n                        index++;\n                    }\n                    return index;\n                };\n                const compareWithBias = (bias) => {\n                    return function(entryV, entryW) {\n                        if (entryV.barycenter < entryW.barycenter) {\n                            return -1;\n                        } else if (entryV.barycenter > entryW.barycenter) {\n                            return 1;\n                        }\n                        return bias ? entryW.i - entryV.i : entryV.i - entryW.i;\n                    };\n                };\n                // partition\n                const parts = { lhs: [], rhs: [] };\n                for (const value of entries) {\n                    if ('barycenter' in value) {\n                        parts.lhs.push(value);\n                    } else {\n                        parts.rhs.push(value);\n                    }\n                }\n                const sortable = parts.lhs;\n                const unsortable = parts.rhs.sort((a, b) => -a.i + b.i);\n                const vs = [];\n                let sum = 0;\n                let weight = 0;\n                let vsIndex = 0;\n                sortable.sort(compareWithBias(Boolean(biasRight)));\n                vsIndex = consumeUnsortable(vs, unsortable, vsIndex);\n                for (const entry of sortable) {\n                    vsIndex += entry.vs.length;\n                    vs.push(entry.vs);\n                    sum += entry.barycenter * entry.weight;\n                    weight += entry.weight;\n                    vsIndex = consumeUnsortable(vs, unsortable, vsIndex);\n                }\n                const result = { vs: flat(vs) };\n                if (weight) {\n                    result.barycenter = sum / weight;\n                    result.weight = weight;\n                }\n                return result;\n            };\n            const node = g.node(v);\n            const bl = node && node.label ? node.label.borderLeft : undefined;\n            const br = node && node.label ? node.label.borderRight : undefined;\n            const subgraphs = {};\n            const movable = bl ? Array.from(g.children(v)).filter((w) => w !== bl && w !== br) : g.children(v);\n            const barycenters = barycenter(g, movable);\n            for (const entry of barycenters) {\n                if (g.hasChildren(entry.v)) {\n                    const result = sortSubgraph(g, entry.v, cg, biasRight);\n                    subgraphs[entry.v] = result;\n                    if ('barycenter' in result) {\n                        if (entry.barycenter === undefined) {\n                            entry.barycenter = result.barycenter;\n                            entry.weight = result.weight;\n                        } else {\n                            entry.barycenter = (entry.barycenter * entry.weight + result.barycenter * result.weight) / (entry.weight + result.weight);\n                            entry.weight += result.weight;\n                        }\n                    }\n                }\n            }\n            const entries = resolveConflicts(barycenters, cg);\n            // expand subgraphs\n            for (const entry of entries) {\n                entry.vs = flat(entry.vs.map((v) => subgraphs[v] ? subgraphs[v].vs : v));\n            }\n            const result = sort(entries, biasRight);\n            if (bl) {\n                result.vs = flat([bl, result.vs, br]);\n                const predecessors = g.predecessors(bl);\n                if (predecessors.size > 0) {\n                    const blPred = g.node(predecessors.keys().next().value).label;\n                    const brPred = g.node(g.predecessors(br).keys().next().value).label;\n                    if (!('barycenter' in result)) {\n                        result.barycenter = 0;\n                        result.weight = 0;\n                    }\n                    result.barycenter = (result.barycenter * result.weight + blPred.order + brPred.order) / (result.weight + 2);\n                    result.weight += 2;\n                }\n            }\n            return result;\n        };\n        const sweepLayerGraphs = (layerGraphs, biasRight) => {\n            const cg = new dagre.Graph(true, false);\n            for (const lg of layerGraphs) {\n                const root = lg.root;\n                const sorted = sortSubgraph(lg, root, cg, biasRight);\n                const vs = sorted.vs;\n                const length = vs.length;\n                for (let i = 0; i < length; i++) {\n                    lg.node(vs[i]).label.order = i;\n                }\n                // add subgraph constraints\n                const prev = {};\n                let rootPrev = '';\n                let exit = false;\n                for (const v of vs) {\n                    let child = lg.parent(v);\n                    let prevChild = null;\n                    while (child) {\n                        const parent = lg.parent(child);\n                        if (parent) {\n                            prevChild = prev[parent];\n                            prev[parent] = child;\n                        } else {\n                            prevChild = rootPrev;\n                            rootPrev = child;\n                        }\n                        if (prevChild && prevChild !== child) {\n                            cg.setEdge(prevChild, child, null);\n                            exit = true;\n                            break;\n                        }\n                        child = parent;\n                    }\n                    if (exit) {\n                        break;\n                    }\n                }\n            }\n        };\n        // A function that takes a layering (an array of layers, each with an array of\n        // ordererd nodes) and a graph and returns a weighted crossing count.\n        //\n        // Pre-conditions:\n        //    1. Input graph must be simple (not a multigraph), directed, and include\n        //       only simple edges.\n        //    2. Edges in the input graph must have assigned weights.\n        //\n        // Post-conditions:\n        //    1. The graph and layering matrix are left unchanged.\n        //\n        // This algorithm is derived from Barth, et al., 'Bilayer Cross Counting.'\n        const crossCount = (g, layering, bestCC) => {\n            let count = 0;\n            for (let i = 1; i < layering.length; i++) {\n                const northLayer = layering[i - 1];\n                const southLayer = layering[i];\n                // Sort all of the edges between the north and south layers by their position in the north layer and then the south.\n                // Map these edges to the position of their head in the south layer.\n                const southPos = new Map();\n                for (let i = 0; i < southLayer.length; i++) {\n                    southPos.set(southLayer[i], i);\n                }\n                const southEntries = [];\n                for (const v of northLayer) {\n                    const entries = [];\n                    for (const e of g.node(v).out) {\n                        entries.push({\n                            pos: southPos.get(e.w),\n                            weight: e.label.weight\n                        });\n                    }\n                    entries.sort((a, b) => a.pos - b.pos);\n                    for (const entry of entries) {\n                        southEntries.push(entry);\n                    }\n                }\n                // Build the accumulator tree\n                let firstIndex = 1;\n                while (firstIndex < southLayer.length) {\n                    firstIndex <<= 1;\n                }\n                const treeSize = 2 * firstIndex - 1;\n                firstIndex -= 1;\n                const tree = Array.from(new Array(treeSize), () => 0);\n                // Calculate the weighted crossings\n                for (const entry of southEntries) {\n                    let index = entry.pos + firstIndex;\n                    tree[index] += entry.weight;\n                    let weightSum = 0;\n                    while (index > 0) {\n                        if (index % 2) {\n                            weightSum += tree[index + 1];\n                        }\n                        index = (index - 1) >> 1;\n                        tree[index] += entry.weight;\n                    }\n                    count += entry.weight * weightSum;\n                }\n                if (count > bestCC) {\n                    break;\n                }\n            }\n            return count;\n        };\n        // Assigns an initial order value for each node by performing a DFS search\n        // starting from nodes in the first rank. Nodes are assigned an order in their\n        // rank as they are first visited.\n        //\n        // This approach comes from Gansner, et al., 'A Technique for Drawing Directed\n        // Graphs.'\n        //\n        // Returns a layering matrix with an array per layer and each layer sorted by\n        // the order of its nodes.\n        const initOrder = (g) => {\n            const visited = new Set();\n            const nodes = Array.from(g.nodes.values()).filter((node) => !g.hasChildren(node.v));\n            let maxRank = -1;\n            for (const node of nodes) {\n                const rank = node.label.rank;\n                if (maxRank === -1 || (rank !== undefined && rank > maxRank)) {\n                    maxRank = rank;\n                }\n            }\n            if (maxRank !== -1) {\n                const layers = Array.from(new Array(maxRank + 1), () => []);\n                const queue = nodes.sort((a, b) => a.label.rank - b.label.rank).map((node) => node.v).reverse();\n                for (let i = 0; i < queue.length; i++) {\n                    const v = queue[i];\n                    if (!visited.has(v)) {\n                        visited.add(v);\n                        const rank = g.node(v).label.rank;\n                        layers[rank].push(v);\n                        queue.push(...g.successors(v).keys());\n                    }\n                }\n                return layers;\n            }\n            return [];\n        };\n        // Constructs a graph that can be used to sort a layer of nodes.\n        // The graph will contain all base and subgraph nodes from the request layer in their original\n        // hierarchy and any edges that are incident on these nodes and are of the type requested by the 'relationship' parameter.\n        //\n        // Nodes from the requested rank that do not have parents are assigned a root node in the output graph,\n        // which is set in the root graph attribute.\n        // This makes it easy to walk the hierarchy of movable nodes during ordering.\n        //\n        // Pre-conditions:\n        //    1. Input graph is a DAG\n        //    2. Base nodes in the input graph have a rank attribute\n        //    3. Subgraph nodes in the input graph has minRank and maxRank attributes\n        //    4. Edges have an assigned weight\n        //\n        // Post-conditions:\n        //    1. Output graph has all nodes in the movable rank with preserved hierarchy.\n        //    2. Root nodes in the movable layer are made children of the node\n        //       indicated by the root attribute of the graph.\n        //    3. Non-movable nodes incident on movable nodes, selected by the\n        //       relationship parameter, are included in the graph (without hierarchy).\n        //    4. Edges incident on movable nodes, selected by the relationship parameter, are added to the output graph.\n        //    5. The weights for copied edges are aggregated as need, since the output graph is not a multi-graph.\n        const buildLayerGraph = (g, nodes, rankIndexes, rank, relationship) => {\n            let root = '';\n            while (g.hasNode((root = uniqueId('_root')))) {\n                // continue\n            }\n            const graph = new dagre.Graph(true, true);\n            graph.root = root;\n            graph.setDefaultNodeLabel((v) => {\n                const node = g.node(v);\n                return node ? node.label : undefined;\n            });\n            const length = nodes.length;\n            if (g.hasBorder) {\n                let i = 0;\n                while (i < length) {\n                    const node = nodes[i++];\n                    const label = node.label;\n                    if (label.rank === rank || 'minRank' in label && 'maxRank' in label && label.minRank <= rank && rank <= label.maxRank) {\n                        const v = node.v;\n                        graph.setNode(v);\n                        const parent = g.parent(v);\n                        graph.setParent(v, parent || root);\n                        // This assumes we have only short edges!\n                        if (relationship) {\n                            for (const e of node.in) {\n                                graph.setEdge(e.v, v, { weight: e.label.weight });\n                            }\n                        } else {\n                            for (const e of node.out) {\n                                graph.setEdge(e.w, v, { weight: e.label.weight });\n                            }\n                        }\n                        if ('minRank' in label) {\n                            graph.setNode(v, {\n                                borderLeft: label.borderLeft[rank],\n                                borderRight: label.borderRight[rank]\n                            });\n                        }\n                    }\n                }\n            } else {\n                // When label.borderTop isn't set, labels don't have minRank and maxRank properties so checking them can be skipped.\n                // And in that case, iterating nodes can be sped up by presorting nodes and using start indexes of each rank.\n                let i = rankIndexes.get(rank);\n                while (i < length) {\n                    const node = nodes[i++];\n                    const label = node.label;\n                    if (label.rank !== rank) {\n                        break;\n                    }\n                    const v = node.v;\n                    graph.setNode(v);\n                    const parent = g.parent(v);\n                    graph.setParent(v, parent || root);\n                    // This assumes we have only short edges!\n                    if (relationship) {\n                        for (const e of node.in) {\n                            graph.setEdge(e.v, v, { weight: e.label.weight });\n                        }\n                    } else {\n                        for (const e of node.out) {\n                            graph.setEdge(e.w, v, { weight: e.label.weight });\n                        }\n                    }\n                }\n            }\n            return graph;\n        };\n        let layering = initOrder(g);\n        const assignOrder = (g, layering) => {\n            for (const layer of layering) {\n                for (let i = 0; i < layer.length; i++) {\n                    g.node(layer[i]).label.order = i;\n                }\n            }\n        };\n        assignOrder(g, layering);\n        const rank = maxRank(g) || 0;\n        const downLayerGraphs = new Array(rank);\n        const upLayerGraphs = new Array(rank);\n        const nodes = Array.from(g.nodes.values());\n        let rankIndexes = null;\n        if (!g.hasBorder) {\n            nodes.sort((a, b) => {\n                return a.label.rank - b.label.rank;\n            });\n            rankIndexes = new Map();\n            for (let i = 0; i < nodes.length; ++i) {\n                const node = nodes[i];\n                const rank = node.label.rank;\n                if (!rankIndexes.has(rank)) {\n                    rankIndexes.set(rank, i);\n                }\n            }\n        }\n        for (let i = 0; i < rank; i++) {\n            downLayerGraphs[i] = buildLayerGraph(g, nodes, rankIndexes, i + 1, true);\n            upLayerGraphs[i] = buildLayerGraph(g, nodes, rankIndexes, rank - i - 1, false);\n        }\n        let bestCC = Number.POSITIVE_INFINITY;\n        let best = [];\n        for (let i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {\n            sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);\n            layering = buildLayerMatrix(g);\n            const cc = crossCount(g, layering, bestCC);\n            if (cc < bestCC) {\n                lastBest = 0;\n                const length = layering.length;\n                best = new Array(length);\n                for (let j = 0; j < length; j++) {\n                    best[j] = layering[j].slice();\n                }\n                bestCC = cc;\n            }\n        }\n        // Reduce crossings\n        const calcDir = (idx0, idx1) => (idx0 < idx1) ? 1 : 2;\n        for (let i = 4; i < best.length; i += 2) {\n            const layer = best[i];\n            for (let j = 0; j < layer.length; ++j) {\n                const node = g.nodes.get(layer[j]);\n                if (node.in && node.in.length === 2) {\n                    let n0 = node.in[0].vNode.in[0].vNode;\n                    let n1 = node.in[1].vNode.in[0].vNode;\n                    const indexes = [];\n                    let dirTotal = 0;\n                    for (let k = i - 2; k >= 0; k -= 2) {\n                        const layer0 = best[k];\n                        const idx0 = layer0.indexOf(n0.v);\n                        const idx1 = layer0.indexOf(n1.v);\n                        const dir = calcDir(idx0, idx1);\n                        dirTotal |= dir;\n                        if (idx0 === idx1\n                            || Math.abs(idx0 - idx1) !== 1\n                            || n0.in.length !== 1\n                            || n1.in.length !== 1\n                            || n0.out.length !== 1\n                            || n1.out.length !== 1\n                        ) {\n                            if (dirTotal === 3) {\n                                const topDir = dir;\n                                let l = k + 2;\n                                while (indexes.length !== 0) {\n                                    const idx1 = indexes.pop();\n                                    const idx0 = indexes.pop();\n                                    const layer1 = best[l];\n                                    const layer2 = best[l - 1];\n                                    const idx2 = layer2.indexOf(g.node(layer1[idx0]).in[0].v);\n                                    const idx3 = layer2.indexOf(g.node(layer1[idx1]).in[0].v);\n                                    if (calcDir(idx0, idx1) !== topDir) {\n                                        [layer1[idx0], layer1[idx1]] = [layer1[idx1], layer1[idx0]];\n                                    }\n                                    if (calcDir(idx2, idx3) !== topDir) {\n                                        [layer2[idx2], layer2[idx3]] = [layer2[idx3], layer2[idx2]];\n                                    }\n                                    l += 2;\n                                }\n                            }\n                            break;\n                        }\n                        indexes.push(idx0, idx1);\n                        n0 = n0.in[0].vNode.in[0].vNode;\n                        n1 = n1.in[0].vNode.in[0].vNode;\n                    }\n                }\n            }\n        }\n        const exchange = (layer, node0, node1) => {\n            const index0 = layer.indexOf(node0.v);\n            const index1 = layer.indexOf(node1.v);\n            layer[index1] = node0.v;\n            layer[index0] = node1.v;\n        };\n        for (let i = 0; i < best.length - 2; i += 2) {\n            const layer0 = best[i];\n            const layer1 = best[i + 1];\n            const layer2 = best[i + 2];\n            for (let j = 0; j < layer0.length; ++j) {\n                const node0 = g.nodes.get(layer0[j]);\n                if (node0.out && node0.out.length >= 2) {\n                    for (let k = 0; k < node0.out.length - 1; ++k) {\n                        const node1d = node0.out[k].wNode;\n                        const node2d = node0.out[k + 1].wNode;\n                        const node1 = node1d.out[0].wNode;\n                        const node2 = node2d.out[0].wNode;\n                        if ((layer1.indexOf(node1d.v) < layer1.indexOf(node2d.v)) ^ (layer2.indexOf(node1.v) < layer2.indexOf(node2.v))) {\n                            exchange(layer1, node1d, node2d);\n                        }\n                    }\n                }\n            }\n            for (let j = 0; j < layer2.length; ++j) {\n                const node0 = g.nodes.get(layer2[j]);\n                if (node0.in && node0.in.length >= 2) {\n                    if (node0.in.length === 2) {\n                        const node1d = node0.in[0].vNode;\n                        const node2d = node0.in[1].vNode;\n                        const node1 = node1d.in[0].vNode;\n                        const node2 = node2d.in[0].vNode;\n                        if ((layer1.indexOf(node1d.v) < layer1.indexOf(node2d.v)) ^ (layer0.indexOf(node1.v) < layer0.indexOf(node2.v))) {\n                            exchange(layer1, node1d, node2d);\n                        }\n                    } else {\n                        const indexes1 = [];\n                        for (let k = 0; k < node0.in.length; ++k) {\n                            const node1 = node0.in[k].vNode;\n                            const node2 = node1.in[0].vNode;\n                            const idx0 = layer0.indexOf(node2.v);\n                            const idx1 = layer1.indexOf(node1.v);\n                            node0.in[k].idx0 = idx0;\n                            indexes1.push(idx1);\n                        }\n                        node0.in.sort((a, b) => a.idx0 - b.idx0);\n                        indexes1.sort((a, b) => a - b);\n                        for (let k = 0; k < indexes1.length; ++k) {\n                            layer1[indexes1[k]] = node0.in[k].v;\n                        }\n                    }\n                }\n            }\n        }\n        for (let i = 0; i < best.length - 4; i += 2) {\n            const layer0 = best[i];\n            const layer2 = best[i + 2];\n            const layer4 = best[i + 4];\n            if (layer2.length >= 2 && layer4.length >= 2) {\n                const layer1 = best[i + 1];\n                const layer3 = best[i + 3];\n                for (let j = 0; j < layer0.length; ++j) {\n                    const node0 = g.nodes.get(layer0[j]);\n                    if (node0.in && node0.out && node0.out.length >= 2) {\n                        for (let k = 0; k < node0.out.length - 1; ++k) {\n                            const node1u = node0.out[k].wNode;\n                            const node2u = node0.out[k + 1].wNode;\n                            const node1 = node1u.out[0].wNode;\n                            const node2 = node2u.out[0].wNode;\n                            if (node1.out.length === 1 && node2.out.length === 1) {\n                                const index1 = layer2.indexOf(node1.v);\n                                const index2 = layer2.indexOf(node2.v);\n                                if (index1 + 1 === index2) {\n                                    const node1d = node1.out[0].wNode;\n                                    const node2d = node2.out[0].wNode;\n                                    if (node1d.out.length === 1 && node2d.out.length === 1) {\n                                        const node3 = node1d.out[0].wNode;\n                                        const node4 = node2d.out[0].wNode;\n                                        const index3 = layer4.indexOf(node3.v);\n                                        const index4 = layer4.indexOf(node4.v);\n                                        if (index3 > index4) {\n                                            exchange(layer1, node1u, node2u);\n                                            exchange(layer2, node1, node2);\n                                            exchange(layer3, node1d, node2d);\n                                            ++k;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n                for (let j = 0; j < layer2.length - 1; ++j) {\n                    const node0 = g.nodes.get(layer2[j]);\n                    if (node0.in && node0.out && node0.in.length === 1 && node0.out.length === 1) {\n                        const node1 = g.nodes.get(layer2[j + 1]);\n                        if (node1.in && node1.out && node1.in.length === 1 && node1.out.length === 1) {\n                            const node0u = node0.in[0].vNode;\n                            const node1u = node1.in[0].vNode;\n                            if (node0u.in.length === 1 && node1u.in.length === 1) {\n                                const node2 = node0u.in[0].vNode;\n                                const node3 = node1u.in[0].vNode;\n                                let index0 = layer0.indexOf(node2.v);\n                                let index1 = layer0.indexOf(node3.v);\n                                if (index1 + 1 === index0) {\n                                    const node0d = node0.out[0].wNode;\n                                    const node1d = node1.out[0].wNode;\n                                    index0 = layer3.indexOf(node0d.v);\n                                    index1 = layer3.indexOf(node1d.v);\n                                    if (index0 + 1 === index1 && node0d.out[0].wNode === node1d.out[0].wNode) {\n                                        exchange(layer1, node0u, node1u);\n                                        exchange(layer2, node0, node1);\n                                        exchange(layer3, node0d, node1d);\n                                        j += 1;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        assignOrder(g, best);\n    };\n\n    const insertSelfEdges = (g) => {\n        const layers = buildLayerMatrix(g);\n        for (const layer of layers) {\n            let orderShift = 0;\n            layer.forEach((v, i) => {\n                const label = g.node(v).label;\n                label.order = i + orderShift;\n                if (label.selfEdges) {\n                    for (const selfEdge of label.selfEdges) {\n                        addDummyNode(g, 'selfedge', {\n                            width: selfEdge.label.width,\n                            height: selfEdge.label.height,\n                            rank: label.rank,\n                            order: i + (++orderShift),\n                            e: selfEdge.e,\n                            label: selfEdge.label\n                        }, '_se');\n                    }\n                    delete label.selfEdges;\n                }\n            });\n        }\n    };\n\n    const coordinateSystem_swapWidthHeight = (g) => {\n        for (const node of g.nodes.values()) {\n            const label = node.label;\n            const w = label.width;\n            label.width = label.height;\n            label.height = w;\n        }\n        for (const e of g.edges.values()) {\n            const label = e.label;\n            const w = label.width;\n            label.width = label.height;\n            label.height = w;\n        }\n    };\n\n    const coordinateSystem_adjust = (g, state, layout) => {\n        const rankDir = layout.rankdir.toLowerCase();\n        if (rankDir === 'lr' || rankDir === 'rl') {\n            coordinateSystem_swapWidthHeight(g);\n        }\n    };\n\n    const coordinateSystem_undo = (g, state, layout) => {\n        const rankDir = layout.rankdir.toLowerCase();\n        if (rankDir === 'bt' || rankDir === 'rl') {\n            for (const node of g.nodes.values()) {\n                node.label.y = -node.label.y;\n            }\n            for (const e of g.edges.values()) {\n                const edge = e.label;\n                for (const attr of edge.points) {\n                    attr.y = -attr.y;\n                }\n                if ('y' in edge) {\n                    edge.y = -edge.y;\n                }\n            }\n        }\n        if (rankDir === 'lr' || rankDir === 'rl') {\n            const swapXYOne = (attrs) => {\n                [attrs.x, attrs.y] = [attrs.y, attrs.x];\n            };\n            for (const node of g.nodes.values()) {\n                swapXYOne(node.label);\n            }\n            for (const e of g.edges.values()) {\n                const edge = e.label;\n                for (const e of edge.points) {\n                    swapXYOne(e);\n                }\n                if (edge.x !== undefined) {\n                    swapXYOne(edge);\n                }\n            }\n            coordinateSystem_swapWidthHeight(g);\n        }\n    };\n\n    const position = (g, state, layout) => {\n        const addConflict = (conflicts, v, w) => {\n            if (v > w) {\n                [v, w] = [w, v];\n            }\n            let conflictsV = conflicts.get(v);\n            if (!conflictsV) {\n                conflictsV = new Set();\n                conflicts.set(v, conflictsV);\n            }\n            conflictsV.add(w);\n        };\n        const hasConflict = (conflicts, v, w) => {\n            if (v > w) {\n                [v, w] = [w, v];\n            }\n            return conflicts.has(v) && conflicts.get(v).has(w);\n        };\n        const buildBlockGraph = (g, layout, layering, root, reverseSep) => {\n            const nodeSep = layout.nodesep;\n            const edgeSep = layout.edgesep;\n            const blockGraph = new dagre.Graph(true, false);\n            for (const layer of layering) {\n                let u = null;\n                for (const v of layer) {\n                    const vRoot = root.get(v);\n                    blockGraph.setNode(vRoot, {});\n                    if (u) {\n                        const uRoot = root.get(u);\n                        const vLabel = g.node(v).label;\n                        const wLabel = g.node(u).label;\n                        let sum = 0;\n                        let delta = 0;\n                        sum += vLabel.width / 2;\n                        if ('labelpos' in vLabel) {\n                            switch (vLabel.labelpos) {\n                                case 'l': delta = -vLabel.width / 2; break;\n                                case 'r': delta = vLabel.width / 2; break;\n                                default: throw new dagre.Error(`Unsupported label position '${vLabel.labelpos}'.`);\n                            }\n                        }\n                        if (delta) {\n                            sum += reverseSep ? delta : -delta;\n                        }\n                        delta = 0;\n                        sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;\n                        sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;\n                        sum += wLabel.width / 2;\n                        if ('labelpos' in wLabel) {\n                            switch (wLabel.labelpos) {\n                                case 'l': delta = wLabel.width / 2; break;\n                                case 'r': delta = -wLabel.width / 2; break;\n                                default: throw new dagre.Error(`Unsupported label position '${wLabel.labelpos}'.`);\n                            }\n                        }\n                        if (delta) {\n                            sum += reverseSep ? delta : -delta;\n                        }\n                        const edge = blockGraph.edge(uRoot, vRoot);\n                        const max = Math.max(sum, edge ? edge.label : 0);\n                        if (edge) {\n                            edge.label = max;\n                        } else {\n                            blockGraph.setEdge(uRoot, vRoot, max);\n                        }\n                    }\n                    u = v;\n                }\n            }\n            return blockGraph;\n        };\n        // Try to align nodes into vertical 'blocks' where possible.\n        // This algorithm attempts to align a node with one of its median neighbors.\n        // If the edge connecting a neighbor is a type-1 conflict then we ignore that possibility.\n        // If a previous node has already formed a block with a node after the node we're trying to form a block with,\n        // we also ignore that possibility - our blocks would be split in that scenario.\n        const verticalAlignment = (layering, conflicts, neighborFn) => {\n            const root = new Map();\n            const align = new Map();\n            const pos = new Map();\n            // We cache the position here based on the layering because the graph and layering may be out of sync.\n            // The layering matrix is manipulated to generate different extreme alignments.\n            for (const layer of layering) {\n                let order = 0;\n                for (const v of layer) {\n                    root.set(v, v);\n                    align.set(v, v);\n                    pos.set(v, order);\n                    order++;\n                }\n            }\n            for (const layer of layering) {\n                let prevIdx = -1;\n                for (const v of layer) {\n                    let ws = neighborFn(v);\n                    if (ws.size > 0) {\n                        ws = Array.from(ws.keys());\n                        ws = ws.sort((a, b) => pos.get(a) - pos.get(b));\n                        const mp = (ws.length - 1) / 2.0000001;\n                        const il = Math.ceil(mp);\n                        for (let i = Math.floor(mp); i <= il; i++) {\n                            const w = ws[i];\n                            if (align.get(v) === v && prevIdx < pos.get(w) && !hasConflict(conflicts, v, w)) {\n                                const x = root.get(w);\n                                align.set(w, v);\n                                align.set(v, x);\n                                root.set(v, x);\n                                prevIdx = pos.get(w);\n                            }\n                        }\n                    }\n                }\n            }\n            return { root, align };\n        };\n        const horizontalCompaction = (g, layout, layering, root, align, reverseSep) => {\n            // This portion of the algorithm differs from BK due to a number of problems.\n            // Instead of their algorithm we construct a new block graph and do two sweeps.\n            const blockG = buildBlockGraph(g, layout, layering, root, reverseSep);\n            const borderType = reverseSep ? 'borderLeft' : 'borderRight';\n            const xs = new Map();\n            // First pass, places blocks with the smallest possible coordinates.\n            if (blockG.nodes.size > 0) {\n                const stack = Array.from(blockG.nodes.keys());\n                const visited = new Set();\n                while (stack.length > 0) {\n                    const v = stack.pop();\n                    if (visited.has(v)) {\n                        let max = 0;\n                        for (const e of blockG.node(v).in) {\n                            max = Math.max(max, xs.get(e.v) + e.label);\n                        }\n                        xs.set(v, max);\n                    } else {\n                        visited.add(v);\n                        stack.push(v);\n                        stack.push(...blockG.predecessors(v).keys());\n                    }\n                }\n            }\n            // Second pass, removes unused space by moving blocks to the greatest coordinates without violating separation.\n            if (blockG.nodes.size > 0) {\n                const stack = Array.from(blockG.nodes.keys());\n                const visited = new Set();\n                while (stack.length > 0) {\n                    const v = stack.pop();\n                    if (visited.has(v)) {\n                        let min = Number.POSITIVE_INFINITY;\n                        for (const e of blockG.node(v).out) {\n                            min = Math.min(min, xs.get(e.w) - e.label);\n                        }\n                        const label = g.node(v).label;\n                        if (label.dummy) {\n                            continue;\n                        }\n                        if (min !== Number.POSITIVE_INFINITY && label.borderType !== borderType) {\n                            xs.set(v, Math.max(xs.get(v), min));\n                        }\n                    } else {\n                        visited.add(v);\n                        stack.push(v);\n                        stack.push(...blockG.successors(v).keys());\n                    }\n                }\n            }\n            // Assign x coordinates to all nodes\n            for (const v of align.values()) {\n                xs.set(v, xs.get(root.get(v)));\n            }\n            return xs;\n        };\n        // Marks all edges in the graph with a type-1 conflict with the 'type1Conflict' property.\n        // A type-1 conflict is one where a non-inner segment crosses an inner segment.\n        // An inner segment is an edge with both incident nodes marked with the 'dummy' property.\n        //\n        // This algorithm scans layer by layer, starting with the second, for type-1\n        // conflicts between the current layer and the previous layer. For each layer\n        // it scans the nodes from left to right until it reaches one that is incident\n        // on an inner segment. It then scans predecessors to determine if they have\n        // edges that cross that inner segment. At the end a final scan is done for all\n        // nodes on the current rank to see if they cross the last visited inner segment.\n        //\n        // This algorithm (safely) assumes that a dummy node will only be incident on a\n        // single node in the layers being scanned.\n        const findType1Conflicts = (g, layering) => {\n            const conflicts = new Map();\n            if (layering.length > 0) {\n                let [prev] = layering;\n                for (let k = 1; k < layering.length; k++) {\n                    const layer = layering[k];\n                    // last visited node in the previous layer that is incident on an inner segment.\n                    let k0 = 0;\n                    // Tracks the last node in this layer scanned for crossings with a type-1 segment.\n                    let scanPos = 0;\n                    const prevLayerLength = prev.length;\n                    const lastNode = layer[layer.length - 1];\n                    for (let i = 0; i < layer.length; i++) {\n                        const v = layer[i];\n                        const w = g.node(v).label.dummy ? Array.from(g.predecessors(v).keys()).find((u) => g.node(u).label.dummy) : null;\n                        if (w || v === lastNode) {\n                            const k1 = w ? g.node(w).label.order : prevLayerLength;\n                            for (const scanNode of layer.slice(scanPos, i + 1)) {\n                            // for (const scanNode of layer.slice(scanPos, scanPos + 1)) {\n                                const predecessors = g.predecessors(scanNode);\n                                if (predecessors.size > 0) {\n                                    for (const u of g.predecessors(scanNode).keys()) {\n                                        const uLabel = g.node(u).label;\n                                        const uPos = uLabel.order;\n                                        if ((uPos < k0 || k1 < uPos) && !(uLabel.dummy && g.node(scanNode).label.dummy)) {\n                                            addConflict(conflicts, u, scanNode);\n                                        }\n                                    }\n                                }\n                            }\n                            // scanPos += 1;\n                            scanPos = i + 1;\n                            k0 = k1;\n                        }\n                    }\n                    prev = layer;\n                }\n            }\n            return conflicts;\n        };\n        const findType2Conflicts = (g, layering) => {\n            const conflicts = new Map();\n            const scan = (south, southPos, southEnd, prevNorthBorder, nextNorthBorder) => {\n                for (let i = southPos; i < southEnd; i++) {\n                    const v = south[i];\n                    if (g.node(v).labeldummy) {\n                        for (const u of g.predecessors(v).keys()) {\n                            const uNode = g.node(u).label;\n                            if (uNode.dummy && (uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {\n                                addConflict(conflicts, u, v);\n                            }\n                        }\n                    }\n                }\n            };\n            if (layering.length > 0) {\n                /* eslint-disable no-loop-func */\n                let [north] = layering;\n                for (let i = 1; i < layering.length; i++) {\n                    const south = layering[i];\n                    let prevNorthPos = -1;\n                    let nextNorthPos = 0;\n                    let southPos = 0;\n                    south.forEach((v, southLookahead) => {\n                        if (g.node(v).label.dummy === 'border') {\n                            const predecessors = g.predecessors(v);\n                            if (predecessors.size > 0) {\n                                nextNorthPos = g.node(predecessors.keys().next().value).label.order;\n                                scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);\n                                southPos = southLookahead;\n                                prevNorthPos = nextNorthPos;\n                            }\n                        }\n                        scan(south, southPos, south.length, nextNorthPos, north.length);\n                    });\n                    north = south;\n                }\n                /* eslint-enable no-loop-func */\n            }\n            return conflicts;\n        };\n\n        g = asNonCompoundGraph(g);\n        const layering = buildLayerMatrix(g);\n        const ranksep = layout.ranksep;\n        // Assign y-coordinate based on rank\n        let y = 0;\n        for (const layer of layering) {\n            const maxHeight = layer.reduce((a, v) => Math.max(a, g.node(v).label.height), 0);\n            for (const v of layer) {\n                g.node(v).label.y = y + maxHeight / 2;\n            }\n            y += maxHeight + ranksep;\n        }\n        // Coordinate assignment based on Brandes and Köpf, 'Fast and Simple Horizontal Coordinate Assignment.'\n        const conflicts = new Map([...findType1Conflicts(g, layering).entries(), ...findType2Conflicts(g, layering).entries()]);\n        const xss = {};\n        for (const vertical of ['u', 'd']) {\n            let adjustedLayering = vertical === 'u' ? layering : Object.values(layering).reverse();\n            for (const horizontal of ['l', 'r']) {\n                if (horizontal === 'r') {\n                    adjustedLayering = adjustedLayering.map((layer) => Object.values(layer).reverse());\n                }\n                const neighborFn = (vertical === 'u' ? g.predecessors : g.successors).bind(g);\n                const align = verticalAlignment(adjustedLayering, conflicts, neighborFn);\n                const xs = horizontalCompaction(g, layout, adjustedLayering, align.root, align.align, horizontal === 'r');\n                if (horizontal === 'r') {\n                    for (const [key, value] of xs.entries(xs)) {\n                        xs.set(key, -value);\n                    }\n                }\n                xss[vertical + horizontal] = xs;\n            }\n        }\n        // Find smallest width alignment: Returns the alignment that has the smallest width of the given alignments.\n        let minWidth = Number.POSITIVE_INFINITY;\n        let minValue = null;\n        for (const xs of Object.values(xss)) {\n            let max = Number.NEGATIVE_INFINITY;\n            let min = Number.POSITIVE_INFINITY;\n            for (const [v, x] of xs.entries()) {\n                const halfWidth = g.node(v).label.width / 2;\n                max = Math.max(x + halfWidth, max);\n                min = Math.min(x - halfWidth, min);\n            }\n            const width = max - min;\n            if (width < minWidth) {\n                minWidth = width;\n                minValue = xs;\n            }\n        }\n        // Align the coordinates of each of the layout alignments such that\n        // left-biased alignments have their minimum coordinate at the same point as\n        // the minimum coordinate of the smallest width alignment and right-biased\n        // alignments have their maximum coordinate at the same point as the maximum\n        // coordinate of the smallest width alignment.\n        const alignTo = minValue;\n        const range = (values) => {\n            let min = Number.POSITIVE_INFINITY;\n            let max = Number.NEGATIVE_INFINITY;\n            for (const value of values) {\n                if (value < min) {\n                    min = value;\n                }\n                if (value > max) {\n                    max = value;\n                }\n            }\n            return [min, max];\n        };\n        const alignToRange = range(alignTo.values(alignTo));\n        for (const vertical of ['u', 'd']) {\n            for (const horizontal of ['l', 'r']) {\n                const alignment = vertical + horizontal;\n                const xs = xss[alignment];\n                if (xs !== alignTo) {\n                    const vsValsRange = range(xs.values());\n                    const delta = horizontal === 'l' ? alignToRange[0] - vsValsRange[0] : alignToRange[1] - vsValsRange[1];\n                    if (delta) {\n                        const list = new Map();\n                        for (const [key, value] of xs.entries()) {\n                            list.set(key, value + delta);\n                        }\n                        xss[alignment] = list;\n                    }\n                }\n            }\n        }\n        // balance\n        const align = layout.align;\n        if (align) {\n            const xs = xss[align.toLowerCase()];\n            for (const v of xss.ul.keys()) {\n                g.node(v).label.x = xs.get(v);\n            }\n        } else {\n            for (const v of xss.ul.keys()) {\n                const xs = [xss.ul.get(v), xss.ur.get(v), xss.dl.get(v), xss.dr.get(v)].sort((a, b) => a - b);\n                g.node(v).label.x = (xs[1] + xs[2]) / 2;\n            }\n        }\n    };\n\n    const positionSelfEdges = (g) => {\n        for (const node of g.nodes.values()) {\n            const label = node.label;\n            if (label.dummy === 'selfedge') {\n                const v = node.v;\n                const selfNode = g.node(label.e.v).label;\n                const x = selfNode.x + selfNode.width / 2;\n                const y = selfNode.y;\n                const dx = label.x - x;\n                const dy = selfNode.height / 2;\n                g.setEdge(label.e.v, label.e.w, label.label);\n                g.removeNode(v);\n                label.label.points = [\n                    { x: x + 2 * dx / 3, y: y - dy },\n                    { x: x + 5 * dx / 6, y: y - dy },\n                    { x: x +     dx    , y },\n                    { x: x + 5 * dx / 6, y: y + dy },\n                    { x: x + 2 * dx / 3, y: y + dy }\n                ];\n                label.label.x = label.x;\n                label.label.y = label.y;\n            }\n        }\n    };\n\n    const removeBorderNodes = (g) => {\n        for (const node of g.nodes.values()) {\n            const v = node.v;\n            if (g.hasChildren(v)) {\n                const label = node.label;\n                const t = g.node(label.borderTop).label;\n                const b = g.node(label.borderBottom).label;\n                const l = g.node(label.borderLeft[label.borderLeft.length - 1]).label;\n                const r = g.node(label.borderRight[label.borderRight.length - 1]).label;\n                label.width = Math.abs(r.x - l.x);\n                label.height = Math.abs(b.y - t.y);\n                label.x = l.x + label.width / 2;\n                label.y = t.y + label.height / 2;\n            }\n        }\n        for (const node of g.nodes.values()) {\n            if (node.label.dummy === 'border') {\n                g.removeNode(node.v);\n            }\n        }\n    };\n\n    const fixupEdgeLabelCoords = (g) => {\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            if ('x' in edge) {\n                if (edge.labelpos === 'l' || edge.labelpos === 'r') {\n                    edge.width -= edge.labeloffset;\n                }\n                switch (edge.labelpos) {\n                    case 'l': edge.x -= edge.width / 2 + edge.labeloffset; break;\n                    case 'r': edge.x += edge.width / 2 + edge.labeloffset; break;\n                    default: throw new dagre.Error(`Unsupported label position '${edge.labelpos}'.`);\n                }\n            }\n        }\n    };\n\n    const translateGraph = (g, state) => {\n        let minX = Number.POSITIVE_INFINITY;\n        let maxX = 0;\n        let minY = Number.POSITIVE_INFINITY;\n        let maxY = 0;\n        const getExtremes = (attrs) => {\n            const x = attrs.x;\n            const y = attrs.y;\n            const w = attrs.width;\n            const h = attrs.height;\n            minX = Math.min(minX, x - w / 2);\n            maxX = Math.max(maxX, x + w / 2);\n            minY = Math.min(minY, y - h / 2);\n            maxY = Math.max(maxY, y + h / 2);\n        };\n        for (const node of g.nodes.values()) {\n            getExtremes(node.label);\n        }\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            if ('x' in edge) {\n                getExtremes(edge);\n            }\n        }\n        for (const node of g.nodes.values()) {\n            node.label.x -= minX;\n            node.label.y -= minY;\n        }\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            for (const p of edge.points) {\n                p.x -= minX;\n                p.y -= minY;\n            }\n            if ('x' in edge) {\n                edge.x -= minX;\n            }\n            if ('y' in edge) {\n                edge.y -= minY;\n            }\n        }\n        state.width = maxX - minX;\n        state.height = maxY - minY;\n    };\n\n    const assignNodeIntersects = (g) => {\n        // Finds where a line starting at point ({x, y}) would intersect a rectangle\n        // ({x, y, width, height}) if it were pointing at the rectangle's center.\n        const intersectRect = (rect, point) => {\n            const x = rect.x;\n            const y = rect.y;\n            // Rectangle intersection algorithm from: http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes\n            const dx = point.x - x;\n            const dy = point.y - y;\n            if (dx === 0 && dy === 0) {\n                throw new Error('Not possible to find intersection inside of the rectangle');\n            }\n            let w = rect.width / 2;\n            let h = rect.height / 2;\n            if (Math.abs(dy) * w > Math.abs(dx) * h) {\n                // Intersection is top or bottom of rect.\n                h = dy < 0 ? -h : h;\n                return { x: x + (h * dx / dy), y: y + h };\n            }\n            // Intersection is left or right of rect.\n            w = dx < 0 ? -w : w;\n            return { x: x + w, y: y + (w * dy / dx) };\n        };\n        for (const e of g.edges.values()) {\n            const edge = e.label;\n            const vNode = e.vNode.label;\n            const wNode = e.wNode.label;\n            let p1 = null;\n            let p2 = null;\n            if (edge.points) {\n                [p1] = edge.points;\n                p2 = edge.points[edge.points.length - 1];\n            } else {\n                edge.points = [];\n                p1 = wNode;\n                p2 = vNode;\n            }\n            edge.points.unshift(intersectRect(vNode, p1));\n            edge.points.push(intersectRect(wNode, p2));\n        }\n    };\n\n    // Build layout graph\n    const g = new dagre.Graph(true, true);\n    for (const node of nodes) {\n        g.setNode(node.v, {\n            width: node.width,\n            height: node.height\n        });\n        if (node.parent) {\n            g.setParent(node.v, node.parent);\n        }\n    }\n    for (const edge of edges) {\n        g.setEdge(edge.v, edge.w, {\n            minlen: edge.minlen || 1,\n            weight: edge.weight || 1,\n            width: edge.width || 0,\n            height: edge.height || 0,\n            labeloffset: edge.labeloffset || 10,\n            labelpos: edge.labelpos || 'r'\n        });\n    }\n\n    // Run layout\n    layout = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: 'tb', ...layout };\n    const tasks = [\n        makeSpaceForEdgeLabels,\n        removeSelfEdges,\n        acyclic_run,\n        nestingGraph_run,\n        rank,\n        injectEdgeLabelProxies,\n        removeEmptyRanks,\n        nestingGraph_cleanup,\n        assignRankMinMax,\n        removeEdgeLabelProxies,\n        normalize,\n        parentDummyChains,\n        addBorderSegments,\n        order,\n        insertSelfEdges,\n        coordinateSystem_adjust,\n        position,\n        positionSelfEdges,\n        removeBorderNodes,\n        denormalize,\n        fixupEdgeLabelCoords,\n        coordinateSystem_undo,\n        translateGraph,\n        assignNodeIntersects,\n        acyclic_undo\n    ];\n    while (tasks.length > 0) {\n        // const start = Date.now();\n        const task = tasks.shift();\n        task(g, state, layout);\n        // const duration = Date.now() - start;\n        // console.log(`${task.name}: ${duration}ms`);\n    }\n\n    // Update source graph\n    for (const node of nodes) {\n        const label = g.node(node.v).label;\n        node.x = label.x;\n        node.y = label.y;\n        if (g.hasChildren(node.v)) {\n            node.width = label.width;\n            node.height = label.height;\n        }\n    }\n    for (const edge of edges) {\n        const label = g.edge(edge.v, edge.w).label;\n        edge.points = label.points;\n        if ('x' in label) {\n            edge.x = label.x;\n            edge.y = label.y;\n        }\n    }\n    if (state.log) {\n        state.log = g.toString();\n    }\n};\n\ndagre.Graph = class {\n\n    constructor(directed, compound) {\n        this.directed = directed;\n        this.compound = compound;\n        this._defaultNodeLabelFn = () => {\n            return undefined;\n        };\n        this.nodes = new Map();\n        this.edges = new Map();\n        if (this.compound) {\n            this._parent = new Map();\n            this._children = new Map();\n            this._children.set('\\x00', new Map());\n        }\n    }\n\n    setDefaultNodeLabel(newDefault) {\n        this._defaultNodeLabelFn = newDefault;\n    }\n\n    setNode(v, label) {\n        const node = this.nodes.get(v);\n        if (node) {\n            if (label) {\n                node.label = label;\n            }\n        } else {\n            const node = { label: label ? label : this._defaultNodeLabelFn(v), in: [], out: [], predecessors: new Map(), successors: new Map(), v };\n            this.nodes.set(v, node);\n            if (this.compound) {\n                this._parent.set(v, '\\x00');\n                this._children.set(v, new Map());\n                this._children.get('\\x00').set(v, true);\n            }\n        }\n    }\n\n    node(v) {\n        return this.nodes.get(v);\n    }\n\n    hasNode(v) {\n        return this.nodes.has(v);\n    }\n\n    removeNode(v) {\n        const node = this.nodes.get(v);\n        if (node) {\n            if (this.compound) {\n                this._children.get(this._parent.get(v)).delete(v);\n                this._parent.delete(v);\n                for (const child of this.children(v)) {\n                    this.setParent(child);\n                }\n                this._children.delete(v);\n            }\n            for (const edge of node.in.concat()) {\n                this.removeEdge(edge);\n            }\n            for (const edge of node.out.concat()) {\n                this.removeEdge(edge);\n            }\n            this.nodes.delete(v);\n        }\n    }\n\n    setParent(v, parent) {\n        if (!this.compound) {\n            throw new Error('Cannot set parent in a non-compound graph');\n        }\n        if (parent) {\n            for (let ancestor = parent; ancestor !== undefined; ancestor = this.parent(ancestor)) {\n                if (ancestor === v) {\n                    throw new Error(`Setting ${parent} as parent of ${v} would create a cycle.`);\n                }\n            }\n            this.setNode(parent);\n        } else {\n            parent = '\\x00';\n        }\n        this._children.get(this._parent.get(v)).delete(v);\n        this._parent.set(v, parent);\n        this._children.get(parent).set(v, true);\n    }\n\n    parent(v) {\n        if (this.compound) {\n            const parent = this._parent.get(v);\n            if (parent !== '\\x00') {\n                return parent;\n            }\n        }\n        return null;\n    }\n\n    children(v) {\n        if (this.compound) {\n            return this._children.get(v === undefined ? '\\x00' : v).keys();\n        } else if (v === undefined) {\n            return this.nodes.keys();\n        } else if (this.hasNode(v)) {\n            return [];\n        }\n        return null;\n    }\n\n    hasChildren(v) {\n        if (this.compound) {\n            return this._children.get(v === undefined ? '\\x00' : v).size > 0;\n        } else if (v === undefined) {\n            return this.nodes.size > 0;\n        }\n        return false;\n    }\n\n    predecessors(v) {\n        return this.nodes.get(v).predecessors;\n    }\n\n    successors(v) {\n        return this.nodes.get(v).successors;\n    }\n\n    neighbors(v) {\n        const n = this.nodes.get(v);\n        const p = n.predecessors.keys();\n        const s = n.successors.keys();\n        const set = new Set();\n        for (const k of p) {\n            set.add(k);\n        }\n        for (const k of s) {\n            set.add(k);\n        }\n        return set;\n    }\n\n    edge(v, w) {\n        return this.edges.get(this._edgeKey(this.directed, v, w));\n    }\n\n    setEdge(v, w, label, name) {\n        const key = this._edgeKey(this.directed, v, w, name);\n        const edge = this.edges.get(key);\n        if (edge) {\n            edge.label = label;\n        } else {\n            if (!this.directed && v > w) {\n                [v, w] = [w, v];\n            }\n            const edge = { label, v, w, name, key, vNode: null, wNode: null };\n            this.edges.set(key, edge);\n            this.setNode(v);\n            this.setNode(w);\n            const wNode = this.nodes.get(w);\n            const vNode = this.nodes.get(v);\n            edge.wNode = wNode;\n            edge.vNode = vNode;\n            const incrementOrInitEntry = (map, k) => {\n                map.set(k, (map.get(k) ?? 0) + 1);\n            };\n            incrementOrInitEntry(wNode.predecessors, v);\n            incrementOrInitEntry(vNode.successors, w);\n            wNode.in.push(edge);\n            vNode.out.push(edge);\n        }\n    }\n\n    removeEdge(edge) {\n        const key = edge.key;\n        const v = edge.v;\n        const w = edge.w;\n        const wNode = edge.wNode;\n        const vNode = edge.vNode;\n        if (wNode.predecessors.has(v)) {\n            const value = wNode.predecessors.get(v);\n            if (value === 1) {\n                wNode.predecessors.delete(v);\n            } else {\n                wNode.predecessors.set(v, value - 1);\n            }\n        }\n        if (vNode.successors.has(w)) {\n            const value = vNode.successors.get(w);\n            if (value === 1) {\n                vNode.successors.delete(w);\n            } else {\n                vNode.successors.set(w, value - 1);\n            }\n        }\n        // Update arrays in-place\n        const idxIn = wNode.in.findIndex((e) => e.key === key);\n        if (idxIn !== -1) {\n            wNode.in.splice(idxIn, 1);\n        }\n        const idxOut = vNode.out.findIndex((e) => e.key === key);\n        if (idxOut !== -1) {\n            vNode.out.splice(idxOut, 1);\n        }\n        this.edges.delete(key);\n    }\n\n    _edgeKey(isDirected, v, w, name) {\n        if (!isDirected && v > w) {\n            return name ? `${w}:${v}:${name}` : `${w}:${v}:`;\n        }\n        return name ? `${v}:${w}:${name}` : `${v}:${w}:`;\n    }\n\n    toString() {\n        return [\n            '[nodes]', Array.from(this.nodes.values()).map((n) => JSON.stringify(n.label)).join('\\n'),\n            '[edges]', Array.from(this.edges.values()).map((e) => JSON.stringify(e.label)).join('\\n'),\n            '[parents]', JSON.stringify(this._parent, null, 2),\n            '[children]', JSON.stringify(this._children, null, 2)\n        ].join('\\n');\n    }\n};\n\nexport const { layout, Graph } = dagre;"
  },
  {
    "path": "source/darknet-metadata.json",
    "content": "[\n  {\n    \"name\": \"avgpool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"batchnorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"connected\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"output\", \"type\": \"int32\", \"visible\": false, \"default\": 1 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" },\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"conv_lstm\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"linear\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 3 },\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"dilation\", \"default\": 1 },\n      { \"name\": \"groups\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"padding\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"xnor\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"shortcut\", \"default\": 0 },\n      { \"name\": \"output\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"state_constrain\", \"type\": \"int32\", \"default\": 16 },\n      { \"name\": \"peephole\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"convolutional\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"filters\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_x\", \"type\": \"int32\", \"default\": -1 },\n      { \"name\": \"stride_y\", \"type\": \"int32\", \"default\": -1 },\n      { \"name\": \"groups\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"padding\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation\", \"default\": 1 },\n      { \"name\": \"share_index\", \"default\": -1000000000 },\n      { \"name\": \"binary\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"xnor\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bin_output\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"flipped\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dot\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" }\n    ]\n  },\n  {\n    \"name\": \"cost\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"string\", \"default\": \"sse\" },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"ratio\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"crnn\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\" },\n      { \"name\": \"dilation\", \"default\": 1 },\n      { \"name\": \"padding\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"groups\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"xnor\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"shortcut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"output_filters\", \"default\": 1 },\n      { \"name\": \"hidden_filters\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"crop\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"crop_height\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"crop_width\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"flip\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"exposure\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"saturation\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"angle\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"noadjust\", \"default\": 0 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"deconvolutional\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"filters\", \"type\": \"int32\", \"visible\": false, \"default\": 1 },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"padding\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" }\n    ]\n  },\n  {\n    \"name\": \"detection\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"classes\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"coord\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"num\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"jitter\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"coord_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"object_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"noobject_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"class_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"forced\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"side\", \"type\": \"int32\", \"default\": 7 },\n      { \"name\": \"softmax\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"sqrt\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"max\", \"type\": \"int32\", \"default\": 30 },\n      { \"name\": \"rescore\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"random\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"reorg\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"dropout\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"probability\", \"type\": \"float32\", \"default\": 0.5 },\n      { \"name\": \"dropblock\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dropblock_size_rel\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"dropblock_size_abs \", \"type\": \"int32\", \"default\": 7 }\n    ]\n  },\n  {\n    \"name\": \"elu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"gaussian_yolo\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"classes\", \"type\": \"int32\", \"default\": 20 },\n      { \"name\": \"num\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"mask\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"jitter\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"label_smooth_eps\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"scale_x_y\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"uc_normalizer\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"iou_normalizer\", \"type\": \"float32\", \"default\": 0.75 },\n      { \"name\": \"cls_normalizer\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"iou_loss\", \"type\": \"string\", \"default\": \"mse\", \"description\": \"options are: mse, giou, diou, and ciou\" },\n      { \"name\": \"max\", \"default\": 90 },\n      { \"name\": \"ignore_thresh\", \"type\": \"float32\", \"default\": 0.5 },\n      { \"name\": \"truth_thresh\", \"default\": 1 },\n      { \"name\": \"iou_thresh\", \"type\": \"float32\", \"default\": 1, \"description\": \"recommended to use iou_thresh=0.213\" },\n      { \"name\": \"random\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"map\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"beta_nms\", \"type\": \"float32\", \"default\": 0.6 },\n      { \"name\": \"nms_kind\", \"type\": \"string\", \"default\": \"default\", \"description\": \"options are: greedynms, diounms, cornersnms, or defaultnms\" },\n      { \"name\": \"anchors\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"yolo_point\", \"type\": \"string\", \"default\": \"center\", \"description\": \"options are: center, left_top, and right_bottom\" }\n    ]\n  },\n  {\n    \"name\": \"gru\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"output\", \"type\": \"int32\", \"visible\": false, \"default\": 1 },\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"h_swish\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"hardtan\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"leaky\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"lhtan\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"linear\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"local\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"filters\", \"type\": \"int32\", \"visible\": false, \"default\": 1 },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"padding\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" }\n    ]\n  },\n  {\n    \"name\": \"loggy\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"logistic\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"lstm\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"output\", \"type\": \"int32\", \"visible\": false, \"default\": 1 },\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"maxpool\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_x\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_y\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"padding\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"maxpool_depth\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"out_channels\", \"default\": 1 },\n      { \"name\": \"antialiasing\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"mish\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"net\",\n    \"attributes\": [\n      { \"name\": \"batch\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"max_batches\", \"type\": \"int32\", \"default\": 0, \"description\": \"Limits the maximum number of iterations\" },\n      { \"name\": \"learning_rate\", \"type\": \"float32\", \"default\": 0.001 },\n      { \"name\": \"momentum\", \"type\": \"float32\", \"default\": 0.9 },\n      { \"name\": \"decay\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"subdivisions\", \"type\": \"int32\", \"default\": 1, \"description\": \"In concert with batch property, this greatly affect memory usage, minimal working number is recommended\" },\n      { \"name\": \"time_steps\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"notruth\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"random\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"adam\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"B1\", \"type\": \"float32\", \"default\": 0.9 },\n      { \"name\": \"B2\", \"type\": \"float32\", \"default\": 0.999 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 1e-7 },\n      { \"name\": \"height\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"width\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channels\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"inputs\", \"type\": \"int32\" },\n      { \"name\": \"max_crop\", \"type\": \"int32\" },\n      { \"name\": \"min_crop\", \"type\": \"int32\" },\n      { \"name\": \"max_ratio\", \"type\": \"float32\" },\n      { \"name\": \"min_ratio\", \"type\": \"float32\" },\n      { \"name\": \"center\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"clip\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"angle\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"aspect\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"saturation\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"exposure\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"hue\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"power\", \"type\": \"float32\", \"default\": 4 },\n      { \"name\": \"flip\", \"type\": \"int32\", \"default\": 1, \"description\": \"Enables augmentation method: horizontal flip\" },\n      { \"name\": \"blur\", \"type\": \"int32\", \"default\": 0, \"description\": \"Enables augmentation method: backgound blurring\" },\n      { \"name\": \"mixup\", \"type\": \"int32\", \"default\": 0, \"description\": \"Enables augmentation method: images mixup\" },\n      { \"name\": \"cutmix\", \"type\": \"int32\", \"default\": 0, \"description\": \"Enables augmentation method: images cutmix\" },\n      { \"name\": \"mosaic\", \"type\": \"int32\", \"default\": 0, \"description\": \"Enables augmentation method: images mosaicing\" },\n      { \"name\": \"letter_box\", \"type\": \"int32\", \"default\": 0, \"description\": \"Enables letter-box resizing (keeping the aspect ratio)\" },\n      { \"name\": \"policy\", \"type\": \"string\", \"default\": \"constant\" },\n      { \"name\": \"burn_in\", \"type\": \"int32\", \"default\": 0, \"description\": \"Is used for MAP calculation: permit a minimal number of iteration before first MAP check\" },\n      { \"name\": \"letter_box\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"optimized_memory\", \"type\": \"int32\", \"default\": 0, \"description\": \"can offload memory from GPU into CPU at the cost of speed, 3 options are possible please look at: https://github.com/AlexeyAB/darknet/issues/4386\" },\n      { \"name\": \"workspace_size_limit_MB\", \"type\": \"float32\", \"default\": 1024 }\n    ]\n  },\n  {\n    \"name\": \"norm_chan\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"norm_chan_softmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"normalization\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.75 },\n      { \"name\": \"kappa\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"size\", \"default\": 5 }\n    ]\n  },\n  {\n    \"name\": \"plse\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ramp\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"region\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"classes\", \"type\": \"int32\", \"default\": 20 },\n      { \"name\": \"coord\", \"default\": 4 },\n      { \"name\": \"num\", \"default\": 1 },\n      { \"name\": \"mask\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"jitter\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"classfix\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"coord_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"object_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"noobject_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"mask_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"class_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"bias_match\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"focal_loss\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"max\", \"type\": \"int32\", \"default\": 90 },\n      { \"name\": \"softmax\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"rescore\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"thresh\", \"type\": \"float32\", \"default\": 0.5 },\n      { \"name\": \"random\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"map\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"tree\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"anchors\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"absolute\", \"default\": 0 },\n      { \"name\": \"log\", \"default\": 0 },\n      { \"name\": \"sqrt\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"relie\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"relu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"relu6\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"reorg\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"reverse\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"rnn\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"output\", \"type\": \"int32\", \"visible\": false },\n      { \"name\": \"hidden\", \"visible\": false, \"default\": 1 },\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" },\n      { \"name\": \"groups\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"xnor\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"shortcut\", \"default\": 0 },\n      { \"name\": \"logistic\", \"default\": 0 },\n      { \"name\": \"batch_normalize\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"route\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"groups_id\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"groups\", \"type\": \"int32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"sam\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"linear\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU\" },\n      { \"name\": \"from\", \"description\": \"This params link the layer to another one, the index of the layer is either positive in which case it's a direct address, if negative it's relative to the layer position\" }\n    ]\n  },\n  {\n    \"name\": \"scale_channels\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"linear\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU\" },\n      { \"name\": \"scale_wh\", \"default\": 0 },\n      { \"name\": \"from\", \"description\": \"This params link the layer to another one, the index of the layer is either positive in which case it's a direct address, if negative it's relative to the layer position\" }\n    ]\n  },\n  {\n    \"name\": \"selu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"silu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"shortcut\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"activation\", \"type\": \"string\", \"default\": \"logistic\", \"description\": \"options are: LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU, SWISH, MISH\" },\n      { \"name\": \"assisted_excitation\", \"default\": 0 },\n      { \"name\": \"from\", \"description\": \"This params link the layer to another one, the index of the layer is either positive in which case it's a direct address, if negative it's relative to the layer position\" }\n    ]\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"groups\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"temperature\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"tree\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"spatial\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"noloss\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"stair\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"swish\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"tanh\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"upsample\",\n    \"category\": \"Data\",\n    \"attributes\": [\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 2 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"yolo\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"classes\", \"type\": \"int32\", \"default\": 20 },\n      { \"name\": \"num\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"mask\", \"type\": \"int32[]\", \"default\": 0 },\n      { \"name\": \"jitter\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"label_smooth_eps\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"scale_x_y\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"iou_normalizer\", \"type\": \"float32\", \"default\": 0.75 },\n      { \"name\": \"cls_normalizer\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"iou_loss\", \"type\": \"string\", \"default\": \"mse\", \"description\": \"options are: mse, giou, diou, and ciou\" },\n      { \"name\": \"focal_loss\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"max\", \"type\": \"int32\", \"default\": 90 },\n      { \"name\": \"ignore_thresh\", \"type\": \"float32\", \"default\": 0.5 },\n      { \"name\": \"truth_thresh\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"iou_thresh\", \"type\": \"float32\", \"default\": 1, \"description\": \"recommended to use iou_thresh=0.213\" },\n      { \"name\": \"random\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"map\", \"type\": \"string\", \"default\": 0 },\n      { \"name\": \"nms_kind\", \"type\": \"string\", \"default\": \"default\", \"description\": \"options are: greedynms, diounms, cornersnms, or defaultnms\" },\n      { \"name\": \"anchors\", \"type\": \"int32[]\", \"default\": 0 }\n    ]\n  }\n]"
  },
  {
    "path": "source/darknet.js",
    "content": "\nconst darknet = {};\n\ndarknet.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        if (extension === 'weights' && !identifier.toLowerCase().endsWith('.espresso.weights')) {\n            const weights = await darknet.Weights.open(context);\n            if (weights) {\n                return context.set('darknet.weights', weights);\n            }\n            return null;\n        }\n        const reader = await context.read('text', 65536);\n        if (reader) {\n            try {\n                for (let line = reader.read('\\n'); line !== undefined; line = reader.read('\\n')) {\n                    const content = line.trim();\n                    if (content.length > 0 && !content.startsWith('#')) {\n                        if (content.startsWith('[') && content.endsWith(']')) {\n                            return context.set('darknet.model');\n                        }\n                        return null;\n                    }\n                }\n            } catch {\n                // continue regardless of error\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('darknet-metadata.json');\n        const identifier = context.identifier;\n        const parts = identifier.split('.');\n        parts.pop();\n        const basename = parts.join('.');\n        switch (context.type) {\n            case 'darknet.weights': {\n                const weights = context.value;\n                const name = `${basename}.cfg`;\n                const content = await context.fetch(name);\n                const reader = await content.read('text');\n                const configuration = new darknet.Configuration(reader, content.identifier);\n                return new darknet.Model(metadata, configuration, weights);\n            }\n            case 'darknet.model': {\n                try {\n                    const name = `${basename}.weights`;\n                    const content = await context.fetch(name);\n                    const weights = await darknet.Weights.open(content);\n                    const reader = await context.read('text');\n                    const configuration = new darknet.Configuration(reader, context.identifier);\n                    return new darknet.Model(metadata, configuration, weights);\n                } catch {\n                    const reader = await context.read('text');\n                    const configuration = new darknet.Configuration(reader, context.identifier);\n                    return new darknet.Model(metadata, configuration, null);\n                }\n            }\n            default: {\n                throw new darknet.Error(`Unsupported Darknet format '${context.type}'.`);\n            }\n        }\n    }\n};\n\ndarknet.Model = class {\n\n    constructor(metadata, configuration, weights) {\n        this.format = 'Darknet';\n        this.modules = [new darknet.Graph(metadata, configuration, weights)];\n    }\n};\n\ndarknet.Graph = class {\n\n    constructor(metadata, configuration, weights) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const params = {};\n        const sections = configuration.read();\n        const globals = new Map();\n        const net = sections.shift();\n        const option_find_int = (options, key, defaultValue) => {\n            let value = options[key];\n            if (typeof value === 'string' && value.startsWith('$')) {\n                const key = value.substring(1);\n                value = globals.has(key) ? globals.get(key) : value;\n            }\n            if (value !== undefined) {\n                const number = parseInt(value, 10);\n                if (!Number.isInteger(number)) {\n                    throw new darknet.Error(`Invalid int option '${JSON.stringify(options[key])}'.`);\n                }\n                return number;\n            }\n            return defaultValue;\n        };\n        const option_find_str = (options, key, defaultValue) => {\n            const value = options[key];\n            return value === undefined ? defaultValue : value;\n        };\n        const make_shape = (dimensions, source) => {\n            if (dimensions.some((dimension) => dimension === 0 || dimension === undefined || isNaN(dimension))) {\n                throw new darknet.Error(`Invalid tensor shape '${JSON.stringify(dimensions)}' in '${source}'.`);\n            }\n            return new darknet.TensorShape(dimensions);\n        };\n        const load_weights = (name, shape, visible) => {\n            const data = weights ? weights.read(4 * shape.reduce((a, b) => a * b, 1)) : null;\n            const type = new darknet.TensorType('float32', make_shape(shape, 'load_weights'));\n            const initializer = new darknet.Tensor(type, data);\n            const value = new darknet.Value('', null, initializer);\n            return new darknet.Argument(name, [value], null, visible !== false);\n        };\n        const load_batch_normalize_weights = (layer, prefix, size) => {\n            layer.weights.push(load_weights(`${prefix}scale`, [size], prefix === ''));\n            layer.weights.push(load_weights(`${prefix}mean`, [size], prefix === ''));\n            layer.weights.push(load_weights(`${prefix}variance`, [size], prefix === ''));\n        };\n        const make_convolutional_layer = (layer, prefix, w, h, c, n, groups, size, stride_x, stride_y, padding, batch_normalize) => {\n            layer.out_w = Math.floor((w + 2 * padding - size) / stride_x) + 1;\n            layer.out_h = Math.floor((h + 2 * padding - size) / stride_y) + 1;\n            layer.out_c = n;\n            layer.out = layer.out_w * layer.out_h * layer.out_c;\n            layer.weights.push(load_weights(`${prefix}biases`, [n], prefix === ''));\n            if (batch_normalize) {\n                if (prefix) {\n                    load_batch_normalize_weights(layer, prefix, n);\n                } else {\n                    const batchnorm_layer = { weights: [] };\n                    load_batch_normalize_weights(batchnorm_layer, prefix, n);\n                    layer.chain.push({ type: 'batchnorm', layer: batchnorm_layer });\n                }\n            }\n            layer.weights.push(load_weights(`${prefix}weights`, [Math.floor(c / groups), n, size, size], prefix === ''));\n            layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'make_convolutional_layer'));\n        };\n        const make_deconvolutional_layer = (l, batch, h, w, c, n, size, stride, padding, activation, batch_normalize) => {\n            const pad = padding;\n            l.out_w = Math.floor((w - 1) * stride + size - 2 * pad);\n            l.out_h = Math.floor((h - 1) * stride + size - 2 * pad);\n            l.out_c = n;\n            l.out = l.out_w * l.out_h * l.out_c;\n            l.weights.push(load_weights(`biases`, [n]));\n            if (batch_normalize) {\n                const batchnorm_layer = { weights: [] };\n                load_batch_normalize_weights(batchnorm_layer, '', n);\n                l.chain.push({ type: 'batchnorm', layer: batchnorm_layer });\n            }\n            l.weights.push(load_weights(`weights`, [c, n, size, size]));\n            l.outputs[0].type = new darknet.TensorType('float32', make_shape([l.out_w, l.out_h, l.out_c], 'make_convolutional_layer'));\n        };\n        const make_connected_layer = (layer, prefix, inputs, outputs, batch_normalize) => {\n            layer.out_h = 1;\n            layer.out_w = 1;\n            layer.out_c = outputs;\n            layer.out = outputs;\n            layer.weights.push(load_weights(`${prefix}biases`, [outputs], prefix === ''));\n            if (batch_normalize) {\n                if (prefix) {\n                    load_batch_normalize_weights(layer, prefix, outputs);\n                } else {\n                    const batchnorm_layer = { weights: [] };\n                    load_batch_normalize_weights(batchnorm_layer, prefix, outputs);\n                    layer.chain.push({ type: 'batchnorm', layer: batchnorm_layer });\n                }\n            }\n            layer.weights.push(load_weights(`${prefix}weights`, [inputs, outputs], prefix === ''));\n            layer.outputs[0].type = new darknet.TensorType('float32', make_shape([outputs], 'make_connected_layer'));\n        };\n        if (sections.length === 0) {\n            throw new darknet.Error('Config file has no sections.');\n        }\n        switch (net.type) {\n            case 'net':\n            case 'network': {\n                params.h = option_find_int(net.options, 'height', 0);\n                params.w = option_find_int(net.options, 'width', 0);\n                params.c = option_find_int(net.options, 'channels', 0);\n                params.inputs = option_find_int(net.options, 'inputs', params.h * params.w * params.c);\n                for (const key of Object.keys(net.options)) {\n                    globals.set(key, net.options[key]);\n                }\n                break;\n            }\n            default: {\n                throw new darknet.Error(`Unexpected '[${net.type}]' section. First section must be [net] or [network].`);\n            }\n        }\n        const inputType = params.w && params.h && params.c ?\n            new darknet.TensorType('float32', make_shape([params.w, params.h, params.c], 'params-if')) :\n            new darknet.TensorType('float32', make_shape([params.inputs], ''));\n        const inputName = 'input';\n        params.value = [new darknet.Value(inputName, inputType, null)];\n        this.inputs.push(new darknet.Argument(inputName, params.value));\n        for (let i = 0; i < sections.length; i++) {\n            const section = sections[i];\n            section.name = i.toString();\n            section.layer = {\n                inputs: [],\n                weights: [],\n                outputs: [new darknet.Value(section.name, null, null)],\n                chain: []\n            };\n        }\n        let infer = true;\n        for (let i = 0; i < sections.length; i++) {\n            const section = sections[i];\n            const options = section.options;\n            const layer = section.layer;\n            layer.inputs.push(...params.value);\n            switch (section.type) {\n                case 'shortcut': {\n                    let remove = true;\n                    const from = options.from ? options.from.split(',').map((item) => Number.parseInt(item.trim(), 10)) : [];\n                    for (const route of from) {\n                        const index = route < 0 ? i + route : route;\n                        const exists = index >= 0 && index < sections.length;\n                        remove = exists && remove;\n                        if (exists) {\n                            const source = sections[index].layer;\n                            layer.inputs.push(source.outputs[0]);\n                        }\n                    }\n                    if (remove) {\n                        delete options.from;\n                    }\n                    break;\n                }\n                case 'sam':\n                case 'scale_channels': {\n                    const from = option_find_int(options, 'from', 0);\n                    const index = from < 0 ? i + from : from;\n                    if (index >= 0 && index < sections.length) {\n                        const source = sections[index].layer;\n                        layer.from = source;\n                        layer.inputs.push(source.outputs[0]);\n                        delete options.from;\n                    }\n                    break;\n                }\n                case 'route': {\n                    layer.inputs = [];\n                    layer.layers = [];\n                    let remove = true;\n                    const routes = options.layers ? options.layers.split(',').map((route) => Number.parseInt(route.trim(), 10)) : [];\n                    for (const route of routes) {\n                        const index = route < 0 ? i + route : route;\n                        const exists = index >= 0 && index < sections.length;\n                        remove = exists && remove;\n                        if (exists) {\n                            const source = sections[index].layer;\n                            layer.inputs.push(source.outputs[0]);\n                            layer.layers.push(source);\n                        }\n                    }\n                    if (remove) {\n                        delete options.layers;\n                    }\n                    break;\n                }\n                default:\n                    break;\n            }\n            if (infer) {\n                switch (section.type) {\n                    case 'conv':\n                    case 'convolutional': {\n                        const shape = layer.inputs[0].type.shape.dimensions;\n                        if (shape[0] !== params.w || shape[1] !== params.h || shape[2] !== params.c) {\n                            throw new darknet.Error('Layer before convolutional layer must output image.');\n                        }\n                        const size = option_find_int(options, 'size', 1);\n                        const n = option_find_int(options, 'filters', 1);\n                        const pad = option_find_int(options, 'pad', 0);\n                        const padding = pad ? (size >> 1) : option_find_int(options, 'padding', 0);\n                        let stride_x = option_find_int(options, 'stride_x', -1);\n                        let stride_y = option_find_int(options, 'stride_y', -1);\n                        if (stride_x < 1 || stride_y < 1) {\n                            const stride = option_find_int(options, 'stride', 1);\n                            stride_x = stride_x < 1 ? stride : stride_x;\n                            stride_y = stride_y < 1 ? stride : stride_y;\n                        }\n                        const groups = option_find_int(options, 'groups', 1);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        const activation = option_find_str(options, 'activation', 'logistic');\n                        make_convolutional_layer(layer, '', params.w, params.h, params.c, n, groups, size, stride_x, stride_y, padding, batch_normalize);\n                        if (activation !== 'logistic' && activation !== 'none') {\n                            layer.chain.push({ type: activation });\n                        }\n                        break;\n                    }\n                    case 'deconvolutional': {\n                        const shape = layer.inputs[0].type.shape.dimensions;\n                        if (shape[0] !== params.w || shape[1] !== params.h || shape[2] !== params.c) {\n                            throw new darknet.Error('Layer before convolutional layer must output image.');\n                        }\n                        const n = option_find_int(options, 'filters', 1);\n                        const size = option_find_int(options, 'size', 1);\n                        const stride = option_find_int(options, 'stride', 1);\n                        const activation = option_find_str(options, 'activation', 'logistic');\n                        const h = params.h;\n                        const w = params.w;\n                        const c = params.c;\n                        const batch = params.batch;\n                        let padding = option_find_int(options, 'padding', 0);\n                        const pad = option_find_int(options, 'pad', 0);\n                        if (pad) {\n                            padding = size / 2;\n                        }\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        make_deconvolutional_layer(layer, batch, h, w, c, n, size, stride, padding, activation, batch_normalize);\n                        if (activation !== 'logistic' && activation !== 'none') {\n                            layer.chain.push({ type: activation });\n                        }\n                        break;\n                    }\n                    case 'connected': {\n                        const outputs = option_find_int(options, 'output', 1);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        const activation = option_find_str(options, 'activation', 'logistic');\n                        make_connected_layer(layer, '', params.inputs, outputs, batch_normalize);\n                        if (activation !== 'logistic' && activation !== 'none') {\n                            layer.chain.push({ type: activation });\n                        }\n                        break;\n                    }\n                    case 'local': {\n                        const shape = layer.inputs[0].type.shape.dimensions;\n                        if (shape[0] !== params.w || shape[1] !== params.h || shape[2] !== params.c) {\n                            throw new darknet.Error('Layer before avgpool layer must output image.');\n                        }\n                        const n = option_find_int(options, 'filters' , 1);\n                        const size = option_find_int(options, 'size', 1);\n                        const stride = option_find_int(options, 'stride', 1);\n                        const pad = option_find_int(options, 'pad', 0);\n                        const activation = option_find_str(options, 'activation', 'logistic');\n                        layer.out_h = Math.floor((params.h - (pad ? 1 : size)) / stride) + 1;\n                        layer.out_w = Math.floor((params.w - (pad ? 1 : size)) / stride) + 1;\n                        layer.out_c = n;\n                        layer.out = layer.out_w * layer.out_h * layer.out_c;\n                        layer.weights.push(load_weights('weights', [params.c, n, size, size, layer.out_h * layer.out_w]));\n                        layer.weights.push(load_weights('biases',[layer.out_w * layer.out_h * layer.out_c]));\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'local'));\n                        if (activation !== 'logistic' && activation !== 'none') {\n                            layer.chain.push({ type: activation });\n                        }\n                        break;\n                    }\n                    case 'batchnorm': {\n                        layer.out_h = params.h;\n                        layer.out_w = params.w;\n                        layer.out_c = params.c;\n                        layer.out = layer.in;\n                        load_batch_normalize_weights(layer, '', layer.out_c);\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'batchnorm'));\n                        break;\n                    }\n                    case 'activation': {\n                        layer.out_h = params.h;\n                        layer.out_w = params.w;\n                        layer.out_c = params.c;\n                        layer.out = layer.in;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'activation'));\n                        break;\n                    }\n                    case 'max':\n                    case 'maxpool': {\n                        const shape = layer.inputs[0].type.shape.dimensions;\n                        if (shape[0] !== params.w || shape[1] !== params.h || shape[2] !== params.c) {\n                            throw new darknet.Error('Layer before maxpool layer must output image.');\n                        }\n                        const antialiasing = option_find_int(options, 'antialiasing', 0);\n                        const stride = option_find_int(options, 'stride', 1);\n                        const blur_stride_x = option_find_int(options, 'stride_x', stride);\n                        const blur_stride_y = option_find_int(options, 'stride_y', stride);\n                        const stride_x = antialiasing ? 1 : blur_stride_x;\n                        const stride_y = antialiasing ? 1 : blur_stride_y;\n                        const size = option_find_int(options, 'size', stride);\n                        const padding = option_find_int(options, 'padding', size - 1);\n                        const out_channels = option_find_int(options, 'out_channels', 1);\n                        const maxpool_depth = option_find_int(options, 'maxpool_depth', 0);\n                        if (maxpool_depth) {\n                            layer.out_c = out_channels;\n                            layer.out_w = params.w;\n                            layer.out_h = params.h;\n                        } else {\n                            layer.out_w = Math.floor((params.w + padding - size) / stride_x) + 1;\n                            layer.out_h = Math.floor((params.h + padding - size) / stride_y) + 1;\n                            layer.out_c = params.c;\n                        }\n                        if (antialiasing) {\n                            const blur_size = antialiasing === 2 ? 2 : 3;\n                            const blur_pad = antialiasing === 2 ? 0 : Math.floor(blur_size / 3);\n                            layer.input_layer = { weights: [], outputs: layer.outputs, chain: [] };\n                            make_convolutional_layer(layer.input_layer, '', layer.out_h, layer.out_w, layer.out_c, layer.out_c, layer.out_c, blur_size, blur_stride_x, blur_stride_y, blur_pad, 0);\n                            layer.out_w = layer.input_layer.out_w;\n                            layer.out_h = layer.input_layer.out_h;\n                            layer.out_c = layer.input_layer.out_c;\n                        } else {\n                            layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'maxpool'));\n                        }\n                        layer.out = layer.out_w * layer.out_h * layer.out_c;\n                        break;\n                    }\n                    case 'avgpool': {\n                        const shape = layer.inputs[0].type.shape.dimensions;\n                        if (shape[0] !== params.w || shape[1] !== params.h || shape[2] !== params.c) {\n                            throw new darknet.Error('Layer before avgpool layer must output image.');\n                        }\n                        layer.out_w = 1;\n                        layer.out_h = 1;\n                        layer.out_c = params.c;\n                        layer.out = layer.out_c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'avgpool'));\n                        break;\n                    }\n                    case 'crnn': {\n                        const size = option_find_int(options, 'size', 3);\n                        const stride = option_find_int(options, 'stride', 1);\n                        const output_filters = option_find_int(options, 'output', 1);\n                        const hidden_filters = option_find_int(options, 'hidden', 1);\n                        const groups = option_find_int(options, 'groups', 1);\n                        const pad = option_find_int(options, 'pad', 0);\n                        const padding = pad ? (size >> 1) : option_find_int(options, 'padding', 0);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        layer.input_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_convolutional_layer(layer.input_layer, 'input_', params.h, params.w, params.c, hidden_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.self_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_convolutional_layer(layer.self_layer, 'self_', params.h, params.w, hidden_filters, hidden_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.output_layer = { weights: [], outputs: layer.outputs, chain: [] };\n                        make_convolutional_layer(layer.output_layer, 'output_', params.h, params.w, hidden_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.weights = layer.weights.concat(layer.input_layer.weights);\n                        layer.weights = layer.weights.concat(layer.self_layer.weights);\n                        layer.weights = layer.weights.concat(layer.output_layer.weights);\n                        layer.out_h = layer.output_layer.out_h;\n                        layer.out_w = layer.output_layer.out_w;\n                        layer.out_c = output_filters;\n                        layer.out = layer.output_layer.out;\n                        break;\n                    }\n                    case 'rnn': {\n                        const outputs = option_find_int(options, 'output', 1);\n                        const hidden = option_find_int(options, 'hidden', 1);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        const inputs = params.inputs;\n                        layer.input_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.input_layer, 'input_', inputs, hidden, batch_normalize);\n                        layer.self_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.self_layer, 'self_', hidden, hidden, batch_normalize);\n                        layer.output_layer = { weights: [], outputs: layer.outputs, chain: [] };\n                        make_connected_layer(layer.output_layer, 'output_', hidden, outputs, batch_normalize);\n                        layer.weights = layer.weights.concat(layer.input_layer.weights);\n                        layer.weights = layer.weights.concat(layer.self_layer.weights);\n                        layer.weights = layer.weights.concat(layer.output_layer.weights);\n                        layer.out_w = 1;\n                        layer.out_h = 1;\n                        layer.out_c = outputs;\n                        layer.out = outputs;\n                        break;\n                    }\n                    case 'gru': {\n                        const inputs = params.inputs;\n                        const outputs = option_find_int(options, 'output', 1);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        layer.input_z_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.input_z_layer, 'input_z', inputs, outputs, batch_normalize);\n                        layer.state_z_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.state_z_layer, 'state_z', outputs, outputs, batch_normalize);\n                        layer.input_r_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.input_r_layer, 'input_r', inputs, outputs, batch_normalize);\n                        layer.state_r_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.state_r_layer, 'state_r', outputs, outputs, batch_normalize);\n                        layer.input_h_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.input_h_layer, 'input_h', inputs, outputs, batch_normalize);\n                        layer.state_h_layer = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.state_h_layer, 'state_h', outputs, outputs, batch_normalize);\n                        layer.weights = layer.weights.concat(layer.input_z_layer.weights);\n                        layer.weights = layer.weights.concat(layer.state_z_layer.weights);\n                        layer.weights = layer.weights.concat(layer.input_r_layer.weights);\n                        layer.weights = layer.weights.concat(layer.state_r_layer.weights);\n                        layer.weights = layer.weights.concat(layer.input_h_layer.weights);\n                        layer.weights = layer.weights.concat(layer.state_h_layer.weights);\n                        layer.out = outputs;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([outputs], 'gru'));\n                        break;\n                    }\n                    case 'lstm': {\n                        const inputs = params.inputs;\n                        const outputs = option_find_int(options, 'output', 1);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        layer.uf = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.uf, 'uf_', inputs, outputs, batch_normalize);\n                        layer.ui = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.ui, 'ui_', inputs, outputs, batch_normalize);\n                        layer.ug = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.ug, 'ug_', inputs, outputs, batch_normalize);\n                        layer.uo = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.uo, 'uo_', inputs, outputs, batch_normalize);\n                        layer.wf = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.wf, 'wf_', outputs, outputs, batch_normalize);\n                        layer.wi = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.wi, 'wi_', outputs, outputs, batch_normalize);\n                        layer.wg = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.wg, 'wg_', outputs, outputs, batch_normalize);\n                        layer.wo = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_connected_layer(layer.wo, 'wo_', outputs, outputs, batch_normalize);\n                        layer.weights = layer.weights.concat(layer.uf.weights);\n                        layer.weights = layer.weights.concat(layer.ui.weights);\n                        layer.weights = layer.weights.concat(layer.ug.weights);\n                        layer.weights = layer.weights.concat(layer.uo.weights);\n                        layer.weights = layer.weights.concat(layer.wf.weights);\n                        layer.weights = layer.weights.concat(layer.wi.weights);\n                        layer.weights = layer.weights.concat(layer.wg.weights);\n                        layer.weights = layer.weights.concat(layer.wo.weights);\n                        layer.out_w = 1;\n                        layer.out_h = 1;\n                        layer.out_c = outputs;\n                        layer.out = outputs;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([outputs], 'lstm'));\n                        weights = null;\n                        break;\n                    }\n                    case 'conv_lstm': {\n                        const size = option_find_int(options, \"size\", 3);\n                        const stride = option_find_int(options, \"stride\", 1);\n                        const output_filters = option_find_int(options, \"output\", 1);\n                        const groups = option_find_int(options, \"groups\", 1);\n                        const pad = option_find_int(options, \"pad\", 0);\n                        const padding = pad ? (size >> 1) : option_find_int(options, 'padding', 0);\n                        const batch_normalize = option_find_int(options, 'batch_normalize', 0);\n                        const bottleneck = option_find_int(options, \"bottleneck\", 0);\n                        const peephole = option_find_int(options, \"peephole\", 0);\n                        layer.uf = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                        make_convolutional_layer(layer.uf, 'uf_', params.h, params.w, params.c, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.ui = { weights: [], outputs: [new darknet.Value('', null, null)], chain: []  };\n                        make_convolutional_layer(layer.ui, 'ui_', params.h, params.w, params.c, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.ug = { weights: [], outputs: [new darknet.Value('', null, null)], chain: []  };\n                        make_convolutional_layer(layer.ug, 'ug_', params.h, params.w, params.c, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.uo = { weights: [], outputs: [new darknet.Value('', null, null)], chain: []  };\n                        make_convolutional_layer(layer.uo, 'uo_', params.h, params.w, params.c, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                        layer.weights = layer.weights.concat(layer.uf.weights);\n                        layer.weights = layer.weights.concat(layer.ui.weights);\n                        layer.weights = layer.weights.concat(layer.ug.weights);\n                        layer.weights = layer.weights.concat(layer.uo.weights);\n                        if (bottleneck) {\n                            layer.wf = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.wf, 'wf_', params.h, params.w, output_filters * 2, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.weights = layer.weights.concat(layer.wf.weights);\n                        } else {\n                            layer.wf = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.wf, 'wf_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.wi = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.wi, 'wi_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.wg = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.wg, 'wg_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.wo = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.wo, 'wo_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.weights = layer.weights.concat(layer.wf.weights);\n                            layer.weights = layer.weights.concat(layer.wi.weights);\n                            layer.weights = layer.weights.concat(layer.wg.weights);\n                            layer.weights = layer.weights.concat(layer.wo.weights);\n                        }\n                        if (peephole) {\n                            layer.vf = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.vf, 'vf_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.vi = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.vi, 'vi_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.vo = { weights: [], outputs: [new darknet.Value('', null, null)], chain: [] };\n                            make_convolutional_layer(layer.vo, 'vo_', params.h, params.w, output_filters, output_filters, groups, size, stride, stride, padding, batch_normalize);\n                            layer.weights = layer.weights.concat(layer.vf.weights);\n                            layer.weights = layer.weights.concat(layer.vi.weights);\n                            layer.weights = layer.weights.concat(layer.vo.weights);\n                        }\n                        layer.out_h = layer.uo.out_h;\n                        layer.out_w = layer.uo.out_w;\n                        layer.out_c = output_filters;\n                        layer.out = layer.out_h * layer.out_w * layer.out_c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'conv_lstm'));\n                        break;\n                    }\n                    case 'softmax': {\n                        layer.out_w = params.w;\n                        layer.out_h = params.h;\n                        layer.out_c = params.c;\n                        layer.out = params.inputs;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out], 'softmax'));\n                        break;\n                    }\n                    case 'dropout': {\n                        layer.out_w = params.w;\n                        layer.out_h = params.h;\n                        layer.out_c = params.c;\n                        layer.out = params.inputs;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'dropout'));\n                        break;\n                    }\n                    case 'upsample': {\n                        const stride = option_find_int(options, 'stride', 2);\n                        layer.out_w = params.w * stride;\n                        layer.out_h = params.h * stride;\n                        layer.out_c = params.c;\n                        layer.out = layer.out_w * layer.out_h * layer.out_c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'upsample'));\n                        break;\n                    }\n                    case 'crop': {\n                        const shape = layer.inputs[0].type.shape.dimensions;\n                        if (shape[0] !== params.w || shape[1] !== params.h || shape[2] !== params.c) {\n                            throw new darknet.Error('Layer before crop layer must output image.');\n                        }\n                        const crop_height = option_find_int(options, 'crop_height', 1);\n                        const crop_width = option_find_int(options, 'crop_width', 1);\n                        layer.out_w = crop_width;\n                        layer.out_h = crop_height;\n                        layer.out_c = params.c;\n                        layer.out = layer.out_w * layer.out_h * layer.out_c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'crop'));\n                        break;\n                    }\n                    case 'yolo': {\n                        const classes = option_find_int(options, 'classes', 20);\n                        const n = option_find_int(options, 'num', 1);\n                        layer.out_h = params.h;\n                        layer.out_w = params.w;\n                        layer.out_c = n * (classes + 4 + 1);\n                        layer.out = layer.out_h * layer.out_w * layer.out_c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'yolo'));\n                        break;\n                    }\n                    case 'Gaussian_yolo': {\n                        const classes = option_find_int(options, 'classes', 20);\n                        const n = option_find_int(options, 'num', 1);\n                        layer.out_h = params.h;\n                        layer.out_w = params.w;\n                        layer.out_c = n * (classes + 8 + 1);\n                        layer.out = layer.out_h * layer.out_w * layer.out_c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'Gaussian_yolo'));\n                        break;\n                    }\n                    case 'region': {\n                        const coords = option_find_int(options, 'coords', 4);\n                        const classes = option_find_int(options, 'classes', 20);\n                        const num = option_find_int(options, 'num', 1);\n                        layer.out = params.h * params.w * num * (classes + coords + 1);\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([params.h, params.w, num, (classes + coords + 1)], 'region'));\n                        break;\n                    }\n                    case 'cost': {\n                        layer.out = params.inputs;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out], 'cost'));\n                        break;\n                    }\n                    case 'reorg': {\n                        const stride = option_find_int(options, 'stride', 1);\n                        const reverse = option_find_int(options, 'reverse', 0);\n                        const extra = option_find_int(options, 'extra', 0);\n                        if (reverse) {\n                            layer.out_w = params.w * stride;\n                            layer.out_h = params.h * stride;\n                            layer.out_c = Math.floor(params.c / (stride * stride));\n                            layer.out = layer.out_h * layer.out_w * layer.out_c;\n                        } else {\n                            layer.out_w = Math.floor(params.w / stride);\n                            layer.out_h = Math.floor(params.h / stride);\n                            layer.out_c = params.c * (stride * stride);\n                            layer.out = layer.out_h * layer.out_w * layer.out_c;\n                        }\n                        if (extra) {\n                            layer.out_w = 0;\n                            layer.out_h = 0;\n                            layer.out_c = 0;\n                            layer.out = (params.h * params.w * params.c) + extra;\n                            layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out], 'reorg'));\n                        } else {\n                            layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'reorg'));\n                        }\n                        break;\n                    }\n                    case 'route': {\n                        const layers = [].concat(layer.layers);\n                        const groups = option_find_int(options, 'groups', 1);\n                        layer.out = 0;\n                        for (const next of layers) {\n                            layer.out += next.outputs / groups;\n                        }\n                        if (layers.length > 0) {\n                            const first = layers.shift();\n                            layer.out_w = first.out_w;\n                            layer.out_h = first.out_h;\n                            layer.out_c = first.out_c / groups;\n                            while (layers.length > 0) {\n                                const next = layers.shift();\n                                if (next.out_w === first.out_w && next.out_h === first.out_h) {\n                                    layer.out_c += next.out_c;\n                                    continue;\n                                }\n                                infer = false;\n                                break;\n                            }\n                            if (infer) {\n                                layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'route'));\n                            }\n                        } else {\n                            infer = false;\n                        }\n                        if (!infer) {\n                            layer.out_h = 0;\n                            layer.out_w = 0;\n                            layer.out_c = 0;\n                        }\n                        break;\n                    }\n                    case 'sam':\n                    case 'scale_channels': {\n                        const activation = option_find_str(options, 'activation', 'linear');\n                        const from = layer.from;\n                        if (from) {\n                            layer.out_w = from.out_w;\n                            layer.out_h = from.out_h;\n                            layer.out_c = from.out_c;\n                            layer.out = layer.out_w * layer.out_h * layer.out_c;\n                            layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out_w, layer.out_h, layer.out_c], 'shortcut|scale_channels|sam'));\n                        }\n                        if (activation !== 'linear' && activation !== 'none') {\n                            layer.chain.push({ type: activation });\n                        }\n                        break;\n                    }\n                    case 'shortcut': {\n                        const activation = option_find_str(options, 'activation', 'linear');\n                        layer.out_w = params.w;\n                        layer.out_h = params.h;\n                        layer.out_c = params.c;\n                        layer.out = params.w * params.h * params.c;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([params.w, params.h, params.c], 'shortcut|scale_channels|sam'));\n                        if (activation !== 'linear' && activation !== 'none') {\n                            layer.chain.push({ type: activation });\n                        }\n                        break;\n                    }\n                    case 'detection': {\n                        layer.out_w = params.w;\n                        layer.out_h = params.h;\n                        layer.out_c = params.c;\n                        layer.out = params.inputs;\n                        layer.outputs[0].type = new darknet.TensorType('float32', make_shape([layer.out], 'detection'));\n                        break;\n                    }\n                    default: {\n                        infer = false;\n                        break;\n                    }\n                }\n                params.h = layer.out_h;\n                params.w = layer.out_w;\n                params.c = layer.out_c;\n                params.inputs = layer.out;\n                params.last = section;\n            }\n            params.value = layer.outputs;\n        }\n\n        for (let i = 0; i < sections.length; i++) {\n            this.nodes.push(new darknet.Node(metadata, net, sections[i]));\n        }\n\n        if (weights) {\n            weights.validate();\n        }\n    }\n};\n\ndarknet.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n\n    }\n};\n\ndarknet.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new darknet.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer && initializer.type ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\ndarknet.Node = class {\n\n    constructor(metadata, net, section) {\n        this.name = section.name || '';\n        this.identifier = section.line === undefined ? undefined : section.line.toString();\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.chain = [];\n        const type = section.type;\n        this.type = metadata.type(type) || { name: type };\n        const layer = section.layer;\n        if (layer && layer.inputs && layer.inputs.length > 0) {\n            this.inputs.push(new darknet.Argument(layer.inputs.length <= 1 ? 'input' : 'inputs', layer.inputs));\n        }\n        if (layer && layer.weights && layer.weights.length > 0) {\n            this.inputs = this.inputs.concat(layer.weights);\n        }\n        if (layer && layer.outputs && layer.outputs.length > 0) {\n            this.outputs.push(new darknet.Argument(layer.outputs.length <= 1 ? 'output' : 'outputs', layer.outputs));\n        }\n        if (layer && layer.chain) {\n            for (const chain of layer.chain) {\n                this.chain.push(new darknet.Node(metadata, net, chain, ''));\n            }\n        }\n        const options = section.options;\n        if (options) {\n            for (const [name, obj] of Object.entries(options)) {\n                const schema = metadata.attribute(section.type, name);\n                let type = null;\n                let value = obj;\n                let visible = true;\n                if (schema) {\n                    type = schema.type || '';\n                    switch (type) {\n                        case '':\n                        case 'string': {\n                            break;\n                        }\n                        case 'int32': {\n                            const number = parseInt(value, 10);\n                            if (Number.isInteger(number)) {\n                                value = number;\n                            }\n                            break;\n                        }\n                        case 'float32': {\n                            const number = parseFloat(value);\n                            if (!isNaN(number)) {\n                                value = number;\n                            }\n                            break;\n                        }\n                        case 'int32[]': {\n                            const numbers = value.split(',').map((item) => parseInt(item.trim(), 10));\n                            if (numbers.every((number) => Number.isInteger(number))) {\n                                value = numbers;\n                            }\n                            break;\n                        }\n                        default: {\n                            throw new darknet.Error(`Unsupported attribute type '${type}'.`);\n                        }\n                    }\n                    visible = (schema.visible === false || value === schema.default);\n                }\n                const attribute = new darknet.Argument(name, value, type, visible);\n                this.attributes.push(attribute);\n            }\n        }\n    }\n};\n\ndarknet.Tensor = class {\n\n    constructor(type, data) {\n        this.type = type;\n        this.values = data;\n    }\n};\n\ndarknet.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\ndarknet.TensorShape = class {\n\n    constructor(dimensions) {\n        if (dimensions.some((dimension) => dimension === 0 || dimension === undefined || isNaN(dimension))) {\n            throw new darknet.Error(`Invalid tensor shape '${JSON.stringify(dimensions)}'.`);\n        }\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions) {\n            if (this.dimensions.length === 0) {\n                return '';\n            }\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\ndarknet.Configuration = class {\n\n    constructor(reader, identifier) {\n        this.reader = reader;\n        this.identifier = identifier;\n    }\n\n    read() {\n        // read_cfg\n        const sections = [];\n        let section = null;\n        const reader = this.reader;\n        let lineNumber = 0;\n        const setup = /^setup.*\\.cfg$/.test(this.identifier);\n        for (let content = reader.read('\\n'); content !== undefined; content = reader.read('\\n')) {\n            lineNumber++;\n            const line = content.replace(/\\s/g, '');\n            if (line.length > 0) {\n                switch (line[0]) {\n                    case '#':\n                    case ';':\n                        break;\n                    case '[': {\n                        const type = line[line.length - 1] === ']' ? line.substring(1, line.length - 1) : line.substring(1);\n                        if (setup) {\n                            if (type === 'metadata' || type === 'global' || type === 'wheel' ||\n                                type === 'isort' || type === 'flake8' || type === 'build_ext' ||\n                                type.startsWith('bdist_') || type.startsWith('tool:') || type.startsWith('coverage:')) {\n                                throw new darknet.Error('Invalid file content. File contains Python setup configuration data.');\n                            }\n                        }\n                        section = {\n                            line: lineNumber,\n                            type,\n                            options: {}\n                        };\n                        sections.push(section);\n                        break;\n                    }\n                    default: {\n                        if (!section || line[0] < 0x20 || line[0] > 0x7E) {\n                            throw new darknet.Error(`Invalid cfg '${content.replace(/[^\\x20-\\x7E]+/g, '?').trim()}' at line ${lineNumber}.`);\n                        }\n                        const index = line.indexOf('=');\n                        if (index < 0) {\n                            throw new darknet.Error(`Invalid cfg '${content.replace(/[^\\x20-\\x7E]+/g, '?').trim()}' at line ${lineNumber}.`);\n                        }\n                        const key = line.substring(0, index);\n                        const value = line.substring(index + 1);\n                        section.options[key] = value;\n                        break;\n                    }\n                }\n            }\n        }\n        return sections;\n    }\n};\n\ndarknet.Weights = class {\n\n    static async open(context) {\n        const reader = await context.read('binary');\n        if (reader && reader.length >= 20) {\n            const major = reader.int32();\n            const minor = reader.int32();\n            reader.int32(); // revision\n            reader.seek(0);\n            const transpose = (major > 1000) || (minor > 1000);\n            if (!transpose) {\n                const offset = 12 + ((major * 10 + minor) >= 2 ? 8 : 4);\n                return new darknet.Weights(reader, offset);\n            }\n        }\n        return null;\n    }\n\n    constructor(reader, offset) {\n        this._reader = reader;\n        this._offset = offset;\n    }\n\n    read(size) {\n        this._reader.skip(this._offset);\n        this._offset = 0;\n        return this._reader.read(size);\n    }\n\n    validate() {\n        if (this._reader.position !== this._reader.length) {\n            throw new darknet.Error('Invalid weights size.');\n        }\n    }\n};\n\ndarknet.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Darknet model.';\n    }\n};\n\nexport const ModelFactory = darknet.ModelFactory;\n\n"
  },
  {
    "path": "source/desktop.mjs",
    "content": "\nimport * as base from './base.js';\nimport * as child_process from 'child_process';\nimport * as electron from 'electron';\nimport * as fs from 'fs';\nimport * as http from 'http';\nimport * as https from 'https';\nimport * as node from './node.js';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as url from 'url';\nimport * as view from './view.js';\n\nconst desktop = {};\n\ndesktop.Host = class {\n\n    constructor() {\n        this._document = window.document;\n        this._window = window;\n        this._global = global;\n        this._telemetry = new base.Telemetry(this._window);\n        process.on('uncaughtException', (error) => {\n            this.exception(error, true);\n            this.message(error.message);\n        });\n        this._global.eval = () => {\n            throw new Error('eval.eval() not supported.');\n        };\n        this._window.eval = () => {\n            throw new Error('window.eval() not supported.');\n        };\n        this._window.addEventListener('unload', () => {\n            if (typeof __coverage__ !== 'undefined') {\n                const dir = path.join(process.cwd(), 'dist', 'nyc', '.nyc_output');\n                if (!fs.existsSync(dir)) {\n                    fs.mkdirSync(dir, { recursive: true });\n                }\n                const base = path.basename(window.location.pathname, '.html');\n                const file = path.join(dir, `${base}.json`);\n                /* eslint-disable-next-line no-undef */\n                fs.writeFileSync(file, JSON.stringify(__coverage__));\n            }\n        });\n        this._environment = electron.ipcRenderer.sendSync('get-environment', {});\n        this._environment.menu = this._environment.titlebar && this._environment.platform !== 'darwin';\n        this._files = [];\n        electron.ipcRenderer.on('open', (sender, data) => {\n            this._open(data);\n        });\n        this._element('menu-button').style.opacity = 0;\n        if (!/^\\d+\\.\\d+\\.\\d+$/.test(this.version)) {\n            throw new Error('Invalid version.');\n        }\n        const metadata = [];\n        metadata.push(os.arch());\n        let packager = '';\n        if (process.platform === 'linux') {\n            try {\n                child_process.execFileSync('dpkg', ['-S', process.execPath]);\n                packager = 'deb';\n            } catch {\n                try {\n                    child_process.execFileSync(\"rpm\", [\"-qf\", process.execPath]);\n                    packager = 'rpm';\n                } catch {\n                    // continue regardless of error\n                }\n            }\n        }\n        metadata.push(packager);\n        this._metadata = metadata.join('|');\n    }\n\n    get window() {\n        return this._window;\n    }\n\n    get document() {\n        return this._document;\n    }\n\n    get version() {\n        return this._environment.version;\n    }\n\n    get type() {\n        return 'Electron';\n    }\n\n    get metadata() {\n        return this._metadata;\n    }\n\n    async view(view) {\n        this._view = view;\n        const age = async () => {\n            const days = (new Date() - new Date(this._environment.date)) / (24 * 60 * 60 * 1000);\n            if (days > 180) {\n                this.document.body.classList.remove('spinner');\n                const link = this._element('logo-github').href;\n                for (;;) {\n                    /* eslint-disable-next-line no-await-in-loop */\n                    await this.message('Please update to the newest version.', null, 'Download');\n                    this.openURL(link);\n                }\n            }\n            return Promise.resolve();\n        };\n        const consent = async () => {\n            const time = this.get('consent');\n            if (!time || (Date.now() - time) > 30 * 24 * 60 * 60 * 1000) {\n                let consent = true;\n                try {\n                    const content = await this._request('https://ipinfo.io/json', { 'Content-Type': 'application/json' }, 2000);\n                    const json = JSON.parse(content);\n                    const countries = ['AT', 'BE', 'BG', 'HR', 'CZ', 'CY', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'SK', 'ES', 'SE', 'GB', 'UK', 'GR', 'EU', 'RO'];\n                    if (json && json.country && countries.indexOf(json.country) === -1) {\n                        consent = false;\n                    }\n                } catch {\n                    // continue regardless of error\n                }\n                if (consent) {\n                    this.document.body.classList.remove('spinner');\n                    await this.message('This app uses cookies to report errors and anonymous usage information.', null, 'Accept');\n                }\n                this.set('consent', Date.now());\n            }\n        };\n        const telemetry = async () => {\n            if (this._environment.packaged) {\n                const measurement_id = '848W2NVWVH';\n                const user = this.get('user') || null;\n                const session = this.get('session') || null;\n                await this._telemetry.start(`G-${measurement_id}`, user && user.indexOf('.') !== -1 ? user : null, session);\n                this._telemetry.send('page_view', {\n                    app_name: this.type,\n                    app_version: this.version,\n                    app_metadata: this.metadata\n                });\n                this._telemetry.send('scroll', {\n                    percent_scrolled: 90,\n                    app_name: this.type,\n                    app_version: this.version,\n                    app_metadata: this.metadata\n                });\n                this.set('user', this._telemetry.get('client_id'));\n                this.set('session', this._telemetry.session);\n            }\n        };\n        await age();\n        await consent();\n        await telemetry();\n    }\n\n    async start() {\n        if (this._files) {\n            const files = this._files;\n            delete this._files;\n            if (files.length > 0) {\n                const data = files.pop();\n                this._open(data);\n            }\n        }\n        this._window.addEventListener('focus', () => {\n            this._document.body.classList.add('active');\n        });\n        this._window.addEventListener('blur', () => {\n            this._document.body.classList.remove('active');\n        });\n        if (this._document.hasFocus()) {\n            this._document.body.classList.add('active');\n        }\n        electron.ipcRenderer.on('recents', (sender, data) => {\n            this._view.recents(data);\n        });\n        electron.ipcRenderer.on('export', (sender, data) => {\n            this._view.export(data.file);\n        });\n        electron.ipcRenderer.on('cut', () => {\n            this.document.execCommand('cut');\n        });\n        electron.ipcRenderer.on('copy', () => {\n            this.document.execCommand('copy');\n        });\n        electron.ipcRenderer.on('paste', () => {\n            if (this.document.queryCommandSupported('paste')) {\n                this.document.execCommand('paste');\n            } else if (this.document.queryCommandSupported('insertText')) {\n                const content = electron.clipboard.readText();\n                this.document.execCommand('insertText', false, content);\n            }\n        });\n        electron.ipcRenderer.on('selectall', () => {\n            this.document.execCommand('selectall');\n        });\n        electron.ipcRenderer.on('toggle', (sender, name) => {\n            this._view.toggle(name);\n            this.update({ ...this._view.options });\n        });\n        electron.ipcRenderer.on('zoom-in', () => {\n            this._element('zoom-in-button').click();\n        });\n        electron.ipcRenderer.on('zoom-out', () => {\n            this._element('zoom-out-button').click();\n        });\n        electron.ipcRenderer.on('zoom-reset', () => {\n            this._view.resetZoom();\n        });\n        electron.ipcRenderer.on('show-properties', () => {\n            this._element('sidebar-target-button').click();\n        });\n        electron.ipcRenderer.on('find', () => {\n            this._view.find();\n        });\n        electron.ipcRenderer.on('about', () => {\n            this._view.about();\n        });\n        this._element('titlebar-close').addEventListener('click', () => {\n            electron.ipcRenderer.sendSync('window-close', {});\n        });\n        this._element('titlebar-toggle').addEventListener('click', () => {\n            electron.ipcRenderer.sendSync('window-toggle', {});\n        });\n        this._element('titlebar-minimize').addEventListener('click', () => {\n            electron.ipcRenderer.sendSync('window-minimize', {});\n        });\n        electron.ipcRenderer.on('window-state', (sender, data) => {\n            if (this._environment.titlebar) {\n                this._element('target').style.marginTop = '32px';\n                this._element('target').style.height = 'calc(100% - 32px)';\n                this._element('sidebar-title').style.marginTop = '24px';\n                this._element('sidebar-closebutton').style.marginTop = '24px';\n                this._element('titlebar').classList.add('titlebar-visible');\n            }\n            if (this._environment.titlebar && this._environment.platform !== 'darwin' && !data.fullscreen) {\n                this._element('titlebar-control-box').classList.add('titlebar-control-box-visible');\n            } else {\n                this._element('titlebar-control-box').classList.remove('titlebar-control-box-visible');\n            }\n            this._element('menu-button').style.opacity = this._environment.menu ? 1 : 0;\n            this._element('titlebar-maximize').style.opacity = data.maximized ? 0 : 1;\n            this._element('titlebar-restore').style.opacity = data.maximized ? 1 : 0;\n            this._element('titlebar-toggle').setAttribute('title', data.maximized ? 'Restore' : 'Maximize');\n        });\n        electron.ipcRenderer.sendSync('update-window-state', {});\n        const openFileButton = this._element('open-file-button');\n        if (openFileButton) {\n            openFileButton.addEventListener('click', async () => {\n                await this.execute('open');\n            });\n        }\n        this.document.addEventListener('dragover', (e) => {\n            e.preventDefault();\n        });\n        this.document.addEventListener('drop', (e) => {\n            e.preventDefault();\n        });\n        this.document.body.addEventListener('drop', (e) => {\n            e.preventDefault();\n            const files = Array.from(e.dataTransfer.files);\n            const paths = files.map((file) => electron.webUtils.getPathForFile(file));\n            if (paths.length > 0) {\n                electron.ipcRenderer.send('drop-paths', { paths });\n            }\n            return false;\n        });\n        this._view.show('welcome');\n    }\n\n    environment(name) {\n        return this._environment[name];\n    }\n\n    async error(message) {\n        await this.message(message, true, 'OK');\n    }\n\n    async require(id) {\n        return import(`${id}.js`);\n    }\n\n    worker(id) {\n        return new this.window.Worker(`${id}.js`, { type: 'module' });\n    }\n\n    async save(name, extension, defaultPath) {\n        return new Promise((resolve, reject) => {\n            electron.ipcRenderer.once('show-save-dialog-complete', (event, data) => {\n                if (data.error) {\n                    reject(new Error(data.error));\n                } else if (data.canceled) {\n                    resolve(null);\n                } else {\n                    resolve(data.filePath);\n                }\n            });\n            electron.ipcRenderer.send('show-save-dialog', {\n                title: 'Export Tensor',\n                defaultPath,\n                buttonLabel: 'Export',\n                filters: [{ name, extensions: [extension] }]\n            });\n        });\n    }\n\n    async export(file, blob) {\n        const window = this.window;\n        const reader = new window.FileReader();\n        reader.onload = (e) => {\n            const data = new Uint8Array(e.target.result);\n            fs.writeFile(file, data, null, async (error) => {\n                if (error) {\n                    await this._view.error(error, 'Error writing file.');\n                }\n            });\n        };\n        let error = null;\n        if (!blob) {\n            error = new Error(`Export blob is '${JSON.stringify(blob)}'.`);\n        } else if (blob instanceof window.Blob === false) {\n            error = new Error(`Export blob type is '${typeof blob}'.`);\n        }\n        if (error) {\n            await this._view.error(error, 'Error exporting image.');\n        } else {\n            reader.readAsArrayBuffer(blob);\n        }\n    }\n\n    async execute(name, value) {\n        return new Promise((resolve, reject) => {\n            electron.ipcRenderer.once('execute-complete', (event, data) => {\n                if (data.error) {\n                    reject(new Error(data.error));\n                } else {\n                    resolve(data.value);\n                }\n            });\n            electron.ipcRenderer.send('execute', { name, value });\n        });\n    }\n\n    async request(file, encoding, basename) {\n        return new Promise((resolve, reject) => {\n            const dirname = path.dirname(url.fileURLToPath(import.meta.url));\n            const pathname = path.join(basename || dirname, file);\n            fs.stat(pathname, (err, stat) => {\n                if (err && err.code === 'ENOENT') {\n                    reject(new Error(`The file '${file}' does not exist.`));\n                } else if (err) {\n                    reject(err);\n                } else if (!stat.isFile()) {\n                    reject(new Error(`The path '${file}' is not a file.`));\n                } else if (stat && stat.size < 0x40000000) {\n                    fs.readFile(pathname, encoding, (err, data) => {\n                        if (err) {\n                            reject(err);\n                        } else {\n                            resolve(encoding ? data : new base.BinaryStream(data));\n                        }\n                    });\n                } else if (encoding) {\n                    reject(new Error(`The file '${file}' size (${stat.size.toString()}) for encoding '${encoding}' is greater than 2 GB.`));\n                } else {\n                    const stream = new node.FileStream(pathname, 0, stat.size, stat.mtimeMs);\n                    resolve(stream);\n                }\n            });\n        });\n    }\n\n    openURL(url) {\n        electron.shell.openExternal(url);\n    }\n\n    exception(error, fatal) {\n        if (this._telemetry && error) {\n            try {\n                const name = error.name ? `${error.name}: ` : '';\n                const message = error.message ? error.message : JSON.stringify(error);\n                let context = '';\n                let stack = '';\n                if (error.stack) {\n                    const format = (file, line, column) => {\n                        return `${file.split('\\\\').join('/').split('/').pop()}:${line}:${column}`;\n                    };\n                    const match = error.stack.match(/\\n {4}at (.*) \\((.*):(\\d*):(\\d*)\\)/);\n                    if (match) {\n                        stack = `${match[1]} (${format(match[2], match[3], match[4])})`;\n                    } else {\n                        const match = error.stack.match(/\\n {4}at (.*):(\\d*):(\\d*)/);\n                        if (match) {\n                            stack = `(${format(match[1], match[2], match[3])})`;\n                        } else {\n                            const match = error.stack.match(/.*\\n\\s*(.*)\\s*/);\n                            if (match) {\n                                [, stack] = match;\n                            }\n                        }\n                    }\n                }\n                if (error.context) {\n                    context = typeof error.context === 'string' ? error.context : JSON.stringify(error.context);\n                }\n                this._telemetry.send('exception', {\n                    app_name: this.type,\n                    app_version: this.version,\n                    app_metadata: this.metadata,\n                    error_name: name,\n                    error_message: message,\n                    error_context: context,\n                    error_stack: stack,\n                    error_fatal: fatal ? true : false\n                });\n            } catch {\n                // continue regardless of error\n            }\n        }\n    }\n\n    event(name, params) {\n        if (name && params) {\n            params.app_name = this.type;\n            params.app_version = this.version;\n            params.app_metadata = this.metadata;\n            this._telemetry.send(name, params);\n        }\n    }\n\n    async _context(location) {\n        const basename = path.basename(location);\n        const stat = fs.statSync(location);\n        if (stat.isFile()) {\n            const dirname = path.dirname(location);\n            const stream = await this.request(basename, null, dirname);\n            return new desktop.Context(this, dirname, basename, stream);\n        } else if (stat.isDirectory()) {\n            const entries = new Map();\n            const walk = (dir) => {\n                for (const item of fs.readdirSync(dir)) {\n                    const pathname = path.join(dir, item);\n                    const stat = fs.statSync(pathname);\n                    if (stat.isDirectory()) {\n                        walk(pathname);\n                    } else if (stat.isFile()) {\n                        const stream = new node.FileStream(pathname, 0, stat.size, stat.mtimeMs);\n                        const name = pathname.split(path.sep).join(path.posix.sep);\n                        entries.set(name, stream);\n                    }\n                }\n            };\n            walk(location);\n            return new desktop.Context(this, location, basename, null, entries);\n        }\n        throw new Error(`Unsupported path stat '${JSON.stringify(stat)}'.`);\n    }\n\n    async _open(location) {\n        if (this._files) {\n            this._files.push(location);\n            return;\n        }\n        const path = location.path;\n        const stat = fs.existsSync(path) ? fs.statSync(path) : null;\n        const size = stat && stat.isFile() ? stat.size : 0;\n        if (path && this._view.accept(path, size)) {\n            this._view.show('welcome spinner');\n            let context = null;\n            try {\n                context = await this._context(path);\n                this._telemetry.set('session_engaged', 1);\n            } catch (error) {\n                await this._view.error(error, 'Error while reading file.');\n                this.update({ path: null });\n                return;\n            }\n            try {\n                const attachment = await this._view.attach(context);\n                if (attachment) {\n                    this._view.show(null);\n                } else {\n                    const model = await this._view.open(context);\n                    this._view.show(null);\n                    const options = { ...this._view.options };\n                    if (model) {\n                        options.path = path;\n                        this._title(location.label);\n                    } else {\n                        options.path = path;\n                        this._title('');\n                    }\n                    electron.ipcRenderer.send('update-recents', { path });\n                    this.update(options);\n                }\n            } catch (error) {\n                const options = { ...this._view.options };\n                if (error) {\n                    await this._view.error(error);\n                }\n                this.update(options);\n            }\n        }\n    }\n\n    _request(location, headers, timeout) {\n        const window = this.window;\n        return new Promise((resolve, reject) => {\n            const url = new window.URL(location);\n            const protocol = url.protocol === 'https:' ? https : http;\n            const options = {};\n            options.headers = headers;\n            if (timeout) {\n                options.timeout = timeout;\n            }\n            const request = protocol.request(location, options, (response) => {\n                if (response.statusCode === 200) {\n                    let data = '';\n                    response.on('data', (chunk) => {\n                        data += chunk;\n                    });\n                    response.on('error', (err) => {\n                        reject(err);\n                    });\n                    response.on('end', () => {\n                        resolve(data);\n                    });\n                } else {\n                    const error = new Error(`The web request failed with status code '${response.statusCode}'.`);\n                    error.context = location;\n                    reject(error);\n                }\n            });\n            request.on(\"error\", (err) => {\n                reject(err);\n            });\n            request.on(\"timeout\", () => {\n                request.destroy();\n                const error = new Error('The web request timed out.');\n                error.context = url;\n                reject(error);\n            });\n            request.end();\n        });\n    }\n\n    get(name) {\n        try {\n            return electron.ipcRenderer.sendSync('get-configuration', { name });\n        } catch {\n            // continue regardless of error\n        }\n        return undefined;\n    }\n\n    set(name, value) {\n        try {\n            electron.ipcRenderer.sendSync('set-configuration', { name, value });\n        } catch {\n            // continue regardless of error\n        }\n    }\n\n    delete(name) {\n        try {\n            electron.ipcRenderer.sendSync('delete-configuration', { name });\n        } catch {\n            // continue regardless of error\n        }\n    }\n\n    _title(label) {\n        const element = this._element('titlebar-content-text');\n        if (element) {\n            element.innerHTML = '';\n            if (label) {\n                const path = label.split(this._environment.separator || '/');\n                for (let i = 0; i < path.length; i++) {\n                    const span = this.document.createElement('span');\n                    span.innerHTML = ` ${path[i]} ${i === path.length - 1 ? '' : '<svg class=\"titlebar-icon\" aria-hidden=\"true\"><use xlink:href=\"#icon-arrow-right\"></use></svg>'}`;\n                    element.appendChild(span);\n                }\n            }\n        }\n    }\n\n    _element(id) {\n        return this.document.getElementById(id);\n    }\n\n    update(data) {\n        electron.ipcRenderer.send('window-update', data);\n    }\n\n    async message(message, alert, action) {\n        return new Promise((resolve) => {\n            const type = this.document.body.getAttribute('class');\n            this._element('message-text').innerText = message || '';\n            const button = this._element('message-button');\n            if (action) {\n                button.style.removeProperty('display');\n                button.innerText = action;\n                button.onclick = () => {\n                    button.onclick = null;\n                    this.document.body.setAttribute('class', type);\n                    resolve(0);\n                };\n            } else {\n                button.style.display = 'none';\n                button.onclick = null;\n            }\n            if (alert) {\n                this.document.body.setAttribute('class', 'alert');\n            } else {\n                this.document.body.classList.add('notification');\n                this.document.body.classList.remove('default');\n            }\n            if (action) {\n                button.focus();\n            }\n        });\n    }\n};\n\ndesktop.Context = class {\n\n    constructor(host, folder, identifier, stream, entries) {\n        this._host = host;\n        this._folder = folder;\n        this._identifier = identifier;\n        this._stream = stream;\n        this._entries = entries || new Map();\n    }\n\n    get identifier() {\n        return this._identifier;\n    }\n\n    get stream() {\n        return this._stream;\n    }\n\n    get entries() {\n        return this._entries;\n    }\n\n    async request(file, encoding, base) {\n        return this._host.request(file, encoding, base === undefined ? this._folder : base);\n    }\n\n    async require(id) {\n        return this._host.require(id);\n    }\n\n    error(error, fatal) {\n        this._host.exception(error, fatal);\n    }\n};\n\nif (typeof window !== 'undefined') {\n    window.addEventListener('load', () => {\n        const value = new desktop.Host();\n        window.__view__ = new view.View(value);\n        window.__view__.start();\n    });\n}\n"
  },
  {
    "path": "source/dl4j-metadata.json",
    "content": "[\n  {\n    \"name\": \"BatchNormalization\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"eps\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"decay\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"dilation\" },\n      { \"name\": \"kernelSize\" },\n      { \"name\": \"padding\" }\n    ]\n  },\n  {\n    \"name\": \"Dense\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Dropout\",\n    \"category\": \"Dropout\"\n  },\n  {\n    \"name\": \"GlobalPooling\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"LReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Merge\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Output\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"ReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SeparableConvolution2D\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Subsampling\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"TanH\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Upsampling2D\",\n    \"category\": \"Layer\"\n  }\n]"
  },
  {
    "path": "source/dl4j.js",
    "content": "\n// Experimental\n\nconst dl4j = {};\n\ndl4j.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        if (identifier === 'configuration.json') {\n            const obj = await context.peek('json');\n            if (obj && (obj.confs || obj.vertices)) {\n                return context.set('dl4j.configuration', obj);\n            }\n        } else if (identifier === 'coefficients.bin') {\n            const signature = [0x00, 0x07, 0x4A, 0x41, 0x56, 0x41, 0x43, 0x50, 0x50]; // JAVACPP\n            const stream = context.stream;\n            if (signature.length <= stream.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {\n                return context.set('dl4j.coefficients');\n            }\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        return context.type !== 'dl4j.configuration' || (match.type !== 'dl4j.coefficients' && match.type !== 'openvino.bin');\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('dl4j-metadata.json');\n        switch (context.type) {\n            case 'dl4j.configuration': {\n                const obj = context.value;\n                try {\n                    const content = await context.fetch('coefficients.bin');\n                    const reader = await content.read('binary.big-endian');\n                    return new dl4j.Model(metadata, obj, reader);\n                } catch {\n                    return new dl4j.Model(metadata, obj, null);\n                }\n            }\n            case 'dl4j.coefficients': {\n                const content = await context.fetch('configuration.json');\n                const obj = await content.read('json');\n                const reader = await context.read('binary.big-endian');\n                return new dl4j.Model(metadata, obj, reader);\n            }\n            default: {\n                throw new dl4j.Error(`Unsupported Deeplearning4j format '${context.type}'.`);\n            }\n        }\n    }\n};\n\ndl4j.Model = class {\n\n    constructor(metadata, configuration, coefficients) {\n        this.format = 'Deeplearning4j';\n        this.modules = [new dl4j.Graph(metadata, configuration, coefficients)];\n    }\n};\n\ndl4j.Graph = class {\n\n    constructor(metadata, configuration, coefficients) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        coefficients = coefficients ? new dl4j.NDArray(coefficients) : null;\n        const dataType = coefficients ? coefficients.dataType : '?';\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (name.length === 0 && tensor) {\n                return new dl4j.Value(name, type || null, tensor);\n            }\n            if (!values.has(name)) {\n                values.set(name, new dl4j.Value(name, type || null, tensor || null));\n            } else if (type || tensor) {\n                throw new dl4j.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        if (configuration.networkInputs) {\n            for (const input of configuration.networkInputs) {\n                const value = values.map(input);\n                const argument = new dl4j.Argument(input, [value]);\n                this.inputs.push(argument);\n            }\n        }\n        if (configuration.networkOutputs) {\n            for (const output of configuration.networkOutputs) {\n                const value = values.map(output);\n                const argument = new dl4j.Argument(output, [value]);\n                this.outputs.push(argument);\n            }\n        }\n        let inputs = null;\n        // Computation Graph\n        if (configuration.vertices) {\n            for (const [name,obj] of Object.entries(configuration.vertices)) {\n                const vertex = dl4j.Node._object(obj);\n                inputs = configuration.vertexInputs[name];\n                let variables = [];\n                let layer = null;\n                switch (vertex.__type__) {\n                    case 'LayerVertex':\n                        layer = dl4j.Node._object(vertex.layerConf.layer);\n                        variables = vertex.layerConf.variables;\n                        break;\n                    case 'MergeVertex':\n                        layer = { __type__: 'Merge', layerName: name };\n                        break;\n                    case 'ElementWiseVertex':\n                        layer = { __type__: 'ElementWise', layerName: name, op: vertex.op };\n                        break;\n                    case 'PreprocessorVertex':\n                        layer = { __type__: 'Preprocessor', layerName: name };\n                        break;\n                    default:\n                        throw new dl4j.Error(`Unsupported vertex class '${vertex['@class']}'.`);\n                }\n                const node = new dl4j.Node(metadata, layer, inputs, dataType, variables, values);\n                this.nodes.push(node);\n            }\n        }\n        // Multi Layer Network\n        if (configuration.confs) {\n            inputs = ['input'];\n            this.inputs.push(new dl4j.Argument('input', [values.map('input')]));\n            for (const conf of configuration.confs) {\n                const layer = dl4j.Node._object(conf.layer);\n                const node = new dl4j.Node(metadata, layer, inputs, dataType, conf.variables, values);\n                this.nodes.push(node);\n                inputs = [layer.layerName];\n            }\n            if (inputs && inputs.length > 0) {\n                const argument = new dl4j.Argument('output', [values.map(inputs[0])]);\n                this.outputs.push(argument);\n            }\n        }\n    }\n};\n\ndl4j.Argument = class {\n\n    constructor(name, value, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.visible = visible;\n    }\n};\n\ndl4j.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new dl4j.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\ndl4j.Node = class {\n\n    constructor(metadata, layer, inputs, dataType, variables, values) {\n        this.name = layer.layerName || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const type = layer.__type__;\n        this.type = metadata.type(type) || { name: type };\n        if (inputs && inputs.length > 0) {\n            const argument = new dl4j.Argument(values.length < 2 ? 'input' : 'inputs', inputs.map((input) => values.map(input)));\n            this.inputs.push(argument);\n        }\n        if (variables) {\n            for (const variable of variables) {\n                let tensor = null;\n                switch (type) {\n                    case 'Convolution':\n                        switch (variable) {\n                            case 'W':\n                                tensor = new dl4j.Tensor(dataType, layer.kernelSize.concat([layer.nin, layer.nout]));\n                                break;\n                            case 'b':\n                                tensor = new dl4j.Tensor(dataType, [layer.nout]);\n                                break;\n                            default:\n                                throw new dl4j.Error(`Unsupported '${type}' variable '${variable}'.`);\n                        }\n                        break;\n                    case 'SeparableConvolution2D':\n                        switch (variable) {\n                            case 'W':\n                                tensor = new dl4j.Tensor(dataType, layer.kernelSize.concat([layer.nin, layer.nout]));\n                                break;\n                            case 'pW':\n                                tensor = new dl4j.Tensor(dataType, [layer.nout]);\n                                break;\n                            default:\n                                throw new dl4j.Error(`Unsupported '${type}' variable '${variable}'.`);\n                        }\n                        break;\n                    case 'Output':\n                    case 'Dense':\n                        switch (variable) {\n                            case 'W':\n                                tensor = new dl4j.Tensor(dataType, [layer.nout, layer.nin]);\n                                break;\n                            case 'b':\n                                tensor = new dl4j.Tensor(dataType, [layer.nout]);\n                                break;\n                            default:\n                                throw new dl4j.Error(`Unsupported '${this.type}' variable '${variable}'.`);\n                        }\n                        break;\n                    case 'BatchNormalization':\n                        tensor = new dl4j.Tensor(dataType, [layer.nin]);\n                        break;\n                    default:\n                        throw new dl4j.Error(`Unsupported '${type}' variable '${variable}'.`);\n                }\n                const argument = new dl4j.Argument(variable, [values.map('', null, tensor)]);\n                this.inputs.push(argument);\n            }\n        }\n        if (this.name) {\n            const value = values.map(this.name);\n            const argument = new dl4j.Argument('output', [value]);\n            this.outputs.push(argument);\n        }\n        let attributes = layer;\n        if (layer.activationFn) {\n            const activation = dl4j.Node._object(layer.activationFn);\n            if (activation.__type__ !== 'ActivationIdentity' && activation.__type__ !== 'Identity') {\n                if (activation.__type__.startsWith('Activation')) {\n                    activation.__type__ = activation.__type__.substring('Activation'.length);\n                }\n                if (this.type === 'Activation') {\n                    this.type = activation.__type__;\n                    attributes = activation;\n                } else {\n                    this.chain = this.chain || [];\n                    this.chain.push(new dl4j.Node(metadata, activation, [], null, null, values));\n                }\n            }\n        }\n        for (const [name, value] of Object.entries(attributes)) {\n            switch (name) {\n                case '__type__':\n                case 'constraints':\n                case 'layerName':\n                case 'activationFn':\n                case 'idropout':\n                case 'hasBias':\n                    continue;\n                default:\n                    break;\n            }\n            const definition = metadata.attribute(type, name);\n            const visible = definition && definition.visible === false ? false : true;\n            const attribute = new dl4j.Argument(name, value, visible);\n            this.attributes.push(attribute);\n        }\n        if (layer.idropout) {\n            const dropout = dl4j.Node._object(layer.idropout);\n            if (dropout.p !== 1.0) {\n                throw new dl4j.Error(\"Layer 'idropout' not implemented.\");\n            }\n        }\n    }\n\n    static _object(value) {\n        let result = {};\n        if (value['@class']) {\n            result = value;\n            let type = value['@class'].split('.').pop();\n            if (type.endsWith('Layer')) {\n                type = type.substring(0, type.length - 5);\n            }\n            delete value['@class'];\n            result.__type__ = type;\n        } else {\n            let [key] = Object.keys(value);\n            result = value[key];\n            if (key.length > 0) {\n                key = key[0].toUpperCase() + key.substring(1);\n            }\n            result.__type__ = key;\n        }\n        return result;\n    }\n};\n\ndl4j.Tensor = class {\n\n    constructor(dataType, shape) {\n        this.type = new dl4j.TensorType(dataType, new dl4j.TensorShape(shape));\n    }\n};\n\ndl4j.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\ndl4j.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions) {\n            if (this.dimensions.length === 0) {\n                return '';\n            }\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\ndl4j.NDArray = class {\n\n    constructor(reader) {\n        reader = new dl4j.BinaryReader(reader);\n        const readHeader = (reader) => {\n            const alloc = reader.string();\n            let length = 0;\n            switch (alloc) {\n                case 'DIRECT':\n                case 'HEAP':\n                case 'JAVACPP':\n                    length = reader.int32();\n                    break;\n                case 'LONG_SHAPE':\n                case 'MIXED_DATA_TYPES':\n                    length = reader.int64().toNumber();\n                    break;\n                default:\n                    throw new dl4j.Error(`Unsupported header alloc '${alloc}'.`);\n            }\n            const type = reader.string();\n            return [alloc, length, type];\n        };\n        const headerShape = readHeader(reader);\n        if (headerShape[2] !== 'INT') {\n            throw new dl4j.Error(`Unsupported header shape type '${headerShape[2]}'.`);\n        }\n        const shapeInfo = new Array(headerShape[1]);\n        for (let i = 0; i < shapeInfo.length; i++) {\n            shapeInfo[i] = reader.int32();\n        }\n        const [rank] = shapeInfo;\n        const shapeInfoLength = rank * 2 + 4;\n        this.shape = shapeInfo.slice(1, 1 + rank);\n        this.strides = shapeInfo.slice(1 + rank, 1 + (rank * 2));\n        this.order = shapeInfo[shapeInfoLength - 1];\n        const headerData = readHeader(reader);\n        const dataTypes = new Map([\n            ['INT', ['int32', 4]],\n            ['FLOAT', ['float32', 4]],\n            ['DOUBLE', ['float64', 8]]\n        ]);\n        if (!dataTypes.has(headerData[2])) {\n            throw new dl4j.Error(`Unsupported header data type '${headerData[2]}'.`);\n        }\n        const [dataType, itemSize] = dataTypes.get(headerData[2]);\n        this.dataType = dataType;\n        const size = headerData[1] * itemSize;\n        if ((reader.position + size) <= reader.length) {\n            this.data = reader.read(size);\n        }\n    }\n};\n\ndl4j.BinaryReader = class {\n\n    constructor(reader) {\n        this._reader = reader;\n    }\n\n    get length() {\n        return this._reader.length;\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    int32() {\n        return this._reader.int32();\n    }\n\n    int64() {\n        return this._reader.int64();\n    }\n\n    uint16() {\n        return this._reader.uint16();\n    }\n\n    string() {\n        const size = this.uint16();\n        const buffer = this.read(size);\n        this._decoder = this._decoder || new TextDecoder('ascii');\n        return this._decoder.decode(buffer);\n    }\n};\n\ndl4j.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Deeplearning4j model.';\n    }\n};\n\nexport const ModelFactory = dl4j.ModelFactory;\n"
  },
  {
    "path": "source/dlc-metadata.json",
    "content": "[\n  {\n    \"name\": \"BatchNorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"Batchnorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Conv2d\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"Convolutional\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"DepthWiseConv2d\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"FullyConnected\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"Gather\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"indices\" }\n    ]\n  },\n  {\n    \"name\": \"Neuron\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"Activation\" }\n    ]\n  },\n  {\n    \"name\": \"Pad\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Permute\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Pool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"PoolAvg2d\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"PoolMax2d\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Prelu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" }\n    ]\n  },\n  {\n    \"name\": \"Relu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Slice\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"SoftMax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Split\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"StridedSlice\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Transpose\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"TransposeConv2d\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/dlc-schema.js",
    "content": "\nexport const dlc = {};\n\ndlc.v3 = dlc.v3 || {};\n\ndlc.v3.Model = class Model {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.Model();\n        $.unk1 = reader.int32_(position, 4, 0);\n        $.nodes = reader.tables(position, 6, dlc.v3.Node);\n        $.unk2 = reader.array(position, 8, Int32Array);\n        $.unk3 = reader.array(position, 10, Int32Array);\n        $.attributes = reader.tables(position, 12, dlc.v3.Attribute);\n        return $;\n    }\n};\n\ndlc.v3.Node = class Node {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.Node();\n        $.index = reader.int32_(position, 4, 0);\n        $.name = reader.string_(position, 6, null);\n        $.type = reader.string_(position, 8, null);\n        $.inputs = reader.strings_(position, 10);\n        $.outputs = reader.strings_(position, 12);\n        $.attributes = reader.tables(position, 14, dlc.v3.Attribute);\n        return $;\n    }\n};\n\ndlc.v3.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.Tensor();\n        $.name = reader.string_(position, 4, null);\n        $.shape = reader.array(position, 6, Int32Array);\n        $.data = reader.table(position, 8, dlc.v3.TensorData);\n        $.attributes = reader.tables(position, 10, dlc.v3.Attribute);\n        return $;\n    }\n};\n\ndlc.v3.TensorData = class TensorData {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.TensorData();\n        $.dtype = reader.uint8_(position, 4, 0);\n        $.bytes = reader.array(position, 6, Uint8Array);\n        $.floats = reader.array(position, 8, Float32Array);\n        return $;\n    }\n};\n\ndlc.v3.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.Attribute();\n        $.name = reader.string_(position, 4, null);\n        $.type = reader.uint8_(position, 6, 0);\n        $.bool_value = reader.bool_(position, 8, false);\n        $.int32_value = reader.int32_(position, 10, 0);\n        $.uint32_value = reader.uint32_(position, 12, 0);\n        $.float32_value = reader.float32_(position, 14, 0);\n        $.string_value = reader.string_(position, 16, null);\n        $.unk6 = reader.array(position, 18, Int8Array);\n        $.byte_list = reader.array(position, 20, Int8Array);\n        $.int32_list = reader.array(position, 22, Int32Array);\n        $.float32_list = reader.array(position, 24, Float32Array);\n        $.unk10 = reader.array(position, 26, Int8Array);\n        $.attributes = reader.tables(position, 28, dlc.v3.Attribute);\n        return $;\n    }\n};\n\ndlc.v3.Activation = {\n    ReLU: 1, '1': 'ReLU',\n    Sigmoid: 3, '3': 'Sigmoid'\n};\n\ndlc.v3.ModelParameters = class ModelParameters {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.ModelParameters();\n        $.nodes = reader.tables(position, 4, dlc.v3.NodeParameters);\n        return $;\n    }\n};\n\ndlc.v3.NodeParameters = class NodeParameters {\n\n    static decode(reader, position) {\n        const $ = new dlc.v3.NodeParameters();\n        $.name = reader.string_(position, 4, null);\n        $.weights = reader.tables(position, 6, dlc.v3.Tensor);\n        return $;\n    }\n};\n\ndlc.v4 = dlc.v4 || {};\n\ndlc.v4.Model = class Model {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Model();\n        $.graphs = reader.tables(position, 4, dlc.v4.Graph);\n        return $;\n    }\n};\n\ndlc.v4.Graph = class Graph {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Graph();\n        $.name = reader.string_(position, 4, null);\n        $.nodes = reader.tables(position, 6, dlc.v4.Node);\n        $.tensors = reader.tables(position, 8, dlc.v4.Tensor);\n        return $;\n    }\n};\n\ndlc.v4.Node = class Node {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Node();\n        $.name = reader.string_(position, 4, null);\n        $.type = reader.string_(position, 6, null);\n        $.inputs = reader.strings_(position, 8);\n        $.outputs = reader.strings_(position, 10);\n        $.attributes = reader.tables(position, 12, dlc.v4.Attribute);\n        return $;\n    }\n};\n\ndlc.v4.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Attribute();\n        $.name = reader.string_(position, 4, null);\n        $.kind = reader.int32_(position, 6, 0);\n        $.flag = reader.uint8_(position, 8, 0);\n        $.value = reader.table(position, 10, dlc.v4.Value);\n        $.tensor = reader.table(position, 12, dlc.v4.Tensor);\n        return $;\n    }\n};\n\ndlc.v4.Value = class Value {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Value();\n        $.kind = reader.int32_(position, 4, 0);\n        $.int32_value = reader.int32_(position, 6, 0);\n        $.float32_value = reader.float32_(position, 8, 0);\n        $.string_value = reader.string_(position, 10, null);\n        return $;\n    }\n};\n\ndlc.v4.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Tensor();\n        $.unk1 = reader.uint32_(position, 4, 0);\n        $.name = reader.string_(position, 6, null);\n        $.location = reader.int32_(position, 8, 0);\n        $.shape = reader.array(position, 10, Int32Array);\n        $.unk2 = reader.int32_(position, 12, 0);\n        $.info = reader.table(position, 14, dlc.v4.TensorInfo);\n        $.dtype = reader.int32_(position, 16, 0);\n        $.output_dtype = reader.int32_(position, 18, 0);\n        $.unk6 = reader.uint8_(position, 20, 0);\n        return $;\n    }\n};\n\ndlc.v4.TensorInfo = class TensorInfo {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.TensorInfo();\n        $.i1 = reader.int32_(position, 4, 0);\n        $.b1 = reader.uint8_(position, 6, 0);\n        $.a = reader.table(position, 8, dlc.v4.TensorInfo1);\n        $.b = reader.table(position, 10, dlc.v4.TensorInfo2);\n        return $;\n    }\n};\n\ndlc.v4.TensorInfo1 = class TensorInfo1 {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.TensorInfo1();\n        $.i1 = reader.int32_(position, 4, 0);\n        $.f1 = reader.float32_(position, 6, 0);\n        $.f2 = reader.float32_(position, 8, 0);\n        $.f3 = reader.float32_(position, 10, 0);\n        $.i2 = reader.int32_(position, 12, 0);\n        return $;\n    }\n};\n\ndlc.v4.TensorInfo2 = class TensorInfo2 {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.TensorInfo2();\n        $.i1 = reader.int32_(position, 4, 0);\n        $.l = reader.tables(position, 6, dlc.v4.TensorInfo3);\n        return $;\n    }\n};\n\ndlc.v4.TensorInfo3 = class TensorInfo3 {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.TensorInfo3();\n        $.i1 = reader.int32_(position, 4, 0);\n        $.f1 = reader.float32_(position, 6, 0);\n        $.f2 = reader.float32_(position, 8, 0);\n        $.f3 = reader.float32_(position, 10, 0);\n        $.i2 = reader.int32_(position, 12, 0);\n        $.b1 = reader.uint8_(position, 14, 0);\n        return $;\n    }\n};\n\ndlc.v4.ModelParameters64 = class ModelParameters64 {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.ModelParameters64();\n        $.buffers = reader.tables(position, 4, dlc.v4.Buffer);\n        $.params = reader.array(position, 6, Uint8Array);\n        return $;\n    }\n};\n\ndlc.v4.ModelParameters = class ModelParameters {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.ModelParameters();\n        $.graphs = reader.tables(position, 4, dlc.v4.GraphParameters);\n        return $;\n    }\n};\n\ndlc.v4.GraphParameters = class GraphParameters {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.GraphParameters();\n        $.name = reader.string_(position, 4, null);\n        $.tensors = reader.tables(position, 6, dlc.v4.TensorData);\n        $.nodes = reader.tables(position, 8, dlc.v4.NodeParameters);\n        return $;\n    }\n};\n\ndlc.v4.NodeParameters = class NodeParameters {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.NodeParameters();\n        $.tensors = reader.tables(position, 4, dlc.v4.TensorData);\n        return $;\n    }\n};\n\ndlc.v4.TensorData = class TensorData {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.TensorData();\n        $.name = reader.string_(position, 4, null);\n        $.bytes = reader.array(position, 6, Uint8Array);\n        return $;\n    }\n};\n\ndlc.v4.Buffer = class Buffer {\n\n    static decode(reader, position) {\n        const $ = new dlc.v4.Buffer();\n        $.bytes = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/dlc.js",
    "content": "\nimport * as flatbuffers from './flatbuffers.js';\nimport * as text from './text.js';\n\nconst dlc = {};\n\ndlc.ModelFactory = class {\n\n    async match(context) {\n        const container = await dlc.Container.open(context);\n        if (container) {\n            return context.set('dlc', container);\n        }\n        return null;\n    }\n\n    async open(context) {\n        dlc.schema = await context.require('./dlc-schema');\n        dlc.schema = dlc.schema.dlc;\n        await context.value.read();\n        const metadata = await context.metadata('dlc-metadata.json');\n        return new dlc.Model(metadata, context.value);\n    }\n};\n\ndlc.Model = class {\n\n    constructor(metadata, target) {\n        this.format = target.format;\n        this.metadata = [];\n        if (target.metadata.size > 0) {\n            const version = target.metadata.get('model-version');\n            if (version) {\n                this.version = version;\n            }\n            const converter = target.metadata.get('converter-command');\n            if (converter) {\n                const source = converter.split(' ').shift().trim();\n                if (source.length > 0) {\n                    const version = target.metadata.get('converter-version');\n                    this.source = version ? `${source} v${version}` : source;\n                }\n            }\n            const license = target.metadata.get('model-copyright');\n            if (license && license !== 'N/A') {\n                this.metadata.push(new dlc.Argument('license', license));\n            }\n        }\n        for (const graph of target.graphs) {\n            this.modules = [new dlc.Graph(metadata, target.version.major, graph)];\n        }\n    }\n};\n\ndlc.Graph = class {\n\n    constructor(metadata, version, graph) {\n        this.name = graph.name;\n        this.inputs = [];\n        this.outputs = [];\n        const values = new Map();\n        switch (version) {\n            case 3: {\n                for (const node of graph.nodes) {\n                    for (const name of node.inputs) {\n                        if (!values.has(name)) {\n                            values.set(name, {});\n                        }\n                    }\n                    for (const name of node.outputs) {\n                        if (!values.has(name)) {\n                            values.set(name, {});\n                        }\n                    }\n                    let shapes = new Array(node.outputs.length);\n                    for (const attribute of node.attributes) {\n                        if (attribute.name === 'OutputDims' &&\n                            Array.isArray(attribute.attributes) && attribute.attributes.length > 0) {\n                            shapes = attribute.data;\n                            break;\n                        }\n                    }\n                    for (let i = 0; i < node.outputs.length; i++) {\n                        const name = node.outputs[i];\n                        const value = values.get(name);\n                        if (!value.shape && i < shapes.length) {\n                            value.shape = shapes[i];\n                        }\n                    }\n                }\n                break;\n            }\n            case 4: {\n                for (const tensor of graph.tensors) {\n                    values.set(tensor.name, tensor);\n                }\n                break;\n            }\n            default: {\n                break;\n            }\n        }\n        for (const [name, tensor] of values) {\n            const type = tensor.shape ? new dlc.TensorType(tensor.dtype, tensor.shape) : null;\n            const initializer = tensor.data && tensor.data ? new dlc.Tensor(tensor.name, type, tensor.data) : null;\n            const value = new dlc.Value(name, type, initializer);\n            values.set(name, value);\n        }\n        const value = (name) => {\n            if (!values.has(name)) {\n                values.set(name, new dlc.Value(name));\n            }\n            return values.get(name);\n        };\n        this.nodes = [];\n        for (const node of graph.nodes) {\n            if (node.type === 'Input') {\n                this.inputs.push(new dlc.Argument(node.name, node.inputs.map((input) => value(input))));\n                continue;\n            }\n            this.nodes.push(new dlc.Node(metadata, version, node, value));\n        }\n    }\n};\n\ndlc.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\ndlc.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new dlc.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = type;\n        this.initializer = initializer;\n    }\n};\n\ndlc.Node = class {\n\n    constructor(metadata, version, obj, value) {\n        this.type = metadata.type(obj.type);\n        this.name = obj.name;\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const inputs = Array.isArray(obj.inputs) ? Array.from(obj.inputs).map((name) => value(name)) : [];\n        if (version !== 3 && Array.isArray(this.type.inputs) && inputs.length === this.type.inputs.length) {\n            for (let i = 0; i < inputs.length; i++) {\n                const argument = new dlc.Argument(this.type.inputs[i].name, [inputs[i]]);\n                this.inputs.push(argument);\n            }\n        } else if (inputs.length > 0) {\n            const argument = new dlc.Argument(inputs.length === 1 ? 'input' : 'inputs', inputs);\n            this.inputs.push(argument);\n        }\n        const outputs = Array.isArray(obj.outputs) ? Array.from(obj.outputs).map((name) => value(name)) : [];\n        if (Array.isArray(this.type.outputs) && outputs.length === this.type.outputs.length) {\n            for (let i = 0; i < outputs.length; i++) {\n                const argument = new dlc.Argument(this.type.outputs[i].name, [outputs[i]]);\n                this.outputs.push(argument);\n            }\n        } else if (outputs.length > 0) {\n            const argument = new dlc.Argument(outputs.length === 1 ? 'output' : 'outputs', outputs);\n            this.outputs.push(argument);\n        }\n        if (obj.attributes) {\n            for (const attr of obj.attributes) {\n                if (attr.name === 'OutputDims') {\n                    continue;\n                }\n                const schema = metadata.attribute(obj.type, attr.name);\n                let type = attr.type;\n                switch (type) {\n                    case 'tensor': {\n                        const tensor = attr.data;\n                        const type = new dlc.TensorType(tensor.dtype, tensor.shape);\n                        value = new dlc.Tensor(tensor.name, type, tensor.data);\n                        break;\n                    }\n                    default: {\n                        value = attr.data;\n                    }\n                }\n                if (schema && schema.type) {\n                    type = schema.type;\n                    let enumType = null;\n                    switch (version) {\n                        case 3: enumType = dlc.schema.v3[type]; break;\n                        case 4: enumType = dlc.schema.v4[type]; break;\n                        default: throw new dlc.Error(`Unsupported version '${version}'.`);\n                    }\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                }\n                const attribute = new dlc.Argument(attr.name, value, type);\n                this.attributes.push(attribute);\n            }\n        }\n        if (obj.weights) {\n            for (const tensor of obj.weights) {\n                const type = new dlc.TensorType(tensor.data.dtype, tensor.shape);\n                const value = new dlc.Value('', type, new dlc.Tensor(tensor.name, type, tensor.data));\n                this.inputs.push(new dlc.Argument(tensor.name, [value]));\n            }\n        }\n    }\n};\n\ndlc.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = new dlc.TensorShape(shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ndlc.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.from(dimensions);\n    }\n\n    toString() {\n        if (Array.isArray(this.dimensions) && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\ndlc.Tensor = class {\n\n    constructor(name, type, data) {\n        this.name = name;\n        this.type = type;\n        if (data instanceof Uint8Array) {\n            this.encoding = '<';\n            this.values = data;\n        } else {\n            this.encoding = '|';\n            switch (type.dataType) {\n                case 'uint8': this.values = data.bytes; break;\n                case 'float32': this.values = data.floats; break;\n                default: throw new dlc.Error(`Unsupported tensor data type '${type.dataType}'.`);\n            }\n        }\n    }\n};\n\ndlc.Container = class {\n\n    static async open(context) {\n        const entries = await context.peek('zip');\n        if (entries instanceof Map) {\n            const model = entries.get('model');\n            const params = entries.get('model.params');\n            const metadata = entries.get('dlc.metadata');\n            if (model) {\n                const signature = dlc.Container._signature(model);\n                if (signature && (signature.identifier === 'NETD' || signature.major === 2)) {\n                    return new dlc.Container(context, model, params, metadata);\n                }\n            }\n            if (params) {\n                const signature = dlc.Container._signature(params);\n                if (signature && signature.identifier === 'NETP') {\n                    return new dlc.Container(context, model, params, metadata);\n                }\n            }\n            return null;\n        }\n        const stream = context.stream;\n        const signature = dlc.Container._signature(stream);\n        switch (signature.identifier) {\n            case 'NETD':\n                return new dlc.Container(context, stream, undefined, undefined);\n            case 'NETP':\n            case 'NR64':\n                return new dlc.Container(context, undefined, stream, undefined);\n            default:\n                return null;\n        }\n    }\n\n    constructor(context, model, params, metadata) {\n        this.context = context;\n        this._model = model;\n        this._params = params;\n        this._metadata = metadata;\n    }\n\n    async read() {\n        if (this._model === undefined) {\n            this._model = await this._fetch('model');\n        }\n        if (this._params === undefined) {\n            this._params = await this._fetch('model.params');\n        }\n        if (this._metadata === undefined) {\n            this._metadata = await this._fetch('dlc.metadata');\n        }\n        delete this.context;\n        this.graphs = [];\n        this.metadata = new Map();\n        if (this._model) {\n            this.format = 'DLC';\n            const stream = this._model;\n            delete this._model;\n            const signature = dlc.Container._signature(stream);\n            if (signature.major === 2) {\n                throw new dlc.Error(\"File contains undocumented DLC v2 data.\");\n            } else if (signature.identifier === 'NETD' && (signature.major === 3 || signature.major === undefined)) {\n                this.version = { major: signature.major || 3, minor: signature.minor || 0 };\n                this.graph = dlc.Container._model3(stream, signature.offset);\n                this.graphs = [this.graph];\n            } else if (signature.identifier === 'NETD' && signature.major === 4) {\n                this.version = { major: signature.major, minor: signature.minor };\n                this.graphs = dlc.Container._model4(stream);\n            } else {\n                const buffer = stream.peek(Math.min(stream.length, 16));\n                const content = Array.from(buffer).map((c) => (c < 16 ? '0' : '') + c.toString(16)).join('');\n                throw new dlc.Error(`File contains undocumented '${content}' data.`);\n            }\n        }\n        if (this._params) {\n            this.format = this.format || 'DLC Weights';\n            const stream = this._params;\n            delete this._params;\n            const signature = dlc.Container._signature(stream);\n            if (signature.major === 2) {\n                throw new dlc.Error(\"File contains undocumented DLC v2 data.\");\n            } else if (signature.identifier === 'NETP' && (signature.major === 3 || signature.major === undefined)) {\n                this.version = this.graphs.length > 0 ? this.version : { major: signature.major || 3, minor: signature.minor || 0 };\n                this.graph = dlc.Container._params3(stream, signature, this.graph);\n                this.graphs = [this.graph];\n            } else if ((signature.identifier === 'NETP' || signature.identifier === 'NR64') && signature.major === 4) {\n                dlc.Container._params4(stream, this.graphs, signature);\n            } else {\n                const buffer = stream.peek(Math.min(stream.length, 16));\n                const content = Array.from(buffer).map((c) => (c < 16 ? '0' : '') + c.toString(16)).join('');\n                throw new dlc.Error(`File contains undocumented '${content}' data.`);\n            }\n        }\n        if (this._metadata) {\n            const stream = this._metadata;\n            delete this._metadata;\n            const reader = text.Reader.open(stream);\n            for (;;) {\n                const line = reader.read('\\n');\n                if (line === undefined) {\n                    break;\n                }\n                const index = line.indexOf('=');\n                if (index === -1) {\n                    break;\n                }\n                const key = line.substring(0, index);\n                const value = line.substring(index + 1);\n                this.metadata.set(key, value);\n            }\n        }\n    }\n\n    static _model3(stream, offset) {\n        let model = null;\n        try {\n            const buffer = new Uint8Array(offset > 0 ? stream.peek().subarray(offset) : stream.peek());\n            const reader = flatbuffers.BinaryReader.open(buffer);\n            model = dlc.schema.v3.Model.decode(reader, reader.root);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new dlc.Error(`File format is not dlc.v3.NETD (${message.replace(/\\.$/, '')}).`);\n        }\n        model.tensors = [];\n        const updateAttribute = (attr) => {\n            switch (attr.type) {\n                case 1: return ['boolean',   attr.bool_value];\n                case 2: return ['int32',     attr.int32_value];\n                case 3: return ['uint32',    attr.uint32_value];\n                case 4: return ['float32',   attr.float32_value];\n                case 5: return ['string',    attr.string_value];\n                case 7: return ['byte[]',    Array.from(attr.byte_list)];\n                case 8: return ['int32[]',   Array.from(attr.int32_list)];\n                case 9: return ['float32[]', Array.from(attr.float32_list)];\n                case 11: {\n                    const obj = {};\n                    let index = 0;\n                    let list = true;\n                    for (const attribute of attr.attributes) {\n                        const name = attribute.name;\n                        const [, data] = updateAttribute(attribute);\n                        obj[name] = data;\n                        list = list && index.toString() === attribute.name;\n                        index++;\n                    }\n                    return list ? ['', Object.values(obj)] : ['', obj];\n                }\n                default:\n                    throw new dlc.Error(`Unsupported attribute type '${attr.type}'.`);\n            }\n        };\n        for (const node of model.nodes) {\n            for (const attribute of node.attributes) {\n                const [type, data] = updateAttribute(attribute);\n                attribute.type = type;\n                attribute.data = data;\n            }\n        }\n        return model;\n    }\n\n    static _model4(stream) {\n        let model = null;\n        try {\n            const buffer = new Uint8Array(stream.peek().subarray(8));\n            const reader = flatbuffers.BinaryReader.open(buffer);\n            model = dlc.schema.v4.Model.decode(reader, reader.root);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new dlc.Error(`File format is not dlc.v4.NETD (${message.replace(/\\.$/, '')}).`);\n        }\n        const dataType = (value) => {\n            switch (value) {\n                case 0x0008: return 'int8';\n                case 0x0016: return 'int16';\n                case 0x0032: return 'int32';\n                case 0x0064: return 'int64';\n                case 0x0108: return 'uint8';\n                case 0x0116: return 'uint16';\n                case 0x0132: return 'uint32';\n                case 0x0164: return 'uint64';\n                case 0x0216: return 'float16';\n                case 0x0232: return 'float32';\n                case 0x0304: return 'qint4';\n                case 0x0308: return 'qint8';\n                case 0x0316: return 'qint16';\n                case 0x0332: return 'qint32';\n                case 0x0404: return 'quint4';\n                case 0x0408: return 'quint8';\n                case 0x0416: return 'quint16';\n                case 0x0432: return 'quint32';\n                case 0x0508: return 'boolean';\n                case 0x0608: return 'string';\n                case 0x7fffffff: return 'undefined';\n                default: throw new dlc.Error(`Unsupported data type '${JSON.stringify(value)}'.`);\n            }\n        };\n        const updateTensor = (tensor) => {\n            tensor.dtype = dataType(tensor.dtype);\n            tensor.output_dtype = dataType(tensor.output_dtype);\n        };\n        for (const graph of model.graphs) {\n            for (const node of graph.nodes) {\n                for (const attribute of node.attributes) {\n                    switch (attribute.kind) {\n                        case 0: {\n                            const value = attribute.value;\n                            switch (value.kind) {\n                                case 0x7fffffff:\n                                    attribute.data = value.string_value;\n                                    attribute.type = 'string';\n                                    break;\n                                case 0x0032:\n                                    attribute.data = value.int32_value;\n                                    break;\n                                case 0x0108:\n                                    attribute.data = value.int32_value;\n                                    attribute.type = 'int8';\n                                    break;\n                                case 0x0132:\n                                    attribute.data = value.int32_value;\n                                    attribute.type = 'int32';\n                                    break;\n                                case 0x0232:\n                                    attribute.data = value.float32_value;\n                                    attribute.type = 'float32';\n                                    break;\n                                case 0x0508:\n                                    attribute.data = value.int32_value !== 0;\n                                    attribute.type = 'boolean';\n                                    break;\n                                case 0x0608:\n                                    attribute.data = value.string_value;\n                                    attribute.type = 'string';\n                                    break;\n                                default:\n                                    throw new dlc.Error(`Unknown attribute value kind '${value.kind}'.`);\n                            }\n                            break;\n                        }\n                        case 1: {\n                            const tensor = attribute.tensor;\n                            updateTensor(tensor);\n                            attribute.type = 'tensor';\n                            attribute.data = tensor;\n                            break;\n                        }\n                        default: {\n                            throw new dlc.Error(`Unknown attribute kind '${attribute.kind}'.`);\n                        }\n                    }\n                }\n            }\n            for (const tensor of graph.tensors) {\n                updateTensor(tensor);\n            }\n        }\n        return model.graphs;\n    }\n\n    static _params3(stream, signature, graph) {\n        let params = null;\n        try {\n            const buffer = new Uint8Array(signature === 'NETP' ? stream.peek() : stream.peek().subarray(8));\n            const reader = flatbuffers.BinaryReader.open(buffer);\n            params = dlc.schema.v3.ModelParameters.decode(reader, reader.root);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new dlc.Error(`File format is not dlc.v3.NETP (${message.replace(/\\.$/, '')}).`);\n        }\n        if (!graph) {\n            graph = new dlc.schema.v3.ModelParameters();\n            graph.nodes = new Array(params.nodes.length);\n            graph.tensors = [];\n            for (let i = 0; i < graph.nodes.length; i++) {\n                const node = new dlc.schema.v3.Node();\n                node.type = 'Weights';\n                node.name = params.nodes[i].name;\n                node.inputs = [];\n                node.outputs = [];\n                node.attributes = [];\n                graph.nodes[i] = node;\n            }\n        }\n        const dataType = (value) => {\n            switch (value) {\n                case null: return '?';\n                case 6: return 'uint8';\n                case 9: return 'float32';\n                default:\n                    throw new dlc.Error(`Unsupported data type '${JSON.stringify(value)}'.`);\n            }\n        };\n        const weights = new Map(params.nodes.map((node) => [node.name, node.weights]));\n        for (const node of graph.nodes) {\n            if (weights.has(node.name)) {\n                const tensors = weights.get(node.name);\n                for (const tensor of tensors) {\n                    tensor.data.dtype = dataType(tensor.data.dtype);\n                }\n                node.weights = tensors;\n            }\n        }\n        return graph;\n    }\n\n    static _params4(stream, graphs, signature) {\n        let buffer = stream.peek().subarray(8);\n        let buffers = null;\n        if (signature.major === 4 && signature.identifier === 'NR64') {\n            try {\n                const reader = flatbuffers.BinaryReader.open(buffer);\n                const nr64 = dlc.schema.v4.ModelParameters64.decode(reader, reader.root);\n                buffers = nr64.buffers;\n                buffer = nr64.params;\n            } catch (error) {\n                const message = error && error.message ? error.message : error.toString();\n                throw new dlc.Error(`File format is not dlc.v4.NR64 (${message.replace(/\\.$/, '')}).`);\n            }\n        }\n        let params = null;\n        try {\n            const reader = flatbuffers.BinaryReader.open(buffer);\n            params = dlc.schema.v4.ModelParameters.decode(reader, reader.root);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new dlc.Error(`File format is not dlc.v4.NETP (${message.replace(/\\.$/, '')}).`);\n        }\n        if (graphs.length === 0) {\n            throw new dlc.Error('Model definition not available.');\n        }\n        const weights = new Map(params.graphs.map((graph) => [graph.name, graph]));\n        for (const graph of graphs) {\n            const params = weights.get(graph.name);\n            const tensors = new Map(params.tensors.map((tensor) => [tensor.name, tensor]));\n            let index = 0;\n            graph.tensors.sort((a, b) => a.name.localeCompare(b.name));\n            for (const tensor of graph.tensors) {\n                if (tensor.location === 4) {\n                    if (buffers && index < buffers.length) {\n                        tensor.data = buffers[index++].bytes;\n                    } else if (tensors.has(tensor.name)) {\n                        tensor.data = tensors.get(tensor.name).bytes;\n                    } else {\n                        throw new dlc.Error(`Unknown tensor `);\n                    }\n                }\n            }\n            for (let i = 0; i < graph.nodes.length; i++) {\n                const node = graph.nodes[i];\n                const tensors = new Map(params.nodes[i].tensors.map((tensor) => [tensor.name, tensor]));\n                for (const attribute of node.attributes) {\n                    const tensor = attribute.tensor;\n                    if (tensor) {\n                        if (buffers && index < buffers.length) {\n                            tensor.data = buffers[index++].bytes;\n                        } else if (tensors.has(tensor.name)) {\n                            tensor.data = tensors.get(tensor.name).bytes;\n                        } else {\n                            throw new dlc.Error(`Unknown tensor `);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    async _fetch(name) {\n        try {\n            const context = await this.context.fetch(name);\n            return context.stream;\n        } catch {\n            return null;\n        }\n    }\n\n    static _signature(stream) {\n        const signature = {};\n        signature.identifier = '?';\n        signature.offset = 0;\n        if (stream) {\n            const buffer = stream.peek(Math.min(stream.length, 16));\n            if (buffer[0] === 0xD5 && buffer[1] === 0x0A) {\n                delete signature.identifier;\n                if (buffer[3] === 0x00 && buffer[5] === 0x00 && buffer[6] === 0x00) {\n                    signature.major = buffer[2] | buffer[3] << 8;\n                    signature.minor = buffer[4] | buffer[5] << 8;\n                    if (signature.major > 2) {\n                        signature.identifier = '?';\n                    }\n                }\n            }\n            if (signature.identifier === '?') {\n                const offset = signature.major === undefined ? 0 : 8;\n                const reader = flatbuffers.BinaryReader.open(stream, offset);\n                if (reader) {\n                    signature.identifier = reader.identifier;\n                    signature.offset = offset;\n                }\n            }\n        }\n        return signature;\n    }\n};\n\ndlc.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading DLC model.';\n    }\n};\n\nexport const ModelFactory = dlc.ModelFactory;\n\n"
  },
  {
    "path": "source/dnn-metadata.json",
    "content": "[\n  {\n    \"name\": \"batchnorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"concat\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\", \"option\": \"variadic\" }\n    ]\n  },\n  {\n    \"name\": \"const_v2\",\n    \"category\": \"Constant\"\n  },\n  {\n    \"name\": \"conv\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"deconv\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"depthdeconv\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"eltwise\",\n    \"inputs\": [\n      { \"name\": \"input\", \"option\": \"variadic\" }\n    ]\n  },\n  {\n    \"name\": \"linear\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"pad\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"pool\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"prelu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"slope\" }\n    ]\n  },\n  {\n    \"name\": \"relu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"relu6\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"sigmoid\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/dnn-proto.js",
    "content": "\nexport const dnn = {};\n\ndnn.Model = class Model {\n\n    constructor() {\n        this.input_shape = [];\n        this.input_name = [];\n        this.node = [];\n        this.input = [];\n        this.output = [];\n    }\n\n    static decode(reader, length) {\n        const message = new dnn.Model();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.version = reader.int32();\n                    break;\n                case 4:\n                    message.input_shape = reader.array(message.input_shape, () => reader.int32(), tag);\n                    break;\n                case 7:\n                    message.input_name.push(reader.string());\n                    break;\n                case 10:\n                    message.node.push(dnn.Node.decode(reader, reader.uint32()));\n                    break;\n                case 12:\n                    message.input.push(dnn.Parameter.decode(reader, reader.uint32()));\n                    break;\n                case 13:\n                    message.output.push(dnn.Parameter.decode(reader, reader.uint32()));\n                    break;\n                case 14:\n                    message.a014 = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Model.prototype.name = \"\";\ndnn.Model.prototype.version = 0;\ndnn.Model.prototype.a014 = 0;\n\ndnn.Parameter = class Parameter {\n\n    static decode(reader, length) {\n        const message = new dnn.Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.shape = dnn.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Parameter.prototype.name = \"\";\ndnn.Parameter.prototype.shape = null;\n\ndnn.Shape = class Shape {\n\n    static decode(reader, length) {\n        const message = new dnn.Shape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim0 = reader.int32();\n                    break;\n                case 2:\n                    message.dim1 = reader.int32();\n                    break;\n                case 3:\n                    message.dim2 = reader.int32();\n                    break;\n                case 4:\n                    message.dim3 = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Shape.prototype.dim0 = 0;\ndnn.Shape.prototype.dim1 = 0;\ndnn.Shape.prototype.dim2 = 0;\ndnn.Shape.prototype.dim3 = 0;\n\ndnn.Node = class Node {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n    }\n\n    static decode(reader, length) {\n        const message = new dnn.Node();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.layer = dnn.Layer.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.input.push(reader.string());\n                    break;\n                case 3:\n                    message.output.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Node.prototype.layer = null;\n\ndnn.Layer = class Layer {\n\n    constructor() {\n        this.weight = [];\n    }\n\n    static decode(reader, length) {\n        const message = new dnn.Layer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.filters = reader.int32();\n                    break;\n                case 7:\n                    message.a007 = reader.int32();\n                    break;\n                case 8:\n                    message.a008 = reader.int32();\n                    break;\n                case 9:\n                    message.groups = reader.int32();\n                    break;\n                case 10:\n                    message.a010 = reader.int32();\n                    break;\n                case 11:\n                    message.a011 = reader.int32();\n                    break;\n                case 14:\n                    message.slope = reader.float();\n                    break;\n                case 15:\n                    message.intercept = reader.float();\n                    break;\n                case 50:\n                    message.weight.push(dnn.Tensor.decode(reader, reader.uint32()));\n                    break;\n                case 72:\n                    message.operation = reader.int32();\n                    break;\n                case 65:\n                    message.axis = reader.int32();\n                    break;\n                case 77:\n                    message.a077 = reader.int32();\n                    break;\n                case 79:\n                    message.scale = reader.float();\n                    break;\n                case 80:\n                    message.pad_1 = reader.int32();\n                    break;\n                case 81:\n                    message.pad_2 = reader.int32();\n                    break;\n                case 82:\n                    message.pad_3 = reader.int32();\n                    break;\n                case 83:\n                    message.pad_4 = reader.int32();\n                    break;\n                case 84:\n                    message.pad_5 = reader.int32();\n                    break;\n                case 85:\n                    message.a085 = reader.int32();\n                    break;\n                case 90:\n                    message.a090 = reader.int32();\n                    break;\n                case 101:\n                    message.is_quantized = reader.bool();\n                    break;\n                case 104:\n                    message.quantization = dnn.Buffer.decode(reader, reader.uint32());\n                    break;\n                case 109:\n                    message.stride_w = reader.int32();\n                    break;\n                case 110:\n                    message.stride_h = reader.int32();\n                    break;\n                case 111:\n                    message.kernel_w = reader.int32();\n                    break;\n                case 112:\n                    message.kernel_h = reader.int32();\n                    break;\n                case 115:\n                    message.a115 = reader.int32();\n                    break;\n                case 116:\n                    message.a116 = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Layer.prototype.name = \"\";\ndnn.Layer.prototype.type = \"\";\ndnn.Layer.prototype.filters = 0;\ndnn.Layer.prototype.a007 = 0;\ndnn.Layer.prototype.a008 = 0;\ndnn.Layer.prototype.groups = 0;\ndnn.Layer.prototype.a010 = 0;\ndnn.Layer.prototype.a011 = 0;\ndnn.Layer.prototype.slope = 0;\ndnn.Layer.prototype.intercept = 0;\ndnn.Layer.prototype.operation = 0;\ndnn.Layer.prototype.axis = 0;\ndnn.Layer.prototype.a077 = 0;\ndnn.Layer.prototype.scale = 0;\ndnn.Layer.prototype.pad_1 = 0;\ndnn.Layer.prototype.pad_2 = 0;\ndnn.Layer.prototype.pad_3 = 0;\ndnn.Layer.prototype.pad_4 = 0;\ndnn.Layer.prototype.pad_5 = 0;\ndnn.Layer.prototype.a085 = 0;\ndnn.Layer.prototype.a090 = 0;\ndnn.Layer.prototype.is_quantized = false;\ndnn.Layer.prototype.quantization = null;\ndnn.Layer.prototype.stride_w = 0;\ndnn.Layer.prototype.stride_h = 0;\ndnn.Layer.prototype.kernel_w = 0;\ndnn.Layer.prototype.kernel_h = 0;\ndnn.Layer.prototype.a115 = 0;\ndnn.Layer.prototype.a116 = 0;\n\ndnn.Buffer = class Buffer {\n\n    static decode(reader, length) {\n        const message = new dnn.Buffer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 5:\n                    message.data = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Buffer.prototype.data = new Uint8Array([]);\n\ndnn.Tensor = class Tensor {\n\n    static decode(reader, length) {\n        const message = new dnn.Tensor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim0 = reader.int32();\n                    break;\n                case 2:\n                    message.dim1 = reader.int32();\n                    break;\n                case 3:\n                    message.dim2 = reader.int32();\n                    break;\n                case 4:\n                    message.dim3 = reader.int32();\n                    break;\n                case 5:\n                    message.data = reader.bytes();\n                    break;\n                case 6:\n                    message.quantized_data = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\ndnn.Tensor.prototype.dim0 = 0;\ndnn.Tensor.prototype.dim1 = 0;\ndnn.Tensor.prototype.dim2 = 0;\ndnn.Tensor.prototype.dim3 = 0;\ndnn.Tensor.prototype.data = new Uint8Array([]);\ndnn.Tensor.prototype.quantized_data = new Uint8Array([]);\n"
  },
  {
    "path": "source/dnn.js",
    "content": "\n// Experimental\n\nconst dnn = {};\n\ndnn.ModelFactory = class {\n\n    async match(context) {\n        const tags = await context.tags('pb');\n        if (tags.get(4) === 0 && tags.get(10) === 2) {\n            return context.set('dnn');\n        }\n        return null;\n    }\n\n    async open(context) {\n        dnn.proto = await context.require('./dnn-proto');\n        dnn.proto = dnn.proto.dnn;\n        let model = null;\n        try {\n            const reader = await context.read('protobuf.binary');\n            model = dnn.proto.Model.decode(reader);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new dnn.Error(`File format is not dnn.Graph (${message.replace(/\\.$/, '')}).`);\n        }\n        const metadata = await context.metadata('dnn-metadata.json');\n        return new dnn.Model(metadata, model);\n    }\n};\n\ndnn.Model = class {\n\n    constructor(metadata, model) {\n        this.name = model.name || '';\n        this.format = `SnapML${model.version ? ` v${model.version}` : ''}`;\n        this.modules = [new dnn.Graph(metadata, model)];\n    }\n};\n\ndnn.Graph = class {\n\n    constructor(metadata, model) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const scope = {};\n        for (let i = 0; i < model.node.length; i++) {\n            const node = model.node[i];\n            node.input = node.input.map((input) => scope[input] ? scope[input] : input);\n            node.output = node.output.map((output) => {\n                scope[output] = scope[output] ? `${output}\\n${i}` : output; // custom argument id\n                return scope[output];\n            });\n        }\n        const values = new Map();\n        values.map = (name, type) => {\n            if (!values.has(name)) {\n                values.set(name, new dnn.Value(name, type));\n            }\n            return values.get(name);\n        };\n        for (const input of model.input) {\n            const shape = input.shape;\n            const type = new dnn.TensorType('float32', new dnn.TensorShape([shape.dim0, shape.dim1, shape.dim2, shape.dim3]));\n            const argument = new dnn.Argument(input.name, [values.map(input.name, type)]);\n            this.inputs.push(argument);\n        }\n        for (const output of model.output) {\n            const shape = output.shape;\n            const type = new dnn.TensorType('float32', new dnn.TensorShape([shape.dim0, shape.dim1, shape.dim2, shape.dim3]));\n            const argument = new dnn.Argument(output.name, [values.map(output.name, type)]);\n            this.outputs.push(argument);\n        }\n        if (this.inputs.length === 0 && model.input_name && model.input_shape && model.input_shape.length === model.input_name.length * 4) {\n            for (let i = 0; i < model.input_name.length; i++) {\n                const name = model.input_name[i];\n                const shape = model.input_shape.slice(i * 4, (i * 4 + 4));\n                const type = new dnn.TensorType('float32', new dnn.TensorShape([shape[1], shape[3], shape[2], shape[0]]));\n                const argument = new dnn.Argument(name, [values.map(name, type)]);\n                this.inputs.push(argument);\n            }\n        }\n        if (this.inputs.length === 0 &&  model.input_shape && model.input_shape.length === 4 && model.node.length > 0 && model.node[0].input.length > 0) {\n            const [name] = model.node[0].input;\n            const shape = model.input_shape;\n            const type = new dnn.TensorType('float32', new dnn.TensorShape([shape[1], shape[3], shape[2], shape[0]]));\n            const argument = new dnn.Argument(name, [values.map(name, type)]);\n            this.inputs.push(argument);\n        }\n\n        for (const node of model.node) {\n            this.nodes.push(new dnn.Node(metadata, node, values));\n        }\n    }\n};\n\ndnn.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\ndnn.Value = class {\n\n    constructor(name, type = null, initializer = null, quantization = null) {\n        if (typeof name !== 'string') {\n            throw new dnn.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = type;\n        this.initializer = initializer;\n        if (quantization) {\n            this.quantization = {\n                type: 'lookup',\n                value: new Map(quantization.map((value, index) => [index, value]))\n            };\n        }\n    }\n};\n\ndnn.Node = class {\n\n    constructor(metadata, node, values) {\n        const layer = node.layer;\n        this.name = layer.name;\n        const type = layer.type;\n        this.type = metadata.type(type) || { name: type };\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const inputs = node.input.map((input) => values.map(input));\n        for (const weight of layer.weight) {\n            let quantization = null;\n            if (layer.is_quantized && weight === layer.weight[0] && layer.quantization && layer.quantization.data) {\n                const data = layer.quantization.data;\n                quantization = new Array(data.length >> 2);\n                const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                for (let i = 0; i < quantization.length; i++) {\n                    quantization[i] = view.getFloat32(i << 2, true);\n                }\n            }\n            const initializer = new dnn.Tensor(weight, quantization);\n            inputs.push(new dnn.Value('', initializer.type, initializer, quantization));\n        }\n        const outputs = node.output.map((output) => values.map(output));\n        if (inputs && inputs.length > 0) {\n            let inputIndex = 0;\n            if (this.type && this.type.inputs) {\n                for (const inputSchema of this.type.inputs) {\n                    if (inputIndex < inputs.length || inputSchema.option !== 'optional') {\n                        const inputCount = (inputSchema.option === 'variadic') ? (node.input.length - inputIndex) : 1;\n                        const inputArguments = inputs.slice(inputIndex, inputIndex + inputCount);\n                        this.inputs.push(new dnn.Argument(inputSchema.name, inputArguments));\n                        inputIndex += inputCount;\n                    }\n                }\n            }\n            this.inputs.push(...inputs.slice(inputIndex).map((input, index) => {\n                const inputName = ((inputIndex + index) === 0) ? 'input' : (inputIndex + index).toString();\n                return new dnn.Argument(inputName, [input]);\n            }));\n        }\n        if (outputs.length > 0) {\n            this.outputs = outputs.map((output, index) => {\n                const inputName = (index === 0) ? 'output' : index.toString();\n                return new dnn.Argument(inputName, [output]);\n            });\n        }\n        for (const [key, obj] of Object.entries(layer)) {\n            switch (key) {\n                case 'name':\n                case 'type':\n                case 'weight':\n                case 'is_quantized':\n                case 'quantization':\n                    break;\n                default: {\n                    const attribute = new dnn.Argument(key, obj);\n                    this.attributes.push(attribute);\n                    break;\n                }\n            }\n        }\n    }\n};\n\ndnn.Tensor = class {\n\n    constructor(weight, quantization) {\n        const shape = new dnn.TensorShape([weight.dim0, weight.dim1, weight.dim2, weight.dim3]);\n        this.values = quantization ? weight.quantized_data : weight.data;\n        const size = shape.dimensions.reduce((a, b) => a * b, 1);\n        const itemsize = Math.floor(this.values.length / size);\n        const remainder = this.values.length - (itemsize * size);\n        if (remainder < 0 || remainder > itemsize) {\n            throw new dnn.Error(`Invalid tensor data size '${this.values.length}' tensor shape '[${shape.dimensions}]' '.`);\n        }\n        let dataType = '?';\n        switch (itemsize) {\n            case 1: dataType = 'int8'; break;\n            case 2: dataType = 'float16'; break;\n            case 4: dataType = 'float32'; break;\n            default: dataType = '?'; break;\n        }\n        this.type = new dnn.TensorType(dataType, shape);\n    }\n};\n\ndnn.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ndnn.TensorShape = class {\n\n    constructor(shape) {\n        this.dimensions = shape;\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.join(',')}]`;\n    }\n};\n\ndnn.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading SnapML model.';\n    }\n};\n\nexport const ModelFactory = dnn.ModelFactory;\n\n"
  },
  {
    "path": "source/dot.js",
    "content": "\nconst dot = {};\n\ndot.ModelFactory = class {\n\n    async match(context) {\n        const reader = await context.read('text', 0x10000);\n        if (reader) {\n            try {\n                for (let i = 0; i < 64; i++) {\n                    const line = reader.read('\\n');\n                    if (line === undefined) {\n                        break;\n                    }\n                    if (line.trim().startsWith('//') || line.trim().startsWith('#')) {\n                        continue;\n                    }\n                    if (line.trim().match(/^(strict)?\\s*digraph/)) {\n                        return context.set('dot');\n                    }\n                }\n            } catch {\n                // continue regardless of error\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        const decoder = await context.read('text.decoder');\n        const parser = new dot.Parser(decoder);\n        const graph = parser.parse();\n        if (graph.kind !== 'digraph') {\n            throw new dot.Error(`Graph type '${graph.type}' is not supported.`);\n        }\n        return new dot.Model(graph);\n    }\n};\n\ndot.Model = class {\n\n    constructor(graph) {\n        this.format = 'DOT';\n        this.modules = [new dot.Graph(graph)];\n    }\n};\n\ndot.Graph = class {\n\n    constructor(graph) {\n        this.name = graph.name || '';\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const values = new Map();\n        values.map = (name, type, tensor, metadata) => {\n            if (typeof name !== 'string') {\n                throw new dot.Error('Invalid value name.');\n            }\n            if (!values.has(name) || tensor) {\n                values.set(name, new dot.Value(name, type, tensor, metadata));\n            }\n            return values.get(name);\n        };\n        const nodes = new Map();\n        nodes.map = (name) => {\n            if (typeof name !== 'string') {\n                throw new dot.Error('Invalid node name.');\n            }\n            if (!nodes.has(name)) {\n                const node = {\n                    kind: 'node',\n                    name: { id: name, key: name },\n                    type: { name },\n                    inputs: [],\n                    outputs: [],\n                    attributes: new Map(),\n                    metadata: new Map()\n                };\n                nodes.set(name, node);\n            }\n            return nodes.get(name);\n        };\n        for (const node of graph.statements) {\n            if (node.kind === 'node') {\n                node.inputs = [];\n                node.outputs = [];\n                node.metadata = new Map([...node.defaults, ...node.attributes]);\n                node.attributes = new Map();\n                delete node.defaults;\n                const metadata = node.metadata;\n                if (metadata.has('label')) {\n                    const label = metadata.get('label');\n                    if (label.startsWith('{') && label.endsWith('}')) {\n                        const lines = label.substring(1, label.length - 1).split('|');\n                        if (lines.length > 1 && node.name.id === lines[0] && lines[1].startsWith('op_code=')) {\n                            const def = lines[1].split('\\\\l');\n                            const op_code = def[0].split('=').pop();\n                            node.type = { name: op_code };\n                            if (op_code === 'call_module') {\n                                node.type = { name: def[1], type: 'function' };\n                            } else if (op_code === 'call_function') {\n                                const vals = lines[2].split('\\\\l');\n                                node.type = { name: vals[0] };\n                            } else if (op_code.startsWith('get_parameter')) {\n                                node.attributes.set('type', op_code.substring(13, op_code.length).trim());\n                                node.type = { name: 'get_parameter' };\n                            }\n                            if (lines.length > 2) {\n                                const attributes = lines[2].split('\\\\l');\n                                for (const attribute of attributes) {\n                                    const parts = attribute.split(':');\n                                    if (parts.length === 2) {\n                                        const key = parts[0].trim();\n                                        let value = parts[1].trim();\n                                        if (value.startsWith('(') && value.endsWith(')')) {\n                                            value = JSON.parse(`[${value.substring(1, value.length - 1)}]`);\n                                        }\n                                        node.attributes.set(key, value);\n                                    }\n                                }\n                            }\n                            metadata.delete('label');\n                        } else if (lines.length === 1 && lines[0].startsWith('buffer\\\\l')) {\n                            const def = lines[0].split('\\\\l');\n                            node.type = { name: def[0] };\n                            if (def.length > 1) {\n                                node.attributes.set('type', def[1]);\n                            }\n                            metadata.delete('label');\n                        }\n                    } else {\n                        const match = label.match(/^name:\\s*([A-Za-z][A-Za-z0-9_]*)\\stype:\\s*([A-Za-z][A-Za-z0-9_]*)$/);\n                        if (match && node.name.id === match[1]) {\n                            node.type = { name: match[2] };\n                            metadata.delete('label');\n                        }\n                    }\n                }\n                if (!node.type) {\n                    const lines = node.name.id.split('\\\\n');\n                    const match = lines[0].match(/^([A-Z][A-Za-z0-9_]*)\\/([A-Z][A-Za-z0-9_]*)\\s\\(op#(\\d+)\\)$/);\n                    if (match) {\n                        node.type = { name: match[2] };\n                    } else {\n                        const match = lines[0].match(/^([A-Z][A-Za-z0-9_]*)\\s\\(op#(\\d+)\\)$/);\n                        if (match) {\n                            node.type = { name: match[1] };\n                        } else {\n                            // debugger;\n                        }\n                    }\n\n                }\n                if (!node.type) {\n                    node.type = { name: node.name.id };\n                }\n                nodes.set(node.name.id, node);\n            }\n        }\n        for (const edge of graph.statements) {\n            if (edge.kind === 'edge') {\n                edge.uses = edge.uses || [];\n                const to = nodes.map(edge.to.id);\n                to.inputs.push(edge);\n                edge.uses.push(to);\n                edge.from = nodes.map(edge.name.id);\n                edge.from.outputs.push(edge);\n            }\n        }\n        for (const [key, node] of nodes) {\n            const keys = new Set(['pos', 'height', 'width', 'shape', 'label']);\n            if (node.metadata.get('shape') === 'octagon' && node.metadata.keys().every((key) => keys.has(key)) &&\n                node.inputs.length === 1 && node.inputs[0].uses.length === 1 && node.inputs[0].from.outputs.length === 1 && node.inputs[0].from.outputs[0].uses.length === 1 &&\n                new Set(node.outputs.map((output) => output.name.id)).size === 1 && node.outputs.every((output) => output.uses.length === 1)) {\n                const [from] = node.inputs[0].from.outputs;\n                for (const e of node.outputs) {\n                    const [n] = e.uses;\n                    n.inputs = n.inputs.map((edge) => edge === e ? from : edge);\n                }\n                nodes.delete(key);\n            }\n        }\n        for (const [key, node] of nodes) {\n            if ((node.type.name === 'get_parameter' || node.type.name === 'buffer' || node.type.name === 'Constant') &&\n                node.inputs.length === 0 &&\n                node.outputs.length === 1 && node.outputs[0].uses.length === 1) {\n                node.outputs[0].initializer = node;\n                nodes.delete(key);\n            }\n        }\n        for (const [, obj] of nodes) {\n            const node = new dot.Node(obj, values);\n            this.nodes.push(node);\n        }\n        for (const edge of graph.statements) {\n            if (edge.kind === 'edge') {\n                const value = values.map(edge.name.id);\n                const metadata = new Map([...edge.defaults, ...edge.attributes]);\n                value.metadata = Array.from(metadata).map(([key, value]) => new dot.Argument(key, value));\n            }\n        }\n    }\n};\n\ndot.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\ndot.Value = class {\n\n    constructor(name, type, initializer, metadata) {\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer || null;\n        this.metadata = metadata;\n    }\n};\n\ndot.Node = class {\n\n    constructor(node, values) {\n        this.name = node.name.key;\n        this.type = node.type;\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        this.metadata = [];\n        for (let i = 0; i < node.inputs.length; i++) {\n            const edge = node.inputs[i];\n            const initializer = edge.initializer ? new dot.Tensor(edge.initializer) : null;\n            const value = values.map(edge.name.key, null, initializer);\n            const argument = new dot.Argument(i.toString(), [value]);\n            this.inputs.push(argument);\n        }\n        for (let i = 0; i < node.outputs.length; i++) {\n            const edge = node.outputs[i];\n            const value = values.map(edge.name.key);\n            const argument = new dot.Argument(i.toString(), [value]);\n            this.outputs.push(argument);\n        }\n        for (const [name, value] of node.attributes) {\n            const argument = new dot.Argument(name, value, 'attribute');\n            this.attributes.push(argument);\n        }\n        for (const [name, value] of node.metadata) {\n            const argument = new dot.Argument(name, value);\n            this.metadata.push(argument);\n        }\n    }\n};\n\ndot.TensorType = class {\n\n    constructor(type) {\n        const index = type.indexOf('[');\n        const dtype = type.substring(0, index);\n        this.dataType = dtype.split('.').pop();\n        if (index > 0) {\n            const dimensions = JSON.parse(type.substring(index, type.length));\n            this.shape = new dot.TensorShape(dimensions);\n        } else {\n            this.shape = new dot.TensorShape([]);\n        }\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\ndot.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\ndot.Tensor = class {\n\n    constructor(stmt) {\n        if (stmt.attributes.has('type')) {\n            const type = stmt.attributes.get('type');\n            this.type = new dot.TensorType(type);\n        } else {\n            this.type = new dot.TensorType('?');\n        }\n    }\n};\n\ndot.Parser = class {\n\n    constructor(decoder) {\n        // https://graphviz.org/doc/info/lang.html\n        this._tokenizer = new dot.Tokenizer(decoder);\n        this._token = this._tokenizer.read();\n    }\n\n    parse() {\n        const graph = {};\n        if (this._eat('id', 'strict')) {\n            graph.strict = true;\n        }\n        let edgeop = '';\n        if (this._match('id', 'graph')) {\n            graph.kind = this._read();\n            edgeop = '--';\n        } else if (this._match('id', 'digraph')) {\n            graph.kind = this._read();\n            edgeop = '->';\n        } else {\n            throw new dot.Error('Invalid graph type.');\n        }\n        if (this._match('id')) {\n            graph.name = this._read();\n        }\n        const defaults = {};\n        defaults.graph = new Map();\n        defaults.node = new Map();\n        defaults.edge = new Map();\n        graph.statements = this._parseBlock(defaults, edgeop, 0);\n        graph.defaults = new Map(defaults.graph);\n        return graph;\n    }\n\n    _parseBlock(defaults, edgeop) {\n        defaults = {\n            graph: new Map(defaults.graph),\n            node: new Map(defaults.node),\n            edge: new Map(defaults.edge)\n        };\n        const list = [];\n        this._read('{');\n        while (!this._match('}')) {\n            if (this._eat('id', 'subgraph')) {\n                const stmt = {};\n                stmt.kind = 'subgraph';\n                if (this._match('id')) {\n                    stmt.name = this._read();\n                }\n                stmt.statements = this._parseBlock(defaults, edgeop);\n            } else if (this._match('{')) {\n                const stmt = {};\n                const statements = this._parseBlock(defaults, edgeop);\n                if (this._eat(edgeop)) {\n                    if (!statements.every((stmt) => stmt.kind === 'node' && stmt.attributes.size === 0)) {\n                        throw new dot.Error('Invalid edge group statement.');\n                    }\n                    const sources = statements.map((stmt) => stmt.name);\n                    list.push(...this._parseEdges(sources, edgeop, defaults.edge));\n                } else {\n                    stmt.kind = 'subgraph';\n                    stmt.statements = statements;\n                }\n            } else if (this._match('id')) {\n                const name = this._parseNodeId();\n                if (this._eat('=')) { // attr\n                    if (this._match('id')) {\n                        const value = this._read();\n                        defaults.graph.set(name, value);\n                    } else {\n                        throw new dot.Error('Invalid attribute value.');\n                    }\n                } else if (this._eat(edgeop)) {\n                    list.push(...this._parseEdges([name], edgeop, defaults.edge));\n                } else {\n                    const attributes = this._parseAttributes();\n                    if (name.key === 'node' || name.key === 'edge' || name.key === 'graph') {\n                        for (const [key, value] of attributes) {\n                            defaults[name.key].set(key, value);\n                        }\n                    } else {\n                        list.push({ kind: 'node', name, attributes, defaults: new Map(defaults.node) });\n                    }\n                }\n            }\n            if (this._match(';') || this._match(',')) {\n                this._read();\n            }\n        }\n        this._read('}');\n        return list;\n    }\n\n    _parseNodeIds() {\n        const list = [];\n        const open = this._eat('{');\n        while (!this._match('}')) {\n            const value = this._parseNodeId();\n            list.push(value);\n            if (this._match(',')) {\n                this._read();\n                continue;\n            } else if (this._match(';')) {\n                this._read();\n                if (!open) {\n                    break;\n                }\n            } else if (!open) {\n                break;\n            }\n        }\n        if (open) {\n            this._read('}');\n        }\n        return list;\n    }\n\n    _parseNodeId() {\n        const name = {};\n        const list = [];\n        name.id = this._read('id');\n        list.push(name.id);\n        if (this._eat(':')) {\n            name.port = this._read('id');\n            list.push(name.port);\n            if (this._eat(':')) {\n                name.compass_pt = this._read('id');\n                list.push(name.compass_pt);\n            }\n        }\n        name.key = list.join(':');\n        return name;\n    }\n\n    _parseAttributes() {\n        const table = new Map();\n        if (this._eat('[')) {\n            while (this._match('id')) {\n                const name = this._read('id');\n                this._read('=');\n                const value = this._read('id');\n                table.set(name, value);\n                if (this._match(';') || this._match(',')) {\n                    this._read();\n                }\n            }\n            this._read(']');\n        }\n        return table;\n    }\n\n    _parseEdges(sources, edgeop, defaults) {\n        const list = [];\n        do {\n            const targets = this._parseNodeIds();\n            for (const name of sources) {\n                for (const to of targets) {\n                    list.push({ kind: 'edge', name, to });\n                }\n            }\n            sources = targets;\n        } while (this._eat(edgeop));\n        const attributes = this._parseAttributes();\n        for (const edge of list) {\n            edge.attributes = attributes;\n            edge.defaults = new Map(defaults.edge);\n        }\n        return list;\n    }\n\n    _match(kind, value) {\n        return (this._token.kind === kind && (!value || this._token.value === value));\n    }\n\n    _read(kind, value) {\n        if (kind && this._token.kind !== kind) {\n            throw new dot.Error(`Expected token of type '${kind}', but got '${this._token.kind}' ${this._tokenizer.location()}`);\n        }\n        if (value && this._token.value !== value) {\n            throw new dot.Error(`Expected token with value '${value}', but got '${this._token.value}' ${this._tokenizer.location()}`);\n        }\n        const token = this._token;\n        this._token = this._tokenizer.read();\n        return token.value;\n    }\n\n    _eat(kind, value) {\n        if (this._match(kind, value)) {\n            return this._read();\n        }\n        return null;\n    }\n};\n\ndot.Tokenizer = class {\n\n    constructor(decoder) {\n        this._decoder = decoder;\n        this._position = 0;\n        this._char = this._decoder.decode();\n    }\n\n    _read() {\n        if (this._char === undefined) {\n            this._unexpected();\n        }\n        const char = this._char;\n        this._position = this._decoder.position;\n        this._char = this._decoder.decode();\n        return char;\n    }\n\n    _peek() {\n        const position = this._decoder.position;\n        const char = this._decoder.decode();\n        this._decoder.position = position;\n        return char;\n    }\n\n    read() {\n        while (this._char) {\n            if (/\\s/.test(this._char)) {\n                this._skipWhitespace();\n                continue;\n            }\n            if (this._char === '/' || this._char === '#') {\n                this._skipComment();\n                continue;\n            }\n            if (/[{}[\\]=:;,]/.test(this._char)) {\n                const value = this._read();\n                return { kind: value, value };\n            } else if (this._char === '-') {\n                let value = this._read();\n                if (this._char === '>' || this._char === '-') {\n                    value += this._read();\n                    return { kind: value, value };\n                }\n                throw new dot.Error(`Unexpected character '${value}' ${this.location()}`);\n            } else if (/[a-zA-Z0-9_$\"<]/.test(this._char)) {\n                const value = this._identifier();\n                return { kind: 'id', value };\n            } else {\n                throw new dot.Error(`Unexpected character '${this._char}' ${this.location()}`);\n            }\n        }\n        return { type: 'eof' };\n    }\n\n    _skipWhitespace() {\n        while (this._char !== undefined && /\\s/.test(this._char)) {\n            this._read();\n        }\n    }\n\n    _skipComment() {\n        if (this._char === '#' || (this._char === '/' && this._peek() === '/')) {\n            while (this._char && this._char !== '\\n') {\n                this._read();\n            }\n            return;\n        }\n        if (this._char === '/' && this._peek() === '*') {\n            while (this._char && (this._char !== '*' || this._peek() !== '/')) {\n                this._read();\n            }\n            this._read();\n            this._read();\n            return;\n        }\n        throw new dot.Error('Invalid comment.');\n    }\n\n    _identifier() {\n        let value = '';\n        if (this._char === '\"') { // double quoted string\n            this._read();\n            while (this._char && this._char !== '\"') {\n                value += this._read();\n            }\n            this._read('\"');\n        } if (this._char === '<') { // HTML String\n            value += this._read();\n            let depth = 0;\n            while (depth > 0 || this._char !== '>') {\n                const c = this._read();\n                value += c;\n                if (c === '<') {\n                    depth += 1;\n                } else if (c === '>') {\n                    depth -= 1;\n                }\n            }\n            value += this._read();\n        } else {\n            while (/[a-zA-Z0-9_$.*]/.test(this._char)) {\n                value += this._read();\n            }\n        }\n        return value;\n    }\n\n    _unexpected() {\n        let c = this._char;\n        if (c === undefined) {\n            throw new dot.Error('Unexpected end of input.');\n        } else if (c === '\"') {\n            c = 'string';\n        } else if ((c >= '0' && c <= '9') || c === '-') {\n            c = 'number';\n        } else {\n            if (c < ' ' || c > '\\x7F') {\n                const name = Object.keys(this._escape).filter((key) => this._escape[key] === c);\n                c = (name.length === 1) ? `\\\\${name}` : `\\\\u${(`000${c.charCodeAt(0).toString(16)}`).slice(-4)}`;\n            }\n            c = `token '${c}'`;\n        }\n        this._throw(`Unexpected ${c}`);\n    }\n\n    _throw(message) {\n        message = message.replace(/\\.$/, '');\n        throw new dot.Error(`${message} ${this._location()}`);\n    }\n\n    location() {\n        let line = 1;\n        let column = 1;\n        const position = this._decoder.position;\n        this._decoder.position = 0;\n        let c = '';\n        do {\n            if (this._decoder.position === this._position) {\n                this._decoder.position = position;\n                return `at ${line}:${column}.`;\n            }\n            c = this._decoder.decode();\n            if (c === '\\n') {\n                line++;\n                column = 1;\n            } else {\n                column++;\n            }\n        }\n        while (c !== undefined);\n        this._decoder.position = position;\n        return `at ${line}:${column}.`;\n    }\n};\n\ndot.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loadig DOT graph';\n    }\n};\n\nexport const ModelFactory = dot.ModelFactory;\n"
  },
  {
    "path": "source/espdl-metadata.json",
    "content": "[\n  {\n    \"name\": \"Add\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Element-wise addition of two tensors.\",\n    \"inputs\": [\n      { \"name\": \"A\", \"description\": \"First input tensor\" },\n      { \"name\": \"B\", \"description\": \"Second input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"AveragePool\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Average pooling operation.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"BatchNormalization\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Batch normalization.\",\n    \"inputs\": [\n      { \"name\": \"X\", \"description\": \"Input data tensor\" },\n      { \"name\": \"scale\", \"description\": \"Scale tensor\" },\n      { \"name\": \"B\", \"description\": \"Bias tensor\" },\n      { \"name\": \"mean\", \"description\": \"Mean tensor\" },\n      { \"name\": \"var\", \"description\": \"Variance tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"Y\", \"description\": \"Output data tensor\" },\n      { \"name\": \"mean\", \"description\": \"Updated mean tensor (optional)\" },\n      { \"name\": \"var\", \"description\": \"Updated variance tensor (optional)\" },\n      { \"name\": \"saved_mean\", \"description\": \"Saved mean tensor (optional)\" },\n      { \"name\": \"saved_var\", \"description\": \"Saved variance tensor (optional)\" }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"Clip\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Activation\",\n    \"description\": \"Clip operator limits values to a specified range.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Clipped output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Concatenates tensors along a given axis.\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"list\": true, \"description\": \"Input tensors to concatenate\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Concatenated output tensor\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Conv\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Convolution operator. Applies a convolution filter to the input.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input feature map\" },\n      { \"name\": \"weight\", \"description\": \"Convolution kernel weights\" },\n      { \"name\": \"bias\", \"option\": \"optional\", \"description\": \"Bias values (optional)\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output feature map\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Gemm\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"General matrix multiplication: alpha * A * B + beta * C\",\n    \"inputs\": [\n      { \"name\": \"A\", \"description\": \"Input tensor A\" },\n      { \"name\": \"B\", \"description\": \"Input tensor B\" },\n      { \"name\": \"C\", \"option\": \"optional\", \"description\": \"Input tensor C (optional)\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"Y\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"GlobalAveragePool\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Global average pooling operation for temporal data.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"HardSwish\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Activation\",\n    \"description\": \"Hard swish activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"LeakyRelu\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Activation\",\n    \"description\": \"Leaky Rectified Linear Unit activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"MaxPool\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Max pooling operation.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Mul\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Element-wise multiplication of two tensors.\",\n    \"inputs\": [\n      { \"name\": \"A\", \"description\": \"First input tensor\" },\n      { \"name\": \"B\", \"description\": \"Second input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Pad\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Tensor\",\n    \"description\": \"Pad operator adds padding to tensor dimensions.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" },\n      { \"name\": \"pads\", \"description\": \"Padding values\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Padded output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Relu\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Rectified Linear Unit activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"RequantizeLinear\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Quantization\",\n    \"description\": \"Requantize linear quantization operator.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor to requantize\" },\n      { \"name\": \"scale\", \"description\": \"Scale for requantization\" },\n      { \"name\": \"zero_point\", \"description\": \"Zero point for requantization\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Requantized output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Reshapes a tensor to a new shape.\",\n    \"inputs\": [\n      { \"name\": \"data\", \"description\": \"Input tensor\" },\n      { \"name\": \"shape\", \"description\": \"New shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"reshaped\", \"description\": \"Reshaped output tensor\" }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Resize\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Data\",\n    \"description\": \"Resize operator for spatial dimensions.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" },\n      { \"name\": \"scales\", \"description\": \"Scale factors for each dimension\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Resized output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Sigmoid activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Softmax\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Softmax activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Split\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Splits a tensor into multiple tensors along a given axis.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor to split\" },\n      { \"name\": \"split\", \"description\": \"Optional list of split sizes or number of splits\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"outputs\", \"list\": true, \"description\": \"Output tensors\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Swish\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"category\": \"Activation\",\n    \"description\": \"Swish activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Tanh\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Hyperbolic tangent activation function.\",\n    \"inputs\": [\n      { \"name\": \"input\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"description\": \"Output tensor\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Transpose\",\n    \"module\": \"espdl\",\n    \"version\": 1,\n    \"description\": \"Transposes the dimensions of a tensor.\",\n    \"inputs\": [\n      { \"name\": \"data\", \"description\": \"Input tensor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"transposed\", \"description\": \"Transposed output tensor\" }\n    ],\n    \"category\": \"Tensor\"\n  }\n]"
  },
  {
    "path": "source/espdl-schema.js",
    "content": "\nexport const espdl = {};\n\nespdl.Version = {\n    _START_VERSION: 0, '0': '_START_VERSION',\n    IR_VERSION_2023_12_22: 1, '1': 'IR_VERSION_2023_12_22'\n};\n\nespdl.AttributeType = {\n    UNDEFINED: 0, '0': 'UNDEFINED',\n    FLOAT: 1, '1': 'FLOAT',\n    INT: 2, '2': 'INT',\n    STRING: 3, '3': 'STRING',\n    TENSOR: 4, '4': 'TENSOR',\n    GRAPH: 5, '5': 'GRAPH',\n    FLOATS: 6, '6': 'FLOATS',\n    INTS: 7, '7': 'INTS',\n    STRINGS: 8, '8': 'STRINGS',\n    TENSORS: 9, '9': 'TENSORS',\n    GRAPHS: 10, '10': 'GRAPHS',\n    TYPE_FBS: 11, '11': 'TYPE_FBS',\n    TYPE_FBSS: 12, '12': 'TYPE_FBSS'\n};\n\nespdl.TensorDataType = {\n    UNDEFINED: 0, '0': 'UNDEFINED',\n    FLOAT: 1, '1': 'FLOAT',\n    UINT8: 2, '2': 'UINT8',\n    INT8: 3, '3': 'INT8',\n    UINT16: 4, '4': 'UINT16',\n    INT16: 5, '5': 'INT16',\n    INT32: 6, '6': 'INT32',\n    INT64: 7, '7': 'INT64',\n    STRING: 8, '8': 'STRING',\n    BOOL: 9, '9': 'BOOL',\n    FLOAT16: 10, '10': 'FLOAT16',\n    DOUBLE: 11, '11': 'DOUBLE',\n    UINT32: 12, '12': 'UINT32',\n    UINT64: 13, '13': 'UINT64'\n};\n\nespdl.DataLocation = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    EXTERNAL: 1, '1': 'EXTERNAL'\n};\n\nespdl.AttributeF = class AttributeF {\n\n    static decode(reader, position) {\n        const $ = new espdl.AttributeF();\n        $.f = reader.float32(position + 0);\n        return $;\n    }\n};\n\nespdl.AttributeI = class AttributeI {\n\n    static decode(reader, position) {\n        const $ = new espdl.AttributeI();\n        $.i = reader.int64(position + 0);\n        return $;\n    }\n};\n\nespdl.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new espdl.Attribute();\n        $.name = reader.string_(position, 4, null);\n        $.ref_attr_name = reader.string_(position, 6, null);\n        $.doc_string = reader.string_(position, 8, null);\n        $.attr_type = reader.int32_(position, 10, 0);\n        $.f = reader.struct(position, 12, espdl.AttributeF);\n        $.i = reader.struct(position, 14, espdl.AttributeI);\n        $.s = reader.array(position, 16, Uint8Array);\n        $.t = reader.table(position, 18, espdl.Tensor);\n        $.g = reader.table(position, 20, espdl.Graph);\n        $.tp = reader.table(position, 22, espdl.TypeInfo);\n        $.floats = reader.array(position, 24, Float32Array);\n        $.ints = reader.int64s_(position, 26);\n        $.strings = reader.strings_(position, 28);\n        $.tensors = reader.tables(position, 30, espdl.Tensor);\n        $.graphs = reader.tables(position, 32, espdl.Graph);\n        $.type_protos = reader.tables(position, 34, espdl.TypeInfo);\n        return $;\n    }\n};\n\nespdl.ValueInfo = class ValueInfo {\n\n    static decode(reader, position) {\n        const $ = new espdl.ValueInfo();\n        $.name = reader.string_(position, 4, null);\n        $.value_info_type = reader.table(position, 6, espdl.TypeInfo);\n        $.doc_string = reader.string_(position, 8, null);\n        $.exponents = reader.int64s_(position, 10);\n        return $;\n    }\n};\n\nespdl.Node = class Node {\n\n    static decode(reader, position) {\n        const $ = new espdl.Node();\n        $.input = reader.strings_(position, 4);\n        $.output = reader.strings_(position, 6);\n        $.name = reader.string_(position, 8, null);\n        $.op_type = reader.string_(position, 10, null);\n        $.domain = reader.string_(position, 12, null);\n        $.attribute = reader.tables(position, 14, espdl.Attribute);\n        $.doc_string = reader.string_(position, 16, null);\n        return $;\n    }\n};\n\nespdl.Model = class Model {\n\n    static create(reader) {\n        return espdl.Model.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new espdl.Model();\n        $.ir_version = reader.int32_(position, 4, 0);\n        $.opset_import = reader.tables(position, 6, espdl.OperatorSetId);\n        $.producer_name = reader.string_(position, 8, null);\n        $.producer_version = reader.string_(position, 10, null);\n        $.domain = reader.string_(position, 12, null);\n        $.model_version = reader.int64_(position, 14, 0n);\n        $.doc_string = reader.string_(position, 16, null);\n        $.graph = reader.table(position, 18, espdl.Graph);\n        $.metadata_props = reader.tables(position, 20, espdl.StringStringEntry);\n        $.functions = reader.tables(position, 22, espdl.Function);\n        return $;\n    }\n};\n\nespdl.StringStringEntry = class StringStringEntry {\n\n    static decode(reader, position) {\n        const $ = new espdl.StringStringEntry();\n        $.key = reader.string_(position, 4, null);\n        $.value = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nespdl.TensorAnnotation = class TensorAnnotation {\n\n    static decode(reader, position) {\n        const $ = new espdl.TensorAnnotation();\n        $.tensor_name = reader.string_(position, 4, null);\n        $.quant_parameter_tensor_names = reader.tables(position, 6, espdl.StringStringEntry);\n        return $;\n    }\n};\n\nespdl.Graph = class Graph {\n\n    static decode(reader, position) {\n        const $ = new espdl.Graph();\n        $.node = reader.tables(position, 4, espdl.Node);\n        $.name = reader.string_(position, 6, null);\n        $.initializer = reader.tables(position, 8, espdl.Tensor);\n        $.doc_string = reader.string_(position, 10, null);\n        $.input = reader.tables(position, 12, espdl.ValueInfo);\n        $.output = reader.tables(position, 14, espdl.ValueInfo);\n        $.value_info = reader.tables(position, 16, espdl.ValueInfo);\n        $.quantization_annotation = reader.tables(position, 18, espdl.TensorAnnotation);\n        $.test_inputs_value = reader.tables(position, 20, espdl.Tensor);\n        $.test_outputs_value = reader.tables(position, 22, espdl.Tensor);\n        return $;\n    }\n};\n\nespdl.AlignedBytes = class AlignedBytes {\n\n    static decode(reader, position) {\n        const $ = new espdl.AlignedBytes();\n        $.bytes = reader.read(position + 0, 16);\n        return $;\n    }\n};\n\nespdl.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new espdl.Tensor();\n        $.dims = reader.int64s_(position, 4);\n        $.data_type = reader.int32_(position, 6, 0);\n        $.float_data = reader.array(position, 8, Float32Array);\n        $.int32_data = reader.array(position, 10, Int32Array);\n        $.string_data = reader.strings_(position, 12);\n        $.int64_data = reader.int64s_(position, 14);\n        $.name = reader.string_(position, 16, null);\n        $.doc_string = reader.string_(position, 18, null);\n        $.raw_data = reader.structs(position, 20, espdl.AlignedBytes, 16);\n        $.external_data = reader.tables(position, 22, espdl.StringStringEntry);\n        $.data_location = reader.int32_(position, 24, 0);\n        $.double_data = reader.array(position, 26, Float64Array);\n        $.uint64_data = reader.uint64s_(position, 28);\n        $.exponents = reader.int64s_(position, 30);\n        return $;\n    }\n};\n\nespdl.TensorShape = class TensorShape {\n\n    static decode(reader, position) {\n        const $ = new espdl.TensorShape();\n        $.dim = reader.tables(position, 4, espdl.Dimension);\n        return $;\n    }\n};\n\nespdl.Dimension = class Dimension {\n\n    static decode(reader, position) {\n        const $ = new espdl.Dimension();\n        $.value = reader.table(position, 4, espdl.DimensionValue);\n        $.denotation = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nespdl.DimensionValueType = {\n    UNKNOWN: 0, '0': 'UNKNOWN',\n    VALUE: 1, '1': 'VALUE',\n    PARAM: 2, '2': 'PARAM'\n};\n\nespdl.DimensionValue = class DimensionValue {\n\n    static decode(reader, position) {\n        const $ = new espdl.DimensionValue();\n        $.dim_type = reader.int8_(position, 4, 0);\n        $.dim_value = reader.int64_(position, 6, 0n);\n        $.dim_param = reader.string_(position, 8, null);\n        return $;\n    }\n};\n\nespdl.TensorTypeAndShape = class TensorTypeAndShape {\n\n    static decode(reader, position) {\n        const $ = new espdl.TensorTypeAndShape();\n        $.elem_type = reader.int32_(position, 4, 0);\n        $.shape = reader.table(position, 6, espdl.TensorShape);\n        return $;\n    }\n};\n\nespdl.SequenceType = class SequenceType {\n\n    static decode(reader, position) {\n        const $ = new espdl.SequenceType();\n        $.elem_type = reader.table(position, 4, espdl.TypeInfo);\n        return $;\n    }\n};\n\nespdl.MapType = class MapType {\n\n    static decode(reader, position) {\n        const $ = new espdl.MapType();\n        $.key_type = reader.int32_(position, 4, 0);\n        $.value_type = reader.table(position, 6, espdl.TypeInfo);\n        return $;\n    }\n};\n\nespdl.OptionalType = class OptionalType {\n\n    static decode(reader, position) {\n        const $ = new espdl.OptionalType();\n        $.elem_type = reader.table(position, 4, espdl.TypeInfo);\n        return $;\n    }\n};\n\nespdl.TypeInfoValue = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return espdl.TensorTypeAndShape.decode(reader, position);\n            case 2: return espdl.SequenceType.decode(reader, position);\n            case 3: return espdl.MapType.decode(reader, position);\n            case 4: return espdl.OptionalType.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nespdl.TypeInfo = class TypeInfo {\n\n    static decode(reader, position) {\n        const $ = new espdl.TypeInfo();\n        $.value = reader.union(position, 4, espdl.TypeInfoValue);\n        $.denotation = reader.string_(position, 8, null);\n        return $;\n    }\n};\n\nespdl.OperatorSetId = class OperatorSetId {\n\n    static decode(reader, position) {\n        const $ = new espdl.OperatorSetId();\n        $.domain = reader.string_(position, 4, null);\n        $.version = reader.int64_(position, 6, 0n);\n        return $;\n    }\n};\n\nespdl.Function = class Function {\n\n    static decode(reader, position) {\n        const $ = new espdl.Function();\n        $.name = reader.string_(position, 4, null);\n        $.input = reader.strings_(position, 6);\n        $.output = reader.strings_(position, 8);\n        $.attribute = reader.strings_(position, 10);\n        $.attribute_proto = reader.tables(position, 12, espdl.Attribute);\n        $.node = reader.tables(position, 14, espdl.Node);\n        $.doc_string = reader.string_(position, 16, null);\n        $.opset_import = reader.tables(position, 18, espdl.OperatorSetId);\n        $.domain = reader.string_(position, 20, null);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/espdl.js",
    "content": "import * as flatbuffers from './flatbuffers.js';\n\nconst espdl = {};\n\nespdl.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        if (extension === 'espdl') {\n            const stream = context.stream;\n            if (stream && stream.length >= 16) {\n                const buffer = stream.peek(16);\n                const header = String.fromCharCode(...buffer.slice(0, 4));\n                if (header === 'EDL2') {\n                    return context.set('espdl.binary', null);\n                }\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        espdl.schema = await context.require('./espdl-schema');\n        espdl.schema = espdl.schema.espdl;\n        const stream = context.stream;\n        const reader = flatbuffers.BinaryReader.open(stream, 16);\n        let model = null;\n        try {\n            model = espdl.schema.Model.create(reader);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new espdl.Error(`File format is not espdl.Model (${message.replace(/\\.$/, '')}).`);\n        }\n        const metadata = await espdl.Metadata.open(context);\n        return new espdl.Model(metadata, model, stream);\n    }\n};\n\nespdl.Model = class {\n\n    constructor(metadata, model, stream) {\n        this.format = `ESP-DL v${model.ir_version}`;\n        this.description = model.doc_string || '';\n        this.modules = [];\n        this.metadata = [];\n        if (model.metadata_props) {\n            for (const prop of model.metadata_props) {\n                this.metadata.push(new espdl.Argument(prop.key, prop.value));\n            }\n        }\n        if (model.graph) {\n            const graph = new espdl.Graph(metadata, model.graph, model, stream);\n            this.modules.push(graph);\n        }\n    }\n};\n\nespdl.Graph = class {\n\n    constructor(metadata, graph) {\n        this.name = graph.name || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        this.signatures = [];\n        const context = new espdl.Context(graph);\n        if (graph.node) {\n            for (let i = 0; i < graph.node.length; i++) {\n                const node = graph.node[i];\n                const nodeObj = new espdl.Node(metadata, context, node, i.toString());\n                this.nodes.push(nodeObj);\n            }\n        }\n        if (graph.input) {\n            for (let i = 0; i < graph.input.length; i++) {\n                const valueInfo = graph.input[i];\n                const tensor = context.initializer(valueInfo.name);\n                if (!tensor) {\n                    const value = context.value(valueInfo.name);\n                    const values = value ? [value] : [];\n                    const argument = new espdl.Argument(valueInfo.name, values);\n                    this.inputs.push(argument);\n                }\n            }\n        }\n        if (graph.output) {\n            for (let i = 0; i < graph.output.length; i++) {\n                const valueInfo = graph.output[i];\n                const value = context.value(valueInfo.name);\n                const values = value ? [value] : [];\n                const argument = new espdl.Argument(valueInfo.name, values);\n                this.outputs.push(argument);\n            }\n        }\n    }\n};\n\nespdl.Argument = class {\n\n    constructor(name, value, type, visible) {\n        this.name = name;\n        this.value = value;\n        this.type = type || null;\n        this.visible = visible !== false;\n    }\n};\n\nespdl.Value = class {\n\n    constructor(name, type, initializer) {\n        this.name = name;\n        this.type = type || null;\n        this.initializer = initializer || null;\n    }\n};\n\nespdl.Node = class {\n\n    constructor(metadata, context, node, identifier) {\n        this.name = node.name || '';\n        this.identifier = identifier;\n        this.type = null;\n        if (metadata) {\n            this.type = metadata.type('espdl', node.op_type);\n        }\n        if (!this.type) {\n            this.type = { name: node.op_type };\n        }\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (node.input) {\n            for (let i = 0; i < node.input.length;) {\n                const inputMeta = this.type && Array.isArray(this.type.inputs) && i < this.type.inputs.length ? this.type.inputs[i] : { name: i.toString() };\n                const count = inputMeta.list ? node.input.length - i : 1;\n                const list = node.input.slice(i, i + count);\n                const values = list.map((inputName) => {\n                    if (!inputName) {\n                        return null;\n                    }\n                    return context.value(inputName);\n                }).filter((v) => v);\n                const argument = new espdl.Argument(inputMeta.name, values);\n                this.inputs.push(argument);\n                i += count;\n            }\n        }\n        if (node.output) {\n            for (let i = 0; i < node.output.length;) {\n                const outputMeta = this.type && Array.isArray(this.type.outputs) && i < this.type.outputs.length ? this.type.outputs[i] : { name: i.toString() };\n                const count = outputMeta.list ? node.output.length - i : 1;\n                const list = node.output.slice(i, i + count);\n                const values = list.map((outputName) => {\n                    if (!outputName) {\n                        return null;\n                    }\n                    return context.value(outputName);\n                }).filter((v) => v);\n                const argument = new espdl.Argument(outputMeta.name, values);\n                this.outputs.push(argument);\n                i += count;\n            }\n        }\n        if (node.attribute) {\n            for (const attr of node.attribute) {\n                const name = attr.name || '';\n                let value = null;\n                let type = null;\n                switch (attr.attr_type) {\n                    case espdl.schema.AttributeType.FLOAT:\n                        value = attr.f ? attr.f.f : 0;\n                        type = 'float32';\n                        break;\n                    case espdl.schema.AttributeType.INT:\n                        value = attr.i ? Number(attr.i.i) : 0;\n                        type = 'int64';\n                        break;\n                    case espdl.schema.AttributeType.STRING:\n                        value = attr.s ? new TextDecoder('utf-8').decode(attr.s) : '';\n                        type = 'string';\n                        break;\n                    case espdl.schema.AttributeType.TENSOR:\n                        value = attr.t ? new espdl.Tensor(0, attr.t) : null;\n                        type = 'tensor';\n                        break;\n                    case espdl.schema.AttributeType.FLOATS:\n                        value = attr.floats ? Array.from(attr.floats) : [];\n                        type = 'float32[]';\n                        break;\n                    case espdl.schema.AttributeType.INTS:\n                        value = attr.ints ? Array.from(attr.ints).map((i) => Number(i)) : [];\n                        type = 'int64[]';\n                        break;\n                    case espdl.schema.AttributeType.STRINGS:\n                        value = attr.strings ? attr.strings.map((s) => new TextDecoder('utf-8').decode(s)) : [];\n                        type = 'string[]';\n                        break;\n                    default:\n                        break;\n                }\n                const attribute = new espdl.Argument(name, value, type);\n                this.attributes.push(attribute);\n            }\n        }\n    }\n};\n\nespdl.Tensor = class {\n\n    constructor(index, tensor) {\n        this.identifier = index.toString();\n        this.name = tensor.name || '';\n        this.type = new espdl.TensorType(tensor);\n        this.category = '';\n        this.encoding = this.type.dataType === 'string' ? '|' : '<';\n        this.values = null;\n        if (tensor.float_data && tensor.float_data.length > 0) {\n            this.values = new Float32Array(tensor.float_data);\n        } else if (tensor.int32_data && tensor.int32_data.length > 0) {\n            this.values = new Int32Array(tensor.int32_data);\n        } else if (tensor.int64_data && tensor.int64_data.length > 0) {\n            this.values = new BigInt64Array(tensor.int64_data);\n        } else if (tensor.string_data && tensor.string_data.length > 0) {\n            this.values = tensor.string_data;\n        } else if (tensor.raw_data && tensor.raw_data.length > 0) {\n            const length = tensor.raw_data.length * 16;\n            const data = new Uint8Array(length);\n            for (let i = 0; i < tensor.raw_data.length; i++) {\n                data.set(tensor.raw_data[i].bytes, i * 16);\n            }\n            this.values = data;\n        }\n    }\n};\n\nespdl.TensorType = class {\n\n    constructor(tensor) {\n        let dataType = '';\n        if (tensor.value_info_type === undefined) {\n            dataType = tensor.data_type;\n            this.shape = new espdl.TensorShape(tensor.dims ? Array.from(tensor.dims).map((d) => Number(d)) : []);\n        } else {\n            const value = tensor.value_info_type.value;\n            dataType = value ? value.elem_type : undefined;\n            let shape = [];\n            const dim = value && value.shape && value.shape.dim;\n            if (dim && dim.length > 0) {\n                shape = dim.map((d) => {\n                    if (d && d.value) {\n                        if (d.value.dim_type === 1) {\n                            return Number(d.value.dim_value);\n                        } else if (d.value.dim_type === 2) {\n                            return d.value.dim_param || '?';\n                        }\n                    }\n                    return '?';\n                });\n            }\n            this.shape = new espdl.TensorShape(shape);\n        }\n        switch (dataType) {\n            case espdl.schema.TensorDataType.FLOAT: this.dataType = 'float32'; break;\n            case espdl.schema.TensorDataType.DOUBLE: this.dataType = 'float64'; break;\n            case espdl.schema.TensorDataType.BOOL: this.dataType = 'boolean'; break;\n            default: this.dataType = espdl.schema.TensorDataType[dataType] ? espdl.schema.TensorDataType[dataType].toLowerCase() : '?'; break;\n        }\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nespdl.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n    }\n};\n\nespdl.Metadata = class {\n\n    static async open(context) {\n        if (!espdl.Metadata._metadata) {\n            let data = null;\n            try {\n                data = await context.request('espdl-metadata.json');\n            } catch {\n                // continue regardless of error\n            }\n            espdl.Metadata._metadata = new espdl.Metadata(data);\n        }\n        return espdl.Metadata._metadata;\n    }\n\n    constructor(data) {\n        this._types = new Map();\n        if (data) {\n            const types = JSON.parse(data);\n            for (const type of types) {\n                if (!this._types.has(type.module)) {\n                    this._types.set(type.module, new Map());\n                }\n                const types = this._types.get(type.module);\n                if (!types.has(type.name)) {\n                    types.set(type.name, []);\n                }\n                types.get(type.name).push(type);\n            }\n        }\n    }\n\n    type(domain, name) {\n        domain = domain || 'espdl';\n        let current = null;\n        if (this._types.has(domain)) {\n            const types = this._types.get(domain);\n            if (types.has(name)) {\n                for (const type of types.get(name)) {\n                    if (!current || type.version > current.version) {\n                        current = type;\n                    }\n                }\n            }\n        }\n        return current;\n    }\n};\n\nespdl.Context = class {\n\n    constructor(graph) {\n        this._initializers = new Map();\n        this._values = new Map();\n        if (graph.initializer) {\n            for (let i = 0; i < graph.initializer.length; i++) {\n                const tensor = graph.initializer[i];\n                const name = tensor.name || '';\n                if (name) {\n                    const initializer = new espdl.Tensor(i, tensor);\n                    this._initializers.set(name, initializer);\n                    this._values.set(name, new espdl.Value(name, initializer.type, initializer));\n                }\n            }\n        }\n        if (graph.input) {\n            for (const valueInfo of graph.input) {\n                const name = valueInfo.name || '';\n                if (name && !this._values.has(name)) {\n                    const type = valueInfo.value_info_type ? new espdl.TensorType(valueInfo) : null;\n                    this._values.set(name, new espdl.Value(name, type, null));\n                }\n            }\n        }\n        if (graph.output) {\n            for (const valueInfo of graph.output) {\n                const name = valueInfo.name || '';\n                if (name && !this._values.has(name)) {\n                    const type = valueInfo.value_info_type ? new espdl.TensorType(valueInfo) : null;\n                    this._values.set(name, new espdl.Value(name, type, null));\n                }\n            }\n        }\n        if (graph.value_info) {\n            for (const valueInfo of graph.value_info) {\n                const name = valueInfo.name || '';\n                if (name && !this._values.has(name)) {\n                    const type = valueInfo.value_info_type ? new espdl.TensorType(valueInfo) : null;\n                    this._values.set(name, new espdl.Value(name, type, null));\n                }\n            }\n        }\n    }\n\n    value(name) {\n        if (!this._values.has(name)) {\n            this._values.set(name, new espdl.Value(name, null, null));\n        }\n        return this._values.get(name);\n    }\n\n    initializer(name) {\n        return this._initializers.get(name) || null;\n    }\n};\n\nespdl.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading ESP-DL model.';\n    }\n};\n\nexport const ModelFactory = espdl.ModelFactory;"
  },
  {
    "path": "source/espresso-metadata.json",
    "content": "[\n  {\n    \"name\": \"convolution\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"inner_product\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"activation\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"transpose\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"pool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"instancenorm_1d\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"batch_norm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"batchnorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"reshape\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"dynamic_quantize\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"dynamic_dequantize\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"general_concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"upsample\",\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"relu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"prelu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"tanh\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"squeeze\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"rnn_arch\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"flatten\",\n    \"category\": \"Shape\"\n  }\n]"
  },
  {
    "path": "source/espresso.js",
    "content": "\nconst espresso = {};\n\nespresso.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier.toLowerCase();\n        if (identifier.endsWith('.espresso.net')) {\n            const obj = await context.peek('json');\n            if (obj && Array.isArray(obj.layers) && obj.format_version) {\n                return context.set('espresso.net', obj);\n            }\n        }\n        if (identifier.endsWith('.espresso.shape')) {\n            const obj = await context.peek('json');\n            if (obj && obj.layer_shapes) {\n                return context.set('espresso.shape', obj);\n            }\n        }\n        if (identifier.endsWith('.espresso.weights')) {\n            const target = await context.read('binary');\n            return context.set('espresso.weights', target);\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        if (context.type === 'espresso.net' && (match.type === 'espresso.weights' || match.type === 'espresso.shape' || match.type === 'coreml.metadata.mlmodelc')) {\n            return false;\n        }\n        if (context.type === 'espresso.shape' && (match.type === 'espresso.weights' || match.type === 'coreml.metadata.mlmodelc')) {\n            return false;\n        }\n        return true;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('espresso-metadata.json');\n        switch (context.type) {\n            case 'espresso.net': {\n                const reader = new espresso.Reader(context.value, null, null);\n                await reader.read(context);\n                return new espresso.Model(metadata, reader);\n            }\n            case 'espresso.weights': {\n                const reader = new espresso.Reader(null, context.value, null);\n                await reader.read(context);\n                return new espresso.Model(metadata, reader);\n            }\n            case 'espresso.shape': {\n                const reader = new espresso.Reader(null, null, context.value);\n                await reader.read(context);\n                return new espresso.Model(metadata, reader);\n            }\n            default: {\n                throw new espresso.Error(`Unsupported Core ML format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nespresso.Model = class {\n\n    constructor(metadata, reader) {\n        this.format = reader.format;\n        this.metadata = [];\n        this.modules = [new espresso.Graph(metadata, reader)];\n        if (reader.version) {\n            this.version = reader.version;\n        }\n        if (reader.description) {\n            this.description = reader.description;\n        }\n        for (const argument of reader.properties) {\n            this.metadata.push(argument);\n        }\n    }\n};\n\nespresso.Graph = class {\n\n    constructor(metadata, reader) {\n        this.name = '';\n        this.type = reader.type;\n        for (const value of reader.values.values()) {\n            const name = value.name;\n            const type = value.type;\n            const description = value.description;\n            const initializer = value.initializer;\n            if (!value.value) {\n                value.value = new espresso.Value(name, type, description, initializer);\n            }\n        }\n        this.inputs = reader.inputs.map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new espresso.Argument(argument.name, values, null, argument.visible);\n        });\n        this.outputs = reader.outputs.map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new espresso.Argument(argument.name, values, null, argument.visible);\n        });\n        for (const obj of reader.nodes) {\n            const attributes = obj.attributes;\n            switch (obj.type) {\n                case 'loop':\n                    attributes.conditionNetwork = new espresso.Graph(attributes.conditionNetwork);\n                    attributes.bodyNetwork = new espresso.Graph(attributes.bodyNetwork);\n                    break;\n                case 'branch':\n                    attributes.ifBranch = new espresso.Graph(attributes.ifBranch);\n                    attributes.elseBranch = new espresso.Graph(attributes.elseBranch);\n                    break;\n                default:\n                    break;\n            }\n        }\n        this.nodes = reader.nodes.map((obj) => new espresso.Node(metadata, obj));\n    }\n};\n\nespresso.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nespresso.Value = class {\n\n    constructor(name, type, description = null, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new espresso.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.description = description;\n        this.initializer = initializer;\n        this.quantization = initializer ? initializer.quantization : null;\n    }\n};\n\nespresso.Node = class {\n\n    constructor(metadata, obj) {\n        if (!obj.type) {\n            throw new Error('Undefined node type.');\n        }\n        const type = metadata.type(obj.type);\n        this.type = type ? { ...type } : { name: obj.type };\n        this.type.name = obj.type.split(':').pop();\n        this.name = obj.name || '';\n        this.description = obj.description || '';\n        this.inputs = (obj.inputs || []).map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new espresso.Argument(argument.name, values, null, argument.visible);\n        });\n        this.outputs = (obj.outputs || []).map((argument) => {\n            const values = argument.value.map((value) => value.value);\n            return new espresso.Argument(argument.name, values, null, argument.visible);\n        });\n        this.attributes = Object.entries(obj.attributes || []).map(([name, value]) => {\n            const schema = metadata.attribute(obj.type, name);\n            let type = null;\n            let visible = true;\n            if (schema) {\n                type = schema.type ? schema.type : type;\n                if (schema.visible === false) {\n                    visible = false;\n                } else if (schema.default !== undefined) {\n                    if (Array.isArray(value)) {\n                        value = value.map((item) => Number(item));\n                    }\n                    if (typeof value === 'bigint') {\n                        value = value.toNumber();\n                    }\n                    if (JSON.stringify(schema.default) === JSON.stringify(value)) {\n                        visible = false;\n                    }\n                }\n            }\n            return new espresso.Argument(name, value, type, visible);\n        });\n        if (Array.isArray(obj.chain)) {\n            this.chain = obj.chain.map((obj) => new espresso.Node(metadata, obj));\n        }\n    }\n};\n\nespresso.Tensor = class {\n\n    constructor(type, data, quantization, category) {\n        this.type = type;\n        this.values = data;\n        this.quantization = quantization;\n        this.category = category;\n        this.encoding = '<';\n    }\n};\n\nespresso.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape || new espresso.TensorShape([]);\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nespresso.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim);\n    }\n\n    equals(obj) {\n        return obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions) &&\n            this.dimensions.length === obj.dimensions.length &&\n            obj.dimensions.every((value, index) => this.dimensions[index] === value);\n    }\n\n    toString() {\n        return Array.isArray(this.dimensions) && this.dimensions.length > 0 ?\n            `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]` : '';\n    }\n};\n\nespresso.Reader = class {\n\n    constructor(net, weights, shape) {\n        this.targets = [net, shape, weights];\n    }\n\n    async read(context) {\n        this.format = 'Espresso';\n        this.properties = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        let [net, shape, weights] = this.targets;\n        delete this.targets;\n        if (!net) {\n            const name = context.identifier.replace(/\\.espresso\\.(net|weights|shape)$/i, '.espresso.net');\n            const content = await context.fetch(name);\n            net = await content.read('json');\n        }\n        this.shapes = new Map();\n        if (!shape) {\n            const name = context.identifier.replace(/\\.espresso\\.(net|weights|shape)$/i, '.espresso.shape');\n            try {\n                const content = await context.fetch(name);\n                shape = await content.read('json');\n            } catch {\n                // continue regardless of error\n            }\n        }\n        if (shape && shape.layer_shapes) {\n            for (const [name, value] of Object.entries(shape.layer_shapes)) {\n                const dimensions = [value.n, value.k, value.w, value.h];\n                const shape = new espresso.TensorShape(dimensions);\n                this.shapes.set(name, shape);\n            }\n        }\n        this.blobs = new Map();\n        if (!weights) {\n            const name = net && net.storage ? net.storage : context.identifier.replace(/\\.espresso\\.(net|weights|shape)$/i, '.espresso.weights');\n            try {\n                const content = await context.fetch(name);\n                weights = await content.read('binary');\n            } catch {\n                // continue regardless of error\n            }\n        }\n        if (weights) {\n            const reader = weights;\n            const length = reader.uint64().toNumber();\n            for (let i = 0; i < length; i++) {\n                const key = reader.uint64().toNumber();\n                const size = reader.uint64().toNumber();\n                this.blobs.set(key, size);\n            }\n            for (const [key, size] of this.blobs) {\n                const buffer = reader.read(size);\n                this.blobs.set(key, buffer);\n            }\n        }\n        this.values = new Map();\n        if (net.format_version) {\n            const major = Math.floor(net.format_version / 100);\n            const minor = net.format_version % 100;\n            this.format += ` v${major}.${minor}`;\n        }\n        if (net && Array.isArray(net.layers)) {\n            for (const layer of net.layers) {\n                const type = layer.type;\n                const data = { ...layer };\n                const top = layer.top.split(',').map((name) => this._value(name));\n                const bottom = layer.bottom.split(',').map((name) => this._value(name));\n                const obj = {};\n                obj.type = type;\n                obj.name = layer.name;\n                obj.attributes = data;\n                obj.inputs = [{ name: 'inputs', value: bottom }];\n                obj.outputs = [{ name: 'outputs', value: top }];\n                obj.chain = [];\n                switch (type) {\n                    case 'convolution':\n                    case 'deconvolution': {\n                        this._weights(obj, data, [data.C, data.K, data.Nx, data.Ny]);\n                        if (data.has_biases) {\n                            obj.inputs.push(this._initializer('biases', data.blob_biases, 'float32', [data.C]));\n                        }\n                        delete data.has_biases;\n                        delete data.blob_biases;\n                        break;\n                    }\n                    case 'batchnorm': {\n                        obj.inputs.push(this._initializer('params', data.blob_batchnorm_params, 'float32', [4, data.C]));\n                        delete data.blob_batchnorm_params;\n                        break;\n                    }\n                    case 'inner_product': {\n                        this._weights(obj, data, [data.nC, data.nB]);\n                        if (data.has_biases) {\n                            obj.inputs.push(this._initializer('biases', data.blob_biases, 'float32', [data.nC]));\n                        }\n                        delete data.has_biases;\n                        delete data.blob_biases;\n                        break;\n                    }\n                    case 'conv3d': {\n                        this._weights(obj, data, null);\n                        if (data.has_biases) {\n                            obj.inputs.push(this._initializer('biases', data.blob_biases, 'float32', null));\n                        }\n                        delete data.has_biases;\n                        delete data.blob_biases;\n                        break;\n                    }\n                    case 'instancenorm_1d':\n                    case 'dynamic_dequantize': {\n                        this._weights(obj, data, null);\n                        break;\n                    }\n                    default: {\n                        break;\n                    }\n                }\n                const blobs = Object.keys(data).filter((key) => key.startsWith('blob_'));\n                if (blobs.length > 0) {\n                    throw new espresso.Error(`Unknown blob '${blobs.join(',')}' for type '${type}'.`);\n                }\n                if (data.has_prelu) {\n                    obj.chain.push({ type: 'prelu' });\n                }\n                if (data.fused_relu || data.has_relu) {\n                    obj.chain.push({ type: 'relu' });\n                }\n                if (data.fused_tanh || data.has_tanh) {\n                    obj.chain.push({ type: 'tanh' });\n                }\n                if (data.has_batch_norm) {\n                    obj.chain.push({ type: 'batch_norm' });\n                }\n                if (data.weights) {\n                    for (const [name, identifier] of Object.entries(data.weights)) {\n                        obj.inputs.push(this._initializer(name, identifier, 'float32', null));\n                    }\n                    delete data.weights;\n                }\n                delete data.name;\n                delete data.type;\n                delete data.top;\n                delete data.bottom;\n                delete data.fused_tanh;\n                delete data.fused_relu;\n                delete data.has_prelu;\n                delete data.has_relu;\n                delete data.has_tanh;\n                delete data.has_batch_norm;\n                this.nodes.push(obj);\n            }\n        }\n        delete this.shapes;\n        delete this.blobs;\n    }\n\n    _value(name) {\n        if (!this.values.has(name)) {\n            const shape = this.shapes.get(name);\n            const type = shape ? new espresso.TensorType('float32', shape) : null;\n            this.values.set(name, { name, type });\n        }\n        return this.values.get(name);\n    }\n\n    _weights(obj, data, dimensions) {\n        if (data.blob_weights !== undefined) {\n            obj.inputs.push(this._initializer('weights', data.blob_weights, 'float32', dimensions));\n            delete data.blob_weights;\n            return;\n        }\n        if (data.blob_weights_f16 !== undefined) {\n            obj.inputs.push(this._initializer('weights', data.blob_weights_f16, 'float16', dimensions));\n            delete data.blob_weights_f16;\n            return;\n        }\n        const keys = ['wBeta', 'wGamma', 'W_S8', 'W_int8', 'W_t_int8'];\n        for (const key of keys) {\n            if (data.weights && data.weights[key] !== undefined) {\n                let dataType = 'float32';\n                let name = key;\n                if (key.endsWith('_S8')) {\n                    dataType = 'int8';\n                    name = key.replace(/_S8$/, '');\n                } else if (key.endsWith('_int8')) {\n                    dataType = 'int8';\n                    name = key.replace(/_int8$/, '');\n                }\n                obj.inputs.push(this._initializer(name, data.weights[key], dataType, dimensions));\n                delete data.weights[key];\n            }\n        }\n    }\n\n    _initializer(name, identifier, dataType, dimensions) {\n        if (!Number.isInteger(identifier)) {\n            throw new espresso.Error(`Invalid '${identifier}' blob identifier.`);\n        }\n        dataType = dataType || 'float32';\n        const blob = this.blobs.get(identifier);\n        if (!dimensions) {\n            const itemsize = dataType === 'float32' ? 4 : 1;\n            dimensions = blob ? [blob.length / itemsize] : ['?'];\n        }\n        const shape = new espresso.TensorShape(dimensions);\n        const type = new espresso.TensorType(dataType, shape);\n        const value = {};\n        const initializer = new espresso.Tensor(type, blob, null, 'Blob');\n        value.value = new espresso.Value(`${identifier}\\nblob`, type, null, initializer);\n        return { name, value: [value] };\n    }\n};\n\nespresso.Error = class extends Error {\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Espresso model.';\n    }\n};\n\nexport const ModelFactory = espresso.ModelFactory;\n"
  },
  {
    "path": "source/executorch-schema.js",
    "content": "\nexport const executorch_flatbuffer = {};\n\nexport const fb_xnnpack = {};\n\nexport const vkgraph = {};\n\nexecutorch_flatbuffer.ScalarType = {\n    BYTE: 0, '0': 'BYTE',\n    CHAR: 1, '1': 'CHAR',\n    SHORT: 2, '2': 'SHORT',\n    INT: 3, '3': 'INT',\n    LONG: 4, '4': 'LONG',\n    HALF: 5, '5': 'HALF',\n    FLOAT: 6, '6': 'FLOAT',\n    DOUBLE: 7, '7': 'DOUBLE',\n    BOOL: 11, '11': 'BOOL',\n    QINT8: 12, '12': 'QINT8',\n    QUINT8: 13, '13': 'QUINT8',\n    QINT32: 14, '14': 'QINT32',\n    BFLOAT16: 15, '15': 'BFLOAT16',\n    QUINT4X2: 16, '16': 'QUINT4X2',\n    QUINT2X4: 17, '17': 'QUINT2X4',\n    BITS16: 22, '22': 'BITS16',\n    FLOAT8E5M2: 23, '23': 'FLOAT8E5M2',\n    FLOAT8E4M3FN: 24, '24': 'FLOAT8E4M3FN',\n    FLOAT8E5M2FNUZ: 25, '25': 'FLOAT8E5M2FNUZ',\n    FLOAT8E4M3FNUZ: 26, '26': 'FLOAT8E4M3FNUZ',\n    UINT16: 27, '27': 'UINT16',\n    UINT32: 28, '28': 'UINT32',\n    UINT64: 29, '29': 'UINT64'\n};\n\nexecutorch_flatbuffer.ContainerMetadata = class ContainerMetadata {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.ContainerMetadata();\n        $.encoded_inp_str = reader.string_(position, 4, null);\n        $.encoded_out_str = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Null = class Null {\n\n    static decode(/* reader, position */) {\n        const $ = new executorch_flatbuffer.Null();\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.AllocationDetails = class AllocationDetails {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.AllocationDetails();\n        $.memory_id = reader.uint32_(position, 4, 0);\n        $.memory_offset_low = reader.uint32_(position, 6, 0);\n        $.memory_offset_high = reader.uint32_(position, 8, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.TensorShapeDynamism = {\n    STATIC: 0, '0': 'STATIC',\n    DYNAMIC_BOUND: 1, '1': 'DYNAMIC_BOUND',\n    DYNAMIC_UNBOUND: 2, '2': 'DYNAMIC_UNBOUND'\n};\n\nexecutorch_flatbuffer.TensorDataLocation = {\n    SEGMENT: 0, '0': 'SEGMENT',\n    EXTERNAL: 1, '1': 'EXTERNAL'\n};\n\nexecutorch_flatbuffer.ExtraTensorInfo = class ExtraTensorInfo {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.ExtraTensorInfo();\n        $.mutable_data_segments_idx = reader.uint64_(position, 4, 0n);\n        $.fully_qualified_name = reader.string_(position, 6, null);\n        $.location = reader.int8_(position, 8, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Tensor();\n        $.scalar_type = reader.int8_(position, 4, 0);\n        $.storage_offset = reader.int32_(position, 6, 0);\n        $.sizes = reader.array(position, 8, Int32Array);\n        $.dim_order = reader.array(position, 10, Uint8Array);\n        $.requires_grad = reader.bool_(position, 12, false);\n        $.data_buffer_idx = reader.uint32_(position, 14, 0);\n        $.allocation_info = reader.table(position, 16, executorch_flatbuffer.AllocationDetails);\n        $.layout = reader.int8_(position, 18, 0);\n        $.shape_dynamism = reader.int8_(position, 20, 0);\n        $.extra_tensor_info = reader.table(position, 22, executorch_flatbuffer.ExtraTensorInfo);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Int = class Int {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Int();\n        $.int_val = reader.int64_(position, 4, 0n);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Bool = class Bool {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Bool();\n        $.bool_val = reader.bool_(position, 4, false);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Double = class Double {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Double();\n        $.double_val = reader.float64_(position, 4, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.String = class String {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.String();\n        $.string_val = reader.string_(position, 4, null);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.IntList = class IntList {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.IntList();\n        $.items = reader.int64s_(position, 4);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.DoubleList = class DoubleList {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.DoubleList();\n        $.items = reader.array(position, 4, Float64Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.BoolList = class BoolList {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.BoolList();\n        $.items = reader.bools_(position, 4);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.TensorList = class TensorList {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.TensorList();\n        $.items = reader.array(position, 4, Int32Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.OptionalTensorList = class OptionalTensorList {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.OptionalTensorList();\n        $.items = reader.array(position, 4, Int32Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.KernelTypes = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return executorch_flatbuffer.Null.decode(reader, position);\n            case 2: return executorch_flatbuffer.Int.decode(reader, position);\n            case 3: return executorch_flatbuffer.Bool.decode(reader, position);\n            case 4: return executorch_flatbuffer.Double.decode(reader, position);\n            case 5: return executorch_flatbuffer.Tensor.decode(reader, position);\n            case 6: return executorch_flatbuffer.String.decode(reader, position);\n            case 7: return executorch_flatbuffer.IntList.decode(reader, position);\n            case 8: return executorch_flatbuffer.DoubleList.decode(reader, position);\n            case 9: return executorch_flatbuffer.BoolList.decode(reader, position);\n            case 10: return executorch_flatbuffer.TensorList.decode(reader, position);\n            case 11: return executorch_flatbuffer.OptionalTensorList.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nexecutorch_flatbuffer.EValue = class EValue {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.EValue();\n        $.val = reader.union(position, 4, executorch_flatbuffer.KernelTypes);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Operator = class Operator {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Operator();\n        $.name = reader.string_(position, 4, null);\n        $.overload = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.KernelCall = class KernelCall {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.KernelCall();\n        $.op_index = reader.int32_(position, 4, 0);\n        $.args = reader.array(position, 6, Int32Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.DelegateCall = class DelegateCall {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.DelegateCall();\n        $.delegate_index = reader.int32_(position, 4, 0);\n        $.args = reader.array(position, 6, Int32Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.MoveCall = class MoveCall {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.MoveCall();\n        $.move_from = reader.int32_(position, 4, 0);\n        $.move_to = reader.int32_(position, 6, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.JumpFalseCall = class JumpFalseCall {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.JumpFalseCall();\n        $.cond_value_index = reader.int32_(position, 4, 0);\n        $.destination_instruction = reader.int32_(position, 6, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.FreeCall = class FreeCall {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.FreeCall();\n        $.value_index = reader.int32_(position, 4, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.InstructionArguments = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return executorch_flatbuffer.KernelCall.decode(reader, position);\n            case 2: return executorch_flatbuffer.DelegateCall.decode(reader, position);\n            case 3: return executorch_flatbuffer.MoveCall.decode(reader, position);\n            case 4: return executorch_flatbuffer.JumpFalseCall.decode(reader, position);\n            case 5: return executorch_flatbuffer.FreeCall.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nexecutorch_flatbuffer.Instruction = class Instruction {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Instruction();\n        $.instr_args = reader.union(position, 4, executorch_flatbuffer.InstructionArguments);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Frame = class Frame {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Frame();\n        $.filename = reader.string_(position, 4, null);\n        $.lineno = reader.int32_(position, 6, 0);\n        $.name = reader.string_(position, 8, null);\n        $.context = reader.string_(position, 10, null);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.FrameList = class FrameList {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.FrameList();\n        $.items = reader.tables(position, 4, executorch_flatbuffer.Frame);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.DataLocation = {\n    INLINE: 0, '0': 'INLINE',\n    SEGMENT: 1, '1': 'SEGMENT'\n};\n\nexecutorch_flatbuffer.BackendDelegateDataReference = class BackendDelegateDataReference {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.BackendDelegateDataReference();\n        $.location = reader.int8_(position, 4, 0);\n        $.index = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.CompileSpec = class CompileSpec {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.CompileSpec();\n        $.key = reader.string_(position, 4, null);\n        $.value = reader.array(position, 6, Uint8Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.BackendDelegate = class BackendDelegate {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.BackendDelegate();\n        $.id = reader.string_(position, 4, null);\n        $.processed = reader.table(position, 6, executorch_flatbuffer.BackendDelegateDataReference);\n        $.compile_specs = reader.tables(position, 8, executorch_flatbuffer.CompileSpec);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Chain = class Chain {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Chain();\n        $.inputs = reader.array(position, 4, Int32Array);\n        $.outputs = reader.array(position, 6, Int32Array);\n        $.instructions = reader.tables(position, 8, executorch_flatbuffer.Instruction);\n        $.stacktrace = reader.tables(position, 10, executorch_flatbuffer.FrameList);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.ExecutionPlan = class ExecutionPlan {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.ExecutionPlan();\n        $.name = reader.string_(position, 4, null);\n        $.container_meta_type = reader.table(position, 6, executorch_flatbuffer.ContainerMetadata);\n        $.values = reader.tables(position, 8, executorch_flatbuffer.EValue);\n        $.inputs = reader.array(position, 10, Int32Array);\n        $.outputs = reader.array(position, 12, Int32Array);\n        $.chains = reader.tables(position, 14, executorch_flatbuffer.Chain);\n        $.operators = reader.tables(position, 16, executorch_flatbuffer.Operator);\n        $.delegates = reader.tables(position, 18, executorch_flatbuffer.BackendDelegate);\n        $.non_const_buffer_sizes = reader.int64s_(position, 20);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Buffer = class Buffer {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Buffer();\n        $.storage = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.BackendDelegateInlineData = class BackendDelegateInlineData {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.BackendDelegateInlineData();\n        $.data = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.DataSegment = class DataSegment {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.DataSegment();\n        $.offset = reader.uint64_(position, 4, 0n);\n        $.size = reader.uint64_(position, 6, 0n);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.SubsegmentOffsets = class SubsegmentOffsets {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.SubsegmentOffsets();\n        $.segment_index = reader.uint32_(position, 4, 0);\n        $.offsets = reader.uint64s_(position, 6);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.NamedData = class NamedData {\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.NamedData();\n        $.key = reader.string_(position, 4, null);\n        $.segment_index = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nexecutorch_flatbuffer.Program = class Program {\n\n    static identifier(reader) {\n        return reader.identifier === 'ET12';\n    }\n\n    static create(reader) {\n        return executorch_flatbuffer.Program.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new executorch_flatbuffer.Program();\n        $.version = reader.uint32_(position, 4, 0);\n        $.execution_plan = reader.tables(position, 6, executorch_flatbuffer.ExecutionPlan);\n        $.constant_buffer = reader.tables(position, 8, executorch_flatbuffer.Buffer);\n        $.backend_delegate_data = reader.tables(position, 10, executorch_flatbuffer.BackendDelegateInlineData);\n        $.segments = reader.tables(position, 12, executorch_flatbuffer.DataSegment);\n        $.constant_segment = reader.table(position, 14, executorch_flatbuffer.SubsegmentOffsets);\n        $.mutable_data_segments = reader.tables(position, 16, executorch_flatbuffer.SubsegmentOffsets);\n        $.named_data = reader.tables(position, 18, executorch_flatbuffer.NamedData);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNDatatype = {\n    xnn_datatype_invalid: 0, '0': 'xnn_datatype_invalid',\n    xnn_datatype_fp32: 1, '1': 'xnn_datatype_fp32',\n    xnn_datatype_fp16: 2, '2': 'xnn_datatype_fp16',\n    xnn_datatype_qint8: 3, '3': 'xnn_datatype_qint8',\n    xnn_datatype_quint8: 4, '4': 'xnn_datatype_quint8',\n    xnn_datatype_qint32: 5, '5': 'xnn_datatype_qint32',\n    xnn_datatype_qcint8: 6, '6': 'xnn_datatype_qcint8',\n    xnn_datatype_qcint32: 7, '7': 'xnn_datatype_qcint32',\n    xnn_datatype_qcint4: 8, '8': 'xnn_datatype_qcint4',\n    xnn_datatype_qdint8: 9, '9': 'xnn_datatype_qdint8',\n    xnn_datatype_qbint4: 10, '10': 'xnn_datatype_qbint4',\n    xnn_datatype_qpint8: 11, '11': 'xnn_datatype_qpint8',\n    xnn_datatype_int32: 12, '12': 'xnn_datatype_int32',\n    xnn_datatype_pfp32: 13, '13': 'xnn_datatype_pfp32',\n    xnn_datatype_bf16: 14, '14': 'xnn_datatype_bf16'\n};\n\nfb_xnnpack.XNNQuantParams = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return fb_xnnpack.PerChannelQuant.decode(reader, position);\n            case 2: return fb_xnnpack.PerTensorQuant.decode(reader, position);\n            case 3: return fb_xnnpack.PerTokenDynamicQuant.decode(reader, position);\n            case 4: return fb_xnnpack.PerChannelGroupQuant.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nfb_xnnpack.Buffer = class Buffer {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.Buffer();\n        $.storage = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n};\n\nfb_xnnpack.PerChannelGroupQuant = class PerChannelGroupQuant {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.PerChannelGroupQuant();\n        $.scale = reader.array(position, 4, Float32Array);\n        $.channel_dim = reader.int32_(position, 6, 0);\n        $.group_size = reader.int32_(position, 8, 0);\n        $.scale_bf16 = reader.array(position, 10, Uint16Array);\n        $.scale_buffer_idx = reader.uint32_(position, 12, 0);\n        $.num_scales = reader.uint32_(position, 14, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.PerChannelQuant = class PerChannelQuant {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.PerChannelQuant();\n        $.scale = reader.array(position, 4, Float32Array);\n        $.channel_dim = reader.int32_(position, 6, 0);\n        $.scale_buffer_idx = reader.uint32_(position, 8, 0);\n        $.num_scales = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.PerTokenDynamicQuant = class PerTokenDynamicQuant {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.PerTokenDynamicQuant();\n        $.num_nonbatch_dims = reader.int32_(position, 4, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.PerTensorQuant = class PerTensorQuant {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.PerTensorQuant();\n        $.scale = reader.float32_(position, 4, 0);\n        $.zero_point = reader.int32_(position, 6, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNTensorValue = class XNNTensorValue {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNTensorValue();\n        $.datatype = reader.int16_(position, 4, 0);\n        $.num_dims = reader.uint32_(position, 6, 0);\n        $.dims = reader.array(position, 8, Uint32Array);\n        $.constant_buffer_idx = reader.uint32_(position, 10, 0);\n        $.external_id = reader.uint32_(position, 12, 0);\n        $.flags = reader.uint32_(position, 14, 0);\n        $.id_out = reader.uint32_(position, 16, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNQuantizedTensorValue = class XNNQuantizedTensorValue {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNQuantizedTensorValue();\n        $.tensor_value = reader.table(position, 4, fb_xnnpack.XNNTensorValue);\n        $.quant_params = reader.union(position, 6, fb_xnnpack.XNNQuantParams);\n        return $;\n    }\n};\n\nfb_xnnpack.XNodeUnion = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return fb_xnnpack.XNNAdd.decode(reader, position);\n            case 2: return fb_xnnpack.XNNFullyConnected.decode(reader, position);\n            case 3: return fb_xnnpack.XNNSoftmax.decode(reader, position);\n            case 4: return fb_xnnpack.XNNSigmoid.decode(reader, position);\n            case 5: return fb_xnnpack.XNNStaticTranspose.decode(reader, position);\n            case 6: return fb_xnnpack.XNNClamp.decode(reader, position);\n            case 7: return fb_xnnpack.XNNConv2d.decode(reader, position);\n            case 8: return fb_xnnpack.XNNDiv.decode(reader, position);\n            case 9: return fb_xnnpack.XNNStaticResizeBilinear2D.decode(reader, position);\n            case 10: return fb_xnnpack.XNNStaticConstantPad.decode(reader, position);\n            case 11: return fb_xnnpack.XNNAvgPooling2d.decode(reader, position);\n            case 12: return fb_xnnpack.XNNMinimum.decode(reader, position);\n            case 13: return fb_xnnpack.XNNDepthwiseConv2d.decode(reader, position);\n            case 14: return fb_xnnpack.XNNMaxPooling2d.decode(reader, position);\n            case 15: return fb_xnnpack.XNNMultiply.decode(reader, position);\n            case 16: return fb_xnnpack.XNNSubtract.decode(reader, position);\n            case 17: return fb_xnnpack.XNNFloor.decode(reader, position);\n            case 18: return fb_xnnpack.XNNConvert.decode(reader, position);\n            case 19: return fb_xnnpack.XNNGlobalAvgPooling2d.decode(reader, position);\n            case 20: return fb_xnnpack.XNNStaticReshape.decode(reader, position);\n            case 21: return fb_xnnpack.XNNArgMaxPooling2d.decode(reader, position);\n            case 22: return fb_xnnpack.XNNSquareRoot.decode(reader, position);\n            case 23: return fb_xnnpack.XNNCeiling.decode(reader, position);\n            case 24: return fb_xnnpack.XNNHardswish.decode(reader, position);\n            case 25: return fb_xnnpack.XNNLeakyReLU.decode(reader, position);\n            case 26: return fb_xnnpack.XNNMaximum.decode(reader, position);\n            case 27: return fb_xnnpack.XNNNegate.decode(reader, position);\n            case 28: return fb_xnnpack.XNNSquare.decode(reader, position);\n            case 29: return fb_xnnpack.XNNELU.decode(reader, position);\n            case 30: return fb_xnnpack.XNNAbs.decode(reader, position);\n            case 31: return fb_xnnpack.XNNPReLU.decode(reader, position);\n            case 32: return fb_xnnpack.XNNConcatenate2.decode(reader, position);\n            case 33: return fb_xnnpack.XNNConcatenate3.decode(reader, position);\n            case 34: return fb_xnnpack.XNNConcatenate4.decode(reader, position);\n            case 35: return fb_xnnpack.XNNStaticSlice.decode(reader, position);\n            case 36: return fb_xnnpack.XNNScaledDotProductAttention.decode(reader, position);\n            case 37: return fb_xnnpack.XNNBatchMatrixMultiply.decode(reader, position);\n            case 38: return fb_xnnpack.XNNConcatenate5.decode(reader, position);\n            case 39: return fb_xnnpack.XNNConvTranspose2d.decode(reader, position);\n            case 40: return fb_xnnpack.XNNReciprocalSquareRoot.decode(reader, position);\n            case 41: return fb_xnnpack.XNNLog.decode(reader, position);\n            case 42: return fb_xnnpack.XNNGelu.decode(reader, position);\n            case 43: return fb_xnnpack.XNNTanh.decode(reader, position);\n            case 44: return fb_xnnpack.XNNExp.decode(reader, position);\n            case 45: return fb_xnnpack.XNNSin.decode(reader, position);\n            case 46: return fb_xnnpack.XNNCopy.decode(reader, position);\n            case 47: return fb_xnnpack.XNNCos.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nfb_xnnpack.XValueUnion = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return fb_xnnpack.XNNTensorValue.decode(reader, position);\n            case 2: return fb_xnnpack.XNNQuantizedTensorValue.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nfb_xnnpack.OutputMinMax = class OutputMinMax {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.OutputMinMax();\n        $.output_min = reader.float32_(position, 4, 0);\n        $.output_max = reader.float32_(position, 6, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNode = class XNode {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNode();\n        $.xnode_union = reader.union(position, 4, fb_xnnpack.XNodeUnion);\n        $.debug_handle = reader.uint32_(position, 8, 0);\n        $.output_min_max = reader.table(position, 10, fb_xnnpack.OutputMinMax);\n        return $;\n    }\n};\n\nfb_xnnpack.XValue = class XValue {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XValue();\n        $.xvalue_union = reader.union(position, 4, fb_xnnpack.XValueUnion);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNStaticTranspose = class XNNStaticTranspose {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNStaticTranspose();\n        $.num_dims = reader.uint32_(position, 4, 0);\n        $.perm = reader.array(position, 6, Uint32Array);\n        $.input_id = reader.uint32_(position, 8, 0);\n        $.output_id = reader.uint32_(position, 10, 0);\n        $.flags = reader.uint32_(position, 12, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNStaticResizeBilinear2D = class XNNStaticResizeBilinear2D {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNStaticResizeBilinear2D();\n        $.new_height = reader.uint32_(position, 4, 0);\n        $.new_width = reader.uint32_(position, 6, 0);\n        $.input_id = reader.uint32_(position, 8, 0);\n        $.output_id = reader.uint32_(position, 10, 0);\n        $.flags = reader.uint32_(position, 12, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNStaticConstantPad = class XNNStaticConstantPad {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNStaticConstantPad();\n        $.pre_paddings = reader.array(position, 4, Uint32Array);\n        $.post_paddings = reader.array(position, 6, Uint32Array);\n        $.padding_value = reader.float32_(position, 8, 0);\n        $.input_id = reader.uint32_(position, 10, 0);\n        $.output_id = reader.uint32_(position, 12, 0);\n        $.flags = reader.uint32_(position, 14, 0);\n        return $;\n    }\n};\n\nfb_xnnpack._XNNNode2x1 = class _XNNNode2x1 {\n\n    static decode(reader, position, $) {\n        $ = $ || new fb_xnnpack._XNNNode2x1();\n        $.input1_id = reader.uint32_(position, 4, 0);\n        $.input2_id = reader.uint32_(position, 6, 0);\n        $.output_id = reader.uint32_(position, 8, 0);\n        $.flags = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nfb_xnnpack._XNNNode1x1 = class _XNNNode1x1 {\n\n    static decode(reader, position, $) {\n        $ = $ || new fb_xnnpack._XNNNode1x1();\n        $.input_id = reader.uint32_(position, 4, 0);\n        $.output_id = reader.uint32_(position, 6, 0);\n        $.flags = reader.uint32_(position, 8, 0);\n        return $;\n    }\n};\n\nfb_xnnpack._XNNCat = class _XNNCat {\n\n    static decode(reader, position, $) {\n        $ = $ || new fb_xnnpack._XNNCat();\n        $.axis = reader.uint32_(position, 4, 0);\n        $.input1_id = reader.uint32_(position, 6, 0);\n        $.input2_id = reader.uint32_(position, 8, 0);\n        $.input3_id = reader.uint32_(position, 10, 0);\n        $.input4_id = reader.uint32_(position, 12, 0);\n        $.output_id = reader.uint32_(position, 14, 0);\n        $.flags = reader.uint32_(position, 16, 0);\n        $.input5_id = reader.uint32_(position, 18, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNELU = class XNNELU {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNELU();\n        $.alpha = reader.float32_(position, 4, 0);\n        $.input_id = reader.uint32_(position, 6, 0);\n        $.output_id = reader.uint32_(position, 8, 0);\n        $.flags = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNFullyConnected = class XNNFullyConnected {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNFullyConnected();\n        $.input1_id = reader.uint32_(position, 4, 0);\n        $.filter_id = reader.uint32_(position, 6, 0);\n        $.bias_id = reader.uint32_(position, 8, 0);\n        $.output_id = reader.uint32_(position, 10, 0);\n        $.flags = reader.uint32_(position, 12, 0);\n        return $;\n    }\n};\n\nfb_xnnpack._XNNNodeConv = class _XNNNodeConv {\n\n    static decode(reader, position, $) {\n        $ = $ || new fb_xnnpack._XNNNodeConv();\n        $.padding_top = reader.uint32_(position, 4, 0);\n        $.padding_right = reader.uint32_(position, 6, 0);\n        $.padding_bottom = reader.uint32_(position, 8, 0);\n        $.padding_left = reader.uint32_(position, 10, 0);\n        $.kernel_height = reader.uint32_(position, 12, 0);\n        $.kernel_width = reader.uint32_(position, 14, 0);\n        $.subsampling_height = reader.uint32_(position, 16, 0);\n        $.subsampling_width = reader.uint32_(position, 18, 0);\n        $.dilation_height = reader.uint32_(position, 20, 0);\n        $.dilation_width = reader.uint32_(position, 22, 0);\n        $.group_input_channels = reader.uint32_(position, 24, 0);\n        $.group_output_channels = reader.uint32_(position, 26, 0);\n        $.groups = reader.uint32_(position, 28, 0);\n        $.adjustment_height = reader.uint32_(position, 30, 0);\n        $.adjustment_width = reader.uint32_(position, 32, 0);\n        $.input1_id = reader.uint32_(position, 34, 0);\n        $.filter_id = reader.uint32_(position, 36, 0);\n        $.bias_id = reader.uint32_(position, 38, 0);\n        $.output_id = reader.uint32_(position, 40, 0);\n        $.flags = reader.uint32_(position, 42, 0);\n        return $;\n    }\n};\n\nfb_xnnpack._XNNPooling2D = class _XNNPooling2D {\n\n    static decode(reader, position, $) {\n        $ = $ || new fb_xnnpack._XNNPooling2D();\n        $.padding_top = reader.uint32_(position, 4, 0);\n        $.padding_right = reader.uint32_(position, 6, 0);\n        $.padding_bottom = reader.uint32_(position, 8, 0);\n        $.padding_left = reader.uint32_(position, 10, 0);\n        $.pooling_height = reader.uint32_(position, 12, 0);\n        $.pooling_width = reader.uint32_(position, 14, 0);\n        $.stride_height = reader.uint32_(position, 16, 0);\n        $.stride_width = reader.uint32_(position, 18, 0);\n        $.dilation_height = reader.uint32_(position, 20, 0);\n        $.dilation_width = reader.uint32_(position, 22, 0);\n        $.input_id = reader.uint32_(position, 24, 0);\n        $.output_id = reader.uint32_(position, 26, 0);\n        $.flags = reader.uint32_(position, 28, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNStaticReshape = class XNNStaticReshape {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNStaticReshape();\n        $.num_dims = reader.uint32_(position, 4, 0);\n        $.new_shape = reader.array(position, 6, Uint32Array);\n        $.input_id = reader.uint32_(position, 8, 0);\n        $.output_id = reader.uint32_(position, 10, 0);\n        $.flags = reader.uint32_(position, 12, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNStaticSlice = class XNNStaticSlice {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNStaticSlice();\n        $.num_dims = reader.uint32_(position, 4, 0);\n        $.offsets = reader.array(position, 6, Uint32Array);\n        $.sizes = reader.array(position, 8, Uint32Array);\n        $.input_id = reader.uint32_(position, 10, 0);\n        $.output_id = reader.uint32_(position, 12, 0);\n        $.flags = reader.uint32_(position, 14, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNScaledDotProductAttention = class XNNScaledDotProductAttention {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNScaledDotProductAttention();\n        $.query_id = reader.uint32_(position, 4, 0);\n        $.key_id = reader.uint32_(position, 6, 0);\n        $.value_id = reader.uint32_(position, 8, 0);\n        $.scale_id = reader.uint32_(position, 10, 0);\n        $.mask_id = reader.uint32_(position, 12, 0);\n        $.output_id = reader.uint32_(position, 14, 0);\n        $.flags = reader.uint32_(position, 16, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNArgMaxPooling2d = class XNNArgMaxPooling2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNArgMaxPooling2d();\n        $.padding_top = reader.uint32_(position, 4, 0);\n        $.padding_right = reader.uint32_(position, 6, 0);\n        $.padding_bottom = reader.uint32_(position, 8, 0);\n        $.padding_left = reader.uint32_(position, 10, 0);\n        $.pooling_height = reader.uint32_(position, 12, 0);\n        $.pooling_width = reader.uint32_(position, 14, 0);\n        $.input_id = reader.uint32_(position, 16, 0);\n        $.output_value_id = reader.uint32_(position, 18, 0);\n        $.output_index_id = reader.uint32_(position, 20, 0);\n        $.flags = reader.uint32_(position, 22, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNLeakyReLU = class XNNLeakyReLU {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNLeakyReLU();\n        $.negative_slope = reader.float32_(position, 4, 0);\n        $.input_id = reader.uint32_(position, 6, 0);\n        $.output_id = reader.uint32_(position, 8, 0);\n        $.flags = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nfb_xnnpack.ConstantDataOffset = class ConstantDataOffset {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.ConstantDataOffset();\n        $.offset = reader.uint64_(position, 4, 0n);\n        $.size = reader.uint64_(position, 6, 0n);\n        $.named_key = reader.string_(position, 8, null);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNGraph = class XNNGraph {\n\n    static identifier(reader) {\n        return reader.identifier === 'XN01';\n    }\n\n    static create(reader) {\n        return fb_xnnpack.XNNGraph.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNGraph();\n        $.version = reader.string_(position, 4, null);\n        $.xnodes = reader.tables(position, 6, fb_xnnpack.XNode);\n        $.xvalues = reader.tables(position, 8, fb_xnnpack.XValue);\n        $.num_externs = reader.uint32_(position, 10, 0);\n        $.input_ids = reader.array(position, 12, Uint32Array);\n        $.output_ids = reader.array(position, 14, Uint32Array);\n        $.constant_buffer = reader.tables(position, 16, fb_xnnpack.Buffer);\n        $.mem_buffer_sizes = reader.array(position, 18, Uint32Array);\n        $.constant_data = reader.tables(position, 20, fb_xnnpack.ConstantDataOffset);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNAdd = class XNNAdd {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNAdd();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNSoftmax = class XNNSoftmax {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNSoftmax();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNSigmoid = class XNNSigmoid {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNSigmoid();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNClamp = class XNNClamp {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNClamp();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConv2d = class XNNConv2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConv2d();\n        fb_xnnpack._XNNNodeConv.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNDiv = class XNNDiv {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNDiv();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNAvgPooling2d = class XNNAvgPooling2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNAvgPooling2d();\n        fb_xnnpack._XNNPooling2D.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNMinimum = class XNNMinimum {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNMinimum();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNDepthwiseConv2d = class XNNDepthwiseConv2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNDepthwiseConv2d();\n        fb_xnnpack._XNNNodeConv.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNMaxPooling2d = class XNNMaxPooling2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNMaxPooling2d();\n        fb_xnnpack._XNNPooling2D.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNMultiply = class XNNMultiply {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNMultiply();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNSubtract = class XNNSubtract {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNSubtract();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNFloor = class XNNFloor {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNFloor();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConvert = class XNNConvert {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConvert();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNGlobalAvgPooling2d = class XNNGlobalAvgPooling2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNGlobalAvgPooling2d();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNSquareRoot = class XNNSquareRoot {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNSquareRoot();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNCeiling = class XNNCeiling {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNCeiling();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNHardswish = class XNNHardswish {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNHardswish();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNMaximum = class XNNMaximum {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNMaximum();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNNegate = class XNNNegate {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNNegate();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNSquare = class XNNSquare {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNSquare();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNAbs = class XNNAbs {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNAbs();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNPReLU = class XNNPReLU {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNPReLU();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConcatenate2 = class XNNConcatenate2 {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConcatenate2();\n        fb_xnnpack._XNNCat.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConcatenate3 = class XNNConcatenate3 {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConcatenate3();\n        fb_xnnpack._XNNCat.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConcatenate4 = class XNNConcatenate4 {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConcatenate4();\n        fb_xnnpack._XNNCat.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNBatchMatrixMultiply = class XNNBatchMatrixMultiply {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNBatchMatrixMultiply();\n        fb_xnnpack._XNNNode2x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConcatenate5 = class XNNConcatenate5 {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConcatenate5();\n        fb_xnnpack._XNNCat.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNConvTranspose2d = class XNNConvTranspose2d {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNConvTranspose2d();\n        fb_xnnpack._XNNNodeConv.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNReciprocalSquareRoot = class XNNReciprocalSquareRoot {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNReciprocalSquareRoot();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNLog = class XNNLog {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNLog();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNGelu = class XNNGelu {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNGelu();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNTanh = class XNNTanh {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNTanh();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNExp = class XNNExp {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNExp();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNSin = class XNNSin {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNSin();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNCopy = class XNNCopy {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNCopy();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nfb_xnnpack.XNNCos = class XNNCos {\n\n    static decode(reader, position) {\n        const $ = new fb_xnnpack.XNNCos();\n        fb_xnnpack._XNNNode1x1.decode(reader, position, $);\n        return $;\n    }\n};\n\nvkgraph.OperatorCall = class OperatorCall {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.OperatorCall();\n        $.node_id = reader.uint32_(position, 4, 0);\n        $.name = reader.string_(position, 6, null);\n        $.args = reader.array(position, 8, Int32Array);\n        return $;\n    }\n};\n\nvkgraph.VkDataType = {\n    BOOL: 0, '0': 'BOOL',\n    UINT8: 1, '1': 'UINT8',\n    INT8: 2, '2': 'INT8',\n    INT32: 3, '3': 'INT32',\n    FLOAT16: 4, '4': 'FLOAT16',\n    FLOAT32: 5, '5': 'FLOAT32',\n    FLOAT64: 6, '6': 'FLOAT64',\n    INT64: 7, '7': 'INT64',\n    UNSET: 127, '127': 'UNSET'\n};\n\nvkgraph.VkStorageType = {\n    BUFFER: 0, '0': 'BUFFER',\n    TEXTURE_3D: 1, '1': 'TEXTURE_3D',\n    TEXTURE_2D: 2, '2': 'TEXTURE_2D',\n    DEFAULT_STORAGE: 255, '255': 'DEFAULT_STORAGE'\n};\n\nvkgraph.VkMemoryLayout = {\n    TENSOR_WIDTH_PACKED: 0, '0': 'TENSOR_WIDTH_PACKED',\n    TENSOR_HEIGHT_PACKED: 1, '1': 'TENSOR_HEIGHT_PACKED',\n    TENSOR_CHANNELS_PACKED: 2, '2': 'TENSOR_CHANNELS_PACKED',\n    PACKED_INT8_4W4C: 3, '3': 'PACKED_INT8_4W4C',\n    PACKED_INT8_4H4W: 4, '4': 'PACKED_INT8_4H4W',\n    PACKED_INT8_4W: 5, '5': 'PACKED_INT8_4W',\n    PACKED_INT8_4C: 6, '6': 'PACKED_INT8_4C',\n    PACKED_INT8_4C1W: 8, '8': 'PACKED_INT8_4C1W',\n    PACKED_INT8_CONV2D: 9, '9': 'PACKED_INT8_CONV2D',\n    DEFAULT_LAYOUT: 255, '255': 'DEFAULT_LAYOUT'\n};\n\nvkgraph.VkTensor = class VkTensor {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.VkTensor();\n        $.datatype = reader.int8_(position, 4, 0);\n        $.dims = reader.array(position, 6, Uint32Array);\n        $.constant_id = reader.int32_(position, 8, 0);\n        $.mem_obj_id = reader.int32_(position, 10, 0);\n        $.storage_type = reader.uint8_(position, 12, 255);\n        $.memory_layout = reader.uint8_(position, 14, 255);\n        $.staging_datatype = reader.int8_(position, 16, 127);\n        return $;\n    }\n};\n\nvkgraph.Null = class Null {\n\n    static decode(/* reader, position */) {\n        const $ = new vkgraph.Null();\n        return $;\n    }\n};\n\nvkgraph.Int = class Int {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.Int();\n        $.int_val = reader.int64_(position, 4, 0n);\n        return $;\n    }\n};\n\nvkgraph.Bool = class Bool {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.Bool();\n        $.bool_val = reader.bool_(position, 4, false);\n        return $;\n    }\n};\n\nvkgraph.Double = class Double {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.Double();\n        $.double_val = reader.float64_(position, 4, 0);\n        return $;\n    }\n};\n\nvkgraph.String = class String {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.String();\n        $.string_val = reader.string_(position, 4, null);\n        return $;\n    }\n};\n\nvkgraph.IntList = class IntList {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.IntList();\n        $.items = reader.int64s_(position, 4);\n        return $;\n    }\n};\n\nvkgraph.DoubleList = class DoubleList {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.DoubleList();\n        $.items = reader.array(position, 4, Float64Array);\n        return $;\n    }\n};\n\nvkgraph.BoolList = class BoolList {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.BoolList();\n        $.items = reader.bools_(position, 4);\n        return $;\n    }\n};\n\nvkgraph.ValueList = class ValueList {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.ValueList();\n        $.items = reader.array(position, 4, Int32Array);\n        return $;\n    }\n};\n\nvkgraph.SymInt = class SymInt {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.SymInt();\n        $.value = reader.int32_(position, 4, 0);\n        return $;\n    }\n};\n\nvkgraph.GraphTypes = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return vkgraph.Null.decode(reader, position);\n            case 2: return vkgraph.Int.decode(reader, position);\n            case 3: return vkgraph.Double.decode(reader, position);\n            case 4: return vkgraph.Bool.decode(reader, position);\n            case 5: return vkgraph.VkTensor.decode(reader, position);\n            case 6: return vkgraph.IntList.decode(reader, position);\n            case 7: return vkgraph.DoubleList.decode(reader, position);\n            case 8: return vkgraph.BoolList.decode(reader, position);\n            case 9: return vkgraph.ValueList.decode(reader, position);\n            case 10: return vkgraph.String.decode(reader, position);\n            case 11: return vkgraph.SymInt.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nvkgraph.VkValue = class VkValue {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.VkValue();\n        $.value = reader.union(position, 4, vkgraph.GraphTypes);\n        return $;\n    }\n};\n\nvkgraph.VkBytes = class VkBytes {\n\n    static decode(reader, position) {\n        const $ = new vkgraph.VkBytes();\n        $.offset = reader.uint64_(position, 4, 0n);\n        $.length = reader.uint64_(position, 6, 0n);\n        $.named_key = reader.string_(position, 8, null);\n        return $;\n    }\n};\n\nvkgraph.VkGraph = class VkGraph {\n\n    static identifier(reader) {\n        return reader.identifier === 'VK00';\n    }\n\n    static create(reader) {\n        return vkgraph.VkGraph.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new vkgraph.VkGraph();\n        $.version = reader.string_(position, 4, null);\n        $.chain = reader.tables(position, 6, vkgraph.OperatorCall);\n        $.values = reader.tables(position, 8, vkgraph.VkValue);\n        $.input_ids = reader.array(position, 10, Uint32Array);\n        $.output_ids = reader.array(position, 12, Uint32Array);\n        $.constants = reader.tables(position, 14, vkgraph.VkBytes);\n        $.shaders = reader.tables(position, 16, vkgraph.VkBytes);\n        $.storage_type_override = reader.uint8_(position, 18, 255);\n        $.memory_layout_override = reader.uint8_(position, 20, 255);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/executorch.js",
    "content": "\n// Experimental\n\nconst executorch = {};\nconst coreml = {};\nconst vulkan = {};\nconst xnnpack = {};\nconst qnn = {};\nconst ethosu = {};\nconst openvino = {};\nconst rockchip = {};\n\nimport * as base from './base.js';\nimport * as python from './python.js';\nimport * as pytorch from './pytorch.js';\n\nexecutorch.ModelFactory = class {\n\n    async match(context) {\n        const reader = await executorch.Reader.open(context);\n        if (reader) {\n            return context.set('executorch', reader);\n        }\n        return null;\n    }\n\n    async open(context) {\n        executorch.schema = await context.require('./executorch-schema');\n        const target = context.value;\n        await target.read();\n        return new executorch.Model(target);\n    }\n};\n\nexecutorch.Model = class {\n\n    constructor(target) {\n        this.format = `ExecuTorch v${target.program.version}`;\n        this.modules = [];\n        for (const plan of target.program.execution_plan) {\n            for (const chain of plan.chains) {\n                const graph = new executorch.Graph(target, plan, chain);\n                this.modules.push(graph);\n            }\n        }\n    }\n};\n\nexecutorch.Graph = class {\n\n    constructor(target, plan, chain) {\n        this.name = plan.name || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.tensors = (index, items) => {\n            const list = [];\n            for (let i = 0; i < items.length; i++) {\n                const item = items[i];\n                const type = item ? new executorch.TensorType(item) : null;\n                let initializer = null;\n                if (item && item.data_buffer_idx > 0) {\n                    initializer = new executorch.Tensor(item, target);\n                }\n                const identifier = items.length > 1 ? `${index}.${i}` : index.toString();\n                const value = new executorch.Value(identifier, type, initializer);\n                list.push(value);\n            }\n            return list;\n        };\n        values.map = (index, output) => {\n            if (!values.has(index)) {\n                const executorch_flatbuffer = executorch.schema.executorch_flatbuffer;\n                const val = plan.values[index].val;\n                const tensor = val instanceof executorch_flatbuffer.Tensor || val instanceof executorch_flatbuffer.TensorList || val instanceof executorch_flatbuffer.OptionalTensorList;\n                if (output && !tensor) {\n                    const value = [new executorch.Value(index.toString(), null, null)];\n                    values.set(index, { type: null, value });\n                } else if (val instanceof executorch_flatbuffer.Null) {\n                    values.set(index, { type: 'attribute', value: null });\n                } else if (val instanceof executorch_flatbuffer.Int) {\n                    values.set(index, { type: 'int64', value: val.int_val });\n                } else if (val instanceof executorch_flatbuffer.Bool) {\n                    values.set(index, { type: 'int64', value: val.bool_val });\n                } else if (val instanceof executorch_flatbuffer.Double) {\n                    values.set(index, { type: 'float64', value: val.double_val });\n                } else if (val instanceof executorch_flatbuffer.Tensor) {\n                    const items = [val];\n                    values.set(index, { type: null, value: values.tensors(index, items) });\n                } else if (val instanceof executorch_flatbuffer.String) {\n                    values.set(index, { type: 'string', value: val.string_val });\n                } else if (val instanceof executorch_flatbuffer.IntList) {\n                    const list = val.items.map((index) => plan.values[index].val.int_val);\n                    values.set(index, { type: 'int64[]', value: list });\n                } else if (val instanceof executorch_flatbuffer.DoubleList) {\n                    values.set(index, { type: 'float64[]', value: Array.from(val.items) });\n                } else if (val instanceof executorch_flatbuffer.BoolList) {\n                    throw new executorch.Error('executorch_flatbuffer.BoolList not implemented.');\n                } else if (val instanceof executorch_flatbuffer.TensorList) {\n                    const items = Array.from(val.items).map((arg) => arg === -1 ? null : plan.values[arg].val);\n                    values.set(index, { type: null, value: values.tensors(index, items) });\n                } else if (val instanceof executorch_flatbuffer.OptionalTensorList) {\n                    const items = Array.from(val.items).map((arg) => arg === -1 ? null : plan.values[arg].val);\n                    values.set(index, { type: null, value: values.tensors(index, items) });\n                } else {\n                    throw new Error(`Value type '${val.constructor.name}' not implemented.`);\n                }\n            }\n            return values.get(index);\n        };\n        for (let i = 0; i < plan.inputs.length; i++) {\n            const input = plan.inputs[i];\n            const value = values.map(input);\n            const name = plan.inputs.length === 1 ? 'input' : `input.${i}`;\n            const argument = new executorch.Argument(name, value.value, value.type);\n            this.inputs.push(argument);\n        }\n        for (let i = 0; i < plan.outputs.length; i++) {\n            const output = plan.outputs[i];\n            const value = values.map(output);\n            const name = plan.outputs.length === 1 ? 'output' : `output.${i}`;\n            const argument = new executorch.Argument(name, value.value, value.type);\n            this.outputs.push(argument);\n        }\n        for (const instruction of chain.instructions) {\n            const node = new executorch.Node(target, plan, chain, instruction, values);\n            this.nodes.push(node);\n        }\n    }\n};\n\nexecutorch.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nexecutorch.Value = class Value {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new executorch.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer && initializer.type ? initializer.type : type || null;\n        this.initializer = initializer;\n    }\n};\n\nexecutorch.Node = class {\n\n    constructor(target, plan, chain, instruction, values) {\n        this.name = '';\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const instr_args = instruction.instr_args;\n        const executorch_flatbuffer = executorch.schema.executorch_flatbuffer;\n        if (instr_args instanceof executorch_flatbuffer.KernelCall) {\n            const op = plan.operators[instr_args.op_index];\n            const name = op.name.split('::').pop();\n            const identifier = op.overload ? `${op.name}.${op.overload}` : op.name;\n            const torch = target.execution.__import__('torch');\n            const schemas = torch._C._jit_get_schemas_for_operator(op.name);\n            const schema = schemas.find((schema) => schema.name === op.name && schema.overload_name === op.overload);\n            if (!schema) {\n                throw new executorch.Error(`Operator schema for '${identifier}' not found.`);\n            }\n            const category = schema && schema.category ? schema.category : '';\n            const alias = (arg) => arg && arg.alias_info && arg.alias_info.before_set.length === 1 ? arg.alias_info.before_set[0] : null;\n            const outputs = new Set(schema && Array.isArray(schema.returns) ? schema.returns.map((arg) => alias(arg)).filter((alias) => alias !== null) : []);\n            const inputs = new Map();\n            this.type = { name, identifier, category };\n            let i = 0;\n            const args = instr_args.args;\n            for (; i < schema.arguments.length; i++) {\n                const index = args[i];\n                const arg = schema && i < schema.arguments.length ? schema.arguments[i] : null;\n                const output = arg ? alias(schema.arguments[i]) : null;\n                if (output && outputs.has(output)) {\n                    inputs.set(output, index);\n                    continue;\n                }\n                const name = arg ? arg.name : i.toString();\n                const value = values.map(index);\n                const argument = new executorch.Argument(name, value.value, value.type);\n                this.inputs.push(argument);\n            }\n            for (let j = 0; j < schema.returns.length; j++) {\n                const ret = schema.returns[j];\n                const output = alias(ret);\n                let index = args[i++];\n                index = output && inputs.has(output) ? inputs.get(output) : index;\n                const name = ret.name;\n                const value = values.map(index, true);\n                const argument = new executorch.Argument(name || '', value.value, value.type);\n                this.outputs.push(argument);\n            }\n        } else if (instr_args instanceof executorch_flatbuffer.DelegateCall) {\n            const delegate = plan.delegates[instr_args.delegate_index];\n            const args = instr_args.args;\n            if (!delegate.backend || !delegate.backend.type) {\n                throw new executorch.Error(`ExecuTorch delegate '${delegate.id}' not implemented.`);\n            }\n            this.type = delegate.backend.type;\n            const inputs = args.slice(0, this.type.inputs.length);\n            for (let i = 0; i < inputs.length; i++) {\n                const input = inputs[i];\n                const value = values.map(input);\n                const name = inputs.length === 1 ? 'input' : `input.${i}`;\n                const argument = new executorch.Argument(name, value.value, value.type);\n                this.inputs.push(argument);\n            }\n            const outputs = args.slice(this.type.inputs.length, this.type.inputs.length + this.type.outputs.length);\n            for (let i = 0; i < outputs.length; i++) {\n                const output = outputs[i];\n                const value = values.map(output);\n                const name = outputs.length === 1 ? 'output' : `output.${i}`;\n                const argument = new executorch.Argument(name, value.value, value.type);\n                this.outputs.push(argument);\n            }\n            for (const spec of delegate.compile_specs) {\n                const value = spec.value instanceof Uint8Array ? new TextDecoder('utf-8').decode(spec.value) : spec.value;\n                const attribute = new executorch.Argument(spec.key, value, 'attribute');\n                this.attributes.push(attribute);\n            }\n        } else {\n            throw new Error(`Instruction type '${instr_args.constructor.name}' not implemented.`);\n        }\n    }\n};\n\nexecutorch.TensorType = class {\n\n    constructor(tensor) {\n        const ScalarType = executorch.schema.executorch_flatbuffer.ScalarType;\n        switch (tensor.scalar_type) {\n            case ScalarType.BYTE: this.dataType = 'uint8'; break;\n            case ScalarType.CHAR: this.dataType = 'int8'; break;\n            case ScalarType.SHORT: this.dataType = 'int16'; break;\n            case ScalarType.INT: this.dataType = 'int32'; break;\n            case ScalarType.LONG: this.dataType = 'int64'; break;\n            case ScalarType.HALF: this.dataType = 'float16'; break;\n            case ScalarType.FLOAT: this.dataType = 'float32'; break;\n            case ScalarType.DOUBLE: this.dataType = 'float64'; break;\n            case ScalarType.BFLOAT16: this.dataType = 'bfloat16'; break;\n            case 8: this.dataType = 'complex<float16>'; break;\n            case 9: this.dataType = 'complex<float32>'; break;\n            case 10: this.dataType = 'complex<float64>'; break;\n            case ScalarType.BOOL: this.dataType = 'boolean'; break;\n            case ScalarType.QINT8: this.dataType = 'qint8'; break;\n            case ScalarType.QUINT8: this.dataType = 'quint8'; break;\n            case ScalarType.QINT32: this.dataType = 'qint32'; break;\n            case 15: this.dataType = 'bfloat16'; break;\n            case ScalarType.QUINT4X2: this.dataType = 'quint4x2'; break;\n            case ScalarType.QUINT2X4: this.dataType = 'quint2x4'; break;\n            case 18: this.dataType = 'bits1x8'; break;\n            case 19: this.dataType = 'bits2x4'; break;\n            case 20: this.dataType = 'bits4x2'; break;\n            case 21: this.dataType = 'bits8'; break;\n            case ScalarType.BITS16: this.dataType = 'bits16'; break;\n            case ScalarType.FLOAT8E5M2: this.dataType = 'float8e5m2'; break;\n            case ScalarType.FLOAT8E4M3FN: this.dataType = 'float8e4m3fn'; break;\n            case ScalarType.FLOAT8E5M2FNUZ: this.dataType = 'float8e5m2fnuz'; break;\n            case ScalarType.FLOAT8E4M3FNUZ: this.dataType = 'float8e4m3fnuz'; break;\n            case ScalarType.UINT16: this.dataType = 'uint16'; break;\n            case ScalarType.UINT32: this.dataType = 'uint32'; break;\n            case ScalarType.UINT64: this.dataType = 'uint64'; break;\n            default: throw new executorch.Error(`Unknown tensor data type '${tensor.scalar_type}'.`);\n        }\n        this.shape = new executorch.TensorShape(Array.from(tensor.sizes));\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nexecutorch.TensorShape = class {\n\n    constructor(dimensions = []) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nexecutorch.Tensor = class {\n\n    constructor(tensor, target) {\n        this.type = new executorch.TensorType(tensor);\n        const data_buffer_idx = tensor.data_buffer_idx;\n        const program = target.program;\n        if (tensor.extra_tensor_info) {\n            throw new executorch.Error('Extra tensor info not implemented.');\n        } else if (Array.isArray(program.constant_buffer) && program.constant_buffer.length > 0) {\n            if (data_buffer_idx >= program.constant_buffer.length) {\n                throw new executorch.Error(`Constant buffer index out of range.`);\n            }\n            const buffer = program.constant_buffer[data_buffer_idx];\n            this.values = buffer.storage;\n            this.encoding = '<';\n        } else if (tensor.allocation_info === null) {\n            const constant_segment = program.constant_segment;\n            const data_segment = program.segments[constant_segment.segment_index];\n            const offset = constant_segment.offsets[data_buffer_idx];\n            let next = data_segment.size;\n            if (data_buffer_idx + 1 < constant_segment.offsets.length) {\n                next = constant_segment.offsets[data_buffer_idx + 1];\n            }\n            const size = next - offset;\n            const position = data_segment.offset + offset;\n            this.values = target.blob(position.toNumber(), size.toNumber());\n            this.encoding = '<';\n        } else {\n            throw new executorch.Error('Tensor allocation info not implemented.');\n        }\n    }\n};\n\nexecutorch.Reader = class {\n\n    static async open(context) {\n        const reader = await context.peek('flatbuffers.binary');\n        if (reader && reader.identifier === 'ET12') {\n            return new executorch.Reader(context, reader);\n        }\n        return null;\n    }\n\n    constructor(context, reader) {\n        this.context = context;\n        this.reader = reader;\n    }\n\n    async read() {\n        const context = this.context;\n        this.metadata = await pytorch.Metadata.open(context);\n        this.execution = new python.Execution();\n        this.metadata.register(this.execution);\n        const executorch_flatbuffer = executorch.schema.executorch_flatbuffer;\n        this.program = executorch_flatbuffer.Program.create(this.reader);\n        this.named_data = new Map();\n        if (this.program.named_data) {\n            this.named_data = new Map(this.program.named_data.map((entry) => [entry.key, entry.segment_index]));\n        }\n        this.reader = await context.read('binary');\n        if (this.reader.length >= 32) {\n            this.reader.seek(8);\n            const magic = String.fromCharCode(...this.reader.read(4));\n            if (magic === 'eh00') {\n                this.extended_file_header = {\n                    length: this.reader.uint32(),\n                    program_size: this.reader.uint64(),\n                    segment_base_offset: this.reader.uint64(),\n                };\n            }\n            this.reader.seek(0);\n        }\n        for (const plan of this.program.execution_plan) {\n            for (const chain of plan.chains) {\n                for (const instruction of chain.instructions) {\n                    const instr_args = instruction.instr_args;\n                    if (instr_args instanceof executorch_flatbuffer.DelegateCall) {\n                        const delegate = plan.delegates[instr_args.delegate_index];\n                        if (delegate.backend) {\n                            continue;\n                        }\n                        let data = null;\n                        switch (delegate.processed.location) {\n                            case executorch_flatbuffer.DataLocation.INLINE: {\n                                data = this.program.backend_delegate_data[delegate.processed.index].data;\n                                break;\n                            }\n                            case executorch_flatbuffer.DataLocation.SEGMENT: {\n                                const segment = this.program.segments[delegate.processed.index];\n                                const offset = segment.offset;\n                                const size = segment.size;\n                                data = this.blob(offset.toNumber(), size.toNumber());\n                                break;\n                            }\n                            default: {\n                                throw new executorch.Error(`Delegate data location '${delegate.processed.location}' not implemented.`);\n                            }\n                        }\n                        switch (delegate.id) {\n                            case 'XnnpackBackend':\n                                delegate.backend = xnnpack.Reader.open(data, this);\n                                break;\n                            case 'CoreMLBackend':\n                                delegate.backend = coreml.Reader.open(data, this);\n                                break;\n                            case 'VulkanBackend':\n                                delegate.backend = vulkan.Reader.open(data, this);\n                                break;\n                            case 'QnnBackend':\n                                delegate.backend = qnn.Reader.open(data, this);\n                                break;\n                            case 'EthosUBackend':\n                                delegate.backend = ethosu.Reader.open(data, this);\n                                break;\n                            case 'OpenvinoBackend':\n                                delegate.backend = openvino.Reader.open(data, this);\n                                break;\n                            case 'RockchipBackend':\n                                delegate.backend = rockchip.Reader.open(data, this);\n                                break;\n                            default:\n                                throw new executorch.Error(`ExecuTorch delegate '${delegate.id}' not implemented.`);\n                        }\n                        /* eslint-disable no-await-in-loop */\n                        await delegate.backend.read();\n                        /* eslint-enable no-await-in-loop */\n                    }\n                }\n            }\n        }\n    }\n\n    blob(offset, size) {\n        if (this.extended_file_header) {\n            const segment_base_offset = this.extended_file_header.segment_base_offset;\n            this.reader.seek(segment_base_offset.toNumber() + offset);\n            const data = this.reader.read(size);\n            this.reader.seek(0);\n            return data;\n        }\n        return null;\n    }\n\n    segment(key) {\n        if (this.named_data.has(key)) {\n            const segment_index = this.named_data.get(key);\n            if (segment_index >= 0 && segment_index < this.program.segments.length) {\n                const segment = this.program.segments[segment_index];\n                const offset = segment.offset;\n                const size = segment.size;\n                return this.blob(offset.toNumber(), size.toNumber());\n            }\n        }\n        return null;\n    }\n};\n\nexecutorch.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading ExecuTorch model.';\n    }\n};\n\nxnnpack.Reader = class {\n\n    static open(data, target) {\n        if (data.length >= 30) {\n            const reader = base.BinaryReader.open(data);\n            reader.skip(4);\n            const magic = String.fromCharCode(...reader.read(4));\n            if (magic === 'XH00') {\n                return new xnnpack.Reader(reader, target);\n            }\n        }\n        return null;\n    }\n\n    constructor(reader, target) {\n        this.reader = reader;\n        this.target = target;\n        reader.skip(2);\n        this.flatbuffer = {\n            offset: reader.uint32(),\n            size: reader.uint32(),\n        };\n        this.constants = {\n            offset: reader.uint32(),\n            size: reader.uint32(),\n        };\n    }\n\n    async read() {\n        this.reader.seek(this.flatbuffer.offset);\n        const flatbuffers = await import('./flatbuffers.js');\n        const data = this.reader.read(this.flatbuffer.size);\n        const reader = flatbuffers.BinaryReader.open(data);\n        if (!executorch.schema.fb_xnnpack.XNNGraph.identifier(reader)) {\n            throw new xnnpack.Error('Invalid XNNPACK data.');\n        }\n        this.graph = executorch.schema.fb_xnnpack.XNNGraph.create(reader);\n        this.reader.seek(0);\n        const metadata = new xnnpack.Metadata();\n        this.type = new xnnpack.Graph(metadata, this.graph, this);\n    }\n\n    constant(idx) {\n        const constant_data = this.graph.constant_data[idx];\n        const named_key = constant_data.named_key;\n        if (named_key) {\n            return this.target.segment(named_key);\n        }\n        const offset = constant_data.offset;\n        const size = constant_data.size;\n        this.reader.seek(this.constants.offset + offset.toNumber());\n        const data = this.reader.read(size.toNumber());\n        this.reader.seek(0);\n        return data;\n    }\n};\n\nxnnpack.Graph = class {\n\n    constructor(metadata, graph, reader) {\n        this.name = 'XnnpackBackend';\n        this.type = 'graph';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.map = (id) => {\n            if (!values.has(id)) {\n                const fb_xnnpack = executorch.schema.fb_xnnpack;\n                const name = id.toString();\n                const xvalue = graph.xvalues[id].xvalue_union;\n                if (xvalue instanceof fb_xnnpack.XNNTensorValue) {\n                    const type = new xnnpack.TensorType(xvalue);\n                    const initializer = xvalue.constant_buffer_idx === 0 ? null : new xnnpack.Tensor(xvalue, reader);\n                    const value = new xnnpack.Value(name, type, initializer);\n                    values.set(id, value);\n                } else if (xvalue instanceof fb_xnnpack.XNNQuantizedTensorValue) {\n                    const value = new xnnpack.Value(name, null, null);\n                    values.set(id, value);\n                } else {\n                    throw new xnnpack.Error(`Value type '${xvalue.constructor.name}' not implemented.`);\n                }\n            }\n            return values.get(id);\n        };\n        for (let i = 0; i < graph.input_ids.length; i++) {\n            const id = graph.input_ids[i];\n            const value = values.map(id);\n            const name = graph.input_ids.length === 1 ? 'input' : `input.${i}`;\n            const argument = new xnnpack.Argument(name, [value]);\n            this.inputs.push(argument);\n        }\n        for (let i = 0; i < graph.output_ids.length; i++) {\n            const id = graph.output_ids[i];\n            const value = values.map(id);\n            const name = graph.output_ids.length === 1 ? 'output' : `output.${i}`;\n            const argument = new xnnpack.Argument(name, [value]);\n            this.outputs.push(argument);\n        }\n        for (const xnode of graph.xnodes) {\n            const node = new xnnpack.Node(metadata, xnode, values);\n            this.nodes.push(node);\n        }\n    }\n};\n\nxnnpack.Node = class {\n\n    constructor(metadata, xnode, values) {\n        const node = xnode.xnode_union;\n        this.type = metadata.type(node.constructor.name) || { name: node.constructor.name };\n        this.name = '';\n        this.inputs = [];\n        this.outputs = [];\n        for (const [name, obj] of Object.entries(node)) {\n            let value = ArrayBuffer.isView(obj) ? Array.from(obj) : obj;\n            let type = 'attribute';\n            if (name.endsWith('_id')) {\n                value = obj === -1 || obj === 0xFFFFFFFF ? [] : [values.map(obj)];\n                type = null;\n            }\n            const argument = new xnnpack.Argument(name, value, type);\n            if (name === 'output_id') {\n                this.outputs.push(argument);\n            } else {\n                this.inputs.push(argument);\n            }\n        }\n    }\n};\n\nxnnpack.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nxnnpack.Value = class Value {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new executorch.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer && initializer.type ? initializer.type : type || null;\n        this.initializer = initializer;\n    }\n};\n\nxnnpack.Metadata = class {\n\n    constructor() {\n        this._types = new Map();\n        this.register('_XNNCat', 'Tensor');\n        this.register('_XNNNodeConv', 'Layer');\n        this.register('XNNArgMaxPooling2d', 'Pool');\n        this.register('XNNAvgPooling2d', 'Pool');\n        this.register('XNNCeiling', 'Activation');\n        this.register('XNNConcatenate2', 'Tensor');\n        this.register('XNNConcatenate3', 'Tensor');\n        this.register('XNNConcatenate4', 'Tensor');\n        this.register('XNNConcatenate5', 'Tensor');\n        this.register('XNNConv2d', 'Layer');\n        this.register('XNNConvTranspose2d', 'Layer');\n        this.register('XNNDepthwiseConv2d', 'Layer');\n        this.register('XNNELU', 'Activation');\n        this.register('XNNFullyConnected', 'Layer');\n        this.register('XNNGelu', 'Activation');\n        this.register('XNNGlobalAvgPooling2d', 'Pool');\n        this.register('XNNGlobalAvgPooling2d', 'Pool');\n        this.register('XNNHardswish', 'Activation');\n        this.register('XNNLeakyReLU', 'Activation');\n        this.register('XNNMaxPooling2d', 'Pool');\n        this.register('XNNPReLU', 'Activation');\n        this.register('XNNSigmoid', 'Activation');\n        this.register('XNNSoftmax', 'Activation');\n        this.register('XNNTanh', 'Activation');\n        this.register('XNNStaticTranspose', 'Transform');\n    }\n\n    register(name, category) {\n        this._types.set(name, { name, category });\n    }\n\n    type(name) {\n        return this._types.get(name);\n    }\n};\n\nxnnpack.TensorType = class {\n\n    constructor(tensor) {\n        xnnpack.TensorType._types = executorch.TensorType._types || [\n            'invalid', 'float32', 'float16',\n            'qint8', 'quint8', 'qint32',\n            'qcint8', 'qcint32', 'qcint4',\n            'qdint8', 'qbint4', 'qpint8',\n            'int32', 'pfp32', 'bfloat16'\n        ];\n        if (tensor.datatype >= xnnpack.TensorType._types.length) {\n            throw new xnnpack.Error(`Unknown tensor data type '${tensor.datatype}'.`);\n        }\n        this.dataType = xnnpack.TensorType._types[tensor.datatype];\n        this.shape = new xnnpack.TensorShape(Array.from(tensor.dims));\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nxnnpack.TensorShape = class {\n\n    constructor(dimensions = []) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nxnnpack.Tensor = class {\n\n    constructor(tensor, reader) {\n        this.type = new xnnpack.TensorType(tensor);\n        this.values = reader.constant(tensor.constant_buffer_idx);\n        this.encoding = '<';\n    }\n};\n\nxnnpack.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading XNNPACK model.';\n    }\n};\n\nvulkan.Reader = class {\n\n    static open(data, target) {\n        if (data.length >= 30) {\n            const reader = base.BinaryReader.open(data);\n            reader.skip(4);\n            const magic = String.fromCharCode(...reader.read(4));\n            if (magic === 'VH00') {\n                return new vulkan.Reader(reader, target);\n            }\n        }\n        return null;\n    }\n\n    constructor(reader, target) {\n        this.reader = reader;\n        this.target = target;\n        reader.skip(2);\n        this.flatbuffer = {\n            offset: reader.uint32(),\n            size: reader.uint32(),\n        };\n        this.constants = {\n            offset: reader.uint32(),\n            size: reader.uint32(),\n        };\n    }\n\n    async read() {\n        this.reader.seek(this.flatbuffer.offset);\n        const metadata = new vulkan.Metadata(this.target.execution);\n        metadata.register('conv_with_clamp(Tensor input, Tensor weight, Tensor? bias, SymInt[] stride, SymInt[] padding, SymInt[] dilation, bool transposed, SymInt[] output_padding, SymInt groups, Scalar? output_min, Scalar? output_max) -> Tensor)');\n        const flatbuffers = await import('./flatbuffers.js');\n        const data = this.reader.read(this.flatbuffer.size);\n        const reader = flatbuffers.BinaryReader.open(data);\n        if (!executorch.schema.vkgraph.VkGraph.identifier(reader)) {\n            throw new xnnpack.Error('Invalid Vuklan data.');\n        }\n        this.graph = executorch.schema.vkgraph.VkGraph.create(reader);\n        this.reader.seek(0);\n        this.type = new vulkan.Graph(metadata, this.graph, this);\n    }\n\n    constant(id) {\n        const constant = this.graph.constants[id];\n        const offset = constant.offset;\n        const length = constant.length;\n        this.reader.seek(this.constants.offset + offset.toNumber());\n        const data = this.reader.read(length.toNumber());\n        this.reader.seek(0);\n        return data;\n    }\n};\n\nvulkan.Graph = class {\n\n    constructor(metadata, graph, reader) {\n        this.name = 'VulkanBackend';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.map = (id) => {\n            if (!values.has(id)) {\n                const vkgraph = executorch.schema.vkgraph;\n                const arg = graph.values[id].value;\n                if (arg instanceof vkgraph.VkTensor) {\n                    const type = new vulkan.TensorType(arg);\n                    const initializer = arg.constant_id === -1 ? null : new vulkan.Tensor(arg, reader);\n                    const value = new vulkan.Value(id.toString(), type, initializer);\n                    values.set(id, { type: null, value: [value] });\n                } else if (arg instanceof vkgraph.Int) {\n                    values.set(id, { type: 'int64', value: arg.int_val });\n                } else if (arg instanceof vkgraph.IntList) {\n                    values.set(id, { type: 'int64[]', value: Array.from(arg.items) });\n                } else if (arg instanceof vkgraph.Double) {\n                    values.set(id, { type: 'float64', value: arg.double_val });\n                } else if (arg instanceof vkgraph.Bool) {\n                    values.set(id, { type: 'boolean', value: arg.bool_val });\n                } else if (arg instanceof vkgraph.Null) {\n                    values.set(id, { type: 'attribute', value: null });\n                } else {\n                    throw new Error(`Value type '${arg.constructor.name}' not implemented.`);\n                }\n            }\n            return values.get(id);\n        };\n        for (let i = 0; i < graph.input_ids.length; i++) {\n            const id = graph.input_ids[i];\n            const value = values.map(id);\n            const name = graph.input_ids.length === 1 ? 'input' : `input.${i}`;\n            const argument = new vulkan.Argument(name, value.value, value.type);\n            this.inputs.push(argument);\n        }\n        for (let i = 0; i < graph.output_ids.length; i++) {\n            const id = graph.output_ids[i];\n            const value = values.map(id);\n            const name = graph.output_ids.length === 1 ? 'output' : `output.${i}`;\n            const argument = new vulkan.Argument(name, value.value, value.type);\n            this.outputs.push(argument);\n        }\n        for (const op of graph.chain) {\n            const node = new vulkan.Node(metadata, op, values);\n            this.nodes.push(node);\n        }\n    }\n};\n\nvulkan.Node = class {\n\n    constructor(metadata, op, values) {\n        const schema = metadata.type(op.name);\n        if (!schema) {\n            throw new vulkan.Error(`Operator schema for '${op.name}' not found.`);\n        }\n        this.type = {\n            name: op.name.split(/\\.([^.]*)$/)[0],\n            identifier: op.name,\n            category: schema.category || ''\n        };\n        this.name = op.node_id.toString();\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        for (let i = 0; i < op.args.length; i++) {\n            const arg = op.args[i];\n            const input = schema && i < schema.arguments.length;\n            const def = input ? schema.arguments[i] : schema.returns[i - schema.arguments.length];\n            const value = values.map(arg);\n            const argument = new vulkan.Argument(def.name || '', value.value, value.type);\n            if (input) {\n                this.inputs.push(argument);\n            } else {\n                this.outputs.push(argument);\n            }\n        }\n\n    }\n};\n\nvulkan.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nvulkan.Value = class Value {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new executorch.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer && initializer.type ? initializer.type : type || null;\n        this.initializer = initializer;\n    }\n};\n\nvulkan.TensorType = class {\n\n    constructor(tensor) {\n        const types = ['bool', 'uint8', 'int8', 'int32', 'float16', 'float32', 'float64', 'int64'];\n        if (tensor.datatype >= types.length) {\n            throw new vulkan.Error(`Unknown tensor data type '${tensor.datatype}'.`);\n        }\n        this.dataType = types[tensor.datatype];\n        this.shape = new vulkan.TensorShape(Array.from(tensor.dims));\n        const vkgraph = executorch.schema.vkgraph;\n        if (tensor.memory_layout !== vkgraph.VkMemoryLayout.DEFAULT_LAYOUT) {\n            this.denotation = vkgraph.VkMemoryLayout[tensor.memory_layout];\n            if (!this.denotation) {\n                throw new vulkan.Error(`Unsupported memory layout '${tensor.memory_layout}'.`);\n            }\n        }\n        if (tensor.storage_type !== vkgraph.VkStorageType.DEFAULT_STORAGE) {\n            this.layout = vkgraph.VkStorageType[tensor.storage_type];\n            if (!this.layout) {\n                throw new vulkan.Error(`Unsupported storage type '${tensor.storage_type}'.`);\n            }\n        }\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nvulkan.TensorShape = class {\n\n    constructor(dimensions = []) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nvulkan.Tensor = class {\n\n    constructor(tensor, reader) {\n        this.type = new vulkan.TensorType(tensor);\n        this.values = reader.constant(tensor.constant_id);\n        this.encoding = '<';\n    }\n};\n\nvulkan.Metadata = class {\n\n    constructor(execution) {\n        this.execution = execution;\n    }\n\n    register(signature) {\n        const torch = this.execution.__import__('torch');\n        const registry = torch._C.getRegistry();\n        const schema = torch.FunctionSchema.parse(signature);\n        const op = new torch._C.Operator(schema);\n        registry.registerOperator(op);\n    }\n\n    type(identifier) {\n        identifier = identifier.split(/\\.([^.]*)$/);\n        const name = identifier[0].replace('.', '::');\n        const overload = identifier[1] === 'default' ? '' : identifier[1];\n        const torch = this.execution.__import__('torch');\n        const schemas = torch._C._jit_get_schemas_for_operator(name);\n        const schema = schemas.find((schema) => schema.name === name && schema.overload_name === overload);\n        return schema;\n    }\n};\n\nvulkan.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Vulkan model.';\n    }\n};\n\ncoreml.Reader = class {\n\n    static open(data, target) {\n        const reader = base.BinaryReader.open(data);\n        return new coreml.Reader(reader, target);\n    }\n\n    constructor(reader, target) {\n        this.reader = reader;\n        this.target = target;\n    }\n\n    async factory() {\n        const coreml = await import('./coreml.js');\n        return new coreml.ModelFactory();\n    }\n\n    async read() {\n        const entries = this.entries(this.reader);\n        const factory = await this.factory();\n        const protobuf = await import('./protobuf.js');\n        for (const [key, value] of entries) {\n            const path = key.split('/');\n            const identifier = path.pop();\n            const folder = path.length === 0 ? '' : `${path.join('/')}/`;\n            const locals = new Map(Array.from(entries).filter(([key]) => key.startsWith(folder)).map(([key, value]) => [key.substring(folder.length), value]));\n            const context = new coreml.Context(this, identifier, value, locals, protobuf);\n            /* eslint-disable no-await-in-loop */\n            const type = await factory.match(context);\n            /* eslint-enable no-await-in-loop */\n            if (type === 'coreml.manifest') {\n                /* eslint-disable no-await-in-loop */\n                const model = await factory.open(context);\n                /* eslint-enable no-await-in-loop */\n                [this.type] = model.modules;\n                this.type.name = 'CoreMLBackend';\n                return;\n            }\n        }\n    }\n\n    stream(offset, size) {\n        this.reader.seek(offset);\n        const stream = this.reader.stream(size);\n        this.reader.seek(0);\n        return stream;\n    }\n\n    entries(reader) {\n        const files = new Map();\n        reader.seek(reader.length - 1);\n        const str = [];\n        let depth = 0;\n        do {\n            const c = String.fromCharCode(reader.byte());\n            reader.skip(-2);\n            if (c === '{') {\n                depth++;\n            } else if (c === '}') {\n                depth--;\n            }\n            str.push(c);\n        } while (depth > 0);\n        const metadata = JSON.parse(str.join(''));\n        const nodes = metadata.nodes;\n        const roots = Array.from(nodes);\n        for (const root of roots) {\n            if (root !== null) {\n                for (const index of Object.values(root.children)) {\n                    roots[index] = null;\n                }\n            }\n        }\n        const process = (path, node) => {\n            path = path ? `${path}/${node.name}` : node.name;\n            if (node.kind === 0) {\n                files.set(path, node.dataRegion);\n            } else if (node.kind === 1) {\n                for (const index of Object.values(node.children)) {\n                    process(path, nodes[index]);\n                }\n            } else {\n                throw new Error(`Node kind '${node.kind}' not implemented.`);\n            }\n        };\n        for (const root of roots.filter((node) => node !== null)) {\n            process('', root);\n        }\n        return files;\n    }\n};\n\ncoreml.Context = class {\n\n    constructor(reader, identifier, location, entries, protobuf) {\n        this._reader = reader;\n        this._location = location;\n        this._identifier = identifier;\n        this._entries = entries;\n        this._protobuf = protobuf;\n    }\n\n    get identifier() {\n        return this._identifier;\n    }\n\n    get stream() {\n        if (!this._stream) {\n            this._stream = this._reader.stream(this._location.offset, this._location.size);\n        }\n        return this._stream;\n    }\n\n    async tags(type) {\n        if (type === 'pb' && this.identifier.endsWith('.mlmodel')) {\n            return new Map([[1,0],[2,2]]);\n        }\n        return new Map();\n    }\n\n    async peek(type) {\n        if (type === 'json') {\n            const data = this.stream.peek();\n            const decoder = new TextDecoder('utf-8');\n            const text = decoder.decode(data);\n            return JSON.parse(text);\n        }\n        return null;\n    }\n\n    async read(type) {\n        if (type === 'protobuf.binary') {\n            return this._protobuf.BinaryReader.open(this.stream);\n        }\n        return null;\n    }\n\n    async fetch(file) {\n        if (this._entries.has(file)) {\n            const location = this._entries.get(file);\n            const identifier = file.split('/').pop();\n            return new coreml.Context(this._reader, identifier, location, this._entries, this._protobuf);\n        }\n        return null;\n    }\n\n    async require(id) {\n        return this._reader.target.context.require(id);\n    }\n\n    async metadata(name) {\n        return this._reader.target.context.metadata(name);\n    }\n\n    set(type, value) {\n        this.type = type;\n        this.value = value;\n        return type;\n    }\n};\n\nqnn.Reader = class {\n\n    static open(data, target) {\n        if (data.length >= 20) {\n            const reader = base.BinaryReader.open(data);\n            const magic = reader.uint32();\n            if (magic === 0x5678ABCD) {\n                return new qnn.Reader(reader, target);\n            }\n        }\n        return null;\n    }\n\n    constructor(reader, target) {\n        this.reader = reader;\n        this.target = target;\n        this.signature = reader.uint64();\n        this.size = reader.uint64();\n    }\n\n    async read() {\n        // https://github.com/pytorch/executorch/blob/main/backends/qualcomm/runtime/backends/QnnCustomProtocol.h\n        throw new executorch.Error('QNN backend not implemented.');\n    }\n};\n\nqnn.Graph = class {\n\n    constructor() {\n        this.name = 'QnnBackend';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n    }\n};\n\nethosu.Reader = class {\n\n    static open(data /* , target */) {\n        if (data.length >= 32) {\n            const reader = base.BinaryReader.open(data);\n            const magicBuffer = reader.read(16);\n            const magic = String.fromCharCode(...magicBuffer).replace(/\\0/g, '');\n            if (magic === 'vela_bin_stream') {\n                return new ethosu.Reader(reader, data.length);\n            }\n        }\n        return null;\n    }\n\n    constructor(reader, size) {\n        this.reader = reader;\n        this.size = size;\n    }\n\n    async read() {\n        this.reader.seek(0);\n        const blocks = new Map();\n        while (this.reader.position < this.size) {\n            const nameBuffer = this.reader.read(16);\n            const name = String.fromCharCode(...nameBuffer).replace(/\\0/g, '');\n            const size = this.reader.uint32();\n            this.reader.skip(12);\n            const data = this.reader.read(size);\n            blocks.set(name, data);\n            const padding = (16 - (size % 16)) % 16;\n            this.reader.skip(padding);\n            if (name === 'vela_end_stream') {\n                break;\n            }\n        }\n        const args = (data) => {\n            if (data && data.length >= 4) {\n                const reader = base.BinaryReader.open(data);\n                const count = reader.int32();\n                const arg = [];\n                for (let i = 0; i < count; i++) {\n                    const shape = [];\n                    for (let j = 0; j < 6; j++) {\n                        shape.push(reader.int32());\n                    }\n                    const elem_size = reader.int32();\n                    const offset = reader.int32();\n                    const region = reader.int32();\n                    arg.push({ shape, elem_size, offset, region });\n                }\n                return arg;\n            }\n            return [];\n        };\n        const inputs = args(blocks.get('inputs'));\n        const outputs = args(blocks.get('outputs'));\n        this.type = new ethosu.Graph(inputs, outputs);\n    }\n};\n\nethosu.Graph = class {\n\n    constructor(inputs, outputs) {\n        this.name = 'EthosUBackend';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        for (let i = 0; i < inputs.length; i++) {\n            const input = inputs[i];\n            const type = new ethosu.TensorType(input);\n            const value = new ethosu.Value(i.toString(), type, null);\n            const name = inputs.length === 1 ? 'input' : `input.${i}`;\n            const argument = new ethosu.Argument(name, [value]);\n            this.inputs.push(argument);\n        }\n        for (let i = 0; i < outputs.length; i++) {\n            const output = outputs[i];\n            const type = new ethosu.TensorType(output);\n            const value = new ethosu.Value((inputs.length + i).toString(), type, null);\n            const name = outputs.length === 1 ? 'output' : `output.${i}`;\n            const argument = new ethosu.Argument(name, [value]);\n            this.outputs.push(argument);\n        }\n    }\n};\n\nethosu.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nethosu.Value = class Value {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new executorch.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer && initializer.type ? initializer.type : type || null;\n        this.initializer = initializer;\n    }\n};\n\nethosu.TensorType = class {\n\n    constructor(io) {\n        switch (io.elem_size) {\n            case 1: this.dataType = 'int8'; break;\n            case 2: this.dataType = 'int16'; break;\n            case 4: this.dataType = 'int32'; break;\n            default: this.dataType = `?${io.elem_size}`; break;\n        }\n        const shape = io.shape.filter((dim, index) => dim !== 1 || index === io.shape.length - 1 || io.shape.slice(index).some((d) => d !== 1));\n        this.shape = new ethosu.TensorShape(shape.length > 0 ? shape : [1]);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nethosu.TensorShape = class {\n\n    constructor(dimensions = []) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nethosu.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Ethos-U model.';\n    }\n};\n\nopenvino.Reader = class {\n\n    static open(data /* , target */) {\n        return new openvino.Reader(data);\n    }\n\n    constructor(data) {\n        this.data = data;\n    }\n\n    async read() {\n        throw new executorch.Error('OpenVINO backend not implemented.');\n    }\n};\n\nopenvino.Graph = class {\n\n    constructor() {\n        this.name = 'OpenvinoBackend';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n    }\n};\n\nrockchip.Reader = class {\n\n    static open(data /* , target */) {\n        return new rockchip.Reader(data);\n    }\n\n    constructor(data) {\n        this.data = data;\n    }\n\n    async read() {\n        throw new executorch.Error('Rockchip backend not implemented.');\n    }\n};\n\nrockchip.Graph = class {\n\n    constructor() {\n        this.name = 'RockchipBackend';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n    }\n};\n\nexport const ModelFactory = executorch.ModelFactory;"
  },
  {
    "path": "source/flatbuffers.js",
    "content": "\nconst flatbuffers = {};\n\nflatbuffers.BinaryReader = class {\n\n    static open(data, offset) {\n        offset = offset || 0;\n        if (data && data.length >= (offset + 8)) {\n            const position = data instanceof Uint8Array ? -1 : data.position;\n            const reader = data instanceof Uint8Array ?\n                new flatbuffers.BufferReader(data) :\n                new flatbuffers.StreamReader(data);\n            reader.root = reader.int32(offset) + offset;\n            let value = false;\n            if (reader.root > 0 && reader.root < reader.length) {\n                const buffer = reader.read(offset + 4, 4);\n                reader.identifier = buffer.every((c) => c >= 32 && c <= 128) ? String.fromCharCode(...buffer) : '';\n                const vtable = reader.int32(reader.root);\n                if (vtable < 0 || (vtable > 4 && vtable < 1024)) {\n                    const start = reader.root - vtable;\n                    if (start > 0 && (start + 4) < reader.length) {\n                        const last = reader.int16(start) + start;\n                        if (last < reader.length) {\n                            const max = reader.int16(start + 2);\n                            if (max > 0 && (max & 1) === 0) {\n                                const offsets = [];\n                                for (let i = start + 4; i < last; i += 2) {\n                                    const offset = reader.int16(i);\n                                    offsets.push(offset);\n                                }\n                                value = max > Math.max(...offsets);\n                            }\n                        }\n                    }\n                }\n            }\n            if (position !== -1) {\n                data.seek(position);\n            }\n            if (value) {\n                return reader;\n            }\n        }\n        return null;\n    }\n\n    bool(offset) {\n        return Boolean(this.int8(offset));\n    }\n\n    bool_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.bool(position + offset) : defaultValue;\n    }\n\n    int8(offset) {\n        return this.uint8(offset) << 24 >> 24;\n    }\n\n    int8_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.int8(position + offset) : defaultValue;\n    }\n\n    uint8_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.uint8(position + offset) : defaultValue;\n    }\n\n    int16_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.int16(position + offset) : defaultValue;\n    }\n\n    uint16_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.uint16(position + offset) : defaultValue;\n    }\n\n    int32_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.int32(position + offset) : defaultValue;\n    }\n\n    uint32_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.uint32(position + offset) : defaultValue;\n    }\n\n    int64_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.int64(position + offset) : defaultValue;\n    }\n\n    uint64_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.uint64(position + offset) : defaultValue;\n    }\n\n    float32_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.float32(position + offset) : defaultValue;\n    }\n\n    float64_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.float64(position + offset) : defaultValue;\n    }\n\n    string(offset, encoding) {\n        offset += this.int32(offset);\n        const length = this.int32(offset);\n        offset += 4;\n        if (encoding === 1) {\n            return this.read(offset, length);\n        }\n        let text = '';\n        for (let i = 0; i < length;) {\n            let codePoint = 0;\n            const a = this.uint8(offset + i++);\n            if (a < 0xC0) {\n                codePoint = a;\n            } else {\n                const b = this.uint8(offset + i++);\n                if (a < 0xE0) {\n                    codePoint = ((a & 0x1F) << 6) | (b & 0x3F);\n                } else {\n                    const c = this.uint8(offset + i++);\n                    if (a < 0xF0) {\n                        codePoint = ((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F);\n                    } else {\n                        const d = this.uint8(offset + i++);\n                        codePoint = ((a & 0x07) << 18) | ((b & 0x3F) << 12) | ((c & 0x3F) << 6) | (d & 0x3F);\n                    }\n                }\n            }\n            // Encode UTF-16\n            if (codePoint < 0x10000) {\n                text += String.fromCharCode(codePoint);\n            } else {\n                codePoint -= 0x10000;\n                text += String.fromCharCode((codePoint >> 10) + 0xD800, (codePoint & ((1 << 10) - 1)) + 0xDC00);\n            }\n        }\n        return text;\n    }\n\n    string_(position, offset, defaultValue) {\n        offset = this.__offset(position, offset);\n        return offset ? this.string(position + offset) : defaultValue;\n    }\n\n    bools_(position, offset) {\n        offset = this.__offset(position, offset);\n        if (offset) {\n            const length = this.__vector_len(position + offset);\n            offset = this.__vector(position + offset);\n            const array = new Array(length);\n            for (let i = 0; i < length; i++) {\n                array[i] = this.uint8(offset + i) ? true : false;\n            }\n            return array;\n        }\n        return [];\n    }\n\n    int64s_(position, offset) {\n        offset = this.__offset(position, offset);\n        if (offset) {\n            const length = this.__vector_len(position + offset);\n            offset = this.__vector(position + offset);\n            const array = new Array(length);\n            for (let i = 0; i < length; i++) {\n                array[i] = this.int64(offset + (i << 3));\n            }\n            return array;\n        }\n        return [];\n    }\n\n    uint64s_(position, offset) {\n        offset = this.__offset(position, offset);\n        if (offset) {\n            const length = this.__vector_len(position + offset);\n            offset = this.__vector(position + offset);\n            const array = new Array(length);\n            for (let i = 0; i < length; i++) {\n                array[i] = this.uint64(offset + (i << 3));\n            }\n            return array;\n        }\n        return [];\n    }\n\n    strings_(position, offset) {\n        offset = this.__offset(position, offset);\n        if (offset) {\n            const length = this.__vector_len(position + offset);\n            offset = this.__vector(position + offset);\n            const array = new Array(length);\n            for (let i = 0; i < length; i++) {\n                array[i] = this.string(offset + i * 4);\n            }\n            return array;\n        }\n        return [];\n    }\n\n    struct(position, offset, type) {\n        offset = this.__offset(position, offset);\n        return offset ? type.decode(this, position + offset) : null;\n    }\n\n    table(position, offset, type) {\n        offset = this.__offset(position, offset);\n        return offset ? type.decode(this, this.__indirect(position + offset)) : null;\n    }\n\n    union(position, offset, type) {\n        const type_offset = this.__offset(position, offset);\n        const union_type = type_offset ? this.uint8(position + type_offset) : 0;\n        offset = this.__offset(position, offset + 2);\n        return offset ? type.decode(this, this.__union(position + offset), union_type) : null;\n    }\n\n    array(position, offset, type) {\n        offset = this.__offset(position, offset);\n        if (offset) {\n            const length = this.__vector_len(position + offset);\n            offset = this.__vector(position + offset);\n            const buffer = this.read(offset, length * type.BYTES_PER_ELEMENT);\n            return new type(buffer.buffer, buffer.byteOffset, length);\n        }\n        return new type(0);\n    }\n\n    unions(/* position, offset, decode */) {\n        return new flatbuffers.Error('Not implemented.');\n    }\n\n    structs(position, offset, type, size) {\n        offset = this.__offset(position, offset);\n        const length = offset ? this.__vector_len(position + offset) : 0;\n        const list = new Array(length);\n        for (let i = 0; i < length; i++) {\n            list[i] = type.decode(this, this.__vector(position + offset) + i * size);\n        }\n        return list;\n    }\n\n    tables(position, offset, type) {\n        offset = this.__offset(position, offset);\n        const length = offset ? this.__vector_len(position + offset) : 0;\n        const list = new Array(length);\n        for (let i = 0; i < length; i++) {\n            list[i] = type.decode(this, this.__indirect(this.__vector(position + offset) + i * 4));\n        }\n        return list;\n    }\n\n    __offset(bb_pos, vtableOffset) {\n        const vtable = bb_pos - this.int32(bb_pos);\n        return vtableOffset < this.int16(vtable) ? this.int16(vtable + vtableOffset) : 0;\n    }\n\n    __indirect(offset) {\n        return offset + this.int32(offset);\n    }\n\n    __vector(offset) {\n        return offset + this.int32(offset) + 4;\n    }\n\n    __vector_len(offset) {\n        return this.int32(offset + this.int32(offset));\n    }\n\n    __union(offset) {\n        return offset + this.int32(offset);\n    }\n};\n\nflatbuffers.BufferReader = class extends flatbuffers.BinaryReader {\n\n    constructor(data) {\n        super();\n        this.length = data.length;\n        this._buffer = data;\n        this._view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n    }\n\n    read(offset, length) {\n        return this._buffer.slice(offset, offset + length);\n    }\n\n    uint8(offset) {\n        return this._buffer[offset];\n    }\n\n    int16(offset) {\n        return this._view.getInt16(offset, true);\n    }\n\n    uint16(offset) {\n        return this._view.getUint16(offset, true);\n    }\n\n    int32(offset) {\n        return this._view.getInt32(offset, true);\n    }\n\n    uint32(offset) {\n        return this._view.getUint32(offset, true);\n    }\n\n    int64(offset) {\n        return this._view.getBigInt64(offset, true);\n    }\n\n    uint64(offset) {\n        return this._view.getBigUint64(offset, true);\n    }\n\n    float32(offset) {\n        return this._view.getFloat32(offset, true);\n    }\n\n    float64(offset) {\n        return this._view.getFloat64(offset, true);\n    }\n};\n\nflatbuffers.StreamReader = class extends flatbuffers.BinaryReader {\n\n    constructor(stream) {\n        super();\n        this._length = stream.length;\n        this._stream = stream;\n        this._size = 0x10000000;\n        this._offset = 0;\n        this._window = Math.min(0x1000, stream.length);\n        const buffer = this._stream.peek(this._window);\n        this._buffer = buffer;\n        this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n        this._chunk = -1;\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    read(offset, length) {\n        const buffer = new Uint8Array(length);\n        this._read(buffer, offset);\n        return buffer;\n    }\n\n    uint8(offset) {\n        const position = this._fill(offset, 1);\n        return this._view.getUint8(position);\n    }\n\n    int16(offset) {\n        const position = this._fill(offset, 2);\n        return this._view.getInt16(position, true);\n    }\n\n    uint16(offset) {\n        const position = this._fill(offset, 2);\n        return this._view.getUint16(position, true);\n    }\n\n    int32(offset) {\n        const position = this._fill(offset, 4);\n        return this._view.getInt32(position, true);\n    }\n\n    uint32(offset) {\n        const position = this._fill(offset, 4);\n        return this._view.getUint32(position, true);\n    }\n\n    int64(offset) {\n        const position = this._fill(offset, 8);\n        return this._view.getBigInt64(position, true);\n    }\n\n    uint64(offset) {\n        const position = this._fill(offset, 8);\n        return this._view.getBigUint64(position, true);\n    }\n\n    float32(offset) {\n        const position = this._fill(offset, 4);\n        return this._view.getFloat32(position, true);\n    }\n\n    float64(offset) {\n        const position = this._fill(offset, 8);\n        return this._view.getFloat64(position, true);\n    }\n\n    _fill(offset, length) {\n        if (offset + length > this._length) {\n            throw new Error(`Expected ${offset + length - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n        if (offset < this._offset || offset + length > this._offset + this._window) {\n            const remainder = offset % this. _size;\n            const last = this._last;\n            if (this._chunk !== -1) {\n                this._last = [this._chunk, this._buffer, this._view];\n            }\n            if (remainder + length > this._size) {\n                const buffer = new Uint8Array(length);\n                this._read(buffer, length);\n                this._chunk = -1;\n                this._offset = offset;\n                this._window = length;\n                this._buffer = buffer;\n                this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n            } else {\n                const chunk = Math.floor(offset / this._size);\n                this._offset = chunk * this._size;\n                this._window = Math.min(this._length - this._offset, this._size);\n                if (last && last[0] === chunk) {\n                    [this._chunk, this._buffer, this._view] = last;\n                } else {\n                    this._chunk = chunk;\n                    this._stream.seek(this._offset);\n                    const buffer = this._stream.read(this._window);\n                    this._buffer = buffer;\n                    this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n                    this._stream.seek(0);\n                }\n            }\n        }\n        return offset - this._offset;\n    }\n\n    _read(buffer, offset) {\n        const length = buffer.length;\n        if (offset < this._offset || offset + length > this._offset + this._window) {\n            this._stream.seek(offset);\n            const data = this._stream.read(length);\n            buffer.set(data, 0);\n            this._stream.seek(0);\n        } else {\n            offset -= this._offset;\n            const data = this._buffer.subarray(offset, offset + length);\n            buffer.set(data, 0);\n        }\n    }\n};\n\nflatbuffers.TextReader = class {\n\n    static open(obj) {\n        return new flatbuffers.TextReader(obj);\n    }\n\n    constructor(obj) {\n        this._root = obj;\n    }\n\n    get root() {\n        return this._root;\n    }\n\n    int64(obj, defaultValue) {\n        return obj === undefined ? defaultValue : BigInt(obj);\n    }\n\n    uint64(obj, defaultValue) {\n        return obj === undefined ? defaultValue : BigInt(obj);\n    }\n\n    value(obj, defaultValue) {\n        return obj === undefined ? defaultValue : obj;\n    }\n\n    object(obj, type) {\n        return obj === undefined ? obj : type.decodeText(this, obj);\n    }\n\n    array(obj, type) {\n        type = type || Array;\n        if (Array.isArray(obj)) {\n            const length = obj.length;\n            const target = new type(length);\n            for (let i = 0; i < length; i++) {\n                target[i] = obj[i];\n            }\n            return target;\n        }\n        if (obj) {\n            throw new flatbuffers.Error('Inalid value array.');\n        }\n        return new type(0);\n    }\n\n    objects(obj, type) {\n        if (Array.isArray(obj)) {\n            const target = new Array(obj.length);\n            for (let i = 0; i < obj.length; i++) {\n                target[i] = type.decodeText(this, obj[i]);\n            }\n            return target;\n        }\n        if (!obj) {\n            return [];\n        }\n        throw new flatbuffers.Error('Inalid object array.');\n    }\n};\n\nflatbuffers.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'FlatBuffers Error';\n        this.message = message;\n    }\n};\n\nexport const BinaryReader = flatbuffers.BinaryReader;\nexport const TextReader = flatbuffers.TextReader;\n"
  },
  {
    "path": "source/flax.js",
    "content": "\n// Experimental\n\nimport * as python from './python.js';\n\nconst flax = {};\n\nflax.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        if (stream.length > 4) {\n            const buffer = stream.peek(1);\n            if (buffer[0] === 0xDE || buffer[0] === 0xDF || ((buffer[0] & 0x80) === 0x80)) {\n                return context.set('flax.msgpack.map');\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        const stream = context.stream;\n        const packed = stream.peek();\n        const execution = new python.Execution();\n        const msgpack = execution.__import__('msgpack');\n        const numpy = execution.__import__('numpy');\n        // https://github.com/google/flax/blob/main/flax/serialization.py\n        const ext_hook = (code, data) => {\n            switch (code) {\n                case 1: { // _MsgpackExtType.ndarray\n                    const tuple = msgpack.unpackb(data);\n                    const dtype = new numpy.dtype(tuple[1]);\n                    dtype.byteorder = '<';\n                    return new numpy.ndarray(tuple[0], dtype, tuple[2]);\n                }\n                default: {\n                    throw new flax.Error(`Unsupported MessagePack extension '${code}'.`);\n                }\n            }\n        };\n        const obj = msgpack.unpackb(packed, ext_hook);\n        return new flax.Model(obj);\n    }\n};\n\nflax.Model = class {\n\n    constructor(obj) {\n        this.format = 'Flax';\n        this.modules = [new flax.Graph(obj)];\n    }\n};\n\nflax.Graph = class {\n\n    constructor(obj) {\n        this.inputs = [];\n        this.outputs = [];\n        const layers = new Map();\n        const layer = (path) => {\n            const name = path.join('.');\n            if (!layers.has(name)) {\n                layers.set(name, {});\n            }\n            return layers.get(name);\n        };\n        const flatten = (path, obj) => {\n            for (const [name, value] of Object.entries(obj)) {\n                if (flax.Utility.isTensor(value)) {\n                    const obj = layer(path);\n                    obj[name] = value;\n                } else if (Array.isArray(value)) {\n                    const obj = layer(path);\n                    obj[name] = value;\n                } else if (Object(value) === value) {\n                    flatten(path.concat(name), value);\n                } else {\n                    const obj = layer(path);\n                    obj[name] = value;\n                }\n            }\n        };\n        if (Array.isArray(obj)) {\n            layer([]).value = obj;\n        } else {\n            flatten([], obj);\n        }\n        this.nodes = Array.from(layers).map(([name, value]) => new flax.Node(name, value));\n    }\n};\n\nflax.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\nflax.Value = class {\n\n    constructor(name, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new flax.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer ? initializer.type : null;\n        this.initializer = initializer;\n    }\n};\n\nflax.Node = class {\n\n    constructor(name, layer) {\n        this.name = name;\n        this.type = { name: 'Module' };\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        for (const [name, value] of Object.entries(layer)) {\n            if (flax.Utility.isTensor(value)) {\n                const tensor = new flax.Tensor(value);\n                const argument = new flax.Argument(name, [new flax.Value('', tensor)]);\n                this.inputs.push(argument);\n            } else if (Array.isArray(value)) {\n                const attribute = new flax.Argument(name, value);\n                this.attributes.push(attribute);\n            } else {\n                const attribute = new flax.Argument(name, value);\n                this.attributes.push(attribute);\n            }\n        }\n    }\n};\n\nflax.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nflax.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return (Array.isArray(this.dimensions) && this.dimensions.length > 0) ?\n            `[${this.dimensions.join(',')}]` : '';\n    }\n};\n\nflax.Tensor = class {\n\n    constructor(array) {\n        this.type = new flax.TensorType(array.dtype.__name__, new flax.TensorShape(array.shape));\n        const dataType = this.type.dataType;\n        this.encoding = dataType === 'string' || dataType === 'object' ? '|' : array.dtype.byteorder;\n        this._data = array.tobytes();\n        this._itemsize = array.dtype.itemsize;\n    }\n\n    get values() {\n        switch (this.type.dataType) {\n            case 'string': {\n                if (this._data instanceof Uint8Array) {\n                    const data = this._data;\n                    const decoder = new TextDecoder('utf-8');\n                    const size = this.type.shape.dimensions.reduce((a, b) => a * b, 1);\n                    this._data = new Array(size);\n                    let offset = 0;\n                    for (let i = 0; i < size; i++) {\n                        const buffer = data.subarray(offset, offset + this._itemsize);\n                        const index = buffer.indexOf(0);\n                        this._data[i] = decoder.decode(index >= 0 ? buffer.subarray(0, index) : buffer);\n                        offset += this._itemsize;\n                    }\n                }\n                return this._data;\n            }\n            default:\n                return this._data;\n        }\n    }\n};\n\nflax.Utility = class {\n\n    static isTensor(obj) {\n        return obj && obj.__class__ && obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray';\n    }\n};\n\nflax.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Flax model.';\n    }\n};\n\nexport const ModelFactory = flax.ModelFactory;\n"
  },
  {
    "path": "source/flexbuffers.js",
    "content": "\nconst flexbuffers = {};\n\nflexbuffers.BinaryReader = class {\n\n    static open(buffer) {\n        const length = buffer.length;\n        if (length >= 3) {\n            const byteWidth = buffer[length - 1];\n            if (byteWidth <= 8) {\n                const packedType = buffer[length - 2];\n                return new flexbuffers.BinaryReader(buffer, length - 2 - byteWidth, byteWidth, 1 << (packedType & 3), packedType >> 2);\n            }\n        }\n        return null;\n    }\n\n    constructor(buffer, offset, parentWidth, byteWidth, type) {\n        this._buffer = buffer;\n        this._length = buffer.length;\n        this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n        this._utf8Decoder = new TextDecoder('utf-8');\n        this._root = new flexbuffers.Reference(this, offset, parentWidth, byteWidth, type);\n    }\n\n    read() {\n        return this._root.read();\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    int(offset, size) {\n        switch (size) {\n            case 1: return this._view.getInt8(offset);\n            case 2: return this._view.getInt16(offset, true);\n            case 4: return this._view.getInt32(offset, true);\n            case 8: return this._view.getBigInt64(offset, true);\n            default: throw new flexbuffers.Error(`Invalid int size '${size}'.`);\n        }\n    }\n\n    uint(offset, size) {\n        switch (size) {\n            case 1: return this._view.getUint8(offset);\n            case 2: return this._view.getUint16(offset, true);\n            case 4: return this._view.getUint32(offset, true);\n            case 8: return this._view.getBigUint64(offset, true);\n            default: throw new flexbuffers.Error(`Invalid uint size '${size}'.`);\n        }\n    }\n\n    float(offset, size) {\n        switch (size) {\n            case 4: return this._view.getFloat32(offset, true);\n            case 8: return this._view.getFloat64(offset, true);\n            default: throw new flexbuffers.Error(`Invalid float size '${size}'.`);\n        }\n    }\n\n    string(offset, size) {\n        let end = size === undefined ? this._buffer.indexOf(0, offset) : offset + size;\n        end = end === -1 ? this._buffer.length : end;\n        const bytes = this._buffer.subarray(offset, end);\n        return this._utf8Decoder.decode(bytes);\n    }\n\n    bytes(offset, size) {\n        return this._buffer.slice(offset, offset + size);\n    }\n};\n\nflexbuffers.Reference = class {\n\n    constructor(reader, offset, parentWidth, byteWidth, type) {\n        this._reader = reader;\n        this._offset = offset;\n        this._parentWidth = parentWidth;\n        this._byteWidth = byteWidth;\n        this._type = type;\n    }\n\n    read() {\n        switch (this._type) {\n            case 0x00:   // null\n                return null;\n            case 0x01:   // int\n                return this._reader.int(this._offset, this._parentWidth);\n            case 0x02:   // uint\n                return this._reader.uint(this._offset, this._parentWidth);\n            case 0x03:   // float\n                return this._reader.float(this._offset, this._parentWidth);\n            case 0x04: { // key\n                return this._reader.string(this._indirect());\n            }\n            case 0x05: { // string\n                const offset = this._indirect();\n                const size = this._reader.uint(offset - this._byteWidth, this._byteWidth);\n                return this._reader.string(offset, size);\n            }\n            case 0x06: // indirect int\n                return this._reader.int(this._indirect(), this._byteWidth);\n            case 0x07: // indirect uint\n                return this._reader.uint(this._indirect(), this._byteWidth);\n            case 0x08:   // indirect float\n                return this._reader.float(this._indirect(), this._byteWidth);\n            case 0x09: { // map\n                const offset = this._indirect();\n                const keysOffset = offset - (this._byteWidth * 3);\n                const keysVectorOffset = keysOffset - this._reader.uint(keysOffset, this._byteWidth);\n                const keysByteWidth = this._reader.uint(keysOffset + this._byteWidth, this._byteWidth);\n                const keys = this._typedVector(keysVectorOffset, keysByteWidth, 0x04);\n                const values = this._vector(offset, this._byteWidth);\n                const map = {};\n                for (let i = 0; i < keys.length; i++) {\n                    map[keys[i]] = values[i];\n                }\n                return map;\n            }\n            case 0x0a: { // vector\n                return this._vector(this._indirect(), this._byteWidth);\n            }\n            case 0x0b:   // vector int\n            case 0x0c:   // vector uint\n            case 0x0d:   // vector float\n            case 0x0e:   // vector key\n            case 0x0f:   // vector string deprecated\n            case 0x24: { // vector bool\n                return this._typedVector(this._indirect(), this._byteWidth, this._type - 0x0b + 0x01);\n            }\n            case 0x10:   // vector int2\n            case 0x11:   // vector uint2\n            case 0x12:   // vector float2\n            case 0x13:   // vector int3\n            case 0x14:   // vector uint3\n            case 0x15:   // vector float3\n            case 0x16:   // vector int4\n            case 0x17:   // vector uint4\n            case 0x18: { // vector float4\n                const offset = this._indirect();\n                const size = (((this._type - 0x10) / 3) >> 0) + 2;\n                const type = ((this._type - 0x10) % 3) + 0x01;\n                return this._typedVector(offset, this._byteWidth, type, size);\n            }\n            case 0x19: { // blob\n                const offset = this._indirect();\n                const size = this._reader.uint(offset - this._byteWidth, this._byteWidth);\n                return this._reader.bytes(offset, size);\n            }\n            case 0x1a: { // bool\n                return this._reader.uint(this._offset, this._parentWidth) !== 0;\n            }\n            default: {\n                throw new flexbuffers.Error(`Unsupported reference type '${this._type}`);\n            }\n        }\n    }\n\n    _indirect() {\n        return this._offset - this._reader.uint(this._offset, this._parentWidth);\n    }\n\n    _vector(offset, byteWidth) {\n        const size = this._reader.uint(offset - byteWidth, byteWidth);\n        const packedTypeOffset = offset + (size * byteWidth);\n        const vector = new Array(size);\n        for (let i = 0; i < size; i++) {\n            const packedType = this._reader.uint(packedTypeOffset + i, 1);\n            const reference = new flexbuffers.Reference(this._reader, offset + (i * byteWidth), byteWidth, 1 << (packedType & 3), packedType >> 2);\n            vector[i] = reference.read();\n        }\n        return vector;\n    }\n\n    _typedVector(offset, byteWidth, type, size) {\n        size = size === undefined ? this._reader.uint(offset - byteWidth, byteWidth) : size;\n        const vector = new Array(size);\n        for (let i = 0; i < size; i++) {\n            const reference = new flexbuffers.Reference(this._reader, offset + (i * byteWidth), byteWidth, 1, type);\n            vector[i] = reference.read();\n        }\n        return vector;\n    }\n};\n\nflexbuffers.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'FlexBuffers Error';\n        this.message = message;\n    }\n};\n\nexport const BinaryReader = flexbuffers.BinaryReader;\n"
  },
  {
    "path": "source/flux-metadata.json",
    "content": "[\n]"
  },
  {
    "path": "source/flux.js",
    "content": "\n// Experimental\n\nconst flux = {};\n\nflux.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        const stream = context.stream;\n        if (stream && extension === 'bson') {\n            return context.set('flux.bson');\n        }\n        return null;\n    }\n\n    async open(context) {\n        let root = null;\n        try {\n            root = await context.read('bson');\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new flux.Error(`File format is not Flux BSON (${message.replace(/\\.$/, '')}).`);\n        }\n        /* const metadata = */ context.metadata('flux-metadata.json');\n        const backref = (obj, root) => {\n            if (Array.isArray(obj)) {\n                for (let i = 0; i < obj.length; i++) {\n                    obj[i] = backref(obj[i], root);\n                }\n            } else if (obj === Object(obj)) {\n                if (obj.tag === 'backref' && obj.ref) {\n                    if (!root._backrefs[obj.ref - 1n]) {\n                        throw new flux.Error(`Invalid backref '${obj.ref}'.`);\n                    }\n                    obj = root._backrefs[obj.ref - 1n];\n                }\n                for (const key of Object.keys(obj)) {\n                    if (obj !== root || key !== '_backrefs') {\n                        obj[key] = backref(obj[key], root);\n                    }\n                }\n            }\n            return obj;\n        };\n        const obj = backref(root, root);\n        const model = obj.model;\n        if (!model) {\n            throw new flux.Error('File does not contain Flux model.');\n        }\n        throw new flux.Error(\"File contains unsupported Flux data.\");\n    }\n};\n\nflux.Model = class {\n\n    constructor(/* root */) {\n        this.format = 'Flux';\n        this.modules = [];\n    }\n};\n\nflux.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Flux Error';\n    }\n};\n\nexport const ModelFactory = flux.ModelFactory;\n"
  },
  {
    "path": "source/gguf-metadata.json",
    "content": "[\n  {\n    \"name\": \"llama\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"llama4\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"deci\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen2vl\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen3\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true, \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen3vl\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true, \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"dream\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"llada\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gemma\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gemma2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gemma3\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gemma3n\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gemma-embedding\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"falcon\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ],\n      \"parallel_ffn\": true\n    }\n  },\n  {\n    \"name\": \"gpt2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"learned\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gptneox\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ],\n      \"parallel_ffn\": true\n    }\n  },\n  {\n    \"name\": \"gptj\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ],\n      \"parallel_ffn\": true\n    }\n  },\n  {\n    \"name\": \"bloom\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"alibi\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"starcoder\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"learned\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"starcoder2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"baichuan\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"internlm2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"codeshell\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"orion\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"refact\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"xverse\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"stablelm\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true, \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"phi2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ],\n      \"parallel_ffn\": true\n    }\n  },\n  {\n    \"name\": \"phi3\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"phimoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"olmo\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"olmo2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"olmoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"exaone\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"exaone4\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"exaone-moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"chameleon\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"chatglm\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"glm4\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"glm4moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"glm-dsa\",\n    \"family\": \"mla\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_LATENT_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q_a\", \"attn_q_b\", \"attn_kv_a_mqa\", \"attn_kv_b\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"command-r\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"cohere2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"plamo\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"plamo3\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"mpt\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"alibi\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"nemotron\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"openelm\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"maincoder\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"arcee\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"mistral3\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"hunyuan-dense\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"pangu-embedded\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"smollm3\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"dots1\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"ernie4_5\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"apertus\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"granite\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"granitemoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"jais\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"alibi\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"jais2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"seed_oss\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"rnd1\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"cogvlm\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"minimax-m2\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"minicpm\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"step35\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true, \"has_gate\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"llama-embed\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"smallthinker\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"mimo2\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"lfm2\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"lfm2moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"gpt-oss\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen2moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen3moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true, \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen3vlmoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_bias\": true, \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"grok\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"arctic\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"dbrx\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"deepseek\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"ernie4_5-moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"hunyuan-moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"bailingmoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"bailingmoe2\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"afmoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true, \"has_gate\": true },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"llada-moe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"grovemoe\",\n    \"family\": \"decoder-moe\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"deepseek2\",\n    \"family\": \"mla\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_LATENT_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q_a\", \"attn_q_b\", \"attn_kv_a_mqa\", \"attn_kv_b\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"minicpm3\",\n    \"family\": \"mla\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_LATENT_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q_a\", \"attn_q_b\", \"attn_kv_a_mqa\", \"attn_kv_b\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"plm\",\n    \"family\": \"mla\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_LATENT_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_kv_a_mqa\", \"attn_kv_b\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"mamba\",\n    \"family\": \"ssm\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ssm\", \"type\": \"MAMBA\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_x\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_out\"] }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"mamba2\",\n    \"family\": \"ssm\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ssm\", \"type\": \"MAMBA2\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_norm\", \"ssm_out\"] }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"rwkv6\",\n    \"family\": \"rwkv\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"time_mix\", \"type\": \"RWKV\", \"category\": \"Layer\", \"tensors\": [\"time_mix_key\", \"time_mix_value\", \"time_mix_receptance\", \"time_mix_gate\", \"time_mix_first\", \"time_mix_decay\", \"time_mix_lerp_x\", \"time_mix_lerp_k\", \"time_mix_lerp_v\", \"time_mix_lerp_r\", \"time_mix_lerp_g\", \"time_mix_lerp_w\", \"time_mix_w1\", \"time_mix_w2\", \"time_mix_decay_w1\", \"time_mix_decay_w2\", \"time_mix_ln\", \"time_mix_output\"] },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"channel_mix\", \"type\": \"RWKV\", \"category\": \"Layer\", \"tensors\": [\"channel_mix_key\", \"channel_mix_receptance\", \"channel_mix_value\", \"channel_mix_lerp_k\", \"channel_mix_lerp_r\"] }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"rwkv6qwen2\",\n    \"family\": \"rwkv\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"time_mix\", \"type\": \"RWKV\", \"category\": \"Layer\", \"tensors\": [\"time_mix_key\", \"time_mix_value\", \"time_mix_receptance\", \"time_mix_gate\", \"time_mix_first\", \"time_mix_decay\", \"time_mix_lerp_x\", \"time_mix_lerp_k\", \"time_mix_lerp_v\", \"time_mix_lerp_r\", \"time_mix_lerp_g\", \"time_mix_lerp_w\", \"time_mix_w1\", \"time_mix_w2\", \"time_mix_decay_w1\", \"time_mix_decay_w2\", \"time_mix_ln\", \"time_mix_output\"] },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"rwkv7\",\n    \"family\": \"rwkv\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"time_mix\", \"type\": \"RWKV\", \"category\": \"Layer\", \"tensors\": [\"time_mix_key\", \"time_mix_value\", \"time_mix_receptance\", \"time_mix_lerp_fused\", \"time_mix_w0\", \"time_mix_w1\", \"time_mix_w2\", \"time_mix_a0\", \"time_mix_a1\", \"time_mix_a2\", \"time_mix_v0\", \"time_mix_v1\", \"time_mix_v2\", \"time_mix_g1\", \"time_mix_g2\", \"time_mix_k_k\", \"time_mix_k_a\", \"time_mix_r_k\", \"time_mix_ln\", \"time_mix_output\"] },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"channel_mix\", \"type\": \"RWKV\", \"category\": \"Layer\", \"tensors\": [\"channel_mix_key\", \"channel_mix_value\", \"channel_mix_lerp_k\"] }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"arwkv7\",\n    \"family\": \"rwkv\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"time_mix\", \"type\": \"RWKV\", \"category\": \"Layer\", \"tensors\": [\"time_mix_key\", \"time_mix_value\", \"time_mix_receptance\", \"time_mix_lerp_fused\", \"time_mix_w0\", \"time_mix_w1\", \"time_mix_w2\", \"time_mix_a0\", \"time_mix_a1\", \"time_mix_a2\", \"time_mix_v0\", \"time_mix_v1\", \"time_mix_v2\", \"time_mix_g1\", \"time_mix_g2\", \"time_mix_k_k\", \"time_mix_k_a\", \"time_mix_r_k\", \"time_mix_ln\", \"time_mix_output\"] },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"jamba\",\n    \"family\": \"hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_ssm\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"none\" },\n          \"ssm\": { \"type\": \"ssm\", \"subtype\": \"mamba\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_x\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_out\"] }\n        },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"ffn_or_moe\",\n          \"type\": \"HYBRID_FFN\",\n          \"category\": \"Layer\",\n          \"dense\": { \"type\": \"ffn\", \"subtype\": \"swiglu\", \"tensors\": [\"ffn_gate\", \"ffn_up\", \"ffn_down\"] },\n          \"moe\": { \"type\": \"moe\", \"subtype\": \"swiglu\", \"tensors\": [\"ffn_gate_inp\", \"ffn_gate_exps\", \"ffn_up_exps\", \"ffn_down_exps\"] }\n        }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"falcon-h1\",\n    \"family\": \"hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ssm\", \"type\": \"MAMBA2\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_norm\", \"ssm_out\"], \"parallel\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"granitehybrid\",\n    \"family\": \"hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_ssm\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n          \"ssm\": { \"type\": \"ssm\", \"subtype\": \"mamba2\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_norm\", \"ssm_out\"] }\n        },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"ffn_or_moe\",\n          \"type\": \"HYBRID_FFN\",\n          \"category\": \"Layer\",\n          \"dense\": { \"type\": \"ffn\", \"subtype\": \"swiglu\", \"tensors\": [\"ffn_gate\", \"ffn_up\", \"ffn_down\"] },\n          \"moe\": { \"type\": \"moe\", \"subtype\": \"swiglu\", \"tensors\": [\"ffn_gate_inp\", \"ffn_gate_exps\", \"ffn_up_exps\", \"ffn_down_exps\"], \"has_shared_expert\": true }\n        }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"nemotron_h\",\n    \"family\": \"hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_ssm\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n          \"ssm\": { \"type\": \"ssm\", \"subtype\": \"mamba2\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_norm\", \"ssm_out\"] }\n        },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"nemotron_h_moe\",\n    \"family\": \"hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_ssm\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n          \"ssm\": { \"type\": \"ssm\", \"subtype\": \"mamba2\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_norm\", \"ssm_out\"] }\n        },\n        {\n          \"name\": \"ffn_or_moe\",\n          \"type\": \"HYBRID_FFN\",\n          \"category\": \"Layer\",\n          \"dense\": { \"type\": \"ffn\", \"subtype\": \"gelu\", \"tensors\": [\"ffn_up\", \"ffn_down\"] },\n          \"moe\": { \"type\": \"moe\", \"subtype\": \"gelu\", \"tensors\": [\"ffn_gate_inp\", \"ffn_up_exps\", \"ffn_down_exps\"], \"has_shared_expert\": true }\n        }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"plamo2\",\n    \"family\": \"hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_ssm\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n          \"ssm\": { \"type\": \"ssm\", \"subtype\": \"mamba2\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_x\", \"ssm_dt\", \"ssm_a\", \"ssm_d\", \"ssm_out\"] }\n        },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"bert\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"token_types\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"position_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"learned\", \"has_bias\": true },\n        { \"name\": \"attn_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"layer_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"nomic-bert\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"token_types\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"attn_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"layer_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"nomic-bert-moe\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"token_types\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"attn_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"layer_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"jina-bert-v2\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"token_types\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"alibi\", \"has_qk_norm\": true },\n        { \"name\": \"attn_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"layer_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\":       []\n    }\n  },\n  {\n    \"name\": \"jina-bert-v3\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"token_types\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"learned\", \"has_bias\": true },\n        { \"name\": \"attn_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"layer_output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"modern-bert\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"neo-bert\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"paddleocr\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"t5\",\n    \"family\": \"encoder-decoder\",\n    \"graph\": {\n      \"encoder\": {\n        \"input\": [\n          { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n        ],\n        \"blocks\": [\n          { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n          { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"enc.attn_q\", \"enc.attn_k\", \"enc.attn_v\", \"enc.attn_o\"], \"position_encoding\": \"relative_bias\" },\n          { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n          { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n          { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n        ],\n        \"output\": [\n          { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n        ]\n      },\n      \"decoder\": {\n        \"input\": [\n          { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n        ],\n        \"blocks\": [\n          { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n          { \"name\": \"self_attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"dec.attn_q\", \"dec.attn_k\", \"dec.attn_v\", \"dec.attn_o\"], \"position_encoding\": \"relative_bias\" },\n          { \"name\": \"cross_attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n          { \"name\": \"cross_attention\", \"type\": \"CROSS_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"dec.cross_attn_q\", \"dec.cross_attn_k\", \"dec.cross_attn_v\", \"dec.cross_attn_o\"] },\n          { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n          { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n          { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n        ],\n        \"output\": [\n          { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n          { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n        ]\n      }\n    }\n  },\n  {\n    \"name\": \"t5encoder\",\n    \"family\": \"encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"enc.attn_q\", \"enc.attn_k\", \"enc.attn_v\", \"enc.attn_o\"], \"position_encoding\": \"relative_bias\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen3next\",\n    \"family\": \"delta-hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_delta\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n          \"delta_net\": { \"type\": \"delta_net\", \"tensors\": [\"ssm_in\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_a\", \"ssm_norm\", \"ssm_ba\", \"ssm_out\"] }\n        },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen35\",\n    \"family\": \"delta-hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_delta\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n          \"delta_net\": { \"type\": \"delta_net\", \"tensors\": [\"ssm_a\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_norm\", \"ssm_beta\", \"ssm_alpha\", \"ssm_out\"] }\n        },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen35moe\",\n    \"family\": \"delta-hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_delta\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mha\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_qk_norm\": true },\n          \"delta_net\": { \"type\": \"delta_net\", \"tensors\": [\"ssm_a\", \"ssm_conv1d\", \"ssm_dt\", \"ssm_norm\", \"ssm_beta\", \"ssm_alpha\", \"ssm_out\"] }\n        },\n        { \"name\": \"attn_post_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"kimi-linear\",\n    \"family\": \"delta-hybrid\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        {\n          \"name\": \"attention_or_delta\",\n          \"type\": \"HYBRID\",\n          \"category\": \"Layer\",\n          \"attention\": { \"type\": \"attention\", \"subtype\": \"mla\", \"tensors\": [\"attn_q_a\", \"attn_q_b\", \"attn_kv_a_mqa\", \"attn_kv_b\", \"attn_output\"], \"position_encoding\": \"rope\" },\n          \"delta_net\": { \"type\": \"delta_net\", \"subtype\": \"kda\", \"tensors\": [\"ssm_conv1d_q\", \"ssm_conv1d_k\", \"ssm_conv1d_v\", \"ssm_f_a\", \"ssm_f_b\", \"ssm_beta\", \"ssm_a\", \"ssm_g_a\", \"ssm_g_b\", \"ssm_dt\", \"ssm_norm\"] }\n        },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate_inp\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_gate_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_up_exps\", \"type\": \"MUL_MAT_ID\" },\n        { \"name\": \"ffn_down_exps\", \"type\": \"MUL_MAT_ID\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"bitnet\",\n    \"family\": \"bitnet\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_q\", \"attn_k\", \"attn_v\", \"attn_output\"], \"position_encoding\": \"rope\", \"has_sub_norm\": true },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"clip\",\n    \"family\": \"vision-encoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"v.patch_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"v.position_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"v.class_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"input_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"v.attn_qkv\", \"v.attn_out\"], \"position_encoding\": \"learned\" },\n        { \"name\": \"post_attn_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"v.post_ln\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"wavtokenizer-dec\",\n    \"family\": \"audio-decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" },\n        { \"name\": \"token_embd_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"conv1d\", \"type\": \"CONV_1D\", \"category\": \"Layer\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"convnext\", \"type\": \"CONV_NEXT\", \"category\": \"Layer\", \"tensors\": [\"convnext.dw\", \"convnext.norm\", \"convnext.pw1\", \"convnext.pw2\", \"convnext.gamma\"] },\n        { \"name\": \"posnet\", \"type\": \"POS_NET\", \"category\": \"Layer\", \"tensors\": [\"posnet.conv1\", \"posnet.conv2\", \"posnet.norm\", \"posnet.norm1\", \"posnet.norm2\", \"posnet.attn_norm\", \"posnet.attn_q\", \"posnet.attn_k\", \"posnet.attn_v\", \"posnet.attn_output\"] }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"LAYER_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  },\n  {\n    \"name\": \"qwen\",\n    \"family\": \"decoder\",\n    \"graph\": {\n      \"input\": [\n        { \"name\": \"token_embd\", \"type\": \"EMBEDDING\", \"category\": \"Transform\" }\n      ],\n      \"blocks\": [\n        { \"name\": \"attn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"attention\", \"type\": \"MULTI_HEAD_ATTENTION\", \"category\": \"Attention\", \"tensors\": [\"attn_qkv\", \"attn_output\"], \"position_encoding\": \"rope\" },\n        { \"name\": \"ffn_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"ffn_gate\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_up\", \"type\": \"MUL_MAT\" },\n        { \"name\": \"ffn_down\", \"type\": \"MUL_MAT\" }\n      ],\n      \"output\": [\n        { \"name\": \"output_norm\", \"type\": \"RMS_NORM\", \"category\": \"Normalization\" },\n        { \"name\": \"output\", \"type\": \"MUL_MAT\" }\n      ]\n    }\n  }\n]\n"
  },
  {
    "path": "source/gguf.js",
    "content": "\nconst gguf = {};\n\ngguf.ModelFactory = class {\n\n    async match(context) {\n        const reader = gguf.Reader.open(context);\n        if (reader) {\n            return context.set('gguf', reader);\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('gguf-metadata.json');\n        const target = context.value;\n        await target.read();\n        return new gguf.Model(metadata, target);\n    }\n};\n\ngguf.Model = class {\n\n    constructor(metadata, target) {\n        this.format = target.format;\n        this.metadata = [];\n        const extra = new Map();\n        let architecture = '?';\n        for (const [name, value] of target.metadata) {\n            switch (name) {\n                case 'general.name': this.name = value; break;\n                case 'general.architecture': architecture = value; break;\n                case 'general.description': this.description = value; break;\n                case 'general.author': this.metadata.push(new gguf.Argument('author', value)); break;\n                case 'general.license': this.metadata.push(new gguf.Argument('license', value)); break;\n                case 'general.file_type':\n                case 'general.quantization_version':\n                    break;\n                default:\n                    extra.set(name, value);\n                    break;\n            }\n        }\n        const tokenizer = { type: 'tokenizer', metadata: new Map(), layers: [] };\n        const graph = {};\n        graph.type = architecture;\n        graph.attributes = [];\n        for (const [name, value] of extra) {\n            if (name.startsWith('tokenizer.')) {\n                const match = name.match(/^(.*)\\.(.*?)$/);\n                if (match) {\n                    const [, param] = match.slice(1);\n                    tokenizer.metadata.set(param, value);\n                }\n            } else if (architecture !== '?' && name.startsWith(`${architecture}.`)) {\n                graph.attributes.push(new gguf.Argument(name, value));\n            } else {\n                this.metadata.push(new gguf.Argument(name, value));\n            }\n        }\n        const context = new gguf.Context(metadata, target, extra, architecture);\n        graph.layers = context.build();\n        if (tokenizer.metadata.size > 0) {\n            graph.layers = graph.layers || [];\n            graph.layers.unshift(tokenizer);\n            if (context.structured) {\n                graph.layers.push({ type: 'tokenizer', metadata: new Map(), layers: [] });\n            }\n        }\n        this.modules = [new gguf.Graph(graph)];\n    }\n\n};\n\ngguf.Graph = class {\n\n    constructor(graph) {\n        this.name = graph.type;\n        this.type = '';\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = graph.attributes || [];\n        let valueIndex = 0;\n        let prevValue = null;\n        const newValue = () => new gguf.Value(`v${valueIndex++}`);\n        const addNode = (entry, inputValues, outputValue) => {\n            const node = new gguf.Node(entry);\n            for (const v of inputValues) {\n                node.inputs.unshift(new gguf.Argument('input', [v]));\n            }\n            if (outputValue) {\n                node.outputs.push(new gguf.Argument('output', [outputValue]));\n            }\n            this.nodes.push(node);\n        };\n        const addOp = (type, inputValues, outputValue) => {\n            addNode({ name: '', type, weights: new Map(), metadata: new Map(), layers: [] }, inputValues, outputValue);\n        };\n        for (const layer of graph.layers) {\n            if (Array.isArray(layer.layers) && layer.layers.length > 0) {\n                const map = new Map();\n                for (const item of layer.layers) {\n                    map.set(item.name, item);\n                }\n                const has = (name) => map.has(name);\n                const get = (name) => map.get(name);\n                const used = new Set();\n                const use = (name) => {\n                    used.add(name);\n                    return get(name);\n                };\n                const hasMoe = has('ffn_gate_inp');\n                const hasFfn = has('ffn_up') || hasMoe;\n                const buildLinearFfn = (input, gateKey, upKey, downKey) => {\n                    const inputs = [input];\n                    if (has(gateKey)) {\n                        const g = newValue();\n                        addNode(use(gateKey), [input], g);\n                        inputs.push(g);\n                    }\n                    const u = newValue();\n                    addNode(use(upKey), [input], u);\n                    inputs.push(u);\n                    const d = newValue();\n                    addNode(use(downKey), inputs, d);\n                    return d;\n                };\n                const buildFfn = (input) => {\n                    if (hasMoe) {\n                        const g1 = newValue();\n                        addNode(use('ffn_gate_inp'), [input], g1);\n                        const moeOut = buildLinearFfn(g1, 'ffn_gate_exps', 'ffn_up_exps', 'ffn_down_exps');\n                        if (has('ffn_up_shexp')) {\n                            const sharedOut = buildLinearFfn(input, 'ffn_gate_shexp', 'ffn_up_shexp', 'ffn_down_shexp');\n                            const sum = newValue();\n                            addOp('ADD', [moeOut, sharedOut], sum);\n                            return sum;\n                        }\n                        return moeOut;\n                    }\n                    return buildLinearFfn(input, 'ffn_gate', 'ffn_up', 'ffn_down');\n                };\n                if (has('attn_norm') && has('attention') && !has('ffn_norm') && !has('attn_post_norm') && hasFfn) {\n                    // Parallel attention + FFN (phi-2, falcon)\n                    const inp = prevValue || newValue();\n                    const normOut = newValue();\n                    const attnOut = newValue();\n                    const out = newValue();\n                    addNode(use('attn_norm'), [inp], normOut);\n                    addNode(use('attention'), [normOut], attnOut);\n                    const ffnOut = buildFfn(normOut);\n                    addOp('ADD', [attnOut, ffnOut, inp], out);\n                    prevValue = out;\n                } else if (has('attn_norm') && has('attention') && has('cross_attn_norm') && has('cross_attention') && has('ffn_norm') && hasFfn) {\n                    // Pre-norm with cross-attention (T5 decoder)\n                    const inp = prevValue || newValue();\n                    let cur = inp;\n                    const n1 = newValue();\n                    addNode(use('attn_norm'), [cur], n1);\n                    const a1 = newValue();\n                    addNode(use('attention'), [n1], a1);\n                    const r1 = newValue();\n                    addOp('ADD', [a1, cur], r1);\n                    cur = r1;\n                    const cn = newValue();\n                    addNode(use('cross_attn_norm'), [cur], cn);\n                    const ca = newValue();\n                    addNode(use('cross_attention'), [cn], ca);\n                    const r2 = newValue();\n                    addOp('ADD', [ca, cur], r2);\n                    cur = r2;\n                    const n2 = newValue();\n                    addNode(use('ffn_norm'), [cur], n2);\n                    const f1 = buildFfn(n2);\n                    const r3 = newValue();\n                    addOp('ADD', [f1, cur], r3);\n                    prevValue = r3;\n                } else if (has('attn_norm') && has('attention') && has('ffn_norm') && hasFfn) {\n                    // Pre-norm transformer (llama, qwen, gemma, etc.)\n                    const inp = prevValue || newValue();\n                    let cur = inp;\n                    const n1 = newValue();\n                    addNode(use('attn_norm'), [cur], n1);\n                    const a1 = newValue();\n                    addNode(use('attention'), [n1], a1);\n                    let preAdd1 = a1;\n                    if (has('ssm')) {\n                        const s1 = newValue();\n                        addNode(use('ssm'), [n1], s1);\n                        const sum = newValue();\n                        addOp('ADD', [a1, s1], sum);\n                        preAdd1 = sum;\n                    }\n                    if (has('attn_post_norm')) {\n                        const pn = newValue();\n                        addNode(use('attn_post_norm'), [preAdd1], pn);\n                        preAdd1 = pn;\n                    }\n                    const r1 = newValue();\n                    addOp('ADD', [preAdd1, cur], r1);\n                    cur = r1;\n                    const n2 = newValue();\n                    addNode(use('ffn_norm'), [cur], n2);\n                    const f1 = buildFfn(n2);\n                    let preAdd2 = f1;\n                    if (has('ffn_post_norm')) {\n                        const pn = newValue();\n                        addNode(use('ffn_post_norm'), [f1], pn);\n                        preAdd2 = pn;\n                    }\n                    const r2 = newValue();\n                    addOp('ADD', [preAdd2, cur], r2);\n                    prevValue = r2;\n                } else if (has('attention') && (has('attn_output_norm') || has('layer_output_norm'))) {\n                    // Post-norm (BERT)\n                    const inp = prevValue || newValue();\n                    const a1 = newValue();\n                    addNode(use('attention'), [inp], a1);\n                    const r1 = newValue();\n                    addOp('ADD', [a1, inp], r1);\n                    let cur = r1;\n                    if (has('attn_output_norm')) {\n                        const n1 = newValue();\n                        addNode(use('attn_output_norm'), [cur], n1);\n                        cur = n1;\n                    }\n                    if (hasFfn) {\n                        const residual = cur;\n                        const f1 = buildFfn(cur);\n                        const r2 = newValue();\n                        addOp('ADD', [f1, residual], r2);\n                        cur = r2;\n                    }\n                    if (has('layer_output_norm')) {\n                        const n2 = newValue();\n                        addNode(use('layer_output_norm'), [cur], n2);\n                        cur = n2;\n                    }\n                    prevValue = cur;\n                } else if (has('attn_norm') && has('ssm') && hasFfn) {\n                    // SSM + FFN (hybrid SSM-variant block: jamba, granitehybrid, etc.)\n                    const inp = prevValue || newValue();\n                    const n1 = newValue();\n                    addNode(use('attn_norm'), [inp], n1);\n                    const s1 = newValue();\n                    addNode(use('ssm'), [n1], s1);\n                    let preAdd1 = s1;\n                    if (has('attn_post_norm')) {\n                        const pn = newValue();\n                        addNode(use('attn_post_norm'), [s1], pn);\n                        preAdd1 = pn;\n                    }\n                    const r1 = newValue();\n                    addOp('ADD', [preAdd1, inp], r1);\n                    let cur = r1;\n                    if (has('ffn_norm')) {\n                        const n2 = newValue();\n                        addNode(use('ffn_norm'), [cur], n2);\n                        cur = n2;\n                    }\n                    const f1 = buildFfn(cur);\n                    let preAdd2 = f1;\n                    if (has('ffn_post_norm')) {\n                        const pn = newValue();\n                        addNode(use('ffn_post_norm'), [f1], pn);\n                        preAdd2 = pn;\n                    }\n                    const r2 = newValue();\n                    addOp('ADD', [preAdd2, r1], r2);\n                    prevValue = r2;\n                } else if (has('attn_norm') && has('ssm')) {\n                    // SSM (Mamba)\n                    const inp = prevValue || newValue();\n                    const n1 = newValue();\n                    addNode(use('attn_norm'), [inp], n1);\n                    const s1 = newValue();\n                    addNode(use('ssm'), [n1], s1);\n                    const r1 = newValue();\n                    addOp('ADD', [s1, inp], r1);\n                    prevValue = r1;\n                } else if (has('attn_norm') && has('time_mix') && has('channel_mix')) {\n                    // RWKV\n                    const inp = prevValue || newValue();\n                    const n1 = newValue();\n                    addNode(use('attn_norm'), [inp], n1);\n                    const t1 = newValue();\n                    addNode(use('time_mix'), [n1], t1);\n                    const r1 = newValue();\n                    addOp('ADD', [t1, inp], r1);\n                    let cur = r1;\n                    let cmInput = cur;\n                    if (has('ffn_norm')) {\n                        const n2 = newValue();\n                        addNode(use('ffn_norm'), [cur], n2);\n                        cmInput = n2;\n                    }\n                    const c1 = newValue();\n                    addNode(use('channel_mix'), [cmInput], c1);\n                    const r2 = newValue();\n                    addOp('ADD', [c1, cur], r2);\n                    cur = r2;\n                    prevValue = cur;\n                } else if (has('attn_norm') && has('attention') && hasFfn) {\n                    // Pre-norm without ffn_norm (some variants)\n                    const inp = prevValue || newValue();\n                    const n1 = newValue();\n                    addNode(use('attn_norm'), [inp], n1);\n                    const a1 = newValue();\n                    addNode(use('attention'), [n1], a1);\n                    let preAdd1 = a1;\n                    if (has('attn_post_norm')) {\n                        const pn = newValue();\n                        addNode(use('attn_post_norm'), [a1], pn);\n                        preAdd1 = pn;\n                    }\n                    const r1 = newValue();\n                    addOp('ADD', [preAdd1, inp], r1);\n                    const f1 = buildFfn(r1);\n                    const r2 = newValue();\n                    addOp('ADD', [f1, r1], r2);\n                    prevValue = r2;\n                } else {\n                    // Fallback: linear chain\n                    for (const item of layer.layers) {\n                        const node = new gguf.Node(item);\n                        if (prevValue) {\n                            node.inputs.unshift(new gguf.Argument('input', [prevValue]));\n                        }\n                        const out = newValue();\n                        node.outputs.push(new gguf.Argument('output', [out]));\n                        prevValue = out;\n                        this.nodes.push(node);\n                    }\n                    continue;\n                }\n                for (const item of layer.layers) {\n                    if (!used.has(item.name)) {\n                        this.nodes.push(new gguf.Node(item));\n                    }\n                }\n            } else {\n                const node = new gguf.Node(layer);\n                if (prevValue && layer.type !== 'weights') {\n                    node.inputs.unshift(new gguf.Argument('input', [prevValue]));\n                }\n                if (layer.type !== 'weights') {\n                    const outputValue = newValue();\n                    node.outputs.push(new gguf.Argument('output', [outputValue]));\n                    prevValue = outputValue;\n                }\n                this.nodes.push(node);\n            }\n        }\n    }\n};\n\ngguf.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\ngguf.Value = class {\n\n    constructor(name, type, initializer) {\n        this.name = name;\n        this.type = type || null;\n        this.quantization = initializer && initializer.quantization ? initializer.quantization : null;\n        this.initializer = initializer || null;\n    }\n};\n\ngguf.Node = class {\n\n    constructor(layer) {\n        this.type = layer.category ? { name: layer.type, category: layer.category } : { name: layer.type };\n        this.name = layer.name || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (layer.weights) {\n            for (const [name, weight] of layer.weights) {\n                const tensor = new gguf.Tensor(weight);\n                const value = new gguf.Value(weight.name, tensor.type, tensor);\n                const argument = new gguf.Argument(name, [value]);\n                this.inputs.push(argument);\n            }\n        }\n        if (layer.metadata) {\n            for (const [name, value] of layer.metadata) {\n                const attribute = new gguf.Argument(name, value);\n                this.attributes.push(attribute);\n            }\n        }\n    }\n};\n\ngguf.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\ngguf.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n    }\n};\n\ngguf.Tensor = class {\n\n    constructor(tensor) {\n        const shape = new gguf.TensorShape(tensor.ne);\n        this.type = new gguf.TensorType(tensor.dtype, shape);\n        if (tensor.type !== gguf.QuantizationType.F32 && tensor.type !== gguf.QuantizationType.F16) {\n            this.quantization = {\n                type: gguf.Utility.enum(gguf.QuantizationType, tensor.type).toLowerCase()\n            };\n        }\n        if (tensor.dtype === 'float32' || tensor.dtype === 'float16' ||\n            tensor.dtype === 'int8' || tensor.dtype === 'int16' || tensor.dtype === 'int32') {\n            this.encoding = '<';\n            this._data = tensor.data;\n        }\n    }\n\n    get values() {\n        if (this._data) {\n            return this._data.peek();\n        }\n        return null;\n    }\n};\n\ngguf.Reader = class {\n\n    static open(context) {\n        const stream = context.stream;\n        if (stream && stream.length > 4) {\n            const buffer = stream.peek(4);\n            const signature = String.fromCharCode.apply(null, buffer);\n            if (signature === 'GGUF') {\n                return new gguf.Reader(context);\n            }\n        }\n        return null;\n    }\n\n    constructor(context) {\n        this.context = context;\n        const QK_K = 256;\n        // https://github.com/ggml-org/llama.cpp/blob/master/gguf-py/gguf/constants.py\n        gguf.Reader.GGML_QUANT_SIZES = gguf.Reader.GGML_QUANT_SIZES || new Map([\n            [gguf.QuantizationType.F32,        [1, 4, 'float32']],\n            [gguf.QuantizationType.F16,        [1, 2, 'float16']],\n            [gguf.QuantizationType.Q4_0,       [32, 2 + 16, 'q4_0']],\n            [gguf.QuantizationType.Q4_1,       [32, 2 + 2 + 16, 'q4_1']],\n            [gguf.QuantizationType.Q4_2,       [16, 2 + 8, 'q4_2']],\n            [gguf.QuantizationType.Q4_3,       [16, 2 + 2 + 8, 'q4_3']],\n            [gguf.QuantizationType.Q5_0,       [32, 2 + 4 + 16, 'q5_0']],\n            [gguf.QuantizationType.Q5_1,       [32, 2 + 2 + 4 + 16, 'q5_1']],\n            [gguf.QuantizationType.Q8_0,       [32, 2 + 32, 'q8_0']],\n            [gguf.QuantizationType.Q8_1,       [32, 4 + 4 + 32, 'q8_1']],\n            [gguf.QuantizationType.Q2_K,       [256, 2 + 2 + Math.floor(QK_K / 16) + Math.floor(QK_K / 4), 'q2_K']],\n            [gguf.QuantizationType.Q3_K,       [256, 2 + Math.floor(QK_K / 4) + Math.floor(QK_K / 8) + 12, 'q3_K']],\n            [gguf.QuantizationType.Q4_K,       [256, 2 + 2 + Math.floor(QK_K / 2) + 12, 'q4_K']],\n            [gguf.QuantizationType.Q5_K,       [256, 2 + 2 + Math.floor(QK_K / 2) + Math.floor(QK_K / 8) + 12, 'q5_K']],\n            [gguf.QuantizationType.Q6_K,       [256, 2 + Math.floor(QK_K / 2) + Math.floor(QK_K / 4) + Math.floor(QK_K / 16), 'q6_K']],\n            [gguf.QuantizationType.Q8_K,       [256, 4 + QK_K + Math.floor(QK_K / 8), 'q8_K']],\n            [gguf.QuantizationType.IQ2_XXS,    [256, 2 + Math.floor(QK_K / 4), 'iq2_xxs']],\n            [gguf.QuantizationType.IQ2_XS,     [256, 2 + Math.floor(QK_K / 4) + Math.floor(QK_K / 32), 'iq2_xs']],\n            [gguf.QuantizationType.IQ3_XXS,    [256, 2 + Math.floor(QK_K / 4) + Math.floor(QK_K / 8), 'iq3_xxs']],\n            [gguf.QuantizationType.IQ1_S,      [256, 2 + Math.floor(QK_K / 8) + Math.floor(QK_K / 16), 'iq1_s']],\n            [gguf.QuantizationType.IQ4_NL,     [32, 2 + 16, 'iq4_nl']],\n            [gguf.QuantizationType.IQ3_S,      [256, 2 + Math.floor(QK_K / 4) + Math.floor(QK_K / 8) + Math.floor(QK_K / 32) + 4, 'iq3_s']],\n            [gguf.QuantizationType.IQ2_S,      [256, 2 + Math.floor(QK_K / 4) + Math.floor(QK_K / 16), 'iq2_s']],\n            [gguf.QuantizationType.IQ4_XS,     [256, 2 + 2 + Math.floor(QK_K / 2) + Math.floor(QK_K / 64), 'iq4_xs']],\n            [gguf.QuantizationType.I8,         [1, 1, 'int8']],\n            [gguf.QuantizationType.I16,        [1, 2, 'int16']],\n            [gguf.QuantizationType.I32,        [1, 4, 'int32']],\n            [gguf.QuantizationType.I64,        [1, 8, 'int64']],\n            [gguf.QuantizationType.F64,        [1, 8, 'float64']],\n            [gguf.QuantizationType.IQ1_M,      [256, Math.floor(QK_K / 8) + Math.floor(QK_K / 16)  + Math.floor(QK_K / 32), 'iq1_m']],\n            [gguf.QuantizationType.BF16,       [1, 2, 'bfloat16']],\n            [gguf.QuantizationType.Q4_0_4_4,   [32, 2 + 16, 'q4_0_4_4']],\n            [gguf.QuantizationType.Q4_0_4_8,   [32, 2 + 16, 'q4_0_4_8']],\n            [gguf.QuantizationType.Q4_0_8_8,   [32, 2 + 16, 'q4_0_8_8']],\n            [gguf.QuantizationType.TQ1_0,      [256, 2 + 4 * 13, 'tq1_0']],\n            [gguf.QuantizationType.TQ2_0,      [256, 2 + 64, 'tq2_0']],\n            [gguf.QuantizationType.IQ4_NL_4_4, [32, 2 + 16, 'iq4_nl_4_4']],\n            [gguf.QuantizationType.IQ4_NL_4_8, [32, 2 + 16, 'iq4_nl_4_8']],\n            [gguf.QuantizationType.IQ4_NL_8_8, [32, 2 + 16, 'iq4_nl_8_8']],\n            [gguf.QuantizationType.MXFP4,      [32, 1 + 16, 'mxfp4']]\n        ]);\n    }\n\n    async read() {\n        const context = this.context;\n        const stream = context.stream;\n        let reader = await context.read('binary');\n        reader = new gguf.BinaryReader(reader);\n        this.tensors = new Map();\n        this.metadata = new Map();\n        this.header = {};\n        this.header.magic = String.fromCharCode.apply(null, reader.read(4));\n        this.header.version = reader.uint32();\n        this.format = `GGUF v${this.header.version}`;\n        if (this.header.version >= 2) {\n            this.header.n_tensors = reader.uint64().toNumber();\n            this.header.n_kv = reader.uint64().toNumber();\n            for (let i = 0; i < this.header.n_kv; i++) {\n                const entry = reader.entry();\n                this.metadata.set(entry.name, entry.value);\n            }\n            const tensors = this.header.n_tensors;\n            if (tensors > 0) {\n                for (let i = 0; i < tensors; i++) {\n                    const tensor = reader.tensor();\n                    this.tensors.set(tensor.name, tensor);\n                }\n                this.alignment = this.metadata.get('general.alignment') || 32;\n                if (reader.position % this.alignment !== 0) {\n                    reader.skip(this.alignment - (reader.position % this.alignment));\n                }\n                const offset = reader.position;\n                for (const tensor of this.tensors.values()) {\n                    if (!gguf.Reader.GGML_QUANT_SIZES.has(tensor.type)) {\n                        throw new gguf.Error(`Unsupported tensor quantization type '${tensor.type}'.`);\n                    }\n                    const [block_size, type_size, dtype] = gguf.Reader.GGML_QUANT_SIZES.get(tensor.type);\n                    tensor.block_size = block_size;\n                    tensor.type_size = type_size;\n                    tensor.dtype = dtype || '?';\n                    if (offset < reader.length) {\n                        const n_elems = tensor.ne.reduce((a, b) => a * b, 1);\n                        const n_bytes = Math.floor((n_elems * type_size) / block_size);\n                        reader.seek(offset + tensor.offset);\n                        tensor.data = reader.stream(n_bytes);\n                    }\n                }\n            }\n        }\n        stream.seek(0);\n        delete this.context;\n    }\n};\n\ngguf.BinaryReader = class {\n\n    constructor(reader) {\n        this._reader = reader;\n    }\n\n    get length() {\n        return this._reader.length;\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    seek(position) {\n        this._reader.seek(position);\n    }\n\n    skip(offset) {\n        this._reader.skip(offset);\n    }\n\n    stream(length) {\n        return this._reader.stream(length);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    byte() {\n        return this._reader.byte();\n    }\n\n    int8() {\n        return this._reader.int8();\n    }\n\n    uint16() {\n        return this._reader.uint16();\n    }\n\n    int16() {\n        return this._reader.int16();\n    }\n\n    uint32() {\n        return this._reader.uint32();\n    }\n\n    int32() {\n        return this._reader.int32();\n    }\n\n    uint64() {\n        return this._reader.uint64();\n    }\n\n    int64() {\n        return this._reader.int64();\n    }\n\n    float32() {\n        return this._reader.float32();\n    }\n\n    float64() {\n        return this._reader.float64();\n    }\n\n    string() {\n        const size = this.uint64().toNumber();\n        const buffer = this.read(size);\n        return String.fromCharCode.apply(null, buffer);\n    }\n\n    value(type) {\n        switch (type) {\n            case gguf.Type.UINT8: return this.byte();\n            case gguf.Type.INT8: return this.int8();\n            case gguf.Type.UINT16: return this.uint16();\n            case gguf.Type.INT16: return this.int16();\n            case gguf.Type.UINT32: return this.uint32();\n            case gguf.Type.INT32: return this.int32();\n            case gguf.Type.UINT64: return this.uint64();\n            case gguf.Type.INT64: return this.int64();\n            case gguf.Type.FLOAT32: return this.float32();\n            case gguf.Type.FLOAT64: return this.float64();\n            case gguf.Type.BOOL: return this.byte() !== 0;\n            case gguf.Type.STRING: return this.string();\n            case gguf.Type.ARRAY: {\n                const type = this.uint32();\n                const size = this.uint64().toNumber();\n                const value = new Array(size);\n                for (let i = 0; i < size; i++) {\n                    value[i] = this.value(type);\n                }\n                return value;\n            }\n            default: {\n                throw new gguf.Error(`Unsupported GGUF type '${type}'.`);\n            }\n        }\n    }\n\n    entry() {\n        const name = this.string();\n        const type = this.uint32();\n        const value = this.value(type);\n        return { name, value, type };\n    }\n\n    tensor() {\n        const tensor = {};\n        tensor.name = this.string();\n        const n_dims = this.uint32();\n        tensor.ne = new Array(n_dims);\n        for (let i = 0; i < n_dims; i++) {\n            tensor.ne[i] = this.uint64().toNumber();\n        }\n        tensor.type = this.uint32();\n        tensor.offset = this.uint64().toNumber();\n        return tensor;\n    }\n};\n\ngguf.Type = {\n    UINT8: 0,\n    INT8: 1,\n    UINT16: 2,\n    INT16: 3,\n    UINT32: 4,\n    INT32: 5,\n    FLOAT32: 6,\n    BOOL: 7,\n    STRING: 8,\n    ARRAY: 9,\n    UINT64: 10,\n    INT64: 11,\n    FLOAT64: 12,\n};\n\n// https://github.com/ggml-org/llama.cpp/blob/master/ggml/include/ggml.h\ngguf.QuantizationType = {\n    F32: 0,\n    F16: 1,\n    Q4_0: 2,\n    Q4_1: 3,\n    Q4_2: 4, // deprecated\n    Q4_3: 5, // deprecated\n    Q5_0: 6,\n    Q5_1: 7,\n    Q8_0: 8,\n    Q8_1: 9,\n    Q2_K: 10,\n    Q3_K: 11,\n    Q4_K: 12,\n    Q5_K: 13,\n    Q6_K: 14,\n    Q8_K: 15,\n    IQ2_XXS: 16,\n    IQ2_XS: 17,\n    IQ3_XXS: 18,\n    IQ1_S: 19,\n    IQ4_NL: 20,\n    IQ3_S: 21,\n    IQ2_S: 22,\n    IQ4_XS: 23,\n    I8: 24,\n    I16: 25,\n    I32: 26,\n    I64: 27,\n    F64: 28,\n    IQ1_M: 29,\n    BF16: 30,\n    Q4_0_4_4: 31, // deprecated\n    Q4_0_4_8: 32, // deprecated\n    Q4_0_8_8: 33, // deprecated\n    TQ1_0: 34,\n    TQ2_0: 35,\n    IQ4_NL_4_4: 36, // deprecated\n    IQ4_NL_4_8: 37, // deprecated\n    IQ4_NL_8_8: 38, // deprecated\n    MXFP4: 39\n};\n\ngguf.Context = class {\n\n    constructor(metadata, target, kvMetadata, architecture) {\n        const archType = metadata ? metadata.type(architecture) : null;\n        const archDef = archType && archType.graph ? archType : null;\n        this._archDef = archDef;\n        this._tensors = target.tensors;\n        this._architecture = architecture;\n        this._blockCount = kvMetadata.get(`${architecture}.block_count`) || 0;\n        this._blockTypes = new Map();\n        if (archDef && archDef.graph) {\n            const registerSection = (section) => {\n                if (section) {\n                    for (const block of section) {\n                        this._blockTypes.set(block.name, block);\n                        if (block.tensors) {\n                            for (const tensor of block.tensors) {\n                                this._blockTypes.set(tensor, block);\n                            }\n                        }\n                    }\n                }\n            };\n            for (const section of [archDef.graph.input, archDef.graph.blocks, archDef.graph.output]) {\n                registerSection(section);\n            }\n            for (const subgraph of [archDef.graph.encoder, archDef.graph.decoder]) {\n                if (subgraph) {\n                    for (const section of [subgraph.input, subgraph.blocks, subgraph.output]) {\n                        registerSection(section);\n                    }\n                }\n            }\n        }\n    }\n\n    get structured() {\n        return this._archDef !== null && this._tensors.size > 0;\n    }\n\n    build() {\n        if (!this._archDef || this._tensors.size === 0) {\n            return this._buildFlat();\n        }\n        const tensors = this._tensors;\n        const layers = [];\n        const claimed = new Set();\n        // Collect tensors matching a prefix into a weights map\n        const collectWeights = (prefix) => {\n            const weights = new Map();\n            for (const [name, tensor] of tensors) {\n                if (name.startsWith(`${prefix}.`) || name === prefix) {\n                    const suffix = name.slice(prefix.length + 1) || 'data';\n                    weights.set(suffix, tensor);\n                    claimed.add(name);\n                }\n            }\n            return weights;\n        };\n        // Classify tensor prefix into a semantic component group\n        const classifyTensor = (name) => this._classifyTensor(name);\n        // Resolve display type and category for a component group using metadata\n        const resolveBlock = (group) => {\n            const block = this._blockTypes.get(group);\n            if (block) {\n                return { type: block.type, category: block.category };\n            }\n            return { type: 'weights' };\n        };\n        // Build global (non-block) input tensors\n        const globalPrefixes = ['token_embd', 'token_types', 'token_embd_norm', 'position_embd', 'rope_freqs'];\n        for (const prefix of globalPrefixes) {\n            const weights = collectWeights(prefix);\n            if (weights.size > 0) {\n                const resolved = resolveBlock(prefix);\n                layers.push({ name: prefix, type: resolved.type, category: resolved.category, weights, metadata: new Map(), layers: [] });\n            }\n        }\n        // Build block sub-graphs\n        for (let i = 0; i < this._blockCount; i++) {\n            const blockPrefix = `blk.${i}`;\n            // Collect all tensors in this block and group by component\n            const groups = new Map();\n            const order = [];\n            for (const [name] of tensors) {\n                if (name.startsWith(`${blockPrefix}.`)) {\n                    const rest = name.slice(blockPrefix.length + 1);\n                    const group = classifyTensor(rest);\n                    if (!groups.has(group)) {\n                        groups.set(group, new Map());\n                        order.push(group);\n                    }\n                    groups.get(group).set(rest, name);\n                }\n            }\n            // Build sub-nodes for each component group in discovery order\n            const blockLayers = [];\n            for (const group of order) {\n                const tensorMap = groups.get(group);\n                const weights = new Map();\n                for (const [suffix, fullName] of tensorMap) {\n                    const tensor = tensors.get(fullName);\n                    if (tensor) {\n                        weights.set(suffix, tensor);\n                        claimed.add(fullName);\n                    }\n                }\n                if (weights.size > 0) {\n                    const resolved = resolveBlock(group);\n                    blockLayers.push({ name: group, type: resolved.type, category: resolved.category, weights, metadata: new Map(), layers: [] });\n                }\n            }\n            if (blockLayers.length > 0) {\n                layers.push({ name: `blk.${i}`, type: this._architecture, layers: blockLayers, metadata: new Map(), weights: new Map() });\n            }\n        }\n        // Build global output tensors\n        const outputPrefixes = ['output_norm', 'output'];\n        for (const prefix of outputPrefixes) {\n            const weights = collectWeights(prefix);\n            if (weights.size > 0) {\n                const resolved = resolveBlock(prefix);\n                layers.push({ name: prefix, type: resolved.type, category: resolved.category, weights, metadata: new Map(), layers: [] });\n            }\n        }\n        // Build encoder/decoder sub-graphs for T5-style models\n        for (const [encPrefix, label] of [['enc', 'Encoder'], ['dec', 'Decoder']]) {\n            const graph = this._archDef.graph;\n            const subgraph = graph ? graph[encPrefix === 'enc' ? 'encoder' : 'decoder'] : null;\n            if (subgraph) {\n                for (const prefix of globalPrefixes) {\n                    const fullPrefix = `${encPrefix}.${prefix}`;\n                    const weights = collectWeights(fullPrefix);\n                    if (weights.size > 0) {\n                        const resolved = resolveBlock(prefix);\n                        layers.push({ name: fullPrefix, type: resolved.type, category: resolved.category, weights, metadata: new Map(), layers: [] });\n                    }\n                }\n            }\n            for (let i = 0; i < this._blockCount; i++) {\n                const blockPrefix = `${encPrefix}.blk.${i}`;\n                const groups = new Map();\n                const order = [];\n                for (const [name] of tensors) {\n                    if (name.startsWith(`${blockPrefix}.`)) {\n                        const rest = name.slice(blockPrefix.length + 1);\n                        const group = classifyTensor(rest);\n                        if (!groups.has(group)) {\n                            groups.set(group, new Map());\n                            order.push(group);\n                        }\n                        groups.get(group).set(rest, name);\n                    }\n                }\n                const blockLayers = [];\n                for (const group of order) {\n                    const tensorMap = groups.get(group);\n                    const weights = new Map();\n                    for (const [suffix, fullName] of tensorMap) {\n                        const tensor = tensors.get(fullName);\n                        if (tensor) {\n                            weights.set(suffix, tensor);\n                            claimed.add(fullName);\n                        }\n                    }\n                    if (weights.size > 0) {\n                        const resolved = resolveBlock(group);\n                        blockLayers.push({ name: group, type: resolved.type, category: resolved.category, weights, metadata: new Map(), layers: [] });\n                    }\n                }\n                if (blockLayers.length > 0) {\n                    layers.push({ name: blockPrefix, type: `${this._architecture} ${label}`, layers: blockLayers, metadata: new Map(), weights: new Map() });\n                }\n            }\n            if (subgraph) {\n                for (const prefix of outputPrefixes) {\n                    const fullPrefix = `${encPrefix}.${prefix}`;\n                    const weights = collectWeights(fullPrefix);\n                    if (weights.size > 0) {\n                        const resolved = resolveBlock(prefix);\n                        layers.push({ name: fullPrefix, type: resolved.type, category: resolved.category, weights, metadata: new Map(), layers: [] });\n                    }\n                }\n            }\n        }\n        // Collect any unclaimed tensors\n        for (const [name, tensor] of tensors) {\n            if (!claimed.has(name)) {\n                const parts = name.split('.');\n                const param = parts.pop();\n                const key = parts.join('.');\n                const existing = layers.find((l) => l.name === key && l.type === 'weights');\n                if (existing) {\n                    existing.weights.set(param, tensor);\n                } else {\n                    layers.push({ name: key || name, type: 'weights', metadata: new Map(), weights: new Map([[param, tensor]]), layers: [] });\n                }\n            }\n        }\n        return layers;\n    }\n\n    _buildFlat() {\n        const tensors = this._tensors;\n        const layers = [];\n        const claimed = new Set();\n        const blockPattern = /^blk\\.(\\d+)\\./;\n        const encDecPattern = /^(enc|dec)\\.blk\\.(\\d+)\\./;\n        const blockIndices = new Set();\n        const encDecIndices = new Map();\n        for (const [name] of tensors) {\n            const m = name.match(blockPattern);\n            if (m) {\n                blockIndices.add(parseInt(m[1], 10));\n            }\n            const m2 = name.match(encDecPattern);\n            if (m2) {\n                if (!encDecIndices.has(m2[1])) {\n                    encDecIndices.set(m2[1], new Set());\n                }\n                encDecIndices.get(m2[1]).add(parseInt(m2[2], 10));\n            }\n        }\n        if (blockIndices.size > 0 || encDecIndices.size > 0) {\n            const collectWeights = (prefix) => {\n                const weights = new Map();\n                for (const [name, tensor] of tensors) {\n                    if (name.startsWith(`${prefix}.`) || name === prefix) {\n                        const suffix = name.slice(prefix.length + 1) || 'data';\n                        weights.set(suffix, tensor);\n                        claimed.add(name);\n                    }\n                }\n                return weights;\n            };\n            const globalPrefixes = ['token_embd', 'token_types', 'token_embd_norm', 'position_embd', 'rope_freqs'];\n            for (const prefix of globalPrefixes) {\n                const weights = collectWeights(prefix);\n                if (weights.size > 0) {\n                    layers.push({ name: prefix, type: 'weights', metadata: new Map(), weights, layers: [] });\n                }\n            }\n            const buildStructuredBlocks = (blockPrefix) => {\n                const groups = new Map();\n                const order = [];\n                for (const [name] of tensors) {\n                    if (name.startsWith(`${blockPrefix}.`)) {\n                        const rest = name.slice(blockPrefix.length + 1);\n                        const group = this._classifyTensor(rest);\n                        if (!groups.has(group)) {\n                            groups.set(group, new Map());\n                            order.push(group);\n                        }\n                        groups.get(group).set(rest, name);\n                    }\n                }\n                const blockLayers = [];\n                for (const group of order) {\n                    const tensorMap = groups.get(group);\n                    const weights = new Map();\n                    for (const [suffix, fullName] of tensorMap) {\n                        const tensor = tensors.get(fullName);\n                        if (tensor) {\n                            weights.set(suffix, tensor);\n                            claimed.add(fullName);\n                        }\n                    }\n                    if (weights.size > 0) {\n                        blockLayers.push({ name: group, type: 'weights', metadata: new Map(), weights, layers: [] });\n                    }\n                }\n                return blockLayers;\n            };\n            for (const i of Array.from(blockIndices).sort((a, b) => a - b)) {\n                const blockLayers = buildStructuredBlocks(`blk.${i}`);\n                if (blockLayers.length > 0) {\n                    layers.push({ name: `blk.${i}`, type: this._architecture, layers: blockLayers, metadata: new Map(), weights: new Map() });\n                }\n            }\n            for (const [prefix, indices] of encDecIndices) {\n                for (const i of Array.from(indices).sort((a, b) => a - b)) {\n                    const blockLayers = buildStructuredBlocks(`${prefix}.blk.${i}`);\n                    if (blockLayers.length > 0) {\n                        const label = prefix === 'enc' ? 'Encoder' : 'Decoder';\n                        layers.push({ name: `${prefix}.blk.${i}`, type: `${this._architecture} ${label}`, layers: blockLayers, metadata: new Map(), weights: new Map() });\n                    }\n                }\n            }\n            const outputPrefixes = ['output_norm', 'output'];\n            for (const prefix of outputPrefixes) {\n                const weights = collectWeights(prefix);\n                if (weights.size > 0) {\n                    layers.push({ name: prefix, type: 'weights', metadata: new Map(), weights, layers: [] });\n                }\n            }\n            for (const [name, tensor] of tensors) {\n                if (!claimed.has(name)) {\n                    const parts = name.split('.');\n                    const param = parts.pop();\n                    const key = parts.join('.');\n                    const existing = layers.find((l) => l.name === key && l.type === 'weights');\n                    if (existing) {\n                        existing.weights.set(param, tensor);\n                    } else {\n                        layers.push({ name: key || name, type: 'weights', metadata: new Map(), weights: new Map([[param, tensor]]), layers: [] });\n                    }\n                }\n            }\n            return layers;\n        }\n        const flatLayers = new Map();\n        for (const [name, tensor] of tensors) {\n            const parts = name.split('.');\n            const param = parts.pop();\n            const key = parts.join('.');\n            if (!flatLayers.has(key)) {\n                flatLayers.set(key, { name: key, type: 'weights', metadata: new Map(), weights: new Map() });\n            }\n            flatLayers.get(key).weights.set(param, tensor);\n        }\n        return Array.from(flatLayers.values());\n    }\n\n    _classifyTensor(name) {\n        if (!gguf.Context._componentGroups) {\n            gguf.Context._componentGroups = [\n                { match: /^attn_norm/, group: 'attn_norm' },\n                { match: /^attn_q_norm/, group: 'attn_norm' },\n                { match: /^attn_k_norm/, group: 'attn_norm' },\n                { match: /^attn_sub_norm/, group: 'attn_norm' },\n                { match: /^attn_q_a/, group: 'attention' },\n                { match: /^attn_q_b/, group: 'attention' },\n                { match: /^attn_kv_a/, group: 'attention' },\n                { match: /^attn_kv_b/, group: 'attention' },\n                { match: /^attn_k_b/, group: 'attention' },\n                { match: /^attn_qkv/, group: 'attention' },\n                { match: /^attn_q/, group: 'attention' },\n                { match: /^attn_k/, group: 'attention' },\n                { match: /^attn_v/, group: 'attention' },\n                { match: /^attn_output/, group: 'attention' },\n                { match: /^attn_out/, group: 'attention' },\n                { match: /^attn_o\\./, group: 'attention' },\n                { match: /^attn_rel_b/, group: 'attention' },\n                { match: /^attn_sinks/, group: 'attention' },\n                { match: /^attn_rot_embd/, group: 'attention' },\n                { match: /^attn_post_norm/, group: 'attn_post_norm' },\n                { match: /^cross_attn_norm/, group: 'cross_attn_norm' },\n                { match: /^cross_attn_/, group: 'cross_attention' },\n                { match: /^ffn_norm/, group: 'ffn_norm' },\n                { match: /^ffn_gate_inp/, group: 'ffn_gate_inp' },\n                { match: /^ffn_exp_probs/, group: 'ffn_gate_inp' },\n                { match: /^ffn_gate_exps/, group: 'ffn_gate_exps' },\n                { match: /^ffn_gate\\.\\d+/, group: 'ffn_gate_exps' },\n                { match: /^ffn_up_exps/, group: 'ffn_up_exps' },\n                { match: /^ffn_up\\.\\d+/, group: 'ffn_up_exps' },\n                { match: /^ffn_down_exps/, group: 'ffn_down_exps' },\n                { match: /^ffn_down\\.\\d+/, group: 'ffn_down_exps' },\n                { match: /^ffn_gate_shexp/, group: 'ffn_gate_shexp' },\n                { match: /^ffn_up_shexp/, group: 'ffn_up_shexp' },\n                { match: /^ffn_down_shexp/, group: 'ffn_down_shexp' },\n                { match: /^ffn_gate/, group: 'ffn_gate' },\n                { match: /^ffn_up/, group: 'ffn_up' },\n                { match: /^ffn_down/, group: 'ffn_down' },\n                { match: /^ffn_act/, group: 'ffn_act' },\n                { match: /^ffn_sub_norm/, group: 'ffn_sub_norm' },\n                { match: /^ffn_post_norm/, group: 'ffn_post_norm' },\n                { match: /^ssm_/, group: 'ssm' },\n                { match: /^time_mix_/, group: 'time_mix' },\n                { match: /^channel_mix_/, group: 'channel_mix' },\n                { match: /^layer_output_norm/, group: 'layer_output_norm' },\n                { match: /^attn_output_norm/, group: 'attn_output_norm' },\n                { match: /^post_attention_norm/, group: 'attn_post_norm' }\n            ];\n        }\n        for (const rule of gguf.Context._componentGroups) {\n            if (rule.match.test(name)) {\n                return rule.group;\n            }\n        }\n        return 'other';\n    }\n};\n\ngguf.Utility = class {\n\n    static enum(type, value) {\n        gguf.Utility._enums = gguf.Utility._enums || new Map();\n        if (!gguf.Utility._enums.has(type)) {\n            const entries = new Map(Object.entries(type).map(([key, value]) => [value, key]));\n            gguf.Utility._enums.set(type, entries);\n        }\n        const entries = gguf.Utility._enums.get(type);\n        if (entries.has(value)) {\n            return entries.get(value);\n        }\n        return value;\n    }\n};\n\ngguf.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'GGML Error';\n    }\n};\n\nexport const ModelFactory = gguf.ModelFactory;\n"
  },
  {
    "path": "source/grapher.css",
    "content": "\n.node path { stroke: #333; fill: none; stroke-width: 1px; }\n.node line { stroke: #333; fill: none; stroke-width: 1px; }\n\n.node-item path { stroke-width: 0; stroke: #000; fill: #fff; }\n.node-item text { font-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"Ubuntu\", \"Droid Sans\", sans-serif, \"PingFang SC\"; font-size: 11px; text-rendering: geometricPrecision; user-select: none; }\n\n.node-item-function path { fill: #fff; }\n.node-item-function text { fill: #000; }\n.node-item-function:hover { cursor: pointer; }\n.node-item-function:hover path { fill: #eee; }\n\n.node-item-type path { fill: #333; }\n.node-item-type text { fill: #fff; }\n.node-item-type:hover { cursor: pointer; }\n.node-item-type:hover path { fill: #fff; }\n.node-item-type:hover text { fill: #000; }\n\n.node-item-type-constant path { fill: #eee; }\n.node-item-type-constant text { fill: #000; }\n.node-item-type-constant:hover path { fill: #fff; }\n\n.node-item-type-control path { fill: #eee; }\n.node-item-type-control text { fill: #000; }\n.node-item-type-control:hover path { fill: #fff; }\n\n.node-item-type-layer path { fill: rgb(51, 85, 136); }\n.node-item-type-activation path { fill: rgb(112, 41, 33); }\n.node-item-type-pool path { fill: rgb(51, 85, 51); }\n.node-item-type-normalization path { fill: rgb(51, 85, 68); }\n.node-item-type-dropout path { fill: rgb(69, 71, 112); }\n.node-item-type-shape path { fill: rgb(108, 79, 71); }\n.node-item-type-tensor path { fill: rgb(89, 66, 59); }\n.node-item-type-transform path { fill: rgb(51, 85, 68); }\n.node-item-type-data path { fill: rgb(85, 85, 85); }\n.node-item-type-quantization path { fill: rgb(80, 40, 0); }\n.node-item-type-attention path { fill: rgb(120, 60, 0); }\n\n.node-item-input path { fill: #fff; }\n.node-item-input:hover { cursor: pointer; }\n.node-item-input:hover path { fill: #fff; }\n\n.node-item-constant path { fill: #eee; }\n.node-item-constant:hover { cursor: pointer; }\n.node-item-constant:hover path { fill: #fff; }\n\n.node-item-undefined path { fill: #f00; }\n.node-item-undefined:hover { cursor: pointer; }\n.node-item-undefined:hover path { fill: #fff; }\n\n.node-argument-list > path { fill: #fff; stroke-width: 0; stroke: #000; }\n.node-argument-list:hover { cursor: pointer; }\n.node-argument-list:hover > path { fill: #f6f6f6; }\n.node-argument > text { font-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"Ubuntu\", \"Droid Sans\", sans-serif, \"PingFang SC\"; font-size: 9px; font-weight: normal; text-rendering: geometricPrecision; user-select: none; }\n.node-argument > rect { fill: transparent; }\n\n.graph-item-input path { fill: #eee; }\n.graph-item-input:hover { cursor: pointer; }\n.graph-item-input:hover path { fill: #fff; }\n\n.graph-item-output path { fill: #eee; }\n.graph-item-output:hover { cursor: pointer; }\n.graph-item-output:hover path { fill: #fff; }\n\n#arrowhead { fill: #000; }\n#arrowhead-hover { fill: rgba(220, 0, 0, 0.9); }\n#arrowhead-select { fill: rgba(220, 0, 0, 0.9); }\n\n.edge-paths { pointer-events: none; }\n.edge-path { stroke: #000; stroke-width: 1px; fill: none; marker-end: url(\"#arrowhead\"); }\n.edge-paths-hit-test { pointer-events: stroke; stroke-width: 0.5em; fill: none; stroke: #000; stroke-opacity: 0.001; }\n\n.select > .node.node-border { stroke: rgba(220, 0, 0, 0.9); stroke-width: 2px; }\n.select.edge-path { stroke: rgba(220, 0, 0, 0.9); stroke-width: 1px; marker-end: url(\"#arrowhead-select\"); }\n.select.node-argument > rect { fill: transparent; stroke: rgba(220, 0, 0, 0.9); }\n\n.edge-label { font-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"Ubuntu\", \"Droid Sans\", sans-serif, \"PingFang SC\"; font-size: 10px; }\n.edge-path-control-dependency { stroke-dasharray: 3, 2; }\n.edge-path-tunnel { stroke-dasharray: 5, 3; marker-end: url(\"#arrowhead-tunnel\"); opacity: 0.4; }\n#arrowhead-tunnel { fill: #000; }\n\n.cluster rect { stroke: #000; fill: #000; fill-opacity: 0.02; stroke-opacity: 0.06; stroke-width: 1px; }\n\n.node-block > .node-block-background { fill: #fff; stroke: none; stroke-width: 0; }\n.node-block .edge-path { stroke: #000; stroke-width: 1px; fill: none; }\n.node-block .select.edge-path { stroke: rgba(220, 0, 0, 0.9); marker-end: url(\"#arrowhead-select\"); }\n\n@keyframes pulse { from { stroke-dashoffset: 100px; } to { stroke-dashoffset: 0; } }\n\n@media (prefers-color-scheme: dark) {\n\n    .edge-path { stroke: #888; }\n\n    .node path { stroke: #242424; }\n    .node line { stroke: #242424; }\n\n    .select > .node.node-border { stroke: rgba(192, 0, 0, 0.8); }\n    .select.edge-path { stroke: rgba(192, 0, 0, 0.8); }\n    .select.node-argument > rect { fill: transparent; stroke: rgba(192, 0, 0, 0.8); }\n    #arrowhead { fill: #888; }\n    #arrowhead-hover { fill: rgba(192, 0, 0, 0.8); }\n    #arrowhead-select { fill: rgba(192, 0, 0, 0.8); }\n\n    .edge-label { fill: #b2b2b2; }\n\n    .node-item-function path { fill: #404040; }\n    .node-item-function text { fill: #dfdfdfdf; }\n    .node-item-function:hover { cursor: pointer; }\n    .node-item-function:hover path { fill: #666666; }\n    \n    .node-item-type path { fill: #303030; }\n    .node-item-type text { fill: #dfdfdf; }\n    .node-item-type:hover { cursor: pointer; }\n    .node-item-type:hover path { fill: #808080; }\n    .node-item-type:hover text { fill: #dfdfdf; }\n\n    .node-item path { stroke: #fff; }\n    .node-item text { fill: #dfdfdf; }\n\n    .node-argument > text { fill: #b2b2b2; }\n    .node-argument-list > path { fill: #2d2d2d; }\n    .node-argument-list:hover > path { fill: #303030; }\n\n    .graph-item-input path { fill: #404040; }\n    .graph-item-input:hover { cursor: pointer; }\n    .graph-item-input:hover path { fill: #666666; }\n\n    .graph-item-output path { fill: #404040; }\n    .graph-item-output:hover { cursor: pointer; }\n    .graph-item-output:hover path { fill: #666666; }\n\n    .node-item-input path { fill: #404040; }\n    .node-item-input:hover path { fill: #666666; }\n    .node-item-constant path { fill: #4b4b4b; }\n    .node-item-constant:hover path { fill: #666666; }\n\n    .node-item-type-layer path { fill: rgba(51, 85, 136, 0.7); }\n    .node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }\n    .node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }\n    .node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }\n    .node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }\n    .node-item-type-normalization path { fill: rgba(51, 85, 68, 0.7); }\n    .node-item-type-dropout path { fill: rgba(69, 71, 112, 0.7); }\n    .node-item-type-shape path { fill: rgba(108, 79, 71, 0.7); }\n    .node-item-type-tensor path { fill: rgba(89, 66, 59, 0.7); }\n    .node-item-type-transform path { fill: rgba(51, 85, 68, 0.7); }\n    .node-item-type-data path { fill: rgba(85, 85, 85, 0.7); }\n    .node-item-type-quantization path { fill: rgb(80, 40, 0, 0.7); }\n    .node-item-type-attention path { fill: rgb(100, 50, 0, 0.7); }\n    .node-item-type-custom path { fill: rgb(64, 64, 64, 0.7); }\n\n    .node-block > .node-block-background { fill: #404040; stroke: none; }\n    .node-block .edge-path { stroke: #888; }\n    .node-block .select.edge-path { stroke: rgba(192, 0, 0, 0.8); marker-end: url(\"#arrowhead-select\"); }\n\n    .edge-path-tunnel { stroke: #888; opacity: 0.4; }\n    #arrowhead-tunnel { fill: #888; }\n}"
  },
  {
    "path": "source/grapher.js",
    "content": "\nconst grapher = {};\n\ngrapher.Graph = class {\n\n    constructor(compound) {\n        this._compound = compound;\n        this._nodes = new Map();\n        this._edges = new Map();\n        this._focusable = new Map();\n        this._focused = null;\n        this._children = new Map();\n        this._children.set('\\x00', new Map());\n        this._parent = new Map();\n    }\n\n    setNode(node) {\n        const key = node.name;\n        const value = this._nodes.get(key);\n        if (value) {\n            value.label = node;\n        } else {\n            this._nodes.set(key, { v: key, label: node });\n            if (this._compound) {\n                this._parent.set(key, '\\x00');\n                this._children.set(key, new Map());\n                this._children.get('\\x00').set(key, true);\n            }\n        }\n    }\n\n    setEdge(edge) {\n        if (!this._nodes.has(edge.v)) {\n            throw new Error(`Invalid edge '${JSON.stringify(edge.v)}'.`);\n        }\n        if (!this._nodes.has(edge.w)) {\n            throw new Error(`Invalid edge '${JSON.stringify(edge.w)}'.`);\n        }\n        const key = `${edge.v}:${edge.w}`;\n        if (!this._edges.has(key)) {\n            this._edges.set(key, { v: edge.v, w: edge.w, label: edge });\n        }\n    }\n\n    setParent(node, parent) {\n        if (!this._compound) {\n            throw new Error(\"Cannot set parent in a non-compound graph\");\n        }\n        parent = String(parent);\n        for (let ancestor = parent; ancestor; ancestor = this.parent(ancestor)) {\n            if (ancestor === node) {\n                throw new Error(`Setting ${parent} as parent of ${node} would create a cycle`);\n            }\n        }\n        this._children.get(this._parent.get(node)).delete(node);\n        this._parent.set(node, parent);\n        this._children.get(parent).set(node, true);\n        return this;\n    }\n\n    get nodes() {\n        return this._nodes;\n    }\n\n    hasNode(key) {\n        return this._nodes.has(key);\n    }\n\n    node(key) {\n        return this._nodes.get(key);\n    }\n\n    edge(v, w) {\n        return this._edges.get(`${v}:${w}`);\n    }\n\n    get edges() {\n        return this._edges;\n    }\n\n    parent(key) {\n        if (this._compound) {\n            const parent = this._parent.get(key);\n            if (parent !== '\\x00') {\n                return parent;\n            }\n        }\n        return null;\n    }\n\n    children(key) {\n        key = key === undefined ? '\\x00' : key;\n        if (this._compound) {\n            const children = this._children.get(key);\n            if (children) {\n                return Array.from(children.keys());\n            }\n        } else if (key === '\\x00') {\n            return this.nodes.keys();\n        } else if (this.hasNode(key)) {\n            return [];\n        }\n        return null;\n    }\n\n    build(document, origin) {\n        origin = origin || document.getElementById('origin');\n        const createGroup = (name) => {\n            const element = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n            element.setAttribute('id', name);\n            element.setAttribute('class', name);\n            return element;\n        };\n        const clusterGroup = createGroup('clusters');\n        const edgePathGroup = createGroup('edge-paths');\n        const edgePathHitTestGroup = createGroup('edge-paths-hit-test');\n        const edgeLabelGroup = createGroup('edge-labels');\n        const nodeGroup = createGroup('nodes');\n        const edgePathGroupDefs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n        edgePathGroup.appendChild(edgePathGroupDefs);\n        const marker = (id) => {\n            const element = document.createElementNS('http://www.w3.org/2000/svg', 'marker');\n            element.setAttribute('id', id);\n            element.setAttribute('viewBox', '0 0 10 10');\n            element.setAttribute('refX', 9);\n            element.setAttribute('refY', 5);\n            element.setAttribute('markerUnits', 'strokeWidth');\n            element.setAttribute('markerWidth', 8);\n            element.setAttribute('markerHeight', 6);\n            element.setAttribute('orient', 'auto');\n            const markerPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n            markerPath.setAttribute('d', 'M 0 0 L 10 5 L 0 10 L 4 5 z');\n            markerPath.style.setProperty('stroke-width', 1);\n            element.appendChild(markerPath);\n            return element;\n        };\n        edgePathHitTestGroup.addEventListener('pointerover', (e) => {\n            if (this._focused) {\n                this._focused.blur();\n                this._focused = null;\n            }\n            const edge = this._focusable.get(e.target);\n            if (edge && edge.focus) {\n                edge.focus();\n                this._focused = edge;\n                e.stopPropagation();\n            }\n        });\n        edgePathHitTestGroup.addEventListener('pointerleave', (e) => {\n            if (this._focused) {\n                this._focused.blur();\n                this._focused = null;\n                e.stopPropagation();\n            }\n        });\n        edgePathHitTestGroup.addEventListener('click', (e) => {\n            const edge = this._focusable.get(e.target);\n            if (edge && edge.activate) {\n                edge.activate();\n                e.stopPropagation();\n            }\n        });\n        edgePathGroupDefs.appendChild(marker(\"arrowhead\"));\n        edgePathGroupDefs.appendChild(marker(\"arrowhead-select\"));\n        edgePathGroupDefs.appendChild(marker(\"arrowhead-hover\"));\n        for (const nodeId of this.nodes.keys()) {\n            const entry = this.node(nodeId);\n            const node = entry.label;\n            if (this.children(nodeId).length === 0) {\n                node.build(document, nodeGroup);\n            } else {\n                // cluster\n                node.rectangle = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n                if (node.rx) {\n                    node.rectangle.setAttribute('rx', entry.rx);\n                }\n                if (node.ry) {\n                    node.rectangle.setAttribute('ry', entry.ry);\n                }\n                node.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n                node.element.setAttribute('class', 'cluster');\n                node.element.appendChild(node.rectangle);\n                clusterGroup.appendChild(node.element);\n            }\n        }\n        this._focusable.clear();\n        this._focused = null;\n        for (const edge of this.edges.values()) {\n            edge.label.build(document, edgePathGroup, edgePathHitTestGroup, edgeLabelGroup);\n            if (edge.label.hitTest) {\n                this._focusable.set(edge.label.hitTest, edge.label);\n            }\n        }\n        const tunnelGroup = createGroup('tunnel-edges');\n        origin.appendChild(clusterGroup);\n        origin.appendChild(edgePathGroup);\n        origin.appendChild(edgePathHitTestGroup);\n        origin.appendChild(edgeLabelGroup);\n        origin.appendChild(nodeGroup);\n        origin.appendChild(tunnelGroup);\n        this._tunnelGroup = tunnelGroup;\n        this._document = document;\n        for (const edge of this.edges.values()) {\n            if (edge.label.labelElement) {\n                const label = edge.label;\n                const box = label.labelElement.getBBox();\n                label.width = box.width;\n                label.height = box.height;\n            }\n        }\n    }\n\n    async measure() {\n        for (const key of this.nodes.keys()) {\n            const entry = this.node(key);\n            if (this.children(key).length === 0) {\n                const node = entry.label;\n                /* eslint-disable no-await-in-loop */\n                await node.measure();\n                /* eslint-enable no-await-in-loop */\n            }\n        }\n    }\n\n    async layout(worker) {\n        let nodes = [];\n        for (const node of this.nodes.values()) {\n            nodes.push({\n                v: node.v,\n                width: node.label.width || 0,\n                height: node.label.height || 0,\n                parent: this.parent(node.v) });\n        }\n        let edges = [];\n        for (const edge of this.edges.values()) {\n            edges.push({\n                v: edge.v,\n                w: edge.w,\n                minlen: edge.label.minlen || 1,\n                weight: edge.label.weight || 1,\n                width: edge.label.width || 0,\n                height: edge.label.height || 0,\n                labeloffset: edge.label.labeloffset || 10,\n                labelpos: edge.label.labelpos || 'r'\n            });\n        }\n        const layout = {};\n        layout.nodesep = 20;\n        layout.ranksep = 20;\n        const direction = this.options.direction;\n        const rotate = edges.length === 0 ? direction === 'vertical' : direction !== 'vertical';\n        if (rotate) {\n            layout.rankdir = 'LR';\n        }\n        if (edges.length === 0) {\n            nodes = nodes.reverse(); // rankdir workaround\n        }\n        if (nodes.length > 3000) {\n            layout.ranker = 'longest-path';\n        }\n        const state = { /* log: true */ };\n        if (worker) {\n            const message = await worker.request({ type: 'dagre.layout', nodes, edges, layout, state }, 2500, 'This large graph layout might take a very long time to complete.');\n            if (message.type === 'cancel' || message.type === 'terminate') {\n                return message.type;\n            }\n            nodes = message.nodes;\n            edges = message.edges;\n            state.log = message.state.log;\n        } else {\n            const dagre = await import('./dagre.js');\n            dagre.layout(nodes, edges, layout, state);\n        }\n        if (state.log) {\n            const fs = await import('fs');\n            fs.writeFileSync(`dist/test/${this.identifier}.log`, state.log);\n        }\n        let minX = Infinity;\n        let minY = Infinity;\n        let maxX = -Infinity;\n        let maxY = -Infinity;\n        for (const node of nodes) {\n            const label = this.node(node.v).label;\n            label.x = node.x;\n            label.y = node.y;\n            if (this.children(node.v).length) {\n                label.width = node.width;\n                label.height = node.height;\n            }\n            const hw = (node.width || 0) / 2;\n            const hh = (node.height || 0) / 2;\n            minX = Math.min(minX, node.x - hw);\n            minY = Math.min(minY, node.y - hh);\n            maxX = Math.max(maxX, node.x + hw);\n            maxY = Math.max(maxY, node.y + hh);\n        }\n        for (const edge of edges) {\n            const label = this.edge(edge.v, edge.w).label;\n            label.points = edge.points;\n            if ('x' in edge) {\n                label.x = edge.x;\n                label.y = edge.y;\n            }\n            if (label.points) {\n                for (const point of label.points) {\n                    minX = Math.min(minX, point.x);\n                    minY = Math.min(minY, point.y);\n                    maxX = Math.max(maxX, point.x);\n                    maxY = Math.max(maxY, point.y);\n                }\n            }\n            if (label.x !== undefined && label.width && label.height) {\n                const hw = label.width / 2;\n                const hh = label.height / 2;\n                minX = Math.min(minX, label.x - hw);\n                minY = Math.min(minY, label.y - hh);\n                maxX = Math.max(maxX, label.x + hw);\n                maxY = Math.max(maxY, label.y + hh);\n            }\n        }\n        if (isFinite(minX)) {\n            this.width = maxX - minX;\n            this.height = maxY - minY;\n            this.originX = minX;\n            this.originY = minY;\n        }\n        for (const key of this.nodes.keys()) {\n            const entry = this.node(key);\n            if (this.children(key).length === 0) {\n                const node = entry.label;\n                // eslint-disable-next-line no-await-in-loop\n                await node.layout();\n            }\n        }\n        return '';\n    }\n\n    update() {\n        for (const nodeId of this.nodes.keys()) {\n            if (this.children(nodeId).length === 0) {\n                // node\n                const entry = this.node(nodeId);\n                const node = entry.label;\n                node.update();\n            } else {\n                // cluster\n                const entry = this.node(nodeId);\n                const node = entry.label;\n                node.element.setAttribute('transform', `translate(${node.x},${node.y})`);\n                node.rectangle.setAttribute('x', - node.width / 2);\n                node.rectangle.setAttribute('y', - node.height / 2);\n                node.rectangle.setAttribute('width', node.width);\n                node.rectangle.setAttribute('height', node.height);\n            }\n        }\n        for (const edge of this.edges.values()) {\n            edge.label.update();\n        }\n    }\n};\n\ngrapher.Node = class {\n\n    constructor() {\n        this.blocks = [];\n    }\n\n    header() {\n        const block = new grapher.Node.Header();\n        this.blocks.push(block);\n        return block;\n    }\n\n    list() {\n        const block = new grapher.ArgumentList();\n        this.blocks.push(block);\n        return block;\n    }\n\n    canvas() {\n        const block = new grapher.Node.Canvas();\n        this.blocks.push(block);\n        return block;\n    }\n\n    build(document, parent) {\n        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n        if (this.id) {\n            this.element.setAttribute('id', this.id);\n        }\n        this.element.setAttribute('class', this.class ? `node ${this.class}` : 'node');\n        this.element.style.opacity = 0;\n        parent.appendChild(this.element);\n        this.border = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n        this.border.setAttribute('class', 'node node-border');\n        for (let i = 0; i < this.blocks.length; i++) {\n            const block = this.blocks[i];\n            block.first = i === 0;\n            block.last = i === this.blocks.length - 1;\n            block.build(document, this.element);\n        }\n        this.element.appendChild(this.border);\n    }\n\n    async measure() {\n        this.height = 0;\n        for (const block of this.blocks) {\n            // eslint-disable-next-line no-await-in-loop\n            await block.measure();\n            this.height += block.height;\n        }\n        this.width = Math.max(...this.blocks.map((block) => block.width));\n        for (const block of this.blocks) {\n            block.width = this.width;\n        }\n    }\n\n    async layout() {\n        let y = 0;\n        for (const block of this.blocks) {\n            block.x = 0;\n            block.y = y;\n            block.width = this.width;\n            // eslint-disable-next-line no-await-in-loop\n            await block.layout();\n            y += block.height;\n        }\n    }\n\n    update() {\n        for (const block of this.blocks) {\n            block.update();\n        }\n        this.border.setAttribute('d', grapher.Node.roundedRect(0, 0, this.width, this.height, true, true, true, true));\n        this.element.setAttribute('transform', `translate(${this.x - (this.width / 2)},${this.y - (this.height / 2)})`);\n        this.element.style.removeProperty('opacity');\n    }\n\n    select() {\n        if (this.element) {\n            this.element.classList.add('select');\n            return [this.element];\n        }\n        return [];\n    }\n\n    deselect() {\n        if (this.element) {\n            this.element.classList.remove('select');\n        }\n    }\n\n    static roundedRect(x, y, width, height, r1, r2, r3, r4) {\n        const radius = 5;\n        r1 = r1 ? radius : 0;\n        r2 = r2 ? radius : 0;\n        r3 = r3 ? radius : 0;\n        r4 = r4 ? radius : 0;\n        return `M${x + r1},${y}h${width - r1 - r2}a${r2},${r2} 0 0 1 ${r2},${r2}v${height - r2 - r3}a${r3},${r3} 0 0 1 ${-r3},${r3}h${r3 + r4 - width}a${r4},${r4} 0 0 1 ${-r4},${-r4}v${-height + r4 + r1}a${r1},${r1} 0 0 1 ${r1},${-r1}z`;\n    }\n};\n\ngrapher.Node.Header = class {\n\n    constructor() {\n        this._entries = [];\n    }\n\n    add(id, classes) {\n        const entry = new grapher.Node.Header.Entry(id, classes);\n        this._entries.push(entry);\n        return entry;\n    }\n\n    build(document, parent) {\n        this._document = document;\n        for (const entry of this._entries) {\n            entry.build(document, parent);\n        }\n        if (!this.first) {\n            this.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n            parent.appendChild(this.line);\n        }\n        for (let i = 0; i < this._entries.length; i++) {\n            const entry = this._entries[i];\n            if (i !== 0) {\n                entry.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n                parent.appendChild(entry.line);\n            }\n        }\n    }\n\n    measure() {\n        this.width = 0;\n        this.height = 0;\n        for (const entry of this._entries) {\n            entry.measure();\n            this.height = Math.max(this.height, entry.height);\n            this.width += entry.width;\n        }\n    }\n\n    layout() {\n        let x = this.width;\n        for (let i = this._entries.length - 1; i >= 0; i--) {\n            const entry = this._entries[i];\n            if (i > 0) {\n                x -= entry.width;\n                entry.x = x;\n            } else {\n                entry.x = 0;\n                entry.width = x;\n            }\n        }\n    }\n\n    update() {\n        for (let i = 0; i < this._entries.length; i++) {\n            const entry = this._entries[i];\n            entry.element.setAttribute('transform', `translate(${entry.x},${this.y})`);\n            const r1 = i === 0 && this.first;\n            const r2 = i === this._entries.length - 1 && this.first;\n            const r3 = i === this._entries.length - 1 && this.last;\n            const r4 = i === 0 && this.last;\n            entry.path.setAttribute('d', grapher.Node.roundedRect(0, 0, entry.width, entry.height, r1, r2, r3, r4));\n            entry.text.setAttribute('x', entry.tx || 6);\n            entry.text.setAttribute('y', entry.ty);\n        }\n        if (this.line) {\n            this.line.setAttribute('class', 'node');\n            this.line.setAttribute('x1', 0);\n            this.line.setAttribute('x2', this.width);\n            this.line.setAttribute('y1', this.y);\n            this.line.setAttribute('y2', this.y);\n        }\n    }\n};\n\ngrapher.Node.Header.Entry = class {\n\n    constructor(id, classes) {\n        this.id = id;\n        this.classes = classes;\n        this._events = {};\n    }\n\n    on(event, callback) {\n        this._events[event] = this._events[event] || [];\n        this._events[event].push(callback);\n    }\n\n    emit(event, data) {\n        if (this._events && this._events[event]) {\n            for (const callback of this._events[event]) {\n                callback(this, data);\n            }\n        }\n    }\n\n    build(document, parent) {\n        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n        parent.appendChild(this.element);\n        this.path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n        this.text = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n        this.element.appendChild(this.path);\n        this.element.appendChild(this.text);\n        const classList = ['node-item'];\n        if (this.classes) {\n            classList.push(...this.classes);\n        }\n        this.element.setAttribute('class', classList.join(' '));\n        if (this.id) {\n            this.element.setAttribute('id', this.id);\n        }\n        if (this._events.click) {\n            this.element.addEventListener('click', (e) => {\n                e.stopPropagation();\n                this.emit('click');\n            });\n        }\n        if (this.tooltip) {\n            const title = document.createElementNS('http://www.w3.org/2000/svg', 'title');\n            title.textContent = this.tooltip;\n            this.element.appendChild(title);\n        }\n        this.text.textContent = this.content || '\\u00A0';\n    }\n\n    measure() {\n        const yPadding = 4;\n        const xPadding = this.padding || 7;\n        const boundingBox = this.text.getBBox();\n        this.width = boundingBox.width + xPadding + xPadding;\n        this.height = boundingBox.height + yPadding + yPadding;\n        this.tx = xPadding;\n        this.ty = yPadding - boundingBox.y;\n    }\n\n    layout() {\n    }\n};\n\ngrapher.ArgumentList = class {\n\n    constructor() {\n        this._items = [];\n        this._events = {};\n    }\n\n    argument(name, value) {\n        return new grapher.Argument(name, value);\n    }\n\n    add(value) {\n        this._items.push(value);\n    }\n\n    on(event, callback) {\n        this._events[event] = this._events[event] || [];\n        this._events[event].push(callback);\n    }\n\n    emit(event, data) {\n        if (this._events && this._events[event]) {\n            for (const callback of this._events[event]) {\n                callback(this, data);\n            }\n        }\n    }\n\n    build(document, parent) {\n        this._document = document;\n        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n        this.element.setAttribute('class', 'node-argument-list');\n        if (this._events.click) {\n            this.element.addEventListener('click', (e) => {\n                e.stopPropagation();\n                this.emit('click');\n            });\n        }\n        this.background = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n        this.element.appendChild(this.background);\n        parent.appendChild(this.element);\n        for (const item of this._items) {\n            item.build(document, this.element);\n        }\n        if (!this.first) {\n            this.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n            this.line.setAttribute('class', 'node');\n            this.element.appendChild(this.line);\n        }\n    }\n\n    async measure() {\n        this.width = 75;\n        this.height = 3;\n        for (let i = 0; i < this._items.length; i++) {\n            const item = this._items[i];\n            /* eslint-disable no-await-in-loop */\n            await item.measure();\n            /* eslint-enable no-await-in-loop */\n            this.height += item.height;\n            this.width = Math.max(this.width, item.width);\n            if (item.type === 'node' || item.type === 'node[]') {\n                if (i === this._items.length - 1) {\n                    this.height += 3;\n                }\n            }\n        }\n        for (const item of this._items) {\n            item.width = this.width;\n        }\n        this.height += 3;\n    }\n\n    async layout() {\n        let y = 3;\n        for (const item of this._items) {\n            item.x = this.x;\n            item.y = y;\n            item.width = this.width;\n            /* eslint-disable no-await-in-loop */\n            await item.layout();\n            /* eslint-enable no-await-in-loop */\n            y += item.height;\n        }\n    }\n\n    update() {\n        this.element.setAttribute('transform', `translate(${this.x},${this.y})`);\n        this.background.setAttribute('d', grapher.Node.roundedRect(0, 0, this.width, this.height, this.first, this.first, this.last, this.last));\n        for (const item of this._items) {\n            item.update();\n        }\n        if (this.line) {\n            this.line.setAttribute('x1', 0);\n            this.line.setAttribute('x2', this.width);\n            this.line.setAttribute('y1', 0);\n            this.line.setAttribute('y2', 0);\n        }\n    }\n};\n\ngrapher.Argument = class {\n\n    constructor(name, content) {\n        this.name = name;\n        this.content = content;\n        this.tooltip = '';\n        this.separator = '';\n        if (content instanceof grapher.Node) {\n            this.type = 'node';\n        } else if (Array.isArray(content) && content.every((value) => value instanceof grapher.Node)) {\n            this.type = 'node[]';\n        }\n    }\n\n    build(document, parent) {\n        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n        this.element.setAttribute('class', 'node-argument');\n        this.border = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n        this.border.setAttribute('rx', 3);\n        this.border.setAttribute('ry', 3);\n        this.element.appendChild(this.border);\n        const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n        text.setAttribute('xml:space', 'preserve');\n        if (this.tooltip) {\n            const title = document.createElementNS('http://www.w3.org/2000/svg', 'title');\n            title.textContent = this.tooltip;\n            text.appendChild(title);\n        }\n        const colon = this.type === 'node' || this.type === 'node[]';\n        const name = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\n        name.textContent =  colon ? `${this.name}:` : this.name;\n        if (this.separator.trim() !== '=' && !colon) {\n            name.style.fontWeight = 'bold';\n        }\n        if (this.focus) {\n            this.element.addEventListener('pointerover', (e) => {\n                this.focus();\n                e.stopPropagation();\n            });\n        }\n        if (this.blur) {\n            this.element.addEventListener('pointerleave', (e) => {\n                this.blur();\n                e.stopPropagation();\n            });\n        }\n        if (this.activate) {\n            this.element.addEventListener('click', (e) => {\n                this.activate();\n                e.stopPropagation();\n            });\n        }\n        text.appendChild(name);\n        this.element.appendChild(text);\n        parent.appendChild(this.element);\n        this.text = text;\n        switch (this.type) {\n            case 'node': {\n                const node = this.content;\n                node.build(document, this.element);\n                break;\n            }\n            case 'node[]': {\n                for (const node of this.content) {\n                    node.build(document, this.element);\n                }\n                break;\n            }\n            default: {\n                const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\n                tspan.textContent = (this.separator || '') + this.content;\n                this.text.appendChild(tspan);\n                break;\n            }\n        }\n    }\n\n    async measure() {\n        const yPadding = 1;\n        const xPadding = 6;\n        const size = this.text.getBBox();\n        this.width = xPadding + size.width + xPadding;\n        this.bottom = yPadding + size.height + yPadding;\n        this.offset = size.y;\n        this.height = this.bottom;\n        if (this.type === 'node') {\n            const node = this.content;\n            await node.measure();\n            this.width = Math.max(150, this.width, node.width + (2 * xPadding));\n            this.height += node.height + yPadding + yPadding + yPadding + yPadding;\n        } else if (this.type === 'node[]') {\n            for (const node of this.content) {\n                /* eslint-disable no-await-in-loop */\n                await node.measure();\n                /* eslint-enable no-await-in-loop */\n                this.width = Math.max(150, this.width, node.width + (2 * xPadding));\n                this.height += node.height + yPadding + yPadding + yPadding + yPadding;\n            }\n        }\n    }\n\n    async layout() {\n        const yPadding = 1;\n        const xPadding = 6;\n        let y = this.y + this.bottom;\n        if (this.type === 'node') {\n            const node = this.content;\n            node.width = this.width - xPadding - xPadding;\n            await node.layout();\n            node.x = this.x + xPadding + (node.width / 2);\n            node.y = y + (node.height / 2) + yPadding + yPadding;\n        } else if (this.type === 'node[]') {\n            for (const node of this.content) {\n                node.width = this.width - xPadding - xPadding;\n                // eslint-disable-next-line no-await-in-loop\n                await node.layout();\n                node.x = this.x + xPadding + (node.width / 2);\n                node.y = y + (node.height / 2) + yPadding + yPadding;\n                y += node.height + yPadding + yPadding + yPadding + yPadding;\n            }\n        }\n    }\n\n    update() {\n        const yPadding = 1;\n        const xPadding = 6;\n        this.text.setAttribute('x', this.x + xPadding);\n        this.text.setAttribute('y', this.y + yPadding - this.offset);\n        this.border.setAttribute('x', this.x + 3);\n        this.border.setAttribute('y', this.y);\n        this.border.setAttribute('width', this.width - 6);\n        this.border.setAttribute('height', this.height);\n        if (this.type === 'node') {\n            const node = this.content;\n            node.update();\n        } else if (this.type === 'node[]') {\n            for (const node of this.content) {\n                node.update();\n            }\n        }\n    }\n\n    select() {\n        if (this.element) {\n            this.element.classList.add('select');\n            return [this.element];\n        }\n        return [];\n    }\n\n    deselect() {\n        if (this.element) {\n            this.element.classList.remove('select');\n        }\n    }\n};\n\ngrapher.Node.Canvas = class {\n\n    constructor() {\n        this.width = 0;\n        this.height = 80;\n    }\n\n    build(/* document, parent */) {\n    }\n\n    update(/* parent, top, width , first, last */) {\n    }\n};\n\ngrapher.Edge = class {\n\n    constructor(from, to) {\n        this.from = from;\n        this.to = to;\n    }\n\n    build(document, edgePathGroupElement, edgePathHitTestGroupElement, edgeLabelGroupElement) {\n        if (this._tunnel) {\n            // Tunnel edges are rendered separately\n            return;\n        }\n        const createElement = (name) => {\n            return document.createElementNS('http://www.w3.org/2000/svg', name);\n        };\n        this.element = createElement('path');\n        if (this.id) {\n            this.element.setAttribute('id', this.id);\n        }\n        this.element.setAttribute('class', this.class ? `edge-path ${this.class}` : 'edge-path');\n        edgePathGroupElement.appendChild(this.element);\n        this.hitTest = createElement('path');\n        edgePathHitTestGroupElement.appendChild(this.hitTest);\n        if (this.label) {\n            const tspan = createElement('tspan');\n            tspan.setAttribute('xml:space', 'preserve');\n            tspan.setAttribute('dy', '1em');\n            tspan.setAttribute('x', '1');\n            tspan.appendChild(document.createTextNode(this.label));\n            this.labelElement = createElement('text');\n            this.labelElement.appendChild(tspan);\n            this.labelElement.style.opacity = 0;\n            this.labelElement.setAttribute('class', 'edge-label');\n            if (this.id) {\n                this.labelElement.setAttribute('id', `edge-label-${this.id}`);\n            }\n            edgeLabelGroupElement.appendChild(this.labelElement);\n        }\n    }\n\n    update() {\n        if (this._tunnel) {\n            return;\n        }\n        const intersectRect = (node, point) => {\n            const x = node.x;\n            const y = node.y;\n            const dx = point.x - x;\n            const dy = point.y - y;\n            let h = node.height / 2;\n            let w = node.width / 2;\n            if (Math.abs(dy) * w > Math.abs(dx) * h) {\n                if (dy < 0) {\n                    h = -h;\n                }\n                return { x: x + (dy === 0 ? 0 : h * dx / dy), y: y + h };\n            }\n            if (dx < 0) {\n                w = -w;\n            }\n            return { x: x + w, y: y + (dx === 0 ? 0 : w * dy / dx) };\n        };\n        const curvePath = (edge, tail, head) => {\n            const points = edge.points.slice(1, edge.points.length - 1);\n            points.unshift(intersectRect(tail, points[0]));\n            points.push(intersectRect(head, points[points.length - 1]));\n            return new grapher.Edge.Curve(points).path.data;\n        };\n        const edgePath = curvePath(this, this.from, this.to);\n        this.element.setAttribute('d', edgePath);\n        this.hitTest.setAttribute('d', edgePath);\n        if (this.labelElement) {\n            this.labelElement.setAttribute('transform', `translate(${this.x - (this.width / 2)},${this.y - (this.height / 2)})`);\n            this.labelElement.style.opacity = 1;\n        }\n    }\n\n    select() {\n        if (this.element) {\n            if (!this.element.classList.contains('select')) {\n                const path = this.element;\n                path.classList.add('select');\n                this.element = path.cloneNode(true);\n                path.parentNode.replaceChild(this.element, path);\n            }\n            return [this.element];\n        }\n        return [];\n    }\n\n    deselect() {\n        if (this.element && this.element.classList.contains('select')) {\n            const path = this.element;\n            path.classList.remove('select');\n            this.element = path.cloneNode(true);\n            path.parentNode.replaceChild(this.element, path);\n        }\n    }\n};\n\ngrapher.Edge.Curve = class {\n\n    constructor(points) {\n        this._path = new grapher.Edge.Path();\n        this._x0 = NaN;\n        this._x1 = NaN;\n        this._y0 = NaN;\n        this._y1 = NaN;\n        this._state = 0;\n        for (let i = 0; i < points.length; i++) {\n            const point = points[i];\n            this.point(point.x, point.y);\n            if (i === points.length - 1) {\n                switch (this._state) {\n                    case 3:\n                        this.curve(this._x1, this._y1);\n                        this._path.lineTo(this._x1, this._y1);\n                        break;\n                    case 2:\n                        this._path.lineTo(this._x1, this._y1);\n                        break;\n                    default:\n                        break;\n                }\n                if (this._line || (this._line !== 0 && this._point === 1)) {\n                    this._path.closePath();\n                }\n                this._line = 1 - this._line;\n            }\n        }\n    }\n\n    get path() {\n        return this._path;\n    }\n\n    point(x, y) {\n        x = Number(x);\n        y = Number(y);\n        switch (this._state) {\n            case 0:\n                this._state = 1;\n                if (this._line) {\n                    this._path.lineTo(x, y);\n                } else {\n                    this._path.moveTo(x, y);\n                }\n                break;\n            case 1:\n                this._state = 2;\n                break;\n            case 2:\n                this._state = 3;\n                this._path.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);\n                this.curve(x, y);\n                break;\n            default:\n                this.curve(x, y);\n                break;\n        }\n        this._x0 = this._x1;\n        this._x1 = x;\n        this._y0 = this._y1;\n        this._y1 = y;\n    }\n\n    curve(x, y) {\n        this._path.bezierCurveTo(\n            (2 * this._x0 + this._x1) / 3,\n            (2 * this._y0 + this._y1) / 3,\n            (this._x0 + 2 * this._x1) / 3,\n            (this._y0 + 2 * this._y1) / 3,\n            (this._x0 + 4 * this._x1 + x) / 6,\n            (this._y0 + 4 * this._y1 + y) / 6\n        );\n    }\n};\n\ngrapher.Edge.Path = class {\n\n    constructor() {\n        this._x0 = null;\n        this._y0 = null;\n        this._x1 = null;\n        this._y1 = null;\n        this._data = '';\n    }\n\n    moveTo(x, y) {\n        this._x0 = x;\n        this._x1 = x;\n        this._y0 = y;\n        this._y1 = y;\n        this._data += `M${x},${y}`;\n    }\n\n    lineTo(x, y) {\n        this._x1 = x;\n        this._y1 = y;\n        this._data += `L${x},${y}`;\n    }\n\n    bezierCurveTo(x1, y1, x2, y2, x, y) {\n        this._x1 = x;\n        this._y1 = y;\n        this._data += `C${x1},${y1},${x2},${y2},${x},${y}`;\n    }\n\n    closePath() {\n        if (this._x1 !== null) {\n            this._x1 = this._x0;\n            this._y1 = this._y0;\n            this._data += \"Z\";\n        }\n    }\n\n    get data() {\n        return this._data;\n    }\n};\n\nexport const { Graph, Node, Edge, Argument } = grapher;"
  },
  {
    "path": "source/hailo-metadata.json",
    "content": "[\n  {\n    \"name\": \"input_layer\",\n    \"description\": \"Represents an input of the model\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"output_layer\",\n    \"description\": \"Represents an output of the model\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"postprocess\",\n    \"description\": \"Represents a whole post-processing function of some meta-architecture\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"max_proposals_per_class\",\n        \"type\": \"int64\",\n        \"description\": \"Maximum number of proposals per class\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"iou_th\",\n        \"type\": \"float32\",\n        \"visible\": false,\n        \"description\": \"Intersection over union overlap threshold, used in the NMS iterative elimination process where potential duplicates of detected items are ignored\"\n      },\n      {\n        \"name\": \"meta_arch\",\n        \"type\": \"string\",\n        \"visible\": false,\n        \"description\": \"Postprocessing meta-architecture name\"\n      },\n      {\n        \"name\": \"max_total_output_proposals\",\n        \"type\": \"int64\",\n        \"visible\": false,\n        \"description\": \"Maximum number of bounding box proposals\"\n      },\n      {\n        \"name\": \"postprocess_type\",\n        \"type\": \"string\",\n        \"visible\": false,\n        \"description\": \"Postprocessing type name\"\n      }\n    ]\n  },\n  {\n    \"name\": \"conv\",\n    \"category\": \"Layer\",\n    \"description\": \"Convolution layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"strides\",\n        \"type\": \"int64[]\",\n        \"description\": \"Stride along each axis (batch, height, width, features)\"\n      },\n      {\n        \"name\": \"dilations\",\n        \"type\": \"int64[]\",\n        \"description\": \"Dilation value along each axis (batch, height, width, features)\"\n      },\n      {\n        \"name\": \"padding\",\n        \"type\": \"string\",\n        \"description\": \"Padding mode, either VALID, SAME (symmetric, Caffe-like), SAME_TENSORFLOW, or DECONV\"\n      },\n      {\n        \"name\": \"groups\",\n        \"type\": \"int64\",\n        \"description\": \"Number of groups input channels and output channels are divided into\"\n      },\n      {\n        \"name\": \"batch_norm\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether batch normalization is folded into the layer\"\n      },\n      {\n        \"name\": \"elementwise_add\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether elementwise addition is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"pre_layer_batch_norm\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether batch normalization is folded into the layer, before the operation itself\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"transpose_output_width_features\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether to transpose the width and the features axes of the layer's output tensor\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"spatial_flatten_output\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether to flatten the layer's output to one row\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"relu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"delta\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"activation\",\n    \"category\": \"Activation\",\n    \"description\": \"Activation function\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"batch_norm\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether batch normalization is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"elementwise_add\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether elementwise addition is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"argmax\",\n    \"description\": \"Argmax layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"avgpool\",\n    \"category\": \"Pool\",\n    \"description\": \"Average pooling layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"strides\",\n        \"type\": \"int64[]\",\n        \"description\": \"Stride along each axis (batch, height, width, features)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"padding\",\n        \"type\": \"string\",\n        \"description\": \"Padding mode, either VALID, SAME (symmetric, Caffe-like), SAME_TENSORFLOW, or DECONV\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"batch_norm\",\n    \"category\": \"Normalization\",\n    \"description\": \"Batch normalization layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"elementwise_add\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether elementwise addition is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"bbox_decoder\",\n    \"description\": \"Bounding box decoding layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"deconv\",\n    \"category\": \"Layer\",\n    \"description\": \"Deconvolution (transposed convolution) layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"strides\",\n        \"type\": \"int64[]\",\n        \"description\": \"Stride along each axis (batch, height, width, features)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"dilations\",\n        \"type\": \"int64[]\",\n        \"description\": \"Dilation value along each axis (batch, height, width, features)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"padding\",\n        \"type\": \"string\",\n        \"description\": \"Padding mode, either VALID, SAME (symmetric, Caffe-like), SAME_TENSORFLOW, or DECONV\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"groups\",\n        \"type\": \"int64\",\n        \"description\": \"Number of groups input channels and output channels are divided into\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"batch_norm\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether batch normalization is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"elementwise_add\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether elementwise addition is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"dense\",\n    \"category\": \"Layer\",\n    \"description\": \"Dense (fully connected) layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"batch_norm\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether batch normalization is folded into the layer\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"depth_to_space\",\n    \"description\": \"Depth to space layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"block_sizes\",\n        \"type\": \"int64[]\",\n        \"description\": \"Block size along each spatial axis\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"depth_to_space_type\",\n        \"type\": \"string\",\n        \"description\": \"Depth to space variant, either dcr (depth-column-row) or crd (column-row-depth)\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"dw\",\n    \"description\": \"Depthwise convolution layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"strides\",\n        \"type\": \"int64[]\",\n        \"description\": \"Stride along each axis (batch, height, width, features)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"dilations\",\n        \"type\": \"int64[]\",\n        \"description\": \"Dilation value along each axis (batch, height, width, features)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"padding\",\n        \"type\": \"string\",\n        \"description\": \"Padding mode, either VALID, SAME (symmetric, Caffe-like), SAME_TENSORFLOW, or DECONV\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"groups\",\n        \"type\": \"int64\",\n        \"description\": \"Number of groups input channels and output channels are divided into\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"batch_norm\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether batch normalization is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"elementwise_add\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether elementwise addition is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"transpose_output_width_features\",\n        \"type\": \"string\",\n        \"description\": \"Whether to transpose the width and the features axes of the layer's output tensor\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"dynamic_weights\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether the layer's weights are data driven\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"external_pad\",\n    \"description\": \"Padding layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"external_pad_params\",\n        \"type\": \"int64[]\",\n        \"description\": \"Padding value in pixels in each edge (top, bottom, left, right)\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"feature_interleave\",\n    \"description\": \"Feature interleave layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"feature_multiplier\",\n    \"description\": \"Elementwise feature multiplication layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"feature_multiplier_type\",\n        \"type\": \"string\",\n        \"description\": \"Feature multiplier variant, either square (to multiply each value by itself), or user_specified\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"feature_shuffle\",\n    \"description\": \"Feature shuffle layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"format_conversion\",\n    \"description\": \"Reshapes the input tensor between different memory layouts\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"expand_spatial_sizes\",\n        \"type\": \"int64[]\",\n        \"description\": \"New output tensor dimensions after the reshape (height, width)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"conversion_type\",\n        \"type\": \"string\",\n        \"visible\": false,\n        \"description\": \"Format conversion variant\"\n      }\n    ]\n  },\n  {\n    \"name\": \"global_avg_pool\",\n    \"category\": \"Pool\",\n    \"description\": \"Global average pooling layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"maxpool\",\n    \"category\": \"Pool\",\n    \"description\": \"Maximum pooling layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"strides\",\n        \"type\": \"int64[]\",\n        \"description\": \"Stride along each axis (batch, height, width, features)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"padding\",\n        \"type\": \"string\",\n        \"description\": \"Padding mode, either VALID, SAME (symmetric, Caffe-like), SAME_TENSORFLOW, or DECONV\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"nms\",\n    \"description\": \"Non-maximum suppression layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"scores_threshold\",\n        \"type\": \"float32\",\n        \"description\": \"Confidence threshold for NMS filtering\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"iou_threshold\",\n        \"type\": \"float32\",\n        \"description\": \"Intersection over union overlap threshold, used in the NMS iterative elimination process where potential duplicates of detected items are ignored\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"classes\",\n        \"type\": \"int64\",\n        \"description\": \"Number of NMS classes\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"max_output_size\",\n        \"type\": \"int64\",\n        \"description\": \"Maximum number of proposals per class\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"normalization\",\n    \"category\": \"Normalization\",\n    \"description\": \"Normalization layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"elementwise_add\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether elementwise addition is folded into the layer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"proposal_generator\",\n    \"description\": \"Proposal generator layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"reduce_l2\",\n    \"description\": \"Reduce layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"reduce_max\",\n    \"description\": \"Reduce Max layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"groups\",\n        \"type\": \"int64\",\n        \"description\": \"Number of groups input channels and output channels are divided into\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"reduce_sum\",\n    \"description\": \"Reduce Sum layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"groups\",\n        \"type\": \"int64\",\n        \"description\": \"Number of groups input channels and output channels are divided into\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"reduce_axes\",\n        \"type\": \"int64[]\",\n        \"description\": \"List of axes to reduce\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"resize\",\n    \"category\": \"Tensor\",\n    \"description\": \"Resize layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"resize_h_ratio_list\",\n        \"type\": \"float32[]\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"resize_w_ratio_list\",\n        \"type\": \"float32[]\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"resize_f_ratio_list\",\n        \"type\": \"float32[]\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"method\",\n        \"type\": \"string\",\n        \"description\": \"Resize method, either bilinear or nearest_neighbor\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"resize_bilinear_pixels_mode\",\n        \"type\": \"string\",\n        \"description\": \"Bilinear resize variant, either half_pixels, align_corners, or disabled (where both align_corners and half_pixels are false)\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"shortcut\",\n    \"description\": \"Shortcut layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"slice\",\n    \"description\": \"Slice layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"height_slice\",\n        \"type\": \"int64[]\",\n        \"visible\": false,\n        \"description\": \"Slice in the height axis (start, stop, step)\"\n      },\n      {\n        \"name\": \"width_slice\",\n        \"type\": \"int64[]\",\n        \"visible\": false,\n        \"description\": \"Slice in the width axis (start, stop, step)\"\n      },\n      {\n        \"name\": \"features_slice\",\n        \"type\": \"int64[]\",\n        \"visible\": false,\n        \"description\": \"Slice in the features axis (start, stop, step)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\",\n    \"description\": \"Softmax layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"groups\",\n        \"type\": \"int64\",\n        \"description\": \"Number of groups input channels and output channels are divided into\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"space_to_depth\",\n    \"description\": \"Space to depth layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"block_sizes\",\n        \"type\": \"int64[]\",\n        \"description\": \"Block size along each spatial axis\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"space_to_depth_type\",\n        \"type\": \"string\",\n        \"description\": \"Space to depth variant, either classic_dcr (depth-column-row) classic_crd (column-row-depth), serial (used by Transformers patchify function), or focus (Yolov5-like)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"spatial_flatten_output\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether to flatten the layer's output to one row\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"output_mux\",\n    \"description\": \"Output muxer layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"concat\",\n    \"category\": \"Tensor\",\n    \"description\": \"Concatenation layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"concat_axis\",\n        \"type\": \"int64\",\n        \"description\": \"Axis to concatenate along, either features or spatial_w (which means the width axis)\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"spatial_w_concat\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether the concat operation is in the width dimension\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"matmul\",\n    \"description\": \"Matrix multiplication layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"kernel_shape\",\n        \"type\": \"int64[]\",\n        \"label\": \"kernel\",\n        \"description\": \"Shape of the kernel in Tensorflow convention (kernel height, kernel width, features in, features out)\",\n        \"visible\": true\n      },\n      {\n        \"name\": \"dynamic_weights\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether the layer's weights are data driven\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"transpose_matmul_input\",\n        \"type\": \"boolean\",\n        \"description\": \"Whether to transpose the width and the features axes of the layer's second input tensor\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"ew_add\",\n    \"description\": \"Elementwise addition layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"ew_div\",\n    \"description\": \"Elementwise division layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"ew_mult\",\n    \"description\": \"Elementwise multiplication layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"ew_sub\",\n    \"description\": \"Elementwise subtraction layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"activation\",\n        \"type\": \"string\",\n        \"description\": \"Activation function name\",\n        \"visible\": false\n      }\n    ]\n  },\n  {\n    \"name\": \"demux\",\n    \"description\": \"Demuxer layer\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"row_splitter\",\n    \"description\": \"Splits the input tensor along the height axis\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"feature_splitter\",\n    \"description\": \"Splits the input tensor along the features axis\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"const_input\",\n    \"category\": \"Constant\",\n    \"description\": \"Constant input\",\n    \"attributes\": [\n      {\n        \"name\": \"original_names\",\n        \"type\": \"string[]\",\n        \"description\": \"Name of this layer in the original framework, such as Pytorch or Tensorflow\",\n        \"visible\": false\n      }]\n  },\n  {\n    \"name\": \"inv_pos\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"exp\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"silu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"leaky\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"layer_normalization\",\n    \"category\": \"Normalization\"\n  }\n]\n\n"
  },
  {
    "path": "source/hailo.js",
    "content": "// Experimental\n\nconst hailo = {};\n\nhailo.ModelFactory = class {\n\n    async match(context) {\n        const container = await hailo.Container.open(context);\n        if (container) {\n            return context.set(container.type, container);\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        if (context.type === 'hailo.metadata' && (match.type === 'hailo.configuration' || match.type === 'npz' || match.type === 'onnx.proto')) {\n            return false;\n        }\n        if (context.type === 'hailo.configuration' && match.type === 'npz') {\n            return false;\n        }\n        return true;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('hailo-metadata.json');\n        const target = context.value;\n        await target.read();\n        return new hailo.Model(metadata, target);\n    }\n};\n\nhailo.Model = class {\n\n    constructor(metadata, container) {\n        const configuration = container.configuration;\n        this.modules = [new hailo.Graph(metadata, configuration, container.weights)];\n        this.name = configuration && configuration.name || \"\";\n        this.format = container.format + (container.metadata && container.metadata.sdk_version ? ` v${container.metadata.sdk_version}` : '');\n        this.metadata = [];\n        if (container.metadata && container.metadata.state) {\n            this.metadata.push(new hailo.Argument('state', container.metadata.state));\n        }\n    }\n};\n\nhailo.Graph = class {\n\n    constructor(metadata, configuration, weights) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (name.length === 0 && tensor) {\n                return new hailo.Value(name, type || null, tensor);\n            }\n            if (!values.has(name)) {\n                values.set(name, new hailo.Value(name, type || null, tensor || null));\n            } else if (tensor) {\n                throw new hailo.Error(`Duplicate value '${name}'.`);\n            } else if (type && !type.equals(values.get(name).type)) {\n                throw new hailo.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const layers = Object.entries(configuration.layers || {}).map(([name, value]) => {\n            value.name = name;\n            return value;\n        });\n        const inputs = new Set();\n        for (const layer of layers) {\n            switch (layer.type) {\n                case 'input_layer': {\n                    for (let i = 0; i < layer.output.length; i++) {\n                        const shape = Array.isArray(layer.output_shapes) && layer.output_shapes.length > 0 ? layer.output_shapes[0] : null;\n                        const type = shape ? new hailo.TensorType('?', new hailo.TensorShape(shape)) : null;\n                        const output = layer.output[i];\n                        if (!inputs.has(output)) {\n                            const name = `${layer.name}\\n${output}`;\n                            const argument = new hailo.Argument('input', [values.map(name, type)]);\n                            this.inputs.push(argument);\n                            inputs.add(output);\n                        }\n                    }\n                    break;\n                }\n                case 'output_layer': {\n                    for (let i = 0; i < layer.input.length; i++) {\n                        const shape = Array.isArray(layer.input_shapes) && layer.input_shapes.length > 0 ? layer.input_shapes[i] : null;\n                        const type = shape ? new hailo.TensorType('?', new hailo.TensorShape(shape)) : null;\n                        const input = layer.input[i];\n                        const name = `${input}\\n${layer.name}`;\n                        const argument = new hailo.Argument('output', [values.map(name, type)]);\n                        this.outputs.push(argument);\n                    }\n                    break;\n                }\n                default: {\n                    const node = new hailo.Node(metadata, layer, values, weights.get(layer.name));\n                    this.nodes.push(node);\n                    break;\n                }\n            }\n        }\n    }\n};\n\nhailo.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nhailo.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new hailo.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nhailo.Node = class {\n\n    constructor(metadata, layer, values, weights) {\n        weights = weights || new Map();\n        this.name = layer.name || '';\n        this.type = metadata.type(layer.type);\n        if (layer.type === 'activation') {\n            const name = layer.params.activation || layer.name || '';\n            this.type = { ...this.type, name };\n        }\n        this.inputs = layer.input.map((name, index) => {\n            const shape = layer.input_shapes ? layer.input_shapes[index] : null;\n            const type = shape ? new hailo.TensorType('?', new hailo.TensorShape(shape)) : null;\n            name = `${name}\\n${layer.name}`;\n            return new hailo.Argument(\"input\", [values.map(name, type, null)]);\n        });\n        const layer_params = layer.params ? Object.entries(layer.params) : [];\n        const params_list = layer_params.reduce((acc, [name, value]) => {\n            const schema = metadata.attribute(layer.type, name) || {};\n            if (schema.visible) {\n                const label = schema.label ? schema.label : name;\n                if (!weights.has(label)) {\n                    const array = weights.get(label);\n                    const tensor = new hailo.Tensor(array, value);\n                    acc.push(new hailo.Argument(label, [values.map('', tensor.type, tensor)]));\n                }\n            }\n            return acc;\n        }, []);\n        const params_from_npz = Array.from(weights).filter(([, value]) => value).map(([name, value]) => {\n            const tensor = new hailo.Tensor(value);\n            return new hailo.Argument(name, [values.map('', tensor.type, tensor)]);\n        });\n        this.inputs = this.inputs.concat(params_list).concat(params_from_npz);\n        this.outputs = (layer.output || []).map((name, index) => {\n            const shape = layer.output_shapes ? layer.output_shapes[index] : null;\n            const type = shape ? new hailo.TensorType('?', new hailo.TensorShape(shape)) : null;\n            name = `${layer.name}\\n${name}`;\n            return new hailo.Argument(\"output\", [values.map(name, type, null)]);\n        });\n        this.attributes = [];\n        const attrs = Object.assign(layer.params || {}, { original_names: layer.original_names || [] });\n        for (const [name, value] of Object.entries(attrs)) {\n            const schema = metadata.attribute(layer.type, name);\n            const type = schema && schema.type ? schema.type : '';\n            const visible = name === 'original_names' || (schema && schema.visible === false) ? false : true;\n            const attribute = new hailo.Argument(name, value, type, visible);\n            this.attributes.push(attribute);\n        }\n        this.chain = [];\n        if (layer && layer.params && layer.params.activation && layer.params.activation !== 'linear' && layer.type !== 'activation') {\n            const activation = {\n                type: layer.params.activation,\n                name: layer.params.activation,\n                input: [],\n                output: []\n            };\n            const node = new hailo.Node(metadata, activation, values.map);\n            this.chain.push(node);\n        }\n    }\n};\n\nhailo.Tensor = class {\n\n    constructor(array, shape) {\n        const dataType = array && array.dtype ? array.dtype.__name__ : '?';\n        shape = array && array.shape ? array.shape : shape;\n        this.type = new hailo.TensorType(dataType, new hailo.TensorShape(shape));\n        if (array) {\n            this.stride = array.strides.map((stride) => stride / array.itemsize);\n            this.layout = this.type.dataType === 'string' || this.type.dataType === 'object' ? '|' : array.dtype.byteorder;\n            this.values = this.type.dataType === 'string' || this.type.dataType === 'object' || this.type.dataType === 'void' ? array.tolist() : array.tobytes();\n        }\n    }\n};\n\nhailo.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return (this.dataType || '?') + this.shape.toString();\n    }\n};\n\nhailo.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    equals(obj) {\n        if (obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions)) {\n            if (this.dimensions.length === obj.dimensions.length) {\n                return obj.dimensions.every((value, index) => this.dimensions[index] === value);\n            }\n            const a = this.dimensions.filter((value, index) => index === 0 || index === this.dimensions.length - 1 || value !== 1);\n            const b = obj.dimensions.filter((value, index) => index === 0 || index === obj.dimensions.length - 1 || value !== 1);\n            if (a.length === b.length) {\n                return a.every((value, index) => b[index] === value);\n            }\n        }\n        return false;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nhailo.Container = class {\n\n    static async open(context) {\n        const identifier = context.identifier;\n        const basename = identifier.split('.');\n        basename.pop();\n        if (identifier.toLowerCase().endsWith('.hn')) {\n            if (basename.length > 1 && (basename[basename.length - 1] === 'native' || basename[basename.length - 1] === 'fp')) {\n                basename.pop();\n            }\n            const configuration = await context.peek('json');\n            if (configuration && configuration.name && configuration.net_params && configuration.layers) {\n                return new hailo.Container(context, 'hailo.configuration', basename.join('.'), configuration, null);\n            }\n        } else if (identifier.toLowerCase().endsWith('.metadata.json')) {\n            basename.pop();\n            const metadata = await context.peek('json');\n            if (metadata && metadata.state && metadata.hn) {\n                return new hailo.Container(context, 'hailo.metadata', basename.join('.'), null, metadata);\n            }\n        }\n        return null;\n    }\n\n    constructor(context, type, basename, configuration, metadata) {\n        this.type = type;\n        this.context = context;\n        this.basename = basename;\n        this.configuration = configuration;\n        this.metadata = metadata;\n    }\n\n    async _request(name, type) {\n        try {\n            const content = await this.context.fetch(name);\n            if (content) {\n                return await content.read(type);\n            }\n        } catch {\n            // continue regardless of error\n        }\n        return null;\n    }\n\n    async read() {\n        this.format = 'Hailo NN';\n        this.weights = new Map();\n        if (!this.metadata) {\n            this.metadata = await this._request(`${this.basename}.metadata.json`, 'json');\n        }\n        if (this.metadata) {\n            this.format = 'Hailo Archive';\n            this.configuration = await this._request(this.metadata.hn, 'json');\n            if (!this.configuration) {\n                throw new hailo.Error(\"Archive does not contain '.nn' configuration.\");\n            }\n            let extension = '';\n            switch (this.metadata.state) {\n                case 'fp_optimized_model': extension = '.fpo.npz'; break;\n                case 'quantized_model': extension = '.q.npz'; break;\n                case 'compiled_model': extension = '.q.npz'; break;\n                default: extension = '.npz'; break;\n            }\n            const entries = await this._request(this.basename + extension, 'npz');\n            if (entries && entries.size > 0) {\n                const inputs = new Set([\n                    'kernel', 'bias',\n                    'input_activation_bits', 'output_activation_bits',\n                    'weight_bits', 'bias_decomposition'\n                ]);\n                for (const [name, value] of entries) {\n                    const key = name.split('.').slice(0, -1).join('.');\n                    const match = key.match(/.*?(?=:[0-9])/);\n                    if (match) {\n                        const path = match[0].split('/');\n                        if (inputs.has(path[2])) {\n                            const layer = `${path[0]}/${path[1]}`;\n                            if (!this.weights.has(layer)) {\n                                this.weights.set(layer, new Map());\n                            }\n                            const weights = this.weights.get(layer);\n                            weights.set(path[2], value);\n                        }\n                    }\n                }\n            }\n        }\n        delete this.context;\n        delete this.basename;\n    }\n};\n\nhailo.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Hailo model.';\n    }\n};\n\nexport const ModelFactory = hailo.ModelFactory;\n\n"
  },
  {
    "path": "source/hdf5.js",
    "content": "\n// Experimental HDF5 reader\n\nimport * as zip from './zip.js';\n\nconst hdf5 = {};\n\nhdf5.File = class {\n\n    static open(data) {\n        if (data && data.length >= 8) {\n            const buffer = data instanceof Uint8Array ? data : data.peek(8);\n            const signature = [0x89, 0x48, 0x44, 0x46, 0x0D, 0x0A, 0x1A, 0x0A]; // \\x89HDF\\r\\n\\x1A\\n\n            if (signature.every((value, index) => value === buffer[index])) {\n                return new hdf5.File(data);\n            }\n        }\n        return null;\n    }\n\n    constructor(data) {\n        this.data = data;\n    }\n\n    read() {\n        if (this.data) {\n            // https://support.hdfgroup.org/HDF5/doc/H5.format.html\n            const data = this.data;\n            delete this.data;\n            const reader = hdf5.Reader.open(data);\n            reader.skip(8);\n            this._globalHeap = new hdf5.GlobalHeap(reader);\n            const version = reader.byte();\n            switch (version) {\n                case 0:\n                case 1: {\n                    this._freeSpaceStorageVersion = reader.byte();\n                    this._rootGroupEntryVersion = reader.byte();\n                    reader.skip(1);\n                    this._sharedHeaderMessageVersionFormat = reader.byte();\n                    reader.initialize();\n                    reader.skip(1);\n                    this._groupLeafNodeK = reader.uint16(); // 0x04?\n                    this._groupInternalNodeK = reader.uint16(); // 0x10?\n                    reader.skip(4);\n                    if (version > 0) {\n                        this._indexedStorageInternalNodeK = reader.uint16();\n                        reader.skip(2); // Reserved\n                    }\n                    this._baseAddress = reader.offset();\n                    reader.offset(); // Address of File Free space Info\n                    this._endOfFileAddress = reader.offset();\n                    reader.offset(); // Driver Information Block Address\n                    if (this._baseAddress !== 0) {\n                        throw new hdf5.Error('Base address is not zero.');\n                    }\n                    const rootGroupEntry = new hdf5.SymbolTableEntry(reader);\n                    this._rootGroup = new hdf5.Group(reader, rootGroupEntry, null, this._globalHeap, '', '');\n                    break;\n                }\n                case 2:\n                case 3: {\n                    reader.initialize();\n                    reader.byte();\n                    this._baseAddress = reader.offset();\n                    this._superBlockExtensionAddress = reader.offset();\n                    this._endOfFileAddress = reader.offset();\n                    const rootGroupObjectHeader = new hdf5.DataObjectHeader(reader, reader.offset());\n                    this._rootGroup = new hdf5.Group(reader, null, rootGroupObjectHeader, this._globalHeap, '', '');\n                    break;\n                }\n                default:\n                    throw new hdf5.Error(`Unsupported Superblock version ${version}.`);\n            }\n            delete this.data;\n        }\n        return this._rootGroup;\n    }\n};\n\nhdf5.Group = class {\n\n    constructor(reader, entry, objectHeader, globalHeap, parentPath, name) {\n        this._reader = reader;\n        this._entry = entry;\n        this._dataObjectHeader = objectHeader;\n        this._globalHeap = globalHeap;\n        this._name = name;\n        this._path = parentPath === '/' ? (parentPath + name) : (`${parentPath}/${name}`);\n    }\n\n    get name() {\n        return this._name;\n    }\n\n    get path() {\n        return this._path;\n    }\n\n    group(path) {\n        this._decodeGroups();\n        if (this._groups.has(path)) {\n            return this._groups.get(path);\n        }\n        const index = path.indexOf('/');\n        if (index !== -1) {\n            const group = this.group(path.substring(0, index));\n            if (group) {\n                return group.group(path.substring(index + 1));\n            }\n        }\n        return null;\n    }\n\n    get groups() {\n        this._decodeGroups();\n        return this._groups;\n    }\n\n    get attributes() {\n        this._decodeDataObject();\n        return this._attributes;\n    }\n\n    get value() {\n        this._decodeDataObject();\n        return this._value;\n    }\n\n    _decodeDataObject() {\n        if (!this._dataObjectHeader) {\n            this._dataObjectHeader = new hdf5.DataObjectHeader(this._reader, this._entry.objectHeaderAddress);\n        }\n        if (!this._attributes) {\n            this._attributes = new Map();\n            for (const attribute of this._dataObjectHeader.attributes) {\n                const name = attribute.name;\n                const value = attribute.decodeValue(this._globalHeap);\n                this._attributes.set(name, value);\n            }\n            this._value = null;\n            const datatype = this._dataObjectHeader.datatype;\n            const dataspace = this._dataObjectHeader.dataspace;\n            const dataLayout = this._dataObjectHeader.dataLayout;\n            const filterPipeline = this._dataObjectHeader.filterPipeline;\n            if (datatype && dataspace && dataLayout) {\n                this._value = new hdf5.Variable(this._reader, this._globalHeap, datatype, dataspace, dataLayout, filterPipeline);\n            }\n        }\n        if (this._reader.position !== 0) {\n            this._reader.seek(0);\n        }\n    }\n\n    _decodeGroups() {\n        if (!this._groups) {\n            this._groups = new Map();\n            if (this._entry) {\n                if (this._entry.treeAddress || this._entry.heapAddress) {\n                    const heap = new hdf5.Heap(this._reader, this._entry.heapAddress);\n                    const tree = new hdf5.Tree(this._reader, this._entry.treeAddress);\n                    for (const node of tree.nodes) {\n                        for (const entry of node.entries) {\n                            const name = heap.getString(entry.linkNameOffset);\n                            const group = new hdf5.Group(this._reader, entry, null, this._globalHeap, this._path, name);\n                            this._groups.set(name, group);\n                        }\n                    }\n                }\n            } else {\n                this._decodeDataObject();\n                for (const link of this._dataObjectHeader.links) {\n                    if (Object.prototype.hasOwnProperty.call(link, 'objectHeaderAddress')) {\n                        const name = link.name;\n                        const objectHeader = new hdf5.DataObjectHeader(this._reader, link.objectHeaderAddress);\n                        const linkGroup = new hdf5.Group(this._reader, null, objectHeader, this._globalHeap, this._path, name);\n                        this._groups.set(name, linkGroup);\n                    }\n                }\n            }\n        }\n    }\n};\n\nhdf5.Variable = class {\n\n    constructor(reader, globalHeap, datatype, dataspace, dataLayout, filterPipeline) {\n        this._reader = reader;\n        this._globalHeap = globalHeap;\n        this._datatype = datatype;\n        this._dataspace = dataspace;\n        this._dataLayout = dataLayout;\n        this._filterPipeline = filterPipeline;\n    }\n\n    get type () {\n        return this._datatype.type;\n    }\n\n    get littleEndian() {\n        return this._datatype.littleEndian;\n    }\n\n    get shape() {\n        return this._dataspace.shape;\n    }\n\n    get value() {\n        const data = this.data;\n        if (data) {\n            const reader = hdf5.Reader.open(data);\n            const array = this._dataspace.read(this._datatype, reader);\n            return this._dataspace.decode(this._datatype, array, array, this._globalHeap);\n        }\n        return null;\n    }\n\n    get data() {\n        switch (this._dataLayout.layoutClass) {\n            case 1: // Contiguous\n                if (this._dataLayout.address && this._dataLayout.address !== -1) {\n                    const position = this._reader.position;\n                    this._reader.seek(this._dataLayout.address);\n                    const stream = this._reader.stream(this._dataLayout.size);\n                    this._reader.seek(position);\n                    return stream;\n                }\n                break;\n            case 2: { // Chunked\n                const dimensionality = this._dataLayout.dimensionality;\n                const tree = new hdf5.Tree(this._reader, this._dataLayout.address, dimensionality);\n                const item_size = this._dataLayout.datasetElementSize;\n                const chunk_shape = this._dataLayout.dimensionSizes;\n                const data_shape = this._dataspace.shape;\n                const chunk_size = chunk_shape.reduce((a, b) => a * b, 1);\n                const data_size = data_shape.reduce((a, b) => a * b, 1);\n                const max_dim = data_shape.length - 1;\n                let data_stride = 1;\n                const data_strides = new Array(data_shape.length);\n                for (let i = data_shape.length - 1; i >= 0; i--) {\n                    data_strides[i] = data_stride;\n                    data_stride *= data_shape[i];\n                }\n                const data = new Uint8Array(data_size * item_size);\n                for (const node of tree.nodes) {\n                    let chunk = node.data;\n                    if (this._filterPipeline) {\n                        for (let i = 0; i < this._filterPipeline.filters.length; i++) {\n                            if ((node.filterMask & (1 << i)) === 0) {\n                                const filter = this._filterPipeline.filters[i];\n                                chunk = filter.decode(chunk);\n                            }\n                        }\n                    }\n                    const chunk_offset = node.fields.map((x) => x.toNumber());\n                    const data_pos = chunk_offset.slice();\n                    const chunk_pos = new Array(data_pos.length).fill(0);\n                    const length = data_pos.length - 1;\n                    for (let chunk_index = 0; chunk_index < chunk_size; chunk_index++) {\n                        for (let i = max_dim; i >= 0; i--) {\n                            if (chunk_pos[i] >= chunk_shape[i]) {\n                                chunk_pos[i] = 0;\n                                data_pos[i] = chunk_offset[i];\n                                if (i > 0) {\n                                    chunk_pos[i - 1]++;\n                                    data_pos[i - 1]++;\n                                }\n                            } else {\n                                break;\n                            }\n                        }\n                        let index = 0;\n                        let inbounds = true;\n                        for (let i = 0; i < length; i++) {\n                            const position = data_pos[i];\n                            if (position >= data_shape[i]) {\n                                inbounds = false;\n                                break;\n                            }\n                            index += position * data_strides[i];\n                        }\n                        if (inbounds) {\n                            let chunk_offset = chunk_index * item_size;\n                            let target_offset = index * item_size;\n                            const target_end = target_offset + item_size;\n                            while (target_offset < target_end) {\n                                data[target_offset++] = chunk[chunk_offset++];\n                            }\n                        }\n                        chunk_pos[max_dim]++;\n                        data_pos[max_dim]++;\n                    }\n                }\n                return data;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported data layout class '${this.layoutClass}'.`);\n            }\n        }\n        return null;\n    }\n};\n\nhdf5.Reader = class {\n\n    static open(data) {\n        if (data instanceof hdf5.BinaryReader || data instanceof hdf5.StreamReader) {\n            return data;\n        } else if (data instanceof Uint8Array) {\n            return new hdf5.BinaryReader(data);\n        } else if (data.length < 0x10000000) {\n            const buffer = data.peek();\n            return new hdf5.BinaryReader(buffer);\n        }\n        return new hdf5.StreamReader(data);\n    }\n\n    initialize() {\n        this._offsetSize = this.byte();\n        this._lengthSize = this.byte();\n    }\n\n    int8() {\n        const position = this.take(1);\n        return this._view.getInt8(position);\n    }\n\n    byte() {\n        const position = this.take(1);\n        return this._view.getUint8(position);\n    }\n\n    int16() {\n        const position = this.take(2);\n        return this._view.getInt16(position, true);\n    }\n\n    uint16() {\n        const position = this.take(2);\n        return this._view.getUint16(position, true);\n    }\n\n    int32() {\n        const position = this.take(4);\n        return this._view.getInt32(position, true);\n    }\n\n    uint32() {\n        const position = this.take(4);\n        return this._view.getUint32(position, true);\n    }\n\n    int64() {\n        const position = this.take(8);\n        return this._view.getBigInt64(position, true);\n    }\n\n    uint64() {\n        const position = this.take(8);\n        return this._view.getBigUint64(position, true);\n    }\n\n    uint(size) {\n        switch (size) {\n            case 0: return this.byte();\n            case 1: return this.uint16();\n            case 2: return this.uint32();\n            case 3: return this.uint64().toNumber();\n            default: throw new hdf5.Error(`Unsupported uint size '${size}'.`);\n        }\n    }\n\n    float16() {\n        const position = this.take(2);\n        const value = this._view.getUint16(position, true);\n        // decode float16 value\n        const s = (value & 0x8000) >> 15;\n        const e = (value & 0x7C00) >> 10;\n        const f = value & 0x03FF;\n        if (e === 0) {\n            return (s ? -1 : 1) * Math.pow(2, -14) * (f / Math.pow(2, 10));\n        } else if (e === 0x1F) {\n            return f ? NaN : ((s ? -1 : 1) * Infinity);\n        }\n        return (s ? -1 : 1) * Math.pow(2, e - 15) * (1 + (f / Math.pow(2, 10)));\n    }\n\n    float32() {\n        const position = this.take(4);\n        return this._view.getFloat32(position, true);\n    }\n\n    float64() {\n        const position = this.take(8);\n        return this._view.getFloat64(position, true);\n    }\n\n    offset() {\n        switch (this._offsetSize) {\n            case 8: {\n                const position = this.take(8);\n                const value = this._view.getBigUint64(position, true);\n                if (value === 0xffffffffffffffffn) {\n                    return -1;\n                }\n                if (value >= Number.MAX_SAFE_INTEGER) {\n                    throw new Error(`64-bit value '${value.toString(16)}' exceeds safe integer.`);\n                }\n                return value.toNumber();\n            }\n            case 4: {\n                const value = this.uint32();\n                if (value === 0xffffffff) {\n                    return undefined;\n                }\n                return value;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported offset size '${this._offsetSize}'.`);\n            }\n        }\n    }\n\n    length() {\n        switch (this._lengthSize) {\n            case 8: {\n                const position = this.take(8);\n                const value = this._view.getBigUint64(position, true);\n                if (value === 0xffffffffffffffffn) {\n                    return -1;\n                }\n                if (value >= Number.MAX_SAFE_INTEGER) {\n                    throw new Error(`64-bit value '${value.toString(16)}' exceeds safe integer.`);\n                }\n                return value.toNumber();\n            }\n            case 4: {\n                const value = this.uint32();\n                if (value === 0xffffffff) {\n                    return undefined;\n                }\n                return value;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported length size '${this._lengthSize}'.`);\n            }\n        }\n    }\n\n    string(size, encoding) {\n        if (!size || size === -1) {\n            size = this.size(0x00);\n        }\n        let data = null;\n        if (size < 16) {\n            data = new Uint8Array(size);\n            for (let i = 0; i < size; i++) {\n                data[i] = this.byte();\n            }\n        } else {\n            data = this.read(size);\n        }\n        if (encoding === 'utf-8') {\n            hdf5.Reader._utf8Decoder = hdf5.Reader._utf8Decoder || new TextDecoder('utf-8');\n            return hdf5.Reader._utf8Decoder.decode(data).replace(/\\0/g, '');\n        }\n        hdf5.Reader._asciiDecoder = hdf5.Reader._asciiDecoder || new TextDecoder('ascii');\n        return hdf5.Reader._asciiDecoder.decode(data).replace(/\\0/g, '');\n    }\n\n    match(signature) {\n        const position = this.position;\n        for (let i = 0; i < signature.length; i++) {\n            if (signature.charCodeAt(i) !== this.byte()) {\n                this.seek(position);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    expect(signature) {\n        if (!this.match(signature)) {\n            throw new hdf5.Error(`Invalid '${signature}' block signature.`);\n        }\n    }\n};\n\nhdf5.BinaryReader = class extends hdf5.Reader {\n\n    constructor(buffer, view, offset, position, offsetSize, lengthSize) {\n        super();\n        this._buffer = buffer;\n        this._length = buffer.length;\n        this._view = view || new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n        this._offset = offset || 0;\n        this._position = position || 0;\n        this._offsetSize = offsetSize;\n        this._lengthSize = lengthSize;\n    }\n\n    get position() {\n        return this._position + this._offset;\n    }\n\n    take(offset) {\n        const position = this._offset + this._position;\n        this.skip(offset);\n        return position;\n    }\n\n    seek(position) {\n        this._offset = position;\n        this._position = 0;\n        if (this._offset > this._length) {\n            throw new Error(`Unexpected end of file. Expected ${this._offset - this._length} more bytes. The file might be corrupted.`);\n        }\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._offset + this._position > this._buffer.length) {\n            throw new hdf5.Error(`Unexpected end of file. Expected ${this._offset + this._position - this._buffer.length} more bytes. The file might be corrupted.`);\n        }\n    }\n\n    align(mod) {\n        if (this._position % mod !== 0) {\n            this._position = (Math.floor(this._position / mod) + 1) * mod;\n        }\n    }\n\n    peek(length) {\n        const position = this._offset + this._position;\n        length = length === undefined ? this._buffer.length - position : length;\n        this.take(length);\n        const buffer = this._buffer.subarray(position, position + length);\n        this._position = position - this._offset;\n        return buffer;\n    }\n\n    read(length) {\n        const position = this.take(length);\n        return this._buffer.subarray(position, position + length);\n    }\n\n    stream(length) {\n        const position = this.take(length);\n        const buffer = this._buffer.subarray(position, position + length);\n        return new hdf5.BinaryReader(buffer);\n    }\n\n    size(terminator) {\n        let position = this._offset + this._position;\n        while (this._buffer[position] !== terminator) {\n            position++;\n        }\n        return position - this._offset - this._position + 1;\n    }\n};\n\nhdf5.StreamReader = class extends hdf5.Reader {\n\n    constructor(stream, view, window, offset, position, offsetSize, lengthSize) {\n        super();\n        this._stream = stream;\n        this._length = stream.length;\n        this._view = view;\n        this._window = window || 0;\n        this._offset = offset || 0;\n        this._position = position || 0;\n        this._offsetSize = offsetSize;\n        this._lengthSize = lengthSize;\n    }\n\n    get position() {\n        return this._offset + this._position;\n    }\n\n    seek(position) {\n        this._offset = position;\n        this._position = 0;\n        if (this._offset > this._length) {\n            throw new Error(`Unexpected end of file. Expected ${this._offset - this._length} more bytes. The file might be corrupted.`);\n        }\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position + this._offset > this._length) {\n            throw new hdf5.Error(`Unexpected end of file. Expected ${this._position + this._offset - this._length} more bytes. The file might be corrupted.`);\n        }\n    }\n\n    align(mod) {\n        if (this._position % mod !== 0) {\n            this._position = (Math.floor(this._position / mod) + 1) * mod;\n        }\n    }\n\n    read(length) {\n        const position = this._stream.position;\n        this._stream.seek(this._offset + this._position);\n        const buffer = this._stream.read(length);\n        this._stream.seek(position);\n        this.skip(length);\n        return buffer;\n    }\n\n    stream(length) {\n        const position = this._stream.position;\n        this._stream.seek(this._offset + this._position);\n        this.skip(length);\n        const stream = this._stream.stream(length);\n        this._stream.seek(position);\n        return stream;\n    }\n\n    byte() {\n        const position = this.take(1);\n        return this._view.getUint8(position);\n    }\n\n    uint16() {\n        const position = this.take(2);\n        return this._view.getUint16(position, true);\n    }\n\n    int32() {\n        const position = this.take(4);\n        return this._view.getInt32(position, true);\n    }\n\n    uint32() {\n        const position = this.take(4);\n        return this._view.getUint32(position, true);\n    }\n\n    int64() {\n        const position = this.take(8);\n        return this._view.getBigInt64(position, true);\n    }\n\n    float32() {\n        const position = this.take(4);\n        return this._view.getFloat32(position, true);\n    }\n\n    float64() {\n        const position = this.take(8);\n        return this._view.getFloat64(position, true);\n    }\n\n    size(terminator) {\n        const position = this._position;\n        let size = 0;\n        while (this.byte() !== terminator) {\n            size++;\n        }\n        this._position = position;\n        return size;\n    }\n\n    take(length) {\n        const position = this.position;\n        if (position + length > this._length) {\n            throw new Error(`Expected ${position + length - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n        if (!this._view || position < this._window || position + length > this._window + this._view.byteLength) {\n            this._window = position;\n            const current = this._stream.position;\n            this._stream.seek(this._window);\n            const buffer = this._stream.read(Math.min(0x100, this._length - this._window)).slice();\n            this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n            this._stream.seek(current);\n        }\n        this._position += length;\n        return position - this._window;\n    }\n};\n\nhdf5.SymbolTableNode = class {\n\n    constructor(reader, offset) {\n        const position = reader.position;\n        reader.seek(offset);\n        reader.expect('SNOD');\n        const version = reader.byte();\n        if (version === 1) {\n            reader.skip(1);\n            const entriesUsed = reader.uint16();\n            this.entries = [];\n            for (let i = 0; i < entriesUsed; i++) {\n                const entry = new hdf5.SymbolTableEntry(reader);\n                this.entries.push(entry);\n            }\n        } else {\n            throw new hdf5.Error(`Unsupported symbol table node version '${version}'.`);\n        }\n        reader.seek(position);\n    }\n};\n\nhdf5.SymbolTableEntry = class {\n\n    constructor(reader) {\n        this.linkNameOffset = reader.offset();\n        this.objectHeaderAddress = reader.offset();\n        const cacheType = reader.uint32();\n        reader.skip(4); // Reserved\n        switch (cacheType) {\n            case 0:\n                break;\n            case 1: {\n                const position = reader.position;\n                this.treeAddress = reader.offset();\n                this.heapAddress = reader.offset();\n                reader.seek(position);\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported cache type '${cacheType}'.`);\n        }\n        reader.skip(16); // Scratch-pad space\n    }\n};\n\nhdf5.DataObjectHeader = class {\n\n    constructor(reader, offset) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#ObjectHeader\n        const position = reader.position;\n        reader.seek(offset);\n        this.attributes = [];\n        this.links = [];\n        this.continuations = [];\n        reader.match('OHDR');\n        const version = reader.byte();\n        switch (version) {\n            case 1: {\n                reader.skip(1);\n                const count = reader.uint16();\n                reader.uint32();\n                const objectHeaderSize = reader.uint32();\n                reader.align(8);\n                let end = reader.position + objectHeaderSize;\n                for (let i = 0; i < count; i++) {\n                    const type = reader.uint16();\n                    const size = reader.uint16();\n                    const flags = reader.byte();\n                    reader.skip(3);\n                    reader.align(8);\n                    const next = this._readMessage(reader, type, size, flags);\n                    if ((!next || reader.position >= end) && this.continuations.length > 0) {\n                        const continuation = this.continuations.shift();\n                        reader.seek(continuation.offset);\n                        end = continuation.offset + continuation.length;\n                    } else {\n                        reader.align(8);\n                    }\n                }\n                break;\n            }\n            case 2: {\n                const flags = reader.byte();\n                if ((flags & 0x20) !== 0) {\n                    reader.uint32(); // access time\n                    reader.uint32(); // modification time\n                    reader.uint32(); // change time\n                    reader.uint32(); // birth time\n                }\n                if ((flags & 0x10) !== 0) {\n                    reader.uint16(); // max compact attributes\n                    reader.uint16(); // min compact attributes\n                }\n                const order = (flags & 0x04) !== 0;\n                const size = reader.uint(flags & 0x03);\n                let next = true;\n                let end = reader.position + size;\n                while (next && reader.position < end) {\n                    const type = reader.byte();\n                    const size = reader.uint16();\n                    const flags = reader.byte();\n                    if (reader.position < end) {\n                        if (order) {\n                            reader.uint16(); // creation order\n                        }\n                        next = this._readMessage(reader, type, size, flags);\n                    }\n                    if ((!next || reader.position >= end) && this.continuations.length > 0) {\n                        const continuation = this.continuations.shift();\n                        reader.seek(continuation.offset);\n                        end = continuation.offset + continuation.length;\n                        reader.expect('OCHK');\n                        next = true;\n                    }\n                }\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported data object header version '${version}'.`);\n            }\n        }\n        reader.seek(position);\n    }\n\n    _readMessage(reader, type, size, flags) {\n        const position = reader.position;\n        switch (type) {\n            case 0x0000: // NIL\n                return false;\n            case 0x0001: // Dataspace\n                this.dataspace = (size !== 4 || flags !== 1) ? new hdf5.Dataspace(reader) : null;\n                break;\n            case 0x0002: // Link Info\n                this.linkInfo = new hdf5.LinkInfo(reader);\n                break;\n            case 0x0003: // Datatype\n                this.datatype = new hdf5.Datatype(reader);\n                break;\n            case 0x0004:\n            case 0x0005: // Fill Value\n                this.fillValue = new hdf5.FillValue(reader, type);\n                break;\n            case 0x0006: // Link\n                this.links.push(new hdf5.Link(reader));\n                break;\n            case 0x0008: // Data Layout\n                this.dataLayout = new hdf5.DataLayout(reader);\n                break;\n            case 0x000A: // Group Info\n                this.groupInfo = new hdf5.GroupInfo(reader);\n                break;\n            case 0x000B: // Filter Pipeline\n                this.filterPipeline = new hdf5.FilterPipeline(reader);\n                break;\n            case 0x000C: // Attribute\n                this.attributes.push(new hdf5.Attribute(reader));\n                break;\n            case 0x000D: // Object Comment Message\n                this.comment = reader.string(-1, 'ascii');\n                break;\n            case 0x0010: // Object Header Continuation\n                this.continuations.push(new hdf5.ObjectHeaderContinuation(reader));\n                break;\n            case 0x0011: // Symbol Table\n                this.symbolTable = new hdf5.SymbolTable(reader);\n                break;\n            case 0x000E: // Object Modification Time (Old)\n            case 0x0012: // Object Modification Time\n                this.objectModificationTime = new hdf5.ObjectModificationTime(reader, type);\n                break;\n            case 0x0015: // Attribute Info\n                this.attributeInfo = new hdf5.AttributeInfo(reader);\n                break;\n            default:\n                throw new hdf5.Error(`Unsupported message type '${type}'.`);\n        }\n        reader.seek(position);\n        reader.skip(size);\n        return true;\n    }\n};\n\nhdf5.Message = class {\n\n    constructor(type, data, flags) {\n        this._type = type;\n        this._data = data;\n        this._flags = flags;\n    }\n};\n\nhdf5.Dataspace = class {\n\n    constructor(reader) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#DataspaceMessage\n        this._sizes = [];\n        const version = reader.byte();\n        switch (version) {\n            case 1:\n                this._dimensions = reader.byte();\n                this._flags = reader.byte();\n                reader.skip(1);\n                reader.skip(4);\n                for (let i = 0; i < this._dimensions; i++) {\n                    this._sizes.push(reader.length());\n                }\n                if ((this._flags & 0x01) !== 0) {\n                    this._maxSizes = [];\n                    for (let j = 0; j < this._dimensions; j++) {\n                        this._maxSizes.push(reader.length());\n                        if (this._maxSizes[j] !== this._sizes[j]) {\n                            throw new hdf5.Error('Max size is not supported.');\n                        }\n                    }\n                }\n                if ((this._flags & 0x02) !== 0) {\n                    throw new hdf5.Error('Permutation indices not supported.');\n                }\n                break;\n            case 2:\n                this._dimensions = reader.byte();\n                this._flags = reader.byte();\n                this._type = reader.byte(); // 0 scalar, 1 simple, 2 null\n                for (let k = 0; k < this._dimensions; k++) {\n                    this._sizes.push(reader.length());\n                }\n                if ((this._flags & 0x01) !== 0) {\n                    this._maxSizes = [];\n                    for (let l = 0; l < this._dimensions; l++) {\n                        this._maxSizes.push(reader.length());\n                    }\n                }\n                break;\n            default:\n                throw new hdf5.Error(`Unsupported dataspace message version '${version}'.`);\n        }\n    }\n\n    get shape() {\n        return this._sizes;\n    }\n\n    read(datatype, reader) {\n        if (this._dimensions === 0) {\n            return datatype.read(reader);\n        }\n        return this._readArray(datatype, reader, this._sizes, 0);\n    }\n\n    _readArray(datatype, reader, shape, dimension) {\n        const array = [];\n        const size = shape[dimension];\n        if (dimension === shape.length - 1) {\n            for (let i = 0; i < size; i++) {\n                array.push(datatype.read(reader));\n            }\n        } else {\n            for (let j = 0; j < size; j++) {\n                array.push(this._readArray(datatype, reader, shape, dimension + 1));\n            }\n        }\n        return array;\n    }\n\n    decode(datatype, data, globalHeap) {\n        if (this._dimensions === 0) {\n            return datatype.decode(data, globalHeap);\n        }\n        return this._decodeArray(datatype, data, globalHeap, this._sizes, 0);\n    }\n\n    _decodeArray(datatype, data, globalHeap, shape, dimension) {\n        const size = shape[dimension];\n        if (dimension === shape.length - 1) {\n            for (let i = 0; i < size; i++) {\n                data[i] = datatype.decode(data[i], globalHeap);\n            }\n        } else {\n            for (let j = 0; j < size; j++) {\n                data[j] = this._decodeArray(datatype, data[j], shape, dimension + 1);\n            }\n        }\n        return data;\n    }\n};\n\nhdf5.LinkInfo = class {\n\n    constructor(reader) {\n        const version = reader.byte();\n        switch (version) {\n            case 0: {\n                const flags = reader.byte();\n                if ((flags & 1) !== 0) {\n                    this.maxCreationIndex = reader.uint64();\n                }\n                this.fractalHeapAddress = reader.offset();\n                this.nameIndexTreeAddress = reader.offset();\n                if ((flags & 2) !== 0) {\n                    this.creationOrderIndexTreeAddress = reader.offset();\n                }\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported link info message version '${version}'.`);\n        }\n    }\n};\n\nhdf5.Datatype = class {\n\n    constructor(reader) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#DatatypeMessage\n        const format = reader.byte();\n        const version = format >> 4;\n        this._class = format & 0xf;\n        switch (version) {\n            case 1:\n            case 2: {\n                this._flags = reader.byte() | reader.byte() << 8 | reader.byte() << 16;\n                this._size = reader.uint32();\n                switch (this._class) {\n                    case 0: { // fixed-Point\n                        this._bitOffset = reader.uint16();\n                        this._bitPrecision = reader.uint16();\n                        break;\n                    }\n                    case 8: { // enumerated\n                        this._base = new hdf5.Datatype(reader);\n                        reader.seek(reader.position);\n                        const size = this._flags & 0xffff;\n                        this._names = new Array(size);\n                        for (let i = 0; i < size; i++) {\n                            this._names[i] = reader.string(-1, 'ascii');\n                            reader.align(8);\n                        }\n                        this._values = new Array(size);\n                        for (let i = 0; i < size; i++) {\n                            this._values[i] = this._base.read(reader);\n                        }\n                        break;\n                    }\n                    default: {\n                        break;\n                    }\n                }\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported datatype version '${version}'.`);\n            }\n        }\n    }\n\n    get type() {\n        switch (this._class) {\n            case 0: // fixed-point\n                if ((this._flags & 0xfff6) === 0) {\n                    if ((this._flags && 0x08) === 0) {\n                        switch (this._size) {\n                            case 1: return 'uint8';\n                            case 2: return 'uint16';\n                            case 4: return 'uint32';\n                            case 8: return 'uint64';\n                            default: throw new hdf5.Error(`Unsupported uint size '${this._size}'.`);\n                        }\n                    } else {\n                        switch (this._size) {\n                            case 1: return 'int8';\n                            case 2: return 'int16';\n                            case 4: return 'int32';\n                            case 8: return 'int64';\n                            default: throw new hdf5.Error(`Unsupported int size '${this._size}'.`);\n                        }\n                    }\n                }\n                break;\n            case 1: // floating-point\n                if (this._size === 2 && this._flags === 0x0f20) {\n                    return 'float16';\n                } else if (this._size === 4 && this._flags === 0x1f20) {\n                    return 'float32';\n                } else if (this._size === 8 && this._flags === 0x3f20) {\n                    return 'float64';\n                }\n                break;\n            case 3: // string\n                return 'string';\n            case 5: // opaque\n                return 'uint8';\n            case 6: // compound\n                return 'compound';\n            case 8: // enumerated\n                if (this._base.type === 'int8' &&\n                    this._names.length === 2 && this._names[0] === 'FALSE' && this._names[1] === 'TRUE' &&\n                    this._values.length === 2 && this._values[0] === 0 && this._values[1] === 1) {\n                    return 'boolean';\n                }\n                break;\n            case 9: // variable-length\n                if ((this._flags & 0x0f) === 1) { // type\n                    return 'char[]';\n                }\n                break;\n            default:\n                break;\n        }\n        throw new hdf5.Error(`Unsupported datatype class '${this._class}'.`);\n    }\n\n    get littleEndian() {\n        switch (this._class) {\n            case 0: // fixed-point\n            case 1: // floating-point\n                return (this.flags & 0x01) === 0;\n            default:\n                return true;\n        }\n    }\n\n    read(reader) {\n        switch (this._class) {\n            case 0: // fixed-point\n                if (this._size === 1) {\n                    return this._flags & 0x8 ? reader.int8() : reader.byte();\n                } else if (this._size === 2) {\n                    return this._flags & 0x8 ? reader.int16() : reader.uint16();\n                } else if (this._size === 4) {\n                    return this._flags & 0x8 ? reader.int32() : reader.uint32();\n                } else if (this._size === 8) {\n                    return this._flags & 0x8 ? reader.int64() : reader.uint64();\n                }\n                throw new hdf5.Error('Unsupported fixed-point datatype.');\n            case 1: // floating-point\n                if (this._size === 2 && this._flags === 0x0f20) {\n                    return reader.float16();\n                } else if (this._size === 4 && this._flags === 0x1f20) {\n                    return reader.float32();\n                } else if (this._size === 8 && this._flags === 0x3f20) {\n                    return reader.float64();\n                }\n                throw new hdf5.Error('Unsupported floating-point datatype.');\n            case 3: // string\n                switch ((this._flags >> 8) & 0x0f) { // character set\n                    case 0:\n                        return reader.string(this._size, 'ascii');\n                    case 1:\n                        return reader.string(this._size, 'utf-8');\n                    default:\n                        throw new hdf5.Error('Unsupported character encoding.');\n                }\n            case 5: // opaque\n                return reader.read(this._size);\n            case 8: // enumerated\n                return reader.read(this._size);\n            case 9: // variable-length\n                return {\n                    length: reader.uint32(),\n                    globalHeapID: new hdf5.GlobalHeapID(reader)\n                };\n            default:\n                throw new hdf5.Error(`Unsupported datatype class '${this._class}'.`);\n        }\n    }\n\n    decode(data, globalHeap) {\n        switch (this._class) {\n            case 0: // fixed-point\n                return data;\n            case 1: // floating-point\n                return data;\n            case 3: // string\n                return data;\n            case 5: // opaque\n                return data;\n            case 8: // enumerated\n                return data;\n            case 9: { // variable-length\n                const globalHeapObject = globalHeap.get(data.globalHeapID);\n                if (globalHeapObject !== null) {\n                    const characterSet = (this._flags >> 8) & 0x0f;\n                    const reader = globalHeapObject.reader();\n                    switch (characterSet) {\n                        case 0:\n                            return reader.string(reader.length(), 'ascii');\n                        case 1:\n                            return reader.string(reader.length(), 'utf-8');\n                        default:\n                            throw new hdf5.Error('Unsupported character encoding.');\n                    }\n                }\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported datatype class '${this._class}'.`);\n        }\n        return null;\n    }\n};\n\nhdf5.FillValue = class {\n\n    constructor(reader, type) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#FillValueMessage\n        switch (type) {\n            case 0x0004: {\n                const size = reader.uint32();\n                this.data = reader.read(size);\n                break;\n            }\n            case 0x0005:\n            default: {\n                const version = reader.byte();\n                switch (version) {\n                    case 1:\n                    case 2: {\n                        reader.byte();\n                        reader.byte();\n                        const valueDefined = reader.byte();\n                        if (version === 1 || valueDefined === 1) {\n                            const size = reader.uint32();\n                            this.data = reader.read(size);\n                        }\n                        break;\n                    }\n                    case 3: {\n                        const flags = reader.byte();\n                        if ((flags & 0x20) !== 0) {\n                            const size = reader.uint32();\n                            this.data = reader.read(size);\n                        }\n                        break;\n                    }\n                    default:\n                        throw new hdf5.Error(`Unsupported fill value version '${version}'.`);\n                }\n                break;\n            }\n        }\n    }\n};\n\nhdf5.Link = class {\n\n    constructor(reader) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#FillValueMessage\n        const version = reader.byte();\n        switch (version) {\n            case 1: {\n                const flags = reader.byte();\n                this.type = (flags & 0x08) === 0 ? 0 : reader.byte();\n                if ((flags & 0x04) !== 0) {\n                    this.creationOrder = reader.uint32();\n                }\n                const encoding = ((flags & 0x10) !== 0 && reader.byte() === 1) ? 'utf-8' : 'ascii';\n                const size = reader.uint(flags & 0x03);\n                this.name = reader.string(size, encoding);\n                switch (this.type) {\n                    case 0: // hard link\n                        this.objectHeaderAddress = reader.offset();\n                        break;\n                    case 1: // soft link\n                        break;\n                    default:\n                        throw new hdf5.Error(`Unsupported link message type '${this.type}'.`);\n                }\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported link message version '${version}'.`);\n        }\n    }\n};\n\nhdf5.DataLayout = class {\n\n    constructor(reader) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#LayoutMessage\n        const version = reader.byte();\n        switch (version) {\n            case 1:\n            case 2: {\n                this.dimensionality = reader.byte();\n                this.layoutClass = reader.byte();\n                reader.skip(5);\n                switch (this.layoutClass) {\n                    case 1:\n                        this.address = reader.offset();\n                        this.dimensionSizes = [];\n                        for (let i = 0; i < this.dimensionality - 1; i++) {\n                            this.dimensionSizes.push(reader.int32());\n                        }\n                        break;\n                    case 2: // Chunked\n                        this.address = reader.offset();\n                        this.dimensionSizes = [];\n                        for (let i = 0; i < this.dimensionality - 1; i++) {\n                            this.dimensionSizes.push(reader.int32());\n                        }\n                        this.datasetElementSize = reader.int32();\n                        break;\n                    default:\n                        throw new hdf5.Error(`Unsupported data layout class '${this.layoutClass}'.`);\n                }\n                break;\n            }\n            case 3: {\n                this.layoutClass = reader.byte();\n                switch (this.layoutClass) {\n                    case 0: // Compact\n                        this.size = reader.uint16();\n                        reader.skip(2);\n                        this.address = reader.position;\n                        break;\n                    case 1: // Contiguous\n                        this.address = reader.offset();\n                        this.size = reader.length();\n                        break;\n                    case 2: // Chunked\n                        this.dimensionality = reader.byte();\n                        this.address = reader.offset();\n                        this.dimensionSizes = [];\n                        for (let i = 0; i < this.dimensionality - 1; i++) {\n                            this.dimensionSizes.push(reader.int32());\n                        }\n                        this.datasetElementSize = reader.int32();\n                        break;\n                    default:\n                        throw new hdf5.Error(`Unsupported data layout class '${this.layoutClass}'.`);\n                }\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported data layout version '${version}'.`);\n            }\n        }\n    }\n};\n\nhdf5.GroupInfo = class {\n\n    constructor(reader) {\n        const version = reader.byte();\n        switch (version) {\n            case 0: {\n                const flags = reader.byte();\n                if ((flags & 0x01) !== 0) {\n                    this.maxCompactLinks = reader.uint16();\n                    this.minDenseLinks = reader.uint16();\n                }\n                if ((flags & 0x02) !== 0) {\n                    this.estimatedEntriesNumber = reader.uint16();\n                    this.estimatedLinkNameLengthEntries = reader.uint16();\n                }\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported group info version '${version}'.`);\n        }\n    }\n};\n\nhdf5.FilterPipeline = class {\n\n    constructor(reader) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#FilterMessage\n        const version = reader.byte();\n        switch (version) {\n            case 1: {\n                this.filters = [];\n                const numberOfFilters = reader.byte();\n                reader.skip(2);\n                reader.skip(4);\n                for (let i = 0; i < numberOfFilters; i++) {\n                    this.filters.push(new hdf5.Filter(reader));\n                    reader.align(8);\n                }\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported filter pipeline message version '${version}'.`);\n        }\n    }\n};\n\nhdf5.Filter = class {\n\n    constructor(reader) {\n        this.id = reader.int16();\n        const nameLength = reader.int16();\n        this.flags = reader.int16();\n        const clientDataSize = reader.int16();\n        this.name = reader.string(nameLength, 'ascii');\n        this.clientData = reader.read(clientDataSize * 4);\n    }\n\n    decode(data) {\n        switch (this.id) {\n            case 1: return this._deflate(data);\n            case 32000: return this._lzf(data);\n            default: throw new hdf5.Error(`Unsupported filter '${this.id}:${this.name}'.`);\n        }\n    }\n\n    _deflate(input) {\n        const archive = zip.Archive.open(input);\n        return archive.entries.get('').peek();\n    }\n\n    _lzf(input) {\n        let i = 0;\n        let o = 0;\n        while (i < input.length) {\n            let c = input[i++];\n            if (c < (1 << 5)) {\n                c++;\n                i += c;\n                o += c;\n                if (i > input.length) {\n                    throw new Error('Invalid LZF compressed data.');\n                }\n            } else {\n                let length = c >> 5;\n                if (i >= input.length) {\n                    throw new Error('Invalid LZF compressed data.');\n                }\n                if (length === 7) {\n                    length += input[i++];\n                    if (i >= input.length) {\n                        throw new Error('Invalid LZF compressed data.');\n                    }\n                }\n                const ref =  (o - ((c & 0x1f) << 8) - 1) - input[i++];\n                if (ref < 0) {\n                    throw new Error('Invalid LZF compressed data.');\n                }\n                o += length + 2;\n            }\n        }\n        const output = new Uint8Array(o);\n        i = 0;\n        o = 0;\n        while (i < input.length) {\n            let c = input[i++];\n            if (c < (1 << 5)) {\n                c++;\n                output.set(input.subarray(i, i + c), o);\n                i += c;\n                o += c;\n            } else {\n                let length = c >> 5;\n                if (length === 7) {\n                    length += input[i++];\n                }\n                length += 2;\n                let ref =  o - ((c & 0x1f) << 8) - 1 - input[i++];\n                do {\n                    output[o++] = output[ref++];\n                } while (--length);\n            }\n        }\n        return output;\n    }\n};\n\nhdf5.Attribute = class {\n\n    constructor(reader) {\n        const version = reader.byte();\n        switch (version) {\n            case 1: {\n                reader.skip(1);\n                const nameSize = reader.uint16();\n                const datatypeSize = reader.uint16();\n                const dataspaceSize = reader.uint16();\n                this.name = reader.string(nameSize, 'utf-8');\n                reader.align(8);\n                const datatypePosition = reader.position;\n                this._datatype = new hdf5.Datatype(reader);\n                reader.seek(datatypePosition);\n                reader.skip(datatypeSize);\n                reader.align(8);\n                const dataspacePosition = reader.position;\n                this._dataspace = new hdf5.Dataspace(reader);\n                reader.seek(dataspacePosition);\n                reader.skip(dataspaceSize);\n                reader.align(8);\n                this._data = this._dataspace.read(this._datatype, reader);\n                break;\n            }\n            case 3: {\n                reader.byte();\n                const nameSize = reader.uint16();\n                const datatypeSize = reader.uint16();\n                const dataspaceSize = reader.uint16();\n                const encoding = reader.byte() === 1 ? 'utf-8' : 'ascii';\n                this.name = reader.string(nameSize, encoding);\n                const datatypePosition = reader.position;\n                this._datatype = new hdf5.Datatype(reader);\n                reader.seek(datatypePosition);\n                reader.skip(datatypeSize);\n                const dataspacePosition = reader.position;\n                this._dataspace = new hdf5.Dataspace(reader);\n                reader.seek(dataspacePosition);\n                reader.skip(dataspaceSize);\n                this._data = this._dataspace.read(this._datatype, reader);\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported attribute message version '${version}'.`);\n        }\n    }\n\n    decodeValue(globalHeap) {\n        if (this._data) {\n            return this._dataspace.decode(this._datatype, this._data, globalHeap);\n        }\n        return null;\n    }\n};\n\nhdf5.ObjectHeaderContinuation = class {\n\n    constructor(reader) {\n        this.offset = reader.offset();\n        this.length = reader.length();\n    }\n};\n\nhdf5.SymbolTable = class {\n\n    constructor(reader) {\n        this.treeAddress = reader.offset();\n        this.heapAddress = reader.offset();\n    }\n};\n\nhdf5.ObjectModificationTime = class {\n\n    constructor(reader, type) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#ModificationTimeMessage\n        switch (type) {\n            case 0x000E: {\n                this.year = reader.uint32();\n                this.month = reader.uint16();\n                this.day = reader.uint16();\n                this.hour = reader.uint16();\n                this.minute = reader.uint16();\n                this.second = reader.uint16();\n                reader.skip(2);\n                break;\n            }\n            case 0x0012: {\n                const version = reader.byte();\n                reader.skip(3);\n                switch (version) {\n                    case 1:\n                        this.timestamp = reader.uint32();\n                        break;\n                    default:\n                        throw new hdf5.Error(`Unsupported object modification time message version '${version}'.`);\n                }\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported object modification time message type '${type}'.`);\n            }\n        }\n    }\n};\n\nhdf5.AttributeInfo = class {\n\n    constructor(reader) {\n        const version = reader.byte();\n        switch (version) {\n            case 0: {\n                const flags = reader.byte();\n                if ((flags & 1) !== 0) {\n                    this.maxCreationIndex = reader.uint64();\n                }\n                this.fractalHeapAddress = reader.offset();\n                this.attributeNameTreeAddress = reader.offset();\n                if ((flags & 2) !== 0) {\n                    this.attributeCreationOrderTreeAddress = reader.offset();\n                }\n                break;\n            }\n            default:\n                throw new hdf5.Error(`Unsupported attribute info message version '${version}'.`);\n        }\n    }\n};\n\nhdf5.Tree = class {\n\n    constructor(reader, offset, dimensionality) {\n        // https://support.hdfgroup.org/HDF5/doc/H5.format.html#V1Btrees\n        const position = reader.position;\n        reader.seek(offset);\n        reader.expect('TREE');\n        this.type = reader.byte();\n        this.level = reader.byte();\n        const entries = reader.uint16();\n        reader.offset(); // address of left sibling\n        reader.offset(); // address of right sibling\n        this.nodes = [];\n        switch (this.type) {\n            case 0: { // Group nodes\n                for (let i = 0; i < entries; i++) {\n                    reader.length();\n                    const childPointer = reader.offset();\n                    if (this.level === 0) {\n                        const node = new hdf5.SymbolTableNode(reader, childPointer);\n                        this.nodes.push(node);\n                    } else {\n                        const tree = new hdf5.Tree(reader, childPointer);\n                        this.nodes.push(...tree.nodes);\n                    }\n                }\n                break;\n            }\n            case 1: { // Raw data chunk nodes\n                for (let i = 0; i < entries; i++) {\n                    const size = reader.int32();\n                    const filterMask = reader.int32();\n                    const fields = [];\n                    for (let j = 0; j < dimensionality; j++) {\n                        fields.push(reader.uint64());\n                    }\n                    const childPointer = reader.offset();\n                    if (this.level === 0) {\n                        const position = reader.position;\n                        reader.seek(childPointer);\n                        const data = reader.read(size);\n                        this.nodes.push({ data, fields, filterMask });\n                        reader.seek(position);\n                    } else {\n                        const tree = new hdf5.Tree(reader, childPointer, dimensionality);\n                        this.nodes.push(...tree.nodes);\n                    }\n                }\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported B-Tree node type '${this.type}'.`);\n            }\n        }\n        reader.seek(position);\n    }\n};\n\nhdf5.Heap = class {\n\n    constructor(reader, offset) {\n        const position = reader.position;\n        reader.seek(offset);\n        this._reader = reader;\n        reader.expect('HEAP');\n        const version = reader.byte();\n        switch (version) {\n            case 0: {\n                reader.skip(3);\n                this._dataSize = reader.length();\n                this._offsetToHeadOfFreeList = reader.length();\n                this._dataAddress = reader.offset();\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported Local Heap version '${version}'.`);\n            }\n        }\n        reader.seek(position);\n    }\n\n    getString(offset) {\n        const position = this._reader.position;\n        this._reader.seek(this._dataAddress + offset);\n        const value = this._reader.string(-1, 'utf-8');\n        this._reader.seek(position);\n        return value;\n    }\n};\n\nhdf5.GlobalHeap = class {\n\n    constructor(reader) {\n        this._reader = reader;\n        this._collections = new Map();\n    }\n\n    get(globalHeapID) {\n        const address = globalHeapID.address;\n        if (!this._collections.has(address)) {\n            this._collections.set(address, new hdf5.GlobalHeapCollection(this._reader, address));\n        }\n        const collection = this._collections.get(globalHeapID.address);\n        return collection.getObject(globalHeapID.objectIndex);\n    }\n};\n\nhdf5.GlobalHeapCollection = class {\n\n    constructor(reader, offset) {\n        const position = reader.position;\n        reader.seek(offset);\n        const start = reader.position;\n        reader.expect('GCOL');\n        const version = reader.byte();\n        switch (version) {\n            case 1: {\n                reader.skip(3);\n                this._objects = new Map();\n                const size = reader.length();\n                const end = start + size;\n                while (reader.position < end) {\n                    const index = reader.uint16();\n                    if (index === 0) {\n                        break;\n                    }\n                    this._objects.set(index, new hdf5.GlobalHeapObject(reader));\n                    reader.align(8);\n                }\n                break;\n            }\n            default: {\n                throw new hdf5.Error(`Unsupported global heap collection version '${version}'.`);\n            }\n        }\n        reader.seek(position);\n    }\n\n    getObject(objectIndex) {\n        if (this._objects.has(objectIndex)) {\n            return this._objects.get(objectIndex);\n        }\n        return null;\n    }\n};\n\nhdf5.GlobalHeapObject = class {\n\n    constructor(reader) {\n        reader.uint16();\n        reader.skip(4);\n        this._position = reader.position;\n        this._reader = reader;\n        const length = reader.length();\n        reader.skip(length);\n    }\n\n    reader() {\n        this._reader.seek(this._position);\n        return this._reader;\n    }\n};\n\nhdf5.GlobalHeapID = class {\n\n    constructor(reader) {\n        this.address = reader.offset();\n        this.objectIndex = reader.uint32();\n    }\n};\n\nhdf5.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'HDF5 Error';\n    }\n};\n\nexport const File = hdf5.File;\n"
  },
  {
    "path": "source/hickle.js",
    "content": "\nconst hickle = {};\n\nhickle.ModelFactory = class {\n\n    async match(context) {\n        const group = await context.peek('hdf5');\n        if (group && group.attributes && group.attributes.get('CLASS') === 'hickle') {\n            return context.set('hickle', group);\n        }\n        return null;\n    }\n\n    async open(context) {\n        return new hickle.Model(context.value);\n    }\n};\n\nhickle.Model = class {\n\n    constructor(group) {\n        this.format = 'Hickle Weights';\n        this.modules = [new hickle.Graph(group)];\n    }\n};\n\nhickle.Graph = class {\n\n    constructor(group) {\n        this.inputs = [];\n        this.outputs = [];\n        const deserialize = (group) => {\n            if (group && group.attributes.has('type')) {\n                const type = group.attributes.get('type');\n                if (Array.isArray(type) && type.length && typeof type[0] === 'string') {\n                    switch (type[0]) {\n                        case 'hickle':\n                        case 'dict_item': {\n                            if (group.groups.size === 1) {\n                                return deserialize(group.groups.values().next().value);\n                            }\n                            throw new hickle.Error(`Invalid Hickle type value '${type[0]}'.`);\n                        }\n                        case 'dict': {\n                            const dict = new Map();\n                            for (const [name, obj] of group.groups) {\n                                const value = deserialize(obj);\n                                dict.set(name, value);\n                            }\n                            return dict;\n                        }\n                        case 'ndarray': {\n                            return group.value;\n                        }\n                        default: {\n                            throw new hickle.Error(`Unsupported Hickle type '${type[0]}'`);\n                        }\n                    }\n                }\n                throw new hickle.Error(`Unsupported Hickle type '${JSON.stringify(type)}'`);\n            }\n            throw new hickle.Error('Unsupported Hickle group.');\n        };\n        const obj = deserialize(group);\n        const layers = new Map();\n        if (obj && obj instanceof Map && Array.from(obj.values()).every((value) => value.type && value.shape)) {\n            for (const [key, value] of obj) {\n                const tensor = new hickle.Tensor(key, value.shape, value.type, value.littleEndian, value.type === 'string' ? value.value : value.data);\n                const bits = key.split('.');\n                const parameter = bits.pop();\n                const layer = bits.join('.');\n                if (!layers.has(layer)) {\n                    layers.set(layer, []);\n                }\n                layers.get(layer).push({ name: parameter, value: tensor });\n            }\n        }\n        this.nodes = Array.from(layers).map(([name, value]) => new hickle.Node(name, value));\n    }\n};\n\nhickle.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\nhickle.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new hickle.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nhickle.Node = class {\n\n    constructor(name, parameters) {\n        this.type = { name: 'Weights' };\n        this.name = name;\n        this.inputs = parameters.map((parameter) => {\n            return new hickle.Argument(parameter.name, [\n                new hickle.Value(parameter.value.name, null, parameter.value)\n            ]);\n        });\n        this.outputs = [];\n        this.attributes = [];\n    }\n};\n\nhickle.Tensor = class {\n\n    constructor(name, shape, type, littleEndian, data) {\n        this.name = name;\n        this.type = new hickle.TensorType(type, new hickle.TensorShape(shape));\n        this.encoding = littleEndian ? '<' : '>';\n        this._data = data;\n    }\n\n    get values() {\n        if (Array.isArray(this._data) || this._data === null) {\n            return null;\n        }\n        if (this._data instanceof Uint8Array) {\n            return this._data;\n        }\n        return this._data.peek();\n    }\n};\n\nhickle.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nhickle.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`) : '';\n    }\n};\n\nhickle.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Hickle model.';\n    }\n};\n\nexport const ModelFactory = hickle.ModelFactory;\n"
  },
  {
    "path": "source/imgdnn.js",
    "content": "\nconst imgdnn = {};\n\nimgdnn.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        const signature = [0x49, 0x4d, 0x47, 0x44, 0x4e, 0x4e]; // IMGDNN\n        if (stream && stream.length >= signature.length && stream.peek(6).every((value, index) => value === signature[index])) {\n            return 'imgdnn';\n        }\n        return null;\n    }\n\n    open(/* context */) {\n        throw new imgdnn.Error('Invalid file content. File contains undocumented IMGDNN data.');\n    }\n};\n\nimgdnn.Model = class {\n\n    constructor(metadata, model) {\n        this.format = 'IMGDNN';\n        this.modules = [new imgdnn.Graph(metadata, model)];\n    }\n};\n\nimgdnn.Graph = class {\n\n    constructor(/* metadata, model */) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n    }\n};\n\nimgdnn.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading IMGDNN model.';\n    }\n};\n\nexport const ModelFactory = imgdnn.ModelFactory;\n\n"
  },
  {
    "path": "source/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"description\" content=\"Visualizer for neural network, deep learning and machine learning models.\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover\">\n<meta http-equiv=\"Content-Security-Policy\" content=\"script-src 'self'\">\n<meta name=\"version\" content=\"0.0.0\">\n<meta name=\"date\" content=\"\">\n<title>Netron</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"grapher.css\">\n<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"favicon.ico\">\n<link rel=\"icon\" type=\"image/png\" href=\"icon.png\">\n<link rel=\"apple-touch-icon\" type=\"image/png\" href=\"icon.png\">\n<link rel=\"apple-touch-icon-precomposed\" type=\"image/png\" href=\"icon.png\">\n<link rel=\"fluid-icon\" type=\"image/png\" href=\"icon.png\">\n<script type=\"text/javascript\" src=\"index.js\"></script>\n<style>\nhtml { touch-action: none; overflow: hidden; width: 100%; height: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; -ms-text-rendering: optimizeLegibility; -o-text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-font-smoothing: antialiased; -ms-font-smoothing: antialiased; -o-font-smoothing: antialiased; }\nbody { touch-action: none; overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"Ubuntu\", \"Droid Sans\", sans-serif, \"PingFang SC\"; font-size: 12px; text-rendering: geometricPrecision; }\nbutton { font-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"Ubuntu\", \"Droid Sans\", sans-serif, \"PingFang SC\"; }\n.center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }\n.target { display: flex; height: 100%; width: 100%; overflow: auto; outline: none; touch-action: pan-x pan-y; }\n.canvas { margin: auto; flex-shrink: 0; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.open-file-dialog { display: none; }\n.default { background-color: #ffffff; }\n.default .logo { display: none; }\n.default .target { display: flex; opacity: 1; }\n.default .toolbar { display: flex; }\n.toolbar { display: flex; align-items: center; position: absolute; bottom: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.toolbar button:focus { outline: 0; }\n.toolbar-button { background: None; border-radius: 6px; border: 0; margin: 0; margin-right: 1px; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 32px; height: 32px; user-select: none; }\n.toolbar-path { display: flex; align-items: center; }\n.toolbar-select { background: transparent; position: relative; width: 170px; margin: 4px 4px 4px 4px; }\n.toolbar-select select { width: 100%; appearance: none; -webkit-appearance: none; -moz-appearance: none; font-family: inherit; font-size: 12px; line-height: 16px; border: 1px solid; padding: 3px 18px 3px 10px; border-radius: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-sizing: border-box; }\n.toolbar-select select { background: #777; border-color: #777; color: #fff; }\n.toolbar-select-arrow { position: absolute; top: 50%; right: 8px; transform: translateY(-50%); pointer-events: none; }\n.toolbar-select-arrow { fill: #ffffff; }\n.toolbar-select select:hover { background: #000000; border-color: #000000; }\n.toolbar-select select:focus { outline: 0; }\n.toolbar-path-back-button { background: #777; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border: 1px solid; border-color: #777; margin: 4px 0px 4px 4px; padding: 5px 8px 5px 8px; cursor: pointer; color: #ffffff; font-size: 12px; line-height: 12px; transition: 0.1s; }\n.toolbar-path-back-button:hover { background: #000000; border-color: #000000; }\n.toolbar-path-name-button { background: #777; border: 0px; border-color: #777; color: #ffffff; border-left: 1px; border-left-color: #ffffff; margin: 4px 0 4px 1px; padding: 6px 8px 6px 8px; cursor: pointer; width: auto; font-size: 12px; line-height: 12px; transition: 0.1s; }\n.toolbar-path-name-button:hover { background: #000000; border-color: #000000; }\n.toolbar-path-name-button:last-child { border-top-right-radius: 6px; border-bottom-right-radius: 6px; }\n.toolbar-icon .border { stroke: #fff; }\n.toolbar-icon .stroke { stroke: #808080; }\n.toolbar-icon .fill { fill: #808080; }\n.toolbar-icon:hover .stroke { stroke: #000000; }\n.toolbar-icon:hover .fill { fill: #000000; }\n.message { display: none; opacity: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%; flex-direction: column; justify-content: flex-start; }\n.message-text { display: inline; text-align: center; width: 562px; font-size: 13px; line-height: 20px; margin-top: 50vh; padding-top: 56px; padding-bottom: 20px; margin-left: auto; margin-right: auto; user-select: text; -webkit-user-select: text; -moz-user-select: text; }\n.welcome .message-text a { text-decoration: none; color: #666666; }\n.welcome .message-text a:visited { color: inherit; }\n.welcome .message-text a:hover { color: #242424; text-decoration: underline; }\n.message-button { display: inline; text-align: center; width: 125px; margin-left: auto; margin-right: auto; }\n.logo-text { top: -57px; width: 582px; transition: 0.1s; }\n.logo-name { top: -170px; width: 582px; transition: 0.1s; }\n.logo-icon { left: 248px; top: -18px; width: 106px; height: 106px; transition: 0.1s; }\n.logo-spinner { left: 248px; top: -18px; width: 106px; height: 106px; display: none; }\n.logo-stroke { stroke: #444444; }\n.logo-fill { fill: #444444; }\n.logo-border { stroke: #555555; }\n.logo-glyph { fill: #444444; }\n.logo-button { font-size: 12px; font-weight: bold; line-height: 1.25; text-align: center; vertical-align: middle; min-width: 5em; height: 2.7em; border-radius: 1.3em; transition: 0.1s; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #444444; background-color: #ececec; border: 1px solid #444444; }\n.logo-button:hover { color: #ececec; background-color: #444444; cursor: pointer; transition: 0.2s; }\n.logo-button:focus { outline: 0; }\n.logo-message { display: none; height: 0px; }\n.logo-github { display: none; }\n.open-file-button { top: 170px; left: 0px; width: 10.5em; }\n.progress { top: 120px; height: 2px; width: 400px; }\n.progress-bar { height: 100%; width: 0%; background-color: #444444; }\n.notification .logo-name { display: none; }\n.notification .open-file-button { display: none; }\n.notification .progress { display: none; }\n.welcome body { background-color: #ececec; }\n.welcome { background-color: #ececec; color: #242424; }\n.welcome .message-text { display: none; opacity: 0; }\n.welcome .message-button { display: none; opacity: 0; }\n.welcome .target { display: none; opacity: 0; }\n.welcome .menu { background-color: #ffffff; }\n.welcome.spinner .logo-spinner { display: block; -webkit-animation: orbit 0.5s infinite linear; animation: orbit 0.5s infinite linear; cursor: wait; }\n.welcome.spinner .menu-button { display: none; }\n.welcome.notification .menu-button { display: none; }\n.notification body { background-color: #ececec; }\n.notification .message { display: flex; opacity: 1; }\n.notification .message-text { display: inline; opacity: 1; }\n.notification .message-button { display: inline; opacity: 1; }\n.alert { background-color: #ececec; color: #242424; }\n.alert .target { display: none; opacity: 0; }\n.alert .toolbar { display: none; opacity: 0; }\n.alert .menu { display: none; opacity: 0; }\n.alert .logo { display: none; opacity: 0; }\n.alert .message { display: flex; opacity: 1; }\n.alert .message-text { display: inline; opacity: 1; width: 50%; padding-top: 0px; }\n.alert .message-button { display: inline; opacity: 1; }\n.about { overflow: hidden; }\n.about .toolbar { display: none; }\n.about .logo { display: block; background-color: #ececec; color: #666666; }\n.about .logo-message { display: block; top: 132px; font-size: 14px; }\n.about .logo-github { display: block; top: 340px; width: 48px; height: 48px; }\n.about a { text-decoration: none; color: #666666; }\n.about a:visited { color: inherit; }\n.about a:hover { color: #242424; }\n.about .open-file-button { display: none; }\n.about .logo-name { display: none; }\n.about .notification { display: none; }\n.about .progress { display: none; }\n.about .menu-button { display: none; }\n.titlebar { color: #aaaaaa; display: none; height: 32px; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 2; -webkit-app-region: drag; }\n.titlebar-visible { display: block; }\n.titlebar-content { display: block; padding: 0 142px; height: 100%; text-align: center; font-size: 14px; line-height: 32px; transition: all .1s ease-in-out; user-select: none; }\n.titlebar-content-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.spinner .titlebar-content { opacity: 0; }\n.active .titlebar { color: #464646; transition: all 0.05s ease-in-out; }\n.titlebar-control-box { display: none; align-items: center; flex-direction: row-reverse; height: 100%; position: absolute; top: 0; right: 0; width: 138px; }\n.titlebar-control-box-visible { display: flex; }\n.titlebar-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; }\n.titlebar-button { display: flex; justify-content: center; align-items: center; width: 46px; height: 32px; user-select: none; -webkit-app-region: no-drag; }\n.titlebar-button:hover { color: #000000; background-color: rgba(0, 0, 0, 0.15); }\n.titlebar-button-close:hover { color: #ffffff; background-color: #b43029; }\n.menu-button { display: flex; justify-content: center; align-items: center; color: #aaaaaa; font-size: 20px; height: 32px; width: 32px; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 2; -webkit-app-region: no-drag; -webkit-app-region: no-drag; user-select: none; }\n.menu-button:hover { color: #000000; }\n.menu { display: block; position: absolute; left: -17em; width: 17em; top: 0; height: 100%; z-index: 2; background-color: #ececec; border-right: 1px solid rgba(255, 255, 255, 0.5); padding-top: 40px; padding-bottom: 2px; margin-left: 0; margin-top: 0; overflow: hidden; transition: 0.1s; }\n.menu .menu-group { margin-bottom: 12px; }\n.menu .menu-group .menu-group-header { display: block; border: none; border-radius: 0; color: black; width: 100%; text-align: left; margin: 4px 12px 5px 12px; white-space: no-wrap; font-size: 11px; font-weight: bold; color: #bbbbbb; white-space: nowrap; }\n.menu .menu-group .menu-command { display: block; border: none; border-radius: 0; background-color: transparent; color: black; width: 100%; text-align: left; padding: 4px 12px 5px 12px; font-size: 12px; }\n.menu .menu-group .menu-command:focus { color: #ffffff; background-color: #2e6bd2; outline: none; }\n.menu .menu-group .menu-command:disabled { color: #888888; }\n.menu .menu-group .menu-command .menu-label { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }\n.menu .menu-group .menu-command .menu-shortcut { display: block; float: right; margin-left: 25px; color: #888888; }\n.menu .menu-group .menu-separator { border-top: 1px; border-bottom: 0; border-style: solid; border-color: #e5e5e5; margin-left: 12px; margin-right: 12px; }\n.about .titlebar-visible { opacity: 0; }\n@-webkit-keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }\n@keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }  100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }\n.welcome.spinner .logo-spinner-stroke { stroke: #ececec; }\n.welcome.spinner .logo-name { display: none; }\n.welcome.spinner .open-file-button { display: none; }\n.welcome.spinner .target { display: flex; opacity: 0; }\n.welcome .notification .logo-name { display: none; }\n.welcome .toolbar { display: none; }\n@media (prefers-color-scheme: dark) {\n:root { color-scheme: dark; }\n.default { background-color: #404040; }\n.target { background-color: #404040; }\n.welcome { background-color: #1e1e1e; color: #888888; }\n.alert { background-color: #1e1e1e; color: #888888; }\n.logo-stroke { stroke: #888888; }\n.logo-fill { fill: #888888; }\n.logo-border { stroke: #000000; }\n.logo-glyph { fill: #888888; }\n.logo-spinner-stroke { stroke: #ffffff; }\n.logo-button { color: #888888; background-color: #1e1e1e; border-color: #888888; }\n.logo-button:hover { color: #1e1e1e; background-color: #888888; }\n.welcome .progress-bar { background-color: #888888; }\n.welcome .menu { background-color: #2d2d2d }\n.about .logo { background-color: #1e1e1e; color: #888888; }\n.about a { color: #c6c6c6; }\n.about a:hover { color: #565656; }\n.welcome .message-text a { color: #c6c6c6; }\n.welcome .message-text a:visited { color: #c6c6c6; }\n.welcome .message-text a:hover { color: #565656; }\n.toolbar-icon .border { stroke: #333333; }\n.toolbar-icon .stroke { stroke: #aaaaaa; }\n.toolbar-icon .fill { fill: #aaaaaa; }\n.toolbar-icon:hover .stroke { stroke: #dfdfdf; }\n.toolbar-icon:hover .fill { fill: #dfdfdf; }\n.toolbar-path-back-button { background: #aaaaaa; border-color: #aaaaaa; color: #333333; }\n.toolbar-path-back-button:hover { background: #dfdfdf; border-color: #dfdfdf; }\n.toolbar-path-name-button { background: #aaaaaa ; border-color: #aaaaaa; color: #404040; }\n.toolbar-path-name-button:hover { background: #dfdfdf; border-color: #dfdfdf; }\n.toolbar-select select { background: #aaaaaa; border-color: #aaaaaa; color: #404040; }\n.toolbar-select select:hover { background: #dfdfdf; border-color: #dfdfdf; color: #404040; }\n.toolbar-select-arrow { fill: #404040; }\n.titlebar { color: #949494; }\n.welcome body { background-color: #1e1e1e; }\n.default body { background-color: #404040; }\n.active .titlebar { color: #c4c4c4; }\n.titlebar-button:hover { color: #ffffff; background-color: rgba(0, 0, 0, 0.15); }\n.titlebar-button-close:hover { color: #ffffff; background-color: #b43029; }\n.menu-button { color: #aaaaaa; }\n.menu-button:hover { color: #ffffff; }\n.menu { background-color: #2d2d2d; border-color: rgba(0, 0, 0, 0); }\n.menu .menu-group .menu-group-header { color: #666666; }\n.menu .menu-group .menu-command { color: #ffffff; }\n.menu .menu-group .menu-command:focus { color: #ffffff; background-color: #2e6bd2; }\n.menu .menu-group .menu-command:disabled { color: #888888; }\n.menu .menu-group .menu-command .shortcut { color: #888888; }\n.menu .menu-group .menu-separator { border-color: #363636; }\n}\n@media all and (max-width: 640px) {\n.logo { width: 240px; }\n.logo-text { opacity: 0; }\n.logo-name { opacity: 0; }\n.logo-icon { left: 0; width: 128px; height: 128px;  }\n.logo-spinner { left: 0; width: 128px; height: 128px; }\n.logo .open-file-button { top: 204px; left: 0; }\n.message-text { padding-top: 68px; width: 320px; }\n.progress { top: 160px; height: 2px; width: 100px; }\n.about .logo { width: 100%; padding-left: 0; padding-right: 0; }\n.about .logo-message { top: 175px; font-size: 12px; }\n.about .logo-github { top: 370px; }\n}\n.sidebar { display: flex; flex-direction: column; font-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"Ubuntu\", \"Droid Sans\", sans-serif; font-size: 12px; height: 100%; right: -100%; position: fixed; transition: 0.1s; top: 0; background-color: #ececec; color: #242424; overflow: hidden; border-left: 1px solid rgba(255, 255, 255, 0.5); opacity: 0; }\n.sidebar-title { font-weight: bold; font-size: 12px; letter-spacing: 0.5px; text-transform: uppercase; height: 20px; margin: 0; padding: 20px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.sidebar-closebutton:hover { color: #242424; }\n.sidebar-content { display: flex; flex-direction: column; flex-grow: 1; height: 0; }\n.sidebar-header { font-weight: bold; font-size: 12px; letter-spacing: 0.5px; text-transform: uppercase; height: 20px; margin: 0; margin-top: 30px; padding-top: 10px; padding-bottom: 10px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.sidebar-section { font-weight: bold; font-size: 11px; text-transform: uppercase; line-height: 1.25; margin-top: 16px; margin-bottom: 16px; display: block; user-select: none; -webkit-user-select: none; -moz-user-select: none; cursor: default; }\n.sidebar-object { flex-grow: 1; padding: 0px 20px 20px 20px; overflow-y: auto; }\n.sidebar-item { margin-bottom: 0px; display: block; }\n.sidebar-item-name { float: left; font-size: 11px; min-width: 95px; max-width: 95px; padding-right: 5px; padding-top: 7px; display: block; }\n.sidebar-item-name input { color: #777; font-family: inherit; font-size: inherit; color: inherit; background-color: inherit; width: 100%; text-align: right; margin: 0; padding: 0; border: 0; outline: none; text-overflow: ellipsis; }\n.sidebar-item-value-list { margin: 0; margin-left: 105px; overflow: hidden; display: block; padding: 0; }\n.sidebar-item-value { font-size: 11px; background-color: #fcfcfc; border-radius: 2px; border: 1px solid #fcfcfc; margin-top: 3px; margin-bottom: 3px; overflow: auto; }\n.sidebar-item-value-content { background-color: #f8f8f8; border: 1px solid #f8f8f8; }\n.sidebar-item-value b { font-weight: bold; }\n.sidebar-item-value code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }\n.sidebar-item-value pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; margin: 0; overflow: auto; white-space: pre; word-wrap: normal; display: block; }\n.sidebar-item-value-line { padding: 4px 6px 4px 6px; overflow-x: auto; white-space: pre; }\n.sidebar-item-value-line-wrap { white-space: pre-wrap; overflow-x: hidden; overflow-wrap: break-word; }\n.sidebar-item-value-line-break { padding: 4px 6px 4px 6px; overflow-x: auto; white-space: pre; }\n.sidebar-item-value-line-link { padding: 4px 6px 4px 6px; cursor: default; overflow-x: auto; white-space: nowrap; }\n.sidebar-item-value-line-link:hover { text-decoration: underline; }\n.sidebar-item-value-line-border { padding: 4px 6px 4px 6px; border-top: 1px solid rgba(27, 31, 35, 0.05); }\n.sidebar-item-value-line-content { white-space: pre; word-wrap: normal; overflow: auto; display: block; }\n.sidebar-item-value-expander { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; float: right; color: #aaa; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; padding: 4px 6px 4px 4px; }\n.sidebar-item-value-expander:hover { color: #333; }\n.sidebar-item-value-button { display: flex; justify-content: center; align-items: center; font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; width: 22px; height: 22px; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #aaa; }\n.sidebar-item-value-button svg use { fill: #aaa; stroke: #aaa; }\n.sidebar-item-value-button:hover svg use { fill: #333; stroke: #333; }\n.sidebar-item-value-button-tool { float: right; padding-left: 3px; }\n.sidebar-item-value-button-context { float: right; }\n.sidebar-item-selector {\n    font-family: inherit; font-size: 12px;\n    background-color: #fcfcfc; border: #fcfcfc; color: #333;\n    border-radius: 2px; width: 100%; height: 23px; padding: 3px 12px 3px 7px;\n    margin-top: 3px; margin-bottom: 3px; outline: none;\n    box-sizing: border-box; -moz-box-sizing: border-box;\n    appearance: none; -webkit-appearance: none; -moz-appearance: none;\n    background-image: linear-gradient(45deg, transparent 50%, #333 50%), linear-gradient(135deg, #333 50%, transparent 50%);\n    background-position: calc(100% - 12px) calc(10px), calc(100% - 7px) calc(10px);\n    background-size: 5px 5px, 5px 5px;\n    background-repeat: no-repeat;\n}\n.sidebar-separator { margin-bottom: 20px; }\n.sidebar-find-search { display: flex; align-items: center; background: #fff; border-radius: 16px; margin: 0px 20px 8px 20px; padding: 0px 8px 0px 8px; }\n.sidebar-find-query { width: 100vw; background: none; font-family: inherit; font-size: 13px; padding: 8px 8px 8px 8px; border: 0; outline: 0; }\n.sidebar-find-toggle { margin-left: auto; margin-right: 2px; width: 16px; height: 16px; cursor: pointer; }\n.sidebar-find-toggle input[type=\"checkbox\"] { display: none; }\n.sidebar-find-toggle input[type=\"checkbox\"]:not(:checked) + svg { fill: #ccc; stroke: #ccc; }\n.sidebar-find-toggle input[type=\"checkbox\"]:checked + svg { fill: #555; stroke: #555; }\n.sidebar-find-toggle-icon { stroke: #555; fill: #555; width: 16px; height: 16px; }\n.sidebar-find-content { flex-grow: 1; padding: 0px 20px 20px 20px; overflow-y: auto; list-style-type: none; margin: 0; }\n.sidebar-find-content li *:first-child { margin-right: 2px; }\n.sidebar-find-content li { color: #666; font-size: 13px; height: 22px; line-height: 22px; padding: 0 12px 0 12px; outline: 0; white-space: nowrap; border-radius: 3px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n.sidebar-find-content li:hover { background: #e5e5e5; color: #000; }\n.sidebar-find-content-icon { stroke: #555; fill: #555; float: left; width: 16px; height: 16px; padding: 3px; }\n.sidebar-documentation { flex-grow: 1; padding: 0px 20px 20px 20px; overflow-y: auto; font-size: 13px; line-height: 1.5; margin: 0; }\n.sidebar-documentation h1 { font-weight: bold; font-size: 13px; line-height: 1.25; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; margin-top: 0; margin-bottom: 16px; }\n.sidebar-documentation h2 { font-weight: bold; font-size: 13px; line-height: 1.25; margin-top: 20px; margin-bottom: 16px; text-transform: uppercase; border: 0; }\n.sidebar-documentation h3 { font-weight: bold; font-size: 11px; line-height: 1.25; }\n.sidebar-documentation p { margin-top: 4px; margin-bottom: 4px; margin-left: 0px; }\n.sidebar-documentation a { color: #237; }\n.sidebar-documentation code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; background-color: rgba(27, 31, 35, 0.05); padding: 0.2em 0.4em; margin: 0; border-radius: 3px; }\n.sidebar-documentation pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; }\n.sidebar-documentation pre code { font-size: 13px; padding: 16px; line-height: 1.45; background-color: transparent; padding: 0; border-radius: 0; }\n.sidebar-documentation tt { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-weight: bold; font-size: 90%; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; padding: 0.2em 0.4em; margin: 0; }\n.sidebar-documentation dl dt { font-size: 13px; font-weight: bold; padding: 0; margin-top: 16px; margin-left: 0px; }\n.sidebar-documentation dd { padding: 0 16px; margin-left: 0; margin-bottom: 16px; }\n.sidebar-documentation ul { margin-top: 6px; margin-bottom: 6px; padding-left: 20px; }\n.sidebar-documentation blockquote { margin-left: 15px; margin-right: 15px; }\n@media (prefers-color-scheme: dark) {\n    .sidebar html { color: #dfdfdf; }\n    .sidebar { background-color: #2d2d2d; color: #dfdfdf; border-left: 1px solid rgba(0, 0, 0, 0); }\n    .sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n    .sidebar-closebutton:hover { color: #ffffff; }\n    .sidebar-item-value { background-color: #383838; border-color: #383838; }\n    .sidebar-item-value-content { background-color: #3e3e3e; border-color: #3e3e3e; }\n    .sidebar-item-value-line-border { border-color: rgba(0, 0, 0, 0.09); }\n    .sidebar-item-selector { background-color: #383838; border: #383838; color: #dfdfdf; background-image: linear-gradient(45deg, transparent 50%, #aaa 50%), linear-gradient(135deg, #aaa 50%, transparent 50%); }\n    .sidebar-item-disable-select { user-select: none; -webkit-user-select: none; -moz-user-select: none; }\n    .sidebar-header { border-bottom-color: #2d2d2d; color: #dfdfdf; }\n    .sidebar-documentation h1 { border-bottom: 1px solid #424242; color: #dfdfdf; }\n    .sidebar-documentation h2 { color: #dfdfdf; }\n    .sidebar-documentation p { color: #aaaaaa; }\n    .sidebar-documentation a { color: #6688aa; }\n    .sidebar-documentation tt { background-color:#1e1e1e; }\n    .sidebar-documentation code { background-color: #1e1e1e; }\n    .sidebar-documentation pre { background-color: #1e1e1e; }\n    .sidebar-find-search { background: #383838; color: #dfdfdf; border-color: #424242; }\n    .sidebar-find-toggle input[type=\"checkbox\"]:not(:checked) + svg { fill: #555; stroke: #555; }\n    .sidebar-find-toggle input[type=\"checkbox\"]:checked + svg { fill: #aaa; stroke: #aaa; }\n    .sidebar-find-content li { color: #aaaaaa; }\n    .sidebar-find-content li:hover { background: #383838; color: #dfdfdf; }\n    .sidebar-find-content-icon { stroke: #888888; fill: #888888; }\n    .sidebar-item-value-expander { color: #888; }\n    .sidebar-item-value-expander:hover { color: #e5e5e5; }\n    .sidebar-item-value-button { color: #888; }\n    .sidebar-item-value-button svg use { fill: #888; stroke: #888; }\n    .sidebar-item-value-button:hover svg use { fill: #e5e5e5; stroke: #e5e5e5; }\n}\n@media screen and (prefers-reduced-motion: reduce) {\n.menu { transition: none; }\n.sidebar { transition: none; }\n}\n</style>\n</head>\n<body class=\"welcome spinner\">\n<div id=\"target\" class=\"target\" tabindex=\"0\">\n</div>\n<div id=\"sidebar\" class=\"sidebar\">\n    <h1 id=\"sidebar-title\" class=\"sidebar-title\"></h1>\n    <a id=\"sidebar-closebutton\" class=\"sidebar-closebutton\" href=\"javascript:void(0)\" draggable=\"false\">&times;</a>\n    <div id=\"sidebar-content\" class=\"sidebar-content\"></div>\n    <svg width=\"0\" height=\"0\" display=\"none\">\n        <defs>\n            <symbol id=\"sidebar-icon-node\" viewBox=\"0 0 20 20\">\n                <circle cx=\"10\" cy=\"10\" r=\"6\" stroke-width=\"2\" fill=\"none\"/>\n            </symbol>\n            <symbol id=\"sidebar-icon-connection\" viewBox=\"0 0 20 20\">\n                <line x1=\"4\" y1=\"10\" x2=\"15\" y2=\"10\" stroke-width=\"2\" />\n                <polyline points=\"11,6 15,10 11,14\" stroke-width=\"2\" />\n            </symbol>\n            <symbol id=\"sidebar-icon-weight\" viewBox=\"0 0 20 20\">\n                <circle cx=\"5\" cy=\"5\" r=\"1\" />\n                <circle cx=\"10\" cy=\"5\" r=\"1\" />\n                <circle cx=\"15\" cy=\"5\" r=\"1\" />\n                <circle cx=\"5\" cy=\"10\" r=\"1\" />\n                <circle cx=\"10\" cy=\"10\" r=\"1\" />\n                <circle cx=\"15\" cy=\"10\" r=\"1\" />\n                <circle cx=\"5\" cy=\"15\" r=\"1\" />\n                <circle cx=\"10\" cy=\"15\" r=\"1\" />\n                <circle cx=\"15\" cy=\"15\" r=\"1\" />\n          </symbol>\n        </defs>\n    </svg>\n</div>\n<div id=\"toolbar\" class=\"toolbar\">\n    <button id=\"zoom-in-button\" class=\"toolbar-button\" title=\"Zoom In\">\n        <svg class=\"toolbar-icon\" viewbox=\"0 0 100 100\">\n            <circle class=\"border\" cx=\"50\" cy=\"50\" r=\"35\" stroke-width=\"8\" stroke=\"#fff\"></circle>\n            <line class=\"border\" x1=\"50\" y1=\"38\" x2=\"50\" y2=\"62\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"38\" y1=\"50\" x2=\"62\" y2=\"50\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"78\" y1=\"78\" x2=\"82\" y2=\"82\" stroke-width=\"12\" stroke-linecap=\"square\" stroke=\"#fff\"></line>\n            <circle class=\"stroke\" cx=\"50\" cy=\"50\" r=\"35\" stroke-width=\"4\"></circle>\n            <line class=\"stroke\" x1=\"50\" y1=\"38\" x2=\"50\" y2=\"62\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"38\" y1=\"50\" x2=\"62\" y2=\"50\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"78\" y1=\"78\" x2=\"82\" y2=\"82\" stroke-width=\"8\" stroke-linecap=\"square\"></line>\n        </svg>\n    </button>\n    <button id=\"zoom-out-button\" class=\"toolbar-button\" title=\"Zoom Out\">\n        <svg class=\"toolbar-icon\" viewbox=\"0 0 100 100\">\n            <circle class=\"border\" cx=\"50\" cy=\"50\" r=\"35\" stroke-width=\"8\" stroke=\"#fff\"></circle>\n            <line class=\"border\" x1=\"38\" y1=\"50\" x2=\"62\" y2=\"50\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"78\" y1=\"78\" x2=\"82\" y2=\"82\" stroke-width=\"12\" stroke-linecap=\"square\" stroke=\"#fff\"></line>\n            <circle class=\"stroke\" cx=\"50\" cy=\"50\" r=\"35\" stroke-width=\"4\"></circle>\n            <line class=\"stroke\" x1=\"38\" y1=\"50\" x2=\"62\" y2=\"50\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"78\" y1=\"78\" x2=\"82\" y2=\"82\" stroke-width=\"8\" stroke-linecap=\"square\"></line>\n        </svg>\n    </button>\n    <button id=\"sidebar-model-button\" class=\"toolbar-button\" title=\"Model Properties\">\n        <svg class=\"toolbar-icon\" viewbox=\"0 0 100 100\">\n            <rect class=\"border\" x=\"12\" y=\"12\" width=\"76\" height=\"76\" rx=\"16\" ry=\"16\" stroke-width=\"8\"></rect>\n            <line class=\"border\" x1=\"28\" y1=\"37\" x2=\"32\" y2=\"37\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"28\" y1=\"50\" x2=\"32\" y2=\"50\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"28\" y1=\"63\" x2=\"32\" y2=\"63\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"40\" y1=\"37\" x2=\"70\" y2=\"37\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"40\" y1=\"50\" x2=\"70\" y2=\"50\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <line class=\"border\" x1=\"40\" y1=\"63\" x2=\"70\" y2=\"63\" stroke-width=\"8\" stroke-linecap=\"round\" stroke=\"#fff\"></line>\n            <rect class=\"stroke\" x=\"12\" y=\"12\" width=\"76\" height=\"76\" rx=\"16\" ry=\"16\" stroke-width=\"4\"></rect>\n            <line class=\"stroke\" x1=\"28\" y1=\"37\" x2=\"32\" y2=\"37\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"28\" y1=\"50\" x2=\"32\" y2=\"50\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"28\" y1=\"63\" x2=\"32\" y2=\"63\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"40\" y1=\"37\" x2=\"70\" y2=\"37\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"40\" y1=\"50\" x2=\"70\" y2=\"50\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n            <line class=\"stroke\" x1=\"40\" y1=\"63\" x2=\"70\" y2=\"63\" stroke-width=\"4\" stroke-linecap=\"round\"></line>\n        </svg>\n    </button>\n    <button id=\"sidebar-target-button\" class=\"toolbar-button\" title=\"Target Properties\">\n        <svg class=\"toolbar-icon\" viewBox=\"0 0 100 100\">\n            <rect class=\"border\" x=\"12\" y=\"12\" width=\"76\" height=\"76\" rx=\"16\" ry=\"16\" stroke-width=\"8\"></rect>\n            <circle class=\"border\" cx=\"50\" cy=\"50\" r=\"18\" stroke-width=\"8\"></circle>\n            <circle class=\"border\" cx=\"50\" cy=\"50\" r=\"3\" stroke-width=\"8\"></circle>\n            <rect class=\"stroke\" x=\"12\" y=\"12\" width=\"76\" height=\"76\" rx=\"16\" ry=\"16\" stroke-width=\"4\"></rect>\n            <circle class=\"stroke\" cx=\"50\" cy=\"50\" r=\"18\" stroke-width=\"4\"></circle>\n            <circle class=\"stroke fill\" cx=\"50\" cy=\"50\" r=\"3\" stroke-width=\"4\"></circle>\n        </svg>\n    </button>\n    <div id=\"toolbar-navigator\" class=\"toolbar-select\">\n        <select id=\"toolbar-target-selector\">\n            <option value=\"Graphs\" disabled=\"true\">&#x2014; Graphs &#x2014;&#x2014;</option>\n            <option value=\"add\">add</option>\n            <option value=\"subtract\">subtract</option>\n            <option value=\"multiply\">multiply</option>\n            <option value=\"Functions\" disabled=\"true\">&#x2014; Functions &#x2014;&#x2014;</option>\n            <option value=\"line\">foo_bar.foo</option>\n        </select>\n        <svg class=\"toolbar-select-arrow\" viewBox=\"0 0 10 6\" width=\"10\" height=\"6\">\n            <path d=\"M0 0L5 6L10 0Z\" />\n        </svg>\n    </div>\n    <div id=\"toolbar-path\" class=\"toolbar-path\">\n        <button id=\"toolbar-path-back-button\" class=\"toolbar-path-back-button\" title=\"Back\">\n            &#x276E;\n        </button>\n    </div>\n</div>\n<div id=\"logo\" class=\"center logo\">\n    <a href=\"https://github.com/lutzroeder/netron\" target=\"blank_\">\n        <svg class=\"center logo-text\" viewbox=\"0 0 5120 1024\">\n            <g transform=\"scale(9) translate(-44,-15)\">\n                <g transform=\"matrix(100,0,0,100,60.9965,126)\">\n                    <path class=\"logo-glyph\" d=\"M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(100,0,0,100,164.341,126)\">\n                    <path class=\"logo-glyph\" d=\"M0.089,0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,0L0.089,0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(100,0,0,100,244.491,126)\">\n                    <path class=\"logo-glyph\" d=\"M0.216,0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,0L0.216,0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(100,0,0,100,323.031,126)\">\n                    <path class=\"logo-glyph\" d=\"M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,0L0.444,0L0.193,-0.341L0.154,-0.341L0.154,0L0.089,0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(100,0,0,100,520.979,126)\">\n                    <path class=\"logo-glyph\" d=\"M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n            </g>\n        </svg>\n        <svg class=\"center logo-icon\" viewbox=\"0 0 1024 1024\">\n            <circle class=\"logo-stroke\" cx=\"512\" cy=\"512\" r=\"431\" fill=\"none\" stroke-width=\"32\"></circle>\n            <circle class=\"logo-border\" cx=\"512\" cy=\"512\" r=\"450\" fill=\"none\" stroke-width=\"6\"></circle>\n            <circle class=\"logo-border\" cx=\"512\" cy=\"512\" r=\"412\" fill=\"none\" stroke-width=\"6\"></circle>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"392\" x2=\"540\" y2=\"280\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"632\" x2=\"540\" y2=\"280\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"392\" x2=\"540\" y2=\"435\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"632\" x2=\"540\" y2=\"435\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"392\" x2=\"540\" y2=\"590\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"632\" x2=\"540\" y2=\"590\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"392\" x2=\"540\" y2=\"744\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"296\" y1=\"632\" x2=\"540\" y2=\"744\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"540\" y1=\"280\" x2=\"785\" y2=\"512\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"540\" y1=\"590\" x2=\"785\" y2=\"512\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"540\" y1=\"435\" x2=\"785\" y2=\"512\" stroke-width=\"12\"></line>\n            <line class=\"logo-stroke\" x1=\"540\" y1=\"744\" x2=\"785\" y2=\"512\" stroke-width=\"12\"></line>\n            <g transform=\"translate(296, 392)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n            <g transform=\"translate(296, 632)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n            <g transform=\"translate(540, 280)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n            <g transform=\"translate(540, 435)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n            <g transform=\"translate(540, 590)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n            <g transform=\"translate(540, 744)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n            <g transform=\"translate(785, 512)\">\n                <circle class=\"logo-fill\" cx=\"0\" cy=\"0\" r=\"51\"></circle>\n                <circle class=\"logo-border\" cx=\"0\" cy=\"0\" r=\"51\" fill=\"none\" stroke-width=\"6\"></circle>\n            </g>\n        </svg>\n        <svg id=\"logo-spinner\" class=\"center logo-spinner\" viewbox=\"0 0 1024 1024\">\n            <g transform=\"translate(512, 512)\" style=\"opacity: 1\">\n                <path class=\"logo-spinner-stroke\" d=\"M-431,0 A-431,-431 0 0,1 0,-431\" stroke-width=\"24\" fill=\"None\"></path>\n            </g>\n        </svg>\n    </a>\n    <a href=\"https://www.lutzroeder.com\" target=\"blank_\">\n        <svg class=\"center logo-name\" viewbox=\"0 0 5120 300\">\n            <g transform=\"scale(5.8) translate(20, 0)\">\n                <g transform=\"matrix(30,0,0,30,18.9123,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.089,-0L0.089,-0.715L0.154,-0.715L0.154,-0.061L0.399,-0.061L0.399,-0L0.089,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,46.7613,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.086,-0.715L0.15,-0.715L0.15,-0.248C0.15,-0.177 0.166,-0.125 0.198,-0.091C0.23,-0.056 0.28,-0.039 0.346,-0.039C0.412,-0.039 0.46,-0.056 0.493,-0.091C0.525,-0.125 0.541,-0.177 0.541,-0.248L0.541,-0.715L0.606,-0.715L0.606,-0.269C0.606,-0.172 0.584,-0.1 0.542,-0.052C0.499,-0.005 0.433,0.019 0.346,0.019C0.259,0.019 0.193,-0.005 0.15,-0.052C0.107,-0.1 0.086,-0.172 0.086,-0.269L0.086,-0.715Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,83.5133,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.216,-0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,-0L0.216,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,114.421,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.012,-0L0.437,-0.656L0.074,-0.656L0.074,-0.715L0.548,-0.715L0.125,-0.06L0.505,-0.06L0.505,-0L0.012,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,171.777,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,203.607,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.437,-0.039C0.479,-0.039 0.519,-0.047 0.557,-0.063C0.595,-0.078 0.629,-0.101 0.659,-0.131C0.689,-0.161 0.712,-0.196 0.727,-0.234C0.743,-0.273 0.751,-0.313 0.751,-0.356C0.751,-0.399 0.743,-0.44 0.728,-0.478C0.712,-0.516 0.689,-0.55 0.659,-0.581C0.63,-0.611 0.596,-0.634 0.558,-0.649C0.52,-0.665 0.48,-0.673 0.437,-0.673C0.395,-0.673 0.355,-0.665 0.317,-0.649C0.28,-0.634 0.246,-0.611 0.216,-0.581C0.186,-0.55 0.163,-0.516 0.147,-0.478C0.132,-0.44 0.124,-0.399 0.124,-0.356C0.124,-0.313 0.132,-0.272 0.147,-0.234C0.163,-0.196 0.186,-0.161 0.216,-0.131C0.246,-0.101 0.279,-0.078 0.316,-0.062C0.354,-0.047 0.394,-0.039 0.437,-0.039ZM0.82,-0.356C0.82,-0.306 0.81,-0.258 0.791,-0.212C0.772,-0.167 0.744,-0.126 0.708,-0.091C0.671,-0.055 0.63,-0.028 0.583,-0.009C0.537,0.01 0.488,0.019 0.437,0.019C0.386,0.019 0.337,0.01 0.291,-0.009C0.245,-0.028 0.203,-0.055 0.167,-0.091C0.131,-0.127 0.103,-0.168 0.084,-0.213C0.065,-0.258 0.055,-0.306 0.055,-0.356C0.055,-0.407 0.065,-0.455 0.084,-0.501C0.103,-0.546 0.131,-0.587 0.167,-0.623C0.203,-0.659 0.244,-0.685 0.29,-0.704C0.335,-0.722 0.385,-0.731 0.437,-0.731C0.49,-0.731 0.539,-0.722 0.585,-0.703C0.631,-0.685 0.672,-0.658 0.708,-0.623C0.744,-0.587 0.772,-0.546 0.791,-0.501C0.81,-0.455 0.82,-0.407 0.82,-0.356Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,245.853,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,277.243,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.154,-0.056L0.245,-0.056C0.319,-0.056 0.371,-0.06 0.402,-0.069C0.433,-0.077 0.459,-0.091 0.481,-0.111C0.511,-0.139 0.534,-0.174 0.549,-0.215C0.564,-0.257 0.572,-0.305 0.572,-0.358C0.572,-0.413 0.564,-0.461 0.549,-0.502C0.533,-0.544 0.51,-0.578 0.48,-0.605C0.457,-0.625 0.429,-0.64 0.396,-0.648C0.364,-0.657 0.306,-0.661 0.224,-0.661L0.154,-0.661L0.154,-0.056ZM0.089,-0L0.089,-0.715L0.2,-0.715C0.299,-0.715 0.37,-0.71 0.412,-0.7C0.453,-0.69 0.489,-0.674 0.519,-0.65C0.559,-0.618 0.589,-0.578 0.61,-0.528C0.631,-0.478 0.641,-0.421 0.641,-0.357C0.641,-0.293 0.631,-0.236 0.61,-0.186C0.589,-0.136 0.559,-0.096 0.52,-0.066C0.489,-0.042 0.454,-0.025 0.414,-0.015C0.374,-0.005 0.31,-0 0.222,-0L0.089,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,314.142,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,345.532,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,376.911,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.06,-0.468L0.155,-0.731L0.228,-0.699L0.1,-0.452L0.06,-0.468Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n                <g transform=\"matrix(30,0,0,30,401.549,38)\">\n                    <path class=\"logo-glyph\" d=\"M0.034,-0.12L0.09,-0.15C0.1,-0.115 0.118,-0.087 0.144,-0.068C0.169,-0.049 0.2,-0.039 0.236,-0.039C0.281,-0.039 0.316,-0.052 0.342,-0.079C0.367,-0.106 0.38,-0.143 0.38,-0.19C0.38,-0.224 0.371,-0.253 0.354,-0.276C0.337,-0.299 0.3,-0.325 0.244,-0.355C0.172,-0.393 0.124,-0.427 0.101,-0.456C0.077,-0.485 0.065,-0.519 0.065,-0.56C0.065,-0.611 0.082,-0.652 0.116,-0.684C0.151,-0.716 0.195,-0.732 0.25,-0.732C0.286,-0.732 0.317,-0.724 0.344,-0.709C0.37,-0.694 0.392,-0.671 0.408,-0.641L0.358,-0.611C0.347,-0.631 0.333,-0.647 0.314,-0.658C0.295,-0.668 0.272,-0.674 0.246,-0.674C0.211,-0.674 0.183,-0.663 0.162,-0.643C0.141,-0.622 0.131,-0.594 0.131,-0.559C0.131,-0.509 0.172,-0.462 0.255,-0.419C0.27,-0.411 0.281,-0.405 0.289,-0.401C0.35,-0.367 0.391,-0.336 0.411,-0.306C0.432,-0.276 0.442,-0.237 0.442,-0.19C0.442,-0.126 0.423,-0.075 0.386,-0.037C0.348,0 0.297,0.019 0.233,0.019C0.186,0.019 0.146,0.007 0.113,-0.016C0.079,-0.039 0.053,-0.074 0.034,-0.12Z\" style=\"fill-rule:nonzero;\"/>\n                </g>\n            </g>\n        </svg>\n    </a>\n    <div class=\"center logo-message\">\n        <div style=\"height: 30px; text-align: center;\">Version <span id=\"version\" class=\"select\">{version}</span></div>\n        <div style=\"height: 30px; text-align: center;\">Copyright &copy; <a href=\"https://www.lutzroeder.com\" target=\"blank_\">Lutz Roeder</a></div>\n    </div>\n    <a id=\"logo-github\" class=\"center logo-github\" href=\"https://github.com/lutzroeder/netron\" target=\"blank_\">\n        <svg viewbox=\"0 0 438.549 438.549\">\n            <path class=\"logo-fill\" d=\"M409.132,114.573c-19.608-33.596-46.205-60.194-79.798-79.8C295.736,15.166,259.057,5.365,219.271,5.365\n                c-39.781,0-76.472,9.804-110.063,29.408c-33.596,19.605-60.192,46.204-79.8,79.8C9.803,148.168,0,184.854,0,224.63\n                c0,47.78,13.94,90.745,41.827,128.906c27.884,38.164,63.906,64.572,108.063,79.227c5.14,0.954,8.945,0.283,11.419-1.996\n                c2.475-2.282,3.711-5.14,3.711-8.562c0-0.571-0.049-5.708-0.144-15.417c-0.098-9.709-0.144-18.179-0.144-25.406l-6.567,1.136\n                c-4.187,0.767-9.469,1.092-15.846,1c-6.374-0.089-12.991-0.757-19.842-1.999c-6.854-1.231-13.229-4.086-19.13-8.559\n                c-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559\n                c-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429c-1.142-1.331-1.997-2.663-2.568-3.997\n                c-0.572-1.335-0.098-2.43,1.427-3.289c1.525-0.859,4.281-1.276,8.28-1.276l5.708,0.853c3.807,0.763,8.516,3.042,14.133,6.851\n                c5.614,3.806,10.229,8.754,13.846,14.842c4.38,7.806,9.657,13.754,15.846,17.847c6.184,4.093,12.419,6.136,18.699,6.136\n                c6.28,0,11.704-0.476,16.274-1.423c4.565-0.952,8.848-2.383,12.847-4.285c1.713-12.758,6.377-22.559,13.988-29.41\n                c-10.848-1.14-20.601-2.857-29.264-5.14c-8.658-2.286-17.605-5.996-26.835-11.14c-9.235-5.137-16.896-11.516-22.985-19.126\n                c-6.09-7.614-11.088-17.61-14.987-29.979c-3.901-12.374-5.852-26.648-5.852-42.826c0-23.035,7.52-42.637,22.557-58.817\n                c-7.044-17.318-6.379-36.732,1.997-58.24c5.52-1.715,13.706-0.428,24.554,3.853c10.85,4.283,18.794,7.952,23.84,10.994\n                c5.046,3.041,9.089,5.618,12.135,7.708c17.705-4.947,35.976-7.421,54.818-7.421s37.117,2.474,54.823,7.421l10.849-6.849\n                c7.419-4.57,16.18-8.758,26.262-12.565c10.088-3.805,17.802-4.853,23.134-3.138c8.562,21.509,9.325,40.922,2.279,58.24\n                c15.036,16.18,22.559,35.787,22.559,58.817c0,16.178-1.958,30.497-5.853,42.966c-3.9,12.471-8.941,22.457-15.125,29.979\n                c-6.191,7.521-13.901,13.85-23.131,18.986c-9.232,5.14-18.182,8.85-26.84,11.136c-8.662,2.286-18.415,4.004-29.263,5.146\n                c9.894,8.562,14.842,22.077,14.842,40.539v60.237c0,3.422,1.19,6.279,3.572,8.562c2.379,2.279,6.136,2.95,11.276,1.995\n                c44.163-14.653,80.185-41.062,108.068-79.226c27.88-38.161,41.825-81.126,41.825-128.906\n                C438.536,184.851,428.728,148.168,409.132,114.573z\"/>\n        </svg>\n    </a>\n    <button id=\"open-file-button\" class=\"center logo-button open-file-button\" tabindex=\"0\">Open Model&hellip;</button>\n    <div class=\"center progress\">\n        <div id=\"progress-bar\" class=\"progress-bar\"></div>\n    </div>\n    <input type=\"file\" id=\"open-file-dialog\" class=\"open-file-dialog\" multiple=\"false\" accept=\"\">\n    <!-- Preload fonts to workaround Chrome SVG layout issue -->\n    <div style=\"font-weight: normal; color: rgba(0, 0, 0, 0.01); user-select: none;\">.</div>\n    <div style=\"font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;\">.</div>\n    <div style=\"font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;\">.</div>\n</div>\n<div id=\"message\" class=\"message\">\n    <div id=\"message-text\" class=\"message-text\"></div>\n    <button id=\"message-button\" class=\"logo-button message-button\" tabindex=\"0\">OK</button>\n</div>\n<div id=\"titlebar\" class=\"titlebar\">\n    <svg style=\"position: absolute; width: 0px; height: 0px; overflow: hidden;\" aria-hidden=\"true\">\n        <symbol id=\"icon-arrow-right\" viewBox=\"0 0 1024 1024\">\n            <path d=\"M698.75712 565.02272l-191.488 225.4848a81.73568 81.73568 0 0 1-62.48448 28.89728 81.89952 81.89952 0 0 1-62.40256-134.94272l146.432-172.4416-146.432-172.4416a81.92 81.92 0 0 1 124.88704-106.06592l191.488 225.4848a81.87904 81.87904 0 0 1 0 106.02496z\"></path>\n        </symbol>\n    </svg>\n    <div id=\"titlebar-content\" class=\"titlebar-content\">\n        <span id=\"titlebar-content-text\" class=\"titlebar-content-text\"></span>\n    </div>\n    <div id=\"titlebar-control-box\" class=\"titlebar-control-box\">\n        <div id=\"titlebar-close\" class=\"titlebar-button titlebar-button-close\" title=\"Close\">\n            <svg class=\"titlebar-icon\" aria-hidden=\"true\">\n                <path d=\"M 0,0 0,0.7 4.3,5 0,9.3 0,10 0.7,10 5,5.7 9.3,10 10,10 10,9.3 5.7,5 10,0.7 10,0 9.3,0 5,4.3 0.7,0 Z\"></path>\n            </svg>\n        </div>\n        <div id=\"titlebar-toggle\" class=\"titlebar-button\" title=\"Maximize\">\n            <svg id=\"titlebar-maximize\" class=\"titlebar-icon\" aria-hidden=\"true\" style=\"position: absolute;\">\n                <path d=\"M 0,0 0,10 10,10 10,0 Z M 1,1 9,1 9,9 1,9 Z\"></path>\n            </svg>\n            <svg id=\"titlebar-restore\" class=\"titlebar-icon\" aria-hidden=\"true\" style=\"position: absolute;\">\n                <path d=\"m 2,1e-5 0,2 -2,0 0,8 8,0 0,-2 2,0 0,-8 z m 1,1 6,0 0,6 -1,0 0,-5 -5,0 z m -2,2 6,0 0,6 -6,0 z\"></path>\n            </svg>\n        </div>\n        <div id=\"titlebar-minimize\" class=\"titlebar-button\" title=\"Minimize\">\n            <svg class=\"titlebar-icon\" aria-hidden=\"true\">\n                <path d=\"M 0,5 10,5 10,6 0,6 Z\"></path>\n            </svg>\n        </div>\n    </div>\n</div>\n<div id=\"menu\" class=\"menu\"></div>\n<div id=\"menu-button\" class=\"menu-button\">&#8801;</div>\n</body>\n</html>"
  },
  {
    "path": "source/index.js",
    "content": "window.exports = {};\n\nwindow.exports.require = function(id, callback) {\n    if (!/^[a-zA-Z0-9_-]+$/.test(id)) {\n        throw new Error(\"Invalid module '\" + id + \"'.\");\n    }\n    var base = window.location.href || '';\n    base = base.split('?')[0].split('#')[0];\n    const index = base.lastIndexOf('/');\n    base = index > 0 ? base.substring(0, index + 1) : base;\n    base = base.lastIndexOf('/') === base.length - 1 ? base : base + '/';\n    var url = base + id + '.js';\n    var document = window.document;\n    var scripts = document.head.getElementsByTagName('script');\n    for (var i = 0; i < scripts.length; i++) {\n        if (url === scripts[i].getAttribute('src')) {\n            throw new Error(\"Duplicate import of '\" + url + \"'.\");\n        }\n    }\n    var script = document.createElement('script');\n    script.setAttribute('id', id);\n    script.setAttribute('type', 'module');\n    /* eslint-disable no-use-before-define */\n    var loadHandler = function() {\n        script.removeEventListener('load', loadHandler);\n        script.removeEventListener('error', errorHandler);\n        callback();\n    };\n    var errorHandler = function(e) {\n        script.removeEventListener('load', loadHandler);\n        script.removeEventListener('error', errorHandler);\n        callback(null, new Error(\"The script '\" + e.target.src + \"' failed to load.\"));\n    };\n    /* eslint-enable no-use-before-define */\n    script.addEventListener('load', loadHandler, false);\n    script.addEventListener('error', errorHandler, false);\n    script.setAttribute('src', url);\n    document.head.appendChild(script);\n};\n\nwindow.exports.preload = function(callback) {\n    var modules = [\n        ['view'],\n        ['json', 'xml', 'protobuf', 'hdf5', 'grapher', 'browser'],\n        ['base', 'text', 'flatbuffers', 'flexbuffers', 'zip',  'tar', 'python']\n    ];\n    var next = function() {\n        if (modules.length === 0) {\n            callback();\n        } else {\n            var ids = modules.pop();\n            /* eslint-disable no-loop-func */\n            var resolved = ids.length;\n            for (var i = 0; i < ids.length; i++) {\n                window.exports.require(ids[i], function(module, error) {\n                    if (error) {\n                        callback(null, error);\n                    } else {\n                        resolved--;\n                        if (resolved === 0) {\n                            next();\n                        }\n                    }\n                });\n            }\n            /* eslint-enable no-loop-func */\n        }\n    };\n    next();\n};\n\nwindow.exports.terminate = function(message) {\n    var document = window.document;\n    document.getElementById('message-text').innerText = message;\n    var button = document.getElementById('message-button');\n    button.style.display = 'none';\n    button.onclick = null;\n    document.body.setAttribute('class', 'welcome message');\n    if (window.__view__) {\n        /* eslint-disable no-unused-vars */\n        try {\n            window.__view__.show('welcome message');\n        } catch (error) {\n            // continue regardless of error\n        }\n        /* eslint-enable no-unused-vars */\n    }\n};\n\nwindow.addEventListener('error', function (event) {\n    var error = event instanceof window.ErrorEvent && event.error && event.error instanceof Error ? event.error : new Error(event && event.message ? event.message : JSON.stringify(event));\n    window.exports.terminate(error.message);\n});\n\nwindow.addEventListener('load', function() {\n    if (typeof Symbol !== 'function' || typeof Symbol.asyncIterator !== 'symbol' ||\n        typeof BigInt !== 'function' || typeof BigInt.asIntN !== 'function' || typeof BigInt.asUintN !== 'function' || typeof DataView.prototype.getBigInt64 !== 'function') {\n        throw new Error('Please update your browser to use this application.');\n    }\n    var ua = window.navigator.userAgent;\n    var chrome = ua.match(/Chrom(e|ium)\\/([0-9]+)\\./);\n    var safari = ua.match(/Version\\/(\\d+)\\.(\\d+).*Safari/);\n    var firefox = ua.match(/Firefox\\/([0-9]+)\\./);\n    if ((Array.isArray(chrome) && parseInt(chrome[2], 10) < 86) ||\n        (Array.isArray(safari) && (parseInt(safari[1], 10) < 16 || (parseInt(safari[1], 10) === 16 && parseInt(safari[2], 10) < 4))) ||\n        (Array.isArray(firefox) && parseInt(firefox[1], 10) < 114)) {\n        throw new Error('Please update your browser to use this application.');\n    }\n    window.exports.preload(function(value, error) {\n        if (error) {\n            window.exports.terminate(error.message);\n        } else {\n            var host = new window.exports.browser.Host();\n            window.__view__ = new window.exports.view.View(host);\n            window.__view__.start();\n        }\n    });\n});\n"
  },
  {
    "path": "source/json.js",
    "content": "\nimport * as text from './text.js';\n\nconst json = {};\nconst bson = {};\n\njson.TextReader = class {\n\n    static open(data) {\n        const decoder = text.Decoder.open(data);\n        const position = decoder.position;\n        let state = '';\n        for (let i = 0; i < 0x1000; i++) {\n            const c = decoder.decode();\n            if (state === 'match') {\n                break;\n            }\n            if (c === undefined || c === '\\0') {\n                if (state === '') {\n                    return null;\n                }\n                break;\n            }\n            if (c <= ' ') {\n                if (c !== ' ' && c !== '\\n' && c !== '\\r' && c !== '\\t') {\n                    return null;\n                }\n                continue;\n            }\n            switch (state) {\n                case '':\n                    if (c === '{') {\n                        state = '{}';\n                    } else if (c === '[') {\n                        state = '[]';\n                    } else {\n                        return null;\n                    }\n                    break;\n                case '[]':\n                    if (c !== '\"' && c !== '-' && c !== '+' && c !== '{' && c !== '[' && c !== ']' && (c < '0' || c > '9')) {\n                        return null;\n                    }\n                    state = 'match';\n                    break;\n                case '{}':\n                    if (c !== '\"' && c !== '}') {\n                        return null;\n                    }\n                    state = 'match';\n                    break;\n                default:\n                    break;\n            }\n        }\n        decoder.position = position;\n        return new json.TextReader(decoder);\n    }\n\n    constructor(decoder) {\n        this._decoder = decoder;\n        this._start = decoder.position;\n        this._escape = { '\"': '\"', '\\\\': '\\\\', '/': '/', b: '\\b', f: '\\f', n: '\\n', r: '\\r', t: '\\t' };\n    }\n\n    read() {\n        const stack = [];\n        this._decoder.position = this._start;\n        this._position = this._start;\n        this._char = this._decoder.decode();\n        this._whitespace();\n        let obj = null;\n        let first = true;\n        for (;;) {\n            if (Array.isArray(obj)) {\n                this._whitespace();\n                let c = this._char;\n                if (c === ']') {\n                    this._next();\n                    this._whitespace();\n                    if (stack.length > 0) {\n                        obj = stack.pop();\n                        first = false;\n                        continue;\n                    }\n                    if (this._char !== undefined) {\n                        this._unexpected();\n                    }\n                    return obj;\n                }\n                if (!first) {\n                    if (this._char !== ',') {\n                        this._unexpected();\n                    }\n                    this._next();\n                    this._whitespace();\n                    c = this._char;\n                }\n                first = false;\n                switch (c) {\n                    case '{': {\n                        this._next();\n                        stack.push(obj);\n                        const item = {};\n                        obj.push(item);\n                        obj = item;\n                        first = true;\n                        break;\n                    }\n                    case '[': {\n                        this._next();\n                        stack.push(obj);\n                        const item = [];\n                        obj.push(item);\n                        obj = item;\n                        first = true;\n                        break;\n                    }\n                    default: {\n                        obj.push(c === '\"' ? this._string() : this._literal());\n                        break;\n                    }\n                }\n            } else if (obj instanceof Object) {\n                this._whitespace();\n                let c = this._char;\n                if (c === '}') {\n                    this._next();\n                    this._whitespace();\n                    if (stack.length > 0) {\n                        obj = stack.pop();\n                        first = false;\n                        continue;\n                    }\n                    if (this._char !== undefined) {\n                        this._unexpected();\n                    }\n                    return obj;\n                }\n                if (!first) {\n                    if (this._char !== ',') {\n                        this._unexpected();\n                    }\n                    this._next();\n                    this._whitespace();\n                    c = this._char;\n                }\n                first = false;\n                if (c === '\"') {\n                    const key = this._string();\n                    switch (key) {\n                        case '__proto__':\n                            throw new json.Error(`Invalid key '${key}' ${this._location()}`);\n                        default:\n                            break;\n                    }\n                    this._whitespace();\n                    if (this._char !== ':') {\n                        this._unexpected();\n                    }\n                    this._next();\n                    this._whitespace();\n                    c = this._char;\n                    switch (c) {\n                        case '{': {\n                            this._next();\n                            stack.push(obj);\n                            const value = {};\n                            obj[key] = value;\n                            obj = value;\n                            first = true;\n                            break;\n                        }\n                        case '[': {\n                            this._next();\n                            stack.push(obj);\n                            const value = [];\n                            obj[key] = value;\n                            obj = value;\n                            first = true;\n                            break;\n                        }\n                        default: {\n                            obj[key] = c === '\"' ? this._string() : this._literal();\n                            break;\n                        }\n                    }\n                    this._whitespace();\n                    continue;\n                }\n                this._unexpected();\n            } else {\n                const c = this._char;\n                switch (c) {\n                    case '{': {\n                        this._next();\n                        this._whitespace();\n                        obj = {};\n                        first = true;\n                        break;\n                    }\n                    case '[': {\n                        this._next();\n                        this._whitespace();\n                        obj = [];\n                        first = true;\n                        break;\n                    }\n                    default: {\n                        let value = null;\n                        if (c === '\"') {\n                            value = this._string();\n                        } else if (c >= '0' && c <= '9') {\n                            value = this._number();\n                        } else {\n                            value = this._literal();\n                        }\n                        this._whitespace();\n                        if (this._char !== undefined) {\n                            this._unexpected();\n                        }\n                        return value;\n                    }\n                }\n            }\n        }\n    }\n\n    _next() {\n        if (this._char === undefined) {\n            this._unexpected();\n        }\n        this._position = this._decoder.position;\n        this._char = this._decoder.decode();\n    }\n\n    _whitespace() {\n        while (this._char === ' ' || this._char === '\\n' || this._char === '\\r' || this._char === '\\t') {\n            this._next();\n        }\n    }\n\n    _literal() {\n        const c = this._char;\n        if (c >= '0' && c <= '9') {\n            return this._number();\n        }\n        switch (c) {\n            case 't': this._expect('true'); return true;\n            case 'f': this._expect('false'); return false;\n            case 'n': this._expect('null'); return null;\n            case 'N': this._expect('NaN'); return NaN;\n            case 'I': this._expect('Infinity'); return Infinity;\n            case '-': return this._number();\n            default: this._unexpected();\n        }\n        return null;\n    }\n\n    _number() {\n        let value = '';\n        if (this._char === '-') {\n            value = '-';\n            this._next();\n        }\n        if (this._char === 'I') {\n            this._expect('Infinity');\n            return -Infinity;\n        }\n        const c = this._char;\n        if (c < '0' || c > '9') {\n            this._unexpected();\n        }\n        value += c;\n        this._next();\n        if (c === '0') {\n            const n = this._char;\n            if (n >= '0' && n <= '9') {\n                this._unexpected();\n            }\n        }\n        while (this._char >= '0' && this._char <= '9') {\n            value += this._char;\n            this._next();\n        }\n        if (this._char === '.') {\n            value += '.';\n            this._next();\n            const n = this._char;\n            if (n < '0' || n > '9') {\n                this._unexpected();\n            }\n            while (this._char >= '0' && this._char <= '9') {\n                value += this._char;\n                this._next();\n            }\n        }\n        if (this._char === 'e' || this._char === 'E') {\n            value += this._char;\n            this._next();\n            const s = this._char;\n            if (s === '-' || s === '+') {\n                value += this._char;\n                this._next();\n            }\n            const c = this._char;\n            if (c < '0' || c > '9') {\n                this._unexpected();\n            }\n            value += this._char;\n            this._next();\n            while (this._char >= '0' && this._char <= '9') {\n                value += this._char;\n                this._next();\n            }\n        }\n        return Number(value);\n    }\n\n    _string() {\n        let value = '';\n        this._next();\n        while (this._char !== '\"') {\n            if (this._char === '\\\\') {\n                this._next();\n                if (this._char === 'u') {\n                    this._next();\n                    let uffff = 0;\n                    for (let i = 0; i < 4; i ++) {\n                        const hex = parseInt(this._char, 16);\n                        if (!isFinite(hex)) {\n                            this._unexpected();\n                        }\n                        this._next();\n                        uffff = uffff * 16 + hex;\n                    }\n                    value += String.fromCharCode(uffff);\n                } else if (this._escape[this._char]) {\n                    value += this._escape[this._char];\n                    this._next();\n                } else {\n                    this._unexpected();\n                }\n            } else if (this._char < ' ') {\n                this._unexpected();\n            } else {\n                value += this._char;\n                this._next();\n            }\n        }\n        this._next();\n        return value;\n    }\n\n    _expect(value) {\n        for (let i = 0; i < value.length; i++) {\n            if (value[i] !== this._char) {\n                this._unexpected();\n            }\n            this._next();\n        }\n    }\n\n    _unexpected() {\n        let c = this._char;\n        if (c === undefined) {\n            throw new json.Error('Unexpected end of JSON input.');\n        } else if (c === '\"') {\n            c = 'string';\n        } else if ((c >= '0' && c <= '9') || c === '-') {\n            c = 'number';\n        } else {\n            if (c < ' ' || c > '\\x7F') {\n                const name = Object.keys(this._escape).filter((key) => this._escape[key] === c);\n                c = (name.length === 1) ? `\\\\${name}` : `\\\\u${(`000${c.charCodeAt(0).toString(16)}`).slice(-4)}`;\n            }\n            c = `token '${c}'`;\n        }\n        throw new json.Error(`Unexpected ${c} ${this._location()}`);\n    }\n\n    _location() {\n        let line = 1;\n        let column = 1;\n        this._decoder.position = this._start;\n        let c = '';\n        do {\n            if (this._decoder.position === this._position) {\n                return `at ${line}:${column}.`;\n            }\n            c = this._decoder.decode();\n            if (c === '\\n') {\n                line++;\n                column = 1;\n            } else {\n                column++;\n            }\n        }\n        while (c !== undefined);\n        return `at ${line}:${column}.`;\n    }\n};\n\njson.BinaryReader = class {\n\n    static open(data) {\n        const length = data.length;\n        const buffer = data instanceof Uint8Array ? data : data.peek(Math.min(data.length, 8));\n        const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n        if (buffer.length >= 4 && view.getInt32(0, true) === length) {\n            return new json.BinaryReader(data, 'bson');\n        }\n        const [signature] = buffer;\n        if (signature === 0x7B || signature === 0x5B) {\n            return new json.BinaryReader(data, 'ubj');\n        }\n        return null;\n    }\n\n    constructor(data, format) {\n        this._buffer = data instanceof Uint8Array ? data : data.peek();\n        this._format = format;\n    }\n\n    read() {\n        switch (this._format) {\n            case 'bson':\n                return this._readBson();\n            case 'ubj':\n                return this._readUbj();\n            default:\n                throw new json.Error(`Unsupported binary JSON format '${this._format}'.`);\n        }\n    }\n\n    _readBson() {\n        const buffer = this._buffer;\n        const length = buffer.length;\n        const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n        const asciiDecoder = new TextDecoder('ascii');\n        const utf8Decoder = new TextDecoder('utf-8');\n        let position = 0;\n        const skip = (offset) => {\n            position += offset;\n            if (position > length) {\n                throw new bson.Error(`Expected ${position + length} more bytes. The file might be corrupted. Unexpected end of file.`);\n            }\n        };\n        const header = () => {\n            const start = position;\n            skip(4);\n            const size = view.getInt32(start, 4);\n            if (size < 5 || start + size > length || buffer[start + size - 1] !== 0x00) {\n                throw new bson.Error('Invalid file size.');\n            }\n        };\n        header();\n        const stack = [];\n        let obj = {};\n        for (;;) {\n            skip(1);\n            const type = buffer[position - 1];\n            if (type === 0x00) {\n                if (stack.length === 0) {\n                    break;\n                }\n                obj = stack.pop();\n                continue;\n            }\n            const start = position;\n            position = buffer.indexOf(0x00, start);\n            if (position === -1) {\n                throw new bson.Error('Missing string terminator.');\n            }\n            position += 1;\n            const key = asciiDecoder.decode(buffer.subarray(start, position - 1));\n            let value = null;\n            switch (type) {\n                case 0x01: { // float64\n                    const start = position;\n                    skip(8);\n                    value = view.getFloat64(start, true);\n                    break;\n                }\n                case 0x02: { // string\n                    skip(4);\n                    const size = view.getInt32(position - 4, true);\n                    const start = position;\n                    skip(size);\n                    value = utf8Decoder.decode(buffer.subarray(start, position - 1));\n                    if (buffer[position - 1] !== 0) {\n                        throw new bson.Error('String missing terminal 0.');\n                    }\n                    break;\n                }\n                case 0x03: { // object\n                    header();\n                    value = {};\n                    break;\n                }\n                case 0x04: { // array\n                    header();\n                    value = [];\n                    break;\n                }\n                case 0x05: { // bytes\n                    const start = position;\n                    skip(5);\n                    const size = view.getInt32(start, true);\n                    const subtype = buffer[start + 4];\n                    if (subtype !== 0x00) {\n                        throw new bson.Error(`Unsupported binary subtype '${subtype}'.`);\n                    }\n                    skip(size);\n                    value = buffer.subarray(start + 5, position);\n                    break;\n                }\n                case 0x08: { // boolean\n                    skip(1);\n                    value = buffer[position - 1];\n                    if (value > 1) {\n                        throw new bson.Error(`Invalid boolean value '${value}'.`);\n                    }\n                    value = value === 1 ? true : false;\n                    break;\n                }\n                case 0x0A:\n                    value = null;\n                    break;\n                case 0x10: {\n                    const start = position;\n                    skip(4);\n                    value = view.getInt32(start, true);\n                    break;\n                }\n                case 0x11: { // uint64\n                    const start = position;\n                    skip(8);\n                    value = view.getBigUint64(start, true);\n                    break;\n                }\n                case 0x12: { // int64\n                    const start = position;\n                    skip(8);\n                    value = view.getBigInt64(start, true);\n                    break;\n                }\n                default: {\n                    throw new bson.Error(`Unsupported value type '${type}'.`);\n                }\n            }\n            if (Array.isArray(obj))  {\n                if (obj.length !== parseInt(key, 10)) {\n                    throw new bson.Error(`Invalid array index '${key}'.`);\n                }\n                obj.push(value);\n            } else {\n                switch (key) {\n                    case '__proto__':\n                    case 'constructor':\n                    case 'prototype':\n                        throw new bson.Error(`Invalid key '${key}' at ${position}'.`);\n                    default:\n                        break;\n                }\n                obj[key] = value;\n            }\n            if (type === 0x03 || type === 0x04) {\n                stack.push(obj);\n                obj = value;\n            }\n        }\n        if (position !== length) {\n            throw new bson.Error(`Unexpected data at '${position}'.`);\n        }\n        return obj;\n    }\n\n    _readUbj() {\n        throw new json.Error('Unsupported JSON UBJ data.');\n    }\n};\n\njson.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'JSON Error';\n    }\n};\n\nbson.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'BSON Error';\n    }\n};\n\nexport const TextReader = json.TextReader;\nexport const BinaryReader = json.BinaryReader;\n"
  },
  {
    "path": "source/kann-metadata.json",
    "content": "[\n    {\n        \"name\": \"Transpose\",\n        \"category\": \"Transform\"\n    },\n    {\n        \"name\": \"Substraction\",\n        \"category\": \"Transform\"\n    },\n    {\n        \"name\": \"LayerNorm\",\n        \"category\": \"Normalization\"\n    },\n    {\n        \"name\": \"ConvolutionCV2\",\n        \"category\": \"Layer\"\n    },\n    {\n        \"name\": \"ReLU\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"Resize\",\n        \"category\": \"Shape\"\n    },\n    {\n        \"name\": \"ResizeNearestAsymFloor\",\n        \"category\": \"Shape\"\n    },\n    {\n        \"name\": \"Exp\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"Mish\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"Stddev\",\n        \"category\": \"Normalization\"\n    },\n    {\n        \"name\": \"AvgPooling\",\n        \"category\": \"Pool\"\n    },\n    {\n        \"name\": \"HardSigmoid\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"SeLU\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"LRN\",\n        \"category\": \"Normalization\"\n    },\n    {\n        \"name\": \"GeLU\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"Reshape\",\n        \"category\": \"Shape\"\n    },\n    {\n        \"name\": \"Tanh\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"MaxPooling\",\n        \"category\": \"Pool\"\n    },\n    {\n        \"name\": \"DepthwiseConvolution\",\n        \"category\": \"Layer\"\n    },\n    {\n        \"name\": \"Softmax\",\n        \"category\": \"Activation\"\n    },\n    {\n        \"name\": \"SiLU\",\n        \"category\": \"Activation\"\n    }\n]"
  },
  {
    "path": "source/kann-schema.js",
    "content": "\nexport const kann = {};\n\nkann.Model = class Model {\n\n    static identifier(reader) {\n        return reader.identifier === 'KaNN';\n    }\n\n    static create(reader) {\n        return kann.Model.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new kann.Model();\n        $.graph = reader.tables(position, 4, kann.Graph);\n        return $;\n    }\n};\n\nkann.Graph = class Graph {\n\n    static decode(reader, position) {\n        const $ = new kann.Graph();\n        $.arcs = reader.tables(position, 4, kann.Arc);\n        $.nodes = reader.tables(position, 6, kann.Node);\n        $.inputs = reader.strings_(position, 8);\n        $.outputs = reader.strings_(position, 10);\n        return $;\n    }\n};\n\nkann.Arc = class Arc {\n\n    static decode(reader, position) {\n        const $ = new kann.Arc();\n        $.name = reader.string_(position, 4, null);\n        $.type = reader.string_(position, 6, null);\n        $.attributes = reader.tables(position, 8, kann.Attribute);\n        return $;\n    }\n};\n\nkann.Node = class Node {\n\n    static decode(reader, position) {\n        const $ = new kann.Node();\n        $.name = reader.string_(position, 4, null);\n        $.type = reader.string_(position, 6, null);\n        $.inputs = reader.strings_(position, 8);\n        $.outputs = reader.strings_(position, 10);\n        $.attributes = reader.tables(position, 12, kann.Attribute);\n        $.tensor = reader.table(position, 14, kann.Param);\n        $.relu = reader.bool_(position, 16, false);\n        $.params = reader.tables(position, 18, kann.Param);\n        return $;\n    }\n};\n\nkann.Param = class Param {\n\n    static decode(reader, position) {\n        const $ = new kann.Param();\n        $.name = reader.string_(position, 4, null);\n        $.type = reader.string_(position, 6, null);\n        $.shape = reader.array(position, 8, Int32Array);\n        $.value = reader.table(position, 10, kann.Data);\n        $.scale = reader.table(position, 12, kann.Data);\n        $.zero_point = reader.table(position, 14, kann.Data);\n        return $;\n    }\n};\n\nkann.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new kann.Attribute();\n        $.name = reader.string_(position, 4, null);\n        $.type = reader.string_(position, 6, null);\n        $.value = reader.table(position, 8, kann.Data);\n        $.attributes = reader.tables(position, 10, kann.Attribute);\n        return $;\n    }\n};\n\nkann.Data = class Data {\n\n    static decode(reader, position) {\n        const $ = new kann.Data();\n        $.type = reader.string_(position, 4, null);\n        $.value_string = reader.string_(position, 6, null);\n        $.value_float = reader.float64_(position, 8, 0);\n        $.value_int = reader.int64_(position, 10, 0n);\n        $.value_uint = reader.uint64_(position, 12, 0n);\n        $.list_string = reader.strings_(position, 14);\n        $.list_float = reader.array(position, 16, Float64Array);\n        $.list_int = reader.int64s_(position, 18);\n        $.list_uint = reader.uint64s_(position, 20);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/kann.js",
    "content": "\nconst kann = {};\n\nkann.ModelFactory = class {\n\n    async match(context) {\n        const reader = await context.peek('flatbuffers.binary');\n        if (reader && reader.identifier === 'KaNN') {\n            return context.set('kann.flatbuffers', reader);\n        }\n        return null;\n    }\n\n    async open(context) {\n        kann.schema = await context.require('./kann-schema');\n        kann.schema = kann.schema.kann;\n        let model = null;\n        switch (context.type) {\n            case 'kann.flatbuffers': {\n                try {\n                    const reader = context.value;\n                    model = kann.schema.Model.create(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new kann.Error(`File format is not kann.Model (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            default: {\n                throw new kann.Error(`Unsupported KaNN format '${context.type}'.`);\n            }\n        }\n        const metadata = await context.metadata('kann-metadata.json');\n        return new kann.Model(metadata, model, context.identifier);\n    }\n};\n\nkann.Model = class {\n\n    constructor(metadata, model, identifier) {\n        this.format = 'KaNN';\n        this.name = identifier;\n        this.modules = model.graph.map((graph) => new kann.Graph(metadata, graph));\n    }\n};\n\nkann.Graph = class {\n\n    constructor(metadata, graph) {\n        const arcs = new Map();\n        for (const arc of graph.arcs) {\n            arcs.set(arc.name, new kann.Value(arc.name, arc.type, null));\n        }\n        this.nodes = graph.nodes.map((node) => new kann.Node(metadata, node, arcs));\n        this.inputs = graph.inputs.map((input) => new kann.Argument(input, [arcs.get(input)]));\n        this.outputs = graph.outputs.map((output) => new kann.Argument(output, [arcs.get(output)]));\n    }\n};\n\nkann.Node = class {\n\n    constructor(metadata, node, arcs) {\n        this.type = metadata.type(node.type);\n        this.name = node.name;\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const extractData = (value) => {\n            switch (value.type) {\n                case 'int': case 'int8': case 'int16': case 'int32': case 'int64': return value.value_int;\n                case 'uint': case 'uint8': case 'uint16': case 'uint32': case 'uint64': return value.value_uint;\n                case 'float': case 'float16': case 'float32': case 'float64': return value.value_float;\n                case 'string': return value.value_string;\n                case 'int[]': case 'int8[]': case 'int16[]': case 'int32[]': case 'int64[]': return Array.from(value.list_int);\n                case 'uint[]': case 'uint8[]': case 'uint16[]': case 'uint32[]': case 'uint64[]': return Array.from(value.list_uint);\n                case 'float[]': case 'float16[]': case 'float32[]': case 'float64[]': return Array.from(value.list_float);\n                case 'string[]': return Array.from(value.list_string);\n                default: throw new kann.Error(`Unsupported data type '${value.type}'.`);\n            }\n        };\n        const getAttributeValue = (attribute) => {\n            if (attribute.type === 'attributes') {\n                const obj = {};\n                for (const attr of attribute.attributes) {\n                    obj[attr.name] = getAttributeValue(attr);\n                }\n                return obj;\n            }\n            if (attribute.value !== null) {\n                return extractData(attribute.value);\n            }\n            throw new kann.Error(`${attribute.name} doesn't have a value.`);\n        };\n        if (Array.isArray(node.attributes) && node.attributes.length > 0) {\n            for (const attr of node.attributes) {\n                let value = attr.type ? getAttributeValue(attr) : attr;\n                value = Array.isArray(value) ? value : [value];\n                const type = value.type === 'attributes' ? null : attr.type || null;\n                const attribute = new kann.Argument(attr.name, value, type);\n                this.attributes.push(attribute);\n            }\n        }\n        if (Array.isArray(node.inputs) && node.inputs.length > 0) {\n            const name = node.inputs.length > 1 ? 'inputs' : 'input';\n            const argument = new kann.Argument(name, node.inputs.map((input) => arcs.get(input)));\n            this.inputs.push(argument);\n        }\n        if (Array.isArray(node.outputs) && node.outputs.length > 0) {\n            const name = node.outputs.length > 1 ? 'outputs' : 'output';\n            const argument = new kann.Argument(name, node.outputs.map((output) => arcs.get(output)));\n            this.outputs.push(argument);\n        }\n        if (Array.isArray(node.params) && node.params.length > 0) {\n            for (const param of node.params) {\n                const type = new kann.TensorType(param.type, param.shape);\n                const data = param.value ? extractData(param.value) : null;\n                const quantization = param.scale && param.zero_point ? {\n                    type: 'linear',\n                    scale: extractData(param.scale),\n                    offset: extractData(param.zero_point)\n                } : null;\n                const tensor = new kann.Tensor(param.name, type, data, quantization);\n                const value = new kann.Value('', type, tensor);\n                const argument = new kann.Argument(param.name, [value]);\n                this.inputs.push(argument);\n            }\n        }\n        if (node.relu) {\n            const relu = { type: 'ReLU', name: `${node.name}/relu`, params: [] };\n            this.chain = [new kann.Node(metadata, relu, arcs)];\n        }\n    }\n};\n\nkann.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nkann.Value = class {\n\n    constructor(name, type, initializer) {\n        this.name = name;\n        this.type = type;\n        this.initializer = initializer;\n        this.quantization = initializer && initializer.quantization ? initializer.quantization : null;\n    }\n};\n\nkann.Tensor = class {\n\n    constructor(name, type, values, quantization) {\n        this.name = name;\n        this.type = type;\n        this.encoding = Array.isArray(values) ? '|' : '<';\n        this.values = values;\n        this.quantization = quantization ? quantization : null;\n    }\n};\n\nkann.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = new kann.TensorShape(shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nkann.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.from(dimensions);\n    }\n\n    toString() {\n        if (Array.isArray(this.dimensions) && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nkann.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading KaNN model.';\n    }\n};\n\nexport const ModelFactory = kann.ModelFactory;"
  },
  {
    "path": "source/keras-metadata.json",
    "content": "[\n  {\n    \"name\": \"Activation\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Applies an activation function to an output.\",\n    \"attributes\": [\n      {\n        \"description\": \"Activation function. It could be a callable, or the name of\\n        an activation from the `keras.activations` namespace.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments, such as `name` and `dtype`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the batch axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> layer = keras.layers.Activation('relu')\\n>>> layer(np.array([-3.0, -1.0, 0.0, 2.0]))\\n[0.0, 0.0, 0.0, 2.0]\\n>>> layer = keras.layers.Activation(keras.activations.relu)\\n>>> layer(np.array([-3.0, -1.0, 0.0, 2.0]))\\n[0.0, 0.0, 0.0, 2.0]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ActivityRegularization\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Layer that applies an update to the cost function based input activity.\",\n    \"attributes\": [\n      {\n        \"description\": \"L1 regularization factor (positive float).\",\n        \"name\": \"l1\"\n      },\n      {\n        \"description\": \"L2 regularization factor (positive float).\",\n        \"name\": \"l2\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the samples axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as input.\",\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Add\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Performs elementwise addition operation.\\n\\nIt takes as input a list of tensors, all of the same shape,\\nand returns a single tensor (also of the same shape).\",\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 3, 4)\\n>>> x1 = np.random.rand(*input_shape)\\n>>> x2 = np.random.rand(*input_shape)\\n>>> y = keras.layers.Add()([x1, x2])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> input1 = keras.layers.Input(shape=(16,))\\n>>> x1 = keras.layers.Dense(8, activation='relu')(input1)\\n>>> input2 = keras.layers.Input(shape=(32,))\\n>>> x2 = keras.layers.Dense(8, activation='relu')(input2)\\n>>> # equivalent to `added = keras.layers.add([x1, x2])`\\n>>> added = keras.layers.Add()([x1, x2])\\n>>> out = keras.layers.Dense(4)(added)\\n>>> model = keras.models.Model(inputs=[input1, input2], outputs=out)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Attention\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Attention\",\n    \"description\": \"Dot-product attention layer, a.k.a. Luong-style attention.\\n\\nInputs are a list with 2 or 3 elements:\\n1. A `query` tensor of shape `(batch_size, Tq, dim)`.\\n2. A `value` tensor of shape `(batch_size, Tv, dim)`.\\n3. A optional `key` tensor of shape `(batch_size, Tv, dim)`. If none\\n    supplied, `value` will be used as a `key`.\\n\\nThe calculation follows the steps:\\n1. Calculate attention scores using `query` and `key` with shape\\n    `(batch_size, Tq, Tv)`.\\n2. Use scores to calculate a softmax distribution with shape\\n    `(batch_size, Tq, Tv)`.\\n3. Use the softmax distribution to create a linear combination of `value`\\n    with shape `(batch_size, Tq, dim)`.\",\n    \"attributes\": [\n      {\n        \"description\": \"If `True`, will create a scalar variable to scale the\\n        attention scores.\",\n        \"name\": \"use_scale\"\n      },\n      {\n        \"description\": \"Boolean. Set to `True` for decoder self-attention. Adds a mask\\n    such that position `i` cannot attend to positions `j > i`. This prevents\\n    the flow of information from the future towards the past.  Defaults to\\n    `False`.\",\n        \"name\": \"causal\"\n      },\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        attention scores. Defaults to `0.0`.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"description\": \"List of the following tensors:\\n        - `query`: Query tensor of shape `(batch_size, Tq, dim)`.\\n        - `value`: Value tensor of shape `(batch_size, Tv, dim)`.\\n        - `key`: Optional key tensor of shape `(batch_size, Tv, dim)`. If\\n            not given, will use `value` for both `key` and `value`, which is\\n            the most common case.\",\n        \"name\": \"inputs\"\n      },\n      {\n        \"description\": \"List of the following tensors:\\n        - `query_mask`: A boolean mask tensor of shape `(batch_size, Tq)`.\\n            If given, the output will be zero at the positions where\\n            `mask==False`.\\n        - `value_mask`: A boolean mask tensor of shape `(batch_size, Tv)`.\\n            If given, will apply the mask such that values at positions\\n             where `mask==False` do not contribute to the result.\",\n        \"name\": \"mask\"\n      },\n      {\n        \"description\": \"bool, it `True`, returns the attention scores\\n        (after masking and softmax) as an additional output argument.\",\n        \"name\": \"return_attention_scores\"\n      },\n      {\n        \"description\": \"Python boolean indicating whether the layer should behave in\\n        training mode (adding dropout) or in inference mode (no dropout).\",\n        \"name\": \"training\"\n      },\n      {\n        \"name\": \"score_mode\",\n        \"description\": \"Function to use to compute attention scores, one of\\n        `{\\\"dot\\\", \\\"concat\\\"}`. `\\\"dot\\\"` refers to the dot product between the\\n        query and key vectors. `\\\"concat\\\"` refers to the hyperbolic tangent\\n        of the concatenation of the `query` and `key` vectors.\"\n      },\n      {\n        \"name\": \"use_causal_mask\",\n        \"description\": \"Boolean. Set to `True` for decoder self-attention. Adds\\n        a mask such that position `i` cannot attend to positions `j > i`.\\n        This prevents the flow of information from the future towards the\\n        past. Defaults to `False`.\\n\\nOutput:\\n    Attention outputs of shape `(batch_size, Tq, dim)`.\\n    (Optional) Attention scores after masking and softmax with shape\\n        `(batch_size, Tq, Tv)`.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"A Python integer to use as random seed in case of `dropout`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"query\",\n        \"type\": \"Tensor[]\"\n      },\n      {\n        \"name\": \"value\",\n        \"type\": \"Tensor[]\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Average\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Tensor\",\n    \"description\": \"Averages a list of inputs element-wise..\\n\\nIt takes as input a list of tensors, all of the same shape,\\nand returns a single tensor (also of the same shape).\",\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 3, 4)\\n>>> x1 = np.random.rand(*input_shape)\\n>>> x2 = np.random.rand(*input_shape)\\n>>> y = keras.layers.Average()([x1, x2])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> input1 = keras.layers.Input(shape=(16,))\\n>>> x1 = keras.layers.Dense(8, activation='relu')(input1)\\n>>> input2 = keras.layers.Input(shape=(32,))\\n>>> x2 = keras.layers.Dense(8, activation='relu')(input2)\\n>>> # equivalent to `y = keras.layers.average([x1, x2])`\\n>>> y = keras.layers.Average()([x1, x2])\\n>>> out = keras.layers.Dense(4)(y)\\n>>> model = keras.models.Model(inputs=[input1, input2], outputs=out)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AveragePooling1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Average pooling for temporal data.\\n\\nDownsamples the input representation by taking the average value over the\\nwindow defined by `pool_size`. The window is shifted by `strides`.  The\\nresulting output when using \\\"valid\\\" padding option has a shape of:\\n`output_shape = (input_shape - pool_size + 1) / strides)`\\n\\nThe resulting output shape when using the \\\"same\\\" padding option is:\\n`output_shape = input_shape / strides`\",\n    \"attributes\": [\n      {\n        \"description\": \"int, size of the max pooling window.\",\n        \"name\": \"pool_size\"\n      },\n      {\n        \"description\": \"int or None. Specifies how much the pooling window moves\\n        for each pooling step. If None, it will default to `pool_size`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    3D tensor with shape `(batch_size, steps, features)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    3D tensor with shape `(batch_size, features, steps)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    3D tensor with shape `(batch_size, downsampled_steps, features)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    3D tensor with shape `(batch_size, features, downsampled_steps)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"summary\": \"`strides=1` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([1., 2., 3., 4., 5.])\\n>>> x = np.reshape(x, [1, 5, 1])\\n>>> avg_pool_1d = keras.layers.AveragePooling1D(pool_size=2,\\n...    strides=1, padding=\\\"valid\\\")\\n>>> avg_pool_1d(x)\"\n      },\n      {\n        \"summary\": \"`strides=2` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([1., 2., 3., 4., 5.])\\n>>> x = np.reshape(x, [1, 5, 1])\\n>>> avg_pool_1d = keras.layers.AveragePooling1D(pool_size=2,\\n...    strides=2, padding=\\\"valid\\\")\\n>>> avg_pool_1d(x)\"\n      },\n      {\n        \"summary\": \"`strides=1` and `padding=\\\"same\\\"`:\",\n        \"code\": \">>> x = np.array([1., 2., 3., 4., 5.])\\n>>> x = np.reshape(x, [1, 5, 1])\\n>>> avg_pool_1d = keras.layers.AveragePooling1D(pool_size=2,\\n...    strides=1, padding=\\\"same\\\")\\n>>> avg_pool_1d(x)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AveragePooling2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Average pooling operation for 2D spatial data.\\n\\nDownsamples the input along its spatial dimensions (height and width)\\nby taking the average value over an input window\\n(of size defined by `pool_size`) for each channel of the input.\\nThe window is shifted by `strides` along each dimension.\\n\\nThe resulting output when using the `\\\"valid\\\"` padding option has a spatial\\nshape (number of rows or columns) of:\\n`output_shape = math.floor((input_shape - pool_size) / strides) + 1`\\n(when `input_shape >= pool_size`)\\n\\nThe resulting output shape when using the `\\\"same\\\"` padding option is:\\n`output_shape = input_shape`\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, channels, height, width)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"int or tuple of 2 integers, factors by which to downscale\\n        (dim1, dim2). If only one integer is specified, the same\\n        window length will be used for all dimensions.\",\n        \"name\": \"pool_size\"\n      },\n      {\n        \"description\": \"int or tuple of 2 integers, or None. Strides values. If None,\\n        it will default to `pool_size`. If only one int is specified, the\\n        same stride size will be used for all dimensions.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    4D tensor with shape `(batch_size, height, width, channels)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    4D tensor with shape `(batch_size, channels, height, width)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    4D tensor with shape\\n    `(batch_size, pooled_height, pooled_width, channels)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    4D tensor with shape\\n    `(batch_size, channels, pooled_height, pooled_width)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"summary\": \"`strides=(1, 1)` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([[1., 2., 3.],\\n...               [4., 5., 6.],\\n...               [7., 8., 9.]])\\n>>> x = np.reshape(x, [1, 3, 3, 1])\\n>>> avg_pool_2d = keras.layers.AveragePooling2D(pool_size=(2, 2),\\n...    strides=(1, 1), padding=\\\"valid\\\")\\n>>> avg_pool_2d(x)\"\n      },\n      {\n        \"summary\": \"`strides=(2, 2)` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([[1., 2., 3., 4.],\\n...              [5., 6., 7., 8.],\\n...              [9., 10., 11., 12.]])\\n>>> x = np.reshape(x, [1, 3, 4, 1])\\n>>> avg_pool_2d = keras.layers.AveragePooling2D(pool_size=(2, 2),\\n...    strides=(2, 2), padding=\\\"valid\\\")\\n>>> avg_pool_2d(x)\"\n      },\n      {\n        \"summary\": \"`stride=(1, 1)` and `padding=\\\"same\\\"`:\",\n        \"code\": \">>> x = np.array([[1., 2., 3.],\\n...                  [4., 5., 6.],\\n...                  [7., 8., 9.]])\\n>>> x = np.reshape(x, [1, 3, 3, 1])\\n>>> avg_pool_2d = keras.layers.AveragePooling2D(pool_size=(2, 2),\\n...    strides=(1, 1), padding=\\\"same\\\")\\n>>> avg_pool_2d(x)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AveragePooling3D\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Average pooling operation for 3D data (spatial or spatio-temporal).\\n\\nDownsamples the input along its spatial dimensions (depth, height, and\\nwidth) by taking the average value over an input window (of size defined by\\n`pool_size`) for each channel of the input. The window is shifted by\\n`strides` along each dimension.\",\n    \"attributes\": [\n      {\n        \"description\": \"int or tuple of 3 integers, factors by which to downscale\\n        (dim1, dim2, dim3). If only one integer is specified, the same\\n        window length will be used for all dimensions.\",\n        \"name\": \"pool_size\"\n      },\n      {\n        \"description\": \"int or tuple of 3 integers, or None. Strides values. If None,\\n        it will default to `pool_size`. If only one int is specified, the\\n        same stride size will be used for all dimensions.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape\\n        `(batch, spatial_dim1, spatial_dim2, spatial_dim3, channels)` while\\n        `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, channels, spatial_dim1, spatial_dim2, spatial_dim3)`.\\n        It defaults to the `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json`. If you never set it, then it\\n        will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, pooled_dim1, pooled_dim2, pooled_dim3, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, channels, pooled_dim1, pooled_dim2, pooled_dim3)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"depth = 30\\nheight = 30\\nwidth = 30\\nchannels = 3\\n\\ninputs = keras.layers.Input(shape=(depth, height, width, channels))\\nlayer = keras.layers.AveragePooling3D(pool_size=3)\\noutputs = layer(inputs)  # Shape: (batch_size, 10, 10, 10, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"LayerNormalization\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Normalization\",\n    \"description\": \"Layer normalization layer (Ba et al., 2016).\\n\\nNormalize the activations of the previous layer for each given example in a\\nbatch independently, rather than across a batch like Batch Normalization.\\ni.e. applies a transformation that maintains the mean activation within each\\nexample close to 0 and the activation standard deviation close to 1.\\n\\nIf `scale` or `center` are enabled, the layer will scale the normalized\\noutputs by broadcasting them with a trainable variable `gamma`, and center\\nthe outputs by broadcasting with a trainable variable `beta`. `gamma` will\\ndefault to a ones tensor and `beta` will default to a zeros tensor, so that\\ncentering and scaling are no-ops before training has begun.\\n\\nSo, with scaling and centering enabled the normalization equations\\nare as follows:\\n\\nLet the intermediate activations for a mini-batch to be the `inputs`.\\n\\nFor each sample `x_i` in `inputs` with `k` features, we compute the mean and\\nvariance of the sample:\\n\\n```python\\nmean_i = sum(x_i[j] for j in range(k)) / k\\nvar_i = sum((x_i[j] - mean_i) ** 2 for j in range(k)) / k\\n```\\n\\nand then compute a normalized `x_i_normalized`, including a small factor\\n`epsilon` for numerical stability.\\n\\n```python\\nx_i_normalized = (x_i - mean_i) / sqrt(var_i + epsilon)\\n```\\n\\nAnd finally `x_i_normalized ` is linearly transformed by `gamma` and `beta`,\\nwhich are learned parameters:\\n\\n```python\\noutput_i = x_i_normalized * gamma + beta\\n```\\n\\n`gamma` and `beta` will span the axes of `inputs` specified in `axis`, and\\nthis part of the inputs' shape must be fully defined.\\n\\nFor example:\\n\\n```\\n>>> layer = keras.layers.LayerNormalization(axis=[1, 2, 3])\\n>>> layer.build([5, 20, 30, 40])\\n>>> print(layer.beta.shape)\\n(20, 30, 40)\\n>>> print(layer.gamma.shape)\\n(20, 30, 40)\\n```\\n\\nNote that other implementations of layer normalization may choose to define\\n`gamma` and `beta` over a separate set of axes from the axes being\\nnormalized across. For example, Group Normalization\\n([Wu et al. 2018](https://arxiv.org/abs/1803.08494)) with group size of 1\\ncorresponds to a Layer Normalization that normalizes across height, width,\\nand channel and has `gamma` and `beta` span only the channel dimension.\\nSo, this Layer Normalization implementation will not match a Group\\nNormalization layer with group size set to 1.\",\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"description\": \"Integer or List/Tuple. The axis or axes to normalize across.\\n        Typically, this is the features axis/axes. The left-out axes are\\n        typically the batch axis/axes. `-1` is the last dimension in the\\n        input. Defaults to `-1`.\"\n      },\n      {\n        \"name\": \"epsilon\",\n        \"description\": \"Small float added to variance to avoid dividing by zero.\\n        Defaults to 1e-3.\"\n      },\n      {\n        \"name\": \"center\",\n        \"description\": \"If True, add offset of `beta` to normalized tensor. If False,\\n        `beta` is ignored. Defaults to `True`.\"\n      },\n      {\n        \"name\": \"scale\",\n        \"description\": \"If True, multiply by `gamma`. If False, `gamma` is not used.\\n        When the next layer is linear (also e.g. `nn.relu`), this can be\\n        disabled since the scaling will be done by the next layer.\\n        Defaults to `True`.\"\n      },\n      {\n        \"name\": \"rms_scaling\",\n        \"description\": \"If True, `center` and `scale` are ignored, and the\\n        inputs are scaled by `gamma` and the inverse square root\\n        of the square of all inputs. This is an approximate and faster\\n        approach that avoids ever computing the mean of the input. Note that\\n        this *isn't* equivalent to the computation that the\\n        `keras.layers.RMSNormalization` layer performs.\"\n      },\n      {\n        \"name\": \"beta_initializer\",\n        \"description\": \"Initializer for the beta weight. Defaults to zeros.\"\n      },\n      {\n        \"name\": \"gamma_initializer\",\n        \"description\": \"Initializer for the gamma weight. Defaults to ones.\"\n      },\n      {\n        \"name\": \"beta_regularizer\",\n        \"description\": \"Optional regularizer for the beta weight.\\n        None by default.\"\n      },\n      {\n        \"name\": \"gamma_regularizer\",\n        \"description\": \"Optional regularizer for the gamma weight.\\n        None by default.\"\n      },\n      {\n        \"name\": \"beta_constraint\",\n        \"description\": \"Optional constraint for the beta weight.\\n        None by default.\"\n      },\n      {\n        \"name\": \"gamma_constraint\",\n        \"description\": \"Optional constraint for the gamma weight.\\n        None by default.\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments (e.g. `name` and `dtype`).\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"gamma\"\n      },\n      {\n        \"name\": \"beta\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Lei Ba et al., 2016](https://arxiv.org/abs/1607.06450).\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      {\n        \"default\": -1,\n        \"name\": \"axis\"\n      },\n      {\n        \"default\": 0.001,\n        \"name\": \"epsilon\"\n      },\n      {\n        \"default\": 0.99,\n        \"name\": \"momentum\"\n      },\n      {\n        \"default\": true,\n        \"name\": \"scale\"\n      },\n      {\n        \"default\": true,\n        \"name\": \"center\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Ones\",\n          \"config\": {}\n        },\n        \"name\": \"gamma_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"name\": \"moving_mean_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Ones\",\n          \"config\": {}\n        },\n        \"name\": \"moving_variance_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"name\": \"beta_initializer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"beta_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"gamma_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"name\": \"beta_constraint\"\n      },\n      {\n        \"name\": \"gamma_constraint\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"gamma\"\n      },\n      {\n        \"name\": \"beta\"\n      },\n      {\n        \"name\": \"running_mean\"\n      },\n      {\n        \"name\": \"running_std\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BatchNormalization\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Normalization\",\n    \"description\": \"Layer that normalizes its inputs.\\n\\nBatch normalization applies a transformation that maintains the mean output\\nclose to 0 and the output standard deviation close to 1.\\n\\nImportantly, batch normalization works differently during training and\\nduring inference.\\n\\n**During training** (i.e. when using `fit()` or when calling the layer/model\\nwith the argument `training=True`), the layer normalizes its output using\\nthe mean and standard deviation of the current batch of inputs. That is to\\nsay, for each channel being normalized, the layer returns\\n`gamma * (batch - mean(batch)) / sqrt(var(batch) + epsilon) + beta`, where:\\n\\n- `epsilon` is small constant (configurable as part of the constructor\\narguments)\\n- `gamma` is a learned scaling factor (initialized as 1), which\\ncan be disabled by passing `scale=False` to the constructor.\\n- `beta` is a learned offset factor (initialized as 0), which\\ncan be disabled by passing `center=False` to the constructor.\\n\\n**During inference** (i.e. when using `evaluate()` or `predict()` or when\\ncalling the layer/model with the argument `training=False` (which is the\\ndefault), the layer normalizes its output using a moving average of the\\nmean and standard deviation of the batches it has seen during training. That\\nis to say, it returns\\n`gamma * (batch - self.moving_mean) / sqrt(self.moving_var+epsilon) + beta`.\\n\\n`self.moving_mean` and `self.moving_var` are non-trainable variables that\\nare updated each time the layer in called in training mode, as such:\\n\\n- `moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum)`\\n- `moving_var = moving_var * momentum + var(batch) * (1 - momentum)`\\n\\nAs such, the layer will only normalize its inputs during inference\\n*after having been trained on data that has similar statistics as the\\ninference data*.\",\n    \"attributes\": [\n      {\n        \"default\": -1,\n        \"description\": \"Integer, the axis that should be normalized\\n        (typically the features axis). For instance, after a `Conv2D` layer\\n        with `data_format=\\\"channels_first\\\"`, use `axis=1`.\",\n        \"name\": \"axis\"\n      },\n      {\n        \"default\": 0.001,\n        \"description\": \"Small float added to variance to avoid dividing by zero.\",\n        \"name\": \"epsilon\"\n      },\n      {\n        \"default\": 0.99,\n        \"description\": \"Momentum for the moving average.\",\n        \"name\": \"momentum\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"If `True`, multiply by `gamma`. If `False`, `gamma` is not used.\\n        When the next layer is linear this can be disabled\\n        since the scaling will be done by the next layer.\",\n        \"name\": \"scale\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"If `True`, add offset of `beta` to normalized tensor.\\n        If `False`, `beta` is ignored.\",\n        \"name\": \"center\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Ones\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the gamma weight.\",\n        \"name\": \"gamma_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the moving mean.\",\n        \"name\": \"moving_mean_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Ones\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the moving variance.\",\n        \"name\": \"moving_variance_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the beta weight.\",\n        \"name\": \"beta_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the beta weight.\",\n        \"name\": \"beta_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the gamma weight.\",\n        \"name\": \"gamma_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional constraint for the beta weight.\",\n        \"name\": \"beta_constraint\"\n      },\n      {\n        \"description\": \"Optional constraint for the gamma weight.\",\n        \"name\": \"gamma_constraint\"\n      },\n      {\n        \"description\": \"Whether to use\\n        [Batch Renormalization](https://arxiv.org/abs/1702.03275). This\\n        adds extra variables during training. The inference is the same\\n        for either value of this parameter.\",\n        \"name\": \"renorm\"\n      },\n      {\n        \"description\": \"Dictionary, valid only if `renorm = True`.\\n        Maps optional keys `\\\"rmax\\\"`, `\\\"rmin\\\"`, `\\\"dmax\\\"` to floats used to\\n        clip the renorm correction. The correction `(r, d)` is used as\\n        `corrected_value = normalized_value * r + d`, with `r` clipped to\\n        `[rmin, rmax]`, and `d` to `[-dmax, dmax]`. Missing `rmax`, `rmin`,\\n        `dmax` are set to `inf`, `0`, `inf`, respectively.\",\n        \"name\": \"renorm_clipping\"\n      },\n      {\n        \"description\": \"Momentum used to update the moving means and standard\\n        deviations with renorm. Valid only if `renorm= True`. Unlike\\n        `momentum`, this affects training and should be neither too small\\n        (which would add noise) nor too large (which would give stale\\n        estimates). Note that `momentum` is still applied to get the means\\n        and variances for inference.\",\n        \"name\": \"renorm_momentum\"\n      },\n      {\n        \"description\": \"if `True`, use a faster, fused implementation, or raise a ValueError\\n    if the fused implementation cannot be used. If `None`, use the faster\\n    implementation if possible. If False, do not used the fused\\n    implementation.\",\n        \"name\": \"fused\"\n      },\n      {\n        \"description\": \"Boolean, if `True` the variables will be marked as trainable.\",\n        \"name\": \"trainable\"\n      },\n      {\n        \"description\": \"An `int`. By default, `virtual_batch_size` is `None`,\\n    which means batch normalization is performed across the whole batch. When\\n    `virtual_batch_size` is not `None`, instead perform \\\"Ghost Batch\\n    Normalization\\\", which creates virtual sub-batches which are each\\n    normalized separately (with shared gamma, beta, and moving statistics).\\n    Must divide the actual batch size during execution.\",\n        \"name\": \"virtual_batch_size\"\n      },\n      {\n        \"description\": \"A function taking the `Tensor` containing the (dynamic) shape of\\n    the input tensor and returning a pair (scale, bias) to apply to the\\n    normalized values (before gamma and beta), only during training. For\\n    example, if axis==-1,\\n      `adjustment = lambda shape: (\\n        tf.random.uniform(shape[-1:], 0.93, 1.07),\\n        tf.random.uniform(shape[-1:], -0.1, 0.1))` will scale the normalized\\n          value by up to 7% up or down, then shift the result by up to 0.1\\n          (with independent scaling and bias for each feature but shared\\n          across all examples), and finally apply gamma and/or beta. If\\n          `None`, no adjustment is applied. Cannot be specified if\\n          virtual_batch_size is specified.\",\n        \"name\": \"adjustment\"\n      },\n      {\n        \"name\": \"synchronized\",\n        \"description\": \"Only applicable with the TensorFlow backend.\\n        If `True`, synchronizes the global batch statistics (mean and\\n        variance) for the layer across all devices at each training step\\n        in a distributed training strategy.\\n        If `False`, each replica uses its own local batch statistics.\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments (e.g. `name` and `dtype`).\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape` (tuple of\\nintegers, does not include the samples axis) when using this layer as the\\nfirst layer in a model.\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"gamma\"\n      },\n      {\n        \"name\": \"beta\"\n      },\n      {\n        \"name\": \"moving_mean\"\n      },\n      {\n        \"name\": \"moving_variance\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as input.\\n\\nReference:\\n  - [Ioffe and Szegedy, 2015](https://arxiv.org/abs/1502.03167).\\n\\n**About setting `layer.trainable = False` on a `BatchNormalization` layer:**\\n\\nThe meaning of setting `layer.trainable = False` is to freeze the layer,\\ni.e. its internal state will not change during training:\\nits trainable weights will not be updated\\nduring `fit()` or `train_on_batch()`, and its state updates will not be run.\\n\\nUsually, this does not necessarily mean that the layer is run in inference\\nmode (which is normally controlled by the `training` argument that can\\nbe passed when calling a layer). \\\"Frozen state\\\" and \\\"inference mode\\\"\\nare two separate concepts.\\n\\nHowever, in the case of the `BatchNormalization` layer, **setting\\n`trainable = False` on the layer means that the layer will be\\nsubsequently run in inference mode** (meaning that it will use\\nthe moving mean and the moving variance to normalize the current batch,\\nrather than using the mean and variance of the current batch).\\n\\nThis behavior has been introduced in TensorFlow 2.0, in order\\nto enable `layer.trainable = False` to produce the most commonly\\nexpected behavior in the convnet fine-tuning use case.\\n\\nNote that:\\n  - Setting `trainable` on an model containing other layers will\\n    recursively set the `trainable` value of all inner layers.\\n  - If the value of the `trainable`\\n    attribute is changed after calling `compile()` on a model,\\n    the new value doesn't take effect for this model\\n    until `compile()` is called again.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Ioffe and Szegedy, 2015](https://arxiv.org/abs/1502.03167).  **About setting `layer.trainable = False` on a `BatchNormalization` layer:**  The meaning of setting `layer.trainable = False` is to freeze the layer, i.e. its internal state will not change during training: its trainable weights will not be updated during `fit()` or `train_on_batch()`, and its state updates will not be run.  Usually, this does not necessarily mean that the layer is run in inference mode (which is normally controlled by the `training` argument that can be passed when calling a layer). \\\"Frozen state\\\" and \\\"inference mode\\\" are two separate concepts.  However, in the case of the `BatchNormalization` layer, **setting `trainable = False` on the layer means that the layer will be subsequently run in inference mode** (meaning that it will use the moving mean and the moving variance to normalize the current batch, rather than using the mean and variance of the current batch).  Note that: \"\n      },\n      {\n        \"description\": \"Setting `trainable` on an model containing other layers will recursively set the `trainable` value of all inner layers.\"\n      },\n      {\n        \"description\": \"If the value of the `trainable` attribute is changed after calling `compile()` on a model, the new value doesn't take effect for this model until `compile()` is called again.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Bidirectional\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Bidirectional wrapper for RNNs.\",\n    \"attributes\": [\n      {\n        \"default\": \"concat\",\n        \"description\": \"Mode by which outputs of the forward and backward RNNs\\n        will be combined. One of `{\\\"sum\\\", \\\"mul\\\", \\\"concat\\\", \\\"ave\\\", None}`.\\n        If `None`, the outputs will not be combined,\\n        they will be returned as a list. Defaults to `\\\"concat\\\"`.\",\n        \"name\": \"merge_mode\"\n      },\n      {\n        \"description\": \"`keras.layers.RNN` instance, such as\\n        `keras.layers.LSTM` or `keras.layers.GRU`.\\n        It could also be a `keras.layers.Layer` instance\\n        that meets the following criteria:\\n        1. Be a sequence-processing layer (accepts 3D+ inputs).\\n        2. Have a `go_backwards`, `return_sequences` and `return_state`\\n        attribute (with the same semantics as for the `RNN` class).\\n        3. Have an `input_spec` attribute.\\n        4. Implement serialization via `get_config()` and `from_config()`.\\n        Note that the recommended way to create new RNN layers is to write a\\n        custom RNN cell and use it with `keras.layers.RNN`, instead of\\n        subclassing `keras.layers.Layer` directly.\\n        When `return_sequences` is `True`, the output of the masked\\n        timestep will be zero regardless of the layer's original\\n        `zero_output_for_mask` value.\",\n        \"name\": \"layer\"\n      },\n      {\n        \"description\": \"Initial weights to load in the Bidirectional model\\n\",\n        \"name\": \"weights\"\n      },\n      {\n        \"description\": \"Optional `keras.layers.RNN`,\\n        or `keras.layers.Layer` instance to be used to handle\\n        backwards input processing.\\n        If `backward_layer` is not provided, the layer instance passed\\n        as the `layer` argument will be used to generate the backward layer\\n        automatically.\\n        Note that the provided `backward_layer` layer should have properties\\n        matching those of the `layer` argument, in particular\\n        it should have the same values for `stateful`, `return_states`,\\n        `return_sequences`, etc. In addition, `backward_layer`\\n        and `layer` should have different `go_backwards` argument values.\\n        A `ValueError` will be raised if these requirements are not met.\",\n        \"name\": \"backward_layer\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"model = Sequential([\\n    Input(shape=(5, 10)),\\n    Bidirectional(LSTM(10, return_sequences=True),\\n    Bidirectional(LSTM(10)),\\n    Dense(5, activation=\\\"softmax\\\"),\\n])\\nmodel.compile(loss='categorical_crossentropy', optimizer='rmsprop')\\n\\n# With custom backward layer\\nforward_layer = LSTM(10, return_sequences=True)\\nbackward_layer = LSTM(10, activation='relu', return_sequences=True,\\n                      go_backwards=True)\\nmodel = Sequential([\\n    Input(shape=(5, 10)),\\n    Bidirectional(forward_layer, backward_layer=backward_layer),\\n    Dense(5, activation=\\\"softmax\\\"),\\n])\\nmodel.compile(loss='categorical_crossentropy', optimizer='rmsprop')\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Concatenate\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Tensor\",\n    \"description\": \"Concatenates a list of inputs.\\n\\nIt takes as input a list of tensors, all of the same shape except\\nfor the concatenation axis, and returns a single tensor that is the\\nconcatenation of all inputs.\",\n    \"attributes\": [\n      {\n        \"description\": \"Axis along which to concatenate.\",\n        \"name\": \"axis\"\n      },\n      {\n        \"description\": \"Standard layer keyword arguments.\",\n        \"name\": \"**kwargs\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.arange(20).reshape(2, 2, 5)\\n>>> y = np.arange(20, 30).reshape(2, 1, 5)\\n>>> keras.layers.Concatenate(axis=1)([x, y])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> x1 = keras.layers.Dense(8)(np.arange(10).reshape(5, 2))\\n>>> x2 = keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))\\n>>> y = keras.layers.Concatenate()([x1, x2])\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Conv1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"1D convolution layer (e.g. temporal convolution).\\n\\nThis layer creates a convolution kernel that is convolved with the layer\\ninput over a single spatial (or temporal) dimension to produce a tensor of\\noutputs. If `use_bias` is True, a bias vector is created and added to the\\noutputs. Finally, if `activation` is not `None`, it is applied to the\\noutputs as well.\",\n    \"attributes\": [\n      {\n        \"default\": \"linear\",\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"valid\",\n        \"description\": \"string, `\\\"valid\\\"`, `\\\"same\\\"` or `\\\"causal\\\"`(case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\\n        `\\\"causal\\\"` results in causal(dilated) convolutions, e.g. `output[t]`\\n        does not depend on`input[t+1:]`. Useful when modeling temporal data\\n        where the model should not violate the temporal order.\\n        See [WaveNet: A Generative Model for Raw Audio, section2.1](\\n        https://arxiv.org/abs/1609.03499).\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": [\n          1\n        ],\n        \"description\": \"int or tuple/list of 1 integer, specifying the stride length\\n        of the convolution. `strides > 1` is incompatible with\\n        `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"default\": [\n          1\n        ],\n        \"description\": \"int or tuple/list of 1 integers, specifying the dilation\\n        rate to use for dilated convolution.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector. If `None`, the\\n        default initializer (`\\\"zeros\\\"`) will be used.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the convolution kernel. If `None`,\\n        the default initializer (`\\\"glorot_uniform\\\"`) will be used.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"int, the dimension of the output space (the number of filters\\n        in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integer, specifying the size of the\\n        convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"Optional regularizer for the convolution kernel.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        kernel after being updated by an `Optimizer` (e.g. used to implement\\n        norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape). Constraints\\n        are not safe to use when doing asynchronous distributed training.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"A positive int specifying the number of groups in which the\\n        input is split along the channel axis. Each group is convolved\\n        separately with `filters // groups` filters. The output is the\\n        concatenation of all the `groups` results along the channel axis.\\n        Input channels and `filters` must both be divisible by `groups`.\",\n        \"name\": \"groups\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 3D tensor with shape: `(batch_shape, steps, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 3D tensor with shape: `(batch_shape, channels, steps)`\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 3D tensor with shape: `(batch_shape, new_steps, filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 3D tensor with shape: `(batch_shape, filters, new_steps)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> # The inputs are 128-length vectors with 10 timesteps, and the\\n>>> # batch size is 4.\\n>>> x = np.random.rand(4, 10, 128)\\n>>> y = keras.layers.Conv1D(32, 3, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 8, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Conv2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"2D convolution layer.\\n\\nThis layer creates a convolution kernel that is convolved with the layer\\ninput over a 2D spatial (or temporal) dimension (height and width) to\\nproduce a tensor of outputs. If `use_bias` is True, a bias vector is created\\nand added to the outputs. Finally, if `activation` is not `None`, it is\\napplied to the outputs as well.\\n\\nNote on numerical precision: While in general Keras operation execution\\nresults are identical across backends up to 1e-7 precision in float32,\\n`Conv2D` operations may show larger variations. Due to the large\\nnumber of element-wise multiplications and additions in convolution\\noperations, especially with large inputs or kernel sizes, accumulated\\nfloating-point differences can exceed this 1e-7 threshold. These variations\\nare particularly noticeable when using different backends (e.g., TensorFlow\\nvs JAX) or different hardware.\",\n    \"attributes\": [\n      {\n        \"default\": \"linear\",\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"valid\",\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\",\n        \"type\": \"boolean\",\n        \"visible\": false\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, height, width)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"int or tuple/list of 2 integer, specifying the stride length\\n        of the convolution. `strides > 1` is incompatible with\\n        `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"int or tuple/list of 2 integers, specifying the dilation\\n        rate to use for dilated convolution.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector. If `None`, the\\n        default initializer (`\\\"zeros\\\"`) will be used.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the convolution kernel. If `None`,\\n        the default initializer (`\\\"glorot_uniform\\\"`) will be used.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"int, the dimension of the output space (the number of filters\\n        in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 2 integer, specifying the size of the\\n        convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"Optional regularizer for the convolution kernel.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        kernel after being updated by an `Optimizer` (e.g. used to implement\\n        norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape). Constraints\\n        are not safe to use when doing asynchronous distributed training.\",\n        \"name\": \"kernel_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"A positive int specifying the number of groups in which the\\n        input is split along the channel axis. Each group is convolved\\n        separately with `filters // groups` filters. The output is the\\n        concatenation of all the `groups` results along the channel axis.\\n        Input channels and `filters` must both be divisible by `groups`.\",\n        \"name\": \"groups\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, height, width, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, new_height, new_width, filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, filters, new_height, new_width)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(4, 10, 10, 128)\\n>>> y = keras.layers.Conv2D(32, 3, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 8, 8, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Conv2DTranspose\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"2D transposed convolution layer.\\n\\nThe need for transposed convolutions generally arise from the desire to use\\na transformation going in the opposite direction of a normal convolution,\\ni.e., from something that has the shape of the output of some convolution\\nto something that has the shape of its input while maintaining a\\nconnectivity pattern that is compatible with said convolution.\",\n    \"attributes\": [\n      {\n        \"description\": \"int, the dimension of the output space (the number of filters\\n        in the transposed convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integer, specifying the size of the\\n        transposed convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integer, specifying the stride length\\n        of the transposed convolution. `strides > 1` is incompatible with\\n        `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, height, width)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\\n     dilation_rate: An integer or tuple/list of 2 integers,\\n        specifying the dilation rate for\\n        all spatial dimensions for dilated convolution.\\n        Specifying different dilation rates\\n        for different dimensions is not supported.\\n        Currently, specifying any `dilation_rate` value != 1 is\\n        incompatible with specifying any stride value != 1.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integers, specifying the dilation\\n        rate to use for dilated transposed convolution.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the convolution kernel. If `None`,\\n        the default initializer (`\\\"glorot_uniform\\\"`) will be used.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector. If `None`, the\\n        default initializer (`\\\"zeros\\\"`) will be used.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the convolution kernel.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        kernel after being updated by an `Optimizer` (e.g. used to implement\\n        norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape). Constraints\\n        are not safe to use when doing asynchronous distributed training.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"An integer or tuple/list of 2 integers,\\n        specifying the amount of padding along the height and width\\n        of the output tensor.\\n        Can be a single integer to specify the same value for all\\n        spatial dimensions.\\n        The amount of output padding along a given dimension must be\\n        lower than the stride along that same dimension.\\n        If set to `None` (default), the output shape is inferred.\",\n        \"name\": \"output_padding\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, height, width, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, new_height, new_width, filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, filters, new_height, new_width)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[A guide to convolution arithmetic for deep learning]( https://arxiv.org/abs/1603.07285v1)\"\n      },\n      {\n        \"description\": \"[Deconvolutional Networks]( https://www.matthewzeiler.com/mattzeiler/deconvolutionalnetworks.pdf) \"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(4, 10, 8, 128)\\n>>> y = keras.layers.Conv2DTranspose(32, 2, 2, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 20, 16, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Conv3D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"3D convolution layer.\\n\\nThis layer creates a convolution kernel that is convolved with the layer\\ninput over a 3D spatial (or temporal) dimension (width,height and depth) to\\nproduce a tensor of outputs. If `use_bias` is True, a bias vector is created\\nand added to the outputs. Finally, if `activation` is not `None`, it is\\napplied to the outputs as well.\",\n    \"attributes\": [\n      {\n        \"description\": \"int, the dimension of the output space (the number of filters\\n        in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 3 integer, specifying the size of the\\n        convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"int or tuple/list of 3 integer, specifying the stride length\\n        of the convolution. `strides > 1` is incompatible with\\n        `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`.\\n        It defaults to the `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json`. If you never set it, then it\\n        will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"int or tuple/list of 3 integers, specifying the dilation\\n        rate to use for dilated convolution.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the convolution kernel. If `None`,\\n        the default initializer (`\\\"glorot_uniform\\\"`) will be used.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector. If `None`, the\\n        default initializer (`\\\"zeros\\\"`) will be used.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the convolution kernel.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        kernel after being updated by an `Optimizer` (e.g. used to implement\\n        norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape). Constraints\\n        are not safe to use when doing asynchronous distributed training.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"A positive int specifying the number of groups in which the\\n        input is split along the channel axis. Each group is convolved\\n        separately with `filters // groups` filters. The output is the\\n        concatenation of all the `groups` results along the channel axis.\\n        Input channels and `filters` must both be divisible by `groups`.\",\n        \"name\": \"groups\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, new_spatial_dim1, new_spatial_dim2, new_spatial_dim3,\\n    filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, filters, new_spatial_dim1, new_spatial_dim2,\\n    new_spatial_dim3)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(4, 10, 10, 10, 128)\\n>>> y = keras.layers.Conv3D(32, 3, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 8, 8, 8, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ConvLSTM2D\",\n    \"module\": \"keras.layers\",\n    \"description\": \"2D Convolutional LSTM.\\n\\nSimilar to an LSTM layer, but the input transformations\\nand recurrent transformations are both convolutional.\",\n    \"attributes\": [\n      {\n        \"description\": \"int, the dimension of the output space (the number of filters\\n        in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 2 integers, specifying the size of the\\n        convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"int or tuple/list of 2 integers, specifying the stride length\\n        of the convolution. `strides > 1` is incompatible with\\n        `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"int or tuple/list of 2 integers, specifying the dilation\\n        rate to use for dilated convolution.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"description\": \"Activation function to use. By default hyperbolic tangent\\n        activation function is applied (`tanh(x)`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"Activation function to use for the recurrent step.\",\n        \"name\": \"recurrent_activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean, whether the layer uses a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel` weights\\n        matrix, used for the linear transformation of the recurrent state.\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Boolean. If `True`, add 1 to the bias of the forget\\n        gate at initialization.\\n        Use in combination with `bias_initializer=\\\"zeros\\\"`.\\n        This is recommended in [Jozefowicz et al., 2015](\\n        http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf)\",\n        \"name\": \"unit_forget_bias\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix.\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix.\",\n        \"name\": \"kernel_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix.\",\n        \"name\": \"recurrent_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\",\n        \"name\": \"bias_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Boolean. Whether to return the last output\\n        in the output sequence, or the full sequence. Default: `False`.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"description\": \"Boolean (default: `False`).\\n        If `True`, process the input sequence backwards and return the\\n        reversed sequence.\",\n        \"name\": \"go_backwards\"\n      },\n      {\n        \"description\": \"Boolean (default False). If `True`, the last state\\n        for each sample at index i in a batch will be used as initial\\n        state for the sample of index i in the following batch.\",\n        \"name\": \"stateful\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        linear transformation of the inputs.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop\\n        for the linear transformation of the recurrent state.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"description\": \"Boolean. Whether to return the last state in addition\\n        to the output. Default: `False`.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Random seed for dropout.\"\n      },\n      {\n        \"name\": \"unroll\",\n        \"description\": \"Boolean (default: `False`).\\n        If `True`, the network will be unrolled,\\n        else a symbolic loop will be used.\\n        Unrolling can speed-up a RNN,\\n        although it tends to be more memory-intensive.\\n        Unrolling is only suitable for short sequences.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format='channels_first'`:\\n    5D tensor with shape: `(samples, time, channels, rows, cols)`\\n- If `data_format='channels_last'`:\\n    5D tensor with shape: `(samples, time, rows, cols, channels)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `return_state`: a list of tensors. The first tensor is the output.\\n    The remaining tensors are the last states,\\n    each 4D tensor with shape: `(samples, filters, new_rows, new_cols)` if\\n    `data_format='channels_first'`\\n    or shape: `(samples, new_rows, new_cols, filters)` if\\n    `data_format='channels_last'`. `rows` and `cols` values might have\\n    changed due to padding.\\n- If `return_sequences`: 5D tensor with shape: `(samples, timesteps,\\n    filters, new_rows, new_cols)` if data_format='channels_first'\\n    or shape: `(samples, timesteps, new_rows, new_cols, filters)` if\\n    `data_format='channels_last'`.\\n- Else, 4D tensor with shape: `(samples, filters, new_rows, new_cols)` if\\n    `data_format='channels_first'`\\n    or shape: `(samples, new_rows, new_cols, filters)` if\\n    `data_format='channels_last'`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"steps = 10\\nheight = 32\\nwidth = 32\\ninput_channels = 3\\noutput_channels = 6\\n\\ninputs = tf.keras.Input(shape=(steps, height, width, input_channels))\\nlayer = tf.keras.layers.ConvLSTM2D(filters=output_channels, kernel_size=3)\\noutputs = layer(inputs)\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Shi et al., 2015](http://arxiv.org/abs/1506.04214v1) (the current implementation does not include the feedback loop on the cells output).\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Convolution2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"2D convolution layer.\\n\\nThis layer creates a convolution kernel that is convolved with the layer\\ninput over a 2D spatial (or temporal) dimension (height and width) to\\nproduce a tensor of outputs. If `use_bias` is True, a bias vector is created\\nand added to the outputs. Finally, if `activation` is not `None`, it is\\napplied to the outputs as well.\\n\\nNote on numerical precision: While in general Keras operation execution\\nresults are identical across backends up to 1e-7 precision in float32,\\n`Conv2D` operations may show larger variations. Due to the large\\nnumber of element-wise multiplications and additions in convolution\\noperations, especially with large inputs or kernel sizes, accumulated\\nfloating-point differences can exceed this 1e-7 threshold. These variations\\nare particularly noticeable when using different backends (e.g., TensorFlow\\nvs JAX) or different hardware.\",\n    \"attributes\": [\n      {\n        \"default\": \"linear\",\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"valid\",\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, height, width)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"int or tuple/list of 2 integer, specifying the stride length\\n        of the convolution. `strides > 1` is incompatible with\\n        `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"int or tuple/list of 2 integers, specifying the dilation\\n        rate to use for dilated convolution.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"default\": 1,\n        \"name\": \"depth_multiplier\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector. If `None`, the\\n        default initializer (`\\\"zeros\\\"`) will be used.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the convolution kernel. If `None`,\\n        the default initializer (`\\\"glorot_uniform\\\"`) will be used.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"int, the dimension of the output space (the number of filters\\n        in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 2 integer, specifying the size of the\\n        convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"Optional regularizer for the convolution kernel.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        kernel after being updated by an `Optimizer` (e.g. used to implement\\n        norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape). Constraints\\n        are not safe to use when doing asynchronous distributed training.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"A positive int specifying the number of groups in which the\\n        input is split along the channel axis. Each group is convolved\\n        separately with `filters // groups` filters. The output is the\\n        concatenation of all the `groups` results along the channel axis.\\n        Input channels and `filters` must both be divisible by `groups`.\",\n        \"name\": \"groups\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, height, width, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, new_height, new_width, filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, filters, new_height, new_width)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(4, 10, 10, 128)\\n>>> y = keras.layers.Conv2D(32, 3, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 8, 8, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Cropping1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Cropping layer for 1D input (e.g. temporal sequence).\\n\\nIt crops along the time dimension (axis 1).\",\n    \"attributes\": [\n      {\n        \"description\": \"Int, or tuple of int (length 2), or dictionary.\\n        - If int: how many units should be trimmed off at the beginning and\\n          end of the cropping dimension (axis 1).\\n        - If tuple of 2 ints: how many units should be trimmed off at the\\n          beginning and end of the cropping dimension\\n          (`(left_crop, right_crop)`).\",\n        \"name\": \"cropping\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D tensor with shape `(batch_size, axis_to_crop, features)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3D tensor with shape `(batch_size, cropped_axis, features)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 3, 2)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> x\\n[[[ 0  1]\\n  [ 2  3]\\n  [ 4  5]]\\n [[ 6  7]\\n  [ 8  9]\\n  [10 11]]]\\n>>> y = keras.layers.Cropping1D(cropping=1)(x)\\n>>> y\\n[[[2 3]]\\n [[8 9]]]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Cropping2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Cropping layer for 2D input (e.g. picture).\\n\\nIt crops along spatial dimensions, i.e. height and width.\",\n    \"attributes\": [\n      {\n        \"description\": \"Int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints.\\n        - If int: the same symmetric cropping is applied to height and\\n          width.\\n        - If tuple of 2 ints: interpreted as two different symmetric\\n          cropping values for height and width:\\n          `(symmetric_height_crop, symmetric_width_crop)`.\\n        - If tuple of 2 tuples of 2 ints: interpreted as\\n          `((top_crop, bottom_crop), (left_crop, right_crop))`.\",\n        \"name\": \"cropping\"\n      },\n      {\n        \"description\": \"A string, one of `\\\"channels_last\\\"` (default) or\\n        `\\\"channels_first\\\"`. The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, height, width, channels)` while `\\\"channels_first\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, channels, height, width)`.\\n        When unspecified, uses `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json` (if exists). Defaults to\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, height, width, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, cropped_height, cropped_width, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, channels, cropped_height, cropped_width)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 28, 28, 3)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> y = keras.layers.Cropping2D(cropping=((2, 2), (4, 4)))(x)\\n>>> y.shape\\n(2, 24, 20, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Cropping3D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Cropping layer for 3D data (e.g. spatial or spatio-temporal).\",\n    \"attributes\": [\n      {\n        \"description\": \"Int, or tuple of 3 ints, or tuple of 3 tuples of 2 ints.\\n        - If int: the same symmetric cropping is applied to depth, height,\\n          and width.\\n        - If tuple of 3 ints: interpreted as three different symmetric\\n          cropping values for depth, height, and width:\\n          `(symmetric_dim1_crop, symmetric_dim2_crop, symmetric_dim3_crop)`.\\n        - If tuple of 3 tuples of 2 ints: interpreted as\\n          `((left_dim1_crop, right_dim1_crop), (left_dim2_crop,\\n          right_dim2_crop), (left_dim3_crop, right_dim3_crop))`.\",\n        \"name\": \"cropping\"\n      },\n      {\n        \"description\": \"A string, one of `\\\"channels_last\\\"` (default) or\\n        `\\\"channels_first\\\"`. The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`.\\n        When unspecified, uses `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json` (if exists). Defaults to\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"5D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, first_axis_to_crop, second_axis_to_crop,\\n  third_axis_to_crop, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, channels, first_axis_to_crop, second_axis_to_crop,\\n  third_axis_to_crop)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"5D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, first_cropped_axis, second_cropped_axis,\\n  third_cropped_axis, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, channels, first_cropped_axis, second_cropped_axis,\\n  third_cropped_axis)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 28, 28, 10, 3)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> y = keras.layers.Cropping3D(cropping=(2, 4, 2))(x)\\n>>> y.shape\\n(2, 24, 20, 6, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"CuDNNGRU\",\n    \"description\": \"Fast GRU implementation backed by [CuDNN](https://developer.nvidia.com/cudnn).\\n\\nCan only be run on GPU, with the TensorFlow backend.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n    used for the linear transformation of the inputs.\\n    (see [initializers](https://keras.io/initializers)).\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel`\\n    weights matrix,\\n    used for the linear transformation of the recurrent state.\\n    (see [initializers](https://keras.io/initializers)).\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector\\n    (see [initializers](https://keras.io/initializers)).\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the `kernel` weights matrix\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the `recurrent_kernel` weights matrix\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the output of the layer (its \\\"activation\\\").\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to\\n    the `kernel` weights matrix\\n    (see [constraints](https://keras.io/constraints)).\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to\\n    the `recurrent_kernel` weights matrix\\n    (see [constraints](https://keras.io/constraints)).\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector\\n    (see [constraints](https://keras.io/constraints)).\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"Boolean. Whether to return the last output.\\n    in the output sequence, or the full sequence.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"description\": \"Boolean. Whether to return the last state\\n    in addition to the output.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"description\": \"Boolean (default False). If True, the last state\\n    for each sample at index i in a batch will be used as initial\\n    state for the sample of index i in the following batch.\\n\",\n        \"name\": \"stateful\"\n      }\n    ]\n  },\n  {\n    \"name\": \"CuDNNLSTM\",\n    \"description\": \"Fast LSTM implementation with [CuDNN](https://developer.nvidia.com/cudnn).\\n\\nCan only be run on GPU, with the TensorFlow backend.\\n\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n    used for the linear transformation of the inputs.\\n    (see [initializers](https://keras.io/initializers)).\",\n        \"name\": \"kernel_initializer\"\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel`\\n    weights matrix,\\n    used for the linear transformation of the recurrent state.\\n    (see [initializers](https://keras.io/initializers)).\",\n        \"name\": \"recurrent_initializer\"\n      },\n      {\n        \"description\": \"Initializer for the bias vector\\n    (see [initializers](https://keras.io/initializers)).\",\n        \"name\": \"bias_initializer\"\n      },\n      {\n        \"description\": \"Boolean.\\n    If True, add 1 to the bias of the forget gate at initialization.\\n    Setting it to true will also force `bias_initializer=\\\"zeros\\\"`.\\n    This is recommended in [Jozefowicz et al. (2015)](\\n    http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf).\",\n        \"name\": \"unit_forget_bias\"\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the `kernel` weights matrix\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"kernel_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the `recurrent_kernel` weights matrix\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"recurrent_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"bias_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the output of the layer (its \\\"activation\\\").\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"activity_regularizer\"\n      },\n      {\n        \"description\": \"Constraint function applied to\\n    the `kernel` weights matrix\\n    (see [constraints](https://keras.io/constraints)).\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to\\n    the `recurrent_kernel` weights matrix\\n    (see [constraints](https://keras.io/constraints)).\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector\\n    (see [constraints](https://keras.io/constraints)).\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"Boolean. Whether to return the last output.\\n    in the output sequence, or the full sequence.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"description\": \"Boolean. Whether to return the last state\\n    in addition to the output.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"description\": \"Boolean (default False). If True, the last state\\n    for each sample at index i in a batch will be used as initial\\n    state for the sample of index i in the following batch.\\n\",\n        \"name\": \"stateful\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Dense\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Just your regular densely-connected NN layer.\\n\\n`Dense` implements the operation:\\n`output = activation(dot(input, kernel) + bias)`\\nwhere `activation` is the element-wise activation function\\npassed as the `activation` argument, `kernel` is a weights matrix\\ncreated by the layer, and `bias` is a bias vector created by the layer\\n(only applicable if `use_bias` is `True`). When this layer is\\nfollowed by a `BatchNormalization` layer, it is recommended to set\\n`use_bias=False` as `BatchNormalization` has its own bias term.\\n\\nNote: If the input to the layer has a rank greater than 2, `Dense`\\ncomputes the dot product between the `inputs` and the `kernel` along the\\nlast axis of the `inputs` and axis 0 of the `kernel` (using `tf.tensordot`).\\nFor example, if input has dimensions `(batch_size, d0, d1)`, then we create\\na `kernel` with shape `(d1, units)`, and the `kernel` operates along axis 2\\nof the `input`, on every sub-tensor of shape `(1, 1, d1)` (there are\\n`batch_size * d0` such sub-tensors). The output in this case will have\\nshape `(batch_size, d0, units)`.\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"default\": \"linear\",\n        \"description\": \"Activation function to use.\\n        If you don't specify anything, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean, whether the layer uses a bias vector.\",\n        \"name\": \"use_bias\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the `kernel` weights matrix.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n        the `kernel` weights matrix.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n        the output of the layer (its \\\"activation\\\").\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to\\n        the `kernel` weights matrix.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"name\": \"lora_rank\",\n        \"description\": \"Optional integer. If set, the layer's forward pass\\n        will implement LoRA (Low-Rank Adaptation)\\n        with the provided rank. LoRA sets the layer's kernel\\n        to non-trainable and replaces it with a delta over the\\n        original kernel, obtained via multiplying two lower-rank\\n        trainable matrices. This can be useful to reduce the\\n        computation cost of fine-tuning large dense layers.\\n        You can also enable LoRA on an existing\\n        `Dense` layer by calling `layer.enable_lora(rank)`.\"\n      },\n      {\n        \"name\": \"lora_alpha\",\n        \"description\": \"Optional integer. If set, this parameter scales the\\n        low-rank adaptation delta (computed as the product of two lower-rank\\n        trainable matrices) during the forward pass. The delta is scaled by\\n        `lora_alpha / lora_rank`, allowing you to fine-tune the strength of\\n        the LoRA adjustment independently of `lora_rank`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"N-D tensor with shape: `(batch_size, ..., input_dim)`.\\nThe most common situation would be\\na 2D input with shape `(batch_size, input_dim)`.\",\n        \"name\": \"input\",\n        \"type\": \"T\"\n      },\n      {\n        \"name\": \"kernel\",\n        \"type\": \"T\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"T\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"N-D tensor with shape: `(batch_size, ..., units)`.\\nFor instance, for a 2D input with shape `(batch_size, input_dim)`,\\nthe output would have shape `(batch_size, units)`.\",\n        \"name\": \"output\",\n        \"type\": \"T\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> # Create a `Sequential` model and add a Dense layer as the first layer.\\n>>> model = tf.keras.models.Sequential()\\n>>> model.add(tf.keras.Input(shape=(16,)))\\n>>> model.add(tf.keras.layers.Dense(32, activation='relu'))\\n>>> # Now the model will take as input arrays of shape (None, 16)\\n>>> # and output arrays of shape (None, 32).\\n>>> # Note that after the first layer, you don't need to specify\\n>>> # the size of the input anymore:\\n>>> model.add(tf.keras.layers.Dense(32))\\n>>> model.output_shape\\n(None, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"DepthwiseConv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      {\n        \"default\": \"linear\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"valid\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": true,\n        \"name\": \"use_bias\",\n        \"type\": \"boolean\",\n        \"visible\": false\n      },\n      {\n        \"default\": \"channels_last\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"name\": \"strides\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"name\": \"depthwise_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": 1,\n        \"name\": \"depth_multiplier\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Dot\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Computes element-wise dot product of two tensors.\\n\\nIt takes a list of inputs of size 2, and the axes\\ncorresponding to each input along with the dot product\\nis to be performed.\\n\\nLet's say `x` and `y` are the two input tensors with shapes\\n`(2, 3, 5)` and `(2, 10, 3)`. The batch dimension should be\\nof same size for both the inputs, and `axes` should correspond\\nto the dimensions that have the same size in the corresponding\\ninputs. e.g. with `axes=(1, 2)`, the dot product of `x`, and `y`\\nwill result in a tensor with shape `(2, 5, 10)`\",\n    \"attributes\": [\n      {\n        \"description\": \"Integer or tuple of integers, axis or axes along which to\\n        take the dot product. If a tuple, should be two integers\\n        corresponding to the desired axis from the first input and the\\n        desired axis from the second input, respectively. Note that the\\n        size of the two selected axes must match, and that\\n        axis `0` (the batch axis) cannot be included.\",\n        \"name\": \"axes\"\n      },\n      {\n        \"description\": \"Whether to L2-normalize samples along the dot product axis\\n        before taking the dot product. If set to `True`, then\\n        the output of the dot product is the cosine proximity\\n        between the two samples.\",\n        \"name\": \"normalize\"\n      },\n      {\n        \"description\": \"Standard layer keyword arguments.\",\n        \"name\": \"**kwargs\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"x\"\n      },\n      {\n        \"name\": \"y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"z\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.arange(10).reshape(1, 5, 2)\\n>>> y = np.arange(10, 20).reshape(1, 2, 5)\\n>>> keras.layers.Dot(axes=(1, 2))([x, y])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> x1 = keras.layers.Dense(8)(np.arange(10).reshape(5, 2))\\n>>> x2 = keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))\\n>>> y = keras.layers.Dot(axes=1)([x1, x2])\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Dropout\",\n    \"description\": \"Applies dropout to the input.\\n\\nThe `Dropout` layer randomly sets input units to 0 with a frequency of\\n`rate` at each step during training time, which helps prevent overfitting.\\nInputs not set to 0 are scaled up by `1 / (1 - rate)` such that the sum over\\nall inputs is unchanged.\\n\\nNote that the `Dropout` layer only applies when `training` is set to `True`\\nin `call()`, such that no values are dropped during inference.\\nWhen using `model.fit`, `training` will be appropriately set to `True`\\nautomatically. In other contexts, you can set the argument explicitly\\nto `True` when calling the layer.\\n\\n(This is in contrast to setting `trainable=False` for a `Dropout` layer.\\n`trainable` does not affect the layer's behavior, as `Dropout` does\\nnot have any variables/weights that can be frozen during training.)\",\n    \"attributes\": [\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the input units to drop.\",\n        \"name\": \"rate\"\n      },\n      {\n        \"description\": \"1D integer tensor representing the shape of the\\n        binary dropout mask that will be multiplied with the input.\\n        For instance, if your inputs have shape\\n        `(batch_size, timesteps, features)` and\\n        you want the dropout mask to be the same for all timesteps,\\n        you can use `noise_shape=(batch_size, 1, features)`.\",\n        \"name\": \"noise_shape\"\n      },\n      {\n        \"description\": \"A Python integer to use as random seed.\",\n        \"name\": \"seed\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Dropout: A Simple Way to Prevent Neural Networks from Overfitting]( http://www.jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ELU\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Applies an Exponential Linear Unit function to an output.\\n\\nFormula:\\n\\n```\\nf(x) = alpha * (exp(x) - 1.) for x < 0\\nf(x) = x for x >= 0\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"float, slope of negative section. Defaults to `1.0`.\",\n        \"name\": \"alpha\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments, such as `name` and `dtype`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the samples axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)](https://arxiv.org/abs/1511.07289v1)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Embedding\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Transform\",\n    \"description\": \"Turns nonnegative integers (indexes) into dense vectors of fixed size.\\n\\ne.g. `[[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]`\\n\\nThis layer can only be used on nonnegative integer inputs of a fixed range.\",\n    \"attributes\": [\n      {\n        \"default\": false,\n        \"description\": \"Boolean, whether or not the input value 0 is a special\\n        \\\"padding\\\" value that should be masked out.\\n        This is useful when using recurrent layers which\\n        may take variable length input. If this is `True`,\\n        then all subsequent layers in the model need\\n        to support masking or an exception will be raised.\\n        If `mask_zero` is set to `True`, as a consequence,\\n        index 0 cannot be used in the vocabulary (`input_dim` should\\n        equal size of vocabulary + 1).\",\n        \"name\": \"mask_zero\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"RandomUniform\",\n          \"config\": {\n            \"maxval\": 0.05,\n            \"minval\": -0.05,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the `embeddings`\\n        matrix (see `keras.initializers`).\",\n        \"name\": \"embeddings_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Integer. Size of the vocabulary,\\n        i.e. maximum integer index + 1.\",\n        \"name\": \"input_dim\"\n      },\n      {\n        \"description\": \"Integer. Dimension of the dense embedding.\",\n        \"name\": \"output_dim\"\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n        the `embeddings` matrix (see `keras.regularizers`).\",\n        \"name\": \"embeddings_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to\\n        the `embeddings` matrix (see `keras.constraints`).\",\n        \"name\": \"embeddings_constraint\"\n      },\n      {\n        \"description\": \"Length of input sequences, when it is constant.\\n    This argument is required if you are going to connect\\n    `Flatten` then `Dense` layers upstream\\n    (without it, the shape of the dense outputs cannot be computed).\",\n        \"name\": \"input_length\"\n      },\n      {\n        \"description\": \"Regularizer function applied to\\n    the output of the layer (its \\\"activation\\\").\\n    (see [regularizer](https://keras.io/regularizers)).\",\n        \"name\": \"activity_regularizer\"\n      },\n      {\n        \"name\": \"sparse\",\n        \"description\": \"If True, calling this layer returns a `tf.SparseTensor`. If False,\\n    the layer returns a dense `tf.Tensor`. For an entry with no features in\\n    a sparse tensor (entry with value 0), the embedding vector of index 0 is\\n    returned by default.\"\n      },\n      {\n        \"name\": \"lora_rank\",\n        \"description\": \"Optional integer. If set, the layer's forward pass\\n        will implement LoRA (Low-Rank Adaptation)\\n        with the provided rank. LoRA sets the layer's embeddings\\n        matrix to non-trainable and replaces it with a delta over the\\n        original matrix, obtained via multiplying two lower-rank\\n        trainable matrices. This can be useful to reduce the\\n        computation cost of fine-tuning large embedding layers.\\n        You can also enable LoRA on an existing\\n        `Embedding` layer by calling `layer.enable_lora(rank)`.\"\n      },\n      {\n        \"name\": \"weights\",\n        \"description\": \"Optional floating-point matrix of size\\n        `(input_dim, output_dim)`. The initial embeddings values\\n        to use.\"\n      },\n      {\n        \"name\": \"lora_alpha\",\n        \"description\": \"Optional integer. If set, this parameter scales the\\n        low-rank adaptation delta (computed as the product of two lower-rank\\n        trainable matrices) during the forward pass. The delta is scaled by\\n        `lora_alpha / lora_rank`, allowing you to fine-tune the strength of\\n        the LoRA adjustment independently of `lora_rank`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2D tensor with shape: `(batch_size, input_length)`.\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"embeddings\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3D tensor with shape: `(batch_size, input_length, output_dim)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](http://arxiv.org/abs/1512.05287)\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> model = keras.Sequential()\\n>>> model.add(keras.layers.Embedding(1000, 64))\\n>>> # The model will take as input an integer matrix of size (batch,\\n>>> # input_length), and the largest integer (i.e. word index) in the input\\n>>> # should be no larger than 999 (vocabulary size).\\n>>> # Now model.output_shape is (None, 10, 64), where `None` is the batch\\n>>> # dimension.\\n>>> input_array = np.random.randint(1000, size=(32, 10))\\n>>> model.compile('rmsprop', 'mse')\\n>>> output_array = model.predict(input_array)\\n>>> print(output_array.shape)\\n(32, 10, 64)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Flatten\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Flattens the input. Does not affect the batch size.\\n\\nNote: If inputs are shaped `(batch,)` without a feature axis, then\\nflattening adds an extra channel dimension and output shape is `(batch, 1)`.\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"A string, one of `\\\"channels_last\\\"` (default) or\\n        `\\\"channels_first\\\"`. The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch, ..., channels)` while `\\\"channels_first\\\"` corresponds to\\n        inputs with shape `(batch, channels, ...)`.\\n        When unspecified, uses `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json` (if exists). Defaults to\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = keras.Input(shape=(10, 64))\\n>>> y = keras.layers.Flatten()(x)\\n>>> y.shape\\n(None, 640)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"GlobalAveragePooling1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Global average pooling operation for temporal data.\",\n    \"attributes\": [\n      {\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"name\": \"keepdims\",\n        \"description\": \"A boolean, whether to keep the temporal dimension or not.\\n        If `keepdims` is `False` (default), the rank of the tensor is\\n        reduced for spatial dimensions. If `keepdims` is `True`, the\\n        temporal dimension are retained with length 1.\\n        The behavior is the same as for `tf.reduce_mean` or `np.mean`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format='channels_last'`:\\n    3D tensor with shape:\\n    `(batch_size, steps, features)`\\n- If `data_format='channels_first'`:\\n    3D tensor with shape:\\n    `(batch_size, features, steps)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `keepdims=False`:\\n    2D tensor with shape `(batch_size, features)`.\\n- If `keepdims=True`:\\n    - If `data_format=\\\"channels_last\\\"`:\\n        3D tensor with shape `(batch_size, 1, features)`\\n    - If `data_format=\\\"channels_first\\\"`:\\n        3D tensor with shape `(batch_size, features, 1)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(2, 3, 4)\\n>>> y = keras.layers.GlobalAveragePooling1D()(x)\\n>>> y.shape\\n(2, 4)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"GlobalAveragePooling2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Global average pooling operation for 2D data.\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, height, weight)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"name\": \"keepdims\",\n        \"description\": \"A boolean, whether to keep the temporal dimension or not.\\n        If `keepdims` is `False` (default), the rank of the tensor is\\n        reduced for spatial dimensions. If `keepdims` is `True`, the\\n        spatial dimension are retained with length 1.\\n        The behavior is the same as for `tf.reduce_mean` or `np.mean`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format='channels_last'`:\\n    4D tensor with shape:\\n    `(batch_size, height, width, channels)`\\n- If `data_format='channels_first'`:\\n    4D tensor with shape:\\n    `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `keepdims=False`:\\n    2D tensor with shape `(batch_size, channels)`.\\n- If `keepdims=True`:\\n    - If `data_format=\\\"channels_last\\\"`:\\n        4D tensor with shape `(batch_size, 1, 1, channels)`\\n    - If `data_format=\\\"channels_first\\\"`:\\n        4D tensor with shape `(batch_size, channels, 1, 1)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(2, 4, 5, 3)\\n>>> y = keras.layers.GlobalAveragePooling2D()(x)\\n>>> y.shape\\n(2, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"GlobalMaxPooling1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Global max pooling operation for temporal data.\",\n    \"attributes\": [\n      {\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"name\": \"keepdims\",\n        \"description\": \"A boolean, whether to keep the temporal dimension or not.\\n        If `keepdims` is `False` (default), the rank of the tensor is\\n        reduced for spatial dimensions. If `keepdims` is `True`, the\\n        temporal dimension are retained with length 1.\\n        The behavior is the same as for `tf.reduce_mean` or `np.mean`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format='channels_last'`:\\n    3D tensor with shape:\\n    `(batch_size, steps, features)`\\n- If `data_format='channels_first'`:\\n    3D tensor with shape:\\n    `(batch_size, features, steps)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `keepdims=False`:\\n    2D tensor with shape `(batch_size, features)`.\\n- If `keepdims=True`:\\n    - If `data_format=\\\"channels_last\\\"`:\\n        3D tensor with shape `(batch_size, 1, features)`\\n    - If `data_format=\\\"channels_first\\\"`:\\n        3D tensor with shape `(batch_size, features, 1)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(2, 3, 4)\\n>>> y = keras.layers.GlobalMaxPooling1D()(x)\\n>>> y.shape\\n(2, 4)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"GlobalMaxPooling2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Global max pooling operation for 2D data.\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, height, weight)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"name\": \"keepdims\",\n        \"description\": \"A boolean, whether to keep the temporal dimension or not.\\n        If `keepdims` is `False` (default), the rank of the tensor is\\n        reduced for spatial dimensions. If `keepdims` is `True`, the\\n        spatial dimension are retained with length 1.\\n        The behavior is the same as for `tf.reduce_mean` or `np.mean`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format='channels_last'`:\\n    4D tensor with shape:\\n    `(batch_size, height, width, channels)`\\n- If `data_format='channels_first'`:\\n    4D tensor with shape:\\n    `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `keepdims=False`:\\n    2D tensor with shape `(batch_size, channels)`.\\n- If `keepdims=True`:\\n    - If `data_format=\\\"channels_last\\\"`:\\n        4D tensor with shape `(batch_size, 1, 1, channels)`\\n    - If `data_format=\\\"channels_first\\\"`:\\n        4D tensor with shape `(batch_size, channels, 1, 1)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(2, 4, 5, 3)\\n>>> y = keras.layers.GlobalMaxPooling2D()(x)\\n>>> y.shape\\n(2, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"GRU\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Gated Recurrent Unit - Cho et al. 2014.\\n\\nBased on available runtime hardware and constraints, this layer\\nwill choose different implementations (cuDNN-based or backend-native)\\nto maximize the performance. If a GPU is available and all\\nthe arguments to the layer meet the requirement of the cuDNN kernel\\n(see below for details), the layer will use a fast cuDNN implementation\\nwhen using the TensorFlow backend.\\n\\nThe requirements to use the cuDNN implementation are:\\n\\n1. `activation` == `tanh`\\n2. `recurrent_activation` == `sigmoid`\\n3. `recurrent_dropout` == 0\\n4. `unroll` is `False`\\n5. `use_bias` is `True`\\n6. `reset_after` is `True`\\n7. Inputs, if use masking, are strictly right-padded.\\n8. Eager execution is enabled in the outermost context.\\n\\nThere are two variants of the GRU implementation. The default one is based\\non [v3](https://arxiv.org/abs/1406.1078v3) and has reset gate applied to\\nhidden state before matrix multiplication. The other one is based on\\n[original](https://arxiv.org/abs/1406.1078v1) and has the order reversed.\\n\\nThe second variant is compatible with CuDNNGRU (GPU-only) and allows\\ninference on CPU. Thus it has separate biases for `kernel` and\\n`recurrent_kernel`. To use this variant, set `reset_after=True` and\\n`recurrent_activation='sigmoid'`.\\n\\nFor example:\\n\\n```\\n>>> inputs = np.random.random((32, 10, 8))\\n>>> gru = keras.layers.GRU(4)\\n>>> output = gru(inputs)\\n>>> output.shape\\n(32, 4)\\n>>> gru = keras.layers.GRU(4, return_sequences=True, return_state=True)\\n>>> whole_sequence_output, final_state = gru(inputs)\\n>>> whole_sequence_output.shape\\n(32, 10, 4)\\n>>> final_state.shape\\n(32, 4)\\n```\",\n    \"attributes\": [\n      {\n        \"default\": \"tanh\",\n        \"description\": \"Activation function to use.\\n        Default: hyperbolic tangent (`tanh`).\\n        If you pass `None`, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"hard_sigmoid\",\n        \"description\": \"Activation function to use\\n        for the recurrent step.\\n        Default: sigmoid (`sigmoid`).\\n        If you pass `None`, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"recurrent_activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean, (default `True`), whether the layer\\n        should use a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs. Default:\\n        `\\\"glorot_uniform\\\"`.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Orthogonal\",\n          \"config\": {\n            \"gain\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the `recurrent_kernel`\\n        weights matrix, used for the linear transformation of the recurrent\\n        state. Default: `\\\"orthogonal\\\"`.\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector. Default: `\\\"zeros\\\"`.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        linear transformation of the inputs. Default: 0.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"Implementation mode, either 1 or 2.\\n    Mode 1 will structure its operations as a larger number of\\n    smaller dot products and additions, whereas mode 2 will\\n    batch them into fewer, larger operations. These modes will\\n    have different performance profiles on different hardware and\\n    for different applications. Default: 2.\",\n        \"name\": \"implementation\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean. Whether to return the last output\\n        in the output sequence, or the full sequence. Default: `False`.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean. Whether to return the last state in addition\\n        to the output. Default: `False`.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default `False`).\\n        If `True`, process the input sequence backwards and return the\\n        reversed sequence.\",\n        \"name\": \"go_backwards\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`). If `True`, the last state\\n        for each sample at index i in a batch will be used as initial\\n        state for the sample of index i in the following batch.\",\n        \"name\": \"stateful\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`).\\n        If `True`, the network will be unrolled,\\n        else a symbolic loop will be used.\\n        Unrolling can speed-up a RNN,\\n        although it tends to be more memory-intensive.\\n        Unrolling is only suitable for short sequences.\",\n        \"name\": \"unroll\"\n      },\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the output of the\\n        layer (its \\\"activation\\\"). Default: `None`.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop\\n        for the linear transformation of the recurrent state. Default: 0.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"description\": \"`None`.\",\n        \"name\": \"Default\"\n      },\n      {\n        \"description\": \"GRU convention (whether to apply reset gate after or\\n        before matrix multiplication). `False` is `\\\"before\\\"`,\\n        `True` is `\\\"after\\\"` (default and cuDNN compatible).\",\n        \"name\": \"reset_after\"\n      },\n      {\n        \"description\": \"The shape format of the `inputs` and `outputs` tensors.\\n    If True, the inputs and outputs will be in shape\\n    `[timesteps, batch, feature]`, whereas in the False case, it will be\\n    `[batch, timesteps, feature]`. Using `time_major = True` is a bit more\\n    efficient because it avoids transposes at the beginning and end of the\\n    RNN calculation. However, most TensorFlow data is batch-major, so by\\n    default this function accepts input and emits output in batch-major\\n    form.\",\n        \"name\": \"time_major\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Random seed for dropout.\"\n      },\n      {\n        \"name\": \"use_cudnn\",\n        \"description\": \"Whether to use a cuDNN-backed implementation. `\\\"auto\\\"` will\\n        attempt to use cuDNN when feasible, and will fallback to the\\n        default implementation if not.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"recurrent_kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation](https://arxiv.org/abs/1406.1078)\"\n      },\n      {\n        \"description\": \"[On the Properties of Neural Machine Translation: Encoder-Decoder Approaches](https://arxiv.org/abs/1409.1259)\"\n      },\n      {\n        \"description\": \"[Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling](https://arxiv.org/abs/1412.3555v1)\"\n      },\n      {\n        \"description\": \"[A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](https://arxiv.org/abs/1512.05287)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"GRUCell\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Cell class for the GRU layer.\\n\\nThis class processes one step within the whole time sequence input, whereas\\n`keras.layer.GRU` processes the whole sequence.\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Activation function to use. Default: hyperbolic tangent\\n        (`tanh`). If you pass None, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"Activation function to use for the recurrent step.\\n        Default: sigmoid (`sigmoid`). If you pass `None`, no activation is\\n        applied (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"recurrent_activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean, (default `True`), whether the layer\\n        should use a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs. Default:\\n        `\\\"glorot_uniform\\\"`.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel`\\n        weights matrix, used for the linear transformation\\n        of the recurrent state. Default: `\\\"orthogonal\\\"`.\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector. Default: `\\\"zeros\\\"`.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        linear transformation of the inputs. Default: 0.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop\\n        for the linear transformation of the recurrent state. Default: 0.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"description\": \"Implementation mode, either 1 or 2.\\n    Mode 1 will structure its operations as a larger number of\\n    smaller dot products and additions, whereas mode 2 (default) will\\n    batch them into fewer, larger operations. These modes will\\n    have different performance profiles on different hardware and\\n    for different applications. Default: 2.\",\n        \"name\": \"implementation\"\n      },\n      {\n        \"description\": \"`None`.\",\n        \"name\": \"Default\"\n      },\n      {\n        \"description\": \"GRU convention (whether to apply reset gate after or\\n        before matrix multiplication). False = \\\"before\\\",\\n        True = \\\"after\\\" (default and cuDNN compatible).\",\n        \"name\": \"reset_after\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Random seed for dropout.\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> inputs = np.random.random((32, 10, 8))\\n>>> rnn = keras.layers.RNN(keras.layers.GRUCell(4))\\n>>> output = rnn(inputs)\\n>>> output.shape\\n(32, 4)\\n>>> rnn = keras.layers.RNN(\\n...    keras.layers.GRUCell(4),\\n...    return_sequences=True,\\n...    return_state=True)\\n>>> whole_sequence_output, final_state = rnn(inputs)\\n>>> whole_sequence_output.shape\\n(32, 10, 4)\\n>>> final_state.shape\\n(32, 4)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"HardSigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"InputLayer\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Data\",\n    \"description\": \"Layer to be used as an entry point into a Network (a graph of layers).\\n\\nIt can either wrap an existing tensor (pass an `input_tensor` argument)\\nor create a placeholder tensor (pass arguments `input_shape`, and\\noptionally, `dtype`).\\n\\nIt is generally recommend to use the Keras Functional model via `Input`,\\n(which creates an `InputLayer`) without directly using `InputLayer`.\\n\\nWhen using `InputLayer` with the Keras Sequential model, it can be skipped\\nby moving the `input_shape` parameter to the first layer after the\\n`InputLayer`.\\n\\nThis class can create placeholders for `tf.Tensors`, `tf.SparseTensors`, and\\n`tf.RaggedTensors` by choosing `sparse=True` or `ragged=True`. Note that\\n`sparse` and `ragged` can't be configured to `True` at the same time.\",\n    \"attributes\": [\n      {\n        \"description\": \"Shape tuple (not including the batch axis), or\\n        `TensorShape` instance (not including the batch axis).\",\n        \"name\": \"input_shape\"\n      },\n      {\n        \"description\": \"Optional input batch size (integer or `None`).\",\n        \"name\": \"batch_size\"\n      },\n      {\n        \"description\": \"Optional datatype of the input. When not provided, the Keras\\n        default `float` type will be used.\",\n        \"name\": \"dtype\"\n      },\n      {\n        \"description\": \"Optional tensor to use as layer input. If set, the layer\\n        will use the `tf.TypeSpec` of this tensor rather\\n        than creating a new placeholder tensor.\",\n        \"name\": \"input_tensor\"\n      },\n      {\n        \"description\": \"Boolean, whether the placeholder created is meant to be sparse.\\n        Defaults to `False`.\",\n        \"name\": \"sparse\"\n      },\n      {\n        \"description\": \"Boolean, whether the placeholder created is meant to be ragged.\\n        In this case, values of `None` in the `shape` argument represent\\n        ragged dimensions. For more information about `tf.RaggedTensor`, see\\n        [this guide](https://www.tensorflow.org/guide/ragged_tensor).\\n        Defaults to `False`.\",\n        \"name\": \"ragged\"\n      },\n      {\n        \"description\": \"Optional name of the layer (string).\",\n        \"name\": \"name\"\n      },\n      {\n        \"description\": \"A `tf.TypeSpec` object to create Input from. This\\n        `tf.TypeSpec` represents the entire batch. When provided, all other\\n        args except name must be `None`.\",\n        \"name\": \"type_spec\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"# With explicit InputLayer.\\nmodel = tf.keras.Sequential([\\n  tf.keras.layers.InputLayer(input_shape=(4,)),\\n  tf.keras.layers.Dense(8)])\\nmodel.compile(tf.keras.optimizers.RMSprop(0.001), loss='mse')\\nmodel.fit(np.zeros((10, 4)),\\n          np.ones((10, 8)))\\n\\n# Without InputLayer and let the first layer to have the input_shape.\\n# Keras will add a input for the model behind the scene.\\nmodel = tf.keras.Sequential([\\n  tf.keras.layers.Dense(8, input_shape=(4,))])\\nmodel.compile(tf.keras.optimizers.RMSprop(0.001), loss='mse')\\nmodel.fit(np.zeros((10, 4)),\\n          np.ones((10, 8)))\"\n      }\n    ]\n  },\n  {\n    \"name\": \"InputSpec\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Data\",\n    \"description\": \"Specifies the rank, dtype and shape of every input to a layer.\\n\\nLayers can expose (if appropriate) an `input_spec` attribute:\\nan instance of `InputSpec`, or a nested structure of `InputSpec` instances\\n(one per input tensor). These objects enable the layer to run input\\ncompatibility checks for input structure, input rank, input shape, and\\ninput dtype for the first argument of `Layer.__call__`.\\n\\nA `None` entry in a shape is compatible with any dimension.\",\n    \"attributes\": [\n      {\n        \"description\": \"Expected dtype of the input.\",\n        \"name\": \"dtype\"\n      },\n      {\n        \"description\": \"Shape tuple, expected shape of the input\\n        (may include `None` for dynamic axes).\\n        Includes the batch size.\",\n        \"name\": \"shape\"\n      },\n      {\n        \"description\": \"Integer, expected rank of the input.\",\n        \"name\": \"ndim\"\n      },\n      {\n        \"description\": \"Integer, maximum rank of the input.\",\n        \"name\": \"max_ndim\"\n      },\n      {\n        \"description\": \"Integer, minimum rank of the input.\",\n        \"name\": \"min_ndim\"\n      },\n      {\n        \"description\": \"Dictionary mapping integer axes to\\n        a specific dimension value.\",\n        \"name\": \"axes\"\n      },\n      {\n        \"description\": \"If `True`, allow inputs of rank N+1 as long\\n        as the last axis of the input is 1, as well as inputs of rank N-1\\n        as long as the last axis of the spec is 1.\",\n        \"name\": \"allow_last_axis_squeeze\"\n      },\n      {\n        \"description\": \"Expected key corresponding to this input when passing data as\\n        a dictionary.\",\n        \"name\": \"name\"\n      },\n      {\n        \"name\": \"optional\",\n        \"description\": \"Boolean, whether the input is optional or not.\\n        An optional input can accept `None` values.\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"class MyLayer(Layer):\\n    def __init__(self):\\n        super().__init__()\\n        # The layer will accept inputs with\\n        # shape (*, 28, 28) & (*, 28, 28, 1)\\n        # and raise an appropriate error message otherwise.\\n        self.input_spec = InputSpec(\\n            shape=(None, 28, 28, 1),\\n            allow_last_axis_squeeze=True)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Lambda\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Wraps arbitrary expressions as a `Layer` object.\\n\\nThe `Lambda` layer exists so that arbitrary expressions can be used\\nas a `Layer` when constructing Sequential\\nand Functional API models. `Lambda` layers are best suited for simple\\noperations or quick experimentation. For more advanced use cases,\\nprefer writing new subclasses of `Layer`.\\n\\nWARNING: `Lambda` layers have (de)serialization limitations!\\n\\nThe main reason to subclass `Layer` instead of using a\\n`Lambda` layer is saving and inspecting a model. `Lambda` layers\\nare saved by serializing the Python bytecode, which is fundamentally\\nnon-portable and potentially unsafe.\\nThey should only be loaded in the same environment where\\nthey were saved. Subclassed layers can be saved in a more portable way\\nby overriding their `get_config()` method. Models that rely on\\nsubclassed Layers are also often easier to visualize and reason about.\",\n    \"attributes\": [\n      {\n        \"description\": \"The function to be evaluated. Takes input tensor as first\\n        argument.\",\n        \"name\": \"function\"\n      },\n      {\n        \"description\": \"Expected output shape from function. This argument\\n        can usually be inferred if not explicitly provided.\\n        Can be a tuple or function. If a tuple, it only specifies\\n        the first dimension onward; sample dimension is assumed\\n        either the same as the input:\\n        `output_shape = (input_shape[0], ) + output_shape` or,\\n        the input is `None` and the sample dimension is also `None`:\\n        `output_shape = (None, ) + output_shape`.\\n        If a function, it specifies the\\n        entire shape as a function of the input shape:\\n        `output_shape = f(input_shape)`.\",\n        \"name\": \"output_shape\"\n      },\n      {\n        \"description\": \"Optional dictionary of keyword arguments to be passed to the\\n        function.\",\n        \"name\": \"arguments\"\n      },\n      {\n        \"description\": \"Either None (indicating no masking) or a callable with the same\\n        signature as the `compute_mask` layer method, or a tensor\\n        that will be returned as output mask regardless\\n        of what the input is.\",\n        \"name\": \"mask\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument input_shape (tuple of\\nintegers, does not include the samples axis) when using this layer as the\\nfirst layer in a model.\",\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Specified by `output_shape` argument\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"# add a x -> x^2 layer\\nmodel.add(Lambda(lambda x: x ** 2))\"\n      }\n    ]\n  },\n  {\n    \"name\": \"LeakyReLU\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Leaky version of a Rectified Linear Unit activation layer.\\n\\nThis layer allows a small gradient when the unit is not active.\\n\\nFormula:\\n\\n``` python\\nf(x) = alpha * x if x < 0\\nf(x) = x if x >= 0\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"Float >= `0.`. Negative slope coefficient. Defaults to `0.3`.\",\n        \"name\": \"alpha\"\n      },\n      {\n        \"name\": \"negative_slope\",\n        \"description\": \"Float >= 0.0. Negative slope coefficient.\\n      Defaults to `0.3`.\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments, such as\\n        `name` and `dtype`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the batch axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Rectifier Nonlinearities Improve Neural Network Acoustic Models]( https://ai.stanford.edu/~amaas/papers/relu_hybrid_icml2013_final.pdf)\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"leaky_relu_layer = LeakyReLU(negative_slope=0.5)\\ninput = np.array([-10, -5, 0.0, 5, 10])\\nresult = leaky_relu_layer(input)\\n# result = [-5. , -2.5,  0. ,  5. , 10.]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"LocallyConnected1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Locally-connected layer for 1D inputs.\\n\\nThe `LocallyConnected1D` layer works similarly to\\nthe `Conv1D` layer, except that weights are unshared,\\nthat is, a different set of filters is applied at each different patch\\nof the input.\\n\\nNote: layer attributes cannot be modified after the layer has been called\\nonce (except the `trainable` attribute).\",\n    \"attributes\": [\n      {\n        \"description\": \"Integer, the dimensionality of the output space (i.e. the\\n      number of output filters in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"An integer or tuple/list of a single integer, specifying\\n      the length of the 1D convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"An integer or tuple/list of a single integer, specifying the\\n      stride length of the convolution.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"Currently only supports `\\\"valid\\\"` (case-insensitive). `\\\"same\\\"`\\n      may be supported in the future. `\\\"valid\\\"` means no padding.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"description\": \"Activation function to use. If you don't specify anything,\\n      no activation is applied (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"Boolean, whether the layer uses a bias vector.\",\n        \"name\": \"use_bias\"\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n      matrix.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the output of the\\n      layer (its \\\"activation\\\")..\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the kernel matrix.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"A string, one of `channels_last` (default) or\\n      `channels_first`. The ordering of the dimensions in the inputs.\\n      `channels_last` corresponds to inputs with shape `(batch, length,\\n      channels)` while `channels_first` corresponds to inputs with shape\\n      `(batch, channels, length)`. When unspecified, uses\\n      `image_data_format` value found in your Keras config file at\\n      `~/.keras/keras.json` (if exists) else 'channels_last'.\\n      Defaults to 'channels_last'.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"implementation mode, either `1`, `2`, or `3`. `1` loops\\n      over input spatial locations to perform the forward pass. It is\\n      memory-efficient but performs a lot of (small) ops.  `2` stores layer\\n      weights in a dense but sparsely-populated 2D matrix and implements the\\n      forward pass as a single matrix-multiply. It uses a lot of RAM but\\n      performs few (large) ops.  `3` stores layer weights in a sparse tensor\\n      and implements the forward pass as a single sparse matrix-multiply.\\n        How to choose:\\n        `1`: large, dense models,\\n        `2`: small models,\\n        `3`: large, sparse models,  where \\\"large\\\" stands for large\\n          input/output activations (i.e. many `filters`, `input_filters`,\\n          large `input_size`, `output_size`), and \\\"sparse\\\" stands for few\\n          connections between inputs and outputs, i.e. small ratio\\n          `filters * input_filters * kernel_size / (input_size * strides)`,\\n          where inputs to and outputs of the layer are assumed to have\\n          shapes `(input_size, input_filters)`, `(output_size, filters)`\\n          respectively.  It is recommended to benchmark each in the setting\\n          of interest to pick the most efficient one (in terms of speed and\\n          memory usage). Correct choice of implementation can lead to\\n          dramatic speed improvements (e.g. 50X), potentially at the expense\\n          of RAM.  Also, only `padding=\\\"valid\\\"` is supported by\\n          `implementation=1`.\",\n        \"name\": \"implementation\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D tensor with shape: `(batch_size, steps, input_dim)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3D tensor with shape: `(batch_size, new_steps, filters)` `steps` value\\n  might have changed due to padding or strides.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"    # apply a unshared weight convolution 1d of length 3 to a sequence with\\n    # 10 timesteps, with 64 output filters\\n    model = Sequential()\\n    model.add(LocallyConnected1D(64, 3, input_shape=(10, 32)))\\n    # now model.output_shape == (None, 8, 64)\\n    # add a new conv1d on top\\n    model.add(LocallyConnected1D(32, 3))\\n    # now model.output_shape == (None, 6, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"LocallyConnected2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Locally-connected layer for 2D inputs.\\n\\nThe `LocallyConnected2D` layer works similarly\\nto the `Conv2D` layer, except that weights are unshared,\\nthat is, a different set of filters is applied at each\\ndifferent patch of the input.\\n\\nNote: layer attributes cannot be modified after the layer has been called\\nonce (except the `trainable` attribute).\",\n    \"attributes\": [\n      {\n        \"description\": \"Integer, the dimensionality of the output space (i.e. the\\n      number of output filters in the convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"An integer or tuple/list of 2 integers, specifying the\\n      width and height of the 2D convolution window. Can be a single integer\\n      to specify the same value for all spatial dimensions.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"An integer or tuple/list of 2 integers, specifying the strides\\n      of the convolution along the width and height. Can be a single integer\\n      to specify the same value for all spatial dimensions.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"Currently only support `\\\"valid\\\"` (case-insensitive). `\\\"same\\\"`\\n      will be supported in future. `\\\"valid\\\"` means no padding.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"A string, one of `channels_last` (default) or\\n      `channels_first`. The ordering of the dimensions in the inputs.\\n      `channels_last` corresponds to inputs with shape `(batch, height,\\n        width, channels)` while `channels_first` corresponds to inputs with\\n        shape\\n      `(batch, channels, height, width)`. When unspecified, uses\\n      `image_data_format` value found in your Keras config file at\\n      `~/.keras/keras.json` (if exists) else 'channels_last'.\\n      Defaults to 'channels_last'.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"Activation function to use. If you don't specify anything,\\n      no activation is applied (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"Boolean, whether the layer uses a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n      matrix.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the output of the\\n      layer (its \\\"activation\\\").\",\n        \"name\": \"activity_regularizer\"\n      },\n      {\n        \"description\": \"Constraint function applied to the kernel matrix.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"implementation mode, either `1`, `2`, or `3`. `1` loops\\n      over input spatial locations to perform the forward pass. It is\\n      memory-efficient but performs a lot of (small) ops.  `2` stores layer\\n      weights in a dense but sparsely-populated 2D matrix and implements the\\n      forward pass as a single matrix-multiply. It uses a lot of RAM but\\n      performs few (large) ops.  `3` stores layer weights in a sparse tensor\\n      and implements the forward pass as a single sparse matrix-multiply.\\n        How to choose:\\n        `1`: large, dense models,\\n        `2`: small models,\\n        `3`: large, sparse models,  where \\\"large\\\" stands for large\\n          input/output activations (i.e. many `filters`, `input_filters`,\\n          large `np.prod(input_size)`, `np.prod(output_size)`), and \\\"sparse\\\"\\n          stands for few connections between inputs and outputs, i.e. small\\n          ratio `filters * input_filters * np.prod(kernel_size) /\\n          (np.prod(input_size) * np.prod(strides))`, where inputs to and\\n          outputs of the layer are assumed to have shapes `input_size +\\n          (input_filters,)`, `output_size + (filters,)` respectively. It is\\n          recommended to benchmark each in the setting of interest to pick\\n          the most efficient one (in terms of speed and memory usage).\\n          Correct choice of implementation can lead to dramatic speed\\n          improvements (e.g. 50X), potentially at the expense of RAM. Also,\\n          only `padding=\\\"valid\\\"` is supported by `implementation=1`.\",\n        \"name\": \"implementation\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D tensor with shape: `(samples, channels, rows, cols)` if\\n  data_format='channels_first'\\nor 4D tensor with shape: `(samples, rows, cols, channels)` if\\n  data_format='channels_last'.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D tensor with shape: `(samples, filters, new_rows, new_cols)` if\\n  data_format='channels_first'\\nor 4D tensor with shape: `(samples, new_rows, new_cols, filters)` if\\n  data_format='channels_last'. `rows` and `cols` values might have\\n  changed due to padding.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"    # apply a 3x3 unshared weights convolution with 64 output filters on a\\n    32x32 image\\n    # with `data_format=\\\"channels_last\\\"`:\\n    model = Sequential()\\n    model.add(LocallyConnected2D(64, (3, 3), input_shape=(32, 32, 3)))\\n    # now model.output_shape == (None, 30, 30, 64)\\n    # notice that this layer will consume (30*30)*(3*3*3*64) + (30*30)*64\\n    parameters\\n\\n    # add a 3x3 unshared weights convolution on top, with 32 output filters:\\n    model.add(LocallyConnected2D(32, (3, 3)))\\n    # now model.output_shape == (None, 28, 28, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Long Short-Term Memory layer - Hochreiter 1997.\\n\\nBased on available runtime hardware and constraints, this layer\\nwill choose different implementations (cuDNN-based or backend-native)\\nto maximize the performance. If a GPU is available and all\\nthe arguments to the layer meet the requirement of the cuDNN kernel\\n(see below for details), the layer will use a fast cuDNN implementation\\nwhen using the TensorFlow backend.\\nThe requirements to use the cuDNN implementation are:\\n\\n1. `activation` == `tanh`\\n2. `recurrent_activation` == `sigmoid`\\n3. `recurrent_dropout` == 0\\n4. `unroll` is `False`\\n5. `use_bias` is `True`\\n6. Inputs, if use masking, are strictly right-padded.\\n7. Eager execution is enabled in the outermost context.\\n\\nFor example:\\n\\n```\\n>>> inputs = np.random.random((32, 10, 8))\\n>>> lstm = keras.layers.LSTM(4)\\n>>> output = lstm(inputs)\\n>>> output.shape\\n(32, 4)\\n>>> lstm = keras.layers.LSTM(\\n...     4, return_sequences=True, return_state=True)\\n>>> whole_seq_output, final_memory_state, final_carry_state = lstm(inputs)\\n>>> whole_seq_output.shape\\n(32, 10, 4)\\n>>> final_memory_state.shape\\n(32, 4)\\n>>> final_carry_state.shape\\n(32, 4)\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"default\": \"tanh\",\n        \"description\": \"Activation function to use.\\n        Default: hyperbolic tangent (`tanh`).\\n        If you pass `None`, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"hard_sigmoid\",\n        \"description\": \"Activation function to use\\n        for the recurrent step.\\n        Default: sigmoid (`sigmoid`).\\n        If you pass `None`, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"recurrent_activation\"\n      },\n      {\n        \"description\": \"Boolean, (default `True`), whether the layer\\n        should use a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs. Default:\\n        `\\\"glorot_uniform\\\"`.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel`\\n        weights matrix, used for the linear transformation of the recurrent\\n        state. Default: `\\\"orthogonal\\\"`.\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector. Default: `\\\"zeros\\\"`.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean (default `True`). If `True`,\\n        add 1 to the bias of the forget gate at initialization.\\n        Setting it to `True` will also force `bias_initializer=\\\"zeros\\\"`.\\n        This is recommended in [Jozefowicz et al.](\\n        https://github.com/mlresearch/v37/blob/gh-pages/jozefowicz15.pdf)\",\n        \"name\": \"unit_forget_bias\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the output of the\\n        layer (its \\\"activation\\\"). Default: `None`.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_constraint\",\n        \"visible\": false\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        linear transformation of the inputs. Default: 0.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop\\n        for the linear transformation of the recurrent state. Default: 0.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"Implementation mode, either 1 or 2. Mode 1 will structure\\n    its operations as a larger number of smaller dot products and additions,\\n    whereas mode 2 will batch them into fewer, larger operations. These modes\\n    will have different performance profiles on different hardware and for\\n    different applications. Default: 2.\",\n        \"name\": \"implementation\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean. Whether to return the last output\\n        in the output sequence, or the full sequence. Default: `False`.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean. Whether to return the last state in addition\\n        to the output. Default: `False`.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`).\\n        If `True`, process the input sequence backwards and return the\\n        reversed sequence.\",\n        \"name\": \"go_backwards\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`). If `True`, the last state\\n        for each sample at index i in a batch will be used as initial\\n        state for the sample of index i in the following batch.\",\n        \"name\": \"stateful\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default False).\\n        If `True`, the network will be unrolled,\\n        else a symbolic loop will be used.\\n        Unrolling can speed-up a RNN,\\n        although it tends to be more memory-intensive.\\n        Unrolling is only suitable for short sequences.\",\n        \"name\": \"unroll\"\n      },\n      {\n        \"description\": \"`None`.\",\n        \"name\": \"Default\"\n      },\n      {\n        \"description\": \"The shape format of the `inputs` and `outputs` tensors.\\n    If True, the inputs and outputs will be in shape\\n    `[timesteps, batch, feature]`, whereas in the False case, it will be\\n    `[batch, timesteps, feature]`. Using `time_major = True` is a bit more\\n    efficient because it avoids transposes at the beginning and end of the\\n    RNN calculation. However, most TensorFlow data is batch-major, so by\\n    default this function accepts input and emits output in batch-major\\n    form.\",\n        \"name\": \"time_major\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Random seed for dropout.\"\n      },\n      {\n        \"name\": \"use_cudnn\",\n        \"description\": \"Whether to use a cuDNN-backed implementation. `\\\"auto\\\"` will\\n        attempt to use cuDNN when feasible, and will fallback to the\\n        default implementation if not.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"recurrent_kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Long short-term memory](http://www.bioinf.jku.at/publications/older/2604.pdf)\"\n      },\n      {\n        \"description\": \"[Learning to forget: Continual prediction with LSTM](http://www.mitpressjournals.org/doi/pdf/10.1162/089976600300015015)\"\n      },\n      {\n        \"description\": \"[Supervised sequence labeling with recurrent neural networks](http://www.cs.toronto.edu/~graves/preprint.pdf)\"\n      },\n      {\n        \"description\": \"[A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](https://arxiv.org/abs/1512.05287)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"LSTMCell\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Cell class for the LSTM layer.\\n\\nThis class processes one step within the whole time sequence input, whereas\\n`keras.layer.LSTM` processes the whole sequence.\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Activation function to use. Default: hyperbolic tangent\\n        (`tanh`). If you pass None, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"Activation function to use for the recurrent step.\\n        Default: sigmoid (`sigmoid`). If you pass `None`, no activation is\\n        applied (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"recurrent_activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean, (default `True`), whether the layer\\n        should use a bias vector.\",\n        \"name\": \"use_bias\"\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs. Default:\\n        `\\\"glorot_uniform\\\"`.\",\n        \"name\": \"kernel_initializer\"\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel`\\n        weights matrix, used for the linear transformation\\n        of the recurrent state. Default: `\\\"orthogonal\\\"`.\",\n        \"name\": \"recurrent_initializer\"\n      },\n      {\n        \"description\": \"Initializer for the bias vector. Default: `\\\"zeros\\\"`.\",\n        \"name\": \"bias_initializer\"\n      },\n      {\n        \"description\": \"Boolean (default `True`). If `True`,\\n        add 1 to the bias of the forget gate at initialization.\\n        Setting it to `True` will also force `bias_initializer=\\\"zeros\\\"`.\\n        This is recommended in [Jozefowicz et al.](\\n        https://github.com/mlresearch/v37/blob/gh-pages/jozefowicz15.pdf)\",\n        \"name\": \"unit_forget_bias\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_regularizer\"\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        linear transformation of the inputs. Default: 0.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop\\n        for the linear transformation of the recurrent state. Default: 0.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"description\": \"Implementation mode, either 1 or 2.\\n    Mode 1 will structure its operations as a larger number of smaller dot\\n    products and additions, whereas mode 2 (default) will batch them into\\n    fewer, larger operations. These modes will have different performance\\n    profiles on different hardware and for different applications. Default: 2.\",\n        \"name\": \"implementation\"\n      },\n      {\n        \"description\": \"`None`.\",\n        \"name\": \"Default\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Random seed for dropout.\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> inputs = np.random.random((32, 10, 8))\\n>>> rnn = keras.layers.RNN(keras.layers.LSTMCell(4))\\n>>> output = rnn(inputs)\\n>>> output.shape\\n(32, 4)\\n>>> rnn = keras.layers.RNN(\\n...    keras.layers.LSTMCell(4),\\n...    return_sequences=True,\\n...    return_state=True)\\n>>> whole_sequence_output, final_state = rnn(inputs)\\n>>> whole_sequence_output.shape\\n(32, 10, 4)\\n>>> final_state.shape\\n(32, 4)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Masking\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Masks a sequence by using a mask value to skip timesteps.\\n\\nFor each timestep in the input tensor (dimension #1 in the tensor),\\nif all values in the input tensor at that timestep\\nare equal to `mask_value`, then the timestep will be masked (skipped)\\nin all downstream layers (as long as they support masking).\\n\\nIf any downstream layer does not support masking yet receives such\\nan input mask, an exception will be raised.\",\n    \"attributes\": [\n      {\n        \"description\": \"Either None or mask value to skip\\n\",\n        \"name\": \"mask_value\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"summary\": \"Consider a NumPy data array `x` of shape `(samples, timesteps, features)`,\\nto be fed to an LSTM layer. You want to mask timestep #3 and #5 because you\\nlack data for these timesteps. You can:\\n- Set `x[:, 3, :] = 0.` and `x[:, 5, :] = 0.`\\n- Insert a `Masking` layer with `mask_value=0.` before the LSTM layer:\",\n        \"code\": \"samples, timesteps, features = 32, 10, 8\\ninputs = np.random.random([samples, timesteps, features]).astype(np.float32)\\ninputs[:, 3, :] = 0.\\ninputs[:, 5, :] = 0.\\n\\nmodel = keras.models.Sequential()\\nmodel.add(keras.layers.Masking(mask_value=0.0))\\nmodel.add(keras.layers.LSTM(32))\\noutput = model(inputs)\\n# The time step 3 and 5 will be skipped from LSTM calculation.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Maximum\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Tensor\",\n    \"description\": \"Computes element-wise maximum on a list of inputs.\\n\\nIt takes as input a list of tensors, all of the same shape,\\nand returns a single tensor (also of the same shape).\",\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 3, 4)\\n>>> x1 = np.random.rand(*input_shape)\\n>>> x2 = np.random.rand(*input_shape)\\n>>> y = keras.layers.Maximum()([x1, x2])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> input1 = keras.layers.Input(shape=(16,))\\n>>> x1 = keras.layers.Dense(8, activation='relu')(input1)\\n>>> input2 = keras.layers.Input(shape=(32,))\\n>>> x2 = keras.layers.Dense(8, activation='relu')(input2)\\n>>> # equivalent to `y = keras.layers.maximum([x1, x2])`\\n>>> y = keras.layers.Maximum()([x1, x2])\\n>>> out = keras.layers.Dense(4)(y)\\n>>> model = keras.models.Model(inputs=[input1, input2], outputs=out)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MaxPooling1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Max pooling operation for 1D temporal data.\\n\\nDownsamples the input representation by taking the maximum value over a\\nspatial window of size `pool_size`. The window is shifted by `strides`.\\n\\nThe resulting output when using the `\\\"valid\\\"` padding option has a shape of:\\n`output_shape = (input_shape - pool_size + 1) / strides)`.\\n\\nThe resulting output shape when using the `\\\"same\\\"` padding option is:\\n`output_shape = input_shape / strides`\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": \"valid\",\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": [\n          2,\n          2\n        ],\n        \"description\": \"int, size of the max pooling window.\",\n        \"name\": \"pool_size\"\n      },\n      {\n        \"default\": [\n          2,\n          2\n        ],\n        \"description\": \"int or None. Specifies how much the pooling window moves\\n        for each pooling step. If None, it will default to `pool_size`.\",\n        \"name\": \"strides\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    3D tensor with shape `(batch_size, steps, features)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    3D tensor with shape `(batch_size, features, steps)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    3D tensor with shape `(batch_size, downsampled_steps, features)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    3D tensor with shape `(batch_size, features, downsampled_steps)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"summary\": \"`strides=1` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([1., 2., 3., 4., 5.])\\n>>> x = np.reshape(x, [1, 5, 1])\\n>>> max_pool_1d = keras.layers.MaxPooling1D(pool_size=2,\\n...    strides=1, padding=\\\"valid\\\")\\n>>> max_pool_1d(x)\"\n      },\n      {\n        \"summary\": \"`strides=2` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([1., 2., 3., 4., 5.])\\n>>> x = np.reshape(x, [1, 5, 1])\\n>>> max_pool_1d = keras.layers.MaxPooling1D(pool_size=2,\\n...    strides=2, padding=\\\"valid\\\")\\n>>> max_pool_1d(x)\"\n      },\n      {\n        \"summary\": \"`strides=1` and `padding=\\\"same\\\"`:\",\n        \"code\": \">>> x = np.array([1., 2., 3., 4., 5.])\\n>>> x = np.reshape(x, [1, 5, 1])\\n>>> max_pool_1d = keras.layers.MaxPooling1D(pool_size=2,\\n...    strides=1, padding=\\\"same\\\")\\n>>> max_pool_1d(x)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MaxPooling2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Max pooling operation for 2D spatial data.\\n\\nDownsamples the input along its spatial dimensions (height and width)\\nby taking the maximum value over an input window\\n(of size defined by `pool_size`) for each channel of the input.\\nThe window is shifted by `strides` along each dimension.\\n\\nThe resulting output when using the `\\\"valid\\\"` padding option has a spatial\\nshape (number of rows or columns) of:\\n`output_shape = math.floor((input_shape - pool_size) / strides) + 1`\\n(when `input_shape >= pool_size`)\\n\\nThe resulting output shape when using the `\\\"same\\\"` padding option is:\\n`output_shape = math.floor((input_shape - 1) / strides) + 1`\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, channels, height, width)`. It defaults to the\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json`. If you never set it, then it will be\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": \"valid\",\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": [\n          2,\n          2\n        ],\n        \"description\": \"int or tuple of 2 integers, factors by which to downscale\\n        (dim1, dim2). If only one integer is specified, the same\\n        window length will be used for all dimensions.\",\n        \"name\": \"pool_size\"\n      },\n      {\n        \"default\": [\n          2,\n          2\n        ],\n        \"description\": \"int or tuple of 2 integers, or None. Strides values. If None,\\n        it will default to `pool_size`. If only one int is specified, the\\n        same stride size will be used for all dimensions.\",\n        \"name\": \"strides\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    4D tensor with shape `(batch_size, height, width, channels)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    4D tensor with shape `(batch_size, channels, height, width)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    4D tensor with shape\\n    `(batch_size, pooled_height, pooled_width, channels)`.\\n- If `data_format=\\\"channels_first\\\"`:\\n    4D tensor with shape\\n    `(batch_size, channels, pooled_height, pooled_width)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"summary\": \"`strides=(1, 1)` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([[1., 2., 3.],\\n...               [4., 5., 6.],\\n...               [7., 8., 9.]])\\n>>> x = np.reshape(x, [1, 3, 3, 1])\\n>>> max_pool_2d = keras.layers.MaxPooling2D(pool_size=(2, 2),\\n...    strides=(1, 1), padding=\\\"valid\\\")\\n>>> max_pool_2d(x)\"\n      },\n      {\n        \"summary\": \"`strides=(2, 2)` and `padding=\\\"valid\\\"`:\",\n        \"code\": \">>> x = np.array([[1., 2., 3., 4.],\\n...               [5., 6., 7., 8.],\\n...               [9., 10., 11., 12.]])\\n>>> x = np.reshape(x, [1, 3, 4, 1])\\n>>> max_pool_2d = keras.layers.MaxPooling2D(pool_size=(2, 2),\\n...    strides=(2, 2), padding=\\\"valid\\\")\\n>>> max_pool_2d(x)\"\n      },\n      {\n        \"summary\": \"`stride=(1, 1)` and `padding=\\\"same\\\"`:\",\n        \"code\": \">>> x = np.array([[1., 2., 3.],\\n...               [4., 5., 6.],\\n...               [7., 8., 9.]])\\n>>> x = np.reshape(x, [1, 3, 3, 1])\\n>>> max_pool_2d = keras.layers.MaxPooling2D(pool_size=(2, 2),\\n...    strides=(1, 1), padding=\\\"same\\\")\\n>>> max_pool_2d(x)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MaxPooling3D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Pool\",\n    \"description\": \"Max pooling operation for 3D data (spatial or spatio-temporal).\\n\\nDownsamples the input along its spatial dimensions (depth, height, and\\nwidth) by taking the maximum value over an input window (of size defined by\\n`pool_size`) for each channel of the input. The window is shifted by\\n`strides` along each dimension.\",\n    \"attributes\": [\n      {\n        \"description\": \"int or tuple of 3 integers, factors by which to downscale\\n        (dim1, dim2, dim3). If only one integer is specified, the same\\n        window length will be used for all dimensions.\",\n        \"name\": \"pool_size\"\n      },\n      {\n        \"description\": \"int or tuple of 3 integers, or None. Strides values. If None,\\n        it will default to `pool_size`. If only one int is specified, the\\n        same stride size will be used for all dimensions.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input such that output has the same\\n        height/width dimension as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape\\n        `(batch, spatial_dim1, spatial_dim2, spatial_dim3, channels)` while\\n        `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, channels, spatial_dim1, spatial_dim2, spatial_dim3)`.\\n        It defaults to the `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json`. If you never set it, then it\\n        will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, pooled_dim1, pooled_dim2, pooled_dim3, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    5D tensor with shape:\\n    `(batch_size, channels, pooled_dim1, pooled_dim2, pooled_dim3)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"depth = 30\\nheight = 30\\nwidth = 30\\nchannels = 3\\n\\ninputs = keras.layers.Input(shape=(depth, height, width, channels))\\nlayer = keras.layers.MaxPooling3D(pool_size=3)\\noutputs = layer(inputs)  # Shape: (batch_size, 10, 10, 10, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MultiHeadAttention\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Attention\",\n    \"description\": \"MultiHeadAttention layer.\\n\\nThis is an implementation of multi-headed attention as described in the\\npaper \\\"Attention is all you Need\\\"\\n[Vaswani et al., 2017](https://arxiv.org/abs/1706.03762).\\nIf `query`, `key,` `value` are the same, then\\nthis is self-attention. Each timestep in `query` attends to the\\ncorresponding sequence in `key`, and returns a fixed-width vector.\\n\\nThis layer first projects `query`, `key` and `value`. These are\\n(effectively) a list of tensors of length `num_attention_heads`, where the\\ncorresponding shapes are `(batch_size, <query dimensions>, key_dim)`,\\n`(batch_size, <key/value dimensions>, key_dim)`,\\n`(batch_size, <key/value dimensions>, value_dim)`.\\n\\nThen, the query and key tensors are dot-producted and scaled. These are\\nsoftmaxed to obtain attention probabilities. The value tensors are then\\ninterpolated by these probabilities, then concatenated back to a single\\ntensor.\\n\\nFinally, the result tensor with the last dimension as `value_dim` can take\\na linear projection and return.\",\n    \"attributes\": [\n      {\n        \"description\": \"Number of attention heads.\",\n        \"name\": \"num_heads\"\n      },\n      {\n        \"description\": \"Size of each attention head for query and key.\",\n        \"name\": \"key_dim\"\n      },\n      {\n        \"description\": \"Size of each attention head for value.\",\n        \"name\": \"value_dim\"\n      },\n      {\n        \"description\": \"Dropout probability.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"description\": \"Boolean, whether the dense layers use bias vectors/matrices.\",\n        \"name\": \"use_bias\"\n      },\n      {\n        \"description\": \"The expected shape of an output tensor, besides the batch\\n        and sequence dims. If not specified, projects back to the query\\n        feature dim (the query input's last dimension).\",\n        \"name\": \"output_shape\"\n      },\n      {\n        \"description\": \"axes over which the attention is applied. `None` means\\n        attention over all axes, but batch, heads, and features.\",\n        \"name\": \"attention_axes\"\n      },\n      {\n        \"description\": \"Initializer for dense layer kernels.\",\n        \"name\": \"kernel_initializer\"\n      },\n      {\n        \"description\": \"Initializer for dense layer biases.\",\n        \"name\": \"bias_initializer\"\n      },\n      {\n        \"description\": \"Regularizer for dense layer kernels.\",\n        \"name\": \"kernel_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer for dense layer biases.\",\n        \"name\": \"bias_regularizer\"\n      },\n      {\n        \"description\": \"Regularizer for dense layer activity.\",\n        \"name\": \"activity_regularizer\"\n      },\n      {\n        \"description\": \"Constraint for dense layer kernels.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint for dense layer kernels.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Optional integer to seed the dropout layer.\"\n      },\n      {\n        \"name\": \"flash_attention\",\n        \"description\": \"If `None`, the layer attempts to use flash\\n        attention for faster and more memory-efficient attention\\n        computations when possible. This behavior can be configured using\\n        `keras.config.enable_flash_attention()` or\\n        `keras.config.disable_flash_attention()`.\"\n      },\n      {\n        \"name\": \"use_gate\",\n        \"description\": \"Boolean, whether to apply a gated attention mechanism.\\n        When True, an additional gating branch is added based on the\\n        (Gated Attention for Large Language Models)[https://arxiv.org/abs/2505.06708].\\n        It applies a sigmoid-activated linear projection to the query\\n        which then gates the attention output. This helps improve training\\n        stability and eliminates \\\"attention sinks\\\".\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"summary\": \"Performs 1D cross-attention over two sequence inputs with an attention mask.\\nReturns the additional attention weights over heads.\",\n        \"code\": \">>> layer = MultiHeadAttention(num_heads=2, key_dim=2)\\n>>> target = tf.keras.Input(shape=[8, 16])\\n>>> source = tf.keras.Input(shape=[4, 16])\\n>>> output_tensor, weights = layer(target, source,\\n...                                return_attention_scores=True)\\n>>> print(output_tensor.shape)\\n(None, 8, 16)\\n>>> print(weights.shape)\\n(None, 2, 8, 4)\"\n      },\n      {\n        \"summary\": \"Performs 2D self-attention over a 5D input tensor on axes 2 and 3.\",\n        \"code\": \">>> layer = MultiHeadAttention(\\n...     num_heads=2, key_dim=2, attention_axes=(2, 3))\\n>>> input_tensor = tf.keras.Input(shape=[5, 3, 4, 16])\\n>>> output_tensor = layer(input_tensor, input_tensor)\\n>>> print(output_tensor.shape)\\n(None, 5, 3, 4, 16)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Multiply\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Performs elementwise multiplication.\\n\\nIt takes as input a list of tensors, all of the same shape,\\nand returns a single tensor (also of the same shape).\",\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 3, 4)\\n>>> x1 = np.random.rand(*input_shape)\\n>>> x2 = np.random.rand(*input_shape)\\n>>> y = keras.layers.Multiply()([x1, x2])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> input1 = keras.layers.Input(shape=(16,))\\n>>> x1 = keras.layers.Dense(8, activation='relu')(input1)\\n>>> input2 = keras.layers.Input(shape=(32,))\\n>>> x2 = keras.layers.Dense(8, activation='relu')(input2)\\n>>> # equivalent to `y = keras.layers.multiply([x1, x2])`\\n>>> y = keras.layers.Multiply()([x1, x2])\\n>>> out = keras.layers.Dense(4)(y)\\n>>> model = keras.models.Model(inputs=[input1, input2], outputs=out)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Permute\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Permutes the dimensions of the input according to a given pattern.\\n\\nUseful e.g. connecting RNNs and convnets.\",\n    \"attributes\": [\n      {\n        \"description\": \"Tuple of integers. Permutation pattern does not include the\\n        batch dimension. Indexing starts at 1.\\n        For instance, `(1, 3, 2)` permutes the second and third dimensions\\n        of the input.\",\n        \"name\": \"dims\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same as the input shape, but with the dimensions re-ordered according\\nto the specified pattern.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = keras.Input(shape=(10, 64))\\n>>> y = keras.layers.Permute((2, 1))(x)\\n>>> y.shape\\n(None, 64, 10)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"PReLU\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Parametric Rectified Linear Unit activation layer.\\n\\nFormula:\\n``` python\\nf(x) = alpha * x for x < 0\\nf(x) = x for x >= 0\\n```\\nwhere `alpha` is a learned array with the same shape as x.\",\n    \"attributes\": [\n      {\n        \"description\": \"Initializer function for the weights.\",\n        \"name\": \"alpha_initializer\"\n      },\n      {\n        \"description\": \"Regularizer for the weights.\",\n        \"name\": \"alpha_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint for the weights.\",\n        \"name\": \"alpha_constraint\"\n      },\n      {\n        \"description\": \"The axes along which to share learnable parameters for the\\n        activation function. For example, if the incoming feature maps are\\n        from a 2D convolution with output shape\\n        `(batch, height, width, channels)`, and you wish to share parameters\\n        across space so that each filter only has one set of parameters,\\n        set `shared_axes=[1, 2]`.\",\n        \"name\": \"shared_axes\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments, such as `name` and `dtype`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the samples axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"params\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification](https://arxiv.org/abs/1502.01852)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ReLU\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Rectified Linear Unit activation function layer.\\n\\nFormula:\\n``` python\\nf(x) = max(x,0)\\nf(x) = max_value if x >= max_value\\nf(x) = x if threshold <= x < max_value\\nf(x) = negative_slope * (x - threshold) otherwise\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"Float >= 0. Maximum activation value. None means unlimited.\\n        Defaults to `None`.\",\n        \"name\": \"max_value\"\n      },\n      {\n        \"description\": \"Float >= 0. Negative slope coefficient.\\n        Defaults to `0.0`.\",\n        \"name\": \"negative_slope\"\n      },\n      {\n        \"description\": \"Float >= 0. Threshold value for thresholded activation.\\n        Defaults to `0.0`.\",\n        \"name\": \"threshold\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments, such as `name` and `dtype`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the batch axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"relu_layer = keras.layers.ReLU(\\n    max_value=10,\\n    negative_slope=0.5,\\n    threshold=0,\\n)\\ninput = np.array([-10, -5, 0.0, 5, 10])\\nresult = relu_layer(input)\\n# result = [-5. , -2.5,  0. ,  5. , 10.]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RepeatVector\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Repeats the input n times.\",\n    \"attributes\": [\n      {\n        \"description\": \"Integer, repetition factor.\",\n        \"name\": \"n\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"2D tensor with shape `(batch_size, features)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3D tensor with shape `(batch_size, n, features)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = keras.Input(shape=(32,))\\n>>> y = keras.layers.RepeatVector(3)(x)\\n>>> y.shape\\n(None, 3, 32)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Shape\",\n    \"description\": \"Layer that reshapes inputs into the given shape.\",\n    \"attributes\": [\n      {\n        \"description\": \"Target shape. Tuple of integers, does not include the\\n        samples dimension (batch size). One element of the `target_shape`\\n        can be -1 in which case the missing value is inferred from the\\n        size of the array and remaining dimensions.\",\n        \"name\": \"target_shape\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary, but required to be compatible with `target_shape`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"`(batch_size, *target_shape)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = keras.Input(shape=(12,))\\n>>> y = keras.layers.Reshape((3, 4))(x)\\n>>> y.shape\\n(None, 3, 4)\"\n      },\n      {\n        \"code\": \">>> # another example with shape inference using `-1` as dimension\\n>>> y = keras.layers.Reshape((-1, 2, 2))(x)\\n>>> y.shape\\n(None, 3, 2, 2)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RNN\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Base class for recurrent layers.\",\n    \"attributes\": [\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default `False`). Whether to return the last\\n        output in the output sequence, or the full sequence.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default `False`).\\n        Whether to return the last state in addition to the output.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default `False`).\\n        If `True`, process the input sequence backwards and return the\\n        reversed sequence.\",\n        \"name\": \"go_backwards\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default `False`). If True, the last state\\n        for each sample at index `i` in a batch will be used as initial\\n        state for the sample of index `i` in the following batch.\",\n        \"name\": \"stateful\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default `False`).\\n        If True, the network will be unrolled, else a symbolic loop will be\\n        used. Unrolling can speed-up a RNN, although it tends to be more\\n        memory-intensive. Unrolling is only suitable for short sequences.\",\n        \"name\": \"unroll\"\n      },\n      {\n        \"description\": \"A RNN cell instance or a list of RNN cell instances.\\n        A RNN cell is a class that has:\\n        - A `call(input_at_t, states_at_t)` method, returning\\n        `(output_at_t, states_at_t_plus_1)`. The call method of the\\n        cell can also take the optional argument `constants`, see\\n        section \\\"Note on passing external constants\\\" below.\\n        - A `state_size` attribute. This can be a single integer\\n        (single state) in which case it is the size of the recurrent\\n        state. This can also be a list/tuple of integers\\n        (one size per state).\\n        - A `output_size` attribute, a single integer.\\n        - A `get_initial_state(batch_size=None)`\\n        method that creates a tensor meant to be fed to `call()` as the\\n        initial state, if the user didn't specify any initial state\\n        via other means. The returned initial state should have\\n        shape `(batch_size, cell.state_size)`.\\n        The cell might choose to create a tensor full of zeros,\\n        or other values based on the cell's implementation.\\n        `inputs` is the input tensor to the RNN layer, with shape\\n        `(batch_size, timesteps, features)`.\\n        If this method is not implemented\\n        by the cell, the RNN layer will create a zero filled tensor\\n        with shape `(batch_size, cell.state_size)`.\\n        In the case that `cell` is a list of RNN cell instances, the cells\\n        will be stacked on top of each other in the RNN, resulting in an\\n        efficient stacked RNN.\",\n        \"name\": \"cell\"\n      },\n      {\n        \"description\": \"dimensionality of the input (integer).\\n    This argument (or alternatively,\\n    the keyword argument `input_shape`)\\n    is required when using this layer as the first layer in a model.\",\n        \"name\": \"input_dim\"\n      },\n      {\n        \"description\": \"Length of input sequences, to be specified\\n    when it is constant.\\n    This argument is required if you are going to connect\\n    `Flatten` then `Dense` layers upstream\\n    (without it, the shape of the dense outputs cannot be computed).\\n    Note that if the recurrent layer is not the first layer\\n    in your model, you would need to specify the input length\\n    at the level of the first layer\\n    (e.g. via the `input_shape` argument)\\n\",\n        \"name\": \"input_length\"\n      },\n      {\n        \"description\": \"The shape format of the `inputs` and `outputs` tensors.\\n    If True, the inputs and outputs will be in shape\\n    `(timesteps, batch, ...)`, whereas in the False case, it will be\\n    `(batch, timesteps, ...)`. Using `time_major = True` is a bit more\\n    efficient because it avoids transposes at the beginning and end of the\\n    RNN calculation. However, most TensorFlow data is batch-major, so by\\n    default this function accepts input and emits output in batch-major\\n    form.\",\n        \"name\": \"time_major\"\n      },\n      {\n        \"description\": \"Boolean (default `False`).\\n        Whether the output should use zeros for the masked timesteps.\\n        Note that this field is only used when `return_sequences`\\n        is `True` and `mask` is provided.\\n        It can useful if you want to reuse the raw output sequence of\\n        the RNN without interference from the masked timesteps, e.g.,\\n        merging bidirectional RNNs.\",\n        \"name\": \"zero_output_for_mask\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3-D tensor with shape `(batch_size, timesteps, features)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `return_state`: a list of tensors. The first tensor is\\nthe output. The remaining tensors are the last states,\\neach with shape `(batch_size, state_size)`, where `state_size` could\\nbe a high dimension tensor shape.\\n- If `return_sequences`: 3D tensor with shape\\n`(batch_size, timesteps, output_size)`.\\n\\nMasking:\\n\\nThis layer supports masking for input data with a variable number\\nof timesteps. To introduce masks to your data,\\nuse a `keras.layers.Embedding` layer with the `mask_zero` parameter\\nset to `True`.\\n\\nNote on using statefulness in RNNs:\\n\\nYou can set RNN layers to be 'stateful', which means that the states\\ncomputed for the samples in one batch will be reused as initial states\\nfor the samples in the next batch. This assumes a one-to-one mapping\\nbetween samples in different successive batches.\\n\\nTo enable statefulness:\\n\\n- Specify `stateful=True` in the layer constructor.\\n- Specify a fixed batch size for your model, by passing\\n    `batch_size=...` to the `Input` layer(s) of your model.\\n    Remember to also specify the same `batch_size=...` when\\n    calling `fit()`, or otherwise use a generator-like\\n    data source like a `keras.utils.PyDataset` or a\\n    `tf.data.Dataset`.\\n- Specify `shuffle=False` when calling `fit()`, since your\\n    batches are expected to be temporally ordered.\\n\\nTo reset the states of your model, call `.reset_state()` on either\\na specific layer, or on your entire model.\\n\\nNote on specifying the initial state of RNNs:\\n\\nYou can specify the initial state of RNN layers symbolically by\\ncalling them with the keyword argument `initial_state`. The value of\\n`initial_state` should be a tensor or list of tensors representing\\nthe initial state of the RNN layer.\\n\\nYou can specify the initial state of RNN layers numerically by\\ncalling `reset_state()` with the keyword argument `states`. The value of\\n`states` should be a numpy array or list of numpy arrays representing\\nthe initial state of the RNN layer.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"from keras.layers import RNN\\nfrom keras import ops\\n\\n# First, let's define a RNN Cell, as a layer subclass.\\nclass MinimalRNNCell(keras.Layer):\\n\\n    def __init__(self, units, **kwargs):\\n        super().__init__(**kwargs)\\n        self.units = units\\n        self.state_size = units\\n\\n    def build(self, input_shape):\\n        self.kernel = self.add_weight(shape=(input_shape[-1], self.units),\\n                                      initializer='uniform',\\n                                      name='kernel')\\n        self.recurrent_kernel = self.add_weight(\\n            shape=(self.units, self.units),\\n            initializer='uniform',\\n            name='recurrent_kernel')\\n\\n    def call(self, inputs, states):\\n        prev_output = states[0]\\n        h = ops.matmul(inputs, self.kernel)\\n        output = h + ops.matmul(prev_output, self.recurrent_kernel)\\n        return output, [output]\\n\\n# Let's use this cell in a RNN layer:\\n\\ncell = MinimalRNNCell(32)\\nx = keras.Input((None, 5))\\nlayer = RNN(cell)\\ny = layer(x)\\n\\n# Here's how to use the cell to build a stacked RNN:\\n\\ncells = [MinimalRNNCell(32), MinimalRNNCell(64)]\\nx = keras.Input((None, 5))\\nlayer = RNN(cells)\\ny = layer(x)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SeparableConv1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"1D separable convolution layer.\\n\\nThis layer performs a depthwise convolution that acts separately on\\nchannels, followed by a pointwise convolution that mixes channels.\\nIf `use_bias` is True and a bias initializer is provided,\\nit adds a bias vector to the output. It then optionally applies an\\nactivation function to produce the final output.\",\n    \"attributes\": [\n      {\n        \"description\": \"int, the dimensionality of the output space (i.e. the number\\n        of filters in the pointwise convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integers, specifying the size of the\\n        depthwise convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integers, specifying the stride length\\n        of the depthwise convolution. If only one int is specified, the same\\n        stride size will be used for all dimensions. `strides > 1` is\\n        incompatible with `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, steps, features)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, features, steps)`. It defaults to the `image_data_format`\\n        value found in your Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"int or tuple/list of 1 integers, specifying the dilation\\n        rate to use for dilated convolution. If only one int is specified,\\n        the same dilation rate will be used for all dimensions.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"description\": \"The number of depthwise convolution output channels\\n        for each input channel. The total number of depthwise convolution\\n        output channels will be equal to `input_channel * depth_multiplier`.\",\n        \"name\": \"depth_multiplier\"\n      },\n      {\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\"\n      },\n      {\n        \"description\": \"An initializer for the depthwise convolution\\n        kernel. If None, then the default initializer (`\\\"glorot_uniform\\\"`)\\n        will be used.\",\n        \"name\": \"depthwise_initializer\"\n      },\n      {\n        \"description\": \"An initializer for the pointwise convolution\\n        kernel. If None, then the default initializer (`\\\"glorot_uniform\\\"`)\\n        will be used.\",\n        \"name\": \"pointwise_initializer\"\n      },\n      {\n        \"description\": \"An initializer for the bias vector. If None, the\\n        default initializer ('\\\"zeros\\\"') will be used.\",\n        \"name\": \"bias_initializer\"\n      },\n      {\n        \"description\": \"Optional regularizer for the depthwise\\n        convolution kernel.\",\n        \"name\": \"depthwise_regularizer\"\n      },\n      {\n        \"description\": \"Optional regularizer for the pointwise\\n        convolution kernel.\",\n        \"name\": \"pointwise_regularizer\"\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\"\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        depthwise kernel after being updated by an `Optimizer` (e.g. used\\n        for norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape).\",\n        \"name\": \"depthwise_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        pointwise kernel after being updated by an `Optimizer`.\",\n        \"name\": \"pointwise_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"Boolean, if `True` the weights of this layer will be marked as\\n    trainable (and listed in `layer.trainable_weights`).\",\n        \"name\": \"trainable\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 3D tensor with shape: `(batch_shape, steps, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 3D tensor with shape: `(batch_shape, channels, steps)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 3D tensor with shape: `(batch_shape, new_steps, filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 3D tensor with shape: `(batch_shape, filters, new_steps)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(4, 10, 12)\\n>>> y = keras.layers.SeparableConv1D(3, 4, 3, 2, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 4, 4)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SeparableConv2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"2D separable convolution layer.\\n\\nThis layer performs a depthwise convolution that acts separately on\\nchannels, followed by a pointwise convolution that mixes channels.\\nIf `use_bias` is True and a bias initializer is provided,\\nit adds a bias vector to the output. It then optionally applies an\\nactivation function to produce the final output.\",\n    \"attributes\": [\n      {\n        \"default\": \"linear\",\n        \"description\": \"Activation function. If `None`, no activation is applied.\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": \"valid\",\n        \"description\": \"string, either `\\\"valid\\\"` or `\\\"same\\\"` (case-insensitive).\\n        `\\\"valid\\\"` means no padding. `\\\"same\\\"` results in padding evenly to\\n        the left/right or up/down of the input. When `padding=\\\"same\\\"` and\\n        `strides=1`, the output has the same size as the input.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"bool, if `True`, bias will be added to the output.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"string, either `\\\"channels_last\\\"` or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs. `\\\"channels_last\\\"`\\n        corresponds to inputs with shape `(batch, height, width, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch, channels, height, width)`. It defaults to the\\n        `image_data_format` value found in your Keras config file\\n        at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"int or tuple/list of 2 integers, specifying the stride length\\n        of the depthwise convolution. If only one int is specified, the same\\n        stride size will be used for all dimensions. `strides > 1` is\\n        incompatible with `dilation_rate > 1`.\",\n        \"name\": \"strides\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"int or tuple/list of 2 integers, specifying the dilation\\n        rate to use for dilated convolution. If only one int is specified,\\n        the same dilation rate will be used for all dimensions.\",\n        \"name\": \"dilation_rate\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"The number of depthwise convolution output channels\\n        for each input channel. The total number of depthwise convolution\\n        output channels will be equal to `input_channel * depth_multiplier`.\",\n        \"name\": \"depth_multiplier\"\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"An initializer for the pointwise convolution\\n        kernel. If None, then the default initializer (`\\\"glorot_uniform\\\"`)\\n        will be used.\",\n        \"name\": \"pointwise_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"An initializer for the depthwise convolution\\n        kernel. If None, then the default initializer (`\\\"glorot_uniform\\\"`)\\n        will be used.\",\n        \"name\": \"depthwise_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"An initializer for the bias vector. If None, the\\n        default initializer ('\\\"zeros\\\"') will be used.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"int, the dimensionality of the output space (i.e. the number\\n        of filters in the pointwise convolution).\",\n        \"name\": \"filters\"\n      },\n      {\n        \"description\": \"int or tuple/list of 2 integers, specifying the size of the\\n        depthwise convolution window.\",\n        \"name\": \"kernel_size\"\n      },\n      {\n        \"description\": \"Optional regularizer for the depthwise\\n        convolution kernel.\",\n        \"name\": \"depthwise_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the pointwise\\n        convolution kernel.\",\n        \"name\": \"pointwise_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer for the bias vector.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional regularizer function for the output.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        depthwise kernel after being updated by an `Optimizer` (e.g. used\\n        for norm constraints or value constraints for layer weights). The\\n        function must take as input the unprojected variable and must return\\n        the projected variable (which must have the same shape).\",\n        \"name\": \"depthwise_constraint\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        pointwise kernel after being updated by an `Optimizer`.\",\n        \"name\": \"pointwise_constraint\"\n      },\n      {\n        \"description\": \"Optional projection function to be applied to the\\n        bias after being updated by an `Optimizer`.\",\n        \"name\": \"bias_constraint\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, height, width, channels)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"- If `data_format=\\\"channels_last\\\"`:\\n    A 4D tensor with shape: `(batch_size, new_height, new_width, filters)`\\n- If `data_format=\\\"channels_first\\\"`:\\n    A 4D tensor with shape: `(batch_size, filters, new_height, new_width)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> x = np.random.rand(4, 10, 10, 12)\\n>>> y = keras.layers.SeparableConv2D(3, 4, 3, 2, activation='relu')(x)\\n>>> print(y.shape)\\n(4, 4, 4, 4)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SimpleRNN\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Fully-connected RNN where the output is to be fed back as the new input.\",\n    \"attributes\": [\n      {\n        \"default\": false,\n        \"description\": \"Boolean. Whether to return the last output\\n        in the output sequence, or the full sequence. Default: `False`.\",\n        \"name\": \"return_sequences\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean. Whether to return the last state\\n        in addition to the output. Default: `False`.\",\n        \"name\": \"return_state\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`).\\n        If `True`, process the input sequence backwards and return the\\n        reversed sequence.\",\n        \"name\": \"go_backwards\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`). If `True`, the last state\\n        for each sample at index i in a batch will be used as the\\n        initial state for the sample of index i in the following batch.\",\n        \"name\": \"stateful\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"Boolean (default: `False`).\\n        If `True`, the network will be unrolled,\\n        else a symbolic loop will be used.\\n        Unrolling can speed-up an RNN,\\n        although it tends to be more memory-intensive.\\n        Unrolling is only suitable for short sequences.\",\n        \"name\": \"unroll\"\n      },\n      {\n        \"default\": \"tanh\",\n        \"description\": \"Activation function to use.\\n        Default: hyperbolic tangent (`tanh`).\\n        If you pass None, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"default\": true,\n        \"description\": \"Boolean, (default `True`), whether the layer uses\\n        a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"VarianceScaling\",\n          \"config\": {\n            \"distribution\": \"uniform\",\n            \"mode\": \"fan_avg\",\n            \"scale\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs. Default:\\n        `\\\"glorot_uniform\\\"`.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Orthogonal\",\n          \"config\": {\n            \"gain\": 1,\n            \"seed\": null\n          }\n        },\n        \"description\": \"Initializer for the `recurrent_kernel`\\n        weights matrix, used for the linear transformation of the recurrent\\n        state.  Default: `\\\"orthogonal\\\"`.\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": {\n          \"class_name\": \"Zeros\",\n          \"config\": {}\n        },\n        \"description\": \"Initializer for the bias vector. Default: `\\\"zeros\\\"`.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1.\\n        Fraction of the units to drop for the linear transformation\\n        of the inputs. Default: 0.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1.\\n        Fraction of the units to drop for the linear transformation of the\\n        recurrent state. Default: 0.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the output of the\\n        layer (its \\\"activation\\\"). Default: `None`.\",\n        \"name\": \"activity_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix.  Default: `None`.\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"description\": \"`None`.\",\n        \"name\": \"Default\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"kernel\"\n      },\n      {\n        \"name\": \"recurrent_kernel\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"inputs = np.random.random((32, 10, 8))\\nsimple_rnn = keras.layers.SimpleRNN(4)\\noutput = simple_rnn(inputs)  # The output has shape `(32, 4)`.\\nsimple_rnn = keras.layers.SimpleRNN(\\n    4, return_sequences=True, return_state=True\\n)\\n# whole_sequence_output has shape `(32, 10, 4)`.\\n# final_state has shape `(32, 4)`.\\nwhole_sequence_output, final_state = simple_rnn(inputs)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SimpleRNNCell\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Cell class for SimpleRNN.\\n\\nThis class processes one step within the whole time sequence input, whereas\\n`keras.layer.SimpleRNN` processes the whole sequence.\",\n    \"attributes\": [\n      {\n        \"description\": \"Positive integer, dimensionality of the output space.\",\n        \"name\": \"units\"\n      },\n      {\n        \"description\": \"Activation function to use.\\n        Default: hyperbolic tangent (`tanh`).\\n        If you pass `None`, no activation is applied\\n        (ie. \\\"linear\\\" activation: `a(x) = x`).\",\n        \"name\": \"activation\"\n      },\n      {\n        \"description\": \"Boolean, (default `True`), whether the layer\\n        should use a bias vector.\",\n        \"name\": \"use_bias\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `kernel` weights matrix,\\n        used for the linear transformation of the inputs. Default:\\n        `\\\"glorot_uniform\\\"`.\",\n        \"name\": \"kernel_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the `recurrent_kernel`\\n        weights matrix, used for the linear transformation\\n        of the recurrent state. Default: `\\\"orthogonal\\\"`.\",\n        \"name\": \"recurrent_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Initializer for the bias vector. Default: `\\\"zeros\\\"`.\",\n        \"name\": \"bias_initializer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Regularizer function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_regularizer\",\n        \"visible\": false\n      },\n      {\n        \"description\": \"Constraint function applied to the `kernel` weights\\n        matrix. Default: `None`.\",\n        \"name\": \"kernel_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the\\n        `recurrent_kernel` weights matrix. Default: `None`.\",\n        \"name\": \"recurrent_constraint\"\n      },\n      {\n        \"description\": \"Constraint function applied to the bias vector.\\n        Default: `None`.\",\n        \"name\": \"bias_constraint\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop for the\\n        linear transformation of the inputs. Default: 0.\",\n        \"name\": \"dropout\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"Float between 0 and 1. Fraction of the units to drop\\n        for the linear transformation of the recurrent state. Default: 0.\",\n        \"name\": \"recurrent_dropout\"\n      },\n      {\n        \"description\": \"`None`.\",\n        \"name\": \"Default\"\n      },\n      {\n        \"name\": \"seed\",\n        \"description\": \"Random seed for dropout.\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"inputs = np.random.random([32, 10, 8]).astype(np.float32)\\nrnn = keras.layers.RNN(keras.layers.SimpleRNNCell(4))\\noutput = rnn(inputs)  # The output has shape `(32, 4)`.\\nrnn = keras.layers.RNN(\\n    keras.layers.SimpleRNNCell(4),\\n    return_sequences=True,\\n    return_state=True\\n)\\n# whole_sequence_output has shape `(32, 10, 4)`.\\n# final_state has shape `(32, 4)`.\\nwhole_sequence_output, final_state = rnn(inputs)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Softmax activation layer.\\n\\nFormula:\\n``` python\\nexp_x = exp(x - max(x))\\nf(x) = exp_x / sum(exp_x)\\n```\",\n    \"inputs\": [\n      {\n        \"name\": \"input\",\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the samples axis)\\nwhen using this layer as the first layer in a model.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"description\": \"Same shape as the input.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"description\": \"Integer, or list of Integers, axis along which the softmax\\n        normalization is applied.\"\n      },\n      {\n        \"name\": \"**kwargs\",\n        \"description\": \"Base layer keyword arguments, such as `name` and `dtype`.\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> softmax_layer = keras.layers.Softmax()\\n>>> input = np.array([1.0, 2.0, 1.0])\\n>>> result = softmax_layer(input)\\n>>> result\\n[0.21194157, 0.5761169, 0.21194157]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SoftPlus\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftSign\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SpatialDropout1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Dropout\",\n    \"description\": \"Spatial 1D version of Dropout.\\n\\nThis layer performs the same function as Dropout, however, it drops\\nentire 1D feature maps instead of individual elements. If adjacent frames\\nwithin feature maps are strongly correlated (as is normally the case in\\nearly convolution layers) then regular dropout will not regularize the\\nactivations and will otherwise just result in an effective learning rate\\ndecrease. In this case, `SpatialDropout1D` will help promote independence\\nbetween feature maps and should be used instead.\",\n    \"attributes\": [\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the input units to drop.\",\n        \"name\": \"rate\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D tensor with shape: `(samples, timesteps, channels)`\\n\\nOutput shape: Same as input.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same as input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Tompson et al., 2014](https://arxiv.org/abs/1411.4280)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SpatialDropout2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Dropout\",\n    \"description\": \"Spatial 2D version of Dropout.\\n\\nThis version performs the same function as Dropout, however, it drops\\nentire 2D feature maps instead of individual elements. If adjacent pixels\\nwithin feature maps are strongly correlated (as is normally the case in\\nearly convolution layers) then regular dropout will not regularize the\\nactivations and will otherwise just result in an effective learning rate\\ndecrease. In this case, `SpatialDropout2D` will help promote independence\\nbetween feature maps and should be used instead.\",\n    \"attributes\": [\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the input units to drop.\",\n        \"name\": \"rate\"\n      },\n      {\n        \"description\": \"`\\\"channels_first\\\"` or `\\\"channels_last\\\"`.\\n        In `\\\"channels_first\\\"` mode, the channels dimension (the depth)\\n        is at index 1, in `\\\"channels_last\\\"` mode is it at index 3.\\n        It defaults to the `image_data_format` value found in your\\n        Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D tensor with shape: `(samples, channels, rows, cols)` if\\n        data_format='channels_first'\\n    or 4D tensor with shape: `(samples, rows, cols, channels)` if\\n        data_format='channels_last'.\\n\\nOutput shape: Same as input.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same as input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Tompson et al., 2014](https://arxiv.org/abs/1411.4280)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SpatialDropout3D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Dropout\",\n    \"description\": \"Spatial 3D version of Dropout.\\n\\nThis version performs the same function as Dropout, however, it drops\\nentire 3D feature maps instead of individual elements. If adjacent voxels\\nwithin feature maps are strongly correlated (as is normally the case in\\nearly convolution layers) then regular dropout will not regularize the\\nactivations and will otherwise just result in an effective learning rate\\ndecrease. In this case, SpatialDropout3D will help promote independence\\nbetween feature maps and should be used instead.\",\n    \"attributes\": [\n      {\n        \"description\": \"Float between 0 and 1. Fraction of the input units to drop.\",\n        \"name\": \"rate\"\n      },\n      {\n        \"description\": \"`\\\"channels_first\\\"` or `\\\"channels_last\\\"`.\\n        In `\\\"channels_first\\\"` mode, the channels dimension (the depth)\\n        is at index 1, in `\\\"channels_last\\\"` mode is it at index 4.\\n        It defaults to the `image_data_format` value found in your\\n        Keras config file at `~/.keras/keras.json`.\\n        If you never set it, then it will be `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"5D tensor with shape: `(samples, channels, dim1, dim2, dim3)` if\\n        data_format='channels_first'\\n    or 5D tensor with shape: `(samples, dim1, dim2, dim3, channels)` if\\n        data_format='channels_last'.\\n\\nOutput shape: Same as input.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same as input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Tompson et al., 2014](https://arxiv.org/abs/1411.4280)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"StackedRNNCells\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Wrapper allowing a stack of RNN cells to behave as a single cell.\\n\\nUsed to implement efficient stacked RNNs.\",\n    \"attributes\": [\n      {\n        \"description\": \"List of RNN cell instances.\",\n        \"name\": \"cells\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \"batch_size = 3\\nsentence_length = 5\\nnum_features = 2\\nnew_shape = (batch_size, sentence_length, num_features)\\nx = np.reshape(np.arange(30), new_shape)\\n\\nrnn_cells = [keras.layers.LSTMCell(128) for _ in range(2)]\\nstacked_lstm = keras.layers.StackedRNNCells(rnn_cells)\\nlstm_layer = keras.layers.RNN(stacked_lstm)\\n\\nresult = lstm_layer(x)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Subtract\",\n    \"module\": \"keras.layers\",\n    \"description\": \"Performs elementwise subtraction.\\n\\nIt takes as input a list of tensors of size 2 both of the\\nsame shape, and returns a single tensor (inputs[0] - inputs[1])\\nof same shape.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\"\n      },\n      {\n        \"name\": \"y\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"z\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 3, 4)\\n>>> x1 = np.random.rand(*input_shape)\\n>>> x2 = np.random.rand(*input_shape)\\n>>> y = keras.layers.Subtract()([x1, x2])\"\n      },\n      {\n        \"summary\": \"Usage in a Keras model:\",\n        \"code\": \">>> input1 = keras.layers.Input(shape=(16,))\\n>>> x1 = keras.layers.Dense(8, activation='relu')(input1)\\n>>> input2 = keras.layers.Input(shape=(32,))\\n>>> x2 = keras.layers.Dense(8, activation='relu')(input2)\\n>>> # equivalent to `subtracted = keras.layers.subtract([x1, x2])`\\n>>> subtracted = keras.layers.Subtract()([x1, x2])\\n>>> out = keras.layers.Dense(4)(subtracted)\\n>>> model = keras.models.Model(inputs=[input1, input2], outputs=out)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TanH\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ThresholdedReLU\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Activation\",\n    \"description\": \"Thresholded Rectified Linear Unit.\\n\\nIt follows:\\n\\n```\\n    f(x) = x for x > theta\\n    f(x) = 0 otherwise`\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"Float >= 0. Threshold location of activation.\",\n        \"name\": \"theta\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"Arbitrary. Use the keyword argument `input_shape`\\n(tuple of integers, does not include the samples axis)\\nwhen using this layer as the first layer in a model.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"Same shape as the input.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"references\": [\n      {\n        \"description\": \"[Zero-Bias Autoencoders and the Benefits of Co-Adapting Features]( https://arxiv.org/abs/1402.3337)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TimeDistributed\",\n    \"module\": \"keras.layers\",\n    \"description\": \"This wrapper allows to apply a layer to every temporal slice of an input.\\n\\nEvery input should be at least 3D, and the dimension of index one of the\\nfirst input will be considered to be the temporal dimension.\\n\\nConsider a batch of 32 video samples, where each sample is a 128x128 RGB\\nimage with `channels_last` data format, across 10 timesteps.\\nThe batch input shape is `(32, 10, 128, 128, 3)`.\\n\\nYou can then use `TimeDistributed` to apply the same `Conv2D` layer to each\\nof the 10 timesteps, independently:\\n\\n```\\n>>> inputs = layers.Input(shape=(10, 128, 128, 3), batch_size=32)\\n>>> conv_2d_layer = layers.Conv2D(64, (3, 3))\\n>>> outputs = layers.TimeDistributed(conv_2d_layer)(inputs)\\n>>> outputs.shape\\n(32, 10, 126, 126, 64)\\n```\\n\\nBecause `TimeDistributed` applies the same instance of `Conv2D` to each of\\nthe timestamps, the same set of weights are used at each timestamp.\",\n    \"attributes\": [\n      {\n        \"description\": \"a `keras.layers.Layer` instance.\",\n        \"name\": \"layer\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"UpSampling1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Upsampling layer for 1D inputs.\\n\\nRepeats each temporal step `size` times along the time axis.\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"Integer. Upsampling factor.\",\n        \"name\": \"size\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D tensor with shape: `(batch_size, steps, features)`.\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3D tensor with shape: `(batch_size, upsampled_steps, features)`.\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 2, 3)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> x\\n[[[ 0  1  2]\\n  [ 3  4  5]]\\n [[ 6  7  8]\\n  [ 9 10 11]]]\\n>>> y = keras.layers.UpSampling1D(size=2)(x)\\n>>> y\\n[[[ 0.  1.  2.]\\n  [ 0.  1.  2.]\\n  [ 3.  4.  5.]\\n  [ 3.  4.  5.]]\\n [[ 6.  7.  8.]\\n  [ 6.  7.  8.]\\n  [ 9. 10. 11.]\\n  [ 9. 10. 11.]]]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"UpSampling2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Upsampling layer for 2D inputs.\\n\\nThe implementation uses interpolative resizing, given the resize method\\n(specified by the `interpolation` argument). Use `interpolation=nearest`\\nto repeat the rows and columns of the data.\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"A string,\\n        one of `\\\"channels_last\\\"` (default) or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, height, width, channels)` while `\\\"channels_first\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, channels, height, width)`.\\n        When unspecified, uses\\n        `image_data_format` value found in your Keras config file at\\n        `~/.keras/keras.json` (if exists) else `\\\"channels_last\\\"`.\\n        Defaults to `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"Int, or tuple of 2 integers.\\n        The upsampling factors for rows and columns.\",\n        \"name\": \"size\"\n      },\n      {\n        \"description\": \"A string, one of `\\\"bicubic\\\"`, `\\\"bilinear\\\"`, `\\\"lanczos3\\\"`,\\n        `\\\"lanczos5\\\"`, `\\\"nearest\\\"`.\",\n        \"name\": \"interpolation\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n    `(batch_size, rows, cols, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n    `(batch_size, channels, rows, cols)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n    `(batch_size, upsampled_rows, upsampled_cols, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n    `(batch_size, channels, upsampled_rows, upsampled_cols)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 2, 1, 3)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> print(x)\\n[[[[ 0  1  2]]\\n  [[ 3  4  5]]]\\n [[[ 6  7  8]]\\n  [[ 9 10 11]]]]\\n>>> y = keras.layers.UpSampling2D(size=(1, 2))(x)\\n>>> print(y)\\n[[[[ 0  1  2]\\n   [ 0  1  2]]\\n  [[ 3  4  5]\\n   [ 3  4  5]]]\\n [[[ 6  7  8]\\n   [ 6  7  8]]\\n  [[ 9 10 11]\\n   [ 9 10 11]]]]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"UpSampling3D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Layer\",\n    \"description\": \"Upsampling layer for 3D inputs.\\n\\nRepeats the 1st, 2nd and 3rd dimensions\\nof the data by `size[0]`, `size[1]` and `size[2]` respectively.\",\n    \"attributes\": [\n      {\n        \"default\": \"channels_last\",\n        \"description\": \"A string,\\n        one of `\\\"channels_last\\\"` (default) or `\\\"channels_first\\\"`.\\n        The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`.\\n        When unspecified, uses\\n        `image_data_format` value found in your Keras config file at\\n         `~/.keras/keras.json` (if exists) else `\\\"channels_last\\\"`.\\n        Defaults to `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      },\n      {\n        \"description\": \"Int, or tuple of 3 integers.\\n        The upsampling factors for dim1, dim2 and dim3.\",\n        \"name\": \"size\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"5D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n    `(batch_size, dim1, dim2, dim3, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n    `(batch_size, channels, dim1, dim2, dim3)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"5D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n    `(batch_size, upsampled_dim1, upsampled_dim2, upsampled_dim3,\\n    channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n    `(batch_size, channels, upsampled_dim1, upsampled_dim2,\\n    upsampled_dim3)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 1, 2, 1, 3)\\n>>> x = np.ones(input_shape)\\n>>> y = keras.layers.UpSampling3D(size=(2, 2, 2))(x)\\n>>> y.shape\\n(2, 2, 4, 2, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ZeroPadding1D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Tensor\",\n    \"description\": \"Zero-padding layer for 1D input (e.g. temporal sequence).\",\n    \"attributes\": [\n      {\n        \"description\": \"Int, or tuple of int (length 2), or dictionary.\\n        - If int: how many zeros to add at the beginning and end of\\n          the padding dimension (axis 1).\\n        - If tuple of 2 ints: how many zeros to add at the beginning and the\\n          end of the padding dimension (`(left_pad, right_pad)`).\",\n        \"name\": \"padding\"\n      },\n      {\n        \"name\": \"data_format\",\n        \"description\": \"A string, one of `\\\"channels_last\\\"` (default) or\\n        `\\\"channels_first\\\"`. The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, axis_to_pad, channels)` while `\\\"channels_first\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, channels, axis_to_pad)`.\\n        When unspecified, uses `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json` (if exists). Defaults to\\n        `\\\"channels_last\\\"`.\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"3D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, axis_to_pad, features)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, features, axis_to_pad)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"3D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, padded_axis, features)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, features, padded_axis)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (2, 2, 3)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> x\\n[[[ 0  1  2]\\n  [ 3  4  5]]\\n [[ 6  7  8]\\n  [ 9 10 11]]]\\n>>> y = keras.layers.ZeroPadding1D(padding=2)(x)\\n>>> y\\n[[[ 0  0  0]\\n  [ 0  0  0]\\n  [ 0  1  2]\\n  [ 3  4  5]\\n  [ 0  0  0]\\n  [ 0  0  0]]\\n [[ 0  0  0]\\n  [ 0  0  0]\\n  [ 6  7  8]\\n  [ 9 10 11]\\n  [ 0  0  0]\\n  [ 0  0  0]]]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ZeroPadding2D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Tensor\",\n    \"description\": \"Zero-padding layer for 2D input (e.g. picture).\\n\\nThis layer can add rows and columns of zeros at the top, bottom, left and\\nright side of an image tensor.\",\n    \"attributes\": [\n      {\n        \"description\": \"Int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints.\\n        - If int: the same symmetric padding is applied to height and width.\\n        - If tuple of 2 ints: interpreted as two different symmetric padding\\n          values for height and width:\\n          `(symmetric_height_pad, symmetric_width_pad)`.\\n        - If tuple of 2 tuples of 2 ints: interpreted as\\n         `((top_pad, bottom_pad), (left_pad, right_pad))`.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"description\": \"A string, one of `\\\"channels_last\\\"` (default) or\\n        `\\\"channels_first\\\"`. The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, height, width, channels)` while `\\\"channels_first\\\"`\\n        corresponds to inputs with shape\\n        `(batch_size, channels, height, width)`.\\n        When unspecified, uses `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json` (if exists). Defaults to\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"4D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, height, width, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, channels, height, width)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"4D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, padded_height, padded_width, channels)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, channels, padded_height, padded_width)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (1, 1, 2, 2)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> x\\n[[[[0 1]\\n   [2 3]]]]\\n>>> y = keras.layers.ZeroPadding2D(padding=1)(x)\\n>>> y\\n[[[[0 0]\\n   [0 0]\\n   [0 0]\\n   [0 0]]\\n  [[0 0]\\n   [0 1]\\n   [2 3]\\n   [0 0]]\\n  [[0 0]\\n   [0 0]\\n   [0 0]\\n   [0 0]]]]\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ZeroPadding3D\",\n    \"module\": \"keras.layers\",\n    \"category\": \"Tensor\",\n    \"description\": \"Zero-padding layer for 3D data (spatial or spatio-temporal).\",\n    \"attributes\": [\n      {\n        \"description\": \"Int, or tuple of 3 ints, or tuple of 3 tuples of 2 ints.\\n        - If int: the same symmetric padding is applied to depth, height,\\n          and width.\\n        - If tuple of 3 ints: interpreted as three different symmetric\\n          padding values for depth, height, and width:\\n          `(symmetric_dim1_pad, symmetric_dim2_pad, symmetric_dim3_pad)`.\\n        - If tuple of 3 tuples of 2 ints: interpreted as\\n          `((left_dim1_pad, right_dim1_pad), (left_dim2_pad,\\n          right_dim2_pad), (left_dim3_pad, right_dim3_pad))`.\",\n        \"name\": \"padding\"\n      },\n      {\n        \"description\": \"A string, one of `\\\"channels_last\\\"` (default) or\\n        `\\\"channels_first\\\"`. The ordering of the dimensions in the inputs.\\n        `\\\"channels_last\\\"` corresponds to inputs with shape\\n        `(batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels)`\\n        while `\\\"channels_first\\\"` corresponds to inputs with shape\\n        `(batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3)`.\\n        When unspecified, uses `image_data_format` value found in your Keras\\n        config file at `~/.keras/keras.json` (if exists). Defaults to\\n        `\\\"channels_last\\\"`.\",\n        \"name\": \"data_format\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"description\": \"5D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, first_axis_to_pad, second_axis_to_pad,\\n  third_axis_to_pad, depth)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, depth, first_axis_to_pad, second_axis_to_pad,\\n  third_axis_to_pad)`\",\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"description\": \"5D tensor with shape:\\n- If `data_format` is `\\\"channels_last\\\"`:\\n  `(batch_size, first_padded_axis, second_padded_axis,\\n  third_axis_to_pad, depth)`\\n- If `data_format` is `\\\"channels_first\\\"`:\\n  `(batch_size, depth, first_padded_axis, second_padded_axis,\\n  third_axis_to_pad)`\",\n        \"name\": \"output\"\n      }\n    ],\n    \"examples\": [\n      {\n        \"code\": \">>> input_shape = (1, 1, 2, 2, 3)\\n>>> x = np.arange(np.prod(input_shape)).reshape(input_shape)\\n>>> y = keras.layers.ZeroPadding3D(padding=2)(x)\\n>>> y.shape\\n(1, 5, 6, 6, 3)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"nn.relu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"math.add\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"Tensor\"\n      },\n      {\n        \"name\": \"y\",\n        \"type\": \"Tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"z\"\n      }\n    ]\n  },\n  {\n    \"name\": \"__operators__.add\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"Tensor\"\n      },\n      {\n        \"name\": \"y\",\n        \"type\": \"Tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"z\"\n      }\n    ]\n  },\n  {\n    \"name\": \"linalg.matmul\",\n    \"attributes\": [\n      {\n        \"name\": \"transpose_a\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"name\": \"transpose_b\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"a\",\n        \"type\": \"Tensor\"\n      },\n      {\n        \"name\": \"b\",\n        \"type\": \"Tensor\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"c\",\n        \"type\": \"Tensor\"\n      }\n    ]\n  },\n  {\n    \"name\": \"nn.abs\",\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"math.sigmoid\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"reshape\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"concat\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"list\": true\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"compat.v1.transpose\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "source/keras-proto.js",
    "content": "\nexport const third_party = {};\n\nthird_party.tensorflow = {};\n\nthird_party.tensorflow.python = {};\n\nthird_party.tensorflow.python.keras = {};\n\nthird_party.tensorflow.python.keras.protobuf = {};\n\nthird_party.tensorflow.python.keras.protobuf.SavedMetadata = class SavedMetadata {\n\n    constructor() {\n        this.nodes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new third_party.tensorflow.python.keras.protobuf.SavedMetadata();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.nodes.push(third_party.tensorflow.python.keras.protobuf.SavedObject.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new third_party.tensorflow.python.keras.protobuf.SavedMetadata();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"nodes\":\n                    message.nodes.push(third_party.tensorflow.python.keras.protobuf.SavedObject.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nthird_party.tensorflow.python.keras.protobuf.SavedObject = class SavedObject {\n\n    static decode(reader, length) {\n        const message = new third_party.tensorflow.python.keras.protobuf.SavedObject();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.node_id = reader.int32();\n                    break;\n                case 3:\n                    message.node_path = reader.string();\n                    break;\n                case 4:\n                    message.identifier = reader.string();\n                    break;\n                case 5:\n                    message.metadata = reader.string();\n                    break;\n                case 6:\n                    message.version = third_party.tensorflow.python.keras.protobuf.VersionDef.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new third_party.tensorflow.python.keras.protobuf.SavedObject();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"node_id\":\n                    message.node_id = reader.int32();\n                    break;\n                case \"node_path\":\n                    message.node_path = reader.string();\n                    break;\n                case \"identifier\":\n                    message.identifier = reader.string();\n                    break;\n                case \"metadata\":\n                    message.metadata = reader.string();\n                    break;\n                case \"version\":\n                    message.version = third_party.tensorflow.python.keras.protobuf.VersionDef.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nthird_party.tensorflow.python.keras.protobuf.SavedObject.prototype.node_id = 0;\nthird_party.tensorflow.python.keras.protobuf.SavedObject.prototype.node_path = \"\";\nthird_party.tensorflow.python.keras.protobuf.SavedObject.prototype.identifier = \"\";\nthird_party.tensorflow.python.keras.protobuf.SavedObject.prototype.metadata = \"\";\nthird_party.tensorflow.python.keras.protobuf.SavedObject.prototype.version = null;\n\nthird_party.tensorflow.python.keras.protobuf.VersionDef = class VersionDef {\n\n    constructor() {\n        this.bad_consumers = [];\n    }\n\n    static decode(reader, length) {\n        const message = new third_party.tensorflow.python.keras.protobuf.VersionDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.producer = reader.int32();\n                    break;\n                case 2:\n                    message.min_consumer = reader.int32();\n                    break;\n                case 3:\n                    message.bad_consumers = reader.array(message.bad_consumers, () => reader.int32(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new third_party.tensorflow.python.keras.protobuf.VersionDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"producer\":\n                    message.producer = reader.int32();\n                    break;\n                case \"min_consumer\":\n                    message.min_consumer = reader.int32();\n                    break;\n                case \"bad_consumers\":\n                    reader.array(message.bad_consumers, () => reader.int32());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nthird_party.tensorflow.python.keras.protobuf.VersionDef.prototype.producer = 0;\nthird_party.tensorflow.python.keras.protobuf.VersionDef.prototype.min_consumer = 0;\n"
  },
  {
    "path": "source/keras.js",
    "content": "\nimport * as json from './json.js';\nimport * as python from './python.js';\n\nconst keras = {};\nconst tfjs = {};\n\nkeras.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        const group = await context.peek('hdf5');\n        if (group && group.attributes && group.attributes.get('CLASS') !== 'hickle') {\n            if (identifier.endsWith('.weights.h5')) {\n                return context.set('keras.model.weights.h5', group);\n            }\n            if (identifier === 'parameter.h5') {\n                return context.set('hdf5.parameter.h5', group);\n            }\n            return context.set('keras.h5', group);\n        }\n        const json = await context.peek('json');\n        if (json) {\n            if (json.mxnet_version || (json.nodes && json.arg_nodes && json.heads)) {\n                return null;\n            }\n            if (json.model_config || (json.class_name && json.config)) {\n                return context.set('keras.config.json', json);\n            }\n            if (identifier === 'metadata.json' && json.keras_version) {\n                return context.set('keras.metadata.json', json);\n            }\n        }\n        const container = await tfjs.Container.open(context);\n        if (container) {\n            return context.set('tfjs', container);\n        }\n        const pickle = await context.peek('pkl');\n        if (pickle && pickle.__class__ &&\n            pickle.__class__.__module__ === 'keras.engine.sequential' &&\n            pickle.__class__.__name__ === 'Sequential') {\n            return context.set('tfjs.pickle', pickle);\n        }\n        // model.weights.npz\n        const entries = await context.peek('npz');\n        const regex = /^(__root__|layers\\/.+|_layer_checkpoint_dependencies\\/.+)\\.npy$/;\n        if (entries instanceof Map && entries.size > 0 && Array.from(entries).every(([name]) => regex.test(name))) {\n            return context.set('keras.model.weights.npz', entries);\n        }\n        // keras_metadata.pb\n        if (extension === 'pb' && context.stream && context.stream.length > 16) {\n            const tags = await context.tags('pb');\n            if (tags.size === 1 && tags.get(1) === 2) {\n                const stream = context.stream;\n                const buffer = stream.peek(Math.min(stream.length, 1024));\n                const content = String.fromCharCode.apply(null, buffer);\n                if (/root\"/.test(content) && /\\{\\s*\"class_name\"\\s*:/.test(content)) {\n                    return context.set('keras.pb.SavedMetadata');\n                }\n            }\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        if (context.type === 'keras.metadata.json' && (match.type === 'keras.config.json' || match.type === 'keras.model.weights.h5' || match.type === 'keras.model.weights.npz')) {\n            return false;\n        }\n        if (context.type === 'keras.config.json' && (match.type === 'keras.model.weights.h5' || match.type === 'keras.model.weights.npz')) {\n            return false;\n        }\n        if (context.type === 'tfjs' && match.type === 'tf.tfjs.weights') {\n            return false;\n        }\n        return true;\n    }\n\n    async open(context) {\n        const request_json = async (context, name) => {\n            try {\n                context = await context.fetch(name);\n            } catch {\n                return null;\n            }\n            return await context.read('json');\n        };\n        const _create_config = (weights_store) => {\n            const config = {};\n            config.class_name = 'Model';\n            config.config = {};\n            config.config.layers = [];\n            const snake_to_pascal_case = (name) => {\n                return name.replace(/(^|_|\\d)([a-z])/g, (match, p1, p2) => p1 === '_' ? p2.toUpperCase() : p1 + p2.toUpperCase());\n            };\n            for (const [name, value] of weights_store) {\n                const layer = {};\n                layer.name = name;\n                layer.class_name = name.split('/').pop().replace(/_[0-9]+$/, '');\n                layer.class_name = snake_to_pascal_case(layer.class_name);\n                layer.config = {};\n                layer.config.name = name;\n                layer._trainable_variables = value;\n                config.config.layers.push(layer);\n            }\n            return config;\n        };\n        const _load_state = (trackable, weights_store, assets_store, inner_path) => {\n            inner_path = inner_path || '';\n            if (trackable && trackable.config && Array.isArray(trackable.config.layers)) {\n                /* eslint-disable no-use-before-define */\n                _load_container_state(trackable, weights_store, assets_store, inner_path ? `${inner_path}/layers` : 'layers');\n                /* eslint-enable no-use-before-define */\n            } else {\n                const weights = weights_store.get(inner_path);\n                if (weights) {\n                    trackable._trainable_variables = weights;\n                }\n            }\n        };\n        const _load_container_state = (container, weights_store, assets_store, inner_path) => {\n            const used_names = new Map();\n            for (const trackable of container.config.layers) {\n                const pascal_to_snake_case = (name) => {\n                    name = name.replace(/\\W+/g, \"\");\n                    name = name.replace(/(.)([A-Z][a-z]+)/g, (match, p1, p2) => `${p1}_${p2}`);\n                    name = name.replace(/([a-z])([A-Z])/g, (match, p1, p2) => `${p1}_${p2}`);\n                    return name.toLowerCase();\n                };\n                let name = pascal_to_snake_case(trackable.class_name);\n                if (used_names.has(name)) {\n                    const next = used_names.get(name) + 1;\n                    used_names.set(name, next);\n                    name = `${name}_${next}`;\n                } else {\n                    used_names.set(name, 0);\n                }\n                _load_state(trackable, weights_store, assets_store, `${inner_path}/${name}`);\n            }\n        };\n        const read_weights_hdf5 = (group) => {\n            const weights_store = new Map();\n            const stack = [[group, '']];\n            while (stack.length > 0) {\n                const [group, path] = stack.pop();\n                if (group.groups instanceof Map) {\n                    const checkpoint = group.groups.get('layers') || group.groups.get('_layer_checkpoint_dependencies');\n                    if (checkpoint) {\n                        for (const [key, layer] of checkpoint.groups) {\n                            const name = `${path ? `${path}/` : ''}layers/${key}`;\n                            stack.push([layer, name]);\n                            const values = [];\n                            for (const vars of layer.groups) {\n                                for (const [name, group] of vars[1].groups) {\n                                    const variable = group.value;\n                                    if (variable) {\n                                        const layout = variable.littleEndian ? '<' : '>';\n                                        const tensor = new keras.Tensor(name, variable.shape, variable.type, null, null, layout, variable.data);\n                                        values.push(tensor);\n                                    }\n                                }\n                            }\n                            if (values.length > 0) {\n                                weights_store.set(name, values);\n                            }\n                        }\n                    }\n                }\n            }\n            return weights_store;\n        };\n        const read_weights_numpy = (entries) => {\n            const weights_store = new Map();\n            for (const [path, array] of entries) {\n                const file = path.split('/').map((name) => name === '_layer_checkpoint_dependencies' ? 'layers' : name).join('/');\n                if (file.endsWith('.npy') && file.startsWith('layers/')) {\n                    if (array.dtype.name === 'object' && array.shape.length === 0 && Array.isArray(array.data) && array.data.length === 1) {\n                        const values = Object.values(array.data[0]).map((array) => {\n                            const stride = array.strides.map((stride) => stride / array.itemsize);\n                            const dataType = array.dtype.__name__;\n                            const values = dataType === 'string' || dataType === 'object' ? array.flatten().tolist() : array.tobytes();\n                            const encoding = dataType === 'string' || dataType === 'object' ? '|' : array.dtype.byteorder;\n                            return new keras.Tensor('', array.shape, dataType, stride, null, encoding, values);\n                        });\n                        if (values.length > 0) {\n                            const name = file.replace(/\\.npy$/, '');\n                            weights_store.set(name, values);\n                        }\n                    }\n                }\n            }\n            return weights_store;\n        };\n        const request_weights = async (context) => {\n            const formats = [\n                ['model.weights.h5', 'hdf5', read_weights_hdf5],\n                ['model.weights.npz', 'npz', read_weights_numpy],\n            ];\n            for (const [name, type, callback] of formats) {\n                let content = null;\n                try {\n                    /* eslint-disable no-await-in-loop */\n                    content = await context.fetch(name);\n                    /* eslint-enable no-await-in-loop */\n                } catch {\n                    // continue regardless of error\n                }\n                if (content) {\n                    /* eslint-disable no-await-in-loop */\n                    const obj = await content.peek(type);\n                    /* eslint-enable no-await-in-loop */\n                    if (obj) {\n                        return callback(obj);\n                    }\n                }\n            }\n            return new Map();\n        };\n        const open_model = async (format, producer, backend, config, weights) => {\n            const metadata = await context.metadata('keras-metadata.json');\n            return new keras.Model(metadata, format, producer, backend, config, weights);\n        };\n        switch (context.type) {\n            case 'keras.config.json': {\n                const obj = context.value;\n                const config = obj.model_config ? obj.model_config : obj;\n                const backend = obj.backend || '';\n                let version = obj.keras_version ? obj.keras_version : null;\n                if (!version) {\n                    const metadata = await request_json(context, 'metadata.json');\n                    if (metadata && metadata.keras_version) {\n                        version = metadata.keras_version;\n                    }\n                }\n                const format = `Keras${version ? ` v${version}` : ''}`;\n                const weights_store = await request_weights(context);\n                _load_state(config, weights_store);\n                return open_model(format, '', backend, config, null);\n            }\n            case 'keras.model.weights.h5': {\n                const group = context.value;\n                const weights_store = read_weights_hdf5(group);\n                const metadata = await request_json(context, 'metadata.json');\n                let config = await request_json(context, 'config.json');\n                const name = config ? 'Keras' : 'Keras Weights';\n                const format = name + (metadata && metadata.keras_version ? ` v${metadata.keras_version}` : '');\n                if (config) {\n                    _load_state(config, weights_store);\n                } else {\n                    config = _create_config(weights_store);\n                }\n                return await open_model(format, '', '', config, null);\n            }\n            case 'keras.model.weights.npz': {\n                const entries = context.value;\n                const weights_store = read_weights_numpy(entries);\n                const metadata = await request_json(context, 'metadata.json');\n                let config = await request_json(context, 'config.json');\n                const name = config ? 'Keras' : 'Keras Weights';\n                const format = name + (metadata && metadata.keras_version ? ` v${metadata.keras_version}` : '');\n                if (config) {\n                    _load_state(config, weights_store);\n                } else {\n                    config = _create_config(weights_store);\n                }\n                return await open_model(format, '', '', config, null);\n            }\n            case 'keras.metadata.json': {\n                const metadata = context.value;\n                let config = await request_json(context, 'config.json');\n                const name = config ? 'Keras' : 'Keras Weights';\n                const format = name + (metadata.keras_version ? ` v${metadata.keras_version}` : '');\n                const weights_store = await request_weights(context);\n                if (!config && (!weights_store || weights_store.size === 0)) {\n                    throw new keras.Error(\"'config.json' or 'model.weights.*' not present.\");\n                }\n                if (config) {\n                    _load_state(config, weights_store);\n                } else {\n                    config = _create_config(weights_store);\n                }\n                return await open_model(format, '', '', config, null);\n            }\n            case 'hdf5.parameter.h5':\n            case 'keras.h5': {\n                const find_root_group = (root_group) => {\n                    const kerasmodel = root_group.group('model/kerasmodel');\n                    if (kerasmodel && kerasmodel.attributes.has('model_config')) {\n                        return kerasmodel;\n                    }\n                    return root_group;\n                };\n                const read_model_config = (group) => {\n                    if (group.attributes.has('model_config')) {\n                        const buffer = group.attributes.get('model_config');\n                        const reader = json.TextReader.open(buffer);\n                        if (reader) {\n                            return reader.read();\n                        }\n                    }\n                    return null;\n                };\n                const load_attributes_from_hdf5_group = (group, name) => {\n                    if (group.attributes.has(name)) {\n                        return group.attributes.get(name);\n                    }\n                    if (group.attributes.has(`${name}0`)) {\n                        let index = 0;\n                        let value = [];\n                        while (group.attributes.has(name + index.toString())) {\n                            const chunk = group.attributes.get(name + index.toString());\n                            value = value.concat(chunk);\n                            index++;\n                        }\n                        return value;\n                    }\n                    return null;\n                };\n                const weights = new keras.Weights();\n                const group = context.value;\n                const root_group = find_root_group(group);\n                const model_config = read_model_config(root_group);\n                if (model_config) {\n                    const backend = root_group.attributes.get('backend') || '';\n                    const version = root_group.attributes.get('keras_version') || '';\n                    const format = `Keras${version ? ` v${version}` : ''}`;\n                    const model_weights_group = root_group.group('model_weights');\n                    if (model_weights_group) {\n                        const layer_names = load_attributes_from_hdf5_group(model_weights_group, 'layer_names');\n                        for (const layer_name of layer_names) {\n                            const layer_weights = model_weights_group.group(layer_name);\n                            if (layer_weights) {\n                                const weight_names = load_attributes_from_hdf5_group(layer_weights, 'weight_names');\n                                if (Array.isArray(weight_names) && weight_names.length > 0) {\n                                    for (const weight_name of weight_names) {\n                                        const weight = layer_weights.group(weight_name);\n                                        if (weight && weight.value) {\n                                            const variable = weight.value;\n                                            const tensor = new keras.Tensor(weight_name, variable.shape, variable.type, null, null, variable.littleEndian ? '<' : '>', variable.data);\n                                            weights.add(layer_name, tensor);\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    if (!model_config) {\n                        throw new keras.Error(\"'model_config' is not present.\");\n                    }\n                    if (!model_config.class_name) {\n                        throw new keras.Error(\"'class_name' is not present.\");\n                    }\n                    return open_model(format, '', backend, model_config, weights);\n                }\n                const layer_names = load_attributes_from_hdf5_group(root_group, 'layer_names');\n                if (layer_names && Array.isArray(layer_names)) {\n                    const version = root_group.attributes.get('keras_version') || '';\n                    const format = `Keras Weights${version ? ` v${version}` : ''}`;\n                    const backend = root_group.attributes.get('backend') || '';\n                    for (const layer_name of layer_names) {\n                        const layer_weights = root_group.group(layer_name);\n                        if (layer_weights) {\n                            const weight_names = load_attributes_from_hdf5_group(layer_weights, 'weight_names');\n                            if (Array.isArray(weight_names) && weight_names.length > 0) {\n                                for (const weight_name of weight_names) {\n                                    const weight = layer_weights.group(weight_name);\n                                    if (weight && weight.value) {\n                                        const variable = weight.value;\n                                        const components = weight_name.split('/');\n                                        components.pop();\n                                        const name = (components.length === 0 || components[0] !== layer_name) ? [layer_name].concat(components).join('/') : components.join('/');\n                                        const encoding = variable.littleEndian ? '<' : '>';\n                                        const tensor = new keras.Tensor(weight_name, variable.shape, variable.type, null, null, encoding, variable.data);\n                                        weights.add(name, tensor);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    return open_model(format, '', backend, null, weights);\n                }\n                const rootKeys = new Set(root_group.attributes.keys());\n                rootKeys.delete('nb_layers');\n                if (rootKeys.size > 0 || root_group.value !== null) {\n                    throw new keras.Error('File format is not HDF5 Weights.');\n                }\n                const format = 'HDF5 Weights';\n                let weights_group = root_group;\n                if (root_group.attributes.size === 0 && root_group.value === null && root_group.groups.size === 1) {\n                    const group = root_group.groups.values().next().value;\n                    if (group.attributes.size === 0 && group.value === null) {\n                        weights_group = group;\n                    }\n                }\n                const tensorKeys = new Set(['name', 'shape', 'quantization']);\n                const groups = Array.from(weights_group.groups.values());\n                if (groups.every((group) => group.attributes.size === 0 && group.groups.length === 0 && group.value !== null)) {\n                    for (const group of groups) {\n                        const variable = group.value;\n                        const layout = variable.littleEndian ? '<' : '>';\n                        const tensor = new keras.Tensor(group.name, variable.shape, variable.type, null, null, layout, variable.type === 'string' ? variable.value : variable.data);\n                        weights.add('', tensor);\n                    }\n                    return open_model(format, '', '', null, weights);\n                }\n                if (groups.every((group) => group.value === null && Array.from(group.attributes.keys()).filter((key) => !tensorKeys.has(key)).length === 0 && Array.from(group.groups.values()).every((variable) => Object.keys(variable.attributes).length === 0 && variable.value !== null))) {\n                    for (const group of groups) {\n                        const module = group.attributes.has('name') ? group.attributes.get('name') : group.name;\n                        for (const variableGroup of group.groups.values()) {\n                            if (variableGroup.attributes.size !== 0 || variableGroup.groups.size !== 0) {\n                                throw new keras.Error('Variable format is not HDF5 Weights.');\n                            }\n                            const variable = variableGroup.value;\n                            if (!variable) {\n                                throw new keras.Error('Variable value is not HDF5 Weights.');\n                            }\n                            const name = module ? [module, variableGroup.name].join('/') : variableGroup.name;\n                            const layout = variable.littleEndian ? '<' : '>';\n                            const tensor = new keras.Tensor(name, variable.shape, variable.type, null, null, layout, variable.type === 'string' ? variable.value : variable.data);\n                            weights.add(module, tensor);\n                        }\n                    }\n                    return open_model(format, '', '', null, weights);\n                }\n                const walk = function(group) {\n                    if (group.attributes.size === 0 && group.value === null && group.groups.size > 0) {\n                        for (const subGroup of group.groups.values()) {\n                            walk(subGroup);\n                        }\n                        return;\n                    }\n                    const subKeys = new Set(['index', 'need_grad']);\n                    const attribtues = Array.from(group.attributes.keys());\n                    const match = attribtues.filter((key) => !subKeys.has(key)).length === 0;\n                    if (match && group.value !== null && group.groups.size === 0) {\n                        const variable = group.value;\n                        const variableName = group.path;\n                        let moduleName = variableName;\n                        const parts = variableName.split('/');\n                        if (parts.length > 1) {\n                            parts.pop();\n                            moduleName = parts.join('/');\n                        }\n                        const layout = variable.littleEndian ? '<' : '>';\n                        const tensor = new keras.Tensor(variableName, variable.shape, variable.type, null, null, layout, variable.type === 'string' ? variable.value : variable.data);\n                        weights.add(moduleName, tensor);\n                        return;\n                    }\n                    throw new keras.Error('Module group format is not HDF5 Weights.');\n                };\n                walk(weights_group);\n                return open_model(format, '', '', null, weights);\n            }\n            case 'tfjs': {\n                const target = context.value;\n                await target.read();\n                return open_model(target.format, target.producer, target.backend, target.config, target.weights);\n            }\n            case 'keras.pickle': {\n                const obj = context.value;\n                const execution = new python.Execution();\n                const decoder = new TextDecoder('utf-8');\n                const format = `Keras Pickle${obj.keras_version ? ` v${decoder.decode(obj.keras_version)}` : ''}`;\n                const backend = obj.backend ? decoder.decode(obj.backend) : '';\n                const reader = json.TextReader.open(obj.model_config);\n                const model_config = reader.read();\n                const weights = new keras.Weights();\n                const model_weights_group = obj.model_weights;\n                if (model_weights_group) {\n                    const layer_names = model_weights_group.layer_names.map((buffer) => decoder.decode(buffer));\n                    for (const layer_name of layer_names) {\n                        const layer_weights = model_weights_group[layer_name];\n                        if (layer_weights) {\n                            const weight_names = layer_weights.weight_names.map((buffer) => decoder.decode(buffer));\n                            if (Array.isArray(weight_names) && weight_names.length > 0) {\n                                for (const weight_name of weight_names) {\n                                    const buffer = layer_weights[weight_name];\n                                    const pickle = execution.__import__('pickle');\n                                    const unpickler = new pickle.Unpickler(buffer);\n                                    const variable = unpickler.load();\n                                    const tensor = new keras.Tensor(weight_name, variable.shape, variable.dtype.__name__, null, null, '<', variable.data);\n                                    weights.add(layer_name, tensor);\n                                }\n                            }\n                        }\n                    }\n                }\n                return open_model(format, '', backend, model_config, weights);\n            }\n            case 'keras.pb.SavedMetadata': {\n                keras.proto = await context.require('./keras-proto');\n                const format = 'Keras Saved Metadata';\n                const reader = await context.read('protobuf.binary');\n                const saved_metadata = keras.proto.third_party.tensorflow.python.keras.protobuf.SavedMetadata.decode(reader);\n                if (!saved_metadata || !Array.isArray(saved_metadata.nodes) ||\n                    !saved_metadata.nodes.every((node) => node && typeof node.metadata === 'string' && node.metadata.length > 0)) {\n                    throw new keras.Error('Invalid keras.protobuf.SavedMetadata.');\n                }\n                const objects = new Map();\n                for (const node of saved_metadata.nodes) {\n                    const reader = json.TextReader.open(node.metadata);\n                    node.metadata = reader.read();\n                    objects.set(node.node_path, node);\n                }\n                const model_config = objects.get('root').metadata;\n                return open_model(format, '', '', model_config, null);\n            }\n            default: {\n                throw new keras.Error(`Unsupported Keras format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nkeras.Model = class {\n\n    constructor(metadata, format, producer, backend, config, weights) {\n        this.format = format;\n        this.runtime = backend;\n        this.producer = producer;\n        metadata = new keras.GraphMetadata(metadata);\n        this.modules = [new keras.Graph(metadata, config, weights)];\n    }\n};\n\nkeras.Graph = class {\n\n    constructor(metadata, config, weights, group) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        group = group || '';\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (tensor) {\n                return new keras.Value(name, type || null, tensor);\n            }\n            if (!values.has(name)) {\n                values.set(name, new keras.Value(name, type || null, tensor || null));\n            } else if (type || tensor) {\n                throw new keras.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        if (config) {\n            const getInputType = (layer) => {\n                if (layer && layer.config) {\n                    let dataType = '?';\n                    let shape = [];\n                    const config = layer.config;\n                    if (config.dtype) {\n                        dataType = config.dtype;\n                        delete config.dtype;\n                    }\n                    if (Array.isArray(config.batch_input_shape)) {\n                        shape = config.batch_input_shape.map((s) => s === null ? '?' : s);\n                        delete config.batch_input_shape;\n                    } else if (config.batch_input_shape &&\n                        config.batch_input_shape.class_name === '__tuple__' &&\n                        Array.isArray(config.batch_input_shape.items)) {\n                        shape = config.batch_input_shape.items.map((s) => s === null ? '?' : s);\n                        delete config.batch_input_shape;\n                    }\n                    return new keras.TensorType(dataType, new keras.TensorShape(shape));\n                }\n                return null;\n            };\n            this.name = config.name || (config.config && config.config.name ? config.config.name : '');\n            this.description = config.class_name;\n            let baseType = config.class_name;\n            switch (baseType) {\n                case '__Function__':\n                    this.type = 'function';\n                    break;\n                case 'Sequential':\n                case 'Functional':\n                case 'Model': {\n                    break;\n                }\n                case 'Tokenizer': {\n                    config = { config: { layers: [config] } };\n                    baseType = 'Functional';\n                    break;\n                }\n                default: {\n                    const layers = Array.from(config.layers ? config.layers : config);\n                    const sequential = layers.every((layer) => layer.inbound_nodes === undefined);\n                    baseType = sequential ? 'Sequential' : 'Functional';\n                    break;\n                }\n            }\n            switch (baseType) {\n                case 'Sequential': {\n                    config = config.config;\n                    const outputs = null;\n                    let name = 'input';\n                    let index = -1;\n                    const layers = Array.from(config.layers ? config.layers : config);\n                    while (layers.length > 0) {\n                        const layer = layers.shift();\n                        let current = index.toString();\n                        index++;\n                        if (index === 0) {\n                            const type = getInputType(layer);\n                            let remove = false;\n                            if (layer.class_name === 'InputLayer' && layer.config && layer.config.name) {\n                                name = layer.config.name;\n                                remove = true;\n                            }\n                            const value = values.map(name, type);\n                            const argument = new keras.Argument(name, [value]);\n                            this.inputs.push(argument);\n                            if (remove) {\n                                continue;\n                            }\n                        }\n                        const nodeInputs = [{ name }];\n                        if (layer.config && layer.config.name) {\n                            current = layer.config.name;\n                        }\n                        name = current;\n                        let nodeOutputs = [name];\n                        if (index === layers.length) {\n                            if (outputs && outputs.length > 0) {\n                                nodeOutputs = [outputs[0]];\n                                name = null;\n                            }\n                        }\n                        layer.inputs = nodeInputs;\n                        layer.outputs = nodeOutputs;\n                        const node = new keras.Node(metadata, layer, group, weights, values);\n                        this.nodes.push(node);\n                    }\n                    if (name) {\n                        const value = values.map(name);\n                        const argument = new keras.Argument(name, [value]);\n                        this.outputs.push(argument);\n                    }\n                    break;\n                }\n                case '__Function__':\n                case 'Functional':\n                case 'Model': {\n                    config = config.config;\n                    const nodes = new Map();\n                    if (config.layers) {\n                        const is_constant = (item) => {\n                            return Array.isArray(item) && (item.length === 3 || item.length === 4) && item[0] === '_CONSTANT_VALUE' && item[1] === -1;\n                        };\n                        const is_connection = (item) => {\n                            return Array.isArray(item) && (item.length === 3 || item.length === 4) && typeof item[0] === 'string' && typeof item[1] === 'number'  && typeof item[2] === 'number';\n                        };\n                        const read_value = (input_data) => {\n                            if (!Array.isArray(input_data)) {\n                                return input_data;\n                            }\n                            const transform = (value) => {\n                                if (value.every((item) => is_constant(item))) {\n                                    for (let i = 0; i < value.length; i++) {\n                                        value[i] = value[i][2];\n                                    }\n                                } else if (value.every((item) => Array.isArray(item))) {\n                                    const dims = value.map((item) => transform(item));\n                                    const [dim] = dims;\n                                    for (let i = 1; i < dims.length; i++) {\n                                        if (dim.length === dims[i].length) {\n                                            if (!dims[i].every((value, i) => value === dim[i])) {\n                                                throw new python.Error('Invalid array shape.');\n                                            }\n                                        }\n                                    }\n                                    return [value.length].concat(dim);\n                                }\n                                return [value.length];\n                            };\n                            const shape = transform(input_data);\n                            const flatten = (input) => input.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);\n                            const value = flatten(input_data);\n                            return { shape, value };\n                        };\n                        const functional = config.layers.every((layer) => Array.isArray(layer.inbound_nodes));\n                        if (functional) {\n                            const read_connection = (input_data) => {\n                                const [node_name, node_index, tensor_index] = input_data;\n                                const inbound_node_key = `${node_name}[${node_index}]`;\n                                const inbound_node = nodes.get(inbound_node_key);\n                                const tensor_key = `${node_name}[${node_index}][${tensor_index}]`;\n                                if (inbound_node) {\n                                    while (tensor_index >= inbound_node.outputs.length) {\n                                        inbound_node.outputs.push(undefined);\n                                    }\n                                    inbound_node.outputs[tensor_index] = tensor_key;\n                                }\n                                return tensor_key;\n                            };\n                            const process_node = (node, inbound_node) => {\n                                if (Array.isArray(inbound_node) && inbound_node.length === 4 && typeof inbound_node[0] === 'string') {\n                                    const key = read_connection(inbound_node);\n                                    node.inputs.push({ name: key });\n                                    for (const [name, value] of Object.entries(inbound_node[3])) {\n                                        if (is_connection(value)) {\n                                            const key = read_connection(value);\n                                            node.inputs.push({ name: key });\n                                        } else if (Array.isArray(value)) {\n                                            const array = read_value(value);\n                                            node.args[name] = array;\n                                        } else {\n                                            node.args[name] = value;\n                                        }\n                                    }\n                                } else if (Array.isArray(inbound_node)) {\n                                    for (const input_data of inbound_node) {\n                                        // [ 'conv2d', 0, 0 ] or [ 'conv2d', 0, 0, {} ]\n                                        if (Array.isArray(input_data) && is_connection(input_data)) {\n                                            const key = read_connection(input_data);\n                                            node.inputs.push({ name: key });\n                                        } else if (Array.isArray(input_data) && input_data.every((item) => is_connection(item))) {\n                                            for (const input of input_data) {\n                                                const key = read_connection(input);\n                                                node.inputs.push({ name: key });\n                                            }\n                                        } else if (Array.isArray(input_data)) {\n                                            const value = read_value(input_data);\n                                            node.inputs.push(value);\n                                        } else {\n                                            throw new keras.Error(`Invalid inbound connection '${JSON.stringify(input_data)}'.`);\n                                        }\n                                    }\n                                } else if (inbound_node && inbound_node.args) {\n                                    for (const arg of inbound_node.args) {\n                                        if (arg && arg.class_name === '__keras_tensor__' && arg.config && is_connection(arg.config.keras_history)) {\n                                            const key = read_connection(arg.config.keras_history);\n                                            node.inputs.push({ name: key });\n                                        } else if (Array.isArray(arg) && arg.every((arg) => arg && arg.class_name === '__keras_tensor__' && arg.config && is_connection(arg.config.keras_history))) {\n                                            for (const input of arg) {\n                                                const key = read_connection(input.config.keras_history);\n                                                node.inputs.push({ name: key });\n                                            }\n                                        }\n                                    }\n                                }\n                            };\n                            let legacy_format = true;\n                            for (const layer of config.layers) {\n                                if (Array.isArray(layer.inbound_nodes)) {\n                                    for (const inbound_node of layer.inbound_nodes) {\n                                        if (Array.isArray(inbound_node.args)) {\n                                            legacy_format = false;\n                                        }\n                                    }\n                                }\n                            }\n                            for (const layer of config.layers) {\n                                const class_name = layer.class_name;\n                                let first_index = 0;\n                                if (legacy_format) {\n                                    const keys = new Set(Object.keys(layer.config));\n                                    const is_functional_config = keys.has('name') && keys.has('layers') && keys.has('input_layers') && keys.has('output_layers');\n                                    if (class_name === 'Sequential' ||\n                                        (is_functional_config && Array.isArray(layer.config.layers) && layer.config.layers.length > 0 && layer.config.layers[0].class_name === 'InputLayer')) {\n                                        first_index++;\n                                    }\n                                }\n                                if (Array.isArray(layer.inbound_nodes) && layer.inbound_nodes.length === 0) {\n                                    layer.inputs = [];\n                                    layer.outputs = [];\n                                    layer.args = {};\n                                    nodes.set(`${layer.name}[${first_index}]`, layer);\n                                } else if (Array.isArray(layer.inbound_nodes) && layer.inbound_nodes.length === 1) {\n                                    layer.inputs = [];\n                                    layer.outputs = [];\n                                    layer.args = {};\n                                    [layer.inbound_node] = layer.inbound_nodes;\n                                    nodes.set(`${layer.name}[${first_index}]`, layer);\n                                } else {\n                                    let config = {};\n                                    switch (class_name) {\n                                        case 'Functional':\n                                        case 'Sequential':\n                                        case 'Model': {\n                                            config = layer;\n                                            break;\n                                        }\n                                        default: {\n                                            config.class_name = '__Function__';\n                                            config.name = layer.name;\n                                            config.config = {};\n                                            config.config.layers = [{ ...layer }];\n                                            delete config.config.layers[0].inbound_nodes;\n                                            delete config.config.layers[0].input_layers;\n                                            delete config.config.layers[0].output_layers;\n                                            break;\n                                        }\n                                    }\n                                    const type = new keras.Graph(metadata, config, weights, '');\n                                    for (let i = 0; i < layer.inbound_nodes.length; i++) {\n                                        const index = i + first_index;\n                                        const key = `${layer.name}[${index}]`;\n                                        const node = {};\n                                        node.name = key;\n                                        node.class_name = '__Function__';\n                                        node.config = {};\n                                        node.config.name = key;\n                                        node.inputs = [];\n                                        node.outputs = [];\n                                        node.args = {};\n                                        node.__type__ = type;\n                                        node.inbound_node = layer.inbound_nodes[i];\n                                        nodes.set(key, node);\n                                    }\n                                }\n                            }\n                            for (const entry of nodes) {\n                                if (entry[1].inbound_node) {\n                                    process_node(entry[1], entry[1].inbound_node);\n                                }\n                            }\n                            if (Array.isArray(config.input_layers)) {\n                                if (config.input_layers.length === 3 && typeof config.input_layers[0] === 'string' && Number.isInteger(config.input_layers[1]) && Number.isInteger(config.input_layers[2])) {\n                                    config.input_layers = [config.input_layers];\n                                }\n                                for (let i = 0; i < config.input_layers.length; i++) {\n                                    const input_data = config.input_layers[i];\n                                    const name = read_connection(input_data);\n                                    const [node_name, node_index] = input_data;\n                                    const inbound_node_key = `${node_name}[${node_index}]`;\n                                    const node = nodes.get(inbound_node_key);\n                                    let type = null;\n                                    if (node && node.class_name === 'InputLayer') {\n                                        type = getInputType(node);\n                                        nodes.delete(name);\n                                        nodes.delete(inbound_node_key);\n                                    }\n                                    const value = values.map(name, type);\n                                    const argument = new keras.Argument(node_name, [value]);\n                                    this.inputs.push(argument);\n                                }\n                            }\n                            if (Array.isArray(config.output_layers)) {\n                                if (config.output_layers.length === 3 && typeof config.output_layers[0] === 'string' && Number.isInteger(config.output_layers[1]) && Number.isInteger(config.output_layers[2])) {\n                                    config.output_layers = [config.output_layers];\n                                }\n                                for (let i = 0; i < config.output_layers.length; i++) {\n                                    const output_data = config.output_layers[i];\n                                    const [name] = output_data;\n                                    const key = read_connection(output_data);\n                                    const value = values.map(key);\n                                    const argument = new keras.Argument(name, [value]);\n                                    this.outputs.push(argument);\n                                }\n                            }\n                        } else {\n                            for (const layer of config.layers) {\n                                layer.inputs = [];\n                                layer.outputs = [];\n                                layer.args = {};\n                                nodes.set(`${layer.name}[0]`, layer);\n                            }\n                        }\n                    }\n                    for (const entry of nodes) {\n                        const node = new keras.Node(metadata, entry[1], group, weights, values);\n                        this.nodes.push(node);\n                    }\n                    break;\n                }\n                default: {\n                    throw new keras.Error(`'${config.class_name}' is not supported.`);\n                }\n            }\n        } else if (weights) {\n            this.type = 'weights';\n            for (const name of weights.keys()) {\n                if (weights.get('', name).length <= 6) {\n                    const layer = { class_name: 'Weights', config: { name } };\n                    const node = new keras.Node(metadata, layer, '', weights, values);\n                    this.nodes.push(node);\n                }\n            }\n        }\n    }\n};\n\nkeras.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nkeras.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new keras.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type  : type;\n        this.quantization = initializer && initializer.quantization ? initializer.quantization : null;\n        this.initializer = initializer;\n    }\n};\n\nkeras.Node = class {\n\n    constructor(metadata, layer, group, weights, values) {\n        const config = layer.config || {};\n        const args = layer.args || {};\n        let inputs = layer.inputs || [];\n        let outputs = layer.outputs || [];\n        const name = config && config.name ? config.name : '';\n        this.group = group || '';\n        this.name = (this.group ? `${this.group}/` : '') + name;\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        this.chain = [];\n        let names = [name];\n        let class_name = layer.class_name;\n        let model = false;\n        switch (class_name) {\n            case '__Function__': {\n                this.type = layer.__type__;\n                model = true;\n                break;\n            }\n            case 'Model':\n            case 'Functional':\n            case 'Sequential': {\n                const name = layer.name || (layer.config ? layer.config.name : '');\n                this.type = new keras.Graph(metadata, layer, weights, (group ? `${group}/` : '') + name);\n                model = true;\n                if (config) {\n                    delete config.layers;\n                    delete config.input_layers;\n                    delete config.output_layers;\n                }\n                this.inputs = [new keras.Argument('inputs', inputs.map((input) => values.map(input.name)))];\n                this.outputs = [new keras.Argument('outputs', outputs.filter((name) => name !== undefined).map((name) => values.map(name)))];\n                inputs = [];\n                outputs = [];\n                break;\n            }\n            case 'Wrapper':\n            case 'Bidirectional':\n            case 'TimeDistributed': {\n                if (config && config.layer) {\n                    const inner = config.layer;\n                    delete config.layer;\n                    this.inner = new keras.Node(metadata, inner, null, null, values);\n                    if (class_name === 'Bidirectional' && inner.config.name) {\n                        names = [`${name}/forward_${inner.config.name}`, `${name}/backward_${inner.config.name}`];\n                        if (!group) {\n                            group = name;\n                        }\n                    }\n                }\n                this.type = metadata.type(class_name) || { name: class_name };\n                break;\n            }\n            case 'TFOpLambda': {\n                if (config && config.function) {\n                    class_name = config.function;\n                    delete config.function;\n                }\n                this.type = metadata.type(class_name) || { name: class_name };\n                break;\n            }\n            default: {\n                this.type = metadata.type(class_name) || { name: class_name };\n                break;\n            }\n        }\n\n        if (layer._trainable_variables) {\n            if (inputs.length === 0 && Array.isArray(this.type.inputs) && this.type.inputs.length > 0) {\n                // weights-only, remove 'input' from type metadata\n                this.type = { ...this.type };\n                this.type.inputs = this.type.inputs.slice(1);\n            }\n            for (const variable of layer._trainable_variables) {\n                inputs.push({ name: '', initializer: variable });\n            }\n        } else if (weights && !model) {\n            for (const name of names) {\n                let tensors = weights.get(group, name);\n                if (tensors.length > 0) {\n                    for (const initializer of tensors) {\n                        inputs.push({ name: initializer.name, initializer });\n                    }\n                } else {\n                    tensors = weights.get('', name);\n                    for (const initializer of tensors) {\n                        inputs.push({ name: initializer.name, initializer });\n                    }\n                }\n            }\n        }\n\n        const attributes = [];\n\n        const convertAttributeValue = (value) => {\n            if (Array.isArray(value) || value !== Object(value)) {\n                return value;\n            }\n            const obj = {};\n            if (value.class_name) {\n                obj.__type__ = value.class_name;\n            }\n            if (value.config) {\n                const config = value.config;\n                for (const [key, value] of Object.entries(config)) {\n                    obj[key] = convertAttributeValue(value);\n                }\n            }\n            return obj;\n        };\n\n        if (config && !Array.isArray(config)) {\n            for (const [name, value] of Object.entries(config)) {\n                if (class_name !== 'Activation' && name === 'activation' && value !== 'linear') {\n                    if (typeof value === 'string') {\n                        const config = { activation: value };\n                        const node = new keras.Node(metadata, { class_name: 'Activation', config }, null, null, value);\n                        this.chain.push(node);\n                    } else if (value && typeof value.class_name === 'string' && value.config) {\n                        const type = value.class_name;\n                        if (!metadata.type(type)) {\n                            metadata.add(type, { name: type, category: 'Activation' });\n                        }\n                        const node = new keras.Node(metadata, value, null, null, value);\n                        this.chain.push(node);\n                    }\n                }\n                if (name !== 'name' && name !== 'batch_input_shape') {\n                    const schema = metadata.attribute(class_name, name);\n                    attributes.push([schema, name, value]);\n                }\n            }\n        }\n\n        const innerType = this.inner ? this.inner.type : null;\n        const innerMetadata = innerType ? metadata.type(innerType) : null;\n        let inputIndex = 0;\n        while (inputs.length > 0) {\n            let list = false;\n            let name = null;\n            let visible = true;\n            if (!innerMetadata || inputIndex === 0) {\n                if (this.type && this.type.inputs && inputIndex < this.type.inputs.length) {\n                    const input = this.type.inputs[inputIndex];\n                    name = input.name;\n                    if (class_name === 'BatchNormalization' && name === 'gamma' && config.scale === false) {\n                        inputIndex++;\n                        continue;\n                    }\n                    visible = input.visible !== false;\n                    if (this.type.inputs[inputIndex].list) {\n                        list = true;\n                    }\n                }\n            } else {\n                switch (class_name) {\n                    case 'Bidirectional': {\n                        let innerIndex = inputIndex;\n                        if (innerMetadata && innerMetadata.inputs) {\n                            if (innerIndex < innerMetadata.inputs.length) {\n                                name = `forward_${innerMetadata.inputs[innerIndex].name}`;\n                            } else {\n                                innerIndex = innerIndex - innerMetadata.inputs.length + 1;\n                                if (innerIndex < innerMetadata.inputs.length) {\n                                    name = `backward_${innerMetadata.inputs[innerIndex].name}`;\n                                }\n                            }\n                        }\n                        visible = false;\n                        break;\n                    }\n                    case 'TimeDistributed':\n                        if (innerMetadata && innerMetadata.inputs && inputIndex < innerMetadata.inputs.length) {\n                            name = innerMetadata.inputs[inputIndex].name;\n                        }\n                        break;\n                    default:\n                        break;\n                }\n            }\n            const input = list ? inputs.splice(0, inputs.length) : [inputs.shift()];\n            const inputArguments = input.map((input) => {\n                if (input.name) {\n                    return values.map(input.name, null, input.initializer);\n                }\n                if (input.initializer) {\n                    return values.map(input.name, null, input.initializer);\n                }\n                if (input.value !== undefined) {\n                    const tensor = new keras.Tensor('', input.shape, config.dtype || '?', null, null, '|', input.value);\n                    return values.map('', null, tensor);\n                }\n                throw new keras.Error(`Invalid argument '${JSON.stringify(input.name)}'.`);\n            });\n            if (!name && inputArguments.length === 1 && inputArguments[0].initializer && inputArguments[0].initializer.name) {\n                if (names.length === 1 && names[0] === '') {\n                    name = inputArguments[0].initializer.name;\n                } else {\n                    const parts = inputArguments[0].initializer.name.split('/').pop().split(':').shift().split('_');\n                    const inputName1 = parts.pop();\n                    const inputName2 = parts.length > 0 ? [parts.pop(), inputName1].join('_') : '';\n                    const inputNames = new Set(['recurrent_kernel', 'running_mean', 'running_std', 'moving_mean', 'moving_variance', 'depthwise_filter', 'pointwise_filter']);\n                    name = inputNames.has(inputName2) ? inputName2 : inputName1;\n                }\n            }\n            const argument = new keras.Argument(name || inputIndex.toString(), inputArguments, null, visible);\n            this.inputs.push(argument);\n            inputIndex++;\n        }\n\n        for (let i = 0; i < outputs.length; i++) {\n            const output = outputs[i];\n            const name = this.type && this.type.outputs && i < this.type.outputs.length && this.type.outputs[i] && this.type.outputs[i].name ? this.type.outputs[i].name : i.toString();\n            const argument = new keras.Argument(name, output === undefined || output.length === 0 ? [] : [values.map(output)]);\n            this.outputs.push(argument);\n        }\n\n        const inputTypes = new Map((this.type.inputs || []).map((input) => [input.name, input.type]));\n        for (const [name, arg] of Object.entries(args)) {\n            if (name !== 'name') {\n                if ((arg && arg.name) || (inputTypes.has(name) && inputTypes.get(name) === 'Tensor' && arg)) {\n                    if (arg.name) {\n                        const value = values.map(arg.name);\n                        const argument = new keras.Argument(name, [value]);\n                        this.inputs.push(argument);\n                    } else {\n                        const tensor = new keras.Tensor('', arg.shape, config.dtype || '?', null, null, '|', arg.value);\n                        const value = values.map('', null, tensor);\n                        const argument = new keras.Argument(name, [value]);\n                        this.inputs.push(argument);\n                    }\n                } else {\n                    const schema = metadata.attribute(class_name, name);\n                    this.attributes.push([schema, name, arg]);\n                }\n            }\n        }\n\n        this.attributes = attributes.map(([metadata, name, value]) => {\n            let type = null;\n            let visible = true;\n            if (value && typeof value === 'object' && value.class_name && value.config) {\n                value = convertAttributeValue(value);\n            }\n            switch (name) {\n                case 'trainable':\n                    type = 'boolean';\n                    visible = false;\n                    break;\n                case 'dtype':\n                    visible = false;\n                    break;\n                default: {\n                    if (metadata) {\n                        type = metadata.type ? metadata.type : type;\n                        if (metadata.visible === false) {\n                            visible = false;\n                        } else if (metadata.default !== undefined) {\n                            if (Array.isArray(value)) {\n                                if (Array.isArray(metadata.default)) {\n                                    visible = value.length !== metadata.default || !value.every((item, index) => item === metadata.default[index]);\n                                } else {\n                                    visible = !value.every((item) => item === metadata.default);\n                                }\n                            } else {\n                                visible = value !== metadata.default;\n                            }\n                        }\n                    }\n                    break;\n                }\n            }\n            return new keras.Argument(name, value, type, visible);\n        });\n\n        if (typeof this.type.name !== 'string' || !this.type.name.split) { // #416\n            throw new keras.Error(`Unsupported node type '${JSON.stringify(this.type.name)}'.`);\n        }\n    }\n};\n\nkeras.Tensor = class {\n\n    constructor(name, shape, type, stride, quantization, encoding, data, location) {\n        this.name = name;\n        this.type = new keras.TensorType(type, new keras.TensorShape(shape));\n        this.stride = stride;\n        this.encoding = encoding;\n        this._data = data;\n        this.location = location;\n        if (quantization && (quantization.scale !== 0 || quantization.min !== 0)) {\n            this.quantization = {\n                type: 'linear',\n                scale: [quantization.scale],\n                min: [quantization.min]\n            };\n        }\n    }\n\n    get values() {\n        if (this.encoding === '|') {\n            return this._data;\n        }\n        if (this._data === null) {\n            return null;\n        }\n        return this._data instanceof Uint8Array ? this._data : this._data.peek();\n    }\n};\n\nkeras.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nkeras.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return this.dimensions && this.dimensions.length > 0 ? (`[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`) : '';\n    }\n};\n\nkeras.GraphMetadata = class {\n\n    constructor(metadata) {\n        this._metadata = metadata;\n        this._types = new Map();\n    }\n\n    type(name) {\n        if (this._types.has(name)) {\n            return this._types.get(name);\n        }\n        return this._metadata.type(name);\n    }\n\n    attribute(type, name) {\n        return this._metadata.attribute(type, name);\n    }\n\n    add(type, metadata) {\n        this._types.set(type, metadata);\n    }\n};\n\nkeras.Weights = class {\n\n    constructor() {\n        this._map = new Map();\n    }\n\n    get empty() {\n        return this._map.size === 0;\n    }\n\n    add(layer_name, tensor) {\n        if (!this._map.has(layer_name)) {\n            this._map.set(layer_name, []);\n        }\n        this._map.get(layer_name).push(tensor);\n    }\n\n    get(group, name) {\n        if (group) {\n            const list = this._map.get(group.split('/').shift());\n            if (list) {\n                const match1 = list.filter((tensor) => tensor.name.startsWith(`${name}/`));\n                if (match1.length > 0) {\n                    return match1;\n                }\n                const match2 = list.filter((tensor) => tensor.name.startsWith(`${group}/${name}/`));\n                if (match2.length > 0) {\n                    return match2;\n                }\n            }\n        } else {\n            const match1 = this._map.get(name);\n            if (match1 && match1.length > 0) {\n                return match1;\n            }\n            const match2 = this._map.get('');\n            if (match2 && match2.length > 0) {\n                const match3 = match2.filter((tensor) => tensor.name.startsWith(`${(group ? `${group}/` : '') + name}/`));\n                if (match3.length > 0) {\n                    return match3;\n                }\n            }\n        }\n        return [];\n    }\n\n    keys() {\n        return this._map.keys();\n    }\n};\n\nkeras.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Keras model.';\n    }\n};\n\ntfjs.Container = class {\n\n    static async open(context) {\n        const json = await context.peek('json');\n        if (json) {\n            if (json.modelTopology && (json.format === 'layers-model' || json.modelTopology.class_name || json.modelTopology.model_config)) {\n                return new tfjs.Container(context, '');\n            }\n            if (Array.isArray(json) && json.every((item) => item.weights && item.paths)) {\n                return new tfjs.Container(context, 'weights.json');\n            }\n            if (json.tfjsVersion) {\n                return new tfjs.Container(context, 'metadata');\n            }\n        }\n        const identifier = context.identifier;\n        if (/^.*group\\d+-shard\\d+of\\d+(\\.bin)?$/.test(identifier)) {\n            return new tfjs.Container(context, 'weights.bin');\n        }\n        return null;\n    }\n\n    constructor(context, type) {\n        this.context = context;\n        this.type = type;\n    }\n\n    async read() {\n        const context = this.context;\n        switch (this.type) {\n            case '': {\n                const obj = await context.peek('json');\n                return this._openModelJson(obj);\n            }\n            case 'weights.json': {\n                this.format = 'TensorFlow.js Weights';\n                this.config = null;\n                const obj = await context.peek('json');\n                const manifests = Array.from(obj);\n                for (const manifest of manifests) {\n                    for (const weight of manifest.weights) {\n                        const name = weight.name;\n                        const index = name.lastIndexOf('/');\n                        weight.identifier = index === -1 ? name : name.substring(0, index);\n                    }\n                }\n                return this._openManifests(manifests);\n            }\n            case 'weights.bin': {\n                const content = await this.context.fetch('model.json');\n                const obj = await content.read('json');\n                return this._openModelJson(obj);\n            }\n            case 'metadata': {\n                const content = await this.context.fetch('model.json');\n                const obj = await content.read('json');\n                return this._openModelJson(obj);\n            }\n            default: {\n                throw new tfjs.Error(`Unsupported TensorFlow.js format '${this.type}'.`);\n            }\n        }\n    }\n\n    _openShards(manifests, shards) {\n        this.weights = new keras.Weights();\n        const dtype_size_map = new Map([\n            ['float16', 2], ['float32', 4], ['float64', 8],\n            ['int8', 1], ['int16', 2], ['int32', 4], ['int64', 8],\n            ['uint8', 1], ['uint16', 2], ['uint32', 4], ['uint64', 8]\n        ]);\n        for (const manifest of manifests) {\n            let buffer = null;\n            let location = '';\n            if (Array.isArray(manifest.paths) && manifest.paths.length > 0 && manifest.paths.every((path) => shards.has(path))) {\n                const list = manifest.paths.map((path) => shards.get(path));\n                location = manifest.paths.join(', ');\n                const size = list.reduce((a, b) => a + b.length, 0);\n                buffer = new Uint8Array(size);\n                let offset = 0;\n                for (const item of list) {\n                    buffer.set(item, offset);\n                    offset += item.length;\n                }\n            }\n            let offset = 0;\n            for (const weight of manifest.weights) {\n                const dtype = weight.quantization && weight.quantization.dtype ? weight.quantization.dtype : weight.dtype;\n                if (!dtype_size_map.has(dtype)) {\n                    throw new keras.Error(`Unsupported weight data type size '${dtype}'.`);\n                }\n                const itemsize = dtype_size_map.get(dtype);\n                const size = weight.shape.reduce((a, b) => a * b, 1);\n                const length = itemsize * size;\n                const data = buffer ? buffer.slice(offset, offset + length) : null;\n                const tensor = new keras.Tensor(weight.name, weight.shape, dtype, null, weight.quantization, '<', data, location);\n                this.weights.add(weight.identifier, tensor);\n                offset += length;\n            }\n        }\n    }\n\n    async _openManifests(manifests) {\n        const shards = new Map();\n        for (const manifest of manifests) {\n            for (const path of manifest.paths) {\n                if (!shards.has(path)) {\n                    const promise = this.context.fetch(path);\n                    shards.set(path, promise);\n                }\n            }\n        }\n        const promises = shards.values();\n        try {\n            const contexts = await Promise.all(promises);\n            for (const key of shards.keys()) {\n                const context = contexts.shift();\n                const buffer = context.stream.peek();\n                shards.set(key, buffer);\n            }\n            this._openShards(manifests, shards);\n        } catch {\n            shards.clear();\n            this._openShards(manifests, shards);\n        }\n    }\n\n    _openModelJson(obj) {\n        if (!obj || !obj.modelTopology || (obj.format !== 'layers-model' && !obj.modelTopology.model_config && !obj.modelTopology.config)) {\n            throw new tfjs.Error('File format is not TensorFlow.js layers-model.');\n        }\n        const modelTopology = obj.modelTopology;\n        if (obj.format) {\n            this.format = `TensorFlow.js ${obj.format}`;\n        } else if (modelTopology.keras_version) {\n            const match = modelTopology.keras_version.match(/^(.+)\\s+(\\d.*)$/);\n            const version = match ? `${match[1]} v${match[2]}` : `v${modelTopology.keras_version}`;\n            this.format = `TensorFlow.js Keras ${version}`;\n        } else {\n            this.format = 'TensorFlow.js Keras';\n        }\n        this.producer = obj.convertedBy || obj.generatedBy || '';\n        this.backend = modelTopology.backend || '';\n        const manifests = obj.weightsManifest;\n        for (const manifest of manifests) {\n            for (const weight of manifest.weights) {\n                weight.identifier = '';\n            }\n        }\n        this.config = modelTopology.model_config ? modelTopology.model_config : modelTopology;\n        return this._openManifests(manifests);\n    }\n};\n\ntfjs.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading TensorFlow.js model.';\n    }\n};\n\nexport const ModelFactory = keras.ModelFactory;\n"
  },
  {
    "path": "source/kmodel.js",
    "content": "\nimport * as base from './base.js';\n\nconst kmodel = {};\n\nkmodel.ModelFactory = class {\n\n    async match(context) {\n        const reader = kmodel.Reader.open(context.stream);\n        if (reader) {\n            return context.set('kmodel', reader);\n        }\n        return null;\n    }\n\n    async open(context) {\n        const target = context.value;\n        target.read();\n        return new kmodel.Model(target);\n    }\n};\n\nkmodel.Model = class {\n\n    constructor(model) {\n        this.format = `kmodel v${model.version}`;\n        this.modules = model.modules.map((module) => new kmodel.Graph(module));\n    }\n};\n\nkmodel.Graph = class {\n\n    constructor(module) {\n        this.name = module.name || '';\n        this.description = module.type || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const scopes = new Map();\n        let index = 0;\n        const values = new Map();\n        const value = (arg) => {\n            const name = arg.name;\n            const type = arg.shape ? new kmodel.TensorType(arg.datatype || '?', arg.shape) : null;\n            if (arg.data) {\n                const tensor = arg.data ? new kmodel.Tensor(type, arg.data) : null;\n                return new kmodel.Value(name, type || null, tensor);\n            }\n            if (!values.has(name)) {\n                values.set(name, new kmodel.Value(name, type || null, null));\n            } if ((type && !type.equals(values.get(name).type))) {\n                return new kmodel.Value(name, type);\n            }\n            return values.get(name);\n        };\n        for (const layer of module.layers) {\n            for (const input of layer.inputs || []) {\n                for (const arg of input.value) {\n                    arg.name = scopes.has(arg.name) ? scopes.get(arg.name) : arg.name;\n                }\n            }\n            for (const output of layer.outputs || []) {\n                for (const arg of output.value) {\n                    const name = scopes.has(arg.name) ? `${arg.name}#${index}` : arg.name;\n                    scopes.set(arg.name, name); // custom argument id\n                    arg.name = name;\n                    if (arg.name && arg.shape && !arg.data) {\n                        value(arg);\n                    }\n                }\n            }\n            index++;\n        }\n        for (const layer of module.layers) {\n            for (const output of layer.outputs || []) {\n                for (const arg of output.value) {\n                    if (arg.name && arg.shape && !arg.data) {\n                        value(arg);\n                    }\n                }\n            }\n        }\n        for (const layer of module.layers) {\n            for (const input of layer.inputs || []) {\n                for (const arg of input.value) {\n                    if (arg.name && arg.shape && !arg.data) {\n                        value(arg);\n                    }\n                }\n            }\n        }\n        for (const layer of module.layers) {\n            switch (layer.type.name) {\n                case 'INPUT':\n                case 'input': {\n                    for (const input of layer.outputs) {\n                        const values = input.value.map((arg) => value(arg));\n                        const argument = new kmodel.Argument('input', values);\n                        this.inputs.push(argument);\n                    }\n                    break;\n                }\n                case 'OUTPUT':\n                case 'output': {\n                    for (const output of layer.inputs) {\n                        const values = output.value.map((arg) => value(arg));\n                        const argument = new kmodel.Argument(output.name, values);\n                        this.outputs.push(argument);\n                    }\n                    break;\n                }\n                default: {\n                    const node = new kmodel.Node(layer, value);\n                    this.nodes.push(node);\n                    break;\n                }\n            }\n        }\n    }\n};\n\nkmodel.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\nkmodel.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new kmodel.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nkmodel.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = new kmodel.TensorShape(shape);\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nkmodel.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    equals(obj) {\n        if (obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions)) {\n            if (this.dimensions.length === obj.dimensions.length) {\n                return obj.dimensions.every((value, index) => this.dimensions[index] === value);\n            }\n            if (obj.dimensions.every((dim) => Number.isInteger(dim)) && this.dimensions.every((dim) => Number.isInteger(dim))) {\n                const a = obj.dimensions.reduce((a, b) => a * b, 1);\n                const b = this.dimensions.reduce((a, b) => a * b, 1);\n                return a === b;\n            }\n        }\n        return false;\n    }\n\n    toString() {\n        if (this.dimensions && Array.isArray(this.dimensions) && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dim) => dim ? dim.toString() : '?').join(',')}]`;\n        }\n        return '';\n    }\n};\n\nkmodel.Tensor = class {\n\n    constructor(type, data) {\n        this.type = type;\n        this.values = data;\n    }\n};\n\nkmodel.Node = class {\n\n    constructor(layer, value) {\n        this.identifier = layer.location === undefined ? layer.location : layer.location.toString();\n        this.name = '';\n        this.type = layer.type;\n        this.inputs = [];\n        this.outputs = [];\n        this.chain = [];\n        this.attributes = [];\n        this.chain = [];\n        for (const [name, value] of Object.entries(layer)) {\n            if (name === 'type' || name === 'location' || name === 'inputs' || name === 'outputs' || name === 'chain') {\n                continue;\n            }\n            const attribute = new kmodel.Argument(name, value);\n            this.attributes.push(attribute);\n        }\n        for (const input of layer.inputs || []) {\n            const values = input.value.map((arg) => value(arg));\n            const argument = new kmodel.Argument(input.name, values);\n            this.inputs.push(argument);\n        }\n        for (const output of layer.outputs || []) {\n            const values = output.value.map((arg) => value(arg));\n            const argument = new kmodel.Argument(output.name, values);\n            this.outputs.push(argument);\n        }\n        for (const chain of layer.chain || []) {\n            const node = new kmodel.Node(chain, value);\n            this.chain.push(node);\n        }\n    }\n};\n\nkmodel.Reader = class {\n\n    static open(stream) {\n        if (stream && stream.length >= 4) {\n            const length = Math.min(8, stream.length);\n            const buffer = stream.peek(length);\n            if ([0x03, 0x00, 0x00, 0x00].every((value, index) => value === buffer[index])) {\n                return new kmodel.Reader(stream, 3);\n            }\n            if ([0x4C, 0x44, 0x4D, 0x4B].every((value, index) => value === buffer[index]) && buffer.length >= 8) {\n                const reader = base.BinaryReader.open(buffer);\n                reader.skip(4);\n                const version = reader.uint32();\n                return new kmodel.Reader(stream, version);\n            }\n        }\n        return null;\n    }\n\n    constructor(stream, version) {\n        this.stream = stream;\n        this.version = version;\n        this.modules = [];\n    }\n\n    read() {\n        if (this.version < 3 || this.version > 7) {\n            throw new kmodel.Error(`Unsupported model version '${this.version}'.`);\n        }\n        const types = new Map();\n        const register = (type, name, category, callback) => {\n            types.set(type, { type: { name, category: category || '' }, callback });\n        };\n        switch (this.version) {\n            case 3: {\n                const reader = new kmodel.BinaryReader.v3(this.stream);\n                const model_header = reader.kpu_model_header_t();\n                const layers = new Array(model_header.layers_length);\n                const outputs = new Array(model_header.output_count);\n                for (let i = 0; i < model_header.output_count; i++) {\n                    outputs[i] = reader.kpu_model_output_t(`output${i > 0 ? i.toString() : ''}`);\n                }\n                for (let i = 0; i < layers.length; i++) {\n                    layers[i] = reader.kpu_model_layer_header_t();\n                    layers[i].location = i;\n                }\n                let offset = reader.position;\n                for (const layer of layers) {\n                    layer.offset = offset;\n                    offset += layer.body_size;\n                }\n                /* eslint-disable space-in-parens */\n                register(   -1, 'DUMMY');\n                register(    0, 'INVALID');\n                register(    1, 'ADD');\n                register(    2, 'QUANTIZED_ADD');\n                register(    3, 'GLOBAL_MAX_POOL2D', 'Pool');\n                register(    4, 'QUANTIZED_GLOBAL_MAX_POOL2D', 'Pool');\n                register(    5, 'GLOBAL_AVERAGE_POOL2D', 'Pool', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.kernel_size = reader.uint32();\n                    layer.channels = reader.uint32();\n                });\n                register(    6, 'QUANTIZED_GLOBAL_AVERAGE_POOL2D', 'Pool');\n                register(    7, 'MAX_POOL2D', 'Pool');\n                register(    8, 'QUANTIZED_MAX_POOL2D', 'Pool', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.outputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.kernel = [reader.uint32(), reader.uint32()];\n                    layer.stride = [reader.uint32(), reader.uint32()];\n                    layer.padding = [reader.uint32(), reader.uint32()];\n                });\n                register(    9, 'AVERAGE_POOL2D', 'Pool');\n                register(   10, 'QUANTIZED_AVERAGE_POOL2D', 'Pool');\n                register(   11, 'QUANTIZE', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.count = reader.uint32();\n                    layer.scale = reader.float32();\n                    layer.bias = reader.float32();\n                });\n                register(   12, 'DEQUANTIZE', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.count = reader.uint32();\n                    layer.scale = reader.float32();\n                    layer.bias = reader.float32();\n                });\n                register(   13, 'REQUANTIZE', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.count = reader.uint32();\n                    layer.table = reader.read(256);\n                });\n                register(   14, 'L2_NORMALIZATION', 'Normalization');\n                register(   15, 'SOFTMAX', 'Activation', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.channels = reader.uint32();\n                });\n                register(   16, 'CONCAT', 'Tensor', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs_mem = new Array(reader.uint32());\n                    for (let i = 0; i < layer.inputs_mem.length; i++) {\n                        layer.inputs_mem[i] = {\n                            start: reader.uint32(),\n                            end: reader.uint32()\n                        };\n                    }\n                });\n                register(   17, 'QUANTIZED_CONCAT', 'Tensor', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs_mem = new Array(reader.uint32());\n                    for (let i = 0; i < layer.inputs_mem.length; i++) {\n                        layer.inputs_mem[i] = {\n                            start: reader.uint32(),\n                            end: reader.uint32()\n                        };\n                    }\n                });\n                register(   18, 'FULLY_CONNECTED', 'Layer', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.in_channels = reader.uint32();\n                    layer.out_channels = reader.uint32();\n                    const act = reader.uint32();\n                    const activations = [\n                        { name: 'LINEAR', category: 'Activation' },\n                        { name: 'RELU', category: 'Activation' },\n                        { name: 'RELU6', category: 'Activation' },\n                    ];\n                    if (act !== 0) {\n                        if (act > activations.length) {\n                            throw new kmodel.Error(`Unsupported FULLY_CONNECTED activation '${act}'.`);\n                        }\n                        layer.chain = [{ type: activations[act] }];\n                    }\n                    layer.inputs.push({ name: 'weights', value: [{ name: '', datatype: 'float32', shape: [layer.in_channels, layer.out_channels], data: reader.read(4 * layer.in_channels * layer.out_channels) }] });\n                    layer.inputs.push({ name: 'bias', value: [{ name: '', datatype: 'float32', shape: [layer.out_channels], data: reader.read(4 * layer.out_channels) }] });\n                });\n                register(   19, 'QUANTIZED_FULLY_CONNECTED', 'Layer');\n                register(   20, 'TENSORFLOW_FLATTEN', 'Shape', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    const shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.inputs[0].value[0].shape = shape;\n                    layer.outputs[0].value[0].shape = shape;\n                });\n                register(   21, 'QUANTIZED_TENSORFLOW_FLATTEN', 'Shape', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    const shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.inputs[0].value[0].shape = shape;\n                    layer.outputs[0].value[0].shape = shape;\n                });\n                register(   22, 'RESIZE_NEAREST_NEIGHBOR', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.out_width = reader.uint32();\n                    layer.out_height = reader.uint32();\n                    layer.align_corners = reader.uint32();\n                });\n                register(   23, 'QUANTIZED_RESIZE_NEAREST_NEIGHBOR', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.out_width = reader.uint32();\n                    layer.out_height = reader.uint32();\n                    layer.align_corners = reader.uint32();\n                });\n                register( 1000, 'CONV', 'Layer');\n                register( 1001, 'DWCONV', 'Layer');\n                register( 1002, 'QUANTIZED_RESHAPE', 'Shape');\n                register( 1003, 'RESHAPE', 'Shape');\n                register(10240, 'K210_CONV', 'Layer', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.outputs = [reader.parameter('output')];\n                    const layer_offset = reader.uint32();\n                    const weights_offset = reader.uint32();\n                    const bn_offset = reader.uint32();\n                    const act_offset = reader.uint32();\n                    reader.seek(layer_offset);\n                    layer.interrupt_enabe = reader.uint64_bits({ int_en: 0, ram_flag: 1, full_add: 2, depth_wise_layer: 3 });\n                    layer.inputs = [reader.parameter('input', 'kpu')];\n                    const outputs = [reader.parameter('output', 'kpu')];\n                    layer.outputs[0].value.push(outputs[0].value[0]);\n                    // layer.outputs = layer.flags & 1 ? layer.outputs : outputs;\n                    layer.image_channel_num = reader.uint64_bits({ i_ch_num: 0, o_ch_num: 32, o_ch_num_coef: 48 });\n                    layer.image_size =  reader.uint64_bits({ i_row_wid: 0, i_col_high: 10, o_row_wid: 32, o_col_high : 42 });\n                    layer.kernel_pool_type_cfg = reader.uint64_bits({ kernel_type: 0, pad_type: 3, pool_type: 4, first_stride: 8, bypass_conv: 9, load_para: 10, dma_burst_size: 16, pad_value: 24, bwsx_base_addr: 32 });\n                    layer.kernel_load_cfg = reader.uint64_bits({ load_coor: 0, load_time: 1, para_size: 15, para_start_addr: 32 });\n                    layer.kernel_offset = reader.uint64_bits({ coef_column_offset: 0, coef_row_offset: 4 });\n                    layer.kernel_calc_type_cfg = reader.uint64_bits({ channel_switch_addr: 0, row_switch_addr: 16, coef_size: 20, coef_group: 28, load_act: 31, active_addr: 32 });\n                    layer.write_back_cfg = reader.uint64_bits({ wb_channel_switch_addr: 0, wb_row_switch_addr: 16, wb_group: 20 });\n                    layer.conv_value = reader.uint64_bits({ shr_w: 0, shr_x: 4, arg_w: 8, arg_x: 32 });\n                    layer.conv_value2 = reader.uint64_bits({ arg_add: 0 });\n                    layer.dma_parameter = reader.uint64_bits({ send_data_out: 0, channel_byte_num: 16, dma_total_byte: 32 });\n                    layer.chain = [];\n                    const ic = layer.image_channel_num.i_ch_num + 1;\n                    const oc = layer.image_channel_num.o_ch_num + 1;\n                    layer.outputs[0].value[0].shape = [layer.image_size.o_row_wid + 1, layer.image_size.o_col_high + 1, oc];\n                    const filter = [1, 3][layer.kernel_pool_type_cfg.kernel_type];\n                    const weights_shape = layer.interrupt_enabe.depth_wise_layer ? [oc, filter, filter] : [ic, oc, filter, filter];\n                    const weights_size = weights_shape.reduce((a, b) => a * b);\n                    reader.seek(bn_offset);\n                    const batch_norm = {\n                        type: { name: 'BATCH_NORM', category: 'Normalization' },\n                        weights: []\n                    };\n                    batch_norm.weights = new Array(oc);\n                    for (let i = 0; i < oc; i++) {\n                        batch_norm.weights[i] = reader.uint64_bits({ norm_mul: 0, norm_add: 24, norm_shift: 56, reserved: 60 });\n                        delete batch_norm.weights[i].reserved;\n                    }\n                    layer.chain.push(batch_norm);\n                    reader.seek(act_offset);\n                    const activation = {};\n                    activation.type = { name: 'ACTIVATION', category: 'Activation' };\n                    activation.activate_para = new Array(16);\n                    for (let i = 0; i < 16; i++) {\n                        activation.activate_para[i] = reader.uint64_bits({ shift_number: 0, y_mul: 8, x_start: 24, reserved: 60 });\n                        delete activation.activate_para[i].reserved;\n                    }\n                    for (let i = 0; i < 16; i++) {\n                        activation.activate_para[i].bias = reader.int8();\n                    }\n                    layer.chain.push(activation);\n                    reader.seek(weights_offset);\n                    layer.inputs.push({\n                        name: 'weights',\n                        value: [{\n                            name: '',\n                            datatype: 'uint8',\n                            shape: weights_shape,\n                            data: reader.read(weights_size)\n                        }]\n                    });\n                    delete layer.kernel_pool_type_cfg.bwsx_base_addr;\n                    delete layer.kernel_calc_type_cfg.active_addr;\n                    delete layer.kernel_load_cfg.para_start_addr;\n                });\n                register(10241, 'K210_ADD_PADDING', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output', 'kpu')];\n                    layer.channels = reader.uint32();\n                });\n                register(10242, 'K210_REMOVE_PADDING', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.channels = reader.uint32();\n                });\n                register(10243, 'K210_UPLOAD', '', (layer, reader) => {\n                    layer.flags = reader.uint32();\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output', 'kpu')];\n                    const shape = [reader.uint32(), reader.uint32(), reader.uint32()];\n                    layer.inputs[0].value[0].shape = shape;\n                    layer.outputs[0].value[0].shape = shape;\n                });\n                /* eslint-enable space-in-parens */\n                for (const layer of layers) {\n                    const type = types.get(layer.type);\n                    if (!type) {\n                        throw new kmodel.Error(`Unsupported version '${this.version}' layer type '${layer.type}'.`);\n                    }\n                    if (!type.callback) {\n                        throw new kmodel.Error(`Unsupported version '${this.version}' layer '${type.type.name}'.`);\n                    }\n                    layer.type = type.type;\n                    reader.seek(layer.offset);\n                    type.callback(layer, reader);\n                    delete layer.offset;\n                    delete layer.body_size;\n                }\n                if (layers.length > 0) {\n                    layers.unshift({\n                        type: { name: 'input' },\n                        outputs: [layers[0].inputs[0]]\n                    });\n                }\n                for (const output of outputs) {\n                    layers.push({\n                        type: { name: 'output' },\n                        inputs: output.address\n                    });\n                }\n                this.modules.push({\n                    name: '',\n                    layers\n                });\n                break;\n            }\n            case 4: {\n                const reader = new kmodel.BinaryReader.v4(this.stream);\n                const model_header = {\n                    flags: reader.uint32(),\n                    target: reader.uint32(), // 0=CPU, 1=K210\n                    constants: reader.uint32(),\n                    main_mem: reader.uint32(),\n                    nodes: reader.uint32(),\n                    inputs: reader.uint32(),\n                    outputs: reader.uint32(),\n                    reserved0: reader.uint32(),\n                };\n                const inputs = new Array(model_header.inputs);\n                for (let i = 0; i < inputs.length; i++) {\n                    inputs[i] = reader.parameter(`input${i === 0 ? '' : (i + 1)}`);\n                }\n                for (let i = 0; i < inputs.length; i++) {\n                    inputs[i].value[0].shape = reader.runtime_shape_t();\n                }\n                const outputs = new Array(model_header.outputs);\n                for (let i = 0; i < outputs.length; i++) {\n                    outputs[i] = reader.parameter(`output${i === 0 ? '' : (i + 1)}`);\n                }\n                reader.constants(model_header.constants);\n                const layers = new Array(model_header.nodes);\n                for (let i = 0; i < layers.length; i++) {\n                    layers[i] = {\n                        location: i,\n                        opcode: reader.uint32(),\n                        body_size: reader.uint32()\n                    };\n                }\n                let offset = reader.position;\n                for (const layer of layers) {\n                    layer.offset = offset;\n                    offset += layer.body_size;\n                }\n                /* eslint-disable space-in-parens */\n                register(  0x00, 'binary', '', (layer, reader) => {\n                    layer.inputs = [\n                        reader.parameter('a'),\n                        reader.parameter('b')\n                    ];\n                    layer.outputs = [reader.parameter('outputs')];\n                    layer.binary_op = reader.binary_op_t();\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.inputs[1].value[0].shape = reader.runtime_shape_t();\n                    layer.outputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                });\n                register(  0x01, 'concat', 'Tensor', (layer, reader) => {\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inner_size = reader.uint32();\n                    layer.outer_size = reader.uint32();\n                    const inputs_count = reader.uint32();\n                    layer.inputs = [{ name: 'inputs', value: [] }];\n                    for (let i = 0; i < inputs_count; i++) {\n                        layer.inputs[0].value[i] = reader.argument();\n                    }\n                    layer.dims = new Array(inputs_count);\n                    for (let i = 0; i < inputs_count; i++) {\n                        layer.dims[i] = reader.int32();\n                    }\n                });\n                register(  0x02, 'conv2d', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.groups = reader.int32();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                    const weights_shape = [layer.out_channels, layer.inputs[0].value[0].shape[1] / layer.groups, layer.filter_h, layer.filter_w];\n                    const weights_size = 4 * weights_shape.reduce((a, b) => a * b);\n                    layer.inputs.push({\n                        name: 'weights',\n                        value: [{\n                            name: '',\n                            datatype: 'float32',\n                            shape: weights_shape,\n                            data: reader.read(weights_size)\n                        }]\n                    });\n                    const bias_shape = [layer.out_channels];\n                    const bias_size = 4 * layer.out_channels;\n                    layer.inputs.push({\n                        name: 'bias',\n                        value: [{\n                            name: '',\n                            datatype: 'float32',\n                            shape: bias_shape,\n                            data: reader.read(bias_size)\n                        }]\n                    });\n                });\n                register(  0x03, 'dequantize', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.zero_point = reader.int32();\n                    layer.scale = reader.float32();\n                });\n                register(  0x04, 'matmul', '', (layer, reader) => {\n                    layer.inputs = [\n                        reader.parameter('a'),\n                        reader.parameter('b'),\n                    ];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.a_rows = reader.int32();\n                    layer.a_cols = reader.int32();\n                    layer.b_cols = reader.int32();\n                    layer.inputs[1].value[0].shape = [layer.a_cols, layer.b_cols];\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                    const bias = reader.read(4 * layer.b_cols);\n                    if (!bias.every((value) => value === 0)) {\n                        layer.inputs.push({\n                            name: 'bias',\n                            value: [{ name: '', datatype: 'float32', shape: [layer.b_cols], data: bias }]\n                        });\n                    }\n                });\n                register(  0x05, 'pad', 'Shape', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.paddings = reader.runtime_paddings_t();\n                    layer.pad_value = reader.scalar();\n                });\n                register(  0x06, 'quantize', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.zero_point = reader.int32();\n                    layer.scale = reader.float32();\n                });\n                register(  0x07, 'reduce', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.reduce_op = reader.reduce_op_t();\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.outputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.init_value = reader.float32();\n                });\n                register(  0x08, 'reduce_window2d', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.reduce_op = reader.reduce_op_t();\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.init_value = reader.float32();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                });\n                register(  0x09, 'memory_copy', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                });\n                register(  0x0A, 'resize_image', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.reduce_op = reader.reduce_op_t();\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.out_h = reader.int32();\n                    layer.out_w = reader.int32();\n                    layer.mode = reader.image_resize_mode_t();\n                    layer.align_corners = reader.boolean();\n                });\n                register(  0x0B, 'softmax', 'Activation');\n                register(  0x0C, 'transpose', 'Transform', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.perm = reader.runtime_shape_t();\n                });\n                register(  0x0D, 'strided_slice', 'Tensor', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.begin = reader.runtime_shape_t();\n                    layer.end = reader.runtime_shape_t();\n                    layer.strides = reader.runtime_shape_t();\n                });\n                register(  0x0E, 'unary', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.unary_op = reader.unary_op_t();\n                });\n                register(  0x0F, 'quantized_conv2d', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.groups = reader.int32();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.input_offset = reader.int32();\n                    layer.filter_offset = reader.int32();\n                    layer.output_mul = reader.int32();\n                    layer.output_shift = reader.int32();\n                    layer.output_offset = reader.int32();\n                    const bias = reader.span('int32', [layer.out_channels]);\n                    if (bias) {\n                        layer.inputs.push({ name: 'bias', value: [bias] });\n                    }\n                    const weights = reader.span('uint8', [layer.out_channels, layer.inputs[0].value[0].shape[1] / layer.groups, layer.filter_h, layer.filter_w]);\n                    if (weights) {\n                        layer.inputs.push({ name: 'weights', value: [weights] });\n                    }\n                });\n                register(  0x10, 'quantized_matmul', '', (layer, reader) => {\n                    layer.inputs = [\n                        reader.parameter('a'),\n                        reader.parameter('b'),\n                    ];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.a_rows = reader.int32();\n                    layer.a_cols = reader.int32();\n                    layer.b_cols = reader.int32();\n                    layer.inputs[1].value[0].shape = [layer.a_cols, layer.b_cols];\n                    layer.input_a_offset = reader.int32();\n                    layer.input_b_offset = reader.int32();\n                    layer.output_mul = reader.int32();\n                    layer.output_shift = reader.int32();\n                    layer.output_offset = reader.int32();\n                    const bias = reader.span('int32', [layer.b_cols]);\n                    if (bias) {\n                        layer.inputs.push({ name: 'bias', value: [bias] });\n                    }\n                });\n                register(  0x11, 'quantized_binary', '', (layer, reader) => {\n                    layer.inputs = [\n                        reader.parameter('a'),\n                        reader.parameter('b')\n                    ];\n                    layer.outputs = [reader.parameter('outputs')];\n                    layer.binary_op = reader.binary_op_t();\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.inputs[1].value[0].shape = reader.runtime_shape_t();\n                    layer.outputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.input_a_offset = reader.int32();\n                    layer.input_a_mul = reader.int32();\n                    layer.input_a_shift = reader.int32();\n                    layer.input_b_offset = reader.int32();\n                    layer.input_b_mul = reader.int32();\n                    layer.input_b_shift = reader.int32();\n                    layer.output_offset = reader.int32();\n                    layer.output_mul = reader.int32();\n                    layer.output_shift = reader.int32();\n                });\n                register(  0x12, 'table_lookup1d', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input'), reader.parameter('table')];\n                    layer.outputs = [reader.parameter('output')];\n                });\n                register(  0x13, 'conv2d_transpose', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.groups = reader.int32();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                    const weights_shape = [layer.out_channels, layer.inputs[0].value[0].shape[1] / layer.groups, layer.filter_h, layer.filter_w];\n                    const weights_size = 4 * weights_shape.reduce((a, b) => a * b);\n                    layer.inputs.push({\n                        name: 'weights',\n                        value: [{\n                            name: '',\n                            datatype: 'float32',\n                            shape: weights_shape,\n                            data: reader.read(weights_size)\n                        }]\n                    });\n                    const bias_shape = [layer.out_channels];\n                    const bias_size = 4 * layer.out_channels;\n                    layer.inputs.push({\n                        name: 'bias',\n                        value: [{\n                            name: '',\n                            datatype: 'float32',\n                            shape: bias_shape,\n                            data: reader.read(bias_size)\n                        }]\n                    });\n                });\n                register(  0x14, 'nnil_unary_method', '', (layer, reader, size) => {\n                    const position = reader.position;\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.body = reader.read(size - (reader.position - position));\n                });\n                register(0x1001, 'cpu_conv2d', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.groups = reader.int32();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                });\n                register(0x1002, 'cpu_depthwise_conv2d', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                });\n                register(0x1003, 'cpu_reduce_window2d', 'Pool', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.reduce_op = reader.reduce_op_t();\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.fused_activation = [reader.float32(), reader.float32()];\n                });\n                register(0x1004, 'cpu_quantized_conv2d', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.groups = reader.int32();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.input_offset = reader.int32();\n                    layer.filter_offset = reader.int32();\n                    layer.output_mul = reader.int32();\n                    layer.output_shift = reader.int32();\n                    layer.output_offset = reader.int32();\n                });\n                register(0x1005, 'cpu_quantized_depthwise_conv2d', 'Layer', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                    layer.out_channels = reader.int32();\n                    layer.padding_h = reader.padding();\n                    layer.padding_w = reader.padding();\n                    layer.filter_h = reader.int32();\n                    layer.filter_w = reader.int32();\n                    layer.stride_h = reader.int32();\n                    layer.stride_w = reader.int32();\n                    layer.dilation_h = reader.int32();\n                    layer.dilation_w = reader.int32();\n                    layer.input_offset = reader.int32();\n                    layer.filter_offset = reader.int32();\n                    layer.output_mul = reader.int32();\n                    layer.output_shift = reader.int32();\n                    layer.output_offset = reader.int32();\n                });\n                register(0x2001, 'kpu_upload', '', (layer, reader) => {\n                    layer.inputs = [reader.parameter('input')];\n                    layer.outputs = [reader.parameter('output')];\n                    layer.inputs[0].value[0].shape = reader.runtime_shape_t();\n                });\n                register(0x2002, 'kpu_conv2d', 'Layer', (layer, reader) => {\n                    layer.outputs = [reader.parameter('output')];\n                    layer.batches = reader.int32();\n                    layer.reserved0 = reader.int32();\n                    layer.interrupt_enabe = reader.uint64_bits({ int_en: 0, ram_flag: 1, full_add: 2, depth_wise_layer: 3 });\n                    const image_src_addr = reader.uint32();\n                    const image_dst_addr = reader.uint32();\n                    layer.inputs = [{ name: 'input', value: [{ name: `kpu:${image_src_addr}` }] }];\n                    const outputs = [{ name: 'output', value: [{ name: `kpu:${image_dst_addr}` }] }];\n                    layer.outputs[0].value.push(outputs[0].value[0]);\n                    // layer.outputs = layer.flags & 1 ? layer.outputs : outputs;\n                    layer.image_channel_num = reader.uint64_bits({ i_ch_num: 0, o_ch_num: 32, o_ch_num_coef: 48 });\n                    layer.image_size =  reader.uint64_bits({ i_row_wid: 0, i_col_high: 10, o_row_wid: 32, o_col_high : 42 });\n                    layer.kernel_pool_type_cfg = reader.uint64_bits({ kernel_type: 0, pad_type: 3, pool_type: 4, first_stride: 8, bypass_conv: 9, load_para: 10, dma_burst_size: 16, pad_value: 24, bwsx_base_addr: 32 });\n                    layer.kernel_load_cfg = reader.uint64_bits({ load_coor: 0, load_time: 1, para_size: 15, para_start_addr: 32 });\n                    layer.kernel_offset = reader.uint64_bits({ coef_column_offset: 0, coef_row_offset: 4 });\n                    layer.kernel_calc_type_cfg = reader.uint64_bits({ channel_switch_addr: 0, row_switch_addr: 16, coef_size: 20, coef_group: 28, load_act: 31, active_addr: 32 });\n                    layer.write_back_cfg = reader.uint64_bits({ wb_channel_switch_addr: 0, wb_row_switch_addr: 16, wb_group: 20 });\n                    layer.conv_value = reader.uint64_bits({ shr_w: 0, shr_x: 4, arg_w: 8, arg_x: 32 });\n                    layer.conv_value2 = reader.uint64_bits({ arg_add: 0 });\n                    layer.dma_parameter = reader.uint64_bits({ send_data_out: 0, reserved: 1, channel_byte_num: 16, dma_total_byte: 32 });\n                    layer.chain = [];\n                    const ic = layer.image_channel_num.i_ch_num + 1;\n                    const oc = layer.image_channel_num.o_ch_num + 1;\n                    layer.outputs[0].value[0].shape = [layer.image_size.o_row_wid + 1, layer.image_size.o_col_high + 1, oc];\n                    const filter = [1, 3][layer.kernel_pool_type_cfg.kernel_type];\n                    const weights_shape = layer.interrupt_enabe.depth_wise_layer ? [oc, filter, filter] : [ic, oc, filter, filter];\n                    reader.skip(layer.kernel_pool_type_cfg.bwsx_base_addr);\n                    delete layer.kernel_pool_type_cfg.bwsx_base_addr;\n                    const batch_norm = {\n                        type: { name: 'batch_norm', category: 'Normalization' },\n                        weights: []\n                    };\n                    batch_norm.weights = new Array(oc);\n                    for (let i = 0; i < oc; i++) {\n                        batch_norm.weights[i] = reader.uint64_bits({ norm_mul: 0, norm_add: 24, norm_shift: 56, reserved: 60 });\n                        delete batch_norm.weights[i].reserved;\n                    }\n                    layer.chain.push(batch_norm);\n                    reader.skip(layer.kernel_calc_type_cfg.active_addr);\n                    delete layer.kernel_calc_type_cfg.active_addr;\n                    const activation = reader.kpu_activate_table_t();\n                    activation.type = { name: 'activation', category: 'Activation' };\n                    layer.chain.push(activation);\n                    reader.skip(layer.kernel_load_cfg.para_start_addr);\n                    delete layer.kernel_load_cfg.para_start_addr;\n                    const weights = reader.span('uint8', weights_shape);\n                    if (weights) {\n                        layer.inputs.push({ name: 'weights', value: [weights] });\n                    }\n                });\n                /* eslint-enable space-in-parens */\n                for (const layer of layers) {\n                    const type = types.get(layer.opcode);\n                    if (!type) {\n                        throw new kmodel.Error(`Unsupported version '${this.version}' layer type '${layer.type}'.`);\n                    }\n                    if (!type.callback) {\n                        throw new kmodel.Error(`Unsupported version '${this.version}' layer '${type.type.name}'.`);\n                    }\n                    layer.type = type.type;\n                    reader.seek(layer.offset);\n                    if (type.callback) {\n                        type.callback(layer, reader, layer.body_size);\n                    }\n                    delete layer.offset;\n                    delete layer.body_size;\n                    delete layer.opcode;\n                }\n                for (const input of inputs) {\n                    layers.unshift({\n                        type: { name: 'INPUT' },\n                        outputs: [input]\n                    });\n                }\n                for (const output of outputs) {\n                    layers.push({\n                        type: { name: 'OUTPUT' },\n                        inputs: [output]\n                    });\n                }\n                this.modules.push({\n                    name: '',\n                    layers\n                });\n                break;\n            }\n            case 5:\n            case 6:\n            case 7: {\n                let reader = null;\n                switch (this.version) {\n                    case 5: reader = new kmodel.BinaryReader.v5(this.stream); break;\n                    case 6: reader = new kmodel.BinaryReader.v6(this.stream); break;\n                    case 7: reader = new kmodel.BinaryReader.v7(this.stream); break;\n                    default: throw new kmodel.Error(`Unsupported model version '${this.version}'.`);\n                }\n                const model_header = reader.model_header();\n                this.modules = new Array(model_header.modules);\n                for (let i = 0; i < this.modules.length; i++) {\n                    const module_header = reader.module_header();\n                    const mempools = new Array(module_header.mempools || 0);\n                    for (let j = 0; j < mempools.length; j++) {\n                        mempools[j] = reader.mempool_desc();\n                    }\n                    const shared_mempools = new Array(module_header.shared_mempools || 0);\n                    for (let j = 0; j < shared_mempools.length; j++) {\n                        shared_mempools[i] = reader.mempool_desc();\n                    }\n                    const function_headers = new Array(module_header.functions);\n                    const functions = new Array(module_header.functions);\n                    for (let j = 0; j < functions.length; j++) {\n                        const position = reader.position;\n                        let inputs = [];\n                        let outputs = [];\n                        if (this.version === 5) {\n                            const function_header = reader.function_header();\n                            inputs = new Array(function_header.inputs || 0);\n                            for (let k = 0; k < inputs.length; k++) {\n                                inputs[k] = reader.parameter(`input${k === 0 ? '' : (k + 1)}`);\n                            }\n                            for (let k = 0; k < inputs.length; k++ || 0) {\n                                inputs[k].value[0].shape = reader.shape();\n                            }\n                            outputs = new Array(function_header.outputs || 0);\n                            for (let k = 0; k < outputs.length; k++) {\n                                outputs[k] = reader.parameter(`output${k === 0 ? '' : (k + 1)}`);\n                            }\n                            for (let k = 0; k < outputs.length; k++) {\n                                outputs[k].value[0].shape = reader.shape();\n                            }\n                            reader.align(8);\n                            const size = reader.position - position;\n                            if (function_header.size > size) {\n                                reader.skip(function_header.size - size);\n                            }\n                            function_headers[j] = function_header;\n                        } else {\n                            const func_start = reader.position;\n                            const function_header = reader.function_header();\n                            const header_size = reader.position - func_start;\n                            const remaining_size = function_header.size - header_size;\n                            if (remaining_size > 0) {\n                                reader.skip(remaining_size);\n                            }\n                            function_headers[j] = function_header;\n                        }\n                        functions[j] = {\n                            type: { name: 'Unknown' },\n                            inputs,\n                            outputs\n                        };\n                    }\n                    const sections = new Map();\n                    for (let j = 0; j < module_header.sections; j++) {\n                        const section_header = reader.section_header();\n                        reader.skip(section_header.body_start);\n                        const body = reader.read(section_header.body_size);\n                        const section = {\n                            reader: base.BinaryReader.open(body),\n                            flags: section_header.flags\n                        };\n                        reader.align(8);\n                        sections.set(section_header.name, section);\n                    }\n                    for (let j = 0; j < function_headers.length; j++) {\n                        const function_header = function_headers[j];\n                        const reader = sections.get('.text').reader;\n                        reader.seek(function_header.entrypoint);\n                        const size = function_header.text_size;\n                        function_header.text = reader.read(size);\n                        const layer = functions[i];\n                        switch (module_header.type) {\n                            case 'stackvm': {\n                                layer.type = { name: 'stackvm' };\n                                let reader = null;\n                                const buffer = function_header.text;\n                                switch (this.version) {\n                                    case 5: reader = new kmodel.BytecodeReader.v5(buffer); break;\n                                    case 6: reader = new kmodel.BytecodeReader.v6(buffer); break;\n                                    case 7: reader = new kmodel.BytecodeReader.v6(buffer); break;\n                                    default: throw new kmodel.Error(`Unsupported model version '${this.version}'.`);\n                                }\n                                reader = null;\n                                if (reader) {\n                                    layer.operations = reader.read();\n                                    layer.tensor_operations = layer.operations.filter((op) => op.name === 'tensor');\n                                }\n                                break;\n                            }\n                            case 'k210':\n                            case 'k230':\n                            case 'k510':\n                                break;\n                            default:\n                                throw new kmodel.Error(`Unsupported module type '${module_header.type}'.`);\n                        }\n                    }\n                    this.modules[i] = {\n                        type: module_header.type,\n                        name: this.modules.length > 1 ? i.toString() : '',\n                        layers: functions\n                    };\n                }\n                break;\n            }\n            default: {\n                throw new kmodel.Error(`Unsupported model version '${this.version}'.`);\n            }\n        }\n        delete this.stream;\n    }\n};\n\nkmodel.BinaryReader = class {\n\n    constructor(data) {\n        this._reader = base.BinaryReader.open(data);\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    seek(position) {\n        this._reader.seek(position);\n    }\n\n    skip(offset) {\n        this._reader.skip(offset);\n    }\n\n    align(size) {\n        this._reader.align(size);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    boolean() {\n        return this._reader.boolean();\n    }\n\n    byte() {\n        return this._reader.byte();\n    }\n\n    int8() {\n        return this._reader.int8();\n    }\n\n    int16() {\n        return this._reader.int16();\n    }\n\n    int32() {\n        return this._reader.int32();\n    }\n\n    uint16() {\n        return this._reader.uint16();\n    }\n\n    uint32() {\n        return this._reader.uint32();\n    }\n\n    uint64() {\n        return this._reader.uint64().toNumber();\n    }\n\n    float32() {\n        return this._reader.float32();\n    }\n\n    uint64_bits(fields) {\n        const buffer = this.read(8);\n        fields = Object.entries(fields);\n        fields.push([null, Math.min(64, fields[fields.length - 1][1] + 56)]);\n        const obj = {};\n        for (let i = 0; i < fields.length - 1; i++) {\n            const current = fields[i];\n            const next = fields[i + 1];\n            const [key, start] = current;\n            const [, end] = next;\n            let value = 0;\n            let position = start;\n            while (position < end) {\n                const offset = (position / 8) >> 0;\n                const start = (position & 7);\n                const count = Math.min((offset + 1) * 8, end) - position;\n                value |= ((buffer[offset] >>> start) & ((1 << count) - 1)) << (position - fields[i][1]);\n                position += count;\n            }\n            obj[key] = value;\n        }\n        return obj;\n    }\n};\n\nkmodel.BinaryReader.v3 = class extends kmodel.BinaryReader {\n\n    constructor(buffer) {\n        super(buffer);\n        this.skip(4);\n    }\n\n    kpu_model_header_t() {\n        return {\n            flags: this.uint32(),\n            arch: this.uint32(),\n            layers_length: this.uint32(),\n            max_start_address: this.uint32(),\n            main_mem_usage: this.uint32(),\n            output_count: this.uint32()\n        };\n    }\n\n    kpu_model_output_t(name) {\n        return {\n            address: [this.parameter(name)],\n            size: this.uint32()\n        };\n    }\n\n    kpu_model_layer_header_t() {\n        return {\n            type: this.uint32(),\n            body_size: this.uint32()\n        };\n    }\n\n    argument(memory_type) {\n        memory_type = memory_type || 'main';\n        const address = this.uint32();\n        return { name: `${memory_type}:${address}` };\n    }\n\n    parameter(name, memory_type) {\n        return { name, value: [this.argument(memory_type)] };\n    }\n};\n\nkmodel.BinaryReader.v4 = class extends kmodel.BinaryReader {\n\n    constructor(buffer) {\n        super(buffer);\n        this.skip(8);\n        this._memory_types = ['const', 'main', 'kpu'];\n        this._datatypes = ['float32', 'uint8'];\n    }\n\n    memory_type_t() {\n        const value = this.uint32();\n        return this._memory_types[value];\n    }\n\n    datatype_t() {\n        const value = this.uint32();\n        return this._datatypes[value];\n    }\n\n    memory_range() {\n        return {\n            memory_type: this.memory_type_t(),\n            datatype: this.datatype_t(),\n            start: this.uint32(),\n            size: this.uint32()\n        };\n    }\n\n    argument() {\n        const memory = this.memory_range();\n        const value = {\n            name: `${memory.memory_type}:${memory.start}`,\n            datatype: memory.datatype\n        };\n        if (memory.memory_type === 'const') {\n            value.data = this._constants.slice(memory.start, memory.start + memory.size);\n            switch (value.datatype) {\n                case 'uint8': value.shape = [value.data.length]; break;\n                case 'float32': value.shape = [value.data.length >> 2]; break;\n                default: break;\n            }\n        }\n        return value;\n    }\n\n    parameter(name) {\n        return { name, value: [this.argument()] };\n    }\n\n    runtime_shape_t() {\n        return [this.uint32(), this.uint32(), this.uint32(), this.uint32()];\n    }\n\n    padding() {\n        return { before: this.int32(), after: this.int32() };\n    }\n\n    runtime_paddings_t() {\n        return [this.padding(), this.padding(), this.padding(), this.padding()];\n    }\n\n    scalar() {\n        return {\n            datatype_t: this.uint32(),\n            storage: this.read(4)\n        };\n    }\n\n    kpu_activate_table_t() {\n        const value = {};\n        value.activate_para = new Array(16);\n        for (let i = 0; i < 16; i++) {\n            value.activate_para[i] = this.uint64_bits({ shift_number: 0, y_mul: 8, x_start: 24, reserved: 60 });\n            delete value.activate_para[i].reserved;\n        }\n        for (let i = 0; i < 16; i++) {\n            value.activate_para[i].bias = this.int8();\n        }\n        return value;\n    }\n\n    unary_op_t() {\n        const value = this.uint32();\n        return ['abs', 'ceil', 'cos', 'exp', 'floor', 'log', 'neg', 'rsqrt', 'sin', 'square'][value];\n    }\n\n    binary_op_t() {\n        const value = this.uint32();\n        return ['add', 'sub', 'mul', 'div', 'min', 'max'][value];\n    }\n\n    reduce_op_t() {\n        const value = this.uint32();\n        return ['mean', 'min', 'max', 'sum'][value];\n    }\n\n    image_resize_mode_t() {\n        const value = this.uint32();\n        return ['bilinear', 'nearest_neighbor'][value];\n    }\n\n    constants(size) {\n        this._constants = this.read(size);\n    }\n\n    span(datatype, shape) {\n        const size = shape.reduce((a, b) => a * b, 1);\n        const itemsize = { 'int32': 4, 'uint8': 1 };\n        const buffer = this.read(itemsize[datatype] * size);\n        if (!buffer.every((value) => value === 0)) {\n            const array = {};\n            array.name = '';\n            array.datatype = datatype;\n            array.shape = shape;\n            array.data = buffer;\n            return array;\n        }\n        return null;\n    }\n};\n\nkmodel.BinaryReader.v5 = class extends kmodel.BinaryReader {\n\n    constructor(buffer) {\n        super(buffer);\n        this.skip(8);\n        this._datatypes = ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float16', 'float32', 'float64', 'bfloat16'];\n        this._memory_locations = new Map([[0, 'input'], [1, 'output'], [2, 'rdata'], [3, 'data'], [4, 'shared_data'], [64, 'kpu']]);\n    }\n\n    model_header() {\n        const model_header = {\n            header_size: this.uint32(),\n            flags: this.uint32(),\n            alignment: this.uint32(),\n            modules: this.uint32(),\n            entry_module: this.uint32(),\n            entry_function: this.uint32()\n        };\n        if (model_header.header_size < 32) {\n            throw new kmodel.Error(`Invalid header size '${model_header.header_size}'.`);\n        }\n        if (model_header.header_size > this.position) {\n            this.skip(model_header.header_size - this.position);\n        }\n        delete model_header.header_size;\n        return model_header;\n    }\n\n    module_type_t() {\n        const buffer = this.read(16);\n        const decoder = new TextDecoder('ascii');\n        const text = decoder.decode(buffer);\n        return text.replace(/\\0.*$/, '');\n    }\n\n    module_header() {\n        const start = this.position;\n        const module_header = {\n            type: this.module_type_t(),\n            version: this.uint32(),\n            header_size: this.uint32(),\n            size: this.uint32(),\n            mempools: this.uint32(),\n            shared_mempools: this.uint32(),\n            sections: this.uint32(),\n            functions: this.uint32(),\n            reserved0: this.uint32()\n        };\n        if (module_header.header_size > (this.position - start)) {\n            this.skip(module_header.header_size - (this.position - start));\n        }\n        return module_header;\n    }\n\n    mempool_desc() {\n        return {\n            location: this.byte(),\n            reserved0: this.read(3),\n            size: this.uint32()\n        };\n    }\n\n    section_header() {\n        const buffer = this.read(16);\n        const decoder = new TextDecoder('ascii');\n        const name = decoder.decode(buffer);\n        return {\n            name: name.replace(/\\0.*$/, ''),\n            flags: this.uint32(),\n            body_start: this.uint32(),\n            body_size: this.uint32(),\n            reserved0: this.uint32()\n        };\n    }\n\n    function_header() {\n        const position = this.position;\n        const function_header = {\n            header_size: this.uint32(),\n            size: this.uint32(),\n            input_pool_size: this.uint32(),\n            output_pool_size: this.uint32(),\n            inputs: this.uint32(),\n            outputs: this.uint32(),\n            entrypoint: this.uint32(),\n            text_size: this.uint32()\n        };\n        const header_size = this.position - position;\n        if (function_header.header_size > header_size) {\n            this.skip(function_header.header_size - header_size);\n        }\n        return function_header;\n    }\n\n    memory_location_t() {\n        const value = this.byte();\n        if (!this._memory_locations.has(value)) {\n            throw new kmodel.Error(`Unsupported memory location '${value}'.`);\n        }\n        return this._memory_locations.get(value);\n    }\n\n    datatype_t() {\n        const value = this.byte();\n        return this._datatypes[value];\n    }\n\n    memory_range() {\n        return {\n            memory_location: this.memory_location_t(),\n            datatype: this.datatype_t(),\n            shared_module: this.uint16(),\n            start: this.uint32(),\n            size: this.uint32()\n        };\n    }\n\n    argument() {\n        const memory = this.memory_range();\n        const value = {\n            name: `${memory.memory_location}:${memory.start}`,\n            datatype: memory.datatype\n        };\n        /*\n        if (memory.memory_type === 'const') {\n            value.data = constants.slice(memory.start, memory.start + memory.size);\n            switch (value.datatype) {\n                case 'uint8': value.shape = [ value.data.length ]; break;\n                case 'float32': value.shape = [ value.data.length >> 2 ]; break;\n                default: break;\n            }\n        }\n        */\n        return value;\n    }\n\n    parameter(name) {\n        return { name, value: [this.argument()] };\n    }\n\n    shape() {\n        const array = new Array(this.uint32());\n        for (let i = 0; i < array.length; i++) {\n            array[i] = this.uint32();\n        }\n        return array;\n    }\n};\n\nkmodel.BinaryReader.v6 = class extends kmodel.BinaryReader.v5 {\n\n    model_header() {\n        return {\n            flags: this.uint32(),\n            alignment: this.uint32(),\n            modules: this.uint32(),\n            entry_module: this.uint32(),\n            entry_function: this.uint32(),\n            reserved0: this.uint32()\n        };\n    }\n\n    module_header() {\n        return {\n            type: this.module_type_t(),\n            version: this.uint32(),\n            size: this.uint32(),\n            sections: this.uint32(),\n            functions: this.uint32()\n        };\n    }\n\n    function_header() {\n        return {\n            parameters: this.uint32(),\n            entrypoint: this.uint32(),\n            text_size: this.uint32(),\n            size: this.uint32(),\n            sections: this.uint32(),\n            reserved0: this.uint32(),\n        };\n    }\n\n    section_header() {\n        const buffer = this.read(16);\n        const decoder = new TextDecoder('ascii');\n        const name = decoder.decode(buffer);\n        return {\n            name: name.replace(/\\0.*$/, ''),\n            size: this.uint32(),\n            flags: this.uint32(),\n            body_start: this.uint32(),\n            body_size: this.uint32(),\n            memory_size: this.uint32(),\n            reserved0: this.uint32()\n        };\n    }\n\n    deserialize_datatype() {\n        const typecode = this.byte();\n        if (typecode === 100) { // dt_pointer\n            const elem_type = this.deserialize_datatype();\n            return { type: 'pointer', elem_type };\n        } else if (typecode === 101) { // dt_valuetype\n            const uuid = this.read(16);\n            const size_bytes = this.uint32();\n            return { type: 'valuetype', uuid, size_bytes };\n        } else if (typecode >= 0 && typecode <= 12) {\n            const types = ['bool', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float16', 'float32', 'float64', 'bfloat16'];\n            return { type: 'prim', name: types[typecode] || `unknown_${typecode}` };\n        }\n        throw new kmodel.Error(`Unknown datatype typecode: ${typecode}`);\n    }\n\n    deserialize_type() {\n        const token = this.byte();\n        switch (token) {\n            case 0: // type_sig_invalid\n                return { type: 'invalid' };\n            case 1: // type_sig_any\n                return { type: 'any' };\n            case 2: { // type_sig_tensor\n                const elem_type = this.deserialize_datatype();\n                const is_scalar = this.byte() === 0;\n                const shape = [];\n                if (!is_scalar) {\n                    let dim_token = 0;\n                    while ((dim_token = this.byte()) !== 255) { // type_sig_end\n                        if (dim_token === 1) { // dim_fixed\n                            shape.push(this.uint32());\n                        } else if (dim_token === 2) { // dim_unknown\n                            shape.push(-1);\n                        } else {\n                            throw new kmodel.Error(`Invalid dim token: ${dim_token}`);\n                        }\n                    }\n                }\n                return { type: 'tensor', elem_type, shape, is_scalar };\n            }\n            case 3: { // type_sig_tuple\n                const fields = [];\n                while (this.peek() !== 255) { // type_sig_end\n                    fields.push(this.deserialize_type());\n                }\n                this.skip(1); // skip end token\n                return { type: 'tuple', fields };\n            }\n            case 4: // type_sig_callable\n                throw new kmodel.Error('Callable types not supported');\n            default:\n                throw new kmodel.Error(`Unknown type signature token: ${token}`);\n        }\n    }\n\n    peek() {\n        const value = this.byte();\n        this.seek(this.position - 1);\n        return value;\n    }\n};\n\nkmodel.BinaryReader.v7 = class extends kmodel.BinaryReader.v6 {\n\n    module_header() {\n        return {\n            type: this.module_type_t(),\n            version: this.uint32(),\n            sections: this.uint32(),\n            functions: this.uint32(),\n            reserved0: this.uint32(),\n            size: this.uint64(),\n        };\n    }\n\n    function_header() {\n        return {\n            parameters: this.uint32(),\n            sections: this.uint32(),\n            entrypoint: this.uint64(),\n            text_size: this.uint64(),\n            size: this.uint64(),\n        };\n    }\n\n    section_header() {\n        const buffer = this.read(16);\n        const decoder = new TextDecoder('ascii');\n        const name = decoder.decode(buffer);\n        return {\n            name: name.replace(/\\0.*$/, ''),\n            flags: this.uint32(),\n            reserved0: this.uint32(),\n            size: this.uint64(),\n            body_start: this.uint64(),\n            body_size: this.uint64(),\n            memory_size: this.uint64(),\n        };\n    }\n};\n\nkmodel.BytecodeReader = class {\n\n    constructor(buffer) {\n        this._reader = base.BinaryReader.open(buffer);\n    }\n\n    read() {\n        const operations = [];\n        while (this._reader.position < this._reader.length) {\n            const position = this._reader.position;\n            const opcode = this._reader.byte();\n            if (!this._opcodes.has(opcode)) {\n                throw new kmodel.Error(`Unknown opcode '${opcode}'.`);\n            }\n            const name = this._opcodes.get(opcode);\n            const operation = { name, position };\n            this.operation(operation);\n            // console.log(JSON.stringify(operation));\n            operations.push(operation);\n            if (name === 'ret') {\n                break;\n            }\n        }\n        return operations;\n    }\n\n    strings() {\n        // Read strings until we encounter a null byte as the first character\n        const array = [];\n        while (this._reader.position < this._reader.length) {\n            // Peek at next byte\n            const byte = this._reader.byte();\n            if (byte === 0) {\n                break; // End of array\n            }\n            // Put the byte back by moving position back\n            this._reader.seek(this._reader.position - 1);\n            array.push(this.string());\n        }\n        return array;\n    }\n};\n\nkmodel.BytecodeReader.v5 = class extends kmodel.BytecodeReader {\n\n    constructor(buffer) {\n        super(buffer);\n        this._opcodes = new Map([\n            [0, 'nop'], [1, 'ldnull'], [2, 'ldc_i4'], [3, 'ldc_i4_0'], [4, 'ldc_i4_1'],\n            [5, 'ldc_r4'], [6, 'ldind_i1'], [7, 'ldind_i2'], [8, 'ldind_i4'], [9, 'ldind_i'],\n            [10, 'ldind_u1'], [11, 'ldind_u2'], [12, 'ldind_u4'], [13, 'ldind_u'],\n            [14, 'ldind_br2'], [15, 'ldind_r4'], [16, 'stind_i1'], [17, 'stind_i2'],\n            [18, 'stind_i4'], [19, 'stind_i'], [20, 'stind_br2'], [21, 'stind_r4'],\n            [22, 'lea_gp'], [23, 'lea_buffer'], [24, 'ldelem_i1'], [25, 'ldelem_i2'],\n            [26, 'ldelem_i4'], [27, 'ldelem_i'], [28, 'ldelem_u1'], [29, 'ldelem_u2'],\n            [30, 'ldelem_u4'], [0x1F, 'ldelem_u'], [0x20, 'ldelem_br2'], [33, 'ldelem_r4'],\n            [34, 'stelem_i1'], [35, 'stelem_i2'], [36, 'stelem_i4'], [37, 'stelem_i'],\n            [38, 'stelem_br2'], [39, 'stelem_r4'], [40, 'ldarg'], [41, 'ldarg_0'],\n            [42, 'ldarg_1'], [43, 'ldarg_2'], [44, 'ldarg_3'], [45, 'ldarg_4'],\n            [46, 'ldarg_5'], [47, 'dup'], [48, 'pop'], [0x31, 'stshape'], [50, 'stpaddings'],\n            [51, 'neg'], [52, 'add'], [53, 'sub'], [54, 'mul'], [55, 'div'], [56, 'div_u'],\n            [57, 'rem'], [58, 'rem_u'], [59, 'and'], [60, 'or'], [61, 'xor'], [62, 'not'],\n            [63, 'shl'], [64, 'shr'], [65, 'shr_u'], [66, 'clt'], [67, 'clt_u'],\n            [68, 'cle'], [69, 'cle_u'], [70, 'ceq'], [71, 'cge'], [72, 'cge_u'],\n            [73, 'cgt'], [74, 'cgt_u'], [75, 'cne'], [76, 'conv_i1'], [77, 'conv_i2'],\n            [78, 'conv_i4'], [79, 'conv_i'], [80, 'conv_u1'], [81, 'conv_u2'],\n            [82, 'conv_u4'], [83, 'conv_u'], [84, 'conv_br2'], [85, 'conv_r4'],\n            [86, 'br'], [87, 'br_true'], [88, 'br_false'], [89, 'ret'], [90, 'call'],\n            [91, 'ecall'], [0x5C, 'throw'], [0x5D, 'break'], [0x5E, 'tensor']\n        ]);\n        this._tensorFunctions = new Map([\n            [0x0000, { name: 'batch_to_space', category: 'Transform' }],\n            [0x0001, { name: 'binary', category: '' }],\n            [0x0002, { name: 'broadcast', category: '' }],\n            [0x0003, { name: 'call', category: '' }],\n            [0x0004, { name: 'clamp', category: 'Activation' }],\n            [0x0005, { name: 'conv2d', category: 'Layer' }],\n            [0x0006, { name: 'conv2d_transpose', category: 'Layer' }],\n            [0x0007, { name: 'convert', category: '' }],\n            [0x0008, { name: 'copy', category: '' }],\n            [0x0009, { name: 'cumsum', category: '' }],\n            [0x000A, { name: 'dequantize', category: 'Quantization' }],\n            [0x000B, { name: 'equal', category: '' }],\n            [0x000C, { name: 'gather', category: 'Transform' }],\n            [0x000D, { name: 'gather_nd', category: 'Transform' }],\n            [0x000E, { name: 'hardmax', category: 'Activation' }],\n            [0x000F, { name: 'logistic', category: 'Activation' }],\n            [0x0010, { name: 'lut1d', category: '' }],\n            [0x0011, { name: 'matmul', category: 'Layer' }],\n            [0x0012, { name: 'onehot', category: '' }],\n            [0x0013, { name: 'pad', category: '' }],\n            [0x0014, { name: 'quantize', category: 'Quantization' }],\n            [0x0015, { name: 'random_normal', category: '' }],\n            [0x0016, { name: 'random_uniform', category: '' }],\n            [0x0017, { name: 'reduce', category: 'Reduce' }],\n            [0x0018, { name: 'reduce_arg', category: 'Reduce' }],\n            [0x0019, { name: 'reduce_prod', category: 'Reduce' }],\n            [0x001A, { name: 'reduce_window2d', category: 'Pool' }],\n            [0x001B, { name: 'resize_image', category: 'Transform' }],\n            [0x001C, { name: 'roi_align', category: '' }],\n            [0x001D, { name: 'sigmoid', category: 'Activation' }],\n            [0x001E, { name: 'slice', category: 'Tensor' }],\n            [0x001F, { name: 'softmax', category: 'Activation' }],\n            [0x0020, { name: 'space_to_batch', category: 'Transform' }],\n            [0x0021, { name: 'take', category: '' }],\n            [0x0022, { name: 'ternary', category: '' }],\n            [0x0023, { name: 'topk', category: '' }],\n            [0x0024, { name: 'transpose', category: 'Transform' }],\n            [0x0025, { name: 'trilu', category: '' }],\n            [0x0026, { name: 'unary', category: '' }]\n        ]);\n    }\n\n    operation(operation) {\n        switch (operation.name) {\n            case 'ldc_i4':\n                operation.value = this._reader.int32();\n                break;\n            case 'ldc_r4':\n                operation.imm = this._reader.float32();\n                break;\n            case 'lea_gp':\n                operation.gpid = this._reader.byte();\n                operation.offset = this._reader.int32();\n                break;\n            case 'lea_buffer':\n                operation.location = this._reader.byte();\n                operation.subres_id = this._reader.byte();\n                operation.offset = this._reader.int32();\n                break;\n            case 'ldarg':\n                operation.index = this._reader.uint32();\n                break;\n            case 'stpaddings':\n                operation.rpaddings = this._reader.byte();\n                operation.rank = this._reader.byte();\n                break;\n            case 'stshape':\n                operation.rshape = this._reader.byte();\n                operation.rank = this._reader.byte();\n                break;\n            case 'br':\n            case 'br_true':\n            case 'br_false':\n                operation.target = this._reader.int32();\n                break;\n            case 'call':\n                operation.args = this._reader.byte();\n                operation.target = this._reader.int32();\n                break;\n            case 'ecall':\n                operation.args = this._reader.byte();\n                break;\n            case 'extcall':\n                operation.args = this._reader.uint16();\n                operation.is_prim_func = this._reader.byte() !== 0;\n                break;\n            case 'cuscall':\n                operation.registered_name = this.string();\n                operation.fields_size = this._reader.uint32();\n                this._reader.skip(operation.fields_size);\n                operation.args = this._reader.uint16();\n                break;\n            case 'tensor': {\n                operation.tensor_function = this._reader.uint16();\n                const func = this._tensorFunctions.get(operation.tensor_function);\n                if (func) {\n                    operation.tensor_name = func.name;\n                    operation.tensor_category = func.category;\n                }\n                this.tensor(operation);\n                break;\n            }\n            default:\n                break;\n        }\n    }\n\n    string() {\n        // Read null-terminated string\n        const bytes = [];\n        let byte = this._reader.byte();\n        while (byte !== 0) {\n            bytes.push(byte);\n            byte = this._reader.byte();\n        }\n        return new TextDecoder('utf-8').decode(new Uint8Array(bytes));\n    }\n\n    tensor(operation) {\n        switch (operation.tensor_name) {\n            case 'binary':\n                operation.datatype = this._reader.byte();\n                operation.rshape_src1 = this._reader.byte();\n                operation.rstride_src1 = this._reader.byte();\n                operation.rshape_src2 = this._reader.byte();\n                operation.rstride_src2 = this._reader.byte();\n                operation.rstride_dest = this._reader.byte();\n                operation.binary_op = this._reader.byte();\n                operation.fused_clamp_low = this._reader.float32();\n                operation.fused_clamp_high = this._reader.float32();\n                break;\n            case 'bitcast':\n                operation.type = this._reader.byte();\n                operation.new_type = this._reader.byte();\n                break;\n            case 'call':\n                operation.function_id = this._reader.uint32();\n                operation.module_id = this._reader.uint16();\n                operation.num_src = this._reader.byte();\n                operation.num_dst = this._reader.byte();\n                break;\n            case 'cast':\n                operation.new_type = this._reader.byte();\n                operation.cast_mode = this._reader.uint32();\n                break;\n            case 'compare':\n                operation.compare_op = this._reader.byte();\n                break;\n            case 'concat':\n                operation.axis = this._reader.int32();\n                break;\n            case 'cumsum':\n                operation.datatype = this._reader.byte();\n                operation.rshape_src = this._reader.byte();\n                operation.axis = this._reader.int32();\n                operation.exclusive = this._reader.byte() !== 0;\n                operation.reverse = this._reader.byte() !== 0;\n                break;\n            case 'condition':\n                operation.can_fold_const_call = this._reader.byte() !== 0;\n                break;\n            case 'conv2d':\n                operation.datatype = this._reader.byte();\n                operation.rshape_src = this._reader.byte();\n                operation.rstride_src = this._reader.byte();\n                operation.rshape_kernel = this._reader.byte();\n                operation.rstride_kernel = this._reader.byte();\n                operation.rstride_bias = this._reader.byte();\n                operation.rstride_dest = this._reader.byte();\n                operation.groups = this._reader.uint16();\n                operation.stride_h = this._reader.uint16();\n                operation.stride_w = this._reader.uint16();\n                operation.dilation_h = this._reader.uint16();\n                operation.dilation_w = this._reader.uint16();\n                operation.fused_clamp_low = this._reader.float32();\n                operation.fused_clamp_high = this._reader.float32();\n                break;\n            case 'conv2d_transpose':\n                operation.pad_mode = this._reader.byte();\n                break;\n            case 'dequantize':\n                operation.target_type = this._reader.byte();\n                break;\n            case 'fake_dequantize':\n                operation.target_type = this._reader.byte();\n                break;\n            case 'fake_quantize':\n                operation.target_type = this._reader.byte();\n                break;\n            case 'gather':\n                operation.axis = this._reader.int32();\n                break;\n            case 'layer_norm':\n                operation.axis = this._reader.int32();\n                operation.epsilon = this._reader.float32();\n                operation.use_mean = this._reader.byte() !== 0;\n                break;\n            case 'lstm':\n                operation.direction = this._reader.uint32();\n                operation.layout = this._reader.uint32();\n                operation.activations = this.strings();\n                break;\n            case 'matmul':\n                operation.rshape_src1 = this._reader.byte();\n                operation.rshape_src2 = this._reader.byte();\n                operation.fused_clamp_low = this._reader.float32();\n                operation.fused_clamp_high = this._reader.float32();\n                break;\n            case 'normal':\n                operation.type = this._reader.byte();\n                break;\n            case 'random_normal':\n                operation.datatype_dest = this._reader.byte();\n                operation.rshape_dest = this._reader.byte();\n                operation.mean = this._reader.float32();\n                operation.std = this._reader.float32();\n                operation.seed = this._reader.float32();\n                break;\n            case 'normal_like':\n                operation.type = this._reader.byte();\n                break;\n            case 'one_hot':\n                operation.one_hot_mode = this._reader.byte();\n                break;\n            case 'pad':\n                operation.datatype = this._reader.byte();\n                operation.rshape_src = this._reader.byte();\n                operation.rstride_src = this._reader.byte();\n                operation.rstride_dest = this._reader.byte();\n                operation.rpaddings = this._reader.byte();\n                operation.pad_mode = this._reader.byte();\n                break;\n            case 'quantize':\n                operation.target_type = this._reader.byte();\n                break;\n            case 'quant_param_of':\n                operation.quant_mode = this._reader.uint32();\n                break;\n            case 'range_of':\n                operation.is_range_of_weight = this._reader.byte() !== 0;\n                break;\n            case 'reduce':\n                operation.reduce_op = this._reader.byte();\n                break;\n            case 'reduce_arg':\n                operation.reduce_arg_op = this._reader.byte();\n                operation.dest_type = this._reader.byte();\n                break;\n            case 'reduce_window2d':\n                operation.reduce_op = this._reader.byte();\n                break;\n            case 'require':\n                operation.message = this.string();\n                operation.can_fold_const_call = this._reader.byte() !== 0;\n                break;\n            case 'resize_image':\n                operation.resize_mode = this._reader.byte();\n                operation.transformation_mode = this._reader.uint32();\n                operation.nearest_mode = this._reader.uint32();\n                operation.is_tfresize = this._reader.byte() !== 0;\n                break;\n            case 'unary':\n                operation.unary_op = this._reader.byte();\n                break;\n            case 'uniform':\n                operation.type = this._reader.byte();\n                break;\n            case 'uniform_like':\n                operation.type = this._reader.byte();\n                break;\n            case 'where':\n                operation.is_tf_where = this._reader.byte() !== 0;\n                break;\n            default:\n                break;\n        }\n    }\n};\n\nkmodel.BytecodeReader.v6 = class extends kmodel.BytecodeReader.v5 {\n\n    constructor(reader) {\n        super(reader);\n        this._opcodes = new Map([\n            [0, 'nop'], [1, 'ldnull'], [2, 'ldc_i4'], [3, 'ldc_i4_0'], [4, 'ldc_i4_1'],\n            [5, 'ldc_r4'], [6, 'ldind_i1'], [7, 'ldind_i2'], [8, 'ldind_i4'], [9, 'ldind_i'],\n            [10, 'ldind_u1'], [11, 'ldind_u2'], [12, 'ldind_u4'], [13, 'ldind_u'],\n            [14, 'ldind_br2'], [15, 'ldind_r4'], [16, 'stind_i1'], [17, 'stind_i2'],\n            [18, 'stind_i4'], [19, 'stind_i'], [20, 'stind_br2'], [21, 'stind_r4'],\n            [22, 'lea_gp'], [23, 'ldelem_i1'], [24, 'ldelem_i2'], [25, 'ldelem_i4'],\n            [26, 'ldelem_i'], [27, 'ldelem_u1'], [28, 'ldelem_u2'], [29, 'ldelem_u4'],\n            [30, 'ldelem_u'], [31, 'ldelem_br2'], [32, 'ldelem_r4'], [33, 'stelem_i1'],\n            [34, 'stelem_i2'], [35, 'stelem_i4'], [36, 'stelem_i'], [37, 'stelem_br2'],\n            [38, 'stelem_r4'], [39, 'ldarg'], [40, 'ldarg_0'], [41, 'ldarg_1'],\n            [42, 'ldarg_2'], [43, 'ldarg_3'], [44, 'ldarg_4'], [45, 'ldarg_5'],\n            [46, 'dup'], [47, 'pop'], [48, 'ldlocal'], [49, 'stlocal'], [50, 'ldtuple_elem'],\n            [51, 'ldtuple'], [52, 'lddatatype'], [53, 'ldtensor'], [54, 'ldscalar'],\n            [55, 'neg'], [56, 'add'], [57, 'sub'], [58, 'mul'], [59, 'div'], [60, 'div_u'],\n            [61, 'rem'], [62, 'rem_u'], [63, 'and'], [64, 'or'], [65, 'xor'], [66, 'not'],\n            [67, 'shl'], [68, 'shr'], [69, 'shr_u'], [70, 'clt'], [71, 'clt_u'],\n            [72, 'cle'], [73, 'cle_u'], [74, 'ceq'], [75, 'cge'], [76, 'cge_u'],\n            [77, 'cgt'], [78, 'cgt_u'], [79, 'cne'], [80, 'conv_i1'], [81, 'conv_i2'],\n            [82, 'conv_i4'], [83, 'conv_i'], [84, 'conv_u1'], [85, 'conv_u2'],\n            [86, 'conv_u4'], [87, 'conv_u'], [88, 'conv_br2'], [89, 'conv_r4'],\n            [90, 'br'], [91, 'br_true'], [92, 'br_false'], [93, 'ret'], [94, 'call'],\n            [95, 'ecall'], [96, 'extcall'], [97, 'cuscall'], [98, 'throw'], [99, 'break'],\n            [100, 'tensor']\n        ]);\n        this._tensorFunctions = new Map([\n            [0, { name: 'batch_normalization', category: 'Normalization' }],\n            [1, { name: 'batch_to_space', category: 'Transform' }],\n            [2, { name: 'binary', category: '' }],\n            [3, { name: 'bitcast', category: '' }],\n            [4, { name: 'broadcast', category: '' }],\n            [5, { name: 'broadcast_shape', category: 'Shape' }],\n            [6, { name: 'bucket_pad', category: '' }],\n            [7, { name: 'cast', category: '' }],\n            [8, { name: 'celu', category: 'Activation' }],\n            [9, { name: 'clamp', category: 'Activation' }],\n            [10, { name: 'compare', category: '' }],\n            [11, { name: 'concat', category: 'Tensor' }],\n            [12, { name: 'condition', category: '' }],\n            [13, { name: 'constant_of_shape', category: '' }],\n            [14, { name: 'conv2d', category: 'Layer' }],\n            [15, { name: 'conv2d_shape', category: 'Shape' }],\n            [16, { name: 'conv2d_transpose', category: 'Layer' }],\n            [17, { name: 'conv2d_transpose_shape', category: 'Shape' }],\n            [18, { name: 'cum_sum', category: '' }],\n            [19, { name: 'dequantize', category: 'Quantization' }],\n            [20, { name: 'elu', category: 'Activation' }],\n            [21, { name: 'erf', category: 'Activation' }],\n            [22, { name: 'expand', category: '' }],\n            [23, { name: 'fake_dequantize', category: 'Quantization' }],\n            [24, { name: 'fake_quantize', category: 'Quantization' }],\n            [25, { name: 'fix_shape', category: 'Shape' }],\n            [26, { name: 'flatten', category: 'Shape' }],\n            [27, { name: 'gather', category: 'Transform' }],\n            [28, { name: 'gather_elements', category: 'Transform' }],\n            [29, { name: 'gather_nd', category: 'Transform' }],\n            [30, { name: 'gelu', category: 'Activation' }],\n            [31, { name: 'get_item', category: '' }],\n            [32, { name: 'get_paddings', category: '' }],\n            [33, { name: 'hardmax', category: 'Activation' }],\n            [34, { name: 'hard_sigmoid', category: 'Activation' }],\n            [35, { name: 'hard_swish', category: 'Activation' }],\n            [36, { name: 'index_of', category: '' }],\n            [37, { name: 'instance_normalization', category: 'Normalization' }],\n            [38, { name: 'l2_normalization', category: 'Normalization' }],\n            [39, { name: 'layer_norm', category: 'Normalization' }],\n            [40, { name: 'leaky_relu', category: 'Activation' }],\n            [41, { name: 'log_softmax', category: 'Activation' }],\n            [42, { name: 'lp_normalization', category: 'Normalization' }],\n            [43, { name: 'lrn', category: 'Normalization' }],\n            [44, { name: 'lstm', category: 'Layer' }],\n            [45, { name: 'mat_mul', category: 'Layer' }],\n            [46, { name: 'mat_mul_shape', category: 'Shape' }],\n            [47, { name: 'normal' }],\n            [48, { name: 'normal_like' }],\n            [49, { name: 'one_hot', category: '' }],\n            [50, { name: 'pad', category: '' }],\n            [51, { name: 'prelu', category: 'Activation' }],\n            [52, { name: 'prod', category: '' }],\n            [53, { name: 'quantize', category: 'Quantization' }],\n            [54, { name: 'quant_param_of', category: 'Quantization' }],\n            [55, { name: 'range', category: '' }],\n            [56, { name: 'range_of', category: '' }],\n            [57, { name: 'rank', category: 'Shape' }],\n            [58, { name: 'reduce', category: 'Reduce' }],\n            [59, { name: 'reduce_arg', category: 'Reduce' }],\n            [60, { name: 'reduce_window2d', category: 'Pool' }],\n            [61, { name: 'relu', category: 'Activation' }],\n            [62, { name: 'relu6', category: 'Activation' }],\n            [63, { name: 'require', category: '' }],\n            [64, { name: 'reshape', category: 'Shape' }],\n            [65, { name: 'reshape_shape', category: 'Shape' }],\n            [66, { name: 'resize_image', category: 'Transform' }],\n            [67, { name: 'reverse_sequence', category: '' }],\n            [68, { name: 'scatter_nd', category: 'Transform' }],\n            [69, { name: 'select', category: '' }],\n            [70, { name: 'selu', category: 'Activation' }],\n            [71, { name: 'shape_of', category: 'Shape' }],\n            [72, { name: 'sigmoid', category: 'Activation' }],\n            [73, { name: 'size_of', category: 'Shape' }],\n            [74, { name: 'slice', category: 'Tensor' }],\n            [75, { name: 'softmax', category: 'Activation' }],\n            [76, { name: 'softplus', category: 'Activation' }],\n            [77, { name: 'softsign', category: 'Activation' }],\n            [78, { name: 'space_to_batch', category: 'Transform' }],\n            [79, { name: 'split', category: 'Tensor' }],\n            [80, { name: 'squeeze', category: 'Shape' }],\n            [81, { name: 'squeeze_shape', category: 'Shape' }],\n            [82, { name: 'stack', category: 'Tensor' }],\n            [83, { name: 'swish', category: 'Activation' }],\n            [84, { name: 'tile', category: '' }],\n            [85, { name: 'top_k', category: '' }],\n            [86, { name: 'transpose', category: 'Transform' }],\n            [87, { name: 'transpose_shape', category: 'Shape' }],\n            [88, { name: 'trilu', category: '' }],\n            [89, { name: 'unary', category: '' }],\n            [90, { name: 'uniform' }],\n            [91, { name: 'uniform_like' }],\n            [92, { name: 'unsqueeze', category: 'Shape' }],\n            [93, { name: 'unsqueeze_shape', category: 'Shape' }],\n            [94, { name: 'where', category: '' }]\n        ]);\n    }\n\n    operation(operation) {\n        switch (operation.opcode) {\n            case 'ldarg':\n                operation.index = this._reader.uint16();\n                break;\n            case 'call':\n                operation.args = this._reader.uint16();\n                operation.target = this._reader.int32();\n                break;\n            case 'ecall':\n                operation.args = this._reader.uint16();\n                break;\n            case 'ldlocal':\n            case 'stlocal':\n                operation.index = this._reader.uint16();\n                break;\n            default:\n                super.operation(operation);\n        }\n    }\n\n    tensor(operation) {\n        switch (operation.tensor_name) {\n            case 'binary':\n                operation.binary_op = this._reader.byte();\n                break;\n            case 'matmul':\n                break;\n            case 'normal':\n                operation.type = this._reader.byte();\n                break;\n            case 'random_normal':\n                operation.type = this._reader.byte();\n                break;\n            case 'normal_like':\n                operation.type = this._reader.byte();\n                break;\n            case 'one_hot':\n                operation.one_hot_mode = this._reader.byte();\n                break;\n            case 'pad':\n                operation.pad_mode = this._reader.byte();\n                break;\n            case 'cumsum':\n                break;\n            case 'conv2d':\n                operation.pad_mode = this._reader.byte();\n                break;\n            default:\n                super.tensor(operation);\n        }\n    }\n};\n\nkmodel.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading kmodel.';\n    }\n};\n\nexport const ModelFactory = kmodel.ModelFactory;\n"
  },
  {
    "path": "source/lasagne-metadata.json",
    "content": "[\n  {\n    \"name\": \"lasagne.layers.conv.Conv2DLayer\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"lasagne.layers.pool.MaxPool2DLayer\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"lasagne.layers.dense.DenseLayer\",\n    \"category\": \"Layer\"\n  }\n]"
  },
  {
    "path": "source/lasagne.js",
    "content": "\n// Experimental\n\nconst lasagne = {};\n\nlasagne.ModelFactory = class {\n\n    async match(context) {\n        const obj = await context.peek('pkl');\n        if (obj && obj.__class__ && obj.__class__.__module__ === 'nolearn.lasagne.base' && obj.__class__.__name__ === 'NeuralNet') {\n            return context.set('lasagne', obj);\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('lasagne-metadata.json');\n        return new lasagne.Model(metadata, context.value);\n    }\n};\n\nlasagne.Model = class {\n\n    constructor(metadata, model) {\n        this.format = 'Lasagne';\n        this.modules = [new lasagne.Graph(metadata, model)];\n    }\n};\n\nlasagne.Graph = class {\n\n    constructor(metadata, model) {\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (!values.has(name)) {\n                values.set(name, new lasagne.Value(name, type, tensor));\n            } else if (tensor) {\n                throw new lasagne.Error(`Duplicate value '${name}'.`);\n            } else if (type && !type.equals(values.get(name).type)) {\n                throw new lasagne.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        for (const [name] of model.layers) {\n            const layer = model.layers_[name];\n            if (layer.input_layer && layer.input_layer.name) {\n                const input_layer = layer.input_layer;\n                const dataType = input_layer.input_var && input_layer.input_var.type ? input_layer.input_var.type.dtype : '?';\n                const shape = layer.input_shape ? new lasagne.TensorShape(layer.input_shape) : null;\n                const type = shape ? new lasagne.TensorType(dataType, shape) : null;\n                values.map(input_layer.name, type);\n            }\n        }\n        for (const [name] of model.layers) {\n            const layer = model.layers_[name];\n            if (layer && layer.__class__ && layer.__class__.__module__ === 'lasagne.layers.input' && layer.__class__.__name__ === 'InputLayer') {\n                const shape = new lasagne.TensorShape(layer.shape);\n                const type = new lasagne.TensorType(layer.input_var.type.dtype, shape);\n                const argument = new lasagne.Argument(layer.name, [values.map(layer.name, type)]);\n                this.inputs.push(argument);\n                continue;\n            }\n            this.nodes.push(new lasagne.Node(metadata, layer, values));\n        }\n        if (model._output_layer) {\n            const output_layer = model._output_layer;\n            this.outputs.push(new lasagne.Argument(output_layer.name, [values.map(output_layer.name)]));\n        }\n    }\n};\n\nlasagne.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nlasagne.Value = class {\n\n    constructor(name, type, initializer) {\n        if (typeof name !== 'string') {\n            throw new lasagne.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nlasagne.Node = class {\n\n    constructor(metadata, layer, values) {\n        this.name = layer.name || '';\n        const type = layer.__class__ ? `${layer.__class__.__module__}.${layer.__class__.__name__}` : '';\n        this.type = metadata.type(type) || { name: type };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const params = new Map();\n        for (const [key, value] of Object.entries(layer)) {\n            if (key === 'name' || key === 'params' || key === 'input_layer' || key === 'input_shape') {\n                continue;\n            }\n            if (value && value.__class__ && value.__class__.__module__ === 'theano.tensor.sharedvar' && value.__class__.__name__ === 'TensorSharedVariable') {\n                params.set(value.name, key);\n                continue;\n            }\n            const type = value && value.__class__ ? `${value.__class__.__module__}.${value.__class__.__name__}` : null;\n            const attribute = new lasagne.Argument(key, value, type);\n            this.attributes.push(attribute);\n        }\n        if (layer.input_layer && layer.input_layer.name) {\n            const value = values.map(layer.input_layer.name);\n            const argument = new lasagne.Argument('input', [value]);\n            this.inputs.push(argument);\n        }\n        if (layer.params) {\n            for (const [param] of layer.params) {\n                const param_key = params.get(param.name);\n                if (param_key) {\n                    const initializer = new lasagne.Tensor(param.container.storage[0]);\n                    const argument = new lasagne.Argument(param_key, [values.map(param.name, null, initializer)]);\n                    this.inputs.push(argument);\n                }\n            }\n        }\n        this.outputs.push(new lasagne.Argument('output', [values.map(this.name)]));\n    }\n};\n\nlasagne.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nlasagne.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    equals(obj) {\n        return obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions) &&\n            this.dimensions.length === obj.dimensions.length &&\n            obj.dimensions.every((value, index) => this.dimensions[index] === value);\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`;\n        }\n        return '';\n    }\n};\n\nlasagne.Tensor = class {\n\n    constructor(storage) {\n        this.type = new lasagne.TensorType(storage.dtype.__name__, new lasagne.TensorShape(storage.shape));\n        this.values = storage.data;\n    }\n};\n\nlasagne.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Lasagne Error';\n    }\n};\n\nexport const ModelFactory = lasagne.ModelFactory;\n"
  },
  {
    "path": "source/lightgbm.js",
    "content": "\nimport * as python from './python.js';\n\nconst lightgbm = {};\n\nlightgbm.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        const signature = [0x74, 0x72, 0x65, 0x65, 0x0A];\n        if (stream && stream.length >= signature.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {\n            return context.set('lightgbm.text');\n        }\n        const obj = await context.peek('pkl');\n        if (obj && obj.__class__ && obj.__class__.__module__ && obj.__class__.__module__.startsWith('lightgbm.')) {\n            return context.set('lightgbm.pickle', obj);\n        }\n        return null;\n    }\n\n    async open(context) {\n        switch (context.type) {\n            case 'lightgbm.pickle': {\n                const obj = context.value;\n                return new lightgbm.Model(obj, 'LightGBM Pickle');\n            }\n            case 'lightgbm.text': {\n                const stream = context.stream;\n                const buffer = stream.peek();\n                const decoder = new TextDecoder('utf-8');\n                const model_str = decoder.decode(buffer);\n                const execution = new python.Execution();\n                const obj = execution.invoke('lightgbm.basic.Booster', []);\n                obj.LoadModelFromString(model_str);\n                return new lightgbm.Model(obj, 'LightGBM');\n            }\n            default: {\n                throw new lightgbm.Error(`Unsupported LightGBM format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nlightgbm.Model = class {\n\n    constructor(obj, format) {\n        this.format = format + (obj && obj.version ? ` ${obj.version}` : '');\n        this.modules = [new lightgbm.Graph(obj)];\n    }\n};\n\nlightgbm.Graph = class {\n\n    constructor(model) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = [];\n        const feature_names = model.feature_names || [];\n        for (let i = 0; i < feature_names.length; i++) {\n            const name = feature_names[i];\n            // const info = model.feature_infos && i < model.feature_infos.length ? model.feature_infos[i] : null;\n            const value = new lightgbm.Value(name);\n            values.push(value);\n            if (feature_names.length < 1000) {\n                const argument = new lightgbm.Argument(name, [value]);\n                this.inputs.push(argument);\n            }\n        }\n        const node = new lightgbm.Node(model, values);\n        this.nodes.push(node);\n    }\n};\n\nlightgbm.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nlightgbm.Value = class {\n\n    constructor(name) {\n        if (typeof name !== 'string') {\n            throw new lightgbm.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n    }\n};\n\nlightgbm.Node = class {\n\n    constructor(obj, values, stack) {\n        const type = obj && obj.__class__ ? `${obj.__class__.__module__}.${obj.__class__.__name__}` : 'builtins.object';\n        this.name = '';\n        this.type = { name: type };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (values) {\n            const argument = new lightgbm.Argument('features', values);\n            this.inputs.push(argument);\n        }\n        const isObject = (obj) => {\n            if (obj && typeof obj === 'object') {\n                const proto = Object.getPrototypeOf(obj);\n                return proto === Object.prototype || proto === null;\n            }\n            return false;\n        };\n        stack = stack || new Set();\n        const entries = Object.entries(obj).filter(([key, value]) => value !== undefined && key !== 'feature_names' && key !== 'feature_infos');\n        for (const [key, value] of entries) {\n            if (Array.isArray(value) && value.every((obj) => isObject(obj))) {\n                const values = value.filter((obj) => !stack.has(obj));\n                const nodes = values.map((obj) => {\n                    stack.add(obj);\n                    const node = new lightgbm.Node(obj, null, stack);\n                    stack.delete(obj);\n                    return node;\n                });\n                const attribute = new lightgbm.Argument(key, nodes, 'object[]');\n                this.attributes.push(attribute);\n                continue;\n            } else if (isObject(value) && !stack.has(value)) {\n                stack.add(obj);\n                const node = new lightgbm.Node(obj, null, stack);\n                stack.delete(obj);\n                const attribute = new lightgbm.Argument(key, node, 'object');\n                this.attributes.push(attribute);\n            } else {\n                const attribute = new lightgbm.Argument(key, value);\n                this.attributes.push(attribute);\n            }\n        }\n    }\n};\n\nlightgbm.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading LightGBM model.';\n    }\n};\n\nexport const ModelFactory = lightgbm.ModelFactory;\n\n"
  },
  {
    "path": "source/mediapipe.js",
    "content": "\nimport * as protobuf from './protobuf.js';\n\nconst mediapipe = {};\n\nmediapipe.ModelFactory = class {\n\n    async match(context) {\n        const tags = await context.tags('pbtxt');\n        if (tags.has('node') && ['input_stream', 'output_stream', 'input_side_packet', 'output_side_packet'].some((key) => tags.has(key) || tags.has(`node.${key}`))) {\n            return context.set('mediapipe.pbtxt');\n        }\n        return null;\n    }\n\n    async open(context) {\n        // mediapipe.proto = await context.require('./mediapipe-proto');\n        mediapipe.proto = {};\n        let config = null;\n        try {\n            const reader = await context.read('protobuf.text');\n            // const config = mediapipe.proto.mediapipe.CalculatorGraphConfig.decodeText(reader);\n            config = new mediapipe.Object(reader);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new mediapipe.Error(`File text format is not mediapipe.CalculatorGraphConfig (${message.replace(/\\.$/, '')}).`);\n        }\n        return new mediapipe.Model(config);\n    }\n};\n\nmediapipe.Model = class {\n\n    constructor(config) {\n        this.format = 'MediaPipe';\n        this.modules = [new mediapipe.Graph(config)];\n    }\n};\n\nmediapipe.Graph = class {\n\n    constructor(config) {\n        config = config || {};\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const types = new Map();\n        const type = (list) => {\n            if (!Array.isArray(list)) {\n                list = list ? [list] : [];\n            }\n            return list.map((item) => {\n                const parts = item.split(':');\n                const name = parts.pop();\n                const type = parts.join(':');\n                if (!types.has(name)) {\n                    const value = new Set();\n                    if (type) {\n                        value.add(type);\n                    }\n                    types.set(name, value);\n                } else if (type && !types.get(name).has(type)) {\n                    types.get(name).add(type);\n                }\n                return name;\n            });\n        };\n        config.input_stream = type(config.input_stream);\n        config.output_stream = type(config.output_stream);\n        config.input_side_packet = type(config.input_side_packet);\n        config.output_side_packet = type(config.output_side_packet);\n        if (!Array.isArray(config.node)) {\n            config.node = config.node ? [config.node] : [];\n        }\n        for (const node of config.node) {\n            node.input_stream = type(node.input_stream);\n            node.output_stream = type(node.output_stream);\n            node.input_side_packet = type(node.input_side_packet);\n            node.output_side_packet = type(node.output_side_packet);\n        }\n        const values = new Map();\n        for (const [name, value] of types) {\n            const type = Array.from(value).join(',');\n            values.set(name, new mediapipe.Value(name, type || null));\n        }\n        const value = (name) => {\n            return values.get(name);\n        };\n        for (const name of config.input_stream) {\n            const argument = new mediapipe.Argument(name, [value(name)]);\n            this.inputs.push(argument);\n        }\n        for (const name of config.output_stream) {\n            const argument = new mediapipe.Argument(name, [value(name)]);\n            this.outputs.push(argument);\n        }\n        for (const name of config.input_side_packet) {\n            const argument = new mediapipe.Argument(name, [value(name, type)]);\n            this.inputs.push(argument);\n        }\n        for (const output of config.output_side_packet) {\n            const parts = output.split(':');\n            const type = (parts.length > 1) ? parts.shift() : '';\n            const name = parts.shift();\n            const argument = new mediapipe.Argument(name, [value(name, type)]);\n            this.outputs.push(argument);\n        }\n        for (const node of config.node) {\n            this.nodes.push(new mediapipe.Node(node, value));\n        }\n    }\n};\n\nmediapipe.Node = class {\n\n    constructor(node, value) {\n        const type = node.calculator || '?';\n        this.name = '';\n        this.type = { name: type.replace(/Calculator$/, '') };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (node.input_stream) {\n            const values = node.input_stream.map((name) => value(name));\n            const argument = new mediapipe.Argument('input_stream', values);\n            this.inputs.push(argument);\n        }\n        if (node.output_stream) {\n            const values = node.output_stream.map((name) => value(name));\n            this.outputs.push(new mediapipe.Argument('output_stream', values));\n        }\n        if (node.input_side_packet) {\n            const values = node.input_side_packet.map((name) => value(name));\n            this.inputs.push(new mediapipe.Argument('output_stream', values));\n        }\n        if (node.output_side_packet) {\n            const values = node.output_side_packet.map((name) => value(name));\n            this.outputs.push(new mediapipe.Argument('output_side_packet', values));\n        }\n        const options = new Map();\n        if (node.options) {\n            for (const key of Object.keys(node.options)) {\n                options.set(key, node.options[key]);\n            }\n        }\n        let node_options = node.node_options;\n        if (!Array.isArray(node_options)) {\n            node_options = node_options ? [node_options] : [];\n        }\n        if (mediapipe.proto.google && node_options.every((options) => options instanceof mediapipe.proto.google.protobuf.Any)) {\n            for (const entry of node_options) {\n                const value = new RegExp(/^\\{(.*)\\}\\s*$/, 's').exec(entry.value);\n                const buffer = new TextEncoder('utf-8').encode(value[1]);\n                const reader = protobuf.TextReader.open(buffer);\n                if (entry.type_url.startsWith('type.googleapis.com/mediapipe.')) {\n                    const type = entry.type_url.split('.').pop();\n                    if (mediapipe.proto && mediapipe.proto.mediapipe && mediapipe.proto.mediapipe[type]) {\n                        const message = mediapipe.proto.mediapipe[type].decodeText(reader);\n                        for (const key of Object.keys(message)) {\n                            options.set(key, message[key]);\n                        }\n                        continue;\n                    }\n                }\n                const message = new mediapipe.Object(reader);\n                for (const [name, value] of Object.entries(message)) {\n                    options.set(name, value);\n                }\n            }\n        } else {\n            for (const option of node_options) {\n                for (const [name, value] of Object.entries(option)) {\n                    if (name !== '__type__') {\n                        options.set(name, value);\n                    }\n                }\n            }\n        }\n        for (const [name, value] of options) {\n            const attribute = new mediapipe.Argument(name, value);\n            this.attributes.push(attribute);\n        }\n    }\n};\n\nmediapipe.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\nmediapipe.Value = class {\n\n    constructor(name, type = null) {\n        if (typeof name !== 'string') {\n            throw new mediapipe.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = type;\n    }\n};\n\nmediapipe.Object = class {\n\n    constructor(reader, block) {\n        if (!block) {\n            reader.start();\n        }\n        const type = reader.token();\n        if (type.startsWith('[') && type.endsWith(']')) {\n            this.__type__ = type.substring(1, type.length - 1);\n            reader.next();\n            reader.match(':');\n            reader.start();\n        }\n        const arrayTags = new Set();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            const next = reader.token();\n            let obj = null;\n            if (next === '{') {\n                reader.start();\n                obj = new mediapipe.Object(reader, true);\n                if (obj.__type__) {\n                    while (!reader.end()) {\n                        if (!Array.isArray(obj)) {\n                            obj = [obj];\n                        }\n                        const token = reader.token();\n                        if (token.startsWith('[') && token.endsWith(']')) {\n                            obj.push(new mediapipe.Object(reader, true));\n                            continue;\n                        }\n                        break;\n                    }\n                }\n            } else if (next.startsWith('\"') && next.endsWith('\"')) {\n                obj = next.substring(1, next.length - 1);\n                reader.next();\n            } else if (next === 'true' || next === 'false') {\n                obj = next;\n                reader.next();\n            } else if (reader.first()) {\n                obj = [];\n                while (!reader.last()) {\n                    const data = reader.token();\n                    reader.next();\n                    if (!isNaN(data)) {\n                        obj.push(parseFloat(data));\n                    }\n                }\n            } else if (isNaN(next)) {\n                obj = next;\n                reader.next();\n            } else {\n                obj = parseFloat(next);\n                reader.next();\n            }\n            if (this[tag] && (!Array.isArray(this[tag]) || arrayTags.has(tag))) {\n                this[tag] = [this[tag]];\n                arrayTags.delete(tag);\n            }\n            if (this[tag]) {\n                this[tag].push(obj);\n            } else {\n                if (Array.isArray(obj)) {\n                    arrayTags.add(tag);\n                }\n                this[tag] = obj;\n            }\n            reader.match(',');\n        }\n    }\n};\n\nmediapipe.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading MediaPipe model.';\n    }\n};\n\nexport const ModelFactory = mediapipe.ModelFactory;\n"
  },
  {
    "path": "source/megengine-metadata.json",
    "content": "[\n  {\n    \"name\": \"megengine.distributed.functional.all_gather\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.all_reduce_max\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.all_reduce_min\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.all_reduce_sum\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.all_to_all\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" },\n      { \"name\": \"split_axis\" },\n      { \"name\": \"concat_axis\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.broadcast\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.collective_comm\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.gather\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.reduce_scatter_sum\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.reduce_sum\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.remote_recv\",\n    \"attributes\": [\n      { \"name\": \"src_rank\" },\n      { \"name\": \"device\" },\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.remote_send\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"dest_rank\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.distributed.functional.scatter\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"group\" },\n      { \"name\": \"device\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.abs\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.add\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.acos\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.asin\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.atan\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.atan2\",\n    \"attributes\": [\n      { \"name\": \"y\" },\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.asinh\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.acosh\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.atanh\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.ceil\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.clip\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"lower\" },\n      { \"name\": \"upper\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.cos\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.cosh\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.div\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.equal\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.exp\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.expm1\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.floor\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.floor_div\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.greater\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.greater_equal\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.left_shift\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.less\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.less_equal\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.log\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.log1p\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.logical_and\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.logical_not\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.logical_or\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.logical_xor\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.logaddexp\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.maximum\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.minimum\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.mod\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.mul\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.neg\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.not_equal\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.pow\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.right_shift\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.round\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.sin\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.sinh\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.sqrt\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.square\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.sub\",\n    \"attributes\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.tan\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.functional.elemwise.tanh\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.loss.l1_loss\",\n    \"category\": \"Layer\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"megengine.functional.loss.square_loss\",\n    \"category\": \"Layer\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"megengine.functional.loss.cross_entropy\",\n    \"category\": \"Layer\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"megengine.functional.loss.binary_cross_entropy\",\n    \"category\": \"Layer\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"megengine.functional.loss.hinge_loss\",\n    \"category\": \"Layer\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"megengine.functional.loss.ctc_loss\",\n    \"attributes\": [\n      { \"name\": \"pred\" },\n      { \"name\": \"pred_lengths\" },\n      { \"name\": \"label\" },\n      { \"name\": \"label_lengths\" },\n      { \"name\": \"blank\" },\n      { \"name\": \"reduction\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.argmax\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.argmin\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.argsort\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"descending\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.dot\",\n    \"attributes\": [\n      { \"name\": \"inp1\" },\n      { \"name\": \"inp2\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.isinf\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.isnan\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.matinv\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.matmul\",\n    \"attributes\": [\n      { \"name\": \"inp1\" },\n      { \"name\": \"inp2\" },\n      { \"name\": \"transpose_a\" },\n      { \"name\": \"transpose_b\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.max\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.mean\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.min\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.norm\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"ord\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.normalize\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"ord\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"eps\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.prod\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.sign\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.sort\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"descending\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.std\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.sum\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.svd\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"full_matrices\" },\n      { \"name\": \"compute_uv\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.math.topk\",\n    \"category\": \"Layer\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"megengine.functional.math.var\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.metric.topk_accuracy\",\n    \"attributes\": [\n      { \"name\": \"logits\" },\n      { \"name\": \"target\" },\n      { \"name\": \"topk\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.adaptive_avg_pool2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"oshp\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.adaptive_max_pool2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"oshp\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.avg_pool2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"kernel_size\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"mode\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.batch_norm\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"running_mean\" },\n      { \"name\": \"running_var\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.conv1d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.conv2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.conv3d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"conv_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.conv_transpose2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.conv_transpose3d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.deformable_conv2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"offset\" },\n      { \"name\": \"mask\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.deformable_psroi_pooling\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"rois\" },\n      { \"name\": \"trans\" },\n      { \"name\": \"no_trans\" },\n      { \"name\": \"part_size\" },\n      { \"name\": \"pooled_h\" },\n      { \"name\": \"pooled_w\" },\n      { \"name\": \"sample_per_part\" },\n      { \"name\": \"spatial_scale\" },\n      { \"name\": \"trans_std\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.dropout\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"drop_prob\" },\n      { \"name\": \"training\" }\n    ],\n    \"category\": \"Dropout\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.embedding\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"padding_idx\" },\n      { \"name\": \"max_norm\" },\n      { \"name\": \"norm_type\" }\n    ],\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.gelu\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.hsigmoid\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.hswish\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.indexing_one_hot\",\n    \"attributes\": [\n      { \"name\": \"src\" },\n      { \"name\": \"index\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.layer_norm\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"normalized_shape\" },\n      { \"name\": \"affine\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"eps\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.leaky_relu\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"negative_slope\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.linear\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.local_conv2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"conv_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.local_response_norm\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"kernel_size\" },\n      { \"name\": \"k\" },\n      { \"name\": \"alpha\" },\n      { \"name\": \"beta\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.logsigmoid\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.logsumexp\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.logsoftmax\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.max_pool2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"kernel_size\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.one_hot\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"num_classes\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.prelu\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.pad\",\n    \"attributes\": [\n      { \"name\": \"src\" },\n      { \"name\": \"pad_width\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"constant_value\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.relu\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.relu6\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.remap\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"map_xy\" },\n      { \"name\": \"border_mode\" },\n      { \"name\": \"scalar\" },\n      { \"name\": \"interp_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.sigmoid\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.sliding_window\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"kernel_size\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"dilation\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.sliding_window_transpose\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"output_size\" },\n      { \"name\": \"kernel_size\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"dilation\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.silu\",\n    \"attributes\": [\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.softmax\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.softplus\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.sync_batch_norm\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"running_mean\" },\n      { \"name\": \"running_var\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"training\" },\n      { \"name\": \"momentum\" },\n      { \"name\": \"eps\" },\n      { \"name\": \"eps_mode\" },\n      { \"name\": \"group\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.warp_affine\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"mat\" },\n      { \"name\": \"out_shape\" },\n      { \"name\": \"border_mode\" },\n      { \"name\": \"border_val\" },\n      { \"name\": \"format\" },\n      { \"name\": \"interp_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.warp_perspective\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"mat\" },\n      { \"name\": \"out_shape\" },\n      { \"name\": \"mat_idx\" },\n      { \"name\": \"border_mode\" },\n      { \"name\": \"border_val\" },\n      { \"name\": \"format\" },\n      { \"name\": \"interp_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.nn.pixel_shuffle\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"upscale_factor\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.debug_param.get_execution_strategy\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.quantized.conv_bias_activation\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"dtype\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"nonlinear_mode\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.quantized.batch_conv_bias_activation\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"dtype\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"nonlinear_mode\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.quantized.conv_transpose2d\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"dtype\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"padding\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"conv_mode\" },\n      { \"name\": \"compute_mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.arange\",\n    \"attributes\": [\n      { \"name\": \"start\" },\n      { \"name\": \"stop\" },\n      { \"name\": \"step\" },\n      { \"name\": \"dtype\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.broadcast_to\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"shape\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.concat\",\n    \"attributes\": [\n      { \"name\": \"inps\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.cond_take\",\n    \"attributes\": [\n      { \"name\": \"mask\" },\n      { \"name\": \"x\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.cumsum\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.diag\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"k\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.expand_dims\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.eye\",\n    \"attributes\": [\n      { \"name\": \"N\" },\n      { \"name\": \"M\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.flatten\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"start_axis\" },\n      { \"name\": \"end_axis\" }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.full\",\n    \"attributes\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"value\" },\n      { \"name\": \"dtype\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.full_like\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"value\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.gather\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"index\" }\n    ],\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.linspace\",\n    \"attributes\": [\n      { \"name\": \"start\" },\n      { \"name\": \"stop\" },\n      { \"name\": \"num\" },\n      { \"name\": \"dtype\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.ones\",\n    \"attributes\": [\n      { \"name\": \"shape\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.ones_like\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.repeat\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"repeats\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.reshape\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"target_shape\" }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.roll\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"shift\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.split\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"nsplits_or_sections\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.squeeze\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" }\n    ],\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.stack\",\n    \"attributes\": [\n      { \"name\": \"inps\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.scatter\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"index\" },\n      { \"name\": \"source\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.tile\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"reps\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.copy\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"device\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.transpose\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"pattern\" }\n    ],\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.swapaxes\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"axis1\" },\n      { \"name\": \"axis2\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.where\",\n    \"attributes\": [\n      { \"name\": \"mask\" },\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.zeros\",\n    \"attributes\": [\n      { \"name\": \"shape\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.tensor.zeros_like\",\n    \"attributes\": [\n      { \"name\": \"inp\" }\n    ],\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.correlation\",\n    \"attributes\": [\n      { \"name\": \"data1\" },\n      { \"name\": \"data2\" },\n      { \"name\": \"kernel_size\" },\n      { \"name\": \"max_displacement\" },\n      { \"name\": \"stride1\" },\n      { \"name\": \"stride2\" },\n      { \"name\": \"pad_size\" },\n      { \"name\": \"is_multiply\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.cvt_color\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"mode\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.interpolate\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"size\" },\n      { \"name\": \"scale_factor\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"align_corners\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.nms\",\n    \"attributes\": [\n      { \"name\": \"boxes\" },\n      { \"name\": \"scores\" },\n      { \"name\": \"iou_thresh\" },\n      { \"name\": \"max_output\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.nvof\",\n    \"attributes\": [\n      { \"name\": \"src\" },\n      { \"name\": \"precision\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.roi_align\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"rois\" },\n      { \"name\": \"output_shape\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"spatial_scale\" },\n      { \"name\": \"sample_points\" },\n      { \"name\": \"aligned\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.functional.vision.roi_pooling\",\n    \"attributes\": [\n      { \"name\": \"inp\" },\n      { \"name\": \"rois\" },\n      { \"name\": \"output_shape\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"scale\" }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"__lt__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__le__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__gt__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ge__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__eq__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ne__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__neg__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__pos__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__abs__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__invert__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__round__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__floor__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__ceil__\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ]\n  },\n  {\n    \"name\": \"__add__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__sub__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__mul__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__matmul__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"other\" }\n    ]\n  },\n  {\n    \"name\": \"__truediv__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__floordiv__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__mod__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__pow__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__lshift__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rshift__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__and__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__or__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__xor__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__radd__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rsub__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rmul__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rmatmul__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"other\" }\n    ]\n  },\n  {\n    \"name\": \"__rtruediv__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rfloordiv__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rmod__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rpow__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rlshift__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rrshift__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rand__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ror__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__rxor__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__iadd__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__isub__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__imul__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__imatmul__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__itruediv__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ifloordiv__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__imod__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ipow__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ilshift__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__irshift__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__iand__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ior__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"__ixor__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"transpose\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ],\n    \"category\": \"Transform\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"astype\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"dtype\" }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"reshape\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ],\n    \"category\": \"Shape\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"_broadcast\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ],\n    \"category\": \"Shape\",\n    \"varargs\": \"args\"\n  },\n  {\n    \"name\": \"flatten\",\n    \"attributes\": [\n      { \"name\": \"self\" }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"sum\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ]\n  },\n  {\n    \"name\": \"prod\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ]\n  },\n  {\n    \"name\": \"min\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ]\n  },\n  {\n    \"name\": \"max\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ]\n  },\n  {\n    \"name\": \"mean\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"keepdims\" }\n    ]\n  },\n  {\n    \"name\": \"__getitem__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"index\" }\n    ]\n  },\n  {\n    \"name\": \"__setitem__\",\n    \"attributes\": [\n      { \"name\": \"self\" },\n      { \"name\": \"index\" },\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"megengine.module.adaptive_pooling.AdaptiveAvgPool2d\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.module.adaptive_pooling.AdaptiveMaxPool2d\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.module.pooling.AvgPool2d\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.module.batch_matmul_activation.BatchMatMulActivation\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.batchnorm.BatchNorm1d\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"megengine.module.batchnorm.BatchNorm2d\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"megengine.module.concat.Concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.module.conv.Conv1d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.Conv2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.Conv3d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv_bn.ConvBn2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv_bn.ConvBnRelu2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.ConvRelu2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.ConvTranspose2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.ConvTranspose3d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.DeformableConv2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.deformable_psroi_pooling.DeformablePSROIPooling\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.module.quant_dequant.DequantStub\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.dropout.Dropout\",\n    \"category\": \"Dropout\"\n  },\n  {\n    \"name\": \"megengine.module.elemwise.Elemwise\"\n  },\n  {\n    \"name\": \"megengine.module.embedding.Embedding\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"megengine.module.activation.GELU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.normalization.GroupNorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"megengine.module.identity.Identity\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.normalization.InstanceNorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"megengine.module.rnn.LSTM\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.rnn.LSTMCell\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.normalization.LayerNorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"megengine.module.activation.LeakyReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.linear.Linear\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.conv.LocalConv2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.lrn.LocalResponseNorm\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.pooling.MaxPool2d\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"megengine.module.module.Module\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.activation.PReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.padding.Pad\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.pixel_shuffle.PixelShuffle\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quant_dequant.QuantStub\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.rnn.RNN\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.rnn.RNNCell\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.activation.ReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.activation.SiLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.activation.Sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.sliding_window.SlidingWindow\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.sliding_window.SlidingWindowTranspose\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.activation.Softmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.batchnorm.SyncBatchNorm\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"megengine.module.qat.batch_matmul_activation.BatchMatMulActivation\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.qat.concat.Concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.module.qat.conv.Conv2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.conv_bn.ConvBn2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.conv_bn.ConvBnRelu2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.conv.ConvRelu2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.conv.ConvTranspose2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.quant_dequant.DequantStub\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.linear.Linear\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.module.QATModule\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.qat.quant_dequant.QuantStub\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.batch_matmul_activation.BatchMatMulActivation\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.concat.Concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.conv.Conv2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.conv_bn.ConvBn2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.conv_bn.ConvBnRelu2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.conv.ConvRelu2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.conv.ConvTranspose2d\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.quant_dequant.DequantStub\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.linear.Linear\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.quant_dequant.QuantStub\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"megengine.module.quantized.module.QuantizedModule\",\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Axis\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionV0\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"data_type\", \"type\": \"ConvolutionV0DataType\", \"default\": \"FLOAT\" },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionV1\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"MaskPropagate\",\n    \"attributes\": [\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"kernel_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"kernel_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"ConvPooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"method\", \"type\": \"ConvPoolingMethod\", \"default\": \"WITH_TEXTURE_OBJ\" },\n      { \"name\": \"convMode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"poolMode\", \"type\": \"ConvPoolingPoolMode\", \"default\": \"AVERAGE\" },\n      { \"name\": \"nonlineMode\", \"type\": \"ConvPoolingNonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"pool_shape_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pool_shape_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pool_stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pool_stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pool_pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pool_pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"conv_stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"conv_stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"conv_pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"conv_pad_w\", \"type\": \"uint32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ConvBiasV0\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"ConvBiasV1\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"data_type\", \"type\": \"ConvolutionV0DataType\", \"default\": \"FLOAT\" },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"ConvBiasV2\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"ConvBiasV3\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"output_block_size\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"ConvBias\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"SeparableConv\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"borderMode\", \"type\": \"SeparableConvBorderMode\", \"default\": \"BORDER_REPLICATE\" },\n      { \"name\": \"is_symm_kernel\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"ksize_h\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"ksize_w\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"anchor_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"anchor_w\", \"type\": \"uint32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"Images2Neibs\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"window_h\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"window_w\", \"type\": \"uint32\", \"default\": 3 }\n    ]\n  },\n  {\n    \"name\": \"SlidingWindowTranspose\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"out_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"out_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"window_h\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"window_w\", \"type\": \"uint32\", \"default\": 3 }\n    ]\n  },\n  {\n    \"name\": \"PoolingV0\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"PoolingV0Mode\", \"default\": \"MAX_\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"window_h\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"window_w\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"PoolingV1\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"PoolingV0Mode\", \"default\": \"MAX_\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"window_h\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"window_w\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": -1 }\n    ]\n  },\n  {\n    \"name\": \"AdaptivePoolingV0\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"PoolingV0Mode\", \"default\": \"MAX_\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"AdaptivePooling\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"PoolingV0Mode\", \"default\": \"MAX_\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"n\", \"type\": \"uint32\", \"default\": 5 },\n      { \"name\": \"k\", \"type\": \"float32\", \"default\": 2 },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.75 }\n    ]\n  },\n  {\n    \"name\": \"BN\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"param_dim\", \"type\": \"BNParamDim\", \"default\": \"DIM_11HW\" },\n      { \"name\": \"fwd_mode\", \"type\": \"BNFwdMode\", \"default\": \"TRAINING\" },\n      { \"name\": \"epsilon\", \"type\": \"float64\", \"default\": 0.0001 },\n      { \"name\": \"avg_factor\", \"type\": \"float64\", \"default\": 1 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"bias\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ROIPoolingMode\", \"default\": \"MAX_\" },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"WarpPerspectiveV1\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"bmode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"border_val\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"WarpPerspective\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"bmode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"border_val\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SpatialTfGridGenerator\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"SpatialTfGridGeneratorMode\", \"default\": \"AFFINE\" }\n    ]\n  },\n  {\n    \"name\": \"SpatialTfSampler\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"SpatialTfSamplerMode\", \"default\": \"BILINEAR\" }\n    ]\n  },\n  {\n    \"name\": \"AddUpdate\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"bias\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Elemwise\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ElemwiseMode\", \"default\": \"RELU\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"ElemwiseMultiType\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ElemwiseMultiTypeMode\", \"default\": \"FUSE_MUL_ADD3_INT16x32x32x32\" }\n    ]\n  },\n  {\n    \"name\": \"PowC\",\n    \"attributes\": [\n      { \"name\": \"exp\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"DctChannelSelectV0\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"fastImpl\", \"type\": \"DctChannelSelectV0FastImpl\", \"default\": \"NONE\" },\n      { \"name\": \"dct_block_size\", \"type\": \"int32\", \"default\": 8 }\n    ]\n  },\n  {\n    \"name\": \"DctChannelSelect\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"fastImpl\", \"type\": \"DctChannelSelectV0FastImpl\", \"default\": \"NONE\" },\n      { \"name\": \"dct_block_size\", \"type\": \"int32\", \"default\": 8 }\n    ]\n  },\n  {\n    \"name\": \"MatrixMulV0\",\n    \"attributes\": [\n      { \"name\": \"transposeA\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"transposeB\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"data_type\", \"type\": \"MatrixMulV0DataType\", \"default\": \"FLOAT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"MatrixMulV1\",\n    \"attributes\": [\n      { \"name\": \"transposeA\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"transposeB\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"compute_mode\", \"type\": \"MatrixMulV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"MatrixMulV2\",\n    \"attributes\": [\n      { \"name\": \"transposeA\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"transposeB\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"compute_mode\", \"type\": \"MatrixMulV1ComputeMode\", \"default\": \"DEFAULT\" },\n      { \"name\": \"format\", \"type\": \"MatrixMulFormat\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"MatrixMul\",\n    \"attributes\": [\n      { \"name\": \"transposeA\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"transposeB\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"compute_mode\", \"type\": \"MatrixMulV1ComputeMode\", \"default\": \"DEFAULT\" },\n      { \"name\": \"format\", \"type\": \"MatrixMulFormat\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"SVD\",\n    \"attributes\": [\n      { \"name\": \"full_matrices\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"compute_uv\", \"type\": \"bool\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"ReduceV0\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ReduceV0Mode\", \"default\": \"SUM\" },\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": -1 }\n    ]\n  },\n  {\n    \"name\": \"ReduceV1\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ReduceV1Mode\", \"default\": \"SUM\" },\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": -1 },\n      { \"name\": \"data_type\", \"type\": \"ReduceV1DataType\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"Reduce\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ReduceMode\", \"default\": \"SUM\" },\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 2147483647 },\n      { \"name\": \"data_type\", \"type\": \"ReduceDataType\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"CumsumV0\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": -1 },\n      { \"name\": \"exclusive\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"reverse\", \"type\": \"bool\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Cumsum\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 2147483647 },\n      { \"name\": \"exclusive\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"reverse\", \"type\": \"bool\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"CondTake\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CondTakeMode\", \"default\": \"EQ\" },\n      { \"name\": \"val\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.000001 }\n    ]\n  },\n  {\n    \"name\": \"Argsort\",\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"ArgsortOrder\", \"default\": \"ASCENDING\" }\n    ]\n  },\n  {\n    \"name\": \"IndexingRemap\",\n    \"attributes\": [\n      { \"name\": \"is_non_overlapping\", \"type\": \"bool\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Sleep\",\n    \"attributes\": [\n      { \"name\": \"time\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Linspace\",\n    \"attributes\": [\n      { \"name\": \"endpoint\", \"type\": \"bool\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"LinspaceFull\",\n    \"attributes\": [\n      { \"name\": \"start\", \"type\": \"float64\", \"default\": 0 },\n      { \"name\": \"stop\", \"type\": \"float64\", \"default\": 1 },\n      { \"name\": \"endpoint\", \"type\": \"bool\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"Eye\",\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dtype\", \"type\": \"DTypeEnum\", \"default\": \"Float32\" }\n    ]\n  },\n  {\n    \"name\": \"Diag\",\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"UniformRNGV0\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"UniformRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 },\n      { \"name\": \"dtype\", \"type\": \"DTypeEnum\", \"default\": \"Float32\" }\n    ]\n  },\n  {\n    \"name\": \"GaussianRNGV0\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 },\n      { \"name\": \"mean\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"std\", \"type\": \"float32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"GaussianRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 },\n      { \"name\": \"mean\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"std\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"dtype\", \"type\": \"DTypeEnum\", \"default\": \"Float32\" }\n    ]\n  },\n  {\n    \"name\": \"GammaRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"BetaRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"PoissonRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"PermutationRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 },\n      { \"name\": \"dtype\", \"type\": \"DTypeEnum\", \"default\": \"Int32\" }\n    ]\n  },\n  {\n    \"name\": \"ShuffleRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Flip\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"vertical\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"horizontal\", \"type\": \"bool\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Rotate\",\n    \"attributes\": [\n      { \"name\": \"clockwise\", \"type\": \"bool\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"ROICopy\",\n    \"attributes\": [\n      { \"name\": \"row_from\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"row_to\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"col_from\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"col_to\", \"type\": \"uint32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"CvtColor\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CvtColorMode\", \"default\": \"RGB2GRAY\" }\n    ]\n  },\n  {\n    \"name\": \"WarpAffineV0\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"border_mode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"border_val\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"WarpAffineV1\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"border_mode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"border_val\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NHWC\" }\n    ]\n  },\n  {\n    \"name\": \"WarpAffine\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"border_mode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"border_val\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NHWC\" }\n    ]\n  },\n  {\n    \"name\": \"GaussianBlur\",\n    \"attributes\": [\n      { \"name\": \"border_mode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"kernel_height\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"kernel_width\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"sigma_x\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"sigma_y\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ResizeV0\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeV1\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NHWC\" }\n    ]\n  },\n  {\n    \"name\": \"Resize\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NHWC\" }\n    ]\n  },\n  {\n    \"name\": \"RemapV0\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"border_type\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NHWC\" },\n      { \"name\": \"scalar\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Remap\",\n    \"attributes\": [\n      { \"name\": \"imode\", \"type\": \"WarpPerspectiveV1InterpolationMode\", \"default\": \"LINEAR\" },\n      { \"name\": \"border_type\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NHWC\" },\n      { \"name\": \"scalar\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Convolution3D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"Convolution3DMode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_d\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_d\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_d\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"Convolution3DSparse\", \"default\": \"DENSE\" },\n      { \"name\": \"data_type\", \"type\": \"Convolution3DDataType\", \"default\": \"FLOAT\" },\n      { \"name\": \"format\", \"type\": \"Convolution3DFormat\", \"default\": \"NCDHW\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"Conv3DBias\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"Conv3DBiasNonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"Convolution3DMode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_d\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_d\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"SeparableConv3D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"Convolution3DMode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"borderMode\", \"type\": \"SeparableConv3DBorderMode\", \"default\": \"BORDER_REPLICATE\" },\n      { \"name\": \"is_symm_kernel\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"pad_d\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_d\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"ksize_d\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"ksize_h\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"ksize_w\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"anchor_d\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"anchor_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"anchor_w\", \"type\": \"uint32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"TopK\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"TopKMode\", \"default\": \"KTH_ONLY\" }\n    ]\n  },\n  {\n    \"name\": \"RelayoutFormatV0\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"RelayoutFormatV0Mode\", \"default\": \"NHWC_NHWCD4\" }\n    ]\n  },\n  {\n    \"name\": \"RelayoutFormat\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"RelayoutFormatV0Mode\", \"default\": \"NHWC_NHWCD4\" },\n      { \"name\": \"oc\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"uint32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"SeparableFilterV0\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"borderMode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"is_symm_kernel\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"ksize_h\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"ksize_w\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"anchor_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"anchor_w\", \"type\": \"uint32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"SeparableFilter\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"borderMode\", \"type\": \"WarpPerspectiveV1BorderMode\", \"default\": \"REPLICATE\" },\n      { \"name\": \"is_symm_kernel\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"ksize_h\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"ksize_w\", \"type\": \"uint32\", \"default\": 3 },\n      { \"name\": \"anchor_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"anchor_w\", \"type\": \"uint32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"LocalShareV0\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"spatial_groups_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"spatial_groups_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"computeMode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"LocalShare\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"spatial_groups_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"spatial_groups_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"computeMode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ]\n  },\n  {\n    \"name\": \"ROIAlignV0\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ROIAlignV0Mode\", \"default\": \"MAX_\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"spatial_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"offset\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"pooled_height\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pooled_width\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sample_height\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"sample_width\", \"type\": \"uint32\", \"default\": 2 }\n    ]\n  },\n  {\n    \"name\": \"ROIAlign\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"ROIAlignV0Mode\", \"default\": \"MAX_\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"spatial_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"offset\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"pooled_height\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pooled_width\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sample_height\", \"type\": \"uint32\", \"default\": 2 },\n      { \"name\": \"sample_width\", \"type\": \"uint32\", \"default\": 2 }\n    ]\n  },\n  {\n    \"name\": \"Correlation\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"max_displacement\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride1\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride2\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pad_size\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"is_multiply\", \"type\": \"bool\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"DeformablePSROIPooling\",\n    \"attributes\": [\n      { \"name\": \"no_trans\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"spatial_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"trans_std\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"pooled_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"pooled_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"part_size\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sample_per_part\", \"type\": \"uint32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"BatchConvBiasV0\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionV0Format\", \"default\": \"NCHW\" },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"BatchConvBias\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"ConvBiasV0NonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"mode\", \"type\": \"ConvolutionV0Mode\", \"default\": \"CROSS_CORRELATION\" },\n      { \"name\": \"pad_h\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"pad_w\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_h\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"dilate_w\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"sparse\", \"type\": \"ConvolutionV0Sparse\", \"default\": \"DENSE\" },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" },\n      { \"name\": \"compute_mode\", \"type\": \"ConvolutionV1ComputeMode\", \"default\": \"DEFAULT\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuant\",\n    \"attributes\": [\n      { \"name\": \"qmin\", \"type\": \"int32\", \"default\": -2147483648 },\n      { \"name\": \"qmax\", \"type\": \"int32\", \"default\": 2147483647 }\n    ]\n  },\n  {\n    \"name\": \"TQT\",\n    \"category\": \"Quantization\",\n    \"attributes\": [\n      { \"name\": \"qmin\", \"type\": \"int32\", \"default\": -2147483648 },\n      { \"name\": \"qmax\", \"type\": \"int32\", \"default\": 2147483647 }\n    ]\n  },\n  {\n    \"name\": \"LSQ\",\n    \"category\": \"Quantization\",\n    \"attributes\": [\n      { \"name\": \"qmin\", \"type\": \"int32\", \"default\": -2147483648 },\n      { \"name\": \"qmax\", \"type\": \"int32\", \"default\": 2147483647 }\n    ]\n  },\n  {\n    \"name\": \"Fill\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"CheckNonFinite\",\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"Padding\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"front_offset_dim0\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"front_offset_dim1\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"front_offset_dim2\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"front_offset_dim3\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"front_offset_dim4\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"front_offset_dim5\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"front_offset_dim6\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim0\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim1\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim2\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim3\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim4\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim5\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"back_offset_dim6\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"padding_val\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"padding_mode\", \"type\": \"PaddingPaddingMode\", \"default\": \"CONSTANT\" }\n    ]\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"affine\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"normalized_dim\", \"type\": \"uint64\", \"default\": 1 },\n      { \"name\": \"normalized_size\", \"type\": \"uint64\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"drop_prob\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"RNNCell\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"nonlineMode\", \"type\": \"RNNCellNonlineMode\", \"default\": \"IDENTITY\" }\n    ]\n  },\n  {\n    \"name\": \"RNN\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_layers\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"bidirectional\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"bias\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"hidden_size\", \"type\": \"uint32\", \"default\": 128 },\n      { \"name\": \"dropout\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"nonlineMode\", \"type\": \"RNNCellNonlineMode\", \"default\": \"IDENTITY\" },\n      { \"name\": \"fwd_mode\", \"type\": \"BNFwdMode\", \"default\": \"TRAINING\" }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_layers\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"bidirectional\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"bias\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"hidden_size\", \"type\": \"uint32\", \"default\": 128 },\n      { \"name\": \"proj_size\", \"type\": \"uint32\", \"default\": 0 },\n      { \"name\": \"dropout\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"fwd_mode\", \"type\": \"BNFwdMode\", \"default\": \"TRAINING\" }\n    ]\n  },\n  {\n    \"name\": \"DType\",\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"DTypeEnum\", \"default\": \"Byte\" }\n    ]\n  },\n  {\n    \"name\": \"PersistentOutputStorage\",\n    \"attributes\": [\n      { \"name\": \"share_key\", \"type\": \"int32\", \"default\": -1 }\n    ]\n  },\n  {\n    \"name\": \"OptionalAxis\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": -1 }\n    ]\n  },\n  {\n    \"name\": \"OptionalAxisV1\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 7 }\n    ]\n  },\n  {\n    \"name\": \"ExecutionPolicyV0\",\n    \"attributes\": [\n      { \"name\": \"strategy\", \"type\": \"ExecutionPolicyV0Strategy\", \"default\": \"HEURISTIC\" },\n      { \"name\": \"workspace_limit\", \"type\": \"uint64\", \"default\": 18446744073709552000 }\n    ]\n  },\n  {\n    \"name\": \"ExecutionPolicy\",\n    \"attributes\": [\n      { \"name\": \"strategy\", \"type\": \"ExecutionPolicyStrategy\", \"default\": \"PROFILE\" },\n      { \"name\": \"workspace_limit\", \"type\": \"uint64\", \"default\": 18446744073709552000 }\n    ]\n  },\n  {\n    \"name\": \"AssertEqual\",\n    \"attributes\": [\n      { \"name\": \"maxerr\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"verbose\", \"type\": \"bool\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"FpgaConv\",\n    \"attributes\": [\n      { \"name\": \"need_output_quantize\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"need_output_threshold\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"stride\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"input_bit_width\", \"type\": \"int32\", \"default\": 2 },\n      { \"name\": \"output_bit_width\", \"type\": \"int32\", \"default\": 2 },\n      { \"name\": \"weight_bit_width\", \"type\": \"int32\", \"default\": 2 },\n      { \"name\": \"thres0\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"thres1\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"unpool_size\", \"type\": \"uint32\", \"default\": 4 },\n      { \"name\": \"direct_size\", \"type\": \"uint32\", \"default\": 4 }\n    ]\n  },\n  {\n    \"name\": \"CollectiveComm\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CollectiveCommMode\", \"default\": \"REDUCE_SUM\" }\n    ]\n  },\n  {\n    \"name\": \"CondExecPred\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CondExecPredMode\", \"default\": \"CASE\" },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.0001 }\n    ]\n  },\n  {\n    \"name\": \"CondExecPredLogical\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CondExecPredLogicalMode\", \"default\": \"OR\" }\n    ]\n  },\n  {\n    \"name\": \"CondExecMark\",\n    \"attributes\": [\n      { \"name\": \"grad_mode\", \"type\": \"CondExecMarkGradMode\", \"default\": \"SUM\" },\n      { \"name\": \"static_infer\", \"type\": \"CondExecMarkStaticInfer\", \"default\": \"SHAPE_VALUE\" }\n    ]\n  },\n  {\n    \"name\": \"CondExecMerge\",\n    \"attributes\": [\n      { \"name\": \"nr_output\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"mode\", \"type\": \"CondExecMergeMode\", \"default\": \"EXACT_ONE\" }\n    ]\n  },\n  {\n    \"name\": \"NvOf\",\n    \"attributes\": [\n      { \"name\": \"precision\", \"type\": \"uint32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"PersistentDTypeScalar\",\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"DTypeEnum\", \"default\": \"Float32\" },\n      { \"name\": \"storage\", \"type\": \"uint8[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"MGBAddUpdate\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"PersistentDTypeScalar\" },\n      { \"name\": \"beta\", \"type\": \"PersistentDTypeScalar\" },\n      { \"name\": \"bias\", \"type\": \"PersistentDTypeScalar\" }\n    ]\n  },\n  {\n    \"name\": \"Host2DeviceCopy\",\n    \"category\": \"Data\",\n    \"attributes\": [\n      { \"name\": \"enable_value_infer\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"dump_default_value\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"allow_cpu_mem_fwd\", \"type\": \"bool\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"Dimshuffle\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"int32[]\", \"default\": 0 },\n      { \"name\": \"ndim\", \"type\": \"uint32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"AxisDesc\",\n    \"attributes\": [\n      { \"name\": \"method\", \"type\": \"AxisDescMethod\", \"default\": \"ADD_1\" },\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"AxisAddRemove\",\n    \"attributes\": [\n      { \"name\": \"desc\", \"type\": \"AxisDesc[]\" }\n    ]\n  },\n  {\n    \"name\": \"MGBSleep\",\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"host\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"seconds\", \"type\": \"float64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"IndexDescMaskItem\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int8\", \"default\": 0 },\n      { \"name\": \"begin\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"end\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"step\", \"type\": \"bool\", \"default\": false },\n      { \"name\": \"idx\", \"type\": \"bool\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"IndexDescMaskDump\",\n    \"attributes\": [\n      { \"name\": \"items\", \"type\": \"IndexDescMaskItem[]\" }\n    ]\n  },\n  {\n    \"name\": \"NMSKeep\",\n    \"attributes\": [\n      { \"name\": \"iou_thresh\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"max_output\", \"type\": \"uint32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"BatchNormForward\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"ConvolutionForward\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"ConvBiasForward\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"biases\" }\n    ]\n  },\n  {\n    \"name\": \"PoolingForward\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"AdaptivePoolingForward\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Subtensor\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"GetVarShape\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"GetVarShapeV1\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"ReshapeV1\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"tensor\" },\n      { \"name\": \"target_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"tensor\" },\n      { \"name\": \"target_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"tensor\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"GroupNorm\",\n    \"attributes\": [\n      { \"name\": \"affine\", \"type\": \"bool\", \"default\": true },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"group\", \"type\": \"uint32\", \"default\": 1 },\n      { \"name\": \"format\", \"type\": \"ConvolutionFormat\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"MultinomialRNG\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"uint64\", \"default\": 0 },\n      { \"name\": \"num_samples\", \"type\": \"uint64\", \"default\": 1 },\n      { \"name\": \"replacement\", \"type\": \"bool\", \"default\": false }\n    ]\n  }\n]"
  },
  {
    "path": "source/megengine-schema.js",
    "content": "\nexport const mgb = {};\n\nmgb.serialization = mgb.serialization || {};\n\nmgb.serialization.fbs = mgb.serialization.fbs || {};\n\nmgb.serialization.fbs.DTypeEnum = {\n    Float32: 0, '0': 'Float32',\n    Uint8: 1, '1': 'Uint8',\n    Int8: 2, '2': 'Int8',\n    Int16: 3, '3': 'Int16',\n    Int32: 4, '4': 'Int32',\n    IntB1: 5, '5': 'IntB1',\n    IntB2: 6, '6': 'IntB2',\n    IntB4: 7, '7': 'IntB4',\n    Byte: 8, '8': 'Byte',\n    Float16: 9, '9': 'Float16',\n    UintB4: 10, '10': 'UintB4',\n    Quantized8Asymm: 11, '11': 'Quantized8Asymm',\n    QuantizedS32: 12, '12': 'QuantizedS32',\n    QuantizedS8: 13, '13': 'QuantizedS8',\n    Quantized4Asymm: 14, '14': 'Quantized4Asymm',\n    QuantizedS4: 15, '15': 'QuantizedS4',\n    QuantizedS16: 16, '16': 'QuantizedS16',\n    BFloat16: 17, '17': 'BFloat16',\n    Bool: 18, '18': 'Bool',\n    Uint16: 19, '19': 'Uint16',\n    QuantizedS1: 20, '20': 'QuantizedS1'\n};\n\nmgb.serialization.fbs.LinearQuantizationParam = class LinearQuantizationParam {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.LinearQuantizationParam();\n        $.scale = reader.float32_(position, 4, 0);\n        $.zero_point = reader.uint8_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.DTypeParam = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return mgb.serialization.fbs.LinearQuantizationParam.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nmgb.serialization.fbs.DType = class DType {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.DType();\n        $.type = reader.int8_(position, 4, 0);\n        $.param = reader.union(position, 6, mgb.serialization.fbs.DTypeParam);\n        return $;\n    }\n};\n\nmgb.serialization = mgb.serialization || {};\n\nmgb.serialization.fbs = mgb.serialization.fbs || {};\n\nmgb.serialization.fbs.param = mgb.serialization.fbs.param || {};\n\nmgb.serialization.fbs.param.ArgsortOrder = {\n    ASCENDING: 0, '0': 'ASCENDING',\n    DESCENDING: 1, '1': 'DESCENDING'\n};\n\nmgb.serialization.fbs.param.BNFwdMode = {\n    TRAINING: 0, '0': 'TRAINING',\n    INFERENCE: 1, '1': 'INFERENCE'\n};\n\nmgb.serialization.fbs.param.BNParamDim = {\n    DIM_11HW: 0, '0': 'DIM_11HW',\n    DIM_1CHW: 1, '1': 'DIM_1CHW',\n    DIM_1C11: 2, '2': 'DIM_1C11',\n    DIM_111C: 3, '3': 'DIM_111C'\n};\n\nmgb.serialization.fbs.param.CondTakeMode = {\n    EQ: 0, '0': 'EQ',\n    NEQ: 1, '1': 'NEQ',\n    LT: 2, '2': 'LT',\n    LEQ: 3, '3': 'LEQ',\n    GT: 4, '4': 'GT',\n    GEQ: 5, '5': 'GEQ'\n};\n\nmgb.serialization.fbs.param.Conv3DBiasNonlineMode = {\n    IDENTITY: 0, '0': 'IDENTITY',\n    RELU: 1, '1': 'RELU',\n    SIGMOID: 2, '2': 'SIGMOID'\n};\n\nmgb.serialization.fbs.param.ConvBiasV0NonlineMode = {\n    IDENTITY: 0, '0': 'IDENTITY',\n    RELU: 1, '1': 'RELU',\n    SIGMOID: 2, '2': 'SIGMOID',\n    H_SWISH: 3, '3': 'H_SWISH'\n};\n\nmgb.serialization.fbs.param.ConvPoolingMethod = {\n    WITH_TEXTURE_OBJ: 0, '0': 'WITH_TEXTURE_OBJ',\n    WITH_SHARED_MEM: 1, '1': 'WITH_SHARED_MEM'\n};\n\nmgb.serialization.fbs.param.ConvPoolingNonlineMode = {\n    IDENTITY: 0, '0': 'IDENTITY',\n    RELU: 1, '1': 'RELU',\n    SIGMOID: 2, '2': 'SIGMOID'\n};\n\nmgb.serialization.fbs.param.ConvPoolingPoolMode = {\n    AVERAGE: 0, '0': 'AVERAGE',\n    MAX_: 1, '1': 'MAX_'\n};\n\nmgb.serialization.fbs.param.ConvolutionFormat = {\n    NCHW: 0, '0': 'NCHW',\n    NHWC: 1, '1': 'NHWC',\n    NHWCD4: 2, '2': 'NHWCD4',\n    NCHW4: 3, '3': 'NCHW4',\n    NCHW8: 4, '4': 'NCHW8',\n    NCHW32: 5, '5': 'NCHW32',\n    NCHW88: 6, '6': 'NCHW88',\n    NCHW44: 7, '7': 'NCHW44',\n    NCHW44_DOT: 8, '8': 'NCHW44_DOT',\n    NCHW4_NCHW32: 9, '9': 'NCHW4_NCHW32',\n    NCHW32_NCHW4: 10, '10': 'NCHW32_NCHW4',\n    NCHW4_NCHW: 11, '11': 'NCHW4_NCHW',\n    NHWC_NCHW: 12, '12': 'NHWC_NCHW',\n    NHWC_NCHW4_IC_SMALL: 13, '13': 'NHWC_NCHW4_IC_SMALL',\n    NCHW_NCHW4_IC_SMALL: 14, '14': 'NCHW_NCHW4_IC_SMALL',\n    CHWN4: 15, '15': 'CHWN4',\n    NCHW64: 16, '16': 'NCHW64',\n    NCHW4_NHWC: 17, '17': 'NCHW4_NHWC'\n};\n\nmgb.serialization.fbs.param.Convolution3DDataType = {\n    FLOAT: 0, '0': 'FLOAT',\n    FLOAT_IO16xC32: 1, '1': 'FLOAT_IO16xC32'\n};\n\nmgb.serialization.fbs.param.Convolution3DFormat = {\n    NCDHW: 0, '0': 'NCDHW',\n    NDHWC: 1, '1': 'NDHWC'\n};\n\nmgb.serialization.fbs.param.Convolution3DMode = {\n    CROSS_CORRELATION: 0, '0': 'CROSS_CORRELATION',\n    CONVOLUTION: 1, '1': 'CONVOLUTION'\n};\n\nmgb.serialization.fbs.param.Convolution3DSparse = {\n    DENSE: 0, '0': 'DENSE',\n    GROUP: 1, '1': 'GROUP'\n};\n\nmgb.serialization.fbs.param.ConvolutionV0DataType = {\n    FLOAT: 0, '0': 'FLOAT',\n    INT8x8x16: 1, '1': 'INT8x8x16',\n    INT8x8x32: 2, '2': 'INT8x8x32',\n    FLOAT_IO16xC32: 3, '3': 'FLOAT_IO16xC32',\n    QUINT8x8x32: 4, '4': 'QUINT8x8x32',\n    INT8x8xX: 5, '5': 'INT8x8xX',\n    QUINT4x4x32: 6, '6': 'QUINT4x4x32'\n};\n\nmgb.serialization.fbs.param.ConvolutionV0Format = {\n    NCHW: 0, '0': 'NCHW',\n    NHWC: 1, '1': 'NHWC',\n    NHWCD4: 2, '2': 'NHWCD4',\n    NCHW4: 3, '3': 'NCHW4',\n    NCHW8: 4, '4': 'NCHW8',\n    NCHW32: 5, '5': 'NCHW32',\n    NCHW88: 6, '6': 'NCHW88',\n    NCHW44: 7, '7': 'NCHW44',\n    NCHW44_DOT: 8, '8': 'NCHW44_DOT',\n    NCHW_WINOGRAD: 9, '9': 'NCHW_WINOGRAD',\n    NCHW88_WINOGRAD: 10, '10': 'NCHW88_WINOGRAD',\n    NCHW44_WINOGRAD: 11, '11': 'NCHW44_WINOGRAD',\n    NCHW4_NCHW32: 12, '12': 'NCHW4_NCHW32',\n    NCHW32_NCHW4: 13, '13': 'NCHW32_NCHW4',\n    NCHW4_NCHW: 14, '14': 'NCHW4_NCHW',\n    NHWC_NCHW: 15, '15': 'NHWC_NCHW',\n    NHWC_NCHW4_IC_SMALL: 16, '16': 'NHWC_NCHW4_IC_SMALL',\n    NCHW_NCHW4_IC_SMALL: 17, '17': 'NCHW_NCHW4_IC_SMALL',\n    CHWN4: 18, '18': 'CHWN4',\n    NCHW4_NHWC: 19, '19': 'NCHW4_NHWC'\n};\n\nmgb.serialization.fbs.param.ConvolutionV0Mode = {\n    CROSS_CORRELATION: 0, '0': 'CROSS_CORRELATION',\n    CONVOLUTION: 1, '1': 'CONVOLUTION'\n};\n\nmgb.serialization.fbs.param.ConvolutionV0Sparse = {\n    DENSE: 0, '0': 'DENSE',\n    GROUP: 1, '1': 'GROUP'\n};\n\nmgb.serialization.fbs.param.ConvolutionV1ComputeMode = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    FLOAT32: 1, '1': 'FLOAT32'\n};\n\nmgb.serialization.fbs.param.CvtColorMode = {\n    RGB2GRAY: 0, '0': 'RGB2GRAY',\n    RGB2YUV: 1, '1': 'RGB2YUV',\n    YUV2RGB: 2, '2': 'YUV2RGB',\n    GRAY2RGB: 3, '3': 'GRAY2RGB',\n    RGBA2RGB: 4, '4': 'RGBA2RGB',\n    RGBA2BGR: 5, '5': 'RGBA2BGR',\n    RGBA2GRAY: 6, '6': 'RGBA2GRAY',\n    RGB2BGR: 7, '7': 'RGB2BGR',\n    BGR2GRAY: 8, '8': 'BGR2GRAY',\n    BGR2RGB: 9, '9': 'BGR2RGB',\n    YUV2GRAY_NV21: 10, '10': 'YUV2GRAY_NV21',\n    YUV2RGB_NV21: 11, '11': 'YUV2RGB_NV21',\n    YUV2BGR_NV21: 12, '12': 'YUV2BGR_NV21',\n    YUV2GRAY_NV12: 13, '13': 'YUV2GRAY_NV12',\n    YUV2RGB_NV12: 14, '14': 'YUV2RGB_NV12',\n    YUV2BGR_NV12: 15, '15': 'YUV2BGR_NV12',\n    YUV2GRAY_YV12: 16, '16': 'YUV2GRAY_YV12',\n    YUV2RGB_YV12: 17, '17': 'YUV2RGB_YV12',\n    YUV2BGR_YV12: 18, '18': 'YUV2BGR_YV12',\n    YUV2GRAY_YU12: 19, '19': 'YUV2GRAY_YU12',\n    YUV2RGB_YU12: 20, '20': 'YUV2RGB_YU12',\n    YUV2BGR_YU12: 21, '21': 'YUV2BGR_YU12',\n    YCrCb2RGB: 22, '22': 'YCrCb2RGB',\n    YCrCb2BGR: 23, '23': 'YCrCb2BGR',\n    BT601_YUV2RGB_NV21: 24, '24': 'BT601_YUV2RGB_NV21',\n    BT601_YUV2BGR_NV21: 25, '25': 'BT601_YUV2BGR_NV21',\n    BT601_YUV2RGB_NV12: 26, '26': 'BT601_YUV2RGB_NV12',\n    BT601_YUV2BGR_NV12: 27, '27': 'BT601_YUV2BGR_NV12',\n    BT601_YUV2RGB_YV12: 28, '28': 'BT601_YUV2RGB_YV12',\n    BT601_YUV2BGR_YV12: 29, '29': 'BT601_YUV2BGR_YV12',\n    BT601_YUV2RGB_YU12: 30, '30': 'BT601_YUV2RGB_YU12',\n    BT601_YUV2BGR_YU12: 31, '31': 'BT601_YUV2BGR_YU12'\n};\n\nmgb.serialization.fbs.param.DctChannelSelectV0FastImpl = {\n    NONE: 0, '0': 'NONE',\n    FIX_32_MASK: 1, '1': 'FIX_32_MASK'\n};\n\nmgb.serialization.fbs.param.ElemwiseMode = {\n    RELU: 0, '0': 'RELU',\n    ABS: 1, '1': 'ABS',\n    ACOS: 2, '2': 'ACOS',\n    ASIN: 3, '3': 'ASIN',\n    CEIL: 4, '4': 'CEIL',\n    COS: 5, '5': 'COS',\n    EXP: 6, '6': 'EXP',\n    EXPM1: 7, '7': 'EXPM1',\n    FLOOR: 8, '8': 'FLOOR',\n    LOG: 9, '9': 'LOG',\n    LOG1P: 10, '10': 'LOG1P',\n    NEGATE: 11, '11': 'NEGATE',\n    SIGMOID: 12, '12': 'SIGMOID',\n    SIN: 13, '13': 'SIN',\n    TANH: 14, '14': 'TANH',\n    ABS_GRAD: 15, '15': 'ABS_GRAD',\n    ADD: 16, '16': 'ADD',\n    FLOOR_DIV: 17, '17': 'FLOOR_DIV',\n    MAX_: 18, '18': 'MAX_',\n    MIN_: 19, '19': 'MIN_',\n    MOD: 20, '20': 'MOD',\n    MUL: 21, '21': 'MUL',\n    POW: 22, '22': 'POW',\n    SIGMOID_GRAD: 23, '23': 'SIGMOID_GRAD',\n    SUB: 24, '24': 'SUB',\n    SWITCH_GT0: 25, '25': 'SWITCH_GT0',\n    TANH_GRAD: 26, '26': 'TANH_GRAD',\n    TRUE_DIV: 27, '27': 'TRUE_DIV',\n    LOG_SUM_EXP: 28, '28': 'LOG_SUM_EXP',\n    LT: 29, '29': 'LT',\n    LEQ: 30, '30': 'LEQ',\n    EQ: 31, '31': 'EQ',\n    SHL: 32, '32': 'SHL',\n    SHR: 33, '33': 'SHR',\n    COND_LEQ_MOV: 34, '34': 'COND_LEQ_MOV',\n    FUSE_MUL_ADD3: 35, '35': 'FUSE_MUL_ADD3',\n    FUSE_MUL_ADD4: 36, '36': 'FUSE_MUL_ADD4',\n    FUSE_ADD_RELU: 37, '37': 'FUSE_ADD_RELU',\n    FUSE_ADD_SIGMOID: 38, '38': 'FUSE_ADD_SIGMOID',\n    FUSE_ADD_TANH: 39, '39': 'FUSE_ADD_TANH',\n    FAST_TANH: 40, '40': 'FAST_TANH',\n    FAST_TANH_GRAD: 41, '41': 'FAST_TANH_GRAD',\n    ROUND: 42, '42': 'ROUND',\n    RMULH: 43, '43': 'RMULH',\n    ATAN2: 44, '44': 'ATAN2',\n    ERF: 45, '45': 'ERF',\n    ERFINV: 46, '46': 'ERFINV',\n    ERFC: 47, '47': 'ERFC',\n    ERFCINV: 48, '48': 'ERFCINV',\n    H_SWISH: 49, '49': 'H_SWISH',\n    H_SWISH_GRAD: 50, '50': 'H_SWISH_GRAD',\n    FUSE_ADD_H_SWISH: 51, '51': 'FUSE_ADD_H_SWISH',\n    NOT: 52, '52': 'NOT',\n    AND: 53, '53': 'AND',\n    OR: 54, '54': 'OR',\n    XOR: 55, '55': 'XOR',\n    SILU: 56, '56': 'SILU',\n    SILU_GRAD: 57, '57': 'SILU_GRAD',\n    GELU: 58, '58': 'GELU',\n    GELU_GRAD: 59, '59': 'GELU_GRAD'\n};\n\nmgb.serialization.fbs.param.ElemwiseMultiTypeMode = {\n    FUSE_MUL_ADD3_INT16x32x32x32: 0, '0': 'FUSE_MUL_ADD3_INT16x32x32x32',\n    FUSE_MUL_ADD3_IXxF32xF32xI8: 1, '1': 'FUSE_MUL_ADD3_IXxF32xF32xI8',\n    ROUND_SHR_SATURATE_IXxI8xI8: 2, '2': 'ROUND_SHR_SATURATE_IXxI8xI8',\n    FUSE_ADD_RMULH_ROUND_SHR_SATURATE_INT16x16x16x8: 3, '3': 'FUSE_ADD_RMULH_ROUND_SHR_SATURATE_INT16x16x16x8',\n    FUSE_ADD_RMULH_ROUND_SHR_SATURATE_INT32x32x32x8: 4, '4': 'FUSE_ADD_RMULH_ROUND_SHR_SATURATE_INT32x32x32x8',\n    ROUND_SHR_SATURATE_IXxI8xI16: 5, '5': 'ROUND_SHR_SATURATE_IXxI8xI16',\n    QADD: 6, '6': 'QADD',\n    QFUSE_ADD_RELU: 7, '7': 'QFUSE_ADD_RELU',\n    QMUL: 8, '8': 'QMUL',\n    QMIN: 9, '9': 'QMIN',\n    QMAX: 10, '10': 'QMAX',\n    QSUB: 11, '11': 'QSUB',\n    QTRUE_DIV: 12, '12': 'QTRUE_DIV',\n    QFUSE_ADD_SIGMOID: 13, '13': 'QFUSE_ADD_SIGMOID',\n    QFUSE_ADD_TANH: 14, '14': 'QFUSE_ADD_TANH',\n    QRELU: 15, '15': 'QRELU',\n    QABS: 16, '16': 'QABS',\n    QSIGMOID: 17, '17': 'QSIGMOID',\n    QEXP: 18, '18': 'QEXP',\n    QTANH: 19, '19': 'QTANH',\n    QFUSE_MUL_ADD3: 20, '20': 'QFUSE_MUL_ADD3',\n    QFAST_TANH: 21, '21': 'QFAST_TANH',\n    QNEGATE: 22, '22': 'QNEGATE',\n    QACOS: 23, '23': 'QACOS',\n    QASIN: 24, '24': 'QASIN',\n    QCEIL: 25, '25': 'QCEIL',\n    QCOS: 26, '26': 'QCOS',\n    QEXPM1: 27, '27': 'QEXPM1',\n    QFLOOR: 28, '28': 'QFLOOR',\n    QLOG: 29, '29': 'QLOG',\n    QLOG1P: 30, '30': 'QLOG1P',\n    QSIN: 31, '31': 'QSIN',\n    QROUND: 32, '32': 'QROUND',\n    QERF: 33, '33': 'QERF',\n    QERFINV: 34, '34': 'QERFINV',\n    QERFC: 35, '35': 'QERFC',\n    QERFCINV: 36, '36': 'QERFCINV',\n    QABS_GRAD: 37, '37': 'QABS_GRAD',\n    QFLOOR_DIV: 38, '38': 'QFLOOR_DIV',\n    QMOD: 39, '39': 'QMOD',\n    QSIGMOID_GRAD: 40, '40': 'QSIGMOID_GRAD',\n    QSWITCH_GT0: 41, '41': 'QSWITCH_GT0',\n    QTANH_GRAD: 42, '42': 'QTANH_GRAD',\n    QLT: 43, '43': 'QLT',\n    QLEQ: 44, '44': 'QLEQ',\n    QEQ: 45, '45': 'QEQ',\n    QPOW: 46, '46': 'QPOW',\n    QLOG_SUM_EXP: 47, '47': 'QLOG_SUM_EXP',\n    QFAST_TANH_GRAD: 48, '48': 'QFAST_TANH_GRAD',\n    QATAN2: 49, '49': 'QATAN2',\n    QCOND_LEQ_MOV: 50, '50': 'QCOND_LEQ_MOV',\n    QH_SWISH: 51, '51': 'QH_SWISH',\n    QFUSE_ADD_H_SWISH: 52, '52': 'QFUSE_ADD_H_SWISH',\n    QH_SWISH_GRAD: 53, '53': 'QH_SWISH_GRAD',\n    FUSE_MUL_ADD3_INT16xF32xF32xF32: 54, '54': 'FUSE_MUL_ADD3_INT16xF32xF32xF32',\n    MUL_INT16xF32xF32: 55, '55': 'MUL_INT16xF32xF32',\n    FUSE_MUL_ADD3_UINT8xF32xF32xF32: 56, '56': 'FUSE_MUL_ADD3_UINT8xF32xF32xF32'\n};\n\nmgb.serialization.fbs.param.MatrixMulFormat = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    MK4: 1, '1': 'MK4',\n    MK8: 2, '2': 'MK8',\n    MK4_DOT: 3, '3': 'MK4_DOT'\n};\n\nmgb.serialization.fbs.param.MatrixMulV0DataType = {\n    FLOAT: 0, '0': 'FLOAT',\n    INT8x8x16: 1, '1': 'INT8x8x16',\n    INT8x8x32: 2, '2': 'INT8x8x32',\n    FLOAT_IO16xC32: 3, '3': 'FLOAT_IO16xC32',\n    QUINT8x8x32: 4, '4': 'QUINT8x8x32',\n    QUINT4x4x32: 5, '5': 'QUINT4x4x32'\n};\n\nmgb.serialization.fbs.param.MatrixMulV1ComputeMode = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    FLOAT32: 1, '1': 'FLOAT32'\n};\n\nmgb.serialization.fbs.param.PaddingPaddingMode = {\n    REPLICATE: 0, '0': 'REPLICATE',\n    REFLECT: 1, '1': 'REFLECT',\n    CONSTANT: 2, '2': 'CONSTANT'\n};\n\nmgb.serialization.fbs.param.PoolingV0Mode = {\n    MAX_: 0, '0': 'MAX_',\n    AVERAGE: 1, '1': 'AVERAGE',\n    AVERAGE_COUNT_EXCLUDE_PADDING: 2, '2': 'AVERAGE_COUNT_EXCLUDE_PADDING'\n};\n\nmgb.serialization.fbs.param.RNNCellNonlineMode = {\n    IDENTITY: 0, '0': 'IDENTITY',\n    RELU: 1, '1': 'RELU',\n    TANH: 2, '2': 'TANH'\n};\n\nmgb.serialization.fbs.param.ROIAlignV0Mode = {\n    MAX_: 0, '0': 'MAX_',\n    AVERAGE: 1, '1': 'AVERAGE'\n};\n\nmgb.serialization.fbs.param.ROIPoolingMode = {\n    MAX_: 0, '0': 'MAX_',\n    AVERAGE: 1, '1': 'AVERAGE'\n};\n\nmgb.serialization.fbs.param.ReduceDataType = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    FLOAT_IO16xC32: 1, '1': 'FLOAT_IO16xC32',\n    FLOAT_O32xC32: 2, '2': 'FLOAT_O32xC32',\n    FLOAT_O16xC32: 3, '3': 'FLOAT_O16xC32',\n    QUINT_I8xO32: 4, '4': 'QUINT_I8xO32',\n    QINT_I8xO32: 5, '5': 'QINT_I8xO32'\n};\n\nmgb.serialization.fbs.param.ReduceMode = {\n    SUM: 0, '0': 'SUM',\n    SUM_SQR: 1, '1': 'SUM_SQR',\n    PRODUCT: 2, '2': 'PRODUCT',\n    MIN_: 3, '3': 'MIN_',\n    MAX_: 4, '4': 'MAX_',\n    MEAN: 5, '5': 'MEAN'\n};\n\nmgb.serialization.fbs.param.ReduceV0Mode = {\n    SUM: 0, '0': 'SUM',\n    SUM_SQR: 1, '1': 'SUM_SQR',\n    PRODUCT: 2, '2': 'PRODUCT',\n    MIN_: 3, '3': 'MIN_',\n    MAX_: 4, '4': 'MAX_'\n};\n\nmgb.serialization.fbs.param.ReduceV1DataType = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    FLOAT_IO16xC32: 1, '1': 'FLOAT_IO16xC32',\n    FLOAT_O32xC32: 2, '2': 'FLOAT_O32xC32',\n    FLOAT_O16xC32: 3, '3': 'FLOAT_O16xC32',\n    QUINT_I8xO32: 4, '4': 'QUINT_I8xO32',\n    QINT_I8xO32: 5, '5': 'QINT_I8xO32'\n};\n\nmgb.serialization.fbs.param.ReduceV1Mode = {\n    SUM: 0, '0': 'SUM',\n    SUM_SQR: 1, '1': 'SUM_SQR',\n    PRODUCT: 2, '2': 'PRODUCT',\n    MIN_: 3, '3': 'MIN_',\n    MAX_: 4, '4': 'MAX_',\n    MEAN: 5, '5': 'MEAN'\n};\n\nmgb.serialization.fbs.param.RelayoutFormatV0Mode = {\n    NHWC_NHWCD4: 0, '0': 'NHWC_NHWCD4',\n    NHWCD4_NHWC: 1, '1': 'NHWCD4_NHWC',\n    NHWC_NHWCD4I: 2, '2': 'NHWC_NHWCD4I',\n    NCHW_NHWCD4: 3, '3': 'NCHW_NHWCD4',\n    NCHW_NHWCD4I: 4, '4': 'NCHW_NHWCD4I',\n    NHWCD4I_NCHW: 5, '5': 'NHWCD4I_NCHW',\n    NHWCD4_NCHW: 6, '6': 'NHWCD4_NCHW',\n    INTER_WEIGHT_DENSE: 7, '7': 'INTER_WEIGHT_DENSE',\n    INTER_WEIGHT_DENSEI: 8, '8': 'INTER_WEIGHT_DENSEI',\n    INTER_WEIGHT_GROUP: 9, '9': 'INTER_WEIGHT_GROUP',\n    INTER_WEIGHT_GROUPI: 10, '10': 'INTER_WEIGHT_GROUPI',\n    INTER_WEIGHT_CHAN: 11, '11': 'INTER_WEIGHT_CHAN',\n    INTER_WEIGHT_CHANI: 12, '12': 'INTER_WEIGHT_CHANI',\n    INTER_WEIGHT_DENSEI_DOT: 13, '13': 'INTER_WEIGHT_DENSEI_DOT',\n    INTER_WEIGHT_GROUPI_DOT: 14, '14': 'INTER_WEIGHT_GROUPI_DOT',\n    NCHW4_CHWN4: 15, '15': 'NCHW4_CHWN4',\n    CHWN4_NCHW4: 16, '16': 'CHWN4_NCHW4',\n    NCHW_NCHW88_CONV_DENSE_WEIGHT: 17, '17': 'NCHW_NCHW88_CONV_DENSE_WEIGHT',\n    NCHW_NCHW88_CONV_CHAN_WEIGHT: 18, '18': 'NCHW_NCHW88_CONV_CHAN_WEIGHT',\n    NCHW_NCHW88_CONV_GROUP_WEIGHT: 19, '19': 'NCHW_NCHW88_CONV_GROUP_WEIGHT',\n    NCHW_NCHW88: 20, '20': 'NCHW_NCHW88',\n    NCHW88_NCHW: 21, '21': 'NCHW88_NCHW',\n    NCHW_NCHW4_IC_SMALL: 22, '22': 'NCHW_NCHW4_IC_SMALL',\n    NCHW_NCHW4_IC_SMALL_CONV_DENSE_WEIGHT: 23, '23': 'NCHW_NCHW4_IC_SMALL_CONV_DENSE_WEIGHT',\n    NCHW_NCHW4: 24, '24': 'NCHW_NCHW4',\n    NCHW4_NCHW: 25, '25': 'NCHW4_NCHW',\n    NCHW_NCHW4_WEIGHT: 26, '26': 'NCHW_NCHW4_WEIGHT',\n    NCHW_NCHW64: 27, '27': 'NCHW_NCHW64',\n    NCHW64_NCHW: 28, '28': 'NCHW64_NCHW',\n    NCHW_NHWC: 29, '29': 'NCHW_NHWC',\n    NHWC_NCHW: 30, '30': 'NHWC_NCHW',\n    NHWCD4I_NHWC: 31, '31': 'NHWCD4I_NHWC'\n};\n\nmgb.serialization.fbs.param.SeparableConvBorderMode = {\n    BORDER_REPLICATE: 0, '0': 'BORDER_REPLICATE',\n    BORDER_REFLECT: 1, '1': 'BORDER_REFLECT',\n    BORDER_REFLECT_101: 2, '2': 'BORDER_REFLECT_101',\n    BORDER_WRAP: 3, '3': 'BORDER_WRAP',\n    BORDER_CONSTANT: 4, '4': 'BORDER_CONSTANT',\n    BORDER_TRANSPARENT: 5, '5': 'BORDER_TRANSPARENT',\n    BORDER_ISOLATED: 6, '6': 'BORDER_ISOLATED'\n};\n\nmgb.serialization.fbs.param.SeparableConv3DBorderMode = {\n    BORDER_REPLICATE: 0, '0': 'BORDER_REPLICATE',\n    BORDER_REFLECT: 1, '1': 'BORDER_REFLECT',\n    BORDER_REFLECT_101: 2, '2': 'BORDER_REFLECT_101',\n    BORDER_WRAP: 3, '3': 'BORDER_WRAP',\n    BORDER_CONSTANT: 4, '4': 'BORDER_CONSTANT',\n    BORDER_TRANSPARENT: 5, '5': 'BORDER_TRANSPARENT',\n    BORDER_ISOLATED: 6, '6': 'BORDER_ISOLATED'\n};\n\nmgb.serialization.fbs.param.SpatialTfGridGeneratorMode = {\n    AFFINE: 0, '0': 'AFFINE'\n};\n\nmgb.serialization.fbs.param.SpatialTfSamplerMode = {\n    BILINEAR: 0, '0': 'BILINEAR'\n};\n\nmgb.serialization.fbs.param.TopKMode = {\n    KTH_ONLY: 0, '0': 'KTH_ONLY',\n    VALUE_IDX_NOSORT: 1, '1': 'VALUE_IDX_NOSORT',\n    VALUE_IDX_SORTED: 2, '2': 'VALUE_IDX_SORTED'\n};\n\nmgb.serialization.fbs.param.WarpPerspectiveV1BorderMode = {\n    REPLICATE: 0, '0': 'REPLICATE',\n    REFLECT: 1, '1': 'REFLECT',\n    REFLECT_101: 2, '2': 'REFLECT_101',\n    WRAP: 3, '3': 'WRAP',\n    CONSTANT: 4, '4': 'CONSTANT',\n    TRANSPARENT: 5, '5': 'TRANSPARENT',\n    ISOLATED: 6, '6': 'ISOLATED'\n};\n\nmgb.serialization.fbs.param.WarpPerspectiveV1InterpolationMode = {\n    NEAREST: 0, '0': 'NEAREST',\n    LINEAR: 1, '1': 'LINEAR',\n    AREA: 2, '2': 'AREA',\n    CUBIC: 3, '3': 'CUBIC',\n    LANCZOS4: 4, '4': 'LANCZOS4'\n};\n\nmgb.serialization.fbs.param.Empty = class Empty {\n\n    static decode(/* reader, position */) {\n        const $ = new mgb.serialization.fbs.param.Empty();\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Axis = class Axis {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Axis();\n        $.axis = reader.int32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvolutionV0 = class ConvolutionV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvolutionV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 1);\n        $.stride_w = reader.uint32_(position, 12, 1);\n        $.dilate_h = reader.uint32_(position, 14, 1);\n        $.dilate_w = reader.uint32_(position, 16, 1);\n        $.data_type = reader.uint32_(position, 18, 0);\n        $.sparse = reader.uint32_(position, 20, 0);\n        $.format = reader.uint32_(position, 22, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvolutionV1 = class ConvolutionV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvolutionV1();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 1);\n        $.stride_w = reader.uint32_(position, 12, 1);\n        $.dilate_h = reader.uint32_(position, 14, 1);\n        $.dilate_w = reader.uint32_(position, 16, 1);\n        $.sparse = reader.uint32_(position, 18, 0);\n        $.format = reader.uint32_(position, 20, 0);\n        $.compute_mode = reader.uint32_(position, 22, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Convolution = class Convolution {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Convolution();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 1);\n        $.stride_w = reader.uint32_(position, 12, 1);\n        $.dilate_h = reader.uint32_(position, 14, 1);\n        $.dilate_w = reader.uint32_(position, 16, 1);\n        $.sparse = reader.uint32_(position, 18, 0);\n        $.format = reader.uint32_(position, 20, 0);\n        $.compute_mode = reader.uint32_(position, 22, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MaskPropagate = class MaskPropagate {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MaskPropagate();\n        $.pad_h = reader.uint32_(position, 4, 0);\n        $.pad_w = reader.uint32_(position, 6, 0);\n        $.stride_h = reader.uint32_(position, 8, 1);\n        $.stride_w = reader.uint32_(position, 10, 1);\n        $.kernel_h = reader.uint32_(position, 12, 1);\n        $.kernel_w = reader.uint32_(position, 14, 1);\n        $.dilate_h = reader.uint32_(position, 16, 1);\n        $.dilate_w = reader.uint32_(position, 18, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvPooling = class ConvPooling {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvPooling();\n        $.method = reader.uint32_(position, 4, 0);\n        $.convMode = reader.uint32_(position, 6, 0);\n        $.poolMode = reader.uint32_(position, 8, 0);\n        $.nonlineMode = reader.uint32_(position, 10, 0);\n        $.pool_shape_h = reader.uint32_(position, 12, 1);\n        $.pool_shape_w = reader.uint32_(position, 14, 1);\n        $.pool_stride_h = reader.uint32_(position, 16, 1);\n        $.pool_stride_w = reader.uint32_(position, 18, 1);\n        $.pool_pad_h = reader.uint32_(position, 20, 0);\n        $.pool_pad_w = reader.uint32_(position, 22, 0);\n        $.conv_stride_h = reader.uint32_(position, 24, 1);\n        $.conv_stride_w = reader.uint32_(position, 26, 1);\n        $.conv_pad_h = reader.uint32_(position, 28, 0);\n        $.conv_pad_w = reader.uint32_(position, 30, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvBiasV0 = class ConvBiasV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvBiasV0();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.pad_h = reader.uint32_(position, 8, 0);\n        $.pad_w = reader.uint32_(position, 10, 0);\n        $.stride_h = reader.uint32_(position, 12, 1);\n        $.stride_w = reader.uint32_(position, 14, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvBiasV1 = class ConvBiasV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvBiasV1();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.data_type = reader.uint32_(position, 8, 0);\n        $.sparse = reader.uint32_(position, 10, 0);\n        $.format = reader.uint32_(position, 12, 0);\n        $.pad_h = reader.uint32_(position, 14, 0);\n        $.pad_w = reader.uint32_(position, 16, 0);\n        $.stride_h = reader.uint32_(position, 18, 1);\n        $.stride_w = reader.uint32_(position, 20, 1);\n        $.dilate_h = reader.uint32_(position, 22, 1);\n        $.dilate_w = reader.uint32_(position, 24, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvBiasV2 = class ConvBiasV2 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvBiasV2();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.sparse = reader.uint32_(position, 8, 0);\n        $.format = reader.uint32_(position, 10, 0);\n        $.pad_h = reader.uint32_(position, 12, 0);\n        $.pad_w = reader.uint32_(position, 14, 0);\n        $.stride_h = reader.uint32_(position, 16, 1);\n        $.stride_w = reader.uint32_(position, 18, 1);\n        $.dilate_h = reader.uint32_(position, 20, 1);\n        $.dilate_w = reader.uint32_(position, 22, 1);\n        $.compute_mode = reader.uint32_(position, 24, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvBiasV3 = class ConvBiasV3 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvBiasV3();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.sparse = reader.uint32_(position, 8, 0);\n        $.format = reader.uint32_(position, 10, 0);\n        $.pad_h = reader.uint32_(position, 12, 0);\n        $.pad_w = reader.uint32_(position, 14, 0);\n        $.stride_h = reader.uint32_(position, 16, 1);\n        $.stride_w = reader.uint32_(position, 18, 1);\n        $.dilate_h = reader.uint32_(position, 20, 1);\n        $.dilate_w = reader.uint32_(position, 22, 1);\n        $.output_block_size = reader.uint32_(position, 24, 0);\n        $.compute_mode = reader.uint32_(position, 26, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ConvBias = class ConvBias {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ConvBias();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.sparse = reader.uint32_(position, 8, 0);\n        $.format = reader.uint32_(position, 10, 0);\n        $.pad_h = reader.uint32_(position, 12, 0);\n        $.pad_w = reader.uint32_(position, 14, 0);\n        $.stride_h = reader.uint32_(position, 16, 1);\n        $.stride_w = reader.uint32_(position, 18, 1);\n        $.dilate_h = reader.uint32_(position, 20, 1);\n        $.dilate_w = reader.uint32_(position, 22, 1);\n        $.compute_mode = reader.uint32_(position, 24, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SeparableConv = class SeparableConv {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SeparableConv();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.borderMode = reader.uint32_(position, 6, 0);\n        $.is_symm_kernel = reader.bool_(position, 8, true);\n        $.pad_h = reader.uint32_(position, 10, 0);\n        $.pad_w = reader.uint32_(position, 12, 0);\n        $.stride_h = reader.uint32_(position, 14, 1);\n        $.stride_w = reader.uint32_(position, 16, 1);\n        $.ksize_h = reader.uint32_(position, 18, 3);\n        $.ksize_w = reader.uint32_(position, 20, 3);\n        $.anchor_h = reader.uint32_(position, 22, 1);\n        $.anchor_w = reader.uint32_(position, 24, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Images2Neibs = class Images2Neibs {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Images2Neibs();\n        $.pad_h = reader.uint32_(position, 4, 0);\n        $.pad_w = reader.uint32_(position, 6, 0);\n        $.stride_h = reader.uint32_(position, 8, 1);\n        $.stride_w = reader.uint32_(position, 10, 1);\n        $.dilate_h = reader.uint32_(position, 12, 1);\n        $.dilate_w = reader.uint32_(position, 14, 1);\n        $.window_h = reader.uint32_(position, 16, 3);\n        $.window_w = reader.uint32_(position, 18, 3);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SlidingWindowTranspose = class SlidingWindowTranspose {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SlidingWindowTranspose();\n        $.out_h = reader.uint32_(position, 4, 0);\n        $.out_w = reader.uint32_(position, 6, 0);\n        $.pad_h = reader.uint32_(position, 8, 0);\n        $.pad_w = reader.uint32_(position, 10, 0);\n        $.stride_h = reader.uint32_(position, 12, 1);\n        $.stride_w = reader.uint32_(position, 14, 1);\n        $.dilate_h = reader.uint32_(position, 16, 1);\n        $.dilate_w = reader.uint32_(position, 18, 1);\n        $.window_h = reader.uint32_(position, 20, 3);\n        $.window_w = reader.uint32_(position, 22, 3);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.PoolingV0 = class PoolingV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.PoolingV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 2);\n        $.stride_w = reader.uint32_(position, 12, 2);\n        $.window_h = reader.uint32_(position, 14, 2);\n        $.window_w = reader.uint32_(position, 16, 2);\n        $.format = reader.uint32_(position, 18, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Pooling = class Pooling {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Pooling();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 2);\n        $.stride_w = reader.uint32_(position, 12, 2);\n        $.window_h = reader.uint32_(position, 14, 2);\n        $.window_w = reader.uint32_(position, 16, 2);\n        $.format = reader.uint32_(position, 18, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Softmax = class Softmax {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Softmax();\n        $.axis = reader.int32_(position, 4, -1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.AdaptivePoolingV0 = class AdaptivePoolingV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.AdaptivePoolingV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.format = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.AdaptivePooling = class AdaptivePooling {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.AdaptivePooling();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.format = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LRN = class LRN {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LRN();\n        $.n = reader.uint32_(position, 4, 5);\n        $.k = reader.float32_(position, 6, 2);\n        $.alpha = reader.float32_(position, 8, 0.0001);\n        $.beta = reader.float32_(position, 10, 0.75);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.BN = class BN {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.BN();\n        $.param_dim = reader.uint32_(position, 4, 0);\n        $.fwd_mode = reader.uint32_(position, 6, 0);\n        $.epsilon = reader.float64_(position, 8, 0.0001);\n        $.avg_factor = reader.float64_(position, 10, 1);\n        $.scale = reader.float32_(position, 12, 1);\n        $.bias = reader.float32_(position, 14, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ROIPooling = class ROIPooling {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ROIPooling();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.scale = reader.float32_(position, 6, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.WarpPerspectiveV1 = class WarpPerspectiveV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.WarpPerspectiveV1();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.bmode = reader.uint32_(position, 6, 0);\n        $.format = reader.uint32_(position, 8, 0);\n        $.border_val = reader.float32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.WarpPerspective = class WarpPerspective {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.WarpPerspective();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.bmode = reader.uint32_(position, 6, 0);\n        $.format = reader.uint32_(position, 8, 0);\n        $.border_val = reader.float32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SpatialTfGridGenerator = class SpatialTfGridGenerator {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SpatialTfGridGenerator();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SpatialTfSampler = class SpatialTfSampler {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SpatialTfSampler();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.AddUpdate = class AddUpdate {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.AddUpdate();\n        $.alpha = reader.float32_(position, 4, 1);\n        $.beta = reader.float32_(position, 6, 1);\n        $.bias = reader.float32_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Elemwise = class Elemwise {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Elemwise();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ElemwiseMultiType = class ElemwiseMultiType {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ElemwiseMultiType();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.PowC = class PowC {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.PowC();\n        $.exp = reader.float32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.DctChannelSelectV0 = class DctChannelSelectV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.DctChannelSelectV0();\n        $.format = reader.uint32_(position, 4, 0);\n        $.fastImpl = reader.uint32_(position, 6, 0);\n        $.dct_block_size = reader.int32_(position, 8, 8);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.DctChannelSelect = class DctChannelSelect {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.DctChannelSelect();\n        $.format = reader.uint32_(position, 4, 0);\n        $.fastImpl = reader.uint32_(position, 6, 0);\n        $.dct_block_size = reader.int32_(position, 8, 8);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MatrixMulV0 = class MatrixMulV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MatrixMulV0();\n        $.transposeA = reader.bool_(position, 4, false);\n        $.transposeB = reader.bool_(position, 6, false);\n        $.data_type = reader.uint32_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MatrixMulV1 = class MatrixMulV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MatrixMulV1();\n        $.transposeA = reader.bool_(position, 4, false);\n        $.transposeB = reader.bool_(position, 6, false);\n        $.compute_mode = reader.uint32_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MatrixMul = class MatrixMul {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MatrixMul();\n        $.transposeA = reader.bool_(position, 4, false);\n        $.transposeB = reader.bool_(position, 6, false);\n        $.compute_mode = reader.uint32_(position, 8, 0);\n        $.format = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SVD = class SVD {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SVD();\n        $.full_matrices = reader.bool_(position, 4, false);\n        $.compute_uv = reader.bool_(position, 6, true);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ReduceV0 = class ReduceV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ReduceV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, -1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ReduceV1 = class ReduceV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ReduceV1();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, -1);\n        $.data_type = reader.uint32_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Reduce = class Reduce {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Reduce();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 2147483647);\n        $.data_type = reader.uint32_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CumsumV0 = class CumsumV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CumsumV0();\n        $.axis = reader.int32_(position, 4, -1);\n        $.exclusive = reader.bool_(position, 6, true);\n        $.reverse = reader.bool_(position, 8, false);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Cumsum = class Cumsum {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Cumsum();\n        $.axis = reader.int32_(position, 4, 2147483647);\n        $.exclusive = reader.bool_(position, 6, true);\n        $.reverse = reader.bool_(position, 8, false);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CondTake = class CondTake {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CondTake();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.val = reader.float32_(position, 6, 0);\n        $.eps = reader.float32_(position, 8, 0.000001);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Argsort = class Argsort {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Argsort();\n        $.order = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.IndexingRemap = class IndexingRemap {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.IndexingRemap();\n        $.is_non_overlapping = reader.bool_(position, 4, false);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Sleep = class Sleep {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Sleep();\n        $.time = reader.float32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Linspace = class Linspace {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Linspace();\n        $.endpoint = reader.bool_(position, 4, true);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LinspaceFull = class LinspaceFull {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LinspaceFull();\n        $.start = reader.float64_(position, 4, 0);\n        $.stop = reader.float64_(position, 6, 1);\n        $.endpoint = reader.bool_(position, 8, true);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Eye = class Eye {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Eye();\n        $.k = reader.int32_(position, 4, 0);\n        $.dtype = reader.int8_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Diag = class Diag {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Diag();\n        $.k = reader.int32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.UniformRNGV0 = class UniformRNGV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.UniformRNGV0();\n        $.seed = reader.uint64_(position, 4, 0n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.UniformRNG = class UniformRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.UniformRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        $.dtype = reader.int8_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.GaussianRNGV0 = class GaussianRNGV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.GaussianRNGV0();\n        $.seed = reader.uint64_(position, 4, 0n);\n        $.mean = reader.float32_(position, 6, 0);\n        $.std = reader.float32_(position, 8, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.GaussianRNG = class GaussianRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.GaussianRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        $.mean = reader.float32_(position, 6, 0);\n        $.std = reader.float32_(position, 8, 1);\n        $.dtype = reader.int8_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.GammaRNG = class GammaRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.GammaRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.BetaRNG = class BetaRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.BetaRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.PoissonRNG = class PoissonRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.PoissonRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MultinomialRNG = class MultinomialRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MultinomialRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        $.num_samples = reader.uint64_(position, 6, 1n);\n        $.replacement = reader.bool_(position, 8, false);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.PermutationRNG = class PermutationRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.PermutationRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        $.dtype = reader.int8_(position, 6, 4);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ShuffleRNG = class ShuffleRNG {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ShuffleRNG();\n        $.seed = reader.uint64_(position, 4, 0n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Flip = class Flip {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Flip();\n        $.vertical = reader.bool_(position, 4, false);\n        $.horizontal = reader.bool_(position, 6, false);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Rotate = class Rotate {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Rotate();\n        $.clockwise = reader.bool_(position, 4, true);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ROICopy = class ROICopy {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ROICopy();\n        $.row_from = reader.uint32_(position, 4, 0);\n        $.row_to = reader.uint32_(position, 6, 0);\n        $.col_from = reader.uint32_(position, 8, 0);\n        $.col_to = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CvtColor = class CvtColor {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CvtColor();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.WarpAffineV0 = class WarpAffineV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.WarpAffineV0();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.border_mode = reader.uint32_(position, 6, 0);\n        $.border_val = reader.float32_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.WarpAffineV1 = class WarpAffineV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.WarpAffineV1();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.border_mode = reader.uint32_(position, 6, 0);\n        $.border_val = reader.float32_(position, 8, 0);\n        $.format = reader.uint32_(position, 10, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.WarpAffine = class WarpAffine {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.WarpAffine();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.border_mode = reader.uint32_(position, 6, 0);\n        $.border_val = reader.float32_(position, 8, 0);\n        $.format = reader.uint32_(position, 10, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.GaussianBlur = class GaussianBlur {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.GaussianBlur();\n        $.border_mode = reader.uint32_(position, 4, 0);\n        $.kernel_height = reader.uint32_(position, 6, 0);\n        $.kernel_width = reader.uint32_(position, 8, 0);\n        $.sigma_x = reader.float32_(position, 10, 0);\n        $.sigma_y = reader.float32_(position, 12, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ResizeV0 = class ResizeV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ResizeV0();\n        $.imode = reader.uint32_(position, 4, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ResizeV1 = class ResizeV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ResizeV1();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.format = reader.uint32_(position, 6, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Resize = class Resize {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Resize();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.format = reader.uint32_(position, 6, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.RemapV0 = class RemapV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.RemapV0();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.border_type = reader.uint32_(position, 6, 0);\n        $.format = reader.uint32_(position, 8, 1);\n        $.scalar = reader.float32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Remap = class Remap {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Remap();\n        $.imode = reader.uint32_(position, 4, 1);\n        $.border_type = reader.uint32_(position, 6, 0);\n        $.format = reader.uint32_(position, 8, 1);\n        $.scalar = reader.float32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Convolution3D = class Convolution3D {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Convolution3D();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_d = reader.uint32_(position, 6, 0);\n        $.pad_h = reader.uint32_(position, 8, 0);\n        $.pad_w = reader.uint32_(position, 10, 0);\n        $.stride_d = reader.uint32_(position, 12, 1);\n        $.stride_h = reader.uint32_(position, 14, 1);\n        $.stride_w = reader.uint32_(position, 16, 1);\n        $.dilate_d = reader.uint32_(position, 18, 1);\n        $.dilate_h = reader.uint32_(position, 20, 1);\n        $.dilate_w = reader.uint32_(position, 22, 1);\n        $.sparse = reader.uint32_(position, 24, 0);\n        $.data_type = reader.uint32_(position, 26, 0);\n        $.format = reader.uint32_(position, 28, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Conv3DBias = class Conv3DBias {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Conv3DBias();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.pad_d = reader.uint32_(position, 8, 0);\n        $.pad_h = reader.uint32_(position, 10, 0);\n        $.pad_w = reader.uint32_(position, 12, 0);\n        $.stride_d = reader.uint32_(position, 14, 1);\n        $.stride_h = reader.uint32_(position, 16, 1);\n        $.stride_w = reader.uint32_(position, 18, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SeparableConv3D = class SeparableConv3D {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SeparableConv3D();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.borderMode = reader.uint32_(position, 6, 0);\n        $.is_symm_kernel = reader.bool_(position, 8, true);\n        $.pad_d = reader.uint32_(position, 10, 0);\n        $.pad_h = reader.uint32_(position, 12, 0);\n        $.pad_w = reader.uint32_(position, 14, 0);\n        $.stride_d = reader.uint32_(position, 16, 0);\n        $.stride_h = reader.uint32_(position, 18, 1);\n        $.stride_w = reader.uint32_(position, 20, 1);\n        $.ksize_d = reader.uint32_(position, 22, 0);\n        $.ksize_h = reader.uint32_(position, 24, 3);\n        $.ksize_w = reader.uint32_(position, 26, 3);\n        $.anchor_d = reader.uint32_(position, 28, 0);\n        $.anchor_h = reader.uint32_(position, 30, 1);\n        $.anchor_w = reader.uint32_(position, 32, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.TopK = class TopK {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.TopK();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.RelayoutFormatV0 = class RelayoutFormatV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.RelayoutFormatV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.RelayoutFormat = class RelayoutFormat {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.RelayoutFormat();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.oc = reader.uint32_(position, 6, 0);\n        $.group = reader.uint32_(position, 8, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SeparableFilterV0 = class SeparableFilterV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SeparableFilterV0();\n        $.format = reader.uint32_(position, 4, 0);\n        $.borderMode = reader.uint32_(position, 6, 0);\n        $.is_symm_kernel = reader.bool_(position, 8, true);\n        $.ksize_h = reader.uint32_(position, 10, 3);\n        $.ksize_w = reader.uint32_(position, 12, 3);\n        $.anchor_h = reader.uint32_(position, 14, 1);\n        $.anchor_w = reader.uint32_(position, 16, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.SeparableFilter = class SeparableFilter {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.SeparableFilter();\n        $.format = reader.uint32_(position, 4, 0);\n        $.borderMode = reader.uint32_(position, 6, 0);\n        $.is_symm_kernel = reader.bool_(position, 8, true);\n        $.ksize_h = reader.uint32_(position, 10, 3);\n        $.ksize_w = reader.uint32_(position, 12, 3);\n        $.anchor_h = reader.uint32_(position, 14, 1);\n        $.anchor_w = reader.uint32_(position, 16, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LocalShareV0 = class LocalShareV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LocalShareV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 1);\n        $.stride_w = reader.uint32_(position, 12, 1);\n        $.dilate_h = reader.uint32_(position, 14, 1);\n        $.dilate_w = reader.uint32_(position, 16, 1);\n        $.spatial_groups_h = reader.uint32_(position, 18, 1);\n        $.spatial_groups_w = reader.uint32_(position, 20, 1);\n        $.sparse = reader.uint32_(position, 22, 0);\n        $.format = reader.uint32_(position, 24, 0);\n        $.computeMode = reader.uint32_(position, 26, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LocalShare = class LocalShare {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LocalShare();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.pad_h = reader.uint32_(position, 6, 0);\n        $.pad_w = reader.uint32_(position, 8, 0);\n        $.stride_h = reader.uint32_(position, 10, 1);\n        $.stride_w = reader.uint32_(position, 12, 1);\n        $.dilate_h = reader.uint32_(position, 14, 1);\n        $.dilate_w = reader.uint32_(position, 16, 1);\n        $.spatial_groups_h = reader.uint32_(position, 18, 1);\n        $.spatial_groups_w = reader.uint32_(position, 20, 1);\n        $.sparse = reader.uint32_(position, 22, 0);\n        $.format = reader.uint32_(position, 24, 0);\n        $.computeMode = reader.uint32_(position, 26, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ROIAlignV0 = class ROIAlignV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ROIAlignV0();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.format = reader.uint32_(position, 6, 0);\n        $.spatial_scale = reader.float32_(position, 8, 1);\n        $.offset = reader.float32_(position, 10, 0);\n        $.pooled_height = reader.uint32_(position, 12, 1);\n        $.pooled_width = reader.uint32_(position, 14, 1);\n        $.sample_height = reader.uint32_(position, 16, 2);\n        $.sample_width = reader.uint32_(position, 18, 2);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ROIAlign = class ROIAlign {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ROIAlign();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.format = reader.uint32_(position, 6, 0);\n        $.spatial_scale = reader.float32_(position, 8, 1);\n        $.offset = reader.float32_(position, 10, 0);\n        $.pooled_height = reader.uint32_(position, 12, 1);\n        $.pooled_width = reader.uint32_(position, 14, 1);\n        $.sample_height = reader.uint32_(position, 16, 2);\n        $.sample_width = reader.uint32_(position, 18, 2);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Correlation = class Correlation {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Correlation();\n        $.format = reader.uint32_(position, 4, 0);\n        $.kernel_size = reader.uint32_(position, 6, 1);\n        $.max_displacement = reader.uint32_(position, 8, 1);\n        $.stride1 = reader.uint32_(position, 10, 1);\n        $.stride2 = reader.uint32_(position, 12, 1);\n        $.pad_size = reader.uint32_(position, 14, 0);\n        $.is_multiply = reader.bool_(position, 16, true);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.DeformablePSROIPooling = class DeformablePSROIPooling {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.DeformablePSROIPooling();\n        $.no_trans = reader.bool_(position, 4, true);\n        $.spatial_scale = reader.float32_(position, 6, 1);\n        $.trans_std = reader.float32_(position, 8, 1);\n        $.pooled_h = reader.uint32_(position, 10, 1);\n        $.pooled_w = reader.uint32_(position, 12, 1);\n        $.part_size = reader.uint32_(position, 14, 1);\n        $.sample_per_part = reader.uint32_(position, 16, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.BatchConvBiasV0 = class BatchConvBiasV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.BatchConvBiasV0();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.pad_h = reader.uint32_(position, 8, 0);\n        $.pad_w = reader.uint32_(position, 10, 0);\n        $.stride_h = reader.uint32_(position, 12, 1);\n        $.stride_w = reader.uint32_(position, 14, 1);\n        $.dilate_h = reader.uint32_(position, 16, 1);\n        $.dilate_w = reader.uint32_(position, 18, 1);\n        $.sparse = reader.uint32_(position, 20, 0);\n        $.format = reader.uint32_(position, 22, 0);\n        $.compute_mode = reader.uint32_(position, 24, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.BatchConvBias = class BatchConvBias {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.BatchConvBias();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        $.mode = reader.uint32_(position, 6, 0);\n        $.pad_h = reader.uint32_(position, 8, 0);\n        $.pad_w = reader.uint32_(position, 10, 0);\n        $.stride_h = reader.uint32_(position, 12, 1);\n        $.stride_w = reader.uint32_(position, 14, 1);\n        $.dilate_h = reader.uint32_(position, 16, 1);\n        $.dilate_w = reader.uint32_(position, 18, 1);\n        $.sparse = reader.uint32_(position, 20, 0);\n        $.format = reader.uint32_(position, 22, 0);\n        $.compute_mode = reader.uint32_(position, 24, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.FakeQuant = class FakeQuant {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.FakeQuant();\n        $.qmin = reader.int32_(position, 4, -2147483648);\n        $.qmax = reader.int32_(position, 6, 2147483647);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.TQT = class TQT {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.TQT();\n        $.qmin = reader.int32_(position, 4, -2147483648);\n        $.qmax = reader.int32_(position, 6, 2147483647);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LSQ = class LSQ {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LSQ();\n        $.qmin = reader.int32_(position, 4, -2147483648);\n        $.qmax = reader.int32_(position, 6, 2147483647);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Fill = class Fill {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Fill();\n        $.value = reader.float32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CheckNonFinite = class CheckNonFinite {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CheckNonFinite();\n        $.scale = reader.float32_(position, 4, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Padding = class Padding {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Padding();\n        $.front_offset_dim0 = reader.uint32_(position, 4, 0);\n        $.front_offset_dim1 = reader.uint32_(position, 6, 0);\n        $.front_offset_dim2 = reader.uint32_(position, 8, 0);\n        $.front_offset_dim3 = reader.uint32_(position, 10, 0);\n        $.front_offset_dim4 = reader.uint32_(position, 12, 0);\n        $.front_offset_dim5 = reader.uint32_(position, 14, 0);\n        $.front_offset_dim6 = reader.uint32_(position, 16, 0);\n        $.back_offset_dim0 = reader.uint32_(position, 18, 0);\n        $.back_offset_dim1 = reader.uint32_(position, 20, 0);\n        $.back_offset_dim2 = reader.uint32_(position, 22, 0);\n        $.back_offset_dim3 = reader.uint32_(position, 24, 0);\n        $.back_offset_dim4 = reader.uint32_(position, 26, 0);\n        $.back_offset_dim5 = reader.uint32_(position, 28, 0);\n        $.back_offset_dim6 = reader.uint32_(position, 30, 0);\n        $.padding_val = reader.float32_(position, 32, 0);\n        $.padding_mode = reader.uint32_(position, 34, 2);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LayerNorm = class LayerNorm {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LayerNorm();\n        $.affine = reader.bool_(position, 4, true);\n        $.eps = reader.float32_(position, 6, 0.00001);\n        $.normalized_dim = reader.uint64_(position, 8, 1n);\n        $.normalized_size = reader.uint64_(position, 10, 1n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.GroupNorm = class GroupNorm {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.GroupNorm();\n        $.affine = reader.bool_(position, 4, true);\n        $.eps = reader.float32_(position, 6, 0.00001);\n        $.group = reader.uint32_(position, 8, 1);\n        $.format = reader.uint32_(position, 10, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Dropout = class Dropout {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Dropout();\n        $.drop_prob = reader.float32_(position, 4, 0);\n        $.seed = reader.uint64_(position, 6, 0n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.RNNCell = class RNNCell {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.RNNCell();\n        $.nonlineMode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.RNN = class RNN {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.RNN();\n        $.num_layers = reader.uint32_(position, 4, 1);\n        $.bidirectional = reader.bool_(position, 6, false);\n        $.bias = reader.bool_(position, 8, true);\n        $.hidden_size = reader.uint32_(position, 10, 128);\n        $.dropout = reader.float32_(position, 12, 0);\n        $.nonlineMode = reader.uint32_(position, 14, 0);\n        $.fwd_mode = reader.uint32_(position, 16, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.LSTM = class LSTM {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.LSTM();\n        $.num_layers = reader.uint32_(position, 4, 1);\n        $.bidirectional = reader.bool_(position, 6, false);\n        $.bias = reader.bool_(position, 8, true);\n        $.hidden_size = reader.uint32_(position, 10, 128);\n        $.proj_size = reader.uint32_(position, 12, 0);\n        $.dropout = reader.float32_(position, 14, 0);\n        $.fwd_mode = reader.uint32_(position, 16, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CollectiveCommMode = {\n    REDUCE_SUM: 0, '0': 'REDUCE_SUM',\n    BROADCAST: 1, '1': 'BROADCAST',\n    ALL_GATHER: 2, '2': 'ALL_GATHER',\n    REDUCE_SCATTER_SUM: 3, '3': 'REDUCE_SCATTER_SUM',\n    ALL_REDUCE_SUM: 4, '4': 'ALL_REDUCE_SUM',\n    ALL_REDUCE_MAX: 5, '5': 'ALL_REDUCE_MAX',\n    ALL_REDUCE_MIN: 6, '6': 'ALL_REDUCE_MIN',\n    ALL_REDUCE_PROD: 7, '7': 'ALL_REDUCE_PROD',\n    GATHER: 8, '8': 'GATHER',\n    SCATTER: 9, '9': 'SCATTER',\n    ALL_TO_ALL: 10, '10': 'ALL_TO_ALL'\n};\n\nmgb.serialization.fbs.param.CondExecMarkGradMode = {\n    SUM: 0, '0': 'SUM',\n    SUM_COND_OUT: 1, '1': 'SUM_COND_OUT'\n};\n\nmgb.serialization.fbs.param.CondExecMarkStaticInfer = {\n    SHAPE_VALUE: 0, '0': 'SHAPE_VALUE',\n    SHAPE_ONLY: 1, '1': 'SHAPE_ONLY',\n    NONE: 2, '2': 'NONE'\n};\n\nmgb.serialization.fbs.param.CondExecMergeMode = {\n    EXACT_ONE: 0, '0': 'EXACT_ONE',\n    EXACT_ONE_SAME_SHAPE: 1, '1': 'EXACT_ONE_SAME_SHAPE',\n    SUM: 2, '2': 'SUM',\n    SUM_COND_OUT: 3, '3': 'SUM_COND_OUT'\n};\n\nmgb.serialization.fbs.param.CondExecPredMode = {\n    CASE: 0, '0': 'CASE',\n    CASE_FALLBACK: 1, '1': 'CASE_FALLBACK',\n    PIECEWISE: 2, '2': 'PIECEWISE'\n};\n\nmgb.serialization.fbs.param.CondExecPredLogicalMode = {\n    OR: 0, '0': 'OR',\n    AND: 1, '1': 'AND',\n    XOR: 2, '2': 'XOR',\n    NOR: 3, '3': 'NOR',\n    NAND: 4, '4': 'NAND',\n    XNOR: 5, '5': 'XNOR'\n};\n\nmgb.serialization.fbs.param.ExecutionPolicyStrategy = {\n    HEURISTIC: 0, '0': 'HEURISTIC',\n    PROFILE: 1, '1': 'PROFILE',\n    REPRODUCIBLE: 2, '2': 'REPRODUCIBLE',\n    OPTIMIZED: 3, '3': 'OPTIMIZED'\n};\n\nmgb.serialization.fbs.param.ExecutionPolicyV0Strategy = {\n    HEURISTIC: 0, '0': 'HEURISTIC',\n    HEURISTIC_REPRODUCIBLE: 1, '1': 'HEURISTIC_REPRODUCIBLE',\n    PROFILE: 2, '2': 'PROFILE',\n    PROFILE_REPRODUCIBLE: 3, '3': 'PROFILE_REPRODUCIBLE',\n    PROFILE_HEURISTIC: 4, '4': 'PROFILE_HEURISTIC'\n};\n\nmgb.serialization.fbs.param.DType = class DType {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.DType();\n        $.dtype = reader.int8_(position, 4, 8);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.PersistentOutputStorage = class PersistentOutputStorage {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.PersistentOutputStorage();\n        $.share_key = reader.int32_(position, 4, -1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.OptionalAxis = class OptionalAxis {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.OptionalAxis();\n        $.axis = reader.int32_(position, 4, -1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.OptionalAxisV1 = class OptionalAxisV1 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.OptionalAxisV1();\n        $.axis = reader.int32_(position, 4, 7);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ExecutionPolicyV0 = class ExecutionPolicyV0 {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ExecutionPolicyV0();\n        $.strategy = reader.uint32_(position, 4, 0);\n        $.workspace_limit = reader.uint64_(position, 6, 18446744073709552000n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.ExecutionPolicy = class ExecutionPolicy {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.ExecutionPolicy();\n        $.strategy = reader.uint32_(position, 4, 1);\n        $.workspace_limit = reader.uint64_(position, 6, 18446744073709552000n);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.AssertEqual = class AssertEqual {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.AssertEqual();\n        $.maxerr = reader.float32_(position, 4, 0.0001);\n        $.verbose = reader.bool_(position, 6, false);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.FpgaConv = class FpgaConv {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.FpgaConv();\n        $.need_output_quantize = reader.bool_(position, 4, false);\n        $.need_output_threshold = reader.bool_(position, 6, false);\n        $.stride = reader.int32_(position, 8, 1);\n        $.input_bit_width = reader.int32_(position, 10, 2);\n        $.output_bit_width = reader.int32_(position, 12, 2);\n        $.weight_bit_width = reader.int32_(position, 14, 2);\n        $.thres0 = reader.int32_(position, 16, 0);\n        $.thres1 = reader.int32_(position, 18, 1);\n        $.unpool_size = reader.uint32_(position, 20, 4);\n        $.direct_size = reader.uint32_(position, 22, 4);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CollectiveComm = class CollectiveComm {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CollectiveComm();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.FakeSerializedDType = class FakeSerializedDType {\n\n    static decode(/* reader, position */) {\n        const $ = new mgb.serialization.fbs.param.FakeSerializedDType();\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CondExecPred = class CondExecPred {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CondExecPred();\n        $.mode = reader.uint32_(position, 4, 0);\n        $.eps = reader.float32_(position, 6, 0.0001);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CondExecPredLogical = class CondExecPredLogical {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CondExecPredLogical();\n        $.mode = reader.uint32_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CondExecMark = class CondExecMark {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CondExecMark();\n        $.grad_mode = reader.uint32_(position, 4, 0);\n        $.static_infer = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.CondExecMerge = class CondExecMerge {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.CondExecMerge();\n        $.nr_output = reader.uint32_(position, 4, 1);\n        $.mode = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.NvOf = class NvOf {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.NvOf();\n        $.precision = reader.uint32_(position, 4, 1);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.PersistentDTypeScalar = class PersistentDTypeScalar {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.PersistentDTypeScalar();\n        $.dtype = reader.int8(position + 0);\n        $.storage = reader.read(position + 1, 4);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MGBAddUpdate = class MGBAddUpdate {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MGBAddUpdate();\n        $.alpha = reader.struct(position, 4, mgb.serialization.fbs.param.PersistentDTypeScalar);\n        $.beta = reader.struct(position, 6, mgb.serialization.fbs.param.PersistentDTypeScalar);\n        $.bias = reader.struct(position, 8, mgb.serialization.fbs.param.PersistentDTypeScalar);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Host2DeviceCopy = class Host2DeviceCopy {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Host2DeviceCopy();\n        $.enable_value_infer = reader.bool_(position, 4, true);\n        $.dump_default_value = reader.bool_(position, 6, false);\n        $.allow_cpu_mem_fwd = reader.bool_(position, 8, true);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.Dimshuffle = class Dimshuffle {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.Dimshuffle();\n        $.pattern = reader.array(position, 4, Int32Array);\n        $.ndim = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.AxisDescMethod = {\n    ADD_1: 0, '0': 'ADD_1',\n    REMOVE: 1, '1': 'REMOVE'\n};\n\nmgb.serialization.fbs.param.AxisDesc = class AxisDesc {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.AxisDesc();\n        $.method = reader.int8(position + 0);\n        $.axis = reader.int32(position + 4);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.AxisAddRemove = class AxisAddRemove {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.AxisAddRemove();\n        $.desc = reader.structs(position, 4, mgb.serialization.fbs.param.AxisDesc, 8);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.MGBSleep = class MGBSleep {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.MGBSleep();\n        $.device = reader.bool_(position, 4, true);\n        $.host = reader.bool_(position, 6, false);\n        $.seconds = reader.float64_(position, 8, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.IndexDescMaskItem = class IndexDescMaskItem {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.IndexDescMaskItem();\n        $.axis = reader.int8(position + 0);\n        $.begin = reader.bool(position + 1);\n        $.end = reader.bool(position + 2);\n        $.step = reader.bool(position + 3);\n        $.idx = reader.bool(position + 4);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.IndexDescMaskDump = class IndexDescMaskDump {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.IndexDescMaskDump();\n        $.items = reader.structs(position, 4, mgb.serialization.fbs.param.IndexDescMaskItem, 5);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.param.NMSKeep = class NMSKeep {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.param.NMSKeep();\n        $.iou_thresh = reader.float32_(position, 4, 0);\n        $.max_output = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization = mgb.serialization || {};\n\nmgb.serialization.fbs = mgb.serialization.fbs || {};\n\nmgb.serialization.fbs.v2 = mgb.serialization.fbs.v2 || {};\n\nmgb.serialization.fbs.v2.CompNode = class CompNode {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.CompNode();\n        $.logical_locator = reader.string_(position, 4, null);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.DefaultTensorFormat = class DefaultTensorFormat {\n\n    static decode(/* reader, position */) {\n        const $ = new mgb.serialization.fbs.v2.DefaultTensorFormat();\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.Image2DPackedTensorFormat = class Image2DPackedTensorFormat {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.Image2DPackedTensorFormat();\n        $.align_axis = reader.uint8_(position, 4, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.LowbitsAlignedTensorFormat = class LowbitsAlignedTensorFormat {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.LowbitsAlignedTensorFormat();\n        $.size_nbits = reader.uint8_(position, 4, 0);\n        $.align_size_in_bits = reader.uint8_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.TensorFormat = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return mgb.serialization.fbs.v2.DefaultTensorFormat.decode(reader, position);\n            case 2: return mgb.serialization.fbs.v2.Image2DPackedTensorFormat.decode(reader, position);\n            case 3: return mgb.serialization.fbs.v2.LowbitsAlignedTensorFormat.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nmgb.serialization.fbs.v2.Blob = class Blob {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.Blob();\n        $.data = reader.array(position, 4, Uint8Array);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.Tensor();\n        $.name = reader.string_(position, 4, null);\n        $.shape = reader.array(position, 6, Uint32Array);\n        $.comp_node = reader.table(position, 8, mgb.serialization.fbs.v2.CompNode);\n        $.dtype = reader.table(position, 10, mgb.serialization.fbs.DType);\n        $.format = reader.union(position, 12, mgb.serialization.fbs.v2.TensorFormat);\n        $.data = reader.array(position, 16, Uint8Array);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.Reserved0 = class Reserved0 {\n\n    static decode(/* reader, position */) {\n        const $ = new mgb.serialization.fbs.v2.Reserved0();\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.DeprecatedParam = class DeprecatedParam {\n\n    static decode(/* reader, position */) {\n        const $ = new mgb.serialization.fbs.v2.DeprecatedParam();\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.OperatorParam = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return mgb.serialization.fbs.param.Empty.decode(reader, position);\n            case 2: return mgb.serialization.fbs.param.Axis.decode(reader, position);\n            case 3: return mgb.serialization.fbs.param.Convolution.decode(reader, position);\n            case 4: return mgb.serialization.fbs.param.MaskPropagate.decode(reader, position);\n            case 5: return mgb.serialization.fbs.param.ConvPooling.decode(reader, position);\n            case 6: return mgb.serialization.fbs.param.ConvBias.decode(reader, position);\n            case 7: return mgb.serialization.fbs.param.SeparableConv.decode(reader, position);\n            case 8: return mgb.serialization.fbs.param.Images2Neibs.decode(reader, position);\n            case 9: return mgb.serialization.fbs.param.Pooling.decode(reader, position);\n            case 10: return mgb.serialization.fbs.param.LRN.decode(reader, position);\n            case 11: return mgb.serialization.fbs.param.BN.decode(reader, position);\n            case 12: return mgb.serialization.fbs.param.ROIPooling.decode(reader, position);\n            case 13: return mgb.serialization.fbs.param.WarpPerspective.decode(reader, position);\n            case 14: return mgb.serialization.fbs.param.SpatialTfGridGenerator.decode(reader, position);\n            case 15: return mgb.serialization.fbs.param.SpatialTfSampler.decode(reader, position);\n            case 16: return mgb.serialization.fbs.param.MGBAddUpdate.decode(reader, position);\n            case 17: return mgb.serialization.fbs.param.Elemwise.decode(reader, position);\n            case 18: return mgb.serialization.fbs.param.ElemwiseMultiType.decode(reader, position);\n            case 19: return mgb.serialization.fbs.param.PowC.decode(reader, position);\n            case 20: return mgb.serialization.fbs.param.MatrixMul.decode(reader, position);\n            case 21: return mgb.serialization.fbs.v2.DeprecatedParam.decode(reader, position);\n            case 22: return mgb.serialization.fbs.param.SVD.decode(reader, position);\n            case 23: return mgb.serialization.fbs.param.Reduce.decode(reader, position);\n            case 24: return mgb.serialization.fbs.param.Cumsum.decode(reader, position);\n            case 25: return mgb.serialization.fbs.param.CondTake.decode(reader, position);\n            case 26: return mgb.serialization.fbs.param.Argsort.decode(reader, position);\n            case 27: return mgb.serialization.fbs.param.IndexingRemap.decode(reader, position);\n            case 28: return mgb.serialization.fbs.param.MGBSleep.decode(reader, position);\n            case 29: return mgb.serialization.fbs.param.Linspace.decode(reader, position);\n            case 30: return mgb.serialization.fbs.param.LinspaceFull.decode(reader, position);\n            case 31: return mgb.serialization.fbs.param.Eye.decode(reader, position);\n            case 32: return mgb.serialization.fbs.param.UniformRNG.decode(reader, position);\n            case 33: return mgb.serialization.fbs.param.GaussianRNG.decode(reader, position);\n            case 34: return mgb.serialization.fbs.param.Flip.decode(reader, position);\n            case 35: return mgb.serialization.fbs.param.Rotate.decode(reader, position);\n            case 36: return mgb.serialization.fbs.param.ROICopy.decode(reader, position);\n            case 37: return mgb.serialization.fbs.param.CvtColor.decode(reader, position);\n            case 38: return mgb.serialization.fbs.param.WarpAffine.decode(reader, position);\n            case 39: return mgb.serialization.fbs.param.GaussianBlur.decode(reader, position);\n            case 40: return mgb.serialization.fbs.param.Resize.decode(reader, position);\n            case 41: return mgb.serialization.fbs.param.Convolution3D.decode(reader, position);\n            case 42: return mgb.serialization.fbs.param.Conv3DBias.decode(reader, position);\n            case 43: return mgb.serialization.fbs.param.SeparableConv3D.decode(reader, position);\n            case 44: return mgb.serialization.fbs.param.TopK.decode(reader, position);\n            case 45: return mgb.serialization.fbs.param.RelayoutFormat.decode(reader, position);\n            case 46: return mgb.serialization.fbs.param.SeparableFilter.decode(reader, position);\n            case 47: return mgb.serialization.fbs.param.LocalShare.decode(reader, position);\n            case 48: return mgb.serialization.fbs.param.ROIAlign.decode(reader, position);\n            case 49: return mgb.serialization.fbs.param.DeformablePSROIPooling.decode(reader, position);\n            case 50: return mgb.serialization.fbs.param.BatchConvBias.decode(reader, position);\n            case 51: return mgb.serialization.fbs.param.DType.decode(reader, position);\n            case 52: return mgb.serialization.fbs.param.PersistentOutputStorage.decode(reader, position);\n            case 53: return mgb.serialization.fbs.param.OptionalAxis.decode(reader, position);\n            case 54: return mgb.serialization.fbs.param.OptionalAxisV1.decode(reader, position);\n            case 55: return mgb.serialization.fbs.param.ExecutionPolicy.decode(reader, position);\n            case 56: return mgb.serialization.fbs.param.AssertEqual.decode(reader, position);\n            case 57: return mgb.serialization.fbs.param.FpgaConv.decode(reader, position);\n            case 58: return mgb.serialization.fbs.param.CollectiveComm.decode(reader, position);\n            case 59: return mgb.serialization.fbs.param.CondExecPred.decode(reader, position);\n            case 60: return mgb.serialization.fbs.param.CondExecPredLogical.decode(reader, position);\n            case 61: return mgb.serialization.fbs.param.CondExecMark.decode(reader, position);\n            case 62: return mgb.serialization.fbs.param.CondExecMerge.decode(reader, position);\n            case 63: return mgb.serialization.fbs.param.Host2DeviceCopy.decode(reader, position);\n            case 64: return mgb.serialization.fbs.param.Dimshuffle.decode(reader, position);\n            case 65: return mgb.serialization.fbs.param.AxisAddRemove.decode(reader, position);\n            case 66: return mgb.serialization.fbs.param.IndexDescMaskDump.decode(reader, position);\n            case 67: return mgb.serialization.fbs.DType.decode(reader, position);\n            case 68: return mgb.serialization.fbs.param.Remap.decode(reader, position);\n            case 69: return mgb.serialization.fbs.param.NMSKeep.decode(reader, position);\n            case 70: return mgb.serialization.fbs.param.AdaptivePooling.decode(reader, position);\n            case 71: return mgb.serialization.fbs.param.NvOf.decode(reader, position);\n            case 72: return mgb.serialization.fbs.param.DctChannelSelect.decode(reader, position);\n            case 73: return mgb.serialization.fbs.param.FakeQuant.decode(reader, position);\n            case 74: return mgb.serialization.fbs.param.TQT.decode(reader, position);\n            case 75: return mgb.serialization.fbs.param.Correlation.decode(reader, position);\n            case 76: return mgb.serialization.fbs.param.LSQ.decode(reader, position);\n            case 77: return mgb.serialization.fbs.param.GammaRNG.decode(reader, position);\n            case 78: return mgb.serialization.fbs.param.PoissonRNG.decode(reader, position);\n            case 79: return mgb.serialization.fbs.param.PermutationRNG.decode(reader, position);\n            case 80: return mgb.serialization.fbs.param.BetaRNG.decode(reader, position);\n            case 81: return mgb.serialization.fbs.param.SlidingWindowTranspose.decode(reader, position);\n            case 82: return mgb.serialization.fbs.param.Padding.decode(reader, position);\n            case 83: return mgb.serialization.fbs.param.ShuffleRNG.decode(reader, position);\n            case 84: return mgb.serialization.fbs.param.CheckNonFinite.decode(reader, position);\n            case 85: return mgb.serialization.fbs.param.LayerNorm.decode(reader, position);\n            case 86: return mgb.serialization.fbs.param.Dropout.decode(reader, position);\n            case 87: return mgb.serialization.fbs.param.RNNCell.decode(reader, position);\n            case 88: return mgb.serialization.fbs.param.RNN.decode(reader, position);\n            case 89: return mgb.serialization.fbs.param.LSTM.decode(reader, position);\n            case 90: return mgb.serialization.fbs.param.Softmax.decode(reader, position);\n            case 91: return mgb.serialization.fbs.param.Diag.decode(reader, position);\n            case 92: return mgb.serialization.fbs.param.GroupNorm.decode(reader, position);\n            case 93: return mgb.serialization.fbs.param.Fill.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nmgb.serialization.fbs.v2.Operator = class Operator {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.Operator();\n        $.type = reader.string_(position, 4, null);\n        $.type_id = reader.uint64_(position, 6, 0n);\n        $.name = reader.string_(position, 8, null);\n        $.param = reader.union(position, 10, mgb.serialization.fbs.v2.OperatorParam);\n        $.additional_params = reader.unions(position, 14, mgb.serialization.fbs.v2.OperatorParam);\n        $.inputs = reader.array(position, 18, Uint32Array);\n        $.outputs = reader.array(position, 20, Uint32Array);\n        $.comp_node = reader.tables(position, 22, mgb.serialization.fbs.v2.CompNode);\n        $.output_dtype = reader.table(position, 24, mgb.serialization.fbs.DType);\n        $.tensors = reader.tables(position, 26, mgb.serialization.fbs.v2.Tensor);\n        $.opr_version = reader.uint32_(position, 28, 0);\n        $.priority = reader.int32_(position, 30, 0);\n        $.custom_data = reader.tables(position, 32, mgb.serialization.fbs.v2.Blob);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.Metadata = class Metadata {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.Metadata();\n        $.is_valid = reader.bool_(position, 4, false);\n        $.graph_modified = reader.bool_(position, 6, false);\n        $.optimize_options = reader.uint64_(position, 8, 0n);\n        $.user_info = reader.string_(position, 10, null);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.MiddleTensor = class MiddleTensor {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.MiddleTensor();\n        $.name = reader.string_(position, 4, null);\n        $.shape = reader.array(position, 6, Uint32Array);\n        $.comp_node = reader.table(position, 8, mgb.serialization.fbs.v2.CompNode);\n        $.dtype = reader.table(position, 10, mgb.serialization.fbs.DType);\n        $.format = reader.union(position, 12, mgb.serialization.fbs.v2.TensorFormat);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.OutputVar = class OutputVar {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.OutputVar();\n        $.compact_id = reader.uint32_(position, 4, 0);\n        $.original_id = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.OutputAlias = class OutputAlias {\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.OutputAlias();\n        $.id = reader.uint32_(position, 4, 0);\n        $.name = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nmgb.serialization.fbs.v2.Model = class Model {\n\n    static identifier(reader) {\n        return reader.identifier === 'mge2';\n    }\n\n    static create(reader) {\n        return mgb.serialization.fbs.v2.Model.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new mgb.serialization.fbs.v2.Model();\n        $.mge_version = reader.uint32_(position, 4, 0);\n        $.model_version = reader.uint32_(position, 6, 0);\n        $.oprs = reader.tables(position, 8, mgb.serialization.fbs.v2.Operator);\n        $.middle_tensors = reader.tables(position, 10, mgb.serialization.fbs.v2.MiddleTensor);\n        $.output_vars_idx = reader.tables(position, 12, mgb.serialization.fbs.v2.OutputVar);\n        $.output_alias = reader.tables(position, 14, mgb.serialization.fbs.v2.OutputAlias);\n        $.nr_shared_tensor = reader.uint32_(position, 16, 0);\n        $.metadata = reader.table(position, 18, mgb.serialization.fbs.v2.Metadata);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/megengine.js",
    "content": "\n// Experimental\n\nimport * as flatbuffers from './flatbuffers.js';\n\nconst megengine = {};\n\nmegengine.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        if (stream && stream.length >= 12) {\n            let buffer = stream.peek(12);\n            const tag = String.fromCharCode.apply(null, buffer);\n            const position = tag.startsWith('mgbtest0') ? 12 : 0;\n            if (stream.length > (position + 12)) {\n                buffer = stream.peek(24).slice(position, position + 12);\n                const size = (buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24) >>> 0;\n                if (position > 0 || size === (stream.length - position - 4)) {\n                    const reader = flatbuffers.BinaryReader.open(stream, position + 4);\n                    if (reader.identifier === 'mgv2') {\n                        return context.set('megengine.mge', reader);\n                    }\n                }\n            }\n            for (const value of ['mgb0001', 'mgb0000a', 'MGBS', 'MGBC']) {\n                if (tag.startsWith(value)) {\n                    return context.set(`megengine.${value}`);\n                }\n            }\n        }\n        const obj = await context.peek('pkl');\n        if (obj && obj.__class__ && obj.__class__.__module__ === 'megengine.traced_module.traced_module' && obj.__class__.__name__ === 'TracedModule') {\n            return context.set('megengine.tm');\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('megengine-metadata.json');\n        switch (context.type) {\n            case 'megengine.tm': {\n                const obj = await context.peek('pkl');\n                return new megengine.Model(metadata, obj, context.type);\n            }\n            case 'megengine.mge': {\n                megengine.schema = await context.require('./megengine-schema');\n                megengine.schema = megengine.schema.mgb.serialization.fbs;\n                let model = null;\n                try {\n                    const reader = context.value;\n                    model = megengine.schema.v2.Model.create(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new megengine.Error(`File format is not megengine.Model (${message.replace(/\\.$/, '')}).`);\n                }\n                return new megengine.Model(metadata, model, context.type);\n            }\n            default: {\n                throw new megengine.Error(`Unsupported MegEngine format '${context.type.replace(/^megengine\\./, '')}'.`);\n            }\n        }\n    }\n};\n\nmegengine.Model = class {\n\n    constructor(metadata, obj, type) {\n        this.format = 'MegEngine';\n        if (type === 'megengine.tm') {\n            this.format += obj.dump_info && obj.dump_info.has('version') ? ` v${obj.dump_info.get('version')}` : '';\n        } else if (type === 'megengine.mge') {\n            this.format += ` Mge${obj.model_version ? ` v${obj.model_version}` : ''}`;\n        }\n        this.modules = [new megengine.Graph(metadata, obj)];\n    }\n};\n\nmegengine.Graph = class {\n\n    constructor(metadata, obj) {\n        this.name = '';\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const values = new Map();\n        values.map = (name, type, tensor, quantization) => {\n            type = type || null;\n            tensor = tensor || null;\n            if (tensor) {\n                return new megengine.Value(name, type, tensor, quantization);\n            }\n            if (!values.has(name)) {\n                values.set(name, new megengine.Value(name, type, tensor, quantization));\n            } else if ((type && !type.equals(values.get(name).type)) || tensor) {\n                throw new megengine.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const loadGraph = (tmodule, igraph, context, namePrefix, metadata, isRoot) => {\n            const expressions = igraph._exprs;\n            const getTensorType = (dtype, shape) => {\n                dtype = dtype ? dtype.__name__ : null;\n                return new megengine.TensorType(dtype, new megengine.TensorShape(shape));\n            };\n            if (isRoot) {\n                for (const node of igraph._inputs) {\n                    if (node.__class__.__name__ !== 'ModuleNode') {\n                        const type = getTensorType(node._dtype, node._shape);\n                        const value = values.map(node._name, type, null);\n                        const argument = new megengine.Argument(node._name, [value]);\n                        this.inputs.push(argument);\n                    }\n                }\n                for (const node of igraph._outputs) {\n                    const type = getTensorType(node._dtype, node._shape);\n                    const value = values.map(node._name, type, null);\n                    const argument = new megengine.Argument(node._name, [value]);\n                    this.outputs.push(argument);\n                }\n            }\n            const parseGetAttr = (module, expression) => {\n                let names = expression.name.split('.');\n                while (expression.inputs[0].expr.__class__.__name__ === 'GetAttr') {\n                    expression = expression.inputs[0].expr;\n                    names = expression.name.split('.').concat(names);\n                }\n                let obj = module;\n                for (const name of names) {\n                    if (obj.__class__.__name__ === '_ModuleState') {\n                        obj = obj.state;\n                    }\n                    obj = obj[name];\n                }\n                return obj;\n            };\n            const parseArgs = (args, kwargs, meta) => {\n                const state = {};\n                let argIdx = 0;\n                const processArgs = (inp, startIdx) => {\n                    while (typeof inp === 'string' && inp.indexOf('Tensor') !== -1) {\n                        inp = inp.replace('Tensor', `input${startIdx === 0 ? '' : startIdx}`);\n                        startIdx += 1;\n                    }\n                    return [inp, startIdx];\n                };\n                const formatTreeDef = (obj) => {\n                    if (obj.__class__.__name__ !== 'TreeDef' && obj.__class__.__name__ !== 'LeafDef') {\n                        throw new megengine.Error(`Invalid argument '${obj.__class__.__name__}'.`);\n                    }\n                    if (obj.__class__.__name__ === 'TreeDef') {\n                        const type = typeof obj.type === 'string' ? obj.type.split('.').slice(-1)[0] : obj.type.__name__;\n                        const list = obj.children_defs.map((child) => formatTreeDef(child));\n                        switch (type) {\n                            case 'tuple': {\n                                return `(${list.join(',')})`;\n                            }\n                            case 'slice': {\n                                return list.join(':');\n                            }\n                            case 'list': {\n                                return `[${list.join(',')}]`;\n                            }\n                            case 'dict': {\n                                let content = '';\n                                for (let i = 0; i < this.children_defs.length; i++) {\n                                    content += `${this.aux_data[i]}:${list[i]}`;\n                                }\n                                return `{${content}}`;\n                            }\n                            default: {\n                                return `${type}(${list.join(',')})`;\n                            }\n                        }\n                    }\n                    if (obj.const_val !== null) {\n                        return obj.const_val;\n                    } else if (obj.type[0].__module__ !== undefined) {\n                        return obj.type[0].__name__;\n                    }\n                    return 'None';\n                };\n                let inpIdx = 0;\n                for (const arg of args.children_defs) {\n                    let name = '';\n                    if (meta.attributes === undefined || (meta.attributes.length !== args.children_defs.length && meta.varargs === null)) {\n                        name = `arg${argIdx}`;\n                    } else if (argIdx < meta.attributes.length) {\n                        name = meta.attributes[argIdx].name;\n                    } else {\n                        name = meta.varargs + (argIdx - meta.attributes.length);\n                    }\n                    const [value, index] = processArgs(formatTreeDef(arg), inpIdx);\n                    state[name] = value;\n                    inpIdx = index;\n                    argIdx += 1;\n                }\n                for (let i = 0; i < kwargs.children_defs.length; i++) {\n                    const [value, index] = processArgs(formatTreeDef(kwargs.children_defs[i]), inpIdx);\n                    state[kwargs.aux_data[i]] = value;\n                    inpIdx = index;\n                }\n                return state;\n            };\n            const getName = (context, name) => {\n                let rst = name;\n                while (context.get(rst) !== undefined) {\n                    if (rst === context.get(rst)) {\n                        return rst;\n                    }\n                    rst = context.get(rst);\n                }\n                return rst;\n            };\n            const getFullName = (prefix, name) => {\n                return prefix === '' ? name : `${prefix}_${name}`;\n            };\n            for (const expression of expressions) {\n                const type = expression.__class__.__name__;\n                for (const input of expression.inputs) {\n                    input._fullname = getName(context, getFullName(namePrefix, input._name));\n                }\n                for (const output of expression.outputs) {\n                    output._fullname = getName(context, getFullName(namePrefix, output._name));\n                }\n                switch (type) {\n                    case 'Input': {\n                        break;\n                    }\n                    case 'GetAttr': {\n                        if (expression.outputs[0].__class__.__name__ === 'TensorNode') {\n                            const tensor = parseGetAttr(tmodule, expression);\n                            const type = getTensorType(tensor.dtype, tensor.data.shape);\n                            const data = tensor.data.data;\n                            expression.outputs[0].initializer = new megengine.Tensor(expression.name, type, data);\n                        }\n                        break;\n                    }\n                    case 'Constant': {\n                        if (expression.outputs[0].__class__.__name__ === 'TensorNode') {\n                            const tensor = expression.value;\n                            const type = getTensorType(tensor.dtype, tensor.data.shape);\n                            const data = tensor.data.data;\n                            expression.outputs[0].initializer = new megengine.Tensor('', type, data);\n                        }\n                        break;\n                    }\n                    case 'CallMethod': {\n                        const obj = { 'name': '' };\n                        let state = {};\n                        if (expression.method === '__call__') {\n                            const module = parseGetAttr(tmodule, expression.inputs[0].expr);\n                            const getModuleType = (obj) => {\n                                if (obj.module !== undefined) {\n                                    return `${obj.module[0]}.${obj.module[1]}`;\n                                }\n                                return `${obj.__class__.__module__}.${obj.__class__.__name__}`;\n                            };\n                            const moduleType = module.__class__.__name__ === 'TracedModule' ? 'TracedModule' : getModuleType(module);\n                            if (moduleType === 'TracedModule') {\n                                const moduleName = expression.outputs[0]._name.endsWith(\"_out\") ? expression.outputs[0]._name.substring(0, expression.outputs[0]._name.length - 4) : expression.outputs[0]._name;\n                                const prefix = getFullName(namePrefix, moduleName);\n                                const internalGraph = module.argdef_graph_map.get(expression.arg_def);\n                                for (let i = 0; i < expression.inputs.length; i++) {\n                                    const actualName = getFullName(namePrefix, expression.inputs[i]._name);\n                                    const internalName = getFullName(prefix, internalGraph._inputs[i]._name);\n                                    context.set(internalName, actualName);\n                                }\n                                for (let i = 0; i < expression.outputs.length; i++) {\n                                    const actualName = getFullName(namePrefix, expression.outputs[i]._name);\n                                    const internalName = getFullName(prefix, internalGraph._outputs[i]._name);\n                                    if (context.get(internalName) === undefined) {\n                                        context.set(internalName, actualName);\n                                    } else {\n                                        context.set(actualName, context.get(internalName));\n                                    }\n                                }\n                                loadGraph(module, internalGraph, context, prefix, metadata, false);\n                                continue;\n                            }\n                            obj.type = moduleType;\n                            state = module.__class__.__name__ === 'TracedModule' ? module : module.state;\n                            if (state === undefined) {\n                                state = module;\n                            }\n                        } else {\n                            obj.type = expression.method;\n                            const [args, kwargs] = expression.arg_def.children_defs;\n                            const schema = metadata.type(expression.method);\n                            state = parseArgs(args, kwargs, schema);\n                        }\n                        const node = new megengine.Node(metadata, obj, values, null, expression, state);\n                        this.nodes.push(node);\n                        break;\n                    }\n                    case 'CallFunction': {\n                        const getFunctionType = (obj) => {\n                            if (obj.func.__module__ !== undefined) {\n                                return `${obj.func.__module__}.${obj.func.__name__}`;\n                            }\n                            return `${obj.func[0]}.${obj.func[1]}`;\n                        };\n                        const func = getFunctionType(expression);\n                        const item = { 'name': '', 'type': func };\n                        const [args, kwargs] = expression.arg_def.children_defs;\n                        const schema = metadata.type(func);\n                        const state = parseArgs(args, kwargs, schema);\n                        const node = new megengine.Node(metadata, item, values, null, expression, state);\n                        this.nodes.push(node);\n                        break;\n                    }\n                    case 'Apply': {\n                        const opdef = expression.opdef_state ? expression.opdef_state.get('opdef_type') : expression.opdef.type;\n                        const item = { 'name': '', 'type': `${opdef.__module__}.${opdef.__name__}` };\n                        const node = new megengine.Node(metadata, item, values, null, expression, expression.opdef_state);\n                        this.nodes.push(node);\n                        break;\n                    }\n                    default: {\n                        break;\n                    }\n                }\n            }\n        };\n        if (obj.argdef_graph_map) {\n            const [graph] = Array.from(obj.argdef_graph_map.values());\n            loadGraph(obj, graph, new Map(), '', metadata, true);\n            return;\n        }\n        const extraInfoNameset = new Set();\n        const getExtraInfo = (opr) => {\n            let name = opr.name;\n            let repeatIdx = 0;\n            while (extraInfoNameset.has(name)) {\n                for (const id of opr.inputs) {\n                    name = `${name}[${id}]`;\n                }\n                name += repeatIdx;\n                repeatIdx += 1;\n            }\n            extraInfoNameset.add(name);\n            const type = opr.type.replace(/V(\\d+)$/, '');\n            const args = [];\n            if (opr.tensors.length > 0) {\n                const [tensor] = opr.tensors;\n                const type = new megengine.TensorType(tensor.dtype.type, new megengine.TensorShape(tensor.shape));\n                const data = tensor.data.byteLength === 0 ? undefined : tensor.data.slice(0);\n                const initializer = opr.type === 'Host2DeviceCopy' ? undefined : new megengine.Tensor('', type, data);\n                const quantization = tensor.dtype.param ? { scale: tensor.dtype.param.scale, zeroPoint: tensor.dtype.param.zero_point } : null;\n                const value = values.map(name, type, initializer, quantization);\n                args.push(value);\n            } else {\n                const type = opr.shape ? new megengine.TensorType('?', new megengine.TensorShape(opr.shape)) : null;\n                const value = values.map(name, type);\n                args.push(value);\n            }\n            return { name, type, args };\n        };\n        const getAllOprAndTensor = (oprs) => {\n            const allOprAndTensor = new Map();\n            for (const opr of oprs) {\n                if (opr.type === 'MultipleDeviceTensorWithFormatHolder' || opr.outputs.length > 1) {\n                    if (opr.type === 'MultipleDeviceTensorWithFormatHolder' || opr.type === 'MultipleDeviceTensorHolder') {\n                        opr.type = 'ImmutableTensor';\n                    }\n                    for (let id = 0; id < opr.outputs.length; id++) {\n                        const keyId = opr.outputs[id];\n                        const name = obj.middle_tensors[keyId] ? obj.middle_tensors[keyId].name : String(keyId);\n                        const type = opr.type;\n                        const tensors = opr.tensors.length ? [opr.tensors[id]] : [];\n                        const onlyShape = obj.middle_tensors[keyId] ? obj.middle_tensors[keyId].shape : [];\n                        allOprAndTensor.set(keyId, { name, type, tensors, shape: onlyShape, inputs: opr.inputs, outputs: opr.outputs });\n                        const _opr = allOprAndTensor.get(keyId);\n                        _opr.extraInfo = getExtraInfo(_opr);\n                    }\n                } else {\n                    const [keyId] = opr.outputs;\n                    opr.name = obj.middle_tensors[keyId] ? obj.middle_tensors[keyId].name : String(keyId);\n                    if (obj.middle_tensors[keyId] && obj.middle_tensors[keyId].shape) {\n                        opr.shape = obj.middle_tensors[keyId].shape;\n                    }\n                    allOprAndTensor.set(keyId, opr);\n                    const _opr = allOprAndTensor.get(keyId);\n                    _opr.extraInfo = getExtraInfo(_opr);\n                }\n            }\n            return allOprAndTensor;\n        };\n        const allOprAndTensor = getAllOprAndTensor(obj.oprs);\n        for (const op of Array.from(allOprAndTensor.values())) {\n            if (op.type === 'Host2DeviceCopy') {\n                const argument = new megengine.Argument('input', op.extraInfo.args);\n                this.inputs.push(argument);\n            } else if (op.type !== 'ImmutableTensor') {\n                this.nodes.push(new megengine.Node(metadata, op, values, allOprAndTensor));\n            }\n        }\n        for (let i = 0; i < obj.output_vars_idx.length; i++) {\n            const id = obj.output_vars_idx[i].compact_id;\n            const out_type = `output${i === 0 ? '' : i}`;\n            const argument = new megengine.Argument(out_type, allOprAndTensor.get(id).extraInfo.args);\n            this.outputs.push(argument);\n        }\n    }\n};\n\nmegengine.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nmegengine.Value = class {\n\n    constructor(name, type, initializer, quantization) {\n        if (typeof name !== 'string') {\n            throw new megengine.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n        if (quantization && ((quantization.scale !== undefined && quantization.scale !== 1) || (quantization.zeroPoint !== undefined && quantization.zeroPoint !== 0))) {\n            this.quantization = {\n                type: 'linear',\n                scale: [quantization.scale],\n                offset: [quantization.zeroPoint]\n            };\n        }\n    }\n};\n\nmegengine.Node = class {\n\n    constructor(metadata, obj, values, allOprAndTensor, expr, state) {\n        this.name = '';\n        const type = metadata.type(obj.type);\n        this.type = type ? { ...type } : { name: obj.type };\n        this.type.name = this.type.name.replace(/V(\\d+)$/, '');\n        if (this.type.name.length > 4 && this.type.name.startsWith('__') && this.type.name.endsWith('__')) {\n            this.type.name = this.type.name.substring(2, this.type.name.length - 2);\n        }\n        this.inputs = [];\n        this.outputs = [];\n        this.chain = [];\n        this.attributes = [];\n        const attributes = [];\n        if (obj.inputs && obj.outputs) {\n            const inputSchemas = this.type && this.type.inputs ? [...this.type.inputs] : [];\n            for (let i = 0; i < obj.inputs.length; i++) {\n                const inputOpr = allOprAndTensor.get(obj.inputs[i]);\n                const schema = inputSchemas.length > 0 ? inputSchemas.shift() : { name: `input${i === 0 ? '' : i.toString()}` };\n                const argument = new megengine.Argument(schema.name, inputOpr.extraInfo.args);\n                this.inputs.push(argument);\n            }\n            const outputSchemas = this.type && this.type.outputs ? [...this.type.outputs] : [];\n            for (let i = 0; i < obj.outputs.length; i++) {\n                const outputOpr = allOprAndTensor.get(obj.outputs[i]);\n                const schema = outputSchemas.length > 0 ? outputSchemas.shift() : { name: `output${i === 0 ? '' : i.toString()}` };\n                const argument = new megengine.Argument(schema.name, outputOpr.extraInfo.args);\n                this.outputs.push(argument);\n            }\n            if (obj.param) {\n                for (const [name, value] of Object.entries(obj.param)) {\n                    if (value !== null) {\n                        const schema = metadata.attribute(obj.param.constructor.name, name);\n                        attributes.push([schema, name, value]);\n                    }\n                }\n            }\n        }\n        if (expr) {\n            let inpIdx = 0;\n            for (const i of expr.inputs) {\n                if (i.__class__.__name__ !== 'ModuleNode') {\n                    const initializer = i.initializer === undefined ? null : i.initializer;\n                    const name = `input${inpIdx === 0 ? '' : inpIdx}`;\n                    const dtype = i._dtype ? i._dtype.__name__ : null;\n                    const shape = new megengine.TensorShape(i._shape);\n                    const type = new megengine.TensorType(dtype, shape);\n                    const value = values.map(i._fullname, type, initializer);\n                    const argument = new megengine.Argument(name, [value]);\n                    this.inputs.push(argument);\n                    inpIdx += 1;\n                }\n            }\n            let outIdx = 0;\n            let qparams = null;\n            for (const o of expr.outputs) {\n                if (o._qparams !== null) {\n                    qparams = o._qparams[1];\n                }\n                const name = `output${outIdx === 0 ? '' : outIdx}`;\n                const dtype = o._dtype ? o._dtype.__name__ : null;\n                const shape = new megengine.TensorShape(o._shape);\n                const type = new megengine.TensorType(dtype, shape);\n                const value = values.map(o._fullname, type, null);\n                const argument = new megengine.Argument(name, [value]);\n                this.outputs.push(argument);\n                outIdx += 1;\n            }\n            if (qparams !== null) {\n                state = state === null ? {} : state;\n                state.scale = qparams.scale;\n                state.zero_point = qparams.zero_point;\n                state.quant_dtype_meta = qparams.dtype_meta;\n            }\n            if (state !== null) {\n                for (const [key, obj] of Array.from(state)) {\n                    const isModule = (obj) => {\n                        return obj && (obj.state || obj._forward_pre_hooks);\n                    };\n                    const isTensor = (obj) => {\n                        return obj && obj.__class__ && obj.__class__.__module__ === 'megengine.tensor' && (obj.__class__.__name__ === 'Tensor' || obj.__class__.__name__ === 'Parameter');\n                    };\n                    if (!key.startsWith('_') && !isModule(obj)) {\n                        if (isTensor(obj)) {\n                            const tensor = obj;\n                            const dtype = tensor.dtype ? tensor.dtype.__name__ : null;\n                            const shape = new megengine.TensorShape(tensor.data.shape);\n                            const type = new megengine.TensorType(dtype, shape);\n                            const data = tensor.data.data;\n                            const initializer = new megengine.Tensor(key, type, data);\n                            const value = values.map('', type, initializer);\n                            const argument = new megengine.Argument(key, [value]);\n                            this.inputs.push(argument);\n                        } else {\n                            const value = obj === null ? 'None' : obj;\n                            attributes.push([null, key, value]);\n                        }\n                    }\n                }\n            }\n        }\n        this.attributes = attributes.map(([metadata, name, value]) => {\n            value = ArrayBuffer.isView(value) ? Array.from(value) : value;\n            let type = metadata ? metadata.type : null;\n            let visible = true;\n            if (name === 'training') {\n                visible = false;\n                type = 'boolean';\n            }\n            if (megengine.schema) {\n                if (megengine.schema.param[type]) {\n                    const enumType = megengine.schema.param[type];\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                } else if (megengine.schema[type]) {\n                    const enumType = megengine.schema[type];\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                } else if (megengine.schema.v2[type]) {\n                    const enumType = megengine.schema.v2[type];\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                }\n            }\n            return new megengine.Argument(name, value, type, visible);\n        });\n    }\n};\n\nmegengine.Tensor = class {\n\n    constructor(name, type, data) {\n        this.category = 'Tensor';\n        this.name = name || '';\n        this.type = type;\n        this.values = data;\n    }\n};\n\nmegengine.TensorType = class {\n\n    constructor(dataType, shape) {\n        if (typeof dataType === 'number') {\n            dataType = megengine.schema.DTypeEnum[dataType] || dataType;\n        }\n        dataType = typeof dataType === 'string' ? dataType.toLowerCase() : dataType;\n        megengine.TensorType._dataTypes = megengine.TensorType._dataTypes || new Map([\n            ['bool', 'boolean'],\n            ['byte', 'uint8'], ['quantizeds4asymm', 'uint8'], ['quantizeds8asymm', 'uint8'], ['uintb4', 'uint8'],\n            ['quantizeds1', 'int8'], ['quantizeds4', 'int8'], ['quantizeds8', 'int8'], ['intb1', 'int8'], ['intb2', 'int8'], ['intb4', 'int8'], ['qint8', 'int8'],\n            ['quantizeds16', 'int16'],\n            ['quantizeds32', 'int32']\n        ]);\n        this.dataType = megengine.TensorType._dataTypes.get(dataType) || dataType;\n        this.shape = shape;\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmegengine.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.from(dimensions || []);\n    }\n\n    equals(obj) {\n        return obj && Array.isArray(obj.dimensions) &&\n            Array.isArray(this.dimensions) && this.dimensions.length === obj.dimensions.length\n            && obj.dimensions.every((value, index) => this.dimensions[index] === value);\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nmegengine.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading MegEngine model.';\n    }\n};\n\nexport const ModelFactory = megengine.ModelFactory;\n\n"
  },
  {
    "path": "source/message.js",
    "content": "\n// Experimental\n\nconst message = {};\n\nmessage.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        if (stream) {\n            const buffer = stream.peek(Math.min(64, stream.length));\n            const content = String.fromCharCode.apply(null, buffer);\n            const match = content.match(/^{\\s*\"signature\":\\s*\"(.*)\"\\s*,\\s*/);\n            if (match && match[1].startsWith('netron:')) {\n                const obj = await context.peek('json');\n                if (obj && obj.signature && obj.signature.startsWith('netron:')) {\n                    return context.set('message', obj);\n                }\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        return new message.Model(context.value);\n    }\n};\n\nmessage.Model = class {\n\n    constructor(data) {\n        this.format = data.format || '';\n        this.format = this.format.replace(/\\s+(\\d+\\.\\d+)$/, ' v$1'); // Format v2.0\n        this.producer = data.producer || '';\n        this.version = data.version || '';\n        this.description = data.description || '';\n        this.metadata = (data.metadata || []).map((entry) => {\n            return { name: entry.name, value: entry.value };\n        });\n        const modules = data.modules || data.graphs || [];\n        this.modules = modules.map((module) => new message.Module(module));\n    }\n};\n\nmessage.Module = class {\n\n    constructor(data) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = new Map();\n        values.map = (index) => {\n            if (!values.has(index)) {\n                values.set(index, new message.Value({ name: index.toString() }));\n            }\n            return values.get(index);\n        };\n        if (Array.isArray(data.values)) {\n            for (let i = 0; i < data.values.length; i++) {\n                values.set(i, new message.Value(data.values[i]));\n            }\n        }\n        if (Array.isArray(data.arguments)) {\n            for (let i = 0; i < data.arguments.length; i++) {\n                values.set(data.arguments[i].name, new message.Value(data.arguments[i]));\n            }\n        }\n        for (const argument of data.inputs || []) {\n            argument.value = argument.value.map((index) => values.map(index)).filter((argument) => !argument.initializer);\n            if (argument.value.filter((argument) => !argument.initializer).length > 0) {\n                this.inputs.push(new message.Argument(argument));\n            }\n        }\n        for (const argument of data.outputs || []) {\n            argument.value = argument.value.map((index) => values.map(index));\n            if (argument.value.filter((argument) => !argument.initializer).length > 0) {\n                this.outputs.push(new message.Argument(argument));\n            }\n        }\n        for (const node of data.nodes || []) {\n            for (const argument of node.inputs || []) {\n                if (!argument.value && argument.arguments) {\n                    argument.value = argument.arguments;\n                    delete argument.arguments;\n                }\n                argument.value = argument.value.map((index) => values.map(index));\n            }\n            for (const argument of node.outputs || []) {\n                if (!argument.value && argument.arguments) {\n                    argument.value = argument.arguments;\n                    delete argument.arguments;\n                }\n                argument.value = argument.value.map((index) => values.map(index));\n            }\n            this.nodes.push(new message.Node(node));\n        }\n    }\n};\n\nmessage.Argument = class {\n\n    constructor(data) {\n        this.name = data.name || '';\n        this.value = data.value || [];\n        this.type = data.type || null;\n    }\n};\n\nmessage.Value = class {\n\n    constructor(data) {\n        this.name = data.name !== undefined && data.name !== null ? data.name.toString() : '';\n        this.initializer = data.initializer ? new message.Tensor(data.initializer) : null;\n        if (this.initializer && this.initializer.type) {\n            this.type = this.initializer.type;\n        } else {\n            this.type = data.type ? new message.TensorType(data.type) : null;\n        }\n    }\n};\n\nmessage.Node = class {\n\n    constructor(data) {\n        this.type = { name: data.type.name, category: data.type.category };\n        this.name = data.name || '';\n        this.inputs = (data.inputs || []).map((input) => new message.Argument(input));\n        this.outputs = (data.outputs || []).map((output) => new message.Argument(output));\n        this.attributes = (data.attributes || []).map((attribute) => new message.Argument(attribute));\n    }\n};\n\nmessage.TensorType = class {\n\n    constructor(data) {\n        this.dataType = data.dataType;\n        this.shape = new message.TensorShape(data.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmessage.TensorShape = class {\n\n    constructor(data) {\n        this.dimensions = data.dimensions;\n    }\n\n    toString() {\n        return `[${this.dimensions}]`;\n    }\n};\n\nmessage.Tensor = class {\n\n    constructor(data) {\n        this.type = new message.TensorType(data.type);\n    }\n};\n\nmessage.Error = class extends Error {\n    constructor(message) {\n        super(message);\n        this.name = 'Message Error';\n    }\n};\n\nexport const ModelFactory = message.ModelFactory;\n"
  },
  {
    "path": "source/mlir-metadata.json",
    "content": "[\n  {\n    \"name\": \"acc.atomic.capture\",\n    \"summary\": \"performs an atomic capture\",\n    \"description\": \"This operation performs an atomic capture.\\n\\n    The region has the following allowed forms:\\n\\n    ```\\n      acc.atomic.capture {\\n        acc.atomic.update ...\\n        acc.atomic.read ...\\n        acc.terminator\\n      }\\n\\n      acc.atomic.capture {\\n        acc.atomic.read ...\\n        acc.atomic.update ...\\n        acc.terminator\\n      }\\n\\n      acc.atomic.capture {\\n        acc.atomic.read ...\\n        acc.atomic.write ...\\n        acc.terminator\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n    )\\n    $region attr-dict\"\n  },\n  {\n    \"name\": \"acc.atomic.read\",\n    \"summary\": \"performs an atomic read\",\n    \"description\": \"This operation performs an atomic read.\\n\\n    The operand `x` is the address from where the value is atomically read.\\n    The operand `v` is the address where the value is stored after reading.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"OpenACC_PointerLikeType\" },\n      { \"name\": \"v\", \"type\": \"OpenACC_PointerLikeType\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n    )\\n    $v `=` $x\\n    `:` type($v) `,` type($x) `,` $element_type\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.atomic.update\",\n    \"summary\": \"performs an atomic update\",\n    \"description\": \"This operation performs an atomic update.\\n\\n    The operand `x` is exactly the same as the operand `x` in the OpenACC\\n    Standard (OpenACC 3.3, section 2.12). It is the address of the variable\\n    that is being updated. `x` is atomically read/written.\\n\\n    The region describes how to update the value of `x`. It takes the value at\\n    `x` as an input and must yield the updated value. Only the update to `x` is\\n    atomic. Generally the region must have only one instruction, but can\\n    potentially have more than one instructions too. The update is sematically\\n    similar to a compare-exchange loop based atomic update.\\n\\n    The syntax of atomic update operation is different from atomic read and\\n    atomic write operations. This is because only the host dialect knows how to\\n    appropriately update a value. For example, while generating LLVM IR, if\\n    there are no special `atomicrmw` instructions for the operation-type\\n    combination in atomic update, a compare-exchange loop is generated, where\\n    the core update operation is directly translated like regular operations by\\n    the host dialect. The front-end must handle semantic checks for allowed\\n    operations.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"OpenACC_PointerLikeType\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n    )\\n    $x `:` type($x)\\n      $region attr-dict\"\n  },\n  {\n    \"name\": \"acc.atomic.write\",\n    \"summary\": \"performs an atomic write\",\n    \"description\": \"This operation performs an atomic write.\\n\\n    The operand `x` is the address to where the `expr` is atomically\\n    written w.r.t. multiple threads. The evaluation of `expr` need not be\\n    atomic w.r.t. the write to address. In general, the type(x) must\\n    dereference to type(expr).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"OpenACC_PointerLikeType\" },\n      { \"name\": \"expr\", \"type\": \"AnyType\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n    )\\n    $x `=` $expr\\n    `:` type($x) `,` type($expr)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.attach\",\n    \"summary\": \"Represents acc attach semantics which updates a pointer in device memory with the corresponding device address of the pointee.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_attach>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.bounds\",\n    \"summary\": \"Represents normalized bounds information for acc data clause.\",\n    \"description\": \"This operation is used to record bounds used in acc data clause in a\\n    normalized fashion (zero-based). This works well with the `PointerLikeType`\\n    requirement in data clauses - since a `lowerbound` of 0 means looking\\n    at data at the zero offset from pointer.\\n\\n    The operation must have an `upperbound` or `extent` (or both are allowed -\\n    but not checked for consistency). When the source language's arrays are\\n    not zero-based, the `startIdx` must specify the zero-position index.\\n\\n    The `stride` represents the distance between consecutive elements. For\\n    multi-dimensional arrays, the `stride` for each outer dimension must account\\n    for the complete size of all inner dimensions.\\n\\n    The `strideInBytes` flag indicates that the `stride` is specified in bytes\\n    rather than the number of elements.\\n\\n    Examples below show copying a slice of 10-element array except first element.\\n    Note that the examples use extent in data clause for C++ and upperbound\\n    for Fortran (as per 2.7.1). To simplify examples, the constants are used\\n    directly in the acc.bounds operands - this is not the syntax of operation.\\n\\n    C++:\\n    ```\\n    int array[10];\\n    #pragma acc copy(array[1:9])\\n    ```\\n    =>\\n    ```mlir\\n    acc.bounds lb(1) ub(9) extent(9) startIdx(0) stride(1)\\n    ```\\n\\n    Fortran:\\n    ```\\n    integer :: array(1:10)\\n    !$acc copy(array(2:10))\\n    ```\\n    =>\\n    ```mlir\\n    acc.bounds lb(1) ub(9) extent(9) startIdx(1) stride(1)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lowerbound\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"upperbound\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"extent\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"stride\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"startIdx\", \"type\": \"Optional<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"OpenACC_DataBoundsType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strideInBytes\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `lowerbound` `(` $lowerbound `:` type($lowerbound) `)`\\n      | `upperbound` `(` $upperbound `:` type($upperbound) `)`\\n      | `extent` `(` $extent `:` type($extent) `)`\\n      | `stride` `(` $stride `:` type($stride) `)`\\n      | `startIdx` `(` $startIdx `:` type($startIdx) `)`\\n    ) attr-dict\"\n  },\n  {\n    \"name\": \"acc.cache\",\n    \"summary\": \"Represents the cache directive that is associated with a loop.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_cache>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.compute_region\",\n    \"summary\": \"Compute region for GPU execution\",\n    \"description\": \"The `acc.compute_region` operation wraps a region of code that will be\\n    compiled and executed on a GPU. It is typically produced by lowering\\n    OpenACC compute constructs (`acc.parallel`, `acc.kernels`, `acc.serial`)\\n    but can also be targeted directly by other frontends or lowered from\\n    other constructs that benefit from the automatic parallelization and data\\n    mapping facilities that the `acc` dialect provides. It serves as the\\n    bridge between the high-level representation and the `gpu.launch`\\n    operation.\\n\\n    The operation is `IsolatedFromAbove`: all values used inside the\\n    region must be explicitly captured. Values are captured in two ways:\\n\\n    - Launch arguments (`launch`): Results of operations that define\\n      the parallel launch configuration. These are `!acc.par_width`-typed\\n      and become block arguments representing the parallel width for each\\n      dimension.\\n\\n    - Input arguments (`ins`): Arbitrary values captured from outside\\n      the region (data pointers, scalars, etc.). These become block\\n      arguments with their original types.\\n\\n    The `origin` attribute records which construct produced this compute\\n    region (e.g., `\\\"acc.parallel\\\"`, `\\\"acc.kernels\\\"`). This is intended to\\n    be solely informational.\\n\\n    Example:\\n\\n    ```mlir\\n    %w0 = acc.par_width %c128 {par_dim = #acc.par_dim<thread_x>}\\n    %w1 = acc.par_width %c8 {par_dim = #acc.par_dim<block_x>}\\n    acc.compute_region launch(%arg0 = %w0, %arg1 = %w1)\\n        ins(%arg2 = %data) : (memref<1024xf32>) {\\n      %c0 = arith.constant 0 : index\\n      %c1 = arith.constant 1 : index\\n      %c1024 = arith.constant 1024 : index\\n      scf.parallel (%iv) = (%c0) to (%c1024) step (%c1) {\\n        %v = memref.load %arg2[%iv] : memref<1024xf32>\\n        scf.reduce\\n      } {acc.par_dims = #acc<par_dims[thread_x]>}\\n      acc.yield\\n    } {origin = \\\"acc.parallel\\\"}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"launchArgs\", \"type\": \"Variadic<OpenACC_ParWidthType>\" },\n      { \"name\": \"inputArgs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"stream\", \"type\": \"Optional<OpenACC_GPUAsyncTokenType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"origin\", \"type\": \"StrAttr\" },\n      { \"name\": \"kernel_func_name\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"kernel_module_name\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"acc.copyin\",\n    \"summary\": \"Represents copyin semantics for acc data clauses like acc copyin and acc copy.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_copyin>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.copyout\",\n    \"summary\": \"Represents acc copyout semantics - reverse of copyin.\",\n    \"description\": \"- `varPtr`: The address of variable to copy back to.- `accVar`: The acc variable. This is the link from the data-entry\\n    operation used.\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, always, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data exit operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_copyout>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AccVar>($accVar, type($accVar))\\n    (`bounds` `(` $bounds^ `)` )?\\n    (`async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)^)?\\n    `to` custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.create\",\n    \"summary\": \"Represents create semantics for acc data clauses like acc create and acc copyout.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_create>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.data\",\n    \"summary\": \"data construct\",\n    \"description\": \"The \\\"acc.data\\\" operation represents a data construct. It defines vars to\\n    be allocated in the current device memory for the duration of the region,\\n    whether data should be copied from local memory to the current device\\n    memory upon region entry , and copied from device memory to local memory\\n    upon region exit.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.data present(%a: memref<10x10xf32>, %b: memref<10x10xf32>,\\n        %c: memref<10xf32>, %d: memref<10xf32>) {\\n      // data region\\n    }\\n    ```\\n\\n    `async` and `wait` operands are supported with `device_type` information.\\n    They should only be accessed by the extra provided getters. If modified,\\n    the corresponding `device_type` attributes must be modified as well.\",\n    \"operands\": [\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"waitOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"waitOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"hasWaitDevnum\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" },\n      { \"name\": \"waitOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"defaultAttr\", \"type\": \"OptionalAttr<DefaultValueAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n      | `wait` `` custom<WaitClause>($waitOperands, type($waitOperands),\\n          $waitOperandsDeviceType, $waitOperandsSegments, $hasWaitDevnum,\\n          $waitOnly)\\n    )\\n    $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.declare\",\n    \"summary\": \"declare implicit region\",\n    \"description\": \"The \\\"acc.declare\\\" operation represents an implicit declare region in\\n    function (and subroutine in Fortran).\\n\\n    Example:\\n\\n    ```mlir\\n    %pa = acc.present varPtr(%a : memref<10x10xf32>) -> memref<10x10xf32>\\n    acc.declare dataOperands(%pa: memref<10x10xf32>) {\\n      // implicit region\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.declare_device_resident\",\n    \"summary\": \"Represents acc declare device_resident semantics.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_declare_device_resident>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.declare_enter\",\n    \"summary\": \"declare directive - entry to implicit data region\",\n    \"description\": \"The \\\"acc.declare_enter\\\" operation represents the OpenACC declare directive\\n    and captures the entry semantics to the implicit data region.\\n    This operation is modeled similarly to \\\"acc.enter_data\\\".\\n\\n    Example showing `acc declare create(a)`:\\n\\n    ```mlir\\n    %0 = acc.create varPtr(%a : !llvm.ptr) -> !llvm.ptr\\n    acc.declare_enter dataOperands(%0 : !llvm.ptr)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"OpenACC_DeclareTokenType\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    )\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.declare_exit\",\n    \"summary\": \"declare directive - exit from implicit data region\",\n    \"description\": \"The \\\"acc.declare_exit\\\" operation represents the OpenACC declare directive\\n    and captures the exit semantics from the implicit data region.\\n    This operation is modeled similarly to \\\"acc.exit_data\\\".\\n\\n    Example showing `acc declare device_resident(a)`:\\n\\n    ```mlir\\n    %0 = acc.getdeviceptr varPtr(%a : !llvm.ptr) -> !llvm.ptr {dataClause = #acc<data_clause declare_device_resident>}\\n    acc.declare_exit dataOperands(%0 : !llvm.ptr)\\n    acc.delete accPtr(%0 : !llvm.ptr) {dataClause = #acc<data_clause declare_device_resident>}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"Optional<OpenACC_DeclareTokenType>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `token` `(` $token `)` |\\n        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    )\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.declare_link\",\n    \"summary\": \"Represents acc declare link semantics.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_declare_link>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.delete\",\n    \"summary\": \"Represents acc delete semantics - reverse of create.\",\n    \"description\": \"- `accVar`: The acc variable. This is the link from the data-entry\\n    operation used.\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, always, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data exit operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_delete>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AccVar>($accVar, type($accVar))\\n    (`bounds` `(` $bounds^ `)` )?\\n    (`async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.detach\",\n    \"summary\": \"Represents acc detach semantics - reverse of attach.\",\n    \"description\": \"- `accVar`: The acc variable. This is the link from the data-entry\\n    operation used.\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, always, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data exit operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_detach>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AccVar>($accVar, type($accVar))\\n    (`bounds` `(` $bounds^ `)` )?\\n    (`async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.deviceptr\",\n    \"summary\": \"Specifies that the variable pointer is a device pointer.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_deviceptr>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.enter_data\",\n    \"summary\": \"enter data operation\",\n    \"description\": \"The \\\"acc.enter_data\\\" operation represents the OpenACC enter data directive.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.enter_data create(%d1 : memref<10xf32>) attributes {async}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"asyncOperand\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"waitDevnum\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"async\", \"type\": \"UnitAttr\" },\n      { \"name\": \"wait\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n      | `async` `` custom<OperandWithKeywordOnly>($asyncOperand,\\n            type($asyncOperand), $async)\\n      | `wait_devnum` `(` $waitDevnum `:` type($waitDevnum) `)`\\n      | `wait` `` custom<OperandsWithKeywordOnly>($waitOperands,\\n            type($waitOperands), $wait)\\n      | `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    )\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.exit_data\",\n    \"summary\": \"exit data operation\",\n    \"description\": \"The \\\"acc.exit_data\\\" operation represents the OpenACC exit data directive.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.exit_data delete(%d1 : memref<10xf32>) attributes {async}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"asyncOperand\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"waitDevnum\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"async\", \"type\": \"UnitAttr\" },\n      { \"name\": \"wait\", \"type\": \"UnitAttr\" },\n      { \"name\": \"finalize\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n      | `async` `` custom<OperandWithKeywordOnly>($asyncOperand,\\n            type($asyncOperand), $async)\\n      | `wait_devnum` `(` $waitDevnum `:` type($waitDevnum) `)`\\n      | `wait` `` custom<OperandsWithKeywordOnly>($waitOperands,\\n            type($waitOperands), $wait)\\n      | `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    )\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.firstprivate\",\n    \"summary\": \"Represents firstprivate semantic for the acc firstprivate clause.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_firstprivate>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.firstprivate_map\",\n    \"summary\": \"Represents the mapping of the initial value for firstprivate semantics.\",\n    \"description\": \"The `acc.firstprivate_map` operation is an intermediate representation\\n    used during the decomposition of `acc.firstprivate` operations. It\\n    represents the mapping of the initial value from the host to the device,\\n    which is then used to initialize per-thread private copies.\\n\\n    This operation is distinct from `acc.copyin` because:\\n    - `acc.copyin` includes present counter updates, but private variables\\n      do not impact reference counters\\n    - The mapped value is used to initialize private copies rather than\\n      being accessed directly\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_firstprivate>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.firstprivate.recipe\",\n    \"summary\": \"privatization recipe\",\n    \"description\": \"Declares an OpenACC privatization recipe with copy of the initial value.\\n    The operation requires two mandatory regions and one optional.\\n\\n      1. The initializer region specifies how to allocate and initialize a new\\n         private value. For example in Fortran, a derived-type might have a\\n         default initialization. The region has an argument that contains the\\n         original value that needs to be privatized, followed by bounds arguments\\n         (if any) in order from innermost to outermost dimension. The region must\\n         yield the privatized copy.\\n      2. The copy region specifies how to copy the initial value to the newly\\n         created private value. It takes the original value, the privatized\\n         value, followed by bounds arguments (if any) in the same order.\\n      3. The destroy region specifies how to destruct the value when it reaches\\n         its end of life. It takes the original value, the privatized value, and\\n         bounds arguments (if any) in the same order. It is optional.\\n\\n    A single privatization recipe can be used for multiple operand if they have\\n    the same type and do not require a specific default initialization.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.firstprivate.recipe @firstprivate_memref : memref<10x20xf32> init {\\n    ^bb0(%original: memref<10x20xf32>):\\n      // init region contains a sequence of operations to create and\\n      // initialize the copy. It yields the privatized copy.\\n      %alloca = memref.alloca() : memref<10x20xf32>\\n      acc.yield %alloca : memref<10x20xf32>\\n    } copy {\\n    ^bb0(%original: memref<10x20xf32>, %privatized: memref<10x20xf32>):\\n      // copy region contains a sequence of operations to copy the initial value\\n      // of the firstprivate value to the newly created value.\\n      memref.copy %original, %privatized : memref<10x20xf32> to memref<10x20xf32>\\n      acc.terminator\\n    } destroy {\\n    ^bb0(%original: memref<10x20xf32>, %privatized: memref<10x20xf32>):\\n      // destroy region is empty since alloca is automatically cleaned up\\n      acc.terminator\\n    }\\n\\n    // Example with bounds for array slicing:\\n    acc.firstprivate.recipe @firstprivate_slice : memref<10x20xf32> init {\\n    ^bb0(%original: memref<10x20xf32>, %bounds_inner: !acc.data_bounds_ty, %bounds_outer: !acc.data_bounds_ty):\\n      // Extract bounds and create appropriately sized allocation\\n      %extent_inner = acc.get_extent %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %extent_outer = acc.get_extent %bounds_outer : (!acc.data_bounds_ty) -> index\\n      %slice_alloc = memref.alloca(%extent_outer, %extent_inner) : memref<?x?xf32>\\n      // ... base pointer adjustment logic ...\\n      acc.yield %result : memref<10x20xf32>\\n    } copy {\\n    ^bb0(%original: memref<10x20xf32>, %privatized: memref<10x20xf32>, %bounds_inner: !acc.data_bounds_ty, %bounds_outer: !acc.data_bounds_ty):\\n      // Copy the slice portion from original to privatized\\n      %lb_inner = acc.get_lowerbound %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %lb_outer = acc.get_lowerbound %bounds_outer : (!acc.data_bounds_ty) -> index\\n      %extent_inner = acc.get_extent %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %extent_outer = acc.get_extent %bounds_outer : (!acc.data_bounds_ty) -> index\\n      %subview = memref.subview %original[%lb_outer, %lb_inner][%extent_outer, %extent_inner][1, 1]\\n        : memref<10x20xf32> to memref<?x?xf32, strided<[20, 1], offset: ?>>\\n      // Copy subview to privatized...\\n      acc.terminator\\n    }\\n\\n    // The privatization symbol is then used in the corresponding operation.\\n    acc.parallel firstprivate(@firstprivate_memref -> %a : memref<10x20xf32>) {\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"copyRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"destroyRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `:` $type attr-dict-with-keyword `init` $initRegion\\n    `copy` $copyRegion\\n    (`destroy` $destroyRegion^)?\"\n  },\n  {\n    \"name\": \"acc.get_extent\",\n    \"summary\": \"Extract extent from OpenACC data bounds.\",\n    \"description\": \"This operation extracts the extent value from an `acc.bounds` value.\\n    If the data bounds does not have an extent specified, it is computed\\n    from the upperbound.\\n\\n    Example:\\n    ```mlir\\n    %extent = acc.get_extent %bounds : (!acc.data_bounds_ty) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"bounds\", \"type\": \"OpenACC_DataBoundsType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$bounds attr-dict `:` `(` type($bounds) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"acc.get_lowerbound\",\n    \"summary\": \"Extract lowerbound from OpenACC data bounds.\",\n    \"description\": \"This operation extracts the lowerbound value from an `acc.bounds` value.\\n    If the data bounds does not have a lowerbound specified, it means it is zero.\\n\\n    Example:\\n    ```mlir\\n    %lb = acc.get_lowerbound %bounds : (!acc.data_bounds_ty) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"bounds\", \"type\": \"OpenACC_DataBoundsType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$bounds attr-dict `:` `(` type($bounds) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"acc.get_stride\",\n    \"summary\": \"Extract stride from OpenACC data bounds.\",\n    \"description\": \"This operation extracts the stride value from an `acc.bounds` value.\\n    If the data bounds does not have a stride specified, it defaults to 1.\\n\\n    Example:\\n    ```mlir\\n    %stride = acc.get_stride %bounds : (!acc.data_bounds_ty) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"bounds\", \"type\": \"OpenACC_DataBoundsType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$bounds attr-dict `:` `(` type($bounds) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"acc.get_upperbound\",\n    \"summary\": \"Extract upperbound from OpenACC data bounds.\",\n    \"description\": \"This operation extracts the upperbound value from an `acc.bounds` value.\\n    If the data bounds does not have an upperbound specified, this operation\\n    uses the extent to compute it.\\n\\n    Example:\\n    ```mlir\\n    %ub = acc.get_upperbound %bounds : (!acc.data_bounds_ty) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"bounds\", \"type\": \"OpenACC_DataBoundsType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$bounds attr-dict `:` `(` type($bounds) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"acc.getdeviceptr\",\n    \"summary\": \"Gets device address if variable exists on device.\",\n    \"description\": \"This operation is used to get the `accPtr` for a variable. This is often\\n      used in conjunction with data exit operations when the data entry\\n      operation is not visible. This operation can have a `dataClause` argument\\n      that is any of the valid `mlir::acc::DataClause` entries.\\n      \\\\Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_getdeviceptr>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.global_ctor\",\n    \"summary\": \"Used to hold construction operations associated with globals such as declare\",\n    \"description\": \"The \\\"acc.global_ctor\\\" operation is used to capture OpenACC actions to apply\\n    on globals (such as `acc declare`) at the entry to the implicit data region.\\n    This operation is isolated and intended to be used in a module.\\n\\n    Example showing `declare create` of global:\\n\\n    ```mlir\\n    llvm.mlir.global external @globalvar() : i32 {\\n      %0 = llvm.mlir.constant(0 : i32) : i32\\n      llvm.return %0 : i32\\n    }\\n    acc.global_ctor @acc_constructor {\\n      %0 = llvm.mlir.addressof @globalvar : !llvm.ptr\\n      %1 = acc.create varPtr(%0 : !llvm.ptr) -> !llvm.ptr\\n      acc.declare_enter dataOperands(%1 : !llvm.ptr)\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.global_dtor\",\n    \"summary\": \"Used to hold destruction operations associated with globals such as declare\",\n    \"description\": \"The \\\"acc.global_dtor\\\" operation is used to capture OpenACC actions to apply\\n    on globals (such as `acc declare`) at the exit from the implicit data\\n    region. This operation is isolated and intended to be used in a module.\\n\\n    Example showing delete associated with `declare create` of global:\\n\\n    ```mlir\\n    llvm.mlir.global external @globalvar() : i32 {\\n      %0 = llvm.mlir.constant(0 : i32) : i32\\n      llvm.return %0 : i32\\n    }\\n    acc.global_dtor @acc_destructor {\\n      %0 = llvm.mlir.addressof @globalvar : !llvm.ptr\\n      %1 = acc.getdeviceptr varPtr(%0 : !llvm.ptr) -> !llvm.ptr {dataClause = #acc<data_clause create>}\\n      acc.declare_exit dataOperands(%1 : !llvm.ptr)\\n      acc.delete accPtr(%1 : !llvm.ptr) {dataClause = #acc<data_clause create>}\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.host_data\",\n    \"summary\": \"host_data construct\",\n    \"description\": \"The \\\"acc.host_data\\\" operation represents the OpenACC host_data construct.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = acc.use_device varPtr(%a : !llvm.ptr) -> !llvm.ptr\\n    acc.host_data dataOperands(%0 : !llvm.ptr) {\\n\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ifPresent\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n      | `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    )\\n    $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.init\",\n    \"summary\": \"init operation\",\n    \"description\": \"The \\\"acc.init\\\" operation represents the OpenACC init executable\\n    directive.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.init\\n    acc.init device_num(%dev1 : i32)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"deviceNum\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_types\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}, Device type attributes>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(`device_num` `(` $deviceNum `:` type($deviceNum) `)`\\n      | `if` `(` $ifCond `)`\\n    ) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.kernel_environment\",\n    \"summary\": \"Decomposition of compute constructs to capture data mapping and asynchronous behavior information\",\n    \"description\": \"The `acc.kernel_environment` operation represents a decomposition of\\n    any OpenACC compute construct (acc.kernels, acc.parallel, or\\n    acc.serial) that captures data mapping and asynchronous behavior:\\n    - data clause operands\\n    - async clause operands\\n    - wait clause operands\\n\\n    This allows kernel execution parallelism and privatization to be\\n    handled separately, facilitating eventual lowering to GPU dialect where\\n    kernel launching and compute offloading are handled separately.\",\n    \"operands\": [\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"waitOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"waitOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"hasWaitDevnum\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" },\n      { \"name\": \"waitOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `wait` `` custom<WaitClause>($waitOperands, type($waitOperands),\\n          $waitOperandsDeviceType, $waitOperandsSegments, $hasWaitDevnum,\\n          $waitOnly)\\n    )\\n    $region attr-dict\"\n  },\n  {\n    \"name\": \"acc.kernels\",\n    \"summary\": \"kernels construct\",\n    \"description\": \"The \\\"acc.kernels\\\" operation represents a kernels construct block. It has\\n    one region to be compiled into a sequence of kernels for execution on the\\n    current device.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.kernels num_gangs(%c10) num_workers(%c10)\\n        private(%c : memref<10xf32>) {\\n      // kernels region\\n    }\\n    ```\\n\\n    `collapse`, `gang`, `worker`, `vector`, `seq`, `independent`, `auto` and\\n    `tile` operands are supported with `device_type` information. They should\\n    only be accessed by the extra provided getters. If modified, the\\n    corresponding `device_type` attributes must be modified as well.\",\n    \"operands\": [\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"numGangs\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"numWorkers\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"vectorLength\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"selfCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"reductionOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"privateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"firstprivateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"waitOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"waitOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"hasWaitDevnum\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" },\n      { \"name\": \"waitOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"numGangsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"numGangsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"numWorkersDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"vectorLengthDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"selfAttr\", \"type\": \"UnitAttr\" },\n      { \"name\": \"defaultAttr\", \"type\": \"OptionalAttr<DefaultValueAttr>\" },\n      { \"name\": \"combined\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"( `combined` `(` `loop` `)` $combined^)?\\n    oilist(\\n        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `firstprivate` `(` $firstprivateOperands `:` type($firstprivateOperands) `)`\\n      | `num_gangs` `(` custom<NumGangs>($numGangs,\\n            type($numGangs), $numGangsDeviceType, $numGangsSegments) `)`\\n      | `num_workers` `(` custom<DeviceTypeOperands>($numWorkers,\\n            type($numWorkers), $numWorkersDeviceType) `)`\\n      | `private` `(` $privateOperands `:` type($privateOperands) `)`\\n      | `vector_length` `(` custom<DeviceTypeOperands>($vectorLength,\\n            type($vectorLength), $vectorLengthDeviceType) `)`\\n      | `wait` `` custom<WaitClause>($waitOperands, type($waitOperands),\\n          $waitOperandsDeviceType, $waitOperandsSegments, $hasWaitDevnum,\\n          $waitOnly)\\n      | `self` `(` $selfCond `)`\\n      | `if` `(` $ifCond `)`\\n      | `reduction` `(` $reductionOperands `:` type($reductionOperands) `)`\\n    )\\n    $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.loop\",\n    \"summary\": \"loop construct\",\n    \"description\": \"The `acc.loop` operation represents the OpenACC loop construct and when\\n    bounds are included, the associated source language loop iterators. The\\n    lower and upper bounds specify a half-open range: the range includes the\\n    lower bound but does not include the upper bound. If the `inclusive`\\n    attribute is set then the upper bound is included.\\n\\n    In cases where the OpenACC loop directive needs to capture multiple\\n    source language loops, such as in the case of `collapse` or `tile`,\\n    the multiple induction arguments are used to capture each case. Having\\n    such a representation makes sure no intermediate transformation such\\n    as Loop Invariant Code Motion breaks the property requested by the\\n    clause on the loop constructs.\\n\\n    Each `acc.loop` holds private and reduction operands which are the\\n    ssa values from the corresponding `acc.private` or `acc.reduction`\\n    operations. Additionally, firstprivate operands are supported to\\n    represent cases where privatization is needed with initialization\\n    from an original value. While the OpenACC specification does not\\n    explicitly support firstprivate on loop constructs, this extension\\n    enables representing privatization scenarios that arise from an\\n    optimization and codegen pipeline operating on acc dialect.\\n\\n    The operation supports capturing information that it comes combined\\n    constructs (e.g., `parallel loop`, `kernels loop`, `serial loop`)\\n    through the `combined` attribute despite requiring the `acc.loop`\\n    to be decomposed from the compute operation representing compute\\n    construct.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.loop gang() vector() (%arg3 : index, %arg4 : index, %arg5 : index) =\\n        (%c0, %c0, %c0 : index, index, index) to \\n        (%c10, %c10, %c10 : index, index, index) step \\n        (%c1, %c1, %c1 : index, index, index) {\\n      // Loop body\\n      acc.yield\\n    } attributes { collapse = [3] }\\n    ```\\n\\n    `collapse`, `gang`, `worker`, `vector`, `seq`, `independent`, `auto`,\\n    `cache`, and `tile` operands are supported with `device_type`\\n    information. These clauses should only be accessed through the provided\\n    device-type-aware getter methods. When modifying these operands, the\\n    corresponding `device_type` attributes must be updated to maintain\\n    consistency between operands and their target device types.\\n\\n    The `unstructured` attribute indicates that the loops inside the OpenACC\\n    construct contain early exits and cannot be lowered to structured MLIR\\n    operations. When this flag is set, the acc.loop should have no induction\\n    variables and the loop must be implemented via explicit control flow\\n    inside its body.\",\n    \"operands\": [\n      { \"name\": \"lowerbound\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"upperbound\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"step\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"gangOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"workerNumOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"vectorOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"tileOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"cacheOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"privateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"firstprivateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"reductionOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inclusiveUpperbound\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"collapse\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"collapseDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"gangOperandsArgType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_GangArgTypeAttr{Num|Dim|Static}>>\" },\n      { \"name\": \"gangOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"gangOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"workerNumOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"vectorOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"seq\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"independent\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"auto_\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"gang\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"worker\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"vector\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"tileOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"tileOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"combined\", \"type\": \"OptionalAttr<OpenACC_CombinedConstructsAttr{kernels_loop|parallel_loop|serial_loop}>\" },\n      { \"name\": \"unstructured\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"( `combined` `(` custom<CombinedConstructsLoop>($combined)^ `)` )?\\n    oilist(\\n        `gang` `` custom<GangClause>($gangOperands, type($gangOperands),\\n            $gangOperandsArgType, $gangOperandsDeviceType,\\n            $gangOperandsSegments, $gang)\\n      | `worker` `` custom<DeviceTypeOperandsWithKeywordOnly>(\\n            $workerNumOperands, type($workerNumOperands),\\n            $workerNumOperandsDeviceType, $worker)\\n      | `vector` `` custom<DeviceTypeOperandsWithKeywordOnly>($vectorOperands,\\n            type($vectorOperands), $vectorOperandsDeviceType, $vector)\\n      | `private` `(` $privateOperands `:` type($privateOperands) `)`\\n      | `firstprivate` `(` $firstprivateOperands `:` type($firstprivateOperands) `)`\\n      | `tile` `(` custom<DeviceTypeOperandsWithSegment>($tileOperands,\\n            type($tileOperands), $tileOperandsDeviceType, $tileOperandsSegments)\\n        `)`\\n      | `reduction` `(` $reductionOperands  `:` type($reductionOperands) `)`\\n      | `cache` `(` $cacheOperands `:` type($cacheOperands) `)`\\n    )\\n    custom<LoopControl>($region, $lowerbound, type($lowerbound), $upperbound,\\n        type($upperbound), $step, type($step))\\n    ( `(` type($results)^ `)` )?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"acc.nocreate\",\n    \"summary\": \"Represents acc no_create semantics.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_no_create>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.par_width\",\n    \"summary\": \"Specify parallel width for a GPU dimension\",\n    \"description\": \"The `acc.par_width` operation specifies the parallel width for a\\n    given GPU parallel dimension. It is used as an input to\\n    `acc.compute_region` to define the launch configuration.\\n\\n    The optional `launchArg` operand provides a known width value. When\\n    absent, the width is unknown and must be determined later (either at\\n    compile time by analysis or at runtime).\\n\\n    Examples:\\n\\n    ```mlir\\n    // Known width from SSA value\\n    %w1 = acc.par_width %vector_len {par_dim = #acc.par_dim<thread_x>}\\n\\n    // Unknown width (to be computed later)\\n    %w2 = acc.par_width {par_dim = #acc.par_dim<block_x>}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"launchArg\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"OpenACC_ParWidthType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"par_dim\", \"type\": \"OpenACC_GPUParallelDimAttr\" }\n    ],\n    \"assemblyFormat\": \"($launchArg^)? attr-dict\"\n  },\n  {\n    \"name\": \"acc.parallel\",\n    \"summary\": \"parallel construct\",\n    \"description\": \"The \\\"acc.parallel\\\" operation represents a parallel construct block. It has\\n    one region to be executed in parallel on the current device.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.parallel num_gangs(%c10) num_workers(%c10)\\n        private(%c : memref<10xf32>) {\\n      // parallel region\\n    }\\n    ```\\n\\n    `async`, `wait`, `num_gangs`, `num_workers` and `vector_length` operands are\\n    supported with `device_type` information. They should only be accessed by\\n    the extra provided getters. If modified, the corresponding `device_type`\\n    attributes must be modified as well.\",\n    \"operands\": [\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"numGangs\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"numWorkers\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"vectorLength\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"selfCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"reductionOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"privateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"firstprivateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"waitOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"waitOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"hasWaitDevnum\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" },\n      { \"name\": \"waitOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"numGangsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"numGangsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"numWorkersDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"vectorLengthDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"selfAttr\", \"type\": \"UnitAttr\" },\n      { \"name\": \"defaultAttr\", \"type\": \"OptionalAttr<DefaultValueAttr>\" },\n      { \"name\": \"combined\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"( `combined` `(` `loop` `)` $combined^)?\\n    oilist(\\n        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `firstprivate` `(` $firstprivateOperands `:` type($firstprivateOperands) `)`\\n      | `num_gangs` `(` custom<NumGangs>($numGangs,\\n            type($numGangs), $numGangsDeviceType, $numGangsSegments) `)`\\n      | `num_workers` `(` custom<DeviceTypeOperands>($numWorkers,\\n            type($numWorkers), $numWorkersDeviceType) `)`\\n      | `private` `(` $privateOperands `:` type($privateOperands) `)`\\n      | `vector_length` `(` custom<DeviceTypeOperands>($vectorLength,\\n            type($vectorLength), $vectorLengthDeviceType) `)`\\n      | `wait` `` custom<WaitClause>($waitOperands, type($waitOperands),\\n          $waitOperandsDeviceType, $waitOperandsSegments, $hasWaitDevnum,\\n          $waitOnly)\\n      | `self` `(` $selfCond `)`\\n      | `if` `(` $ifCond `)`\\n      | `reduction` `(` $reductionOperands `:` type($reductionOperands) `)`\\n    )\\n    $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.present\",\n    \"summary\": \"Specifies that the variable is already present on device.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_present>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.private\",\n    \"summary\": \"Represents private semantics for acc private clause.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_private>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.private.recipe\",\n    \"summary\": \"privatization recipe\",\n    \"description\": \"Declares an OpenACC privatization recipe. The operation requires one\\n    mandatory and one optional region.\\n\\n      1. The initializer region specifies how to allocate and initialize a new\\n         private value. For example in Fortran, a derived-type might have a\\n         default initialization. The region has an argument that contains the\\n         original value that needs to be privatized, followed by bounds arguments\\n         (if any) in order from innermost to outermost dimension. The region\\n         must yield the privatized copy.\\n      2. The destroy region specifies how to destruct the value when it reaches\\n         its end of life. It takes the original value, the privatized value, and\\n         bounds arguments (if any) in the same order as the init region.\\n\\n    A single privatization recipe can be used for multiple operand if they have\\n    the same type and do not require a specific default initialization.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.private.recipe @privatization_memref : memref<10x20xf32> init {\\n    ^bb0(%original: memref<10x20xf32>):\\n      // init region contains a sequence of operations to create and\\n      // initialize the copy. It yields the privatized copy.\\n      %alloca = memref.alloca() : memref<10x20xf32>\\n      acc.yield %alloca : memref<10x20xf32>\\n    } destroy {\\n    ^bb0(%original: memref<10x20xf32>, %privatized: memref<10x20xf32>):\\n      // destroy region is empty since alloca is automatically cleaned up\\n      acc.terminator\\n    }\\n\\n    // Example with bounds for array slicing:\\n    acc.private.recipe @privatization_slice : memref<10x20xf32> init {\\n    ^bb0(%original: memref<10x20xf32>, %bounds_inner: !acc.data_bounds_ty, %bounds_outer: !acc.data_bounds_ty):\\n      // Extract bounds and create appropriately sized allocation\\n      %extent_inner = acc.get_extent %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %extent_outer = acc.get_extent %bounds_outer : (!acc.data_bounds_ty) -> index\\n      %slice_alloc = memref.alloca(%extent_outer, %extent_inner) : memref<?x?xf32>\\n      // ... base pointer adjustment logic ...\\n      acc.yield %result : memref<10x20xf32>\\n    } destroy {\\n    ^bb0(%original: memref<10x20xf32>, %privatized: memref<10x20xf32>, %bounds_inner: !acc.data_bounds_ty, %bounds_outer: !acc.data_bounds_ty):\\n      // Cleanup is automatic for alloca-based allocations\\n      acc.terminator\\n    }\\n\\n    // The privatization symbol is then used in the corresponding operation.\\n    acc.parallel private(@privatization_memref -> %a : memref<10x20xf32>) {\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"destroyRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `:` $type attr-dict-with-keyword `init` $initRegion\\n    (`destroy` $destroyRegion^)?\"\n  },\n  {\n    \"name\": \"acc.reduction\",\n    \"summary\": \"Represents reduction semantics for acc reduction clause.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_reduction>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.reduction_combine\",\n    \"summary\": \"Combine a reduction partial sum with its original value\",\n    \"description\": \"This operation is a composite to do a typical update of a reduction\\n    variable. The intention of this operator is to facilitate codegen\\n    decisions (such as generate an atomic update). E.g.\\n\\n    ```\\n      acc.reduction_combine %src into %dest <addi> : memref<i32>\\n    ```\\n\\n    Might lower to something similar to\\n\\n    ```\\n      %loadSrc = memref.load %src[] : memref<i32>\\n      %loadDest = memref.load %dest[] : memref<i32>\\n      %combine = arith.addi %loadSrc, %loadDest : i32\\n      memref.store %combine, %dest[] : memref<i32>\\n    ```\\n    \\n    The $destMemref operand is a \\\"pointer\\\" to the original reduction \\n    variable (typically shared). The $srcMemref operand is a \\\"pointer\\\"\\n    to the partial sum of the reduction (typically private).\\n\\n    The $kind is the OpenACC reduction operator that determines how to \\n    accumulate the two values.\",\n    \"operands\": [\n      { \"name\": \"destMemref\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"srcMemref\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reductionOperator\", \"type\": \"OpenACC_ReductionOperatorAttr{none|add|mul|max|min|iand|ior|xor|eqv|neqv|land|lor|maximumf|minimumf|maxnumf|minnumf}\" }\n    ],\n    \"assemblyFormat\": \"$srcMemref `into` $destMemref $reductionOperator `:` type($destMemref) attr-dict\"\n  },\n  {\n    \"name\": \"acc.reduction_combine_region\",\n    \"summary\": \"Combine a reduction private value with its original (recipe)\",\n    \"description\": \"This operation provides materialized reduction combine code from an\\n    OpenACC reduction recipe. The region takes the partially reduced value(s)\\n    from the private reduction variable and combines them with the current\\n    value(s) in the original/shared reduction variable. The region is\\n    terminated by `acc.yield` with no operands.\\n\\n    The destVar operand is the original/shared reduction variable.\\n    The srcVar operand is typically the result of acc.reduction_init.\",\n    \"operands\": [\n      { \"name\": \"destVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"srcVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$srcVar `into` $destVar `:` type($srcVar) $region\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.reduction_init\",\n    \"summary\": \"Allocate and initialize a reduction variable from a recipe\",\n    \"description\": \"This operation provides materialized allocation and initialization for a\\n    private reduction variable from an OpenACC reduction recipe. The region\\n    contains the recipe's init code and must yield a single value (the private\\n    reduction storage) via `acc.yield`.\\n\\n    The var operand is the original/shared reduction variable. The\\n    reduction_operator specifies the reduction kind (e.g. add, mul).\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reductionOperator\", \"type\": \"OpenACC_ReductionOperatorAttr{none|add|mul|max|min|iand|ior|xor|eqv|neqv|land|lor|maximumf|minimumf|maxnumf|minnumf}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$var $reductionOperator `:` type($result) $region attr-dict\"\n  },\n  {\n    \"name\": \"acc.reduction.recipe\",\n    \"summary\": \"reduction recipe\",\n    \"description\": \"Declares an OpenACC reduction recipe. The operation requires two\\n    mandatory regions and one optional region.\\n\\n      1. The initializer region specifies how to initialize the local reduction\\n         value. The region has a first argument that contains the original value\\n         that needs to be reduced, followed by bounds arguments (if any) in order\\n         from innermost to outermost dimension. It is expected to `acc.yield` the\\n         initialized reduction value.\\n      2. The combiner region contains a sequence of operations to combine two\\n         values of the reduction type into one. It has the first reduction value,\\n         the second reduction value, followed by bounds arguments (if any) in the\\n         same order. It is expected to `acc.yield` the combined value.\\n      3. The optional destroy region specifies how to destruct the value when it\\n         reaches its end of life. It takes the original value, the reduction value,\\n         and bounds arguments (if any) in the same order.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.reduction.recipe @reduction_add_memref : memref<10x20xf32> reduction_operator<add> init {\\n    ^bb0(%original: memref<10x20xf32>):\\n      // init region contains a sequence of operations to initialize the local\\n      // reduction value as specified in 2.5.15\\n      %alloca = memref.alloca() : memref<10x20xf32>\\n      %cst = arith.constant 0.0 : f32\\n      linalg.fill ins(%cst : f32) outs(%alloca : memref<10x20xf32>)\\n      acc.yield %alloca : memref<10x20xf32>\\n    } combiner {\\n    ^bb0(%lhs: memref<10x20xf32>, %rhs: memref<10x20xf32>):\\n      // combiner region contains a sequence of operations to combine\\n      // two values into one.\\n      linalg.add ins(%lhs, %rhs : memref<10x20xf32>, memref<10x20xf32>)\\n                 outs(%lhs : memref<10x20xf32>)\\n      acc.yield %lhs : memref<10x20xf32>\\n    } destroy {\\n    ^bb0(%original: memref<10x20xf32>, %reduction: memref<10x20xf32>):\\n      // destroy region is empty since alloca is automatically cleaned up\\n      acc.terminator\\n    }\\n\\n    // Example with bounds for array slicing:\\n    acc.reduction.recipe @reduction_add_slice : memref<10x20xf32> reduction_operator<add> init {\\n    ^bb0(%original: memref<10x20xf32>, %bounds_inner: !acc.data_bounds_ty, %bounds_outer: !acc.data_bounds_ty):\\n      // Extract bounds and create appropriately sized allocation\\n      %extent_inner = acc.get_extent %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %extent_outer = acc.get_extent %bounds_outer : (!acc.data_bounds_ty) -> index\\n      %slice_alloc = memref.alloca(%extent_outer, %extent_inner) : memref<?x?xf32>\\n      %cst = arith.constant 0.0 : f32\\n      linalg.fill ins(%cst : f32) outs(%slice_alloc : memref<?x?xf32>)\\n      // ... base pointer adjustment logic ...\\n      acc.yield %result : memref<10x20xf32>\\n    } combiner {\\n    ^bb0(%lhs: memref<10x20xf32>, %rhs: memref<10x20xf32>, %bounds_inner: !acc.data_bounds_ty, %bounds_outer: !acc.data_bounds_ty):\\n      // Extract bounds to operate only on the slice portion\\n      %lb_inner = acc.get_lowerbound %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %lb_outer = acc.get_lowerbound %bounds_outer : (!acc.data_bounds_ty) -> index\\n      %extent_inner = acc.get_extent %bounds_inner : (!acc.data_bounds_ty) -> index\\n      %extent_outer = acc.get_extent %bounds_outer : (!acc.data_bounds_ty) -> index\\n\\n      // Create subviews to access only the slice portions\\n      %lhs_slice = memref.subview %lhs[%lb_outer, %lb_inner][%extent_outer, %extent_inner][1, 1]\\n        : memref<10x20xf32> to memref<?x?xf32, strided<[20, 1], offset: ?>>\\n      %rhs_slice = memref.subview %rhs[%lb_outer, %lb_inner][%extent_outer, %extent_inner][1, 1]\\n        : memref<10x20xf32> to memref<?x?xf32, strided<[20, 1], offset: ?>>\\n\\n      // Combine only the slice portions\\n      linalg.add ins(%lhs_slice, %rhs_slice : memref<?x?xf32, strided<[20, 1], offset: ?>>, memref<?x?xf32, strided<[20, 1], offset: ?>>)\\n                 outs(%lhs_slice : memref<?x?xf32, strided<[20, 1], offset: ?>>)\\n      acc.yield %lhs : memref<10x20xf32>\\n    }\\n\\n    // The reduction symbol is then used in the corresponding operation.\\n    acc.parallel reduction(@reduction_add_memref -> %a : memref<10x20xf32>) {\\n    }\\n    ```\\n\\n    The following table lists the valid operators and the initialization values\\n    according to OpenACC 3.3:\\n\\n    |------------------------------------------------|\\n    |        C/C++          |        Fortran         |\\n    |-----------------------|------------------------|\\n    | operator | init value | operator | init value  |\\n    |     +    |      0     |     +    |      0      |\\n    |     *    |      1     |     *    |      1      |\\n    |    max   |    least   |    max   |    least    |\\n    |    min   |   largest  |    min   |   largest   |\\n    |     &    |     ~0     |   iand   | all bits on |\\n    |     |    |      0     |    ior   |      0      |\\n    |     ^    |      0     |   ieor   |      0      |\\n    |    &&    |      1     |   .and.  |    .true.   |\\n    |    ||    |      0     |    .or.  |   .false.   |\\n    |          |            |   .eqv.  |    .true.   |\\n    |          |            |  .neqv.  |   .false.   |\\n    -------------------------------------------------|\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"reductionOperator\", \"type\": \"OpenACC_ReductionOperatorAttr{none|add|mul|max|min|iand|ior|xor|eqv|neqv|land|lor|maximumf|minimumf|maxnumf|minnumf}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"combinerRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"destroyRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `:` $type attr-dict-with-keyword\\n    `reduction_operator` $reductionOperator\\n    `init` $initRegion `combiner` $combinerRegion\\n    (`destroy` $destroyRegion^)?\"\n  },\n  {\n    \"name\": \"acc.routine\",\n    \"summary\": \"acc routine operation\",\n    \"description\": \"The `acc.routine` operation is used to capture the clauses of acc\\n    routine directive, including the associated function name. The associated\\n    function keeps track of its corresponding routine declaration through\\n    the `RoutineInfoAttr`.\\n\\n    Example:\\n\\n    ```mlir\\n    func.func @acc_func(%a : i64) -> () attributes \\n        {acc.routine_info = #acc.routine_info<[@acc_func_rout1]>} {\\n      return\\n    }\\n    acc.routine @acc_func_rout1 func(@acc_func) gang\\n    ```\\n\\n    `bind`, `gang`, `worker`, `vector` and `seq` operands are supported with\\n    `device_type` information. They should only be accessed by the extra\\n    provided getters. If modified, the corresponding `device_type` attributes\\n    must be modified as well.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"func_name\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"bindIdName\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"bindStrName\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"bindIdNameDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"bindStrNameDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"worker\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"vector\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"seq\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"nohost\", \"type\": \"UnitAttr\" },\n      { \"name\": \"implicit\", \"type\": \"UnitAttr\" },\n      { \"name\": \"gang\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"gangDim\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"gangDimDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `func` `(` $func_name `)`\\n    oilist (\\n        `bind` `(` custom<BindName>($bindIdName, $bindStrName ,$bindIdNameDeviceType, $bindStrNameDeviceType) `)`\\n      | `gang` `` custom<RoutineGangClause>($gang, $gangDim, $gangDimDeviceType)\\n      | `worker` custom<DeviceTypeArrayAttr>($worker)\\n      | `vector` custom<DeviceTypeArrayAttr>($vector)\\n      | `seq` custom<DeviceTypeArrayAttr>($seq)\\n      | `nohost` $nohost\\n      | `implicit` $implicit\\n    ) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.serial\",\n    \"summary\": \"serial construct\",\n    \"description\": \"The \\\"acc.serial\\\" operation represents a serial construct block. It has\\n    one region to be executed in serial on the current device.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.serial private(%c : memref<10xf32>) {\\n      // serial region\\n    }\\n    ```\\n\\n    `async` and `wait` operands are supported with `device_type` information.\\n    They should only be accessed by the extra provided getters. If modified,\\n    the corresponding `device_type` attributes must be modified as well.\",\n    \"operands\": [\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"selfCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"reductionOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"privateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"firstprivateOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"waitOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"waitOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"hasWaitDevnum\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" },\n      { \"name\": \"waitOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"selfAttr\", \"type\": \"UnitAttr\" },\n      { \"name\": \"defaultAttr\", \"type\": \"OptionalAttr<DefaultValueAttr>\" },\n      { \"name\": \"combined\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"( `combined` `(` `loop` `)` $combined^)?\\n    oilist(\\n        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `firstprivate` `(` $firstprivateOperands `:` type($firstprivateOperands) `)`\\n      | `private` `(` $privateOperands `:` type($privateOperands) `)`\\n      | `wait` `` custom<WaitClause>($waitOperands, type($waitOperands),\\n          $waitOperandsDeviceType, $waitOperandsSegments, $hasWaitDevnum,\\n          $waitOnly)\\n      | `self` `(` $selfCond `)`\\n      | `if` `(` $ifCond `)`\\n      | `reduction` `(` $reductionOperands `:` type($reductionOperands) `)`\\n    )\\n    $region attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.set\",\n    \"summary\": \"set operation\",\n    \"description\": \"The \\\"acc.set\\\" operation represents the OpenACC set directive.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.set device_num(%dev1 : i32)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"defaultAsync\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"deviceNum\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_type\", \"type\": \"OptionalAttr<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(`default_async` `(` $defaultAsync `:` type($defaultAsync) `)`\\n    | `device_num` `(` $deviceNum `:` type($deviceNum) `)`\\n    | `if` `(` $ifCond `)`\\n    ) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.shutdown\",\n    \"summary\": \"shutdown operation\",\n    \"description\": \"The \\\"acc.shutdown\\\" operation represents the OpenACC shutdown executable\\n    directive.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.shutdown\\n    acc.shutdown device_num(%dev1 : i32)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"deviceNum\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_types\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}, Device type attributes>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(`device_num` `(` $deviceNum `:` type($deviceNum) `)`\\n    |`if` `(` $ifCond `)`\\n    ) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.terminator\",\n    \"summary\": \"Generic terminator for OpenACC regions\",\n    \"description\": \"A terminator operation for regions that appear in the body of OpenACC\\n    operation. Generic OpenACC construct regions are not expected to return any\\n    value so the terminator takes no operands. The terminator op returns control\\n    to the enclosing op.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"acc.update\",\n    \"summary\": \"update operation\",\n    \"description\": \"The `acc.update` operation represents the OpenACC update executable\\n    directive.\\n    As host and self clauses are synonyms, any operands for host and self are\\n    add to $hostOperands.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.update device(%d1 : memref<10xf32>) attributes {async}\\n    ```\\n\\n    `async` and `wait` operands are supported with `device_type` information.\\n    They should only be accessed by the extra provided getters. If modified,\\n    the corresponding `device_type` attributes must be modified as well.\",\n    \"operands\": [\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"dataClauseOperands\", \"type\": \"Variadic<OpenACC_AnyPointerOrMappableType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"waitOperandsSegments\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"waitOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"hasWaitDevnum\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" },\n      { \"name\": \"waitOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"ifPresent\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `if` `(` $ifCond `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `wait` `` custom<WaitClause>($waitOperands, type($waitOperands),\\n          $waitOperandsDeviceType, $waitOperandsSegments, $hasWaitDevnum,\\n          $waitOnly)\\n      | `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`\\n    )\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.update_device\",\n    \"summary\": \"Represents acc update device semantics.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_update_device>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.update_host\",\n    \"summary\": \"Represents acc update host semantics.\",\n    \"description\": \"- `varPtr`: The address of variable to copy back to.- `accVar`: The acc variable. This is the link from the data-entry\\n    operation used.\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, always, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data exit operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_update_host>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AccVar>($accVar, type($accVar))\\n    (`bounds` `(` $bounds^ `)` )?\\n    (`async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)^)?\\n    `to` custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"acc.use_device\",\n    \"summary\": \"Represents acc use_device semantics.\",\n    \"description\": \"Description of arguments:\\n    - `var`: The variable to copy. Must be either `MappableType` or\\n    `PointerLikeType`.\\n    - `varType`: The type of the variable that is being copied. When `var` is\\n    a `MappableType`, this matches the type of `var`. When `var` is a\\n    `PointerLikeType`, this type holds information about the target of the\\n    pointer.\\n    - `varPtrPtr`: Specifies the address of the address of `var` - only used\\n    when the variable copied is a field in a struct. This is important for\\n    OpenACC due to implicit attach semantics on data clauses (2.6.4).\\n    - `bounds`: Used when copying just slice of array or array's bounds are not\\n    encoded in type. They are in rank order where rank 0 is inner-most dimension.\\n    - `asyncOperands` and `asyncOperandsDeviceType`:\\n    pair-wise lists of the async clause values associated with device_type's.\\n    - `asyncOnly`: a list of device_type's for which async clause\\n    does not specify a value (default is acc_async_noval - OpenACC 3.3 2.16.1).\\n    - `dataClause`: Keeps track of the data clause the user used. This is because\\n    the acc operations are decomposed. So a 'copy' clause is decomposed to both \\n    `acc.copyin` and `acc.copyout` operations, but both have dataClause that\\n    specifies `acc_copy` in this field.\\n    - `structured`: Flag to note whether this is associated with structured region\\n    (parallel, kernels, data) or unstructured (enter data, exit data). This is\\n    important due to spec specifically calling out structured and dynamic reference\\n    counters (2.6.7).\\n    - `implicit`: Whether this is an implicitly generated operation, such as copies\\n    done to satisfy \\\"Variables with Implicitly Determined Data Attributes\\\" in 2.6.2.\\n    - `modifiers`: Keeps track of the data clause modifiers (eg zero, readonly, etc)\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n\\n    The async values attached to the data entry operation imply that the data\\n    action applies to all device types specified by the device_type clauses\\n    using the activity queues on these devices as defined by the async values.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"OpenACC_AnyPointerOrMappableType\" },\n      { \"name\": \"varPtrPtr\", \"type\": \"Optional<OpenACC_PointerLikeTypeInterface>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenACC_DataBoundsType>\" },\n      { \"name\": \"asyncOperands\", \"type\": \"Variadic<IntOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"accVar\", \"type\": \"OpenACC_AnyPointerOrMappableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"asyncOperandsDeviceType\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"asyncOnly\", \"type\": \"OptionalAttr<TypedArrayAttrBase<OpenACC_DeviceTypeAttr{none|star|default|host|multicore|nvidia|radeon}>>\" },\n      { \"name\": \"dataClause\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseAttr{acc_copyin|acc_copyin_readonly|acc_copy|acc_copyout|acc_copyout_zero|acc_present|acc_create|acc_create_zero|acc_delete|acc_attach|acc_detach|acc_no_create|acc_private|acc_firstprivate|acc_deviceptr|acc_getdeviceptr|acc_update_host|acc_update_self|acc_update_device|acc_use_device|acc_reduction|acc_declare_device_resident|acc_declare_link|acc_cache|acc_cache_readonly}, mlir::acc::DataClause::acc_use_device>\" },\n      { \"name\": \"structured\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"implicit\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"modifiers\", \"type\": \"DefaultValuedAttr<OpenACC_DataClauseModifierAttr{none|zero|readonly|alwaysin|alwaysout|always|capture}, mlir::acc::DataClauseModifier::none>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"recipe\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)\\n    oilist(\\n        `varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`\\n      | `bounds` `(` $bounds `)`\\n      | `async` `` custom<DeviceTypeOperandsWithKeywordOnly>($asyncOperands,\\n            type($asyncOperands), $asyncOperandsDeviceType, $asyncOnly)\\n      | `recipe` `(` custom<RecipeSym>($recipe) `)`\\n    ) `->` type($accVar) attr-dict\"\n  },\n  {\n    \"name\": \"acc.wait\",\n    \"summary\": \"wait operation\",\n    \"description\": \"The \\\"acc.wait\\\" operation represents the OpenACC wait executable\\n    directive.\\n\\n    Example:\\n\\n    ```mlir\\n    acc.wait(%value1: index)\\n    acc.wait() async(%async1: i32)\\n    ```\\n\\n    acc.wait does not implement MemoryEffects interface,\\n    so it affects all the resources. This is conservatively\\n    correct. More precise modelling of the memory effects\\n    seems to be impossible without the whole program analysis.\",\n    \"operands\": [\n      { \"name\": \"waitOperands\", \"type\": \"Variadic<IntOrIndex>\" },\n      { \"name\": \"asyncOperand\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"waitDevnum\", \"type\": \"Optional<IntOrIndex>\" },\n      { \"name\": \"ifCond\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"async\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"( `(` $waitOperands^ `:` type($waitOperands) `)` )?\\n    oilist(\\n        `async` `` custom<OperandWithKeywordOnly>($asyncOperand,\\n            type($asyncOperand), $async)\\n      |  `wait_devnum` `(` $waitDevnum `:` type($waitDevnum) `)`\\n      | `if` `(` $ifCond `)`\\n    ) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"acc.yield\",\n    \"summary\": \"Acc yield and termination operation\",\n    \"description\": \"`acc.yield` is a special terminator operation for block inside regions in\\n    various acc ops (including parallel, loop, atomic.update). It returns values\\n    to the immediately enclosing acc op.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"affine.apply\",\n    \"summary\": \"affine apply operation\",\n    \"description\": \"The `affine.apply` operation applies an [affine mapping](#affine-maps)\\n    to a list of SSA values, yielding a single SSA value. The number of\\n    dimension and symbol operands to `affine.apply` must be equal to the\\n    respective number of dimensional and symbolic inputs to the affine mapping;\\n    the affine mapping has to be one-dimensional, and so the `affine.apply`\\n    operation always returns one value. The input operands and result must all\\n    have ‘index’ type.\\n\\n    An operand that is a valid dimension as per the [rules on valid affine\\n    dimensions and symbols](#restrictions-on-dimensions-and-symbols)\\n    cannot be used as a symbolic operand.\\n\\n    Example:\\n\\n    ```mlir\\n    #map = affine_map<(d0, d1) -> (d0 floordiv 8 + d1 floordiv 128)>\\n    ...\\n    %1 = affine.apply #map (%s, %t)\\n\\n    // Inline example.\\n    %2 = affine.apply affine_map<(i)[s0] -> (i + s0)> (%42)[%n]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"mapOperands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.delinearize_index\",\n    \"summary\": \"delinearize an index\",\n    \"description\": \"The `affine.delinearize_index` operation takes a single index value and\\n    calculates the multi-index according to the given basis.\\n\\n    Example:\\n\\n    ```\\n    %indices:3 = affine.delinearize_index %linear_index into (%c16, %c224, %c224) : index, index, index\\n    ```\\n\\n    In the above example, `%indices:3` conceptually holds the following:\\n\\n    ```\\n    #map0 = affine_map<()[s0] -> (s0 floordiv 50176)>\\n    #map1 = affine_map<()[s0] -> ((s0 mod 50176) floordiv 224)>\\n    #map2 = affine_map<()[s0] -> (s0 mod 224)>\\n    %indices_0 = affine.apply #map0()[%linear_index]\\n    %indices_1 = affine.apply #map1()[%linear_index]\\n    %indices_2 = affine.apply #map2()[%linear_index]\\n    ```\\n\\n    In other words, `%0:3 = affine.delinearize_index %x into (B, C)` produces\\n    `%0 = {%x / (B * C), (%x mod (B * C)) / C, %x mod C}`.\\n\\n    The basis may either contain `N` or `N-1` elements, where `N` is the number of results.\\n    If there are N basis elements, the first one will not be used during computations,\\n    but may be used during analysis and canonicalization to eliminate terms from\\n    the `affine.delinearize_index` or to enable conclusions about the total size of\\n    `%linear_index`.\\n\\n    If the basis is fully provided, the delinearize_index operation is said to \\\"have\\n    an outer bound\\\". The builders assume that an `affine.delinearize_index` has\\n    an outer bound by default, as this is how the operation was initially defined.\\n\\n    That is, the example above could also have been written\\n    ```mlir\\n    %0:3 = affine.delinearize_index %linear_index into (244, 244) : index, index\\n    ```\\n\\n    Note that, for symmetry with `getPaddedBasis()`, if `hasOuterBound` is `true`\\n    when one of the `OpFoldResult` builders is called but the first element of the\\n    basis is `nullptr`, that first element is ignored and the builder proceeds as if\\n    there was no outer bound.\\n\\n    Due to the constraints of affine maps, all the basis elements must\\n    be strictly positive. A dynamic basis element being 0 or negative causes\\n    undefined behavior.\\n\\n    As with other affine operations, lowerings of delinearize_index may assume\\n    that the underlying computations do not overflow the index type in a signed sense\\n    - that is, the product of all basis elements is positive as an `index` as well.\",\n    \"operands\": [\n      { \"name\": \"linear_index\", \"type\": \"Index\" },\n      { \"name\": \"dynamic_basis\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"multi_index\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_basis\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$linear_index `into`\\n    custom<DynamicIndexList>($dynamic_basis, $static_basis, \\\"{}\\\", \\\"::mlir::AsmParser::Delimiter::Paren\\\")\\n    attr-dict `:` type($multi_index)\"\n  },\n  {\n    \"name\": \"affine.dma_start\",\n    \"summary\": \"affine dma start operation\",\n    \"description\": \"The `affine.dma_start` op starts a non-blocking DMA operation that\\n    transfers data from a source memref to a destination memref. The source and\\n    destination memref need not be of the same dimensionality, but need to have\\n    the same elemental type. The operands include the source and destination\\n    memref's each followed by its indices, size of the data transfer in terms of\\n    the number of elements (of the elemental type of the memref), a tag memref\\n    with its indices, and optionally at the end, a stride and a\\n    number_of_elements_per_stride arguments. The tag location is used by an\\n    `affine.dma_wait` to check for completion. The indices of the source memref,\\n    destination memref, and the tag memref have the same restrictions as any\\n    affine.load/store. In particular, index for each memref dimension must be an\\n    affine expression of loop induction variables and symbols.\\n\\n    The optional stride arguments should be of 'index' type, and specify a\\n    stride for the slower memory space (memory space with a lower memory space\\n    id), transferring chunks of number_of_elements_per_stride every stride until\\n    %num_elements are transferred. Either both or no stride arguments should be\\n    specified. The value of 'num_elements' must be a multiple of\\n    'number_of_elements_per_stride'. If the source and destination locations\\n    overlap the behavior of this operation is not defined.\\n\\n    Example:\\n\\n    ```mlir\\n    %num_elements = arith.constant 256\\n    %idx = arith.constant 0 : index\\n    %tag = memref.alloc() : memref<1xi32, 4>\\n    affine.dma_start %src[%i + 3, %j], %dst[%k + 7, %l], %tag[%idx],\\n      %num_elements :\\n        memref<40x128xf32, 0>, memref<2x1024xf32, 1>, memref<1xi32, 2>\\n\\n    // If %stride and %num_elt_per_stride are specified, the DMA is expected to\\n    // transfer %num_elt_per_stride elements every %stride elements apart from\\n    // memory space 0 until %num_elements are transferred.\\n    affine.dma_start %src[%i, %j], %dst[%k, %l], %tag[%idx], %num_elements,\\n      %stride, %num_elt_per_stride : ...\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"src_map\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"dst_map\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"tag_map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.dma_wait\",\n    \"summary\": \"affine dma wait operation\",\n    \"description\": \"The `affine.dma_wait` op blocks until the completion of a DMA operation\\n    associated with the tag element `%tag[%index]`. `%tag` is a memref, and\\n    `%index` has to be an index with the same restrictions as any load/store\\n    index. In particular, index for each memref dimension must be an affine\\n    expression of loop induction variables and symbols. `%num_elements` is the\\n    number of elements associated with the DMA operation.\\n\\n    Example:\\n\\n    ```mlir\\n    affine.dma_start %src[%i, %j], %dst[%k, %l], %tag[%index], %num_elements :\\n      memref<2048xf32, 0>, memref<256xf32, 1>, memref<1xi32, 2>\\n    ...\\n    affine.dma_wait %tag[%index], %num_elements : memref<1xi32, 2>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"tag_map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.for\",\n    \"summary\": \"for operation\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation   ::= `affine.for` ssa-id `=` lower-bound `to` upper-bound\\n                    (`step` integer-literal)? `{` op* `}`\\n\\n    lower-bound ::= `max`? affine-map-attribute dim-and-symbol-use-list | shorthand-bound\\n    upper-bound ::= `min`? affine-map-attribute dim-and-symbol-use-list | shorthand-bound\\n    shorthand-bound ::= ssa-id | `-`? integer-literal\\n    ```\\n\\n    The `affine.for` operation represents an affine loop nest. It has one region\\n    containing its body. This region must contain one block that terminates with\\n    [`affine.yield`](#affineyield-mliraffineyieldop). *Note:* when\\n    `affine.for` is printed in custom format, the terminator is omitted. The\\n    block has one argument of [`index`](Builtin.md/#indextype) type that\\n    represents the induction variable of the loop.\\n\\n    The `affine.for` operation executes its body a number of times iterating\\n    from a lower bound to an upper bound by a stride. The stride, represented by\\n    `step`, is a positive constant integer which defaults to \\\"1\\\" if not present.\\n    The lower and upper bounds specify a half-open range: the range includes the\\n    lower bound but does not include the upper bound.\\n\\n    The lower and upper bounds of a `affine.for` operation are represented as an\\n    application of an affine mapping to a list of SSA values passed to the map.\\n    The [same restrictions](#restrictions-on-dimensions-and-symbols) hold for\\n    these SSA values as for all bindings of SSA values to dimensions and\\n    symbols.\\n\\n    The affine mappings for the bounds may return multiple results, in which\\n    case the `max`/`min` keywords are required (for the lower/upper bound\\n    respectively), and the bound is the maximum/minimum of the returned values.\\n    There is no semantic ambiguity, but MLIR syntax requires the use of these\\n    keywords to make things more obvious to human readers.\\n\\n    Many upper and lower bounds are simple, so MLIR accepts two custom form\\n    syntaxes: the form that accepts a single 'ssa-id' (e.g. `%N`) is shorthand\\n    for applying that SSA value to a function that maps a single symbol to\\n    itself, e.g., `()[s]->(s)()[%N]`. The integer literal form (e.g. `-42`) is\\n    shorthand for a nullary mapping function that returns the constant value\\n    (e.g. `()->(-42)()`).\\n\\n    Example showing reverse iteration of the inner loop:\\n\\n    ```mlir\\n    #map57 = affine_map<(d0)[s0] -> (s0 - d0 - 1)>\\n\\n    func.func @simple_example(%A: memref<?x?xf32>, %B: memref<?x?xf32>) {\\n      %N = dim %A, 0 : memref<?x?xf32>\\n      affine.for %i = 0 to %N step 1 {\\n        affine.for %j = 0 to %N {   // implicitly steps by 1\\n          %0 = affine.apply #map57(%j)[%N]\\n          %tmp = call @F1(%A, %i, %0) : (memref<?x?xf32>, index, index)->(f32)\\n          call @F2(%tmp, %B, %i, %0) : (f32, memref<?x?xf32>, index, index)->()\\n        }\\n      }\\n      return\\n    }\\n    ```\\n    `affine.for` can also operate on loop-carried variables (`iter_args`) and\\n    return the final values after loop termination. The initial values of the\\n    variables are passed as additional SSA operands to the `affine.for`\\n    following the operands for the loop's lower and upper bounds. The\\n    operation's region has equivalent arguments for each variable representing\\n    the value of the variable at the current iteration.\\n\\n    The region must terminate with an `affine.yield` that passes all the current\\n    iteration variables to the next iteration, or to the `affine.for`'s results\\n    if at the last iteration. For `affine.for`'s that execute zero iterations, the\\n    initial values of the loop-carried variables (corresponding to the SSA\\n    operands) will be the op's results.\\n\\n    For example, to sum-reduce a memref:\\n\\n     ```mlir\\n    func.func @reduce(%buffer: memref<1024xf32>) -> (f32) {\\n      // Initial sum set to 0.\\n      %sum_0 = arith.constant 0.0 : f32\\n      // iter_args binds initial values to the loop's region arguments.\\n      %sum = affine.for %i = 0 to 10 step 2\\n          iter_args(%sum_iter = %sum_0) -> (f32) {\\n        %t = affine.load %buffer[%i] : memref<1024xf32>\\n        %sum_next = arith.addf %sum_iter, %t : f32\\n        // Yield current iteration sum to next iteration %sum_iter or to %sum\\n        // if final iteration.\\n        affine.yield %sum_next : f32\\n      }\\n      return %sum : f32\\n    }\\n    ```\\n\\n    ```mlir\\n    %res:2 = affine.for %i = 0 to 128 iter_args(%arg0 = %init0, %arg1 = %init1)\\n               -> (index, index) {\\n      %y0 = arith.addi %arg0, %c1 : index\\n      %y1 = arith.addi %arg1, %c2 : index\\n      affine.yield %y0, %y1 : index, index\\n    }\\n    ```\\n    If the `affine.for` defines any values, a yield terminator must be\\n    explicitly present. The number and types of the \\\"affine.for\\\" results must\\n    match the initial values in the `iter_args` binding and the yield operands.\",\n    \"operands\": [\n      { \"name\": \"lowerBoundOperands\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"upperBoundOperands\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lowerBoundMap\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"upperBoundMap\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"step\", \"type\": \"IndexAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.if\",\n    \"summary\": \"if-then-else operation\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation  ::= `affine.if` if-op-cond `{` op* `}` (`else` `{` op* `}`)?\\n    if-op-cond ::= integer-set-attr dim-and-symbol-use-list\\n    ```\\n\\n    The `affine.if` operation restricts execution to a subset of the loop\\n    iteration space defined by an integer set (a conjunction of affine\\n    constraints). A single `affine.if` may end with an optional `else` clause.\\n\\n    The condition of the `affine.if` is represented by an\\n    [integer set](#integer-sets) (a conjunction of affine constraints),\\n    and the SSA values bound to the dimensions and symbols in the integer set.\\n    The [same restrictions](#restrictions-on-dimensions-and-symbols) hold for\\n    these SSA values as for all bindings of SSA values to dimensions and\\n    symbols.\\n\\n    The `affine.if` operation contains two regions for the \\\"then\\\" and \\\"else\\\"\\n    clauses.  `affine.if` may return results that are defined in its regions.\\n    The values defined are determined by which execution path is taken.  Each\\n    region of the `affine.if` must contain a single block with no arguments,\\n    and be terminated by `affine.yield`.  If `affine.if` defines no values,\\n    the `affine.yield` can be left out, and will be inserted implicitly.\\n    Otherwise, it must be explicit.  If no values are defined, the else block\\n    may be empty (i.e. contain no blocks).\\n\\n    Example:\\n\\n    ```mlir\\n    #set = affine_set<(d0, d1)[s0]: (d0 - 10 >= 0, s0 - d0 - 9 >= 0,\\n                                     d1 - 10 >= 0, s0 - d1 - 9 >= 0)>\\n    func.func @reduced_domain_example(%A, %X, %N) : (memref<10xi32>, i32, i32) {\\n      affine.for %i = 0 to %N {\\n         affine.for %j = 0 to %N {\\n           %0 = affine.apply #map42(%j)\\n           %tmp = call @S1(%X, %i, %0)\\n           affine.if #set(%i, %j)[%N] {\\n              %1 = affine.apply #map43(%i, %j)\\n              call @S2(%tmp, %A, %i, %1)\\n           }\\n        }\\n      }\\n      return\\n    }\\n    ```\\n\\n    Example with an explicit yield (initialization with edge padding):\\n\\n    ```mlir\\n    #interior = affine_set<(i, j) : (i - 1 >= 0, j - 1 >= 0,  10 - i >= 0, 10 - j >= 0)> (%i, %j)\\n    func.func @pad_edges(%I : memref<10x10xf32>) -> (memref<12x12xf32) {\\n      %O = alloc memref<12x12xf32>\\n      affine.parallel (%i, %j) = (0, 0) to (12, 12) {\\n        %1 = affine.if #interior (%i, %j) {\\n          %2 = load %I[%i - 1, %j - 1] : memref<10x10xf32>\\n          affine.yield %2\\n        } else {\\n          %2 = arith.constant 0.0 : f32\\n          affine.yield %2 : f32\\n        }\\n        affine.store %1, %O[%i, %j] : memref<12x12xf32>\\n      }\\n      return %O\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"condition\", \"type\": \"IntegerSetAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"elseRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.linearize_index\",\n    \"summary\": \"linearize an index\",\n    \"description\": \"The `affine.linearize_index` operation takes a sequence of index values and a\\n    basis of the same length and linearizes the indices using that basis.\\n\\n    That is, for indices `%idx_0` to `%idx_{N-1}` and basis elements `b_0`\\n    (or `b_1`) up to `b_{N-1}` it computes\\n\\n    ```\\n    sum(i = 0 to N-1) %idx_i * product(j = i + 1 to N-1) B_j\\n    ```\\n\\n    In other words, `%0 = affine.linearize_index [%z, %y, %x] by (Z, Y, X)`\\n    gives `%0 = %x + %y * X + %z * X * Y`, or `%0 = %x + X * (%y + Y * (%z))`.\\n\\n    The basis may either have `N` or `N-1` elements, where `N` is the number of\\n    inputs to linearize_index. If `N` inputs are provided, the first one is not used\\n    in computation, but may be used during analysis or canonicalization as a bound\\n    on `%idx_0`.\\n\\n    If all `N` basis elements are provided, the linearize_index operation is said to\\n    \\\"have an outer bound\\\".\\n\\n    As a convenience, and for symmetry with `getPaddedBasis()`, if the first\\n    element of a set of `OpFoldResult`s passed to the builders of this operation is\\n    `nullptr`, that element is ignored.\\n\\n    If the `disjoint` property is present, this is an optimization hint that,\\n    for all `i`, `0 <= %idx_i < B_i` - that is, no index affects any other index,\\n    except that `%idx_0` may be negative to make the index as a whole negative.\\n    In addition, `disjoint` is an assertion that all bases elements are non-negative.\\n\\n    Note that the outputs of `affine.delinearize_index` are, by definition, `disjoint`.\\n\\n    As with other affine ops, undefined behavior occurs if the linearization\\n    computation overflows in the signed sense.\\n\\n    Example:\\n\\n    ```mlir\\n    %linear_index = affine.linearize_index [%index_0, %index_1, %index_2] by (2, 3, 5) : index\\n    // Same effect\\n    %linear_index = affine.linearize_index [%index_0, %index_1, %index_2] by (3, 5) : index\\n    ```\\n\\n    In the above example, `%linear_index` conceptually holds the following:\\n\\n    ```mlir\\n    #map = affine_map<()[s0, s1, s2] -> (s0 * 15 + s1 * 5 + s2)>\\n    %linear_index = affine.apply #map()[%index_0, %index_1, %index_2]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"multi_index\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"dynamic_basis\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"linear_index\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_basis\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"disjoint\", \"type\": \"UnitProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`disjoint` $disjoint^)? ` `\\n    `[` $multi_index `]` `by`\\n    custom<DynamicIndexList>($dynamic_basis, $static_basis, \\\"{}\\\", \\\"::mlir::AsmParser::Delimiter::Paren\\\")\\n    attr-dict `:` type($linear_index)\"\n  },\n  {\n    \"name\": \"affine.load\",\n    \"summary\": \"affine load operation\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= ssa-id `=` `affine.load` ssa-use `[` multi-dim-affine-map-of-ssa-ids `]` `:` memref-type\\n    ```\\n\\n    The `affine.load` op reads an element from a memref, where the index\\n    for each memref dimension is an affine expression of loop induction\\n    variables and symbols. The output of `affine.load` is a new value with the\\n    same type as the elements of the memref. An affine expression of loop IVs\\n    and symbols must be specified for each dimension of the memref. The keyword\\n    `symbol` can be used to indicate SSA identifiers which are symbolic.\\n\\n    Example 1:\\n\\n    ```mlir\\n    %1 = affine.load %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>\\n    ```\\n\\n    Example 2: Uses `symbol` keyword for symbols `%n` and `%m`.\\n\\n    ```mlir\\n    %1 = affine.load %0[%i0 + symbol(%n), %i1 + symbol(%m)] : memref<100x100xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.max\",\n    \"summary\": \"max operation\",\n    \"description\": \"The `affine.max` operation computes the maximum value result from a multi-result\\n    affine map.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = affine.max (d0) -> (1000, d0 + 512) (%i0) : index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.min\",\n    \"summary\": \"min operation\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= ssa-id `=` `affine.min` affine-map-attribute dim-and-symbol-use-list\\n    ```\\n\\n    The `affine.min` operation applies an [affine mapping](#affine-expressions)\\n    to a list of SSA values, and returns the minimum value of all result\\n    expressions. The number of dimension and symbol arguments to `affine.min`\\n    must be equal to the respective number of dimensional and symbolic inputs to\\n    the affine mapping; the `affine.min` operation always returns one value. The\\n    input operands and result must all have 'index' type.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = affine.min affine_map<(d0)[s0] -> (1000, d0 + 512, s0)> (%arg0)[%arg1]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.parallel\",\n    \"summary\": \"multi-index parallel band operation\",\n    \"description\": \"The `affine.parallel` operation represents a hyper-rectangular affine\\n    parallel band, defining zero or more SSA values for its induction variables.\\n    It has one region capturing the parallel band body. The induction variables\\n    are represented as arguments of this region. These SSA values always have\\n    type index, which is the size of the machine word. The strides, represented\\n    by steps, are positive constant integers which defaults to \\\"1\\\" if not\\n    present. The lower and upper bounds specify a half-open range: the range\\n    includes the lower bound but does not include the upper bound. The body\\n    region must contain exactly one block that terminates with `affine.yield`.\\n\\n    The lower and upper bounds of a parallel operation are represented as an\\n    application of an affine mapping to a list of SSA values passed to the map.\\n    The same restrictions hold for these SSA values as for all bindings of SSA\\n    values to dimensions and symbols. The list of expressions in each map is\\n    interpreted according to the respective bounds group attribute. If a single\\n    expression belongs to the group, then the result of this expression is taken\\n    as a lower(upper) bound of the corresponding loop induction variable. If\\n    multiple expressions belong to the group, then the lower(upper) bound is the\\n    max(min) of these values obtained from these expressions. The loop band has\\n    as many loops as elements in the group bounds attributes.\\n\\n    Each value yielded by `affine.yield` will be accumulated/reduced via one of\\n    the reduction methods defined in the AtomicRMWKind enum.  The order of\\n    reduction is unspecified, and lowering may produce any valid ordering.\\n    Loops with a 0 trip count will produce as a result the identity value\\n    associated with each reduction (i.e. 0.0 for addf, 1.0 for mulf).  Assign\\n    reductions for loops with a trip count != 1 produces undefined results.\\n\\n    Note: Calling `AffineParallelOp::build` will create the required region and\\n    block, and insert the required terminator if it is trivial (i.e. no values\\n    are yielded).  Parsing will also create the required region, block, and\\n    terminator, even when they are missing from the textual representation.\\n\\n    Example (3x3 valid convolution):\\n\\n    ```mlir\\n    func.func @conv_2d(%D : memref<100x100xf32>, %K : memref<3x3xf32>) -> (memref<98x98xf32>) {\\n      %O = memref.alloc() : memref<98x98xf32>\\n      affine.parallel (%x, %y) = (0, 0) to (98, 98) {\\n        %0 = affine.parallel (%kx, %ky) = (0, 0) to (2, 2) reduce (\\\"addf\\\") -> f32 {\\n          %1 = affine.load %D[%x + %kx, %y + %ky] : memref<100x100xf32>\\n          %2 = affine.load %K[%kx, %ky] : memref<3x3xf32>\\n          %3 = arith.mulf %1, %2 : f32\\n          affine.yield %3 : f32\\n        }\\n        affine.store %0, %O[%x, %y] : memref<98x98xf32>\\n      }\\n      return %O : memref<98x98xf32>\\n    }\\n    ```\\n\\n    Example (tiling by potentially imperfectly dividing sizes):\\n\\n    ```mlir\\n    affine.parallel (%ii, %jj) = (0, 0) to (%N, %M) step (32, 32) {\\n      affine.parallel (%i, %j) = (%ii, %jj)\\n                              to (min(%ii + 32, %N), min(%jj + 32, %M)) {\\n        call @f(%i, %j) : (index, index) -> ()\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"mapOperands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reductions\", \"type\": \"TypedArrayAttrBase<AtomicRMWKindAttr{addf|addi|andi|assign|maximumf|maxnumf|maxs|maxu|minimumf|minnumf|mins|minu|mulf|muli|ori|xori}, Reduction ops>\" },\n      { \"name\": \"lowerBoundsMap\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"lowerBoundsGroups\", \"type\": \"I32ElementsAttr\" },\n      { \"name\": \"upperBoundsMap\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"upperBoundsGroups\", \"type\": \"I32ElementsAttr\" },\n      { \"name\": \"steps\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.prefetch\",\n    \"summary\": \"affine prefetch operation\",\n    \"description\": \"The `affine.prefetch` op prefetches data from a memref location described\\n    with an affine subscript similar to affine.load, and has three attributes:\\n    a read/write specifier, a locality hint, and a cache type specifier as shown\\n    below:\\n\\n    ```mlir\\n    affine.prefetch %0[%i, %j + 5], read, locality<3>, data : memref<400x400xi32>\\n    ```\\n\\n    The read/write specifier is either 'read' or 'write', the locality hint\\n    specifier ranges from locality<0> (no locality) to locality<3> (extremely\\n    local keep in cache). The cache type specifier is either 'data' or 'instr'\\n    and specifies whether the prefetch is performed on data cache or on\\n    instruction cache.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isWrite\", \"type\": \"BoolAttr\" },\n      { \"name\": \"localityHint\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>\" },\n      { \"name\": \"isDataCache\", \"type\": \"BoolAttr\" },\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.store\",\n    \"summary\": \"affine store operation\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= `affine.store` ssa-use, ssa-use `[` multi-dim-affine-map-of-ssa-ids `]` `:` memref-type\\n    ```\\n\\n    The `affine.store` op writes an element to a memref, where the index\\n    for each memref dimension is an affine expression of loop induction\\n    variables and symbols. The `affine.store` op stores a new value which is the\\n    same type as the elements of the memref. An affine expression of loop IVs\\n    and symbols must be specified for each dimension of the memref. The keyword\\n    `symbol` can be used to indicate SSA identifiers which are symbolic.\\n\\n    Example 1:\\n\\n    ```mlir\\n    affine.store %v0, %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>\\n    ```\\n\\n    Example 2: Uses `symbol` keyword for symbols `%n` and `%m`.\\n\\n    ```mlir\\n    affine.store %v0, %0[%i0 + symbol(%n), %i1 + symbol(%m)] : memref<100x100xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.vector_load\",\n    \"summary\": \"affine vector load operation\",\n    \"description\": \"The `affine.vector_load` is the vector counterpart of\\n    [affine.load](#affineload-mliraffineloadop). It reads a slice from a\\n    [MemRef](Builtin.md/#memreftype), supplied as its first operand,\\n    into a [vector](Builtin.md/#vectortype) of the same base elemental type.\\n    The index for each memref dimension is an affine expression of loop induction\\n    variables and symbols. These indices determine the start position of the read\\n    within the memref. The shape of the return vector type determines the shape of\\n    the slice read from the memref. This slice is contiguous along the respective\\n    dimensions of the shape. Strided vector loads will be supported in the future.\\n    An affine expression of loop IVs and symbols must be specified for each\\n    dimension of the memref. The keyword `symbol` can be used to indicate SSA\\n    identifiers which are symbolic.\\n\\n    Example 1: 8-wide f32 vector load.\\n\\n    ```mlir\\n    %1 = affine.vector_load %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>, vector<8xf32>\\n    ```\\n\\n    Example 2: 4-wide f32 vector load. Uses `symbol` keyword for symbols `%n` and `%m`.\\n\\n    ```mlir\\n    %1 = affine.vector_load %0[%i0 + symbol(%n), %i1 + symbol(%m)] : memref<100x100xf32>, vector<4xf32>\\n    ```\\n\\n    Example 3: 2-dim f32 vector load.\\n\\n    ```mlir\\n    %1 = affine.vector_load %0[%i0, %i1] : memref<100x100xf32>, vector<2x8xf32>\\n    ```\\n\\n    TODOs:\\n    * Add support for strided vector loads.\\n    * Consider adding a permutation map to permute the slice that is read from memory\\n    (see [vector.transfer_read](../Vector/#vectortransfer_read-mlirvectortransferreadop)).\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.vector_store\",\n    \"summary\": \"affine vector store operation\",\n    \"description\": \"The `affine.vector_store` is the vector counterpart of\\n    [affine.store](#affinestore-mliraffinestoreop). It writes a\\n    [vector](Builtin.md/#vectortype), supplied as its first operand,\\n    into a slice within a [MemRef](Builtin.md/#memreftype) of the same base\\n    elemental type, supplied as its second operand.\\n    The index for each memref dimension is an affine expression of loop\\n    induction variables and symbols. These indices determine the start position\\n    of the write within the memref. The shape of the input vector determines the\\n    shape of the slice written to the memref. This slice is contiguous along the\\n    respective dimensions of the shape. Strided vector stores will be supported\\n    in the future.\\n    An affine expression of loop IVs and symbols must be specified for each\\n    dimension of the memref. The keyword `symbol` can be used to indicate SSA\\n    identifiers which are symbolic.\\n\\n    Example 1: 8-wide f32 vector store.\\n\\n    ```mlir\\n    affine.vector_store %v0, %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>, vector<8xf32>\\n    ```\\n\\n    Example 2: 4-wide f32 vector store. Uses `symbol` keyword for symbols `%n` and `%m`.\\n\\n    ```mlir\\n    affine.vector_store %v0, %0[%i0 + symbol(%n), %i1 + symbol(%m)] : memref<100x100xf32>, vector<4xf32>\\n    ```\\n\\n    Example 3: 2-dim f32 vector store.\\n\\n    ```mlir\\n    affine.vector_store %v0, %0[%i0, %i1] : memref<100x100xf32>, vector<2x8xf32>\\n    ```\\n\\n    TODOs:\\n    * Add support for strided vector stores.\\n    * Consider adding a permutation map to permute the slice that is written to memory\\n    (see [vector.transfer_write](../Vector/#vectortransfer_write-mlirvectortransferwriteop)).\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"affine.yield\",\n    \"summary\": \"Yield values to parent operation\",\n    \"description\": \"The `affine.yield` yields zero or more SSA values from an affine op region and\\n    terminates the region. The semantics of how the values yielded are used\\n    is defined by the parent operation.\\n    If `affine.yield` has any operands, the operands must match the parent\\n    operation's results.\\n    If the parent operation defines no values, then the `affine.yield` may be\\n    left out in the custom syntax and the builders will insert one implicitly.\\n    Otherwise, it has to be present in the syntax to indicate which values are\\n    yielded.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"amdg.arrive_barrier\",\n    \"summary\": \"perform the arrive operation on an mbarrier\",\n    \"description\": \"Performs the \\\"arrive\\\" operation on an mbarrier object in shared memory. The operation requires a `count` attribute\\n    of at least 1, and decreases the pending arrival count of the mbarrier by the specific count. If the pending count reaches\\n    zero, the phase changes (is decremented in a wraparound manner) and the pending count is reloaded with the init count value. Returns the phase\\n    parity (0 for even, 1 for odd) of the mbarrier object prior to the \\\"arrive\\\" operation.\\n\\n    Example:\\n\\n    ```mlir\\n    ttag.arrive_barrier %barrier, 2 : !ttg.memdesc<1xi64, #shared, #smem, mutable>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $count attr-dict `:` qualified(type($alloc)) `->` type($result)\"\n  },\n  {\n    \"name\": \"amdg.async_copy_local_to_global\",\n    \"summary\": \"copy data from local memory to global memory asynchronously\",\n    \"description\": \"This operation copies data from local memory to global memory asynchronously.\\n    This is analogue to tt.store except the data are copied from local memory pointed\\n    to by the memory descriptor instead of a distributed tensor.\\n    Contiguity is the maximum number of elements that can be stored in a single vector with\\n    the given layout and mask.\\n    This allows op to use async_copy_local_to_global even if the alignment cannot be proven based on IR.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"dst\", \"type\": \"TT_PtrTensor\" },\n      { \"name\": \"mask\", \"type\": \"Optional<I1Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, triton::EvictionPolicy::NORMAL>\" },\n      { \"name\": \"contiguity\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'dst', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $dst (`mask` $mask^)?\\n    oilist(`cacheModifier` `=` $cache | `evictionPolicy` `=` $evict)\\n    attr-dict `:` qualified(type($src)) `->` type($dst)\"\n  },\n  {\n    \"name\": \"amdg.async_copy_mbarrier_arrive\",\n    \"summary\": \"arrive on mbarrier once all previously issued copies are completed\",\n    \"description\": \"Performs the \\\"async arrive\\\" operation by decrementing pending account by 1 when all previous async load to LDS (particularly, not TDM) have completed.\\n    The instruction itself is asynchronous; it returns immediately. Decrements the barrier pending count. The update value for decrementing is fixed at 1.\\n    If the pending count becomes zero, the phase changes (is decremented in a wraparound manner) and the pending count is reloaded with the init count value.\",\n    \"operands\": [\n      { \"name\": \"barrier\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$barrier attr-dict `:` qualified(type($barrier))\"\n  },\n  {\n    \"name\": \"amdg.async_tdm_copy_global_to_local\",\n    \"summary\": \"Copy data based on descriptor from global memory to local memory asynchronously\",\n    \"description\": \"This operation copies data from global memory to local memory\\n    asynchronously. This is analogue to tt.load except the data are copied to\\n    local memory pointed by `result` instead of a distributed tensor. The data\\n    copied depends on the global memory pointed to by `desc`. Set `pred` to\\n    false will disable the copy. This operation does not support shared memory\\n    swizzling.\\n    The operation can also take an optional 64bit LDS barrier address, in which case\\n    it sends an \\\"LDS atomic arrive\\\" to signal its completion.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"I32\" },\n      { \"name\": \"barrier\", \"type\": \"Optional<TTG_MemDescType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $indices `]` `into` $result `,` `pred` `=` $pred (`,` `barrier` `=` $barrier^)?\\n    attr-dict `:` qualified(type($desc)) (`,` qualified(type($barrier))^)? `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"amdg.async_tdm_copy_local_to_global\",\n    \"summary\": \"Copy data based on descriptor from local memory to global memory asynchronously\",\n    \"description\": \"This operation copies data from local memory to global memory\\n    asynchronously. This is analogue to tt.store except the data are copied from\\n    local memory pointed by `src` instead of a distributed tensor. The copy\\n    destination depends on the global memory pointed to by `desc`. This\\n    operation does not support shared memory padding or swizzling.\\n    The operation can also take an optional 64bit LDS barrier address, in which case\\n    it sends an \\\"LDS atomic arrive\\\" to signal its completion.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"barrier\", \"type\": \"Optional<TTG_MemDescType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $indices `]` `from` $src (`,` `barrier` `=` $barrier^)?\\n    attr-dict `:` qualified(type($src)) (`,` qualified(type($barrier))^)? `->` qualified(type($desc))\"\n  },\n  {\n    \"name\": \"amdg.async_tdm_gather\",\n    \"summary\": \"Gather data from non-contiguous global memory rows to local memory asynchronously\",\n    \"description\": \"This operation gathers data from non-contiguous rows in global memory to local\\n    memory using TDM gather mode.\\n    Unlike the regular async_tdm_copy_global_to_local which reads from contiguous memory,\\n    this operation uses src_row_indices to specify which rows in global memory to read from.\\n\\n    The descriptor must be 2D. The src_row_indices specify which rows in global memory\\n    to read from. The element type of src_row_indices determines the index size:\\n    - I16: 16-bit indices, up to 16 rows per instruction\\n    - I32: 32-bit indices, up to 8 rows per instruction\\n    If more rows are needed, multiple TDM instructions will be issued.\\n\\n    The src_col_offset specifies the starting column in the source tensor for\\n    all gathered rows.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"src_row_indices\", \"type\": \"TensorOf<[I16, I32]>\" },\n      { \"name\": \"src_col_offset\", \"type\": \"I32\" },\n      { \"name\": \"dst\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"I32\" },\n      { \"name\": \"barrier\", \"type\": \"Optional<TTG_MemDescType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $src_row_indices `,` $src_col_offset `]` `to` $dst `,` `pred` `=` $pred (`,` `barrier` `=` $barrier^)?\\n    attr-dict `:` qualified(type($src_row_indices)) `,` qualified(type($dst)) (`,` qualified(type($barrier))^)? `->` qualified(type($desc))\"\n  },\n  {\n    \"name\": \"amdg.async_tdm_intrinsic_wait\",\n    \"summary\": \"Wait until there are less than or equal to the given number of outstanding TDM intrinsics\",\n    \"description\": \"This operation waits until there are less than or equal to the given number\\n    of outstanding TDM intrinsics (assembly instructions). This is necessary to\\n    ensure that data is available in LDS (load, gather) or HBM (store, scatter)\\n    before it is used.\\n\\n    Unlike AsyncTDMWait which counts IR operations, this operation counts the\\n    actual number of TDM assembly instructions (e.g., tensor_load_to_lds,\\n    tensor_store_from_lds) that are emitted. Which is required for the lowering\\n    to LLVM.\",\n    \"operands\": [\n      { \"name\": \"asyncToken\", \"type\": \"Variadic<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"retToken\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"($asyncToken^)? attr-dict\"\n  },\n  {\n    \"name\": \"amdg.async_tdm_scatter\",\n    \"summary\": \"Scatter data from local memory to non-contiguous global memory rows asynchronously\",\n    \"description\": \"This operation scatters data from local memory to non-contiguous rows in global\\n    memory using TDM scatter mode.\\n    Unlike the regular async_tdm_copy_local_to_global which copies to contiguous memory,\\n    this operation uses dst_row_indices to specify which rows in global memory to write to.\\n\\n    The descriptor must be 2D. The dst_row_indices specify which rows in global memory\\n    to write to. The element type of dst_row_indices determines the index size:\\n    - I16: 16-bit indices, up to 16 rows per instruction\\n    - I32: 32-bit indices, up to 8 rows per instruction\\n    If more rows are needed, multiple TDM instructions will be issued.\\n\\n    The dst_col_offset specifies the starting column in the destination tensor for\\n    all scattered rows.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"dst_row_indices\", \"type\": \"TensorOf<[I16, I32]>\" },\n      { \"name\": \"dst_col_offset\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"barrier\", \"type\": \"Optional<TTG_MemDescType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"retToken\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $dst_row_indices `,` $dst_col_offset `]` `from` $src (`,` `barrier` `=` $barrier^)?\\n    attr-dict `:` qualified(type($dst_row_indices)) `,` qualified(type($src)) (`,` qualified(type($barrier))^)? `->` qualified(type($desc))\"\n  },\n  {\n    \"name\": \"amdg.async_tdm_wait\",\n    \"summary\": \"Wait until there are less than or equal to the given number of outstanding TDM operations\",\n    \"description\": \"This operation waits until there are less than or equal to the given number\\n    of outstanding async TDM operations.\\n    This is necessary to ensure that data is available in the LDS (load, gather)\\n    or HBM (store, scatter) before it is used.\\n\\n    This operation counts the number of TDM IR operations (AsyncTDMCopyGlobalToLocalOp,\\n    AsyncTDMCopyLocalToGlobalOp, AsyncTDMScatterOp, AsyncTDMGatherOp).\",\n    \"operands\": [\n      { \"name\": \"asyncToken\", \"type\": \"Variadic<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"retToken\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$asyncToken attr-dict\"\n  },\n  {\n    \"name\": \"amdg.async_wait\",\n    \"summary\": \"Wait until there are less than or equal to the given number of outstanding async intrinsics\",\n    \"description\": \"Similar to ttg.async_wait but instead of waiting on oustanding ttg.async_commit_groups\\n    this op waits on the number of outstanding async instructions/intrinsics as required for the\\n    lowering to LLVM on the AMD backend.\",\n    \"operands\": [\n      { \"name\": \"asyncToken\", \"type\": \"Variadic<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"retToken\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_inst\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"($asyncToken^)? attr-dict\"\n  },\n  {\n    \"name\": \"amdg.buffer_atomic_cas\",\n    \"summary\": \"Atomic CAS op which does compare-exchange to a scalar base pointer and a tensor offset\",\n    \"description\": \"AMD Buffer Atomic CAS operation. Buffer atomics are similar to normal atomics, but access global memory via a\\n        scalar base pointer and a tensor of offsets instead of a tensor of pointers.\\n        Similar to TT_AtomicCASOp: Buffer atomic CAS op loads data at $ptr, and stores $val to $ptr atomically if value at $ptr equals $cmp, with\\n        the specified memory semantics and scope. Atomic CAS ops return the pre-op value if used, otherwise the value is implicitly dropped.\\n        Stride is the distance between the beginning of contiguous memory chunks. When performing a CAS, the `stride` is\\n        the address difference between the first elements of each row in bytes. Compiler tries to obtain the `stride`\\n        when it converts to the buffer ops because it is important for optimizing the cache memory access.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"I32Tensor\" },\n      { \"name\": \"cmp\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"val\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"stride\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sem\", \"type\": \"TT_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" },\n      { \"name\": \"scope\", \"type\": \"TT_MemSyncScopeAttr{gpu|cta|sys}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'val', '$_self'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'cmp', '$_self'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'ptr', 'getPointerTypeToElement($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'offsets', 'getI32SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'val', 'offsets', 'getI32SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'val', 'cmp', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$sem `,` $scope `,` $cmp `,` $val `,` $ptr `[` $offsets `]`\\n        (`stride` `=` $stride^)?\\n        attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"amdg.buffer_atomic_rmw\",\n    \"summary\": \"Atomic RMW op which reads, modifies, and writes to a scalar base pointer and a tensor offset\",\n    \"description\": \"AMD Buffer atomic RMW operation. Buffer atomics are similar to normal atomics, but access global memory via a\\n        scalar base pointer and a tensor of offsets instead of a tensor of pointers.\\n        Similar to other buffer ops, the `mask` is a boolean vector that determines if a given element should be processed with\\n        the atomic RMW op. Elements with `mask[i] == 0` are dropped (i.e., the atomic is not executed).\\n        Similar to TT_AtomicRMWOp: Buffer atomic RMW ops load data at $ptr, do $rmw_op with $val, and store result to $ptr with\\n        the specified memory semantics and scope. Atomic RMW ops return the pre-op value if used, otherwise the value is implicitly dropped.\\n        Stride is the distance between the beginning of contiguous memory chunks. When performing a RMW, the `stride` is\\n        the address difference between the first elements of each row in bytes. Compiler tries to obtain the `stride`\\n        when it converts to the buffer ops because it is important for optimizing the cache memory access.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"I32Tensor\" },\n      { \"name\": \"value\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"stride\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"atomic_rmw_op\", \"type\": \"TT_AtomicRMWAttr{and|or|xor|add|fadd|max|min|umax|umin|exch}\" },\n      { \"name\": \"sem\", \"type\": \"TT_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" },\n      { \"name\": \"scope\", \"type\": \"TT_MemSyncScopeAttr{gpu|cta|sys}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'result', 'value', '$_self'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'ptr', 'getPointerTypeToElement($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'offsets', 'getI32SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'mask', 'getI1SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'value', 'ptr', 'getPointerTypeToElement($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'value', 'offsets', 'getI32SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'value', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$atomic_rmw_op `,` $sem `,` $scope `,` $value `,` $ptr `[` $offsets `]` (`,` $mask^)?\\n        (`stride` `=` $stride^)?\\n        attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"amdg.buffer_load\",\n    \"summary\": \"Load from a scalar base pointer and a tensor offset\",\n    \"description\": \"AMD Buffer load operation. Buffer store is similar to\\n      a normal store but it accesses global memory via a scalar base pointer\\n      and a tensor of offsets instead of a tensor of pointers. The other fields\\n      are similar to a normal load, i.e., the `mask` is a boolean vector that\\n      determines if a given element should be read from memory, and `other` is the\\n      element that should be returned on lane `i` when `mask[i] == 0`.\\n      Stride is the distance between the beginning of contiguous memory chunks.\\n      When performing a load of a block, the `stride` is the address difference between\\n      the first elements of each row in bytes. Compiler tries to obtain the `stride`\\n      when it converts to the buffer ops because it is important for optimizing\\n      the cache memory access.\\n      Contiguity is the maximum number of elements that can be loaded in a single vector\\n      with the given layout and mask.\\n      This allows to use buffer_load even if the alignment cannot be proven based on IR.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"I32Tensor\" },\n      { \"name\": \"stride\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolTensor>\" },\n      { \"name\": \"other\", \"type\": \"Optional<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"contiguity\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'result', 'ptr', 'getPointerTypeToElement($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'offsets', 'getI32SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'mask', 'getI1SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'result', 'other', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `[` $offsets `]` (`,` $mask^)? (`,` $other^)?\\n      oilist(`cacheModifier` `=` $cache)\\n      (`stride` `=` $stride^)?\\n      attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"amdg.buffer_load_to_local\",\n    \"summary\": \"Load from a scalar base pointer and a tensor offset to shared memory\",\n    \"description\": \"AMD Buffer load operation. Similar to amdg.buffer_load op but directly wirtes to shared memory instead of into registers.\\n      Contiguity is the maximum number of elements that can be loaded in a single vector with the given layout and mask.\\n      This allows to use buffer_load_to_local even if the alignment cannot be proven based on IR.\",\n    \"operands\": [\n      { \"name\": \"dest\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"ptr\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"I32Tensor\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolTensor>\" },\n      { \"name\": \"other\", \"type\": \"Optional<TT_Tensor>\" },\n      { \"name\": \"stride\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"contiguity\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'dest', 'ptr', 'getPointerTypeToElement($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'offsets', 'mask', 'getI1SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'offsets', 'other', 'cast<TensorType>($_self).clone(getPointeeType($ptr.getType()))'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `[` $offsets `]` (`mask` `=` $mask^)? (`other` `=` $other^)? (`stride` `=` $stride^)?\\n      oilist(`cacheModifier` `=` $cache) `into` $dest\\n      attr-dict `:` type($ptr) `[` type($offsets) `]` type($other) `->` type($dest)\"\n  },\n  {\n    \"name\": \"amdg.buffer_store\",\n    \"summary\": \"Store into scalar base pointer and a tensor offset\",\n    \"description\": \"AMD Buffer store operation. Buffer store is similar to\\n      normal store but it accesses global memory via a scalar base pointer\\n      and a tensor of offsets instead of a tensor of pointers. The other fields\\n      are similar to a normal store , i.e., the `mask` is a boolean vector that\\n      determines if a given element should be written to memory, and `value` is the\\n      tensor of elements that should be written on lane `i` when `mask[i] == 1`.\\n      Stride is the distance between the beginning of contiguous memory chunks.\\n      When performing a block store, the `stride` is the address difference between\\n      the first elements of each row in bytes. Compiler tries to obtain the `stride`\\n      when it converts to the buffer ops because it is important for optimizing\\n      the cache memory access.\\n      Contiguity is the maximum number of elements that can be loaded in a single vector\\n      with the given layout and mask.\\n      This allows to use buffer_store even if the alignment cannot be proven based on IR.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"ptr\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"I32Tensor\" },\n      { \"name\": \"stride\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"contiguity\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'value', 'ptr', 'getPointerTypeToElement($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'value', 'offsets', 'getI32SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'value', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $ptr `[` $offsets `]` (`,` $mask^)?\\n      oilist(`cacheModifier` `=` $cache)\\n      (`stride` `=` $stride^)?\\n      attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"amdg.cluster_barrier_arrive\",\n    \"summary\": \"Arrive at a cluster barrier\",\n    \"description\": \"Signals that the cluster has arrived at a barrier, used to synchronizing CTAs within a cluster.\\n\\n    See ClusterBarrierWaitOp for how to wait on the arrived cluster barrier.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"amdg.cluster_barrier_wait\",\n    \"summary\": \"Wait on a cluster barrier\",\n    \"description\": \"Waits for all CTAs of the same cluster to have arrived at a cluster barrier.\\n    Arrive and wait operations must come in pairs. Waiting before arriving or arriving\\n    more than once without a corresponding wait will result in undefined behavior.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"amdg.concat\",\n    \"summary\": \"concat operation\",\n    \"description\": \"The \\\"concat\\\" operation combines a list of source n-dimensional tensors into a single larger destination tensor.\\n\\n    All source tensors must have the same shape, element type, and encoding.\\n    The concatenation dimension is inferred from the source and destination shapes provided by the user.\\n    For example, two tensors of shape 64x128 can produce a destination shape of 128x128,\\n    indicating concatenation along dimension 0; or 64x256, indicating concatenation along dimension 1.\\n\\n    Generally, source tensors passed as op arguments can be arranged into the resulting shape in multiple ways.\\n    For example, given four tensors of shape 64x64:\\n      concat s0<64x64>, s1<64x64>, s2<64x64>, s3<64x64> -> <128x128>\\n\\n    They can be laid out in different configurations within the result tensor:\\n      1) s0 s1     2) s0 s2\\n         s2 s3        s1 s3\\n\\n    From a logical tensor perspective, the source tensors are treated as elements of a tensor of tensors.\\n    In other words, the 1-D array of input tensors is conceptually reshaped into an n-D grid.\\n    The semantics of this op assume a row-major order (or its n-D generalization),\\n    meaning the fastest-varying dimension is filled first, and the slowest-varying dimension is filled last.\\n    In the example above, this corresponds to layout 1).\\n\\n    The source and destination tensors must have identical linear layouts at the CTA tile level.\\n    That is, all base vectors for input dimensions must match, except for the register input dimension.\\n    The register basis must align on the subset that defines the logical tensor shape of a single CTA tile.\\n\\n    This ensures that the concatenation is a no-op, meaning no data rearrangement among threads is required\\n    to assemble the destination tensor with the given shape and layout.\\n    However, the order of CTA tiles within the layout does not need to match between source and destination layouts.\\n    It is the responsibility of the op's lowering logic to handle this correctly.\\n\\n    This op is designed to work on logical tensors directly, avoiding the need for complex layout reinterpretation or reshaping.\\n    For example, the `tt.join` operation only supports concatenation along the innermost dimension,\\n    and requires that the resulting innermost dimension provide 2 elements per thread, distributed across registers.\\n    In contrast, this `concat` op imposes no constraints on the concatenation dimension or the size of dimensions.\\n\\n    * sources: a list of the input tensors.\\n\\n    Example 1:\\n\\n    ```mlir\\n    #blocked = #ttg.blocked<{sizePerThread = [1, 8],\\n        threadsPerWarp = [8, 8], warpsPerCTA = [4, 1], order = [1, 0]}>\\n    %0 = amdg.concat %arg0, %arg1: tensor<32x64xf32, #blocked>,tensor<32x64xf32, #blocked>,\\n      -> tensor<64x64xf32, #blocked>\\n    ```\\n\\n    Example 2:\\n    ```mlir\\n    #src_layout = #ttg.linear<{register=[[0, 1], [0, 2], [0, 8], [0, 16], [0, 64], [64, 0]], lane=[[1, 0], [2, 0], [4, 0], [8, 0], [16, 0], [0, 4]], warp=[[0, 32], [32, 0]], block=[]}>\\n    #dst_layout = #ttg.linear<{register=[[0, 1], [0, 2], [0, 8], [0, 16], [0, 64], [0, 128], [64, 0], [128, 0]], lane=[[1, 0], [2, 0], [4, 0], [8, 0], [16, 0], [0, 4]], warp=[[0, 32], [32, 0]], block=[]}>\\n    %0 = amdg.concat %arg0, %arg1, %arg2, %arg3 : tensor<128x128xf16, #src_layout>, tensor<128x128xf16, #src_layout>, tensor<128x128xf16, #src_layout>,\\n                                                    tensor<128x128xf16, #src_layout> -> tensor<256x256xf16, #dst_layout>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sources\", \"type\": \"Variadic<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$sources attr-dict `:` type($sources) `->` type($result)\"\n  },\n  {\n    \"name\": \"amdg.cond_barrier\",\n    \"summary\": \"Conditionally set barriers to synchronize partial threads in a block\",\n    \"description\": \"condBarrierOp sets barrier instruction only when the given argument is true.\\n      This provides a way to synchronize partial threads in a block, deliberately\\n      diverges the execution sequences. However, user should guarantee all threads\\n      converge at the end by calling condBarrierOp(true) with the remaining threads.\\n      Conceptually, this is similar to having an execution barrier inside an if statement.\\n      This op allows us to avoid blocking the whole block when suitable to help scheduling.\\n      NB. This doesn't set any memory fence.\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$pred attr-dict\"\n  },\n  {\n    \"name\": \"amdg.extract_slice\",\n    \"summary\": \"extract slice operation\",\n    \"description\": \"The \\\"extract_slice\\\" operation enables extracting a slice of a tensor in\\n    registers.\\n\\n    The \\\"extract_slice\\\" operation supports the following arguments:\\n\\n    * source: the base tensor on which to create a view tensor\\n    * offsets: offsets into the base tensor at which to create the view\\n\\n    In distributed layouts, tensors are divided into CTA tiles.\\n    A CTA tile represents the smallest contiguous portion of a tensor that is\\n    distributed across all threads and warps within a workgroup.\\n    The ExtractSlice operation extracts a portion of the tensor that is a\\n    multiple of CTA tiles.\\n\\n    The source and destination must have matching linear layouts at the CTA\\n    tile level. This ensures that the extract_slice is a no-op, meaning no data\\n    rearrangement between threads is required to extract the destination tensor\\n    with the given shape and layout.\\n\\n      +-------+-------+\\n      |  W0   |  W1   |\\n      |       |       |\\n      |   +   |   +   |\\n      |  W2   |  W3   |  <-- Single CTA tile (distributed across warps W0-W3)\\n      |       |       |\\n      |   +   |   +   |\\n      |       |       |\\n      +-------+-------+\\n      |          Source Tensor                    Extracted Slice\\n      |             .                           +--------------+\\n      |             .                           |  W0  |  W1   |\\n      |             .                           |      |       |\\n      |                                         |  +   |   +   |\\n      |                                         |  W2  |  W3   |\\n      |                                         |      |       |\\n      |                                         |  +   |   +   |\\n      |                                         |      |       |\\n      |                                         +-------+------+\\n      |                                         |  W0  |   W1  |\\n      |                                         |      |       |\\n      |                                         |  +   |   +   |\\n      |                                         |  W2     W3   |\\n      |                                         |      |       |\\n      |                                         |  +   |   +   |\\n      |                                         |      |       |\\n      |                                         +--------------+\\n\\n\\n    This op is designed to work on logical tensors directly, avoiding the need\\n    for complex layout reinterpretation or reshaping. For example, the tt.split\\n    operation only supports splitting along the innermost dimension,\\n    and requires that the resulting innermost dimension provide 2 elements per thread,\\n    distributed across registers. In contrast, extract_slice op imposes no constraints\\n    on the extraction dimension or the size of dimensions.\\n\\n    Example 1:\\n\\n    ```mlir\\n    #blocked = #ttg.blocked<{sizePerThread = [1, 8],\\n        threadsPerWarp = [4, 16], warpsPerCTA = [4, 1], order = [0, 1]}>\\n    #blocked1 = #ttg.blocked<{sizePerThread = [1, 8],\\n        threadsPerWarp = [16, 4], warpsPerCTA = [4, 1], order = [0, 1]}>\\n    %1 = ttg.convert_layout %0 : tensor<128x128xf16, #blocked>\\n        -> tensor<128x128xf16, #blocked1>\\n    // create a slice of base tensor %1 with static offsets\\n    %2 = amdg.extract_slice %0 [0, 0] :\\n      tensor<128x128xf16, #blocked1> to tensor<128x32xf16, #blocked1>\\n    ```\\n\\n    Example 1 shows how \\\"extract_slice\\\" operation may be used. In this example a\\n    new slice of 128x32 is created. \\\"extract_slice\\\" works on tensors\\n    where the desired slice has the same layout on a CTA tile as the source tensor.\\n    \\\"%0\\\" cannot be sliced directly as the resulting slice does not satisfy this condition.\\n    Therefore it needs to be converted to a layout suitable for slicing.\\n    \\\"#blocked1\\\" layout is appropriate for this as it keeps the\\n    sizePerThread the same thus keeping coalescing properties the same.\\n    In order to utilize all threads in a warp, \\\"threadsPerWarp\\\" is set to\\n    [16,4] for this new layout. This layout conversion carried out before\\n    using \\\"extract_slice\\\" ensures slicing still uses all threads efficiently. The\\n    size of the slice is determined by the result type.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source $static_offsets attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"amdg.in_thread_transpose\",\n    \"summary\": \"Perform transpose of register values belonging to each threads\",\n    \"description\": \"This operation performs a layout transpose over values in registers per thread.\\n    Specifically, given the input layout's blocked layout, it transposes the two last dimensions(rank-1 and rank-2)\\n    along the register dimension of the underlying linear layout.\\n\\n    Conversion example:\\n    * input layout: blocked layout with sizePerThread=[2, 2], order=[0, 1]. It's linear layout register bases = [[1, 0], [2, 0], [0, 1], [0, 2]]\\n    * output layout: same thread and warp bases as in input, register bases = [[0, 1], [0, 2], [1, 0], [2, 0]]\\n\\n    This operation enables efficient coalesced loading from HBM with following vectorized writing to shared memory\\n    in cases when HBM and shared memory order differ and target AMD hardware does not natively support this transposition.\\n    This is a specific variant of ttg.convert_layout and will be converted to ttg.convert_layout when lowering to llvm.\\n    We do not want this conversion to be optimized out, because we need to explicitly materialize instructions\\n    to transpose within each thread after loading from HBM and before writing to shared memory.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"amdg.init_barrier\",\n    \"summary\": \"Initialize a barrier in the given shared memory allocation.\",\n    \"description\": \"Initializes a shared memory allocation with mbarrier information.\\n      `alloc` is a descriptor to the shared memory allocation. `count` is the\\n      number of arrives expected by the barrier.\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $count attr-dict `:` qualified(type($alloc))\"\n  },\n  {\n    \"name\": \"amdg.instruction_sched_hint\",\n    \"summary\": \"A placeholder op for instruction scheduling hints within a basic block\",\n    \"description\": \"A placeholder op for instruction scheduling hints applied to instructions within\\n    a basic block where the placeholder op is located. This op is primarily intended\\n    to be used to adjust instruction scheduling inside the resulting main loop\\n    of a `tt.dot` operation. It's easier to identify dot ops at a high level and, thus,\\n    to mark intended scheduling regions. The hint ops are eventually lowered\\n    into LLVM AMDGPU instruction scheduling primitives, which are meant to control\\n    how different kinds of instructions (valu/mfma, global/shared memory, etc.) should\\n    interleave for better instruction level parallelism.\",\n    \"attributes\": [\n      { \"name\": \"variant\", \"type\": \"TritonAMDGPU_SchedHintVariantAttr{none|attention}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"amdg.local_load_packed_tranposed\",\n    \"summary\": \"Load a transposed packed tensor from shared memory into a distributed tensor\",\n    \"description\": \"Requires a M/N packed and M/N contiguous tensor in shared memory and will yield a K packed K contiguous tensor in registers.\\n      The packing change will change the shape of the tensor by doubling the M/N dimension and halving the K dimension.\\n      For example if A is 16x64 in shared memory, the result of this operation will be 32x32.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src (`token` $token^)? attr-dict `:` qualified(type($src)) `->` type($result)\"\n  },\n  {\n    \"name\": \"amdg.masked_load\",\n    \"summary\": \"Masked load operation\",\n    \"description\": \"Load operation with masking and multicast support. If the mask is true, loads from the given pointer. Works with LLVM types as a utility op for making LLVM conversion easier.\\n    On architectures supporting multicast, the `multicastMask`specifies which CTAs in the cluster request the same data. This allows the hardware to efficiently broadcast the\\n    data to multiple CTAs in the cluster.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"I1\" },\n      { \"name\": \"falseVal\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"multicastMask\", \"type\": \"Optional<I16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"forceNoAlias\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $mask `,` $falseVal (`,` $multicastMask^)?\\n    oilist(`cacheModifier` `=` $cache)\\n    (`forceNoAlias` $forceNoAlias^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"amdg.masked_store\",\n    \"summary\": \"Masked Store operation\",\n    \"description\": \"Store operation with masking support. If the mask is true, Store from the given pointer. Works with LLVM types as a utility op for making LLVM conversion easier.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"value\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"mask\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"forceNoAlias\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $value `,` $mask\\n    oilist(`cacheModifier` `=` $cache)\\n    (`forceNoAlias` $forceNoAlias^)?\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"amdg.memory_counter_wait\",\n    \"summary\": \"Wait for specified hardware counters\",\n    \"description\": \"Wait for the specified counters to be less-than or equal-to the provided\\n    values before continuing.\\n\\n    Counters can lower to different instructions on different architectires,\\n    including clamping to the some HW supported max value or combining multiple\\n    counters into one.\",\n    \"attributes\": [\n      { \"name\": \"load\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"store\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"ds\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"oilist( `load` `(` $load `)` | `store` `(` $store `)` | `ds` `(` $ds `)` ) attr-dict\"\n  },\n  {\n    \"name\": \"amdg.scaled_upcast_fp4\",\n    \"summary\": \"Upcast fp4 and then multiply scale\",\n    \"description\": \"Upcast fp4 (e2m1) values packed as i8 values and multiply with the given\\n    E8M0 scale encoded as BF16. This maps to `v_cvt_scalef32_*` intrinsics\\n    on the AMD CDNA4 architecture.\\n\\n    The lower 4 bits of the i8s represent the first fp4 element, and the upper\\n    4 bits the second fp4 element.\\n\\n    The `axis` attribute specifies the axis along which the fp4 elements are\\n    packed.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"RankedTensorOf<[I8]>\" },\n      { \"name\": \"scale\", \"type\": \"RankedTensorOf<[BF16, I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"RankedTensorOf<[AnyTypeOf<[F16, BF16, F32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$input `scale` $scale attr-dict\\n        `:` type($input) `,` type($scale) `->` type($output)\"\n  },\n  {\n    \"name\": \"amdg.scaled_upcast_fp8\",\n    \"summary\": \"Upcast Fp8 and then multiply scale\",\n    \"description\": \"Upcast fp8 (e4m3/e5m2) values and multiply with the given E8M0 scale\\n    encoded as BF16. This maps to `v_cvt_scalef32_*` intrinsics\\n    on the AMD CDNA4 architecture.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"RankedTensorOf<[AnyTypeOf<[F8E4M3FN, F8E5M2]>]>\" },\n      { \"name\": \"scale\", \"type\": \"RankedTensorOf<[AnyTypeOf<[BF16, I8]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"RankedTensorOf<[AnyTypeOf<[F16, BF16, F32]>]>\" }\n    ],\n    \"assemblyFormat\": \"$input `scale` $scale attr-dict\\n        `:` type($input) `,` type($scale) `->` type($output)\"\n  },\n  {\n    \"name\": \"amdg.tdm_prefetch\",\n    \"summary\": \"Prefetch data based on a TDM descriptor from global memory to L2.\",\n    \"description\": \"This operation prefetches data from global memory to L2. It is analogous to the AsyncTDMCopyGlobalToLocalOp,\\n    but it does not copy the data to local memory and instead only prefetches the data into the L2 cache.\\n    Speculative prefetches can generate more efficient assembly because they do not require out of bounds checks.\\n    However, they are dropped by the hardware in case the virtual address translation is not already cached at CU level.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"maybeOffsets\", \"type\": \"Optional<TT_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"speculative\", \"type\": \"BoolAttr\" },\n      { \"name\": \"returnOffsets\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $indices `]` `,` $pred `,` `speculative` `=` $speculative\\n    (`returnOffsets` $returnOffsets^)?\\n    attr-dict `:` qualified(type($desc))\\n    (`->` type($maybeOffsets)^)?\"\n  },\n  {\n    \"name\": \"amdg.upcast_mxfp\",\n    \"summary\": \"Convert an mxfp tensor to bf16/fp16\",\n    \"description\": \"Compute the bf16 encoded in the given mxfp number as per\\n    https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"scale\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fp_type\", \"type\": \"TT_ScaleDotElemTypeAttr{e4m3|e5m2|e2m3|e3m2|e2m1|bf16|fp16}\" },\n      { \"name\": \"fastMath\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $scale  `fp_type` `=` $fp_type attr-dict `:` type($src) `,` type($scale) `->` type($result)\"\n  },\n  {\n    \"name\": \"amdg.wait_barrier\",\n    \"summary\": \"wait until the mbarrier phase completes.\",\n    \"description\": \"Blocks the program progress until the mbarrier object in `alloc` completes\\n    its current phase.\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"phase\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $phase attr-dict `:` qualified(type($alloc))\"\n  },\n  {\n    \"name\": \"amdgpu.dpp\",\n    \"summary\": \"AMDGPU DPP operation\",\n    \"description\": \"The `amdgpu.dpp` op performs a Data Parallel Primitives (DPP) lane\\n    permutation on a source value within a wavefront. Each lane reads its\\n    source data from another lane according to the permutation mode specified\\n    by `kind`. DPP operates at dword (32-bit) granularity: sub-32-bit types\\n    (e.g., f16, i16) are packed into an i32 during lowering, permuted, and\\n    extracted back.\\n\\n    - Lanes are organized into rows of 16.\\n    - A Wave64 wavefront has 4 rows of 16 lanes each: row 0 = lanes 0-15,\\n      row 1 = lanes 16-31, row 2 = lanes 32-47, row 3 = lanes 48-63.\\n    - Similarly, a Wave32 wavefront has two rows of 16 lanes each, organized\\n      in the same fashion.\\n    - Each row is divided into 4 banks of 4 consecutive lanes: bank 0 =\\n      lanes 0-3, bank 1 = lanes 4-7, bank 2 = lanes 8-11, bank 3 =\\n      lanes 12-15 (lane numbers shown for row 0; add 16/32/48 for other rows).\\n\\n    The `kind` attribute selects the permutation. Some modes require a\\n    `permArgument`; others take no argument.\\n\\n    Quad permutation:\\n    - `quad_perm([a, b, c, d])`: Full permute within each group of 4\\n      consecutive lanes (a quad). Each element is in [0, 3] and selects which\\n      lane within the quad to read from. Lane 4k+i reads from lane 4k+perm[i].\\n      For example, `quad_perm([1, 0, 3, 2])` swaps adjacent pairs within\\n      every quad.\\n\\n    Row shifts and rotates (operate within each 16-lane row independently):\\n    - `row_shl(N)`: Shift left by N (1-15) within the row. Lane n reads from\\n      lane (n % 16) + N in the same row. Lanes where the source index exceeds\\n      15 are out of bounds (see `bound_ctrl`).\\n    - `row_shr(N)`: Shift right by N (1-15) within the row. Lane n reads from\\n      lane (n % 16) - N in the same row. Lanes where the source index is\\n      negative are out of bounds.\\n    - `row_ror(N)`: Rotate right by N (1-15) within the row. Lane n reads from\\n      lane ((n % 16) - N) mod 16 in the same row. Always in bounds.\\n\\n    Wavefront shifts and rotates (not available on RDNA):\\n    - `wave_shl`: Shift left by 1. Lane n reads from lane n + 1. The last lane\\n      in the wavefront is out of bounds.\\n    - `wave_shr`: Shift right by 1. Lane n reads from lane n - 1. Lane 0 is\\n      out of bounds.\\n    - `wave_rol`: Rotate left by 1. Lane n reads from lane (n + 1) mod W, where\\n      W is the wavefront size.\\n    - `wave_ror`: Rotate right by 1. Lane n reads from lane (n - 1) mod W, where\\n      W is the wavefront size.\\n\\n    Row mirrors:\\n    - `row_mirror`: Reverse lanes within each 16-lane row. Lane n reads from\\n      lane 15 - (n % 16) within its row.\\n    - `row_half_mirror`: Reverse within each 8-lane half-row. Lane n reads\\n      from lane 7 - (n % 8) within its half-row.\\n\\n    Row broadcasts (not available on RDNA):\\n    - `row_bcast_15`: Lane 15 of each row broadcasts to all lanes of the next\\n      row. Lanes in row 0 are not affected (retain `old`).\\n    - `row_bcast_31`: Lane 31 broadcasts to all lanes in rows 2 and 3.\\n      Lanes in rows 0 and 1 are not affected (retain `old`).\\n\\n    Example:\\n    ```mlir\\n    // Swap adjacent pairs within each quad (lanes 0<->1, 2<->3, etc.)\\n    %0 = amdgpu.dpp %old %src quad_perm( [1, 0, 3, 2] ) : i32\\n\\n    // Shift right by 1 lane within each 16-lane row.\\n    // bound_ctrl=true -> lanes that would read past the row return 0.\\n    // row_mask=0x5 (0b0101) -> only rows 0 and 2 apply the shift;\\n    // rows 1 and 3 pass through %old unchanged.\\n    %1 = amdgpu.dpp %old %src row_shr( 0x1 : i32 )\\n      { row_mask = 0x5 : i32, bound_ctrl = true } : f32\\n\\n    // Rotate left across the full wavefront by 1 lane\\n    %2 = amdgpu.dpp %old %src wave_rol : i32\\n    ```\\n\\n    Operands:\\n    * `$old`: Fallback value. Lanes that are masked off by `row_mask` /\\n      `bank_mask` retain `old`. For lanes with an out-of-bounds source, behavior\\n      depends on `bound_ctrl`.\\n    * `$src`: Source value to be permuted across lanes.\\n    * `$kind`: A `#amdgpu.dpp_perm` enum selecting the permutation mode.\\n    * `$permArgument`: Mode-specific argument. Required for `quad_perm`\\n      (array of 4 integers in [0, 3]) and `row_shl`/`row_shr`/`row_ror`\\n      (integer in [1, 15]). Absent for all other modes.\\n    * `$row_mask` (default 0xf): 4-bit mask controlling which rows write\\n      results. Bit i enables row i (bit 0 = lanes 0-15, bit 1 = lanes\\n      16-31, etc.). Disabled lanes retain `old`.\\n    * `$bank_mask` (default 0xf): 4-bit mask controlling which banks write\\n      results. Bit i enables bank i (bit 0 = lanes 0-3, 16-19, etc. across all rows).\\n      Disabled lanes retain `old`.\\n    * `$bound_ctrl` (default false): When false, out of bounds lanes retain\\n      `old`. When true, out-of-bounds lanes receive zero.\",\n    \"operands\": [\n      { \"name\": \"old\", \"type\": \"AMDGPU_IntOrFloatOr1DVectorWidthLeq64\" },\n      { \"name\": \"src\", \"type\": \"AMDGPU_IntOrFloatOr1DVectorWidthLeq64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"AMDGPU_DPPPermAttr{quad_perm|row_shl|row_shr|row_ror|wave_shl|wave_shr|wave_ror|wave_rol|row_mirror|row_half_mirror|row_bcast_15|row_bcast_31}\" },\n      { \"name\": \"permArgument\", \"type\": \"OptionalAttr<AnyAttrOf<[ I32Attr, ArrayAttr, UnitAttr ]>>\" },\n      { \"name\": \"row_mask\", \"type\": \"DefaultValuedAttr<I32Attr, 0xf>\" },\n      { \"name\": \"bank_mask\", \"type\": \"DefaultValuedAttr<I32Attr, 0xf>\" },\n      { \"name\": \"bound_ctrl\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'old', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$old $src $kind (`(` $permArgument^ `)`)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_async_barrier_arrive\",\n    \"summary\": \"Asynchronously arrive at an in-LDS barrier.\",\n    \"description\": \"Add a arrival to the LDS barrier at `base[indices]` to the sequence of pending\\n    asynchronous memory operations.\\n\\n    This will add an \\\"asynchronous memory operation\\\" to the in-order list of pending\\n    asynchronous loads from global memory to LDS. When the queue of such operations\\n    issued before this operation is complete, the specified barrier will be arrived at,\\n    decrementing the pending count by 1 **per lane that executes it** and rolling\\n    over the phase if applicable.\\n\\n    This operation does not return the old barrier state.\\n\\n    Example:\\n    ```mlir\\n    amdgpu.ds_async_barrier_arrive %barrier[] : memref<!amdgpu.ds_barrier_state, #gpu.address_space<workgroup>>\\n    ```\\n\\n    This operation is only available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"MemRefOf<[ AMDGPU_DsBarrierStateType ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` attr-dict `:` type($base)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_arrive\",\n    \"summary\": \"Arrive at an in-LDS barrier and return old state.\",\n    \"description\": \"Atomically arrive at the LDS barrier at `base[indices]` and decrement it by `count`,\\n    rolling over the phase if needed and returning the old barrier state.\\n\\n    `count` is the number of participants that should be subtracted from the barrier's\\n    pending count **per lane that executes the operation**.\\n\\n    Example:\\n    ```mlir\\n    %old_state = amdgpu.ds_barrier_arrive %barrier[], %c1 : memref<!amdgpu.ds_barrier_state, #gpu.address_space<workgroup>>, i64 -> !amdgpu.ds_barrier_state\\n    ```\\n\\n    This operation is only available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"MemRefOf<[ AMDGPU_DsBarrierStateType ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"count\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AMDGPU_DsBarrierStateType\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $count attr-dict `:` type($base) `,` type($count) `->` type($out)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_init\",\n    \"summary\": \"Initialize an in-LDS barrier.\",\n    \"description\": \"Given the location `!amdgpu.ds_barrier_state` in LDS (as specified by `base` and `indices`),\\n    initialize the barrier structure so that the pending and init counts are equal to\\n    `participants - 1`, which will have its high bits masked off, and its phase is equal to 0.\\n\\n    Note that we subtract 1 from `participants` when constructing the barrier state\\n    to provide clearer high-level semantics.\\n\\n    The subtraction means that, when the `participant`th arrival occurs, the phase will change.\\n    In practical terms, this means that you can use (for example) the number of subgroups or\\n    waves per workgroup as `participants`, instead of manually needing to remove one.\\n\\n    While the write of the initial state will be performed atomically, no synchronization\\n    between waves will be performed by this operation.\\n\\n    Example:\\n    ```mlir\\n    amdgpu.ds_barrier_init %barrier[], %c32 : memref<!amdgpu.ds_barrier_state, #gpu.address_space<workgroup>>, i32\\n    ```\\n\\n    This operation is only available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"MemRefOf<[ AMDGPU_DsBarrierStateType ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"participants\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $participants attr-dict `:` type($base) `,` type($participants)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_poll_state\",\n    \"summary\": \"Atomically read the state of an in-LDS barrier.\",\n    \"description\": \"Atomically read and return the state of the barrier at `base[indices...]`.\\n\\n    This will ultimately act like a `memref.load`, but this operation will ensure\\n    that appropriate atomic orderings and syncscopes are set.\\n\\n    Example:\\n    ```mlir\\n    %state = amdgpu.ds_barrier_poll_state %barrier[] : memref<!amdgpu.ds_barrier_state, #gpu.address_space<workgroup>> -> !amdgpu.ds_barrier_state\\n    ```\\n\\n    This operation is only available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"MemRefOf<[ AMDGPU_DsBarrierStateType ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AMDGPU_DsBarrierStateType\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` attr-dict `:` type($base) `->` type($out)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_state_init_count\",\n    \"summary\": \"Extract the init count of a barrier state.\",\n    \"description\": \"Extract the init count of the `!amdgpu.ds_barrier_state` `state` as a 32-bit value.\\n\\n    Example:\\n    ```mlir\\n    %init = amdgpu.ds_barrier_state_init_count %state : !amdgpu.ds_barrier_state -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"AMDGPU_DsBarrierStateType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$state attr-dict `:` type($state) `->` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_state_pending_count\",\n    \"summary\": \"Extract the pending count of a barrier state.\",\n    \"description\": \"Extract the pending count of the `!amdgpu.ds_barrier_state` `state` as a 32-bit value.\\n\\n    Example:\\n    ```mlir\\n    %pending = amdgpu.ds_barrier_state_pending_count %state : !amdgpu.ds_barrier_state -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"AMDGPU_DsBarrierStateType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$state attr-dict `:` type($state) `->` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_state_phase\",\n    \"summary\": \"Extract the phase of a barrier state.\",\n    \"description\": \"Extract the phase of the `!amdgpu.ds_barrier_state` `state` as a 32-bit value.\\n\\n    Example:\\n    ```mlir\\n    %phase = amdgpu.ds_barrier_state_phase %state : !amdgpu.ds_barrier_state -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"AMDGPU_DsBarrierStateType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$state attr-dict `:` type($state) `->` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.ds_barrier_state_phase_parity\",\n    \"summary\": \"Extract the phase parity of a barrier state.\",\n    \"description\": \"Return the parity of the phase of the `!amdgpu.ds_barrier_state` `state`.\\n\\n    This is intended to simplify the case where the barrier is being used to repeatedly\\n    track completion of a task where the precise value of the phase won't mater, only that\\n    it changed since (or as a result of) the arrival.\\n\\n    Example:\\n    ```mlir\\n    %parity = amdgpu.ds_barrier_state_phase_parity %state : !amdgpu.ds_barrier_state -> i1\\n    ```\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"AMDGPU_DsBarrierStateType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$state attr-dict `:` type($state) `->` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.ext_packed_fp8\",\n    \"summary\": \"Extend a fp8 value to a float or a vector of packed fp8 values to two floats\",\n    \"description\": \"Extend one or two 8-bit floats in `source[index]` to a 32-bit float or\\n    two floats and return them.\\n\\n    This rather unusual signature arises from the fact that AMD GPUs cannot\\n    easily work with sub 32-bit quantities, so the compiler intrinsics for\\n    extending 8-bit floats (which are, currently, the only way to work with\\n    this operation) take packed vectors of 4 such floats.\\n\\n    If the passed-in vector has fewer than four elements, or the input is scalar,\\n    the remaining values in the <4 x i8> will be filled with\\n    undefined values as needed.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[F8E5M2FNUZ, F8E4M3FNUZ, F8E5M2, F8E4M3FN, VectorOfLengthAndType<[1, 2, 3, 4], [F8E5M2FNUZ, F8E4M3FNUZ, F8E5M2, F8E4M3FN]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[F32, FixedVectorOfLengthAndType<[2], [F32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<3>]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `[` $index `]` `:` type($source) `to` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.fat_raw_buffer_cast\",\n    \"summary\": \"Create a raw buffer fat pointer that matches `memref`\",\n    \"description\": \"Wraps the memory pointed to by `source` as a raw buffer fat pointer, or,\\n    in LLVM terms, a `ptr addrspace(7)`, returning a memref that has the same\\n    sizes and layout but the `#amdgpu.address_space<fat_raw_buffer>`\\n    address space.\\n\\n    This memref can be used with standard memref operations like `memref.load`,\\n    `memref.store`, and `memref.atomicrmw`, which will be lowered to the relevant\\n    buffer intrinsics. (`vector.masked_load/store` will work once there's backend\\n    support for lowering them, and then this document will be updated)\\n\\n    If `validBytes` is given, it is the number of bytes that will be valid as\\n    an offset to `out`. If it is not provided, this will be inferred from\\n    the size of the memref during lowering. This size is\\n    max_{d = 0 upto rank(source)} (sizes[d] * strides[d]) * sizeof(element type).\\n\\n    The flags of the buffer descriptor will be set up to enable raw usage -\\n    for example, stride = 0, add_tid = 0, and so on. The `boundsCheck`\\n    property determines if bounds checking is enabled or not (on architectures\\n    where this can be controlled - that is, on RDNA chips).\\n\\n    If `cacheSwizzleStride` is provided, L1 cache swizzling will be enabled\\n    on architectures that support it. This swizzling, unlike the main swizzling\\n    mode (whose usage makes a buffer non-raw) does not affect index calculation,\\n    but does affect cache behavior. Mixing access between cache-swizzled raw\\n    buffers and other forms of memory access, like ordinary pointer loads or\\n    unswizzled buffer pointers can cause incorrect behavior and must be avoided.\\n\\n    This operation preserves the sizes, strides, and offset of the input\\n    memref - they'll be added in by `memref.load` later. However, if\\n    `resetOffset` is set, that offset will be added to the base pointer.\\n    If the value of the memref's offset is not uniform (independent of the lane/thread ID),\\n    this will lead to substantially decreased performance due to the need for\\n    a waterfall loop on the base address of the buffer resource.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"validBytes\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"cacheSwizzleStride\", \"type\": \"Optional<I<14>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"resetOffset\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source oilist (`validBytes` `(` $validBytes `)`\\n      | `cacheSwizzleStride` `(` $cacheSwizzleStride `)`\\n      | `boundsCheck` `(` $boundsCheck `)`\\n      | `resetOffset` $resetOffset )\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"amdgpu.gather_to_lds\",\n    \"summary\": \"MLIR wrapper for CDNA Gather to LDS instructions\",\n    \"description\": \"The `amdgpu.gather_to_lds` op is a wrapper around the `global_load_lds` instructions.\\n\\n    Operands:\\n    * `$src`: global memory (including fat buffer) memref to read from.\\n    * `$srcIndices`: indices into `$src` to read from for this thread.\\n    * `$dst`: LDS memory memref to write to.\\n    * `$dstIndices`: base indices into `$dst` to write to for the subgroup of this thread.\\n      The elements gathered by the subgroup will be written contiguously in order of lane ID\\n      starting at `$dst[$dstIndices]`. Byte-sized (ex. i8) or short-sized (ex. i16)\\n      types will be zero-padded/extended to 32 bits before being written. 96-bit types\\n      (ex. vector<3xf32>) will be zero-padded to 128 bits before being written. Only the\\n      offsets held by lane 0 are used.\\n    * `$transferType`: type of the data to be transferred by each thread. This is used to determine\\n      the size of the data to be transferred and the number of threads in the subgroup.\\n      The transfer type must be a scalar type or a vector type with a single element type.\\n    * If `$async` is set, the compiler will not attempt to infer the\\n      memory waits needed to ensure that the DMA operation has succeeded\\n      before a load that might access the stored-to LDS is performed.\\n      Instead, the `rocdl.asyncmark` and `rocdl.wait.asyncmark N`\\n      operations must be used to explicitly indicate the desired completion\\n      behavior. This enables more precise calculation of these waits at the\\n      cost of requiring user management of asynchrony.\\n\\n    The `$dst`, along with its indices, points to the memory location the subgroup of this thread\\n    will write to.\\n\\n    Note: only supported on gfx9 and gfx10.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"srcIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"dstIndices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transferType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"async\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`async` $async^)? $src `[` $srcIndices `]` `,` $dst `[` $dstIndices `]` attr-dict `:` $transferType `,` type($src) `,` type($dst)\"\n  },\n  {\n    \"name\": \"amdgpu.lds_barrier\",\n    \"summary\": \"Barrier that includes a wait for LDS memory operations.\",\n    \"description\": \"**DEPRECATION NOTICE**: Unless you need the inline-assembly-based workaround\\n    for gfx908/MI-100, you should represent this pattern with the equivalent\\n\\n    ```mlir\\n    gpu.barrier memfence [#gpu.address_space<workgroup>]\\n    ```\\n\\n    instead.\\n\\n    `amdgpu.lds_barrier` is both a barrier (all workitems in a workgroup must reach\\n    the barrier before any of them may proceed past it) and a wait for all\\n    operations that affect the Local Data Store (LDS) issued from that workgroup\\n    to complete before the workgroup may continue. Since the LDS is per-workgroup\\n    memory, this barrier may be used, for example, to ensure all workitems have\\n    written data to LDS before any workitem attempts to read from it.\\n\\n    Note that `lds_barrier` does **not** force reads to or from global memory\\n    to complete before execution continues. Therefore, it should be used when\\n    operations on global memory can be issued far in advance of when their results\\n    are used (for example, by writing them to LDS).\\n\\n    WARNING: On architectures that do not support the BackOffBarrier feature,\\n    (those which will implement this barrier by emitting inline assembly),\\n    use of this operation will impede the usabiliity of memory watches (including\\n    breakpoints set on variables) when debugging.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"amdgpu.make_dma_base\",\n    \"summary\": \"Pair of based addresses used when moving tiles between LDS and global memory.\",\n    \"description\": \"This operation creates a pair of addresses that will be used by tensor_load_to_lds\\n    and tensor_store_from_lds.\\n\\n    This operation creates a value corresponding to the tensor descriptor (D#) group 0\\n    found in TensorLoadToLDSOp and TensorStoreFromLDSOp in the rocdl dialect.\\n\\n    For example:\\n\\n    ```mlir\\n      %base = amdgpu.make_dma_base %global[%idx0, %idx1], %lds[%idx2, %idx3] : memref<64x64xi32>, memref<64x64xi32, #gpu.address_space<workgroup>> -> !amdgpu.tdm_base<i32>\\n      %descriptor = amdgpu.make_dma_descriptor %base globalSize [2, 2] globalStride [2, 1] sharedSize [2, 2] : !amdgpu.tdm_base<i32> -> !amdgpu.tdm_descriptor\\n      amdgpu.tensor_load_to_lds %descriptor : !amdgpu.tdm_descriptor\\n    ```\\n\\n    to\\n\\n    ```mlir\\n      // pseudo-code\\n      %global_base = llvm.extractvalue %global_memref[1]\\n      %global_address = llvm.get_element_ptr ...\\n\\n      %lds_base = llvm.extractvalue %lds_memref[1]\\n      %lds_address = llvm.get_element_ptr ...\\n\\n      // Definition of %base\\n      %undef = llvm.mlir.undef : vector<4xi32>\\n      %v0 = llvm.insertelement %15, %undef[0] : vector<4xi32>\\n      %v1 = llvm.insertelement %lds_address, %v0[1] : vector<4xi32>\\n      %v2 = llvm.insertelement %global_address_low, %v1[2] : vector<4xi32>\\n      %base = llvm.insertelement %global_address_high, %v2[3] : vector<4xi32>\\n\\n      rocdl.tensor.load.to.lds %base, %dgroup1, %dgroup2, %dgroup3 cachepolicy 0 : vector<4xi32>, vector<8xi32>\\n    ```\\n\\n    These tensor DMA operations were introduced in gfx1250.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"global_indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"lds\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"lds_indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"base\", \"type\": \"AMDGPU_TDMBaseType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$global `[` $global_indices `]` `,` $lds `[` $lds_indices `]` attr-dict `:` type($global) `,` type($lds) `->` type(results)\"\n  },\n  {\n    \"name\": \"amdgpu.make_dma_descriptor\",\n    \"summary\": \"Make all descriptor groups needed by TensorLoadToLDS/TensorStoreFromLDS.\",\n    \"description\": \"Make all descriptor groups needed by tensor memory operations.\\n\\n     The $base operand corresponds to the base pair addresses, one must be an address in LDS\\n     while the other must be a global memory location.\\n\\n     $global_{static/dynamic}_sizes determine the size of the tensor.\\n     $global_{static/dynamic}_strides determine the strides of the tensor.\\n     $shared_{static/dynamic}_sizes determines the size of the tile.\\n\\n     $workgroup_mask broadcast load to workgroups inside of a workgroup cluster\\n     (0 = do not broadcast result to workgroup, 1 = broadcast result to workgroup). Ignored for stores.\\n     An all zeros mask is interpreted as a non-broadcasted load.\\n\\n     $early_timeout return data to requesters as soon as cache supplies it.\\n\\n     Padding can be applied to the LDS address when copying from memory to LDS,\\n     but not when copying from LDS to memory.\\n     The values in the padded target addresses remain the same as before the operation was applied.\\n     $pad_interval must be a power of two contained in [2, 256].\\n     $pad_amount must be a value contained in [1, 128].\\n\\n     If an atomic barrier is provided, it will be arrived at **once** after\\n     each load/store using this descriptor is completed.\\n\\n     2D and 3D tensors may be iterated over by setting $global_increment, $lds_increment, and $iteration_count.\\n     $global_increment determines how much to increment the starting global memory address per iteration in units of the $base's element type.\\n     $lds_increment determines how much to increment the starting LDS address per iteration in units of the $base's element type.\\n     $iterate_count determines how many times to iterate, it must be a value in the inclusive interval [1, 256].\\n\\n     ```mlir\\n      // Example of moving a two-dimensional tensor to LDS.\\n      %base = amdgpu.make_dma_base %global[0, 0], %lds[0, 0] : memref<64x64xi32>, memref<64x64xi32, #gpu.address_space<workgroup>> -> !amdgpu.tdm_base<i32>\\n      %descriptor = amdgpu.make_dma_descriptor %base globalSize [64, 64] globalStride [64, 1] sharedSize [64, 64] : !amdgpu.tdm_base<i32> -> !amdgpu.tdm_descriptor\\n      amdgpu.tensor_load_to_lds %descriptor : !amdgpu.tdm_descriptor\\n\\n      // Example of moving a two dimension tensor to LDS where padding is applied after every integer.\\n      %base = amdgpu.make_dma_base %global[0, 0], %lds[0, 0] : memref<32x32xi32>, memref<64x64xi32, #gpu.address_space<workgroup>> -> !amdgpu.tdm_base<i32>\\n      %descriptor = amdgpu.make_dma_descriptor %base globalSize [32, 32] globalStride [32, 1] sharedSize [64, 64] padShared(%pad_amount every %pad_interval) : !amdgpu.tdm_base<i32> -> !amdgpu.tdm_descriptor\\n      amdgpu.tensor_load_to_lds %descriptor : !amdgpu.tdm_descriptor\\n     ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AMDGPU_TDMBaseType\" },\n      { \"name\": \"global_dynamic_sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"global_dynamic_strides\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"shared_dynamic_sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"workgroup_mask\", \"type\": \"Optional<AMDGPU_ConcreteVector<I1, 16>>\" },\n      { \"name\": \"early_timeout\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"pad_amount\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"pad_interval\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"atomic_barrier_address\", \"type\": \"Optional<MemRefOf<[ AMDGPU_DsBarrierStateType ]>>\" },\n      { \"name\": \"atomic_barrier_indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"global_increment\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"lds_increment\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"iteration_count\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"desc\", \"type\": \"AMDGPU_TDMDescriptorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global_static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"global_static_strides\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"shared_static_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$base\\n    `globalSize` custom<DynamicIndexList>($global_dynamic_sizes, $global_static_sizes)\\n    `globalStride` custom<DynamicIndexList>($global_dynamic_strides, $global_static_strides)\\n    `sharedSize` custom<DynamicIndexList>($shared_dynamic_sizes, $shared_static_sizes)\\n    ( `padShared` `(` $pad_amount^ `every` $pad_interval `)` )?\\n    ( `workgroupMask` $workgroup_mask^ ( `earlyTimeout` $early_timeout^)?)?\\n    ( `atomicBarrier` `(` $atomic_barrier_address^ `[` $atomic_barrier_indices `]`\\n                      `:` type($atomic_barrier_address) `)`)?\\n    ( `iterate` $global_increment^ `,` $lds_increment `,` $iteration_count )?\\n    attr-dict `:` qualified(type($base)) `->` type(results)\"\n  },\n  {\n    \"name\": \"amdgpu.make_gather_dma_base\",\n    \"summary\": \"Pair of based addresses used when moving tiles between LDS and global memory.\",\n    \"description\": \"This operation creates a pair of addresses that will be used by `tensor_load_to_lds`\\n    and `tensor_store_from_lds`.\\n\\n    This operation creates a value corresponding to the tensor descriptor (D#) group 0\\n    found in TensorLoadToLDSOp and TensorStoreFromLDSOp in the rocdl dialect.\\n\\n    Unlike `make_dma_base`, this operation returns `!amdgpu.tdm_gather_base<$element_type, $index_type>`\\n    which is only compatible with `make_gather_dma_descriptor`. Using the descriptor returned\\n    by `make_gather_dma_descriptor` will set the `tensor_load_to_lds` and `tensor_store_from_lds` to gather mode.\\n\\n    ```mlir\\n      %base = amdgpu.make_gather_dma_base %global[%idx0, %idx1], %lds[%idx2, %idx3] : memref<64x64xi32>, memref<64x64xi32, #gpu.address_space<workgroup>> -> !amdgpu.tdm_gather_base<i32, i16>\\n      // %indices : i16\\n      %descriptor = amdgpu.make_gather_dma_descriptor %base[%indices] globalSize [2, 2] globalStride [2, 1] sharedSize [2, 2] : !amdgpu.tdm_gather_base<i32, i16>, i16 -> !amdgpu.tdm_descriptor\\n      amdgpu.tensor_load_to_lds %descriptor : !amdgpu.tdm_descriptor\\n    ```\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"global_indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"lds\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"lds_indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"base\", \"type\": \"AMDGPU_TDMGatherBaseType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$global `[` $global_indices `]` `,` $lds `[` $lds_indices `]` attr-dict `:` type($global) `,` type($lds) `->` type(results)\"\n  },\n  {\n    \"name\": \"amdgpu.make_gather_dma_descriptor\",\n    \"summary\": \"Make all descriptor groups needed by TensorLoadToLDS/TensorStoreFromLDS.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AMDGPU_TDMGatherBaseType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[VectorOfMinMaxLengthAndType<1, 8, [I32]>, VectorOfMinMaxLengthAndType<1, 16, [I16]>]>\" },\n      { \"name\": \"global_dynamic_sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"global_dynamic_strides\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"shared_dynamic_sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"workgroup_mask\", \"type\": \"Optional<AMDGPU_ConcreteVector<I1, 16>>\" },\n      { \"name\": \"early_timeout\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"pad_amount\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"pad_interval\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"atomic_barrier_address\", \"type\": \"Optional<MemRefOf<[ AMDGPU_DsBarrierStateType ]>>\" },\n      { \"name\": \"atomic_barrier_indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"global_increment\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"lds_increment\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"iteration_count\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"desc\", \"type\": \"AMDGPU_TDMDescriptorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global_static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"global_static_strides\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"shared_static_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]`\\n    `globalSize` custom<DynamicIndexList>($global_dynamic_sizes, $global_static_sizes)\\n    `globalStride` custom<DynamicIndexList>($global_dynamic_strides, $global_static_strides)\\n    `sharedSize` custom<DynamicIndexList>($shared_dynamic_sizes, $shared_static_sizes)\\n    ( `padShared` `(` $pad_amount^ `every` $pad_interval `)` )?\\n    ( `workgroupMask` $workgroup_mask^ ( `earlyTimeout` $early_timeout^)?)?\\n    ( `atomicBarrier` `(` $atomic_barrier_address^ `[` $atomic_barrier_indices `]`\\n                      `:` type($atomic_barrier_address) `)`)?\\n    ( `iterate` $global_increment^ `,` $lds_increment `,` $iteration_count )?\\n    attr-dict `:` qualified(type($base)) `,` type($indices) `->` type(results)\"\n  },\n  {\n    \"name\": \"amdgpu.memory_counter_wait\",\n    \"summary\": \"Wait for specified hardware counters\",\n    \"description\": \"Wait for the specified counters to be less-than or equal-to the provided\\n    values before continuing.\\n\\n    Counters can lower to different instructions on different architectires,\\n    including clamping to the some HW supported max value or combining multiple\\n    counters into one.\",\n    \"attributes\": [\n      { \"name\": \"load\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"store\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"ds\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"exp\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"tensor\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"oilist( `load` `(` $load `)` | `store` `(` $store `)` | `ds` `(` $ds `)` | `exp` `(` $exp `)` | `tensor` `(` $tensor `)` ) attr-dict\"\n  },\n  {\n    \"name\": \"amdgpu.mfma\",\n    \"summary\": \"MLIR wrapper for CDNA mfma instructions\",\n    \"description\": \"The `amdgpu.mfma` op is an MLIR wrapper around intrinsics\\n    for various `mfma` instructions in the CDNA architecture, which perform\\n    multiple outer products in order to allow fast matrix multiplication.\\n\\n    The wrapper will select an appropriate `mfma` instruction, if one is available,\\n    based on the provided `m`, `k`, `n`, and `nBlks` attributes, along with the\\n    types of the source and destination arguments.\\n\\n    For information on the layouts of the input and output matrices (which are stored\\n    in `sourceA`, `sourceB`, `destC`, and `destD`), see the CDNA ISA documentation.\\n\\n    The `cbsz`, `abid`, and `blgp` parameters control how the lanes of the wave\\n    are permuted when matrix data is being loaded: `blgp` can be any number of\\n    fixed permutations, `cbsz` specifies the log_2 of the number of chunks the lanes\\n    holding sourceA are split into, and `abid` selects one of those chunks.\\n\\n    Note, this wrapper allows specifying `vector<4Kxi8>` arguments to MFMA\\n    intrinsics that take an integer type of width `4K`. For example,\\n    one can provide a vector<4xi8> as an argument to an MFMA instruction that\\n    logically takes 4 i8s but whose intrinsics are specified to take an i32.\\n    In these cases, the bytes in the vector will be concatenated in little-endian\\n    order (that is, v[0] will go to arg[7:0], v[1] to arg[15:8] and so on).\\n\\n    The negateA, negateB, and negateC flags are only supported for double-precision\\n    operations on gfx94x.\\n\\n    Example:\\n    ```mlir\\n      %0 = amdgpu.mfma 16x16x16 %matA * %matB + %matC\\n        : vector<4xf16>, vector<4xf16>, vector<4xf32>\\n\\n      %1 = amdgpu.mfma 32x32x1 %matD * %matE + %matF\\n        { abid = 1 : i32, cbsz = 1 : i32, blocks = 2 : i32 }\\n        blgp = bcast_second_32 : f32, f32, vector<32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"MFMAInTypes\" },\n      { \"name\": \"sourceB\", \"type\": \"MFMAInTypes\" },\n      { \"name\": \"destC\", \"type\": \"MFMAOutTypes\" }\n    ],\n    \"results\": [\n      { \"name\": \"destD\", \"type\": \"MFMAOutTypes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[4, 16, 32]>]>\" },\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[4, 16, 32]>]>\" },\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[1, 2, 4, 8, 16, 32, 64, 128]>]>\" },\n      { \"name\": \"blocks\", \"type\": \"DefaultValuedAttr<ConfinedAttr<I32Attr, [ IntIsOneOf < [ 1 , 2 , 4 , 16 ] > ]>, 1>\" },\n      { \"name\": \"cbsz\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"abid\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"blgp\", \"type\": \"DefaultValuedAttr<AMDGPU_MFMAPermBAttr{none|bcast_first_32|bcast_second_32|rotate_16_right|bcast_first_16|bcast_second_16|bcast_third_16|bcast_fourth_16}, ::mlir::amdgpu::MFMAPermB::none>\" },\n      { \"name\": \"reducePrecision\", \"type\": \"UnitAttr\" },\n      { \"name\": \"negateA\", \"type\": \"UnitAttr\" },\n      { \"name\": \"negateB\", \"type\": \"UnitAttr\" },\n      { \"name\": \"negateC\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['destC', 'destD']>\" }\n    ],\n    \"assemblyFormat\": \"custom<MNKDimensionList>($m, $n, $k) $sourceA `*` $sourceB `+` $destC\\n    attr-dict\\n    `blgp` `=` $blgp\\n    `:` type($sourceA) `,` type($sourceB) `,` type($destC)\"\n  },\n  {\n    \"name\": \"amdgpu.packed_scaled_trunc\",\n    \"summary\": \"Round two floats into a packed vector of floats\",\n    \"description\": \"Scale and round the inputs `source` (which is undefined if not\\n    specified) into the low or high word (bottom two or top two) elements\\n    of the returned vector, keeping the other two elements of `existing`\\n    unchanged if present (or undefined if it was not passed in).\\n\\n    The reason for this odd signature is that AMD GPUs cannot easily work with\\n    sub-registers, and so the conversion intrinsics take 32-bit wide\\n    packed vectors of float values.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"VectorOfLengthAndType<[1, 2], [F32, F16, BF16]>\" },\n      { \"name\": \"scale\", \"type\": \"F32\" },\n      { \"name\": \"existing\", \"type\": \"Optional<AnyTypeOf<[ FixedVectorOfLengthAndType < [ 4 ] , [ F8E5M2 , F8E4M3FN ] >, FixedVectorOfLengthAndType < [ 8 ] , [ F4E2M1FN ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[FixedVectorOfLengthAndType<[4], [F8E5M2, F8E4M3FN]>, FixedVectorOfLengthAndType<[8], [F4E2M1FN]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<7>]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `into` ($existing^):(`undef`)? `[` $index `]`\\n    `,` $scale\\n    `:` type($source) `to` type($res) (`into` type($existing)^)?\"\n  },\n  {\n    \"name\": \"amdgpu.packed_stoch_round_fp8\",\n    \"summary\": \"Round float stochiastically into a packed vector of 8-bit floats\",\n    \"description\": \"Round the input `source`, adding in `stochiasticParam`, and place it into\\n    the `storeIndex`th element of `res`.\\n\\n    If `existing` is passed in, elements of `res` other than the one at `storeIndex`\\n    are copied from `existing`.\\n\\n    The reason for this odd signature is that AMD GPUs cannot easily work with\\n    sub-registers, and so the conversion intrinsics (which are currently the\\n    only way to work with 8-bit float types) take packed vectors of 4 8-bit\\n    values.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"F32\" },\n      { \"name\": \"stochiasticParam\", \"type\": \"I32\" },\n      { \"name\": \"existing\", \"type\": \"Optional<FixedVectorOfLengthAndType<[ 4 ], [ F8E4M3FNUZ, F8E5M2FNUZ, F8E4M3FN, F8E5M2 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"FixedVectorOfLengthAndType<[4], [F8E4M3FNUZ, F8E5M2FNUZ, F8E4M3FN, F8E5M2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"storeIndex\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<3>]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `+` $stochiasticParam\\n    `into` ($existing^):(`undef`)? `[` $storeIndex `]`\\n    `:` type($source) `to` type($res) (`into` type($existing)^)?\"\n  },\n  {\n    \"name\": \"amdgpu.packed_trunc_2xfp8\",\n    \"summary\": \"Round two floats into a packed vector of 8-bit floats\",\n    \"description\": \"Round the inputs `sourceA` and `sourceB` (which is undefined if not\\n    specified) into the low or high word (bottom two or top two) elements\\n    of the returned vector, keeping the other two elements of `existing`\\n    unchanged if present (or undefined if it was not passed in).\\n\\n    The reason for this odd signature is that AMD GPUs cannot easily work with\\n    sub-registers, and so the conversion intrinsics (which are currently the\\n    only way to work with 8-bit float types) take packed vectors of 4 8-bit\\n    values.\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"F32\" },\n      { \"name\": \"sourceB\", \"type\": \"Optional<F32>\" },\n      { \"name\": \"existing\", \"type\": \"Optional<FixedVectorOfLengthAndType<[ 4 ], [ F8E4M3FNUZ, F8E5M2FNUZ, F8E4M3FN, F8E5M2 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"FixedVectorOfLengthAndType<[4], [F8E4M3FNUZ, F8E5M2FNUZ, F8E4M3FN, F8E5M2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"wordIndex\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<1>]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $sourceA `,` ($sourceB^):(`undef`)?\\n    `into` ($existing^):(`undef`)? `[` `word` $wordIndex `]`\\n    `:` type($sourceA) `to` type($res) (`into` type($existing)^)?\"\n  },\n  {\n    \"name\": \"amdgpu.permlane_swap\",\n    \"summary\": \"AMDGPU permlane swap op\",\n    \"description\": \"High-level wrapper on `rocdl.permlane{16,32}.swap` variants for permutations\\n    on rows of lanes in a subgroup.\\n\\n    Supports arbitrary int/float/vector types, which will be repacked to i32 and\\n    one or more `rocdl.permlane_swap` ops during lowering.\\n    Supported lane permutations:\\n    - Swap the data between odd and even rows of 16 lanes\\n    - Swap the data between the first 32 lanes and the last 32 lanes\\n\\n    Example:\\n    ```mlir\\n    %0 = amdgpu.permlane_swap %src 16 : f16\\n    %1 = amdgpu.permlane_swap %src 32 { fetch_inactive = true, bound_ctrl = true } : f16\\n    ```\\n\\n    Operands:\\n    * `$src`: Vector register to permute across lanes of the subgroup.\\n    * `$row_length`: The length of a row to permute in number of lanes (valid values are 16 and 32).\\n    * `$fetch_inactive`: Optional. Used to dertermine behavior of a fetch from a disabled lane.\\n      `fetch_inactive = false`: If the source lane is disabled, use `bound_ctrl` to determine the source value.\\n      `fetch_inactive = true`: If the source lane is disabled, fetch the source value anyway (ignoring `bound_ctrl`).\\n    * `$bound_ctrl`: Optional. Used to determine what a thread should do if its source operand is from\\n      a disabled lane: use the value zero, or disable the write.\\n      `bound_ctrl = false`: Do not write when source is from a disabled lane\\n      `bound_ctrl = true`: Use zero as input if source is from a disabled lane\\n\\n    Note: Lowering is only supported on gfx950 and up.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"row_length\", \"type\": \"I32Attr\" },\n      { \"name\": \"fetch_inactive\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"bound_ctrl\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$src $row_length attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_atomic_cmpswap\",\n    \"summary\": \"Raw Buffer Atomic compare-and-swap\",\n    \"description\": \"The `amdgpu.raw_buffer_atomic_cmpswap` op is a wrapper around the\\n    buffer-based atomic compare-and-swap min available on AMD GPUs.\\n\\n    The index into the buffer is computed as for `memref.store` with the addition\\n    of `indexOffset` (which is used to aid in emitting vectorized code) and,\\n    if present `sgprOffset` (which is added after bounds checks and includes\\n    any non-zero offset on the memref type).\\n\\n    All indexing components are given in terms of the memref's element size, not\\n    the byte lengths required by the intrinsic.\\n\\n    Out of bounds atomic operations are ignored in hardware.\\n\\n    See `amdgpu.raw_buffer_load` for a description of how the underlying\\n    instruction is constructed.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyType\" },\n      { \"name\": \"cmp\", \"type\": \"AnyType\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['src', 'cmp', 'value']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $cmp `->` $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($value) `->` type($memref) `,` type($indices)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_atomic_fadd\",\n    \"summary\": \"Raw Buffer Floating-point Atomic Add (MI-* only)\",\n    \"description\": \"The `amdgpu.raw_buffer_atomic_fadd` op is a wrapper around the\\n    buffer-based atomic floating point addition available on the MI-* series\\n    of AMD GPUs.\\n\\n    The index into the buffer is computed as for `memref.store` with the addition\\n    of `indexOffset` (which is used to aid in emitting vectorized code) and,\\n    if present `sgprOffset` (which is added after bounds checks and includes\\n    any non-zero offset on the memref type).\\n\\n    All indexing components are given in terms of the memref's element size, not\\n    the byte lengths required by the intrinsic.\\n\\n    Out of bounds atomic operations are ignored in hardware.\\n\\n    See `amdgpu.raw_buffer_load` for a description of how the underlying\\n    instruction is constructed.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[F32, VectorOfLengthAndType<[2], [F16, BF16]>]>\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `->` $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($value) `->` type($memref) `,` type($indices)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_atomic_fmax\",\n    \"summary\": \"Raw Buffer Floating-point Atomic Max (non-GFX9)\",\n    \"description\": \"The `amdgpu.raw_buffer_atomic_fmax` op is a wrapper around the\\n    buffer-based atomic floating point max available on AMD GPUs (except GFX9).\\n\\n    The index into the buffer is computed as for `memref.store` with the addition\\n    of `indexOffset` (which is used to aid in emitting vectorized code) and,\\n    if present `sgprOffset` (which is added after bounds checks and includes\\n    any non-zero offset on the memref type).\\n\\n    All indexing components are given in terms of the memref's element size, not\\n    the byte lengths required by the intrinsic.\\n\\n    Out of bounds atomic operations are ignored in hardware.\\n\\n    See `amdgpu.raw_buffer_load` for a description of how the underlying\\n    instruction is constructed.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[F32, F64]>\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `->` $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($value) `->` type($memref) `,` type($indices)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_atomic_smax\",\n    \"summary\": \"Raw Buffer Signed Integer Atomic Max\",\n    \"description\": \"The `amdgpu.raw_buffer_atomic_smax` op is a wrapper around the\\n    buffer-based atomic signed integer max available on AMD GPUs.\\n\\n    The index into the buffer is computed as for `memref.store` with the addition\\n    of `indexOffset` (which is used to aid in emitting vectorized code) and,\\n    if present `sgprOffset` (which is added after bounds checks and includes\\n    any non-zero offset on the memref type).\\n\\n    All indexing components are given in terms of the memref's element size, not\\n    the byte lengths required by the intrinsic.\\n\\n    Out of bounds atomic operations are ignored in hardware.\\n\\n    See `amdgpu.raw_buffer_load` for a description of how the underlying\\n    instruction is constructed.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I32\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `->` $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($value) `->` type($memref) `,` type($indices)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_atomic_umin\",\n    \"summary\": \"Raw Buffer Unsigned Integer Atomic Min\",\n    \"description\": \"The `amdgpu.raw_buffer_atomic_umin` op is a wrapper around the\\n    buffer-based atomic signed integer min available on AMD GPUs.\\n\\n    The index into the buffer is computed as for `memref.store` with the addition\\n    of `indexOffset` (which is used to aid in emitting vectorized code) and,\\n    if present `sgprOffset` (which is added after bounds checks and includes\\n    any non-zero offset on the memref type).\\n\\n    All indexing components are given in terms of the memref's element size, not\\n    the byte lengths required by the intrinsic.\\n\\n    Out of bounds atomic operations are ignored in hardware.\\n\\n    See `amdgpu.raw_buffer_load` for a description of how the underlying\\n    instruction is constructed.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I32\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `->` $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($value) `->` type($memref) `,` type($indices)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_load\",\n    \"summary\": \"Raw Buffer load, exposing GCN features\",\n    \"description\": \"The `amdgpu.raw_buffer_load` op is a wrapper around the buffer load intrinsics\\n    available on AMD GPUs, including extensions in newer GPUs.\\n\\n    The index into the buffer is computed as for `memref.load` with the additon\\n    of `indexOffset` and `sgprOffset` (which **may or may not** be considered\\n    in bounds checks and includes any offset present on the memref type if it's\\n    non-zero).\\n\\n    All indices and offsets are in units of the memref's data type and are\\n    converted to bytes during lowering.\\n\\n    When a load is out of bounds, the instruction returns zero.\\n    Partially-out of bounds have chipset-dependent behavior: whether reading\\n    2 elements starting at index 7 of a `memref<8xf32>` returns the last element\\n    in the first vector component depends on the architecture.\\n\\n    The memref struct is converted into a buffer resource (a V#) and the arguments\\n    are translated to intrinsic arguments as follows:\\n    - The base address of the buffer is the base address of the memref\\n    - The stride is 0 to enable raw mode\\n    - The number of records is the size of the memref, in bytes\\n      In the case of dynamically-shaped memrefs, this is computed at runtime\\n      as max_d (size(d) * stride(d)) * sizeof(elementType(memref))\\n    - The offset enable bit is 1, the index enable bit is 0.\\n    - The thread ID addition bit is off\\n    - If `boundsCheck` is false and the target chipset is RDNA, OOB_SELECT is set\\n      to 2 to disable bounds checks, otherwise it is 3\\n    - The cache coherency bits are off\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($memref) (`,` type($indices)^)? `->` type($value)\"\n  },\n  {\n    \"name\": \"amdgpu.raw_buffer_store\",\n    \"summary\": \"Raw Buffer Store, exposing GCN features\",\n    \"description\": \"The `amdgpu.raw_buffer_store` op is a wrapper around the buffer store\\n    intrinsics available on AMD GPUs, including extensions in newer GPUs.\\n\\n    The store index is computed as in `memref.store` with the addition of\\n    `indexOffset` (which is included for uniformity with atomics and may be useful\\n    when writing vectorized code) and `sgprOffset` (which is added after bounds\\n    checks and implicitly includes the offset of the memref type if non-zero).\\n    All index components are in terms of the elements of the memref, not bytes,\\n    and are scaled up appropriately.\\n\\n    Out of bounds stores are ignored in hardware.\\n    Wthether a vector write that includes some in-bounds and soeme out-of-bounds\\n    components is partically completed is chipset-dependent.\\n\\n    See `amdgpu.raw_buffer_load` for a description of how the underlying\\n    instruction is constructed.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"sgprOffset\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundsCheck\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"indexOffset\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `->` $memref `[` $indices `]`\\n      (`sgprOffset` $sgprOffset^)? `:`\\n      type($value) `->` type($memref) (`,` type($indices)^)?\"\n  },\n  {\n    \"name\": \"amdgpu.scaled_ext_packed\",\n    \"summary\": \"Extend a vector of packed floating point values\",\n    \"description\": \"Extend and scale two packed floats in `source[index]` to two floats and\\n    return them.\\n\\n    This rather unusual signature arises from the fact that AMD GPUs cannot\\n    easily work with sub 32-bit quantities, so the compiler intrinsics for\\n    extending 8-bit floats (which are, currently, the only way to work with\\n    this operation) take packed vectors of 2 such floats.\\n\\n    If the passed-in vector has fewer than two elements, or the input is scalar,\\n    the remaining values in the <2 x i8> will be filled with\\n    undefined values as needed.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[VectorOfLengthAndType<[1, 2, 3, 4], [F8E5M2, F8E4M3FN]>, VectorOfLengthAndType<[1, 2, 3, 4, 5, 6, 7, 8], [F4E2M1FN]>]>\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[FixedVectorOfLengthAndType<[2], [F32]>, FixedVectorOfLengthAndType<[2], [F16]>, FixedVectorOfLengthAndType<[2], [BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<7>]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `[` $index `]` `,` $scale `:` type($source) `to` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.scaled_ext_packed_matrix\",\n    \"summary\": \"Extend a wave-wide matrix of packed floating point values\",\n    \"description\": \"Extend matrix of microfloats (8 or 16 elements per lane) using a set of scales\\n    that may be stored on other lanes.\\n\\n    The scales applied to the input microfloats are stored in bytes which\\n    come from the `scales` input provided in a *half* of the wave identified\\n    by `firstScaleLane`. The bytes used is selected by `firstScaleByte` and depends\\n    on the type of `source`. The 16 vectors in consecutive lanes starting from\\n    `firstScaleLane` (which we'll call the scale vectors) will be used by both\\n    halves of the wave (with lane L reading from L % 16'th scale vector).\\n\\n    When `source` is either F4E2M1FN, F6E2M3FN, or F6E3M2FN each half of the\\n    wave will use a different byte. The first one being `firstScaleByte` and\\n    the second one being `firstScaleByte` + 1. When the block size is 32,\\n    `firstScaleByte` can be either 0 or 2, selecting halves of the scale vectors.\\n    Lanes 0-15 will read from `firstScaleByte` and lanes 16-31 will read\\n    from `firstScaleByte` + 1.\\n\\n\\n    For example:\\n    ```mlir\\n    // Input: 8-element vector of F8E4M3FN, converting to F32\\n    // Lanes 0-15 read from byte 0, lanes 16-31 read from byte 1\\n    %result = amdgpu.scaled_ext_packed_matrix %source scale(%scales)\\n      blockSize(32) firstScaleLane(0) firstScaleByte(0)\\n      : vector<8xf8E4M3FN>, vector<4xf8E8M0FNU> -> vector<8xf32>\\n\\n    // Input: 16-element vector of F6E2M3FN, converting to F16\\n    // Lanes 0-15 read from byte 2, lanes 16-31 read from byte 3\\n    %result = amdgpu.scaled_ext_packed_matrix %source scale(%scales)\\n      blockSize(32) firstScaleLane(16) firstScaleByte(2)\\n      : vector<16xf6E2M3FN>, vector<4xf8E8M0FNU> -> vector<16xf16>\\n    ```\\n\\n    When `source` is either F4E2M1FN, F6E2M3FN, or F6E3M2FN and\\n    the block size is 16, `firstScaleByte` can be 0 or 1.\\n    Lanes 0-15 read from the `firstScaleByte`th element of the scale vectors,\\n    while lanes 16-31 read from `firstScaleByte` + 2.\\n    For example:\\n    ```mlir\\n    // Input: 8-element vector of F8E5M2, converting to BF16\\n    // Lanes 0-15 read from byte 0, lanes 16-31 read from byte 2 (0+2)\\n    %result = amdgpu.scaled_ext_packed_matrix %source scale(%scales)\\n      blockSize(16) firstScaleLane(0) firstScaleByte(0)\\n      : vector<8xf8E5M2>, vector<4xf8E8M0FNU> -> vector<8xbf16>\\n\\n    // Input: 16-element vector of F6E3M2FN, converting to F32\\n    // Lanes 0-15 read from byte 1, lanes 16-31 read from byte 3 (1+2)\\n    %result = amdgpu.scaled_ext_packed_matrix %source scale(%scales)\\n      blockSize(16) firstScaleLane(16) firstScaleByte(1)\\n      : vector<16xf6E3M2FN>, vector<4xf8E8M0FNU> -> vector<16xf32>\\n    ```\\n\\n    Note: the layout for the scales generally mirrors how the WMMA\\n    instructions use for matrix scales. These selection operands allows\\n    one to choose portions of the matrix to convert.\\n\\n    When `source` is either F8E4M3FN or F8E5M2 and `blockSize` is 32,\\n    then the same byte will be used by both halves of the wave.\\n    In this case, `firstScaleByte` can be any value from 0 to 3.\\n\\n    When `source` is either F8E4M3FN or F8E5M2 and `blockSize` is 16,\\n    following combinations are allowed:\\n    * `firstScaleLane(0), firstScaleByte(0)`\\n    * `firstScaleLane(16), firstScaleByte(2)`\\n    all other combinations are reserved.\\n\\n    Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[FixedVectorOfShapeAndType<[8], F4E2M1FN>, FixedVectorOfShapeAndType<[8], F8E4M3FN>, FixedVectorOfShapeAndType<[8], F8E5M2>, FixedVectorOfShapeAndType<[16], F6E2M3FN>, FixedVectorOfShapeAndType<[16], F6E3M2FN>]>\" },\n      { \"name\": \"scale\", \"type\": \"FixedVectorOfShapeAndType<[4], F8E8M0FNU>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[FixedVectorOfShapeAndType<[8], F32>, FixedVectorOfShapeAndType<[8], F16>, FixedVectorOfShapeAndType<[8], BF16>, FixedVectorOfShapeAndType<[16], F32>, FixedVectorOfShapeAndType<[16], F16>, FixedVectorOfShapeAndType<[16], BF16>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blockSize\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32]>]>\" },\n      { \"name\": \"firstScaleLane\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[0, 16]>]>\" },\n      { \"name\": \"firstScaleByte\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source\\n    `scale` `(` $scale `)`\\n    `blockSize` `(` $blockSize `)`\\n    `firstScaleLane` `(` $firstScaleLane`)`\\n    `firstScaleByte` `(` $firstScaleByte `)`\\n    `:` type($source) `,` type($scale) `->` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.scaled_ext_packed816\",\n    \"summary\": \"Extend a vector of packed floating point values\",\n    \"description\": \"The scales applied to the input microfloats are stored in bytes which\\n    come from the `scales` input provided in a *half* of the wave identified\\n    by `firstScaleLane`. The bytes used is selected by `firstScaleByte` and depends\\n    on the type of `source`. The 16 vectors in consecutive lanes starting from\\n    `firstScaleLane` (which we'll call the scale vectors) will be used by both\\n    halves of the wave (with lane L reading from L % 16'th scale vector).\\n\\n    When `source` is either F4E2M1FN, F6E2M3FN, or F6E3M2FN each half of the\\n    wave will use a different byte. The first one being `firstScaleByte` and\\n    the second one being `firstScaleByte` + 1. When the block size is 32,\\n    `firstScaleByte` can be either 0 or 2, selecting halves of the scale vectors.\\n    Lanes 0-15 will read from `firstScaleByte` and lanes 16-31 will read\\n    from `firstScaleByte` + 1.\\n\\n\\n    For example:\\n    ```mlir\\n    // Input: 8-element vector of F8E4M3FN, converting to F32\\n    // Lanes 0-15 read from byte 0, lanes 16-31 read from byte 1\\n    %result = amdgpu.scaled_ext_packed816 %source scale(%scales)\\n      blockSize(32) firstScaleLane(0) firstScaleByte(0)\\n      : vector<8xf8E4M3FN>, vector<4xf8E8M0FNU> -> vector<8xf32>\\n\\n    // Input: 16-element vector of F6E2M3FN, converting to F16\\n    // Lanes 0-15 read from byte 2, lanes 16-31 read from byte 3\\n    %result = amdgpu.scaled_ext_packed816 %source scale(%scales)\\n      blockSize(32) firstScaleLane(1) firstScaleByte(2)\\n      : vector<16xf6E2M3FN>, vector<4xf8E8M0FNU> -> vector<16xf16>\\n    ```\\n\\n    When `source` is either F4E2M1FN, F6E2M3FN, or F6E3M2FN and\\n    the block size is 16, `firstScaleByte` can be 0 or 1.\\n    Lanes 0-15 read from the `firstScaleByte`th element of the scale vectors,\\n    while lanes 16-31 read from `firstScaleByte` + 2.\\n    For example:\\n    ```mlir\\n    // Input: 8-element vector of F8E5M2, converting to BF16\\n    // Lanes 0-15 read from byte 0, lanes 16-31 read from byte 2 (0+2)\\n    %result = amdgpu.scaled_ext_packed816 %source scale(%scales)\\n      blockSize(16) firstScaleLane(0) firstScaleByte(0)\\n      : vector<8xf8E5M2>, vector<4xf8E8M0FNU> -> vector<8xbf16>\\n\\n    // Input: 16-element vector of F6E3M2FN, converting to F32\\n    // Lanes 0-15 read from byte 1, lanes 16-31 read from byte 3 (1+2)\\n    %result = amdgpu.scaled_ext_packed816 %source scale(%scales)\\n      blockSize(16) firstScaleLane(1) firstScaleByte(1)\\n      : vector<16xf6E3M2FN>, vector<4xf8E8M0FNU> -> vector<16xf32>\\n    ```\\n\\n    Note: the layout for the scales generally mirrors how the WMMA\\n    instructions use for matix scales. These selection operands allows\\n    one to choose portions of the matrix to convert.\\n\\n    When `source` is either F8E4M3FN or F8E5M2 and `blockSize` is 32,\\n    then the same byte will be used by both halves of the wave.\\n    In this case, `firstScaleByte` can be any value from 0 to 3.\\n\\n    When `source` is either F8E4M3FN or F8E5M2 and `blockSize` is 16,\\n    following combinations are allowed:\\n    * `firstScaleLane(0), firstScaleByte(0)`\\n    * `firstScaleLane(1), firstScaleByte(2)`\\n    all other combinations are reserved.\\n\\n    Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[FixedVectorOfShapeAndType<[8], F4E2M1FN>, FixedVectorOfShapeAndType<[8], F8E4M3FN>, FixedVectorOfShapeAndType<[8], F8E5M2>, FixedVectorOfShapeAndType<[16], F6E2M3FN>, FixedVectorOfShapeAndType<[16], F6E3M2FN>]>\" },\n      { \"name\": \"scale\", \"type\": \"FixedVectorOfShapeAndType<[4], F8E8M0FNU>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[FixedVectorOfShapeAndType<[8], F32>, FixedVectorOfShapeAndType<[8], F16>, FixedVectorOfShapeAndType<[8], BF16>, FixedVectorOfShapeAndType<[16], F32>, FixedVectorOfShapeAndType<[16], F16>, FixedVectorOfShapeAndType<[16], BF16>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blockSize\", \"type\": \"ConfinedAttr<I32Attr, [IsValidBlockSize]>\" },\n      { \"name\": \"firstScaleLane\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<1>]>\" },\n      { \"name\": \"firstScaleByte\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source\\n    `scale` `(` $scale `)`\\n    `blockSize` `(` $blockSize `)`\\n    `firstScaleLane` `(` $firstScaleLane`)`\\n    `firstScaleByte` `(` $firstScaleByte `)`\\n    `:` type($source) `,` type($scale) `->` type($res)\"\n  },\n  {\n    \"name\": \"amdgpu.scaled_mfma\",\n    \"summary\": \"MLIR wrapper for CDNA scaled mfma instructions\",\n    \"description\": \"The `amdgpu.scaled_mfma` op is an MLIR wrapper around intrinsics\\n    for various scaled versions of `mfma` instructions in the CDNA architecture, which\\n    perform multiple outer products in order to allow fast matrix multiplication.\\n\\n    The wrapper will select an appropriate `mfma` instruction, if one is available,\\n    based on the provided `m`, `k`, `n`, and `nBlks` attributes, along with the\\n    types of the source and destination arguments.\\n\\n    Note, this wrapper allows specifying `vector<4Kxi8>` arguments to MFMA\\n    intrinsics that take an integer type of width `4K`. For example,\\n    one can provide a `vector<4xi8>` as an argument to an MFMA instruction that\\n    logically takes 4 i8s but whose intrinsics are specified to take an i32.\\n    In these cases, the bytes in the vector will be concatenated in little-endian\\n    order (that is, v[0] will go to arg[7:0], v[1] to arg[15:8] and so on).\\n\\n    This wrapper takes inspiration from `amdgpu.mfma`, but has some key differences:\\n    - `amdgpu.scaled_mfma` operates on fp4 (f4E2M1FN), fp6 (f6E2M3FN and f6E3M2FN) and\\n      fp8 (f8E4M3FN and f8E5M2) types using either M=N=16, K=128 or M=N=32, K=64 as\\n      their tile size.\\n    - `amdgpu.scaled_mfma` does not support broadcasting. So, `cbsz`, `abid`, and `blgp`\\n      are omitted from this wrapper.\\n    - The `negateA`, `negateB`, and `negateC` flags in `amdgpu.mfma` are only supported\\n      for double-precision operations on gfx94x and so are not included here.\\n\\n    Example:\\n    ```mlir\\n      %0 = amdgpu.scaled_mfma 32x32x64 (%arg0[0] * %arg1) * (%arg0[1] * %arg1) + %arg2\\n        : vector<4xf8E8M0FNU>, vector<32xf6E2M3FN>, f8E8M0FNU, vector<32xf6E2M3FN>, vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"ScaledMFMAInTypes\" },\n      { \"name\": \"sourceB\", \"type\": \"ScaledMFMAInTypes\" },\n      { \"name\": \"destC\", \"type\": \"ScaledMFMAOutTypes\" },\n      { \"name\": \"scalesA\", \"type\": \"AnyTypeOf<[F8E8M0FNU, FixedVectorOfLengthAndType<[4], [F8E8M0FNU]>]>\" },\n      { \"name\": \"scalesB\", \"type\": \"AnyTypeOf<[F8E8M0FNU, FixedVectorOfLengthAndType<[4], [F8E8M0FNU]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"destD\", \"type\": \"ScaledMFMAOutTypes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32]>]>\" },\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32]>]>\" },\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[64, 128]>]>\" },\n      { \"name\": \"scalesIdxA\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<3>]>\" },\n      { \"name\": \"scalesIdxB\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<3>]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['destC', 'destD']>\" }\n    ],\n    \"assemblyFormat\": \"custom<MNKDimensionList>($m, $n, $k) ` `\\n    `(` $scalesA `[` $scalesIdxA `]` `*` $sourceA `)` `*`\\n    `(` $scalesB `[` $scalesIdxB `]` `*` $sourceB `)` `+` $destC\\n    attr-dict\\n    `:` type($scalesA) `,` type($sourceA) `,` type($scalesB) `,` type($sourceB) `,` type($destC)\"\n  },\n  {\n    \"name\": \"amdgpu.scaled_wmma\",\n    \"summary\": \"MLIR wrapper for scaled wmma instructions\",\n    \"description\": \"The `amdgpu.scaled_wmma` op is an MLIR wrapper around intrinsics for scaled\\n    `wmma` instructions. These instructions perform matrix multiplication with\\n    per-block scaling of inputs, supporting fp4, fp6, and fp8 data formats.\\n\\n    The scale instructions support a block size of 16 or 32 and two tile sizes:\\n    - 16x16x128 with mixed f8/f6/f4 formats (output: vector<8xf32>)\\n    - 32x16x128 with f4 format only (output: vector<16xf32>)\\n\\n    Scale parameters (`scaleA`, `scaleB`) are small vectors of f8 scale values\\n    (either f8E8M0FNU, or f8E4M3FN) that are packed into i32/i64 values during\\n    lowering. Each lane can operate on 4 bytes (4 scale values), and the\\n    number of scales required for each matrix is determined by:\\n      num_scales_A = (M × K) / block_size\\n      num_scales_B = (N × K) / block_size\\n\\n    The index attributes (`a_first_scale_lane`, `b_first_scale_lane`) select\\n    which lane to start reading scale values from (0 or 16):\\n    - For block size 32, 32 lanes across a single wave are used for the scale\\n    values. If the number of scales (num_scales_A or num_scales_B) can fit\\n    into half of the available lanes\\n    (i.e., num_scales / scales_per_lane == 16 (num_lanes)),\\n    then then first_scale_lane can be either 0 or 16. If all lanes are required\\n    for storing the scale values (num_scales / scales_per_lane == 32 (num_lanes)),\\n    then the first_scale_lane must be 0.\\n    - For block size 16, the same rules apply as above except that there are 64\\n    lanes across two waves that are used for the scale values. When\\n    num_scales / scales_per_lane == 32 (num lanes), then 16 lanes from each wave are used.\\n    first_scale_lane of 0 or 16 will decide which lanes are used for this. When\\n    num_scales / scales_per_lane == 64 (num_lanes), then first_scale_lane must\\n    be set to 0.\\n\\n    Example:\\n    ```mlir\\n      // 16x16x128: fp8 inputs\\n      %0 = amdgpu.scaled_wmma 16x16x128 (%scaleVecA * %matA) * (%scaleVecB * %matB) + %matC\\n        {a_first_scale_lane = 0 : i32, b_first_scale_lane = 0 : i32}\\n        : vector<4xf8E8M0FNU>, vector<64xf8E4M3FN>,\\n        vector<4xf8E8M0FNU>, vector<64xf8E4M3FN>, vector<8xf32>\\n\\n      // 32x16x128: fp4 inputs with different scale lanes\\n      %1 = amdgpu.scaled_wmma 32x16x128 (%scaleVecD * %matD) * (%scaleVecE * %matE) + %matF\\n        {a_first_scale_lane = 0 : i32, b_first_scale_lane = 16 : i32}\\n        : vector<8xf8E4M3FN>, vector<128xf4E2M1FN>,\\n        vector<8xf8E4M3FN>, vector<64xf4E2M1FN>, vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"ScaledWMMAInTypes\" },\n      { \"name\": \"sourceB\", \"type\": \"ScaledWMMAInTypes\" },\n      { \"name\": \"destC\", \"type\": \"ScaledWMMAOutTypes\" },\n      { \"name\": \"scaleA\", \"type\": \"VectorOfLengthAndType<[4, 8], [F8E8M0FNU, F8E4M3FN]>\" },\n      { \"name\": \"scaleB\", \"type\": \"VectorOfLengthAndType<[4, 8], [F8E8M0FNU, F8E4M3FN]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"destD\", \"type\": \"ScaledWMMAOutTypes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32]>]>\" },\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16]>]>\" },\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[128]>]>\" },\n      { \"name\": \"a_first_scale_lane\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[0, 16]>]>\" },\n      { \"name\": \"b_first_scale_lane\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[0, 16]>]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['destC', 'destD']>\" }\n    ],\n    \"assemblyFormat\": \"custom<MNKDimensionList>($m, $n, $k) ` `\\n    `(` $scaleA `*` $sourceA `)` `*`\\n    `(` $scaleB `*` $sourceB `)` `+` $destC\\n    attr-dict\\n    `:` type($scaleA) `,` type($sourceA) `,` type($scaleB) `,` type($sourceB) `,` type($destC)\"\n  },\n  {\n    \"name\": \"amdgpu.sched_barrier\",\n    \"summary\": \"Barrier that limits the backend scheduler of instruction movement\",\n    \"description\": \"`amdgpu.sched_barrier` serves as a barrier that could be\\n    configured to restrict movements of instructions through it as\\n    defined by sched_barrier_opts.\",\n    \"attributes\": [\n      { \"name\": \"opts\", \"type\": \"AMDGPU_SchedBarrierOpOptAttr{none|non_mem_non_sideffect|valu|salu|mfma_wmma|all_vmem|vmem_read|vmem_write|all_ds|ds_read|ds_write|transcendental}\" }\n    ],\n    \"assemblyFormat\": \"`allow` `=` $opts attr-dict\"\n  },\n  {\n    \"name\": \"amdgpu.sparse_mfma\",\n    \"summary\": \"MLIR wrapper for CDNA sparse mfma (smfmac) instructions\",\n    \"description\": \"The `amdgpu.sparse_mfma` op is an MLIR wrapper around intrinsics for various\\n    `smfmac` instructions in the AMDGPU architecture, which perform matrix\\n    multiply-accumulate operations using 2:4 structured sparsity on matrix A\\n    with dense matrices B, C, and D.\\n\\n    On gfx942, smfmac intrinsics support:\\n      - M=N=16, K=32 and M=N=32, K=16 for f16 and bf16 sources\\n      - M=N=16, K=64 and M=N=32, K=32 for i8 and fp8 sources\\n\\n    On gfx950, smfmac intrinsics additionally support:\\n      - M=N=16, K=64 and M=N=32, K=32 for f16 and bf16 sources\\n      - M=N=16, K=128 and M=N=32, K=64 for i8 and fp8 sources\\n\\n    The `sparseIdx` parameter contains packed indices identifying the positions\\n    of non-zero elements in the 2:4 sparse matrix A. For 16-bit source data,\\n    use `vector<4xi8>` (four 8-bit indices). For 8-bit source data, use\\n    `vector<2xi16>` (two 16-bit indices).\\n\\n    The `cbsz` and `abid` parameters are repurposed to select the index set.\\n    If `cbsz == 0`, then `abid[1:0]` selects which index set to use.\\n    If `cbsz != 0`, then the very first is selected.\\n\\n    Example:\\n    ```mlir\\n      %0 = amdgpu.sparse_mfma 16x16x32 %matA * %matB + %matC sparse(%idx : vector<4xi8>)\\n        : vector<4xf16>, vector<8xf16>, vector<4xf32>\\n\\n      %1 = amdgpu.sparse_mfma 16x16x64 %matA * %matB + %matC sparse(%idx : vector<2xi16>)\\n        : vector<8xi8>, vector<16xi8>, vector<4xi32>\\n\\n      %2 = amdgpu.sparse_mfma 16x16x64 %matA * %matB + %matC sparse(%idx : vector<2xi16>)\\n        { cbsz = 0 : i32, abid = 1 : i32 }\\n        : vector<8xf8E4M3FNUZ>, vector<16xf8E4M3FNUZ>, vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"SMFMACSparseInTypes\" },\n      { \"name\": \"sourceB\", \"type\": \"SMFMACDenseInTypes\" },\n      { \"name\": \"destC\", \"type\": \"SMFMACOutTypes\" },\n      { \"name\": \"sparseIdx\", \"type\": \"SMFMACIdxTypes\" }\n    ],\n    \"results\": [\n      { \"name\": \"destD\", \"type\": \"SMFMACOutTypes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32]>]>\" },\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32]>]>\" },\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16, 32, 64, 128]>]>\" },\n      { \"name\": \"cbsz\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"abid\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['destC', 'destD']>\" }\n    ],\n    \"assemblyFormat\": \"custom<MNKDimensionList>($m, $n, $k) $sourceA `*` $sourceB `+` $destC\\n    `sparse` `(` $sparseIdx `:` type($sparseIdx) `)`\\n    attr-dict\\n    `:` type($sourceA) `,` type($sourceB) `,` type($destC)\"\n  },\n  {\n    \"name\": \"amdgpu.sparse_wmma\",\n    \"summary\": \"MLIR wrapper for CDNA sparse mfma (smfmac) instructions\",\n    \"description\": \"The `amdgpu.sparse_wmma` op is an MLIR wrapper around intrinsics for various\\n    `swmmac` instructions in the AMDGPU architecture, which perform matrix\\n    multiply-accumulate operations using 2:4 structured sparsity on matrix A\\n    with dense matrices B, C, and D.\\n\\n    On gfx12, swmmac intrinsics support:\\n      - M=N=16, K=32 and M=N=32, K=16 for f16, bf16, i8 and i4 sources\\n      - M=N=16, K=64 for i4 sources\\n\\n    On gfx1250, swmmac intrinsics additionally support:\\n      - M=N=16, K=64 for f16 and bf16 sources\\n      - M=N=16, K=128 for f16, bf16 and i8 sources\\n\\n    The `sparseIdx` parameter contains packed indices identifying the positions\\n    of non-zero elements in the 2:4 sparse matrix A. For 16-bit source data,\\n    use `vector<4xi8>` (four 8-bit indices). For 8-bit source data, use\\n    `vector<2xi16>` (two 16-bit indices).\\n\\n    `unsignedA` and `unsignedB` flag that the `int8` LLVM inputs are unsigned.\\n\\n    The `clamp` flag is used to saturate the output of type T to `numeric_limits<T>::max()`\\n    in case of overflow.\\n\\n    Example:\\n    ```mlir\\n      %0 = amdgpu.sparse_wmma 16x16x32 %matA * %matB + %matC sparse(%idx : vector<4xi8>)\\n        : vector<4xf16>, vector<8xf16>, vector<4xf32>\\n\\n      %1 = amdgpu.sparse_wmma 16x16x64 %matA * %matB + %matC sparse(%idx : vector<2xi16>)\\n        : vector<8xi8>, vector<16xi8>, vector<4xi32>\\n\\n      %2 = amdgpu.sparse_wmma 16x16x64 %matA * %matB + %matC sparse(%idx : vector<2xi16>)\\n        { unsignedA = 0 : i1, unsignedB = 1 : i1, clamp = 0 : i1 }\\n        : vector<8xf8E4M3FNUZ>, vector<16xf8E4M3FNUZ>, vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"SWMMACSparseInTypes\" },\n      { \"name\": \"sourceB\", \"type\": \"SWMMACDenseInTypes\" },\n      { \"name\": \"destC\", \"type\": \"SWMMACOutTypes\" },\n      { \"name\": \"sparseIdx\", \"type\": \"SWMMACIdxTypes\" }\n    ],\n    \"results\": [\n      { \"name\": \"destD\", \"type\": \"SWMMACOutTypes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16]>]>\" },\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16]>]>\" },\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[32, 64, 128]>]>\" },\n      { \"name\": \"unsignedA\", \"type\": \"UnitAttr\" },\n      { \"name\": \"unsignedB\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reuseA\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reuseB\", \"type\": \"UnitAttr\" },\n      { \"name\": \"clamp\", \"type\": \"UnitAttr\" },\n      { \"name\": \"wave64\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['destC', 'destD']>\" }\n    ],\n    \"assemblyFormat\": \"custom<MNKDimensionList>($m, $n, $k) $sourceA `*` $sourceB `+` $destC\\n    `sparse` `(` $sparseIdx `:` type($sparseIdx) `)`\\n    attr-dict\\n    `:` type($sourceA) `,` type($sourceB) `,` type($destC)\"\n  },\n  {\n    \"name\": \"amdgpu.swizzle_bitmode\",\n    \"summary\": \"AMDGPU ds_swizzle op, bitmode variant\",\n    \"description\": \"High-level wrapper on bitmode `rocdl.ds_swizzle` op, masks are represented\\n    as separate fields so user won't need to do manual bitpacking.\\n\\n    Supports arbitrary int/float/vector types, which will be repacked to i32 and\\n    one or more `rocdl.ds_swizzle` ops during lowering.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"and_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"or_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"xor_mask\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$src $and_mask $or_mask $xor_mask attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"amdgpu.tensor_load_to_lds\",\n    \"summary\": \"Load tensors from global memory to LDS.\",\n    \"description\": \"Load tensors of up to five dimensions from global memory to LDS.\\n\\n    This operation was introduced in gfx1250.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"AMDGPU_TDMDescriptorType\" }\n    ],\n    \"assemblyFormat\": \"$desc attr-dict `:` qualified(type($desc))\"\n  },\n  {\n    \"name\": \"amdgpu.tensor_store_from_lds\",\n    \"summary\": \"Store tensors from LDS to global memory.\",\n    \"description\": \"Store tensors of up to five dimensions from LDS to global memory.\\n\\n    This operation was introduced in gfx1250.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"AMDGPU_TDMDescriptorType\" }\n    ],\n    \"assemblyFormat\": \"$desc attr-dict `:` qualified(type($desc))\"\n  },\n  {\n    \"name\": \"amdgpu.transpose_load\",\n    \"summary\": \"MLIR wrapper for CDNA Transpose Load instructions\",\n    \"description\": \"The `amdgpu.transpose_load` op is a wrapper around the `ds_read_tr` instructions.\\n    The transpose load op represents a subgroup load from LDS memory,\\n    where the subgroup of threads collectively reads a matrix from the source\\n    memref, with each thread reading a vector of the matrix, and gets a transposed matrix\\n    in as the result. That is, each thread reads a vector of the col-major matrix at different\\n    indices, and the thread's read result is a vector of the corresponding row of the transposed\\n    matrix.\\n\\n    This op is a direct wrapper around the ROCDL `ds_read_tr` family intrinsics. Please refer\\n    to the CDNA4 ISA documentation for more details about its exact semantics.\\n\\n    Format example:\\n    ```\\n    %0 = amdgpu.transpose_load %src[%srcIndices] : memref<128x256xf16> -> vector<4xf16>\\n    ```\\n    Operands:\\n    * `$src`: LDS memref to read from.\\n    * `$srcIndices`: indices into `$src` to read from for this thread.\\n    * `$result`: target register this transpose load instruction will write to.\\n\\n    Note: Lowering is only supported on gfx950 and up.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"srcIndices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $srcIndices `]` attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"amdgpu.wmma\",\n    \"summary\": \"MLIR wrapper for wmma instructions\",\n    \"description\": \"The `amdgpu.wmma` op is an MLIR wrapper around intrinsics for various `wmma`\\n    instructions in the AMDGPU architecture, which perform matrix multiplication.\\n\\n    On gfx11/RDNA3, wmma intrinsics have M=N=K=16 dimensions.\\n\\n    On gfx12/RDNA4, wmma intrinsics have M=N=16 dimensions and support K=16 for\\n    all element types, and K=32 for i4 sources.\\n\\n    On gfx1250, wmma intrinsics have M=N=16 and K dimensions of 4, 32, 64, or 128,\\n    depending on the element types.\\n\\n    On gfx11/RDNA3, emitting f16->f16 (or bf16->bf16) wmma the output is a 16xf16\\n    (or 16xbf16) vector containing only 8 valid values:\\n      - If `subwordOffset` is 0, then the output is stored at indices 0, 2, 4, ..., 14.\\n      - If `subwordOffset` is 1, then the output is stored at indices 1, 3, 5, ..., 15.\\n    On gfx12/RDNA4 and gfx1250, the result is instead returned as vector where all\\n    the values are valid and the `subwordOffset` must be `0`, as it cannot be used.\\n\\n    `unsignedA` and `unsignedB` flag that the `int8` LLVM inputs are unsigned.\\n\\n    The `clamp` flag is used to saturate the output of type T to `numeric_limits<T>::max()`\\n    in case of overflow.\\n\\n    The `wave64`attribute indicates whether an op is designed for 64 threads wavefont.\\n\\n    Example:\\n    ```mlir\\n      %0 = amdgpu.wmma 16x16x16 %matA * %matB + %matC : vector<8xf16>, vector<8xf16>, vector<8xf16>\\n\\n      %1 = amdgpu.wmma 16x16x64 %matD * %matE + %matF : vector<32xi8>, vector<8xf32>, vector<8xf32>\\n\\n      %2 = amdgpu.wmma 16x16x128 %matG * %matH + %matI : vector<64xf4E2M1FN>, vector<64xf4E2M1FN>, vector<8xf32>\\n\\n      %3 = amdgpu.wmma 16x16x4 %matJ * %matK + %matL : vector<2xf32>, vector<2xf32>, vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sourceA\", \"type\": \"WMMAInTypes\" },\n      { \"name\": \"sourceB\", \"type\": \"WMMAInTypes\" },\n      { \"name\": \"destC\", \"type\": \"WMMAOutTypes\" }\n    ],\n    \"results\": [\n      { \"name\": \"destD\", \"type\": \"WMMAOutTypes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16]>]>\" },\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[16]>]>\" },\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I32Attr, [IntIsOneOf<[4, 16, 32, 64, 128]>]>\" },\n      { \"name\": \"subwordOffset\", \"type\": \"DefaultValuedAttr<ConfinedAttr<I32Attr, [ IntIsOneOf < [ 0 , 1 ] > ]>, 0>\" },\n      { \"name\": \"unsignedA\", \"type\": \"UnitAttr\" },\n      { \"name\": \"unsignedB\", \"type\": \"UnitAttr\" },\n      { \"name\": \"clamp\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['destC', 'destD']>\" }\n    ],\n    \"assemblyFormat\": \"custom<MNKDimensionList>($m, $n, $k) $sourceA `*` $sourceB `+` $destC\\n    attr-dict\\n    `:` type($sourceA) `,` type($sourceB) `,` type($destC)\"\n  },\n  {\n    \"name\": \"amx.tile_load\",\n    \"summary\": \"tile load operation\",\n    \"description\": \"Loads a tile from memory defined by a `base` and `indices`, with the\\n    shape defined by the 2-dim vector type of the result.\\n    The tile's rows are populated by reading contiguous elements starting\\n    at the `base`. For each tile row, the `base` is incremented by `stride`\\n    number of elements.\\n\\n    The tile is loaded using the following indexing scheme:\\n\\n    ```\\n    for row in enumerate(tile_rows):\\n      mem_row = base[i0, i1, ..., iN + row * stride]\\n      for col in enumerate(tile_cols):\\n        tile[row, col] = mem_row[col]\\n    ```\\n\\n    If the `stride` is not provided, then the `base` buffer must be at least\\n    2-dimensional, and the `stride` is automatically inferred and corresponds\\n    to the stride of the buffer's second innermost dimension.\\n\\n    The operation is eventually lowered into the \\\"tileloadd\\\" instruction\\n    with the corresponding tile configuration.\\n\\n    With the write memory effect, each `amx.tile_load` operation serves as\\n    a compilation hint to use a separate tile register.\\n\\n    Example:\\n\\n    ```mlir\\n      // Tile load from a 2-D memref with implicit stride.\\n      %0 = amx.tile_load %arg0[%c0, %c0] : memref<?x?xi8> into !amx.tile<16x64xi8>\\n\\n      // Tile load from a 1-D memref with explicit stride.\\n      %0 = amx.tile_load %arg0[%c0], %stride : memref<?xi8> into !amx.tile<16x64xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"stride\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyAMXTile\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` (`,` $stride^ )? attr-dict`:` type($base) `into` qualified(type($res))\"\n  },\n  {\n    \"name\": \"amx.tile_mulf\",\n    \"summary\": \"tile multiplication operation (floating-point)\",\n    \"description\": \"Multiplies a \\\"m x k\\\" tile with a \\\"k x n\\\" tile and accumulates the results\\n    into a \\\"m x n\\\" destination tile. Supports \\\"f32 <- bf16 x bf16\\\" (with\\n    pairs of \\\"bf16\\\").\\n    \\n    The operation is eventually lowered into the \\\"tdpbf16ps\\\" instruction with\\n    the corresponding tile configuration.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = amx.tile_mulf %a, %b, %c\\n        : !amx.tile<16x32xbf16>, !amx.tile<16x32xbf16>, !amx.tile<16x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AMXTileF16OrBF16\" },\n      { \"name\": \"rhs\", \"type\": \"AMXTileF16OrBF16\" },\n      { \"name\": \"acc\", \"type\": \"AMXTileF32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AMXTileF32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `,` $acc attr-dict `:` qualified(type($lhs)) `,` qualified(type($rhs)) `,` qualified(type($acc))\"\n  },\n  {\n    \"name\": \"amx.tile_muli\",\n    \"summary\": \"tile multiplication operation (integer)\",\n    \"description\": \"Multiplies a \\\"m x k\\\" tile with a \\\"k x n\\\" tile and accumulates the results\\n    into a \\\"m x n\\\" destination tile. Supports all \\\"si32 <- s/ui8 x s/ui8\\\"\\n    combinations (4 bytes packed into dwords in the columns of both the\\n    source operand tiles; the zero or sign extension is specified with\\n    the attributes and default to sign extended).\\n    \\n    The operation is eventually lowered into one of the \\\"tdpbssd\\\",\\n    \\\"tdpbsud\\\", \\\"tdpbusd\\\", or \\\"tdpbuud\\\" instructions with the corresponding\\n    tile configuration.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = amx.tile_muli %a zext, %b zext, %c\\n        : !amx.tile<16x64xi8>, !amx.tile<16x64xi8>, !amx.tile<16x16xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AMXTileI8\" },\n      { \"name\": \"rhs\", \"type\": \"AMXTileI8\" },\n      { \"name\": \"acc\", \"type\": \"AMXTileI32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AMXTileI32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isZextLhs\", \"type\": \"UnitAttr\" },\n      { \"name\": \"isZextRhs\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs (`zext` $isZextLhs^)? `,` $rhs (`zext` $isZextRhs^)? `,` $acc attr-dict `:` qualified(type($lhs)) `,` qualified(type($rhs)) `,` qualified(type($acc))\"\n  },\n  {\n    \"name\": \"amx.tile_store\",\n    \"summary\": \"tile store operation\",\n    \"description\": \"Stores a tile to memory defined by a `base` and `indices`, with the\\n    shape defined by the 2-dim vector type of the value.\\n    The tile's rows are written contiguously to the buffer starting at\\n    the `base`. For each tile row, the `base` is incremented by `stride`\\n    number of elements.\\n\\n    The tile is stored using the following indexing scheme:\\n\\n    ```\\n    for row in enumerate(tile_rows):\\n      mem_row = base[i0, i1, ..., iN + row * stride]\\n      for col in enumerate(tile_cols):\\n        mem_row[col] = tile[row, col]\\n    ```\\n\\n    If the `stride` is not provided, then the `base` buffer must be at least\\n    2-dimensional, and the `stride` is automatically inferred and corresponds\\n    to the stride of the buffer's second innermost dimension.\\n\\n    The operation is eventually lowered into the \\\"tilestored\\\" instruction\\n    with the corresponding tile configuration.\\n\\n    Example:\\n\\n    ```mlir\\n      // Tile store to a 2-D memref with implicit stride.\\n      amx.tile_store %arg1[%c0, %c0], %0 : memref<?x?xi8>, !amx.tile<16x64xi8>\\n\\n      // Tile store to a 1-D memref with explicit stride.\\n      amx.tile_store %arg1[%c0], %0, %stride : memref<?xi8>, !amx.tile<16x64xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"val\", \"type\": \"AnyAMXTile\" },\n      { \"name\": \"stride\", \"type\": \"Optional<Index>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $val (`,` $stride^ )?attr-dict `:` type($base) `,` qualified(type($val))\"\n  },\n  {\n    \"name\": \"amx.tile_zero\",\n    \"summary\": \"tile zero operation\",\n    \"description\": \"Zeroes the destination tile, with the shape defined by the 2-dim\\n    vector type of the result.\\n    \\n    The operation is eventually lowered into the \\\"tilezero\\\" instruction\\n    with the corresponding tile configuration.\\n    \\n    With the write memory effect, each `amx.tile_zero` operation serves as\\n    a compilation hint to use a separate tile register.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = amx.tile_zero : !amx.tile<16x16xbf16>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyAMXTile\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` qualified(type($res))\"\n  },\n  {\n    \"name\": \"arith.addf\",\n    \"summary\": \"floating point addition operation\",\n    \"description\": \"The `addf` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be a floating point\\n    scalar type, a vector whose element type is a floating point type, or a\\n    floating point tensor.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar addition.\\n    %a = arith.addf %b, %c : f64\\n\\n    // SIMD vector addition, e.g. for Intel SSE.\\n    %f = arith.addf %g, %h : vector<4xf32>\\n\\n    // Tensor addition.\\n    %x = arith.addf %y, %z : tensor<4x?xbf16>\\n    ```\\n\\n    TODO: In the distant future, this will accept optional attributes for fast\\n    math, contraction, rounding mode, and other controls.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.addi\",\n    \"summary\": \"integer addition operation\",\n    \"description\": \"Performs N-bit addition on the operands. The operands are interpreted as\\n    unsigned bitvectors. The result is represented by a bitvector containing the\\n    mathematical value of the addition modulo 2^n, where `n` is the bitwidth.\\n    Because `arith` integers use a two's complement representation, this operation\\n    is applicable on both signed and unsigned integer operands.\\n\\n    The `addi` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be an integer scalar type,\\n    a vector whose element type is integer, or a tensor of integers.\\n\\n    This op supports `nuw`/`nsw` overflow flags which stands for\\n    \\\"No Unsigned Wrap\\\" and \\\"No Signed Wrap\\\", respectively. If the `nuw` and/or\\n    `nsw` flags are present, and an unsigned/signed overflow occurs\\n    (respectively), the result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar addition.\\n    %a = arith.addi %b, %c : i64\\n\\n    // Scalar addition with overflow flags.\\n    %a = arith.addi %b, %c overflow<nsw, nuw> : i64\\n\\n    // SIMD vector element-wise addition.\\n    %f = arith.addi %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise addition.\\n    %x = arith.addi %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"DefaultValuedAttr<Arith_IntegerOverflowAttr{none|nsw|nuw}, ::mlir::arith::IntegerOverflowFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`overflow` `` $overflowFlags^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.addui_extended\",\n    \"summary\": \"extended unsigned integer addition operation returning sum and overflow bit\",\n    \"description\": \"Performs (N+1)-bit addition on zero-extended operands. Returns two results:\\n    the N-bit sum (same type as both operands), and the overflow bit\\n    (boolean-like), where `1` indicates unsigned addition overflow, while `0`\\n    indicates no overflow.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar addition.\\n    %sum, %overflow = arith.addui_extended %b, %c : i64, i1\\n\\n    // Vector element-wise addition.\\n    %d:2 = arith.addui_extended %e, %f : vector<4xi32>, vector<4xi1>\\n\\n    // Tensor element-wise addition.\\n    %x:2 = arith.addui_extended %y, %z : tensor<4x?xi8>, tensor<4x?xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"sum\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"overflow\", \"type\": \"BoolLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'sum']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($sum) `,` type($overflow)\"\n  },\n  {\n    \"name\": \"arith.andi\",\n    \"summary\": \"integer binary and\",\n    \"description\": \"The `andi` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be an integer scalar\\n    type, a vector whose element type is integer, or a tensor of integers. It\\n    has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar integer bitwise and.\\n    %a = arith.andi %b, %c : i64\\n\\n    // SIMD vector element-wise bitwise integer and.\\n    %f = arith.andi %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise bitwise integer and.\\n    %x = arith.andi %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.bitcast\",\n    \"summary\": \"bitcast between values of equal bit width\",\n    \"description\": \"Bitcast an integer or floating point value to an integer or floating point\\n    value of equal bit width. When operating on vectors, casts elementwise.\\n\\n    Note that this implements a logical bitcast independent of target\\n    endianness. This allows constant folding without target information and is\\n    consitent with the bitcast constant folders in LLVM (see\\n    https://github.com/llvm/llvm-project/blob/18c19414eb/llvm/lib/IR/ConstantFold.cpp#L168)\\n    For targets where the source and target type have the same endianness (which\\n    is the standard), this cast will also change no bits at runtime, but it may\\n    still require an operation, for example if the machine has different\\n    floating point and integer register files. For targets that have a different\\n    endianness for the source and target types (e.g. float is big-endian and\\n    integer is little-endian) a proper lowering would add operations to swap the\\n    order of words in addition to the bitcast.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"BitcastTypeConstraint\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"BitcastTypeConstraint\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.ceildivsi\",\n    \"summary\": \"signed ceil integer division operation\",\n    \"description\": \"Signed integer division. Rounds towards positive infinity, i.e. `7 / -2 = -3`.\\n\\n    Divison by zero, or signed division overflow (minimum value divided by -1)\\n    is undefined behavior. When applied to `vector` and `tensor` values, the\\n    behavior is undefined if _any_ of its elements are divided by zero or has a\\n    signed division overflow.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar signed integer division.\\n    %a = arith.ceildivsi %b, %c : i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.ceildivui\",\n    \"summary\": \"unsigned ceil integer division operation\",\n    \"description\": \"Unsigned integer division. Rounds towards positive infinity. Treats the\\n    leading bit as the most significant, i.e. for `i16` given two's complement\\n    representation, `6 / -2 = 6 / (2^16 - 2) = 1`.\\n\\n    Division by zero is undefined behavior. When applied to `vector` and\\n    `tensor` values, the behavior is undefined if _any_ elements are divided by\\n    zero.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar unsigned integer division.\\n    %a = arith.ceildivui %b, %c : i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.cmpf\",\n    \"summary\": \"floating-point comparison operation\",\n    \"description\": \"The `cmpf` operation compares its two operands according to the float\\n    comparison rules and the predicate specified by the respective attribute.\\n    The predicate defines the type of comparison: (un)orderedness, (in)equality\\n    and signed less/greater than (or equal to) as well as predicates that are\\n    always true or false.  The operands must have the same type, and this type\\n    must be a float type, or a vector or tensor thereof.  The result is an i1,\\n    or a vector/tensor thereof having the same shape as the inputs. Unlike cmpi,\\n    the operands are always treated as signed. The u prefix indicates\\n    *unordered* comparison, not unsigned comparison, so \\\"une\\\" means unordered or\\n    not equal. For the sake of readability by humans, custom assembly form for\\n    the operation uses a string-typed attribute for the predicate.  The value of\\n    this attribute corresponds to lower-cased name of the predicate constant,\\n    e.g., \\\"one\\\" means \\\"ordered not equal\\\".  The string representation of the\\n    attribute is merely a syntactic sugar and is converted to an integer\\n    attribute by the parser.\\n\\n    Example:\\n\\n    ```mlir\\n    %r1 = arith.cmpf oeq, %0, %1 : f32\\n    %r2 = arith.cmpf ult, %0, %1 : tensor<42x42xf64>\\n    %r3 = \\\"arith.cmpf\\\"(%0, %1) {predicate: 0} : (f8, f8) -> i1\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"Arith_CmpFPredicateAttr{false|oeq|ogt|oge|olt|ole|one|ord|ueq|ugt|uge|ult|ule|une|uno|true}\" },\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'lhs', 'result', '::getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$predicate `,` $lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"arith.cmpi\",\n    \"summary\": \"integer comparison operation\",\n    \"description\": \"The `cmpi` operation is a generic comparison for integer-like types. Its two\\n    arguments can be integers, vectors or tensors thereof as long as their types\\n    match. The operation produces an i1 for the former case, a vector or a\\n    tensor of i1 with the same shape as inputs in the other cases.\\n\\n    Its first argument is an attribute that defines which type of comparison is\\n    performed. The following comparisons are supported:\\n\\n    -   equal (mnemonic: `\\\"eq\\\"`; integer value: `0`)\\n    -   not equal (mnemonic: `\\\"ne\\\"`; integer value: `1`)\\n    -   signed less than (mnemonic: `\\\"slt\\\"`; integer value: `2`)\\n    -   signed less than or equal (mnemonic: `\\\"sle\\\"`; integer value: `3`)\\n    -   signed greater than (mnemonic: `\\\"sgt\\\"`; integer value: `4`)\\n    -   signed greater than or equal (mnemonic: `\\\"sge\\\"`; integer value: `5`)\\n    -   unsigned less than (mnemonic: `\\\"ult\\\"`; integer value: `6`)\\n    -   unsigned less than or equal (mnemonic: `\\\"ule\\\"`; integer value: `7`)\\n    -   unsigned greater than (mnemonic: `\\\"ugt\\\"`; integer value: `8`)\\n    -   unsigned greater than or equal (mnemonic: `\\\"uge\\\"`; integer value: `9`)\\n\\n    The result is `1` if the comparison is true and `0` otherwise. For vector or\\n    tensor operands, the comparison is performed elementwise and the element of\\n    the result indicates whether the comparison is true for the operand elements\\n    with the same indices as those of the result.\\n\\n    Note: while the custom assembly form uses strings, the actual underlying\\n    attribute has integer type (or rather enum class in C++ code) as seen from\\n    the generic assembly form. String literals are used to improve readability\\n    of the IR by humans.\\n\\n    This operation only applies to integer-like operands, but not floats. The\\n    main reason being that comparison operations have diverging sets of\\n    attributes: integers require sign specification while floats require various\\n    floating point-related particularities, e.g., `-ffast-math` behavior,\\n    IEEE754 compliance, etc\\n    ([rationale](../Rationale/Rationale.md#splitting-floating-point-vs-integer-operations)).\\n    The type of comparison is specified as attribute to avoid introducing ten\\n    similar operations, taking into account that they are often implemented\\n    using the same operation downstream\\n    ([rationale](../Rationale/Rationale.md#specifying-comparison-kind-as-attribute)). The\\n    separation between signed and unsigned order comparisons is necessary\\n    because of integers being signless. The comparison operation must know how\\n    to interpret values with the foremost bit being set: negatives in two's\\n    complement or large positives\\n    ([rationale](../Rationale/Rationale.md#specifying-sign-in-integer-comparison-operations)).\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of scalar \\\"signed less than\\\" comparison.\\n    %x = arith.cmpi slt, %lhs, %rhs : i32\\n\\n    // Generic form of the same operation.\\n    %x = \\\"arith.cmpi\\\"(%lhs, %rhs) {predicate = 2 : i64} : (i32, i32) -> i1\\n\\n    // Custom form of vector equality comparison.\\n    %x = arith.cmpi eq, %lhs, %rhs : vector<4xi64>\\n\\n    // Generic form of the same operation.\\n    %x = \\\"arith.cmpi\\\"(%lhs, %rhs) {predicate = 0 : i64}\\n        : (vector<4xi64>, vector<4xi64>) -> vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"Arith_CmpIPredicateAttr{eq|ne|slt|sle|sgt|sge|ult|ule|ugt|uge}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'lhs', 'result', '::getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$predicate `,` $lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"arith.constant\",\n    \"summary\": \"integer or floating point constant\",\n    \"description\": \"The `constant` operation produces an SSA value equal to some integer or\\n    floating-point constant specified by an attribute. This is the way MLIR\\n    forms simple integer and floating point constants.\\n\\n    Example:\\n\\n    ```\\n    // Integer constant\\n    %1 = arith.constant 42 : i32\\n\\n    // Equivalent generic form\\n    %1 = \\\"arith.constant\\\"() {value = 42 : i32} : () -> i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"arith.divf\",\n    \"summary\": \"floating point division operation\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.divsi\",\n    \"summary\": \"signed integer division operation\",\n    \"description\": \"Signed integer division. Rounds towards zero. Treats the leading bit as\\n    sign, i.e. `6 / -2 = -3`.\\n\\n    Divison by zero, or signed division overflow (minimum value divided by -1)\\n    is undefined behavior. When applied to `vector` and `tensor` values, the\\n    behavior is undefined if _any_ of its elements are divided by zero or has a\\n    signed division overflow.\\n\\n    If the `exact` attribute is present, the result value is poison if `lhs` is\\n    not a multiple of `rhs`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar signed integer division.\\n    %a = arith.divsi %b, %c : i64\\n\\n    // Scalar signed integer division where %b is known to be a multiple of %c.\\n    %a = arith.divsi %b, %c exact : i64\\n\\n    // SIMD vector element-wise division.\\n    %f = arith.divsi %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise integer division.\\n    %x = arith.divsi %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`exact` $isExact^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.divui\",\n    \"summary\": \"unsigned integer division operation\",\n    \"description\": \"Unsigned integer division. Rounds towards zero. Treats the leading bit as\\n    the most significant, i.e. for `i16` given two's complement representation,\\n    `6 / -2 = 6 / (2^16 - 2) = 0`.\\n\\n    Division by zero is undefined behavior. When applied to `vector` and\\n    `tensor` values, the behavior is undefined if _any_ elements are divided by\\n    zero.\\n\\n    If the `exact` attribute is present, the result value is poison if `lhs` is\\n    not a multiple of `rhs`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar unsigned integer division.\\n    %a = arith.divui %b, %c : i64\\n\\n    // Scalar unsigned integer division where %b is known to be a multiple of %c.\\n    %a = arith.divui %b, %c exact : i64\\n\\n    // SIMD vector element-wise division.\\n    %f = arith.divui %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise integer division.\\n    %x = arith.divui %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`exact` $isExact^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.extf\",\n    \"summary\": \"cast from floating-point to wider floating-point\",\n    \"description\": \"Cast a floating-point value to a larger floating-point-typed value.\\n    The destination type must to be strictly wider than the source type.\\n    When operating on vectors, casts elementwise.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"OptionalAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}>\" }\n    ],\n    \"assemblyFormat\": \"$in (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.extsi\",\n    \"summary\": \"integer sign extension operation\",\n    \"description\": \"The integer sign extension operation takes an integer input of\\n    width M and an integer destination type of width N. The destination\\n    bit-width must be larger than the input bit-width (N > M).\\n    The top-most (N - M) bits of the output are filled with copies\\n    of the most-significant bit of the input.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = arith.constant 5 : i3      // %1 is 0b101\\n    %2 = arith.extsi %1 : i3 to i6  // %2 is 0b111101\\n    %3 = arith.constant 2 : i3      // %3 is 0b010\\n    %4 = arith.extsi %3 : i3 to i6  // %4 is 0b000010\\n\\n    %5 = arith.extsi %0 : vector<2 x i32> to vector<2 x i64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.extui\",\n    \"summary\": \"integer zero extension operation\",\n    \"description\": \"The integer zero extension operation takes an integer input of\\n    width M and an integer destination type of width N. The destination\\n    bit-width must be larger than the input bit-width (N > M).\\n    The top-most (N - M) bits of the output are filled with zeros.\\n\\n    When the `nneg` flag is present, the operand is assumed to have\\n    the most significant bit set to 0. In this case, zero extension is\\n    equivalent to sign extension. When this assumption is violated, the\\n    result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n      %1 = arith.constant 5 : i3      // %1 is 0b101\\n      %2 = arith.extui %1 : i3 to i6  // %2 is 0b000101\\n      %3 = arith.constant 2 : i3      // %3 is 0b010\\n      %4 = arith.extui %3 : i3 to i6  // %4 is 0b000010\\n\\n      %5 = arith.extui %0 : vector<2 x i32> to vector<2 x i64>\\n\\n      // Zero extension with nneg flag.\\n      %6 = arith.extui %3 nneg : i3 to i6\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nonNeg\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$in (`nneg` $nonNeg^)? attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.floordivsi\",\n    \"summary\": \"signed floor integer division operation\",\n    \"description\": \"Signed integer division. Rounds towards negative infinity, i.e. `5 / -2 = -3`.\\n\\n    Divison by zero, or signed division overflow (minimum value divided by -1)\\n    is undefined behavior. When applied to `vector` and `tensor` values, the\\n    behavior is undefined if _any_ of its elements are divided by zero or has a\\n    signed division overflow.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar signed integer division.\\n    %a = arith.floordivsi %b, %c : i64\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.fptosi\",\n    \"summary\": \"cast from floating-point type to integer type\",\n    \"description\": \"Cast from a value interpreted as floating-point to the nearest (rounding\\n    towards zero) signed integer value. When operating on vectors, casts\\n    elementwise.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.fptoui\",\n    \"summary\": \"cast from floating-point type to integer type\",\n    \"description\": \"Cast from a value interpreted as floating-point to the nearest (rounding\\n    towards zero) unsigned integer value. When operating on vectors, casts\\n    elementwise.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.index_cast\",\n    \"summary\": \"cast between index and integer types\",\n    \"description\": \"Casts between scalar or vector integers and corresponding 'index' scalar or\\n    vectors. Index is an integer of platform-specific bit width. If casting to\\n    a wider integer, the value is sign-extended. If casting to a narrower\\n    integer, the value is truncated.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"IndexCastTypeConstraint\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"IndexCastTypeConstraint\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.index_castui\",\n    \"summary\": \"unsigned cast between index and integer types\",\n    \"description\": \"Casts between scalar or vector integers and corresponding 'index' scalar or\\n    vectors. Index is an integer of platform-specific bit width. If casting to\\n    a wider integer, the value is zero-extended. If casting to a narrower\\n    integer, the value is truncated.\\n\\n    When the `nneg` flag is present, the operand is assumed to have\\n    the most significant bit set to 0. In this case, zero extension\\n    is equivalent to sign extension. When this assumption is violated,\\n    the result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = arith.index_castui %a : i32 to index\\n      %1 = arith.index_castui %a nneg : i32 to index\\n      %2 = arith.index_castui %b nneg : index to i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"IndexCastTypeConstraint\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"IndexCastTypeConstraint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nonNeg\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$in (`nneg` $nonNeg^)? attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.maximumf\",\n    \"summary\": \"floating-point maximum operation\",\n    \"description\": \"Returns the maximum of the two arguments, treating -0.0 as less than +0.0.\\n    If one of the arguments is NaN, then the result is also NaN.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar floating-point maximum.\\n    %a = arith.maximumf %b, %c : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.maxnumf\",\n    \"summary\": \"floating-point maximum operation\",\n    \"description\": \"Returns the maximum of the two arguments.\\n    If the arguments are -0.0 and +0.0, then the result is either of them.\\n    If one of the arguments is NaN, then the result is the other argument.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar floating-point maximum.\\n    %a = arith.maxnumf %b, %c : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.maxsi\",\n    \"summary\": \"signed integer maximum operation\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.maxui\",\n    \"summary\": \"unsigned integer maximum operation\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.minimumf\",\n    \"summary\": \"floating-point minimum operation\",\n    \"description\": \"Returns the minimum of the two arguments, treating -0.0 as less than +0.0.\\n    If one of the arguments is NaN, then the result is also NaN.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar floating-point minimum.\\n    %a = arith.minimumf %b, %c : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.minnumf\",\n    \"summary\": \"floating-point minimum operation\",\n    \"description\": \"Returns the minimum of the two arguments.\\n    If the arguments are -0.0 and +0.0, then the result is either of them.\\n    If one of the arguments is NaN, then the result is the other argument.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar floating-point minimum.\\n    %a = arith.minnumf %b, %c : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.minsi\",\n    \"summary\": \"signed integer minimum operation\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.minui\",\n    \"summary\": \"unsigned integer minimum operation\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.mulf\",\n    \"summary\": \"floating point multiplication operation\",\n    \"description\": \"The `mulf` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be a floating point\\n    scalar type, a vector whose element type is a floating point type, or a\\n    floating point tensor.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar multiplication.\\n    %a = arith.mulf %b, %c : f64\\n\\n    // SIMD pointwise vector multiplication, e.g. for Intel SSE.\\n    %f = arith.mulf %g, %h : vector<4xf32>\\n\\n    // Tensor pointwise multiplication.\\n    %x = arith.mulf %y, %z : tensor<4x?xbf16>\\n    ```\\n\\n    TODO: In the distant future, this will accept optional attributes for fast\\n    math, contraction, rounding mode, and other controls.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.muli\",\n    \"summary\": \"Integer multiplication operation.\",\n    \"description\": \"Performs N-bit multiplication on the operands. The operands are interpreted as\\n    unsigned bitvectors. The result is represented by a bitvector containing the\\n    mathematical value of the multiplication modulo 2^n, where `n` is the bitwidth.\\n    Because `arith` integers use a two's complement representation, this operation is\\n    applicable on both signed and unsigned integer operands.\\n\\n    The `muli` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be an integer scalar type,\\n    a vector whose element type is integer, or a tensor of integers.\\n\\n    This op supports `nuw`/`nsw` overflow flags which stands for\\n    \\\"No Unsigned Wrap\\\" and \\\"No Signed Wrap\\\", respectively. If the `nuw` and/or\\n    `nsw` flags are present, and an unsigned/signed overflow occurs\\n    (respectively), the result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar multiplication.\\n    %a = arith.muli %b, %c : i64\\n\\n    // Scalar multiplication with overflow flags.\\n    %a = arith.muli %b, %c overflow<nsw, nuw> : i64\\n\\n    // SIMD vector element-wise multiplication.\\n    %f = arith.muli %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise multiplication.\\n    %x = arith.muli %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"DefaultValuedAttr<Arith_IntegerOverflowAttr{none|nsw|nuw}, ::mlir::arith::IntegerOverflowFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`overflow` `` $overflowFlags^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.mulsi_extended\",\n    \"summary\": \"extended signed integer multiplication operation\",\n    \"description\": \"Performs (2*N)-bit multiplication on sign-extended operands. Returns two\\n    N-bit results: the low and the high halves of the product. The low half has\\n    the same value as the result of regular multiplication `arith.muli` with\\n    the same operands.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar multiplication.\\n    %low, %high = arith.mulsi_extended %a, %b : i32\\n\\n    // Vector element-wise multiplication.\\n    %c:2 = arith.mulsi_extended %d, %e : vector<4xi32>\\n\\n    // Tensor element-wise multiplication.\\n    %x:2 = arith.mulsi_extended %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"low\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"high\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'low', 'high']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"arith.mului_extended\",\n    \"summary\": \"extended unsigned integer multiplication operation\",\n    \"description\": \"Performs (2*N)-bit multiplication on zero-extended operands. Returns two\\n    N-bit results: the low and the high halves of the product. The low half has\\n    the same value as the result of regular multiplication `arith.muli` with\\n    the same operands.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar multiplication.\\n    %low, %high = arith.mului_extended %a, %b : i32\\n\\n    // Vector element-wise multiplication.\\n    %c:2 = arith.mului_extended %d, %e : vector<4xi32>\\n\\n    // Tensor element-wise multiplication.\\n    %x:2 = arith.mului_extended %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"low\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"high\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'low', 'high']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"arith.negf\",\n    \"summary\": \"floating point negation\",\n    \"description\": \"The `negf` operation computes the negation of a given value. It takes one\\n    operand and returns one result of the same type. This type may be a float\\n    scalar type, a vector whose element type is float, or a tensor of floats.\\n    It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar negation value.\\n    %a = arith.negf %b : f64\\n\\n    // SIMD vector element-wise negation value.\\n    %f = arith.negf %g : vector<4xf32>\\n\\n    // Tensor element-wise negation value.\\n    %x = arith.negf %y : tensor<4x?xf8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.ori\",\n    \"summary\": \"integer binary or\",\n    \"description\": \"The `ori` operation takes two operands and returns one result, each of these\\n    is required to be the same type. This type may be an integer scalar type, a\\n    vector whose element type is integer, or a tensor of integers. It has no\\n    standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar integer bitwise or.\\n    %a = arith.ori %b, %c : i64\\n\\n    // SIMD vector element-wise bitwise integer or.\\n    %f = arith.ori %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise bitwise integer or.\\n    %x = arith.ori %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.remf\",\n    \"summary\": \"floating point division remainder operation\",\n    \"description\": \"Returns the floating point division remainder.\\n    The remainder has the same sign as the dividend (lhs operand).\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.remsi\",\n    \"summary\": \"signed integer division remainder operation\",\n    \"description\": \"Signed integer division remainder. Treats the leading bit as sign, i.e. `6 %\\n    -2 = 0`.\\n\\n    Division by zero is undefined behavior. When applied to `vector` and\\n    `tensor` values, the behavior is undefined if _any_ elements are divided by\\n    zero.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar signed integer division remainder.\\n    %a = arith.remsi %b, %c : i64\\n\\n    // SIMD vector element-wise division remainder.\\n    %f = arith.remsi %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise integer division remainder.\\n    %x = arith.remsi %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.remui\",\n    \"summary\": \"unsigned integer division remainder operation\",\n    \"description\": \"Unsigned integer division remainder. Treats the leading bit as the most\\n    significant, i.e. for `i16`, `6 % -2 = 6 % (2^16 - 2) = 6`.\\n\\n    Division by zero is undefined behavior. When applied to `vector` and\\n    `tensor` values, the behavior is undefined if _any_ elements are divided by\\n    zero.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar unsigned integer division remainder.\\n    %a = arith.remui %b, %c : i64\\n\\n    // SIMD vector element-wise division remainder.\\n    %f = arith.remui %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise integer division remainder.\\n    %x = arith.remui %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.scaling_extf\",\n    \"summary\": \"Upcasts input floats using provided scales values following OCP MXFP Spec\",\n    \"description\": \"This operation upcasts input floating-point values using provided scale\\n    values. It expects both scales and the input operand to be of the same shape,\\n    making the operation elementwise. Scales are usually calculated per block\\n    following the OCP MXFP spec as described in https://arxiv.org/abs/2310.10537.\\n\\n    If scales are calculated per block where blockSize != 1, then scales may\\n    require broadcasting to make this operation elementwise. For example, let's\\n    say the input is of shape `<dim1 x dim2 x ... dimN>`. Given blockSize != 1 and\\n    assuming quantization happens on the last axis, the input can be reshaped to\\n    `<dim1 x dim2 x ... (dimN/blockSize) x blockSize>`. Scales will be calculated\\n    per block on the last axis. Therefore, scales will be of shape\\n    `<dim1 x dim2 x ... (dimN/blockSize) x 1>`. Scales could also be of some other\\n    shape as long as it is broadcast compatible with the input, e.g.,\\n    `<1 x 1 x ... (dimN/blockSize) x 1>`.\\n\\n    In this example, before calling into `arith.scaling_extf`, scales must be\\n    broadcasted to `<dim1 x dim2 x dim3 ... (dimN/blockSize) x blockSize>`. Note\\n    that there could be multiple quantization axes. Internally,\\n    `arith.scaling_extf` would perform the following:\\n\\n    ```mlir\\n    // Cast scale to result type.\\n    %0 = arith.truncf %1 : f32 to f8E8M0FNU\\n    %1 = arith.extf %0 : f8E8M0FNU to f16\\n\\n    // Cast input to result type.\\n    %2 = arith.extf %3 : f4E2M1FN to f16\\n\\n    // Perform scaling\\n    %3 = arith.mulf %2, %1 : f16\\n    ```\\n    It propagates NaN values. Therefore, if either scale or the input element\\n    contains NaN, then the output element value will also be a NaN.\\n\\n    Example:\\n\\n    ```mlir\\n    // Upcast from f4E2M1FN to f32.\\n    %a = arith.scaling_extf %b, %c : f4E2M1FN, f8E8M0FNU to f32\\n\\n    // Element-wise upcast with broadcast (blockSize = 32).\\n    %f = vector.broadcast %g : vector<1xf8E8M0FNU> to vector<32xf8E8M0FNU>\\n    %h = arith.scaling_extf %i, %f : vector<32xf4E2M1FN>, vector<32xf8E8M0FNU> to vector<32xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" },\n      { \"name\": \"scale\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"OptionalAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}>\" }\n    ],\n    \"assemblyFormat\": \"$in `,` $scale (`fastmath` `` $fastmath^)? attr-dict `:`\\n      type($in) `,` type($scale) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.scaling_truncf\",\n    \"summary\": \"Downcasts input floating point values using provided scales values following OCP MXFP Spec\",\n    \"description\": \"This operation downcasts input using the provided scale values. It expects\\n    both scales and the input operand to be of the same shape and, therefore,\\n    makes the operation elementwise. Scales are usually calculated per block\\n    following the OCP MXFP spec as described in https://arxiv.org/abs/2310.10537.\\n    Users are required to normalize and clamp the scales as necessary before calling\\n    passing them to this operation.  OCP MXFP spec also does the flushing of denorms\\n    on the input operand, which should be handled during lowering by passing appropriate\\n    fastMath flag to this operation.\\n\\n    If scales are calculated per block where blockSize != 1, scales may require\\n    broadcasting to make this operation elementwise. For example, let's say the\\n    input is of shape `<dim1 x dim2 x ... dimN>`. Given blockSize != 1 and\\n    assuming quantization happens on the last axis, the input can be reshaped to\\n    `<dim1 x dim2 x ... (dimN/blockSize) x blockSize>`. Scales will be calculated\\n    per block on the last axis. Therefore, scales will be of shape\\n    `<dim1 x dim2 x ... (dimN/blockSize) x 1>`. Scales could also be of some other\\n    shape as long as it is broadcast compatible with the input, e.g.,\\n    `<1 x 1 x ... (dimN/blockSize) x 1>`.\\n\\n    In this example, before calling into `arith.scaling_truncf`, scales must be\\n    broadcasted to `<dim1 x dim2 x dim3 ... (dimN/blockSize) x blockSize>`. Note\\n    that there could be multiple quantization axes. Internally,\\n    `arith.scaling_truncf` would perform the following:\\n\\n    ```mlir\\n    // Cast scale to input type.\\n    %0 = arith.truncf %1 : f32 to f8E8M0FNU\\n    %1 = arith.extf %0 : f8E8M0FNU to f16\\n\\n    // Perform scaling.\\n    %3 = arith.divf %2, %1 : f16\\n\\n    // Cast to result type.\\n    %4 = arith.truncf %3 : f16 to f4E2M1FN\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    // Downcast from f32 to f4E2M1FN.\\n    %a = arith.scaling_truncf %b, %c : f32, f8E8M0FNU to f4E2M1FN\\n\\n    // Element-wise downcast with broadcast (blockSize = 32).\\n    %f = vector.broadcast %g : vector<1xf8E8M0FNU> to vector<32xf8E8M0FNU>\\n    %h = arith.scaling_truncf %i, %f : vector<32xbf16>, vector<32xf8E8M0FNU> to vector<32xf4E2M1FN>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" },\n      { \"name\": \"scale\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"roundingmode\", \"type\": \"OptionalAttr<Arith_RoundingModeAttr{to_nearest_even|downward|upward|toward_zero|to_nearest_away}>\" },\n      { \"name\": \"fastmath\", \"type\": \"OptionalAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}>\" }\n    ],\n    \"assemblyFormat\": \"$in `,` $scale ($roundingmode^)? (`fastmath` `` $fastmath^)? attr-dict `:`\\n      type($in) `,` type($scale) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.select\",\n    \"summary\": \"select operation\",\n    \"description\": \"The `arith.select` operation chooses one value based on a binary condition\\n    supplied as its first operand.\\n\\n    If the value of the first operand (the condition) is `1`, then the second\\n    operand is returned, and the third operand is ignored, even if it was poison.\\n\\n    If the value of the first operand (the condition) is `0`, then the third\\n    operand is returned, and the second operand is ignored, even if it was poison.\\n\\n    If the value of the first operand (the condition) is poison, then the\\n    operation returns poison.\\n\\n    The operation applies to vectors and tensors elementwise given the _shape_\\n    of all operands is identical. The choice is made for each element\\n    individually based on the value at the same position as the element in the\\n    condition operand. If an i1 is provided as the condition, the entire vector\\n    or tensor is chosen.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of scalar selection.\\n    %x = arith.select %cond, %true, %false : i32\\n\\n    // Generic form of the same operation.\\n    %x = \\\"arith.select\\\"(%cond, %true, %false) : (i1, i32, i32) -> i32\\n\\n    // Element-wise vector selection.\\n    %vx = arith.select %vcond, %vtrue, %vfalse : vector<42xi1>, vector<42xf32>\\n\\n    // Full vector selection.\\n    %vx = arith.select %cond, %vtrue, %vfalse : vector<42xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"BoolLike\" },\n      { \"name\": \"true_value\", \"type\": \"AnyType\" },\n      { \"name\": \"false_value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"arith.shli\",\n    \"summary\": \"integer left-shift\",\n    \"description\": \"The `shli` operation shifts the integer value of the first operand to the left\\n    by the integer value of the second operand. The second operand is interpreted as\\n    unsigned. The low order bits are filled with zeros. If the value of the second\\n    operand is greater or equal than the bitwidth of the first operand, then the\\n    operation returns poison.\\n\\n    This op supports `nuw`/`nsw` overflow flags which stands for\\n    \\\"No Unsigned Wrap\\\" and \\\"No Signed Wrap\\\", respectively. If the `nuw` and/or\\n    `nsw` flags are present, and an unsigned/signed overflow occurs\\n    (respectively), the result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = arith.constant 5 : i8  // %1 is 0b00000101\\n    %2 = arith.constant 3 : i8\\n    %3 = arith.shli %1, %2 : i8 // %3 is 0b00101000\\n    %4 = arith.shli %1, %2 overflow<nsw, nuw> : i8\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"DefaultValuedAttr<Arith_IntegerOverflowAttr{none|nsw|nuw}, ::mlir::arith::IntegerOverflowFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`overflow` `` $overflowFlags^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.shrsi\",\n    \"summary\": \"signed integer right-shift\",\n    \"description\": \"The `shrsi` operation shifts an integer value of the first operand to the right\\n    by the value of the second operand. The first operand is interpreted as signed,\\n    and the second operand is interpreter as unsigned. The high order bits in the\\n    output are filled with copies of the most-significant bit of the shifted value\\n    (which means that the sign of the value is preserved). If the value of the second\\n    operand is greater or equal than bitwidth of the first operand, then the operation\\n    returns poison.\\n\\n    If the `exact` attribute is present, the result value of shrsi is a poison\\n    value if any of the bits shifted out are non-zero.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = arith.constant 160 : i8         // %1 is 0b10100000\\n    %2 = arith.constant 3 : i8\\n    %3 = arith.shrsi %1, %2 exact : i8   // %3 is 0b11110100\\n    %4 = arith.constant 98 : i8          // %4 is 0b01100010\\n    %5 = arith.shrsi %4, %2 : i8         // %5 is 0b00001100\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`exact` $isExact^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.shrui\",\n    \"summary\": \"unsigned integer right-shift\",\n    \"description\": \"The `shrui` operation shifts an integer value of the first operand to the right\\n    by the value of the second operand. The first operand is interpreted as unsigned,\\n    and the second operand is interpreted as unsigned. The high order bits are always\\n    filled with zeros. If the value of the second operand is greater or equal than the\\n    bitwidth of the first operand, then the operation returns poison.\\n\\n    If the `exact` attribute is present, the result value of shrui is a poison\\n    value if any of the bits shifted out are non-zero.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = arith.constant 160 : i8        // %1 is 0b10100000\\n    %2 = arith.constant 3 : i8\\n    %3 = arith.constant 6 : i8\\n    %4 = arith.shrui %1, %2 exact : i8  // %4 is 0b00010100\\n    %5 = arith.shrui %1, %3 : i8        // %3 is 0b00000010\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`exact` $isExact^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.sitofp\",\n    \"summary\": \"cast from integer type to floating-point\",\n    \"description\": \"Cast from a value interpreted as a signed integer to the corresponding\\n    floating-point value. If the value cannot be exactly represented, it is\\n    rounded using the default rounding mode. When operating on vectors, casts\\n    elementwise.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.subf\",\n    \"summary\": \"floating point subtraction operation\",\n    \"description\": \"The `subf` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be a floating point\\n    scalar type, a vector whose element type is a floating point type, or a\\n    floating point tensor.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar subtraction.\\n    %a = arith.subf %b, %c : f64\\n\\n    // SIMD vector subtraction, e.g. for Intel SSE.\\n    %f = arith.subf %g, %h : vector<4xf32>\\n\\n    // Tensor subtraction.\\n    %x = arith.subf %y, %z : tensor<4x?xbf16>\\n    ```\\n\\n    TODO: In the distant future, this will accept optional attributes for fast\\n    math, contraction, rounding mode, and other controls.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.subi\",\n    \"summary\": \"Integer subtraction operation.\",\n    \"description\": \"Performs N-bit subtraction on the operands. The operands are interpreted as unsigned\\n    bitvectors. The result is represented by a bitvector containing the mathematical\\n    value of the subtraction modulo 2^n, where `n` is the bitwidth. Because `arith`\\n    integers use a two's complement representation, this operation is applicable on\\n    both signed and unsigned integer operands.\\n\\n    The `subi` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be an integer scalar type,\\n    a vector whose element type is integer, or a tensor of integers.\\n\\n    This op supports `nuw`/`nsw` overflow flags which stands for\\n    \\\"No Unsigned Wrap\\\" and \\\"No Signed Wrap\\\", respectively. If the `nuw` and/or\\n    `nsw` flags are present, and an unsigned/signed overflow occurs\\n    (respectively), the result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar subtraction.\\n    %a = arith.subi %b, %c : i64\\n\\n    // Scalar subtraction with overflow flags.\\n    %a = arith.subi %b, %c overflow<nsw, nuw> : i64\\n\\n    // SIMD vector element-wise subtraction.\\n    %f = arith.subi %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise subtraction.\\n    %x = arith.subi %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"DefaultValuedAttr<Arith_IntegerOverflowAttr{none|nsw|nuw}, ::mlir::arith::IntegerOverflowFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`overflow` `` $overflowFlags^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arith.truncf\",\n    \"summary\": \"cast from floating-point to narrower floating-point\",\n    \"description\": \"Truncate a floating-point value to a smaller floating-point-typed value.\\n    The destination type must be strictly narrower than the source type.\\n    If the value cannot be exactly represented, it is rounded using the\\n    provided rounding mode or the default one if no rounding mode is provided.\\n    When operating on vectors, casts elementwise.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"roundingmode\", \"type\": \"OptionalAttr<Arith_RoundingModeAttr{to_nearest_even|downward|upward|toward_zero|to_nearest_away}>\" },\n      { \"name\": \"fastmath\", \"type\": \"OptionalAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}>\" }\n    ],\n    \"assemblyFormat\": \"$in ($roundingmode^)?\\n                          (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.trunci\",\n    \"summary\": \"integer truncation operation\",\n    \"description\": \"The integer truncation operation takes an integer input of\\n    width M and an integer destination type of width N. The destination\\n    bit-width must be smaller than the input bit-width (N < M).\\n    The top-most (N - M) bits of the input are discarded.\\n\\n    This op supports `nuw`/`nsw` overflow flags which stands for \\\"No Unsigned\\n    Wrap\\\" and \\\"No Signed Wrap\\\", respectively. If the nuw keyword is present,\\n    and any of the truncated bits are non-zero, the result is a poison value.\\n    If the nsw keyword is present, and any of the truncated bits are not the\\n    same as the top bit of the truncation result, the result is a poison value.\\n\\n    Example:\\n\\n    ```mlir\\n      // Scalar truncation.\\n      %1 = arith.constant 21 : i5     // %1 is 0b10101\\n      %2 = arith.trunci %1 : i5 to i4 // %2 is 0b0101\\n      %3 = arith.trunci %1 : i5 to i3 // %3 is 0b101\\n\\n      // Vector truncation.\\n      %4 = arith.trunci %0 : vector<2 x i32> to vector<2 x i16>\\n\\n      // Scalar truncation with overflow flags.\\n      %5 = arith.trunci %a overflow<nsw, nuw> : i32 to i16\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"DefaultValuedAttr<Arith_IntegerOverflowAttr{none|nsw|nuw}, ::mlir::arith::IntegerOverflowFlags::none>\" }\n    ],\n    \"assemblyFormat\": \"$in (`overflow` `` $overflowFlags^)? attr-dict\\n    `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.uitofp\",\n    \"summary\": \"cast from unsigned integer type to floating-point\",\n    \"description\": \"Cast from a value interpreted as unsigned integer to the corresponding\\n    floating-point value. If the value cannot be exactly represented, it is\\n    rounded using the default rounding mode. When operating on vectors, casts\\n    elementwise.\\n\\n    When the `nneg` flag is present, the operand is assumed to have\\n    the most significant bit set to 0. In this case, zero extension is\\n    equivalent to sign extension. When this assumption is violated, the\\n    result is poison.\\n\\n    Example:\\n\\n    ```mlir\\n      // Without nneg flag.\\n      %0 = arith.uitofp %a : i32 to f64\\n\\n      // With nneg flag.\\n      %1 = arith.uitofp %a nneg : i32 to f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"SignlessFixedWidthIntegerLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nonNeg\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$in (`nneg` $nonNeg^)? attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"arith.xori\",\n    \"summary\": \"integer binary xor\",\n    \"description\": \"The `xori` operation takes two operands and returns one result, each of\\n    these is required to be the same type. This type may be an integer scalar\\n    type, a vector whose element type is integer, or a tensor of integers. It\\n    has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar integer bitwise xor.\\n    %a = arith.xori %b, %c : i64\\n\\n    // SIMD vector element-wise bitwise integer xor.\\n    %f = arith.xori %g, %h : vector<4xi32>\\n\\n    // Tensor element-wise bitwise integer xor.\\n    %x = arith.xori %y, %z : tensor<4x?xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Arith_SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arm_neon.2d.sdot\",\n    \"summary\": \"sdot op\",\n    \"description\": \"The two input vectors `b` and `c` have a 2D shape, consisting of either 2\\n    or 4 rows, each row having length 4. This operation computes the pair-wise\\n    dot-products of the rows of `b` and `c` and accumulates them with the\\n    corresponding entry of `a`:\\n\\n    ```\\n    res[i] := a[i] + dot_product(b[i, ...], c[i, ...])\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[4, 2], [I32]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 8], [I8]>\" },\n      { \"name\": \"c\", \"type\": \"VectorOfLengthAndType<[16, 8], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"VectorOfLengthAndType<[4, 2], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['b', 'c']>\" },\n      { \"type\": \"AllTypesMatch<['a', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` type($b) `,` type($c) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_neon.intr.bfmmla\",\n    \"summary\": \"BFloat16 matrix multiply-accumulate to single-precision\",\n    \"description\": \"BFMMLA: BFloat16 matrix multiply-accumulate to single-precision.\\n\\n    The operation multiplies the 2x4 BFloat16 matrix in the first source vector\\n    with the 4x2 BFloat16 matrix in the second source vector, then accumulates\\n    this intermediate result with the 2x2 Float32 matrix in the accumulator\\n    vector, yielding the final 2x2 Float32 result.\\n\\n    Source:\\n    https://developer.arm.com/architectures/instruction-sets/intrinsics/vbfmmlaq_f32\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"NeonVectorOfLength<4, F32>\" },\n      { \"name\": \"src1\", \"type\": \"NeonVectorOfLength<8, BF16>\" },\n      { \"name\": \"src2\", \"type\": \"NeonVectorOfLength<8, BF16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"NeonVectorOfLength<4, F32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_neon.intr.sdot\",\n    \"summary\": \"sdot op\",\n    \"description\": \"Signed integer addition of dot product (vector). This instruction performs\\n    the following operation on signed integer vectors: res = dot(b, c) + a,\\n    where vector operands are partitioned into groups of four elements.\\n\\n    Source:\\n    https://developer.arm.com/architectures/instruction-sets/simd-isas/neon/intrinsics\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[4, 2], [I32]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 8], [I8]>\" },\n      { \"name\": \"c\", \"type\": \"VectorOfLengthAndType<[16, 8], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"VectorOfLengthAndType<[4, 2], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['b', 'c']>\" },\n      { \"type\": \"AllTypesMatch<['a', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'b', 'res', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` type($b) `,` type($c) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_neon.intr.smmla\",\n    \"summary\": \"Matrix-matrix multiply and accumulate op\",\n    \"description\": \"SMMLA: Signed integer matrix multiply-accumulate.\\n\\n    Signed 8-bit integer matrix multiply-accumulate. This instruction multiplies\\n    the 2x8 matrix of signed 8-bit integer values in the first source vector by\\n    the 8x2 matrix of signed 8-bit integer values in the second source vector.\\n    The resulting 2x2 32-bit integer matrix product is destructively added to\\n    the 32-bit integer matrix accumulator in the destination vector. This is\\n    equivalent to performing an 8-way dot product per destination element.\\n\\n    Source:\\n    https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon]&q=smmla\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"NeonVectorOfLength<4, I32>\" },\n      { \"name\": \"src1\", \"type\": \"NeonVectorOfLength<16, I8>\" },\n      { \"name\": \"src2\", \"type\": \"NeonVectorOfLength<16, I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"NeonVectorOfLength<4, I32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_neon.intr.smull\",\n    \"summary\": \"smull roundscale op\",\n    \"description\": \"Signed Multiply Long (vector). This instruction multiplies corresponding\\n    signed integer values in the lower or upper half of the vectors of the two\\n    source SIMD&FP registers, places the results in a vector, and writes the\\n    vector to the destination SIMD&FP register.\\n\\n    Source:\\n    https://developer.arm.com/architectures/instruction-sets/simd-isas/neon/intrinsics\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8, 4, 2], [I8, I16, I32]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8, 4, 2], [I8, I16, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"VectorOfLengthAndType<[8, 4, 2], [I16, I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"TypesMatchWith<'a', 'res', '::llvm::cast<VectorType>($_self).scaleElementBitwidth(2)'>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($a) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_neon.intr.ummla\",\n    \"summary\": \"Unsinged matrix-matrix multiply and accumulate op\",\n    \"description\": \"UMMLA: Signed integer matrix multiply-accumulate.\\n\\n    Unsigned 8-bit integer matrix multiply-accumulate. This instruction\\n    multiplies the 2x8 matrix of unsigned 8-bit integer values in the first\\n    source vector by the 8x2 matrix of unsigned 8-bit integer values in the\\n    second source vector. The resulting 2x2 32-bit integer matrix product is\\n    destructively added to the 32-bit integer matrix accumulator in the\\n    destination vector. This is equivalent to performing an 8-way dot product\\n    per destination element.\\n\\n    Source:\\n    https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon]&q=ummla\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"NeonVectorOfLength<4, I32>\" },\n      { \"name\": \"src1\", \"type\": \"NeonVectorOfLength<16, I8>\" },\n      { \"name\": \"src2\", \"type\": \"NeonVectorOfLength<16, I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"NeonVectorOfLength<4, I32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_neon.intr.usmmla\",\n    \"summary\": \"Unsignged and signed matrix-matrix multiply and accumulate op\",\n    \"description\": \"USMMLA: Signed integer matrix multiply-accumulate.\\n\\n    Unsigned and signed 8-bit integer matrix multiply-accumulate. This\\n    instruction multiplies the 2x8 matrix of unsigned 8-bit integer values in\\n    the first source vector by the 8x2 matrix of signed 8-bit integer values in\\n    the second source vector. The resulting 2x2 32-bit integer matrix product is\\n    destructively added to the 32-bit integer matrix accumulator in the\\n    destination vector. This is equivalent to performing an 8-way dot product\\n     per destination element.\\n\\n\\n    Source:\\n    https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon]&q=usmmla\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"NeonVectorOfLength<4, I32>\" },\n      { \"name\": \"src1\", \"type\": \"NeonVectorOfLength<16, I8>\" },\n      { \"name\": \"src2\", \"type\": \"NeonVectorOfLength<16, I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"NeonVectorOfLength<4, I32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_sme.copy_tile\",\n    \"summary\": \"Copies an SME tile value\",\n    \"description\": \"Copies an SME \\\"virtual tile\\\" value to a new SSA value. This operation is\\n    primarily intended to be used to normalize the IR prior to tile allocation.\\n\\n    Example:\\n\\n    ```mlir\\n    %copy = arm_sme.copy_tile %tile : vector<[4]x[4]xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tile\", \"type\": \"SMETile\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SMETile\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['tile', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$tile attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.extract_tile_slice\",\n    \"summary\": \"Extract 1-D scalable vector from slice of 2-D tile\",\n    \"description\": \"Extracts a 1-D scalable slice from a 2-D scalable tile at the given index.\\n    A tile slice is a 1-D vector of horizontally or vertically contiguous\\n    elements within a ZA tile.\\n\\n    An optional tile slice layout attribute specifies whether the tile slice is\\n    horizontal (default) or vertical.\\n\\n    Example 1: Extract `vector<[16]xi8>` from tile horizontally at the given index.\\n    ```mlir\\n    %slice = arm_sme.extract_tile_slice %tile[%tile_slice_index] : vector<[16]xi8> from vector<[16]x[16]xi8>\\n    ```\\n\\n    Example 2: Extract `vector<[2]xf64>` from tile vertically at the given index.\\n    ```mlir\\n    %slice = arm_sme.extract_tile_slice %tile[%tile_slice_index] layout<vertical> : vector<[2]xf64> from vector<[2]x[2]xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tile\", \"type\": \"SMETile\" },\n      { \"name\": \"tile_slice_index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SVEVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"ArmSME_TileSliceLayoutAttr{horizontal|vertical}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'tile', 'result', 'VectorType(VectorType::Builder(::llvm::cast<mlir::VectorType>($_self)).dropDim(0))'>\" }\n    ],\n    \"assemblyFormat\": \"$tile `[` $tile_slice_index `]` (`layout` `` $layout^)? attr-dict\\n      `:` type($result) `from` type($tile)\"\n  },\n  {\n    \"name\": \"arm_sme.fmopa_2way\",\n    \"summary\": \"Floating-point sum of 2 outer products and accumulate\",\n    \"description\": \"This operation represents a sum of 2 widened outer products. It takes 2 1-D\\n    scalable vectors as input and a 2-D scalable vector (ZA tile) as output.\\n\\n    For example (fp16 to fp32):\\n\\n    ```mlir\\n    %result = arm_sme.fmopa_2way %lhs, %rhs :\\n      vector<[8]xf16>, vector<[8]xf16> into vector<[4]x[4]xf32>\\n    ```\\n\\n    The `lhs` encodes a matrix of shape SVLSx2 and the `rhs` a matrix of\\n    2xSVLS, where SVLS (spec [1], section B2.1) is the number of 32-bit\\n    elements in a vector of SVL bits. To illustrate, below is a breakdown of\\n    this operation for fp16 to fp32, SVL=128 (i.e., vscale=1):\\n\\n    ```\\n                          LHS                          RHS\\n               [A0 A1 A2 A3 A4 A5 A6 A7]    [B0 B1 B2 B3 B4 B5 B6 B7]\\n\\n    ----------------------------------------------------------------------------\\n\\n                                  implicit layout\\n\\n                              [A0 A1]    |\\n                              [A2 A3]    |    [B0 B2 B4 B6]\\n                              [A4 A5]    |    [B1 B3 B5 B7]\\n                              [A6 A7]    |\\n\\n    ----------------------------------------------------------------------------\\n\\n                                  2 outer products\\n\\n                      Acol0 ⊗ Brow0      |           Acol1 ⊗ Brow1\\n                      -------------      |           -------------\\n                                         |\\n                  [B0 B2 B4 B6]          |       [B1 B3 B5 B7]\\n                                         |\\n             [A0  [A0B0 A0B2 A0B4 A0B6]  |  [A1  [A1B1 A1B3 A1B5 A1B7]\\n              A2  [A2B0 A2B2 A2B4 A2B6]  |   A3  [A3B1 A3B3 A3B5 A3B7]\\n              A4  [A4B0 A4B2 A4B4 A4B6]  |   A5  [A5B1 A5B3 A5B5 A5B7]\\n              A6] [A6B0 A6B2 A6B4 A6B6]  |   A7] [A7B1 A7B3 A7B5 A7B7]\\n                                         |\\n\\n    ----------------------------------------------------------------------------\\n\\n                              sum of 2 outer products\\n\\n                           Acol0 ⊗ Brow0 + Acol1 ⊗ Brow1\\n\\n                 [A0B0 + A1B1 A0B2 + A1B3 A0B4 + A1B5 A0B6 + A1B7]\\n                 [A2B0 + A3B1 A2B2 + A3B3 A2B4 + A3B5 A2B6 + A3B7]\\n                 [A4B0 + A5B1 A4B2 + A5B3 A4B4 + A5B5 A4B6 + A5B7]\\n                 [A6B0 + A7B1 A6B2 + A7B3 A6B4 + A7B5 A6B6 + A7B7]\\n\\n    ----------------------------------------------------------------------------\\n    ```\\n\\n    This operation enables the folding of 2 outer products chained via the\\n    accumulator into a single outer product.\\n\\n    For example:\\n\\n    ```mlir\\n    %a0_ext = arith.extf %a0 : vector<[4]xf16> to vector<[4]xf32>\\n    %b0_ext = arith.extf %b0 : vector<[4]xf16> to vector<[4]xf32>\\n    %a1_ext = arith.extf %a1 : vector<[4]xf16> to vector<[4]xf32>\\n    %b1_ext = arith.extf %b1 : vector<[4]xf16> to vector<[4]xf32>\\n\\n    %0 = arm_sme.outerproduct %a0_ext, %b0_ext : vector<[4]xf32>, vector<[4]xf32>\\n    %1 = arm_sme.outerproduct %a1_ext, %b1_ext acc(%0) : vector<[4]xf32>, vector<[4]xf32>\\n    ```\\n\\n    The 2 outer products in the example above can be fused into a single outer\\n    product as follows:\\n\\n    ```mlir\\n    %a_packed = vector.interleave %a0, %a1 : vector<[4]xf16> -> vector<[8]xf16>\\n    %b_packed = vector.interleave %b0, %b1 : vector<[4]xf16> -> vector<[8]xf16>\\n    %0 = arm_sme.fmopa_2way %a_packed, %b_packed : vector<[8]xf16>, vector<[8]xf16> into vector<[4]x[4]xf32>\\n    ```\\n\\n    This is implemented in the `-arm-sme-outer-product-fusion` pass.\\n\\n    Example: FP16 to FP32\\n    ```mlir\\n    %result = arm_sme.fmopa_2way $lhs, $rhs : vector<[8]xf16>, vector<[8]xf16> into vector<[4]x[4]xf32>\\n    ```\\n\\n    Example: BF16 to FP32\\n    ```mlir\\n    %result = arm_sme.fmopa_2way $lhs, $rhs : vector<[8]xbf16>, vector<[8]xbf16> into vector<[4]x[4]xf32>\\n    ```\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [FMOPA (widening, 2-way, FP16 to FP32)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/FMOPA--widening--2-way--FP16-to-FP32---Half-precision-floating-point-sum-of-outer-products-and-accumulate-) | +sme |\\n    | [BFMOPA (widening, 2-way, BF16 to FP32)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/BFMOPA--widening---BFloat16-sum-of-outer-products-and-accumulate-) | +sme |\\n\\n    [1] https://developer.arm.com/documentation/ddi0616\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [8], [F16, BF16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4f32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.fmops_2way\",\n    \"summary\": \"Floating-point sum of 2 outer products and subtract\",\n    \"description\": \"Equivalent to `fmopa_2way` but outer products are subtracted from\\n    destination `result`.\\n\\n    Example: FP16 to FP32\\n    ```mlir\\n    %result = arm_sme.fmops_2way $lhs, $rhs : vector<[8]xf16>, vector<[8]xf16> into vector<[4]x[4]xf32>\\n    ```\\n\\n    Example: BF16 to FP32\\n    ```mlir\\n    %result = arm_sme.fmops_2way $lhs, $rhs : vector<[8]xbf16>, vector<[8]xbf16> into vector<[4]x[4]xf32>\\n    ```\\n\\n    Refer to\\n    [fmopa_2way](#arm_smefmopa_2way-arm_smefmopa2wayop) for a detailed\\n    description of 2-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [FMOPS (widening, 2-way, FP16 to FP32)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/FMOPS--widening---Half-precision-floating-point-sum-of-outer-products-and-subtract-) | +sme |\\n    | [BFMOPS (widening, 2-way, BF16 to FP32)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/BMOPS--Bitwise-exclusive-NOR-population-count-outer-product-and-subtract-) | +sme |\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [8], [F16, BF16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4f32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.get_tile\",\n    \"summary\": \"Creates an undefined value of SME virtual tile type\",\n    \"description\": \"Creates a new SME \\\"virtual tile\\\" value within a function. The contents of\\n    the tile returned from this operation are undefined.\\n\\n    Example 1:\\n\\n    ```mlir\\n    // Create an 8-bit element \\\"virtual tile\\\" value:\\n    %za0_b = arm_sme.get_tile: vector<[16]x[16]xi8>\\n    ```\\n\\n    Example 2:\\n\\n    ```mlir\\n    // Create two 16-bit element \\\"virtual tiles\\\" values:\\n    %za0_h = arm_sme.get_tile : vector<[8]x[8]xi16>\\n    %za1_h = arm_sme.get_tile : vector<[8]x[8]xi16>\\n    ```\\n\\n    Example 3:\\n    ```mlir\\n    // Create an 128-bit element \\\"virtual tile\\\" value:\\n    %za0_q = arm_sme.get_tile : vector<[1]x[1]xi128>\\n    ```\",\n    \"results\": [\n      { \"name\": \"tile\", \"type\": \"SMETile\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($tile)\"\n  },\n  {\n    \"name\": \"arm_sme.insert_tile_slice\",\n    \"summary\": \"Insert 1-D scalable vector into slice of 2-D tile\",\n    \"description\": \"Inserts a 1-D scalable vector into a slice of a 2-D scalable vector tile at\\n    the given index. The type of the 1-D scalable vector to be inserted must\\n    match the type of the tile slice. A tile slice is a 1-D vector of\\n    horizontally or vertically contiguous elements within a ZA tile. The updated\\n    tile is returned as the result.\\n\\n    An optional tile slice layout attribute specifies whether the tile slice is\\n    horizontal (default) or vertical.\\n\\n    Example 1: Insert `vector<[16]xi8>` into tile horizontally at the given index.\\n    ```mlir\\n    %tile_update = arm_sme.insert_tile_slice %vector, %tile[%tile_slice_index] : vector<[16]xi8> into vector<[16]x[16]xi8>\\n    ```\\n\\n    Example 2: Insert `vector<[2]xf64>` into tile vertically at the given index.\\n    ```mlir\\n    %tile_update = arm_sme.insert_tile_slice %vector, %tile[%tile_slice_index] layout<vertical> : vector<[2]xf64> into vector<[2]x[2]xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"SVEVector\" },\n      { \"name\": \"tile\", \"type\": \"SMETile\" },\n      { \"name\": \"tile_slice_index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SMETile\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"ArmSME_TileSliceLayoutAttr{horizontal|vertical}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['tile', 'result']>\" },\n      { \"type\": \"TypesMatchWith<'tile', 'vector', '[object Object],[object Object],[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$vector `,` $tile `[` $tile_slice_index `]` (`layout` `` $layout^)?\\n      attr-dict `:` type($vector) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.load_tile_slice\",\n    \"summary\": \"Tile slice load and update operation\",\n    \"description\": \"Loads a 1D tile slice from memory into a 2D SME \\\"virtual tile\\\". The tile\\n    slice is defined by the dimension of the 2D scalable vector type pointed by\\n    the index. A tile slice index describes where in the input tile the tile\\n    slice is loaded to. An optional tile slice layout attribute specifies\\n    whether the tile slice being loaded at the given index is horizontal\\n    (default) or vertical. The updated tile is returned as the result.\\n\\n    The slice of memory read is defined by a base and indices and must be\\n    contiguous. The memref must be either rank 1 or rank 2, have dynamic\\n    dimensions since the operation is scalable, and the element type must be a\\n    scalar that matches the element type of the result.\\n\\n    The provided `mask` is used to specify which elements of the tile slice\\n    will be loaded.\\n\\n    Example 1: Load a vector<[16]xi8> tile slice from memory into tile horizontally (default) at given index.\\n    ```mlir\\n    %tile_update = arm_sme.load_tile_slice %base[%c0], %mask, %tile, %tile_slice_index : memref<?x?xi8>, vector<[16]xi1>, vector<[16]x[16]xi8>\\n    ```\\n\\n    Example 2: Load a vector<[4]xf32> tile slice from memory into tile vertically at given index.\\n    ```mlir\\n    %tile_update = arm_sme.load_tile_slice %base[%c0], %mask, %tile, %tile_slice_index layout<vertical> : memref<?x?xf32>, vector<[4]xi1>, vector<[4]x[4]xf32>\\n    ```\\n\\n    Example 3: Load a vector<[1]xi128> tile slice from memory into tile vertically at given index.\\n    ```mlir\\n    %tile_update = arm_sme.load_tile_slice %base[%c0], %mask, %tile, %tile_slice_index layout<vertical> : memref<?x?xi128>, vector<[1]xi1>, vector<[1]x[1]xi128>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"mask\", \"type\": \"SVEPredicate\" },\n      { \"name\": \"tile\", \"type\": \"SMETile\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"tile_slice_index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SMETile\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"ArmSME_TileSliceLayoutAttr{horizontal|vertical}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['tile', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $mask `,` $tile `,` $tile_slice_index\\n      (`layout` `` $layout^)? attr-dict `:` type($base) `,` type($mask) `,`\\n                                            type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.outerproduct\",\n    \"summary\": \"Outer product with optional fused add/sub\",\n    \"description\": \"This operation represents an outer product that fits within an SME tile.\\n    All operands must be SVE vectors and the result a SME tile. Unlike\\n    `vector.outerproduct` masking is on the operands (rather than the result),\\n    which mirrors the SME instructions.\\n\\n    Example 1: Unmasked outerproduct (without accumulator)\\n    ```mlir\\n    // Not specifying an accumulator implicitly zeros the destination tile.\\n    %result = arm_sme.outerproduct $lhs, $rhs : vector<[4]xf32>, vector<[4]xf32>\\n    ```\\n\\n    Example 2: Unmasked outerproduct (with accumulator)\\n    ```mlir\\n    %result = arm_sme.outerproduct $lhs, $rhs acc($accumulator)\\n                : vector<[4]xf32>, vector<[4]xf32>\\n    ```\\n\\n    Example 3: Masked outerproduct\\n    ```mlir\\n    %result = arm_sme.outerproduct $lhs, $rhs masks($lhsMask, $rhsMask)\\n                : vector<[4]xf32>, vector<[4]xf32>\\n    ```\\n\\n    Example 4: Masked outerproduct (with accumulator)\\n    ```mlir\\n    %result = arm_sme.outerproduct $lhs, $rhs acc($accumulator) masks($lhsMask, $rhsMask)\\n                : vector<[4]xf32>, vector<[4]xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SVEVector\" },\n      { \"name\": \"rhs\", \"type\": \"SVEVector\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<SVEPredicate>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<SVEPredicate>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<SMETile>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SMETile\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"ArmSME_CombiningKindAttr{add|sub}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `kind` `` $kind\\n      | `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs)\"\n  },\n  {\n    \"name\": \"arm_sme.smopa_2way\",\n    \"summary\": \"Signed integer sum of 2 outer products and accumulate\",\n    \"description\": \"Example:\\n    ```mlir\\n    %result = arm_sme.smopa_2way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Refer to\\n    [fmopa_2way](#arm_smefmopa_2way-arm_smefmopa2wayop) for a detailed\\n    description of 2-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [SMOPA (2-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/SMOPA--2-way---Signed-integer-sum-of-outer-products-and-accumulate-) | +sme2 |\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.smopa_4way\",\n    \"summary\": \"Signed integer sum of 4 outer products and accumulate\",\n    \"description\": \"This operation represents a sum of 4 widened outer products. It takes 2 1-D\\n    scalable vectors as input and a 2-D scalable vector (ZA tile) as output.\\n\\n    For example (i8 to i32):\\n\\n    ```mlir\\n    %result = arm_sme.smopa_4way $lhs, $rhs :\\n      vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    The `lhs` encodes a matrix of shape SVLSx4 and the `rhs` a matrix of\\n    4xSVLS, where SVLS (spec [1], section B2.1) is the number of 32-bit\\n    elements in a vector of SVL bits. To illustrate, below is a breakdown of\\n    this operation for i8 to i32, SVL=128 (i.e., vscale=1):\\n\\n    ```\\n                                        LHS\\n              [A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A15 A14 A15]\\n\\n                                        RHS\\n              [B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15]\\n\\n    ----------------------------------------------------------------------------\\n\\n                                  implicit layout\\n\\n                    [A0   A1  A2  A3]    |    [B0 B4  B8 B12]\\n                    [A4   A5  A6  A7]    |    [B1 B5  B9 B13]\\n                    [A8   A9 A10 A11]    |    [B2 B6 B10 B14]\\n                    [A12 A13 A14 A15]    |    [B3 B7 B11 B15]\\n\\n    ----------------------------------------------------------------------------\\n\\n                                  4 outer products\\n\\n                 Acol0 ⊗ Brow0           |            Acol1 ⊗ Brow1\\n                 -------------           |            -------------\\n                                         |\\n             [B0 B4 B8 B12]              |        [B1 B5 B9 B13]\\n                                         |\\n       [A0   [ A0B0  A0B4  A0B8  A0B12]  |  [A1   [ A1B1  A1B5  A1B9  A1B13]\\n        A4   [ A4B0  A4B4  A4B8  A4B12]  |   A5   [ A5B1  A5B5  A5B9  A5B13]\\n        A8   [ A8B0  A8B4  A8B8  A8B12]  |   A9   [ A9B1  A9B5  A9B9  A9B13]\\n        A12] [A12B0 A12B4 A12B8 A12B12]  |   A13] [A13B1 A13B5 A13B9 A13B13]\\n                                         |\\n                 Acol2 ⊗ Brow2           |            Acol3 ⊗ Brow3\\n                 -------------           |            -------------\\n                                         |\\n             [B2, B6, B10, B14]          |        [B3 B7 B11 B15]\\n                                         |\\n       [A2   [ A2B2  A2B6  A2B10  A2B14] |  [A3   [ A3B3  A3B7  A3B11  A3B15]\\n        A6   [ A6B2  A6B6  A6B10  A6B14] |   A7   [ A7B3  A7B7  A7B11  A7B15]\\n        A10  [A10B2 A10B6 A10B10 A10B14] |   A11  [A11B3 A11B7 A11B11 A11B15]\\n        A14] [A14B2 A14B6 A14B10 A14B14] |   A15] [A15B3 A15B7 A15B11 A15B15]\\n                                         |\\n\\n    ----------------------------------------------------------------------------\\n\\n                              sum of 4 outer products\\n\\n           Acol0 ⊗ Brow0 + Acol1 ⊗ Brow1 + Acol2 ⊗ Brow2 + Acol3 ⊗ Brow3\\n\\n     [ A0B0 +  A1B1 +  A2B2 +  A3B3 ... ...  A0B12 +  A1B13 +  A2B14 +  A3B15]\\n     [ A4B0 +  A5B1 +  A6B2 +  A7B3 ... ...  A4B12 +  A5B13 +  A6B14 +  A7B15]\\n     [ A8B0 +  A9B1 + A10B2 + A11B3 ... ...  A8B12 +  A9B13 + A10B14 + A11B15]\\n     [A12B0 + A13B1 + A14B2 + A15B3 ... ... A12B12 + A13B13 + A14B14 + A15B15]\\n\\n    ----------------------------------------------------------------------------\\n    ```\\n\\n    This operation enables the folding of 4 outer products chained via the\\n    accumulator into a single outer product.\\n\\n    For example:\\n\\n    ```mlir\\n    %a0_ext = arith.extsi %a0 : vector<[4]xi8> to vector<[4]xi32>\\n    %b0_ext = arith.extsi %b0 : vector<[4]xi8> to vector<[4]xi32>\\n\\n    %a1_ext = arith.extsi %a1 : vector<[4]xi8> to vector<[4]xi32>\\n    %b1_ext = arith.extsi %b1 : vector<[4]xi8> to vector<[4]xi32>\\n\\n    %a2_ext = arith.extsi %a2 : vector<[4]xi8> to vector<[4]xi32>\\n    %b2_ext = arith.extsi %b2 : vector<[4]xi8> to vector<[4]xi32>\\n\\n    %a3_ext = arith.extsi %a3 : vector<[4]xi8> to vector<[4]xi32>\\n    %b3_ext = arith.extsi %b3 : vector<[4]xi8> to vector<[4]xi32>\\n\\n    %0 = arm_sme.outerproduct %a0_ext, %b0_ext : vector<[4]xi32>, vector<[4]xi32>\\n    %1 = arm_sme.outerproduct %a1_ext, %b1_ext acc(%0) : vector<[4]xi32>, vector<[4]xi32>\\n    %2 = arm_sme.outerproduct %a2_ext, %b2_ext acc(%1) : vector<[4]xi32>, vector<[4]xi32>\\n    %3 = arm_sme.outerproduct %a3_ext, %b3_ext acc(%2) : vector<[4]xi32>, vector<[4]xi32>\\n    ```\\n\\n    The 4 outer products in the example above can be fused into a single outer\\n    product as follows:\\n\\n    ```mlir\\n    %lhs0 = vector.interleave %a0, %a2 : vector<[4]xi8> -> vector<[8]xi8>\\n    %lhs1 = vector.interleave %a1, %a3 : vector<[4]xi8> -> vector<[8]xi8>\\n    %lhs = vector.interleave %lhs0, %lhs1 : vector<[8]xi8> -> vector<[16]xi8>\\n\\n    %rhs0 = vector.interleave %b0, %b2 : vector<[4]xi8> -> vector<[8]xi8>\\n    %rhs1 = vector.interleave %b1, %b3 : vector<[4]xi8> -> vector<[8]xi8>\\n    %rhs = vector.interleave %rhs0, %rhs1 : vector<[8]xi8> -> vector<[16]xi8>\\n\\n    %0 = arm_sme.smopa_4way %lhs, %rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    This is implemented in the `-arm-sme-outer-product-fusion` pass.\\n\\n    Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.smopa_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.smopa_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [SMOPA (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/SMOPA--4-way---Signed-integer-sum-of-outer-products-and-accumulate-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.smops_2way\",\n    \"summary\": \"Signed integer sum of 2 outer products and subtract\",\n    \"description\": \"Example:\\n    ```mlir\\n    %result = arm_sme.smops_2way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Refer to\\n    [fmopa_2way](#arm_smefmopa_2way-arm_smefmopa2wayop) for a detailed\\n    description of 2-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [SMOPS (2-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/SMOPS--2-way---Signed-integer-sum-of-outer-products-and-subtract-) | +sme2 |\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.smops_4way\",\n    \"summary\": \"Signed integer sum of 4 outer products and subtract\",\n    \"description\": \"Equivalent to `smopa_4way` but outer products are subtracted from\\n    destination `result`.\\n\\n    Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.smops_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.smops_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [SMOPS (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/SMOPS--4-way---Signed-integer-sum-of-outer-products-and-subtract-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.store_tile_slice\",\n    \"summary\": \"Tile slice store operation\",\n    \"description\": \"Stores a 1D tile slice from a 2D SME \\\"virtual tile\\\" into memory. The tile\\n    slice is defined by the dimension of the 2D scalable vector type pointed by\\n    the index. A tile slice index describes where in the input tile the tile\\n    slice is stored from. An optional tile slice layout attribute specifies\\n    whether the tile slice being stored from the given index is horizontal\\n    (default) or vertical.\\n\\n    The slice of memory written is defined by a base and indices and must be\\n    contiguous. The memref must be either rank 1 or rank 2, have dynamic\\n    dimensions since the operation is scalable, and the element type must be a\\n    scalar that matches the element type of the input tile.\\n\\n    The provided `mask` is used to specify which elements of the tile slice\\n    will be stored.\\n\\n    Example 1: Store vector<[16]xi8> horizontal (default) tile slice from tile at given index to memory.\\n    ```mlir\\n    arm_sme.store_tile_slice %tile, %tile_slice_index, %mask, %base[%c0] : vector<[16]x[16]xi8>, vector<[16]xi1>, memref<?x?xi8>\\n    ```\\n\\n    Example 2: Store vector<[4]xf32> vertical tile slice from tile at given index to memory.\\n    ```mlir\\n    arm_sme.store_tile_slice %tile, %tile_slice_index, %mask, %base[%c0] layout<vertical> : vector<[4]x[4]xf32>, vector<[4]xi1>, memref<?x?xf32>\\n    ```\\n\\n    Example 3: Store a vector<[1]xi128> vertical tile slice from tile at given index to memory.\\n    ```mlir\\n    arm_sme.store_tile_slice %tile, %tile_slice_index, %mask, %base[%c0] layout<vertical> : vector<[1]x[1]xi128>, vector<[1]xi1>, memref<?x?xi128>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tile\", \"type\": \"SMETile\" },\n      { \"name\": \"tile_slice_index\", \"type\": \"Index\" },\n      { \"name\": \"mask\", \"type\": \"SVEPredicate\" },\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"ArmSME_TileSliceLayoutAttr{horizontal|vertical}\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tile_slice_index `,` $mask `,` $base `[` $indices `]` (`layout` `` $layout^)?\\n      attr-dict `:` type($base) `,` type($mask) `,` type($tile)\"\n  },\n  {\n    \"name\": \"arm_sme.streaming_vl\",\n    \"summary\": \"Query the streaming vector length\",\n    \"description\": \"This operation returns the streaming vector length (SVL) for a given type\\n    size. Unlike `vector.vscale` the value returned is invariant to the\\n    streaming mode.\\n\\n    Example:\\n    ```mlir\\n    // Streaming vector length in:\\n    // - bytes (8-bit, SVL.B)\\n    %svl_b = arm_sme.streaming_vl <byte>\\n    // - half words (16-bit, SVL.H)\\n    %svl_h = arm_sme.streaming_vl <half>\\n    // - words (32-bit, SVL.W)\\n    %svl_w = arm_sme.streaming_vl <word>\\n    // - double words (64-bit, SVL.D)\\n    %svl_d = arm_sme.streaming_vl <double>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type_size\", \"type\": \"ArmSME_TypeSizeAttr{byte|half|word|double}\" }\n    ],\n    \"assemblyFormat\": \"$type_size attr-dict\"\n  },\n  {\n    \"name\": \"arm_sme.sumopa_4way\",\n    \"summary\": \"Signed by unsigned integer sum of 4 outer products and accumulate\",\n    \"description\": \"Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.sumopa_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.sumopa_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [SUMOPA (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/SUMOPA--Signed-by-unsigned-integer-sum-of-outer-products-and-accumulate-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.sumops_4way\",\n    \"summary\": \"Signed by unsigned integer sum of 4 outer products and subtract\",\n    \"description\": \"Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.sumops_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.sumops_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [SUMOPS (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/SUMOPS--Signed-by-unsigned-integer-sum-of-outer-products-and-subtract-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.tile_load\",\n    \"summary\": \"Tile load operation\",\n    \"description\": \"Loads a 2D SME \\\"virtual tile\\\" from memory defined by a base and indices,\\n    with the shape defined by the 2D scalable vector type of the result tile.\\n    An optional tile slice layout attribute specifies whether the slices of the\\n    tile being loaded are horizontal (default) or vertical. The slice of memory\\n    must be contiguous. The memref must be either rank 1 or rank 2 with dynamic\\n    dimensions, since the operation is scalable, and the element type must be a\\n    scalar that matches the element type of the result.\\n\\n    An optional SSA value `padding` of the same elemental type as the MemRef is\\n    provided to specify a fallback value in the case of masking.\\n\\n    An optional SSA value `mask` may be specified to mask out elements read\\n    from the MemRef. The `mask` type is an `i1` vector with a shape that\\n    matches how elements are read from the MemRef. Elements whose corresponding\\n    mask element is `0` are masked out and replaced with `padding`.\\n\\n    If either `padding` or `mask` are specified, both must be specified.\\n\\n    Example 1: Load an 8-bit element ZA tile with horizontal layout (default) from memory (ZA0.B).\\n    ```mlir\\n    %tile = arm_sme.tile_load %base[%c0, %c0] : memref<?x?xi8>, vector<[16]x[16]xi8>\\n    ```\\n\\n    Example 2: Load a FP 32-bit element ZA tile with vertical layout from memory.\\n    ```mlir\\n    %tile = arm_sme.tile_load %base[%c0, %c0] layout<vertical> : memref<?x?xf32>, vector<[4]x[4]xf32>\\n    ```\\n\\n    Example 3: Load a 128-bit element ZA tile with horizontal layout (default) from memory.\\n    ```mlir\\n    %tile = arm_sme.tile_load %base[%c0, %c0] layout<horizontal> : memref<?x?xi128>, vector<[1]x[1]xi128>\\n    ```\\n\\n    Example 4: Masked load of int 32-bit element ZA tile with horizontal layout (default) from memory.\\n    ```mlir\\n    %tile = arm_sme.tile_load %base[%c0, %c0], %pad, %mask : memref<?x?xf32>, vector<[4]x[4]xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"MemRefRankOf<[ AnyType ], [ 2 ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"padding\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SMETile\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"ArmSME_TileSliceLayoutAttr{horizontal|vertical}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'result', 'padding', '::llvm::cast<VectorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` (`,` $padding `,` $mask^)? (`layout` `` $layout^)?attr-dict `:` type($base) `,` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.tile_store\",\n    \"summary\": \"Tile store operation\",\n    \"description\": \"Stores a 2D SME \\\"virtual tile\\\" to memory defined by a base and indices,\\n    with the shape defined by the 2D scalable vector type of the tile being\\n    stored. An optional tile slice layout attribute specifies whether the\\n    slices of the tile being stored are horizontal (default) or vertical. The\\n    slice of memory must be contiguous. The memref must be either rank 1 or\\n    rank 2 with dynamic dimensions, since the operation is scalable, and the\\n    element type must be a scalar that matches the element type of the result.\\n\\n    An optional `mask` may be provided, the shape of which corresponds to the\\n    `tile`, and selects which elements of the tile will be stored.\\n\\n    Example 1: Store an 8-bit element ZA tile with horizontal (default) layout to memory (ZA0.B).\\n    ```mlir\\n    arm_sme.tile_store %tile, %base[%c0, %c0] : vector<[16]x[16]xi8>, memref<?x?xi8>\\n    ```\\n\\n    Example 2: Store a FP 32-bit element ZA tile with vertical layout to memory.\\n    ```mlir\\n    arm_sme.tile_store %tile, %base[%c0, %c0] layout<vertical> : vector<[4]x[4]xf32>, memref<?x?xf32>\\n    ```\\n\\n    Example 3: Store a 128-bit element ZA tile with horizontal (default) layout to memory.\\n    ```mlir\\n    arm_sme.tile_store %tile, %base[%c0, %c0] layout<horizontal> : vector<[1]x[1]xi128>, memref<?x?xi128>\\n    ```\\n\\n    Example 4: Masked store a int 32-bit element ZA tile with vertical layout to memory.\\n    ```mlir\\n    arm_sme.tile_store %tile, %base[%c0, %c0], %mask layout<vertical> : vector<[4]x[4]xf32>, memref<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueToStore\", \"type\": \"SMETile\" },\n      { \"name\": \"base\", \"type\": \"MemRefRankOf<[ AnyType ], [ 2 ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"ArmSME_TileSliceLayoutAttr{horizontal|vertical}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$valueToStore `,` $base `[` $indices `]` (`,` $mask^)? (`layout` `` $layout^)?attr-dict `:` type($base) `,` type($valueToStore)\"\n  },\n  {\n    \"name\": \"arm_sme.umopa_2way\",\n    \"summary\": \"Unsiged integer sum of 2 outer products and accumulate\",\n    \"description\": \"Example:\\n    ```mlir\\n    %result = arm_sme.umopa_2way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Refer to\\n    [fmopa_2way](#arm_smefmopa_2way-arm_smefmopa2wayop) for a detailed\\n    description of 2-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [UMOPA (2-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/UMOPA--2-way---Unsigned-integer-sum-of-outer-products-and-accumulate-) | +sme2 |\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.umopa_4way\",\n    \"summary\": \"Unsigned integer sum of 4 outer products and accumulate\",\n    \"description\": \"Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.umopa_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.umopa_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [UMOPA (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/UMOPA--4-way---Unsigned-integer-sum-of-outer-products-and-accumulate-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.umops_2way\",\n    \"summary\": \"Unsiged integer sum of 2 outer products and subtract\",\n    \"description\": \"Example:\\n    ```mlir\\n    %result = arm_sme.umops_2way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Refer to\\n    [fmopa_2way](#arm_smefmopa_2way-arm_smefmopa2wayop) for a detailed\\n    description of 2-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [UMOPS (2-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/UMOPS--2-way---Unsigned-integer-sum-of-outer-products-and-subtract-) | +sme2 |\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.umops_4way\",\n    \"summary\": \"Unsigned integer sum of 4 outer products and subtract\",\n    \"description\": \"Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.umops_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.umops_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [UMOPS (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/UMOPS--4-way---Unsigned-integer-sum-of-outer-products-and-subtract-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.usmopa_4way\",\n    \"summary\": \"Unsigned by signed integer sum of 4 outer products and accumulate\",\n    \"description\": \"Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.usmopa_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.usmopa_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [USMOPA (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/USMOPA--Unsigned-by-signed-integer-sum-of-outer-products-and-accumulate-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.usmops_4way\",\n    \"summary\": \"Unsigned by signed integer sum of 4 outer products and subtract\",\n    \"description\": \"Example: I8 to I32\\n    ```mlir\\n    %result = arm_sme.usmops_4way $lhs, $rhs : vector<[16]xi8>, vector<[16]xi8> into vector<[4]x[4]xi32>\\n    ```\\n\\n    Example: I16 to I64\\n    ```mlir\\n    %result = arm_sme.usmops_4way $lhs, $rhs : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64>\\n    ```\\n\\n    Refer to [smopa_4way](#arm_smesmopa_4way-arm_smesmopa4wayop) for a\\n    detailed description of 4-way outer products.\\n\\n    | Spec | Features |\\n    | ---- | -------- |\\n    | [USMOPS (4-way)](https://developer.arm.com/documentation/ddi0602/2023-09/SME-Instructions/USMOPS--Unsigned-by-signed-integer-sum-of-outer-products-and-subtract-) | +sme (32-bit), +sme-i16i64 (64-bit)|\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[ScalableVectorOfRankAndLengthAndType<[1], [16], [I8]>, ScalableVectorOfRankAndLengthAndType<[1], [8], [I16]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"lhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"rhsMask\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRank>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[nxnxv4i32, nxnxv2i64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs\\n    oilist(\\n        `acc` `` `(` $acc `)`\\n      | `masks` `` `(` $lhsMask `,` $rhsMask `)`\\n    ) attr-dict `:` type($lhs) `,` type($rhs) `into` type($result)\"\n  },\n  {\n    \"name\": \"arm_sme.zero\",\n    \"summary\": \"Creates a zero-initialized value of SME virtual tile type\",\n    \"description\": \"Creates a new SME \\\"virtual tile\\\" value within a function. The contents of\\n    the tile returned from this operation are zero-initialized.\\n\\n    Example 1: Zero an 8-bit element ZA tile.\\n\\n    ```mlir\\n    %0 = arm_sme.zero : vector<[16]x[16]xi8>\\n    ```\\n\\n    Example 2: Zero a 64-bit element ZA tile.\\n\\n    ```mlir\\n    %0 = arm_sme.zero : vector<[2]x[2]xi64>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"SMETile\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.convert_from_svbool\",\n    \"summary\": \"Convert a svbool type to a SVE predicate type\",\n    \"description\": \"Converts svbool types (`vector<[16]xi1>` or vectors of that type, e.g.\\n    `vector<2x3x[16]xi1>`) to SVE predicate types. Note: Only the trailing\\n    dimension can be scalable.\\n\\n    Example 1: Convert a 1-D svbool mask to a SVE predicate.\\n    ```mlir\\n    %source = vector.load %memref[%c0] : memref<?xi1>, vector<[16]xi1>\\n    %result = arm_sve.convert_from_svbool %source : vector<[4]xi1>\\n    ```\\n\\n    Example 2: Convert a 2-D svbool mask to a mask of SVE predicates.\\n    ```mlir\\n    %source = vector.load %memref[%c0, %c0] : memref<2x?xi1>, vector<2x[16]xi1>\\n    %result = arm_sve.convert_from_svbool %source : vector<2x[8]xi1>\\n    ```\\n\\n    ---\\n\\n    A `svbool` is the smallest SVE predicate type that has a in-memory\\n    representation (and maps to a full predicate register). In MLIR `svbool` is\\n    represented as `vector<[16]xi1>`. Smaller SVE predicate types\\n    (`vector<[1|2|4|8]xi1>`) must be stored as a `svbool` then converted back to\\n    the original predicate type after loading.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"SVBoolMask\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SVEPredicateMask\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'source', 'VectorType(VectorType::Builder(::llvm::cast<VectorType>($_self)).setDim(::llvm::cast<VectorType>($_self).getRank() - 1, 16))'>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"arm_sve.convert_to_svbool\",\n    \"summary\": \"Convert a SVE predicate type to a svbool type\",\n    \"description\": \"Converts SVE predicate types (or vectors of predicate types, e.g.\\n    `vector<4x[4]xi1>`) to svbool types. Note: Only the trailing dimension can\\n    be scalable.\\n\\n    Example 1: Convert a 1-D SVE predicate to a svbool mask.\\n    ```mlir\\n    %source = vector.create_mask %dim_size : vector<[4]xi1>\\n    %result = arm_sve.convert_to_svbool %source : vector<[4]xi1>\\n    // => Results in vector<[16]xi1>\\n    ```\\n\\n    Example 2: Convert a 2-D mask of SVE predicates to a svbool mask.\\n    ```mlir\\n    %source = vector.create_mask %c2, %dim_size : vector<2x[2]xi1>\\n    %result = arm_sve.convert_to_svbool %source : vector<2x[2]xi1>\\n    // => Results in vector<2x[16]xi1>\\n    ```\\n\\n    ---\\n\\n    A `svbool` is the smallest SVE predicate type that has a in-memory\\n    representation (and maps to a full predicate register). In MLIR `svbool` is\\n    represented as `vector<[16]xi1>`. Smaller SVE predicate types\\n    (`vector<[1|2|4|8]xi1>`) must be converted to a `svbool` before they can be\\n    stored.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"SVEPredicateMask\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SVBoolMask\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'source', 'result', 'VectorType(VectorType::Builder(::llvm::cast<VectorType>($_self)).setDim(::llvm::cast<VectorType>($_self).getRank() - 1, 16))'>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source)\"\n  },\n  {\n    \"name\": \"arm_sve.dupq_lane\",\n    \"summary\": \"Broadcast indexed 128-bit segment to vector\",\n    \"description\": \"This operation fills each 128-bit segment of a vector with the elements\\n    from the indexed 128-bit segment of the source vector. If the VL is\\n    128 bits the operation is a NOP. If the index exceeds the number of\\n    128-bit segments in a vector the result is an all-zeroes vector.\\n\\n    Example:\\n    ```mlir\\n    // VL == 256\\n    // %X = [A B C D x x x x]\\n    %Y = arm_sve.dupq_lane %X[0] : vector<[4]xi32>\\n    // Y = [A B C D A B C D]\\n\\n    // %U = [x x x x x x x x A B C D E F G H]\\n    %V = arm_sve.dupq_lane %U[1] : vector<[8]xf16>\\n    // %V = [A B C D E F H A B C D E F H]\\n    ```\\n\\n    Note: The semantics of the operation match those of the `svdupq_lane` intrinsics.\\n    [Source](https://developer.arm.com/architectures/instruction-sets/intrinsics/#q=svdupq_lane)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"SVEVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"SVEVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lane\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'dst']>\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $lane `]` attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"arm_sve.intr.add\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.bfmmla\",\n    \"summary\": \"BFloat16 matrix multiply-accumulate\",\n    \"description\": \"BFMMLA: BFloat16 matrix multiply-accumulate into 2×2 matrices\\\";\\n\\n    This operation multiplies the 2x4 BFloat16 matrix held in each 128-bit\\n    segment of the first source vector by the 4x2 BFloat16 matrix in the\\n    corresponding segment of the second source vector, then accumulates\\n    this intermediate result with the 2x2 Float32 matrix in the corresponding\\n    segment of the accumulator vector, yielding the final 2x2 Float32\\n    segment of the result.\\n\\n    Source:\\n    https://developer.arm.com/documentation/100987/0000\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"ScalableVectorOfLengthAndType<[4], [F32]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfLengthAndType<[8], [BF16]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfLengthAndType<[8], [BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfLengthAndType<[4], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.intr.convert.from.svbool\",\n    \"operands\": [\n      { \"name\": \"svbool\", \"type\": \"SVBool\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.convert.to.svbool\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"SVEPredicate\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.dupq_lane\",\n    \"operands\": [\n      { \"name\": \"v\", \"type\": \"ScalableVectorOfRank<[ 1 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lane\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.fadd\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.fdiv\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.fmul\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.fsub\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.mul\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.psel\",\n    \"operands\": [\n      { \"name\": \"p1\", \"type\": \"SVBool\" },\n      { \"name\": \"p2\", \"type\": \"SVEPredicate\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.sdiv\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.sdot\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.smmla\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.sub\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.udiv\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.udot\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.ummla\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.usmmla\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.whilelt\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"I64\" },\n      { \"name\": \"n\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.zip.x2\",\n    \"operands\": [\n      { \"name\": \"v1\", \"type\": \"AnyScalableVectorOfAnyRank\" },\n      { \"name\": \"v2\", \"type\": \"AnyScalableVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.intr.zip.x4\",\n    \"operands\": [\n      { \"name\": \"v1\", \"type\": \"AnyScalableVectorOfAnyRank\" },\n      { \"name\": \"v2\", \"type\": \"AnyScalableVectorOfAnyRank\" },\n      { \"name\": \"v3\", \"type\": \"AnyScalableVectorOfAnyRank\" },\n      { \"name\": \"v4\", \"type\": \"AnyScalableVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"arm_sve.masked.addf\",\n    \"summary\": \"masked addition for scalable vectors of floats\",\n    \"description\": \"The `arm_sve.masked.addf` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform floating pointadditionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.addi\",\n    \"summary\": \"masked addition for scalable vectors of integers\",\n    \"description\": \"The `arm_sve.masked.addi` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform integeradditionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.divf\",\n    \"summary\": \"masked division for scalable vectors of floats\",\n    \"description\": \"The `arm_sve.masked.divf` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform floating pointdivisionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.divi_signed\",\n    \"summary\": \"masked signed division for scalable vectors of integers\",\n    \"description\": \"The `arm_sve.masked.divi_signed` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform integersigned divisionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.divi_unsigned\",\n    \"summary\": \"masked unsigned division for scalable vectors of integers\",\n    \"description\": \"The `arm_sve.masked.divi_unsigned` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform integerunsigned divisionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.mulf\",\n    \"summary\": \"masked multiplication for scalable vectors of floats\",\n    \"description\": \"The `arm_sve.masked.mulf` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform floating pointmultiplicationon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.muli\",\n    \"summary\": \"masked multiplication for scalable vectors of integers\",\n    \"description\": \"The `arm_sve.masked.muli` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform integermultiplicationon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.subf\",\n    \"summary\": \"masked subtraction for scalable vectors of floats\",\n    \"description\": \"The `arm_sve.masked.subf` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform floating pointsubtractionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[AnyFloat]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.masked.subi\",\n    \"summary\": \"masked subtraction for scalable vectors of integers\",\n    \"description\": \"The `arm_sve.masked.subi` operation takes one scalable vector mask\\n    and two scalable vector operands, and perform integersubtractionon active lanes. Inactive lanes will keep the value of\\n    the first operand.\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"ScalableVectorOfAnyRank<[I1]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ScalableVectorOfAnyRank<[I8, I16, I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2', 'res']>\" },\n      { \"type\": \"TypesMatchWith<'src1', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $src1 `,` $src2 attr-dict `:` type($mask) `,` type($res)\"\n  },\n  {\n    \"name\": \"arm_sve.psel\",\n    \"summary\": \"Predicate select\",\n    \"description\": \"This operation returns the input predicate `p1` or an all-false predicate\\n    based on the bit at `p2[index]`. Informally, the semantics are:\\n    ```\\n    if p2[index % num_elements(p2)] == 1:\\n      return p1 : type(p1)\\n    return all-false : type(p1)\\n    ```\\n\\n    Example:\\n    ```mlir\\n    // Note: p1 and p2 can have different sizes.\\n    %pd = arm_sve.psel %p1, %p2[%index] : vector<[4]xi1>, vector<[8]xi1>\\n    ```\\n\\n    Note: This requires SME or SVE2.1 (`+sme` or `+sve2p1` in LLVM target features).\",\n    \"operands\": [\n      { \"name\": \"p1\", \"type\": \"SVEPredicate\" },\n      { \"name\": \"p2\", \"type\": \"SVEPredicate\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SVEPredicate\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['p1', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$p1 `,` $p2 `[` $index `]` attr-dict `:` type($p1) `,` type($p2)\"\n  },\n  {\n    \"name\": \"arm_sve.sdot\",\n    \"summary\": \"Vector-vector dot product and accumulate op\",\n    \"description\": \"SDOT: Signed integer addition of dot product.\\n\\n    This function maps to the SDOT instruction, and it takes signless integer\\n    operands that the operation interprets as signed. It partitions the second\\n    and third vector inputs into groups of four elements. They calculate the dot\\n    product of each group (without loss of precision) and then add each result\\n    to the overlapping element of the first vector input.\\n\\n    Source:\\n    https://developer.arm.com/documentation/100987/0000\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"ScalableVectorOfLengthAndType<[4, 2], [I32, I64]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfLengthAndType<[16, 8], [I8, I16]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfLengthAndType<[16, 8], [I8, I16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"ScalableVectorOfLengthAndType<[4, 2], [I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'dst']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($dst)\"\n  },\n  {\n    \"name\": \"arm_sve.smmla\",\n    \"summary\": \"Matrix-matrix multiply and accumulate op\",\n    \"description\": \"SMMLA: Signed integer matrix multiply-accumulate.\\n\\n    This function maps to the SMMLA instruction, and it takes signless integer\\n    operands that the operation interprets as signed. It partitions the inputs\\n    into 128-bit quadwords, with the first input containing a row-by-row 2×2\\n    matrix of 32-bit integers, the second input containing a row-by-row 2×8\\n    matrix of 8-bit integers, and the third input containing a column-by-column\\n    8×2 matrix of 8-bit integers. For each quadword, they multiply the second\\n    input matrix by the third input matrix using natural arithmetic and then add\\n    the result to the first input using modular arithmetic.\\n\\n    Source:\\n    https://developer.arm.com/documentation/100987/0000\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"ScalableVectorOfLengthAndType<[4], [I32]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfLengthAndType<[16], [I8]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfLengthAndType<[16], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"ScalableVectorOfLengthAndType<[4], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'dst']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($dst)\"\n  },\n  {\n    \"name\": \"arm_sve.udot\",\n    \"summary\": \"Vector-vector dot product and accumulate op\",\n    \"description\": \"UDOT: Unsigned integer addition of dot product.\\n\\n    This function maps to the UDOT instruction, and it takes signless integer\\n    operands that the operation interprets as unsigned. It partitions the second\\n    and third vector inputs into groups of four elements. They calculate the dot\\n    product of each group (without loss of precision) and then add each result\\n    to the overlapping element of the first vector input.\\n\\n    Source:\\n    https://developer.arm.com/documentation/100987/0000\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"ScalableVectorOfLengthAndType<[4, 2], [I32, I64]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfLengthAndType<[16, 8], [I8, I16]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfLengthAndType<[16, 8], [I8, I16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"ScalableVectorOfLengthAndType<[4, 2], [I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'dst']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($dst)\"\n  },\n  {\n    \"name\": \"arm_sve.ummla\",\n    \"summary\": \"Matrix-matrix multiply and accumulate op\",\n    \"description\": \"UMMLA: Unsigned integer matrix multiply-accumulate.\\n\\n    This function maps to the UMMLA instruction, and it takes signless integer\\n    operands that the operation interprets as unsigned. It partitions the inputs\\n    into 128-bit quadwords, with the first input containing a row-by-row 2×2\\n    matrix of 32-bit integers, the second input containing a row-by-row 2×8\\n    matrix of 8-bit integers, and the third input containing a column-by-column\\n    8×2 matrix of 8-bit integers. For each quadword, they multiply the second\\n    input matrix by the third input matrix using natural arithmetic and then add\\n    the result to the first input using modular arithmetic.\\n\\n    Source:\\n    https://developer.arm.com/documentation/100987/0000\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"ScalableVectorOfLengthAndType<[4], [I32]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfLengthAndType<[16], [I8]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfLengthAndType<[16], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"ScalableVectorOfLengthAndType<[4], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'dst']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($dst)\"\n  },\n  {\n    \"name\": \"arm_sve.usmmla\",\n    \"summary\": \"Matrix-matrix multiply and accumulate op\",\n    \"description\": \"USMMLA: Unsigned by signed integer matrix multiply-accumulate.\\n\\n    The unsigned by signed integer matrix multiply-accumulate operation\\n    multiplies the 2×8 matrix of unsigned 8-bit integer values held\\n    the first source vector by the 8×2 matrix of signed 8-bit integer\\n    values in the second source vector. The resulting 2×2 widened 32-bit\\n    integer matrix product is then added to the 32-bit integer matrix\\n    accumulator.\\n\\n    Source:\\n    https://developer.arm.com/documentation/100987/0000\",\n    \"operands\": [\n      { \"name\": \"acc\", \"type\": \"ScalableVectorOfLengthAndType<[4], [I32]>\" },\n      { \"name\": \"src1\", \"type\": \"ScalableVectorOfLengthAndType<[16], [I8]>\" },\n      { \"name\": \"src2\", \"type\": \"ScalableVectorOfLengthAndType<[16], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"ScalableVectorOfLengthAndType<[4], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" },\n      { \"type\": \"AllTypesMatch<['acc', 'dst']>\" }\n    ],\n    \"assemblyFormat\": \"$acc `,` $src1 `,` $src2 attr-dict `:` type($src1) `to` type($dst)\"\n  },\n  {\n    \"name\": \"arm_sve.zip.x2\",\n    \"summary\": \"Multi-vector two-way zip op\",\n    \"description\": \"This operation interleaves elements from two input SVE vectors, returning\\n    two new SVE vectors (`resultV1` and `resultV2`), which contain the low and\\n    high halves of the result respectively.\\n\\n    Example:\\n    ```mlir\\n    // sourceV1 = [ A1, A2, A3, ... An ]\\n    // sourceV2 = [ B1, B2, B3, ... Bn ]\\n    // (resultV1, resultV2) = [ A1, B1, A2, B2, A3, B3, ... An, Bn ]\\n    %resultV1, %resultV2 = arm_sve.zip.x2 %sourceV1, %sourceV2 : vector<[16]xi8>\\n    ```\\n\\n    Note: This requires SME 2 (`+sme2` in LLVM target features)\\n\\n    [Source](https://developer.arm.com/documentation/ddi0602/2023-12/SME-Instructions/ZIP--two-registers---Interleave-elements-from-two-vectors-?lang=en)\",\n    \"operands\": [\n      { \"name\": \"sourceV1\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"sourceV2\", \"type\": \"ZipInputVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"resultV1\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"resultV2\", \"type\": \"ZipInputVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['sourceV1', 'sourceV2', 'resultV1', 'resultV2']>\" }\n    ],\n    \"assemblyFormat\": \"$sourceV1 `,` $sourceV2 attr-dict `:` type($sourceV1)\"\n  },\n  {\n    \"name\": \"arm_sve.zip.x4\",\n    \"summary\": \"Multi-vector four-way zip op\",\n    \"description\": \"This operation interleaves elements from four input SVE vectors, returning\\n    four new SVE vectors, each of which contain a quarter of the result. The\\n    first quarter will be in `resultV1`, second in `resultV2`, third in\\n    `resultV3`, and fourth in `resultV4`.\\n\\n    ```mlir\\n    // sourceV1 = [ A1, A2, ... An ]\\n    // sourceV2 = [ B1, B2, ... Bn ]\\n    // sourceV3 = [ C1, C2, ... Cn ]\\n    // sourceV4 = [ D1, D2, ... Dn ]\\n    // (resultV1, resultV2, resultV3, resultV4)\\n    //   = [ A1, B1, C1, D1, A2, B2, C2, D2, ... An, Bn, Cn, Dn ]\\n    %resultV1, %resultV2, %resultV3, %resultV4 = arm_sve.zip.x4\\n      %sourceV1, %sourceV2, %sourceV3, %sourceV4 : vector<[16]xi8>\\n    ```\\n\\n    **Warning:** The result of this op is undefined for 64-bit elements on\\n    hardware with less than 256-bit vectors!\\n\\n    Note: This requires SME 2 (`+sme2` in LLVM target features)\\n\\n    [Source](https://developer.arm.com/documentation/ddi0602/2023-12/SME-Instructions/ZIP--four-registers---Interleave-elements-from-four-vectors-?lang=en)\",\n    \"operands\": [\n      { \"name\": \"sourceV1\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"sourceV2\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"sourceV3\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"sourceV4\", \"type\": \"ZipInputVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"resultV1\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"resultV2\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"resultV3\", \"type\": \"ZipInputVectorType\" },\n      { \"name\": \"resultV4\", \"type\": \"ZipInputVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['sourceV1', 'sourceV2', 'sourceV3', 'sourceV4', 'resultV1', 'resultV2', 'resultV3', 'resultV4']>\" }\n    ],\n    \"assemblyFormat\": \"$sourceV1 `,` $sourceV2 `,` $sourceV3 `,` $sourceV4 attr-dict\\n      `:` type($sourceV1)\"\n  },\n  {\n    \"name\": \"asuka.abs\",\n    \"summary\": \"abs\",\n    \"description\": \"abs\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.add\",\n    \"summary\": \"add\",\n    \"description\": \"add\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.avg_pool\",\n    \"summary\": \"asuka avgpool\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_size\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"count_include_pad\", \"type\": \"BoolAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `kernel_size` `=` $kernel_size `,` `stride` `=` $stride `,` `padding` `=` $padding `,` `ceil_mode` `=` $ceil_mode `,` `count_include_pad` `=` $count_include_pad attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.block_for\",\n    \"summary\": \"block for\",\n    \"operands\": [\n      { \"name\": \"block_args\", \"type\": \"Variadic<AS_AnyTensor>\" },\n      { \"name\": \"init_args\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower_bound\", \"type\": \"IndexAttr\" },\n      { \"name\": \"upper_bound\", \"type\": \"IndexAttr\" },\n      { \"name\": \"step\", \"type\": \"IndexAttr\" },\n      { \"name\": \"block_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`lb` `=` $lower_bound `,` `ub` `=` $upper_bound `,` `step` `=` $step `,` `args` `=` `[` $block_args `]` `,` `dims` `=` $block_dims `,` `init` `=` `[` $init_args `]` $region attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.block_yield\",\n    \"summary\": \"block yield in block for op\",\n    \"operands\": [\n      { \"name\": \"block_outs\", \"type\": \"Variadic<AS_AnyTensor>\" },\n      { \"name\": \"iter_outs\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`block_outs` `=` `[` $block_outs `]` `,` `iter_outs` `=` `[` $iter_outs `]` attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"asuka.call\",\n    \"summary\": \"call\",\n    \"description\": \"call\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"asuka.cmp\",\n    \"summary\": \"cmp\",\n    \"description\": \"cmp\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cmp_type\", \"type\": \"Asuka_CmpTypeAttr{GT|GE}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$cmp_type $lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.convert\",\n    \"summary\": \"convert\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_TypedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_TypedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dst_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `type` `=` $dst_type attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.div\",\n    \"summary\": \"div\",\n    \"description\": \"div\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.dot\",\n    \"summary\": \"asuka dot\",\n    \"description\": \"dot op\\n    for lhs: [x.., m, k]\\n    for rhs: [y.., k, n]\\n    k is reduce dim, x.. and y.. are batch dim\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.dynamic_block_for\",\n    \"summary\": \"block for\",\n    \"operands\": [\n      { \"name\": \"lower_bound\", \"type\": \"Index\" },\n      { \"name\": \"upper_bound\", \"type\": \"Index\" },\n      { \"name\": \"block_args\", \"type\": \"Variadic<AS_AnyTensor>\" },\n      { \"name\": \"init_args\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"step\", \"type\": \"IndexAttr\" },\n      { \"name\": \"block_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`lb` `=` $lower_bound `,` `ub` `=` $upper_bound `,` `step` `=` $step `,` `args` `=` `[` $block_args `]` `,` `dims` `=` $block_dims `,` `init` `=` `[` $init_args `]` $region attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.erase_type\",\n    \"summary\": \"erase type\",\n    \"description\": \"erase type\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AS_ShapedOnlyTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.exp\",\n    \"summary\": \"exp\",\n    \"description\": \"exp\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.exp2\",\n    \"summary\": \"exp2\",\n    \"description\": \"exp2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.kernel\",\n    \"summary\": \"asuka kernel\",\n    \"description\": \"kernel\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"asuka.log\",\n    \"summary\": \"log\",\n    \"description\": \"log\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.log2\",\n    \"summary\": \"log2\",\n    \"description\": \"log2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.mask\",\n    \"operands\": [\n      { \"name\": \"starts\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"element_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`starts` `=` `[` $starts `]` `,` `sizes` `=` $sizes `,` `type` `=` $element_type $region attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.mask_yield\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<AS_FloatIntLike>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcs `:` type($srcs)\"\n  },\n  {\n    \"name\": \"asuka.mul\",\n    \"summary\": \"mul\",\n    \"description\": \"mul\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.neg\",\n    \"summary\": \"neg\",\n    \"description\": \"neg\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.normalize\",\n    \"summary\": \"asuka normalize\",\n    \"description\": \"normalize\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"lp\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dim` `=` $reduce_dimension `,` `Lp` `=` $lp attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.parallel_for\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$inputs $region attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.parallel_yield\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcs `:` type($srcs)\"\n  },\n  {\n    \"name\": \"asuka.permute\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dims` `=` $dims attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.pow\",\n    \"summary\": \"pow\",\n    \"description\": \"pow\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.precise_dot_op\",\n    \"summary\": \"Dot operation with output precision at least as high as input precision\",\n    \"description\": \"This operation performs a dot product on two input tensors with the same element type,\\n    and ensures the output tensor has a precision (element type) that is at least as high as the inputs.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"acc_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `,` `acc` `=` $acc_type attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.reduce\",\n    \"summary\": \"asuka reduce\",\n    \"description\": \"reduce\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"init\", \"type\": \"Optional<AS_AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"reduce_type\", \"type\": \"Asuka_ReduceTypeAttr{ADD|MUL|ANY}\" },\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`(` $operand ( `,` `init` `=` $init^ )? `)` `,` `dim` `=` $reduce_dimension `,` `op` `=` $reduce_type attr-dict `,` `keep_dim` `=` $keep_dim `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.reshape\",\n    \"category\": \"Shape\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.return\",\n    \"summary\": \"return\",\n    \"description\": \"return\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($srcs^ `:` type($srcs))?\"\n  },\n  {\n    \"name\": \"asuka.rng\",\n    \"summary\": \"rng\",\n    \"description\": \"rng\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_distribution\", \"type\": \"Asuka_RngDistributionAttr{UNIT_UNIFORM|UNIT_GUMBEL}\" }\n    ],\n    \"assemblyFormat\": \"`distribution` `=` $rng_distribution attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"asuka.softmax\",\n    \"category\": \"Activation\",\n    \"summary\": \"asuka softmax\",\n    \"description\": \"softmax\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dim` `=` $reduce_dimension attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.specify_type\",\n    \"summary\": \"specify type\",\n    \"description\": \"specify type\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AS_ShapedOnlyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AS_TypedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_types\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$inputs `with` `type` `=` $element_types attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.split\",\n    \"category\": \"Tensor\",\n    \"summary\": \"rng\",\n    \"description\": \"split\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AS_AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dim` `=` $split_dimension attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.sub\",\n    \"summary\": \"sub\",\n    \"description\": \"sub\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AS_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"tanh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.transpose\",\n    \"category\": \"Transform\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dims` `=` $dims attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.trilu\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"diagonal\", \"type\": \"I64Attr\" },\n      { \"name\": \"is_upper\", \"type\": \"BoolAttr\" },\n      { \"name\": \"shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"val\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`diagonal` `=` $diagonal `,` `is_upper` `=` $is_upper `,` `shape` `=` $shape `,` `val` `=` $val attr-dict\"\n  },\n  {\n    \"name\": \"asuka.unsqueeze\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dim` `=` $dim attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.view\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"asuka.zero\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AS_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"element_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`shape` `=` $shape `,` `type` `=` $element_type attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"async.add_to_group\",\n    \"summary\": \"adds an async token or value to the group\",\n    \"description\": \"The `async.add_to_group` adds an async token or value to the async group.\\n    Returns the rank of the added element in the group. This rank is fixed\\n    for the group lifetime.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = async.create_group %size : !async.group\\n    %1 = ... : !async.token\\n    %2 = async.add_to_group %1, %0 : !async.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyValueOrTokenType\" },\n      { \"name\": \"group\", \"type\": \"Async_GroupType\" }\n    ],\n    \"results\": [\n      { \"name\": \"rank\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $group `:` type($operand) attr-dict\"\n  },\n  {\n    \"name\": \"async.await\",\n    \"summary\": \"waits for the argument to become ready\",\n    \"description\": \"The `async.await` operation waits until the argument becomes ready, and for\\n    the `async.value` arguments it unwraps the underlying value\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = ... : !async.token\\n    async.await %0 : !async.token\\n\\n    %1 = ... : !async.value<f32>\\n    %2 = async.await %1 : !async.value<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyValueOrTokenType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` custom<AwaitResultType>(\\n      type($operand), type($result)\\n    ) attr-dict\"\n  },\n  {\n    \"name\": \"async.await_all\",\n    \"summary\": \"waits for the all async tokens or values in the group to become ready\",\n    \"description\": \"The `async.await_all` operation waits until all the tokens or values in the\\n    group become ready.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = async.create_group %size : !async.group\\n\\n    %1 = ... : !async.token\\n    %2 = async.add_to_group %1, %0 : !async.token\\n\\n    %3 = ... : !async.token\\n    %4 = async.add_to_group %2, %0 : !async.token\\n\\n    async.await_all %0\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_GroupType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"async.call\",\n    \"summary\": \"async call operation\",\n    \"description\": \"The `async.call` operation represents a direct call to an async function\\n    that is within the same symbol scope as the call. The operands and result\\n    types of the call must match the specified async function type. The callee\\n    is encoded as a symbol reference attribute named \\\"callee\\\".\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = async.call @my_add(%0, %1) : (f32, f32) -> !async.value<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<Async_AnyValueOrTokenType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"async.coro.begin\",\n    \"summary\": \"returns a handle to the coroutine\",\n    \"description\": \"The `async.coro.begin` allocates a coroutine frame and returns a handle to\\n    the coroutine.\",\n    \"operands\": [\n      { \"name\": \"id\", \"type\": \"Async_CoroIdType\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"Async_CoroHandleType\" }\n    ],\n    \"assemblyFormat\": \"$id attr-dict\"\n  },\n  {\n    \"name\": \"async.coro.end\",\n    \"summary\": \"marks the end of the coroutine in the suspend block\",\n    \"description\": \"The `async.coro.end` marks the point where a coroutine needs to return\\n    control back to the caller if it is not an initial invocation of the\\n    coroutine. It the start part of the coroutine is is no-op.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"Async_CoroHandleType\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict\"\n  },\n  {\n    \"name\": \"async.coro.free\",\n    \"summary\": \"deallocates the coroutine frame\",\n    \"description\": \"The `async.coro.free` deallocates the coroutine frame created by the\\n    async.coro.begin operation.\",\n    \"operands\": [\n      { \"name\": \"id\", \"type\": \"Async_CoroIdType\" },\n      { \"name\": \"handle\", \"type\": \"Async_CoroHandleType\" }\n    ],\n    \"assemblyFormat\": \"$id `,` $handle attr-dict\"\n  },\n  {\n    \"name\": \"async.coro.id\",\n    \"summary\": \"returns a switched-resume coroutine identifier\",\n    \"description\": \"The `async.coro.id` returns a switched-resume coroutine identifier.\",\n    \"results\": [\n      { \"name\": \"id\", \"type\": \"Async_CoroIdType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"async.coro.save\",\n    \"summary\": \"saves the coroutine state\",\n    \"description\": \"The `async.coro.saves` saves the coroutine state.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"Async_CoroHandleType\" }\n    ],\n    \"results\": [\n      { \"name\": \"state\", \"type\": \"Async_CoroStateType\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict\"\n  },\n  {\n    \"name\": \"async.coro.suspend\",\n    \"summary\": \"suspends the coroutine\",\n    \"description\": \"The `async.coro.suspend` suspends the coroutine and transfers control to the\\n    `suspend` successor. If suspended coroutine later resumed it will transfer\\n    control to the `resume` successor. If it is destroyed it will transfer\\n    control to the the `cleanup` successor.\\n\\n    In switched-resume lowering coroutine can be already in resumed state when\\n    suspend operation is called, in this case control will be transferred to the\\n    `resume` successor skipping the `suspend` successor.\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"Async_CoroStateType\" }\n    ],\n    \"successors\": [\n      { \"name\": \"suspendDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"resumeDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cleanupDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$state `,` $suspendDest `,` $resumeDest  `,` $cleanupDest attr-dict\"\n  },\n  {\n    \"name\": \"async.create_group\",\n    \"summary\": \"creates an empty async group\",\n    \"description\": \"The `async.create_group` allocates an empty async group. Async tokens or\\n    values can be added to this group later. The size of the group must be\\n    specified at construction time, and `await_all` operation will first\\n    wait until the number of added tokens or values reaches the group size.\\n\\n    Example:\\n\\n    ```mlir\\n    %size = ... : index\\n    %group = async.create_group %size : !async.group\\n    ...\\n    async.await_all %group\\n    ```\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Async_GroupType\" }\n    ],\n    \"assemblyFormat\": \"$size `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"async.execute\",\n    \"summary\": \"Asynchronous execute operation\",\n    \"description\": \"The `body` region attached to the `async.execute` operation semantically\\n    can be executed concurrently with the successor operation. In the followup\\n    example \\\"compute0\\\" can be executed concurrently with \\\"compute1\\\".\\n\\n    The actual concurrency semantics depends on the dialect lowering to the\\n    executable format. Fully sequential execution (\\\"compute0\\\" completes before\\n    \\\"compute1\\\" starts) is a completely legal execution.\\n\\n    Because concurrent execution is not guaranteed, it is illegal to create an\\n    implicit dependency from \\\"compute1\\\" to \\\"compute0\\\" (e.g. via shared global\\n    state). All dependencies must be made explicit with async execute arguments\\n    (`async.token` or `async.value`).\\n\\n   `async.execute` operation takes `async.token` dependencies and `async.value`\\n    operands separately, and starts execution of the attached body region only\\n    when all tokens and values become ready.\\n\\n    Example:\\n\\n    ```mlir\\n    %dependency = ... : !async.token\\n    %value = ... : !async.value<f32>\\n\\n    %token, %results =\\n      async.execute [%dependency](%value as %unwrapped: !async.value<f32>)\\n                 -> !async.value<!some.type>\\n      {\\n        %0 = \\\"compute0\\\"(%unwrapped): (f32) -> !some.type\\n        async.yield %0 : !some.type\\n      }\\n\\n    %1 = \\\"compute1\\\"(...) : !some.type\\n    ```\\n\\n    In the example above asynchronous execution starts only after dependency\\n    token and value argument become ready. Unwrapped value passed to the\\n    attached body region as an %unwrapped value of f32 type.\",\n    \"operands\": [\n      { \"name\": \"dependencies\", \"type\": \"Variadic<Async_TokenType>\" },\n      { \"name\": \"bodyOperands\", \"type\": \"Variadic<Async_AnyValueOrTokenType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"Async_TokenType\" },\n      { \"name\": \"bodyResults\", \"type\": \"Variadic<Async_ValueType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"async.func\",\n    \"summary\": \"async function operation\",\n    \"description\": \"An async function is like a normal function, but supports non-blocking\\n    await. Internally, async function is lowered to the LLVM coroutinue with\\n    async runtime intrinsic. It can return an async token and/or async values.\\n    The token represents the execution state of async function and can be used\\n    when users want to express dependencies on some side effects, e.g.,\\n    the token becomes available once every thing in the func body is executed.\\n\\n    Example:\\n\\n    ```mlir\\n    // Async function can't return void, it always must be some async thing.\\n    async.func @async.0() -> !async.token {\\n      return\\n    }\\n\\n    // Function returns only async value.\\n    async.func @async.1() -> !async.value<i32> {\\n      %0 = arith.constant 42 : i32\\n      return %0 : i32\\n    }\\n\\n    // Implicit token can be added to return types.\\n    async.func @async.2() -> !async.token, !async.value<i32> {\\n      %0 = arith.constant 42 : i32\\n      return %0 : i32\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"async\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"async.return\",\n    \"summary\": \"Async function return operation\",\n    \"description\": \"The `async.return` is a special terminator operation for Async function.\\n\\n    Example:\\n\\n    ```mlir\\n    async.func @foo() : !async.token {\\n      return\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"async.runtime.add_ref\",\n    \"summary\": \"adds a reference to async value\",\n    \"description\": \"The `async.runtime.add_ref` operation adds a reference(s) to async value\\n    (token, value or group).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyAsyncType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.add_to_group\",\n    \"summary\": \"adds an async token or value to the group\",\n    \"description\": \"The `async.runtime.add_to_group` adds an async token or value to the async\\n    group. Returns the rank of the added element in the group.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyValueOrTokenType\" },\n      { \"name\": \"group\", \"type\": \"Async_GroupType\" }\n    ],\n    \"results\": [\n      { \"name\": \"rank\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $group attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.await\",\n    \"summary\": \"blocks the caller thread until the operand becomes available\",\n    \"description\": \"The `async.runtime.await` operation blocks the caller thread until the\\n    operand becomes available or error.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyAsyncType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.await_and_resume\",\n    \"summary\": \"awaits the async operand and resumes the coroutine\",\n    \"description\": \"The `async.runtime.await_and_resume` operation awaits for the operand to\\n    become available or error and resumes the coroutine on a thread managed by\\n    the runtime.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyAsyncType\" },\n      { \"name\": \"handle\", \"type\": \"Async_CoroHandleType\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $handle attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.create\",\n    \"summary\": \"creates an async runtime token or value\",\n    \"description\": \"The `async.runtime.create` operation creates an async dialect token or\\n    value. Tokens and values are created in the non-ready state.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Async_AnyValueOrTokenType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"async.runtime.create_group\",\n    \"summary\": \"creates an async runtime group\",\n    \"description\": \"The `async.runtime.create_group` operation creates an async dialect group\\n    of the given size. Group created in the empty state.\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Async_GroupType\" }\n    ],\n    \"assemblyFormat\": \"$size `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"async.runtime.drop_ref\",\n    \"summary\": \"drops a reference to async value\",\n    \"description\": \"The `async.runtime.drop_ref` operation drops a reference(s) to async value\\n    (token, value or group).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyAsyncType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.is_error\",\n    \"summary\": \"returns true if token, value or group is in error state\",\n    \"description\": \"The `async.runtime.is_error` operation returns true if the token, value or\\n    group (any of the async runtime values) is in the error state. It is the\\n    caller responsibility to check error state after the call to `await` or\\n    resuming after `await_and_resume`.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyAsyncType\" }\n    ],\n    \"results\": [\n      { \"name\": \"is_error\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.load\",\n    \"summary\": \"loads the value from the runtime async.value\",\n    \"description\": \"The `async.runtime.load` operation loads the value from the runtime\\n    async.value storage.\",\n    \"operands\": [\n      { \"name\": \"storage\", \"type\": \"Async_ValueType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'storage', 'result', '::llvm::cast<ValueType>($_self).getValueType()'>\" }\n    ],\n    \"assemblyFormat\": \"$storage attr-dict `:` type($storage)\"\n  },\n  {\n    \"name\": \"async.runtime.num_worker_threads\",\n    \"summary\": \"gets the number of threads in the threadpool from the runtime\",\n    \"description\": \"The `async.runtime.num_worker_threads` operation gets the number of threads\\n    in the threadpool from the runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"async.runtime.resume\",\n    \"summary\": \"resumes the coroutine on a thread managed by the runtime\",\n    \"description\": \"The `async.runtime.resume` operation resumes the coroutine on a thread\\n    managed by the runtime.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"Async_CoroHandleType\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict\"\n  },\n  {\n    \"name\": \"async.runtime.set_available\",\n    \"summary\": \"switches token or value to available state\",\n    \"description\": \"The `async.runtime.set_available` operation switches async token or value\\n    state to available.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyValueOrTokenType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.set_error\",\n    \"summary\": \"switches token or value to error state\",\n    \"description\": \"The `async.runtime.set_error` operation switches async token or value\\n    state to error.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Async_AnyValueOrTokenType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"async.runtime.store\",\n    \"summary\": \"stores the value into the runtime async.value\",\n    \"description\": \"The `async.runtime.store` operation stores the value into the runtime\\n    async.value storage.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"storage\", \"type\": \"Async_ValueType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'storage', 'value', '::llvm::cast<ValueType>($_self).getValueType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $storage attr-dict `:` type($storage)\"\n  },\n  {\n    \"name\": \"async.yield\",\n    \"summary\": \"terminator for Async execute operation\",\n    \"description\": \"The `async.yield` is a special terminator operation for the block inside\\n    `async.execute` operation.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($operands^ `:` type($operands))? attr-dict\"\n  },\n  {\n    \"name\": \"bufferization.alloc_tensor\",\n    \"summary\": \"allocate buffer for a tensor\",\n    \"description\": \"`bufferization.alloc_tensor` materializes an uninitialized tensor with a\\n    given shape (dynamic or static). It always bufferizes to a new buffer\\n    allocation of the given shape. The optional `copy` operand specifies the\\n    contents of the tensors. If no `copy` operand is specified, reading from the\\n    result of an `alloc_tensor` op yields an undefined value.\\n\\n    If `copy` is specified, no dynamic sizes should be passed, since they are\\n    the same as the dynamic sizes of the `copy` operand.\\n\\n    `alloc_tensor` is a helper op for bufferization. The operation is provided\\n    as an anchor that marks the beginning of a new tensor SSA use-def chain. It\\n    can be used to control in-place bufferization decisions during One-Shot\\n    Bufferize: The bufferized result of a `bufferization.alloc_tensor` does not\\n    alias with any other buffer, so it can be used to resolve read-after-write\\n    conflicts that would have been introduced by the in-place bufferization of\\n    another op.\\n\\n    The optional `memory_space` attribute specifies the memory space when\\n    bufferizing this op. The memory space is inferred from `copy` if specified.\\n    If neither `copy` nor `memory_space` is specified, the default memory space\\n    is used during bufferization.\\n\\n    The optional `size_hint` operand specifies the number of non-zero elements\\n    for sparse tensors. The value of `size_hint` should be not less than 1 and\\n    not larger than the linear size of the corresponding dense tensor type. If\\n    this requirement is not met, the behavior of the operator is undefined.\\n\\n    Both dense and sparse tensor types are supported. The result of a\\n    `bufferization.alloc_tensor` is a tensor value that can be used like any\\n    other tensor value. In practice, it is often used as the \\\"out\\\" operand of\\n    another op. Sparse tensor allocations should always be used in a local\\n    construction operation and never escape the function boundary directly.\\n\\n    Example:\\n\\n    ```mlir\\n    %c = bufferization.alloc_tensor(%d1, %d2) : tensor<?x?xf32, #SparseMatrix>\\n    %0 = linalg.matmul\\n      ins(%a, %b: tensor<?x?xf32, #SparseMatrix>, tensor<?x?xf32, #SparseMatrix>)\\n      outs(%c: tensor<?x?xf32, #SparseMatrix>) -> tensor<?x?xf32, #SparseMatrix>\\n    return %0 : tensor<?x?xf32, #SparseMatrix>\\n    ```\\n\\n    ```mlir\\n    %c = bufferization.alloc_tensor(%d1, %d2) size_hint = %noe\\n      : tensor<?x?xf32, #SparseMatrix>\\n    ```\\n\\n    Note: An `alloc_tensor` with a `copy` should also be expressed as an\\n    `alloc_tensor` without `copy`, followed by a `copy_tensor`.\",\n    \"operands\": [\n      { \"name\": \"dynamic_sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"copy\", \"type\": \"Optional<AnyTensor>\" },\n      { \"name\": \"size_hint\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_space\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"bufferization.clone\",\n    \"summary\": \"clone a memref\",\n    \"description\": \"Clones the data in the input view into an implicitly defined output view.\\n\\n    Usage:\\n\\n    ```mlir\\n    %arg1 = bufferization.clone %arg0 : memref<?xf32> to memref<?xf32>\\n    ```\\n\\n    Valid implementations of this operation may alias the input and output\\n    views or create an actual copy. Mutating the source or result\\n    of the clone operation after the clone operation thus leads to undefined\\n    behavior.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($output)\"\n  },\n  {\n    \"name\": \"bufferization.dealloc\",\n    \"summary\": \"deallocates the given memrefs if no alias is retained\",\n    \"description\": \"This operation deallocates each of the given memrefs if there is no alias\\n    to that memref in the list of retained memrefs and the corresponding\\n    condition value is set. This condition can be used to indicate and pass on\\n    ownership of memref values (or in other words, the responsibility of\\n    deallocating that memref). If two memrefs alias each other, only one will be\\n    deallocated to avoid double free situations.\\n\\n    The number of variadic `memref` operands (the memrefs to be deallocated)\\n    must equal the number of variadic `condition` operands and correspond to\\n    each other element-wise.\\n\\n    The `memref` operands must be the originally allocated memrefs, however, the\\n    `retained` memref operands may be arbitrary memrefs.\\n\\n    This operation returns a variadic number of `updatedConditions` operands,\\n    one updated condition per retained memref. An updated condition indicates\\n    the ownership of the respective retained memref. It is computed as the\\n    disjunction of all `conditions` operands where the corresponding to\\n    `memrefs` operand aliases with the retained memref. If the retained memref\\n    has no aliases among `memrefs`, the resulting updated condition is 'false'.\\n    This is because all memrefs that need to be deallocated within one basic\\n    block should be added to the same `bufferization.dealloc` operation at the\\n    end of the block; if no aliasing memref is present, then it does not have to\\n    be deallocated and thus we don't need to claim ownership. If the memrefs to\\n    be deallocated are split over multiple dealloc operations (e.g., to avoid\\n    aliasing checks at runtime between the `memref` operands), then the results\\n    have to be manually combined using an `arith.ori` operation and all of them\\n    still require the same list of `retained` memref operands unless the\\n    (potentially empty) set of aliasing memrefs can be determined statically. In\\n    that case, the `updatedCondition` operand can be replaced accordingly (e.g.,\\n    by a canonicalizer).\\n\\n    Example:\\n    ```mlir\\n    %0:3 = bufferization.dealloc (%a0, %a1 : memref<2xf32>, memref<4xi32>)\\n      if (%cond0, %cond1) retain (%r0, %r1, %r2 : memref<?xf32>, memref<f64>,\\n      memref<2xi32>)\\n    ```\\n    Deallocation will be called on `%a0` if `%cond0` is 'true' and neither\\n    `%r0`, `%r1`, or `%r2` are aliases of `%a0`. `%a1` will be deallocated when\\n    `%cond1` is set to 'true' and none of `%r0`, `%r1`, `%r2`, and `%a0` are\\n    aliases.\\n\\n    Note that this can be an expensive operation if there are many operands that\\n    cannot be optimized away. The runtime cost of this operation (assuming that\\n    nothing is optimized away) is `O(|memrefs|^2+|memrefs|*|retained|)`. The\\n    cost in terms of memory space is `O(|memrefs|+|retained|)`. As a result, it\\n    is recommended to place it carefully in the IR such that most operands can\\n    be optimized away by running the `buffer-deallocation-simplification` pass.\",\n    \"operands\": [\n      { \"name\": \"memrefs\", \"type\": \"Variadic<AnyRankedOrUnrankedMemRef>\" },\n      { \"name\": \"conditions\", \"type\": \"Variadic<I1>\" },\n      { \"name\": \"retained\", \"type\": \"Variadic<AnyRankedOrUnrankedMemRef>\" }\n    ],\n    \"results\": [\n      { \"name\": \"updatedConditions\", \"type\": \"Variadic<I1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(` ``(` $memrefs^ `:` type($memrefs) `)` `if` ` ` `(` $conditions `)` )?\\n    (`retain` ` ` `(` $retained^ `:` type($retained) `)` )? attr-dict\"\n  },\n  {\n    \"name\": \"bufferization.dealloc_tensor\",\n    \"summary\": \"release underlying storage format of given tensor\",\n    \"description\": \"`bufferization.dealloc_tensor` is a buffer deallocation in tensor land. This\\n    op can be used for manual buffer deallocation. Some bufferizations (such as\\n    One-Shot Bufferize) take care of buffer deallocation, in which case this op\\n    is usually not needed. Details can be found in the documentation of the\\n    respective bufferization passes.\\n\\n    In case of a dense tensor, this op lowers to a `memref.dealloc` op during\\n    bufferization.\\n\\n    In case of a sparse tensor, this op releases the underlying sparse storage\\n    format for a tensor that materialized earlier through a `new` operation, a\\n    `convert` operation with annotated destination tensor type (unless the\\n    convert is folded away), or a `bufferization.alloc_tensor` operation. The\\n    release operation should only be called once for any materialized tensor.\\n    After this operation, any subsequent `memref` querying operation on the\\n    tensor returns undefined results.\\n\\n    Example:\\n\\n    ```mlir\\n    bufferization.dealloc_tensor %tensor : tensor<1024x1024xf64, #CSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"bufferization.materialize_in_destination\",\n    \"summary\": \"copy a tensor\",\n    \"description\": \"This op indicates that the data of the `source` tensor is guaranteed to\\n    materialize in `dest`, which can be a tensor or a memref. In case of a\\n    tensor, `source` materializes in the future buffer of `dest` and a the\\n    updated destination tensor is returned. If this is not possible, e.g.,\\n    because the destination tensor is read-only or because its original\\n    contents are still read later, the input IR fails to bufferize. In case of a\\n    memref, `source` materializes in `dest`, which is already a buffer. The op\\n    has no results in that case.\\n\\n    `source`, `dest` and `result` (if present) must have the same runtime shape\\n    and element type. If the op has a result, the types of `result` and `dest`\\n    must match exactly (e.g., including any tensor encodings).\\n\\n    By default, this op bufferizes to a memcpy from the future buffer of the\\n    `source` tensor to the future buffer of the `dest` tensor or to the `dest`\\n    buffer. However, transformations such as \\\"empty tensor elimination\\\" may\\n    rewrite IR such that a computation is performed directly in `dest` and no\\n    memcpy is needed.\\n\\n    If `dest` is a buffer, the `writable` attribute must be specified and the\\n    `restrict` keyword can be specified. These attributes have the same meaning\\n    as the respective attributes of `bufferization.to_tensor`.\\n\\n    `writable` indicates that the `dest` buffer is considered writable. It does\\n    not make sense to materialize a computation in a read-only buffer, so\\n    `writable` is required.\\n\\n    `restrict` indicates that there is no `bufferization.to_tensor` op and no\\n    other `bufferization.materialize_in_destination` op with `dest` (or an alias\\n    thereof) and \\\"restrict\\\". Only ops with this attribute are considered for\\n    \\\"empty tensor elimination\\\". As part of empty tensor elimination, a new\\n    `to_tensor` op with `dest` may be inserted and the `restrict` attribute is\\n    transferred from this op to the new `to_tensor` op. Having \\\"restrict\\\" on\\n    this op guarantees that performing empty tensor elimination would not create\\n    invalid IR (i.e., having multiple `to_tensor restrict` with aliasing\\n    buffers).\\n\\n    Note: `writable` could be removed from this op because it must always be set\\n    for memref destinations. This op has that attribute to make clear the\\n    requirements on the `dest` operand in the op assembly format.\\n\\n    Note: If `dest` is a tensor, `tensor.insert_slice` could be used for the\\n    same purpose, but since tensor dialect ops only indicate *what* should be\\n    computed but not *where*, it could fold away, causing the computation to\\n    materialize in a different buffer.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"restrict\", \"type\": \"UnitAttr\" },\n      { \"name\": \"writable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `in` (`restrict` $restrict^)? (`writable` $writable^)? $dest\\n        attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"bufferization.to_buffer\",\n    \"summary\": \"cast a tensor-like type to buffer-like type\",\n    \"description\": \"An operation that returns the future buffer of a `tensor`.\\n\\n    ```mlir\\n    // Result type is memref<4x?xf32, #layout, 0>\\n    %m = bufferization.to_buffer %t : tensor<4x?xf32> to memref<4x?xf32, #layout, 0>\\n    ```\\n\\n    This operation is a specialized variant of the built-in\\n    `unrealized_conversion_cast` and is used to make sure that the IR stays\\n    valid at any point during the bufferization.\\n\\n    The `read_only` attribute can optionally be set, indicating to the\\n    bufferization that the buffer returned by this op (or an alias created from\\n    the returned buffer) will not be written to.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"buffer\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"read_only\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$tensor (`read_only` $read_only^)? attr-dict `:` type($tensor) `to` type($buffer)\"\n  },\n  {\n    \"name\": \"bufferization.to_memref\"\n  },\n  {\n    \"name\": \"bufferization.to_tensor\",\n    \"summary\": \"create a tensor-like type from a buffer-like type\",\n    \"description\": \"An operation that creates a tensor from a buffer. The result value is a\\n    tensor-like type that must match the corresponding buffer-like operand as\\n    per TensorLikeType::verifyCompatibleBufferType(). For builtins (TensorType\\n    and BaseMemRefType), this means that shapes and element types match between\\n    the tensor and the buffer.\\n\\n    The opposite of this op is `to_buffer`. Together, these two ops are\\n    useful for source/target materializations when doing type conversions\\n    involving tensors and buffers.\\n\\n    Example:\\n\\n    ```mlir\\n    // Produces a value of tensor<4x?xf32> type.\\n    %t = bufferization.to_tensor %m : memref<4x?xf32, #layout, 0> to tensor<4x?xf32>\\n    ```\\n\\n    If the `writable` unit attribute is set, the produced tensor is considered\\n    \\\"writable\\\" during bufferization. Otherwise, every OpOperand that bufferizes\\n    to a write to the future buffer of the resulting tensor (or an alias\\n    thereof) will bufferize out-of-place to prevent emitting any writes to\\n    `memref` during bufferization.\\n\\n    The `restrict` unit attribute (similar to the C `restrict` keyword)\\n    indicates that the produced tensor result is the only way for the tensor\\n    IR to gain access to the `memref` operand (or an alias thereof). E.g.,\\n    there must be no other `to_tensor` op with the same or with an aliasing\\n    `memref` operand.\\n\\n    Note: Only `to_tensor` ops with the `restrict` unit attribute are supported\\n    by One-Shot Bufferize. Other IR is rejected. (To support `to_tensor`\\n    without `restrict`, One-Shot Bufferize would have to analyze memref IR.)\\n    Ops that have incorrect usage of `restrict` may bufferize incorrectly.\\n\\n    Example:\\n\\n    ```\\n    %t = bufferization.to_tensor %m restrict writable : memref<4xf32> to tensor<4xf32>\\n\\n    // %t is writable, so the tensor.insert may bufferize in-place in the\\n    // absence of other conflicts.\\n    %r = tensor.insert %f into %t[%idx] : tensor<4xf32>\\n    ```\\n\\n    `to_tensor` ops are not bufferized. They are expected to fold away after\\n    bufferization. If there are non-bufferizable ops in the IR and\\n    `allowUnknownOps` is set, they may be part of the resulting IR and not fold\\n    away. However, such IR is no longer bufferizable with One-Shot Bufferize.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"restrict\", \"type\": \"UnitAttr\" },\n      { \"name\": \"writable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$buffer (`restrict` $restrict^)? (`writable` $writable^)? attr-dict\\n      `:` type($buffer) `to` type($result)\"\n  },\n  {\n    \"name\": \"builtin.module\",\n    \"summary\": \"A top level container operation\",\n    \"description\": \"A `module` represents a top-level container operation. It contains a single\\n    [graph region](../LangRef.md#control-flow-and-ssacfg-regions) containing a single block\\n    which can contain any operations and does not have a terminator. Operations\\n    within this region cannot implicitly capture values defined outside the module,\\n    i.e. Modules are [IsolatedFromAbove](../Traits#isolatedfromabove). Modules have\\n    an optional [symbol name](../SymbolsAndSymbolTables.md) which can be used to refer\\n    to them in operations.\\n\\n    Example:\\n\\n    ```mlir\\n    module {\\n      func.func @foo()\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"OptionalAttr<SymbolNameAttr>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"builtin\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"($sym_name^)? attr-dict-with-keyword $bodyRegion\"\n  },\n  {\n    \"name\": \"builtin.unrealized_conversion_cast\",\n    \"summary\": \"An unrealized conversion from one set of types to another\",\n    \"description\": \"An `unrealized_conversion_cast` operation represents an unrealized\\n    conversion from one set of types to another, that is used to enable the\\n    inter-mixing of different type systems. This operation should not be\\n    attributed any special representational or execution semantics, and is\\n    generally only intended to be used to satisfy the temporary intermixing of\\n    type systems during the conversion of one type system to another.\\n\\n    This operation may produce results of arity 1-N, and accept as input\\n    operands of arity 0-N.\\n\\n    Example:\\n\\n    ```mlir\\n    // An unrealized 0-1 conversion. These types of conversions are useful in\\n    // cases where a type is removed from the type system, but not all uses have\\n    // been converted. For example, imagine we have a tuple type that is\\n    // expanded to its element types. If only some uses of an empty tuple type\\n    // instance are converted we still need an instance of the tuple type, but\\n    // have no inputs to the unrealized conversion.\\n    %result = unrealized_conversion_cast to !bar.tuple_type<>\\n\\n    // An unrealized 1-1 conversion.\\n    %result1 = unrealized_conversion_cast %operand : !foo.type to !bar.lowered_type\\n\\n    // An unrealized 1-N conversion.\\n    %results2:2 = unrealized_conversion_cast %tuple_operand : !foo.tuple_type<!foo.type, !foo.type> to !foo.type, !foo.type\\n\\n    // An unrealized N-1 conversion.\\n    %result3 = unrealized_conversion_cast %operand, %operand : !foo.type, !foo.type to !bar.tuple_type<!foo.type, !foo.type>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($inputs^ `:` type($inputs))? `to` type($outputs) attr-dict\"\n  },\n  {\n    \"name\": \"cf.assert\",\n    \"summary\": \"Assert operation with message attribute\",\n    \"description\": \"Assert operation at runtime with single boolean operand and an error\\n    message attribute.\\n    If the argument is `true` this operation has no effect. Otherwise, the\\n    program execution will abort. The provided error message may be used by a\\n    runtime to propagate the error to the user.\\n\\n    Example:\\n\\n    ```mlir\\n    cf.assert %b, \\\"Expected ... to be true\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$arg `,` $msg attr-dict\"\n  },\n  {\n    \"name\": \"cf.br\",\n    \"summary\": \"Branch operation\",\n    \"description\": \"The `cf.br` operation represents a direct branch operation to a given\\n    block. The operands of this operation are forwarded to the successor block,\\n    and the number and type of the operands must match the arguments of the\\n    target block.\\n\\n    Example:\\n\\n    ```mlir\\n    ^bb2:\\n      %2 = call @someFn()\\n      cf.br ^bb3(%2 : tensor<*xf32>)\\n    ^bb3(%3: tensor<*xf32>):\\n    ```\",\n    \"operands\": [\n      { \"name\": \"destOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"cf.cond_br\",\n    \"summary\": \"Conditional branch operation\",\n    \"description\": \"The `cf.cond_br` terminator operation represents a conditional branch on a\\n    boolean (1-bit integer) value. If the bit is set, then the first destination\\n    is jumped to; if it is false, the second destination is chosen. The count\\n    and types of operands must align with the arguments in the corresponding\\n    target blocks.\\n\\n    The MLIR conditional branch operation is not allowed to target the entry\\n    block for a region. The two destinations of the conditional branch operation\\n    are allowed to be the same.\\n\\n    The following example illustrates a function with a conditional branch\\n    operation that targets the same block.\\n\\n    Example:\\n\\n    ```mlir\\n    func.func @select(%a: i32, %b: i32, %flag: i1) -> i32 {\\n      // Both targets are the same, operands differ\\n      cf.cond_br %flag, ^bb1(%a : i32), ^bb1(%b : i32)\\n\\n    ^bb1(%x : i32) :\\n      return %x : i32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"trueDestOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"falseDestOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branch_weights\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$condition (`weights` `(` $branch_weights^ `)` )? `,`\\n    $trueDest (`(` $trueDestOperands^ `:` type($trueDestOperands) `)`)? `,`\\n    $falseDest (`(` $falseDestOperands^ `:` type($falseDestOperands) `)`)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cf.switch\",\n    \"summary\": \"Switch operation\",\n    \"description\": \"The `cf.switch` terminator operation represents a switch on a signless integer\\n    value. If the flag matches one of the specified cases, then the\\n    corresponding destination is jumped to. If the flag does not match any of\\n    the cases, the default destination is jumped to. The count and types of\\n    operands must align with the arguments in the corresponding target blocks.\\n\\n    Example:\\n\\n    ```mlir\\n    cf.switch %flag : i32, [\\n      default: ^bb1(%a : i32),\\n      42: ^bb1(%b : i32),\\n      43: ^bb3(%c : i32)\\n    ]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"flag\", \"type\": \"AnyInteger\" },\n      { \"name\": \"defaultOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"caseOperands\", \"type\": \"VariadicOfVariadic<AnyType, case_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"case_values\", \"type\": \"OptionalAttr<AnyIntElementsAttr>\" },\n      { \"name\": \"case_operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDestination\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"caseDestinations\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$flag `:` type($flag) `,` `[` `\\\\n`\\n      custom<SwitchOpCases>(ref(type($flag)),$defaultDestination,\\n                            $defaultOperands,\\n                            type($defaultOperands),\\n                            $case_values,\\n                            $caseDestinations,\\n                            $caseOperands,\\n                            type($caseOperands))\\n   `]`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_all_true\",\n    \"summary\": \"Checks that the operand contains only values that are true.\",\n    \"description\": \"Verifies that the operand contains true values, which are represented by any\\n    non-zero integer.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    ```mlir\\n    check.expect_all_true<%device>(%arg0) : !hal.buffer_view\\n    check.expect_all_true(%arg1) : tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<HAL_Device>\" },\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<[HAL_BufferView, TensorOf<[AnySignlessInteger]>]>\" }\n    ],\n    \"assemblyFormat\": \"(`` `<` $device^ `>`)?\\n    `` `(` $operand `)` attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_almost_eq\",\n    \"summary\": \"Checks that the operands are almost equal.\",\n    \"description\": \"Verifies that the buffer view or tensor operands with float elements satisfy\\n    the Numpy-style fuzzy-comparison condition with parameters `atol`,\\n    `rtol`, defined exactly as in NumPy isclose():\\n    https://github.com/numpy/numpy/blob/7297f3117d84745bfade1e2f9aec3531e5917500/numpy/_core/numeric.py#L2447-L2449\\n\\n    The condition being verified on each lhs and rhs value is:\\n      lhs == rhs || (isfinite(rhs) && abs(lhs - rhs) <= atol + rtol * abs(rhs)).\\n    Note that the `lhs == rhs` part is needed for the case (lhs=+inf, rhs+inf)\\n    to return true. Indeed, in that case, lhs-rhs is NaN.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    The `atol`, `rtol` parameters may be omitted, in which case some default\\n    value is used. The default `atol` is nonzero, while the default `rtol` is\\n    zero, which makes these comparison behave closer to exact comparisons as\\n    the values being compared get large.\\n\\n    This default behavior is supported for legacy compatibility and to support\\n    some use cases that legitimately don't care, but the majority of use cases\\n    should care and so should provide explicit `atol`, `rtol` values.\\n\\n    ```mlir\\n    check.expect_almost_eq(%arg0, %arg1, atol 1.0e-2, rtol 1.0e-3) : tensor<5xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<HAL_Device>\" },\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[HAL_BufferView, TensorOf<[AnyFloat]>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[HAL_BufferView, TensorOf<[AnyFloat]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"atol\", \"type\": \"DefaultValuedAttr<F32Attr, 1.e-4f>\" },\n      { \"name\": \"rtol\", \"type\": \"DefaultValuedAttr<F32Attr, 0.f>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"(`` `<` $device^ `>`)?\\n    `` `(` $lhs `,` $rhs (`` `,` `atol` $atol^)? (`` `,` `rtol` $rtol^)? `)`\\n    attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_almost_eq_const\",\n    \"summary\": \"Checks that the tensor operand is almost equal to some constant.\",\n    \"description\": \"This op is just a convenience wrapper around the expect_almost_eq op.\\n\\n    Verifies that the buffer view or tensor operands with float elements satisfy\\n    the Numpy-style fuzzy-comparison condition with pararameters `atol`,\\n    `rtol`. More details in the description of `expect_almost_eq`.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    ```mlir\\n    check.expect_almost_eq_const(%const0, dense<[0.999999, 2.0]> : tensor<5xf32>, atol 1.0e-2, rtol 1.0e-3) : tensor<5xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<HAL_Device>\" },\n      { \"name\": \"lhs\", \"type\": \"TensorOf<[AnyFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" },\n      { \"name\": \"atol\", \"type\": \"DefaultValuedAttr<F32Attr, 1.e-4f>\" },\n      { \"name\": \"rtol\", \"type\": \"DefaultValuedAttr<F32Attr, 0.f>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'value']>\" }\n    ],\n    \"assemblyFormat\": \"(`` `<` $device^ `>`)?\\n    `` `(` $lhs `,` $value (`` `,` `atol` $atol^)? (`` `,` `rtol` $rtol^)? `)`\\n    attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_eq\",\n    \"summary\": \"Checks that the tensor or buffer view operands are equal.\",\n    \"description\": \"Verifies that the operands are exactly equal.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    ```mlir\\n    check.expect_eq(%arg0, %arg1) : tensor<5xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<HAL_Device>\" },\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[HAL_BufferView, AnyTensor]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[HAL_BufferView, AnyTensor]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"(`` `<` $device^ `>`)?\\n    `` `(` $lhs `,` $rhs `)` attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_eq_const\",\n    \"summary\": \"Checks that the tensor operand is equal to some constant.\",\n    \"description\": \"Verifies that the tensor operand is exactly equal to a constant attribute.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    This op is just a convenience wrapper around the expect_eq op.\\n\\n    ```mlir\\n    check.expect_eq_const(%arg0, dense<[1, 2]> : tensor<2xi32>) : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<HAL_Device>\" },\n      { \"name\": \"lhs\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'value']>\" }\n    ],\n    \"assemblyFormat\": \"(`` `<` $device^ `>`)?\\n    `` `(` $lhs `,` $value `)` attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_false\",\n    \"summary\": \"Checks that the operand is false.\",\n    \"description\": \"Verifies that the operand contains a false value, which is represented by\\n    zero.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    ```mlir\\n    check.expect_false(%arg0) : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"assemblyFormat\": \"`(` $operand `)` attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"check.<iree>.expect_true\",\n    \"summary\": \"Checks that the operand is true.\",\n    \"description\": \"Verifies that the operand contains a true value, which is represented by\\n    any non-zero integer.\\n\\n    Issues a non-fatal failure if the verification fails.\\n\\n    ```mlir\\n    check.expect_true(%arg0) : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"assemblyFormat\": \"`(` $operand `)` attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"check.<stablehlo>.expect_almost_eq\",\n    \"summary\": \"Checks that the tensor operands are almost equal\",\n    \"description\": \"Verifies that the tensor operands with floating-point or complex element\\n    types are almost equal within an implementation-defined tolerance.\\n\\n    ```mlir\\n    check.expect_almost_eq %arg0, %arg1, tolerance = 0.001 : f64 : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TensorOf<[AnyFloat, AnyComplex]>\" },\n      { \"name\": \"rhs\", \"type\": \"TensorOf<[AnyFloat, AnyComplex]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tolerance\", \"type\": \"DefaultValuedOptionalAttr<F64Attr, 1e-4>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`,` `tolerance` `=` $tolerance^)? attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"check.<stablehlo>.expect_almost_eq_const\",\n    \"summary\": \"Checks the tensor operand is almost equal to some constant\",\n    \"description\": \"Verifies that the tensor operand with floating-point or complex element\\n    type is almost equal to the constant attribute within an\\n    implementation-defined tolerance.\\n\\n    ```mlir\\n    check.expect_almost_eq_const %arg0, dense<[0.999999, 2.0]> : tensor<2xf32>, tolerance = 0.0001\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TensorOf<[AnyFloat, AnyComplex]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" },\n      { \"name\": \"tolerance\", \"type\": \"DefaultValuedOptionalAttr<F64Attr, 1e-4>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'value']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $value (`,` `tolerance` `=` $tolerance^)? attr-dict\"\n  },\n  {\n    \"name\": \"check.<stablehlo>.expect_close\",\n    \"summary\": \"Checks that the tensor operand ULP-distance to expected tensor operand is within specified limits\",\n    \"description\": \"Verifies that the floating-point tensor operands, actual and\\n    expected, are close within user-defined limits:\\n\\n      min_ulp_difference <= ulp_difference(actual, reference) <= max_ulp_difference\\n\\n    where ulp_difference returns the number of all possible floating\\n    point values that are greater than or equal to min(actual,\\n    expected) and smaller than max(actual, expected) provided that\\n    both operands are finite.\\n\\n    When either of operands is non-finite, expect_close returns true\\n    when actual and expected are bitwise equal, or when both values\\n    are NaNs, otherwise false. Note that quiet NaN and signaling NaN\\n    values with different payloads are all considered equivalent.\\n\\n    ```mlir\\n    check.expect_close %arg0, %arg1, max_ulp_difference = 3, min_ulp_difference = 0 : tensor<2xf32>, tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"actual\", \"type\": \"TensorOf<[AnyFloat, AnyComplex]>\" },\n      { \"name\": \"expected\", \"type\": \"TensorOf<[AnyFloat, AnyComplex]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_ulp_difference\", \"type\": \"DefaultValuedAttr<UI64Attr, 1>\" },\n      { \"name\": \"min_ulp_difference\", \"type\": \"DefaultValuedOptionalAttr<UI64Attr, 0>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['actual', 'expected']>\" }\n    ],\n    \"assemblyFormat\": \"$actual `,` $expected\\n      `,` `max_ulp_difference` `=` $max_ulp_difference\\n      (`,` `min_ulp_difference` `=` $min_ulp_difference^)?\\n      `:` attr-dict type($actual) `,` type($expected)\"\n  },\n  {\n    \"name\": \"check.<stablehlo>.expect_eq\",\n    \"summary\": \"Checks that the tensor operands are equal\",\n    \"description\": \"Verifies that the operands are exactly equal.\\n\\n    ```mlir\\n    check.expect_eq %arg0, %arg1 : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"check.<stablehlo>.expect_eq_const\",\n    \"summary\": \"Checks the tensor operand is equal to some constant\",\n    \"description\": \"Verifies that the tensor operand is exactly equal to a constant attribute.\\n\\n    ```mlir\\n    check.expect_eq_const %arg0, dense<[1, 2]> : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'value']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $value attr-dict\"\n  },\n  {\n    \"name\": \"check.<stablehlo>.expect_serialized_eq\",\n    \"summary\": \"Checks value of serialized tensor value.\",\n    \"description\": \"Verifies that the value and type of the serialized tensor `probe_id` match\\n    the optionally specified input tensor at iteration `iteration`, using\\n    previously serialized filepaths in `index.csv`.\\n\\n    ```mlir\\n    check.expect_serialized_eq %arg0,\\n      probe_id = \\\"probe0\\\",\\n      iter = 0 : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"expected\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"probe_id\", \"type\": \"StrAttr\" },\n      { \"name\": \"iteration\", \"type\": \"DefaultValuedOptionalAttr<UI32Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$expected `,` `probe_id` `=` $probe_id (`,` `iter` `=` $iteration^)?\\n    attr-dict `:` type($expected)\"\n  },\n  {\n    \"name\": \"chlo._asin_acos_kernel\",\n    \"summary\": \"AsinAcosKernel operator\",\n    \"description\": \"Returns `AsinAcosKernel(operand)` element-wise.\\n\\n    ```\\n    If\\n      w = _asin_acos_kernel(z)\\n      w' = _asin_acos_kernel(I * z)\\n    Then\\n      asin(z) = complex(atan2(z.real, w.real), sign(z.imag) * w.imag)\\n      acos(z) = complex(atan2(w.real, z.real), -sign(z.imag) * w.imag)\\n      asinh(z) = complex(sign(z.real) * w'.imag, atan2(z.imag, w'.real))\\n      acosh(z) = complex(w.imag, sign(z.imag) * atan2(w.real, z.real))\\n    ```\\n\\n    This op is used as an intermediate value in decompositions and\\n    should never be constructed directly by frameworks or consumed by\\n    backends.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.acos\",\n    \"summary\": \"Acos operator\",\n    \"description\": \"Returns `Acos(operand)` element-wise.\\n\\n    $$\\n    \\\\acos(x) = 2 * \\\\atan(\\\\sqrt(1 - x^2) / (1 + x)) if x != -1\\n             = pi                                  if x == -1\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.acosh\",\n    \"summary\": \"Acosh operation\",\n    \"description\": \"Returns `Acosh(operand)` element-wise.\\n\\n    $$\\n    \\\\acosh(x) = log(x + sqrt(x^2 - 1))      if x >= -1\\n    \\\\acosh(x) = nan                         if x < -1\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.asin\",\n    \"summary\": \"Asin operator\",\n    \"description\": \"Returns `Asin(operand)` element-wise.\\n\\n    $$\\n    \\\\asin(x) = 2 * atan(x / (1 + sqrt(1 - x^2)))\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.asinh\",\n    \"summary\": \"Asinh operation\",\n    \"description\": \"Returns `Asinh(operand)` element-wise.\\n\\n    $$\\n    \\\\asinh(x) = log(x + sqrt(x^2 + 1))\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.atan\",\n    \"summary\": \"Atan operator\",\n    \"description\": \"Returns `Atan(operand)` element-wise.\\n\\n    $$\\n    \\\\atan(x) = \\\\atan2(x, 1)\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.atanh\",\n    \"summary\": \"Atanh operator\",\n    \"description\": \"Returns `Atanh(operand)` element-wise.\\n\\n    $$\\n    \\\\atanh(x) = 0.5 * log((1 + x) / (1 - x)) if abs(x) <= 1\\n              = nan                          otherwise\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.bessel_i1e\",\n    \"summary\": \"Bessel function of order 1\",\n    \"description\": \"Returns `bessel_i1e(operand)` element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_add\",\n    \"summary\": \"Addition operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs + rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_and\",\n    \"summary\": \"Logical and operator (with optional broadcasting)\",\n    \"description\": \"Returns `logical_and(lhs, rhs)` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyPredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyPredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_atan2\",\n    \"summary\": \"Atan2 operator (with optional broadcasting)\",\n    \"description\": \"Returns `atan2(lhs/rhs)` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_compare\",\n    \"summary\": \"Compare operator (with optional broadcasting)\",\n    \"description\": \"Compares `lhs` and `rhs` elementwise according to `comparison_direction`\\n    and `compare_type`. If unspecified, `compare_type` is FLOAT for float element\\n    types, SIGNED for signed element types and UNSIGNED for unsigned element\\n    types.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_comparison_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyPredTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"comparison_direction\", \"type\": \"CHLO_ComparisonDirectionAttr{EQ|NE|GE|GT|LE|LT}\" },\n      { \"name\": \"compare_type\", \"type\": \"OptionalAttr<CHLO_ComparisonTypeAttr{NOTYPE|FLOAT|TOTALORDER|SIGNED|UNSIGNED}>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_complex\",\n    \"summary\": \"Complex operator (with optional broadcasting)\",\n    \"description\": \"Performs element-wise conversion of a pair of real and imaginary values to\\n    a complex value.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyFpTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_divide\",\n    \"summary\": \"Division operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs / rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_maximum\",\n    \"summary\": \"Maximum operator (with optional broadcasting)\",\n    \"description\": \"Returns `max(lhs, rhs)` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_minimum\",\n    \"summary\": \"Minimum operator (with optional broadcasting)\",\n    \"description\": \"Returns `min(lhs, rhs)` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_multiply\",\n    \"summary\": \"Multiplication operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs * rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_next_after\",\n    \"summary\": \"std::nextafter operator (with optional broadcasting)\",\n    \"description\": \"Returns the next representable value of `lhs` in the direction of `rhs`,\\n    element-wise. It can also return a subnormal number.\\n\\n    Equivalent to the C++ std::nextafter function.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_or\",\n    \"summary\": \"Logical or operator (with optional broadcasting)\",\n    \"description\": \"Returns `logical_or(lhs, rhs)` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyPredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyPredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_polygamma\",\n    \"summary\": \"Polygamma function (with optional broadcasting)\",\n    \"description\": \"Returns `Polygamma(operand, operand)` element-wise.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_power\",\n    \"summary\": \"Power operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs ^ rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_remainder\",\n    \"summary\": \"Remainder operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs % rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_select\",\n    \"summary\": \"Select operator (with optional numpy-style broadcasting)\",\n    \"description\": \"Constructs an output array from elements of two input arrays, based on the\\n    values of a predicate array.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#select\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"HLO_PredTensor\" },\n      { \"name\": \"on_true\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"on_false\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$pred `,` $on_true `,` $on_false attr-dict `:`\\n    `(` type($pred) `,` type($on_true) `,` type($on_false) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_shift_left\",\n    \"summary\": \"Shift left operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs << rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_shift_right_arithmetic\",\n    \"summary\": \"Shift right arithmetic operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs >> rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_shift_right_logical\",\n    \"summary\": \"Shift right logical operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs >> rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_subtract\",\n    \"summary\": \"Subtraction operator (with optional broadcasting)\",\n    \"description\": \"Returns `lhs - rhs` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_xor\",\n    \"summary\": \"Logical xor operator (with optional broadcasting)\",\n    \"description\": \"Returns `logical_xor(lhs, rhs)` element-wise.\\n\\n    See\\n    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyPredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyPredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.broadcast_zeta\",\n    \"summary\": \"Hurwitz zeta function\",\n    \"description\": \"Returns `Zeta(operand, operand)` element-wise.\\n\\n    $$\\n    \\\\(\\\\zeta(x, q) = \\\\sum_{n=0}^{\\\\infty} (q + n)^{-x}\\\\)\\n    $$\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyFpTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:`\\n    `(` type($lhs) `,` type($rhs) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.conj\",\n    \"summary\": \"Conj operator\",\n    \"description\": \"Returns `Conj(operand)` element-wise.\\n\\n    $$\\n    \\\\conj(x) = (\\\\real(x), \\\\neg(\\\\imag(x)))\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.constant\",\n    \"summary\": \"Constant operator\",\n    \"description\": \"Represents a constant value.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"HLO_StaticShapeTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"chlo.constant_like\",\n    \"summary\": \"Constant like operator\",\n    \"description\": \"Returns a splat constant of the same shape as the operand.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ]\n  },\n  {\n    \"name\": \"chlo.cosh\",\n    \"summary\": \"Cosh operator\",\n    \"description\": \"Returns `Cosh(operand)` element-wise.\\n\\n    $$\\n    \\\\cosh(x) = (e^x + e^-x) / 2\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.digamma\",\n    \"summary\": \"Digamma function\",\n    \"description\": \"Returns `Digamma(operand)` element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.erf\",\n    \"summary\": \"Erfc operator\",\n    \"description\": \"Computes the Gauss error function of `x` element-wise.\\n\\n    erf(x) = erf_impl(x)            if |x| < 1\\n           = 1 - erfc_impl(x)       otherwise\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.erf_inv\",\n    \"summary\": \"Inverse Erf\",\n    \"description\": \"Returns `ErfInv(operand)` element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.erfc\",\n    \"summary\": \"Erfc operator\",\n    \"description\": \"Computes an approximation of the error function complement (1 - erf(x)).\\n\\n    erfc(x) = erfc_impl(x)           if |x| > 1\\n            = 1 - erf_impl(x)        otherwise\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.is_inf\",\n    \"summary\": \"IsInf predicate\",\n    \"description\": \"Returns if a value is +/-inf element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyPredTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.is_neg_inf\",\n    \"summary\": \"IsNegInf predicate\",\n    \"description\": \"Returns if a value is -inf element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyPredTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.is_pos_inf\",\n    \"summary\": \"IsPosInf predicate\",\n    \"description\": \"Returns if a value is +inf element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyPredTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.lgamma\",\n    \"summary\": \"Lgamma function\",\n    \"description\": \"Returns `Lgamma(operand)` element-wise.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.next_after\",\n    \"summary\": \"std::nextafter operator\",\n    \"description\": \"Returns the next representable value of `x` in the direction of `y`,\\n    element-wise. It can also return a subnormal number.\\n\\n    Equivalent to the C++ std::nextafter function.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"HLO_AnyFpTensor\" },\n      { \"name\": \"y\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $y attr-dict `:` type($x) `,` type($y) `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.polygamma\",\n    \"summary\": \"Polygamma function\",\n    \"description\": \"Returns `Polygamma(operand, operand)` element-wise.\",\n    \"operands\": [\n      { \"name\": \"n\", \"type\": \"HLO_AnyFpTensor\" },\n      { \"name\": \"x\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$n `,` $x attr-dict `:` type($n) `,` type($x) `->` type(results)\"\n  },\n  {\n    \"name\": \"chlo.ragged_dot\",\n    \"summary\": \"Computes a matmul over a single ragged dimension\",\n    \"description\": \"This operation takes three tensor args---lhs, rhs, and group_sizes---and\\n    a \\\"ragged_dot_dimension_numbers\\\" attribute. Like dot_general, the lhs and\\n    rhs are allowed arbitrary batch and contracting dimensions. Additionally,\\n    the lhs is required to have one ragged dimension, and the rhs may have at\\n    most one group dimension. The op has three modes, depending on the kind of\\n    the lhs ragged dimension.\\n\\n    In mode 1, the shape-signature is `[b,m,k], [g,b,k,n], [b,g] -> [b,m,n]`.\\n    Here the ragged dimension is an lhs non-contracting dimension (`m`). The\\n    dimensions `b` and `k` represent batch and contracting dimensions\\n    respectively. The rhs is required to have a group dimension (`g`).\\n\\n    In mode 2, the shape-signature is `[b,m,k], [b,k,n], [b,g] -> [g,b,m,n]`.\\n    Here the ragged dimension is an lhs/rhs contracting dimension (`k`).\\n\\n    In mode 3, the shape-signature is `[b,m,k], [b,k,n], [g] -> [b,m,n]`. Here\\n    the ragged dimension is an lhs/rhs batch dimension (`b`).\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"group_sizes\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ragged_dot_dimension_numbers\", \"type\": \"CHLO_RaggedDotDimensionNumbers\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<CHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ]\n  },\n  {\n    \"name\": \"chlo.scan\",\n    \"summary\": \"Scan operation\",\n    \"description\": \"Applies a reduction function `body` to `inputs` and `inits` along the\\n    `dimension` and produces `results` (comprising `outputs` and `carries`).\\n\\n    If `is_reverse` is true, the scan is performed in reverse order.\\n    `is_associative` indicates whether the reduction function is associative.\\n\\n    See: https://www.tensorflow.org/xla/operation_semantics#scan\\n\\n    ScanOp currently does not have a decomposition to StableHLO.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_AnyTensor>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<HLO_AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<HLO_AnyTensor>\" },\n      { \"name\": \"carries\", \"type\": \"Variadic<HLO_AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"is_associative\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"chlo.sinh\",\n    \"summary\": \"Sinh operation\",\n    \"description\": \"Returns `Sinh(operand)` element-wise.\\n\\n    $$\\n    \\\\sinh(x) = (e^x - e^-x) / 2                     if |x| < 1\\n             = e^(x + log(1/2)) - e^(-x + log(1/2)) otherwise.\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.square\",\n    \"summary\": \"Square operation\",\n    \"description\": \"Returns `Square(operand)` element-wise.\\n\\n    $$\\n    \\\\square(x) = complex((x.real - x.imag) * (x.real + x.imag), x.real * x.imag * 2) if x is a complex number\\n               = x * x                                                               otherwise\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.tan\",\n    \"summary\": \"Tan operation\",\n    \"description\": \"Returns `Tan(operand)` element-wise.\\n\\n    $$\\n    \\\\tan(x) = \\\\sin(x) / \\\\cos(x)\\n    $$\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\"\n  },\n  {\n    \"name\": \"chlo.top_k\",\n    \"summary\": \"Finds values and indices of the `k` largest elements for the last dimension\",\n    \"description\": \"If the input is a vector (rank-1), finds the `k` largest entries in the\\n    vector and outputs their values and indices as vectors.  Thus `values[j]` is\\n    the `j`-th largest entry in `input`, and its index is `indices[j]`.\\n\\n    For matrices (resp. higher rank input), computes the top `k` entries in each\\n    row (resp. vector along the last dimension).  Thus,\\n\\n    ```\\n    values.shape = indices.shape = input.shape[:-1] + [k]\\n    ```\\n\\n    If two elements are equal, the lower-index element appears first.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"HLO_AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"HLO_AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"`(`$operand `,` `k` `=` $k`)` attr-dict `:`\\n    type($operand) `->` `(`type($values)`,` type($indices)`)`\"\n  },\n  {\n    \"name\": \"chlo.zeta\",\n    \"summary\": \"Hurwitz zeta function\",\n    \"description\": \"Returns `Zeta(operand, operand)` element-wise.\\n\\n    $$\\n    \\\\(\\\\zeta(x, q) = \\\\sum_{n=0}^{\\\\infty} (q + n)^{-x}\\\\)\\n    $$\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"HLO_AnyFpTensor\" },\n      { \"name\": \"q\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpTensor\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $q attr-dict `:` type($x) `,` type($q) `->` type(results)\"\n  },\n  {\n    \"name\": \"cir.abs\",\n    \"summary\": \"libc builtin equivalent abs, labs, llabs\\n\\n    The `poison` argument indicate whether the result value\\n    is a poison value if the first argument is statically or\\n    dynamically an INT_MIN value.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = cir.const #cir.int<-42> : s32i\\n      %1 = cir.abs %0 poison : s32i\\n      %2 = cir.abs %3 : !cir.vector<!s32i x 4>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnySIntOrVecOfSIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnySIntOrVecOfSIntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"poison\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src ( `poison` $poison^ )? `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.acos\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.alloc.exception\",\n    \"summary\": \"Allocates an exception according to Itanium ABI\",\n    \"description\": \"Implements a slightly higher level __cxa_allocate_exception:\\n\\n    `void *__cxa_allocate_exception(size_t thrown_size);`\\n\\n    If operation fails, program terminates, not throw.\\n\\n    Example:\\n\\n    ```mlir\\n    // if (b == 0) {\\n    //   ...\\n    //   throw \\\"...\\\";\\n    cir.if %10 {\\n        %11 = cir.alloc_exception 8 -> !cir.ptr<!void>\\n        ... // store exception content into %11\\n        cir.throw %11 : !cir.ptr<!cir.ptr<!u8i>>, ...\\n    ```\",\n    \"results\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$size `->` qualified(type($addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.alloca\",\n    \"summary\": \"Defines a scope-local variable\",\n    \"description\": \"The `cir.alloca` operation defines a scope-local variable.\\n\\n    The presence `init` attribute indicates that the local variable represented\\n    by this alloca was originally initialized in C/C++ source code. In such\\n    cases, the first use contains the initialization (a cir.store, a cir.call\\n    to a ctor, etc).\\n\\n    The presence of the `const` attribute indicates that the local variable is\\n    declared with C/C++ `const` keyword.\\n\\n    The `dynAllocSize` specifies the size to dynamically allocate on the stack\\n    and ignores the allocation size based on the original type. This is useful\\n    when handling VLAs and is omitted when declaring regular local variables.\\n\\n    The result type is a pointer to the input's type.\\n\\n    Example:\\n\\n    ```mlir\\n    // int count = 3;\\n    %0 = cir.alloca i32, !cir.ptr<i32>, [\\\"count\\\", init] {alignment = 4 : i64}\\n\\n    // int *ptr;\\n    %1 = cir.alloca !cir.ptr<i32>, !cir.ptr<!cir.ptr<i32>>, [\\\"ptr\\\"] {alignment = 8 : i64}\\n    ...\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynAllocSize\", \"type\": \"Optional<CIR_AnyFundamentalIntType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"allocaType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"init\", \"type\": \"UnitAttr\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"alignment\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>\" },\n      { \"name\": \"annotations\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"ast\", \"type\": \"OptionalAttr<ASTVarDeclInterface>\" }\n    ],\n    \"assemblyFormat\": \"$allocaType `,` qualified(type($addr)) `,`\\n    ($dynAllocSize^ `:` type($dynAllocSize) `,`)?\\n    `[` $name\\n       (`,` `init` $init^)?\\n       (`,` `const` $constant^)?\\n    `]`\\n    ($annotations^)?\\n    (`ast` $ast^)? attr-dict\"\n  },\n  {\n    \"name\": \"cir.array.ctor\",\n    \"summary\": \"Initialize array elements with C++ constructors\",\n    \"description\": \"Initialize each array element using the same C++ constructor. This\\n    operation has one region, with one single block. The block has an\\n    incoming argument for the current array index to initialize.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PtrToArray\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`(` $addr `:` qualified(type($addr)) `)` $body attr-dict\"\n  },\n  {\n    \"name\": \"cir.array.dtor\",\n    \"summary\": \"Destroy array elements with C++ dtors\",\n    \"description\": \"Destroy each array element using the same C++ destructor. This\\n    operation has one region, with one single block. The block has an\\n    incoming argument for the current array index to initialize.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PtrToArray\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`(` $addr `:` qualified(type($addr)) `)` $body attr-dict\"\n  },\n  {\n    \"name\": \"cir.asin\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.asm\",\n    \"description\": \"The `cir.asm` operation represents C/C++ asm inline.\\n\\n    CIR constraints strings follow barelly the same rules that are established\\n    for the C level assembler constraints with several differences caused by\\n    clang::AsmStmt processing.\\n\\n    Thus, numbers that appears in the constraint string may also refer to:\\n    - the output variable index referenced by the input operands.\\n    - the index of early-clobber operand\\n\\n    Operand attributes is a storage, where each element corresponds to the operand with\\n    the same index. The first index relates to the operation result (if any).\\n    Note, the operands themselves are stored as VariadicOfVariadic in the next order:\\n    output, input and then in/out operands.\\n\\n    Note, when several output operands are present, the result type may be represented as\\n    an anon record type.\\n\\n    Example:\\n    ```C++\\n    __asm__(\\\"foo\\\" : : : );\\n    __asm__(\\\"bar $42 %[val]\\\" : [val] \\\"=r\\\" (x), \\\"+&r\\\"(x));\\n    __asm__(\\\"baz $42 %[val]\\\" : [val] \\\"=r\\\" (x), \\\"+&r\\\"(x) : \\\"[val]\\\"(y));\\n    ```\\n\\n    ```mlir\\n    !rec_22anon2E022 = !cir.record<struct \\\"anon.0\\\" {!cir.int<s, 32>, !cir.int<s, 32>}>\\n    !rec_22anon2E122 = !cir.record<struct \\\"anon.1\\\" {!cir.int<s, 32>, !cir.int<s, 32>}>\\n    ...\\n    %0 = cir.alloca !s32i, !cir.ptr<!s32i>, [\\\"x\\\", init]\\n    %1 = cir.alloca !s32i, !cir.ptr<!s32i>, [\\\"y\\\", init]\\n    ...\\n    %2 = cir.load %0 : !cir.ptr<!s32i>, !s32i\\n    %3 = cir.load %1 : !cir.ptr<!s32i>, !s32i\\n\\n    cir.asm(x86_att,\\n      out = [],\\n      in = [],\\n      in_out = [],\\n      {\\\"foo\\\" \\\"~{dirflag},~{fpsr},~{flags}\\\"}) side_effects\\n\\n    cir.asm(x86_att,\\n      out = [],\\n      in = [],\\n      in_out = [%2 : !s32i],\\n      {\\\"bar $$42 $0\\\" \\\"=r,=&r,1,~{dirflag},~{fpsr},~{flags}\\\"}) -> !rec_22anon2E022\\n\\n    cir.asm(x86_att,\\n      out = [],\\n      in = [%3 : !s32i],\\n      in_out = [%2 : !s32i],\\n      {\\\"baz $$42 $0\\\" \\\"=r,=&r,0,1,~{dirflag},~{fpsr},~{flags}\\\"}) -> !rec_22anon2E122\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asm_operands\", \"type\": \"VariadicOfVariadic<AnyType, operands_segments>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asm_string\", \"type\": \"StrAttr\" },\n      { \"name\": \"constraints\", \"type\": \"StrAttr\" },\n      { \"name\": \"side_effects\", \"type\": \"UnitAttr\" },\n      { \"name\": \"asm_flavor\", \"type\": \"CIR_AsmFlavor{x86_att|x86_intel}\" },\n      { \"name\": \"operand_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"operands_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"cir.assume\",\n    \"summary\": \"Tell the optimizer that a boolean value is true\",\n    \"description\": \"The `cir.assume` operation takes a single boolean prediate as its only\\n    argument and does not have any results. The operation tells the optimizer\\n    that the predicate's value is true.\\n\\n    This operation corresponds to the `__assume` and the `__builtin_assume`\\n    builtin function.\",\n    \"operands\": [\n      { \"name\": \"predicate\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"assemblyFormat\": \"$predicate `:` type($predicate) attr-dict\"\n  },\n  {\n    \"name\": \"cir.assume.aligned\",\n    \"summary\": \"Tell the optimizer that a pointer is aligned\",\n    \"description\": \"The `cir.assume.aligned` operation takes two or three arguments.\\n\\n    When the 3rd argument `offset` is absent, this operation tells the optimizer\\n    that the pointer given by the `pointer` argument is aligned to the alignment\\n    given by the `align` argument.\\n\\n    When the `offset` argument is given, it represents an offset from the\\n    alignment. This operation then tells the optimizer that the pointer given by\\n    the `pointer` argument is always misaligned by the alignment given by the\\n    `align` argument by `offset` bytes, a.k.a. the pointer yielded by\\n    `(char *)pointer - offset` is aligned to the specified alignment.\\n\\n    The `align` argument is a constant integer represented as an integer\\n    attribute instead of an SSA value. It must be a positive integer.\\n\\n    The result of this operation has the same value as the `pointer` argument,\\n    but the optimizer has additional knowledge about its alignment.\\n\\n    This operation corresponds to the `__builtin_assume_aligned` builtin\\n    function.\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"offset\", \"type\": \"Optional<CIR_IntType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['pointer', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$pointer `:` qualified(type($pointer))\\n    `[` `alignment` $alignment (`,` `offset` $offset^ `:` type($offset))? `]`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.assume.separate_storage\",\n    \"summary\": \"Tell the optimizer that two pointers point to different allocations\",\n    \"description\": \"The `cir.assume.separate_storage` operation takes two pointers as arguments,\\n    and the operation tells the optimizer that these two pointers point to\\n    different allocations.\\n\\n    This operation corresponds to the `__builtin_assume_separate_storage`\\n    builtin function.\",\n    \"operands\": [\n      { \"name\": \"ptr1\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"ptr2\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"assemblyFormat\": \"$ptr1 `,` $ptr2 `:` qualified(type($ptr1)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.atan\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.atan2\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.atomic.clear\",\n    \"summary\": \"Atomic clear\",\n    \"description\": \"C/C++ atomic clear operation. Implements the builtin function\\n    `__atomic_clear`.\\n\\n    The operation takes as its only operand a pointer to an 8-bit signed\\n    integer. The operation atomically sets the integer to zero.\\n\\n    Example:\\n    ```mlir\\n      cir.atomic.clear seq_cst %ptr : !cir.ptr<!s8i>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PtrToType<CIR_SInt8>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mem_order\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"sync_scope\", \"type\": \"OptionalAttr<CIR_SyncScopeKind{single_thread|system}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$mem_order $ptr\\n    (`volatile` $is_volatile^)?\\n    `:` qualified(type($ptr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.atomic.cmp_xchg\",\n    \"summary\": \"Atomic compare exchange\",\n    \"description\": \"C/C++ Atomic compare and exchange operation. Implements builtins like\\n    `__atomic_compare_exchange_n` and `__atomic_compare_exchange`.\\n\\n    Example:\\n    %old, %cmp = cir.atomic.cmp_xchg(%ptr : !cir.ptr<!some_record>,\\n                                     %expected : !u64i,\\n                                     %desired : !u64i,\\n                                     success = seq_cst,\\n                                     failure = seq_cst) weak\\n                                     : (!u64i, !cir.bool)\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"expected\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"desired\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"old\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"cmp\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"succ_order\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"fail_order\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"sync_scope\", \"type\": \"OptionalAttr<CIR_SyncScopeKind{single_thread|system}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"weak\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['old', 'expected', 'desired']>\" }\n    ],\n    \"assemblyFormat\": \"`(`\\n    $ptr `:` qualified(type($ptr)) `,`\\n    $expected `:` type($expected) `,`\\n    $desired `:` type($desired) `,`\\n    `success` `=`  $succ_order `,`\\n    `failure` `=`  $fail_order\\n    `)`\\n    (`syncscope` `(` $sync_scope^ `)`)?\\n    (`align` `(` $alignment^ `)`)?\\n    (`weak` $weak^)?\\n    (`volatile` $is_volatile^)?\\n    `:` `(` type($old) `,` type($cmp) `)` attr-dict\"\n  },\n  {\n    \"name\": \"cir.atomic.fence\",\n    \"summary\": \"Atomic thread fence\",\n    \"description\": \"C/C++ Atomic thread fence synchronization primitive. Implements the builtin\\n    `__atomic_thread_fence` which enforces memory ordering constraints across\\n    threads within the specified synchronization scope.\\n\\n    This handles all variations including:\\n      - `__atomic_thread_fence`\\n      - `__atomic_signal_fence`\\n      - `__c11_atomic_thread_fence`\\n      - `__c11_atomic_signal_fence`\\n\\n    Example:\\n    ```mlir\\n      cir.atomic.fence syncscope(system) seq_cst\\n      cir.atomic.fence syncscope(single_thread) seq_cst\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"ordering\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"sync_scope\", \"type\": \"OptionalAttr<CIR_SyncScopeKind{single_thread|system}>\" }\n    ],\n    \"assemblyFormat\": \"(`syncscope` `(` $sync_scope^ `)`)? $ordering attr-dict\"\n  },\n  {\n    \"name\": \"cir.atomic.fetch\",\n    \"summary\": \"Atomic fetch with unary and binary operations\",\n    \"description\": \"Represents `__atomic_<binop>_fetch` and `__atomic_fetch_<binop>` builtins,\\n    where `binop` is on of the binary opcodes : `add`, `sub`, `and`, `xor`,\\n    `or`, `nand`, `max` and `min`.\\n\\n    `ptr` is an integer or fp pointer, followed by `val`, which must be\\n    an integer or fp (only supported for `add` and `sub`). The operation\\n    can also be marked `volatile`.\\n\\n    If `fetch_first` is present, the operation works like\\n    `__atomic_fetch_binop` and returns the value that had\\n    previously been in *ptr, otherwise it returns the final result\\n    of the computation (`__atomic_binop_fetch`).\\n\\n    Example:\\n    %res = cir.atomic.fetch(add, %ptr : !cir.ptr<!s32i>,\\n                            %val : !s32i, seq_cst) : !s32i\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PtrToIntOrFloatType\" },\n      { \"name\": \"val\", \"type\": \"CIR_AnyIntOrFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyIntOrFloatType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"binop\", \"type\": \"CIR_AtomicFetchKind{add|sub|and|xor|or|nand|max|min|xchg}\" },\n      { \"name\": \"mem_order\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" },\n      { \"name\": \"fetch_first\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'val']>\" }\n    ],\n    \"assemblyFormat\": \"`(`$binop `,`\\n    $ptr `:` qualified(type($ptr)) `,`\\n    $val `:` type($val) `,`\\n    $mem_order `)`\\n    (`volatile` $is_volatile^)?\\n    (`fetch_first` $fetch_first^)?\\n    `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.atomic.test_and_set\",\n    \"summary\": \"Atomic test and set\",\n    \"description\": \"C/C++ atomic test and set operation. Implements the builtin function\\n    `__atomic_test_and_set`.\\n\\n    The operation takes as its only operand a pointer to an 8-bit signed\\n    integer. The operation atomically set the integer to an implementation-\\n    defined non-zero \\\"set\\\" value. The result of the operation is a boolean value\\n    indicating whether the previous value of the integer was the \\\"set\\\" value.\\n\\n    Example:\\n    ```mlir\\n      %res = cir.atomic.test_and_set seq_cst %ptr : !cir.ptr<!s8i> -> !cir.bool\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PtrToType<CIR_SInt8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mem_order\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"sync_scope\", \"type\": \"OptionalAttr<CIR_SyncScopeKind{single_thread|system}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$mem_order $ptr\\n    (`volatile` $is_volatile^)?\\n    `:` qualified(type($ptr)) `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.atomic.xchg\",\n    \"summary\": \"Atomic exchange\",\n    \"description\": \"Atomic exchange operations. Implements C/C++ builtins such as\\n    `__atomic_exchange`and `__atomic_exchange_n`.\\n\\n    Example:\\n    %res = cir.atomic.xchg(%ptr : !cir.ptr<!some_record>,\\n                           %val : !u64i, seq_cst) : !u64i\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"val\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mem_order\", \"type\": \"CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'val']>\" }\n    ],\n    \"assemblyFormat\": \"`(`\\n    $ptr `:` qualified(type($ptr)) `,`\\n    $val `:` type($val) `,`\\n    $mem_order `)`\\n    (`volatile` $is_volatile^)?\\n    `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.await\",\n    \"summary\": \"Wraps C++ co_await implicit logic\",\n    \"description\": \"The under the hood effect of using C++ `co_await expr` roughly\\n    translates to:\\n\\n    ```c++\\n    // co_await expr;\\n\\n    auto &&x = CommonExpr();\\n    if (!x.await_ready()) {\\n       ...\\n       x.await_suspend(...);\\n       ...\\n    }\\n    x.await_resume();\\n    ```\\n\\n    `cir.await` represents this logic by using 3 regions:\\n      - ready: covers veto power from x.await_ready()\\n      - suspend: wraps actual x.await_suspend() logic\\n      - resume: handles x.await_resume()\\n\\n    Breaking this up in regions allow individual scrutiny of conditions\\n    which might lead to folding some of them out. Lowerings coming out\\n    of CIR, e.g. LLVM, should use the `suspend` region to track more\\n    lower level codegen (e.g. intrinsic emission for coro.save/coro.suspend).\\n\\n    There are also 4 flavors of `cir.await` available:\\n    - `init`: compiler generated initial suspend via implicit `co_await`.\\n    - `user`: also known as normal, representing user written co_await's.\\n    - `yield`: user written `co_yield` expressions.\\n    - `final`: compiler generated final suspend via implicit `co_await`.\\n\\n    From the C++ snippet we get:\\n\\n    ```mlir\\n      cir.scope {\\n        ... // auto &&x = CommonExpr();\\n        cir.await(user, ready : {\\n          ... // x.await_ready()\\n        }, suspend : {\\n          ... // x.await_suspend()\\n        }, resume : {\\n          ... // x.await_resume()\\n        })\\n      }\\n    ```\\n\\n    Note that resulution of the common expression is assumed to happen\\n    as part of the enclosing await scope.\",\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_AwaitKind{init|user|yield|final}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"ready\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"suspend\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"resume\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,`\\n    `ready` `:` $ready `,`\\n    `suspend` `:` $suspend `,`\\n    `resume` `:` $resume `,`\\n    `)`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.base_class_addr\",\n    \"summary\": \"Get the base class address for a class/struct\",\n    \"description\": \"The `cir.base_class_addr` operaration gets the address of a particular\\n    non-virtual base class given a derived class pointer. The offset in bytes\\n    of the base class must be passed in, since it is easier for the front end\\n    to calculate that than the MLIR passes. The operation contains a flag for\\n    whether or not the operand may be nullptr. That depends on the context and\\n    cannot be known by the operation, and that information affects how the\\n    operation is lowered.\\n\\n    Example:\\n    ```c++\\n    struct Base { };\\n    struct Derived : Base { };\\n    Derived d;\\n    Base& b = d;\\n    ```\\n    will generate\\n    ```mlir\\n    %3 = cir.base_class_addr %1 : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"derived_addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"base_addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"IndexAttr\" },\n      { \"name\": \"assume_not_null\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$derived_addr `:` qualified(type($derived_addr))\\n      (`nonnull` $assume_not_null^)?\\n      ` ` `[` $offset `]` `->` qualified(type($base_addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.base_data_member\",\n    \"summary\": \"Cast a derived class data member pointer to a base class data member pointer\",\n    \"description\": \"The `cir.base_data_member` operation casts a data member pointer of type\\n    `T Derived::*` to a data member pointer of type `T Base::*`, where `Base`\\n    is an accessible non-ambiguous non-virtual base class of `Derived`.\\n\\n    The `offset` parameter gives the offset in bytes of the `Base` base class\\n    subobject within a `Derived` object.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_DataMemberType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_DataMemberType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `:` qualified(type($src))\\n    ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.base_method\",\n    \"summary\": \"Cast a derived class pointer-to-member-function to a base class\\n    pointer-to-member-function\",\n    \"description\": \"The `cir.base_method` operation casts a pointer-to-member-function of type\\n    `Ret (Derived::*)(Args)` to a pointer-to-member-function of type\\n    `Ret (Base::*)(Args)`, where `Base` is a non-virtual base class of\\n    `Derived`.\\n\\n    The `offset` parameter gives the offset in bytes of the `Base` base class\\n    subobject within a `Derived` object.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = cir.base_method %0 : !cir.method<!cir.func<(!s32i)> in !rec_Derived> [16] -> !cir.method<!cir.func<(!s32i)> in !rec_Base>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_MethodType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_MethodType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `:` qualified(type($src))\\n    ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.binop\",\n    \"summary\": \"Binary operations (arith and logic)\",\n    \"description\": \"cir.binop performs the binary operation according to\\n    the specified opcode kind: [mul, div, rem, add, sub,\\n    and, xor, or].\\n\\n    It requires two input operands and has one result, all types\\n    should be the same.\\n\\n    ```mlir\\n    %7 = cir.binop(add, %1, %2) : !s32i\\n    %7 = cir.binop(mul, %1, %2) : !u8i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_BinOpKind{mul|div|rem|add|sub|and|xor|or|max}\" },\n      { \"name\": \"no_unsigned_wrap\", \"type\": \"UnitAttr\" },\n      { \"name\": \"no_signed_wrap\", \"type\": \"UnitAttr\" },\n      { \"name\": \"saturated\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,` $lhs `,` $rhs  `)`\\n    (`nsw` $no_signed_wrap^)?\\n    (`nuw` $no_unsigned_wrap^)?\\n    (`sat` $saturated^)?\\n    `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"cir.binop.overflow\",\n    \"summary\": \"Perform binary integral arithmetic with overflow checking\",\n    \"description\": \"`cir.binop.overflow` performs binary arithmetic operations with overflow\\n    checking on integral operands.\\n\\n    The `kind` argument specifies the kind of arithmetic operation to perform.\\n    It can be either `add`, `sub`, or `mul`. The `lhs` and `rhs` arguments\\n    specify the input operands of the arithmetic operation. The types of `lhs`\\n    and `rhs` must be the same.\\n\\n    `cir.binop.overflow` produces two SSA values. `result` is the result of the\\n    arithmetic operation truncated to its specified type. `overflow` is a\\n    boolean value indicating whether overflow happens during the operation.\\n\\n    The exact semantic of this operation is as follows:\\n\\n      - `lhs` and `rhs` are promoted to an imaginary integral type that has\\n        infinite precision.\\n      - The arithmetic operation is performed on the promoted operands.\\n      - The infinite-precision result is truncated to the type of `result`. The\\n        truncated result is assigned to `result`.\\n      - If the truncated result is equal to the un-truncated result, `overflow`\\n        is assigned to false. Otherwise, `overflow` is assigned to true.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_IntType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" },\n      { \"name\": \"overflow\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_BinOpOverflowKind{add|sub|mul}\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,`\\n    `(` type($result) `,` type($overflow) `)`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.bit_reverse\",\n    \"summary\": \"Reverse the bit pattern of the operand integer\",\n    \"description\": \"The `cir.bit_reverse` operation reverses the bit pattern of the operand\\n    integer. Its only argument must be of unsigned integer types of width 8, 16,\\n    32, or 64.\\n\\n    This operation covers the C/C++ builtin function `__builtin_bitreverse`.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = cir.bit_reverse %0 : !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_UIntOfWidths<[8, 16, 32, 64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_UIntOfWidths<[8, 16, 32, 64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.blockaddress\",\n    \"summary\": \"Get the address of a cir.label within a function\",\n    \"description\": \"The `cir.blockaddress` operation takes a function name and a label and\\n    produces a pointer value that represents the address of that cir.label within\\n    the specified function.\\n\\n    This operation models GCC's \\\"labels as values\\\" extension (`&&label`), which\\n    allows taking the address of a local label and using it as a computed\\n    jump target (e.g., with `goto *addr;`).\\n\\n    Example:\\n    ```mlir\\n    %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, [\\\"ptr\\\", init] {alignment = 8 : i64}\\n    %addr = cir.blockaddress(\\\"foo\\\", \\\"label\\\") -> !cir.ptr<!cir.void>\\n    cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>\\n    cir.br ^bb1\\n   ^bb1:\\n    cir.label \\\"label\\\"\\n    ```\",\n    \"results\": [\n      { \"name\": \"addr\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blockAddrInfo\", \"type\": \"CIR_BlockAddrInfoAttr\" }\n    ],\n    \"assemblyFormat\": \"$blockAddrInfo `->` qualified(type($addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.br\",\n    \"summary\": \"Unconditional branch\",\n    \"description\": \"The `cir.br` branches unconditionally to a block. Used to represent C/C++\\n    goto's and general block branching.\\n\\n    Note that for source level `goto`'s crossing scope boundaries, those are\\n    usually represented with the \\\"symbolic\\\" `cir.goto` operation.\\n\\n    Example:\\n\\n    ```mlir\\n      ...\\n        cir.br ^bb3\\n      ^bb3:\\n        cir.return\\n    ```\",\n    \"operands\": [\n      { \"name\": \"destOperands\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"cir.brcond\",\n    \"summary\": \"Conditional branch\",\n    \"description\": \"The `cir.brcond %cond, ^bb0, ^bb1` branches to 'bb0' block in case\\n    %cond (which must be a !cir.bool type) evaluates to true, otherwise\\n    it branches to 'bb1'.\\n\\n    Example:\\n\\n    ```mlir\\n      ...\\n        cir.brcond %a, ^bb3, ^bb4\\n      ^bb3:\\n        cir.return\\n      ^bb4:\\n        cir.yield\\n    ```\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"CIR_BoolType\" },\n      { \"name\": \"destOperandsTrue\", \"type\": \"Variadic<CIR_AnyType>\" },\n      { \"name\": \"destOperandsFalse\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"destTrue\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"destFalse\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$cond\\n    $destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?\\n    `,`\\n    $destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.break\",\n    \"summary\": \"C/C++ `break` statement equivalent\",\n    \"description\": \"The `cir.break` operation is used to cease the control flow to the parent\\n    operation, exiting its region's control flow. It is only allowed if it is\\n    within a breakable operation (loops and `switch`).\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"cir.byte_swap\",\n    \"summary\": \"Reverse the bytes that constitute the operand integer\",\n    \"description\": \"The `cir.byte_swap` operation takes an integer as operand, and returns it\\n    with the order of bytes that constitute the operand reversed.\\n\\n    The operand integer must be an unsigned integer. Its widths must be either\\n    16, 32, or 64.\\n\\n    Example:\\n\\n    ```mlir\\n    !u32i = !cir.int<u, 32>\\n\\n    // %0 = 0x12345678\\n    %0 = cir.const #cir.int<305419896> : !u32i\\n\\n    // %1 should be 0x78563412\\n    %1 = cir.byte_swap(%0 : !u32i) : !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_UIntOfWidths<[16, 32, 64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.call\",\n    \"summary\": \"call operation\",\n    \"description\": \"Direct and indirect calls.\\n\\n    For direct calls, the `call` operation represents a direct call to a\\n    function that is within the same symbol scope as the call. The operands\\n    and result types of the call must match the specified function type.\\n    The callee is encoded as a aymbol reference attribute named \\\"callee\\\".\\n\\n    For indirect calls, the first `mlir::Operation` operand is the call target.\\n\\n    Given the way indirect calls are encoded, avoid using `mlir::Operation`\\n    methods to walk the operands for this operation, instead use the methods\\n    provided by `CIRCallOpInterface`.\\n\\n    If the `cir.call` has the `exception` keyword, the call can throw. In this\\n    case, cleanups can be added in the `cleanup` region.\\n\\n    Example:\\n\\n    ```mlir\\n    // Direct call\\n    %2 = cir.call @my_add(%0, %1) : (f32, f32) -> f32\\n     ...\\n    // Indirect call\\n    %20 = cir.call %18(%17)\\n     ...\\n    // Call that might throw\\n    cir.call exception @my_div() -> () cleanup {\\n      // call dtor...\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg_ops\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exception\", \"type\": \"UnitAttr\" },\n      { \"name\": \"callee\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"calling_conv\", \"type\": \"DefaultValuedAttr<CIR_CallingConv{c|spir_kernel|spir_function|opencl_kernel|ptx_kernel|amdgpu_kernel}, CallingConv::C>\" },\n      { \"name\": \"side_effect\", \"type\": \"DefaultValuedAttr<CIR_SideEffect{all|pure|const}, SideEffect::All>\" },\n      { \"name\": \"extra_attrs\", \"type\": \"CIR_ExtraFuncAttr\" },\n      { \"name\": \"ast\", \"type\": \"OptionalAttr<ASTCallExprInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cleanup\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"cir.case\",\n    \"summary\": \"Case operation\",\n    \"description\": \"The `cir.case` operation represents a case within a C/C++ switch.\\n    The `cir.case` operation must be in a `cir.switch` operation directly or indirectly.\\n\\n    The `cir.case` have 4 kinds:\\n    - `equal, <constant>`: equality of the second case operand against the\\n    condition.\\n    - `anyof, [constant-list]`: equals to any of the values in a subsequent\\n    following list.\\n    - `range, [lower-bound, upper-bound]`: the condition is within the closed interval.\\n    - `default`: any other value.\\n\\n    Each case region must be explicitly terminated.\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"kind\", \"type\": \"CIR_CaseOpKind{default|equal|anyof|range}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"caseRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,` $value `)` $caseRegion attr-dict\"\n  },\n  {\n    \"name\": \"cir.cast\",\n    \"summary\": \"Conversion between values of different types\",\n    \"description\": \"Apply the usual C/C++ conversion rules between values. This operation models\\n    a subset of conversions as defined in Clang's `OperationKinds.def`\\n    (`llvm-project/clang/include/clang/AST/OperationKinds.def`).\\n\\n    Note: not all conversions are implemented using `cir.cast`. For instance,\\n    lvalue-to-rvalue conversion is modeled as a `cir.load` instead.  Currently\\n    supported kinds:\\n\\n    - `bitcast`\\n    - `array_to_ptrdecay`\\n    - `member_ptr_to_bool\\n    - `int_to_ptr`\\n    - `ptr_to_int`\\n    - `ptr_to_bool`\\n    - `integral`\\n    - `int_to_bool`\\n    - `int_to_float`\\n    - `float_to_int`\\n    - `float_to_bool`\\n    - `bool_to_int`\\n    - `floating`\\n    - `float_to_complex`\\n    - `float_complex_to_real`\\n    - `float_complex_to_bool`\\n    - `float_complex`\\n    - `float_complex_to_int_complex`\\n    - `int_to_complex`\\n    - `int_complex_to_real`\\n    - `int_complex_to_bool`\\n    - `int_complex`\\n    - `int_complex_to_float_complex`\\n    - `address_space`\\n\\n    CIR also supports some additional conversions that are not part of the classic\\n    Clang codegen:\\n\\n    - `bool_to_float`\\n\\n    Example:\\n\\n    ```mlir\\n    %4 = cir.cast int_to_bool %3 : i32 -> !cir.bool\\n    ...\\n    %x = cir.cast array_to_ptrdecay %0 : !cir.ptr<!cir.array<i32 x 10>> -> !cir.ptr<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_CastKind{bitcast|array_to_ptrdecay|member_ptr_to_bool|int_to_ptr|ptr_to_int|ptr_to_bool|integral|int_to_bool|int_to_float|float_to_int|float_to_bool|bool_to_int|floating|float_to_complex|float_complex_to_real|float_complex_to_bool|float_complex|float_complex_to_int_complex|int_to_complex|int_complex_to_real|int_complex_to_bool|int_complex|int_complex_to_float_complex|address_space|bool_to_float}\" }\n    ],\n    \"assemblyFormat\": \"$kind $src `:` type($src) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.catch_param\",\n    \"summary\": \"Represents catch clause formal parameter\",\n    \"description\": \"The `cir.catch_param` can operate in two modes: within catch regions of\\n    `cir.try` or anywhere else with the `begin` or `end` markers. The `begin`\\n    version requires an exception pointer of `cir.ptr<!void>`.\\n\\n    Example:\\n    ```mlir\\n    // TBD\\n    ```\",\n    \"operands\": [\n      { \"name\": \"exception_ptr\", \"type\": \"Optional<CIR_VoidPtrType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"param\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"OptionalAttr<CIR_CatchParamKind{begin|end}>\" }\n    ],\n    \"assemblyFormat\": \"($kind^)?\\n    ($exception_ptr^)?\\n    (`->` qualified(type($param))^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.ceil\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.clear_cache\",\n    \"summary\": \"clear cache operation\",\n    \"description\": \"CIR representation for `__builtin___clear_cache`.\",\n    \"operands\": [\n      { \"name\": \"begin\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"end\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['begin', 'end']>\" }\n    ],\n    \"assemblyFormat\": \"$begin `:` qualified(type($begin)) `,`\\n    $end `,`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.clrsb\",\n    \"summary\": \"Get the number of leading redundant sign bits in the input\",\n    \"description\": \"Compute the number of leading redundant sign bits in the input integer.\\n\\n    The input integer must be a signed integer. The most significant bit of the\\n    input integer is the sign bit. The `cir.clrsb` operation returns the number\\n    of redundant sign bits in the input, that is, the number of bits following\\n    the most significant bit that are identical to it.\\n\\n    The bit width of the input integer must be either 32 or 64.\\n\\n    Examples:\\n\\n    ```mlir\\n    !s32i = !cir.int<s, 32>\\n\\n    // %0 = 0xDEADBEEF, 0b1101_1110_1010_1101_1011_1110_1110_1111\\n    %0 = cir.const #cir.int<3735928559> : !s32i\\n    // %1 will be 1 because there is 1 bit following the most significant bit\\n    // that is identical to it.\\n    %1 = cir.clrsb(%0 : !s32i) : !s32i\\n\\n    // %2 = 1, 0b0000_0000_0000_0000_0000_0000_0000_0001\\n    %2 = cir.const #cir.int<1> : !s32i\\n    // %3 will be 30\\n    %3 = cir.clrsb(%2 : !s32i) : !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_SIntOfWidths<[ 32, 64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_SIntOfWidths<[ 32, 64 ]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.clz\",\n    \"summary\": \"Get the number of leading 0-bits in the input\",\n    \"description\": \"Compute the number of leading 0-bits in the input.\\n\\n    The input integer must be an unsigned integer. The `cir.clz` operation\\n    returns the number of consecutive 0-bits at the most significant bit\\n    position in the input.\\n\\n    Zero_poison attribute means this operation invokes undefined behavior if the\\n    input value is 0.\\n\\n    Example:\\n\\n    ```mlir\\n    !u32i = !cir.int<u, 32>\\n\\n    // %0 = 0b0000_0000_0000_0000_0000_0000_0000_1000\\n    %0 = cir.const #cir.int<8> : !u32i\\n    // %1 will be 28\\n    %1 = cir.clz(%0 : !u32i) zero_poison : !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_UIntOfWidths<[ 16, 32, 64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_UIntOfWidths<[ 16, 32, 64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_zero_poison\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input (`zero_poison` $is_zero_poison^)?\\n    `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.cmp\",\n    \"summary\": \"Compare values two values and produce a boolean result\",\n    \"description\": \"`cir.cmp` compares two input operands of the same type and produces a\\n    `cir.bool` result. The kinds of comparison available are:\\n    [lt,le,gt,ge,eq,ne] for all types, and [fone,funo] for floating-point only.\\n\\n    ```mlir\\n    %7 = cir.cmp(gt, %1, %2) : i32, !cir.bool\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_CmpOpKind{lt|le|gt|ge|eq|ne|fone|funo}\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,` $lhs `,` $rhs  `)` `:` type($lhs) `,` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.cmp3way\",\n    \"summary\": \"Compare two values with C++ three-way comparison semantics\",\n    \"description\": \"The `cir.cmp3way` operation models the `<=>` operator in C++20. It takes two\\n    operands with the same type and produces a result indicating the ordering\\n    between the two input operands.\\n\\n    The result of the operation is a signed integer that indicates the ordering\\n    between the two input operands.\\n\\n    There are two kinds of ordering: strong ordering and partial ordering.\\n    Comparing different types of values yields different kinds of orderings.\\n    The `info` parameter gives the ordering kind and other necessary information\\n    about the comparison.\\n\\n    Example:\\n\\n    ```mlir\\n    !s32i = !cir.int<s, 32>\\n\\n    #cmp3way_strong = #cmp3way_info<strong, lt = -1, eq = 0, gt = 1>\\n    #cmp3way_partial = #cmp3way_info<strong, lt = -1, eq = 0, gt = 1, unordered = 2>\\n\\n    %0 = cir.const #cir.int<0> : !s32i\\n    %1 = cir.const #cir.int<1> : !s32i\\n    %2 = cir.cmp3way(%0 : !s32i, %1, #cmp3way_strong) : !s8i\\n\\n    %3 = cir.const #cir.fp<0.0> : !cir.float\\n    %4 = cir.const #cir.fp<1.0> : !cir.float\\n    %5 = cir.cmp3way(%3 : !cir.float, %4, #cmp3way_partial) : !s8i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnySIntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"info\", \"type\": \"CIR_CmpThreeWayInfoAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $lhs `:` type($lhs) `,` $rhs `,` qualified($info) `)`\\n    `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.complex.binop\",\n    \"summary\": \"Binary operations on operands of complex type\",\n    \"description\": \"The `cir.complex.binop` operation represents a binary operation on operands\\n    of C complex type (e.g. `float _Complex`). The operation can only represent\\n    binary multiplication or division on complex numbers; other binary\\n    operations, such as addition and subtraction, are represented by the\\n    `cir.binop` operation.\\n\\n    The operation requires two input operands and has one result. The types of\\n    all the operands and the result should be of the same `!cir.complex` type.\\n\\n    The operation also takes a `range` attribute that specifies the complex\\n    range of the binary operation.\\n\\n    Examples:\\n\\n    ```mlir\\n    %2 = cir.complex.binop add %0, %1 : !cir.complex<!cir.float>\\n    %2 = cir.complex.binop mul %0, %1 : !cir.complex<!cir.float>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_ComplexType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_ComplexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_ComplexType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_ComplexBinOpKind{mul|div}\" },\n      { \"name\": \"range\", \"type\": \"CIR_ComplexRangeKind{full|improved|promoted|basic}\" },\n      { \"name\": \"promoted\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$kind $lhs `,` $rhs `range` `(` $range `)` (`promoted` $promoted^)?\\n    `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.complex.create\",\n    \"summary\": \"Create a complex value from its real and imaginary parts\",\n    \"description\": \"`cir.complex.create` operation takes two operands that represent the real\\n    and imaginary part of a complex number, and yields the complex number.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = cir.const #cir.fp<1.000000e+00> : !cir.double\\n    %1 = cir.const #cir.fp<2.000000e+00> : !cir.double\\n    %2 = cir.complex.create %0, %1 : !cir.complex<!cir.double>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"real\", \"type\": \"CIR_AnyIntOrFloatType\" },\n      { \"name\": \"imag\", \"type\": \"CIR_AnyIntOrFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_ComplexType\" }\n    ],\n    \"assemblyFormat\": \"$real `,` $imag\\n    `:` qualified(type($real)) `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.complex.imag\",\n    \"summary\": \"Extract the imaginary part of a complex value\",\n    \"description\": \"`cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int`\\n    `!cir.bool` or `!cir.float`. If the operand is `!cir.complex`, the imag \\n    part of it will be returned, otherwise a zero value will be returned.   \\n\\n    Example:\\n\\n    ```mlir\\n    %imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float\\n    %imag = cir.complex.imag %scalar : !cir.float -> !cir.float\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"CIR_AnyComplexOrIntOrBoolOrFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyIntOrBoolOrFloatType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` qualified(type($operand)) `->` qualified(type($result))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.complex.imag_ptr\",\n    \"summary\": \"Derive a pointer to the imaginary part of a complex value\",\n    \"description\": \"`cir.complex.imag_ptr` operation takes a pointer operand that points to a\\n    complex value of type `!cir.complex` and yields a pointer to the imaginary\\n    part of the operand.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = cir.complex.imag_ptr %0 : !cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"CIR_PtrToComplexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PtrToIntOrFloatType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:`\\n    qualified(type($operand)) `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.complex.real\",\n    \"summary\": \"Extract the real part of a complex value\",\n    \"description\": \"`cir.complex.real` operation takes an operand of `!cir.complex`, `cir.int`, \\n    `!cir.bool` or `!cir.float`. If the operand is `!cir.complex`, the real \\n    part of it will be returned, otherwise the value returned unmodified.  \\n\\n    Example:\\n\\n    ```mlir\\n    %real = cir.complex.real %complex : !cir.complex<!cir.float> -> !cir.float\\n    %real = cir.complex.real %scalar  : !cir.float -> !cir.float\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"CIR_AnyComplexOrIntOrBoolOrFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyIntOrBoolOrFloatType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` qualified(type($operand)) `->` qualified(type($result))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.complex.real_ptr\",\n    \"summary\": \"Derive a pointer to the real part of a complex value\",\n    \"description\": \"`cir.complex.real_ptr` operation takes a pointer operand that points to a\\n    complex value of type `!cir.complex` and yields a pointer to the real part\\n    of the operand.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = cir.complex.real_ptr %0 : !cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"CIR_PtrToComplexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PtrToIntOrFloatType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:`\\n    qualified(type($operand)) `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.condition\",\n    \"summary\": \"Loop continuation condition.\",\n    \"description\": \"The `cir.condition` terminates conditional regions. It takes a single\\n    `cir.bool` operand and, depending on its value, may branch to different\\n    regions:\\n\\n     - When in the `cond` region of a `cir.loop`, it continues the loop\\n       if true, or exits it if false.\\n     - When in the `ready` region of a `cir.await`, it branches to the `resume`\\n       region when true, and to the `suspend` region when false.\\n\\n    Example:\\n\\n    ```mlir\\n    cir.loop for(cond : {\\n      cir.condition(%arg0) // Branches to `step` region or exits.\\n    }, step : {\\n      [...]\\n    }) {\\n      [...]\\n    }\\n\\n    cir.await(user, ready : {\\n      cir.condition(%arg0) // Branches to `resume` or `suspend` region.\\n    }, suspend : {\\n      [...]\\n    }, resume : {\\n      [...]\\n    },)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"assemblyFormat\": \"`(` $condition `)` attr-dict\"\n  },\n  {\n    \"name\": \"cir.const\",\n    \"summary\": \"Create a CIR constant from a literal attribute\",\n    \"description\": \"The `cir.const` operation turns a literal into an SSA value. The data is\\n    attached to the operation as an attribute.\\n\\n    ```mlir\\n      %0 = cir.const #cir.int<4> : !u32i\\n      %1 = cir.const #cir.fp<1.500000e+00> : !cir.float\\n      %2 = cir.const #cir.ptr<null> : !cir.ptr<!void>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"cir.continue\",\n    \"summary\": \"C/C++ `continue` statement equivalent\",\n    \"description\": \"The `cir.continue` operation is used to continue execution to the next\\n    iteration of a loop. It is only allowed within `cir.loop` regions.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"cir.copy\",\n    \"summary\": \"Copies contents from a CIR pointer to another\",\n    \"description\": \"Given two CIR pointers, `src` and `dst`, `cir.copy` will copy the memory\\n    pointed by `src` to the memory pointed by `dst`.\\n\\n    The amount of bytes copied is inferred from the pointee type. Naturally,\\n    the pointee type of both `src` and `dst` must match and must implement\\n    the `DataLayoutTypeInterface`.\\n\\n    Examples:\\n\\n    ```mlir\\n      // Copying contents from one record to another:\\n      cir.copy %0 to %1 : !cir.ptr<!record_ty>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"src\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<CIR_AnyTBAAAttr>\" }\n    ],\n    \"assemblyFormat\": \"$src `to` $dst (`volatile` $is_volatile^)?\\n                        attr-dict `:` qualified(type($dst))\\n                        (`tbaa` `(` $tbaa^ `)`)?\"\n  },\n  {\n    \"name\": \"cir.copysign\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.cos\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.ctz\",\n    \"summary\": \"Get the number of trailing 0-bits in the input\",\n    \"description\": \"Compute the number of trailing 0-bits in the input.\\n\\n    The input integer must be an unsigned integer. The `cir.ctz` operation\\n    returns the number of consecutive 0-bits at the least significant bit\\n    position in the input.\\n\\n    Zero_poison attribute means this operation invokes undefined behavior if the\\n    input value is 0.\\n\\n    Example:\\n\\n    ```mlir\\n    !s32i = !cir.int<s, 32>\\n    !u32i = !cir.int<u, 32>\\n\\n    // %0 = 0b1000\\n    %0 = cir.const #cir.int<8> : !u32i\\n    // %1 will be 3\\n    %1 = cir.ctz(%0 : !u32i) : !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_UIntOfWidths<[ 16, 32, 64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_UIntOfWidths<[ 16, 32, 64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_zero_poison\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input (`zero_poison` $is_zero_poison^)?\\n    `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.delete.array\",\n    \"summary\": \"Delete address representing an array\",\n    \"description\": \"`cir.delete.array` operation deletes an array. For example, `delete[] ptr;`\\n    will be translated to `cir.delete.array %ptr`.\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$address `:` type($address) attr-dict\"\n  },\n  {\n    \"name\": \"cir.derived_class_addr\",\n    \"summary\": \"Get the derived class address for a class/struct\",\n    \"description\": \"The `cir.derived_class_addr` operaration gets the address of a particular\\n    derived class given a non-virtual base class pointer. The offset in bytes\\n    of the base class must be passed in, similar to `cir.base_class_addr`, but\\n    going into the other direction (In the itanium ABI this means lowering to\\n    a negative offset).\\n\\n    The operation contains a flag for whether or not the operand may be nullptr.\\n    That depends on the context and cannot be known by the operation, and that\\n    information affects how the operation is lowered.\\n\\n    Example:\\n    ```c++\\n    class A { int a; };\\n    class B { int b;\\n    public:\\n        A *getAsA();\\n    };\\n    class X : public A, public B { int x; };\\n\\n    A *B::getAsA() {\\n      return static_cast<X*>(this);\\n    ```\\n\\n    leads to\\n    ```mlir\\n      %2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>\\n      %3 = cir.derived_class_addr %2 : !cir.ptr<!rec_B> nonnull [4] -> !cir.ptr<!rec_X>\\n      %4 = cir.base_class_addr %3 : !cir.ptr<!rec_X> [0] -> !cir.ptr<!rec_A>\\n      cir.return %4\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base_addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"derived_addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"IndexAttr\" },\n      { \"name\": \"assume_not_null\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$base_addr `:` qualified(type($base_addr))\\n      (`nonnull` $assume_not_null^)?\\n      ` ` `[` $offset `]` `->` qualified(type($derived_addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.derived_data_member\",\n    \"summary\": \"Cast a base class data member pointer to a derived class data member pointer\",\n    \"description\": \"The `cir.derived_data_member` operation casts a data member pointer of type\\n    `T Base::*` to a data member pointer of type `T Derived::*`, where `Base`\\n    is an accessible non-ambiguous non-virtual base class of `Derived`.\\n\\n    The `offset` parameter gives the offset in bytes of the `Base` base class\\n    subobject within a `Derived` object.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_DataMemberType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_DataMemberType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `:` qualified(type($src))\\n    ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.derived_method\",\n    \"summary\": \"Cast a base class pointer-to-member-function to a derived class\\n    pointer-to-member-function\",\n    \"description\": \"The `cir.derived_method` operation casts a pointer-to-member-function of\\n    type `Ret (Base::*)(Args)` to a pointer-to-member-function of type\\n    `Ret (Derived::*)(Args)`, where `Base` is a non-virtual base class of\\n    `Derived`.\\n\\n    The `offset` parameter gives the offset in bytes of the `Base` base class\\n    subobject within a `Derived` object.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = cir.derived_method %0 : !cir.method<!cir.func<(!s32i)> in !rec_Base> [16] -> !cir.method<!cir.func<(!s32i)> in !rec_Derived>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_MethodType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_MethodType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `:` qualified(type($src))\\n    ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.do\",\n    \"summary\": \"C/C++ do-while loop\",\n    \"description\": \"Represents a C/C++ do-while loop. Identical to `cir.while` but the\\n    condition is evaluated after the body.\\n\\n    Example:\\n\\n    ```mlir\\n    cir.do {\\n      cir.break\\n    ^bb2:\\n      cir.yield\\n    } while {\\n      cir.condition %cond : cir.bool\\n    }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"MinSizedRegion<1>\" },\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$body `while` $cond attr-dict\"\n  },\n  {\n    \"name\": \"cir.dyn_cast\",\n    \"summary\": \"Perform dynamic cast on record pointers\",\n    \"description\": \"The `cir.dyn_cast` operation models part of the semantics of the\\n    `dynamic_cast` operator in C++. It can be used to perform 3 kinds of casts\\n    on record pointers:\\n\\n    - Down-cast, which casts a base class pointer to a derived class pointer;\\n    - Side-cast, which casts a class pointer to a sibling class pointer;\\n    - Cast-to-complete, which casts a class pointer to a void pointer.\\n\\n    The input of the operation must be a record pointer. The result of the\\n    operation is either a record pointer or a void pointer.\\n\\n    The parameter `kind` specifies the semantics of this operation. If its value\\n    is `ptr`, then the operation models dynamic casts on pointers. Otherwise, if\\n    its value is `ref`, the operation models dynamic casts on references.\\n    Specifically:\\n\\n    - When the input pointer is a null pointer value:\\n      - If `kind` is `ref`, the operation will invoke undefined behavior. A\\n        sanitizer check will be emitted if sanitizer is on.\\n      - Otherwise, the operation will return a null pointer value as its result.\\n    - When the runtime type check fails:\\n      - If `kind` is `ref`, the operation will throw a `bad_cast` exception.\\n      - Otherwise, the operation will return a null pointer value as its result.\\n\\n    The `info` argument gives detailed information about the requested dynamic\\n    cast operation. It is an optional `#cir.dyn_cast_info` attribute that is\\n    only present when the operation models a down-cast or a side-cast.\\n\\n    The `relative_layout` argument specifies whether the Itanium C++ ABI vtable\\n    uses relative layout. It is only meaningful when the operation models a\\n    cast-to-complete operation.\\n\\n    Example:\\n\\n    ```mlir\\n    %res = cir.dyn_cast ptr %ptr: !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>\\n    %res = cir.dyn_cast ptr relative_layout %ptr: !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_PtrToRecordType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PtrToAnyOf<[CIR_VoidType, CIR_RecordType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_DynamicCastKind{ptr|ref}\" },\n      { \"name\": \"info\", \"type\": \"OptionalAttr<CIR_DynamicCastInfoAttr>\" },\n      { \"name\": \"relative_layout\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$kind (`relative_layout` $relative_layout^)? $src \\n    `:` qualified(type($src)) `->` qualified(type($result)) \\n    (qualified($info)^)? attr-dict\"\n  },\n  {\n    \"name\": \"cir.eh.inflight_exception\",\n    \"summary\": \"Materialize the catch clause formal parameter\",\n    \"description\": \"`cir.eh.inflight_exception` returns two values:\\n      - `exception_ptr`: The exception pointer for the inflight exception\\n      - `type_id`: pointer to the exception object\\n    This operation is expected to be the first one basic blocks on the\\n    exception path out of `cir.try_call` operations.\\n\\n    The `cleanup` attribute indicates that clean up code might run before the\\n    values produced by this operation are used to gather exception information.\\n    This helps CIR to pass down more accurate information for LLVM lowering\\n    to landingpads.\",\n    \"results\": [\n      { \"name\": \"exception_ptr\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"type_id\", \"type\": \"CIR_UInt32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cleanup\", \"type\": \"UnitAttr\" },\n      { \"name\": \"sym_type_list\", \"type\": \"OptionalAttr<TypedArrayAttrBase<FlatSymbolRefAttr>>\" }\n    ],\n    \"assemblyFormat\": \"(`cleanup` $cleanup^)?\\n    ($sym_type_list^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.eh.longjmp\",\n    \"summary\": \"CIR longjmp operation\",\n    \"description\": \"Restore the environment (e.g., stack pointer, instruction pointer,\\n    signal mask, and other registers) at the time of setjmp() call, by using\\n    the information saved in `env` by setjmp().\\n\\n    Examples:\\n    ```mlir\\n      cir.eh.longjmp %arg0 : !cir.ptr<!cir.void>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"env\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$env `:` qualified(type($env)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.eh.setjmp\",\n    \"summary\": \"CIR setjmp operation\",\n    \"description\": \"Saves call-site information (e.g., stack pointer, instruction\\n    pointer, signal mask, and other registers) in memory at `env` for use by longjmp(). In this case,\\n    setjmp() returns 0. Following a successful longjmp(), execution proceeds\\n    from cir.eh.setjmp with the operation yielding a non-zero value.\\n\\n    The presence of the `builtin` attribute refers to the setjmp() function; the lack of the attribute refers\\n    to the _setjmp() function.\\n\\n    Examples:\\n    ```mlir\\n      // Specify setjmp is builtin.\\n      %0 = cir.eh.setjmp builtin %arg0 : (!cir.ptr<!cir.void>) -> !s32i\\n\\n      // Specify setjmp is not builtin.\\n      %0 = cir.eh.setjmp %arg0 : (!cir.ptr<!cir.void>) -> !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"env\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"CIR_SInt32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_builtin\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`builtin` $is_builtin^)?\\n      $env `:` functional-type($env, results) attr-dict\"\n  },\n  {\n    \"name\": \"cir.eh.typeid\",\n    \"summary\": \"Compute exception type id from it's global type symbol\",\n    \"description\": \"Returns the exception type id for a given global symbol representing\\n    a type.\",\n    \"results\": [\n      { \"name\": \"type_id\", \"type\": \"CIR_UInt32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type_sym\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$type_sym attr-dict\"\n  },\n  {\n    \"name\": \"cir.exp\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.exp2\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.expect\",\n    \"summary\": \"Compute whether expression is likely to evaluate to a specified value\",\n    \"description\": \"Provides __builtin_expect functionality in Clang IR.\\n\\n    If $prob is not specified, then behaviour is same as __builtin_expect.\\n    If specified, then behaviour is same as __builtin_expect_with_probability,\\n    where probability = $prob.\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"CIR_AnyFundamentalIntType\" },\n      { \"name\": \"expected\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prob\", \"type\": \"OptionalAttr<F64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'val', 'expected']>\" }\n    ],\n    \"assemblyFormat\": \"`(` $val`,` $expected (`,` $prob^)? `)` `:` type($val) attr-dict\"\n  },\n  {\n    \"name\": \"cir.extract_member\",\n    \"summary\": \"Extract the value of a member of a record value\",\n    \"description\": \"The `cir.extract_member` operation extracts the value of a particular member\\n    from the input record. Unlike `cir.get_member` which derives pointers, this\\n    operation operates on values. It takes a value of record type, and extract\\n    the value of the specified record member from the input record value.\\n\\n    Currently `cir.extract_member` does not work on unions.\\n\\n    Example:\\n\\n    ```mlir\\n    // Suppose we have a record with multiple members.\\n    !s32i = !cir.int<s, 32>\\n    !s8i = !cir.int<s, 32>\\n    !record_ty = !cir.record<\\\"struct.Bar\\\" {!s32i, !s8i}>\\n\\n    // And suppose we have a value of the record type.\\n    %0 = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s8i}> : !record_ty\\n\\n    // Extract the value of the second member of the record.\\n    %1 = cir.extract_member %0[1] : !record_ty -> !s8i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"record\", \"type\": \"CIRRecordType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$record `[` $index `]` attr-dict\\n    `:` qualified(type($record)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"cir.fabs\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.ffs\",\n    \"summary\": \"Get the position of the least significant 1-bit of input\",\n    \"description\": \"Compute the position of the least significant 1-bit of the input.\\n\\n    The input integer must be a signed integer. The `cir.ffs` operation returns\\n    one plus the index of the least significant 1-bit of the input signed\\n    integer. As a special case, if the input integer is 0, `cir.ffs` returns 0.\\n\\n    Example:\\n\\n    ```mlir\\n    !s32i = !cir.int<s, 32>\\n\\n    // %0 = 0x0010_1000\\n    %0 = cir.const #cir.int<40> : !s32i\\n    // #1 will be 4 since the 4th least significant bit is 1.\\n    %1 = cir.ffs(%0 : !s32i) : !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_SIntOfWidths<[ 32, 64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_SIntOfWidths<[ 32, 64 ]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.floor\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.fmaximum\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.fmaxnum\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.fminimum\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.fminnum\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.fmod\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.for\",\n    \"summary\": \"C/C++ for loop counterpart\",\n    \"description\": \"Represents a C/C++ for loop. It consists of three regions:\\n\\n     - `cond`: single block region with the loop's condition. Should be\\n     terminated with a `cir.condition` operation.\\n     - `body`: contains the loop body and an arbitrary number of blocks.\\n     - `step`: single block region with the loop's step.\\n\\n    Example:\\n\\n    ```mlir\\n    cir.for cond {\\n      cir.condition(%val)\\n    } body {\\n      cir.break\\n    ^bb2:\\n      cir.yield\\n    } step {\\n      cir.yield\\n    }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body\", \"type\": \"MinSizedRegion<1>\" },\n      { \"name\": \"step\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`:` `cond` $cond\\n    `body` $body\\n    `step` $step\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.frame_address\",\n    \"summary\": \"The frame address of the current function, or of one of its callers\",\n    \"description\": \"Represents call to builtin function ` __builtin_frame_address` in CIR.\\n    This builtin function returns the frame address of the current function,\\n    or of one of its callers. The frame is the area on the stack that holds\\n    local variables and saved registers. The frame address is normally the\\n    address of the first word pushed on to the stack by the function.\\n    However, the exact definition depends upon the processor and the calling\\n    convention. If the processor has a dedicated frame pointer register, and\\n    the function has a frame, then __builtin_frame_address returns the value of\\n    the frame pointer register.\\n\\n    The `level` argument is number of frames to scan up the call stack.\\n    For instance, value of 0 yields the frame address of the current function,\\n    value of 1 yields the frame address of the caller of the current function,\\n    and so forth.\\n\\n    Examples:\\n\\n    ```mlir\\n    %p = frame_address(%level) -> !cir.ptr<!void>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"level\", \"type\": \"CIR_UInt32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"assemblyFormat\": \"`(` $level `)` attr-dict\"\n  },\n  {\n    \"name\": \"cir.free.exception\",\n    \"summary\": \"Frees an exception according to Itanium ABI\",\n    \"description\": \"Implements a slightly higher level version of:\\n    `void __cxa_free_exception(void *thrown_exception);`\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = cir.alloc.exception 16 -> !cir.ptr<!some_record>\\n    %1 = cir.get_global @d2 : !cir.ptr<!some_record>\\n    cir.try synthetic cleanup {\\n      cir.call exception @_ZN7test2_DC1ERKS_(%0, %1) : (!cir.ptr<!some_record>, !cir.ptr<!some_record>) -> () cleanup {\\n        %2 = cir.cast bitcast %0 : !cir.ptr<!some_record> -> !cir.ptr<!void>\\n        cir.free.exception %2\\n        cir.yield\\n      }\\n      ...\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict\"\n  },\n  {\n    \"name\": \"cir.func\",\n    \"summary\": \"Declare or define a function\",\n    \"description\": \"Similar to `mlir::FuncOp` built-in:\\n    > Operations within the function cannot implicitly capture values defined\\n    > outside of the function, i.e. Functions are `IsolatedFromAbove`. All\\n    > external references must use function arguments or attributes that establish\\n    > a symbolic connection (e.g. symbols referenced by name via a string\\n    > attribute like SymbolRefAttr). An external function declaration (used when\\n    > referring to a function declared in some other module) has no body. While\\n    > the MLIR textual form provides a nice inline syntax for function arguments,\\n    > they are internally represented as “block arguments” to the first block in\\n    > the region.\\n    >\\n    > Only dialect attribute names may be specified in the attribute dictionaries\\n    > for function arguments, results, or the function itself.\\n\\n    The function linkage information is specified by `linkage`, as defined by\\n    `GlobalLinkageKind` attribute.\\n\\n    The `calling_conv` attribute specifies the calling convention of the function.\\n    The default calling convention is `CallingConv::C`.\\n\\n    A compiler builtin function must be marked as `builtin` for further\\n    processing when lowering from CIR.\\n\\n    The `coroutine` keyword is used to mark coroutine function, which requires\\n    at least one `cir.await` instruction to be used in its body.\\n\\n    The `lambda` translates to a C++ `operator()` that implements a lambda, this\\n    allow callsites to make certain assumptions about the real function nature\\n    when writing analysis. The verifier should, but do act on this keyword yet.\\n\\n    The `no_proto` keyword is used to identify functions that were declared\\n    without a prototype and, consequently, may contain calls with invalid\\n    arguments and undefined behavior.\\n\\n    The `extra_attrs`, which is an aggregate of function-specific attributes is\\n    required and mandatory to describle additional attributes that are not listed\\n    above. Though mandatory, the prining of the attribute can be omitted if it is\\n    empty.\\n\\n    The `global_ctor` indicates whether a function should execute before `main()`\\n    function, as specified by `__attribute__((constructor))`. A execution priority\\n    can also be specified `global_ctor(<prio>)`. Similarly, for global destructors\\n    both `global_dtor` and `global_dtor(<prio>)` are available.\\n\\n    Example:\\n\\n    ```mlir\\n    // External function definitions.\\n    cir.func @abort()\\n\\n    // A function with internal linkage.\\n    cir.func internal @count(%x: i64) -> (i64)\\n      return %x : i64\\n    }\\n\\n    // Linkage information\\n    cir.func linkonce_odr @some_method(...)\\n\\n    // Calling convention information\\n    cir.func @another_func(...) cc(spir_kernel) extra(#fn_attr)\\n\\n    // Builtin function\\n    cir.func builtin @__builtin_coro_end(!cir.ptr<i8>, !cir.bool) -> !cir.bool\\n\\n    // Coroutine\\n    cir.func coroutine @_Z10silly_taskv() -> !CoroTask {\\n      ...\\n      cir.await(...)\\n      ...\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"global_visibility\", \"type\": \"CIR_VisibilityAttr{default|hidden|protected}\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<CIR_FuncType>\" },\n      { \"name\": \"builtin\", \"type\": \"UnitAttr\" },\n      { \"name\": \"coroutine\", \"type\": \"UnitAttr\" },\n      { \"name\": \"inline_kind\", \"type\": \"OptionalAttr<CIR_InlineKind{no_inline|always_inline|inline_hint}>\" },\n      { \"name\": \"lambda\", \"type\": \"UnitAttr\" },\n      { \"name\": \"no_proto\", \"type\": \"UnitAttr\" },\n      { \"name\": \"opt_none\", \"type\": \"UnitAttr\" },\n      { \"name\": \"cold\", \"type\": \"UnitAttr\" },\n      { \"name\": \"dso_local\", \"type\": \"UnitAttr\" },\n      { \"name\": \"linkage\", \"type\": \"DefaultValuedAttr<CIR_GlobalLinkageKind{external|available_externally|linkonce|linkonce_odr|weak|weak_odr|appending|internal|cir_private|extern_weak|common}, GlobalLinkageKind::ExternalLinkage>\" },\n      { \"name\": \"calling_conv\", \"type\": \"DefaultValuedAttr<CIR_CallingConv{c|spir_kernel|spir_function|opencl_kernel|ptx_kernel|amdgpu_kernel}, CallingConv::C>\" },\n      { \"name\": \"extra_attrs\", \"type\": \"CIR_ExtraFuncAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"comdat\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"aliasee\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"global_ctor_priority\", \"type\": \"CIR_OptionalPriorityAttr\" },\n      { \"name\": \"global_dtor_priority\", \"type\": \"CIR_OptionalPriorityAttr\" },\n      { \"name\": \"annotations\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"cxx_special_member\", \"type\": \"OptionalAttr<CIR_CXXSpecialMemberAttr>\" },\n      { \"name\": \"ast\", \"type\": \"OptionalAttr<AnyASTFunctionDeclAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"cir.get_bitfield\",\n    \"summary\": \"Get a bitfield\",\n    \"description\": \"The `cir.get_bitfield` operation provides a load-like access to\\n    a bit field of a record.\\n\\n    It expects a name if a bit field, a pointer to a storage in the\\n    base record, a type of the storage, a name of the bitfield,\\n    a size the bit field, an offset of the bit field and a sign.\\n\\n    A unit attribute `volatile` can be used to indicate a volatile load of the\\n    bitfield.\\n\\n    Example:\\n    Suppose we have a struct with multiple bitfields stored in\\n    different storages. The `cir.get_bitfield` operation gets the value\\n    of the bitfield\\n    ```C++\\n    typedef struct {\\n      int a : 4;\\n      int b : 27;\\n      int c : 17;\\n      int d : 2;\\n      int e : 15;\\n    } S;\\n\\n    int load_bitfield(S& s) {\\n      return s.d;\\n    }\\n    ```\\n\\n    ```mlir\\n    // 'd' is in the storage with the index 1\\n    !record_type = !cir.record<struct \\\"S\\\" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>\\n    #bfi_d = #cir.bitfield_info<name = \\\"d\\\", storage_type = !u32i, size = 2, offset = 17, is_signed = true>\\n\\n    %2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>\\n    %3 = cir.get_member %2[1] {name = \\\"d\\\"} : !cir.ptr<!record_type> -> !cir.ptr<!u32i>\\n    %4 = cir.get_bitfield align(4) (#bfi_d, %3 : !cir.ptr<!u32i>) -> !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bitfield_info\", \"type\": \"CIR_BitfieldInfoAttr\" },\n      { \"name\": \"alignment\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`align` `(` $alignment^ `)`)?\\n    `(`$bitfield_info `,` $addr attr-dict `:`\\n    qualified(type($addr)) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"cir.get_element\",\n    \"summary\": \"Get the address of an array element\",\n    \"description\": \"The `cir.get_element` operation gets the address of a particular element\\n    from the `base` array.\\n\\n    It expects a pointer to the `base` array and the `index` of the element.\\n\\n    Example:\\n    ```mlir\\n    // Suppose we have a array.\\n    !s32i = !cir.int<s, 32>\\n    !arr_ty = !cir.array<!s32i x 4>\\n\\n    // Get the address of the element at index 1.\\n    %elem_1 = cir.get_element %0[1] : (!cir.ptr<!array_ty>, !s32i) -> !cir.ptr<!s32i>\\n\\n    // Get the address of the element at index %i.\\n    %i = ...\\n    %elem_i = cir.get_element %0[%i] : (!cir.ptr<!array_ty>, !s32i) -> !cir.ptr<!s32i>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"CIR_PtrToArray\" },\n      { \"name\": \"index\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $index `]` `:` `(` qualified(type($base)) `,` qualified(type($index)) `)`\\n    `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.get_global\",\n    \"summary\": \"Get the address of a global variable\",\n    \"description\": \"The `cir.get_global` operation retrieves the address pointing to a\\n    named global variable. If the global variable is marked constant, writing\\n    to the resulting address (such as through a `cir.store` operation) is\\n    undefined. Resulting type must always be a `!cir.ptr<...>` type with the\\n    same address space as the global variable.\\n\\n    Addresses of thread local globals can only be retrieved if this operation\\n    is marked `thread_local`, which indicates the address isn't constant.\\n\\n    Example:\\n    ```mlir\\n    %x = cir.get_global @foo : !cir.ptr<i32>\\n    ...\\n    %y = cir.get_global thread_local @batata : !cir.ptr<i32>\\n    ...\\n    cir.global external addrspace(offload_global) @gv = #cir.int<0> : !s32i\\n    %z = cir.get_global @gv : !cir.ptr<!s32i, addrspace(offload_global)>\\n    ```\",\n    \"results\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"tls\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`thread_local` $tls^)?\\n    $name `:` qualified(type($addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.get_member\",\n    \"summary\": \"Get the address of a member of a record\",\n    \"description\": \"The `cir.get_member` operation gets the address of a particular named\\n    member from the input record.\\n\\n    It expects a pointer to the base record as well as the name of the member\\n    and its field index.\\n\\n    Example:\\n    ```mlir\\n    // Suppose we have a record with multiple members.\\n    !s32i = !cir.int<s, 32>\\n    !s8i = !cir.int<s, 32>\\n    !record_ty = !cir.record<\\\"struct.Bar\\\" {!s32i, !s8i}>\\n\\n    // Get the address of the member at index 1.\\n    %1 = cir.get_member %0[1] {name = \\\"i\\\"} : (!cir.ptr<!record_ty>) -> !cir.ptr<!s8i>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$addr `[` $index `]` attr-dict\\n    `:` qualified(type($addr)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"cir.get_method\",\n    \"summary\": \"Resolve a method to a function pointer as callee\",\n    \"description\": \"The `cir.get_method` operation takes a method and an object as input, and\\n    yields a function pointer that points to the actual function corresponding\\n    to the input method. The operation also applies any necessary adjustments to\\n    the input object pointer for calling the method and yields the adjusted\\n    pointer.\\n\\n    This operation is generated when calling a method through a pointer-to-\\n    member-function in C++:\\n\\n    ```cpp\\n    // Foo *object;\\n    // int arg;\\n    // void (Foo::*method)(int);\\n\\n    (object->*method)(arg);\\n    ```\\n\\n    The code above will generate CIR similar as:\\n\\n    ```mlir\\n    // %object = ...\\n    // %arg = ...\\n    // %method = ...\\n    %callee, %this = cir.get_method %method, %object\\n    cir.call %callee(%this, %arg)\\n    ```\\n\\n    The method type must match the callee type. That is:\\n    - The return type of the method must match the return type of the callee.\\n    - The first parameter of the callee must have type `!cir.ptr<!cir.void>`.\\n    - Types of other parameters of the callee must match the parameters of the\\n      method.\",\n    \"operands\": [\n      { \"name\": \"method\", \"type\": \"CIR_MethodType\" },\n      { \"name\": \"object\", \"type\": \"CIR_PtrToRecordType\" }\n    ],\n    \"results\": [\n      { \"name\": \"callee\", \"type\": \"CIR_PtrToFunc\" },\n      { \"name\": \"adjusted_this\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"assemblyFormat\": \"$method `,` $object\\n    `:` `(` qualified(type($method)) `,` qualified(type($object)) `)`\\n    `->` `(` qualified(type($callee)) `,` qualified(type($adjusted_this)) `)`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.get_runtime_member\",\n    \"summary\": \"Get the address of a member of a record\",\n    \"description\": \"The `cir.get_runtime_member` operation gets the address of a member from\\n    the input record. The target member is given by a value of type\\n    `!cir.data_member` (i.e. a pointer-to-data-member value).\\n\\n    This operation differs from `cir.get_member` in when the target member can\\n    be determined. For the `cir.get_member` operation, the target member is\\n    specified as a constant index so the member it returns access to is known\\n    when the operation is constructed. For the `cir.get_runtime_member`\\n    operation, the target member is given through a pointer-to-data-member\\n    value which is unknown until the program being compiled is executed. In\\n    other words, `cir.get_member` represents a normal member access through the\\n    `.` operator in C/C++:\\n\\n    ```cpp\\n    struct Foo { int x; };\\n    Foo f;\\n    (void)f.x;  // cir.get_member\\n    ```\\n\\n    And `cir.get_runtime_member` represents a member access through the `.*` or\\n    the `->*` operator in C++:\\n\\n    ```cpp\\n    struct Foo { int x; }\\n    Foo f;\\n    Foo *p;\\n    int Foo::*member;\\n\\n    (void)f.*member;   // cir.get_runtime_member\\n    (void)f->*member;  // cir.get_runtime_member\\n    ```\\n\\n    This operation expects a pointer to the base record as well as the pointer\\n    to the target member.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PtrToRecordType\" },\n      { \"name\": \"member\", \"type\": \"CIR_DataMemberType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$addr `[` $member `:` qualified(type($member)) `]` attr-dict\\n    `:` qualified(type($addr)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"cir.global\",\n    \"summary\": \"Declares or defines a global variable\",\n    \"description\": \"The `cir.global` operation declares or defines a named global variable.\\n\\n    The backing memory for the variable is allocated statically and is\\n    described by the type of the variable.\\n\\n    The operation is a declaration if no `inital_value` is\\n    specified, else it is a definition.\\n\\n    The global variable can also be marked constant using the\\n    `constant` unit attribute. Writing to such constant global variables is\\n    undefined.\\n\\n    The `linkage` tracks C/C++ linkage types, currently very similar to LLVM's.\\n    Symbol visibility in `sym_visibility` is defined in terms of MLIR's visibility\\n    and verified to be in accordance to `linkage`.\\n\\n    `visibility_attr` is defined in terms of CIR's visibility.\\n\\n    Example:\\n\\n    ```mlir\\n    // Public and constant variable with initial value.\\n    cir.global public constant @c : i32 = 4;\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"global_visibility\", \"type\": \"DefaultValuedAttr<CIR_VisibilityAttr{default|hidden|protected}, VisibilityKind::Default>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"linkage\", \"type\": \"CIR_GlobalLinkageKind{external|available_externally|linkonce|linkonce_odr|weak|weak_odr|appending|internal|cir_private|extern_weak|common}\" },\n      { \"name\": \"addr_space\", \"type\": \"OptionalAttr<MemorySpaceAttrInterface>\" },\n      { \"name\": \"tls_model\", \"type\": \"OptionalAttr<CIR_TLSModel{tls_dyn|tls_local_dyn|tls_init_exec|tls_local_exec}>\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"comdat\", \"type\": \"UnitAttr\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"dso_local\", \"type\": \"UnitAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"ast\", \"type\": \"OptionalAttr<ASTVarDeclInterface>\" },\n      { \"name\": \"section\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"annotations\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"ctorRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"dtorRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"($sym_visibility^)?\\n       (`` $global_visibility^)?\\n       (`constant` $constant^)?\\n       $linkage\\n       (`comdat` $comdat^)?\\n       ($tls_model^)?\\n       (`dso_local` $dso_local^)?\\n       (` ` custom<GlobalAddressSpaceValue>($addr_space)^ )?\\n       $sym_name\\n       custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value, $ctorRegion, $dtorRegion)\\n       ($annotations^)?\\n       attr-dict\"\n  },\n  {\n    \"name\": \"cir.goto\",\n    \"description\": \"Transfers control to the specified `label`. This requires a corresponding\\n  `cir.label` to exist and is used by to represent source level `goto`s\\n  that jump across region boundaries. Alternatively, `cir.br` is used to\\n  construct goto's that don't violate such boundaries.\\n\\n  `cir.goto` is completely symbolic (i.e. it \\\"jumps\\\" on a label that isn't\\n  yet materialized) and should be taken into account by passes and analysis\\n  when deciding if it's safe to make some assumptions about a given region\\n  or basic block.\\n\\n  Example:\\n  ```C++\\n    int test(int x) {\\n      if (x)\\n        goto label;\\n      {\\n        x = 10;\\n    label:\\n        return x;\\n      }\\n    }\\n  ```\\n\\n  ```mlir\\n    cir.scope {  // REGION #1\\n      %2 = cir.load %0 : !cir.ptr<!s32i>, !s32i\\n      %3 = cir.cast int_to_bool %2 : !s32i -> !cir.bool\\n      cir.if %3 {\\n        cir.goto \\\"label\\\"\\n      }\\n      }\\n      cir.scope {  // REGION #2\\n        %2 = cir.const #cir.int<10> : !s32i\\n        cir.store %2, %0 : !s32i, !cir.ptr<!s32i>\\n        cir.br ^bb1\\n      ^bb1:  // pred: ^bb0\\n        cir.label \\\"label\\\"\\n        %3 = cir.load %0 : !cir.ptr<!s32i>, !s32i\\n        cir.store %3, %1 : !s32i, !cir.ptr<!s32i>\\n        %4 = cir.load %1 : !cir.ptr<!s32i>, !s32i\\n        cir.return %4 : !s32i\\n      }\\n      cir.unreachable\\n  ```\",\n    \"attributes\": [\n      { \"name\": \"label\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$label attr-dict\"\n  },\n  {\n    \"name\": \"cir.if\",\n    \"summary\": \"The if-then-else operation\",\n    \"description\": \"The `cir.if` operation represents an if-then-else construct for\\n    conditionally executing two regions of code. The operand is a `cir.bool`\\n    type.\\n\\n    Examples:\\n\\n    ```mlir\\n    cir.if %b  {\\n      ...\\n    } else {\\n      ...\\n    }\\n\\n    cir.if %c  {\\n      ...\\n    }\\n\\n    cir.if %c  {\\n      ...\\n      cir.br ^a\\n    ^a:\\n      cir.yield\\n    }\\n    ```\\n\\n    `cir.if` defines no values and the 'else' can be omitted. The if/else\\n    regions must be terminated. If the region has only one block, the terminator\\n    can be left out, and `cir.yield` terminator will be inserted implictly.\\n    Otherwise, the region must be explicitly terminated.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"elseRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"cir.indirectbr\",\n    \"summary\": \"Indirect branch\",\n    \"description\": \"The `cir.indirectbr` operation represents an indirect branch to one of\\n    several possible successor blocks. The target block is computed from\\n    the value of the given address operand.\\n\\n    This operation is typically generated when handling constructs like\\n    the GCC extension `&&label` combined with an indirect `goto *ptr;`.\\n\\n    The `poison` attribute is used to mark an `indirectbr` that was created\\n    but is known to be invalid — for instance, when a label address was\\n    taken but no indirect branch was ever emitted.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, [\\\"ptr\\\", init]\\n      %1 = cir.blockaddress <@A, \\\"A\\\"> -> !cir.ptr<!void>\\n      cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>\\n      %2 = cir.load align(8) %0 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>\\n      cir.br ^bb1(%2 : !cir.ptr<!void>)\\n    ^bb1(%3: !cir.ptr<!void>):\\n      cir.indirectbr %3 : <!void>, [\\n      ^bb2\\n      ]\\n    ```\\n    or with a poison:\\n\\n    ```mlir\\n      cir.indirectbr %0 poison : <!void>, [\\n      ^bb3,\\n      ^bb2\\n      ]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"succOperands\", \"type\": \"VariadicOfVariadic<AnyType, indbr_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"poison\", \"type\": \"UnitAttr\" },\n      { \"name\": \"indbr_operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"successors\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"$addr ( `poison` $poison^ )? `:` type($addr) `,`\\n    custom<IndirectBrOpSucessors>(ref(type($addr)),\\n                                  $successors,\\n                                  $succOperands,\\n                                  type($succOperands))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.insert_member\",\n    \"summary\": \"Overwrite the value of a member of a record value\",\n    \"description\": \"The `cir.insert_member` operation overwrites the value of a particular\\n    member in the input record value, and returns the modified record value. The\\n    result of this operation is equal to the input record value, except for the\\n    member specified by `index_attr` whose value is equal to the given value.\\n\\n    This operation is named after the LLVM instruction `insertvalue`.\\n\\n    Currently `cir.insert_member` does not work on unions.\\n\\n    Example:\\n\\n    ```mlir\\n    // Suppose we have a record with multiple members.\\n    !s32i = !cir.int<s, 32>\\n    !s8i = !cir.int<s, 32>\\n    !record_ty = !cir.record<\\\"struct.Bar\\\" {!s32i, !s8i}>\\n\\n    // And suppose we have a value of the record type.\\n    %0 = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s8i}> : !record_ty\\n    // %0 is {1, 2}\\n\\n    // Overwrite the second member of the record value.\\n    %1 = cir.const #cir.int<3> : !s8i\\n    %2 = cir.insert_member %0[1], %1 : !record_ty, !s8i\\n    // %2 is {1, 3}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"record\", \"type\": \"CIRRecordType\" },\n      { \"name\": \"value\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIRRecordType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['record', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$record `[` $index `]` `,` $value attr-dict\\n    `:` qualified(type($record)) `,` qualified(type($value))\"\n  },\n  {\n    \"name\": \"cir.invariant_group\",\n    \"summary\": \"Start an invariant group\",\n    \"description\": \"The `cir.invariant_group` operation takes a single pointer value as argument\\n    and returns the same pointer value with fresh [invariant group] information.\\n    All loads and stores that access the returned pointer value are presumed by\\n    the optimizer to load or store the same value.\\n\\n    [invariant group]: https://llvm.org/docs/LangRef.html#invariant-group-metadata\\n\\n    This operation is not emitted during CIRGen. Instead, it is created when\\n    hoisting constant alloca operations to the entry block of a function. This\\n    operation effectively marks the syntactic scope of the constant local\\n    variable represented by the hosited alloca operation, and it allows for\\n    better LLVMIR generation with potentially more optimizations.\\n\\n    For example, if we have the following CIR before alloca hoisting:\\n\\n    ```mlir\\n    cir.func @foo() {\\n      cir.scope {\\n        %0 = cir.alloca !s32i : !cir.ptr<!s32i>\\n        use(%0)\\n      }\\n    }\\n    ```\\n\\n    After alloca hoisting:\\n\\n    ```mlir\\n    cir.func @foo() {\\n      %0 = cir.alloca !s32i : !cir.ptr<!s32i>\\n      cir.scope {\\n        %1 = cir.invariant_group %0 : !cir.ptr<!s32i>\\n        use(%1)\\n      }\\n    }\\n    ```\\n\\n    During LLVMIR lowering, load and store operations whose pointer operand\\n    comes from `cir.invariant_group` are lowered to corresponding LLVM\\n    instructions with invariant group metadata attached.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$ptr `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.is_constant\",\n    \"description\": \"Returns `true` if the argument is known to be a compile-time constant\\n    otherwise returns 'false'.\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"assemblyFormat\": \"`(` $val `:` type($val) `)` `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.is_fp_class\",\n    \"summary\": \"Corresponding to the `__builtin_fpclassify` builtin function in clang\",\n    \"description\": \"The `cir.is_fp_class` operation takes a floating-point value as its first\\n    argument and a bitfield of flags as its second argument. The operation\\n    returns a boolean value indicating whether the floating-point value\\n    satisfies the given flags.\\n\\n    The flags must be a compile time constant and the values are:\\n\\n    | Bit # | floating-point class |\\n    | -------- | ------- |\\n    | 0 | Signaling NaN      |\\n    | 1 | Quiet NaN          |\\n    | 2 | Negative infinity  |\\n    | 3 | Negative normal    |\\n    | 4 | Negative subnormal |\\n    | 5 | Negative zero      |\\n    | 6 | Positive zero      |\\n    | 7 | Positive subnormal |\\n    | 8 | Positive normal    |\\n    | 9 | Positive infinity  |\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $flags `:` functional-type($src, $result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.label\",\n    \"description\": \"An identifier which may be referred by cir.goto operation\",\n    \"attributes\": [\n      { \"name\": \"label\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$label attr-dict\"\n  },\n  {\n    \"name\": \"cir.libc.memchr\",\n    \"summary\": \"libc's `memchr`\",\n    \"description\": \"Search for `pattern` in data range from `src` to `src` + `len`.\\n    provides a bound to the search in `src`. `result` is a pointer to found\\n    `pattern` or a null pointer.\\n\\n    Examples:\\n\\n    ```mlir\\n    %p = cir.libc.memchr(%src, %pattern, %len) -> !cir.ptr<!void>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"pattern\", \"type\": \"CIR_SInt32\" },\n      { \"name\": \"len\", \"type\": \"CIR_UInt64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"assemblyFormat\": \"`(`\\n      $src `,` $pattern `,` $len `)` attr-dict\"\n  },\n  {\n    \"name\": \"cir.libc.memcpy\",\n    \"summary\": \"Equivalent to libc's `memcpy`\",\n    \"description\": \"Given two CIR pointers, `src` and `dst`, `cir.libc.memcpy` will copy `len`\\n    bytes from the memory pointed by `src` to the memory pointed by `dst`.\\n\\n    While `cir.copy` is meant to be used for implicit copies in the code where\\n    the length of the copy is known, `cir.memcpy` copies only from and to void\\n    pointers, requiring the copy length to be passed as an argument.\\n\\n    Examples:\\n\\n    ```mlir\\n      // Copying 2 bytes from one array to a record:\\n      %2 = cir.const #cir.int<2> : !u32i\\n      cir.libc.memcpy %2 bytes from %arr to %record : !cir.ptr<!arr> -> !cir.ptr<!record>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"src\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"len\", \"type\": \"CIR_AnyFundamentalUIntType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dst', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$len `bytes` `from` $src `to` $dst attr-dict\\n    `:` type($len) `` `,` qualified(type($src)) `->` qualified(type($dst))\"\n  },\n  {\n    \"name\": \"cir.libc.memmove\",\n    \"summary\": \"Equivalent to libc's `memmove`\",\n    \"description\": \"Given two CIR pointers, `src` and `dst`, `cir.libc.memmove` will copy `len`\\n    bytes from the memory pointed by `src` to the memory pointed by `dst`.\\n\\n    similiar to `cir.libc.memcpy` but accounts for overlapping memory.\\n\\n    Examples:\\n\\n    ```mlir\\n      // Copying 2 bytes from one array to a record:\\n      %2 = cir.const #cir.int<2> : !u32i\\n      cir.libc.memmove %2 bytes from %arr to %record : !cir.ptr<!void>, !u64i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"src\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"len\", \"type\": \"CIR_AnyFundamentalUIntType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dst', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$len `bytes` `from` $src `to` $dst attr-dict\\n    `:` qualified(type($dst)) `,` type($len)\"\n  },\n  {\n    \"name\": \"cir.libc.memset\",\n    \"summary\": \"Equivalent to libc's `memset`\",\n    \"description\": \"Given the CIR pointer, `dst`, `cir.libc.memset` will set the first `len`\\n    bytes of the memory pointed by `dst` to the specified `val`.\\n\\n    Examples:\\n\\n    ```mlir\\n      // Set 2 bytes from a record to 0:\\n      %2 = cir.const #cir.int<2> : !u32i\\n      %3 = cir.const #cir.int<0> : !u32i\\n      %zero = cir.cast integral %3 : !s32i -> !u8i\\n      cir.libc.memset %2 bytes from %record set to %zero : !cir.ptr<!void>, !s32i, !u64i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"val\", \"type\": \"CIR_SInt32\" },\n      { \"name\": \"len\", \"type\": \"CIR_AnyFundamentalUIntType\" }\n    ],\n    \"assemblyFormat\": \"$len `bytes` `from` $dst `set` `to` $val attr-dict\\n    `:` qualified(type($dst)) `,` type($val) `,` type($len)\"\n  },\n  {\n    \"name\": \"cir.linker_options\",\n    \"summary\": \"Options to pass to the linker when the object file is linked\",\n    \"description\": \"Pass the given options to the linker when the resulting object file\\n    is linked.\\n    This is used extensively on Windows to determine the C runtime that the\\n    object files should link against.\\n\\n    Examples:\\n    ```mlir\\n    // Link against the MSVC static threaded CRT.\\n    cir.linker_options [\\\"/DEFAULTLIB:\\\", \\\"libcmt\\\"]\\n\\n    // Link against aarch64 compiler-rt builtins\\n    cir.linker_options [\\\"-l\\\", \\\"clang_rt.builtins-aarch64\\\"]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"options\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$options attr-dict\"\n  },\n  {\n    \"name\": \"cir.llrint\",\n    \"summary\": \"Builtin function that takes a floating-point value as input and produces an\\n    integral value as output.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.llround\",\n    \"summary\": \"Builtin function that takes a floating-point value as input and produces an\\n    integral value as output.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.llvm.intrinsic\",\n    \"summary\": \"Call to llvm intrinsic functions that is not defined in CIR\",\n    \"description\": \"`cir.llvm.intrinsic` operation represents a call-like expression which has\\n    return type and arguments that maps directly to a llvm intrinsic.\\n    It only records intrinsic `intrinsic_name`.\",\n    \"operands\": [\n      { \"name\": \"arg_ops\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"intrinsic_name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$intrinsic_name $arg_ops `:` functional-type($arg_ops, $result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.load\",\n    \"summary\": \"Load value from memory adddress\",\n    \"description\": \"`cir.load` reads a value (lvalue to rvalue conversion) given an address\\n    backed up by a `cir.ptr` type. A unit attribute `deref` can be used to\\n    mark the resulting value as used by another operation to dereference\\n    a pointer. A unit attribute `volatile` can be used to indicate a volatile\\n    loading. Load can be marked atomic by using `atomic(<mem_order>)`.\\n\\n    `align` can be used to specify an alignment that's different from the\\n    default, which is computed from `result`'s type ABI data layout.\\n\\n    Example:\\n\\n    ```mlir\\n\\n    // Read from local variable, address in %0.\\n    %1 = cir.load %0 : !cir.ptr<i32>, i32\\n\\n    // Load address from memory at address %0. %3 is used by at least one\\n    // operation that dereferences a pointer.\\n    %3 = cir.load deref %0 : !cir.ptr<!cir.ptr<i32>>\\n\\n    // Perform a volatile load from address in %0.\\n    %4 = cir.load volatile %0 : !cir.ptr<i32>, i32\\n\\n    // Others\\n    %x = cir.load align(16) syncscope(single_thread) atomic(seq_cst)\\n      %0 : !cir.ptr<i32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isDeref\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_nontemporal\", \"type\": \"UnitAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"sync_scope\", \"type\": \"OptionalAttr<CIR_SyncScopeKind{single_thread|system}>\" },\n      { \"name\": \"mem_order\", \"type\": \"OptionalAttr<CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<CIR_AnyTBAAAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'addr', 'result', 'mlir::cast<cir::PointerType>($_self).getPointee()'>\" }\n    ],\n    \"assemblyFormat\": \"(`deref` $isDeref^)?\\n    (`volatile` $is_volatile^)?\\n    (`nontemporal` $is_nontemporal^)?\\n    (`align` `(` $alignment^ `)`)?\\n    (`syncscope` `(` $sync_scope^ `)`)?\\n    (`atomic` `(` $mem_order^ `)`)?\\n    $addr `:` qualified(type($addr)) `,` type($result) attr-dict\\n    (`tbaa` `(` $tbaa^ `)`)?\"\n  },\n  {\n    \"name\": \"cir.log\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.log10\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.log2\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.lrint\",\n    \"summary\": \"Builtin function that takes a floating-point value as input and produces an\\n    integral value as output.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.lround\",\n    \"summary\": \"Builtin function that takes a floating-point value as input and produces an\\n    integral value as output.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.memcpy_inline\",\n    \"summary\": \"Memory copy with constant length without callingany external function\",\n    \"description\": \"Given two CIR pointers, `src` and `dst`, `memcpy_inline` will copy `len`\\n    bytes from the memory pointed by `src` to the memory pointed by `dst`.\\n\\n    Unlike `cir.libc.memcpy`,  this Op guarantees that no external functions\\n    are called, and length of copied bytes is a constant.\\n\\n    Examples:\\n\\n    ```mlir\\n      // Copying 2 bytes from one array to a record:\\n      cir.memcpy_inline 2 bytes from %arr to %record : !cir.ptr<!arr> -> !cir.ptr<!record>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"src\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"len\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dst', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$len `bytes` `from` $src `to` $dst attr-dict\\n    `:` qualified(type($src)) `->` qualified(type($dst))\"\n  },\n  {\n    \"name\": \"cir.memset_inline\",\n    \"summary\": \"Fill a block of memory with constant length without callingany external function\",\n    \"description\": \"Given the CIR pointer, `dst`, `cir.memset_inline` will set the first `len`\\n    bytes of the memory pointed by `dst` to the specified `val`.\\n\\n    The `len` argument must be a constant integer argument specifying the number\\n    of bytes to fill.\\n\\n    Examples:\\n\\n    ```mlir\\n      // Set 2 bytes from a record to 0\\n      cir.memset_inline 2 bytes from %record set to %zero : !cir.ptr<!void>, !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"val\", \"type\": \"CIR_SInt32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"len\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$len `bytes` `from` $dst `set` `to` $val attr-dict\\n    `:` qualified(type($dst)) `,` type($val)\"\n  },\n  {\n    \"name\": \"cir.nearbyint\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.objsize\",\n    \"summary\": \"Implements llvm.objsize builtin.\",\n    \"description\": \"The `cir.objsize` operation models the behavior of the `llvm.objectsize`\\n    builtins in Clang. It returns the number of accessible bytes past ptr.\\n\\n    The `kind` argument  determines whether `cir.objsize` returns 0 (if\\n    true) or -1 (if false) when the object size is unknown. Corresponds to \\n    `llvm.objectsize`'s `min` argument.\\n    \\n    The `dynamic` attribute determines if the value should be evaluated at\\n    runtime. Corresponds to `llvm.objectsize`'s `dynamic` argument.\\n\\n    Example:\\n\\n    ```mlir\\n    %size = cir.objsize min %ptr : !cir.ptr<i32> -> i64\\n    %dsize = cir.objsize max dynamic %ptr : !cir.ptr<i32> -> i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"UnitAttr\" },\n      { \"name\": \"dynamic\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`min` $min^) : (`max`)?\\n      (`dynamic` $dynamic^)?\\n      $ptr `:` qualified(type($ptr)) `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.parity\",\n    \"summary\": \"Get the parity of input\",\n    \"description\": \"Compute the parity of the input. The parity of an integer is the number of\\n    1-bits in it modulo 2.\\n\\n    The input must be an unsigned integer.\\n\\n    Example:\\n\\n    ```mlir\\n    !s32i = !cir.int<s, 32>\\n    !u32i = !cir.int<u, 32>\\n\\n    // %0 = 0x0110_1000\\n    %0 = cir.const #cir.int<104> : !u32i\\n    // %1 will be 1 since there are 3 1-bits in %0\\n    %1 = cir.parity(%0 : !u32i) : !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_UIntOfWidths<[ 32, 64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_UIntOfWidths<[ 32, 64 ]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.popcount\",\n    \"summary\": \"Get the number of 1-bits in input\",\n    \"description\": \"Compute the number of 1-bits in the input.\\n\\n    The input must be an unsigned integer.\\n\\n    Example:\\n\\n    ```mlir\\n    !u32i = !cir.int<u, 32>\\n\\n    // %0 = 0x0110_1000\\n    %0 = cir.const #cir.int<104> : !u32i\\n    // %1 will be 3 since there are 3 1-bits in %0\\n    %1 = cir.popcount(%0 : !u32i) : !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_UIntOfWidths<[ 16, 32, 64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_UIntOfWidths<[ 16, 32, 64 ]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.pow\",\n    \"summary\": \"libc builtin equivalent ignoring floating-point exceptions and errno.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `:` qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.prefetch\",\n    \"summary\": \"prefetch operation\",\n    \"description\": \"The `cir.prefetch` op prefetches data from the memmory address.\\n\\n    ```mlir\\n    cir.prefetch(%0 : !cir.ptr<!void>) locality(1) write\\n    ```\\n\\n    This opcode has the three attributes:\\n    1. The $locality is a temporal locality specifier\\n    ranging from (0) - no locality, to (3) - extremely local keep in cache.\\n    2. The $isWrite is the specifier determining if the prefetch is prepaired\\n    for a 'read' or 'write'.\\n    If $isWrite doesn't specified it means that prefetch is prepared for 'read'.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"locality\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>\" },\n      { \"name\": \"isWrite\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $addr `:` qualified(type($addr)) `)`\\n        `locality``(` $locality `)`\\n        (`write` $isWrite^) : (`read`)?\\n        attr-dict\"\n  },\n  {\n    \"name\": \"cir.ptr_diff\",\n    \"summary\": \"Pointer subtraction arithmetic\",\n    \"description\": \"The cir.ptr_diff operation computes the difference between two pointers that\\n    have the same element type\\n\\n    The result reflects the ABI-defined size of the pointed-to type. For example,\\n    subtracting two !cir.ptr<!u64i> values may yield 1, representing an 8-byte\\n    difference. In contrast, for pointers to void or function types, a result of\\n    8 corresponds to an 8-byte difference.\\n\\n    Example:\\n\\n    ```mlir\\n    %7 = cir.ptr_diff %0, %1 : !cir.ptr<!u64i> -> !u64i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs  `:` qualified(type($lhs)) `->` qualified(type($result)) \\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.ptr_mask\",\n    \"summary\": \"Masks out bits of the pointer according to a mask\",\n    \"description\": \"The `cir.ptr_mask` operation takes a pointer and an interger `mask` as its\\n    argument and return the masked pointer type according to the `mask`.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"mask\", \"type\": \"CIR_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['ptr', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`(` $ptr `,` $mask `:` type($mask) `)` `:` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.ptr_stride\",\n    \"summary\": \"Pointer access with stride\",\n    \"description\": \"The `cir.ptr_stride` operation computes a new pointer from a base pointer\\n    and an integer stride, similar to a single-index `getelementptr` in LLVM IR.\\n    It moves the pointer by `stride * sizeof(element_type)` bytes.\\n\\n    Optional no-wrap flags refine pointer arithmetic semantics, that mirror\\n    LLVM's GEP no-wrap semantics.\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = cir.ptr_stride %1, %2 : (!cir.ptr<i32>, i32) ->!cir.ptr<i32>\\n    %4 = cir.ptr_stride inbounds %1, %2 : (!cir.ptr<i32>, i32) -> !cir.ptr<i32>\\n    %5 = cir.ptr_stride inbounds|nuw %1, %2 : (!cir.ptr<i32>, i32) -> !cir.ptr<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"stride\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"noWrapFlags\", \"type\": \"CIR_GEPNoWrapFlagsProp{none|inbounds_flag|nusw|nuw|inbounds}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['base', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"($noWrapFlags^)? $base`,` $stride `:` functional-type(operands, results) \\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.resume\",\n    \"summary\": \"Resumes execution after not catching exceptions\",\n    \"description\": \"The `cir.resume` operation handles an uncaught exception scenario and\\n    behaves in two different modes:\\n\\n    - As the terminator of a `CatchUnwind` region of `cir.try`, where it\\n    does not receive any arguments (implied from the `cir.try` scope), or\\n    - The terminator of a regular basic block without an enclosing `cir.try`\\n    operation, where it requires an `exception_ptr` and a `type_id`.\\n\\n    The `rethrow` attribute is used to denote rethrowing behavior for the\\n    resume operation (versus default terminaton).\\n    ```\",\n    \"operands\": [\n      { \"name\": \"exception_ptr\", \"type\": \"Optional<CIR_VoidPtrType>\" },\n      { \"name\": \"type_id\", \"type\": \"Optional<CIR_UInt32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rethrow\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`rethrow` $rethrow^)?\\n    ($exception_ptr^ (`,` $type_id^)?)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.resume.flat\",\n    \"summary\": \"A flattened version of `cir.resume`\",\n    \"description\": \"The `cir.resume.flat` operation is a region-less and simplified\\n    version of the `cir.resume`.\\n\\n    Its representation is closer to LLVM IR dialect\\n    than the C/C++ language feature.\\n\\n    This operation is used only after the CFG flatterning pass.\\n\\n    Examples:\\n    ```mlir\\n    cir.resume.flat %exception_ptr, %type_id\\n    ```\",\n    \"operands\": [\n      { \"name\": \"exception_ptr\", \"type\": \"CIR_VoidPtrType\" },\n      { \"name\": \"type_id\", \"type\": \"CIR_UInt32\" }\n    ],\n    \"assemblyFormat\": \"$exception_ptr `,` $type_id\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.return\",\n    \"summary\": \"Return from function\",\n    \"description\": \"The \\\"return\\\" operation represents a return operation within a function.\\n    The operation takes an optional operand and produces no results.\\n    The operand type must match the signature of the function that contains\\n    the operation.\\n\\n    ```mlir\\n      func @foo() -> i32 {\\n        ...\\n        cir.return %0 : i32\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($input^ `:` type($input))? attr-dict\"\n  },\n  {\n    \"name\": \"cir.return_address\",\n    \"summary\": \"The return address of the current function, or of one of its callers\",\n    \"description\": \"Represents call to builtin function ` __builtin_return_address` in CIR.\\n    This builtin function returns the return address of the current function,\\n    or of one of its callers.\\n    The `level` argument is number of frames to scan up the call stack.\\n    For instance, value of 0 yields the return address of the current function,\\n    value of 1 yields the return address of the caller of the current function,\\n    and so forth.\\n\\n    Examples:\\n\\n    ```mlir\\n    %p = return_address(%level) -> !cir.ptr<!void>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"level\", \"type\": \"CIR_UInt32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VoidPtrType\" }\n    ],\n    \"assemblyFormat\": \"`(` $level `)` attr-dict\"\n  },\n  {\n    \"name\": \"cir.rint\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.rotate\",\n    \"summary\": \"Reverse the bytes that constitute the operand integer\",\n    \"description\": \"The `cir.rotate` rotates operand in `src` by the given bit amount `amt`.\\n    Its widths must be either 8, 16, 32, or 64 and both `src`, `amt` and\\n    `result` be of the same type. The rotate direction is specified by a\\n    `left`/`right` keyword.\\n\\n    This operation covers different C/C++\\n    builtins, some examples: `__builtin_rotateleft8`, `__builtin_rotateleft16`,\\n    `__builtin_rotateleft32`, `__builtin_rotateleft64`, `_rotl8`, `_rotl16`,\\n    `_rotl`, `_lrotl`, `_rotl64`, etc and their \\\"right\\\" variants.\\n\\n    Example:\\n\\n    ```mlir\\n    %r = cir.rotate left %0, %1 -> !u32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_IntType\" },\n      { \"name\": \"amt\", \"type\": \"CIR_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`left` $left^) : (`right`)?\\n    $src `,` $amt `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.round\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.roundeven\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.scope\",\n    \"summary\": \"Represents a C/C++ scope\",\n    \"description\": \"`cir.scope` contains one region and defines a strict \\\"scope\\\" for all new\\n    values produced within its blocks.\\n\\n    The region can contain an arbitrary number of blocks but usually defaults\\n    to one and can optionally return a value (useful for representing values\\n    coming out of C++ full-expressions) via `cir.yield`:\\n\\n\\n    ```mlir\\n    %rvalue = cir.scope {\\n      ...\\n      cir.yield %value\\n    }\\n    ```\\n\\n    The blocks can be terminated by `cir.yield`, `cir.return` or `cir.throw`.\\n    If `cir.scope` yields no value, the `cir.yield` can be left out, and\\n    will be inserted implicitly.\\n\\n    The scope might also have an associated `cleanup` region, providing code\\n    that run destruction of automatic variables. Note that in order to lower the\\n    cleanup region while keeping C++ semantics, all immediate control-flow\\n    breaking operations not under a children scope should jump to this cleanup\\n    code.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"scopeRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"cleanupRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"custom<OmittedTerminatorRegion>($scopeRegion, $cleanupRegion) (`:` type($results)^)? attr-dict\"\n  },\n  {\n    \"name\": \"cir.select\",\n    \"summary\": \"Yield one of two values based on a boolean value\",\n    \"description\": \"The `cir.select` operation takes three operands. The first operand\\n    `condition` is a boolean value of type `!cir.bool`. The second and the third\\n    operand can be of any CIR types, but their types must be the same. If the\\n    first operand is `true`, the operation yields its second operand. Otherwise,\\n    the operation yields its third operand.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = cir.const #cir.bool<true> : !cir.bool\\n    %1 = cir.const #cir.int<42> : !s32i\\n    %2 = cir.const #cir.int<72> : !s32i\\n    %3 = cir.select if %0 then %1 else %2 : (!cir.bool, !s32i, !s32i) -> !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"CIR_BoolType\" },\n      { \"name\": \"true_value\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"false_value\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`if` $condition `then` $true_value `else` $false_value\\n    `:` `(`\\n      qualified(type($condition)) `,`\\n      qualified(type($true_value)) `,`\\n      qualified(type($false_value))\\n    `)` `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.set_bitfield\",\n    \"summary\": \"Set a bitfield\",\n    \"description\": \"The `cir.set_bitfield` operation provides a store-like access to\\n    a bit field of a record.\\n\\n    It expects an address of a storage where to store, a type of the storage,\\n    a value being stored, a name of a bit field, a pointer to the storage in the\\n    base record, a size of the storage, a size the bit field, an offset\\n    of the bit field and a sign. Returns a value being stored.\\n\\n    A unit attribute `volatile` can be used to indicate a volatile load of the\\n    bitfield.\\n\\n    Example.\\n    Suppose we have a struct with multiple bitfields stored in\\n    different storages. The `cir.set_bitfield` operation sets the value\\n    of the bitfield.\\n    ```C++\\n    typedef struct {\\n      int a : 4;\\n      int b : 27;\\n      int c : 17;\\n      int d : 2;\\n      int e : 15;\\n    } S;\\n\\n    void store_bitfield(S& s) {\\n      s.d = 3;\\n    }\\n    ```\\n\\n    ```mlir\\n    // 'd' is in the storage with the index 1\\n    !record_type = !cir.record<struct \\\"S\\\" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>\\n    #bfi_d = #cir.bitfield_info<name = \\\"d\\\", storage_type = !u32i, size = 2, offset = 17, is_signed = true>\\n\\n    %1 = cir.const #cir.int<3> : !s32i\\n    %2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>\\n    %3 = cir.get_member %2[1] {name = \\\"d\\\"} : !cir.ptr<!record_type> -> !cir.ptr<!u32i>\\n    %4 = cir.set_bitfield align(4) (#bfi_d, %3 : !cir.ptr<!u32i>, %1 : !s32i) -> !s32i\\n    ```\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"src\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bitfield_info\", \"type\": \"CIR_BitfieldInfoAttr\" },\n      { \"name\": \"alignment\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`align` `(` $alignment^ `)`)?\\n    `(`$bitfield_info`,` $addr`:`qualified(type($addr))`,`\\n    $src`:`type($src) `)`  attr-dict `->` type($result)\"\n  },\n  {\n    \"name\": \"cir.shift\",\n    \"summary\": \"Shift\",\n    \"description\": \"Shift `left` or `right`, according to the first operand. Second operand is\\n    the shift target and the third the amount. Second and the thrid operand can\\n    be either integer type or vector of integer type. However, they must be\\n    either all vector of integer type, or all integer type. If they are vectors,\\n    each vector element of the shift target is shifted by the corresponding\\n    shift amount in the shift amount vector.\\n\\n    ```mlir\\n    %7 = cir.shift(left, %1 : !u64i, %4 : !s32i) -> !u64i\\n    %8 = cir.shift(left, %2 : !cir.vector<!s32i x 2>, %3 : !cir.vector<!s32i x 2>) -> !cir.vector<!s32i x 2>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"CIR_AnyIntOrVecOfIntType\" },\n      { \"name\": \"amount\", \"type\": \"CIR_AnyIntOrVecOfIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyIntOrVecOfIntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isShiftleft\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"`(`\\n      (`left` $isShiftleft^) : (```right`)?\\n      `,` $value `:` type($value)\\n      `,` $amount `:` type($amount)\\n    `)` `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.signbit\",\n    \"summary\": \"Checks the sign of a floating-point number\",\n    \"description\": \"It returns whether the sign bit (i.e. the highest bit) of the input operand\\n    is set.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_AnyFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"cir.sin\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.sqrt\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.stack_restore\",\n    \"summary\": \"restores the state of the function stack\",\n    \"description\": \"Restore the state of the function stack to the state it was\\n    in when the corresponding cir.stack_save executed.\\n    Useful for implementing language features like variable length arrays.\\n\\n    ```mlir\\n    %0 = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, [\\\"saved_stack\\\"] {alignment = 8 : i64}\\n    %1 = cir.stack_save : <!u8i>\\n    cir.store %1, %0 : !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>\\n    %2 = cir.load %0 : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>\\n    cir.stack_restore %2 : !cir.ptr<!u8i>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"cir.stack_save\",\n    \"summary\": \"remembers the current state of the function stack\",\n    \"description\": \"Remembers the current state of the function stack. Returns a pointer\\n    that later can be passed into cir.stack_restore.\\n    Useful for implementing language features like variable length arrays.\\n\\n    ```mlir\\n    %0 = cir.stack_save : <!u8i>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"cir.std.begin\",\n    \"summary\": \"std::begin()\",\n    \"operands\": [\n      { \"name\": \"container\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"original_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`(`  `,` $original_fn `)` `->` type($) attr-dict\"\n  },\n  {\n    \"name\": \"cir.std.end\",\n    \"summary\": \"std::end()\",\n    \"operands\": [\n      { \"name\": \"container\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"original_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`(`  `,` $original_fn `)` `->` type($) attr-dict\"\n  },\n  {\n    \"name\": \"cir.std.find\",\n    \"summary\": \"std::find()\",\n    \"operands\": [\n      { \"name\": \"first\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"last\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"pattern\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"original_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['first', 'last', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`(`  `,` $original_fn `)` `->` type($) attr-dict\"\n  },\n  {\n    \"name\": \"cir.std.strlen\",\n    \"summary\": \"std::strlen()\",\n    \"operands\": [\n      { \"name\": \"string\", \"type\": \"CIR_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"original_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`(`  `,` $original_fn `)` `->` type($) attr-dict\"\n  },\n  {\n    \"name\": \"cir.store\",\n    \"summary\": \"Store value to memory address\",\n    \"description\": \"`cir.store` stores a value (first operand) to the memory address specified\\n    in the second operand. A unit attribute `volatile` can be used to indicate\\n    a volatile store. Store's can be marked atomic by using\\n    `atomic(<mem_order>)`.\\n\\n    `align` can be used to specify an alignment that's different from the\\n    default, which is computed from `result`'s type ABI data layout.\\n\\n    Example:\\n\\n    ```mlir\\n    // Store a function argument to local storage, address in %0.\\n    cir.store %arg0, %0 : i32, !cir.ptr<i32>\\n\\n    // Perform a volatile store into memory location at the address in %0.\\n    cir.store volatile %arg0, %0 : i32, !cir.ptr<i32>\\n\\n    // Others\\n    cir.store align(16) atomic(seq_cst) %x, %addr : i32, !cir.ptr<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"CIR_AnyType\" },\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_volatile\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_nontemporal\", \"type\": \"UnitAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"mem_order\", \"type\": \"OptionalAttr<CIR_MemOrder{relaxed|consume|acquire|release|acq_rel|seq_cst}>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<CIR_AnyTBAAAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'addr', 'value', 'mlir::cast<cir::PointerType>($_self).getPointee()'>\" }\n    ],\n    \"assemblyFormat\": \"(`volatile` $is_volatile^)?\\n    (`nontemporal` $is_nontemporal^)?\\n    (`align` `(` $alignment^ `)`)?\\n    (`atomic` `(` $mem_order^ `)`)?\\n    $value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr))\\n    (`tbaa` `(` $tbaa^ `)`)?\"\n  },\n  {\n    \"name\": \"cir.switch\",\n    \"summary\": \"Switch operation\",\n    \"description\": \"The `cir.switch` operation represents C/C++ switch functionality for\\n    conditionally executing multiple regions of code. The operand to an switch\\n    is an integral condition value.\\n\\n    The set of `cir.case` operations and their enclosing `cir.switch`\\n    represents the semantics of a C/C++ switch statement. Users can use\\n    `collectCases(llvm::SmallVector<CaseOp> &cases)` to collect the `cir.case`\\n    operation in the `cir.switch` operation easily.\\n\\n    The `cir.case` operations doesn't have to be in the region of `cir.switch`\\n    directly. However, when all the `cir.case` operations lives in the region\\n    of `cir.switch` directly and there is no other operations except the ending\\n    `cir.yield` operation in the region of `cir.switch` directly, we call the\\n    `cir.switch` operation is in a simple form. Users can use\\n    `bool isSimpleForm(llvm::SmallVector<CaseOp> &cases)` member function to\\n    detect if the `cir.switch` operation is in a simple form. The simple form\\n    makes analysis easier to handle the `cir.switch` operation\\n    and makes the boundary to give up pretty clear.\\n\\n    To make the simple form as common as possible, CIR code generation attaches\\n    operations corresponding to the statements that lives between top level\\n    cases into the closest `cir.case` operation.\\n\\n    For example,\\n\\n    ```\\n    switch(int cond) {\\n      case 4:\\n        a++;\\n\\n      b++;\\n      case 5;\\n        c++;\\n\\n      ...\\n    }\\n    ```\\n\\n    The statement `b++` is not a sub-statement of the case statement `case 4`.\\n    But to make the generated `cir.switch` a simple form, we will attach the\\n    statement `b++` into the closest `cir.case` operation. So that the generated\\n    code will be like:\\n\\n    ```\\n    cir.switch(int cond) {\\n      cir.case(equal, 4) {\\n        a++;\\n        b++;\\n        cir.yield\\n      }\\n      cir.case(equal, 5) {\\n        c++;\\n        cir.yield\\n      }\\n      ...\\n    }\\n    ```\\n\\n    For the same reason, we will hoist the case statement as the substatement\\n    of another case statement so that they will be in the same level. For\\n    example,\\n\\n    ```\\n    switch(int cond) {\\n      case 4:\\n      default;\\n      case 5;\\n        a++;\\n      ...\\n    }\\n    ```\\n\\n    will be generated as\\n\\n    ```\\n    cir.switch(int cond) {\\n      cir.case(equal, 4) {\\n        cir.yield\\n      }\\n      cir.case(default) {\\n        cir.yield\\n      }\\n      cir.case(equal, 5) {\\n        a++;\\n        cir.yield\\n      }\\n      ...\\n    }\\n    ```\\n\\n    The cir.switch might not be considered \\\"simple\\\" if any of the following is\\n    true:\\n    - There are case statements of the switch statement lives in other scopes\\n      other than the top level compound statement scope. Note that a case\\n      statement itself doesn't form a scope.\\n    - The sub-statement of the switch statement is not a compound statement.\\n    - There are codes before the first case statement. For example,\\n\\n    ```\\n    switch(int cond) {\\n      l:\\n        b++;\\n\\n      case 4:\\n        a++;\\n        break;\\n\\n      case 5:\\n        goto l;\\n      ...\\n    }\\n    ```\\n\\n    the generated CIR for this non-simple switch would be:\\n\\n    ```\\n    cir.switch(int cond) {\\n      cir.label \\\"l\\\"\\n      b++;\\n      cir.case(4) {\\n        a++;\\n        cir.break\\n      }\\n      cir.case(5) {\\n        goto \\\"l\\\"\\n      }\\n      cir.yield\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"CIR_IntType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"custom<SwitchOp>(\\n      $body, $condition, type($condition)\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.switch.flat\",\n    \"summary\": \"A flattened version of cir.switch\",\n    \"description\": \"The `cir.switch.flat` operation is a region-less and simplified version of the `cir.switch`.\\n    It's representation is closer to LLVM IR dialect than the C/C++ language feature.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"CIR_IntType\" },\n      { \"name\": \"defaultOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"caseOperands\", \"type\": \"VariadicOfVariadic<AnyType, case_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"case_values\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"case_operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDestination\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"caseDestinations\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$condition `:` type($condition) `,`\\n    $defaultDestination (`(` $defaultOperands^ `:` type($defaultOperands) `)`)?\\n    custom<SwitchFlatOpCases>(ref(type($condition)), $case_values, $caseDestinations,\\n                                   $caseOperands, type($caseOperands))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.tan\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.ternary\",\n    \"summary\": \"The `cond ? a : b` C/C++ ternary operation\",\n    \"description\": \"The `cir.ternary` operation represents C/C++ ternary, much like a `select`\\n    operation. First argument is a `cir.bool` condition to evaluate, followed\\n    by two regions to execute (true or false). This is different from `cir.if`\\n    since each region is one block sized and the `cir.yield` closing the block\\n    scope should have one argument.\\n\\n    Example:\\n\\n    ```mlir\\n    // x = cond ? a : b;\\n\\n    %x = cir.ternary (%cond, true_region {\\n      ...\\n      cir.yield %a : i32\\n    }, false_region {\\n      ...\\n      cir.yield %b : i32\\n    }) -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"CIR_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"trueRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"falseRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`(` $cond `,`\\n      `true` $trueRegion `,`\\n      `false` $falseRegion\\n    `)` `:` functional-type(operands, results) attr-dict\"\n  },\n  {\n    \"name\": \"cir.throw\",\n    \"summary\": \"(Re)Throws an exception\",\n    \"description\": \"Very similar to __cxa_throw:\\n\\n    ```\\n    void __cxa_throw(void *thrown_exception, std::type_info *tinfo,\\n                     void (*dest) (void *));\\n    ```\\n\\n    The absense of arguments for `cir.throw` means it rethrows.\\n\\n    For the no-rethrow version, it must have at least two operands, the RTTI\\n    information, a pointer to the exception object (likely allocated via\\n    `cir.cxa.allocate_exception`) and finally an optional dtor, which might\\n    run as part of this operation.\\n\\n    ```mlir\\n      // if (b == 0)\\n      //   throw \\\"Division by zero condition!\\\";\\n      cir.if %10 {\\n        %11 = cir.alloc_exception 8 -> !cir.ptr<!void>\\n        ...\\n        cir.store %13, %11 : // Store string addr for \\\"Division by zero condition!\\\"\\n        cir.throw %11 : !cir.ptr<!cir.ptr<!u8i>>, @\\\"typeinfo for char const*\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"exception_ptr\", \"type\": \"Optional<CIR_PointerType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type_info\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"dtor\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" }\n    ],\n    \"assemblyFormat\": \"($exception_ptr^ `:` type($exception_ptr))?\\n    (`,` $type_info^)?\\n    (`,` $dtor^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.trap\",\n    \"summary\": \"Exit the program abnormally\",\n    \"description\": \"The cir.trap operation causes the program to exit abnormally. The\\n    implementations may implement this operation with different mechanisms. For\\n    example, an implementation may implement this operation by calling abort,\\n    while another implementation may implement this operation by executing an\\n    illegal instruction.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"cir.trunc\",\n    \"summary\": \"libc builtin equivalent ignoring floating point exceptions and errno\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyFloatOrVecOfFloatType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$src `:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"cir.try\",\n    \"summary\": \"C++ try block\",\n    \"description\": \"```mlir\\n\\n    Holds the lexical scope of `try {}`. Note that resources used on catch\\n    clauses are usually allocated in the same parent as `cir.try`.\\n\\n    `synthetic`: use `cir.try` to represent try/catches not originally\\n    present in the source code (e.g. `g = new Class` under `-fexceptions`).\\n\\n    `cleanup`: signal to targets (LLVM for now) that this try/catch, needs\\n    to specially tag their landing pads as needing \\\"cleanup\\\".\\n\\n    Example: TBD\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"synthetic\", \"type\": \"UnitAttr\" },\n      { \"name\": \"cleanup\", \"type\": \"UnitAttr\" },\n      { \"name\": \"catch_types\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"try_region\", \"type\": \"AnyRegion\" },\n      { \"name\": \"catch_regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"(`synthetic` $synthetic^)?\\n    (`cleanup` $cleanup^)?\\n    $try_region\\n    custom<CatchRegions>($catch_regions, $catch_types)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.try_call\",\n    \"summary\": \"try_call operation\",\n    \"description\": \"Mostly similar to cir.call but requires two destination\\n    branches, one for handling exceptions in case its thrown and\\n    the other one to follow on regular control-flow.\\n\\n    Example:\\n\\n    ```mlir\\n    // Direct call\\n    %2 = cir.try_call @my_add(%0, %1) ^continue, ^landing_pad : (f32, f32) -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"contOperands\", \"type\": \"Variadic<CIR_AnyType>\" },\n      { \"name\": \"landingPadOperands\", \"type\": \"Variadic<CIR_AnyType>\" },\n      { \"name\": \"arg_ops\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"calling_conv\", \"type\": \"DefaultValuedAttr<CIR_CallingConv{c|spir_kernel|spir_function|opencl_kernel|ptx_kernel|amdgpu_kernel}, CallingConv::C>\" },\n      { \"name\": \"side_effect\", \"type\": \"DefaultValuedAttr<CIR_SideEffect{all|pure|const}, SideEffect::All>\" },\n      { \"name\": \"extra_attrs\", \"type\": \"CIR_ExtraFuncAttr\" },\n      { \"name\": \"ast\", \"type\": \"OptionalAttr<ASTCallExprInterface>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"cont\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"landing_pad\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"cir.unary\",\n    \"summary\": \"Unary operations\",\n    \"description\": \"`cir.unary` performs the unary operation according to\\n    the specified opcode kind: [inc, dec, plus, minus, not].\\n\\n    It requires one input operand and has one result, both types\\n    should be the same.\\n\\n    ```mlir\\n    %7 = cir.unary(inc, %1) : i32 -> i32\\n    %8 = cir.unary(dec, %2) : i32 -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_UnaryOpKind{inc|dec|plus|minus|not}\" },\n      { \"name\": \"no_signed_wrap\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,` $input `)`\\n      (`nsw` $no_signed_wrap^)?\\n      `:` type($input) `,` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"cir.unreachable\",\n    \"summary\": \"invoke immediate undefined behavior\",\n    \"description\": \"If the program control flow reaches a `cir.unreachable` operation, the\\n    program exhibits undefined behavior immediately. This operation is useful\\n    in cases where the unreachability of a program point needs to be explicitly\\n    marked.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"cir.va.arg\",\n    \"summary\": \"Fetches next variadic element as a given type\",\n    \"operands\": [\n      { \"name\": \"arg_list\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_AnyType\" }\n    ],\n    \"assemblyFormat\": \"$arg_list attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"cir.va.copy\",\n    \"summary\": \"Copies a variable argument list\",\n    \"operands\": [\n      { \"name\": \"dst_list\", \"type\": \"CIR_PointerType\" },\n      { \"name\": \"src_list\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$src_list `to` $dst_list attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"cir.va.end\",\n    \"summary\": \"Ends a variable argument list\",\n    \"operands\": [\n      { \"name\": \"arg_list\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$arg_list attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"cir.va.start\",\n    \"summary\": \"Starts a variable argument list\",\n    \"operands\": [\n      { \"name\": \"arg_list\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"assemblyFormat\": \"$arg_list attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"cir.vec.cmp\",\n    \"summary\": \"Compare two vectors\",\n    \"description\": \"The `cir.vec.cmp` operation does an element-wise comparison of two vectors\\n    of the same type. The result is a vector of the same size as the operands\\n    whose element type is the signed integral type that is the same size as the\\n    element type of the operands.  The values in the result are 0 or -1.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"CIR_VectorType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"CIR_CmpOpKind{lt|le|gt|ge|eq|ne|fone|funo}\" }\n    ],\n    \"assemblyFormat\": \"`(` $kind `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`\\n    qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.vec.create\",\n    \"summary\": \"Create a vector value\",\n    \"description\": \"The `cir.vec.create` operation creates a vector value with the given element\\n    values. The number of element arguments must match the number of elements\\n    in the vector type.\",\n    \"operands\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<CIR_VectorElementType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"assemblyFormat\": \"`(` ($elements^ `:` type($elements))? `)` `:` qualified(type($result))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.vec.extract\",\n    \"summary\": \"Extract one element from a vector object\",\n    \"description\": \"The `cir.vec.extract` operation extracts the element at the given index\\n    from a vector object.\",\n    \"operands\": [\n      { \"name\": \"vec\", \"type\": \"CIR_VectorType\" },\n      { \"name\": \"index\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorElementType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'vec', 'result', 'mlir::cast<cir::VectorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$vec `[` $index `:` type($index) `]` attr-dict `:` qualified(type($vec))\"\n  },\n  {\n    \"name\": \"cir.vec.insert\",\n    \"summary\": \"Insert one element into a vector object\",\n    \"description\": \"The `cir.vec.insert` operation replaces the element of the given vector at\\n    the given index with the given value.  The new vector with the inserted\\n    element is returned.\",\n    \"operands\": [\n      { \"name\": \"vec\", \"type\": \"CIR_VectorType\" },\n      { \"name\": \"value\", \"type\": \"CIR_VectorElementType\" },\n      { \"name\": \"index\", \"type\": \"CIR_AnyFundamentalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'vec', 'value', 'mlir::cast<cir::VectorType>($_self).getElementType()'>\" },\n      { \"type\": \"AllTypesMatch<['result', 'vec']>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $vec `[` $index `:` type($index) `]` attr-dict `:`\\n    qualified(type($vec))\"\n  },\n  {\n    \"name\": \"cir.vec.shuffle\",\n    \"summary\": \"Combine two vectors using indices passed as constant integers\",\n    \"description\": \"The `cir.vec.shuffle` operation implements the documented form of Clang's\\n    __builtin_shufflevector, where the indices of the shuffled result are\\n    integer constants.\\n\\n    The two input vectors, which must have the same type, are concatenated.\\n    Each of the integer constant arguments is interpreted as an index into that\\n    concatenated vector, with a value of -1 meaning that the result value\\n    doesn't matter. The result vector, which must have the same element type as\\n    the input vectors and the same number of elements as the list of integer\\n    constant indices, is constructed by taking the elements at the given\\n    indices from the concatenated vector.  The size of the result vector does\\n    not have to match the size of the individual input vectors or of the\\n    concatenated vector.\",\n    \"operands\": [\n      { \"name\": \"vec1\", \"type\": \"CIR_VectorType\" },\n      { \"name\": \"vec2\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vec1', 'vec2']>\" }\n    ],\n    \"assemblyFormat\": \"`(` $vec1 `,` $vec2 `:` qualified(type($vec1)) `)` $indices `:`\\n     qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.vec.shuffle.dynamic\",\n    \"summary\": \"Shuffle a vector using indices in another vector\",\n    \"description\": \"The `cir.vec.shuffle.dynamic` operation implements the undocumented form of\\n    Clang's __builtin_shufflevector, where the indices of the shuffled result\\n    can be runtime values.\\n\\n    There are two input vectors, which must have the same number of elements.\\n    The second input vector must have an integral element type. The elements of\\n    the second vector are interpreted as indices into the first vector. The\\n    result vector is constructed by taking the elements from the first input\\n    vector from the indices indicated by the elements of the second vector.\",\n    \"operands\": [\n      { \"name\": \"vec\", \"type\": \"CIR_VectorType\" },\n      { \"name\": \"indices\", \"type\": \"CIR_VectorOfIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vec', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$vec `:` qualified(type($vec)) `,` $indices `:` qualified(type($indices))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"cir.vec.splat\",\n    \"summary\": \"Convert a scalar into a vector\",\n    \"description\": \"The `cir.vec.splat` operation creates a vector value from a scalar value.\\n    All elements of the vector have the same value, that of the given scalar.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"CIR_VectorElementType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'value', 'mlir::cast<cir::VectorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) `,` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.vec.ternary\",\n    \"summary\": \"The `cond ? a : b` ternary operator for vector types\",\n    \"description\": \"The `cir.vec.ternary` operation represents the C/C++ ternary operator,\\n    `?:`, for vector types, which does a `select` on individual elements of the\\n    vectors. Unlike a regular `?:` operator, there is no short circuiting. All\\n    three arguments are always evaluated.  Because there is no short\\n    circuiting, there are no regions in this operation, unlike cir.ternary.\\n\\n    The first argument is a vector of integral type. The second and third\\n    arguments are vectors of the same type and have the same number of elements\\n    as the first argument.\\n\\n    The result is a vector of the same type as the second and third arguments.\\n    Each element of the result is `(bool)a[n] ? b[n] : c[n]`.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"CIR_VectorOfIntType\" },\n      { \"name\": \"lhs\", \"type\": \"CIR_VectorType\" },\n      { \"name\": \"rhs\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_VectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"`(` $cond `,` $lhs `,` $rhs `)` `:` qualified(type($cond)) `,`\\n    qualified(type($lhs)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.vtable.address_point\",\n    \"summary\": \"Get the vtable (global variable) address point\",\n    \"description\": \"The `vtable.address_point` operation retrieves the \\\"effective\\\" address\\n    (address point) of a C++ virtual table. An object internal `__vptr`\\n    gets initializated on top of the value returned by this operation.\\n\\n    `address_point.index` (vtable index) provides the appropriate vtable within\\n    the vtable group (as specified by Itanium ABI), and `address_point.offset`\\n    (address point index) the actual address point within that vtable.\\n\\n    The `name` argument to this operation must be the name of a C++ vtable\\n    object. The return value is the address of the virtual function pointer\\n    array within the vtable (the vptr). This value will be written to the\\n    vptr member of a dynamic class by the constructor of the class. Derived\\n    classes have their own vtable, which is used to obtain the vptr stored\\n    in instances of the derived class.\\n\\n    The return type is always `!cir.vptr`.\\n\\n    Examples:\\n\\n    ```C++\\n    struct Base {\\n      Base();\\n      virtual void f();\\n    };\\n    struct Derived : public Base {\\n      Derived();\\n    };\\n    ```\\n\\n    ```mlir\\n    !rec_Base = !cir.record<struct \\\"Base\\\" {!cir.vptr}\\n    !rec_Derived = !cir.record<struct \\\"Derived\\\" {!rec_Base}\\n    ...\\n    // VTable for Base\\n    cir.global linkonce_odr @_ZTV1Base = ...\\n    ...\\n    // Constructor for Base\\n    cir.func dso_local @_ZN4BaseC2Ev ...\\n      ...\\n      %2 = cir.vtable.address_point(@_ZTV1Base,\\n              address_point = <index = 0, offset = 2>) : !cir.vptr\\n      %3 = cir.vtable.get_vptr %1 : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>\\n      cir.store align(8) %2, %3 : !cir.vptr, !cir.ptr<!cir.vptr>\\n    ...\\n    // VTable for Derived\\n    cir.global linkonce_odr @_ZTV7Derived = ...\\n    ...\\n    // Constructor for Derived\\n    cir.func dso_local @_ZN7DerivedC2Ev ...\\n      // Get the address of Base within this Derived instance\\n      %2 = cir.base_class_addr %1 : !cir.ptr<!rec_Derived> nonnull [0]\\n      cir.call @_ZN4BaseC2Ev(%2)\\n      %3 = cir.vtable.address_point(@_ZTV7Derived,\\n              address_point = <index = 0, offset = 2>) : !cir.vptr\\n      // The vptr is still at the start of the object in this case\\n      %4 = cir.vtable.get_vptr %1 : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>\\n      // This overwrites the vptr that was stored in the Base constructor call\\n      cir.store align(8) %3, %4 : !cir.vptr, !cir.ptr<!cir.vptr>\\n    ```\",\n    \"results\": [\n      { \"name\": \"addr\", \"type\": \"CIR_VPtrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"address_point\", \"type\": \"CIR_AddressPointAttr\" }\n    ],\n    \"assemblyFormat\": \"`(`\\n      $name `,` `address_point` `=` $address_point\\n    `)`\\n    `:` qualified(type($addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.vtable.get_virtual_fn_addr\",\n    \"summary\": \"Get a the address of a virtual function pointer\",\n    \"description\": \"The `vtable.get_virtual_fn_addr` operation retrieves the address of a\\n    virtual function pointer from an object's vtable (__vptr).\\n    This is an abstraction to perform the basic pointer arithmetic to get\\n    the address of the virtual function pointer, which can then be loaded and\\n    called.\\n\\n    The `vptr` operand must be a `!cir.ptr<!cir.vptr>` value, which would\\n    have been returned by a previous call to `cir.vatble.get_vptr`. The\\n    `index` operand is an index of the virtual function in the vtable.\\n\\n    The return type is a pointer-to-pointer to the function type.\\n\\n    Example 1:\\n    Suppose we have two classes, Base and Derived, where Derived overrides\\n    virtual functions that were defined in Base. When a pointer to a Base\\n    object is used to call one of these function, we may not know at compile\\n    time whether it points to an instance of Base or an instance of Derived.\\n    The compiler does not need to know. It will load the vptr from the object\\n    and use that to get the address of the correct function to call. The\\n    vptr will have been initialized in the object's constructor to point to\\n    the correct vtable for the object being instantiated.\\n    ```C++\\n    // In this example, when f3 is called, we don't know at compile-time\\n    // whether\\n    struct Base {\\n      virtual void f1();\\n      virtual void f2();\\n    };\\n    struct Derived : public Base {\\n      void f1() override;\\n      void f2() override;\\n    };\\n    void f3(Base *b) {\\n      b->f2();\\n    }\\n    ```\\n\\n    ```mlir\\n    // VTable for Base\\n    cir.global external @_ZTV4Base = #cir.vtable<{\\n      #cir.const_array<[\\n        #cir.ptr<null> : !cir.ptr<!u8i>,\\n        #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>,\\n        #cir.global_view<@_ZN4Base2f1Ev> : !cir.ptr<!u8i>,\\n        #cir.global_view<@_ZN4Base2f2Ev> : !cir.ptr<!u8i>\\n      ]> : !cir.array<!cir.ptr<!u8i> x 4>}> ...\\n    // VTable for Derived\\n    cir.global external @_ZTV7Derived = #cir.vtable<{\\n      #cir.const_array<[\\n        #cir.ptr<null> : !cir.ptr<!u8i>,\\n        #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>,\\n        #cir.global_view<@_ZN7Derived2f1Ev> : !cir.ptr<!u8i>,\\n        #cir.global_view<@_ZN7Derived2f2Ev> : !cir.ptr<!u8i>\\n      ]> : !cir.array<!cir.ptr<!u8i> x 4>}> ...\\n    // f3()\\n    cir.func dso_local @_Z2f3P4Base(%b: !cir.ptr<!rec_Base>)\\n      // Get the vptr\\n      %1 = cir.vtable.get_vptr %b : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>\\n      %2 = cir.load align(8) %1 : !cir.ptr<!cir.vptr>, !cir.vptr\\n      // Get the address of b->f2() -- may be Base::f2() or Derived::f2()\\n      %3 = cir.vtable.get_virtual_fn_addr %2[1] : !cir.vptr\\n              -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>\\n      %4 = cir.load align(8) %3\\n              : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>,\\n                !cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>\\n      cir.call %4(%b)\\n    ```\\n\\n    Example 2:\\n    Consider the case of multiple inheritance, where Base1 and Base2 both\\n    provide virtual functions and a third class, Derived, inherits from both\\n    bases. When a pointer to a Derived is used to call a virtual function in\\n    Base2, we must retrieve a pointer to the Base2 portion of the Derived object\\n    and use that pointer to get the vptr for Base2 as a base class.\\n    ```C++\\n    struct Base1 {\\n      virtual void f1();\\n    };\\n    struct Base2 {\\n      virtual void f2();\\n    };\\n    struct Derived : public Base1, Base2 { };\\n    void f3(Derived *d) {\\n      d->f2();\\n    }\\n    ```\\n\\n    ```mlir\\n    !rec_Base1 = !cir.record<struct \\\"Base1\\\" {!cir.vptr}\\n    !rec_Base2 = !cir.record<struct \\\"Base2\\\" {!cir.vptr}\\n    !rec_Derived = !cir.record<struct \\\"Derived\\\" {!rec_Base1, !rec_Base2}\\n    cir.func dso_local @_Z2f3P7Derived(%d: !cir.ptr<!rec_Derived>)\\n      %2 = cir.base_class_addr %d : !cir.ptr<!rec_Derived> nonnull [8]\\n              -> !cir.ptr<!rec_Base2>\\n      %3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_Base2> -> !cir.ptr<!cir.vptr>\\n      %4 = cir.load align(8) %3 : !cir.ptr<!cir.vptr>, !cir.vptr\\n      %5 = cir.vtable.get_virtual_fn_addr %4[0] : !cir.vptr\\n              -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>>\\n      %6 = cir.load align(8) %5\\n              : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>>,\\n                !cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>\\n      cir.call %6(%2) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>,\\n                         !cir.ptr<!rec_Base2>) -> ()\\n     ```\",\n    \"operands\": [\n      { \"name\": \"vptr\", \"type\": \"CIR_VPtrType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$vptr `[` $index `]` attr-dict\\n    `:` qualified(type($vptr)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"cir.vtable.get_vptr\",\n    \"summary\": \"Get a the address of the vtable pointer for an object\",\n    \"description\": \"The `vtable.get_vptr` operation retrieves the address of the vptr for a\\n    C++ object. This operation requires that the object pointer points to\\n    the start of a complete object. (TODO: Describe how we get that).\\n    The vptr will always be at offset zero in the object, but this operation\\n    is more explicit about what is being retrieved than a direct bitcast.\\n\\n    The return type is always `!cir.ptr<!cir.vptr>`.\\n\\n    Example:\\n    ```C++\\n    struct S {\\n      virtual void f1();\\n      virtual void f2();\\n    };\\n    void f3(S *s) {\\n      s->f2();\\n    }\\n    ```\\n\\n    ```mlir\\n    // VTable for S\\n    cir.global external @_ZTV1S = #cir.vtable<{\\n      #cir.const_array<[\\n        // Offset to the base object\\n        #cir.ptr<null> : !cir.ptr<!u8i>,\\n        // Type info for S\\n        #cir.global_view<@_ZTI1S> : !cir.ptr<!u8i>,\\n        // Pointer to S::f1\\n        #cir.global_view<@_ZN1S2f1Ev> : !cir.ptr<!u8i>,\\n        // Pointer to S::f2\\n        #cir.global_view<@_ZN1S2f2Ev> : !cir.ptr<!u8i>\\n      ]> : !cir.array<!cir.ptr<!u8i> x 4>}> ...\\n    // f3()\\n    cir.func dso_local @_Z2f3P1S(%s: !cir.ptr<!rec_S>) {\\n      // Get the vptr -- This points to offset 2 in the vtable.\\n      %1 = cir.vtable.get_vptr %s : !cir.ptr<!rec_S> -> !cir.ptr<!cir.vptr>\\n      %2 = cir.load align(8) %1 : !cir.ptr<!cir.vptr>, !cir.vptr\\n      // Get the address of b->f2() -- may be Base::f2() or Derived::f2()\\n      %3 = cir.vtable.get_virtual_fn_addr %2[1] : !cir.vptr\\n              -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>\\n      %4 = cir.load align(8) %3\\n              : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>,\\n                !cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>\\n      cir.call %4(%b)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CIR_PtrToVPtr\" }\n    ],\n    \"assemblyFormat\": \"$src `:` qualified(type($src)) `->` qualified(type($result)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.vtt.address_point\",\n    \"summary\": \"Get the VTT address point\",\n    \"description\": \"The `vtt.address_point` operation retrieves an element from the VTT,\\n    which is the address point of a C++ vtable. In virtual inheritance,\\n    A set of internal `__vptr` for an object are initialized by this operation,\\n    which assigns an element from the VTT. The initialization order is as follows:\\n\\n    The complete object constructors and destructors find the VTT,\\n    via the mangled name of VTT global variable. They pass the address of\\n    the subobject's sub-VTT entry in the VTT as a second parameter\\n    when calling the base object constructors and destructors.\\n    The base object constructors and destructors use the addresses passed to\\n    initialize the primary virtual pointer and virtual pointers that point to\\n    the classes which either have virtual bases or override virtual functions\\n    with a virtual step.\\n\\n    The first parameter is either the mangled name of VTT global variable\\n    or the address of the subobject's sub-VTT entry in the VTT.\\n    The second parameter `offset` provides a virtual step to adjust to\\n    the actual address point of the vtable.\\n\\n    The return type is always a `!cir.ptr<!cir.ptr<void>>`.\\n\\n    Example:\\n    ```mlir\\n    cir.global linkonce_odr @_ZTV1B = ...\\n    ...\\n    %3 = cir.base_class_addr(%1 : !cir.ptr<!rec_D> nonnull) [0] -> !cir.ptr<!rec_B>\\n    %4 = cir.vtt.address_point @_ZTT1D, offset = 1 -> !cir.ptr<!cir.ptr<!void>>\\n    cir.call @_ZN1BC2Ev(%3, %4)\\n    ```\\n    Or:\\n    ```mlir\\n    %7 = cir.vtt.address_point %3 : !cir.ptr<!cir.ptr<!void>>, offset = 1 -> !cir.ptr<!cir.ptr<!void>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sym_addr\", \"type\": \"Optional<CIR_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"addr\", \"type\": \"CIR_PointerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"offset\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"($name^)?\\n      ($sym_addr^ `:` type($sym_addr))?\\n      `,`\\n      `offset` `=` $offset\\n    `->` qualified(type($addr)) attr-dict\"\n  },\n  {\n    \"name\": \"cir.while\",\n    \"summary\": \"C/C++ while loop\",\n    \"description\": \"Represents a C/C++ while loop. It consists of two regions:\\n\\n     - `cond`: single block region with the loop's condition. Should be\\n     terminated with a `cir.condition` operation.\\n     - `body`: contains the loop body and an arbitrary number of blocks.\\n\\n    Example:\\n\\n    ```mlir\\n    cir.while {\\n      cir.break\\n    ^bb2:\\n      cir.yield\\n    } do {\\n      cir.condition %cond : cir.bool\\n    }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body\", \"type\": \"MinSizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$cond `do` $body attr-dict\"\n  },\n  {\n    \"name\": \"cir.yield\",\n    \"summary\": \"Represents the default branching behaviour of a region\",\n    \"description\": \"The `cir.yield` operation terminates regions on different CIR operations,\\n    and it is used to represent the default branching behaviour of a region.\\n    Said branching behaviour is determinted by the parent operation. For\\n    example, a yield in a `switch-case` region implies a fallthrough, while\\n    a yield in a `cir.if` region implies a branch to the exit block, and so\\n    on.\\n\\n    In some cases, it might yield an SSA value and the semantics of how the\\n    values are yielded is defined by the parent operation. For example, a\\n    `cir.ternary` operation yields a value from one of its regions.\\n\\n    As a general rule, `cir.yield` must be explicitly used whenever a region has\\n    more than one block and no terminator, or within `cir.switch` regions not\\n    `cir.return` terminated.\\n\\n    Examples:\\n    ```mlir\\n    cir.if %4 {\\n      ...\\n      cir.yield\\n    }\\n\\n    cir.switch (%5) [\\n      case (equal, 3) {\\n        ...\\n        cir.yield\\n      }, ...\\n    ]\\n\\n    cir.scope {\\n      ...\\n      cir.yield\\n    }\\n\\n    %x = cir.scope {\\n      ...\\n      cir.yield %val\\n    }\\n\\n    %y = cir.ternary {\\n      ...\\n      cir.yield %val : i32\\n    } : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<CIR_AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($args^ `:` type($args))? attr-dict\"\n  },\n  {\n    \"name\": \"complex.abs\",\n    \"summary\": \"computes absolute value of a complex number\",\n    \"description\": \"The `abs` op takes a single complex number and computes its absolute value.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.abs %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyFloat\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'complex', 'result', '::llvm::cast<ComplexType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.add\",\n    \"summary\": \"complex addition\",\n    \"description\": \"The `add` operation takes two complex numbers and returns their sum.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.add %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"complex.angle\",\n    \"summary\": \"computes argument value of a complex number\",\n    \"description\": \"The `angle` op takes a single complex number and computes its argument value with a branch cut along the negative real axis.\\n\\n    Example:\\n\\n    ```mlir\\n         %a = complex.angle %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyFloat\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'complex', 'result', '::llvm::cast<ComplexType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.atan2\",\n    \"summary\": \"complex 2-argument arctangent\",\n    \"description\": \"For complex numbers it is expressed using complex logarithm\\n    atan2(y, x) = -i * log((x + i * y) / sqrt(x**2 + y**2))\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.atan2 %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"complex.bitcast\",\n    \"summary\": \"computes bitcast between complex and equal arith types\",\n    \"description\": \"Example:\\n\\n    ```mlir\\n         %a = complex.bitcast %b : complex<f32> -> i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"complex.conj\",\n    \"summary\": \"Calculate the complex conjugate\",\n    \"description\": \"The `conj` op takes a single complex number and computes the\\n    complex conjugate.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.conj %b: complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.constant\",\n    \"summary\": \"complex number constant operation\",\n    \"description\": \"The `complex.constant` operation creates a constant complex number from an\\n    attribute containing the real and imaginary parts.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.constant [0.1, -1.0] : complex<f64>\\n    ```\",\n    \"results\": [\n      { \"name\": \"complex\", \"type\": \"AnyComplex\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.cos\",\n    \"summary\": \"computes cosine of a complex number\",\n    \"description\": \"The `cos` op takes a single complex number and computes the cosine of\\n    it, i.e. `cos(x)`, where `x` is the input value.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.cos %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.create\",\n    \"summary\": \"complex number creation operation\",\n    \"description\": \"The `complex.create` operation creates a complex number from two\\n    floating-point operands, the real and the imaginary part.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.create %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"real\", \"type\": \"AnyFloat\" },\n      { \"name\": \"imaginary\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['real', 'imaginary']>\" },\n      { \"type\": \"TypesMatchWith<'complex', 'real', '::llvm::cast<ComplexType>($_self).getElementType()'>\" },\n      { \"type\": \"TypesMatchWith<'complex', 'imaginary', '::llvm::cast<ComplexType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$real `,` $imaginary attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.div\",\n    \"summary\": \"complex division\",\n    \"description\": \"The `div` operation takes two complex numbers and returns result of their\\n    division:\\n\\n    ```mlir\\n    %a = complex.div %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"complex.eq\",\n    \"summary\": \"computes whether two complex values are equal\",\n    \"description\": \"The `eq` op takes two complex numbers and returns whether they are equal.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.eq %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs  attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"complex.exp\",\n    \"summary\": \"computes exponential of a complex number\",\n    \"description\": \"The `exp` op takes a single complex number and computes the exponential of\\n    it, i.e. `exp(x)` or `e^(x)`, where `x` is the input value.\\n    `e` denotes Euler's number and is approximately equal to 2.718281.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.exp %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.expm1\",\n    \"summary\": \"computes exponential of a complex number minus 1\",\n    \"description\": \"complex.expm1(x) := complex.exp(x) - 1\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.expm1 %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.im\",\n    \"summary\": \"extracts the imaginary part of a complex number\",\n    \"description\": \"The `im` op takes a single complex number and extracts the imaginary part.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.im %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"imaginary\", \"type\": \"AnyFloat\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'complex', 'imaginary', '::llvm::cast<ComplexType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.log\",\n    \"summary\": \"computes natural logarithm of a complex number\",\n    \"description\": \"The `log` op takes a single complex number and computes the natural\\n    logarithm of it, i.e. `log(x)` or `log_e(x)`, where `x` is the input value.\\n    `e` denotes Euler's number and is approximately equal to 2.718281.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.log %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.log1p\",\n    \"summary\": \"computes natural logarithm of a complex number\",\n    \"description\": \"The `log` op takes a single complex number and computes the natural\\n    logarithm of one plus the given value, i.e. `log(1 + x)` or `log_e(1 + x)`,\\n    where `x` is the input value. `e` denotes Euler's number and is\\n    approximately equal to 2.718281.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.log1p %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.mul\",\n    \"summary\": \"complex multiplication\",\n    \"description\": \"The `mul` operation takes two complex numbers and returns their product:\\n\\n    ```mlir\\n    %a = complex.mul %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"complex.neg\",\n    \"summary\": \"Negation operator\",\n    \"description\": \"The `neg` op takes a single complex number `complex` and returns `-complex`.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.neg %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.neq\",\n    \"summary\": \"computes whether two complex values are not equal\",\n    \"description\": \"The `neq` op takes two complex numbers and returns whether they are not\\n    equal.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.neq %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs  attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"complex.pow\",\n    \"summary\": \"complex power function\",\n    \"description\": \"The `pow` operation takes a complex number raises it to the given complex\\n    exponent.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.pow %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"complex.powi\",\n    \"summary\": \"complex number raised to signed integer power\",\n    \"description\": \"The `powi` operation takes a `base` operand of complex type and a `power`\\n    operand of signed integer type and returns one result of the same type\\n    as `base`. The result is `base` raised to the power of `power`.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.powi %b, %c : complex<f32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"OptionalAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result) `,` type($rhs)\"\n  },\n  {\n    \"name\": \"complex.re\",\n    \"summary\": \"extracts the real part of a complex number\",\n    \"description\": \"The `re` op takes a single complex number and extracts the real part.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.re %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"real\", \"type\": \"AnyFloat\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'complex', 'real', '::llvm::cast<ComplexType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.rsqrt\",\n    \"summary\": \"complex reciprocal of square root\",\n    \"description\": \"The `rsqrt` operation computes reciprocal of square root.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.rsqrt %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.sign\",\n    \"summary\": \"computes sign of a complex number\",\n    \"description\": \"The `sign` op takes a single complex number and computes the sign of\\n    it, i.e. `y = sign(x) = x / |x|` if `x != 0`, otherwise `y = 0`.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.sign %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.sin\",\n    \"summary\": \"computes sine of a complex number\",\n    \"description\": \"The `sin` op takes a single complex number and computes the sine of\\n    it, i.e. `sin(x)`, where `x` is the input value.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.sin %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.sqrt\",\n    \"summary\": \"complex square root\",\n    \"description\": \"The `sqrt` operation takes a complex number and returns its square root.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.sqrt %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.sub\",\n    \"summary\": \"complex subtraction\",\n    \"description\": \"The `sub` operation takes two complex numbers and returns their difference.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.sub %b, %c : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Complex<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"complex.tan\",\n    \"summary\": \"computes tangent of a complex number\",\n    \"description\": \"The `tan` op takes a single complex number and computes the tangent of\\n    it, i.e. `tan(x)`, where `x` is the input value.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.tan %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"complex.tanh\",\n    \"summary\": \"complex hyperbolic tangent\",\n    \"description\": \"The `tanh` operation takes a complex number and returns its hyperbolic\\n    tangent.\\n\\n    Example:\\n\\n    ```mlir\\n    %a = complex.tanh %b : complex<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"complex\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.f32.0\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.f32.1\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.f32.2\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.f32.3\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.i32.0\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.i32.1\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.i32.2\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_coo_to_dht.i32.3\",\n    \"summary\": \"coo.convert_coo_to_dht operation\",\n    \"description\": \"Convert a sparse tensor to a dense host tensor.\\n    It takes a sparse tensor and chain as input and outputs dht tensor and\\n    chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_coo_to_dht.i32.0 %1, %0\\n      %5, %6 = coo.convert_coo_to_dht.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.f32.0\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.f32.1\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.f32.2\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.f32.3\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.i32.0\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.i32.1\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.i32.2\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.convert_dht_to_coo.i32.3\",\n    \"summary\": \"coo.convert_dht_to_coo operation\",\n    \"description\": \"Convert a dense host tensor into a coo sparse host tensor.\\n    It takes a dht tensor and chain as input and outputs a coo tensor and chain.\\n\\n    Example:\\n      %4, %3 = coo.convert_dht_to_coo.i32.0 %1, %0\\n      %5, %6 = coo.convert_dht_to_coo.i32.2 %2, %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.print_tensor\",\n    \"summary\": \"coo.print_tensor operation\",\n    \"description\": \"An operation that prints a tensor.\\n    It takes a tensor and chain as input and outputs a chain.\\n\\n    Example:\\n      %3 = coo.print_tensor %1, %2\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.f32.0\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.f32.1\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.f32.2\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.f32.3\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.i32.0\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.i32.1\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.i32.2\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"coo.tensor_equal.i32.3\",\n    \"summary\": \"coo.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal.\\n    It takes two input tensors and a chain as inputs and outputs an i1 result\\n    and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = \\\"coo.tensor_equal.i32.2 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"corert_sync.const_dense_tensor\",\n    \"summary\": \"Create a constant host tensor.\",\n    \"description\": \"ConstDenseTensorOp creates a constant dense host tensor.\\n\\n    Example:\\n      %tensor_handle = corert_sync.const_dense_tensor dense<[0, 1, 2]>: tensor<3xi32>\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.bf16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.complex128\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.complex64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.f16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.f32\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.f64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.i1\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.i16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.i32\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.i64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.i8\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.ui16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.ui32\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.ui64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.create_dense_tensor.ui8\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.executeop\",\n    \"summary\": \"The CoreRuntime ExecuteOp\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device.\\n\\n    Example:\\n      %res = corert_sync.executeop(%op_handler) \\\"some.op\\\"(%arg) : 1\\n\\n    Note that the trailing number indicates the number of results.\",\n    \"operands\": [\n      { \"name\": \"op_handler\", \"type\": \"CoreRT_OpHandlerType\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert_sync.get_op_handler\",\n    \"summary\": \"return the registered op handler\",\n    \"description\": \"GetOpHandler returns a registered op handler, which can be used by ExecuteOp.\\n\\n    Example:\\n      %cpu = corert_sync.get_op_handler \\\"cpu\\\"\",\n    \"results\": [\n      { \"name\": \"op_handler\", \"type\": \"CoreRT_OpHandlerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$device_name attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.cond\",\n    \"summary\": \"conditional operation\",\n    \"description\": \"The \\\"corert.cond\\\" operation takes a tensorhandle as predicate, a 'true'\\n    function and a 'false' function.  If the condition is true, the 'true'\\n    function is called and the \\\"hex.cond\\\" operation returns the results of that\\n    function, otherwise the \\\"false\\\" function is called and its values are\\n    returned.\\n\\n    The 'true' and 'false' functions must have the same signature, but they may\\n    take an arbitrary number of arguments and return values with the same types\\n    as the op return types. Both functions are encoded as function attribute,\\n    named true_fn and false_fn. The a_ and b_ prefix prevent reordering by BEF\\n    since BEF orders attribute by name alphabetically.\\n\\n    This operation is safe to use as a 'nonstrict' op, which dispatches its body\\n    whenever the condition and any dependent arguments are resolved.\\n\\n    Example:\\n\\n      %chain, %z = corert.cond %cond, @true_fn, @false_fn (%chain, %x, %y) : (i32)\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"CoreRT_TensorHandleType\" },\n      { \"name\": \"in_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"fn_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"fn_outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_true_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"b_false_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$cond $a_true_fn $b_false_fn `(` $in_op_chain (`,` $fn_operands^)? `)` attr-dict `:` `(` type($fn_operands) `)` `->` `(` type($fn_outputs) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.const_dense_tensor\",\n    \"summary\": \"Create a constant dense host tensor.\",\n    \"description\": \"ConstDenseTensorOp creates a constant dense host tensor.\\n\\n    Example:\\n      %tensor_handle = corert.const_dense_tensor dense<[0, 1, 2]>: tensor<3xi32>\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.const_string_tensor\",\n    \"summary\": \"Create a constant string host tensor.\",\n    \"description\": \"ConstStringTensorOp creates a constant string host tensor.\\n\\n    Example:\\n      %tensor_handle = corert.const_string_tensor {shape = [1, 2], value = [\\\"const\\\", \\\"string\\\"]}\\n\\n    Note: if the entries in `value` are all the same, we can just keep one copy.\\n      In other words, the following two lines are effectively the same.\\n      %tensor_handle = corert.const_string_tensor {shape = [1, 2], value = [\\\"string\\\", \\\"string\\\"]}\\n      %tensor_handle = corert.const_string_tensor {shape = [1, 2], value = [\\\"string\\\"]}\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.bf16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.complex128\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.complex64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.f16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.f32\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.f64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.i1\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.i16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.i32\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.i64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.i8\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.ui16\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.ui32\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.ui64\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.create_dense_tensor.ui8\",\n    \"summary\": \"Create a constant dense host tensor with explicit dtype and rank.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.executeop\",\n    \"summary\": \"The CoreRuntime ExecuteOp\",\n    \"description\": \"The ExecuteOp executes an operation on the specified op handler.\\n\\n    Example:\\n      %res = corert.executeop(%op_handler) \\\"some.op\\\"(%arg) : 1\\n\\n    Note that the trailing number indicates the number of results.\\n\\n\\n    The func attrs and op attrs are placed in two separate regions.\\n\\n    Example:\\n      %res = corert.executeop(%op_handler) \\\"some.op\\\"(%arg)\\n      {attr1 = value, attr2 = value2} {f_attr1 = \\\"fn1\\\", f_attr2 = \\\"fn2\\\"} : 1\\n\\n    Note that in this case, the first braket contains op attributes other than\\n    function attributes, and the second braket contains function attributes,\\n    which represent function names.\",\n    \"operands\": [\n      { \"name\": \"op_handler\", \"type\": \"CoreRT_OpHandlerType\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.executeop.seq\",\n    \"summary\": \"The sequenced version of CoreRuntime ExecuteOp\",\n    \"description\": \"The ExecuteOpSeq executes an operation on the specified op handler, similar to\\n    ExecuteOp. In addition, it takes an in_op_chain and produces an out_op_chain\\n    that can be used to sequence op executions. ExecuteOpSeq is nonstrict on\\n    in_op_chain.\\n\\n    Example:\\n      %op_ch_out, %res = corert.executeop.seq(%op_handler, %op_ch_in) \\\"some.op\\\"(%arg) : 1\\n\\n    Note that the trailing number indicates the number of results.\\n\\n    The func attrs and op attrs are placed in two separate regions.\\n\\n    Example:\\n      %op_ch_out, %res = corert.executeop.seq(%op_ch_in) \\\"some.op\\\"(%arg)\\n      {fn = function_1} {attr1 = value, attr2 = value2} : 1\\n\\n    Note that in this case, the first braket contains op attributes other than\\n    function attributes, and the second braket contains function attributes,\\n    which represent function names.\",\n    \"operands\": [\n      { \"name\": \"op_handler\", \"type\": \"CoreRT_OpHandlerType\" },\n      { \"name\": \"in_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"results\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.get_dst_tensor_type\",\n    \"summary\": \"Get the type of the tensor to be used on the dst_device\",\n    \"description\": \"Get the type of the tensor to be used on the dst_device.\\n\\n    Example:\\n      %result = corert.get_dst_tensor_type %src_tensor_handle, %dst_device\",\n    \"operands\": [\n      { \"name\": \"src_tensor_handle\", \"type\": \"CoreRT_TensorHandleType\" },\n      { \"name\": \"dst_device\", \"type\": \"TFRT_DeviceType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_TensorTypeType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.get_op_handler\",\n    \"summary\": \"return the registered op handler\",\n    \"description\": \"GetOpHandler returns a registered op handler, which can be used by ExecuteOp.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cpu = corert.get_op_handler %ch0 \\\"cpu\\\"\",\n    \"operands\": [\n      { \"name\": \"in_op_chain\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"op_handler\", \"type\": \"CoreRT_OpHandlerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_handler_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$in_op_chain $op_handler_name attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.register_op_handler\",\n    \"summary\": \"Register a name for an OpHandler.\",\n    \"description\": \"Register a name for the given OpHandler and make it accessible through\\n      corert.get_op_handler.\\n\\n    Example:\\n      %chain = corert.register_op_handler %op_handler, \\\"my_op_handler0\\\"\",\n    \"operands\": [\n      { \"name\": \"op_handler\", \"type\": \"CoreRT_OpHandlerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_op_chain\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_handler_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$op_handler $op_handler_name attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.tensorhandle_to_int32\",\n    \"summary\": \"Cast a TensorHandle to int32.\",\n    \"description\": \"Cast a TensorHandle to int32.\\n\\n    Example:\\n      %one = corert.tensorhandle_to_int32 %src_th\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.transfer\",\n    \"summary\": \"Transfer a TensorHandle to the specified device\",\n    \"description\": \"Transfer a TensorHandle to the specified device.\\n\\n    Example:\\n      %dst_th = corert.transfer %src_th {device=\\\"CPU:0\\\", dst_tensor_type_name=\\\"DenseHost\\\"}\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CoreRT_TensorHandleType\" },\n      { \"name\": \"device\", \"type\": \"TFRT_DeviceType\" },\n      { \"name\": \"dst_tensor_type\", \"type\": \"TFRT_TensorTypeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.transfer_inferred_tensortype\",\n    \"summary\": \"Transfer a TensorHandle to the specified device\",\n    \"description\": \"Transfer a TensorHandle to the specified device. Destination tensor type\\n    is inferred.\\n\\n    Example:\\n      %dst_th = corert.transfer_inferred_type %src_th {device=\\\"CPU:0\\\"}\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"CoreRT_TensorHandleType\" },\n      { \"name\": \"device\", \"type\": \"TFRT_DeviceType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CoreRT_TensorHandleType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"corert.while\",\n    \"summary\": \"while loop operation\",\n    \"description\": \"The \\\"corert.while\\\" operation takes a 'Cond' function and a 'Body' function\\n    and performs the following action:\\n        fn_output = fn_operands; while(cond_fn(fn_output)) { fn_output = body_fn(fn_output) }\\n\\n    The 'Cond' and 'Body' functions must have the same input signature, but they\\n    may take an arbitrary number of arguments. The 'Body' function must return\\n    values with the same types as the op return types. Both functions are\\n    encoded as function attribute, named cond_fn and body_fn. The a_ and b_\\n    prefix prevent reordering by BEF since BEF orders attribute by name\\n    alphabetically.\\n\\n    This operation is safe to use as a 'nonstrict' op, which dispatches its body\\n    whenever the condition and any dependent arguments are resolved.\\n\\n    Example:\\n\\n      %chain, %z = corert.while @cond_fn, @body_fn (%chain, %x, %y) : (i32)\",\n    \"operands\": [\n      { \"name\": \"in_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"fn_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"fn_outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_cond_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"b_body_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$a_cond_fn $b_body_fn `(` $in_op_chain (`,` $fn_operands^)? `)` attr-dict `:` `(` type($fn_operands) `)` `->` `(` type($fn_outputs) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"cuda.alloc\",\n    \"description\": \"`cuda.memory.alloc` performs an asynchronous memory allocation on the\\n    provided `stream`. The memory is associated with the device that is\\n    associated with the stream.\\n\\n    The `dynamic_sizes` must be provided for each dynamic dimension of the\\n    result type.\\n\\n    An optional alignment may be specified.\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"Optional<CUDA_Stream>\" },\n      { \"name\": \"dynamic_sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` ($dynamic_sizes^ `)`) : (`)`)?\\n    (`stream` `(` $stream^ `)`)?\\n    (`align` $alignment^)?\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"cuda.blas.algo_select\",\n    \"summary\": \"Retrieve possible GEMM algorithm, given the problem size\",\n    \"description\": \"`cuda.blas.algo_select` tries to find the best possible cuBLAS GEMM algorithm\\n    for the given problem size using cuBLAS `cublasLtMatmulAlgoGetHeuristic` API. If\\n    no algorithm is found, it returns an error at the runtime.\\n\\n    Problem size is defined with the following attributes,\\n    - `data_type`: Data type for input. For now, the input data type and cuBLAS\\n    matmul algorithm data type is same.\\n    - `size_a`: Size of input matrix A.\\n\\n    NOTE: Unit of both the size and the stride is the number of elements of type\\n    `data_type`.\\n\\n    - `stride_a`: Stride of input matrix A.\\n\\n    NOTE: Even though the default cuBLAS format is `column-major`, default format\\n    used here and implemented at runtime is `row-major`.\\n\\n    - `transpose_a`: If this unit attribute is set, matrix A is transposed before\\n    GEMM computation.\\n    - `size_b`: Size of input matrix B.\\n    - `stride_b`: Stride of input matrix B.\\n    - `transpose_b`: If this unit attribute is set, matrix B is transposed before\\n    GEMM computation.\\n    - `size_c`: Size of input matrix C.\\n    - `stride_c`: Stride of input matrix C.\\n    - `tile_sizes`: Desired CTA tile sizes for the M/N dimensions for the\\n    selected algorithm. 2 elements are expected in tile sizes. If any element\\n    is 0, then this argument will be considered as invalid.\\n\\n    NOTE: All dimensions should be static.\\n\\n    Example,\\n    ```mlir\\n    %r = cuda.blas.algo_select {\\n        data_type = f32,\\n        size_a = array<i64: 4, 4>,\\n        stride_a = array<i64: 4, 1>,\\n        size_b = array<i64: 4, 4>,\\n        stride_b = array<i64: 4, 1>,\\n        size_c = array<i64: 4, 4>,\\n        stride_c = array<i64: 4, 1>,\\n        tile_sizes = array<i64: 16, 16>\\n    }  %h : !cuda.blas.gemm_algorithm\\n    ```\\n    If matrix A and C needs to be transposed,\\n\\n    ```mlir\\n    %r = cuda.blas.algo_select {\\n        data_type = f32,\\n        size_a = array<i64: 3, 2>,\\n        stride_a = array<i64: 2, 1>,\\n        transpose_a,\\n        size_b = array<i64: 3, 4>,\\n        stride_b = array<i64: 4, 1>,\\n        size_c = array<i64: 4, 2>,\\n        stride_c = array<i64: 2, 1>,\\n        tile_sizes = array<i64: 16, 16>\\n    }  %h : !cuda.blas.gemm_algorithm\\n    ```\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"CUDA_BlasHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_BlasGemmAlgorithm\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"data_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"size_a\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"stride_a\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"transpose_a\", \"type\": \"UnitAttr\" },\n      { \"name\": \"size_b\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"stride_b\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"transpose_b\", \"type\": \"UnitAttr\" },\n      { \"name\": \"size_c\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"stride_c\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"tile_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $handle `:` type($result)\"\n  },\n  {\n    \"name\": \"cuda.blas.handle.create\",\n    \"summary\": \"Creates cuBLAS handle\",\n    \"description\": \"Creates a cuBLAS handle that manages cuBLAS library context.\\n\\n    Example,\\n    ```mlir\\n     %0 = cuda.blas.handle.create : !cuda.blas.handle\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_BlasHandle\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"cuda.blas.handle.destroy\",\n    \"summary\": \"Destroys cuBLAS handle\",\n    \"description\": \"Destroys cuBLAS handle.\\n    Example,\\n    ```mlir\\n    %0 = cuda.blas.handle.create : !cuda.blas.handle\\n    cuda.blas.handle.destroy %0 : !cuda.blas.handle\\n    ```\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"CUDA_BlasHandle\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $handle `:` type($handle)\"\n  },\n  {\n    \"name\": \"cuda.blas.run_gemm\",\n    \"summary\": \"Runs cuBLAS gemm algorithm\",\n    \"description\": \"`cuda.blas.run_gemm` runs GEMM or MatMul (Multiply-Accumulate) operation, based\\n    on input operands.\\n    GEMM is implemented as,\\n    `C = alpha*(A@B) + beta*C` (i.e. in-place GEMM).\\n    MatMul is implemented as,\\n    `C += A@B` (If `C` is non-zero, result of matmul `(A@B)` is accumulated into `C`.)\\n\\n    NOTE: `@` represents matrix multiplication and `*` represents elementwise\\n    multiplication.\\n\\n    - `handle`: cuBLAS Handle\\n    - `stream`: CUDA\\n    - `algo`: A gemm algorithm selected heuristically by `cuda.blas.algo_select` op\\n    for the given problem size.\\n\\n    If the input has a `tensor` type, then `algo` should not be specified. The IR\\n    required to create `algo` is automatically added during bufferization.\\n\\n    #### Implementing MatMul (C += A @ B)\\n    1. If input has `tensor` type, only operand `mat_a`, `mat_b` and `mat_c` are\\n    compulsory.\\n        Example,\\n        ```mlir\\n        %a = arith.constant dense<2.0> : tensor<2x2xf32>\\n        %b = arith.constant dense<2.0> : tensor<2x2xf32>\\n        %c = arith.constant dense<0.0> : tensor<2x2xf32>\\n        %h = cuda.blas.handle.create : !cuda.blas.handle\\n        %s = cuda.stream.create : !cuda.stream\\n\\n        %r = cuda.blas.run_gemm %h stream (%s) inputs(%a, %b) out (%c) : !cuda.blas.handle,\\n        !cuda.stream, tensor<2x2xf32>, tensor<2x2xf32>, tensor<2x2xf32>\\n        ```\\n    2. If input has `memref` form, all operands are compulsory. Runtime sets both\\n    `alpha` and `beta` to 1.\\n        Example,\\n        ```mlir\\n        %a = memref.alloc() {alignment = 64 : i64} : memref<2x2xf32,\\n                #executor.memory_type<device>>\\n        %b = memref.alloc() {alignment = 64 : i64} : memref<2x2xf32,\\n                #executor.memory_type<device>>\\n        %c = memref.alloc() {alignment = 64 : i64} : memref<2x2xf32,\\n                #executor.memory_type<device>>\\n\\n        cuda.blas.run_gemm %h stream (%s) algo (%r) inputs(%a, %b) out (%c) :\\n        !cuda.blas.handle, !cuda.stream, !cuda.blas.gemm_algorithm,\\n        memref<2x2xf32, #executor.memory_type<device>>, memref<2x2xf32, #executor.memory_type<device>>, memref<2x2xf32, #executor.memory_type<device>>\\n        ```\\n\\n    #### Implementing GEMM (C = alpha*(A@B) + beta*C)\\n    1. If input has `tensor` form, all operands except `algo` are compulsory.\\n        Example,\\n        ```\\n        %a = arith.constant dense<2.0> : tensor<2x2xf32>\\n        %b = arith.constant dense<2.0> : tensor<2x2xf32>\\n        %c = arith.constant dense<2.0> : tensor<2x2xf32>\\n\\n        // set alpha and beta to 1.\\n        %alpha = arith.constant dense<1.0> : tensor<1xf32>\\n        %beta = arith.constant dense<1.0> : tensor<1xf32>\\n        %h = cuda.blas.handle.create : !cuda.blas.handle\\n        %s = cuda.stream.create : !cuda.stream\\n\\n        %r = cuda.blas.run_gemm %h stream (%s) inputs(alpha %alpha, %a, %b, beta %beta)\\n        out (%c) : !cuda.blas.handle, !cuda.stream, tensor<1xf32>, tensor<2x2xf32>,\\n        tensor<2x2xf32>, tensor<1xf32>, tensor<2x2xf32>\\n        ```\\n    2. If input has `memref` form, all operands are compulsory.\\n        Example,\\n        ```\\n        %a = memref.alloc() {alignment = 64 : i64} : memref<2x2xf32,\\n                #executor.memory_type<device>>\\n        %b = memref.alloc() {alignment = 64 : i64} : memref<2x2xf32,\\n                #executor.memory_type<device>>\\n        %c = memref.alloc() {alignment = 64 : i64} : memref<2x2xf32,\\n                #executor.memory_type<device>>\\n\\n        // set to intended values\\n        %alpha = memref.alloc() {alignment = 64 : i64} : memref<1xf32, #executor.memory_type<device>>\\n        %beta = memref.alloc() {alignment = 64 : i64} : memref<1xf32, #executor.memory_type<device>>\\n\\n        cuda.blas.run_gemm %h stream (%s) algo (%r) inputs(alpha %alpha, %a, %b, beta %beta) out (%c) :\\n        !cuda.blas.handle, !cuda.stream, !cuda.blas.gemm_algorithm, memref<1xf32, #executor.memory_type<device>>,\\n        memref<2x2xf32, #executor.memory_type<device>>, memref<2x2xf32, #executor.memory_type<device>>,\\n        memref<1xf32, #executor.memory_type<device>>, memref<2x2xf32, #executor.memory_type<device>>\\n        ```\\n\\n    NOTE: If input is `memref`, memory space is on device.\\n    NOTE: `transpose_<x>` attribute should be provided wherever necessary.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"CUDA_BlasHandle\" },\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"algo\", \"type\": \"Optional<CUDA_BlasGemmAlgorithm>\" },\n      { \"name\": \"alpha\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"mat_a\", \"type\": \"AnyShaped\" },\n      { \"name\": \"mat_b\", \"type\": \"AnyShaped\" },\n      { \"name\": \"beta\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"mat_c\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"UnitAttr\" },\n      { \"name\": \"transpose_b\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$handle `stream` `(` $stream `)` (`algo` `(` $algo^ `)`)?\\n    `inputs` `(`(`alpha` $alpha^ `,`)? $mat_a  `,` $mat_b  (`,` `beta` $beta^)?`)`\\n    `out` `(` $mat_c `)` attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"cuda.compiled_module\",\n    \"summary\": \"represents a compiled CUDA binary\",\n    \"description\": \"The `cuda.compiled_module` is a global operation that represents\\n    a compiled CUDA kernel module.\\n\\n    The module contents can be provided in one of two ways:\\n\\n    - `value`: an in-IR byte buffer (1D i8 ElementsAttr) containing the module\\n      data (e.g. PTX).\\n    - `file`: a path to a file containing the module data (e.g. a `.ptx` file).\\n\\n    Exactly one of `value` or `file` must be specified.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<ElementsAttr>\" },\n      { \"name\": \"file\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"kind\", \"type\": \"DefaultValuedAttr<CUDA_CompiledModuleKindAttr{PTX|LLVMIR}, CompiledModuleKind::PTX>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name ($value^)? (`file` $file^)? attr-dict\"\n  },\n  {\n    \"name\": \"cuda.copy_d2d\",\n    \"description\": \"`cuda.memcpy_d2d` copies `num_bytes` from device buffer `source` to\\n    device buffer `target` at the specified offsets.\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"target\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `stream` `(` $stream`)` $source `,` $target `:` type($source) `to` type($target)\"\n  },\n  {\n    \"name\": \"cuda.copy_d2h\",\n    \"description\": \"`cuda.memcpy_d2h` copies `num_bytes` from device buffer `source` to\\n    host buffer `target` at the specified offsets.\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"target\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `stream` `(` $stream`)` $source `,` $target `:` type($source) `to` type($target)\"\n  },\n  {\n    \"name\": \"cuda.copy_h2d\",\n    \"description\": \"`cuda.memcpy_h2d` copies `num_bytes` from host buffer `source` to\\n    device buffer `target` at the specified offsets.\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"target\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `stream` `(` $stream`)` $source `,` $target `:` type($source) `to` type($target)\"\n  },\n  {\n    \"name\": \"cuda.dealloc\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `stream` `(` $stream `)` $memref `:` type($memref)\"\n  },\n  {\n    \"name\": \"cuda.event.create\",\n    \"summary\": \"Creates a CUDA event\",\n    \"description\": \"Creates a CUDA event object. This allocates a CUDA event resource.\\n    This is equivalent to `cudaEventCreate`.\\n\\n    The `device` argument specifies which CUDA device the event should be\\n    associated with.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_Event\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `device` `(` $device `)`\"\n  },\n  {\n    \"name\": \"cuda.event.create_on_stream\",\n    \"summary\": \"Creates and records a CUDA event on a stream\",\n    \"description\": \"Creates a CUDA event associated with the same device as the given\\n    `stream`, then records the event on the stream. This is equivalent\\n    to `cuda.event.create` followed by `cuda.stream.record_event`.\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_Event\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $stream `:` type($stream)\"\n  },\n  {\n    \"name\": \"cuda.event.elapsed\",\n    \"summary\": \"Computes time elapsed between two CUDA events\",\n    \"description\": \"Computes the elapsed time in milliseconds between two CUDA events.\\n    This is equivalent to `cudaEventElapsedTime`.\\n\\n    Both events must have been recorded (via `cuda.stream.record_event`)\\n    before calling this operation.\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"CUDA_Event\" },\n      { \"name\": \"end\", \"type\": \"CUDA_Event\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $start `,` $end `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"cuda.event.release\",\n    \"summary\": \"Releases a CUDA event\",\n    \"description\": \"Releases the given CUDA event, freeing its associated resources.\\n    This is equivalent to `cudaEventDestroy`.\\n\\n    After release, the event should not be used again.\",\n    \"operands\": [\n      { \"name\": \"event\", \"type\": \"CUDA_Event\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $event `:` qualified(type($event))\"\n  },\n  {\n    \"name\": \"cuda.event.sync\",\n    \"summary\": \"Wait for a CUDA event to complete (host-side synchronization)\",\n    \"description\": \"Blocks the host thread until the given event has completed. This is\\n    equivalent to `cudaEventSynchronize`.\\n\\n    This op is preferred over synchronizing an entire stream when only a\\n    specific dependency needs to be enforced on the host.\",\n    \"operands\": [\n      { \"name\": \"event\", \"type\": \"CUDA_Event\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $event `:` qualified(type($event))\"\n  },\n  {\n    \"name\": \"cuda.get_active_device\",\n    \"summary\": \"returns the ID of the device associated with the active CUDA context\",\n    \"description\": \"Returns the ID of the CUDA device that is active for the current\\n    thread. This is equivalent to the device associated with the currently\\n    active CUDA driver context (CUcontext).\\n\\n    In our runtime model, a program is usually associated with a\\n    single-threaded execution context, and the CUDA runtime associates an\\n    \\\"active context\\\" with each thread. If no operation is invoked that can\\n    change the active context associatd with the thread within each\\n    function, then we we are free to deduplicate or hoist instances\\n    of this operation.\\n\\n    Programs that use multiple devices must perform additional analysis\\n    to determine whether de-duplication or reordering of this operation\\n    is safe.\\n\\n    This operation is marked as having a read side-effect on an\\n    unknown resource in order to prevent speculation. However, it can\\n    be safely dropped if there are no users.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"cuda.get_device\",\n    \"summary\": \"returns the identifier of a particular device\",\n    \"description\": \"Returns the identifier for a particular CUDA device. Note that\\n    currently this is just the identity function since the CUDA runtime\\n    identifies devices by their ordinal.\\n\\n    Note that this operation is marked as being speculatable and\\n    side-effect free. We assume that the number of devices cannot\\n    change during the execution of the program and that the\\n    IDs associated with devices cannot change.\",\n    \"operands\": [\n      { \"name\": \"deviceNumber\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $deviceNumber `:` type($result)\"\n  },\n  {\n    \"name\": \"cuda.get_function\",\n    \"summary\": \"retrieves a CUDA function handle from a compiled module\",\n    \"description\": \"The `cuda.get_function` operation references a `cuda.compiled_module`\\n    and returns an opaque `cuda.function` (representing a `CUfunction`\\n    from the CUDA driver API). The specific kernel entrypoint retrieved\\n    is given by the `kernel_name`.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_Function\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"module\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"kernel_name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $kernel_name `from` $module\"\n  },\n  {\n    \"name\": \"cuda.get_global_stream\",\n    \"summary\": \"gets handle to the runtime's CUDA stream associated with the specified device\",\n    \"description\": \"The `cuda.stream.get_global_stream` operation returns a handle to the\\n    runtime's CUDA stream associated with the specified device.\\n\\n    Each device has a pool of global streams addressable by `index`.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_Stream\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `device` `(` $device `)` `[` $index `]`\"\n  },\n  {\n    \"name\": \"cuda.get_program_device\",\n    \"summary\": \"returns the CUDA device ordinal associated with a program logical device\",\n    \"description\": \"Returns the CUDA device ordinal for the given program \\\"logical device\\\"\\n    identifier.\\n\\n    This operation is intended to support compilation modes where device\\n    selection is modeled explicitly and provided by the runtime when the\\n    program is loaded (e.g. via a constant mapping table). As a result, this\\n    operation is marked as being speculatable and side-effect free.\",\n    \"operands\": [\n      { \"name\": \"logicalDevice\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $logicalDevice `:` type($result)\"\n  },\n  {\n    \"name\": \"cuda.launch\",\n    \"operands\": [\n      { \"name\": \"func\", \"type\": \"CUDA_Function\" },\n      { \"name\": \"grid_x\", \"type\": \"I32\" },\n      { \"name\": \"grid_y\", \"type\": \"I32\" },\n      { \"name\": \"grid_z\", \"type\": \"I32\" },\n      { \"name\": \"block_x\", \"type\": \"I32\" },\n      { \"name\": \"block_y\", \"type\": \"I32\" },\n      { \"name\": \"block_z\", \"type\": \"I32\" },\n      { \"name\": \"dynamic_shared_mem\", \"type\": \"I32\" },\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyTypeOf<[ CUDA_Integer, CUDA_Float, AnyMemRef, CUDA_Complex ]>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    $func `(` ($args^ `:` type($args))? `)` `with` `\\\\n`\\n    ` ` `grid` `(` $grid_x `,` $grid_y `,` $grid_z `)` `\\\\n`\\n    ` ` `block` `(` $block_x `,` $block_y `,` $block_z `)` `\\\\n`\\n    ` ` `smem` `(` $dynamic_shared_mem `)` `stream` `(` $stream `)`\"\n  },\n  {\n    \"name\": \"cuda.memset\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"fill_value\", \"type\": \"AnyTypeOf<[I32, F32, I16, F16, BF16, I8, F8E4M3FN]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `stream` `(` $stream `)` $memref `with` $fill_value\\n    `:` type($memref) `,` type($fill_value)\"\n  },\n  {\n    \"name\": \"cuda.num_devices\",\n    \"summary\": \"returns the number of CUDA devices on the host\",\n    \"description\": \"Returns the number of CUDA devices (e.g. GPUs) on the host. This is\\n    equivalent to the `cudaDeviceCount` CUDA runtime API call.\\n\\n    Note that this operation is marked as being speculatable and\\n    side-effect free. We assume that the number of devices cannot\\n    change during the execution of the program.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"cuda.set_active_device\",\n    \"summary\": \"sets the active CUDA device context\",\n    \"description\": \"Sets the active CUDA device context for the current thread.\\n\\n    This operation is marked as having a write side-effect on an\\n    unknown resource in order to prevent speculation. Since this\\n    change the active device, it cannot be safely reordered or\\n    dropped without careful analysis.\\n\\n    This operation is rarely used outside of testing since\\n    currently our Executor runtime assumes that there is a\\n    single device per execution context and that multi-device\\n    programs are executed in SPMD fashion by utilizing one execution\\n    session per device and one thread per execution context.\\n\\n    In the future, we may support multiple devices for a\\n    single program and/or multiple threads per program. In such\\n    cases, this operation can be utilized to change the device.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $device\"\n  },\n  {\n    \"name\": \"cuda.stream.create\",\n    \"summary\": \"Creates an asynchronous CUDA stream\",\n    \"description\": \"Creates a CUDA stream associated with the given device.\\n    This is equivalent to `cudaStreamCreate`.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CUDA_Stream\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `device` `(` $device `)`\"\n  },\n  {\n    \"name\": \"cuda.stream.destroy\",\n    \"summary\": \"Destroy CUDA stream\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $stream `:` type($stream)\"\n  },\n  {\n    \"name\": \"cuda.stream.record_event\",\n    \"summary\": \"Records an event in the given stream\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"event\", \"type\": \"CUDA_Event\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $stream `,` $event\"\n  },\n  {\n    \"name\": \"cuda.stream.sync\",\n    \"summary\": \"Wait for stream tasks to complete\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $stream `:` type($stream)\"\n  },\n  {\n    \"name\": \"cuda.stream.wait_event\",\n    \"summary\": \"Makes stream wait on a CUDA event\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"event\", \"type\": \"CUDA_Event\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $stream `,` $event\"\n  },\n  {\n    \"name\": \"emitc.add\",\n    \"summary\": \"Addition operation\",\n    \"description\": \"With the `emitc.add` operation the arithmetic operator + (addition) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of the addition operation.\\n    %0 = emitc.add %arg0, %arg1 : (i32, i32) -> i32\\n    %1 = emitc.add %arg2, %arg3 : (!emitc.ptr<f32>, i32) -> !emitc.ptr<f32>\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    int32_t v5 = v1 + v2;\\n    float* v6 = v3 + v4;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.address_of\",\n    \"summary\": \"Address operation\",\n    \"description\": \"This operation models the C & (address of) operator for a single operand,\\n    which must be an emitc.lvalue, and returns an emitc pointer to its location.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of applying the & operator.\\n    %0 = emitc.address_of %arg0 : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"reference\", \"type\": \"EmitC_LValueType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitC_PointerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'reference', 'result', 'emitc::PointerType::get(::llvm::cast<emitc::LValueType>($_self).getValueType())'>\" }\n    ],\n    \"assemblyFormat\": \"$reference `:` qualified(type($reference)) attr-dict\"\n  },\n  {\n    \"name\": \"emitc.apply\",\n    \"summary\": \"Deprecated (use address_of/dereference)\",\n    \"description\": \"With the `emitc.apply` operation the operators & (address of) and * (contents of)\\n    can be applied to a single operand.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of applying the & operator.\\n    %0 = emitc.apply \\\"&\\\"(%arg0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>\\n\\n    // Generic form of the same operation.\\n    %0 = \\\"emitc.apply\\\"(%arg0) {applicableOperator = \\\"&\\\"}\\n        : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<[EmitCType, EmitC_LValueType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"applicableOperator\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$applicableOperator `(` $operand `)` attr-dict `:` functional-type($operand, results)\"\n  },\n  {\n    \"name\": \"emitc.assign\",\n    \"summary\": \"Assign operation\",\n    \"description\": \"The `emitc.assign` operation stores an SSA value to the location designated by an\\n    EmitC variable. This operation doesn't return any value. The assigned value\\n    must be of the same type as the variable being assigned. The operation is\\n    emitted as a C/C++ '=' operator.\\n\\n    Example:\\n\\n    ```mlir\\n    // Integer variable\\n    %0 = \\\"emitc.variable\\\"(){value = 42 : i32} : () -> !emitc.lvalue<i32>\\n    %1 = emitc.call_opaque \\\"foo\\\"() : () -> (i32)\\n\\n    // Assign emitted as `... = ...;`\\n    \\\"emitc.assign\\\"(%0, %1) : (!emitc.lvalue<i32>, i32) -> ()\\n    ```\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"EmitC_LValueType\" },\n      { \"name\": \"value\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) `to` $var `:` type($var) attr-dict\"\n  },\n  {\n    \"name\": \"emitc.bitwise_and\",\n    \"summary\": \"Bitwise and operation\",\n    \"description\": \"With the `emitc.bitwise_and` operation the bitwise operator & (and) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.bitwise_and %arg0, %arg1 : (i32, i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v3 = v1 & v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.bitwise_left_shift\",\n    \"summary\": \"Bitwise left shift operation\",\n    \"description\": \"With the `emitc.bitwise_left_shift` operation the bitwise operator <<\\n    (left shift) can be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.bitwise_left_shift %arg0, %arg1 : (i32, i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v3 = v1 << v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.bitwise_not\",\n    \"summary\": \"Bitwise not operation\",\n    \"description\": \"With the `emitc.bitwise_not` operation the bitwise operator ~ (not) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.bitwise_not %arg0 : (i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v2 = ~v1;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.bitwise_or\",\n    \"summary\": \"Bitwise or operation\",\n    \"description\": \"With the `emitc.bitwise_or` operation the bitwise operator | (or)\\n    can be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.bitwise_or %arg0, %arg1 : (i32, i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v3 = v1 | v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.bitwise_right_shift\",\n    \"summary\": \"Bitwise right shift operation\",\n    \"description\": \"With the `emitc.bitwise_right_shift` operation the bitwise operator >>\\n    (right shift) can be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.bitwise_right_shift %arg0, %arg1 : (i32, i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v3 = v1 >> v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.bitwise_xor\",\n    \"summary\": \"Bitwise xor operation\",\n    \"description\": \"With the `emitc.bitwise_xor` operation the bitwise operator ^ (xor)\\n    can be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.bitwise_xor %arg0, %arg1 : (i32, i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v3 = v1 ^ v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.call\",\n    \"summary\": \"Call operation\",\n    \"description\": \"The `emitc.call` operation represents a direct call to an `emitc.func`\\n    that is within the same symbol scope as the call. The operands and result type\\n    of the call must match the specified function type. The callee is encoded as a\\n    symbol reference attribute named \\\"callee\\\".\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = emitc.call @my_add(%0, %1) : (f32, f32) -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<EmitCType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<EmitCType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"emitc.call_opaque\",\n    \"summary\": \"Opaque call operation\",\n    \"description\": \"The `emitc.call_opaque` operation represents a C++ function call. The callee\\n    can be an arbitrary non-empty string. The call allows specifying order\\n    of operands and attributes in the call as follows:\\n\\n    - integer value of index type refers to an operand;\\n    - attribute which will get lowered to constant value in call;\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form defining a call to `foo()`.\\n    %0 = emitc.call_opaque \\\"foo\\\" () : () -> i32\\n\\n    // Generic form of the same operation.\\n    %0 = \\\"emitc.call_opaque\\\"() {callee = \\\"foo\\\"} : () -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<EmitCType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<EmitCType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"StrAttr\" },\n      { \"name\": \"args\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"template_args\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"emitc.cast\",\n    \"summary\": \"Cast operation\",\n    \"description\": \"The `emitc.cast` operation performs an explicit type conversion and is emitted\\n    as a C-style cast expression. It can be applied to integer, float, index\\n    and EmitC types.\\n\\n    Example:\\n\\n    ```mlir\\n    // Cast from `int32_t` to `float`\\n    %0 = emitc.cast %arg0: i32 to f32\\n\\n    // Cast from `void` to `int32_t` pointer\\n    %1 = emitc.cast %arg1 :\\n        !emitc.ptr<!emitc.opaque<\\\"void\\\">> to !emitc.ptr<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"emitc.class\",\n    \"summary\": \"Represents a C++ class definition, encapsulating fields and methods.\",\n    \"description\": \"The `emitc.class` operation defines a C++ class, acting as a container\\n    for its data fields (`emitc.field`) and methods (`emitc.func`).\\n    It creates a distinct scope, isolating its contents from the surrounding\\n    MLIR region, similar to how C++ classes encapsulate their internals.\\n\\n    Example:\\n\\n    ```mlir\\n    emitc.class @modelClass {\\n      emitc.field @fieldName0 : !emitc.array<1xf32> = {emitc.opaque = \\\"input_tensor\\\"}\\n      emitc.func @execute() {\\n        %0 = \\\"emitc.constant\\\"() <{value = 0 : index}> : () -> !emitc.size_t\\n        %1 = get_field @fieldName0 : !emitc.array<1xf32>\\n        %2 = subscript %1[%0] : (!emitc.array<1xf32>, !emitc.size_t) -> !emitc.lvalue<f32>\\n        return\\n      }\\n    }\\n    // Class with a final specifer\\n    emitc.class final @modelClass {\\n      emitc.field @fieldName0 : !emitc.array<1xf32> = {emitc.opaque = \\\"input_tensor\\\"}\\n      emitc.func @execute() {\\n        %0 = \\\"emitc.constant\\\"() <{value = 0 : index}> : () -> !emitc.size_t\\n        %1 = get_field @fieldName0 : !emitc.array<1xf32>\\n        %2 = subscript %1[%0] : (!emitc.array<1xf32>, !emitc.size_t) -> !emitc.lvalue<f32>\\n        return\\n      }\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"final_specifier\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"(`final` $final_specifier^)? $sym_name attr-dict-with-keyword $body\"\n  },\n  {\n    \"name\": \"emitc.cmp\",\n    \"summary\": \"Comparison operation\",\n    \"description\": \"With the `emitc.cmp` operation the comparison operators ==, !=, <, <=, >, >=, <=> \\n    can be applied.\\n\\n    Its first argument is an attribute that defines the comparison operator:\\n\\n    - equal to (mnemonic: `\\\"eq\\\"`; integer value: `0`)\\n    - not equal to (mnemonic: `\\\"ne\\\"`; integer value: `1`)\\n    - less than (mnemonic: `\\\"lt\\\"`; integer value: `2`)\\n    - less than or equal to (mnemonic: `\\\"le\\\"`; integer value: `3`)\\n    - greater than (mnemonic: `\\\"gt\\\"`; integer value: `4`)\\n    - greater than or equal to (mnemonic: `\\\"ge\\\"`; integer value: `5`)\\n    - three-way-comparison (mnemonic: `\\\"three_way\\\"`; integer value: `6`)\\n\\n    Example:\\n    ```mlir\\n    // Custom form of the cmp operation.\\n    %0 = emitc.cmp eq, %arg0, %arg1 : (i32, i32) -> i1\\n    %1 = emitc.cmp lt, %arg2, %arg3 : \\n        (\\n          !emitc.opaque<\\\"std::valarray<float>\\\">,\\n          !emitc.opaque<\\\"std::valarray<float>\\\">\\n        ) -> !emitc.opaque<\\\"std::valarray<bool>\\\">\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    bool v5 = v1 == v2;\\n    std::valarray<bool> v6 = v3 < v4;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"EmitC_CmpPredicateAttr{eq|ne|lt|le|gt|ge|three_way}\" }\n    ],\n    \"assemblyFormat\": \"$predicate `,` operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.conditional\",\n    \"summary\": \"Conditional (ternary) operation\",\n    \"description\": \"With the `emitc.conditional` operation the ternary conditional operator can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.cmp gt, %arg0, %arg1 : (i32, i32) -> i1\\n\\n    %c0 = \\\"emitc.constant\\\"() {value = 10 : i32} : () -> i32\\n    %c1 = \\\"emitc.constant\\\"() {value = 11 : i32} : () -> i32\\n\\n    %1 = emitc.conditional %0, %c0, %c1 : i32\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    bool v3 = v1 > v2;\\n    int32_t v4 = 10;\\n    int32_t v5 = 11;\\n    int32_t v6 = v3 ? v4 : v5;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"true_value\", \"type\": \"EmitCType\" },\n      { \"name\": \"false_value\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"emitc.constant\",\n    \"summary\": \"Constant operation\",\n    \"description\": \"The `emitc.constant` operation produces an SSA value equal to some constant\\n    specified by an attribute. This can be used to form simple integer and\\n    floating point constants, as well as more exotic things like tensor\\n    constants. The `emitc.constant` operation also supports the EmitC opaque\\n    attribute and the EmitC opaque type. Since folding is supported,\\n    it should not be used with pointers.\\n\\n    Example:\\n\\n    ```mlir\\n    // Integer constant\\n    %0 = \\\"emitc.constant\\\"(){value = 42 : i32} : () -> i32\\n\\n    // Constant emitted as `char = CHAR_MIN;`\\n    %1 = \\\"emitc.constant\\\"() {value = #emitc.opaque<\\\"CHAR_MIN\\\">}\\n      : () -> !emitc.opaque<\\\"char\\\">\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"EmitC_OpaqueOrTypedAttr\" }\n    ]\n  },\n  {\n    \"name\": \"emitc.declare_func\",\n    \"summary\": \"An operation to declare a function\",\n    \"description\": \"The `emitc.declare_func` operation allows to insert a function declaration for an\\n    `emitc.func` at a specific position. The operation only requires the \\\"callee\\\"\\n    of the `emitc.func` to be specified as an attribute.\\n\\n    Example:\\n\\n    ```mlir\\n    emitc.declare_func @bar\\n    emitc.func @foo(%arg0: i32) -> i32 {\\n      %0 = emitc.call @bar(%arg0) : (i32) -> (i32)\\n      emitc.return %0 : i32\\n    }\\n\\n    emitc.func @bar(%arg0: i32) -> i32 {\\n      emitc.return %arg0 : i32\\n    }\\n    ```\\n\\n    ```c++\\n    // Code emitted for the operations above.\\n    int32_t bar(int32_t v1);\\n    int32_t foo(int32_t v1) {\\n      int32_t v2 = bar(v1);\\n      return v2;\\n    }\\n\\n    int32_t bar(int32_t v1) {\\n      return v1;\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict\"\n  },\n  {\n    \"name\": \"emitc.dereference\",\n    \"summary\": \"Dereference operation\",\n    \"description\": \"This operation models the C * (dereference) operator, which must be of\\n    !emitc.ptr<> type, returning an !emitc.lvalue<> the value pointed to by the\\n    pointer.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of the dereference operator.\\n    %0 = emitc.dereference %arg0 : (!emitc.ptr<i32>) -> !emitc.lvalue<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"EmitC_PointerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitC_LValueType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'emitc::LValueType::get(::llvm::cast<emitc::PointerType>($_self).getPointee())'>\" }\n    ],\n    \"assemblyFormat\": \"$pointer `:` qualified(type($pointer)) attr-dict\"\n  },\n  {\n    \"name\": \"emitc.div\",\n    \"summary\": \"Division operation\",\n    \"description\": \"With the `emitc.div` operation the arithmetic operator / (division) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of the division operation.\\n    %0 = emitc.div %arg0, %arg1 : (i32, i32) -> i32\\n    %1 = emitc.div %arg2, %arg3 : (f32, f32) -> f32\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    int32_t v5 = v1 / v2;\\n    float v6 = v3 / v4;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatIntegerIndexOrOpaqueType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.do\",\n    \"summary\": \"Do-while operation\",\n    \"description\": \"The `emitc.do` operation represents a C/C++ do-while loop construct that\\n    repeatedly executes a body region as long as a condition region evaluates to\\n    true. The operation has two regions:\\n\\n    1. A body region that contains the loop body\\n    2. A condition region that must yield a boolean value (i1)\\n\\n    The condition is evaluated before each iteration as follows:\\n    - The condition region must contain exactly one block with:\\n      1. An `emitc.expression` operation producing an i1 value\\n      2. An `emitc.yield` passing through the expression result\\n    - The expression's body contains the actual condition logic\\n\\n    The body region is executed before the first evaluation of the \\n    condition. Thus, there is a guarantee that the loop will be executed \\n    at least once. The loop terminates when the condition yields false.\\n\\n    The canonical structure of `emitc.do` is:\\n\\n    ```mlir\\n    emitc.do {\\n      // Body region (no terminator required).\\n      // Loop body operations...\\n    } while {\\n      // Condition region (must yield i1)\\n      %condition = emitc.expression : () -> i1 {\\n        // Condition computation...\\n        %result = ... : i1  // Last operation must produce i1\\n        emitc.yield %result : i1\\n      }\\n      // Forward expression result\\n      emitc.yield %condition : i1  \\n    }\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    emitc.func @do_example() {\\n      %counter = \\\"emitc.variable\\\"() <{value = 0 : i32}> : () -> !emitc.lvalue<i32>\\n      %end = emitc.literal \\\"10\\\" : i32\\n      %step = emitc.literal \\\"1\\\" : i32\\n\\n      emitc.do {\\n        // Print current value\\n        %val = emitc.load %counter : !emitc.lvalue<i32>\\n        emitc.verbatim \\\"printf(\\\\\\\"%d\\\\\\\\n\\\\\\\", {});\\\" args %val : i32\\n\\n        // Increment counter\\n        %new_val = emitc.add %val, %step : (i32, i32) -> i32\\n        \\\"emitc.assign\\\"(%counter, %new_val) : (!emitc.lvalue<i32>, i32) -> ()\\n      } while {\\n        %condition = emitc.expression %counter, %end : (!emitc.lvalue<i32>, i32) -> i1 {\\n          %current = emitc.load %counter : !emitc.lvalue<i32>\\n          %cmp_res = emitc.cmp lt, %current, %end : (i32, i32) -> i1\\n          emitc.yield %cmp_res : i1\\n        }\\n        emitc.yield %condition : i1\\n      }\\n      return\\n    }\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    void do_example() {\\n      int32_t v1 = 0;\\n      do {\\n        int32_t v2 = v1;\\n        printf(\\\"%d\\\\n\\\", v2);\\n        int32_t v3 = v2 + 1;\\n        v1 = v3;\\n      } while (v1 < 10);\\n      return;\\n    }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"conditionRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"emitc.expression\",\n    \"summary\": \"Expression operation\",\n    \"description\": \"The `emitc.expression` operation returns a single SSA value which is yielded by\\n    its single-basic-block region. The operation takes zero or more input operands \\n    that are passed as block arguments to the region.\\n\\n    As the operation is to be emitted as a C expression, the operations within\\n    its body must form a single Def-Use tree, or a DAG trivially expandable to\\n    one, i.e. a DAG where each operation with side effects is only reachable\\n    once from the expression root.\\n\\n    Input operands can be of both value types (`EmitCType`) and lvalue types\\n    (`EmitC_LValueType`).\\n\\n    Example:\\n    ```mlir\\n    %r = emitc.expression %a, %b, %c : (i32, i32, i32) -> i32 {\\n      %0 = emitc.call_opaque \\\"foo\\\"(%a) : (i32) -> i32\\n      %1 = emitc.add %b, %c : (i32, i32) -> i32\\n      %2 = emitc.mul %0, %1 : (i32, i32) -> i32\\n      emitc.yield %2 : i32\\n    }\\n    ```\\n\\n    May be emitted as:\\n    ```c++\\n    int32_t v4 = foo(v1) * (v2 + v3);\\n    ```\\n\\n    When specified, the optional `noinline` indicates that the expression is\\n    to be emitted as seen above, i.e. as the rhs of an EmitC SSA value\\n    definition. Otherwise, the expression may be emitted inline, i.e. directly\\n    at its use.\",\n    \"operands\": [\n      { \"name\": \"defs\", \"type\": \"Variadic<AnyTypeOf<[ EmitCType, EmitC_LValueType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_not_inline\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"emitc.field\",\n    \"summary\": \"A field within a class\",\n    \"description\": \"The `emitc.field` operation declares a named field within an `emitc.class`\\n    operation. The field's type must be an EmitC type. \\n\\n    Example:\\n\\n    ```mlir\\n    // Example with an attribute:\\n    emitc.field @fieldName0 : !emitc.array<1xf32>  {emitc.opaque = \\\"another_feature\\\"}\\n    // Example with no attribute:\\n    emitc.field @fieldName0 : !emitc.array<1xf32>\\n    // Example with an initial value:\\n    emitc.field @fieldName0 : !emitc.array<1xf32> = dense<0.0>\\n    // Example with an initial value and attributes:\\n    emitc.field @fieldName0 : !emitc.array<1xf32> = dense<0.0> {\\n      emitc.opaque = \\\"input_tensor\\\"}\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<EmitC_OpaqueOrTypedAttr>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name\\n       `:` custom<EmitCFieldOpTypeAndInitialValue>($type, $initial_value)\\n       attr-dict\"\n  },\n  {\n    \"name\": \"emitc.file\",\n    \"summary\": \"A file container operation\",\n    \"description\": \"A `file` represents a single C/C++ file.\\n\\n    `mlir-translate` ignores the body of all `emitc.file` ops\\n    unless the `-file-id=id` flag is used. With that flag, all `emitc.file` ops\\n    with matching id are emitted.\\n\\n    Example:\\n\\n    ```mlir\\n    emitc.file \\\"main\\\" {\\n      emitc.func @func_one() {\\n        emitc.return\\n      }\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"Builtin_StringAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$id attr-dict-with-keyword $bodyRegion\"\n  },\n  {\n    \"name\": \"emitc.for\",\n    \"summary\": \"For operation\",\n    \"description\": \"The `emitc.for` operation represents a C loop of the following form:\\n\\n    ```c++\\n    for (T i = lb; i < ub; i += step) { /* ... */ } // where T is typeof(lb)\\n    ```\\n\\n    The operation takes 3 SSA values as operands that represent the lower bound,\\n    upper bound and step respectively, and defines an SSA value for its\\n    induction variable. It has one region capturing the loop body. The induction\\n    variable is represented as an argument of this region. This SSA value is a\\n    signless integer, or an index. The step is a value of same type.\\n\\n    This operation has no result. The body region must contain exactly one block\\n    that terminates with `emitc.yield`. Calling ForOp::build will create such a\\n    region and insert the terminator implicitly if none is defined, so will the\\n    parsing even in cases when it is absent from the custom format. For example:\\n\\n    ```mlir\\n    // Index case.\\n    emitc.for %iv = %lb to %ub step %step {\\n      ... // body\\n    }\\n    ...\\n    // Integer case.\\n    emitc.for %iv_32 = %lb_32 to %ub_32 step %step_32 : i32 {\\n      ... // body\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lowerBound\", \"type\": \"IntegerIndexOrOpaqueType\" },\n      { \"name\": \"upperBound\", \"type\": \"IntegerIndexOrOpaqueType\" },\n      { \"name\": \"step\", \"type\": \"IntegerIndexOrOpaqueType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lowerBound', 'upperBound', 'step']>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"emitc.func\",\n    \"summary\": \"An operation with a name containing a single `SSACFG` region\",\n    \"description\": \"Operations within the function cannot implicitly capture values defined\\n    outside of the function, i.e. Functions are `IsolatedFromAbove`. All\\n    external references must use function arguments or attributes that establish\\n    a symbolic connection (e.g. symbols referenced by name via a string\\n    attribute like SymbolRefAttr). While the MLIR textual form provides a nice\\n    inline syntax for function arguments, they are internally represented as\\n    “block arguments” to the first block in the region.\\n\\n    Only dialect attribute names may be specified in the attribute dictionaries\\n    for function arguments, results, or the function itself.\\n\\n    Example:\\n\\n    ```mlir\\n    // A function with no results:\\n    emitc.func @foo(%arg0 : i32) {\\n      emitc.call_opaque \\\"bar\\\" (%arg0) : (i32) -> ()\\n      emitc.return\\n    }\\n\\n    // A function with its argument as single result:\\n    emitc.func @foo(%arg0 : i32) -> i32 {\\n      emitc.return %arg0 : i32\\n    }\\n\\n    // A function with specifiers attribute:\\n    emitc.func @example_specifiers_fn_attr() -> i32\\n                attributes {specifiers = [\\\"static\\\",\\\"inline\\\"]} {\\n      %0 = emitc.call_opaque \\\"foo\\\" (): () -> i32\\n      emitc.return %0 : i32\\n    }\\n\\n    // An external function definition:\\n    emitc.func private @extern_func(i32)\\n                        attributes {specifiers = [\\\"extern\\\"]}\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"specifiers\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"emitc.get_field\",\n    \"summary\": \"Obtain access to a field within a class instance\",\n    \"description\": \"The `emitc.get_field` operation retrieves the lvalue of a\\n     named field from a given class instance.\\n\\n     Example:\\n\\n     ```mlir\\n     %0 = get_field @fieldName0 : !emitc.array<1xf32>\\n     ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"field_name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$field_name `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"emitc.get_global\",\n    \"summary\": \"Obtain access to a global variable\",\n    \"description\": \"The `emitc.get_global` operation retrieves the lvalue of a\\n     named global variable. If the global variable is marked constant, assigning\\n     to that lvalue is undefined.\\n\\n     Example:\\n\\n     ```mlir\\n     %x = emitc.get_global @foo : !emitc.array<2xf32>\\n     %y = emitc.get_global @bar : !emitc.lvalue<i32>\\n     ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$name `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"emitc.global\",\n    \"summary\": \"A global variable\",\n    \"description\": \"The `emitc.global` operation declares or defines a named global variable.\\n    The backing memory for the variable is allocated statically and described by\\n    the variable's type, which must be an EmitC type.\\n    Optionally, an `initial_value` can be provided.\\n    Internal linkage can be specified using the `static_specifier` unit attribute\\n    and external linkage can be specified using the `extern_specifier` unit attribute.\\n    Note that the default linkage without those two keywords depends on whether\\n    the target is C or C++ and whether the global variable is `const`.\\n    The global variable can also be marked constant using the `const_specifier`\\n    unit attribute. Writing to such constant global variables is\\n    undefined.\\n\\n    The global variable can be accessed by using the `emitc.get_global` to\\n    retrieve the value for the global variable.\\n\\n    Example:\\n\\n    ```mlir\\n    // Global variable with an initial value.\\n    emitc.global @x : !emitc.array<2xf32> = dense<0.0>\\n    // Global variable with an initial values.\\n    emitc.global @x : !emitc.array<3xi32> = dense<[0, 1, 2]>\\n    // Global variable with an opaque initial value.\\n    emitc.global @x : !emitc.opaque<\\\"char\\\"> = #emitc.opaque<\\\"CHAR_MIN\\\">\\n    // External global variable\\n    emitc.global extern @x : !emitc.array<2xf32>\\n    // Constant global variable with internal linkage\\n    emitc.global static const @x : i32 = 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<EmitC_OpaqueOrTypedAttr>\" },\n      { \"name\": \"extern_specifier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"static_specifier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"const_specifier\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`extern` $extern_specifier^)?\\n       (`static` $static_specifier^)?\\n       (`const` $const_specifier^)?\\n       $sym_name\\n       `:` custom<EmitCGlobalOpTypeAndInitialValue>($type, $initial_value)\\n       attr-dict\"\n  },\n  {\n    \"name\": \"emitc.if\",\n    \"summary\": \"If-then-else operation\",\n    \"description\": \"The `emitc.if` operation represents an if-then-else construct for\\n    conditionally executing two regions of code. The operand to an if operation\\n    is a boolean value. For example:\\n\\n    ```mlir\\n    emitc.if %b  {\\n      ...\\n    } else {\\n      ...\\n    }\\n    ```\\n\\n    The \\\"then\\\" region has exactly 1 block. The \\\"else\\\" region may have 0 or 1\\n    blocks. The blocks are always terminated with `emitc.yield`, which can be\\n    left out to be inserted implicitly. This operation doesn't produce any\\n    results.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"elseRegion\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"emitc.include\",\n    \"summary\": \"Include operation\",\n    \"description\": \"The `emitc.include` operation allows to define a source file inclusion via the\\n    `#include` directive.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form defining the inclusion of `<myheader>`.\\n    emitc.include <\\\"myheader.h\\\">\\n\\n    // Generic form of the same operation.\\n    \\\"emitc.include\\\" (){include = \\\"myheader.h\\\", is_standard_include} : () -> ()\\n\\n    // Custom form defining the inclusion of `\\\"myheader\\\"`.\\n    emitc.include \\\"myheader.h\\\"\\n\\n    // Generic form of the same operation.\\n    \\\"emitc.include\\\" (){include = \\\"myheader.h\\\"} : () -> ()\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"include\", \"type\": \"StrAttr\" },\n      { \"name\": \"is_standard_include\", \"type\": \"UnitAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"emitc.literal\",\n    \"summary\": \"Literal operation\",\n    \"description\": \"The `emitc.literal` operation produces an SSA value equal to some constant\\n    specified by an attribute.\\n\\n    Example:\\n\\n    ```mlir\\n    %p0 = emitc.literal \\\"M_PI\\\" : f32\\n    %1 = \\\"emitc.add\\\" (%arg0, %p0) : (f32, f32) -> f32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    float v2 = v1 + M_PI;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"emitc.load\",\n    \"summary\": \"Load an lvalue into an SSA value.\",\n    \"description\": \"This operation loads the content of a modifiable lvalue into an SSA value. \\n    Modifications of the lvalue executed after the load are not observable on \\n    the produced value.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = emitc.load %0 : !emitc.lvalue<i32>\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v2 = v1;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EmitC_LValueType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', '::llvm::cast<LValueType>($_self).getValueType()'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"emitc.logical_and\",\n    \"summary\": \"Logical and operation\",\n    \"description\": \"With the `emitc.logical_and` operation the logical operator && (and) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.logical_and %arg0, %arg1 : i32, i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    bool v3 = v1 && v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"emitc.logical_not\",\n    \"summary\": \"Logical not operation\",\n    \"description\": \"With the `emitc.logical_not` operation the logical operator ! (negation) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.logical_not %arg0 : i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    bool v2 = !v1;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"emitc.logical_or\",\n    \"summary\": \"Logical or operation\",\n    \"description\": \"With the `emitc.logical_or` operation the logical operator || (inclusive or)\\n    can be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.logical_or %arg0, %arg1 : i32, i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    bool v3 = v1 || v2;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"emitc.member\",\n    \"summary\": \"Member operation\",\n    \"description\": \"With the `emitc.member` operation the member access operator `.` can be\\n    applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = \\\"emitc.member\\\" (%arg0) {member = \\\"a\\\"}\\n        : (!emitc.lvalue<!emitc.opaque<\\\"mystruct\\\">>) -> !emitc.lvalue<i32>\\n    %1 = \\\"emitc.member\\\" (%arg0) {member = \\\"b\\\"}\\n        : (!emitc.lvalue<!emitc.opaque<\\\"mystruct\\\">>) -> !emitc.array<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EmitC_LValueOf<[EmitC_OpaqueType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"member\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"emitc.member_of_ptr\",\n    \"summary\": \"Member of pointer operation\",\n    \"description\": \"With the `emitc.member_of_ptr` operation the member access operator `->`\\n    can be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = \\\"emitc.member_of_ptr\\\" (%arg0) {member = \\\"a\\\"}\\n        : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<\\\"mystruct\\\">>>)\\n        -> !emitc.lvalue<i32>\\n    %1 = \\\"emitc.member_of_ptr\\\" (%arg0) {member = \\\"b\\\"}\\n        : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<\\\"mystruct\\\">>>)\\n        -> !emitc.array<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EmitC_LValueOf<[EmitC_OpaqueType, EmitC_PointerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"member\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"emitc.mul\",\n    \"summary\": \"Multiplication operation\",\n    \"description\": \"With the `emitc.mul` operation the arithmetic operator * (multiplication) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of the multiplication operation.\\n    %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32\\n    %1 = emitc.mul %arg2, %arg3 : (f32, f32) -> f32\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    int32_t v5 = v1 * v2;\\n    float v6 = v3 * v4;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatIntegerIndexOrOpaqueType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.rem\",\n    \"summary\": \"Remainder operation\",\n    \"description\": \"With the `emitc.rem` operation the arithmetic operator % (remainder) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of the remainder operation.\\n    %0 = emitc.rem %arg0, %arg1 : (i32, i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v5 = v1 % v2;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntegerIndexOrOpaqueType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.return\",\n    \"summary\": \"Function return operation\",\n    \"description\": \"The `emitc.return` operation represents a return operation within a function.\\n    The operation takes zero or exactly one operand and produces no results.\\n    The operand number and type must match the signature of the function\\n    that contains the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    emitc.func @foo() -> (i32) {\\n      ...\\n      emitc.return %0 : i32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Optional<EmitCType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operand^ `:` type($operand))?\"\n  },\n  {\n    \"name\": \"emitc.sub\",\n    \"summary\": \"Subtraction operation\",\n    \"description\": \"With the `emitc.sub` operation the arithmetic operator - (subtraction) can\\n    be applied.\\n\\n    Example:\\n\\n    ```mlir\\n    // Custom form of the substraction operation.\\n    %0 = emitc.sub %arg0, %arg1 : (i32, i32) -> i32\\n    %1 = emitc.sub %arg2, %arg3 : (!emitc.ptr<f32>, i32) -> !emitc.ptr<f32>\\n    %2 = emitc.sub %arg4, %arg5 : (!emitc.ptr<i32>, !emitc.ptr<i32>)\\n        -> !emitc.ptrdiff_t\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    int32_t v7 = v1 - v2;\\n    float* v8 = v3 - v4;\\n    ptrdiff_t v9 = v5 - v6;\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EmitCType\" },\n      { \"name\": \"rhs\", \"type\": \"EmitCType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.subscript\",\n    \"summary\": \"Subscript operation\",\n    \"description\": \"With the `emitc.subscript` operation the subscript operator `[]` can be applied\\n    to variables or arguments of array, pointer and opaque type.\\n\\n    Example:\\n\\n    ```mlir\\n    %i = index.constant 1\\n    %j = index.constant 7\\n    %0 = emitc.subscript %arg0[%i, %j] : (!emitc.array<4x8xf32>, index, index)\\n           -> !emitc.lvalue<f32>\\n    %1 = emitc.subscript %arg1[%i] : (!emitc.ptr<i32>, index)\\n           -> !emitc.lvalue<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[ EmitC_ArrayType, EmitC_OpaqueType, EmitC_PointerType ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<EmitCType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitC_LValueType\" }\n    ],\n    \"assemblyFormat\": \"$value `[` $indices `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.switch\",\n    \"summary\": \"Switch operation\",\n    \"description\": \"The `emitc.switch` is a control-flow operation that branches to one of\\n    the given regions based on the values of the argument and the cases.\\n    The operand to a switch operation is a opaque, integral or pointer\\n    wide types.\\n\\n    The operation always has a \\\"default\\\" region and any number of case regions\\n    denoted by integer constants. Control-flow transfers to the case region\\n    whose constant value equals the value of the argument. If the argument does\\n    not equal any of the case values, control-flow transfer to the \\\"default\\\"\\n    region.\\n\\n    The operation does not return any value. Moreover, case regions must be\\n    explicitly terminated using the `emitc.yield` operation. Default region is\\n    yielded implicitly.\\n\\n    Example:\\n\\n    ```mlir\\n    // Example:\\n    emitc.switch %0 : i32\\n    case 2 {\\n      %1 = emitc.call_opaque \\\"func_b\\\" () : () -> i32\\n      emitc.yield\\n    }\\n    case 5 {\\n      %2 = emitc.call_opaque \\\"func_a\\\" () : () -> i32\\n      emitc.yield\\n    }\\n    default {\\n      %3 = \\\"emitc.constant\\\"(){value = 42.0 : f32} : () -> f32\\n      emitc.call_opaque \\\"func2\\\" (%3) : (f32) -> ()\\n    }\\n    ```\\n    ```c++\\n    // Code emitted for the operations above.\\n    switch (v1) {\\n    case 2: {\\n      int32_t v2 = func_b();\\n      break;\\n    }\\n    case 5: {\\n      int32_t v3 = func_a();\\n      break;\\n    }\\n    default: {\\n      float v4 = 4.200000000e+01f;\\n      func2(v4);\\n      break;\\n    }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"IntegerIndexOrOpaqueType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cases\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"defaultRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"caseRegions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"defaultDialect\": \"emitc\",\n    \"assemblyFormat\": \"$arg `:` type($arg) attr-dict custom<SwitchCases>($cases, $caseRegions) `\\\\n`\\n    `` `default` $defaultRegion\"\n  },\n  {\n    \"name\": \"emitc.unary_minus\",\n    \"summary\": \"Unary minus operation\",\n    \"description\": \"With the `emitc.unary_minus` operation the unary operator - (minus) can be\\n    applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.unary_minus %arg0 : (i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v2 = -v1;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.unary_plus\",\n    \"summary\": \"Unary plus operation\",\n    \"description\": \"With the `emitc.unary_plus` operation the unary operator + (plus) can be\\n    applied.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = emitc.unary_plus %arg0 : (i32) -> i32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    int32_t v2 = +v1;\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EmitCType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"emitc.variable\",\n    \"summary\": \"Variable operation\",\n    \"description\": \"The `emitc.variable` operation produces an SSA value equal to some value\\n    specified by an attribute. This can be used to form simple integer and\\n    floating point variables, as well as more exotic things like tensor\\n    variables. The `emitc.variable` operation also supports the EmitC opaque\\n    attribute and the EmitC opaque type. If further supports the EmitC\\n    pointer type, whereas folding is not supported.\\n    The `emitc.variable` is emitted as a C/C++ local variable.\\n\\n    Example:\\n\\n    ```mlir\\n    // Integer variable\\n    %0 = \\\"emitc.variable\\\"(){value = 42 : i32} : () -> !emitc.lvalue<i32>\\n\\n    // Variable emitted as `int32_t* = NULL;`\\n    %1 = \\\"emitc.variable\\\"() {value = #emitc.opaque<\\\"NULL\\\">} \\n      : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<\\\"int32_t\\\">>>\\n    ```\\n\\n    Since folding is not supported, it can be used with pointers.\\n    As an example, it is valid to create pointers to `variable` operations\\n    by using `apply` operations and pass these to a `call` operation.\\n    ```mlir\\n    %0 = \\\"emitc.variable\\\"() {value = 0 : i32} : () -> !emitc.lvalue<i32>\\n    %1 = \\\"emitc.variable\\\"() {value = 0 : i32} : () -> !emitc.lvalue<i32>\\n    %2 = emitc.apply \\\"&\\\"(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>\\n    %3 = emitc.apply \\\"&\\\"(%1) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>\\n    emitc.call_opaque \\\"write\\\"(%2, %3)\\n      : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[ EmitC_ArrayType, EmitC_LValueType ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"EmitC_OpaqueOrTypedAttr\" }\n    ]\n  },\n  {\n    \"name\": \"emitc.verbatim\",\n    \"summary\": \"Verbatim operation\",\n    \"description\": \"The `emitc.verbatim` operation produces no results and the value is emitted as is\\n    followed by a line break  ('\\\\n' character) during translation.\\n\\n    Note: Use with caution. This operation can have arbitrary effects on the\\n    semantics of the emitted code. Use semantically more meaningful operations\\n    whenever possible. Additionally this op is *NOT* intended to be used to\\n    inject large snippets of code.\\n\\n    This operation can be used in situations where a more suitable operation is\\n    not yet implemented in the dialect or where preprocessor directives\\n    interfere with the structure of the code. One example of this is to declare\\n    the linkage of external symbols to make the generated code usable in both C\\n    and C++ contexts:\\n\\n    ```c++\\n    #ifdef __cplusplus\\n    extern \\\"C\\\" {\\n    #endif\\n\\n    ...\\n    \\n    #ifdef __cplusplus\\n    }\\n    #endif\\n    ```\\n\\n    If the `emitc.verbatim` op has operands, then the `value` is interpreted as\\n    format string, where `{}` is a placeholder for an operand in their order.\\n    For example, `emitc.verbatim \\\"#pragma my src={} dst={}\\\" %src, %dest : i32, i32`\\n    would be emitted as `#pragma my src=a dst=b` if `%src` became `a` and\\n    `%dest` became `b` in the C code.\\n    `{{` in the format string is interpreted as a single `{` and doesn't introduce\\n    a placeholder.\\n\\n    Example:\\n\\n    ```mlir\\n    emitc.verbatim \\\"typedef float f32;\\\"\\n    emitc.verbatim \\\"#pragma my var={} property\\\" args %arg : f32\\n    ```\\n    ```c++\\n    // Code emitted for the operation above.\\n    typedef float f32;\\n    #pragma my var=v1 property\\n    ```\",\n    \"operands\": [\n      { \"name\": \"fmtArgs\", \"type\": \"Variadic<AnyTypeOf<[ EmitCType, EmitC_LValueType ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$value (`args` $fmtArgs^ `:` type($fmtArgs))? attr-dict\"\n  },\n  {\n    \"name\": \"emitc.yield\",\n    \"summary\": \"Block termination operation\",\n    \"description\": \"The `emitc.yield` terminates its parent EmitC op's region, optionally yielding\\n    an SSA value. The semantics of how the values are yielded is defined by the\\n    parent operation.\\n    If `emitc.yield` has an operand, the operand must match the parent operation's\\n    result. If the parent operation defines no values, then the `emitc.yield`\\n    may be left out in the custom syntax and the builders will insert one\\n    implicitly. Otherwise, it has to be present in the syntax to indicate which\\n    value is yielded.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"Optional<EmitCType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($result^ `:` type($result))?\"\n  },\n  {\n    \"name\": \"ensemble.alloc_cbits\",\n    \"summary\": \"Allocate a tensor of classical bits for a given circuit size.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[Cbit]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"circuit_size\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$circuit_size attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.apply\",\n    \"summary\": \"Apply a deterministic gate to any number of qubits.\",\n    \"operands\": [\n      { \"name\": \"gate\", \"type\": \"Gate\" },\n      { \"name\": \"input\", \"type\": \"Variadic<AnyQubit>\" }\n    ],\n    \"assemblyFormat\": \"$gate attr-dict $input `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.apply_distribution\",\n    \"summary\": \"Gate distribution on a variable number of qubits and gates\",\n    \"operands\": [\n      { \"name\": \"gates\", \"type\": \"GateDistribution\" },\n      { \"name\": \"index\", \"type\": \"AnyIndexType\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyQubit>\" }\n    ],\n    \"assemblyFormat\": \"$gates `[` $index `]` attr-dict $inputs `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.cbit_distribution_1c\",\n    \"summary\": \"Cbit distribution sampled from by an integer\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<Cbit>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Cbit\" }\n    ],\n    \"assemblyFormat\": \"$input `[` $index `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.cnot_pair_distribution\",\n    \"summary\": \"Distribution of non-overlapping CNOT pairs sampled from a connectivity graph.\",\n    \"description\": \"This operation generates random non-overlapping CNOT pairs sampled from a connectivity graph.\\n    The operation produces a tensor of the given shape, where each element is a pair of qubits.\",\n    \"operands\": [\n      { \"name\": \"connectivity\", \"type\": \"ConnectivityGraph\" },\n      { \"name\": \"num_samples\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[AnyQubit]>\" }\n    ],\n    \"assemblyFormat\": \"$connectivity `,` `[` $num_samples `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.device_connectivity\",\n    \"summary\": \"Create a connectivity graph for a device.\",\n    \"description\": \"This operation creates a connectivity graph for a device from a tensor of qubits and a dense array \\n    of indices specifying the connectivity between qubits.\",\n    \"operands\": [\n      { \"name\": \"qubits\", \"type\": \"TensorOf<[AnyQubit]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"connectivity\", \"type\": \"ConnectivityGraph\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"I32ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"$qubits `,` `{` $indices `}` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.float_uniform\",\n    \"summary\": \"Uniform float distribution over low (inclusive) to high (exclusive).\",\n    \"description\": \"This operation generates random floats uniformly distributed between\\n    two bounds (`low` and `high`). The operation produces a tensor of the \\n    given shape.\",\n    \"operands\": [\n      { \"name\": \"low\", \"type\": \"AnyFloat\" },\n      { \"name\": \"high\", \"type\": \"AnyFloat\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[AnyFloat]>\" }\n    ],\n    \"assemblyFormat\": \"$low `,` $high `,` `[` $shape `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.gate\",\n    \"summary\": \"Gate constructor. Takes in a name, optional inverse annotation, and variadic floating point parameters.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"Variadic<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Gate\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"inverse\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"num_operands\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$name ($inverse^)? $num_operands (`(` $parameters^ `)`)? attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.gate_distribution\",\n    \"summary\": \"Gate distribution constructor that accepts a variable number of gates\",\n    \"operands\": [\n      { \"name\": \"gates\", \"type\": \"Variadic<Gate>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"GateDistribution\" }\n    ],\n    \"assemblyFormat\": \"$gates attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.int_categorical\",\n    \"summary\": \"Categorical integer distribution over low (inclusive) to low + len(probs) (exclusive).\",\n    \"description\": \"This operation generates random integers non-uniformly distributed between\\n    two bounds (`low` and `low + len(probs)`)., with each integer being produced with probability\\n    equal to the magnitude of the corresponding probability argument. The operation produces a tensor of the \\n    given shape.\",\n    \"operands\": [\n      { \"name\": \"low\", \"type\": \"AnyInteger\" },\n      { \"name\": \"probs\", \"type\": \"TensorOf<[AnyFloat]>\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[AnyInteger]>\" }\n    ],\n    \"assemblyFormat\": \"$low `,` $probs `,` `[` $shape `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.int_uniform\",\n    \"summary\": \"Uniform integer distribution over low (inclusive) to high (exclusive).\",\n    \"description\": \"This operation generates random integers uniformly distributed between\\n    two bounds (`low` and `high`). The operation produces a tensor of the \\n    given shape if provided, otherwise a single integer.\",\n    \"operands\": [\n      { \"name\": \"low\", \"type\": \"AnyInteger\" },\n      { \"name\": \"high\", \"type\": \"AnyInteger\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[AnyInteger]>\" }\n    ],\n    \"assemblyFormat\": \"$low `,` $high ( `,` `[` $shape^ `]`)? attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.measure\",\n    \"summary\": \"Single qubit measurement to classical bit.\",\n    \"operands\": [\n      { \"name\": \"input0\", \"type\": \"AnyQubit\" },\n      { \"name\": \"input1\", \"type\": \"Cbit\" }\n    ],\n    \"assemblyFormat\": \"$input0 `,` $input1 attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.permutation\",\n    \"summary\": \"Generates a random permutation of numbers from 0 to N-1.\",\n    \"description\": \"This operation generates a random permutation of numbers from 0 to N-1.\\n    The operation produces a tensor of the given shape.\",\n    \"operands\": [\n      { \"name\": \"N\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[AnyInteger]>\" }\n    ],\n    \"assemblyFormat\": \"$N attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.program_alloc\",\n    \"summary\": \"Allocate a tensor of qubits for a given circuit size.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[PhysicalQubit]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"circuit_size\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$circuit_size attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.quantum_program_iteration\",\n    \"summary\": \"An operation that wraps multiple operations and contains all of the code for one iteration of a quantum program.\",\n    \"description\": \"This operation wraps a single region. The region can have multiple blocks, and\\n    the operation itself persists across transformations unless explicitly targeted.\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$body attr-dict\"\n  },\n  {\n    \"name\": \"ensemble.qubit_distribution_1q\",\n    \"summary\": \"Qubit distribution sampled from by an integer\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyQubit>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyQubit\" }\n    ],\n    \"assemblyFormat\": \"$input `[` $index `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.reset\",\n    \"summary\": \"variadic qubit reset.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyQubit>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.reset_tensor\",\n    \"summary\": \"Reset a tensor of qubits.\",\n    \"description\": \"This operation resets all qubits in a given tensor to their ground state.\\n    It takes a tensor of qubits as input and returns a tensor of reset qubits of the same shape.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[AnyQubit]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ensemble.transmit_results\",\n    \"summary\": \"Transmit results from a quantum program iteration.\",\n    \"description\": \"This operation transmits results from a quantum program iteration.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"TensorOf<[Cbit]>\" }\n    ],\n    \"assemblyFormat\": \"$results attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.abi.recv\",\n    \"summary\": \"receive an argument from the caller\",\n    \"description\": \"The `executor.abi.recv` operation represents loading an argument value\\n    indirectly from a function input argument which has host pointer type.\\n\\n    The argument must be annotated with an `#executor.arg<byval, ...>` argument\\n    ABI. Currently, only non-scalar value types are supported for passing\\n    inputs via pointer arguments.\\n\\n    The result type of the operation must match the type of the argument's\\n    `#executor.arg<byval, ...>` value type.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Executor_HostPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_space\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.abi.send\",\n    \"summary\": \"send an argument to the caller\",\n    \"description\": \"The `executor.abi.send` operation \\\"stores\\\" value to a function output argument\\n    which has host poitner type and is annotated with `#executor.arg<byref, ...>`\\n    argument ABI.\\n\\n    The value type of the argument's `#executor.arg<byref, ...>` must match the type\\n    of `value`.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"ptr\", \"type\": \"Executor_HostPtr\" },\n      { \"name\": \"ownership\", \"type\": \"Optional<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$value `to` $ptr ( `ownership` `(` $ownership^ `)`)? attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"executor.absf\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.absi\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.addf\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.addi\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.alignto\",\n    \"summary\": \"rounds up integer operand to nearest multiple of power-of-two alignment\",\n    \"description\": \"`executor.alignto` returns an integer formed from taking `arg` and\\n    rounding it up to the nearest multiple of `alignment`, which must be a power\\n    of two.\\n\\n    One possible implementation of this is:\\n\\n    ```\\n    bumped = arg + alignment -1\\n    result = bumped - urem(bumped, alignment)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"UI32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['arg', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $arg `,` $alignment `:` type($arg)\"\n  },\n  {\n    \"name\": \"executor.alloc\",\n    \"description\": \"`executor.alloc` performs an allocation of `num_bytes` using the given\\n    allocation. It returns an opaque pointer representing the allocation.\\n    The caller must also specify `alignment`.\\n\\n    Backends/runtimes impleemnting this operation may automatically round up\\n    `num_bytes` to the next multiple of the `alignment`. `num_bytes` should\\n    be a power of two.\",\n    \"operands\": [\n      { \"name\": \"num_bytes\", \"type\": \"Executor_Index\" },\n      { \"name\": \"alignment\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_HostPtr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $num_bytes `bytes` `align` `(` $alignment `)` `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.alloc_host_pinned\",\n    \"description\": \"The `executor.alloc_host_pinned` op performs a synchronous allocation of\\n    `num_bytes` of host-pinned memory. The actual allocation size may be larger;\\n    this is decided by the underlying runtime allocator object.\",\n    \"operands\": [\n      { \"name\": \"num_bytes\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_HostPinnedPtr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $num_bytes `bytes` `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.alloca\",\n    \"summary\": \"block-scoped temporary allocation\",\n    \"description\": \"The `executor.alloca` operation allocates temporary memory to be\\n    automatically released when control transfers back from the region of its\\n    closest surrounding operation with an\\n    [`AutomaticAllocationScope`](../Traits.md/#automaticallocationscope) trait.\\n\\n    The size of the allocation is specified by giving the element type and\\n    number of elements of an array which it must be large enough to hold.\\n    Once allocated, the size of the allocation cannot change.\\n\\n    An optional alignment can be specified, the alignment is implicitly\\n    interpreted as the DataLayout-specified ABI alignment for the\\n    `element_type`.\",\n    \"operands\": [\n      { \"name\": \"num_elements\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_HostPtr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"element_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$num_elements `x` $element_type (`align` `(` $alignment^ `)`)?\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.assert\",\n    \"summary\": \"Assert operation with message attribute\",\n    \"description\": \"The `executor.assert` operation represents a runtime assertion with a single\\n    boolean operand and an error message attribute.\\n\\n    If the argument is `true` this operation has no effect. Otherwise, the\\n    program execution will abort. The provided error message may be used by a\\n    runtime to propagate the error to the user.\\n\\n    Example:\\n\\n    ```mlir\\n    executor.assert %b, \\\"Expected some condition to be true\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$arg `,` $msg attr-dict\"\n  },\n  {\n    \"name\": \"executor.atan2\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.bitcast\",\n    \"description\": \"`executor.bitcast` op performs a bitcast between values of equal bit width.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[F4E2M1FN, F8E4M3FN, F64, F32, F16, I64, I32, I16, I8, I4]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[F4E2M1FN, F8E4M3FN, F64, F32, F16, I64, I32, I16, I8, I4]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.bitwise_andi\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.bitwise_ori\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.bitwise_xori\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.buffer_bitcast\",\n    \"description\": \"`executor.buffer_bitcast` op performs a bitcast from one tensor or\\n    memref type to another tensor or memref type.\\n\\n    The result element type must have the same bit width as the source\\n    element type.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.call\",\n    \"summary\": \"call to an Executor IR function\",\n    \"description\": \"The `executor.call` operation represents a procedure call to an externally\\n    defined function given by the `callee` symbol name. The procedure is invoked\\n    by passing `args`.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $args `)` attr-dict\\n       `:`  functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"executor.call_plugin\",\n    \"summary\": \"call a plugin callable\",\n    \"description\": \"The `executor.call_plugin` operation calls an instance of a plugin\\n    callable.\\n\\n    For TVM FFI backend (`ffi_backend = #executor.ffi_backend<tvm_ffi>`):\\n    This operation invokes a TVM FFI function following the TVM FFI ABI calling\\n    convention. All arguments and outputs are converted to `TVMFFIAny` structures\\n    and arranged according to the `arg_spec` attribute.\\n\\n    Argument Specification (`arg_spec`):\\n    The `arg_spec` is a list of strings that encodes how to arrange arguments\\n    for the TVM FFI call. Each string can be:\\n    - `\\\"args.N\\\"`: Use the N-th input argument from `args`\\n    - `\\\"rets.N\\\"`: Use the N-th output argument from `outputs`\\n    - `\\\"attrs.name\\\"`: Use the attribute named `name` from `immediate_args`\\n    - `\\\"none\\\"`: Insert an optional None value\\n\\n    Argument Conversion:\\n    - POD values (integers, floats): Stored directly in the 16-byte `TVMFFIAny`\\n      union structure without heap allocation\\n    - Tensor values: Converted to DLPack-compatible `DLTensor` structures and\\n      stored as pointers (`kTVMFFIDLTensorPtr`). The DLTensor contains:\\n      - Data pointer and device information (CUDA, CPU, etc.)\\n      - Rank, shape, and strides arrays (promoted to host memory)\\n      - Data type information (DLDataType)\\n      - Byte offset for non-contiguous views\\n    - Attributes: Converted to appropriate `TVMFFIAny` values (POD or string literals)\\n\\n    Output Handling:\\n    TVM FFI functions do not return values through a result parameter. All\\n    outputs must be provided as input arguments with I/O aliasing specified\\n    via the `io_aliasing` attribute. This attribute maps each input index to\\n    an output index (-1 if not aliased), allowing in-place operations.\\n\\n    Stream Handling:\\n    The optional `stream` operand specifies a CUDA stream for async operations.\\n    If not provided, NULL will be passed as the stream argument to the\\n    TVM FFI call.\\n\\n    Memory Management:\\n    - DLTensor structures are allocated on the stack (via alloca) and contain\\n      pointers to the actual tensor data\\n    - Shape and strides arrays are promoted to host-allocated memory for runtime\\n      access\\n    - The `TVMFFIAny` argument array is allocated on the host stack for passing\\n      to the FFI runtime\\n\\n    During lowering, this operation is converted to a call to the runtime\\n    function `_call_plugin_tvm_ffi`, which:\\n    1. Sets CUDA streams for DLTensor arguments (if applicable)\\n    2. Invokes the TVM FFI function using the `TVMFFISafeCallType` signature:\\n       `int (*TVMFFISafeCallType)(void* handle, const TVMFFIAny* args,\\n                                  int32_t num_args, TVMFFIAny* result)`\\n    3. Handles errors and propagates them appropriately\\n\\n    Example:\\n\\n    ```mlir\\n    %result = executor.call_plugin @my_plugin\\n      ins(%arg0 : tensor<*xf32>, %arg1 : tensor<*xf32>)\\n      outs(%output : tensor<*xf32>)\\n      {\\n        arg_spec = [\\\"args.0\\\", \\\"args.1\\\", \\\"rets.0\\\", \\\"attrs.backend\\\"],\\n        io_aliasing = [-1, -1, 0],\\n        immediate_args = {backend = \\\"paged\\\"}\\n      } : (tensor<*xf32>, tensor<*xf32>, tensor<*xf32>) -> ()\\n    ```\\n\\n    In this example:\\n    - `args.0` and `args.1` are the input tensors\\n    - `rets.0` is the output tensor (aliased with input 0 via `io_aliasing`)\\n    - `attrs.backend` is an immediate string attribute\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"immediate_args\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"arg_spec\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"io_aliasing\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee\\n    (`stream` `(` $stream^ `:` type($stream) `)`)?\\n    `ins` `(` $args `:` type($args) `)`\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    attr-dict (`:` type($results)^)?\"\n  },\n  {\n    \"name\": \"executor.cbrt\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.ceil\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.constant\",\n    \"summary\": \"integer or floating point constant\",\n    \"description\": \"The `executor.constant` operation produces an SSA value equal to some\\n    integer or floating-point constant specified by an attribute.\\n\\n    This is basically the same as `arith.constant`, but we are more limited\\n    in terms of allowed types based on the target VM.\\n\\n    For example, if Lua is the target VM, then depending on Lua's build\\n    config, integers are either signed 32 bit or signed 64 bit.\\n\\n    Example:\\n\\n    ```\\n    // Integer constant\\n    %1 = executor.constant 42 : i32\\n\\n    // Equivalent generic form\\n    %1 = \\\"executor.constant\\\"() {value = 42 : i32} : () -> i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Executor_Integer, Executor_Float]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"executor.copysign\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.coro_await\",\n    \"summary\": \"resume coroutine\",\n    \"description\": \"`executor.coro_await` resumes a coroutine. The 'callee_operands' must either be\\n    empty or they must match the operands of the coroutine (for the initial\\n    resume). The results yielded from the coroutine should always match\\n    the function signature results, so the result types of `executor.coro_await`\\n    must match the callee function result types.\\n\\n    The results of `executor.coro_await` are a flag indicating whether or not\\n    the coroutine was resumed (false indicates the coroutine is terminated and cannot\\n    be resumed) followed by the list of values yielded from the coroutine.\\n    If the 'status' flag is false, then the 'results' values contain undefined\\n    contents.\",\n    \"operands\": [\n      { \"name\": \"callee\", \"type\": \"FunctionType\" },\n      { \"name\": \"callee_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"status\", \"type\": \"I1\" },\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'callee', 'results', '::llvm::cast<FunctionType>($_self).getResults()'>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $callee_operands (`:` type($callee_operands)^)? `)` attr-dict `:` type($callee)\"\n  },\n  {\n    \"name\": \"executor.coro_create\",\n    \"description\": \"Constructs a coroutine handle from a function or coroutine function.\\n    Functions may or may not use 'executor.coro_yield' in their bodies\\n    (abcense of 'coro_yield' does not prevent a 'func.func' from being\\n    used as a coroutine, although the in that case 'coro_await' is\\n    identical to just using 'func.call').\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FunctionType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"func\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $func `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.coro_yield\",\n    \"summary\": \"suspends a coroutine\",\n    \"description\": \"The 'executor.coro_yield' operation suspends the current coroutine and\\n    transfers control back to the program point immediately after the\\n    point where the coroutine was resumed.\\n\\n    The control flow returns to the the 'coro_yield' point when the coroutine\\n    is resumed. Note that 'coro_yield' is not a \\\"terminator\\\", but invoking the\\n    coro suspension has \\\"return-like\\\" semantics with respect to 'executor.coro_resume`.\\n\\n    Therefore, the types passed to the continuation must match the result\\n    types of the containing function.\\n\\n    Any function containing a 'coro_yield' is a coroutine function, and while\\n    the compiler might not object until runtime when invoking\\n    it directly with 'func.call', this is invalid and will result in undefined\\n    behavior. A coroutine function can only be invoked through the sequence of\\n    'executor.coro_create' and then one or more 'executor.coro_await' calls.\",\n    \"operands\": [\n      { \"name\": \"yielded\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($yielded^ `:` type($yielded))?\"\n  },\n  {\n    \"name\": \"executor.cos\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.ctpop\",\n    \"summary\": \"count the number of set bits in an integer\",\n    \"description\": \"Returns the number of bits set to 1 in the input integer.\\n    Only i32 and i64 types are supported. For smaller bit types,\\n    user `executor.zext` to extend the width to 32 or 64.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.data_segment\",\n    \"summary\": \"declares a read-only constant resource\",\n    \"description\": \"The `executor.data_segment` operation represents a declaration of a region\\n    of memory.\\n\\n    The region of memory must have an initial `value` attached. If the\\n    `uninitialized` attribute is set, then the `value` is used just to indicate\\n    the size of the zero-initialized data, and `value` should be a dense splat\\n    elements attribute. Only the size is encoded in the compiled artifact (no\\n    actual data is encoded). This lets us create a mechanism for indicating that\\n    globals should be initialized with a new zero-filled allocation, similar to\\n    the BSS section in an ELF.\\n\\n    If `constant` is specified, then the memory is read-only, and this is\\n    exclusive to `uninitialized`.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"value\", \"type\": \"AnyAttrOf<[ElementsAttr, StrAttr]>\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"uninitialized\", \"type\": \"UnitAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"address_space\", \"type\": \"DefaultValuedAttr<Executor_MemoryTypeAttr{host|host_pinned|device|unified|raw}, ::mlir::executor::MemoryType::host>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict\\n      ( `constant` $constant^ )?\\n      (`uninitialized` $uninitialized^ )?\\n      (`align` $alignment^)?\\n      (`address_space` $address_space^)?\\n      $value\"\n  },\n  {\n    \"name\": \"executor.dealloc\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Executor_HostPtr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $ptr `:` type($ptr)\"\n  },\n  {\n    \"name\": \"executor.divf\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.erf\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.exp\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.exp2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.expm1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.extf\",\n    \"description\": \"Cast a floating point type to another floating point type of a wider\\n    bitwidth. The numeric values should be equivalent.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Executor_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Float\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.fcmp\",\n    \"description\": \"`executor.fcmp` performs a comparison between `lhs` and `rhs` floats.\\n    The comparison type is given by the `predicate` attribute.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Float\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"Executor_FCmpTypeAttr{_false|oeq|ogt|oge|olt|ole|one|ord|ueq|ugt|uge|ult|ule|une|uno|_true}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$predicate $lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.file_artifact\",\n    \"description\": \"`executor.file_artifact` op declares a file artifact that will be\\n    emitted to the artifacts directory.\",\n    \"attributes\": [\n      { \"name\": \"path\", \"type\": \"StrAttr\" },\n      { \"name\": \"data\", \"type\": \"ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"$path `data` `(` $data `)` attr-dict\"\n  },\n  {\n    \"name\": \"executor.floor\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.fmax\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Float\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Float\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.fmin\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Float\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Float\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.fptosi\",\n    \"description\": \"`executor.fptosi` casts floating point value to the nearest signed integer\\n    value. This is similar to `static_cast` in C++.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.func\",\n    \"summary\": \"an executor function\",\n    \"description\": \"The `executor.func` operation defines either a function along\\n    with its definition or a function declaration that is defined\\n    externally by runtime bindings.\\n\\n    Example:\\n\\n    ```mlir\\n    executor.func @enqueue_kernel(%arg0: i32, ...)\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<Executor_ExecutorFunctionType>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"executor.get_global\",\n    \"description\": \"The `executor.get_global` operation returns an SSA value representing the\\n    global stored at the given symbol name.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$name attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.getoffset\",\n    \"summary\": \"calculates byte offsets to positions within aggregate types\",\n    \"description\": \"The `executor.getoffset` operation is used to calculate byte offsets within\\n    an aggregate type (e.g. array or table/struct). It is semantically equivalent\\n    to the [LLVM GetElementPtr (GEP) operation](https://llvm.org/docs/GetElementPtr.html),\\n    except that the `executor.getoffset` operation does not perform pointer arithmetic,\\n    it only calculates offsets. While the LLVM GEP op takes a pointer operand to\\n    which the calculated offset is added, this operation does not take a pointer\\n    operand and simply returns the offset which should be added to a base pointer\\n    assuming the base pointer points to data of `elem_type`.\\n\\n    Since `executor` load/store operations take byte offsets as arguments,\\n    we omitted the pointer modification, especially since doing so would\\n    require materialization of excess `inttoptr|ptrtoint` ops.\\n\\n    This operation may be further lowered when targeting interpreters; in\\n    such cases the `executor-expand-ops` pass can be invoked with\\n    `lower-getoffset=true` to lower `executor.getoffset` to more primitive\\n    ops.\\n\\n    Note that internal storage of `staticIndices` uses I64, but if the\\n    DataModel specifies that the pointer or index type width is 32, then\\n    static indices should be convertible to i32 losslessly.\",\n    \"operands\": [\n      { \"name\": \"dynamicIndices\", \"type\": \"Variadic<Executor_Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"staticIndices\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"elem_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` custom<ExecutorMixedIndices>($dynamicIndices, $staticIndices) `]` attr-dict\\n    `:` functional-type(operands, results) `,` $elem_type\"\n  },\n  {\n    \"name\": \"executor.global\",\n    \"summary\": \"defines a global variable\",\n    \"description\": \"The `executor.global` operation describes a global variable declaration and,\\n    optionally, the IR that initializes the global when the program is loaded.\\n\\n    Providing an initialization region is optional. Besides initialization\\n    regions, a global with a numeric constant value can also utilize the\\n    `initial_value` attribute. Only one of `initial_value` and an initialization\\n    region can be used. If the program does not provide an initialization region\\n    or an initial_value, then its state is considered undefined.\\n\\n    If an initialization region is provided, then it should be terminated with\\n    an `executor.return` statement that returns the SSA value which should be\\n    stored into the region. The type of this value must match the `type`\\n    attribute.\\n\\n    The operation can optionally specify that the global is a constant. In this\\n    case, a `executor.set_global` referencing this global is illegal, the global\\n    can only be set by its initialization region.\\n\\n    Please note that ordering of `executor.global` operations matter: Since any\\n    number of `executor.global` variables can be declared, the final backend\\n    should execute the initialization of global variables one after another in\\n    the order that they are listed in the IR. Therefore, certain globals can\\n    depend on the initialization of other globals as long as the global being\\n    used in the initialization region was initialized earlier in the program\\n    declaration.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<TypedAttrInterface>\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name (`constant` $constant^)? `:` $type attr-dict-with-keyword\\n    ($body_region^)?\"\n  },\n  {\n    \"name\": \"executor.icmp\",\n    \"description\": \"`executor.icmp` performs a comparison between `lhs` and `rhs` integers.\\n    The comparison type is given by the `predicate` attribute.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"Executor_ICmpTypeAttr{eq|ne|slt|sgt|sle|sge|ult|ugt}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$predicate $lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.inttoptr\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Ptr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $arg `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.load\",\n    \"description\": \"`executor.load` loads `result` from the memory location given by `ptr +\\n    offset`. The offset is in terms of bytes.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Executor_Ptr\" },\n      { \"name\": \"offset\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Executor_Integer, Executor_Float, Executor_Table, Executor_Ptr]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $ptr `+` $offset `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.load_data_segment\",\n    \"summary\": \"loads a constant resource into a new host buffer\",\n    \"description\": \"The `executor.load_data_segment` operation allocates a new host buffer\\n    and loads the specified resource into the buffer.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Ptr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $name `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"executor.log\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.log10\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.log1p\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.log2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.memcpy\",\n    \"description\": \"`executor.memcpy` copies `num_bytes` bytes from `source` to `dest`. Both\\n    buffers must be host memory buffers.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"Executor_HostVisiblePtr\" },\n      { \"name\": \"src_offset\", \"type\": \"Executor_Index\" },\n      { \"name\": \"dest\", \"type\": \"Executor_HostVisiblePtr\" },\n      { \"name\": \"dest_offset\", \"type\": \"Executor_Index\" },\n      { \"name\": \"num_bytes\", \"type\": \"Executor_Index\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src_offset', 'dest_offset', 'num_bytes']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `+` $src_offset `to` $dest `+` $dest_offset `size` $num_bytes\\n     `:` type(operands)\"\n  },\n  {\n    \"name\": \"executor.mulf\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.muli\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.negf\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.plugin\",\n    \"summary\": \"declare a plugin handle\",\n    \"description\": \"The `executor.plugin` operation defines a new global symbol representing\\n    a handle to a plugin instance that can be invoked with\\n    `executor.call_plugin`.\\n\\n    For TVM FFI backend (`ffi_backend = #executor.ffi_backend<tvm_ffi>`):\\n    This operation declares a callable handle to a TVM FFI function. The\\n    `plugin_name` identifies the TVM FFI library (e.g., a shared library path),\\n    and `function_name` identifies the function symbol within that library.\\n\\n    During lowering, this operation is converted to a global variable that\\n    holds an opaque callable handle. The handle is initialized at module load\\n    time by calling the runtime function `_create_plugin_callable_tvm_ffi`,\\n    which:\\n    - Loads the TVM FFI library from `plugin_name` (caching loaded libraries)\\n    - Resolves the function symbol `function_name` from the library\\n    - Returns an opaque handle wrapping the `tvm::ffi::Function` object\\n\\n    The `function_type` attribute specifies the MLIR function signature\\n    (arguments and results), which is used to validate `executor.call_plugin`\\n    calls. The `config` dictionary may contain additional backend-specific\\n    configuration attributes, but for the TVM FFI backend, it is currently\\n    unused.\\n\\n    Example:\\n\\n    ```mlir\\n    executor.plugin @my_plugin {\\n      plugin_name = \\\"libflashinfer.so\\\",\\n      function_name = \\\"single_prefill_with_kv_cache\\\",\\n      ffi_backend = #executor.ffi_backend<tvm_ffi>,\\n      function_type = (tensor<*xf32>, tensor<*xf32>) -> (),\\n      config = {}\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"plugin_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"function_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"ffi_backend\", \"type\": \"Executor_FFIBackendAttr{tvm_ffi}\" },\n      { \"name\": \"function_type\", \"type\": \"OptionalAttr<TypeAttrOf<FunctionType>>\" },\n      { \"name\": \"config\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict `:` $function_type\"\n  },\n  {\n    \"name\": \"executor.print\",\n    \"description\": \"The `executor.print` op prints a formatted string to \\\"the output stream\\\",\\n    the specifics of which depend on the runtime implementation.\\n\\n    The operation takes an optional format string, which follows the C\\n    `sprintf`-style string formatting rules.\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($format^)? `(` ($arguments^ `:` type($arguments))?  `)`\"\n  },\n  {\n    \"name\": \"executor.ptrtoint\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Executor_Ptr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $arg `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.remf\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.return\",\n    \"summary\": \"global initialization or function return operation\",\n    \"description\": \"The `executor.return` op represents a return within a region that yields\\n    some results, such as a global initialization region.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"executor.round\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.sdivi\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.select\",\n    \"description\": \"`executor.select`op chooses one of the `true_value` or `false_value` based on\\n    value of the predicate. If the value of predicate is 1, `true_value` is chosen\\n    otherwise `false_value` is chosen.\",\n    \"operands\": [\n      { \"name\": \"predicate\", \"type\": \"I1\" },\n      { \"name\": \"true_value\", \"type\": \"Executor_AnyType\" },\n      { \"name\": \"false_value\", \"type\": \"Executor_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $predicate `,` $true_value `,` $false_value `:` type($true_value)\"\n  },\n  {\n    \"name\": \"executor.set_global\",\n    \"description\": \"The `executor.set_global` operation sets the value of the global\\n    with the given symbol name to the given `value`.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $name attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"executor.sfloor_divi\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.shift_lefti\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.shift_right_arithmetici\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.shift_right_logicali\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.siext\",\n    \"description\": \"`executor.siext` extends the bitwidth of an integer, by appending bits to\\n    the most significant side of the nubmer such that the positive/negative\\n    sign of the number is preserved. The positive/negative sign of the number\\n    is determined by interpreting the `operand` as an integer in two's complement\\n    format.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.sin\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.sitofp\",\n    \"description\": \"`executor.sitofp` casts signed integer to the corresponding floating point\\n    value. This is similar to `static_cast` in C++. If value can't be exactly\\n    represented, it is rounded (implementation-defined).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.smax\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.smin\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.sqrt\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.sremi\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.store\",\n    \"description\": \"`executor.store` stores `value` to the memory location given by `ptr +\\n    offset`. The offset is in terms of bytes.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Executor_Ptr\" },\n      { \"name\": \"offset\", \"type\": \"Executor_Index\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[Executor_Ptr, Executor_Integer, Executor_Float, Executor_Table]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `to` $ptr `+` $offset\\n     `:` type($value) `,` qualified(type($ptr)) `,` type($offset)\"\n  },\n  {\n    \"name\": \"executor.str_literal\",\n    \"summary\": \"declares a constant string literal\",\n    \"description\": \"The `executor.str_literal` operation declares an SSA value\\n    that holds a single string literal.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_StrLiteral\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"executor.strided_memref_copy\",\n    \"description\": \"Executes a copy from a source buffer to a destination buffer where the\\n    source and destination may be strided memrefs (with potentially different strides,\\n    but of the same shape).\\n\\n    The `source_aligned_ptr` and `destination_aligned_ptr` are pointers to the aligned data\\n    of the source and destination memrefs, respectively while `src_descriptor` and `dest_descriptor`\\n    are pointers to the caller-allocated MLIR C-ABI compatible ranked memref\\n    descriptors provided for callee use.\\n\\n    When this operation is lowered to the target, only the descriptor is passed. The\\n    data pointers are present here in order to capture the full memory effects of the\\n    operation.\",\n    \"operands\": [\n      { \"name\": \"rank\", \"type\": \"I32\" },\n      { \"name\": \"elem_size\", \"type\": \"Executor_Index\" },\n      { \"name\": \"shape\", \"type\": \"Executor_HostPtr\" },\n      { \"name\": \"src_aligned_ptr\", \"type\": \"Executor_HostVisiblePtr\" },\n      { \"name\": \"src_offset\", \"type\": \"Executor_Index\" },\n      { \"name\": \"src_strides\", \"type\": \"Executor_HostPtr\" },\n      { \"name\": \"dest_aligned_ptr\", \"type\": \"Executor_HostVisiblePtr\" },\n      { \"name\": \"dest_offset\", \"type\": \"Executor_Index\" },\n      { \"name\": \"dest_strides\", \"type\": \"Executor_HostPtr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `(` operands `)`\\n     `:` type(operands)\"\n  },\n  {\n    \"name\": \"executor.subf\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.subi\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"executor.table.create\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"Variadic<Executor_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Table\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`(` $init^ `:` type($init) `)`)? `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.table.dynamic_get\",\n    \"description\": \"The `executor.table.dynamic_get` operation returns the element at the\\n    `index-th` position in the given table. `index` is a variable.\",\n    \"operands\": [\n      { \"name\": \"table\", \"type\": \"Executor_Table\" },\n      { \"name\": \"index\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_AnyType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $table `[` $index `]` `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"executor.table.get\",\n    \"description\": \"The `executor.table.extract` operation returns the element at the `index-th`\\n    position in the given table.\",\n    \"operands\": [\n      { \"name\": \"table\", \"type\": \"Executor_Table\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $table `[` $index `]` `:` type($table)\"\n  },\n  {\n    \"name\": \"executor.table.set\",\n    \"description\": \"The `executor.table.insert` operation insert `value` into the `index`-th\\n    position in the table, returning a new (updated) copy of the table.\",\n    \"operands\": [\n      { \"name\": \"table\", \"type\": \"Executor_Table\" },\n      { \"name\": \"value\", \"type\": \"Executor_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['table', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `into` $table `[` $index `]` `:` type($value) `,` type($table)\"\n  },\n  {\n    \"name\": \"executor.tan\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.tanh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.trunc\",\n    \"description\": \"The `executor.trunc` op truncates an integer to a smaller bitwidth.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.truncf\",\n    \"description\": \"Truncates a floating point type from one bitwidth to a floating point\\n    type of a narrower bitwidth. When an exact conversion is not possible,\\n    rounding occurs using the default rounding mode.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Executor_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Float\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.uitofp\",\n    \"description\": \"`executor.uitofp` casts unsigned integer to the corresponding floating point\\n    value. If value can't be exactly represented, it is rounded\\n    (implementation-defined). Out-of-range casts (truncations) result in mapping\\n    to +/-inf or max/min value depending on whether the target floating point\\n    type has a representation for infinities.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<Executor_ArithIntTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<Executor_ArithFloatTypes>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"executor.umax\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.umin\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Integer\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.undef\",\n    \"summary\": \"produces an undefined value\",\n    \"description\": \"The `executor.undefined` operation produces a value whose binary\\n    storage representation (of the correct size for the scalar or fixed size\\n    aggregate) contains undefined data, and therefore may contain any possible\\n    bit pattern\\n\\n    Current support for lowering `executor.undefined` is very limited. It\\n    is only created at intermediate stages (e.g. to support mem2reg transform,\\n    and translation to certain targets like the Lua interpreter will yield\\n    an error if the IR contains lingering `undef` values).\\n\\n    See also [discussion on LLVM's undef](https://llvm.org/docs/LangRef.html#undefined-values)\\n    values for background on why this op exists and ideas for what we can\\n    do with it in the future.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Executor_Integer, Executor_Float, Executor_Table, Executor_Ptr]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"executor.uremi\",\n    \"description\": \"`executor.uremi` performs an unsigned integer remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Executor_Index\" },\n      { \"name\": \"rhs\", \"type\": \"Executor_Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Index\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"executor.zext\",\n    \"description\": \"`executor.zext` extends the bitwidth of an integer, filling in the\\n    new bits with zeros.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Executor_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Executor_Integer\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"flow.call\",\n    \"summary\": \"Calls a streamable external host function.\",\n    \"description\": \"Calls a function taking/returning tensor values with stream semantics.\\n    Tensors have their shapes captured and may be tied to denote in-place\\n    operations. Asynchronous calls must have no side-effects.\\n\\n    Note that returned tensors must have their shapes declared prior to the call\\n    as this is what allows the call to be made on the stream. If external host\\n    logic is required to compute the shape (avoid at all costs!) a separate\\n    func.call can be used outside of the stream to do so. If shapes are\\n    unknowable until the operation is performed it should be made as a normal\\n    asynchronous host call with 'coarse-fences' instead.\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"argument_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee\\n    `(` $arguments `)` attr-dict `:`\\n    custom<ShapedFunctionType>(ref($arguments),\\n                               type($arguments), $argument_dims,\\n                               type($results), $result_dims,\\n                               $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.channel.count\",\n    \"summary\": \"Returns the total number of participants in the group.\",\n    \"description\": \"Returns the total participant count in the collective communicator group.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$channel `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.channel.default\",\n    \"summary\": \"Returns a default collective communication channel.\",\n    \"description\": \"Returns a channel initialized using the runtime environment.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($group^)?\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.channel.rank\",\n    \"summary\": \"Returns the rank of the local participant in the group.\",\n    \"description\": \"Returns the rank the channel represents as a participant in a collective\\n    group in `[0, count)`.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$channel `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.channel.split\",\n    \"summary\": \"Splits a collective communication channel.\",\n    \"description\": \"Partitions the group associated with the given channel into disjoint\\n    subgroups for each unique value of color. Each new subgroup contains all\\n    participants of the same color and within each subgroup the key argument\\n    is used to define the rank order. When multiple participants in a group\\n    use the same key the tie will be broken using their rank in the parent\\n    group.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" },\n      { \"name\": \"color\", \"type\": \"Index\" },\n      { \"name\": \"key\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"assemblyFormat\": \"$channel `,` $color `,` $key\\n    `:` type($channel) `->` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.collective.all_gather\",\n    \"summary\": \"Performs all-gather operation.\",\n    \"description\": \"Gathers data from all ranks and concatenates them on the 0-th dimension.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_type\", \"type\": \"FLOW_CollectiveElementTypeAttr{si8|ui8|si16|ui16|si32|ui32|si64|ui64|f16|f32|f64|bf16}\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$element_type `,` $target `,` $source `,` $channel `:`\\n    `(` type($target) `,` type($source) `,` type($channel) `)` `->`\\n    custom<ShapedTiedResult>(type($result), $target_dims, $tied_operands)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.collective.all_reduce\",\n    \"summary\": \"Performs all-reduce operation.\",\n    \"description\": \"Reduces data across all the ranks in the channel.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_op\", \"type\": \"FLOW_CollectiveReductionOpAttr{none|sum|product|minimum|maximum|average}\" },\n      { \"name\": \"element_type\", \"type\": \"FLOW_CollectiveElementTypeAttr{si8|ui8|si16|ui16|si32|ui32|si64|ui64|f16|f32|f64|bf16}\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$reduction_op `,` $element_type `,` $target `,` $source `,` $channel `:`\\n    `(` type($target) `,` type($source) `,` type($channel) `)` `->`\\n    custom<ShapedTiedResult>(type($result), $target_dims, $tied_operands)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.collective.all_to_all\",\n    \"summary\": \"Performs all-to-all operation.\",\n    \"description\": \"This operation mutually exchanges data across all of the ranks in the channel.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_type\", \"type\": \"FLOW_CollectiveElementTypeAttr{si8|ui8|si16|ui16|si32|ui32|si64|ui64|f16|f32|f64|bf16}\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$element_type `,` $target `,` $source `,` $channel `:`\\n    `(` type($target) `,` type($source) `,` type($channel) `)` `->`\\n    custom<ShapedTiedResult>(type($result), $target_dims, $tied_operands)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.collective.reduce_scatter\",\n    \"summary\": \"Performs reduce and scatter operations.\",\n    \"description\": \"The operation reduces data across all the ranks in the channel and\\n    scatters the result to each rank.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_op\", \"type\": \"FLOW_CollectiveReductionOpAttr{none|sum|product|minimum|maximum|average}\" },\n      { \"name\": \"element_type\", \"type\": \"FLOW_CollectiveElementTypeAttr{si8|ui8|si16|ui16|si32|ui32|si64|ui64|f16|f32|f64|bf16}\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$reduction_op `,` $element_type `,` $target `,` $source `,` $channel `:`\\n    `(` type($target) `,` type($source) `,` type($channel) `)` `->`\\n    custom<ShapedTiedResult>(type($result), $target_dims, $tied_operands)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.collective.send_recv\",\n    \"summary\": \"Performs a grouped send and receive operation.\",\n    \"description\": \"The operation sends data to the rank specified by send\\n    and receives data from the rank specified by recv. If send is -1, this rank\\n    will not send any data. If recv is -1, this rank will not receive any data\\n    and the output will be all zeros.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"channel\", \"type\": \"FLOW_Channel\" },\n      { \"name\": \"send\", \"type\": \"Index\" },\n      { \"name\": \"recv\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_type\", \"type\": \"FLOW_CollectiveElementTypeAttr{si8|ui8|si16|ui16|si32|ui32|si64|ui64|f16|f32|f64|bf16}\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$element_type `,` $target `,` $source `,` $channel `,` $send `,` $recv `:`\\n    `(` type($target) `,` type($source) `,` type($channel) `,` type($send) `,` type($recv) `)` `->`\\n    custom<ShapedTiedResult>(type($result), $target_dims, $tied_operands)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch\",\n    \"summary\": \"A dispatch of workgroups across a grid.\",\n    \"description\": \"Dispatches workgroups across an grid defined by the captured workload\\n    parameters carrying the information required to compute the workgroup count\\n    at runtime. The function for converting the workload into a 3D workgroup\\n    count is attached to the dispatch entry point and may contain\\n    arbitrary host logic.\",\n    \"operands\": [\n      { \"name\": \"workload\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"argument_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_points\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<DispatchEntryPoints>($entry_points)\\n    (`[` $workload^ `]`)? ``\\n    `(` $arguments `)` attr-dict `:`\\n    custom<ShapedFunctionType>(ref($arguments),\\n                               type($arguments), $argument_dims,\\n                               type($results), $result_dims,\\n                               $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch.entry\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"flow.dispatch.region\",\n    \"summary\": \"A grouping of ops with implicit capture.\",\n    \"description\": \"This op is a container/grouping of ops. It represents a fusion group before\\n    being lowered to a dispatch region. Ops are collected inside of the region\\n    body of the op. Values from parent regions can be captured. Results are\\n    yielded with a `return` terminator and returned from this op.\\n\\n    `dispatch.region` ops are lowered to `dispatch.workgroups` ops. Workgroups\\n    isolated from above. `dispatch.region` ops are a more lightweight\\n    abstraction for implementing fusion heuristics, i.e., the process of\\n    deciding which ops should form a dispatch region.\\n\\n    This op also has a second region: `workload_count`. The arguments to the\\n    region represent the workload for the dispatch, and returns the number of\\n    workgroups for the dispatch. The region is lowered directly to\\n    `workload_count` region of `dispatch.workgroups`.\",\n    \"operands\": [\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"workload\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" },\n      { \"name\": \"workgroup_count\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch.tensor.load\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"flow.dispatch.tensor.store\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"flow.dispatch.tie_shape\",\n    \"summary\": \"Ties a runtime shape to a dispatch I/O argument.\",\n    \"description\": \"Metadata op used to tie a runtime-computed shape with dynamic dimensions to\\n    a dispatch input/output argument. All uses of the argument should use the\\n    pass-through result of this op to allow for SSA-based shape resolution.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"IREETensorExt_DispatchTensor\" },\n      { \"name\": \"dynamic_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IREETensorExt_DispatchTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n    `:` type($result) (`{` $dynamic_dims^ `}`)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch.workgroup.count\",\n    \"summary\": \"Returns the total workgroup count of the grid.\",\n    \"description\": \"The total number of workgroups along each dimension in the dispatch grid.\\n\\n    Represented as a 3D grid classically written as XYZ.\\n    Corresponds to the `NumWorkgroups` SPIR-V built-in and the `gridDim` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = flow.dispatch.workgroup.count[0] : index\\n    %y = flow.dispatch.workgroup.count[1] : index\\n    %z = flow.dispatch.workgroup.count[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch.workgroup.id\",\n    \"summary\": \"Returns the index of the current workgroup in the grid.\",\n    \"description\": \"The global workgroup ID of the current workgroup in the range of\\n    `[0, flow.dispatch.workgroup.count)` along each dimension.\\n\\n    Represented as a 3D grid classically written as XYZ.\\n    Corresponds to the `WorkgroupId` SPIR-V built-in and the `blockIdx` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = flow.dispatch.workgroup.id[0] : index\\n    %y = flow.dispatch.workgroup.id[1] : index\\n    %z = flow.dispatch.workgroup.id[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch.workgroup.size\",\n    \"summary\": \"Returns the size of each workgroup in invocations.\",\n    \"description\": \"The number of local invocations within the current workgroup along each\\n    dimension. Depending on backend this may map to the SIMT thread count or\\n    inner loop nest parameters.\\n\\n    Workgroup sizes are not determined at the flow dialect level as they are\\n    dependent on the target backend determined when lowering into the HAL. It's\\n    still possible to use the symbolic workgroup size inside of dispatch\\n    executables as a placeholder for the resolved value once in the HAL.\\n\\n    Represented as a 3D grid classically written as XYZ.\\n    Corresponds to the `WorkgroupSize` SPIR-V built-in and the `blockDim` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = flow.dispatch.workgroup.size[0] : index\\n    %y = flow.dispatch.workgroup.size[1] : index\\n    %z = flow.dispatch.workgroup.size[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.dispatch.workgroups\",\n    \"summary\": \"A dispatch of workgroups across a 3-dimensional grid.\",\n    \"description\": \"Dispatches some number of workgroups across a 3-dimensional grid. The\\n    body region will be invoked for each workgroup with a unique\\n    `flow.dispatch.workgroup.id` in the range of\\n    `[0, flow.dispatch.workgroup.count)` (along each dimension XYZ).\\n\\n    From the outside the dispatch operation has value semantics: some tensors\\n    (and optionally other primitive types) are consumed and one or more new\\n    result tensors are produced. Inside each workgroup, however, the input and\\n    output tensors are available for arbitrary loads and stores. In many cases\\n    each workgroup will load some particular tile(s) from the input tensors and\\n    store some particular tile(s) to the output tensors unique to that\\n    workgroup. Though it's possible for multiple workgroups to load the same\\n    regions of the input tensors behavior is undefined if multiple workgroups\\n    store to the same regions of the output tensors.\\n\\n    Though the representation is similar to the GPU-style grid dispatch model\\n    here we still have not yet allocated buffers, determined the target device\\n    for execution, or even completed fully resolving shapes/types/etc. Because\\n    of this it's important that the workgroup body use the\\n    `flow.dispatch.workgroup.*` ops to query the workgroup ID/count/size instead\\n    of hardcoding them to a particular set of values. Assume that any workgroup\\n    dispatch may end up being specialized for several different target devices\\n    and even several different variants for a particular target device\\n    (differing workgroup sizes, etc).\\n\\n    Because at this point in the layering devices have not yet been selected the\\n    workgroup count cannot be fully evaluated. Instead workload parameters are\\n    captured that are then passed to a function that when later evaluated\\n    computes the actual workgroup count based on target information. The\\n    workload is not limited to the 3D XYZ grid dispatch of the workgroup count\\n    and can contain any number of parameters used to compute it.\\n\\n    ```mlir\\n    %r = flow.dispatch.workgroups[%c5, %c5](%0, %1)\\n        : (tensor<5x5xf32>, tensor<5xf32>) -> tensor<5x5xf32> =\\n              (%arg0: !iree_tensor_ext.dispatch.tensor<readonly:tensor<5x5xf32>>,\\n               %arg1: !iree_tensor_ext.dispatch.tensor<readonly:tensor<5xf32>>,\\n               %arg2: !iree_tensor_ext.dispatch.tensor<writeonly:tensor<5x5xf32>>) {\\n      ...\\n    }\\n    ```\\n\\n    The number of results of the operation is equal to the number of results\\n    in the type signature (`(tensor<5x5xf32>, tensor<5xf32>) -> tensor<5x5xf32>`).\\n    Each tensor argument and result in the type signature has a corresponding\\n    block argument of type `!iree_tensor_ext.dispatch.tensor`. Furthermore, each argument\\n    has a corresponding `arguments` operand.\\n\\n    There are no `arguments` operands for results, but a result can be tied an\\n    argument by writing the argument operand's SSA value instead of its type:\\n    E.g., in the above example, `-> %0` would tie the first argument to the\\n    result. In that case, there would be no separate block argument for the\\n    result.\",\n    \"operands\": [\n      { \"name\": \"workload\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"argument_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"workgroup_body\", \"type\": \"AnyRegion\" },\n      { \"name\": \"workgroup_count\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`[` $workload^ `]`)? ``\\n    `(` $arguments `)` `:`\\n    custom<ShapedFunctionType>(ref($arguments),\\n                               type($arguments), $argument_dims,\\n                               type($results), $result_dims,\\n                               $tied_operands)\\n    attr-dict-with-keyword\\n    `=` `\\\\n` ` ` ` ` ` `\\n    custom<DispatchWorkgroupBody>(ref(type($arguments)),\\n                                  ref(type($results)),\\n                                  $workgroup_body)\\n    `` custom<DispatchWorkgroupsCountRegion>($workgroup_count)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.ex.stream.fragment\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"flow.executable\",\n    \"summary\": \"Generic executable module.\",\n    \"description\": \"An executable module containing one or more public functions. The contents\\n    of the functions are safe to dispatch and can be lowered further to\\n    target-specific backend IR representations.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    attr-dict-with-keyword\\n    regions\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.executable_end\",\n    \"summary\": \"Terminator pseudo-op for the executable op.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.executable.export\",\n    \"summary\": \"Defines an executable entry point for dispatch operations.\",\n    \"description\": \"Specifies an exported function with an externally-visible alias. Multiple\\n    exports can reference the same internal function.\\n\\n    Each entry point can have a unique workgroup count calculation region.\\n    This region takes the workload parameters passed to each flow.dispatch and\\n    produces an XYZ workgroup count for the 3D grid dispatch.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_ref\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"workgroup_count\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    custom<SymbolAlias>($sym_name, $function_ref)\\n    custom<WorkgroupCountRegion>($workgroup_count)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.func\",\n    \"summary\": \"Streamable function declaration.\",\n    \"description\": \"Declares a function that can be called as an asynchronous streaming\\n    operation via `flow.call`. Today only external functions are allowed.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    ``\\n    custom<ShapedFunctionSignature>($function_type,\\n                                    $tied_operands,\\n                                    $arg_attrs,\\n                                    $res_attrs)\\n    attr-dict-with-keyword\\n    ($body^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.parameter.load\",\n    \"summary\": \"Loads a tensor from a parameter archive.\",\n    \"description\": \"Allocates a new tensor and populates it with data from a parameter archive\\n    file (or in-memory buffer) at the specified byte offset. The scope is an\\n    optional namespace for the parameter key.\\n\\n    Example:\\n    ```mlir\\n    %result = flow.parameter.load %key[%offset] : tensor<4x8xf32>\\n    %result = flow.parameter.load %scope::%key[%offset] : tensor<?x8xf32>{%dim0}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<ParameterReference>($source_scope, $source_key)\\n    `` `[` $source_offset `]`\\n    `:` type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.parameter.write\",\n    \"summary\": \"Writes a tensor to a parameter archive.\",\n    \"description\": \"Writes data from a source tensor to a parameter archive file (or in-memory\\n    buffer) at the specified byte offset. The source tensor is returned\\n    unchanged to establish proper data flow dependencies. The scope is an\\n    optional namespace for the parameter key.\\n\\n    Example:\\n    ```mlir\\n    %written = flow.parameter.write %source -> %key[%offset] : tensor<4x8xf32>\\n    %written = flow.parameter.write %source -> %scope::%key[%offset] : tensor<?x8xf32>{%dim0}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `->` custom<ParameterReference>($target_scope, $target_key)\\n    `` `[` $target_offset `]`\\n    `:` type($source) (`{` $source_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.return\",\n    \"summary\": \"Return from a flow.dispatch_region.\",\n    \"description\": \"Returns the given values from the region and back to the host code.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.alloca\",\n    \"summary\": \"An empty tensor allocation with undefined contents.\",\n    \"description\": \"Returns a new transient tensor allocation with undefined contents.\\n    Subsequent writes must populate any ranges of the tensor that are later\\n    read. The resulting tensor may be long-lived and allocated as part of a\\n    dedicated allocation. Prefer using `flow.tensor.empty` whenever possible as\\n    this op disables nearly all allocation-related optimizations performed by\\n    the compiler. The presence of this op is often an indication of an improper\\n    lowering.\",\n    \"operands\": [\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"assemblyFormat\": \"`:` type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.barrier\",\n    \"summary\": \"Indicates a value that must have a specific affinity.\",\n    \"description\": \"Prevents fusion and scheduling of a value across an affinity boundary.\\n    May introduce copy-on-write behavior if the operand value is used as well as\\n    the result and users should try to keep the operand to a single use by this\\n    op.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"operand_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"AnyAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($result) (`{` $operand_dims^ `}`)?\\n    `on` $target\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.bitcast\",\n    \"summary\": \"Bitcasts a tensor without modifying the contents.\",\n    \"description\": \"Bitcasts a tensor |source| to the shape implied by this operations result\\n    type interleaved with |result_dims|, potentially with a different element\\n    type. For example,\\n\\n    ```\\n    result_dims = {%0, %1}\\n    result_type = tensor<1x?x2x?x3 x!eltype>\\n    ```\\n\\n    produces a tensor of shape [1, %0, 2, %1, 3] and element type `!eltype`.\\n    Note that the source and result tensors must serialized to the same size.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `:`\\n    type($source) (`{` $source_dims^ `}`)? `->`\\n    type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.clone\",\n    \"summary\": \"Performs a full tensor clone operation.\",\n    \"description\": \"Clones the input tensor into an identical output tensor.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"operand_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($result) (`{` $operand_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.constant\",\n    \"summary\": \"Tensor constant that can have dynamic dimensions.\",\n    \"description\": \"Allows specifying a tensor constant of IREE-specific types/attributes.\\n\\n    ```mlir\\n    %cst = flow.tensor.constant #something_tensor_like : tensor<2x2xf32>\\n    %res = math.absf %cst : tensor<2x2xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.dynamic_constant\",\n    \"summary\": \"Tensor constant that can have dynamic dimensions.\",\n    \"description\": \"Allows specifying a tensor constant of IREE-specific types/attributes with\\n    a dynamic shape that approximates a value as passed from the user. This\\n    disables many optimizations and should only be used when testing or\\n    benchmarking and wanting to ensure that dynamic dimension behavior is\\n    preserved.\\n\\n    ```mlir\\n    %cst = flow.tensor.dynamic_constant #something_tensor_like : tensor<2x2xf32> -> tensor<?x2xf32>\\n    %res = math.absf %cst : tensor<?x2xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.empty\",\n    \"summary\": \"An empty tensor carrying metadata but no contents.\",\n    \"description\": \"Returns a tensor with undefined contents. Subsequent writes must populate\\n    any ranges of the tensor that are later read.\",\n    \"operands\": [\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"assemblyFormat\": \"`:` type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.encode\",\n    \"summary\": \"Performs a full tensor encode operation.\",\n    \"description\": \"Encode the input tensor into an encoded output tensor.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"operand_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$operand `:`\\n    type($operand) (`{` $operand_dims^ `}`)? `->`\\n    type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.load\",\n    \"summary\": \"Loads a value from a tensor element.\",\n    \"description\": \"Returns the element at the given location from within the tensor.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[FLOW_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'source', 'result', 'cast<ShapedType>($_self).getElementType()'>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source (`[` $indices^ `]`)? `:`\\n    type($source) (`{` $source_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.reshape\",\n    \"summary\": \"Reshapes a tensor without modifying the contents.\",\n    \"description\": \"Reshapes a tensor |source| to the shape implied by this operations result\\n    type interleaved with |result_dims|. For example,\\n\\n    ```\\n    result_dims = {%0, %1}\\n    result_type = tensor<1x?x2x?x3>\\n    ```\\n\\n    produces a tensor of shape [1, %0, 2, %1, 3] and the same element type.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `:`\\n    type($source) (`{` $source_dims^ `}`)? `->`\\n    type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.slice\",\n    \"summary\": \"Clones a subregion of a tensor.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"lengths\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $start_indices `for` $lengths `]` `:`\\n    type($source) (`{` $source_dims^ `}`)? `->`\\n    type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.splat\",\n    \"summary\": \"Splats a value into a shaped tensor.\",\n    \"description\": \"Returns a tensor initialized to the given primitive value.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"FLOW_PrimitiveType\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'value', 'cast<ShapedType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.store\",\n    \"summary\": \"Stores a value into a tensor element.\",\n    \"description\": \"Returns a tensor with the element at the given index set to the given value.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[FLOW_PrimitiveType, AnyVectorOfNonZeroRank]>\" },\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" },\n      { \"type\": \"TypesMatchWith<'target', 'value', 'cast<ShapedType>($_self).getElementType()'>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target (`[` $indices^ `]`)? `:`\\n    type($target) (`{` $target_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.tie_shape\",\n    \"summary\": \"Ties a runtime shape to a tensor value.\",\n    \"description\": \"Metadata op used to tie tensors with their runtime-computed dynamic\\n    dimensions. This only exists transiently in the IR as a witness to shape\\n    calculations and is removed during lowering.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"dynamic_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n    `:` type($result) (`{` $dynamic_dims^ `}`)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.trace\",\n    \"summary\": \"Traces one or more tensor values at runtime.\",\n    \"description\": \"Traces out to a runtime trace sink (console, log file, etc) the given\\n    tensors. The key is arbitrary and can be used for identifying the set of\\n    values being traced.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<FLOW_Tensor>\" },\n      { \"name\": \"value_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$key `=` `[`\\n    custom<ShapedOperandList>($values, type($values), $value_dims)\\n    `]` attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.transfer\",\n    \"summary\": \"Transfers a tensor to a target by copying if needed.\",\n    \"description\": \"Transfers the tensor from whichever context it may be in to the specified\\n    target context. If the contexts are compatible and can access each others\\n    memory the operation may be elided and otherwise will become one or more\\n    copies to transfer the tensor in cases where staging through an intermediate\\n    context is required.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"operand_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"AnyAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($result) (`{` $operand_dims^ `}`)?\\n    `to` $target\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"flow.tensor.update\",\n    \"summary\": \"Updates a tensor with the contents of another tensor.\",\n    \"description\": \"Updates the target tensor with the contents of the update tensor at the\\n    given offset indices.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<FLOW_Dim>\" },\n      { \"name\": \"update\", \"type\": \"FLOW_Tensor\" },\n      { \"name\": \"update_dims\", \"type\": \"Variadic<FLOW_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FLOW_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$update `,` $target `[` $start_indices `]` `:`\\n    type($update) (`{` $update_dims^ `}`)? `->`\\n    custom<ShapedTiedResult>(type($result), $target_dims)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"func.call\",\n    \"summary\": \"call operation\",\n    \"description\": \"The `func.call` operation represents a direct call to a function that is\\n    within the same symbol scope as the call. The operands and result types of\\n    the call must match the specified function type. The callee is encoded as a\\n    symbol reference attribute named \\\"callee\\\".\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = func.call @my_add(%0, %1) : (f32, f32) -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"no_inline\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"func.call_indirect\",\n    \"summary\": \"indirect call operation\",\n    \"description\": \"The `func.call_indirect` operation represents an indirect call to a value\\n    of function type. The operands and result types of the call must match the\\n    specified function type.\\n\\n    Function values can be created with the\\n    [`func.constant` operation](#funcconstant-constantop).\\n\\n    Example:\\n\\n    ```mlir\\n    %func = func.constant @my_func : (tensor<16xf32>, tensor<16xf32>) -> tensor<16xf32>\\n    %result = func.call_indirect %func(%0, %1) : (tensor<16xf32>, tensor<16xf32>) -> tensor<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"callee\", \"type\": \"FunctionType\" },\n      { \"name\": \"callee_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'callee', 'callee_operands', '::llvm::cast<FunctionType>($_self).getInputs()'>\" },\n      { \"type\": \"TypesMatchWith<'callee', 'results', '::llvm::cast<FunctionType>($_self).getResults()'>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $callee_operands `)` attr-dict `:` type($callee)\"\n  },\n  {\n    \"name\": \"func.constant\",\n    \"summary\": \"constant\",\n    \"description\": \"The `func.constant` operation produces an SSA value from a symbol reference\\n    to a `func.func` operation\\n\\n    Example:\\n\\n    ```mlir\\n    // Reference to function @myfn.\\n    %2 = func.constant @myfn : (tensor<16xf32>, f32) -> tensor<16xf32>\\n\\n    // Equivalent generic forms\\n    %2 = \\\"func.constant\\\"() { value = @myfn } : () -> ((tensor<16xf32>, f32) -> tensor<16xf32>)\\n    ```\\n\\n    MLIR does not allow direct references to functions in SSA operands because\\n    the compiler is multithreaded, and disallowing SSA values to directly\\n    reference a function simplifies this\\n    ([rationale](../Rationale/Rationale.md#multithreading-the-compiler)).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type(results)\"\n  },\n  {\n    \"name\": \"func.func\",\n    \"summary\": \"An operation with a name containing a single `SSACFG` region\",\n    \"description\": \"Operations within the function cannot implicitly capture values defined\\n    outside of the function, i.e. Functions are `IsolatedFromAbove`. All\\n    external references must use function arguments or attributes that establish\\n    a symbolic connection (e.g. symbols referenced by name via a string\\n    attribute like SymbolRefAttr). An external function declaration (used when\\n    referring to a function declared in some other module) has no body. While\\n    the MLIR textual form provides a nice inline syntax for function arguments,\\n    they are internally represented as “block arguments” to the first block in\\n    the region.\\n\\n    Only dialect attribute names may be specified in the attribute dictionaries\\n    for function arguments, results, or the function itself.\\n\\n    Example:\\n\\n    ```mlir\\n    // External function definitions.\\n    func.func private @abort()\\n    func.func private @scribble(i32, i64, memref<? x 128 x f32, #layout_map0>) -> f64\\n\\n    // A function that returns its argument twice:\\n    func.func @count(%x: i64) -> (i64, i64)\\n      attributes {fruit = \\\"banana\\\"} {\\n      return %x, %x: i64, i64\\n    }\\n\\n    // A function with an argument attribute\\n    func.func private @example_fn_arg(%x: i32 {swift.self = unit})\\n\\n    // A function with a result attribute\\n    func.func private @example_fn_result() -> (f64 {dialectName.attrName = 0 : i64})\\n\\n    // A function with an attribute\\n    func.func private @example_fn_attr() attributes {dialectName.attrName = false}\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"no_inline\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"func\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"func.return\",\n    \"summary\": \"Function return operation\",\n    \"description\": \"The `func.return` operation represents a return operation within a function.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number and types must match the signature of the function\\n    that contains the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    func.func @foo() -> (i32, f8) {\\n      ...\\n      return %0, %1 : i32, f8\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"gluon.set_auto_layout\",\n    \"summary\": \"set auto encoding to a concrete encoding type\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"gpu.all_reduce\",\n    \"summary\": \"Reduce values among workgroup.\",\n    \"description\": \"The `all_reduce` op reduces the value of every work item across a local\\n    workgroup. The result is equal for all work items of a workgroup.\\n\\n    For example, both\\n\\n    ```mlir\\n    %1 = gpu.all_reduce add %0 {} : (f32) -> (f32)\\n    %2 = gpu.all_reduce %0 {\\n    ^bb(%lhs : f32, %rhs : f32):\\n      %sum = arith.addf %lhs, %rhs : f32\\n      \\\"gpu.yield\\\"(%sum) : (f32) -> ()\\n    } : (f32) -> (f32)\\n    ```\\n\\n    compute the sum of each work item's %0 value. The first version specifies\\n    the accumulation as operation, whereas the second version specifies the\\n    accumulation as code region. The reduction operation must be one of:\\n    *  Integer types: `add`, `mul`, `minui`, `minsi`, `maxui`, `maxsi`, `and`,\\n       `or`, `xor`\\n    *  Floating point types: `add`, `mul`, `minnumf`, `maxnumf`, `minimumf`,\\n       `maximumf`\\n\\n    If `uniform` flag is set either none or all work items of a workgroup\\n    need to execute this op in convergence.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyIntegerOrFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyIntegerOrFloat\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"OptionalAttr<GPU_AllReduceOperationAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|minimumf|maximumf}>\" },\n      { \"name\": \"uniform\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<AllReduceOperation>($op) $value\\n                          (`uniform` $uniform^)? $body attr-dict\\n                          `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"gpu.alloc\",\n    \"summary\": \"GPU memory allocation operation.\",\n    \"description\": \"The `gpu.alloc` operation allocates a region of memory on the GPU. It is\\n    similar to the `memref.alloc` op, but supports asynchronous GPU execution.\\n\\n    The op does not execute before all async dependencies have finished\\n    executing.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it also returns a !gpu.async.token.\\n\\n    If the `host_shared` keyword is present, the memory will be allocated in a\\n    memory accessible both on host and on device.\\n\\n    Example:\\n\\n    ```mlir\\n    %memref, %token = gpu.alloc async [%dep] host_shared (%width) : memref<64x?xf32, 1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"symbolOperands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hostShared\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies) (` ` `host_shared` $hostShared^)? ` `\\n    `(` $dynamicSizes `)` (`` `[` $symbolOperands^ `]`)? attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"gpu.barrier\",\n    \"summary\": \"Synchronizes all work items of a workgroup.\",\n    \"description\": \"The `barrier` op synchronizes all work items of a workgroup. It is used\\n    to coordinate communication between the work items of the workgroup.\\n\\n    ```mlir\\n    gpu.barrier\\n    ```\\n\\n    waits until all work items in the workgroup have reached the operation\\n    and all memory accesses made by these work items prior to the op are\\n    visible to all work items in the workgroup. Data hazards between work items\\n    accessing the same memory can be avoided by synchronizing work items\\n    in-between these accesses.\\n\\n    If the `memfence` attribute is specified, the set of memory accesses that must\\n    by completed after the barrier resolves is limited to only those accesses that\\n    read from or write to the specified address spaces (though accesses to other\\n    address spaces may be completed as well, especially if a particular combination\\n    of address spaces is not supported on a given backend). In particular,\\n    specifying `memfence []` creates a barrier that is not required to affect\\n    the visibility of any memory operations and is purely used for synchronizing\\n    work items.\\n\\n    ```mlir\\n    // Only workgroup address spaces accesses required to be visible.\\n    gpu.barrier memfence [#gpu.address_space<workgroup>]\\n    // No memory accesses required to be visible.\\n    gpu.barrier memfence []\\n    // All memory accesses required to be visible.\\n    gpu.barrier\\n    ```\\n\\n    Either none or all work items of a workgroup need to execute this op\\n    in convergence.\",\n    \"attributes\": [\n      { \"name\": \"address_spaces\", \"type\": \"OptionalAttr<TypedArrayAttrBase<GPU_AddressSpaceAttr{global|workgroup|private}>>\" }\n    ],\n    \"assemblyFormat\": \"(`memfence` $address_spaces^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.binary\",\n    \"summary\": \"An Op for storing serialized GPU binary objects.\",\n    \"description\": \"GPU binaries provide a semantic mechanism for storing GPU objects,\\n    e.g. the result of compiling a GPU module to an object file.\\n\\n    This operation has 3 arguments:\\n     - The name of the binary.\\n     - An optional attribute implementing the offloading LLVM translation interface.\\n     - An array of GPU object attributes.\\n\\n    During translation, the offloading attribute will be called for translating\\n    GPU `binary` and `launch_func` operations. The default offloading handler is:\\n    `#gpu.select_object`, this handler selects the first object from the array\\n    and embeds it as a string.\\n\\n    Examples:\\n    ```\\n      // Selects the first object.\\n      gpu.binary @myobject [#gpu.object<...>, #gpu.object<...>]\\n      // Uses the `#foo.my_handler` for handling the binary during translation.\\n      gpu.binary @myobject <#foo.my_handler> [#gpu.object<...>, #gpu.object<...>]\\n      // Selects the object with the `#rocdl.target` target attribute.\\n      gpu.binary @myobject <#gpu.select_object<#rocdl.target>> [#gpu.object<...>, #gpu.object<#rocdl.target, ...>]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"offloadingHandler\", \"type\": \"OptionalAttr<ConfinedAttr<AnyAttr, [HasOffloadingTranslationAttrTrait]>>\" },\n      { \"name\": \"objects\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<GPU_ObjectAttr>, [ArrayMinCount<1>]>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name custom<OffloadingHandler>($offloadingHandler) attr-dict $objects\"\n  },\n  {\n    \"name\": \"gpu.block_dim\",\n    \"description\": \"Returns the number of threads in the thread block (aka the block size) along\\n    the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %bDimX = gpu.block_dim x\\n    ```\\n\\n    If `known_block_size` is set on an this operation's enclosing `gpu.func`,\\n    or `gpu.known_block_size` is set on an enclosing `FunctionOpInterface`\\n    implementor, or if the enclosing `gpu.launch` specifies a constant size for\\n    `dimension`'s blocks, these contextual facts may be used to infer that this\\n    operation has a constant value, though such a transformation will not be\\n    performed by canonicalization or the default constant folder. Executions which\\n    cause that constant-value assumption to be false incur undefined behavior.\\n\\n    If `upper_bound` is set, executions where the bblock size along `dimension`\\n    exceeds `upper_bound` cause undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.block_id\",\n    \"description\": \"Returns the block id, i.e. the index of the current block within the grid\\n    along the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %bIdY = gpu.block_id y\\n    ```\\n\\n    If `upper_bound` is set, or if one can be inferred from `known_grid_size`-type\\n    annotations in context, executions where the block index in `dimension` would\\n    be greater than or equal to that bound cause undefined behavior. `upper_bound`\\n    takes priority over bounds inferrable from context.\\n\\n    There is an implicit upper bound of `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.cluster_block_id\",\n    \"description\": \"Returns the block id within the cluster along the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %cBlockIdY = gpu.cluster_block_id y\\n    ```\\n\\n    If `upper_bound` is set, then executing (a lowering of) this operation in an\\n    environment where the number of thread blocks per cluster along `dimension`\\n    is greater than `upper_bound` causes undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxClusterDim` (currently 8).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.cluster_dim\",\n    \"description\": \"Returns the number of cluster identifiers per grid along\\n    the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %cDimX = gpu.cluster_dim x\\n    ```\\n\\n    If `upper_bound` is set, then executing (a lowering of) this operation in an\\n    environment where the clusters per grid is greater than `upper_bound` causes\\n    undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.cluster_dim_blocks\",\n    \"description\": \"Returns the number of thread blocks in the cluster along\\n    the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %cDimBlocksX = gpu.cluster_dim_blocks x\\n    ```\\n\\n    If `upper_bound` is set, then executing (a lowering of) this operation in an\\n    environment where the thread blocks per cluster  is greater than `upper_bound`\\n    causes undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxClusterDim` (currently 8).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.cluster_id\",\n    \"description\": \"Returns the cluster id, i.e. the index of the current cluster within the\\n    grid along the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %cIdY = gpu.cluster_id y\\n    ```\\n\\n    If `upper_bound` is set, then executing (a lowering of) this operation in an\\n    environment where the number of clusters in the grid along `dimension` is\\n    greater than `upper_bound` causes undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.create_2to4_spmat\",\n    \"summary\": \"Create sparse matrix with 2:4 sparsity operation\",\n    \"description\": \"The `gpu.create_2to4_spmat` operation initializes a sparse matrix in dense\\n    format with 2:4 sparsity.\\n    The buffers must already be copied from the host to the device prior to\\n    using this operation. The operation returns a handle to the sparse\\n    matrix descriptor.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %spmat, %token = gpu.create_2to4_spmat async [%dep] {PRUNE_AND_CHECK} %rows, %cols, %mem: memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"rows\", \"type\": \"Index\" },\n      { \"name\": \"cols\", \"type\": \"Index\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"spMat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pruneFlag\", \"type\": \"GPU_Prune2To4SpMatFlagAttr{NONE|PRUNE_ONLY|PRUNE_AND_CHECK}\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n     `{` $pruneFlag `}` $rows `,` $cols `,` $memref attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"gpu.create_bsr\",\n    \"summary\": \"Create sparse matrix in BSR format operation\",\n    \"description\": \"The `gpu.create_bsr` operation initializes a sparse matrix in BSR format\\n    with the given sizes for the matrix and blocks from the given position,\\n    index, and values buffers. The buffers must already be copied from the\\n    host to the device prior to using this operation. The operation returns\\n    a handle to the sparse matrix descriptor.\\n\\n    The BSR format is similar to CSR, where the column indices represent\\n    two-dimensional blocks instead of a single matrix entry. Note that this\\n    operation (currently) only supports storage with **square** blocks,\\n    i.e., `rBlockSize == cBlockSize`.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %spmat, %token = gpu.create_bsr async [%dep]\\n       %brows, %bcols, %bnnz, %rBlockSize, %cBlockSize,\\n       %bRowPos, %bColIdxs, %values : memref<?xindex>, memref<?xindex>, memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"brows\", \"type\": \"Index\" },\n      { \"name\": \"bcols\", \"type\": \"Index\" },\n      { \"name\": \"bnnz\", \"type\": \"Index\" },\n      { \"name\": \"rBlockSize\", \"type\": \"Index\" },\n      { \"name\": \"cBlockSize\", \"type\": \"Index\" },\n      { \"name\": \"bRowPos\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"bColIdxs\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"values\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $brows `,` $bcols `,` $bnnz `,` $rBlockSize `,` $cBlockSize `,`\\n    $bRowPos `,` $bColIdxs `,` $values attr-dict\\n    `:` type($bRowPos) `,` type($bColIdxs) `,` type($values)\"\n  },\n  {\n    \"name\": \"gpu.create_coo\",\n    \"summary\": \"Create sparse matrix in COO format operation\",\n    \"description\": \"The `gpu.create_coo` operation initializes a sparse matrix in COO format\\n    with the given sizes from the given index and values buffers. The buffers\\n    must already be copied from the host to the device prior to using this\\n    operation. The operation returns a handle to the sparse matrix descriptor.\\n    Note that this operation builds the COO in SoA format.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %spmat, %token = gpu.create_coo async [%dep] %rows, %cols, %nnz, %rowIdx,\\n        %colIdx, %values : memref<?xindex>, memref<?xindex>, memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"rows\", \"type\": \"Index\" },\n      { \"name\": \"cols\", \"type\": \"Index\" },\n      { \"name\": \"nnz\", \"type\": \"Index\" },\n      { \"name\": \"rowIdxs\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"colIdxs\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"values\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $rows `,` $cols `,` $nnz `,` $rowIdxs `,` $colIdxs `,` $values attr-dict\\n    `:` type($rowIdxs) `,` type($colIdxs) `,` type($values)\"\n  },\n  {\n    \"name\": \"gpu.create_coo_aos\",\n    \"summary\": \"Create sparse matrix in COO format operation (AoS)\",\n    \"description\": \"The `gpu.create_coo_aos` operation initializes a sparse matrix in COO format\\n    with the given sizes from the given index and values buffers. The buffers\\n    must already be copied from the host to the device prior to using this\\n    operation. The operation returns a handle to the sparse matrix descriptor.\\n    Unlike the default `gpu.create_coo` operation, this operation builds the\\n    COO format from a single index buffer in AoS format (note that this\\n    feature has been deprecated in cuSparse 11.2).\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %spmat, %token = gpu.create_coo_aos async [%dep] %rows, %cols, %nnz, %idxs,\\n        %values : memref<?xindex>, memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"rows\", \"type\": \"Index\" },\n      { \"name\": \"cols\", \"type\": \"Index\" },\n      { \"name\": \"nnz\", \"type\": \"Index\" },\n      { \"name\": \"idxs\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"values\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $rows `,` $cols `,` $nnz `,` $idxs `,` $values attr-dict\\n    `:` type($idxs) `,` type($values)\"\n  },\n  {\n    \"name\": \"gpu.create_csc\",\n    \"summary\": \"Create sparse matrix in CSC format operation\",\n    \"description\": \"The `gpu.create_csc` operation initializes a sparse matrix in CSC format\\n    with the given sizes from the given position, index, and values buffers.\\n    The buffers must already be copied from the host to the device prior to\\n    using this operation. The operation returns a handle to the sparse\\n    matrix descriptor.\\n\\n    The CSC format has exactly the same memory layout as its transpose\\n    in CSR format (and vice versa).\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %spmat, %token = gpu.create_csc async [%dep] %rows, %cols, %nnz, %colPos,\\n        %rowIdx, %values : memref<?xindex>, memref<?xindex>, memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"rows\", \"type\": \"Index\" },\n      { \"name\": \"cols\", \"type\": \"Index\" },\n      { \"name\": \"nnz\", \"type\": \"Index\" },\n      { \"name\": \"colPos\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"rowIdxs\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"values\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $rows `,` $cols `,` $nnz `,` $colPos `,` $rowIdxs `,` $values attr-dict\\n    `:` type($colPos) `,` type($rowIdxs) `,` type($values)\"\n  },\n  {\n    \"name\": \"gpu.create_csr\",\n    \"summary\": \"Create sparse matrix in CSR format operation\",\n    \"description\": \"The `gpu.create_csr` operation initializes a sparse matrix in CSR format\\n    with the given sizes from the given position, index, and values buffers.\\n    The buffers must already be copied from the host to the device prior to\\n    using this operation. The operation returns a handle to the sparse\\n    matrix descriptor.\\n\\n    The CSR format has exactly the same memory layout as its transpose\\n    in CSC format (and vice versa).\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %spmat, %token = gpu.create_csr async [%dep] %rows, %cols, %nnz, %rowPos,\\n        %colIdx, %values : memref<?xindex>, memref<?xindex>, memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"rows\", \"type\": \"Index\" },\n      { \"name\": \"cols\", \"type\": \"Index\" },\n      { \"name\": \"nnz\", \"type\": \"Index\" },\n      { \"name\": \"rowPos\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"colIdxs\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"values\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $rows `,` $cols `,` $nnz `,` $rowPos `,` $colIdxs `,` $values attr-dict\\n    `:` type($rowPos) `,` type($colIdxs) `,` type($values)\"\n  },\n  {\n    \"name\": \"gpu.create_dn_tensor\",\n    \"summary\": \"Create dense tensor operation\",\n    \"description\": \"The `gpu.create_dn_tensor` operation initializes a dense tensor from\\n    the given values buffer and sizes. The buffer must already be copied\\n    from the host to the device prior to using this operation. The\\n    operation returns a handle to the dense tensor descriptor.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %dmat, %token = gpu.create_dn_tensor async [%dep] %mem, %dims : index, index into memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"dims\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dnTensor\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $memref `,` $dims attr-dict `:` type($dims) `into` type($memref)\"\n  },\n  {\n    \"name\": \"gpu.dealloc\",\n    \"summary\": \"GPU memory deallocation operation\",\n    \"description\": \"The `gpu.dealloc` operation frees the region of memory referenced by a\\n    memref which was originally created by the `gpu.alloc` operation. It is\\n    similar to the `memref.dealloc` op, but supports asynchronous GPU execution.\\n\\n    The op does not execute before all async dependencies have finished\\n    executing.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.dealloc async [%dep] %memref : memref<8x64xf32, 1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $memref attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"gpu.destroy_dn_tensor\",\n    \"summary\": \"Destroy dense tensor operation\",\n    \"description\": \"The `gpu.destroy_dn_tensor` operation releases all resources of a dense\\n    tensor represented by a handle that was previously created by a\\n    `gpu.create_dn_tensor` operation.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.destroy_dn_tensor async [%dep] %dnTensor\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"dnTensor\", \"type\": \"GPU_SparseDnTensorHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $dnTensor attr-dict\"\n  },\n  {\n    \"name\": \"gpu.destroy_sp_mat\",\n    \"summary\": \"Destroy sparse matrix operation\",\n    \"description\": \"The `gpu.destroy_sp_mat` operation releases all resources of a sparse\\n    matrix represented by a handle that was previously created by a\\n    one of the sparse matrix creation operations.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.destroy_sp_mat async [%dep] %spmat\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies) $spmat attr-dict\"\n  },\n  {\n    \"name\": \"gpu.dynamic_shared_memory\",\n    \"summary\": \"Get the memref for dynamic shared memory\",\n    \"description\": \"This operation provides a memref pointer to the start of dynamic shared\\n    memory, often referred to as workgroup memory. It's important to note that\\n    this dynamic shared memory needs to be allocated at kernel launch. One can\\n    conveniently utilize the `dynamic_shared_memory_size` parameter of\\n    `gpu.launch` for this purpose.\\n\\n    Examples:\\n    ```mlir\\n    %0 = gpu.dynamic.shared.memory : memref<?xi8, #gpu.address_space<workgroup>>\\n    %1 = memref.view %0[%c8192][] : memref<?xi8, #gpu.address_space<workgroup>>\\n                            to memref<32x64xf32, #gpu.address_space<workgroup>>\\n    %2 = memref.view %0[%c16384][] : memref<?xi8, #gpu.address_space<workgroup>>\\n                            to memref<32x64xf32, #gpu.address_space<workgroup>>\\n    ```\",\n    \"results\": [\n      { \"name\": \"resultMemref\", \"type\": \"MemRefRankOf<[ I8 ], [ 1 ]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($resultMemref)\"\n  },\n  {\n    \"name\": \"gpu.func\",\n    \"summary\": \"Function executable on a GPU\",\n    \"description\": \"Defines a function that can be executed on a GPU. This supports memory\\n    attribution and its body has a particular execution model.\\n\\n    GPU functions are either kernels (as indicated by the `kernel` attribute) or\\n    regular functions. The former can be launched from the host side, while the\\n    latter are device side only.\\n\\n    The memory attribution defines SSA values that correspond to memory buffers\\n    allocated in the memory hierarchy of the GPU (see below).\\n\\n    The operation has one attached region that corresponds to the body of the\\n    function. The region arguments consist of the function arguments without\\n    modification, followed by buffers defined in memory annotations. The body of\\n    a GPU function, when launched, is executed by multiple work items. There are\\n    no guarantees on the order in which work items execute, or on the connection\\n    between them. In particular, work items are not necessarily executed in\\n    lock-step. Synchronization ops such as \\\"gpu.barrier\\\" should be used to\\n    coordinate work items. Declarations of GPU functions, i.e. not having the\\n    body region, are not supported.\\n\\n    A function may optionally be annotated with the block and/or grid sizes\\n    that will be used when it is launched using the `known_block_size` and\\n    `known_grid_size` attributes, respectively. If set, these attributes must\\n    be arrays of three 32-bit integers giving the x, y, and z launch dimensions.\\n    Launching a kernel that has these annotations, or that calls a function with\\n    these annotations, using a block size or grid size other than what is specified\\n    is undefined behavior. These attributes may be set on non-`gpu.func` functions\\n    by using `gpu.known_block_size` or `gpu.known_grid_size`, but this carries\\n    the risk that they will de discarded.\\n\\n    Syntax:\\n\\n    ```\\n    op ::= `gpu.func` symbol-ref-id `(` argument-list `)` (`->`\\n    function-result-list)?\\n           memory-attribution `kernel`? function-attributes? region\\n\\n    memory-attribution ::= (`workgroup` `(` ssa-id-and-type-list `)`)?\\n                           (`private` `(` ssa-id-and-type-list `)`)?\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    gpu.func @foo(%arg0: index)\\n        workgroup(%workgroup: memref<32xf32, 3>)\\n        private(%private: memref<1xf32, 5>)\\n        kernel\\n        attributes {qux: \\\"quux\\\"} {\\n      gpu.return\\n    }\\n    ```\\n\\n    The generic form illustrates the concept\\n\\n    ```mlir\\n    \\\"gpu.func\\\"(%arg: index) {sym_name: \\\"foo\\\", kernel, qux: \\\"quux\\\"} ({\\n    ^bb0(%arg0: index, %workgroup: memref<32xf32, 3>,\\n         %private: memref<1xf32, 5>):\\n      \\\"gpu.return\\\"() : () -> ()\\n    }) : (index) -> ()\\n    ```\\n\\n    Note the non-default memory spaces used in memref types in memory\\n    attribution.\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"workgroup_attrib_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"private_attrib_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"known_block_size\", \"type\": \"ConfinedAttr<OptionalAttr<DenseI32ArrayAttr>, [AttrConstraint<Or<[ IsNullAttr.predicate, And < [ DenseArrayCount < 3 > . predicate , CPred < ([](mlir::Attribute a) {    auto arr = ::llvm::cast<::mlir::DenseI32ArrayAttr>(a).asArrayRef();   return ::llvm::all_of(arr, [](int32_t v) { return v >= 1; }); })($_self) > ] > ]>, with 3 elements (if present) and all elements >= 1>]>\" },\n      { \"name\": \"known_grid_size\", \"type\": \"ConfinedAttr<OptionalAttr<DenseI32ArrayAttr>, [AttrConstraint<Or<[ IsNullAttr.predicate, And < [ DenseArrayCount < 3 > . predicate , CPred < ([](mlir::Attribute a) {    auto arr = ::llvm::cast<::mlir::DenseI32ArrayAttr>(a).asArrayRef();   return ::llvm::all_of(arr, [](int32_t v) { return v >= 1; }); })($_self) > ] > ]>, with 3 elements (if present) and all elements >= 1>]>\" },\n      { \"name\": \"known_cluster_size\", \"type\": \"ConfinedAttr<OptionalAttr<DenseI32ArrayAttr>, [AttrConstraint<Or<[ IsNullAttr.predicate, And < [ DenseArrayCount < 3 > . predicate , CPred < ([](mlir::Attribute a) {    auto arr = ::llvm::cast<::mlir::DenseI32ArrayAttr>(a).asArrayRef();   return ::llvm::all_of(arr, [](int32_t v) { return v >= 1; }); })($_self) > ] > ]>, with 3 elements (if present) and all elements >= 1>]>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"gpu.global_id\",\n    \"description\": \"Returns the unique global workitem/thread id, i.e., the unique index of the\\n    current workitem/thread within all workgroups / grid along the x, y, or z\\n    `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %gidX = gpu.global_id x\\n    %gidX = gpu.global_id x upper_bound 65536\\n    ```\\n\\n    The `upper_bound` attribute defines an upper bound analogously to the ones on\\n    `thread_id` and `block_id`. If one is not set, the bound may be inferred from\\n    a combination of `known_block_size` and `known_grid_size`-type annotations.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.grid_dim\",\n    \"description\": \"Returns the number of thread blocks in the grid along the x, y, or z\\n    `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %gDimZ = gpu.grid_dim z\\n    ```\\n\\n\\n    If `known_grid_size` is set on an this operation's enclosing `gpu.func`,\\n    or `gpu.known_grid_size` is set on an enclosing `FunctionOpInterface`\\n    implementor, or if the enclosing `gpu.launch` specifies a constant size for\\n    `dimension`'s grid length, these contextual facts may be used to infer that this\\n    operation has a constant value, though such a transformation will not be\\n    performed by canonicalization or the default constant folder. Executions which\\n    cause that constant-value assumption to be false incur undefined behavior.\\n\\n    If `upper_bound` is set, executions where the grid size in `dimension` would\\n    exceed `upper_bound` cause undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.host_register\",\n    \"summary\": \"Registers a memref for access from device.\",\n    \"description\": \"This op maps the provided host buffer into the device address space.\\n\\n    This operation may not be supported in every environment, there is not yet a\\n    way to check at runtime whether this feature is supported.\\n\\n    Writes from the host are guaranteed to be visible to device kernels that are\\n    launched afterwards. Writes from the device are guaranteed to be visible on\\n    the host after synchronizing with the device kernel completion.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"gpu.host_unregister\",\n    \"summary\": \"Unregisters a memref for access from device.\",\n    \"description\": \"This op unmaps the provided host buffer from the device address space.\\n\\n      This operation may not be supported in every environment, there is not yet a\\n          way to check at runtime whether this feature is supported.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"gpu.lane_id\",\n    \"description\": \"Returns the lane id within the subgroup (warp/wave).\\n\\n    Example:\\n    ```mlir\\n    %laneId = gpu.lane_id\\n    ```\\n\\n    If `upper_bound` is set, executions with more than `upper_bound` lanes per\\n    subgroup cause undefined behavior. In the abscence of `upper_bound`,\\n    the lane id is still assumed to be non-negative and less than the\\n    target-independent `kMaxSubgroupSize` (currently 128).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.launch\",\n    \"summary\": \"GPU kernel launch operation\",\n    \"description\": \"Launch a kernel on the specified grid of thread blocks. The body of the\\n    kernel is defined by the single region that this operation contains. The\\n    operation takes an optional list of async dependencies followed by six\\n    operands and an optional operand.\\n\\n    The `async` keyword indicates the kernel should be launched asynchronously;\\n    the operation returns a new !gpu.async.token when the keyword is specified.\\n    The kernel launched does not start executing until the ops producing its\\n    async dependencies (optional operands) have completed.\\n\\n    The first three operands (following any async dependencies) are grid sizes\\n    along the x,y,z dimensions and the following three are block sizes along the\\n    x,y,z dimensions. When a lower-dimensional kernel is required, unused sizes\\n    must be explicitly set to `1`.  The last operand is optional and corresponds\\n    to the amount of dynamic shared memory a kernel's workgroup should be\\n    allocated; when this operand is not present, a zero size is assumed.\\n\\n    The body region has at least _twelve_ arguments, or _eighteen_ if cluster\\n    dimensions are present, grouped as follows:\\n\\n    -   three optional arguments that contain cluster identifiers along x,y,z\\n        dimensions;\\n    -   three arguments that contain block identifiers along x,y,z dimensions;\\n    -   three arguments that contain thread identifiers along x,y,z dimensions;\\n    -   operands of the `gpu.launch` operation as is (i.e. the operands for\\n        grid and block sizes).\\n    -   a variadic number of Workgroup memory attributions.\\n    -   a variadic number of Private memory attributions.\\n\\n    The `function` and `module` attributes are optional and specifies\\n    the kernel name and a module in which the kernel should be outlined.\\n\\n    Syntax:\\n\\n    ```\\n    operation ::= `gpu.launch` (`async` (`[` ssa-id-list `]`)? )?\\n                             ( `clusters` `(` ssa-id-list `)` `in` ssa-reassignment )?\\n                             `blocks` `(` ssa-id-list `)` `in` ssa-reassignment\\n                             `threads` `(` ssa-id-list `)` `in` ssa-reassignment\\n                             (dynamic_shared_memory_size ssa-use)?\\n                             (`module(` symbol-ref-id `)`)?\\n                             (`function(` symbol-ref-id `)`)?\\n                             memory-attribution\\n                             region attr-dict?\\n    ssa-reassignment ::= `(` ssa-id `=` ssa-use (`,` ssa-id `=` ssa-use)* `)`\\n    memory-attribution ::= (`workgroup` `(` ssa-id-and-type-list `)`)?\\n                           (`private` `(` ssa-id-and-type-list `)`)?\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    gpu.launch blocks(%bx, %by, %bz) in (%sz_bx = %0, %sz_by = %1, %sz_bz = %2)\\n               threads(%tx, %ty, %tz) in (%sz_tx = %3, %sz_ty = %4, %sz_tz = %5) {\\n      // Block and thread identifiers, as well as block/grid sizes are\\n      // immediately usable inside body region.\\n      \\\"some_op\\\"(%bx, %tx) : (index, index) -> ()\\n      // Assuming %val1 is defined outside the gpu.launch region.\\n      %42 = load %val1[%bx] : memref<?xf32, 1>\\n    }\\n\\n    // Generic syntax explains how the pretty syntax maps to the IR structure.\\n    \\\"gpu.launch\\\"(%cst, %cst, %c1,  // Grid sizes.\\n                 %cst, %c1, %c1)   // Block sizes.\\n\\n        {/*attributes*/}\\n        // All sizes and identifiers have \\\"index\\\" size.\\n        : (index, index, index, index, index, index) -> () {\\n    // The operation passes block and thread identifiers, followed by grid and\\n    // block sizes.\\n    ^bb0(%bx : index, %by : index, %bz : index,\\n         %tx : index, %ty : index, %tz : index,\\n         %num_bx : index, %num_by : index, %num_bz : index,\\n         %num_tx : index, %num_ty : index, %num_tz : index)\\n      \\\"some_op\\\"(%bx, %tx) : (index, index) -> ()\\n      %3 = \\\"memref.load\\\"(%val1, %bx) : (memref<?xf32, 1>, index) -> f32\\n    }\\n\\n    // Launch with memory attributions.\\n    gpu.launch blocks(%bx, %by, %bz) in (%sz_bx = %0, %sz_by = %1, %sz_bz = %2)\\n               threads(%tx, %ty, %tz) in (%sz_tx = %3, %sz_ty = %4, %sz_tz = %5)\\n               workgroup(%workgroup: memref<32xf32, 3>)\\n               private(%private: memref<1xf32, 5>) {\\n      // Block and thread identifiers, as well as block/grid sizes are\\n      // immediately usable inside body region.\\n      \\\"some_op\\\"(%bx, %tx) : (index, index) -> ()\\n      // Assuming %val1 is defined outside the gpu.launch region.\\n      %42 = load %workgroup[%bx] : memref<32xf32, 3>\\n    }\\n\\n    // Launch with clusters.\\n    gpu.launch clusters(%cx, %cy, %cz) in (%sz_cx = %0, %sz_cy = %1, %sz_cz = %2)\\n               blocks(%bx, %by, %bz) in (%sz_bx = %3, %sz_by = %4, %sz_bz = %5)\\n               threads(%tx, %ty, %tz) in (%sz_tx = %6, %sz_ty = %7, %sz_tz = %8)\\n    {\\n      // Cluster, block and thread identifiers, as well as cluster/block/grid\\n      // sizes are immediately usable inside body region.\\n      \\\"some_op\\\"(%cx, %bx, %tx) : (index, index, index) -> ()\\n    }\\n\\n    // Launch with module and function attributes.\\n    gpu.launch blocks(%bx, %by, %bz) in (%sz_bx = %0, %sz_by = %1, %sz_bz = %2)\\n               threads(%tx, %ty, %tz) in (%sz_tx = %3, %sz_ty = %4, %sz_tz = %5)\\n               module(@kernel_module) function(@kernel_func) {\\n      \\\"some_op\\\"(%bx, %tx) : (index, index) -> ()\\n      %42 = load %val1[%bx] : memref<?xf32, 1>\\n    }\\n    ```\\n\\n    Rationale: using operation/block arguments gives analyses a clear way of\\n    understanding that a value has additional semantics (e.g., we will need to\\n    know what value corresponds to threadIdx.x for coalescing). We can recover\\n    these properties by analyzing the operations producing values, but it is\\n    easier just to have that information by construction.\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"gridSizeX\", \"type\": \"Index\" },\n      { \"name\": \"gridSizeY\", \"type\": \"Index\" },\n      { \"name\": \"gridSizeZ\", \"type\": \"Index\" },\n      { \"name\": \"blockSizeX\", \"type\": \"Index\" },\n      { \"name\": \"blockSizeY\", \"type\": \"Index\" },\n      { \"name\": \"blockSizeZ\", \"type\": \"Index\" },\n      { \"name\": \"clusterSizeX\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"clusterSizeY\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"clusterSizeZ\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"dynamicSharedMemorySize\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"module\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"function\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"gpu.launch_func\",\n    \"summary\": \"Launches a function as a GPU kernel\",\n    \"description\": \"Launch a kernel function on the specified grid of thread blocks.\\n    `gpu.launch` operations are lowered to `gpu.launch_func` operations by\\n    outlining the kernel body into a function in a dedicated module, which\\n    reflects the separate compilation process. The kernel function is required\\n    to have the `gpu.kernel` attribute. The module containing the kernel\\n    function is required to be a gpu.module. And finally, the module containing\\n    the kernel module (which thus cannot be the top-level module) is required\\n    to have the `gpu.container_module` attribute. The `gpu.launch_func`\\n    operation has a symbol attribute named `kernel` to identify the fully\\n    specified kernel function to launch (both the gpu.module and func).\\n\\n    The `gpu.launch_func` supports async dependencies: the kernel does not start\\n    executing until the ops producing those async dependencies have completed.\\n\\n    By the default, the host implicitly blocks until kernel execution has\\n    completed. If the `async` keyword is present, the host does not block but\\n    instead a `!gpu.async.token` is returned. Other async GPU ops can take this\\n    token as dependency.\\n\\n    The operation requires at least the grid and block sizes along the x,y,z\\n    dimensions as arguments. When a lower-dimensional kernel is required,\\n    unused sizes must be explicitly set to `1`.\\n\\n    The remaining operands are optional. The first optional operand corresponds\\n    to the amount of dynamic shared memory a kernel's workgroup should be\\n    allocated; when this operand is not present, a zero size is assumed.\\n\\n    The remaining operands if present are passed as arguments to the kernel\\n    function.\\n\\n    The `gpu.launch_func` also supports kernel launching with clusters if\\n    supported by the target architecture. The cluster size can be set by\\n    `clusterSizeX`, `clusterSizeY`, and `clusterSizeZ` arguments. When these\\n    arguments are present, the Op launches a kernel that clusters the given\\n    thread blocks. This feature is exclusive to certain architectures.\\n\\n    Example:\\n\\n    ```mlir\\n    module attributes {gpu.container_module} {\\n\\n      // This module creates a separate compilation unit for the GPU compiler.\\n      gpu.module @kernels {\\n        func.func @kernel_1(%arg0 : f32, %arg1 : memref<?xf32, 1>)\\n            attributes { nvvm.kernel = true } {\\n\\n          // Operations that produce block/thread IDs and dimensions are\\n          // injected when outlining the `gpu.launch` body to a function called\\n          // by `gpu.launch_func`.\\n          %tIdX = gpu.thread_id x\\n          %tIdY = gpu.thread_id y\\n          %tIdZ = gpu.thread_id z\\n\\n          %bDimX = gpu.block_dim x\\n          %bDimY = gpu.block_dim y\\n          %bDimZ = gpu.block_dim z\\n\\n          %bIdX = gpu.block_id x\\n          %bIdY = gpu.block_id y\\n          %bIdZ = gpu.block_id z\\n\\n          %gDimX = gpu.grid_dim x\\n          %gDimY = gpu.grid_dim y\\n          %gDimZ = gpu.grid_dim z\\n\\n          // (Optional)  Cluster size only for support architectures\\n          %cIdX = gpu.cluster_id x\\n          %cIdY = gpu.cluster_id y\\n          %cIdZ = gpu.cluster_id z\\n\\n          %cDimX = gpu.cluster_dim x\\n          %cDimY = gpu.cluster_dim y\\n          %cDimZ = gpu.cluster_dim z\\n\\n          \\\"some_op\\\"(%bx, %tx) : (index, index) -> ()\\n          %42 = load %arg1[%bx] : memref<?xf32, 1>\\n        }\\n      }\\n\\n      %t0 = gpu.wait async\\n      gpu.launch_func\\n          async                           // (Optional) Don't block host, return token.\\n          [%t0]                           // (Optional) Execute only after %t0 has completed.\\n          @kernels::@kernel_1             // Kernel function.\\n          clusters in (%cst, %cst, %cst)  // (Optional) Cluster size only for support architectures.\\n          blocks in (%cst, %cst, %cst)    // Grid size.\\n          threads in (%cst, %cst, %cst)   // Block size.\\n          dynamic_shared_memory_size %s   // (Optional) Amount of dynamic shared\\n                                          // memory to allocate for a workgroup.\\n          args(%arg0 : f32,               // (Optional) Kernel arguments.\\n               %arg1 : memref<?xf32, 1>)\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"gridSizeX\", \"type\": \"LaunchIndx\" },\n      { \"name\": \"gridSizeY\", \"type\": \"LaunchIndx\" },\n      { \"name\": \"gridSizeZ\", \"type\": \"LaunchIndx\" },\n      { \"name\": \"blockSizeX\", \"type\": \"LaunchIndx\" },\n      { \"name\": \"blockSizeY\", \"type\": \"LaunchIndx\" },\n      { \"name\": \"blockSizeZ\", \"type\": \"LaunchIndx\" },\n      { \"name\": \"clusterSizeX\", \"type\": \"Optional<LaunchIndx>\" },\n      { \"name\": \"clusterSizeY\", \"type\": \"Optional<LaunchIndx>\" },\n      { \"name\": \"clusterSizeZ\", \"type\": \"Optional<LaunchIndx>\" },\n      { \"name\": \"dynamicSharedMemorySize\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"kernelOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"asyncObject\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['gridSizeX', 'gridSizeY', 'gridSizeZ', 'blockSizeX', 'blockSizeY', 'blockSizeZ']>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n      (`<` $asyncObject^ `:` type($asyncObject) `>`)?\\n      $kernel\\n      ( `clusters` `in` ` ` `(` $clusterSizeX^ `,` $clusterSizeY `,` $clusterSizeZ `)` )?\\n      `blocks` `in` ` ` `(` $gridSizeX `,` $gridSizeY `,` $gridSizeZ `)`\\n      `threads` `in` ` ` `(` $blockSizeX `,` $blockSizeY `,` $blockSizeZ `)`\\n      custom<LaunchDimType>(type($gridSizeX), ref($clusterSizeX), type($clusterSizeX), type($clusterSizeY), type($clusterSizeZ))\\n      (`dynamic_shared_memory_size` $dynamicSharedMemorySize^)?\\n      custom<LaunchFuncOperands>($kernelOperands, type($kernelOperands)) attr-dict\"\n  },\n  {\n    \"name\": \"gpu.memcpy\",\n    \"summary\": \"GPU memcpy operation\",\n    \"description\": \"The `gpu.memcpy` operation copies the content of one memref to another.\\n\\n    The op does not execute before all async dependencies have finished\\n    executing.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.memcpy async [%dep] %dst, %src : memref<?xf32, 1>, memref<?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $dst`,` $src `:` type($dst)`,` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"gpu.memset\",\n    \"summary\": \"GPU memset operation\",\n    \"description\": \"The `gpu.memset` operation sets the content of memref to a scalar value.\\n\\n    The op does not execute before all async dependencies have finished\\n    executing.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.memset async [%dep] %dst, %value : memref<?xf32, 1>, f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $dst`,` $value `:` type($dst)`,` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"gpu.module\",\n    \"summary\": \"A top level compilation unit containing code to be run on a GPU.\",\n    \"description\": \"GPU module contains code that is intended to be run on a GPU. A host device\\n    can launch this code through a gpu.launc_func that creates a fully\\n    qualified symbol through the gpu.module's symbol and a gpu.func symbol\\n    contained in the gpu.module.\\n\\n    The module's top-level scope is modeled by a single region with a single\\n    block. GPU modules are required to have a name that is used for symbol\\n    resolution by the gpu.launch_func operation.\\n\\n    Using an op with a region to define a GPU module enables \\\"embedding\\\" GPU\\n    modules with SIMT execution models in other dialects in a clean manner and\\n    allows filtering of code regions to execute passes on only code intended to\\n    or not intended to be run on the separate device.\\n\\n    Modules can contain zero or more target attributes. These attributes encode\\n    how to transform modules into binary strings and are used by the\\n    `gpu-module-to-binary` pass to transform modules into GPU binaries.\\n\\n    Modules can contain an optional `OffloadingTranslationAttr` attribute. This\\n    attribute will be used during the `gpu-module-to-binary` pass to specify the\\n    `OffloadingTranslationAttr` used when creating the `gpu.binary` operation.\\n\\n    ```\\n    gpu.module @symbol_name {\\n      gpu.func {}\\n        ...\\n    }\\n    // Module with offloading handler and target attributes.\\n    gpu.module @symbol_name2 <#gpu.select_object<1>> [\\n        #nvvm.target,\\n        #rocdl.target<chip = \\\"gfx90a\\\">] {\\n      gpu.func {}\\n        ...\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"targets\", \"type\": \"OptionalAttr<ConfinedAttr<TypedArrayAttrBase<ConfinedAttr<AnyAttr, [PromisedAttrInterface<GPUTargetAttrInterface>]>>, [ArrayMinCount<1>]>>\" },\n      { \"name\": \"offloadingHandler\", \"type\": \"OptionalAttr<ConfinedAttr<AnyAttr, [HasOffloadingTranslationAttrTrait]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name\\n    (`<` $offloadingHandler^ `>`)?\\n    ($targets^)?\\n    attr-dict-with-keyword $bodyRegion\"\n  },\n  {\n    \"name\": \"gpu.num_subgroups\",\n    \"description\": \"Returns the number of subgroups within a workgroup.\\n\\n    Example:\\n\\n    ```mlir\\n    %numSg = gpu.num_subgroups : index\\n    ```\\n\\n    If `upper_bound` is set, executions with more than `upper_bound` subgroups\\n    per workgroup cause undefined behavior. There is a default upper bound of\\n    `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`upper_bound` $upper_bound^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"gpu.printf\",\n    \"summary\": \"Device-side printf, as in CUDA or OpenCL, for debugging\",\n    \"description\": \"`gpu.printf` takes a literal format string `format` and an arbitrary number of\\n    scalar arguments that should be printed.\\n\\n    The format string is a C-style printf string, subject to any restrictions\\n    imposed by one's target platform.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyTypeOf<[ AnyInteger, Index, AnyFloat ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$format attr-dict (`,` $args^ `:` type($args))?\"\n  },\n  {\n    \"name\": \"gpu.return\",\n    \"summary\": \"Terminator for GPU functions.\",\n    \"description\": \"A terminator operation for regions that appear in the body of `gpu.func`\\n    functions. The operands to the `gpu.return` are the result values returned\\n    by an invocation of the `gpu.func`.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"gpu.rotate\",\n    \"summary\": \"Rotate values within a subgroup.\",\n    \"description\": \"The \\\"rotate\\\" op moves values across lanes in a subgroup (a.k.a., local\\n    invocations) within the same subgroup. The `width` attribute specifies the\\n    number of lanes that participate in the rotation, and must be uniform across\\n    all participating lanes. Further, the first `width` lanes of the subgroup\\n    must be active.\\n\\n    `width` must be a power of two, and `offset` must be in the range\\n    `[0, width)`.\\n\\n    Return the `rotateResult` of the invocation whose id within the group is\\n    calculated as follows:\\n\\n    ```mlir\\n    Invocation ID = ((LaneId + offset) & (width - 1)) + (LaneId & ~(width - 1))\\n    ```\\n\\n    Returns the `rotateResult` and `true` if the current lane id is smaller than\\n    `width`, and poison value and `false` otherwise.\\n\\n    example:\\n\\n    ```mlir\\n    %1, %2 = gpu.rotate %0, 1, 16 : f32\\n    ```\\n\\n    For lane `k`, returns the value from lane `(k + cst1) % width`.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"rotateResult\", \"type\": \"AnyIntegerOrFloatOr1DVector\" },\n      { \"name\": \"valid\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"width\", \"type\": \"ConfinedAttr<I32Attr, [IntPowerOf2]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'rotateResult']>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $offset `,` $width attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"gpu.sddmm\",\n    \"summary\": \"SDDMM operation\",\n    \"description\": \"The `gpu.sddmm` operation performs the SDDMM operation on the given sparse and\\n    dense matrices, and buffer.  The operation expects handles returned by previous\\n    sparse operations to construct an environment and the operands for SDDMM. The\\n    buffer must have been allocated on the device.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.sddmm async [%dep] %dnmatA{TRANSPOSE}, %dnmatB{TRANSPOSE}, %spmatC, %buffer into f32\\n    ```\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"dnmatA\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"dnmatB\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"spmatC\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"modeB\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $dnmatA (`{` $modeA^ `}`)? `,` $dnmatB (`{` $modeB^ `}`)? `,` $spmatC `,` $buffer attr-dict `:` type($buffer) `into` $computeType\"\n  },\n  {\n    \"name\": \"gpu.sddmm_buffer_size\",\n    \"summary\": \"Precompute buffersize for SDDMM operation\",\n    \"description\": \"The `gpu.sddmm_buffer_size` operation returns the buffer size required\\n    to perform the SDDMM operation on the given sparse and dense matrices.\\n    The operation expects handles returned by previous sparse operations\\n    to construct an environment and the operands for SDDMM.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %buffersz, %token = gpu.sddmm_buffer_size async [%dep] %dnmatA{TRANSPOSE}, %dnmatB{TRANSPOSE}, %spmatC into f32\\n    ```\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"dnmatA\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"dnmatB\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"spmatC\", \"type\": \"GPU_SparseSpMatHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"bufferSz\", \"type\": \"Index\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"modeB\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $dnmatA (`{` $modeA^ `}`)? `,` $dnmatB (`{` $modeB^ `}`)? `,` $spmatC attr-dict `into` $computeType\"\n  },\n  {\n    \"name\": \"gpu.set_csr_pointers\",\n    \"summary\": \"SpGEMM get size operation\",\n    \"description\": \"The `gpu.set_csr_pointers` assigns the given positions, coordinates,\\n    and values buffer that reside on the device directly to the given sparse\\n    matrix descriptor in csr format.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a `!gpu.async.token` in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.set_csr_pointers async [%dep] %positions, %coordinates, %values\\n          : memref<?xf32>, memref<?xindex>, memref<?xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"positions\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"coordinates\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"values\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n      $spmat `,` $positions `,` $coordinates `,` $values attr-dict\\n        `:` type($positions) `,` type($coordinates) `,` type($values)\"\n  },\n  {\n    \"name\": \"gpu.set_default_device\",\n    \"summary\": \"Set default GPU for operations after this by index\",\n    \"description\": \"Operation that sets the current default GPU, using a zero-based index\\n    into the set of GPUs on the system. The default GPU setting may be\\n    thread-local.\",\n    \"operands\": [\n      { \"name\": \"devIndex\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $devIndex\"\n  },\n  {\n    \"name\": \"gpu.shuffle\",\n    \"summary\": \"Shuffles values within a subgroup.\",\n    \"description\": \"The \\\"shuffle\\\" op moves values across lanes in a subgroup (a.k.a., local\\n    invocation) within the same subgroup. The `width` argument specifies the\\n    number of lanes that participate in the shuffle, and must be uniform\\n    across all lanes. Further, the first `width` lanes of the subgroup must\\n    be active.\\n\\n    The intepretation of the `offset` arguments depends on the selected\\n    `mode`.\\n\\n    Returns the `shuffleResult` and `true` if the current lane id is smaller\\n    than `width`, and an unspecified value and `false` otherwise.\\n\\n    `xor` example:\\n\\n    ```mlir\\n    %1, %2 = gpu.shuffle xor %0, %offset, %width : f32\\n    ```\\n\\n    For lane `k`, returns the value `%0` from lane `k ^ offset`. Every lane\\n    trades value with exactly one other lane.\\n\\n    `down` example:\\n\\n    ```mlir\\n    %cst1 = arith.constant 1 : i32\\n    %3, %4 = gpu.shuffle down %0, %cst1, %width : f32\\n    ```\\n\\n    For lane `k`, returns the value from lane `(k + cst1)`. If `(k + cst1)` is\\n    bigger than or equal to `width`, the value is poison and `valid` is `false`.\\n\\n    `up` example:\\n\\n    ```mlir\\n    %cst1 = arith.constant 1 : i32\\n    %5, %6 = gpu.shuffle up %0, %cst1, %width : f32\\n    ```\\n\\n    For lane `k`, returns the value from lane `(k - cst1)`. If `(k - cst1)` is\\n    smaller than `0`, the value is poison and `valid` is `false`.\\n\\n    `idx` example:\\n\\n    ```mlir\\n    %cst0 = arith.constant 0 : i32\\n    %7, %8 = gpu.shuffle idx %0, %cst0, %width : f32\\n    ```\\n\\n    Broadcasts the value from lane 0 to all lanes.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyIntegerOrFloatOr1DVector\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"width\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"shuffleResult\", \"type\": \"AnyIntegerOrFloatOr1DVector\" },\n      { \"name\": \"valid\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"GPU_ShuffleModeAttr{xor|up|down|idx}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'shuffleResult']>\" }\n    ],\n    \"assemblyFormat\": \"$mode $value `,` $offset `,` $width attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"gpu.spgemm_copy\",\n    \"summary\": \"SpGEMM copy operation\",\n    \"description\": \"The `gpu.spgemm_copy` operation copies the sparse matrix result of\\n    a SpGEMM computation.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a `!gpu.async.token` in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    gpu.spgemm_copy %spmatA, %spmatB, %spmatC, %spgemmDesc: f32\\n    ```\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"desc\", \"type\": \"GPU_SparseSpGEMMOpHandle\" },\n      { \"name\": \"spmatA\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"spmatB\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"spmatC\", \"type\": \"GPU_SparseSpMatHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"modeB\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $spmatA (`{` $modeA^ `}`)? `,` $spmatB (`{` $modeB^ `}`)? `,` $spmatC `,` $desc attr-dict `:` $computeType\"\n  },\n  {\n    \"name\": \"gpu.spgemm_create_descr\",\n    \"summary\": \"SpGEMM Create Descr operation\",\n    \"description\": \"The `gpu.spgemm_create_descr` creates a descriptor for the SpGEMM operation.\\n    The descriptor describes the SpGEMM operation and stores the internal data\\n    throughout the computation. It needs to be passed as an argument to\\n    spgemm_* operations.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a `!gpu.async.token` in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %desc, %token = gpu.spgemm_create_descr async [%dep]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"desc\", \"type\": \"GPU_SparseSpGEMMOpHandle\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"gpu.spgemm_destroy_descr\",\n    \"summary\": \"SpGEMM Destroy Descr operation\",\n    \"description\": \"The `gpu.spgemm_destroy_descr` destroys the SpGEMM operation descriptor.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a `!gpu.async.token` in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.spgemm_destroy_descr async [%dep] %desc\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"desc\", \"type\": \"GPU_SparseSpGEMMOpHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $desc attr-dict\"\n  },\n  {\n    \"name\": \"gpu.spgemm_work_estimation_or_compute\",\n    \"summary\": \"SpGEMM work estimation operation\",\n    \"description\": \"The `gpu.spgemm_work_estimation_or_compute` is used to call\\n    cusparseSpGEMM_workEstimation or cusparseSpGEMM_compute. Both of them are\\n    for both determining the buffer size and performing the actual computation.\\n    The operation expects handles returned by previous sparse operations to\\n    construct an environment and the operands for SpGEMM.\\n    The buffer must have been allocated on the device.\\n\\n    C' = alpha * op(A) * op(B) + beta * C\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a `!gpu.async.token` in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %bufferSz, %token = gpu.spgemm_work_estimation_or_compute async [%dep] {COMPUTE}\\n                          %desc, %spmatA{NON_TRANSPOSE}, %spmatB{NON_TRANSPOSE},\\n                          %spmatC, %spgemmDesc, %c0, %alloc: f32 into\\n                          memref<0xi8>\\n    ```\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"desc\", \"type\": \"GPU_SparseSpGEMMOpHandle\" },\n      { \"name\": \"spmatA\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"spmatB\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"spmatC\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"bufferSz\", \"type\": \"Index\" },\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"bufferSzNew\", \"type\": \"Index\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"modeB\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" },\n      { \"name\": \"kind\", \"type\": \"GPU_SpGEMMWorkEstimationOrComputeKindAttr{WORK_ESTIMATION|COMPUTE}\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    `{` $kind `}` $spmatA (`{` $modeA^ `}`)? `,` $spmatB (`{` $modeB^ `}`)? `,` $spmatC `,` $desc `,` $bufferSz `,` $buffer  attr-dict `:` $computeType `into` type($buffer)\"\n  },\n  {\n    \"name\": \"gpu.spmat_get_size\",\n    \"summary\": \"SpMat get size operation\",\n    \"description\": \"The `gpu.spmat_get_size` operation retrieves the number of rows, number of\\n    columns, and number of non-zero elements of a sparse matrix.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a `!gpu.async.token` in addition to the environment.\\n\\n    Example:\\n\\n    ```mlir\\n    %rows, %cols, %nnz, %token = gpu.spmat_get_size async [%dep] %spmatC\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmat\", \"type\": \"GPU_SparseSpMatHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"rows\", \"type\": \"Index\" },\n      { \"name\": \"cols\", \"type\": \"Index\" },\n      { \"name\": \"nnz\", \"type\": \"Index\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $spmat attr-dict\"\n  },\n  {\n    \"name\": \"gpu.spmm\",\n    \"summary\": \"SpMM operation\",\n    \"description\": \"The `gpu.spmm` operation performs the SpMM operation on the given sparse and\\n    dense matrix, and buffer.  The operation expects handles returned by previous\\n    sparse operations to construct an environment and the operands for SpMM. The\\n    buffer must have been allocated on the device.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.spmm async [%dep] %spmatA{TRANSPOSE}, %dnmatB{TRANSPOSE}, %dnmatC, %buffers : type($buffers) into f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmatA\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"dnmatB\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"dnmatC\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"buffers\", \"type\": \"Variadic<AnyMemRef>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"modeB\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $spmatA (`{` $modeA^ `}`)? `,` $dnmatB (`{` $modeB^ `}`)? `,` $dnmatC `,` $buffers attr-dict `:` type($buffers) `into` $computeType\"\n  },\n  {\n    \"name\": \"gpu.spmm_buffer_size\",\n    \"summary\": \"Precompute buffersize for SpMM operation\",\n    \"description\": \"The `gpu.spmm_buffer_size` operation returns the buffer size required\\n    to perform the SpMM operation on the given sparse and dense matrix.\\n    The operation expects handles returned by previous sparse operations\\n    to construct an environment and the operands for SpMM.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\\n\\n    Example:\\n\\n    ```mlir\\n    %bufferszs, %token = gpu.spmm_buffer_size async [%dep] %spmatA{TRANSPOSE}, %dnmatB{TRANSPOSE}, %dnmatC : i64 into f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmatA\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"dnmatB\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"dnmatC\", \"type\": \"GPU_SparseDnTensorHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"bufferSzs\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"modeB\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $spmatA (`{` $modeA^ `}`)? `,` $dnmatB (`{` $modeB^ `}`)? `,` $dnmatC attr-dict `:` type($bufferSzs) `into` $computeType\"\n  },\n  {\n    \"name\": \"gpu.spmv\",\n    \"summary\": \"SpMV operation\",\n    \"description\": \"The `gpu.spmv` operation performs the SpMV operation on the given sparse matrix,\\n    dense vectors, and buffer.  The operation expects handles returned by previous\\n    sparse operations to construct an environment and the operands for SpMV. The\\n    buffer must have been allocated on the device.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = gpu.spmv async [%dep] %spmatA{TRANSPOSE}, %dnX, %dnY : memref<?xf64> into bf16\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmatA\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"dnX\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"dnY\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $spmatA (`{` $modeA^ `}`)? `,` $dnX `,` $dnY `,` $buffer attr-dict `:` type($buffer) `into` $computeType\"\n  },\n  {\n    \"name\": \"gpu.spmv_buffer_size\",\n    \"summary\": \"Precompute buffersize for SpMV operation\",\n    \"description\": \"The `gpu.spmv_buffer_size` operation returns the buffer size required\\n    to perform the SpMV operation on the given sparse matrix and dense vectors.\\n    The operation expects handles returned by previous sparse operations\\n    to construct an environment and the operands for SpMV.\\n\\n    If the `async` keyword is present, the op is executed asynchronously (i.e.\\n    it does not block until the execution has finished on the device). In\\n    that case, it returns a !gpu.async.token in addition to the environment.\\n\\n    The matrix arguments can also be associated with one of the following\\n    operators: NON_TRANSPOSE, TRANSPOSE, CONJUGATE_TRANSPOSE. The default value\\n    is NON_TRANSPOSE.\\n\\n    Example:\\n\\n    ```mlir\\n    %buffersz, %token = gpu.spmv_buffer_size async [%dep] %spmatA{TRANSPOSE}, %dnX, %dnY into f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" },\n      { \"name\": \"spmatA\", \"type\": \"GPU_SparseSpMatHandle\" },\n      { \"name\": \"dnX\", \"type\": \"GPU_SparseDnTensorHandle\" },\n      { \"name\": \"dnY\", \"type\": \"GPU_SparseDnTensorHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"bufferSz\", \"type\": \"Index\" },\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modeA\", \"type\": \"GPU_TransposeModeAttr{NON_TRANSPOSE|TRANSPOSE|CONJUGATE_TRANSPOSE}\" },\n      { \"name\": \"computeType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\\n    $spmatA (`{` $modeA^ `}`)? `,` $dnX `,` $dnY attr-dict  `into` $computeType\"\n  },\n  {\n    \"name\": \"gpu.subgroup_broadcast\",\n    \"summary\": \"Broadcasts a value from the specific lane across subgroup\",\n    \"description\": \"Broadcasts a value from one lane to all active lanes in a subgroup. The\\n      result is guaranteed to be uniform across the active lanes in subgroup.\\n\\n      The possible broadcast types are:\\n\\n      * `first_active_lane` - broadcasts the value from the first active lane\\n      in the subgroup.\\n      * `specific_lane` - broadcasts from the specified lane. The lane index\\n      must be uniform and within the subgroup size. The result is poison if the\\n      lane index is invalid, non subgroup-uniform, or if the source lane is not\\n      active.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyType\" },\n      { \"name\": \"lane\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_type\", \"type\": \"GPU_BroadcastTypeAttr{first_active_lane|specific_lane}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $broadcast_type ($lane^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_id\",\n    \"description\": \"Returns the subgroup id, i.e., the index of the current subgroup within the\\n    workgroup.\\n\\n    Example:\\n\\n    ```mlir\\n    %sgId = gpu.subgroup_id : index\\n    ```\\n\\n    Executions where there are more than `upper_bound` subgroups per workgroup\\n    cause undefined behavior. There is an implicit upper bound of `kMaxDim`\\n    (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`upper_bound` $upper_bound^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_compute\",\n    \"summary\": \"GPU warp synchronous matrix multiply accumulate\",\n    \"description\": \"The `gpu.subgroup_mma_compute` operation performs a matrix-multiply accumulate (mma)\\n    operation using all the threads in a subgroup.\\n\\n    This operation takes three `!gpu.mma_matrix`s as arguments: these hold `A`,\\n    `B` and `C`operands for the mma operation. The operation performed is represented\\n    as `C += A * B`. The op returns a `!gpu.mma_matrix` which contains the result of\\n    the operation held by all threads in a subgroup. `a_transpose` or\\n    `b_transpose` if present, signify that the respective operand was loaded in a\\n    transposed manner. The transpose operands are required to map to correct\\n    underlying intrisics but they currently do not seem to affect correctness\\n    even if they are absent given that the operands were loaded correctly using\\n    the `transpose` attribute in `gpu.subgroup_mma_load_matrix` op.\\n\\n    For integer types, the `A` and `B` matrices carry their signedness with their\\n    types. The accumulator type is expected to be signless and imply a signed integer\\n    with a greater width than the other two operands.\\n\\n    This op is meant to be used along with `gpu.subgroup_mma_store_matrix` and\\n    `gpu.subgroup_mma_load_matrix` ops.\\n\\n    Example:\\n\\n    ```mlir\\n    %D = gpu.subgroup_mma_compute_matrix %A, %B, %C :\\n      !gpu.mma_matrix<16x16xf16, \\\"AOp\\\">, !gpu.mma_matrix<16x16xf16, \\\"BOp\\\">>\\n      -> !gpu.mma_matrix<16x16xf16, \\\"COp\\\">\\n    ```\",\n    \"operands\": [\n      { \"name\": \"opA\", \"type\": \"MMAMatrixOf<[ SI8, UI8, F16, F32, F64 ]>\" },\n      { \"name\": \"opB\", \"type\": \"MMAMatrixOf<[ SI8, UI8, F16, F32, F64 ]>\" },\n      { \"name\": \"opC\", \"type\": \"MMAMatrixOf<[ I32, F16, F32, F64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"GPU_MMAMatrix\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_transpose\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"b_transpose\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['opC', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$opA`,` $opB`,` $opC attr-dict `:` type($opA)`,` type($opB) `->` type($res)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_constant_matrix\",\n    \"summary\": \"GPU warp synchronous constant matrix\",\n    \"description\": \"The `gpu.subgroup_mma_constant_matrix` creates a `!gpu.mma_matrix` with\\n    constant elements.\\n\\n    The operation takes a scalar input and return a `!gpu.mma_matrix` where\\n    each element of is equal to the operand constant. The destination\\n    mma_matrix type must have elememt type equal to the constant type. Since\\n    the layout of `!gpu.mma_matrix` is opaque this only support setting all the\\n    elements to the same value.\\n\\n    This op is meant to be used along with `gpu.subgroup_mma_compute`.\\n\\n    Example:\\n\\n    ```mlir\\n     %0 = gpu.subgroup_mma_constant_matrix %a :\\n       !gpu.mma_matrix<16x16xf16, \\\"AOp\\\">\\n     %1 = gpu.subgroup_mma_constant_matrix %b :\\n       !gpu.mma_matrix<16x16xf32, \\\"COp\\\">\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[SI8, UI8, I32, F16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"GPU_MMAMatrix\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'res', 'value', '::llvm::cast<gpu::MMAMatrixType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_elementwise\",\n    \"summary\": \"GPU warp elementwise operation on a matrix\",\n    \"description\": \"The `gpu.subgroup_mma_elementwise` takes `!gpu.mma_matrix` inputs and\\n    compute a new `!gpu.mma_matrix` by applying an elementwise operation to each\\n    element.\\n\\n    Since the operation is elementwise and the matrix type must match, the\\n    matrix elements are processed independently of the matrix layout.\\n\\n    This op is meant to be used along with `gpu.subgroup_mma_compute`.\\n\\n    Example:\\n\\n    ```mlir\\n     %0 =  %A, %B { opType = \\\"ADD\\\" } :\\n      (!gpu.mma_matrix<16x16xf16, \\\"COp\\\">, !gpu.mma_matrix<16x16xf16, \\\"COp\\\">)\\n      -> !gpu.mma_matrix<16x16xf16, \\\"COp\\\">\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<GPU_MMAMatrix>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"GPU_MMAMatrix\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"opType\", \"type\": \"MMAElementWiseAttr{addf|mulf|subf|maxf|minf|divf|addi|muli|subi|divs|divu|negatef|negates|extf|truncf}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['args']>\" }\n    ],\n    \"assemblyFormat\": \"$opType $args attr-dict `:` functional-type($args, $res)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_extract_thread_local\",\n    \"summary\": \"Extract a value from GPU warp by invocation and indices\",\n    \"description\": \"The `gpu.subgroup_mma_extract_thread_local` operation extracts a value from `!gpu.mma_matrix`\\n    that is stored at subgroup level.\\n\\n    This operation takes `!gpu.mma_matrix` as its first operand. It is the source\\n    matrix across a subgroup. The op returns a scalar value stored in the invocation\\n    in the subgroup.\\n\\n    Since `matrix` is packed into the the threads within a subgroup, `indices` are\\n    the indices into the values stored by each thread. That is, an index of 0 (or [0, 0])\\n    does not necessarily refer to the first element of the matrix, but the first element\\n    that a particular thread holds.\\n\\n    The mapping of matrix elements to threads is not defined by this operation and may\\n    not be defined by some lowerings (such as the lowering to SPIR-V). However, if the\\n    size of the subgroup is S, then `subgroup_mma_extract_thread_local` at each index in\\n    `[0, (M * N) / S)` will have the entire matrix extracted across the subgroup.\\n\\n    Example:\\n\\n    ```mlir\\n    %c0 = arith.constant 0 : index\\n    %val = gpu.subgroup_mma_extract_thread_local %m[%c0] : !gpu.mma_matrix<16x16xf32, \\\"AOp\\\"> -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"GPU_MMAMatrix\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyIntegerOrFloat\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'matrix', 'res', '::llvm::cast<gpu::MMAMatrixType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$matrix`[`$indices`]` attr-dict `:` type($matrix) `->` type($res)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_insert_thread_local\",\n    \"summary\": \"Insert a value into GPU warp by invocation and indices\",\n    \"description\": \"The `gpu.subgroup_mma_insert_thread_local` operation inserts a value to `!gpu.mma_matrix`\\n    that is stored at subgroup level.\\n\\n    This operation takes scalar value as its first operand and `!gpu.mma_matrix`\\n    as its second operand. The op inserts the scalar value to the matrix.\\n\\n    Since `matrix` is packed into the the threads within a subgroup, `indices` are\\n    the indices into the values stored by each thread. That is, an index of 0 (or [0, 0])\\n    does not necessarily refer to the first element of the matrix, but the first element\\n    that a particular thread holds.\\n\\n    The mapping of matrix elements to threads is not defined by this operation and may\\n    not be defined by some lowerings (such as the lowering to SPIR-V). However, if the\\n    size of the subgroup is S, then `subgroup_mma_insert_thread_local` at each index in\\n    `[0, (M * N) / S)` will have the entire matrix inserted across the subgroup.\\n\\n    The op returns `!gpu.mma_matrix` with the updated value.\\n\\n    Example:\\n\\n    ```mlir\\n    %c0 = arith.constant 0 : index\\n    %s0 = gpu.subgroup_mma_insert_thread_local %val, %m[%c0] : f16, !gpu.mma_matrix<16x16xf16, \\\"COp\\\">\\n            -> !gpu.mma_matrix<16x16xf16, \\\"COp\\\">\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyIntegerOrFloat\" },\n      { \"name\": \"matrix\", \"type\": \"GPU_MMAMatrix\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"GPU_MMAMatrix\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'matrix', 'value', '::llvm::cast<gpu::MMAMatrixType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value`,` $matrix`[`$indices`]` attr-dict `:` type($value)`,` type($matrix) `->` type($res)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_load_matrix\",\n    \"summary\": \"GPU warp synchronous matrix load\",\n    \"description\": \"The `gpu.subgroup_mma_load_matrix` operation loads a matrix collectively\\n    using all the threads in a subgroup.\\n\\n    This operation takes a memref as its first operand: it is the source matrix\\n    from which data is to be loaded. The op returns a `!gpu.mma_matrix`. The\\n    source memref can be in global memory or shared memory. The load address is\\n    determined using `indices`. The matrix being loaded into is the result.  The\\n    `leadDimension` attribute specifies the leading dimension size of the source\\n    matrix which eventually allows the lowering to determine the size of each\\n    row.  If the `transpose` attribute is present then the op does a transposed load.\\n\\n    For integer types, the resulting `!gpu.mma_matrix` type needs to specify the\\n    signedness of the data if the matrix type is an `A` or `B` operand for\\n    `gpu.subgroup_mma_compute`.\\n\\n    This op is often meant to be used along with `gpu.subgroup_mma_store_matrix` and\\n    `gpu.subgroup_mma_compute`.\\n\\n    Example:\\n\\n    ```mlir\\n     %0 = gpu.subgroup_mma_load_matrix src[%i,%j] : {leadDimension = 32 : i32}\\n          : memref<32x32xf16, 3>, !gpu.mma_matrix<16x16xf16, \\\"AOp\\\">\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcMemref\", \"type\": \"GPU_MMAMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"GPU_MMAMatrix\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"leadDimension\", \"type\": \"IndexAttr\" },\n      { \"name\": \"transpose\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$srcMemref`[`$indices`]` attr-dict `:` type($srcMemref) `->` type($res)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_mma_store_matrix\",\n    \"summary\": \"GPU warp synchronous matrix store\",\n    \"description\": \"The `gpu.subgroup_mma_store_matrix` operation stores a matrix collectively\\n    using all the threads in a subgroup.\\n\\n    This operation takes a `!gpu.mma_matrix` and a memref as operands.\\n    `!gpu.mma_matrix` is the source value containing the data to be stored into the\\n    destination memref which can be in global or shared memory.  The store address\\n    is determined using the indices provided. The `leadDimension` attribute\\n    specifies the leading dimension of the destination matrix. If the\\n    `transpose` attribute is present then the op does a transposed store.\\n\\n    This op is often meant to be used along with `gpu.subgroup_mma_load_matrix` and\\n    `gpu.subgroup_mma_compute`.\\n\\n    Example:\\n\\n    ```mlir\\n    gpu.subgroup_mma_store_matrix %D, %sg[%i,%j] : { leadDimension = 32 : i32}\\n                    : !gpu.mma_matrix<16x16xf16, \\\"COp\\\">, memref<32x32xf16, 3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"MMAMatrixOf<[ SI8, UI8, I32, F16, F32, F64 ]>\" },\n      { \"name\": \"dstMemref\", \"type\": \"GPU_MMAMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"leadDimension\", \"type\": \"IndexAttr\" },\n      { \"name\": \"transpose\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$src`,` $dstMemref`[`$indices`]` attr-dict `:` type($src)`,` type($dstMemref)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_reduce\",\n    \"summary\": \"Reduce values among subgroup.\",\n    \"description\": \"The `subgroup_reduce` op reduces the values of lanes (work items) across a\\n    subgroup.\\n\\n    The subgroup is divided into clusters starting at lane index 0. Within each\\n    cluster, there are `size` lanes, and the lane index advances by `stride`.\\n    A reduction is done for each cluster in parallel: every lane in the cluster\\n    is reduced, and the result is equal for all lanes in the cluster. If `size`\\n    is omitted, there is a single cluster covering the entire subgroup. If\\n    `stride` is omitted, the stride is 1 (the cluster's lanes are contiguous).\\n\\n    When the reduced value is of a vector type, each vector element is reduced\\n    independently. Only 1-d vector types are allowed.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = gpu.subgroup_reduce add %a : (f32) -> f32\\n    %2 = gpu.subgroup_reduce add %b : (vector<4xf16>) -> vector<4xf16>\\n    %3 = gpu.subgroup_reduce add %c cluster(size = 4) : (f32) -> f32\\n    %3 = gpu.subgroup_reduce add %c cluster(size = 4, stride = 2) : (f32) -> f32\\n    ```\\n\\n    If `uniform` flag is set either none or all lanes of a subgroup need to execute\\n    this op in convergence.\\n\\n    The reduction operation must be one of:\\n    *  Integer types: `add`, `mul`, `minui`, `minsi`, `maxui`, `maxsi`, `and`,\\n       `or`, `xor`\\n    *  Floating point types: `add`, `mul`, `minnumf`, `maxnumf`, `minimumf`,\\n       `maximumf`\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyIntegerOrFloatOr1DVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"GPU_AllReduceOperationAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|minimumf|maximumf}\" },\n      { \"name\": \"uniform\", \"type\": \"UnitAttr\" },\n      { \"name\": \"cluster_size\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"cluster_stride\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"custom<AllReduceOperation>($op) $value\\n                          (`uniform` $uniform^)?\\n                          (`cluster` `(` `size` `=` $cluster_size^ (`,` `stride` `=` $cluster_stride^)? `)`)?\\n                          attr-dict\\n                          `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"gpu.subgroup_size\",\n    \"description\": \"Returns the number of threads within a subgroup.\\n\\n    Example:\\n\\n    ```mlir\\n    %sgSz = gpu.subgroup_size : index\\n    ```\\n\\n    Executions where the number of threads per subgroup exceed `upper_bound` cause\\n    undefined behavior. When no `upper_bound` is specified, range analyses and\\n    similar machinery assume the default bound of `kMaxSubgroupSize`, currently\\n    128.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`upper_bound` $upper_bound^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"gpu.terminator\",\n    \"summary\": \"Terminator for GPU launch regions.\",\n    \"description\": \"A terminator operation for regions that appear in the body of `gpu.launch`\\n    operation.  These regions are not expected to return any value so the\\n    terminator takes no operands.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"gpu.thread_id\",\n    \"description\": \"Returns the thread id, i.e. the index of the current thread within the block\\n    along the x, y, or z `dimension`.\\n\\n    Example:\\n\\n    ```mlir\\n    %tIdX = gpu.thread_id x\\n    ```\\n\\n    If `upper_bound` is set, or if one can be inferred from `known_block_size`-type\\n    annotations in context, executions where the thread index would be greater\\n    than or equal to that bound cause undefined behavior.\\n\\n    There is an implicit upper bound of `kMaxDim` (currently uint32_t::max).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"GPU_DimensionAttr{x|y|z}\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"$dimension (`upper_bound` $upper_bound^)? attr-dict\"\n  },\n  {\n    \"name\": \"gpu.wait\",\n    \"summary\": \"Wait for async gpu ops to complete.\",\n    \"description\": \"This op synchronizes the host or the device with a list of dependent ops.\\n\\n    If the op contains the `async` keyword, it returns a new async token which\\n    is synchronized with the op arguments. This new token is merely a shortcut\\n    to the argument list, and one could replace the uses of the result with the\\n    arguments for the same effect. The async version of this op is primarily\\n    used to make each async token have a single use during lowering and\\n    thereby make forks in async execution explicit. Example usage:\\n\\n    ```mlir\\n    %t0 = gpu.foo async : !gpu.async.token\\n    %t1 = gpu.bar async : !gpu.async.token\\n    %t2 = gpu.wait async [%t0, %t1]\\n    // gpu.baz doesn't run until gpu.foo and gpu.bar have both completed, just\\n    // as if the async dependencies were [%t0, %t1].\\n    %t3 = gpu.baz async [%t2]\\n    ```\\n\\n    If the op does not contain the `async` keyword, it does not return a new\\n    async token but blocks until all ops producing the async dependency tokens\\n    finished execution. All dependent memory operations are visible to the host\\n    once this op completes. Example usage:\\n\\n    ```mlir\\n    %t0 = gpu.foo async : !gpu.async.token\\n    %t1 = gpu.bar async : !gpu.async.token\\n    // The gpu.wait op blocks until gpu.foo and gpu.bar have completed.\\n    gpu.wait [%t0, %t1]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"Variadic<GPU_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"Optional<GPU_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"custom<AsyncDependencies>(type($asyncToken), $asyncDependencies) attr-dict\"\n  },\n  {\n    \"name\": \"gpu.warp_execute_on_lane_0\",\n    \"summary\": \"Executes operations in the associated region on thread #0 of aSPMD program\",\n    \"description\": \"`warp_execute_on_lane_0` is an operation used to bridge the gap between\\n    vector programming and SPMD programming model like GPU SIMT. It allows to\\n    trivially convert a region of vector code meant to run on a multiple threads\\n    into a valid SPMD region and then allows incremental transformation to\\n    distribute vector operations on the threads.\\n\\n    Any code present in the region would only be executed on first thread/lane\\n    based on the `laneid` operand. The `laneid` operand is an integer ID between\\n    [0, `warp_size`). The `warp_size` attribute indicates the number of lanes in\\n    a warp.\\n\\n    Operands are vector values distributed on all lanes that may be used by\\n    the single lane execution. The matching region argument is a vector of all\\n    the values of those lanes available to the single active lane. The\\n    distributed dimension is implicit based on the shape of the operand and\\n    argument. the properties of the distribution may be described by extra\\n    attributes (e.g. affine map).\\n\\n    Return values are distributed on all lanes using laneId as index. The\\n    vector is distributed based on the shape ratio between the vector type of\\n    the yield and the result type.\\n    If the shapes are the same this means the value is broadcasted to all lanes.\\n    In the future the distribution can be made more explicit using affine_maps\\n    and will support having multiple Ids.\\n\\n    Therefore the `warp_execute_on_lane_0` operations allow to implicitly copy\\n    between lane0 and the lanes of the warp. When distributing a vector\\n    from lane0 to all the lanes, the data are distributed in a block cyclic way.\\n    For example `vector<64xf32>` gets distributed on 32 threads and map to\\n    `vector<2xf32>` where thread 0 contains vector[0] and vector[1].\\n\\n    During lowering values passed as operands and return value need to be\\n    visible to different lanes within the warp. This would usually be done by\\n    going through memory.\\n\\n    The region is *not* isolated from above. For values coming from the parent\\n    region not going through operands only the lane 0 value will be accesible so\\n    it generally only make sense for uniform values.\\n\\n    Example:\\n    ```\\n    // Execute in parallel on all threads/lanes.\\n    gpu.warp_execute_on_lane_0 (%laneid)[32] {\\n      // Serial code running only on thread/lane 0.\\n      ...\\n    }\\n    // Execute in parallel on all threads/lanes.\\n    ```\\n\\n    This may be lowered to an scf.if region as below:\\n    ```\\n      // Execute in parallel on all threads/lanes.\\n      %cnd = arith.cmpi eq, %laneid, %c0 : index\\n      scf.if %cnd {\\n        // Serial code running only on thread/lane 0.\\n        ...\\n      }\\n      // Execute in parallel on all threads/lanes.\\n    ```\\n\\n    When the region has operands and/or return values:\\n    ```\\n    // Execute in parallel on all threads/lanes.\\n    %0 = gpu.warp_execute_on_lane_0(%laneid)[32]\\n    args(%v0 : vector<4xi32>) -> (vector<1xf32>) {\\n    ^bb0(%arg0 : vector<128xi32>) :\\n      // Serial code running only on thread/lane 0.\\n      ...\\n      gpu.yield %1 : vector<32xf32>\\n    }\\n    // Execute in parallel on all threads/lanes.\\n    ```\\n\\n    values at the region boundary would go through memory:\\n    ```\\n    // Execute in parallel on all threads/lanes.\\n    ...\\n    // Store the data from each thread into memory and Synchronization.\\n    %tmp0 = memreg.alloc() : memref<128xf32>\\n    %tmp1 = memreg.alloc() : memref<32xf32>\\n    %cnd = arith.cmpi eq, %laneid, %c0 : index\\n    vector.store %v0, %tmp0[%laneid] : memref<128xf32>, vector<4xf32>\\n    some_synchronization_primitive\\n    scf.if %cnd {\\n      // Serialized code running only on thread 0.\\n      // Load the data from all the threads into a register from thread 0. This\\n      // allow threads 0 to access data from all the threads.\\n      %arg0 = vector.load %tmp0[%c0] : memref<128xf32>, vector<128xf32>\\n      ...\\n      // Store the data from thread 0 into memory.\\n      vector.store %1, %tmp1[%c0] : memref<32xf32>, vector<32xf32>\\n    }\\n    // Synchronization and load the data in a block cyclic way so that the\\n    // vector is distributed on all threads.\\n    some_synchronization_primitive\\n    %0 = vector.load %tmp1[%laneid] : memref<32xf32>, vector<32xf32>\\n    // Execute in parallel on all threads/lanes.\\n    ```\",\n    \"operands\": [\n      { \"name\": \"laneid\", \"type\": \"Index\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"warp_size\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"warpRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"gpu.yield\",\n    \"summary\": \"GPU yield operation\",\n    \"description\": \"`gpu.yield` is a special terminator operation for blocks inside regions\\n    in gpu ops. It returns values to the immediately enclosing gpu op.\\n\\n    Example:\\n\\n    ```mlir\\n    gpu.yield %f0, %f1 : f32, f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($values^ `:` type($values))?\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.assert\",\n    \"summary\": \"Buffer view contents assertion.\",\n    \"description\": \"Asserts that the buffer view contains a data compatible tensor with the\\n    given encoding. Program execution will abort as if `std.assert` had been\\n    used.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" },\n      { \"name\": \"element_type\", \"type\": \"HAL_ElementType\" },\n      { \"name\": \"encoding_type\", \"type\": \"HAL_EncodingType\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `message` `(` $message `)`\\n    `shape` `(` `[` $shape `]` `)`\\n    `type` `(` $element_type `)`\\n    `encoding` `(` $encoding_type `)`\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.buffer\",\n    \"summary\": \"Buffer view buffer accessor.\",\n    \"description\": \"Returns the buffer backing this view's contents.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.create\",\n    \"summary\": \"Buffer view reference initializer.\",\n    \"description\": \"Creates a reference to a buffer with a particular shape and element type.\\n    The buffer is not copied and both the original and view references must be\\n    synchronized. This makes it easier to associate commonly-carried metadata\\n    along with the contents.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"HAL_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"source_length\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"element_type\", \"type\": \"HAL_ElementType\" },\n      { \"name\": \"encoding_type\", \"type\": \"HAL_EncodingType\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"assemblyFormat\": \"`buffer` `(` $source_buffer `:` type($source_buffer) `)`\\n    `` `[` $source_offset `,` $source_length `]`\\n    `shape` `(` `[` $shape `]` `)`\\n    `type` `(` $element_type `)`\\n    `encoding` `(` $encoding_type `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.dim\",\n    \"summary\": \"Buffer view dimension value query.\",\n    \"description\": \"Returns the value of the given dimension.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `` `[` $index `]`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.element_type\",\n    \"summary\": \"Buffer view element type query.\",\n    \"description\": \"Returns the element type of the buffer view.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_ElementType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.encoding_type\",\n    \"summary\": \"Buffer view encoding type query.\",\n    \"description\": \"Returns the encoding type of the buffer view.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_EncodingType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.rank\",\n    \"summary\": \"Buffer view rank query.\",\n    \"description\": \"Returns the rank of the buffer view.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer_view.trace\",\n    \"summary\": \"Trace value(s) operation.\",\n    \"description\": \"Traces out to a runtime trace sink (console, log file, etc) the given buffer\\n    views and titles them with the given key. The key is informational only and\\n    useful for titling/marking specific sets of buffers for easier searching.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<HAL_BufferView>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$key `=`\\n    $operands `:` type($operands)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer.allocate\",\n    \"summary\": \"Empty buffer allocation operation.\",\n    \"description\": \"Allocates a buffer of the given size.\\n    The size of the buffer returned may be larger than the requested size if the\\n    allocator has specific alignment requirements or minimum allocation sizes.\",\n    \"operands\": [\n      { \"name\": \"minimum_alignment\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"allocation_size\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"storage\", \"type\": \"Util_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`alignment` `(` $minimum_alignment `)`\\n    `:` custom<SizeAwareType>(type($result), $allocation_size) `in` type($storage)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer.allocate.initialized\",\n    \"summary\": \"Buffer allocation with cloning.\",\n    \"description\": \"Allocates a buffer with a copy of the provided contents.\",\n    \"operands\": [\n      { \"name\": \"minimum_alignment\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"storage\", \"type\": \"Util_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`source` `(` $source `:` type($source) `)` `` `[` $offset `,` $length `]`\\n    `alignment` `(` $minimum_alignment `)`\\n    `:` custom<SizeAwareType>(type($result), ref($length)) `in` type($storage)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer.length\",\n    \"summary\": \"Buffer byte length accessor.\",\n    \"description\": \"Returns the allocated size of a buffer in bytes.\\n    May be less than the underlying buffer allocation if this is a subspan or\\n    view into another buffer.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer.storage\",\n    \"summary\": \"Buffer backing storage accessor.\",\n    \"description\": \"Returns the host backing storage of the HAL buffer as a subspan limited to\\n    to the buffer's logical range (meaning that byte 0 of the returned buffer is\\n    byte 0 of the HAL buffer).\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"storage\", \"type\": \"Util_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    `:` type($storage)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer.subspan\",\n    \"summary\": \"Buffer subspan operation.\",\n    \"description\": \"Returns a reference to a subspan of the buffer.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"HAL_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`<` $source_buffer `:` type($source_buffer) `>`\\n    `` `[` $source_offset `,` $length `]`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.buffer.wrap\",\n    \"summary\": \"Host buffer wrapping operation.\",\n    \"description\": \"Tries wrapping a !hal.buffer around host memory backed by the given byte\\n    buffer.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Buffer\" }\n    ],\n    \"assemblyFormat\": \"`source` `(` $source `:` type($source) `)` `` `[` $offset `,` $length `]`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_inline.device.query\",\n    \"summary\": \"Returns a runtime configuration parameter from the device.\",\n    \"description\": \"Queries a device configuration parameter with the given key.\\n    Returns a status indicating whether the pair was recognized/available and if\\n    it was the value converted to the specified type. Queries must return the\\n    same value for the lifetime of the module though may vary from run to run.\\n\\n    This is roughly equivalent to the `sysconf` linux syscall\\n    (https://man7.org/linux/man-pages/man3/sysconf.3.html) in that the exact\\n    set of keys available and their interpretation is target-dependent.\\n\\n    Users of the op must check the `ok` result before using the value as what\\n    set of keys is available may change over time. If in doubt: don't use this.\\n    Each key used adds additional versioning and testing complexity as runtime\\n    code path changes will explode combinatorially and should be treated with as\\n    much care as a binary file format change. Keys should be prefixed with `ex.`\\n    when experimental indicating that they are not expected to be present\\n    forever; all non-experimental keys should be vetted.\\n\\n    Well-known keys: (none yet)\",\n    \"results\": [\n      { \"name\": \"ok\", \"type\": \"I1\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"category\", \"type\": \"StrAttr\" },\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"default_value\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"`key` `(` $category `:` `` `:` $key `)`\\n    `:` type($ok) `,` type($value)\\n    (`=` $default_value^)?\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_loader.executable.dispatch\",\n    \"summary\": \"Inline executable dispatch operation.\",\n    \"description\": \"Dispatches execution to an executable entry point with the given parameters.\",\n    \"operands\": [\n      { \"name\": \"executable\", \"type\": \"HAL_Executable\" },\n      { \"name\": \"entry_point\", \"type\": \"HAL_Ordinal\" },\n      { \"name\": \"workgroup_x\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"workgroup_y\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"workgroup_z\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"constants\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"binding_buffers\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"binding_offsets\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"binding_lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`executable` `(` $executable `:` type($executable) `)`\\n    `` `[` $entry_point `]`\\n    `workgroups` `(` `[`\\n        $workgroup_x `,`\\n        $workgroup_y `,`\\n        $workgroup_z\\n    `]` `)`\\n    (`constants` `(` `[` $constants^ `]` `)`)?\\n    `bindings` `(` `[`\\n    custom<DispatchBindings>($binding_buffers,\\n                             type($binding_buffers),\\n                             $binding_offsets,\\n                             $binding_lengths)\\n    `]` `)`\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_loader.executable.export.ordinal\",\n    \"summary\": \"Executable export ordinal lookup pseudo-op.\",\n    \"description\": \"Resolves an executable export ordinal to a value once ordinals have been\\n    assigned.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_point\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`target` `(` $entry_point `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_loader.executable.load\",\n    \"summary\": \"Dynamically loads an executable.\",\n    \"description\": \"Creates, loads, and dynamically links an executable.\\n\\n    Optional constants provide for specialization of the executable based on\\n    runtime-derived parameters.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"constants\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Executable\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`format` `(` $format `)`\\n    `data` `(` $data `)`\\n    (`constants` `(` `[` $constants^ `]` `)`)?\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_loader.executable.lookup\",\n    \"summary\": \"Executable cache lookup pseudo-op.\",\n    \"description\": \"Used during conversion to provide a placeholder for a globally cached and\\n    possibly lazy-initialized executable.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Executable\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"executable\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`executable` `(` $executable `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal_loader.executable.query_support\",\n    \"summary\": \"Queries whether an executable format is supported.\",\n    \"description\": \"Returns true if the given format is supported by the device loader. This\\n    does not guarantee that loading will succeed as the executable may require\\n    functionality that cannot be met my the hosting runtime environment.\",\n    \"results\": [\n      { \"name\": \"supported\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"executable_format\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`format` `(` $executable_format `)`\\n    `:` type($supported)\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"hal.allocator.allocate\",\n    \"summary\": \"Empty buffer allocation operation.\",\n    \"description\": \"Allocates a buffer of the given size from the allocator.\\n    The size of the buffer returned may be larger than the requested size if the\\n    allocator has specific alignment requirements or minimum allocation sizes.\",\n    \"operands\": [\n      { \"name\": \"allocator\", \"type\": \"HAL_Allocator\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryType\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsage\" },\n      { \"name\": \"result_size\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Buffer\" }\n    ],\n    \"assemblyFormat\": \"`<` $allocator `:` type($allocator) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `type` `(` $memory_types `)`\\n    `usage` `(` $buffer_usage `)`\\n    `:` custom<SizeAwareType>(type($result), $result_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.allocator.compute_size\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.allocator.import\",\n    \"summary\": \"Allocator-supported host buffer import operation.\",\n    \"description\": \"Tries importing host memory backed by the given byte buffer into a\\n    device accessible `!hal.buffer`. The returned buffer may be host-only and\\n    not directly usable on devices. If the mapping cannot be completed (such as\\n    trying to map the host memory as device-local on devices with discrete\\n    memory) then `did_import` will indicate that the returned buffer is null.\",\n    \"operands\": [\n      { \"name\": \"allocator\", \"type\": \"HAL_Allocator\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryType\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsage\" },\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"did_import\", \"type\": \"I1\" },\n      { \"name\": \"result\", \"type\": \"HAL_Buffer\" }\n    ],\n    \"assemblyFormat\": \"`<` $allocator `:` type($allocator) `>`\\n    `source` `(` $source `:` type($source) `)` `` `[` $offset `,` $length `]`\\n    `affinity` `(` $queue_affinity `)`\\n    `type` `(` $memory_types `)`\\n    `usage` `(` $buffer_usage `)`\\n    `:` type($did_import) `,` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.allocator.resolve_memory_properties\",\n    \"summary\": \"Resolves memory properties from resource lifetime and affinity.\",\n    \"description\": \"Resolves the required memory types and buffer usage for a resource with\\n    the given lifetime and affinity. This operation encapsulates the logic\\n    for deriving buffer properties based on stream resource semantics.\\n\\n    This operation can be resolved later in compilation either by canonicalization\\n    for single device affinities or using the topology attribute for multiple devices.\\n\\n    Example:\\n    ```mlir\\n    %memory_types, %buffer_usage = hal.allocator.resolve_memory_properties\\n        for(#hal.device.affinity<@device_a>)\\n        lifetime(transient) : i32, i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryType\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsage\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"lifetime\", \"type\": \"HAL_LifetimeAttr{*|external|staging|transient|variable|constant}\" }\n    ],\n    \"assemblyFormat\": \"(`for` `(` $affinity^ `)`)?\\n    `lifetime` `(` $lifetime `)`\\n    `:` type($memory_types) `,` type($buffer_usage)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.allocator.select\",\n    \"summary\": \"Selects a device/queue from the given set for allocations.\",\n    \"description\": \"Chooses one device and queue affinity pair from the given optimal set that\\n    can service the requested memory type and usage for all devices in the set.\\n    Returns a null device if no pair is able to satisfy the conditions.\",\n    \"operands\": [\n      { \"name\": \"devices\", \"type\": \"Variadic<HAL_Device>\" },\n      { \"name\": \"queue_affinities\", \"type\": \"Variadic<HAL_DeviceQueueAffinity>\" },\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryType\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsage\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"selected_queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" }\n    ],\n    \"assemblyFormat\": \"`from` `(` custom<DeviceQueueAffinityList>($devices, type($devices), $queue_affinities) `)`\\n    `type` `(` $memory_types `)`\\n    `usage` `(` $buffer_usage `)`\\n    `:`\\n    type($selected_device) `,` type($selected_queue_affinity)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_usage\",\n    \"summary\": \"An iree_hal_buffer_usage_t for the given usage bits.\",\n    \"description\": \"Maps buffer usage bits to a runtime `iree_hal_buffer_usage_t` value.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferUsage\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"usage\", \"type\": \"HAL_BufferUsageBitfieldAttr{None|TransferSource|TransferTarget|Transfer|DispatchIndirectParameters|DispatchUniformRead|DispatchStorageRead|DispatchStorageWrite|DispatchStorage|DispatchImageRead|DispatchImageWrite|DispatchImage|SharingExport|SharingReplicate|SharingConcurrent|SharingImmutable|MappingScoped|MappingPersistent|MappingOptional|MappingAccessRandom|MappingAccessSequentialWrite|Mapping}\" }\n    ],\n    \"assemblyFormat\": \"`<` $usage `>`\\n    attr-dict\\n    `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.assert\",\n    \"summary\": \"Buffer view contents assertion.\",\n    \"description\": \"Asserts that the buffer view contains a data compatible tensor with the\\n    given encoding. Program execution will abort as if `std.assert` had been\\n    used.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" },\n      { \"name\": \"element_type\", \"type\": \"HAL_ElementType\" },\n      { \"name\": \"encoding_type\", \"type\": \"HAL_EncodingType\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `message` `(` $message `)`\\n    `shape` `(` `[` $shape `]` `)`\\n    `type` `(` $element_type `)`\\n    `encoding` `(` $encoding_type `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.buffer\",\n    \"summary\": \"Buffer view buffer accessor.\",\n    \"description\": \"Returns the buffer backing this view's contents.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.create\",\n    \"summary\": \"Buffer view reference initializer.\",\n    \"description\": \"Creates a reference to a buffer with a particular shape and element type.\\n    The buffer is not copied and both the original and view references must be\\n    synchronized. This makes it easier to associate commonly-carried metadata\\n    along with the contents.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"HAL_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"source_length\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"element_type\", \"type\": \"HAL_ElementType\" },\n      { \"name\": \"encoding_type\", \"type\": \"HAL_EncodingType\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"assemblyFormat\": \"`buffer` `(` $source_buffer `:` type($source_buffer) `)`\\n    `` `[` $source_offset `,` $source_length `]`\\n    `shape` `(` `[` $shape `]` `)`\\n    `type` `(` $element_type `)`\\n    `encoding` `(` $encoding_type `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.dim\",\n    \"summary\": \"Buffer view dimension value query.\",\n    \"description\": \"Returns the value of the given dimension.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `` `[` $index `]`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.element_type\",\n    \"summary\": \"Buffer view element type query.\",\n    \"description\": \"Returns the element type of the buffer view.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_ElementType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.encoding_type\",\n    \"summary\": \"Buffer view encoding type query.\",\n    \"description\": \"Returns the encoding type of the buffer view.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_EncodingType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.rank\",\n    \"summary\": \"Buffer view rank query.\",\n    \"description\": \"Returns the rank of the buffer view.\",\n    \"operands\": [\n      { \"name\": \"buffer_view\", \"type\": \"HAL_BufferView\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer_view `:` type($buffer_view) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer_view.trace\",\n    \"summary\": \"Trace value(s) operation.\",\n    \"description\": \"Traces out to a runtime trace sink (console, log file, etc) the given buffer\\n    views and titles them with the given key. The key is informational only and\\n    useful for titling/marking specific sets of buffers for easier searching.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<HAL_BufferView>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$key `=`\\n    $operands `:` type($operands)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.allocation.discard\",\n    \"summary\": \"Discards ownership of the underlying buffer allocation by the caller.\",\n    \"description\": \"Decrementing the preserve count indicates that the owner is releasing its\\n    ownership. When the last owner discards their ownership it is safe to\\n    deallocate the buffer allocation even if there are still references\\n    remaining to the buffer object.\\n\\n    Any code that _may_ receive asynchronously allocated buffers must properly\\n    balance their preserves and discards. Code that will never receive\\n    asynchronously allocated buffers - such as those using the inline HAL - can\\n    ignore tracking as there's no asynchronous deallocation and allocation\\n    lifetime is tied to buffer object lifetime. Note that unbalanced discards\\n    will result in either correctness issues (buffer is deallocated too early)\\n    or extended lifetime (buffer cannot be deallocated until all buffer object\\n    references have been released).\\n\\n    Returns true if the caller was the last owner of the allocation and it can\\n    now be deallocated.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.allocation.is_terminal\",\n    \"summary\": \"Returns true if the underlying buffer allocation has a single owner.\",\n    \"description\": \"This can be used to reuse a buffer that has no other owners.\\n\\n    Note that an allocated buffer may have multiple suballocations referencing\\n    it and this query is only for the entire allocation. When reusing a buffer\\n    one should ensure the allocation size matches (or is within threshold) so\\n    that a reuse of 16MB doesn't keep an underlying allocation of 16GB wired.\\n\\n    Since device allocators are expected to reuse memory if in doubt prefer to\\n    dealloca and alloca. This method should only be used in situations where the\\n    buffer types are known to the application (such as fixed input and output\\n    buffers).\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.allocation.preserve\",\n    \"summary\": \"Preserves the underlying buffer allocation for the caller.\",\n    \"description\": \"Preservation is a way to track lifetime of an asynchronously-allocated\\n    buffer on multiple device timelines. Incrementing the preserve count\\n    indicates that there is a new co-owner of the buffer lifetime and that owner\\n    must make a corresponding `hal.buffer.allocation.discard` call to release\\n    their ownership and possibly deallocate the buffer.\\n\\n    Though intended for asynchronously-allocated buffers it is fine to preserve\\n    synchronously-allocated ones. Any code that _may_ receive asynchronously\\n    allocated buffers must properly balance their preserves and discards. Code\\n    that will never receive asynchronously allocated buffers - such as those\\n    using the inline HAL - can ignore tracking.\\n\\n    This preservation roughly translates to retaining logical ownership of the\\n    allocation and may differ from the buffer object reference count. As an\\n    example if the Python GC hasn't run there may still be several references to\\n    the buffer object even after the application has stopped using the buffer.\\n    Tracking the preserve count independently allows the application to eagerly\\n    deallocate the buffer without relying on the lifetime of the object to do\\n    so.\\n\\n    A preserved buffer will still be deallocated if there are no longer any\\n    references to the buffer object. Preserving the buffer only prevents any\\n    other owner from deallocating it while there are references outstanding.\\n    See `hal.buffer.allocation.discard` for more information about releasing\\n    ownership.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.assert\",\n    \"summary\": \"Buffer compatibility assertion.\",\n    \"description\": \"Asserts that the buffer is compatible with the given allocator and usage.\\n    Program execution will abort as if `std.assert` had been used.\\n\\n    This only checks that the buffer can be used and not that it matches the\\n    given parameters exactly. Buffers may be from other allocators so long as\\n    the allocators are compatible (devices can address each other's memory),\\n    the type and usage contain all the requested bits (having more bits is ok),\\n    and the length is at least the requested minimum (as padding may be\\n    ignored).\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"allocator\", \"type\": \"HAL_Allocator\" },\n      { \"name\": \"minimum_length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" },\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryTypeBitfieldAttr{None|Optimal|HostVisible|HostCoherent|HostCached|HostLocal|DeviceVisible|DeviceLocal}\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsageBitfieldAttr{None|TransferSource|TransferTarget|Transfer|DispatchIndirectParameters|DispatchUniformRead|DispatchStorageRead|DispatchStorageWrite|DispatchStorage|DispatchImageRead|DispatchImageWrite|DispatchImage|SharingExport|SharingReplicate|SharingConcurrent|SharingImmutable|MappingScoped|MappingPersistent|MappingOptional|MappingAccessRandom|MappingAccessSequentialWrite|Mapping}\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    `message` `(` $message `)`\\n    `allocator` `(` $allocator `:` type($allocator) `)`\\n    `minimum_length` `(` $minimum_length `)`\\n    `type` `(` $memory_types `)`\\n    `usage` `(` $buffer_usage `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.length\",\n    \"summary\": \"Buffer byte length accessor.\",\n    \"description\": \"Returns the allocated size of a buffer in bytes.\\n    May be less than the underlying buffer allocation if this is a subspan or\\n    view into another buffer.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"assemblyFormat\": \"`<` $buffer `:` type($buffer) `>`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.load\",\n    \"summary\": \"Buffer element load operation.\",\n    \"description\": \"Loads a value from a buffer by mapping it.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"HAL_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[HAL_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"assemblyFormat\": \"`<` $source_buffer `:` type($source_buffer) `>`\\n    `` `[` $source_offset `]`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.store\",\n    \"summary\": \"Buffer element store operation.\",\n    \"description\": \"Stores a value into a buffer by mapping it.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[HAL_PrimitiveType, AnyVectorOfNonZeroRank]>\" },\n      { \"name\": \"target_buffer\", \"type\": \"HAL_BufferType\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"assemblyFormat\": \"`<` $target_buffer `:` type($target_buffer) `>`\\n    `` `[` $target_offset `]`\\n    `value` `(` $value `:` type($value) `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.buffer.subspan\",\n    \"summary\": \"Buffer subspan operation.\",\n    \"description\": \"Returns a reference to a subspan of the buffer.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"HAL_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_BufferType\" }\n    ],\n    \"assemblyFormat\": \"`<` $source_buffer `:` type($source_buffer) `>`\\n    `` `[` $source_offset `,` $length `]`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.channel.create\",\n    \"summary\": \"Creates a new channel for collective communication.\",\n    \"description\": \"Returns a new channel with the given rank associated with the given device\\n    queue. Collective operations using this channel must only be submitted on\\n    compatible queues.\\n\\n    The group and ID are optional and may be null. A rank or count of -1 can be\\n    used to indicate a default inherited from the environment or device\\n    configuration.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"id\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"group\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"rank\", \"type\": \"I32\" },\n      { \"name\": \"count\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Channel\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_ChannelFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `affinity` `(` $queue_affinity `)`\\n    `flags` `(` $flags `)`\\n    `id` `(` $id `)`\\n    `group` `(` $group `)`\\n    `rank` `(` $rank `)`\\n    `count` `(` $count `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.channel.rank_and_count\",\n    \"summary\": \"Returns the rank of the local participant in the group.\",\n    \"description\": \"Returns the rank the channel represents as a participant in a collective\\n    group in `[0, count)` and the total participant count.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"HAL_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"rank\", \"type\": \"I32\" },\n      { \"name\": \"count\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`<` $channel `:` type($channel) `>`\\n    `:` type($rank) `,` type($count)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.channel.split\",\n    \"summary\": \"Splits a collective communication channel.\",\n    \"description\": \"Partitions the group associated with the given channel into disjoint\\n    subgroups for each unique value of color. Each new subgroup contains all\\n    participants of the same color and within each subgroup the key argument\\n    is used to define the rank order. When multiple participants in a group\\n    use the same key the tie will be broken using their rank in the parent\\n    group. A color of -1 indicates that the rank does not participate in any\\n    subgroup and will return a null channel.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"HAL_Channel\" },\n      { \"name\": \"color\", \"type\": \"I32\" },\n      { \"name\": \"key\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Channel\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_ChannelFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $channel `:` type($channel) `>`\\n    `color` `(` $color `)`\\n    `key` `(` $key `)`\\n    `flags` `(` $flags `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.begin\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.command_buffer.begin_debug_group\",\n    \"summary\": \"Pushes a command buffer debug group label.\",\n    \"description\": \"Pushes a new debug group with the given label.\\n    All commands between this and a mandatory matching call to\\n    `hal.command_buffer.end_debug_group` will be grouped together with the\\n    given label.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"label\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `label` `(` $label `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.collective\",\n    \"summary\": \"Command buffer collective dispatch recording operation.\",\n    \"description\": \"Dispatches a collective operation defined by op using the given buffers.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"channel\", \"type\": \"HAL_Channel\" },\n      { \"name\": \"element_count\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"param\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"send_buffer\", \"type\": \"Optional<AnyTypeOf<[ Index, HAL_BufferType ]>>\" },\n      { \"name\": \"send_offset\", \"type\": \"Optional<HAL_DeviceSize>\" },\n      { \"name\": \"send_length\", \"type\": \"Optional<HAL_DeviceSize>\" },\n      { \"name\": \"recv_buffer\", \"type\": \"Optional<AnyTypeOf<[ Index, HAL_BufferType ]>>\" },\n      { \"name\": \"recv_offset\", \"type\": \"Optional<HAL_DeviceSize>\" },\n      { \"name\": \"recv_length\", \"type\": \"Optional<HAL_DeviceSize>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"HAL_CollectiveAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `channel` `(` $channel `:` type($channel) `)`\\n    `op` `(` $op `)`\\n    (`param` `(` $param^ `:` type($param) `)`)?\\n    (`send` `(` $send_buffer^ `:` type($send_buffer) `)`\\n     `` `[` $send_offset `,` $send_length `]`)?\\n    (`recv` `(` $recv_buffer^ `:` type($recv_buffer) `)`\\n     `` `[` $recv_offset `,` $recv_length `]`)?\\n    `count` `(` $element_count `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.copy_buffer\",\n    \"summary\": \"Command buffer buffer copy recording operation.\",\n    \"description\": \"Copies a range of one buffer to another.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"source_buffer\", \"type\": \"AnyTypeOf<[Index, HAL_BufferType]>\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"target_buffer\", \"type\": \"AnyTypeOf<[Index, HAL_BufferType]>\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_CopyFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `source` `(` $source_buffer `:` type($source_buffer) `)`\\n    `` `[` $source_offset `]`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.create\",\n    \"summary\": \"Command buffer allocation operation.\",\n    \"description\": \"Returns a command buffer from the device pool ready to begin recording.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"binding_capacity\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modes\", \"type\": \"HAL_CommandBufferModeBitfieldAttr{None|OneShot|AllowInlineExecution}\" },\n      { \"name\": \"command_categories\", \"type\": \"HAL_CommandCategoryBitfieldAttr{None|Transfer|Dispatch}\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `mode` `(` $modes `)`\\n    `categories` `(` $command_categories `)`\\n    `affinity` `(` $queue_affinity `)`\\n    (`bindings` `(` $binding_capacity^ `)`)?\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.device\",\n    \"summary\": \"Command buffer device query operation.\",\n    \"description\": \"Used during conversion to access the device used to create a command buffer.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"results\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `:` type($device)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.dispatch\",\n    \"summary\": \"Command buffer dispatch recording operation.\",\n    \"description\": \"Dispatches an execution request.\\n    The request may execute overlapped with any other transfer operation or\\n    dispatch made within the same barrier-defined sequence.\\n\\n    The provided constant data and binding list will be recorded into the\\n    command buffer and need not remain live beyond the call. Push constants are\\n    always 4-byte values and treated as opaque, meaning that they may be\\n    bit-casted floats, bit-packed booleans, etc. The provided buffers may either\\n    be HAL buffers or indirect references into the command buffer binding table.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"executable\", \"type\": \"HAL_Executable\" },\n      { \"name\": \"entry_point\", \"type\": \"HAL_Ordinal\" },\n      { \"name\": \"workgroup_x\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"workgroup_y\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"workgroup_z\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"constants\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"binding_buffers\", \"type\": \"Variadic<AnyTypeOf<[ Index, HAL_BufferType ]>>\" },\n      { \"name\": \"binding_offsets\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"binding_lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_DispatchFlagsAttr{None|Reserved}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `target` `(` $executable `:` type($executable) `)`\\n    `` `[` $entry_point `]`\\n    `workgroups` `(` `[`\\n        $workgroup_x `,`\\n        $workgroup_y `,`\\n        $workgroup_z\\n    `]` `)`\\n    (`constants` `(` `[` $constants^ `]` `)`)?\\n    `bindings` `(` `[`\\n    custom<Bindings>($binding_buffers,\\n                     type($binding_buffers),\\n                     $binding_offsets,\\n                     $binding_lengths)\\n    `]` `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.dispatch.indirect\",\n    \"summary\": \"Command buffer indirect dispatch recording operation.\",\n    \"description\": \"Dispatches an execution request with a deferred workgroup count.\\n    This is the same as iree_hal_command_buffer_dispatch but the workgroup count\\n    is read from the given |workgroups_ref| buffer at the specified offset as\\n    3 uint32_t XYZ values immediately before performing the dispatch. This\\n    allows prior dispatches within the command sequence to populate the\\n    workgroup count or the workgroup count to change across submissions of the\\n    same reusable command buffer.\\n\\n    The provided constant data and binding list will be recorded into the\\n    command buffer and need not remain live beyond the call. Push constants are\\n    always 4-byte values and treated as opaque, meaning that they may be\\n    bit-casted floats, bit-packed booleans, etc. The provided buffers may either\\n    be HAL buffers or indirect references into the command buffer binding table.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"executable\", \"type\": \"HAL_Executable\" },\n      { \"name\": \"entry_point\", \"type\": \"HAL_Ordinal\" },\n      { \"name\": \"workgroups_buffer\", \"type\": \"AnyTypeOf<[Index, HAL_BufferType]>\" },\n      { \"name\": \"workgroups_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"constants\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"binding_buffers\", \"type\": \"Variadic<AnyTypeOf<[ Index, HAL_BufferType ]>>\" },\n      { \"name\": \"binding_offsets\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"binding_lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_DispatchFlagsAttr{None|Reserved}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `target` `(` $executable `:` type($executable) `)`\\n    `` `[` $entry_point `]`\\n    `workgroups` `(` $workgroups_buffer `:` type($workgroups_buffer) `)`\\n    `` `[` $workgroups_offset `]`\\n    (`constants` `(` `[` $constants^ `]` `)`)?\\n    `bindings` `(` `[`\\n    custom<Bindings>($binding_buffers,\\n                     type($binding_buffers),\\n                     $binding_offsets,\\n                     $binding_lengths)\\n    `]` `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.dispatch.symbol\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.command_buffer.end\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.command_buffer.end_debug_group\",\n    \"summary\": \"Pops a command buffer debug group label.\",\n    \"description\": \"Pops a debug group from the stack.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.execution_barrier\",\n    \"summary\": \"Command buffer execution barrier recording operation.\",\n    \"description\": \"Defines an execution dependency between all commands recorded before the\\n    barrier and all commands recorded after the barrier. Only the stages\\n    provided will be affected.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_stage_mask\", \"type\": \"HAL_ExecutionStageBitfieldAttr{None|CommandIssue|CommandProcess|Dispatch|Transfer|CommandRetire|Host}\" },\n      { \"name\": \"target_stage_mask\", \"type\": \"HAL_ExecutionStageBitfieldAttr{None|CommandIssue|CommandProcess|Dispatch|Transfer|CommandRetire|Host}\" },\n      { \"name\": \"flags\", \"type\": \"HAL_ExecutionBarrierFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `source` `(` $source_stage_mask `)`\\n    `target` `(` $target_stage_mask `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.fill_buffer\",\n    \"summary\": \"Command buffer buffer fill recording operation.\",\n    \"description\": \"Fills the target buffer with the given repeating value.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"target_buffer\", \"type\": \"AnyTypeOf<[Index, HAL_BufferType]>\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"pattern\", \"type\": \"HAL_FillPatternType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_FillFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `,` $length `]`\\n    `pattern` `(` $pattern `:` type($pattern) `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.finalize\",\n    \"summary\": \"Finalizes command buffer recording.\",\n    \"description\": \"Ends recording into the command buffer and prepares it for submission.\\n    No more commands may be recorded into the command buffer.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.command_buffer.push_descriptor_set\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.command_buffer.update_buffer\",\n    \"summary\": \"Command buffer buffer update recording operation.\",\n    \"description\": \"Copies a range of a host buffer into a device buffer. The host buffer\\n    contents will be captured at the time of the call and embedded in the\\n    command buffer.\",\n    \"operands\": [\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"source_buffer\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Util_Size\" },\n      { \"name\": \"target_buffer\", \"type\": \"AnyTypeOf<[Index, HAL_BufferType]>\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_UpdateFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $command_buffer `:` type($command_buffer) `>`\\n    `source` `(` $source_buffer `:` type($source_buffer) `{` $source_size `}` `)`\\n    `` `[` $source_offset `]`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.descriptor_set_layout.create\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.device.allocator\",\n    \"summary\": \"Device allocator accessor operation.\",\n    \"description\": \"Returns the allocator that can be used to allocate buffers compatible with\\n    the device.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Allocator\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>` `:` type($result) attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.memoize\",\n    \"summary\": \"Memoizes resources for a particular device and queue affinity.\",\n    \"description\": \"Executes the nested region once per device and affinity mask and memoizes\\n    the results such that future references return the previously memoized\\n    values. The initial execution may happen on demand or be hoisted to module\\n    initialization time.\\n\\n    Any uses of the device or affinity specified within the nested region will\\n    be substituted with the appropriate device and affinity during memoization.\\n    All other implicitly captured values must be either constant or global\\n    values available at the time the memoization occurs.\\n\\n    It is valid for the nested region contents to be inlined in place and never\\n    memoized. This can be useful when diagnosing memoization issues and can be\\n    forced with the `--iree-hal-memoization=false` flag.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `->` type($results)\\n    attr-dict-with-keyword\\n    $body\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.query\",\n    \"summary\": \"Returns a runtime configuration parameter from the device.\",\n    \"description\": \"Queries a device configuration parameter with the given key.\\n    Returns a status indicating whether the pair was recognized/available and if\\n    it was the value converted to the specified type. Queries must return the\\n    same value for the lifetime of the module though may vary from run to run.\\n\\n    This is roughly equivalent to the `sysconf` linux syscall\\n    (https://man7.org/linux/man-pages/man3/sysconf.3.html) in that the exact\\n    set of keys available and their interpretation is target-dependent.\\n\\n    Users of the op must check the `ok` result before using the value as what\\n    set of keys is available may change over time. If in doubt: don't use this.\\n    Each key used adds additional versioning and testing complexity as runtime\\n    code path changes will explode combinatorially and should be treated with as\\n    much care as a binary file format change. Keys should be prefixed with `ex.`\\n    when experimental indicating that they are not expected to be present\\n    forever; all non-experimental keys should be vetted.\\n\\n    Well-known keys:\\n\\n    * hal.device.id :: {some id pattern}\\n      Returns 1 if the device identifier matches the given pattern string.\\n\\n    * hal.executable.format :: {some format pattern}\\n      Returns 1 if the given format is supported by the device loader.\\n\\n    * hal.device :: concurrency\\n      The maximum concurrently executable submissions, mapping roughly to the\\n      queue count. The actual concurrency available may be less than this based\\n      on dynamic runtime parameters such as power/thermal modes, quota limits,\\n      or user choice.\\n\\n    * hal.dispatch :: concurrency\\n      The maximum concurrently executable workgroups for a particular dispatch.\\n      The actual concurrency available may be less depending on device state.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"ok\", \"type\": \"I1\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"category\", \"type\": \"StrAttr\" },\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"default_value\", \"type\": \"OptionalAttr<TypedAttrInterface>\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `key` `(` $category `:` `` `:` $key `)`\\n    `:` type($ok) `,` type($value)\\n    (`=` $default_value^)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.alloca\",\n    \"summary\": \"Allocates a queue-ordered transient buffer.\",\n    \"description\": \"Returns a queue-ordered transient buffer that will be available for use when\\n    the signal fence is reached. The allocation will not be made until the\\n    wait fence has been reached.\\n\\n    The size of the buffer returned may be larger than the requested size if the\\n    allocator has specific alignment requirements or minimum allocation sizes.\\n\\n    The buffer handle will remain live so long as there are retainers but the\\n    contents are undefined before the allocation signal fence has been signaled\\n    and after the deallocation wait fence has been reached.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"pool\", \"type\": \"HAL_DeviceQueuePool\" },\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryType\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsage\" },\n      { \"name\": \"result_size\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Buffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_AllocaFlagBitfieldAttr{None|IndeterminateLifetime}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `pool` `(` $pool `)`\\n    `type` `(` $memory_types `)`\\n    `usage` `(` $buffer_usage `)`\\n    `flags` `(` $flags `)`\\n    `:` custom<SizeAwareType>(type($result), $result_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.barrier\",\n    \"summary\": \"Enqueues an execution barrier.\",\n    \"description\": \"Signals the provided fence once the wait fence is reached.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_ExecuteFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.copy\",\n    \"summary\": \"Copies one device-visible buffer to another.\",\n    \"description\": \"The source buffer and target buffer must both be visible to the device\\n    queue performing the copy. In most cases the queue affinity should be set to\\n    where the target buffer will be consumed so that it has a chance of being\\n    cached. The source buffer must have transfer-source usage and the target\\n    buffer must have transfer-target usage.\\n\\n    Note that individual queue transfer operations have a high overhead and they\\n    should be batched with other operations in command buffers.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"target_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_CopyFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `source` `(` $source_buffer `:` type($source_buffer) `)`\\n    `` `[` $source_offset `]`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.dealloca\",\n    \"summary\": \"Deallocates a queue-ordered transient buffer.\",\n    \"description\": \"Deallocates a queue-ordered transient buffer.\\n    The deallocation will not be made until the wait fence has been reached and\\n    once the storage is available for reuse the signal fence will be signaled.\\n\\n    After deallocation the contents of the buffer may still be accessible but\\n    will have undefined contents as other operations reuse the memory.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"buffer\", \"type\": \"HAL_Buffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_DeallocaFlagBitfieldAttr{None|PreferOrigin}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `buffer` `(` $buffer `:` type($buffer) `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.execute\",\n    \"summary\": \"Enqueues command buffer execution.\",\n    \"description\": \"Executes a command buffer on a device queue.\\n    No commands will execute until the wait fence has been reached and the\\n    signal fence will be signaled when all commands have completed.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_ExecuteFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `commands` `(` $command_buffer `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.execute.indirect\",\n    \"summary\": \"Enqueues command buffer execution.\",\n    \"description\": \"Executes a command buffer on a device queue with the given binding table.\\n    No commands will execute until the wait fence has been reached and the\\n    signal fence will be signaled when all commands have completed.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" },\n      { \"name\": \"binding_buffers\", \"type\": \"Variadic<HAL_BufferType>\" },\n      { \"name\": \"binding_offsets\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"binding_lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_ExecuteFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `commands` `(` $command_buffer `)`\\n    `bindings` `(` `[`\\n    custom<BindingTable>($binding_buffers,\\n                         type($binding_buffers),\\n                         $binding_offsets,\\n                         $binding_lengths)\\n    `]` `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.fill\",\n    \"summary\": \"Fills a buffer with a repeating pattern.\",\n    \"description\": \"The target buffer must be visible to the device queue performing the update.\\n    In most cases the queue affinity should be set to where the target buffer\\n    will be consumed so that it has a chance of being cached.\\n\\n    Note that individual queue transfer operations have a high overhead and they\\n    should be batched with other operations in command buffers.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"target_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"pattern\", \"type\": \"HAL_FillPatternType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_FillFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `pattern` `(` $pattern `:` type($pattern) `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.flush\",\n    \"summary\": \"Flushes locally-pending submissions to the queue.\",\n    \"description\": \"Flushes any locally-pending submissions in the queue.\\n    When submitting many queue operations this can be used to eagerly flush\\n    earlier submissions while later ones are still being constructed.\\n    This may be a no-op.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.read\",\n    \"summary\": \"Reads a segment from a file into a device buffer.\",\n    \"description\": \"Enqueues a file read operation that streams a segment of the source file\\n    defined by the source offset and length into the target HAL buffer at the\\n    specified target offset. The queue affinity should be set to where the\\n    target buffer will be consumed. The source file must have read permission\\n    and the target buffer must have transfer-target usage. Read failure will\\n    result in propagated semaphore failure or device loss.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_file\", \"type\": \"HAL_File\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"target_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_ReadFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `source` `(` $source_file `:` type($source_file) `)`\\n    `` `[` $source_offset `]`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.update\",\n    \"summary\": \"Updates a buffer with the contents of a host buffer.\",\n    \"description\": \"The provided host source buffer will be captured and need not remain live or\\n    unchanged while the operation is queued. The target buffer must be visible\\n    to the device queue performing the update. In most cases the queue affinity\\n    should be set to where the target buffer will be consumed so that it has a\\n    chance of being cached.\\n\\n    Some implementations may have limits on the size of the update or may\\n    perform poorly if the size is larger than an implementation-defined limit.\\n    Updates should be kept as small and infrequent as possible.\\n\\n    Note that individual queue transfer operations have a high overhead and they\\n    should be batched with other operations in command buffers.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_buffer\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"target_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"target_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_UpdateFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `source` `(` $source_buffer `:` type($source_buffer) `)`\\n    `` `[` $source_offset `]`\\n    `target` `(` $target_buffer `:` type($target_buffer) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.queue.write\",\n    \"summary\": \"Writes a segment from a device buffer into a file.\",\n    \"description\": \"Enqueues a file write operation that streams a segment of the source HAL\\n    buffer defined by the source offset and length into the target file at the\\n    specified target offset. The queue affinity should be set to where the\\n    source buffer was produced. The source buffer must have transfer-source\\n    usage and the target file must have write permission. Write failure will\\n    result in propagated semaphore failure or device loss.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"source_offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"target_file\", \"type\": \"HAL_File\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_WriteFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `source` `(` $source_buffer `:` type($source_buffer) `)`\\n    `` `[` $source_offset `]`\\n    `target` `(` $target_file `:` type($target_file) `)`\\n    `` `[` $target_offset `]`\\n    `length` `(` $length `)`\\n    `flags` `(` $flags `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.resolve\",\n    \"summary\": \"Resolves device handles based on affinity.\",\n    \"description\": \"Examples:\\n    ```\\n    // Returns a HAL device.\\n    = hal.device.resolve on(#something) : !hal.device\\n    // Returns a HAL device, allocator, and (optional) queue affinity.\\n    = hal.device.resolve on(#something) : !hal.device, !hal.allocator, i64\\n    // Returns a HAL allocator and (optional) queue affinity.\\n    = hal.device.resolve on(#something) : !hal.allocator, i64\\n    // Returns \\\"any\\\" device. Should only be used as a fallback.\\n    = hal.device.resolve : !hal.device\\n    ```\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ HAL_Device, HAL_Allocator, I64, ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<HAL_DeviceAffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` qualified($affinity)^ `)`)?\\n    attr-dict `:` type($results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.device.switch\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.devices.count\",\n    \"summary\": \"Returns the number of available devices.\",\n    \"description\": \"Returns the total number of available devices registered at runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.devices.get\",\n    \"summary\": \"Returns the device with the given index.\",\n    \"description\": \"Returns the device with the given index in the [0, hal.devices.count) range.\\n    Devices may be lazily initialized upon first use.\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Device\" }\n    ],\n    \"assemblyFormat\": \"$index attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.dispatch.extern\",\n    \"summary\": \"A dispatch of workgroups across a 3-dimensional grid.\",\n    \"description\": \"Dispatches some number of workgroups across a 3-dimensional grid using a\\n    function defined externally in one or more referenced objects. Objects are\\n    declared per executable target and selected automatically during linking\\n    based on where the dispatch is used. Semantically this is equivalent to\\n    a `flow.dispatch.workgroups` but with the workgroup region invisible to the\\n    compiler. See `hal.executable` for more information about object linkage.\\n\\n    Note that since this happens at tensor level the dispatch operation has\\n    value semantics: some tensors (and optionally other primitive types) are\\n    consumed and one or more new result tensors are produced. Inside each\\n    workgroup, however, the input and output tensors are available for arbitrary\\n    loads and stores. In many cases each workgroup will load some particular\\n    tile(s) from the input tensors and store some particular tile(s) to the\\n    output tensors unique to that workgroup. Though it's possible for multiple\\n    workgroups to load the same regions of the input tensors behavior is\\n    undefined if multiple workgroups store to the same regions of the output\\n    tensors. Codegen guarantees this behavior but when sourcing externally\\n    authored dispatch functions it's critical that this behavior is observed.\\n\\n    Though the representation is similar to the GPU-style grid dispatch model\\n    here we still have not yet allocated buffers, determined the target device\\n    for execution, or even completed fully resolving shapes/types/etc. Because\\n    of this it's important that the workgroup body use the platform-dependent\\n    primitives for accessing workgroup ID, size, and count intrinsics instead\\n    of hardcoding them to a particular set of values. Assume that any workgroup\\n    dispatch may end up being specialized for several different target devices\\n    and even several different variants for a particular target device\\n    (differing workgroup sizes, etc). To aid deduplication code producing these\\n    external dispatches should try not to specialize early for particular shapes\\n    and instead emit the most generic code possible as having 500 slightly\\n    different `hal.dispatch.extern` ops pointing at the same object file is\\n    likely to require 500 copies of the object instead of 500 calls to the same\\n    object.\\n\\n    Because at this point in the layering devices have not yet been selected the\\n    workgroup count cannot be fully evaluated. Instead workload parameters are\\n    captured that are then passed to a function that when later evaluated\\n    computes the actual workgroup count based on target information. The\\n    workload is not limited to the 3D XYZ grid dispatch of the workgroup count\\n    and can contain any number of parameters used to compute it. If workgroup\\n    size or distribution varies based on the target device a `!hal.device`\\n    argument can be used by the workgroup count calculation region to factor in\\n    device parameters. See `hal.device.query` for more information on how to\\n    query information.\\n\\n    ```mlir\\n    %r = hal.dispatch.extern \\\"some_function\\\"[%c5, %c5](%0, %1)\\n        : (tensor<5x5xf32>, tensor<5xf32>) -> tensor<5x5xf32>\\n      ...\\n    ```\\n\\n    The number of results of the operation is equal to the number of results\\n    in the type signature (`(tensor<5x5xf32>, tensor<5xf32>) -> tensor<5x5xf32>`).\\n    Each tensor argument and result in the type signature has a corresponding\\n    pipeline layout slot and must be declared. If multiple arguments or results\\n    share the same layout slot they can be aliased using the `bindings`\\n    attribute and otherwise each is assumed unique.\\n\\n    There are no `arguments` operands for results, but a result can be tied an\\n    argument by writing the argument operand's SSA value instead of its type:\\n    E.g., in the above example, `-> %0` would tie the first argument to the\\n    result. In that case, there would be no separate block argument for the\\n    result.\\n\\n    Objects for multiple targets can be specified and the ones used are selected\\n    based on their target and an optional condition region that returns true if\\n    the variant is valid for use on the provided runtime `!hal.device`. If no\\n    variants within an executable are valid then loading will fail at runtime.\\n    If multiple variants are valid the first valid one found will be loaded and\\n    used for execution.\",\n    \"operands\": [\n      { \"name\": \"workload\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"argument_dims\", \"type\": \"Variadic<HAL_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"export_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"layout\", \"type\": \"HAL_PipelineLayoutAttr\" },\n      { \"name\": \"targets\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"target_ordinals\", \"type\": \"TypedArrayAttrBase<HAL_OrdinalAttr>\" },\n      { \"name\": \"target_objects\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"workgroup_size\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttrBase<size_t>>>\" },\n      { \"name\": \"subgroup_size\", \"type\": \"OptionalAttr<HAL_SubgroupSizeAttr>\" },\n      { \"name\": \"workgroup_local_memory\", \"type\": \"OptionalAttr<IndexAttr>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"workgroup_count\", \"type\": \"AnyRegion\" },\n      { \"name\": \"target_regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$export_name\\n    (`[` $workload^ `]`)? ``\\n    `(` $arguments `)` `:`\\n    custom<ShapedFunctionType>(ref($arguments),\\n                               type($arguments), $argument_dims,\\n                               type($results), $result_dims,\\n                               $tied_operands)\\n    `count` `` custom<WorkgroupCountRegion>($workgroup_count)\\n    `layout` `(` $layout `)`\\n    `objects` `(` `{` custom<TargetConditionObjects>($targets,\\n                                                     $target_ordinals,\\n                                                     $target_objects,\\n                                                     $target_regions) `}` `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.element_type\",\n    \"summary\": \"An iree_hal_element_type_t for the given MLIR type.\",\n    \"description\": \"Maps an MLIR type to a runtime `iree_hal_element_type_t` value for all types\\n    that are convertible.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_ElementType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`<` $type `>`\\n    attr-dict\\n    `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.encoding_type\",\n    \"summary\": \"An iree_hal_encoding_type_t for the given MLIR encoding.\",\n    \"description\": \"Maps an MLIR encoding to a runtime `iree_hal_encoding_type_t` value for all\\n    encodings that are convertible.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_EncodingType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"encoding\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"`<` ($encoding^):( `` `dense_row_major`)? `>`\\n    attr-dict\\n    `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.ex.file.from_memory\",\n    \"summary\": \"Creates a file mapped into a byte range of a host buffer.\",\n    \"description\": \"Returns a file handle that is backed by the given `buffer` contents.\\n    Behavior is undefined if the buffer contents change while the accesses are\\n    in-flight.\\n\\n    Experimental as the exact interface for getting files from module contents\\n    still needs iteration. Most hardware APIs require a file descriptor or\\n    native platform handle but here we only have host pointers. When\\n    memory-mapped some systems allow for retrieval of the platform handle from\\n    a virtual address (GetMappedFileNameA/posix_mem_offset) but the APIs are\\n    sketchy and likely slow. Instead we should probably have a way to query for\\n    a file handle derived from the calling module by stack-walking and asking\\n    the VM module for its handle. Until we can figure this out this method will\\n    be marked experimental.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"buffer\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"offset\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"length\", \"type\": \"HAL_DeviceSize\" },\n      { \"name\": \"flags\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_File\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"access\", \"type\": \"HAL_MemoryAccessBitfieldAttr{None|Read|Write|Discard|MayAlias|Unaligned|Any}\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `affinity` `(` $queue_affinity `)`\\n    `access` `(` $access `)`\\n    `buffer` `(` $buffer `:` type($buffer) `)`\\n    `` `[` $offset `for` $length `]`\\n    `flags` `(` $flags `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.ex.shared_device\",\n    \"summary\": \"Returns the shared device instance.\",\n    \"description\": \"Deprecated operation that returns the shared device instance.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Device\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"hal.ex.submit_and_wait\",\n    \"summary\": \"Submits a command buffer and waits for completion.\",\n    \"description\": \"Deprecated operation that submits a command buffer to the device and waits for its completion.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"command_buffer\", \"type\": \"HAL_CommandBuffer\" }\n    ],\n    \"assemblyFormat\": \"$device `,` $command_buffer attr-dict\"\n  },\n  {\n    \"name\": \"hal.executable\",\n    \"summary\": \"Target-specific executable module.\",\n    \"description\": \"An executable module representing a target-specific compiled\\n    kernel/shader/etc. Executables are treated as independent compilation units\\n    and may contain multiple exported entry points that are able to share code\\n    internally. To support multi-targeting each executable may have one or more\\n    target-specific variants that are lowered independently during compilation\\n    while still appearing as one executable at runtime (ala fat binaries).\\n\\n    At runtime executables are loaded during module initialization and cached\\n    for the lifetime of the module. If the `lazy` attribute is set the\\n    executable _may_ have its loading deferred until first use.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"lazy\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`lazy` $lazy^)?\\n    $sym_name\\n    attr-dict-with-keyword\\n    regions\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable_end\",\n    \"summary\": \"Terminator pseudo-op for the executable op.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable_layout.create\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.executable_layout.lookup\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.executable.binary\",\n    \"summary\": \"Compiled executable binary data.\",\n    \"description\": \"A compiled executable binary with an optional nested module containing the\\n    IR prior to serialization (for debugging).\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"format\", \"type\": \"StrAttr\" },\n      { \"name\": \"data\", \"type\": \"Util_AnySerializableAttr\" },\n      { \"name\": \"mime_type\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.calculate_workgroups\",\n    \"summary\": \"Calculates workgroup count from workload for an exported function.\",\n    \"description\": \"Calculates the workgroup count (grid XYZ) based on the given workload using\\n    the workgroup count calculation region of the target\\n    `hal.executable.export` op.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"workload\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"workgroup_x\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"workgroup_y\", \"type\": \"HAL_Dim\" },\n      { \"name\": \"workgroup_z\", \"type\": \"HAL_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_point\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `target` `(` $entry_point `)`\\n    (`workload` `(` `[` $workload^ `]` `)`)?\\n    `:` type($workgroup_x) `,` type($workgroup_y) `,` type($workgroup_z)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.condition\",\n    \"summary\": \"Host code to determine if the executable is enabled.\",\n    \"description\": \"Variants are selected based on their target and this optional condition\\n    op that returns true if the variant is valid for use on the provided\\n    runtime `!hal.device`. If no variants within an executable are valid then\\n    loading will fail at runtime. If multiple variants are valid the first valid\\n    one found will be loaded and used for execution.\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.constant.block\",\n    \"summary\": \"Executable constant block initializer.\",\n    \"description\": \"Initializes one or more constants in the executable constant block by\\n    returning one value per identified constant. Each constant block is\\n    evaluated on the host prior to instantiating the executable for a given\\n    device and allows for the executable to be specialized based on device\\n    capabilities and limits.\\n\\n    The keys specified are unique per variant and will be deduplicated across\\n    multiple constant blocks when present. They are only used during lowering\\n    and will not survive to runtime so they need only have descriptive enough\\n    names to avoid collisions and represent the semantics of the value.\\n\\n    Constant values can be loaded in the device code with the\\n    `hal.executable.constant.load` op:\\n\\n    ```mlir\\n    hal.executable.variant public @target {\\n      hal.executable.constant.block(%device: !hal.device) -> (i32, i32) as (\\\"foo\\\", \\\"bar\\\") {\\n        %0 = hal.device.query<%device> key(\\\"some.device.prop\\\")...\\n        %1 = hal.device.query<%device> key(\\\"another.device.prop\\\")...\\n        hal.return %0, %1 : i32, i32\\n      }\\n      builtin.module {\\n        func @dispatch0() {\\n          %0 = hal.executable.constant.load \\\"foo\\\" : i32\\n          %1 = hal.executable.constant.load \\\"bar\\\" : i32\\n          return\\n        }\\n      }\\n    }\\n    ```\\n\\n    Each target backend will implement the constant initialization and access in\\n    a way compatible with its execution model. Examples:\\n    - CPU: read-only buffer initialized on load and passed to each dispatch\\n    - CUDA: read-only buffer initialized on load and passed to each dispatch\\n    - SPIR-V: specialization constants\\n    - Metal: function constants\\n    - WebGPU: pipeline-overridable constants\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"keys\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.constant.load\",\n    \"summary\": \"Loads a constant value from the executable constant block.\",\n    \"description\": \"Loads a scalar constant value from the static executable constant block.\\n    The value provided by a constant block with the given key will be loaded and\\n    bitcast (possibly with truncation or zero-extension) to the result type.\\n\\n    Note that backends are allowed to implement their own mechanisms for\\n    referencing constant block values and this is provided only as a default for\\n    those not needing special behavior.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_PrimitiveType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$key attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.create\",\n    \"summary\": \"Creates an executable.\",\n    \"description\": \"Creates a target-dependent executable cached on the provided device. Entry\\n    points contained within the executable can be dispatched using the resulting\\n    executable handle.\\n\\n    Depending on the driver creation may take a non-trivial amount of time\\n    (such as when JITing/etc). As the cache is internally synchronized callers\\n    can issue preparation requests from multiple threads - even for the same\\n    executables - and calls will block until preparation completes.\\n\\n    Optional constants provide for specialization of the executable based on\\n    runtime-derived parameters.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"constants\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Executable\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"executable_target\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `affinity` `(` $queue_affinity `)`\\n    `target` `(` $executable_target `)`\\n    (`constants` `(` `[` $constants^ `]` `)`)?\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.entry_point\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.executable.export\",\n    \"summary\": \"Executable entry point declaration.\",\n    \"description\": \"An entry point exported by the executable with statically-available\\n    information describing the IO interface it uses and other dispatch metadata.\\n\\n    The `workgroup_count` region represents the computation that\\n    returns the number of workgroups to use in the 3D grid dispatch.\\n    The arguments to the region represents the workload as captured by each\\n    dispatch. It returns the number of workgroups along x, y, and z.\\n\\n    The optional `condition` region provides boolean logic determining whether\\n    the export should be dispatched given the device and workload or if a\\n    specified fallback export in the same executable should be dispatched\\n    instead. Multiple exports can be chained together as fallbacks to allow for\\n    arbitrarily complex decisions trees. Fallbacks for an export must match the\\n    layout and workload exactly but may vary any other attribute (such as\\n    workgroup size or translation configuration).\\n\\n    Workgroup count and condition regions that have dependencies on dynamic\\n    workload information will be executed using indirect dispatch. If the\\n    information is available on the host at the time a command buffer containing\\n    the dispatch is available the indirect dispatch _may_ have lower overhead\\n    by using `IREE_HAL_DISPATCH_FLAG_STATIC_INDIRECT_PARAMETERS`. If the\\n    information required is data-dependent on work within the same command\\n    buffer some backends will suffer a performance penalty. Condition regions\\n    consuming dynamic workloads in particular may result in long chains of\\n    indirect dispatches sent to the device or even host round-trips.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<HAL_OrdinalAttr>\" },\n      { \"name\": \"layout\", \"type\": \"HAL_PipelineLayoutAttr\" },\n      { \"name\": \"condition_fallback\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"workgroup_size\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttrBase<size_t>>>\" },\n      { \"name\": \"subgroup_size\", \"type\": \"OptionalAttr<HAL_SubgroupSizeAttr>\" },\n      { \"name\": \"workgroup_local_memory\", \"type\": \"OptionalAttr<IndexAttr>\" },\n      { \"name\": \"source_locs\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"workgroup_count\", \"type\": \"AnyRegion\" },\n      { \"name\": \"condition\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    (`ordinal` `(` $ordinal^ `)`)?\\n    `layout` `(` qualified($layout) `)`\\n    (`condition` `` custom<ExportConditionRegion>($condition)^)?\\n    (`fallback` `(` $condition_fallback^ `)`)?\\n    (`count` `` custom<WorkgroupCountRegion>($workgroup_count)^)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.export.ordinal\",\n    \"summary\": \"Executable export ordinal lookup pseudo-op.\",\n    \"description\": \"Resolves an executable export ordinal to a value once ordinals have been\\n    assigned.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_point\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`target` `(` $entry_point `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.lookup\",\n    \"summary\": \"Executable cache lookup pseudo-op.\",\n    \"description\": \"Used during conversion to provide a placeholder for a globally cached and\\n    possibly lazy-initialized executable.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Executable\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"executable\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `executable` `(` $executable `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.source\",\n    \"summary\": \"Generic source contents of an executable op.\",\n    \"description\": \"This is an unspecialized source representation of an executable\\n    module without an assigned target. This is useful for hand-authoring\\n    executables prior to device specification.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"objects\", \"type\": \"OptionalAttr<HAL_ExecutableObjectsAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    attr-dict-with-keyword\\n    $body\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.source_end\",\n    \"summary\": \"Terminator pseudo-op for the executable source op.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.variant\",\n    \"summary\": \"Target-specific variant of an executable op.\",\n    \"description\": \"The target IR for the executable. This can be preserved for debugging but\\n    is usually removed during transformation.\\n\\n    Variants are selected based on their target and an optional condition\\n    op that returns true if the variant is valid for use on the provided\\n    runtime `!hal.device`. If no variants within an executable are valid then\\n    loading will fail at runtime. If multiple variants are valid the first valid\\n    one found will be loaded and used for execution.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"target\", \"type\": \"HAL_ExecutableTargetAttr\" },\n      { \"name\": \"objects\", \"type\": \"OptionalAttr<TypedArrayAttrBase<HAL_ExecutableObjectAttr>>\" },\n      { \"name\": \"sources\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    `target` `(` $target `)`\\n    (`objects` `(` $objects^ `)` )?\\n    (`sources` `(` $sources^ `)` )?\\n    attr-dict-with-keyword\\n    $body\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.executable.variant_end\",\n    \"summary\": \"Terminator pseudo-op for the executable variant op.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.fence.await\",\n    \"summary\": \"Asynchronous fence wait operation.\",\n    \"description\": \"Yields the caller until all fences is reached. Returns the `status` of the\\n    fence after the wait, with a non-zero value indicating failure.\",\n    \"operands\": [\n      { \"name\": \"timeout_millis\", \"type\": \"I32\" },\n      { \"name\": \"fences\", \"type\": \"Variadic<HAL_Fence>\" }\n    ],\n    \"results\": [\n      { \"name\": \"status\", \"type\": \"Util_Status\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_WaitFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`until` `(` `[` $fences `]` `)`\\n    `timeout_millis` `(` $timeout_millis `)`\\n    `flags` `(` $flags `)`\\n    `:` type($status)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.fence.create\",\n    \"summary\": \"Creates an unsignaled fence.\",\n    \"description\": \"Returns a fence that defines a point in time. By default fences will remain\\n    unsignaled unless they are explicitly signaled with `hal.fence.signal` or\\n    asynchronously signaled by the device by passing them as an operand to\\n    queue submission ops.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Fence\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_FenceFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`device` `(` $device `:` type($device) `)`\\n    `flags` `(` $flags `)`\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.fence.fail\",\n    \"summary\": \"Fence failure operation.\",\n    \"description\": \"Signals the fence with a failure. The `status` will be returned from\\n    each timepoint semaphores `hal.semaphore.query` and `hal.semaphore.signal`\\n    for the lifetime of each semaphore.\",\n    \"operands\": [\n      { \"name\": \"fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"status\", \"type\": \"Util_Status\" }\n    ],\n    \"assemblyFormat\": \"`<` $fence `:` type($fence) `>`\\n    `status` `(` $status `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.fence.join\",\n    \"summary\": \"Creates a fence from the given timepoints.\",\n    \"description\": \"Returns a fence that joins the input fences as a wait-all operation.\",\n    \"operands\": [\n      { \"name\": \"fences\", \"type\": \"Variadic<HAL_Fence>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Fence\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"HAL_FenceFlagBitfieldAttr{None|Reserved}\" }\n    ],\n    \"assemblyFormat\": \"`at` `(` `[` $fences `]` `)`\\n    `flags` `(` $flags `)`\\n    `->` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.fence.query\",\n    \"summary\": \"Fence query operation.\",\n    \"description\": \"Queries whether the fence has been reached and its status.\\n    Returns OK if the fence has been signaled successfully, DEFERRED if it is\\n    unsignaled, and otherwise an error indicating the failure.\",\n    \"operands\": [\n      { \"name\": \"fence\", \"type\": \"HAL_Fence\" }\n    ],\n    \"results\": [\n      { \"name\": \"status\", \"type\": \"Util_Status\" }\n    ],\n    \"assemblyFormat\": \"`<` $fence `:` type($fence) `>`\\n    `:` type($status)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.fence.signal\",\n    \"summary\": \"Fence signal operation.\",\n    \"description\": \"Signals the fence to indicate that the timepoints contained have been\\n    reached. Waiting work may begin immediately.\",\n    \"operands\": [\n      { \"name\": \"fence\", \"type\": \"HAL_Fence\" }\n    ],\n    \"assemblyFormat\": \"`<` $fence `:` type($fence) `>`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.instrument.memory.load\",\n    \"summary\": \"Emits a memory load instrumentation event.\",\n    \"description\": \"Emits a workgroup-specific memory load event indicating that a number of\\n    bytes from the given resolved pointer have been loaded by the workgroup.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"workgroupKey\", \"type\": \"Index\" },\n      { \"name\": \"loadValue\", \"type\": \"AnyType\" },\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['loadValue', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`` `[` $buffer `:` type($buffer) `for` $workgroupKey `]`\\n    $base `[` $indices `]` `,` $loadValue\\n    attr-dict `:` type($base) `,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.instrument.memory.store\",\n    \"summary\": \"Emits a memory store instrumentation event.\",\n    \"description\": \"Emits a workgroup-specific memory store event indicating that a number of\\n    bytes have been stored to the given resolved pointer by the workgroup.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"workgroupKey\", \"type\": \"Index\" },\n      { \"name\": \"storeValue\", \"type\": \"AnyType\" },\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['storeValue', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`` `[` $buffer `:` type($buffer) `for` $workgroupKey `]`\\n    $base `[` $indices `]` `,` $storeValue\\n    attr-dict `:` type($base) `,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.instrument.print\",\n    \"summary\": \"Emits a human-readable printf-style string event.\",\n    \"description\": \"Formats a string using a limited subset of printf format specifiers and the\\n    provided values and then emits an `iree_instrument_dispatch_print_t` event. Final\\n    formatted string lengths may be limited to as much as 1024 characters and\\n    should be kept as small as possible to avoid easily exceeding the\\n    instrumentation storage buffers with redundant strings.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"workgroupKey\", \"type\": \"Index\" },\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`` `[` $buffer `:` type($buffer) `for` $workgroupKey `]`\\n    $format (`*` `(` $values^ `:` type($values) `)`)?\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.instrument.value\",\n    \"summary\": \"Emits a scalar value instrumentation event.\",\n    \"description\": \"Emits a workgroup-specific typed value with the given workgroup-relative\\n    ordinal.\\n\\n    This op will be preserved even if the output is not used as it is only for\\n    debugging purposes.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"workgroupKey\", \"type\": \"Index\" },\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ordinal\", \"type\": \"AnyI8Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`` `[` $buffer `:` type($buffer) `for` $workgroupKey `]`\\n    $ordinal `=` $operand attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.instrument.workgroup\",\n    \"summary\": \"Emits a dispatch workgroup instrumentation event.\",\n    \"description\": \"Emits an `iree_instrument_dispatch_workgroup_t` event into the\\n    instrumentation stream. The workgroup event identifies the unique dispatch,\\n    its workgroup count, and the ID of the emitting workgroup within the\\n    dispatch. Optionally targets that support querying the processor ID\\n    executing the workgroup can attach that information for tracking purposes.\\n\\n    On targets such as CPUs where entire workgroups execute as atomic units\\n    only one workgroup event should be emitted. On targets such as GPUs where\\n    there may be multiple invocations executing as part of a single workgroup\\n    only the first invocation within the workgroup should emit the workgroup\\n    event (by checking if the LocalInvocationIndex or threadIdx == 0, etc).\\n\\n    The resulting workgroup key is used by subsequent workgroup-specific\\n    instrumentation events.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"dispatchId\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"workgroupKey\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"`` `[` $buffer `:` type($buffer) `]`\\n    `dispatch` `(` $dispatchId `)`\\n    attr-dict `:` type($workgroupKey)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.interface\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.interface.binding\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.interface.binding.subspan\",\n    \"summary\": \"Returns an alias to a subspan of interface binding data.\",\n    \"description\": \"Returns a subspan of an interface binding storage buffer in a generic type.\\n    The exact shape, type, and alignment of the returned type are defined by\\n    the result type (tensor, memref, etc).\\n\\n    An optional alignment indicates the byte alignment of the base binding\\n    resource. Note that the byte offset is added to the base and the alignment\\n    will be the minimum of the two.\",\n    \"operands\": [\n      { \"name\": \"byte_offset\", \"type\": \"Optional<HAL_DeviceSize>\" },\n      { \"name\": \"dynamic_dims\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"HAL_PipelineLayoutAttr\" },\n      { \"name\": \"binding\", \"type\": \"IndexAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IndexAttr>\" },\n      { \"name\": \"descriptor_flags\", \"type\": \"OptionalAttr<HAL_DescriptorFlagsAttr{None|ReadOnly|Indirect}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`layout` `(` $layout `)`\\n    `binding` `(` $binding `)`\\n    (`alignment` `(` $alignment^ `)`)?\\n    (`offset` `(` $byte_offset^ `)`)?\\n    (`flags` `(` $descriptor_flags^ `)`)?\\n    attr-dict `:` type($result) (`{` $dynamic_dims^ `}`)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.interface.constant.load\",\n    \"summary\": \"Loads a constant value from the interface constant block.\",\n    \"description\": \"Loads a scalar constant value from an executable IO push constant block.\\n    The value will be loaded from the given constant offset and will be\\n    bitcast (possibly with truncation or zero-extension) to the result type.\\n\\n    An optional alignment indicates the byte alignment of potential values for\\n    the constant when it could be determined from analysis. If omitted the value\\n    may be anything and its interpretation is up to the usage. This is intended\\n    to provide pointer alignment-like semantics to constants that are used to\\n    index into binding resources.\\n\\n    An optional set of values indicates all possible values that can be passed\\n    to the constant from all dispatch sites in the program. If omitted the value\\n    may be from an unanalyzable source (outside of the program, indirect, etc)\\n    and must be assumed to have any value.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_PrimitiveType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"HAL_PipelineLayoutAttr\" },\n      { \"name\": \"ordinal\", \"type\": \"HAL_HostSizeAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IndexAttr>\" },\n      { \"name\": \"values\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"`layout` `(` $layout `)`\\n    `ordinal` `(` $ordinal `)`\\n    (`alignment` `(` $alignment^ `)`)?\\n    (`values` `(` $values^ `)`)?\\n    attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.interface.workgroup.count\",\n    \"summary\": \"Returns the total workgroup count of the grid.\",\n    \"description\": \"The total number of workgroups along each dimension in the dispatch grid.\\n    Matches what was passed to the `hal.command_buffer.dispatch` command (or\\n    what was indirectly specified).\\n\\n    Corresponds to the `NumWorkgroups` SPIR-V built-in and the `gridDim` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = hal.interface.workgroup.count[0] : index\\n    %y = hal.interface.workgroup.count[1] : index\\n    %z = hal.interface.workgroup.count[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` (`upper_bound` $upper_bound^)? attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.interface.workgroup.id\",\n    \"summary\": \"Returns the index of the current workgroup in the grid.\",\n    \"description\": \"The global workgroup ID of the current tile in the range of\\n    `[0, hal.interface.workgroup.count)` along each XYZ dimension.\\n\\n    Corresponds to the `WorkgroupId` SPIR-V built-in and the `blockIdx` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = hal.interface.workgroup.id[0] : index\\n    %y = hal.interface.workgroup.id[1] : index\\n    %z = hal.interface.workgroup.id[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` (`upper_bound` $upper_bound^)? attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.interface.workgroup.size\",\n    \"summary\": \"Returns the size of each workgroup in invocations.\",\n    \"description\": \"The number of local invocations within the current workgroup along each\\n    dimension. Depending on backend this may map to the SIMT thread count or\\n    inner loop nest parameters.\\n\\n    Corresponds to the `WorkgroupSize` SPIR-V built-in and the `blockDim` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = hal.interface.workgroup.size[0] : index\\n    %y = hal.interface.workgroup.size[1] : index\\n    %z = hal.interface.workgroup.size[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` (`upper_bound` $upper_bound^)? attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.memory_type\",\n    \"summary\": \"An iree_hal_memory_type_t for the given memory type bits.\",\n    \"description\": \"Maps memory type bits to a runtime `iree_hal_memory_type_t` value.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HAL_MemoryType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"HAL_MemoryTypeBitfieldAttr{None|Optimal|HostVisible|HostCoherent|HostCached|HostLocal|DeviceVisible|DeviceLocal}\" }\n    ],\n    \"assemblyFormat\": \"`<` $type `>`\\n    attr-dict\\n    `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.return\",\n    \"summary\": \"Return from a hal.* region.\",\n    \"description\": \"Returns the given values from the region and back to the host code.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($operands^ `:` type($operands))? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.tensor.alias\",\n    \"summary\": \"Hints that tensor storage should alias a HAL buffer view.\",\n    \"description\": \"Hints that the backing storage of an entire tensor aliases the given storage\\n    buffer. There's no guarantee that the storage will alias and instead only\\n    that the tensor contents will be written to the storage as if a copy had\\n    occurred. This allows the compiler to avoid copies in the ideal case of a\\n    producer that is able to produce directly into the target storage but still\\n    handle cases where the producer is not able to be in-place.\\n\\n    The storage buffer provided must have sufficient space for the tensor once\\n    encoded. Dynamically shaped tensors may not consume the entire provided\\n    storage. If a buffer view is provided the metadata is ignored and only the\\n    backing buffer is used.\\n\\n    An optional wait fence can be provided in cases where the storage is not\\n    immediately available. Producers that may alias the storage will wait until\\n    the storage is available before updating the contents.\\n\\n    Explicit aliasing side-steps any analysis that may be performed by the\\n    compiler and requires users to guarantee that the safety of the aliasing.\\n    Copy-on-write, alias analysis for overlap detection, and ordering via\\n    use-def chains are all ignorant of the aliased buffer memory and only ensure\\n    the compiler consumes or produces the aliased memory consistent with itself.\\n\\n    Example:\\n    ```mlir\\n    %init = tensor.empty\\n    %value = linalg.generic ... outs(%init)\\n    %aliased = hal.tensor.alias %value : tensor<...> to %buffer : !hal.buffer\\n    ... linalg.generic ins(%aliased) ...\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<HAL_Dim>\" },\n      { \"name\": \"storage\", \"type\": \"AnyTypeOf<[HAL_Buffer, HAL_BufferView]>\" },\n      { \"name\": \"wait_fence\", \"type\": \"Optional<HAL_Fence>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`wait` `(` $wait_fence^ `)` `=` `` `>`)?\\n    $source `:` type($source) (`{` $source_dims^ `}`)?\\n    `to`\\n    $storage `:` type($storage)\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.tensor.barrier\",\n    \"summary\": \"Signals a fence when all tensors are available.\",\n    \"description\": \"Defines a barrier that is used to indicate availability of an entire set of\\n    tensors by signaling a fence. The source tensors are returned for chaining.\",\n    \"operands\": [\n      { \"name\": \"sources\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['sources', 'results']>\" }\n    ],\n    \"assemblyFormat\": \"`join` `` `(` $sources `:` type($sources) `)`\\n    `=` `` `>`\\n    $signal_fence `:` type($signal_fence)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.tensor.cast\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"hal.tensor.export\",\n    \"summary\": \"Exports a tensor to a HAL buffer view.\",\n    \"description\": \"Defines an export of an SSA-form tensor to an external HAL buffer view.\\n\\n    The provided `source_encoding`, if different from the `source` type,\\n    indicates that the ABI-facing type may differ from the internal\\n    representation. The types must be bitcastable (same storage size) and\\n    dynamically shaped values must have the same number of dynamic dimensions.\\n    This allows for casting between rank-0 and rank-N types, different element\\n    types, etc.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<HAL_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"target\", \"type\": \"AnyTypeOf<[HAL_Buffer, HAL_BufferView]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source\\n    ($name^)?\\n    `:`\\n    custom<TypeAlias>($source_encoding, type($source)) (`{` $source_dims^ `}`)?\\n    `->`\\n    type($target)\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.tensor.import\",\n    \"summary\": \"Imports a tensor from a HAL buffer view.\",\n    \"description\": \"Defines an import of an external HAL buffer view into a SSA-form tensor.\\n    An optional fence can be specified indicating when the buffer view is\\n    available for use. If no fence is provided it is assumed the buffer view is\\n    immediately available.\\n\\n    The provided `target_encoding`, if different from the `target` type,\\n    indicates that the ABI-facing type may differ from the internal\\n    representation. The types must be bitcastable (same storage size) and\\n    dynamically shaped values must have the same number of dynamic dimensions.\\n    This allows for casting between rank-0 and rank-N types, different element\\n    types, etc.\\n\\n    `consume` can be used to indicate a transfer of ownership. Though the\\n    imported value may still have external references when consumed a resource\\n    will be conceptually released from its existing owner and retained by the\\n    importer atomically.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[HAL_Buffer, HAL_BufferView]>\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<HAL_Dim>\" },\n      { \"name\": \"wait_fence\", \"type\": \"Optional<HAL_Fence>\" }\n    ],\n    \"results\": [\n      { \"name\": \"target\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"consume\", \"type\": \"UnitAttr\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`wait` `(` $wait_fence^ `)` `=` `` `>`)?\\n    (`consume` $consume^)?\\n    $source\\n    ($name^)?\\n    `:` type($source) `->`\\n    custom<TypeAlias>($target_encoding, type($target)) (`{` $target_dims^ `}`)?\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"hal.tensor.transients\",\n    \"summary\": \"Annotates a tensor to use transient storage from a provided buffer.\",\n    \"description\": \"Annotates that any transient memory used in the production of the given\\n    tensor should be suballocated from the provided storage buffer. This allows\\n    users to control transient allocations by providing their own storage,\\n    enabling zero-allocation execution in steady state.\\n\\n    The storage buffer provided must have sufficient space for all transient\\n    allocations required to produce the tensor. Unless otherwise overridden the\\n    compiler will verify that all allocation sizes are computable and generate\\n    size query functions to allow users to query the required buffer size. If\\n    size checks are disabled then the user must ensure they pass in a buffer\\n    with sufficient capacity.\\n\\n    The storage buffer is assumed to be immediately usable (i.e., any previous\\n    work using it has completed). Users must ensure proper synchronization if\\n    reusing storage across multiple operations. Future work may add explicit\\n    wait semantics to enable pipelining, but for now synchronization is the\\n    caller's responsibility.\\n\\n    This operation preserves SSA use-def chains by returning the same tensor\\n    value it receives. It exists purely for annotation purposes and will be\\n    lowered away during compilation.\\n\\n    Example:\\n    ```mlir\\n    %result = some.operation(%input) : tensor<?xf32>\\n    %annotated = hal.tensor.transients %result : tensor<?xf32>{%dim} from %storage : !hal.buffer\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<HAL_Dim>\" },\n      { \"name\": \"storage\", \"type\": \"AnyTypeOf<[HAL_Buffer, HAL_BufferView]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `:` type($source) (`{` $source_dims^ `}`)?\\n    `from`\\n    $storage `:` type($storage)\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"ifrt.After\",\n    \"summary\": \"Get a control handle for array materialization.\",\n    \"description\": \"When depending on the `control_output`, the op will be not be scheduled\\n    until all `inputs` are materialized. For example, this could mean the data\\n    transfer is completed from a `Reshard` op.\\n\\n    Moreover, this op provides fine-grained control dependency on `CallOp`'s\\n    result. Consider\\n      %0, %1, %ctrl_0 = \\\"ifrt.Call\\\" @callee() ...\\n    The following 3 control handles may resolve at difference time instances:\\n      \\\"ifrt.After\\\"(%0)\\n      \\\"ifrt.After\\\"(%1)\\n      %ctrl_0\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"control_output\", \"type\": \"Ifrt_ControlType\" }\n    ]\n  },\n  {\n    \"name\": \"ifrt.Assemble\",\n    \"summary\": \"Assembles single device arrays to a sharded array\",\n    \"description\": \"Builds a larger array out of individual per-device arrays.\\n\\n    On each device, the local shard of the result array is the input array.\\n    Thus, in an efficient implementation, no buffer transfer is needed.\\n\\n    The inputs' `device` parameter must have size 1. They should be distinct and\\n    combine to the output's `device` list.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Ifrt_ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Ifrt_ArrayType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ifrt.BitcastArrays\",\n    \"summary\": \"Bitcasts `Array`s to new `Array`s with a different type.\",\n    \"description\": \"A metadata-only op that can change the per-shard interpretation without\\n    changing the per-sharding location. The new arrays must use the same\\n    devices, have the same on-device size, and have the same memory kind.\\n\\n    The `dtype`, `shape`, `sharding`, and `layout` of the new arrays might be\\n    different from the input arrays.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"donated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"`(` $inputs `)` attr-dict `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"ifrt.Call\",\n    \"summary\": \"Call some function on a set of devices\",\n    \"description\": \"The callee is a global FuncOp to be sharded onto the given set of devices.\\n    It's up to the IFRT implementation to define which dialects are legal in the\\n    callee.\\n\\n    The callee's inputs/outputs should be regular tensors, the shape of which\\n    are the same as inputs/outputs' global shape, correspondingly. Every\\n    input/output of the callee must have a `ifrt.sharding` attribute matching\\n    that on the corresponding input/output of this CallOp.\\n\\n    The callee doesn't specify the device placement. It's specified at the\\n    `devices` attribute of this CallOp. Every input/output must be placed on\\n    a subset of these devices.\\n\\n    `io_aliases` represents pairs of inputs and outputs, where the input buffer\\n    may be aliased and used as the output buffer. The aliased pair must have the\\n    same byte size. It's up to IFRT implementations whether to respect this\\n    hint or not. Alternatively, if the index of an input is In\\n    `donated_input_indices` then the input buffer might be donated to the\\n    callee if an output with the same byte size is found.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Ifrt_ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_output\", \"type\": \"Ifrt_ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"devices\", \"type\": \"Ifrt_DevicesAttr\" },\n      { \"name\": \"io_aliases\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<ConfinedAttr<DenseI32ArrayAttr, [ DenseArrayCount < 2 > ]>>, {}>\" },\n      { \"name\": \"donated_input_indices\", \"type\": \"DefaultValuedAttr<DenseI32ArrayAttr, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $inputs `)` oilist(`after` $control_inputs)\\n    `on` `devices` $devices attr-dict `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"ifrt.CallLoadedExecutable\",\n    \"summary\": \"Call some loaded executable\",\n    \"description\": \"The callee is a LoadedExecutableOp that declares the signature of the\\n    LoadedExecutable. The actual LoadedExecutable instance is bound through\\n    CompileOptions.\\n\\n    The callee is placed on devices because it's loaded. Every input/output must\\n    be placed on a subset of these devices.\\n\\n    `io_aliases` represents pairs of inputs and outputs, where the input buffer\\n    may be aliased and used as the output buffer. The aliased pair must have the\\n    same byte size. It's up to IFRT implementations whether to respect this\\n    hint or not. Alternatively, if the index of an input is In\\n    `donated_input_indices` then the input buffer might be donated to the\\n    callee if an output with the same byte size is found.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Ifrt_ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_output\", \"type\": \"Ifrt_ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"io_aliases\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<ConfinedAttr<DenseI32ArrayAttr, [ DenseArrayCount < 2 > ]>>, {}>\" },\n      { \"name\": \"donated_input_indices\", \"type\": \"DefaultValuedAttr<DenseI32ArrayAttr, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $inputs `)` oilist(`after` $control_inputs) attr-dict\\n    `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"ifrt.CopyArrays\",\n    \"summary\": \"Copies arrays to a new set of devices\",\n    \"description\": \"Copies the input arrays to the output arrays.\\n\\n    This op requires that all input arrays have use the same devices and memory\\n    kind, and all the output arrays use the same devices and memory kind. Note\\n    that the devices and memory kind used by the input and output arrays might\\n    not be the same. Moreover, the corresponding output array of an input array\\n    must have the same sharding as the op can not reshard.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Ifrt_ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_output\", \"type\": \"Ifrt_ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"donated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $inputs `)` oilist(`after` $control_inputs) attr-dict\\n    `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"ifrt.Disassemble\",\n    \"summary\": \"Disassembles a sharded array to single device arrays\",\n    \"description\": \"Breaks an array up into per-device arrays.\\n\\n    On each device, the result array is its local shard in the input array.\\n    Thus, in an efficient implementation, no buffer transfer is needed.\\n\\n    The outputs' `devices` parameter must have size 1. They should be distinct\\n    and combine to the input's `devices` list.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Ifrt_ArrayType\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Ifrt_ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" }\n    ]\n  },\n  {\n    \"name\": \"ifrt.LoadedExecutable\",\n    \"summary\": \"Declare a loaded executable\",\n    \"description\": \"The inputs/outputs of `function_type` should be IFRT arrays. They should be\\n    placed on a subset of the `devices`.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"devices\", \"type\": \"Ifrt_DevicesAttr\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `on` `devices` $devices attr-dict `:` $function_type\"\n  },\n  {\n    \"name\": \"ifrt.RemapArrays\",\n    \"summary\": \"Remaps shards from input `Array`s to create new `Array`s.\",\n    \"description\": \"A metadata-only op that remaps shards across input `Array`s to create\\n    new `Array`s based on a plan remapping array shards. The op can shuffle\\n    or extract input array shards without causing a data copy or transfer. It\\n    must meet the following requirements:\\n     - All input/output `Array`s must have the same `DType` and per-shard shape.\\n     - An input shard can be used at most once.\\n     - Every output shard must have exactly one input shard mapped.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mappings\", \"type\": \"TypedArrayAttrBase<Ifrt_ArrayMappingAttr>\" },\n      { \"name\": \"donated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"`(` $inputs `)` `mappings` `=` $mappings attr-dict\\n    `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"ifrt.Reshard\",\n    \"summary\": \"Reshards a sequence of host tensors or device arrays\",\n    \"description\": \"Copies the host tensors or device arrays to a new sharding.\\n\\n    The corresponding output of each input must have the same global shape\\n    as the input.\\n\\n    An input and its corresponding output are allowed to have the same sharding\\n    and devices. In this case, this ReshardOp will have no transfer across\\n    devices.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Ifrt_ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Ifrt_ArrayType>\" },\n      { \"name\": \"control_output\", \"type\": \"Ifrt_ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"donated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $inputs `)` oilist(`after` $control_inputs) attr-dict\\n    `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"index.add\",\n    \"summary\": \"index addition\",\n    \"description\": \"The `index.add` operation takes two index values and computes their sum.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a + b\\n    %c = index.add %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.and\",\n    \"summary\": \"index bitwise and\",\n    \"description\": \"The `index.and` operation takes two index values and computes their bitwise\\n    and.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a & b\\n    %c = index.and %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.bool.constant\",\n    \"summary\": \"boolean constant\",\n    \"description\": \"The `index.bool.constant` operation produces an bool-typed SSA value equal\\n    to either `true` or `false`.\\n\\n    This operation is used to materialize bool constants that arise when folding\\n    `index.cmp`.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = index.bool.constant true\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"index.casts\",\n    \"summary\": \"index signed cast\",\n    \"description\": \"The `index.casts` operation enables conversions between values of index type\\n    and concrete fixed-width integer types. If casting to a wider integer, the\\n    value is sign-extended. If casting to a narrower integer, the value is\\n    truncated.\\n\\n    Example:\\n\\n    ```mlir\\n    // Cast to i32\\n    %0 = index.casts %a : index to i32\\n\\n    // Cast from i64\\n    %1 = index.casts %b : i64 to index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[AnyInteger, Index]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[AnyInteger, Index]>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($output)\"\n  },\n  {\n    \"name\": \"index.castu\",\n    \"summary\": \"index unsigned cast\",\n    \"description\": \"The `index.castu` operation enables conversions between values of index type\\n    and concrete fixed-width integer types. If casting to a wider integer, the\\n    value is zero-extended. If casting to a narrower integer, the value is\\n    truncated.\\n\\n    Example:\\n\\n    ```mlir\\n    // Cast to i32\\n    %0 = index.castu %a : index to i32\\n\\n    // Cast from i64\\n    %1 = index.castu %b : i64 to index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[AnyInteger, Index]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[AnyInteger, Index]>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($output)\"\n  },\n  {\n    \"name\": \"index.ceildivs\",\n    \"summary\": \"index signed ceil division\",\n    \"description\": \"The `index.ceildivs` operation takes two index values and computes their\\n    signed quotient. Treats the leading bit as the sign and rounds towards\\n    positive infinity, i.e. `7 / -2 = -3`.\\n\\n    Note: division by zero and signed division overflow are undefined behaviour.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = ceil(a / b)\\n    %c = index.ceildivs %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.ceildivu\",\n    \"summary\": \"index unsigned ceil division\",\n    \"description\": \"The `index.ceildivu` operation takes two index values and computes their\\n    unsigned quotient. Treats the leading bit as the most significant and rounds\\n    towards positive infinity, i.e. `6 / -2 = 1`.\\n\\n    Note: division by zero is undefined behaviour.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = ceil(a / b)\\n    %c = index.ceildivu %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.cmp\",\n    \"summary\": \"index compare\",\n    \"description\": \"The `index.cmp` operation takes two index values and compares them according\\n    to the comparison predicate and returns an `i1`. The following comparisons\\n    are supported:\\n\\n    -   `eq`:  equal\\n    -   `ne`:  not equal\\n    -   `slt`: signed less than\\n    -   `sle`: signed less than or equal\\n    -   `sgt`: signed greater than\\n    -   `sge`: signed greater than or equal\\n    -   `ult`: unsigned less than\\n    -   `ule`: unsigned less than or equal\\n    -   `ugt`: unsigned greater than\\n    -   `uge`: unsigned greater than or equal\\n\\n    The result is `1` if the comparison is true and `0` otherwise.\\n\\n    Example:\\n\\n    ```mlir\\n    // Signed less than comparison.\\n    %0 = index.cmp slt(%a, %b)\\n\\n    // Unsigned greater than or equal comparison.\\n    %1 = index.cmp uge(%a, %b)\\n\\n    // Not equal comparison.\\n    %2 = index.cmp ne(%a, %b)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pred\", \"type\": \"IndexCmpPredicateAttr{eq|ne|slt|sle|sgt|sge|ult|ule|ugt|uge}\" }\n    ],\n    \"assemblyFormat\": \"$pred `(` $lhs `,` $rhs `)` attr-dict\"\n  },\n  {\n    \"name\": \"index.constant\",\n    \"summary\": \"index constant\",\n    \"description\": \"The `index.constant` operation produces an index-typed SSA value equal to\\n    some index-typed integer constant.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = index.constant 42\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"index.divs\",\n    \"summary\": \"index signed division\",\n    \"description\": \"The `index.divs` operation takes two index values and computes their signed\\n    quotient. Treats the leading bit as the sign and rounds towards zero, i.e.\\n    `6 / -2 = -3`.\\n\\n    Note: division by zero and signed division overflow are undefined behaviour.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a / b\\n    %c = index.divs %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.divu\",\n    \"summary\": \"index unsigned division\",\n    \"description\": \"The `index.divu` operation takes two index values and computes their\\n    unsigned quotient. Treats the leading bit as the most significant and rounds\\n    towards zero, i.e. `6 / -2 = 0`.\\n\\n    Note: division by zero is undefined behaviour.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a / b\\n    %c = index.divu %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.floordivs\",\n    \"summary\": \"index signed floor division\",\n    \"description\": \"The `index.floordivs` operation takes two index values and computes their\\n    signed quotient. Treats the leading bit as the sign and rounds towards\\n    negative infinity, i.e. `5 / -2 = -3`.\\n\\n    Note: division by zero and signed division overflow are undefined behaviour.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = floor(a / b)\\n    %c = index.floordivs %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.maxs\",\n    \"summary\": \"index signed maximum\",\n    \"description\": \"The `index.maxs` operation takes two index values and computes their signed\\n    maximum value. Treats the leading bit as the sign, i.e. `max(-2, 6) = 6`.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = max(a, b)\\n    %c = index.maxs %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.maxu\",\n    \"summary\": \"index unsigned maximum\",\n    \"description\": \"The `index.maxu` operation takes two index values and computes their\\n    unsigned maximum value. Treats the leading bit as the most significant, i.e.\\n    `max(15, 6) = 15` or `max(-2, 6) = -2`.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = max(a, b)\\n    %c = index.maxu %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.mins\",\n    \"summary\": \"index signed minimum\",\n    \"description\": \"The `index.mins` operation takes two index values and computes their signed\\n    minimum value. Treats the leading bit as the sign, i.e. `min(-2, 6) = -2`.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = min(a, b)\\n    %c = index.mins %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.minu\",\n    \"summary\": \"index unsigned minimum\",\n    \"description\": \"The `index.minu` operation takes two index values and computes their\\n    unsigned minimum value. Treats the leading bit as the most significant, i.e.\\n    `min(15, 6) = 6` or `min(-2, 6) = 6`.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = min(a, b)\\n    %c = index.minu %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.mul\",\n    \"summary\": \"index multiplication\",\n    \"description\": \"The `index.mul` operation takes two index values and computes their product.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a * b\\n    %c = index.mul %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.or\",\n    \"summary\": \"index bitwise or\",\n    \"description\": \"The `index.or` operation takes two index values and computes their bitwise\\n    or.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a | b\\n    %c = index.or %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.rems\",\n    \"summary\": \"index signed remainder\",\n    \"description\": \"The `index.rems` operation takes two index values and computes their signed\\n    remainder. Treats the leading bit as the sign, i.e. `6 % -2 = 0`.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a % b\\n    %c = index.rems %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.remu\",\n    \"summary\": \"index unsigned remainder\",\n    \"description\": \"The `index.remu` operation takes two index values and computes their\\n    unsigned remainder. Treats the leading bit as the most significant, i.e.\\n    `6 % -2 = 6`.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a % b\\n    %c = index.remu %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.shl\",\n    \"summary\": \"index shift left\",\n    \"description\": \"The `index.shl` operation shifts an index value to the left by a variable\\n    amount. The low order bits are filled with zeroes. The RHS operand is always\\n    treated as unsigned. If the RHS operand is equal to or greater than the\\n    index bitwidth, the result is a poison value.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a << b\\n    %c = index.shl %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.shrs\",\n    \"summary\": \"signed index shift right\",\n    \"description\": \"The `index.shrs` operation shifts an index value to the right by a variable\\n    amount. The LHS operand is treated as signed. The high order bits are filled\\n    with copies of the most significant bit. If the RHS operand is equal to or\\n    greater than the index bitwidth, the result is a poison value.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a >> b\\n    %c = index.shrs %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.shru\",\n    \"summary\": \"unsigned index shift right\",\n    \"description\": \"The `index.shru` operation shifts an index value to the right by a variable\\n    amount. The LHS operand is treated as unsigned. The high order bits are\\n    filled with zeroes. If the RHS operand is equal to or greater than the index\\n    bitwidth, the result is a poison value.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a >> b\\n    %c = index.shru %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.sizeof\",\n    \"summary\": \"size in bits of the index type\",\n    \"description\": \"The `index.sizeof` operation produces an index-typed SSA value equal to the\\n    size in bits of the `index` type. For example, on 32-bit systems, the result\\n    is `32 : index`, and on 64-bit systems, the result is `64 : index`.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = index.sizeof\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"index.sub\",\n    \"summary\": \"index subtraction\",\n    \"description\": \"The `index.sub` operation takes two index values and computes the difference\\n    of the first from the second operand.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a - b\\n    %c = index.sub %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"index.xor\",\n    \"summary\": \"index bitwise xor\",\n    \"description\": \"The `index.xor` operation takes two index values and computes their bitwise\\n    xor.\\n\\n    Example:\\n\\n    ```mlir\\n    // c = a ^ b\\n    %c = index.xor %a, %b\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Index\" },\n      { \"name\": \"rhs\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"interpreter.print\",\n    \"summary\": \"Print operation\",\n    \"description\": \"Print the value to stdout.\\n\\n    This is useful to print intermediate states of the tensors while debugging.\\n    This should only be used to debug small tensors since every instance of this\\n    op and its contents are printed to stdout. To gather information in bulk for\\n    larger tensors, prefer using ProbeOp.\\n\\n    Example:\\n    ```mlir\\n    interpreter.print %operand : tensor<i1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"interpreter.probe\",\n    \"description\": \"Probe and store the values of the input tensor at runtime, using the NumPy\\n    file format. Writes tensor input value to\\n    `<output-dir>/<probe_id>_<iteration>.npy` (where output-dir is specified by\\n    the `--probe_output_dir` flag). Additionally, adds an entry to\\n    <output-dir>/index.csv metadata file which maps probe IDs, types and\\n    filenames with their tensor values.\\n\\n    The `probe` operation will not modify its input in any way. Probe\\n    instrumentation may however slow down the interpretation of a module as\\n    there will be increased file I/O.\\n\\n    Note that `probe_id` should be unique for each `probe` instruction in a\\n    StableHLO module. A `probe` may run more than once, in which case it will\\n    produce separate serialized data for each iteration in the form\\n    `probe_id_#` where # is a 1-based counter.\\n\\n    Example:\\n    ```mlir\\n    %result = interpreter.probe %operand, probe_id = \\\"probe0\\\" : tensor<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"probe_id\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `probe_id` `=` $probe_id attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"interpreter.run_parallel\",\n    \"summary\": \"RunParallel operation\",\n    \"description\": \"Runs a two-dimensional grid of `num_replicas` by `num_partitions` StableHLO\\n    processes based on programs specified by two-dimensional grid of `programs`.\\n\\n    Given that each program in the grid can have a different number of inputs\\n    and outputs, we'd want a ragged three-dimensional tensor to model `inputs`\\n    and `results`, which cannot be easily achieved via conventional means.\\n\\n    Instead, `inputs` and `results` are represented in a flattened way, obtained\\n    by reshaping the said three-dimensional tensors into a one-dimensional form\\n    (with the same semantics as StableHLO's reshape). This is a reversible\\n    transformation because StableHLO programs have a static number of inputs and\\n    outputs.\\n\\n    For example, for a 2x2 StableHLO process grid, `inputs` first has inputs\\n    from the process `(0, 0)` (i.e. replica_id = 0 and partition_id = 0),\\n    then `(0, 1)` (i.e. replica_id = 0 and partition_id = 1), etc.\\n\\n    Example:\\n    ```mlir\\n    %results:2 = \\\"interpreter.run_parallel\\\"() {\\n      infeed=[@infeed_queue0, @infeed_queue1]\\n      programs=[[@foo], [@bar]]\\n    } : () -> (tensor<ui32>, tensor<ui32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_TensorOrToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<HLO_TensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"infeed\", \"type\": \"OptionalAttr<TypedArrayAttrBase<FlatSymbolRefAttr>>\" },\n      { \"name\": \"programs\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<FlatSymbolRefAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"io_parameters.gather\",\n    \"summary\": \"Gathers multiple parameters from a parameter scope.\",\n    \"description\": \"Asynchronously gathers one or more parameters into a single target buffer.\\n    This is equivalent to one read per parameter but allows implementations that\\n    can batch operations to do so without additional overhead.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"target_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"target_lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `{`\\n    custom<ParameterGatherOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        $target_buffer, type($target_buffer), $target_offsets, $target_lengths)\\n    `}`\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"io_parameters.load\",\n    \"summary\": \"Reads one or more parameters from a parameter scope.\",\n    \"description\": \"Asynchronously reads one or more parameters from an external parameter\\n    provider and returns the resulting buffers. Depending on the parameter and\\n    buffer types this may alias existing cached storage or be directly mapped to\\n    the parameter origin or result in a copy as if an allocate + read had been\\n    used.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"memory_types\", \"type\": \"HAL_MemoryType\" },\n      { \"name\": \"buffer_usage\", \"type\": \"HAL_BufferUsage\" },\n      { \"name\": \"lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<HAL_Buffer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `type` `(` $memory_types `)`\\n    `usage` `(` $buffer_usage `)`\\n    `{`\\n    custom<ParameterLoadOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        type($results), $lengths)\\n    `}`\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"io_parameters.scatter\",\n    \"summary\": \"Scatters multiple parameters to a parameter scope.\",\n    \"description\": \"Asynchronously scatters one or more parameters from a single source buffer\\n    into one or more parameters. This is equivalent to one write per parameter\\n    but allows implementations that can batch operations to do so without\\n    additional overhead.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"HAL_Device\" },\n      { \"name\": \"queue_affinity\", \"type\": \"HAL_DeviceQueueAffinity\" },\n      { \"name\": \"wait_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"signal_fence\", \"type\": \"HAL_Fence\" },\n      { \"name\": \"source_buffer\", \"type\": \"HAL_Buffer\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"source_lengths\", \"type\": \"Variadic<HAL_DeviceSize>\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`<` $device `:` type($device) `>`\\n    `affinity` `(` $queue_affinity `)`\\n    `wait` `(` $wait_fence `)`\\n    `signal` `(` $signal_fence `)`\\n    `{`\\n    custom<ParameterScatterOperations>(\\n        $source_buffer, type($source_buffer), $source_offsets, $source_lengths,\\n        $target_scope, $target_keys, $target_offsets)\\n    `}`\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"irdl.all_of\",\n    \"summary\": \"Constraints to the intersection of the provided constraints\",\n    \"description\": \"`irdl.all_of` defines a constraint that accepts any type or attribute that\\n    satisfies all of its provided constraints.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex_f32 {\\n        %0 = irdl.is i32\\n        %1 = irdl.is f32\\n        %2 = irdl.any_of(%0, %1) // is 32-bit\\n\\n        %3 = irdl.is f32\\n        %4 = irdl.is f64\\n        %5 = irdl.any_of(%3, %4) // is a float\\n\\n        %6 = irdl.all_of(%2, %5) // is a 32-bit float\\n        irdl.parameters(%6)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a type `complex` inside the dialect `cmath` that\\n    has one parameter that must be 32-bit long and a float (in other\\n    words, that must be `f32`).\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` ` ` attr-dict\"\n  },\n  {\n    \"name\": \"irdl.any\",\n    \"summary\": \"Accept any type or attribute\",\n    \"description\": \"`irdl.any` defines a constraint that accepts any type or attribute.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex_flexible {\\n        %0 = irdl.any\\n        irdl.parameters(%0)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a type `complex_flexible` inside the dialect\\n    `cmath` that has a single parameter that can be any attribute.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"irdl.any_of\",\n    \"summary\": \"Constraints to the union of the provided constraints\",\n    \"description\": \"`irdl.any_of` defines a constraint that accepts any type or attribute that\\n    satisfies at least one of its provided type constraints.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex {\\n        %0 = irdl.is i32\\n        %1 = irdl.is i64\\n        %2 = irdl.is f32\\n        %3 = irdl.is f64\\n        %4 = irdl.any_of(%0, %1, %2, %3)\\n        irdl.parameters(%4)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a type `complex` inside the dialect `cmath` that\\n    has a single type parameter that can be either `i32`, `i64`, `f32` or\\n    `f64`.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` ` ` attr-dict\"\n  },\n  {\n    \"name\": \"irdl.attribute\",\n    \"summary\": \"Define a new attribute\",\n    \"description\": \"`irdl.attribute` defines a new attribute belonging to the `irdl.dialect`\\n    parent.\\n\\n    The attribute parameters can be defined with an `irdl.parameters` operation\\n    in the optional region.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @testd {\\n      irdl.attribute @enum_attr {\\n        %0 = irdl.is \\\"foo\\\"\\n        %1 = irdl.is \\\"bar\\\"\\n        %2 = irdl.any_of(%0, %1)\\n        irdl.parameters(%2)\\n      }\\n    }\\n    ```\\n\\n    The above program defines an `enum_attr` attribute inside the `testd`\\n    dialect. The attribute has one `StringAttr` parameter that should be\\n    either a `\\\"foo\\\"` or a `\\\"bar\\\"`.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)\"\n  },\n  {\n    \"name\": \"irdl.attributes\",\n    \"summary\": \"Define the attributes of an operation\",\n    \"description\": \"`irdl.attributes` defines the attributes of the `irdl.operation` parent\\n    operation definition.\\n\\n    In the following example, `irdl.attributes` defines the attributes of the\\n    `attr_op` operation:\\n\\n    ```mlir\\n    irdl.dialect @example {\\n\\n      irdl.operation @attr_op {\\n        %0 = irdl.any\\n        %1 = irdl.is i64\\n        irdl.attibutes {\\n          \\\"attr1\\\" = %0,\\n          \\\"attr2\\\" = %1\\n        }\\n      }\\n    }\\n    ```\\n\\n    The operation will expect an arbitrary attribute \\\"attr1\\\" and an\\n    attribute \\\"attr2\\\" with value `i64`.\",\n    \"operands\": [\n      { \"name\": \"attributeValues\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attributeValueNames\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"custom<AttributesOp>($attributeValues, $attributeValueNames) attr-dict\"\n  },\n  {\n    \"name\": \"irdl.base\",\n    \"summary\": \"Constraints an attribute/type base\",\n    \"description\": \"`irdl.base` defines a constraint that only accepts a single type\\n    or attribute base, e.g. an `IntegerType`. The attribute base is defined\\n    either by a symbolic reference to the corresponding IRDL definition,\\n    or by the name of the base. Named bases are prefixed with `!` or `#`\\n    respectively for types and attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex {\\n        %0 = irdl.base \\\"!builtin.integer\\\"\\n        irdl.parameters(%0)\\n      }\\n\\n      irdl.type @complex_wrapper {\\n        %0 = irdl.base @cmath::@complex\\n        irdl.parameters(%0)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a `cmath.complex` type that expects a single\\n    parameter, which is a type with base name `builtin.integer`, which is the\\n    name of an `IntegerType` type.\\n    It also defines a `cmath.complex_wrapper` type that expects a single\\n    parameter, which is a type of base type `cmath.complex`.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"base_ref\", \"type\": \"OptionalAttr<SymbolRefAttr>\" },\n      { \"name\": \"base_name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($base_ref^)? ($base_name^)? ` ` attr-dict\"\n  },\n  {\n    \"name\": \"irdl.c_pred\",\n    \"summary\": \"Constraints an attribute using a C++ predicate\",\n    \"description\": \"`irdl.c_pred` defines a constraint that is written in C++.\\n\\n    Dialects using this operation cannot be registered at runtime, as it relies\\n    on C++ code.\\n\\n    Special placeholders can be used to refer to entities in the context where\\n    this predicate is used. They serve as \\\"hooks\\\" to the enclosing environment.\\n    The following special placeholders are supported in constraints for an op:\\n\\n    * `$_builder` will be replaced by a mlir::Builder instance.\\n    * `$_op` will be replaced by the current operation.\\n    * `$_self` will be replaced with the entity this predicate is attached to.\\n       Compared to ODS, `$_self` is always of type `mlir::Attribute`, and types\\n       are manipulated as `TypeAttr` attributes.\\n\\n    Example:\\n    ```mlir\\n    irdl.type @op_with_attr {\\n      %0 = irdl.c_pred \\\"::llvm::isa<::mlir::IntegerAttr>($_self)\\\"\\n      irdl.parameters(%0)\\n    }\\n    ```\\n\\n    In this example, @op_with_attr is defined as a type with a single\\n    parameter, which is an `IntegerAttr`, as constrained by the C++ predicate.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pred\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$pred ` ` attr-dict\"\n  },\n  {\n    \"name\": \"irdl.dialect\",\n    \"summary\": \"Define a new dialect\",\n    \"description\": \"The `irdl.dialect` operation defines a dialect. All operations, attributes,\\n    and types defined inside its region will be part of the dialect.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      ...\\n    }\\n    ```\\n\\n    The above program defines a `cmath` dialect.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)\"\n  },\n  {\n    \"name\": \"irdl.IRDL_Dialect\",\n    \"summary\": \"Define a new dialect\",\n    \"description\": \"The `irdl.dialect` operation defines a dialect. All operations, attributes,\\n    and types defined inside its region will be part of the dialect.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      ...\\n    }\\n    ```\\n\\n    The above program defines a `cmath` dialect.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)\",\n    \"hasCustomAssemblyFormat\": 0\n  },\n  {\n    \"name\": \"irdl.is\",\n    \"summary\": \"Constraints an attribute/type to be a specific attribute instance\",\n    \"description\": \"`irdl.is` defines a constraint that only accepts a specific instance of a\\n    type or attribute.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex_i32 {\\n        %0 = irdl.is i32\\n        irdl.parameters(%0)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a `complex_i32` type inside the dialect `cmath`\\n    that can only have a `i32` as its parameter.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"expected\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"$expected ` ` attr-dict\"\n  },\n  {\n    \"name\": \"irdl.operands\",\n    \"summary\": \"Define the operands of an operation\",\n    \"description\": \"`irdl.operands` define the operands of the `irdl.operation` parent operation\\n    definition. Each operand is named after an identifier.\\n\\n    In the following example, `irdl.operands` defines the operands of the\\n    `mul` operation:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n\\n      irdl.type @complex { /* ... */ }\\n\\n      irdl.operation @mul {\\n        %0 = irdl.any\\n        %1 = irdl.parametric @cmath::@complex<%0>\\n        irdl.results(res: %1)\\n        irdl.operands(lhs: %1, rhs: %1)\\n      }\\n    }\\n    ```\\n\\n    The `mul` operation will expect two operands of type `cmath.complex`, that\\n    have the same type, and return a result of the same type.\\n\\n    The operands can also be marked as variadic or optional:\\n    ```mlir\\n    irdl.operands(foo: %0, bar: single %1, baz: optional %2, qux: variadic %3)\\n    ```\\n\\n    Here, foo and bar are required single operands, baz is an optional operand,\\n    and qux is a variadic operand.\\n\\n    When more than one operand is marked as optional or variadic, the operation\\n    will expect a 'operandSegmentSizes' attribute that defines the number of\\n    operands in each segment.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"variadicity\", \"type\": \"VariadicityArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`` custom<NamedValueListWithVariadicity>($args, $names, $variadicity) attr-dict\"\n  },\n  {\n    \"name\": \"irdl.operation\",\n    \"summary\": \"Define a new operation\",\n    \"description\": \"`irdl.operation` defines a new operation belonging to the `irdl.dialect`\\n    parent.\\n\\n    Operations can define constraints on their operands and results with the\\n    `irdl.results` and `irdl.operands` operations. If these operations are not\\n    present in the region, the results or operands are expected to be empty.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n\\n      irdl.type @complex { /* ... */ }\\n\\n      irdl.operation @norm {\\n        %0 = irdl.any\\n        %1 = irdl.parametric @cmath::@complex<%0>\\n        irdl.results(%0)\\n        irdl.operands(%1)\\n      }\\n    }\\n    ```\\n\\n    The above program defines an operation `norm` inside the dialect `cmath`.\\n    The operation expects a single operand of base type `cmath.complex`, and\\n    returns a single result of the element type of the operand.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)\"\n  },\n  {\n    \"name\": \"irdl.parameters\",\n    \"summary\": \"Define the constraints on parameters of a type/attribute definition\",\n    \"description\": \"`irdl.parameters` defines the constraints on parameters of a type or\\n    attribute definition. Each parameter is named after an identifier.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex {\\n        %0 = irdl.is i32\\n        %1 = irdl.is i64\\n        %2 = irdl.any_of(%0, %1)\\n        irdl.parameters(elem: %2)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a type `complex` inside the dialect `cmath`. The\\n    type has a single parameter `elem` that should be either `i32` or `i64`.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"`` custom<NamedValueList>($args, $names) attr-dict\"\n  },\n  {\n    \"name\": \"irdl.parametric\",\n    \"summary\": \"Constraints an attribute/type base and its parameters\",\n    \"description\": \"`irdl.parametric` defines a constraint that accepts only a single type\\n    or attribute base. The attribute base is defined by a symbolic reference\\n    to the corresponding definition. It will additionally constraint the\\n    parameters of the type/attribute.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n\\n      irdl.type @complex { /* ... */ }\\n\\n      irdl.operation @norm {\\n        %0 = irdl.any\\n        %1 = irdl.parametric @cmath::@complex<%0>\\n        irdl.operands(%1)\\n        irdl.results(%0)\\n      }\\n    }\\n    ```\\n\\n    The above program defines an operation `norm` inside the dialect `cmath` that\\n    for any `T` takes a `cmath.complex` with parameter `T` and returns a `T`.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_AttributeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"base_type\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$base_type `<` $args `>` ` ` attr-dict\"\n  },\n  {\n    \"name\": \"irdl.region\",\n    \"summary\": \"Define a region of an operation\",\n    \"description\": \"The irdl.region construct defines a set of characteristics\\n    that a region of an operation should satify. Each region is named after\\n    an identifier.\\n\\n    These characteristics include constraints for the entry block arguments\\n    of the region and the total number of blocks it contains.\\n    The number of blocks must be a non-zero and non-negative integer,\\n    and it is optional by default.\\n    The set of constraints for the entry block arguments may be optional or\\n    empty. If no parentheses are provided, the set is assumed to be optional,\\n    and the arguments are not constrained in any way. If parentheses are\\n    provided with no arguments, it means that the region must have\\n    no entry block arguments\\n\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @example {\\n      irdl.operation @op_with_regions {\\n          %r0 = irdl.region\\n          %r1 = irdl.region()\\n          %v0 = irdl.is i32\\n          %v1 = irdl.is i64\\n          %r2 = irdl.region(%v0, %v1)\\n          %r3 = irdl.region with size 3\\n\\n          irdl.regions(foo: %r0, bar: %r1, baz: %r2, qux: %r3)\\n      }\\n    }\\n    ```\\n\\n    The above snippet demonstrates an operation named `@op_with_regions`,\\n    which is constrained to have four regions.\\n\\n    * Region `foo` doesn't have any constraints on the arguments\\n      or the number of blocks.\\n    * Region `bar` should have an empty set of arguments.\\n    * Region `baz` should have two arguments of types `i32` and `i64`.\\n    * Region `qux` should contain exactly three blocks.\",\n    \"operands\": [\n      { \"name\": \"entryBlockArgs\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IRDL_RegionType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numberOfBlocks\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"constrainedArguments\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"``(`(` $entryBlockArgs $constrainedArguments^ `)`)?\\n    ``(` ` `with` `size` $numberOfBlocks^)? attr-dict\"\n  },\n  {\n    \"name\": \"irdl.regions\",\n    \"summary\": \"Define the regions of an operation\",\n    \"description\": \"`irdl.regions` defines the regions of an operation by accepting\\n    values produced by `irdl.region` operation as arguments. Each\\n    region has an identifier as name.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @example {\\n      irdl.operation @op_with_regions {\\n        %r1 = irdl.region with size 3\\n        %0 = irdl.any\\n        %r2 = irdl.region(%0)\\n        irdl.regions(foo: %r1, bar: %r2)\\n      }\\n    }\\n    ```\\n\\n    In the snippet above the operation is constrained to have two regions.\\n    The first region (`foo`) should contain three blocks.\\n    The second region (`bar`) should have one region with one argument.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_RegionType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"`` custom<NamedValueList>($args, $names) attr-dict\"\n  },\n  {\n    \"name\": \"irdl.results\",\n    \"summary\": \"Define the results of an operation\",\n    \"description\": \"`irdl.results` define the results of the `irdl.operation` parent operation\\n    definition. Each result is named after an identifier.\\n\\n    In the following example, `irdl.results` defines the results of the\\n    `get_values` operation:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n\\n      irdl.type @complex { /* ... */ }\\n\\n      /// Returns the real and imaginary parts of a complex number.\\n      irdl.operation @get_values {\\n        %0 = irdl.any\\n        %1 = irdl.parametric @cmath::@complex<%0>\\n        irdl.results(re: %0, im: %0)\\n        irdl.operands(complex: %1)\\n      }\\n    }\\n    ```\\n\\n    The operation will expect one operand of the `cmath.complex` type, and two\\n    results that have the underlying type of the `cmath.complex`.\\n\\n    The results can also be marked as variadic or optional:\\n    ```mlir\\n    irdl.results(foo: %0, bar: single %1, baz: optional %2, qux: variadic %3)\\n    ```\\n\\n    Here, foo and bar are required single results, baz is an optional result,\\n    and qux is a variadic result.\\n\\n    When more than one result is marked as optional or variadic, the operation\\n    will expect a 'resultSegmentSizes' attribute that defines the number of\\n    results in each segment.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<IRDL_AttributeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"variadicity\", \"type\": \"VariadicityArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`` custom<NamedValueListWithVariadicity>($args, $names, $variadicity) attr-dict\"\n  },\n  {\n    \"name\": \"irdl.type\",\n    \"summary\": \"Define a new type\",\n    \"description\": \"`irdl.type` defines a new type belonging to the `irdl.dialect` parent.\\n\\n    The type parameters can be defined with an `irdl.parameters` operation in\\n    the optional region.\\n\\n    Example:\\n\\n    ```mlir\\n    irdl.dialect @cmath {\\n      irdl.type @complex {\\n        %0 = irdl.is i32\\n        %1 = irdl.is i64\\n        %2 = irdl.any_of(%0, %1)\\n        irdl.parameters(%2)\\n      }\\n    }\\n    ```\\n\\n    The above program defines a type `complex` inside the dialect `cmath`. The\\n    type has a single parameter that should be either `i32` or `i64`.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)\"\n  },\n  {\n    \"name\": \"iree_codegen.constraints\",\n    \"summary\": \"SMT constraints for a codegen configuration of root ops.\",\n    \"description\": \"Declares SMT constraints over problem dimensions and configuration\\n    knobs for a codegen pipeline, targeting a set of root ops.\\n\\n    `target`: A `#iree_codegen.root_op<set = N>` attribute identifying\\n    which root op set these constraints apply to. All ops marked with\\n    the same `#iree_codegen.root_op<set = N>` attribute share the same\\n    lowering config. This decouples constraints from SSA values, so ops\\n    with zero or multiple results are supported.\\n\\n    `pipeline`: The codegen pipeline to use. This is a fixed choice,\\n    not decided by the solver.\\n\\n    `knobs`: DictionaryAttr mirroring GPULoweringConfigAttr. Leaves\\n    that are `#iree_codegen.int_knob<\\\"name\\\">` attrs name tunable SMT\\n    constants (materialized by `iree_codegen.knob` ops in the body).\\n    Integer/attr leaves are fixed.\\n\\n    `problem_dims`: index-typed problem dimensions; corresponding block\\n    arguments are !smt.int.\\n\\n    Does not have any execution semantics and is meant to be used by the\\n    tuner or verification passes, and erased before lowering.\\n\\n    Example:\\n    ```mlir\\n    // The matmul is marked: {root_op = #iree_codegen.root_op<set = 0>}\\n    iree_codegen.constraints target = <set = 0>, pipeline = LLVMGPUVectorDistribute,\\n     knobs = {workgroup = [#iree_codegen.int_knob<\\\"wg_m\\\">, #iree_codegen.int_knob<\\\"wg_n\\\">]}\\n     dims(%M, %N, %K) {\\n    ^bb0(%m: !smt.int, %n: !smt.int, %k: !smt.int):\\n      %wg_m = iree_codegen.knob \\\"wg_m\\\" : !smt.int\\n      %wg_n = iree_codegen.knob \\\"wg_n\\\" : !smt.int\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"problem_dims\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"IREECodegen_RootOpAttr\" },\n      { \"name\": \"pipeline\", \"type\": \"AnyAttrOf<[DispatchLoweringPassPipelineAttr{CPUDefault|CPUDoubleTilingExpert|CPUConvTileAndDecomposeExpert|Mmt4dTilingExpert|CPUBufferOpsTileAndVectorize|CPUDataTiling|CPULinalgExtTileAndVectorize|LLVMGPUDefault|LLVMGPUBaseLowering|LLVMGPUDistribute|LLVMGPUVectorize|LLVMGPUVectorDistribute|LLVMGPUWinogradVectorize|LLVMGPUTileAndFuse|SPIRVBaseLowering|SPIRVBaseDistribute|SPIRVBaseVectorize|SPIRVSubgroupReduce|SPIRVMatmulPromoteVectorize|SPIRVCooperativeMatrixVectorize|SPIRVWinogradVectorize|VMVXDefault|TransformDialectCodegen|Custom|None}, IREECodegen_PipelineAttrInterface]>\" },\n      { \"name\": \"knobs\", \"type\": \"DictionaryAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`target` `=` $target `,` `pipeline` `=` custom<PipelineAttr>($pipeline) `,`\\n    custom<KnobsDictionary>($knobs)\\n    `dims` `(` $problem_dims `)` attr-dict-with-keyword\\n    $body\"\n  },\n  {\n    \"name\": \"iree_codegen.extract_strided_metadata\",\n    \"summary\": \"Extracts a buffer base with offset and strides.\",\n    \"description\": \"This op is implemented similarly to the upstream MemRef::ExtractStridedMetadataOp\\n    with the following differences.\\n\\n    1. It does not fold away static offset/stride information.\\n    Hence unlike the upstream Op the link between the memref and consumers of the\\n    metadata is not broken when later passes change this information. A common\\n    example in IREE of this is buffer binding optimizations.\\n\\n    2. Helper functions getConstifiedMixed{Offset|Strides|Sizes} are not implemented\\n    as the expectation is you should lower to the upstream op before using those\\n    functions if you need them.\\n\\n    Copy of MemRef::ExtractStridedMetadataOp description for reference below.\\n    Extracts a base buffer, offset and strides. This op allows additional layers\\n    of transformations and foldings to be added as lowering progresses from\\n    higher-level dialect to lower-level dialects such as the LLVM dialect.\\n\\n    The op requires a strided memref source operand. If the source operand is not\\n    a strided memref, then verification fails.\\n\\n    This operation is also useful for completeness to the existing memref.dim op.\\n    While accessing strides, offsets and the base pointer independently is not\\n    available, this is useful for composing with its natural complement op:\\n    `memref.reinterpret_cast`.\\n\\n    Intended Use Cases:\\n\\n    The main use case is to expose the logic for manipulate memref metadata at a\\n    higher level than the LLVM dialect.\\n    This makes lowering more progressive and brings the following benefits:\\n      - not all users of MLIR want to lower to LLVM and the information to e.g.\\n        lower to library calls---like libxsmm---or to SPIR-V was not available.\\n      - foldings and canonicalizations can happen at a higher level in MLIR:\\n        before this op existed, lowering to LLVM would create large amounts of\\n        LLVMIR. Even when LLVM does a good job at folding the low-level IR from\\n        a performance perspective, it is unnecessarily opaque and inefficient to\\n        send unkempt IR to LLVM.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"base_buffer\", \"type\": \"AnyStridedMemRefOfRank<0>\" },\n      { \"name\": \"offset\", \"type\": \"Index\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$source `:` type($source) `->` type(results) attr-dict\"\n  },\n  {\n    \"name\": \"iree_codegen.fusion_barrier\",\n    \"summary\": \"Prevents fusion through a tensor value\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_codegen.index_hint\",\n    \"summary\": \"Compiler hint providing semantic information about an index\",\n    \"description\": \"Pure pass-through operation that annotates an index value with semantic\\n    information about how it varies across parallel workers (e.g., GPU lanes).\\n\\n    The hint attribute describes the index behavior. Common hints include:\\n    - `#iree_gpu.lane_constant<N>`: Index is uniform within groups of N lanes\\n    - `#iree_gpu.lane_increment<N>`: Index increments by 1 within groups of N lanes\\n\\n    This operation is always safe to remove (replace with input). It exists\\n    purely to guide optimization passes.\\n\\n    Example:\\n    ```mlir\\n    %row = iree_codegen.index_hint %idx(#iree_gpu.lane_constant<16>) : index\\n    %col = iree_codegen.index_hint %idx(#iree_gpu.lane_increment<16>) : index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hint\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `(` $hint `)` attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"iree_codegen.inner_tiled\",\n    \"summary\": \"Models an inner-tiled operation that may perform contractions.\",\n    \"description\": \"Represents an operation that updates \\\"inner tiles\\\" (vector slices) of its accumulator\\n    outputs using inner tiles of its input operands. The way the inner tiles are\\n    used is determined by the semantics of the `kind` attribute. These inner tiles\\n    are the trailing dimensions of the tensor/vector operands that are not present\\n    in the indexing maps.\\n\\n    In the case of a matrix-multiply-accumulate (MMA) inner tiled operation,\\n    the semantics logically match `vector.contraction`. However, instead of a\\n    combiner type, it has a intrinsic description that specifies how the inner tiles\\n    are combined.\\n\\n    Similar to `vector.contract`, an iterator type attribute list must be\\n    specified, where each element of the list represents an iterator over one\\n    of the outer dimensions. Iteration of inner dimensions is defined solely by\\n    the intrinsic and may be opaque.\\n\\n    An indexing map attribute list must be specified with an entry for input and\\n    output arguments. An indexing map attribute specifies a mapping from each\\n    outer loop iterator in the iterator type list, to each dimension of each\\n    operand.\\n\\n    Example:\\n\\n    ```mlir\\n    #contraction_accesses = [\\n     affine_map<(i, j, k) -> (i, k)>,\\n     affine_map<(i, j, k) -> (k, j)>,\\n     affine_map<(i, j, k) -> (i, j)>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"reduction\\\"],\\n      kind = #iree_gpu.mma_layout<MFMA_F32_16x16x16_F16>,\\n      distributed = true,\\n      opaque = false\\n    }\\n    %3 = iree_codegen.inner_tiled ins(%0, %1) outs(%2) #contraction_trait\\n      : vector<2x3x4xf16>, vector<3x5x4xf16> into vector<2x5x4xf32>\\n\\n    // Takes tensors as well, however the inner dimensions must always be\\n    // static.\\n    %7 = iree_codegen.inner_tiled ins(%4, %5) outs(%6) #contraction_trait\\n      : tensor<?x?x4xf16>, tensor<?x?x4xf16> into tensor<?x?x4xf32>\\n    ```\\n\\n    The example above can be logically lowered directly to loops like this\\n    (ignoring type conversions from tensor to vector needed for the mfma).\\n    ```\\n    %outer_m = tensor.dim %6, %c0 : index\\n    %outer_n = tensor.dim %6, %c1 : index\\n    %outer_k = tensor.dim %4, %c1 : index\\n    %7 = scf.for %i = %c0 to %outer_m iter_args(%arg0 = %6) {\\n      %8 = scf.for %j = %c0 to %outer_n iter_args(%arg1 = %arg0) {\\n        %9 = scf.for %k = %c0 to %outer_k iter_args(%arg2 = %arg1) {\\n          %lhs = tensor.extract_slice %4 [%i, %k, 0] [1, 1, 4] [1, 1, 1] : tensor<4xf16>\\n          %rhs = tensor.extract_slice %5 [%k, %j, 0] [1, 1, 4] [1, 1, 1] : tensor<4xf16>\\n          %acc = tensor.extract_slice %arg2 [%i, %j, 0] [1, 1, 4] [1, 1, 1] : tensor<4xf32>\\n          %res = amdgpu.mfma %lhs, %rhs, %acc : tensor<4xf32>\\n          %ret = tensor.insert_slice %acc into %arg2 [%i, %j, 0] [1, 1, 4] [1, 1, 1] : tensor<?x?x4xf32>\\n          scf.yield %ret : tensor<?x?x4xf32>\\n        }\\n        scf.yield %9 : tensor<?x?x4xf32>\\n      }\\n      scf.yield %8 : tensor<?x?x4xf32>\\n    }\\n    ```\\n\\n    Or alternatively unrolled to a single intrinsic when operating on vectors.\\n    ```mlir\\n    #contraction_accesses = [\\n     affine_map<() -> ()>,\\n     affine_map<() -> ()>,\\n     affine_map<() -> ()>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [],\\n      kind = #iree_gpu.mma_layout<MFMA_F32_16x16x16_F16>,\\n      distributed = true,\\n      opaque = false\\n    }\\n    %3 = iree_codegen.inner_tiled ins(%0, %1) outs(%2) #contraction_trait\\n      : vector<4xf16>, vector<4xf16> into vector<4xf32>\\n    ```\\n\\n    This operation can represent an intrinsic both in undistributed\\n    (workgroup/subgroup/warp) and distributed (thread) level. This is indicated\\n    by the `distributed` boolean attribute. The same `kind` attribute may be\\n    used in both cases.\\n\\n    The inner-tile shapes of tensor operands (defined as above as the trailing\\n    dimensions not present in the indexing maps) must agree with the shapes of\\n    the vector tiles implied by the intrinsic specified in `kind`. The exact\\n    criterion depends on the `opaque` boolean attribute:\\n    * When `opaque = true`, the only requirement is that they have the same\\n      number of elements.\\n    * When `opaque = false`, the shapes must match exactly after omitting any\\n      unit-dimensions.\\n\\n    Note that different `kind` attributes may adopt different conventions as to\\n    the intrinsic vector tile formats. Some may use only flattened 1-D vectors,\\n    and it may be necessary to use `opaque = true` to accommodate them. Others\\n    may use higher-rank vectors with shapes reflecting semantics, allowing to\\n    use `opaque = false`, which is preferable when possible at all thanks to the\\n    stricter semantics. However, that is not only a function of the `kind`\\n    attribute: using `opaque = false` also requires the tensor operands to have\\n    appropriate shapes.\\n\\n    In some cases, variations on the inner tiled operations can be expressed\\n    with the permutations attribute. This attribute represents the permutation\\n    from that intrinsic's \\\"canonical\\\" layout (in the case of matrix multiplication,\\n    this is row-major storage of the inner tile) to the format of the inner tile\\n    in the arguments, with a permutation specified for each argument.\\n\\n    For example, an MMT product of inner dimensions with warp semantics can be\\n    represented with the following.\\n\\n    ```mlir\\n    #contraction_accesses = [\\n     affine_map<(i, j, k) -> (i, k)>,\\n     affine_map<(i, j, k) -> (k, j)>,\\n     affine_map<(i, j, k) -> (i, j)>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"reduction\\\"],\\n      kind = #iree_gpu.mma_layout<MFMA_F32_16x16x16_F16>,\\n      permutations = [[0, 1], [1, 0], [0, 1]]\\n    }\\n    %7 = iree_codegen.inner_tiled ins(%4, %5) outs(%6) #contraction_trait\\n      : tensor<?x?x16x16xf16>, tensor<?x?x16x16xf16> into tensor<?x?x16x16xf32>\\n    ```\\n\\n    #### Motivation, Design Choices, and Pitfalls\\n\\n    This operation grew out of a general representation for matrix multiplication\\n    intrinsics on GPUs, where the inner tiles would be the tiles of the A, B,\\n    and C matrices that were computed by an entire GPU workgroup or subgroup. It\\n    is now used for generalizations of such multiplications. Currently,\\n    the only usage is for scaled matrix-multiply-accumulate, where block scales\\n    must be passed in as additional inputs, but it's possible more uses\\n    will be possible in the future.\\n\\n    The idea behind this operation is to decouple the layout setting/tiling\\n    required to target certain intrinsics from the lowering to them. Because\\n    typically tiling of this sort happens on tensor operands, however the target\\n    intrinsics operate on vectors, we use this operation to bridge the gap. The\\n    choice for a shared operation is intended to ease the lowering process and\\n    allow for different transformations at different stages of the pipeline\\n    without needing to essentially clone this op.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensorOrVector>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensorOrVector>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensorOrVector>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr, indexing affine maps>\" },\n      { \"name\": \"iterator_types\", \"type\": \"TypedArrayAttrBase<IteratorTypeEnum{parallel|reduction}>\" },\n      { \"name\": \"kind\", \"type\": \"IREECodegen_AnyInnerTileDescAttr\" },\n      { \"name\": \"semantics\", \"type\": \"IREECodegen_AnyInnerTiledSemanticscAttr\" },\n      { \"name\": \"permutations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DenseI64ArrayAttr, permutations>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`ins` `(` $inputs `)` `outs` `(` $outputs `)` attr-dict\\n    `:` type($inputs) `into` type($outputs)\"\n  },\n  {\n    \"name\": \"iree_codegen.knob\",\n    \"summary\": \"Declare an SMT constant for a tunable configuration knob.\",\n    \"description\": \"Materializes a named SMT constant (!smt.int) for use in constraint\\n    expressions. The name must match an `#iree_codegen.int_knob<\\\"name\\\">`\\n    leaf in the enclosing `iree_codegen.constraints` op's `knobs`\\n    dictionary.\\n\\n    In SMT terminology this is a constant (0-ary function), not a variable.\\n    The tuner assigns concrete integer values to these constants.\\n\\n    Example:\\n    ```mlir\\n    %wg_m = iree_codegen.knob \\\"wg_m\\\" : !smt.int\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_codegen.load_from_buffer\",\n    \"summary\": \"Loads a tensor from a memref.\",\n    \"description\": \"Loads a tensor from a memref with a compatible shape and the same element\\n    type.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$buffer attr-dict `:` type($buffer) `->` type($tensor)\"\n  },\n  {\n    \"name\": \"iree_codegen.null_pointer\",\n    \"summary\": \"Returns a null_pointer value.\",\n    \"description\": \"This is meant to be used only as arguments to microkernels.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"NullPointer\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"iree_codegen.query_tile_sizes\",\n    \"summary\": \"Yields tile sizes for the specified tensor type.\",\n    \"description\": \"For targets where tile sizes can't be resolved at compile time, this\\n    operation allows querying the sizes at runtime. Today this only applies\\n    to VMVX.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_type\", \"type\": \"TensorTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $tensor_type `->` type($results)\"\n  },\n  {\n    \"name\": \"iree_codegen.smt.assert\",\n    \"summary\": \"Named SMT assertion for constraint verification.\",\n    \"description\": \"Asserts that a boolean SMT expression holds, with a human-readable\\n    format string describing what is being checked. The format string may\\n    contain `{}` placeholders that correspond positionally to the `args`\\n    operands. An evaluator or verifier can substitute concrete values into\\n    the placeholders for diagnostics.\\n\\n    Args are restricted to `!smt.int` because all constraint knobs and\\n    dimension values are integers.\\n\\n    Used inside `iree_codegen.smt.constraints` regions.\\n\\n    Examples:\\n    ```mlir\\n    // Static message (no args):\\n    iree_codegen.smt.assert %cond, \\\"dim_0 == 128\\\" : !smt.bool\\n\\n    // Format string with args:\\n    iree_codegen.smt.assert %cond, \\\"wg_x ({}) < wg_y ({})\\\", %x, %y : !smt.bool, !smt.int, !smt.int\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"BoolType\" },\n      { \"name\": \"printArgs\", \"type\": \"Variadic<IntType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$condition `,` $msg (`,` $printArgs^)?\\n        `:` type($condition) (`,` type($printArgs)^)? attr-dict\"\n  },\n  {\n    \"name\": \"iree_codegen.smt.constraints\",\n    \"summary\": \"SMT constraints for a codegen configuration of root ops.\",\n    \"description\": \"Declares SMT constraints over problem dimensions and configuration\\n    knobs for a codegen pipeline, targeting a set of root ops.\\n\\n    `target`: A `#iree_codegen.root_op<set = N>` attribute identifying\\n    which root op set these constraints apply to. All ops marked with\\n    the same `#iree_codegen.root_op<set = N>` attribute share the same\\n    lowering config. This decouples constraints from SSA values, so ops\\n    with zero or multiple results are supported.\\n\\n    `pipeline`: The codegen pipeline to use. This is a fixed choice,\\n    not decided by the solver.\\n\\n    `knobs`: DictionaryAttr mirroring GPULoweringConfigAttr. Leaves\\n    that are `#iree_codegen.smt.int_knob<\\\"name\\\">` attrs name tunable SMT\\n    constants (materialized by `iree_codegen.smt.knob` ops in the body).\\n    Integer/attr leaves are fixed.\\n\\n    `problem_dims`: index-typed problem dimensions; corresponding block\\n    arguments are !smt.int.\\n\\n    Does not have any execution semantics and is meant to be used by the\\n    tuner or verification passes, and erased before lowering.\\n\\n    Example:\\n    ```mlir\\n    // The matmul is marked: {root_op = #iree_codegen.root_op<set = 0>}\\n    iree_codegen.smt.constraints target = <set = 0>, pipeline = #iree_gpu.pipeline<VectorDistribute>,\\n     knobs = {workgroup = [#iree_codegen.smt.int_knob<\\\"wg_m\\\">, #iree_codegen.smt.int_knob<\\\"wg_n\\\">]}\\n     dims(%M, %N, %K) {\\n    ^bb0(%m: !smt.int, %n: !smt.int, %k: !smt.int):\\n      %wg_m = iree_codegen.smt.knob \\\"wg_m\\\" : !smt.int\\n      %wg_n = iree_codegen.smt.knob \\\"wg_n\\\" : !smt.int\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"problem_dims\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"IREECodegen_RootOpAttr\" },\n      { \"name\": \"pipeline\", \"type\": \"AnyAttrOf<[DispatchLoweringPassPipelineAttr{CPUDefault|CPUDoubleTilingExpert|CPUConvTileAndDecomposeExpert|Mmt4dTilingExpert|CPUBufferOpsTileAndVectorize|CPUDataTiling|CPULinalgExtTileAndVectorize|VMVXDefault|TransformDialectCodegen|Custom|None}, IREECodegen_PipelineAttrInterface]>\" },\n      { \"name\": \"knobs\", \"type\": \"DictionaryAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`target` `=` $target `,` `pipeline` `=` custom<PipelineAttr>($pipeline) `,`\\n    custom<KnobsDictionary>($knobs)\\n    `dims` `(` $problem_dims `)` attr-dict-with-keyword\\n    $body\"\n  },\n  {\n    \"name\": \"iree_codegen.smt.knob\",\n    \"summary\": \"Declare an SMT constant for a tunable configuration knob.\",\n    \"description\": \"Materializes a named SMT constant (!smt.int) for use in constraint\\n    expressions. The name must match an `#iree_codegen.smt.int_knob<\\\"name\\\">`\\n    or `#iree_codegen.smt.one_of_knob<\\\"name\\\", [...]>` leaf in the\\n    enclosing `iree_codegen.smt.constraints` op's `knobs` dictionary.\\n\\n    In SMT terminology this is a constant (0-ary function), not a variable.\\n    The tuner assigns concrete integer values to these constants.\\n\\n    Example:\\n    ```mlir\\n    %wg_m = iree_codegen.smt.knob \\\"wg_m\\\" : !smt.int\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_codegen.smt.lookup\",\n    \"summary\": \"Integer table lookup for SMT constraints.\",\n    \"description\": \"Maps an SMT integer index to an integer value via a sparse key-value\\n    table. Used to derive values from enumerated knobs (e.g., MMA shape\\n    dimensions from an mma_idx knob).\\n\\n    TODO: During constraint verification, the lookup will be evaluated\\n    directly. During SMT-LIB export, it will be lowered to a chain of\\n    `smt.ite` ops. Neither pass is implemented yet.\\n\\n    Example:\\n    ```mlir\\n    %mma_m = iree_codegen.smt.lookup %idx [3, 7, 12] -> [16, 32, 64] : !smt.int\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keys\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"values\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$index $keys `->` $values attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_codegen.store_to_buffer\",\n    \"summary\": \"Stores a tensor into a memref.\",\n    \"description\": \"Stores a tensor into a memref with a compatible shape and the same element\\n    type.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$tensor `,` $buffer\\n    attr-dict `:` type($tensor) `into` type($buffer)\"\n  },\n  {\n    \"name\": \"iree_codegen.swizzle_hint\",\n    \"summary\": \"Hint to swizzle accesses according to an access pattern.\",\n    \"description\": \"Optimization hint to swizzle all accesses to the memref or tensor that this takes a\\n    view of. This only affects reads/writes that immediately consume this operation\\n    and is best effort. If the desired swizzling is not apparently possible, this\\n    op will no-op. As a result, it should not be relied on for correctness.\\n\\n    Any subviews on this operation will cause the swizzle application to fail. The\\n    expectation is for all view like operations to fold into the accessing ops\\n    (loads/stores) before this op takes effect.\\n\\n    Note that this only rewrites direct users. If there are any aliased loads\\n    or stores of the data from/to the |src| memref of a hintOp, those accesses\\n    will not be swizzled. This allows reusing an allocation with different\\n    swizzled access patterns as long as there is no data dependency between\\n    memory with different layouts. For example:\\n\\n    ```\\n    %0 = alloc()\\n    %1 = iree_codegen.swizzle_hint %0, #layout_0\\n    %2 = iree_codegen.swizzle_hint %0, #layout_1\\n    {\\n       vector.store %1\\n       vector.load %1\\n         ^\\n         |\\n        unrelated\\n         |\\n         v\\n       vector.store %2\\n       vector.load %2\\n    }\\n    ```\\n\\n    If there is a data dependency between the accesses of %1 and %2, for example\\n    a value stored to %1 is loaded from %2, this is undefined behavior. Aliasing\\n    is otherwise perfectly legal.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"swizzle\", \"type\": \"IREECodegen_AnySwizzleAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `[` $swizzle attr-dict `]` `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_codegen.ukernel.generic\",\n    \"summary\": \"Generic Microkernel operator.\",\n    \"description\": \"Operation to wrap a computation forwarded to a microkernel.\\n\\n    This operation is a generic representation of the DAG that is to be\\n    lowered into a micro-kernel. The name of the microkernel is specified\\n    as a `StrAttr`. The DAG to be forwarded is meant to be captured at\\n    tensor-level. The operation implements the `DestinationStyleOpInterface`\\n    so all tensors in the `outs` list must match the number and type of the\\n    results of the operation.\\n    After bufferization the tensor operands in `outs` are converted to\\n    a memref type. At the memref-level, the operands are expected to\\n    match directly into a function call with the arguments to the\\n    function call being the `ins`, `outs` and `other_operands`.\\n\\n    The operands of `memref` type are expected to lower to this sequence of\\n    function arguments:\\n      `base_pointer, offset, stride0, stride1, stride2, ...`\\n    By default, all N strides are passed for each memref of rank N. This can be\\n    overridden by the optional `strided_dims` attribute: if set, its value\\n    is a list of dimensions for which strides are passed for each ShapedType\\n    operand, in the order that they appear as operands. Non-ShapedType operands\\n    are ignored in the strided_dims list.\\n\\n    Note that `memref` semantics only guarantee that a `base_pointer + offset`\\n    represents the position to read from. So all micro-kernel implementations\\n    are expected to take at least a `base_pointer, offset` pair for each\\n    operand (input or output) of `memref` type. The `offset` has to be added to\\n    the `base_pointer` before dereferencing to read/write data. Also note that\\n    the `offset` is in number of elements.\\n\\n    All other operands are expected to be scalar types.\\n    TODO: `vector` types can be supported as well, but needs better\\n    ABI specification.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensorOrMemRef>\" },\n      { \"name\": \"other_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"u_kernel_fn_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"fn_def_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"strided_dims\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $u_kernel_fn_name\\n    (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    (`outs` `(` $outputs^  `:` type($outputs) `)`)?\\n    (`(` $other_operands^ `:` type($other_operands) `)`)?\\n    ( `fn_def_attrs` $fn_def_attrs^ )?\\n    (`strided_dims` `(` $strided_dims^ `)`)? (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"iree_codegen.workgroup_count_hint\",\n    \"summary\": \"Hints at the workgroup count to set\",\n    \"description\": \"Captures a set of values to use as the workgroup count. The backward slice\\n    starting from this op's operands is cloned into the workgroup count region\\n    of all transitive callers.\\n\\n    The sizes are specified in logical order (innermost to outermost), matching\\n    the workgroup count region's (x, y, z) convention. If fewer than 3 sizes\\n    are provided, the remaining dimensions default to 1.\\n\\n    If multiple hints inform the same entry point, the **elementwise maximum**\\n    across all hints is used as the count along each dimension. For example:\\n\\n    ```mlir\\n    hal.executable.export @entry_point\\n    module {\\n      func.func @entry_point() {\\n        iree_codegen.workgroup_count_hint sizes(%a, %b, %c)\\n        iree_codegen.workgroup_count_hint sizes(%x, %y, %z)\\n      }\\n    }\\n    ```\\n\\n    resolves to:\\n\\n    ```mlir\\n    hal.executable.export @entry_point {\\n      %wx = arith.maxsi %a, %x\\n      %wy = arith.maxsi %b, %y\\n      %wz = arith.maxsi %c, %z\\n      hal.return %wx, %wy, %wz\\n    }\\n    ```\\n\\n    #### Common Usage: Linearized Workgroup Counts\\n\\n    The most common use case for this operation involves computing a linearized\\n    (1-D) workgroup count and specifying it as a single size.\\n\\n    ```mlir\\n    %num_workgroups = arith.ceildivui %total_iterations, %tile_size : index\\n    iree_codegen.workgroup_count_hint sizes(%num_workgroups)\\n    ```\\n\\n    This results in `(%num_workgroups, 1, 1)` as the final workgroup count.\",\n    \"operands\": [\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_encoding.set_encoding\",\n    \"summary\": \"Perform pack and pad operation on source.\",\n    \"description\": \"Operation to assign an encoding to a tensor. The operation does not change\\n    the rank or extent of a tensor. Instead it adds a LayoutResolverAttr\\n    attribute to the tensor type to represent a change in layout.\\n\\n    The optional `encoding_dims` operand carries dynamic values needed by the\\n    encoding (e.g., M, N, K dimensions for matmul encodings). These values are\\n    used for runtime layout selection based on problem size.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"encoding_dims\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source (`encoding_dims` `{` $encoding_dims^ `}`)? `:` type($source) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_encoding.unset_encoding\",\n    \"summary\": \"Perform unpack and extract operation on source.\",\n    \"description\": \"Operation to convert a tensor with LayoutResolverAttr encoding that\\n    represents its data layout into a tensor with default layout\\n    (i.e. no encoding). For now in IREE the default layout is row-major.\\n\\n    The optional `encoding_dims` operand carries dynamic values needed by the\\n    encoding (e.g., M, N, K dimensions for matmul encodings). These values are\\n    used for runtime layout selection based on problem size.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"encoding_dims\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source (`encoding_dims` `{` $encoding_dims^ `}`)? `:` type($source) `->` type($result) (`` `{` $result_dims^ `}`)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_gpu.barrier_region\",\n    \"summary\": \"Synchronizes workers on a region of shared code.\",\n    \"description\": \"This op is designed to represent synchronization of workers on the operands\\n    and results of the given region. This operation naturally arises when combining\\n    the regions of producer-consumer `scf.forall` operations that share a\\n    mapping type.\\n\\n    For example, consider the following pair of parallel loops.\\n    ```mlir\\n      %0 = scf.forall (%idy, %idx) in (2, 32) shared_outs(%init = %empty) -> (tensor<4x128xf32>) {\\n        %in = ...\\n        %2 = affine.apply #affine_map<(d0) -> (d0 * 2)> (%idy)\\n        %3 = affine.apply #affine_map<(d0) -> (d0 * 4)> (%idx)\\n        scf.forall.in_parallel {\\n          tensor.parallel_insert_slice %in into %init[%2, %3] [2, 4] [1, 1]\\n            : tensor<2x4xf32> into tensor<4x128xf32>\\n        }\\n      } {mapping = [#gpu.thread<y>, #gpu.thread<x>]}\\n      %1 = scf.forall (%idy, %idx) in (8, 8) -> (tensor<128x128xf32>) {\\n        %4 = affine.apply #affine_map<(d0) -> (d0 * 16)> (%idx)\\n        %extracted_slice = tensor.extract_slice %0[0, %4] [4, 16] [1, 1]\\n          : tensor<4x128xf32> to tensor<4x16xf32>\\n        ...\\n      } {mapping = [#gpu.thread<y>, #gpu.thread<x>]}\\n    ```\\n\\n    Because these loops share the same worker type and total count, the bodies\\n    of these two loops can be merged with a barrier an insert_slice and a\\n    shuffle where the boundary of the loops currently is.\\n\\n    ```mlir\\n      %0 = scf.forall (%idy, %idx) in (8, 8) -> (tensor<4x128xf32>) {\\n        %alloc = bufferization.alloc_tensor {memory_space = #gpu.address_space<workgroup>}\\n          : tensor<4x128xf32>\\n        %barrier = iree_gpu.barrier_region %alloc {\\n        ^bb0(%shared: tensor<4x128xf32>):\\n          %ids = affine.delinearize_index %idy * 8 + %idx to (2, 32) : index\\n          %in = ...\\n          %2 = affine.apply #affine_map<(d0) -> (d0 * 2)> (%ids#0)\\n          %3 = affine.apply #affine_map<(d0) -> (d0 * 4)> (%ids#1)\\n          %inserted_slice = tensor.insert_slice %in into %shared[%2, %3] [2, 4] [1, 1]\\n            : tensor<2x4xf32> to tensor<4x128xf32>\\n          iree_gpu.yield %slice : tensor<4x16xf32>\\n        } : tensor<4x128xf32> -> tensor<4x16xf32>\\n        %4 = affine.apply #affine_map<(d0) -> (d0 * 16)> (%idx)\\n        %slice = tensor.extract_slice %barrier[0, %4] [4, 16] [1, 1] : tensor<4x128xf32> to tensor<4x16xf32>\\n        ...\\n      } {mapping = [#gpu.thread<y>, #gpu.thread<x>]}\\n    ```\\n\\n    A barrier_region can be lowered to two barriers, one on the input operands\\n    and a second one on the results.\\n\\n    Movtivation and Intended Use Cases:\\n\\n    The primary way this op is generated is when fusing parallel loops with\\n    tensor results. This operation helps to make lowerings more progressive\\n    and flexible.\\n      - Lowering directly to an alloc + reads and writes breaks the dependency\\n        chain making transformations like barrier placement and pipelining\\n        potentially more difficult.\\n      - Allows the option of non-vector based lowering paths.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"(`ins` `(` $inputs^ `:` type($inputs) `)` )?\\n    $region attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"iree_gpu.buffer_resource_cast\",\n    \"summary\": \"Represents a cast to addr_space<7> (buffer resource) before bufferization.\",\n    \"description\": \"Nominal cast of a tensor to AMDGPU buffer resource memory space before\\n    bufferization. This op takes the parameters with which to perform the cast\\n    if |input| bufferizes to `storage_buffer` memory space. If |input| resolves\\n    to any other memory space this op is silently dropped and has no effect.\\n\\n    If |cache_swizzle_stride| is present, there is verification before\\n    bufferization that all producers of |input| are view-like and single source\\n    and user (i.e. trivially no alias). In all other cases this op is best\\n    effort and has no verification or failure modes.\\n\\n    // TODO: Add other parameters for casting as needed.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"cache_swizzle_stride\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$input oilist (`cacheSwizzleStride` `(` $cache_swizzle_stride `)` )\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_gpu.coalesced_gather_dma\",\n    \"summary\": \"Coalesced gather DMA operation for efficient GPU memory access\",\n    \"description\": \"Performs a coalesced gather operation.\\n    This operation can exist in two forms: a tensor-based\\n    (value-semantic) form and a buffer-based (memref-semantic) form.\\n\\n    In both forms, it reads elements from a source operand based on the\\n    optional `indices` operand and writes the gathered data into the\\n    destination `init` operand using destination-passing style.\\n\\n    The `indices` operand is optional. The `source` represents the data\\n    loaded by this thread, while `init` is the collective output for all\\n    threads in the subgroup. Therefore, `source` and `init` may have\\n    different shapes (typically source is smaller, representing one\\n    thread's portion).\\n\\n    The operation is specifically designed for subgroup-level\\n    parallelism, where threads within a subgroup cooperatively gather\\n    data with coalesced memory accesses. It implements\\n    ParallelCombiningOpInterface and must live inside an op implementing\\n    `InParallelOpInterface`, such as `scf.forall.in_parallel`.\\n\\n    ## Lowering Paths\\n\\n    Two lowering strategies are supported:\\n    1. Lowers to `amdgpu.gather_to_lds` operations when lowering\\n       requirements are met.\\n    2. Default lowering using `vector.gather` operations.\\n\\n    ## Operands and Results\\n\\n    * `$indices`: The variadic `indices` operand is an optional tensor\\n      or vector of indices to gather from `source`. If the indices are\\n      present, their shape must be a prefix of the `init`/`result` type.\\n      Each element of `indices` must be a 1D tensor or vector whose\\n      length matches the length of the corresponding dimension of `source`.\\n\\n      The values in `indices` form indices into the memref starting at\\n      `source` from which a given thread will gather data, and each\\n      tensor/vector component in `indices` corresponds to one index\\n      dimension in `source`.\\n      Any component that is not specified is implicitly assumed to be\\n      `[0, 1, ..., len - 1]` where `len` is the length of the\\n      corresponding dimension of source. That is, gather all the\\n      elements along that dimension.\\n\\n      This operation will gather data into its result as by setting:\\n      ```\\n      forall (i0, i1, ... iN) in (dim(source, 0), dim(source, 1), ...\\n          dim(source, N)):\\n        result[i0, i1, ... iN-1, iN + lane_id * dim(init, N)] =\\n            source[indices[0][i0], indices[1][i1], ..., indices[N][iN]]\\n      ```\\n      where `lane_id` is the ID of the thread within its subgroup.\\n\\n      Note that, in order to enable efficient gathers, the trailing\\n      dimension of `source` must have unspecified indices and the dim's\\n      size must be a supported DMA width for your target.\\n\\n      `$indices` supports both index and i32 element types. The reason\\n      is that one lowering path (from linalg_ext.gather) already have\\n      indices in i32 type.\\n\\n    * `$source`: Source tensor/memref containing the data to be gathered.\\n    * `$init`: Destination tensor/memref receiving the gathered data\\n      (destination-passing style).\\n    * `lane`: The lane that specifies the coalescing store's offset within the\\n      workgroup/shared memory.\\n\\n    ## In-Bounds Attribute\\n\\n    The optional `in_bounds` attribute is a boolean array with one entry per\\n    dimension of `init`. When not present, all dimensions are treated as\\n    in-bounds (source and init must have matching sizes for non-indexed dims).\\n\\n    When present, `in_bounds[i] = false` indicates that the source may be\\n    smaller than init along dimension `i`. Reads beyond the source extent\\n    return zero (padding semantics). This enables fusion of `tensor.pad`\\n    with zero padding into the DMA operation.\\n\\n    `in_bounds[i] = true` means the source and init sizes match along that\\n    dimension, and no padding is needed.\\n\\n    ## Example of a single subgroup using coalesced_gather_dma in copy mode\\n       for transferring tensor<4x128xf32>, with an intended DMA width of 128 bits\\n       (4 x f32), with subgroup size 32:\\n    ```mlir\\n    scf.forall (%arg6) in (32) ... {\\n        %2 = %arg6 * 4\\n        %thread_slice = ... : tensor<4x128xf32>\\n        %dest_slice = ... : tensor<4x128xf32>\\n        scf.forall.in_parallel {\\n          iree_gpu.coalesced_gather_dma %thread_slice into %dest_slice lane(%arg6) :  ...\\n        }\\n      } {mapping = [#gpu.lane_id<linear_dim_0>]}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<RankedTensorOrVectorOrMemRefOf<[ I32, Index ]>>\" },\n      { \"name\": \"init\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"lane\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyRankedTensorOrMemRef>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_bounds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<BoolAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$source (`[` $indices^ `]`)? `into` $init `lane` `(` $lane `)`\\n    (`in_bounds` $in_bounds^)?\\n    attr-dict `:` type(operands) ( `->` type($result)^ )?\"\n  },\n  {\n    \"name\": \"iree_gpu.global_load_dma\",\n    \"summary\": \"Does a global load DMA operation\",\n    \"description\": \"This operation represents a subgroup-level global load DMA operation.\\n    It is used to represent a direct gathering operation from global memory to workgroup.\\n    To be specific, the thread gathers data from the global memoryspace at the designated\\n    indices, and stores it to the thread's lane-offset of the workgroup memref at the\\n    designated indices.\\n\\n    Specifically, if the thread's subgroup lane id is `lane_id`, the thread will load the data\\n    from `$source[sourceIndices]` and store it to `$target[targetIndices] + lane_id`.\\n    Collectively, all threads in the subgroup orchestrate the load DMA operation.\\n\\n    Note: each gather has a load width is 32bit.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"sourceIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"target\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"targetIndices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"assemblyFormat\": \"$source`[` $sourceIndices `]` `->` $target `[` $targetIndices `]` attr-dict\\n      `:` type($source) `->` type($target)\"\n  },\n  {\n    \"name\": \"iree_gpu.global_subgroup_barrier\",\n    \"summary\": \"Synchronization-only barrier across all subgroups.\",\n    \"description\": \"All subgroups in the workgroup must reach any instance of this op before\\n    any can proceed past it. Unlike `gpu.barrier`, this op has no memory\\n    fence semantics - memory operations can be freely reordered with respect\\n    to it. Fences are handled separately.\\n\\n    This operation operates on a single, global workgroup-wide barrier object\\n    that can implement such dynamic join and must not be used if such a barrier\\n    isn't available.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"iree_gpu.value_barrier\",\n    \"summary\": \"Synchronizes workers on a value semantic tensor or vector.\",\n    \"description\": \"This operation acts as a barrier on a value semantic SSA values (tensor or\\n    vector). It takes multiple operands and produces a value equivalent to each\\n    input. This does not have copy and/or data movement semantics and simply\\n    represents a barrier on all writes in the tensor case, and a barrier until\\n    all threads acquire the input vector in the vector case.\\n\\n    The inputs must be either all tensors, or all vectors.\\n\\n    This operation is a no-op when not present in a parallel context. This\\n    operation is pure as it only requires synchronization for the value it\\n    produces.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensorOrVector>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensorOrVector>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['inputs', 'results']>\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` type($inputs)\"\n  },\n  {\n    \"name\": \"iree_gpu.yield\",\n    \"summary\": \"Yield values from a iree_gpu region.\",\n    \"description\": \"This operation is used to yield values from a within a region.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($values^ `:` type($values))?\"\n  },\n  {\n    \"name\": \"iree_linalg_ext.arg_compare\",\n    \"summary\": \"Performs an arg-reduction using a user-defined comparator.\",\n    \"description\": \"The `arg_compare` op performs a reduction over a given dimension of a tensor,\\n    returning both the selected value and its corresponding index. The selection\\n    logic is defined by a user-specified comparator region.\\n\\n    The operation supports three index modes for flexibility in tiling:\\n\\n    1. Implicit-index without index_base (single input, no index_base):\\n       Indices are computed from local position (linalg.index on reduction dimension).\\n       Used for untiled operations or when global offset is not needed.\\n\\n    2. Implicit-index with index_base (single input, with index_base):\\n       Indices are computed as: index_base + local position.\\n       Used in OuterParallel tiling where each parallel chunk has a fixed offset.\\n\\n    3. Explicit-index (two inputs: values + indices, no index_base):\\n       Indices are provided as input tensor alongside values.\\n       Used in OuterReduction tiling and merge operations where indices are\\n       accumulated across iterations.\\n\\n    The comparator region defines the sorting rule, e.g., \\\"greater than\\\" for argmax or\\n    \\\"less than\\\" for argmin, allowing for generalization beyond simple argmax-style\\n    behavior.\\n\\n    Example (implicit-index mode - argmax over dim 1):\\n    ```mlir\\n    %input = memref<2x10xf32>\\n    %out_val = memref<2xf32>\\n    %out_idx = memref<2xi32>\\n    iree_linalg_ext.arg_compare\\n      dimension(1)\\n      ins(%input : memref<2x10xf32>)\\n      outs(%out_val, %out_idx : memref<2xf32>, memref<2xi32>) {\\n    ^bb0(%a: f32, %b: f32):\\n      %cmp = arith.cmpf ogt, %a, %b : f32\\n      iree_linalg_ext.yield %cmp : i1\\n    }\\n    ```\\n\\n    Example (implicit-index mode with index_base = 5):\\n    ```mlir\\n    %input = memref<2x10xf32>\\n    %out_val = memref<2xf32>\\n    %out_idx = memref<2xi32>\\n    %base = arith.constant 5 : index\\n    iree_linalg_ext.arg_compare\\n      dimension(1)\\n      ins(%input : memref<2x10xf32>)\\n      outs(%out_val, %out_idx : memref<2xf32>, memref<2xi32>)\\n      index_base(%base : index) {\\n    ^bb0(%a: f32, %b: f32):\\n      %cmp = arith.cmpf ogt, %a, %b : f32\\n      iree_linalg_ext.yield %cmp : i1\\n    }\\n    ```\\n\\n    Example (explicit-index mode - combining partial results):\\n    ```mlir\\n    %partial_vals = memref<2x4xf32>\\n    %partial_idxs = memref<2x4xi32>\\n    %out_val = memref<2xf32>\\n    %out_idx = memref<2xi32>\\n    iree_linalg_ext.arg_compare\\n      dimension(1)\\n      ins(%partial_vals, %partial_idxs : memref<2x4xf32>, memref<2x4xi32>)\\n      outs(%out_val, %out_idx : memref<2xf32>, memref<2xi32>) {\\n    ^bb0(%a: f32, %b: f32):\\n      %cmp = arith.cmpf ogt, %a, %b : f32\\n      iree_linalg_ext.yield %cmp : i1\\n    }\\n    ```\\n\\n    The `index_base` is optional. When specified, it is added to the selected index\\n    in the result, which is useful when reducing over a tiled or sliced subregion.\",\n    \"operands\": [\n      { \"name\": \"input_value\", \"type\": \"AnyShaped\" },\n      { \"name\": \"input_index\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"output_value\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output_index\", \"type\": \"AnyShaped\" },\n      { \"name\": \"index_base\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    `ins` `(` $input_value (`,` $input_index^)? `:` type($input_value) (`,` type($input_index)^)? `)`\\n    `outs` `(` $output_value `,` $output_index `:` type($output_value) `,` type($output_index) `)`\\n    (`index_base` `(` $index_base^ `:` type($index_base) `)`)?\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.attention\",\n    \"summary\": \"Attention operator.\",\n    \"description\": \"Computes the scaled dot product attention function:\\n\\n    attention(Q, K, V, scale) = softmax(Q @ K.T * scale) @ V\\n\\n    Here Q, K, V are given tensors and scale is a scalar value specifying\\n    the scale to use.\\n\\n    If an additional mask argument M is included, the result of the first matmul is modified according to:\\n\\n    Q @ K.T += M\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyShaped\" },\n      { \"name\": \"key\", \"type\": \"AnyShaped\" },\n      { \"name\": \"value\", \"type\": \"AnyShaped\" },\n      { \"name\": \"scale\", \"type\": \"AnyFloat\" },\n      { \"name\": \"mask\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"decomposition_config\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `ins` `(` $query `,` $key `,` $value `,` $scale (`,` $mask^)?  `:` type($query) `,` type($key) `,` type($value) `,` type($scale) (`,` type($mask)^ )?`)`\\n    `outs` `(` $output `:` type($output) `)`\\n    $region\\n    (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.custom_op\",\n    \"summary\": \"Custom operation for compiling with IREE.\",\n    \"description\": \"This operation is meant to allow computation sequences that are fused at\\n    tile level prescriptively. This is to account for cases where such fusion\\n    cannot/is not yet discovered appropriately.\\n\\n    The operation implements all the interfaces needed to be able to\\n    1. Compile e2e using IREE\\n    2. Still be able to fuse with other operations that the compiler can\\n       figure out automatically.\\n\\n    Similar to how `LinalgOp`s represent a perfectly nested loop computation\\n    with\\n    - `indexing_maps` representing how the `ins`/`outs` are accessed\\n    - `region` representing the scalar computation performed\\n    - `iterator_types` representing the dependence along each iteration space\\n      dimension\\n    this operation represent a tiled computation with perfectly nested\\n    inter-tile loop nest.\\n    - `indexing_maps` represent what slices slices of the `ins`/`outs` are\\n      needed for each iteration of the tiled computation.\\n    - `region` represents the tiled computation performed using these slices\\n    - `iterator_types` represents the dependence between tiles along each\\n      iteration space.\\n\\n    Some modifications required to handle the tile-level semantics are\\n    - Some dimensions of operands might not be accessed by dimensions of the\\n      inter-tile iteration space. This means that along these dimensions the\\n      slice size matches the dimension size. This access pattern of operands\\n      is captured in the respective indexing map using a `symbol` to represent\\n      that the entire dimension needs to be sliced.\\n    - The basic block arguments of the region represent the slice of the\\n      operand. These are either scalar types (if the corresponding operand is a\\n      scalar), or a `tensor` type with dynamic shapes (if the corresponding\\n      operand is a `tensor` type).\\n\\n    For example, one could represent a prescriptively fused matmul computation\\n    as follows\\n\\n    ```\\n    %0:2 = iree_linalg_ext.custom_op {\\n        indexing_maps = [affine_map<(d0, d1)[s0, s1] -> (d0, s0)>,\\n                         affine_map<(d0, d1)[s0, s1] -> (s0, s1)>,\\n                         affine_map<(d0, d1)[s0, s1] -> (s1, d1)>,\\n                         affine_map<(d0, d1)[s0, s1] -> (d0, s1)>,\\n                         affine_map<(d0, d1)[s0, s1] -> (d0, d1)],\\n        iterator_types = [\\\"parallel\\\", \\\"parallel\\\"]}\\n        ins(%lhs1, %rhs1, %rhs2\\n            : tensor<1000000x?xf32>, tensor<?x?xf32>, tensor<?x?xf32>)\\n        outs(%outs1, %outs2 : tensor<1000000x?xf32>, tensor<1000000x?xf32>) {\\n      ^bb0(%t0 : tensor<?x?xf32>, %t1 : tensor<?x?xf32>, %t2 : tensor<?x?xf32>,\\n           %t3 : tensor<?x?xf32>, %t4 : tensor<?x?xf32>) :\\n        %0 = linalg.matmul ins(%t0, %t1 : tensor<?x?xf32>, tensor<?x?xf32>)\\n            outs(%t3 : tensor<?x?xf32>) -> tensor<?x?xf32>\\n        %1 = linalg.matmul ins(%0, %t2 : tensor<?x?xf32>, tensor<?x?xf32>)\\n            outs(%t4 : tensor<?x?xf32>) -> tensor<?x?xf32>\\n        iree_linalg_ext.yield %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>\\n    } -> tensor<1000000x?xf32>, tensor<x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensorOrScalarType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"iterator_types\", \"type\": \"TypedArrayAttrBase<IREELinalgExt_IteratorTypeEnum{parallel|reduction}>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`{` `indexing_maps` `=` $indexing_maps `,`\\n    `iterator_types` `=` $iterator_types `}`\\n    attr-dict-with-keyword\\n    (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    (`outs` `(` $outputs^ `:` type($outputs) `)`)?\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.exp_reduction\",\n    \"summary\": \"A linalg.generic extension with support for exponential reduction.\",\n    \"description\": \"This operation is a restricted form of a linalg.generic operation,\\n    representing a reduction over `e^{x}` where `x` is an input, and it is known\\n    that the function's result is independent of translation over x,\\n      i.e. f(x) = f(x + c).\\n\\n    Since `e{x}` grows exponentially for `x > 0`, if the values of `x` are\\n    unbounded, the intermediate computation for `e^{x}` in `f(x)`, may not fit\\n    in the floating point range, even if the result does. To prevent such\\n    numerical inaccuracies, we can instead compute `f(max(x) - x)`, which will\\n    ensure that `e{max(x) - x}` always fits in the range (0, 1], because\\n    0 < e{negative} <= 1.\\n\\n    These properties allow us to compute an online normalization of this\\n    function, in which we don't have to compute the `max(x)` as a separate\\n    reduction, but as a running max.\\n\\n    Generally, these properties are hard to infer from a linalg.generic, because\\n    two back-to-back reduction combiners in a linalg.generic can have hard to\\n    infer properties. This restricted form ensures we don't have to do\\n    complicated analysis to infer these properties.\\n\\n    The first input and output operands are intrinsically linked.\\n    - The first output operand is always the maximum of the first input operand,\\n      henceforth 'nmax'.\\n    - The first input operand in the basic block is always `2^{nmax-x}`, where\\n      `x` is the value\\n\\n    `norm` is calculated by `2^{nmax - pmax}`, where\\n    - `pmax` is the value from the previous iteration.\\n    - `nmax` is the new maximum, read from the current element from the input\\n      tensor\\n\\n    The other input operands are unaffected.\\n\\n    The operands listed in `exp_reduced_operands` will be multiplied by `norm`\\n    before executing the basic block. Other output operands are unaffected.\\n\\n    For example, we write the online normalized softmax algorithm as follows:\\n\\n    ```mlir\\n    // compute the exponentials and the sum\\n    %M, %O = iree_linalg_ext.exp_reduction {\\n      indexing_maps = [\\n        affine_map<(i) -> (i)>,\\n        affine_map<(i) -> ()>,\\n        affine_map<(i) -> ()>\\n      ],\\n      iterator_types = [\\n        #iree_linalg_ext.iterator_type<reduction>\\n      ],\\n      exp_reduced_operands = [ 1 ]  // 1 corresponds to %s being normalized by %m\\n    } ins(%V: tensor<256xf32>)\\n      outs(%M_init, %S: tensor<f32>, tensor<f32>) {\\n      ^bb0(%exp_v: f32, %m: f32, %s: f32):\\n        // take note of the operand names when comparing with the subsequent\\n        // code snippets\\n        %add = arith.addf %exp_v, %s : f32\\n        linalg.yield %m, %add        : f32, f32\\n    } -> tensor<f32>, tensor<f32>\\n  ```\\n\\n  This encodes the following computation, sans handling of the norms\\n\\n  ```\\n  %M, %O = linalg.generic {\\n      indexing_maps = [\\n        affine_map<(i) -> (i)>,\\n        affine_map<(i) -> ()>,\\n        affine_map<(i) -> ()>\\n      ],\\n  } ins(%V: tensor<256xf32>)\\n    outs(%M_init, %S: tensor<f32>, tensor<f32>) {\\n    ^bb0(%v: f32, %m: f32, %s: f32):\\n      %exp_v = math.exp2 %v       : f32\\n      %add = arith.addf %exp_v, %s : f32\\n      linalg.yield %m, %add       : f32, f32\\n  } -> tensor<f32>, tensor<f32>\\n  ```\\n\\n  And decomposes into operations equivalent to the following:\\n\\n  ```\\n  %M, %O = linalg.generic {\\n      indexing_maps = [\\n        affine_map<(i) -> (i)>,\\n        affine_map<(i) -> ()>,\\n        affine_map<(i) -> ()>\\n      ],\\n  } ins(%V: tensor<256xf32>)\\n    outs(%M_init, %S: tensor<f32>, tensor<f32>) {\\n    ^bb0(%v: f32, %prev_m: f32, %prev_s: f32):\\n      %m      = arith.maximumf %v, %prev_m : f32\\n      %m_diff = arith.subf %m, %prev_m     : f32\\n      %norm   = math.exp2 %m_diff          : f32\\n\\n      %exp_v  = math.exp2 %v               : f32  // raise v to the exponent\\n      %s      = arith.mulf %prev_s, %norm  : f32  // multiply s by the norm\\n      %add    = arith.addf %exp_v, %s      : f32\\n      linalg.yield %m, %add                : f32, f32\\n  } -> tensor<f32>, tensor<f32>\\n  ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"iterator_types\", \"type\": \"TypedArrayAttrBase<IREELinalgExt_IteratorTypeEnum{parallel|reduction}>\" },\n      { \"name\": \"exp_reduced_operands\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`{`\\n      `indexing_maps` `=` $indexing_maps `,`\\n      `iterator_types` `=` $iterator_types `,`\\n      `exp_reduced_operands` `=` $exp_reduced_operands\\n    `}`\\n    attr-dict\\n    `ins` `(` $inputs `:` type($inputs) `)`\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.fft\",\n    \"summary\": \"Fft operator.\",\n    \"description\": \"Apply 1D FFT to innermost dim. This is an iterative FFT, not recurrsive.\\n    Thus, the bit reversal is assumed applied on the input. The op carries an\\n    input -- stage, which indicates the level of reduction loop in the\\n    algorithm. It represents the computation body. For more details, see\\n    \\\"Data reordering, bit reversal, and in-place algorithms\\\" section in\\n    https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm\\n\\n    The size of innermost dim is expected to be a power of 2.\\n\\n    It is optional to carry coefficient tensors/buffers as inputs. In this\\n    context, they will be the second and third inputs.\",\n    \"operands\": [\n      { \"name\": \"stage\", \"type\": \"AnyType\" },\n      { \"name\": \"real_coeff\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"imag_coeff\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"real\", \"type\": \"AnyShaped\" },\n      { \"name\": \"imag\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `ins` `(` $stage (`,` $real_coeff^ `,` $imag_coeff)? `:` type($stage) (`,` type($real_coeff)^ `,` type($imag_coeff))? `)`\\n    `outs` `(` $real `,` $imag `:` type($real) `,` type($imag) `)`\\n    (`:` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.gather\",\n    \"summary\": \"Gathers slices from a source based on a tensor of indices.\",\n    \"description\": \"Takes two inputs (`source` and `indices`) and outputs value (`output`).\\n    The operation returns the value at the slices specified by `indices`.\\n\\n    The size of the `dimension_map` attribute is used to determine how many\\n    indices are used to index into `source`, i.e. `index_depth`. The\\n    `dimension_map` attribute describes which index value maps to which dimension\\n    in the destination.\\n\\n    This operation preforms the opposite operation of `iree_linalg_ext.scatter`.\\n    Instead of scattering `updates` into `original`, it gathers the values from\\n    `source` into `output` using the indices in `indices`. See the documentation\\n    on `iree_linalg_ext.scatter` for more details regarding the indexing/shape\\n    semantics.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_map\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `dimension_map` `=` $dimension_map\\n    `ins` `(` $source `,` $indices `:` type($source) `,` type($indices) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.im2col\",\n    \"summary\": \"Im2col operation for convolutions.\",\n    \"description\": \"Transforms a convolution input tensor into a GEMM-compatible layout. Each\\n    output position `(batch, m, k)` maps to a specific input element determined\\n    by the convolution metadata (strides, dilations, kernel_size).\\n\\n    #### Attributes\\n\\n    **Convolution metadata** — derived from the original convolution:\\n    - `strides`: spatial stride per m_pos dimension.\\n    - `dilations`: dilation factor per m_pos dimension.\\n    - `kernel_size`: filter kernel extent per m_pos dimension.\\n\\n    **Dimension mapping** — describes which input dimensions are batch, spatial\\n    (M), or reduction (K):\\n    - `batch_pos`: input dimensions that are batch (pass-through to output).\\n    - `m_pos`: input dimensions that are spatial (indexed by stride/dilation).\\n    - `k_pos`: input dimensions that are channels (direct index).\\n\\n    **Indexing**:\\n    - `offsets`: one offset per output dimension in canonical\\n      `[Batch..., M..., K...]` order. Updated by tiling to reflect the tile\\n      position; `output_sizes` remain unchanged.\\n    - `output_sizes`: nested list of delinearization sizes per output dimension.\\n      Each entry describes how to delinearize that output dimension back to\\n      spatial/channel coordinates. For example:\\n      `output_sizes = [[2], [32, 32], [3, 3, 640]]` means batch=[2],\\n      M delinearizes into [OH=32, OW=32], K delinearizes into [KH=3, KW=3, C=640].\\n\\n    **Layout permutations**:\\n    - `input_k_perm`: permutation that maps the delinearized K output dimension\\n      coordinates (window offsets from spatial dims and channel indices) to their\\n      corresponding input dimension positions. Used when\\n      the filter layout differs from the input layout (e.g., input=HWC,\\n      filter=CHW requires `input_k_perm = [2, 0, 1]`). The identity permutation\\n      means the layouts are already aligned.\\n    - `output_perm`: permutation of the canonical `[Batch, M, K]` order to the\\n      actual output tensor layout. For example, `output_perm = [2, 0, 1]` means\\n      the result is in `KxBxM` layout.\\n\\n    #### Semantics\\n\\n    For each output position `(b, m, k)`, the op computes input coordinates,\\n    where `i` indexes over `m_pos` dimensions (spatial) and `j` indexes over\\n    `k_pos` dimensions (channel):\\n    ```\\n      spatial_coord[i] = m_coord[i] * stride[i] + window_offset[i] * dilation[i]\\n      channel_coord[j] = k_coord[j]\\n    ```\\n    where `m_coord` and `window_offset`/`k_coord` come from delinearizing the\\n    M and K output indices using `output_sizes`.\\n\\n    #### Examples\\n\\n    Basic im2col (NHWC conv, 3x3 kernel):\\n    ```mlir\\n      %im2col = iree_linalg_ext.im2col\\n          strides = [1, 1] dilations = [1, 1] kernel_size = [3, 3]\\n          offsets = [0, 0, 0]\\n          output_sizes = [[2], [32, 32], [3, 3, 640]]\\n          batch_pos = [0] m_pos = [1, 2] k_pos = [3]\\n          input_k_perm = [0, 1, 2] output_perm = [0, 1, 2]\\n          ins(%in : tensor<2x34x34x640xf32>)\\n          outs(%out : tensor<2x1024x5760xf32>) -> tensor<2x1024x5760xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" },\n      { \"name\": \"kernel_size\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"output_sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_kernel_size\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_output_sizes\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"batch_pos\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"m_pos\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"k_pos\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"input_k_perm\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"output_perm\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `strides` `=` $strides\\n    `dilations` `=` $dilations\\n    `kernel_size` `=`\\n    custom<DynamicIndexList>($kernel_size, $static_kernel_size)\\n    `offsets` `=`\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    `output_sizes` `=`\\n    custom<NestedDynamicIndexList>($output_sizes, $static_output_sizes)\\n    `batch_pos` `=` $batch_pos\\n    `m_pos` `=` $m_pos\\n    `k_pos` `=` $k_pos\\n    `input_k_perm` `=` $input_k_perm\\n    `output_perm` `=` $output_perm\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.index\",\n    \"summary\": \"LinalgExt index operation.\",\n    \"description\": \"This operation is a mirror of `linalg.index` operation and has the same\\n    semantics, except that `linalg.index` enforces that the parent op is a\\n    `LinalgOp`, and the `iree_linalg_ext.index` operation enforces that the\\n    parent op is one of `IREE::LinalgExt::CustomOp` or `IREE::LinalgExt::AttentionOp`.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" }\n    ],\n    \"assemblyFormat\": \"$dim attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"iree_linalg_ext.map_gather\",\n    \"summary\": \"Gather with a mapping from result indices to source indices.\",\n    \"description\": \"Takes two operands, `source` and `output`, and reads every element from\\n    the `source` based on a computed index mapping to store into the `output`.\\n    If the operands are tensors, the op will also return a Value for the result.\\n    For an element of the `output`, the index to read from the `source` is\\n    determined by index computation mapping the index in the `output` value to\\n    an index in the `source` value. This computation is contained in the\\n    `transformation_region`, which contains a single block, with one argument\\n    for each dimension in the `output` value. The block arguments represent the\\n    index of a given element along the corresponding dimension (i.e., block arg\\n    `i` represents the index along dimension `i` of the `output` value). The\\n    block is terminated by an iree_linalg_ext.yield op, which yields one index\\n    for each dimension in the `source`, and an additional padding value which\\n    represents the value to use if the computed source indices are out of bounds.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"transformation_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `into` $output\\n    $transformation_region\\n    `:` type($source) `into` type($output) (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.map_load\",\n    \"summary\": \"Load with a mapping from result indices to source indices.\",\n    \"description\": \"Takes two operands, `source` and `output`, and reads every element from\\n    the `source` based on a computed index mapping to store into the `output`.\\n    If the operands are tensors, the op will also return a Value for the result.\\n    For an element of the `output`, the index to read from the `source` is\\n    determined by index computation mapping the index in the `output` value to\\n    an index in the `source` value. This computation is contained in the\\n    `transformation_region`, which contains a single block, with one argument\\n    for each dimension in the `output` value. The block arguments represent the\\n    index of a given element along the corresponding dimension (i.e., block arg\\n    `i` represents the index along dimension `i` of the `output` value). The\\n    block is terminated by an iree_linalg_ext.yield op, which yields one index\\n    for each dimension in the `source`, and an additional padding value which\\n    represents the value to use if the computed source indices are out of bounds.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"transformation_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `into` $output\\n    $transformation_region\\n    `:` type($source) `into` type($output) (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.map_scatter\",\n    \"summary\": \"Scatter with a mapping from source indices to result indices.\",\n    \"description\": \"Takes two operands, `input` and `output`, and stores every element of\\n    `input` to a unique location in `output`. If the operands are tensors, the\\n    op will also return a Value for the result. For an element of the `input`,\\n    the index to store into the `output` is determined by index computation\\n    mapping the index in the `input` value to an index in the `output` value.\\n    This computation is contained in the `transformation_region`, which contains\\n    a single block, with one argument for each dimension in the `input` value.\\n    The block arguments represent the index of a given element along the\\n    corresponding dimension (i.e., block arg `i` represents the index along\\n    dimension `i` of the `input` value). The block is terminated by an\\n    iree_linalg_ext.yield op, which yields one index for each dimension in\\n    the `output`, and an additional `i1` Value, which represents a mask on\\n    whether or not to write to the `output` at the yielded set of indices. If\\n    the mask value is true, the input value will be written.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"transformation_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `into` $output\\n    $transformation_region\\n    `:` type($input) `into` type($output) (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.map_store\",\n    \"summary\": \"Store with a mapping from source indices to result indices.\",\n    \"description\": \"Takes two operands, `input` and `output`, and stores every element of\\n    `input` to a unique location in `output`. If the operands are tensors, the\\n    op will also return a Value for the result. For an element of the `input`,\\n    the index to store into the `output` is determined by index computation\\n    mapping the index in the `input` value to an index in the `output` value.\\n    This computation is contained in the `transformation_region`, which contains\\n    a single block, with one argument for each dimension in the `input` value.\\n    The block arguments represent the index of a given element along the\\n    corresponding dimension (i.e., block arg `i` represents the index along\\n    dimension `i` of the `input` value). The block is terminated by an\\n    iree_linalg_ext.yield op, which yields one index for each dimension in\\n    the `output`, and an additional `i1` Value, which represents a mask on\\n    whether or not to write to the `output` at the yielded set of indices. If\\n    the mask value is true, the input value will be written.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"transformation_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `into` $output\\n    $transformation_region\\n    `:` type($input) `into` type($output) (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.online_attention\",\n    \"summary\": \"Online Attention operator.\",\n    \"description\": \"Traditional scaled dot product attention computes:\\n\\n    attention(Q, K, V, scale) = softmax(Q @ K.T * scale) @ V\\n\\n    Online Attention on the other hand, uses an online normalizer instead of\\n    softmax:\\n\\n    online_attention(Q, K, V, scale, running_max, running_sum)\\n      = online_normalizer(Q @ K.T * scale, running_max, running_sum) @ V\\n\\n    If an additional mask argument M is included, the result of the first matmul is modified according to:\\n\\n    Q @ K.T += M\\n\\n    The advantage of this online_normalizer is that it can be tiled along\\n    its reduction dimension, making the online_attention operator:\\n      - Tilable along softmax reduction dimension\\n      - Associative along softmax reduction dimension\\n      - Commutative along softmax associative dimension\\n\\n    Note: The results of online_attention need to be combined after computing\\n    it over the entire softmax reduction dimension by:\\n      x, _, sum : results\\n      x = (1 / sum) * x\\n\\n    Decomposition Configuration:\\n    The `decomposition_config` attribute is a DictionaryAttr that controls how\\n    this operation is decomposed into lower-level operations. It supports:\\n      - \\\"qk_attrs\\\": DictionaryAttr - Attributes to attach to the Q@K matmul\\n        operation after decomposition (e.g., lowering_config, attention markers)\\n      - \\\"pv_attrs\\\": DictionaryAttr - Attributes to attach to the P@V matmul\\n        operation after decomposition\\n      - \\\"use_exp2\\\": BoolAttr - If true, uses exp2 with log2(e) scaling instead\\n        of exp. (Gives better perf on some hardware, but trades off accuracy)\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyShaped\" },\n      { \"name\": \"key\", \"type\": \"AnyShaped\" },\n      { \"name\": \"value\", \"type\": \"AnyShaped\" },\n      { \"name\": \"scale\", \"type\": \"AnyFloat\" },\n      { \"name\": \"mask\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" },\n      { \"name\": \"max\", \"type\": \"AnyShaped\" },\n      { \"name\": \"sum\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"decomposition_config\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `ins` `(` $query `,` $key `,` $value `,` $scale (`,` $mask^)?  `:` type($query) `,` type($key) `,` type($value) `,` type($scale) (`,` type($mask)^ )?`)`\\n    `outs` `(` $output `,` $max `,` $sum `:` type($output) `,` type($max) `,` type($sum) `)`\\n    $region\\n    (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.pack\",\n    \"summary\": \"LinalgExt pack operation for both tensors and buffers.\",\n    \"description\": \"The pack operation converts an `input` into a tiled and packed layout. The\\n    dimensions to be tiled are obtained from `inner_dims_pos` and the size of the\\n    tile is obtained from `inner_tiles`. The dimensions listed in `inner_dims_pos`\\n    do not need to be contiguous in which case the tile will get transposed.  We\\n    handle only full tiles if `padding_value` is not set; it is UB if the tile does\\n    not perfectly divide the dimension. If `padding_value` is set, it will pad\\n    along high dimensions, i.e., it pads at the bottom and on the right if the\\n    input has rank 2, and the result type shape, will be dynamic in any dimension\\n    if and only if the input shape is. As optional input, the operation takes\\n    `outer_dims_perm` that allows to permute the tiled loops.\\n\\n    Example KC_to_KCck:\\n\\n    ```mlir\\n    iree_linalg_ext.pack %arg0 inner_dims_pos = [1, 0]\\n      inner_tiles = [32, 8] into %arg1 : (memref<128x256xf32> memref<16x8x32x8xf32>)\\n    ```\\n\\n    Example NC_to_NCnc:\\n\\n    ```mlir\\n    iree_linalg_ext.pack %arg0 inner_dims_pos = [0, 1]\\n      inner_tiles = [8, 32] into %arg1 : (memref<128x256xf32> memref<16x8x8x32xf32>)\\n    ```\\n    Example KC_to_CKkc\\n\\n    ```mlir\\n    iree_linalg_ext.pack %arg0 outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]\\n      inner_tiles = [32, 8] into %arg1 : (memref<128x256xf32> memref<32x4x32x8xf32>)\\n    ```\\n\\n    In all cases, dimension at position 0 in the input memref (128) is tiled\\n    with a factor of 8, while dimension at position 1 (256) is tiled with a factor\\n    of 32. In the KC_to_KCck example, the point loops are interchanged, while in the\\n    KC_to_CKkc example the tiled loops.\\n\\n    Example NC_to_NCnc with padding:\\n\\n    ```mlir\\n    iree_linalg_ext.pack %arg padding_value(%pad : f32) inner_dims_pos = [0, 1]\\n      inner_tiles = [8, 2] into %arg1 : (memref<13x15xf32> memref<2x8x8x2xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" },\n      { \"name\": \"inner_tiles\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"padding_value\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outer_dims_perm\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"inner_dims_pos\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_inner_tiles\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    $input\\n    (`padding_value` `(` $padding_value^ `:` type($padding_value) `)`)?\\n    (`outer_dims_perm` `=` $outer_dims_perm^)?\\n    `inner_dims_pos` `=` $inner_dims_pos\\n    `inner_tiles` `=`\\n    custom<DynamicIndexList>($inner_tiles, $static_inner_tiles)\\n    `into` $output `:` `(` type($input) type($output) `)`\\n     (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.scan\",\n    \"summary\": \"Scan operator.\",\n    \"description\": \"Computes the inclusive/exclusive scan along a given dimension.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" },\n      { \"name\": \"accumulator\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"inclusive\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    `inclusive` `(` $inclusive `)`\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `,` $accumulator `:` type($output) `,` type($accumulator) `)`\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.scatter\",\n    \"summary\": \"Scatters an input in slices based on a tensor of indices.\",\n    \"description\": \"Takes two `inputs` (`update` and `indices`) and `outputs` value (`original`).\\n    The operation updates the value at the slices specified by `indices` by\\n    combining the current value with the value in `updates` using the computation\\n    specified in `region`. The `region` specifies a binary operation\\n    of signature `(T, T) -> T`, where `T` is the element-type of\\n    `updates` (and `original`). The first argument is from `updates`,\\n    and the second is from `original`.\\n\\n    The size of the `dimension_map` attribute is used to determine how many\\n    indices are used to index into `original`, i.e. `index_depth`. The\\n    `dimension_map` attribute describes which index value maps to which dimension\\n    in the destination.\\n\\n    The operand `indices` is a N-D tensor/memref type that is composed\\n    of two logical parts. The first `N-1` dimensions represent the batch of\\n    updates. The last dim (at index `N-1`) is the `index_depth`, which can be\\n    omitted if `index_depth` is 1.\\n\\n    The operand `update` is a M-D tensor/memref type and similarly\\n    consists of two parts. The first `N-1` dimensions represent the batch of\\n    updates. This must exactly match to the first `N-1` dimensions in `indices`.\\n    Dimensions `N..M-1` represent the slice scattered into `original`,\\n    `update_slice`, and must match the last dimensions in original. This\\n    represents a contiguous slice to be inserted into `original`.\\n\\n    The operand `original` is a DPS init representing the destination that\\n    `update` gets scattered to.\\n    Where `rank(original) = rank(update_slice) + index_depth`\\n\\n    The unique_indices attribute carries the information whether all the\\n    indices are unique. If `unique_indices` is `true` and two or more updates\\n    scatter to the same location in `original` the final value in `original` is\\n    not guaranteed. If `unique_indices` is set to false, the first\\n    `batch_rank` iteration loops will be marked as reduction.\\n\\n    The shapes definition follows tensorflow operations. See more information in\\n      https://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_update\",\n    \"operands\": [\n      { \"name\": \"updates\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"original\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_map\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"unique_indices\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `dimension_map` `=` $dimension_map\\n              `unique_indices` `(` $unique_indices `)`\\n    `ins` `(` $updates `,` $indices `:` type($updates) `,` type($indices) `)`\\n    `outs` `(` $original `:` type($original) `)`\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.sort\",\n    \"summary\": \"Sorts a tensor a specified dimension.\",\n    \"description\": \"Based on XLA operation semantics, sorts the given `operands` at the given\\n    `dimension` with the given `comparator`.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#sort.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.topk\",\n    \"summary\": \"Top-K operator.\",\n    \"description\": \"A Top-K operation for N-D tensors. Reduces the target dimension from the input\\n   size N down to K elements based on the supplied binary region.\\n\\n   Accepts an N-D tensor input consisting of values and an optional N-D tensor\\n   for indices of those values (i32 type). If input indices aren't provided, the\\n   index mapping is inferred based on the k dim.  Both input values/indices\\n   tensors and output values/indices tensors must have the same shape. Top-K is\\n   computed along the target dimension (from dimension()). Returns two output\\n   tensors of values and the indices of Top-K results. The output dimensions\\n   must match the input save for the dimension that is reduced to K results.\\n\\n   Region accepts lhs=[next N input] and rhs=[exiting K output] and yields an\\n   i1. If true, the two values are swapped:\\n     - For Top-K compoarision: >\\n     - For Min-K comparison: <\\n   Note: when the two values are equal, the first occurrence is always selected.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"AnyShaped\" },\n      { \"name\": \"indices\", \"type\": \"Optional<AnyShaped>\" },\n      { \"name\": \"output_values\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output_indices\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    `ins` `(` $values (`,` $indices^)? `:` type($values) (`,` type($indices)^)? `)`\\n    `outs` `(` $output_values `,` $output_indices `:` type($output_values) `,` type($output_indices) `)`\\n    $region (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.unpack\",\n    \"summary\": \"LinalgExt unpack operation for both tensors and buffers.\",\n    \"description\": \"The unpack operation converts a tiled and packed input to an unpacked\\n    output. See `pack` for more details on `inner_tiles` and `dims_pos`; it is UB\\n    if the tile does not perfectly divide the dimension. Optionally, the operation\\n    also supports permuting the tiled loops.\\n\\n    Example KCck_to_KC:\\n\\n    ```mlir\\n    iree_linalg_ext.unpack %arg0 dims_pos = [1, 0]\\n      inner_tiles = [32, 8] into %arg1 : (memref<16x8x32x8xf32> memref<128x256xf32>)\\n    ```\\n\\n    Example NCnc_to_NC:\\n\\n    ```mlir\\n    iree_linalg_ext.unpack %arg0 dims_pos = [0, 1]\\n      inner_tiles = [8, 32] into %arg1 : (memref<16x8x8x32xf32> memref<128x256xf32>)\\n    ```\\n\\n    Example CKkc_to_KC:\\n\\n    ```mlir\\n    iree_linalg_ext.unpack %arg1 outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]\\n      inner_tiles = [32, 8] into %arg0 : (memref<32x4x32x8xf32> memref<128x256xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" },\n      { \"name\": \"inner_tiles\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outer_dims_perm\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"inner_dims_pos\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_inner_tiles\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    $input\\n    (`outer_dims_perm` `=` $outer_dims_perm^)?\\n    `inner_dims_pos` `=` $inner_dims_pos\\n    `inner_tiles` `=`\\n    custom<DynamicIndexList>($inner_tiles, $static_inner_tiles)\\n    `into` $output `:` `(` type($input) type($output) `)`\\n     (`->` type($results)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.winograd.filter_transform\",\n    \"summary\": \"Winograd Filter Transform operator.\",\n    \"description\": \"This operator is part of the first step in converting a convolution to\\n    its Winograd equivalent. Given a tile of a convolution filter (F),\\n    this operator computes matmul(G, matmul(F, transpose(B))).\\n    The filter tile is assumed to be the full m x m convolutional kernel,\\n    and the result of the transformation on this tile is a square with each\\n    side of size m + r - 1, where the output tile size is r x r. G is a constant\\n    2-d matrix of shape (m + r - 1) x m. The input to the operator is a filter\\n    of shape (H, W, C, F) or (F, C, H, W) and the output is an operator of shape\\n    (m + r - 1, m + r - 1, C, F). The result of this operator is first collapsed\\n    and then fed to a batch matmul op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_tile_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"kernel_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `output_tile_size` `(` $output_tile_size `)`\\n    `kernel_size` `(` $kernel_size `)`\\n    `kernel_dimensions` `(` $kernel_dimensions `)`\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    (`->` type($result)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.winograd.input_transform\",\n    \"summary\": \"Winograd Input Transform operator.\",\n    \"description\": \"This operator is part of the first step in converting a convolution to\\n    its Winograd equivalent. Given a tile of an input image (I),\\n    this operator computes matmul(transpose(B), matmul(I, B)).\\n    The input tile is assumed to be square with each side of size m + r - 1,\\n    where the convolutional kernel is m x m and the output tile size is r x r.\\n    B is a constant 2-d square matrix of the same shape as the input tile I.\\n    The input to the operator is an image of shape (N, H, W, C) or (N, C, H, W)\\n    and the output is an operator of shape (m + r - 1, m + r - 1, N, H', W', C)\\n    where H' = ceil((H - m + 1)/r) and W' = ceil((W - m + 1)/r). The result\\n    of this operator is first collapsed and then fed to a batch matmul op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_tile_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"image_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `output_tile_size` `(` $output_tile_size `)`\\n    `kernel_size` `(` $kernel_size `)`\\n    `image_dimensions` `(` $image_dimensions `)`\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    (`->` type($result)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.winograd.output_transform\",\n    \"summary\": \"Winograd Output Transform operator.\",\n    \"description\": \"This operator is the last transform in converting a convolution to\\n    its Winograd equivalent. After convolution in the Winograd domain\\n    (which turns into an elementwise product for a single channel and\\n    batch matrix multiplication for many channels), this operator converts\\n    the output back into the original domain. Given a tile of the\\n    output (O) in the Winograd domain, this operator computes\\n    matmul(transpose(A), matmul(O, A)). The output tile is square with\\n    each side of size m + r - 1, where the convolutional kernel is m x m\\n    and the output tile size is r x r. A is a constant 2-d matrix of\\n    shape (m + r - 1) x r. The input to the operator is a tensor of\\n    shape (m + r - 1, m + r - 1, N, H', W', C) and the output is a\\n    tensor of shape (N, H, W, C) or (N, C, H, W) where H = r H' and W = r W'.\\n    This operator is followed by a tensor.extract_slice which extracts\\n    only the non-padded part of the output.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_tile_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"image_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `output_tile_size` `(` $output_tile_size `)`\\n    `kernel_size` `(` $kernel_size `)`\\n    `image_dimensions` `(` $image_dimensions `)`\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    (`->` type($result)^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_linalg_ext.yield\",\n    \"summary\": \"LinalgExt yield op.\",\n    \"description\": \"`iree_linalg_ext.yield` is a special terminator operation for blocks inside\\n    regions in `iree_linalg_ext` ops.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"iree_tensor_ext.barrier.end\",\n    \"summary\": \"Tensor barrier end operation\",\n    \"description\": \"This barrier prevents certain transformations (like reshape propagation)\\n    from moving operations up across this boundary.\\n    The operand is returned as the result with identical type.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value_dims\", \"type\": \"IREETensorExt_ShapeDynamicDims\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) (`{` $value_dims^ `}`)? `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"iree_tensor_ext.barrier.start\",\n    \"summary\": \"Tensor barrier start operation\",\n    \"description\": \"This barrier prevents certain transformations (like reshape propagation)\\n    from moving operations down across this boundary.\\n    The operand is returned as the result with identical type.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value_dims\", \"type\": \"IREETensorExt_ShapeDynamicDims\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) (`{` $value_dims^ `}`)? `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"iree_tensor_ext.bitcast\",\n    \"summary\": \"Bitcasts a tensor without modifying the contents.\",\n    \"description\": \"Bitcasts a tensor |source| to the shape implied by this operations result\\n    type interleaved with |result_dims|, potentially with a different element\\n    type. For example,\\n\\n    ```\\n    result_dims = {%0, %1}\\n    result_type = tensor<1x?x2x?x3 x!eltype>\\n    ```\\n\\n    produces a tensor of shape [1, %0, 2, %1, 3] and element type `!eltype`.\\n    Note that the source and result tensors must serialized to the same size.\\n\\n    Different from the flow.bitcast op, the op is allowed to be cloned into\\n    dispatch regions and supports transformations required by executable\\n    translation such as bufferization.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<IREETensorExt_Dim>\" },\n      { \"name\": \"result_dims\", \"type\": \"Variadic<IREETensorExt_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `:`\\n    type($source) (`{` $source_dims^ `}`)? `->`\\n    type($result) (`{` $result_dims^ `}`)?\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.cast_to_ragged_shape\",\n    \"summary\": \"Create a shaped type with ragged rows.\",\n    \"description\": \"The op takes a shaped type and reinterprets its contents as a ragged shaped type. The\\n    dimensions specified by `ragged_dim` in the source is interpreted as two\\n    dimensions at `ragged_dim` and `ragged_dim + 1` in the result shaped type. The\\n    result shaped type has a rank of one more than that of the `source`. The result\\n    type also has the encoding set to an attribute of type `RaggedShapeAttr`\\n    with the specified `ragged_dim` used to specify the `raggedRow` in the\\n    encoding attribute. (See description of `RaggedShapeAttr`). The number of\\n    ragged rows is specified using `num_ragged_rows` argument. The size of each\\n    row is specified using `column_lengths` argument, which is a single rank\\n    shaped type of size `num_rows + 1` and where size of the `i`-th row of the result\\n    is computed using\\n\\n    ```\\n    column_lengths[i+1] - column_lengths[i]\\n    ```\\n\\n    In other words, `column_lengths` is same as the `ROW_INDEX` in CSR\\n    representation (https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_(CSR,_CRS_or_Yale_format)).\\n    An optional argument `max_ragged_column_length` allows specifying the dynamic\\n    upper bound for the number of columns (for static upper bounds the shape of the\\n    dimension in the result shaped type encodes this value)\\n\\n    For example, if the `n` and `n+1` dimensions of the result represent this ragged structure\\n\\n    ```\\n    OOOO\\n    OOOOOO\\n    OOO\\n    OOOOO\\n    ```\\n\\n    then,\\n    - `ragged_dim` is `n`\\n    - `num_ragged_rows` is 4\\n    - `column_lengths` is [0, 4, 10, 13, 18]\\n    - result has an encoding attribute of `#iree_tensor_ext.ragged_shape<n>`.\\n\\n    Constraints are\\n    1. `ragged_dim` < rank(`source`)\\n    2. rank(`columnLengths`) == 1.\\n    3. dim(`columnLengths`, 0) == `num_rows` + 1.\\n    4. dim(`result`, `raggedRowDim` + 1) >=\\n        (`columnLengths`[k+1] - `columnLengths`[k])\\n        for all 0 <= k < dim(`result`, `raggedRowDim`)\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[AnyRankedTensor, AnyMemRef]>\" },\n      { \"name\": \"columnLengths\", \"type\": \"AnyTypeOf<[AnyRankedTensor, AnyMemRef]>\" },\n      { \"name\": \"numRaggedRows\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"avgRaggedColumnLength\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"sourceDynamicDims\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyRankedTensor, AnyMemRef]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"raggedDim\", \"type\": \"IndexAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `ragged_dim` `(` $raggedDim `)`\\n    `column_lengths` `(` $columnLengths `)`\\n    (`num_ragged_rows` `(` $numRaggedRows^ `)`)?\\n    (`avg_ragged_column_length` `(` $avgRaggedColumnLength^ `)`)?\\n    attr-dict `:`\\n    `(` type($source) (`{` $sourceDynamicDims^ `}`)? `,` type($columnLengths) `)`\\n    `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.compute_barrier.end\",\n    \"summary\": \"Tensor compute barrier end operation\",\n    \"description\": \"This barrier prevents certain transformations (like reshape propagation)\\n    from moving operations up across this boundary.\\n    The operand is returned as the result with identical type.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value_dims\", \"type\": \"Variadic<IREETensorExt_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) (`{` $value_dims^ `}`)? `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.compute_barrier.start\",\n    \"summary\": \"Tensor compute barrier start operation\",\n    \"description\": \"This barrier prevents certain transformations (like reshape propagation)\\n    from moving operations down across this boundary.\\n    The operand is returned as the result with identical type.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value_dims\", \"type\": \"Variadic<IREETensorExt_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) (`{` $value_dims^ `}`)? `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.dispatch.tensor.load\",\n    \"summary\": \"Loads a tensor from a dispatch input placeholder.\",\n    \"description\": \"Loads an input tensor or subtensor from an input placeholder. As each\\n    workgroup executes concurrently all workgroups will receive identical loaded\\n    results of regions that may overlap.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"IREETensorExt_DispatchTensor\" },\n      { \"name\": \"source_dims\", \"type\": \"Variadic<IREETensorExt_Dim>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source\\n    `,` `offsets` `=` custom<DynamicIndexList>(\\n      $offsets, $static_offsets)\\n    `,` `sizes` `=` custom<DynamicIndexList>(\\n      $sizes, $static_sizes)\\n    `,` `strides` `=` custom<DynamicIndexList>(\\n      $strides, $static_strides)\\n    attr-dict `:` type($source) (`{` $source_dims^ `}`)?  `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.dispatch.tensor.store\",\n    \"summary\": \"Stores a tensor into a dispatch output placeholder.\",\n    \"description\": \"Stores a tensor or subtensor into an output tensor placeholder. As each\\n    workgroup executes concurrently behavior is undefined if more than one\\n    workgroup stores into overlapping regions of the full output tensor.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"target\", \"type\": \"IREETensorExt_WritableDispatchTensor\" },\n      { \"name\": \"target_dims\", \"type\": \"Variadic<IREETensorExt_Dim>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target\\n    `,` `offsets` `=` custom<DynamicIndexList>(\\n      $offsets, $static_offsets)\\n    `,` `sizes` `=` custom<DynamicIndexList>(\\n      $sizes, $static_sizes)\\n    `,` `strides` `=` custom<DynamicIndexList>(\\n      $strides, $static_strides)\\n    attr-dict `:` type($value) `->` type($target) (`{` $target_dims^ `}`)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.dispatch.workgroup_count_from_dag_root\",\n    \"summary\": \"Workgroup count computed based on iteration range of the root of the DAG\\n    for ops within the dispatch.\",\n    \"description\": \"When using tile + distribution of the root of the DAG (Directed Acyclic\\n    Graph) of ops within the dispatch to split the work amongst workgroups. The\\n    workload captured is the size of the iteration space of the root of the DAG.\\n    This op represents the computation that given the workload returns the\\n    number of workgroups to use. The backends are responsible for lowering this\\n    op into actual computation (typically based on the tile sizes used to tile\\n    and distribute the root of the DAG).\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"x\", \"type\": \"Index\" },\n      { \"name\": \"y\", \"type\": \"Index\" },\n      { \"name\": \"z\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `(` $operands `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.dispatch.workgroup_count_from_slice\",\n    \"summary\": \"Place holder to signify default workgroup count calculation.\",\n    \"description\": \"The default computation of the number of workgroups (or workgroup count)\\n    assumes that the dispatch + captured values is enough to compute the\\n    workgroup count. It does so by using a program slice of the values\\n    within the dispatch that represent the number of workgroups when available\\n    within the dispatch.\\n    Currently the arguments of index types captured by the\\n    `flow.dispatch.workgroups` is treated as the workload for the operation.\\n    It is a requirement that the slice of the program that computes the\\n    number of workgroups will need to have its leaves be these captured values.\\n\\n    TODO: This could be generalized in future to allow the slices to encompass\\n    arbitrary computation. The computation of the workgroup count can then be\\n    done on the device itself, if this is data dependent. In such cases the\\n    workload could be more than just values of index types.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"x\", \"type\": \"Index\" },\n      { \"name\": \"y\", \"type\": \"Index\" },\n      { \"name\": \"z\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `(` $operands `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.dispatch.workgroup_count_split_reduction_modifier\",\n    \"summary\": \"Modifies the workgroup count calculation to account for split reductions.\",\n    \"description\": \"A split reduction dispatch contains an `scf.forall` within which the\\n    partial reduction computation is done. The `scf.forall` represents parallel\\n    partial reduction computations. `workgroup_x`, `workgroup_y`, and\\n    `workgroup_z` represent the workgroups needed to execute the inner compute\\n    ops. This is combined with `workload` to determine the total number of\\n    workgroups required to run the computation after accounting for the\\n    `scf.forall`.\",\n    \"operands\": [\n      { \"name\": \"workgroup_x\", \"type\": \"Index\" },\n      { \"name\": \"workgroup_y\", \"type\": \"Index\" },\n      { \"name\": \"workgroup_z\", \"type\": \"Index\" },\n      { \"name\": \"workload\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_x\", \"type\": \"Index\" },\n      { \"name\": \"result_y\", \"type\": \"Index\" },\n      { \"name\": \"result_z\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `workgroups` `(` $workgroup_x `,` $workgroup_y `,` $workgroup_z `)` `workload` `(` $workload `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_tensor_ext.dispatch.workload.ordinal\",\n    \"summary\": \"Annotates the values captured as workload within the body of\\n    `flow.dispatch.workgroups` op.\",\n    \"description\": \"The arguments that represent the captured/returned values of the\\n    `flow.dispatch.workgroups`, i.e. the signature of the body of the op is not\\n    preserved during IREEs compilation. Since the workloads are derived from\\n    the operands captured by the operation, this op denotes the values captured\\n    as workloads. This can be used in the backends to map back to the workload\\n    values while materializing the workgroup count computation.\\n\\n    TODO: Find a better way to represent this information, either by somehow\\n    propagating the signature of the created dispatch workgroup op through\\n    the compilation stack until the codegen backends, or as a separate\\n    list/attribute that can be plumbed through without using explicit ops.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ordinal\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `,` $ordinal `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"iree_vector_ext.arg_compare\",\n    \"summary\": \"Vectorized arg-reduction using a user-defined comparator.\",\n    \"description\": \"The `iree_vector_ext.arg_compare` op is the vectorized form of\\n    `iree_linalg_ext.arg_compare`. It performs a reduction over a given\\n    dimension of a vector, returning both the selected value and its\\n    corresponding index.\\n\\n    **Comparator region semantics:**\\n\\n    The comparator region defines the predication logic that determines the\\n    selection rule for the reduction (e.g., \\\"greater than\\\" for argmax or\\n    \\\"less than\\\" for argmin). The region takes two scalar values of the input\\n    element type as arguments and returns a single `i1` result via\\n    `iree_vector_ext.yield`.\\n\\n    The region is invoked during the reduction to determine which element to\\n    select: when the comparison yields `true`, the first argument is selected;\\n    otherwise, the second argument is selected.\\n\\n    The region must contain only pure operations (operations with the `Pure`\\n    trait). This ensures the comparator can be safely executed in any order\\n    during the reduction.\\n\\n    Example (implicit-index mode - argmax over dim 1):\\n    ```mlir\\n    %input_vec = vector<4x128xf32>\\n    %out_val_vec = vector<4xf32>\\n    %out_idx_vec = vector<4xi32>\\n    %result:2 = iree_vector_ext.arg_compare\\n      dimension(1)\\n      ins(%input_vec : vector<4x128xf32>)\\n      inits(%out_val_vec, %out_idx_vec : vector<4xf32>, vector<4xi32>) {\\n    ^bb0(%a: f32, %b: f32):\\n      %cmp = arith.cmpf ogt, %a, %b : f32\\n      iree_vector_ext.yield %cmp : i1\\n    } -> vector<4xf32>, vector<4xi32>\\n    ```\\n\\n    Example (explicit-index mode):\\n    ```mlir\\n    %partial_vals = vector<4x32xf32>\\n    %partial_idxs = vector<4x32xi32>\\n    %out_val = vector<4xf32>\\n    %out_idx = vector<4xi32>\\n    %result:2 = iree_vector_ext.arg_compare\\n      dimension(1)\\n      ins(%partial_vals, %partial_idxs : vector<4x32xf32>, vector<4x32xi32>)\\n      inits(%out_val, %out_idx : vector<4xf32>, vector<4xi32>) {\\n    ^bb0(%a: f32, %b: f32):\\n      %cmp = arith.cmpf ogt, %a, %b : f32\\n      iree_vector_ext.yield %cmp : i1\\n    } -> vector<4xf32>, vector<4xi32>\\n    ```\\n\\n    The `index_base` is an optional offset value that, when specified, is added\\n    to the computed indices in the result. This is useful when reducing over a\\n    sliced subregion where the indices need to be adjusted to reflect their\\n    position in the original vector. The `index_base` can only be used in\\n    implicit-index mode (single input).\\n\\n    The `inits` operands provide the initial accumulator values for the\\n    reduction (initial max/min value and index).\",\n    \"operands\": [\n      { \"name\": \"input_value\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"input_index\", \"type\": \"Optional<AnyVectorOfAnyRank>\" },\n      { \"name\": \"init_value\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"init_index\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"index_base\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_value\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"result_index\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['init_value', 'result_value']>\" },\n      { \"type\": \"AllTypesMatch<['init_index', 'result_index']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    `ins` `(` $input_value (`,` $input_index^)? `:` type($input_value) (`,` type($input_index)^)? `)`\\n    `inits` `(` $init_value `,` $init_index `:` type($init_value) `,` type($init_index) `)`\\n    (`index_base` `(` $index_base^ `:` type($index_base) `)`)?\\n    $region `->` type($result_value) `,` type($result_index)\"\n  },\n  {\n    \"name\": \"iree_vector_ext.to_layout\",\n    \"summary\": \"Layout conversion operator.\",\n    \"description\": \"The layout conversion operator takes a shaped value and a layout and\\n    transforms the value to have that layout.\\n\\n    If the \\\"shared_memory_conversion\\\" attribute is set, then this layout\\n    change has to be materialized through shared memory.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"VectorLayoutInterface\" },\n      { \"name\": \"shared_memory_conversion\", \"type\": \"DefaultValuedAttr<UnitAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input `to` `layout` `(` $layout `)` attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"iree_vector_ext.to_simd\",\n    \"summary\": \"SIMT to SIMD conversion operation.\",\n    \"description\": \"This operation is a temporary operation useful for source/target\\n    materializations when doing type conversions between distributed and not\\n    distributed vectors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"iree_vector_ext.to_simt\",\n    \"summary\": \"SIMD to SIMT conversion operation.\",\n    \"description\": \"This operation is a temporary operation useful for source/target\\n    materializations when doing type conversions between distributed and not\\n    distributed vectors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"iree_vector_ext.transfer_gather\",\n    \"summary\": \"Gathers a supervector from a shaped source into an SSA vector value.\",\n    \"description\": \"The `transfer_gather` operation reads elements from a shaped source (memref\\n    or tensor) into a vector, where each source dimension can be independently\\n    contiguous, gathered, or broadcast.\\n\\n    Semantically, for each position in the result vector:\\n\\n    ```\\n    result[d0, d1, ...] = base[offsets[0] + f0(d, s), offsets[1] + f1(d, s), ...]\\n    ```\\n\\n    where each `fi` is the i-th result of the source indexing map evaluated at\\n    the vector position `d = (d0, d1, ...)` and gathered index values\\n    `s = (s0, s1, ...)`.\\n\\n    The `indexing_maps` attribute describes all indexing. Every map has\\n    `numDims = result vector rank` and `numSymbols = number of index vecs`:\\n\\n    - Map 0 (source map): `(vector_dims)[symbols] -> (source_dims)`.\\n      A dim expr means the source dimension is contiguous (iterated in\\n      lockstep with the vector dimension). A symbol expr means the source\\n      dimension is gathered (looked up via the corresponding index vector).\\n      A constant 0 means the source dimension is broadcast (always reads\\n      at the base offset).\\n    - Maps 1..N (index vec maps): `(vector_dims)[symbols] -> (index_vec_dims)`.\\n      Describes how each index vector is indexed from the vector iteration\\n      space. Only dim exprs are allowed.\\n    - Optional last map (mask map): present only when a mask operand is\\n      provided. Only dim exprs are allowed.\\n\\n    Example — embedding lookup: reading rows from a 3D source where the row\\n    index is gathered from an index vector, while the column is contiguous:\\n\\n    ```\\n    // result[i, j] = base[0, indices[i], j]\\n    %result = iree_vector_ext.transfer_gather %base[%c0, %c0, %c0]\\n      [%indices : vector<16xindex>], %pad {\\n        indexing_maps = [\\n          affine_map<(d0, d1)[s0] -> (0, s0, d1)>,\\n          affine_map<(d0, d1)[s0] -> (d0)>\\n        ]\\n      } : memref<4096x512x8xf16>, vector<16x8xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyShaped\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"index_vecs\", \"type\": \"Variadic<AnyTypeOf<[ Index, VectorOfAnyRankOf < [ Index ] > ]>>\" },\n      { \"name\": \"padding\", \"type\": \"AnyType\" },\n      { \"name\": \"mask\", \"type\": \"Optional<VectorOfAnyRankOf<[ I1 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'base', 'padding', 'getElementTypeOrSelf($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $offsets `]` (`[` $index_vecs^ `:` type($index_vecs) `]`)? `,` $padding (`,` $mask^)? attr-dict `:` type($base) `,` type($vector) (`,` type($mask)^)?\"\n  },\n  {\n    \"name\": \"iree_vector_ext.transfer_scatter\",\n    \"summary\": \"Scatters a supervector from an SSA vector value into a shaped destination.\",\n    \"description\": \"The `transfer_scatter` operation is the write counterpart of\\n    `transfer_gather`. It writes elements from a vector into a shaped\\n    destination (memref or tensor), where each destination dimension can be\\n    independently contiguous, scattered, or broadcast.\\n\\n    The scatter indices are expected to be unique. If multiple vector elements\\n    map to the same destination location, the behavior is undefined. I.e., There may be data races.\\n\\n    For tensor operands, the operation returns the modified tensor. For memref\\n    operands, the operation has no result.\\n\\n    Example — scatter write: writing values into scattered rows of a 2D dest:\\n\\n    ```\\n    // dest[indices[i], j] = vector[i, j]\\n    %result = iree_vector_ext.transfer_scatter %vector into %dest[%c0, %c0]\\n      [%indices : vector<16xindex>] {\\n        indexing_maps = [\\n          affine_map<(d0, d1)[s0] -> (s0, d1)>,\\n          affine_map<(d0, d1)[s0] -> (d0)>\\n        ]\\n      } : vector<16x8xf16>, tensor<4096x8xf16> -> tensor<4096x8xf16>\\n    ```\\n\\n    Semantically, for each position in the source vector:\\n\\n    ```\\n    dest[offsets[0] + f0(d, s), offsets[1] + f1(d, s), ...] = vector[d0, d1, ...]\\n    ```\\n\\n    where each `fi` is the i-th result of the dest indexing map evaluated at\\n    the vector position `d = (d0, d1, ...)` and scattered index values\\n    `s = (s0, s1, ...)`.\\n\\n    The `indexing_maps` attribute follows the same structure as\\n    `transfer_gather`. See `transfer_gather` documentation for details. The\\n    only difference is that Map 0 describes the destination indexing rather\\n    than the source indexing.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyShaped\" },\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"index_vecs\", \"type\": \"Variadic<AnyTypeOf<[ Index, VectorOfAnyRankOf < [ Index ] > ]>>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<VectorOfAnyRankOf<[ I1 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyShaped>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$vector `into` $base `[` $offsets `]`\\n    (`[` $index_vecs^ `:` type($index_vecs) `]`)?\\n    (`,` $mask^)?\\n    attr-dict `:` type($vector) `,` type($base)\\n    (`,` type($mask)^)?\\n    (`->` type($result)^)?\"\n  },\n  {\n    \"name\": \"iree_vector_ext.yield\",\n    \"summary\": \"Yield operation for VectorExt operations with regions\",\n    \"description\": \"Yields values from regions in VectorExt operations.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($values^ `:` type($values))?\"\n  },\n  {\n    \"name\": \"kernel.call\",\n    \"summary\": \"calls a kernel defined in a `gpu.module`\",\n    \"description\": \"The `kernel.call` operation calls (launches/executes) a kernel that is\\n    defined within a `gpu.module`. The `kernel.call` operation cannot be\\n    nested within a `gpu.module` since it represents an operation executed on\\n    the host. The kernel accepts `grid_size` values (at least one and up to\\n    three values). The grid size indicates the size of the grid of threadblocks\\n    that should be launched. The total number of threadblocks launched is the\\n    product of all the values given to `grid_size`.\\n\\n    A kernel may yield some number of results, in which case it is in\\n    destination-passing style and the results  are tied to the `outs` arguments.\\n\\n    #### Example:\\n\\n    ```mlir\\n    gpu.module @kernels {\\n      func.func @kernel(%arg0: memref<1xf32>, %arg1: memref<1xf32>) {\\n        %c0 = arith.constant 0 : index\\n        %0 = memref.load %arg0[%c0] : memref<1xf32>\\n        memref.store %0, %arg1[%c0] : memref<1xf32>\\n        return\\n      }\\n    }\\n\\n    func.func @caller(%arg0: memref<1xf32>, %arg1: memref<1xf32>) {\\n      kernel.call @kernels::@kernel(%arg0) outs(%arg1) : (memref<1xf32>)->(memref<1xf32>)\\n      return\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"grid_size\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"block_size\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_sym\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$kernel_sym `grid` `[` $grid_size `]`\\n    `block` `[` $block_size `]` `(` $inputs `)` `outs` `(` $outs `)`\\n    attr-dict `:` custom<KernelFunctionalType>(\\n      ref($inputs),\\n      ref($outs),\\n      type($inputs), type($outs), type($results))\"\n  },\n  {\n    \"name\": \"kernel.combiner\",\n    \"description\": \"`kernel.combiner` represents a group of scalar operations which\\n    collectively represent an associative reduction operation.\\n\\n    The purpose of this operation is to allow the programmer or a previous\\n    compiler pass to specify that a group of inline scalar operations\\n    has an associative property (and optionally one can also specify that the\\n    group is commutative).\\n\\n    For example, the following 'kernel.combiner' represents the so-called\\n    \\\"online softmax\\\" reduction function, which is both associative and commutative:\\n\\n    ```\\n    func.func @test_associative(%arg0: f32, %arg1: f32, %arg2: f32, %arg3: f32) -> (f32, f32) {\\n      %0, %1 = kernel.combiner (%arg0, %arg1, %arg2, %arg3) : f32, f32, f32, f32 {\\n      ^bb0(%in0: f32, %in1: f32, %out0: f32, %out1: f32):\\n        %max = arith.maximumf %in0, %out0 : f32\\n        %0 = arith.subf %in0, %max : f32\\n        %1 = arith.subf %out0, %max : f32\\n        %2 = math.exp %0 : f32\\n        %3 = math.exp %1 : f32\\n        %4 = arith.mulf %2, %in1 : f32\\n        %5 = arith.addf %4, %3 : f32\\n        kernel.yield %max, %5 : f32, f32\\n      }\\n      return %0, %1 : f32, f32\\n    }\\n    ```\\n\\n    The assembly format is very basic and in the future could be improved. The\\n    semantic of the operation is simply that it forwards the operands to the\\n    block arguments, executes the operations in the body, and yields the results\\n    back to the parent. However, the operation also has certain requirements:\\n\\n    1. It must have an even number of arguments\\n    2. The types of the first half of the arguments must match the last half.\\n    3. The number of results is half the number of arguments and the types\\n      are taken from the first half of the arguments.\\n\\n    Conceptually, it indicates that the following represents an associative\\n    reduction on a pair of 2-tuples:\\n\\n    ```\\n    f( [in0, in1], [out0, out1]) := [\\n      max(in0, out0),\\n      in1 * exp(in0 - max(in0, out0)) + in1 * exp(out0 - max(in0, out0))\\n    ]\\n    ````\\n\\n    Note that no actual verification is performed to ensure that the operation\\n    is actually commutative since that would be very expensive. The analysis should\\n    come from the creator (programmer or compiler pass).\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyFloat, AnyComplex, AnySignlessIntegerOrIndex ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"commutative\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` ( $inputs^ `)` ) : ( `)` ) ?\\n     attr-dict-with-keyword `:` type($inputs)\\n     $body\"\n  },\n  {\n    \"name\": \"kernel.ext_call\",\n    \"summary\": \"extended kernel call with tensor support and explicit aliasing\",\n    \"description\": \"The `kernel.ext_call` operation is an extended version of `kernel.call` that\\n    accepts tensors directly with explicit side-effect and aliasing annotations.\\n\\n    Key features:\\n    - Single unified argument list (no ins/outs split)\\n    - Explicit side effects per argument: \\\"r\\\" (read), \\\"rw\\\" (read/write), \\\"-\\\" (none)\\n    - Explicit aliasing: maps arguments to results for in-place operations\\n    - Automatic bufferization integration\\n\\n    The `result_aliases` attribute is an array of argument indices that specifies\\n    which arguments alias which results. For each `i` in `range(0, num_results)`,\\n    `result[i]` must alias `args[result_aliases[i]]`.\\n\\n    The `effects` attribute specifies memory effects for each argument:\\n    - \\\"r\\\": read-only (for memref/tensor arguments)\\n    - \\\"rw\\\": read-write (for in-place modified arguments)\\n    - \\\"-\\\": no effect (for scalars)\\n\\n    #### Example:\\n\\n    ```mlir\\n    %results:2 = kernel.ext_call @kernels::@my_kernel\\n        grid[%gx] block[%bx]\\n        args(%keys, %temps, %ping : tensor<?xi32>, tensor<?xi32>, i1)\\n        result_aliases = [0, 1],  // result[0] aliases arg[0], result[1] aliases arg[1]\\n        effects = [\\\"rw\\\", \\\"rw\\\", \\\"-\\\"]  // read/write, read/write, no effect\\n        : tensor<?xi32>, tensor<?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"grid_size\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"block_size\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_sym\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"result_aliases\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"effects\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$kernel_sym `grid` `[` $grid_size `]`\\n    `block` `[` $block_size `]`\\n    `args` `(` $args `:` type($args) `)`\\n    `result_aliases` `=` $result_aliases\\n    `,` `effects` `=` $effects\\n    attr-dict (`:` type($results)^)?\"\n  },\n  {\n    \"name\": \"kernel.scatter\",\n    \"description\": \"The `kernel.scatter` operation performs scatters updates to the\\n    `init` tensor and returns a new updated tensor.\\n\\n    The `init` tensor is the starting tensor, and the `updates` tensor\\n    contains the values to be scattered into the `init` tensor. The `indices`\\n    tensor specifies the indices of the elements in the `init` tensor\\n    that should be updated.\\n\\n    The update is performed by combining the value from `init` with the\\n    scalar value from `updates` using the `update_computation` region.\\n\\n    The semantics of this operation exactly match those of\\n    `stablehlo.scatter`. See the following spec for more details:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#scatter\\n\\n    This operation implements TilingInterface and ToLoopsOpInterface,\\n    and it is not currently bufferizable. The expected usage pattern\\n    is to lower to loops via ToLoopsOpInterface prior to\\n    bufferization.\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"AnyShaped\" },\n      { \"name\": \"updates\", \"type\": \"Variadic<AnyShaped>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"update_window_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"inserted_window_dims\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"input_batching_dims\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"scatter_indices_batching_dims\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"scatter_dims_to_operand_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"UnitAttr\" },\n      { \"name\": \"unique_indices\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"update_computation\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`updates` `(` $updates `:` type($updates) `)`\\n    `into`    `(` $inits `:` type($inits) `)`\\n    `at`      `(` $indices `:` type($indices) `)`\\n    $update_computation\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"kernel.sort\",\n    \"summary\": \"Merge sort operator for keys-only or key-value pairs\",\n    \"description\": \"The `kernel.sort` operation performs a merge sort on the input tensor(s)\\n    and returns sorted result(s). It supports two modes:\\n\\n    1. Keys-only: Sorts a single input tensor of keys\\n    2. Key-value: Sorts keys and rearranges corresponding values\\n\\n    The sort is performed along the innermost (fastest-varying) dimension.\\n    The implementation uses a CUB-inspired two-stage GPU merge sort:\\n    - Stage 1: Block-level sort using bitonic sort within threads and merge across threads\\n    - Stage 2: Multi-pass global merge using merge path algorithm\\n\\n    Configuration parameters:\\n    - `block_threads`: Number of threads per block (default: 128, recommended: 128)\\n    - `items_per_thread`: Nominal number of elements per thread (default: 4, recommended: 4)\\n\\n    ## Type-Based Tuning (Automatic)\\n\\n    The `items_per_thread` parameter is automatically scaled based on the key type's\\n    size to maintain constant register pressure. This follows CUB's\\n    `Nominal4BItemsToItems` strategy (see cub/util/util_math.cuh).\\n\\n    Formula: `actual_items = min(nominal, max(1, nominal * 4 / sizeof(KeyType)))`\\n\\n    Examples with `items_per_thread = 4`:\\n    - `i8`  (1 byte):  4 items/thread (no scaling needed)\\n    - `i32` (4 bytes): 4 items/thread (optimal baseline)\\n    - `i64` (8 bytes): 2 items/thread (scaled down to prevent register spills)\\n    - `f64` (8 bytes): 2 items/thread (scaled down to prevent register spills)\\n\\n    This means you can use the same configuration for all types, and the compiler\\n    will automatically optimize for each type:\\n\\n    ```mlir\\n    // Same config works optimally for all types!\\n    %sorted_i32 = kernel.sort ins(%keys_i32 : tensor<?xi32>)\\n                              outs(%out_i32 : tensor<?xi32>)\\n                              {block_threads = 128, items_per_thread = 4}\\n                              -> tensor<?xi32>\\n\\n    %sorted_i64 = kernel.sort ins(%keys_i64 : tensor<?xi64>)\\n                              outs(%out_i64 : tensor<?xi64>)\\n                              {block_threads = 128, items_per_thread = 4}\\n                              -> tensor<?xi64>\\n    // Automatically uses 2 items/thread for i64 to prevent register spills!\\n    ```\\n\\n    ## Recommended Configuration\\n\\n    For best performance on Hopper/Blackwell GPUs with MLIR codegen:\\n    - `block_threads = 128`\\n    - `items_per_thread = 4`\\n\\n    These defaults are empirically tuned for MLIR's codegen and provide 35% better\\n    performance than larger tile sizes. Smaller tiles maximize occupancy and enable\\n    better memory coalescing with our explicit loop unrolling optimizations.\\n\\n    Note: These defaults differ from CUB's tuning (256x17) because:\\n    - MLIR codegen benefits from smaller tiles and better occupancy\\n    - Hopper architecture prefers more concurrent blocks with smaller working sets\\n    - Our loop unrolling optimizations work best with smaller tiles\\n\\n    Users typically do not need to tune these parameters.\\n\\n    ## Examples\\n\\n    Example (keys-only with recommended config):\\n    ```mlir\\n    %sorted = kernel.sort ins(%keys : tensor<?xi32>)\\n                          outs(%out : tensor<?xi32>)\\n                          {block_threads = 128, items_per_thread = 4}\\n                          -> tensor<?xi32>\\n    ```\\n\\n    Example (key-value):\\n    ```mlir\\n    %sorted_keys, %sorted_values = kernel.sort\\n        ins(%keys, %values : tensor<?xi32>, tensor<?xf32>)\\n        outs(%out_keys, %out_values : tensor<?xi32>, tensor<?xf32>)\\n        {block_threads = 128, items_per_thread = 4}\\n        -> tensor<?xi32>, tensor<?xf32>\\n    ```\\n\\n    ## References\\n\\n    - CUB DeviceMergeSort: https://nvidia.github.io/cccl/cub/api/structcub_1_1DeviceMergeSort.html\\n    - CUB Nominal4BItemsToItems: cub/util/util_math.cuh lines 86-91\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_threads\", \"type\": \"DefaultValuedAttr<I64Attr, 128>\" },\n      { \"name\": \"items_per_thread\", \"type\": \"DefaultValuedAttr<I64Attr, 4>\" }\n    ],\n    \"assemblyFormat\": \"`(` ( $inputs^ `)` ) : ( `)` )?\\n    `<` `block_threads` `=` $block_threads\\n    `,` `items_per_thread` `=` $items_per_thread `>` attr-dict\\n    ( `:` type($inputs)^ )?\"\n  },\n  {\n    \"name\": \"kernel.yield\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ AnyFloat, AnyComplex, AnySignlessIntegerOrIndex ]>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"krnl.acos\",\n    \"summary\": \"Krnl acos scalar operation\",\n    \"description\": \"Krnl acos scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.acosh\",\n    \"summary\": \"Krnl acosh scalar operation\",\n    \"description\": \"Krnl acosh scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.asin\",\n    \"summary\": \"Krnl asin scalar operation\",\n    \"description\": \"Krnl asin scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.asinh\",\n    \"summary\": \"Krnl asinh scalar operation\",\n    \"description\": \"Krnl asinh scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.atan\",\n    \"summary\": \"Krnl atan scalar operation\",\n    \"description\": \"Krnl atan scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.atanh\",\n    \"summary\": \"Krnl atanh scalar operation\",\n    \"description\": \"Krnl atanh scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.block\",\n    \"summary\": \"Krnl block operation\",\n    \"description\": \"Block a single for loop by a constant tile size. For instance,\\n    ```\\n    $ib, $il = krnl.block %i, 4\\n    ```\\n    means to block the for loop referred to by %i using a tile size of 4.\",\n    \"operands\": [\n      { \"name\": \"loop\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"loop_block\", \"type\": \"AnyType\" },\n      { \"name\": \"loop_local\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile_size\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$loop $tile_size attr-dict `:` functional-type($loop, results)\"\n  },\n  {\n    \"name\": \"krnl.call\",\n    \"summary\": \"call operation\",\n    \"description\": \"The call operation provides a generic way to replace an ONNX Op with a call\\n    to an external function at Krnl level.\\n    `funcName` attributes determines which function to call.\\n    `parameters` is the inputs to Krnl.Call. It includes the outputs and inputs\\n    of the ONNX Op. The outputs and inputs are already lowered to MemRefs.\\n    The external function is assumed NOT to allocate or free any memory.\\n    'numOfOutput` attribute to tell how manu outputs Memref in parameters.\\n    mlir::OpTrait::AttrSizedOperandSegments is not used to put outputs and\\n    inputs into separate variadic parameters because I am thinking of mixing\\n    the inputs and outpus as required by external library.\\n\\n    The attributes of the ONNX Op will be copied to KrnlCallOp under the control\\n    of the user.\\n    In Krnl To llvm lowering, the parameters and attributes will be lowered to\\n    parameters of the llvm function call.\\n\\n    Several builder is defined to help translating an ONNX Op to Krnl.Call.\\n    User can provides the allocated MemRefs for outputs and the inputs\\n    separately. The inputs are usually the operands of the ONNX Op.\\n    The attributes of ONNX Op can be copied or not copied based on a bool\\n    parameter in the builder. Builder also provide a mechanism for user\\n    to selectively copy some attributes.\\n\\n    The krnl.call op will be lowered to llvm at krnl-to-llvm conversion in which\\n    OMTensor is used as a container for MemRef arguments. Other representation\\n    of parameters, such as data pointer only, will be supported in future.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"returnValue\", \"type\": \"Variadic<AnyTypeOf<[ AnyFloat, AnyInteger ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"funcName\", \"type\": \"StrAttr\" },\n      { \"name\": \"numOfOutput\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.copy_from_tile_buffer\",\n    \"summary\": \"Copy from buffer.\",\n    \"description\": \"Operation that copy a destination memory from a buffer memory.\\n    Starts indicate where the buffer data starts to go into the destination\\n    memory. Start values must be at multiples of buffer size in all dimensions.\\n    The buffer rank and dimensions are compile time constants.\\n\\n    If the buffer was oversized with respect of the actual data contained\\n    in the tile, the actual tile size can be given using the tileSize\\n    optional attribute. This attributes has the same rank as the buffer size,\\n    and each dimension must be smaller or equal to the actual buffer size.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"dest\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"starts\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tileSize\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$buffer `,` $dest `[` $starts `]`  attr-dict `:` type($buffer) `,` type($dest)\"\n  },\n  {\n    \"name\": \"krnl.copy_to_tile_buffer\",\n    \"summary\": \"Copy to buffer.\",\n    \"description\": \"Operation that copy a source memory to a buffer memory.\\n    Starts indicate where the source data starts to come from within\\n    the source memory. Start values must be at multiples of buffer size\\n    in all dimensions. The buffer rank and dimensions are compile time\\n    constants.\\n\\n    The buffer will be entirely filled with the source data. By default,\\n    the amount of data to copy is given by the size of the buffer.\\n    In some cases, we may want to oversize a buffer for better cache,\\n    simd, or loop unroll and jam reasons. If that is the case, the\\n    actual tile size of the data to be copied over is given by an\\n    optional tileSize attribute. This attributes has the same rank as\\n    the buffer size, and each dimension must be smaller or equal to\\n    the actual buffer size.\\n\\n    If there is not enough data in the source memory to fill the buffer,\\n    because the operation reaches the upper bounds of the source memory,\\n    several actions may happen.\\n\\n    * If`padToNext` attribute is given, the pad value will be copied from\\n      the last source data of to the next index for which index modulo `padToNext`\\n      is zero, i.e. to the end of a \\\"cache line\\\" of side `padToLine`. Pad\\n      of 1 means no padding, pad of buffer size means fully pad the buffer.\\n      Default is no padding (1). `PadValue` is used to initialized the padded\\n      areas.\\n\\n    * If `overreadToNext` attribute is given, the copy may read source past\\n      its upper bound value. This enable optimized code, e.g. using SIMD\\n      read operations even if going past the last value of the source\\n      memory, or unrolling and jamming copy loops to reduce memory latency.\\n      `overreadToNext` is expressed like padToNext: value of 1 means no\\n      reading past boundary; value of buffer size enables reading\\n      as many additional source value as needed to fill the full\\n      buffer. Default is buffer-size.\\n\\n    `padToNext` and `overreadToNex`t are of the same rank as source and memory\\n    memrefs.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"starts\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"padValue\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tileSize\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"padToNext\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'source', 'padValue', 'mlir::cast<MemRefType>($_self).getElementType()'>\" },\n      { \"type\": \"TypesMatchWith<'buffer', 'padValue', 'mlir::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$buffer `,` $source `[` $starts `]` `,`  $padValue  attr-dict\\n     `:` type($buffer) `,` type($source)\"\n  },\n  {\n    \"name\": \"krnl.define_loops\",\n    \"summary\": \"define_loops operation\",\n    \"description\": \"The \\\"krnl.define_loops\\\" operation is used to define input loops,\\n    those are the for loops appearing in the input program that we\\n    intend to optimize.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"krnl.entry_point\",\n    \"summary\": \"Indicate ONNX entry point\",\n    \"description\": \"The \\\"krnl.entry_point\\\" function indicates the main entry\\n                           point of ONNX model.\",\n    \"attributes\": [\n      { \"name\": \"func\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"numInputs\", \"type\": \"IntegerAttr\" },\n      { \"name\": \"numOutputs\", \"type\": \"IntegerAttr\" },\n      { \"name\": \"signature\", \"type\": \"StringAttr\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.erf\",\n    \"summary\": \"Krnl erf scalar operation\",\n    \"description\": \"Krnl erf scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.find_index\",\n    \"summary\": \"Retrieve an index into a perfect hash table described by G and V.\",\n    \"description\": \"This operation can be used to generate a call to a runtime function which,\\n    given two arrays of int32_t values (G and V), which are used to represent a perfect\\n    hash table for a dictionary, returns the index corresponding to the input value.\\n    The index returned is valid only if 'input' is in the dictionary described by G and V.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[StringType, I64]>\" },\n      { \"name\": \"G\", \"type\": \"I32MemRef\" },\n      { \"name\": \"V\", \"type\": \"I32MemRef\" },\n      { \"name\": \"len\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.get_induction_var_value\",\n    \"summary\": \"Krnl\",\n    \"description\": \"Krnl operation to convert loop references to corresponding induction\\n     variable values. This is useful for accessing optimized loop induction\\n     variables, as they are not otherwise accessible during Krnl Dialect.\\n\\n     For example, this operation can be applied to loop references corresponding to\\n     inter-tile iterations. The return values will be the starting index of the\\n     current tile being iterated over.\",\n    \"operands\": [\n      { \"name\": \"loops\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"ind_var_vals\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $loops `)` attr-dict `:` functional-type($loops, results)\"\n  },\n  {\n    \"name\": \"krnl.get_linear_offset_index\",\n    \"summary\": \"A Krnl operation to compute a linear offset index from a N-D index.\",\n    \"description\": \"Given a MemRef and an N-D index (id_1, id_2, ..., id_n), where n is\\n    the rank of the MemRef, this operation computes a linear offset index.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"krnl.global\",\n    \"summary\": \"Krnl global operation\",\n    \"description\": \"Operation for holding global data values. A global constant can have a\\n    meaningful name recorded as its `name` attribute. Its content is stored\\n    in the `value` dense element attribute.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[AnyMemRef]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"AnyAttr\" },\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"offset\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.isinf\",\n    \"summary\": \"Krnl isinf scalar operation\",\n    \"description\": \"Krnl isinf scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"I1\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.isnan\",\n    \"summary\": \"Krnl isnan scalar operation\",\n    \"description\": \"Krnl isnan scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"I1\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.iterate\",\n    \"summary\": \"iterate operation\",\n    \"description\": \"The \\\"krnl.iterate\\\" operation is conceptually equivalent to a nested for loops.\\n\\n    For instance, say we have the following two\\n    ```\\n    %l0, %l1 = krnl.define_loops 2\\n    %o0, %o1 = krnl.optimize_loops  {\\n        // Identity schedule.\\n        krnl.return_loops %l0, %l1\\n    }\\n    ```\\n\\n    Then, consider the following krnl.iterate operation:\\n    ```\\n    krnl.iterate (%o0, %o1) with (%l0 -> %i0 = 0 to 10, %l1 -> %i1 = 0 to 10) {\\n      // Some operations.\\n    }\\n    ```\\n\\n    It is equivalent to:\\n    ```\\n    for (i0 = 0; i0 < 10; i0++)\\n      for (i1 = 0; i1 < 10; i1++)\\n        // Some operations.\\n    ```\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"krnl.load\",\n    \"summary\": \"A Krnl operation to load data from the memref.\",\n    \"description\": \"The `krnl.load` op reads an element from a memref specified by an index\\n    list. The output of load is a new value with the same type as the elements\\n    of the memref. The arity of indices is the rank of the memref (i.e., if the\\n    memref loaded from is of rank 3, then 3 indices are required for the load\\n    following the memref identifier).\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'memref', 'result', 'mlir::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memref `[` $indices `]` attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"krnl.matmul\",\n    \"summary\": \"Matmul operation for a single pannel.\",\n    \"description\": \"Perform a matrix multiplication AA * BB + CC with sizes `[IxK] * [KxJ] + [IxJ]`.\\n    The original matrices AA, BB, and CC can be buffered in buffered arrays\\n    which may be padded. The original matrices and the padded array might\\n    have a higher rank than 2, but the actual matrix multiplication operation\\n    only deal with the innermost 2 ranks of the matrices to perform its matrix\\n    multiplication operations.\\n\\n    The computations may also compute only a sub-tile of the buffered arrays.\\n    This region is depicted using stars '*' below.\\n\\n    All indices passed to this operation are the global indices in the original\\n    computation, so as to better know if we have boundary conditions.\\n\\n    ORIGINAL ARRAY: denoted as AA, BB, CC with sizes AA: `*xIxK`; BB: `*xKxJ`; CC: `*xI*J`).\\n\\n    BUFFER ARRAYS: denoted as A, B, and C. Note that this operation does\\n      not require the use of buffers arrays. If none are used, then A=AA,\\n      B=BB, C=CC. If buffers are used, it is the responsibility of the caller\\n      to properly fill the buffers with the appropriate data. Buffers are\\n      typically used for cache tiling.\\n\\n     ORIGINAL ARRAY\\n\\n```\\n     -------------------------------------------------\\n     |                                               ]\\n     |                                               ]\\n     |             buffer array       buffer pad     ]\\n     |            (3)---------------- ++++           ]\\n     |             |                 |   +           ]\\n     |             |     (1)****     |   +           ]\\n     |             |      *    *     |   +           ]\\n     |             |      *    *     |   +           ]\\n     |             |      ****(5)    |   +           ]\\n     |             |                 |   +           ]\\n     |             |                 |   +           ]\\n     |             ------------------|   +           ]\\n     |             +                     +           ]\\n     |             +++++++++++++++++++++(4)          ]\\n     |                                               ]\\n     -----------------------------------------------(2)\\n```\\n\\n* (1) `iGlobalIndexComputeStart`/`jGlobalIndexComputeStart`/`kGlobalIndexComputeStart`,\\n   required, each three are global 1D indices.\\n* (2) `iGlobalUB`/`jGlobalUB`/`jGlobalUB`, required, each three are global 1D indices.\\n* (3) `aGlobalIndexMemStart`/`bGlobalIndexMemStart`/`cGlobalIndexMemStart`,\\n   required, global nD indices with the same rank as the buffers A, B, and C.\\n* (4) `aTileSize`/`bTileSize`/`cTileSize`, required when padding, each 2D sizes.\\n* (5) `computeTileSizes`, required when tiled computation within buffer, 3D sizes (I, J, K).\\n\\n    The `iGlobalIndexComputeStart`/`jGlobalIndexComputeStart`/\\n    `kGlobalIndexComputeStart` (1) indicate the global indices of the\\n    first element of a tile to be computed in the original computations.\\n\\n    The `iGlobalUB`/`jGlobalUB`/`kGlobalUB` (2) indicate the global upper bounds\\n    in the original computations.\\n\\n    We provide 3 buffers for matrix multiply: A, B, and C. For each buffer,\\n    we indicate the global indices pointing the beginning of the buffer:\\n    `aGlobalIndexMemStart`, `bGlobalIndexMemStart`, and `cGlobalIndexMemStart` (3).\\n    If no buffers are used, i.e. the computation starts directly in the\\n    original memory, the global index is 0. If a buffer for AA is used to\\n    put data into it starting at indices `[i1, k1]`, where `i1` & `k1` are the\\n    global indices in the original computations, then `aGlobalIndexMemStart0`\\n    and `aGlobalIndexMemStart1` are `i1` & `k1`, respectively.\\n\\n    If the A, B, or C buffers are larger than the actual data tile they\\n    contain (see `copy_to_tile_buffer`), then the actual tile size must be\\n    given using an optional attribute: `aTileSize`, `bTileSize`, or `cTileSize` (4).\\n    These optional tile size have a rank of 2, and their values must be\\n    equal or smaller than their corresponding buffer memrefs.\\n\\n    If the computation are further tiled with respect to the size of the\\n    buffers A, B, or C, then the actual computation tile is given by\\n    the optional tile attribute `computeTileSize` (5). Its rank is 3, for the\\n    I, J, and K dimension. The actual A, B, and C buffer tile size\\n    (possibly specified by the optional parameters) must be a multiple of\\n    the I, J, and K `computeTileSizes`, in their respective\\n    dimensions (A: `[IxK]`, B: `[KxJ]`, C: `[IxJ]`).\\n\\n    Note that the buffers A, B, and C can be of higher dimensionality than\\n    the traditional 2D mentioned up to now, because of broadcasting rules.\\n    At this time, we only support broadcast of arrays having ranks of 2 or\\n    more. Because of the broadcast rules, the higher dimensions have a\\n    constant index during one matrix multiply. These fixed indices are\\n    given as prefix dimensions in the starting indices for AA, BB, and CC\\n    as described above. E.g. if AA has a rank of 3, and BB has a rank of 2,\\n    the starting indices for AA are `[d, i1, k1]` where `i1` and `k1` are as\\n    above, and d is index pointing to the current instance of the `IxK`\\n    AA matrix to be computed. B start indices would be unchanged at `[k1, j1]`.\\n\\n    Simdize is used to state if simdization is requested.\\n    Unrolling is used to unroll and jam loops as warranted.\\n\\n    Below is an example calculating a matrix multiply with pre-zeroed\\n    C matrix with the sizes below.\\n\\n```\\n    %A: memref<40x60xf32>, %B: memref<60x80xf32>, %C: memref<40x80xf32>\\n\\n    // 3 tiled loops.\\n    %ii, %jj, %kk = krnl.define_loops 3\\n    %ib, %il = krnl.block %ii 10 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    %jb, %jl = krnl.block %jj 8 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    %kb, %kl = krnl.block %kk 10 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    // 3 subtiles.\\n    %ilb, %ill = krnl.block %il 5 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    %jlb, %jll = krnl.block %jl 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    %klb, %kll = krnl.block %kl 5 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    // Permute.\\n    krnl.permute(%ib, %ilb, %ill, %jb, %jlb, %jll, %kb, %klb, %kll)\\n        [0, 3, 6, 1, 4, 7, 2, 5, 8] :\\n        !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop,\\n        !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop\\n    // Outer 2 for i, j.\\n    krnl.iterate(%ib, %jb) with (%ii -> %i = 0 to 40,\\n                                 %jj -> %j = 0 to 80,\\n                                 %kk -> %k = 0 to 60) {\\n        %i1, %j1 = krnl.get_induction_var_value(%ib, %jb) :\\n          (!krnl.loop,!krnl.loop) -> (index, index)\\n        // Fill C buffer.\\n        %Cbuff = alloca(): memref<10x8xf32>  // n x m_simd\\n        krnl.copy_to_tile_buffer %Cbuff, %C[%i1, %j1], %f0 :\\n          memref<10x8xf32>, memref<40x80xf32>\\n        // Outer 1 for k.\\n        krnl.iterate(%kb) with () {\\n            %k1 = krnl.get_induction_var_value(%kb) : (!krnl.loop) -> (index)\\n            // Fill A and B buffer\\n            %Abuff = alloca(): memref<10x10xf32> // i x k\\n            %Bbuff = alloca(): memref<10x8xf32>  // k x j_simd\\n            krnl.copy_to_tile_buffer %Abuff, %A[%i1, %k1], %f0 :\\n              memref<10x10xf32>, memref<40x60xf32>\\n            krnl.copy_to_tile_buffer %Bbuff, %B[%k1, %j1], %f0 :\\n              memref<10x8xf32>, memref<60x80xf32>\\n\\n            // Inner iterations for subtiles.\\n            krnl.iterate(%ilb, %jlb, %klb) with () {\\n                %i2, %j2, %k2 = krnl.get_induction_var_value(%ilb, %jlb, %klb) :\\n                (!krnl.loop,!krnl.loop,!krnl.loop) -> (index,index,index)\\n\\n                krnl.matmul %Abuff[%i1, %k1], %Bbuff[%k1, %j1], %Cbuff[%i1, %j1],\\n                    (%ill, %jll, %kll), (%i2, %j2, %k2), (%c40, %c80, %c60)\\n                    { computeTileSize=[5,4,5], simdize=false, unroll=false } :\\n                    memref<10x10xf32>, memref<10x8xf32>, memref<10x8xf32>,\\n                    (!krnl.loop,!krnl.loop,!krnl.loop)\\n            }\\n        }\\n        // Copy back the data into C.\\n        krnl.copy_from_tile_buffer %Cbuff, %C[%i1, %j1] :\\n          memref<10x8xf32>, memref<40x80xf32>\\n    }\\n```\\n\\n    Note that code is simdized along the J dim (last dim of B and C matrices).\\n    For simd to be enabled, the simdized flag must be set to true, and the\\n    following condition must be true:\\n    1) The vector length is the second entry of (i, j, k) compute tile size.\\n       The vector length must be a compile time constant.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"aGlobalIndexMemStart\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"B\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"bGlobalIndexMemStart\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"C\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"cGlobalIndexMemStart\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"iGlobalIndexComputeStart\", \"type\": \"Index\" },\n      { \"name\": \"jGlobalIndexComputeStart\", \"type\": \"Index\" },\n      { \"name\": \"kGlobalIndexComputeStart\", \"type\": \"Index\" },\n      { \"name\": \"iGlobalUB\", \"type\": \"Index\" },\n      { \"name\": \"jGlobalUB\", \"type\": \"Index\" },\n      { \"name\": \"kGlobalUB\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"computeTileSize\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"aTileSize\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"bTileSize\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"cTileSize\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"simdize\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"unroll\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"overcompute\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$A `[` $aGlobalIndexMemStart `]` `,`\\n    $B `[` $bGlobalIndexMemStart `]` `,`\\n    $C `[` $cGlobalIndexMemStart `]` `,`\\n    `(` $loops `)` `,`\\n    `(` $iGlobalIndexComputeStart `,` $jGlobalIndexComputeStart `,`\\n        $kGlobalIndexComputeStart `)` `,`\\n    `(` $iGlobalUB `,` $jGlobalUB `,` $kGlobalUB `)`\\n    attr-dict `:` type($A) `,` type($B)`,` type($C) `,` `(` type($loops) `)`\"\n  },\n  {\n    \"name\": \"krnl.memcpy\",\n    \"summary\": \"Krnl memcpy operation\",\n    \"description\": \"Copy `num_elems` elements from `src` to `dest` MemRef.\\n\\n    Starting positions for `src` and `dest` are defined by `src_offset` and\\n    `dest_offset`, respectively.\\n\\n    It is the users' responsibility to make sure there is no out-of-bound read/write.\",\n    \"operands\": [\n      { \"name\": \"dest\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"num_elems\", \"type\": \"I64\" },\n      { \"name\": \"dest_offset\", \"type\": \"Index\" },\n      { \"name\": \"src_offset\", \"type\": \"Index\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.memset\",\n    \"summary\": \"Set buffer to a given value.\",\n    \"description\": \"Krnl operation that sets a buffer to a given value.\\n    In case that the buffer is a MemRef with affine_map, `delayed` indicates\\n    whether we set values along original or extended iteration space.\\n\\n    For example, given\\n    - an affine_map `#tile = affine_map < (i)->(i floordiv 4, i mod 4) >`, and\\n    - a buffer of type `memref<5xf32, #tile>`\\n\\n    Original iteration space is along the first axis that has 5 elements.\\n\\n    If we do normalization, the memref becomes `memref<2x4xf32>`. Now we have\\n    an extended iteration space along two axes of sizes 2 and 4, respectively.\\n    This extended iteration space has 8 elements in total.\\n\\n    If `delayed = false`, the original iteration space is used to set values.\\n    In the above example, only 5 out of 8 elementes will be set to the given value.\\n\\n    If `delayed = true`, the extended iteration space is used to set values.\\n    In the above example, all 8 elements will be set to the given value.\",\n    \"operands\": [\n      { \"name\": \"dest\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"delayed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'dest', 'value', 'mlir::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$dest `,` $value attr-dict `:` type($dest)\"\n  },\n  {\n    \"name\": \"krnl.movable\",\n    \"summary\": \"Krnl movable operation\",\n    \"description\": \"Encapsulates a list of operations, which should be moved under a newly lowered\\n     affine for operation eventually, but cannot presently because the destination\\n     affine for operation is not materialized yet.\\n\\n     This operation is automatically generated by the lowering of Krnl to affine dialect\\n     to assist with maintaining the relative positioning of loop and inner-loop statements.\\n     This construct is particularly helpful, for example, for lowering statements that\\n     are nested imperfectly between an \\\"eager\\\" and a \\\"lazy\\\" loop.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"krnl.noValue\",\n    \"summary\": \"An operation representing the absence of a value.\",\n    \"description\": \"This operation can be used to represent the absence of a value. It is\\n    typically used as an argument to operators that have optional parameters,\\n    and converted into nullptr while krnl to llvm lowering.\\n    Typically it is used for optional arguments used in KrnlCallop.\",\n    \"results\": [\n      { \"name\": \"none_val\", \"type\": \"NoneType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.parallel\",\n    \"summary\": \"Mark Krnl loops as parallel loops\",\n    \"description\": \"Parallelize the specified loops. When multiple loop specifiers are passed\\n    as parameters, there loops can be parallelized as a collapsed loop.\\n    krnl.parallel should be placed as the last operator before krnl.iterate,\\n    Since we do not want to parallelize the loop until we interpret krnl.block,\\n    krnl.permute and krnl.unroll.\\n\\n    Optionally, a value may specifiy the number of threads requested for the\\n    parallel loop. A proc_bind string may also be specified; valid values are\\n    \\\"primary\\\", \\\"close\\\", or \\\"spread\\\". Default values are used when not specified.\\n\\n    ```\\n    krnl.parallel (%i0, %i1) : !Krnl.loop, !Krnl.loop\\n    ```\",\n    \"operands\": [\n      { \"name\": \"loops\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"num_threads\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"proc_bind\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $loops `)` (`,` `num_threads` `(` $num_threads^ `)`)? attr-dict `:` type($loops)\"\n  },\n  {\n    \"name\": \"krnl.parallel_clause\",\n    \"summary\": \"Attach OpenMP clauses to an index varialbe\",\n    \"description\": \"Attach OpenMP clauses to an index variable. That index variable\\n    is used to uniquely associate a parallel loop with its clauses.\",\n    \"operands\": [\n      { \"name\": \"parallel_loop_index\", \"type\": \"Index\" },\n      { \"name\": \"num_threads\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"proc_bind\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $parallel_loop_index `)` (`,` `num_threads` `(` $num_threads^ `)`)? \\n      attr-dict `:` type($parallel_loop_index)\"\n  },\n  {\n    \"name\": \"krnl.permute\",\n    \"summary\": \"Krnl permute operation\",\n    \"description\": \"Permute a set of affine for loops using a specified permutation map.\\n    The permutation map `map` should be constructed in such way that the\\n    for loop referred to by the i-th operand to permute operation is sent\\n    to the `map[i]`-th position.\\n\\n    For example, the following krnl dialect IR:\\n    ```\\n    %ii, %jj, %kk = krnl.define_loops 3\\n    krnl.permute(%ii, %jj, %kk) [1, 2, 0] : !krnl.loop, !krnl.loop, !krnl.loop\\n    krnl.iterate (%ii, %jj, %kk) with (%ii -> %i = 0 to 10, %jj -> %j = 0 to 20, %kk -> %k = 0 to 30) {}\\n    ```\\n    will be lowered to:\\n    ```\\n    // Referenced by %kk\\n    affine.for %arg0 = 0 to 30 {\\n      // Referenced by %ii\\n      affine.for %arg1 = 0 to 10 {\\n        // Referenced by %jj\\n        affine.for %arg2 = 0 to 20 {\\n        }\\n      }\\n    }\\n    ```\\n\\n    For a more complicated example, we demonstrate 3-D tiling using krnl.block in\\n    conjunction with krnl.permute:\\n    ```\\n    %ii, %jj, %kk = krnl.define_loops 3\\n    // Blocking each loop by a factor of 4.\\n    %ib, %il = krnl.block %ii 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    %jb, %jl = krnl.block %jj 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    %kb, %kl = krnl.block %kk 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)\\n    // Move iteration over tile coordinates to be the outer loops and iterateion over\\n    // the inter-tile elements to be the inner loops.\\n    krnl.permute(%ib, %il, %jb, %jl, %kb, %kl) [0, 3, 1, 4, 2, 5] : !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop\\n    krnl.iterate(%ib, %il, %jb, %jl, %kb, %kl) with (%ii -> %i = 0 to 1024, %jj -> %j = 0 to 2048, %kk -> %k = 0 to 4096)  {\\n    }\\n    ```\\n\\n    The above IR gets lowered to:\\n    ```\\n    affine.for %arg0 = 0 to 1024 step 4 {\\n      affine.for %arg1 = 0 to 2048 step 4 {\\n        affine.for %arg2 = 0 to 4096 step 4 {\\n          affine.for %arg3 = #map0(%arg0) to #map1(%arg0) {\\n            affine.for %arg4 = #map0(%arg1) to #map1(%arg1) {\\n              affine.for %arg5 = #map0(%arg2) to #map1(%arg2) {\\n              }\\n            }\\n          }\\n        }\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"loops\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $loops `)` $map attr-dict `:` type($loops)\"\n  },\n  {\n    \"name\": \"krnl.prefetch\",\n    \"summary\": \"A Krnl operation to compute a linear offset index from a N-D index.\",\n    \"description\": \"Given a MemRef and an N-D index (id_1, id_2, ..., id_n), prefetch the memory\\n    location pointed by this memory reference.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isWrite\", \"type\": \"BoolAttr\" },\n      { \"name\": \"localityHint\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>\" },\n      { \"name\": \"isDataCache\", \"type\": \"BoolAttr\" },\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"krnl.print\",\n    \"summary\": \"Print a value.\",\n    \"description\": \"This operation can be used to print the input value. The user needs to provide a\\n    format string (à la printf) to specify how to print the input value.\\n    If the input value is not specified the operator will print the format string.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.print_tensor\",\n    \"summary\": \"Print a tensor.\",\n    \"description\": \"This operation can be used to generate a call to a runtime function which prints a tensor.\\n    At the beginning of the msg string, user can add formatting instructions. The flags are:\\n\\n    *  `%s`: detailed signature (including shape, type, offsets),\\n    *  `%t`: compact type (ala MLIR: `32x16xfloat`),\\n    *  `%d`: data values.\\n\\n    When no formatting is provided, `%s%d` is used (detailed signature and data) by default.\\n    Print operation ends with a newline, except when only requesting a compact types (`%t`).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.random_normal\",\n    \"summary\": \"Generate a random normal tensor.\",\n    \"description\": \"Operation that generates a random normally distributed tensor.\",\n    \"operands\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[ AnyMemRef ]>\" },\n      { \"name\": \"numberOfValues\", \"type\": \"Index\" },\n      { \"name\": \"mean\", \"type\": \"AnyFloat\" },\n      { \"name\": \"scale\", \"type\": \"AnyFloat\" },\n      { \"name\": \"seed\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.region\",\n    \"summary\": \"Affine boundary for krnl loops\",\n    \"description\": \"This Op has a region with AffineScope trait and is used to limit the\\n    scope of `affine.for`. The loop inside `krnl.region` can be affined if\\n    its boundary is defined at the level of `krnl.region`. The `krnl.region` does\\n    not guarantee or require the loops inside it to be affine.\\n    With `krnl.region`, a krnl loop may not be  affine if its boundary symbol\\n    is not defined inside a enclosing region without AffineScope trait.\\n    In MLIR, FuncOp has the AffineScope trait.\\n    The `krnl.region` will be removed after affine.for is lowered.\\n    ToFix: current `krnl.region` does not have input and output. You cannot\\n    create a new memref inside the region and use it outside of the region.\",\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.round_even\",\n    \"summary\": \"Krnl round to nearest even operation\",\n    \"description\": \"Krnl round to nearest even operation.  Accept scalar or vector float values.\\n    Vector must be 1D of a size that is a multiple of the hardware vector size.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"FloatLike\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.runtime_instrument\",\n    \"summary\": \"instrumentation point.\",\n    \"description\": \"Operation that invokes the runtime instrument utility.\\n    May be used for gdb.\",\n    \"attributes\": [\n      { \"name\": \"opName\", \"type\": \"StrAttr\" },\n      { \"name\": \"tag\", \"type\": \"I64Attr\" },\n      { \"name\": \"nodeName\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.seqalloc\",\n    \"summary\": \"Krnl create a sequence\",\n    \"description\": \"This op allocates a memref for a new sequence according to the input Type and length.\\n    The output is tagged with Allocate side effect, and a deallocation is defined for\\n    sequence. This deallocation will free all the elements in the sequence as well as\\n    the sequence itself.\",\n    \"operands\": [\n      { \"name\": \"length\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.seqdealloc\",\n    \"summary\": \"Krnl dealloc a sequence\",\n    \"description\": \"This op deallocate the elements in the sequence and the sequence itself\\n    with memref::dealloc. This Op is a deep dealloc for sequence type.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.seqextract\",\n    \"summary\": \"Krnl load from a sequence\",\n    \"description\": \"This op loads an element from the input sequence 'seq' at position 'index'.\\n    The loaded element is copied and then return.\\n    The position value is guaranteed to be positive. Negative position allowed\\n    by ONNX Op definition should be handled before lowered to KrnlSeqExtract.\\n\\n    Attribute 'copy' provides an optimization for copying.\\n    When the attribute 'copy' is 1 (default value): the extracted element is copied and then return.\\n    When the attribute 'copy' is 0: the extracted element is directly returned\\n    without copy.\\n\\n    The returned element is marked as allocated by this Op with the bufferation\\n    interface so that deallocation can be generated correctly through the\\n    Bufferization::Deallocation pass.\",\n    \"operands\": [\n      { \"name\": \"seq\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"copy\", \"type\": \"DefaultValuedAttr<UI1Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.seqstore\",\n    \"summary\": \"Krnl store into a seq\",\n    \"description\": \"This op is similar to KrnSeqInsertOp but assumes that the input seq has\\n    the space for the new element and\\n    only need to copy the element and store it into the sequence.\\n    There is no return of a new seq, different from KrnlSeqInsertOp.\\n    This Op is introduced to accumulate a dynamic tensor in a LoopOp with\\n    statically known iteration count.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyType\" },\n      { \"name\": \"seq\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.specialized_kernel\",\n    \"summary\": \"Krnl specialized kernel op\",\n    \"description\": \"Krnl operation to convert.\",\n    \"operands\": [\n      { \"name\": \"loops\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $loops `)` attr-dict `:` type($loops)\"\n  },\n  {\n    \"name\": \"krnl.store\",\n    \"summary\": \"A Krnl operation to store data to the memref.\",\n    \"description\": \"The `krnl.store` stores a value to a memref location given by indices. The\\n    value stored should have the same type as the elemental type of the memref.\\n    The number of arguments provided within brackets need to match the rank of\\n    the memref.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'memref', 'value', 'mlir::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $memref `[` $indices `]` attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"krnl.strlen\",\n    \"summary\": \"Compute the length of a string.\",\n    \"description\": \"Krnl operation that computes the length of a string.\",\n    \"operands\": [\n      { \"name\": \"str\", \"type\": \"StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I64\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.strncmp\",\n    \"summary\": \"Perform string comparison up to N bytes.\",\n    \"description\": \"Krnl operation that performs a string comparison up to N bytes.\",\n    \"operands\": [\n      { \"name\": \"str1\", \"type\": \"StringType\" },\n      { \"name\": \"str2\", \"type\": \"StringType\" },\n      { \"name\": \"len\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.tan\",\n    \"summary\": \"Krnl tan scalar operation\",\n    \"description\": \"Krnl tan scalar operation.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyFloat\" }\n    ]\n  },\n  {\n    \"name\": \"krnl.terminate\",\n    \"summary\": \"Krnl terminator operation\",\n    \"description\": \"Krnl terminator is a special terminator operation for blocks inside krnl\\n    iterate operations. It unconditionally transmits the control flow to the\\n    successor of the operation enclosing the region.\\n\\n    This operation does _not_ have a custom syntax. However, krnl control\\n    operations omit the terminator in their custom syntax for brevity.\"\n  },\n  {\n    \"name\": \"krnl.unroll\",\n    \"summary\": \"Krnl unroll operation\",\n    \"description\": \"Fully unroll the specified loops.\\n    ```\\n    krnl.unroll %i\\n    ```\\n    unrolls the loop referred to by %i fully.\",\n    \"operands\": [\n      { \"name\": \"loop\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$loop attr-dict `:` type($loop)\"\n  },\n  {\n    \"name\": \"krnl.vector_type_cast\",\n    \"summary\": \"vector type cast operation\",\n    \"description\": \"The \\\"vector_type_cast\\\" operation converts a memref from an non-vector\\n    element type to another memref of a vector elemental type while not changing\\n    the source memref's element type. The last dimension size of the source\\n    dimension is divided (floor division) by the vector size to obtain the\\n    corresponding dimension for target memref type.\\n\\n    ```\\n    %MV = vector_type_cast %M : memref<64x16xf32> to memref<64x2xvector<8xf32>>\\n    %AV = vector_type_cast %A : memref<?x?xf32> to memref<?x?xvector<8xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"krnl.yield\",\n    \"summary\": \"Yield values to parent operation\",\n    \"description\": \"The `krnl.yield` yields zero or more SSA values from an krnl.iterate op region and\\n    terminates the region. The semantics of how the values yielded are used\\n    is defined by the parent operation.\\n    If `krnl.yield` has any operands, the operands must match the parent\\n    operation's results.\\n    If the parent operation defines no values, then the `krnl.yield` may be\\n    left out in the custom syntax and the builders will insert one implicitly.\\n    Otherwise, it has to be present in the syntax to indicate which values are\\n    yielded.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"lagrad.diff\",\n    \"summary\": \"Annotate a function for automatic differentiation via Enzyme\",\n    \"description\": \"The `lagrad.diff` operation annotates a function for automatic differentiation via Enzyme.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"FunctionType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"FunctionType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `,` type($res)\"\n  },\n  {\n    \"name\": \"lagrad.grad\",\n    \"summary\": \"Reverse-mode autodiff a standard function.\",\n    \"description\": \"The `lagrad.grad` operation performs a source transformation to compute the gradient of a func op.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"F\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$F `(` $operands `)` attr-dict `:` functional-type($operands, $results)\"\n  },\n  {\n    \"name\": \"lagrad.pack\",\n    \"summary\": \"convert fully materialized triangular tensor to packed\",\n    \"description\": \"The `lagrad.pack` operation denotes a conversion from a fully materialized strictly lower triangular tensor to a packed triangular tensor.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"lagrad.tangent\",\n    \"summary\": \"Forward-mode autodiff a standard function.\",\n    \"description\": \"The `lagrad.tangent` operation performs a source transformation to compute the forward-mode (tangent) gradient of a function.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"F\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$F `(` $operands `)` attr-dict `:` functional-type($operands, $results)\"\n  },\n  {\n    \"name\": \"layer.box\",\n    \"summary\": \"layer container operation\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"StrAttr\" },\n      { \"name\": \"attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$op `(` $operands `)` attr-dict `:` type($operands) `->` type($results) $body\"\n  },\n  {\n    \"name\": \"layer.return\",\n    \"summary\": \"Return results from a layer\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"linalg.abs\",\n    \"summary\": \"Applies abs(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.add\",\n    \"summary\": \"Adds two tensors elementwise.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.add` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.batch_matmul\",\n    \"summary\": \"Performs a batched matrix multiplication of two 3D inputs.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\n    them to the same data type as the accumulator/output.\\n\\n    Broadcast and Transpose semantics can be appiled by specifying the explicit attribute\\n    'indexing_maps' as shown below. This is a list attribute, so must include maps for all\\n    arguments if specified.\\n\\n    Example Transpose:\\n    ```mlir\\n    linalg.batch_matmul\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (batch, k, m)>, // transpose\\n                         affine_map<(batch, m, n, k) -> (batch, k, n)>,\\n                         affine_map<(batch, m, n, k) -> (batch, m, n)>]\\n        ins(%arg0, %arg1 : memref<2x5x3xf32>,memref<2x5x7xf32>)\\n        outs(%arg2: memref<2x3x7xf32>)\\n    ```\\n\\n    Example Broadcast:\\n    ```mlir\\n    linalg.batch_matmul\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (k)>,           // broadcast\\n                         affine_map<(batch, m, n, k) -> (batch, k, n)>,\\n                         affine_map<(batch, m, n, k) -> (batch, m, n)>]\\n        ins(%arg0, %arg1 : memref<5xf32>, memref<2x5x7xf32>)\\n        outs(%arg2: memref<2x3x7xf32>)\\n    ```\\n\\n    Example Broadcast and Transpose:\\n    ```mlir\\n    linalg.batch_matmul\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (m, k)>,        // broadcast\\n                         affine_map<(batch, m, n, k) -> (batch, n, k)>, // transpose\\n                         affine_map<(batch, m, n, k) -> (batch, m, n)>]\\n        ins(%arg0, %arg1 : memref<3x5xf32>, memref<2x7x5xf32>)\\n        outs(%arg2: memref<2x3x7xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<AffineMapAttr>, BatchMatmulOp::getDefaultIndexingMaps($_builder.getContext())>\" },\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr<TypeFnAttr{cast_signed|cast_unsigned}, TypeFn::cast_signed>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.batch_matvec\",\n    \"summary\": \"Performs a batched matrix-vector multiplication.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.batch_mmt4d\",\n    \"summary\": \"Performs a batched matrix-matrix-transpose multiplication of two\\nbatched-4D (5D) inputs.\",\n    \"description\": \"Besides the outermost batch dimension has the same semantic as\\nlinalg.batch_matmul, the differences from linalg.batch_matmul in the\\nnon-batch dimensions are the same as linalg.mmt4d vs. linalg.matmul. See the\\ndescription of lingalg.mmt4d.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.batch_reduce_matmul\",\n    \"summary\": \"Performs a batch-reduce matrix multiplication on two inputs.\\n    The partial multiplication results are reduced into a 2D output.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply,\\n    promoting them to the same data type as the accumulator/output.\\n\\n    Broadcast and Transpose semantics can be applied by specifying the explicit attribute\\n    'indexing_maps' as shown below. This is a list attribute, so must include maps for all\\n    arguments if specified.\\n\\n    Example Transpose:\\n    ```mlir\\n    linalg.batch_reduce_matmul\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (batch, k, m)>, // transpose\\n                         affine_map<(batch, m, n, k) -> (batch, k, n)>,\\n                         affine_map<(batch, m, n, k) -> (m, n)>]\\n        ins(%arg0, %arg1 : memref<2x5x3xf32>,memref<2x5x7xf32>)\\n        outs(%arg2: memref<3x7xf32>)\\n    ```\\n\\n    Example Broadcast:\\n    ```mlir\\n    linalg.batch_reduce_matmul\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (k)>,         // broadcast\\n                         affine_map<(batch, m, n, k) -> (batch, k, n)>,\\n                         affine_map<(batch, m, n, k) -> (m, n)>]\\n        ins(%arg0, %arg1 : memref<5xf32>, memref<2x5x7xf32>)\\n        outs(%arg2: memref<3x7xf32>)\\n    ```\\n\\n    Example Broadcast and Transpose:\\n    ```mlir\\n    linalg.batch_reduce_matmul\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (m, k)>,        // broadcast\\n                         affine_map<(batch, m, n, k) -> (batch, n, k)>, // transpose\\n                         affine_map<(batch, m, n, k) -> (m, n)>]\\n        ins(%arg0, %arg1 : memref<3x5xf32>, memref<2x7x5xf32>)\\n        outs(%arg2: memref<3x7xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<AffineMapAttr>, BatchReduceMatmulOp::getDefaultIndexingMaps($_builder.getContext())>\" },\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr<TypeFnAttr{cast_signed|cast_unsigned}, TypeFn::cast_signed>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.batch_vecmat\",\n    \"summary\": \"Performs a batched matrix-vector multiplication.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.broadcast\",\n    \"summary\": \"Static broadcast operator\",\n    \"description\": \"Broadcast the input into the given shape by adding `dimensions`.\\n\\n    Example:\\n    ```mlir\\n      %bcast = linalg.broadcast\\n          ins(%input:tensor<16xf32>)\\n          outs(%init:tensor<16x64xf32>)\\n          dimensions = [1]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOrMemref\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.ceil\",\n    \"summary\": \"Applies ceil(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.contract\",\n    \"summary\": \"Perform a contraction on two inputs, accumulating into the third.\",\n    \"description\": \"The semantics of contracting inputs `A` and `B` on top of `C` to produce\\n    output `D` is given by\\n\\n      `D[H] = (SUM_{(I ∪ J) \\\\ H} A[I] * B[J]) + C[H]`\\n\\n    where `I`, `J`, and `H` are tuples of (pairwise distinct) dimension\\n    identifiers - meant to range over valid indices - corresponding to the\\n    results of the mandatory (projected permutation) `indexing_maps` for `A`,\\n    `B` and `C`. `SUM_{dims}` means reduce over all valid indices for the\\n    dimensions in the set `dims` (with `I`, `J`, and `K` treated as _sets_ of\\n    dim identifiers).\\n\\n    The iteration space consists of all dimensions in `I`, `J` and `H`, i.e. the\\n    domain of each of the `affine_map`s. Like for einsums, the iteration type of\\n    each dim is inferred and is either:\\n\\n    - reduction: the dim is used to index into `A` and `B` but not `C`. Per the\\n      above semantics, these dims will be contracted, i.e. reduced over.\\n\\n    - parallel: the dim is used to index into `C` and at least one of `A` and\\n      `B`, and - deriving from matmul terminology - is either an \\\"M-like\\\" dim\\n      (if used on `A` and `C`), an \\\"N-like\\\" dim (if used on `B` and `C`) or a\\n      \\\"batch\\\"-dim (if used to index into `A`, `B`, and `C`).\\n\\n    For example, batch-matmul is given by `I = ⟨ b, m, k ⟩`, `J = ⟨ b, k, n ⟩`,\\n    `H = ⟨ b, m, n ⟩` (with `k` as a contracting reduction-dimension while `m`,\\n    `n` and `b` have parallel iteration-type) and gets represented as:\\n\\n    ```mlir\\n    %D = linalg.contract\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (batch, m, k)>,\\n                         affine_map<(batch, m, n, k) -> (batch, k, n)>,\\n                         affine_map<(batch, m, n, k) -> (batch, m, n)>]\\n        ins(%A, %B: tensor<?x?x?xf32>, tensor<?x?x?xf32>)\\n        outs(%C: tensor<?x?x?xf32>) -> tensor<?x?x?xf32>\\n    ```\\n\\n    Note that by permuting dims in the `affine_map`s' results, accesses to\\n    to the inputs and output can be arbitrarily transposed. Similarly, arbitrary\\n    broadcasts can be achieved through leaving out dims on either input operand.\\n    For example, the following is a variant of batch-matmul with a transposition\\n    applied to `A` while `B`'s 2D-matrix gets broadcasted along the batch dim:\\n\\n    ```mlir\\n    linalg.contract\\n        indexing_maps = [affine_map<(batch, m, n, k) -> (batch, k, m)>,\\n                         affine_map<(batch, m, n, k) -> (k, n)>,\\n                         affine_map<(batch, m, n, k) -> (batch, m, n)>]\\n        ins(%A, %B: memref<?x?x?xf32>, memref<?x?xf32>)\\n        outs(%C: memref<?x?x?xf32>)\\n    ```\\n\\n    Numeric casting is performed on the operands to the inner multiplication,\\n    promoting/truncating them to the same data type as the accumulator/output.\\n\\n    TODO: Allow control over the combining/accumulating op and possibly the\\n          multiplication op.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr<TypeFnAttr{cast_signed|cast_unsigned}, TypeFn::cast_signed>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"combiner\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.conv\",\n    \"summary\": \"\",\n    \"description\": \"\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_1d\",\n    \"summary\": \"Performs 1-D convolution with no channels.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_1d_ncw_fcw\",\n    \"summary\": \"Performs 1-D convolution.\",\n    \"description\": \"Layout:\\n  * Input: NCW.\\n  * Kernel: FCW.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_1d_nwc_wcf\",\n    \"summary\": \"Performs 1-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d\",\n    \"category\": \"Layer\",\n    \"summary\": \"Performs 2-D convolution with no channels.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nchw_fchw\",\n    \"summary\": \"Performs 2-D convolution.\",\n    \"description\": \"Layout:\\n  * Input: NCHW.\\n  * Kernel: FCHW.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nchw_fchw_q\",\n    \"summary\": \"Performs 2-D convolution with zero point offsets.\",\n    \"description\": \"Layout:\\n  * Input: NCHW.\\n  * Kernel: FCHW.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. This includes the zero\\npoint offsets common to quantized operations.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_ngchw_fgchw\",\n    \"summary\": \"Performs 2-D grouped convolution.\",\n    \"description\": \"Layout:\\n  * Input: NGCHW.\\n  * Kernel: FGCHW.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_ngchw_gfchw\",\n    \"summary\": \"Performs 2-D grouped convolution.\",\n    \"description\": \"Layout:\\n  * Input: NGCHW.\\n  * Kernel: GFCHW.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_ngchw_gfchw_q\",\n    \"summary\": \"Performs 2-D grouped convolution with zero-point offsets.\",\n    \"description\": \"Layout:\\n  * Input: NGCHW.\\n  * Kernel: GFCHW.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. This includes the zero\\npoint offsets common to quantized operations.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nhwc_fhwc\",\n    \"summary\": \"Performs 2-D convolution.\",\n    \"description\": \"Layout:\\n  * Input: NHWC.\\n  * Kernel: FHWC.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nhwc_fhwc_q\",\n    \"summary\": \"Performs 2-D convolution with zero point offsets.\",\n    \"description\": \"Layout:\\n  * Input: NHWC.\\n  * Kernel: FHWC.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. This includes the zero\\npoint offsets common to quantized operations.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nhwc_hwcf\",\n    \"summary\": \"Performs 2-D convolution.\",\n    \"description\": \"Layout:\\n  * Input: NHWC.\\n  * Kernel: HWCF.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nhwc_hwcf_q\",\n    \"summary\": \"Performs 2-D convolution with zero point offsets.\",\n    \"description\": \"Layout:\\n  * Input: NHWC.\\n  * Kernel: HWCF.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. This includes the zero\\npoint offsets common to quantized operations.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nhwgc_gfhwc\",\n    \"summary\": \"Performs 2-D grouped convolution.\",\n    \"description\": \"Layout:\\n  * Input: NHWGC.\\n  * Kernel: GFHWC.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_2d_nhwgc_gfhwc_q\",\n    \"summary\": \"Performs 2-D grouped convolution with zero point offsets.\",\n    \"description\": \"Layout:\\n  * Input: NHWGC.\\n  * Kernel: GFHWC.\\n\\nNumeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. This includes the zero\\npoint offsets common to quantized operations.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_3d\",\n    \"summary\": \"Performs 3-D convolution with no channels.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_3d_ncdhw_fcdhw\",\n    \"summary\": \"Performs 3-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_3d_ndhwc_dhwcf\",\n    \"summary\": \"Performs 3-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.conv_3d_ndhwc_dhwcf_q\",\n    \"summary\": \"Performs 3-D convolution with zero point offsets.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. This includes the zero\\npoint offsets common to quantized operations.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.copy\",\n    \"summary\": \"Copies the tensor elementwise.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_1d_ncw_cw\",\n    \"summary\": \"Performs depth-wise 1-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. Multiplier is set to 1\\nwhich is a special case for most depthwise convolutions.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_1d_nwc_wc\",\n    \"summary\": \"Performs depth-wise 1-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. Multiplier is set to 1\\nwhich is a special case for most depthwise convolutions.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_1d_nwc_wcm\",\n    \"summary\": \"Performs depth-wise 1-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_2d_nchw_chw\",\n    \"summary\": \"Performs depth-wise 2-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. Multiplier is set to 1\\nwhich is a special case for most depthwise convolutions.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_2d_nhwc_hwc\",\n    \"summary\": \"Performs depth-wise 2-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. Multiplier is set to 1\\nwhich is a special case for most depthwise convolutions.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_2d_nhwc_hwc_q\",\n    \"summary\": \"Performs depth-wise 2-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_2d_nhwc_hwcm\",\n    \"summary\": \"Performs depth-wise 2-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_2d_nhwc_hwcm_q\",\n    \"summary\": \"Performs depth-wise 2-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_3d_ncdhw_cdhw\",\n    \"summary\": \"Performs depth-wise 3-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. Multiplier is set to 1\\nwhich is a special case for most depthwise convolutions.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_3d_ndhwc_dhwc\",\n    \"summary\": \"Performs depth-wise 3-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. Multiplier is set to 1\\nwhich is a special case for most depthwise convolutions.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.depthwise_conv_3d_ndhwc_dhwcm\",\n    \"summary\": \"Performs depth-wise 3-D convolution.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.div\",\n    \"summary\": \"Divides the first tensor by the second tensor, elementwise.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.div` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.div_unsigned\",\n    \"summary\": \"Divides the first tensor by the second tensor, elementwise. For integer\\ntypes, performs an unsigned division.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.div` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.dot\",\n    \"summary\": \"Performs a dot product of two vectors to a scalar result.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.elementwise\",\n    \"summary\": \"Performs element-wise operation\",\n    \"description\": \"The attribute `kind` describes arithmetic operation to perform. The\\n    operation kind can be unary (e.g. max), binary (e.g. add) or ternary\\n    (e.g. select).\\n\\n    By default, all indexing maps are identities. In the case of default\\n    indexing map, all input and output shapes must match. The number of dims in\\n    each of the identity maps is equal to the rank of the output type.\\n\\n    Affine-maps for operands and result are required to be provided by the user\\n    when a transpose and/or broadcast is needed on any operand. When a map is not\\n    provided, default identity maps are inferred for each operand.\\n\\n    Iterator-types are always all `parallel`.\\n    Iterator-types are needed for constructing the underlying structured op.\\n\\n    The number of dims of the iterator-types are inferred from the rank of\\n    the result type.\\n\\n    Example:\\n\\n    Defining a unary linalg.elementwise with default indexing-map:\\n    ```mlir\\n    %exp = linalg.elementwise\\n        kind=#linalg.elementwise_kind<exp>\\n        ins(%x : tensor<4x16x8xf32>)\\n        outs(%y: tensor<4x16x8xf32>) -> tensor<4x16x8xf32>\\n    ```\\n\\n    Defining a binary linalg.elementwise with user-defined indexing-map:\\n    ```mlir\\n    %add = linalg.elementwise\\n        kind=#linalg.elementwise_kind<add>\\n        indexing_maps = [#transpose, #broadcast, #identity]\\n        ins(%exp, %arg1 : tensor<4x16x8xf32>, tensor<4x16xf32>)\\n        outs(%arg2: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"ElementwiseKindAttr\" },\n      { \"name\": \"indexing_maps\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<AffineMapAttr>, {}>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.erf\",\n    \"summary\": \"Applies erf(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.exp\",\n    \"summary\": \"Applies exp(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.fill\",\n    \"summary\": \"Fills the output tensor with the given value.\",\n    \"description\": \"Works for arbitrary ranked output tensors since the operation performs scalar\\naccesses only and is thus rank polymorphic. Numeric casting is performed on\\nthe value operand, promoting it to the same data type as the output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.fill_rng_2d\",\n    \"summary\": \"Fills the output tensor with pseudo random numbers.\",\n    \"description\": \"The operation generations pseudo random numbers using a linear congruential\\ngenerator. It provides no guarantees regarding the distribution of the\\ngenerated random numbers. Instead of generating the random numbers\\nsequentially, it instantiates one random number generator per data element\\nand runs them in parallel. The seed operand and the indices of the data\\nelement seed the random number generation. The min and max operands limit\\nthe range of the generated random numbers.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.floor\",\n    \"summary\": \"Applies floor(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.generic\",\n    \"description\": \"Generic Linalg op form where the key properties of the computation are\\n    specified as attributes. In pretty form, a `linalg.generic` op is written\\n    as:\\n\\n      ```mlir\\n      linalg.generic #trait_attribute\\n          ins(%A, %B : memref<?x?xf32, stride_specification>,\\n                       memref<?x?xf32, stride_specification>)\\n          outs(%C : memref<?x?xf32, stride_specification>)\\n          attrs = {other-optional-attributes}\\n          {region}\\n      ```\\n\\n    Where #trait_attributes is an alias of a dictionary attribute containing:\\n      - doc [optional]: a documentation string\\n      - indexing_maps: a list of AffineMapAttr, one AffineMapAttr per each input\\n        and output view. Such AffineMapAttr specifies the mapping between the\\n        loops and the indexing within each view.\\n      - library_call [optional]: a StringAttr containing the name of an\\n        external library function that the linalg.generic operation maps to.\\n        The external library is assumed to be dynamically linked and no strong\\n        compile-time guarantees are provided. In the absence of such a library\\n        call, linalg.generic will always lower to loops.\\n      - iterator_types: an ArrayAttr specifying the type of the enclosing loops.\\n        Each element of the list represents and iterator of one of the following\\n        types:\\n          parallel, reduction, window\\n\\n    Example:\\n    Defining a #matmul_trait attribute in MLIR can be done as follows:\\n      ```mlir\\n      #matmul_accesses = [\\n        (m, n, k) -> (m, k),\\n        (m, n, k) -> (k, n),\\n        (m, n, k) -> (m, n)\\n      ]\\n      #matmul_trait = {\\n        doc = \\\"C(m, n) += A(m, k) * B(k, n)\\\",\\n        indexing_maps = #matmul_accesses,\\n        library_call = \\\"linalg_matmul\\\",\\n        iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"reduction\\\"]\\n      }\\n      ```\\n\\n    And can be reused in multiple places as:\\n      ```mlir\\n      linalg.generic #matmul_trait\\n        ins(%A, %B : memref<?x?xf32, stride_specification>,\\n                     memref<?x?xf32, stride_specification>)\\n        outs(%C : memref<?x?xf32, stride_specification>)\\n        {other-optional-attributes} {\\n        ^bb0(%a: f32, %b: f32, %c: f32) :\\n          %d = arith.mulf %a, %b: f32\\n          %e = arith.addf %c, %d: f32\\n          linalg.yield %e : f32\\n      }\\n      ```\\n\\n    This may lower to either:\\n      ```mlir\\n      call @linalg_matmul(%A, %B, %C) :\\n        (memref<?x?xf32, stride_specification>,\\n         memref<?x?xf32, stride_specification>,\\n         memref<?x?xf32, stride_specification>)\\n        -> ()\\n      ```\\n\\n    or IR resembling:\\n    ```mlir\\n    scf.for %m = %c0 to %M step %c1 {\\n      scf.for %n = %c0 to %N step %c1 {\\n        scf.for %k = %c0 to %K step %c1 {\\n          %a = load %A[%m, %k] : memref<?x?xf32, stride_specification>\\n          %b = load %B[%k, %n] : memref<?x?xf32, stride_specification>\\n          %c = load %C[%m, %n] : memref<?x?xf32, stride_specification>\\n          %d = arith.mulf %a, %b: f32\\n          %e = arith.addf %c, %d: f32\\n          store %e, %C[%m, %n] : memref<?x?x?xf32, stride_specification>\\n        }\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"iterator_types\", \"type\": \"TypedArrayAttrBase<IteratorTypeEnum{parallel|reduction}>\" },\n      { \"name\": \"doc\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"library_call\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.index\",\n    \"summary\": \"linalg index operation\",\n    \"description\": \"The `linalg.index` operation returns the iteration index of the immediately\\n    enclosing linalg structured operation for the iteration dimension `dim`. The\\n    `dim` attribute specifies the position of the accessed dimension in the\\n    indexing map domain.\\n\\n    Example:\\n\\n    ```mlir\\n    #map = affine_map<(i, j) -> (i, j)>\\n    linalg.generic {indexing_maps = [#map, #map],\\n                    iterator_types = [\\\"parallel\\\", \\\"parallel\\\"]}\\n      outs(%I, %J : memref<?x?xindex>, memref<?x?xindex>) {\\n      ^bb0(%arg0 : index, %arg1 : index):\\n      // Access the outer iteration dimension i\\n      %i = linalg.index 0 : index\\n      // Access the inner iteration dimension j\\n      %j = linalg.index 1 : index\\n      linalg.yield %i, %j : index, index\\n    }\\n    ```\\n\\n    This may lower to IR resembling:\\n\\n    ```mlir\\n    %0 = dim %I, %c0 : memref<?x?xindex>\\n    %1 = dim %I, %c1 : memref<?x?xindex>\\n    scf.for %i = %c0 to %0 step %c1 {\\n      scf.for %j = %c0 to %1 step %c1 {\\n        store %i, %I[%i, %j] : memref<?x?xindex>\\n        store %j, %J[%i, %j] : memref<?x?xindex>\\n      }\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" }\n    ],\n    \"assemblyFormat\": \"$dim attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"linalg.init_tensor\",\n    \"summary\": \"Replace all init_tensor ops by alloc_tensor ops.\",\n    \"description\": \"init_tensor ops return a tensor of unspecified contents who's only purpose is to carry the tensor shape. This pass converts such ops to bufferization.alloc_tensor ops, which bufferize to buffer allocations.\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.log\",\n    \"summary\": \"Applies log(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.map\",\n    \"summary\": \"Elementwise operations\",\n    \"description\": \"Models elementwise operations on tensors in terms of arithmetic operations\\n    on the corresponding elements.\\n\\n    Example:\\n    ```mlir\\n      %add = linalg.map\\n          ins(%lhs, %rhs : tensor<64xf32>, tensor<64xf32>)\\n          outs(%init: tensor<64xf32>)\\n          (%lhs_elem: f32, %rhs_elem: f32) {\\n            %0 = arith.addf %lhs_elem, %rhs_elem: f32\\n            linalg.yield %0: f32\\n          }\\n    ```\\n\\n    Shortened print form is available for simple maps where the body contains exactly\\n    two operations (the payload operation and a yield), the payload operation has\\n    the same number of operands as block arguments with operands matching block\\n    arguments in order, and the yield operand is the result of the payload operation.\\n\\n    The example above will be printed using the shortened form as:\\n    ```mlir\\n      %add = linalg.map { arith.addf }\\n          ins(%lhs, %rhs : tensor<64xf32>, tensor<64xf32>)\\n          outs(%init: tensor<64xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorOrMemref>\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"mapper\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.matmul\",\n    \"summary\": \"Performs a matrix multiplication of two 2D inputs without broadcast or transpose.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply,\\n    promoting them to the same data type as the accumulator/output.\\n\\n    Broadcast and Transpose semantics can be appiled by specifying the explicit attribute\\n    'indexing_maps' as shown below.This is a list attribute, so the list must include all\\n    the maps if specified.\\n\\n    Example Transpose:\\n    ```mlir\\n    linalg.matmul\\n        indexing_maps = [affine_map<(m, n, k) -> (k, m)>, // transpose\\n                         affine_map<(m, n, k) -> (k, n)>,\\n                         affine_map<(m, n, k) -> (m, n)>]\\n        ins(%arg0, %arg1 : memref<5x3xf32>,memref<5x7xf32>)\\n        outs(%arg2: memref<3x7xf32>)\\n     ```\\n\\n    Example Broadcast:\\n     ```mlir\\n    linalg.matmul\\n        indexing_maps = [affine_map<(m, n, k) -> (k)>,     // broadcast\\n                         affine_map<(m, n, k) -> (k, n)>,\\n                         affine_map<(m, n, k) -> (m, n)>]\\n        ins(%arg0, %arg1 : memref<3xf32>, memref<5x7xf32>)\\n        outs(%arg2: memref<3x7xf32>)\\n    ```\\n\\n    Example Broadcast and transpose:\\n    ```mlir\\n    linalg.matmul\\n        indexing_maps = [affine_map<(m, n, k) -> (k, m)>, // transpose\\n                         affine_map<(m, n, k) -> (k)>,    // broadcast\\n                         affine_map<(m, n, k) -> (m, n)>]\\n        ins(%arg0, %arg1 : memref<5x3xf32>, memref<7xf32>)\\n        outs(%arg2: memref<3x7xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<AffineMapAttr>, MatmulOp::getDefaultIndexingMaps($_builder.getContext())>\" },\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr<TypeFnAttr{cast_signed|cast_unsigned}, TypeFn::cast_signed>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.matmul_transpose_a\",\n    \"category\": \"Layer\",\n    \"summary\": \"Performs a matrix multiplication with transposed LHS.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr<TypeFnAttr{cast_signed|cast_unsigned}, TypeFn::cast_signed>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.matmul_transpose_b\",\n    \"summary\": \"Performs a matrix multiplication with transposed RHS.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cast\", \"type\": \"DefaultValuedOptionalAttr<TypeFnAttr{cast_signed|cast_unsigned}, TypeFn::cast_signed>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.matvec\",\n    \"summary\": \"Performs a matrix-vector multiplication.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.max\",\n    \"summary\": \"Takes the max (signed) between two inputs, elementwise.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.max` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.min\",\n    \"summary\": \"Takes the min (signed) between two inputs, elementwise.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.min` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.mmt4d\",\n    \"summary\": \"Performs a matrix-matrix-transpose multiplication of two 4D inputs.\",\n    \"description\": \"Differences from linalg.matmul:\\n* The right hand side is transposed, whence the 't' in 'mmt'.\\n* The input and output tensors have a 4D shape instead of a 2D shape. They\\n  are interpreted as 2D matrices with one level of 2D tile subdivision,\\n  whence the 2+2=4 dimensions. The inner tile dimensions are identified with\\n  '0' suffixes below, for instance the LHS matrix shape (M, K, M0, K0) reads\\n  as: MxK tiles, each of shape M0xK0.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.mul\",\n    \"summary\": \"Multiplies two tensors elementwise.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.mul` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.negf\",\n    \"summary\": \"Applies negf(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pack\",\n    \"summary\": \"linalg.pack operation\",\n    \"description\": \"The \\\"pack\\\" operation converts a source tensor of rank `n` into a result\\n    tensor of rank `n + k` with a tiled and packed layout (maybe with padding)\\n    and optionally transposes the tiled source tensor dimensions.\\n\\n    `inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes\\n    correspond to the least significant (\\\"inner\\\") result tensor dimension sizes,\\n    in the same order. Tile sizes can be static or dynamic.\\n\\n    `inner_dims_pos` (mandatory) specifies `k` source tensor dimensions that are\\n    being tiled, where `0 <= k <= n`.\\n     - `inner_dims_pos[i]` specifies the source tensor dimension tiled by\\n    `inner_tiles[i]` where `0 <= i < k`. All the values in `inner_dims_pos` are\\n    within [0, n).\\n     - The tiled dimensions (of size `inner_tiles`) are added to the end of the\\n     result tensor in the order in which they appear, i.e.\\n     `shape(result)[rank(source) + i] = inner_tiles[i]` for `0 <= i < k`.\\n     - The following relationship for the tiled dimensions holds:\\n     `shape(result)[inner_dims_pos[i]] = shape(source)[inner_dims_pos[i]] / inner_tiles[i]`,\\n     where (⌈/⌉ indicates CeilDiv).\\n\\n\\n    Example: If `inner_tiles = [16, 32]`, the result tensor has a shape of\\n    `...x16x32`. If `inner_dims_pos = [0, 1]`, the 0th source dimension is tiled\\n    by 16 and the 1st source dimension is tiled by 32. Other source dimensions\\n    (if any) are not tiled. If `inner_dims_pos = [1, 0]`, the 1st dimension is\\n    tiled by 16 and the 0th dimension is tiled by 32.\\n\\n    Example:\\n    ```mlir\\n    // NC to NCnc\\n    %0 = linalg.pack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]\\n        into %dest : tensor<128x256xf32> -> tensor<16x8 x 8x32 xf32>\\n    //                                             \\\\  /   \\\\  /\\n    //                                 Outer Dims: 16x8   Inner Dims: 8x32\\n\\n    // CHW to CHWhw\\n    %0 = linalg.pack %source inner_dims_pos = [2, 1] inner_tiles = [4, 2]\\n        into %dest : tensor<3x20x24xf32> -> tensor<3x10x6 x 4x2 xf32>\\n    //                                              \\\\  /    \\\\ /\\n    //                                 Outer Dims: 3x10x6  Inner Dims: 4x2\\n\\n    // HCW to HCWhw\\n    %0 = linalg.pack %source inner_dims_pos = [2, 0] inner_tiles = [4, 2]\\n        into %dest : tensor<18x3x32xf32> -> tensor<9x3x8 x 4x2 xf32>\\n    //                                              \\\\  /   \\\\ /\\n    //                                 Outer Dims: 9x3x8  Inner Dims: 4x2\\n    ```\\n\\n    `outer_dims_perm` (optional) specifies a permutation for the outer\\n    dimensions. If specified, it must have `n` elements.\\n\\n    Example:\\n    ```mlir\\n    // CK to KCck\\n    %0 = linalg.pack %source outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]\\n        inner_tiles = [8, 32] into %dest\\n        : tensor<128x256xf32> -> tensor<8x16 x 8x32 xf32>\\n    //                                  \\\\  /\\n    //            compare with \\\"NC to NCnc\\\": outer dims are transposed\\n    ```\\n\\n    `padding_value` specifies a padding value at the boundary on non-perfectly\\n    divisible dimensions. Padding is optional:\\n    - If absent, it is assumed that for all inner tiles,\\n      `shape(source)[inner_dims_pos[i]] % inner_tiles[i] == 0`, i.e. all inner\\n      tiles divide perfectly the corresponding outer dimension in the result\\n      tensor. It is UB if the tile does not perfectly divide the dimension.\\n    - If present, it will pad along high dimensions (high-padding) to make the\\n      tile complete. Note that it is not allowed to have artificial padding that\\n      is not strictly required by linalg.pack (i.e., padding past what is needed\\n      to complete the last tile along each packed dimension). It is UB if extra\\n      padding is requested.\\n    It is not possible to verify the requirements statically with dynamic\\n    shapes, so they are treated as UB.\\n\\n    Example:\\n    ```mlir\\n    %0 = linalg.pack %arg0 padding_value(%pad : f32) outer_dims_perm = [2, 1, 0]\\n        inner_dims_pos = [1] inner_tiles = [2] into %arg1\\n        : tensor<200x127x256xf32> -> tensor<256x64x200x2xf32>\\n    //                 \\\\\\n    //                padded and tiled dim\\n    //\\n    // Source dimension 1 is tiled. 64 does not divide 127 evenly, so 1 padded\\n    // element is added at the end.\\n    //\\n    // Note: Only tiled dimensions can be padded.\\n    ```\\n\\n    Invalid example that has artificial padding:\\n    ```mlir\\n    %0 = linalg.pack %src padding_value(%cst : f32) inner_dims_pos = [0]\\n        inner_tiles = [8] into %dest\\n        : tensor<9xf32> -> tensor<3x8xf32>\\n    //                             \\\\\\n    //            expect tensor<2x8xf32> because CeilDiv(9, 8) = 2\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"TensorOrMemRef<[AnyType]>\" },\n      { \"name\": \"dest\", \"type\": \"TensorOrMemRef<[AnyType]>\" },\n      { \"name\": \"padding_value\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"inner_tiles\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outer_dims_perm\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"inner_dims_pos\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_inner_tiles\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'dest', 'result', '$_self'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.pooling_nchw_max\",\n    \"summary\": \"Performs max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nchw_sum\",\n    \"summary\": \"Performs sum pooling.\",\n    \"description\": \"Layout:\\n  * Input: NCHW.\\n  * Kernel: HW.\\n\\nNumeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_ncw_max\",\n    \"summary\": \"Performs max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_ncw_sum\",\n    \"summary\": \"Performs sum pooling.\",\n    \"description\": \"Layout:\\n  * Input: NCW.\\n  * Kernel: W.\\n\\nNumeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_ndhwc_max\",\n    \"summary\": \"Performs 3D max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_ndhwc_min\",\n    \"summary\": \"Performs 3D min pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_ndhwc_sum\",\n    \"summary\": \"Performs 3D sum pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nhwc_max\",\n    \"summary\": \"Performs max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nhwc_max_unsigned\",\n    \"summary\": \"Performs unsigned max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nhwc_min\",\n    \"summary\": \"Performs min pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nhwc_min_unsigned\",\n    \"summary\": \"Performs unsigned min pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nhwc_sum\",\n    \"summary\": \"Performs sum pooling.\",\n    \"description\": \"Layout:\\n  * Input: NHWC.\\n  * Kernel: HW.\\n\\nNumeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nwc_max\",\n    \"summary\": \"Performs max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nwc_max_unsigned\",\n    \"summary\": \"Performs unsigned max pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nwc_min\",\n    \"summary\": \"Performs min pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nwc_min_unsigned\",\n    \"summary\": \"Performs unsigned min pooling.\",\n    \"description\": \"Numeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.pooling_nwc_sum\",\n    \"summary\": \"Performs sum pooling.\",\n    \"description\": \"Layout:\\n  * Input: NWC.\\n  * Kernel: W.\\n\\nNumeric casting is performed on the input operand, promoting it to the same\\ndata type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"DefaultValuedOptionalAttr\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.powf\",\n    \"summary\": \"Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.square`.\",\n    \"description\": \"Only applies to floating point values.\\n\\nThe shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.powf` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.quantized_batch_matmul\",\n    \"summary\": \"Performs a batched matrix multiplication of two 3D inputs.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. The quantized variant\\nincludes zero-point adjustments for the left and right operands of the\\nmatmul.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.quantized_matmul\",\n    \"summary\": \"Performs a matrix multiplication of two 2D inputs.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output. The quantized variant\\nincludes zero-point adjustments for the left and right operands of the\\nmatmul.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.reciprocal\",\n    \"summary\": \"Applies reciprocal(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.reduce\",\n    \"summary\": \"Reduce operator\",\n    \"description\": \"Executes `combiner` on the `dimensions` of `inputs` and returns the\\n    reduced result. The `dimensions` attribute needs to list the reduction\\n    dimensions in increasing order.\\n\\n    Example:\\n    ```mlir\\n      %reduce = linalg.reduce\\n          ins(%input:tensor<16x32x64xf32>)\\n          outs(%init:tensor<16x64xf32>)\\n          dimensions = [1]\\n          (%in: f32, %out: f32) {\\n            %0 = arith.addf %out, %in: f32\\n            linalg.yield %0: f32\\n          }\\n    ```\\n\\n    Shortened print form is available for simple reduces where the body contains exactly\\n    two operations (the payload operation and a yield), the payload operation has the\\n    same number of operands as block arguments, the first block argument (init) is the\\n    last operand of the payload operation with remaining operands matching remaining\\n    block arguments in order, and the yield operand is the result of the payload operation.\\n\\n    The example above will be printed using the shortened form as:\\n    ```mlir\\n      %reduce = linalg.reduce { arith.addf }\\n          ins(%input:tensor<16x32x64xf32>)\\n          outs(%init:tensor<16x64xf32>)\\n          dimensions = [1]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorOrMemref>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<TensorOrMemref>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlySorted<DenseI64ArrayAttr>]>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"combiner\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.round\",\n    \"summary\": \"Applies round(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.rsqrt\",\n    \"summary\": \"Applies rsqrt(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.select\",\n    \"summary\": \"Chooses one value based on a binary condition supplied as its first operand.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.select` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.softmax\",\n    \"category\": \"Activation\",\n    \"summary\": \"Softmax operator\",\n    \"description\": \"linalg.softmax computes a numerically stable version of softmax.\\n\\n    For a given input tensor and a specified dimension `d`, compute:\\n      1. the max `m` along that dimension `d`\\n      2. f(x) = exp(x - m)\\n      3. sum f(x) along dimension d to get l(x).\\n      4. compute the final result f(x) / l(x).\\n\\n    This is an aggregate linalg operation that further reduces to a small DAG of\\n    structured operations.\\n\\n    Warning: Regarding the tiling capabilities, the implementation doesn't\\n    check that the provided dimensions make sense. This is the responsability\\n    of the transformation calling the tiling to ensure that the provided\\n    sizes for each dimension make sense with respect to the semantic of\\n    softmax.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" },\n      { \"name\": \"output\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    (`->` type($result)^)?\"\n  },\n  {\n    \"name\": \"linalg.sqrt\",\n    \"summary\": \"Applies sqrt(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.square\",\n    \"summary\": \"Applies square(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.sub\",\n    \"summary\": \"Subtracts two tensors elementwise.\",\n    \"description\": \"The shapes and element types must be identical. The appropriate casts,\\nbroadcasts and reductions should be done previously to calling this op.\\n\\nThis means reduction/broadcast/element cast semantics is explicit. Further\\npasses can take that into account when lowering this code. For example,\\na `linalg.broadcast` + `linalg.sub` sequence can be lowered to a\\n`linalg.generic` with different affine maps for the two operands.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"Applies tanh(x) elementwise.\",\n    \"description\": \"No numeric casting is performed on the input operand.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"Transpose operator\",\n    \"description\": \"Permutes the dimensions of `input` according to the given `permutation`.\\n      `dim(result, i) = dim(input, permutation[i])`\\n\\n    This op actually moves data, unlike `memref.transpose` which is a metadata\\n    operation only that produces a transposed \\\"view\\\".\\n\\n    Example:\\n    ```mlir\\n      %transpose = linalg.transpose\\n          ins(%input:tensor<16x64xf32>)\\n          outs(%init:tensor<64x16xf32>)\\n          permutation = [1, 0]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOrMemref\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.unpack\",\n    \"summary\": \"linalg.unpack operation\",\n    \"description\": \"The \\\"unpack\\\" operation converts a source tensor of rank `n` with a tiled and\\n    packed layout to a result tensor of rank `n - k`.\\n\\n    `inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes\\n    correspond to the least significant (\\\"inner\\\") source tensor dimension sizes.\\n    The behavior of this op is undefined if:\\n    - `inner_tiles` do not exactly match with the corresponding source tensor\\n      dimension sizes.\\n    - Or, `inner_tiles[i]` does not divide the size of dimension\\n      `inner_dims_pos[i]` (assuming that `outer_dims_perm` is not specified)\\n      evenly.\\n\\n    `inner_dims_pos` (mandatory) specifies `k` result tensor (i.e. unpacked\\n    tensor) dimensions that were tiled with the `inner_tiles` to create the\\n    packed source tensor. The source tensor (i.e. packed tensor) dimensions can\\n    be unpacked given `inner_dims_pos` as follows.\\n    - For `0 <= i < k` the following relationship holds:\\n    `shape(result)[inner_dims_pos[i]] <= shape(source)[n-k+i] * shape(source)[inner_dims_pos[i]]`.\\n    - For `0 <= j < n-k` and `j` not in `inner_dims_pos` the following relationship holds:\\n    `shape(result)[j] = shape(source)[j]`.\\n\\n    `outer_dims_perm` (optional) specifies a permutation for the outer\\n    dimensions. If specified, it must have `n - k` elements. If specified, this\\n    permutation is applied before combining any dimensions.\\n\\n    Note, the unpack operation may drop any padding introduced by the pack\\n    operation and hence the following holds\\n    `NumElementsOf(source) >= NumElementsOf(result)`.\\n\\n    Examples:\\n\\n    ```mlir\\n    // NCnc to NC:\\n    %0 = linalg.unpack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]\\n        into %dest : tensor<16x8 x 8x32 xf32> -> tensor<128x256xf32>\\n    //                      \\\\  /   \\\\  /\\n    //          Outer Dims: 16x8  Inner Dims: 8x32\\n\\n    // CK to KCck:\\n    %0 = linalg.unpack %source outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]\\n        inner_tiles = [8, 32]\\n        into %dest : tensor<8x16 x 8x32 xf32> -> tensor<128x256xf32>\\n    //                      \\\\  /   \\\\  /\\n    //          Outer Dims: 8x16  Inner Dims: 8x32\\n\\n    // CHW to CHWhw:\\n    %0 = linalg.unpack %source inner_dims_pos = [2, 1] inner_tiles = [4, 2]\\n        into %dest : tensor<3x10x6 x 4x2 xf32> -> tensor<3x20x24xf32>\\n    //                       \\\\  /    \\\\ /\\n    //          Outer Dims: 3x10x6  Inner Dims: 4x2\\n\\n    // HCW to HCWhw\\n    %0 = linalg.unpack %source inner_dims_pos = [2, 0] inner_tiles = [4, 2]\\n        into %dest : tensor<9x3x8 x 4x2 xf32> -> tensor<18x3x32xf32>\\n    //                       \\\\  /   \\\\ /\\n    //          Outer Dims: 9x3x8   Inner Dims: 4x2\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"TensorOrMemRef<[AnyType]>\" },\n      { \"name\": \"dest\", \"type\": \"TensorOrMemRef<[AnyType]>\" },\n      { \"name\": \"inner_tiles\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outer_dims_perm\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"inner_dims_pos\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_inner_tiles\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'dest', 'result', '$_self'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalg.vecmat\",\n    \"summary\": \"Performs a vector-matrix multiplication.\",\n    \"description\": \"Numeric casting is performed on the operands to the inner multiply, promoting\\nthem to the same data type as the accumulator/output.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensors\", \"type\": \"Variadic\" }\n    ],\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"linalg.winograd_filter_transform\",\n    \"summary\": \"Winograd filter transform operator\",\n    \"description\": \"Winograd Conv2D algorithm will convert linalg Conv2D operator into batched\\n    matrix multiply. Before the matrix multiply, it will convert filter and\\n    input into a format suitable for batched matrix multiply. After the matrix\\n    multiply, it will convert output to the final result tensor.\\n\\n    The algorithm F(m x m, r x r) is\\n\\n    Y = A^T x [(G x g x G^T) @ (B^T x d x B)] x A\\n\\n    The size of output Y is m x m. The size of filter g is r x r. The size of\\n    input d is (m + r - 1) x (m + r - 1). A^T, A, G^T, G, B^T, and B are\\n    transformation matrices.\\n\\n    This operator is defined to represent the high level concept of filter\\n    transformation (G x g x G^T) in the Winograd Conv2D algorithm.\",\n    \"operands\": [\n      { \"name\": \"filter\", \"type\": \"TensorRankOf<[AnyType], [4]>\" },\n      { \"name\": \"output\", \"type\": \"TensorRankOf<[AnyType], [4]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRankOf<[AnyType], [4]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmr\", \"type\": \"WinogradConv2DFmr{F_2_3|F_4_3|F_2_5}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `fmr` `(` $fmr `)`\\n    `ins` `(` $filter `:` type($filter) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    `->` type($result)\"\n  },\n  {\n    \"name\": \"linalg.winograd_input_transform\",\n    \"summary\": \"Winograd input transform operator\",\n    \"description\": \"Winograd Conv2D algorithm will convert linalg Conv2D operator into batched\\n    matrix multiply. Before the matrix multiply, it will convert filter and\\n    input into a format suitable for batched matrix multiply. After the matrix\\n    multiply, it will convert output to the final result tensor.\\n\\n    The algorithm F(m x m, r x r) is\\n\\n    Y = A^T x [(G x g x G^T) @ (B^T x d x B)] x A\\n\\n    The size of output Y is m x m. The size of filter g is r x r. The size of\\n    input d is (m + r - 1) x (m + r - 1). A^T, A, G^T, G, B^T, and B are\\n    transformation matrices.\\n\\n    This operator is defined to represent the high level concept of input\\n    transformation (B^T x d x B) in the Winograd Conv2D algorithm.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRankOf<[AnyType], [4]>\" },\n      { \"name\": \"output\", \"type\": \"TensorRankOf<[AnyType], [6]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRankOf<[AnyType], [6]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmr\", \"type\": \"WinogradConv2DFmr{F_2_3|F_4_3|F_2_5}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `fmr` `(` $fmr `)`\\n    `ins` `(` $input `:` type($input) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    `->` type($result)\"\n  },\n  {\n    \"name\": \"linalg.winograd_output_transform\",\n    \"summary\": \"Winograd output transform operator\",\n    \"description\": \"Winograd Conv2D algorithm will convert linalg Conv2D operator into batched\\n    matrix multiply. Before the matrix multiply, it will convert filter and\\n    input into a format suitable for batched matrix multiply. After the matrix\\n    multiply, it will convert output to the final result tensor.\\n\\n    The algorithm F(m x m, r x r) is\\n\\n    Y = A^T x [(G x g x G^T) @ (B^T x d x B)] x A\\n\\n    The size of output Y is m x m. The size of filter g is r x r. The size of\\n    input d is (m + r - 1) x (m + r - 1). A^T, A, G^T, G, B^T, and B are\\n    transformation matrices.\\n\\n    This operator is defined to represent the high level concept of output\\n    transformation (A^T x y x A) in the Winograd Conv2D algorithm.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TensorRankOf<[AnyType], [6]>\" },\n      { \"name\": \"output\", \"type\": \"TensorRankOf<[AnyType], [4]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRankOf<[AnyType], [4]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmr\", \"type\": \"WinogradConv2DFmr{F_2_3|F_4_3|F_2_5}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `fmr` `(` $fmr `)`\\n    `ins` `(` $value `:` type($value) `)`\\n    `outs` `(` $output `:` type($output) `)`\\n    `->` type($result)\"\n  },\n  {\n    \"name\": \"linalg.yield\",\n    \"summary\": \"Linalg yield operation\",\n    \"description\": \"`linalg.yield` is a special terminator operation for blocks inside regions\\n    in `linalg` generic ops. It returns values to the immediately enclosing\\n    `linalg` generic op.\\n\\n    Example:\\n\\n    ```mlir\\n    linalg.yield %f0, %f1 : f32, f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"linalgx.copy\",\n    \"summary\": \"tensor copy operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inputMap\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"outputMap\", \"type\": \"OptionalAttr<AffineMapAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`(` $input `,` $output `)` attr-dict `:` type($input) `,` type($output)\\n      `->` type($result)\\n      custom<CopyOpRegion>($region, ref(type($input)), ref(type($input)))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.add\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"LLVM_IntegerOverflowFlagsProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs ($overflowFlags^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.addrspacecast\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.alloca\",\n    \"operands\": [\n      { \"name\": \"arraySize\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"elem_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"inalloca\", \"type\": \"UnitAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.and\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.ashr\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`exact` $isExact^)? $lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.atomicrmw\",\n    \"operands\": [\n      { \"name\": \"bin_op\", \"type\": \"AtomicBinOp{xchg|add|sub|_and|nand|_or|_xor|max|min|umax|umin|fadd|fsub|fmax|fmin|uinc_wrap|udec_wrap}\" },\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"val\", \"type\": \"LLVM_AtomicRMWType\" },\n      { \"name\": \"ordering\", \"type\": \"AtomicOrdering{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AtomicRMWType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"volatile_\", \"type\": \"UnitAttr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'val', 'res', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"(`volatile` $volatile_^)? $bin_op $ptr `,` $val\\n    (`syncscope` `(` $syncscope^ `)`)? $ordering attr-dict `:`\\n    qualified(type($ptr)) `,` type($val)\"\n  },\n  {\n    \"name\": \"llvm.bitcast\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyNonAggregate\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyNonAggregate\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.blockaddress\",\n    \"summary\": \"Creates a LLVM blockaddress ptr\",\n    \"description\": \"Creates an SSA value containing a pointer to a basic block. The block\\n    address information (function and block) is given by the `BlockAddressAttr`\\n    attribute. This operation assumes an existing `llvm.blocktag` operation\\n    identifying an existing MLIR block within a function. Example:\\n\\n    ```mlir\\n    llvm.mlir.global private @g() : !llvm.ptr {\\n      %0 = llvm.blockaddress <function = @fn, tag = <id = 0>> : !llvm.ptr\\n      llvm.return %0 : !llvm.ptr\\n    }\\n\\n    llvm.func @fn() {\\n      llvm.br ^bb1\\n    ^bb1:  // pred: ^bb0\\n      llvm.blocktag <id = 0>\\n      llvm.return\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_addr\", \"type\": \"LLVM_BlockAddressAttr\" }\n    ],\n    \"assemblyFormat\": \"$block_addr\\n    attr-dict `:` qualified(type($res))\"\n  },\n  {\n    \"name\": \"llvm.blocktag\",\n    \"description\": \"This operation uses a `tag` to uniquely identify an MLIR block in a\\n    function. The same tag is used by `llvm.blockaddress` in order to compute\\n    the target address.\\n\\n    A given function should have at most one `llvm.blocktag` operation with a\\n    given `tag`. This operation cannot be used as a terminator.\\n\\n    Example:\\n\\n    ```mlir\\n    llvm.func @f() -> !llvm.ptr {\\n      %addr = llvm.blockaddress <function = @f, tag = <id = 1>> : !llvm.ptr\\n      llvm.br ^bb1\\n    ^bb1:\\n      llvm.blocktag <id = 1>\\n      llvm.return %addr : !llvm.ptr\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"LLVM_BlockTagAttr\" }\n    ],\n    \"assemblyFormat\": \"$tag attr-dict\"\n  },\n  {\n    \"name\": \"llvm.br\",\n    \"operands\": [\n      { \"name\": \"destOperands\", \"type\": \"Variadic<LLVM_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"loop_annotation\", \"type\": \"OptionalAttr<LoopAnnotationAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"llvm.call\",\n    \"summary\": \"Call to an LLVM function.\",\n    \"description\": \"In LLVM IR, functions may return either 0 or 1 value. LLVM IR dialect\\n    implements this behavior by providing a variadic `call` operation for 0- and\\n    1-result functions. Even though MLIR supports multi-result functions, LLVM\\n    IR dialect disallows them.\\n\\n    The `call` instruction supports both direct and indirect calls. Direct calls\\n    start with a function name (`@`-prefixed) and indirect calls start with an\\n    SSA value (`%`-prefixed). The direct callee, if present, is stored as a\\n    function attribute `callee`. For indirect calls, the callee is of `!llvm.ptr` type\\n    and is stored as the first value in `callee_operands`. If and only if the\\n    callee is a variadic function, the `var_callee_type` attribute must carry\\n    the variadic LLVM function type. The trailing type list contains the\\n    optional indirect callee type and the MLIR function type, which differs from\\n    the LLVM function type that uses an explicit void type to model functions\\n    that do not return a value.\\n\\n    If this operatin has the `no_inline` attribute, then this specific function call\\n    will never be inlined. The opposite behavior will occur if the call has `always_inline`\\n    attribute. The `inline_hint` attribute indicates that it is desirable to inline\\n    this function call.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Direct call without arguments and with one result.\\n    %0 = llvm.call @foo() : () -> (f32)\\n\\n    // Direct call with arguments and without a result.\\n    llvm.call @bar(%0) : (f32) -> ()\\n\\n    // Indirect call with an argument and without a result.\\n    %1 = llvm.mlir.addressof @foo : !llvm.ptr\\n    llvm.call %1(%0) : !llvm.ptr, (f32) -> ()\\n\\n    // Direct variadic call.\\n    llvm.call @printf(%0, %1) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i32) -> i32\\n\\n    // Indirect variadic call\\n    llvm.call %1(%0) vararg(!llvm.func<void (...)>) : !llvm.ptr, (i32) -> ()\\n    ```\",\n    \"operands\": [\n      { \"name\": \"callee_operands\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"op_bundle_operands\", \"type\": \"VariadicOfVariadic<LLVM_Type, op_bundle_sizes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<LLVM_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"var_callee_type\", \"type\": \"OptionalAttr<TypeAttrOf<LLVM_FunctionType>>\" },\n      { \"name\": \"callee\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" },\n      { \"name\": \"CConv\", \"type\": \"DefaultValuedAttr<CConv, CConv::C>\" },\n      { \"name\": \"TailCallKind\", \"type\": \"DefaultValuedAttr<TailCallKind, TailCallKind::None>\" },\n      { \"name\": \"memory_effects\", \"type\": \"OptionalAttr<LLVM_MemoryEffectsAttr>\" },\n      { \"name\": \"convergent\", \"type\": \"UnitAttr\" },\n      { \"name\": \"no_unwind\", \"type\": \"UnitAttr\" },\n      { \"name\": \"will_return\", \"type\": \"UnitAttr\" },\n      { \"name\": \"noreturn\", \"type\": \"UnitAttr\" },\n      { \"name\": \"returns_twice\", \"type\": \"UnitAttr\" },\n      { \"name\": \"hot\", \"type\": \"UnitAttr\" },\n      { \"name\": \"cold\", \"type\": \"UnitAttr\" },\n      { \"name\": \"noduplicate\", \"type\": \"UnitAttr\" },\n      { \"name\": \"no_caller_saved_registers\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nocallback\", \"type\": \"UnitAttr\" },\n      { \"name\": \"modular_format\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"nobuiltins\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"allocsize\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"optsize\", \"type\": \"UnitAttr\" },\n      { \"name\": \"minsize\", \"type\": \"UnitAttr\" },\n      { \"name\": \"builtin\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nobuiltin\", \"type\": \"UnitAttr\" },\n      { \"name\": \"save_reg_params\", \"type\": \"UnitAttr\" },\n      { \"name\": \"zero_call_used_regs\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"trap_func_name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"default_func_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"op_bundle_sizes\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"op_bundle_tags\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"no_inline\", \"type\": \"UnitAttr\" },\n      { \"name\": \"always_inline\", \"type\": \"UnitAttr\" },\n      { \"name\": \"inline_hint\", \"type\": \"UnitAttr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.call_intrinsic\",\n    \"summary\": \"Call to an LLVM intrinsic function.\",\n    \"description\": \"Call the specified llvm intrinsic. If the intrinsic is overloaded, use\\n    the MLIR function type of this op to determine which intrinsic to call.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"op_bundle_operands\", \"type\": \"VariadicOfVariadic<LLVM_Type, op_bundle_sizes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Optional<LLVM_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"intrin\", \"type\": \"StrAttr\" },\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" },\n      { \"name\": \"op_bundle_sizes\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"op_bundle_tags\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.cmpxchg\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"cmp\", \"type\": \"LLVM_AtomicCmpXchgType\" },\n      { \"name\": \"val\", \"type\": \"LLVM_AtomicCmpXchgType\" },\n      { \"name\": \"success_ordering\", \"type\": \"AtomicOrdering{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}\" },\n      { \"name\": \"failure_ordering\", \"type\": \"AtomicOrdering{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"weak\", \"type\": \"UnitAttr\" },\n      { \"name\": \"volatile_\", \"type\": \"UnitAttr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'val', 'cmp', '$_self'>\" },\n      { \"type\": \"TypesMatchWith<'val', 'res', 'getValAndBoolStructType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"(`weak` $weak^)? (`volatile` $volatile_^)? $ptr `,` $cmp `,` $val\\n    (`syncscope` `(` $syncscope^ `)`)? $success_ordering $failure_ordering\\n    attr-dict `:` qualified(type($ptr)) `,` type($val)\"\n  },\n  {\n    \"name\": \"llvm.comdat\",\n    \"summary\": \"LLVM dialect comdat region\",\n    \"description\": \"Provides access to object file COMDAT section/group functionality.\\n\\n    Examples:\\n    ```mlir\\n    llvm.comdat @__llvm_comdat {\\n      llvm.comdat_selector @any any\\n    }\\n    llvm.mlir.global internal constant @has_any_comdat(1 : i64) comdat(@__llvm_comdat::@any) : i64\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name $body attr-dict\"\n  },\n  {\n    \"name\": \"llvm.comdat_selector\",\n    \"summary\": \"LLVM dialect comdat selector declaration\",\n    \"description\": \"Provides access to object file COMDAT section/group functionality.\\n\\n    Examples:\\n    ```mlir\\n    llvm.comdat @__llvm_comdat {\\n      llvm.comdat_selector @any any\\n    }\\n    llvm.mlir.global internal constant @has_any_comdat(1 : i64) comdat(@__llvm_comdat::@any) : i64\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"comdat\", \"type\": \"Comdat{any|exactmatch|largest|nodeduplicate|samesize}\" }\n    ],\n    \"assemblyFormat\": \"$sym_name $comdat attr-dict\"\n  },\n  {\n    \"name\": \"llvm.cond_br\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"trueDestOperands\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"falseDestOperands\", \"type\": \"Variadic<LLVM_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branch_weights\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"loop_annotation\", \"type\": \"OptionalAttr<LoopAnnotationAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$condition ( `weights` `(` $branch_weights^ `)` )? `,`\\n    $trueDest (`(` $trueDestOperands^ `:` type($trueDestOperands) `)`)? `,`\\n    $falseDest (`(` $falseDestOperands^ `:` type($falseDestOperands) `)`)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"llvm.dso_local_equivalent\",\n    \"summary\": \"Creates a LLVM dso_local_equivalent ptr\",\n    \"description\": \"Creates an SSA value containing a pointer to a global value (function or\\n    alias to function). It represents a function which is functionally\\n    equivalent to a given function, but is always defined in the current\\n    linkage unit. The target function may not have `extern_weak` linkage.\\n\\n    Examples:\\n\\n    ```mlir\\n    llvm.mlir.global external constant @const() : i64 {\\n      %0 = llvm.mlir.addressof @const : !llvm.ptr\\n      %1 = llvm.ptrtoint %0 : !llvm.ptr to i64\\n      %2 = llvm.dso_local_equivalent @func : !llvm.ptr\\n      %4 = llvm.ptrtoint %2 : !llvm.ptr to i64\\n      llvm.return %4 : i64\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function_name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$function_name attr-dict `:` qualified(type($res))\"\n  },\n  {\n    \"name\": \"llvm.extractelement\",\n    \"summary\": \"Extract an element from an LLVM vector.\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"position\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'vector', 'res', '::llvm::cast<::mlir::VectorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$vector `[` $position `:` type($position) `]` attr-dict `:` type($vector)\"\n  },\n  {\n    \"name\": \"llvm.extractvalue\",\n    \"summary\": \"Extract a value from an LLVM struct.\",\n    \"operands\": [\n      { \"name\": \"container\", \"type\": \"LLVM_AnyAggregate\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"position\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$container `` $position attr-dict `:` type($container)\\n    custom<InsertExtractValueElementType>(type($res), ref(type($container)),\\n                                          ref($position))\"\n  },\n  {\n    \"name\": \"llvm.fadd\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fcmp\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"FCmpPredicate{_false|oeq|ogt|oge|olt|ole|one|ord|ueq|ugt|uge|ult|ule|une|uno|_true}\" },\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'lhs', 'res', '::getI1SameShape($_self)'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.fdiv\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fence\",\n    \"operands\": [\n      { \"name\": \"ordering\", \"type\": \"AtomicOrdering{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`syncscope` `(` $syncscope^ `)`)? $ordering attr-dict\"\n  },\n  {\n    \"name\": \"llvm.fmul\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fneg\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fpext\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fptosi\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fptoui\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fptrunc\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.freeze\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$val attr-dict `:` type($val)\"\n  },\n  {\n    \"name\": \"llvm.frem\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.fsub\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.func\",\n    \"summary\": \"LLVM dialect function.\",\n    \"description\": \"MLIR functions are defined by an operation that is not built into the IR\\n    itself. The LLVM dialect provides an `llvm.func` operation to define\\n    functions compatible with LLVM IR. These functions have LLVM dialect\\n    function type but use MLIR syntax to express it. They are required to have\\n    exactly one result type. LLVM function operation is intended to capture\\n    additional properties of LLVM functions, such as linkage and calling\\n    convention, that may be modeled differently by the built-in MLIR function.\\n\\n    ```mlir\\n    // The type of @bar is !llvm<\\\"i64 (i64)\\\">\\n    llvm.func @bar(%arg0: i64) -> i64 {\\n      llvm.return %arg0 : i64\\n    }\\n\\n    // Type type of @foo is !llvm<\\\"void (i64)\\\">\\n    // !llvm.void type is omitted\\n    llvm.func @foo(%arg0: i64) {\\n      llvm.return\\n    }\\n\\n    // A function with `internal` linkage.\\n    llvm.func internal @internal_func() {\\n      llvm.return\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<LLVM_FunctionType>\" },\n      { \"name\": \"linkage\", \"type\": \"DefaultValuedAttr<Linkage, Linkage::External>\" },\n      { \"name\": \"dso_local\", \"type\": \"UnitAttr\" },\n      { \"name\": \"CConv\", \"type\": \"DefaultValuedAttr<CConv, CConv::C>\" },\n      { \"name\": \"comdat\", \"type\": \"OptionalAttr<SymbolRefAttr>\" },\n      { \"name\": \"convergent\", \"type\": \"UnitAttr\" },\n      { \"name\": \"personality\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"garbageCollector\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"passthrough\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"function_entry_count\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"memory_effects\", \"type\": \"OptionalAttr<LLVM_MemoryEffectsAttr>\" },\n      { \"name\": \"visibility_\", \"type\": \"DefaultValuedAttr<Visibility{hidden|protected}, mlir::LLVM::Visibility::Default>\" },\n      { \"name\": \"arm_streaming\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_locally_streaming\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_streaming_compatible\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_new_za\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_in_za\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_out_za\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_inout_za\", \"type\": \"UnitAttr\" },\n      { \"name\": \"arm_preserves_za\", \"type\": \"UnitAttr\" },\n      { \"name\": \"section\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"unnamed_addr\", \"type\": \"OptionalAttr<UnnamedAddr{local_unnamed_addr|unnamed_addr}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"vscale_range\", \"type\": \"OptionalAttr<LLVM_VScaleRangeAttr>\" },\n      { \"name\": \"frame_pointer\", \"type\": \"OptionalAttr<FramePointerKindAttr>\" },\n      { \"name\": \"target_cpu\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"tune_cpu\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"reciprocal_estimates\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"prefer_vector_width\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"target_features\", \"type\": \"OptionalAttr<LLVM_TargetFeaturesAttr>\" },\n      { \"name\": \"no_signed_zeros_fp_math\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"denormal_fpenv\", \"type\": \"OptionalAttr<LLVM_DenormalFPEnvAttr>\" },\n      { \"name\": \"fp_contract\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"instrument_function_entry\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"instrument_function_exit\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"no_inline\", \"type\": \"UnitAttr\" },\n      { \"name\": \"always_inline\", \"type\": \"UnitAttr\" },\n      { \"name\": \"inline_hint\", \"type\": \"UnitAttr\" },\n      { \"name\": \"no_unwind\", \"type\": \"UnitAttr\" },\n      { \"name\": \"will_return\", \"type\": \"UnitAttr\" },\n      { \"name\": \"noreturn\", \"type\": \"UnitAttr\" },\n      { \"name\": \"optimize_none\", \"type\": \"UnitAttr\" },\n      { \"name\": \"returns_twice\", \"type\": \"UnitAttr\" },\n      { \"name\": \"hot\", \"type\": \"UnitAttr\" },\n      { \"name\": \"cold\", \"type\": \"UnitAttr\" },\n      { \"name\": \"noduplicate\", \"type\": \"UnitAttr\" },\n      { \"name\": \"no_caller_saved_registers\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nocallback\", \"type\": \"UnitAttr\" },\n      { \"name\": \"modular_format\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"nobuiltins\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"allocsize\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"optsize\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"minsize\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"save_reg_params\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"zero_call_used_regs\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"default_func_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"vec_type_hint\", \"type\": \"OptionalAttr<LLVM_VecTypeHintAttr>\" },\n      { \"name\": \"work_group_size_hint\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"reqd_work_group_size\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"intel_reqd_sub_group_size\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"uwtable_kind\", \"type\": \"OptionalAttr<UWTableKindAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.getelementptr\",\n    \"description\": \"This operation mirrors LLVM IRs 'getelementptr' operation that is used to\\n    perform pointer arithmetic.\\n\\n    Like in LLVM IR, it is possible to use both constants as well as SSA values\\n    as indices. In the case of indexing within a structure, it is required to\\n    either use constant indices directly, or supply a constant SSA value.\\n\\n    The no-wrap flags can be used to specify the low-level pointer arithmetic\\n    overflow behavior that LLVM uses after lowering the operation to LLVM IR.\\n    Valid options include 'inbounds' (pointer arithmetic must be within object\\n    bounds), 'nusw' (no unsigned signed wrap), and 'nuw' (no unsigned wrap).\\n    Note that 'inbounds' implies 'nusw' which is ensured by the enum\\n    definition. The flags can be set individually or in combination.\\n\\n    Examples:\\n\\n    ```mlir\\n    // GEP with an SSA value offset\\n    %0 = llvm.getelementptr %1[%2] : (!llvm.ptr, i64) -> !llvm.ptr, f32\\n\\n    // GEP with a constant offset and the inbounds attribute set\\n    %0 = llvm.getelementptr inbounds %1[3] : (!llvm.ptr) -> !llvm.ptr, f32\\n\\n    // GEP with constant offsets into a structure\\n    %0 = llvm.getelementptr %1[0, 1]\\n       : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, f32)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" },\n      { \"name\": \"dynamicIndices\", \"type\": \"Variadic<LLVM_ScalarOrVectorOf<AnySignlessInteger>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rawConstantIndices\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"elem_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"noWrapFlags\", \"type\": \"GEPNoWrapFlagsProp{none|inbounds_flag|nusw|nuw|inbounds}\" }\n    ],\n    \"assemblyFormat\": \"($noWrapFlags^)?\\n    $base `[` custom<GEPIndices>($dynamicIndices, $rawConstantIndices) `]` attr-dict\\n    `:` functional-type(operands, results) `,` $elem_type\"\n  },\n  {\n    \"name\": \"llvm.icmp\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[LLVM_ScalarOrVectorOf<AnySignlessInteger>, LLVM_ScalarOrVectorOf<LLVM_AnyPointer>]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[LLVM_ScalarOrVectorOf<AnySignlessInteger>, LLVM_ScalarOrVectorOf<LLVM_AnyPointer>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"ICmpPredicate{eq|ne|slt|sle|sgt|sge|ult|ule|ugt|uge}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'lhs', 'res', '::getI1SameShape($_self)'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.indirectbr\",\n    \"description\": \"Transfer control flow to address in `$addr`. A list of possible target\\n    blocks in `$successors` can be provided and maybe used as a hint in LLVM:\\n\\n    ```mlir\\n    ...\\n    llvm.func @g(...\\n      %dest = llvm.blockaddress <function = @g, tag = <id = 0>> : !llvm.ptr\\n      llvm.indirectbr %dest : !llvm.ptr, [\\n        ^head\\n      ]\\n    ^head:\\n      llvm.blocktag <id = 0>\\n      llvm.return %arg0 : i32\\n      ...\\n    ```\\n\\n    It also supports a list of operands that can be passed to a target block:\\n\\n    ```mlir\\n      llvm.indirectbr %dest : !llvm.ptr, [\\n        ^head(%arg0 : i32),\\n        ^tail(%arg1, %arg0 : i32, i32)\\n      ]\\n    ^head(%r0 : i32):\\n      llvm.return %r0 : i32\\n    ^tail(%r1 : i32, %r2 : i32):\\n      ...\\n    ```\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"succOperands\", \"type\": \"VariadicOfVariadic<AnyType, indbr_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indbr_operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"successors\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"$addr `:` type($addr) `,`\\n      custom<IndirectBrOpSucessors>(ref(type($addr)),\\n                                    $successors,\\n                                    $succOperands,\\n                                    type($succOperands))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"llvm.inline_asm\",\n    \"description\": \"The InlineAsmOp mirrors the underlying LLVM semantics with a notable\\n    exception: the embedded `asm_string` is not allowed to define or reference\\n    any symbol or any global variable: only the operands of the op may be read,\\n    written, or referenced.\\n    Attempting to define or reference any symbol or any global behavior is\\n    considered undefined behavior at this time.\\n    If `tail_call_kind` is used, the operation behaves like the specified\\n    tail call kind. The `musttail` kind it's not available for this operation,\\n    since it isn't supported by LLVM's inline asm.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<LLVM_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<LLVM_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asm_string\", \"type\": \"StrAttr\" },\n      { \"name\": \"constraints\", \"type\": \"StrAttr\" },\n      { \"name\": \"has_side_effects\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_align_stack\", \"type\": \"UnitAttr\" },\n      { \"name\": \"tail_call_kind\", \"type\": \"DefaultValuedAttr<TailCallKind, TailCallKind::None>\" },\n      { \"name\": \"asm_dialect\", \"type\": \"OptionalAttr<DefaultValuedAttr<AsmATTOrIntel{att|intel}, AsmDialect::AD_ATT>>\" },\n      { \"name\": \"operand_attrs\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`has_side_effects` $has_side_effects^)?\\n    (`is_align_stack` $is_align_stack^)?\\n    (`tail_call_kind` `=` $tail_call_kind^)?\\n    (`asm_dialect` `=` $asm_dialect^)?\\n    (`operand_attrs` `=` $operand_attrs^)?\\n    attr-dict\\n    $asm_string `,` $constraints\\n    operands `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.insertelement\",\n    \"summary\": \"Insert an element into an LLVM vector.\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"value\", \"type\": \"LLVM_PrimitiveType\" },\n      { \"name\": \"position\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'vector', 'value', '::llvm::cast<::mlir::VectorType>($_self).getElementType()'>\" },\n      { \"type\": \"AllTypesMatch<['res', 'vector']>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $vector `[` $position `:` type($position) `]` attr-dict `:`\\n    type($vector)\"\n  },\n  {\n    \"name\": \"llvm.insertvalue\",\n    \"summary\": \"Insert a value into an LLVM struct.\",\n    \"operands\": [\n      { \"name\": \"container\", \"type\": \"LLVM_AnyAggregate\" },\n      { \"name\": \"value\", \"type\": \"LLVM_PrimitiveType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyAggregate\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"position\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['container', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $container `` $position attr-dict `:` type($container)\\n    custom<InsertExtractValueElementType>(type($value), ref(type($container)),\\n                                          ref($position))\"\n  },\n  {\n    \"name\": \"llvm.intr.abs\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_int_min_poison\", \"type\": \"I1Attr\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.acos\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.annotation\",\n    \"operands\": [\n      { \"name\": \"integer\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"annotation\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"fileName\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"line\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'integer']>\" },\n      { \"type\": \"AllTypesMatch<['annotation', 'fileName']>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.asin\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.assume\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1\" },\n      { \"name\": \"op_bundle_operands\", \"type\": \"VariadicOfVariadic<LLVM_Type, op_bundle_sizes>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_bundle_sizes\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"op_bundle_tags\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$cond\\n    ( custom<OpBundles>($op_bundle_operands, type($op_bundle_operands),\\n                        $op_bundle_tags)^ )?\\n    `:` type($cond) attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.atan\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.atan2\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.bitreverse\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.bswap\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.ceil\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.copysign\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.align\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.begin\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"LLVM_TokenType\" },\n      { \"name\": \"mem\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$token `,` $mem attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.end\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"unwind\", \"type\": \"I1\" },\n      { \"name\": \"retvals\", \"type\": \"LLVM_TokenType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$handle `,` $unwind `,` $retvals attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.free\",\n    \"operands\": [\n      { \"name\": \"id\", \"type\": \"LLVM_TokenType\" },\n      { \"name\": \"handle\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$id `,` $handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.id\",\n    \"operands\": [\n      { \"name\": \"align\", \"type\": \"I32\" },\n      { \"name\": \"promise\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"coroaddr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"fnaddrs\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$align `,` $promise `,` $coroaddr `,` $fnaddrs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.promise\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"align\", \"type\": \"I32\" },\n      { \"name\": \"from\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$handle `,` $align `,` $from attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.resume\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict `:` qualified(type($handle))\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.save\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.size\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.coro.suspend\",\n    \"operands\": [\n      { \"name\": \"save\", \"type\": \"LLVM_TokenType\" },\n      { \"name\": \"final\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$save `,` $final attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.cos\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.cosh\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.ctlz\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_zero_poison\", \"type\": \"I1Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.ctpop\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.cttz\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_zero_poison\", \"type\": \"I1Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.dbg.declare\",\n    \"summary\": \"Describes how the address relates to a source language variable.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varInfo\", \"type\": \"LLVM_DILocalVariableAttr\" },\n      { \"name\": \"locationExpr\", \"type\": \"DefaultValuedAttr<LLVM_DIExpressionAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"qualified($varInfo) (qualified($locationExpr)^)? `=` $addr`:` qualified(type($addr)) attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.dbg.label\",\n    \"summary\": \"Relates the program to a debug information label.\",\n    \"attributes\": [\n      { \"name\": \"label\", \"type\": \"LLVM_DILabelAttr\" }\n    ],\n    \"assemblyFormat\": \"$label attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.dbg.value\",\n    \"summary\": \"Describes how the value relates to a source language variable.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"varInfo\", \"type\": \"LLVM_DILocalVariableAttr\" },\n      { \"name\": \"locationExpr\", \"type\": \"DefaultValuedAttr<LLVM_DIExpressionAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"qualified($varInfo) (qualified($locationExpr)^)? `=` $value`:` qualified(type($value)) attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.debugtrap\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.eh.typeid.for\",\n    \"operands\": [\n      { \"name\": \"type_info\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$type_info attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.exp\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.exp10\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.exp2\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.expect\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"expected\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$val `,` $expected attr-dict `:` type($val)\"\n  },\n  {\n    \"name\": \"llvm.intr.expect.with.probability\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"expected\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prob\", \"type\": \"F64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['val', 'expected', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$val `,` $expected `,` $prob attr-dict `:` type($val)\"\n  },\n  {\n    \"name\": \"llvm.intr.experimental.constrained.fpext\",\n    \"operands\": [\n      { \"name\": \"arg_0\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fpExceptionBehavior\", \"type\": \"FPExceptionBehaviorAttr{ignore|maytrap|strict}\" }\n    ],\n    \"assemblyFormat\": \"$arg_0 $fpExceptionBehavior attr-dict `:` type($arg_0) `to` type(results)\"\n  },\n  {\n    \"name\": \"llvm.intr.experimental.constrained.fptrunc\",\n    \"operands\": [\n      { \"name\": \"arg_0\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"roundingmode\", \"type\": \"ConfinedAttr<RoundingModeAttr{towardzero|tonearest|upward|downward|tonearestaway|dynamic|invalid}, [IntMinValue<0>]>\" },\n      { \"name\": \"fpExceptionBehavior\", \"type\": \"FPExceptionBehaviorAttr{ignore|maytrap|strict}\" }\n    ],\n    \"assemblyFormat\": \"$arg_0 $roundingmode $fpExceptionBehavior attr-dict `:` type($arg_0) `to` type(results)\"\n  },\n  {\n    \"name\": \"llvm.intr.experimental.constrained.sitofp\",\n    \"operands\": [\n      { \"name\": \"arg_0\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"roundingmode\", \"type\": \"ConfinedAttr<RoundingModeAttr{towardzero|tonearest|upward|downward|tonearestaway|dynamic|invalid}, [IntMinValue<0>]>\" },\n      { \"name\": \"fpExceptionBehavior\", \"type\": \"FPExceptionBehaviorAttr{ignore|maytrap|strict}\" }\n    ],\n    \"assemblyFormat\": \"$arg_0 $roundingmode $fpExceptionBehavior attr-dict `:` type($arg_0) `to` type(results)\"\n  },\n  {\n    \"name\": \"llvm.intr.experimental.constrained.uitofp\",\n    \"operands\": [\n      { \"name\": \"arg_0\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"roundingmode\", \"type\": \"ConfinedAttr<RoundingModeAttr{towardzero|tonearest|upward|downward|tonearestaway|dynamic|invalid}, [IntMinValue<0>]>\" },\n      { \"name\": \"fpExceptionBehavior\", \"type\": \"FPExceptionBehaviorAttr{ignore|maytrap|strict}\" }\n    ],\n    \"assemblyFormat\": \"$arg_0 $roundingmode $fpExceptionBehavior attr-dict `:` type($arg_0) `to` type(results)\"\n  },\n  {\n    \"name\": \"llvm.intr.experimental.noalias.scope.decl\",\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"LLVM_AliasScopeAttr\" }\n    ],\n    \"assemblyFormat\": \"$scope attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.experimental.vp.strided.load\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"stride\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.experimental.vp.strided.store\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"stride\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.fabs\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.fake.use\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<LLVM_Type>\" }\n    ],\n    \"assemblyFormat\": \"$args attr-dict `:` type($args)\"\n  },\n  {\n    \"name\": \"llvm.intr.floor\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.fma\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<element>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.fmuladd\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<element>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.frexp\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.fshl\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<element>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.fshr\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<element>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.get.active.lane.mask\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"n\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$base `,` $n attr-dict `:` type($base) `,` type($n) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.invariant.end\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"LLVM_DefaultPointer\" },\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$start `,` $size `,` $ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.invariant.start\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_DefaultPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$size `,` $ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.is.constant\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I1\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.is.fpclass\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bit\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.launder.invariant.group\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.ldexp\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"power\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.lifetime.end\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.lifetime.start\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.llrint\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.llround\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.log\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.log10\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.log2\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.lrint\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.lround\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.masked.compressstore\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.masked.expandload\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"passthru\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.masked.gather\",\n    \"operands\": [\n      { \"name\": \"ptrs\", \"type\": \"LLVM_VectorOf<LLVM_AnyPointer>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"pass_thru\", \"type\": \"Variadic<LLVM_AnyVector>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.masked.load\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"pass_thru\", \"type\": \"Optional<LLVM_AnyVector>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"I32Attr\" },\n      { \"name\": \"nontemporal\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.masked.scatter\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"ptrs\", \"type\": \"LLVM_VectorOf<LLVM_AnyPointer>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $ptrs `,` $mask attr-dict `:` type($value) `,` type($mask) `into` type($ptrs)\"\n  },\n  {\n    \"name\": \"llvm.intr.masked.store\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"data\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $data `,` $mask attr-dict `:` type($value) `,` type($mask) `into` qualified(type($data))\"\n  },\n  {\n    \"name\": \"llvm.intr.matrix.column.major.load\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"stride\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"rows\", \"type\": \"I32Attr\" },\n      { \"name\": \"columns\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$data `,` `<` `stride` `=` $stride `>` attr-dict`:` type($res) `from` qualified(type($data)) `stride` type($stride)\"\n  },\n  {\n    \"name\": \"llvm.intr.matrix.column.major.store\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"data\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"stride\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"rows\", \"type\": \"I32Attr\" },\n      { \"name\": \"columns\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$matrix `,` $data `,` `<` `stride` `=` $stride `>` attr-dict`:` type($matrix) `to` qualified(type($data)) `stride` type($stride)\"\n  },\n  {\n    \"name\": \"llvm.intr.matrix.multiply\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_rows\", \"type\": \"I32Attr\" },\n      { \"name\": \"lhs_columns\", \"type\": \"I32Attr\" },\n      { \"name\": \"rhs_columns\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` `(` type($lhs) `,` type($rhs) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.matrix.transpose\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rows\", \"type\": \"I32Attr\" },\n      { \"name\": \"columns\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$matrix attr-dict `:` type($matrix) `into` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.maximum\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.maxnum\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.memcpy\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"src\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"len\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.memcpy.inline\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"src\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"len\", \"type\": \"APIntAttr\" },\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.memmove\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"src\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"len\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.memset\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"val\", \"type\": \"I8\" },\n      { \"name\": \"len\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.memset.inline\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"val\", \"type\": \"I8\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"len\", \"type\": \"APIntAttr\" },\n      { \"name\": \"isVolatile\", \"type\": \"I1Attr\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.minimum\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.minnum\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.nearbyint\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.pow\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.powi\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"power\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.prefetch\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rw\", \"type\": \"I32Attr\" },\n      { \"name\": \"hint\", \"type\": \"I32Attr\" },\n      { \"name\": \"cache\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.ptr.annotation\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"annotation\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"fileName\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"line\", \"type\": \"I32\" },\n      { \"name\": \"attr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'ptr']>\" },\n      { \"type\": \"AllTypesMatch<['annotation', 'fileName', 'attr']>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.ptrmask\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['ptr', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $mask attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.rint\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.round\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.roundeven\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.sadd.sat\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.sadd.with.overflow\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.scmp\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.sin\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.sincos\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.sinh\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.smax\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.smin\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.smul.with.overflow\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.sqrt\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.ssa.copy\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"llvm.intr.sshl.sat\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.ssub.sat\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.ssub.with.overflow\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.stackrestore\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.stacksave\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` qualified(type($res))\"\n  },\n  {\n    \"name\": \"llvm.intr.stepvector\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.strip.invariant.group\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"llvm.intr.tan\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.tanh\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.threadlocal.address\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.trap\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.trunc\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.uadd.sat\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.uadd.with.overflow\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.ubsantrap\",\n    \"attributes\": [\n      { \"name\": \"failureKind\", \"type\": \"I8Attr\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"llvm.intr.ucmp\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.umax\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.umin\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.umul.with.overflow\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.ushl.sat\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.usub.sat\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.usub.with.overflow\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vacopy\",\n    \"summary\": \"Copies the current argument position from `src_list` to `dest_list`.\",\n    \"operands\": [\n      { \"name\": \"dest_list\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"src_list\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$src_list `to` $dest_list attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"llvm.intr.vaend\",\n    \"summary\": \"Destroys `arg_list`, which has been initialized by `intr.vastart` or `intr.vacopy`.\",\n    \"operands\": [\n      { \"name\": \"arg_list\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$arg_list attr-dict `:` qualified(type($arg_list))\"\n  },\n  {\n    \"name\": \"llvm.intr.var.annotation\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"annotation\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"fileName\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"line\", \"type\": \"I32\" },\n      { \"name\": \"attr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['annotation', 'fileName', 'attr']>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vastart\",\n    \"summary\": \"Initializes `arg_list` for subsequent variadic argument extractions.\",\n    \"operands\": [\n      { \"name\": \"arg_list\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"$arg_list attr-dict `:` qualified(type($arg_list))\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.deinterleave2\",\n    \"operands\": [\n      { \"name\": \"vec\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.extract\",\n    \"operands\": [\n      { \"name\": \"srcvec\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pos\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$srcvec `[` $pos `]` attr-dict `:` type($res) `from` type($srcvec)\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.insert\",\n    \"operands\": [\n      { \"name\": \"dstvec\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"srcvec\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pos\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dstvec', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$srcvec `,` $dstvec `[` $pos `]` attr-dict `:` type($srcvec) `into` type($res)\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.interleave2\",\n    \"operands\": [\n      { \"name\": \"vec1\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"vec2\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vec1', 'vec2']>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.add\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.and\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.fadd\",\n    \"operands\": [\n      { \"name\": \"start_value\", \"type\": \"AnyFloat\" },\n      { \"name\": \"input\", \"type\": \"LLVM_VectorOf<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.fmax\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.fmaximum\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.fmin\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.fminimum\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.fmul\",\n    \"operands\": [\n      { \"name\": \"start_value\", \"type\": \"AnyFloat\" },\n      { \"name\": \"input\", \"type\": \"LLVM_VectorOf<AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.mul\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.or\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.smax\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.smin\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.umax\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.umin\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vector.reduce.xor\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.add\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.and\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.ashr\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fadd\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fdiv\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fma\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"op2\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"op3\", \"type\": \"LLVM_VectorOf<element>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fmul\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fmuladd\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"op2\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"op3\", \"type\": \"LLVM_VectorOf<element>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fneg\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fpext\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fptosi\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fptoui\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fptrunc\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.frem\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.fsub\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.inttoptr\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.load\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.lshr\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.merge\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"true_val\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"false_val\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.mul\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.or\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.ptrtoint\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<LLVM_AnyPointer>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.add\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.and\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.fadd\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnyFloat\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.fmax\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnyFloat\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.fmin\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnyFloat\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.fmul\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnyFloat\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnyFloat>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.mul\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.or\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.smax\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.smin\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.umax\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.umin\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.reduce.xor\",\n    \"operands\": [\n      { \"name\": \"satrt_value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"val\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.sdiv\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.select\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"true_val\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"false_val\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.sext\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.shl\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.sitofp\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.smax\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.smin\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.srem\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.store\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.sub\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.trunc\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.udiv\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.uitofp\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.umax\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.umin\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.urem\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.xor\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vp.zext\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_VectorOf<AnySignlessInteger>\" },\n      { \"name\": \"mask\", \"type\": \"LLVM_VectorOf<I1>\" },\n      { \"name\": \"evl\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.intr.vscale\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ]\n  },\n  {\n    \"name\": \"llvm.inttoptr\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dereferenceable\", \"type\": \"OptionalAttr<LLVM_DereferenceableAttr>\" }\n    ],\n    \"assemblyFormat\": \"$arg (`dereferenceable` `` $dereferenceable^)? attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.invoke\",\n    \"operands\": [\n      { \"name\": \"callee_operands\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"normalDestOperands\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"unwindDestOperands\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"op_bundle_operands\", \"type\": \"VariadicOfVariadic<LLVM_Type, op_bundle_sizes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<LLVM_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"var_callee_type\", \"type\": \"OptionalAttr<TypeAttrOf<LLVM_FunctionType>>\" },\n      { \"name\": \"callee\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"branch_weights\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"CConv\", \"type\": \"DefaultValuedAttr<CConv, CConv::C>\" },\n      { \"name\": \"op_bundle_sizes\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"op_bundle_tags\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"normalDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"unwindDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.landingpad\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cleanup\", \"type\": \"UnitAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.linker_options\",\n    \"summary\": \"Options to pass to the linker when the object file is linked\",\n    \"description\": \"Pass the given options to the linker when the resulting object file is linked.\\n    This is used extensively on Windows to determine the C runtime that the object\\n    files should link against.\\n\\n    Examples:\\n    ```mlir\\n    // Link against the MSVC static threaded CRT.\\n    llvm.linker_options [\\\"/DEFAULTLIB:\\\", \\\"libcmt\\\"]\\n\\n    // Link against aarch64 compiler-rt builtins\\n    llvm.linker_options [\\\"-l\\\", \\\"clang_rt.builtins-aarch64\\\"]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"options\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$options attr-dict\"\n  },\n  {\n    \"name\": \"llvm.load\",\n    \"description\": \"The `load` operation is used to read from memory. A load may be marked as\\n    atomic, volatile, and/or nontemporal, and takes a number of optional\\n    attributes that specify aliasing information.\\n\\n    An atomic load only supports a limited set of pointer, integer, and\\n    floating point types, and requires an explicit alignment.\\n\\n    Examples:\\n    ```mlir\\n    // A volatile load of a float variable.\\n    %0 = llvm.load volatile %ptr : !llvm.ptr -> f32\\n\\n    // A nontemporal load of a float variable.\\n    %0 = llvm.load %ptr {nontemporal} : !llvm.ptr -> f32\\n\\n    // An atomic load of an integer variable.\\n    %0 = llvm.load %ptr atomic monotonic {alignment = 8 : i64}\\n        : !llvm.ptr -> i64\\n    ```\\n\\n    See the following link for more details:\\n    https://llvm.org/docs/LangRef.html#load-instruction\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_LoadableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"volatile_\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nontemporal\", \"type\": \"UnitAttr\" },\n      { \"name\": \"invariant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"invariantGroup\", \"type\": \"UnitAttr\" },\n      { \"name\": \"ordering\", \"type\": \"DefaultValuedAttr<AtomicOrdering{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}, AtomicOrdering::not_atomic>\" },\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"dereferenceable\", \"type\": \"OptionalAttr<LLVM_DereferenceableAttr>\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"(`volatile` $volatile_^)? $addr\\n    (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?\\n    (`invariant` $invariant^)?\\n    (`invariant_group` $invariantGroup^)?\\n    (`dereferenceable` `` $dereferenceable^)?\\n    attr-dict `:` qualified(type($addr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"llvm.lshr\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`exact` $isExact^)? $lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.mlir.addressof\",\n    \"summary\": \"Creates a pointer pointing to a global, alias or a function\",\n    \"description\": \"Creates an SSA value containing a pointer to a global value (function,\\n    variable or alias). The global value can be defined after its first\\n    referenced. If the global value is a constant, storing into it is not\\n    allowed.\\n\\n    Examples:\\n\\n    ```mlir\\n    func @foo() {\\n      // Get the address of a global variable.\\n      %0 = llvm.mlir.addressof @const : !llvm.ptr\\n\\n      // Use it as a regular pointer.\\n      %1 = llvm.load %0 : !llvm.ptr -> i32\\n\\n      // Get the address of a function.\\n      %2 = llvm.mlir.addressof @foo : !llvm.ptr\\n\\n      // The function address can be used for indirect calls.\\n      llvm.call %2() : !llvm.ptr, () -> ()\\n\\n      // Get the address of an aliased global.\\n      %3 = llvm.mlir.addressof @const_alias : !llvm.ptr\\n    }\\n\\n    // Define the global.\\n    llvm.mlir.global @const(42 : i32) : i32\\n\\n    // Define an alias.\\n    llvm.mlir.alias @const_alias : i32 {\\n      %0 = llvm.mlir.addressof @const : !llvm.ptr\\n      llvm.return %0 : !llvm.ptr\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global_name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global_name attr-dict `:` qualified(type($res))\"\n  },\n  {\n    \"name\": \"llvm.mlir.alias\",\n    \"summary\": \"LLVM dialect alias.\",\n    \"description\": \"`llvm.mlir.alias` is a top level operation that defines a global alias for\\n    global variables and functions. The operation is always initialized by\\n    using a initializer region which could be a direct map to another global\\n    value or contain some address computation on top of it.\\n\\n    It uses a symbol for its value, which will be uniqued by the module\\n    with respect to other symbols in it.\\n\\n    Similarly to functions and globals, they can also have a linkage attribute.\\n    This attribute is placed between `llvm.mlir.alias` and the symbol name. If\\n    the attribute is omitted, `external` linkage is assumed by default.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Global alias use @-identifiers.\\n    llvm.mlir.alias external @foo_alias {addr_space = 0 : i32} : !llvm.ptr {\\n      %0 = llvm.mlir.addressof @some_function : !llvm.ptr\\n      llvm.return %0 : !llvm.ptr\\n    }\\n\\n    // More complex initialization.\\n    llvm.mlir.alias linkonce_odr hidden @glob\\n    {addr_space = 0 : i32, dso_local} : !llvm.array<32 x i32> {\\n      %0 = llvm.mlir.constant(1234 : i64) : i64\\n      %1 = llvm.mlir.addressof @glob.private : !llvm.ptr\\n      %2 = llvm.ptrtoint %1 : !llvm.ptr to i64\\n      %3 = llvm.add %2, %0 : i64\\n      %4 = llvm.inttoptr %3 : i64 to !llvm.ptr\\n      llvm.return %4 : !llvm.ptr\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"alias_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"linkage\", \"type\": \"Linkage\" },\n      { \"name\": \"dso_local\", \"type\": \"UnitAttr\" },\n      { \"name\": \"thread_local_\", \"type\": \"UnitAttr\" },\n      { \"name\": \"unnamed_addr\", \"type\": \"OptionalAttr<UnnamedAddr{local_unnamed_addr|unnamed_addr}>\" },\n      { \"name\": \"visibility_\", \"type\": \"DefaultValuedAttr<Visibility{hidden|protected}, mlir::LLVM::Visibility::Default>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initializer\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.mlir.constant\",\n    \"summary\": \"Defines a constant of LLVM type.\",\n    \"description\": \"Unlike LLVM IR, MLIR does not have first-class constant values. Therefore,\\n    all constants must be created as SSA values before being used in other\\n    operations. `llvm.mlir.constant` creates such values for scalars, vectors,\\n    strings, structs, and array of structs. It has a mandatory `value` attribute\\n    whose type depends on the type of the constant value. The type of the constant\\n    value must correspond to the attribute type converted to LLVM IR type.\\n\\n    When creating constant scalars, the `value` attribute must be either an\\n    integer attribute or a floating point attribute. The type of the attribute\\n    may be omitted for `i64` and `f64` types that are implied.\\n\\n    When creating constant vectors, the `value` attribute must be either an\\n    array attribute, a dense attribute, or a sparse attribute that contains\\n    integers or floats. The number of elements in the result vector must match\\n    the number of elements in the attribute.\\n\\n    When creating constant strings, the `value` attribute must be a string\\n    attribute. The type of the constant must be an LLVM array of `i8`s, and the\\n    length of the array must match the length of the attribute.\\n\\n    When creating constant structs, the `value` attribute must be an array\\n    attribute that contains integers or floats. The type of the constant must be\\n    an LLVM struct type. The number of fields in the struct must match the\\n    number of elements in the attribute, and the type of each LLVM struct field\\n    must correspond to the type of the corresponding attribute element converted\\n    to LLVM IR.\\n\\n    When creating an array of structs, the `value` attribute must be an array\\n    attribute, itself containing zero, or undef, or array attributes for each\\n    potential nested array type, and the elements of the leaf array attributes\\n    for must match the struct element types or be zero or undef attributes.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Integer constant, internal i32 is mandatory\\n    %0 = llvm.mlir.constant(42 : i32) : i32\\n\\n    // It's okay to omit i64.\\n    %1 = llvm.mlir.constant(42) : i64\\n\\n    // Floating point constant.\\n    %2 = llvm.mlir.constant(42.0 : f32) : f32\\n\\n    // Splat dense vector constant.\\n    %3 = llvm.mlir.constant(dense<1.0> : vector<4xf32>) : vector<4xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.mlir.global\",\n    \"summary\": \"LLVM dialect global.\",\n    \"description\": \"Since MLIR allows for arbitrary operations to be present at the top level,\\n    global variables are defined using the `llvm.mlir.global` operation. Both\\n    global constants and variables can be defined, and the value may also be\\n    initialized in both cases.\\n\\n    There are two forms of initialization syntax. Simple constants that can be\\n    represented as MLIR attributes can be given in-line:\\n\\n    ```mlir\\n    llvm.mlir.global @variable(32.0 : f32) : f32\\n    ```\\n\\n    This initialization and type syntax is similar to `llvm.mlir.constant` and\\n    may use two types: one for MLIR attribute and another for the LLVM value.\\n    These types must be compatible.\\n\\n    More complex constants that cannot be represented as MLIR attributes can be\\n    given in an initializer region:\\n\\n    ```mlir\\n    // This global is initialized with the equivalent of:\\n    //   i32* getelementptr (i32* @g2, i32 2)\\n    llvm.mlir.global constant @int_gep() : !llvm.ptr {\\n      %0 = llvm.mlir.addressof @g2 : !llvm.ptr\\n      %1 = llvm.mlir.constant(2 : i32) : i32\\n      %2 = llvm.getelementptr %0[%1]\\n         : (!llvm.ptr, i32) -> !llvm.ptr, i32\\n      // The initializer region must end with `llvm.return`.\\n      llvm.return %2 : !llvm.ptr\\n    }\\n    ```\\n\\n    Only one of the initializer attribute or initializer region may be provided.\\n\\n    `llvm.mlir.global` must appear at top-level of the enclosing module. It uses\\n    an @-identifier for its value, which will be uniqued by the module with\\n    respect to other @-identifiers in it.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Global values use @-identifiers.\\n    llvm.mlir.global constant @cst(42 : i32) : i32\\n\\n    // Non-constant values must also be initialized.\\n    llvm.mlir.global @variable(32.0 : f32) : f32\\n\\n    // Strings are expected to be of wrapped LLVM i8 array type and do not\\n    // automatically include the trailing zero.\\n    llvm.mlir.global @string(\\\"abc\\\") : !llvm.array<3 x i8>\\n\\n    // For strings globals, the trailing type may be omitted.\\n    llvm.mlir.global constant @no_trailing_type(\\\"foo bar\\\")\\n\\n    // A complex initializer is constructed with an initializer region.\\n    llvm.mlir.global constant @int_gep() : !llvm.ptr {\\n      %0 = llvm.mlir.addressof @g2 : !llvm.ptr\\n      %1 = llvm.mlir.constant(2 : i32) : i32\\n      %2 = llvm.getelementptr %0[%1]\\n         : (!llvm.ptr, i32) -> !llvm.ptr, i32\\n      llvm.return %2 : !llvm.ptr\\n    }\\n    ```\\n\\n    Similarly to functions, globals have a linkage attribute. In the custom\\n    syntax, this attribute is placed between `llvm.mlir.global` and the optional\\n    `constant` keyword. If the attribute is omitted, `external` linkage is\\n    assumed by default.\\n\\n    Examples:\\n\\n    ```mlir\\n    // A constant with internal linkage will not participate in linking.\\n    llvm.mlir.global internal constant @cst(42 : i32) : i32\\n\\n    // By default, \\\"external\\\" linkage is assumed and the global participates in\\n    // symbol resolution at link-time.\\n    llvm.mlir.global @glob(0 : f32) : f32\\n\\n    // Alignment is optional\\n    llvm.mlir.global private constant @y(dense<1.0> : tensor<8xf32>) : !llvm.array<8 x f32>\\n    ```\\n\\n    Like global variables in LLVM IR, globals can have an (optional)\\n    alignment attribute using keyword `alignment`. The integer value of the\\n    alignment must be a positive integer that is a power of 2.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Alignment is optional\\n    llvm.mlir.global private constant @y(dense<1.0> : tensor<8xf32>) { alignment = 32 : i64 } : !llvm.array<8 x f32>\\n    ```\\n\\n    The `target_specific_attrs` attribute provides a mechanism to preserve\\n    target-specific LLVM IR attributes that are not explicitly modeled in the\\n    LLVM dialect.\\n\\n    The attribute is an array containing either string attributes or\\n    two-element array attributes of strings. The value of a standalone string\\n    attribute is interpreted as the name of an LLVM IR attribute on the global.\\n    A two-element array is interpreted as a key-value pair.\\n\\n    Example:\\n\\n    ```mlir\\n    llvm.mlir.global external @example() {\\n      target_specific_attrs = [\\\"value-less-attr\\\", [\\\"int-attr\\\", \\\"4\\\"], [\\\"string-attr\\\", \\\"string\\\"]]} : f64\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"global_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"linkage\", \"type\": \"Linkage\" },\n      { \"name\": \"dso_local\", \"type\": \"UnitAttr\" },\n      { \"name\": \"thread_local_\", \"type\": \"UnitAttr\" },\n      { \"name\": \"externally_initialized\", \"type\": \"UnitAttr\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"addr_space\", \"type\": \"DefaultValuedAttr<ConfinedAttr<I32Attr, [ IntNonNegative ]>, 0>\" },\n      { \"name\": \"unnamed_addr\", \"type\": \"OptionalAttr<UnnamedAddr{local_unnamed_addr|unnamed_addr}>\" },\n      { \"name\": \"section\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"comdat\", \"type\": \"OptionalAttr<SymbolRefAttr>\" },\n      { \"name\": \"dbg_exprs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_DIGlobalVariableExpressionAttr>>\" },\n      { \"name\": \"visibility_\", \"type\": \"DefaultValuedAttr<Visibility{hidden|protected}, mlir::LLVM::Visibility::Default>\" },\n      { \"name\": \"target_specific_attrs\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initializer\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"llvm.mlir.global_ctors\",\n    \"summary\": \"LLVM dialect global_ctors.\",\n    \"description\": \"Specifies a list of constructor functions, priorities, and associated data.\\n    The functions referenced by this array will be called in ascending order\\n    of priority (i.e. lowest first) when the module is loaded. The order of\\n    functions with the same priority is not defined. This operation is\\n    translated to LLVM's global_ctors global variable. The initializer\\n    functions are run at load time. However, if the associated data is not\\n    `#llvm.zero`, functions only run if the data is not discarded.\\n\\n    Examples:\\n\\n    ```mlir\\n    llvm.func @ctor() {\\n      ...\\n      llvm.return\\n    }\\n    llvm.mlir.global_ctors ctors = [@ctor], priorities = [0],\\n                                   data = [#llvm.zero]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"ctors\", \"type\": \"TypedArrayAttrBase<FlatSymbolRefAttr>\" },\n      { \"name\": \"priorities\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"data\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`ctors` `=` $ctors\\n    `,` `priorities` `=` $priorities\\n    `,` `data` `=` $data\\n    attr-dict\"\n  },\n  {\n    \"name\": \"llvm.mlir.global_dtors\",\n    \"summary\": \"LLVM dialect global_dtors.\",\n    \"description\": \"Specifies a list of destructor functions and priorities. The functions\\n    referenced by this array will be called in descending order of priority\\n    (i.e. highest first) when the module is unloaded. The order of functions\\n    with the same priority is not defined. This operation is translated to\\n    LLVM's global_dtors global variable. The destruction functions are run at\\n    load time. However, if the associated data is not `#llvm.zero`, functions\\n    only run if the data is not discarded.\\n\\n    Examples:\\n\\n    ```mlir\\n    llvm.func @dtor() {\\n      llvm.return\\n    }\\n    llvm.mlir.global_dtors dtors = [@dtor], priorities = [0],\\n                                   data = [#llvm.zero]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"dtors\", \"type\": \"TypedArrayAttrBase<FlatSymbolRefAttr>\" },\n      { \"name\": \"priorities\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"data\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`dtors` `=` $dtors\\n    `,` `priorities` `=` $priorities\\n    `,` `data` `=` $data\\n    attr-dict\"\n  },\n  {\n    \"name\": \"llvm.mlir.ifunc\",\n    \"summary\": \"LLVM dialect ifunc\",\n    \"description\": \"`llvm.mlir.ifunc` is a top level operation that defines a global ifunc.\\n    It defines a new symbol and takes a symbol refering to a resolver function.\\n    IFuncs can be called as regular functions. The function type is the same\\n    as the IFuncType. The symbol is resolved at runtime by calling a resolver\\n    function.\\n\\n    Examples:\\n\\n    ```mlir\\n    // IFuncs resolve a symbol at runtime using a resovler function.\\n    llvm.mlir.ifunc external @foo: !llvm.func<f32 (i64)>, !llvm.ptr @resolver\\n\\n    llvm.func @foo_1(i64) -> f32\\n    llvm.func @foo_2(i64) -> f32\\n\\n    llvm.func @resolve_foo() -> !llvm.ptr attributes {\\n      %0 = llvm.mlir.addressof @foo_2 : !llvm.ptr\\n      %1 = llvm.mlir.addressof @foo_1 : !llvm.ptr\\n\\n      // ... Logic selecting from foo_{1, 2}\\n\\n      // Return function pointer to the selected function\\n      llvm.return %7 : !llvm.ptr\\n    }\\n\\n    llvm.func @use_foo() {\\n      // IFuncs are called as regular functions\\n      %res = llvm.call @foo(%value) : i64 -> f32\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"i_func_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"resolver\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"resolver_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"linkage\", \"type\": \"Linkage\" },\n      { \"name\": \"dso_local\", \"type\": \"UnitAttr\" },\n      { \"name\": \"address_space\", \"type\": \"DefaultValuedAttr<ConfinedAttr<I32Attr, [ IntNonNegative ]>, 0>\" },\n      { \"name\": \"unnamed_addr\", \"type\": \"DefaultValuedAttr<UnnamedAddr{local_unnamed_addr|unnamed_addr}, mlir::LLVM::UnnamedAddr::None>\" },\n      { \"name\": \"visibility_\", \"type\": \"DefaultValuedAttr<Visibility{hidden|protected}, mlir::LLVM::Visibility::Default>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<LLVMLinkage>($linkage) ($visibility_^)? ($unnamed_addr^)?\\n    $sym_name `:` $i_func_type `,` $resolver_type $resolver attr-dict\"\n  },\n  {\n    \"name\": \"llvm.mlir.none\",\n    \"summary\": \"Defines a value containing an empty token to LLVM type.\",\n    \"description\": \"Unlike LLVM IR, MLIR does not have first-class token values. They must be\\n    explicitly created as SSA values using `llvm.mlir.none`. This operation has\\n    no operands or attributes, and returns a none token value of a wrapped LLVM IR\\n    pointer type.\\n\\n    Examples:\\n\\n    ```mlir\\n    %0 = llvm.mlir.none : !llvm.token\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_TokenType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.mlir.poison\",\n    \"summary\": \"Creates a poison value of LLVM dialect type.\",\n    \"description\": \"Unlike LLVM IR, MLIR does not have first-class poison values. Such values\\n    must be created as SSA values using `llvm.mlir.poison`. This operation has\\n    no operands or attributes. It creates a poison value of the specified LLVM\\n    IR dialect type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Create a poison value for a structure with a 32-bit integer followed\\n    // by a float.\\n    %0 = llvm.mlir.poison : !llvm.struct<(i32, f32)>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.mlir.undef\",\n    \"summary\": \"Creates an undefined value of LLVM dialect type.\",\n    \"description\": \"Unlike LLVM IR, MLIR does not have first-class undefined values. Such values\\n    must be created as SSA values using `llvm.mlir.undef`. This operation has no\\n    operands or attributes. It creates an undefined value of the specified LLVM\\n    IR dialect type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Create a structure with a 32-bit integer followed by a float.\\n    %0 = llvm.mlir.undef : !llvm.struct<(i32, f32)>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.mlir.zero\",\n    \"summary\": \"Creates a zero-initialized value of LLVM dialect type.\",\n    \"description\": \"Unlike LLVM IR, MLIR does not have first-class zero-initialized values.\\n    Such values must be created as SSA values using `llvm.mlir.zero`. This\\n    operation has no operands or attributes. It creates a zero-initialized\\n    value of the specified LLVM IR dialect type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Create a zero-initialized value for a structure with a 32-bit integer\\n    // followed by a float.\\n    %0 = llvm.mlir.zero : !llvm.struct<(i32, f32)>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.module_flags\",\n    \"summary\": \"Information about module properties\",\n    \"description\": \"Represents the equivalent in MLIR for LLVM's `llvm.module.flags` metadata,\\n    which requires a list of metadata triplets. Each triplet entry is described\\n    by a `ModuleFlagAttr`.\\n\\n    Example:\\n    ```mlir\\n    llvm.module.flags [\\n      #llvm.mlir.module_flag<error, \\\"wchar_size\\\", 4>,\\n      #llvm.mlir.module_flag<max, \\\"PIC Level\\\", 2>\\n    ]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$flags attr-dict\"\n  },\n  {\n    \"name\": \"llvm.mul\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"LLVM_IntegerOverflowFlagsProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs ($overflowFlags^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.named_metadata\",\n    \"summary\": \"Module-level named metadata\",\n    \"description\": \"Represents an LLVM named metadata node (`llvm::NamedMDNode`). Named\\n    metadata nodes are module-level metadata that associate a name string\\n    with a list of metadata nodes. Each operand must be an `#llvm.md_node`.\\n\\n    Note: cyclic metadata graphs are not supported. Because metadata attributes\\n    are represented as MLIR attributes (which form a tree), there is no way to\\n    express a metadata node that directly or transitively references itself.\\n    LLVM IR permits such cycles (e.g. `!0 = !{!0}`), but they cannot be\\n    represented here and will not round-trip through this op.\\n\\n    Example:\\n    ```mlir\\n    llvm.named_metadata \\\"foo.version\\\" [\\n      #llvm.md_node<#llvm.md_const<2 : i32>,\\n                    #llvm.md_const<9 : i32>,\\n                    #llvm.md_const<0 : i32>\\n      >\\n    ]\\n    llvm.named_metadata \\\"foo.kernel\\\" [\\n      #llvm.md_node<\\n        #llvm.md_func<@my_kernel>,\\n        #llvm.md_node<>,\\n        #llvm.md_node<\\n          #llvm.md_node<#llvm.md_const<0 : i32>,\\n                        #llvm.md_string<\\\"foo.buffer\\\">\\n          >\\n        >\\n      >\\n    ]\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"metadata_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"nodes\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$metadata_name $nodes attr-dict\"\n  },\n  {\n    \"name\": \"llvm.or\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isDisjoint\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`disjoint` $isDisjoint^)? $lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.ptrtoaddr\",\n    \"description\": \"Operation mirroring LLVM's `ptrtoaddr` operation.\\n\\n    This operation casts a pointer (or a vector of pointers) to an integer\\n    (or a vector of integers) without capturing the provenance of the pointer.\\n    Therefore, an integer returned or derived from `llvm.ptrtoaddr` does not\\n    create a legal-to-access pointer when used in `llvm.inttoptr`.\\n    Code that only cares about the address value of a pointer\\n    (e.g. pointer subtraction) should prefer `llvm.ptrtoaddr` over\\n    `llvm.ptrtoint`.\\n\\n    The integer type used as the result type is required to be equal in width\\n    to the pointer type as specified in the data layout.\\n    Use the `llvm-target-to-data-layout` pass to derive an MLIR datalayout from\\n    an LLVM datalayout.\\n\\n    Examples:\\n    ```\\n    llvm.func @default_64_bit_ptrtoaddr(%arg0 : !llvm.ptr) -> i64 {\\n      %0 = llvm.ptrtoaddr %arg0 : !llvm.ptr to i64\\n      llvm.return i64\\n    }\\n\\n    module attributes { dlti.dl_spec = #dlti.dl_spec<\\n      #dlti.dl_entry<!llvm.ptr, dense<[/*size=*/32, 32, 64]> : vector<3xi64>>\\n    >} {\\n      llvm.func @datalayout_32_bit(%arg0 : !llvm.ptr) -> i32 {\\n        %0 = llvm.ptrtoaddr %arg0 : !llvm.ptr to i32\\n        llvm.return %0 : i32\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.ptrtoint\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyPointer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.resume\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"llvm.return\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Optional<LLVM_Type>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($arg^ `:` type($arg))?\"\n  },\n  {\n    \"name\": \"llvm.sdiv\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`exact` $isExact^)? $lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.select\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"LLVM_ScalarOrVectorOf<I1>\" },\n      { \"name\": \"trueValue\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"falseValue\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmathFlags\", \"type\": \"DefaultValuedAttr<LLVM_FastmathFlagsAttr{none|nnan|ninf|nsz|arcp|contract|afn|reassoc|fast}, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['trueValue', 'falseValue', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($condition) `,` type($res)\"\n  },\n  {\n    \"name\": \"llvm.sext\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.shl\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"LLVM_IntegerOverflowFlagsProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs ($overflowFlags^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.shufflevector\",\n    \"summary\": \"Construct a permutation of two vectors.\",\n    \"operands\": [\n      { \"name\": \"v1\", \"type\": \"LLVM_AnyVector\" },\n      { \"name\": \"v2\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mask\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['v1', 'v2']>\" }\n    ],\n    \"assemblyFormat\": \"$v1 `,` $v2 $mask attr-dict `:` type($v1)\\n    custom<ShuffleType>(ref(type($v1)), type($res), ref($mask))\"\n  },\n  {\n    \"name\": \"llvm.sitofp\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.srem\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.store\",\n    \"description\": \"The `store` operation is used to write to memory. A store may be marked as\\n    atomic, volatile, and/or nontemporal, and takes a number of optional\\n    attributes that specify aliasing information.\\n\\n    An atomic store only supports a limited set of pointer, integer, and\\n    floating point types, and requires an explicit alignment.\\n\\n    Examples:\\n    ```mlir\\n    // A volatile store of a float variable.\\n    llvm.store volatile %val, %ptr : f32, !llvm.ptr\\n\\n    // A nontemporal store of a float variable.\\n    llvm.store %val, %ptr {nontemporal} : f32, !llvm.ptr\\n\\n    // An atomic store of an integer variable.\\n    llvm.store %val, %ptr atomic monotonic {alignment = 8 : i64}\\n        : i64, !llvm.ptr\\n    ```\\n\\n    See the following link for more details:\\n    https://llvm.org/docs/LangRef.html#store-instruction\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"LLVM_LoadableType\" },\n      { \"name\": \"addr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"volatile_\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nontemporal\", \"type\": \"UnitAttr\" },\n      { \"name\": \"invariantGroup\", \"type\": \"UnitAttr\" },\n      { \"name\": \"ordering\", \"type\": \"DefaultValuedAttr<AtomicOrdering{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}, AtomicOrdering::not_atomic>\" },\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"access_groups\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AccessGroupAttr>>\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"(`volatile` $volatile_^)? $value `,` $addr\\n    (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?\\n    (`invariant_group` $invariantGroup^)?\\n    attr-dict `:` type($value) `,` qualified(type($addr))\"\n  },\n  {\n    \"name\": \"llvm.sub\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"LLVM_IntegerOverflowFlagsProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs ($overflowFlags^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.switch\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnySignlessInteger\" },\n      { \"name\": \"defaultOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"caseOperands\", \"type\": \"VariadicOfVariadic<AnyType, case_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"case_values\", \"type\": \"OptionalAttr<AnyIntElementsAttr>\" },\n      { \"name\": \"case_operand_segments\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"branch_weights\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDestination\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"caseDestinations\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) `,`\\n    $defaultDestination (`(` $defaultOperands^ `:` type($defaultOperands) `)`)?\\n    custom<SwitchOpCases>(ref(type($value)), $case_values, $caseDestinations,\\n                                   $caseOperands, type($caseOperands))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"llvm.trunc\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"overflowFlags\", \"type\": \"LLVM_IntegerOverflowFlagsProp\" }\n    ],\n    \"assemblyFormat\": \"$arg ($overflowFlags^)? attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.udiv\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isExact\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`exact` $isExact^)? $lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.uitofp\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nonNeg\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`nneg` $nonNeg^)? $arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"llvm.unreachable\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"llvm.urem\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.va_arg\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` functional-type($arg, $res)\"\n  },\n  {\n    \"name\": \"llvm.xor\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" },\n      { \"name\": \"rhs\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"llvm.zext\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnySignlessInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nonNeg\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`nneg` $nonNeg^)? $arg attr-dict `:` type($arg) `to` type($res)\"\n  },\n  {\n    \"name\": \"math.absf\",\n    \"summary\": \"floating point absolute-value operation\",\n    \"description\": \"The `absf` operation computes the absolute value. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result\\n    of the same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar absolute value.\\n    %a = math.absf %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.absi\",\n    \"summary\": \"integer absolute-value operation\",\n    \"description\": \"The `absi` operation computes the absolute value. It takes one operand of\\n    integer type (i.e., scalar, tensor or vector) and returns one result of the\\n    same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar absolute value.\\n    %a = math.absi %b : i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.acos\",\n    \"summary\": \"arcus cosine of the specified value\",\n    \"description\": \"The `acos` operation computes the arcus cosine of a given value. It takes one\\n    operand of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type.  It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar arcus cosine value.\\n    %a = math.acos %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.acosh\",\n    \"summary\": \"Hyperbolic arcus cosine of the given value\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= ssa-id `=` `math.acosh` ssa-use `:` type\\n    ```\\n\\n    The `acosh` operation computes the arcus cosine of a given value.  It takes\\n    one operand of floating point type (i.e., scalar, tensor or vector) and returns\\n    one result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Hyperbolic arcus cosine of scalar value.\\n    %a = math.acosh %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.asin\",\n    \"summary\": \"arcus sine of the given value\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= ssa-id `=` `math.asin` ssa-use `:` type\\n    ```\\n\\n    The `asin` operation computes the arcus sine of a given value.  It takes\\n    one operand of floating point type (i.e., scalar, tensor or vector) and returns\\n    one result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Arcus sine of scalar value.\\n    %a = math.asin %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.asinh\",\n    \"summary\": \"hyperbolic arcus sine of the given value\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= ssa-id `=` `math.asinh` ssa-use `:` type\\n    ```\\n\\n    The `asinh` operation computes the hyperbolic arcus sine of a given value.  It takes\\n    one operand of floating point type (i.e., scalar, tensor or vector) and returns\\n    one result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Hyperbolic arcus sine of scalar value.\\n    %a = math.asinh %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.atan\",\n    \"summary\": \"arcus tangent of the given value\",\n    \"description\": \"The `atan` operation computes the arcus tangent of a given value.  It takes\\n    one operand of floating point type (i.e., scalar, tensor or vector) and returns\\n    one result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Arcus tangent of scalar value.\\n    %a = math.atan %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.atan2\",\n    \"summary\": \"2-argument arcus tangent of the given values\",\n    \"description\": \"The `atan2` operation takes two operands and returns one result, all of\\n    which must be of the same type.  The operands must be of floating point type\\n    (i.e., scalar, tensor or vector).\\n\\n    The 2-argument arcus tangent `atan2(y, x)` returns the angle in the\\n    Euclidian plane between the positive x-axis and the ray through the point\\n    (x, y).  It is a generalization of the 1-argument arcus tangent which\\n    returns the angle on the basis of the ratio y/x.\\n\\n    See also https://en.wikipedia.org/wiki/Atan2\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar variant.\\n    %a = math.atan2 %b, %c : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.atanh\",\n    \"summary\": \"hyperbolic arcus tangent of the given value\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= ssa-id `=` `math.atanh` ssa-use `:` type\\n    ```\\n\\n    The `atanh` operation computes the hyperbolic arcus tangent of a given value.  It takes\\n    one operand of floating point type (i.e., scalar, tensor or vector) and returns\\n    one result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Hyperbolic arcus tangent of scalar value.\\n    %a = math.atanh %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.cbrt\",\n    \"summary\": \"cube root of the specified value\",\n    \"description\": \"The `cbrt` operation computes the cube root. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result\\n    of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar cube root value.\\n    %a = math.cbrt %b : f64\\n    ```\\n\\n    Note: This op is not equivalent to powf(..., 1/3.0).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.ceil\",\n    \"summary\": \"ceiling of the specified value\",\n    \"description\": \"The `ceil` operation computes the ceiling of a given value. It takes one\\n    operand of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type.  It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar ceiling value.\\n    %a = math.ceil %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.clampf\",\n    \"summary\": \"floating point clamping operation\",\n    \"description\": \"The `clampf` operation takes three operands and returns one result, each of\\n    these is required to be the same type. Operands must be of floating point type\\n    (i.e., scalar, tensor or vector).\\n\\n    The semantics of the operation are described by:\\n    ```\\n      clampf(value, min, max) = maxf(minf(value, max), min)\\n    ```\\n    If `min > max` the resulting value is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    %d = math.clampf %value to [%min, %max] : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"FloatLike\" },\n      { \"name\": \"min\", \"type\": \"FloatLike\" },\n      { \"name\": \"max\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$value `to` ` ` `[` $min `,` $max `]` (`fastmath` `` $fastmath^)?\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.copysign\",\n    \"summary\": \"A copysign operation\",\n    \"description\": \"The `copysign` returns a value with the magnitude of the first operand and\\n    the sign of the second operand. It takes two operands and returns one result of\\n    the same type. The operands must be of floating point type (i.e., scalar,\\n    tensor or vector). It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar copysign value.\\n    %a = math.copysign %b, %c : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.cos\",\n    \"summary\": \"cosine of the specified value\",\n    \"description\": \"The `cos` operation computes the cosine of a given value. It takes one\\n    operand of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type.  It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar cosine value.\\n    %a = math.cos %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.cosh\",\n    \"summary\": \"hyperbolic cosine of the specified value\",\n    \"description\": \"The `cosh` operation computes the hyperbolic cosine. It takes one operand\\n    of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar hyperbolic cosine value.\\n    %a = math.cosh %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.ctlz\",\n    \"summary\": \"counts the leading zeros an integer value\",\n    \"description\": \"The `ctlz` operation computes the number of leading zeros of an integer value.\\n    It operates on scalar, tensor or vector.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar ctlz function value.\\n    %a = math.ctlz %b : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.ctpop\",\n    \"summary\": \"counts the number of set bits of an integer value\",\n    \"description\": \"The `ctpop` operation computes the number of set bits of an integer value.\\n    It operates on scalar, tensor or vector.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar ctpop function value.\\n    %a = math.ctpop %b : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.cttz\",\n    \"summary\": \"counts the trailing zeros an integer value\",\n    \"description\": \"The `cttz` operation computes the number of trailing zeros of an integer value.\\n    It operates on scalar, tensor or vector.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar cttz function value.\\n    %a = math.cttz %b : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.erf\",\n    \"summary\": \"error function of the specified value\",\n    \"description\": \"The `erf` operation computes the error function. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result of\\n    the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar error function value.\\n    %a = math.erf %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.erfc\",\n    \"summary\": \"complementary error function of the specified value\",\n    \"description\": \"The `erfc` operation computes the complementary error function, defined as\\n    1-erf(x). This function is part of libm and is needed for accuracy, since\\n    simply calculating 1-erf(x) when x is close to 1 will give inaccurate results.\\n    It takes one operand of floating point type (i.e., scalar,\\n    tensor or vector) and returns one result of the same type. It has no\\n    standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar error function value.\\n    %a = math.erfc %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.exp\",\n    \"summary\": \"base-e exponential of the specified value\",\n    \"description\": \"The `exp` operation takes one operand of floating point type (i.e., scalar,\\n    tensor or vector) and returns one result of the same type. It has no standard\\n    attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar natural exponential.\\n    %a = math.exp %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.exp2\",\n    \"summary\": \"base-2 exponential of the specified value\",\n    \"description\": \"The `exp` operation takes one operand of floating point type (i.e., scalar,\\n    tensor or vector) and returns one result of the same type. It has no standard\\n    attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar natural exponential.\\n    %a = math.exp2 %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.expm1\",\n    \"summary\": \"base-e exponential of the specified value minus 1\",\n    \"description\": \"expm1(x) := exp(x) - 1\\n\\n    The `expm1` operation takes one operand of floating point type (i.e.,\\n    scalar, tensor or vector) and returns one result of the same type. It has no\\n    standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar natural exponential minus 1.\\n    %a = math.expm1 %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.floor\",\n    \"summary\": \"floor of the specified value\",\n    \"description\": \"The `floor` operation computes the floor of a given value. It takes one\\n    operand of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type.  It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar floor value.\\n    %a = math.floor %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.fma\",\n    \"summary\": \"floating point fused multipy-add operation\",\n    \"description\": \"The `fma` operation takes three operands and returns one result, each of\\n    these is required to be the same type. Operands must be of floating point type\\n    (i.e., scalar, tensor or vector).\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar fused multiply-add: d = a*b + c\\n    %d = math.fma %a, %b, %c : f64\\n    ```\\n\\n    The semantics of the operation correspond to those of the `llvm.fma`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#llvm-fma-intrinsic). In the\\n    particular case of lowering to LLVM, this is guaranteed to lower\\n    to the `llvm.fma.*` intrinsic.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"FloatLike\" },\n      { \"name\": \"b\", \"type\": \"FloatLike\" },\n      { \"name\": \"c\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.fpowi\",\n    \"summary\": \"floating point raised to the signed integer power\",\n    \"description\": \"The `fpowi` operation takes a `base` operand of floating point type\\n    (i.e. scalar, tensor or vector) and a `power` operand of integer type\\n    (also scalar, tensor or vector) and returns one result of the same type\\n    as `base`. The result is `base` raised to the power of `power`.\\n    The operation is elementwise for non-scalars, e.g.:\\n\\n    ```mlir\\n    %v = math.fpowi %base, %power : vector<2xf32>, vector<2xi32\\n    ```\\n\\n    The result is a vector of:\\n\\n    ```\\n    [<math.fpowi %base[0], %power[0]>, <math.fpowi %base[1], %power[1]>]\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar exponentiation.\\n    %a = math.fpowi %base, %power : f64, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($lhs) `,` type($rhs)\"\n  },\n  {\n    \"name\": \"math.ipowi\",\n    \"summary\": \"signed integer raised to the power of operation\",\n    \"description\": \"The `ipowi` operation takes two operands of integer type (i.e., scalar,\\n    tensor or vector) and returns one result of the same type. Operands\\n    must have the same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar signed integer exponentiation.\\n    %a = math.ipowi %b, %c : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SignlessIntegerOrIndexLike\" },\n      { \"name\": \"rhs\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.isfinite\",\n    \"summary\": \"returns true if the operand classifies as finite\",\n    \"description\": \"Determines if the given floating-point number has finite value i.e. it\\n    is normal, subnormal or zero, but not infinite or NaN.\\n\\n    Example:\\n\\n    ```mlir\\n    %f = math.isfinite %a : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', '::getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"math.isinf\",\n    \"summary\": \"returns true if the operand classifies as infinite\",\n    \"description\": \"Determines if the given floating-point number is positive or negative\\n    infinity.\\n\\n    Example:\\n\\n    ```mlir\\n    %f = math.isinf %a : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', '::getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"math.isnan\",\n    \"summary\": \"returns true if the operand classifies as NaN\",\n    \"description\": \"Determines if the given floating-point number is a not-a-number (NaN)\\n    value.\\n\\n    Example:\\n\\n    ```mlir\\n    %f = math.isnan %a : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', '::getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"math.isnormal\",\n    \"summary\": \"returns true if the operand classifies as normal\",\n    \"description\": \"Determines if the given floating-point number is normal, i.e. is neither\\n    zero, subnormal, infinite, nor NaN.\\n\\n    Example:\\n\\n    ```mlir\\n    %f = math.isnormal %a : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', '::getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"math.log\",\n    \"summary\": \"base-e logarithm of the specified value\",\n    \"description\": \"Computes the base-e logarithm of the given value. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result of\\n    the same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar log operation.\\n    %y = math.log %x : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.log10\",\n    \"summary\": \"base-10 logarithm of the specified value\",\n    \"description\": \"Computes the base-10 logarithm of the given value. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result of\\n    the same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar log10 operation.\\n    %y = math.log10 %x : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.log1p\",\n    \"summary\": \"Computes the natural logarithm of one plus the given value\",\n    \"description\": \"Computes the base-e logarithm of one plus the given value. It takes one\\n    operand of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type.\\n\\n    log1p(x) := log(1 + x)\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar log1p operation.\\n    %y = math.log1p %x : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.log2\",\n    \"summary\": \"base-2 logarithm of the specified value\",\n    \"description\": \"Computes the base-2 logarithm of the given value. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result of\\n    the same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar log2 operation.\\n    %y = math.log2 %x : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.powf\",\n    \"summary\": \"floating point raised to the power of operation\",\n    \"description\": \"The `powf` operation takes two operands of floating point type (i.e.,\\n    scalar, tensor or vector) and returns one result of the same type. Operands\\n    must have the same type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar exponentiation.\\n    %a = math.powf %b, %c : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"FloatLike\" },\n      { \"name\": \"rhs\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.round\",\n    \"summary\": \"round of the specified value\",\n    \"description\": \"The `round` operation returns the operand rounded to the nearest integer\\n    value in floating-point format. It takes one operand of floating point type\\n    (i.e., scalar, tensor or vector) and produces one result of the same type.  The\\n    operation rounds the argument to the nearest integer value in floating-point\\n    format, rounding halfway cases away from zero, regardless of the current\\n    rounding direction.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar round operation.\\n    %a = math.round %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.roundeven\",\n    \"summary\": \"round of the specified value with halfway cases to even\",\n    \"description\": \"The `roundeven` operation returns the operand rounded to the nearest integer\\n    value in floating-point format. It takes one operand of floating point type\\n    (i.e., scalar, tensor or vector) and produces one result of the same type.  The\\n    operation rounds the argument to the nearest integer value in floating-point\\n    format, rounding halfway cases to even, regardless of the current\\n    rounding direction.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar round operation.\\n    %a = math.roundeven %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.rsqrt\",\n    \"summary\": \"reciprocal of sqrt (1 / sqrt of the specified value)\",\n    \"description\": \"The `rsqrt` operation computes the reciprocal of the square root. It takes\\n    one operand of floating point type (i.e., scalar, tensor or vector) and returns\\n    one result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar reciprocal square root value.\\n    %a = math.rsqrt %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.sin\",\n    \"summary\": \"sine of the specified value\",\n    \"description\": \"The `sin` operation computes the sine of a given value. It takes one\\n    operand of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type.  It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar sine value.\\n    %a = math.sin %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.sincos\",\n    \"summary\": \"sine and cosine of the specified value\",\n    \"description\": \"The `sincos` operation computes both the sine and cosine of a given value\\n    simultaneously. It takes one operand of floating point type (i.e., scalar,\\n    tensor or vector) and returns two results of the same type. This operation\\n    can be more efficient than computing sine and cosine separately when both\\n    values are needed.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar sine and cosine values.\\n    %sin, %cos = math.sincos %input : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"sin\", \"type\": \"FloatLike\" },\n      { \"name\": \"cos\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'sin', 'cos']>\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"math.sinh\",\n    \"summary\": \"hyperbolic sine of the specified value\",\n    \"description\": \"The `sinh` operation computes the hyperbolic sine. It takes one operand\\n    of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar hyperbolic sine value.\\n    %a = math.sinh %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.sqrt\",\n    \"summary\": \"sqrt of the specified value\",\n    \"description\": \"The `sqrt` operation computes the square root. It takes one operand of\\n    floating point type (i.e., scalar, tensor or vector) and returns one result of\\n    the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar square root value.\\n    %a = math.sqrt %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.tan\",\n    \"summary\": \"tangent of the specified value\",\n    \"description\": \"The `tan` operation computes the tangent. It takes one operand\\n    of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar tangent value.\\n    %a = math.tan %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.tanh\",\n    \"summary\": \"hyperbolic tangent of the specified value\",\n    \"description\": \"The `tanh` operation computes the hyperbolic tangent. It takes one operand\\n    of floating point type (i.e., scalar, tensor or vector) and returns one\\n    result of the same type. It has no standard attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar hyperbolic tangent value.\\n    %a = math.tanh %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"math.trunc\",\n    \"summary\": \"trunc of the specified value\",\n    \"description\": \"The `trunc` operation returns the operand rounded to the nearest integer\\n    value in floating-point format. It takes one operand of floating point type\\n    (i.e., scalar, tensor or vector) and produces one result of the same type.\\n    The operation always rounds to the nearest integer not larger in magnitude\\n    than the operand, regardless of the current rounding direction.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar trunc operation.\\n    %a = math.trunc %b : f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand (`fastmath` `` $fastmath^)?\\n                          attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"memref.alloc\",\n    \"summary\": \"memory allocation operation\",\n    \"description\": \"The `alloc` operation allocates a region of memory, as specified by its\\n    memref type.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = memref.alloc() : memref<8x64xf32, 1>\\n    ```\\n\\n    The optional list of dimension operands are bound to the dynamic dimensions\\n    specified in its memref type. In the example below, the ssa value '%d' is\\n    bound to the second dimension of the memref (which is dynamic).\\n\\n    ```mlir\\n    %0 = memref.alloc(%d) : memref<8x?xf32, 1>\\n    ```\\n\\n    The optional list of symbol operands are bound to the symbols of the\\n    memrefs affine map. In the example below, the ssa value '%s' is bound to\\n    the symbol 's0' in the affine map specified in the allocs memref type.\\n\\n    ```mlir\\n    %0 = memref.alloc()[%s] : memref<8x64xf32,\\n                              affine_map<(d0, d1)[s0] -> ((d0 + s0), d1)>, 1>\\n    ```\\n\\n    This operation returns a single ssa value of memref type, which can be used\\n    by subsequent load and store operations.\\n\\n    The optional `alignment` attribute may be specified to ensure that the\\n    region of memory that will be indexed is aligned at the specified byte\\n    boundary.\\n\\n    ```mlir\\n    %0 = memref.alloc()[%s] {alignment = 8} :\\n      memref<8x64xf32, affine_map<(d0, d1)[s0] -> ((d0 + s0), d1)>, 1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"symbolOperands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(`$dynamicSizes`)` (`` `[` $symbolOperands^ `]`)? attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.alloca\",\n    \"summary\": \"stack memory allocation operation\",\n    \"description\": \"The `alloca` operation allocates memory on the stack, to be automatically\\n    released when control transfers back from the region of its closest\\n    surrounding operation with an\\n    [`AutomaticAllocationScope`](../Traits/#automaticallocationscope) trait.\\n    The amount of memory allocated is specified by its memref and additional\\n    operands. For example:\\n\\n    ```mlir\\n    %0 = memref.alloca() : memref<8x64xf32>\\n    ```\\n\\n    The optional list of dimension operands are bound to the dynamic dimensions\\n    specified in its memref type. In the example below, the SSA value '%d' is\\n    bound to the second dimension of the memref (which is dynamic).\\n\\n    ```mlir\\n    %0 = memref.alloca(%d) : memref<8x?xf32>\\n    ```\\n\\n    The optional list of symbol operands are bound to the symbols of the\\n    memref's affine map. In the example below, the SSA value '%s' is bound to\\n    the symbol 's0' in the affine map specified in the allocs memref type.\\n\\n    ```mlir\\n    %0 = memref.alloca()[%s] : memref<8x64xf32,\\n                               affine_map<(d0, d1)[s0] -> ((d0 + s0), d1)>>\\n    ```\\n\\n    This operation returns a single SSA value of memref type, which can be used\\n    by subsequent load and store operations. An optional alignment attribute, if\\n    specified, guarantees alignment at least to that boundary. If not specified,\\n    an alignment on any convenient boundary compatible with the type will be\\n    chosen.\",\n    \"operands\": [\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"symbolOperands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(`$dynamicSizes`)` (`` `[` $symbolOperands^ `]`)? attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.alloca_scope\",\n    \"summary\": \"explicitly delimited scope for stack allocation\",\n    \"description\": \"The `memref.alloca_scope` operation represents an explicitly-delimited\\n    scope for the alloca allocations. Any `memref.alloca` operations that are\\n    used within this scope are going to be cleaned up automatically once\\n    the control-flow exits the nested region. For example:\\n\\n    ```mlir\\n    memref.alloca_scope {\\n      %myalloca = memref.alloca(): memref<4x3xf32>\\n      ...\\n    }\\n    ```\\n\\n    Here, `%myalloca` memref is valid within the explicitly delimited scope\\n    and is automatically deallocated at the end of the given region. Conceptually,\\n    `memref.alloca_scope` is a passthrough operation with\\n    `AutomaticAllocationScope` that spans the body of the region within the operation.\\n\\n    `memref.alloca_scope` may also return results that are defined in the nested\\n    region. To return a value, one should use `memref.alloca_scope.return`\\n    operation:\\n\\n    ```mlir\\n    %result = memref.alloca_scope -> f32 {\\n      %value = arith.constant 1.0 : f32\\n      ...\\n      memref.alloca_scope.return %value : f32\\n    }\\n    ```\\n\\n    If `memref.alloca_scope` returns no value, the `memref.alloca_scope.return ` can\\n    be left out, and will be inserted implicitly.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"memref.alloca_scope.return\",\n    \"summary\": \"terminator for alloca_scope operation\",\n    \"description\": \"`memref.alloca_scope.return` operation returns zero or more SSA values\\n    from the region within `memref.alloca_scope`. If no values are returned,\\n    the return operation may be omitted. Otherwise, it has to be present\\n    to indicate which values are going to be returned. For example:\\n\\n    ```mlir\\n    memref.alloca_scope.return %value : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"memref.assume_alignment\",\n    \"summary\": \"assumption that gives alignment information to the input memref\",\n    \"description\": \"The `assume_alignment` operation takes a memref and an integer alignment\\n      value. It returns a new SSA value of the same memref type, but associated\\n      with the assumption that the underlying buffer is aligned to the given\\n      alignment.\\n\\n      If the buffer isn't aligned to the given alignment, its result is poison.\\n      This operation doesn't affect the semantics of a program where the\\n      alignment assumption holds true. It is intended for optimization purposes,\\n      allowing the compiler to generate more efficient code based on the\\n      alignment assumption. The optimization is best-effort.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$memref `,` $alignment attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.atomic_rmw\",\n    \"summary\": \"atomic read-modify-write operation\",\n    \"description\": \"The `memref.atomic_rmw` operation provides a way to perform a read-modify-write\\n    sequence that is free from data races. The kind enumeration specifies the\\n    modification to perform. The value operand represents the new value to be\\n    applied during the modification. The memref operand represents the buffer\\n    that the read and write will be performed against, as accessed by the\\n    specified indices. The arity of the indices is the rank of the memref. The\\n    result represents the latest value that was stored.\\n\\n    Example:\\n\\n    ```mlir\\n    %x = memref.atomic_rmw \\\"addf\\\" %value, %I[%i] : (f32, memref<10xf32>) -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[AnySignlessInteger, AnyFloat]>\" },\n      { \"name\": \"memref\", \"type\": \"MemRefOf<[ AnySignlessInteger, AnyFloat ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnySignlessInteger, AnyFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"AtomicRMWKindAttr{addf|addi|andi|assign|maximumf|maxnumf|maxs|maxu|minimumf|minnumf|mins|minu|mulf|muli|ori|xori}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" },\n      { \"type\": \"TypesMatchWith<'memref', 'value', '::llvm::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$kind $value `,` $memref `[` $indices `]` attr-dict `:` `(` type($value) `,`\\n    type($memref) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"memref.atomic_yield\",\n    \"summary\": \"yield operation for GenericAtomicRMWOp\",\n    \"description\": \"\\\"memref.atomic_yield\\\" yields an SSA value from a\\n    GenericAtomicRMWOp region.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"memref.cast\",\n    \"summary\": \"memref cast operation\",\n    \"description\": \"The `memref.cast` operation converts a memref from one type to an equivalent\\n    type with a compatible shape. The source and destination types are\\n    compatible if:\\n\\n    a. Both are ranked memref types with the same element type, address space,\\n    and rank and:\\n      1. Both have the same layout or both have compatible strided layouts.\\n      2. The individual sizes (resp. offset and strides in the case of strided\\n         memrefs) may convert constant dimensions to dynamic dimensions and\\n         vice-versa.\\n\\n    If the cast converts any dimensions from an unknown to a known size, then it\\n    acts as an assertion that fails at runtime if the dynamic dimensions\\n    disagree with resultant destination size.\\n\\n    Example:\\n\\n    ```mlir\\n    // Assert that the input dynamic shape matches the destination static shape.\\n    %2 = memref.cast %1 : memref<?x?xf32> to memref<4x4xf32>\\n    // Erase static shape information, replacing it with dynamic information.\\n    %3 = memref.cast %1 : memref<4xf32> to memref<?xf32>\\n\\n    // The same holds true for offsets and strides.\\n\\n    // Assert that the input dynamic shape matches the destination static stride.\\n    %4 = memref.cast %1 : memref<12x4xf32, strided<[?, ?], offset: ?>> to\\n                          memref<12x4xf32, strided<[4, 1], offset: 5>>\\n    // Erase static offset and stride information, replacing it with\\n    // dynamic information.\\n    %5 = memref.cast %1 : memref<12x4xf32, strided<[4, 1], offset: 5>> to\\n                          memref<12x4xf32, strided<[?, ?], offset: ?>>\\n    ```\\n\\n    b. Either or both memref types are unranked with the same element type, and\\n    address space.\\n\\n    Example:\\n\\n    ```mlir\\n    // Cast to concrete shape.\\n    %4 = memref.cast %1 : memref<*xf32> to memref<4x?xf32>\\n\\n    // Erase rank information.\\n    %5 = memref.cast %1 : memref<4x?xf32> to memref<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"memref.collapse_shape\",\n    \"summary\": \"operation to produce a memref with a smaller rank.\",\n    \"description\": \"The `memref.collapse_shape` op produces a new view with a smaller rank\\n    whose sizes are a reassociation of the original `view`. The operation is\\n    limited to such reassociations, where subsequent, contiguous dimensions are\\n    collapsed into a single dimension. Such reassociations never require\\n    additional allocs or copies.\\n\\n    Collapsing non-contiguous dimensions is undefined behavior. When a group of\\n    dimensions can be statically proven to be non-contiguous, collapses of such\\n    groups are rejected in the verifier on a best-effort basis. In the general\\n    case, collapses of dynamically-sized dims with dynamic strides cannot be\\n    proven to be contiguous or non-contiguous due to limitations in the memref\\n    type.\\n\\n    A reassociation is defined as a continuous grouping of dimensions and is\\n    represented with an array of DenseI64ArrayAttr attribute.\\n\\n    Note: Only the dimensions within a reassociation group must be contiguous.\\n    The remaining dimensions may be non-contiguous.\\n\\n    The result memref type can be zero-ranked if the source memref type is\\n    statically shaped with all dimensions being unit extent. In such a case, the\\n    reassociation indices must be empty.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Dimension collapse (i, j) -> i' and k -> k'\\n    %1 = memref.collapse_shape %0 [[0, 1], [2]] :\\n        memref<?x?x?xf32, stride_spec> into memref<?x?xf32, stride_spec_2>\\n    ```\\n\\n    For simplicity, this op may not be used to cast dynamicity of dimension\\n    sizes and/or strides. I.e., a result dimension must be dynamic if and only\\n    if at least one dimension in the corresponding reassociation group is\\n    dynamic. Similarly, the stride of a result dimension must be dynamic if and\\n    only if the corresponding start dimension in the source type is dynamic.\\n\\n    Note: This op currently assumes that the inner strides are of the\\n    source/result layout map are the faster-varying ones.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reassociation\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$src $reassociation attr-dict `:` type($src) `into` type($result)\"\n  },\n  {\n    \"name\": \"memref.copy\",\n    \"description\": \"Copies the data from the source to the destination memref.\\n\\n    Usage:\\n\\n    ```mlir\\n    memref.copy %arg0, %arg1 : memref<?xf32> to memref<?xf32>\\n    ```\\n\\n    Source and destination are expected to have the same element type and shape.\\n    Otherwise, the result is undefined. They may have different layouts.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"target\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$source `,` $target attr-dict `:` type($source) `to` type($target)\"\n  },\n  {\n    \"name\": \"memref.dealloc\",\n    \"summary\": \"memory deallocation operation\",\n    \"description\": \"The `dealloc` operation frees the region of memory referenced by a memref\\n    which was originally created by the `alloc` operation.\\n    The `dealloc` operation should not be called on memrefs which alias an\\n    alloc'd memref (e.g. memrefs returned by `view` operations).\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = memref.alloc() : memref<8x64xf32, affine_map<(d0, d1) -> (d0, d1)>, 1>\\n    memref.dealloc %0 : memref<8x64xf32,  affine_map<(d0, d1) -> (d0, d1)>, 1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$memref attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.dim\",\n    \"summary\": \"dimension index operation\",\n    \"description\": \"The `dim` operation takes a memref and a dimension operand of type `index`.\\n    It returns the size of the requested dimension of the given memref.\\n    If the dimension index is out of bounds the behavior is undefined.\\n\\n    The specified memref type is that of the first operand.\\n\\n    Example:\\n\\n    ```mlir\\n    // Always returns 4, can be constant folded:\\n    %c0 = arith.constant 0 : index\\n    %x = memref.dim %A, %c0 : memref<4 x ? x f32>\\n\\n    // Returns the dynamic dimension of %A.\\n    %c1 = arith.constant 1 : index\\n    %y = memref.dim %A, %c1 : memref<4 x ? x f32>\\n\\n    // Equivalent generic form:\\n    %x = \\\"memref.dim\\\"(%A, %c0) : (memref<4 x ? x f32>, index) -> index\\n    %y = \\\"memref.dim\\\"(%A, %c1) : (memref<4 x ? x f32>, index) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyNon0RankedOrUnrankedMemRef\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `,` $index `:` type($source)\"\n  },\n  {\n    \"name\": \"memref.distinct_objects\",\n    \"summary\": \"assumption that acesses to specific memrefs will never alias\",\n    \"description\": \"The `distinct_objects` operation takes a list of memrefs and returns the same\\n      memrefs, with the additional assumption that accesses to them will never\\n      alias with each other. This means that loads and stores to different\\n      memrefs in the list can be safely reordered.\\n\\n      If the memrefs do alias, the load/store behavior is undefined. This\\n      operation doesn't affect the semantics of a valid program. It is\\n      intended for optimization purposes, allowing the compiler to generate more\\n      efficient code based on the non-aliasing assumption. The optimization is\\n      best-effort.\\n\\n      Example:\\n\\n      ```mlir\\n      %1, %2 = memref.distinct_objects %a, %b : memref<?xf32>, memref<?xf32>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyMemRef>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyMemRef>\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict `:` type($operands)\"\n  },\n  {\n    \"name\": \"memref.dma_start\",\n    \"summary\": \"non-blocking DMA operation that starts a transfer\",\n    \"description\": \"Syntax:\\n\\n    ```\\n    operation ::= `memref.dma_start` ssa-use`[`ssa-use-list`]` `,`\\n                   ssa-use`[`ssa-use-list`]` `,` ssa-use `,`\\n                   ssa-use`[`ssa-use-list`]` (`,` ssa-use `,` ssa-use)?\\n                  `:` memref-type `,` memref-type `,` memref-type\\n    ```\\n\\n    DmaStartOp starts a non-blocking DMA operation that transfers data from a\\n    source memref to a destination memref. The source and destination memref\\n    need not be of the same dimensionality, but need to have the same elemental\\n    type. The operands include the source and destination memref's each followed\\n    by its indices, size of the data transfer in terms of the number of elements\\n    (of the elemental type of the memref), a tag memref with its indices, and\\n    optionally at the end, a stride and a number_of_elements_per_stride\\n    arguments. The tag location is used by a DmaWaitOp to check for completion.\\n    The indices of the source memref, destination memref, and the tag memref\\n    have the same restrictions as any load/store. The optional stride arguments\\n    should be of 'index' type, and specify a stride for the slower memory space\\n    (memory space with a lower memory space id), transferring chunks of\\n    number_of_elements_per_stride every stride until %num_elements are\\n    transferred. Either both or no stride arguments should be specified. If the\\n    source and destination locations overlap the behavior of this operation is\\n    not defined.\\n\\n    For example, a DmaStartOp operation that transfers 256 elements of a memref\\n    '%src' in memory space 0 at indices [%i, %j] to memref '%dst' in memory\\n    space 1 at indices [%k, %l], would be specified as follows:\\n\\n    ```mlir\\n    %num_elements = arith.constant 256 : index\\n    %idx = arith.constant 0 : index\\n    %tag = memref.alloc() : memref<1 x i32, affine_map<(d0) -> (d0)>, 2>\\n    memref.dma_start %src[%i, %j], %dst[%k, %l], %num_elements, %tag[%idx] :\\n      memref<40 x 128 x f32, affine_map<(d0, d1) -> (d0, d1)>, 0>,\\n      memref<2 x 1024 x f32, affine_map<(d0, d1) -> (d0, d1)>, 1>,\\n      memref<1 x i32, affine_map<(d0) -> (d0)>, 2>\\n    ```\\n\\n    If %stride and %num_elt_per_stride are specified, the DMA is expected to\\n    transfer %num_elt_per_stride elements every %stride elements apart from\\n    memory space 0 until %num_elements are transferred.\\n\\n    ```mlir\\n    memref.dma_start %src[%i, %j], %dst[%k, %l], %num_elements, %tag[%idx], %stride,\\n                     %num_elt_per_stride :\\n    ```\\n\\n    * TODO: add additional operands to allow source and destination striding, and\\n    multiple stride levels.\\n    * TODO: Consider replacing src/dst memref indices with view memrefs.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"memref.dma_wait\",\n    \"summary\": \"blocking DMA operation that waits for transfer completion\",\n    \"description\": \"DmaWaitOp blocks until the completion of a DMA operation associated with the\\n   tag element '%tag[%index]'. %tag is a memref, and %index has to be an index\\n   with the same restrictions as any load/store index. %num_elements is the\\n   number of elements associated with the DMA operation.\\n\\n   Example:\\n\\n   ```mlir\\n    memref.dma_start %src[%i, %j], %dst[%k, %l], %num_elements, %tag[%index] :\\n      memref<2048 x f32, affine_map<(d0) -> (d0)>, 0>,\\n      memref<256 x f32, affine_map<(d0) -> (d0)>, 1>,\\n      memref<1 x i32, affine_map<(d0) -> (d0)>, 2>\\n    ...\\n    ...\\n    dma_wait %tag[%index], %num_elements : memref<1 x i32, affine_map<(d0) -> (d0)>, 2>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tagMemRef\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tagIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"numElements\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$tagMemRef `[` $tagIndices `]` `,` $numElements attr-dict `:` type($tagMemRef)\"\n  },\n  {\n    \"name\": \"memref.expand_shape\",\n    \"summary\": \"operation to produce a memref with a higher rank.\",\n    \"description\": \"The `memref.expand_shape` op produces a new view with a higher rank whose\\n    sizes are a reassociation of the original `view`. The operation is limited\\n    to such reassociations, where a dimension is expanded into one or multiple\\n    contiguous dimensions. Such reassociations never require additional allocs\\n    or copies.\\n\\n    A reassociation is defined as a grouping of dimensions and is represented\\n    with an array of DenseI64ArrayAttr attributes.\\n\\n    Example:\\n\\n    ```mlir\\n    %r = memref.expand_shape %0 [[0, 1], [2]] output_shape [%sz0, %sz1, 32]\\n        : memref<?x32xf32> into memref<?x?x32xf32>\\n    ```\\n\\n    If an op can be statically proven to be invalid (e.g, an expansion from\\n    `memref<10xf32>` to `memref<2x6xf32>`), it is rejected by the verifier. If\\n    it cannot statically be proven invalid (e.g., the full example above; it is\\n    unclear whether the first source dimension is divisible by 5), the op is\\n    accepted by the verifier. However, if the op is in fact invalid at runtime,\\n    the behavior is undefined.\\n\\n    The source memref can be zero-ranked. In that case, the reassociation\\n    indices must be empty and the result shape may only consist of unit\\n    dimensions.\\n\\n    For simplicity, this op may not be used to cast dynamicity of dimension\\n    sizes and/or strides. I.e., if and only if a source dimension is dynamic,\\n    there must be a dynamic result dimension in the corresponding reassociation\\n    group. Same for strides.\\n\\n    The representation for the output shape supports a partially-static\\n    specification via attributes specified through the `static_output_shape`\\n    argument. A special sentinel value `ShapedType::kDynamic` encodes that the\\n    corresponding entry has a dynamic value. Both the number of SSA inputs in\\n    `output_shape` and the number of `ShapedType::kDynamic` entries in\\n    `static_output_shape` match the number of dynamic dimensions in the result\\n    type.\\n\\n    Note: This op currently assumes that the inner strides are of the\\n    source/result layout map are the faster-varying ones.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyStridedMemRef\" },\n      { \"name\": \"output_shape\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reassociation\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"static_output_shape\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$src $reassociation `output_shape`\\n    custom<DynamicIndexList>($output_shape, $static_output_shape) attr-dict `:`\\n    type($src) `into` type($result)\"\n  },\n  {\n    \"name\": \"memref.extract_aligned_pointer_as_index\",\n    \"summary\": \"Extracts a memref's underlying aligned pointer as an index\",\n    \"description\": \"Extracts the underlying aligned pointer as an index.\\n\\n    This operation is useful for lowering to lower-level dialects while still\\n    avoiding the need to define a pointer type in higher-level dialects such as\\n    the memref dialect.\\n\\n    This operation is intended solely as step during lowering, it has no side\\n    effects. A reverse operation that creates a memref from an index interpreted\\n    as a pointer is explicitly discouraged.\\n\\n    Example:\\n\\n    ```\\n      %0 = memref.extract_aligned_pointer_as_index %arg : memref<4x4xf32> -> index\\n      %1 = arith.index_cast %0 : index to i64\\n      %2 = llvm.inttoptr %1 : i64 to !llvm.ptr\\n      call @foo(%2) : (!llvm.ptr) ->()\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"aligned_pointer\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$source `:` type($source) `->` type(results) attr-dict\"\n  },\n  {\n    \"name\": \"memref.extract_strided_metadata\",\n    \"summary\": \"Extracts a buffer base with offset and strides\",\n    \"description\": \"Extracts a base buffer, offset and strides. This op allows additional layers\\n    of transformations and foldings to be added as lowering progresses from\\n    higher-level dialect to lower-level dialects such as the LLVM dialect.\\n\\n    The op requires a strided memref source operand. If the source operand is not\\n    a strided memref, then verification fails.\\n\\n    This operation is also useful for completeness to the existing memref.dim op.\\n    While accessing strides, offsets and the base pointer independently is not\\n    available, this is useful for composing with its natural complement op:\\n    `memref.reinterpret_cast`.\\n\\n    Intended Use Cases:\\n\\n    The main use case is to expose the logic for manipulate memref metadata at a\\n    higher level than the LLVM dialect.\\n    This makes lowering more progressive and brings the following benefits:\\n      - not all users of MLIR want to lower to LLVM and the information to e.g.\\n        lower to library calls---like libxsmm---or to SPIR-V was not available.\\n      - foldings and canonicalizations can happen at a higher level in MLIR:\\n        before this op existed, lowering to LLVM would create large amounts of\\n        LLVMIR. Even when LLVM does a good job at folding the low-level IR from\\n        a performance perspective, it is unnecessarily opaque and inefficient to\\n        send unkempt IR to LLVM.\\n\\n    Example:\\n\\n    ```mlir\\n      %base, %offset, %sizes:2, %strides:2 =\\n        memref.extract_strided_metadata %memref : memref<10x?xf32>\\n          -> memref<f32>, index, index, index, index, index\\n\\n      // After folding, the type of %m2 can be memref<10x?xf32> and further\\n      // folded to %memref.\\n      %m2 = memref.reinterpret_cast %base to\\n          offset: [%offset],\\n          sizes: [%sizes#0, %sizes#1],\\n          strides: [%strides#0, %strides#1]\\n        : memref<f32> to memref<?x?xf32, strided<[?, ?], offset:?>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"base_buffer\", \"type\": \"AnyStridedMemRefOfRank<0>\" },\n      { \"name\": \"offset\", \"type\": \"Index\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$source `:` type($source) `->` type(results) attr-dict\"\n  },\n  {\n    \"name\": \"memref.generic_atomic_rmw\",\n    \"summary\": \"atomic read-modify-write operation with a region\",\n    \"description\": \"The `memref.generic_atomic_rmw` operation provides a way to perform a\\n    read-modify-write sequence that is free from data races. The memref operand\\n    represents the buffer that the read and write will be performed against, as\\n    accessed by the specified indices. The arity of the indices is the rank of\\n    the memref. The result represents the latest value that was stored. The\\n    region contains the code for the modification itself. The entry block has\\n    a single argument that represents the value stored in `memref[indices]`\\n    before the write is performed. No side-effecting ops are allowed in the\\n    body of `GenericAtomicRMWOp`.\\n\\n    Example:\\n\\n    ```mlir\\n    %x = memref.generic_atomic_rmw %I[%i] : memref<10xf32> {\\n      ^bb0(%current_value : f32):\\n        %c1 = arith.constant 1.0 : f32\\n        %inc = arith.addf %c1, %current_value : f32\\n        memref.atomic_yield %inc : f32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"MemRefOf<[ AnySignlessInteger, AnyFloat ]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnySignlessInteger, AnyFloat]>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"atomic_body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'memref', 'result', '::llvm::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"memref.get_global\",\n    \"summary\": \"get the memref pointing to a global variable\",\n    \"description\": \"The `memref.get_global` operation retrieves the memref pointing to a\\n     named global variable. If the global variable is marked constant, writing\\n     to the result memref (such as through a `memref.store` operation) is\\n     undefined.\\n\\n     Example:\\n\\n     ```mlir\\n     %x = memref.get_global @foo : memref<2xf32>\\n     ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStaticShapeMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$name `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"memref.global\",\n    \"summary\": \"declare or define a global memref variable\",\n    \"description\": \"The `memref.global` operation declares or defines a named global memref\\n    variable. The backing memory for the variable is allocated statically and is\\n    described by the type of the variable (which should be a statically shaped\\n    memref type). The operation is a declaration if no `initial_value` is\\n    specified, else it is a definition. The `initial_value` can either be a unit\\n    attribute to represent a definition of an uninitialized global variable, or\\n    an elements attribute to represent the definition of a global variable with\\n    an initial value. The global variable can also be marked constant using the\\n    `constant` unit attribute. Writing to such constant global variables is\\n    undefined.\\n\\n    The global variable can be accessed by using the `memref.get_global` to\\n    retrieve the memref for the global variable. Note that the memref\\n    for such global variable itself is immutable (i.e., memref.get_global for a\\n    given global variable will always return the same memref descriptor).\\n\\n    Example:\\n\\n    ```mlir\\n    // Private variable with an initial value.\\n    memref.global \\\"private\\\" @x : memref<2xf32> = dense<[0.0, 2.0]>\\n\\n    // Private variable with an initial value and an alignment (power of 2).\\n    memref.global \\\"private\\\" @x : memref<2xf32> = dense<[0.0, 2.0]> {alignment = 64}\\n\\n    // Declaration of an external variable.\\n    memref.global \\\"private\\\" @y : memref<4xi32>\\n\\n    // Uninitialized externally visible variable.\\n    memref.global @z : memref<3xf16> = uninitialized\\n\\n    // Externally visible constant variable.\\n    memref.global constant @c : memref<2xi32> = dense<[1, 4]>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"type\", \"type\": \"MemRefTypeAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"($sym_visibility^)?\\n       (`constant` $constant^)?\\n       $sym_name `:`\\n       custom<GlobalMemrefOpTypeAndInitialValue>($type, $initial_value)\\n       attr-dict\"\n  },\n  {\n    \"name\": \"memref.load\",\n    \"summary\": \"load operation\",\n    \"description\": \"The `load` op reads an element from a memref at the specified indices.\\n\\n    The number of indices must match the rank of the memref. The indices must\\n    be in-bounds: `0 <= idx < dim_size`.\\n\\n    Lowerings of `memref.load` may emit attributes, e.g. `inbouds` + `nuw`\\n    when converting to LLVM's `llvm.getelementptr`, that would cause undefined\\n    behavior if indices are out of bounds or if computing the offset in the\\n    memref would cause signed overflow of the `index` type.\\n\\n    The single result of `memref.load` is a value with the same type as the\\n    element type of the memref.\\n\\n    A set `nontemporal` attribute indicates that this load is not expected to\\n    be reused in the cache. For details, refer to the\\n    [LLVM load instruction](https://llvm.org/docs/LangRef.html#load-instruction).\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    load operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violations may lead to\\n    architecture-specific faults or performance penalties.\\n    A value of 0 indicates no specific alignment requirement.\\n    Example:\\n\\n    ```mlir\\n    %0 = memref.load %A[%a, %b] : memref<8x?xi32, #layout, memspace0>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nontemporal\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'memref', 'result', '::llvm::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memref `[` $indices `]` attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.memory_space_cast\",\n    \"summary\": \"memref memory space cast operation\",\n    \"description\": \"This operation casts memref values between memory spaces.\\n    The input and result will be memrefs of the same types and shape that alias\\n    the same underlying memory, though, for some casts on some targets,\\n    the underlying values of the pointer stored in the memref may be affected\\n    by the cast.\\n\\n    The input and result must have the same shape, element type, rank, and layout.\\n\\n    If the source and target address spaces are the same, this operation is a noop.\\n\\n    Finally, if the target memory-space is the generic/default memory-space,\\n    then it is assumed this cast can be bubbled down safely. See the docs of\\n    `MemorySpaceCastOpInterface` interface for more details.\\n\\n    Example:\\n\\n    ```mlir\\n    // Cast a GPU private memory attribution into a generic pointer\\n    %2 = memref.memory_space_cast %1 : memref<?xf32, 5> to memref<?xf32>\\n    // Cast a generic pointer to workgroup-local memory\\n    %4 = memref.memory_space_cast %3 : memref<5x4xi32> to memref<5x34xi32, 3>\\n    // Cast between two non-default memory spaces\\n    %6 = memref.memory_space_cast %5\\n      : memref<*xmemref<?xf32>, 5> to memref<*xmemref<?xf32>, 3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"memref.prefetch\",\n    \"summary\": \"prefetch operation\",\n    \"description\": \"The \\\"prefetch\\\" op prefetches data from a memref location described with\\n    subscript indices similar to memref.load, and with three attributes: a\\n    read/write specifier, a locality hint, and a cache type specifier as shown\\n    below:\\n\\n    ```mlir\\n    memref.prefetch %0[%i, %j], read, locality<3>, data : memref<400x400xi32>\\n    ```\\n\\n    The read/write specifier is either 'read' or 'write', the locality hint\\n    ranges from locality<0> (no locality) to locality<3> (extremely local keep\\n    in cache). The cache type specifier is either 'data' or 'instr'\\n    and specifies whether the prefetch is performed on data cache or on\\n    instruction cache.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isWrite\", \"type\": \"BoolAttr\" },\n      { \"name\": \"localityHint\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>\" },\n      { \"name\": \"isDataCache\", \"type\": \"BoolAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"memref.rank\",\n    \"summary\": \"rank operation\",\n    \"description\": \"The `memref.rank` operation takes a memref operand and returns its rank.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = memref.rank %arg0 : memref<*xf32>\\n    %1 = memref.rank %arg1 : memref<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$memref attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.realloc\",\n    \"summary\": \"memory reallocation operation\",\n    \"description\": \"The `realloc` operation changes the size of a memory region. The memory\\n    region is specified by a 1D source memref and the size of the new memory\\n    region is specified by a 1D result memref type and an optional dynamic Value\\n    of `Index` type. The source and the result memref must be in the same memory\\n    space and have the same element type.\\n\\n    The operation may move the memory region to a new location. In this case,\\n    the content of the memory block is preserved up to the lesser of the new\\n    and old sizes. If the new size if larger, the value of the extended memory\\n    is undefined. This is consistent with the ISO C realloc.\\n\\n    The operation returns an SSA value for the memref.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = memref.realloc %src : memref<64xf32> to memref<124xf32>\\n    ```\\n\\n    The source memref may have a dynamic shape, in which case, the compiler will\\n    generate code to extract its size from the runtime data structure for the\\n    memref.\\n\\n    ```mlir\\n    %1 = memref.realloc %src : memref<?xf32> to memref<124xf32>\\n    ```\\n\\n    If the result memref has a dynamic shape, a result dimension operand is\\n    needed to spefify its dynamic dimension. In the example below, the ssa value\\n    '%d' specifies the unknown dimension of the result memref.\\n\\n    ```mlir\\n    %2 = memref.realloc %src(%d) : memref<?xf32> to memref<?xf32>\\n    ```\\n\\n    An optional `alignment` attribute may be specified to ensure that the\\n    region of memory that will be indexed is aligned at the specified byte\\n    boundary.  This is consistent with the fact that memref.alloc supports such\\n    an optional alignment attribute. Note that in ISO C standard, neither alloc\\n    nor realloc supports alignment, though there is aligned_alloc but not\\n    aligned_realloc.\\n\\n    ```mlir\\n    %3 = memref.realloc %src {alignment = 8} : memref<64xf32> to memref<124xf32>\\n    ```\\n\\n    Referencing the memref through the old SSA value after realloc is undefined\\n    behavior.\\n\\n    ```mlir\\n    %new = memref.realloc %old : memref<64xf32> to memref<124xf32>\\n    %4 = memref.load %new[%index] : memref<124xf32> // ok\\n    %5 = memref.load %old[%index] : memref<64xf32>  // undefined behavior\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"MemRefRankOf<[ AnyType ], [ 1 ]>\" },\n      { \"name\": \"dynamicResultSize\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MemRefRankOf<[ AnyType ], [ 1 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$source (`(` $dynamicResultSize^ `)`)? attr-dict\\n    `:` type($source) `to` type(results)\"\n  },\n  {\n    \"name\": \"memref.reinterpret_cast\",\n    \"summary\": \"memref reinterpret cast operation\",\n    \"description\": \"Modify offset, sizes and strides of an unranked/ranked memref.\\n\\n    Example 1:\\n\\n    Consecutive `reinterpret_cast` operations on memref's with static\\n    dimensions.\\n\\n    We distinguish between *underlying memory* — the sequence of elements as\\n    they appear in the contiguous memory of the memref — and the\\n    *strided memref*, which refers to the underlying memory interpreted\\n    according to specified offsets, sizes, and strides.\\n\\n    ```mlir\\n    %result1 = memref.reinterpret_cast %arg0 to\\n      offset: [9],\\n      sizes: [4, 4],\\n      strides: [16, 2]\\n    : memref<8x8xf32, strided<[8, 1], offset: 0>> to\\n      memref<4x4xf32, strided<[16, 2], offset: 9>>\\n\\n    %result2 = memref.reinterpret_cast %result1 to\\n      offset: [0],\\n      sizes: [2, 2],\\n      strides: [4, 2]\\n    : memref<4x4xf32, strided<[16, 2], offset: 9>> to\\n      memref<2x2xf32, strided<[4, 2], offset: 0>>\\n    ```\\n\\n    The underlying memory of `%arg0` consists of a linear sequence of integers\\n    from 1 to 64. Its memref has the following 8x8 elements:\\n\\n    ```mlir\\n    [[1,  2,  3,  4,  5,  6,  7,  8],\\n    [9,  10, 11, 12, 13, 14, 15, 16],\\n    [17, 18, 19, 20, 21, 22, 23, 24],\\n    [25, 26, 27, 28, 29, 30, 31, 32],\\n    [33, 34, 35, 36, 37, 38, 39, 40],\\n    [41, 42, 43, 44, 45, 46, 47, 48],\\n    [49, 50, 51, 52, 53, 54, 55, 56],\\n    [57, 58, 59, 60, 61, 62, 63, 64]]\\n    ```\\n\\n    Following the first `reinterpret_cast`, the strided memref elements\\n    of `%result1` are:\\n\\n    ```mlir\\n    [[10, 12, 14, 16],\\n    [26, 28, 30, 32],\\n    [42, 44, 46, 48],\\n    [58, 60, 62, 64]]\\n    ```\\n\\n    Note: The offset and strides are relative to the underlying memory of\\n    `%arg0`.\\n\\n    The second `reinterpret_cast` results in the following strided memref\\n    for `%result2`:\\n\\n    ```mlir\\n    [[1, 3],\\n    [5, 7]]\\n    ```\\n\\n    Notice that it does not matter if you use %result1 or %arg0 as a source\\n    for the second `reinterpret_cast` operation. Only the underlying memory\\n    pointers will be reused.\\n\\n    The offset and stride are relative to the base underlying memory of the\\n    memref, starting at 1, not at 10 as seen in the output of `%result1`.\\n    This behavior contrasts with the `subview` operator, where values are\\n    relative to the strided memref (refer to `subview` examples).\\n    Consequently, the second `reinterpret_cast` behaves as if `%arg0` were\\n    passed directly as its argument.\\n\\n    Example 2:\\n    ```mlir\\n    memref.reinterpret_cast %ranked to\\n      offset: [0],\\n      sizes: [%size0, 10],\\n      strides: [1, %stride1]\\n    : memref<?x?xf32> to memref<?x10xf32, strided<[1, ?], offset: 0>>\\n\\n    memref.reinterpret_cast %unranked to\\n      offset: [%offset],\\n      sizes: [%size0, %size1],\\n      strides: [%stride0, %stride1]\\n    : memref<*xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>\\n    ```\\n\\n    This operation creates a new memref descriptor using the base of the\\n    source and applying the input arguments to the other metadata.\\n    In other words:\\n    ```mlir\\n    %dst = memref.reinterpret_cast %src to\\n      offset: [%offset],\\n      sizes: [%sizes],\\n      strides: [%strides] :\\n      memref<*xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>\\n    ```\\n    means that `%dst`'s descriptor will be:\\n    ```mlir\\n    %dst.base = %src.base\\n    %dst.aligned = %src.aligned\\n    %dst.offset = %offset\\n    %dst.sizes = %sizes\\n    %dst.strides = %strides\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `to` `offset` `` `:`\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    `` `,` `sizes` `` `:`\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    `` `,` `strides` `` `:`\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"memref.reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"memref reshape operation\",\n    \"description\": \"The `reshape` operation converts a memref from one type to an\\n    equivalent type with a provided shape. The data is never copied or\\n    modified. The source and destination types are compatible if both have the\\n    same element type, same number of elements, address space and identity\\n    layout map. The following combinations are possible:\\n\\n    a. Source type is ranked or unranked. Shape argument has static size.\\n    Result type is ranked.\\n\\n    ```mlir\\n    // Reshape statically-shaped memref.\\n    %dst = memref.reshape %src(%shape)\\n             : (memref<4x1xf32>, memref<1xi32>) -> memref<4xf32>\\n    %dst0 = memref.reshape %src(%shape0)\\n             : (memref<4x1xf32>, memref<2xi32>) -> memref<2x2xf32>\\n    // Flatten unranked memref.\\n    %dst = memref.reshape %src(%shape)\\n             : (memref<*xf32>, memref<1xi32>) -> memref<?xf32>\\n    ```\\n\\n    b. Source type is ranked or unranked. Shape argument has dynamic size.\\n    Result type is unranked.\\n\\n    ```mlir\\n    // Reshape dynamically-shaped 1D memref.\\n    %dst = memref.reshape %src(%shape)\\n             : (memref<?xf32>, memref<?xi32>) -> memref<*xf32>\\n    // Reshape unranked memref.\\n    %dst = memref.reshape %src(%shape)\\n             : (memref<*xf32>, memref<?xi32>) -> memref<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"shape\", \"type\": \"MemRefRankOf<[ AnySignlessInteger, Index ], [ 1 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$source `(` $shape `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"memref.store\",\n    \"summary\": \"store operation\",\n    \"description\": \"The `store` op stores an element into a memref at the specified indices.\\n\\n    The number of indices must match the rank of the memref. The indices must\\n    be in-bounds: `0 <= idx < dim_size`.\\n\\n    Lowerings of `memref.store` may emit attributes, e.g. `inbouds` + `nuw`\\n    when converting to LLVM's `llvm.getelementptr`, that would cause undefined\\n    behavior if indices are out of bounds or if computing the offset in the\\n    memref would cause signed overflow of the `index` type.\\n\\n    A set `nontemporal` attribute indicates that this store is not expected to\\n    be reused in the cache. For details, refer to the\\n    [LLVM store instruction](https://llvm.org/docs/LangRef.html#store-instruction).\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    store operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violations may lead to\\n    architecture-specific faults or performance penalties.\\n    A value of 0 indicates no specific alignment requirement.\\n    Example:\\n\\n    ```mlir\\n    memref.store %val, %A[%a, %b] : memref<8x?xi32, #layout, memspace0>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nontemporal\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'memref', 'value', '::llvm::cast<MemRefType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $memref `[` $indices `]` attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"memref.subview\",\n    \"summary\": \"memref subview operation\",\n    \"description\": \"The `subview` operation converts a memref type to a memref type which\\n    represents a reduced-size view of the original memref as specified by the\\n    operation's offsets, sizes and strides arguments.\\n\\n    The `subview` operation supports the following arguments:\\n\\n    * source: the \\\"base\\\" memref on which to create a \\\"view\\\" memref.\\n    * offsets: memref-rank number of offsets into the \\\"base\\\" memref at which to\\n               create the \\\"view\\\" memref.\\n    * sizes: memref-rank number of sizes which specify the sizes of the result\\n             \\\"view\\\" memref type.\\n    * strides: memref-rank number of strides that compose multiplicatively with\\n               the base memref strides in each dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value `ShapedType::kDynamic` encodes that the corresponding entry\\n    has a dynamic value.\\n\\n    A `subview` operation may additionally reduce the rank of the resulting\\n    view by removing dimensions that are statically known to be of size 1.\\n\\n    In the absence of rank reductions, the resulting memref type is computed\\n    as follows:\\n    ```\\n    result_sizes[i] = size_operands[i]\\n    result_strides[i] = src_strides[i] * stride_operands[i]\\n    result_offset = src_offset + dot_product(offset_operands, src_strides)\\n    ```\\n\\n    The offset, size and stride operands must be in-bounds with respect to the\\n    source memref. When possible, the static operation verifier will detect\\n    out-of-bounds subviews. Subviews that cannot be confirmed to be in-bounds\\n    or out-of-bounds based on compile-time information are valid. However,\\n    performing an out-of-bounds subview at runtime is undefined behavior.\\n\\n    Example 1:\\n\\n    Consecutive `subview` operations on memref's with static dimensions.\\n\\n    We distinguish between *underlying memory* — the sequence of elements as\\n    they appear in the contiguous memory of the memref — and the\\n    *strided memref*, which refers to the underlying memory interpreted\\n    according to specified offsets, sizes, and strides.\\n\\n    ```mlir\\n    %result1 = memref.subview %arg0[1, 1][4, 4][2, 2]\\n    : memref<8x8xf32, strided<[8, 1], offset: 0>> to\\n      memref<4x4xf32, strided<[16, 2], offset: 9>>\\n\\n    %result2 = memref.subview %result1[1, 1][2, 2][2, 2]\\n    : memref<4x4xf32, strided<[16, 2], offset: 9>> to\\n      memref<2x2xf32, strided<[32, 4], offset: 27>>\\n    ```\\n\\n    The underlying memory of `%arg0` consists of a linear sequence of integers\\n    from 1 to 64. Its memref has the following 8x8 elements:\\n\\n    ```mlir\\n    [[1,  2,  3,  4,  5,  6,  7,  8],\\n    [9,  10, 11, 12, 13, 14, 15, 16],\\n    [17, 18, 19, 20, 21, 22, 23, 24],\\n    [25, 26, 27, 28, 29, 30, 31, 32],\\n    [33, 34, 35, 36, 37, 38, 39, 40],\\n    [41, 42, 43, 44, 45, 46, 47, 48],\\n    [49, 50, 51, 52, 53, 54, 55, 56],\\n    [57, 58, 59, 60, 61, 62, 63, 64]]\\n    ```\\n\\n    Following the first `subview`, the strided memref elements of `%result1`\\n    are:\\n\\n    ```mlir\\n    [[10, 12, 14, 16],\\n    [26, 28, 30, 32],\\n    [42, 44, 46, 48],\\n    [58, 60, 62, 64]]\\n    ```\\n\\n    Note: The offset and strides are relative to the strided memref of `%arg0`\\n    (compare to the corresponding `reinterpret_cast` example).\\n\\n    The second `subview` results in the following strided memref for\\n    `%result2`:\\n\\n    ```mlir\\n    [[28, 32],\\n    [60, 64]]\\n    ```\\n\\n    Unlike the `reinterpret_cast`, the values are relative to the strided\\n    memref of the input (`%result1` in this case) and not its\\n    underlying memory.\\n\\n    Example 2:\\n\\n    ```mlir\\n    // Subview of static memref with strided layout at static offsets, sizes\\n    // and strides.\\n    %1 = memref.subview %0[4, 2][8, 2][3, 2]\\n        : memref<64x4xf32, strided<[7, 9], offset: 91>> to\\n          memref<8x2xf32, strided<[21, 18], offset: 137>>\\n    ```\\n\\n    Example 3:\\n\\n    ```mlir\\n    // Subview of static memref with identity layout at dynamic offsets, sizes\\n    // and strides.\\n    %1 = memref.subview %0[%off0, %off1][%sz0, %sz1][%str0, %str1]\\n        : memref<64x4xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>\\n    ```\\n\\n    Example 4:\\n\\n    ```mlir\\n    // Subview of dynamic memref with strided layout at dynamic offsets and\\n    // strides, but static sizes.\\n    %1 = memref.subview %0[%off0, %off1][4, 4][%str0, %str1]\\n        : memref<?x?xf32, strided<[?, ?], offset: ?>> to\\n          memref<4x4xf32, strided<[?, ?], offset: ?>>\\n    ```\\n\\n    Example 5:\\n\\n    ```mlir\\n    // Rank-reducing subviews.\\n    %1 = memref.subview %0[0, 0, 0][1, 16, 4][1, 1, 1]\\n        : memref<8x16x4xf32> to memref<16x4xf32>\\n    %3 = memref.subview %2[3, 4, 2][1, 6, 3][1, 1, 1]\\n        : memref<8x16x4xf32> to memref<6x3xf32, strided<[4, 1], offset: 210>>\\n    ```\\n\\n    Example 6:\\n\\n    ```mlir\\n    // Identity subview. The subview is the full source memref.\\n    %1 = memref.subview %0[0, 0, 0] [8, 16, 4] [1, 1, 1]\\n        : memref<8x16x4xf32> to memref<8x16x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"memref.tensor_load\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"memref.transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"`transpose` produces a new strided memref (metadata-only)\",\n    \"description\": \"The `transpose` op produces a strided memref whose sizes and strides\\n    are a permutation of the original `in` memref. This is purely a metadata\\n    transformation.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = memref.transpose %0 (i, j) -> (j, i) : memref<?x?xf32> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d1 * s0 + d0)>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStridedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"memref.view\",\n    \"summary\": \"memref view operation\",\n    \"description\": \"The \\\"view\\\" operation extracts an N-D contiguous memref with empty layout map\\n    with arbitrary element type from a 1-D contiguous memref with empty layout\\n    map of i8 element  type. The ViewOp supports the following arguments:\\n\\n    * A single dynamic byte-shift operand must be specified which represents a\\n      a shift of the base 1-D memref pointer from which to create the resulting\\n      contiguous memref view with identity layout.\\n    * A dynamic size operand that must be specified for each dynamic dimension\\n      in the resulting view memref type.\\n\\n    The \\\"view\\\" operation gives a structured indexing form to a flat 1-D buffer.\\n    Unlike \\\"subview\\\" it can perform a type change. The type change behavior\\n    requires the op to have special semantics because, e.g. a byte shift of 3\\n    cannot be represented as an offset on f64.\\n    For now, a \\\"view\\\" op:\\n\\n    1. Only takes a contiguous source memref with 0 offset and empty layout.\\n    2. Must specify a byte_shift operand (in the future, a special integer\\n       attribute may be added to support the folded case).\\n    3. Returns a contiguous memref with 0 offset and empty layout.\\n\\n    Example:\\n\\n    ```mlir\\n    // Allocate a flat 1D/i8 memref.\\n    %0 = memref.alloc() : memref<2048xi8>\\n\\n    // ViewOp with dynamic offset and static sizes.\\n    %1 = memref.view %0[%offset_1024][] : memref<2048xi8> to memref<64x4xf32>\\n\\n    // ViewOp with dynamic offset and two dynamic size.\\n    %2 = memref.view %0[%offset_1024][%size0, %size1] :\\n      memref<2048xi8> to memref<?x4x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"MemRefRankOf<[I8], [1]>\" },\n      { \"name\": \"byte_shift\", \"type\": \"Index\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $byte_shift `]` `` `[` $sizes `]` attr-dict\\n    `:` type($source) `to` type(results)\"\n  },\n  {\n    \"name\": \"mhlo.abs\",\n    \"summary\": \"Abs operation\",\n    \"description\": \"Performs element-wise abs operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#abs\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.abs %operand : tensor<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[ MHLO_SInt, MHLO_Float, MHLO_Complex, MHLO_QuantizedInt ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[ MHLO_SInt, MHLO_Float, MHLO_QuantizedInt ]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.acos\",\n    \"summary\": \"Acos operation\",\n    \"description\": \"Performs element-wise acos operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.acos %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.acosh\",\n    \"summary\": \"Acosh operation\",\n    \"description\": \"Performs element-wise acosh operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.acosh %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.add\",\n    \"summary\": \"Add operation\",\n    \"description\": \"Performs element-wise addition of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#add\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.add %lhs, %rhs : tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.add_dependency\",\n    \"summary\": \"AddDependency operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation two operands: a data operand and a token. The\\n    output of the operation is the data operand. When used with AfterAll this\\n    operation enables ordering non-side-effecting operations (those that do not\\n    produce token values).\\n\\n    Example:\\n    ```mlir\\n    %1 = mhlo.add_dependency %arg0, %0 : (tensor<3x4xf32>, !mhlo.token) -> tensor<3x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_TensorOrAnyToken\" },\n      { \"name\": \"token\", \"type\": \"MHLO_AnyToken\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MHLO_TensorOrAnyToken\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.after_all\",\n    \"summary\": \"AfterAll operation\",\n    \"description\": \"Ensures that the operations producing the `inputs` are executed before any\\n    operations that depend on `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#after_all\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.after_all %input0, %input1 : !mhlo.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Token>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Token\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\\n      `:` custom<VariadicSameOperandsAndResultType>(ref($inputs), type($inputs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.all_gather\",\n    \"summary\": \"AllGather operation\",\n    \"description\": \"Within each process group in the process grid, concatenates the values of the\\n    operand tensor from each process along `all_gather_dim` and produces a\\n    result tensor. The `computation` is applied separately for each operand in\\n    `operands`, producing one result per operand.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_gather\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.all_gather\\\"(%operand) {\\n      all_gather_dim = 1 : i64,\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>\\n      // channel_id = 0\\n      channel_handle = #mhlo.channel_handle<handle = 0, type = 0>,\\n      // use_global_device_ids = false\\n    } : (tensor<2x2xf32>) -> tensor<2x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"all_gather_dim\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<MHLO_ChannelHandle>\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.all_reduce\",\n    \"summary\": \"AllReduce operation\",\n    \"description\": \"Within each process group in the process grid, applies a reduction function\\n    `computation` to the values of an operand tensor from each process and\\n    produces a result tensor. The `computation` is applied separately for each\\n    operand in `operands`, producing one result per operand.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_reduce\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.all_reduce\\\"(%operand) ({\\n      ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):\\n        %0 = mhlo.add %arg1, %arg2 : tensor<f32>\\n        mhlo.return %0 : tensor<f32>\\n    }) {\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>\\n      // channel_id = 0\\n      channel_handle = #mhlo.channel_handle<handle = 0, type = 0>\\n      // use_global_device_ids = false\\n    } : (tensor<4xf32>) -> tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<MHLO_ChannelHandle>\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.all_to_all\",\n    \"summary\": \"AllToAll operation\",\n    \"description\": \"Within each process group in the process grid, splits the values of the\\n    `operand` tensor along `split_dimension` into parts, scatters the split parts\\n    between the processes, concatenates the scattered parts along `concat_dimension`\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_to_all\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.all_to_all\\\"(%operand) {\\n      split_dimension = 1 : i64,\\n      concat_dimension = 0 : i64,\\n      split_count = 2 : i64,\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>\\n    } : (tensor<2x4xf32>) -> tensor<4x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dimension\", \"type\": \"OptionalAttr<ConfinedAttr<I64Attr, [ IntNonNegative ]>>\" },\n      { \"name\": \"concat_dimension\", \"type\": \"OptionalAttr<ConfinedAttr<I64Attr, [ IntNonNegative ]>>\" },\n      { \"name\": \"split_count\", \"type\": \"OptionalAttr<ConfinedAttr<I64Attr, [ IntPositive ]>>\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<MHLO_ChannelHandle>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.and\",\n    \"summary\": \"And operation\",\n    \"description\": \"Performs element-wise AND of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#and\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.and %lhs, %rhs : tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_PredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.asin\",\n    \"summary\": \"Asin operation\",\n    \"description\": \"Performs element-wise asin operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.asin %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.asinh\",\n    \"summary\": \"Asinh operation\",\n    \"description\": \"Performs element-wise asinh operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.asinh %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.async_done\",\n    \"summary\": \"AsyncDone operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation blocks until the end of an asynchronous computation.\\n    It returns the final result of the asynchronous computation.\\n\\n    See the documentation for AsyncStart for more information.\",\n    \"operands\": [\n      { \"name\": \"bundle\", \"type\": \"MHLO_AsyncBundle\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_TensorOrAnyTokenOrTuple>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.async_start\",\n    \"summary\": \"AsyncStart operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation kicks off an asynchronous computation.\\n\\n    This is used when there are functions that contain both asynchronous waits\\n    (such as DMAs) and on-thread computation. For example, a function might\\n    consist of a computation, a DMA, another computation, a second DMA, and a\\n    final computation. This would be represented as an async_start followed by\\n    and async_update and an async_done. The async_start would do the first\\n    computation on-thread and then start the DMA. The async_update would wait\\n    for the DMA to complete if it wasn't yet done, then execute the second\\n    computation in the function, and start the second DMA. Finally, the\\n    async_done would wait on this last DMA, and then run the last computation\\n    that needs to be run on-thread and return the result of that final\\n    computation.\\n\\n    `operands` are passed to the computation directly\\n    `called_computation` is the function that will be run asynchronously\\n    `execution_thread` is the name of the thread in which it will be run. The main\\n      thread is called \\\"main\\\". All threads have names.\\n\\n    This returns all the state needed between async ops. After buffer\\n    assignment, the return values represents the space needed to hold the input,\\n    results, and any scratchpads needed or edited by the async op.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_TensorOrAnyTokenOrTuple>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_AsyncBundle\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"called_computation\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"execution_thread\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.async_update\",\n    \"summary\": \"AsyncUpdate operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation blocks on an asynchronous computation until a\\n    sync barrier. This returns `bundle` after operating on it.\\n\\n    See the documentation for AsyncStart for more information.\",\n    \"operands\": [\n      { \"name\": \"bundle\", \"type\": \"MHLO_AsyncBundle\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_AsyncBundle\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.atan2\",\n    \"summary\": \"Atan2 operation\",\n    \"description\": \"Performs element-wise atan2 operation on `lhs` and `rhs` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#atan2\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.atan2 %lhs, %rhs : tensor<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.atanh\",\n    \"summary\": \"Atanh operation\",\n    \"description\": \"Performs element-wise atanh operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.atanh %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.batch_norm_grad\",\n    \"summary\": \"BatchNormGrad operation\",\n    \"description\": \"Computes gradients of several inputs of BatchNormTrainingOp backpropagating\\n    from `grad_output`, and produces `grad_operand`, `grad_scale` and\\n    `grad_offset` tensors.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#batch_norm_grad\\n\\n    Example:\\n    ```mlir\\n    %grad_operand, %grad_scale, %grad_offset =\\n    \\\"mhlo.batch_norm_grad\\\"(%operand, %scale, %mean, %variance, %grad_output) {\\n      epsilon = 0.0 : f32,\\n      feature_index = 2 : i64\\n    } : (tensor<2x2x2xf32>, tensor<2xf32>, tensor<2xf32>, tensor<2xf32>,\\n        tensor<2x2x2xf32>) -> (tensor<2x2x2xf32>, tensor<2xf32>, tensor<2xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" },\n      { \"name\": \"scale\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"mean\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"variance\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"grad_output\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_operand\", \"type\": \"MHLO_FpTensor\" },\n      { \"name\": \"grad_scale\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"grad_offset\", \"type\": \"1DTensorOf<[MHLO_Float]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"feature_index\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.batch_norm_inference\",\n    \"summary\": \"BatchNormInference operation\",\n    \"description\": \"Normalizes the `operand` tensor across all dimensions except for the\\n    `feature_index` dimension and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#batch_norm_inference\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.batch_norm_inference\\\"(%operand, %scale, %offset, %mean, %variance) {\\n      epsilon = 0.0 : f32,\\n      feature_index = 2 : i64\\n    } : (tensor<2x2x2xf32>, tensor<2xf32>, tensor<2xf32>, tensor<2xf32>, tensor<2xf32>) -> tensor<2x2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" },\n      { \"name\": \"scale\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"offset\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"mean\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"variance\", \"type\": \"1DTensorOf<[MHLO_Float]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"feature_index\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.batch_norm_training\",\n    \"summary\": \"BatchNormTraining operation\",\n    \"description\": \"Computes mean and variance across batch and spatial dimensions and\\n    normalizes the `operand` tensor, for each feature in the `feature_index`\\n    dimension and produces `output`, `batch_mean` and `batch_var` tensors.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#batch_norm_training\\n\\n    Example:\\n    ```mlir\\n    %output, %batch_mean, %batch_var = \\\"mhlo.batch_norm_training\\\"(%operand, %scale, %offset) {\\n      epsilon = 0.0 : f32,\\n      feature_index = 2 : i64\\n    } : (tensor<2x2x2xf32>, tensor<2xf32>, tensor<2xf32>) -> (tensor<2x2x2xf32>, tensor<2xf32>, tensor<2xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" },\n      { \"name\": \"scale\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"offset\", \"type\": \"1DTensorOf<[MHLO_Float]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MHLO_FpTensor\" },\n      { \"name\": \"batch_mean\", \"type\": \"1DTensorOf<[MHLO_Float]>\" },\n      { \"name\": \"batch_var\", \"type\": \"1DTensorOf<[MHLO_Float]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"feature_index\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.bitcast\",\n    \"summary\": \"Bitcast operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation changes the shape of the input in the way that\\n    the physical arrangement of elements are unchanged.\\n\\n    This operation needs layout information to make sense of \\\"physical\\n    arrangement of elements\\\", and layout support in MHLO is currently a work\\n    in progress.\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.bitcast %arg0 : (tensor<3x4xf32>) -> tensor<3x4x1xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.bitcast_convert\",\n    \"summary\": \"BitcastConvert operation\",\n    \"description\": \"Performs a bitcast operation on `operand` tensor and produces a `result`\\n    tensor where the bits of the entire `operand` tensor are reinterpreted using\\n    the type of the `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#bitcast_convert\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.bitcast_convert %operand : (tensor<2xf32>) -> tensor<2x4xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.broadcast\",\n    \"summary\": \"Broadcast operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as XLA's Broadcast:\\n    https://www.tensorflow.org/xla/operation_semantics#broadcast\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.broadcast %operand, sizes = [1, 2] : (tensor<3xi32>) -> tensor<1x2x3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_sizes\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.broadcast_in_dim\",\n    \"summary\": \"BroadcastInDim operation\",\n    \"description\": \"Expands the dimensions and/or rank of an input tensor by duplicating the\\n    data in the `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#broadcast_in_dim\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.broadcast_in_dim %operand, dims = [2, 1] : (tensor<1x3xi32>) -> tensor<2x3x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_StaticShapeOrBoundedDimTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"MHLO_BroadcastDimAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.case\",\n    \"summary\": \"Case operation\",\n    \"description\": \"Produces the output from executing exactly one `function` from `branches`\\n    depending on the value of `index`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#case\\n\\n    Example:\\n    ```mlir\\n    %result0, %result1 = \\\"mhlo.case\\\"(%index) ({\\n      mhlo.return %result_branch0, %result_branch0 : tensor<2xi64>, tensor<2xi64>\\n    }, {\\n      mhlo.return %result_branch1, %result_branch1 : tensor<2xi64>, tensor<2xi64>\\n    }) : (tensor<i32>) -> (tensor<2xi64>, tensor<2xi64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_TensorOrToken>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.cbrt\",\n    \"summary\": \"Cbrt operation\",\n    \"description\": \"Performs element-wise cubic root operation on `operand` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#cbrt\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.cbrt %operand : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.ceil\",\n    \"summary\": \"Ceil operation\",\n    \"description\": \"Performs element-wise ceil of `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#ceil\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.ceil %operand : tensor<5xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.cholesky\",\n    \"summary\": \"Cholesky operation\",\n    \"description\": \"Computes the Cholesky decomposition of a batch of matrices.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#cholesky\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.cholesky %a, lower = true : tensor<3x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MHLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpOrComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.clamp\",\n    \"summary\": \"Clamp operation\",\n    \"description\": \"Clamps every element of the `operand` tensor between a minimum and maximum\\n    value and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#clamp\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.clamp %min, %operand, %max : tensor<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"min\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"max\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$min `,` $operand `,` $max attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($min), type($operand), type($max), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.collective_broadcast\",\n    \"summary\": \"CollectiveBroadcast operation\",\n    \"description\": \"Within each process group in the process grid, send the value of the\\n    `operand` tensor from the source process to the target processes and produce a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#collective_broadcast\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.collective_broadcast\\\"(%operand) {\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,\\n      channel_handle = #mhlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<1x2xi64>) -> tensor<1x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<MHLO_ChannelHandle>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.collective_permute\",\n    \"summary\": \"CollectivePermute operation\",\n    \"description\": \"Within each process group in the process grid, sends the value of the\\n    `operand` tensor from the source process to the target process and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#collective_permute\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.collective_permute\\\"(%operand) {\\n      source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>,\\n      // channel_id = 0\\n      channel_handle = #mhlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<4x2xf32>) -> tensor<4x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_target_pairs\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<MHLO_ChannelHandle>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.compare\",\n    \"summary\": \"Compare operation\",\n    \"description\": \"Performs element-wise comparison of `lhs` and `rhs` tensors according to\\n    `comparison_direction` and `compare_type`, and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#compare\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.compare LT, %lhs, %rhs, FLOAT : (tensor<2xf32>, tensor<2xf32>) -> tensor<2xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_PredTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"comparison_direction\", \"type\": \"MHLO_ComparisonDirectionAttr{EQ|NE|GE|GT|LE|LT}\" },\n      { \"name\": \"compare_type\", \"type\": \"OptionalAttr<MHLO_ComparisonTypeAttr{NOTYPE|FLOAT|TOTALORDER|SIGNED|UNSIGNED}>\" }\n    ],\n    \"assemblyFormat\": \"$comparison_direction `,` $lhs `,` $rhs (`,` $compare_type^)?\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.complex\",\n    \"summary\": \"Complex operation\",\n    \"description\": \"Performs element-wise conversion to a complex value from a pair of real and\\n    imaginary values, `lhs` and `rhs`, and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#complex\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.complex %lhs, %rhs : tensor<2xcomplex<f32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Fp32Or64Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Fp32Or64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_ComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\\n      `:` custom<ComplexOpType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.composite\",\n    \"summary\": \"Composite operation\",\n    \"description\": \"Encapsulates an operation made up (composed) of other StableHLO operations,\\n    taking `inputs` and `composite_attributes` and producing `results`. The\\n    semantics of the op are implemented by the `decomposition` attribute. The\\n    `composite` op can be replaced with its decomposition without changing program\\n    semantics. In cases where inlining the decomposition does not provide the same\\n    op semantics, prefer using `custom_call`.\\n\\n    The `version` field (defaults to `0`) is used to denote when a composite's\\n    semantics change.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#composite\\n\\n    Example:\\n    ```mlir\\n    %results = mhlo.composite \\\"my.op\\\" %arg0, %arg1 {\\n      decomposition = @my_op,\\n      composite_attributes = { my_attribute = \\\"my_value\\\" },\\n      version = 1 : i32\\n    } : (tensor<f32>, tensor<f32>) -> tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_TensorOrTokenOrTuple>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_TensorOrTokenOrTuple>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"composite_attributes\", \"type\": \"DefaultValuedOptionalAttr<DictionaryAttr, {}>\" },\n      { \"name\": \"decomposition\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"version\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 0>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"composite_regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"$name operands (` ` `(` $composite_regions^ `)`)? attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.compute_reshape_shape\",\n    \"summary\": \"Compute input for reshape with any dynamic dim resolved\",\n    \"description\": \"This operation handles the dynamic aspect of a TF/NumPy/CHLO reshape. The\\n    dynamic aspect is that a single extent can be -1 and that dimension will\\n    instead be computed. This handles the computation and can then be passed to\\n    an HLO DynamicReshapeOp to replicate the TF/NumPy reshape behavior.\\n\\n    This op has undefined behavior if the dimensions do not evenly divide the\\n    number of elements, or if there are multiple -1 values. It is an identity op\\n    if no dimensions are -1.\\n\\n    ```\\n    %0 = hlo.compute_reshape_shape 12, [2, -1] -> [2, 6]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"num_elements\", \"type\": \"Index\" },\n      { \"name\": \"dynamic_shape\", \"type\": \"1DTensorOf<[AnyInteger, Index]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"1DTensorOf<[AnyInteger, Index]>\" }\n    ],\n    \"assemblyFormat\": \"$num_elements `,` $dynamic_shape attr-dict `:` type($num_elements) `,` type($dynamic_shape) `->` type($result)\"\n  },\n  {\n    \"name\": \"mhlo.concatenate\",\n    \"summary\": \"Concatenate operation\",\n    \"description\": \"Concatenates a variadic number of tensors in `inputs` along `dimension`\\n    dimension in the same order as the given arguments and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#concatenate\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.concatenate %input0, %input1, dim = 0 : (tensor<3x2xi64>, tensor<1x2xi64>) -> tensor<4x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.constant\",\n    \"summary\": \"Constant operation\",\n    \"description\": \"Produces an `output` tensor from a constant `value`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#constant\\n\\n    Example:\\n    ```mlir\\n    %output = mhlo.constant dense<[[0.0, 1.0], [2.0, 3.0]]> : tensor<2x2xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MHLO_StaticShapeTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mhlo.convert\",\n    \"summary\": \"Convert operation\",\n    \"description\": \"Performs an element-wise conversion from one element type to another on\\n    `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#convert\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.convert %operand : (tensor<3xi32>) -> tensor<3xcomplex<f32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.convolution\",\n    \"summary\": \"Convolution operation\",\n    \"description\": \"Computes dot products between windows of `lhs` and slices of `rhs` and\\n    produces `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#convolution\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.convolution\\\"(%lhs, %rhs) {\\n      window_strides = dense<4> : tensor<2xi64>,\\n      padding = dense<0> : tensor<2x2xi64>,\\n      lhs_dilation = dense<2> : tensor<2xi64>,\\n      rhs_dilation = dense<1> : tensor<2xi64>,\\n      window_reversal = dense<false> : tensor<2xi1>,\\n      dimension_numbers = #mhlo.conv<[b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f]>,\\n      feature_group_count = 1 : i64,\\n      batch_group_count = 1 : i64,\\n      precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]\\n    } : (tensor<1x4x4x1xi32>, tensor<3x3x1x1xi32>) -> tensor<1x2x2x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"window_reversal\", \"type\": \"OptionalAttr<MHLO_BoolElementsAttr>\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"MHLO_ConvDimensionNumbers\" },\n      { \"name\": \"feature_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"batch_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ],\n    \"assemblyFormat\": \"`(`operands`)`\\n       `dim_numbers` `=` custom<ConvolutionDimensions>($dimension_numbers) `,`\\n       `window` `=` `{` custom<WindowAttributes>($window_strides, $padding,\\n                                                 $lhs_dilation, $rhs_dilation,\\n                                                 $window_reversal) `}`\\n       attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.copy\",\n    \"summary\": \"Copy operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation a copy of `operand`. Depending on the metadata\\n    attached to the operation, it can behave quite differently from a no-op.\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.copy %arg0 : tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_TensorOrTokenOrTuple\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_TensorOrTokenOrTuple\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cross_program_prefetch_index\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.cosh\",\n    \"summary\": \"Cosh operation\",\n    \"description\": \"Performs element-wise cosh operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.cosh %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.cosine\",\n    \"summary\": \"Cosine operation\",\n    \"description\": \"Performs element-wise cosine operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#cosine\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.cosine %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.count_leading_zeros\",\n    \"summary\": \"Clz operation\",\n    \"description\": \"Performs element-wise count of the number of leading zero bits in the\\n    `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#count_leading_zeros\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.count_leading_zeros %operand : tensor<2x2xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.create_token\",\n    \"summary\": \"CreateToken operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as AfterAllOp with 0 inputs:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#after_all\\n\\n    Example:\\n    ```mlir\\n    %output = mhlo.create_token : !mhlo.token\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MHLO_Token\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mhlo.cross-replica-sum\",\n    \"summary\": \"CrossReplicaSum operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as AllReduceOp with\\n    `channel_id = 0`, `use_global_device_ids = false` and `computation`\\n    implementing addition:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_reduce\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.cross-replica-sum\\\"(%operand) {\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>\\n    } : (tensor<4xf32>) -> tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.cstr_reshapable\",\n    \"summary\": \"Compute input for reshape with any dynamic dim resolved\",\n    \"description\": \"This operation creates a witness on the constraint that a given shape would\\n    be a valid reshape for the given number of elements.\\n\\n    ```\\n    %0 = mhlo.cstr_reshapable 12, [2, -1] -> success\\n    %1 = mhlo.cstr_reshapable 13, [2, -1] -> failure\\n    ```\",\n    \"operands\": [\n      { \"name\": \"num_elements\", \"type\": \"Index\" },\n      { \"name\": \"dynamic_shape\", \"type\": \"1DTensorOf<[AnyInteger, Index]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"assemblyFormat\": \"$num_elements `,` $dynamic_shape attr-dict `:` type($num_elements) `,` type($dynamic_shape)\"\n  },\n  {\n    \"name\": \"mhlo.custom_call\",\n    \"summary\": \"CustomCall operation\",\n    \"description\": \"Encapsulates an implementation-defined operation `call_target_name` that\\n    takes `inputs` and `called_computations` and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#custom_call\\n\\n    Example:\\n    ```mlir\\n    %results = \\\"mhlo.custom_call\\\"(%input0) {\\n      call_target_name = \\\"foo\\\",\\n      has_side_effect = false,\\n      backend_config = \\\"bar\\\",\\n      api_version = 1 : i32,\\n      called_computations = [@foo]\\n    } : (tensor<f32>) -> tensor<f32>\\n\\n    A custom call invokes code external to XLA. The `inputs` are passed to the\\n    external code, and the external code is expected to produce a result of the\\n    given type. The exact mechanism is backend-specific. For example, in the CPU\\n    backend, a call instruction is emitted which targets a symbol with the name\\n    `call_target_name`.\\n\\n    If XLA runtime is enabled for a backend, then custom calls use the runtime\\n    custom call calling convention to call into the external functions. This\\n    calling convention defines an ABI for encoding arguments, attributes and\\n    results.\\n\\n    Depending on the API version there are two ways to pass extra bits of static\\n    information to the external function:\\n\\n    1. For `API_VERSION_TYPED_FFI` custom calls `backend_config` must be a\\n       dictionary attribute, that will be encoded according to the custom call\\n       calling convention and passed to the external function as the attributes\\n       argument. External code is expected to use declarative bindings (see\\n       `xla/runtime/custom_call.h`) to decode them at run time. These custom\\n       calls are only supported if XLA uses XLA runtime.\\n\\n    2. For previous API versions it is the user responsibility to encode extra\\n       bits of static information as a string `backend_config` attribute, and\\n       decode it at run time.\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_CustomCallValue>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_CustomCallValue>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"call_target_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"has_side_effect\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"backend_config\", \"type\": \"OptionalAttr<AnyAttrOf<[ StrAttr, DictionaryAttr ]>>\" },\n      { \"name\": \"api_version\", \"type\": \"DefaultValuedOptionalAttr<MHLO_CustomCallApiVersionAttr{API_VERSION_UNSPECIFIED|API_VERSION_ORIGINAL|API_VERSION_STATUS_RETURNING|API_VERSION_STATUS_RETURNING_UNIFIED|API_VERSION_TYPED_FFI}, ::mlir::mhlo::CustomCallApiVersion::API_VERSION_ORIGINAL>\" },\n      { \"name\": \"called_computations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<FlatSymbolRefAttr>, {}>\" },\n      { \"name\": \"custom_call_schedule\", \"type\": \"DefaultValuedOptionalAttr<MHLO_CustomCallScheduleAttr{NONE|LATEST|EARLIEST}, ::mlir::mhlo::CustomCallSchedule::NONE>\" },\n      { \"name\": \"operand_layouts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_LayoutAttr>>\" },\n      { \"name\": \"result_layouts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_LayoutAttr>>\" },\n      { \"name\": \"output_operand_aliases\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<MHLO_OutputOperandAlias, Aliasing attribute for outputs and operands of CustomCall>, {}>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomCallTarget>($call_target_name) `(` $inputs `)`\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.dequantize\",\n    \"summary\": \"Dequantize operator\",\n    \"description\": \"Dequantize the quantized input of packed uint32 to bfloat16. Only uint8 or\\n    uint16 is supported for the original unpacked input.\\n\\n    Returns a tensor of shape [d0,..., dn * unpack_size] if unpacked input shape\\n    is [d0, ..., dn], where unpack_size = sizeof(unit32) / sizeof(T), where T is\\n    the unpacked input type. If transpose_output is true, will return a tensor\\n    of shape [dn * unpack_size, dn-1, ..., d1, d0]. transpose_output is faster\\n    when input's rank higher than 1. The input needs to be transposed to use\\n    transpose_output feature.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[BF16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min_range\", \"type\": \"F32Attr\" },\n      { \"name\": \"max_range\", \"type\": \"F32Attr\" },\n      { \"name\": \"mode\", \"type\": \"HLO_DequantizeModeAttr\" },\n      { \"name\": \"transpose_output\", \"type\": \"BoolAttr\" },\n      { \"name\": \"is_16bits\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.divide\",\n    \"summary\": \"Div operation\",\n    \"description\": \"Performs element-wise division of dividend `lhs` and divisor `rhs` tensors\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#divide\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.divide %lhs, %rhs : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.domain\",\n    \"summary\": \"Domain operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, these operations are used to group instructions with the same\\n    DomainMetadata property. ShardingMetadata is the main use case today to\\n    group instructions on the same device. Domain instructions provide two\\n    major benefits:\\n      - Prevent unintentionally optimizing instructions across domains.\\n      - Automatically assign the metadata of the instructions created in the domain.\\n    Without domain instructions, each HLO optimization pass would have to check\\n    and propagate the metadata, which would be easy to miss and also adds\\n    complexity to the compiler. Since domain instructions connect two different\\n    domains, each domain instruction is associated with two DomainMetadata --\\n    one on the operand side and one on the user side of the domain.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_TensorOrToken\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_TensorOrToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MHLO_DomainKindAttr{sharding}\" },\n      { \"name\": \"entry_metadata\", \"type\": \"StrAttr\" },\n      { \"name\": \"exit_metadata\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dot\",\n    \"summary\": \"Dot operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as XLA's Dot:\\n    https://www.tensorflow.org/xla/operation_semantics#dot\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.dot %arg0, %arg1 : (tensor<1x2xi32>, tensor<2x1xi32>) -> tensor<1x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dot_general\",\n    \"summary\": \"DotGeneral operation\",\n    \"description\": \"Computes dot products between slices of `lhs` and slices of `rhs` and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dot_general\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.dot_general\\\"(%lhs, %rhs) {\\n      dot_dimension_numbers = #mhlo.dot<\\n        lhs_batching_dimensions = [0],\\n        rhs_batching_dimensions = [0],\\n        lhs_contracting_dimensions = [2],\\n        rhs_contracting_dimensions = [1]\\n      >,\\n      precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]\\n    } : (tensor<2x2x2xi32>, tensor<2x2x2xi32>) -> tensor<2x2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dot_dimension_numbers\", \"type\": \"MHLO_DotDimensionNumbers\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" },\n      { \"name\": \"algorithm\", \"type\": \"OptionalAttr<MHLO_DotAlgorithmAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic_broadcast_in_dim\",\n    \"summary\": \"DynamicBroadcastInDim operation\",\n    \"description\": \"This operation is functionally identical to\\n    [broadcast_in_dim](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#broadcast_in_dim)\\n    op, but the result shape is specified dynamically via `output_dimensions`.\\n\\n    It also accepts optional attributes to express static knowledge about the\\n    expanding behavior of dimensions. If not specified, all dimensions are\\n    assumed to be possibly expanding. The sets of dimensions that are known to\\n    be expanding and the set of dimensions that are known to be non-expanding\\n    must be disjoint and they must be a subset of the operand's dimensions.\\n\\n    See: https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_broadcast_in_dim\\n\\n    Example:\\n    ```mlir\\n    %operand = mhlo.constant dense<[[1, 2, 3]]> : tensor<1x3xi64>\\n    %output_dimensions = mhlo.constant dense<[2, 3, 2]> : tensor<3xi64>\\n    %result = \\\"mhlo.dynamic_broadcast_in_dim\\\"(%operand, %output_dimensions) {\\n      broadcast_dimensions = array<i64: 2, 1>,\\n      known_expanding_dimensions = array<i64: 0>,\\n      known_nonexpanding_dimensions = array<i64: 1>\\n    } : (tensor<1x3xi64>, tensor<3xi64>) -> tensor<2x3x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"output_dimensions\", \"type\": \"MHLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"MHLO_BroadcastDimAttr\" },\n      { \"name\": \"known_expanding_dimensions\", \"type\": \"OptionalAttr<MHLO_BroadcastDimAttr>\" },\n      { \"name\": \"known_nonexpanding_dimensions\", \"type\": \"OptionalAttr<MHLO_BroadcastDimAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic_conv\",\n    \"summary\": \"DynamicConv operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/8.\\n\\n    Informally, this operation does the same thing as ConvolutionOp except\\n    that `padding` is specified dynamically via `d_padding`:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#convolution\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.dynamic_conv\\\"(%lhs, %rhs, %d_padding) {\\n      window_strides = dense<4> : tensor<2xi64>,\\n      lhs_dilation = dense<2> : tensor<2xi64>,\\n      rhs_dilation = dense<1> : tensor<2xi64>,\\n      window_reversal = dense<false> : tensor<2xi1>,\\n      dimension_numbers = #mhlo.conv<[b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f]>,\\n      feature_group_count = 1 : i64,\\n      batch_group_count = 1 : i64,\\n      precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]\\n    } : (tensor<1x4x4x1xi32>, tensor<3x3x1x1xi32>, tensor<2x2xi64>) -> tensor<1x2x2x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"d_padding\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"window_reversal\", \"type\": \"OptionalAttr<MHLO_BoolElementsAttr>\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"MHLO_ConvDimensionNumbers\" },\n      { \"name\": \"feature_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"batch_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic_gather\",\n    \"summary\": \"DynamicGather operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/8.\\n\\n    Informally, this operation does the same thing as GatherOp except\\n    that `slice_sizes` are specified dynamically:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#gather\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.dynamic_gather\\\"(%operand, %start_indices, %slice_sizes) {\\n      dimension_numbers = #mhlo.gather<\\n        offset_dims = [2, 3],\\n        collapsed_slice_dims = [0],\\n        start_index_map = [0, 2],\\n        index_vector_dim = 2>,\\n      indices_are_sorted = false\\n    } : (tensor<3x4x2xi32>, tensor<2x3x2xi64>, tensor<3xi64>) -> tensor<2x3x2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"MHLO_IntTensor\" },\n      { \"name\": \"slice_sizes\", \"type\": \"MHLO_Static1DIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"MHLO_GatherDimensionNumbers\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic_iota\",\n    \"summary\": \"DynamicIota operation\",\n    \"description\": \"This operation is functionally identical to\\n    [iota](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#iota)\\n    op, but the result shape is specified dynamically via `output_shape`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_iota\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.dynamic_iota %arg0, dim = 0 : (tensor<1xindex>) -> tensor<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"output_shape\", \"type\": \"MHLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic_pad\",\n    \"summary\": \"DynamicPad operation\",\n    \"description\": \"Dynamically Pads the `operand`, with amount of padding added at\\n    low-end/high-end/interior is passed through input tensors.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"edge_padding_low\", \"type\": \"MHLO_DimensionTensor\" },\n      { \"name\": \"edge_padding_high\", \"type\": \"MHLO_DimensionTensor\" },\n      { \"name\": \"interior_padding\", \"type\": \"MHLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['edge_padding_low', 'edge_padding_high', 'interior_padding']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.dynamic_reshape\",\n    \"summary\": \"DynamicReshape operation\",\n    \"description\": \"This operation is functionally identical to\\n    [reshape](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reshape)\\n    op, but the result shape is specified dynamically via `output_shape`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_reshape\\n\\n    Example:\\n    ```mlir\\n    %output_shape = mhlo.constant dense<[3, 2]> : tensor<2xi64>\\n    %result = mhlo.dynamic_reshape %operand, %output_shape : (tensor<2x3xi64>, tensor<2xi64>) -> tensor<3x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_AnyTensor\" },\n      { \"name\": \"output_shape\", \"type\": \"MHLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.dynamic_slice\",\n    \"summary\": \"DynamicSlice operation\",\n    \"description\": \"Extracts a slice from the `operand` using dynamically-computed starting\\n    indices and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_slice\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.dynamic_slice %operand, %start_indices0, %start_indices1, sizes = [2, 2]\\n      : (tensor<4x4xi32>, tensor<i64>, tensor<i64>) -> tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<MHLO_ScalarIntTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slice_sizes\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic_update_slice\",\n    \"summary\": \"DynamicUpdateSlice operation\",\n    \"description\": \"Produces a `result` tensor which is equal to the `operand` tensor except\\n    that the slice starting at `start_indices` is updated with the values in\\n    `update`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_update_slice\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.dynamic_update_slice %operand, %update, %start_indices0, %start_indices1\\n      : (tensor<4x4xi32>, tensor<2x2xi32>, tensor<i64>, tensor<i64>) -> tensor<4x4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"update\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<MHLO_ScalarIntTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.dynamic-slice\",\n    \"summary\": \"Dynamic Slice operator\",\n    \"description\": \"Extracts a sub-array from the input array at dynamic start_indices.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#dynamicslice.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<HLO_ScalarIntTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slice_sizes\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.dynamic-update-slice\",\n    \"summary\": \"Dynamic Update Slice operator\",\n    \"description\": \"DynamicUpdateSlice generates a result which is the value of the input array\\n    operand, with a slice update overwritten at start_indices.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#dynamicupdateslice.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"update\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<HLO_ScalarIntTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.einsum\",\n    \"summary\": \"Einsum operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as TF's einsum:\\n    https://www.tensorflow.org/api_docs/python/tf/einsum\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.einsum\\\"(%lhs, %rhs) {\\n      einsum_config = \\\"ab,bc->ac\\\"\\n    } : (tensor<4x16xf32>, tensor<16x4xf32>) -> tensor<4x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"einsum_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.erf\",\n    \"summary\": \"Erf operation\",\n    \"description\": \"Performs element-wise erf operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.erf %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.exponential\",\n    \"summary\": \"Exp operation\",\n    \"description\": \"Performs element-wise exponential operation on `operand` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#exponential\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.exponential %operand : tensor<2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.exponential_minus_one\",\n    \"summary\": \"Expm1 operation\",\n    \"description\": \"Performs element-wise exponential minus one operation on `operand` tensor\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#exponential_minus_one\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.exponential_minus_one %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.fft\",\n    \"summary\": \"Fft operation\",\n    \"description\": \"Performs the forward and inverse Fourier transforms for real and complex\\n    inputs/outputs.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#fft\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.fft %operand, type = FFT, length = [4] : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fft_type\", \"type\": \"MHLO_FftTypeAttr{FFT|IFFT|RFFT|IRFFT}\" },\n      { \"name\": \"fft_length\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.floor\",\n    \"summary\": \"Floor operation\",\n    \"description\": \"Performs element-wise floor of `operand` tensor and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#floor\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.floor %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.fusion\",\n    \"summary\": \"Fusion operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation consists of a group of basic ops (represented as\\n    a region attached to it). It serves as a hint to the backend that it is\\n    beneficial to emit the contained ops into a single loop nest or kernel.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_TensorOrToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ MHLO_Tensor, MHLO_Tuple ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fusion_kind\", \"type\": \"OptionalAttr<MHLO_FusionKindAttr{kLoop|kInput|kOutput|kCustom}>\" },\n      { \"name\": \"output_operand_aliases\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<MHLO_OutputOperandAlias, Aliasing attribute for outputs and operands of Fusion>, {}>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"fused_computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.gather\",\n    \"summary\": \"Gather operation\",\n    \"description\": \"Gathers slices from `operand` tensor from offsets specified in\\n    `start_indices` and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#gather\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.gather\\\"(%operand, %start_indices) {\\n      dimension_numbers = #stablehlo.gather<\\n        offset_dims = [3, 4],\\n        collapsed_slice_dims = [1],\\n        operand_batching_dims = [0],\\n        start_indices_batching_dims = [1],\\n        start_index_map = [2, 1],\\n        index_vector_dim = 3>,\\n      slice_sizes = dense<[0, 2, 2]> : tensor<3xi64>,\\n      indices_are_sorted = false\\n    } : (tensor<2x3x4x2xi64>, tensor<2x2x3x2xi64>) -> tensor<2x2x3x2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"MHLO_GatherDimensionNumbers\" },\n      { \"name\": \"slice_sizes\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.get_dimension_size\",\n    \"summary\": \"GetDimensionSize operation\",\n    \"description\": \"Produces the size of the given `dimension` of the `operand`.\\n\\n    See\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#get_dimension_size\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.get_dimension_size %operand, dim = 1 : (tensor<2x3xf32>) -> tensor<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.get_tuple_element\",\n    \"summary\": \"GetTupleElement operation\",\n    \"description\": \"Extracts element at `index` position of the `operand` tuple and produces a\\n    `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#get_tuple_element\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.get_tuple_element %operand[0] : (tuple<tensor<2xf32>, tuple<tensor<i32>>>) -> tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tuple\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_TensorOrTokenOrTupleOrBuffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `[` $index `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.if\",\n    \"summary\": \"If operation\",\n    \"description\": \"Produces the output from executing exactly one branch from `true_branch` or\\n    `false_branch` depending on the value of `pred`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#if\\n\\n    Example:\\n    %result = \\\"mhlo.if\\\"(%pred) ({\\n      \\\"mhlo.return\\\"(%result_true_branch) : (tensor<i32>) -> ()\\n    }, {\\n      \\\"mhlo.return\\\"(%result_false_branch) : (tensor<i32>) -> ()\\n    }) : (tensor<i1>) -> tensor<i32>\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"MHLO_PredTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_TensorOrToken>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"true_branch\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"false_branch\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.imag\",\n    \"summary\": \"Imag operation\",\n    \"description\": \"Extracts the imaginary part, element-wise, from the `operand` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#imag\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.imag %operand : (tensor<2xcomplex<f32>>) -> tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.infeed\",\n    \"summary\": \"Infeed operation\",\n    \"description\": \"Reads data from the infeed and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#infeed\\n\\n    Example:\\n    ```mlir\\n    %results:2 = \\\"mhlo.infeed\\\"(%token) {\\n      infeed_config = \\\"\\\"\\n    } : (!mhlo.token) -> (tensor<3x3x3xi32>, !mhlo.token)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"MHLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_StaticShapeTensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"infeed_config\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.iota\",\n    \"summary\": \"Iota operation\",\n    \"description\": \"Fills an `output` tensor with values in increasing order starting from zero\\n    along the `iota_dimension` dimension.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#iota\\n\\n    Example:\\n    ```mlir\\n    %output = mhlo.iota dim = 0 : tensor<4x5xi32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MHLO_StaticShapeIntFpOrComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.is_finite\",\n    \"summary\": \"IsFinite operation\",\n    \"description\": \"Performs element-wise check whether the value in `x` is finite (i.e. is\\n    neither +Inf, -Inf, nor NaN) and produces a `y` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#is_finite\\n\\n    Example:\\n    ```mlir\\n    %y = mhlo.is_finite %x : (tensor<7xf32>) -> tensor<7xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"MHLO_PredTensor\" }\n    ],\n    \"assemblyFormat\": \"$x attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.log\",\n    \"summary\": \"Log operation\",\n    \"description\": \"Performs element-wise logarithm operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#log\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.log %operand : tensor<2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.log_plus_one\",\n    \"summary\": \"Log1p operation\",\n    \"description\": \"Performs element-wise logarithm plus one operation on `operand` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#log_plus_one\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.log_plus_one %operand : tensor<6xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.logistic\",\n    \"summary\": \"Logistic operation\",\n    \"description\": \"Performs element-wise logistic operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#logistic\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.logistic %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.map\",\n    \"summary\": \"Map operation\",\n    \"description\": \"Applies a map function `computation` to `inputs` along the `dimensions` and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#map\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.map\\\"(%input0, %input1) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = mhlo.multiply %arg0, %arg1 : tensor<i32>\\n        mhlo.return %0 : tensor<i32>\\n    }) {\\n      dimensions = dense<[0, 1]> : tensor<2xi64>\\n    } : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"I64ElementsAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.maximum\",\n    \"summary\": \"Max operation\",\n    \"description\": \"Performs element-wise max operation on tensors `lhs` and `rhs` and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#maximum\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.maximum %lhs, %rhs : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.minimum\",\n    \"summary\": \"Min operation\",\n    \"description\": \"Performs element-wise min operation on tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#minimum\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.minimum %lhs, %rhs : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.minimum_broadcast_shapes\",\n    \"summary\": \"Minimizes the rank of two or more shapes to be broadcasted\",\n    \"description\": \"Given two or more 1D tensors representing shapes, returns one 1D tensor for\\n    each operand, where operand `i` corresponds to output `i`.\\n\\n    The returned tensors have the property that they specify a shape which is a\\n    reshape of the corresponding input shape, and the broadcasted output shape\\n    (using shape::BroadcastOp) of the returned shapes is a reshape of the\\n    broadcasted output shape of the input shapes. Among all possibilities with\\n    this property, the one is chosen which minimizes the rank of each returned\\n    shape.\\n\\n    The general idea of this op is that it can be used for ops which have a\\n    broadcasting semantic to operate on shapes with a possibly smaller rank\\n    while preserving equivalence of the computed values. After computing the\\n    result of the op using reshaped operands, the result can be reshaped to the\\n    result that would have been originally computed.\\n\\n    Here is an example with two input shapes:\\n\\n    ```mlir\\n    mhlo.minimum_broadcast_shapes [1, 2, 3, 1, 2, 1],\\n                                     [1, 1, 1, 2, 3] -> [6, 2, 1], [2, 3]\\n    ```\\n\\n    The broadcasted output shape of the operands is [1, 2, 3, 1, 2, 3], the\\n    broadcasted output shape of the outputs is [6, 2, 3]. These two shapes are\\n    reshapes of each other, and also each output is a reshape of the\\n    corresponding input.\",\n    \"operands\": [\n      { \"name\": \"shapes\", \"type\": \"Variadic<1DTensorOf<[ Index ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<1DTensorOf<[ Index ]>>\" }\n    ],\n    \"assemblyFormat\": \"$shapes attr-dict `:` type($shapes) `->` type($results)\"\n  },\n  {\n    \"name\": \"mhlo.multiply\",\n    \"summary\": \"Mul operation\",\n    \"description\": \"Performs element-wise product of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#multiply\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.multiply %lhs, %rhs : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.negate\",\n    \"summary\": \"Neg operation\",\n    \"description\": \"Performs element-wise negation of `operand` tensor and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#negate\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.negate %operand : tensor<2x3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.not\",\n    \"summary\": \"Not operation\",\n    \"description\": \"Performs element-wise NOT of tensor `operand` of type integer and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#not\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.not %operand : tensor<5x3x1xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_PredOrIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.optimization_barrier\",\n    \"summary\": \"OptimizationBarrier operation\",\n    \"description\": \"Ensures that the operations that produce the `operand` are executed before any\\n    operations that depend on the `result` and prevents compiler transformations\\n    from moving operations across the barrier. Other than that, the operation is\\n    an identity, i.e. `result` = `operand`.\\n\\n    See\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#optimization_barrier\\n\\n    Example:\\n    ```mlir\\n    %result0, %result1 = mhlo.optimization_barrier %operand0, %operand1 : tensor<f32>, tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<MHLO_TensorOrToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_TensorOrToken>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operand^ `:` custom<PairwiseOpType>(type($operand), type($result))):(`(` `)`)?\"\n  },\n  {\n    \"name\": \"mhlo.or\",\n    \"summary\": \"Or operation\",\n    \"description\": \"Performs element-wise OR of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#or\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.or %lhs, %rhs : tensor<2xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_PredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.outfeed\",\n    \"summary\": \"Outfeed operation\",\n    \"description\": \"Writes `inputs` to the outfeed and produces a `result` token.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#outfeed\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.outfeed\\\"(%input0, %token) {\\n      outfeed_config = \\\"\\\"\\n    } : (tensor<3x3x3xi32>, !mhlo.token) -> !mhlo.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"token\", \"type\": \"MHLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Token\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outfeed_config\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.pad\",\n    \"summary\": \"Pad operation\",\n    \"description\": \"Expands `operand` by padding around the tensor as well as between the\\n    elements of the tensor with the given `padding_value`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#pad\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.pad %arg0, %arg1, low = [0, 1], high = [2, 1], interior = [1, 2]\\n      : (tensor<2x3xi32>, tensor<i32>) -> tensor<5x9xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"edge_padding_low\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"edge_padding_high\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"interior_padding\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.partition_id\",\n    \"summary\": \"PartitionId operation\",\n    \"description\": \"Produces `partition_id` of the current process.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#partition_id\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.partition_id : tensor<ui32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"UI32RankedTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mhlo.popcnt\",\n    \"summary\": \"PopulationCount operation\",\n    \"description\": \"Performs element-wise count of the number of bits set in the `operand`\\n    tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#popcnt\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.popcnt %operand : tensor<4xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.power\",\n    \"summary\": \"Pow operation\",\n    \"description\": \"Performs element-wise exponentiation of `lhs` tensor by `rhs` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#power\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.power %lhs, %rhs : tensor<6xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.print\",\n    \"summary\": \"Print operation\",\n    \"description\": \"PrintOp is used to print tensor, which can be used to debug.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"HLO_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.ragged_dot\",\n    \"summary\": \"Ragged matrix multiplication over a single ragged dimension\",\n    \"description\": \"This operation takes three tensor args---lhs, rhs, and group_sizes---and\\n    a \\\"ragged_dot_dimension_numbers\\\" attribute. Like dot_general, the lhs and\\n    rhs are allowed arbitrary batch and contracting dimensions. Additionally,\\n    the lhs is required to have one ragged dimension, and the rhs may have at\\n    most one group dimension. The op has three modes, depending on the kind of\\n    the lhs ragged dimension.\\n\\n    In mode 1, the shape-signature is `[b,m,k], [g,b,k,n], [b,g] -> [b,m,n]`.\\n    Here the ragged dimension is an lhs non-contracting dimension (`m`). The\\n    dimensions `b` and `k` represent batch and contracting dimensions\\n    respectively. The rhs is required to have a group dimension (`g`).\\n\\n    In mode 2, the shape-signature is `[b,m,k], [b,k,n], [b,g] -> [g,b,m,n]`.\\n    Here the ragged dimension is an lhs/rhs contracting dimension (`k`).\\n\\n    In mode 3, the shape-signature is `[b,m,k], [b,k,n], [g] -> [b,m,n]`. Here\\n    the ragged dimension is an lhs/rhs batch dimension (`b`).\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"group_sizes\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ragged_dot_dimension_numbers\", \"type\": \"MHLO_RaggedDotDimensionNumbers\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<MHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.real\",\n    \"summary\": \"Real operation\",\n    \"description\": \"Extracts the real part, element-wise, from the `operand` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#real\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.real %operand : (tensor<2xcomplex<f32>>) -> tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.real_dynamic_slice\",\n    \"summary\": \"RealDynamicSlice operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/8.\\n\\n    Informally, this operation does the same thing as SliceOp except\\n    that `start_indices`, `limit_indices` and `strides` are specified dynamically:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#slice\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.real_dynamic_slice %operand,\\n                %start_indices, %limit_indices, %strides\\n           : (tensor<256x?xf32>, tensor<2xindex>, tensor<2xindex>, tensor<2xindex>) -> tensor<256x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"MHLO_DimensionTensor\" },\n      { \"name\": \"limit_indices\", \"type\": \"MHLO_DimensionTensor\" },\n      { \"name\": \"strides\", \"type\": \"MHLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['start_indices', 'limit_indices', 'strides']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.recv\",\n    \"summary\": \"Recv operation\",\n    \"description\": \"Receives data from a channel with `channel_id` and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#recv\\n\\n    Example:\\n    ```mlir\\n    %results:2 = \\\"mhlo.recv\\\"(%token) {\\n      // channel_id = 5 : i64,\\n      // channel_type = #stablehlo<channel_type DEVICE_TO_DEVICE>,\\n      channel_handle = #mhlo.channel_handle<handle = 5, type = 1>,\\n      is_host_transfer = false,\\n      source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>\\n    } : (!mhlo.token) -> (tensor<3x4xi32>, !mhlo.token)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"MHLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_StaticShapeTensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_handle\", \"type\": \"MHLO_ChannelHandle\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.reduce\",\n    \"summary\": \"Reduce operation\",\n    \"description\": \"Applies a reduction function `body` to `inputs` and `init_values` along the\\n    `dimensions` and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.reduce\\\"(%input, %init_value) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"mhlo.add\\\"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>\\n        \\\"mhlo.return\\\"(%0) : (tensor<i32>) -> ()\\n    }) {\\n      dimensions = dense<1> : tensor<1xi64>\\n    } : (tensor<1x6xi32>, tensor<i32>) -> tensor<1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"I64ElementsAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mhlo.reduce_precision\",\n    \"summary\": \"ReducePrecision operation\",\n    \"description\": \"Performs element-wise conversion of `operand` to another floating-point type\\n    that uses `exponent_bits` and `mantissa_bits` and back to the original\\n    floating-point type and produces an `output` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce_precision\\n\\n    Example:\\n    ```mlir\\n    %output = mhlo.reduce_precision %operand, format = e5m2 : tensor<6xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exponent_bits\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"mantissa_bits\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `format` `=` custom<ExponentMantissa>($exponent_bits, $mantissa_bits)\\n      attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($output))\"\n  },\n  {\n    \"name\": \"mhlo.reduce_scatter\",\n    \"summary\": \"ReduceScatter operation\",\n    \"description\": \"Within each process group in the process grid, performs reduction, using\\n     `computations`, over the values of the `operand` tensor from each process,\\n     splits the reduction result along `scatter_dimension` into parts, and\\n     scatters the split parts between the processes to produce the `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce_scatter\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.reduce_scatter\\\"(%operand) ({\\n      ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):\\n      %0 = mhlo.add %arg0, %arg1 : tensor<f32>\\n      mhlo.return %0 : tensor<f32>\\n    }) {\\n      scatter_dimension = 1 : i64,\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,\\n      // channel_id = 0\\n      channel_handle = #mhlo.channel_handle<handle = 0, type = 0>\\n      // use_global_device_ids = false\\n    } : (tensor<2x4xf32>) -> tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<MHLO_ChannelHandle>\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.reduce_window\",\n    \"summary\": \"ReduceWindow operation\",\n    \"description\": \"Applies a reduction function `body` to windows of `inputs` and `init_values`\\n    and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce_window\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.reduce_window\\\"(%input, %init_value) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = mhlo.add %arg0, %arg1 : tensor<i32>\\n        mhlo.return %0 : tensor<i32>\\n    }) {\\n      window_dimensions = dense<[2, 1]> : tensor<2xi64>,\\n      window_strides = dense<[4, 1]> : tensor<2xi64>,\\n      base_dilations = dense<[2, 1]> : tensor<2xi64>,\\n      window_dilations = dense<[3, 1]> : tensor<2xi64>,\\n      padding = dense<[[2, 1], [0, 0]]> : tensor<2x2xi64>\\n    } : (tensor<3x2xi32>, tensor<i32>) -> tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"base_dilations\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"window_dilations\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.remainder\",\n    \"summary\": \"Rem operation\",\n    \"description\": \"Performs element-wise remainder of dividend `lhs` and divisor `rhs` tensors\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#remainder\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.remainder %lhs, %rhs : tensor<4xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.replica_id\",\n    \"summary\": \"ReplicaId operation\",\n    \"description\": \"Produces `replica_id` of the current process.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#replica_id\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.replica_id : tensor<ui32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"UI32RankedTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mhlo.reshape\",\n    \"summary\": \"Reshape operation\",\n    \"description\": \"Performs reshape of `operand` tensor to a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reshape\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.reshape %operand : (tensor<2xf32>) -> tensor<1x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_StaticShapeOrBoundedDimTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mhlo.return\",\n    \"summary\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/425.\\n\\n    Informally, this operation serves as a terminator for regions defined by\\n    the StableHLO ops. Non-StableHLO ops, e.g. `func.func`, have their own\\n    terminators, e.g. `func.return`.\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.reduce\\\"(%input, %init_value) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"mhlo.add\\\"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>\\n        \\\"mhlo.return\\\"(%0) : (tensor<i32>) -> ()\\n    }) {\\n      dimensions = dense<1> : tensor<1xi64>\\n    } : (tensor<1x6xi32>, tensor<i32>) -> tensor<1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MHLO_TensorOrTokenOrTupleOrBuffer>\" }\n    ],\n    \"assemblyFormat\": \"$results attr-dict (`:` type($results)^)?\"\n  },\n  {\n    \"name\": \"mhlo.reverse\",\n    \"summary\": \"Reverse operation\",\n    \"description\": \"Reverses the order of elements in the `operand` along the specified\\n    `dimensions` and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reverse\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.reverse %operand, dims = [1] : tensor<3x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.rng\",\n    \"summary\": \"Rng operation\",\n    \"description\": \"Generates random numbers using the `rng_distribution` algorithm and produces\\n    a `result` tensor of a given shape `shape`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#rng\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.rng %a, %b, %shape, distribution = NORMAL : (tensor<i32>, tensor<i32>, tensor<2xi64>) -> tensor<3x3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"0DTensorOf<[MHLO_Pred, MHLO_Int, MHLO_Float]>\" },\n      { \"name\": \"b\", \"type\": \"0DTensorOf<[MHLO_Pred, MHLO_Int, MHLO_Float]>\" },\n      { \"name\": \"shape\", \"type\": \"MHLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_PredIntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_distribution\", \"type\": \"MHLO_RngDistributionAttr{UNIFORM|NORMAL}\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.rng_bit_generator\",\n    \"summary\": \"RngBitGenerator operation\",\n    \"description\": \"Returns an `output` filled with uniform random data and an updated output\\n    state `output_state` given an initial state `initial_state` using the\\n    pseudorandom number generator algorithm `rng_algorithm`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#rng_bit_generator\\n\\n    Example:\\n    ```mlir\\n    %output_state, %output = mhlo.rng_bit_generator %initial_state, algorithm = THREE_FRY : (tensor<2xui64>) -> (tensor<2xui64>, tensor<2x2xui64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"initial_state\", \"type\": \"MHLO_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_state\", \"type\": \"MHLO_IntOrFpTensor\" },\n      { \"name\": \"output\", \"type\": \"MHLO_StaticShapeIntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_algorithm\", \"type\": \"MHLO_RngAlgorithmAttr{DEFAULT|THREE_FRY|PHILOX}\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.rng_normal\",\n    \"summary\": \"RNG with normal distribution.\",\n    \"description\": \"Constructs an output of a given shape with random numbers generated\\n    following the normal distribution with parameters `mu` and `sigma`. The\\n    parameters and output shape have to have a floating point elemental type.\\n    The parameters furthermore have to be scalar valued.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#rngnormal.\",\n    \"operands\": [\n      { \"name\": \"mu\", \"type\": \"HLO_FpTensor\" },\n      { \"name\": \"sigma\", \"type\": \"HLO_FpTensor\" },\n      { \"name\": \"shape\", \"type\": \"HLO_DimensionTensor\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.rng_uniform\",\n    \"summary\": \"RNG with uniform distribution.\",\n    \"description\": \"Constructs an output of a given shape with random numbers generated\\n    following the uniform distribution over the interval `[a,b)`. The parameters\\n    and output element type have to be a boolean type, an integral type or a\\n    floating point types, and the types have to be consistent.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#rnguniform.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"HLO_PredIntOrFpTensor\" },\n      { \"name\": \"b\", \"type\": \"HLO_PredIntOrFpTensor\" },\n      { \"name\": \"shape\", \"type\": \"HLO_DimensionTensor\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.round_nearest_afz\",\n    \"summary\": \"Round operation\",\n    \"description\": \"Performs element-wise rounding towards the nearest integer, breaking ties\\n    away from zero, on the `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#round_nearest_afz\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.round_nearest_afz %operand : tensor<5xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.round_nearest_even\",\n    \"summary\": \"RoundNearestEven operation\",\n    \"description\": \"Performs element-wise rounding towards the nearest integer, breaking ties\\n    towards the even integer, on the `operand` tensor and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#round_nearest_even\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.round_nearest_even %operand : tensor<5xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.rsqrt\",\n    \"summary\": \"Rsqrt operation\",\n    \"description\": \"Performs element-wise reciprocal square root operation on `operand` tensor\\n    and produces a `result` tensor, implementing the `rSqrt` operation from the\\n    IEEE-754 specification.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#rsqrt\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.rsqrt %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.scan\",\n    \"summary\": \"Scan operation\",\n    \"description\": \"Applies a reduction function `body` to `inputs` and `inits` along the\\n    `dimension` and produces `results` (comprising `outputs` and `carries`).\\n\\n    If `is_reverse` is true, the scan is performed in reverse order.\\n    `is_associative` indicates whether the reduction function is associative.\\n\\n    See: https://www.tensorflow.org/xla/operation_semantics#scan\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"carries\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"is_associative\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mhlo.scatter\",\n    \"summary\": \"Scatter operation\",\n    \"description\": \"Produces `results` tensors which are equal to `inputs` tensors except that\\n    several slices specified by `scatter_indices` are updated with the values\\n    `updates` using `update_computation`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#scatter\\n\\n   Example:\\n   ```mlir\\n   %result = \\\"mhlo.scatter\\\"(%input, %scatter_indices, %update) ({\\n     ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n       %0 = mhlo.add %arg0, %arg1 : tensor<i32>\\n       mhlo.return %0 : tensor<i32>\\n   }) {\\n     scatter_dimension_numbers = #mhlo.scatter<\\n       update_window_dims = [3, 4],\\n       inserted_window_dims = [1],\\n       input_batching_dims = [0],\\n       scatter_indices_batching_dims = [1],\\n       scatter_dims_to_operand_dims = [2, 1],\\n       index_vector_dim = 3>,\\n     indices_are_sorted = false,\\n     unique_indices = false\\n   } : (tensor<2x3x4x2xi64>, tensor<2x2x3x2xi64>, tensor<2x2x3x2x2xi64>) -> tensor<2x3x4x2xi64>\\n   ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"scatter_indices\", \"type\": \"RankedTensorOf<[AnyInteger, Index]>\" },\n      { \"name\": \"updates\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dimension_numbers\", \"type\": \"MHLO_ScatterDimensionNumbers\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"unique_indices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"update_computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.select\",\n    \"summary\": \"Select operation\",\n    \"description\": \"Produces a `result` tensor where each element is selected from `on_true` or\\n    `on_false` tensor based on the value of the corresponding element of `pred`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#select\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.select %pred, %on_true, %on_false : tensor<2x2xi1>, tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"MHLO_PredTensor\" },\n      { \"name\": \"on_true\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"on_false\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:`\\n      custom<SelectOpType>(type($pred), type($on_true), type($on_false), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.select_and_scatter\",\n    \"summary\": \"SelectAndScatter operation\",\n    \"description\": \"Scatters the values from the `source` tensor using `scatter` based on the\\n    outcome of `reduce_window` of the `input` tensor using `select` and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#select_and_scatter\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.select_and_scatter\\\"(%operand, %source, %init_value) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"mhlo.compare\\\"(%arg0, %arg1) {\\n          comparison_direction = #stablehlo<comparison_direction GE>\\n        } : (tensor<i32>, tensor<i32>) -> tensor<i1>\\n        \\\"mhlo.return\\\"(%0) : (tensor<i1>) -> ()\\n    }, {\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"mhlo.add\\\"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>\\n        \\\"mhlo.return\\\"(%0) : (tensor<i32>) -> ()\\n    }) {\\n      window_dimensions = dense<[3, 1]> : tensor<2xi64>,\\n      window_strides = dense<[2, 1]> : tensor<2xi64>,\\n      padding = dense<[[0, 1], [0, 0]]> : tensor<2x2xi64>\\n    } : (tensor<4x2xi32>, tensor<2x2xi32>, tensor<i32>) -> tensor<4x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"source\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"init_value\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"select\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"scatter\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.send\",\n    \"summary\": \"Send operation\",\n    \"description\": \"Sends `inputs` to a channel `channel_id` and produces a `result` token.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#send\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.send\\\"(%operand, %token) {\\n      // channel_id = 5 : i64,\\n      // channel_type = #stablehlo<channel_type DEVICE_TO_DEVICE>,\\n      channel_handle = #mhlo.channel_handle<handle = 5, type = 1>,\\n      is_host_transfer = false,\\n      source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>\\n    } : (tensor<3x4xi32>, !mhlo.token) -> !mhlo.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" },\n      { \"name\": \"token\", \"type\": \"MHLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Token\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_handle\", \"type\": \"MHLO_ChannelHandle\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.set_dimension_size\",\n    \"summary\": \"SetDimensionSize operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/8.\\n\\n    Informally, this operation does the same thing as XLA's SetDimensionSize:\\n    https://www.tensorflow.org/xla/operation_semantics#setdimensionsize\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.set_dimension_size %arg0, %arg1, dim = 1 : (tensor<4x2xf32>, tensor<i32>) -> tensor<4x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"size\", \"type\": \"I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.shift_left\",\n    \"summary\": \"ShiftLeft operation\",\n    \"description\": \"Performs element-wise left-shift operation on the `lhs` tensor by `rhs`\\n    number of bits and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#shift_left\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.shift_left %lhs, %rhs : tensor<6xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.shift_right_arithmetic\",\n    \"summary\": \"ShiftRightArithmetic operation\",\n    \"description\": \"Performs element-wise arithmetic right-shift operation on the `lhs` tensor\\n    by `rhs` number of bits and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#shift_right_arithmetic\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.shift_right_arithmetic %lhs, %rhs : tensor<6xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.shift_right_logical\",\n    \"summary\": \"ShiftRightLogical operation\",\n    \"description\": \"Performs element-wise logical right-shift operation on the `lhs` tensor by\\n    `rhs` number of bits and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#shift_right_logical\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.shift_right_logical %lhs, %rhs : tensor<6xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.sign\",\n    \"summary\": \"Sign operation\",\n    \"description\": \"Returns the sign of the `operand` element-wise and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sign\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.sign %operand : tensor<7xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[ MHLO_SInt, MHLO_Float, MHLO_Complex, HLO_QuantizedInt ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[ MHLO_SInt, MHLO_Float, MHLO_Complex, HLO_QuantizedInt ]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.sine\",\n    \"summary\": \"Sine operation\",\n    \"description\": \"Performs element-wise sine operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sine\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.sine %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.sinh\",\n    \"summary\": \"Sinh operation\",\n    \"description\": \"Performs element-wise sinh operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.sinh %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_AnyFpOrComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.slice\",\n    \"summary\": \"Slice operation\",\n    \"description\": \"Extracts a slice from the `operand` using statically-computed starting\\n    indices and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#slice\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.slice\\\" (%operand) {\\n      start_indices = dense<[1, 2]> : tensor<2xi64>,\\n      limit_indices = dense<[3, 4]> : tensor<2xi64>,\\n      strides = dense<1> : tensor<2xi64>\\n    } : (tensor<3x4xi64>) -> tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start_indices\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"limit_indices\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"strides\", \"type\": \"I64ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['start_indices', 'limit_indices', 'strides']>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.sort\",\n    \"summary\": \"Sort operation\",\n    \"description\": \"Sorts a variadic number of tensors in `inputs` together, according to a\\n    custom `comparator`, along the given `dimension` and produces a variadic\\n    number of tensors as `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sort\\n\\n    Example:\\n    ```mlir\\n    %result0, %result1 = \\\"mhlo.sort\\\"(%input0, %input1) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>):\\n        %predicate = \\\"mhlo.compare\\\"(%arg0, %arg1) {\\n          comparison_direction = #stablehlo<comparison_direction GT>\\n          } : (tensor<i32>, tensor<i32>) -> tensor<i1>\\n        \\\"mhlo.return\\\"(%predicate) : (tensor<i1>) -> ()\\n    }) {\\n      dimension = 0 : i64,\\n      is_stable = true\\n    } : (tensor<2x3xi32>, tensor<2x3xi32>) -> (tensor<2x3xi32>, tensor<2x3xi32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"is_stable\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"comparator\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.sqrt\",\n    \"summary\": \"Sqrt operation\",\n    \"description\": \"Performs element-wise square root operation on `operand` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sqrt\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.sqrt %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.stochastic_convert\",\n    \"summary\": \"StochasticConvert operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/295.\\n\\n    Informally, this operation performs element-wise conversion of values from\\n    a bigger type to a smaller one with stochastic rounding using the random\\n    number passed in.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpTensor\" },\n      { \"name\": \"random\", \"type\": \"RankedTensorOf<[MHLO_UInt]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.subtract\",\n    \"summary\": \"Subtract operation\",\n    \"description\": \"Performs element-wise subtraction of two tensors `lhs` and `rhs` and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#subtract\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.subtract %lhs, %rhs : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.tan\",\n    \"summary\": \"Tan operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the specification: https://github.com/openxla/stablehlo/issues/954.\\n\\n    Informally, this operation returns `Tan(operand)` element-wise.\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.tan %arg0 : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.tanh\",\n    \"summary\": \"Tanh operation\",\n    \"description\": \"Performs element-wise hyperbolic tangent operation on `operand` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#tanh\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.tanh %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<MHLO_ResultAccuracyAttr, ::mlir::mhlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.topk\",\n    \"summary\": \"TopK operation\",\n    \"description\": \"Returns top `k` values and their indices, along the last\\n    dimension of the operand if `largest=true` or the bottom `k` values if\\n    `largest=false`.\\n\\n    See:\\n    https://www.tensorflow.org/xla/operation_semantics#top-k\\n\\n    Example:\\n    ```mlir\\n    %values, %indices = mhlo.topk(%operand, k=5, largest=true)\\n      : tensor<100xf32> -> (tensor<5xf32>, tensor<5xi32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I64Attr\" },\n      { \"name\": \"largest\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ],\n    \"assemblyFormat\": \"`(`$operand `,` `k` `=` $k (`,` `largest` `=` $largest^)? `)` attr-dict `:`\\n    type($operand) `->` `(`type($values)`,` type($indices)`)`\"\n  },\n  {\n    \"name\": \"mhlo.torch_index_select\",\n    \"summary\": \"TorchIndexSelect operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as PyTorch's index_select,\\n    augmented with support for batch dimensions:\\n    https://pytorch.org/docs/stable/generated/torch.index_select.html.\\n\\n    The `batch_dims` attribute specifies the number of major batch dimensions\\n    (0 or more) that act like a multidimensional loop over both the operand and\\n    the index.\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.torch_index_select\\\"(%operand, %index) {\\n      dim = 2 : i64,\\n      batch_dims = 1 : i64\\n    } : (tensor<8x128x3072x64xf32>, tensor<8x16x1024xi32>) -> tensor<8x128x16x1024x64xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" },\n      { \"name\": \"index\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"batch_dims\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.trace\",\n    \"summary\": \"Trace operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the specification: https://github.com/openxla/stablehlo/issues/604.\\n\\n    It is not used by JAX, PyTorch or TensorFlow, so it looks like we should've\\n    classified it as \\\"Private to XLA\\\" and not included it in StableHLO in the\\n    first place. With that in mind, its semantics will not be documented here.\\n\\n    Example:\\n    ```mlir\\n    mhlo.trace %arg0, \\\"In test code.\\\" : tensor<5x1x5xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $tag attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"mhlo.transpose\",\n    \"summary\": \"Transpose operation\",\n    \"description\": \"Permutes the dimensions of `operand` tensor using `permutation` and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#transpose\\n\\n    Example:\\n    ```mlir\\n    %0 = mhlo.transpose %arg0, dims = [2, 1, 0] : (tensor<1x2x3xi32>) -> tensor<3x2x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.triangular_solve\",\n    \"summary\": \"TriangularSolve operation\",\n    \"description\": \"Solves batches of systems of linear equations with lower or upper triangular\\n    coefficient matrices.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#triangular_solve\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"mhlo.triangular_solve\\\"(%a, %b) {\\n      left_side = true,\\n      lower = true,\\n      unit_diagonal = false,\\n      transpose_a = #stablehlo<transpose NO_TRANSPOSE>\\n    } : (tensor<3x3xf32>, tensor<3x3xf32>) -> tensor<3x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MHLO_FpOrComplexTensor\" },\n      { \"name\": \"b\", \"type\": \"MHLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpOrComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_side\", \"type\": \"BoolAttr\" },\n      { \"name\": \"lower\", \"type\": \"BoolAttr\" },\n      { \"name\": \"unit_diagonal\", \"type\": \"BoolAttr\" },\n      { \"name\": \"transpose_a\", \"type\": \"MHLO_TransposeAttr{TRANSPOSE_INVALID|NO_TRANSPOSE|TRANSPOSE|ADJOINT}\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.tuple\",\n    \"summary\": \"Tuple operation\",\n    \"description\": \"Produces a `result` tuple from values `val`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#tuple\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.tuple %val0, %val1 : tuple<tensor<2xf32>, tuple<tensor<i32>>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"Variadic<MHLO_TensorOrTokenOrTupleOrBuffer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tuple\" }\n    ],\n    \"assemblyFormat\": \"$val attr-dict `:` custom<TupleOpType>(type($val), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.unary_einsum\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"einsum_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"mhlo.uniform_dequantize\",\n    \"summary\": \"UniformDequantize operation\",\n    \"description\": \"Performs element-wise conversion of quantized tensor `operand` to a\\n    floating-point tensor `result` according to the quantization parameters\\n    defined by the `operand` type.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#uniform_dequantize\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.uniform_dequantize %operand : (tensor<16x16x!quant.uniform<i8:f32, 34.0:16>>) -> tensor<16x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"MHLO_QuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.uniform_quantize\",\n    \"summary\": \"UniformQuantize operation\",\n    \"description\": \"Performs element-wise conversion of floating-point tensor or quantized\\n    tensor `operand` to a quantized tensor `result` according to the\\n    quantization parameters defined by the `result` type.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#uniform_quantize\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.uniform_quantize %operand : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[ MHLO_Float, MHLO_QuantizedInt ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_QuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"mhlo.while\",\n    \"summary\": \"While operation\",\n    \"description\": \"Produces the output from executing `body` function 0 or more times while the\\n    `cond` function outputs `true`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#while\\n\\n    Example:\\n    ```mlir\\n    %results0, %results1 = \\\"mhlo.while\\\"(%operand0, %operand1) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"mhlo.compare\\\"(%arg0, %arg1) {\\n          comparison_direction = #stablehlo<comparison_direction LT>\\n        } : (tensor<i32>, tensor<i32>) -> tensor<i1>\\n        \\\"mhlo.return\\\"(%0) : (tensor<i1>) -> ()\\n    }, {\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"mhlo.add\\\"(%arg0, %constant0) : (tensor<i32>, tensor<i32>) -> tensor<i32>\\n        \\\"mhlo.return\\\"(%0, %arg1) : (tensor<i32>, tensor<i32>) -> ()\\n    }) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<MHLO_TensorOrTokenOrBuffer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MHLO_TensorOrTokenOrBuffer>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mhlo.xla.rng_get_and_update_state\",\n    \"summary\": \"XlaRngGetAndUpdateState operation\",\n    \"description\": \"This operation is private to the XLA compiler, so it is does not yet have\\n    a specification.\\n\\n    Informally, this operation represents the change of the global random number\\n    generator state for rng instructions. The global state is incremented by\\n    delta and the old state is returned.\\n\\n    The output is currently defined for a single output type. If this changes in\\n    the future to support multiple types, lowering to use of a global memref\\n    must ensure that a single memref is still used and updated appropriately.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"StaticShapeTensorOf<[UI64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"delta\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"mhlo.xor\",\n    \"summary\": \"Xor operation\",\n    \"description\": \"Performs element-wise XOR of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#xor\\n\\n    Example:\\n    ```mlir\\n    %result = mhlo.xor %lhs, %rhs : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"MHLO_PredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"MHLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MHLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"michelson.get_amount\",\n    \"summary\": \"Get the amount of the current transaction.\",\n    \"description\": \"The `michelson.get_amount` operation returns the amount of the current transaction.\\n\\n        Example:\\n        ```mlir\\n        %0 = michelson.get_amount() : !michelson.mutez\\n        ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"MichelsonMutez\" }\n    ]\n  },\n  {\n    \"name\": \"migraphx.abs\",\n    \"summary\": \"Elementwise abs\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.add\",\n    \"summary\": \"Elementwise add of two shaped values with broadcast\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.backwards_data_convolution\",\n    \"summary\": \"Backwards data convolution\",\n    \"description\": \"The `migraphx.backwards_data_convolution` op computes a transposed\\n    convolution op which effectively reverses a standard convolution's\\n    spatial transformation. It is an upsampling technique that increases\\n    the height and width of an input feature map.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"MIXRShapedOf<[F32, F16, BF16]>\" },\n      { \"name\": \"filter\", \"type\": \"MIXRShapedOf<[F32, F16, BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<[F32, F16, BF16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilation\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"perf_config\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$input `,` $filter attr-dict\\n      `:` type($input) `,` type($filter) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.batch_norm_inference\",\n    \"summary\": \"batch_norm_inference\",\n    \"description\": \"The `migraphx.batch_norm_inference` op computes batch_norm.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"a\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"b\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"c\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"d\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"momentum\", \"type\": \"F32Attr\" },\n      { \"name\": \"bn_mode\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type(operands) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.broadcast\",\n    \"summary\": \"Broadcast tensor\",\n    \"description\": \"The `migraphx.broadcast` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"out_lens\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.ceil\",\n    \"summary\": \"Elementwise ceil\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.clip\",\n    \"summary\": \"Elementwise clip\",\n    \"description\": \"Elementwise clip: output = min(max(x, minVals), maxVals)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"minVals\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"maxVals\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $minVals `,` $maxVals attr-dict\\n    `:` type($x) `,` type($minVals) `,` type($maxVals) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.code_object\",\n    \"summary\": \"OP representing a code object\",\n    \"description\": \"The `migraphx.code_object` op. Holds the compiled kernel binary and arguments.\",\n    \"operands\": [\n      { \"name\": \"kernelArgs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"globalSize\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"localSize\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `(`$kernelArgs`)` `:` `(`type($kernelArgs)`)` `->` type($outputs)\"\n  },\n  {\n    \"name\": \"migraphx.convert\",\n    \"summary\": \"Elementwise type conversion\",\n    \"description\": \"Type conversion. Due to impedance mismatches between MIGraphX and Tosa,\\n    currently only supports float to float conversions\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `to` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.convolution\",\n    \"summary\": \"convolution forward\",\n    \"description\": \"The `migraphx.convolution` op computes convolution forward.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"MIXRShapedOf<[F32, F16, BF16, F8E4M3FNUZ, F8E5M2FNUZ, F8E5M2, F8E4M3FN]>\" },\n      { \"name\": \"filter\", \"type\": \"MIXRShapedOf<[F32, F16, BF16, F8E4M3FNUZ, F8E5M2FNUZ, F8E5M2, F8E4M3FN]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<[F32, F16, BF16, F8E4M3FNUZ, F8E5M2FNUZ, F8E5M2, F8E4M3FN]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilation\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"perf_config\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$input `,` $filter attr-dict\\n      `:` type($input) `,` type($filter) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.dequantizelinear\",\n    \"summary\": \"Channelwise dequantization\",\n    \"description\": \"De-Quantization tensor channelwise. It computes the following:\\n    tensor[n,c,h,w] = to_float(tensor[n,c,h,w] - quantBias[c]) * quantScale[c]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"MIXRShapedOf<[AnyInteger, AnyFloat]>\" },\n      { \"name\": \"scale\", \"type\": \"MIXRShapedOf<[AnyFloat]>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<MIXRShapedOf<[ AnyInteger, AnyFloat ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<[AnyFloat]>\" }\n    ],\n    \"assemblyFormat\": \"$input `,` $scale (`,` $bias^)? attr-dict\\n    `:` type($input) `,` type($scale) (`,` type($bias)^)? `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.div\",\n    \"summary\": \"Elementwise div of two shaped values with broadcast\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.dot\",\n    \"summary\": \"Dot product of tensors\",\n    \"description\": \"The `migraphx.dot` op computes the dot product of two tensors.\",\n    \"operands\": [\n      { \"name\": \"in_a\", \"type\": \"MIXRShapedOf<DotInTypes>\" },\n      { \"name\": \"in_b\", \"type\": \"MIXRShapedOf<DotInTypes>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<DotOutTypes>\" }\n    ],\n    \"assemblyFormat\": \"$in_a `,` $in_b attr-dict `:` type($in_a) `,` type($in_b) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.equal\",\n    \"summary\": \"Elementwise equality comparison\",\n    \"description\": \"Returns the truth value of (input1 == input2) element-wise.\\n\\n    Returns a tensor with the same element type as the inputs (not i1) to\\n    match MIGraphX's IR representation. This allows direct use with\\n    `migraphx.where`, which requires I8/SI8/UI8 condition tensors.\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.erf\",\n    \"summary\": \"Gauss error function\",\n    \"description\": \"compute gauss error function\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.exp\",\n    \"summary\": \"Elementwise exp\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.flatten\",\n    \"summary\": \"Flatten tensor\",\n    \"description\": \"The `migraphx.flatten` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.floor\",\n    \"summary\": \"Elementwise floor\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.greater\",\n    \"summary\": \"Elementwise greater of two shaped values with broadcast\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.literal\",\n    \"summary\": \"MIGraphX literal op\",\n    \"description\": \"A MLIR operation corresponding to MIGraphX's literals.\\n\\n    The provided value should be a tensor containing the bytes of the relevant\\n    literal or a splat tensor. Non-splat tensors must be in standard form.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.log\",\n    \"summary\": \"Elementwise log\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.mlir.as.logical.shape\",\n    \"summary\": \"View an input shaped type as its logical shape\",\n    \"description\": \"Convert a MIXR shaped value to a tensor, ensuring that reads from the tensor\\n    lead to reads from the underlying memory implied by the strides.\\n\\n    In the case of a standard-layout type, this is a noop.\\n\\n    When dealing with non-standard layouts, such as NHWC tensors, this will\\n    lower to `tosa.transpose` and potentially `tosa.slice` and/or a broadcast\\n    by way of `tosa.add`.\\n\\n    Strides that don't neatly form a (padded) rectangle, that is, cases where\\n    (ignoring broadcasted dimensions), you can't permute the nonzero strides into\\n    [s1, ..., sL] such that sL is 1 and sK = prod_(i = K + 1)^L s_i with\\n    and sK >= prod_(i = K + 1)^L size_i , are unsupported\\n\\n    Equivalently, you have to be able to create a tensor type that you can then\\n    `tosa.transpose`, `tosa.slice`, and then potentially broadcast to get the\\n    logical shape, otherwise we can't easily evaluate the correctness of kernels\\n    during testing.\\n\\n    That is, unpacked shapes like !mixr.shaped<3x2xf32, 2x6> are unsupported.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"migraphx.mlir.as.underlying.shape\",\n    \"summary\": \"View a logical tensor as its underlying shape in memory\",\n    \"description\": \"Convert a tensor to a MIXR shaped type, such that writes to it (after\\n    bufferization) lead to the memory locations indicated by the strides in\\n    the underlying shaped type.\\n\\n    In the case of a standard-layout type, this is a noop.\\n\\n    When dealing with non-standard layouts, such as NHWC tensors, this will\\n    lower to tosa.transpose.\\n\\n    Currently, the operation must be implementable as `tosa.transpose`, that is,\\n    the strides of the underlying memory must be a permutation of the strides\\n    that would be used if the type were in standard form. That is, types like\\n    `!migraphx.shaped<3x2xf32, 4x1>` or `!migraphx.shaped<3x2xf32, 2x6>` are\\n    unsupported.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `to` type($out)\"\n  },\n  {\n    \"name\": \"migraphx.mul\",\n    \"summary\": \"Elementwise mul of two shaped values with broadcast\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.multibroadcast\",\n    \"summary\": \"Broadcast tensor in multiple dimensions\",\n    \"description\": \"The `migraphx.multibroadcast` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"out_lens\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.neg\",\n    \"summary\": \"Elementwise neg\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.pad\",\n    \"summary\": \"Pad operation\",\n    \"description\": \"The `migraphx.pad` op adds padding to the tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"F32Attr\" },\n      { \"name\": \"mode\", \"type\": \"PadOpModeAttr{constant_pad|reflect_pad|edge_pad}\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.pooling\",\n    \"summary\": \"Pooling operation\",\n    \"description\": \"The `migraphx.pooling` op computes average/max pooling op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"length\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.pow\",\n    \"summary\": \"Elementwise pow of two shaped values with broadcast\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.quant_convolution\",\n    \"summary\": \"quantized convolution forward\",\n    \"description\": \"The `migraphx.quant_convolution` op computes quantized convolution forward.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"MIXRShapedOf<[F8E4M3FNUZ, F8E5M2FNUZ, F8E5M2, F8E4M3FN, I8, SI8]>\" },\n      { \"name\": \"filter\", \"type\": \"MIXRShapedOf<[F8E4M3FNUZ, F8E5M2FNUZ, F8E5M2, F8E4M3FN, I8, SI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<[F32, I32, SI32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilation\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"perf_config\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$input `,` $filter attr-dict\\n      `:` type($input) `,` type($filter) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.quant_dot\",\n    \"summary\": \"Dot product of quantized tensors\",\n    \"description\": \"The `migraphx.quant_dot` op computes the dot product of two tensors. This operation is used when converting MIGraphX IR's quant_dot operation to MIGraphX Dialect. \\n    Usually `migraphx.quant_dot` operations have QuantizeLinear and DequantizeLinear operations to convert data types from higher precision to lower precision.  \\n    `migraphx.quant_dot` operation is also used for \\\"scaled\\\" GEMMs.\",\n    \"operands\": [\n      { \"name\": \"in_a\", \"type\": \"MIXRShapedOf<QuantDotInTypes>\" },\n      { \"name\": \"in_b\", \"type\": \"MIXRShapedOf<QuantDotInTypes>\" },\n      { \"name\": \"scaleA\", \"type\": \"Optional<MIXRShapedOf<QuantDotScaleTypes>>\" },\n      { \"name\": \"scaleB\", \"type\": \"Optional<MIXRShapedOf<QuantDotScaleTypes>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<QuantDotOutTypes>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$in_a (`scaled` `by` $scaleA^)? `,` $in_b (`scaled` `by` $scaleB^)? attr-dict\\n    `:` type($in_a) (`scaled` `by` type($scaleA)^)? `,` type($in_b)\\n        (`scaled` `by` type($scaleB)^)?\\n    `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.quantizelinear\",\n    \"summary\": \"Channelwise quantization\",\n    \"description\": \"Quantization tensor channelwise. It computes the following:\\n    tensor[n,c,h,w] = clamping_truncate(round(tensor[n,c,h,w] / quantScale[c]) + quantBias[c])\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"MIXRShapedOf<[AnyFloat]>\" },\n      { \"name\": \"scale\", \"type\": \"MIXRShapedOf<[AnyFloat]>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<MIXRShapedOf<[ AnyInteger, AnyFloat ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"MIXRShapedOf<[AnyInteger, AnyFloat]>\" }\n    ],\n    \"assemblyFormat\": \"$input `,` $scale (`,` $bias^)? attr-dict\\n    `:` type($input) `,` type($scale) (`,` type($bias)^)? `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.recip\",\n    \"summary\": \"Elementwise recip\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.reduce_max\",\n    \"summary\": \"Get the max of the values in given axis\",\n    \"description\": \"The `migraphx.reduce_max` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.reduce_mean\",\n    \"summary\": \"Get the mean of the values in given axis\",\n    \"description\": \"The `migraphx.reduce_mean` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.reduce_sum\",\n    \"summary\": \"Get the sum of the values in given axis\",\n    \"description\": \"The `migraphx.reduce_sum` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.relu\",\n    \"summary\": \"Elementwise relu\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.reshape\",\n    \"summary\": \"reshape a tensor\",\n    \"description\": \"The `migraphx.reshape` op.\\n\\n    `dims` can contain values of -1 and 0. A value of -1 means to infer this \\n    dimension from the others. i.e., If we have an output shape of\\n    `<4x2xf32, 0x1>` and the dims are `[4, -1]`, then the second dimension will\\n    be inferred to be 2. A value of 0 means explicit zero-length dimension.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.rsqrt\",\n    \"summary\": \"Elementwise rsqrt\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.sigmoid\",\n    \"summary\": \"Elementwise sigmoid\",\n    \"description\": \"Sigmoid function, aka 1 / (1 + exp(-x)).\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.slice\",\n    \"summary\": \"slice a tensor\",\n    \"description\": \"The `migraphx.slice` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ends\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"starts\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.softmax\",\n    \"summary\": \"softmax operation\",\n    \"description\": \"The `migraphx.softmax` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.sqrt\",\n    \"summary\": \"Elementwise sqrt\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.sub\",\n    \"summary\": \"Elementwise sub of two shaped values with broadcast\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA `,` $inB attr-dict\\n    `:` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.tanh\",\n    \"summary\": \"Elementwise tanh\",\n    \"operands\": [\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$inA attr-dict `:` type($inA) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.transpose\",\n    \"summary\": \"transpose dimensions\",\n    \"description\": \"The `migraphx.transpose` op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"migraphx.unpack\",\n    \"summary\": \"Unpack int4 vaules stored as bytes\",\n    \"description\": \"Given a shaped tensor of bytes, double the length of `axis` by\\n    ```\\n    out[..., 2*i, ...] = in[..., i, ...] & 0xf\\n    out[..., 2*i + 1, ...] = in[ ..., i, ...] >>[unsigned] 4\\n    ```\\n\\n    That is, the `axis` dimension of `in` consists of, in MLIR terms,\\n    `vector<2xi4>`, which we then turn into `vector<2xi8>` by zero-extension\\n    and then we flatten out the elements back into `axis`.\\n\\n    To enable MLIR rewrites, this can also take a tensor of i4 and return\\n    the corresponding tensor of i8 (in which case, the `i4` are exposed as an\\n    extra dimension and not flattened) or another tensor of i4. This allows us to\\n    progressively move unpack up to function boundaries.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"MIXRShapedOf<[I8, UI8, SI8, I<4>, SI<4>, UI<4>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"MIXRShapedOf<[I8, UI8, SI8, I<4>, SI<4>, UI<4>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` type($in) `->` type($out)\"\n  },\n  {\n    \"name\": \"migraphx.where\",\n    \"summary\": \"Elementwise select\",\n    \"description\": \"output[x] = cond[x] ? inA[x] : inB[x]\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"MIXRShapedOf<[I8, SI8, UI8]>\" },\n      { \"name\": \"inA\", \"type\": \"AnyMIXRShaped\" },\n      { \"name\": \"inB\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyMIXRShaped\" }\n    ],\n    \"assemblyFormat\": \"$cond `,` $inA `,` $inB attr-dict\\n    `:` type($cond) `,` type($inA) `,` type($inB) `->` type($output)\"\n  },\n  {\n    \"name\": \"ml_program.func\",\n    \"summary\": \"Function containing a single `SSACFG` region\",\n    \"description\": \"This simple function container represents callables in an ML program where\\n    the body is an `SSACFG` region. It must be terminated by a `return` op which\\n    yields values with the same arity and types as the `FunctionType` results\\n    of the containing `func`.\\n\\n    This op is a `Symbol` but does not introduce a new `SymbolTable`. As such,\\n    it cannot represent nested symbols.\\n\\n    Example:\\n\\n    ```mlir\\n    ml_program.func private @some_extern(i32) -> i32\\n    ml_program.func @compute(%arg0 : i32) -> i32 {\\n      ml_program.return %arg0 : i32\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"ml_program.global\",\n    \"summary\": \"Module level declaration of a global variable\",\n    \"description\": \"Declares a named global variable (or constant).\\n\\n    A global contains a value of a specified type which can be accessed at\\n    runtime via appropriate load/store operations. It can be mutable or\\n    constant, optionally taking an initial value or declared as\\n    extern (in which case, the initial value is found in external storage\\n    by symbol name).\\n\\n    Generally, the type of the global and the type of the initial value\\n    will be the same. However, for type hierarchies which can have a more\\n    generalized bounding type that can be assigned from a narrow type, this\\n    is allowed (but not verified).\\n\\n    Examples:\\n\\n    ```mlir\\n    // Constant global.\\n    ml_program.global @foobar(dense<4> : tensor<4xi32>) : tensor<?xi32>\\n\\n    // Constant with external linkage.\\n    ml_program.global mutable @foobar(#ml_program.extern<tensor<4xi32>>)\\n      : tensor<?xi32>\\n\\n    // Mutable global with an undefined initial value.\\n    ml_program.global mutable @foobar : tensor<?xi32>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name ``\\n    custom<TypedInitialValue>($type, $value)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"ml_program.global_load\",\n    \"summary\": \"Direct load of a mutable value from a global\",\n    \"description\": \"Performs a non-atomic, non-volatile, non-synchronized load from a global\\n    that may be mutable.\\n\\n    It is fully expected that these constraints are not suitable for\\n    all situations, and alternative ops should be defined and used for more\\n    advanced cases.\\n\\n    This op is side effecting and may not be valid to use in graph regions\\n    without additional consideration to evaluation order constraints. See\\n    `global_load_graph` for op which allows for explicit ordering constraints.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = ml_program.global_load @foobar : tensor<?xi32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"ml_program.global_load_const\",\n    \"summary\": \"Direct load a constant value from a global\",\n    \"description\": \"Loads a constant (immutable) value from a global directly by symbol.\\n\\n    This op is only legal for globals that are not mutable and exists because\\n    such a load can be considered to have no side effects.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = ml_program.global_load_const @foobar : tensor<?xi32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"ml_program.global_load_graph\",\n    \"summary\": \"Direct load of a mutable value from a global in Graph region\",\n    \"description\": \"Performs a non-atomic, non-volatile, non-synchronized load from a global\\n    that may be mutable.\\n\\n    It is fully expected that these constraints are not suitable for all\\n    situations, and alternative ops should be defined and used for more advanced\\n    cases.\\n\\n    This op is side effecting and may not be valid to use in graph regions\\n    without additional consideration to evaluation order constraints.\\n\\n    Example:\\n\\n    ```mlir\\n    %0, %cstr = ml_program.global_load_graph @foobar\\n      ordering (%token -> !ml_program.token) : tensor<?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"consumeTokens\", \"type\": \"Variadic<MLProgram_TokenType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" },\n      { \"name\": \"produceToken\", \"type\": \"MLProgram_TokenType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global `` custom<TokenOrdering>($consumeTokens, type($produceToken)) `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"ml_program.global_store\",\n    \"summary\": \"Direct store of a value into a mutable global\",\n    \"description\": \"Performs a non-atomic, non-volatile, non-synchronized store to a mutable\\n    global.\\n\\n    It is fully expected that these constraints are not suitable for\\n    all situations, and alternative ops should be defined and used for more\\n    advanced cases.\\n\\n    This op is side effecting and may not be valid to use in graph regions\\n    without additional consideration to evaluation order constraints. See\\n    `global_store_graph` for op which allows for explicit ordering constraints.\\n\\n    Example:\\n\\n    ```mlir\\n    ml_program.global_store @foobar = %0 : tensor<?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global `=` $value `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"ml_program.global_store_graph\",\n    \"summary\": \"Direct store of a value into a mutable global\",\n    \"description\": \"Performs a non-atomic, non-volatile, non-synchronized store to a mutable\\n    global.\\n\\n    It is fully expected that these constraints are not suitable for\\n    all situations, and alternative ops should be defined and used for more\\n    advanced cases.\\n\\n    This op is side effecting and may not be valid to use in graph regions\\n    without additional consideration to evaluation order constraints.\\n\\n    Example:\\n\\n    ```mlir\\n    %token = ml_program.global_store @foobar = %0 : tensor<?xi32>\\n      ordering (%in_token -> !ml_program.token) : tensor<?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"consumeTokens\", \"type\": \"Variadic<MLProgram_TokenType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"produceToken\", \"type\": \"MLProgram_TokenType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global `=` $value `` custom<TokenOrdering>($consumeTokens, type($produceToken)) `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"ml_program.output\",\n    \"summary\": \"Outputs values from a subgraph function\",\n    \"description\": \"The `output` operation terminates a subgraph by yielding values\\n    to the caller.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number and types must match the signature of the function\\n    that contains the operation.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"ml_program.return\",\n    \"summary\": \"Returns values from a `func` function\",\n    \"description\": \"The `return` operation terminates a `func` function by yielding values\\n    to the caller.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number and types must match the signature of the function\\n    that contains the operation.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"ml_program.subgraph\",\n    \"summary\": \"An function containing a single `Graph` region\",\n    \"description\": \"This simple function container represents callables in an ML program where\\n    the body is a `Graph` region containing a single block. It must be\\n    terminated by an `output` op which yields values with the same arity and\\n    types as the `FunctionType` results of the containing `subgraph`.\\n\\n    This op is a `Symbol` but does not introduce a new `SymbolTable`. As such,\\n    it cannot represented nested symbols.\\n\\n    Example:\\n\\n    ```mlir\\n    ml_program.subgraph private @some_extern(i32) -> i32\\n    ml_program.subgraph @compute(%arg0 : i32) -> i32 {\\n      ml_program.output %arg0 : i32\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"ml_program.token\",\n    \"summary\": \"Produces a new token value\",\n    \"description\": \"Token values are used to chain side effecting ops in a graph so as to\\n    establish an execution order. This op produces a token.\",\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"MLProgram_TokenType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"mlrt.allocate_control_futures\",\n    \"summary\": \"Allocate futures and corresponding promises\",\n    \"description\": \"Allocate futures and corresponding promises.\\n\\n    $num: The number of futures to be allocated.\\n\\n    $promises: There are $num promises, and promises[i] shares the state with futures[i].\\n    $futures: There are $num futures, and futures[i] shares the state with promises[i].\",\n    \"results\": [\n      { \"name\": \"promises\", \"type\": \"Variadic<MlrtPromiseType>\" },\n      { \"name\": \"futures\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"mlrt.async\",\n    \"summary\": \"Launches a function asynchronously.\",\n    \"description\": \"Launch a function asynchronously.\\n\\n    $args: a list of arguments to be passed.\\n    $callee: The function to be launched. Its return op must not have operands.\\n\\n    $handle: This op returns a handle object that manages the context of the async execution.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"MlrtAsyncHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` attr-dict `:` functional-type($args, $handle)\"\n  },\n  {\n    \"name\": \"mlrt.await_all_control\",\n    \"summary\": \"Awaits multiple signals\",\n    \"description\": \"Awaits multiple signals\\n\\n    $futures: A list of !mlrt.futures\",\n    \"operands\": [\n      { \"name\": \"futures\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($futures)\"\n  },\n  {\n    \"name\": \"mlrt.await_all_handle\",\n    \"summary\": \"Awaits multiple async executions\",\n    \"description\": \"Awaits multiple async execution.\\n\\n    $handles: A list of handles returned by mlrt.async ops.\",\n    \"operands\": [\n      { \"name\": \"handles\", \"type\": \"Variadic<MlrtAsyncHandleType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($handles)\"\n  },\n  {\n    \"name\": \"mlrt.await_control\",\n    \"summary\": \"Await a signal from a future\",\n    \"description\": \"Await a signal, instead of a value, from a future.\\n\\n    $future: A value of !mlrt.future type.\",\n    \"operands\": [\n      { \"name\": \"future\", \"type\": \"MlrtFutureType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"mlrt.await_handle\",\n    \"summary\": \"Awaits an async execution\",\n    \"description\": \"Awaits an async execution.\\n\\n    $handle: The handle returned by mlrt.async op.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"MlrtAsyncHandleType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"mlrt.case\",\n    \"summary\": \"An n-way switch statement which calls a single branch function.\",\n    \"description\": \"An n-way switch statement, implementing the following:\\n        ```\\n        switch (branch_index) {\\n          case 0:\\n            outputs = branches[0](inputs);\\n            break;\\n          case 1:\\n            outputs = branches[1](inputs);\\n            break;\\n          ...\\n          case [[nbranches-1]]:\\n          default:\\n            outputs = branches[nbranches-1](inputs);\\n            break;\\n        }\\n        ```\\n    Example: %res = mlrt.case %branch_idx [@branch0, @branch1] (%arg0, %arg1) : (i32, i32) -> (i32)\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32\" },\n      { \"name\": \"branch_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"branch_outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branches\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<SymbolRefAttr>, [ArrayMinCount<1>]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$branch_index $branches `(` $branch_operands `)` attr-dict `:` `(` type($branch_operands) `)` `->` `(` type($branch_outputs) `)`\"\n  },\n  {\n    \"name\": \"mlrt.cond\",\n    \"summary\": \"mlrt.cond op\",\n    \"description\": \"Execute $a_true_fn with $args if $cond is true; otherwise, %b_false_fn is\\n    executed.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_true_fn\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"b_false_fn\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$cond $a_true_fn $b_false_fn `(` $args `)` attr-dict `:` `(` type($args) `)` `->` `(` type($results) `)`\"\n  },\n  {\n    \"name\": \"mlrt.promise_control\",\n    \"summary\": \"Set a control promise\",\n    \"description\": \"Set a control promise.\\n\\n    $promise: A value of !mlrt.promise type.\",\n    \"operands\": [\n      { \"name\": \"promise\", \"type\": \"MlrtPromiseType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"mlrt.while\",\n    \"summary\": \"while operation\",\n    \"description\": \"cond: The boolean to control whether the first iteration should be\\n      executed.\\n    operands: The arguments to the first iteration.\\n    results: The results of the last iteration. The number and types of results\\n      excluding the last one are the same as the number and types of operands. The\\n      last element of results is an I1 value that is false.\\n    body_fn: The body function that takes the arguments and returns the results\\n      that includes an I1 value to indicate whether next iteration should be executed.\\n\\n    The pseudo code:\\n\\n    while(cond) {\\n      results = body_fn(operands)\\n      cond = results#1\\n    }\\n    return results\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"body_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$cond $body_fn `(` $arguments `)` attr-dict `:` `(` type($arguments) `)` `->` `(` type(results) `)`\"\n  },\n  {\n    \"name\": \"mpi.allgather\",\n    \"summary\": \"Equivalent to `MPI_Allgather(sendbuf, sendcount, sendtype,\\n                                 recvbuf, recvcount, recvtype,\\n                                 comm)`.\",\n    \"description\": \"MPI_Allgather collects data from all processes in a given communicator and\\n    stores the gathered data in the receive buffer of each process.\\n\\n    Each process contributes the same amount of data defined by `sendbuf`.\\n    The MPI call specifies the number of elements contributed by each process\\n    via the `recvcount` parameter. However, this operation, assumes `recvbuf`\\n    to be sufficiently large to hold the data contributed by all processes.\\n    Therefore, `recvcount` is implicitly defined as\\n    `num_elements(recvbuf) / MPI_Comm_size(comm)`.\\n\\n    This operation may optionally return an !mpi.retval value, which can be\\n    used for error checking.\",\n    \"operands\": [\n      { \"name\": \"sendbuf\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"recvbuf\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"`(` $sendbuf `,` $recvbuf `,` $comm `)` attr-dict `:` type($sendbuf) `,` type($recvbuf) (`->` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.allreduce\",\n    \"summary\": \"Equivalent to `MPI_Allreduce(sendbuf, recvbuf, op, comm)`\",\n    \"description\": \"MPI_Allreduce performs a reduction operation on the values in the sendbuf\\n    array and stores the result in the recvbuf array. The operation is \\n    performed across all processes in the communicator.\\n\\n    The `op` attribute specifies the reduction operation to be performed.\\n    Currently only the `MPI_Op` predefined in the standard (e.g. `MPI_SUM`) are\\n    supported.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"sendbuf\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"recvbuf\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"MPI_ReductionOpEnum{MPI_OP_NULL|MPI_MAX|MPI_MIN|MPI_SUM|MPI_PROD|MPI_LAND|MPI_BAND|MPI_LOR|MPI_BOR|MPI_LXOR|MPI_BXOR|MPI_MINLOC|MPI_MAXLOC|MPI_REPLACE}\" }\n    ],\n    \"assemblyFormat\": \"`(` $sendbuf `,` $recvbuf `,` $op `,` $comm `)` attr-dict `:` type($sendbuf) `,` type($recvbuf) (`->` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.barrier\",\n    \"summary\": \"Equivalent to `MPI_Barrier(comm)`\",\n    \"description\": \"MPI_Barrier blocks execution until all processes in the communicator have\\n    reached this routine.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"`(` $comm `)` attr-dict\\n    (`->` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.comm_rank\",\n    \"summary\": \"Get the current rank, equivalent to `MPI_Comm_rank(comm, &rank)`\",\n    \"description\": \"This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" },\n      { \"name\": \"rank\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $comm `)` attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mpi.comm_size\",\n    \"summary\": \"Get the size of the group associated to the communicator, equivalent to `MPI_Comm_size(comm, &size)`\",\n    \"description\": \"This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" },\n      { \"name\": \"size\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $comm `)` attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mpi.comm_split\",\n    \"summary\": \"Partition the group associated with the given communicator into disjoint subgroups\",\n    \"description\": \"This operation splits the communicator into multiple sub-communicators.\\n    The color value determines the group of processes that will be part of the\\n    new communicator. The key value determines the rank of the calling process\\n    in the new communicator.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" },\n      { \"name\": \"color\", \"type\": \"I32\" },\n      { \"name\": \"key\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" },\n      { \"name\": \"newcomm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"assemblyFormat\": \"`(` $comm `,` $color `,` $key `)` attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mpi.comm_world\",\n    \"summary\": \"Get the World communicator, equivalent to `MPI_COMM_WORLD`\",\n    \"description\": \"This operation returns the predefined MPI_COMM_WORLD communicator.\",\n    \"results\": [\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"mpi.error_class\",\n    \"summary\": \"Get the error class from an error code, equivalent to the `MPI_Error_class` function\",\n    \"description\": \"`MPI_Error_class` maps return values from MPI calls to a set of well-known\\n    MPI error classes.\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"MPI_Retval\" }\n    ],\n    \"results\": [\n      { \"name\": \"errclass\", \"type\": \"MPI_Retval\" }\n    ],\n    \"assemblyFormat\": \"$val attr-dict `:` type($val)\"\n  },\n  {\n    \"name\": \"mpi.finalize\",\n    \"summary\": \"Finalize the MPI library, equivalent to `MPI_Finalize()`\",\n    \"description\": \"This function cleans up the MPI state. Afterwards, no MPI methods may \\n    be invoked (excpet for MPI_Get_version, MPI_Initialized, and MPI_Finalized).\\n    Notably, MPI_Init cannot be called again in the same program.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`:` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.init\",\n    \"summary\": \"Initialize the MPI library, equivalent to `MPI_Init(NULL, NULL)`\",\n    \"description\": \"This operation must preceed most MPI calls (except for very few exceptions,\\n    please consult with the MPI specification on these).\\n\\n    Passing &argc, &argv is not supported currently.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`:` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.irecv\",\n    \"summary\": \"Equivalent to `MPI_Irecv(ptr, size, dtype, source, tag, comm, &req)`\",\n    \"description\": \"MPI_Irecv begins a non-blocking receive of `size` elements of type `dtype` \\n    from rank `source`. The `tag` value and communicator enables the library to\\n    determine the matching of multiple sends and receives between the same \\n    ranks.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tag\", \"type\": \"I32\" },\n      { \"name\": \"source\", \"type\": \"I32\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" },\n      { \"name\": \"req\", \"type\": \"MPI_Request\" }\n    ],\n    \"assemblyFormat\": \"`(` $ref `,` $tag `,` $source `,` $comm`)` attr-dict `:` type($ref) `,` type($tag) `,` type($source)`->` type(results)\"\n  },\n  {\n    \"name\": \"mpi.isend\",\n    \"summary\": \"Equivalent to `MPI_Isend(ptr, size, dtype, dest, tag, comm)`\",\n    \"description\": \"MPI_Isend begins a non-blocking send of `size` elements of type `dtype` to\\n    rank `dest`. The `tag` value and communicator enables the library to\\n    determine the matching of multiple sends and receives between the same\\n    ranks.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tag\", \"type\": \"I32\" },\n      { \"name\": \"dest\", \"type\": \"I32\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" },\n      { \"name\": \"req\", \"type\": \"MPI_Request\" }\n    ],\n    \"assemblyFormat\": \"`(` $ref `,` $tag `,` $dest `,` $comm`)` attr-dict `:` type($ref) `,` type($tag) `,` type($dest) `->` type(results)\"\n  },\n  {\n    \"name\": \"mpi.recv\",\n    \"summary\": \"Equivalent to `MPI_Recv(ptr, size, dtype, source, tag, comm, MPI_STATUS_IGNORE)`\",\n    \"description\": \"MPI_Recv performs a blocking receive of `size` elements of type `dtype` \\n    from rank `source`. The `tag` value and communicator enables the library to\\n    determine the matching of multiple sends and receives between the same \\n    ranks.\\n\\n    The MPI_Status is set to `MPI_STATUS_IGNORE`, as the status object \\n    is not yet ported to MLIR.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tag\", \"type\": \"I32\" },\n      { \"name\": \"source\", \"type\": \"I32\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"`(` $ref `,` $tag `,` $source `,` $comm `)` attr-dict `:` type($ref) `,` type($tag) `,` type($source) (`->` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.reduce_scatter_block\",\n    \"summary\": \"Equivalent to `MPI_Reduce_scatter_block(sendbuf, recvbuf, recvcount, dtype, op, comm)`\",\n    \"description\": \"MPI_Reduce_scatter_block first performs an element-wise reduction on the\\n    sendbuf across all processes in the communicator, then scatters the result\\n    by distributing equal-sized blocks to each process into recvbuf.\\n\\n    The `op` attribute specifies the reduction operation to be performed.\\n    Currently only the `MPI_Op` predefined in the standard (e.g. `MPI_SUM`) are\\n    supported.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"sendbuf\", \"type\": \"AnyNon0RankedMemRef\" },\n      { \"name\": \"recvbuf\", \"type\": \"AnyNon0RankedMemRef\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"MPI_ReductionOpEnum{MPI_OP_NULL|MPI_MAX|MPI_MIN|MPI_SUM|MPI_PROD|MPI_LAND|MPI_BAND|MPI_LOR|MPI_BOR|MPI_LXOR|MPI_BXOR|MPI_MINLOC|MPI_MAXLOC|MPI_REPLACE}\" }\n    ],\n    \"assemblyFormat\": \"`(` $sendbuf `,` $recvbuf `,` $op `,` $comm `)` attr-dict `:` type($sendbuf) `,` type($recvbuf) (`->` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.retval_check\",\n    \"summary\": \"Check an MPI return value against an error class\",\n    \"description\": \"This operation compares MPI status codes to known error class\\n    constants such as `MPI_SUCCESS`, or `MPI_ERR_COMM`.\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"MPI_Retval\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"errclass\", \"type\": \"MPI_ErrorClassAttr{MPI_SUCCESS|MPI_ERR_ACCESS|MPI_ERR_AMODE|MPI_ERR_ARG|MPI_ERR_ASSERT|MPI_ERR_BAD_FILE|MPI_ERR_BASE|MPI_ERR_BUFFER|MPI_ERR_COMM|MPI_ERR_CONVERSION|MPI_ERR_COUNT|MPI_ERR_DIMS|MPI_ERR_DISP|MPI_ERR_DUP_DATAREP|MPI_ERR_ERRHANDLER|MPI_ERR_FILE|MPI_ERR_FILE_EXISTS|MPI_ERR_FILE_IN_USE|MPI_ERR_GROUP|MPI_ERR_INFO|MPI_ERR_INFO_KEY|MPI_ERR_INFO_NOKEY|MPI_ERR_INFO_VALUE|MPI_ERR_IN_STATUS|MPI_ERR_INTERN|MPI_ERR_IO|MPI_ERR_KEYVAL|MPI_ERR_LOCKTYPE|MPI_ERR_NAME|MPI_ERR_NO_MEM|MPI_ERR_NO_SPACE|MPI_ERR_NO_SUCH_FILE|MPI_ERR_NOT_SAME|MPI_ERR_OP|MPI_ERR_OTHER|MPI_ERR_PENDING|MPI_ERR_PORT|MPI_ERR_PROC_ABORTED|MPI_ERR_QUOTA|MPI_ERR_RANK|MPI_ERR_READ_ONLY|MPI_ERR_REQUEST|MPI_ERR_RMA_ATTACH|MPI_ERR_RMA_CONFLICT|MPI_ERR_RMA_FLAVOR|MPI_ERR_RMA_RANGE|MPI_ERR_RMA_SHARED|MPI_ERR_RMA_SYNC|MPI_ERR_ROOT|MPI_ERR_SERVICE|MPI_ERR_SESSION|MPI_ERR_SIZE|MPI_ERR_SPAWN|MPI_ERR_TAG|MPI_ERR_TOPOLOGY|MPI_ERR_TRUNCATE|MPI_ERR_TYPE|MPI_ERR_UNKNOWN|MPI_ERR_UNSUPPORTED_DATAREP|MPI_ERR_UNSUPPORTED_OPERATION|MPI_ERR_VALUE_TOO_LARGE|MPI_ERR_WIN|MPI_ERR_LASTCODE}\" }\n    ],\n    \"assemblyFormat\": \"$val `=` $errclass attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"mpi.send\",\n    \"summary\": \"Equivalent to `MPI_Send(ptr, size, dtype, dest, tag, comm)`\",\n    \"description\": \"MPI_Send performs a blocking send of `size` elements of type `dtype` to rank\\n    `dest`. The `tag` value and communicator enables the library to determine \\n    the matching of multiple sends and receives between the same ranks.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tag\", \"type\": \"I32\" },\n      { \"name\": \"dest\", \"type\": \"I32\" },\n      { \"name\": \"comm\", \"type\": \"MPI_Comm\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"`(` $ref `,` $tag `,` $dest `,` $comm `)` attr-dict `:` type($ref) `,` type($tag) `,` type($dest)(`->` type($retval)^)?\"\n  },\n  {\n    \"name\": \"mpi.wait\",\n    \"summary\": \"Equivalent to `MPI_Wait(req, MPI_STATUS_IGNORE)`\",\n    \"description\": \"MPI_Wait blocks execution until the request has completed.\\n\\n    The MPI_Status is set to `MPI_STATUS_IGNORE`, as the status object \\n    is not yet ported to MLIR.\\n\\n    This operation can optionally return an `!mpi.retval` value that can be used\\n    to check for errors.\",\n    \"operands\": [\n      { \"name\": \"req\", \"type\": \"MPI_Request\" }\n    ],\n    \"results\": [\n      { \"name\": \"retval\", \"type\": \"Optional<MPI_Retval>\" }\n    ],\n    \"assemblyFormat\": \"`(` $req `)` attr-dict `:` type($req) (`->` type($retval) ^)?\"\n  },\n  {\n    \"name\": \"mpmd.assign\",\n    \"summary\": \"assign operation\",\n    \"description\": \"Assigns a local tensor to a mesh as fully replicated within that mesh.\\n\\n    This is a temporary op that is introduced when lowering jax ops, to move\\n    from local types to mesh types. These ops will be eliminated during import,\\n    when the inputs and results of the func op become mesh tensors.\\n\\n    The mesh name of the result type should correspond to a mesh in the\\n    topology, and its global type should be identical to the operand type.\\n\\n    The origin of the assign op is the origin of mesh, e.g. named_computation,\\n    mesh inference, etc.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Mpmd_MeshTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"origin\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $tensor `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mpmd.broadcast\",\n    \"summary\": \"broadcast operation\",\n    \"description\": \"Allows for a tensor to be transferred (or replicated) in any mesh where it's\\n    used. Whenever transferred, the origin of the transfer is the current\\n    location of the operand.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $tensor `:` type($tensor)\"\n  },\n  {\n    \"name\": \"mpmd.call\",\n    \"summary\": \"MPMD specific call function\",\n    \"description\": \"A function call operation. Useful to wrap the body of loops in function\\n    declarations to reduce code size, for example.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<LocalOrMeshTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<LocalOrMeshTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $tensors `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mpmd.for\",\n    \"summary\": \"For operator\",\n    \"description\": \"Returns the result of executing a body function for a fixed number of\\n    iterations, with the iteration index available in the body.\\n\\n    An optional unroll factor, that must divide the number of iterations,\\n    can be specified to unroll the body of the op by that factor, i.e. for\\n    unroll factor N, the body is replicated to create N copies and the number of\\n    iterations is reduced by a factor of 1/N. Each copy except the first uses\\n    the results of the previous copy instead of the block arguments, and the\\n    iteration index is multiplied by the unroll factor and incremented after\\n    every copy.\\n\\n    A for operator can accept and return any types, but the TypeID of these\\n    must be the same -- e.g. all tensor types or all MPMD mesh types etc. This\\n    allows us to use the op at various levels, sharing implementation and\\n    transformations.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iterations\", \"type\": \"UI32Attr\" },\n      { \"name\": \"unroll_factor\", \"type\": \"OptionalAttr<UI32Attr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mpmd.fragment\",\n    \"summary\": \"fragment operation\",\n    \"description\": \"Assigns a computation, i.e. a block of operations, to a specific mesh in an\\n    MPMD topology, that is intended to be executed as an individual SPMD program\\n    fragment.\\n\\n    The fragment takes and returns only mesh tensors that are assigned to the\\n    same mesh as the fragment.\\n\\n    The mesh name of the fragment should correspond to a mesh in the topology.\\n\\n    The fragment includes a list of origins, i.e., metadata with information re\\n    the original named_computations that formed this fragment, and a staged_id\\n    defined _iff_ it is a user defined fragment, i.e., it has a non-empty list\\n    of origins. The optional in_shardings specifies the sharding of the\\n    block arguments of a fragment, which correspond to the operands.\\n    The optional out_shardings specifies the shardings of the results.\\n\\n    The fragment's region shouldn't have any free variables, and the type of\\n    each block arguments and returned values in the region is the global tensor\\n    type of the corresponding mesh tensor.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<MeshTensorOrToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MeshTensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"origin\", \"type\": \"TypedArrayAttrBase<Mpmd_UserOrigin, array of origin infos>\" },\n      { \"name\": \"mesh_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"stage_id\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"in_shardings\", \"type\": \"OptionalAttr<Sdy_TensorShardingPerValue>\" },\n      { \"name\": \"out_shardings\", \"type\": \"OptionalAttr<Sdy_TensorShardingPerValue>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mpmd.fragment_call\",\n    \"summary\": \"fragment call operation\",\n    \"description\": \"Represents a call to a function that holds an MPMD fragment body, i.e. a\\n    computation assigned to a specific mesh in an MPMD topology, that is\\n    intended to be executed as an individual SPMD program fragment.\\n\\n    The mesh name of the fragment should correspond to a mesh in the topology of\\n    the enclosing function, and that mesh shape should match that of the callee.\\n\\n    The origin specifies the user named computations that contributed to this\\n    fragment call e.g. through merging.\\n\\n    The function input and result types of the callee must be the local tensor\\n    types of the corresponding mesh tensors of this op's operands and results\\n    respectively.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = mpmd.fragment_call<mesh=\\\"m1\\\", origin=[]> @my_fragment(%0, %1) :\\n      (mesh_tensor<...>, mesh_tensor<...>) -> mesh_tensor<...>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<Mpmd_MeshTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<Mpmd_MeshTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"origin\", \"type\": \"TypedArrayAttrBase<Mpmd_UserOrigin, array of origin infos>\" },\n      { \"name\": \"mesh_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mpmd.named_computation\",\n    \"summary\": \"named scope operation\",\n    \"description\": \"Groups a computation, i.e. a block of operations, and gives it a name and\\n    a transpose count via the UserOrigin attribute. This NamedComputation can be\\n    used to assign a mesh to the computation in MPMD or for optimizations.\\n\\n    The transpose count (default=0) denotes whether the named computation has\\n    been produced by a certain number of JAX AD transpose transformations.\\n\\n    The op's region shouldn't have any free variables, and the type of\\n    each block arguments and returned values in the region must be the same as\\n    the type of the inputs and the return type of the op.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<HLO_TensorOrToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<HLO_TensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"origin\", \"type\": \"Mpmd_UserOrigin\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mpmd.named_tensor\",\n    \"summary\": \"Assign a tensor to a mesh\",\n    \"description\": \"An identity op that associates the result of the tensor with a given name.\\n    This NamedTensor can be used to assign a mesh to the tensor in MPMD.\\n\\n    NOTE: this is different than TagOp in that TagOp is used for naming a tensor\\n    and can be used to partition that tensor. NamedTensorOp is for MPMD programs\\n    for tensors that may be explicitly assigned to meshes.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$tensor `name````=```$name attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"mpmd.reduce\",\n    \"summary\": \"cross-mesh reduce operation\",\n    \"description\": \"Allows for a tensor to be reduced across different meshes, and then\\n    broadcast to wherever it needs to be used.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<Mpmd_Reduction, ReductionType::kNone>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`` $reduction attr-dict $tensors `:` functional-type(operands, results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"mpmd.return\",\n    \"summary\": \"The `mpmd.return` operation terminates the regions attached to mpmd\\n    region-based ops. It is variadic: it takes as arguments a list of values\\n    whose types can be any (but of the same kind, e.g. `AnyTensor`) and\\n    therefore can be reused at various levels of the MPMD IR stack.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $results (`:` type($results)^)?\"\n  },\n  {\n    \"name\": \"mpmd.transfer\",\n    \"summary\": \"transfer operation\",\n    \"description\": \"Transfers a distributed tensor from one mesh to another.\\n\\n    The mesh names of the operand and result types should correspond to meshes\\n    in the topology, and their global types should be identical.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"Mpmd_MeshTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Mpmd_MeshTensorType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $tensor `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"mpmd.unassign\",\n    \"summary\": \"unassign operation\",\n    \"description\": \"Unassigns a fully replicated tensor from a mesh.\\n\\n    This is a temporary op that is introduced when lowering jax ops, to move\\n    from local types to mesh types. These ops will be eliminated during import,\\n    when the inputs and results of the func op become mesh tensors.\\n\\n    The mesh name of the operand type should correspond to a mesh in the\\n    topology, and its global type should be identical to the result type.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"Mpmd_MeshTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"origin\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $tensor `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"noisy.add\",\n    \"summary\": \"Addition operation between noisy ints. Adds noise.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Noisy_I32\" },\n      { \"name\": \"rhs\", \"type\": \"Noisy_I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Noisy_I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"noisy.decode\",\n    \"summary\": \"Decodes a noisy integer to a regular integer, failing if the noise is too high.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Noisy_I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyIntOfWidths<[1, 2, 3, 4, 5]>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` qualified(type($input)) `->` type($output)\"\n  },\n  {\n    \"name\": \"noisy.encode\",\n    \"summary\": \"Encodes a noisy i32 from a small-width integer, injecting 12 bits of noise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyIntOfWidths<[1, 2, 3, 4, 5]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Noisy_I32\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` qualified(type($output))\"\n  },\n  {\n    \"name\": \"noisy.mul\",\n    \"summary\": \"Multiplication operation between noisy ints. Multiplies noise.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Noisy_I32\" },\n      { \"name\": \"rhs\", \"type\": \"Noisy_I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Noisy_I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"noisy.reduce_noise\",\n    \"summary\": \"Reduces the noise in a noisy integer to a fixed noise level. Expensive!\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Noisy_I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Noisy_I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"noisy.sub\",\n    \"summary\": \"Subtraction operation between noisy ints. Adds noise.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Noisy_I32\" },\n      { \"name\": \"rhs\", \"type\": \"Noisy_I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Noisy_I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"nvg.cluster_id\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvg.device_async_copy\",\n    \"summary\": \"device-side asynchronous copy\",\n    \"description\": \"The `nvgpu.device_async_copy` op initiates an asynchronous copy operation of\\n    elements from source (global memory) to the destination (shared memory)\\n    without blocking the thread. The async copy is added to a group.\\n\\n    This op is meant to be used with `nvgpu.device_async_create_group` and\\n    `nvgpu.device_async_wait` to synchronize copies as explained in those ops\\n    descriptions.\\n\\n    `bypassL1` attribute is hint to the hardware to bypass the L1 cache during\\n    async copy, this hint may be ignored by the hardware.\\n\\n    `dstElements` attribute is the total number of elements written to\\n    destination (shared memory).\\n\\n    `srcElements` argument is the total number of elements read from\\n    source (global memory).\\n\\n    `srcElements` is an optional argument and when present the op only reads\\n    `srcElements` number of elements from the source (global memory) and zero fills\\n    the rest of the elements in the destination (shared memory).\\n\\n    In order to do a copy and wait for the result we need the following\\n    combination:\\n    ```\\n    // copy 1.\\n    %cp1 = nvgpu.device_async_copy %A[%c0], %B[%c0], 4 :memref<16xf32> to memref<16xf32, 3>\\n    // copy 2.\\n    %cp2 = nvgpu.device_async_copy %C[%c0], %D[%c0], 4 : memref<16xf32> to memref<16xf32, 3>\\n    // group 1 contains copy 1 and copy 2.\\n    %token1 = nvgpu.device_async_create_group %cp1, %cp2\\n    // copy 3.\\n    %cp3 = nvgpu.device_async_copy %E[%c0], %F[%c0], 4 : memref<16xf32> to memref<16xf32, 3>\\n    // group 2 contains copy 3.\\n    %token2 = nvgpu.device_async_create_group %cp3\\n    // after the wait copy 1 and copy 2 are complete.\\n    nvgpu.device_async_wait %token1\\n    // after the wait copy 3 is complete.\\n    nvgpu.device_async_wait %token2\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = nvgpu.device_async_copy %src[%c0, %c0], %dst[%c0, %c0, %c0], 4 :\\n      memref<4x5xf32> to memref<2x7x5xf32, 3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"dstIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"srcIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"srcElements\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"NVGPU_DeviceAsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstElements\", \"type\": \"IndexAttr\" },\n      { \"name\": \"bypassL1\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $srcIndices `]` `,` $dst `[` $dstIndices `]` `,` $dstElements (`,` $srcElements^)?\\n      attr-dict `:` type($src) `to` type($dst)\"\n  },\n  {\n    \"name\": \"nvg.device_async_create_group\",\n    \"summary\": \"device side asynchronous create group operation\",\n    \"description\": \"The `nvgpu.device_async_create_group` op creates a group of memory accesses\\n    containing all the pending `device_async_copy` operations associated with\\n    argument tokens. Each token can only be part of one group.\\n\\n    It returns a token that can be use to wait until the group fully completes.\\n\\n    This is meant to be used with `nvgpu.device_async_wait` to synchronize copies\\n    as explained in those ops descriptions.\\n\\n    Groups are executed in the order they are created.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = nvgpu.device_async_create_group\\n  ```\",\n    \"operands\": [\n      { \"name\": \"inputTokens\", \"type\": \"Variadic<NVGPU_DeviceAsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"NVGPU_DeviceAsyncToken\" }\n    ],\n    \"assemblyFormat\": \"$inputTokens attr-dict\"\n  },\n  {\n    \"name\": \"nvg.device_async_wait\",\n    \"summary\": \"Wait for async gpu ops to complete.\",\n    \"description\": \"The `nvgpu.device_async_wait` op will block the execution thread until the group\\n    associated with the source token is fully completed.\\n\\n    The optional `$numGroups` attribute gives an upper bound of the number of\\n    groups uncompleted when the wait can unblock the thread. For example,  if\\n    16 async groups are pushe and `$numGroups` is set to 12, then the thread\\n    will unblock when 12 groups or fewer are in flight (4 groups have\\n    completed).\\n\\n    Example:\\n\\n    ```mlir\\n    nvgpu.device_async_wait %0\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"NVGPU_DeviceAsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numGroups\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"$asyncDependencies attr-dict\"\n  },\n  {\n    \"name\": \"nvg.ld_acquire\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_PointerGlobal\" },\n      { \"name\": \"mask\", \"type\": \"Optional<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"NVGPU_ScalarLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sem\", \"type\": \"NVGPU_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" },\n      { \"name\": \"scope\", \"type\": \"NVGPU_MemSyncScopeAttr{gpu|cta|sys}\" }\n    ],\n    \"assemblyFormat\": \"$sem `,` $scope `,` $addr (`,` $mask^)? attr-dict `:` functional-type($addr, $result)\"\n  },\n  {\n    \"name\": \"nvg.ldmatrix\",\n    \"description\": \"The `nvgpu.ldmatrix` op represents loading a matrix fragment from\\n    memory to registers. The source and result type must be compatible\\n    with lowering to the `nvvm.ldmatrix` instruction. This op represents\\n    the distributed version of a `vector.transfer_read` as an intermediate\\n    step between lowering from `vector.transfer_read` to `nvvm.ldmatrix`.\\n\\n    This operation is meant to follow the semantic of described here:\\n    https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-instructions-ldmatrix\\n\\n    Example:\\n    ```mlir\\n    %0 = nvgpu.ldmatrix %sm[%c0, %c0] {numTiles = 4 : i32, transpose = false} :\\n      memref<?x?xf16, 3> -> vector<4x2xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcMemref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose\", \"type\": \"BoolAttr\" },\n      { \"name\": \"numTiles\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$srcMemref`[` $indices `]` attr-dict `:` type($srcMemref) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.arrive\",\n    \"summary\": \"Performs arrive operation on the `nvgpu.mbarrier.arrive`.\",\n    \"description\": \"The Op performs arrive-on operation on the `mbarrier` object and returns a \\n    `nvgpu.mbarrier.token`.\\n\\n    For more information, see\\n    https://docs.nvidia.com/cuda/parallel-thread-execution/#arrive-on-operation-on-mbarrier-object\\n\\n    Example:\\n    ```mlir\\n      %token = nvgpu.mbarrier.arrive %barrier : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>> -> !nvgpu.mbarrier.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"NVGPU_MBarrierToken\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` attr-dict `:` type($barriers) `->` type($token)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.arrive.expect_tx\",\n    \"summary\": \"Performs expect_tx operation on the `nvgpu.mbarrier.arrive`\",\n    \"description\": \"A thread executing the Op performs an expect-tx operation on the mbarrier \\n    object at the location specified by the address operand $barrier. The \\n    expect-tx operation, with an $txcount argument, increases the tx-count of \\n    an mbarrier object by the value specified by $txcount. This makes the \\n    current phase of the mbarrier object to expect and track the completion of \\n    additional asynchronous transactions.\\n    \\n    The `$txCount` specifies the number of element to the expect-tx operation.\\n\\n    Example:\\n    ```mlir\\n      nvgpu.mbarrier.arrive.expect_tx %barrier, %ic0 : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"txcount\", \"type\": \"Index\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $txcount  (`,` `predicate` `=` $predicate^)? attr-dict `:` type($barriers)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.arrive.nocomplete\",\n    \"summary\": \"Performs arrive operation on the `nvgpu.mbarrier.arrive.nocomplete` as non-blocking.\",\n    \"description\": \"The Op performs arrive-on operation on the `mbarrier` object and returns a \\n    `nvgpu.mbarrier.token`.\\n\\n    The Op does not cause the `nvgpu.mbarrier` to complete its current phase.\\n\\n    Example:\\n    ```mlir\\n      %token = nvgpu.mbarrier.arrive.noComplete %barrier, %count : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>> -> !nvgpu.mbarrier.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"count\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"NVGPU_MBarrierToken\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $count attr-dict `:` type($barriers) `->` type($token)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.create\",\n    \"summary\": \"Creates a `nvgpu.mbarrier` object.\",\n    \"description\": \"The Op generates one or more `mbarrier` object, which is a barrier created in \\n    shared memory and supports various synchronization behaviors for threads.\\n\\n    The `mbarrier` object has the following type and alignment requirements:\\n      Type: .b64, Alignment: 8, Memory space: .shared\\n    \\n    Example:\\n    ```mlir\\n      %barrier = nvgpu.mbarrier.create -> !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"results\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `->` type($barriers)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.get\",\n    \"summary\": \"Return a pointer to an `nvgpu.mbarrier`.\",\n    \"description\": \"The `nvgpu.mbarrier.get` operation retrieves a pointer to a specific \\n    `mbarrier` object from a group of barriers created by the `nvgpu.mbarrier.create` operation.\\n\\n    Example:\\n    ```mlir\\n      %mbars = nvgpu.mbarrier.create -> !nvgpu.mbarrier.group<memorySpace = #gpu.address_space<workgroup>, num_barriers = 10>\\n      %mbar_pointer = nvgpu.mbarrier.get %mbars[%c2] : !nvgpu.mbarrier.group<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"mbarrierPointer\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` attr-dict `:` type($barriers) `->` type($mbarrierPointer)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.init\",\n    \"summary\": \"Initialize the `nvgpu.mbarrier`.\",\n    \"description\": \"The Op initializes the `mbarrier` object with the given number of threads.\\n\\n    Example:\\n    ```mlir\\n      %num_threads = gpu.block_dim x\\n      %barrier = nvgpu.mbarrier.create -> !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n      nvgpu.mbarrier.init %barrier, %num_threads : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"count\", \"type\": \"Index\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $count (`,` `predicate` `=` $predicate^)? attr-dict `:` type($barriers)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.test.wait\",\n    \"summary\": \"Checks if the `nvgpu.mbarrier` has completed its current phase.\",\n    \"description\": \"Checks whether the mbarrier object has completed the phase. It is is a \\n    non-blocking instruction which tests for the completion of the phase.\\n\\n    Example:\\n    ```mlir\\n      %isComplete = nvgpu.mbarrier.test.wait %barrier, %token : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>, !nvgpu.mbarrier.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"token\", \"type\": \"NVGPU_MBarrierToken\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"waitComplete\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $token attr-dict `:` type($barriers) `,` type($token)\"\n  },\n  {\n    \"name\": \"nvg.mbarrier.try_wait.parity\",\n    \"summary\": \"Waits for the `nvgpu.mbarrier` to complete its current phase.\",\n    \"description\": \"Checks whether the mbarrier object has completed the phase. It is is a \\n    potentially blocking instruction which tests for the completion of the \\n    phase. Suspended thread resumes execution when the specified phase completes \\n    OR before the phase completes following a system-dependent time limit. \\n\\n    The `$phaseParity` specifies either even phase (0) or odd phase (1) to \\n    wait.\\n\\n    Example:\\n    ```mlir\\n      nvgpu.mbarrier.try_wait.parity %barrier, %phaseParity, %ticks : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"phaseParity\", \"type\": \"I1\" },\n      { \"name\": \"ticks\", \"type\": \"Index\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $phaseParity `,` $ticks attr-dict `:` type($barriers)\"\n  },\n  {\n    \"name\": \"nvg.mma.sp.sync\",\n    \"description\": \"The `nvgu.mma.sp.sync` operation performs a warp-distributed MMA operation\\n  where operand A is \\\"structured sparse\\\". In this case, the `matrixA` operand\\n  represents the (warp-distributed) non-zero values of operand A, and the\\n  `sparse_metadata` operand provides the indices.\\n\\n  The full description of the sparsity storage format and distribution scheme is\\n  described in the PTX docs. This operation is meant to follow the semantic\\n  described in the PTX documentation here:\\n  https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-instructions-for-sparse-mma\\n\\n  The way the indices are distributed among the threads in a warp is controlled\\n  by the optional `sparsity_selector` operand, which is `0` by default. For\\n  more information, please consult the PTX documentation linked above.\\n\\n  Example (targetingthe f16 16x8x32 `mma.sp` PTX instruction):\\n\\n  ```mlir\\n  nvgpu.mma.sp.sync (%a, %b, %c) metadata (%meta) {mmaShape = [16, 8, 32]} :\\n    (vector<4x2xf16>, vector<2x2xf16>, vector<2x2xf16>) -> vector<2x2xf16>\\n  ```\",\n    \"operands\": [\n      { \"name\": \"matrixA\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixB\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixC\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"NVGPU_MmaSparseSyncMetadataType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mmaShape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"sparsitySelector\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"tf32Enabled\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $matrixA`,` $matrixB`,` $matrixC `)` `metadata` `(` $sparseMetadata `)` attr-dict\\n    `:` `(` type($matrixA) `,` type($matrixB) `,` type($matrixC) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"nvg.mma.sync\",\n    \"description\": \"The `nvgpu.mma.sync` op represents the warp-level matrix-multiply-and-\\n    accumulate (mma) operation that is compatible with `nvvm.mma.sync`.\\n    The operands and results vector sizes are thread-level onwership to\\n    the warp-level mma operation shape. `mmaShape` attribute holds the\\n    warp-level matrix-multiply shape.\\n\\n    The `nvgpu.mma.sync` op serves as an intermediate point between lowering from\\n    `vector.contract` to `nvvm.mma.sync`.\\n\\n    This operation is meant to follow the semantic of described here:\\n      https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-instructions-mma\\n\\n    Example:\\n\\n    ```mlir\\n    %res = nvgpu.mma.sync (%matrixA, %matrixB, %matrixC) {mmaShape = [16, 8, 16]} :\\n        (vector<4x2xf16>, vector<2x2xf16>, vector<2x2xf32>) -> vector<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"matrixA\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixB\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixC\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mmaShape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tf32Enabled\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $matrixA`,` $matrixB`,` $matrixC `)` attr-dict\\n    `:` `(` type($matrixA) `,` type($matrixB) `,` type($matrixC) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"nvg.rcp\",\n    \"summary\": \"The reciprocal calculation for vector types\",\n    \"description\": \"Reciprocal calculation for `vector` types using `nvvm.rcp` OPs.\\n\\n    Currently, only the `approx` rounding mode and `ftz` are supported, and only for the `f32` type.\\n\\n    The input and output must be of the same vector type and shape.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"VectorOfNonZeroRankOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"VectorOfNonZeroRankOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rounding\", \"type\": \"DefaultValuedAttr<RcpRoundingModeAttr{approx|rn|rz|rm|rp}, RcpRoundingMode::APPROX>\" },\n      { \"name\": \"ftz\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$in `{` `rounding` `=` $rounding (`,` `ftz` $ftz^)? `}` \\n    attr-dict `:` type($out)\"\n  },\n  {\n    \"name\": \"nvg.tensor_memory_base\",\n    \"description\": \"Op to represent base address of tensor memory in a kernel.\\n    This is used to simplify lowering from TritonGPU to LLVM.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"LLVM_PointerTensorMemory\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvg.tma.async.load\",\n    \"summary\": \"TMA asynchronous load\",\n    \"description\": \"The Op loads a tile memory region from global memory to shared memory by \\n    Tensor Memory Access (TMA).\\n    \\n    `$tensorMapDescriptor` is tensor map descriptor which has information about\\n    tile shape. The descriptor is created by `nvgpu.tma.create.descriptor`\\n\\n    The Op uses `$barrier` mbarrier based completion mechanism.\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"multicastMask\", \"type\": \"Optional<I16>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$tensorMapDescriptor `[` $coordinates `]` `,` $barriers `[` $mbarId `]` \\n      `to` $dst\\n      (`multicast_mask` `=` $multicastMask^ )?\\n      (`,` `predicate` `=` $predicate^)?\\n      attr-dict `:` type($tensorMapDescriptor) `,` type($barriers) \\n      `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvg.tma.async.store\",\n    \"summary\": \"TMA asynchronous store\",\n    \"description\": \"The Op store a tile memory region from global memory to shared memory by \\n    Tensor Memory Access (TMA).\\n    \\n    `$tensorMapDescriptor` is tensor map descriptor which has information about\\n    tile shape. The descriptor is created by `nvgpu.tma.create.descriptor`\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$src `to` $tensorMapDescriptor `[` $coordinates `]`\\n      (`,` `predicate` `=` $predicate^)?\\n      attr-dict `:` type($src)\\n      `->` type($tensorMapDescriptor)\"\n  },\n  {\n    \"name\": \"nvg.tma.create.descriptor\",\n    \"summary\": \"TMA create descriptor\",\n    \"description\": \"The Op creates a tensor map descriptor object representing tiled memory \\n    region. To do that it calls CUDA Driver's `cuTensorMapEncodeTiled`. The \\n    descriptor is used by Tensor Memory Access (TMA).\\n\\n    The `tensor` is the source tensor to be tiled. \\n\\n    The `boxDimensions` is the size of the tiled memory region in each dimension.\\n\\n    For more information see below:\\n    https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__TENSOR__MEMORY.html\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyUnrankedMemRef\" },\n      { \"name\": \"boxDimensions\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensorMap\", \"type\": \"NVGPU_TensorMapDescriptor\" }\n    ],\n    \"assemblyFormat\": \"$tensor `box` `[` $boxDimensions `]` attr-dict `:` type($tensor) `->` type($tensorMap)\"\n  },\n  {\n    \"name\": \"nvg.tma.fence.descriptor\",\n    \"summary\": \"Insert fence given `nvgpu.tensormap.descriptor`\",\n    \"description\": \"The Op fences the given `$tmaDescriptor`. This is necessary if the tensor map\\n    descriptor was modified from the host using cudaMemcpy. In this case, the\\n    kernel needs a fence after which it is safe to use `tensor.map`.\",\n    \"operands\": [\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" }\n    ],\n    \"assemblyFormat\": \"$tensorMapDescriptor attr-dict `:` type($tensorMapDescriptor)\"\n  },\n  {\n    \"name\": \"nvg.tma.prefetch.descriptor\",\n    \"summary\": \"Prefetch given `nvgpu.tensormap.descriptor`\",\n    \"description\": \"The Op brings the cache line containing the given `$tmaDescriptor` for \\n    subsequent use by the `tma.async.load` instruction.\",\n    \"operands\": [\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$tensorMapDescriptor (`,` `predicate` `=` $predicate^)? attr-dict `:` type($tensorMapDescriptor)\"\n  },\n  {\n    \"name\": \"nvg.warpgroup.generate.descriptor\",\n    \"summary\": \"Generate a warpgroup matrix descriptor\",\n    \"description\": \"This Op builds a `nvgpu.warpgroup.descriptor` that is used by \\n  `nvgpu.warpgroup.mma` to perform warpgroup-level matrix multiply and \\n  accumulate.\\n\\n  The descriptor specifies the properties of the matrix in shared memory that \\n  is a multiplicand in the matrix multiply and accumulate operation.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tensorMap\", \"type\": \"NVGPU_TensorMapDescriptor\" }\n    ],\n    \"results\": [\n      { \"name\": \"descriptor\", \"type\": \"NVGPU_WarpgroupMatrixDescriptor\" }\n    ],\n    \"assemblyFormat\": \"$tensor `,` $tensorMap attr-dict `:` type($tensor) `,` type($tensorMap) `->` type($descriptor)\"\n  },\n  {\n    \"name\": \"nvg.warpgroup.mma\",\n    \"description\": \"The `nvgpu.warpgroup.mma` op performs the warpgroup-level (4 warps) \\n    matrix-multiply-and-accumulate (mma) operation that results in \\n    `nvvm.wgmma.mma_async`. \\n    \\n    The operands are `descriptorA` and `descriptorB` that are wgmma matrix \\n    descriptors that shows the properties of the matrix in shared memory. The \\n    results are thread-level ownership to the warpgroup-level mma operation \\n    shape. The shape is deduced from the descriptor types and output vector.\\n\\n    The Op encapsulates multiple `nvvm.wgmma.mma_async` operations to complete \\n    the given shape. As `nvvm.wgmma.async` Op, or its corresponding PTX \\n    instruction, is asynchronous, this Op groups the `nvvm.wgmma.async` and \\n    surrounds them between `wgmma.fence.aligned` and \\n    `wgmma.commit.group.sync.aligned`, `wgmma.wait.group.sync.aligned` Ops.\\n\\n    Example:\\n    ```mlir\\n      %r1,%r2 = nvgpu.warpgroup.mma %descA, %descB, %acc1, %acc2: \\n                 !nvgpu.warpgroup.descriptor<tensor = memref<128x64xf16, 3>>, \\n                 !nvgpu.warpgroup.descriptor<tensor = memref<64x128xf16, 3>>, \\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>,\\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>\\n                 -> \\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>,\\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"descriptorA\", \"type\": \"NVGPU_WarpgroupMatrixDescriptor\" },\n      { \"name\": \"descriptorB\", \"type\": \"NVGPU_WarpgroupMatrixDescriptor\" },\n      { \"name\": \"matrixC\", \"type\": \"NVGPU_WarpgroupAccumulator\" }\n    ],\n    \"results\": [\n      { \"name\": \"matrixD\", \"type\": \"NVGPU_WarpgroupAccumulator\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"waitGroup\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"transposeA\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"transposeB\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$descriptorA`,` $descriptorB`,` $matrixC attr-dict\\n    `:` type($descriptorA) `,` type($descriptorB) `,` type($matrixC) `->` type($matrixD)\"\n  },\n  {\n    \"name\": \"nvg.warpgroup.mma.init.accumulator\",\n    \"summary\": \"Initializes the accumulator matrix\",\n    \"description\": \"This Op generates and initializes the accumulator matrix for \\n    `nvgpu.warpgroup.mma` op to perform matrix-multiply-and-accumulate.\",\n    \"results\": [\n      { \"name\": \"matrixC\", \"type\": \"NVGPU_WarpgroupAccumulator\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `->` type($matrixC)\"\n  },\n  {\n    \"name\": \"nvg.warpgroup.mma.store\",\n    \"description\": \"The `nvgpu.warpgroup.mma.store` op performs the store of fragmented result \\n    in $matrixD to given memref. \\n\\n    [See the details of register fragment layout for accumulator matrix D]\\n    (https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#wgmma-64n16-d) \\n\\n    Note that, the op must be run with warp group.\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"NVGPU_WarpgroupAccumulator\" },\n      { \"name\": \"dstMemref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $dstMemref attr-dict `:` type($matrixD) `to` type($dstMemref)\"\n  },\n  {\n    \"name\": \"nvg.wgmma\",\n    \"operands\": [\n      { \"name\": \"opA\", \"type\": \"WGMMA_OperandType\" },\n      { \"name\": \"opB\", \"type\": \"WGMMA_OperandType\" },\n      { \"name\": \"useC\", \"type\": \"I1\" },\n      { \"name\": \"opC\", \"type\": \"Optional<LLVM_AnyStruct>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"I32Attr\" },\n      { \"name\": \"n\", \"type\": \"I32Attr\" },\n      { \"name\": \"k\", \"type\": \"I32Attr\" },\n      { \"name\": \"eltTypeC\", \"type\": \"WGMMA_EltTypeAttr{s8|s32|e4m3|e5m2|f16|bf16|tf32|f32}\" },\n      { \"name\": \"eltTypeA\", \"type\": \"WGMMA_EltTypeAttr{s8|s32|e4m3|e5m2|f16|bf16|tf32|f32}\" },\n      { \"name\": \"eltTypeB\", \"type\": \"WGMMA_EltTypeAttr{s8|s32|e4m3|e5m2|f16|bf16|tf32|f32}\" },\n      { \"name\": \"layoutA\", \"type\": \"WGMMA_LayoutAttr{row|col}\" },\n      { \"name\": \"layoutB\", \"type\": \"WGMMA_LayoutAttr{row|col}\" }\n    ],\n    \"assemblyFormat\": \"$opA `,` $opB `,` $useC (`,` $opC^)? attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"nvg.wgmma_wait_group\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pendings\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"nvgpu.device_async_copy\",\n    \"summary\": \"device-side asynchronous copy\",\n    \"description\": \"The `nvgpu.device_async_copy` op initiates an asynchronous copy operation of\\n    elements from source (global memory) to the destination (shared memory)\\n    without blocking the thread. The async copy is added to a group.\\n\\n    This op is meant to be used with `nvgpu.device_async_create_group` and\\n    `nvgpu.device_async_wait` to synchronize copies as explained in those ops\\n    descriptions.\\n\\n    `bypassL1` attribute is hint to the hardware to bypass the L1 cache during\\n    async copy, this hint may be ignored by the hardware.\\n\\n    `dstElements` attribute is the total number of elements written to\\n    destination (shared memory).\\n\\n    `srcElements` argument is the total number of elements read from\\n    source (global memory).\\n\\n    `srcElements` is an optional argument and when present the op only reads\\n    `srcElements` number of elements from the source (global memory) and zero fills\\n    the rest of the elements in the destination (shared memory).\\n\\n    In order to do a copy and wait for the result we need the following\\n    combination:\\n    ```\\n    // copy 1.\\n    %cp1 = nvgpu.device_async_copy %A[%c0], %B[%c0], 4 :memref<16xf32> to memref<16xf32, 3>\\n    // copy 2.\\n    %cp2 = nvgpu.device_async_copy %C[%c0], %D[%c0], 4 : memref<16xf32> to memref<16xf32, 3>\\n    // group 1 contains copy 1 and copy 2.\\n    %token1 = nvgpu.device_async_create_group %cp1, %cp2\\n    // copy 3.\\n    %cp3 = nvgpu.device_async_copy %E[%c0], %F[%c0], 4 : memref<16xf32> to memref<16xf32, 3>\\n    // group 2 contains copy 3.\\n    %token2 = nvgpu.device_async_create_group %cp3\\n    // after the wait copy 1 and copy 2 are complete.\\n    nvgpu.device_async_wait %token1\\n    // after the wait copy 3 is complete.\\n    nvgpu.device_async_wait %token2\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = nvgpu.device_async_copy %src[%c0, %c0], %dst[%c0, %c0, %c0], 4 :\\n      memref<4x5xf32> to memref<2x7x5xf32, 3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"dstIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"srcIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"srcElements\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"NVGPU_DeviceAsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstElements\", \"type\": \"IndexAttr\" },\n      { \"name\": \"bypassL1\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $srcIndices `]` `,` $dst `[` $dstIndices `]` `,` $dstElements (`,` $srcElements^)?\\n      attr-dict `:` type($src) `to` type($dst)\"\n  },\n  {\n    \"name\": \"nvgpu.device_async_create_group\",\n    \"summary\": \"device side asynchronous create group operation\",\n    \"description\": \"The `nvgpu.device_async_create_group` op creates a group of memory accesses\\n    containing all the pending `device_async_copy` operations associated with\\n    argument tokens. Each token can only be part of one group.\\n\\n    It returns a token that can be use to wait until the group fully completes.\\n\\n    This is meant to be used with `nvgpu.device_async_wait` to synchronize copies\\n    as explained in those ops descriptions.\\n\\n    Groups are executed in the order they are created.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = nvgpu.device_async_create_group\\n  ```\",\n    \"operands\": [\n      { \"name\": \"inputTokens\", \"type\": \"Variadic<NVGPU_DeviceAsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"NVGPU_DeviceAsyncToken\" }\n    ],\n    \"assemblyFormat\": \"$inputTokens attr-dict\"\n  },\n  {\n    \"name\": \"nvgpu.device_async_wait\",\n    \"summary\": \"Wait for async gpu ops to complete.\",\n    \"description\": \"The `nvgpu.device_async_wait` op will block the execution thread until the group\\n    associated with the source token is fully completed.\\n\\n    The optional `$numGroups` attribute gives an upper bound of the number of\\n    groups uncompleted when the wait can unblock the thread. For example,  if\\n    16 async groups are pushe and `$numGroups` is set to 12, then the thread\\n    will unblock when 12 groups or fewer are in flight (4 groups have\\n    completed).\\n\\n    Example:\\n\\n    ```mlir\\n    nvgpu.device_async_wait %0\\n    ```\",\n    \"operands\": [\n      { \"name\": \"asyncDependencies\", \"type\": \"NVGPU_DeviceAsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numGroups\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"$asyncDependencies attr-dict\"\n  },\n  {\n    \"name\": \"nvgpu.ldmatrix\",\n    \"description\": \"The `nvgpu.ldmatrix` op represents loading a matrix fragment from\\n    memory to registers. The source and result type must be compatible\\n    with lowering to the `nvvm.ldmatrix` instruction. This op represents\\n    the distributed version of a `vector.transfer_read` as an intermediate\\n    step between lowering from `vector.transfer_read` to `nvvm.ldmatrix`.\\n\\n    This operation is meant to follow the semantic of described here:\\n    https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-instructions-ldmatrix\\n\\n    Example:\\n    ```mlir\\n    %0 = nvgpu.ldmatrix %sm[%c0, %c0] {numTiles = 4 : i32, transpose = false} :\\n      memref<?x?xf16, 3> -> vector<4x2xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcMemref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose\", \"type\": \"BoolAttr\" },\n      { \"name\": \"numTiles\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$srcMemref`[` $indices `]` attr-dict `:` type($srcMemref) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.arrive\",\n    \"summary\": \"Performs arrive operation on the `nvgpu.mbarrier.arrive`.\",\n    \"description\": \"The Op performs arrive-on operation on the `mbarrier` object and returns a \\n    `nvgpu.mbarrier.token`.\\n\\n    For more information, see\\n    https://docs.nvidia.com/cuda/parallel-thread-execution/#arrive-on-operation-on-mbarrier-object\\n\\n    Example:\\n    ```mlir\\n      %token = nvgpu.mbarrier.arrive %barrier : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>> -> !nvgpu.mbarrier.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"NVGPU_MBarrierToken\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` attr-dict `:` type($barriers) `->` type($token)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.arrive.expect_tx\",\n    \"summary\": \"Performs expect_tx operation on the `nvgpu.mbarrier.arrive`\",\n    \"description\": \"A thread executing the Op performs an expect-tx operation on the mbarrier \\n    object at the location specified by the address operand $barrier. The \\n    expect-tx operation, with an $txcount argument, increases the tx-count of \\n    an mbarrier object by the value specified by $txcount. This makes the \\n    current phase of the mbarrier object to expect and track the completion of \\n    additional asynchronous transactions.\\n    \\n    The `$txCount` specifies the number of element to the expect-tx operation.\\n\\n    Example:\\n    ```mlir\\n      nvgpu.mbarrier.arrive.expect_tx %barrier, %ic0 : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"txcount\", \"type\": \"Index\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $txcount  (`,` `predicate` `=` $predicate^)? attr-dict `:` type($barriers)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.arrive.nocomplete\",\n    \"summary\": \"Performs arrive operation on the `nvgpu.mbarrier.arrive.nocomplete` as non-blocking.\",\n    \"description\": \"The Op performs arrive-on operation on the `mbarrier` object and returns a \\n    `nvgpu.mbarrier.token`.\\n\\n    The Op does not cause the `nvgpu.mbarrier` to complete its current phase.\\n\\n    Example:\\n    ```mlir\\n      %token = nvgpu.mbarrier.arrive.noComplete %barrier, %count : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>> -> !nvgpu.mbarrier.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"count\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"NVGPU_MBarrierToken\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $count attr-dict `:` type($barriers) `->` type($token)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.create\",\n    \"summary\": \"Creates a `nvgpu.mbarrier` object.\",\n    \"description\": \"The Op generates one or more `mbarrier` object, which is a barrier created in \\n    shared memory and supports various synchronization behaviors for threads.\\n\\n    The `mbarrier` object has the following type and alignment requirements:\\n      Type: .b64, Alignment: 8, Memory space: .shared\\n    \\n    Example:\\n    ```mlir\\n      %barrier = nvgpu.mbarrier.create -> !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"results\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `->` type($barriers)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.get\",\n    \"summary\": \"Return a pointer to an `nvgpu.mbarrier`.\",\n    \"description\": \"The `nvgpu.mbarrier.get` operation retrieves a pointer to a specific \\n    `mbarrier` object from a group of barriers created by the `nvgpu.mbarrier.create` operation.\\n\\n    Example:\\n    ```mlir\\n      %mbars = nvgpu.mbarrier.create -> !nvgpu.mbarrier.group<memorySpace = #gpu.address_space<workgroup>, num_barriers = 10>\\n      %mbar_pointer = nvgpu.mbarrier.get %mbars[%c2] : !nvgpu.mbarrier.group<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"mbarrierPointer\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` attr-dict `:` type($barriers) `->` type($mbarrierPointer)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.init\",\n    \"summary\": \"Initialize the `nvgpu.mbarrier`.\",\n    \"description\": \"The Op initializes the `mbarrier` object with the given number of threads.\\n\\n    Example:\\n    ```mlir\\n      %num_threads = gpu.block_dim x\\n      %barrier = nvgpu.mbarrier.create -> !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n      nvgpu.mbarrier.init %barrier, %num_threads : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"count\", \"type\": \"Index\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $count (`,` `predicate` `=` $predicate^)? attr-dict `:` type($barriers)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.test.wait\",\n    \"summary\": \"Checks if the `nvgpu.mbarrier` has completed its current phase.\",\n    \"description\": \"Checks whether the mbarrier object has completed the phase. It is is a \\n    non-blocking instruction which tests for the completion of the phase.\\n\\n    Example:\\n    ```mlir\\n      %isComplete = nvgpu.mbarrier.test.wait %barrier, %token : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>, !nvgpu.mbarrier.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"token\", \"type\": \"NVGPU_MBarrierToken\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"waitComplete\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $token attr-dict `:` type($barriers) `,` type($token)\"\n  },\n  {\n    \"name\": \"nvgpu.mbarrier.try_wait.parity\",\n    \"summary\": \"Waits for the `nvgpu.mbarrier` to complete its current phase.\",\n    \"description\": \"Checks whether the mbarrier object has completed the phase. It is is a \\n    potentially blocking instruction which tests for the completion of the \\n    phase. Suspended thread resumes execution when the specified phase completes \\n    OR before the phase completes following a system-dependent time limit. \\n\\n    The `$phaseParity` specifies either even phase (0) or odd phase (1) to \\n    wait.\\n\\n    Example:\\n    ```mlir\\n      nvgpu.mbarrier.try_wait.parity %barrier, %phaseParity, %ticks : !nvgpu.mbarrier.barrier<memorySpace = #gpu.address_space<workgroup>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"phaseParity\", \"type\": \"I1\" },\n      { \"name\": \"ticks\", \"type\": \"Index\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$barriers `[` $mbarId `]` `,` $phaseParity `,` $ticks attr-dict `:` type($barriers)\"\n  },\n  {\n    \"name\": \"nvgpu.mma.sp.sync\",\n    \"description\": \"The `nvgu.mma.sp.sync` operation performs a warp-distributed MMA operation\\n  where operand A is \\\"structured sparse\\\". In this case, the `matrixA` operand\\n  represents the (warp-distributed) non-zero values of operand A, and the\\n  `sparse_metadata` operand provides the indices.\\n\\n  The full description of the sparsity storage format and distribution scheme is\\n  described in the PTX docs. This operation is meant to follow the semantic\\n  described in the PTX documentation here:\\n  https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-instructions-for-sparse-mma\\n\\n  The way the indices are distributed among the threads in a warp is controlled\\n  by the optional `sparsity_selector` operand, which is `0` by default. For\\n  more information, please consult the PTX documentation linked above.\\n\\n  Example (targetingthe f16 16x8x32 `mma.sp` PTX instruction):\\n\\n  ```mlir\\n  nvgpu.mma.sp.sync (%a, %b, %c) metadata (%meta) {mmaShape = [16, 8, 32]} :\\n    (vector<4x2xf16>, vector<2x2xf16>, vector<2x2xf16>) -> vector<2x2xf16>\\n  ```\",\n    \"operands\": [\n      { \"name\": \"matrixA\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixB\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixC\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"NVGPU_MmaSparseSyncMetadataType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mmaShape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"sparsitySelector\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"tf32Enabled\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $matrixA`,` $matrixB`,` $matrixC `)` `metadata` `(` $sparseMetadata `)` attr-dict\\n    `:` `(` type($matrixA) `,` type($matrixB) `,` type($matrixC) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"nvgpu.mma.sync\",\n    \"description\": \"The `nvgpu.mma.sync` op represents the warp-level matrix-multiply-and-\\n    accumulate (mma) operation that is compatible with `nvvm.mma.sync`.\\n    The operands and results vector sizes are thread-level onwership to\\n    the warp-level mma operation shape. `mmaShape` attribute holds the\\n    warp-level matrix-multiply shape.\\n\\n    The `nvgpu.mma.sync` op serves as an intermediate point between lowering from\\n    `vector.contract` to `nvvm.mma.sync`.\\n\\n    This operation is meant to follow the semantic of described here:\\n      https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-instructions-mma\\n\\n    Example:\\n\\n    ```mlir\\n    %res = nvgpu.mma.sync (%matrixA, %matrixB, %matrixC) {mmaShape = [16, 8, 16]} :\\n        (vector<4x2xf16>, vector<2x2xf16>, vector<2x2xf32>) -> vector<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"matrixA\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixB\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"matrixC\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mmaShape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tf32Enabled\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $matrixA`,` $matrixB`,` $matrixC `)` attr-dict\\n    `:` `(` type($matrixA) `,` type($matrixB) `,` type($matrixC) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"nvgpu.rcp\",\n    \"summary\": \"The reciprocal calculation for vector types\",\n    \"description\": \"Reciprocal calculation for `vector` types using `nvvm.rcp` OPs.\\n\\n    Currently, only the `approx` rounding mode and `ftz` are supported, and only for the `f32` type.\\n\\n    The input and output must be of the same vector type and shape.\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"VectorOfNonZeroRankOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"VectorOfNonZeroRankOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rounding\", \"type\": \"DefaultValuedAttr<RcpRoundingModeAttr{approx|rn|rz|rm|rp}, RcpRoundingMode::APPROX>\" },\n      { \"name\": \"ftz\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$in `{` `rounding` `=` $rounding (`,` `ftz` $ftz^)? `}` \\n    attr-dict `:` type($out)\"\n  },\n  {\n    \"name\": \"nvgpu.tma.async.load\",\n    \"summary\": \"TMA asynchronous load\",\n    \"description\": \"The Op loads a tile memory region from global memory to shared memory by \\n    Tensor Memory Access (TMA).\\n    \\n    `$tensorMapDescriptor` is tensor map descriptor which has information about\\n    tile shape. The descriptor is created by `nvgpu.tma.create.descriptor`\\n\\n    The Op uses `$barrier` mbarrier based completion mechanism.\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"barriers\", \"type\": \"NVGPU_MBarrierGroup\" },\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mbarId\", \"type\": \"Index\" },\n      { \"name\": \"multicastMask\", \"type\": \"Optional<I16>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$tensorMapDescriptor `[` $coordinates `]` `,` $barriers `[` $mbarId `]` \\n      `to` $dst\\n      (`multicast_mask` `=` $multicastMask^ )?\\n      (`,` `predicate` `=` $predicate^)?\\n      attr-dict `:` type($tensorMapDescriptor) `,` type($barriers) \\n      `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvgpu.tma.async.store\",\n    \"summary\": \"TMA asynchronous store\",\n    \"description\": \"The Op store a tile memory region from global memory to shared memory by \\n    Tensor Memory Access (TMA).\\n    \\n    `$tensorMapDescriptor` is tensor map descriptor which has information about\\n    tile shape. The descriptor is created by `nvgpu.tma.create.descriptor`\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$src `to` $tensorMapDescriptor `[` $coordinates `]`\\n      (`,` `predicate` `=` $predicate^)?\\n      attr-dict `:` type($src)\\n      `->` type($tensorMapDescriptor)\"\n  },\n  {\n    \"name\": \"nvgpu.tma.create.descriptor\",\n    \"summary\": \"TMA create descriptor\",\n    \"description\": \"The Op creates a tensor map descriptor object representing tiled memory \\n    region. To do that it calls CUDA Driver's `cuTensorMapEncodeTiled`. The \\n    descriptor is used by Tensor Memory Access (TMA).\\n\\n    The `tensor` is the source tensor to be tiled. \\n\\n    The `boxDimensions` is the size of the tiled memory region in each dimension.\\n\\n    For more information see below:\\n    https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__TENSOR__MEMORY.html\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyUnrankedMemRef\" },\n      { \"name\": \"boxDimensions\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensorMap\", \"type\": \"NVGPU_TensorMapDescriptor\" }\n    ],\n    \"assemblyFormat\": \"$tensor `box` `[` $boxDimensions `]` attr-dict `:` type($tensor) `->` type($tensorMap)\"\n  },\n  {\n    \"name\": \"nvgpu.tma.fence.descriptor\",\n    \"summary\": \"Insert fence given `nvgpu.tensormap.descriptor`\",\n    \"description\": \"The Op fences the given `$tmaDescriptor`. This is necessary if the tensor map\\n    descriptor was modified from the host using cudaMemcpy. In this case, the\\n    kernel needs a fence after which it is safe to use `tensor.map`.\",\n    \"operands\": [\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" }\n    ],\n    \"assemblyFormat\": \"$tensorMapDescriptor attr-dict `:` type($tensorMapDescriptor)\"\n  },\n  {\n    \"name\": \"nvgpu.tma.prefetch.descriptor\",\n    \"summary\": \"Prefetch given `nvgpu.tensormap.descriptor`\",\n    \"description\": \"The Op brings the cache line containing the given `$tmaDescriptor` for \\n    subsequent use by the `tma.async.load` instruction.\",\n    \"operands\": [\n      { \"name\": \"tensorMapDescriptor\", \"type\": \"NVGPU_TensorMapDescriptor\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$tensorMapDescriptor (`,` `predicate` `=` $predicate^)? attr-dict `:` type($tensorMapDescriptor)\"\n  },\n  {\n    \"name\": \"nvgpu.warpgroup.generate.descriptor\",\n    \"summary\": \"Generate a warpgroup matrix descriptor\",\n    \"description\": \"This Op builds a `nvgpu.warpgroup.descriptor` that is used by \\n  `nvgpu.warpgroup.mma` to perform warpgroup-level matrix multiply and \\n  accumulate.\\n\\n  The descriptor specifies the properties of the matrix in shared memory that \\n  is a multiplicand in the matrix multiply and accumulate operation.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tensorMap\", \"type\": \"NVGPU_TensorMapDescriptor\" }\n    ],\n    \"results\": [\n      { \"name\": \"descriptor\", \"type\": \"NVGPU_WarpgroupMatrixDescriptor\" }\n    ],\n    \"assemblyFormat\": \"$tensor `,` $tensorMap attr-dict `:` type($tensor) `,` type($tensorMap) `->` type($descriptor)\"\n  },\n  {\n    \"name\": \"nvgpu.warpgroup.mma\",\n    \"description\": \"The `nvgpu.warpgroup.mma` op performs the warpgroup-level (4 warps) \\n    matrix-multiply-and-accumulate (mma) operation that results in \\n    `nvvm.wgmma.mma_async`. \\n    \\n    The operands are `descriptorA` and `descriptorB` that are wgmma matrix \\n    descriptors that shows the properties of the matrix in shared memory. The \\n    results are thread-level ownership to the warpgroup-level mma operation \\n    shape. The shape is deduced from the descriptor types and output vector.\\n\\n    The Op encapsulates multiple `nvvm.wgmma.mma_async` operations to complete \\n    the given shape. As `nvvm.wgmma.async` Op, or its corresponding PTX \\n    instruction, is asynchronous, this Op groups the `nvvm.wgmma.async` and \\n    surrounds them between `wgmma.fence.aligned` and \\n    `wgmma.commit.group.sync.aligned`, `wgmma.wait.group.sync.aligned` Ops.\\n\\n    Example:\\n    ```mlir\\n      %r1,%r2 = nvgpu.warpgroup.mma %descA, %descB, %acc1, %acc2: \\n                 !nvgpu.warpgroup.descriptor<tensor = memref<128x64xf16, 3>>, \\n                 !nvgpu.warpgroup.descriptor<tensor = memref<64x128xf16, 3>>, \\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>,\\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>\\n                 -> \\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>,\\n                 !nvgpu.warpgroup.accumulator<fragmented = vector<64x128xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"descriptorA\", \"type\": \"NVGPU_WarpgroupMatrixDescriptor\" },\n      { \"name\": \"descriptorB\", \"type\": \"NVGPU_WarpgroupMatrixDescriptor\" },\n      { \"name\": \"matrixC\", \"type\": \"NVGPU_WarpgroupAccumulator\" }\n    ],\n    \"results\": [\n      { \"name\": \"matrixD\", \"type\": \"NVGPU_WarpgroupAccumulator\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"waitGroup\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"transposeA\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"transposeB\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$descriptorA`,` $descriptorB`,` $matrixC attr-dict\\n    `:` type($descriptorA) `,` type($descriptorB) `,` type($matrixC) `->` type($matrixD)\"\n  },\n  {\n    \"name\": \"nvgpu.warpgroup.mma.init.accumulator\",\n    \"summary\": \"Initializes the accumulator matrix\",\n    \"description\": \"This Op generates and initializes the accumulator matrix for \\n    `nvgpu.warpgroup.mma` op to perform matrix-multiply-and-accumulate.\",\n    \"results\": [\n      { \"name\": \"matrixC\", \"type\": \"NVGPU_WarpgroupAccumulator\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `->` type($matrixC)\"\n  },\n  {\n    \"name\": \"nvgpu.warpgroup.mma.store\",\n    \"description\": \"The `nvgpu.warpgroup.mma.store` op performs the store of fragmented result \\n    in $matrixD to given memref. \\n\\n    [See the details of register fragment layout for accumulator matrix D]\\n    (https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#wgmma-64n16-d) \\n\\n    Note that, the op must be run with warp group.\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"NVGPU_WarpgroupAccumulator\" },\n      { \"name\": \"dstMemref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $dstMemref attr-dict `:` type($matrixD) `to` type($dstMemref)\"\n  },\n  {\n    \"name\": \"nvvm.addf\",\n    \"summary\": \"Performs floating point addition of the given arguments `lhs` and `rhs`\",\n    \"description\": \"The `nvvm.addf` operation performs floating point addition of two floating \\n    point operands of the same type.\\n\\n    The rounding mode is specified by the `rnd` attribute, saturation mode by \\n    the `sat` attribute, and flush-to-zero by the `ftz` attribute.\\n\\n    For more information, see PTX ISA:\\n    - [floating point addition](https://docs.nvidia.com/cuda/parallel-thread-execution/#floating-point-instructions-add)\\n    - [half-precision floating point addition](https://docs.nvidia.com/cuda/parallel-thread-execution/#half-precision-floating-point-instructions-add)\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SIMTFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"SIMTFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"SIMTFloatType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<ConfinedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, [EnumAttrIsOneOf<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, [FPRoundingModeNone, FPRoundingModeRM, FPRoundingModeRN, FPRoundingModeRP, FPRoundingModeRZ]>]>, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<ConfinedAttr<SaturationModeAttr{none|satfinite|sat}, [EnumAttrIsOneOf<SaturationModeAttr{none|satfinite|sat}, [SaturationModeNone, SaturationModeSat]>]>, SaturationMode::NONE>\" },\n      { \"name\": \"ftz\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.bar.warp.sync\",\n    \"summary\": \"Warp Barrier Synchronization Op\",\n    \"description\": \"The `nvvm.bar.warp.sync` operation performs barrier synchronization for threads \\n    within a warp. \\n\\n    This operation causes the executing thread to wait until all threads corresponding \\n    to the `mask` operand have executed a `bar.warp.sync` with the same mask value \\n    before resuming execution.\\n\\n    The `mask` operand specifies the threads participating in the barrier, where each \\n    bit position corresponds to the thread's lane ID within the warp. Only threads with \\n    their corresponding bit set in the mask participate in the barrier synchronization.\\n\\n    **Important constraints**:\\n    - The behavior is undefined if the executing thread is not included in the mask \\n      (i.e., the bit corresponding to the thread's lane ID is not set)\\n    - For compute capability sm_6x or below, all threads in the mask must execute \\n      the same `bar.warp.sync` instruction in convergence\\n\\n    This operation also guarantees memory ordering among participating threads. \\n    Threads within the warp that wish to communicate via memory can store to memory, \\n    execute `bar.warp.sync`, and then safely read values stored by other threads \\n    in the warp.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-bar-warp-sync)\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$mask attr-dict `:` type($mask)\"\n  },\n  {\n    \"name\": \"nvvm.barrier\",\n    \"summary\": \"CTA Barrier Synchronization Op\",\n    \"description\": \"The `nvvm.barrier` operation performs barrier synchronization and communication \\n    within a CTA (Cooperative Thread Array). It causes executing threads to wait for \\n    all non-exited threads participating in the barrier to arrive.\\n\\n    The operation takes two optional operands:\\n\\n    - `barrierId`: Specifies a logical barrier resource with value 0 through 15. \\n      Each CTA instance has sixteen barriers numbered 0..15. Defaults to 0 if not specified.\\n    - `numberOfThreads`: Specifies the number of threads participating in the barrier. \\n      When specified, the value must be a multiple of the warp size. If not specified, \\n      all threads in the CTA participate in the barrier.\\n    - `reductionOp`: specifies the reduction operation (`popc`, `and`, `or`).\\n    - `reductionPredicate`: specifies the predicate to be used with the\\n      `reductionOp`. \\n\\n    The barrier operation guarantees that when the barrier completes, prior memory \\n    accesses requested by participating threads are performed relative to all threads \\n    participating in the barrier. It also ensures that no new memory access is \\n    requested by participating threads before the barrier completes.\\n\\n    When a barrier completes, the waiting threads are restarted without delay, and \\n    the barrier is reinitialized so that it can be immediately reused.\\n\\n    This operation generates an aligned barrier, indicating that all threads in the CTA \\n    will execute the same barrier instruction. Behavior is undefined if all threads in the \\n    CTA do not reach this instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-bar)\",\n    \"operands\": [\n      { \"name\": \"barrierId\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"numberOfThreads\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"reductionPredicate\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reductionOp\", \"type\": \"OptionalAttr<BarrierReductionAttr{popc|and|or}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`id` `=` $barrierId^)? (`number_of_threads` `=` $numberOfThreads^)? (qualified($reductionOp)^ $reductionPredicate)? (`->` type($res)^)? attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.barrier.arrive\",\n    \"description\": \"Thread that executes this op announces their arrival at the barrier with \\n    given id and continue their execution.\\n\\n    The default barrier id is 0 that is similar to `nvvm.barrier` Op. When \\n    `barrierId` is not present, the default barrier id is used. \\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-bar)\",\n    \"operands\": [\n      { \"name\": \"barrierId\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"numberOfThreads\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"(`id` `=` $barrierId^)? `number_of_threads` `=` $numberOfThreads attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.barrier0\",\n    \"summary\": \"CTA Barrier Synchronization Op (Barrier ID 0)\",\n    \"description\": \"The `nvvm.barrier0` operation is a convenience operation that performs barrier \\n    synchronization and communication within a CTA (Cooperative Thread Array) using \\n    barrier ID 0. It is functionally equivalent to `nvvm.barrier` or `nvvm.barrier id=0`. \\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-bar)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.breakpoint\",\n    \"summary\": \"Breakpoint Op\",\n    \"description\": \"Breakpoint suspends execution of the program for debugging.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#miscellaneous-instructions-brkpt)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.cluster.arrive\",\n    \"summary\": \"Cluster Barrier Arrive Op\",\n    \"description\": \"The `cluster.arrive` can be used by the threads within the cluster for synchronization and\\n    communication. The `cluster.arrive` instruction marks the warps' arrival at the barrier\\n    without causing the executing thread to wait for other participating threads.\\n\\n    The `aligned` attribute, when provided, generates the .aligned version of the PTX instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-barrier-cluster)\",\n    \"attributes\": [\n      { \"name\": \"aligned\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.cluster.arrive.relaxed\",\n    \"summary\": \"Cluster Barrier Relaxed Arrive Op\",\n    \"description\": \"The `cluster.arrive` can be used by the threads within the cluster for synchronization and\\n    communication. The `cluster.arrive` instruction marks the warps' arrival at the barrier\\n    without causing the executing thread to wait for other participating threads.\\n\\n    The `aligned` attribute, when provided, generates the .aligned version of the PTX instruction.\\n    The .relaxed qualifier on `cluster.arrive` specifies that there are no memory\\n    ordering and visibility guarantees provided for the memory accesses performed prior to\\n    `cluster.arrive`.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-barrier-cluster)\",\n    \"attributes\": [\n      { \"name\": \"aligned\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.cluster.wait\",\n    \"summary\": \"Cluster Barrier Wait Op\",\n    \"description\": \"The `cluster.wait` causes the executing thread to wait for all non-exited threads\\n    of the cluster to perform `cluster.arrive`. The `aligned` attribute, when provided,\\n    generates the .aligned version of the PTX instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-barrier-cluster)\",\n    \"attributes\": [\n      { \"name\": \"aligned\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.clusterlaunchcontrol.query.cancel\",\n    \"summary\": \"Query the response of a clusterlaunchcontrol.try.cancel operation\",\n    \"description\": \"`clusterlaunchcontrol.query.cancel` queries the response of a \\n    `clusterlaunchcontrol.try.cancel` operation specified by operand \\n    `try_cancel_response`.\\n\\n    Operand `query_type` specifies the type of query to perform and can be one \\n    of the following:\\n    - `is_canceled` : Returns true if the try cancel request succeeded, \\n    and false otherwise.\\n    - `get_first_cta_id_{x/y/z}` : Returns the x, y, or z coordinate of the \\n    first CTA in the canceled cluster. Behaviour is defined only if the try \\n    cancel request succeeded. \\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-clusterlaunchcontrol-query-cancel)\",\n    \"operands\": [\n      { \"name\": \"try_cancel_response\", \"type\": \"I128\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I1, I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"query_type\", \"type\": \"ClusterLaunchControlQueryTypeAttr{is_canceled|get_first_cta_id_x|get_first_cta_id_y|get_first_cta_id_z}\" }\n    ],\n    \"assemblyFormat\": \"`query` `=` $query_type `,` $try_cancel_response attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.clusterlaunchcontrol.try.cancel\",\n    \"summary\": \"Request atomically canceling the launch of a cluster that has not started running yet\",\n    \"description\": \"`clusterlaunchcontrol.try.cancel` requests atomically canceling the launch \\n    of a cluster that has not started running yet. It asynchronously writes an \\n    opaque response to shared memory indicating whether the operation succeeded \\n    or failed.\\n\\n    Operand `smemAddress` specifies the naturally aligned address of the \\n    16-byte wide shared memory location where the request's response is written.\\n\\n    Operand `mbarrier` specifies the mbarrier object used to track the \\n    completion of the asynchronous operation.\\n\\n    If `multicast` is specified, the response is asynchronously written to the \\n    corresponding local shared memory location (specifed by `addr`) of each CTA \\n    in the requesting cluster.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-clusterlaunchcontrol-try-cancel)\",\n    \"operands\": [\n      { \"name\": \"smemAddress\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"mbarrier\", \"type\": \"LLVM_PointerShared\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multicast\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`multicast` $multicast^ `,`)? $smemAddress `,` $mbarrier attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.convert.bf16x2.to.f8x2\",\n    \"summary\": \"Convert a pair of bf16 inputs to f8x2\",\n    \"description\": \"This Op converts the given bf16 inputs in a bf16x2 vector to the specified \\n    f8 type.\\n    The result `dst` is represented as an i16 type or as a vector\\n    of two i8 types.\\n    If `dst` is returned as an i16 type, the converted values from `a`\\n    are packed such that the value converted from the first element of `a`\\n    is stored in the upper 8 bits of `dst` and the value converted from the\\n    second element of `a` is stored in the lower 8 bits of `dst`.\\n    If `dst` is returned as a vector type, each converted value is stored as an \\n    i8 element in the vector.\\n    The `rnd` and `sat` attributes specify the rounding and saturation modes \\n    respectively.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[2], [BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"AnyTypeOf<[I16, VectorOfLengthAndType<[2], [I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<SaturationModeAttr{none|satfinite|sat}, SaturationMode::NONE>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$a attr-dict `:` type($a) `->` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f16x2.to.f8x2\",\n    \"summary\": \"Convert an f16x2 input to f8x2\",\n    \"description\": \"This Op converts the given f16 inputs in an f16x2 vector to the specified \\n    f8 type.\\n    The result `dst` is represented as an i16 type or as a vector\\n    of two i8 types.\\n    If `dst` is returned as an i16 type, the converted values from `a`\\n    are packed such that the value converted from the first element of `a`\\n    is stored in the upper 8 bits of `dst` and the value converted from the\\n    second element of `a` is stored in the lower 8 bits of `dst`.\\n    If `dst` is returned as a vector type, each converted value is stored as an \\n    i8 element in the vector.\\n    The `relu` attribute, when set, lowers to the '.relu' variant of\\n    the cvt instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[2], [F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"AnyTypeOf<[I16, VectorOfLengthAndType<[2], [I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$a attr-dict `:` type($a) `->` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x2.to.bf16x2\",\n    \"summary\": \"Convert two F32 values to packed bf16x2.\",\n    \"description\": \"Converts two F32 values to packedbf16x2format with \\n    the specified rounding mode. The `src_hi` and `src_lo` parameters \\n    correspond to operands `a` and `b` in the PTX ISA, respectively.\\n    \\n    The `random_bits` parameter is required for stochastic rounding and \\n    provides the [random bits](https://docs.nvidia.com/cuda/parallel-thread-execution/#cvt-rs-rbits-layout-bf16) to be used for the conversion.\\n\\n    The `relu` attribute clamps negative results to 0.\\n\\n    The `sat` attribute determines saturation behavior.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src_hi\", \"type\": \"F32\" },\n      { \"name\": \"src_lo\", \"type\": \"F32\" },\n      { \"name\": \"random_bits\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[ 2 ], [ BF16 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<SaturationModeAttr{none|satfinite|sat}, SaturationMode::NONE>\" },\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$src_hi `,` $src_lo (`,` $random_bits^)? attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x2.to.f16x2\",\n    \"summary\": \"Convert two F32 values to packed f16x2.\",\n    \"description\": \"Converts two F32 values to packedf16x2format with \\n    the specified rounding mode. The `src_hi` and `src_lo` parameters \\n    correspond to operands `a` and `b` in the PTX ISA, respectively.\\n    \\n    The `random_bits` parameter is required for stochastic rounding and \\n    provides the [random bits](https://docs.nvidia.com/cuda/parallel-thread-execution/#cvt-rs-rbits-layout-f16) to be used for the conversion.\\n\\n    The `relu` attribute clamps negative results to 0.\\n\\n    The `sat` attribute determines saturation behavior.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src_hi\", \"type\": \"F32\" },\n      { \"name\": \"src_lo\", \"type\": \"F32\" },\n      { \"name\": \"random_bits\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[ 2 ], [ F16 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<SaturationModeAttr{none|satfinite|sat}, SaturationMode::NONE>\" },\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$src_hi `,` $src_lo (`,` $random_bits^)? attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x2.to.f4x2\",\n    \"summary\": \"Convert a pair of float inputs to f4x2\",\n    \"description\": \"This Op converts each of the given float inputs to the specified fp4 type.\\n    The result `dst` is returned as an i8 type where the converted values are \\n    packed such that the value converted from `a` is stored in the upper 4 bits \\n    of `dst` and the value converted from `b` is stored in the lower 4 bits of \\n    `dst`.\\n    The `relu` attribute, when set, lowers to the '.relu' variant of\\n    the cvt instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"F32\" },\n      { \"name\": \"b\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"I8\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x2.to.f6x2\",\n    \"summary\": \"Convert a pair of float inputs to f6x2\",\n    \"description\": \"This Op converts each of the given float inputs to the specified fp6 type.\\n    The result `dst` is represented either as an i16 type or as a vector\\n    of two i8 types.\\n    If `dst` is returned as an i16 type, the converted values are packed such \\n    that the value converted from `a` is stored in the upper 8 bits of `dst` \\n    with 2 MSB bits padded with zeros and the value converted from `b` is \\n    stored in the lower 8 bits of `dst` with 2 MSB bits padded with zeros.\\n    If `dst` is returned as a vector type, each converted value is stored as an \\n    i8 element in the vector.\\n    The `relu` attribute, when set, lowers to the '.relu' variant of\\n    the cvt instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"F32\" },\n      { \"name\": \"b\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"AnyTypeOf<[I16, VectorOfLengthAndType<[2], [I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x2.to.f8x2\",\n    \"summary\": \"Convert a pair of float inputs to f8x2\",\n    \"description\": \"This Op converts each of the given float inputs to the specified fp8 type.\\n    The result `dst` is represented as an i16 type or as a vector\\n    of two i8 types.\\n    If `dst` is returned as an i16 type, the converted values are packed such \\n    that the value converted from `a` is stored in the upper 8 bits of `dst` \\n    and the value converted from `b` is stored in the lower 8 bits of `dst`.\\n    If `dst` is returned as a vector type, each converted value is stored as an \\n    i8 element in the vector.\\n    The `rnd` and `sat` attributes specify the rounding and saturation modes respectively.\\n    The `relu` attribute, when set, lowers to the '.relu' variant of\\n    the cvt instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"F32\" },\n      { \"name\": \"b\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"AnyTypeOf<[I16, VectorOfLengthAndType<[2], [I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<SaturationModeAttr{none|satfinite|sat}, SaturationMode::NONE>\" },\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x4.to.f4x4\",\n    \"summary\": \"Convert vector<4xf32> to packed f4x4 with stochastic rounding (.rs) and satfinite\",\n    \"description\": \"Converts a vector<4xf32> to packedf4x4format using \\n    stochastic rounding (.rs) mode with SATFINITE saturation. Randomness is \\n    provided by the `rbits` parameter. The `dstTy` attribute specifies the \\n    target floating-point format. The `relu` attribute clamps negative results to 0.\\n    \\n    Note: These operations always use RS rounding mode and SATFINITE saturation mode.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[4], [F32]>\" },\n      { \"name\": \"rbits\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"I16\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $rbits attr-dict `:` type($src) `->` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x4.to.f6x4\",\n    \"summary\": \"Convert vector<4xf32> to packed f6x4 with stochastic rounding (.rs) and satfinite\",\n    \"description\": \"Converts a vector<4xf32> to packedf6x4format using \\n    stochastic rounding (.rs) mode with SATFINITE saturation. Randomness is \\n    provided by the `rbits` parameter. The `dstTy` attribute specifies the \\n    target floating-point format. The `relu` attribute clamps negative results to 0.\\n    \\n    Note: These operations always use RS rounding mode and SATFINITE saturation mode.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[4], [F32]>\" },\n      { \"name\": \"rbits\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[ 4 ], [ I8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $rbits attr-dict `:` type($src) `->` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f32x4.to.f8x4\",\n    \"summary\": \"Convert vector<4xf32> to packed f8x4 with stochastic rounding (.rs) and satfinite\",\n    \"description\": \"Converts a vector<4xf32> to packedf8x4format using \\n    stochastic rounding (.rs) mode with SATFINITE saturation. Randomness is \\n    provided by the `rbits` parameter. The `dstTy` attribute specifies the \\n    target floating-point format. The `relu` attribute clamps negative results to 0.\\n    \\n    Note: These operations always use RS rounding mode and SATFINITE saturation mode.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[4], [F32]>\" },\n      { \"name\": \"rbits\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[ 4 ], [ I8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dstTy\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $rbits attr-dict `:` type($src) `->` type($dst) `(` $dstTy `)`\"\n  },\n  {\n    \"name\": \"nvvm.convert.f4x2.to.f16x2\",\n    \"summary\": \"Convert a pair of f4 inputs to f16x2\",\n    \"description\": \"This Op converts the givenf4inputs in apacked i8tof16.\\n\\n    The result `dst` is represented as a vector off16elements.The `relu` attribute, when set, lowers to the '.relu' variant of \\n    the cvt instruction.\\\"[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I8\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"srcType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `(` $srcType `)` `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.convert.f6x2.to.f16x2\",\n    \"summary\": \"Convert a pair of f6 inputs to f16x2\",\n    \"description\": \"This Op converts the givenf6inputs in ai8x2 vectortof16.\\n\\n    The result `dst` is represented as a vector off16elements.The `relu` attribute, when set, lowers to the '.relu' variant of \\n    the cvt instruction.\\\"[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[ 2 ], [ I8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"srcType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `(` $srcType `)` `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.convert.f8x2.to.bf16x2\",\n    \"summary\": \"Convert a pair of f8 inputs to bf16x2\",\n    \"description\": \"This Op converts the givenf8inputs in ai8x2 vectortobf16.\\n\\n    The result `dst` is represented as a vector ofbf16elements.[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[ 2 ], [ I8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `(` $srcType `)` `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.convert.f8x2.to.f16x2\",\n    \"summary\": \"Convert a pair of f8 inputs to f16x2\",\n    \"description\": \"This Op converts the givenf8inputs in ai8x2 vectortof16.\\n\\n    The result `dst` is represented as a vector off16elements.The `relu` attribute, when set, lowers to the '.relu' variant of \\n    the cvt instruction.\\\"[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[ 2 ], [ I8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"srcType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `(` $srcType `)` `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.convert.float.to.tf32\",\n    \"summary\": \"Convert the given float input to TF32\",\n    \"description\": \"This Op converts the given f32 input to tf32.\\n    The result `res` is represented as an i32 type.\\n    The `relu` attribute, when set, lowers to the '.relu' variant of\\n    the cvt instruction. The `rnd` and `sat` attributes specify the\\n    the rounding and saturation modes respectively.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<SaturationModeAttr{none|satfinite|sat}, SaturationMode::NONE>\" },\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.convert.x2.to.x2\",\n    \"summary\": \"Convert a pair of  inputs to x2\",\n    \"description\": \"This Op converts the giveninputs in apacked i8to.\\n\\n    The result `dst` is represented as a vector ofelements.The `relu` attribute, when set, lowers to the '.relu' variant of \\n    the cvt instruction.\\\"[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt)\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I8\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[2]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"srcType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `(` $srcType `)` `->` type($dst)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.commit.group\",\n    \"description\": \"This Op commits all prior initiated but uncommitted cp.async.bulk\\n    instructions into a cp.async.bulk-group.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk-commit-group)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.global.shared.cta\",\n    \"summary\": \"Async bulk copy from Shared CTA memory to Global memory\",\n    \"description\": \"Initiates an asynchronous copy operation from Shared CTA memory to\\n    global memory. The 32-bit operand `size` specifies the amount of\\n    memory to be copied, in terms of number of bytes. `size` must be a\\n    multiple of 16. The `l2CacheHint` operand is optional, and it is used\\n    to specify cache eviction policy that may be used during the memory\\n    access. The `byteMask` operand is optional. The i-th bit in the 16-bit\\n    wide `byteMask` specifies whether the i-th byte of each 16-byte wide\\n    chunk of source data is copied to the destination. If the bit is set,\\n    the byte is copied.\\n\\n    Example:\\n    ```mlir\\n      nvvm.cp.async.bulk.global.shared.cta %dst, %src, %size\\n          : !llvm.ptr<1>, !llvm.ptr<3>\\n\\n      // with l2_cache_hint\\n      nvvm.cp.async.bulk.global.shared.cta %dst, %src, %size l2_cache_hint = %ch\\n          : !llvm.ptr<1>, !llvm.ptr<3>\\n\\n      // with byte_mask\\n      nvvm.cp.async.bulk.global.shared.cta %dst, %src, %size byte_mask = %mask\\n          : !llvm.ptr<1>, !llvm.ptr<3>\\n\\n      // with both l2_cache_hint and byte_mask\\n      nvvm.cp.async.bulk.global.shared.cta %dst, %src, %size l2_cache_hint = %ch byte_mask = %mask\\n          : !llvm.ptr<1>, !llvm.ptr<3>\\n    ```\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk)\",\n    \"operands\": [\n      { \"name\": \"dstMem\", \"type\": \"LLVM_PointerGlobal\" },\n      { \"name\": \"srcMem\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"byteMask\", \"type\": \"Optional<I16>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$dstMem `,` $srcMem `,` $size\\n    (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    (`byte_mask` `=` $byteMask^ )?\\n    attr-dict `:` type($dstMem) `,` type($srcMem)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.prefetch\",\n    \"summary\": \"Async bulk prefetch from global memory to L2 cache\",\n    \"description\": \"Initiates an asynchronous prefetch of data from the location\\n    specified by `srcMem` to the L2 cache.\\n\\n    The `l2CacheHint` operand is optional, and it is used to specify cache\\n    eviction policy that may be used during the memory access.\\n\\n    Example:\\n    ```mlir\\n      nvvm.cp.async.bulk.prefetch %src, %size : !llvm.ptr<1>\\n\\n      // with l2_cache_hint\\n      nvvm.cp.async.bulk.prefetch %src, %size l2_cache_hint = %ch : !llvm.ptr<1>\\n    ```\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk-prefetch)\",\n    \"operands\": [\n      { \"name\": \"srcMem\", \"type\": \"LLVM_PointerGlobal\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" }\n    ],\n    \"assemblyFormat\": \"$srcMem `,` $size (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    attr-dict  `:` type($srcMem)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.shared.cluster.global\",\n    \"summary\": \"Async bulk copy from global to Shared {cta or cluster} memory\",\n    \"description\": \"Initiates an asynchronous copy operation from global memory to shared\\n    memory or shared_cluster memory.\\n\\n    The `multicastMask` operand is optional and can be used only when the\\n    destination is shared::cluster memory. When it is present, this Op copies\\n    data from global memory to shared memory of multiple CTAs in the cluster.\\n    Operand `multicastMask` specifies the destination CTAs in the cluster such\\n    that each bit position in the 16-bit `multicastMask` operand corresponds to\\n    the `nvvm.read.ptx.sreg.ctaid` of the destination CTA. \\n\\n    The `l2CacheHint` operand is optional, and it is used to specify cache\\n    eviction policy that may be used during the memory access.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk)\",\n    \"operands\": [\n      { \"name\": \"dstMem\", \"type\": \"AnyTypeOf<[LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"srcMem\", \"type\": \"LLVM_PointerGlobal\" },\n      { \"name\": \"mbar\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"multicastMask\", \"type\": \"Optional<I16>\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$dstMem `,` $srcMem `,` $mbar `,` $size\\n    (`multicast_mask` `=` $multicastMask^ )?\\n    (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    attr-dict  `:` type($dstMem) `,` type($srcMem)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.shared.cluster.shared.cta\",\n    \"summary\": \"Async bulk copy from Shared CTA memory to Shared cluster memory\",\n    \"description\": \"Initiates an asynchronous copy operation from Shared CTA memory to Shared\\n    cluster memory.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk)\",\n    \"operands\": [\n      { \"name\": \"dstMem\", \"type\": \"LLVM_PointerSharedCluster\" },\n      { \"name\": \"srcMem\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"mbar\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"size\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$dstMem `,` $srcMem `,` $mbar `,` $size\\n    attr-dict  `:` type($dstMem) `,` type($srcMem)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.tensor.global.shared.cta\",\n    \"description\": \"Initiates an asynchronous copy of the tensor data from shared::cta\\n    memory to global memory. This Op supports all the store modes specified in\\n    `TMAStoreMode`.\\n\\n    The `l2CacheHint` operand is optional, and it is used to specify cache\\n    eviction policy that may be used during the memory access.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-cp-async-bulk-tensor)\",\n    \"operands\": [\n      { \"name\": \"tmaDescriptor\", \"type\": \"LLVM_PointerGeneric\" },\n      { \"name\": \"srcMem\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<TMAStoreModeAttr{tile|im2col|tile_scatter4}, TMAStoreMode::TILE>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$tmaDescriptor `,` \\n    $srcMem `,` \\n    `box` `[`$coordinates `]` \\n    (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    (`,` `predicate` `=` $predicate^)?\\n    attr-dict `:` type($tmaDescriptor) `,` type($srcMem)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.tensor.prefetch\",\n    \"description\": \"Initiates an asynchronous prefetch operation on the tensor data from global\\n    memory to L2 cache. This Op supports all the load modes specified in\\n    `TMALoadMode`.\\n\\n    The `l2CacheHint` operand is optional, and it is used to specify cache\\n    eviction policy that may be used during the memory access.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk-prefetch-tensor)\",\n    \"operands\": [\n      { \"name\": \"tmaDescriptor\", \"type\": \"LLVM_PointerGeneric\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"im2colOffsets\", \"type\": \"Variadic<I16>\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<TMALoadModeAttr{tile|im2col|im2col_w|im2col_w_128|tile_gather4}, TMALoadMode::TILE>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$tmaDescriptor `,`\\n    `box` `[`$coordinates `]`\\n    (`im2col` `[` $im2colOffsets^ `]` )?\\n    (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    attr-dict  `:` type($tmaDescriptor)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.tensor.reduce\",\n    \"description\": \"Initiates an asynchronous reduction operation of tensor data in\\n    global memory with tensor data in shared memory.\\n\\n    The `mode` attribute indicates whether the copy mode is tile or im2col.\\n    The `redOp` attribute specifies the reduction operations applied.\\n    The supported reduction operations are:\\n    {add, min, max, inc, dec, and, or, xor}\\n\\n    The `l2CacheHint` operand is optional, and it is used to specify cache\\n    eviction policy that may be used during the memory access.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-reduce-async-bulk-tensor)\",\n    \"operands\": [\n      { \"name\": \"tmaDescriptor\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"srcMem\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"redKind\", \"type\": \"TMAReduxKindAttr{add|max|min|inc|dec|and|or|xor}\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<TMAStoreModeAttr{tile|im2col|tile_scatter4}, TMAStoreMode::TILE>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$tmaDescriptor `,`\\n    $srcMem `,`\\n    `box` `[`$coordinates `]`\\n    (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    attr-dict  `:` type($tmaDescriptor) `,` type($srcMem)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.tensor.shared.cluster.global\",\n    \"description\": \"Initiates an asynchronous copy operation on the tensor data from global \\n    memory to shared::cluster (or) shared::cta memory. This Op supports all\\n    the load modes specified in `TMALoadMode`.\\n\\n    The `multicastMask` operand is optional. When it is present, the Op copies\\n    data from global memory to shared memory of multiple CTAs in the cluster.\\n    Operand `multicastMask` specifies the destination CTAs in the cluster such \\n    that each bit position in the 16-bit `multicastMask` operand corresponds to\\n    the `nvvm.read.ptx.sreg.ctaid` of the destination CTA.     \\n\\n    The `l2CacheHint` operand is optional, and it is used to specify cache \\n    eviction policy that may be used during the memory access.\\n    \\n    When the `isCTAOnly` attribute is set to true, the destination is\\n    shared::cta only. Hence, `multicastMask` and `CTAGroup` are not applicable\\n    when `isCTAOnly` is true.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk-tensor)\",\n    \"operands\": [\n      { \"name\": \"dstMem\", \"type\": \"AnyTypeOf<[LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"tmaDescriptor\", \"type\": \"LLVM_PointerGeneric\" },\n      { \"name\": \"coordinates\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"mbar\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"im2colOffsets\", \"type\": \"Variadic<I16>\" },\n      { \"name\": \"multicastMask\", \"type\": \"Optional<I16>\" },\n      { \"name\": \"l2CacheHint\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<TMALoadModeAttr{tile|im2col|im2col_w|im2col_w_128|tile_gather4}, TMALoadMode::TILE>\" },\n      { \"name\": \"isCTAOnly\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"group\", \"type\": \"OptionalAttr<CTAGroupKindAttr{cta_1|cta_2}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$dstMem `,` \\n    $tmaDescriptor `,` \\n    $mbar `,` \\n    `box` `[`$coordinates `]` \\n    (`im2col` `[` $im2colOffsets^ `]` )?\\n    (`multicast_mask` `=` $multicastMask^ )?\\n    (`l2_cache_hint` `=` $l2CacheHint^ )?\\n    (`predicate` `=` $predicate^)? \\n    attr-dict  `:` type($dstMem) `,` type($tmaDescriptor)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.bulk.wait_group\",\n    \"description\": \"Op waits for completion of the most recent bulk async-groups.\\n\\n    The `$group` operand tells waiting has to be done until for $group or fewer\\n    of the most recent bulk async-groups. If `$group` is 0, the op wait until \\n    all the most recent bulk async-groups have completed.\\n\\n    The `$read` indicates that the waiting has to be done until all the bulk \\n    async operations in the specified bulk async-group have completed reading \\n    from their source locations.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cp-async-bulk-wait-group)\",\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"read\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$group attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.commit.group\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.mbarrier.arrive\",\n    \"summary\": \"NVVM Dialect Op for cp.async.mbarrier.arrive\",\n    \"description\": \"The `cp.async.mbarrier.arrive` Op makes the *mbarrier object* track\\n    all prior cp.async operations initiated by the executing thread.\\n    The `addr` operand specifies the address of the *mbarrier object*\\n    in generic or shared::cta address space. When it is generic, the\\n    underlying memory should fall within the shared::cta space;\\n    otherwise the behavior is undefined. The `noinc` attr impacts\\n    how the mbarrier's state is updated.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-cp-async-mbarrier-arrive)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"noinc\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$addr attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.shared.global\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"src\", \"type\": \"LLVM_PointerGlobal\" },\n      { \"name\": \"cpSize\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I32Attr\" },\n      { \"name\": \"modifier\", \"type\": \"LoadCacheModifierAttr{ca|cg|cs|lu|cv}\" }\n    ],\n    \"assemblyFormat\": \"$dst `,` $src `,` $size `,` `cache` `=` $modifier (`,` $cpSize^)? attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.cp.async.wait.group\",\n    \"attributes\": [\n      { \"name\": \"n\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$n attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.dot.accumulate.2way\",\n    \"summary\": \"Two-way 16-bit to 8-bit dot product-accumulate instruction\",\n    \"description\": \"Performs a two-way 16-bit to 8-bit dot-product which is accumulated in a \\n    32-bit result.\\n    Operand `a` is a vector of two 16-bit elements and operand `b` a vector \\n    of four 8-bit elements between which the dot product is computed.\\n\\n    The `a_type` and `b_type` attributes specify the type of the elements in `a`\\n    and `b` respectively.\\n    If `a_type` or `b_type` is `s`, then the elements in the corresponding \\n    vector are sign-extended to 32-bit before the dot product is computed.\\n    If `a_type` or `b_type` is `u`, then the elements in the corresponding \\n    vector are zero-extended to 32-bit instead.\\n\\n    The `b_hi` boolean attribute specifies which two bytes of `b` are used for \\n    the dot product. If `b_hi` is true, then the dot product is computed \\n    between  `a` and elements at indices 2 and 3 of `b`. If `b_hi` is false, \\n    then the dot product is computed between `a` and elements at indices 0 and \\n    1 of `b`.\\n\\n    Operand `c` is a 32-bit integer to which the result is accumulated. It is\\n    treated as holding a signed integer if any of `a_type` or `b_type` is \\n    signed.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#integer-arithmetic-instructions-dp2a)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[2], [I16]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[4], [I8]>\" },\n      { \"name\": \"c\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_type\", \"type\": \"DotAccumulateTypeAttr{signed|unsigned}\" },\n      { \"name\": \"b_type\", \"type\": \"DotAccumulateTypeAttr{signed|unsigned}\" },\n      { \"name\": \"b_hi\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"$a $a_type `,` $b $b_type `,` $c attr-dict `:` type($a) `,` type($b)\"\n  },\n  {\n    \"name\": \"nvvm.dot.accumulate.4way\",\n    \"summary\": \"Four-way byte dot product-accumulate instruction\",\n    \"description\": \"Performs a four-way byte dot-product which is accumulated in a 32-bit\\n    result.\\n    Operand `a` and `b` are vectors of 4 bytes between which the dot product is \\n    computed.\\n\\n    The `a_type` and `b_type` attributes specify the type of the elements in `a`\\n    and `b` respectively.\\n    If `a_type` or `b_type` is `signed`, then the elements in the corresponding \\n    vector are sign-extended to 32-bit before the dot product is computed.\\n    If `a_type` or `b_type` is `unsigned`, then the elements in the \\n    corresponding vector are zero-extended to 32-bit instead.\\n\\n    Operand `c` is a 32-bit integer to which the result is accumulated. It is\\n    treated as holding a signed integer if any of `a_type` or `b_type` is `s8`.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#integer-arithmetic-instructions-dp4a)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[4], [I8]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[4], [I8]>\" },\n      { \"name\": \"c\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_type\", \"type\": \"DotAccumulateTypeAttr{signed|unsigned}\" },\n      { \"name\": \"b_type\", \"type\": \"DotAccumulateTypeAttr{signed|unsigned}\" }\n    ],\n    \"assemblyFormat\": \"$a $a_type `,` $b $b_type `,` $c attr-dict `:` type($a) `,` type($b)\"\n  },\n  {\n    \"name\": \"nvvm.elect.sync\",\n    \"summary\": \"Elect one leader thread\",\n    \"description\": \"The `elect.sync` instruction elects one predicated active leader\\n    thread from among a set of threads specified in the `membermask`.\\n    When the `membermask` is not provided explicitly, a default value\\n    of `0xFFFFFFFF` is used. The predicate result is set to `True` for\\n    the leader thread, and `False` for all other threads.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-elect-sync)\",\n    \"operands\": [\n      { \"name\": \"membermask\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"($membermask^)? attr-dict `->` type(results)\"\n  },\n  {\n    \"name\": \"nvvm.exit\",\n    \"summary\": \"Exit Op\",\n    \"description\": \"Ends execution of a thread.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-exit)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.mbarrier.init\",\n    \"description\": \"Fence operation that applies on the prior nvvm.mbarrier.init\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-membar)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.proxy\",\n    \"description\": \"Fence operation with proxy to establish an ordering between memory accesses\\n    that may happen through different proxies.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-membar)\",\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"ProxyKindNotTensormapOrGeneric\" },\n      { \"name\": \"space\", \"type\": \"OptionalAttr<SharedSpaceAttr{cta|cluster}>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.proxy.acquire\",\n    \"summary\": \"Uni-directional proxy fence operation with acquire semantics\",\n    \"description\": \"`fence.proxy.acquire` is a uni-directional fence used to establish ordering\\n    between a prior memory access performed via the generic proxy and a\\n    subsequent memory access performed via the tensormap proxy\\n\\n    The address operand `addr` and the operand `size` together specify the\\n    memory range `[addr, addr+size)` on which the ordering guarantees on the\\n    memory accesses across the proxies is to be provided. The only supported\\n    value for the `size` operand is 128 and must be an immediate. Generic Addressing\\n    is used unconditionally, and the address specified by the operand `addr` must\\n    fall within the `.global` state space. Otherwise, the behavior is undefined\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-membar)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_PointerGeneric\" },\n      { \"name\": \"size\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"MemScopeKindAttr{cta|cluster|gpu|sys}\" },\n      { \"name\": \"fromProxy\", \"type\": \"DefaultValuedAttr<ProxyKindAttr{alias|async|async.global|async.shared|tensormap|generic}, ProxyKind::GENERIC>\" },\n      { \"name\": \"toProxy\", \"type\": \"DefaultValuedAttr<ProxyKindAttr{alias|async|async.global|async.shared|tensormap|generic}, ProxyKind::TENSORMAP>\" }\n    ],\n    \"assemblyFormat\": \"$scope $addr `,` $size (`from_proxy` `=` $fromProxy^)? (`to_proxy` `=` $toProxy^)? attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.proxy.release\",\n    \"summary\": \"Uni-directional proxy fence operation with release semantics\",\n    \"description\": \"`fence.proxy.release` is a uni-directional fence used to establish ordering\\n    between a prior memory access performed via the generic proxy and a\\n    subsequent memory access performed via the tensormap proxy. `fence.proxy.release`\\n    operation can form a release sequence that synchronizes with an acquire\\n    sequence that contains the fence.proxy.acquire proxy fence operation\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-membar)\",\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"MemScopeKindAttr{cta|cluster|gpu|sys}\" },\n      { \"name\": \"fromProxy\", \"type\": \"DefaultValuedAttr<ProxyKindAttr{alias|async|async.global|async.shared|tensormap|generic}, ProxyKind::GENERIC>\" },\n      { \"name\": \"toProxy\", \"type\": \"DefaultValuedAttr<ProxyKindAttr{alias|async|async.global|async.shared|tensormap|generic}, ProxyKind::TENSORMAP>\" }\n    ],\n    \"assemblyFormat\": \"$scope (`from_proxy` `=` $fromProxy^)? (`to_proxy` `=` $toProxy^)? attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.proxy.sync_restrict\",\n    \"summary\": \"Uni-directional proxy fence operation with sync_restrict\",\n    \"description\": \"The `nvvm.fence.proxy.sync_restrict` Op used to establish\\n    ordering between a prior memory access performed between proxies. Currently,\\n    the ordering is only supported between async and generic proxies. `sync_restrict`\\n    restricts `acquire` memory semantics to `shared_cluster` and `release` memory\\n    semantics to `shared_cta` with cluster scope.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-membar)\",\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"MemOrderAcquireOrRelease\" },\n      { \"name\": \"fromProxy\", \"type\": \"DefaultValuedAttr<ProxyKindAttr{alias|async|async.global|async.shared|tensormap|generic}, ProxyKind::GENERIC>\" },\n      { \"name\": \"toProxy\", \"type\": \"DefaultValuedAttr<ProxyKindAttr{alias|async|async.global|async.shared|tensormap|generic}, ProxyKind::async>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.sc.cluster\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fence.sync_restrict\",\n    \"summary\": \"Uni-directional thread fence operation\",\n    \"description\": \"The `nvvm.fence.sync_restrict` Op restricts the class of memory\\n    operations for which the fence instruction provides the memory ordering guarantees.\\n    `sync_restrict` restricts `acquire` memory semantics to `shared_cluster` and\\n    `release` memory semantics to `shared_cta` with cluster scope.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-membar)\",\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"MemOrderAcquireOrRelease\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.fma\",\n    \"summary\": \"Performs floating point fused multiply-add operation with support for mixed \\n    precision operands\",\n    \"description\": \"The `nvvm.fma` operation performs floating point fused multiply-add of \\n    three operands of the same type.\\n\\n    The rounding mode is specified by the `rnd` attribute, saturation mode by \\n    the `sat` attribute, flush-to-zero by the `ftz` attribute, and ReLU by the \\n    `relu` attribute.\\n    \\n    Out-of-bounds (OOB) behavior is controlled by the `oob` attribute. `oob` \\n    clamps the result to 0 if either of the operands is `OOB NaN` (see [Tensors](https://docs.nvidia.com/cuda/parallel-thread-execution/#tensors)).\\n\\n    For more information, see PTX ISA:\\n    - [floating point fused multiply-add](https://docs.nvidia.com/cuda/parallel-thread-execution/#floating-point-instructions-fma)\\n    - [half-precision floating point fused multiply-add](https://docs.nvidia.com/cuda/parallel-thread-execution/#half-precision-floating-point-instructions-fma)\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"SIMTFloatType\" },\n      { \"name\": \"b\", \"type\": \"SIMTFloatType\" },\n      { \"name\": \"c\", \"type\": \"SIMTFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"SIMTFloatType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"ConfinedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, [EnumAttrIsOneOf<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, [FPRoundingModeNone, FPRoundingModeRM, FPRoundingModeRN, FPRoundingModeRP, FPRoundingModeRZ]>]>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<ConfinedAttr<SaturationModeAttr{none|satfinite|sat}, [EnumAttrIsOneOf<SaturationModeAttr{none|satfinite|sat}, [SaturationModeNone, SaturationModeSat]>]>, SaturationMode::NONE>\" },\n      { \"name\": \"ftz\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"oob\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` type($a)\"\n  },\n  {\n    \"name\": \"nvvm.griddepcontrol\",\n    \"description\": \"If the $kind attribute is set to `wait`, it causes the \\n    executing thread to wait until all prerequisite grids in flight \\n    have completed and all the memory operations from the prerequisite grids \\n    are performed and made visible to the current grid.\\n\\n    When the $kind is launch_dependents, it signals that specific dependents \\n    the runtime system designated to react to this instruction can be scheduled \\n    as soon as all other CTAs in the grid issue the same instruction or have \\n    completed.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-griddepcontrol)\",\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"GridDepActionAttr{wait|launch_dependents}\" }\n    ],\n    \"assemblyFormat\": \"$kind attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.inline_ptx\",\n    \"summary\": \"Inline PTX Op\",\n    \"description\": \"This op allows using PTX directly within the NVVM \\n    dialect, while greatly simplifying llvm.inline_asm generation. It \\n    automatically handles register size selection and sets the correct \\n    read/write access for each operand. The operation leverages the \\n    `BasicPtxBuilderInterface` to abstract away low-level details of \\n    PTX assembly formatting.\\n\\n    The `predicate` attribute is used to specify a predicate for the \\n    PTX instruction.\\n\\n    Example 1: Read-only Parameters\\n    ```mlir\\n    nvvm.inline_ptx \\\"mbarrier.init.b64 [$0], $1;\\\" (%barrier_gen, %count) : !llvm.ptr, i32\\n\\n    // Lowers to:\\n    llvm.inline_asm has_side_effects asm_dialect = att \\n      \\\"mbarrier.init.b64 [$0], $1;\\\", \\\"l,r\\\" %arg0, %arg2 : (!llvm.ptr, i32) -> ()\\n    ```\\n\\n    Example 2: Read-only and Write-only Parameters\\n    ```mlir\\n    %0 = nvvm.inline_ptx \\\"ex2.approx.ftz.f32 $0, $1;\\\" (%input) : f32 -> f32\\n\\n    // Lowers to:\\n    %0 = llvm.inline_asm has_side_effects asm_dialect = att \\n      \\\"ex2.approx.ftz.f32 $0, $1;\\\", \\\"=f,f\\\" %arg0 : (f32) -> f32\\n    ```\\n\\n    Example 3: Predicate Usage\\n    ```mlir\\n    nvvm.inline_ptx \\\"mbarrier.init.b64 [$0], $1;\\\" (%barrier_gen, %count), \\n      predicate = %pred : !llvm.ptr, i32, i1\\n\\n    // Lowers to:\\n    llvm.inline_asm has_side_effects asm_dialect = att \\n      \\\"@$2 mbarrier.init.b64 [$0], $1;\\\", \\\"l,r,b\\\" %arg0, %arg2, %arg3 \\n      : (!llvm.ptr, i32, i1) -> ()\\n    ```\",\n    \"operands\": [\n      { \"name\": \"readOnlyArgs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"readWriteArgs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"writeOnlyArgs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ptxCode\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$ptxCode\\n    ( `ro` `(` $readOnlyArgs^ `:` type($readOnlyArgs) `)` )?\\n    ( `rw` `(` $readWriteArgs^ `:` type($readWriteArgs) `)` )?\\n    (`,` `predicate` `=` $predicate^)? \\n    attr-dict\\n    ( `->` type($writeOnlyArgs)^ )?\"\n  },\n  {\n    \"name\": \"nvvm.ldmatrix\",\n    \"summary\": \"cooperative matrix load\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerShared\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"I32Attr\" },\n      { \"name\": \"layout\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"shape\", \"type\": \"LdStMatrixShapeAttr\" },\n      { \"name\": \"eltType\", \"type\": \"LdStMatrixEltTypeAttr{b16|b8|b8x16.b6x16_p32|b8x16.b4x16_p64}\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` functional-type($ptr, $res)\"\n  },\n  {\n    \"name\": \"nvvm.mapa\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"b\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerSharedCluster]>\" }\n    ],\n    \"assemblyFormat\": \"$a`,` $b attr-dict `:` type($a) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.match.sync\",\n    \"summary\": \"Broadcast and compare a value across threads in warp\",\n    \"description\": \"The `match.sync` op performs broadcast and compare of operand `val` across \\n    all non-exited threads in `thread_mask` and returns a mask depending on the \\n    kind and an optional predicate.\\n\\n    The matching operation kinds are:\\n    - `any`: Returns a mask corresponding to the non-exited threads in the \\n    `thread_mask` that have the same value of operand `val`.\\n    - `all`: Returns a mask and a predicate. If all non-exited threads in the \\n    `thread_mask` have the same value of operand `val`, the predicate is set to \\n    true and the mask corresponds to the non-exited threads in the \\n    `thread_mask`. Otherwise, the predicate is set to false and the mask is 0.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-match-sync)\",\n    \"operands\": [\n      { \"name\": \"thread_mask\", \"type\": \"I32\" },\n      { \"name\": \"val\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, LLVMStructType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MatchSyncKindAttr{any|all}\" }\n    ],\n    \"assemblyFormat\": \"$kind $thread_mask `,` $val attr-dict `:` type($val) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.arrive\",\n    \"summary\": \"MBarrier Arrive Operation\",\n    \"description\": \"The `nvvm.mbarrier.arrive` operation performs an arrive-on operation on the \\n    *mbarrier object* at the specified address. Uses the default `.release.cta` semantics. \\n    This release pattern establishes memory ordering for operations occurring in program \\n    order before this arrive instruction by making operations from the current thread \\n    visible to subsequent operations in other threads within the CTA. When other threads \\n    perform corresponding acquire operations (like 'mbarrier.test.wait'), they synchronize \\n    with this release pattern.\\n\\n    This operation causes the executing thread to signal its arrival at the barrier.\\n\\n    - `res`: When the `space` is not shared_cluster, this operation returns an\\n      opaque 64-bit value capturing the phase of the *mbarrier object* prior to\\n      the arrive-on operation. The contents of this return value are\\n      implementation-specific. An *mbarrier object* located in the shared_cluster\\n      space cannot return a value.\\n\\n    The operation takes the following operands:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. The `addr`\\n      must be a pointer to generic or shared_cta or shared_cluster memory. When it\\n      is generic, the underlying address must be within the shared_cta memory space;\\n      otherwise the behavior is undefined.\\n    - `count`: This specifies the amount by which the pending arrival count is\\n      decremented. If the `count` argument is not specified, the pending arrival\\n      count is decremented by 1.\\n    - `scope`: This specifies the set of threads that directly observe the memory\\n      synchronizing effect of the `mbarrier.arrive` operation.\\n    - `space`: This indicates the memory space where the mbarrier object resides.\\n    - `relaxed`: When set to true, the `arrive` operation has relaxed memory semantics\\n      and does not provide any ordering or visibility guarantees.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"count\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" },\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$addr (`,` $count^)? attr-dict `:` type($addr) (`->` type($res)^)?\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.arrive_drop\",\n    \"summary\": \"MBarrier Arrive-Drop Operation\",\n    \"description\": \"The `nvvm.mbarrier.arrive_drop` operation decrements the expected arrival\\n    count of the *mbarrier object* by `count` and then performs an arrive-on\\n    operation. When `count` is not specified, it defaults to 1. The decrement\\n    of the expected arrival count applies to all the subsequent phases of the\\n    *mbarrier object*. The remaining semantics are identical to those of the\\n    `nvvm.mbarrier.arrive` operation.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive-drop)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"count\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" },\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$addr (`,` $count^)? attr-dict `:` type($addr) (`->` type($res)^)?\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.arrive_drop.expect_tx\",\n    \"summary\": \"MBarrier arrive_drop with expected transaction count\",\n    \"description\": \"The `nvvm.mbarrier.arrive_drop.expect_tx` operation is similar to the\\n    `nvvm.mbarrier.arrive.expect_tx` operation except that it performs an\\n    `arrive_drop` operation instead of only an `arrive` operation.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive-drop)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"txcount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" },\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $txcount attr-dict `:` type(operands) (`->` type($res)^)?\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.arrive_drop.nocomplete\",\n    \"summary\": \"MBarrier Arrive-Drop No-Complete Operation\",\n    \"description\": \"The `nvvm.mbarrier.arrive_drop.nocomplete` operation decrements the expected\\n    arrival count of the *mbarrier object* by the amount `count` and then performs\\n    an arrive-on operation on the *mbarrier object* with the guarantee that it\\n    will not cause the barrier to complete its current phase.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive-drop)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"count\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $count attr-dict `:` type(operands) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.arrive.expect_tx\",\n    \"summary\": \"MBarrier Arrive with Expected Transaction Count\",\n    \"description\": \"The `nvvm.mbarrier.arrive.expect_tx` operation performs an expect-tx operation \\n    followed by an arrive-on operation on the *mbarrier object*. Uses the default \\n    `.release.cta` semantics. This release pattern establishes memory ordering for \\n    operations occurring in program order before this arrive instruction by making \\n    operations from the current thread visible to subsequent operations in other \\n    threads within the CTA. When other threads perform corresponding acquire operations \\n    (like 'mbarrier.test.wait'), they synchronize with this release pattern.\\n\\n    This operation first performs an expect-tx operation with the specified transaction\\n    count, then performs an arrive-on operation with an implicit count of 1. The\\n    expect-tx operation increases the expect-count of the *mbarrier object* by the\\n    specified value (i.e. `txcount`), setting the current phase to expect and track\\n    the completion of additional asynchronous transactions.\\n\\n    The operation takes the following operands:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. Uses generic \\n      addressing, but the address must still be in the shared memory space.\\n    - `txcount`: An unsigned integer specifying the expected transaction count \\n      for the expect-tx operation. This represents the number of asynchronous transactions \\n      expected to complete before the barrier phase completes.\\n    - `scope`: This specifies the set of threads that directly observe the memory\\n      synchronizing effect of the `mbarrier.test.wait` operation.\\n    - `relaxed`: When set to true, the `arrive` operation has relaxed memory semantics\\n      and does not provide any ordering or visibility guarantees.\\n    - `predicate`: Optional predicate for conditional execution used only when lowering to\\n      inline-ptx.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive-drop)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"txcount\", \"type\": \"I32\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" },\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $txcount (`,` `predicate` `=` $predicate^)? attr-dict `:` type(operands) (`->` type($res)^)?\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.arrive.nocomplete\",\n    \"summary\": \"MBarrier Arrive No-Complete Operation\",\n    \"description\": \"The `nvvm.mbarrier.arrive.nocomplete` operation performs an arrive-on operation \\n    on the *mbarrier object* with the guarantee that it will not cause the barrier to \\n    complete its current phase. Uses the default `.release.cta` semantics. This release \\n    pattern establishes memory ordering for operations occurring in program order before \\n    this arrive instruction by making operations from the current thread visible to \\n    subsequent operations in other threads within the CTA. When other threads perform \\n    corresponding acquire operations (like 'mbarrier.test.wait'), they synchronize with \\n    this release pattern.\\n\\n    This operation causes the executing thread to signal its arrival at the barrier \\n    with a specified count, but ensures that the barrier phase will not complete as \\n    a result of this operation. The operation returns an opaque value that \\n    captures the phase of the *mbarrier object* prior to the arrive-on operation.\\n\\n    The operation takes the following operands:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. The `addr`\\n      must be a pointer to generic or shared::cta memory. When it is generic, the\\n      underlying address must be within the shared::cta memory space; otherwise\\n      the behavior is undefined.\\n    - `count`: Integer specifying the count argument to the arrive-on operation. \\n      Must be in the valid range as specified in the *mbarrier object* contents.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"count\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $count attr-dict `:` type(operands) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.complete_tx\",\n    \"summary\": \"MBarrier complete-tx Operation\",\n    \"description\": \"The `nvvm.mbarrier.complete_tx` operation decrements the transaction\\n    count of the *mbarrier object* at `addr` by `txcount`. It also signals\\n    the completion of asynchronous transactions that were tracked by the\\n    current phase. The `scope` specifies the set of threads that can directly\\n    observe the memory synchronizing effect of the `mbarrier.complete_tx`\\n    operation. `CTA` and `CLUSTER` are the only allowed values for `scope`.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-complete-tx)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"txcount\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $txcount attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.expect_tx\",\n    \"summary\": \"MBarrier expect-tx Operation\",\n    \"description\": \"The `nvvm.mbarrier.expect_tx` operation increases the transaction count\\n    of the mbarrier located at `addr` by `txcount` amount. The `scope`\\n    specifies the set of threads that can directly observe the memory\\n    synchronizing effect of the `mbarrier.expect_tx` operation. `CTA`\\n    and `CLUSTER` are the only allowed values for `scope`.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-expect-tx)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerShared, LLVM_PointerSharedCluster]>\" },\n      { \"name\": \"txcount\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $txcount attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.init\",\n    \"summary\": \"MBarrier Initialization Op\",\n    \"description\": \"The `nvvm.mbarrier.init` operation initializes an *mbarrier object* at the specified \\n    memory location. \\n\\n    This operation initializes the *mbarrier object* with the following state:\\n    - Current phase: 0\\n    - Expected arrival count: `count`\\n    - Pending arrival count: `count`  \\n    - Transaction count (tx-count): 0\\n\\n    The operation takes the following operands:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. The `addr`\\n      must be a pointer to generic or shared::cta memory. When it is generic, the\\n      underlying address must be within the shared::cta memory space; otherwise\\n      the behavior is undefined.\\n    - `count`: Integer specifying the number of threads that will participate in barrier\\n      synchronization. Must be in the range [1, 2²⁰ - 1].\\n    - `predicate`: Optional predicate for conditional execution.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-init)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"count\", \"type\": \"I32\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $count (`,` `predicate` `=` $predicate^)? attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.inval\",\n    \"summary\": \"MBarrier Invalidation Operation\",\n    \"description\": \"The `nvvm.mbarrier.inval` operation invalidates an *mbarrier object* at the \\n    specified memory location. \\n\\n    This operation marks the *mbarrier object* as invalid, making it safe to repurpose \\n    the memory location for other uses or to reinitialize it as a new *mbarrier object*.\\n    It is undefined behavior if the *mbarrier object* is already invalid.\\n    \\n    The operation takes the following operand:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. The `addr`\\n      must be a pointer to generic or shared::cta memory. When it is generic, the\\n      underlying address must be within the shared::cta memory space; otherwise\\n      the behavior is undefined.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-inval)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" }\n    ],\n    \"assemblyFormat\": \"$addr attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.test.wait\",\n    \"summary\": \"MBarrier Non-Blocking Test Wait Operation\",\n    \"description\": \"The `nvvm.mbarrier.test.wait` operation performs a non-blocking test for the\\n    completion of a specific phase of an *mbarrier object*. It uses the default\\n    `.acquire.cta` semantics. This acquire pattern establishes memory ordering for\\n    operations occurring in program order after this wait instruction by making\\n    operations from other threads in the CTA visible to subsequent operations in the current\\n    thread. When this wait completes, it synchronizes with the corresponding release\\n    pattern from the `mbarrier.arrive` operation, establishing memory ordering within\\n    the CTA.\\n\\n    This operation tests whether the mbarrier phase specified by the state operand\\n    has completed. It is a non-blocking instruction that immediately returns the\\n    completion status without suspending the executing thread.\\n\\n    The operation takes the following operands:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. Uses generic\\n      addressing, but the address must still be in the shared memory space.\\n    - `stateOrPhase`: This argument represents a `state` when it is a 64-bit value\\n      and represents a `phase` when it is a 32-bit value. The `state` is an opaque\\n      value returned by a previous `mbarrier.arrive` operation on the same\\n      *mbarrier object* during the current or immediately preceding phase.\\n      The `phase` is an integer specifying the phase parity (0 or 1).\\n      Even phases have parity 0, odd phases have parity 1.\\n    - `scope`: This specifies the set of threads that directly observe the memory\\n      synchronizing effect of the `mbarrier.test.wait` operation.\\n    - `relaxed`: When set to true, the `arrive` operation has relaxed memory semantics\\n      and does not provide any ordering or visibility guarantees.\\n\\n    The operation returns a boolean value indicating whether the specified phase \\n    has completed:\\n    - `true`: The immediately preceding phase has completed\\n    - `false`: The phase is still incomplete (current phase)\\n\\n    **Memory ordering guarantees**: When this wait returns true, the following \\n    ordering guarantees hold:\\n\\n    1. All memory accesses (except async operations) requested prior to\\n       `mbarrier.arrive` having release semantics by participating CTA threads\\n       are visible to the executing thread.\\n    2. All `cp.async` operations requested prior to `cp.async.mbarrier.arrive`\\n       by participating CTA threads are visible to the executing thread.\\n    3. All `cp.async.bulk` operations using the same *mbarrier object* requested\\n       prior to `mbarrier.arrive` having release semantics by participating CTA\\n       threads are visible to the executing thread.\\n    4. Memory accesses requested after this wait are not visible to memory\\n       accesses performed prior to `mbarrier.arrive` by other participating\\n       threads.\\n    5. No ordering guarantee exists for memory accesses by the same thread\\n       between `mbarrier.arrive` and this wait.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-mbarrier-test-wait-try-wait)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"stateOrPhase\", \"type\": \"AnyTypeOf<[I64, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" },\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $stateOrPhase attr-dict `:` type(operands) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.try_wait\",\n    \"summary\": \"MBarrier try wait on state or phase with an optional timelimit\",\n    \"description\": \"The `nvvm.mbarrier.try_wait` operation checks whether the specified\\n    *mbarrier object* at `addr` has completed the given phase. Note that\\n    unlike the `nvvm.mbarrier.test.wait` operation, the try_wait operation\\n    is a potentially-blocking one. If the phase is not yet complete, the\\n    calling thread may be suspended. A suspended thread resumes execution\\n    once the phase completes or when a system-defined timeout occurs.\\n    Optionally, the `ticks` operand can be used to provide a custom timeout\\n    (in nanoseconds), overriding the system-defined one. The semantics of\\n    this operation and its operands are otherwise similar to those of the\\n    `nvvm.mbarrier.test.wait` Op.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-mbarrier-test-wait-try-wait)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"stateOrPhase\", \"type\": \"AnyTypeOf<[I64, I32]>\" },\n      { \"name\": \"ticks\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"DefaultValuedAttr<MemScopeKindAttr{cta|cluster|gpu|sys}, MemScopeKind::CTA>\" },\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $stateOrPhase (`,` $ticks^)? attr-dict `:` type(operands) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.mbarrier.try_wait.parity\",\n    \"summary\": \"MBarrier Potentially-Blocking Try Wait with Phase Parity\",\n    \"description\": \"The `nvvm.mbarrier.try_wait.parity` operation performs a potentially-blocking \\n    test for the completion of a specific phase of an *mbarrier object* using phase \\n    parity. It uses the default `.acquire.cta` semantics. This acquire pattern \\n    establishes memory ordering for operations occurring in program order after this \\n    wait instruction by making operations from other threads in the CTA visible to subsequent \\n    operations in the current thread. When this wait completes, it synchronizes with \\n    the corresponding release pattern from the `mbarrier.arrive` operation, establishing \\n    memory ordering within the CTA.\\n\\n    This operation waits for the completion of the mbarrier phase indicated by the \\n    phase parity. While it uses the underlying PTX `mbarrier.try_wait.parity` \\n    instruction, this MLIR operation generates a loop that enforces the test to \\n    complete before continuing execution, ensuring the barrier phase is actually \\n    completed rather than potentially timing out.\\n\\n    The operation takes the following operands:\\n    - `addr`: A pointer to the memory location of the *mbarrier object*. Uses generic \\n      addressing, but the address must still be in the shared memory space.\\n    - `phase`: An integer specifying the phase parity (0 or 1). Even phases \\n      have parity 0, odd phases have parity 1.\\n    - `ticks`: An unsigned integer specifying the suspend time hint in \\n      nanoseconds. This may be used instead of the system-dependent time limit.\\n\\n    **Memory ordering guarantees**: When this wait returns true, the following \\n    ordering guarantees hold:\\n\\n    1. All memory accesses (except async operations) requested prior to\\n       `mbarrier.arrive` having release semantics by participating CTA threads\\n       are visible to the executing thread.\\n    2. All `cp.async` operations requested prior to `cp.async.mbarrier.arrive`\\n       by participating CTA threads are visible to the executing thread.\\n    3. All `cp.async.bulk` operations using the same *mbarrier object* requested\\n       prior to `mbarrier.arrive` having release semantics by participating CTA\\n       threads are visible to the executing thread.\\n    4. Memory accesses requested after this wait are not visible to memory\\n       accesses performed prior to `mbarrier.arrive` by other participating\\n       threads.\\n    5. No ordering guarantee exists for memory accesses by the same thread\\n       between `mbarrier.arrive` and this wait.\\n\\n    **Implementation behavior**:\\n    This operation generates a PTX loop that repeatedly calls the underlying \\n    `mbarrier.try_wait.parity` instruction until the barrier phase completes. \\n    Unlike the raw PTX instruction which may return without completion after a \\n    timeout, this MLIR operation guarantees completion by continuing to loop until \\n    the specified phase is reached.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-mbarrier-test-wait-try-wait)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"phase\", \"type\": \"I32\" },\n      { \"name\": \"ticks\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $phase `,` $ticks attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.memory.barrier\",\n    \"summary\": \"Memory barrier operation\",\n    \"description\": \"`membar` operation guarantees that prior memory accesses requested by this\\n    thread are performed at the specified `scope`, before later memory\\n    operations requested by this thread following the membar instruction.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-membar)\",\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"MemScopeKindAttr{cta|cluster|gpu|sys}\" }\n    ],\n    \"assemblyFormat\": \"$scope attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.mma.block_scale\",\n    \"summary\": \"cooperative matrix-multiply and accumulate with block scaling\",\n    \"description\": \"The `nvvm.mma.block_scale` operation collectively performs the operation\\n    `D = matmul(A * SF_A, B * SF_B) + C` using all threads in a warp.\\n\\n    A, B, C and D are dense matrices and SF_A and SF_B are scaling factors.\\n    Dimensions of SF_A and SF_B are based on scale vector sizes (x1, x2, x4),\\n    and the data type must be either ue8m0 or ue4m3.\\n\\n    All the threads in the warp must execute the same `mma.block_scale` operation.\\n\\n    This operation follows the same design pattern as `nvvm.mma.sync`, with additional\\n    scaling operands for both A and B matrices.\\n\\n    Example:\\n    ```mlir\\n    %d = nvvm.mma.block_scale A[%a0, %a1] B[%b0, %b1] C[%c0, %c1]\\n                              scaleA[%scaleAData, %byteIdA, %threadIdA]\\n                              scaleB[%scaleBData, %byteIdB, %threadIdB]\\n                              {shape = #nvvm.shape<m = 16, n = 8, k = 64>,\\n                               multiplicandAPtxType = #nvvm.mma_type<e2m1>,\\n                               multiplicandBPtxType = #nvvm.mma_type<e2m1>,\\n                               scaleVecSize = #nvvm.scale_vec_size<x2>,\\n                               blockScaleFormat = #nvvm.block_scale_format<ue8m0>,\\n                               kind = #nvvm.block_scale_kind<mxf4nvf4>}\\n        : (vector<4xf16>, vector<2xf16>, vector<2xf32>) -> !llvm.struct<(f32, f32)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operandA\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandB\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandC\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"scaleAData\", \"type\": \"I32\" },\n      { \"name\": \"byteIdA\", \"type\": \"I16\" },\n      { \"name\": \"threadIdA\", \"type\": \"I16\" },\n      { \"name\": \"scaleBData\", \"type\": \"I32\" },\n      { \"name\": \"byteIdB\", \"type\": \"I16\" },\n      { \"name\": \"threadIdB\", \"type\": \"I16\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"NVVM_MMAShapeAttr\" },\n      { \"name\": \"multiplicandAPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"multiplicandBPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"scaleVecSize\", \"type\": \"ScaleVecSizeAttr{x1|x2|x4}\" },\n      { \"name\": \"blockScaleFormat\", \"type\": \"BlockScaleFormatAttr{ue8m0|ue4m3}\" },\n      { \"name\": \"kind\", \"type\": \"MMABlockScaleKindAttr{mxf8f6f4|mxf4|mxf4nvf4}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"nvvm.mma.sp.block_scale\",\n    \"summary\": \"cooperative sparse matrix-multiply and accumulate with block scaling\",\n    \"description\": \"The `nvvm.mma.sp.block_scale` operation collectively performs the operation\\n    `D = matmul(A_sparse * SF_A, B * SF_B) + C` using all threads in a warp.\\n\\n    A is a sparse matrix, and B, C and D are dense matrices.\\n    SF_A and SF_B are scaling factors.\\n    Dimensions of SF_A and SF_B are based on scale vector sizes (x1, x2, x4),\\n    and the data type must be either ue8m0 or ue4m3.\\n\\n    This operation is similar to `nvvm.mma.block_scale` but with structured sparsity\\n    in the A operand. The sparsity follows the 2:4 structured sparse pattern\\n    where 2 out of every 4 elements are non-zero.\\n\\n    All the threads in the warp must execute the same `mma.sp.block_scale` operation.\\n\\n    The `sparseMetadata` operand provides the sparsity indices that indicate\\n    which elements in the A operand are non-zero. The `sparsitySelector`\\n    controls how the indices are distributed among threads in the warp and\\n    should typically be 0 or 1.\\n\\n    This operation follows the same design pattern as `nvvm.mma.sp.sync`, with additional\\n    scaling operands for both A and B matrices. Note that sparse block scale operations\\n    always use ordered metadata (sm_90+).\\n\\n    Example:\\n    ```mlir\\n    %d = nvvm.mma.sp.block_scale A[%a0, %a1] B[%b0, %b1] C[%c0, %c1]\\n                                 sparseMetadata[%meta] selector[%sel]\\n                                 scaleA[%scaleAData, %byteIdA, %threadIdA]\\n                                 scaleB[%scaleBData, %byteIdB, %threadIdB]\\n                                 {shape = #nvvm.shape<m = 16, n = 8, k = 128>,\\n                                  multiplicandAPtxType = #nvvm.mma_type<e2m1>,\\n                                  multiplicandBPtxType = #nvvm.mma_type<e2m1>,\\n                                  scaleVecSize = #nvvm.scale_vec_size<x2>,\\n                                  blockScaleFormat = #nvvm.block_scale_format<ue8m0>,\\n                                  kind = #nvvm.block_scale_kind<mxf4>}\\n        : (vector<2xf16>, vector<2xf16>, vector<2xf32>) -> !llvm.struct<(f32, f32)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operandA\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandB\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandC\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"I32\" },\n      { \"name\": \"sparsitySelector\", \"type\": \"I32\" },\n      { \"name\": \"scaleAData\", \"type\": \"I32\" },\n      { \"name\": \"byteIdA\", \"type\": \"I16\" },\n      { \"name\": \"threadIdA\", \"type\": \"I16\" },\n      { \"name\": \"scaleBData\", \"type\": \"I32\" },\n      { \"name\": \"byteIdB\", \"type\": \"I16\" },\n      { \"name\": \"threadIdB\", \"type\": \"I16\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"NVVM_MMAShapeAttr\" },\n      { \"name\": \"multiplicandAPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"multiplicandBPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"scaleVecSize\", \"type\": \"ScaleVecSizeAttr{x1|x2|x4}\" },\n      { \"name\": \"blockScaleFormat\", \"type\": \"BlockScaleFormatAttr{ue8m0|ue4m3}\" },\n      { \"name\": \"kind\", \"type\": \"MMABlockScaleKindAttr{mxf8f6f4|mxf4|mxf4nvf4}\" },\n      { \"name\": \"orderedMetadata\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"nvvm.mma.sp.sync\",\n    \"summary\": \"cooperative sparse matrix-multiply and accumulate\",\n    \"description\": \"The `nvvm.mma.sp.sync` operation collectively performs the sparse operation\\n    `D = matmul(A_sparse, B) + C` using all threads in a warp.\\n\\n    This operation is similar to `nvvm.mma.sync` but with structured sparsity\\n    in the A operand. The sparsity follows the 2:4 structured sparse pattern\\n    where 2 out of every 4 elements are non-zero.\\n\\n    All the threads in the warp must execute the same `mma.sp.sync` operation.\\n\\n    The `sparseMetadata` operand provides the sparsity indices that indicate\\n    which elements in the A operand are non-zero. The `sparsitySelector`\\n    controls how the indices are distributed among threads in the warp and\\n    should typically be 0 or 1.\\n\\n    The optional `orderedMetadata` attribute specifies the metadata ordering:\\n    - Absence (default): Uses standard sparse metadata ordering\\n    - Presence: Uses ordered metadata (PTX ISA 8.5+, sm_90+)\\n\\n    The optional `kind` attribute specifies mixed-precision modes for FP8 operations:\\n    - `f8f6f4`: Enables e3m2, e2m3, e2m1 FP8 types and f16 accumulator (PTX ISA 8.7+, sm_90+)\\n    - Only valid with ordered metadata and m16n8k64 shape\\n\\n    The shapes, layouts, and data types follow the same constraints as the\\n    regular `nvvm.mma.sync` operation, but the A operand contains only the\\n    non-zero elements in compressed format.\\n\\n    Example:\\n    ```mlir\\n    %d = nvvm.mma.sp.sync A[%a0, %a1] B[%b0, %b1] C[%c0, %c1]\\n                          sparseMetadata[%meta] selector[%sel]\\n                          {shape = {k = 32 : i32, m = 16 : i32, n = 8 : i32}}\\n        : (vector<2xf16>, vector<2xf16>, vector<2xf16>) -> !llvm.struct<(vector<2xf16>, vector<2xf16>)>\\n\\n    // With ordered metadata:\\n    %d = nvvm.mma.sp.sync A[%a0, %a1] B[%b0, %b1] C[%c0, %c1]\\n                          sparseMetadata[%meta] selector[%sel]\\n                          {orderedMetadata, shape = {k = 32 : i32, m = 16 : i32, n = 8 : i32}}\\n        : (vector<2xf16>, vector<2xf16>, vector<2xf16>) -> !llvm.struct<(vector<2xf16>, vector<2xf16>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operandA\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandB\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandC\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"I32\" },\n      { \"name\": \"sparsitySelector\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"NVVM_MMAShapeAttr\" },\n      { \"name\": \"intOverflowBehavior\", \"type\": \"OptionalAttr<MMAIntOverflowAttr{satfinite|wrapped}>\" },\n      { \"name\": \"multiplicandAPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"multiplicandBPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"orderedMetadata\", \"type\": \"UnitAttr\" },\n      { \"name\": \"kind\", \"type\": \"OptionalAttr<MMAKindAttr{f8f6f4}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"nvvm.mma.sync\",\n    \"summary\": \"cooperative matrix-multiply and accumulate\",\n    \"description\": \"The `nvvm.mma.sync` operation collectively performs the operation\\n    `D = matmul(A, B) + C` using all threads in a warp.\\n\\n    All the threads in the warp must execute the same `mma.sync` operation.\\n\\n    For each possible multiplicand PTX data type, there are one or more possible\\n    instruction shapes given as \\\"mMnNkK\\\". The below table describes the posssibilities\\n    as well as the types required for the operands. Note that the data type for\\n    C (the accumulator) and D (the result) can vary independently when there are\\n    multiple possibilities in the \\\"C/D Type\\\" column.\\n\\n    When an optional attribute cannot be immediately inferred from the types of\\n    the operands and the result during parsing or validation, an error will be\\n    raised.\\n\\n    `b1Op` is only relevant when the binary (b1) type is given to\\n    `multiplicandDataType`. It specifies how the multiply-and-acumulate is\\n    performed and is either `xor_popc` or `and_poc`. The default is `xor_popc`.\\n\\n    `intOverflowBehavior` is only relevant when the `multiplicandType` attribute\\n    is one of `u8, s8, u4, s4`, this attribute describes how overflow is handled\\n    in the accumulator. When the attribute is `satfinite`, the accumulator values\\n    are clamped in the int32 range on overflow. This is the default behavior.\\n    Alternatively, accumulator behavior `wrapped` can also be specified, in\\n    which case overflow wraps from one end of the range to the other.\\n\\n    `layoutA` and `layoutB` are required and should generally be set to\\n    `#nvvm.mma_layout<row>` and `#nvvm.mma_layout<col>` respectively, but other\\n    combinations are possible for certain layouts according to the table below.\\n\\n    ```\\n    | A/B Type | Shape     | ALayout | BLayout | A Type   | B Type   | C/D Type          |\\n    |----------|-----------|---------|---------|----------|----------|-------------------|\\n    | f64      | .m8n8k4   | row     | col     | 1x f64   | 1x f64   | 2x f64            |\\n    | f16      | .m8n8k4   | row/col | row/col | 2x f16x2 | 2x f16x2 | 4x f16x2 or 8xf32 |\\n    |          | .m16n8k8  | row     | col     | 2x f16x2 | 1x f16x2 | 2x f16x2 or 4 f32 |\\n    |          | .m16n8k16 | row     | col     | 4x f16x2 | 2x f16x2 | 2x f16x2 or 4 f32 |\\n    | bf16     | .m16n8k8  | row     | col     | 2x i32   | 1x i32   | 4x f32            |\\n    |          | .m16n8k16 | row     | col     | 4x i32   | 2x i32   | 4x f32            |\\n    | tf32     | .m16n8k4  | row     | col     | 2x i32   | 1x i32   | 4x f32            |\\n    |          | .m16n8k8  | row     | col     | 4x i32   | 2x i32   | 2x f16x2 or 4 f32 |\\n    | u8/s8    | .m8n8k16  | row     | col     | 1x i32   | 1x i32   | 2x i32            |\\n    |          | .m16n8k16 | row     | col     | 2x i32   | 1x i32   | 4x i32            |\\n    |          | .m16n8k32 | row     | col     | 4x i32   | 2x i32   | 4x i32            |\\n    | u4/s4    | .m8n8k32  | row     | col     | 1x i32   | 1x i32   | 2x i32            |\\n    |          | m16n8k32  | row     | col     | 2x i32   | 1x i32   | 4x i32            |\\n    |          | m16n8k64  | row     | col     | 4x i32   | 2x i32   | 4x i32            |\\n    | b1       | m8n8k128  | row     | col     | 1x i32   | 1x i32   | 2x i32            |\\n    |          | m16n8k128 | row     | col     | 2x i32   | 1x i32   | 4x i32            |\\n    ```\\n\\n\\n    Example:\\n    ```mlir\\n\\n    %128 = nvvm.mma.sync A[%120, %121, %122, %123]\\n                         B[%124, %125]\\n                         C[%126, %127]\\n                         {layoutA = #nvvm.mma_layout<row>,\\n                          layoutB = #nvvm.mma_layout<col>,\\n                          shape = {k = 16 : i32, m = 16 : i32, n = 8 : i32}}\\n        : (vector<2xf16>, vector<2xf16>, vector<2xf16>)\\n           -> !llvm.struct<(vector<2xf16>, vector<2xf16>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operandA\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandB\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"operandC\", \"type\": \"Variadic<LLVM_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"NVVM_MMAShapeAttr\" },\n      { \"name\": \"b1Op\", \"type\": \"OptionalAttr<MMAB1OpAttr{none|xor_popc|and_popc}>\" },\n      { \"name\": \"intOverflowBehavior\", \"type\": \"OptionalAttr<MMAIntOverflowAttr{satfinite|wrapped}>\" },\n      { \"name\": \"layoutA\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"layoutB\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"multiplicandAPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" },\n      { \"name\": \"multiplicandBPtxType\", \"type\": \"OptionalAttr<MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"nvvm.nanosleep\",\n    \"summary\": \"Suspends the thread for a specified duration.\",\n    \"description\": \"The op suspends the thread for a sleep duration approximately close to the \\n    delay `$duration`, specified in nanoseconds. \\n\\n    The sleep duration is approximated, but guaranteed to be in the \\n    interval [0, 2*t]. The maximum sleep duration is 1 millisecond. \\n    The implementation may reduce the sleep duration for individual threads \\n    within a warp such that all sleeping threads in the warp wake up together.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#miscellaneous-instructions-nanosleep)\",\n    \"operands\": [\n      { \"name\": \"duration\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $duration\"\n  },\n  {\n    \"name\": \"nvvm.pmevent\",\n    \"summary\": \"Trigger one or more Performance Monitor events.\",\n    \"description\": \"Triggers one or more of a fixed number of performance monitor events, with\\n    event index or mask specified by immediate operand.\\n\\n    Without `mask` it triggers a single performance monitor event indexed by\\n    immediate operand a, in the range 0..15.\\n\\n    With `mask` it triggers one or more of the performance monitor events. Each\\n    bit in the 16-bit immediate operand controls an event.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#miscellaneous-instructions-pmevent)\",\n    \"attributes\": [\n      { \"name\": \"maskedEventId\", \"type\": \"OptionalAttr<I16Attr>\" },\n      { \"name\": \"eventId\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`id` `=` $eventId^)? (`mask` `=` $maskedEventId^)?\"\n  },\n  {\n    \"name\": \"nvvm.prefetch\",\n    \"summary\": \"Brings the cache line containing an address into the specified cache level\",\n    \"description\": \"Prefetches the cache line containing the address given by `addr`. The \\n    operand may be a global, local, or generic pointer. When `tensormap` is \\n    specified, the operand may instead be a constant or generic pointer. If the \\n    address maps to shared memory, the operation has no effect.\\n\\n    At most one of `cacheLevel` or `tensormap` may be present. The `cacheLevel` \\n    attribute selects the target cache level. When combined with `uniform`, the \\n    prefetch is performed to the uniform cache, in which case `addr` must be a \\n    generic pointer.\\n\\n    When `tensormap` is used, the line containing `addr` is brought from the \\n    constant or parameter state space for later use by `cp.async.bulk.tensor`. \\n    If `in_param_space` is specified, the generic pointer is interpreted as \\n    referring to the parameter state space.\\n\\n    `uniform` can be specified after the `cacheLevel` to indicate that the \\n    prefetch is performed to the specified uniform cache level. If `uniform` is \\n    specified, `addr` must be a generic address pointer and no operation is \\n    performed if `addr` maps to a `const`, `local`, or `shared` memory location.\\n\\n    The `evictPriority` attribute is optional and specifies the cache eviction\\n    priority when `cacheLevel` is L2.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-prefetch-prefetchu)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGlobal, LLVM_PointerLocal, LLVM_PointerGeneric, LLVM_PointerConst]>\" },\n      { \"name\": \"predicate\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cacheLevel\", \"type\": \"OptionalAttr<PrefetchCacheLevelAttr{L1|L2}>\" },\n      { \"name\": \"evictPriority\", \"type\": \"OptionalAttr<CacheEvictionPriorityAttr{evict_normal|evict_first|evict_last|evict_unchanged|no_allocate}>\" },\n      { \"name\": \"tensormap\", \"type\": \"UnitAttr\" },\n      { \"name\": \"uniform\", \"type\": \"UnitAttr\" },\n      { \"name\": \"in_param_space\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`level` `=` $cacheLevel^ (`uniform` $uniform^)? `,`)? (`tensormap` $tensormap^ (`in_param_space` $in_param_space^)? `,`)? (`evict_priority` `=` $evictPriority^ `,`)? $addr (`,` `predicate` `=` $predicate^)? attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.prmt\",\n    \"summary\": \"Permute bytes from two 32-bit registers\",\n    \"description\": \"The `nvvm.prmt` operation constructs a permutation of the\\n    bytes of the first one or two operands, selecting based on \\n    the 2 least significant bits of the final operand.\\n    \\n    The bytes in the first one or two source operands are numbered. \\n    The first source operand (%lo) is numbered {b3, b2, b1, b0}, \\n    in the case of the '``default``', '``f4e``' and '``b4e``' variants, \\n    the second source operand (%hi) is numbered {b7, b6, b5, b4}.\\n\\n    Modes:\\n    - `default`: Index mode         - each nibble in `selector` selects a byte from the 8-byte pool\\n    - `f4e`    : Forward 4 extract  - extracts 4 contiguous bytes starting from position in `selector`\\n    - `b4e`    : Backward 4 extract - extracts 4 contiguous bytes in reverse order\\n    - `rc8`    : Replicate 8        - replicates the lower 8 bits across the 32-bit result\\n    - `ecl`    : Edge clamp left    - clamps out-of-range indices to the leftmost valid byte\\n    - `ecr`    : Edge clamp right   - clamps out-of-range indices to the rightmost valid byte  \\n    - `rc16`   : Replicate 16       - replicates the lower 16 bits across the 32-bit result\\n\\n    Depending on the 2 least significant bits of the %selector operand, the result\\n    of the permutation is defined as follows:\\n\\n    +------------+----------------+--------------+\\n    |    Mode    | %selector[1:0] |    Output    |\\n    +------------+----------------+--------------+\\n    | '``f4e``'  | 0              | {3, 2, 1, 0} |\\n    |            +----------------+--------------+\\n    |            | 1              | {4, 3, 2, 1} |\\n    |            +----------------+--------------+\\n    |            | 2              | {5, 4, 3, 2} |\\n    |            +----------------+--------------+\\n    |            | 3              | {6, 5, 4, 3} |\\n    +------------+----------------+--------------+\\n    | '``b4e``'  | 0              | {5, 6, 7, 0} |\\n    |            +----------------+--------------+\\n    |            | 1              | {6, 7, 0, 1} |\\n    |            +----------------+--------------+\\n    |            | 2              | {7, 0, 1, 2} |\\n    |            +----------------+--------------+\\n    |            | 3              | {0, 1, 2, 3} |\\n    +------------+----------------+--------------+\\n    | '``rc8``'  | 0              | {0, 0, 0, 0} |\\n    |            +----------------+--------------+\\n    |            | 1              | {1, 1, 1, 1} |\\n    |            +----------------+--------------+\\n    |            | 2              | {2, 2, 2, 2} |\\n    |            +----------------+--------------+\\n    |            | 3              | {3, 3, 3, 3} |\\n    +------------+----------------+--------------+\\n    | '``ecl``'  | 0              | {3, 2, 1, 0} |\\n    |            +----------------+--------------+\\n    |            | 1              | {3, 2, 1, 1} |\\n    |            +----------------+--------------+\\n    |            | 2              | {3, 2, 2, 2} |\\n    |            +----------------+--------------+\\n    |            | 3              | {3, 3, 3, 3} |\\n    +------------+----------------+--------------+\\n    | '``ecr``'  | 0              | {0, 0, 0, 0} |\\n    |            +----------------+--------------+\\n    |            | 1              | {1, 1, 1, 0} |\\n    |            +----------------+--------------+\\n    |            | 2              | {2, 2, 1, 0} |\\n    |            +----------------+--------------+\\n    |            | 3              | {3, 2, 1, 0} |\\n    +------------+----------------+--------------+\\n    | '``rc16``' | 0              | {1, 0, 1, 0} |\\n    |            +----------------+--------------+\\n    |            | 1              | {3, 2, 3, 2} |\\n    |            +----------------+--------------+\\n    |            | 2              | {1, 0, 1, 0} |\\n    |            +----------------+--------------+\\n    |            | 3              | {3, 2, 3, 2} |\\n    +------------+----------------+--------------+\\n    \\n    [For more information, see PTX ISA]\\n    (https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-prmt)\",\n    \"operands\": [\n      { \"name\": \"lo\", \"type\": \"I32\" },\n      { \"name\": \"hi\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"selector\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"PermuteModeAttr{default|f4e|b4e|rc8|ecl|ecr|rc16}\" }\n    ],\n    \"assemblyFormat\": \"$mode $selector `,` $lo  (`,` $hi^)?  attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.rcp.approx.ftz.f\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.aggr.smem.size\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.clock\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.clock64\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.ctaid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.ctaid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.ctaid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.ctarank\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.nctaid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.nctaid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.nctaid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.cluster.nctarank\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.clusterid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.clusterid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.clusterid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.ctaid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.ctaid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.ctaid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.dynamic.smem.size\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg0\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg1\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg10\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg11\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg12\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg13\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg14\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg15\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg16\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg17\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg18\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg19\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg2\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg20\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg21\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg22\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg23\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg24\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg25\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg26\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg27\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg28\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg29\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg3\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg30\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg31\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg4\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg5\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg6\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg7\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg8\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.envreg9\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.globaltimer\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.globaltimer.lo\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.gridid\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.laneid\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.lanemask.eq\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.lanemask.ge\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.lanemask.gt\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.lanemask.le\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.lanemask.lt\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nclusterid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nclusterid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nclusterid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nctaid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nctaid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nctaid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nsmid\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.ntid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.ntid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.ntid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.nwarpid\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.smid\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.tid.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.tid.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.tid.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.total.smem.size\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.warpid\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.read.ptx.sreg.warpsize\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.redux.sync\",\n    \"summary\": \"Redux Sync Op\",\n    \"description\": \"`redux.sync` performs a reduction operation `kind` of the 32 bit source \\n    register across all non-exited threads in the membermask.\\n\\n    The `abs` and `nan` attributes can be used in the case of f32 input type, \\n    where the `abs` attribute causes the absolute value of the input to be used \\n    in the reduction operation, and the `nan` attribute causes the reduction \\n    operation to return NaN if any of the inputs to participating threads are \\n    NaN.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-redux-sync)\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"AnyTypeOf<[I32, F32]>\" },\n      { \"name\": \"mask_and_clamp\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"ReductionKindAttr{add|and|max|min|or|umax|umin|xor|fmin|fmax}\" },\n      { \"name\": \"abs\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"nan\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'val']>\" }\n    ],\n    \"assemblyFormat\": \"$kind $val `,` $mask_and_clamp  attr-dict `:` type($val) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.setmaxregister\",\n    \"attributes\": [\n      { \"name\": \"regCount\", \"type\": \"I32Attr\" },\n      { \"name\": \"action\", \"type\": \"SetMaxRegisterActionAttr{decrease|increase}\" }\n    ],\n    \"assemblyFormat\": \"$action $regCount attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.shfl.sync\",\n    \"summary\": \"NVVM Dialect Op for shfl.sync\",\n    \"description\": \"The `shfl.sync` Op implements data shuffle within threads of a warp.\\n    The `thread_mask` denotes the threads participating in the Op where\\n    the bit position corresponds to a particular thread's laneid.\\n    The `offset` specifies a source lane or source lane offset\\n    (depending on `kind`). The `val` is the input value to be copied from\\n    the source. The `mask_and_clamp` contains two packed values specifying\\n    a mask for logically splitting warps into sub-segments and an upper bound\\n    for clamping the source lane index.\\n    \\n    The `return_value_and_is_valid` unit attribute can be specified to indicate \\n    that the return value is a two-element struct, where the first element is \\n    the result value and the second element is a predicate indicating if the \\n    computed source lane index is valid.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-shfl-sync)\",\n    \"operands\": [\n      { \"name\": \"thread_mask\", \"type\": \"I32\" },\n      { \"name\": \"val\", \"type\": \"AnyTypeOf<[I32, F32]>\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"mask_and_clamp\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, F32, LLVMStructType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"ShflKindAttr{bfly|up|down|idx}\" },\n      { \"name\": \"return_value_and_is_valid\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$kind $thread_mask `,` $val `,` $offset `,` $mask_and_clamp  attr-dict\\n     `:` type($val) `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.st.bulk\",\n    \"summary\": \"Bulk Store Op\",\n    \"description\": \"Initializes a region of shared memory at the address given by `addr`.\\n    The `size` operand specifies the number of bytes to initialize and must be \\n    a multiple of 8.\\n    The `initVal` operand specifies the value to initialize the memory to. The \\n    only supported value is 0.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-st-bulk)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGeneric, LLVM_PointerShared]>\" },\n      { \"name\": \"size\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"initVal\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` `size` `=` $size (`,` `init` `=` $initVal^)? attr-dict `:` type($addr)\"\n  },\n  {\n    \"name\": \"nvvm.stmatrix\",\n    \"summary\": \"cooperative matrix store\",\n    \"description\": \"Collectively store one or more matrices across all threads in a warp to the\\n    location indicated by the address operand $ptr in shared memory.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#warp-level-matrix-store-instruction-stmatrix)\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerShared\" },\n      { \"name\": \"sources\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"shape\", \"type\": \"LdStMatrixShapeAttr\" },\n      { \"name\": \"eltType\", \"type\": \"LdStMatrixEltTypeAttr{b16|b8|b8x16.b6x16_p32|b8x16.b4x16_p64}\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $sources attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.subf\",\n    \"summary\": \"Performs floating point subtraction of the given arguments `lhs` and `rhs`\",\n    \"description\": \"The `nvvm.subf` operation performs floating point subtraction of two \\n    operands.\\n\\n    It supports the same type combinations and modifiers as `nvvm.addf`.\\n    This is equivalent to `nvvm.addf(lhs, -rhs)`.\\n    \\n    For more information, see PTX ISA:\\n    - [floating point subtraction](https://docs.nvidia.com/cuda/parallel-thread-execution/#floating-point-instructions-sub) \\n    - [half-precision floating point subtraction](https://docs.nvidia.com/cuda/parallel-thread-execution/#half-precision-floating-point-instructions-sub)\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SIMTFloatType\" },\n      { \"name\": \"rhs\", \"type\": \"SIMTFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"SIMTFloatType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rnd\", \"type\": \"DefaultValuedAttr<ConfinedAttr<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, [EnumAttrIsOneOf<FPRoundingModeAttr{none|rn|rm|rp|rz|rna|rs}, [FPRoundingModeNone, FPRoundingModeRM, FPRoundingModeRN, FPRoundingModeRP, FPRoundingModeRZ]>]>, FPRoundingMode::NONE>\" },\n      { \"name\": \"sat\", \"type\": \"DefaultValuedAttr<ConfinedAttr<SaturationModeAttr{none|satfinite|sat}, [EnumAttrIsOneOf<SaturationModeAttr{none|satfinite|sat}, [SaturationModeNone, SaturationModeSat]>]>, SaturationMode::NONE>\" },\n      { \"name\": \"ftz\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.alloc\",\n    \"summary\": \"Tcgen05 alloc operation\",\n    \"description\": \"The `tcgen05.alloc` Op allocates tensor core memory for\\n    the amount specified by `nCols` and writes the destination\\n    address to the `addr` argument. The `nCols` operand specifies the\\n    number of columns to be allocated and it must be a power-of-two.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-memory-alloc-manage-instructions)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_AnyPointer, LLVM_PointerShared]>\" },\n      { \"name\": \"nCols\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<CTAGroupKindAttr{cta_1|cta_2}, CTAGroupKind::CTA_1>\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $nCols attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.commit\",\n    \"summary\": \"Tcgen05 commit operations\",\n    \"description\": \"The `tcgen05.commit` makes the *mbarrier object*, specified by\\n    the operand `addr`, track the completion of all the prior\\n    async-tcgen05 operations initiated by the executing thread.\\n    The multicast variants allow signaling on the *mbarrier objects*\\n    of multiple CTAs within the cluster. Operand `multicastMask`,\\n    when present, specifies the destination CTAs in the cluster such\\n    that each bit position in the 16-bit `multicastMask` operand\\n    corresponds to the `nvvm.read.ptx.sreg.ctaid` of the destination CTA.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen-async-sync-operations-commit)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_AnyPointer, LLVM_PointerShared]>\" },\n      { \"name\": \"multicastMask\", \"type\": \"Optional<I16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<CTAGroupKindAttr{cta_1|cta_2}, CTAGroupKind::CTA_1>\" }\n    ],\n    \"assemblyFormat\": \"$addr (`,` `multicast_mask` `=` $multicastMask^)?\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.cp\",\n    \"summary\": \"Tcgen05 copy operation\",\n    \"description\": \"Instruction tcgen05.cp initiates an asynchronous copy operation from\\n    shared memory to the location specified by the address operand `taddr`\\n    in the Tensor Memory. The 64-bit register operand `smem_desc` specifies\\n    the matrix descriptor representing the source matrix in the shared memory\\n    that needs to be copied.\\n\\n    Example:\\n    ```mlir\\n      nvvm.tcgen05.cp %taddr, %smem_desc {\\n        group = #nvvm.tcgen05_group<cta_2>,\\n        shape = #nvvm.tcgen05_cp_shape<shape_64x128b>,\\n        multicast = #nvvm.tcgen05_cp_multicast<warpx2_01_23>,\\n        srcFormat = #nvvm.tcgen05_cp_src_fmt<b6x16_p32>\\n      }\\n    ```\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tensorcore-5th-generation-instructions-tcgen05-cp)\",\n    \"operands\": [\n      { \"name\": \"taddr\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"smem_desc\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"Tcgen05CpShapeAttr{shape_128x256b|shape_4x256b|shape_128x128b|shape_64x128b|shape_32x128b}\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<CTAGroupKindAttr{cta_1|cta_2}, CTAGroupKind::CTA_1>\" },\n      { \"name\": \"multicast\", \"type\": \"DefaultValuedAttr<Tcgen05CpMulticastAttr{none|warpx2_02_13|warpx2_01_23|warpx4}, Tcgen05CpMulticast::NONE>\" },\n      { \"name\": \"srcFormat\", \"type\": \"OptionalAttr<Tcgen05CpSrcFormatAttr{b6x16_p32|b4x16_p64}>\" }\n    ],\n    \"assemblyFormat\": \"$taddr`,` $smem_desc attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.dealloc\",\n    \"summary\": \"Tcgen05 dealloc operation\",\n    \"description\": \"The `tcgen05.dealloc` Op de-allocates the tensor core memory\\n    specified by `tmemAddr`, which must be from a previous tensor\\n    memory allocation. The `nCols` operand specifies the number\\n    of columns to be de-allocated, and it must be a power-of-two.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-memory-alloc-manage-instructions)\",\n    \"operands\": [\n      { \"name\": \"taddr\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"nCols\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<CTAGroupKindAttr{cta_1|cta_2}, CTAGroupKind::CTA_1>\" }\n    ],\n    \"assemblyFormat\": \"$taddr `,` $nCols attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.fence\",\n    \"summary\": \"Tcgen05 fence operations\",\n    \"description\": \"The `tcgen05.fence<before>` orders all prior async tcgen05 operations\\n    with respect to the subsequent tcgen05 and execution ordering operations.\\n    The `tcgen05.fence<after>` orders all subsequent async tcgen05 operations\\n    with respect to the prior tcgen05 and execution ordering operations.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tensorcore-5th-generation-instructions-tcgen05-fence)\",\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05FenceKindAttr{before|after}\" }\n    ],\n    \"assemblyFormat\": \"$kind attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.ld\",\n    \"summary\": \"tensor memory load instructions\",\n    \"description\": \"Instruction `tcgen05.ld` asynchronously loads data from the Tensor Memory at\\n    the location specified by the 32-bit address operand `tmemAddr` into the\\n    destination register `res`, collectively across all threads of the warps.\\n\\n    The `shape` and the `num` attribute together determines the total\\n    dimension of the data which is loaded from the Tensor Memory. The `shape`\\n    attribute indicates the base dimension of data to be accessed as described\\n    in the Data Movement Shape. The `num` attribute indicates the repeat\\n    factor on the base dimension resulting in the total dimension of the data\\n    that is accessed.\\n\\n    The shape `16x32bx2` performs two accesses into Tensor Memory of the shape\\n    `16x32b`. The base address of the first access is specified by `tmemAddr`\\n    and the base address of the second access is specified by\\n    `tmemAddr + offset`, where `offset` is an immediate argument.\\n\\n    The unit attribute `pack` can be used to pack two 16-bit\\n    elements from adjacent columns into a single 32-bit element during the load.\\n\\n    The following table describes the size of the vector for various combinations\\n    of `num` and `shape` attributes:\\n    ```\\n    |=====================================================================|\\n    | num/shape      |     16x32bx2/16x64b/32x32b |  16x128b   | 16x256b  |\\n    |=====================================================================|\\n    | x1             |          1                 |    2       |    4     |\\n    | x2             |          2                 |    4       |    8     |\\n    | x4             |          4                 |    8       |    16    |\\n    | x8             |          8                 |    16      |    32    |\\n    | x16            |          16                |    32      |    64    |\\n    | x32            |          32                |    64      |    128   |\\n    | x64            |          64                |    128     |    NA    |\\n    | x128           |          128               |    NA      |    NA    |\\n    |=====================================================================|\\n    ```\\n\\n    Example:\\n    ```mlir\\n      nvvm.tcgen05.ld %tmemAddr, %offset pack {\\n        shape = #nvvm.tcgen05_ldst_shape<shape_16x32bx2>,\\n      } : <2xi32>\\n    ```\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instructions-tcgen05-st)\",\n    \"operands\": [\n      { \"name\": \"tmemAddr\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"offset\", \"type\": \"Optional<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, VectorOfLengthAndType<[2, 4, 8, 16, 32, 64, 128], [I32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pack\", \"type\": \"UnitAttr\" },\n      { \"name\": \"shape\", \"type\": \"Tcgen05LdStShapeAttr{shape_16x64b|shape_16x128b|shape_16x256b|shape_32x32b|shape_16x32bx2}\" }\n    ],\n    \"assemblyFormat\": \"$tmemAddr (`,` $offset^)? (`pack` $pack^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.ld.red\",\n    \"summary\": \"Tcgen05 tensor memory load and reduce instructions\",\n    \"description\": \"Instruction `tcgen05.ld.red` asynchronously loads data from the Tensor\\n    Memory at the location specified by the 32-bit address operand `addr` into\\n    the destination register `data`, collectively across all threads of the\\n    warp. The operation also performs reduction operation specified by `op` on\\n    the loaded data across columns in each lane and stored into `redVal`\\n\\n    The `shape` and the `num` attribute together determines the total\\n    dimension of the data which is loaded from the Tensor Memory. The `shape`\\n    attribute indicates the base dimension of data to be accessed as described\\n    in the Data Movement Shape. The `num` attribute indicates the repeat\\n    factor on the base dimension resulting in the total dimension of the data\\n    that is accessed.\\n\\n    The shape `16x32bx2` performs two accesses into Tensor Memory of the shape\\n    `16x32b`. The base address of the first access is specified by `addr`\\n    and the base address of the second access is specified by\\n    `addr + offset`, where `offset` is an immediate argument.\\n\\n    The following table describes the size of the vector for various combinations\\n    of `num` and `shape` attributes:\\n    ```\\n    |=============================================|\\n    | num/shape      |     16x32bx2/32x32b        |\\n    |=============================================|\\n    | x2             |             2              |\\n    | x4             |             4              |\\n    | x8             |             8              |\\n    | x16            |             16             |\\n    | x32            |             32             |\\n    | x64            |             64             |\\n    | x128           |             128            |\\n    |=============================================|\\n    ```\\n\\n    Example:\\n    ```mlir\\n      %data, %redval = nvvm.tcgen05.ld,red %addr, %offset {\\n        shape = #nvvm.tcgen05_ldst_shape<shape_16x32bx2>,\\n      } : <2xi32>, i32\\n\\n      %data, %redval = nvvm.tcgen05.ld,red %addr {\\n        shape = #nvvm.tcgen05_ldst_shape<shape_32x32b>,\\n      } : <2xf32>, f32\\n    ```\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instructions-tcgen05-ld)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"offset\", \"type\": \"Optional<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"VectorOfLengthAndType<[2, 4, 8, 16, 32, 64, 128], [I32, F32]>\" },\n      { \"name\": \"redVal\", \"type\": \"AnyTypeOf<[I32, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"Tcgen05LdStShapeAttr{shape_16x64b|shape_16x128b|shape_16x256b|shape_32x32b|shape_16x32bx2}\" },\n      { \"name\": \"op\", \"type\": \"ReductionKindAttr{add|and|max|min|or|umax|umin|xor|fmin|fmax}\" },\n      { \"name\": \"abs\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nan\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$op $addr (`,` $offset^)? attr-dict `:` type($data) `,` type($redVal)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma\",\n    \"summary\": \"Performs MMA operation on 5th-gen tensor cores\",\n    \"description\": \"The `tcgen05.mma` operation is an asynchronous tensor core instruction that\\n    performs matrix multiplication, accumulation in a single fused operation. It\\n    targets 5th-generation tensor cores, providing developers with fine-grained\\n    control over execution and scheduling.\\n\\n    ```\\n    D = A * B + (D * 2^ -scaleInputD)    // if `scaleInputD` is provided\\n    D = A * B                            // if `enableInputD` is false\\n    D = A * B + D                        // otherwise\\n    ```\\n\\n    where:\\n    - A is an `M x K` matrix in tensor memory or described using shared memory descriptor\\n    - B is a `K x N` matrix described using shared memory descriptor\\n    - D is an `M x N` accumulator matrix in tensor memory\\n\\n    The `shared memory descriptor` can be generated using `tcgen05.mma_smem_desc` Op\\n\\n    - idesc is a 32-bit value representing the [Instruction Descriptor](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instruction-descriptor)\\n\\n    Optional Operands:\\n    - `scaleInputD` is an Immediate value operand used for scaling D matrix by 2 ^ (-scaleInputD). The valid range is [0, 15]\\n\\n    - `disableOutputLane` is a vector mask for selective output\\n      * vector<4 x i32> when ctaGroup is CTA_1\\n      * vector<8 x i32> when ctaGroup is CTA_2\\n\\n    Required Attributes:\\n    - `kind` is a Tcgen05MMAKind attribute\\n\\n    - `ctaGroup` specifies CTA group configuration\\n      * cta_1: MMA will be performed on the current thread's CTA\\n      * cta_2: MMA will be performed on the current thread and it's peer CTA\\n\\n    Default Attributes:\\n    - collectorOp is a Tcgen05MMACollectorOp attribute with matrix A as the collector buffer\\n\\n    - `aShift` shifts the rows of the A matrix down by one row and can only be\\n       applied if A is in tensor memory\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-mma-instructions-mma)\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"matrixA\", \"type\": \"AnyTypeOf<[LLVM_PointerTensor, I64]>\" },\n      { \"name\": \"matrixB\", \"type\": \"I64\" },\n      { \"name\": \"idesc\", \"type\": \"I32\" },\n      { \"name\": \"enableInputD\", \"type\": \"I1\" },\n      { \"name\": \"scaleInputD\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"disableOutputLane\", \"type\": \"Optional<FixedVectorOfLengthAndType<[ 4, 8 ], [ I32 ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05MMANonBlockScaleKindAttr\" },\n      { \"name\": \"ctaGroup\", \"type\": \"CTAGroupKindAttr{cta_1|cta_2}\" },\n      { \"name\": \"collectorOp\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorOpAttr{discard|lastuse|fill|use}, Tcgen05MMACollectorOp::DISCARD>\" },\n      { \"name\": \"aShift\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $matrixA `,` $matrixB `,` $idesc `,` $enableInputD (`scale` `=` $scaleInputD^)?\\n    (`mask` `=` $disableOutputLane^)? attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma_smem_desc\",\n    \"summary\": \"Constructs a Shared Memory descriptor for MMA Operands A or B\",\n    \"description\": \"The `nvvm.tcgen05_mma_smem_desc` constructs a Shared Memory descriptor\\n    for tcgen05.mma. This descriptor is a 64-bit value which describes the\\n    properties of multiplicand matrix in shared memory including its location\\n    in the shared memory of the current CTA.\\n\\n    ```\\n    +-----------+------+------------------------------------------------------+\\n    | Bit-field | Size | Description                                          |\\n    +-----------+------+------------------------------------------------------+\\n    | 0-13      | 14   | Matrix start address                                 |\\n    | 14-15     | 2    | Reserved                                             |\\n    | 16-29     | 14   | Leading dim relative-offset (or) absolute-address    |\\n    | 30-31     | 2    | Reserved                                             |\\n    | 32-45     | 14   | Stride dimension byte offset                         |\\n    | 46-48     | 3    | Fixed constant value of 0b001                        |\\n    | 49-51     | 3    | Matrix base offset                                   |\\n    | 52        | 1    | Leading dimension stride mode:                       |\\n    |           |      |   0: byte offset relative                            |\\n    |           |      |   1: byte address absolute                           |\\n    | 53-60     | 8    | Fixed constant value of 0xb00000000                  |\\n    | 61-63     | 3    | Swizzling mode:                                      |\\n    |           |      |   0: No swizzling                                    |\\n    |           |      |   1: 128-Byte with 32B atomic swizzling              |\\n    |           |      |   2: 128-Byte swizzling                              |\\n    |           |      |   4: 64-Byte swizzling                               |\\n    |           |      |   6: 32-Byte swizzling                               |\\n    |           |      |   (Values 3, 5 and 7 are invalid)                    |\\n    +-----------+------+------------------------------------------------------+    \\n    ```\\n\\n    Example:\\n    ```mlir\\n      %desc = nvvm.tcgen05.mma_smem_desc (%startAddr, %leadingDimOffset, %strideDimOffset,\\n                                          %baseOffset, %leadingDimMode, %swizzleMode) : (i32, i32, i32, i8, i1, i8) -> i64\\n    ```\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-shared-memory-descriptor)\",\n    \"operands\": [\n      { \"name\": \"startAddr\", \"type\": \"I32\" },\n      { \"name\": \"leadingDimOffset\", \"type\": \"I32\" },\n      { \"name\": \"strideDimOffset\", \"type\": \"I32\" },\n      { \"name\": \"baseOffset\", \"type\": \"I8\" },\n      { \"name\": \"leadingDimMode\", \"type\": \"I1\" },\n      { \"name\": \"swizzleMode\", \"type\": \"I8\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` `(` type(operands) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma.block_scale\",\n    \"summary\": \"Performs block scaled MMA operation on 5th-gen tensor cores\",\n    \"description\": \"The `tcgen05.mma.block_scale` operation is an asynchronous tensor core instruction\\n    that performs matrix multiplication, accumulation with block scaling in a\\n    single fused operation. It targets 5th-generation tensor cores, providing\\n    developers with fine-grained control over execution and scheduling.\\n\\n    ```\\n    D = (A * scale_a)  * (B * scale_b)`      // if `enableInputD` is false\\n    D = (A * scale_a)  * (B * scale_b) + D`\\n    ```\\n\\n    where:\\n    - A is an M x (K / 2) matrix in tensor memory or described using shared memory descriptor\\n    - B is a K x N matrix described using shared memory descriptor\\n    - D is an M x N accumulator matrix in tensor memory\\n    - `scale_a` and `scale_b` are matrices in tensor memory used to scale `A` and `B` respectively\\n\\n    The `shared memory descriptor` can be generated using `tcgen05.mma_smem_desc` Op\\n\\n    - `idesc` is a 32 bit value representing the [Instruction Descriptor](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instruction-descriptor)\\n\\n    Required Attributes:\\n    - `kind` is a Tcgen05MMAKind attribute restricted to mxf8f6f4, mxf4, or mxf4nvf4\\n\\n    - `ctaGroup` specifies CTA group configuration\\n      * cta_1: MMA will be performed on the current thread's CTA\\n      * cta_2: MMA will be performed on the current thread and it's peer CTA\\n\\n    Default Attributes:\\n    - collectorOp is a Tcgen05MMACollectorOp attribute with matrix A as the collector buffer\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-mma-instructions-mma)\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"matrixA\", \"type\": \"AnyTypeOf<[LLVM_PointerTensor, I64]>\" },\n      { \"name\": \"matrixB\", \"type\": \"I64\" },\n      { \"name\": \"idesc\", \"type\": \"I32\" },\n      { \"name\": \"enableInputD\", \"type\": \"I1\" },\n      { \"name\": \"scaleA\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"scaleB\", \"type\": \"LLVM_PointerTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05MMABlockScaleKindAttr\" },\n      { \"name\": \"ctaGroup\", \"type\": \"CTAGroupKindAttr{cta_1|cta_2}\" },\n      { \"name\": \"blockScale\", \"type\": \"DefaultValuedAttr<Tcgen05MMABlockScaleAttr{default|block16|block32}, Tcgen05MMABlockScale::DEFAULT>\" },\n      { \"name\": \"collectorOp\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorOpAttr{discard|lastuse|fill|use}, Tcgen05MMACollectorOp::DISCARD>\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $matrixA `,` $matrixB `,` $idesc `,` $enableInputD `,`\\n    $scaleA `,` $scaleB attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma.sp\",\n    \"summary\": \"Performs MMA operation with sparse A matrix on 5th-gen tensor cores\",\n    \"description\": \"The `tcgen05.mma.sp` operation is an asynchronous tensor core instruction\\n    that performs matrix multiplication, accumulation with sparse `A` matrix in\\n    a single fused operation. It targets 5th-generation tensor cores, providing\\n    developers with fine-grained control over execution and scheduling.\\n\\n    ```\\n    D = A * B + (D * 2^ -scaleInputD)    // if `scaleInputD` is provided\\n    D = A * B                            // if `enableInputD` is false\\n    D = A * B + D                        // otherwise\\n    ```\\n\\n    where:\\n    - A is an `M x (K / 2)` matrix in tensor memory or described using shared memory descriptor\\n    - B is a `K x N` matrix described using shared memory descriptor\\n    - D is an `M x N` accumulator matrix in tensor memory\\n    - sparseMetadata located in tensor memory specifies the mapping of the `K / 2`\\n    non-zero elements to the K elements before performing the MMA operation\\n\\n    Other attributes and operands are similar to that of tcgen05.mma Op\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-mma-instructions-mma-sp)\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"matrixA\", \"type\": \"AnyTypeOf<[LLVM_PointerTensor, I64]>\" },\n      { \"name\": \"matrixB\", \"type\": \"I64\" },\n      { \"name\": \"idesc\", \"type\": \"I32\" },\n      { \"name\": \"enableInputD\", \"type\": \"I1\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"scaleInputD\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"disableOutputLane\", \"type\": \"Optional<FixedVectorOfLengthAndType<[ 4, 8 ], [ I32 ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05MMANonBlockScaleKindAttr\" },\n      { \"name\": \"ctaGroup\", \"type\": \"CTAGroupKindAttr{cta_1|cta_2}\" },\n      { \"name\": \"collectorOp\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorOpAttr{discard|lastuse|fill|use}, Tcgen05MMACollectorOp::DISCARD>\" },\n      { \"name\": \"aShift\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $matrixA `,` $matrixB `,` $idesc `,` $enableInputD `,` $sparseMetadata (`scale` `=` $scaleInputD^)? (`mask` `=` $disableOutputLane^)? attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma.sp.block_scale\",\n    \"summary\": \"Performs block scaled MMA operation with sparse A matrix on 5th-gen tensor cores\",\n    \"description\": \"The `tcgen05.mma.sp.block_scale` operation is an asynchronous tensor core\\n    instruction that performs matrix multiplication, accumulation with block\\n    scaling, and sparse `A` matrix in a single fused operation. It targets\\n    5th-generation tensor cores, providing developers with fine-grained control\\n    over execution, and scheduling.\\n\\n    ```\\n    D = (A * scale_a)  * (B * scale_b)      // if `enableInputD` is specified\\n    D = (A * scale_a)  * (B * scale_b) + D  // otherwise\\n    ```\\n\\n    where:\\n    - A is an M x (K / 2) matrix in tensor memory or described using shared memory descriptor\\n    - B is a K x N matrix described using shared memory descriptor\\n    - D is an M x N accumulator matrix in tensor memory\\n    - `scale_a` and `scale_b` are matrices in tensor memory used to scale `A` and `B` respectively\\n\\n    Other attributes and operands are similar to that of tcgen05.mma.block_scale Op\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-mma-instructions-mma-sp)\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"matrixA\", \"type\": \"AnyTypeOf<[LLVM_PointerTensor, I64]>\" },\n      { \"name\": \"matrixB\", \"type\": \"I64\" },\n      { \"name\": \"idesc\", \"type\": \"I32\" },\n      { \"name\": \"enableInputD\", \"type\": \"I1\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"scaleA\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"scaleB\", \"type\": \"LLVM_PointerTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05MMABlockScaleKindAttr\" },\n      { \"name\": \"ctaGroup\", \"type\": \"CTAGroupKindAttr{cta_1|cta_2}\" },\n      { \"name\": \"blockScale\", \"type\": \"DefaultValuedAttr<Tcgen05MMABlockScaleAttr{default|block16|block32}, Tcgen05MMABlockScale::DEFAULT>\" },\n      { \"name\": \"collectorOp\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorOpAttr{discard|lastuse|fill|use}, Tcgen05MMACollectorOp::DISCARD>\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $matrixA `,` $matrixB `,` $idesc `,` $enableInputD `,`\\n    $sparseMetadata `,` $scaleA `,` $scaleB attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma.ws\",\n    \"summary\": \"Performs weight stationary convolution MMA operation on 5th-gen tensor cores\",\n    \"description\": \"The `tcgen05.mma.ws` operation is an asynchronous tensor core instruction\\n    that performs weight stationary convolution matrix multiplication, accumulation\\n    in a single fused operation. It targets 5th-generation tensor cores, providing\\n    developers with fine-grained control over execution, and scheduling.\\n\\n    ```\\n    D = A * B`      // if `enableInputD` is false\\n    D = A * B + D`  // otherwise\\n    ```\\n\\n    where:\\n    - A is an `M x K` matrix in tensor memory or described using shared memory descriptor\\n    - B is a `K x N` matrix described using shared memory descriptor\\n    - D is an `M x N` accumulator matrix in tensor memory\\n\\n    The `shared memory descriptor` can be generated using `tcgen05.mma_smem_desc` Op\\n\\n    - idesc is a 32-bit value representing the [Instruction Descriptor](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instruction-descriptor)\\n\\n    Optional Operands:\\n    - zeroColMask is a 64 bit value representing the [Zero-column mask descriptor](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-zero-column-mask-descriptor)\\n\\n    Required Attributes:\\n    - `kind` is a Tcgen05MMAKind attribute\\n\\n    Default Valued Attributes:\\n    - collectorBBuffer specifies collector buffer for matrix B: b0 (default), b1, b2, b3\\n\\n    - collectorOp is a Tcgen05MMACollectorOp attribute with matrix B as the collector buffer\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-mma-instructions-mma-ws)\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"matrixA\", \"type\": \"AnyTypeOf<[LLVM_PointerTensor, I64]>\" },\n      { \"name\": \"matrixB\", \"type\": \"I64\" },\n      { \"name\": \"idesc\", \"type\": \"I32\" },\n      { \"name\": \"enableInputD\", \"type\": \"I1\" },\n      { \"name\": \"zeroColMask\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05MMANonBlockScaleKindAttr\" },\n      { \"name\": \"collectorBBuffer\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorBBufferAttr{b0|b1|b2|b3}, Tcgen05MMACollectorBBuffer::B0>\" },\n      { \"name\": \"collectorOp\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorOpAttr{discard|lastuse|fill|use}, Tcgen05MMACollectorOp::DISCARD>\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $matrixA `,` $matrixB `,` $idesc `,` $enableInputD (`,` $zeroColMask^)?\\n    attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.mma.ws.sp\",\n    \"summary\": \"Performs weight stationary convolution MMA with sparse A matrix on 5th-gen tensor cores\",\n    \"description\": \"The `tcgen05.mma.ws.sp` operation is an asynchronous tensor core instruction\\n    that performs weight stationary convolution matrix multiplication, accumulation\\n    with sparse `A` matrix in a single fused operation. It targets 5th-generation\\n    tensor cores, providing developers with fine-grained control over execution,\\n    and scheduling.\\n\\n    ```\\n    D = A * B`      // if `enableInputD` is false\\n    D = A * B + D`  // otherwise\\n    ```\\n\\n    where:\\n    - A is an M x (K / 2) matrix in memory or descriptor format\\n    - B is a K x N matrix\\n    - D is an M x N accumulator matrix\\n    - sparseMetadata located in tensor memory specifies the mapping of the `K / 2`\\n    non-zero elements to the K elements before performing the MMA operation\\n\\n    Other attributes and operands are similar to that of tcgen05.mma.ws Op\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-mma-instructions-mma-ws-sp)\",\n    \"operands\": [\n      { \"name\": \"matrixD\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"matrixA\", \"type\": \"AnyTypeOf<[LLVM_PointerTensor, I64]>\" },\n      { \"name\": \"matrixB\", \"type\": \"I64\" },\n      { \"name\": \"idesc\", \"type\": \"I32\" },\n      { \"name\": \"enableInputD\", \"type\": \"I1\" },\n      { \"name\": \"sparseMetadata\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"zeroColMask\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05MMANonBlockScaleKindAttr\" },\n      { \"name\": \"collectorBBuffer\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorBBufferAttr{b0|b1|b2|b3}, Tcgen05MMACollectorBBuffer::B0>\" },\n      { \"name\": \"collectorOp\", \"type\": \"DefaultValuedAttr<Tcgen05MMACollectorOpAttr{discard|lastuse|fill|use}, Tcgen05MMACollectorOp::DISCARD>\" }\n    ],\n    \"assemblyFormat\": \"$matrixD `,` $matrixA `,` $matrixB `,` $idesc `,` $enableInputD `,` $sparseMetadata (`,` $zeroColMask^)? attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.relinquish_alloc_permit\",\n    \"summary\": \"Tcgen05 Op to relinquish the right to allocate\",\n    \"description\": \"The `tcgen05.relinquish_alloc_permit` Op specifies that the CTA\\n    of the executing thread is relinquishing the right to allocate\\n    Tensor Memory. So, it is illegal for a CTA to perform `tcgen05.alloc`\\n    after any of its constituent threads execute `tcgen05.relinquish_alloc_permit`.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-memory-alloc-manage-instructions)\",\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<CTAGroupKindAttr{cta_1|cta_2}, CTAGroupKind::CTA_1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.shift\",\n    \"summary\": \"Tcgen05 shift operation\",\n    \"description\": \"The `tcgen05.shift` is an asynchronous instruction which initiates\\n    the shifting of 32-byte elements downwards across all the rows,\\n    except the last, by one row. The operand `taddr` specifies the base\\n    address of the matrix in Tensor Memory whose rows must be down shifted.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instructions-tcgen05-shift)\",\n    \"operands\": [\n      { \"name\": \"taddr\", \"type\": \"LLVM_PointerTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<CTAGroupKindAttr{cta_1|cta_2}, CTAGroupKind::CTA_1>\" }\n    ],\n    \"assemblyFormat\": \"$taddr attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.st\",\n    \"summary\": \"tensor memory store instructions\",\n    \"description\": \"Instruction `tcgen05.st` asynchronously stores data from the source register `r`\\n    into the Tensor Memory at the location specified by the 32-bit address operand\\n    `tmemAddr`, collectively across all threads of the warps.\\n\\n    The `shape` and the `num` attribute together determines the total dimension of\\n    the data which is stored to the Tensor Memory. The `shape` indicates the base\\n    dimension of data to be accessed. The `num` attribute indicates the repeat\\n    factor on the base dimension resulting in the total dimension of the data that\\n    is accessed.\\n\\n    The shape `16x32bx2` performs two accesses into Tensor Memory of the shape\\n    `16x32b`. The base address of the first access is specified by `tmemAddr`\\n    and the base address of the second access is specified by\\n    `tmemAddr + offset`, where `offset` is an immediate argument.\\n\\n    The unit attribute `unpack` can be used to unpack a 32-bit element\\n    in the register into two 16-bit elements and store them in adjacent columns.\\n\\n    The following table describes the size of the vector for various combinations\\n    of `num` and `shape` attributes:\\n    ```\\n    |=====================================================================|\\n    | num/shape      |     16x32bx2/16x64b/32x32b |  16x128b   | 16x256b  |\\n    |=====================================================================|\\n    | x1             |          1                 |    2       |    4     |\\n    | x2             |          2                 |    4       |    8     |\\n    | x4             |          4                 |    8       |    16    |\\n    | x8             |          8                 |    16      |    32    |\\n    | x16            |          16                |    32      |    64    |\\n    | x32            |          32                |    64      |    128   |\\n    | x64            |          64                |    128     |    NA    |\\n    | x128           |          128               |    NA      |    NA    |\\n    |=====================================================================|\\n    ```\\n\\n    Example:\\n    ```mlir\\n      nvvm.tcgen05.st %tmemAddr, %val, %offset unpack {\\n        shape = #nvvm.tcgen05_ldst_shape<shape_16x32bx2>,\\n      } : <2xi32>\\n    ```\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instructions-tcgen05-st)\",\n    \"operands\": [\n      { \"name\": \"tmemAddr\", \"type\": \"LLVM_PointerTensor\" },\n      { \"name\": \"val\", \"type\": \"AnyTypeOf<[I32, VectorOfLengthAndType<[2, 4, 8, 16, 32, 64, 128], [I32]>]>\" },\n      { \"name\": \"offset\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"unpack\", \"type\": \"UnitAttr\" },\n      { \"name\": \"shape\", \"type\": \"Tcgen05LdStShapeAttr{shape_16x64b|shape_16x128b|shape_16x256b|shape_32x32b|shape_16x32bx2}\" }\n    ],\n    \"assemblyFormat\": \"$tmemAddr `,` $val (`,` $offset^)? (`unpack` $unpack^)? attr-dict `:` type($val)\"\n  },\n  {\n    \"name\": \"nvvm.tcgen05.wait\",\n    \"summary\": \"Tcgen05 wait operations\",\n    \"description\": \"The `tcgen05.wait<load>` causes the executing thread to block until\\n    all prior `tcgen05.ld` operations issued by the executing thread\\n    have completed. Similarly, the `tcgen05.wait<store>` causes the executing\\n    thread to block until all prior `tcgen05.st` operations issued by the\\n    executing thread have completed.\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#tcgen05-instructions-tcgen05-wait)\",\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Tcgen05WaitKindAttr{load|store}\" }\n    ],\n    \"assemblyFormat\": \"$kind attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.tensormap.replace\",\n    \"summary\": \"Modifies a field of the tensor-map object\",\n    \"description\": \"The `nvvm.tensormap.replace` replaces the specified field of the tensor-map \\n    object at the location specified by `addr` with a new value (specified by \\n    `new_value` or `new_value_attr`).\\n\\n    The `field` argument specifies the field of the tensor-map object to \\n    replace.\\n\\n    `new_value` is an `i32`/`i64` argument that specifies the new value to \\n    replace the `field` with for the `global_address`, `rank`, `box_dim`, \\n    `global_dim`, `global_stride`, and `element_stride` fields. It must be an \\n    `i64` for the `global_address` and `global_stride` fields and `i32` for the \\n    remaining fields.\\n    \\n    For `rank`, `new_value` must be one less than the desired tensor rank as \\n    this field uses zero-based numbering.\\n\\n    `new_value_attr` is an attribute that specifies the new value to replace \\n    the `field` with for the `elemtype`, `interleave_layout`, `swizzle_mode`, \\n    `swizzle_atomicity`, and `fill_mode` fields. It takes the place of \\n    `new_value` for these fields. It must be a valid attribute corresponding to \\n    the `field` type.\\n\\n    The ordinal `ord` is an immediate integer argument that specifies the \\n    ordinal of the `field` across the tensor which needs to be replaced and is \\n    required only for the `box_dim`, `global_dim`, `global_stride`, and \\n    `element_stride` fields.\\n\\n    [For more information, see PTX ISA.](https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-tensormap-replace)\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[LLVM_PointerGlobal, LLVM_PointerShared]>\" },\n      { \"name\": \"new_value\", \"type\": \"Optional<AnyTypeOf<[ I64, I32 ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"field\", \"type\": \"TensormapFieldAttr{global_address|rank|box_dim|global_dim|global_stride|element_stride|elemtype|interleave_layout|swizzle_mode|swizzle_atomicity|fill_mode}\" },\n      { \"name\": \"ord\", \"type\": \"OptionalAttr<ConfinedAttr<I32Attr, [ IntMinValue < 1 >, IntMaxValue < 5 > ]>>\" },\n      { \"name\": \"new_value_attr\", \"type\": \"OptionalAttr<TensormapFieldValueAttr>\" }\n    ],\n    \"assemblyFormat\": \"`field` `=` $field (`[` $ord^ `]`)? `,` `new_value` `=` ($new_value_attr^):($new_value)? `in` $addr attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvvm.vote.sync\",\n    \"summary\": \"Vote across thread group\",\n    \"description\": \"The `vote.sync` op will cause executing thread to wait until all non-exited\\n    threads corresponding to membermask have executed `vote.sync` with the same\\n    qualifiers and same membermask value before resuming execution.\\n\\n    The vote operation kinds are:\\n    - `any`: True if source predicate is True for some thread in membermask.\\n    - `all`: True if source predicate is True for all non-exited threads in\\n      membermask. \\n    - `uni`: True if source predicate has the same value in all non-exited\\n      threads in membermask.\\n    - `ballot`: In the ballot form, the destination result is a 32 bit integer.\\n      In this form, the predicate from each thread in membermask are copied into\\n      the corresponding bit position of the result, where the bit position\\n      corresponds to the thread's lane id.\\n\\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-vote-sync)\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"I32\" },\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"VoteSyncKindAttr{any|all|ballot|uni}\" }\n    ],\n    \"assemblyFormat\": \"$kind $mask `,` $pred attr-dict `->` type($res)\"\n  },\n  {\n    \"name\": \"nvvm.wgmma.commit.group.sync.aligned\",\n    \"description\": \"Commits all prior uncommitted warpgroup level matrix multiplication operations.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#asynchronous-warpgroup-level-matrix-instructions-wgmma-commit-group)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.wgmma.fence.aligned\",\n    \"description\": \"Enforce an ordering of register accesses between warpgroup level matrix \\n    multiplication and other operations. \\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#asynchronous-warpgroup-level-matrix-instructions-wgmma-fence)\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvvm.wgmma.mma_async\",\n    \"description\": \"The warpgroup (128 threads) level matrix multiply and accumulate operation \\n    has either of the following forms, where matrix D is called accumulator:\\n      D = A * B + D\\n      D = A * B, where the input from accumulator D is disabled.\\n\\n    Supported shapes:  \\n    ```\\n    |--------------|--------------|------------|--------------|---------------|\\n    |              |              |            |              |f16+=e4m3*e4m3 |\\n    |              |              |            |              |f16+=e5m2*e5m2 |\\n    |f32+=tf32*tf32|f16+=f16 *f16 | s32+=s8*s8 |s32 += b1 * b1|f16+=e5m2*e4m3 |\\n    |              |f32+=f16 *f16 | s32+=u8*u8 |              |f16+=e4m3*e5m2 |\\n    |              |f32+=bf16*bf16| s32+=u8*u8 |              |f16+=e4m3*e5m2 |\\n    |              |f32+=bf16*bf16| s32+=s8*u8 |              |f32+=e4m3*e4m3 |\\n    |              |              | s32+=u8*s8 |              |f32+=e5m2*e5m2 |\\n    |              |              |            |              |f32+=e4m3*e5m2 |\\n    |              |              |            |              |f32+=e4m3*e5m2 |\\n    |--------------|--------------|------------|--------------|---------------|\\n    |   .m64n8k8   |  .m64n8k16   | .m64n8k32  | .m64n8k256   | .m64n8k32     |\\n    |   .m64n16k8  |  .m64n16k16  | .m64n16k32 | .m64n16k256  | .m64n16k32    |\\n    |   .m64n24k8  |  .m64n24k16  | .m64n24k32 | .m64n24k256  | .m64n24k32    |\\n    |   .m64n32k8  |  .m64n32k16  | .m64n32k32 | .m64n32k256  | .m64n32k32    |\\n    |   .m64n40k8  |  .m64n40k16  | .m64n48k32 | .m64n48k256  | .m64n40k32    |\\n    |   .m64n48k8  |  .m64n48k16  | .m64n64k32 | .m64n64k256  | .m64n48k32    |\\n    |   .m64n56k8  |  .m64n56k16  | .m64n80k32 | .m64n80k256  | .m64n56k32    |\\n    |   .m64n64k8  |  .m64n64k16  | .m64n96k32 | .m64n96k256  | .m64n64k32    |\\n    |   .m64n72k8  |  .m64n72k16  | .m64n112k32| .m64n112k256 | .m64n72k32    |\\n    |   .m64n80k8  |  .m64n80k16  | .m64n128k32| .m64n128k256 | .m64n80k32    |\\n    |   .m64n88k8  |  .m64n88k16  | .m64n144k32| .m64n144k256 | .m64n88k32    |\\n    |   .m64n96k8  |  .m64n96k16  | .m64n160k32| .m64n160k256 | .m64n96k32    |\\n    |   .m64n104k8 |  .m64n104k16 | .m64n176k32| .m64n176k256 | .m64n104k32   |\\n    |   .m64n112k8 |  .m64n112k16 | .m64n192k32| .m64n192k256 | .m64n112k32   |\\n    |   .m64n120k8 |  .m64n120k16 | .m64n208k32| .m64n208k256 | .m64n120k32   |\\n    |   .m64n128k8 |  .m64n128k16 | .m64n224k32| .m64n224k256 | .m64n128k32   |\\n    |   .m64n136k8 |  .m64n136k16 | .m64n240k32| .m64n240k256 | .m64n136k32   |\\n    |   .m64n144k8 |  .m64n144k16 | .m64n256k32| .m64n256k256 | .m64n144k32   |\\n    |   .m64n152k8 |  .m64n152k16 |            |              | .m64n152k32   |\\n    |   .m64n160k8 |  .m64n160k16 |            |              | .m64n160k32   |\\n    |   .m64n168k8 |  .m64n168k16 |            |              | .m64n168k32   |\\n    |   .m64n176k8 |  .m64n176k16 |            |              | .m64n176k32   |\\n    |   .m64n184k8 |  .m64n184k16 |            |              | .m64n184k32   |\\n    |   .m64n192k8 |  .m64n192k16 |            |              | .m64n192k32   |\\n    |   .m64n200k8 |  .m64n200k16 |            |              | .m64n200k32   |\\n    |   .m64n208k8 |  .m64n208k16 |            |              | .m64n208k32   |\\n    |   .m64n216k8 |  .m64n216k16 |            |              | .m64n216k32   |\\n    |   .m64n224k8 |  .m64n224k16 |            |              | .m64n224k32   |\\n    |   .m64n232k8 |  .m64n232k16 |            |              | .m64n232k32   |\\n    |   .m64n240k8 |  .m64n240k16 |            |              | .m64n240k32   |\\n    |   .m64n248k8 |  .m64n248k16 |            |              | .m64n248k32   |\\n    |   .m64n256k8 |  .m64n256k16 |            |              | .m64n256k32   |\\n    |--------------|--------------|------------|--------------|---------------|\\n    ```\\n\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#asynchronous-warpgroup-level-matrix-instructions)\",\n    \"operands\": [\n      { \"name\": \"inouts\", \"type\": \"LLVM_AnyStruct\" },\n      { \"name\": \"descriptorA\", \"type\": \"I64\" },\n      { \"name\": \"descriptorB\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"NVVM_MMAShapeAttr\" },\n      { \"name\": \"typeA\", \"type\": \"WGMMATypesAttr{f16|tf32|u8|s8|b1|bf16|e4m3|e5m2|f32|s32}\" },\n      { \"name\": \"typeB\", \"type\": \"WGMMATypesAttr{f16|tf32|u8|s8|b1|bf16|e4m3|e5m2|f32|s32}\" },\n      { \"name\": \"typeD\", \"type\": \"WGMMATypesAttr{f16|tf32|u8|s8|b1|bf16|e4m3|e5m2|f32|s32}\" },\n      { \"name\": \"scaleD\", \"type\": \"WGMMAScaleOutAttr{zero|one}\" },\n      { \"name\": \"scaleA\", \"type\": \"WGMMAScaleInAttr{one|neg}\" },\n      { \"name\": \"scaleB\", \"type\": \"WGMMAScaleInAttr{one|neg}\" },\n      { \"name\": \"layoutA\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"layoutB\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"satfinite\", \"type\": \"OptionalAttr<MMAIntOverflowAttr{satfinite|wrapped}>\" }\n    ],\n    \"assemblyFormat\": \"$descriptorA `,` $descriptorB `,` $inouts `,` $shape `,`\\n      `D` `[` $typeD `,` $scaleD (`,` $satfinite^)? `]` `,`\\n      `A` `[` $typeA `,` $scaleA `,` $layoutA `]` `,` \\n      `B` `[` $typeB `,` $scaleB `,` $layoutB `]`\\n      attr-dict `:` \\n      type($inouts) `->` type($results)\"\n  },\n  {\n    \"name\": \"nvvm.wgmma.wait.group.sync.aligned\",\n    \"description\": \"Signal the completion of a preceding warpgroup operation.\\n    \\n    [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#asynchronous-warpgroup-level-matrix-instructions-wgmma-wait-group)\",\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $group\"\n  },\n  {\n    \"name\": \"nvvm.wmma.load\",\n    \"summary\": \"Warp synchronous matrix load\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"stride\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[LLVM_AnyStruct, F64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"I32Attr\" },\n      { \"name\": \"n\", \"type\": \"I32Attr\" },\n      { \"name\": \"k\", \"type\": \"I32Attr\" },\n      { \"name\": \"layout\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"eltype\", \"type\": \"MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}\" },\n      { \"name\": \"frag\", \"type\": \"MMAFragAttr{a|b|c}\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $stride attr-dict `:` functional-type($ptr, $res)\"\n  },\n  {\n    \"name\": \"nvvm.wmma.mma\",\n    \"summary\": \"Warp synchronous matrix-multiply accumulate using tensor cores.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<LLVM_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyStruct\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"I32Attr\" },\n      { \"name\": \"n\", \"type\": \"I32Attr\" },\n      { \"name\": \"k\", \"type\": \"I32Attr\" },\n      { \"name\": \"layoutA\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"layoutB\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"eltypeA\", \"type\": \"MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}\" },\n      { \"name\": \"eltypeB\", \"type\": \"MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}\" }\n    ],\n    \"assemblyFormat\": \"$args attr-dict `:` functional-type($args, $res)\"\n  },\n  {\n    \"name\": \"nvvm.wmma.store\",\n    \"summary\": \"Warp synchronous matrix store\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"args\", \"type\": \"Variadic<LLVM_Type>\" },\n      { \"name\": \"stride\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"I32Attr\" },\n      { \"name\": \"n\", \"type\": \"I32Attr\" },\n      { \"name\": \"k\", \"type\": \"I32Attr\" },\n      { \"name\": \"layout\", \"type\": \"MMALayoutAttr{row|col}\" },\n      { \"name\": \"eltype\", \"type\": \"MMATypesAttr{f16|f32|tf32|bf16|s8|u8|s32|s4|u4|b1|f64|e4m3|e5m2|e3m2|e2m3|e2m1}\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $stride `,` $args attr-dict `:` qualified(type($ptr)) `,`\\n    type($args)\"\n  },\n  {\n    \"name\": \"nvws.aref.buffer\",\n    \"summary\": \"Get buffer from aref\",\n    \"operands\": [\n      { \"name\": \"aref\", \"type\": \"NVWS_ArefType\" },\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" },\n      { \"name\": \"stage\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"buffers\", \"type\": \"Variadic<TTG_MemDescType>\" }\n    ],\n    \"assemblyFormat\": \"$aref (`[` $stage^ `]`)? `,` $token attr-dict\\n    `:` type($aref) `,` type($token) `->` type(results)\"\n  },\n  {\n    \"name\": \"nvws.aref.create\",\n    \"summary\": \"Create an asynchronous reference.\",\n    \"description\": \"Create an asynchronous reference.\\n\\n    Takes as inputs a variadic number of buffers, and returns an ARef.\\n    The inputs are expected to be array-like (i.e., Tensor, MemDesc, etc)\\n    and the first axis of the shape should match between all inputs, representing\\n    multi-buffering of the values.\",\n    \"operands\": [\n      { \"name\": \"buffers\", \"type\": \"Variadic<TTG_MemDescType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"NVWS_ArefType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'buffers', '::llvm::cast<ArefType>($_self).getBaseType()'>\" }\n    ],\n    \"assemblyFormat\": \"$buffers attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"nvws.aref.get.enter\",\n    \"summary\": \"Enter ArefGet region where the buffer can be used to read data\",\n    \"description\": \"Enter a \\\"region\\\" where you can freely read from the buffer)\\n                      These ArefGet \\\"regions\\\" can span multiple iterations.\",\n    \"operands\": [\n      { \"name\": \"aref\", \"type\": \"NVWS_ArefType\" },\n      { \"name\": \"stage\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"phase\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"buffers\", \"type\": \"Variadic<TTG_MemDescType>\" },\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$aref ( `[` $stage^ `,` $phase `]`)? attr-dict\\n    `:` type($aref) `->` type(results)\"\n  },\n  {\n    \"name\": \"nvws.aref.get.exit\",\n    \"summary\": \"Exit ArefGet region, where the buffer should no longer be used\",\n    \"description\": \"Leave the region where you can freely read from the buffer).\\n                      These ArefGet \\\"regions\\\" can span multiple iterations.\",\n    \"operands\": [\n      { \"name\": \"aref\", \"type\": \"NVWS_ArefType\" },\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" },\n      { \"name\": \"stage\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"async_ops\", \"type\": \"TypedArrayAttrBase<NVWS_AsyncOpEnum{none|tma_load|tc5mma|tmem_copy|cp_async|wgmma}>\" }\n    ],\n    \"assemblyFormat\": \"$aref (`[` $stage^ `]`)? `,` $token $async_ops attr-dict\\n    `:` type($aref) `,` type($token)\"\n  },\n  {\n    \"name\": \"nvws.aref.put.enter\",\n    \"summary\": \"Enter ArefPut region where the buffer can be used to read data\",\n    \"description\": \"Enter a \\\"region\\\" where you can freely write to the buffer)\\n                      These ArefPut \\\"regions\\\" can span multiple iterations.\",\n    \"operands\": [\n      { \"name\": \"aref\", \"type\": \"NVWS_ArefType\" },\n      { \"name\": \"stage\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"phase\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"buffers\", \"type\": \"Variadic<TTG_MemDescType>\" },\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$aref ( `[` $stage^ `,` $phase `]`)? attr-dict\\n    `:` type($aref) `->` type(results)\"\n  },\n  {\n    \"name\": \"nvws.aref.put.exit\",\n    \"summary\": \"Exit ArefPut region, where the buffer should no longer be used\",\n    \"description\": \"Leave the region where you can freely write to the buffer).\\n                      These ArefPut \\\"regions\\\" can span multiple iterations.\",\n    \"operands\": [\n      { \"name\": \"aref\", \"type\": \"NVWS_ArefType\" },\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" },\n      { \"name\": \"stage\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"async_ops\", \"type\": \"TypedArrayAttrBase<NVWS_AsyncOpEnum{none|tma_load|tc5mma|tmem_copy|cp_async|wgmma}>\" }\n    ],\n    \"assemblyFormat\": \"$aref (`[` $stage^ `]`)? `,` $token  $async_ops attr-dict\\n    `:` type($aref) `,` type($token)\"\n  },\n  {\n    \"name\": \"nvws.consumer_release\",\n    \"summary\": \"Consumer releases the token\",\n    \"description\": \"The consumer will release the token and signal the producer\\n    that the buffers are ready to be filled.\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"TensorOf<[NVWS_TokenType]>\" },\n      { \"name\": \"idx\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$token `,` $idx attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvws.consumer_wait\",\n    \"summary\": \"Consumer awaits buffer readiness\",\n    \"description\": \"The consumer will wait for the buffer to be ready\\n    to be consumed. If the buffers are not ready, the consumer will wait to be\\n    signalled by the producer which finishes filling the buffers and\\n    releases the token.\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"TensorOf<[NVWS_TokenType]>\" },\n      { \"name\": \"idx\", \"type\": \"I32\" },\n      { \"name\": \"phase\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$token `,` $idx `,` $phase attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvws.create_token\",\n    \"summary\": \"Create a token to be used for synchronizations in communication channels\",\n    \"description\": \"A token will be used by the producer and consumer to synchronize.\\n    The producer will acquire and hold the token, until it has filled the buffers,\\n    and signal the waiting consumer.\\n    The consumer will hold the token until it has consumed the buffers,\\n    and will signal the waiting producer trying to acquire the token.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[NVWS_TokenType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBuffers\", \"type\": \"I32Attr\" },\n      { \"name\": \"loadType\", \"type\": \"NVWS_TokenLoadTypeAttr{none|asyncLoadOp|tmaLoadOp|localStoreOp|TmemLoadOp}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"nvws.descriptor_gather\",\n    \"summary\": \"gather multiple rows from a descriptor into shared memory\",\n    \"description\": \"This op behaves exactly like the op with the same name in Triton Dialect, but the result of the load is stored into shared memory.\\n    The execution is still synchronous.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"x_offsets\", \"type\": \"RankedTensorOf<[I32]>\" },\n      { \"name\": \"y_offset\", \"type\": \"I32\" },\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"txCount\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $x_offsets `,` $y_offset `]` $txCount $result\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvws.descriptor_load\",\n    \"summary\": \"Load from descriptor and store into shared memory\",\n    \"description\": \"This op behaves exactly like the op with the same name in Triton Dialect, but the result of the load is stored into shared memory.\\n    The execution is still synchronous.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"txCount\", \"type\": \"I32Attr\" },\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, ::mlir::triton::EvictionPolicy::NORMAL>\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $indices `]` $txCount $result\\n    oilist(\\n      `cacheModifier` `=` $cache |\\n      `evictionPolicy` `=` $evict\\n    )\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvws.producer_acquire\",\n    \"summary\": \"Producer acquires a token to fill buffers\",\n    \"description\": \"The producer will try to acquire the token prior to filling\\n    the buffers. If the buffers are not ready to be filled, the producer will wait to be\\n    signalled by the consumer which finishes consuming the buffers and\\n    releases the token.\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"TensorOf<[NVWS_TokenType]>\" },\n      { \"name\": \"idx\", \"type\": \"I32\" },\n      { \"name\": \"phase\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$token `,` $idx `,` $phase attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvws.producer_commit\",\n    \"summary\": \"Producer commits the buffer changes\",\n    \"description\": \"The producer will release the token and signal the consumer\\n    that the buffers are ready to be consumed.\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"TensorOf<[NVWS_TokenType]>\" },\n      { \"name\": \"idx\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$token `,` $idx attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"nvws.warp_group\",\n    \"summary\": \"Container Op for Warp Specialization\",\n    \"description\": \"Higher level container for Warp Specialization Analysis.\\n\\n    Contains a variadic number warp groups, with\\n    the number of warps in each group, plus a region to hold the\\n    computation for that warp group.\\n\\n    The results of this op, if any, are those of the first region, as returned by\\n    nvws.warp_group.yield op.\\n\\n    nvws.warp_group should be lowered to ttg.warp_specialize\\n    before execution.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numWarps\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"partitionRegions\", \"type\": \"VariadicRegion<MinSizedRegion<1>>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"nvws.warp_group.return\",\n    \"summary\": \"Terminator for a warp group region\",\n    \"description\": \"Warp groups are expected to return values via referential modification\\n    of their inputs. Thus, the warp_group.return op takes no values to\\n    return from the warp group.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"nvws.warp_group.yield\",\n    \"summary\": \"yield from the first region of `nvws.warp_group`\",\n    \"description\": \"This op is equivalent to ttg.warp_yield op for ttg.warp_specialize op.\\n\\n    TODO: Decide if we should move nvws.warp_group to TritonGPU, or continue to\\n    have TritonGPU depend on NVWS. In the former case, this op can be removed.\\n    The latter one involves a circular dependency between TritonGPU and NVWS.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($values^)? attr-dict (`:` type($values)^)?\"\n  },\n  {\n    \"name\": \"omp.affinity_entry\",\n    \"summary\": \"OpenMP affinity clause entry value\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"OpenMP_PointerLikeType\" },\n      { \"name\": \"len\", \"type\": \"IntLikeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"entry\", \"type\": \"OpenMP_AffinityEntryType\" }\n    ],\n    \"assemblyFormat\": \"$addr `,` $len `:` `(` type($addr) `,` type($len) `)` `->`\\n    qualified(type($entry)) attr-dict\"\n  },\n  {\n    \"name\": \"omp.allocate_dir\",\n    \"summary\": \"allocate directive\",\n    \"description\": \"The storage for each list item that appears in the allocate directive is\\n    provided an allocation through the memory allocator.The `align` clause is used to specify the byte alignment to use for\\n    allocations associated with the construct on which the clause appears.`allocator` specifies the memory allocator to be used for allocations\\n    associated with the construct on which the clause appears.\",\n    \"operands\": [\n      { \"name\": \"varList\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator\", \"type\": \"Optional<I64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $varList `:` type($varList) `)` oilist(`align` `(` $align `)`|`allocator` `(` $allocator `)`) attr-dict\"\n  },\n  {\n    \"name\": \"omp.atomic.capture\",\n    \"summary\": \"performs an atomic capture\",\n    \"description\": \"This operation performs an atomic capture.\\n\\n    The region has the following allowed forms:\\n    ```\\n      omp.atomic.capture {\\n        omp.atomic.update ...\\n        omp.atomic.read ...\\n        omp.terminator\\n      }\\n\\n      omp.atomic.capture {\\n        omp.atomic.read ...\\n        omp.atomic.update ...\\n        omp.terminator\\n      }\\n\\n      omp.atomic.capture {\\n        omp.atomic.read ...\\n        omp.atomic.write ...\\n        omp.terminator\\n      }\\n    ````hint` is the value of hint (as specified in the hint clause). It is a\\n    compile time constant. As the name suggests, this is just a hint for\\n    optimization.`memory_order` indicates the memory ordering behavior of the construct. It\\n    can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`.\",\n    \"attributes\": [\n      { \"name\": \"hint\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"memory_order\", \"type\": \"OptionalAttr<MemoryOrderKindAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"oilist(`hint` `(` custom<SynchronizationHint>($hint) `)`|`memory_order` `(` custom<ClauseAttr>($memory_order) `)`) $region attr-dict\"\n  },\n  {\n    \"name\": \"omp.atomic.read\",\n    \"summary\": \"performs an atomic read\",\n    \"description\": \"This operation performs an atomic read.\\n\\n    The operand `x` is the address from where the value is atomically read.\\n    The operand `v` is the address where the value is stored after reading.`hint` is the value of hint (as specified in the hint clause). It is a\\n    compile time constant. As the name suggests, this is just a hint for\\n    optimization.`memory_order` indicates the memory ordering behavior of the construct. It\\n    can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"OpenMP_PointerLikeType\" },\n      { \"name\": \"v\", \"type\": \"OpenMP_PointerLikeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"hint\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"memory_order\", \"type\": \"OptionalAttr<MemoryOrderKindAttr>\" }\n    ],\n    \"assemblyFormat\": \"$v `=` $x oilist(`hint` `(` custom<SynchronizationHint>($hint) `)`|`memory_order` `(` custom<ClauseAttr>($memory_order) `)`) `:` type($v) `,` type($x) `,` $element_type attr-dict\"\n  },\n  {\n    \"name\": \"omp.atomic.update\",\n    \"summary\": \"performs an atomic update\",\n    \"description\": \"This operation performs an atomic update.\\n\\n    The operand `x` is exactly the same as the operand `x` in the OpenMP\\n    Standard (OpenMP 5.0, section 2.17.7). It is the address of the variable\\n    that is being updated. `x` is atomically read/written.\\n\\n    The region describes how to update the value of `x`. It takes the value at\\n    `x` as an input and must yield the updated value. Only the update to `x` is\\n    atomic. Generally the region must have only one instruction, but can\\n    potentially have more than one instructions too. The update is sematically\\n    similar to a compare-exchange loop based atomic update.\\n\\n    The syntax of atomic update operation is different from atomic read and\\n    atomic write operations. This is because only the host dialect knows how to\\n    appropriately update a value. For example, while generating LLVM IR, if\\n    there are no special `atomicrmw` instructions for the operation-type\\n    combination in atomic update, a compare-exchange loop is generated, where\\n    the core update operation is directly translated like regular operations by\\n    the host dialect. The front-end must handle semantic checks for allowed\\n    operations.`hint` is the value of hint (as specified in the hint clause). It is a\\n    compile time constant. As the name suggests, this is just a hint for\\n    optimization.`memory_order` indicates the memory ordering behavior of the construct. It\\n    can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"OpenMP_PointerLikeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"atomic_control\", \"type\": \"OptionalAttr<AtomicControlAttr>\" },\n      { \"name\": \"hint\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"memory_order\", \"type\": \"OptionalAttr<MemoryOrderKindAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"oilist(`hint` `(` custom<SynchronizationHint>($hint) `)`|`memory_order` `(` custom<ClauseAttr>($memory_order) `)`)$x `:` type($x) $region attr-dict\"\n  },\n  {\n    \"name\": \"omp.atomic.write\",\n    \"summary\": \"performs an atomic write\",\n    \"description\": \"This operation performs an atomic write.\\n\\n    The operand `x` is the address to where the `expr` is atomically\\n    written w.r.t. multiple threads. The evaluation of `expr` need not be\\n    atomic w.r.t. the write to address. In general, the type(x) must\\n    dereference to type(expr).`hint` is the value of hint (as specified in the hint clause). It is a\\n    compile time constant. As the name suggests, this is just a hint for\\n    optimization.`memory_order` indicates the memory ordering behavior of the construct. It\\n    can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"OpenMP_PointerLikeType\" },\n      { \"name\": \"expr\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hint\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"memory_order\", \"type\": \"OptionalAttr<MemoryOrderKindAttr>\" }\n    ],\n    \"assemblyFormat\": \"$x `=` $expr oilist(`hint` `(` custom<SynchronizationHint>($hint) `)`|`memory_order` `(` custom<ClauseAttr>($memory_order) `)`) `:` type($x) `,` type($expr) attr-dict\"\n  },\n  {\n    \"name\": \"omp.barrier\",\n    \"summary\": \"barrier construct\",\n    \"description\": \"The barrier construct specifies an explicit barrier at the point at which\\n    the construct appears.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"omp.cancel\",\n    \"summary\": \"cancel directive\",\n    \"description\": \"The cancel construct activates cancellation of the innermost enclosing\\n    region of the type specified.\",\n    \"operands\": [\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cancel_directive\", \"type\": \"CancellationConstructTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`cancellation_construct_type` `(`\\n      custom<ClauseAttr>($cancel_directive) `)` oilist(`if` `(` $if_expr `)`) attr-dict\"\n  },\n  {\n    \"name\": \"omp.cancellation_point\",\n    \"summary\": \"cancellation point directive\",\n    \"description\": \"The cancellation point construct introduces a user-defined cancellation\\n    point at which implicit or explicit tasks check if cancellation of the\\n    innermost enclosing region of the type specified has been activated.\",\n    \"attributes\": [\n      { \"name\": \"cancel_directive\", \"type\": \"CancellationConstructTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`cancellation_construct_type` `(`\\n      custom<ClauseAttr>($cancel_directive) `)`  attr-dict\"\n  },\n  {\n    \"name\": \"omp.canonical_loop\",\n    \"summary\": \"OpenMP Canonical Loop Operation\",\n    \"description\": \"All loops that conform to OpenMP's definition of a canonical loop can be\\n    simplified to a CanonicalLoopOp. In particular, there are no loop-carried\\n    variables and the number of iterations it will execute is known before the\\n    operation. This allows e.g. to determine the number of threads and chunks\\n    the iterations space is split into before executing any iteration. More\\n    restrictions may apply in cases such as (collapsed) loop nests, doacross\\n    loops, etc.\\n\\n    In contrast to other loop operations such as `scf.for`, the number of\\n    iterations is determined by only a single variable, the trip-count. The\\n    induction variable value is the logical iteration number of that iteration,\\n    which OpenMP defines to be between 0 and the trip-count (exclusive).\\n    Loop representation having lower-bound, upper-bound, and step-size operands,\\n    require passes to do more work than necessary, including handling special\\n    cases such as upper-bound smaller than lower-bound, upper-bound equal to\\n    the integer type's maximal value, negative step size, etc. This complexity\\n    is better only handled once by the front-end and can apply its semantics\\n    for such cases while still being able to represent any kind of loop, which\\n    kind of the point of a mid-end intermediate representation. User-defined\\n    types such as random-access iterators in C++ could not directly be\\n    represented anyway.\\n\\n    The induction variable is always of the same type as the tripcount argument.\\n    Since it can never be negative, tripcount is always interpreted as an\\n    unsigned integer. It is the caller's responsibility to ensure the tripcount\\n    is not negative when its interpretation is signed, i.e.\\n    `%tripcount = max(0,%tripcount)`.\\n\\n    An optional argument to a omp.canonical_loop that can be passed in\\n    is a CanonicalLoopInfo value that can be used to refer to the canonical\\n    loop to apply transformations -- such as tiling, unrolling, or\\n    work-sharing -- to the loop, similar to the transform dialect but\\n    with OpenMP-specific semantics. Because it is optional, it has to be the\\n    last of the operands, but appears first in the pretty format printing.\\n\\n    The pretty assembly format is inspired by python syntax, where `range(n)`\\n    returns an iterator that runs from $0$ to $n-1$. The pretty assembly syntax\\n    is one of:\\n\\n     omp.canonical_loop(%cli) %iv : !type in range(%tripcount)\\n     omp.canonical_loop       %iv : !type in range(%tripcount)\\n\\n    A CanonicalLoopOp is lowered to LLVM-IR using\\n    `OpenMPIRBuilder::createCanonicalLoop`.\\n\\n    #### Examples\\n\\n    Translation from lower-bound, upper-bound, step-size to trip-count.\\n    ```c\\n    for (int i = 3; i < 42; i+=2) {\\n      B[i] = A[i];\\n    }\\n    ```\\n\\n    ```mlir\\n    %lb = arith.constant 3 : i32\\n    %ub = arith.constant 42 : i32\\n    %step = arith.constant 2 : i32\\n    %range = arith.sub %ub, %lb : i32\\n    %tripcount = arith.div %range, %step : i32\\n    omp.canonical_loop %iv : i32 in range(%tripcount) {\\n      %offset = arith.mul %iv, %step : i32\\n      %i = arith.add %offset, %lb : i32\\n      %a = load %arrA[%i] : memref<?xf32>\\n      store %a, %arrB[%i] : memref<?xf32>\\n    }\\n    ```\\n\\n    Nested canonical loop with transformation of the inner loop.\\n    ```mlir\\n    %outer = omp.new_cli : !omp.cli\\n    %inner = omp.new_cli : !omp.cli\\n    omp.canonical_loop(%outer) %iv1 : i32 in range(%tc1) {\\n      omp.canonical_loop(%inner) %iv2 : i32 in range(%tc2) {\\n        %a = load %arrA[%iv1, %iv2] : memref<?x?xf32>\\n        store %a, %arrB[%iv1, %iv2] : memref<?x?xf32>\\n      }\\n    }\\n    omp.unroll_full(%inner)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tripCount\", \"type\": \"IntLikeType\" },\n      { \"name\": \"cli\", \"type\": \"Optional<CanonicalLoopInfoType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"omp.critical\",\n    \"summary\": \"critical construct\",\n    \"description\": \"The critical construct imposes a restriction on the associated structured\\n    block (region) to be executed by only a single thread at a time.\\n\\n    The optional `name` argument of critical constructs is used to identify\\n    them. Unnamed critical constructs behave as though an identical name was\\n    specified.\",\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"(`(` $name^ `)`)? $region attr-dict\"\n  },\n  {\n    \"name\": \"omp.critical.declare\",\n    \"summary\": \"declares a named critical section.\",\n    \"description\": \"Declares a named critical section.The `sym_name` can be used in `omp.critical` constructs in the dialect.`hint` is the value of hint (as specified in the hint clause). It is a\\n    compile time constant. As the name suggests, this is just a hint for\\n    optimization.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"hint\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name oilist(`hint` `(` custom<SynchronizationHint>($hint) `)`) attr-dict\"\n  },\n  {\n    \"name\": \"omp.declare_mapper\",\n    \"summary\": \"declare mapper directive\",\n    \"description\": \"The declare mapper directive declares a user-defined mapper for a given\\n    type, and defines a mapper-identifier that can be used in a map clause.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `:` $type $body attr-dict\"\n  },\n  {\n    \"name\": \"omp.declare_mapper.info\",\n    \"summary\": \"declare mapper info\",\n    \"description\": \"This Op is used to capture the map information related to it's\\n    parent DeclareMapperOp.The optional `map_vars` maps data from the current task's data environment\\n    to the device data environment.\",\n    \"operands\": [\n      { \"name\": \"map_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"assemblyFormat\": \"oilist(`map_entries` `(` $map_vars `:` type($map_vars) `)`) attr-dict\"\n  },\n  {\n    \"name\": \"omp.declare_reduction\",\n    \"summary\": \"declares a reduction kind\",\n    \"description\": \"Declares an OpenMP reduction kind. This requires two mandatory and four\\n    optional regions.\\n\\n      1. The optional alloc region specifies how to allocate the thread-local\\n         reduction value. This region should not contain control flow and all\\n         IR should be suitable for inlining straight into an entry block. In\\n         the common case this is expected to contain only allocas. It is\\n         expected to `omp.yield` the allocated value on all control paths.\\n         If allocation is conditional (e.g. only allocate if the mold is\\n         allocated), this should be done in the initilizer region and this\\n         region not included. The alloc region is not used for by-value\\n         reductions (where allocation is implicit).\\n      2. The initializer region specifies how to initialize the thread-local\\n         reduction value. This is usually the neutral element of the reduction.\\n         For convenience, the region has an argument that contains the value\\n         of the reduction accumulator at the start of the reduction. If an alloc\\n         region is specified, there is a second block argument containing the\\n         address of the allocated memory. The initializer region is expected to\\n         `omp.yield` the new value on all control flow paths.\\n      3. The reduction region specifies how to combine two values into one, i.e.\\n         the reduction operator. It accepts the two values as arguments and is\\n         expected to `omp.yield` the combined value on all control flow paths.\\n      4. The atomic reduction region is optional and specifies how two values\\n         can be combined atomically given local accumulator variables. It is\\n         expected to store the combined value in the first accumulator variable.\\n      5. The cleanup region is optional and specifies how to clean up any memory\\n         allocated by the initializer region. The region has an argument that\\n         contains the value of the thread-local reduction accumulator. This will\\n         be executed after the reduction has completed.\\n      6. The DataPtrPtr region specifies how to access the base address of a\\n         descriptor. This is used, in particular, for GPU reductions in order\\n         know where partial reduction results are stored in remote lanes.\\n\\n    Note that the MLIR type system does not allow for type-polymorphic\\n    reductions. Separate reduction declarations should be created for different\\n    element and accumulator types.\\n\\n    For initializer and reduction regions, the operand to `omp.yield` must\\n    match the parent operation's results.\\n\\n    * `$byref_element_type`: For by-ref reductions, we want to keep track of the\\n      boxed/allocated type.  For example, for a `real, allocatable` variable, \\n      `real` should be stored in this attribute.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"byref_element_type\", \"type\": \"OptionalAttr<TypeAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"allocRegion\", \"type\": \"MaxSizedRegion<1>\" },\n      { \"name\": \"initializerRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"reductionRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"atomicReductionRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"cleanupRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"dataPtrPtrRegion\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `:` $type attr-dict-with-keyword ( `alloc` $allocRegion^ )? `init` $initializerRegion `combiner` $reductionRegion ( `atomic` $atomicReductionRegion^ )? ( `cleanup` $cleanupRegion^ )? ( `data_ptr_ptr` $dataPtrPtrRegion^ )?\"\n  },\n  {\n    \"name\": \"omp.declare_simd\",\n    \"summary\": \"declare simd directive\",\n    \"description\": \"\\\"omp.declare_simd\\\" models the OpenMP `declare simd` directive.\\n\\n    This is a declarative operation (no region) intended to appear inside\\n    a function body. It attaches clauses of declare simd to the enclosing\\n    function.\\n\\n    Example:\\n    ```mlir\\n    func.func @add(%a: memref<16xi32>) {\\n      omp.declare_simd simdlen(8) aligned(%a : memref<16xi32> -> 64 : i64)\\n      ...\\n    }\\n    ```The `alignments` attribute additionally specifies alignment of each\\n    corresponding aligned operand. Note that `aligned_vars` and `alignments`\\n    must contain the same number of elements.The `inbranch` clause indicates that the generated SIMD function variant\\n    is intended for use in conditional branches.The `linear_step_vars` operand additionally specifies the step for each\\n    associated linear operand. Note that the `linear_vars` and\\n    `linear_step_vars` variadic lists should contain the same number of\\n    elements.The `notinbranch` clause indicates that the generated SIMD function variant\\n    is intended for use when not in conditional branches.When a `simdlen` clause is present, the preferred number of iterations to be\\n    executed concurrently is the value provided to the `simdlen` clause.The `uniform` clause declares one or more arguments to have an invariant\\n    value for all concurrent invocations of the function in the execution of\\n    a single SIMD loop.\",\n    \"operands\": [\n      { \"name\": \"aligned_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"linear_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"linear_step_vars\", \"type\": \"Variadic<AnyInteger>\" },\n      { \"name\": \"uniform_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignments\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"inbranch\", \"type\": \"UnitAttr\" },\n      { \"name\": \"linear_var_types\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"notinbranch\", \"type\": \"UnitAttr\" },\n      { \"name\": \"simdlen\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>\" }\n    ],\n    \"assemblyFormat\": \"oilist(`aligned` `(` custom<AlignedClause>($aligned_vars, type($aligned_vars),\\n                                        $alignments) `)`|`inbranch` $inbranch|`linear` `(`\\n      custom<LinearClause>($linear_vars, type($linear_vars),\\n                           $linear_step_vars, type($linear_step_vars)) `)`|`notinbranch` $notinbranch|`simdlen` `(` $simdlen  `)`|`uniform` `(` custom<UniformClause>($uniform_vars, type($uniform_vars)) `)`) attr-dict\"\n  },\n  {\n    \"name\": \"omp.distribute\",\n    \"summary\": \"distribute construct\",\n    \"description\": \"The distribute construct specifies that the iterations of one or more loops\\n    (optionally specified using collapse clause) will be executed by the\\n    initial teams in the context of their implicit tasks. The loops that the\\n    distribute op is associated with starts with the outermost loop enclosed by\\n    the distribute op region and going down the loop nest toward the innermost\\n    loop. The iterations are distributed across the initial threads of all\\n    initial teams that execute the teams region to which the distribute region\\n    binds.\\n\\n    The distribute loop construct specifies that the iterations of the loop(s)\\n    will be executed in parallel by threads in the current context. These\\n    iterations are spread across threads that already exist in the enclosing\\n    region.\\n\\n    The body region can only contain a single block which must contain a single\\n    operation. This operation must be another compatible loop wrapper or an\\n    `omp.loop_nest`.\\n\\n    ```mlir\\n    omp.distribute <clauses> {\\n      omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {\\n        %a = load %arrA[%i1, %i2] : memref<?x?xf32>\\n        %b = load %arrB[%i1, %i2] : memref<?x?xf32>\\n        %sum = arith.addf %a, %b : f32\\n        store %sum, %arrC[%i1, %i2] : memref<?x?xf32>\\n        omp.yield\\n      }\\n    }\\n    ```The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The `dist_schedule_static` attribute specifies the schedule for this loop,\\n    determining how the loop is distributed across the various teams. The\\n    optional `dist_schedule_chunk_size` associated with this determines further\\n    controls this distribution.The optional `order` attribute specifies which order the iterations of the\\n    associated loops are executed in. Currently the only option for this\\n    attribute is \\\"concurrent\\\".\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"dist_schedule_chunk_size\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dist_schedule_static\", \"type\": \"UnitAttr\" },\n      { \"name\": \"order\", \"type\": \"OptionalAttr<OrderKindAttr>\" },\n      { \"name\": \"order_mod\", \"type\": \"OptionalAttr<OrderModifierAttr{reproducible|unconstrained}>\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`dist_schedule_static` $dist_schedule_static\\n    | `dist_schedule_chunk_size` `(` $dist_schedule_chunk_size `:`\\n      type($dist_schedule_chunk_size) `)`|`order` `(` custom<OrderClause>($order, $order_mod) `)`)custom<PrivateRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier) attr-dict\"\n  },\n  {\n    \"name\": \"omp.flush\",\n    \"summary\": \"flush construct\",\n    \"description\": \"The flush construct executes the OpenMP flush operation. This operation\\n    makes a thread's temporary view of memory consistent with memory and\\n    enforces an order on the memory operations of the variables explicitly\\n    specified or implied.\",\n    \"operands\": [\n      { \"name\": \"varList\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"( `(` $varList^ `:` type($varList) `)` )? attr-dict\"\n  },\n  {\n    \"name\": \"omp.fuse\",\n    \"summary\": \"OpenMP fuse operation\",\n    \"description\": \"Represents the OpenMP fuse directive introduced in OpenMP 6.0.\\n    \\n    The construct takes a loop sequence and merges the loops specifed by the\\n    `looprange` clause and generates a loop sequence with the loops before the\\n    `first` attribute untouched, the generated fused loop, and the loops after\\n    the the `first` + `count` attributes untouched mantaining the orignal\\n    order. If the `looprange` clause is not present all the loops in the\\n    sequence are fused generating a single loop.\\n    Each logical iteration of the fused loop executes a logical iteration of\\n    each affected loop. The fused loop has the number of logical iterations \\n    equal to the affected loop with most logical iterations.\\n\\n    The `first` and `count` attributes of the `looprange` clause are constant\\n    and known beforehand if present.The `looprange` clause contains a range that represent the loops affected\\n    by a loop fusion. The `first` attribute is the first loop of the sequence\\n    that will be affected and the `count` attribute is the number of loops that\\n    are affected by the loop fusion.\",\n    \"operands\": [\n      { \"name\": \"generatees\", \"type\": \"Variadic<CanonicalLoopInfoType>\" },\n      { \"name\": \"applyees\", \"type\": \"Variadic<CanonicalLoopInfoType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"first\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"count\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"custom<LoopTransformClis>($generatees, $applyees)oilist(`looprange` `(` `first` `=` $first `,` `count` `=` $count `)`)attr-dict\"\n  },\n  {\n    \"name\": \"omp.iterator\",\n    \"summary\": \"OpenMP iterator modifier\",\n    \"description\": \"The result of `omp.iterator` is an abstract handle of type\\n    `!omp.iterated<T>`, representing the list of yielded values. This handle\\n    can be directly consumed by OpenMP clauses that accept iterator modifiers,\\n    such as `affinity`, `map`, `to`, `from`, or `depend`.\\n\\n    Example:\\n      %it = omp.iterator(%i, %j) =\\n        (%lb_i to %ub_i step %st_i, %lb_j to %ub_j step %st_j) {\\n        %addr = ...\\n        omp.yield(%addr)\\n      } -> !omp.iterated<ptr>\",\n    \"operands\": [\n      { \"name\": \"loop_lower_bounds\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"loop_upper_bounds\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"loop_steps\", \"type\": \"Variadic<IntLikeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"iterated\", \"type\": \"OpenMP_IteratedType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"loop_inclusive\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` custom<IteratorHeader>($region,\\n                                $loop_lower_bounds, $loop_upper_bounds, $loop_steps,\\n                                type($loop_lower_bounds), type($loop_upper_bounds), type($loop_steps))\\n    `->` qualified(type($iterated)) attr-dict\"\n  },\n  {\n    \"name\": \"omp.loop\",\n    \"summary\": \"loop construct\",\n    \"description\": \"A loop construct specifies that the logical iterations of the associated loops\\n    may execute concurrently and permits the encountering threads to execute the\\n    loop accordingly. A loop construct can have 3 different types of binding:\\n      1. teams: in which case the binding region is the innermost enclosing `teams`\\n         region.\\n      2. parallel: in which case the binding region is the innermost enclosing `parallel`\\n         region.\\n      3. thread: in which case the binding region is not defined.\\n\\n    The body region can only contain a single block which must contain a single\\n    operation, this operation must be an `omp.loop_nest`.\\n\\n    ```\\n    omp.loop <clauses> {\\n      omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {\\n        %a = load %arrA[%i1, %i2] : memref<?x?xf32>\\n        %b = load %arrB[%i1, %i2] : memref<?x?xf32>\\n        %sum = arith.addf %a, %b : f32\\n        store %sum, %arrC[%i1, %i2] : memref<?x?xf32>\\n        omp.yield\\n      }\\n    }\\n    ```The `bind` clause specifies the binding region of the construct on which it\\n    appears.The optional `order` attribute specifies which order the iterations of the\\n    associated loops are executed in. Currently the only option for this\\n    attribute is \\\"concurrent\\\".Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.\",\n    \"operands\": [\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bind_kind\", \"type\": \"OptionalAttr<BindKindAttr>\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"order\", \"type\": \"OptionalAttr<OrderKindAttr>\" },\n      { \"name\": \"order_mod\", \"type\": \"OptionalAttr<OrderModifierAttr{reproducible|unconstrained}>\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`bind` `(` custom<ClauseAttr>($bind_kind) `)`|`order` `(` custom<OrderClause>($order, $order_mod) `)`)custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $reduction_mod, $reduction_vars,\\n        type($reduction_vars), $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.loop_nest\",\n    \"summary\": \"rectangular loop nest\",\n    \"description\": \"This operation represents a rectangular loop nest which may be collapsed\\n    and/or tiled. For each rectangular loop of the nest represented by an\\n    instance of this operation, lower and upper bounds, as well as a step\\n    variable, must be defined. The collapse clause specifies how many loops\\n    that should be collapsed (1 if no collapse is done) after any tiling is\\n    performed. The tiling sizes is represented by the tile sizes clause.\\n\\n    The lower and upper bounds specify a half-open range: the range includes the\\n    lower bound but does not include the upper bound. If the `loop_inclusive`\\n    attribute is specified then the upper bound is also included.\\n\\n    The body region can contain any number of blocks. The region is terminated\\n    by an `omp.yield` instruction without operands. The induction variables,\\n    represented as entry block arguments to the loop nest operation's single\\n    region, match the types of the `loop_lower_bounds`, `loop_upper_bounds` and\\n    `loop_steps` arguments.\\n\\n    ```mlir\\n    omp.loop_nest (%i1, %i2) : i32 = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) collapse(2) tiles(5,5) {\\n      %a = load %arrA[%i1, %i2] : memref<?x?xf32>\\n      %b = load %arrB[%i1, %i2] : memref<?x?xf32>\\n      %sum = arith.addf %a, %b : f32\\n      store %sum, %arrC[%i1, %i2] : memref<?x?xf32>\\n      omp.yield\\n    }\\n    ```\\n\\n    This is a temporary simplified definition of a loop based on existing OpenMP\\n    loop operations intended to serve as a stopgap solution until the long-term\\n    representation of canonical loops is defined. Specifically, this operation\\n    is intended to serve as a unique source for loop information during the\\n    transition to making `omp.distribute`, `omp.simd`, `omp.taskloop` and\\n    `omp.wsloop` wrapper operations. It is not intended to help with the\\n    addition of support for loop transformations, non-rectangular loops and\\n    non-perfectly nested loops.\",\n    \"operands\": [\n      { \"name\": \"loop_lower_bounds\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"loop_upper_bounds\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"loop_steps\", \"type\": \"Variadic<IntLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"collapse_num_loops\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, 1>, [IntMinValue<1>]>\" },\n      { \"name\": \"loop_inclusive\", \"type\": \"UnitAttr\" },\n      { \"name\": \"tile_sizes\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"omp.map.bounds\",\n    \"summary\": \"Represents normalized bounds information for map clauses.\",\n    \"description\": \"This operation is a variation on the OpenACC dialects DataBoundsOp. Within\\n    the OpenMP dialect it stores the bounds/range of data to be mapped to a\\n    device specified by map clauses on target directives. Within\\n    the OpenMP dialect, the MapBoundsOp is associated with MapInfoOp,\\n    helping to store bounds information for the mapped variable.\\n\\n    It is used to support OpenMP array sectioning, Fortran pointer and\\n    allocatable mapping and pointer/allocatable member of derived types.\\n    In all cases the MapBoundsOp holds information on the section of\\n    data to be mapped. Such as the upper bound and lower bound of the\\n    section of data to be mapped. This information is currently\\n    utilised by the LLVM-IR lowering to help generate instructions to\\n    copy data to and from the device when processing target operations.\\n\\n    The example below copys a section of a 10-element array; all except the\\n    first element, utilising OpenMP array sectioning syntax where array\\n    subscripts are provided to specify the bounds to be mapped to device.\\n    To simplify the examples, the constants are used directly, in reality\\n    they will be MLIR SSA values.\\n\\n    C++:\\n    ```\\n    int array[10];\\n    #pragma target map(array[1:9])\\n    ```\\n    =>\\n    ```mlir\\n    omp.map.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(0)\\n    ```\\n\\n    Fortran:\\n    ```\\n    integer :: array(1:10)\\n    !$target map(array(2:10))\\n    ```\\n    =>\\n    ```mlir\\n    omp.map.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(1)\\n    ```\\n\\n    For Fortran pointers and allocatables (as well as those that are\\n    members of derived types) the bounds information is provided by\\n    the Fortran compiler and runtime through descriptor information.\\n\\n    A basic pointer example can be found below (constants again\\n    provided for simplicity, where in reality SSA values will be\\n    used, in this case that point to data yielded by Fortran's\\n    descriptors):\\n\\n    Fortran:\\n    ```\\n    integer, pointer :: ptr(:)\\n    allocate(ptr(10))\\n    !$target map(ptr)\\n    ```\\n    =>\\n    ```mlir\\n    omp.map.bounds lower_bound(0) upper_bound(9) extent(10) start_idx(1)\\n    ```\\n\\n    This operation records the bounds information in a normalized fashion\\n    (zero-based). This works well with the `PointerLikeType`\\n    requirement in data clauses - since a `lower_bound` of 0 means looking\\n    at data at the zero offset from pointer.\\n\\n    This operation must have an `upper_bound` or `extent` (or both are allowed -\\n    but not checked for consistency). When the source language's arrays are\\n    not zero-based, the `start_idx` must specify the zero-position index.\",\n    \"operands\": [\n      { \"name\": \"lower_bound\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"upper_bound\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"extent\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"stride\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"start_idx\", \"type\": \"Optional<IntLikeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"OpenMP_MapBoundsType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"stride_in_bytes\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(\\n        `lower_bound` `(` $lower_bound `:` type($lower_bound) `)`\\n      | `upper_bound` `(` $upper_bound `:` type($upper_bound) `)`\\n      | `extent` `(` $extent `:` type($extent) `)`\\n      | `stride` `(` $stride `:` type($stride) `)`\\n      | `start_idx` `(` $start_idx `:` type($start_idx) `)`\\n    ) attr-dict\"\n  },\n  {\n    \"name\": \"omp.map.info\",\n    \"description\": \"The MapInfoOp captures information relating to individual OpenMP map clauses\\n    that are applied to certain OpenMP directives such as Target and Target Data.\\n\\n    For example, the map type modifier; such as from, tofrom and to, the variable\\n    being captured or the bounds of an array section being mapped.\\n\\n    It can be used to capture both implicit and explicit map information, where\\n    explicit is an argument directly specified to an OpenMP map clause or implicit\\n    where a variable is utilised in a target region but is defined externally to\\n    the target region.\\n\\n    This map information is later used to aid the lowering of the target operations\\n    they are attached to providing argument input and output context for kernels\\n    generated or the target data mapping environment.\\n\\n    Example (Fortran):\\n\\n    ```\\n    integer :: index\\n    !$target map(to: index)\\n    ```\\n    =>\\n    ```mlir\\n    omp.map.info var_ptr(%index_ssa) map_type(to) map_capture_type(ByRef)\\n      name(index)\\n    ```\\n\\n    Description of arguments:\\n    - `var_ptr`: The address of variable to copy.\\n    - `var_type`: The type of the variable to copy.\\n    - 'map_type': OpenMP map type for this map capture, for example: from, to and\\n       always. It's a bitfield composed of the OpenMP runtime flags stored in\\n       OpenMPOffloadMappingFlags.\\n    - 'map_capture_type': Capture type for the variable e.g. this, byref, byvalue, byvla\\n       this can affect how the variable is lowered.\\n    - `var_ptr_ptr`: Used when the variable copied is a member of a class, structure\\n      or derived type and refers to the originating struct.\\n    - `members`: Used to indicate mapped child members for the current MapInfoOp,\\n       represented as other MapInfoOp's, utilised in cases where a parent structure\\n       type and members of the structure type are being mapped at the same time.\\n       For example: map(to: parent, parent->member, parent->member2[:10])\\n    - `members_index`: Used to indicate the ordering of members within the containing\\n       parent (generally a record type such as a structure, class or derived type),\\n       e.g. struct {int x, float y, double z}, x would be 0, y would be 1, and z\\n       would be 2. This aids the mapping.\\n    - `bounds`: Used when copying slices of array's, pointers or pointer members of\\n       objects (e.g. derived types or classes), indicates the bounds to be copied\\n       of the variable. When it's an array slice it is in rank order where rank 0\\n       is the inner-most dimension.\\n    - 'mapper_id': OpenMP mapper map type modifier for this map capture. It's used to\\n       specify a user defined mapper to be used for mapping.\\n    - `name`: Holds the name of variable as specified in user clause (including bounds).\\n    - `partial_map`: The record type being mapped will not be mapped in its entirety,\\n       it may be used however, in a mapping to bind it's mapped components together.\",\n    \"operands\": [\n      { \"name\": \"var_ptr\", \"type\": \"OpenMP_PointerLikeType\" },\n      { \"name\": \"var_ptr_ptr\", \"type\": \"Optional<OpenMP_PointerLikeType>\" },\n      { \"name\": \"members\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"bounds\", \"type\": \"Variadic<OpenMP_MapBoundsType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"omp_ptr\", \"type\": \"OpenMP_PointerLikeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"var_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"map_type\", \"type\": \"ClauseMapFlagsAttr{none|storage|to|from|always|del|return_param|priv|literal|implicit|close|present|ompx_hold|attach|attach_always|attach_never|attach_auto|ref_ptr|ref_ptee|ref_ptr_ptee|is_device_ptr}\" },\n      { \"name\": \"map_capture_type\", \"type\": \"VariableCaptureKindAttr{This|ByRef|ByCopy|VLAType}\" },\n      { \"name\": \"members_index\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>>\" },\n      { \"name\": \"mapper_id\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"partial_map\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`var_ptr` `(` $var_ptr `:` type($var_ptr) `,` $var_type `)`\\n    `map_clauses` `(` custom<MapClause>($map_type) `)`\\n    `capture` `(` custom<CaptureType>($map_capture_type) `)`\\n    oilist(\\n        `var_ptr_ptr` `(` $var_ptr_ptr `:` type($var_ptr_ptr) `)`\\n      | `mapper` `(` $mapper_id `)`\\n      | `members` `(` $members `:` custom<MembersIndex>($members_index) `:` type($members) `)`\\n      | `bounds` `(` $bounds `)`\\n    ) `->` type($omp_ptr) attr-dict\"\n  },\n  {\n    \"name\": \"omp.masked\",\n    \"summary\": \"masked construct\",\n    \"description\": \"Masked construct allows to specify a structured block to be executed by a subset of\\n    threads of the current team.If `filter` is specified, the masked construct masks the execution of\\n    the region to only the thread id filtered. Other threads executing the\\n    parallel region are not expected to execute the region specified within\\n    the `masked` directive. If `filter` is not specified, master thread is\\n    expected to execute the region enclosed within `masked` directive.\",\n    \"operands\": [\n      { \"name\": \"filtered_thread_id\", \"type\": \"Optional<IntLikeType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`filter` `(` $filtered_thread_id `:` type($filtered_thread_id) `)`) $region attr-dict\"\n  },\n  {\n    \"name\": \"omp.master\",\n    \"summary\": \"master construct\",\n    \"description\": \"The master construct specifies a structured block that is executed by\\n    the master thread of the team.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"omp.new_cli\",\n    \"summary\": \"Create a new Canonical Loop Info value.\",\n    \"description\": \"Create a new CLI that can be passed as an argument to a CanonicalLoopOp\\n    and to loop transformation operations to handle dependencies between\\n    loop transformation operations.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"CanonicalLoopInfoType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"omp.ordered\",\n    \"summary\": \"ordered construct without region\",\n    \"description\": \"The ordered construct without region is a stand-alone directive that\\n    specifies cross-iteration dependencies in a doacross loop nest.The `doacross_depend_type` attribute refers to either the DEPEND(SOURCE)\\n    clause or the DEPEND(SINK: vec) clause.\\n\\n    The `doacross_num_loops` attribute specifies the number of loops in the\\n    doacross nest.\\n\\n    The `doacross_depend_vars` is a variadic list of operands that specifies the\\n    index of the loop iterator in the doacross nest for the DEPEND(SOURCE)\\n    clause or the index of the element of \\\"vec\\\" for the DEPEND(SINK: vec)\\n    clause. It contains the operands in multiple \\\"vec\\\" when multiple\\n    DEPEND(SINK: vec) clauses exist in one ORDERED directive.\",\n    \"operands\": [\n      { \"name\": \"doacross_depend_vars\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"doacross_depend_type\", \"type\": \"OptionalAttr<ClauseDependAttr{dependsource|dependsink}>\" },\n      { \"name\": \"doacross_num_loops\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>\" }\n    ],\n    \"assemblyFormat\": \"( `depend_type` `` $doacross_depend_type^ )?\\n    ( `depend_vec` `(` $doacross_depend_vars^ `:` type($doacross_depend_vars)\\n                   `)` )?  attr-dict\"\n  },\n  {\n    \"name\": \"omp.ordered.region\",\n    \"summary\": \"ordered construct with region\",\n    \"description\": \"The ordered construct with region specifies a structured block in a\\n    worksharing-loop, SIMD, or worksharing-loop SIMD region that is executed in\\n    the order of the loop iterations.The `par_level_simd` attribute corresponds to the simd clause specified. If\\n    it is not present, it behaves as if the threads clause is specified or no\\n    clause is specified.\",\n    \"attributes\": [\n      { \"name\": \"par_level_simd\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`par_level_simd` $par_level_simd) $region attr-dict\"\n  },\n  {\n    \"name\": \"omp.parallel\",\n    \"summary\": \"parallel construct\",\n    \"description\": \"The parallel construct includes a region of code which is to be executed\\n    by a team of threads.\\n\\n    The optional `if_expr` parameter specifies a boolean result of a conditional\\n    check. If this value is 1 or is not provided then the parallel region runs\\n    as normal, if it is 0 then the parallel region is executed with one thread.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The `num_threads` clause specifies the number of threads.\\n\\n    Multi-dimensional format (dims modifier):\\n    - Multiple values can be specified for multi-dimensional thread counts.\\n    - The number of dimensions is derived from the number of values.\\n    - Values can have different integer types.\\n    - Format: `num_threads(%v1, %v2, ... : type1, type2, ...)`\\n    - Example: `num_threads(%n, %m : i32, i64)`\\n\\n    Single value format:\\n    - A single value specifies the number of threads.\\n    - Format: `num_threads(%value : type)`\\n    - Example: `num_threads(%n : i32)`The optional `proc_bind_kind` attribute controls the thread affinity for the\\n    execution of the parallel region.Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"num_threads_vars\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"proc_bind_kind\", \"type\": \"OptionalAttr<ProcBindKindAttr>\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`if` `(` $if_expr `)`|`num_threads` `(` $num_threads_vars `:` type($num_threads_vars) `)`|`proc_bind` `(` custom<ClauseAttr>($proc_bind_kind) `)`)custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $reduction_mod, $reduction_vars,\\n        type($reduction_vars), $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.private\",\n    \"summary\": \"Provides declaration of [first]private logic.\",\n    \"description\": \"This operation provides a declaration of how to implement the\\n    [first]privatization of a variable. The dialect users should provide\\n    which type should be allocated for this variable. The allocated (usually by\\n    alloca) variable is passed to the initialization region which does everything\\n    else (e.g. initialization of Fortran runtime descriptors). Information about\\n    how to initialize the copy from the original item should be given in the\\n    copy region, and if needed, how to deallocate memory (allocated by the\\n    initialization region) in the dealloc region.\\n\\n    Examples:\\n\\n    * `private(x)` would not need any regions because no initialization is\\n      required by the standard for i32 variables and this is not firstprivate.\\n    ```mlir\\n    omp.private {type = private} @x.privatizer : i32\\n    ```\\n\\n    * `firstprivate(x)` would be emitted as:\\n    ```mlir\\n    omp.private {type = firstprivate} @x.privatizer : i32 copy {\\n    ^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>):\\n    // %arg0 is the original host variable.\\n    // %arg1 represents the memory allocated for this private variable.\\n    ... copy from host to the privatized clone ....\\n    omp.yield(%arg1 : !fir.ref<i32>)\\n    }\\n    ```\\n\\n    * `private(x)` for \\\"allocatables\\\" would be emitted as:\\n    ```mlir\\n    omp.private {type = private} @x.privatizer : !some.type init {\\n    ^bb0(%arg0: !some.pointer<!some.type>, %arg1: !some.pointer<!some.type>):\\n    // initialize %arg1, using %arg0 as a mold for allocations.\\n    // For example if %arg0 is a heap allocated array with a runtime determined\\n    // length and !some.type is a runtime type descriptor, the init region\\n    // will read the array length from %arg0, and heap allocate an array of the\\n    // right length and initialize %arg1 to contain the array allocation and\\n    // length.\\n    omp.yield(%arg1 : !some.pointer<!some.type>)\\n    } dealloc {\\n    ^bb0(%arg0: !some.pointer<!some.type>):\\n    // ... deallocate memory allocated by the init region...\\n    // In the example above, this will free the heap allocated array data.\\n    omp.yield\\n    }\\n    ```\\n\\n    There are no restrictions on the body except for:\\n    - The `dealloc` regions has a single argument.\\n    - The `init` & `copy` regions have 2 arguments.\\n    - All three regions are terminated by `omp.yield` ops.\\n    The above restrictions and other obvious restrictions (e.g. verifying the\\n    type of yielded values) are verified by the custom op verifier. The actual\\n    contents of the blocks inside all regions are not verified.\\n\\n    Instances of this op would then be used by ops that model directives that\\n    accept data-sharing attribute clauses.\\n\\n    The `sym_name` attribute provides a symbol by which the privatizer op can be\\n    referenced by other dialect ops.\\n\\n    The `type` attribute is the type of the value being privatized. This type\\n    will be implicitly allocated in MLIR->LLVMIR conversion and passed as the\\n    second argument to the init region. Therefore the type of arguments to\\n    the regions should be a type which represents a pointer to `type`.\\n\\n    The `data_sharing_type` attribute specifies whether privatizer corresponds\\n    to a `private` or a `firstprivate` clause.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttrOf<AnyType>\" },\n      { \"name\": \"data_sharing_type\", \"type\": \"DataSharingClauseTypeAttr{private|firstprivate}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"init_region\", \"type\": \"AnyRegion\" },\n      { \"name\": \"copy_region\", \"type\": \"AnyRegion\" },\n      { \"name\": \"dealloc_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$data_sharing_type $sym_name `:` $type\\n      (`init` $init_region^)?\\n      (`copy` $copy_region^)?\\n      (`dealloc` $dealloc_region^)?\\n      attr-dict\"\n  },\n  {\n    \"name\": \"omp.scan\",\n    \"summary\": \"scan directive\",\n    \"description\": \"The scan directive allows to specify scan reductions. It should be\\n    enclosed within a parent directive along with which a reduction clause\\n    with `inscan` modifier must be specified. The scan directive allows to\\n    split code blocks into input phase and scan phase in the region\\n    enclosed by the parent.The inclusive clause is used on a separating directive that separates a\\n    structured block into two structured block sequences. If it is specified,\\n    the input phase includes the preceding structured block sequence and the\\n    scan phase includes the following structured block sequence.\\n\\n    The `inclusive_vars` is a variadic list of operands that specifies the\\n    scan-reduction accumulator symbols.The exclusive clause is used on a separating directive that separates a\\n    structured block into two structured block sequences. If it\\n    is specified, the input phase excludes the preceding structured block \\n    sequence and instead includes the following structured block sequence, \\n    while the scan phase includes the preceding structured block sequence.\\n\\n    The `exclusive_vars` is a variadic list of operands that specifies the\\n    scan-reduction accumulator symbols.\",\n    \"operands\": [\n      { \"name\": \"inclusive_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"exclusive_vars\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist(`inclusive` `(` $inclusive_vars `:` type($inclusive_vars) `)`|`exclusive` `(` $exclusive_vars `:` type($exclusive_vars) `)`) attr-dict\"\n  },\n  {\n    \"name\": \"omp.section\",\n    \"summary\": \"section directive\",\n    \"description\": \"A section operation encloses a region which represents one section in a\\n    sections construct. A section op should always be surrounded by an\\n    `omp.sections` operation. The section operation may have block args\\n    which corespond to the block arguments of the surrounding `omp.sections`\\n    operation. This is done to reflect situations where these block arguments\\n    represent variables private to each section.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"omp.sections\",\n    \"summary\": \"sections construct\",\n    \"description\": \"The sections construct is a non-iterative worksharing construct that\\n    contains `omp.section` operations. The `omp.section` operations are to be\\n    distributed among and executed by the threads in a team. Each `omp.section`\\n    is executed once by one of the threads in the team in the context of its\\n    implicit task.\\n    Block arguments for reduction variables should be mirrored in enclosed\\n    `omp.section` operations.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`nowait` $nowait)custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $reduction_mod, $reduction_vars,\\n        type($reduction_vars), $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.simd\",\n    \"summary\": \"simd construct\",\n    \"description\": \"The simd construct can be applied to a loop to indicate that the loop can be\\n    transformed into a SIMD loop (that is, multiple iterations of the loop can\\n    be executed concurrently using SIMD instructions).\\n\\n    The body region can only contain a single block which must contain a single\\n    operation. This operation must be another compatible loop wrapper or an\\n    `omp.loop_nest`.\\n\\n    ```\\n    omp.simd <clauses> {\\n      omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {\\n        %a = load %arrA[%i1, %i2] : memref<?x?xf32>\\n        %b = load %arrB[%i1, %i2] : memref<?x?xf32>\\n        %sum = arith.addf %a, %b : f32\\n        store %sum, %arrC[%i1, %i2] : memref<?x?xf32>\\n        omp.yield\\n      }\\n    }\\n    ```\\n\\n    When an if clause is present and evaluates to false, the preferred number of\\n    iterations to be executed concurrently is one, regardless of whether\\n    a simdlen clause is specified.The `alignments` attribute additionally specifies alignment of each\\n    corresponding aligned operand. Note that `aligned_vars` and `alignments`\\n    must contain the same number of elements.The `linear_step_vars` operand additionally specifies the step for each\\n    associated linear operand. Note that the `linear_vars` and\\n    `linear_step_vars` variadic lists should contain the same number of\\n    elements.The optional `nontemporal` attribute specifies variables which have low\\n    temporal locality across the iterations where they are accessed.The optional `order` attribute specifies which order the iterations of the\\n    associated loops are executed in. Currently the only option for this\\n    attribute is \\\"concurrent\\\".Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.The `safelen` clause specifies that no two concurrent iterations within a\\n    SIMD chunk can have a distance in the logical iteration space that is\\n    greater than or equal to the value given in the clause.When a `simdlen` clause is present, the preferred number of iterations to be\\n    executed concurrently is the value provided to the `simdlen` clause.\",\n    \"operands\": [\n      { \"name\": \"aligned_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"linear_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"linear_step_vars\", \"type\": \"Variadic<AnyInteger>\" },\n      { \"name\": \"nontemporal_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignments\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"linear_var_types\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"order\", \"type\": \"OptionalAttr<OrderKindAttr>\" },\n      { \"name\": \"order_mod\", \"type\": \"OptionalAttr<OrderModifierAttr{reproducible|unconstrained}>\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"safelen\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>\" },\n      { \"name\": \"simdlen\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`aligned` `(` custom<AlignedClause>($aligned_vars, type($aligned_vars),\\n                                        $alignments) `)`|`if` `(` $if_expr `)`|`linear` `(`\\n      custom<LinearClause>($linear_vars, type($linear_vars),\\n                           $linear_step_vars, type($linear_step_vars)) `)`|`nontemporal` `(`  $nontemporal_vars `:` type($nontemporal_vars) `)`|`order` `(` custom<OrderClause>($order, $order_mod) `)`|`safelen` `(` $safelen  `)`|`simdlen` `(` $simdlen  `)`)custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $reduction_mod, $reduction_vars,\\n        type($reduction_vars), $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.single\",\n    \"summary\": \"single directive\",\n    \"description\": \"The single construct specifies that the associated structured block is\\n    executed by only one of the threads in the team (not necessarily the\\n    master thread), in the context of its implicit task. The other threads\\n    in the team, which do not execute the block, wait at an implicit barrier\\n    at the end of the single construct.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.If `copyprivate` variables and functions are specified, then each thread\\n    variable is updated with the variable value of the thread that executed\\n    the single region, using the specified copy functions.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"copyprivate_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"copyprivate_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`copyprivate` `(`\\n      custom<Copyprivate>($copyprivate_vars, type($copyprivate_vars),\\n                          $copyprivate_syms) `)`|`nowait` $nowait)custom<PrivateRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier) attr-dict\"\n  },\n  {\n    \"name\": \"omp.target\",\n    \"summary\": \"target construct\",\n    \"description\": \"The target construct includes a region of code which is to be executed\\n    on a device.\\n\\n    The optional `if_expr` parameter specifies a boolean result of a conditional\\n    check. If this value is 1 or is not provided then the target region runs on\\n    a device, if it is 0 then the target region is executed on the host device.\\n\\n    The `private_maps` attribute connects `private` operands to their corresponding\\n    `map` operands. For `private` operands that require a map, the value of the\\n    corresponding element in the attribute is the index of the `map` operand\\n    (relative to other `map` operands not the whole operands of the operation). For\\n    `private` opernads that do not require a map, this value is -1 (which is omitted\\n    from the assembly foramt printing).The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.`ompx_bare` allows `omp target teams` to be executed on a GPU with an\\n    explicit number of teams and threads. This clause also allows the teams and\\n    threads sizes to have up to 3 dimensions.The `depend_kinds` and `depend_vars` arguments are variadic lists of values\\n    that specify the dependencies of this particular task in relation to other\\n    tasks.The optional `device` parameter specifies the device number for the target\\n    region.The optional `has_device_addr_vars` indicates that list items already have\\n    device addresses, so they may be directly accessed from the target device.\\n    This includes array sections.The optional `host_eval_vars` holds values defined outside of the region of\\n    the `IsolatedFromAbove` operation for which a corresponding entry block\\n    argument is defined. The only legal uses for these captured values are the\\n    following:\\n      - `num_teams` or `thread_limit` clause of an immediately nested\\n      `omp.teams` operation.\\n      - If the operation is the top-level `omp.target` of a target SPMD kernel:\\n        - `num_threads` clause of the nested `omp.parallel` operation.\\n        - Bounds and steps of the nested `omp.loop_nest` operation.The optional `is_device_ptr_vars` indicates list items are device pointers.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.The `thread_limit` clause specifies the limit on the number of threads.\\n\\n    Multi-dimensional format (dims modifier):\\n    - Multiple values can be specified for multi-dimensional thread limits.\\n    - The number of dimensions is derived from the number of values.\\n    - Values can have different integer types.\\n    - Format: `thread_limit(%v1, %v2, ... : type1, type2, ...)`\\n    - Example: `thread_limit(%n, %m : i32, i64)`\\n\\n    Single value format:\\n    - A single value specifies the thread limit.\\n    - Format: `thread_limit(%value : type)`\\n    - Example: `thread_limit(%n : i32)`\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"depend_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"device\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"has_device_addr_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"host_eval_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"in_reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"is_device_ptr_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"thread_limit_vars\", \"type\": \"Variadic<IntLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bare\", \"type\": \"UnitAttr\" },\n      { \"name\": \"depend_kinds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<ClauseTaskDependAttr{taskdependin|taskdependout|taskdependinout|taskdependmutexinoutset|taskdependinoutset}>>\" },\n      { \"name\": \"in_reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"in_reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"private_maps\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`ompx_bare` $bare|`depend` `(`\\n      custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`|`device` `(` $device `:` type($device) `)`|`if` `(` $if_expr `)`|`is_device_ptr` `(` $is_device_ptr_vars `:` type($is_device_ptr_vars) `)`|`nowait` $nowait|`thread_limit` `(` $thread_limit_vars `:` type($thread_limit_vars) `)`)custom<TargetOpRegion>(\\n        $region, $has_device_addr_vars, type($has_device_addr_vars),\\n        $host_eval_vars, type($host_eval_vars), $in_reduction_vars,\\n        type($in_reduction_vars), $in_reduction_byref, $in_reduction_syms,\\n        $map_vars, type($map_vars), $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $private_maps) attr-dict\"\n  },\n  {\n    \"name\": \"omp.target_allocmem\",\n    \"summary\": \"allocate storage on an openmp device for an object of a given type\",\n    \"description\": \"Allocates memory on the specified OpenMP device for an object of the given type.\\n    Returns an integer value representing the device pointer to the allocated memory.\\n    The memory is uninitialized after allocation. Operations must be paired with \\n    `omp.target_freemem` to avoid memory leaks.\\n\\n    * `$device`: The integer ID of the OpenMP device where the memory will be allocated.\\n    * `$in_type`: The type of the object for which memory is being allocated. \\n      For arrays, this can be a static or dynamic array type.\\n    * `$uniq_name`: An optional unique name for the allocated memory.\\n    * `$bindc_name`: An optional name used for C interoperability.\\n    * `$typeparams`: Runtime type parameters for polymorphic or parameterized types. \\n      These are typically integer values that define aspects of a type not fixed at compile time.\\n    * `$shape`: Runtime shape operands for dynamic arrays. \\n      Each operand is an integer value representing the extent of a specific dimension. \\n\\n  ```mlir\\n    // Allocate a static 3x3 integer vector on device 0\\n    %device_0 = arith.constant 0 : i32\\n    %ptr_static = omp.target_allocmem %device_0 : i32, vector<3x3xi32>\\n    // ... use %ptr_static ...\\n    omp.target_freemem %device_0, %ptr_static : i32, i64\\n\\n    // Allocate a dynamic 2D Fortran array (fir.array) on device 1\\n    %device_1 = arith.constant 1 : i32\\n    %rows = arith.constant 10 : index\\n    %cols = arith.constant 20 : index\\n    %ptr_dynamic = omp.target_allocmem %device_1 : i32, !fir.array<?x?xf32>, %rows, %cols : index, index\\n    // ... use %ptr_dynamic ...\\n    omp.target_freemem %device_1, %ptr_dynamic : i32, i64\\n  ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"AnyInteger\" },\n      { \"name\": \"typeparams\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<IntLikeType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"uniq_name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"bindc_name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"omp.target_data\",\n    \"summary\": \"target data construct\",\n    \"description\": \"Map variables to a device data environment for the extent of the region.\\n\\n    The omp target data directive maps variables to a device data\\n    environment, and defines the lexical scope of the data environment\\n    that is created. The omp target data directive can reduce data copies\\n    to and from the offloading device when multiple target regions are using\\n    the same data.\\n\\n    The optional `if_expr` parameter specifies a boolean result of a conditional\\n    check. If this value is 1 or is not provided then the target region runs on\\n    a device, if it is 0 then the target region is executed on the host device.The optional `device` parameter specifies the device number for the target\\n    region.The optional `map_vars` maps data from the current task's data environment\\n    to the device data environment.The optional `use_device_addr_vars` specifies the address of the objects in\\n    the device data environment.The optional `use_device_ptr_vars` specifies the device pointers to the\\n    corresponding list items in the device data environment.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"map_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"use_device_addr_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"use_device_ptr_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`device` `(` $device `:` type($device) `)`|`if` `(` $if_expr `)`|`map_entries` `(` $map_vars `:` type($map_vars) `)`)custom<UseDeviceAddrUseDevicePtrRegion>(\\n        $region, $use_device_addr_vars, type($use_device_addr_vars),\\n        $use_device_ptr_vars, type($use_device_ptr_vars)) attr-dict\"\n  },\n  {\n    \"name\": \"omp.target_enter_data\",\n    \"summary\": \"target enter data construct\",\n    \"description\": \"The target enter data directive specifies that variables are mapped to\\n    a device data environment. The target enter data directive is a\\n    stand-alone directive.\\n\\n    The optional `if_expr` parameter specifies a boolean result of a conditional\\n    check. If this value is 1 or is not provided then the target region runs on\\n    a device, if it is 0 then the target region is executed on the host device.The `depend_kinds` and `depend_vars` arguments are variadic lists of values\\n    that specify the dependencies of this particular task in relation to other\\n    tasks.The optional `device` parameter specifies the device number for the target\\n    region.The optional `map_vars` maps data from the current task's data environment\\n    to the device data environment.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.\",\n    \"operands\": [\n      { \"name\": \"depend_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"device\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"map_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depend_kinds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<ClauseTaskDependAttr{taskdependin|taskdependout|taskdependinout|taskdependmutexinoutset|taskdependinoutset}>>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"oilist(`depend` `(`\\n      custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`|`device` `(` $device `:` type($device) `)`|`if` `(` $if_expr `)`|`map_entries` `(` $map_vars `:` type($map_vars) `)`|`nowait` $nowait) attr-dict\"\n  },\n  {\n    \"name\": \"omp.target_exit_data\",\n    \"summary\": \"target exit data construct\",\n    \"description\": \"The target exit data directive specifies that variables are mapped to a\\n    device data environment. The target exit data directive is\\n    a stand-alone directive.\\n\\n    The optional `if_expr` parameter specifies a boolean result of a conditional\\n    check. If this value is 1 or is not provided then the target region runs on\\n    a device, if it is 0 then the target region is executed on the host device.The `depend_kinds` and `depend_vars` arguments are variadic lists of values\\n    that specify the dependencies of this particular task in relation to other\\n    tasks.The optional `device` parameter specifies the device number for the target\\n    region.The optional `map_vars` maps data from the current task's data environment\\n    to the device data environment.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.\",\n    \"operands\": [\n      { \"name\": \"depend_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"device\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"map_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depend_kinds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<ClauseTaskDependAttr{taskdependin|taskdependout|taskdependinout|taskdependmutexinoutset|taskdependinoutset}>>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"oilist(`depend` `(`\\n      custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`|`device` `(` $device `:` type($device) `)`|`if` `(` $if_expr `)`|`map_entries` `(` $map_vars `:` type($map_vars) `)`|`nowait` $nowait) attr-dict\"\n  },\n  {\n    \"name\": \"omp.target_freemem\",\n    \"summary\": \"free memory on an openmp device\",\n    \"description\": \"Deallocates memory on the specified OpenMP device that was previously\\n    allocated by an `omp.target_allocmem` operation. After this operation, the\\n    deallocated memory is in an undefined state and should not be accessed.\\n    It is crucial to ensure that all accesses to the memory region are completed\\n    before `omp.target_freemem` is called to avoid undefined behavior.\\n\\n    * `$device`: The integer ID of the OpenMP device from which the memory will be freed.\\n    * `$heapref`: The integer value representing the device pointer to the memory\\n      to be deallocated, which was previously returned by `omp.target_allocmem`.\\n\\n    ```mlir\\n      // Example of allocating and freeing memory on an OpenMP device\\n      %device_id = arith.constant 0 : i32\\n      %allocated_ptr = omp.target_allocmem %device_id : i32, vector<3x3xi32>\\n      // ... operations using %allocated_ptr on the device ...\\n      omp.target_freemem %device_id, %allocated_ptr : i32, i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"AnyInteger\" },\n      { \"name\": \"heapref\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$device `,` $heapref attr-dict `:` type($device) `,` qualified(type($heapref))\"\n  },\n  {\n    \"name\": \"omp.target_update\",\n    \"summary\": \"target update construct\",\n    \"description\": \"The target update directive makes the corresponding list items in the device\\n    data environment consistent with their original list items, according to the\\n    specified motion clauses. The target update construct is a stand-alone\\n    directive.\\n\\n    The optional `if_expr` parameter specifies a boolean result of a conditional\\n    check. If this value is 1 or is not provided then the target region runs on\\n    a device, if it is 0 then the target region is executed on the host device.\\n\\n    We use `MapInfoOp` to model the motion clauses and their modifiers. Even\\n    though the spec differentiates between map-types & map-type-modifiers vs.\\n    motion-clauses & motion-modifiers, the motion clauses and their modifiers\\n    are a subset of map types and their modifiers. The subset relation is\\n    handled in during verification to make sure the restrictions for target\\n    update are respected.The `depend_kinds` and `depend_vars` arguments are variadic lists of values\\n    that specify the dependencies of this particular task in relation to other\\n    tasks.The optional `device` parameter specifies the device number for the target\\n    region.The optional `map_vars` maps data from the current task's data environment\\n    to the device data environment.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.\",\n    \"operands\": [\n      { \"name\": \"depend_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"device\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"map_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depend_kinds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<ClauseTaskDependAttr{taskdependin|taskdependout|taskdependinout|taskdependmutexinoutset|taskdependinoutset}>>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"oilist(`depend` `(`\\n      custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`|`device` `(` $device `:` type($device) `)`|`if` `(` $if_expr `)`|`map_entries` `(` $map_vars `:` type($map_vars) `)`|`nowait` $nowait) attr-dict\"\n  },\n  {\n    \"name\": \"omp.task\",\n    \"summary\": \"task construct\",\n    \"description\": \"The task construct defines an explicit task.\\n\\n    For definitions of \\\"undeferred task\\\", \\\"included task\\\", \\\"final task\\\" and\\n    \\\"mergeable task\\\", please check OpenMP Specification.\\n\\n    When an `if` clause is present on a task construct, and the value of\\n    `if_expr` evaluates to `false`, an \\\"undeferred task\\\" is generated, and the\\n    encountering thread must suspend the current task region, for which\\n    execution cannot be resumed until execution of the structured block that is\\n    associated with the generated task is completed.\\n\\n    The `in_reduction` clause specifies that this particular task (among all the\\n    tasks in current taskgroup, if any) participates in a reduction.\\n    `in_reduction_byref` indicates whether each reduction variable should\\n    be passed by value or by reference.The `affinity` clause specifies a locator list used as a hint for task\\n    placement / scheduling affinity.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The `depend_kinds` and `depend_vars` arguments are variadic lists of values\\n    that specify the dependencies of this particular task in relation to other\\n    tasks.When a `final` clause is present and the `final` clause expression evaluates\\n    to `true`, the generated tasks will be final tasks. All task constructs\\n    encountered during execution of a final task will generate final and\\n    included tasks. The use of a variable in a `final` clause expression causes\\n    an implicit reference to the variable in all enclosing constructs.When the `mergeable` clause is present, the tasks generated by the construct\\n    are \\\"mergeable tasks\\\".The `priority` clause is a hint for the priority of the generated tasks.\\n    The `priority` is a non-negative integer expression that provides a hint for\\n    task execution order. Among all tasks ready to be executed, higher priority\\n    tasks (those with a higher numerical value in the priority clause\\n    expression) are recommended to execute before lower priority ones. The\\n    default priority-value when no priority clause is specified should be\\n    assumed to be zero (the lowest priority).If the `untied` clause is present on a task construct, any thread in the\\n    team can resume the task region after a suspension. The `untied` clause is\\n    ignored if a `final` clause is present on the same task construct and the\\n    `final` expression evaluates to `true`, or if a task is an included task.The detach clause specifies that the task generated by the construct on which it appears is a\\n\\tdetachable task. A new allow-completion event is created and connected to the completion of the\\n\\tassociated task region. The original event-handle is updated to represent that allow-completion\\n\\tevent before the task data environment is created.\",\n    \"operands\": [\n      { \"name\": \"iterated\", \"type\": \"Variadic<OpenMP_IteratedType>\" },\n      { \"name\": \"affinity_vars\", \"type\": \"Variadic<OpenMP_AffinityEntryType>\" },\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"depend_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"final\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"in_reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"priority\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"event_handle\", \"type\": \"Optional<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depend_kinds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<ClauseTaskDependAttr{taskdependin|taskdependout|taskdependinout|taskdependmutexinoutset|taskdependinoutset}>>\" },\n      { \"name\": \"in_reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"in_reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"mergeable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"untied\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`affinity` `(` custom<AffinityClause>($iterated, $affinity_vars,\\n                                          type($iterated), type($affinity_vars)) `)`|`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`depend` `(`\\n      custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`|`final` `(` $final `)`|`if` `(` $if_expr `)`|`mergeable` $mergeable|`priority` `(` $priority `:` type($priority) `)`|`untied` $untied|`detach` `(` $event_handle `:` type($event_handle) `)`)custom<InReductionPrivateRegion>(\\n        $region, $in_reduction_vars, type($in_reduction_vars),\\n        $in_reduction_byref, $in_reduction_syms, $private_vars,\\n        type($private_vars), $private_syms, $private_needs_barrier) attr-dict\"\n  },\n  {\n    \"name\": \"omp.taskgroup\",\n    \"summary\": \"taskgroup construct\",\n    \"description\": \"The taskgroup construct specifies a wait on completion of child tasks of the\\n    current task and their descendent tasks.\\n\\n    When a thread encounters a taskgroup construct, it starts executing the\\n    region. All child tasks generated in the taskgroup region and all of their\\n    descendants that bind to the same parallel region as the taskgroup region\\n    are part of the taskgroup set associated with the taskgroup region. There is\\n    an implicit task scheduling point at the end of the taskgroup region. The\\n    current task is suspended at the task scheduling point until all tasks in\\n    the taskgroup set complete execution.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The `task_reduction` clause specifies a reduction among tasks. For each list\\n    item, the number of copies is unspecified. Any copies associated with the\\n    reduction are initialized before they are accessed by the tasks\\n    participating in the reduction. After the end of the region, the original\\n    list item contains the result of the reduction. Similarly to the `reduction`\\n    clause, accumulator variables must be passed in `task_reduction_vars`,\\n    symbols referring to reduction declarations in the `task_reduction_syms`\\n    attribute, and whether the reduction variable should be passed into the\\n    reduction region by value or by reference in `task_reduction_byref`.\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"task_reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"task_reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"task_reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`)custom<TaskReductionRegion>(\\n        $region, $task_reduction_vars, type($task_reduction_vars),\\n        $task_reduction_byref, $task_reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.taskloop\",\n    \"summary\": \"taskloop construct\",\n    \"description\": \"The taskloop construct specifies that the iterations of one or more\\n    associated loops will be executed in parallel using explicit tasks. The\\n    iterations are distributed across tasks generated by the construct and\\n    scheduled to be executed.\\n\\n    The body region can only contain a single block which must contain a single\\n    operation. This operation must be another compatible loop wrapper or an\\n    `omp.loop_nest`.\\n\\n    ```\\n    omp.taskloop <clauses> {\\n      omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {\\n        %a = load %arrA[%i1, %i2] : memref<?x?xf32>\\n        %b = load %arrB[%i1, %i2] : memref<?x?xf32>\\n        %sum = arith.addf %a, %b : f32\\n        store %sum, %arrC[%i1, %i2] : memref<?x?xf32>\\n        omp.yield\\n      }\\n    }\\n    ```\\n\\n    For definitions of \\\"undeferred task\\\", \\\"included task\\\", \\\"final task\\\" and\\n    \\\"mergeable task\\\", please check OpenMP Specification.\\n\\n    When an `if` clause is present on a taskloop construct, and if the `if`\\n    clause expression evaluates to `false`, undeferred tasks are generated. The\\n    use of a variable in an `if` clause expression of a taskloop construct\\n    causes an implicit reference to the variable in all enclosing constructs.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.When a `final` clause is present and the `final` clause expression evaluates\\n    to `true`, the generated tasks will be final tasks. All task constructs\\n    encountered during execution of a final task will generate final and\\n    included tasks. The use of a variable in a `final` clause expression causes\\n    an implicit reference to the variable in all enclosing constructs.If a `grainsize` clause is present, the number of logical loop iterations\\n    assigned to each generated task is greater than or equal to the minimum of\\n    the value of the grain-size expression and the number of logical loop\\n    iterations, but less than two times the value of the grain-size expression.When the `mergeable` clause is present, the tasks generated by the construct\\n    are \\\"mergeable tasks\\\".By default, the taskloop construct executes as if it was enclosed in a\\n    taskgroup construct with no statements or directives outside of the taskloop\\n    construct. Thus, the taskloop construct creates an implicit taskgroup\\n    region. If the `nogroup` clause is present, no implicit taskgroup region is\\n    created.If `num_tasks` is specified, the taskloop construct creates as many tasks as\\n    the minimum of the num-tasks expression and the number of logical loop\\n    iterations. Each task must have at least one logical loop iteration.The `priority` clause is a hint for the priority of the generated tasks.\\n    The `priority` is a non-negative integer expression that provides a hint for\\n    task execution order. Among all tasks ready to be executed, higher priority\\n    tasks (those with a higher numerical value in the priority clause\\n    expression) are recommended to execute before lower priority ones. The\\n    default priority-value when no priority clause is specified should be\\n    assumed to be zero (the lowest priority).Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.If the `untied` clause is present on a task construct, any thread in the\\n    team can resume the task region after a suspension. The `untied` clause is\\n    ignored if a `final` clause is present on the same task construct and the\\n    `final` expression evaluates to `true`, or if a task is an included task.If an `in_reduction` clause is present on the taskloop construct, the\\n    behavior is as if each generated task was defined by a task construct on\\n    which an `in_reduction` clause with the same reduction operator and list\\n    items is present. Thus, the generated tasks are participants of a reduction\\n    previously defined by a reduction scoping clause. In this case, accumulator\\n    variables are specified in `in_reduction_vars`, symbols referring to\\n    reduction declarations in `in_reduction_syms` and `in_reduction_byref`\\n    indicate for each reduction variable whether it should be passed by value or\\n    by reference.\\n\\n    If a `reduction` clause is present on the taskloop construct, the behavior\\n    is as if a `task_reduction` clause with the same reduction operator and list\\n    items was applied to the implicit taskgroup construct enclosing the taskloop\\n    construct. The taskloop construct executes as if each generated task was\\n    defined by a task construct on which an `in_reduction` clause with the same\\n    reduction operator and list items is present. Thus, the generated tasks are\\n    participants of the reduction defined by the `task_reduction` clause that\\n    was applied to the implicit taskgroup construct.\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"final\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"grainsize\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"in_reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"num_tasks\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"priority\", \"type\": \"Optional<AnyInteger>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grainsize_mod\", \"type\": \"OptionalAttr<GrainsizeTypeAttr>\" },\n      { \"name\": \"in_reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"in_reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"mergeable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nogroup\", \"type\": \"UnitAttr\" },\n      { \"name\": \"num_tasks_mod\", \"type\": \"OptionalAttr<NumTasksTypeAttr>\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"untied\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`final` `(` $final `)`|`grainsize` `(` custom<GrainsizeClause>($grainsize_mod , $grainsize, type($grainsize)) `)`|`if` `(` $if_expr `)`|`mergeable` $mergeable|`nogroup` $nogroup|`num_tasks` `(` custom<NumTasksClause>($num_tasks_mod , $num_tasks, type($num_tasks)) `)`|`priority` `(` $priority `:` type($priority) `)`|`untied` $untied)custom<InReductionPrivateReductionRegion>(\\n        $region, $in_reduction_vars, type($in_reduction_vars),\\n        $in_reduction_byref, $in_reduction_syms, $private_vars,\\n        type($private_vars), $private_syms, $private_needs_barrier,\\n        $reduction_mod, $reduction_vars, type($reduction_vars),\\n        $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.taskwait\",\n    \"summary\": \"taskwait construct\",\n    \"description\": \"The taskwait construct specifies a wait on the completion of child tasks\\n    of the current task.The `depend_kinds` and `depend_vars` arguments are variadic lists of values\\n    that specify the dependencies of this particular task in relation to other\\n    tasks.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.\",\n    \"operands\": [\n      { \"name\": \"depend_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depend_kinds\", \"type\": \"OptionalAttr<TypedArrayAttrBase<ClauseTaskDependAttr{taskdependin|taskdependout|taskdependinout|taskdependmutexinoutset|taskdependinoutset}>>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"oilist(`depend` `(`\\n      custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`|`nowait` $nowait) attr-dict\"\n  },\n  {\n    \"name\": \"omp.taskyield\",\n    \"summary\": \"taskyield construct\",\n    \"description\": \"The taskyield construct specifies that the current task can be suspended\\n    in favor of execution of a different task.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"omp.teams\",\n    \"summary\": \"teams construct\",\n    \"description\": \"The teams construct defines a region of code that triggers the creation of a\\n    league of teams. Once created, the number of teams remains constant for the\\n    duration of its code region.\\n\\n    If the `if_expr` is present and it evaluates to `false`, the number of teams\\n    created is one.The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The `num_teams` clause specifies the bounds on the league space formed by the\\n    construct on which it appears.\\n\\n    Multi-dimensional (OpenMP 6.1 dims modifier):\\n    - Uses `num_teams_upper_vars` with multiple values (one per dimension)\\n    - Values may have different types; they will be cast at LLVM IR translation\\n    - Format: `num_teams(to %v0, %v1, ... : type0, type1, ...)`\\n    - Example: `num_teams(to %ub0, %ub1, %ub2 : i32, i64, i32)`\\n    - The number of dimensions is implicitly `num_teams_upper_vars.size()`\\n\\n    Uni-dimensional (legacy format):\\n    - Uses `num_teams_upper_vars` with one value and optional `num_teams_lower`\\n    - If lower bound not specified, it defaults to upper bound value\\n    - Format: `num_teams(%lb : type to %ub : type)` or `num_teams(to %ub : type)`\\n    - Example: `num_teams(%lb : i32 to %ub : i32)` or `num_teams(to %ub : i32)`Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.The `thread_limit` clause specifies the limit on the number of threads.\\n\\n    Multi-dimensional format (dims modifier):\\n    - Multiple values can be specified for multi-dimensional thread limits.\\n    - The number of dimensions is derived from the number of values.\\n    - Values can have different integer types.\\n    - Format: `thread_limit(%v1, %v2, ... : type1, type2, ...)`\\n    - Example: `thread_limit(%n, %m : i32, i64)`\\n\\n    Single value format:\\n    - A single value specifies the thread limit.\\n    - Format: `thread_limit(%value : type)`\\n    - Example: `thread_limit(%n : i32)`\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"if_expr\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"num_teams_lower\", \"type\": \"Optional<IntLikeType>\" },\n      { \"name\": \"num_teams_upper_vars\", \"type\": \"Variadic<IntLikeType>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"thread_limit_vars\", \"type\": \"Variadic<IntLikeType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`if` `(` $if_expr `)`|`num_teams` `(` ( $num_teams_lower^ `:` type($num_teams_lower) )? `to`\\n                  $num_teams_upper_vars `:` type($num_teams_upper_vars) `)`|`thread_limit` `(` $thread_limit_vars `:` type($thread_limit_vars) `)`)custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $reduction_mod, $reduction_vars,\\n        type($reduction_vars), $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.terminator\",\n    \"summary\": \"terminator for OpenMP regions\",\n    \"description\": \"A terminator operation for regions that appear in the body of OpenMP\\n    operation.  These regions are not expected to return any value so the\\n    terminator takes no operands. The terminator op returns control to the\\n    enclosing op.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"omp.threadprivate\",\n    \"summary\": \"threadprivate directive\",\n    \"description\": \"The threadprivate directive specifies that variables are replicated, with\\n    each thread having its own copy.\\n\\n    The current implementation uses the OpenMP runtime to provide thread-local\\n    storage (TLS). Using the TLS feature of the LLVM IR will be supported in\\n    future.\\n\\n    This operation takes in the address of a symbol that represents the original\\n    variable and returns the address of its TLS. All occurrences of\\n    threadprivate variables in a parallel region should use the TLS returned by\\n    this operation.\\n\\n    The `sym_addr` refers to the address of the symbol, which is a pointer to\\n    the original variable.\",\n    \"operands\": [\n      { \"name\": \"sym_addr\", \"type\": \"OpenMP_PointerLikeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"tls_addr\", \"type\": \"OpenMP_PointerLikeType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['sym_addr', 'tls_addr']>\" }\n    ],\n    \"assemblyFormat\": \"$sym_addr `:` type($sym_addr) `->` type($tls_addr) attr-dict\"\n  },\n  {\n    \"name\": \"omp.tile\",\n    \"summary\": \"OpenMP tile operation\",\n    \"description\": \"Represents the OpenMP tile directive introduced in OpenMP 5.1.\\n\\n    The construct partitions the logical iteration space of the affected loops\\n    into equally-sized tiles, then creates two sets of nested loops. The outer\\n    loops, called the grid loops, iterate over all tiles. The inner loops,\\n    called the intratile loops, iterate over the logical iterations of a tile.\\n    The sizes clause determines the size of a tile.\\n\\n    Currently, the affected loops must be rectangular (the tripcount of the\\n    inner loop must not depend on any iv of an surrounding affected loop) and\\n    perfectly nested (except for the innermost affected loop, no operations\\n    other than the nested loop and the terminator in the loop body).The `sizes` clauses defines the size of a grid over a multi-dimensional\\n    logical iteration space. This grid is used for loop transformations such as\\n    `tile` and `strip`. The size per dimension can be a variable, but only\\n    values that are not at least 2 make sense. It is not specified what happens\\n    when smaller values are used, but should still result in a loop nest that\\n    executes each logical iteration once.\",\n    \"operands\": [\n      { \"name\": \"generatees\", \"type\": \"Variadic<CanonicalLoopInfoType>\" },\n      { \"name\": \"applyees\", \"type\": \"Variadic<CanonicalLoopInfoType>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<IntLikeType>\" }\n    ],\n    \"assemblyFormat\": \"custom<LoopTransformClis>($generatees, $applyees)oilist(`sizes` `(` $sizes `:` type($sizes) `)`)attr-dict\"\n  },\n  {\n    \"name\": \"omp.unroll_heuristic\",\n    \"summary\": \"OpenMP heuristic unroll operation\",\n    \"description\": \"Represents a `#pragma omp unroll` construct introduced in OpenMP 5.1.\\n\\n    The operation has one applyee and no generatees. The applyee is unrolled\\n    according to implementation-defined heuristics. Implementations may choose\\n    to not unroll the loop, partially unroll by a chosen factor, or fully\\n    unroll it. Even if the implementation chooses to partially unroll the\\n    applyee, the resulting unrolled loop is not accessible as a generatee. Use\\n    omp.unroll_partial if a generatee is required.\\n\\n    The lowering is implemented using `OpenMPIRBuilder::unrollLoopHeuristic`,\\n    which just attaches `llvm.loop.unroll.enable` metadata to the loop so the\\n    unrolling is carried-out by LLVM's LoopUnroll pass. That is, unrolling only\\n    actually performed in optimized builds.\\n\\n    Assembly formats:\\n      omp.unroll_heuristic(%cli)\\n      omp.unroll_heuristic(%cli) -> ()\",\n    \"operands\": [\n      { \"name\": \"applyee\", \"type\": \"CanonicalLoopInfoType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"omp.workdistribute\",\n    \"summary\": \"workdistribute directive\",\n    \"description\": \"workdistribute divides execution of the enclosed structured block into\\n    separate units of work, each executed only once by each\\n    initial thread in the league.\\n    ```\\n    !$omp target teams\\n        !$omp workdistribute\\n        y = a * x + y \\n        !$omp end workdistribute\\n    !$omp end target teams\\n    ```\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"omp.workshare\",\n    \"summary\": \"workshare directive\",\n    \"description\": \"The workshare construct divides the execution of the enclosed structured\\n    block into separate units of work, and causes the threads of the team to\\n    share the work such that each unit is executed only once by one thread, in\\n    the context of its implicit task\\n\\n    This operation is used for the intermediate representation of the workshare\\n    block before the work gets divided between the threads. See the flang\\n    LowerWorkshare pass for details.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.\",\n    \"attributes\": [\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`nowait` $nowait) $region attr-dict\"\n  },\n  {\n    \"name\": \"omp.workshare.loop_wrapper\",\n    \"summary\": \"contains loop nests to be parallelized by workshare\",\n    \"description\": \"This operation wraps a loop nest that is marked for dividing into units of\\n    work by an encompassing omp.workshare operation.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"omp.wsloop\",\n    \"summary\": \"worksharing-loop construct\",\n    \"description\": \"The worksharing-loop construct specifies that the iterations of the loop(s)\\n    will be executed in parallel by threads in the current context. These\\n    iterations are spread across threads that already exist in the enclosing\\n    parallel region.\\n\\n    The body region can only contain a single block which must contain a single\\n    operation. This operation must be another compatible loop wrapper or an\\n    `omp.loop_nest`.\\n\\n    ```\\n    omp.wsloop <clauses> {\\n      omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {\\n        %a = load %arrA[%i1, %i2] : memref<?x?xf32>\\n        %b = load %arrB[%i1, %i2] : memref<?x?xf32>\\n        %sum = arith.addf %a, %b : f32\\n        store %sum, %arrC[%i1, %i2] : memref<?x?xf32>\\n        omp.yield\\n      }\\n    }\\n    ```The `allocator_vars` and `allocate_vars` parameters are a variadic list of\\n    values that specify the memory allocator to be used to obtain storage for\\n    private values.The `linear_step_vars` operand additionally specifies the step for each\\n    associated linear operand. Note that the `linear_vars` and\\n    `linear_step_vars` variadic lists should contain the same number of\\n    elements.The optional `nowait` attribute, when present, eliminates the implicit\\n    barrier at the end of the construct, so the parent operation can make\\n    progress even if the child operation has not completed yet.The optional `order` attribute specifies which order the iterations of the\\n    associated loops are executed in. Currently the only option for this\\n    attribute is \\\"concurrent\\\".The optional `ordered` attribute specifies how many loops are associated\\n    with the worksharing-loop construct. The value of zero refers to the ordered\\n    clause specified without parameter.Reductions can be performed by specifying the reduction modifer\\n    (`default`, `inscan` or `task`) in `reduction_mod`, reduction accumulator\\n    variables in `reduction_vars`, symbols referring to reduction declarations\\n    in the `reduction_syms` attribute, and whether the reduction variable\\n    should be passed into the reduction region by value or by reference in\\n    `reduction_byref`. Each reduction is identified by the accumulator it uses\\n    and accumulators must not be repeated in the same reduction. A private\\n    variable corresponding to the accumulator is used in place of the\\n    accumulator inside the body of the operation. The reduction declaration\\n    specifies how to combine the values from each iteration, section, team,\\n    thread or simd lane defined by the operation's region into the final value,\\n    which is available in the accumulator after they all complete.The optional `schedule_kind` attribute specifies the loop schedule for this\\n    loop, determining how the loop is distributed across the parallel threads.\\n    The optional `schedule_chunk` associated with this determines further\\n    controls this distribution.\",\n    \"operands\": [\n      { \"name\": \"allocate_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"allocator_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"linear_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"linear_step_vars\", \"type\": \"Variadic<AnyInteger>\" },\n      { \"name\": \"private_vars\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"reduction_vars\", \"type\": \"Variadic<OpenMP_PointerLikeType>\" },\n      { \"name\": \"schedule_chunk\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"linear_var_types\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" },\n      { \"name\": \"order\", \"type\": \"OptionalAttr<OrderKindAttr>\" },\n      { \"name\": \"order_mod\", \"type\": \"OptionalAttr<OrderModifierAttr{reproducible|unconstrained}>\" },\n      { \"name\": \"ordered\", \"type\": \"ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>\" },\n      { \"name\": \"private_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"private_needs_barrier\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reduction_mod\", \"type\": \"OptionalAttr<ReductionModifierAttr{defaultmod|inscan|task}>\" },\n      { \"name\": \"reduction_byref\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"reduction_syms\", \"type\": \"OptionalAttr<TypedArrayAttrBase<SymbolRefAttr>>\" },\n      { \"name\": \"schedule_kind\", \"type\": \"OptionalAttr<ScheduleKindAttr>\" },\n      { \"name\": \"schedule_mod\", \"type\": \"OptionalAttr<ScheduleModifierAttr{none|monotonic|nonmonotonic|simd}>\" },\n      { \"name\": \"schedule_simd\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"oilist(`allocate` `(`\\n      custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),\\n                                   $allocator_vars, type($allocator_vars)) `)`|`linear` `(`\\n      custom<LinearClause>($linear_vars, type($linear_vars),\\n                           $linear_step_vars, type($linear_step_vars)) `)`|`nowait` $nowait|`order` `(` custom<OrderClause>($order, $order_mod) `)`|`ordered` `(` $ordered `)`|`schedule` `(`\\n      custom<ScheduleClause>($schedule_kind, $schedule_mod, $schedule_simd,\\n                             $schedule_chunk, type($schedule_chunk)) `)`)custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),\\n        $private_syms, $private_needs_barrier, $reduction_mod, $reduction_vars,\\n        type($reduction_vars), $reduction_byref, $reduction_syms) attr-dict\"\n  },\n  {\n    \"name\": \"omp.yield\",\n    \"summary\": \"loop yield and termination operation\",\n    \"description\": \"\\\"omp.yield\\\" yields SSA values from the OpenMP dialect op region and\\n    terminates the region. The semantics of how the values are yielded is\\n    defined by the parent operation.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"( `(` $results^ `:` type($results) `)` )? attr-dict\"\n  },\n  {\n    \"name\": \"onnx.Abs\",\n    \"summary\": \"ONNX Abs operation\",\n    \"description\": \"Absolute takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where absolute value, y = abs(x), is applied to\\n  the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Acos\",\n    \"summary\": \"ONNX Acos operation\",\n    \"description\": \"Calculates the arccosine (inverse of cosine) of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Acosh\",\n    \"summary\": \"ONNX Acosh operation\",\n    \"description\": \"Calculates the hyperbolic arccosine of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Adagrad\",\n    \"summary\": \"ONNX Adagrad operation\",\n    \"description\": \"Compute one iteration of ADAGRAD, a stochastic gradient based optimization\\n      algorithm. This operator can conduct the optimization of multiple tensor variables.\\n  \\n      Let's define the behavior of this operator. As you can imagine, ADAGRAD requires\\n      some parameters:\\n  \\n       - The initial learning-rate \\\\\\\"R\\\\\\\".\\n       - The update count \\\\\\\"T\\\\\\\". That is, the number of training iterations conducted.\\n       - A L2-norm regularization coefficient \\\\\\\"norm_coefficient\\\\\\\".\\n       - A learning-rate decay factor \\\\\\\"decay_factor\\\\\\\".\\n       - A small constant \\\\\\\"epsilon\\\\\\\" to avoid dividing-by-zero.\\n  \\n      At each ADAGRAD iteration, the optimized tensors are moved along a direction\\n      computed based on their estimated gradient and accumulated squared gradient. Assume\\n      that only a single tensor \\\\\\\"X\\\\\\\" is updated by this operator. We need the value of \\\\\\\"X\\\\\\\",\\n      its gradient \\\\\\\"G\\\\\\\", and its accumulated squared gradient \\\\\\\"H\\\\\\\". Therefore, variables in\\n      this operator's input list are sequentially \\\\\\\"R\\\\\\\", \\\\\\\"T\\\\\\\", \\\\\\\"X\\\\\\\", \\\\\\\"G\\\\\\\", and \\\\\\\"H\\\\\\\". Other\\n      parameters are given as attributes because they are usually constants. Also, the\\n      corresponding output tensors are the new value of \\\\\\\"X\\\\\\\" (called \\\\\\\"X_new\\\\\\\"), and then\\n      the new accumulated squared gradient (called \\\\\\\"H_new\\\\\\\"). Those outputs are computed\\n      from the given inputs following the pseudo code below.\\n  \\n      Let \\\\\\\"+\\\\\\\", \\\\\\\"-\\\\\\\", \\\\\\\"*\\\\\\\", and \\\\\\\"/\\\\\\\" are all element-wise arithmetic operations with\\n      numpy-style broadcasting support. The pseudo code to compute those outputs is:\\n  \\n        // Compute a scalar learning-rate factor. At the first update of X, T is generally\\n        // 0 (0-based update index) or 1 (1-based update index).\\n        r = R / (1 + T * decay_factor);\\n  \\n        // Add gradient of 0.5 * norm_coefficient * ||X||_2^2, where ||X||_2 is the 2-norm.\\n        G_regularized = norm_coefficient * X + G;\\n  \\n        // Compute new accumulated squared gradient.\\n        H_new = H + G_regularized * G_regularized;\\n  \\n        // Compute the adaptive part of per-coordinate learning rate. Note that Sqrt(...)\\n        // computes element-wise square-root.\\n        H_adaptive = Sqrt(H_new) + epsilon\\n  \\n        // Compute the new value of \\\\\\\"X\\\\\\\".\\n        X_new = X - r * G_regularized / H_adaptive;\\n  \\n      If one assign this operators to optimize multiple inputs, for example, \\\\\\\"X_1\\\\\\\" and \\\\\\\"X_2\\\\\\\", the same\\n      pseudo code may be extended to handle all tensors jointly. More specifically, we can view \\\\\\\"X\\\\\\\" as a\\n      concatenation of \\\\\\\"X_1\\\\\\\" and \\\\\\\"X_2\\\\\\\" (of course, their gradient and accumulate gradient should\\n      be concatenated too) and then just reuse the entire pseudo code.\\n  \\n      Note that ADAGRAD was first proposed in http://jmlr.org/papers/volume12/duchi11a/duchi11a.pdf.\\n      In that reference paper, this operator is a special case of the Figure 1's composite mirror\\n      descent update.\",\n    \"operands\": [\n      { \"name\": \"R\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"T\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"decay_factor\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"norm_coefficient\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Adam\",\n    \"summary\": \"ONNX Adam operation\",\n    \"description\": \"Compute one iteration of Adam, a stochastic gradient based optimization\\n      algorithm. This operator can conduct the optimization of multiple tensor variables.\\n  \\n      Let's define the behavior of this operator. First of all, Adam requires\\n      some parameters:\\n  \\n       - The learning-rate \\\\\\\"R\\\\\\\".\\n       - The update count \\\\\\\"T\\\\\\\". That is, the number of training iterations conducted.\\n       - A L2-norm regularization coefficient \\\\\\\"norm_coefficient\\\\\\\".\\n       - A small constant \\\\\\\"epsilon\\\\\\\" to avoid dividing-by-zero.\\n       - Two coefficients, \\\\\\\"alpha\\\\\\\" and \\\\\\\"beta\\\\\\\".\\n  \\n      At each Adam iteration, the optimized tensors are moved along a direction\\n      computed based on their exponentially-averaged historical gradient and\\n      exponentially-averaged historical squared gradient. Assume that only a tensor\\n      \\\\\\\"X\\\\\\\" is being optimized. The rest of required information is\\n  \\n       - the value of \\\\\\\"X\\\\\\\",\\n       - \\\\\\\"X\\\\\\\"'s gradient (denoted by \\\\\\\"G\\\\\\\"),\\n       - \\\\\\\"X\\\\\\\"'s exponentially-averaged historical gradient (denoted by \\\\\\\"V\\\\\\\"), and\\n       - \\\\\\\"X\\\\\\\"'s exponentially-averaged historical squared gradient (denoted by \\\\\\\"H\\\\\\\").\\n  \\n      Some of those parameters are passed into this operator as input tensors and others\\n      are stored as this operator's attributes. Specifically, this operator's input tensor\\n      list is [\\\\\\\"R\\\\\\\", \\\\\\\"T\\\\\\\", \\\\\\\"X\\\\\\\", \\\\\\\"G\\\\\\\", \\\\\\\"V\\\\\\\", \\\\\\\"H\\\\\\\"]. That is, \\\\\\\"R\\\\\\\" is the first input, \\\\\\\"T\\\\\\\" is\\n      the second input, and so on. Other parameters are given as attributes because they\\n      are constants. Moreover, the corresponding output tensors are\\n  \\n       - the new value of \\\\\\\"X\\\\\\\" (called \\\\\\\"X_new\\\\\\\"),\\n       - the new exponentially-averaged historical gradient (denoted by \\\\\\\"V_new\\\\\\\"), and\\n       - the new exponentially-averaged historical squared gradient (denoted by \\\\\\\"H_new\\\\\\\").\\n  \\n      Those outputs are computed following the pseudo code below.\\n  \\n      Let \\\\\\\"+\\\\\\\", \\\\\\\"-\\\\\\\", \\\\\\\"*\\\\\\\", and \\\\\\\"/\\\\\\\" are all element-wise arithmetic operations with\\n      numpy-style broadcasting support. The pseudo code to compute those outputs is:\\n  \\n        // Add gradient of 0.5 * norm_coefficient * ||X||_2^2, where ||X||_2 is the 2-norm.\\n        G_regularized = norm_coefficient * X + G\\n  \\n        // Update exponentially-averaged historical gradient.\\n        V_new = alpha * V + (1 - alpha) * G_regularized\\n  \\n        // Update exponentially-averaged historical squared gradient.\\n        H_new = beta * H + (1 - beta) * G_regularized * G_regularized\\n  \\n        // Compute the element-wise square-root of H_new. V_new will be element-wisely\\n        // divided by H_sqrt for a better update direction.\\n        H_sqrt = Sqrt(H_new) + epsilon\\n  \\n        // Compute learning-rate. Note that \\\\\\\"alpha**T\\\\\\\"/\\\\\\\"beta**T\\\\\\\" is alpha's/beta's T-th power.\\n        R_adjusted = T > 0 ? R * Sqrt(1 - beta**T) / (1 - alpha**T) : R\\n  \\n        // Compute new value of \\\\\\\"X\\\\\\\".\\n        X_new = X - R_adjusted * V_new / H_sqrt\\n  \\n        // Post-update regularization.\\n        X_final = (1 - norm_coefficient_post) * X_new\\n  \\n      If there are multiple inputs to be optimized, the pseudo code will be applied\\n      independently to each of them.\",\n    \"operands\": [\n      { \"name\": \"R\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"T\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 0.9>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F32Attr, 0.999>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"norm_coefficient\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"norm_coefficient_post\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Add\",\n    \"summary\": \"ONNX Add operation\",\n    \"description\": \"Performs element-wise binary addition (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\\n  \\n  (Opset 14 change): Extend supported types to include uint8, int8, uint16, and int16.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.And\",\n    \"summary\": \"ONNX And operation\",\n    \"description\": \"Returns the tensor resulted from performing the `and` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"B\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ArgMax\",\n    \"summary\": \"ONNX ArgMax operation\",\n    \"description\": \"Computes the indices of the max elements of the input tensor's element along the\\n  provided axis. The resulting tensor has the same rank as the input if keepdims equals 1.\\n  If keepdims equals 0, then the resulting tensor has the reduced dimension pruned.\\n  If select_last_index is True (default False), the index of the last occurrence of the max\\n  is selected if the max appears more than once in the input. Otherwise the index of the\\n  first occurrence is selected.\\n  The type of the output tensor is integer.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"select_last_index\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ArgMin\",\n    \"summary\": \"ONNX ArgMin operation\",\n    \"description\": \"Computes the indices of the min elements of the input tensor's element along the\\n  provided axis. The resulting tensor has the same rank as the input if keepdims equals 1.\\n  If keepdims equals 0, then the resulting tensor has the reduced dimension pruned.\\n  If select_last_index is True (default False), the index of the last occurrence of the min\\n  is selected if the min appears more than once in the input. Otherwise the index of the\\n  first occurrence is selected.\\n  The type of the output tensor is integer.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"select_last_index\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ArrayFeatureExtractor\",\n    \"summary\": \"ONNX ArrayFeatureExtractor operation\",\n    \"description\": \"Select elements of the input tensor based on the indices passed.<br>\\n      The indices are applied to the last axes of the tensor.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>, TensorOf<[StringType]>]>\" },\n      { \"name\": \"Y\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Z\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>, TensorOf<[StringType]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Asin\",\n    \"summary\": \"ONNX Asin operation\",\n    \"description\": \"Calculates the arcsine (inverse of sine) of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Asinh\",\n    \"summary\": \"ONNX Asinh operation\",\n    \"description\": \"Calculates the hyperbolic arcsine of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Atan\",\n    \"summary\": \"ONNX Atan operation\",\n    \"description\": \"Calculates the arctangent (inverse of tangent) of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Atanh\",\n    \"summary\": \"ONNX Atanh operation\",\n    \"description\": \"Calculates the hyperbolic arctangent of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.AveragePool\",\n    \"summary\": \"ONNX AveragePool operation\",\n    \"description\": \"AveragePool consumes an input tensor X and applies average pooling across\\n   the tensor according to kernel sizes, stride sizes, and pad lengths.\\n   average pooling consisting of computing the average on all values of a\\n   subset of the input tensor according to the kernel size and downsampling the\\n   data into the output tensor Y for further processing. The output spatial shape is calculated differently\\n   depending on whether explicit padding is used, where pads is employed, or auto padding is used, where auto_pad is utilized.\\n   With explicit padding (https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html?highlight=maxpool#torch.nn.MaxPool2d):\\n   ```\\n   output_spatial_shape[i] = floor((input_spatial_shape[i] + pad_shape[i] - dilation[i] * (kernel_shape[i] - 1) - 1) / strides_spatial_shape[i] + 1)\\n   ```\\n   or\\n   ```\\n   output_spatial_shape[i] = ceil((input_spatial_shape[i] + pad_shape[i] - dilation[i] * (kernel_shape[i] - 1) - 1) / strides_spatial_shape[i] + 1)\\n   ```\\n   if ceil_mode is enabled. `pad_shape[i]` is the sum of pads along axis `i`. Sliding windows that would start in the right padded region are ignored.\\n  \\n   `auto_pad` is a DEPRECATED attribute. If you are using them currently, the output spatial shape will be following when ceil_mode is enabled:\\n   ```\\n   VALID: output_spatial_shape[i] = ceil((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) + 1) / strides_spatial_shape[i])\\n   SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides_spatial_shape[i])\\n   ```\\n   or when ceil_mode is disabled (https://www.tensorflow.org/api_docs/python/tf/keras/layers/AveragePooling2D):\\n   ```\\n   VALID: output_spatial_shape[i] = floor((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1)) / strides_spatial_shape[i]) + 1\\n   SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = floor((input_spatial_shape[i] - 1) / strides_spatial_shape[i]) + 1\\n   ```\\n   And pad shape will be following if `SAME_UPPER` or `SAME_LOWER`:\\n   ```\\n   pad_shape[i] = (output_spatial_shape[i] - 1) * strides_spatial_shape[i] + ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) - input_spatial_shape[i]\\n   ```\\n   The output of each pooling window is divided by the number of elements (exclude pad when attribute count_include_pad is zero).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BatchNormalization\",\n    \"summary\": \"ONNX BatchNormalization operation\",\n    \"description\": \"Carries out batch normalization as described in the paper\\n  https://arxiv.org/abs/1502.03167. Depending on the mode it is being run,\\n  There are five required inputs 'X', 'scale', 'B', 'input_mean' and\\n  'input_var'.\\n  Note that 'input_mean' and 'input_var' are expected to be the estimated\\n  statistics in inference mode (training_mode=False, default),\\n  and the running statistics in training mode (training_mode=True).\\n  There are multiple cases for the number of outputs, which we list below:\\n  \\n  * Output case #1: Y, running_mean, running_var (training_mode=True)\\n  * Output case #2: Y (training_mode=False)\\n  \\n  When training_mode=False, extra outputs are invalid.\\n  The outputs are updated as follows when training_mode=True:\\n  ```\\n  running_mean = input_mean * momentum + current_mean * (1 - momentum)\\n  running_var = input_var * momentum + current_var * (1 - momentum)\\n  \\n  Y = (X - current_mean) / sqrt(current_var + epsilon) * scale + B\\n  ```\\n  where:\\n  ```\\n  current_mean = ReduceMean(X, axis=all_except_channel_index)\\n  current_var =  ReduceVar(X, axis=all_except_channel_index)\\n  ```\\n  Notice that `ReduceVar` refers to the population variance, and it equals to\\n  `sum(sqrd(x_i - x_avg)) / N`\\n  where `N` is the population size (this formula does not use sample size `N - 1`).\\n  \\n  The computation of ReduceMean and ReduceVar uses float to avoid overflow for float16 inputs.\\n  \\n  When training_mode=False:\\n  ```\\n  Y = (X - input_mean) / sqrt(input_var + epsilon) * scale + B\\n  ```\\n  \\n  For previous (depreciated) non-spatial cases, implementors are suggested\\n  to flatten the input shape to (N x C * D1 * D2 * ... * Dn) before a BatchNormalization Op.\\n  This operator has **optional** inputs/outputs. See [the doc](IR.md) for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"scale\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"input_mean\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"input_var\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"momentum\", \"type\": \"DefaultValuedAttr<F32Attr, 0.9>\" },\n      { \"name\": \"training_mode\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BatchNormalizationInferenceMode\",\n    \"summary\": \"ONNX BatchNormalization operation in test mode\",\n    \"description\": \"Carries out batch normalization as described in the paper\\n    https://arxiv.org/abs/1502.03167. Depending on the mode it is being run,\\n    there are multiple cases for the number of outputs, which we list below:\\n\\n    Output case #1: Y, mean, var, saved_mean, saved_var (training mode)\\n    Output case #2: Y (test mode)\\\"\\n\\n    For previous (depreciated) non-spatial cases, implementors are suggested\\n    to flatten the input shape to (N x C*D1*D2 ..*Dn) before a BatchNormalization Op.\\n    This operator has **optional** inputs/outputs. See [the doc](IR.md)\\n    for more details about the representation of optional arguments.\\n    An empty string may be used in the place of an actual argument's name to\\n    indicate a missing argument. Trailing optional arguments (those not followed\\n    by an argument that is present) may also be simply omitted.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" },\n      { \"name\": \"scale\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" },\n      { \"name\": \"mean\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" },\n      { \"name\": \"var\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"o_Y\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"momentum\", \"type\": \"DefaultValuedAttr<F32Attr, 0.9>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Bernoulli\",\n    \"summary\": \"ONNX Bernoulli operation\",\n    \"description\": \"Draws binary random numbers (0 or 1) from a Bernoulli distribution. The input tensor should be a tensor\\n  containing probabilities p (a value in the range [0,1]) to be used for drawing the binary random number,\\n  where an output of 1 is produced with probability p and an output of 0 is produced with probability (1-p).\\n  \\n  This operator is non-deterministic and may not produce the same values in different\\n  implementations (even if a seed is specified).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I1]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Binarizer\",\n    \"summary\": \"ONNX Binarizer operation\",\n    \"description\": \"Maps the values of the input tensor to either 0 or 1, element-wise, based on the outcome of a comparison against a threshold value.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"threshold\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BitShift\",\n    \"summary\": \"ONNX BitShift operation\",\n    \"description\": \"Bitwise shift operator performs element-wise operation. For each input element, if the\\n  attribute \\\\\\\"direction\\\\\\\" is \\\\\\\"RIGHT\\\\\\\", this operator moves its binary representation toward\\n  the right side so that the input value is effectively decreased. If the attribute \\\\\\\"direction\\\\\\\"\\n  is \\\\\\\"LEFT\\\\\\\", bits of binary representation moves toward the left side, which results the\\n  increase of its actual value. The input X is the tensor to be shifted and another input\\n  Y specifies the amounts of shifting. For example, if \\\\\\\"direction\\\\\\\" is \\\\\\\"Right\\\\\\\", X is [1, 4],\\n  and S is [1, 1], the corresponding output Z would be [0, 2]. If \\\\\\\"direction\\\\\\\" is \\\\\\\"LEFT\\\\\\\" with\\n  X=[1, 2] and S=[1, 2], the corresponding output Y would be [2, 8].\\n  \\n  Because this operator supports Numpy-style broadcasting, X's and Y's shapes are\\n  not necessarily identical.\\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>]>\" },\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Z\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"direction\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BitwiseAnd\",\n    \"summary\": \"ONNX BitwiseAnd operation\",\n    \"description\": \"Returns the tensor resulting from performing the bitwise `and` operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BitwiseNot\",\n    \"summary\": \"ONNX BitwiseNot operation\",\n    \"description\": \"Returns the bitwise not of the input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BitwiseOr\",\n    \"summary\": \"ONNX BitwiseOr operation\",\n    \"description\": \"Returns the tensor resulting from performing the bitwise `or` operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BitwiseXor\",\n    \"summary\": \"ONNX BitwiseXor operation\",\n    \"description\": \"Returns the tensor resulting from performing the bitwise `xor` operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.BlackmanWindow\",\n    \"summary\": \"ONNX BlackmanWindow operation\",\n    \"description\": \"Generates a Blackman window as described in the paper https://ieeexplore.ieee.org/document/1455106.\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_datatype\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"periodic\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Cast\",\n    \"summary\": \"ONNX Cast operation\",\n    \"description\": \"The operator casts the elements of a given input tensor to a data type\\n  specified by the 'to' argument and returns an output tensor of the same size in\\n  the converted type. The 'to' argument must be one of the data types specified\\n  in the 'DataType' enum field in the TensorProto message.\\n  \\n  Casting from string tensor in plain (e.g., \\\\\\\"3.14\\\\\\\" and \\\\\\\"1000\\\\\\\") and scientific numeric representations\\n  (e.g., \\\\\\\"1e-5\\\\\\\" and \\\\\\\"1E8\\\\\\\") to float types is supported. For example, converting string \\\\\\\"100.5\\\\\\\" to an integer may\\n  yield result 100. There are some string literals reserved for special floating-point values;\\n  \\\\\\\"+INF\\\\\\\" (and \\\\\\\"INF\\\\\\\"), \\\\\\\"-INF\\\\\\\", and \\\\\\\"NaN\\\\\\\" are positive infinity, negative infinity, and not-a-number, respectively.\\n  Any string which can exactly match \\\\\\\"+INF\\\\\\\" in a case-insensitive way would be mapped to positive infinite. Similarly,\\n  this case-insensitive rule is applied to \\\\\\\"INF\\\\\\\" and \\\\\\\"NaN\\\\\\\". When casting from numeric tensors\\n  to string tensors, plain floating-point representation (such as \\\\\\\"314.15926\\\\\\\") would be used.\\n  Converting non-numerical-literal string such as \\\\\\\"Hello World!\\\\\\\" is an undefined behavior. Cases\\n  of converting string representing floating-point arithmetic value, such as \\\\\\\"2.718\\\\\\\", to INT is an undefined behavior.\\n  \\n  Conversion from a numerical type to any numerical type is always allowed.\\n  User must be aware of precision loss and value change caused by range difference between two types.\\n  For example, a 64-bit float 3.1415926459 may be round to a 32-bit float 3.141592. Similarly, converting\\n  an integer 36 to Boolean may produce 1 because we truncate bits which can't be stored in the targeted type.\\n  \\n  In more detail, the conversion among numerical types should follow these rules\\n  if the destination type is not a float 8 type.\\n  \\n  * Casting from floating point to:\\n    * floating point: +/- infinity if OOR (out of range).\\n    * fixed point: undefined if OOR.\\n    * bool: +/- 0.0 to False; all else to True.\\n  * Casting from fixed point to:\\n    * floating point: +/- infinity if OOR. (+ infinity in the case of uint)\\n    * fixed point: when OOR, discard higher bits and reinterpret (with respect to two's complement representation for\\n      signed types). For example, 200 (int16) -> -56 (int8).\\n    * bool: zero to False; nonzero to True.\\n  * Casting from bool to:\\n    * floating point: `{1.0, 0.0}`.\\n    * fixed point: `{1, 0}`.\\n    * bool: no change.\\n  \\n  Float 8 type were introduced to speed up the training of\\n  deep models. By default the conversion of a float *x* obeys\\n  to the following rules. `[x]` means the value rounded to\\n  the target mantissa width.\\n  \\n  | x                 | E4M3FN   | E4M3FNUZ | E5M2     | E5M2FNUZ |\\n  | ----------------- | -------- | -------- | -------- | -------- |\\n  | 0                 | 0        | 0        | 0        | 0        |\\n  | -0                | -0       | 0        | -0       | 0        |\\n  | NaN               | NaN      | NaN      | NaN      | NaN      |\\n  | Inf               | FLT_MAX  | NaN      | FLT_MAX  | NaN      |\\n  | -Inf              | -FLT_MAX | NaN      | -FLT_MAX | NaN      |\\n  | \\\\[x\\\\] > FLT_MAX   | FLT_MAX  | FLT_MAX  | FLT_MAX  | FLT_MAX  |\\n  | \\\\[x\\\\] \\\\< -FLT_MAX | -FLT_MAX | -FLT_MAX | -FLT_MAX | -FLT_MAX |\\n  | else              | RNE      | RNE      | RNE      | RNE      |\\n  \\n  The behavior changes if the parameter 'saturate' is set to False.\\n  The rules then become:\\n  \\n  | x                 | E4M3FN | E4M3FNUZ | E5M2 | E5M2FNUZ |\\n  | ----------------- | ------ | -------- | ---- | -------- |\\n  | 0                 | 0      | 0        | 0    | 0        |\\n  | -0                | -0     | 0        | -0   | 0        |\\n  | NaN               | NaN    | NaN      | NaN  | NaN      |\\n  | -NaN              | -NaN   | NaN      | -NaN | NaN      |\\n  | Inf               | NaN    | NaN      | Inf  | NaN      |\\n  | -Inf              | -NaN   | NaN      | -Inf | NaN      |\\n  | \\\\[x\\\\] > FLT_MAX   | NaN    | NaN      | Inf  | NaN      |\\n  | \\\\[x\\\\] \\\\< -FLT_MAX | NaN    | NaN      | -Inf | NaN      |\\n  | else              | RNE    | RNE      | RNE  | RNE      |\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I1]>, TensorOf<[StringType]>, TensorOf<[BF16]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I1]>, TensorOf<[StringType]>, TensorOf<[BF16]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"saturate\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"to\", \"type\": \"TypeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.CastLike\",\n    \"summary\": \"ONNX CastLike operation\",\n    \"description\": \"The operator casts the elements of a given input tensor (the first input) to\\n  the same data type as the elements of the second input tensor.\\n  See documentation of the Cast operator for further details.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I1]>, TensorOf<[StringType]>, TensorOf<[BF16]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" },\n      { \"name\": \"target_type\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I1]>, TensorOf<[StringType]>, TensorOf<[BF16]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I1]>, TensorOf<[StringType]>, TensorOf<[BF16]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"saturate\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.CastMap\",\n    \"summary\": \"ONNX CastMap operation\",\n    \"description\": \"Converts a map to a tensor.<br>The map key must be an int64 and the values will be ordered\\n      in ascending order based on this key.<br>The operator supports dense packing or sparse packing.\\n      If using sparse packing, the key cannot exceed the max_map-1 value.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TupleOf<[I64, StringType]>, TupleOf<[I64, F32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[F32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cast_to\", \"type\": \"DefaultValuedStrAttr<StrAttr, TO_FLOAT>\" },\n      { \"name\": \"map_form\", \"type\": \"DefaultValuedStrAttr<StrAttr, DENSE>\" },\n      { \"name\": \"max_map\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.CategoryMapper\",\n    \"summary\": \"ONNX CategoryMapper operation\",\n    \"description\": \"Converts strings to integers and vice versa.<br>\\n      Two sequences of equal length are used to map between integers and strings,\\n      with strings and integers at the same index detailing the mapping.<br>\\n      Each operator converts either integers to strings or strings to integers, depending\\n      on which default value attribute is provided. Only one default value attribute\\n      should be defined.<br>\\n      If the string default value is set, it will convert integers to strings.\\n      If the int default value is set, it will convert strings to integers.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cats_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"cats_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"default_int64\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" },\n      { \"name\": \"default_string\", \"type\": \"DefaultValuedStrAttr<StrAttr, _Unused>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Ceil\",\n    \"summary\": \"ONNX Ceil operation\",\n    \"description\": \"Ceil takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the ceil is, y = ceil(x), is applied to\\n  the tensor elementwise. If x is integral, +0, -0, NaN,  or infinite, x itself is returned.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Celu\",\n    \"summary\": \"ONNX Celu operation\",\n    \"description\": \"Continuously Differentiable Exponential Linear Units:\\n  Perform the linear unit element-wise on the input tensor X\\n  using formula:\\n  \\n  ```\\n  max(0,x) + min(0,alpha*(exp(x/alpha)-1))\\n  ```\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.CenterCropPad\",\n    \"summary\": \"ONNX CenterCropPad operation\",\n    \"description\": \"Center crop or pad an input to given dimensions.\\n  \\n  The crop/pad dimensions can be specified for a subset of the `axes`; unspecified dimensions will remain unchanged.\\n  \\n  If the input dimensions are larger than the target crop dimensions, a centered cropping window will be extracted\\n  from the input. The starting value for the cropping window is rounded down, which means that if the difference\\n  between the input shape and the crop shape is odd, the cropping window will be shifted half a pixel to the left\\n  of the input center.\\n  \\n  If the input dimensions are smaller than the target crop dimensions, the input will be padded equally on both sides\\n  to center it in the output. In cases where the total number of padding pixels is odd, an additional pixel will be\\n  added to the right side.\\n  \\n  The padding value used is zero.\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"shape\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Clip\",\n    \"summary\": \"ONNX Clip operation\",\n    \"description\": \"Clip operator limits the given input within an interval. The interval is\\n  specified by the inputs 'min' and 'max'. They default to\\n  numeric_limits::lowest() and numeric_limits::max(), respectively.\\n  When 'min' is greater than 'max', the clip operator sets all the 'input' values to\\n  the value of 'max'. Thus, this is equivalent to 'Min(max, Max(input, min))'.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"min\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" },\n      { \"name\": \"max\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ClipV11\",\n    \"summary\": \"ONNX Clip operation\",\n    \"description\": \"Clip operator limits the given input within an interval. The interval is\\n  specified by the inputs 'min' and 'max'. They default to\\n  numeric_limits::lowest() and numeric_limits::max(), respectively.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"min\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"max\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ClipV12\",\n    \"summary\": \"ONNX Clip operation\",\n    \"description\": \"Clip operator limits the given input within an interval. The interval is\\n  specified by the inputs 'min' and 'max'. They default to\\n  numeric_limits::lowest() and numeric_limits::max(), respectively.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"min\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"max\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ClipV6\",\n    \"summary\": \"ONNX Clip operation\",\n    \"description\": \"Clip operator limits the given input within an interval. The interval is\\n  specified with arguments 'min' and 'max'. They default to\\n  numeric_limits::lowest() and numeric_limits::max() respectively.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max\", \"type\": \"DefaultValuedAttr<F32Attr, (3.402823e+38)>\" },\n      { \"name\": \"min\", \"type\": \"DefaultValuedAttr<F32Attr, (-3.402823e+38)>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Col2Im\",\n    \"summary\": \"ONNX Col2Im operation\",\n    \"description\": \"The operator rearranges column blocks back into a multidimensional image\\n  \\n  Col2Im behaves similarly to PyTorch's fold https://pytorch.org/docs/stable/generated/torch.nn.Fold.html,\\n  but it only supports *batched* multi-dimensional image tensors.\\n  Another implementation in Python with N-dimension support can be found at https://github.com/f-dangel/unfoldNd/.\\n  \\n  NOTE:\\n    Although specifying image_shape looks redundant because it could be calculated from\\n    convolution formulas, it is required as input for more advanced scenarios as explained\\n    at PyTorch's implementation (https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/native/Col2Im.cpp#L10)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"image_shape\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"block_shape\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Compress\",\n    \"summary\": \"ONNX Compress operation\",\n    \"description\": \"Selects slices from an input tensor along a given axis where condition evaluates to True for each axis index.\\n      In case axis is not provided, input is flattened before elements are selected.\\n      Compress behaves like numpy.compress: https://docs.scipy.org/doc/numpy/reference/generated/numpy.compress.html\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"condition\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<SI64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Concat\",\n    \"summary\": \"ONNX Concat operation\",\n    \"description\": \"Concatenate a list of tensors into a single tensor. All input tensors must have the same shape, except for the dimension size of the axis to concatenate on.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"concat_result\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ConcatFromSequence\",\n    \"summary\": \"ONNX ConcatFromSequence operation\",\n    \"description\": \"Concatenate a sequence of tensors into a single tensor.\\n  All input tensors must have the same shape, except for the dimension size of the axis to concatenate on.\\n  By default 'new_axis' is 0, the behavior is similar to numpy.concatenate.\\n  When 'new_axis' is 1, the behavior is similar to numpy.stack.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"concat_result\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI64Attr\" },\n      { \"name\": \"new_axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ConcatShapeTranspose\",\n    \"summary\": \"ONNX merged operation\",\n    \"description\": \"Merge the following sequence of ops into one op\\n    v1 = onnx.concat\\n    v2 = onnx.shape(v1)\\n    v3 = onnx.transpose(v1)\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"shape\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"transposed\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI64Attr\" },\n      { \"name\": \"end\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"start\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"perm\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Constant\",\n    \"summary\": \"ONNX Constant operation\",\n    \"description\": \"This operator produces a constant tensor. Exactly one of the provided attributes, either value, sparse_value,\\n  or value_* must be specified.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sparse_value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"value_float\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"value_floats\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"value_int\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"value_ints\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"value_string\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"value_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"onnx.ConstantOfShape\",\n    \"category\": \"Shape\",\n    \"summary\": \"ONNX ConstantOfShape operation\",\n    \"description\": \"Generate a tensor with given value and shape.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I1]>, TensorOf<[BF16]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"onnx.Conv\",\n    \"category\": \"Layer\",\n    \"summary\": \"ONNX Conv operation\",\n    \"description\": \"The convolution operator consumes an input tensor and a filter, and\\n  computes the output.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"W\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ConvInteger\",\n    \"summary\": \"ONNX ConvInteger operation\",\n    \"description\": \"The integer convolution operator consumes an input tensor, its zero-point, a filter, and its zero-point,\\n  and computes the output. The production MUST never overflow. The accumulation may overflow if and only if in 32 bits.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"w\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"x_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, NoneType]>\" },\n      { \"name\": \"w_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ConvTranspose\",\n    \"summary\": \"ONNX ConvTranspose operation\",\n    \"description\": \"The convolution transpose operator consumes an input tensor and a filter,\\n  and computes the output.\\n  \\n  If the pads parameter is provided the shape of the output is calculated via the following equation:\\n  \\n    output_shape[i] = stride[i] * (input_size[i] - 1) + output_padding[i] + ((kernel_shape[i] - 1) * dilations[i] + 1) - pads[start_i] - pads[end_i]\\n  \\n  output_shape can also be explicitly specified in which case pads values are auto generated using these equations:\\n  \\n    total_padding[i] = stride[i] * (input_size[i] - 1) + output_padding[i] + ((kernel_shape[i] - 1) * dilations[i] + 1) - output_shape[i]\\n    If (auto_pads == SAME_UPPER): pads[start_i] = total_padding[i]/2; pads[end_i] = total_padding[i] - (total_padding[i]/2)\\n    Else: pads[start_i] = total_padding[i] - (total_padding[i]/2); pads[end_i] = (total_padding[i]/2).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"W\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"output_padding\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"output_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Cos\",\n    \"summary\": \"ONNX Cos operation\",\n    \"description\": \"Calculates the cosine of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Cosh\",\n    \"summary\": \"ONNX Cosh operation\",\n    \"description\": \"Calculates the hyperbolic cosine of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.CumSum\",\n    \"summary\": \"ONNX CumSum operation\",\n    \"description\": \"Performs cumulative sum of the input elements along the given axis.\\n  By default, it will do the sum inclusively meaning the first element is copied as is.\\n  Through an `exclusive` attribute, this behavior can change to exclude the first element.\\n  It can also perform summation in the opposite direction of the axis. For that, set `reverse` attribute to 1.\\n  \\n  Example:\\n  ```\\n  input_x = [1, 2, 3]\\n  axis=0\\n  output = [1, 3, 6]\\n  exclusive=1\\n  output = [0, 1, 3]\\n  exclusive=0\\n  reverse=1\\n  output = [6, 5, 3]\\n  exclusive=1\\n  reverse=1\\n  output = [5, 3, 0]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axis\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"reverse\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Custom\",\n    \"summary\": \"ONNX Custom operation\",\n    \"description\": \"CustomOp is not an Op defined in onnx standard and was added to support\\n    extention of Op that can be transformed or finally call a user-defined\\n    external function.\\\"\\n\\n    It allows for calling a user-defined operation, with a single required\\n    attribute being a string that names the operation. Other inputs are passed\\n    to the user operation.\\n\\n    The number of inputs and outputs can vary.\\n\\n    NoneType is allowed for both input and output, as the CustomOp may require\\n    a fixed number of inputs/outputs for the external function call.\\n\\n    In addition to the values passed to the user-defined operation, certain\\n    attributes are introduced to facilitate the analysis and transformation of\\n    CustomOp.\\n\\n    Since the compiler does not define the semantics of CustomOp, onnx-mlir\\n    cannot infer the shape of its output. Consequently, specific attributes are\\n    introduced to specify how shape inference should be performed on a CustomOp.\\n    These attributes are:\\n      'inputs_for_infer':\\n           Optional. The index of inputs used for shape inference.\\n           The value of index should be [0, the number of inputs).\\n           If not specified, all the inputs of the CustomOp will be used for\\n           shape inference.\\n      'shape_infer_pattern':\\n           Optional. Specify how to propagate the shape info from the inputs\\n           (may be limited by inputs_for_infer) to output. Current supported\\n           patterns are `SameAs`, `MDBroadcast`.\\n      'output_element_type':\\n           Optional. The element type for the output tensor. If not specified,\\n           follow the shape infer pattern behavior. Usually the element type of\\n           the first input is used.\\n    Each instance of CustomOp can have its own attributes for shape inference,\\n    allowing for customization. However, CustomOps with the same function_name\\n    typically behave similarly in terms of shape inference, and therefore have\\n    the same attributes.\\n\\n    The existing shape inference patterns for ONNX ops are reused for CustomOp,\\n    with the polymorphism in shape inference based on its attribute values.\\n    Due to the current implementation for ONNX Ops, a CustomOp with specified\\n    shape inference attributes supports only a single output, rather than\\n    variadic outputs.\\n\\n    When attributes for shape inference are not provided, the shape inference\\n    for CustomOp will simply pass through.\\n\\n    All of these additional attributes are optional, designed to be less\\n    intrusive. The .mlir file can remain the same when a new attribute is\\n    added.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, AnyMemRef, NoneType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, AnyMemRef, NoneType ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"output_element_type\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"shape_infer_pattern\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"inputs_for_infer\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DeformConv\",\n    \"summary\": \"ONNX DeformConv operation\",\n    \"description\": \"Performs deformable convolution as described in https://arxiv.org/abs/1703.06211 and https://arxiv.org/abs/1811.11168.\\n  This operator specification supports the general N-D case. Note that most common use cases have 2D or 3D data.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"W\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"offset\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"mask\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"offset_group\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DepthToSpace\",\n    \"summary\": \"ONNX DepthToSpace operation\",\n    \"description\": \"DepthToSpace rearranges (permutes) data from depth into blocks of spatial data.\\n  This is the reverse transformation of SpaceToDepth. More specifically, this op outputs a copy of\\n  the input tensor where values from the depth dimension are moved in spatial blocks to the height\\n  and width dimensions. By default, `mode` = `DCR`.\\n  In the DCR mode, elements along the depth dimension from the input tensor are rearranged in the\\n  following order: depth, column, and then row. The output y is computed from the input x as below:\\n  \\n  ```\\n  b, c, h, w = x.shape\\n  tmp = np.reshape(x, [b, blocksize, blocksize, c // (blocksize**2), h, w])\\n  tmp = np.transpose(tmp, [0, 3, 4, 1, 5, 2])\\n  y = np.reshape(tmp, [b, c // (blocksize**2), h * blocksize, w * blocksize])\\n  ```\\n  \\n  In the CRD mode, elements along the depth dimension from the input tensor are rearranged in the\\n  following order: column, row, and the depth. The output y is computed from the input x as below:\\n  \\n  ```\\n  b, c, h, w = x.shape\\n  tmp = np.reshape(x, [b, c // (blocksize ** 2), blocksize, blocksize, h, w])\\n  tmp = np.transpose(tmp, [0, 1, 4, 2, 5, 3])\\n  y = np.reshape(tmp, [b, c // (blocksize ** 2), h * blocksize, w * blocksize])\\n  ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blocksize\", \"type\": \"SI64Attr\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, DCR>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DequantizeLinear\",\n    \"summary\": \"ONNX DequantizeLinear operation\",\n    \"description\": \"The linear dequantization operator. It consumes a quantized tensor, a scale, and a zero point to compute the full precision tensor.\\n  The dequantization formula is `y = (x - x_zero_point) * x_scale`. `x_scale` and `x_zero_point` must have same shape, and can be either a scalar\\n  for per-tensor / per layer quantization, or a 1-D tensor for per-axis quantization.\\n  `x_zero_point` and `x` must have same type. `x` and `y` must have same shape. In the case of dequantizing int32,\\n  there's no zero point (zero point is supposed to be 0).\\n  `zero-point` is usually not used in the case of float8e4m3fn, float8e4m3fnuz, float8e5m2, float8e5m2fnuz quantization,\\n  but the dequantization formula remains the same for consistency and 'x_scale' still determines the output type.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, TensorOf<[I32]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" },\n      { \"name\": \"x_scale\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"x_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, TensorOf<[I32]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Det\",\n    \"summary\": \"ONNX Det operation\",\n    \"description\": \"Det calculates determinant of a square matrix or batches of square matrices.\\n  Det takes one input tensor of shape `[*, M, M]`, where `*` is zero or more batch dimensions,\\n  and the inner-most 2 dimensions form square matrices.\\n  The output is a tensor of shape `[*]`, containing the determinants of all input submatrices.\\n  e.g., When the input is 2-D, the output is a scalar(shape is empty: `[]`).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DFT\",\n    \"summary\": \"ONNX DFT operation\",\n    \"description\": \"Computes the discrete Fourier Transform (DFT) of the input.\\n  \\n  Assuming the input has shape `[M, N]`, where `N` is the dimension over which the\\n  DFT is computed and `M` denotes the conceptual \\\\\\\"all other dimensions,\\\\\\\"\\n  the DFT `y[m, k]` of shape `[M, N]` is defined as\\n  \\n  $$y[m, k] = \\\\sum_{n=0}^{N-1} e^{-2 \\\\pi j \\\\frac{k n}{N} } x[m, n] ,$$\\n  \\n  and the inverse transform is defined as\\n  \\n  $$x[m, n] = \\\\frac{1}{N} \\\\sum_{k=0}^{N-1} e^{2 \\\\pi j \\\\frac{k n}{N} } y[m, k] ,$$\\n  \\n  where $j$ is the imaginary unit.\\n  \\n  The actual shape of the output is specified in the \\\\\\\"output\\\\\\\" section.\\n  \\n  Reference: https://docs.scipy.org/doc/scipy/tutorial/fft.html\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"dft_length\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" },\n      { \"name\": \"axis\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inverse\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"onesided\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DFTV17\",\n    \"summary\": \"ONNX DFT operation\",\n    \"description\": \"Computes the discrete Fourier transform of input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"dft_length\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"inverse\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"onesided\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DictVectorizer\",\n    \"summary\": \"ONNX DictVectorizer operation\",\n    \"description\": \"Uses an index mapping to convert a dictionary to an array.<br>\\n      Given a dictionary, each key is looked up in the vocabulary attribute corresponding to\\n      the key type. The index into the vocabulary array at which the key is found is then\\n      used to index the output 1-D tensor 'Y' and insert into it the value found in the dictionary 'X'.<br>\\n      The key type of the input map must correspond to the element type of the defined vocabulary attribute.\\n      Therefore, the output array will be equal in length to the index mapping vector parameter.\\n      All keys in the input dictionary must be present in the index mapping vector.\\n      For each item in the input dictionary, insert its value in the output array.\\n      Any keys not present in the input dictionary, will be zero in the output array.<br>\\n      For example: if the ``string_vocabulary`` parameter is set to ``[\\\\\\\"a\\\\\\\", \\\\\\\"c\\\\\\\", \\\\\\\"b\\\\\\\", \\\\\\\"z\\\\\\\"]``,\\n      then an input of ``{\\\\\\\"a\\\\\\\": 4, \\\\\\\"c\\\\\\\": 8}`` will produce an output of ``[4, 8, 0, 0]``.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TupleOf<[StringType, I64]>, TupleOf<[I64, StringType]>, TupleOf<[I64, F32]>, TupleOf<[I64, F64]>, TupleOf<[StringType, F32]>, TupleOf<[StringType, F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"int64_vocabulary\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"string_vocabulary\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Dim\",\n    \"summary\": \"ONNX dimensions operation.\",\n    \"description\": \"This operation is to obtain the dimension of a Tensor;\\n\\n    ```\\n    \\\"onnx.Dim\\\"(%tensor) {axis = 0 : si64} : (tensor<?x3x5xf32>) -> tensor<1xi64>\\n    ```\\n\\n    The axis identifies the dimension within the shape which is going to be obtained.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dim\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DimGroup\",\n    \"summary\": \"ONNX dimension group operation.\",\n    \"description\": \"This operation is to link a compile-time unknown dimension of a Tensor\\n    to a group id. Two dimensions that have the same group id are expected\\n    to be equal at runtime.\\n\\n    ```\\n    \\\"onnx.DimGroup\\\"(%tensor) {axis = 0 : si64, group_id = 1: si64} : (tensor<?x3x5xf32>) -> ()\\n    ```\\n\\n    `axis` identifies the dimension position in the tensor.\\n\\n    `group_id` identifies the group id of the dimension. It is non-negative.\\n    Value -1 for `group_id` means the dimension does not belong to any group.\\n\\n    This operation is currently used in the pass `--onnx-dim-analysis`\\n    for testing the unknown dimension analysis class.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"group_id\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Div\",\n    \"summary\": \"ONNX Div operation\",\n    \"description\": \"Performs element-wise binary division (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\\n  \\n  (Opset 14 change): Extend supported types to include uint8, int8, uint16, and int16.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Dropout\",\n    \"summary\": \"ONNX Dropout operation\",\n    \"description\": \"Dropout takes an input floating-point tensor, an optional input ratio (floating-point scalar) and an optional input training_mode (boolean scalar). It produces two tensor outputs,\\n  output (floating-point tensor) and mask (optional `Tensor<bool>`). If `training_mode` is true then the output Y will be a random dropout;\\n  Note that this Dropout scales the masked input data by the following equation, so to convert the trained model into inference mode,\\n  the user can simply not pass `training_mode` input or set it to false.\\n  ```\\n  output = scale * data * mask,\\n  ```\\n  where\\n  ```\\n  scale = 1. / (1. - ratio).\\n  ```\\n  This operator has **optional** inputs/outputs. See [the doc](IR.md) for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" },\n      { \"name\": \"ratio\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, NoneType]>\" },\n      { \"name\": \"training_mode\", \"type\": \"AnyTypeOf<[TensorOf<[I1]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" },\n      { \"name\": \"mask\", \"type\": \"AnyTypeOf<[TensorOf<[I1]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<SI64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.DynamicQuantizeLinear\",\n    \"summary\": \"ONNX DynamicQuantizeLinear operation\",\n    \"description\": \"A Function to fuse calculation for Scale, Zero Point and FP32->8Bit conversion of FP32 Input data.\\n  Outputs Scale, ZeroPoint and Quantized Input for a given FP32 Input.\\n  Scale is calculated as:\\n  ```\\n  y_scale = (maximum(0, max(x)) - minimum(0, min(x))) / (qmax - qmin)\\n  ```\\n  \\n  * where qmax and qmin are max and min values for quantization range i.e. [0, 255] in case of uint8\\n  * data range is adjusted to include 0.\\n  \\n  Zero point is calculated as:\\n  ```\\n  intermediate_zero_point = qmin - min(x)/y_scale\\n  y_zero_point = cast(round(saturate(intermediate_zero_point)))\\n  ```\\n  \\n  * where qmax and qmin are max and min values for quantization range .i.e [0, 255] in case of uint8\\n  * for saturation, it saturates to [0, 255] if it's uint8, or [-127, 127] if it's int8. Right now only uint8 is supported.\\n  * rounding to nearest ties to even.\\n  \\n  Data quantization formula is:\\n  ```\\n  y = saturate (round (x / y_scale) + y_zero_point)\\n  ```\\n  \\n  * for saturation, it saturates to [0, 255] if it's uint8, or [-127, 127] if it's int8. Right now only uint8 is supported.\\n  * rounding to nearest ties to even.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[UI8]>\" },\n      { \"name\": \"y_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"y_zero_point\", \"type\": \"TensorOf<[UI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Einsum\",\n    \"summary\": \"ONNX Einsum operation\",\n    \"description\": \"An einsum of the form `term1, term2 -> output-term` produces an output tensor using the following equation\\n  \\n  ```\\n  output[output-term] = reduce-sum( input1[term1] * input2[term2] )\\n  ```\\n  \\n  where the reduce-sum performs a summation over all the indices occurring in the input terms (term1, term2)\\n  that do not occur in the output-term.\\n  \\n  The Einsum operator evaluates algebraic tensor operations on a sequence of tensors, using the Einstein summation\\n  convention. The equation string contains a comma-separated sequence of lower case letters. Each term corresponds to\\n  an operand tensor, and the characters within the terms correspond to operands dimensions.\\n  \\n  This sequence may be followed by \\\\\\\"->\\\\\\\" to separate the left and right hand side of the equation.\\n  If the equation contains \\\\\\\"->\\\\\\\" followed by the right-hand side, the explicit (not classical) form of the Einstein\\n  summation is performed, and the right-hand side indices indicate output tensor dimensions. In other cases,\\n  output indices are (implicitly) set to the alphabetically sorted sequence of indices appearing exactly once in the\\n  equation.\\n  \\n  When a dimension character is repeated in the left-hand side, it represents summation along the dimension.\\n  \\n  The equation may contain ellipsis (\\\\\\\"...\\\\\\\") to enable broadcasting. Ellipsis must indicate a fixed number of dimensions.\\n  Specifically, every occurrence of ellipsis in the equation must represent the same number of dimensions.\\n  The right-hand side may contain exactly one ellipsis. In implicit mode, the ellipsis dimensions are set to the\\n  beginning of the output. The equation string may contain space (U+0020) character.\",\n    \"operands\": [\n      { \"name\": \"Inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"equation\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Elu\",\n    \"summary\": \"ONNX Elu operation\",\n    \"description\": \"Elu takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the function `f(x) = alpha * (exp(x) - 1.) for x <\\n  0`, `f(x) = x for x >= 0`., is applied to the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.EntryPoint\",\n    \"summary\": \"Indicate ONNX entry point\",\n    \"description\": \"The \\\"onnx.EntryPoint\\\" function indicates the main entry point of ONNX model.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"attributes\": [\n      { \"name\": \"func\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Equal\",\n    \"summary\": \"ONNX Equal operation\",\n    \"description\": \"Returns the tensor resulted from performing the `equal` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[I1]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[StringType]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[I1]>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[StringType]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Erf\",\n    \"summary\": \"ONNX Erf operation\",\n    \"description\": \"Computes the error function of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Exp\",\n    \"summary\": \"ONNX Exp operation\",\n    \"description\": \"Calculates the exponential of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Expand\",\n    \"summary\": \"ONNX Expand operation\",\n    \"description\": \"Broadcast the input tensor following the given shape and the broadcast rule.\\n  The broadcast rule is similar to numpy.array(input) * numpy.ones(shape):\\n  Dimensions are right alignment;\\n  Two corresponding dimensions must have the same value, or one of them is equal to 1.\\n  Also, this operator is similar to numpy.broadcast_to(input, shape),\\n  but the major difference is numpy.broadcast_to() does not allow shape to be smaller than input.size().\\n  It is possible that the output.shape is not equal to shape, when some dimensions in shape is equal to 1,\\n  or the shape.ndim < input.shape.ndim.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"shape\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.EyeLike\",\n    \"summary\": \"ONNX EyeLike operation\",\n    \"description\": \"Generate a 2D tensor (matrix) with ones on the diagonal and zeros everywhere else. Only 2D\\n  tensors are supported, i.e. input T1 must be of rank 2. The shape of the output tensor is the\\n  same as the input tensor. The data type can be specified by the 'dtype' argument. If\\n  'dtype' is not specified, then the type of input tensor is used. By default, the main diagonal\\n  is populated with ones, but attribute 'k' can be used to populate upper or lower diagonals.\\n  The 'dtype' argument must be one of the data types specified in the 'DataType' enum field in the\\n  TensorProto message and be valid as an output type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I1]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I1]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"k\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.FeatureVectorizer\",\n    \"summary\": \"ONNX FeatureVectorizer operation\",\n    \"description\": \"Concatenates input tensors into one continuous output.<br>\\n      All input shapes are 2-D and are concatenated along the second dimension. 1-D tensors are treated as [1,C].\\n      Inputs are copied to the output maintaining the order of the input arguments.<br>\\n      All inputs must be integers or floats, while the output will be all floating point values.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inputdimensions\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Flatten\",\n    \"summary\": \"ONNX Flatten operation\",\n    \"description\": \"Flattens the input tensor into a 2D matrix. If input tensor has shape\\n  (d_0, d_1, ... d_n) then the output will have shape\\n  (d_0 X d_1 ... d_(axis-1), d_axis X d_(axis+1) ... X dn).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Floor\",\n    \"summary\": \"ONNX Floor operation\",\n    \"description\": \"Floor takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the floor is, y = floor(x), is applied to\\n  the tensor elementwise. If x is integral, +0, -0, NaN,  or infinite, x itself is returned.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"ONNX Gather operation\",\n    \"description\": \"Given `data` tensor of rank r >= 1, and `indices` tensor of rank q, gather\\n  entries of the axis dimension of `data` (by default outer-most one as axis=0) indexed by `indices`, and concatenates\\n  them in an output tensor of rank q + (r - 1).\\n  \\n  It is an indexing operation that indexes into the input `data` along a single (specified) axis.\\n  Each entry in `indices` produces a `r-1` dimensional slice of the input tensor.\\n  The entire operation produces, conceptually, a `q`-dimensional tensor of `r-1` dimensional slices,\\n  which is arranged into a `q + (r-1)`-dimensional tensor, with the `q` dimensions taking the\\n  place of the original `axis` that is being indexed into.\\n  \\n  The following few examples illustrate how `Gather` works for specific shapes of `data`,\\n  `indices`, and given value of `axis`:\\n  | data shape | indices shape | axis | output shape | output equation |\\n  | --- | --- | --- | --- | --- |\\n  | (P, Q) | ( )  (a scalar)   | 0 | (Q)       | output[q] = data[indices, q] |\\n  | (P, Q, R) | ( )  (a scalar)   | 1 | (P, R)       | output[p, r] = data[p, indices, r] |\\n  | (P, Q) | (R, S) | 0 | (R, S, Q) | output[r, s, q] = data[ [indices[r, s], q] |\\n  | (P, Q) | (R, S) | 1 | (P, R, S) | output[p, r, s] = data[ p, indices[r, s]] |\\n  \\n  More generally, if `axis = 0`, let `k = indices[i_{0}, ..., i_{q-1\\\\}\\\\]`\\n  then `output[i_{0}, ..., i_{q-1}, j_{0}, ..., j_{r-2\\\\}\\\\] = input[k , j_{0}, ..., j_{r-2\\\\}\\\\]`:\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  indices = [\\n      [0, 1],\\n      [1, 2],\\n  ]\\n  output = [\\n      [\\n          [1.0, 1.2],\\n          [2.3, 3.4],\\n      ],\\n      [\\n          [2.3, 3.4],\\n          [4.5, 5.7],\\n      ],\\n  ]\\n  ```\\n  \\n  If `axis = 1`, let `k = indices[i_{0}, ..., i_{q-1\\\\}\\\\]`\\n  then `output[j_{0}, i_{0}, ..., i_{q-1}, j_{1}, ..., j_{r-2\\\\}\\\\] = input[j_{0}, k, j_{1}, ..., j_{r-2\\\\}\\\\]`:\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2, 1.9],\\n      [2.3, 3.4, 3.9],\\n      [4.5, 5.7, 5.9],\\n  ]\\n  indices = [\\n      [0, 2],\\n  ]\\n  axis = 1,\\n  output = [\\n          [[1.0, 1.9]],\\n          [[2.3, 3.9]],\\n          [[4.5, 5.9]],\\n  ]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GatherElements\",\n    \"summary\": \"ONNX GatherElements operation\",\n    \"description\": \"GatherElements takes two inputs `data` and `indices` of the same rank r >= 1\\n  and an optional attribute `axis` that identifies an axis of `data`\\n  (by default, the outer-most axis, that is axis 0). It is an indexing operation\\n  that produces its output by indexing into the input data tensor at index\\n  positions determined by elements of the `indices` tensor.\\n  Its output shape is the same as the shape of `indices` and consists of one value\\n  (gathered from the `data`) for each element in `indices`.\\n  \\n  For instance, in the 3-D case (r = 3), the output produced is determined\\n  by the following equations:\\n  ```\\n  out[i][j][k] = input[index[i][j][k]][j][k] if axis = 0,\\n  out[i][j][k] = input[i][index[i][j][k]][k] if axis = 1,\\n  out[i][j][k] = input[i][j][index[i][j][k]] if axis = 2,\\n  ```\\n  \\n  This operator is also the inverse of ScatterElements. It is similar to Torch's gather operation.\\n  \\n  Example 1:\\n  ```\\n  data = [\\n      [1, 2],\\n      [3, 4],\\n  ]\\n  indices = [\\n      [0, 0],\\n      [1, 0],\\n  ]\\n  axis = 1\\n  output = [\\n      [1, 1],\\n      [4, 3],\\n  ]\\n  ```\\n  Example 2:\\n  ```\\n  data = [\\n      [1, 2, 3],\\n      [4, 5, 6],\\n      [7, 8, 9],\\n  ]\\n  indices = [\\n      [1, 2, 0],\\n      [2, 0, 0],\\n  ]\\n  axis = 0\\n  output = [\\n      [4, 8, 3],\\n      [7, 2, 3],\\n  ]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GatherND\",\n    \"summary\": \"ONNX GatherND operation\",\n    \"description\": \"Given `data` tensor of rank `r` >= 1, `indices` tensor of rank `q` >= 1, and `batch_dims` integer `b`, this operator gathers\\n  slices of `data` into an output tensor of rank `q + r - indices_shape[-1] - 1 - b`.\\n  \\n  `indices` is an q-dimensional integer tensor, best thought of as a `(q-1)`-dimensional tensor of index-tuples into `data`,\\n  where each element defines a slice of `data`\\n  \\n  `batch_dims` (denoted as `b`) is an integer indicating the number of batch dimensions, i.e the leading `b` number of dimensions of\\n  `data` tensor and `indices` are representing the batches, and the gather starts from the `b+1` dimension.\\n  \\n  Some salient points about the inputs' rank and shape:\\n  \\n  1) r >= 1 and q >= 1 are to be honored. There is no dependency condition to be met between ranks `r` and `q`\\n  \\n  2) The first `b` dimensions of the shape of `indices` tensor and `data` tensor must be equal.\\n  \\n  3) b < min(q, r) is to be honored.\\n  \\n  4) The `indices_shape[-1]` should have a value between 1 (inclusive) and rank `r-b` (inclusive)\\n  \\n  5) All values in `indices` are expected to be within bounds [-s, s-1] along axis of size `s` (i.e.) `-data_shape[i] <= indices[...,i] <= data_shape[i] - 1`.\\n     It is an error if any of the index values are out of bounds.\\n  \\n  The output is computed as follows:\\n  \\n  The output tensor is obtained by mapping each index-tuple in the `indices` tensor to the corresponding slice of the input `data`.\\n  \\n  1) If `indices_shape[-1] > r-b` => error condition\\n  \\n  2) If `indices_shape[-1] == r-b`, since the rank of `indices` is `q`, `indices` can be thought of as `N` `(q-b-1)`-dimensional tensors\\n     containing 1-D tensors of dimension `r-b`, where `N` is an integer equals to the product of 1 and all the elements in the batch dimensions\\n     of the indices_shape. Let us think of each such `r-b` ranked tensor as `indices_slice`. Each *scalar value* corresponding to `data[0:b-1,indices_slice]`\\n     is filled into the corresponding location of the `(q-b-1)`-dimensional tensor to form the `output` tensor (Example 1 below)\\n  \\n  3) If `indices_shape[-1] < r-b`, since the rank of `indices` is `q`, `indices` can be thought of as `N` `(q-b-1)`-dimensional tensor\\n     containing 1-D tensors of dimension `< r-b`. Let us think of each such tensors as `indices_slice`. Each *tensor slice* corresponding\\n     to `data[0:b-1, indices_slice , :]` is filled into the corresponding location of the `(q-b-1)`-dimensional tensor\\n     to form the `output` tensor (Examples 2, 3, 4 and 5 below)\\n  \\n  This operator is the inverse of `ScatterND`.\\n  \\n  **Example 1**\\n  \\n  ```\\n  batch_dims = 0\\n  data    = [[0,1],[2,3]]   # data_shape    = [2, 2]\\n  indices = [[0,0],[1,1]]   # indices_shape = [2, 2]\\n  output  = [0,3]           # output_shape  = [2]\\n  ```\\n  \\n  **Example 2**\\n  \\n  ```\\n  batch_dims = 0\\n  data    = [[0,1],[2,3]]  # data_shape    = [2, 2]\\n  indices = [[1],[0]]      # indices_shape = [2, 1]\\n  output  = [[2,3],[0,1]]  # output_shape  = [2, 2]\\n  ```\\n  \\n  **Example 3**\\n  \\n  ```\\n  batch_dims = 0\\n  data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape    = [2, 2, 2]\\n  indices = [[0,1],[1,0]]                 # indices_shape = [2, 2]\\n  output  = [[2,3],[4,5]]                 # output_shape  = [2, 2]\\n  ```\\n  \\n  **Example 4**\\n  \\n  ```\\n  batch_dims = 0\\n  data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape    = [2, 2, 2]\\n  indices = [[[0,1]],[[1,0]]]             # indices_shape = [2, 1, 2]\\n  output  = [[[2,3]],[[4,5]]]             # output_shape  = [2, 1, 2]\\n  ```\\n  \\n  **Example 5**\\n  \\n  ```\\n  batch_dims = 1\\n  data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape    = [2, 2, 2]\\n  indices = [[1],[0]]                     # indices_shape = [2, 1]\\n  output  = [[2,3],[4,5]]                 # output_shape  = [2, 2]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Gelu\",\n    \"summary\": \"ONNX Gelu operation\",\n    \"description\": \"Gelu takes one input data (Tensor<T>) and produces one\\n  output data (Tensor<T>) where the gaussian error linear units function,\\n  $y = 0.5 * x * (1 + erf(x/sqrt(2)))$ is applied to the tensor elementwise.\\n  If the attribute \\\\\\\"approximate\\\\\\\" is set to \\\\\\\"tanh\\\\\\\", the function estimation,\\n  $y = 0.5 * x * (1 + Tanh(sqrt(2/\\\\pi) * (x + 0.044715 * x^3)))$ is used and applied\\n  to the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"approximate\", \"type\": \"DefaultValuedStrAttr<StrAttr, none>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Gemm\",\n    \"summary\": \"ONNX Gemm operation\",\n    \"description\": \"General Matrix multiplication:\\n  https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms#Level_3\\n  \\n  * A' = transpose(A) if transA else A\\n  * B' = transpose(B) if transB else B\\n  \\n  Compute Y = alpha * A' * B' + beta * C, where input tensor A has shape (M, K) or (K, M),\\n  input tensor B has shape (K, N) or (N, K), input tensor C is broadcastable to shape (M, N),\\n  and output tensor Y has shape (M, N). A will be transposed before doing the\\n  computation if attribute transA is non-zero, same for B and transB.\\n  This operator supports **unidirectional broadcasting** (tensor C should be unidirectional broadcastable to tensor A * B); for more details please check [the doc](Broadcasting.md).\\n  This operator has **optional** inputs/outputs. See [the doc](IR.md) for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"transA\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"transB\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GlobalAveragePool\",\n    \"summary\": \"ONNX GlobalAveragePool operation\",\n    \"description\": \"GlobalAveragePool consumes an input tensor X and applies average pooling across\\n   the values in the same channel. This is equivalent to AveragePool with kernel size\\n   equal to the spatial dimension of input tensor.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GlobalLpPool\",\n    \"summary\": \"ONNX GlobalLpPool operation\",\n    \"description\": \"GlobalLpPool consumes an input tensor X and applies lp pool pooling across\\n   the values in the same channel. This is equivalent to LpPool with kernel size\\n   equal to the spatial dimension of input tensor.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"p\", \"type\": \"DefaultValuedAttr<SI64Attr, 2>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GlobalMaxPool\",\n    \"summary\": \"ONNX GlobalMaxPool operation\",\n    \"description\": \"GlobalMaxPool consumes an input tensor X and applies max pooling across\\n   the values in the same channel. This is equivalent to MaxPool with kernel size\\n   equal to the spatial dimension of input tensor.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Gradient\",\n    \"summary\": \"ONNX Gradient operation\",\n    \"description\": \"Gradient operator computes the partial derivatives of a specific tensor w.r.t.\\n  some other tensors. This operator is widely used in gradient-based training\\n  algorithms. To illustrate its use, let's consider a computation graph,\\n  \\n  ```\\n  X -----.\\n         |\\n         v\\n  W --> Conv --> H --> Gemm --> Y\\n                        ^\\n                        |\\n                        Z\\n  ```\\n  \\n  , where W and Z are trainable tensors. Note that operators' attributes are\\n  omitted for the sake of simplicity. Let dY/dW (dY/dZ) be the gradient of\\n  Y with respect to W (Z). The user can compute gradient by inserting Gradient\\n  operator to form another graph shown below.\\n  \\n  ```\\n  W --> Conv --> H --> Gemm --> Y\\n  |      ^              ^\\n  |      |              |\\n  |      X              Z\\n  |      |              |\\n  |      |   .----------'\\n  |      |   |  (W/Z/X is the 1st/2nd/3rd input of Gradient as shown in\\n  |      |   |   \\\\\\\"xs\\\\\\\" followed by \\\\\\\"zs\\\\\\\")\\n  |      v   v\\n  '---> Gradient(xs=[\\\\\\\"W\\\\\\\", \\\\\\\"Z\\\\\\\"], zs=[\\\\\\\"X\\\\\\\"], y=\\\\\\\"Y\\\\\\\")\\n         |   |\\n         |   '-----------------------------------> dY/dW (1st output of Gradient)\\n         |\\n         '---------------------------------------> dY/dZ (2nd output of Gradient)\\n  ```\\n  \\n  By definition, the tensor \\\\\\\"y\\\\\\\" is a function of independent variables in \\\\\\\"xs\\\\\\\"\\n  and \\\\\\\"zs\\\\\\\". Since we only compute the gradient of \\\\\\\"y\\\\\\\" w.r.t. the differentiable\\n  variables in \\\\\\\"xs\\\\\\\", this Gradient only outputs dY/dW and dY/dZ. Note that \\\\\\\"H\\\\\\\"\\n  cannot appear in \\\\\\\"xs\\\\\\\" and \\\\\\\"zs\\\\\\\". The reason is that \\\\\\\"H\\\\\\\" can be determined by\\n  tensors \\\\\\\"W\\\\\\\" and \\\\\\\"X\\\\\\\" and therefore \\\\\\\"H\\\\\\\" is not an independent variable.\\n  \\n  All outputs are optional. If needed, for example, user can assign an empty\\n  string to the 1st output name of that Gradient to skip the generation of dY/dW.\\n  Note that the concept of optional outputs can also be found in ONNX's RNN, GRU,\\n  and LSTM.\\n  \\n  Gradient operator can compute derivative against intermediate tensors. For\\n  example, the gradient of Y with respect to H can be done via\\n  \\n  ```\\n  W --> Conv --> H --> Gemm --> Y\\n         ^       |      ^\\n         |       |      |\\n         X       |      Z\\n         .-------'      |\\n         |   .----------'\\n         |   | (H/Z is the 1st/2nd input of Gradient as shown in \\\\\\\"xs\\\\\\\")\\n         v   v\\n        Gradient(xs=[\\\\\\\"H\\\\\\\", \\\\\\\"Z\\\\\\\"], y=\\\\\\\"Y\\\\\\\")\\n         |   |\\n         |   '-----------------------------------> dY/dH (1st output of Gradient)\\n         |\\n         '---------------------------------------> dY/dZ (2nd output of Gradient)\\n  ```\\n  \\n  It is possible to represent high-order differentiation using Gradient operators.\\n  For example, given the following linear model:\\n  \\n  ```\\n  W --> Gemm --> Y --> Loss --> O\\n         ^              ^\\n         |              |\\n         X              L\\n  ```\\n  \\n  To compute the 2nd order derivative of O with respect to W (denoted by\\n  d^2O/dW^2), one can do\\n  \\n  ```\\n  W --> Gemm --> Y --> Loss --> O\\n  |      ^              ^\\n  |      |              |\\n  |      X .------------L\\n  |      | |            |\\n  |      | |            v\\n  +------+-+> Gradient(xs=[\\\\\\\"X\\\\\\\", \\\\\\\"W\\\\\\\"], zs=[\\\\\\\"L\\\\\\\"], y=\\\\\\\"O\\\\\\\") ---> dO/dX (1st output of Gradient)\\n  |      | |    |\\n  |      | |    '---> dO/dW (2nd output of Gradient)\\n  |      v v\\n  '---> Gradient(xs=[\\\\\\\"X\\\\\\\", \\\\\\\"W\\\\\\\"], zs=[\\\\\\\"L\\\\\\\"], y=\\\\\\\"dO/dW\\\\\\\") ---> d(dO/dW)dX (1st output of\\n         |                                                  Gradient)\\n         |\\n         |\\n         '---> d^2O/dW^2 (2nd output of Gradient)\\n  ```\\n  \\n  The tensors named in attributes \\\\\\\"xs\\\\\\\", \\\\\\\"zs\\\\\\\", and \\\\\\\"y\\\\\\\" define the differentiated\\n  computation graph, and the inputs to Gradient node define the values at\\n  which the gradient is computed. We can feed different tensors to the identified\\n  graph. For example, one can compute the gradient of Y with respect to H at\\n  a specific value of H, H_1, by providing that value as an input to the Gradient\\n  node.\\n  \\n  ```\\n  W --> Conv --> H --> Gemm --> Y\\n         ^              ^\\n         |              |\\n         X              Z\\n  \\n            Z_1 (2nd input of Gradient)\\n             |\\n             v\\n  H_1 --> Gradient(xs=[\\\\\\\"H\\\\\\\", \\\\\\\"Z\\\\\\\"], y=\\\\\\\"Y\\\\\\\") ---> dY/dH when H = H_1 and Y = Y_1.\\n             |\\n             '------------------------------> dY/dZ (2nd output of Gradient)\\n  ```\\n  \\n  When the inputs of Gradient are the tensors named in \\\\\\\"xs\\\\\\\" and \\\\\\\"zs\\\\\\\", the\\n  computation can be optimized. More specifically, intermediate variables in\\n  forward pass can be reused if the gradient is computed via reverse-mode\\n  auto-differentiation.\",\n    \"operands\": [\n      { \"name\": \"Inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"xs\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"y\", \"type\": \"StrAttr\" },\n      { \"name\": \"zs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Greater\",\n    \"summary\": \"ONNX Greater operation\",\n    \"description\": \"Returns the tensor resulted from performing the `greater` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GreaterOrEqual\",\n    \"summary\": \"ONNX GreaterOrEqual operation\",\n    \"description\": \"Returns the tensor resulted from performing the `greater_equal` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GridSample\",\n    \"summary\": \"ONNX GridSample operation\",\n    \"description\": \"Given an input `X` and a flow-field `grid`, computes the output `Y` using `X` values and pixel locations from the `grid`.\\n  For spatial input `X` with shape (N, C, H, W), the `grid` will have shape (N, H_out, W_out, 2),\\n  the output `Y` will have shape (N, C, H_out, W_out). For volumetric input `X` with shape (N, C, D, H, W),\\n  the `grid` will have shape (N, D_out, H_out, W_out, 3), the output `Y` will have shape (N, C, D_out, H_out, W_out).\\n  More generally, for an input `X` of rank r+2 with shape (N, C, d1, d2, ..., dr),\\n  the `grid` will have shape (N, D1_out, D2_out, ..., Dr_out, r), the output `Y` will have shape (N, C, D1_out, D2_out, ..., Dr_out).\\n  \\n  The tensor `X` contains values at centers of square pixels (voxels, etc) locations such as (n, c, d1_in, d2_in, ..., dr_in).\\n  The (n, d1_out, d2_out, ..., dr_out, :) values from the tensor `grid` are the normalized positions for interpolating the values\\n  at the (n, c, d1_out, d2_out, ..., dr_out) locations from the output tensor `Y` using a specified interpolation method (the mode)\\n  and a padding mode (for `grid` positions falling outside the 2-dimensional image).\\n  \\n  For example, the values in `grid[n, h_out, w_out, :]` are size-2 vectors specifying normalized positions in the 2-dimensional space of `X`.\\n  They are used to interpolate output values of `Y[n, c, h_out, w_out]`.\\n  \\n  The GridSample operator is often used in doing grid generator and sampler in the\\n  [Spatial Transformer Networks](https://arxiv.org/abs/1506.02025).\\n  See also in [torch.nn.functional.grid_sample](https://pytorch.org/docs/stable/generated/torch.nn.functional.grid_sample.html).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"grid\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, linear>\" },\n      { \"name\": \"padding_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, zeros>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GridSampleV16\",\n    \"summary\": \"ONNX GridSample operation\",\n    \"description\": \"Given an input `X` and a flow-field `grid`, computes the output `Y` using `X` values and pixel locations from `grid`.\\n  Currently, only spatial (4-D) inputs are supported. For input `X` with shape (N, C, H, W) and `grid` with shape (N, H_out, W_out, 2),\\n  the output `Y` will have shape (N, C, H_out, W_out).\\n  \\n  The tensor `X` contains values at centers of square pixels in a H by W 2-dimensional image.\\n  The tensor `grid` describes normalized positions where the output `Y` is to be computed\\n  using a specified interpolation method (the mode) and a padding mode (for grid positions falling outside the 2-dimensional image).\\n  \\n  Elements in `grid[N, H_out, W_out]` are size-2 vectors specifying positions in the 2-dimensional space of `X`.\\n  They are used to interpolate output values of `Y[N, C, H_out, W_out]`.\\n  \\n  The GridSample operator is often used in doing grid generator and sampler in the [Spatial Transformer Networks](https://arxiv.org/abs/1506.02025).\\n  See also in [torch.nn.functional.grid_sample](https://pytorch.org/docs/master/generated/torch.nn.functional.grid_sample.html#torch-nn-functional-grid-sample).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"grid\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, bilinear>\" },\n      { \"name\": \"padding_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, zeros>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GroupNormalization\",\n    \"summary\": \"ONNX GroupNormalization operation\",\n    \"description\": \"A GroupNormalization function. Carries out group normalization as described in\\n  the paper https://arxiv.org/abs/1803.08494\\n  \\n  This operator transforms input according to\\n  ```\\n  y = scale * (x - mean) / sqrt(variance + epsilon) + bias,\\n  ```\\n  where the mean and variance are computed per instance per group of channels, and\\n  `scale` and `bias` should be specified for each channel. The number of\\n  groups `num_groups` should be divisible by the number of channels so that there are\\n  an equal number of channels per group.\\n  \\n  The overall computation has two stages: the first stage normalizes the elements to\\n  have zero mean and unit variance for each instance in each group, and the second\\n  stage scales and shifts the results of the first stage. The floating-point precision\\n  used in the first stage is determined by the `stash_type` attribute. For example,\\n  if `stash_type` is 1, the operator casts all input variables to 32-bit float,\\n  performs the computation, and finally casts the normalized results back to the\\n  original type of `X`. The second stage does not depend on `stash_type`.\\n  \\n  When the number of groups is the same as the number of channels, this operator is\\n  equivalent to InstanceNormalization. When there is only one group, this operator\\n  is equivalent to LayerNormalization.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"scale\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"bias\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"num_groups\", \"type\": \"SI64Attr\" },\n      { \"name\": \"stash_type\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GroupNormalizationV18\",\n    \"summary\": \"ONNX GroupNormalization operation\",\n    \"description\": \"A GroupNormalization function. Carries out group normalization as described in\\n  the paper https://arxiv.org/abs/1803.08494\\n  \\n  This operator transforms input according to\\n  ```\\n  y = scale * (x - mean) / sqrt(variance + epsilon) + bias,\\n  ```\\n  where the mean and variance are computed per instance per group of channels, and\\n  `scale` and `bias` should be specified for each group of channels. The number of\\n  groups `num_groups` should be divisible by the number of channels so that there are\\n  an equal number of channels per group.\\n  \\n  When the number of groups is the same as the number of channels, this operator is\\n  equivalent to InstanceNormalization. When there is only one group, this operator\\n  is equivalent to LayerNormalization.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"scale\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"bias\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"num_groups\", \"type\": \"SI64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.GRU\",\n    \"summary\": \"ONNX GRU operation\",\n    \"description\": \"Computes an one-layer GRU. This operator is usually supported via some custom\\n  implementation such as CuDNN.\\n  \\n  Notations:\\n  \\n  * `X` - input tensor\\n  * `z` - update gate\\n  * `r` - reset gate\\n  * `h` - hidden gate\\n  * `t` - time step (t-1 means previous time step)\\n  * `W[zrh]` - W parameter weight matrix for update, reset, and hidden gates\\n  * `R[zrh]` - R recurrence weight matrix for update, reset, and hidden gates\\n  * `Wb[zrh]` - W bias vectors for update, reset, and hidden gates\\n  * `Rb[zrh]` - R bias vectors for update, reset, and hidden gates\\n  * `WB[zrh]` - W parameter weight matrix for backward update, reset, and hidden gates\\n  * `RB[zrh]` - R recurrence weight matrix for backward update, reset, and hidden gates\\n  * `WBb[zrh]` - W bias vectors for backward update, reset, and hidden gates\\n  * `RBb[zrh]` - R bias vectors for backward update, reset, and hidden gates\\n  * `H` - Hidden state\\n  * `num_directions` - 2 if direction == bidirectional else 1\\n  \\n  Activation functions:\\n  \\n  * Relu(x)                - max(0, x)\\n  * Tanh(x)                - (1 - e^{-2x})/(1 + e^{-2x})\\n  * Sigmoid(x)             - 1/(1 + e^{-x})\\n  \\n  NOTE:\\n    Below are optional\\n  \\n  * Affine(x)              - alpha * x + beta\\n  * LeakyRelu(x)           - x if x >= 0 else alpha * x\\n  * ThresholdedRelu(x)     - x if x >= alpha else 0\\n  * ScaledTanh(x)          - alpha * Tanh(beta * x)\\n  * HardSigmoid(x)         - min(max(alpha * x + beta, 0), 1)\\n  * Elu(x)                 - x if x >= 0 else alpha * (e^x - 1)\\n  * Softsign(x)            - x/(1 + |x|)\\n  * Softplus(x)            - log(1 + e^x)\\n  \\n  Equations (Default: f=Sigmoid, g=Tanh):\\n  \\n  * zt = f(Xt*(Wz^T) + Ht-1*(Rz^T) + Wbz + Rbz)\\n  * rt = f(Xt*(Wr^T) + Ht-1*(Rr^T) + Wbr + Rbr)\\n  * ht = g(Xt*(Wh^T) + (rt (.) Ht-1)*(Rh^T) + Rbh + Wbh) # default, when linear_before_reset = 0\\n  * ht = g(Xt*(Wh^T) + (rt (.) (Ht-1*(Rh^T) + Rbh)) + Wbh) # when linear_before_reset != 0\\n  * Ht = (1 - zt) (.) ht + zt (.) Ht-1\\n  This operator has **optional** inputs/outputs. See [the doc](IR.md) for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"W\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"R\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"sequence_lens\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, NoneType]>\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"activation_alpha\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"activation_beta\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"activations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"clip\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"direction\", \"type\": \"DefaultValuedStrAttr<StrAttr, forward>\" },\n      { \"name\": \"hidden_size\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"layout\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"linear_before_reset\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.HammingWindow\",\n    \"summary\": \"ONNX HammingWindow operation\",\n    \"description\": \"Generates a Hamming window as described in the paper https://ieeexplore.ieee.org/document/1455106.\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_datatype\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"periodic\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.HannWindow\",\n    \"summary\": \"ONNX HannWindow operation\",\n    \"description\": \"Generates a Hann window as described in the paper https://ieeexplore.ieee.org/document/1455106.\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_datatype\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"periodic\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Hardmax\",\n    \"summary\": \"ONNX Hardmax operation\",\n    \"description\": \"The operator computes the hardmax values for the given input:\\n  \\n   Hardmax(element in input, axis) = 1 if the element is the first maximum value along the specified axis, 0 otherwise\\n  \\n  The \\\\\\\"axis\\\\\\\" attribute indicates the dimension along which Hardmax\\n  will be performed. The output tensor has the same shape\\n  and contains the Hardmax values of the corresponding input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.HardSigmoid\",\n    \"summary\": \"ONNX HardSigmoid operation\",\n    \"description\": \"HardSigmoid takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the HardSigmoid function, y = max(0, min(1, alpha * x + beta)),\\n  is applied to the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 0.2>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F32Attr, 0.5>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.HardSwish\",\n    \"summary\": \"ONNX HardSwish operation\",\n    \"description\": \"HardSwish takes one input data (Tensor<T>) and produces one output data (Tensor<T>) where\\n  the HardSwish function, y = x * max(0, min(1, alpha * x + beta)) = x * HardSigmoid<alpha, beta>(x),\\n  where alpha = 1/6 and beta = 0.5, is applied to the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Identity\",\n    \"summary\": \"ONNX Identity operation\",\n    \"description\": \"Identity operator\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>, SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>, OptOf<SeqOf<[ TensorOf < [ UI8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ StringType ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I1 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F32 > ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F64 > ] > ]>>, OptOf<TensorOf<[ UI8 ]>>, OptOf<TensorOf<[ UI16 ]>>, OptOf<TensorOf<[ UI32 ]>>, OptOf<TensorOf<[ UI64 ]>>, OptOf<TensorOf<[ I8 ]>>, OptOf<TensorOf<[ I16 ]>>, OptOf<TensorOf<[ I32 ]>>, OptOf<TensorOf<[ I64 ]>>, OptOf<TensorOf<[ F16 ]>>, OptOf<TensorOf<[ F32 ]>>, OptOf<TensorOf<[ F64 ]>>, OptOf<TensorOf<[ StringType ]>>, OptOf<TensorOf<[ I1 ]>>, OptOf<TensorOf<[ Complex < F32 > ]>>, OptOf<TensorOf<[ Complex < F64 > ]>>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>, SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>, OptOf<SeqOf<[ TensorOf < [ UI8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ StringType ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I1 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F32 > ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F64 > ] > ]>>, OptOf<TensorOf<[ UI8 ]>>, OptOf<TensorOf<[ UI16 ]>>, OptOf<TensorOf<[ UI32 ]>>, OptOf<TensorOf<[ UI64 ]>>, OptOf<TensorOf<[ I8 ]>>, OptOf<TensorOf<[ I16 ]>>, OptOf<TensorOf<[ I32 ]>>, OptOf<TensorOf<[ I64 ]>>, OptOf<TensorOf<[ F16 ]>>, OptOf<TensorOf<[ F32 ]>>, OptOf<TensorOf<[ F64 ]>>, OptOf<TensorOf<[ StringType ]>>, OptOf<TensorOf<[ I1 ]>>, OptOf<TensorOf<[ Complex < F32 > ]>>, OptOf<TensorOf<[ Complex < F64 > ]>>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.If\",\n    \"summary\": \"ONNX If operation\",\n    \"description\": \"If conditional\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] >, TensorOf < [ F8E4M3FN ] >, TensorOf < [ F8E4M3FNUZ ] >, TensorOf < [ F8E5M2 ] >, TensorOf < [ F8E5M2FNUZ ] >, TensorOf < [ UI < 4 > ] >, TensorOf < [ I < 4 > ] >, SeqOf < [ TensorOf < [ UI8 ] > ] >, SeqOf < [ TensorOf < [ UI16 ] > ] >, SeqOf < [ TensorOf < [ UI32 ] > ] >, SeqOf < [ TensorOf < [ UI64 ] > ] >, SeqOf < [ TensorOf < [ I8 ] > ] >, SeqOf < [ TensorOf < [ I16 ] > ] >, SeqOf < [ TensorOf < [ I32 ] > ] >, SeqOf < [ TensorOf < [ I64 ] > ] >, SeqOf < [ TensorOf < [ BF16 ] > ] >, SeqOf < [ TensorOf < [ F16 ] > ] >, SeqOf < [ TensorOf < [ F32 ] > ] >, SeqOf < [ TensorOf < [ F64 ] > ] >, SeqOf < [ TensorOf < [ StringType ] > ] >, SeqOf < [ TensorOf < [ I1 ] > ] >, SeqOf < [ TensorOf < [ Complex < F32 > ] > ] >, SeqOf < [ TensorOf < [ Complex < F64 > ] > ] >, SeqOf < [ TensorOf < [ F8E4M3FN ] > ] >, SeqOf < [ TensorOf < [ F8E4M3FNUZ ] > ] >, SeqOf < [ TensorOf < [ F8E5M2 ] > ] >, SeqOf < [ TensorOf < [ F8E5M2FNUZ ] > ] >, SeqOf < [ TensorOf < [ UI < 4 > ] > ] >, SeqOf < [ TensorOf < [ I < 4 > ] > ] >, OptOf < SeqOf < [ TensorOf < [ UI8 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I8 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ BF16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ StringType ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I1 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ Complex < F32 > ] > ] > >, OptOf < SeqOf < [ TensorOf < [ Complex < F64 > ] > ] > >, OptOf < TensorOf < [ UI8 ] > >, OptOf < TensorOf < [ UI16 ] > >, OptOf < TensorOf < [ UI32 ] > >, OptOf < TensorOf < [ UI64 ] > >, OptOf < TensorOf < [ I8 ] > >, OptOf < TensorOf < [ I16 ] > >, OptOf < TensorOf < [ I32 ] > >, OptOf < TensorOf < [ I64 ] > >, OptOf < TensorOf < [ BF16 ] > >, OptOf < TensorOf < [ F16 ] > >, OptOf < TensorOf < [ F32 ] > >, OptOf < TensorOf < [ F64 ] > >, OptOf < TensorOf < [ StringType ] > >, OptOf < TensorOf < [ I1 ] > >, OptOf < TensorOf < [ Complex < F32 > ] > >, OptOf < TensorOf < [ Complex < F64 > ] > >, OptOf < TensorOf < [ F8E4M3FN ] > >, OptOf < TensorOf < [ F8E4M3FNUZ ] > >, OptOf < TensorOf < [ F8E5M2 ] > >, OptOf < TensorOf < [ F8E5M2FNUZ ] > >, OptOf < TensorOf < [ UI < 4 > ] > >, OptOf < TensorOf < [ I < 4 > ] > > ]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_branch\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_branch\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Imputer\",\n    \"summary\": \"ONNX Imputer operation\",\n    \"description\": \"Replaces inputs that equal one value with another, leaving all other elements alone.<br>\\n      This operator is typically used to replace missing values in situations where they have a canonical\\n      representation, such as -1, 0, NaN, or some extreme value.<br>\\n      One and only one of imputed_value_floats or imputed_value_int64s should be defined -- floats if the input tensor\\n      holds floats, integers if the input tensor holds integers. The imputed values must all fit within the\\n      width of the tensor element type. One and only one of the replaced_value_float or replaced_value_int64 should be defined,\\n      which one depends on whether floats or integers are being processed.<br>\\n      The imputed_value attribute length can be 1 element, or it can have one element per input feature.<br>In other words, if the input tensor has the shape [*,F], then the length of the attribute array may be 1 or F. If it is 1, then it is broadcast along the last dimension and applied to each feature.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"imputed_value_floats\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"imputed_value_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"replaced_value_float\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"replaced_value_int64\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.InstanceNormalization\",\n    \"summary\": \"ONNX InstanceNormalization operation\",\n    \"description\": \"Carries out instance normalization as described in the paper\\n  https://arxiv.org/abs/1607.08022.\\n  \\n  y = scale * (x - mean) / sqrt(variance + epsilon) + B,\\n  where mean and variance are computed per instance per channel.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"scale\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.IsInf\",\n    \"summary\": \"ONNX IsInf operation\",\n    \"description\": \"Map infinity to true and other values to false.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"detect_negative\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"detect_positive\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.IsNaN\",\n    \"summary\": \"ONNX IsNaN operation\",\n    \"description\": \"Returns which elements of the input are NaN.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LabelEncoder\",\n    \"summary\": \"ONNX LabelEncoder operation\",\n    \"description\": \"Maps each element in the input tensor to another value.<br>\\n      The mapping is determined by the two parallel attributes, 'keys_*' and\\n      'values_*' attribute. The i-th value in the specified 'keys_*' attribute\\n      would be mapped to the i-th value in the specified 'values_*' attribute. It\\n      implies that input's element type and the element type of the specified\\n      'keys_*' should be identical while the output type is identical to the\\n      specified 'values_*' attribute. If an input element can not be found in the\\n      specified 'keys_*' attribute, the 'default_*' that matches the specified\\n      'values_*' attribute may be used as its output value.<br>\\n      Let's consider an example which maps a string tensor to an integer tensor.\\n      Assume and 'keys_strings' is [\\\\\\\"Amy\\\\\\\", \\\\\\\"Sally\\\\\\\"], 'values_int64s' is [5, 6],\\n      and 'default_int64' is '-1'.  The input [\\\\\\\"Dori\\\\\\\", \\\\\\\"Amy\\\\\\\", \\\\\\\"Amy\\\\\\\", \\\\\\\"Sally\\\\\\\",\\n      \\\\\\\"Sally\\\\\\\"] would be mapped to [-1, 5, 5, 6, 6].<br>\\n      Since this operator is an one-to-one mapping, its input and output shapes\\n      are the same. Notice that only one of 'keys_*'/'values_*' can be set.<br>\\n      For key look-up, bit-wise comparison is used so even a float NaN can be\\n      mapped to a value in 'values_*' attribute.<br>\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>, TensorOf<[F32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>, TensorOf<[F32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"default_float\", \"type\": \"DefaultValuedAttr<F32Attr, -0.0>\" },\n      { \"name\": \"default_int64\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" },\n      { \"name\": \"default_string\", \"type\": \"DefaultValuedStrAttr<StrAttr, _Unused>\" },\n      { \"name\": \"keys_floats\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"keys_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keys_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"values_floats\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"values_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"values_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LayerNormalization\",\n    \"summary\": \"ONNX LayerNormalization operation\",\n    \"description\": \"This is layer normalization defined in ONNX as function.\\n        The overall computation can be split into two stages.\\n        The first stage is standardization, which makes the\\n        normalized elements have zero mean and unit variances.\\n        The computation required by standardization can be\\n        described by the following equations.\\n        ```\\n        Mean = ReduceMean<axes=normalized_axes>(X)\\n        D = Sub(X, Mean)\\n        DD = Mul(D, D)\\n        Var = ReduceMean<axes=normalized_axes>(DD)\\n        VarEps = Add(Var, epsilon)\\n        StdDev = Sqrt(VarEps)\\n        InvStdDev = Reciprocal(StdDev)\\n        Normalized = Mul(D, InvStdDev)\\n        ```\\n        where `normalized_axes` is `[axis, ..., rank of X - 1]`.\\n        The variables `Var` and `StdDev` stand for variance and\\n        standard deviation, respectively. The second output is\\n        `Mean` and the last one is `InvStdDev`.\\n        Depending on `stash_type` attribute, the actual computation\\n        must happen in different floating-point precision.\\n        For example, if `stash_type` is 1, this operator casts\\n        all input variables to 32-bit float, perform the computation, and\\n        finally cast `Normalized` back to the original type of `X`.\\n        The second stage then scales and shifts the outcome of the\\n        first stage using\\n        ```\\n        NormalizedScaled = Mul(Normalized, Scale)\\n        Y = Add(NormalizedScaled, B)\\n        ```\\n        The second stage doesn't depends on `stash_type`.\\n        All equations are in [this syntax](https://github.com/onnx/onnx/blob/main/docs/Syntax.md).\\n        The same variable (i.e., input, output, and attribute) uses\\n        the same name in the equations above and this operator's definition.\\n        Let `d[i]` indicate the i-th dimension of `X`.\\n        If `X`'s shape is `[d[0], ..., d[axis-1], d[axis], ..., d[rank-1]]`,\\n        the shape of `Mean` and `InvStdDev` is `[d[0], ..., d[axis-1], 1, ..., 1]`.\\n        `Y` and `X` have the same shape. This operator supports unidirectional broadcasting\\n        (tensors `Scale` and `B` should be unidirectional broadcastable to tensor `X`);\\n        for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"Scale\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"Mean\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[BF16]>, NoneType]>\" },\n      { \"name\": \"InvStdDev\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"stash_type\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LayoutTransform\",\n    \"summary\": \"An operation that transforms data between different layout formats\",\n    \"description\": \"An operation that transforms a tensor from a layout to another layout. \\n    A layout is defined by an attribute, i.e. `target_layout`, which allows this\\n    operation work with an arbitrary layout (e.g. a layout used for accelerators).\\n\\n    `target_layout` is optional. If it is not given, the input tensor will be\\n    transformed to a normal tensor that does not have layout.\\n\\n    If `target_layout` is the same as the input's layout, this operation will\\n    become an no-op by canonicalization. \\n\\n    The input and output tensors must have the same shape.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[F16, F32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16, F32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_layout\", \"type\": \"OptionalAttr<AnyAttrOf<[ LayoutAttr ]>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LeakyRelu\",\n    \"summary\": \"ONNX LeakyRelu operation\",\n    \"description\": \"LeakyRelu takes input data (Tensor<T>) and an argument alpha, and produces one\\n  output data (Tensor<T>) where the function `f(x) = alpha * x for x < 0`,\\n  `f(x) = x for x >= 0`, is applied to the data tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 0.01>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Less\",\n    \"summary\": \"ONNX Less operation\",\n    \"description\": \"Returns the tensor resulted from performing the `less` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LessOrEqual\",\n    \"summary\": \"ONNX LessOrEqual operation\",\n    \"description\": \"Returns the tensor resulted from performing the `less_equal` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LinearClassifier\",\n    \"summary\": \"ONNX LinearClassifier operation\",\n    \"description\": \"Linear classifier\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"Z\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"classlabels_ints\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"classlabels_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"coefficients\", \"type\": \"TypedArrayAttrBase<F32Attr>\" },\n      { \"name\": \"intercepts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"multi_class\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"post_transform\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LinearRegressor\",\n    \"summary\": \"ONNX LinearRegressor operation\",\n    \"description\": \"Generalized linear regression evaluation.<br>\\n      If targets is set to 1 (default) then univariate regression is performed.<br>\\n      If targets is set to M then M sets of coefficients must be passed in as a sequence\\n      and M results will be output for each input n in N.<br>\\n      The coefficients array is of length n, and the coefficients for each target are contiguous.\\n      Intercepts are optional but if provided must match the number of targets.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"coefficients\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"intercepts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"post_transform\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" },\n      { \"name\": \"targets\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Log\",\n    \"summary\": \"ONNX Log operation\",\n    \"description\": \"Calculates the natural log of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LogSoftmax\",\n    \"summary\": \"ONNX LogSoftmax operation\",\n    \"description\": \"The operator computes the log of softmax values for the given input:\\n  \\n   LogSoftmax(input, axis) = Log(Softmax(input, axis=axis))\\n  \\n  The \\\\\\\"axis\\\\\\\" attribute indicates the dimension along which LogSoftmax\\n  will be performed. The output tensor has the same shape\\n  and contains the LogSoftmax values of the corresponding input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Loop\",\n    \"summary\": \"ONNX Loop operation\",\n    \"description\": \"Generic Looping construct. This loop has multiple termination conditions:\\n  \\n  1) Trip count. Iteration count specified at runtime. Set by\\n     specifying the input M. Optional. Set to empty string to omit.\\n     Note that a static trip count (specified at graph construction time) can be\\n     specified by passing in a constant node for input M.\\n  2) Loop termination condition. This is an input to the op that determines\\n     whether to run the first iteration and also a loop-carried dependency for\\n     the body graph. The body graph must yield a value for the condition variable,\\n     whether this input is provided or not.\\n  \\n  This table summarizes the operating modes of this operator with equivalent\\n  C-style code:\\n  \\n  Operator inputs defined as (max_trip_count, condition_var).\\n  \\n  * input (\\\\\\\"\\\\\\\", \\\\\\\"\\\\\\\"):\\n          for (int i=0; ; ++i) {\\n            cond = ... // Note this value is ignored, but is required in the body\\n          }\\n  \\n  * input (\\\\\\\"\\\\\\\", cond) // Note this is analogous to a while loop\\n          bool cond = ...;\\n          for (int i=0; cond; ++i) {\\n            cond = ...;\\n          }\\n  \\n  * input (\\\\\\\"\\\\\\\", 1) // Note this is analogous to a do-while loop\\n          bool cond = true\\n          for (int i=0; cond; ++i) {\\n            cond = ...;\\n          }\\n  \\n  * input (trip_count, \\\\\\\"\\\\\\\") // Note this is analogous to a for loop\\n          int trip_count = ...\\n          for (int i=0; i < trip_count; ++i) {\\n            cond = ...; // ignored\\n          }\\n  \\n  * input (trip_count, cond)\\n          int trip_count = ...;\\n          bool cond = ...;\\n          for (int i=0; i < trip_count && cond; ++i) {\\n            cond = ...;\\n          }\\n  \\n  \\n  *Sample usage - cond as well as trip count*\\n  \\n      graph predict-net {\\n        %a = Constant[value = <Scalar Tensor [3]>]()\\n        %b = Constant[value = <Scalar Tensor [6]>]()\\n        %keepgoing = Constant[value = <Scalar Tensor [1]>]()\\n        %max_trip_count = Constant[value = <Scalar Tensor [10]>]()\\n        %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)\\n        return\\n      }\\n  \\n      graph body-net (\\n        %i[INT32, scalar]           // iteration number\\n        %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used\\n        %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b\\n      ) {\\n        %my_local = Add(%a, %b_in)\\n        %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b\\n        %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition\\n        %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated\\n        return %keepgoing_out, %b_out, %user_defined_val\\n      }\\n  \\n  *Sample equivalent C code*\\n  \\n      {\\n        /* User-defined code (enclosing scope) */\\n        int a = 3, b = 6;\\n        bool keepgoing = true; // Analogous to input cond\\n        /* End user-defined code */\\n  \\n        /* Implicitly-defined code */\\n        const int max_trip_count = 10; // Analogous to input M\\n        int user_defined_vals[]; // Imagine this is resizable\\n        /* End implicitly-defined code */\\n        /* initialize loop-carried variables and scan-output variables */\\n        bool keepgoing_out = keepgoing\\n        int b_out = b\\n  \\n        for (int i=0; i < max_trip_count && keepgoing_out; ++i) {\\n          /* Implicitly-defined code: bind actual parameter values\\n             to formal parameter variables of loop-body */\\n          bool keepgoing_in = keepgoing_out;\\n          bool b_in = b_out;\\n  \\n          /* User-defined code (loop body) */\\n          int my_local = a + b_in; // Reading value \\\\\\\"a\\\\\\\" from the enclosing scope is fine\\n          b_out = a - b_in;\\n          keepgoing_out = my_local > b_out;\\n          user_defined_val = b_in + b_in; // b_in and b_out are different variables\\n          /* End user-defined code */\\n  \\n          /* Implicitly defined-code */\\n          user_defined_vals[i] = user_defined_val // accumulate scan-output values\\n        }\\n        // int t = my_local; // Can't do this. my_local is not accessible here.\\n  \\n        // The values below are bound to the output variables of the loop and therefore accessible\\n        // b_out; user_defined_vals; keepgoing_out;\\n      }\\n  \\n  There are several things of note in this code snippet:\\n  \\n  1) Values from the enclosing scope (i.e. variable \\\\\\\"a\\\\\\\" here) are in scope and can\\n     be referenced in the inputs of the loop.\\n  2) Any values computed in the loop body that needs to be used in a subsequent\\n     iteration or after the loop are modelled using a pair of variables in the loop-body,\\n     consisting of an input variable (eg., b_in) and an output variable (eg., b_out).\\n     These are referred to as loop-carried dependences. The loop operation node\\n     supplies the input value of the input variable for the first iteration, and\\n     returns the output value of the output variable produced by the final\\n     iteration.\\n  3) Scan_output variables are used to implicitly concatenate values computed across\\n     all the iterations. In the above example, the value of user_defined_val computed\\n     over all iterations are concatenated and returned as the value of user_defined_vals\\n     after the loop.\\n  4) Values created in the body cannot be accessed in the enclosing scope,\\n     except using the mechanism described above.\\n  \\n  Note that the semantics of this op support \\\\\\\"diagonal\\\\\\\" or \\\\\\\"wavefront\\\\\\\" execution.\\n  (See Step 3 here for an example:\\n  https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/).\\n  Frontends should emit multi-layer RNNs as a series of While operators (with\\n  time being the inner looping dimension), with each successive layer consuming\\n  the scan_outputs from the previous layer, possibly going through several\\n  point-wise operators (e.g. dropout, residual connections, linear layer).\\n  \\n  The input/output of subgraph (produced by loop node) matching is based on order instead of name. The implementation will figure out the names based on this order.\",\n    \"operands\": [\n      { \"name\": \"M\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" },\n      { \"name\": \"cond\", \"type\": \"AnyTypeOf<[TensorOf<[I1]>, NoneType]>\" },\n      { \"name\": \"v_initial\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] >, TensorOf < [ F8E4M3FN ] >, TensorOf < [ F8E4M3FNUZ ] >, TensorOf < [ F8E5M2 ] >, TensorOf < [ F8E5M2FNUZ ] >, TensorOf < [ UI < 4 > ] >, TensorOf < [ I < 4 > ] >, SeqOf < [ TensorOf < [ UI8 ] > ] >, SeqOf < [ TensorOf < [ UI16 ] > ] >, SeqOf < [ TensorOf < [ UI32 ] > ] >, SeqOf < [ TensorOf < [ UI64 ] > ] >, SeqOf < [ TensorOf < [ I8 ] > ] >, SeqOf < [ TensorOf < [ I16 ] > ] >, SeqOf < [ TensorOf < [ I32 ] > ] >, SeqOf < [ TensorOf < [ I64 ] > ] >, SeqOf < [ TensorOf < [ BF16 ] > ] >, SeqOf < [ TensorOf < [ F16 ] > ] >, SeqOf < [ TensorOf < [ F32 ] > ] >, SeqOf < [ TensorOf < [ F64 ] > ] >, SeqOf < [ TensorOf < [ StringType ] > ] >, SeqOf < [ TensorOf < [ I1 ] > ] >, SeqOf < [ TensorOf < [ Complex < F32 > ] > ] >, SeqOf < [ TensorOf < [ Complex < F64 > ] > ] >, SeqOf < [ TensorOf < [ F8E4M3FN ] > ] >, SeqOf < [ TensorOf < [ F8E4M3FNUZ ] > ] >, SeqOf < [ TensorOf < [ F8E5M2 ] > ] >, SeqOf < [ TensorOf < [ F8E5M2FNUZ ] > ] >, SeqOf < [ TensorOf < [ UI < 4 > ] > ] >, SeqOf < [ TensorOf < [ I < 4 > ] > ] >, OptOf < SeqOf < [ TensorOf < [ UI8 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I8 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ BF16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ StringType ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I1 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ Complex < F32 > ] > ] > >, OptOf < SeqOf < [ TensorOf < [ Complex < F64 > ] > ] > >, OptOf < TensorOf < [ UI8 ] > >, OptOf < TensorOf < [ UI16 ] > >, OptOf < TensorOf < [ UI32 ] > >, OptOf < TensorOf < [ UI64 ] > >, OptOf < TensorOf < [ I8 ] > >, OptOf < TensorOf < [ I16 ] > >, OptOf < TensorOf < [ I32 ] > >, OptOf < TensorOf < [ I64 ] > >, OptOf < TensorOf < [ BF16 ] > >, OptOf < TensorOf < [ F16 ] > >, OptOf < TensorOf < [ F32 ] > >, OptOf < TensorOf < [ F64 ] > >, OptOf < TensorOf < [ StringType ] > >, OptOf < TensorOf < [ I1 ] > >, OptOf < TensorOf < [ Complex < F32 > ] > >, OptOf < TensorOf < [ Complex < F64 > ] > >, OptOf < TensorOf < [ F8E4M3FN ] > >, OptOf < TensorOf < [ F8E4M3FNUZ ] > >, OptOf < TensorOf < [ F8E5M2 ] > >, OptOf < TensorOf < [ F8E5M2FNUZ ] > >, OptOf < TensorOf < [ UI < 4 > ] > >, OptOf < TensorOf < [ I < 4 > ] > > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"v_final_and_scan_outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] >, TensorOf < [ F8E4M3FN ] >, TensorOf < [ F8E4M3FNUZ ] >, TensorOf < [ F8E5M2 ] >, TensorOf < [ F8E5M2FNUZ ] >, TensorOf < [ UI < 4 > ] >, TensorOf < [ I < 4 > ] >, SeqOf < [ TensorOf < [ UI8 ] > ] >, SeqOf < [ TensorOf < [ UI16 ] > ] >, SeqOf < [ TensorOf < [ UI32 ] > ] >, SeqOf < [ TensorOf < [ UI64 ] > ] >, SeqOf < [ TensorOf < [ I8 ] > ] >, SeqOf < [ TensorOf < [ I16 ] > ] >, SeqOf < [ TensorOf < [ I32 ] > ] >, SeqOf < [ TensorOf < [ I64 ] > ] >, SeqOf < [ TensorOf < [ BF16 ] > ] >, SeqOf < [ TensorOf < [ F16 ] > ] >, SeqOf < [ TensorOf < [ F32 ] > ] >, SeqOf < [ TensorOf < [ F64 ] > ] >, SeqOf < [ TensorOf < [ StringType ] > ] >, SeqOf < [ TensorOf < [ I1 ] > ] >, SeqOf < [ TensorOf < [ Complex < F32 > ] > ] >, SeqOf < [ TensorOf < [ Complex < F64 > ] > ] >, SeqOf < [ TensorOf < [ F8E4M3FN ] > ] >, SeqOf < [ TensorOf < [ F8E4M3FNUZ ] > ] >, SeqOf < [ TensorOf < [ F8E5M2 ] > ] >, SeqOf < [ TensorOf < [ F8E5M2FNUZ ] > ] >, SeqOf < [ TensorOf < [ UI < 4 > ] > ] >, SeqOf < [ TensorOf < [ I < 4 > ] > ] >, OptOf < SeqOf < [ TensorOf < [ UI8 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ UI64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I8 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ BF16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F16 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F32 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ F64 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ StringType ] > ] > >, OptOf < SeqOf < [ TensorOf < [ I1 ] > ] > >, OptOf < SeqOf < [ TensorOf < [ Complex < F32 > ] > ] > >, OptOf < SeqOf < [ TensorOf < [ Complex < F64 > ] > ] > >, OptOf < TensorOf < [ UI8 ] > >, OptOf < TensorOf < [ UI16 ] > >, OptOf < TensorOf < [ UI32 ] > >, OptOf < TensorOf < [ UI64 ] > >, OptOf < TensorOf < [ I8 ] > >, OptOf < TensorOf < [ I16 ] > >, OptOf < TensorOf < [ I32 ] > >, OptOf < TensorOf < [ I64 ] > >, OptOf < TensorOf < [ BF16 ] > >, OptOf < TensorOf < [ F16 ] > >, OptOf < TensorOf < [ F32 ] > >, OptOf < TensorOf < [ F64 ] > >, OptOf < TensorOf < [ StringType ] > >, OptOf < TensorOf < [ I1 ] > >, OptOf < TensorOf < [ Complex < F32 > ] > >, OptOf < TensorOf < [ Complex < F64 > ] > >, OptOf < TensorOf < [ F8E4M3FN ] > >, OptOf < TensorOf < [ F8E4M3FNUZ ] > >, OptOf < TensorOf < [ F8E5M2 ] > >, OptOf < TensorOf < [ F8E5M2FNUZ ] > >, OptOf < TensorOf < [ UI < 4 > ] > >, OptOf < TensorOf < [ I < 4 > ] > > ]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LpNormalization\",\n    \"summary\": \"ONNX LpNormalization operation\",\n    \"description\": \"Given a matrix, apply Lp-normalization along the provided axis.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" },\n      { \"name\": \"p\", \"type\": \"DefaultValuedAttr<SI64Attr, 2>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LpPool\",\n    \"summary\": \"ONNX LpPool operation\",\n    \"description\": \"LpPool consumes an input tensor X and applies Lp pooling across\\n   the tensor according to kernel sizes, stride sizes, and pad lengths.\\n   Lp pooling consisting of computing the Lp norm on all values of a subset\\n   of the input tensor according to the kernel size and downsampling the\\n   data into the output tensor Y for further processing. The output spatial shape will be following:\\n   ```\\n   output_spatial_shape[i] = floor((input_spatial_shape[i] + pad_shape[i] - {kernelSpatialShape}) / strides_spatial_shape[i] + 1)\\n   ```\\n   or\\n   ```\\n   output_spatial_shape[i] = ceil((input_spatial_shape[i] + pad_shape[i] - {kernelSpatialShape}) / strides_spatial_shape[i] + 1)\\n   ```\\n   if ceil_mode is enabled `pad_shape[i]` is the sum of pads along axis `i`.\\n  \\n   `auto_pad` is a DEPRECATED attribute. If you are using them currently, the output spatial shape will be following:\\n   ```\\n   VALID: output_spatial_shape[i] = ceil((input_spatial_shape[i] - {kernelSpatialShape} + 1) / strides_spatial_shape[i])\\n   SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides_spatial_shape[i])\\n   ```\\n   And pad shape will be following if `SAME_UPPER` or `SAME_LOWER`:\\n   ```\\n   pad_shape[i] = (output_spatial_shape[i] - 1) * strides_spatial_shape[i] + {kernelSpatialShape} - input_spatial_shape[i]\\n   ```\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"p\", \"type\": \"DefaultValuedAttr<SI64Attr, 2>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LRN\",\n    \"summary\": \"ONNX LRN operation\",\n    \"description\": \"Local Response Normalization proposed in the [AlexNet paper](https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf).\\n  It normalizes over local input regions.\\n  The local region is defined across the channels. For an element `X[n, c, d1, ..., dk]` in a tensor\\n  of shape `(N x C x D1 x D2, ..., Dk)`, its region is\\n  `{X[n, i, d1, ..., dk] | max(0, c - floor((size - 1) / 2)) <= i <= min(C - 1, c + ceil((size - 1) / 2))}`.\\n  \\n  `square_sum[n, c, d1, ..., dk] = sum(X[n, i, d1, ..., dk] ^ 2)`,\\n  where `max(0, c - floor((size - 1) / 2)) <= i <= min(C - 1, c + ceil((size - 1) / 2))`.\\n  \\n  `Y[n, c, d1, ..., dk] = X[n, c, d1, ..., dk] / (bias + alpha / size * square_sum[n, c, d1, ..., dk] ) ^ beta`\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0001>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F32Attr, 0.75>\" },\n      { \"name\": \"bias\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"size\", \"type\": \"SI64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.LSTM\",\n    \"summary\": \"ONNX LSTM operation\",\n    \"description\": \"Computes an one-layer LSTM. This operator is usually supported via some\\n  custom implementation such as CuDNN.\\n  \\n  Notations:\\n  \\n  * `X` - input tensor\\n  * `i` - input gate\\n  * `o` - output gate\\n  * `f` - forget gate\\n  * `c` - cell gate\\n  * `t` - time step (t-1 means previous time step)\\n  * `W[iofc]` - W parameter weight matrix for input, output, forget, and cell gates\\n  * `R[iofc]` - R recurrence weight matrix for input, output, forget, and cell gates\\n  * `Wb[iofc]` - W bias vectors for input, output, forget, and cell gates\\n  * `Rb[iofc]` - R bias vectors for input, output, forget, and cell gates\\n  * `P[iof]`  - P peephole weight vector for input, output, and forget gates\\n  * `WB[iofc]` - W parameter weight matrix for backward input, output, forget, and cell gates\\n  * `RB[iofc]` - R recurrence weight matrix for backward input, output, forget, and cell gates\\n  * `WBb[iofc]` - W bias vectors for backward input, output, forget, and cell gates\\n  * `RBb[iofc]` - R bias vectors for backward input, output, forget, and cell gates\\n  * `PB[iof]`  - P peephole weight vector for backward input, output, and forget gates\\n  * `H` - Hidden state\\n  * `num_directions` - 2 if direction == bidirectional else 1\\n  \\n  Activation functions:\\n  \\n  * Relu(x)                - max(0, x)\\n  * Tanh(x)                - (1 - e^{-2x})/(1 + e^{-2x})\\n  * Sigmoid(x)             - 1/(1 + e^{-x})\\n  \\n  NOTE: Below are optional\\n  \\n  * Affine(x)              - alpha*x + beta\\n  * LeakyRelu(x)           - x if x >= 0 else alpha * x\\n  * ThresholdedRelu(x)     - x if x >= alpha else 0\\n  * ScaledTanh(x)          - alpha*Tanh(beta*x)\\n  * HardSigmoid(x)         - min(max(alpha*x + beta, 0), 1)\\n  * Elu(x)                 - x if x >= 0 else alpha*(e^x - 1)\\n  * Softsign(x)            - x/(1 + |x|)\\n  * Softplus(x)            - log(1 + e^x)\\n  \\n  Equations (Default: f=Sigmoid, g=Tanh, h=Tanh):\\n  \\n  * it = f(Xt*(Wi^T) + Ht-1*(Ri^T) + Pi (.) Ct-1 + Wbi + Rbi)\\n  * ft = f(Xt*(Wf^T) + Ht-1*(Rf^T) + Pf (.) Ct-1 + Wbf + Rbf)\\n  * ct = g(Xt*(Wc^T) + Ht-1*(Rc^T) + Wbc + Rbc)\\n  * Ct = ft (.) Ct-1 + it (.) ct\\n  * ot = f(Xt*(Wo^T) + Ht-1*(Ro^T) + Po (.) Ct + Wbo + Rbo)\\n  * Ht = ot (.) h(Ct)\\n  This operator has **optional** inputs/outputs. See [the doc](IR.md) for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"W\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"R\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"sequence_lens\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, NoneType]>\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"initial_c\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"P\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"Y_c\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"activation_alpha\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"activation_beta\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"activations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"clip\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"direction\", \"type\": \"DefaultValuedStrAttr<StrAttr, forward>\" },\n      { \"name\": \"hidden_size\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"input_forget\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"layout\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MatMul\",\n    \"summary\": \"ONNX MatMul operation\",\n    \"description\": \"Matrix product that behaves like [numpy.matmul](https://numpy.org/doc/stable/reference/generated/numpy.matmul.html).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MatMulInteger\",\n    \"summary\": \"ONNX MatMulInteger operation\",\n    \"description\": \"Matrix product that behaves like [numpy.matmul](https://numpy.org/doc/stable/reference/generated/numpy.matmul.html).\\n  The production MUST never overflow. The accumulation may overflow if and only if in 32 bits.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"a_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, NoneType]>\" },\n      { \"name\": \"b_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Max\",\n    \"summary\": \"ONNX Max operation\",\n    \"description\": \"Element-wise max of each of the input tensors (with Numpy-style broadcasting support).\\n  All inputs and outputs must have the same data type.\\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"data_0\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ BF16 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"max\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MaxPool\",\n    \"summary\": \"ONNX MaxPool operation\",\n    \"description\": \"MaxPool consumes an input tensor X and applies max pooling across\\n   the tensor according to kernel sizes, stride sizes, and pad lengths.\\n   max pooling consisting of computing the max on all values of a\\n   subset of the input tensor according to the kernel size and downsampling the\\n   data into the output tensor Y for further processing. The output spatial shape is calculated differently\\n   depending on whether explicit padding is used, where pads is employed, or auto padding is used, where auto_pad is utilized.\\n   With explicit padding (https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html?highlight=maxpool#torch.nn.MaxPool2d):\\n   ```\\n   output_spatial_shape[i] = floor((input_spatial_shape[i] + pad_shape[i] - dilation[i] * (kernel_shape[i] - 1) - 1) / strides_spatial_shape[i] + 1)\\n   ```\\n   or\\n   ```\\n   output_spatial_shape[i] = ceil((input_spatial_shape[i] + pad_shape[i] - dilation[i] * (kernel_shape[i] - 1) - 1) / strides_spatial_shape[i] + 1)\\n   ```\\n   if ceil_mode is enabled. `pad_shape[i]` is the sum of pads along axis `i`. Sliding windows that would start in the right padded region are ignored.\\n  \\n   `auto_pad` is a DEPRECATED attribute. If you are using them currently, the output spatial shape will be following when ceil_mode is enabled:\\n   ```\\n   VALID: output_spatial_shape[i] = ceil((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) + 1) / strides_spatial_shape[i])\\n   SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides_spatial_shape[i])\\n   ```\\n   or when ceil_mode is disabled (https://www.tensorflow.org/api_docs/python/tf/keras/layers/AveragePooling2D):\\n   ```\\n   VALID: output_spatial_shape[i] = floor((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1)) / strides_spatial_shape[i]) + 1\\n   SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = floor((input_spatial_shape[i] - 1) / strides_spatial_shape[i]) + 1\\n   ```\\n   And pad shape will be following if `SAME_UPPER` or `SAME_LOWER`:\\n   ```\\n   pad_shape[i] = (output_spatial_shape[i] - 1) * strides_spatial_shape[i] + ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) - input_spatial_shape[i]\\n   ```\\n   The output of each pooling window is maximum number of elements exclude pad.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[UI8]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"Indices\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"storage_order\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MaxPoolSingleOut\",\n    \"category\": \"Pool\",\n    \"summary\": \"ONNX MaxPool operation with a single output.\",\n    \"description\": \"ONNX MaxPool operation with a single output.\\n    See ONNXMaxPoolOp for a full description of the MaxPool semantics.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"o_Y\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyTensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"storage_order\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MaxRoiPool\",\n    \"summary\": \"ONNX MaxRoiPool operation\",\n    \"description\": \"ROI max pool consumes an input tensor X and region of interests (RoIs) to\\n   apply max pooling across each RoI, to produce output 4-D tensor of shape\\n   (num_rois, channels, pooled_shape[0], pooled_shape[1]).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"rois\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pooled_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"spatial_scale\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MaxUnpool\",\n    \"summary\": \"ONNX MaxUnpool operation\",\n    \"description\": \"MaxUnpool essentially computes the partial inverse of the MaxPool op.\\n   The input information to this op is typically the output information from a MaxPool op. The first\\n   input tensor X is the tensor that needs to be unpooled, which is typically the pooled tensor (first output)\\n   from MaxPool. The second input tensor, I, contains the indices to the (locally maximal) elements corresponding\\n   to the elements in the first input tensor X. Input tensor I is typically the second output of the MaxPool op.\\n   The third (optional) input is a tensor that specifies the output size of the unpooling operation.\\n  \\n  MaxUnpool is intended to do 'partial' inverse of the MaxPool op. 'Partial' because all the non-maximal\\n   values from the original input to MaxPool are set to zero in the output of the MaxUnpool op. Pooling\\n   the result of an unpooling operation should give back the original input to the unpooling op.\\n  \\n  MaxUnpool can produce the same output size for several input sizes, which makes unpooling op ambiguous.\\n   The third input argument, output_size, is meant to disambiguate the op and produce output tensor of\\n   known/predictable size.\\n  \\n  In addition to the inputs, MaxUnpool takes three attributes, namely kernel_shape, strides, and pads,\\n   which define the exact unpooling op. The attributes typically have the same values as the corresponding\\n   pooling op that the unpooling op is trying to invert.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"I\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"output_shape\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Mean\",\n    \"summary\": \"ONNX Mean operation\",\n    \"description\": \"Element-wise mean of each of the input tensors (with Numpy-style broadcasting support).\\n  All inputs and outputs must have the same data type.\\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"data_0\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ BF16 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"mean\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MeanVarianceNormalization\",\n    \"summary\": \"ONNX MeanVarianceNormalization operation\",\n    \"description\": \"A MeanVarianceNormalization Function: Perform mean variance normalization\\n        on the input tensor X using formula: `(X-EX)/sqrt(E(X-EX)^2)`\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {0, 2, 3}>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.MelWeightMatrix\",\n    \"summary\": \"ONNX MelWeightMatrix operation\",\n    \"description\": \"Generate a MelWeightMatrix that can be used to re-weight a Tensor containing a linearly sampled frequency spectra (from DFT or STFT) into num_mel_bins frequency information based on the [lower_edge_hertz, upper_edge_hertz] range on the mel scale.\\n  This function defines the mel scale in terms of a frequency in hertz according to the following formula:\\n  \\n      mel(f) = 2595 * log10(1 + f/700)\\n  \\n  In the returned matrix, all the triangles (filterbanks) have a peak value of 1.0.\\n  \\n  The returned MelWeightMatrix can be used to right-multiply a spectrogram S of shape [frames, num_spectrogram_bins] of linear scale spectrum values (e.g. STFT magnitudes) to generate a \\\\\\\"mel spectrogram\\\\\\\" M of shape [frames, num_mel_bins].\",\n    \"operands\": [\n      { \"name\": \"num_mel_bins\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"dft_length\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"sample_rate\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"lower_edge_hertz\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"upper_edge_hertz\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_datatype\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Min\",\n    \"summary\": \"ONNX Min operation\",\n    \"description\": \"Element-wise min of each of the input tensors (with Numpy-style broadcasting support).\\n  All inputs and outputs must have the same data type.\\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"data_0\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ BF16 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"min\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Mish\",\n    \"summary\": \"ONNX Mish operation\",\n    \"description\": \"Mish: A Self Regularized Non-Monotonic Neural Activation Function.\\n  \\n  Perform the linear unit element-wise on the input tensor X using formula:\\n  \\n  ```\\n  mish(x) = x * tanh(softplus(x)) = x * tanh(ln(1 + e^{x}))\\n  ```\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Mod\",\n    \"summary\": \"ONNX Mod operation\",\n    \"description\": \"Performs an element-wise binary modulo operation.\\n  The semantics and supported data types depend on the value of the `fmod` attribute which must be `0` (default), or `1`.\\n  \\n  If the `fmod` attribute is set to `0`, `T` is constrained to integer data types and the semantics follow that of the Python `%`-operator.\\n  The sign of the result is that of the divisor.\\n  \\n  If `fmod` is set to `1`, the behavior of this operator follows that of the `fmod` function in C and `T` is constrained to floating point data types.\\n  The result of this operator is the remainder of the division operation `x / y` where `x` and `y` are respective elements of `A` and `B`. The result is exactly the value `x - n * y`, where `n` is `x / y` with its fractional part truncated.\\n  The returned value has the same sign as `x` (except if `x` is `-0`) and is less or equal to `|y|` in magnitude.\\n  The following special cases apply when `fmod` is set to `1`:\\n  - If `x` is `-0` and `y` is greater than zero, either `+0` or `-0` may be returned.\\n  - If `x` is `±∞` and `y` is not `NaN`, `NaN` is returned.\\n  - If `y` is `±0` and `x` is not `NaN`, `NaN` should be returned.\\n  - If `y` is `±∞` and `x` is finite, `x` is returned.\\n  - If either argument is `NaN`, `NaN` is returned.\\n  \\n  This operator supports **multidirectional (i.e., NumPy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmod\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Momentum\",\n    \"summary\": \"ONNX Momentum operation\",\n    \"description\": \"Compute one iteration of stochastic gradient update with momentum.\\n      This operator can conduct the optimization of multiple tensor variables.\\n  \\n      Let's define the behavior of this operator. As you can imagine, SG with momentum requires\\n      several parameters:\\n  \\n       - The learning-rate \\\\\\\"R\\\\\\\".\\n       - The update count \\\\\\\"T\\\\\\\". That is, the number of conducted training iterations. It should\\n         be zero in the first training iteration.\\n       - A L2-norm regularization coefficient \\\\\\\"norm_coefficient\\\\\\\".\\n       - A decay coefficient of previous accumulated gradient (i.e., momentum) \\\\\\\"alpha\\\\\\\".\\n       - The scaling coefficient of current gradient \\\\\\\"beta\\\\\\\".\\n       - An attribute to choose either standard momentum or Nesterov's momentum \\\\\\\"mode\\\\\\\" should\\n         be used.\\n  \\n      For the sake of simplicity, assume that there is only one tensor (called \\\\\\\"X\\\\\\\") to be optimized.\\n      Other necessary inputs are \\\\\\\"X\\\\\\\"'s gradient (called \\\\\\\"G\\\\\\\") and \\\\\\\"X\\\\\\\"'s momentum (called \\\\\\\"V\\\\\\\"). This\\n      Momentum operator maps all these inputs to the new value of \\\\\\\"X\\\\\\\" (called \\\\\\\"X_new\\\\\\\") and its new\\n      momentum (called \\\\\\\"V_new\\\\\\\").\\n  \\n      This operator supports two different momentum algorithms. Set the attribute \\\\\\\"mode\\\\\\\" to\\n      \\\\\\\"nesterov\\\\\\\" if Nesterov's momentum is desired. Otherwise, set the attribute \\\\\\\"model\\\\\\\" to\\n      \\\\\\\"standard\\\\\\\" to use standard momentum. Computation details are described subsequently.\\n  \\n      Let \\\\\\\"+\\\\\\\", \\\\\\\"-\\\\\\\", \\\\\\\"*\\\\\\\", and \\\\\\\"/\\\\\\\" are all element-wise operations with numpy-style broadcasting.\\n  \\n      Pseudo code for SG with standard momentum:\\n  \\n        // Add gradient of 0.5 * norm_coefficient * ||X||^2, where ||X|| is the sum of squared\\n        // values of all elements in X.\\n        G_regularized = norm_coefficient * X + G\\n  \\n        // In the first training iteration, beta should always be 1.\\n        beta_adjusted = T > 0 ? beta : 1\\n  \\n        // Compute the current momentum based on previous momentum and the current gradient.\\n        V_new = alpha * V + beta_adjusted * G_regularized\\n  \\n        // Update X.\\n        X_new = X - R * V_new\\n  \\n      Pseudo code for SG with Nesterov's momentum:\\n  \\n        // Add gradient of 0.5 * norm_coefficient * ||X||^2, where ||X|| is the sum of squared\\n        // values of all elements in X.\\n        G_regularized = norm_coefficient * X + G;\\n  \\n        // In the first training iteration, beta should always be 1.\\n        beta_adjusted = T > 0 ? beta : 1\\n  \\n        // Compute the current momentum based on previous momentum and the current gradient.\\n        V_new = alpha * V + beta_adjusted * G_regularized;\\n  \\n        // Compute final update direction and then update X.\\n        X_new = X - R * (G_regularized + alpha * V_new)\\n  \\n      If one assign this operators to optimize multiple inputs, for example, \\\\\\\"X_1\\\\\\\" and \\\\\\\"X_2\\\\\\\". The same\\n      pseudo code would be extended to handle all tensors jointly. More specifically, we can view \\\\\\\"X\\\\\\\" as a\\n      concatenation of \\\\\\\"X_1\\\\\\\" and \\\\\\\"X_2\\\\\\\" (of course, their gradient and accumulate gradient should\\n      be concatenated too) and then our pseudo code becomes applicable.\",\n    \"operands\": [\n      { \"name\": \"R\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"T\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F32 ] >, TensorOf < [ F64 ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta\", \"type\": \"F32Attr\" },\n      { \"name\": \"mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"norm_coefficient\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Mul\",\n    \"summary\": \"ONNX Mul operation\",\n    \"description\": \"Performs element-wise binary multiplication (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\\n  \\n  (Opset 14 change): Extend supported types to include uint8, int8, uint16, and int16.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Multinomial\",\n    \"summary\": \"ONNX Multinomial operation\",\n    \"description\": \"Generate a tensor of samples from a multinomial distribution according to the probabilities\\n  of each of the possible outcomes.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"DefaultValuedAttr<SI64Attr, 6>\" },\n      { \"name\": \"sample_size\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Neg\",\n    \"summary\": \"ONNX Neg operation\",\n    \"description\": \"Neg takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where each element flipped sign, y = -x, is applied to\\n  the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[I32]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[I32]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.NegativeLogLikelihoodLoss\",\n    \"summary\": \"ONNX NegativeLogLikelihoodLoss operation\",\n    \"description\": \"A NegativeLogLikelihoodLoss operator computes (weighted) negative log likelihood loss.\\n  Its \\\\\\\"input\\\\\\\" tensor has the shape of (N, C, d1, d2, ..., dk) where k >= 0.\\n  The \\\\\\\"input\\\\\\\" tensor contains log-probabilities for input[n, :, d_1, d_2,..., d_k] being in a class of [0, C).\\n  The operator's \\\\\\\"target\\\\\\\" input tensor has the shape of (N, d1, d2, ..., dk). It encodes class labels (one of C classes)\\n  or it may contain a special value (indicated by an attribute ignore_index) for N x d1 x d2 x ... x dk samples.\\n  The loss value for input[n, :, d_1, d_2,...d_k] being classified as class c = target[n][d_1][d_2]...[d_k] is computed as:\\n  \\n  ```\\n  loss[n][d_1][d_2]...[d_k] = -input[n][c][d_1][d_2]...[d_k].\\n  ```\\n  \\n  When an optional \\\\\\\"weight\\\\\\\" is provided, the sample loss is calculated as:\\n  \\n  ```\\n  loss[n][d_1][d_2]...[d_k] = -input[n][c][d_1][d_2]...[d_k] * weight[c].\\n  ```\\n  \\n  loss is zero for the case when target-value equals ignore_index.\\n  \\n  ```\\n  loss[n][d_1][d_2]...[d_k] = 0, when target[n][d_1][d_2]...[d_k] = ignore_index\\n  ```\\n  \\n  If \\\\\\\"reduction\\\\\\\" attribute is set to \\\\\\\"none\\\\\\\", the operator's output will be the above loss with shape (N, d1, d2, ..., dk).\\n  If \\\\\\\"reduction\\\\\\\" attribute is set to \\\\\\\"mean\\\\\\\" (the default attribute value), the output loss is (weight) averaged:\\n  \\n  ```\\n  mean(loss), if \\\\\\\"weight\\\\\\\" is not provided,\\n  ```\\n  \\n  or if weight is provided,\\n  \\n  ```\\n  sum(loss) / sum(weight[target[n][d_1][d_2]...[d_k]]]), for all samples.\\n  ```\\n  \\n  If \\\\\\\"reduction\\\\\\\" attribute is set to \\\\\\\"sum\\\\\\\", the output is a scalar: `sum(loss)`.\\n  \\n  See also https://pytorch.org/docs/stable/nn.html#torch.nn.NLLLoss.\\n  \\n  Example 1:\\n  \\n  ```\\n  // negative log likelihood loss, \\\\\\\"none\\\\\\\" reduction\\n  N, C, d1 = 2, 3, 2\\n  input = [[[1.0, 2.0], [2.0, 2.0], [3.0, 2.0]],\\n            [[0.0, 1.0], [2.0, 2.0], [1.0, 2]]]\\n  target = [[2, 1], [0, 2]]\\n  \\n  loss = np.zeros((N, d1))\\n  for n in range(N):\\n      for d_1 in range(d1):\\n          c = target[n][d_1]\\n          loss[n][d_1] = -input[n][c][d_1]\\n  \\n  // print(loss)\\n  // [[-3. -2.]\\n  //  [-0. -2.]]\\n  ```\\n  \\n  Example 2:\\n  \\n  ```\\n  // weighted negative log likelihood loss, sum reduction\\n  N, C, d1 = 2, 3, 2\\n  input = [[[1.0, 2.0], [2.0, 2.0], [3.0, 2.0]],\\n          [[0.0, 1.0], [2.0, 2.0], [1.0, 2]]]\\n  target = [[2, 1], [0, 2]]\\n  weight = [0.2, 0.3, 0.1]\\n  loss = np.zeros((N, d1))\\n  for n in range(N):\\n      for d_1 in range(d1):\\n          c = target[n][d_1]\\n          loss[n][d_1] = -input[n][c][d_1] * weight[c]\\n  \\n  loss = np.sum(loss)\\n  // print(loss)\\n  // -1.1\\n  ```\\n  \\n  Example 3:\\n  \\n  ```\\n  // weighted negative log likelihood loss, mean reduction\\n  N, C, d1 = 2, 3, 2\\n  input = [[[1.0, 2.0], [2.0, 2.0], [3.0, 2.0]],\\n          [[0.0, 1.0], [2.0, 2.0], [1.0, 2]]]\\n  target = [[2, 1], [0, 2]]\\n  weight = [0.2, 0.3, 0.1]\\n  loss = np.zeros((N, d1))\\n  weight_total = 0\\n  for n in range(N):\\n      for d_1 in range(d1):\\n          c = target[n][d_1]\\n          loss[n][d_1] = -input[n][c][d_1] * weight[c]\\n          weight_total = weight_total + weight[c]\\n  \\n  loss = np.sum(loss) / weight_total\\n  // print(loss)\\n  // -1.57\\n  ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"target\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"weight\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"loss\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ignore_index\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedStrAttr<StrAttr, mean>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.NonMaxSuppression\",\n    \"summary\": \"ONNX NonMaxSuppression operation\",\n    \"description\": \"Filter out boxes that have high intersection-over-union (IOU) overlap with previously selected boxes.\\n  Bounding boxes with score less than score_threshold are removed. Bounding box format is indicated by attribute center_point_box.\\n  Note that this algorithm is agnostic to where the origin is in the coordinate system and more generally is invariant to\\n  orthogonal transformations and translations of the coordinate system; thus translating or reflections of the coordinate system\\n  result in the same boxes being selected by the algorithm.\\n  The selected_indices output is a set of integers indexing into the input collection of bounding boxes representing the selected boxes.\\n  The bounding box coordinates corresponding to the selected indices can then be obtained using the Gather or GatherND operation.\",\n    \"operands\": [\n      { \"name\": \"boxes\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"scores\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"max_output_boxes_per_class\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" },\n      { \"name\": \"iou_threshold\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, NoneType]>\" },\n      { \"name\": \"score_threshold\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_indices\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"center_point_box\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.NonZero\",\n    \"summary\": \"ONNX NonZero operation\",\n    \"description\": \"Returns the indices of the elements that are non-zero\\n      (in row-major order - by dimension).\\n      NonZero behaves similar to numpy.nonzero:\\n      https://docs.scipy.org/doc/numpy/reference/generated/numpy.nonzero.html,\\n      but for scalar input, NonZero produces output shape (0, N) instead of (1, N), which is different from Numpy's behavior.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Normalizer\",\n    \"summary\": \"ONNX Normalizer operation\",\n    \"description\": \"Normalize the input.  There are three normalization modes, which have the corresponding formulas,\\n      defined using element-wise infix operators '/' and '^' and tensor-wide functions 'max' and 'sum':<br>\\n  <br>\\n      Max: Y = X / max(X)<br>\\n      L1:  Y = X / sum(X)<br>\\n      L2:  Y = sqrt(X^2 / sum(X^2)}<br>\\n      In all modes, if the divisor is zero, Y == X.\\n  <br>\\n      For batches, that is, [N,C] tensors, normalization is done along the C axis. In other words, each row\\n      of the batch is normalized independently.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"norm\", \"type\": \"DefaultValuedStrAttr<StrAttr, MAX>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Not\",\n    \"summary\": \"ONNX Not operation\",\n    \"description\": \"Returns the negation of the input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.NoValue\",\n    \"summary\": \"An operation representing the absence of a value.\",\n    \"description\": \"This operation can be used to represent the absence of a value. It is typically\\n    used as an argument to operators that have optional parameters.\\n\\n    Example:\\n    ```MLIR\\n      %cst = \\\"onnx.NoValue\\\"() {value} : () -> none\\n      %0, %1 = \\\"onnx.Split\\\"(%arg0, %cst) { axis=1 : si64 } : (tensor<?xf32>, none) -> (tensor<*xf32>, tensor<*xf32>)\\n    ```\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"results\": [\n      { \"name\": \"none_val\", \"type\": \"NoneType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.OneHot\",\n    \"summary\": \"ONNX OneHot operation\",\n    \"description\": \"Produces a one-hot tensor based on inputs.\\n      The locations represented by the index values in the 'indices' input tensor will have 'on_value'\\n      and the other locations will have 'off_value' in the output tensor, where 'on_value' and 'off_value'\\n      are specified as part of required input argument 'values', which is a two-element tensor of format\\n      [off_value, on_value]. The rank of the output tensor will be one greater than the rank of the\\n      input tensor. The additional dimension is for one-hot representation. The additional dimension will\\n      be inserted at the position specified by 'axis'. If 'axis' is not specified then then additional\\n      dimension will be inserted as the innermost dimension, i.e. axis=-1. The size of the additional\\n      dimension is specified by required scalar input 'depth'. The type of the output tensor is the same\\n      as the type of the 'values' input. Any entries in the 'indices' input tensor with values outside\\n      the range [-depth, depth-1] will result in one-hot representation with all 'off_value' values in the\\n      output tensor.\\n  \\n      when axis = 0:\\n      output[input[i, j, k], i, j, k] = 1 for all i, j, k and 0 otherwise.\\n  \\n      when axis = -1:\\n      output[i, j, k, input[i, j, k]] = 1 for all i, j, k and 0 otherwise.\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"depth\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"values\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.OneHotEncoder\",\n    \"summary\": \"ONNX OneHotEncoder operation\",\n    \"description\": \"Replace each input element with an array of ones and zeros, where a single\\n      one is placed at the index of the category that was passed in. The total category count\\n      will determine the size of the extra dimension of the output array Y.<br>\\n      For example, if we pass a tensor with a single value of 4, and a category count of 8,\\n      the output will be a tensor with ``[0,0,0,0,1,0,0,0]``.<br>\\n      This operator assumes every input feature is from the same set of categories.<br>\\n      If the input is a tensor of float, int32, or double, the data will be cast\\n      to integers and the cats_int64s category list will be used for the lookups.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>, TensorOf<[I32]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cats_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"cats_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"zeros\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Optional\",\n    \"summary\": \"ONNX Optional operation\",\n    \"description\": \"Constructs an optional-type value containing either an empty optional of a certain type specified by the attribute,\\n  or a non-empty value containing the input element.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[OptOf<SeqOf<[ TensorOf < [ UI8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ StringType ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I1 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F32 > ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F64 > ] > ]>>, OptOf<TensorOf<[ UI8 ]>>, OptOf<TensorOf<[ UI16 ]>>, OptOf<TensorOf<[ UI32 ]>>, OptOf<TensorOf<[ UI64 ]>>, OptOf<TensorOf<[ I8 ]>>, OptOf<TensorOf<[ I16 ]>>, OptOf<TensorOf<[ I32 ]>>, OptOf<TensorOf<[ I64 ]>>, OptOf<TensorOf<[ F16 ]>>, OptOf<TensorOf<[ F32 ]>>, OptOf<TensorOf<[ F64 ]>>, OptOf<TensorOf<[ StringType ]>>, OptOf<TensorOf<[ I1 ]>>, OptOf<TensorOf<[ Complex < F32 > ]>>, OptOf<TensorOf<[ Complex < F64 > ]>>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"OptionalAttr<TypeAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.OptionalGetElement\",\n    \"summary\": \"ONNX OptionalGetElement operation\",\n    \"description\": \"If the input is a tensor or sequence type, it returns the input.\\n  If the input is an optional type, it outputs the element in the input.\\n  It is an error if the input is an empty optional-type (i.e. does not have an element) and the behavior is undefined in this case.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[OptOf<SeqOf<[ TensorOf < [ UI8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ StringType ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I1 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F32 > ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F64 > ] > ]>>, OptOf<TensorOf<[ UI8 ]>>, OptOf<TensorOf<[ UI16 ]>>, OptOf<TensorOf<[ UI32 ]>>, OptOf<TensorOf<[ UI64 ]>>, OptOf<TensorOf<[ I8 ]>>, OptOf<TensorOf<[ I16 ]>>, OptOf<TensorOf<[ I32 ]>>, OptOf<TensorOf<[ I64 ]>>, OptOf<TensorOf<[ F16 ]>>, OptOf<TensorOf<[ F32 ]>>, OptOf<TensorOf<[ F64 ]>>, OptOf<TensorOf<[ StringType ]>>, OptOf<TensorOf<[ I1 ]>>, OptOf<TensorOf<[ Complex < F32 > ]>>, OptOf<TensorOf<[ Complex < F64 > ]>>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.OptionalHasElement\",\n    \"summary\": \"ONNX OptionalHasElement operation\",\n    \"description\": \"Returns true if (1) the input is an optional-type and contains an element,\\n  or, (2) the input is a tensor or sequence type.\\n  If the input is not provided or is an empty optional-type, this op returns false.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[OptOf<SeqOf<[ TensorOf < [ UI8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ UI64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I8 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F16 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F32 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ F64 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ StringType ] > ]>>, OptOf<SeqOf<[ TensorOf < [ I1 ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F32 > ] > ]>>, OptOf<SeqOf<[ TensorOf < [ Complex < F64 > ] > ]>>, OptOf<TensorOf<[ UI8 ]>>, OptOf<TensorOf<[ UI16 ]>>, OptOf<TensorOf<[ UI32 ]>>, OptOf<TensorOf<[ UI64 ]>>, OptOf<TensorOf<[ I8 ]>>, OptOf<TensorOf<[ I16 ]>>, OptOf<TensorOf<[ I32 ]>>, OptOf<TensorOf<[ I64 ]>>, OptOf<TensorOf<[ F16 ]>>, OptOf<TensorOf<[ F32 ]>>, OptOf<TensorOf<[ F64 ]>>, OptOf<TensorOf<[ StringType ]>>, OptOf<TensorOf<[ I1 ]>>, OptOf<TensorOf<[ Complex < F32 > ]>>, OptOf<TensorOf<[ Complex < F64 > ]>>, TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Or\",\n    \"summary\": \"ONNX Or operation\",\n    \"description\": \"Returns the tensor resulted from performing the `or` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"B\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Pad\",\n    \"category\": \"Transform\",\n    \"summary\": \"ONNX Pad operation\",\n    \"description\": \"Given a tensor containing the data to be padded (`data`), a tensor containing the number of start and end pad values for axis (`pads`), (optionally) a `mode`, and (optionally) `constant_value`,\\n  a padded tensor (`output`) is generated.\\n  \\n  The three supported `modes` are (similar to corresponding modes supported by `numpy.pad`):\\n  \\n  1) `constant`(default) - pads with a given constant value as specified by `constant_value` (which defaults to 0, empty string, or False)\\n  \\n  2) `reflect` - pads with the reflection of the vector mirrored on the first and last values of the vector along each axis\\n  \\n  3) `edge` - pads with the edge values of array\\n  \\n  4) `wrap` - wrap-around padding as if the data tensor forms a torus\\n  \\n  \\n  Example 1 (`constant` mode):\\n  \\n  Insert 0 pads to the beginning of the second dimension.\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [0, 2, 0, 0]\\n  \\n  mode = 'constant'\\n  \\n  constant_value = 0.0\\n  \\n  output = [\\n      [0.0, 0.0, 1.0, 1.2],\\n      [0.0, 0.0, 2.3, 3.4],\\n      [0.0, 0.0, 4.5, 5.7],\\n  ]\\n  ```\\n  \\n  Example 2 (`reflect` mode):\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [0, 2, 0, 0]\\n  \\n  mode = 'reflect'\\n  \\n  output = [\\n      [1.0, 1.2, 1.0, 1.2],\\n      [2.3, 3.4, 2.3, 3.4],\\n      [4.5, 5.7, 4.5, 5.7],\\n  ]\\n  ```\\n  \\n  Example 3 (`edge` mode):\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [0, 2, 0, 0]\\n  \\n  mode = 'edge'\\n  \\n  output = [\\n      [1.0, 1.0, 1.0, 1.2],\\n      [2.3, 2.3, 2.3, 3.4],\\n      [4.5, 4.5, 4.5, 5.7],\\n  ]\\n  ```\\n  \\n  Example 4 (`wrap` mode):\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [2, 1, 1, 1]\\n  \\n  mode = 'wrap'\\n  \\n  output = [\\n      [3.4, 2.3, 3.4, 2.3],\\n      [5.7, 4.5, 5.7, 4.5],\\n      [1.2, 1.0, 1.2, 1.0],\\n      [3.4, 2.3, 3.4, 2.3],\\n      [5.7, 4.5, 5.7, 4.5],\\n      [1.2, 1.0, 1.2, 1.0],\\n  ]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" },\n      { \"name\": \"pads\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"constant_value\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>, NoneType]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, constant>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.PadV11\",\n    \"summary\": \"ONNX Pad operation\",\n    \"description\": \"Given a tensor containing the data to be padded (`data`), a tensor containing the number of start and end pad values for axis (`pads`), (optionally) a `mode`, and (optionally) `constant_value`,\\n  a padded tensor (`output`) is generated.\\n  \\n  The three supported `modes` are (similar to corresponding modes supported by `numpy.pad`):\\n  \\n  1) `constant`(default) - pads with a given constant value as specified by `constant_value` (which defaults to 0)\\n  \\n  2) `reflect` - pads with the reflection of the vector mirrored on the first and last values of the vector along each axis\\n  \\n  3) `edge` - pads with the edge values of array\\n  \\n  \\n  Example 1 (`constant` mode):\\n    Insert 0 pads to the beginning of the second dimension.\\n  \\n    data =\\n    [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n  \\n    pads = [0, 2, 0, 0]\\n  \\n    mode = 'constant'\\n  \\n    constant_value = 0.0\\n  \\n    output =\\n    [\\n        [0.0, 0.0, 1.0, 1.2],\\n        [0.0, 0.0, 2.3, 3.4],\\n        [0.0, 0.0, 4.5, 5.7],\\n    ]\\n  \\n  \\n  Example 2 (`reflect` mode):\\n    data =\\n    [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n  \\n    pads = [0, 2, 0, 0]\\n  \\n    mode = 'reflect'\\n  \\n    output =\\n    [\\n        [1.0, 1.2, 1.0, 1.2],\\n        [2.3, 3.4, 2.3, 3.4],\\n        [4.5, 5.7, 4.5, 5.7],\\n    ]\\n  \\n  \\n  Example 3 (`edge` mode):\\n    data =\\n    [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n  \\n    pads = [0, 2, 0, 0]\\n  \\n    mode = 'edge'\\n  \\n    output =\\n    [\\n        [1.0, 1.0, 1.0, 1.2],\\n        [2.3, 2.3, 2.3, 3.4],\\n        [4.5, 4.5, 4.5, 5.7],\\n    ]\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"pads\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"constant_value\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, constant>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.PadV13\",\n    \"summary\": \"ONNX Pad operation\",\n    \"description\": \"Given a tensor containing the data to be padded (`data`), a tensor containing the number of start and end pad values for axis (`pads`), (optionally) a `mode`, and (optionally) `constant_value`,\\n  a padded tensor (`output`) is generated.\\n  \\n  The three supported `modes` are (similar to corresponding modes supported by `numpy.pad`):\\n  \\n  1) `constant`(default) - pads with a given constant value as specified by `constant_value` (which defaults to 0, empty string, or False)\\n  \\n  2) `reflect` - pads with the reflection of the vector mirrored on the first and last values of the vector along each axis\\n  \\n  3) `edge` - pads with the edge values of array\\n  \\n  \\n  Example 1 (`constant` mode):\\n    Insert 0 pads to the beginning of the second dimension.\\n  \\n    data =\\n    [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n  \\n    pads = [0, 2, 0, 0]\\n  \\n    mode = 'constant'\\n  \\n    constant_value = 0.0\\n  \\n    output =\\n    [\\n        [0.0, 0.0, 1.0, 1.2],\\n        [0.0, 0.0, 2.3, 3.4],\\n        [0.0, 0.0, 4.5, 5.7],\\n    ]\\n  \\n  \\n  Example 2 (`reflect` mode):\\n    data =\\n    [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n  \\n    pads = [0, 2, 0, 0]\\n  \\n    mode = 'reflect'\\n  \\n    output =\\n    [\\n        [1.0, 1.2, 1.0, 1.2],\\n        [2.3, 3.4, 2.3, 3.4],\\n        [4.5, 5.7, 4.5, 5.7],\\n    ]\\n  \\n  \\n  Example 3 (`edge` mode):\\n    data =\\n    [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n  \\n    pads = [0, 2, 0, 0]\\n  \\n    mode = 'edge'\\n  \\n    output =\\n    [\\n        [1.0, 1.0, 1.0, 1.2],\\n        [2.3, 2.3, 2.3, 3.4],\\n        [4.5, 4.5, 4.5, 5.7],\\n    ]\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"pads\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"constant_value\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, constant>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.PadV18\",\n    \"summary\": \"ONNX Pad operation\",\n    \"description\": \"Given a tensor containing the data to be padded (`data`), a tensor containing the number of start and end pad values for axis (`pads`), (optionally) a `mode`, and (optionally) `constant_value`,\\n  a padded tensor (`output`) is generated.\\n  \\n  The three supported `modes` are (similar to corresponding modes supported by `numpy.pad`):\\n  \\n  1) `constant`(default) - pads with a given constant value as specified by `constant_value` (which defaults to 0, empty string, or False)\\n  \\n  2) `reflect` - pads with the reflection of the vector mirrored on the first and last values of the vector along each axis\\n  \\n  3) `edge` - pads with the edge values of array\\n  \\n  \\n  Example 1 (`constant` mode):\\n  \\n  Insert 0 pads to the beginning of the second dimension.\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [0, 2, 0, 0]\\n  \\n  mode = 'constant'\\n  \\n  constant_value = 0.0\\n  \\n  output = [\\n      [0.0, 0.0, 1.0, 1.2],\\n      [0.0, 0.0, 2.3, 3.4],\\n      [0.0, 0.0, 4.5, 5.7],\\n  ]\\n  ```\\n  \\n  Example 2 (`reflect` mode):\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [0, 2, 0, 0]\\n  \\n  mode = 'reflect'\\n  \\n  output = [\\n      [1.0, 1.2, 1.0, 1.2],\\n      [2.3, 3.4, 2.3, 3.4],\\n      [4.5, 5.7, 4.5, 5.7],\\n  ]\\n  ```\\n  \\n  Example 3 (`edge` mode):\\n  \\n  ```\\n  data = [\\n      [1.0, 1.2],\\n      [2.3, 3.4],\\n      [4.5, 5.7],\\n  ]\\n  \\n  pads = [0, 2, 0, 0]\\n  \\n  mode = 'edge'\\n  \\n  output = [\\n      [1.0, 1.0, 1.0, 1.2],\\n      [2.3, 2.3, 2.3, 3.4],\\n      [4.5, 4.5, 4.5, 5.7],\\n  ]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"pads\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"constant_value\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, NoneType]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, constant>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.PadV2\",\n    \"summary\": \"ONNX Pad operation\",\n    \"description\": \"Given `data` tensor, pads, mode, and value.\\n  Example:\\n    Insert 0 pads to the beginning of the second dimension.\\n    data = [\\n        [1.0, 1.2],\\n        [2.3, 3.4],\\n        [4.5, 5.7],\\n    ]\\n    pads = [0, 2, 0, 0]\\n    output = [\\n        [\\n            [0.0, 0.0, 1.0, 1.2],\\n            [0.0, 0.0, 2.3, 3.4],\\n            [0.0, 0.0, 4.5, 5.7],\\n        ],\\n    ]\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, constant>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Pow\",\n    \"summary\": \"ONNX Pow operation\",\n    \"description\": \"Pow takes input data (Tensor<T>) and exponent Tensor, and\\n  produces one output data (Tensor<T>) where the function `f(x) = x^exponent`,\\n  is applied to the data tensor elementwise.\\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Z\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.PRelu\",\n    \"summary\": \"ONNX PRelu operation\",\n    \"description\": \"PRelu takes input data (Tensor<T>) and slope tensor as input, and produces one\\n  output data (Tensor<T>) where the function `f(x) = slope * x for x < 0`,\\n  `f(x) = x for x >= 0`., is applied to the data tensor elementwise.\\n  This operator supports **unidirectional broadcasting** (tensor slope should be unidirectional broadcastable to input tensor X); for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"slope\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.PrintSignature\",\n    \"summary\": \"ONNX Op to print type signature or data of its input operands\",\n    \"description\": \"Print type signature or data of the input operands of this op.\\n    The parameter op_name specifies a string to be printed before the tensors.\\n    and usually the op_name and onnx_node_name are used.\\n    This operation is introduced early so as to preserve the name of the original ONNX op.\\n    The argument print_data control whether the data of the tensors to be printed.\\n    When print_data == 1, the data of the tensor will be printed. Otherwise, just shape.\\n    The argument input specifies the tensor to be printed. They could be a list\\n    of the inputs and outputs of an ONNX op.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, NoneType ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"print_data\", \"type\": \"SI64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.QLinearConv\",\n    \"summary\": \"ONNX QLinearConv operation\",\n    \"description\": \"The convolution operator consumes a quantized input tensor, its scale and zero point,\\n  a quantized filter, its scale and zero point, and output's scale and zero point,\\n  and computes the quantized output. Each scale and zero-point pair must have same shape.\\n  It means they must be either scalars (per tensor) or 1-D tensors (per output channel).\\n  Each input or output and its related zero point must have same type.\\n  When bias is present it must be quantized using scale = input scale * weight scale and\\n  zero point as 0.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"x_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"x_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"w\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"w_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"w_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"y_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"y_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"auto_pad\", \"type\": \"DefaultValuedStrAttr<StrAttr, NOTSET>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"pads\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"strides\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.QLinearMatMul\",\n    \"summary\": \"ONNX QLinearMatMul operation\",\n    \"description\": \"Matrix product that behaves like [numpy.matmul](https://numpy.org/doc/stable/reference/generated/numpy.matmul.html).\\n  It consumes two quantized input tensors, their scales and zero points, scale and zero point of output,\\n  and computes the quantized output. The quantization formula is y = saturate((x / y_scale) + y_zero_point).\\n  For (x / y_scale), it is rounding to nearest ties to even. Refer to https://en.wikipedia.org/wiki/Rounding for details.\\n  Scale and zero point must have same shape. They must be either scalar (per tensor) or N-D tensor\\n  (per row for 'a' and per column for 'b'). Scalar refers to per tensor quantization whereas N-D refers to per row\\n  or per column quantization. If the input is 2D of shape [M, K] then zero point and scale tensor may be\\n  an M element vector [v_1, v_2, ..., v_M] for per row quantization and K element vector of shape [v_1, v_2, ..., v_K]\\n  for per column quantization. If the input is N-D tensor with shape [D1, D2, M, K] then zero point and scale tensor may\\n  have shape [D1, D2, M, 1] for per row quantization and shape [D1, D2, 1, K] for per column quantization.\\n  Production must never overflow, and accumulation may overflow if and only if in 32 bits.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"a_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"a_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"b\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"b_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"b_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" },\n      { \"name\": \"y_scale\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"y_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.QuantizeLinear\",\n    \"summary\": \"ONNX QuantizeLinear operation\",\n    \"description\": \"The linear quantization operator. It consumes a high precision tensor, a scale, and a zero point to compute the low precision / quantized tensor.\\n  The scale factor and zero point must have same shape, and can be either a scalar for per-tensor / per layer quantization, or a 1-D tensor for per-axis quantization.\\n  The quantization formula is `y = saturate ((x / y_scale) + y_zero_point)`.\\n  For saturation, it saturates to [0, 255] if it's uint8, or [-128, 127] if it's int8.\\n  For (x / y_scale), it's rounding to the nearest even. Refer to https://en.wikipedia.org/wiki/Rounding for details.\\n  'y_zero_point' and 'y' must have same type.\\n  'y_zero_point' is usually not used for quantization to float8e4m3fn, float8e4m3fnuz, float8e5m2, float8e5m2fnuz,\\n  but the quantization formula remains the same for consistency and\\n  the type of the attribute 'y_zero_point' still determines the quantization type.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[BF16]>, TensorOf<[I32]>]>\" },\n      { \"name\": \"y_scale\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[BF16]>, TensorOf<[I32]>]>\" },\n      { \"name\": \"y_zero_point\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"AnyTypeOf<[TensorOf<[I8]>, TensorOf<[UI8]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"saturate\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RandomNormal\",\n    \"summary\": \"ONNX RandomNormal operation\",\n    \"description\": \"Generate a tensor with random values drawn from a normal distribution. The shape\\n  of the tensor is specified by the `shape` argument and the parameter of the normal distribution\\n  specified by `mean` and `scale`.\\n  \\n  The data type is specified by the 'dtype' argument. The 'dtype' argument must\\n  be one of the data types specified in the 'DataType' enum field in the\\n  TensorProto message.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"mean\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RandomNormalLike\",\n    \"summary\": \"ONNX RandomNormalLike operation\",\n    \"description\": \"Generate a tensor with random values drawn from a normal distribution.\\n  The shape of the output tensor is copied from the shape of the input tensor,\\n  and the parameters of the normal distribution are specified by `mean` and `scale`.\\n  \\n  The data type is specified by the 'dtype' argument, or copied from the input tensor if not provided.\\n  The 'dtype' argument must be one of the data types specified in the 'DataType' enum field in the\\n  TensorProto message, and be valid as an output type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"mean\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RandomUniform\",\n    \"summary\": \"ONNX RandomUniform operation\",\n    \"description\": \"Generate a tensor with random values drawn from a uniform distribution. The shape\\n  of the tensor is specified by the `shape` argument and the range by `low` and `high`.\\n  \\n  The data type is specified by the 'dtype' argument. The 'dtype' argument must\\n  be one of the data types specified in the 'DataType' enum field in the\\n  TensorProto message.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"high\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"low\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RandomUniformLike\",\n    \"summary\": \"ONNX RandomUniformLike operation\",\n    \"description\": \"Generate a tensor with random values drawn from a uniform distribution.\\n  The shape of the output tensor is copied from the shape of the input tensor,\\n  and the parameters of the uniform distribution are specified by `low` and `high`.\\n  \\n  The data type is specified by the 'dtype' argument, or copied from the input tensor if not provided.\\n  The 'dtype' argument must be one of the data types specified in the 'DataType' enum field in the\\n  TensorProto message and be valid as an output type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"high\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"low\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"seed\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Range\",\n    \"summary\": \"ONNX Range operation\",\n    \"description\": \"Generate a tensor containing a sequence of numbers that begin at `start` and extends by increments of `delta`\\n  up to `limit` (exclusive).\\n  \\n  The number of elements in the output of range is computed as below:\\n  \\n  ```\\n  number_of_elements = max( ceil( (limit - start) / delta ) , 0 )\\n  ```\\n  \\n  The pseudocode determining the contents of the output is shown below:\\n  \\n  ```\\n  for(int i=0; i<number_of_elements; ++i) {\\n    output[i] =  start + (i * delta);\\n  }\\n  ```\\n  \\n  Example 1\\n  \\n  ```\\n  Inputs: start = 3, limit = 9, delta = 3\\n  Output: [3, 6]\\n  ```\\n  \\n  Example 2\\n  \\n  ```\\n  Inputs: start = 10, limit = 4, delta = -2\\n  Output: [10, 8, 6]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"limit\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"delta\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Reciprocal\",\n    \"summary\": \"ONNX Reciprocal operation\",\n    \"description\": \"Reciprocal takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the reciprocal is, y = 1/x, is applied to\\n  the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceL1\",\n    \"summary\": \"ONNX ReduceL1 operation\",\n    \"description\": \"Computes the L1 norm of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceL1V13\",\n    \"summary\": \"ONNX ReduceL1 operation\",\n    \"description\": \"Computes the L1 norm of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceL2\",\n    \"summary\": \"ONNX ReduceL2 operation\",\n    \"description\": \"Computes the L2 norm of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceL2V13\",\n    \"summary\": \"ONNX ReduceL2 operation\",\n    \"description\": \"Computes the L2 norm of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceLogSum\",\n    \"summary\": \"ONNX ReduceLogSum operation\",\n    \"description\": \"Computes the log sum of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or undefined otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceLogSumExp\",\n    \"summary\": \"ONNX ReduceLogSumExp operation\",\n    \"description\": \"Computes the log sum exponent of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or undefined otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceLogSumExpV13\",\n    \"summary\": \"ONNX ReduceLogSumExp operation\",\n    \"description\": \"Computes the log sum exponent of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or undefined otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceLogSumV13\",\n    \"summary\": \"ONNX ReduceLogSum operation\",\n    \"description\": \"Computes the log sum of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or undefined otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMax\",\n    \"summary\": \"ONNX ReduceMax operation\",\n    \"description\": \"Computes the max of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or the minimum value of the data type otherwise.\\n  \\n  \\n  If the input data type is Boolean, the comparison should consider `False < True`.\\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>, TensorOf<[I1]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>, TensorOf<[I1]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMaxV13\",\n    \"summary\": \"ONNX ReduceMax operation\",\n    \"description\": \"Computes the max of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or the minimum value of the data type otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMaxV18\",\n    \"summary\": \"ONNX ReduceMax operation\",\n    \"description\": \"Computes the max of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or the minimum value of the data type otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMean\",\n    \"summary\": \"ONNX ReduceMean operation\",\n    \"description\": \"Computes the mean of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields undefined.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMeanV13\",\n    \"summary\": \"ONNX ReduceMean operation\",\n    \"description\": \"Computes the mean of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields undefined.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMin\",\n    \"summary\": \"ONNX ReduceMin operation\",\n    \"description\": \"Computes the min of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields plus infinity (if supported by the datatype) or the maximum value of the data type otherwise.\\n  \\n  \\n  If the input data type is Boolean, the comparison should consider `False < True`.\\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>, TensorOf<[I1]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>, TensorOf<[I1]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMinV13\",\n    \"summary\": \"ONNX ReduceMin operation\",\n    \"description\": \"Computes the min of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields plus infinity (if supported by the datatype) or the maximum value of the data type otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceMinV18\",\n    \"summary\": \"ONNX ReduceMin operation\",\n    \"description\": \"Computes the min of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields plus infinity (if supported by the datatype) or the maximum value of the data type otherwise.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, TensorOf<[UI8]>, TensorOf<[I8]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceProd\",\n    \"summary\": \"ONNX ReduceProd operation\",\n    \"description\": \"Computes the product of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 1.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceProdV13\",\n    \"summary\": \"ONNX ReduceProd operation\",\n    \"description\": \"Computes the product of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 1.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceSum\",\n    \"summary\": \"ONNX ReduceSum operation\",\n    \"description\": \"Computes the sum of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceSumSquare\",\n    \"summary\": \"ONNX ReduceSumSquare operation\",\n    \"description\": \"Computes the sum square of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"noop_with_empty_axes\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceSumSquareV13\",\n    \"summary\": \"ONNX ReduceSumSquare operation\",\n    \"description\": \"Computes the sum square of the input tensor's elements along the provided axes. The resulting\\n  tensor has the same rank as the input if `keepdims` equals 1. If `keepdims` equals 0, then\\n  the resulting tensor has the reduced dimension pruned. Input tensors of rank zero are\\n  valid. Reduction over an empty set of values yields 0.\\n  \\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults `keepdims`\\n  to `False` instead of `True`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ReduceSumV11\",\n    \"summary\": \"ONNX ReduceSum operation\",\n    \"description\": \"Computes the sum of the input tensor's element along the provided axes. The resulting\\n  tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then\\n  the resulted tensor have the reduced dimension pruned.\\n  \\n  The above behavior is similar to numpy, with the exception that numpy defaults keepdims to\\n  False instead of True.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reduced\", \"type\": \"AnyTypeOf<[TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Relu\",\n    \"category\": \"Activation\",\n    \"summary\": \"ONNX Relu operation\",\n    \"description\": \"Relu takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the rectified linear function, y = max(0, x), is applied to\\n  the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[I32]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[I32]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"ONNX Reshape operation\",\n    \"description\": \"Reshape the input tensor similar to numpy.reshape.\\n  First input is the data tensor, second input is a shape tensor which specifies the output shape. It outputs the reshaped tensor.\\n  At most one dimension of the new shape can be -1. In this case, the value is\\n  inferred from the size of the tensor and the remaining dimensions. A dimension\\n  could also be 0, in which case the actual dimension value is unchanged (i.e. taken\\n  from the input tensor). If 'allowzero' is set, and the new shape includes 0, the\\n  dimension will be set explicitly to zero (i.e. not taken from input tensor).\\n  Shape (second input) could be an empty shape, which means converting to a scalar.\\n  The input tensor's shape and the output tensor's shape are required to have the same number of elements.\\n  \\n  If the attribute 'allowzero' is set, it is invalid for the specified shape to\\n  contain both a zero value and -1, as the value of the dimension corresponding\\n  to -1 cannot be determined uniquely.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" },\n      { \"name\": \"shape\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"reshaped\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"allowzero\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Resize\",\n    \"summary\": \"ONNX Resize operation\",\n    \"description\": \"Resize the input tensor. In general, it calculates every value in the output tensor as a weighted average of neighborhood (a.k.a. sampling locations) in the input tensor.\\n  Each dimension value of the output tensor is:\\n  ```\\n  output_dimension = floor(input_dimension * (roi_end - roi_start) * scale)\\n  ```\\n  if input \\\\\\\\\\\"sizes\\\\\\\\\\\" is not specified.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"roi\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"scales\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, NoneType]>\" },\n      { \"name\": \"sizes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"antialias\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"coordinate_transformation_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, half_pixel>\" },\n      { \"name\": \"cubic_coeff_a\", \"type\": \"DefaultValuedAttr<F32Attr, -0.75>\" },\n      { \"name\": \"exclude_outside\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"extrapolation_value\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"keep_aspect_ratio_policy\", \"type\": \"DefaultValuedStrAttr<StrAttr, stretch>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" },\n      { \"name\": \"nearest_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, round_prefer_floor>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ResizeV10\",\n    \"summary\": \"ONNX Resize operation\",\n    \"description\": \"Resize the input tensor.\\n  Each dimension value of the output tensor is:\\n    output_dimension = floor(input_dimension * scale).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"scales\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ResizeV11\",\n    \"summary\": \"ONNX Resize operation\",\n    \"description\": \"Resize the input tensor. In general, it calculates every value in the output tensor as a weighted average of neighborhood (a.k.a. sampling locations) in the input tensor.\\n  Each dimension value of the output tensor is:\\n    output_dimension = floor(input_dimension * (roi_end - roi_start) * scale) if input \\\\\\\\\\\"sizes\\\\\\\\\\\" is not specified.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"roi\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"scales\", \"type\": \"TensorOf<[F32]>\" },\n      { \"name\": \"sizes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"coordinate_transformation_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, half_pixel>\" },\n      { \"name\": \"cubic_coeff_a\", \"type\": \"DefaultValuedAttr<F32Attr, -0.75>\" },\n      { \"name\": \"exclude_outside\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"extrapolation_value\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" },\n      { \"name\": \"nearest_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, round_prefer_floor>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ResizeV13\",\n    \"summary\": \"ONNX Resize operation\",\n    \"description\": \"Resize the input tensor. In general, it calculates every value in the output tensor as a weighted average of neighborhood (a.k.a. sampling locations) in the input tensor.\\n  Each dimension value of the output tensor is:\\n    output_dimension = floor(input_dimension * (roi_end - roi_start) * scale) if input \\\\\\\\\\\"sizes\\\\\\\\\\\" is not specified.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"roi\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"scales\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, NoneType]>\" },\n      { \"name\": \"sizes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"coordinate_transformation_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, half_pixel>\" },\n      { \"name\": \"cubic_coeff_a\", \"type\": \"DefaultValuedAttr<F32Attr, -0.75>\" },\n      { \"name\": \"exclude_outside\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"extrapolation_value\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" },\n      { \"name\": \"nearest_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, round_prefer_floor>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ResizeV18\",\n    \"summary\": \"ONNX Resize operation\",\n    \"description\": \"Resize the input tensor. In general, it calculates every value in the output tensor as a weighted average of neighborhood (a.k.a. sampling locations) in the input tensor.\\n  Each dimension value of the output tensor is: <br/>\\n    `output_dimension = floor(input_dimension * (roi_end - roi_start) * scale)` <br/>\\n  if input \\\\\\\\\\\"sizes\\\\\\\\\\\" is not specified.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"roi\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"scales\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, NoneType]>\" },\n      { \"name\": \"sizes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"antialias\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"coordinate_transformation_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, half_pixel>\" },\n      { \"name\": \"cubic_coeff_a\", \"type\": \"DefaultValuedAttr<F32Attr, -0.75>\" },\n      { \"name\": \"exclude_outside\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"extrapolation_value\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"keep_aspect_ratio_policy\", \"type\": \"DefaultValuedStrAttr<StrAttr, stretch>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" },\n      { \"name\": \"nearest_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, round_prefer_floor>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Return\",\n    \"summary\": \"Function return operation\",\n    \"description\": \"The `onnx.Return` operation represents a return operation within a function.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number and types must match the signature of the function\\n    that contains the operation, with the exception that shaped types may have\\n    more specific shapes than the function signature result types, which allows\\n    rewrites of defining ops of operands to make their result shapes more specific.\\n    This operation terminates a func::FuncOp in the ONNX dialect and is replaced\\n    by func::ReturnOp in StandardFuncReturnPass before lowering to Krnl or other\\n    dialects.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"onnx.ReverseSequence\",\n    \"summary\": \"ONNX ReverseSequence operation\",\n    \"description\": \"Reverse batch of sequences having different lengths specified by `sequence_lens`.\\n  \\n  For each slice i iterating on batch axis, the operator reverses the first sequence_lens[i] elements on time axis,\\n  and copies elements whose index's beyond sequence_lens[i] to the output. So the output slice i contains reversed\\n  sequences on the first sequence_lens[i] elements, then have original values copied for the other elements.\\n  \\n  Example 1:\\n    input = [[0.0, 4.0, 8.0,  12.0],\\n             [1.0, 5.0, 9.0,  13.0],\\n             [2.0, 6.0, 10.0, 14.0],\\n             [3.0, 7.0, 11.0, 15.0]]\\n    sequence_lens = [4, 3, 2, 1]\\n    time_axis = 0\\n    batch_axis = 1\\n  \\n    output = [[3.0, 6.0, 9.0,  12.0],\\n              [2.0, 5.0, 8.0,  13.0],\\n              [1.0, 4.0, 10.0, 14.0],\\n              [0.0, 7.0, 11.0, 15.0]]\\n  \\n  Example 2:\\n    input = [[0.0,  1.0,  2.0,  3.0 ],\\n             [4.0,  5.0,  6.0,  7.0 ],\\n             [8.0,  9.0,  10.0, 11.0],\\n             [12.0, 13.0, 14.0, 15.0]]\\n    sequence_lens = [1, 2, 3, 4]\\n    time_axis = 1\\n    batch_axis = 0\\n  \\n    output = [[0.0,  1.0,  2.0,  3.0 ],\\n              [5.0,  4.0,  6.0,  7.0 ],\\n              [10.0, 9.0,  8.0,  11.0],\\n              [15.0, 14.0, 13.0, 12.0]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"sequence_lens\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"time_axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RMSLayerNormalization\",\n    \"summary\": \"ONNX RMSLayerNormalization operation\",\n    \"description\": \"This is RMS layer normalization defined in ONNX as function.\\n        The overall computation can be split into two stages.\\n        The first stage is an approximate standardization, which makes the\\n        normalized elements have zero mean and unit variances.\\n        See Equation (4) in [this paper](https://arxiv.org/pdf/1910.07467.pdf).\\n        The computation required by standardization can be\\n        described by the following equations.\\n        ```\\n        DD = Mul(X, X)\\n        Var = ReduceMean<axes=normalized_axes>(DD)\\n        VarEps = Add(Var, epsilon)\\n        StdDev = Sqrt(VarEps)\\n        InvStdDev = Reciprocal(StdDev)\\n        Normalized = Mul(X, InvStdDev)\\n        ```\\n        where `normalized_axes` is `[axis, ..., rank of X - 1]`.\\n        The variables `Var` and `StdDev` stand for approximate variance and\\n        standard deviation, respectively.\\n        Depending on `stash_type` attribute, the actual computation\\n        must happen in different floating-point precision.\\n        For example, if `stash_type` is 1, this operator casts\\n        all input variables to 32-bit float, perform the computation, and\\n        finally cast `Normalized` back to the original type of `X`.\\n        The second stage then scales and shifts the outcome of the\\n        first stage using\\n        ```\\n        NormalizedScaled = Mul(Normalized, Scale)\\n        Y = Add(NormalizedScaled, B)\\n        ```\\n        The second stage doesn't depends on `stash_type`.\\n        All equations are in [this syntax](https://github.com/onnx/onnx/blob/main/docs/Syntax.md).\\n        The same variable (i.e., input, output, and attribute) uses\\n        the same name in the equations above and this operator's definition.\\n        Let `d[i]` indicate the i-th dimension of `X`.\\n        If `X`'s shape is `[d[0], ..., d[axis-1], d[axis], ..., d[rank-1]]`,\\n        the shape of `Mean` and `InvStdDev` is `[d[0], ..., d[axis-1], 1, ..., 1]`.\\n        `Y` and `X` have the same shape.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"Scale\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"InvStdDev\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"stash_type\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RNN\",\n    \"summary\": \"ONNX RNN operation\",\n    \"description\": \"Computes an one-layer simple RNN. This operator is usually supported\\n  via some custom implementation such as CuDNN.\\n  \\n  Notations:\\n  \\n  * `X` - input tensor\\n  * `i` - input gate\\n  * `t` - time step (t-1 means previous time step)\\n  * `Wi` - W parameter weight matrix for input gate\\n  * `Ri` - R recurrence weight matrix for input gate\\n  * `Wbi` - W parameter bias vector for input gate\\n  * `Rbi` - R parameter bias vector for input gate\\n  * `WBi` - W parameter weight matrix for backward input gate\\n  * `RBi` - R recurrence weight matrix for backward input gate\\n  * `WBbi` - WR bias vectors for backward input gate\\n  * `RBbi` - RR bias vectors for backward input gate\\n  * `H` - Hidden state\\n  * `num_directions` - 2 if direction == bidirectional else 1\\n  \\n  Activation functions:\\n  \\n  * Relu(x)                - max(0, x)\\n  * Tanh(x)                - (1 - e^{-2x})/(1 + e^{-2x})\\n  * Sigmoid(x)             - 1/(1 + e^{-x})\\n  \\n  NOTE: Below are optional\\n  \\n  * Affine(x)              - alpha*x + beta\\n  * LeakyRelu(x)           - x if x >= 0 else alpha * x\\n  * ThresholdedRelu(x)     - x if x >= alpha else 0\\n  * ScaledTanh(x)          - alpha*Tanh(beta*x)\\n  * HardSigmoid(x)         - min(max(alpha*x + beta, 0), 1)\\n  * Elu(x)                 - x if x >= 0 else alpha*(e^x - 1)\\n  * Softsign(x)            - x/(1 + |x|)\\n  * Softplus(x)            - log(1 + e^x)\\n  \\n  Equations (Default: f=Tanh):\\n  \\n  * Ht = f(Xt*(Wi^T) + Ht-1*(Ri^T) + Wbi + Rbi)\\n  This operator has **optional** inputs/outputs. See [the doc](IR.md) for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"W\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"R\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"sequence_lens\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, NoneType]>\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"activation_alpha\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"activation_beta\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"activations\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<StrAttr>, {\\\"Tanh\\\", \\\"Tanh\\\"}>\" },\n      { \"name\": \"clip\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"direction\", \"type\": \"DefaultValuedStrAttr<StrAttr, forward>\" },\n      { \"name\": \"hidden_size\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"layout\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.RoiAlign\",\n    \"summary\": \"ONNX RoiAlign operation\",\n    \"description\": \"Region of Interest (RoI) align operation described in the\\n  [Mask R-CNN paper](https://arxiv.org/abs/1703.06870).\\n  RoiAlign consumes an input tensor X and region of interests (rois)\\n  to apply pooling across each RoI; it produces a 4-D tensor of shape\\n  (num_rois, C, output_height, output_width).\\n  \\n  RoiAlign is proposed to avoid the misalignment by removing\\n  quantizations while converting from original image into feature\\n  map and from feature map into RoI feature; in each ROI bin,\\n  the value of the sampled locations are computed directly\\n  through bilinear interpolation.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"rois\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"batch_indices\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"coordinate_transformation_mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, half_pixel>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, avg>\" },\n      { \"name\": \"output_height\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"output_width\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"sampling_ratio\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"spatial_scale\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Round\",\n    \"summary\": \"ONNX Round operation\",\n    \"description\": \"Round takes one input Tensor and rounds the values, element-wise, meaning\\n  it finds the nearest integer for each value.\\n  In case of halves, the rule is to round them to the nearest even integer.\\n  If input x is integral, +0, -0, NaN,  or infinite, x itself is returned.\\n  The output tensor has the same shape and type as the input.\\n  \\n  Examples:\\n  ```\\n  round([0.9]) = [1.0]\\n  round([2.5]) = [2.0]\\n  round([2.3]) = [2.0]\\n  round([1.5]) = [2.0]\\n  round([-4.5]) = [-4.0]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Scaler\",\n    \"summary\": \"ONNX Scaler operation\",\n    \"description\": \"Rescale input data, for example to standardize features by removing the mean and scaling to unit variance.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Scan\",\n    \"summary\": \"ONNX Scan operation\",\n    \"description\": \"Scan can be used to iterate over one or more scan_input tensors,\\n  constructing zero or more scan_output tensors. It combines ideas from general recurrences,\\n  functional programming constructs such as scan, fold, map, and zip, and is intended to enable\\n  generalizations of RNN-like constructs for sequence-to-sequence processing.\\n  Other tensors (referred to as state_variables here) can be used to carry a state\\n  when iterating from one element to another (similar to hidden-state in RNNs, also referred\\n  to as loop-carried dependences in the context of loops).\\n  Many common usages involve a single scan_input tensor (where functionality\\n  similar to scan, fold and map can be obtained). When more than one scan_input is used,\\n  a behavior similar to zip is obtained.\\n  \\n  The attribute body must be a graph, specifying the computation to be performed in\\n  every iteration. It takes as input the current values of the state_variables and\\n  the current iterated element of the scan_inputs. It must return the (updated) values\\n  of the state_variables and zero or more scan_output_element tensors. The values of the\\n  scan_output_element tensors are concatenated over all the iterations to produce the\\n  scan_output values of the scan construct (similar to the concatenated intermediate\\n  hidden-state values of RNN-like constructs). All the output tensors (state_variables as\\n  well as scan_output_element tensors) are required to have the same shape in each iteration\\n  of the loop (a restriction imposed to enable efficient memory allocation).\\n  \\n  Note that the iterated element passed to the body subgraph does not have a sequence\\n  axis. It will have a rank one less than the rank of the corresponding scan_input.\\n  \\n  The scan operation returns the final values of the state_variables as well as the\\n  scan_outputs.\\n  \\n  The optional attribute scan_input_directions specifies the direction (forward or backward)\\n  for each scan input. If this attribute is omitted, all sequences are scanned in the forward\\n  direction. A bidirectional scan may be performed by specifying the same tensor input twice\\n  in the scan_inputs, once with a forward direction, and once with a backward direction.\\n  \\n  The scan_output of the operation is produced by concatenating the scan_output_element\\n  values produced by the body in each iteration.  The optional attribute scan_output_directions\\n  specifies the direction in which scan_output is constructed (by appending or prepending the\\n  scan_output_element to scan_output in each iteration) for each scan_output. If this attribute\\n  is omitted, the scan_output_element is appended to the scan_output in each iteration.\\n  \\n  The optional attribute scan_input_axes specifies the axis to be scanned for each scan_input.\\n  If omitted, every scan_input will be scanned in axis 0. For example, if axis 0 is the\\n  batch axis and axis 1 is the time axis (to be scanned), specify an axis value of 1.\\n  Note that scanning a non-zero axis may be less efficient than scanning axis zero.\\n  \\n  The optional attribute scan_output_axes specifies the axis along which the scan_outputs\\n  are accumulated for each scan_output. For example, if axis 1 is the time axis (to be\\n  scanned) for both inputs and outputs, specify a scan_input axis and scan_output axis\\n  value of 1.\\n  \\n  Note that because of the ONNX restriction that only the last parameter of an operator can\\n  be variadic, the initial-states and scan-inputs are listed together as one input parameter.\\n  Similarly, the final-states and scan-outputs are listed together as one output parameter.\\n  The attribute num_scan_inputs indicates the number M of scan-inputs.\\n  \\n  The behavior of\\n  \\n      Scan <\\n          num_scan_inputs = m,\\n          body = loop-body,\\n          scan_input_axes = [axis_1, ..., axis_m]\\n      > (init_1, ..., init_n, scan_1, ..., scan_m)\\n  \\n  is equivalent to the following pseudo-code:\\n  \\n      // scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i\\n      // scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.\\n      sequence_length = scan_1.shape[axis_1];\\n  \\n      // initialize state-variables\\n      st_1 = init_1; ... st_n = init_n;\\n      // initialize scan-output variables: [] denotes an empty tensor\\n      scan_out_1 = []; ...; scan_out_k = [];\\n      // identify number of iterations:\\n  \\n      // execute loop\\n      for (int t = 0; t < sequence_length; ++t) {\\n          // generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor\\n          // of rank one less than T obtained by indexing T at position t along axis k.\\n          si_1 = scan_1<axis=axis_1>[t];\\n          ... ;\\n          si_m = scan_m<axis=axis_m>[t];\\n          // execute loop-body\\n          st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)\\n          // accumulate the scan-output elements\\n          scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);\\n      }\\n  \\n      return st_1, ..., st_n, scan_out_1, ..., scan_out_k;\\n  \\n  *Sample usage: Encoding RNN using a Scan*\\n  \\n  The following example shows how a simple RNN over an input tensor %X, with weight tensor %Wi,\\n  recurrence weight tensor %Ri, bias tensors %Wbi and %Rbi, and initial hidden-state %H_0 can\\n  be encoded as a ScanLoop. Note that the loop-body is a nested graph, and it directly computes\\n  %Wi, %Ri, %Wbi, and %Rbi (typically constants or initializers in the body graph). If these\\n  values are computed in the outer graph, they need to be passed in as extra state_variables.\\n  \\n      graph rnn-encoding {\\n        %H_0 = ...\\n        %X = ...\\n        %Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)\\n        return %Y, %Y_h\\n      }\\n  \\n      graph rnn-cell-1 (\\n        %H_tminus1[FLOAT, tensor]\\n        %X_t[FLOAT, tensor]\\n      ) {\\n        %Wi = ...\\n        %Ri = ...\\n        %Wbi = ...\\n        %Rbi = ...\\n        %t1 = X_t * (Wi^T)\\n        %t2 = H_tminus1*(Ri^T)\\n        %t3 = Add(%t1, %t2)\\n        %t4 = Add(%t3, %Wbi)\\n        %t5 = Add(%t4, %Rbi)\\n        %Ht = Tanh(%t5)\\n        %Accumulate = Identity(%Ht)\\n        return %Ht, %Accumulate\\n      }\",\n    \"operands\": [\n      { \"name\": \"initial_state_and_scan_inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] >, TensorOf < [ F8E4M3FN ] >, TensorOf < [ F8E4M3FNUZ ] >, TensorOf < [ F8E5M2 ] >, TensorOf < [ F8E5M2FNUZ ] >, TensorOf < [ UI < 4 > ] >, TensorOf < [ I < 4 > ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"final_state_and_scan_outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] >, TensorOf < [ F8E4M3FN ] >, TensorOf < [ F8E4M3FNUZ ] >, TensorOf < [ F8E5M2 ] >, TensorOf < [ F8E5M2FNUZ ] >, TensorOf < [ UI < 4 > ] >, TensorOf < [ I < 4 > ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_scan_inputs\", \"type\": \"SI64Attr\" },\n      { \"name\": \"scan_input_axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"scan_input_directions\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"scan_output_axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"scan_output_directions\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Scatter\",\n    \"category\": \"Tensor\",\n    \"summary\": \"ONNX Scatter operation\",\n    \"description\": \"This operator is deprecated. Please use ScatterElements, which provides the same functionality.\\n  \\n  Scatter takes three inputs `data`, `updates`, and `indices` of the same\\n  rank r >= 1 and an optional attribute axis that identifies an axis of `data`\\n  (by default, the outer-most axis, that is axis 0). The output of the operation\\n  is produced by creating a copy of the input `data`, and then updating its value\\n  to values specified by `updates` at specific index positions specified by\\n  `indices`. Its output shape is the same as the shape of `data`.\\n  \\n  For each entry in `updates`, the target index in `data` is obtained by combining\\n  the corresponding entry in `indices` with the index of the entry itself: the\\n  index-value for dimension = axis is obtained from the value of the corresponding\\n  entry in `indices` and the index-value for dimension != axis is obtained from the\\n  index of the entry itself.\\n  \\n  For instance, in a 2-D tensor case, the update corresponding to the [i][j] entry\\n  is performed as below:\\n  ```\\n    output[indices[i][j]][j] = updates[i][j] if axis = 0,\\n    output[i][indices[i][j]] = updates[i][j] if axis = 1,\\n  ```\\n  \\n  This operator is the inverse of GatherElements. It is similar to Torch's Scatter operation.\\n  \\n  Example 1:\\n  ```\\n    data = [\\n        [0.0, 0.0, 0.0],\\n        [0.0, 0.0, 0.0],\\n        [0.0, 0.0, 0.0],\\n    ]\\n    indices = [\\n        [1, 0, 2],\\n        [0, 2, 1],\\n    ]\\n    updates = [\\n        [1.0, 1.1, 1.2],\\n        [2.0, 2.1, 2.2],\\n    ]\\n    output = [\\n        [2.0, 1.1, 0.0]\\n        [1.0, 0.0, 2.2]\\n        [0.0, 2.1, 1.2]\\n    ]\\n  ```\\n  Example 2:\\n  ```\\n    data = [[1.0, 2.0, 3.0, 4.0, 5.0]]\\n    indices = [[1, 3]]\\n    updates = [[1.1, 2.1]]\\n    axis = 1\\n    output = [[1.0, 1.1, 3.0, 2.1, 5.0]]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"updates\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ScatterElements\",\n    \"summary\": \"ONNX ScatterElements operation\",\n    \"description\": \"ScatterElements takes three inputs `data`, `updates`, and `indices` of the same\\n  rank r >= 1 and an optional attribute axis that identifies an axis of `data`\\n  (by default, the outer-most axis, that is axis 0). The output of the operation\\n  is produced by creating a copy of the input `data`, and then updating its value\\n  to values specified by `updates` at specific index positions specified by\\n  `indices`. Its output shape is the same as the shape of `data`.\\n  \\n  For each entry in `updates`, the target index in `data` is obtained by combining\\n  the corresponding entry in `indices` with the index of the entry itself: the\\n  index-value for dimension = axis is obtained from the value of the corresponding\\n  entry in `indices` and the index-value for dimension != axis is obtained from the\\n  index of the entry itself.\\n  \\n  `reduction` allows specification of an optional reduction operation, which is applied to all values in `updates`\\n  tensor into `output` at the specified `indices`.\\n  In cases where `reduction` is set to \\\\\\\"none\\\\\\\", indices should not have duplicate entries: that is, if idx1 != idx2,\\n  then indices[idx1] != indices[idx2]. For instance, in a 2-D tensor case, the update\\n  corresponding to the [i][j] entry is performed as below:\\n  ```\\n  output[indices[i][j]][j] = updates[i][j] if axis = 0,\\n  output[i][indices[i][j]] = updates[i][j] if axis = 1,\\n  ```\\n  When `reduction` is set to some reduction function `f`, the update corresponding to the [i][j] entry is performed as below:\\n  ```\\n  output[indices[i][j]][j] = f(output[indices[i][j]][j], updates[i][j]) if axis = 0,\\n  output[i][indices[i][j]] = f(output[i][indices[i][j]], updates[i][j]) if axis = 1,\\n  ```\\n  where the `f` is `+`, `*`, `max` or `min` as specified.\\n  \\n  This operator is the inverse of GatherElements. It is similar to Torch's Scatter operation.\\n  \\n  (Opset 18 change): Adds max/min to the set of allowed reduction ops.\\n  \\n  Example 1:\\n  ```\\n  data = [\\n      [0.0, 0.0, 0.0],\\n      [0.0, 0.0, 0.0],\\n      [0.0, 0.0, 0.0],\\n  ]\\n  indices = [\\n      [1, 0, 2],\\n      [0, 2, 1],\\n  ]\\n  updates = [\\n      [1.0, 1.1, 1.2],\\n      [2.0, 2.1, 2.2],\\n  ]\\n  output = [\\n      [2.0, 1.1, 0.0]\\n      [1.0, 0.0, 2.2]\\n      [0.0, 2.1, 1.2]\\n  ]\\n  ```\\n  Example 2:\\n  ```\\n  data = [[1.0, 2.0, 3.0, 4.0, 5.0]]\\n  indices = [[1, 3]]\\n  updates = [[1.1, 2.1]]\\n  axis = 1\\n  output = [[1.0, 1.1, 3.0, 2.1, 5.0]]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"updates\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedStrAttr<StrAttr, none>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ScatterND\",\n    \"summary\": \"ONNX ScatterND operation\",\n    \"description\": \"ScatterND takes three inputs `data` tensor of rank r >= 1, `indices` tensor of rank q >= 1,\\n  and `updates` tensor of rank q + r - indices.shape[-1] - 1. The output of the operation\\n  is produced by creating a copy of the input `data`, and then updating its value to values\\n  specified by `updates` at specific index positions specified by `indices`. Its output shape\\n  is the same as the shape of `data`.\\n  \\n  `indices` is an integer tensor. Let k denote indices.shape[-1], the last dimension in the shape of `indices`.\\n  `indices` is treated as a (q-1)-dimensional tensor of k-tuples, where each k-tuple is a partial-index into `data`.\\n  Hence, k can be a value at most the rank of `data`. When k equals rank(data), each update entry specifies an\\n  update to a single element of the tensor. When k is less than rank(data) each update entry specifies an\\n  update to a slice of the tensor. Index values are allowed to be negative, as per the usual\\n  convention for counting backwards from the end, but are expected in the valid range.\\n  \\n  `updates` is treated as a (q-1)-dimensional tensor of replacement-slice-values. Thus, the\\n  first (q-1) dimensions of updates.shape must match the first (q-1) dimensions of indices.shape.\\n  The remaining dimensions of `updates` correspond to the dimensions of the\\n  replacement-slice-values. Each replacement-slice-value is a (r-k) dimensional tensor,\\n  corresponding to the trailing (r-k) dimensions of `data`.  Thus, the shape of `updates`\\n  must equal indices.shape[0:q-1] ++ data.shape[k:r-1], where ++ denotes the concatenation\\n  of shapes.\\n  \\n  The `output` is calculated via the following equation:\\n  \\n  ```\\n  output = np.copy(data)\\n  update_indices = indices.shape[:-1]\\n  for idx in np.ndindex(update_indices):\\n      output[tuple(indices[idx])] = updates[idx]\\n  ```\\n  \\n  The order of iteration in the above loop is not specified.\\n  In particular, indices should not have duplicate entries: that is, if idx1 != idx2, then indices[idx1] != indices[idx2].\\n  This ensures that the output value does not depend on the iteration order.\\n  \\n  `reduction` allows specification of an optional reduction operation, which is applied to all values in `updates`\\n  tensor into `output` at the specified `indices`.\\n  In cases where `reduction` is set to \\\\\\\"none\\\\\\\", indices should not have duplicate entries: that is, if idx1 != idx2,\\n  then indices[idx1] != indices[idx2]. This ensures that the output value does not depend on the iteration order.\\n  When `reduction` is set to some reduction function `f`, `output` is calculated as follows:\\n  \\n  ```\\n  output = np.copy(data)\\n  update_indices = indices.shape[:-1]\\n  for idx in np.ndindex(update_indices):\\n      output[tuple(indices[idx])] = f(output[tuple(indices[idx])], updates[idx])\\n  ```\\n  \\n  where the `f` is `+`, `*`, `max` or `min` as specified.\\n  \\n  This operator is the inverse of GatherND.\\n  \\n  (Opset 18 change): Adds max/min to the set of allowed reduction ops.\\n  \\n  Example 1:\\n  ```\\n  data    = [1, 2, 3, 4, 5, 6, 7, 8]\\n  indices = [[4], [3], [1], [7]]\\n  updates = [9, 10, 11, 12]\\n  output  = [1, 11, 3, 10, 9, 6, 7, 12]\\n  ```\\n  \\n  Example 2:\\n  ```\\n  data    = [[[1, 2, 3, 4], [5, 6, 7, 8], [8, 7, 6, 5], [4, 3, 2, 1]],\\n              [[1, 2, 3, 4], [5, 6, 7, 8], [8, 7, 6, 5], [4, 3, 2, 1]],\\n              [[8, 7, 6, 5], [4, 3, 2, 1], [1, 2, 3, 4], [5, 6, 7, 8]],\\n              [[8, 7, 6, 5], [4, 3, 2, 1], [1, 2, 3, 4], [5, 6, 7, 8]]]\\n  indices = [[0], [2]]\\n  updates = [[[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],\\n              [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]]\\n  output  = [[[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],\\n              [[1, 2, 3, 4], [5, 6, 7, 8], [8, 7, 6, 5], [4, 3, 2, 1]],\\n              [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]],\\n              [[8, 7, 6, 5], [4, 3, 2, 1], [1, 2, 3, 4], [5, 6, 7, 8]]]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"TensorOf<[I64]>\" },\n      { \"name\": \"updates\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedStrAttr<StrAttr, none>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Selu\",\n    \"summary\": \"ONNX Selu operation\",\n    \"description\": \"Selu takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the scaled exponential linear unit function,\\n  `y = gamma * (alpha * e^x - alpha) for x <= 0`, `y = gamma * x for x > 0`,\\n  is applied to the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 1.67326>\" },\n      { \"name\": \"gamma\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0507>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceAt\",\n    \"summary\": \"ONNX SequenceAt operation\",\n    \"description\": \"Outputs a tensor copy from the tensor at 'position' in 'input_sequence'.\\n  Accepted range for 'position' is in `[-n, n - 1]`, where `n` is the number of tensors in 'input_sequence'.\\n  Negative value means counting positions from the back.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" },\n      { \"name\": \"position\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceConstruct\",\n    \"summary\": \"ONNX SequenceConstruct operation\",\n    \"description\": \"Construct a tensor sequence containing 'inputs' tensors.\\n  All tensors in 'inputs' must have the same data type.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceEmpty\",\n    \"summary\": \"ONNX SequenceEmpty operation\",\n    \"description\": \"Construct an empty tensor sequence, with given data type.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<SI64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceErase\",\n    \"summary\": \"ONNX SequenceErase operation\",\n    \"description\": \"Outputs a tensor sequence that removes the tensor at 'position' from 'input_sequence'.\\n  Accepted range for 'position' is in `[-n, n - 1]`, where `n` is the number of tensors in 'input_sequence'.\\n  Negative value means counting positions from the back.\\n  'position' is optional, by default it erases the last tensor from 'input_sequence'.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" },\n      { \"name\": \"position\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceInsert\",\n    \"summary\": \"ONNX SequenceInsert operation\",\n    \"description\": \"Outputs a tensor sequence that inserts 'tensor' into 'input_sequence' at 'position'.\\n  'tensor' must have the same data type as 'input_sequence'.\\n  Accepted range for 'position' is in `[-n, n]`, where `n` is the number of tensors in 'input_sequence'.\\n  Negative value means counting positions from the back.\\n  'position' is optional, by default it inserts 'tensor' to the back of 'input_sequence'.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" },\n      { \"name\": \"tensor\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"position\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceLength\",\n    \"summary\": \"ONNX SequenceLength operation\",\n    \"description\": \"Produces a scalar(tensor of empty shape) containing the number of tensors in 'input_sequence'.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"length\", \"type\": \"TensorOf<[I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SequenceMap\",\n    \"summary\": \"ONNX SequenceMap operation\",\n    \"description\": \"Applies a sub-graph to each sample in the input sequence(s).\\n  \\n  Inputs can be either tensors or sequences, with the exception of the first input which must\\n  be a sequence. The length of the first input sequence will determine the number of samples in the\\n  outputs. Any other sequence inputs should have the same number of samples. The number of inputs\\n  and outputs, should match the one of the subgraph.\\n  \\n  For each i-th element in the output, a sample will be extracted from the input sequence(s) at\\n  the i-th position and the sub-graph will be applied to it.\\n  The outputs will contain the outputs of the sub-graph for each sample, in the same order as in\\n  the input.\\n  \\n  This operator assumes that processing each sample is independent and could executed in parallel\\n  or in any order. Users cannot expect any specific ordering in which each subgraph is computed.\",\n    \"operands\": [\n      { \"name\": \"input_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" },\n      { \"name\": \"additional_inputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] >, SeqOf < [ TensorOf < [ UI8 ] > ] >, SeqOf < [ TensorOf < [ UI16 ] > ] >, SeqOf < [ TensorOf < [ UI32 ] > ] >, SeqOf < [ TensorOf < [ UI64 ] > ] >, SeqOf < [ TensorOf < [ I8 ] > ] >, SeqOf < [ TensorOf < [ I16 ] > ] >, SeqOf < [ TensorOf < [ I32 ] > ] >, SeqOf < [ TensorOf < [ I64 ] > ] >, SeqOf < [ TensorOf < [ F16 ] > ] >, SeqOf < [ TensorOf < [ F32 ] > ] >, SeqOf < [ TensorOf < [ F64 ] > ] >, SeqOf < [ TensorOf < [ StringType ] > ] >, SeqOf < [ TensorOf < [ I1 ] > ] >, SeqOf < [ TensorOf < [ Complex < F32 > ] > ] >, SeqOf < [ TensorOf < [ Complex < F64 > ] > ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_sequence\", \"type\": \"Variadic<AnyTypeOf<[ SeqOf < [ TensorOf < [ UI8 ] > ] >, SeqOf < [ TensorOf < [ UI16 ] > ] >, SeqOf < [ TensorOf < [ UI32 ] > ] >, SeqOf < [ TensorOf < [ UI64 ] > ] >, SeqOf < [ TensorOf < [ I8 ] > ] >, SeqOf < [ TensorOf < [ I16 ] > ] >, SeqOf < [ TensorOf < [ I32 ] > ] >, SeqOf < [ TensorOf < [ I64 ] > ] >, SeqOf < [ TensorOf < [ F16 ] > ] >, SeqOf < [ TensorOf < [ F32 ] > ] >, SeqOf < [ TensorOf < [ F64 ] > ] >, SeqOf < [ TensorOf < [ StringType ] > ] >, SeqOf < [ TensorOf < [ I1 ] > ] >, SeqOf < [ TensorOf < [ Complex < F32 > ] > ] >, SeqOf < [ TensorOf < [ Complex < F64 > ] > ] > ]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Shape\",\n    \"category\": \"Shape\",\n    \"summary\": \"ONNX Shape operation\",\n    \"description\": \"Takes a tensor as input and outputs an 1D int64 tensor containing the shape of the input tensor.\\n  Optional attributes start and end can be used to compute a slice of the input tensor's shape.\\n  If start axis is omitted, the slice starts from axis 0.\\n  The end axis, if specified, is exclusive (and the returned value will not include the size of that axis).\\n  If the end axis is omitted, the axes upto the last one will be included.\\n  Negative axes indicate counting back from the last axis.\\n  Note that axes will be clamped to the range [0, r], where r is the\\n  rank of the input tensor if they are out-of-range (after adding r in the case of\\n  negative axis). Thus, specifying any end value > r is equivalent to specifying an end\\n  value of r, and specifying any start value < -r is equivalent to specifying a start\\n  value of 0. If start > end, the result will be an empty shape.\\n  \\n  Examples:\\n  \\n  ```\\n  Input tensor with shape: [2, 3, 4]\\n  No attributes specified.\\n  Output: [2, 3, 4]\\n  ```\\n  \\n  ```\\n  Input tensor with shape: [2, 3, 4]\\n  start: -1\\n  Output: [4]\\n  ```\\n  \\n  ```\\n  Input tensor with shape: [2, 3, 4]\\n  end: -1\\n  Output: [2, 3]\\n  ```\\n  \\n  ```\\n  Input tensor with shape: [2, 3, 4]\\n  start: 1\\n  end: 2\\n  Output: [3]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"shape\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"end\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"start\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ShapeTransform\",\n    \"summary\": \"ONNX Element-wise shape transformation operation\",\n    \"description\": \"This operator transforms a tensor into another tensor whose shape is changed\\n    by a given affine map. This is elemement-wise transformation, so each element\\n    in the input will be copied to an element in the output via the affine map.\\n    The affine map must be bijective.\\n\\n    For example, the following code is using `onnx.ShapeTransform` to reshape\\n    a tensor from 2D to 4D.\\n    ```mlir\\n    #reshape = affine_map(d0, d1) -> (d0/32, d0%32, d1/64, d1%64)\\n    %Y = onnx.ShapeTransform(%arg0) {index_map = #reshape} :  (tensor<128x128xf32>) -> tensor<4x32x2x64xf32>\\n    ```\\n\\n    `onnx.ShapeTransform` will be finally materialized into an `affine.for` via\\n    lowering to `krnl` dialect, e.g.\\n    ```mlir\\n    %alloc = memref.alloc() {alignment = 16 : i64} : memref<4x32x2x64xf32>\\n    affine.for %arg1 = 0 to 128 {\\n      affine.for %arg2 = 0 to 128 {\\n        %0 = affine.load %arg0[%arg1, %arg2] : memref< 128x128xf32 >\\n        affine.store %0, %alloc[%arg1 / 32, %arg1 % 32, %arg2 / 64, %arg2 % 64] : memref<4x32x2x64xf32>\\n      }\\n    }\\n    ```\\n\\n    When being canonicalized, ShapeTransform operations are composed into\\n    a new ShapeTransform operation by composing their affine maps.\\n\\n    At this moment, this operation only supports static dimensions.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index_map\", \"type\": \"AffineMapAttr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Shrink\",\n    \"summary\": \"ONNX Shrink operation\",\n    \"description\": \"Shrink takes one input data (Tensor<numeric>) and produces one Tensor output,\\n  having same datatype and shape with input. It has two attributes, lambd and\\n  bias. The formula of this operator is: If x < -lambd, y = x + bias;\\n  If x > lambd, y = x - bias; Otherwise, y = 0.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bias\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"lambd\", \"type\": \"DefaultValuedAttr<F32Attr, 0.5>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sigmoid\",\n    \"category\": \"Activation\",\n    \"summary\": \"ONNX Sigmoid operation\",\n    \"description\": \"Sigmoid takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the sigmoid function, y = 1 / (1 + exp(-x)), is applied to the\\n  tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sign\",\n    \"summary\": \"ONNX Sign operation\",\n    \"description\": \"Calculate the sign of the given input tensor element-wise.\\n  If input > 0, output 1. if input < 0, output -1. if input == 0, output 0.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sin\",\n    \"summary\": \"ONNX Sin operation\",\n    \"description\": \"Calculates the sine of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sinh\",\n    \"summary\": \"ONNX Sinh operation\",\n    \"description\": \"Calculates the hyperbolic sine of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Size\",\n    \"category\": \"Shape\",\n    \"summary\": \"ONNX Size operation\",\n    \"description\": \"Takes a tensor as input and outputs a int64 scalar that equals to the total number of elements of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"size\", \"type\": \"TensorOf<[I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Slice\",\n    \"category\": \"Tensor\",\n    \"summary\": \"ONNX Slice operation\",\n    \"description\": \"Produces a slice of the input tensor along multiple axes. Similar to numpy:\\n  https://numpy.org/doc/stable/user/basics.indexing.html?highlight=slice#slicing-and-striding\\n  \\n  Slice uses the `starts`, `ends`, `axes` and `steps` inputs to select a sub-tensor\\n  of its input `data` tensor.\\n  \\n  An effective `starts[i]`, `ends[i]`, and `steps[i]` must be computed for each `i`\\n  in `[0, ... r-1]` where `r = rank(input)` as follows:\\n  \\n  If `axes` are omitted, they are set to `[0, ..., r-1]`.\\n  If `steps` are omitted, they are set to `[1, ..., 1]` of length `len(starts)`\\n  \\n  The effective values are initialized as `start[i] = 0`, `ends[i] = dims[i]` where\\n  `dims` are the dimensions of `input` and `steps[i] = 1`.\\n  \\n  All negative elements of `axes` are made non-negative by adding `r` to them, where\\n  `r =rank(input)`.\\n  \\n  All negative values in `starts[i]` and `ends[i]` have `dims[axes[i]]` added to them,\\n  where `dims` are the dimensions of `input`. Then `start[axes[i]]` is the adjusted\\n  `starts[i]` is clamped into the range `[0, dims[axes[i]]]` for positive stepping\\n  and `[0, dims[axes[i]]-1]` for negative stepping.\\n  \\n  The clamping for the adjusted `ends[i]` depends on the sign of `steps[i]` and must\\n  accommodate copying 0 through `dims[axes[i]]` elements, so for positive stepping\\n  `ends[axes[i]]` is clamped to `[0, dims[axes[i]]]`, while for negative stepping it\\n  is clamped to `[-1, dims[axes[i]]-1]`.\\n  \\n  Finally, `steps[axes[i]] = steps[i]`.\\n  \\n  For slicing to the end of a dimension with unknown size, it is recommended to pass\\n  in `INT_MAX` when slicing forward and 'INT_MIN' when slicing backward.\\n  \\n  Example 1:\\n  \\n  ```\\n  data = [\\n      [1, 2, 3, 4],\\n      [5, 6, 7, 8],\\n  ]\\n  axes = [0, 1]\\n  starts = [1, 0]\\n  ends = [2, 3]\\n  steps = [1, 2]\\n  result = [\\n      [5, 7],\\n  ]\\n  ```\\n  \\n  Example 2:\\n  \\n  ```\\n  data = [\\n      [1, 2, 3, 4],\\n      [5, 6, 7, 8],\\n  ]\\n  starts = [0, 1]\\n  ends = [-1, 1000]\\n  result = [\\n      [2, 3, 4],\\n  ]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"starts\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"ends\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" },\n      { \"name\": \"steps\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Softmax\",\n    \"category\": \"Activation\",\n    \"summary\": \"ONNX Softmax operation\",\n    \"description\": \"The operator computes the normalized exponential values for the given input:\\n  \\n   Softmax(input, axis) = Exp(input) / ReduceSum(Exp(input), axis=axis, keepdims=1) \\n  \\n  The \\\\\\\"axis\\\\\\\" attribute indicates the dimension along which Softmax\\n  will be performed. The output tensor has the same shape\\n  and contains the Softmax values of the corresponding input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SoftmaxCrossEntropyLoss\",\n    \"summary\": \"ONNX SoftmaxCrossEntropyLoss operation\",\n    \"description\": \"Loss function that measures the softmax cross entropy\\n  between 'scores' and 'labels'.\\n  This operator first computes a loss tensor whose shape is identical to the labels input.\\n  If the input is 2-D with shape (N, C), the loss tensor may be a N-element vector L = (l_1, l_2, ..., l_N).\\n  If the input is N-D tensor with shape (N, C, D1, D2, ..., Dk),\\n  the loss tensor L may have (N, D1, D2, ..., Dk) as its shape and L[i,][j_1][j_2]...[j_k] denotes a scalar element in L.\\n  After L is available, this operator can optionally do a reduction operator.\\n  \\n  * shape(scores): (N, C) where C is the number of classes, or (N, C, D1, D2,..., Dk),\\n    with K >= 1 in case of K-dimensional loss.\\n  * shape(labels): (N) where each value is 0 <= labels[i] <= C-1, or (N, D1, D2,..., Dk),\\n    with K >= 1 in case of K-dimensional loss.\\n  \\n  The loss for one sample, l_i, can calculated as follows:\\n  ```\\n  l[i][d1][d2]...[dk] = -y[i][c][d1][d2]..[dk], where i is the index of classes.\\n  ```\\n  or\\n  ```\\n  l[i][d1][d2]...[dk] = -y[i][c][d1][d2]..[dk] * weights[c], if 'weights' is provided.\\n  ```\\n  \\n  loss is zero for the case when label-value equals ignore_index.\\n  ```\\n  l[i][d1][d2]...[dk]  = 0, when labels[n][d1][d2]...[dk] = ignore_index\\n  ```\\n  \\n  where:\\n  ```\\n  p = Softmax(scores)\\n  y = Log(p)\\n  c = labels[i][d1][d2]...[dk]\\n  ```\\n  \\n  Finally, L is optionally reduced:\\n  \\n  * If reduction = 'none', the output is L with shape (N, D1, D2, ..., Dk).\\n  * If reduction = 'sum', the output is scalar: Sum(L).\\n  * If reduction = 'mean', the output is scalar: ReduceMean(L), or if weight is provided: `ReduceSum(L) / ReduceSum(W)`,\\n    where tensor W is of shape `(N, D1, D2, ..., Dk)` and `W[n][d1][d2]...[dk] = weights[labels[i][d1][d2]...[dk]]`.\",\n    \"operands\": [\n      { \"name\": \"scores\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"labels\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"weights\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"log_prob\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ignore_index\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedStrAttr<StrAttr, mean>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SoftmaxV11\",\n    \"summary\": \"ONNX Softmax operation\",\n    \"description\": \"The operator computes the softmax (normalized exponential) values for each layer in the batch\\n   of the given input.\\n  \\n  The input does not need to explicitly be a 2D vector; rather, it will be\\n  coerced into one. For an arbitrary n-dimensional tensor\\n  input \\\\in [a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1\\\\}\\\\] and k is\\n  the axis provided, then input will be coerced into a 2-dimensional tensor with\\n  dimensions [a_0 * ... * a_{k-1}, a_k * ... * a_{n-1\\\\}\\\\]. For the default\\n  case where axis=1, this means the input tensor will be coerced into a 2D tensor\\n  of dimensions [a_0, a_1 * ... * a_{n-1\\\\}\\\\], where a_0 is often the batch size.\\n  In this situation, we must have a_0 = N and a_1 * ... * a_{n-1} = D.\\n  Each of these dimensions must be matched correctly, or else the operator\\n  will throw errors. The output tensor has the same shape\\n  and contains the softmax values of the corresponding input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Softplus\",\n    \"summary\": \"ONNX Softplus operation\",\n    \"description\": \"Softplus takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the softplus function, y = ln(exp(x) + 1), is applied to\\n  the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Softsign\",\n    \"summary\": \"ONNX Softsign operation\",\n    \"description\": \"Calculates the softsign (x/(1+|x|)) of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SpaceToDepth\",\n    \"summary\": \"ONNX SpaceToDepth operation\",\n    \"description\": \"SpaceToDepth rearranges blocks of spatial data into depth. More specifically,\\n  this op outputs a copy of the input tensor where values from the height and width dimensions\\n  are moved to the depth dimension.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blocksize\", \"type\": \"SI64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Split\",\n    \"summary\": \"ONNX Split operation\",\n    \"description\": \"Split a tensor into a list of tensors, along the specified 'axis'.\\n  Either input 'split' or the attribute 'num_outputs' should be specified, but not both.\\n  If the attribute 'num_outputs' is specified, then the tensor is split into equal sized parts.\\n  If the tensor is not evenly splittable into `num_outputs`, the last chunk will be smaller.\\n  If the input 'split' is specified, it indicates the sizes of each output in the split.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"split\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"num_outputs\", \"type\": \"OptionalAttr<SI64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SplitToSequence\",\n    \"summary\": \"ONNX SplitToSequence operation\",\n    \"description\": \"Split a tensor into a sequence of tensors, along the specified 'axis'.\\n  Lengths of the parts can be specified using the optional argument 'split'.\\n  If the argument `split' is not specified, a default scalar value of 1\\n  is used as the value of `split'.\\n  'split' must contain only positive numbers.\\n  'split' is either a scalar (tensor of empty shape), or a 1-D tensor.\\n  If 'split' is a scalar, then 'input' will be split into chunks all of size 'split'\\n  if possible. The last chunk alone may be smaller than 'split' if the 'input' size\\n  along the given axis 'axis' is not divisible by 'split'.\\n  If 'split' is a 1-dimensional tensor, the input tensor is split into 'size(split)' chunks,\\n  with lengths of the parts on 'axis' specified in 'split'. In this scenario, the sum of entries\\n  in 'split' must be equal to the dimension size of input tensor on 'axis'.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"split\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_sequence\", \"type\": \"AnyTypeOf<[SeqOf<[TensorOf<[UI8]>]>, SeqOf<[TensorOf<[UI16]>]>, SeqOf<[TensorOf<[UI32]>]>, SeqOf<[TensorOf<[UI64]>]>, SeqOf<[TensorOf<[I8]>]>, SeqOf<[TensorOf<[I16]>]>, SeqOf<[TensorOf<[I32]>]>, SeqOf<[TensorOf<[I64]>]>, SeqOf<[TensorOf<[F16]>]>, SeqOf<[TensorOf<[F32]>]>, SeqOf<[TensorOf<[F64]>]>, SeqOf<[TensorOf<[StringType]>]>, SeqOf<[TensorOf<[I1]>]>, SeqOf<[TensorOf<[Complex<F32>]>]>, SeqOf<[TensorOf<[Complex<F64>]>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SplitV11\",\n    \"summary\": \"ONNX Split operation\",\n    \"description\": \"Split a tensor into a list of tensors, along the specified\\n  'axis'. Lengths of the parts can be specified using argument 'split'.\\n  Otherwise, the tensor is split to equal sized parts.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"split\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SplitV13\",\n    \"summary\": \"ONNX Split operation\",\n    \"description\": \"Split a tensor into a list of tensors, along the specified\\n  'axis'. Lengths of the parts can be specified using input 'split'.\\n  Otherwise, the tensor is split to equal sized parts.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"split\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ UI8 ] >, TensorOf < [ UI16 ] >, TensorOf < [ UI32 ] >, TensorOf < [ UI64 ] >, TensorOf < [ I8 ] >, TensorOf < [ I16 ] >, TensorOf < [ I32 ] >, TensorOf < [ I64 ] >, TensorOf < [ BF16 ] >, TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ StringType ] >, TensorOf < [ I1 ] >, TensorOf < [ Complex < F32 > ] >, TensorOf < [ Complex < F64 > ] > ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sqrt\",\n    \"summary\": \"ONNX Sqrt operation\",\n    \"description\": \"Square root takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the square root is, y = x^0.5, is applied to\\n  the tensor elementwise. If x is negative, then it will return NaN.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Squeeze\",\n    \"summary\": \"ONNX Squeeze operation\",\n    \"description\": \"Remove single-dimensional entries from the shape of a tensor.\\n  Takes an input `axes` with a list of axes to squeeze.\\n  If `axes` is not provided, all the single dimensions will be removed from\\n  the shape. If an axis is selected with shape entry not equal to one, an error is raised.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" },\n      { \"name\": \"axes\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"squeezed\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SqueezeV11\",\n    \"summary\": \"ONNX Squeeze operation\",\n    \"description\": \"Remove single-dimensional entries from the shape of a tensor.\\n  Takes a  parameter `axes` with a list of axes to squeeze.\\n  If `axes` is not provided, all the single dimensions will be removed from\\n  the shape. If an axis is selected with shape entry not equal to one, an error is raised.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"squeezed\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.STFT\",\n    \"summary\": \"ONNX STFT operation\",\n    \"description\": \"Computes the Short-time Fourier Transform of the signal.\",\n    \"operands\": [\n      { \"name\": \"signal\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"frame_step\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"window\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>, NoneType]>\" },\n      { \"name\": \"frame_length\", \"type\": \"AnyTypeOf<[TensorOf<[I32]>, TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F16]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"onesided\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.StringNormalizer\",\n    \"summary\": \"ONNX StringNormalizer operation\",\n    \"description\": \"StringNormalization performs string operations for basic cleaning.\\n  This operator has only one input (denoted by X) and only one output\\n  (denoted by Y). This operator first examines the elements in the X,\\n  and removes elements specified in \\\\\\\"stopwords\\\\\\\" attribute.\\n  After removing stop words, the intermediate result can be further lowercased,\\n  uppercased, or just returned depending the \\\\\\\"case_change_action\\\\\\\" attribute.\\n  This operator only accepts [C]- and [1, C]-tensor.\\n  If all elements in X are dropped, the output will be the empty value of string tensor with shape [1]\\n  if input shape is [C] and shape [1, 1] if input shape is [1, C].\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"TensorOf<[StringType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[StringType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"case_change_action\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" },\n      { \"name\": \"is_case_sensitive\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"locale\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"stopwords\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sub\",\n    \"summary\": \"ONNX Sub operation\",\n    \"description\": \"Performs element-wise binary subtraction (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\\n  \\n  (Opset 14 change): Extend supported types to include uint8, int8, uint16, and int16.\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" },\n      { \"name\": \"B\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Sum\",\n    \"summary\": \"ONNX Sum operation\",\n    \"description\": \"Element-wise sum of each of the input tensors (with Numpy-style broadcasting support).\\n  All inputs and outputs must have the same data type.\\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"data_0\", \"type\": \"Variadic<AnyTypeOf<[ TensorOf < [ F16 ] >, TensorOf < [ F32 ] >, TensorOf < [ F64 ] >, TensorOf < [ BF16 ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sum\", \"type\": \"AnyTypeOf<[TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[BF16]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SVMClassifier\",\n    \"summary\": \"ONNX SVMClassifier operation\",\n    \"description\": \"Support Vector Machine classifier\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"Z\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"classlabels_ints\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"classlabels_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"coefficients\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"kernel_params\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"kernel_type\", \"type\": \"DefaultValuedStrAttr<StrAttr, LINEAR>\" },\n      { \"name\": \"post_transform\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" },\n      { \"name\": \"prob_a\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"prob_b\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"rho\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"support_vectors\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"vectors_per_class\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.SVMRegressor\",\n    \"summary\": \"ONNX SVMRegressor operation\",\n    \"description\": \"Support Vector Machine regression prediction and one-class SVM anomaly detection.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"coefficients\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"kernel_params\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"kernel_type\", \"type\": \"DefaultValuedStrAttr<StrAttr, LINEAR>\" },\n      { \"name\": \"n_supports\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"one_class\", \"type\": \"DefaultValuedAttr<SI64Attr, 0>\" },\n      { \"name\": \"post_transform\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" },\n      { \"name\": \"rho\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"support_vectors\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Tan\",\n    \"summary\": \"ONNX Tan operation\",\n    \"description\": \"Calculates the tangent of the given input tensor, element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"ONNX Tanh operation\",\n    \"description\": \"Calculates the hyperbolic tangent of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.TfIdfVectorizer\",\n    \"summary\": \"ONNX TfIdfVectorizer operation\",\n    \"description\": \"This transform extracts n-grams from the input sequence and save them as a vector. Input can\\n  be either a 1-D or 2-D tensor. For 1-D input, output is the n-gram representation of that input.\\n  For 2-D input, the output is also a  2-D tensor whose i-th row is the n-gram representation of the i-th input row.\\n  More specifically, if input shape is [C], the corresponding output shape would be [max(ngram_indexes) + 1].\\n  If input shape is [N, C], this operator produces a [N, max(ngram_indexes) + 1]-tensor.\\n  \\n  In contrast to standard n-gram extraction, here, the indexes of extracting an n-gram from the original\\n  sequence are not necessarily consecutive numbers. The discontinuity between indexes are controlled by the number of skips.\\n  If the number of skips is 2, we should skip two tokens when scanning through the original sequence.\\n  Let's consider an example. Assume that input sequence is [94, 17, 36, 12, 28] and the number of skips is 2.\\n  The associated 2-grams are [94, 12] and [17, 28] respectively indexed by [0, 3] and [1, 4].\\n  If the number of skips becomes 0, the 2-grams generated are [94, 17], [17, 36], [36, 12], [12, 28]\\n  indexed by [0, 1], [1, 2], [2, 3], [3, 4], respectively.\\n  \\n  The output vector (denoted by Y) stores the count of each n-gram;\\n  Y[ngram_indexes[i]] indicates the times that the i-th n-gram is found. The attribute ngram_indexes is used to determine the mapping\\n  between index i and the corresponding n-gram's output coordinate. If pool_int64s is [94, 17, 17, 36], ngram_indexes is [1, 0],\\n  ngram_counts=[0, 0], then the Y[0] (first element in Y) and Y[1] (second element in Y) are the counts of [17, 36] and [94, 17],\\n  respectively. An n-gram which cannot be found in pool_strings/pool_int64s should be ignored and has no effect on the output.\\n  Note that we may consider all skips up to S when generating the n-grams.\\n  \\n  The examples used above are true if mode is \\\\\\\"TF\\\\\\\". If mode is \\\\\\\"IDF\\\\\\\", all the counts larger than 1 would be truncated to 1 and\\n  the i-th element in weights would be used to scale (by multiplication) the count of the i-th n-gram in pool. If mode is \\\\\\\"TFIDF\\\\\\\",\\n  this operator first computes the counts of all n-grams and then scale them by the associated values in the weights attribute.\\n  \\n  Only one of pool_strings and pool_int64s can be set. If pool_int64s is set, the input should be an integer tensor.\\n  If pool_strings is set, the input must be a string tensor.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I32]>, TensorOf<[I64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_gram_length\", \"type\": \"SI64Attr\" },\n      { \"name\": \"max_skip_count\", \"type\": \"SI64Attr\" },\n      { \"name\": \"min_gram_length\", \"type\": \"SI64Attr\" },\n      { \"name\": \"mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"ngram_counts\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ngram_indexes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pool_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"pool_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"weights\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.ThresholdedRelu\",\n    \"summary\": \"ONNX ThresholdedRelu operation\",\n    \"description\": \"ThresholdedRelu takes one input data (Tensor<T>) and produces one output data\\n  (Tensor<T>) where the rectified linear function, y = x for x > alpha, y = 0 otherwise,\\n  is applied to the tensor elementwise.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Tile\",\n    \"summary\": \"ONNX Tile operation\",\n    \"description\": \"Constructs a tensor by tiling a given tensor.\\n  This is the same as function `tile` in Numpy, but no broadcast.\\n  For example A = [[1, 2], [3, 4]], B = [1, 2], tile(A, B) = [[1, 2, 1, 2], [3, 4, 3, 4]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"repeats\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.TopK\",\n    \"summary\": \"ONNX TopK operation\",\n    \"description\": \"Retrieve the top-K largest or smallest elements along a specified axis. Given an input tensor of\\n  shape [a_0, a_1, ..., a_{n-1\\\\}\\\\] and integer argument k, return two outputs:\\n  \\n  * Value tensor of shape [a_0, a_1, ..., a_{axis-1}, k, a_{axis+1}, ... a_{n-1\\\\}\\\\]\\n    which contains the values of the top k elements along the specified axis\\n  * Index tensor of shape [a_0, a_1, ..., a_{axis-1}, k, a_{axis+1}, ... a_{n-1\\\\}\\\\] which\\n    contains the indices of the top k elements (original indices from the input\\n    tensor).\\n  \\n  * If \\\\\\\"largest\\\\\\\" is 1 (the default value) then the k largest elements are returned.\\n  * If \\\\\\\"sorted\\\\\\\" is 1 (the default value) then the resulting k elements will be sorted.\\n  * If \\\\\\\"sorted\\\\\\\" is 0, order of returned 'Values' and 'Indices' are undefined.\\n  \\n  Given two equivalent values, this operator uses the indices along the axis as\\n  a tiebreaker. That is, the element with the lower index will appear first.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"K\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Values\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>]>\" },\n      { \"name\": \"Indices\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI64Attr, -1>\" },\n      { \"name\": \"largest\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" },\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"ONNX Transpose operation\",\n    \"description\": \"Returns a transpose of the input tensor. (Similar to `numpy.transpose`).\\n  The optional attribute `perm` must be a permutation of the dimensions of\\n  the input tensor. Axis `i` of the output tensor corresponds to the axis\\n  `perm[i]` of the input tensor.\\n  For example, when perm=(1, 0, 2), given an input tensor of shape (1, 2, 3),\\n  the output shape will be (2, 1, 3).\\n  When perm=(1, 2, 0), given an input tensor of shape (1, 2, 3),\\n  the output shape will be (2, 3, 1).\\n  If the attribute `perm` is omitted, its default value is `(n-1, ..., 0)`,\\n  where `n` is the rank of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"transposed\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"perm\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.TreeEnsembleClassifier\",\n    \"summary\": \"ONNX TreeEnsembleClassifier operation\",\n    \"description\": \"Tree Ensemble classifier.  Returns the top class for each of N inputs.<br>\\n      The attributes named 'nodes_X' form a sequence of tuples, associated by\\n      index into the sequences, which must all be of equal length. These tuples\\n      define the nodes.<br>\\n      Similarly, all fields prefixed with 'class_' are tuples of votes at the leaves.\\n      A leaf may have multiple votes, where each vote is weighted by\\n      the associated class_weights index.<br>\\n      One and only one of classlabels_strings or classlabels_int64s\\n      will be defined. The class_ids are indices into this list.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[StringType]>, TensorOf<[I64]>]>\" },\n      { \"name\": \"Z\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"base_values\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"class_ids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"class_nodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"class_treeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"class_weights\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"classlabels_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"classlabels_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"nodes_falsenodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_featureids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_hitrates\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"nodes_missing_value_tracks_true\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_modes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"nodes_nodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_treeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_truenodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_values\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"post_transform\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.TreeEnsembleRegressor\",\n    \"summary\": \"ONNX TreeEnsembleRegressor operation\",\n    \"description\": \"Tree Ensemble regressor.  Returns the regressed values for each input in N.<br>\\n      All args with nodes_ are fields of a tuple of tree nodes, and\\n      it is assumed they are the same length, and an index i will decode the\\n      tuple across these inputs.  Each node id can appear only once\\n      for each tree id.<br>\\n      All fields prefixed with target_ are tuples of votes at the leaves.<br>\\n      A leaf may have multiple votes, where each vote is weighted by\\n      the associated target_weights index.<br>\\n      All trees must have their node ids start at 0 and increment by 1.<br>\\n      Mode enum is BRANCH_LEQ, BRANCH_LT, BRANCH_GTE, BRANCH_GT, BRANCH_EQ, BRANCH_NEQ, LEAF\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[I64]>, TensorOf<[I32]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"aggregate_function\", \"type\": \"DefaultValuedStrAttr<StrAttr, SUM>\" },\n      { \"name\": \"base_values\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"n_targets\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"nodes_falsenodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_featureids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_hitrates\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"nodes_missing_value_tracks_true\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_modes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"nodes_nodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_treeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_truenodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"nodes_values\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" },\n      { \"name\": \"post_transform\", \"type\": \"DefaultValuedStrAttr<StrAttr, NONE>\" },\n      { \"name\": \"target_ids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"target_nodeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"target_treeids\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"target_weights\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Trilu\",\n    \"summary\": \"ONNX Trilu operation\",\n    \"description\": \"Given a 2-D matrix or batches of 2-D matrices, returns the upper or lower triangular part of the tensor(s).\\n  The attribute \\\\\\\"upper\\\\\\\" determines whether the upper or lower part is retained. If set to true,\\n  the upper triangular matrix is retained. Lower triangular matrix is retained otherwise.\\n  Default value for the \\\\\\\"upper\\\\\\\" attribute is true.\\n  Trilu takes one input tensor of shape [*, N, M], where * is zero or more batch dimensions. The upper triangular part consists\\n  of the elements on and above the given diagonal (k). The lower triangular part consists of elements on and below the diagonal.\\n  All other elements in the matrix are set to zero.\\n  If k = 0, the triangular part on and above/below the main diagonal is retained.\\n  If upper is set to true, a positive k retains the upper triangular matrix excluding the main diagonal and (k-1) diagonals above it.\\n  A negative k value retains the main diagonal and |k| diagonals below it.\\n  If upper is set to false, a positive k retains the lower triangular matrix including the main diagonal and k diagonals above it.\\n  A negative k value excludes the main diagonal and (|k|-1) diagonals below it.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"k\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Unique\",\n    \"summary\": \"ONNX Unique operation\",\n    \"description\": \"Find the unique elements of a tensor. When an optional attribute 'axis' is provided, unique subtensors sliced along the 'axis' are returned.\\n  Otherwise the input tensor is flattened and unique values of the flattened tensor are returned.\\n  \\n  This operator returns the unique values or sliced unique subtensors of the input tensor and three optional outputs.\\n  The first output tensor 'Y' contains all unique values or subtensors of the input.\\n  The second optional output tensor 'indices' contains indices of 'Y' elements' first occurrence in 'X'.\\n  The third optional output tensor 'inverse_indices' contains, for elements of 'X', its corresponding indices in 'Y'.\\n  The fourth optional output tensor 'counts' contains the count of each element of 'Y' in the input.\\n  \\n  Outputs are either sorted in ascending order or optionally in the order of the first occurrence of the values in the input.\\n  \\n  https://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html\\n  \\n  Example 1:\\n  ```\\n  input_X = [2, 1, 1, 3, 4, 3]\\n  attribute_sorted = 0\\n  attribute_axis = None\\n  output_Y = [2, 1, 3, 4]\\n  output_indices = [0, 1, 3, 4]\\n  output_inverse_indices = [0, 1, 1, 2, 3, 2]\\n  output_counts = [1, 2, 2, 1]\\n  ```\\n  \\n  Example 2:\\n  ```\\n  input_X = [[1, 3], [2, 3]]\\n  attribute_sorted = 1\\n  attribute_axis = None\\n  output_Y = [1, 2, 3]\\n  output_indices = [0, 2, 1]\\n  output_inverse_indices = [0, 2, 1, 2]\\n  output_counts = [1, 1, 2]\\n  ```\\n  \\n  Example 3:\\n  ```\\n  input_X = [[1, 0, 0], [1, 0, 0], [2, 3, 4]]\\n  attribute_sorted = 1\\n  attribute_axis = 0\\n  output_Y = [[1, 0, 0], [2, 3, 4]]\\n  output_indices = [0, 2]\\n  output_inverse_indices = [0, 0, 1]\\n  output_counts = [2, 1]\\n  ```\\n  \\n  Example 4:\\n  ```\\n  input_x = [[[1., 1.], [0., 1.], [2., 1.], [0., 1.]],\\n              [[1., 1.], [0., 1.], [2., 1.], [0., 1.]]]\\n  attribute_sorted = 1\\n  attribute_axis = 1\\n  ```\\n  \\n  intermediate data are presented below for better understanding:\\n  there are 4 subtensors sliced along axis 1 of input_x (shape = (2, 4, 2)):\\n  ```\\n  A: [[1, 1], [1, 1]],\\n     [[0, 1], [0, 1]],\\n     [[2, 1], [2, 1]],\\n     [[0, 1], [0, 1]].\\n  ```\\n  \\n  there are 3 unique subtensors:\\n  ```\\n  [[1, 1], [1, 1]],\\n  [[0, 1], [0, 1]],\\n  [[2, 1], [2, 1]].\\n  ```\\n  \\n  sorted unique subtensors:\\n  ```\\n  B: [[0, 1], [0, 1]],\\n     [[1, 1], [1, 1]],\\n     [[2, 1], [2, 1]].\\n  ```\\n  \\n  output_Y is constructed from B:\\n  ```\\n  [[[0. 1.], [1. 1.], [2. 1.]],\\n   [[0. 1.], [1. 1.], [2. 1.]]]\\n  ```\\n  \\n  output_indices is to map from B to A:\\n  ```\\n  [1, 0, 2]\\n  ```\\n  \\n  output_inverse_indices is to map from A to B:\\n  ```\\n  [1, 0, 2, 0]\\n  ```\\n  \\n  output_counts:\\n  ```\\n  [2, 1, 1]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"indices\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" },\n      { \"name\": \"inverse_indices\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" },\n      { \"name\": \"counts\", \"type\": \"AnyTypeOf<[TensorOf<[I64]>, NoneType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<SI64Attr>\" },\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedAttr<SI64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Unsqueeze\",\n    \"summary\": \"ONNX Unsqueeze operation\",\n    \"description\": \"Insert single-dimensional entries to the shape of an input tensor (`data`).\\n  Takes one required input `axes` - which contains a list of dimension indices and this operator will insert a dimension of value `1` into the corresponding index of the output tensor (`expanded`).\\n  \\n  For example, given an input tensor (`data`) of shape [3, 4, 5], then\\n  Unsqueeze(data, axes=[0, 4]) outputs a tensor (`expanded`) containing same data as `data` but with shape [1, 3, 4, 5, 1].\\n  \\n  The input `axes` should not contain any duplicate entries. It is an error if it contains duplicates.\\n  The rank of the output tensor (`output_rank`) is the rank of the input tensor (`data`) plus the number of values in `axes`.\\n  Each value in `axes` should be within the (inclusive) range [-output_rank , output_rank - 1].\\n  The order of values in `axes` does not matter and can come in any order.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" },\n      { \"name\": \"axes\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"expanded\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>, TensorOf<[F8E4M3FN]>, TensorOf<[F8E4M3FNUZ]>, TensorOf<[F8E5M2]>, TensorOf<[F8E5M2FNUZ]>, TensorOf<[UI<4>]>, TensorOf<[I<4>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.UnsqueezeV11\",\n    \"summary\": \"ONNX Unsqueeze operation\",\n    \"description\": \"Insert single-dimensional entries to the shape of an input tensor (`data`).\\n  Takes one required argument `axes` - which contains a list of dimension indices and this operator will insert a dimension of value `1` into the corresponding index of the output tensor (`expanded`).\\n  \\n  For example:\\n    Given an input tensor (`data`) of shape [3, 4, 5], then\\n    Unsqueeze(data, axes=[0, 4]) outputs a tensor (`expanded`) containing same data as `data` but with shape [1, 3, 4, 5, 1].\\n  \\n  The attribute `axes` should not contain any duplicate entries. It is an error if it contains duplicates.\\n  The rank of the output tensor (`output_rank`) is the rank of the input tensor (`data`) plus the number of values in `axes`.\\n  Each value in `axes` should be within the (inclusive) range [-output_rank , output_rank - 1].\\n  The order of values in `axes` does not matter and can come in any order.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"expanded\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Upsample\",\n    \"summary\": \"ONNX Upsample operation\",\n    \"description\": \"Upsample the input tensor.\\n  Each dimension value of the output tensor is:\\n    output_dimension = floor(input_dimension * scale).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"scales\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.UpsampleV7\",\n    \"summary\": \"ONNX Upsample operation\",\n    \"description\": \"Upsample the input tensor.\\n  Each dimension value of the output tensor is:\\n    output_dimension = floor(input_dimension * scale).\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedStrAttr<StrAttr, nearest>\" },\n      { \"name\": \"scales\", \"type\": \"TypedArrayAttrBase<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Where\",\n    \"summary\": \"ONNX Where operation\",\n    \"description\": \"Return elements, either from X or Y, depending on condition.\\n  Where behaves like\\n  [numpy.where](https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html)\\n  with three parameters.\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"X\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" },\n      { \"name\": \"Y\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTypeOf<[TensorOf<[UI8]>, TensorOf<[UI16]>, TensorOf<[UI32]>, TensorOf<[UI64]>, TensorOf<[I8]>, TensorOf<[I16]>, TensorOf<[I32]>, TensorOf<[I64]>, TensorOf<[BF16]>, TensorOf<[F16]>, TensorOf<[F32]>, TensorOf<[F64]>, TensorOf<[StringType]>, TensorOf<[I1]>, TensorOf<[Complex<F32>]>, TensorOf<[Complex<F64>]>]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Xor\",\n    \"summary\": \"ONNX Xor operation\",\n    \"description\": \"Returns the tensor resulted from performing the `xor` logical operation\\n  elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).\\n  \\n  This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check [the doc](Broadcasting.md).\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"B\", \"type\": \"TensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"C\", \"type\": \"TensorOf<[I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"onnx.Yield\",\n    \"summary\": \"ONNX yield operation\",\n    \"description\": \"The `onnx.Yield` operation represents a yield operation within an ONNX subgraph.\\n    The operation takes variable number of operands and produces no results.\\n\\n    This operation is not part of the standard and was added to assist onnx-mlir.\\n    It terminates a ONNXLoop/Scan/IfOp region.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"onnx.ZipMap\",\n    \"summary\": \"ONNX ZipMap operation\",\n    \"description\": \"Creates a map from the input and the attributes.<br>\\n      The values are provided by the input tensor, while the keys are specified by the attributes.\\n      Must provide keys in either classlabels_strings or classlabels_int64s (but not both).<br>\\n      The columns of the tensor correspond one-by-one to the keys specified by the attributes. There must be as many columns as keys.<br>\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"TensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Z\", \"type\": \"AnyTypeOf<[SeqOf<[TupleOf<[StringType, F32]>]>, SeqOf<[TupleOf<[I64, F32]>]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"classlabels_int64s\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"classlabels_strings\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"pcf.alloc\",\n    \"summary\": \"Shaped ref allocation operation\",\n    \"description\": \"Allocates a `pcf.sref` with the given element type and shape. Dynamic\\n    dimensions in the result type must have corresponding dynamic size\\n    operands. The allocation scope is determined by the scope attribute of\\n    the result type.\\n\\n    Example:\\n    ```mlir\\n      %sref = pcf.alloc() : !pcf.sref<4x8xf32, #foo.scope>\\n      %sref_dyn = pcf.alloc(%d0, %d1) : !pcf.sref<?x?xf32, #foo.scope>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PCF_AnyShapedRef\" }\n    ],\n    \"assemblyFormat\": \"`(`$dynamicSizes`)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"pcf.br.cond_return\",\n    \"summary\": \"Branch operation with conditional return\",\n    \"description\": \"The `pcf.br.cond_return` operation represents a conditional branch operation\\n    to a given block, or return from the parent.\\n\\n    Example:\\n\\n    ```mlir\\n    pcf.<scoped op> #foo.scope {\\n      ^bb0(%0: !foo.type)\\n        %1 = ... %0 : !foo.type\\n        pcf.br.cond_return %cond ^bb0(%0: !foo.type)\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"dest_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$condition $dest (`(` $dest_operands^ `:` type($dest_operands) `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"pcf.generic\",\n    \"summary\": \"Execute a set of workers in parallel on a region.\",\n    \"description\": \"Executes a region across a set of workers at a specified scope. When\\n    control flow reaches this op, `nproc` workers of the specified scope are\\n    spawned and begin executing the region. The scope is given by an attribute\\n    implementing the `ScopeAttrInterface` interface and is responsible for the semantics\\n    of all pcf primitives at the same scope. Further details about scopes are\\n    included in the docs for the interface.\\n\\n    The optional `initialize` region is executed once when control flow first\\n    reaches the op. Values yielded from the initializer become block arguments\\n    available to the execute region. This is useful for setting up per-op\\n    state that persists across all worker invocations.\\n\\n    Results are produced by snapshotting the value of each result's tied sref\\n    once all workers have returned. Results can either be:\\n    1. Tied to initial values (tensor or memref) - the init value provides the\\n       initial contents and the result captures the final state.\\n    2. Allocated by the op itself - dynamic sizes must be provided for\\n       untied results with dynamic dimensions.\\n\\n    Basic example with tied results:\\n    ```mlir\\n      %0 = ... : tensor<4x8xf32>\\n      %1 = pcf.generic scope(#foo.scope)\\n        execute(%ref = %0)[%id: index, %num_workers: index]\\n             : (!pcf.sref<4x8xf32, #foo.scope>) -> (tensor<4x8xf32>) {\\n        // Each worker can read/write %ref.\\n        pcf.return\\n      }\\n    ```\\n\\n    Example with initializer:\\n    ```mlir\\n      %result = pcf.generic scope(#foo.scope)\\n        initialize {\\n          %scratch = pcf.alloc() : !pcf.sref<16xf32, #foo.scope>\\n          pcf.yield %scratch : !pcf.sref<16xf32, #foo.scope>\\n        } -> (%scratch_arg: !pcf.sref<16xf32, #foo.scope>)\\n        execute(%ref = %init)[%id: index, %num_workers: index]\\n             : (!pcf.sref<4x8xf32, #foo.scope>) -> (tensor<4x8xf32>) {\\n        // %scratch_arg is available here, initialized once.\\n        pcf.return\\n      }\\n    ```\\n\\n    Example with untied (allocated) results:\\n    ```mlir\\n      %d0, %d1 = ... : index\\n      %result = pcf.generic scope(#foo.scope)\\n        execute[%id: index, %num_workers: index]\\n             : () -> (tensor<?x?xf32>{%d0, %d1}) {\\n        // Result sref is allocated by the op, not tied to any init.\\n        pcf.return\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyRankedTensorOrMemRef>\" },\n      { \"name\": \"dynamic_sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensorOrMemRef>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"PCF_ScopeAttrInterface\" },\n      { \"name\": \"is_tied\", \"type\": \"ArrayProp<BoolProp>\" },\n      { \"name\": \"sync_on_return\", \"type\": \"DefaultValuedProp<BoolProp, false>\" },\n      { \"name\": \"num_index_args\", \"type\": \"IntProp<int64_t>\" },\n      { \"name\": \"num_leading_args\", \"type\": \"IntProp<int64_t>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initializer\", \"type\": \"MaxSizedRegion<1>\" },\n      { \"name\": \"region\", \"type\": \"MinSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`sync` $sync_on_return^)?\\n    `scope` `(` $scope `)`\\n    (`initialize` $initializer^)?\\n    custom<ParallelExecutionBody>($inits,\\n                                  type($inits),\\n                                  $dynamic_sizes,\\n                                  type($results),\\n                                  $is_tied,\\n                                  $region,\\n                                  $num_leading_args,\\n                                  \\\"true\\\")\\n    custom<InferNumIndexArgs>(ref($region), ref($num_leading_args), $num_index_args)\\n    prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"pcf.get_memref\",\n    \"summary\": \"Extract a memref view from a slice of a `pcf.sref`.\",\n    \"description\": \"The `pcf.get_memref` operation extracts a memref view from a slice of a\\n    sref, breaking the synchronization guarantees of the source.\\n\\n    The returned memref must have a maximally dynamic layout (all strides and\\n    offset dynamic) and no memory space. Layout and memory space information\\n    is determined by the ConvertSRefToMemRef analysis pass.\\n\\n    The operation supports the following arguments:\\n    * source: the sref from which to extract a view.\\n    * offsets: shaped-rank number of offsets into the `source` from which\\n               the slice begins.\\n    * sizes: shaped-rank number of sizes which specify the sizes of the result\\n             memref type.\\n    * strides: shaped-rank number of strides that specify subsampling in each\\n               dimension.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"PCF_AnyShapedRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"pcf.loop\",\n    \"summary\": \"Execute a set of workers in parallel on a region.\",\n    \"description\": \"Executes a region for each point in the iteration space defined by the\\n    `count` operands. Unlike `pcf.generic` which spawns workers equal to the\\n    native parallelism of the scope, `pcf.loop` explicitly specifies the\\n    iteration count and maps iterations to workers according to the scope's\\n    scheduling policy.\\n\\n    When control flow reaches this op, the scope determines how to distribute\\n    the iterations across available workers. The scope is given by an attribute\\n    implementing the `ScopeAttrInterface` interface. Further details about scopes are\\n    included in the docs for the interface.\\n\\n    The execute region receives one index block argument per count operand,\\n    representing the current iteration's coordinates in the iteration space.\\n\\n    Results are produced by snapshotting the value of each result's tied sref\\n    once all iterations have completed. Results can either be:\\n    1. Tied to initial values (tensor or memref) - the init value provides the\\n       initial contents and the result captures the final state.\\n    2. Allocated by the op itself - dynamic sizes must be provided for\\n       untied results with dynamic dimensions.\\n\\n    Basic example with 1D iteration:\\n    ```mlir\\n      %n = ... : index\\n      %0 = ... : tensor<4x8xf32>\\n      %1 = pcf.loop scope(#foo.scope) count(%n)\\n        execute(%ref = %0)[%id: index]\\n             : (!pcf.sref<4x8xf32, #foo.scope>) -> (tensor<4x8xf32>) {\\n        // %id ranges from 0 to %n-1.\\n        pcf.return\\n      }\\n    ```\\n\\n    Example with multi-dimensional iteration:\\n    ```mlir\\n      %m, %n = ... : index\\n      %result = pcf.loop scope(#foo.scope) count(%m, %n)\\n        execute(%ref = %init)[%i: index, %j: index]\\n             : (!pcf.sref<?x?xf32, #foo.scope>) -> (tensor<?x?xf32>) {\\n        // %i ranges from 0 to %m-1, %j ranges from 0 to %n-1.\\n        pcf.return\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"count\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyRankedTensorOrMemRef>\" },\n      { \"name\": \"dynamic_sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensorOrMemRef>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"PCF_ScopeAttrInterface\" },\n      { \"name\": \"is_tied\", \"type\": \"ArrayProp<BoolProp>\" },\n      { \"name\": \"sync_on_return\", \"type\": \"DefaultValuedProp<BoolProp, false>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`sync` $sync_on_return^)?\\n    `scope` `(` $scope `)`\\n    `count` `(` $count `)`\\n    custom<ParallelExecutionBody>($inits,\\n                                  type($inits),\\n                                  $dynamic_sizes,\\n                                  type($results),\\n                                  $is_tied,\\n                                  $region)\\n    prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"pcf.read_slice\",\n    \"summary\": \"Read a tensor or vector from a `pcf.sref` based on the provided slice\\n    parameters.\",\n    \"description\": \"Read a slice from a `pcf.sref`. If this is reading a vector, the sizes\\n    may be smaller than the return vector type. In this case out of bounds\\n    elements have undefined value.\\n\\n    The `pcf.read_slice` operation supports the following arguments:\\n    * source: the shaped value that is written.\\n    * dest: the sref into which the source is written.\\n    * offsets: shaped-rank number of offsets into the `dest` into which\\n               the slice is inserted.\\n    * sizes: shaped-rank number of sizes which specify the sizes of the source\\n             tensor type.\\n    * strides: shaped-rank number of strides that specify subsampling in each\\n               dimension.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"PCF_AnyShapedRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyRankedTensor, AnyVectorOfAnyRank]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"pcf.return\",\n    \"summary\": \"Returns from a thread.\",\n    \"description\": \"Returns control flow to the parent without fencing memory. If the parent\\n    carries an implicit fence one may still occur after the parent has finished.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"pcf.write_slice\",\n    \"summary\": \"Submit a write of a tensor, vector, or memref to a slice of a `pcf.sref`.\",\n    \"description\": \"The `pcf.write_slice` operation supports the following arguments:\\n\\n    * source: the shaped value that is written.\\n    * dest: the sref into which the source is written.\\n    * offsets: shaped-rank number of offsets into the `dest` into which\\n               the slice is inserted.\\n    * sizes: shaped-rank number of sizes which specify the sizes of the source\\n             tensor type.\\n    * strides: shaped-rank number of strides that specify subsampling in each\\n               dimension.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensorVectorOrMemRef\" },\n      { \"name\": \"dest\", \"type\": \"PCF_AnyShapedRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `into` type($dest)\"\n  },\n  {\n    \"name\": \"pcf.yield\",\n    \"summary\": \"Yields results from a region.\",\n    \"description\": \"The values returned are copied by-value.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    $operands `:` type($operands)\"\n  },\n  {\n    \"name\": \"pdl_interp.apply_constraint\",\n    \"summary\": \"Apply a constraint to a set of positional values\",\n    \"description\": \"`pdl_interp.apply_constraint` operations apply a generic constraint, that\\n    has been registered with the interpreter, with a given set of positional\\n    values.\\n    The constraint function may return any number of results.\\n    On success, this operation branches to the true destination,\\n    otherwise the false destination is taken. This behavior can be reversed\\n    by setting the attribute `isNegated` to true.\\n\\n    Example:\\n\\n    ```mlir\\n    // Apply `myConstraint` to the entities defined by `input`, `attr`, and\\n    // `op`.\\n    pdl_interp.apply_constraint \\\"myConstraint\\\"(%input, %attr, %op : !pdl.value, !pdl.attribute, !pdl.operation) -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"isNegated\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$name `(` $args `:` type($args) `)` (`:` type($results)^)? attr-dict \\n    `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.apply_rewrite\",\n    \"summary\": \"Invoke and apply an externally registered rewrite method\",\n    \"description\": \"`pdl_interp.apply_rewrite` operations invoke an external rewriter that has\\n    been registered with the interpreter to perform the rewrite after a\\n    successful match. The rewrite is passed a set of positional arguments. The\\n    rewrite function may return any number of results.\\n\\n    Example:\\n\\n    ```mlir\\n    // Rewriter operating solely on the root operation.\\n    pdl_interp.apply_rewrite \\\"rewriter\\\"(%root : !pdl.operation)\\n\\n    // Rewriter operating solely on the root operation and return an attribute.\\n    %attr = pdl_interp.apply_rewrite \\\"rewriter\\\"(%root : !pdl.operation) : !pdl.attribute\\n\\n    // Rewriter operating on the root operation along with additional arguments\\n    // from the matcher.\\n    pdl_interp.apply_rewrite \\\"rewriter\\\"(%root : !pdl.operation, %value : !pdl.value)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name (`(` $args^ `:` type($args) `)`)? (`:` type($results)^)? attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.are_equal\",\n    \"summary\": \"Check if two positional values or ranges are equivalent\",\n    \"description\": \"`pdl_interp.are_equal` operations compare two positional values for\\n    equality. On success, this operation branches to the true destination,\\n    otherwise the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.are_equal %result1, %result2 : !pdl.value -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"PDL_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"PDL_AnyType\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"operands `:` type($lhs) attr-dict `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.branch\",\n    \"summary\": \"General branch operation\",\n    \"description\": \"`pdl_interp.branch` operations expose general branch functionality to the\\n    interpreter, and are generally used to branch from one pattern match\\n    sequence to another.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.branch ^dest\\n    ```\",\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.check_attribute\",\n    \"summary\": \"Check the value of an `Attribute`\",\n    \"description\": \"`pdl_interp.check_attribute` operations compare the value of a given\\n    attribute with a constant value. On success, this operation branches to the\\n    true destination, otherwise the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.check_attribute %attr is 10 -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"attribute\", \"type\": \"PDL_Attribute\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"constantValue\", \"type\": \"AnyAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$attribute `is` $constantValue attr-dict `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.check_operand_count\",\n    \"summary\": \"Check the number of operands of an `Operation`\",\n    \"description\": \"`pdl_interp.check_operand_count` operations compare the number of operands\\n    of a given operation value with a constant. The comparison is either exact\\n    or at_least, with the latter used to compare against a minimum number of\\n    expected operands. On success, this operation branches to the true\\n    destination, otherwise the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    // Check for exact equality.\\n    pdl_interp.check_operand_count of %op is 2 -> ^matchDest, ^failureDest\\n\\n    // Check for at least N operands.\\n    pdl_interp.check_operand_count of %op is at_least 2 -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" },\n      { \"name\": \"compareAtLeast\", \"type\": \"UnitAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"`of` $inputOp `is` (`at_least` $compareAtLeast^)? $count attr-dict\\n    `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.check_operation_name\",\n    \"summary\": \"Check the OperationName of an `Operation`\",\n    \"description\": \"`pdl_interp.check_operation_name` operations compare the name of a given\\n    operation with a known name. On success, this operation branches to the true\\n    destination, otherwise the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.check_operation_name of %op is \\\"foo.op\\\" -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"`of` $inputOp `is` $name attr-dict `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.check_result_count\",\n    \"summary\": \"Check the number of results of an `Operation`\",\n    \"description\": \"`pdl_interp.check_result_count` operations compare the number of results\\n    of a given operation value with a constant. The comparison is either exact\\n    or at_least, with the latter used to compare against a minimum number of\\n    expected results. On success, this operation branches to the true\\n    destination, otherwise the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    // Check for exact equality.\\n    pdl_interp.check_result_count of %op is 2 -> ^matchDest, ^failureDest\\n\\n    // Check for at least N results.\\n    pdl_interp.check_result_count of %op is at_least 2 -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" },\n      { \"name\": \"compareAtLeast\", \"type\": \"UnitAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"`of` $inputOp `is` (`at_least` $compareAtLeast^)? $count attr-dict\\n    `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.check_type\",\n    \"summary\": \"Compare a type to a known value\",\n    \"description\": \"`pdl_interp.check_type` operations compare a type with a statically known\\n    type. On success, this operation branches to the true destination, otherwise\\n    the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.check_type %type is i32 -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$value `is` $type attr-dict `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.check_types\",\n    \"summary\": \"Compare a range of types to a range of known values\",\n    \"description\": \"`pdl_interp.check_types` operations compare a range of types with a\\n    statically known range of types. On success, this operation branches\\n    to the true destination, otherwise the false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.check_types %type are [i32, i64] -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_RangeOf<PDL_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"types\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$value `are` $types attr-dict `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.continue\",\n    \"summary\": \"Breaks the current iteration\",\n    \"description\": \"`pdl_interp.continue` operation breaks the current iteration within the\\n    `pdl_interp.foreach` region and continues with the next iteration from\\n    the beginning of the region.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.continue\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.create_attribute\",\n    \"summary\": \"Create an interpreter handle to a constant `Attribute`\",\n    \"description\": \"`pdl_interp.create_attribute` operations generate a handle within the\\n    interpreter for a specific constant attribute value.\\n\\n    Example:\\n\\n    ```mlir\\n    %attr = pdl_interp.create_attribute 10 : i64\\n    ```\",\n    \"results\": [\n      { \"name\": \"attribute\", \"type\": \"PDL_Attribute\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"pdl_interp.create_operation\",\n    \"summary\": \"Create an instance of a specific `Operation`\",\n    \"description\": \"`pdl_interp.create_operation` operations create an `Operation` instance with\\n    the specified attributes, operands, and result types. See `pdl.operation`\\n    for a more detailed description on the general interpretation of the arguments\\n    to this operation.\\n\\n    Example:\\n\\n    ```mlir\\n    // Create an instance of a `foo.op` operation.\\n    %op = pdl_interp.create_operation \\\"foo.op\\\"(%arg0 : !pdl.value) {\\\"attrA\\\" = %attr0} -> (%type : !pdl.type)\\n\\n    // Create an instance of a `foo.op` operation that has inferred result types\\n    // (using the InferTypeOpInterface).\\n    %op = pdl_interp.create_operation \\\"foo.op\\\"(%arg0 : !pdl.value) {\\\"attrA\\\" = %attr0} -> <inferred>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOperands\", \"type\": \"Variadic<PDL_InstOrRangeOf<PDL_Value>>\" },\n      { \"name\": \"inputAttributes\", \"type\": \"Variadic<PDL_Attribute>\" },\n      { \"name\": \"inputResultTypes\", \"type\": \"Variadic<PDL_InstOrRangeOf<PDL_Type>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"resultOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"inputAttributeNames\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"inferredResultTypes\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$name (`(` $inputOperands^ `:` type($inputOperands) `)`)? ``\\n    custom<CreateOperationOpAttributes>($inputAttributes, $inputAttributeNames)\\n    custom<CreateOperationOpResults>($inputResultTypes, type($inputResultTypes),\\n                                     $inferredResultTypes)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.create_range\",\n    \"summary\": \"Construct a range of PDL entities\",\n    \"description\": \"`pdl_interp.create_range` operations construct a range from a given set of PDL\\n    entities, which all share the same underlying element type. For example, a\\n    `!pdl.range<value>` may be constructed from a list of `!pdl.value`\\n    or `!pdl.range<value>` entities.\\n\\n    Example:\\n\\n    ```mlir\\n    // Construct a range of values.\\n    %valueRange = pdl_interp.create_range %inputValue, %inputRange : !pdl.value, !pdl.range<value>\\n\\n    // Construct a range of types.\\n    %typeRange = pdl_interp.create_range %inputType, %inputRange : !pdl.type, !pdl.range<type>\\n\\n    // Construct an empty range of types.\\n    %valueRange = pdl_interp.create_range : !pdl.range<type>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_RangeOf<AnyTypeOf<[ PDL_Type, PDL_Value ]>>\" }\n    ],\n    \"assemblyFormat\": \"($arguments^ `:` type($arguments))?\\n    custom<RangeType>(ref(type($arguments)), type($result))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.create_type\",\n    \"summary\": \"Create an interpreter handle to a constant `Type`\",\n    \"description\": \"`pdl_interp.create_type` operations generate a handle within the interpreter\\n    for a specific constant type value.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.create_type i64\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.create_types\",\n    \"summary\": \"Create an interpreter handle to a range of constant `Type`s\",\n    \"description\": \"`pdl_interp.create_types` operations generate a handle within the\\n    interpreter for a specific range of constant type values.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.create_types [i64, i64]\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_RangeOf<PDL_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.erase\",\n    \"summary\": \"Mark an operation as `erased`\",\n    \"description\": \"`pdl.erase` operations are used to specify that an operation should be\\n    marked as erased. The semantics of this operation correspond with the\\n    `eraseOp` method on a `PatternRewriter`.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.erase %root\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"assemblyFormat\": \"$inputOp attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.extract\",\n    \"summary\": \"Extract the item at the specified index in a range\",\n    \"description\": \"`pdl_interp.extract` operations are used to extract an item from a range\\n    at the specified index. If the index is out of range, returns null.\\n\\n    Example:\\n\\n    ```mlir\\n    // Extract the value at index 1 from a range of values.\\n    %ops = pdl_interp.extract 1 of %values : !pdl.value\\n    ```\",\n    \"operands\": [\n      { \"name\": \"range\", \"type\": \"PDL_RangeOf<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'range', 'pdl::RangeType::get($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$index `of` $range `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.finalize\",\n    \"summary\": \"Finalize a pattern match or rewrite sequence\",\n    \"description\": \"`pdl_interp.finalize` is used to denote the termination of a match or\\n    rewrite sequence.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.finalize\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.foreach\",\n    \"summary\": \"Iterates over a range of values or ranges\",\n    \"description\": \"`pdl_interp.foreach` iteratively selects an element from a range of values\\n    and executes the region until pdl.continue is reached.\\n\\n    In the bytecode interpreter, this operation is implemented by looping over\\n    the values and, for each selection, running the bytecode until we reach\\n    pdl.continue. This may result in multiple matches being reported. Note\\n    that the input range is mutated (popped from).\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.foreach %op : !pdl.operation in %ops {\\n      pdl_interp.continue\\n    } -> ^next\\n    ```\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"PDL_RangeOf<PDL_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"successor\", \"type\": \"AnySuccessor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pdl_interp.func\",\n    \"summary\": \"PDL Interpreter Function Operation\",\n    \"description\": \"`pdl_interp.func` operations act as interpreter functions. These are\\n    callable SSA-region operations that contain other interpreter operations.\\n    Interpreter functions are used for both the matching and the rewriting\\n    portion of the interpreter.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.func @rewriter(%root: !pdl.operation) {\\n      %op = pdl_interp.create_operation \\\"foo.new_operation\\\"\\n      pdl_interp.erase %root\\n      pdl_interp.finalize\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"MinSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pdl_interp.get_attribute\",\n    \"summary\": \"Get a specified attribute value from an `Operation`\",\n    \"description\": \"`pdl_interp.get_attribute` operations try to get a specific attribute from\\n    an operation. If the operation does not have that attribute, a null value is\\n    returned.\\n\\n    Example:\\n\\n    ```mlir\\n    %attr = pdl_interp.get_attribute \\\"attr\\\" of %op\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"attribute\", \"type\": \"PDL_Attribute\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name `of` $inputOp attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_attribute_type\",\n    \"summary\": \"Get the result type of a specified `Attribute`\",\n    \"description\": \"`pdl_interp.get_attribute_type` operations get the resulting type of a\\n    specific attribute.\\n\\n    Example:\\n\\n    ```mlir\\n    %type = pdl_interp.get_attribute_type of %attr\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_Attribute\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_Type\" }\n    ],\n    \"assemblyFormat\": \"`of` $value attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_defining_op\",\n    \"summary\": \"Get the defining operation of a `Value`\",\n    \"description\": \"`pdl_interp.get_defining_op` operations try to get the defining operation\\n    of a specific value or range of values. In the case of range, the defining\\n    op of the first value is returned. If the value is not an operation result\\n    or range of operand results, null is returned.\\n\\n    Example:\\n\\n    ```mlir\\n    %op = pdl_interp.get_defining_op of %value : !pdl.value\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_InstOrRangeOf<PDL_Value>\" }\n    ],\n    \"results\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"assemblyFormat\": \"`of` $value `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_operand\",\n    \"summary\": \"Get a specified operand from an `Operation`\",\n    \"description\": \"`pdl_interp.get_operand` operations try to get a specific operand from an\\n    operation If the operation does not have an operand for the given index, a\\n    null value is returned.\\n\\n    Example:\\n\\n    ```mlir\\n    %operand = pdl_interp.get_operand 1 of %op\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"PDL_Value\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$index `of` $inputOp attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_operands\",\n    \"summary\": \"Get a specified operand group from an `Operation`\",\n    \"description\": \"`pdl_interp.get_operands` operations try to get a specific operand\\n    group from an operation. If the expected result is a single Value, null is\\n    returned if the operand group is not of size 1. If a range is expected,\\n    null is returned if the operand group is invalid. If no index is provided,\\n    the returned operand group corresponds to all operands of the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    // Get the first group of operands from an operation, and expect a single\\n    // element.\\n    %operand = pdl_interp.get_operands 0 of %op : !pdl.value\\n\\n    // Get the first group of operands from an operation.\\n    %operands = pdl_interp.get_operands 0 of %op : !pdl.range<value>\\n\\n    // Get all of the operands from an operation.\\n    %operands = pdl_interp.get_operands of %op : !pdl.range<value>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"PDL_InstOrRangeOf<PDL_Value>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"OptionalAttr<ConfinedAttr<I32Attr, [ IntNonNegative ]>>\" }\n    ],\n    \"assemblyFormat\": \"($index^)? `of` $inputOp `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_result\",\n    \"summary\": \"Get a specified result from an `Operation`\",\n    \"description\": \"`pdl_interp.get_result` operations try to get a specific result from an\\n    operation. If the operation does not have a result for the given index, a\\n    null value is returned.\\n\\n    Example:\\n\\n    ```mlir\\n    %result = pdl_interp.get_result 1 of %op\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"PDL_Value\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$index `of` $inputOp attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_results\",\n    \"summary\": \"Get a specified result group from an `Operation`\",\n    \"description\": \"`pdl_interp.get_results` operations try to get a specific result group\\n    from an operation. If the expected result is a single Value, null is\\n    returned if the result group is not of size 1. If a range is expected,\\n    null is returned if the result group is invalid. If no index is provided,\\n    the returned operand group corresponds to all results of the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    // Get the first group of results from an operation, and expect a single\\n    // element.\\n    %result = pdl_interp.get_results 0 of %op : !pdl.value\\n\\n    // Get the first group of results from an operation.\\n    %results = pdl_interp.get_results 0 of %op : !pdl.range<value>\\n\\n    // Get all of the results from an operation.\\n    %results = pdl_interp.get_results of %op : !pdl.range<value>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"PDL_InstOrRangeOf<PDL_Value>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"OptionalAttr<ConfinedAttr<I32Attr, [ IntNonNegative ]>>\" }\n    ],\n    \"assemblyFormat\": \"($index^)? `of` $inputOp `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_users\",\n    \"summary\": \"Get the users of a `Value`\",\n    \"description\": \"`pdl_interp.get_users` extracts the users that accept this value. In the\\n    case of a range, the union of users of the all the values are returned,\\n    similarly to ResultRange::getUsers.\\n\\n    Example:\\n\\n    ```mlir\\n    // Get all the users of a single value.\\n    %ops = pdl_interp.get_users of %value : !pdl.value\\n\\n    // Get all the users of the first value in a range.\\n    %ops = pdl_interp.get_users of %values : !pdl.range<value>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_InstOrRangeOf<PDL_Value>\" }\n    ],\n    \"results\": [\n      { \"name\": \"operations\", \"type\": \"PDL_RangeOf<PDL_Operation>\" }\n    ],\n    \"assemblyFormat\": \"`of` $value `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.get_value_type\",\n    \"summary\": \"Get the result type of a specified `Value`\",\n    \"description\": \"`pdl_interp.get_value_type` operations get the resulting type of a specific\\n    value or range thereof.\\n\\n    Example:\\n\\n    ```mlir\\n    // Get the type of a single value.\\n    %type = pdl_interp.get_value_type of %value : !pdl.type\\n\\n    // Get the types of a value range.\\n    %type = pdl_interp.get_value_type of %values : !pdl.range<type>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_InstOrRangeOf<PDL_Value>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_InstOrRangeOf<PDL_Type>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'value', 'getGetValueTypeOpValueType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"`of` $value `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.is_not_null\",\n    \"summary\": \"Check if a positional value is non-null\",\n    \"description\": \"`pdl_interp.is_not_null` operations check that a positional value or range\\n    exists. For ranges, this does not mean that the range was simply empty. On\\n    success, this operation branches to the true destination. Otherwise, the\\n    false destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.is_not_null %value : !pdl.value -> ^matchDest, ^failureDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_AnyType\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$value `:` type($value) attr-dict `->` successors\"\n  },\n  {\n    \"name\": \"pdl_interp.record_match\",\n    \"summary\": \"Record the metadata for a successful pattern match\",\n    \"description\": \"`pdl_interp.record_match` operations record a successful pattern match with\\n    the interpreter and branch to the next part of the matcher. The metadata\\n    recorded by these operations correspond to a specific `pdl.pattern`, as well\\n    as what values were used during that match that should be propagated to the\\n    rewriter.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.record_match @rewriters::myRewriter(%root : !pdl.operation) : benefit(1), loc([%root, %op1]), root(\\\"foo.op\\\") -> ^nextDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<PDL_AnyType>\" },\n      { \"name\": \"matchedOps\", \"type\": \"Variadic<PDL_Operation>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rewriter\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"rootKind\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"generatedOps\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"benefit\", \"type\": \"ConfinedAttr<I16Attr, [IntNonNegative]>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$rewriter (`(` $inputs^ `:` type($inputs) `)`)? `:`\\n    `benefit` `(` $benefit `)` `,`\\n    (`generatedOps` `(` $generatedOps^ `)` `,`)?\\n    `loc` `(` `[` $matchedOps `]` `)`\\n    (`,` `root` `(` $rootKind^ `)`)? attr-dict `->` $dest\"\n  },\n  {\n    \"name\": \"pdl_interp.replace\",\n    \"summary\": \"Mark an operation as `replace`d\",\n    \"description\": \"`pdl_interp.replaced` operations are used to specify that an operation\\n    should be marked as replaced. The semantics of this operation correspond\\n    with the `replaceOp` method on a `PatternRewriter`. The set of replacement\\n    values must match the number of results specified by the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    // Replace root node with 2 values:\\n    pdl_interp.replace %root with (%val0, %val1 : !pdl.type, !pdl.type)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" },\n      { \"name\": \"replValues\", \"type\": \"Variadic<PDL_InstOrRangeOf<PDL_Value>>\" }\n    ],\n    \"assemblyFormat\": \"$inputOp `with` ` ` `(` ($replValues^ `:` type($replValues))? `)`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"pdl_interp.switch_attribute\",\n    \"summary\": \"Switch on the value of an `Attribute`\",\n    \"description\": \"`pdl_interp.switch_attribute` operations compare the value of a given\\n    attribute with a set of constant attributes. If the value matches one of the\\n    provided case values the destination for that case value is taken, otherwise\\n    the default destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.switch_attribute %attr to [10, true](^10Dest, ^trueDest) -> ^defaultDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"attribute\", \"type\": \"PDL_Attribute\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"caseValues\", \"type\": \"ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cases\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"$attribute `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest\"\n  },\n  {\n    \"name\": \"pdl_interp.switch_operand_count\",\n    \"summary\": \"Switch on the operand count of an `Operation`\",\n    \"description\": \"`pdl_interp.switch_operand_count` operations compare the operand count of a\\n    given operation with a set of potential counts. If the value matches one of\\n    the provided case values the destination for that case value is taken,\\n    otherwise the default destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.switch_operand_count of %op to [10, 2] -> ^10Dest, ^2Dest, ^defaultDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"caseValues\", \"type\": \"I32ElementsAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cases\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"`of` $inputOp `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest\"\n  },\n  {\n    \"name\": \"pdl_interp.switch_operation_name\",\n    \"summary\": \"Switch on the OperationName of an `Operation`\",\n    \"description\": \"`pdl_interp.switch_operation_name` operations compare the name of a given\\n    operation with a set of known names. If the value matches one of the\\n    provided case values the destination for that case value is taken, otherwise\\n    the default destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.switch_operation_name of %op to [\\\"foo.op\\\", \\\"bar.op\\\"](^fooDest, ^barDest) -> ^defaultDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"caseValues\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cases\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"`of` $inputOp `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest\"\n  },\n  {\n    \"name\": \"pdl_interp.switch_result_count\",\n    \"summary\": \"Switch on the result count of an `Operation`\",\n    \"description\": \"`pdl_interp.switch_result_count` operations compare the result count of a\\n    given operation with a set of potential counts. If the value matches one of\\n    the provided case values the destination for that case value is taken,\\n    otherwise the default destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.switch_result_count of %op to [0, 2](^0Dest, ^2Dest) -> ^defaultDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputOp\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"caseValues\", \"type\": \"I32ElementsAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cases\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"`of` $inputOp `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest\"\n  },\n  {\n    \"name\": \"pdl_interp.switch_type\",\n    \"summary\": \"Switch on a `Type` value\",\n    \"description\": \"`pdl_interp.switch_type` operations compare a type with a set of statically\\n    known types. If the value matches one of the provided case values the\\n    destination for that case value is taken, otherwise the default destination\\n    is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.switch_type %type to [i32, i64] -> ^i32Dest, ^i64Dest, ^defaultDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"caseValues\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cases\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"$value `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest\"\n  },\n  {\n    \"name\": \"pdl_interp.switch_types\",\n    \"summary\": \"Switch on a range of `Type` values\",\n    \"description\": \"`pdl_interp.switch_types` operations compare a range of types with a set of\\n    statically known ranges. If the value matches one of the provided case\\n    values the destination for that case value is taken, otherwise the default\\n    destination is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl_interp.switch_types %type is [[i32], [i64, i64]] -> ^i32Dest, ^i64Dest, ^defaultDest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"PDL_RangeOf<PDL_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"caseValues\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<TypeAttr>, type-array array attribute>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"cases\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"$value `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest\"\n  },\n  {\n    \"name\": \"pdl.apply_native_constraint\",\n    \"summary\": \"Apply a native constraint to a set of provided entities\",\n    \"description\": \"`pdl.apply_native_constraint` operations apply a native C++ constraint, that\\n    has been registered externally with the consumer of PDL, to a given set of\\n    entities and optionally return a number of values.\\n\\n    Example:\\n\\n    ```mlir\\n    // Apply `myConstraint` to the entities defined by `input`, `attr`, and `op`.\\n    pdl.apply_native_constraint \\\"myConstraint\\\"(%input, %attr, %op : !pdl.value, !pdl.attribute, !pdl.operation)\\n    // Apply constraint `with_result` to `root`. This constraint returns an attribute.\\n    %attr = pdl.apply_native_constraint \\\"with_result\\\"(%root : !pdl.operation) : !pdl.attribute\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"isNegated\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$name `(` $args `:` type($args) `)` (`:`  type($results)^ )? attr-dict\"\n  },\n  {\n    \"name\": \"pdl.apply_native_rewrite\",\n    \"summary\": \"Apply a native rewrite method inside of pdl.rewrite region\",\n    \"description\": \"`pdl.apply_native_rewrite` operations apply a native C++ function, that has\\n    been registered externally with the consumer of PDL, to perform a rewrite\\n    and optionally return a number of values. The native function may accept any\\n    number of arguments. This operation is used within a pdl.rewrite region to enable\\n    the interleaving of native rewrite methods with other pdl constructs.\\n\\n    Example:\\n\\n    ```mlir\\n    // Apply a native rewrite method that returns an attribute.\\n    %ret = pdl.apply_native_rewrite \\\"myNativeFunc\\\"(%arg0, %attr1) : !pdl.attribute\\n    ```\\n\\n    ```c++\\n    // The native rewrite as defined in C++:\\n    static Attribute myNativeFunc(PatternRewriter &rewriter, Value arg0, Attribute arg1) {\\n      // Just return the second arg.\\n      return arg1;\\n    }\\n\\n    void registerNativeRewrite(PDLPatternModule &pdlModule) {\\n      pdlModule.registerRewriteFunction(\\\"myNativeFunc\\\", myNativeFunc);\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name (`(` $args^ `:` type($args) `)`)? (`:` type($results)^)? attr-dict\"\n  },\n  {\n    \"name\": \"pdl.attribute\",\n    \"summary\": \"Define an input attribute in a pattern\",\n    \"description\": \"`pdl.attribute` operations capture named attribute edges into an operation.\\n    Instances of this operation define, and partially constrain, attributes of a\\n    given operation. A `pdl.attribute` may partially constrain the input by\\n    specifying an expected attribute value type (via a `pdl.type` operation), or\\n    a constant value for the attribute (via `val`). Only one of these may be set\\n    for a given input, as the type of the constant value provides the type. When\\n    defined within a `pdl.rewrite` region, the constant value must be specified.\\n\\n    Example:\\n\\n    ```mlir\\n    // Define an attribute:\\n    %attr = pdl.attribute\\n\\n    // Define an attribute with an expected type:\\n    %type = pdl.type : i32\\n    %attr = pdl.attribute : %type\\n\\n    // Define an attribute with a constant value:\\n    %attr = pdl.attribute = \\\"hello\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueType\", \"type\": \"Optional<PDL_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"attr\", \"type\": \"PDL_Attribute\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`:` $valueType^)? (`=` $value^)? attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"pdl.erase\",\n    \"summary\": \"Mark an input operation as `erased`\",\n    \"description\": \"`pdl.erase` operations are used within `pdl.rewrite` regions to specify that\\n    an input operation should be marked as erased. The semantics of this\\n    operation correspond with the `eraseOp` method on a `PatternRewriter`.\\n\\n    Example:\\n\\n    ```mlir\\n    pdl.erase %root\\n    ```\",\n    \"operands\": [\n      { \"name\": \"opValue\", \"type\": \"PDL_Operation\" }\n    ],\n    \"assemblyFormat\": \"$opValue attr-dict\"\n  },\n  {\n    \"name\": \"pdl.operand\",\n    \"summary\": \"Define an external input operand in a pattern\",\n    \"description\": \"`pdl.operand` operations capture external operand edges into an operation\\n    node that originate from operations or block arguments not otherwise\\n    specified within the pattern (i.e. via `pdl.result` or `pdl.results`). These\\n    operations define individual operands of a given operation. A `pdl.operand`\\n    may partially constrain an operand by specifying an expected value type\\n    (via a `pdl.type` operation).\\n\\n    Example:\\n\\n    ```mlir\\n    // Define an external operand:\\n    %operand = pdl.operand\\n\\n    // Define an external operand with an expected type:\\n    %type = pdl.type : i32\\n    %operand = pdl.operand : %type\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueType\", \"type\": \"Optional<PDL_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"PDL_Value\" }\n    ],\n    \"assemblyFormat\": \"(`:` $valueType^)? attr-dict\"\n  },\n  {\n    \"name\": \"pdl.operands\",\n    \"summary\": \"Define a range of input operands in a pattern\",\n    \"description\": \"`pdl.operands` operations capture external operand range edges into an\\n    operation node that originate from operations or block arguments not\\n    otherwise specified within the pattern (i.e. via `pdl.result` or\\n    `pdl.results`). These operations define groups of input operands into a\\n    given operation. A `pdl.operands` may partially constrain a set of input\\n    operands by specifying expected value types (via `pdl.types` operations).\\n\\n    Example:\\n\\n    ```mlir\\n    // Define a range of input operands:\\n    %operands = pdl.operands\\n\\n    // Define a range of input operands with expected types:\\n    %types = pdl.types : [i32, i64, i32]\\n    %typed_operands = pdl.operands : %types\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueType\", \"type\": \"Optional<PDL_RangeOf<PDL_Type>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"PDL_RangeOf<PDL_Value>\" }\n    ],\n    \"assemblyFormat\": \"(`:` $valueType^)? attr-dict\"\n  },\n  {\n    \"name\": \"pdl.operation\",\n    \"summary\": \"Define an operation within a pattern\",\n    \"description\": \"`pdl.operation` operations define operation nodes within a pattern. Within\\n    a match sequence, i.e. when directly nested within a `pdl.pattern`, these\\n    operations correspond to input operations, or those that already existing\\n    within the MLIR module. Inside of a `pdl.rewrite`, these operations\\n    correspond to operations that should be created as part of the replacement\\n    sequence.\\n\\n    `pdl.operation`s are composed of a name, and a set of attribute, operand,\\n    and result type values, that map to what those that would be on a\\n    constructed instance of that operation. The results of a `pdl.operation` are\\n    a handle to the operation itself. Handles to the results of the operation\\n    can be extracted via `pdl.result`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Define an instance of a `foo.op` operation.\\n    %op = pdl.operation \\\"foo.op\\\"(%arg0, %arg1 : !pdl.value, !pdl.value)\\n      {\\\"attrA\\\" = %attr0} -> (%type, %type : !pdl.type, !pdl.type)\\n    ```\\n\\n    When used within a matching context, the name of the operation may be\\n    omitted.\\n\\n    When used within a rewriting context, i.e. when defined within a\\n    `pdl.rewrite`, all of the result types must be \\\"inferable\\\". This means that\\n    the type must be attributable to either a constant type value or the result\\n    type of another entity, such as an attribute, the result of a\\n    `apply_native_rewrite`, or the result type of another operation. If the\\n    result type value does not meet any of these criteria, the operation must\\n    override the `InferTypeOpInterface` to ensure that the result types can be\\n    inferred.\\n\\n    The operands of the operation are interpreted in the following ways:\\n\\n    1) A single !pdl.range<value>:\\n\\n    In this case, the single range is treated as all of the operands of the\\n    operation.\\n\\n    ```mlir\\n    // Define an instance with single range of operands.\\n    %op = pdl.operation \\\"func.return\\\"(%allArgs : !pdl.range<value>)\\n    ```\\n\\n    2) A variadic number of either !pdl.value or !pdl.range<value>:\\n\\n    In this case, the inputs are expected to correspond with the operand groups\\n    defined on the operation in ODS.\\n\\n    ```tablgen\\n    // Given the following operation definition in ODS:\\n    def MyIndirectCallOp {\\n      let results = (outs FunctionType:$call, Variadic<AnyType>:$args);\\n    }\\n    ```\\n\\n    ```mlir\\n    // We can match the operands as so:\\n    %op = pdl.operation \\\"my.indirect_call\\\"(%call, %args : !pdl.value, !pdl.range<value>)\\n    ```\\n\\n    The results of the operation are interpreted in the following ways:\\n\\n    1) A single !pdl.range<type>:\\n\\n    In this case, the single range is treated as all of the result types of the\\n    operation.\\n\\n    ```mlir\\n    // Define an instance with single range of types.\\n    %allResultTypes = pdl.types\\n    %op = pdl.operation \\\"builtin.unrealized_conversion_cast\\\" -> (%allResultTypes : !pdl.types)\\n    ```\\n\\n    2) A variadic number of either !pdl.type or !pdl.range<type>:\\n\\n    In this case, the inputs are expected to correspond with the result groups\\n    defined on the operation in ODS.\\n\\n    ```tablgen\\n    // Given the following operation definition in ODS:\\n    def MyOp {\\n      let results = (outs SomeType:$result, Variadic<SomeType>:$otherResults);\\n    }\\n    ```\\n\\n    ```mlir\\n    // We can match the results as so:\\n    %result = pdl.type\\n    %otherResults = pdl.types\\n    %op = pdl.operation \\\"foo.op\\\" -> (%result, %otherResults : !pdl.type, !pdl.range<type>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operandValues\", \"type\": \"Variadic<PDL_InstOrRangeOf<PDL_Value>>\" },\n      { \"name\": \"attributeValues\", \"type\": \"Variadic<PDL_Attribute>\" },\n      { \"name\": \"typeValues\", \"type\": \"Variadic<PDL_InstOrRangeOf<PDL_Type>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"op\", \"type\": \"PDL_Operation\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"opName\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"attributeValueNames\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"($opName^)? (`(` $operandValues^ `:` type($operandValues) `)`)?\\n    custom<OperationOpAttributes>($attributeValues, $attributeValueNames)\\n    (`->` `(` $typeValues^ `:` type($typeValues) `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"pdl.pattern\",\n    \"summary\": \"Define a rewrite pattern\",\n    \"description\": \"`pdl.pattern` operations provide a transformable representation for a\\n    `RewritePattern`. The attributes on this operation correspond to the various\\n    metadata on a `RewritePattern`, such as the benefit. The match section of\\n    the pattern is specified within the region body, with the rewrite provided\\n    by a terminating `pdl.rewrite`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Provide a pattern matching \\\"foo.op\\\" that replaces the root with its\\n    // operand.\\n    pdl.pattern : benefit(1) {\\n      %resultType = pdl.type\\n      %inputOperand = pdl.operand\\n      %root = pdl.operation \\\"foo.op\\\"(%inputOperand) -> (%resultType)\\n      pdl.rewrite %root {\\n        pdl.replace %root with (%inputOperand)\\n      }\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"benefit\", \"type\": \"ConfinedAttr<I16Attr, [IntNonNegative]>\" },\n      { \"name\": \"sym_name\", \"type\": \"OptionalAttr<SymbolNameAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"pdl\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"($sym_name^)? `:` `benefit` `(` $benefit `)` attr-dict-with-keyword $bodyRegion\"\n  },\n  {\n    \"name\": \"pdl.range\",\n    \"summary\": \"Construct a range of pdl entities\",\n    \"description\": \"`pdl.range` operations construct a range from a given set of PDL entities,\\n    which all share the same underlying element type. For example, a\\n    `!pdl.range<value>` may be constructed from a list of `!pdl.value`\\n    or `!pdl.range<value>` entities.\\n\\n    Example:\\n\\n    ```mlir\\n    // Construct a range of values.\\n    %valueRange = pdl.range %inputValue, %inputRange : !pdl.value, !pdl.range<value>\\n\\n    // Construct a range of types.\\n    %typeRange = pdl.range %inputType, %inputRange : !pdl.type, !pdl.range<type>\\n\\n    // Construct an empty range of types.\\n    %valueRange = pdl.range : !pdl.range<type>\\n    ```\\n\\n    TODO: Range construction is currently limited to rewrites, but it could\\n    be extended to constraints under certain circustances; i.e., if we can\\n    determine how to extract the underlying elements. If we can't, e.g. if\\n    there are multiple sub ranges used for construction, we won't be able\\n    to determine their sizes during constraint time.\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_RangeOf<AnyTypeOf<[ PDL_Type, PDL_Value ]>>\" }\n    ],\n    \"assemblyFormat\": \"($arguments^ `:` type($arguments))?\\n    custom<RangeType>(ref(type($arguments)), type($result))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"pdl.replace\",\n    \"summary\": \"Mark an input operation as `replaced`\",\n    \"description\": \"`pdl.replace` operations are used within `pdl.rewrite` regions to specify\\n    that an input operation should be marked as replaced. The semantics of this\\n    operation correspond with the `replaceOp` method on a `PatternRewriter`. The\\n    set of replacement values can be either:\\n    * a single `Operation` (`replOperation` should be populated)\\n      - The operation will be replaced with the results of this operation.\\n    * a set of `Value`s (`replValues` should be populated)\\n      - The operation will be replaced with these values.\\n\\n    Example:\\n\\n    ```mlir\\n    // Replace root node with 2 values:\\n    pdl.replace %root with (%val0, %val1 : !pdl.value, !pdl.value)\\n\\n    // Replace root node with a range of values:\\n    pdl.replace %root with (%vals : !pdl.range<value>)\\n\\n    // Replace root with another operation:\\n    pdl.replace %root with %otherOp\\n    ```\",\n    \"operands\": [\n      { \"name\": \"opValue\", \"type\": \"PDL_Operation\" },\n      { \"name\": \"replOperation\", \"type\": \"Optional<PDL_Operation>\" },\n      { \"name\": \"replValues\", \"type\": \"Variadic<PDL_InstOrRangeOf<PDL_Value>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$opValue `with` (`(` $replValues^ `:` type($replValues) `)`)?\\n    ($replOperation^)? attr-dict\"\n  },\n  {\n    \"name\": \"pdl.result\",\n    \"summary\": \"Extract a result from an operation\",\n    \"description\": \"`pdl.result` operations extract result edges from an operation node within\\n    a pattern or rewrite region. The provided index is zero-based, and\\n    represents the concrete result to extract, i.e. this is not the result index\\n    as defined by the ODS definition of the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    // Extract a result:\\n    %operation = pdl.operation ...\\n    %pdl_result = pdl.result 1 of %operation\\n\\n    // Imagine the following IR being matched:\\n    %result_0, %result_1 = foo.op ...\\n\\n    // If the example pattern snippet above were matching against `foo.op` in\\n    // the IR snippet, `%pdl_result` would correspond to `%result_1`.\\n    ```\",\n    \"operands\": [\n      { \"name\": \"parent\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"val\", \"type\": \"PDL_Value\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$index `of` $parent attr-dict\"\n  },\n  {\n    \"name\": \"pdl.results\",\n    \"summary\": \"Extract a result group from an operation\",\n    \"description\": \"`pdl.results` operations extract a result group from an operation within a\\n    pattern or rewrite region. If an index is provided, this operation extracts\\n    a result group as defined by the ODS definition of the operation. In this\\n    case the result of this operation may be either a single `pdl.value` or\\n    a `pdl.range<value>`, depending on the constraint of the result in ODS. If\\n    no index is provided, this operation extracts the full result range of the\\n    operation.\\n\\n    Example:\\n\\n    ```mlir\\n    // Extract all of the results of an operation:\\n    %operation = pdl.operation ...\\n    %results = pdl.results of %operation\\n\\n    // Extract the results in the first result group of an operation, which is\\n    // variadic:\\n    %operation = pdl.operation ...\\n    %results = pdl.results 0 of %operation -> !pdl.range<value>\\n\\n    // Extract the results in the second result group of an operation, which is\\n    // not variadic:\\n    %operation = pdl.operation ...\\n    %results = pdl.results 1 of %operation -> !pdl.value\\n    ```\",\n    \"operands\": [\n      { \"name\": \"parent\", \"type\": \"PDL_Operation\" }\n    ],\n    \"results\": [\n      { \"name\": \"val\", \"type\": \"PDL_InstOrRangeOf<PDL_Value>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"($index^)? `of` $parent custom<ResultsValueType>(ref($index), type($val))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"pdl.rewrite\",\n    \"summary\": \"Specify the rewrite of a matched pattern\",\n    \"description\": \"`pdl.rewrite` operations terminate the region of a `pdl.pattern` and specify\\n    the main rewrite of a `pdl.pattern`, on the optional root operation. The\\n    rewrite is specified either via a string name (`name`) to a native\\n    rewrite function, or via the region body. The rewrite region, if specified,\\n    must contain a single block. If the rewrite is external it functions\\n    similarly to `pdl.apply_native_rewrite`, and takes a set of additional\\n    positional values defined within the matcher as arguments. If the rewrite is\\n    external, the root operation is passed to the native function as the leading\\n    arguments. The root operation, if provided, specifies the starting point in\\n    the pattern for the subgraph isomorphism search. Pattern matching will proceed\\n    from this node downward (towards the defining operation) or upward\\n    (towards the users) until all the operations in the pattern have been matched.\\n    If the root is omitted, the pdl_interp lowering will automatically select\\n    the best root of the pdl.rewrite among all the operations in the pattern.\\n\\n    Example:\\n\\n    ```mlir\\n    // Specify an external rewrite function:\\n    pdl.rewrite %root with \\\"myExternalRewriter\\\"(%value : !pdl.value)\\n\\n    // Specify a rewrite inline using PDL with the given root:\\n    pdl.rewrite %root {\\n      %op = pdl.operation \\\"foo.op\\\"(%arg0, %arg1)\\n      pdl.replace %root with %op\\n    }\\n\\n    // Specify a rewrite inline using PDL, automatically selecting root:\\n    pdl.rewrite {\\n      %op1 = pdl.operation \\\"foo.op\\\"(%arg0, %arg1)\\n      %op2 = pdl.operation \\\"bar.op\\\"(%arg0, %arg1)\\n      pdl.replace %root1 with %op1\\n      pdl.replace %root2 with %op2\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"Optional<PDL_Operation>\" },\n      { \"name\": \"externalArgs\", \"type\": \"Variadic<PDL_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"pdl\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"($root^)? (`with` $name^ (`(` $externalArgs^ `:` type($externalArgs) `)`)?)?\\n              ($bodyRegion^)?\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"pdl.type\",\n    \"summary\": \"Define a type handle within a pattern\",\n    \"description\": \"`pdl.type` operations capture result type constraints of `Attributes`,\\n    `Values`, and `Operations`. Instances of this operation define, and\\n    partially constrain, results types of a given entity. A `pdl.type` may\\n    partially constrain the result by specifying a constant `Type`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Define a type:\\n    %type = pdl.type\\n\\n    // Define a type with a constant value:\\n    %type = pdl.type : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"constantType\", \"type\": \"OptionalAttr<TypeAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`:` $constantType^)?\"\n  },\n  {\n    \"name\": \"pdl.types\",\n    \"summary\": \"Define a range of type handles within a pattern\",\n    \"description\": \"`pdl.types` operations capture result type constraints of `Value`s, and\\n    `Operation`s. Instances of this operation define results types of a given\\n    entity. A `pdl.types` may partially constrain the results by specifying\\n    an array of `Type`s.\\n\\n    Example:\\n\\n    ```mlir\\n    // Define a range of types:\\n    %types = pdl.types\\n\\n    // Define a range of types with a range of constant values:\\n    %types = pdl.types : [i32, i64, i32]\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PDL_RangeOf<PDL_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"constantTypes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`:` $constantTypes^)?\"\n  },\n  {\n    \"name\": \"plan.alloc_cluster\",\n    \"description\": \"The `plan.alloc_cluster` operation is a variant of the\\n  `plan.dps_cluster` operation that does not use destination-passing style\\n  (DPS). It is isolated from above and explicitly captures input operands, but unlike\\n  its DPS counterpart, it does not capture destination operands because its results must\\n  be lowered to allocation(s). The allocations may or may not be of a size that can only\\n  be computed inside of the region.\\n  This operation takes input operands and their corresponding bounds attributes,\\n  and produces results. The `input_attrs` hold bounds attribute information for\\n  the input operands. The absence of bounds information is allowed (`none` bounds).\\n\\n  The `target` attribute specifies the execution target for the group.\\n\\n  #### Example\\n\\n  Consider the following simple program containing operations with dynamically shaped operands:\\n\\n  ```mlir\\n  %0 = ... : tensor<?xf32> // A dynamically shaped operand\\n  %1 = ... : index         // A dynamic calculation of %0's extent\\n\\n  %2 = plan.alloc_cluster target(#plan.cluster_target<tensorrt>)\\n    inputs(%0, %1 : tensor<?xf32>, index)\\n    in_attrs [#plan.bounds<shape, [10], [20]>, #plan.bounds<none>]-> tensor<?xf32> {\\n    %3 = plan.with_shape %0 (%1) : (tensor<?xf32>, index) -> tensor<?xf32>\\n    %4 = stablehlo.exponential %3 : tensor<?xf32>\\n    yield %4 : tensor<?xf32>\\n  }\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_attrs\", \"type\": \"TypedArrayAttrBase<Plan_BoundsAttr>\" },\n      { \"name\": \"target\", \"type\": \"OptionalAttr<CompilerBackendAttrInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"plan\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"(`target` `(` $target^ `)` `\\\\n`)?\\n    `inputs` `(` ( $inputs^ `:` type($inputs) `)` ) : ( `)` ) ?  `\\\\n`\\n    `in_attrs` $input_attrs `\\\\n`\\n     attr-dict-with-keyword `->` type($results)\\n     $body\"\n  },\n  {\n    \"name\": \"plan.cluster\",\n    \"description\": \"The `plan.cluster` operation encapsulates a group of operations within\\n    its single-block region. The purpose of this operation is materialize\\n    in the IR the result of a clustering analysis.\\n\\n    Each `plan.cluster` operation must be assigned a `target` attribute\\n    that indicates how the cluster should be compiled / what \\\"backend\\\" will\\n    be targeted. Examples of \\\"backends\\\" could include entire sub-compiler\\n    stacks like TensorRT or an external library like CUBlas or CUDNN.\\n\\n    The `plan.cluster` operation is meant to be gradually lowered into a\\n    more specialized operation(s) and/or have the body outlined to a\\n    function-like operation such that the reuslts are replaced with a\\n    call-like operation.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"OptionalAttr<CompilerBackendAttrInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"plan\",\n    \"assemblyFormat\": \"( `target` `(` $target^ `)` )?\\n     attr-dict-with-keyword (`->` type($results)^)? $body\"\n  },\n  {\n    \"name\": \"plan.constraint\",\n    \"summary\": \"Used for applying constraints to its memref operand using attributes.\",\n    \"description\": \"This op is used to apply constraints to its memref operand using the\\n   attributes associated for dimension analysis passes.\",\n    \"operands\": [\n      { \"name\": \"memrefToConstrain\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"`(` $memrefToConstrain `)` attr-dict  `:` type($memrefToConstrain)\"\n  },\n  {\n    \"name\": \"plan.dps_cluster\",\n    \"description\": \"The `plan.dps_cluster` operation is similar to `plan.cluster`\\n    except that it is isolated from above and explicitly captures destination\\n    operands. The `in_attrs` and `res_attrs` hold bounds attribute information\\n    for the input and result operands. The abcense of bounds information\\n    is allowed (`none` bounds).\\n\\n    #### Example\\n\\n    Consider the following simple program containing operations with\\n    dynamically shaped operands:\\n\\n    ```mlir\\n\\n    %0 = ... : tensor<?xf32> // A dynamically shaped operand\\n    %1 = .... : index        // A dynamic calculation of %0's extent\\n\\n    %2 = plan.cluster target(#plan.cluster_target<tensorrt>) {\\n      %2 = plan.with_shape %0 (%1) : (tensor<?xf32>, index) -> tensor<?xf32>\\n      %3 = stablehlo.exponential %2 : tensor<?xf32>\\n      yield %3 : tensor<?xf32>\\n    }\\n\\n    ```\\n\\n    It can be transformed into the below IR which explicitly captures all\\n    operands, operand shape bounds, and the allocation of a destination tensor\\n    based on the upper bound of the yielded values:\\n\\n\\n    ```mlir\\n\\n    // Destination operand calculated from the upper bound of the\\n    // output.\\n    %empty = tensor.empty() : tensor<128xf32>\\n\\n    //Slice %empty to actual linear size.\\n    %out = tensor.extract_slice %empty[0][%ub][1] :  tensor<128xf32> to tensor<?xf32>\\n\\n    %2 = plan.dps_cluster target(#plan.cluster_target<tensorrt>)\\n      inputs( %0, %1 : tensor<?xf32>, index)\\n      outs( %out : tensor<?xf32> )\\n      in_attrs [#plan.bounds<shape, [10], [20]>, #plan.bounds<none>]\\n      res_attrs [#plan.bounds<shape, [10], [20]>, #plan.bounds<none>]  -> tensor<?xf32> {\\n    ^bb0(%in0: tensor<?xf32>, %in1: index, %out0: tensor<?xf32>):\\n      %2 = plan.with_shape %in0 (%in1) : (tensor<?xf32>, index) -> tensor<?xf32>\\n      %res = stablehlo.exponential %2 : tensor<?xf32>\\n      yield %res : tensor<?xf32>\\n    }\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyRankedTensor, AnySignlessIntegerOrIndex ]>>\" },\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_attrs\", \"type\": \"TypedArrayAttrBase<Plan_BoundsAttr>\" },\n      { \"name\": \"res_attrs\", \"type\": \"TypedArrayAttrBase<Plan_BoundsAttr>\" },\n      { \"name\": \"target\", \"type\": \"OptionalAttr<CompilerBackendAttrInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"plan\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"(`target` `(` $target^ `)` `\\\\n`)?\\n    `inputs` `(` ( $inputs^ `:` type($inputs) `)` ) : ( `)` ) ?  `\\\\n`\\n    `outs` `(` $outs `:` type($outs) `)` `\\\\n`\\n    `in_attrs` $input_attrs `\\\\n`\\n    `res_attrs` $res_attrs attr-dict-with-keyword `->` type($results)\\n     $body\"\n  },\n  {\n    \"name\": \"plan.inline_closed_alloc_group\",\n    \"description\": \"The `plan.inline_closed_alloc_group` operation is a variant of the\\n  `plan.inline_closed_group` operation that does not use destination-passing style\\n  (DPS). It is isolated from above and explicitly captures input operands, but unlike\\n  its DPS counterpart, it does not capture destination operands because its results must\\n  be lowered to allocation(s). The allocations may or may not be of a size that can only\\n  be computed inside of the region.\\n  This operation takes input operands and their corresponding bounds attributes,\\n  and produces results. The `input_attrs` hold bounds attribute information for\\n  the input operands. The absence of bounds information is allowed (`none` bounds).\\n\\n  The `target` attribute specifies the execution target for the group.\\n\\n  #### Example\\n\\n  Consider the following simple program containing operations with dynamically shaped operands:\\n\\n  ```mlir\\n  %0 = ... : tensor<?xf32> // A dynamically shaped operand\\n  %1 = ... : index         // A dynamic calculation of %0's extent\\n\\n  %2 = plan.inline_closed_alloc_group target(#plan.cluster_target<tensorrt>)\\n    inputs(%0, %1 : tensor<?xf32>, index)\\n    in_attrs [#plan.bounds<shape, [10], [20]>, #plan.bounds<none>]-> tensor<?xf32> {\\n    %3 = plan.with_shape %0 (%1) : (tensor<?xf32>, index) -> tensor<?xf32>\\n    %4 = stablehlo.exponential %3 : tensor<?xf32>\\n    yield %4 : tensor<?xf32>\\n  }\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_attrs\", \"type\": \"TypedArrayAttrBase<Plan_BoundsAttr>\" },\n      { \"name\": \"target\", \"type\": \"AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`target` `(` $target `)` `\\\\n`\\n    `inputs` `(` ( $inputs^ `:` type($inputs) `)` ) : ( `)` ) ?  `\\\\n`\\n    `in_attrs` $input_attrs `\\\\n`\\n     attr-dict-with-keyword `->` type($results)\\n     $body\",\n    \"defaultDialect\": \"plan\"\n  },\n  {\n    \"name\": \"plan.inline_closed_group\",\n    \"description\": \"The `plan.inline_closed_group` operation is similar to `dps.inline_group`\\n    except that it is isolated from above and explicitly captures destination\\n    operands. The `in_attrs` and `res_attrs` hold bounds attribute information\\n    for the input and result operands. The abcense of bounds information\\n    is allowed (`none` bounds).\\n\\n    #### Example\\n\\n    Consider the following simple program containing operations with\\n    dynamically shaped operands:\\n\\n    ```mlir\\n\\n    %0 = ... : tensor<?xf32> // A dynamically shaped operand\\n    %1 = .... : index        // A dynamic calculation of %0's extent\\n\\n    %2 = plan.inline_group target(#plan.cluster_target<tensorrt>) {\\n      %2 = plan.with_shape %0 (%1) : (tensor<?xf32>, index) -> tensor<?xf32>\\n      %3 = stablehlo.exponential %2 : tensor<?xf32>\\n      yield %3 : tensor<?xf32>\\n    }\\n\\n    ```\\n\\n    It can be transformed into the below IR which explicitly captures all\\n    operands, operand shape bounds, and the allocation of a destination tensor\\n    based on the upper bound of the yielded values:\\n\\n\\n    ```mlir\\n\\n    // Destination operand calculated from the upper bound of the\\n    // output.\\n    %empty = tensor.empty() : tensor<128xf32>\\n\\n    //Slice %empty to actual linear size.\\n    %out = tensor.extract_slice %empty[0][%ub][1] :  tensor<128xf32> to tensor<?xf32>\\n\\n    %2 = plan.inline_closed_group target(#plan.cluster_target<tensorrt>)\\n      inputs( %0, %1 : tensor<?xf32>, index)\\n      outs( %out : tensor<?xf32> )\\n      in_attrs [#plan.bounds<shape, [10], [20]>, #plan.bounds<none>]\\n      res_attrs [#plan.bounds<shape, [10], [20]>, #plan.bounds<none>]  -> tensor<?xf32> {\\n    ^bb0(%in0: tensor<?xf32>, %in1: index, %out0: tensor<?xf32>):\\n      %2 = plan.with_shape %in0 (%in1) : (tensor<?xf32>, index) -> tensor<?xf32>\\n      %res = stablehlo.exponential %2 : tensor<?xf32>\\n      yield %res : tensor<?xf32>\\n    }\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyRankedTensor, AnySignlessIntegerOrIndex ]>>\" },\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_attrs\", \"type\": \"TypedArrayAttrBase<Plan_BoundsAttr>\" },\n      { \"name\": \"res_attrs\", \"type\": \"TypedArrayAttrBase<Plan_BoundsAttr>\" },\n      { \"name\": \"target\", \"type\": \"AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`target` `(` $target `)` `\\\\n`\\n    `inputs` `(` ( $inputs^ `:` type($inputs) `)` ) : ( `)` ) ?  `\\\\n`\\n    `outs` `(` $outs `:` type($outs) `)` `\\\\n`\\n    `in_attrs` $input_attrs `\\\\n`\\n    `res_attrs` $res_attrs attr-dict-with-keyword `->` type($results)\\n     $body\",\n    \"defaultDialect\": \"plan\"\n  },\n  {\n    \"name\": \"plan.inline_group\",\n    \"description\": \"The `plan.inline_group` operation encapsulates a group of operations within\\n    its single-block region. The purpose of this operation is materialize\\n    in the IR the result of a clustering analysis.\\n\\n    Each `plan.inline_group` operation must be assigned a `target` attribute\\n    that indicates how the cluster should be compiled / what \\\"backend\\\" will\\n    be targeted. Examples of \\\"backends\\\" could include entire sub-compiler\\n    stacks like TensorRT or an external library like CUBlas or CUDNN.\\n\\n    The `plan.inline_group` operation is meant to be gradually lowered into a\\n    more specialized operation(s) and/or have the body outlined to a\\n    function-like operation such that the reuslts are replaced with a\\n    call-like operation.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"CompilerBackendAttrInterface\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`target` `(` $target `)` attr-dict-with-keyword (`->` type($results)^)? $body\",\n    \"defaultDialect\": \"plan\"\n  },\n  {\n    \"name\": \"plan.nvtx_pop\",\n    \"summary\": \"End an NVTX range using a correlation ID\",\n    \"description\": \"The `plan.nvtx_pop` operation ends an NVTX process range via\\n    `nvtxDomainRangeEnd` using the `range_id` from a corresponding\\n    `plan.nvtx_push`.\\n\\n    Semantically, the tensor inputs are identity -- they are tied to\\n    the corresponding results. The `range_id` operand is consumed (passed to\\n    the NVTX runtime) and does not appear in the results.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"range_id\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'inputs', 'results', 'llvm::make_range($_self.begin(), $_self.end())'>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict operands `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"plan.nvtx_push\",\n    \"summary\": \"Start an NVTX range and return a correlation ID\",\n    \"description\": \"The `plan.nvtx_push` operation starts an NVTX process and returns\\n    a correlation ID (`range_id`) along with identity-forwarded operands.\\n    The `range_id` must be passed to a corresponding `plan.nvtx_pop` to end the range.\\n\\n    Semantically, the tensor operands are identity -- they are tied to\\n    the corresponding results. The `range_id` result is a new i64 value\\n    returned that represents the correlation ID of the NVTX range.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"range_id\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"color\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'inputs', 'results', 'llvm::make_range($_self.begin(), $_self.end())'>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict operands `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"plan.optimization_barrier\",\n    \"summary\": \"identity operation that prevents optimizations\",\n    \"description\": \"The `plan.optimization_barrier` is a utility operation that is used to\\n    prevent some optimizations which match patterns in the input IR (e.g.\\n    constant folding) from being applied. Semantically, the operation\\n    is an identity -- the operands are tied to the results -- but it\\n    disrupts potential pattern matching.\\n\\n    Note that the operation is still functionally pure, so it does not\\n    prevent optimizations like loop-invariant code motion or CSE.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operands', 'results', 'llvm::make_range($_self.begin(), $_self.end())'>\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict  `:` type($operands)\"\n  },\n  {\n    \"name\": \"plan.transfer\",\n    \"summary\": \"Transfer a tensor from one memory space to another\",\n    \"description\": \"The `plan.transfer` operation is a utility operation that is used to\\n    transfer a tensor from one memory space to another. It is converted\\n    into a `linalg.copy` prior to running one-shot-bufferization.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict  `:` type($operand) `to` type($result)\"\n  },\n  {\n    \"name\": \"plan.with_shape\",\n    \"summary\": \"Ties a tensor value with index SSA values representing its shape\",\n    \"description\": \"The `plan.with_shape` operation is a utility operation that links a tensor\\n    SSA value with individual scalar Index-typed values representing the\\n    dimension sizes. The number of `shape` dimension values should be equal to\\n    the rank of `operand`.\\n\\n    The operation returns a single result which is exactly equivalent to the\\n    operand. The purpose of the operation is therefore purely to link the SSA\\n    value to the dimension sizes.\\n\\n    This operation is only really useful when `operand` has dynamic dimensions\\n    type, so if `operand` is statically shaped then this operation will be\\n    folded away.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<AnySignlessIntegerOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `(` $shape `)` `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"plan.with_values\",\n    \"summary\": \"Ties a tensor value with index SSA values representing its element values\",\n    \"description\": \"The `plan.with_values` operation is a utility operation that links a tensor\\n    SSA value with individual scalar values representing the values of individual\\n    elements. The number of `elements` should be equal to the volume of the\\n    `operand`, which must have a static shape.\\n\\n    The operation returns a single result which is exactly equivalent to the\\n    operand. The purpose of the operation is therefore purely to link the SSA\\n    value to the element values.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"StaticShapeTensorOf<[AnySignlessIntegerOrIndex]>\" },\n      { \"name\": \"elements\", \"type\": \"Variadic<AnySignlessIntegerOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `(` $elements `)` `:` custom<WithValuesTypes>(\\n      ref($elements), type($result), type($elements))\"\n  },\n  {\n    \"name\": \"plan.yield\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"plugin.magic\",\n    \"summary\": \"Illustrates how to define a custom operation.\",\n    \"description\": \"The `plugin.magic` operation illustrates how to define a new\\n        operation in a dialect. It uses an operation trait to declare that it\\n        has no side effects.\\n\\n        This operation takes an integer argument and returns an integer.\\n\\n        Example:\\n\\n        ```mlir\\n        %0 = arith.constant 2 : i32\\n        // Apply the magic operation to %0\\n        %1 = plugin.magic %0 : i32\\n        ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"poly.add\",\n    \"summary\": \"Addition operation between polynomials.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"PolyOrContainer\" },\n      { \"name\": \"rhs\", \"type\": \"PolyOrContainer\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"PolyOrContainer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"poly.constant\",\n    \"summary\": \"Define a constant polynomial via an attribute.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Polynomial\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"coefficients\", \"type\": \"AnyIntElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"$coefficients attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"poly.eval\",\n    \"summary\": \"Evaluates a Polynomial at a given input value.\",\n    \"operands\": [\n      { \"name\": \"polynomial\", \"type\": \"Polynomial\" },\n      { \"name\": \"point\", \"type\": \"IntOrComplex\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"IntOrComplex\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['point', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$polynomial `,` $point attr-dict `:` `(` qualified(type($polynomial)) `,` type($point) `)` `->` type($output)\"\n  },\n  {\n    \"name\": \"poly.from_tensor\",\n    \"summary\": \"Creates a Polynomial from integer coefficients stored in a tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[AnyInteger]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Polynomial\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` qualified(type($output))\"\n  },\n  {\n    \"name\": \"poly.mul\",\n    \"summary\": \"Multiplication operation between polynomials.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"PolyOrContainer\" },\n      { \"name\": \"rhs\", \"type\": \"PolyOrContainer\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"PolyOrContainer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"poly.sub\",\n    \"summary\": \"Subtraction operation between polynomials.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"PolyOrContainer\" },\n      { \"name\": \"rhs\", \"type\": \"PolyOrContainer\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"PolyOrContainer\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($output))\"\n  },\n  {\n    \"name\": \"poly.to_tensor\",\n    \"summary\": \"Converts a polynomial to a tensor of its integer coefficients.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Polynomial\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[AnyInteger]>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` qualified(type($input)) `->` type($output)\"\n  },\n  {\n    \"name\": \"proton_gpu.circular_store\",\n    \"summary\": \"Store the value into a circular buffer\",\n    \"description\": \"Store a metric `counter` into a circular buffer backed by the internal memory `segment`.\\n    automatically updated. Older metric counters are dropped if the `segment` buffer is full.\",\n    \"operands\": [\n      { \"name\": \"segment\", \"type\": \"PTG_SegmentType\" },\n      { \"name\": \"counter\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isStart\", \"type\": \"UnitAttr\" },\n      { \"name\": \"scopeId\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"(`start` $isStart^):(`end`)? $segment `,` $counter attr-dict `:`\\n    qualified(type($segment)) `,` type($counter)\"\n  },\n  {\n    \"name\": \"proton_gpu.finalize\",\n    \"summary\": \"Finalize the intra kernel profiler\",\n    \"description\": \"Write back the metadata and profile to global memory.\\n    `segment` is the segment of the internal profiling buffer that contains the profiling data.\\n    `scratchPtr` is the address of the profiling scratch buffer.\",\n    \"operands\": [\n      { \"name\": \"segment\", \"type\": \"PTG_SegmentType\" },\n      { \"name\": \"scratchPtr\", \"type\": \"TT_Ptr\" }\n    ],\n    \"assemblyFormat\": \"$segment `,` $scratchPtr attr-dict `:` qualified(type($segment)) `,` qualified(type($scratchPtr))\"\n  },\n  {\n    \"name\": \"proton_gpu.global_scratch_alloc\",\n    \"summary\": \"Allocate a global memory profile buffer\",\n    \"description\": \"This operation allocates a profile buffer in global memory.\\n    Each Triton program being profiled will hold a pointer to the buffer until profiling is finalized.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Ptr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nbytes\", \"type\": \"I32Attr\" },\n      { \"name\": \"alignment\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"proton_gpu.init_ctx\",\n    \"summary\": \"Initialize the intra kernel profiler warp-level contexts\",\n    \"description\": \"Initialize the intra kernel profiler warp-level contexts for all warps in\\n    `scratchPtr` (base address of the profiling scratch buffer). It can't be\\n    called inside `ttg.warp_specialize`.\",\n    \"operands\": [\n      { \"name\": \"scratchPtr\", \"type\": \"TT_Ptr\" }\n    ],\n    \"assemblyFormat\": \"$scratchPtr attr-dict `:` qualified(type($scratchPtr))\"\n  },\n  {\n    \"name\": \"proton_gpu.initialize\",\n    \"summary\": \"Initialize the intra kernel profiler\",\n    \"description\": \"Initialize the intra kernel profiler by filling the auxiliary metadata to the header.\\n    `scratchPtr` is the base address of the profiling scratch buffer where the header is stored.\",\n    \"operands\": [\n      { \"name\": \"scratchPtr\", \"type\": \"TT_Ptr\" }\n    ],\n    \"assemblyFormat\": \"$scratchPtr attr-dict `:` qualified(type($scratchPtr))\"\n  },\n  {\n    \"name\": \"proton_gpu.read_counter\",\n    \"summary\": \"Read a GPU metric counter into a scalar register\",\n    \"description\": \"Read a GPU metric counter into a scalar register.\",\n    \"results\": [\n      { \"name\": \"counter\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"metric\", \"type\": \"DefaultValuedAttr<MetricTypeAttr{cycle}, MetricType::CYCLE>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($counter)\"\n  },\n  {\n    \"name\": \"proton_gpu.restore_ctx\",\n    \"summary\": \"Restore the current warp-level context\",\n    \"description\": \"Restore the current warp context in `$segment` from\\n    `scratchPtr` (base address of the profiling scratch buffer).\",\n    \"operands\": [\n      { \"name\": \"segment\", \"type\": \"PTG_SegmentType\" },\n      { \"name\": \"scratchPtr\", \"type\": \"TT_Ptr\" }\n    ],\n    \"assemblyFormat\": \"$segment `,` $scratchPtr attr-dict `:` qualified(type($segment)) `,` qualified(type($scratchPtr))\"\n  },\n  {\n    \"name\": \"proton_gpu.save_ctx\",\n    \"summary\": \"Save the current warp-level context\",\n    \"description\": \"Save the current warp context from `$segment` to\\n    `scratchPtr` (base address of the profiling scratch buffer).\",\n    \"operands\": [\n      { \"name\": \"segment\", \"type\": \"PTG_SegmentType\" },\n      { \"name\": \"scratchPtr\", \"type\": \"TT_Ptr\" }\n    ],\n    \"assemblyFormat\": \"$segment `,` $scratchPtr attr-dict `:` qualified(type($segment)) `,` qualified(type($scratchPtr))\"\n  },\n  {\n    \"name\": \"proton_gpu.segment_alloc\",\n    \"summary\": \"Get the base offset of the segment of the internal buffer\",\n    \"description\": \"The internal buffer is partitioned into segments for each profiling \\\"unit\\\".\\n    This operation gets the location of the memory segment in the internal buffer.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyTypeOf<[TTG_MemDescType, TT_Ptr]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"segment\", \"type\": \"PTG_SegmentType\" }\n    ],\n    \"assemblyFormat\": \"$buffer attr-dict `:` qualified(type($buffer)) `->` type($segment)\"\n  },\n  {\n    \"name\": \"proton.record\",\n    \"summary\": \"Record an event\",\n    \"description\": \"This operation annotates a region of IR where events are recorded.\\n    Events can be classified as hardware or software events.\\n    Hardware events are provided by the hardware performance counters obtained in later passes that convert Triton to target-specific IR.\\n    Software events are provided by the user or the compiler.\\n\\n    Example:\\n\\n    ```mlir\\n    proton.record start \\\"name0\\\"\\n    ...\\n    proton.record end \\\"name0\\\"\\n    ```\\n\\n    Scope names cannot be reused within the same function.\",\n    \"attributes\": [\n      { \"name\": \"isStart\", \"type\": \"UnitAttr\" },\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"(`start` $isStart^):(`end`)? $name attr-dict\"\n  },\n  {\n    \"name\": \"ptr.constant\",\n    \"summary\": \"Pointer constant operation\",\n    \"description\": \"The `constant` operation produces a pointer constant. The attribute must be\\n    a typed attribute of pointer type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Create a null pointer\\n    %null = ptr.constant #ptr.null : !ptr.ptr<#ptr.generic_space>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_PtrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"ptr.from_ptr\",\n    \"summary\": \"Casts a `!ptr.ptr` value to a ptr-like value.\",\n    \"description\": \"The `from_ptr` operation casts a `ptr` value to a ptr-like object. It's\\n    important to note that:\\n    - The ptr-like object cannot be a `!ptr.ptr`.\\n    - The memory-space of both the `ptr` and ptr-like object must match.\\n    - The cast is Pure (no UB and side-effect free).\\n\\n    The optional `metadata` operand exists to provide any ptr-like metadata\\n    that might be required to perform the cast.\\n\\n    Example:\\n\\n    ```mlir\\n    %typed_ptr = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> !my.ptr<f32, #ptr.generic_space>\\n    %memref = ptr.from_ptr %ptr metadata %md : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>\\n\\n    // Cast the `%ptr` to a memref without utilizing metadata.\\n    %memref = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Ptr_PtrType\" },\n      { \"name\": \"metadata\", \"type\": \"Optional<Ptr_PtrMetadata>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"PtrLikeTypeInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'metadata', 'PtrMetadataType::get(cast<PtrLikeTypeInterface>($_self))'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr (`metadata` $metadata^)? attr-dict `:` type($ptr) `->` type($result)\"\n  },\n  {\n    \"name\": \"ptr.gather\",\n    \"summary\": \"Gather operation\",\n    \"description\": \"The `gather` operation performs conditional loads from multiple memory\\n    locations specified by `ptrs` based on a mask `mask`. Elements of the\\n    result corresponding to masked-off lanes are taken from the passthrough\\n    operand.\\n\\n    The mask operand is a shaped type of `i1` elements that must have the same\\n    shape as the result type.\\n\\n    Examples:\\n    ```mlir\\n    // Gather values from multiple memory locations\\n    %result = ptr.gather %ptrs, %mask, %passthrough :\\n      vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xf32>\\n\\n    // Gather with alignment\\n    %result = ptr.gather %ptrs, %mask, %passthrough alignment = 8 :\\n      vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptrs\", \"type\": \"Ptr_Ptr1DType\" },\n      { \"name\": \"mask\", \"type\": \"Ptr_Mask1DType\" },\n      { \"name\": \"passthrough\", \"type\": \"Ptr_Any1DType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_Any1DType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"AlignmentProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'mask', '::llvm::cast<ShapedType>($_self).clone(\\n        IntegerType::get($_self.getContext(), 1))'>\" },\n      { \"type\": \"AllTypesMatch<['result', 'passthrough']>\" }\n    ],\n    \"assemblyFormat\": \"$ptrs `,` $mask `,` $passthrough (`alignment` `=` $alignment^)?\\n    attr-dict `:` type($ptrs) `->` type($result)\"\n  },\n  {\n    \"name\": \"ptr.get_metadata\",\n    \"summary\": \"SSA value representing pointer metadata.\",\n    \"description\": \"The `get_metadata` operation produces an opaque value that encodes the\\n    metadata of the ptr-like type.\\n\\n    Example:\\n\\n    ```mlir\\n    %metadata = ptr.get_metadata %memref : memref<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"PtrLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_PtrMetadata\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'ptr', 'result', 'PtrMetadataType::get(cast<PtrLikeTypeInterface>($_self))'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr)\"\n  },\n  {\n    \"name\": \"ptr.load\",\n    \"description\": \"The `load` operation is used to read from memory. A load may be marked as\\n    atomic, volatile, and/or nontemporal.\\n\\n    An atomic load only supports a limited set of value types, and requires\\n    an explicit alignment.\\n\\n    Examples:\\n    ```mlir\\n    // A volatile load of a float variable.\\n    %0 = ptr.load volatile %ptr : !ptr.ptr -> f32\\n\\n    // A nontemporal load of a float variable.\\n    %0 = ptr.load %ptr nontemporal : !ptr.ptr -> f32\\n\\n    // An atomic load of an integer variable.\\n    %0 = ptr.load %ptr atomic monotonic alignment = 8 : !ptr.ptr -> i64\\n    ```\\n\\n    See the following link for more details on the meaning of `alignment`,\\n    `volatile_`, `nontemporal`, `invariant`, `invariant_group`, `ordering`,\\n    and `syncscope`:\\n    https://llvm.org/docs/LangRef.html#load-instruction\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Ptr_PtrType\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"AlignmentProp\" },\n      { \"name\": \"volatile_\", \"type\": \"UnitProp\" },\n      { \"name\": \"nontemporal\", \"type\": \"UnitProp\" },\n      { \"name\": \"invariant\", \"type\": \"UnitProp\" },\n      { \"name\": \"invariantGroup\", \"type\": \"UnitProp\" },\n      { \"name\": \"ordering\", \"type\": \"DefaultValuedProp<AtomicOrderingProp{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}, AtomicOrdering::not_atomic>\" },\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`volatile` $volatile_^)? $ptr\\n    (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?\\n    oilist(\\n      `nontemporal` $nontemporal |\\n      `invariant` $invariant |\\n      `invariant_group` $invariantGroup |\\n      `alignment` `=` $alignment\\n    )\\n    attr-dict `:` qualified(type($ptr)) `->` type($value)\"\n  },\n  {\n    \"name\": \"ptr.masked_load\",\n    \"summary\": \"Masked load operation\",\n    \"description\": \"The `masked_load` operation performs a conditional load from memory based\\n    on  a mask. Elements of the result corresponding to masked-off lanes are\\n    taken from the passthrough operand.\\n\\n    The mask operand is a shaped type of `i1` elements that must have the same\\n    shape as the result type.\\n\\n    Examples:\\n    ```mlir\\n    // Masked load with passthrough on vectors\\n    %result = ptr.masked_load %ptr, %mask, %passthrough :\\n      !ptr.ptr<#ptr.generic_space> -> vector<4xf32>\\n\\n    // Masked load with passthrough on tensors\\n    %result = ptr.masked_load %ptr, %mask, %passthrough :\\n      !ptr.ptr<#ptr.generic_space> -> tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Ptr_PtrType\" },\n      { \"name\": \"mask\", \"type\": \"Ptr_Mask1DType\" },\n      { \"name\": \"passthrough\", \"type\": \"Ptr_Any1DType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_Any1DType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"AlignmentProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'mask', '::llvm::cast<ShapedType>($_self).clone(\\n        IntegerType::get($_self.getContext(), 1))'>\" },\n      { \"type\": \"AllTypesMatch<['result', 'passthrough']>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $mask `,` $passthrough (`alignment` `=` $alignment^)?\\n    attr-dict `:` qualified(type($ptr)) `->` type($result)\"\n  },\n  {\n    \"name\": \"ptr.masked_store\",\n    \"summary\": \"Masked store operation\",\n    \"description\": \"The `masked_store` operation performs a conditional store to memory based\\n    on  a mask. Only elements corresponding to set bits in the mask are written\\n    to memory.\\n\\n    The mask operand is a shaped type of `i1` elements that must have the same\\n    shape as the value being stored.\\n\\n    Examples:\\n    ```mlir\\n    // Masked store\\n    ptr.masked_store %value, %ptr, %mask :\\n      vector<4xf32>, !ptr.ptr<#ptr.generic_space>\\n\\n    // Masked store with alignment\\n    ptr.masked_store %value, %ptr, %mask alignment = 8 :\\n      vector<4xf32>, !ptr.ptr<#ptr.generic_space>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Ptr_Any1DType\" },\n      { \"name\": \"ptr\", \"type\": \"Ptr_PtrType\" },\n      { \"name\": \"mask\", \"type\": \"Ptr_Mask1DType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"AlignmentProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'mask', '::llvm::cast<ShapedType>($_self).clone(\\n        IntegerType::get($_self.getContext(), 1))'>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $ptr `,` $mask (`alignment` `=` $alignment^)? attr-dict `:`\\n    type($value) `,` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"ptr.ptr_add\",\n    \"summary\": \"Pointer add operation\",\n    \"description\": \"The `ptr_add` operation adds an int-like offset to one or more pointers to produce one or more new pointers.\\n\\n    The operation supports both scalar and shaped types with value semantics:\\n    - When both base and offset are scalar: produces a single new pointer\\n    - When base is shaped and offset is scalar: adds the same offset to each\\n    pointer in the base\\n    - When base is scalar and offset is shaped: adds the single pointer to each\\n    offset in the shaped value\\n    - When both are shaped: performs element-wise addition (shapes must be\\n    compatible)\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar base and offset\\n    %x_off  = ptr.ptr_add %x, %off : !ptr.ptr<#ptr.generic_space>, i32\\n    %x_off0 = ptr.ptr_add nusw %x, %off : !ptr.ptr<#ptr.generic_space>, i32\\n\\n    // Shaped base with scalar offset\\n    %ptrs_off = ptr.ptr_add %ptrs, %off : vector<4x!ptr.ptr<#ptr.generic_space>>, i32\\n\\n    // Scalar base with shaped offset\\n    %x_offs = ptr.ptr_add %x, %offs : !ptr.ptr<#ptr.generic_space>, vector<4xi32>\\n\\n    // Both base and offset are shaped\\n    %ptrs_offs = ptr.ptr_add %ptrs, %offs : vector<4x!ptr.ptr<#ptr.generic_space>>, vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"Ptr_PtrLikeType\" },\n      { \"name\": \"offset\", \"type\": \"Ptr_IntLikeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_PtrLikeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"DefaultValuedProp<EnumProp<Ptr_PtrAddFlags{none|nusw|nuw|inbounds}>, PtrAddFlags::none>\" }\n    ],\n    \"assemblyFormat\": \"($flags^)? $base `,` $offset attr-dict `:` type($base) `,` type($offset)\"\n  },\n  {\n    \"name\": \"ptr.ptr_diff\",\n    \"summary\": \"Pointer difference operation\",\n    \"description\": \"The `ptr_diff` operation computes the difference between two pointers,\\n    returning an integer or index value representing the number of bytes\\n    between them.\\n\\n    The operation supports both scalar and shaped types with value semantics:\\n    - When both operands are scalar: produces a single difference value\\n    - When both are shaped: performs element-wise subtraction,\\n      shapes must be the same\\n\\n    The operation also supports the following flags:\\n    - `none`: No flags are set.\\n    - `nuw`: No Unsigned Wrap, if the subtraction causes an unsigned overflow\\n      (that is: the result would be negative), the result is a poison value.\\n    - `nsw`: No Signed Wrap, if the subtraction causes a signed overflow, the\\n      result is a poison value.\\n\\n    NOTE: The pointer difference is calculated using an integer type specified\\n    by the data layout. The final result will be sign-extended or truncated to\\n    fit the result type as necessary.\\n\\n    Example:\\n\\n    ```mlir\\n    // Scalar pointers\\n    %diff = ptr.ptr_diff %p1, %p2 : !ptr.ptr<#ptr.generic_space> -> i64\\n\\n    // Shaped pointers\\n    %diffs = ptr.ptr_diff nsw %ptrs1, %ptrs2 :\\n      vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Ptr_PtrLikeType\" },\n      { \"name\": \"rhs\", \"type\": \"Ptr_PtrLikeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_IntLikeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"flags\", \"type\": \"DefaultValuedProp<EnumProp<Ptr_PtrDiffFlags{none|nuw|nsw}>, PtrDiffFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"($flags^)? $lhs `,` $rhs attr-dict `:` type($lhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"ptr.scatter\",\n    \"summary\": \"Scatter operation\",\n    \"description\": \"The `scatter` operation performs a conditional store of a value `value` to\\n    multiple memory locations specified by `ptrs` based on a mask `mask`.\\n\\n    Only elements corresponding to set bits in the mask are written to memory.\\n    The mask operand is a shaped type of `i1` elements that must have the same\\n    shape as the value being stored.\\n\\n    Examples:\\n    ```mlir\\n    // Scatter values to multiple memory locations\\n    ptr.scatter %value, %ptrs, %mask :\\n      vector<4xf32>, vector<4x!ptr.ptr<#ptr.generic_space>>\\n\\n    // Scatter with alignment\\n    ptr.scatter %value, %ptrs, %mask alignment = 8 :\\n      vector<4xf32>, vector<4x!ptr.ptr<#ptr.generic_space>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Ptr_Any1DType\" },\n      { \"name\": \"ptrs\", \"type\": \"Ptr_Ptr1DType\" },\n      { \"name\": \"mask\", \"type\": \"Ptr_Mask1DType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"AlignmentProp\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'mask', '::llvm::cast<ShapedType>($_self).clone(\\n        IntegerType::get($_self.getContext(), 1))'>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $ptrs `,` $mask  (`alignment` `=` $alignment^)?\\n    attr-dict `:` type($value) `,` type($ptrs)\"\n  },\n  {\n    \"name\": \"ptr.store\",\n    \"description\": \"The `store` operation is used to write to memory. A store may be marked as\\n    atomic, volatile, and/or nontemporal.\\n\\n    An atomic store only supports a limited set of value types, and requires\\n    an explicit alignment.\\n\\n    Examples:\\n    ```mlir\\n    // A volatile store of a float variable.\\n    ptr.store volatile %val, %ptr : f32, !ptr.ptr\\n\\n    // A nontemporal store of a float variable.\\n    ptr.store %val, %ptr nontemporal : f32, !ptr.ptr\\n\\n    // An atomic store of an integer variable.\\n    ptr.store %val, %ptr atomic monotonic alignment = 8: i64, !ptr.ptr\\n    ```\\n\\n    See the following link for more details on the meaning of `alignment`,\\n    `volatile_`, `nontemporal`, `invariant_group`, `ordering`, and `syncscope`:\\n    https://llvm.org/docs/LangRef.html#store-instruction\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"ptr\", \"type\": \"Ptr_PtrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"AlignmentProp\" },\n      { \"name\": \"volatile_\", \"type\": \"UnitProp\" },\n      { \"name\": \"nontemporal\", \"type\": \"UnitProp\" },\n      { \"name\": \"invariantGroup\", \"type\": \"UnitProp\" },\n      { \"name\": \"ordering\", \"type\": \"DefaultValuedProp<AtomicOrderingProp{not_atomic|unordered|monotonic|acquire|release|acq_rel|seq_cst}, AtomicOrdering::not_atomic>\" },\n      { \"name\": \"syncscope\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`volatile` $volatile_^)? $value `,` $ptr\\n    (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?\\n    oilist(\\n      `nontemporal` $nontemporal |\\n      `invariant_group` $invariantGroup |\\n      `alignment` `=` $alignment\\n    )\\n    attr-dict `:` type($value) `,` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"ptr.to_ptr\",\n    \"summary\": \"Casts a ptr-like value to a `!ptr.ptr` value.\",\n    \"description\": \"The `to_ptr` operation casts a ptr-like object to a `!ptr.ptr`. It's\\n    important to note that:\\n    - The ptr-like object cannot be a `!ptr.ptr`.\\n    - The memory-space of both the `ptr` and ptr-like object must match.\\n    - The cast is side-effect free.\\n\\n    Example:\\n\\n    ```mlir\\n    %ptr0 = ptr.to_ptr %my_ptr : !my.ptr<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>\\n    %ptr1 = ptr.to_ptr %memref : memref<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"PtrLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Ptr_PtrType\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr) `->` type($result)\"\n  },\n  {\n    \"name\": \"ptr.type_offset\",\n    \"summary\": \"Type offset operation\",\n    \"description\": \"The `type_offset` operation produces an int or index-typed SSA value\\n    equal to a target-specific constant representing the offset of a single\\n    element of the given type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Return the offset between two f32 stored in memory\\n    %0 = ptr.type_offset f32 : index\\n    // Return the offset between two memref descriptors stored in memory\\n    %1 = ptr.type_offset memref<12 x f64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySignlessIntegerOrIndex\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elementType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$elementType attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"pxa.generic\",\n    \"summary\": \"PXA generic operation\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyMemRef>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyMemRef>\" },\n      { \"name\": \"inputIndices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"outputIndices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyMemRef>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inputAccessMaps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"inputTileMaps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"outputAccessMaps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"outputTileMaps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"kernel\", \"type\": \"StrAttr\" },\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"reductions\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pxa.load\",\n    \"summary\": \"affine load operation\",\n    \"description\": \"The \\\"affine.load\\\" op reads an element from a memref, where the index\\n    for each memref dimension is an affine expression of loop induction\\n    variables and symbols. The output of 'affine.load' is a new value with the\\n    same type as the elements of the memref. An affine expression of loop IVs\\n    and symbols must be specified for each dimension of the memref. The keyword\\n    'symbol' can be used to indicate SSA identifiers which are symbolic.\\n\\n    Example 1:\\n\\n    ```mlir\\n    %1 = affine.load %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>\\n    ```\\n\\n    Example 2: Uses 'symbol' keyword for symbols '%n' and '%m'.\\n\\n    ```mlir\\n    %1 = affine.load %0[%i0 + symbol(%n), %i1 + symbol(%m)] : memref<100x100xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"idxs\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pxa.prng\",\n    \"summary\": \"pseudorandom number generator operation\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"tensor\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"new_state\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_tensor\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"result_state\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"pxa.reduce\",\n    \"summary\": \"affine reduction operation\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"AnyType\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"idxs\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"agg\", \"type\": \"AtomicRMWKindAttr{addf|addi|andi|assign|maximumf|maxnumf|maxs|maxu|minimumf|minnumf|mins|minu|mulf|muli|ori|xori}\" },\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pxa.store\",\n    \"summary\": \"PXA non-affine store operation\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[AnySignlessInteger, AnyFloat, AnyVector]>\" },\n      { \"name\": \"memref\", \"type\": \"MemRefOf<[AnySignlessInteger, AnyFloat]>\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MemRefOf<[AnySignlessInteger, AnyFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"agg\", \"type\": \"AtomicRMWKindAttr{addf|addi|andi|assign|maximumf|maxnumf|maxs|maxu|minimumf|minnumf|mins|minu|mulf|muli|ori|xori}\" }\n    ],\n    \"assemblyFormat\": \"$agg $value `,` $memref `[` $indices `]` attr-dict `:` `(` type($value) `,`\\n    type($memref) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pxa.vector_load\",\n    \"summary\": \"affine vector load operation\",\n    \"description\": \"The \\\"affine.vector_load\\\" is the vector counterpart of\\n    [affine.load](#affineload-operation). It reads a slice from a\\n    [MemRef](../LangRef.md#memref-type), supplied as its first operand,\\n    into a [vector](../LangRef.md#vector-type) of the same base elemental type.\\n    The index for each memref dimension is an affine expression of loop induction\\n    variables and symbols. These indices determine the start position of the read\\n    within the memref. The shape of the return vector type determines the shape of\\n    the slice read from the memref. This slice is contiguous along the respective\\n    dimensions of the shape. Strided vector loads will be supported in the future.\\n    An affine expression of loop IVs and symbols must be specified for each\\n    dimension of the memref. The keyword 'symbol' can be used to indicate SSA\\n    identifiers which are symbolic.\\n\\n    Example 1: 8-wide f32 vector load.\\n\\n    ```mlir\\n    %1 = affine.vector_load %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>, vector<8xf32>\\n    ```\\n\\n    Example 2: 4-wide f32 vector load. Uses 'symbol' keyword for symbols '%n' and '%m'.\\n\\n    ```mlir\\n    %1 = affine.vector_load %0[%i0 + symbol(%n), %i1 + symbol(%m)] : memref<100x100xf32>, vector<4xf32>\\n    ```\\n\\n    Example 3: 2-dim f32 vector load.\\n\\n    ```mlir\\n    %1 = affine.vector_load %0[%i0, %i1] : memref<100x100xf32>, vector<2x8xf32>\\n    ```\\n\\n    TODOs:\\n    * Add support for strided vector loads.\\n    * Consider adding a permutation map to permute the slice that is read from memory\\n    (see [vector.transfer_read](../Vector/#vectortransfer_read-vectortransferreadop)).\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"idxs\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"pxa.vector_reduce\",\n    \"summary\": \"affine vector reduction operation\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"AnyVector\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"idxs\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"agg\", \"type\": \"AtomicRMWKindAttr{addf|addi|andi|assign|maximumf|maxnumf|maxs|maxu|minimumf|minnumf|mins|minu|mulf|muli|ori|xori}\" },\n      { \"name\": \"map\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"quant.dcast\",\n    \"summary\": \"Dequantize cast operation\",\n    \"description\": \"Convert an input quantized value into its expressed floating-point value.\\n    The dequantization process consists of the following steps:\\n\\n    ```\\n    def dequantize(quantizedValue: quantizedType) -> expressedType:\\n        storedValue = reinterpretCast(quantizedValue, storageType)\\n        storedValueFloat = convertIntToFloat(storedValue, expressedType)\\n        zeroPointFloat = convertIntToFloat(zeroPoint, expressedType)\\n        expressedValue = (storedValueFloat - zeroPointFloat) * scale\\n        return expressedValue\\n    ```\\n\\n    Here, `storageType`, `expressedType`, `scale`, and `zeroPoint` are obtained\\n    from the corresponding parameters encoded in `quantizedType`. For\\n    per-channel quantization, the appropriate `scale` and `zeroPoint` values\\n    are used for each tensor element computation according to the channel the\\n    element belongs to.\\n    \\n    The numerical results produced by the algorithm above may vary depending on\\n    the rounding methods used by `convertIntToFloat()`, subtraction (`-`), and\\n    multiplication (`*`). This operation does not define specific rounding\\n    methods; instead, it is the responsibility of a transform pipeline to\\n    determine which rounding method to apply when this operation is broken down\\n    into lower-level dialects.\\n\\n    The operation must satisfy the following syntactic constraints:\\n\\n    - Operand `input` must be a scalar or tensor of type `!quant.uniform`.\\n\\n    - The result type must be a floating-point scalar or tensor.\\n\\n    - The `expressedType` parameter of the `!quant.uniform` type of the input\\n      must match the floating-point type of the result.\\n\\n    - The operand and result types must be both scalars or both tensors. If\\n      tensors, they must be both ranked or both unranked. If ranked, both must\\n      have the same shape, including matching static and dynamic dimensions.\\n\\n    - If the operand uses per-channel quantization, its `!quant.uniform` type\\n      must adhere to the [Per-axis quantization\\n      integrity](#per-axis-quantization-integrity) guidelines.\\n\\n    Examples:\\n\\n    ```\\n    // Dequantize a scalar quantized value\\n    %result = quant.dcast %input : !quant.uniform<i8:f32, 2.0> to f32\\n\\n    // Dequantize a dynamically shaped tensor of quantized values\\n    %result = quant.dcast %input : tensor<?x!quant.uniform<i8:f32, 2.0>> to tensor<?xf32>\\n\\n    // Dequantize an unranked tensor using per-axis quantization information\\n    %result = quant.dcast %input : tensor<*x!quant.uniform<i8:f32:1, {2.0, 3.0}>> to tensor<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"quant_QuantizedScalarOrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"quant_FloatScalarOrTensor\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"quant.qcast\",\n    \"summary\": \"Quantize cast operation\",\n    \"description\": \"Convert a floating-point value to a quantized type. The quantization\\n    process consists of the following steps:\\n\\n    ```\\n    def quantize(expressedValue: expressedType) -> quantizedType:\\n        zeroPointFloat = convertIntToFloat(zeroPoint, expressedType)\\n        scaledValue = expressedValue / scale\\n        storedValueFloat = scaledValue + zeroPointFloat\\n        storedValue = convertFloatToInt(storedValueFloat, storageType)\\n        storedValueClamped = clamp(storedValue, storageMin, storageMax)\\n        quantizedValue = reinterpretCast(storedValueClamped, quantizedType)\\n        return quantizedValue\\n    ```\\n\\n    Here, `storageType`, `storageMin`, `storageMax`, `expressedType`, `scale`,\\n    and `zeroPoint` are obtained from the corresponding parameters encoded in\\n    `quantizedType`. For per-channel quantization, the appropriate `scale` and\\n    `zeroPoint` values are used for each tensor element computation according\\n    to the channel the element belongs to.\\n\\n    The numerical results produced by the algorithm above may vary depending on\\n    the rounding methods used by `convertIntToFloat()`, `convertFloatToInt()`,\\n    `clamp()`, division (`/`), and addition (`+`). This operation does not\\n    define specific rounding methods; instead, it is the responsibility of a\\n    transform pipeline to determine which rounding method to apply when this\\n    operation is broken down into lower-level dialects.\\n\\n    The operation must satisfy the following syntactic constraints:\\n\\n    - Operand `input` must be a floating-point scalar or tensor.\\n\\n    - The result type must be a scalar or tensor of type `!quant.uniform`.\\n\\n    - The `expressedType` parameter in the `!quant.uniform` type of the result\\n      must match the floating-point type of the input.\\n\\n    - The operand and result types must be both scalars or both tensors. If\\n      tensors, they must be both ranked or both unranked. If ranked, both must\\n      have the same shape, including matching static and dynamic dimensions.\\n\\n    - If the result uses per-channel quantization, its `!quant.uniform` type\\n      must adhere to the [Per-axis quantization\\n      integrity](#per-axis-quantization-integrity) guidelines.\\n\\n    Examples:\\n\\n    ```\\n    // Quantize a scalar floating-point value\\n    %result = quant.qcast %input : f32 to !quant.uniform<i8:f32, 2.0>\\n\\n    // Quantize a dynamically shaped tensor of quantized values\\n    %result = quant.qcast %input : tensor<?xf32> to tensor<?x!quant.uniform<i8:f32, 2.0>>\\n\\n    // Quantize an unranked tensor using per-axis quantization information\\n    %result = quant.qcast %input : tensor<*xf32> to tensor<*x!quant.uniform<i8:f32:1, {2.0, 3.0}>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"quant_FloatScalarOrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"quant_QuantizedScalarOrTensor\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"quant.scast\",\n    \"summary\": \"Storage cast operation\",\n    \"description\": \"Convert a value from a quantized type to the corresponding signless integer\\n    storage type, or vice versa. This conversion simply involves a\\n    reinterpretation of the input bits and does not involve any data\\n    manipulation.\\n\\n    The following syntactic restrictions must be met:\\n\\n    - Operand `input` must be a scalar or tensor of a signless integer or\\n      `!quant.uniform` type.\\n\\n    - The result must be a scalar or tensor of a signless integer or\\n      `!quant.uniform` type.\\n\\n    - If the operand is a scalar or tensor of type integer, the result must be\\n      a scalar or tensor of type `!quant.uniform`, and vice versa.\\n\\n    - The operand and result must be both scalars or both tensors. If tensors,\\n      they must be both ranked or both unranked. If ranked, both must have the\\n      same shape, including matching static and dynamic dimensions.\\n\\n    - The width of the `storageType` parameter of the quantized type of the\\n      operand or result must match the width of the signless integer type of\\n      the operand or result.\\n\\n    - If the operand or result uses per-channel quantization, its\\n      `!quant.uniform` type must adhere to the [Per-axis quantization\\n      integrity](#per-axis-quantization-integrity) guidelines.\\n\\n    Examples:\\n\\n    ```\\n    // Cast a scalar quantized value into its storage type\\n    %result = quant.scast %input : !quant.uniform<i8:f32, 2.0> to i8\\n\\n    // Cast a dynamically shaped tensor of quantized values into their storage type\\n    %result = quant.scast %input : tensor<?x!quant.uniform<i8:f32, 2.0>> to tensor<?xi8>\\n\\n    // Cast an unranked tensor of signless integers into a quantized type using\\n    // per-channel quantization\\n    %result = quant.scast %input : tensor<*xi8> to tensor<*x!quant.uniform<i8:f32:1, {2.0, 3.0}>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"quant_IntegerOrQuantizedScalarOrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"quant_IntegerOrQuantizedScalarOrTensor\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"rocdl.asyncmark\",\n    \"summary\": \"Mark the end of a group of asynchronous operations\",\n    \"description\": \"This operation, in conjunction with `rocdl.wait.asyncmark`, forms the\\n      compiler-provided framework for tracking explicitly asynchronous\\n      memory operations, such as copies to LDS that use async intrinsics\\n      and gfx1250's tensor loads.\\n\\n      Details of its behavior can be found in\\n      [the LLVM documentation on async tracking](/llvm/docs/AMDGPUAsyncOperations.rst).\\n\\n      See `rocdl.wait.asyncmark`'s documentation for a usage example.\\n\\n      Example:\\n      ```mlir\\n      // Mark the end of an async operation group.\\n      rocdl.asyncmark\\n      ```\\n\\n      Available on gfx9 and later.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.ballot\",\n    \"summary\": \"Vote across thread group\",\n    \"description\": \"Ballot provides a bit mask containing the 1-bit predicate value from each lane.\\n      The nth bit of the result contains the 1 bit contributed by the nth warp lane.\\n\\n      Example:\\n      ```mlir\\n      // Ballot across thread group.\\n      %0 = rocdl.ballot %pred : i64\\n      ```\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"$pred attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.barrier\",\n    \"description\": \"An operation with the same expansion as HIP's __synchthreads();\\n\\n    **DEPRECATION NOTICE**: Use `gpu.barrier`, which will expand to these\\n    operations, instead.\\n\\n    Example:\\n    ```mlir\\n    // Workgroup barrier with acquire/release fences.\\n    rocdl.barrier\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.cluster.id.x\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cluster.id.y\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cluster.id.z\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cluster.load.async.to.lds.b128\",\n    \"description\": \"Broadcasts memory load ofbits of data for a cluster of workgroups.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // Cluster broadcastbitsVal-bit load to LDS.\\n      rocdl.cluster.load.async.to.lds.b128%src, %dst, 0, 0, %mask : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"mask\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"cpol\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $cpol `,` $mask\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.cluster.load.async.to.lds.b32\",\n    \"description\": \"Broadcasts memory load ofbits of data for a cluster of workgroups.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // Cluster broadcastbitsVal-bit load to LDS.\\n      rocdl.cluster.load.async.to.lds.b32%src, %dst, 0, 0, %mask : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"mask\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"cpol\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $cpol `,` $mask\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.cluster.load.async.to.lds.b64\",\n    \"description\": \"Broadcasts memory load ofbits of data for a cluster of workgroups.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // Cluster broadcastbitsVal-bit load to LDS.\\n      rocdl.cluster.load.async.to.lds.b64%src, %dst, 0, 0, %mask : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"mask\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"cpol\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $cpol `,` $mask\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.cluster.load.async.to.lds.b8\",\n    \"description\": \"Broadcasts memory load ofbits of data for a cluster of workgroups.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // Cluster broadcastbitsVal-bit load to LDS.\\n      rocdl.cluster.load.async.to.lds.b8%src, %dst, 0, 0, %mask : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"mask\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"cpol\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $cpol `,` $mask\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.cluster.workgroup.id.x\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cluster.workgroup.id.y\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cluster.workgroup.id.z\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cos\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.cos%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.cvt.f32.bf8\",\n    \"summary\": \"Convert bf8 to f32\",\n    \"description\": \"Convert 8-bit bf8 value from the `byteSel`th bit of `srcA` to fp32.\\n\\n    Example:\\n    ```mlir\\n    // Convert bf8 byte 0 to f32.\\n    %0 = rocdl.cvt.f32.bf8 %src[0] : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"byteSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `[` $byteSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.f32.fp8\",\n    \"summary\": \"Convert fp8 to f32\",\n    \"description\": \"Convert 8-bit fp8 value from the `byteSel`th bit of `srcA` to fp32.\\n\\n    Example:\\n    ```mlir\\n    // Convert fp8 byte 0 to f32.\\n    %0 = rocdl.cvt.f32.fp8 %src[0] : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"byteSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `[` $byteSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.pk.bf8.f32\",\n    \"summary\": \"Convert two f32's to bf8\",\n    \"description\": \"Convert `srcA` and `srcB` to bf8 and store into the low/high word of\\n    `old`, preserving the other word.\\n\\n    Example:\\n    ```mlir\\n    // Pack two f32 values into bf8 in the low word of old.\\n    %0 = rocdl.cvt.pk.bf8.f32 %a, %b -> %old[false] : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"F32\" },\n      { \"name\": \"srcB\", \"type\": \"F32\" },\n      { \"name\": \"old\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"wordSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `,` $srcB `->` $old `[` $wordSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.pk.f32.bf8\",\n    \"summary\": \"Convert packed bf8 to packed f32\",\n    \"description\": \"Convert `src` based on $wordSel to packed fp32.\\n\\n    Example:\\n    ```mlir\\n    // Unpack bf8 word to packed f32.\\n    %0 = rocdl.cvt.pk.f32.bf8 %src[false] : vector<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"wordSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $wordSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.pk.f32.fp8\",\n    \"summary\": \"Convert packed fp8 to packed f32\",\n    \"description\": \"Convert `src` based on $wordSel to packed fp32.\\n\\n    Example:\\n    ```mlir\\n    // Unpack fp8 word to packed f32.\\n    %0 = rocdl.cvt.pk.f32.fp8 %src[false] : vector<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"wordSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $wordSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.pk.fp8.f32\",\n    \"summary\": \"Convert two f32's to fp8\",\n    \"description\": \"Convert `srcA` and `srcB` to fp8 and store into the low/high word of\\n    `old`, preserving the other word.\\n\\n    Example:\\n    ```mlir\\n    // Pack two f32 values into fp8 in the low word of old.\\n    %0 = rocdl.cvt.pk.fp8.f32 %a, %b -> %old[false] : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"F32\" },\n      { \"name\": \"srcB\", \"type\": \"F32\" },\n      { \"name\": \"old\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"wordSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `,` $srcB `->` $old `[` $wordSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.pkrtz\",\n    \"summary\": \"Convert two f32 input into a vector<2xf16>\",\n    \"description\": \"Convert two f32 values into a packed vector<2xf16>.\\n\\n    Example:\\n    ```mlir\\n    // Pack two f32 values into a vector<2xf16> with round-to-zero.\\n    %0 = rocdl.cvt.pkrtz %a, %b : vector<2xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"F32\" },\n      { \"name\": \"srcB\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `,` $srcB `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk16.bf16.bf6\",\n    \"summary\": \"Scales 16 bf6 and converts them to 16 bf16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V3I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V16BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk16.bf16.fp6\",\n    \"summary\": \"Scales 16 fp6 and converts them to 16 bf16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V3I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V16BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk16.f16.bf6\",\n    \"summary\": \"Scales 16 bf6 and converts them to 16 f16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V3I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V16F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk16.f16.fp6\",\n    \"summary\": \"Scales 16 fp6 and converts them to 16 f16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V3I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V16F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk16.f32.bf6\",\n    \"summary\": \"Scales 16 bf6 and converts them to 16 f32.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V3I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V16F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk16.f32.fp6\",\n    \"summary\": \"Scales 16 fp6 and converts them to 16 f32.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V3I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V16F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.bf16.bf8\",\n    \"summary\": \"Scales 8 bf8 and converts them to 8 bf16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V2I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.bf16.fp4\",\n    \"summary\": \"Scales 8 fp4 and converts them to 8 bf16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.bf16.fp8\",\n    \"summary\": \"Scales 8 fp8 and converts them to 8 bf16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V2I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.f16.bf8\",\n    \"summary\": \"Scales 8 bf8 and converts them to 8 f16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V2I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.f16.fp4\",\n    \"summary\": \"Scales 8 fp4 and converts them to 8 f16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.f16.fp8\",\n    \"summary\": \"Scales 8 fp8 and converts them to 8 f16.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V2I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.f32.bf8\",\n    \"summary\": \"Scales 8 bf8 and converts them to 8 f32.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V2I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.f32.fp4\",\n    \"summary\": \"Scales 8 fp4 and converts them to 8 f32.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scale.pk8.f32.fp8\",\n    \"summary\": \"Scales 8 fp8 and converts them to 8 f32.\",\n    \"description\": \"Available on gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V2I32Type\" },\n      { \"name\": \"scale\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V8F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scaleSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `[` $scaleSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.2xpk16.bf6.f32\",\n    \"summary\": \"Scale and convert two vector<16xf32> to 32 packed bf6\",\n    \"description\": \"Convert 32 single-precision float values, packed into two length-16\\n      vectors that will be logically concanenated, to packedbf6, dividing by the exponent part of `scale`\\n      before doing so.\",\n    \"operands\": [\n      { \"name\": \"src0\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"src1\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $src1 `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.2xpk16.fp6.f32\",\n    \"summary\": \"Scale and convert two vector<16xf32> to 32 packed fp6\",\n    \"description\": \"Convert 32 single-precision float values, packed into two length-16\\n      vectors that will be logically concanenated, to packedfp6, dividing by the exponent part of `scale`\\n      before doing so.\",\n    \"operands\": [\n      { \"name\": \"src0\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"src1\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $src1 `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.f16.bf8\",\n    \"summary\": \"Scaled convert bf8 from packed vector to f16, updating tied result\",\n    \"description\": \"Convert abf8byte from `src`, selected by\\n      `srcSelIndex`, to f16 while multiplying it by the expontent of `scale`,\\n      and place it into the `dstLoHiSel`th bit\\n      of `oldVdst` preserving the other element of that vector in\\n      the return value.\\n\\n      The bytes are stored as an `i32` and not a `<4 x i8>`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2F16Type\" },\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" },\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.f16.fp8\",\n    \"summary\": \"Scaled convert fp8 from packed vector to f16, updating tied result\",\n    \"description\": \"Convert afp8byte from `src`, selected by\\n      `srcSelIndex`, to f16 while multiplying it by the expontent of `scale`,\\n      and place it into the `dstLoHiSel`th bit\\n      of `oldVdst` preserving the other element of that vector in\\n      the return value.\\n\\n      The bytes are stored as an `i32` and not a `<4 x i8>`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2F16Type\" },\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" },\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.f32.bf8\",\n    \"summary\": \"Scaled convert bf8 from packed vector to f32\",\n    \"description\": \"Convert abf8byte from `src`, selected by\\n      `srcSelIndex`, to f32, multiplying it by the exponent of `scale`.\\n\\n      The bytes are stored in an `i32`, not a `<4 x i8>`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.f32.fp8\",\n    \"summary\": \"Scaled convert fp8 from packed vector to f32\",\n    \"description\": \"Convert afp8byte from `src`, selected by\\n      `srcSelIndex`, to f32, multiplying it by the exponent of `scale`.\\n\\n      The bytes are stored in an `i32`, not a `<4 x i8>`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.bf16.bf8\",\n    \"summary\": \"Scaled convert two bf8to two bf16\",\n    \"description\": \"Convert two packedbf8values in `src0` to twobf16values, multiplying by the exponent in `scale`.\\n        The two values to be converted are selected from the low or high half\\n        of `src` (a packed vector represented as an `i32`)\\n        on the basis of `srcLoHiSel`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcLoHiSel `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.bf16.fp4\",\n    \"summary\": \"Scale and convert two packed fp4 to packed bf16\",\n    \"description\": \"Convert two packed fp4 (f4E2M1) values  stored as one byte of a 32-bit integer\\n      to packedbf16, multiplying by the exponent part of `scale`\\n      before doing so.\\n\\n      The byte to convert is chosen by `srcSelIndex`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.bf16.fp8\",\n    \"summary\": \"Scaled convert two fp8to two bf16\",\n    \"description\": \"Convert two packedfp8values in `src0` to twobf16values, multiplying by the exponent in `scale`.\\n        The two values to be converted are selected from the low or high half\\n        of `src` (a packed vector represented as an `i32`)\\n        on the basis of `srcLoHiSel`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2BF16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcLoHiSel `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.bf8.bf16\",\n    \"summary\": \"Scaled convert two bf16to two bf8, updating packed vector\",\n    \"description\": \"Convert twobf16values in `src0` to twobf8bytes, dividing by the exponent in `scale`. The bytes are\\n        packed into a 16-bit value which is inserted into `oldVdst` at the\\n        `dstLoHiSel` position, with the entire updated vector being returned.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2I16Type\" },\n      { \"name\": \"src0\", \"type\": \"ROCDL_V2BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.bf8.f16\",\n    \"summary\": \"Scaled convert two f16to two bf8, updating packed vector\",\n    \"description\": \"Convert twof16values in `src0` to twobf8bytes, dividing by the exponent in `scale`. The bytes are\\n        packed into a 16-bit value which is inserted into `oldVdst` at the\\n        `dstLoHiSel` position, with the entire updated vector being returned.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2I16Type\" },\n      { \"name\": \"src0\", \"type\": \"ROCDL_V2F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.bf8.f32\",\n    \"summary\": \"Scaled convert two f32 to two bf8, updating packed vector\",\n    \"description\": \"Convert two f32 values in `src0` and `src1` to twobf8bytes,\\n      dividing by the exponent in `scale`. The bytes are packed into\\n      a 16-bit value which is inserted into `oldVdst` at the `dstLoHiSel`\\n      position, with the entire updated vector being returned.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2I16Type\" },\n      { \"name\": \"src0\", \"type\": \"F32\" },\n      { \"name\": \"src1\", \"type\": \"F32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  $src0 `,` $src1 `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.f16.bf8\",\n    \"summary\": \"Scaled convert two bf8to two f16\",\n    \"description\": \"Convert two packedbf8values in `src0` to twof16values, multiplying by the exponent in `scale`.\\n        The two values to be converted are selected from the low or high half\\n        of `src` (a packed vector represented as an `i32`)\\n        on the basis of `srcLoHiSel`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcLoHiSel `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.f16.fp4\",\n    \"summary\": \"Scale and convert two packed fp4 to packed f16\",\n    \"description\": \"Convert two packed fp4 (f4E2M1) values  stored as one byte of a 32-bit integer\\n      to packedf16, multiplying by the exponent part of `scale`\\n      before doing so.\\n\\n      The byte to convert is chosen by `srcSelIndex`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.f16.fp8\",\n    \"summary\": \"Scaled convert two fp8to two f16\",\n    \"description\": \"Convert two packedfp8values in `src0` to twof16values, multiplying by the exponent in `scale`.\\n        The two values to be converted are selected from the low or high half\\n        of `src` (a packed vector represented as an `i32`)\\n        on the basis of `srcLoHiSel`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcLoHiSel `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.f32.bf8\",\n    \"summary\": \"Scaled convert two bf8to two f32\",\n    \"description\": \"Convert two packedbf8values in `src0` to twof32values, multiplying by the exponent in `scale`.\\n        The two values to be converted are selected from the low or high half\\n        of `src` (a packed vector represented as an `i32`)\\n        on the basis of `srcLoHiSel`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcLoHiSel `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.f32.fp4\",\n    \"summary\": \"Scale and convert two packed fp4 to packed f32\",\n    \"description\": \"Convert two packed fp4 (f4E2M1) values  stored as one byte of a 32-bit integer\\n      to packedf32, multiplying by the exponent part of `scale`\\n      before doing so.\\n\\n      The byte to convert is chosen by `srcSelIndex`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcSelIndex `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.f32.fp8\",\n    \"summary\": \"Scaled convert two fp8to two f32\",\n    \"description\": \"Convert two packedfp8values in `src0` to twof32values, multiplying by the exponent in `scale`.\\n        The two values to be converted are selected from the low or high half\\n        of `src` (a packed vector represented as an `i32`)\\n        on the basis of `srcLoHiSel`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2F32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"srcLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `[` $srcLoHiSel `]` `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.fp4.bf16\",\n    \"summary\": \"Scale and convert two bf16 to packed fp4, updating tied vector\",\n    \"description\": \"Convert two packedbf16values to packed\\n        fp4, dividing by the exponent part of `scale`\\n        before doing so.\\n\\n        The two scaled values are packed  into a byte.\\n        That byte is used to update the `dstSelIndex`th\\n        byte of `oldVdst`, which is returned in its entirity.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"ROCDL_V2BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.fp4.f16\",\n    \"summary\": \"Scale and convert two f16 to packed fp4, updating tied vector\",\n    \"description\": \"Convert two packedf16values to packed\\n        fp4, dividing by the exponent part of `scale`\\n        before doing so.\\n\\n        The two scaled values are packed  into a byte.\\n        That byte is used to update the `dstSelIndex`th\\n        byte of `oldVdst`, which is returned in its entirity.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"ROCDL_V2F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.fp4.f32\",\n    \"summary\": \"Scale and convert two f32 values to two packed fp4, updating tied vector\",\n    \"description\": \"Convert two single-precision float values, passed in `src0` and `src1`\\n    into two fp4 values, dividing them by the expontent part of `scale`\\n    before doing so.\\n\\n    The two scaled values are packed  into a byte.\\n    That byte is used to update the `dstSelIndex`th\\n    byte of `oldVdst`, which is returned in its entirity.\\n\\n    Example:\\n    ```mlir\\n    // Scaled convert two f32 values to packed fp4 in byte 0 of old.\\n    %0 = rocdl.cvt.scalef32.pk.fp4.f32 %a, %b, %scale -> %old[0] : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"F32\" },\n      { \"name\": \"src1\", \"type\": \"F32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $src1 `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.fp8.bf16\",\n    \"summary\": \"Scaled convert two bf16to two fp8, updating packed vector\",\n    \"description\": \"Convert twobf16values in `src0` to twofp8bytes, dividing by the exponent in `scale`. The bytes are\\n        packed into a 16-bit value which is inserted into `oldVdst` at the\\n        `dstLoHiSel` position, with the entire updated vector being returned.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2I16Type\" },\n      { \"name\": \"src0\", \"type\": \"ROCDL_V2BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.fp8.f16\",\n    \"summary\": \"Scaled convert two f16to two fp8, updating packed vector\",\n    \"description\": \"Convert twof16values in `src0` to twofp8bytes, dividing by the exponent in `scale`. The bytes are\\n        packed into a 16-bit value which is inserted into `oldVdst` at the\\n        `dstLoHiSel` position, with the entire updated vector being returned.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2I16Type\" },\n      { \"name\": \"src0\", \"type\": \"ROCDL_V2F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk.fp8.f32\",\n    \"summary\": \"Scaled convert two f32 to two fp8, updating packed vector\",\n    \"description\": \"Convert two f32 values in `src0` and `src1` to twofp8bytes,\\n      dividing by the exponent in `scale`. The bytes are packed into\\n      a 16-bit value which is inserted into `oldVdst` at the `dstLoHiSel`\\n      position, with the entire updated vector being returned.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"ROCDL_V2I16Type\" },\n      { \"name\": \"src0\", \"type\": \"F32\" },\n      { \"name\": \"src1\", \"type\": \"F32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I16Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstLoHiSel\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  $src0 `,` $src1 `,` $scale `->` $oldVdst `[` $dstLoHiSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk16.bf6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed bf6\",\n    \"description\": \"Convert 8 packedbf16values to packedbf6, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk16.bf6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed bf6\",\n    \"description\": \"Convert 8 packedf16values to packedbf6, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk16.bf6.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed bf6\",\n    \"description\": \"Convert 8 packedf32values to packedbf6, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk16.fp6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp6\",\n    \"description\": \"Convert 8 packedbf16values to packedfp6, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk16.fp6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp6\",\n    \"description\": \"Convert 8 packedf16values to packedfp6, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk16.fp6.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp6\",\n    \"description\": \"Convert 8 packedf32values to packedfp6, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.bf16.bf6\",\n    \"summary\": \"Scale and convert packed bf6 to packed bf16\",\n    \"description\": \"Convert 32 packedbf6values to packedbf16, multiplying by the exponent part of `scale`\\n        before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V6I32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V32BF16Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.bf16.fp6\",\n    \"summary\": \"Scale and convert packed fp6 to packed bf16\",\n    \"description\": \"Convert 32 packedfp6values to packedbf16, multiplying by the exponent part of `scale`\\n        before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V6I32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V32BF16Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.bf6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed bf6\",\n    \"description\": \"Convert 32 packedbf16values to packedbf6, dividing by the exponent part of `scale`\\n          before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.bf6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed bf6\",\n    \"description\": \"Convert 32 packedf16values to packedbf6, dividing by the exponent part of `scale`\\n          before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.f16.bf6\",\n    \"summary\": \"Scale and convert packed bf6 to packed f16\",\n    \"description\": \"Convert 32 packedbf6values to packedf16, multiplying by the exponent part of `scale`\\n        before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V6I32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V32F16Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.f16.fp6\",\n    \"summary\": \"Scale and convert packed fp6 to packed f16\",\n    \"description\": \"Convert 32 packedfp6values to packedf16, multiplying by the exponent part of `scale`\\n        before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V6I32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V32F16Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.f32.bf6\",\n    \"summary\": \"Scale and convert packed bf6 to packed f32\",\n    \"description\": \"Convert 32 packedbf6values to packedf32, multiplying by the exponent part of `scale`\\n        before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V6I32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V32F32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.f32.fp6\",\n    \"summary\": \"Scale and convert packed fp6 to packed f32\",\n    \"description\": \"Convert 32 packedfp6values to packedf32, multiplying by the exponent part of `scale`\\n        before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V6I32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V32F32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.fp6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp6\",\n    \"description\": \"Convert 32 packedbf16values to packedfp6, dividing by the exponent part of `scale`\\n          before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk32.fp6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp6\",\n    \"description\": \"Convert 32 packedf16values to packedfp6, dividing by the exponent part of `scale`\\n          before doing so.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.bf8.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed bf8\",\n    \"description\": \"Convert 8 packedbf16values to packedbf8, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.bf8.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed bf8\",\n    \"description\": \"Convert 8 packedf16values to packedbf8, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.bf8.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed bf8\",\n    \"description\": \"Convert 8 packedf32values to packedbf8, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.fp4.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp4\",\n    \"description\": \"Convert 8 packedbf16values to packedfp4, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.fp4.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp4\",\n    \"description\": \"Convert 8 packedf16values to packedfp4, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.fp4.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp4\",\n    \"description\": \"Convert 8 packedf32values to packedfp4, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.fp8.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp8\",\n    \"description\": \"Convert 8 packedbf16values to packedfp8, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8BF16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.fp8.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp8\",\n    \"description\": \"Convert 8 packedf16values to packedfp8, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F16Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.pk8.fp8.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp8\",\n    \"description\": \"Convert 8 packedf32values to packedfp8, multiplying by the exponent part of `scale`\\n        before doing so. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F32Type\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.bf8.bf16\",\n    \"summary\": \"Scaled convert bf16to bf8 with stochiastic rounding, updating packed vector\",\n    \"description\": \"Convert abf16value in `src0` to abf8bytes, dividing by the exponent in `scale` and using `seed`\\n        for stochiastic rounding. Place the resulting byte in the\\n        `dstSelIndex`th bit of `oldVdst` and return the entire packed vector,\\n        which is stored as an `i32`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"BF16\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.bf8.f16\",\n    \"summary\": \"Scaled convert f16to bf8 with stochiastic rounding, updating packed vector\",\n    \"description\": \"Convert af16value in `src0` to abf8bytes, dividing by the exponent in `scale` and using `seed`\\n        for stochiastic rounding. Place the resulting byte in the\\n        `dstSelIndex`th bit of `oldVdst` and return the entire packed vector,\\n        which is stored as an `i32`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"F16\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.bf8.f32\",\n    \"summary\": \"Scaled convert f32to bf8 with stochiastic rounding, updating packed vector\",\n    \"description\": \"Convert af32value in `src0` to abf8bytes, dividing by the exponent in `scale` and using `seed`\\n        for stochiastic rounding. Place the resulting byte in the\\n        `dstSelIndex`th bit of `oldVdst` and return the entire packed vector,\\n        which is stored as an `i32`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"F32\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.fp8.bf16\",\n    \"summary\": \"Scaled convert bf16to fp8 with stochiastic rounding, updating packed vector\",\n    \"description\": \"Convert abf16value in `src0` to afp8bytes, dividing by the exponent in `scale` and using `seed`\\n        for stochiastic rounding. Place the resulting byte in the\\n        `dstSelIndex`th bit of `oldVdst` and return the entire packed vector,\\n        which is stored as an `i32`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"BF16\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.fp8.f16\",\n    \"summary\": \"Scaled convert f16to fp8 with stochiastic rounding, updating packed vector\",\n    \"description\": \"Convert af16value in `src0` to afp8bytes, dividing by the exponent in `scale` and using `seed`\\n        for stochiastic rounding. Place the resulting byte in the\\n        `dstSelIndex`th bit of `oldVdst` and return the entire packed vector,\\n        which is stored as an `i32`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"F16\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.fp8.f32\",\n    \"summary\": \"Scaled convert f32to fp8 with stochiastic rounding, updating packed vector\",\n    \"description\": \"Convert af32value in `src0` to afp8bytes, dividing by the exponent in `scale` and using `seed`\\n        for stochiastic rounding. Place the resulting byte in the\\n        `dstSelIndex`th bit of `oldVdst` and return the entire packed vector,\\n        which is stored as an `i32`.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src0\", \"type\": \"F32\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src0 `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk.fp4.bf16\",\n    \"summary\": \"Scale and convert two bf16 to packed fp4 with stochiastic rounding, updating tied vector\",\n    \"description\": \"Convert two packedbf16values to packed\\n      fp4, dividing by the exponent part of `scale`\\n      before doing so and using `seed` as the random seed for\\n      stochiastic rounding.\\n\\n      The two scaled values are packed (little-endian)\\n      into a byte. That byte is used to update the `dstSelIndex`th\\n      byte of `oldVdst`, which is returned in its entirity.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"ROCDL_V2BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk.fp4.f16\",\n    \"summary\": \"Scale and convert two f16 to packed fp4 with stochiastic rounding, updating tied vector\",\n    \"description\": \"Convert two packedf16values to packed\\n      fp4, dividing by the exponent part of `scale`\\n      before doing so and using `seed` as the random seed for\\n      stochiastic rounding.\\n\\n      The two scaled values are packed (little-endian)\\n      into a byte. That byte is used to update the `dstSelIndex`th\\n      byte of `oldVdst`, which is returned in its entirity.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"ROCDL_V2F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk.fp4.f32\",\n    \"summary\": \"Scale and convert two f32 to packed fp4 with stochiastic rounding, updating tied vector\",\n    \"description\": \"Convert two packedf32values to packed\\n      fp4, dividing by the exponent part of `scale`\\n      before doing so and using `seed` as the random seed for\\n      stochiastic rounding.\\n\\n      The two scaled values are packed (little-endian)\\n      into a byte. That byte is used to update the `dstSelIndex`th\\n      byte of `oldVdst`, which is returned in its entirity.\",\n    \"operands\": [\n      { \"name\": \"oldVdst\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"ROCDL_V2F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstSelIndex\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `->` $oldVdst `[` $dstSelIndex `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk16.bf6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed bf6 with stochastic rounding\",\n    \"description\": \"Convert 8 packedbf16values to packedbf6, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk16.bf6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed bf6 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf16values to packedbf6, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk16.bf6.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed bf6 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf32values to packedbf6, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk16.fp6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp6 with stochastic rounding\",\n    \"description\": \"Convert 8 packedbf16values to packedfp6, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk16.fp6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp6 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf16values to packedfp6, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk16.fp6.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp6 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf32values to packedfp6, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V16F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V3I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk32.bf6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed bf6 with stochiastic rounding\",\n    \"description\": \"Convert 32 packedbf16values to packedbf6, dividing by the exponent part of `scale`\\n        before doing so and applying random rounding derived from\\n        `seed`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk32.bf6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed bf6 with stochiastic rounding\",\n    \"description\": \"Convert 32 packedf16values to packedbf6, dividing by the exponent part of `scale`\\n        before doing so and applying random rounding derived from\\n        `seed`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk32.bf6.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed bf6 with stochiastic rounding\",\n    \"description\": \"Convert 32 packedf32values to packedbf6, dividing by the exponent part of `scale`\\n        before doing so and applying random rounding derived from\\n        `seed`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk32.fp6.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp6 with stochiastic rounding\",\n    \"description\": \"Convert 32 packedbf16values to packedfp6, dividing by the exponent part of `scale`\\n        before doing so and applying random rounding derived from\\n        `seed`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk32.fp6.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp6 with stochiastic rounding\",\n    \"description\": \"Convert 32 packedf16values to packedfp6, dividing by the exponent part of `scale`\\n        before doing so and applying random rounding derived from\\n        `seed`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk32.fp6.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp6 with stochiastic rounding\",\n    \"description\": \"Convert 32 packedf32values to packedfp6, dividing by the exponent part of `scale`\\n        before doing so and applying random rounding derived from\\n        `seed`.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V32F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V6I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.bf8.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed bf8 with stochastic rounding\",\n    \"description\": \"Convert 8 packedbf16values to packedbf8, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.bf8.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed bf8 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf16values to packedbf8, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.bf8.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed bf8 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf32values to packedbf8, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.fp4.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp4 with stochastic rounding\",\n    \"description\": \"Convert 8 packedbf16values to packedfp4, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.fp4.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp4 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf16values to packedfp4, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.fp4.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp4 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf32values to packedfp4, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.fp8.bf16\",\n    \"summary\": \"Scale and convert packed bf16 to packed fp8 with stochastic rounding\",\n    \"description\": \"Convert 8 packedbf16values to packedfp8, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8BF16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.fp8.f16\",\n    \"summary\": \"Scale and convert packed f16 to packed fp8 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf16values to packedfp8, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F16Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.scalef32.sr.pk8.fp8.f32\",\n    \"summary\": \"Scale and convert packed f32 to packed fp8 with stochastic rounding\",\n    \"description\": \"Convert 8 packedf32values to packedfp8, multiplying by the exponent part of `scale`\\n        before doing so and apply stochastic rounding. This op is for gfx1250+ arch.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"ROCDL_V8F32Type\" },\n      { \"name\": \"seed\", \"type\": \"I32\" },\n      { \"name\": \"scale\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_V2I32Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $src `,` $seed `,` $scale `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.sr.bf8.f32\",\n    \"summary\": \"Convert f32 to bf8, stochiastic rounding\",\n    \"description\": \"Convert `srcA` to bf8, adding the rounding factor from `srcB`,\\n    and store into the `byteSel`th byte of `old`, preserving the others.\\n\\n    Example:\\n    ```mlir\\n    // Stochastic rounding convert f32 to bf8 in byte 2 of old.\\n    %0 = rocdl.cvt.sr.bf8.f32 %val, %stoch -> %old[2] : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"F32\" },\n      { \"name\": \"srcB\", \"type\": \"I32\" },\n      { \"name\": \"old\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"byteSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `,` $srcB `->` $old `[` $byteSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.cvt.sr.fp8.f32\",\n    \"summary\": \"Convert f32 to fp8, stochiastic rounding\",\n    \"description\": \"Convert `srcA` to fp8, adding the rounding factor from `srcB`,\\n    and store into the `byteSel`th byte of `old`, preserving the others.\\n\\n    Example:\\n    ```mlir\\n    // Stochastic rounding convert f32 to fp8 in byte 3 of old.\\n    %0 = rocdl.cvt.sr.fp8.f32 %val, %stoch -> %old[3] : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcA\", \"type\": \"F32\" },\n      { \"name\": \"srcB\", \"type\": \"I32\" },\n      { \"name\": \"old\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"byteSel\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $srcA `,` $srcB `->` $old `[` $byteSel `]` `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds_bpermute\",\n    \"description\": \"Perform a backward permute (pull) operation across lanes using DS/LDS permute hardware.\\n\\n    Each lane reads the value of `src` from the lane whose byte address is\\n    given by `index` (i.e. lane id = `index / 4`).\\n    \\n    This is “backward” (pull) in contrast to `ds_permute_b32`, which is\\n    “forward” (push/scatter).\\n\\n    Example:\\n    ```mlir\\n    // Backward permute across lanes (pull from selected lane).\\n    %0 = rocdl.ds_bpermute %index, %src : (i32, i32) -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$index `,` $src  attr-dict `:` `(` type($index) `,` type($src) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds_swizzle\",\n    \"description\": \"Perform a data-sharing swizzle operation within a wavefront.\\n\\n    The `offset` operand encodes the *swizzle pattern* that will be placed in the\\n    instruction's `offset` field (i.e., the pattern used by `ds_swizzle_b32`).\\n    See https://llvm.org/docs/AMDGPUModifierSyntax.html#swizzle-pattern for\\n    how this 16-bit pattern is constructed.\\n\\n    Example:\\n    ```mlir\\n    // Swizzle data within a wavefront.\\n    %0 = rocdl.ds_swizzle %src, %offset : (i32, i32) -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $offset  attr-dict `:` `(` type($src) `,` type($offset) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.atomic.async.barrier.arrive.b64\",\n    \"description\": \"Waits on a given DS barrier and decrements pending count by -1.\\n    Stays in order with ASYNC loads to LDS, and uses ASYNCcnt to track its completion.\\n    Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Async atomic barrier arrive (fire-and-forget).\\n    rocdl.ds.atomic.async.barrier.arrive.b64 %ptr : !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barrierPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$barrierPtr attr-dict `:` qualified(type($barrierPtr))\"\n  },\n  {\n    \"name\": \"rocdl.ds.atomic.barrier.arrive.rtn.b64\",\n    \"description\": \"Waits on a given DS barrier and decrements its pending count by a given value. Note, the barrier state\\n    is given as a 64-bit structure containing pending count, phase and init count. The op returns the old\\n    barrier state. The op is executed as an ordinary LDS operations and it is ordered with other LDS operations.\\n    Thus, check DSCNT to determine when this instruction has executed.\\n    Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Atomic barrier arrive with return of old barrier state.\\n    %res = rocdl.ds.atomic.barrier.arrive.rtn.b64 %ptr, %val : !llvm.ptr<3>, i64 -> i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"barrierPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"val\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$barrierPtr `,` $val attr-dict `:` qualified(type($barrierPtr)) `,` type($val) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.load.tr16.b128\",\n    \"summary\": \"Loads and transposes a matrix from ds memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of16-bit data from thedsmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a128-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<3>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.load.tr4.b64\",\n    \"summary\": \"Loads and transposes a matrix from ds memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of4-bit data from thedsmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a64-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<3>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.load.tr6.b96\",\n    \"summary\": \"Loads and transposes a matrix from ds memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of6-bit data from thedsmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a96-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<3>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.load.tr8.b64\",\n    \"summary\": \"Loads and transposes a matrix from ds memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of8-bit data from thedsmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a64-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<3>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.read.tr16.b64\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.read.tr4.b64\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.read.tr6.b96\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.ds.read.tr8.b64\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.exp\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.exp%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.exp2\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.exp2%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.flat.prefetch\",\n    \"description\": \"Prefetches 1 byte of data per lane using flat-memory addresses into the WGP-cache or L2-cache.\\n    Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Prefetch from flat memory into cache.\\n    rocdl.flat.prefetch %ptr, scope 0 : !llvm.ptr\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<0>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` `scope` $scope attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"rocdl.fmed3\",\n    \"summary\": \"Median of three float/half values\",\n    \"description\": \"Computes the median of three floating-point values using the AMDGPU fmed3 intrinsic.\\n    This operation is equivalent to `max(min(a, b), min(max(a, b), c))` but uses the\\n    hardware-accelerated V_MED3_F16/V_MED3_F32 instruction for better performance.\\n\\n    The operation supports both scalar and vector floating-point types (f16, f32).\\n\\n    Example:\\n    ```mlir\\n    // Scalar f32 median\\n    %result = rocdl.fmed3 %a, %b, %c : f32\\n\\n    // Vector f16 median\\n    %result = rocdl.fmed3 %va, %vb, %vc : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src0\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"src1\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" },\n      { \"name\": \"src2\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<LLVM_AnyFloat>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'src0', 'src1', 'src2']>\" }\n    ],\n    \"assemblyFormat\": \"$src0 `,` $src1 `,` $src2 attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.global.load.async.lds\",\n    \"summary\": \"Version of rocdl.load.async.to.lds specialized to global pointers\",\n    \"description\": \"This operation works identically to `rocdl.load.async.to.lds` except that the\\n    global pointer argument is limited to pointers in address space 1 (pure global\\n    pointers) instead of also allowing fat buffer pointers.\\n\\n    Available on gfx9 and gfx10.\\n\\n    For the operation introduced in gfx1250, see `rocdl.global.load.async.to.lds.bN`.\\n\\n    Example:\\n    ```mlir\\n    // Async load from global pointer to LDS (address space 1 only).\\n    rocdl.load.async.to.lds %global, %shared, 4, 0, 0 : !llvm.ptr<1>, !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I32Attr\" },\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $size `,` $offset `,` $aux\\n    attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.global.load.async.to.lds.b128\",\n    \"description\": \"Asynchronously loadsbits of data from a global memory pointer\\n      to a Local Data Share (LDS) pointer.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // AsyncbitsVal-bit load from global to LDS.\\n      rocdl.global.load.async.to.lds.b128%src, %dst, 0, 0 : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $aux\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.global.load.async.to.lds.b32\",\n    \"description\": \"Asynchronously loadsbits of data from a global memory pointer\\n      to a Local Data Share (LDS) pointer.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // AsyncbitsVal-bit load from global to LDS.\\n      rocdl.global.load.async.to.lds.b32%src, %dst, 0, 0 : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $aux\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.global.load.async.to.lds.b64\",\n    \"description\": \"Asynchronously loadsbits of data from a global memory pointer\\n      to a Local Data Share (LDS) pointer.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // AsyncbitsVal-bit load from global to LDS.\\n      rocdl.global.load.async.to.lds.b64%src, %dst, 0, 0 : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $aux\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.global.load.async.to.lds.b8\",\n    \"description\": \"Asynchronously loadsbits of data from a global memory pointer\\n      to a Local Data Share (LDS) pointer.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // AsyncbitsVal-bit load from global to LDS.\\n      rocdl.global.load.async.to.lds.b8%src, %dst, 0, 0 : !llvm.ptr<1>, !llvm.ptr<3>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $offset `,` $aux\\n      attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.global.load.lds\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"ROCDLGlobalBuffer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I32Attr\" },\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $size `,` $offset `,` $aux\\n    attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.global.load.tr.b128\",\n    \"summary\": \"Loads and transposes a matrix from global memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of16-bit data from theglobalmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a128-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.global.load.tr.b64\",\n    \"summary\": \"Loads and transposes a matrix from global memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of8-bit data from theglobalmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a64-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.global.load.tr4.b64\",\n    \"summary\": \"Loads and transposes a matrix from global memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of4-bit data from theglobalmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a64-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.global.load.tr6.b96\",\n    \"summary\": \"Loads and transposes a matrix from global memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of6-bit data from theglobalmemory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a96-bit vector register.\\n\\n    Available in gfx1250+.\\n\\n    Example (concrete mnemonics depend on address space and element size):\\n    ```mlir\\n    // 64-bit transpose load from global memory.\\n    %0 = rocdl.global.load.tr4.b64 %ptr : !llvm.ptr<1> -> vector<2xi32>\\n\\n    // 128-bit transpose load from global memory with f16 result.\\n    %1 = rocdl.global.load.tr.b128 %ptr : !llvm.ptr<1> -> vector<8xf16>\\n\\n    // 64-bit transpose load from LDS.\\n    %2 = rocdl.ds.load.tr4.b64 %ptr : !llvm.ptr<3> -> vector<2xi32>\\n\\n    // 128-bit transpose load from LDS with bf16 result.\\n    %3 = rocdl.ds.load.tr16.b128 %ptr : !llvm.ptr<3> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.global.prefetch\",\n    \"description\": \"Prefetches 1 byte of data per lane from global memory into the WGP-cache or L2-cache.\\n    Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Prefetch from global memory into cache.\\n    rocdl.global.prefetch %ptr, scope 0 : !llvm.ptr<1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_PointerInAddressSpace<1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` `scope` $scope attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"rocdl.grid.dim.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.grid.dim.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.grid.dim.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.iglp.opt\",\n    \"description\": \"Instruction-group-level parallelism optimization hint.\\n\\n    Example:\\n    ```mlir\\n    // IGLP optimization hint variant 0.\\n    rocdl.iglp.opt 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"variant\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$variant attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.load.async.to.lds\",\n    \"summary\": \"Gathering load to LDS that requires explicit async memory tracking\",\n    \"description\": \"Load `size` bytes (the valid sizes vary by architecture) from the global memory\\n    pointed to by `globalPtr` and put them at `ldsPtr`, concantenating (and applying\\n    padding for sizes less than 4 bytes, along with padding out 12-byte reads\\n    to 16-byte writes). The value of `globalPtr` can vary between lanes, while\\n    `sharedPtr` must be subgroup-uniform (the values from each lane are concatentated\\n    before being written to LDS with appropriate padding applied.)\\n\\n    `offset` is a constant offset applied to **both** pointers, and `aux` sets the cache\\n    policy. Unlike `rocdl.load.to.lds`, the compiler will not automatically inserts waits\\n    for this load to complete at the point it thinks you're using a region of LDS you've\\n    stored values to - you need to use the `rocdl.asyncmark` and `rocdl.wait.asyncmark`\\n    operations to explicitly group these operations and wait for their completion.\\n\\n    Available on gfx10 and earlier with varying suppported values of `size`.\\n\\n    Example:\\n    ```mlir\\n    // Async load 4 bytes from global pointer to LDS.\\n    rocdl.load.async.to.lds %global, %shared, 4, 0, 0 : !llvm.ptr<1>, !llvm.ptr<3>\\n\\n    // Async load 4 bytes from fat buffer pointer to LDS.\\n    rocdl.load.async.to.lds %fatBuffer, %shared, 4, 0, 0 : !llvm.ptr<7>, !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I32Attr\" },\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $size `,` $offset `,` $aux\\n    attr-dict `:` qualified(type($globalPtr)) `,` qualified(type($ldsPtr))\"\n  },\n  {\n    \"name\": \"rocdl.load.to.lds\",\n    \"operands\": [\n      { \"name\": \"globalPtr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I32Attr\" },\n      { \"name\": \"offset\", \"type\": \"I32Attr\" },\n      { \"name\": \"aux\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$globalPtr `,`  $ldsPtr `,` $size `,` $offset `,` $aux\\n    attr-dict `:` type($globalPtr)\"\n  },\n  {\n    \"name\": \"rocdl.load.tr.b\",\n    \"summary\": \"Loads and transposes a matrix from  memory to registers (available in gfx1250+).\",\n    \"description\": \"Load a matrix of-bit data from thememory,\\n    transpose data between row-major and column-major order,\\n    and store the result into a-bit vector register.\\n\\n    Available in gfx1250+.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"Arg<LLVM_PointerInAddressSpace, , [MemRead]>\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.log\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.log%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.make.buffer.rsrc\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"stride\", \"type\": \"I16\" },\n      { \"name\": \"numRecords\", \"type\": \"I64\" },\n      { \"name\": \"flags\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($base) `to` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.mbcnt.hi\",\n    \"description\": \"Masked bit count of threads below the current lane in a wavefront.\\n\\n    `in0` is a 32-bit mask that is AND-ed with the relevant half of the\\n    execution mask and the bits below the current lane; `in1` is added\\n    to the resulting popcount:\\n\\n    - **lo**: `in1 + popcount(in0 & exec_lo & ((1 << min(lane_id, 32)) - 1))`\\n    - **hi**: `in1 + popcount(in0 & exec_hi & ((1 << saturating_usub(lane_id, 32)) - 1))`\\n\\n    To obtain a unique thread index within a wave64, chain the two ops\\n    with `in0 = -1` (all bits set):\\n\\n    Example:\\n    ```mlir\\n    %all_ones = arith.constant -1 : i32\\n    %zero = arith.constant 0 : i32\\n\\n    // Count active threads below this lane in the low 32 lanes.\\n    %lo = rocdl.mbcnt.lo %all_ones, %zero : (i32, i32) -> i32\\n\\n    // Add the count from the high 32 lanes to get the full lane index.\\n    %hi = rocdl.mbcnt.hi %all_ones, %lo : (i32, i32) -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in0\", \"type\": \"I32\" },\n      { \"name\": \"in1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$in0 `,` $in1  attr-dict `:` `(` type($in0) `,` type($in1) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.mbcnt.lo\",\n    \"description\": \"Masked bit count of threads below the current lane in a wavefront.\\n\\n    `in0` is a 32-bit mask that is AND-ed with the relevant half of the\\n    execution mask and the bits below the current lane; `in1` is added\\n    to the resulting popcount:\\n\\n    - **lo**: `in1 + popcount(in0 & exec_lo & ((1 << min(lane_id, 32)) - 1))`\\n    - **hi**: `in1 + popcount(in0 & exec_hi & ((1 << saturating_usub(lane_id, 32)) - 1))`\\n\\n    To obtain a unique thread index within a wave64, chain the two ops\\n    with `in0 = -1` (all bits set):\\n\\n    Example:\\n    ```mlir\\n    %all_ones = arith.constant -1 : i32\\n    %zero = arith.constant 0 : i32\\n\\n    // Count active threads below this lane in the low 32 lanes.\\n    %lo = rocdl.mbcnt.lo %all_ones, %zero : (i32, i32) -> i32\\n\\n    // Add the count from the high 32 lanes to get the full lane index.\\n    %hi = rocdl.mbcnt.hi %all_ones, %lo : (i32, i32) -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in0\", \"type\": \"I32\" },\n      { \"name\": \"in1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$in0 `,` $in1  attr-dict `:` `(` type($in0) `,` type($in1) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x16bf16.1k\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x16bf16.1k%a0, %b0, %c0, 0, 0, 0 : (vector<4xi16>,vector<4xi16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x16f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x16f16%a0, %b0, %c0, 0, 0, 0 : (vector<4xf16>,vector<4xf16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x1f32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x1f32%a0, %b0, %c0, 0, 0, 0 : (f32,f32,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x2bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x2bf16%a0, %b0, %c0, 0, 0, 0 : (vector<2xi16>,vector<2xi16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x32.bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x32.bf16%a0, %b0, %c0, 0, 0, 0 : (vector<8xbf16>,vector<8xbf16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<BF16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<BF16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x32.bf8.bf8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x32.bf8.bf8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x32.bf8.fp8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x32.bf8.fp8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x32.f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x32.f16%a0, %b0, %c0, 0, 0, 0 : (vector<8xf16>,vector<8xf16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x32.fp8.bf8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x32.fp8.bf8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x32.fp8.fp8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x32.fp8.fp8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x4bf16.1k\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x4bf16.1k%a0, %b0, %c0, 0, 0, 0 : (vector<4xi16>,vector<4xi16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x4f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x4f16%a0, %b0, %c0, 0, 0, 0 : (vector<4xf16>,vector<4xf16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x4f32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x4f32%a0, %b0, %c0, 0, 0, 0 : (f32,f32,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x8.xf32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x8.xf32%a0, %b0, %c0, 0, 0, 0 : (vector<2xf32>,vector<2xf32>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F32, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.16x16x8bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.16x16x8bf16%a0, %b0, %c0, 0, 0, 0 : (vector<2xi16>,vector<2xi16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x16.bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x16.bf16%a0, %b0, %c0, 0, 0, 0 : (vector<8xbf16>,vector<8xbf16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<BF16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<BF16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x16.bf8.bf8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x16.bf8.bf8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x16.bf8.fp8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x16.bf8.fp8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x16.f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x16.f16%a0, %b0, %c0, 0, 0, 0 : (vector<8xf16>,vector<8xf16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x16.fp8.bf8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x16.fp8.bf8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x16.fp8.fp8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x16.fp8.fp8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x1f32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x1f32%a0, %b0, %c0, 0, 0, 0 : (f32,f32,vector<32xf32>) ->vector<32xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x2bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x2bf16%a0, %b0, %c0, 0, 0, 0 : (vector<2xi16>,vector<2xi16>,vector<32xf32>) ->vector<32xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x2f32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x2f32%a0, %b0, %c0, 0, 0, 0 : (f32,f32,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x4.xf32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x4.xf32%a0, %b0, %c0, 0, 0, 0 : (vector<2xf32>,vector<2xf32>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F32, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x4bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x4bf16%a0, %b0, %c0, 0, 0, 0 : (vector<2xi16>,vector<2xi16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x4bf16.1k\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x4bf16.1k%a0, %b0, %c0, 0, 0, 0 : (vector<4xi16>,vector<4xi16>,vector<32xf32>) ->vector<32xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x4f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x4f16%a0, %b0, %c0, 0, 0, 0 : (vector<4xf16>,vector<4xf16>,vector<32xf32>) ->vector<32xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x8bf16.1k\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x8bf16.1k%a0, %b0, %c0, 0, 0, 0 : (vector<4xi16>,vector<4xi16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.32x32x8f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.32x32x8f16%a0, %b0, %c0, 0, 0, 0 : (vector<4xf16>,vector<4xf16>,vector<16xf32>) ->vector<16xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.4x4x1f32\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.4x4x1f32%a0, %b0, %c0, 0, 0, 0 : (f32,f32,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.4x4x2bf16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.4x4x2bf16%a0, %b0, %c0, 0, 0, 0 : (vector<2xi16>,vector<2xi16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 2>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.4x4x4bf16.1k\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.4x4x4bf16.1k%a0, %b0, %c0, 0, 0, 0 : (vector<4xi16>,vector<4xi16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f32.4x4x4f16\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f32.4x4x4f16%a0, %b0, %c0, 0, 0, 0 : (vector<4xf16>,vector<4xf16>,vector<4xf32>) ->vector<4xf32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f64.16x16x4f64\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f64.16x16x4f64%a0, %b0, %c0, 0, 0, 0 : (f64,f64,vector<4xf64>) ->vector<4xf64>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F64, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F64, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.f64.4x4x4f64\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.f64.4x4x4f64%a0, %b0, %c0, 0, 0, 0 : (f64,f64,f64) ->f64```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<F64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<F64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_Scalar<F64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_Scalar<F64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.16x16x16i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.16x16x16i8%a0, %b0, %c0, 0, 0, 0 : (i32,i32,vector<4xi32>) ->vector<4xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.16x16x32.i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.16x16x32.i8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<4xi32>) ->vector<4xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.16x16x4i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.16x16x4i8%a0, %b0, %c0, 0, 0, 0 : (i32,i32,vector<16xi32>) ->vector<16xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.16x16x64.i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.16x16x64.i8%a0, %b0, %c0, 0, 0, 0 : (vector<4xi32>,vector<4xi32>,vector<4xi32>) ->vector<4xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.32x32x16.i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.32x32x16.i8%a0, %b0, %c0, 0, 0, 0 : (i64,i64,vector<16xi32>) ->vector<16xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I64>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.32x32x32.i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.32x32x32.i8%a0, %b0, %c0, 0, 0, 0 : (vector<4xi32>,vector<4xi32>,vector<16xi32>) ->vector<16xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.32x32x4i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.32x32x4i8%a0, %b0, %c0, 0, 0, 0 : (i32,i32,vector<32xi32>) ->vector<32xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.32x32x8i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.32x32x8i8%a0, %b0, %c0, 0, 0, 0 : (i32,i32,vector<16xi32>) ->vector<16xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.i32.4x4x4i8\",\n    \"description\": \"Matrix fused multiply-add (MFMA) intrinsic. Computes `D = A * B + C`\\n    with matrix operands. The `cbsz`, `abid`, and `blgp` attributes control\\n    broadcast and block layout modes.\\n\\n    Example:\\n    ```mlir\\n    %r0 =mfma.i32.4x4x4i8%a0, %b0, %c0, 0, 0, 0 : (i32,i32,vector<4xi32>) ->vector<4xi32>```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_Scalar<I32>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $abid `,` $blgp attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.scale.f32.16x16x128.f8f6f4\",\n    \"description\": \"Scaled matrix fused multiply-add (MFMA) intrinsic with per-operand scaling.\\n    The `opselA`/`opselB` and `scaleA`/`scaleB` arguments control the scaling\\n    of input operands.\\n\\n    Example:\\n    ```mlir\\n    // Scaled MFMA with fp8 * fp8 inputs.\\n    %r0 = rocdl.mfma.scale.f32.32x32x64.f8f6f4 %a, %a, %c, 0, 0, 0, %scaleA, 0, %scaleB :\\n      (vector<8xi32>, vector<8xi32>, vector<16xf32>, i32, i32) -> vector<16xf32>\\n\\n    // Scaled MFMA with fp8 * bf8 inputs.\\n    %r1 = rocdl.mfma.scale.f32.32x32x64.f8f6f4 %a, %a, %c, 0, 1, 0, %scaleA, 0, %scaleB :\\n      (vector<8xi32>, vector<8xi32>, vector<16xf32>, i32, i32) -> vector<16xf32>\\n\\n    // Scaled MFMA with fp8 * fp6 inputs (6xi32 operand B).\\n    %r2 = rocdl.mfma.scale.f32.32x32x64.f8f6f4 %a, %b6, %c, 0, 2, 0, %scaleA, 0, %scaleB :\\n      (vector<8xi32>, vector<6xi32>, vector<16xf32>, i32, i32) -> vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_VectorOf<I32>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_VectorOf<I32>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_VectorOf<F32>\" },\n      { \"name\": \"scaleA\", \"type\": \"I32\" },\n      { \"name\": \"scaleB\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" },\n      { \"name\": \"opselA\", \"type\": \"I32Attr\" },\n      { \"name\": \"opselB\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $blgp `,` $opselA `,` $scaleA `,` $opselB `,` $scaleB attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.mfma.scale.f32.32x32x64.f8f6f4\",\n    \"description\": \"Scaled matrix fused multiply-add (MFMA) intrinsic with per-operand scaling.\\n    The `opselA`/`opselB` and `scaleA`/`scaleB` arguments control the scaling\\n    of input operands.\\n\\n    Example:\\n    ```mlir\\n    // Scaled MFMA with fp8 * fp8 inputs.\\n    %r0 = rocdl.mfma.scale.f32.32x32x64.f8f6f4 %a, %a, %c, 0, 0, 0, %scaleA, 0, %scaleB :\\n      (vector<8xi32>, vector<8xi32>, vector<16xf32>, i32, i32) -> vector<16xf32>\\n\\n    // Scaled MFMA with fp8 * bf8 inputs.\\n    %r1 = rocdl.mfma.scale.f32.32x32x64.f8f6f4 %a, %a, %c, 0, 1, 0, %scaleA, 0, %scaleB :\\n      (vector<8xi32>, vector<8xi32>, vector<16xf32>, i32, i32) -> vector<16xf32>\\n\\n    // Scaled MFMA with fp8 * fp6 inputs (6xi32 operand B).\\n    %r2 = rocdl.mfma.scale.f32.32x32x64.f8f6f4 %a, %b6, %c, 0, 2, 0, %scaleA, 0, %scaleB :\\n      (vector<8xi32>, vector<6xi32>, vector<16xf32>, i32, i32) -> vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_VectorOf<I32>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_VectorOf<I32>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_VectorOf<F32>\" },\n      { \"name\": \"scaleA\", \"type\": \"I32\" },\n      { \"name\": \"scaleB\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"blgp\", \"type\": \"I32Attr\" },\n      { \"name\": \"opselA\", \"type\": \"I32Attr\" },\n      { \"name\": \"opselB\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $cbsz `,` $blgp `,` $opselA `,` $scaleA `,` $opselB `,` $scaleB attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.permlane16.swap\",\n    \"description\": \"Performs a `permlane16.swap` operation with the given operands, applying the\\n    permutation specified by $fi to the provided inputs.\\n\\n    Example:\\n    ```mlir\\n    // Swap lanes between groups of 16 threads.\\n    %res = rocdl.permlane16.swap %src, %src, 0, -1 : (i32, i32) -> !llvm.struct<(i32, i32)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"old\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcretePair<I32, I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fi\", \"type\": \"I1Attr\" },\n      { \"name\": \"boundControl\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $old `,` $src `,` $fi `,` $boundControl `:` `(` type($old) `,` type($src) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.permlane32.swap\",\n    \"description\": \"Performs a `permlane32.swap` operation with the given operands, applying the\\n    permutation specified by $fi to the provided inputs.\\n\\n    Example:\\n    ```mlir\\n    // Swap lanes between groups of 32 threads.\\n    %res = rocdl.permlane32.swap %src, %src, 0, -1 : (i32, i32) -> !llvm.struct<(i32, i32)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"old\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcretePair<I32, I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fi\", \"type\": \"I1Attr\" },\n      { \"name\": \"boundControl\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $old `,` $src `,` $fi `,` $boundControl `:` `(` type($old) `,` type($src) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.permlanex16\",\n    \"description\": \"Performs a `permlanex16` operation with the given operands, applying the\\n    permutation specified by $fi to the provided inputs.\\n\\n    Example:\\n    ```mlir\\n    // Scalar permlanex16.\\n    %ret0 = rocdl.permlanex16 %src0, %src0, %sel, %sel, 0, -1 : f32, i32\\n\\n    // Vector permlanex16.\\n    %ret1 = rocdl.permlanex16 %src1, %src1, %sel, %sel, 0, -1 : vector<2xf32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"old\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"src0\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"src1\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"src2\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fi\", \"type\": \"I1Attr\" },\n      { \"name\": \"boundControl\", \"type\": \"I1Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'old', 'src0']>\" },\n      { \"type\": \"AllTypesMatch<['src1', 'src2']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $old `,` $src0 `,` $src1 `,` $src2 `,` $fi `,` $boundControl `:` type($src0) `,` type($src1)\"\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.atomic.cmpswap\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"cmp\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'src', 'cmp']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `(` operands `)` `:` type($res) `,` type($rsrc)\"\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.atomic.fadd\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"soffset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"aux\", \"type\": \"LLVM_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.atomic.fmax\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"soffset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"aux\", \"type\": \"LLVM_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.atomic.smax\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"soffset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"aux\", \"type\": \"LLVM_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.atomic.umin\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"soffset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"aux\", \"type\": \"LLVM_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.load\",\n    \"operands\": [\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"soffset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"aux\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"rocdl.raw.buffer.store\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"offset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"soffset\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"aux\", \"type\": \"LLVM_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.atomic.cmpswap\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"cmp\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'src', 'cmp']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.atomic.fadd\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vdata)\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.atomic.fmax\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vdata)\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.atomic.smax\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vdata)\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.atomic.umin\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vdata)\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.load\",\n    \"operands\": [\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.load.async.lds\",\n    \"summary\": \"Async variant of raw.ptr.buffer.load.lds\",\n    \"description\": \"Load from a buffer resource `rsrc` to `ldsPtr`, which must be uniform.\\n\\n    See `rocdl.load.async.to.lds` for overall semantics of such loads, noting that\\n    here `voffset` can be lane-varying and that `rsrc` (which holds the base addres)\\n    must, as always, be uniform.\\n\\n    Available on gfx9 and gfx10.\\n\\n    Example:\\n    ```mlir\\n    // Async buffer load to LDS via buffer resource pointer.\\n    rocdl.raw.ptr.buffer.load.async.lds %rsrc, %ldsPtr, %size, %voffset, %soffset, %offset, %aux\\n    ```\",\n    \"operands\": [\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"voffset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.load.lds\",\n    \"operands\": [\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"ldsPtr\", \"type\": \"ROCDLBufferLDS\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"voffset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.raw.ptr.buffer.store\",\n    \"operands\": [\n      { \"name\": \"vdata\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"rsrc\", \"type\": \"ROCDLBufferRsrc\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"soffset\", \"type\": \"I32\" },\n      { \"name\": \"aux\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vdata)\"\n  },\n  {\n    \"name\": \"rocdl.rcp\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.rcp%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.readfirstlane\",\n    \"summary\": \"Get the value in first active lane.\",\n    \"description\": \"Returns the value in the lowest active lane of the input operand.\\n\\n    Example:\\n    ```mlir\\n    // Scalar readfirstlane.\\n    %0 = rocdl.readfirstlane %src0 : f32\\n\\n    // Vector readfirstlane.\\n    %1 = rocdl.readfirstlane %src1 : vector<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.readlane\",\n    \"summary\": \"Get the value in the specific lane.\",\n    \"description\": \"Get the value in lane `src1` from input `src0`.\\n\\n    Example:\\n    ```mlir\\n    // Scalar readlane.\\n    %0 = rocdl.readlane %src0, %idx : (f32, i32) -> f32\\n\\n    // Vector readlane.\\n    %1 = rocdl.readlane %src1, %idx : (vector<2xf32>, i32) -> vector<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src0\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"src1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'src0']>\" }\n    ],\n    \"assemblyFormat\": \"$src0 `,` $src1  attr-dict `:` `(` type($src0) `,` type($src1) `)` `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.rsq\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.rsq%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier\",\n    \"description\": \"Insert a workgroup barrier without memory fences.\\n\\n    Available on gfx9 and later but deprecated on gfx12+; see\\n    `rocdl.s.barrier.signal` and `rocdl.s.barrier.wait` instead.\\n\\n    Example:\\n    ```mlir\\n    // Synchronize threads within a workgroup.\\n    rocdl.s.barrier\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.init\",\n    \"description\": \"Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Initialize a named barrier with member count.\\n    rocdl.s.barrier.init %ptr member_cnt = 1 : !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memberCnt\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$ptr `member_cnt` `=` $memberCnt attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.join\",\n    \"description\": \"Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Join a named barrier.\\n    rocdl.s.barrier.join %ptr : !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.leave\",\n    \"description\": \"Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Leave a named barrier by id.\\n    rocdl.s.barrier.leave id = 1\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"`id` `=` $id attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.signal\",\n    \"description\": \"Signal a barrier by id. Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Signal barrier with id -1 (all barriers).\\n    rocdl.s.barrier.signal id = -1\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`id` `=` $id attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.signal.isfirst\",\n    \"description\": \"Available on gfx1200+.\\n\\n    Example:\\n    ```mlir\\n    // Signal barrier and check if this wave is first to arrive.\\n    %0 = rocdl.s.barrier.signal.isfirst id = 1 -> i1\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`id` `=` $id attr-dict `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.signal.var\",\n    \"description\": \"Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Signal a named barrier with variable ID.\\n    rocdl.s.barrier.signal.var %ptr member_cnt = 1 : !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memberCnt\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$ptr `member_cnt` `=` $memberCnt attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"rocdl.s.barrier.wait\",\n    \"description\": \"Wait on a barrier by id. Available on gfx1200+.\\n\\n    Example:\\n    ```mlir\\n    // Wait on barrier with id -1 (all barriers).\\n    rocdl.s.barrier.wait id = -1\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"`id` `=` $id attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.get.barrier.state\",\n    \"description\": \"Available on gfx1200+.\\n\\n    Example:\\n    ```mlir\\n    // Query barrier state by id.\\n    %0 = rocdl.s.get.barrier.state id = 1 -> i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`id` `=` $id attr-dict `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.s.get.named.barrier.state\",\n    \"description\": \"Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Query named barrier state by pointer.\\n    %0 = rocdl.s.get.named.barrier.state %ptr : !llvm.ptr<3> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr)) `->` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.s.nop\",\n    \"description\": \"Insert a number of NOP cycles.\\n\\n    Example:\\n    ```mlir\\n    // Insert a no-op.\\n    rocdl.s.nop 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $count\"\n  },\n  {\n    \"name\": \"rocdl.s.setprio\",\n    \"description\": \"Set the wavefront scheduling priority.\\n\\n    Example:\\n    ```mlir\\n    // Set priority to 0.\\n    rocdl.s.setprio 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"priority\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$priority attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.sleep\",\n    \"description\": \"Sleep for a number of clock cycles.\\n\\n    Example:\\n    ```mlir\\n    // Sleep for a minimum duration.\\n    rocdl.s.sleep 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $count\"\n  },\n  {\n    \"name\": \"rocdl.s.wait.asynccnt\",\n    \"summary\": \"Wait until ASYNCCNT is less than or equal to `count`\",\n    \"description\": \"Wait for the counter specified to be less-than or equal-to the `count`\\n      before continuing.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // Wait for async counter to drain.\\n      rocdl.s.wait.asynccnt 0\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.wait.dscnt\",\n    \"summary\": \"Wait until DSCNT is less than or equal to `count`\",\n    \"description\": \"Wait for the counter specified to be less-than or equal-to the `count`\\n      before continuing.\\n\\n      Available on gfx12+.\\n\\n      Example:\\n      ```mlir\\n      // Wait for data-sharing counter to drain.\\n      rocdl.s.wait.dscnt 0\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.wait.expcnt\",\n    \"summary\": \"Wait until EXPCNT is less than or equal to `count`\",\n    \"description\": \"Wait for the counter specified to be less-than or equal-to the `count`\\n      before continuing.\\n\\n      Available on gfx12+.\\n\\n      Example:\\n      ```mlir\\n      // Wait for export counter to drain.\\n      rocdl.s.wait.expcnt 0\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.wait.loadcnt\",\n    \"summary\": \"Wait until LOADCNT is less than or equal to `count`\",\n    \"description\": \"Wait for the counter specified to be less-than or equal-to the `count`\\n      before continuing.\\n\\n      Available on gfx12+.\\n\\n      Example:\\n      ```mlir\\n      // Wait for load counter to drain.\\n      rocdl.s.wait.loadcnt 0\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.wait.storecnt\",\n    \"summary\": \"Wait until STORECNT is less than or equal to `count`\",\n    \"description\": \"Wait for the counter specified to be less-than or equal-to the `count`\\n      before continuing.\\n\\n      Available on gfx12+.\\n\\n      Example:\\n      ```mlir\\n      // Wait for store counter to drain.\\n      rocdl.s.wait.storecnt 0\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.wait.tensorcnt\",\n    \"summary\": \"Wait until TENSORCNT is less than or equal to `count`\",\n    \"description\": \"Wait for the counter specified to be less-than or equal-to the `count`\\n      before continuing.\\n\\n      Available on gfx1250+.\\n\\n      Example:\\n      ```mlir\\n      // Wait for tensor counter to drain.\\n      rocdl.s.wait.tensorcnt 0\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.s.waitcnt\",\n    \"description\": \"Wait for outstanding memory operations to complete, as specified by a\\n    bitfield whose semantics depend on the target chipset.\\n\\n    Example:\\n    ```mlir\\n    // Wait for all counters to reach zero.\\n    rocdl.s.waitcnt 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"bitfield\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $bitfield\"\n  },\n  {\n    \"name\": \"rocdl.s.wakeup.barrier\",\n    \"description\": \"Wakes up waves associated with a given named barrier. Note, This op does not release waves waiting\\n    at the barrier. It just signal other waves in the same work-group waiting on the indicated named barrier\\n    to wake up.\\n    Available on gfx1250+.\\n\\n    Example:\\n    ```mlir\\n    // Wake up waves waiting on a named barrier.\\n    rocdl.s.wakeup.barrier %ptr : !llvm.ptr<3>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"ROCDLBufferLDS\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` qualified(type($ptr))\"\n  },\n  {\n    \"name\": \"rocdl.sched.barrier\",\n    \"description\": \"Insert a scheduling barrier with the given mask. The mask is a\\n    bitfield that controls which instruction types may be scheduled\\n    across the barrier (e.g. `0x0000` = no instructions may cross,\\n    `0x0001` = ALU only, `0x0010` = all VMEM, etc.). See\\n    https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsAMDGPU.td#L349\\n    for the full list of mask values.\\n\\n    Example:\\n    ```mlir\\n    // Scheduling barrier with mask 0.\\n    rocdl.sched.barrier 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"mask\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$mask attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.sched.group.barrier\",\n    \"description\": \"Insert a scheduling group barrier.\\n\\n    Example:\\n    ```mlir\\n    // Schedule group barrier with mask, size, and group id.\\n    rocdl.sched.group.barrier 8, 1, 0\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"size\", \"type\": \"I32Attr\" },\n      { \"name\": \"groupId\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$mask `,` $size `,` $groupId attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.sin\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.sin%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x128.bf8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x128.bf8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x128.fp8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x128.fp8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x32.bf16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x32.f16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x64.bf16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<BF16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<BF16, 16>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x64.bf8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x64.bf8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x64.f16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 16>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x64.fp8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.16x16x64.fp8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x16.bf16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x16.f16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x32.bf16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<BF16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<BF16, 16>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x32.bf8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x32.bf8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x32.f16\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<F16, 8>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<F16, 16>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x32.fp8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x32.fp8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x64.bf8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x64.bf8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x64.fp8.bf8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.f32.32x32x64.fp8.fp8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<F32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.i32.16x16x128.i8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.i32.16x16x64.i8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.i32.32x32x32.i8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 2>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.smfmac.i32.32x32x64.i8\",\n    \"description\": \"Sparse matrix fused multiply-accumulate (SMFMAC) intrinsic with 2:4\\n    structured sparsity. The `index` operand provides the sparsity metadata,\\n    and `cbsz`/`abid` control broadcast modes.\\n\\n    Example:\\n    ```mlir\\n    // SMFMAC with f16 inputs.\\n    %r0 = rocdl.smfmac.f32.16x16x32.f16 %a0, %b0, %c0, %idx, 0, 0 :\\n      (vector<4xf16>, vector<8xf16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with bf16 inputs.\\n    %r1 = rocdl.smfmac.f32.16x16x32.bf16 %a1, %b1, %c0, %idx, 0, 0 :\\n      (vector<4xi16>, vector<8xi16>, vector<4xf32>, i32) -> vector<4xf32>\\n\\n    // SMFMAC with i8 inputs and i32 accumulator.\\n    %r2 = rocdl.smfmac.i32.16x16x64.i8 %a2, %b2, %c2, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xi32>, i32) -> vector<4xi32>\\n\\n    // SMFMAC with fp8 inputs.\\n    %r3 = rocdl.smfmac.f32.16x16x64.fp8.fp8 %a2, %b2, %c0, %idx, 0, 0 :\\n      (vector<2xi32>, vector<4xi32>, vector<4xf32>, i32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"ROCDL_ConcreteVector<I32, 4>\" },\n      { \"name\": \"b\", \"type\": \"ROCDL_ConcreteVector<I32, 8>\" },\n      { \"name\": \"c\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"ROCDL_ConcreteVector<I32, 16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cbsz\", \"type\": \"I32Attr\" },\n      { \"name\": \"abid\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index `,` $cbsz `,` $abid attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.sqrt\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.sqrt%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.bf16.16x16x32.bf16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_VectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_VectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_VectorOf<AnyInteger>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_VectorOf<AnyInteger>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.bf16.16x16x64.bf16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.bf16f32.16x16x64.bf16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f16.16x16x128.bf8.bf8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f16.16x16x128.bf8.fp8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f16.16x16x128.fp8.bf8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f16.16x16x128.fp8.fp8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f16.16x16x32.f16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_VectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_VectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_VectorOf<F16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_VectorOf<F16>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f16.16x16x64.f16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x128.bf8.bf8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x128.bf8.fp8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x128.fp8.bf8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x128.fp8.fp8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x32.bf16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_VectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_VectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_VectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_VectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x32.bf8.bf8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x32.bf8.fp8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x32.f16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_VectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_VectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_VectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_VectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x32.fp8.bf8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x32.fp8.fp8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x64.bf16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.f32.16x16x64.f16\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.i32.16x16x128.iu8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.i32.16x16x32.iu4\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.i32.16x16x32.iu8\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.swmmac.i32.16x16x64.iu4\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $index attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.tanh\",\n    \"description\": \"Note: In the general case, prefer the conventional `arith`, `math`, or `llvm` ops over this.\\n    Use this ROCDL-specific operation only when you fully understand its implication and\\n    when it is strictly necessary. This op is usually chosen when a small loss in precision is\\n    acceptable in exchange for higher execution speed.\\n\\n    Example:\\n    ```mlir\\n    %0 = rocdl.tanh%a f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"$arg qualified(type($arg)) attr-dict `->` qualified(type($res))\"\n  },\n  {\n    \"name\": \"rocdl.tensor.load.to.lds\",\n    \"summary\": \"Base class for ROCDL tensor load/store to/from LDS.\",\n    \"description\": \"Moves tiles of tensor data between global memory and LDS. The tile is\\n    described by the $dgroup descriptors. 5 $dgroup descriptors allows for\\n    movement of up to 5D tensors. $cachePolicy describes the memory scope and an\\n    indicator of expected data re-use.\\n\\n    This op is for gfx1250+ architectures.\\n\\n    Example:\\n    ```mlir\\n    // Tensor load from global memory to LDS using 4 descriptor groups.\\n    rocdl.tensor.load.to.lds %dg0, %dg1, %dg2, %dg3 cachepolicy 0 : vector<4xi32>, vector<8xi32>\\n\\n    // Tensor store from LDS to global memory using 4 descriptor groups.\\n    rocdl.tensor.store.from.lds %dg0, %dg1, %dg2, %dg3 cachepolicy 0 : vector<4xi32>, vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dgroup0\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup1\", \"type\": \"ROCDL_V8I32Type\" },\n      { \"name\": \"dgroup2\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup3\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup4\", \"type\": \"ROCDL_V8I32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cachePolicy\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict operands `cachepolicy` $cachePolicy `:` type($dgroup0) `,` type($dgroup1)\"\n  },\n  {\n    \"name\": \"rocdl.tensor.load.to.lds.d2\",\n    \"summary\": \"Base class for ROCDL tensor load/store to/from LDS (D2 variant).\",\n    \"description\": \"Moves tiles of tensor data between global memory and LDS. The tile is\\n    described by the $dgroup descriptors. 2 $dgroup descriptors allows for\\n    movement of up to 2D tensors. $cachePolicy describes the memory scope and an\\n    indicator of expected data re-use.\\n\\n    This op is for gfx1250+ architectures.\",\n    \"operands\": [\n      { \"name\": \"dgroup0\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup1\", \"type\": \"ROCDL_V8I32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cachePolicy\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict operands `cachepolicy` $cachePolicy `:` type($dgroup0) `,` type($dgroup1)\"\n  },\n  {\n    \"name\": \"rocdl.tensor.store.from.lds\",\n    \"summary\": \"Base class for ROCDL tensor load/store to/from LDS.\",\n    \"description\": \"Moves tiles of tensor data between global memory and LDS. The tile is\\n    described by the $dgroup descriptors. 5 $dgroup descriptors allows for\\n    movement of up to 5D tensors. $cachePolicy describes the memory scope and an\\n    indicator of expected data re-use.\\n\\n    This op is for gfx1250+ architectures.\\n\\n    Example:\\n    ```mlir\\n    // Tensor load from global memory to LDS using 4 descriptor groups.\\n    rocdl.tensor.load.to.lds %dg0, %dg1, %dg2, %dg3 cachepolicy 0 : vector<4xi32>, vector<8xi32>\\n\\n    // Tensor store from LDS to global memory using 4 descriptor groups.\\n    rocdl.tensor.store.from.lds %dg0, %dg1, %dg2, %dg3 cachepolicy 0 : vector<4xi32>, vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dgroup0\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup1\", \"type\": \"ROCDL_V8I32Type\" },\n      { \"name\": \"dgroup2\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup3\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup4\", \"type\": \"ROCDL_V8I32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cachePolicy\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict operands `cachepolicy` $cachePolicy `:` type($dgroup0) `,` type($dgroup1)\"\n  },\n  {\n    \"name\": \"rocdl.tensor.store.from.lds.d2\",\n    \"summary\": \"Base class for ROCDL tensor load/store to/from LDS (D2 variant).\",\n    \"description\": \"Moves tiles of tensor data between global memory and LDS. The tile is\\n    described by the $dgroup descriptors. 2 $dgroup descriptors allows for\\n    movement of up to 2D tensors. $cachePolicy describes the memory scope and an\\n    indicator of expected data re-use.\\n\\n    This op is for gfx1250+ architectures.\",\n    \"operands\": [\n      { \"name\": \"dgroup0\", \"type\": \"ROCDL_V4I32Type\" },\n      { \"name\": \"dgroup1\", \"type\": \"ROCDL_V8I32Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cachePolicy\", \"type\": \"I32Attr\" },\n      { \"name\": \"alias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"noalias_scopes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_AliasScopeAttr>>\" },\n      { \"name\": \"tbaa\", \"type\": \"OptionalAttr<TypedArrayAttrBase<LLVM_TBAATagAttr>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict operands `cachepolicy` $cachePolicy `:` type($dgroup0) `,` type($dgroup1)\"\n  },\n  {\n    \"name\": \"rocdl.update.dpp\",\n    \"operands\": [\n      { \"name\": \"old\", \"type\": \"LLVM_Type\" },\n      { \"name\": \"src\", \"type\": \"LLVM_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dppCtrl\", \"type\": \"I32Attr\" },\n      { \"name\": \"rowMask\", \"type\": \"I32Attr\" },\n      { \"name\": \"bankMask\", \"type\": \"I32Attr\" },\n      { \"name\": \"boundCtrl\", \"type\": \"I1Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['res', 'src', 'old']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $old `,` $src `with` $dppCtrl `,` $rowMask `,` $bankMask `,` $boundCtrl `:` type($src)\"\n  },\n  {\n    \"name\": \"rocdl.wait.asyncmark\",\n    \"summary\": \"Wait until N or fewer async operation groups are unexecuted\",\n    \"description\": \"This operation, along with `rocdl.asyncmark`, forms the compiler-provided\\n      framework for explicitly tracking asynchronous operations.\\n\\n      At the point where a wait.asyncmark operation is executed, all async operations\\n      that were parts of any async group (established by asyncmark in program order)\\n      other than the `count` previously-added ones will have finished executing.\\n\\n      For more detail, including on how this mechanism composes with function calls,\\n      see [the LLVM documentation on async tracking](/llvm/docs/AMDGPUAsyncOperations.rst).\\n\\n      Available on gfx9 and later.\\n\\n      Example:\\n      ```mlir\\n      // Wait until at most N async groups remain outstanding.\\n      rocdl.wait.asyncmark 1\\n      ```\\n\\n      Usage example:\\n      ```mlir\\n      rocdl.tensor.load.to.lds ...\\n      rocdl.global.async.load.to.lds ...\\n\\n      rocdl.asyncmark\\n\\n      rocdl.tensor.load.to.lds ...\\n      rocdl.global.async.load.to.lds ...\\n\\n      rocdl.asyncmark\\n\\n      rocdl.wait.asyncmark 1 // First group of loads completes after this\\n      ```\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I16Attr\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"rocdl.wave.id\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.wavefrontsize\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.bf16.16x16x16.bf16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with output operand selection.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f16 with opsel control.\\n    %r = rocdl.wmma.f16.16x16x16.f16 %a, %b, %c {opsel = false} :\\n      (vector<16xf16>, vector<16xf16>, vector<16xf16>) -> vector<16xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"opsel\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.bf16.16x16x32.bf16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with sign, modC, and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with f16 inputs and reuse controls.\\n    %r = rocdl.wmma.f32.16x16x32.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.bf16f32.16x16x32.bf16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with different C and D types.\\n\\n    Example:\\n    ```mlir\\n    // WMMA bf16 output from f32 accumulator with bf16 inputs.\\n    %r = rocdl.wmma.bf16f32.16x16x32.bf16 %a, %b, %c :\\n      (vector<16xbf16>, vector<16xbf16>, vector<8xf32>) -> vector<16xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x128.bf8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x128.bf8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x128.fp8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x128.fp8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x16.f16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with output operand selection.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f16 with opsel control.\\n    %r = rocdl.wmma.f16.16x16x16.f16 %a, %b, %c {opsel = false} :\\n      (vector<16xf16>, vector<16xf16>, vector<16xf16>) -> vector<16xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"opsel\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x32.f16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with sign, modC, and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with f16 inputs and reuse controls.\\n    %r = rocdl.wmma.f32.16x16x32.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x64.bf8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x64.bf8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x64.fp8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f16.16x16x64.fp8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x128.bf8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x128.bf8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x128.fp8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x128.fp8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x16.bf16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) intrinsic.\\n\\n    Example:\\n    ```mlir\\n    // WMMA with f16 inputs and f32 accumulator.\\n    %r = rocdl.wmma.f32.16x16x16.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x16.bf8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) intrinsic.\\n\\n    Example:\\n    ```mlir\\n    // WMMA with f16 inputs and f32 accumulator.\\n    %r = rocdl.wmma.f32.16x16x16.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x16.bf8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) intrinsic.\\n\\n    Example:\\n    ```mlir\\n    // WMMA with f16 inputs and f32 accumulator.\\n    %r = rocdl.wmma.f32.16x16x16.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x16.f16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) intrinsic.\\n\\n    Example:\\n    ```mlir\\n    // WMMA with f16 inputs and f32 accumulator.\\n    %r = rocdl.wmma.f32.16x16x16.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x16.fp8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) intrinsic.\\n\\n    Example:\\n    ```mlir\\n    // WMMA with f16 inputs and f32 accumulator.\\n    %r = rocdl.wmma.f32.16x16x16.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x16.fp8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) intrinsic.\\n\\n    Example:\\n    ```mlir\\n    // WMMA with f16 inputs and f32 accumulator.\\n    %r = rocdl.wmma.f32.16x16x16.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x32.bf16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with sign, modC, and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with f16 inputs and reuse controls.\\n    %r = rocdl.wmma.f32.16x16x32.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<BF16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x32.f16\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with sign, modC, and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with f16 inputs and reuse controls.\\n    %r = rocdl.wmma.f32.16x16x32.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F16>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x4.f32\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with sign, modC, and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with f16 inputs and reuse controls.\\n    %r = rocdl.wmma.f32.16x16x32.f16 %a, %b, %c :\\n      (vector<16xf16>, vector<16xf16>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x64.bf8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x64.bf8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x64.fp8_bf8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.f32.16x16x64.fp8_fp8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) with modC and reuse controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA f32 with fp8 inputs and modC/reuse controls.\\n    %r = rocdl.wmma.f32.16x16x64.fp8_fp8 %a, %b, %c :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.i32.16x16x16.iu4\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) for integer types with\\n    sign and clamp control.\\n\\n    Example:\\n    ```mlir\\n    // WMMA i32 with unsigned i8 inputs.\\n    %r = rocdl.wmma.i32.16x16x16.iu8 %a, %b, %c\\n      {signA = false, signB = false, clamp = false} :\\n      (vector<4xi32>, vector<4xi32>, vector<8xi32>) -> vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.i32.16x16x16.iu8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) for integer types with\\n    sign and clamp control.\\n\\n    Example:\\n    ```mlir\\n    // WMMA i32 with unsigned i8 inputs.\\n    %r = rocdl.wmma.i32.16x16x16.iu8 %a, %b, %c\\n      {signA = false, signB = false, clamp = false} :\\n      (vector<4xi32>, vector<4xi32>, vector<8xi32>) -> vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.i32.16x16x32.iu4\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) for integer types with\\n    sign and clamp control.\\n\\n    Example:\\n    ```mlir\\n    // WMMA i32 with unsigned i8 inputs.\\n    %r = rocdl.wmma.i32.16x16x16.iu8 %a, %b, %c\\n      {signA = false, signB = false, clamp = false} :\\n      (vector<4xi32>, vector<4xi32>, vector<8xi32>) -> vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.i32.16x16x64.iu8\",\n    \"description\": \"Wave Matrix Multiply-Accumulate (WMMA) for integer types with\\n    sign, reuse, and clamp controls.\\n\\n    Example:\\n    ```mlir\\n    // WMMA i32 with unsigned i8 inputs and reuse controls.\\n    %r = rocdl.wmma.i32.16x16x64.iu8 %a, %b, %c\\n      {signA = false, signB = false, reuseA = false, reuseB = false, clamp = false} :\\n      (vector<8xi32>, vector<8xi32>, vector<8xi32>) -> vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"signB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"clamp\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.scale.f32.16x16x128.f8f6f4\",\n    \"description\": \"Scaled Wave Matrix Multiply-Accumulate (WMMA) with per-operand scaling.\\n\\n    Example:\\n    ```mlir\\n    // Scaled WMMA with f8f6f4 format inputs.\\n    %r = rocdl.wmma.scale.f32.16x16x128.f8f6f4 %a, %b, %c, %scaleA, %scaleB :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>, i32, i32) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"scaleA\", \"type\": \"I32\" },\n      { \"name\": \"scaleB\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmtA\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtB\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"scaleAType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleA\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"scaleBType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleB\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $scaleA `,` $scaleB attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.scale.f32.32x16x128.f4\",\n    \"description\": \"Scaled Wave Matrix Multiply-Accumulate (WMMA) for F4 format inputs.\\n\\n    Example:\\n    ```mlir\\n    // Scaled WMMA with f4 format inputs.\\n    %r = rocdl.wmma.scale.f32.16x16x128.f4 %a, %b, %c, %scaleA, %scaleB :\\n      (vector<8xi32>, vector<8xi32>, vector<8xf32>, i32, i32) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"scaleA\", \"type\": \"I32\" },\n      { \"name\": \"scaleB\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"scaleAType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleA\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"scaleBType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleB\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $scaleA `,` $scaleB attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.scale16.f32.16x16x128.f8f6f4\",\n    \"description\": \"Scaled Wave Matrix Multiply-Accumulate (WMMA) with per-operand scaling.\\n\\n    Example:\\n    ```mlir\\n    // Scaled WMMA with f8f6f4 format inputs.\\n    %r = rocdl.wmma.scale.f32.16x16x128.f8f6f4 %a, %b, %c, %scaleA, %scaleB :\\n      (vector<16xi32>, vector<16xi32>, vector<8xf32>, i32, i32) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"scaleA\", \"type\": \"I64\" },\n      { \"name\": \"scaleB\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmtA\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtB\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"scaleAType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleA\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"scaleBType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleB\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $scaleA `,` $scaleB attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.wmma.scale16.f32.32x16x128.f4\",\n    \"description\": \"Scaled Wave Matrix Multiply-Accumulate (WMMA) for F4 format inputs.\\n\\n    Example:\\n    ```mlir\\n    // Scaled WMMA with f4 format inputs.\\n    %r = rocdl.wmma.scale.f32.16x16x128.f4 %a, %b, %c, %scaleA, %scaleB :\\n      (vector<8xi32>, vector<8xi32>, vector<8xf32>, i32, i32) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"b\", \"type\": \"LLVM_ScalarOrVectorOf<AnyInteger>\" },\n      { \"name\": \"c\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" },\n      { \"name\": \"scaleA\", \"type\": \"I64\" },\n      { \"name\": \"scaleB\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_ScalarOrVectorOf<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"modC\", \"type\": \"DefaultValuedAttr<I16Attr, 0>\" },\n      { \"name\": \"scaleAType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleA\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"scaleBType\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"fmtScaleB\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"reuseA\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" },\n      { \"name\": \"reuseB\", \"type\": \"DefaultValuedAttr<I1Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c `,` $scaleA `,` $scaleB attr-dict `:` functional-type(operands, $res)\"\n  },\n  {\n    \"name\": \"rocdl.workgroup.dim.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workgroup.dim.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workgroup.dim.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workgroup.id.x\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workgroup.id.y\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workgroup.id.z\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workitem.id.x\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workitem.id.y\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"rocdl.workitem.id.z\",\n    \"description\": \"Read a hardware register for thread/workgroup/cluster identification.\\n    An optional `range` attribute can constrain the returned value.\\n\\n    Example:\\n    ```mlir\\n    // Read the workitem id in the x dimension.\\n    %0 = rocdl.workitem.id.x : i32\\n\\n    // Read with a known range constraint.\\n    %1 = rocdl.workitem.id.x range <i32, 0, 64> : i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"LLVM_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"scf.condition\",\n    \"summary\": \"loop continuation condition\",\n    \"description\": \"This operation accepts the continuation (i.e., inverse of exit) condition\\n    of the `scf.while` construct. If its first argument is true, the \\\"after\\\"\\n    region of `scf.while` is executed, with the remaining arguments forwarded\\n    to the entry block of the region. Otherwise, the loop terminates.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $condition `)` attr-dict ($args^ `:` type($args))?\"\n  },\n  {\n    \"name\": \"scf.execute_region\",\n    \"summary\": \"operation that executes its region exactly once\",\n    \"description\": \"The `scf.execute_region` operation is used to allow multiple blocks within SCF\\n    and other operations which can hold only one block.  The `scf.execute_region`\\n    operation executes the region held exactly once and cannot have any operands.\\n    As such, its region has no arguments. All SSA values that dominate the op can\\n    be accessed inside the op. The op's region can have multiple blocks and the\\n    blocks can have multiple distinct terminators. Values returned from this op's\\n    region define the op's results.\\n    The optional 'no_inline' flag can be set to request the ExecuteRegionOp to be\\n    preserved as much as possible and not being inlined in the parent block until\\n    an explicit lowering step.\\n\\n    Example:\\n\\n    ```mlir\\n    scf.for %i = 0 to 128 step %c1 {\\n      %y = scf.execute_region -> i32 {\\n        %x = load %A[%i] : memref<128xi32>\\n        scf.yield %x : i32\\n      }\\n    }\\n\\n    // the same as above but with no_inline attribute\\n    scf.for %i = 0 to 128 step %c1 {\\n      %y = scf.execute_region -> i32 no_inline {\\n        %x = load %A[%i] : memref<128xi32>\\n        scf.yield %x : i32\\n      }\\n    }\\n\\n    affine.for %i = 0 to 100 {\\n      \\\"foo\\\"() : () -> ()\\n      %v = scf.execute_region -> i64 {\\n        cf.cond_br %cond, ^bb1, ^bb2\\n\\n      ^bb1:\\n        %c1 = arith.constant 1 : i64\\n        cf.br ^bb3(%c1 : i64)\\n\\n      ^bb2:\\n        %c2 = arith.constant 2 : i64\\n        cf.br ^bb3(%c2 : i64)\\n\\n      ^bb3(%x : i64):\\n        scf.yield %x : i64\\n      }\\n      \\\"bar\\\"(%v) : (i64) -> ()\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"no_inline\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.for\",\n    \"summary\": \"for operation\",\n    \"description\": \"The `scf.for` operation represents a loop taking 3 SSA value as operands\\n    that represent the lower bound, upper bound and step respectively. The\\n    operation defines an SSA value for its induction variable. It has one\\n    region capturing the loop body. The induction variable is represented as an\\n    argument of this region. This SSA value is a signless integer or index.\\n    The step is a value of same type but required to be positive, the lower and\\n    upper bounds can be also negative or zero. The lower and upper bounds\\n    specify a half-open range: the iteration is executed iff the comparison of\\n    induction variable value is less than the upper bound and bigger or equal\\n    to the lower bound.\\n\\n    By default, the integer comparison is signed. If the `unsignedCmp` unit\\n    attribute is specified, the integer comparison is unsigned.\\n\\n    The body region must contain exactly one block that terminates with\\n    `scf.yield`. Calling ForOp::build will create such a region and insert\\n    the terminator implicitly if none is defined, so will the parsing even in\\n    cases when it is absent from the custom format. For example:\\n\\n    ```mlir\\n    // Index case.\\n    scf.for %iv = %lb to %ub step %step {\\n      ... // body\\n    }\\n    ...\\n    // Unsigned integer case.\\n    scf.for unsigned %iv_32 = %lb_32 to %ub_32 step %step_32 : i32 {\\n      ... // body\\n    }\\n    ```\\n\\n    `scf.for` can also operate on loop-carried variables and returns the final\\n    values after loop termination. The initial values of the variables are\\n    passed as additional SSA operands to the `scf.for` following the 3 loop\\n    control SSA values mentioned above (lower bound, upper bound and step). The\\n    operation region has an argument for the induction variable, followed by\\n    one argument for each loop-carried variable, representing the value of the\\n    variable at the current iteration.\\n\\n    The region must terminate with a `scf.yield` that passes the current\\n    values of all loop-carried variables to the next iteration, or to the\\n    `scf.for` result, if at the last iteration. The static type of a\\n    loop-carried variable may not change with iterations; its runtime type is\\n    allowed to change. Note, that when the loop-carried variables are present,\\n    calling ForOp::build will not insert the terminator implicitly. The caller\\n    must insert `scf.yield` in that case.\\n\\n    `scf.for` results hold the final values after the last iteration.\\n    For example, to sum-reduce a memref:\\n\\n    ```mlir\\n    func.func @reduce(%buffer: memref<1024xf32>, %lb: index,\\n                      %ub: index, %step: index) -> (f32) {\\n      // Initial sum set to 0.\\n      %sum_0 = arith.constant 0.0 : f32\\n      // iter_args binds initial values to the loop's region arguments.\\n      %sum = scf.for %iv = %lb to %ub step %step\\n          iter_args(%sum_iter = %sum_0) -> (f32) {\\n        %t = load %buffer[%iv] : memref<1024xf32>\\n        %sum_next = arith.addf %sum_iter, %t : f32\\n        // Yield current iteration sum to next iteration %sum_iter or to %sum\\n        // if final iteration.\\n        scf.yield %sum_next : f32\\n      }\\n      return %sum : f32\\n    }\\n    ```\\n\\n    If the `scf.for` defines any values, a yield must be explicitly present.\\n    The number and types of the `scf.for` results must match the initial\\n    values in the `iter_args` binding and the yield operands.\\n\\n    Another example with a nested `scf.if` (see `scf.if` for details) to\\n    perform conditional reduction:\\n\\n    ```mlir\\n    func.func @conditional_reduce(%buffer: memref<1024xf32>, %lb: index,\\n                                  %ub: index, %step: index) -> (f32) {\\n      %sum_0 = arith.constant 0.0 : f32\\n      %c0 = arith.constant 0.0 : f32\\n      %sum = scf.for %iv = %lb to %ub step %step\\n          iter_args(%sum_iter = %sum_0) -> (f32) {\\n        %t = load %buffer[%iv] : memref<1024xf32>\\n        %cond = arith.cmpf \\\"ugt\\\", %t, %c0 : f32\\n        %sum_next = scf.if %cond -> (f32) {\\n          %new_sum = arith.addf %sum_iter, %t : f32\\n          scf.yield %new_sum : f32\\n        } else {\\n          scf.yield %sum_iter : f32\\n        }\\n        scf.yield %sum_next : f32\\n      }\\n      return %sum : f32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lowerBound\", \"type\": \"AnySignlessIntegerOrIndex\" },\n      { \"name\": \"upperBound\", \"type\": \"AnySignlessIntegerOrIndex\" },\n      { \"name\": \"step\", \"type\": \"AnySignlessIntegerOrIndex\" },\n      { \"name\": \"initArgs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"unsignedCmp\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lowerBound', 'upperBound', 'step']>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.forall\",\n    \"summary\": \"evaluate a block multiple times in parallel\",\n    \"description\": \"`scf.forall` is a target-independent multi-dimensional parallel\\n    region application operation. It has exactly one block that represents the\\n    parallel body and it takes index operands that specify lower bounds, upper\\n    bounds and steps.\\n\\n    The op also takes a variadic number of tensor operands (`shared_outs`).\\n    The future buffers corresponding to these tensors are shared among all\\n    threads. Shared tensors should be accessed via their corresponding block\\n    arguments. If multiple threads write to a shared buffer in a racy\\n    fashion, these writes will execute in some unspecified order. Tensors that\\n    are not shared can be used inside the body (i.e., the op is not isolated\\n    from above); however, if a use of such a tensor bufferizes to a memory\\n    write, the tensor is privatized, i.e., a thread-local copy of the tensor is\\n    used. This ensures that memory side effects of a thread are not visible to\\n    other threads (or in the parent body), apart from explicitly shared tensors.\\n\\n    The name \\\"thread\\\" conveys the fact that the parallel execution is mapped\\n    (i.e. distributed) to a set of virtual threads of execution, one function\\n    application per thread. Further lowerings are responsible for specifying\\n    how this is materialized on concrete hardware resources.\\n\\n    An optional `mapping` is an attribute array that specifies processing units\\n    with their dimension, how it remaps 1-1 to a set of concrete processing\\n    element resources (e.g. a CUDA grid dimension or a level of concrete nested\\n    async parallelism). It is expressed via any attribute that implements the\\n    device mapping interface. It is the reponsibility of the lowering mechanism\\n    to interpret the `mapping` attributes in the context of the concrete target\\n    the op is lowered to, or to ignore it when the specification is ill-formed\\n    or unsupported for a particular target.\\n\\n    The only allowed terminator is `scf.forall.in_parallel`.\\n    `scf.forall` returns one value per `shared_out` operand. The\\n    actions of the `scf.forall.in_parallel` terminators specify how to combine the\\n    partial results of all parallel invocations into a full value, in some\\n    unspecified order. The \\\"destination\\\" of each such op must be a `shared_out`\\n    block argument of the `scf.forall` op.\\n\\n    The actions involved in constructing the return values are further described\\n    by `tensor.parallel_insert_slice`.\\n\\n    `scf.forall` acts as an implicit synchronization point.\\n\\n    When the parallel function body has side effects, their order is unspecified\\n    across threads.\\n\\n    `scf.forall` can be printed in two different ways depending on\\n    whether the loop is normalized or not. The loop is 'normalized' when all\\n    lower bounds are equal to zero and steps are equal to one. In that case,\\n    `lowerBound` and `step` operands will be omitted during printing.\\n\\n    Normalized loop example:\\n\\n    ```mlir\\n    //\\n    // Sequential context.\\n    //\\n    %matmul_and_pointwise:2 = scf.forall (%thread_id_1, %thread_id_2) in\\n        (%num_threads_1, %numthread_id_2) shared_outs(%o1 = %C, %o2 = %pointwise)\\n      -> (tensor<?x?xT>, tensor<?xT>) {\\n      //\\n      // Parallel context, each thread with id = (%thread_id_1, %thread_id_2)\\n      // runs its version of the code.\\n      //\\n      %sA = tensor.extract_slice %A[f((%thread_id_1, %thread_id_2))]:\\n        tensor<?x?xT> to tensor<?x?xT>\\n      %sB = tensor.extract_slice %B[g((%thread_id_1, %thread_id_2))]:\\n        tensor<?x?xT> to tensor<?x?xT>\\n      %sC = tensor.extract_slice %o1[h((%thread_id_1, %thread_id_2))]:\\n        tensor<?x?xT> to tensor<?x?xT>\\n      %sD = linalg.matmul\\n        ins(%sA, %sB : tensor<?x?xT>, tensor<?x?xT>)\\n        outs(%sC : tensor<?x?xT>)\\n\\n      %spointwise = subtensor %o2[i((%thread_id_1, %thread_id_2))]:\\n        tensor<?xT> to tensor<?xT>\\n      %sE = linalg.add ins(%spointwise : tensor<?xT>) outs(%sD : tensor<?xT>)\\n\\n      scf.forall.in_parallel {\\n        tensor.parallel_insert_slice %sD into %o1[h((%thread_id_1, %thread_id_2))]:\\n          tensor<?x?xT> into tensor<?x?xT>\\n\\n        tensor.parallel_insert_slice %spointwise into %o2[i((%thread_id_1, %thread_id_2))]:\\n          tensor<?xT> into tensor<?xT>\\n      }\\n    }\\n    // Implicit synchronization point.\\n    // Sequential context.\\n    //\\n    ```\\n\\n    Loop with loop bounds example:\\n\\n    ```mlir\\n    //\\n    // Sequential context.\\n    //\\n    %pointwise = scf.forall (%i, %j) = (0, 0) to (%dim1, %dim2)\\n      step (%tileSize1, %tileSize2) shared_outs(%o1 = %out)\\n      -> (tensor<?x?xT>, tensor<?xT>) {\\n      //\\n      // Parallel context.\\n      //\\n      %sA = tensor.extract_slice %A[%i, %j][%tileSize1, %tileSize2][1, 1]\\n        : tensor<?x?xT> to tensor<?x?xT>\\n      %sB = tensor.extract_slice %B[%i, %j][%tileSize1, %tileSize2][1, 1]\\n        : tensor<?x?xT> to tensor<?x?xT>\\n      %sC = tensor.extract_slice %o[%i, %j][%tileSize1, %tileSize2][1, 1]\\n        : tensor<?x?xT> to tensor<?x?xT>\\n\\n      %add = linalg.map {\\\"arith.addf\\\"}\\n        ins(%sA, %sB : tensor<?x?xT>, tensor<?x?xT>)\\n        outs(%sC : tensor<?x?xT>)\\n\\n      scf.forall.in_parallel {\\n        tensor.parallel_insert_slice %add into\\n          %o[%i, %j][%tileSize1, %tileSize2][1, 1]\\n          : tensor<?x?xT> into tensor<?x?xT>\\n      }\\n    }\\n    // Implicit synchronization point.\\n    // Sequential context.\\n    //\\n    ```\\n\\n    Example with mapping attribute:\\n\\n    ```mlir\\n    //\\n    // Sequential context. Here `mapping` is expressed as GPU thread mapping\\n    // attributes\\n    //\\n    %matmul_and_pointwise:2 = scf.forall (%thread_id_1, %thread_id_2) in\\n        (%num_threads_1, %numthread_id_2) shared_outs(...)\\n      -> (tensor<?x?xT>, tensor<?xT>) {\\n      //\\n      // Parallel context, each thread with id = **(%thread_id_2, %thread_id_1)**\\n      // runs its version of the code.\\n      //\\n       scf.forall.in_parallel {\\n         ...\\n      }\\n    } { mapping = [#gpu.thread<y>, #gpu.thread<x>] }\\n    // Implicit synchronization point.\\n    // Sequential context.\\n    //\\n    ```\\n\\n    Example with privatized tensors:\\n\\n    ```mlir\\n    %t0 = ...\\n    %t1 = ...\\n    %r = scf.forall ... shared_outs(%o = t0) -> tensor<?xf32> {\\n      // %t0 and %t1 are privatized. %t0 is definitely copied for each thread\\n      // because the scf.forall op's %t0 use bufferizes to a memory\\n      // write. In the absence of other conflicts, %t1 is copied only if there\\n      // are uses of %t1 in the body that bufferize to a memory read and to a\\n      // memory write.\\n      \\\"some_use\\\"(%t0)\\n      \\\"some_use\\\"(%t1)\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynamicLowerBound\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"dynamicUpperBound\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"dynamicStep\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"staticLowerBound\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"staticUpperBound\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"staticStep\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.forall.in_parallel\",\n    \"summary\": \"terminates a `forall` block\",\n    \"description\": \"The `scf.forall.in_parallel` is a designated terminator for\\n    the `scf.forall` operation.\\n\\n    It has a single region with a single block that contains a flat list of ops.\\n    Each such op participates in the aggregate formation of a single result of\\n    the enclosing `scf.forall`.\\n    The result number corresponds to the position of the op in the terminator.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.if\",\n    \"summary\": \"if-then-else operation\",\n    \"description\": \"The `scf.if` operation represents an if-then-else construct for\\n    conditionally executing two regions of code. The operand to an if operation\\n    is a boolean value. For example:\\n\\n    ```mlir\\n    scf.if %b  {\\n      ...\\n    } else {\\n      ...\\n    }\\n    ```\\n\\n    `scf.if` may also produce results. Which values are returned depends on\\n    which execution path is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    %x, %y = scf.if %b -> (f32, f32) {\\n      %x_true = ...\\n      %y_true = ...\\n      scf.yield %x_true, %y_true : f32, f32\\n    } else {\\n      %x_false = ...\\n      %y_false = ...\\n      scf.yield %x_false, %y_false : f32, f32\\n    }\\n    ```\\n\\n    The \\\"then\\\" region has exactly 1 block. The \\\"else\\\" region may have 0 or 1\\n    block. In case the `scf.if` produces results, the \\\"else\\\" region must also\\n    have exactly 1 block.\\n\\n    The blocks are always terminated with `scf.yield`. If `scf.if` defines no\\n    values, the `scf.yield` can be left out, and will be inserted implicitly.\\n    Otherwise, it must be explicit.\\n\\n    Example:\\n\\n    ```mlir\\n    scf.if %b  {\\n      ...\\n    }\\n    ```\\n\\n    The types of the yielded values must match the result types of the\\n    `scf.if`.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"elseRegion\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.index_switch\",\n    \"summary\": \"switch-case operation on an index argument\",\n    \"description\": \"The `scf.index_switch` is a control-flow operation that branches to one of\\n    the given regions based on the values of the argument and the cases. The\\n    argument is always of type `index`.\\n\\n    The operation always has a \\\"default\\\" region and any number of case regions\\n    denoted by integer constants. Control-flow transfers to the case region\\n    whose constant value equals the value of the argument. If the argument does\\n    not equal any of the case values, control-flow transfer to the \\\"default\\\"\\n    region.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = scf.index_switch %arg0 : index -> i32\\n    case 2 {\\n      %1 = arith.constant 10 : i32\\n      scf.yield %1 : i32\\n    }\\n    case 5 {\\n      %2 = arith.constant 20 : i32\\n      scf.yield %2 : i32\\n    }\\n    default {\\n      %3 = arith.constant 30 : i32\\n      scf.yield %3 : i32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cases\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"defaultRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"caseRegions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict (`->` type($results)^)?\\n    custom<SwitchCases>($cases, $caseRegions) `\\\\n`\\n    `` `default` $defaultRegion\"\n  },\n  {\n    \"name\": \"scf.parallel\",\n    \"summary\": \"parallel for operation\",\n    \"description\": \"The `scf.parallel` operation represents a loop nest taking 4 groups of SSA\\n    values as operands that represent the lower bounds, upper bounds, steps and\\n    initial values, respectively. The operation defines a variadic number of\\n    SSA values for its induction variables. It has one region capturing the\\n    loop body. The induction variables are represented as an argument of this\\n    region. These SSA values always have type index, which is the size of the\\n    machine word. The steps are values of type index, required to be positive.\\n    The lower and upper bounds specify a half-open range: the range includes\\n    the lower bound but does not include the upper bound. The initial values\\n    have the same types as results of `scf.parallel`. If there are no results,\\n    the keyword `init` can be omitted.\\n\\n    Semantically we require that the iteration space can be iterated in any\\n    order, and the loop body can be executed in parallel. If there are data\\n    races, the behavior is undefined.\\n\\n    The parallel loop operation supports reduction of values produced by\\n    individual iterations into a single result. This is modeled using the\\n    `scf.reduce` terminator operation (see `scf.reduce` for details). The i-th\\n    result of an `scf.parallel` operation is associated with the i-th initial\\n    value operand, the i-th operand of the `scf.reduce` operation (the value to\\n    be reduced) and the i-th region of the `scf.reduce` operation (the reduction\\n    function). Consequently, we require that the number of results of an\\n    `scf.parallel` op matches the number of initial values and the the number of\\n    reductions in the `scf.reduce` terminator.\\n\\n    The body region must contain exactly one block that terminates with a\\n    `scf.reduce` operation. If an `scf.parallel` op has no reductions, the\\n    terminator has no operands and no regions. The `scf.parallel` parser will\\n    automatically insert the terminator for ops that have no reductions if it is\\n    absent.\\n\\n    Example:\\n\\n    ```mlir\\n    %init = arith.constant 0.0 : f32\\n    %r:2 = scf.parallel (%iv) = (%lb) to (%ub) step (%step) init (%init, %init)\\n        -> f32, f32 {\\n      %elem_to_reduce1 = load %buffer1[%iv] : memref<100xf32>\\n      %elem_to_reduce2 = load %buffer2[%iv] : memref<100xf32>\\n      scf.reduce(%elem_to_reduce1, %elem_to_reduce2 : f32, f32) {\\n        ^bb0(%lhs : f32, %rhs: f32):\\n          %res = arith.addf %lhs, %rhs : f32\\n          scf.reduce.return %res : f32\\n      }, {\\n        ^bb0(%lhs : f32, %rhs: f32):\\n          %res = arith.mulf %lhs, %rhs : f32\\n          scf.reduce.return %res : f32\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lowerBound\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"upperBound\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"step\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"initVals\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.reduce\",\n    \"summary\": \"reduce operation for scf.parallel\",\n    \"description\": \"The `scf.reduce` operation is the terminator for `scf.parallel` operations. It can model\\n    an arbitrary number of reductions. It has one region per reduction. Each\\n    region has one block with two arguments which have the same type as the\\n    corresponding operand of `scf.reduce`. The operands of the op are the values\\n    that should be reduce; one value per reduction.\\n\\n    The i-th reduction (i.e., the i-th region and the i-th operand) corresponds\\n    the i-th initial value and the i-th result of the enclosing `scf.parallel`\\n    op.\\n\\n    The `scf.reduce` operation contains regions whose entry blocks expect two\\n    arguments of the same type as the corresponding operand. As the iteration\\n    order of the enclosing parallel loop and hence reduction order is\\n    unspecified, the results of the reductions may be non-deterministic unless\\n    the reductions are associative and commutative.\\n\\n    The result of a reduction region (`scf.reduce.return` operand) must have the\\n    same type as the corresponding `scf.reduce` operand and the corresponding\\n    `scf.parallel` initial value.\\n\\n    Example:\\n\\n    ```mlir\\n    %operand = arith.constant 1.0 : f32\\n    scf.reduce(%operand : f32) {\\n      ^bb0(%lhs : f32, %rhs: f32):\\n        %res = arith.addf %lhs, %rhs : f32\\n        scf.reduce.return %res : f32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"reductions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"(`(` $operands^ `:` type($operands) `)`)? $reductions attr-dict\"\n  },\n  {\n    \"name\": \"scf.reduce.return\",\n    \"summary\": \"terminator for reduce operation\",\n    \"description\": \"The `scf.reduce.return` operation is a special terminator operation for the block inside\\n    `scf.reduce` regions. It terminates the region. It should have the same\\n    operand type as the corresponding operand of the enclosing `scf.reduce` op.\\n\\n    Example:\\n\\n    ```mlir\\n    scf.reduce.return %res : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"scf.while\",\n    \"summary\": \"a generic 'while' loop\",\n    \"description\": \"This operation represents a generic \\\"while\\\"/\\\"do-while\\\" loop that keeps\\n    iterating as long as a condition is satisfied. There is no restriction on\\n    the complexity of the condition. It consists of two regions (with single\\n    block each): \\\"before\\\" region and \\\"after\\\" region. The names of regions\\n    indicates whether they execute before or after the condition check.\\n    Therefore, if the main loop payload is located in the \\\"before\\\" region, the\\n    operation is a \\\"do-while\\\" loop. Otherwise, it is a \\\"while\\\" loop.\\n\\n    The \\\"before\\\" region terminates with a special operation, `scf.condition`,\\n    that accepts as its first operand an `i1` value indicating whether to\\n    proceed to the \\\"after\\\" region (value is `true`) or not. The two regions\\n    communicate by means of region arguments. Initially, the \\\"before\\\" region\\n    accepts as arguments the operands of the `scf.while` operation and uses them\\n    to evaluate the condition. It forwards the trailing, non-condition operands\\n    of the `scf.condition` terminator either to the \\\"after\\\" region if the\\n    control flow is transferred there or to results of the `scf.while` operation\\n    otherwise. The \\\"after\\\" region takes as arguments the values produced by the\\n    \\\"before\\\" region and uses `scf.yield` to supply new arguments for the\\n    \\\"before\\\" region, into which it transfers the control flow unconditionally.\\n\\n    A simple \\\"while\\\" loop can be represented as follows.\\n\\n    ```mlir\\n    %res = scf.while (%arg1 = %init1) : (f32) -> f32 {\\n      // \\\"Before\\\" region.\\n      // In a \\\"while\\\" loop, this region computes the condition.\\n      %condition = call @evaluate_condition(%arg1) : (f32) -> i1\\n\\n      // Forward the argument (as result or \\\"after\\\" region argument).\\n      scf.condition(%condition) %arg1 : f32\\n\\n    } do {\\n    ^bb0(%arg2: f32):\\n      // \\\"After\\\" region.\\n      // In a \\\"while\\\" loop, this region is the loop body.\\n      %next = call @payload(%arg2) : (f32) -> f32\\n\\n      // Forward the new value to the \\\"before\\\" region.\\n      // The operand types must match the types of the `scf.while` operands.\\n      scf.yield %next : f32\\n    }\\n    ```\\n\\n    A simple \\\"do-while\\\" loop can be represented by reducing the \\\"after\\\" block\\n    to a simple forwarder.\\n\\n    ```mlir\\n    %res = scf.while (%arg1 = %init1) : (f32) -> f32 {\\n      // \\\"Before\\\" region.\\n      // In a \\\"do-while\\\" loop, this region contains the loop body.\\n      %next = call @payload(%arg1) : (f32) -> f32\\n\\n      // And also evaluates the condition.\\n      %condition = call @evaluate_condition(%arg1) : (f32) -> i1\\n\\n      // Loop through the \\\"after\\\" region.\\n      scf.condition(%condition) %next : f32\\n\\n    } do {\\n    ^bb0(%arg2: f32):\\n      // \\\"After\\\" region.\\n      // Forwards the values back to \\\"before\\\" region unmodified.\\n      scf.yield %arg2 : f32\\n    }\\n    ```\\n\\n    Note that the types of region arguments need not to match with each other.\\n    The op expects the operand types to match with argument types of the\\n    \\\"before\\\" region; the result types to match with the trailing operand types\\n    of the terminator of the \\\"before\\\" region, and with the argument types of the\\n    \\\"after\\\" region. The following scheme can be used to share the results of\\n    some operations executed in the \\\"before\\\" region with the \\\"after\\\" region,\\n    avoiding the need to recompute them.\\n\\n    ```mlir\\n    %res = scf.while (%arg1 = %init1) : (f32) -> i64 {\\n      // One can perform some computations, e.g., necessary to evaluate the\\n      // condition, in the \\\"before\\\" region and forward their results to the\\n      // \\\"after\\\" region.\\n      %shared = call @shared_compute(%arg1) : (f32) -> i64\\n\\n      // Evaluate the condition.\\n      %condition = call @evaluate_condition(%arg1, %shared) : (f32, i64) -> i1\\n\\n      // Forward the result of the shared computation to the \\\"after\\\" region.\\n      // The types must match the arguments of the \\\"after\\\" region as well as\\n      // those of the `scf.while` results.\\n      scf.condition(%condition) %shared : i64\\n\\n    } do {\\n    ^bb0(%arg2: i64) {\\n      // Use the partial result to compute the rest of the payload in the\\n      // \\\"after\\\" region.\\n      %res = call @payload(%arg2) : (i64) -> f32\\n\\n      // Forward the new value to the \\\"before\\\" region.\\n      // The operand types must match the types of the `scf.while` operands.\\n      scf.yield %res : f32\\n    }\\n    ```\\n\\n    The custom syntax for this operation is as follows.\\n\\n    ```\\n    op ::= `scf.while` assignments `:` function-type region `do` region\\n           `attributes` attribute-dict\\n    initializer ::= /* empty */ | `(` assignment-list `)`\\n    assignment-list ::= assignment | assignment `,` assignment-list\\n    assignment ::= ssa-value `=` ssa-value\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"before\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"after\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"scf.yield\",\n    \"summary\": \"loop yield and termination operation\",\n    \"description\": \"The `scf.yield` operation yields an SSA value from the SCF dialect op region and\\n    terminates the regions. The semantics of how the values are yielded is\\n    defined by the parent operation.\\n    If `scf.yield` has any operands, the operands must match the parent\\n    operation's results.\\n    If the parent operation defines no values, then the `scf.yield` may be\\n    left out in the custom syntax and the builders will insert one implicitly.\\n    Otherwise, it has to be present in the syntax to indicate which values are\\n    yielded.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"sdfg.alloc\",\n    \"summary\": \"Array allocation operation\",\n    \"description\": \"Alloc operation to create arrays and reserve the specified space.\\n        For example:\\n\\n        ```mlir\\n            %A = sdfg.alloc() : !sdfg.array<i32>\\n        ```\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[SDFG_ArrayType, SDFG_StreamType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"transient\", \"type\": \"UnitAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.alloc_symbol\",\n    \"summary\": \"symbol creation operation\",\n    \"description\": \"Alloc operation to create a new symbol.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            sdfg.alloc_symbol(\\\"N\\\")\\n            ...\\n        }\\n        ```\",\n    \"attributes\": [\n      { \"name\": \"sym\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.call\"\n  },\n  {\n    \"name\": \"sdfg.consume\",\n    \"summary\": \"Consume scope\",\n    \"description\": \"Describes a consume scope where the region has access to the popped \\n        element as well as the processing element.\\n        For example:\\n\\n        ```mlir\\n        sdfg.consume{num_pes=5} (%a : !sdfg.stream<i32>) -> (pe: %p, elem: %e) {\\n                %c = sdfg.call @add_one(%a) : i32 -> i32\\n            ...\\n        } \\n        ```\",\n    \"operands\": [\n      { \"name\": \"stream\", \"type\": \"SDFG_StreamType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entryID\", \"type\": \"I32Attr\" },\n      { \"name\": \"exitID\", \"type\": \"I32Attr\" },\n      { \"name\": \"num_pes\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"condition\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.copy\",\n    \"summary\": \"Memlet copy operation\",\n    \"description\": \"Allows a state to copy the contents from one memlet to another.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            sdfg.copy %a -> %c : !sdfg.memlet<i32>\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"SDFG_ArrayType\" },\n      { \"name\": \"dest\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.edge\",\n    \"summary\": \"edge operation\",\n    \"description\": \"Represents an edge from one state to another with assignment and \\n        condition attributes.\\n        For example:\\n\\n        ```mlir\\n        sdfg.sdfg {\\n            ...\\n            sdfg.edge{assign=[\\\"i = 1\\\"]} @state_0 -> @state_1\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"dest\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"assign\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"condition\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"1\\\">\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.get_access\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"sdfg.libcall\",\n    \"summary\": \"library call operation\",\n    \"description\": \"The `libcall` operation represents a direct call to a library function. \\n        For example:\\n\\n        ```mlir\\n        %2 = sdfg.libcall \\\"dace.libraries.blas.nodes.Dot\\\" (%0, %1) : (f32, f32) -> f32\\n        ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.load\",\n    \"summary\": \"Memlet load operation\",\n    \"description\": \"Allows a state to load a value from a memlet.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            %a = sdfg.get_access %A : !sdfg.memlet<i32>\\n            %a_1 = sdfg.load %a[0] : !sdfg.memlet<i32> -> i32\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"arr\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'arr', 'res', '$_self.cast<ArrayType>().getDimensions().getElementType()'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.map\",\n    \"summary\": \"Map scope\",\n    \"description\": \"Describes a map where the region has access to the map symbol variables.\\n        For example:\\n\\n        ```mlir\\n        sdfg.map (%i, %j) = (0, 0) to (2, 2) step (1, 1) {\\n            ...\\n            %a = sdfg.load %A[%i, %j] : !sdfg.array<12x34xi32>\\n            ...\\n        } \\n        ```\",\n    \"operands\": [\n      { \"name\": \"ranges\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entryID\", \"type\": \"I32Attr\" },\n      { \"name\": \"exitID\", \"type\": \"I32Attr\" },\n      { \"name\": \"lowerBounds\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"upperBounds\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"steps\", \"type\": \"ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.nested_sdfg\",\n    \"summary\": \"Nested SDFG region\",\n    \"description\": \"Describes a nested SDFG where the states are placed in the region. \\n        For example:\\n\\n        ```mlir\\n        sdfg.nested_sdfg{entry=@state_0} {\\n            sdfg.edge{assign=[\\\"i = 1\\\"]} @state_0 -> @state_1\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ID\", \"type\": \"I32Attr\" },\n      { \"name\": \"entry\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"num_args\", \"type\": \"I32Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.return\",\n    \"summary\": \"return operation\",\n    \"description\": \"The \\\"return\\\" operation represents a return operation within a function.\\n        The operation takes an optional operand and produces no results.\\n        The operand type must match the signature of the function that contains\\n        the operation. \\n        For example:\\n\\n        ```mlir\\n        func @foo() -> tensor<2xf64> {\\n            ...\\n            sdfg.return %0 : tensor<2xf64>\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.sdfg\",\n    \"summary\": \"SDFG region\",\n    \"description\": \"Describes an SDFG where the states are placed in the region. \\n        For example:\\n\\n        ```mlir\\n        sdfg.sdfg{entry=@state_0} {\\n            sdfg.edge{assign=[\\\"i = 1\\\"]} @state_0 -> @state_1\\n            ...\\n        }\\n        ```\",\n    \"attributes\": [\n      { \"name\": \"ID\", \"type\": \"I32Attr\" },\n      { \"name\": \"entry\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"num_args\", \"type\": \"I32Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.state\",\n    \"summary\": \"State region\",\n    \"description\": \"Describes a state where the subgraphs are placed in the region. \\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0{\\n            ...\\n        } \\n        ```\",\n    \"attributes\": [\n      { \"name\": \"ID\", \"type\": \"I32Attr\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.store\",\n    \"summary\": \"Memlet store operation\",\n    \"description\": \"Allows a state to store a value in a memlet.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            %1 = arith.constant 1 : i32\\n            %a = sdfg.get_access %A : !sdfg.memlet<i32>\\n            sdfg.store %1, %a[0] : !sdfg.memlet<i32>\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"val\", \"type\": \"AnyType\" },\n      { \"name\": \"arr\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'arr', 'val', '$_self.cast<ArrayType>().getDimensions().getElementType()'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.stream_length\",\n    \"summary\": \"Stream length operation\",\n    \"description\": \"Returns the length of the stream.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            %l = sdfg.stream_length %A : !sdfg.stream<i32> -> i32\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"str\", \"type\": \"SDFG_StreamType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.stream_pop\",\n    \"summary\": \"Stream pop operation\",\n    \"description\": \"Allows a state to pop a value from a stream.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            %a = sdfg.stream_pop %A : !sdfg.stream<i32> -> i32\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"str\", \"type\": \"SDFG_StreamType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'str', 'res', '$_self.cast<StreamType>().getDimensions().getElementType()'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.stream_push\",\n    \"summary\": \"Stream push operation\",\n    \"description\": \"Allows a state to push a value into a stream.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            %1 = arith.constant 1 : i32\\n            sdfg.stream_push %1, %A : i32 -> !sdfg.stream<i32>\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"AnyType\" },\n      { \"name\": \"str\", \"type\": \"SDFG_StreamType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'str', 'val', '$_self.cast<StreamType>().getDimensions().getElementType()'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.subview\",\n    \"summary\": \"Subview operation\",\n    \"description\": \"Return a subview of a memlet with the provided offsets, sizes and \\n        strides.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state {\\n            ...\\n            %B = sdfg.subview %A[3, 4, 2][1, 6, 3][1, 1, 1] : !sdfg.array<8x16x4xi32> -> !sdfg.array<6x3xi32>\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offsets\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"sizes\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"strides\", \"type\": \"ArrayAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.sym\",\n    \"summary\": \"symbolic expression operation\",\n    \"description\": \"Describes an arithmetic symbolic expression.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state @state_0 {\\n            ...\\n            %res = sdfg.sym(\\\"3*N+2\\\") : i32\\n            ...\\n        }\\n        ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[AnyInteger, Index]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"expr\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.tasklet\",\n    \"summary\": \"Tasklet\",\n    \"description\": \"Describes a tasklet as a pure function. For example:\\n\\n        ```mlir\\n        sdfg.tasklet @add(%a: i32, %b: i32) -> i32{\\n            %c = arith.addi %a, %b, : i32\\n            sdfg.return %c\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ID\", \"type\": \"I32Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdfg.view_cast\",\n    \"summary\": \"view node operation\",\n    \"description\": \"Represents a view node to cast a memlet from one view to another.\\n        For example:\\n\\n        ```mlir\\n        sdfg.state {\\n            ...\\n            %B = sdfg.view_cast %A : !sdfg.memlet<2x16xi32> -> !sdfg.memlet<32xi32>\\n            ...\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"SDFG_ArrayType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdy.all_gather\",\n    \"summary\": \"Performs an all-gather communication along axes\",\n    \"description\": \"Gathers chunks of a tensor along axes specified in `gathering_axes`.\\n\\n    The `gathering_axes` is a list of lists of axes. The outer list is over the\\n    dimensions of the tensor. Each inner list specifies the axes along which a\\n    separate gather should be performed on the respective dimension. It will be\\n    applied to the sharding of the operand (`tensor`) to obtain the sharding of\\n    the result (`out_sharding`).\\n\\n    Note that `out_sharding` is not used to determine the sharding of the\\n    result. Instead, the sharding of the result is determined by the sharding of\\n    the operand and the `gathering_axes`, and `out_sharding` must match this\\n    inferred sharding.\\n\\n    Example:\\n    ```mlir\\n    %1 = stablehlo.tanh(%0) {sdy.sharding = #sdy.sharding_per_value<[<@mesh, [{\\\"a\\\", \\\"b\\\", \\\"c\\\"}, {}, {\\\"d\\\"}\\\\]>]>} : tensor<8x8x8xf32>\\n    %2 = sdy.all_gather [{\\\"b\\\", \\\"c\\\"}, {}, {\\\"d\\\"}\\\\] %1 out_sharding=<@mesh, [{\\\"a\\\"}, {}, {}\\\\]> : tensor<8x8x8xf32>\\n    ```\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - Elements in `gathering_axes` must satisfy the constraints listed in\\n      `AxisRefListAttr`.\\n    - Applying `gathering_axes` to the operand sharding gets `out_sharding`.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"gathering_axes\", \"type\": \"Sdy_ListOfAxisRefLists\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$gathering_axes $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.all_reduce\",\n    \"summary\": \"Perform an all-reduce comunication along axes\",\n    \"description\": \"Reduces chunks of a tensor along axes specified in `reduction_axes`.\\n    The order of `reduction_axes` is not important for the result, but can\\n    affect the order of the corresponding replica groups.\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - `reduction_axes` must satisfy the constraints listed in `AxisRefListAttr`.\\n    - `reduction_axes` must be sorted w.r.t. the mesh.\\n    - The operand sharding and `out_sharding` must have equivalent dimension\\n      shardings.\\n    - `reduction_axes` must not overlap with the operand dimension sharding and\\n      replicated axes (it can overlap with unreduced axes).\\n    - `reduction_axes` must not overlap with the unreduced axes of\\n      `out_sharding`. In other words, `out_sharding` must be be replicated along\\n      `reduction_axes` (implicitly or explicitly).\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_axes\", \"type\": \"Sdy_AxisRefList\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$reduction_axes $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.all_slice\",\n    \"summary\": \"Performs a dynamic-slice operation along axes\",\n    \"description\": \"Slices chunks of a tensor along axes specified in `slicing_axes`. There is\\n    an algebric duality between `sdy.all_slice` and `sdy.all_gather`.\\n\\n    The `slicing_axes` is a list of lists of axes. The outer list is over the\\n    dimensions of the tensor. Each inner list specifies the axes along which a\\n    slice should be performed on the respective dimension. It will be applied to\\n    the sharding of the operand (`tensor`) to obtain the sharding of the result\\n    (`out_sharding`).\\n\\n    Note that `out_sharding` is not used to determine the sharding of the\\n    result. Instead, the sharding of the result is determined by the sharding of\\n    the operand and the `slicing_axes`, and `out_sharding` must match this\\n    inferred sharding.\\n\\n    Example:\\n    ```mlir\\n    %1 = stablehlo.tanh(%0) {sdy.sharding = #sdy.sharding_per_value<[<@mesh, [{\\\"a\\\"}, {}, {}\\\\]>]>} : tensor<8x8x8xf32>\\n    %2 = sdy.all_slice [{\\\"b\\\", \\\"c\\\"}, {}, {\\\"d\\\"}\\\\] %1 out_sharding=<@mesh, [{\\\"a\\\", \\\"b\\\", \\\"c\\\"}, {}, {\\\"d\\\"}\\\\]> : tensor<8x8x8xf32>\\n    ```\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - Elements in `slicing_axes` must satisfy the constraints listed in\\n      `AxisRefListAttr`.\\n    - Applying `slicing_axes` to the operand sharding gets `out_sharding`.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slicing_axes\", \"type\": \"Sdy_ListOfAxisRefLists\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$slicing_axes $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.all_to_all\",\n    \"summary\": \"Performs an all-to-all communication along axes\",\n    \"description\": \"For each (axes, src_dim, tgt_dim) tuple in the parameter list, this\\n    operation slices chunks of a tensor along dimension `tgt_dim` and axes\\n    specified in `axes`, scatteres those chunks along the axes, and concatenates\\n    them along dimension `src_dim`.\\n\\n    This operation is essentially a combination of an all-gather along `src_dim`\\n    and `axes`, followed by an all-slice along `tgt_dim` and `axes`, i.e., a\\n    suffix of the axes sharding dimension `src_dim` on the input tensor is\\n    appended to the axes sharding dimension `tgt_dim` on the output tensor.\\n\\n    The all-to-all will be applied to the sharding of the operand (`tensor`) to\\n    obtain the sharding of the result (`out_sharding`).\\n\\n    Note that `out_sharding` is not used to determine the sharding of the\\n    result. Instead, the sharding of the result is determined by the sharding of\\n    the operand, `src_dim`, `tgt_dim`, and `axes`, and `out_sharding` must match\\n    this inferred sharding.\\n\\n    Example:\\n    ```mlir\\n    %1 = stablehlo.tanh(%0) {sdy.sharding = #sdy.sharding_per_value<[<@mesh, [{\\\"a\\\", \\\"b\\\"}, {\\\"c\\\"}, {}, {}\\\\]>]>} : tensor<8x8x4x4x32>\\n    %2 = sdy.all_to_all [{\\\"b\\\"}: 0->2, {\\\"c\\\"}: 1->3] %1 out_sharding=<@mesh, [{\\\"a\\\"}, {}, {\\\"b\\\"}, {\\\"c\\\"}\\\\]> : tensor<8x8x4x4x32>\\n    ```\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - The parameter list must not be empty.\\n    - For each parameter in `params`:\\n      - Elements in `axes` must satisfy the constraints of `AxisRefAttr`.\\n      - `src_dim` and `tgt_dim` must be valid dimensions (non-negative and less\\n      than rank of tensor).\\n      - Any `src_dim` or `tgt_dim` must be unique across all parameters.\\n      - `src_dim` must be sorted in ascending order across all parameters.\\n    - Moving `axes` from `src_dim` to `tgt_dim` in the operand sharding gets\\n      `out_sharding`.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"params\", \"type\": \"Sdy_AllToAllParamList\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$params $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.collective_permute\",\n    \"summary\": \"Performs a collective-permute communication to replace axes\",\n    \"description\": \"Sends a chunk of the input tensor from each device to another to\\n    reorder/replace the axes that shard the tensor.\\n\\n    A collective permute can transform the input sharding such that each\\n    dimension must be as sharded as it was before, i.e., it must be sharded\\n    along axes whose product of sizes matches that of the axes that previously\\n    sharded the tensor.\\n\\n    This is useful for reordering axes in a single dimension or across different\\n    dimensions, and swapping sharded axes with replicated ones.\\n\\n    In the below example, the sharded tensor size is `tensor<1x4x2xf32>`, and\\n    that is preserved by the collective permute.\\n\\n    Example:\\n    ```mlir\\n    sdy.mesh @mesh = <[\\\"a\\\"=2, \\\"b\\\"=2, \\\"c\\\"=4, \\\"d\\\"=2, \\\"e\\\"=2, \\\"f\\\"=2]>\\n    %1 = stablehlo.tanh(%0) {sdy.sharding = #sdy.sharding_per_value<[<@mesh, [{\\\"a\\\", \\\"c\\\"}, {\\\"f\\\"}, {\\\"d\\\", \\\"e\\\"}\\\\]>]>} : tensor<8x8x8xf32>\\n    %2 = sdy.collective_permute %1 out_sharding=<@mesh, [{\\\"c\\\":(1)2, \\\"b\\\", \\\"f\\\"}, {\\\"a\\\"}, {\\\"e\\\", \\\"d\\\"}\\\\]> : tensor<8x8x8xf32>\\n    ```\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - If input and output sharding have different meshes, then those meshes must\\n      have exactly the same axes and different order of device ids.\\n    - For each dimension, the product of sharding axis sizes in `out_sharding`\\n      must match that of the corresponding operand dimension sharding.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.constant\",\n    \"summary\": \"Constant operation\",\n    \"description\": \"Produces an `output` tensor from a constant `value`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#constant\\n\\n    NOTE: SDY defines its own constant op that isn't ConstantLike and doesn't\\n    have a folder, so that we'll be able to duplicate constants without any\\n    greedy pattern rewriter folding them back into a single constant. In this\\n    way, constants can be sharded differently for every use, and no propagation\\n    is done between constants (or constant expressions).\\n\\n    Example:\\n    ```mlir\\n    %output = sdy.constant dense<[[0.0, 1.0], [2.0, 3.0]]> : tensor<2x2xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyStaticShapeTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sdy.data_flow_edge\",\n    \"summary\": \"data flow edge op.\",\n    \"description\": \"A data flow edge of some op X defines a bridge between a set of sources\\n    (each is either an operand of X or an operand of X's block terminator) and\\n    a set of targets (each is either a result of X or a block argument of X),\\n    such that all sources and targets should be sharded in the same way.\\n\\n    An op can have multiple data flow edges that are orthogonal to one another.\\n\\n    For example:\\n\\n    ```mlir\\n      y_0, ..., y_n = while (x_0, ..., x_n)\\n                      ((pred_arg_0,... , pred_arg_n) { ... })\\n                      ((body_arg_0,..., body_arg_n) {\\n                        ...\\n                        return return_value_0, ..., return_value_n\\n                      })\\n    ```\\n\\n    This while op has n data flow edges, the i-th data flow edges is between\\n    sources `x_i`, `return_value_i` and targets `y_i`, `pred_arg_i`,\\n    `body_arg_i`.\\n\\n    An `sdy.data_flow_edge` takes as input the owner of an edge (can be\\n    any of the targets, but preferably an op result rather than a block\\n    argument), which shouldn't have any other uses. This op isn't pure because\\n    it can take an input that originally didn't have any uses.\\n\\n    The `sdy.data_flow_edge` also holds an optional sharding for all targets of\\n    the edge, and that sharding should be updated instead of the targets'\\n    sharding (if can be attached) during propagation. This is useful when an op\\n    has many edges, as it's much more efficient to:\\n    - propagate through each edge separately.\\n    - update the sharding of each edge separately instead of all targets at once\\n      (e.g. an op has a single immutable `TensorShardingPerValueAttr` for result\\n      shardings).\\n    - add each edge to the worklist separately when the sharding of a source has\\n      changed.\\n\\n    Propagation will propagate shardings between all sources and targets of a\\n    `sdy.data_flow_edge` as if it was a regular op with the sources as operands\\n    and targets as results, and an identity `sdy.op_sharding_rule`. That means\\n    that forward propagation is from sources to targets and backwards\\n    propagation is from targets to sources.\\n\\n    We don't allow the input of a `sdy.data_flow_edge` to be defined by an\\n    `SdyDialect` op, so we can assume that it's defined by an op that has\\n    unregistered `sdy.sharding` attribute.\\n\\n    NOTE: it's NOT the responsibility of the `sdy.data_flow_edge` to link\\n    between sources and targets, it's simply attached to the owner of the edge.\\n    The op that this edge is bound to (while in the example above) is\\n    responsible for providing this information.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sharding\", \"type\": \"OptionalAttr<Sdy_TensorSharding>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input (`sharding````=``` $sharding^)? attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.manual_computation\",\n    \"summary\": \"Multi-device parallelism operation with manual collectives\",\n    \"description\": \"Jump into a region written in terms of per-device local code with explicit\\n    collectives, where logical shapes match local per-device physical buffer\\n    shapes and collectives correspond exactly to physical cross-device\\n    communication.\\n\\n    The body is local wrt the manual_axes. Propagation will occur through\\n    the body on any free axes - those not in the manual_axes list.\\n\\n    Note that any unranked tensors are expected to have a sharding with rank 0,\\n    i.e. fully replicated.\\n\\n    **Constraints:**\\n    - Elements in `in_shardings` and `out_shardings` must satisfy the constraints listed in `TensorShardingAttr`.\\n    - The number of global and local tensor inputs/outputs of the op region must match.\\n    - The manual axes must come before any free axes in each dim sharding.\\n    - The manual axes cannot introduce padding. Namely, the dimension size must be divisible by the corresponding manual axes size.\\n    - The global and local shapes of the op regions arguments/results must match.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_shardings\", \"type\": \"Sdy_TensorShardingPerValue\" },\n      { \"name\": \"out_shardings\", \"type\": \"Sdy_TensorShardingPerValue\" },\n      { \"name\": \"manual_axes\", \"type\": \"Sdy_ManualAxes\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(`operands`)`\\n    `in_shardings````=```custom<StrippedTensorShardingPerValueAttr>($in_shardings)\\n    `out_shardings````=```custom<StrippedTensorShardingPerValueAttr>($out_shardings)\\n    `manual_axes````=```$manual_axes\\n    custom<SingleBlockRegionNoBlockId>($body)\\n    attr-dict\\n    `:`\\n    functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"sdy.mesh\",\n    \"summary\": \"Named mesh\",\n    \"description\": \"Defines a new named mesh. All meshes in a module must have the same number\\n    of devices (except for meshes with a single device_id).\\n    The mesh is a `Symbol` operation that appears in the module's\\n    `SymbolTable` and can be referenced by its `name`.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"mesh\", \"type\": \"Sdy_Mesh\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `=` $mesh attr-dict\"\n  },\n  {\n    \"name\": \"sdy.named_computation\",\n    \"summary\": \"named computation operation\",\n    \"description\": \"Groups a computation, i.e. a block of operations, and gives it a name.\\n    Propagation will flow in/out of the region as if everything was inlined.\\n\\n    This can be used to handle propagating through call instructions to other\\n    functions. Any users of Shardy should write an import/export pass that\\n    converts their call ops to `sdy.named_computation` ops, duplicating/copying\\n    the body of the called function into the body of the `named_computation`.\\n\\n    The type of each block arguments and returned values in the region must be\\n    the same as the type of the operands and results type of the op.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = sdy.named_computation<\\\"foo\\\">(%0) (%arg1: tensor<16x32xf32>) {\\n      sdy.return %arg1 : tensor<16x32xf32>\\n    } : (tensor<16x32xf32>) -> tensor<16x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"in_shardings\", \"type\": \"OptionalAttr<Sdy_TensorShardingPerValue>\" },\n      { \"name\": \"out_shardings\", \"type\": \"OptionalAttr<Sdy_TensorShardingPerValue>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`<`$name`>` `` `(` $operands `)`\\n    (`in_shardings````=```custom<StrippedTensorShardingPerValueAttr>($in_shardings)^)?\\n    (`out_shardings````=```custom<StrippedTensorShardingPerValueAttr>($out_shardings)^)?\\n    custom<SingleBlockRegionNoBlockId>($body)\\n    attr-dict\\n    `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"sdy.propagation_barrier\",\n    \"summary\": \"Propagation barrier operation\",\n    \"description\": \"This op operates like an identity op, outputting the same value it took as\\n    input. But in terms of propagation, this will only allow propagation to flow\\n    through it in a certain direction.\\n\\n    This prevents shardings from being propagated between the uses of the result\\n    of the barrier op and its operand.\\n\\n    - `FORWARD` means shardings can only flow from the operand to the result.\\n    - `BACKWARD` means shardings can only flow from the result to the operand.\\n    - `NONE` means no sharding can propagate through this op.\\n    - Cannot specify `BOTH`, as this op would be redundant.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"allowed_direction\", \"type\": \"Sdy_PropagationDirection{NONE|FORWARD|BACKWARD|BOTH}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input `allowed_direction````=```$allowed_direction attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"sdy.reduce_scatter\",\n    \"summary\": \"Performs a reduce-scatter communication along axes\",\n    \"description\": \"Reduces chunks of a tensor along axes specified in `reduce_scatter_axes`,\\n    and then scatters the result along the same axes. This operation is\\n    essentially a combination of an `sdy.all_reduce` followed by an\\n    `sdy.all_slice` along the same `reduce_scatter_axes`.\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - Elements in `reduce_scatter_axes` must satisfy the constraints listed in\\n      `AxisRefListAttr`.\\n    - Applying `reduce_scatter_axes` to the operand sharding gets\\n      `out_sharding`.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_scatter_axes\", \"type\": \"Sdy_ListOfAxisRefLists\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$reduce_scatter_axes $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.replicated_to_unreduced\",\n    \"summary\": \"Move implicitly or explicitly replicated axes to unreduced axes.\",\n    \"description\": \"The `axes` should be implicitly or explicitly replicated in the operand.\\n    This operation makes them unreduced in the result. We have the following\\n    relationship:\\n\\n    all-reduce(replicated-to-unreduced(x, axes), axes) = x\\n\\n    Example:\\n    ```mlir\\n    %1 = stablehlo.tanh(%0) {sdy.sharding = #sdy.sharding_per_value<[<@mesh, [{\\\"b\\\"}, {}, {}\\\\], replicated={\\\"c\\\", \\\"d\\\"}, unreduced={\\\"e\\\"}>]>} : tensor<8x8x8xf32>\\n    %2 = sdy.replicated_to_unreduced {\\\"a\\\", \\\"c\\\", \\\"f\\\"} %1 out_sharding=<@mesh, [{\\\"b\\\"}, {}, {}\\\\], replicated={\\\"d\\\"}, unreduced={\\\"a\\\", \\\"c\\\", \\\"e\\\", \\\"f\\\"}> : tensor<8x8x8xf32>\\n    ```\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - `axes` must satisfy the constraints listed in `AxisRefListAttr`.\\n    - `axes` must be sorted w.r.t. the mesh.\\n    - `axes` are not empty.\\n    - The input and output sharding must have the same dimension shardings.\\n    - `axes` must be implicitly or explicitly replicated in the operand sharding.\\n    - inUnreducedAxes + axes = outUnreducedAxes.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"Sdy_AxisRefList\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$axes $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.reshard\",\n    \"summary\": \"Reshards a tensor to a different sharding\",\n    \"description\": \"Reshards the input tensor with the specified sharding, which is different\\n    from the input tensor's existing sharding.\\n\\n    Both ShardingConstraintOp and ReshardOp attach a sharding to a tensor. Their\\n    lifespan is:\\n    1. Before sharding propagation, ShardingConstraintOp is added by users.\\n    2. Sharding propagation consumes ShardingConstraintOp. There is no\\n       ShardingConstraintOp in the results of sharding propagation. Instead,\\n       ReshardOp may be added if needed.\\n    3. A partitioner converts a ReshardOp into a collective op (or an identity\\n       op). There should be no ReshardOp in the results of the partitioner.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$input $sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.return\",\n    \"summary\": \"The `sdy.return` operation terminates the regions attached to\\n    `sdy` region-based ops and any other Shardy region-based ops. It is\\n    variadic: it takes as arguments a list of values whose types can be any (but\\n    of the same kind, e.g. `AnyTensor`) and therefore can be reused at various\\n    levels of the Shardy IR stack.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"sdy.sharded_to_unreduced\",\n    \"summary\": \"Move some sharded axes of the operand to unreduced axes of the result.\",\n    \"description\": \"The `axes` should be used to shard the operand. This operation makes them\\n    unreduced in the result. We have the following relationship:\\n\\n    all-gather(x, axes) = all-reduce(sharded-to-unreduced(x, axes), axes), where\\n    all-gather, sharded-to-unreduced, all-reduce are applied on the same axes.\\n\\n    Example:\\n    ```mlir\\n    %1 = stablehlo.tanh(%0) {sdy.sharding = #sdy.sharding_per_value<[<@mesh, [{\\\"a\\\", \\\"b\\\", \\\"c\\\"}, {}, {\\\"d\\\"}\\\\], unreduced={\\\"e\\\"}>]>} : tensor<8x8x8xf32>\\n    %2 = sdy.sharded_to_unreduced [{\\\"b\\\", \\\"c\\\"}, {}, {\\\"d\\\"}\\\\] %1 out_sharding=<@mesh, [{\\\"a\\\"}, {}, {}\\\\], unreduced={\\\"b\\\", \\\"c\\\", \\\"d\\\", \\\"e\\\"}> : tensor<8x8x8xf32>\\n    ```\\n\\n    **Constraints:**\\n    - Must satisfy the constraints listed in `Sdy_CollectiveOpInterface`.\\n    - Elements in `axes` must satisfy the constraints listed in `AxisRefListAttr`.\\n    - Applying `axes` to the operand sharding gets `out_sharding`.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"Sdy_ListOfAxisRefLists\" },\n      { \"name\": \"out_sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$axes $tensor `out_sharding````=```$out_sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.sharding_constraint\",\n    \"summary\": \"Constrains a tensor to the specified sharding\",\n    \"description\": \"Attaches a sharding to an intermediate tensor (e.g. the result of a matmul)\\n    to indicate that this is how that tensor, or a subset of its uses, should be\\n    sharded.\\n\\n    If the sharding has open dimensions and unconstraint axes, it means the\\n    tensor can be further sharded along the open dimensions.\\n\\n    This op can either:\\n    - Have no uses (dangling) - which means the attached sharding is how the\\n      input tensor itself should be sharded.\\n    - Have uses - which means the attached sharding is how the uses of the\\n      sharding constraint op should be sharded, while other uses of the input\\n      tensor might have a different sharding (if the input tensor has no other\\n      uses then the behavior is the same as the no uses case).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sharding\", \"type\": \"Sdy_TensorSharding\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" },\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$input $sharding attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"sdy.sharding_group\",\n    \"summary\": \"Constrains tensors in the group to have the same sharding.\",\n    \"description\": \"This op provides an interface to assign tensors to sharding groups (\\n    groups of tensors that will be enforced to have identical shardings).\\n    During propagation, as soon as one group element is sharded, all other\\n    members will be sharded in exactly the same way. This operation takes the\\n    argument group ID and returns no result, but instead modifies the internal\\n    sharding group representation to add the input tensor to the group with the\\n    given ID.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group_id\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$input `group_id````=```$group_id attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"shape.add\",\n    \"summary\": \"Addition of sizes and indices\",\n    \"description\": \"Adds two sizes or indices. If either operand is an error it will be\\n    propagated to the result. The operands can be of type `size` or `index`. If\\n    at least one of the operands can hold an error, i.e. if it is of type\\n    `size`, the result must be of type `size`. If error propagation is not\\n    possible because both operands are of type `index` then the result may be\\n    of type `size` or `index`.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Shape_SizeOrIndexType\" },\n      { \"name\": \"rhs\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.any\",\n    \"summary\": \"Return any combination of the input shapes\",\n    \"description\": \"This operation takes multiple input shapes or extent tensors and returns\\n    some combination of their dimensions. This can be best seen with examples\\n    below.\\n\\n    The result is undefined, but still side-effect free, in cases where the\\n    inputs have differing ranks or differ in extents of shared dimensions.\\n\\n    Example:\\n    ```mlir\\n    %s0 = shape.any [2,?], [?,3] // [2,3]\\n    %s1 = shape.any [?,?], [1,2] // [1,2]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Shape_ShapeOrExtentTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` type($inputs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.assuming\",\n    \"summary\": \"Execute the region\",\n    \"description\": \"Executes the region assuming all witnesses are true.\\n\\n    \\\"assuming\\\" operations represent an execution order restriction to the\\n    compiler, information for dependent code to rely on (by assuming), and\\n    nothing else. They should not exist after a program is fully lowered and\\n    ready to execute.\",\n    \"operands\": [\n      { \"name\": \"witness\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"doRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"shape.assuming_all\",\n    \"summary\": \"Return a logical AND of all witnesses\",\n    \"description\": \"Used to simplify constraints as any single failing precondition is enough\\n    to prevent execution.\\n\\n    \\\"assuming\\\" operations represent an execution order restriction to the\\n    compiler, information for dependent code to rely on (by assuming), and\\n    nothing else. They should not exist after a program is fully lowered and\\n    ready to execute.\\n\\n    Example:\\n    ```mlir\\n    %w0 = shape.cstr_broadcastable [2,2], [3,1,2] // Passing\\n    %w1 = shape.cstr_broadcastable [2,2], [3,2] // Failure\\n    %w2 = shape.cstr_eq [1,2], [1,2], [1,2] // Passing\\n    %wf = shape.assuming_all %w0, %w1 // Failure\\n    %wt = shape.assuming_all %w0, %w2 // Passing\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Shape_WitnessType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\"\n  },\n  {\n    \"name\": \"shape.assuming_yield\",\n    \"summary\": \"Yield operation\",\n    \"description\": \"This yield operation represents a return operation within the\\n    `shape.assuming` operation region. The operation takes variable number of\\n    operands and produces no results. The operand number and types must match\\n    the number and types of parent `shape.assuming` results.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"shape.broadcast\",\n    \"summary\": \"Returns the broadcasted output shape of two or more inputs\",\n    \"description\": \"Returns the broadcasted shape for input shapes or extent tensors. The rest\\n    of this description is simplified for the 2 input case but can be extended\\n    to more inputs. Both operands can be of type `shape.shape` or\\n    `tensor<?xindex>`. The result is of type `shape.shape` and, if both\\n    operands are tensors, may be of type `tensor<?xindex>`.\\n\\n    If the two operand shapes are of different rank the smaller one is padded\\n    with 1's from the left. The resulting broadcasted shape is then defined as\\n\\n        result[i] = lhs[i] if lhs[i] == rhs[i]\\n                  = lhs[i] if rhs[i] == 1\\n                  = rhs[i] if lhs[i] == 1.\\n\\n    In case the resulting shape is undefined, i.e. if corresponding extents are\\n    different from each other but none is 1, the result is an error shape.\\n    Likewise error values are propagated if any of the operands holds an error\\n    value. If the result type is an extent tensor (and can therefore not hold\\n    the error value) the behavior may be undefined. The optional string\\n    attribute can be used to describe the error case.\",\n    \"operands\": [\n      { \"name\": \"shapes\", \"type\": \"Variadic<Shape_ShapeOrExtentTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"error\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$shapes attr-dict `:` type($shapes) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.concat\",\n    \"summary\": \"Concatenates two shapes\",\n    \"description\": \"Creates a shape whose dimensions consist of first the dimensions from `lhs`\\n    followed by the dimensions of `rhs`.\\n\\n    Example:\\n    concat([2,3], [4,5]) -> [2,3,4,5]\\n    concat([], []) -> []\\n    concat([], [4,5,6]) -> [4,5,6]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Shape_ShapeOrExtentTensorType\" },\n      { \"name\": \"rhs\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.const_shape\",\n    \"summary\": \"Creates a constant shape or extent tensor\",\n    \"description\": \"Creates a constant shape or extent tensor. The individual extents are given\\n    as the `shape` attribute. The number of these values equals the shape's\\n    rank.\\n\\n    ```mlir\\n    %0 = shape.const_shape [] : !shape.shape\\n    %1 = shape.const_shape [1, 2, 3] : !shape.shape\\n    %2 = shape.const_shape [4, 5, 6] : tensor<3xindex>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"IndexElementsAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"shape.const_size\",\n    \"summary\": \"Creates a constant of type `shape.size`\",\n    \"description\": \"Creates a `shape.size` type representing the constant size given by `value`.\\n\\n    ```mlir\\n    %x = shape.const_size 10\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_SizeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"shape.const_witness\",\n    \"summary\": \"An operation that returns a statically known witness value\",\n    \"description\": \"This operation represents a statically known witness result. This can be\\n  often used to canonicalize/fold constraint and assuming code that will always\\n  pass.\\n\\n  ```mlir\\n  %0 = shape.const_shape [1,2,3]\\n  %1 = shape.const_shape [1,2,3]\\n  %w0 = shape.cstr_eq(%0, %1) // Can be folded to \\\"const_witness true\\\"\\n  %w1 = shape.const_witness true\\n  %w2 = shape.assuming_all(%w0, %w2) // Can be folded to \\\"const_witness true\\\"\\n  ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"passing\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"$passing attr-dict\"\n  },\n  {\n    \"name\": \"shape.cstr_broadcastable\",\n    \"summary\": \"Determines if 2+ shapes can be successfully broadcasted\",\n    \"description\": \"Given input shapes or extent tensors, return a witness specifying if they\\n    are broadcastable. This broadcastable follows the same logic as what\\n    shape.broadcast documents.\\n\\n    \\\"cstr\\\" operations represent runtime assertions.\\n\\n    Example:\\n    ```mlir\\n    %w0 = shape.cstr_broadcastable [2,2], [3,1,2] // Passing\\n    %w1 = shape.cstr_broadcastable [2,2], [3,2] // Failure\\n    ```\",\n    \"operands\": [\n      { \"name\": \"shapes\", \"type\": \"Variadic<Shape_ShapeOrExtentTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"assemblyFormat\": \"$shapes attr-dict `:` type($shapes)\"\n  },\n  {\n    \"name\": \"shape.cstr_eq\",\n    \"summary\": \"Determines if all input shapes are equal\",\n    \"description\": \"Given 1 or more input shapes, determine if all shapes are the exact same.\\n\\n    \\\"cstr\\\" operations represent runtime assertions.\\n\\n    Example:\\n    ```mlir\\n    %w0 = shape.cstr_eq [1,2], [1,2], [1,2] // Passing\\n    %w1 = shape.cstr_eq [2,2], [1,2] // Failure\\n    ```\",\n    \"operands\": [\n      { \"name\": \"shapes\", \"type\": \"Variadic<Shape_ShapeOrExtentTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"assemblyFormat\": \"$shapes attr-dict `:` type($shapes)\"\n  },\n  {\n    \"name\": \"shape.cstr_require\",\n    \"summary\": \"Represents a runtime assertion that an i1 is `true`\",\n    \"description\": \"Represents a runtime assertion that an i1 is true. It returns a\\n    !shape.witness to order this assertion.\\n\\n    For simplicity, prefer using other cstr_* ops if they are available for a\\n    given constraint.\\n\\n    Example:\\n    ```mlir\\n    %bool = ...\\n    %w0 = shape.cstr_require %bool, \\\"msg\\\" // Passing if `%bool` is true.\\n    ```\\n\\n    Since this op can be used to express many different possible assertions\\n    (depending on whatever computation calculated `pred`), the `msg`\\n    should clarify the nature of the assertion for users.\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_WitnessType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$pred `,` $msg attr-dict\"\n  },\n  {\n    \"name\": \"shape.debug_print\",\n    \"summary\": \"Prints the input shape or size\",\n    \"description\": \"Prints the input dim or shape and passes through input.\\n\\n    Note: This is intended for testing and debugging only.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Shape_ShapeOrSizeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Shape_ShapeOrSizeType\" }\n    ]\n  },\n  {\n    \"name\": \"shape.dim\",\n    \"summary\": \"Gets the specified extent from the shape of a shaped input\",\n    \"description\": \"Gets the extent indexed by `dim` from the shape of the `value` operand. If\\n    the index is error or out-of-bound then it returns an invalid size if the\\n    return type carries error information else the behavior is undefined.\\n\\n    This is a convenience op that performs the equivalent of getting the extent\\n    of a shape (e.g., `dim(x, i) == get_extent(shape_of(x), i)`).\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyShaped\" },\n      { \"name\": \"index\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"extent\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $index attr-dict `:` type($value) `,`type($index) `->` type($extent)\"\n  },\n  {\n    \"name\": \"shape.div\",\n    \"summary\": \"Division of sizes and indices\",\n    \"description\": \"Divides two sizes or indices. If either operand is an error it will be\\n    propagated to the result. The operands can be of type `size` or `index`.\\n    If at least one of the operands can hold an error, i.e. if it is of type\\n    `size`, the result must be of type `size`. If error propagation is not\\n    possible because both operands are of type `index` then the result may be\\n    of type  `size` or `index`. If both operands and result are of type\\n    `index`, their runtime values could be negative. The result is rounded\\n    toward negative infinity, i.e. floor(lhs / rhs), such that\\n\\n        div(lhs, rhs) * rhs + mod(lhs, rhs) = lhs\\n\\n    always holds. If any of the values is of type `size`, the behavior for\\n    negative value is undefined.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Shape_SizeOrIndexType\" },\n      { \"name\": \"rhs\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.from_extent_tensor\",\n    \"summary\": \"Creates a shape from a tensor of extents\",\n    \"description\": \"Creates a shape from a 1D integral tensor of extents. The rank of the\\n    resulting shape equals the number of elements in the tensor, and the\\n    extents match the values of the elements.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"1DTensorOf<[Index]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"shape.from_extents\",\n    \"summary\": \"Creates a shape from extents\",\n    \"description\": \"Creates a shape from multiple SSA values representing the extents of\\n    the shape.\\n\\n    ```mlir\\n    // Rank 2 shape.\\n    %s0 = shape.from_extents %a, %b\\n    // Rank 0 shape.\\n    %s1 = shape.from_extents\\n    ```\",\n    \"operands\": [\n      { \"name\": \"extents\", \"type\": \"Variadic<Shape_SizeOrIndexType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"shape\", \"type\": \"Shape_ShapeType\" }\n    ],\n    \"assemblyFormat\": \"$extents attr-dict `:` type($extents)\"\n  },\n  {\n    \"name\": \"shape.func\",\n    \"summary\": \"Shape function\",\n    \"description\": \"An operation with a name containing a single `SSACFG` region which\\n    represents a shape transfer function or helper function for shape transfer\\n    function.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"shape\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"shape.function_library\",\n    \"summary\": \"Represents shape functions and corresponding ops\",\n    \"description\": \"Represents a list of shape functions and the ops whose shape transfer\\n    functions they represent.\\n\\n    Example:\\n\\n    ```mlir\\n    shape.function_library {\\n      func @same_result_shape(%arg: !shape.value_shape) -> !shape.shape {\\n        %0 = shape_of %arg : !shape.value_shape -> !shape.shape\\n        return %0 : !shape.shape\\n      }\\n    } mapping {\\n      std.atan = @same_result_shape\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"mapping\", \"type\": \"DictionaryAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"shape\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"shape.get_extent\",\n    \"summary\": \"Gets the specified extent from a shape or extent tensor\",\n    \"description\": \"Gets the extent indexed by `dim` from the `shape` operand. If the shape is\\n    an error then it returns an invalid size.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Shape_ShapeOrExtentTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"extent\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$shape `,` $dim attr-dict `:` type($shape) `,` type($dim) `->` type($extent)\"\n  },\n  {\n    \"name\": \"shape.index_to_size\",\n    \"summary\": \"Converts a standard index to a shape size\",\n    \"description\": \"Converts a standard index to a `shape.size`. This operation and its\\n    inverse, `size_to_index`, facilitate index conversion between the standard\\n    and the shape dialect.\\n\\n    The behavior is undefined for negative indices.\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_SizeType\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict\"\n  },\n  {\n    \"name\": \"shape.is_broadcastable\",\n    \"summary\": \"Determines if 2+ shapes can be successfully broadcasted\",\n    \"description\": \"Given multiple input shapes or extent tensors, return a predicate\\n    specifying if they are broadcastable. This broadcastable follows the same\\n    logic as what shape.broadcast documents.\\n\\n    Concretely, shape.is_broadcastable returning true implies that\\n    shape.broadcast will not give an error, and shape.cstr_broadcastable will\\n    not result in an assertion failure. Similarly, false implies an error or\\n    assertion failure.\\n\\n    Example:\\n    ```mlir\\n    %true = shape.is_broadcastable [2,2], [3,1,2]\\n    %false = shape.is_broadcastable [2,2], [3,2]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"shapes\", \"type\": \"Variadic<Shape_ShapeOrExtentTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$shapes attr-dict `:` type($shapes)\"\n  },\n  {\n    \"name\": \"shape.max\",\n    \"summary\": \"Elementwise maximum\",\n    \"description\": \"Computes the elementwise maximum of two sizes or shapes with equal ranks.\\n    If either operand is an error, then an error will be propagated to the\\n    result. If the input types mismatch or the ranks do not match, then the\\n    result is an error.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Shape_ShapeOrSizeType\" },\n      { \"name\": \"rhs\", \"type\": \"Shape_ShapeOrSizeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrSizeType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.meet\",\n    \"summary\": \"Returns the least general shape or size of its operands\",\n    \"description\": \"An operation that computes the least general shape or dim of input operands.\\n    This effectively asserts that corresponding static dimensions are equal.\\n    The behavior is to match each element of the shape/size and propagate the\\n    most restrictive information, returning an invalid shape if there are\\n    contradictory requirements. E.g., using pseudo code\\n\\n    ```\\n    shape.meet([*], [*]) -> [*]\\n    shape.meet([*], [1, ?]) -> [1, ?]\\n    shape.meet([1, 2], [1, ?]) -> [1, 2]\\n    shape.meet([*], [1, 2]) -> [1, 2]\\n    shape.meet([], []) -> []\\n    shape.meet([], [*]) -> []\\n    shape.meet([], [?, ?]) -> [invalid]\\n    shape.meet([1, ?], [2, ?, ?]) -> [invalid]\\n    ```\\n\\n    `shape.meet` also allows specifying an optional error string, that may be\\n    used to return an error to the user upon mismatch of dimensions.\\n\\n    ```mlir\\n    %c = shape.meet %a, %b, error=\\\"<reason>\\\" : !shape.shape, !shape.shape -> !shape.shape\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"Shape_AnyShapeOrSizeType\" },\n      { \"name\": \"arg1\", \"type\": \"Shape_AnyShapeOrSizeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_AnyShapeOrSizeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"error\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$arg0 `,` $arg1 (`,` `error` `=` $error^)? attr-dict `:`\\n      type($arg0) `,` type($arg1) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.min\",\n    \"summary\": \"Elementwise minimum\",\n    \"description\": \"Computes the elementwise minimum of two sizes or shapes with equal ranks.\\n    If either operand is an error, then an error will be propagated to the\\n    result. If the input types mismatch or the ranks do not match, then the\\n    result is an error.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Shape_ShapeOrSizeType\" },\n      { \"name\": \"rhs\", \"type\": \"Shape_ShapeOrSizeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrSizeType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.mul\",\n    \"summary\": \"Multiplication of sizes and indices\",\n    \"description\": \"Multiplies two sizes or indices. If either operand is an error it will be\\n    propagated to the result. The operands can be of type `size` or `index`. If\\n    at least one of the operands can hold an error, i.e. if it is of type\\n    `size`, the result must be of type `size`. If error propagation is not\\n    possible because both operands are of type `index` then the result may be\\n    of type `size` or `index`.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Shape_SizeOrIndexType\" },\n      { \"name\": \"rhs\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.num_elements\",\n    \"summary\": \"Returns the number of elements for a given shape\",\n    \"description\": \"Returns the number of elements for a given shape which is the product of\\n    its extents. If the argument is of type `shape` then the result will be of\\n    type `size` and potential errors will be propagated. Otherwise, if the\\n    argument is and extent tensor `tensor<?xindex>` then the result will be of\\n    type `index`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict `:` type($shape) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.rank\",\n    \"summary\": \"Gets the rank of a shape\",\n    \"description\": \"Returns the rank of the shape or extent tensor, i.e. the number of extents.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"rank\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict `:` type($shape) `->` type($rank)\"\n  },\n  {\n    \"name\": \"shape.reduce\",\n    \"summary\": \"Returns an expression reduced over a shape or extent tensor\",\n    \"description\": \"An operation that takes as input a shape or extent tensor, and a number of\\n    initial values. This operation has a region that is applied repeatedly for\\n    every extent of the input. Starting with the initial values, the individual\\n    extents are then aggregated as defined by the associated region.\\n\\n    Conceptually this op performs the following reduction:\\n\\n    ```\\n    res[] = init;\\n    for (int i = 0, i < shape.rank(); i++) {\\n      res = reduce(i, shape[i], res[0], ..., res[n]);\\n    }\\n    ```\\n\\n    Where `reduce` represents the region attached and the result of the reduce\\n    op is the last computed output of the reduce region. As an example, the\\n    number of elements can be computed as follows:\\n\\n    ```mlir\\n    func.func @reduce(%shape : !shape.shape, %init : !shape.size) ->\\n        !shape.size {\\n      %num_elements = shape.reduce(%shape, %init) -> !shape.size  {\\n        ^bb0(%index: index, %dim: !shape.size, %acc: !shape.size):\\n          %updated_acc = \\\"shape.mul\\\"(%acc, %dim) :\\n            (!shape.size, !shape.size) -> !shape.size\\n          shape.yield %updated_acc : !shape.size\\n      }\\n      return %num_elements : !shape.size\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Shape_ShapeOrExtentTensorType\" },\n      { \"name\": \"initVals\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"shape.return\",\n    \"summary\": \"Shape function return operation\",\n    \"description\": \"The `shape.return` operation represents a return operation within a\\n    function.  The operation takes variable number of operands and produces no\\n    results.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"shape.shape_eq\",\n    \"summary\": \"Returns whether the input shapes or extent tensors are equal\",\n    \"description\": \"Takes one or more shape or extent tensor operands and determines whether\\n    they are equal. When extent tensors are compared to shapes they are\\n    regarded as their equivalent non-error shapes. Error shapes can be tested\\n    for equality like any other shape value, meaning that the error value is\\n    equal to itself.\",\n    \"operands\": [\n      { \"name\": \"shapes\", \"type\": \"Variadic<Shape_ShapeOrExtentTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$shapes attr-dict `:` type($shapes)\"\n  },\n  {\n    \"name\": \"shape.shape_of\",\n    \"summary\": \"Returns shape of a value or shaped type operand\",\n    \"description\": \"The operation takes a value or a shaped operand as an argument and it\\n    returns a shape or extent tensor.\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"AnyTypeOf<[AnyShaped, Shape_ValueShapeType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.size_to_index\",\n    \"summary\": \"Casts between index types of the shape and standard dialect\",\n    \"description\": \"Converts a `shape.size` to a standard index. This operation and its\\n    inverse, `index_to_size`, facilitate index conversion between the standard\\n    and the shape dialect. The behavior is undefined for unknown and invalid\\n    arguments.\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg)\"\n  },\n  {\n    \"name\": \"shape.split_at\",\n    \"summary\": \"Splits a shape at a given index\",\n    \"description\": \"Splits a shape at a given dimension `index`, returning two shapes. If\\n    `index` is negative, it is treated as indexing from the back of the shape.\\n    This negative-handling behavior is important when handling unranked shapes,\\n    where the positive index is not necessarily knowable due to a dynamic\\n    number of leading dimensions. If the result is in extent tensor form out of\\n    bounds indices result in undefined behavior.\\n\\n    Examples:\\n    - split_at([4,5,6], index=0) -> [], [4,5,6]\\n    - split_at([4,5,6], index=1) -> [4], [5,6]\\n    - split_at([4,5,6], index=2) -> [4,5], [6]\\n    - split_at([4,5,6], index=3) -> [4,5,6], []\\n    - split_at([4,5,6], index=4) -> error\\n    - split_at([4,5,6], index=-1) -> [4,5], [6]\\n    - split_at([4,5,6], index=-2) -> [4], [5,6]\\n    - split_at([4,5,6], index=-3) -> [], [4,5,6]\\n    - split_at([4,5,6], index=-4) -> error\\n\\n    Requires:\\n    - `index` is in the range [-rank(operand),rank(operand)]\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Shape_ShapeOrExtentTensorType\" },\n      { \"name\": \"index\", \"type\": \"Shape_SizeOrIndexType\" }\n    ],\n    \"results\": [\n      { \"name\": \"head\", \"type\": \"Shape_ShapeOrExtentTensorType\" },\n      { \"name\": \"tail\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ]\n  },\n  {\n    \"name\": \"shape.to_extent_tensor\",\n    \"summary\": \"Creates a dimension tensor from a shape\",\n    \"description\": \"Converts a shape to a 1D integral tensor of extents. The number of elements\\n    in the tensor equals the rank of the shape, and the elements equal the\\n    extents of the shape.\\n\\n    If the shape represents an error, this op's behavior is undefined.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IndexTensor\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.value_as_shape\",\n    \"summary\": \"Returns value as a shape\",\n    \"description\": \"The operations takes a ValueShape and returns a Shape corresponding to the\\n    value.  If the input value cannot be shape (e.g., not a 1D tensor of\\n    integral value representing sizes) then this propagages the error shape.\\n    E.g.,\\n\\n    ```mlir\\n    // The following\\n    %0 = arith.constant dense<[1,2]> : tensor<2xi32>\\n    %shape = shape.value_as_shape %0 : tensor<2xi32> -> !shape.shape\\n    // is equivalent to\\n    %shape' = shape.const_shape [1, 2] : !shape.shape\\n    ```\\n\\n    This operation is the complement of `shape_of` wrt ValueShape values.\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"AnyTypeOf<[1DTensorOf<[AnyInteger, Index]>, Shape_ValueShapeType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($arg) `->` type($result)\"\n  },\n  {\n    \"name\": \"shape.value_of\",\n    \"summary\": \"Returns value of a !shape.value_shape operand\",\n    \"description\": \"The operation takes !shape.value_shape, a.k.a. (value, shape) tuple as an\\n    argument, and returns its value. The behavior is undefined for unknown and\\n    invalid arguments.\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Shape_ValueShapeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"shape.with_shape\",\n    \"summary\": \"Returns ValueShape with given shape\",\n    \"description\": \"Returns ValueShape with the shape updated to match the shape operand. That\\n    is a new ValueShape tuple is created with value equal to `operand`'s\\n    value and shape equal to `shape`. If the ValueShape and given `shape` are\\n    non-conformant, then the returned ValueShape will represent an error of\\n    this mismatch. Similarly if either inputs are in an error state, then an\\n    error is propagated.\\n\\n    Usage:\\n      %0 = shape.with_shape %1, %2 : tensor<...>, !shape.shape\\n\\n    This is used, for example, where one combines shape function calculations\\n    and/or call one shape function from another. E.g.,\\n\\n    ```mlir\\n    func.func @shape_foobah(%a: !shape.value_shape,\\n                       %b: !shape.value_shape,\\n                       %c: !shape.value_shape) -> !shape.shape {\\n      %0 = call @shape_foo(%a, %b) :\\n        (!shape.value_shape, !shape.value_shape) -> !shape.shape\\n      %1 = shape.with_shape %b, %0 : !shape.value_shape, !shape.shape\\n      %2 = call @shape_bah(%c, %1) :\\n        (!shape.value_shape, !shape.value_shape) -> !shape.shape\\n      return %2 : !shape.shape\\n    }\\n    ```\\n\\n    This op need not be a refinement of the shape. In non-error cases the input\\n    ValueShape's value and shape are conformant and so too for the output, but\\n    the result may be less specified than `operand`'s shape as `shape` is\\n    merely used to construct the new ValueShape. If join behavior is desired\\n    then a join op should be used.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<[AnyShaped, Shape_ValueShapeType]>\" },\n      { \"name\": \"shape\", \"type\": \"Shape_ShapeOrExtentTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shape_ValueShapeType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand) `,` type($shape)\"\n  },\n  {\n    \"name\": \"shape.yield\",\n    \"summary\": \"Returns the value to parent op\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"shard.all_gather\",\n    \"summary\": \"All-gather over a device grid.\",\n    \"description\": \"Concatenates all tensor slices from a device group defined by `grid_axes` along\\n    the tensor dimension `gather_axis` and replicates the result across all devices\\n    in the group.\\n\\n    Example:\\n    ```mlir\\n    shard.grid @grid0(shape = 2x2)\\n    ...\\n    %1 = shard.all_gather %0 on @grid0 grid_axes = [1] gather_axis = 1\\n      : tensor<2x2xi8> -> tensor<2x4xi8>\\n    ```\\n    Input:\\n    ```\\n                     +-------+-------+\\n    device (0, 0) -> |  1  2 |  5  6 | <- device (0, 1)\\n                     |  3  4 |  7  8 |\\n                     +-------+-------+\\n    device (1, 0) -> |  9 10 | 13 14 | <- device (1, 1)\\n                     | 11 12 | 15 16 |\\n                     +-------+-------+\\n    ```\\n    Result:\\n    ```\\n    gather tensor\\n    axis 1\\n    ------------>\\n    +-------------+\\n    |  1  2  5  6 | <- devices (0, 0) and (0, 1)\\n    |  3  4  7  8 |\\n    +-------------+\\n    |  9 10 13 14 | <- devices (1, 0) and (1, 1)\\n    | 11 12 15 16 |\\n    +-------------+\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyRankedTensor]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyRankedTensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"gather_axis\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)? `gather_axis` `=` $gather_axis\\n    attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.all_reduce\",\n    \"summary\": \"All-reduce over a device grid.\",\n    \"description\": \"Reduces the input tensor across all devices within the groups defined by\\n    `grid_axes`, using the specified reduction method. The operation performs an\\n    element-wise reduction over the tensor slices from all devices in each group.\\n    Each device in a group receives a replicated copy of the reduction result.\\n    The accumulation element type is determined by the result type and does not\\n    need to match the input element type. Before performing the reduction, each\\n    input element is converted to the result element type.\\n\\n    Attributes:\\n    `reduction`: Indicates the reduction method.\\n\\n    Example:\\n    ```\\n    %1 = shard.all_reduce %0 on @grid0 grid_axes = [1, 0] reduction = <max>\\n      : tensor<3x4xf32> -> tensor<3x4xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyRankedTensor]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyRankedTensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<Shard_ReductionKindAttr{sum|max|min|product|average|bitwise_and|bitwise_or|bitwise_xor|generic}, ::mlir::shard::ReductionKind::Sum>\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)? (`reduction` `=` $reduction^)?\\n    attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.all_slice\",\n    \"summary\": \"All-slice over a device grid.\",\n    \"description\": \"Within each device group defined by `grid_axes`, slices the input tensor along\\n    the `slice_axis` dimension. It can be viewed as the inverse of an all-gather if\\n    the input data is replicated along the `slice_axis`.\\n    Each process simply crops its local data to the slice corresponding to its\\n    in-group device index.\\n    Notice: `AllSliceOp` does not involve any communication between devices and\\n            devices within a group may not have replicated input data.\\n\\n    Example:\\n    ```mlir\\n    shard.grid @grid0(shape = 2x2)\\n    ...\\n    %1 = shard.all_slice %0 on @grid0 grid_axes = [1] slice_axis = 1\\n      : tensor<2x4xi8> -> tensor<2x2xi8>\\n    ```\\n    Input:\\n    ```\\n    +-------------+\\n    |  1  2  5  6 | <- devices (0, 0) and (0, 1)\\n    |  3  4  7  8 |\\n    +-------------+\\n    |  9 10 13 14 | <- devices (1, 0) and (1, 1)\\n    | 11 12 15 16 |\\n    +-------------+\\n    ```\\n    Result:\\n    ```\\n    slice tensor\\n    axis 1\\n    ------------>\\n                     +-------+-------+\\n    device (0, 0) -> |  1  2 |  5  6 | <- device (0, 1)\\n                     |  3  4 |  7  8 |\\n                     +-------+-------+\\n    device (1, 0) -> |  9 10 | 13 14 | <- device (1, 1)\\n                     | 11 12 | 15 16 |\\n                     +-------+-------+\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"slice_axis\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)? `slice_axis` `=` $slice_axis\\n    attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.all_to_all\",\n    \"summary\": \"All-to-all over a device grid.\",\n    \"description\": \"Each participant logically splits its input along split_axis,\\n    then scatters the resulting pieces across the group defined by `grid_axes`.\\n    After receiving data pieces from other participants' scatters,\\n    it concatenates them along concat_axis to produce the final result.\\n\\n    Example:\\n    ```\\n    shard.grid @grid0(shape = 3)\\n    ...\\n    %1 = shard.all_to_all %0 on @grid0 grid_axes = [0]\\n      split_axis = 0 concat_axis = 0\\n      : tensor<3x2xi8> -> tensor<3x2xi8>\\n    ```\\n    Input:\\n    ```\\n     device  device  device\\n     (0)     (1)     (2)\\n    +-------+-------+-------+  | split and concat along\\n    | 11 12 | 21 22 | 31 32 |  | tensor axis 0\\n    | 13 14 | 23 24 | 33 34 |  ↓\\n    | 15 16 | 25 26 | 35 36 |\\n    +-------+-------+-------+\\n    ```\\n    Result:\\n    ```\\n     device  device  device\\n     (0)     (1)     (2)\\n    +-------+-------+-------+\\n    | 11 12 | 13 14 | 15 16 |\\n    | 21 22 | 23 24 | 25 26 |\\n    | 31 32 | 33 34 | 35 36 |\\n    +-------+-------+-------+\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"split_axis\", \"type\": \"IndexAttr\" },\n      { \"name\": \"concat_axis\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    `split_axis` `=` $split_axis\\n    `concat_axis` `=` $concat_axis\\n    attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.broadcast\",\n    \"summary\": \"Broadcast over a device grid.\",\n    \"description\": \"Copies the input tensor on `root` to all devices in each group defined by\\n    `grid_axes`. The `root` device is defined by its in-group multi-index.\\n    The contents of input tensors on non-root devices are ignored.\\n    \\n    Example:\\n    ```\\n    shard.grid @grid0(shape = 2x2)\\n\\n    %1 = shard.broadcast %0 on @grid0\\n      grid_axes = [0]\\n      root = [0]\\n      : (tensor<2xi8>) -> tensor<2xi8>\\n    ```\\n    \\n    Input:\\n    ```\\n                     +-------+-------+                   | broadcast\\n    device (0, 0) -> |  1  2 |  3  4 | <- device (0, 1)  | along axis 0\\n                     +-------+-------+                   ↓\\n    device (1, 0) -> |  *  * |  *  * | <- device (1, 1)\\n                     +-------+-------+\\n    ```\\n\\n    Output:\\n    ```\\n                     +-------+-------+\\n    device (0, 0) -> |  1  2 |  3  4 | <- device (0, 1)\\n                     +-------+-------+\\n    device (1, 0) -> |  1  2 |  3  4 | <- device (1, 1)\\n                     +-------+-------+\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"root_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"root\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    `root` `=` custom<DynamicIndexList>($root_dynamic, $root)\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"shard.gather\",\n    \"summary\": \"Gather over a device grid.\",\n    \"description\": \"Concatenates all tensor slices from a device group defined by `grid_axes` along\\n    the tensor dimension `gather_axis` and returns the resulting tensor on each\\n    `root` device. The result on all other (non-root) devices is undefined.\\n    The `root` device is defined by its in-group multi-index.\\n\\n    Example:\\n    ```mlir\\n    shard.grid @grid0(shape = 2x2)\\n    ...\\n    %1 = shard.gather %0 on @grid0 grid_axes = [1]\\n      gather_axis = 1 root = [1]\\n      : (tensor<2x2xi8>) -> tensor<2x4xi8>\\n    ```\\n    Input:\\n    ```\\n                      gather tensor\\n                      axis 1\\n                      ------------>\\n                     +-------+-------+\\n    device (0, 0) -> |  1  2 |  5  6 | <- device (0, 1)\\n                     |  3  4 |  7  8 |\\n                     +-------+-------+\\n    device (1, 0) -> |  9 10 | 13 14 | <- device (1, 1)\\n                     | 11 12 | 15 16 |\\n                     +-------+-------+\\n    ```\\n    Result:\\n    ```\\n    +-------------+\\n    |  1  2  5  6 | <- devices (0, 1)\\n    |  3  4  7  8 |\\n    +-------------+\\n    |  9 10 13 14 | <- devices (1, 1)\\n    | 11 12 15 16 |\\n    +-------------+\\n    ```\\n    Devices `(0, 0)` and `(1, 0)` have undefined result.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" },\n      { \"name\": \"root_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"gather_axis\", \"type\": \"IndexAttr\" },\n      { \"name\": \"root\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    `gather_axis` `=` $gather_axis\\n    `root` `=` custom<DynamicIndexList>($root_dynamic, $root)\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"shard.get_sharding\",\n    \"summary\": \"Get the sharding of the given tensor.\",\n    \"description\": \"This operation returns the sharding of the given tensor as a Sharding.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shard_Sharding\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.grid\",\n    \"summary\": \"Description of a device/process grid.\",\n    \"description\": \"The shard.grid operation is a symbol operation that identifies a specific\\n    grid. The operation has three attributes:\\n\\n    1. `sym_name`: This attribute uniquely identifies the name of the grid.\\n    This name serves as a symbolic reference to the grid throughout\\n    the MLIR module, allowing for consistent referencing and easier debugging.\\n\\n    2. `shape`: This attribute represents the shape of the device grid.\\n    It uses the same notation as a tensor shape. Also allowing for dynamic\\n    dimensions.\\n    This flexibility allows for dynamic device assignment or configurations\\n    where the exact number of devices might not be determined during compile\\n    time.\\n    For example `2x?x4`.\\n\\n    Example:\\n    ```\\n    // A device grid with 3 axes, the total device number is 4 * 8 * 12\\n    // The dimension sizes are 4, 8, 12 \\n    shard.grid @grid0(shape = 4x8x12)\\n\\n    // A device grid with 2 axes, the total device number is unknown\\n    // The first dimension size is 4 and the second is unknown\\n    shard.grid @grid1(shape = 4x?)\\n\\n    // A device grid with 2 axes, the total device number is unknown\\n    // The first dimension size is unknown and the second is 4\\n    shard.grid @grid2(shape = ?x4)\\n\\n    // A device grid with 2 axes, the number of devices along both axes\\n    // is unknown\\n    shard.grid @grid3(shape = ?x?)\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"shape\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `(` `shape` `=` custom<DimensionList>($shape) `)`\\n      attr-dict\"\n  },\n  {\n    \"name\": \"shard.grid_shape\",\n    \"summary\": \"Get the shape of the grid.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$grid (`axes` `=` $axes^)?\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"shard.neighbors_linear_indices\",\n    \"summary\": \"For given grid index get the linear indices of the direct neighbor processes along the given split.\",\n    \"description\": \"Example:\\n    ```\\n    shard.grid @grid0(shape = 10x20x30)\\n    %c1 = arith.constant 1 : index\\n    %c2 = arith.constant 2 : index\\n    %c3 = arith.constant 3 : index\\n    %idx = shard.neighbors_linear_indices on @grid[%c1, %c2, %c3] split_axes = [1] : index\\n    ```\\n    The above returns two indices, `633` and `693`, which correspond to the\\n    index of the previous process `(1, 1, 3)`, and the next process \\n    `(1, 3, 3)` along the split axis `1`.\\n\\n    A negative value is returned if there is no neighbor in the respective\\n    direction along the given `split_axes`.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"neighbor_down\", \"type\": \"Index\" },\n      { \"name\": \"neighbor_up\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"split_axes\", \"type\": \"Shard_GridAxesAttr\" }\n    ],\n    \"assemblyFormat\": \"`on` $grid `[` $device `]`\\n      `split_axes` `=` $split_axes\\n      attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"shard.process_linear_index\",\n    \"summary\": \"Get the linear index of the current device.\",\n    \"description\": \"Example:\\n    ```\\n    %idx = shard.process_linear_index on @grid : index\\n    ```\\n    if `@grid` has shape `(10, 20, 30)`, a device with multi\\n    index `(1, 2, 3)` will have linear index `3 + 30*2 + 20*30*1`.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`on` $grid attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"shard.process_multi_index\",\n    \"summary\": \"Get the multi index of current device along specified grid axes.\",\n    \"description\": \"It is used in the SPMD format of IR.\\n    The `axes` mush be non-negative and less than the total number of grid axes.\\n    If the axes are empty then get the index along all axes.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"`on` $grid (`axes` `=` $axes^)?\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"shard.recv\",\n    \"summary\": \"Send over a device grid.\",\n    \"description\": \"Receive tensor from device `source`, which is defined by its in-group\\n    multi-index. The groups are defined by `grid_axes`.\\n    The content of input tensor is ignored.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" },\n      { \"name\": \"source_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"source\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    (`source` `=` custom<DynamicIndexList>($source_dynamic, $source)^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"shard.reduce\",\n    \"summary\": \"Reduce over a device grid.\",\n    \"description\": \"Reduces the input tensor across all devices within the groups defined by\\n    `grid_axes`, using the specified reduction method. The operation performs an\\n    element-wise reduction over the tensor slices from all devices in each group.\\n    The reduction result will be returned on the `root` device of each group.\\n    It is undefined on all other (non-root) devices.\\n    The `root` device is defined by its in-group multi-index.\\n    The accumulation element type is determined by the result type and does not\\n    need to match the input element type. Before performing the reduction, each\\n    input element is converted to the result element type.\\n\\n    Attributes:\\n    `reduction`: Indicates the reduction method.\\n\\n    Example:\\n    ```\\n    %1 = shard.reduce %0 on @grid0 grid_axes = [1, 0]\\n      reduction = <max> root = [2, 3]\\n      : (tensor<3x4xf32>) -> tensor<3x4xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"root_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<Shard_ReductionKindAttr{sum|max|min|product|average|bitwise_and|bitwise_or|bitwise_xor|generic}, ::mlir::shard::ReductionKind::Sum>\" },\n      { \"name\": \"root\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    (`reduction` `=` $reduction^)?\\n    `root` `=` custom<DynamicIndexList>($root_dynamic, $root)\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"shard.reduce_scatter\",\n    \"summary\": \"Reduce-scatter over a device grid.\",\n    \"description\": \"Reduces the input tensor across all devices within the groups defined by\\n    `grid_axes` using the specified reduction method. The reduction is performed\\n    element-wise across the tensor pieces from all devices in the group.\\n    After reduction, the reduction result is scattered (split and distributed)\\n    across the device group along `scatter_dim`.\\n    Example:\\n    ```\\n    shard.grid @grid0(shape = 2x2)\\n    ...\\n    %1 = shard.reduce_scatter %0 on @grid0 grid_axes = [1]\\n      reduction = <max> scatter_dim = 0\\n      : tensor<2x2xf32> -> tensor<1x2xf64>\\n    ```\\n    Input:\\n    ```\\n                              device\\n                              (0, 1)\\n                                 ↓\\n                     +-------+-------+  | scatter tensor\\n    device (0, 0) -> |  1  2 |  5  6 |  | axis 0\\n                     |  3  4 |  7  8 |  ↓\\n                     +-------+-------+\\n    device (1, 0) -> |  9 10 | 13 14 |\\n                     | 11 12 | 15 16 |\\n                     +-------+-------+\\n                                ↑\\n                              device\\n                              (1, 1)\\n    ```\\n    Result:\\n    ```\\n    +-------+\\n    |  5  6 | <- devices (0, 0)\\n    +-------+\\n    |  7  8 | <- devices (0, 1)\\n    +-------+\\n    | 13 14 | <- devices (1, 0)\\n    +-------+\\n    | 15 16 | <- devices (1, 1)\\n    +-------+\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyRankedTensor]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyMemRef, AnyRankedTensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<Shard_ReductionKindAttr{sum|max|min|product|average|bitwise_and|bitwise_or|bitwise_xor|generic}, ::mlir::shard::ReductionKind::Sum>\" },\n      { \"name\": \"scatter_dim\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    (`reduction` `=` $reduction^)?\\n    `scatter_dim` `=` $scatter_dim\\n    attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.scatter\",\n    \"summary\": \"Scatter over a device grid.\",\n    \"description\": \"For each device group defined by `grid_axes`, the input tensor on the `root`\\n    device is split along axis `scatter_dim` and distributed across the group.\\n    The content of the input on all other (non-root) devices is ignored.\\n    The `root` device is defined by its in-group multi-index.\\n\\n    Example:\\n    ```\\n    shard.grid @grid0(shape = 2x2)\\n    %1 = shard.scatter %0 on @grid0 grid_axes = [0]\\n      scatter_dim = 0\\n      root = [1]\\n      : (tensor<2x2xi8>) -> tensor<1x2xi8>\\n    ```\\n\\n    Input:\\n    ```\\n                              device\\n                              (0, 1)\\n                                 ↓\\n                     +-------+-------+  | scatter tensor\\n    device (0, 0) -> |  *  * |  *  * |  | axis 0\\n                     |  *  * |  *  * |  ↓\\n                     +-------+-------+\\n    device (1, 0) -> |  1  2 |  5  6 |\\n                     |  3  4 |  7  8 |\\n                     +-------+-------+\\n                                ↑\\n                              device\\n                              (1, 1)\\n    ```\\n    \\n    Result:\\n    ```\\n                              device\\n                              (0, 1)\\n                                 ↓\\n                     +-------+-------+\\n    device (0, 0) -> |  1  2 |  5  6 |\\n                     +-------+-------+ \\n    device (1, 0) -> |  3  4 |  7  8 |\\n                     +-------+-------+\\n                                ↑\\n                              device\\n                              (1, 1)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" },\n      { \"name\": \"root_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"scatter_dim\", \"type\": \"IndexAttr\" },\n      { \"name\": \"root\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    `scatter_dim` `=` $scatter_dim\\n    `root` `=` custom<DynamicIndexList>($root_dynamic, $root)\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"shard.send\",\n    \"summary\": \"Send over a device grid.\",\n    \"description\": \"Send input tensor to device `destination`, which is defined by its in-group\\n    multi-index. The groups are defined by `grid_axes`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" },\n      { \"name\": \"destination_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"destination\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    `destination` `=` custom<DynamicIndexList>($destination_dynamic, $destination)\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"shard.shard\",\n    \"summary\": \"Annotate on how a tensor is sharded across a shard.\",\n    \"description\": \"The shard.shard operation is designed to specify and guide the sharding\\n    behavior of a tensor value across a grid topology. This operation has two\\n    operands and two optional attributes:\\n\\n    1. `input`: This operand represents the tensor value that needs to be\\n    annotated for sharding.\\n\\n    2. `sharding`: This attribute is type of `ShardingType`, which is the core data\\n    structure to represent distribution of a tensor on a shard. it is typically defined\\n    by an `shard.sharding` operation.\\n\\n    3. `annotate_for_users`: A unit attribute addressing the scenario when a\\n    tensor's sharding annotation differs based on its context of use (either as\\n    a result or an operand). If specified, the sharding pertains to specific\\n    users of the tensor value, indicating how it should be considered when used\\n    as an operand in subsequent operations. If not, the sharding applies to the\\n    operation that defines the tensor value.\\n\\n    Example:\\n    ```\\n  func.func @only_result_annotated(%arg0 : tensor<4x8xf32>) -> () {\\n      %sharding = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding : tensor<4x8xf32>\\n      ...\\n    }\\n\\n    func.func @only_operand_annotated(%arg0 : tensor<4x8xf32>) -> () {\\n      %sharding = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding annotate_for_users : tensor<4x8xf32>\\n      ...\\n    }\\n    \\n    func.func @two_operands_annotated(%arg0 : tensor<4x8xf32>, %arg1 : tensor<16x8xf32>) -> () {\\n      %sharding = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding annotate_for_users : tensor<4x8xf32>\\n      %1 = shard.shard %arg1 to %sharding annotate_for_users : tensor<16x8xf32>\\n      ...\\n    }\\n\\n    // The first shard.shard op applies to %arg0, the second shard.shard op\\n    // applies for the operand of op0, the third shard.shard op applies for the\\n    // operand of op2\\n    func.func @both_result_and_multi_operands_annotated(\\n        %arg0 : tensor<4x8xf32>) -> () {\\n      %sharding = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding : tensor<4x8xf32>\\n      %sharding1 = shard.sharding @grid0 split_axes = [[1]] : !shard.sharding\\n      %1 = shard.shard %0 to %sharding1 annotate_for_users : tensor<4x8xf32>\\n      %sharding2 = shard.sharding @grid0 split_axes = [[2]] : !shard.sharding\\n      %2 = shard.shard %0 to %sharding2 annotate_for_users : tensor<4x8xf32>\\n      \\\"op0\\\"(%1) : ...\\n      \\\"op1\\\"(%2) : ...\\n      ...\\n    }\\n    ```\\n\\n    The following usages are undefined:\\n    ```\\n    func.func @annotate_on_same_result_with_different_sharding(\\n        %arg0 : tensor<4x8xf32>) -> () {\\n      %sharding1 = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %sharding2 = shard.sharding @grid0 split_axes = [[1]] : !shard.sharding\\n      %0 = shard.shard %arg0 to $sharding1 : tensor<4x8xf32>\\n      %1 = shard.shard %0 to sharding2 : tensor<4x8xf32>\\n      ...\\n    }\\n\\n    func.func @annotate_on_same_result_same_value_with_different_sharding(\\n        %arg0 : tensor<4x8xf32>) -> () {\\n      %sharding1 = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %sharding2 = shard.sharding @grid0 split_axes = [[1]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding1 : tensor<4x8xf32>\\n      %1 = shard.shard %arg0 to %sharding2 : tensor<4x8xf32>\\n      ...\\n    }\\n\\n    func.func @annotate_on_same_operand_with_different_sharding(\\n        %arg0 : tensor<4x8xf32>) -> () {\\n      %sharding1 = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %sharding2 = shard.sharding @grid0 split_axes = [[1]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding1 annotate_for_users : tensor<4x8xf32>\\n      %1 = shard.shard %0 to %sharding2 annotate_for_users : tensor<4x8xf32>\\n      ...\\n    }\\n\\n    func.func @result_annotated_after_operand(\\n        %arg0 : tensor<4x8xf32>) -> () {\\n      %sharding1 = shard.sharding @grid0 split_axes = [[0]] : !shard.sharding\\n      %sharding2 = shard.sharding @grid0 split_axes = [[1]] : !shard.sharding\\n      %0 = shard.shard %arg0 to %sharding1 annotate_for_users : tensor<4x8xf32>\\n      %1 = shard.shard %0 to %sharding2 : tensor<4x8xf32>\\n      ...\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"sharding\", \"type\": \"Shard_Sharding\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"annotate_for_users\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'src']>\" }\n    ],\n    \"assemblyFormat\": \"$src `to` $sharding\\n      (`annotate_for_users` $annotate_for_users^)?\\n      attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"shard.shard_shape\",\n    \"summary\": \"Get the shard shape for a given process/device.\",\n    \"description\": \"The device/process id is a multi-index of the device/process in the shard.\\n    This operation might be used during partition when the shard shape depends\\n    on (non-constant) values used in `shard.sharding`.\",\n    \"operands\": [\n      { \"name\": \"dims_dynamic\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sharding\", \"type\": \"Shard_Sharding\" },\n      { \"name\": \"device_dynamic\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"device\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`dims` `=` custom<DynamicIndexList>($dims_dynamic, $dims)\\n      `sharding` `=` $sharding\\n      `device` `=` custom<DynamicIndexList>($device_dynamic, $device)\\n      attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"shard.sharding\",\n    \"summary\": \"Define a sharding of a tensor.\",\n    \"description\": \"The Sharding specifies how a tensor is sharded and distributed across the\\n    process shard. It is typically used in a `shard.shard` operation.\\n    The operation has the following attributes and operands:\\n\\n    1. `grid`: this attribute is a FlatSymbolRefAttr that refers to the device\\n    grid where the distributed tensor is placed. The symbol must resolve to a\\n    `shard.grid` operation.\\n\\n    2. `split_axes`: is an array composed of int64_t sub-arrays. The outer array's\\n    maximum size is the `rank` of the related tensor. For the i-th sub-array, if\\n    its value is [x, y], it indicates that the tensor's i-th dimension is splitted\\n    along the x and y axes of the device grid.\\n\\n    3. [Optional] Sizes of halos to be added for each sharded tensor dimension.\\n    `halo_sizes` is provided as a flattened 1d array of i64s, 2 values for each\\n    sharded dimension. `halo_sizes = [1, 2]` means that the first sharded dimension\\n    gets an additional halo of size 1 at the start of the first dimension and a halo\\n    size is 2 at its end. `halo_sizes = [1, 2, 2, 3]` defines halos for the first 2\\n    sharded dimensions e.g. the first sharded dimension gets `[1,2]` halos and the\\n    seconds gets `[2,3]` halos. `?` indicates dynamic halo sizes.\\n    \\n    4. [Optional] Offsets for each shard and sharded tensor dimension.\\n    `sharded_dims_offsets` is provided as a flattened 1d array of i64s. For each\\n    sharded tensor dimension the offsets (starting index) of all shards in that\\n    dimension and an additional value for the end of the last shard are provided.\\n    For a 1d sharding this means that position `i` has the exclusive prefix sum for\\n    shard `i`, and since only contiguous sharding is supported, its inclusive prefix\\n    sum is at position 'i+1'.\\n    \\n    Assuming a 3d-tensor of shape 32x32x32 with the first 2 dimensions being sharded,\\n    `sharded_dims_offsets` = [0, 24, 32, 0, 20, 32] means that the first device of\\n    the device-grid will get a shard of shape 24x20x32 and the second device will get\\n    a shard of shape 8x12x32. `?` indicates dynamic shard dimensions.\\n    \\n    `halo_sizes` and `sharded_dims_offsets` are mutually exclusive.\\n\\n    Examples:\\n\\n    ```\\n    shard.grid @grid0(shape = 2x2x4)\\n    shard.grid @grid1d_4(shape = 4)\\n\\n    // The tensor is fully replicated on @grid0.\\n    // Currently, there must be at least one sub-array present in axes, even\\n    // if it's empty. Otherwise, a parsing error will occur.\\n    %sharding0 = shard.sharding @grid0 split_axes = [[]]\\n\\n    // The tensor is sharded on the first dimension along axis 0 of @grid0\\n    %sharding1 = shard.sharding @grid0 split_axes = [[0]]\\n\\n    // Could be used for a shard.shard op\\n    %sharded0 = shard.shard %arg0 to %sharding3 : tensor<4x8xf32>\\n\\n    // The tensor is sharded on its first dimension along axis 0 of @grid0 and\\n    // and it has halo-sizes of 1 and 2 on the sharded dim.\\n    %halo_sharding = shard.sharding @grid0 split_axes = [[0]] halo_sizes = [1, 2]\\n    %sharded1 = shard.shard %arg0 to %halo_sharding : tensor<4x8xf32>\\n    \\n    // The tensor is sharded on its second dimension along axis 0 of @grid1d_4\\n    // and it has pre-defined shard sizes. The shards of the devices will have\\n    // the following shapes: [4x2, 4x3, 4x4, 4x5]\\n    %sharding4 = shard.sharding @grid1d_4 split_axes = [[], [0]] sharded_dims_offsets = [0, 2, 5, 9, 14]\\n    %sharded2 = shard.shard %arg0 to %sharding4 : tensor<4x14xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynamic_sharded_dims_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"dynamic_halo_sizes\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Shard_Sharding\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"split_axes\", \"type\": \"Shard_GridAxesArrayAttr\" },\n      { \"name\": \"static_sharded_dims_offsets\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_halo_sizes\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$grid\\n    `split_axes` `=` $split_axes\\n    (`halo_sizes` `=` custom<DynamicIndexList>($dynamic_halo_sizes, $static_halo_sizes)^)?\\n    (`sharded_dims_offsets` `=` custom<DynamicIndexList>($dynamic_sharded_dims_offsets, $static_sharded_dims_offsets)^)?\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"shard.shift\",\n    \"summary\": \"Shift over a device grid.\",\n    \"description\": \"Within each device group defined by `grid_axes`, shifts input tensors along the\\n    device grid's axis `shift_axis` by the specified offset. The `shift_axis` must\\n    be one of the `grid_axes`. If the `rotate` attribute is set, the shift is circular.\\n    That is, the offset wraps around according to the group size along `shift_axis`.\\n    Otherwise, the results on devices without a corresponding source are undefined.\\n\\n    Example:\\n    ```\\n    shard.grid @grid0(shape = 2x4)\\n    %1 = shard.shift on @grid0 grid_axes = [1]\\n      shift_axis = 1 offset = 2 rotate\\n      : tensor<2xi8> -> tensor<2xi8>\\n    ```\\n\\n    Input:\\n    ```\\n    grid axis 1\\n    ----------->\\n\\n    +----+----+----+----+\\n    |  1 |  2 |  3 |  4 |\\n    +----+----+----+----+\\n    |  5 |  6 |  7 |  8 |\\n    +----+----+----+----+\\n    ```\\n\\n    Result:\\n    ```\\n    +----+----+----+----+\\n    |  3 |  4 |  1 |  2 |\\n    +----+----+----+----+\\n    |  7 |  8 |  5 |  6 |\\n    +----+----+----+----+\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"grid_axes\", \"type\": \"DefaultValuedAttr<Shard_GridAxesAttr, {}>\" },\n      { \"name\": \"shift_axis\", \"type\": \"IndexAttr\" },\n      { \"name\": \"offset\", \"type\": \"I64Attr\" },\n      { \"name\": \"rotate\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `on` $grid (`grid_axes` `=` $grid_axes^)?\\n    `shift_axis` `=` $shift_axis\\n    `offset` `=` $offset\\n    (`rotate` $rotate^)?\\n    attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"shard.update_halo\",\n    \"summary\": \"Update halo data.\",\n    \"description\": \"This operation updates halo regions of shards, e.g. if their sharding\\n    specified halos and the actual tensor/memref data might have changed\\n    on the remote devices. Changes might be caused by mutating operations\\n    and/or if the new halo regions are larger than the existing ones.\\n\\n    Destination is supposed to be initialized with the local data (not halos).\\n\\n    Assumes all devices hold tensors with same-sized halo data as specified\\n    by `source_halo_sizes/static_source_halo_sizes` and\\n    `destination_halo_sizes/static_destination_halo_sizes` in source shard\\n    and destination/result shard.\\n\\n    `split_axes` specifies for each tensor axis along which grid axes its halo\\n    data is updated.\",\n    \"operands\": [\n      { \"name\": \"destination\", \"type\": \"AnyTypeOf<[AnyNon0RankedMemRef, AnyNon0RankedTensor]>\" },\n      { \"name\": \"halo_sizes\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyNon0RankedMemRef, AnyNon0RankedTensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"split_axes\", \"type\": \"Shard_GridAxesArrayAttr\" },\n      { \"name\": \"static_halo_sizes\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'destination', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$destination\\n    `on` $grid\\n    `split_axes` `=` $split_axes\\n    (`halo_sizes` `=` custom<DynamicIndexList>($halo_sizes, $static_halo_sizes)^)?\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"smt.and\",\n    \"summary\": \"a boolean conjunction\",\n    \"description\": \"This operation performs a boolean conjunction.\\n    The semantics are equivalent to the 'and' operator in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2).\\n    of the SMT-LIB Standard 2.7.\\n\\n    It supports a variadic number of operands, but requires at least two.\\n    This is because the operator is annotated with the `:left-assoc` attribute\\n    which means that `op a b c` is equivalent to `(op (op a b) c)`.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<BoolType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\"\n  },\n  {\n    \"name\": \"smt.apply_func\",\n    \"summary\": \"apply a function\",\n    \"description\": \"This operation performs a function application as described in the\\n    [SMT-LIB 2.7 standard](https://smt-lib.org/papers/smt-lib-reference-v2.7-r2025-02-05.pdf).\\n    It is part of the language itself rather than a theory or logic.\",\n    \"operands\": [\n      { \"name\": \"func\", \"type\": \"SMTFuncType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyNonFuncSMTType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNonFuncSMTType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'func', 'result', 'cast<SMTFuncType>($_self).getRangeType()'>\" },\n      { \"type\": \"TypesMatchWith<'func', 'args', 'cast<SMTFuncType>($_self).getDomainTypes()'>\" }\n    ],\n    \"assemblyFormat\": \"$func `(` $args `)` attr-dict `:` qualified(type($func))\"\n  },\n  {\n    \"name\": \"smt.array.broadcast\",\n    \"summary\": \"construct an array with the given value stored at every index\",\n    \"description\": \"This operation represents a broadcast of the 'value' operand to all indices\\n    of the array. It is equivalent to\\n    ```\\n    %0 = smt.declare_fun \\\"array\\\" : !smt.array<[!smt.int -> !smt.bool]>\\n    %1 = smt.forall [\\\"idx\\\"] {\\n    ^bb0(%idx: !smt.int):\\n      %2 = smt.array.select %0[%idx] : !smt.array<[!smt.int -> !smt.bool]>\\n      %3 = smt.eq %value, %2 : !smt.bool\\n      smt.yield %3 : !smt.bool\\n    }\\n    smt.assert %1\\n    // return %0\\n    ```\\n\\n    In SMT-LIB, this is frequently written as\\n    `((as const (Array Int Bool)) value)`.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnySMTType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"ArrayType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'value', 'cast<ArrayType>($_self).getRangeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.array.select\",\n    \"summary\": \"get the value stored in the array at the given index\",\n    \"description\": \"This operation is retuns the value stored in the given array at the given\\n    index. The semantics are equivalent to the `select` operator defined in the\\n    [SMT ArrayEx theory](https://smtlib.cs.uiowa.edu/Theories/ArraysEx.smt2) of\\n    the SMT-LIB standard 2.7.\",\n    \"operands\": [\n      { \"name\": \"array\", \"type\": \"ArrayType\" },\n      { \"name\": \"index\", \"type\": \"AnySMTType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySMTType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'array', 'index', 'cast<ArrayType>($_self).getDomainType()'>\" },\n      { \"type\": \"TypesMatchWith<'array', 'result', 'cast<ArrayType>($_self).getRangeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$array `[` $index `]` attr-dict `:` qualified(type($array))\"\n  },\n  {\n    \"name\": \"smt.array.store\",\n    \"summary\": \"stores a value at a given index and returns the new array\",\n    \"description\": \"This operation returns a new array which is the same as the 'array' operand\\n    except that the value at the given 'index' is changed to the given 'value'.\\n    The semantics are equivalent to the 'store' operator described in the\\n    [SMT ArrayEx theory](https://smtlib.cs.uiowa.edu/Theories/ArraysEx.smt2) of\\n    the SMT-LIB standard 2.7.\",\n    \"operands\": [\n      { \"name\": \"array\", \"type\": \"ArrayType\" },\n      { \"name\": \"index\", \"type\": \"AnySMTType\" },\n      { \"name\": \"value\", \"type\": \"AnySMTType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"ArrayType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'array', 'index', 'cast<ArrayType>($_self).getDomainType()'>\" },\n      { \"type\": \"TypesMatchWith<'array', 'value', 'cast<ArrayType>($_self).getRangeType()'>\" },\n      { \"type\": \"AllTypesMatch<['array', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$array `[` $index `]` `,` $value attr-dict `:` qualified(type($array))\"\n  },\n  {\n    \"name\": \"smt.assert\",\n    \"summary\": \"assert that a boolean expression holds\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BoolType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict\"\n  },\n  {\n    \"name\": \"smt.bv.add\",\n    \"summary\": \"equivalent to bvadd in SMT-LIB\",\n    \"description\": \"This operation performs addition. The semantics are\\n    equivalent to the `bvadd` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.and\",\n    \"summary\": \"equivalent to bvand in SMT-LIB\",\n    \"description\": \"This operation performs bitwise AND. The semantics are\\n    equivalent to the `bvand` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.ashr\",\n    \"summary\": \"equivalent to bvashr in SMT-LIB\",\n    \"description\": \"This operation performs arithmetic shift right. The semantics are\\n    equivalent to the `bvashr` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.cmp\",\n    \"summary\": \"compare bit-vectors interpreted as signed or unsigned\",\n    \"description\": \"This operation compares bit-vector values, interpreting them as signed or\\n    unsigned values depending on the predicate. The semantics are equivalent to\\n    the `bvslt`, `bvsle`, `bvsgt`, `bvsge`, `bvult`, `bvule`, `bvugt`, or\\n    `bvuge` operator defined in the SMT-LIB 2.7 standard depending on the\\n    specified predicate. More precisely in the\\n    [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pred\", \"type\": \"BVCmpPredicate{slt|sle|sgt|sge|ult|ule|ugt|uge}\" }\n    ],\n    \"assemblyFormat\": \"$pred $lhs `,` $rhs attr-dict `:` qualified(type($lhs))\"\n  },\n  {\n    \"name\": \"smt.bv.concat\",\n    \"summary\": \"bit-vector concatenation\",\n    \"description\": \"This operation concatenates bit-vector values with semantics equivalent to\\n    the `concat` operator defined in the SMT-LIB 2.7 standard. More precisely in\\n    the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\\n\\n    Note that the following equivalences hold:\\n    * `smt.bv.concat %a, %b : !smt.bv<4>, !smt.bv<4>` is equivalent to\\n      `(concat a b)` in SMT-LIB\\n    * `(= (concat #xf #x0) #xf0)`\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type(operands))\"\n  },\n  {\n    \"name\": \"smt.bv.constant\",\n    \"summary\": \"produce a constant bit-vector\",\n    \"description\": \"This operation produces an SSA value equal to the bit-vector constant\\n    specified by the 'value' attribute.\\n    Refer to the `BitVectorAttr` documentation for more information about\\n    the semantics of bit-vector constants, their format, and associated sort.\\n    The result type always matches the attribute's type.\\n\\n    Examples:\\n    ```mlir\\n    %c92_bv8 = smt.bv.constant #smt.bv<92> : !smt.bv<8>\\n    %c5_bv4 = smt.bv.constant #smt.bv<5> : !smt.bv<4>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"BitVectorAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ],\n    \"assemblyFormat\": \"qualified($value) attr-dict\"\n  },\n  {\n    \"name\": \"smt.bv.extract\",\n    \"summary\": \"bit-vector extraction\",\n    \"description\": \"This operation extracts the range of bits starting at the 'lowBit' index\\n    (inclusive) up to the 'lowBit' + result-width index (exclusive). The\\n    semantics are equivalent to the `extract` operator defined in the SMT-LIB\\n    2.7 standard. More precisely in the\\n    [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\\n\\n    Note that `smt.bv.extract %bv from 2 : (!smt.bv<32>) -> !smt.bv<16>` is\\n    equivalent to `((_ extract 17 2) bv)`, i.e., the SMT-LIB operator takes the\\n    low and high indices where both are inclusive. The following equivalence\\n    holds: `(= ((_ extract 3 0) #x0f) #xf)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lowBit\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$input `from` $lowBit attr-dict `:` functional-type($input, $result)\"\n  },\n  {\n    \"name\": \"smt.bv.lshr\",\n    \"summary\": \"equivalent to bvlshr in SMT-LIB\",\n    \"description\": \"This operation performs logical shift right. The semantics are\\n    equivalent to the `bvlshr` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.mul\",\n    \"summary\": \"equivalent to bvmul in SMT-LIB\",\n    \"description\": \"This operation performs multiplication. The semantics are\\n    equivalent to the `bvmul` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.neg\",\n    \"summary\": \"equivalent to bvneg in SMT-LIB\",\n    \"description\": \"This operation performs two's complement unary minus. The semantics are\\n    equivalent to the `bvneg` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.not\",\n    \"summary\": \"equivalent to bvnot in SMT-LIB\",\n    \"description\": \"This operation performs bitwise negation. The semantics are\\n    equivalent to the `bvnot` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.or\",\n    \"summary\": \"equivalent to bvor in SMT-LIB\",\n    \"description\": \"This operation performs bitwise OR. The semantics are\\n    equivalent to the `bvor` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.repeat\",\n    \"summary\": \"repeated bit-vector concatenation of one value\",\n    \"description\": \"This operation is a shorthand for repeated concatenation of the same\\n    bit-vector value, i.e.,\\n    ```mlir\\n    smt.bv.repeat 5 times %a : !smt.bv<4>\\n    // is the same as\\n    %0 = smt.bv.repeat 4 times %a : !smt.bv<4>\\n    smt.bv.concat %a, %0 : !smt.bv<4>, !smt.bv<16>\\n    // or also \\n    %0 = smt.bv.repeat 4 times %a : !smt.bv<4>\\n    smt.bv.concat %0, %a : !smt.bv<16>, !smt.bv<4>\\n    ```\\n    \\n    The semantics are equivalent to the `repeat` operator defined in the SMT-LIB\\n    2.7 standard. More precisely in the\\n    [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"smt.bv.sdiv\",\n    \"summary\": \"equivalent to bvsdiv in SMT-LIB\",\n    \"description\": \"This operation performs two's complement signed division. The semantics are\\n    equivalent to the `bvsdiv` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.shl\",\n    \"summary\": \"equivalent to bvshl in SMT-LIB\",\n    \"description\": \"This operation performs shift left. The semantics are\\n    equivalent to the `bvshl` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.smod\",\n    \"summary\": \"equivalent to bvsmod in SMT-LIB\",\n    \"description\": \"This operation performs two's complement signed remainder (sign follows divisor). The semantics are\\n    equivalent to the `bvsmod` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.srem\",\n    \"summary\": \"equivalent to bvsrem in SMT-LIB\",\n    \"description\": \"This operation performs two's complement signed remainder (sign follows dividend). The semantics are\\n    equivalent to the `bvsrem` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.udiv\",\n    \"summary\": \"equivalent to bvudiv in SMT-LIB\",\n    \"description\": \"This operation performs unsigned division (rounded towards zero). The semantics are\\n    equivalent to the `bvudiv` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.urem\",\n    \"summary\": \"equivalent to bvurem in SMT-LIB\",\n    \"description\": \"This operation performs unsigned remainder. The semantics are\\n    equivalent to the `bvurem` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv.xor\",\n    \"summary\": \"equivalent to bvxor in SMT-LIB\",\n    \"description\": \"This operation performs bitwise exclusive OR. The semantics are\\n    equivalent to the `bvxor` operator defined in the SMT-LIB 2.7\\n    standard. More precisely in the [theory of FixedSizeBitVectors](https://smtlib.cs.uiowa.edu/Theories/FixedSizeBitVectors.smt2)\\n    and the [QF_BV logic](https://smtlib.cs.uiowa.edu/Logics/QF_BV.smt2)\\n    describing closed quantifier-free formulas over the theory of fixed-size\\n    bit-vectors.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BitVectorType\" },\n      { \"name\": \"rhs\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.bv2int\",\n    \"summary\": \"Convert an SMT bit-vector to an SMT integer.\",\n    \"description\": \"Create an integer from the bit-vector argument `input`. If `is_signed` is\\n    present, the bit-vector is treated as two's complement signed.  Otherwise,\\n    it is treated as an unsigned integer in the range [0..2^N-1], where N is\\n    the number of bits in `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BitVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_signed\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$input (`signed` $is_signed^)? attr-dict `:`\\n    qualified(type($input))\"\n  },\n  {\n    \"name\": \"smt.check\",\n    \"summary\": \"check if the current set of assertions is satisfiable\",\n    \"description\": \"This operation checks if all the assertions in the solver defined by the\\n    nearest ancestor operation of type `smt.solver` are consistent. The outcome\\n    an be 'satisfiable', 'unknown', or 'unsatisfiable' and the corresponding\\n    region will be executed. It is the corresponding construct to the\\n    `check-sat` in SMT-LIB.\\n\\n    Example:\\n    ```mlir\\n    %0 = smt.check sat {\\n      %c1_i32 = arith.constant 1 : i32\\n      smt.yield %c1_i32 : i32\\n    } unknown {\\n      %c0_i32 = arith.constant 0 : i32\\n      smt.yield %c0_i32 : i32\\n    } unsat {\\n      %c-1_i32 = arith.constant -1 : i32\\n      smt.yield %c-1_i32 : i32\\n    } -> i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"satRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"unknownRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"unsatRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `sat` $satRegion `unknown` $unknownRegion `unsat` $unsatRegion\\n    (`->` qualified(type($results))^ )?\"\n  },\n  {\n    \"name\": \"smt.constant\",\n    \"summary\": \"Produce a constant boolean\",\n    \"description\": \"Produces the constant expressions 'true' and 'false' as described in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2) of the SMT-LIB\\n    Standard 2.7.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"smt.declare_fun\",\n    \"summary\": \"declare a symbolic value of a given sort\",\n    \"description\": \"This operation declares a symbolic value just as the `declare-const` and\\n    `declare-fun` statements in SMT-LIB 2.7. The result type determines the SMT\\n    sort of the symbolic value. The returned value can then be used to refer to\\n    the symbolic value instead of using the identifier like in SMT-LIB.\\n\\n    The optionally provided string will be used as a prefix for the newly\\n    generated identifier (useful for easier readability when exporting to\\n    SMT-LIB). Each `declare` will always provide a unique new symbolic value\\n    even if the identifier strings are the same.\\n\\n    Note that there does not exist a separate operation equivalent to\\n    SMT-LIBs `define-fun` since\\n    ```\\n    (define-fun f (a Int) Int (-a))\\n    ```\\n    is only syntactic sugar for\\n    ```\\n    %f = smt.declare_fun : !smt.func<(!smt.int) !smt.int>\\n    %0 = smt.forall {\\n    ^bb0(%arg0: !smt.int):\\n      %1 = smt.apply_func %f(%arg0) : !smt.func<(!smt.int) !smt.int>\\n      %2 = smt.int.neg %arg0\\n      %3 = smt.eq %1, %2 : !smt.int\\n      smt.yield %3 : !smt.bool\\n    }\\n    smt.assert %0\\n    ```\\n\\n    Note that this operation cannot be marked as Pure since two operations (even\\n    with the same identifier string) could then be CSEd, leading to incorrect\\n    behavior.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySMTType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"namePrefix\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($namePrefix^)? attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.distinct\",\n    \"summary\": \"returns true iff all operands are not identical to any other\",\n    \"description\": \"This operation compares the operands and returns true iff all operands are\\n    not identical to any of the other operands. The semantics are equivalent to\\n    the `distinct` operator defined in the SMT-LIB Standard 2.7 in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2).\\n\\n    Any SMT sort/type is allowed for the operands and it supports a variadic\\n    number of operands, but requires at least two. This is because the\\n    `distinct` operator is annotated with `:pairwise` which means that\\n    `distinct a b c d` is equivalent to\\n    ```\\n    and (distinct a b) (distinct a c) (distinct a d)\\n        (distinct b c) (distinct b d)\\n        (distinct c d)\\n    ```\\n    where `and` is annotated `:left-assoc`, i.e., it can be further rewritten to\\n    ```\\n    (and (and (and (and (and (distinct a b)\\n                             (distinct a c))\\n                        (distinct a d))\\n                   (distinct b c))\\n              (distinct b d))\\n         (distinct c d)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyNonFuncSMTType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"smt.eq\",\n    \"summary\": \"returns true iff all operands are identical\",\n    \"description\": \"This operation compares the operands and returns true iff all operands are\\n    identical. The semantics are equivalent to the `=` operator defined in the\\n    SMT-LIB Standard 2.7 in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2).\\n\\n    Any SMT sort/type is allowed for the operands and it supports a variadic\\n    number of operands, but requires at least two. This is because the `=`\\n    operator is annotated with `:chainable` which means that `= a b c d` is\\n    equivalent to `and (= a b) (= b c) (= c d)` where `and` is annotated\\n    `:left-assoc`, i.e., it can be further rewritten to\\n    `and (and (= a b) (= b c)) (= c d)`.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyNonFuncSMTType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"smt.exists\",\n    \"summary\": \"exists quantifier\",\n    \"description\": \"This operation represents theexists quantifieras described in the\\n    [SMT-LIB 2.7 standard](https://smt-lib.org/papers/smt-lib-reference-v2.7-r2025-02-05.pdf).\\n    It is part of the language itself rather than a theory or logic.\\n\\n    The operation specifies the name prefixes (as an optional attribute) and\\n    types (as the types of the block arguments of the regions) of bound\\n    variables that may be used in the 'body' of the operation. If a 'patterns'\\n    region is specified, the block arguments must match the ones of the 'body'\\n    region and (other than there) must be used at least once in the 'patterns'\\n    region. It may also not contain any operations that bind variables, such as\\n    quantifiers. While the 'body' region must always yield exactly one\\n    `!smt.bool`-typed value, the 'patterns' region can yield an arbitrary number\\n    (but at least one) of SMT values.\\n\\n    The bound variables can be any SMT type except of functions, since SMT only\\n    supports first-order logic.\\n\\n    The 'no_patterns' attribute is only allowed when no 'patterns' region is\\n    specified and forbids the solver to generate and use patterns for this\\n    quantifier.\\n\\n    The 'weight' attribute indicates the importance of this quantifier being\\n    instantiated compared to other quantifiers that may be present. The default\\n    value is zero.\\n\\n    Both the 'no_patterns' and 'weight' attributes are annotations to the\\n    quantifiers body term. Annotations and attributes are described in the\\n    standard in sections 3.4, and 3.6 (specifically 3.6.5). SMT-LIB allows\\n    adding custom attributes to provide solvers with additional metadata, e.g.,\\n    hints such as above mentioned attributes. They are not part of the standard\\n    themselves, but supported by common SMT solvers (e.g., Z3).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"weight\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"noPattern\", \"type\": \"UnitAttr\" },\n      { \"name\": \"boundVarNames\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"patterns\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"($boundVarNames^)? (`no_pattern` $noPattern^)? (`weight` $weight^)?\\n    attr-dict-with-keyword $body (`patterns` $patterns^)?\"\n  },\n  {\n    \"name\": \"smt.forall\",\n    \"summary\": \"forall quantifier\",\n    \"description\": \"This operation represents theforall quantifieras described in the\\n    [SMT-LIB 2.7 standard](https://smt-lib.org/papers/smt-lib-reference-v2.7-r2025-02-05.pdf).\\n    It is part of the language itself rather than a theory or logic.\\n\\n    The operation specifies the name prefixes (as an optional attribute) and\\n    types (as the types of the block arguments of the regions) of bound\\n    variables that may be used in the 'body' of the operation. If a 'patterns'\\n    region is specified, the block arguments must match the ones of the 'body'\\n    region and (other than there) must be used at least once in the 'patterns'\\n    region. It may also not contain any operations that bind variables, such as\\n    quantifiers. While the 'body' region must always yield exactly one\\n    `!smt.bool`-typed value, the 'patterns' region can yield an arbitrary number\\n    (but at least one) of SMT values.\\n\\n    The bound variables can be any SMT type except of functions, since SMT only\\n    supports first-order logic.\\n\\n    The 'no_patterns' attribute is only allowed when no 'patterns' region is\\n    specified and forbids the solver to generate and use patterns for this\\n    quantifier.\\n\\n    The 'weight' attribute indicates the importance of this quantifier being\\n    instantiated compared to other quantifiers that may be present. The default\\n    value is zero.\\n\\n    Both the 'no_patterns' and 'weight' attributes are annotations to the\\n    quantifiers body term. Annotations and attributes are described in the\\n    standard in sections 3.4, and 3.6 (specifically 3.6.5). SMT-LIB allows\\n    adding custom attributes to provide solvers with additional metadata, e.g.,\\n    hints such as above mentioned attributes. They are not part of the standard\\n    themselves, but supported by common SMT solvers (e.g., Z3).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"weight\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"noPattern\", \"type\": \"UnitAttr\" },\n      { \"name\": \"boundVarNames\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"patterns\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"($boundVarNames^)? (`no_pattern` $noPattern^)? (`weight` $weight^)?\\n    attr-dict-with-keyword $body (`patterns` $patterns^)?\"\n  },\n  {\n    \"name\": \"smt.implies\",\n    \"summary\": \"boolean implication\",\n    \"description\": \"This operation performs a boolean implication. The semantics are equivalent\\n    to the '=>' operator in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2) of the SMT-LIB\\n    Standard 2.7.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"BoolType\" },\n      { \"name\": \"rhs\", \"type\": \"BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.abs\",\n    \"summary\": \"the absolute value of an Int\",\n    \"description\": \"This operation represents the absolute value function for the `Int` sort.\\n    The semantics are equivalent to the `abs` operator as described in the\\n    [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.add\",\n    \"summary\": \"integer addition\",\n    \"description\": \"This operation represents (infinite-precision)integer addition.\\n    The semantics are equivalent to the corresponding operator described in\\n    the [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<IntType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.cmp\",\n    \"summary\": \"integer comparison\",\n    \"description\": \"This operation represents the comparison of (infinite-precision) integers.\\n    The semantics are equivalent to the `<= (le)`, `< (lt)`, `>= (ge)`, or\\n    `> (gt)` operator depending on the predicate (indicated in parentheses) as\\n    described in the\\n    [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"IntType\" },\n      { \"name\": \"rhs\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pred\", \"type\": \"IntPredicate{lt|le|gt|ge}\" }\n    ],\n    \"assemblyFormat\": \"$pred $lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.constant\",\n    \"summary\": \"produce a constant (infinite-precision) integer\",\n    \"description\": \"This operation represents (infinite-precision) integer literals of the `Int`\\n    sort. The set of values for the sort `Int` consists of all numerals and\\n    all terms of the form `-n`where n is a numeral other than 0. For more\\n    information refer to the \\n    [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"APIntAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"smt.int.div\",\n    \"summary\": \"integer division\",\n    \"description\": \"This operation represents (infinite-precision)integer division.\\n    The semantics are equivalent to the corresponding operator described in\\n    the [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"IntType\" },\n      { \"name\": \"rhs\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.mod\",\n    \"summary\": \"integer remainder\",\n    \"description\": \"This operation represents (infinite-precision)integer remainder.\\n    The semantics are equivalent to the corresponding operator described in\\n    the [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"IntType\" },\n      { \"name\": \"rhs\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.mul\",\n    \"summary\": \"integer multiplication\",\n    \"description\": \"This operation represents (infinite-precision)integer multiplication.\\n    The semantics are equivalent to the corresponding operator described in\\n    the [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<IntType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int.sub\",\n    \"summary\": \"integer subtraction\",\n    \"description\": \"This operation represents (infinite-precision)integer subtraction.\\n    The semantics are equivalent to the corresponding operator described in\\n    the [SMT Ints theory](https://smtlib.cs.uiowa.edu/Theories/Ints.smt2) of the\\n    SMT-LIB 2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"IntType\" },\n      { \"name\": \"rhs\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"IntType\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\"\n  },\n  {\n    \"name\": \"smt.int2bv\",\n    \"summary\": \"Convert an integer to an inferred-width bitvector.\",\n    \"description\": \"Designed to lower directly to an operation of the same name in Z3. The Z3\\n    C API describes the semantics as follows:\\n    Create an n bit bit-vector from the integer argument t1.\\n    The resulting bit-vector has n bits, where the i'th bit (counting from 0\\n    to n-1) is 1 if (t1 div 2^i) mod 2 is 1.\\n    The node t1 must have integer sort.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BitVectorType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.ite\",\n    \"summary\": \"an if-then-else function\",\n    \"description\": \"This operation returns its second operand or its third operand depending on\\n    whether its first operand is true or not. The semantics are equivalent to\\n    the `ite` operator defined in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2) of the SMT-LIB\\n    2.7 standard.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"BoolType\" },\n      { \"name\": \"thenValue\", \"type\": \"AnySMTType\" },\n      { \"name\": \"elseValue\", \"type\": \"AnySMTType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySMTType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['thenValue', 'elseValue', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$cond `,` $thenValue `,` $elseValue attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"smt.not\",\n    \"summary\": \"a boolean negation\",\n    \"description\": \"This operation performs a boolean negation. The semantics are equivalent to\\n    the 'not' operator in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2) of the SMT-LIB\\n    Standard 2.7.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict\"\n  },\n  {\n    \"name\": \"smt.or\",\n    \"summary\": \"a boolean disjunction\",\n    \"description\": \"This operation performs a boolean disjunction.\\n    The semantics are equivalent to the 'or' operator in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2).\\n    of the SMT-LIB Standard 2.7.\\n\\n    It supports a variadic number of operands, but requires at least two.\\n    This is because the operator is annotated with the `:left-assoc` attribute\\n    which means that `op a b c` is equivalent to `(op (op a b) c)`.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<BoolType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\"\n  },\n  {\n    \"name\": \"smt.pop\",\n    \"summary\": \"pop a given number of levels from the assertion stack\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"smt.push\",\n    \"summary\": \"push a given number of levels onto the assertion stack\",\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$count attr-dict\"\n  },\n  {\n    \"name\": \"smt.reset\",\n    \"summary\": \"reset the solver\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"smt.set_logic\",\n    \"summary\": \"set the logic for the SMT solver\",\n    \"attributes\": [\n      { \"name\": \"logic\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$logic attr-dict\"\n  },\n  {\n    \"name\": \"smt.solver\",\n    \"summary\": \"create a solver instance within a lifespan\",\n    \"description\": \"This operation defines an SMT context with a solver instance. SMT operations\\n    are only valid when being executed between the start and end of the region\\n    of this operation. Any invocation outside is undefined. However, they do not\\n    have to be direct children of this operation. For example, it is allowed to\\n    have SMT operations in a `func.func` which is only called from within this\\n    region. No SMT value may enter or exit the lifespan of this region (such\\n    that no value created from another SMT context can be used in this scope and\\n    the solver can deallocate all state required to keep track of SMT values at\\n    the end).\\n\\n    As a result, the region is comparable to an entire SMT-LIB script, but\\n    allows for concrete operations and control-flow. Concrete values may be\\n    passed in and returned to influence the computations after the `smt.solver`\\n    operation.\\n\\n    Example:\\n    ```mlir\\n    %0:2 = smt.solver (%in) {smt.some_attr} : (i8) -> (i8, i32) {\\n    ^bb0(%arg0: i8):\\n      %c = smt.declare_fun \\\"c\\\" : !smt.bool\\n      smt.assert %c\\n      %1 = smt.check sat {\\n        %c1_i32 = arith.constant 1 : i32\\n        smt.yield %c1_i32 : i32\\n      } unknown {\\n        %c0_i32 = arith.constant 0 : i32\\n        smt.yield %c0_i32 : i32\\n      } unsat {\\n        %c-1_i32 = arith.constant -1 : i32\\n        smt.yield %c-1_i32 : i32\\n      } -> i32\\n      smt.yield %arg0, %1 : i8, i32\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyNonSMTType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyNonSMTType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $inputs `)` attr-dict `:` functional-type($inputs, $results) $bodyRegion\"\n  },\n  {\n    \"name\": \"smt.xor\",\n    \"summary\": \"a boolean exclusive OR\",\n    \"description\": \"This operation performs a boolean exclusive OR.\\n    The semantics are equivalent to the 'xor' operator in the\\n    [Core theory](https://smtlib.cs.uiowa.edu/Theories/Core.smt2).\\n    of the SMT-LIB Standard 2.7.\\n\\n    It supports a variadic number of operands, but requires at least two.\\n    This is because the operator is annotated with the `:left-assoc` attribute\\n    which means that `op a b c` is equivalent to `(op (op a b) c)`.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<BoolType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolType\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\"\n  },\n  {\n    \"name\": \"smt.yield\",\n    \"summary\": \"terminator operation for various regions of SMT operations\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($values^ `:` qualified(type($values)))? attr-dict\"\n  },\n  {\n    \"name\": \"sparse_tensor.assemble\",\n    \"summary\": \"Returns a sparse tensor assembled from the given levels and values\",\n    \"description\": \"Assembles the per-level position and coordinate arrays together with\\n    the values arrays into a sparse tensor. The order and types of the\\n    provided levels must be consistent with the actual storage layout of\\n    the returned sparse tensor described below.\\n\\n    - `levels: [tensor<? x iType>, ...]`\\n      supplies the sparse tensor position and coordinate arrays\\n      of the sparse tensor for the corresponding level as specifed by\\n      `sparse_tensor::StorageLayout`.\\n    - `values : tensor<? x V>`\\n      supplies the values array for the stored elements in the sparse tensor.\\n\\n    This operation can be used to assemble a sparse tensor from an\\n    external source; e.g., by passing numpy arrays from Python. It\\n    is the user's responsibility to provide input that can be correctly\\n    interpreted by the sparsifier, which does not perform any sanity\\n    test to verify data integrity.\\n\\n    Example:\\n\\n    ```mlir\\n    %pos    = arith.constant dense<[0, 3]>                : tensor<2xindex>\\n    %index  = arith.constant dense<[[0,0], [1,2], [1,3]]> : tensor<3x2xindex>\\n    %values = arith.constant dense<[ 1.1,   2.2,   3.3 ]> : tensor<3xf64>\\n    %s = sparse_tensor.assemble (%pos, %index), %values\\n       : (tensor<2xindex>, tensor<3x2xindex>), tensor<3xf64> to tensor<3x4xf64, #COO>\\n    // yields COO format |1.1, 0.0, 0.0, 0.0|\\n    //     of 3x4 matrix |0.0, 0.0, 2.2, 3.3|\\n    //                   |0.0, 0.0, 0.0, 0.0|\\n    ```\",\n    \"operands\": [\n      { \"name\": \"levels\", \"type\": \"Variadic<RankedTensorOf<[ AnySignlessIntegerOrIndex ]>>\" },\n      { \"name\": \"values\", \"type\": \"RankedTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"assemblyFormat\": \"` ` `(` $levels       `)` `,` $values attr-dict `:`    `(` type($levels) `)` `,` type($values) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.binary\",\n    \"summary\": \"Binary set operation utilized within linalg.generic\",\n    \"description\": \"Defines a computation within a `linalg.generic` operation that takes two\\n      operands and executes one of the regions depending on whether both operands\\n      or either operand is nonzero (i.e. stored explicitly in the sparse storage\\n      format).\\n\\n      Three regions are defined for the operation and must appear in this order:\\n      - overlap (elements present in both sparse tensors)\\n      - left (elements only present in the left sparse tensor)\\n      - right (element only present in the right sparse tensor)\\n\\n      Each region contains a single block describing the computation and result.\\n      Every non-empty block must end with a sparse_tensor.yield and the return\\n      type must match the type of `output`. The primary region's block has two\\n      arguments, while the left and right region's block has only one argument.\\n\\n      A region may also be declared empty (i.e. `left={}`), indicating that the\\n      region does not contribute to the output. For example, setting both\\n      `left={}` and `right={}` is equivalent to the intersection of the two\\n      inputs as only the overlap region will contribute values to the output.\\n\\n      As a convenience, there is also a special token `identity` which can be\\n      used in place of the left or right region. This token indicates that\\n      the return value is the input value (i.e. func(%x) => return %x).\\n      As a practical example, setting `left=identity` and `right=identity`\\n      would be equivalent to a union operation where non-overlapping values\\n      in the inputs are copied to the output unchanged.\\n\\n      Due to the possibility of empty regions, i.e. lack of a value for certain\\n      cases, the result of this operation may only feed directly into the output\\n      of the `linalg.generic` operation or into into a custom reduction\\n      `sparse_tensor.reduce` operation that follows in the same region.\\n\\n      Example of isEqual applied to intersecting elements only:\\n\\n      ```mlir\\n      %C = tensor.empty(...)\\n      %0 = linalg.generic #trait\\n        ins(%A: tensor<?xf64, #SparseVector>,\\n            %B: tensor<?xf64, #SparseVector>)\\n        outs(%C: tensor<?xi8, #SparseVector>) {\\n        ^bb0(%a: f64, %b: f64, %c: i8) :\\n          %result = sparse_tensor.binary %a, %b : f64, f64 to i8\\n            overlap={\\n              ^bb0(%arg0: f64, %arg1: f64):\\n                %cmp = arith.cmpf \\\"oeq\\\", %arg0, %arg1 : f64\\n                %ret_i8 = arith.extui %cmp : i1 to i8\\n                sparse_tensor.yield %ret_i8 : i8\\n            }\\n            left={}\\n            right={}\\n          linalg.yield %result : i8\\n      } -> tensor<?xi8, #SparseVector>\\n      ```\\n\\n      Example of A+B in upper triangle, A-B in lower triangle:\\n\\n      ```mlir\\n      %C = tensor.empty(...)\\n      %1 = linalg.generic #trait\\n        ins(%A: tensor<?x?xf64, #CSR>, %B: tensor<?x?xf64, #CSR>\\n        outs(%C: tensor<?x?xf64, #CSR> {\\n        ^bb0(%a: f64, %b: f64, %c: f64) :\\n          %row = linalg.index 0 : index\\n          %col = linalg.index 1 : index\\n          %result = sparse_tensor.binary %a, %b : f64, f64 to f64\\n            overlap={\\n              ^bb0(%x: f64, %y: f64):\\n                %cmp = arith.cmpi \\\"uge\\\", %col, %row : index\\n                %upperTriangleResult = arith.addf %x, %y : f64\\n                %lowerTriangleResult = arith.subf %x, %y : f64\\n                %ret = arith.select %cmp, %upperTriangleResult, %lowerTriangleResult : f64\\n                sparse_tensor.yield %ret : f64\\n            }\\n            left=identity\\n            right={\\n              ^bb0(%y: f64):\\n                %cmp = arith.cmpi \\\"uge\\\", %col, %row : index\\n                %lowerTriangleResult = arith.negf %y : f64\\n                %ret = arith.select %cmp, %y, %lowerTriangleResult : f64\\n                sparse_tensor.yield %ret : f64\\n            }\\n          linalg.yield %result : f64\\n      } -> tensor<?x?xf64, #CSR>\\n      ```\\n\\n      Example of set difference. Returns a copy of A where its sparse structure\\n      is *not* overlapped by B. The element type of B can be different than A\\n      because we never use its values, only its sparse structure:\\n\\n      ```mlir\\n      %C = tensor.empty(...)\\n      %2 = linalg.generic #trait\\n        ins(%A: tensor<?x?xf64, #CSR>, %B: tensor<?x?xi32, #CSR>\\n        outs(%C: tensor<?x?xf64, #CSR> {\\n        ^bb0(%a: f64, %b: i32, %c: f64) :\\n          %result = sparse_tensor.binary %a, %b : f64, i32 to f64\\n            overlap={}\\n            left=identity\\n            right={}\\n          linalg.yield %result : f64\\n      } -> tensor<?x?xf64, #CSR>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_identity\", \"type\": \"UnitAttr\" },\n      { \"name\": \"right_identity\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"overlapRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"leftRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"rightRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $y `:` attr-dict type($x) `,` type($y) `to` type($output) `\\\\n`\\n        `overlap` `=` $overlapRegion `\\\\n`\\n        `left` `=` (`identity` $left_identity^):($leftRegion)? `\\\\n`\\n        `right` `=` (`identity` $right_identity^):($rightRegion)?\"\n  },\n  {\n    \"name\": \"sparse_tensor.coiterate\",\n    \"summary\": \"Co-iterates over a set of sparse iteration spaces\",\n    \"description\": \"The `sparse_tensor.coiterate` operation represents a loop (nest) over\\n      a set of iteration spaces. The operation can have multiple regions,\\n      with each of them defining a case to compute a result at the current iterations.\\n      The case condition is defined solely based on the pattern of specified iterators.\\n      For example:\\n      ```mlir\\n      %ret = sparse_tensor.coiterate (%sp1, %sp2) at(%coord) iter_args(%arg = %init)\\n           : (!sparse_tensor.iter_space<#CSR, lvls = 0>,\\n              !sparse_tensor.iter_space<#COO, lvls = 0>)\\n           -> index\\n      case %it1, _ {\\n        // %coord is specifed in space %sp1 but *NOT* specified in space %sp2.\\n      }\\n      case %it1, %it2 {\\n        // %coord is specifed in *BOTH* spaces %sp1 and %sp2.\\n      }\\n      ```\\n\\n      `sparse_tensor.coiterate` can also operate on loop-carried variables.\\n      It returns the final value for each loop-carried variable after loop termination.\\n      The initial values of the variables are passed as additional SSA operands\\n      to the iterator SSA value and used coordinate SSA values.\\n      Each operation region has variadic arguments for specified (used), one argument\\n      for each loop-carried variable, representing the value of the variable\\n      at the current iteration, followed by a list of arguments for iterators.\\n      The body region must contain exactly one block that terminates with\\n      `sparse_tensor.yield`.\\n\\n      The results of an `sparse_tensor.coiterate` hold the final values after\\n      the last iteration. If the `sparse_tensor.coiterate` defines any values,\\n      a yield must be explicitly present in every region defined in the operation.\\n      The number and types of the `sparse_tensor.coiterate` results must match\\n      the initial values in the iter_args binding and the yield operands.\\n\\n\\n      A `sparse_tensor.coiterate` example that does elementwise addition between two\\n      sparse vectors.\\n\\n\\n      ```mlir\\n      %ret = sparse_tensor.coiterate (%sp1, %sp2) at(%coord) iter_args(%arg = %init)\\n           : (!sparse_tensor.iter_space<#CSR, lvls = 0>,\\n              !sparse_tensor.iter_space<#CSR, lvls = 0>)\\n           -> tensor<?xindex, #CSR>\\n      case %it1, _ {\\n         // v = v1 + 0 = v1\\n         %v1 = sparse_tensor.extract_value %t1 at %it1 : index\\n         %yield = sparse_tensor.insert %v1 into %arg[%coord]\\n         sparse_tensor.yield %yield\\n      }\\n      case _, %it2 {\\n         // v = v2 + 0 = v2\\n         %v2 = sparse_tensor.extract_value %t2 at %it2 : index\\n         %yield = sparse_tensor.insert %v1 into %arg[%coord]\\n         sparse_tensor.yield %yield\\n      }\\n      case %it1, %it2 {\\n         // v = v1 + v2\\n         %v1 = sparse_tensor.extract_value %t1 at %it1 : index\\n         %v2 = sparse_tensor.extract_value %t2 at %it2 : index\\n         %v = arith.addi %v1, %v2 : index\\n         %yield = sparse_tensor.insert %v into %arg[%coord]\\n         sparse_tensor.yield %yield\\n      }\\n      ```\",\n    \"operands\": [\n      { \"name\": \"iterSpaces\", \"type\": \"Variadic<AnySparseIterSpace>\" },\n      { \"name\": \"initArgs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"crdUsedLvls\", \"type\": \"I64BitSetAttr\" },\n      { \"name\": \"cases\", \"type\": \"TypedArrayAttrBase<I64BitSetAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"caseRegions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sparse_tensor.compress\",\n    \"summary\": \"Compressed an access pattern for insertion\",\n    \"description\": \"Finishes a single access pattern expansion by moving inserted elements\\n    into the sparse storage scheme of the given tensor with the given\\n    level-coordinates.  The arity of `lvlCoords` is one less than the\\n    level-rank of the tensor, with the coordinate of the innermost\\n    level defined through the `added` array.  The `values` and `filled`\\n    arrays are reset in a *sparse* fashion by only iterating over set\\n    elements through an indirection using the `added` array, so that\\n    the operations are kept proportional to the number of nonzeros.\\n    See the `sparse_tensor.expand` operation for more details.\\n\\n    Note that this operation is \\\"impure\\\" in the sense that even though\\n    the result is modeled through an SSA value, the insertion is eventually\\n    done \\\"in place\\\", and referencing the old SSA value is undefined behavior.\\n\\n    Example:\\n\\n    ```mlir\\n    %result = sparse_tensor.compress %values, %filled, %added, %count into %tensor[%i]\\n      : memref<?xf64>, memref<?xi1>, memref<?xindex>, tensor<4x4xf64, #CSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"AnyStridedMemRefOfRank<1>\" },\n      { \"name\": \"filled\", \"type\": \"StridedMemRefRankOf<[I1], [1]>\" },\n      { \"name\": \"added\", \"type\": \"StridedMemRefRankOf<[Index], [1]>\" },\n      { \"name\": \"count\", \"type\": \"Index\" },\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" },\n      { \"name\": \"lvlCoords\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['tensor', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$values `,` $filled `,` $added `,` $count `into` $tensor `[` $lvlCoords `]` attr-dict `:` type($values) `,` type($filled) `,` type($added) `,` type($tensor)\"\n  },\n  {\n    \"name\": \"sparse_tensor.concatenate\",\n    \"summary\": \"Concatenates a list of tensors into a single tensor.\",\n    \"description\": \"Concatenates a list input tensors and the output tensor with the same\\n     dimension-rank.  The concatenation happens on the specified `dimension`\\n     (0 <= dimension < dimRank).  The resulting `dimension` size is the\\n     sum of all the input sizes for that dimension, while all the other\\n     dimensions should have the same size in the input and output tensors.\\n\\n     Only statically-sized input tensors are accepted, while the output tensor\\n     can be dynamically-sized.\\n\\n     Example:\\n\\n     ```mlir\\n     %0 = sparse_tensor.concatenate %1, %2 { dimension = 0 : index }\\n       : tensor<64x64xf64, #CSR>, tensor<64x64xf64, #CSR> to tensor<128x64xf64, #CSR>\\n     ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"DimensionAttr\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` type($inputs) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.convert\",\n    \"summary\": \"Converts between different tensor types\",\n    \"description\": \"Converts one sparse or dense tensor type to another tensor type. The rank\\n    of the source and destination types must match exactly, and the dimension\\n    sizes must either match exactly or relax from a static to a dynamic size.\\n    The sparse encoding of the two types can obviously be completely different.\\n    The name `convert` was preferred over `cast`, since the operation may incur\\n    a non-trivial cost.\\n\\n    When converting between two different sparse tensor types, only explicitly\\n    stored values are moved from one underlying sparse storage format to\\n    the other. When converting from an unannotated dense tensor type to a\\n    sparse tensor type, an explicit test for nonzero values is used. When\\n    converting to an unannotated dense tensor type, implicit zeroes in the\\n    sparse storage format are made explicit. Note that the conversions can have\\n    non-trivial costs associated with them, since they may involve elaborate\\n    data structure transformations. Also, conversions from sparse tensor types\\n    into dense tensor types may be infeasible in terms of storage requirements.\\n\\n    Trivial dense-to-dense convert will be removed by canonicalization while\\n    trivial sparse-to-sparse convert will be removed by the sparse codegen. This\\n    is because we use trivial sparse-to-sparse convert to tell bufferization\\n    that the sparse codegen will expand the tensor buffer into sparse tensor\\n    storage.\\n\\n    Examples:\\n\\n    ```mlir\\n    %0 = sparse_tensor.convert %a : tensor<32x32xf32> to tensor<32x32xf32, #CSR>\\n    %1 = sparse_tensor.convert %a : tensor<32x32xf32> to tensor<?x?xf32, #CSR>\\n    %2 = sparse_tensor.convert %b : tensor<8x8xi32, #CSC> to tensor<8x8xi32, #CSR>\\n    %3 = sparse_tensor.convert %c : tensor<4x8xf64, #CSR> to tensor<4x?xf64, #CSC>\\n\\n    // The following conversion is not allowed (since it would require a\\n    // runtime assertion that the source's dimension size is actually 100).\\n    %4 = sparse_tensor.convert %d : tensor<?xf64> to tensor<100xf64, #SV>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"sparse_tensor.coordinates\",\n    \"summary\": \"Extracts the `level`-th coordinates array of the `tensor`\",\n    \"description\": \"Returns the coordinates array of the tensor's storage at the given\\n    level.  This is similar to the `bufferization.to_buffer` operation\\n    in the sense that it provides a bridge between a tensor world view\\n    and a bufferized world view.  Unlike the `bufferization.to_buffer`\\n    operation, however, this sparse operation actually lowers into code\\n    that extracts the coordinates array from the sparse storage itself\\n    (either by calling a support library or through direct code).\\n\\n    Writing into the result of this operation is undefined behavior.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = sparse_tensor.coordinates %0 { level = 1 : index }\\n       : tensor<64x64xf64, #CSR> to memref<?xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"level\", \"type\": \"LevelAttr\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.coordinates_buffer\",\n    \"summary\": \"Extracts the linear coordinates array from a tensor\",\n    \"description\": \"Returns the linear coordinates array for a sparse tensor with\\n    a trailing COO region with at least two levels.  It is an error\\n    if the tensor doesn't contain such a COO region.  This is similar\\n    to the `bufferization.to_buffer` operation in the sense that it\\n    provides a bridge between a tensor world view and a bufferized\\n    world view.  Unlike the `bufferization.to_buffer` operation,\\n    however, this operation actually lowers into code that extracts\\n    the linear coordinates array from the sparse storage scheme that\\n    stores the coordinates for the COO region as an array of structures.\\n    For example, a 2D COO sparse tensor with two non-zero elements at\\n    coordinates (1, 3) and (4, 6) are stored in a linear buffer as\\n    (1, 4, 3, 6) instead of two buffer as (1, 4) and (3, 6).\\n\\n    Writing into the result of this operation is undefined behavior.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = sparse_tensor.coordinates_buffer %0\\n       : tensor<64x64xf64, #COO> to memref<?xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.crd_translate\",\n    \"summary\": \"Performs coordinate translation between level and dimension coordinate space.\",\n    \"description\": \"Performs coordinate translation between level and dimension coordinate space according\\n    to the affine maps defined by $encoder.\\n\\n    Example:\\n\\n    ```mlir\\n    %l0, %l1, %l2, %l3 = sparse_tensor.crd_translate dim_to_lvl [%d0, %d1] as #BSR\\n                       : index, index, index, index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"in_crds\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_crds\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"direction\", \"type\": \"SparseTensorCrdTransDirectionAttr{dim_to_lvl|lvl_to_dim}\" },\n      { \"name\": \"encoder\", \"type\": \"SparseTensorEncodingAttr\" }\n    ],\n    \"assemblyFormat\": \"$direction `[` $in_crds `]` `as` $encoder attr-dict `:` type($out_crds)\"\n  },\n  {\n    \"name\": \"sparse_tensor.disassemble\",\n    \"summary\": \"Copies the levels and values of the given sparse tensor\",\n    \"description\": \"The disassemble operation is the inverse of `sparse_tensor::assemble`.\\n    It copies the per-level position and coordinate arrays together with\\n    the values array of the given sparse tensor into the user-supplied buffers\\n    along with the actual length of the memory used in each returned buffer.\\n\\n    This operation can be used for returning a disassembled MLIR sparse tensor;\\n    e.g., copying the sparse tensor contents into pre-allocated numpy arrays\\n    back to Python. It is the user's responsibility to allocate large enough\\n    buffers of the appropriate types to hold the sparse tensor contents.\\n    The sparsifier simply copies all fields of the sparse tensor into the\\n    user-supplied buffers without any sanity test to verify data integrity.\\n\\n    Example:\\n\\n    ```mlir\\n    // input COO format |1.1, 0.0, 0.0, 0.0|\\n    //    of 3x4 matrix |0.0, 0.0, 2.2, 3.3|\\n    //                  |0.0, 0.0, 0.0, 0.0|\\n    %p, %c, %v, %p_len, %c_len, %v_len =\\n      sparse_tensor.disassemble %s : tensor<3x4xf64, #COO>\\n         out_lvls(%op, %oi : tensor<2xindex>, tensor<3x2xindex>)\\n         out_vals(%od : tensor<3xf64>) ->\\n           (tensor<2xindex>, tensor<3x2xindex>), tensor<3xf64>, (index, index), index\\n    // %p = arith.constant dense<[ 0,              3 ]> : tensor<2xindex>\\n    // %c = arith.constant dense<[[0,0], [1,2], [1,3]]> : tensor<3x2xindex>\\n    // %v = arith.constant dense<[ 1.1,   2.2,   3.3 ]> : tensor<3xf64>\\n    // %p_len = 2\\n    // %c_len = 6 (3x2)\\n    // %v_len = 3\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" },\n      { \"name\": \"out_levels\", \"type\": \"Variadic<RankedTensorOf<[ AnySignlessIntegerOrIndex ]>>\" },\n      { \"name\": \"out_values\", \"type\": \"RankedTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"ret_levels\", \"type\": \"Variadic<RankedTensorOf<[ AnySignlessIntegerOrIndex ]>>\" },\n      { \"name\": \"ret_values\", \"type\": \"RankedTensorOf<[AnyType]>\" },\n      { \"name\": \"lvl_lens\", \"type\": \"Variadic<AnyIndexingScalarLike>\" },\n      { \"name\": \"val_len\", \"type\": \"AnyIndexingScalarLike\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor)`out_lvls` `(` $out_levels `:` type($out_levels) `)` `out_vals` `(` $out_values `:` type($out_values) `)` `->``(` type($ret_levels) `)` `,` type($ret_values) `,` `(` type($lvl_lens)   `)` `,` type($val_len)\"\n  },\n  {\n    \"name\": \"sparse_tensor.expand\",\n    \"summary\": \"Expands an access pattern for insertion\",\n    \"description\": \"Performs an access pattern expansion for the innermost levels of the\\n    given tensor. This operation is useful to implement kernels in which a\\n    sparse tensor appears as output. This technique is known under several\\n    different names and using several alternative implementations,\\n    for example, phase counter [Gustavson72], expanded or switch array\\n    [Pissanetzky84], in phase scan [Duff90], access pattern expansion [Bik96],\\n    and workspaces [Kjolstad19].\\n\\n    The `values` and `filled` arrays must have lengths equal to the\\n    level-size of the innermost level (i.e., as if the innermost level\\n    were *dense*).  The `added` array and `count` are used to store new\\n    level-coordinates when a false value is encountered in the `filled`\\n    array.  All arrays should be allocated before the loop (possibly even\\n    shared between loops in a future optimization) so that their *dense*\\n    initialization can be amortized over many iterations.  Setting and\\n    resetting the dense arrays in the loop nest itself is kept *sparse*\\n    by only iterating over set elements through an indirection using\\n    the added array, so that the operations are kept proportional to\\n    the number of nonzeros.\\n\\n    Note that this operation is \\\"impure\\\" in the sense that even though the\\n    results are modeled through SSA values, the operation relies on a proper\\n    side-effecting context that sets and resets the expanded arrays.\\n\\n    Example:\\n\\n    ```mlir\\n    %values, %filled, %added, %count = sparse_tensor.expand %tensor\\n      : tensor<4x4xf64, #CSR> to memref<?xf64>, memref<?xi1>, memref<?xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyStridedMemRefOfRank<1>\" },\n      { \"name\": \"filled\", \"type\": \"StridedMemRefRankOf<[I1], [1]>\" },\n      { \"name\": \"added\", \"type\": \"StridedMemRefRankOf<[Index], [1]>\" },\n      { \"name\": \"count\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor) `to` type($values) `,` type($filled) `,` type($added)\"\n  },\n  {\n    \"name\": \"sparse_tensor.extract_iteration_space\",\n    \"summary\": \"Extracts an iteration space from a sparse tensor between certain levels\",\n    \"description\": \"Extracts a `!sparse_tensor.iter_space` from a sparse tensor between\\n      certain (consecutive) levels. For sparse levels, it is usually done by\\n      loading a postion range from the underlying sparse tensor storage.\\n      E.g., for a compressed level, the iteration space is extracted by\\n      [pos[i], pos[i+1]) supposing the the parent iterator points at `i`.\\n\\n      `tensor`: the input sparse tensor that defines the iteration space.\\n      `parentIter`: the iterator for the previous level, at which the iteration space\\n      at the current levels will be extracted.\\n      `loLvl`, `hiLvl`: the level range between [loLvl, hiLvl) in the input tensor that\\n      the returned iteration space covers. `hiLvl - loLvl` defines the dimension of the\\n      iteration space.\\n\\n      The type of returned the value is must be\\n      `!sparse_tensor.iter_space<#INPUT_ENCODING, lvls = $loLvl to $hiLvl>`.\\n      The returned iteration space can then be iterated over by\\n      `sparse_tensor.iterate` operations to visit every stored element\\n      (usually nonzeros) in the input sparse tensor.\\n\\n      Example:\\n      ```mlir\\n      // Extracts a 1-D iteration space from a COO tensor at level 1.\\n      %space = sparse_tensor.iteration.extract_space %sp at %it1 lvls = 1\\n        : tensor<4x8xf32, #COO>, !sparse_tensor.iterator<#COO, lvls = 0>\\n       ->!sparse_tensor.iter_space<#COO, lvls = 1>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" },\n      { \"name\": \"parentIter\", \"type\": \"Optional<AnySparseIterator>\" }\n    ],\n    \"results\": [\n      { \"name\": \"extractedSpace\", \"type\": \"AnySparseIterSpace\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"loLvl\", \"type\": \"LevelAttr\" },\n      { \"name\": \"hiLvl\", \"type\": \"LevelAttr\" }\n    ],\n    \"assemblyFormat\": \"$tensor (`at` $parentIter^)? `lvls` `=` custom<LevelRange>($loLvl, $hiLvl)  attr-dict `:` type($tensor) (`,` type($parentIter)^)? `->` qualified(type($extractedSpace))\"\n  },\n  {\n    \"name\": \"sparse_tensor.extract_value\",\n    \"summary\": \"Extracts a value from a sparse tensor using an iterator.\",\n    \"description\": \"The `sparse_tensor.extract_value` operation extracts the value\\n      pointed to by a sparse iterator from a sparse tensor.\\n\\n      Example:\\n\\n      ```mlir\\n      %val = sparse_tensor.extract_value %sp at %it\\n           : tensor<?x?xf32, #CSR>, !sparse_tensor.iterator<#CSR, lvl = 1>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" },\n      { \"name\": \"iterator\", \"type\": \"AnySparseIterator\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'tensor', 'result', '::llvm::cast<TensorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$tensor `at` $iterator attr-dict `:` type($tensor)`,` qualified(type($iterator))\"\n  },\n  {\n    \"name\": \"sparse_tensor.foreach\",\n    \"summary\": \"Iterates over elements in a tensor\",\n    \"description\": \"Iterates over stored elements in a tensor (which are typically, but not always,\\n     non-zero for sparse tensors) and executes the block.\\n\\n     `tensor`: the input tensor to iterate over.\\n     `initArgs`: the initial loop argument to carry and update during each iteration.\\n     `order`: an optional permutation affine map that specifies the order in which\\n     the dimensions are visited (e.g., row first or column first). This is only\\n     applicable when the input tensor is a non-annotated dense tensor.\\n\\n     For an input tensor with dim-rank `n`, the block must take `n + 1`\\n     arguments (plus additional loop-carried variables as described below).\\n     The first `n` arguments provide the dimension-coordinates of the element\\n     being visited, and must all have `index` type.  The `(n+1)`-th argument\\n     provides the element's value, and must have the tensor's element type.\\n\\n     `sparse_tensor.foreach` can also operate on loop-carried variables and returns\\n     the final values after loop termination. The initial values of the variables are\\n     passed as additional SSA operands to the \\\"sparse_tensor.foreach\\\" following the n + 1\\n     SSA values mentioned above (n coordinates and 1 value).\\n\\n     The region must terminate with a \\\"sparse_tensor.yield\\\" that passes the current\\n     values of all loop-carried variables to the next iteration, or to the\\n     result, if at the last iteration. The number and static types of loop-carried\\n     variables may not change with iterations.\\n\\n     For example:\\n     ```mlir\\n     %c0 = arith.constant 0 : i32\\n     %ret = sparse_tensor.foreach in %0 init(%c0): tensor<?x?xi32, #DCSR>, i32 -> i32 do {\\n      ^bb0(%arg1: index, %arg2: index, %arg3: i32, %iter: i32):\\n        %sum = arith.add %iter, %arg3\\n        sparse_tensor.yield %sum\\n     }\\n     ```\\n\\n     It is important to note that the generated loop iterates over\\n     elements in their storage order.  However, regardless of the\\n     storage scheme used by the tensor, the block is always given\\n     the dimension-coordinates.\\n\\n     For example:\\n     ```mlir\\n     #COL_MAJOR = #sparse_tensor.encoding<{\\n       map = (d0, d1) -> (d1 : compressed, d0 : compressed)\\n     }>\\n\\n     // foreach on a column-major sparse tensor\\n     sparse_tensor.foreach in %0 : tensor<2x3xf64, #COL_MAJOR> do {\\n      ^bb0(%row: index, %col: index, %arg3: f64):\\n         // [%row, %col] -> [0, 0], [1, 0], [2, 0], [0, 1], [1, 1], [2, 1]\\n     }\\n\\n     #ROW_MAJOR = #sparse_tensor.encoding<{\\n       map = (d0, d1) -> (d0 : compressed, d1 : compressed)\\n     }>\\n\\n     // foreach on a row-major sparse tensor\\n     sparse_tensor.foreach in %0 : tensor<2x3xf64, #ROW_MAJOR> do {\\n      ^bb0(%row: index, %col: index, %arg3: f64):\\n         // [%row, %col] -> [0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]\\n     }\\n\\n     // foreach on a row-major dense tensor but visit column first\\n     sparse_tensor.foreach in %0 {order=affine_map<(i,j)->(j,i)>}: tensor<2x3xf64> do {\\n      ^bb0(%row: index, %col: index, %arg3: f64):\\n         // [%row, %col] -> [0, 0], [1, 0], [2, 0], [0, 1], [1, 1], [2, 1]\\n     }\\n\\n     ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"initArgs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"OptionalAttr<AffineMapAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`in` $tensor (`init``(`$initArgs^`)`)? attr-dict    `:` type($tensor) (`,` type($initArgs)^)?  (`->` type($results)^)?  `do` $region\"\n  },\n  {\n    \"name\": \"sparse_tensor.has_runtime_library\",\n    \"summary\": \"Indicates whether running in runtime/codegen mode\",\n    \"description\": \"Returns a boolean value that indicates whether the sparsifier runs in\\n    runtime library mode or not. For testing only! This operation is useful\\n    for writing test cases that require different code depending on\\n    runtime/codegen mode.\\n\\n    Example:\\n\\n    ```mlir\\n    %has_runtime = sparse_tensor.has_runtime_library\\n    scf.if %has_runtime {\\n      ...\\n    }\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"sparse_tensor.iterate\",\n    \"summary\": \"Iterates over a sparse iteration space\",\n    \"description\": \"The `sparse_tensor.iterate` operation represents a loop (nest) over\\n      the provided iteration space extracted from a specific sparse tensor.\\n      The operation defines an SSA value for a sparse iterator that points\\n      to the current stored element in the sparse tensor and SSA values\\n      for coordinates of the stored element. The coordinates are always\\n      converted to `index` type despite of the underlying sparse tensor\\n      storage. When coordinates are not used, the SSA values can be skipped\\n      by `_` symbols, which usually leads to simpler generated code after\\n      sparsification. For example:\\n\\n      ```mlir\\n      // The coordinate for level 0 is not used when iterating over a 2-D\\n      // iteration space.\\n      %sparse_tensor.iterate %iterator in %space at(_, %crd_1)\\n        : !sparse_tensor.iter_space<#CSR, lvls = 0 to 2>\\n      ```\\n\\n      `sparse_tensor.iterate` can also operate on loop-carried variables.\\n      It returns the final values after loop termination.\\n      The initial values of the variables are passed as additional SSA operands\\n      to the iterator SSA value and used coordinate SSA values mentioned\\n      above. The operation region has an argument for the iterator, variadic\\n      arguments for specified (used) coordiates and followed by one argument\\n      for each loop-carried variable, representing the value of the variable\\n      at the current iteration.\\n      The body region must contain exactly one block that terminates with\\n      `sparse_tensor.yield`.\\n\\n      The results of an `sparse_tensor.iterate` hold the final values after\\n      the last iteration. If the `sparse_tensor.iterate` defines any values,\\n      a yield must be explicitly present.\\n      The number and types of the `sparse_tensor.iterate` results must match\\n      the initial values in the iter_args binding and the yield operands.\\n\\n\\n      A nested `sparse_tensor.iterate` example that prints all the coordinates\\n      stored in the sparse input:\\n\\n      ```mlir\\n      func.func @nested_iterate(%sp : tensor<4x8xf32, #COO>) {\\n        // Iterates over the first level of %sp\\n        %l1 = sparse_tensor.extract_iteration_space %sp lvls = 0\\n            : tensor<4x8xf32, #COO> -> !sparse_tensor.iter_space<#COO, lvls = 0 to 1>\\n        %r1 = sparse_tensor.iterate %it1 in %l1 at (%coord0)\\n            : !sparse_tensor.iter_space<#COO, lvls = 0 to 1>  {\\n          // Iterates over the second level of %sp\\n          %l2 = sparse_tensor.extract_iteration_space %sp at %it1 lvls = 1\\n              : tensor<4x8xf32, #COO>, !sparse_tensor.iterator<#COO, lvls = 0 to 1>\\n             -> !sparse_tensor.iter_space<#COO, lvls = 1 to 2>\\n          %r2 = sparse_tensor.iterate %it2 in %l2 at (coord1)\\n              : !sparse_tensor.iter_space<#COO, lvls = 1 to 2>  {\\n             vector.print %coord0 : index\\n             vector.print %coord1 : index\\n          }\\n        }\\n      }\\n\\n      ```\",\n    \"operands\": [\n      { \"name\": \"iterSpace\", \"type\": \"AnySparseIterSpace\" },\n      { \"name\": \"initArgs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"crdUsedLvls\", \"type\": \"I64BitSetAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"sparse_tensor.load\",\n    \"summary\": \"Rematerializes tensor from underlying sparse storage format\",\n    \"description\": \"Rematerializes a tensor from the underlying sparse storage format of the\\n    given tensor. This is similar to the `bufferization.to_tensor` operation\\n    in the sense that it provides a bridge between a bufferized world view\\n    and a tensor world view. Unlike the `bufferization.to_tensor` operation,\\n    however, this sparse operation is used only temporarily to maintain a\\n    correctly typed intermediate representation during progressive\\n    bufferization.\\n\\n    The `hasInserts` attribute denote whether insertions to the underlying\\n    sparse storage format may have occurred, in which case the underlying\\n    sparse storage format needs to be finalized. Otherwise, the operation\\n    simply folds away.\\n\\n    Note that this operation is \\\"impure\\\" in the sense that even though\\n    the result is modeled through an SSA value, the operation relies on\\n    a proper context of materializing and inserting the tensor value.\\n\\n    Examples:\\n\\n    ```mlir\\n    %result = sparse_tensor.load %tensor : tensor<8xf64, #SV>\\n\\n    %1 = sparse_tensor.load %0 hasInserts : tensor<16x32xf32, #CSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hasInserts\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$tensor (`hasInserts` $hasInserts^)? attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"sparse_tensor.lvl\",\n    \"summary\": \"level index operation\",\n    \"description\": \"The `sparse_tensor.lvl` behaves similar to `tensor.dim` operation.\\n    It takes a sparse tensor and a level operand of type `index` and returns\\n    the size of the requested level of the given sparse tensor.\\n    If the sparse tensor has an identity dimension to level mapping, it returns\\n    the same result as `tensor.dim`.\\n    If the level index is out of bounds, the behavior is undefined.\\n\\n    Example:\\n\\n    ```mlir\\n    #BSR = #sparse_tensor.encoding<{\\n      map = ( i, j ) ->\\n        ( i floordiv 2 : dense,\\n          j floordiv 3 : compressed,\\n          i mod 2      : dense,\\n          j mod 3      : dense\\n        )\\n    }>\\n\\n    // Always returns 2 (4 floordiv 2), can be constant folded:\\n    %c0 = arith.constant 0 : index\\n    %x = sparse_tensor.lvl %A, %c0 : tensor<4x?xf32, #BSR>\\n\\n    // Return the dynamic dimension of %A computed by %j mod 3.\\n    %c1 = arith.constant 1 : index\\n    %y = sparse_tensor.lvl %A, %c1 : tensor<4x?xf32, #BSR>\\n\\n    // Always return 3 (since j mod 3 < 3), can be constant fold\\n    %c3 = arith.constant 3 : index\\n    %y = sparse_tensor.lvl %A, %c3 : tensor<4x?xf32, #BSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnySparseTensor\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `,` $index `:` type($source)\"\n  },\n  {\n    \"name\": \"sparse_tensor.new\",\n    \"summary\": \"Materializes a new sparse tensor from given source\",\n    \"description\": \"Materializes a sparse tensor with contents taken from an opaque pointer\\n    provided by `source`. For targets that have access to a file system,\\n    for example, this pointer may be a filename (or file) of a sparse\\n    tensor in a particular external storage format. The form of the operation\\n    is kept deliberately very general to allow for alternative implementations\\n    in the future, such as pointers to buffers or runnable initialization\\n    code. The operation is provided as an anchor that materializes a properly\\n    typed sparse tensor with inital contents into a computation.\\n\\n    Reading in a symmetric matrix will result in just the lower/upper triangular\\n    part of the matrix (so that only relevant information is stored). Proper\\n    symmetry support for operating on symmetric matrices is still TBD.\\n\\n    Example:\\n\\n    ```mlir\\n    sparse_tensor.new %source : !Source to tensor<1024x1024xf64, #CSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.number_of_entries\",\n    \"summary\": \"Returns the number of entries that are stored in the tensor.\",\n    \"description\": \"Returns the number of entries that are stored in the given sparse tensor.\\n    Note that this is typically the number of nonzero elements in the tensor,\\n    but since explicit zeros may appear in the storage formats, the more\\n    accurate nomenclature is used.\\n\\n    Example:\\n\\n    ```mlir\\n    %noe = sparse_tensor.number_of_entries %tensor : tensor<64x64xf64, #CSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"sparse_tensor.out\",\n    \"summary\": \"Outputs a sparse tensor to the given destination\",\n    \"description\": \"Outputs the contents of a sparse tensor to the destination defined by an\\n    opaque pointer provided by `dest`. For targets that have access to a file\\n    system, for example, this pointer may specify a filename (or file) for output.\\n    The form of the operation is kept deliberately very general to allow for\\n    alternative implementations in the future, such as sending the contents to\\n    a buffer defined by a pointer.\\n\\n    Note that this operation is \\\"impure\\\" in the sense that its behavior\\n    is solely defined by side-effects and not SSA values.\\n\\n    Example:\\n\\n    ```mlir\\n    sparse_tensor.out %t, %dest : tensor<1024x1024xf64, #CSR>, !Dest\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$tensor `,` $dest attr-dict `:` type($tensor) `,` type($dest)\"\n  },\n  {\n    \"name\": \"sparse_tensor.positions\",\n    \"summary\": \"Extracts the `level`-th positions array of the `tensor`\",\n    \"description\": \"Returns the positions array of the tensor's storage at the given\\n    level.  This is similar to the `bufferization.to_buffer` operation\\n    in the sense that it provides a bridge between a tensor world view\\n    and a bufferized world view.  Unlike the `bufferization.to_buffer`\\n    operation, however, this sparse operation actually lowers into code\\n    that extracts the positions array from the sparse storage itself\\n    (either by calling a support library or through direct code).\\n\\n    Writing into the result of this operation is undefined behavior.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = sparse_tensor.positions %0 { level = 1 : index }\\n       : tensor<64x64xf64, #CSR> to memref<?xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"level\", \"type\": \"LevelAttr\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.print\",\n    \"summary\": \"Prints a sparse tensor (for testing and debugging)\",\n    \"description\": \"Prints the individual components of a sparse tensors (the positions,\\n    coordinates, and values components) to stdout for testing and debugging\\n    purposes. This operation lowers to just a few primitives in a light-weight\\n    runtime support to simplify supporting this operation on new platforms.\\n\\n    Example:\\n\\n    ```mlir\\n    sparse_tensor.print %tensor : tensor<1024x1024xf64, #CSR>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"sparse_tensor.push_back\",\n    \"summary\": \"Pushes a value to the back of a given buffer\",\n    \"description\": \"Pushes `value` to the end of the given sparse tensor storage buffer\\n    `inBuffer` as indicated by the value of `curSize` and returns the\\n    new size of the buffer in `newSize` (`newSize = curSize + n`).\\n    The capacity of the buffer is recorded in the memref type of `inBuffer`.\\n    If the current buffer is full, then `inBuffer.realloc` is called before\\n    pushing the data to the buffer. This is similar to std::vector push_back.\\n\\n    The optional input `n` specifies the number of times to repeately push\\n    the value to the back of the tensor. When `n` is a compile-time constant,\\n    its value can't be less than 1. If `n` is a runtime value that is less\\n    than 1, the behavior is undefined. Although using input `n` is semantically\\n    equivalent to calling push_back n times, it gives compiler more chances to\\n    to optimize the memory reallocation and the filling of the memory with the\\n    same value.\\n\\n    The `inbounds` attribute tells the compiler that the insertion won't go\\n    beyond the current storage buffer. This allows the compiler to not generate\\n    the code for capacity check and reallocation. The typical usage will be for\\n    \\\"dynamic\\\" sparse tensors for which a capacity can be set beforehand.\\n\\n    Note that this operation is \\\"impure\\\" in the sense that even though\\n    the result is modeled through an SSA value, referencing the memref\\n    through the old SSA value after this operation is undefined behavior.\\n\\n    Example:\\n\\n    ```mlir\\n    %buf, %newSize = sparse_tensor.push_back %curSize, %buffer, %val\\n       : index, memref<?xf64>, f64\\n    ```\\n\\n    ```mlir\\n    %buf, %newSize = sparse_tensor.push_back inbounds %curSize, %buffer, %val\\n       : xindex, memref<?xf64>, f64\\n    ```\\n\\n    ```mlir\\n    %buf, %newSize = sparse_tensor.push_back inbounds %curSize, %buffer, %val, %n\\n       : xindex, memref<?xf64>, f64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"curSize\", \"type\": \"Index\" },\n      { \"name\": \"inBuffer\", \"type\": \"StridedMemRefRankOf<[AnyType], [1]>\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"n\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outBuffer\", \"type\": \"StridedMemRefRankOf<[AnyType], [1]>\" },\n      { \"name\": \"newSize\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inbounds\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'inBuffer', 'value', '::llvm::cast<ShapedType>($_self).getElementType()'>\" },\n      { \"type\": \"AllTypesMatch<['inBuffer', 'outBuffer']>\" }\n    ],\n    \"assemblyFormat\": \"(`inbounds` $inbounds^)? $curSize `,` $inBuffer `,` $value (`,` $n^ )?  attr-dict `:` type($curSize) `,` type($inBuffer) `,` type($value) (`,` type($n)^ )?\"\n  },\n  {\n    \"name\": \"sparse_tensor.reduce\",\n    \"summary\": \"Custom reduction operation utilized within linalg.generic\",\n    \"description\": \"Defines a computation with a `linalg.generic` operation that takes two\\n      operands and an identity value and reduces all stored values down to a\\n      single result based on the computation in the region.\\n\\n      The region must contain exactly one block taking two arguments. The block\\n      must end with a sparse_tensor.yield and the output must match the input\\n      argument types.\\n\\n      Note that this operation is only required for custom reductions beyond\\n      the standard reduction operations (add, sub, or, xor) that can be\\n      sparsified by merely reducing the stored values. More elaborate reduction\\n      operations (mul, and, min, max, etc.) would need to account for implicit\\n      zeros as well. They can still be handled using this custom reduction\\n      operation. The `linalg.generic` `iterator_types` defines which indices\\n      are being reduced. When the associated operands are used in an operation,\\n      a reduction will occur. The use of this explicit `reduce` operation\\n      is not required in most cases.\\n\\n      Example of Matrix->Vector reduction using max(product(x_i), 100):\\n\\n      ```mlir\\n      %cf1 = arith.constant 1.0 : f64\\n      %cf100 = arith.constant 100.0 : f64\\n      %C = tensor.empty(...)\\n      %0 = linalg.generic #trait\\n         ins(%A: tensor<?x?xf64, #SparseMatrix>)\\n        outs(%C: tensor<?xf64, #SparseVector>) {\\n        ^bb0(%a: f64, %c: f64) :\\n          %result = sparse_tensor.reduce %c, %a, %cf1 : f64 {\\n              ^bb0(%arg0: f64, %arg1: f64):\\n                %0 = arith.mulf %arg0, %arg1 : f64\\n                %cmp = arith.cmpf \\\"ogt\\\", %0, %cf100 : f64\\n                %ret = arith.select %cmp, %cf100, %0 : f64\\n                sparse_tensor.yield %ret : f64\\n            }\\n          linalg.yield %result : f64\\n      } -> tensor<?xf64, #SparseVector>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" },\n      { \"name\": \"identity\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $y `,` $identity attr-dict `:` type($output) $region\"\n  },\n  {\n    \"name\": \"sparse_tensor.reinterpret_map\",\n    \"summary\": \"Reinterprets the dimension/level maps of the source tensor\",\n    \"description\": \"Reinterprets the dimension-to-level and level-to-dimension map specified in\\n    `source` according to the type of `dest`.\\n    `reinterpret_map` is a no-op and is introduced merely to resolve type conflicts.\\n    It does not make any modification to the source tensor and source/dest tensors\\n    are considered to be aliases.\\n\\n    `source` and `dest` tensors are \\\"reinterpretable\\\" if and only if they have\\n    the exactly same storage at a low level.\\n    That is, both `source` and `dest` has the same number of levels and level types,\\n    and their shape is consistent before and after `reinterpret_map`.\\n\\n    Example:\\n    ```mlir\\n    #CSC = #sparse_tensor.encoding<{\\n      map = (d0, d1) -> (d1: dense, d0: compressed)\\n    }>\\n    #CSR = #sparse_tensor.encoding<{\\n      map = (d0, d1) -> (d0: dense, d1: compressed)\\n    }>\\n    %t1 = sparse_tensor.reinterpret_map %t0 : tensor<3x4xi32, #CSC> to tensor<4x3xi32, #CSR>\\n\\n    #BSR = #sparse_tensor.encoding<{\\n      map = ( i, j ) -> ( i floordiv 2 : dense,\\n                          j floordiv 3 : compressed,\\n                          i mod 2      : dense,\\n                          j mod 3      : dense\\n      )\\n    }>\\n    #DSDD = #sparse_tensor.encoding<{\\n      map = (i, j, k, l) -> (i: dense, j: compressed, k: dense, l: dense)\\n    }>\\n    %t1 = sparse_tensor.reinterpret_map %t0 : tensor<6x12xi32, #BSR> to tensor<3x4x2x3xi32, #DSDD>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dstEnc\", \"type\": \"SparseTensorEncodingAttr\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"sparse_tensor.reorder_coo\",\n    \"summary\": \"Reorder the input COO such that it has the the same order as the output COO\",\n    \"description\": \"Reorders the input COO to the same order as specified by the output format.\\n    E.g., reorder an unordered COO into an ordered one.\\n\\n    The input and result COO tensor must have the same element type, position type and\\n    coordinate type. At the moment, the operation also only supports ordering\\n    input and result COO with the same dim2lvl map.\\n\\n    Example:\\n\\n    ```mlir\\n    %res = sparse_tensor.reorder_coo quick_sort %coo : tensor<?x?xf64 : #Unordered_COO> to\\n                                                       tensor<?x?xf64 : #Ordered_COO>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input_coo\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_coo\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"algorithm\", \"type\": \"SparseTensorSortKindAttr{hybrid_quick_sort|insertion_sort_stable|quick_sort|heap_sort}\" }\n    ],\n    \"assemblyFormat\": \"$algorithm $input_coo attr-dict`:` type($input_coo) `to` type($result_coo)\"\n  },\n  {\n    \"name\": \"sparse_tensor.select\",\n    \"summary\": \"Select operation utilized within linalg.generic\",\n    \"description\": \"Defines an evaluation within a `linalg.generic` operation that takes a single\\n      operand and decides whether or not to keep that operand in the output.\\n\\n      A single region must contain exactly one block taking one argument. The block\\n      must end with a sparse_tensor.yield and the output type must be boolean.\\n\\n      Value threshold is an obvious usage of the select operation. However, by using\\n      `linalg.index`, other useful selection can be achieved, such as selecting the\\n      upper triangle of a matrix.\\n\\n      Example of selecting A >= 4.0:\\n\\n      ```mlir\\n      %C = tensor.empty(...)\\n      %0 = linalg.generic #trait\\n         ins(%A: tensor<?xf64, #SparseVector>)\\n        outs(%C: tensor<?xf64, #SparseVector>) {\\n        ^bb0(%a: f64, %c: f64) :\\n          %result = sparse_tensor.select %a : f64 {\\n              ^bb0(%arg0: f64):\\n                %cf4 = arith.constant 4.0 : f64\\n                %keep = arith.cmpf \\\"uge\\\", %arg0, %cf4 : f64\\n                sparse_tensor.yield %keep : i1\\n            }\\n          linalg.yield %result : f64\\n      } -> tensor<?xf64, #SparseVector>\\n      ```\\n\\n      Example of selecting lower triangle of a matrix:\\n\\n      ```mlir\\n      %C = tensor.empty(...)\\n      %1 = linalg.generic #trait\\n         ins(%A: tensor<?x?xf64, #CSR>)\\n        outs(%C: tensor<?x?xf64, #CSR>) {\\n        ^bb0(%a: f64, %c: f64) :\\n          %row = linalg.index 0 : index\\n          %col = linalg.index 1 : index\\n          %result = sparse_tensor.select %a : f64 {\\n              ^bb0(%arg0: f64):\\n                %keep = arith.cmpf \\\"olt\\\", %col, %row : f64\\n                sparse_tensor.yield %keep : i1\\n            }\\n          linalg.yield %result : f64\\n      } -> tensor<?x?xf64, #CSR>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$x attr-dict `:` type($x) $region\"\n  },\n  {\n    \"name\": \"sparse_tensor.slice.offset\",\n    \"summary\": \"Extracts the offset of the sparse tensor slice at the given dimension\",\n    \"description\": \"Extracts the offset of the sparse tensor slice at the given dimension.\\n\\n    Currently, sparse tensor slices are still a work in progress, and only\\n    works when runtime library is disabled (i.e., running the sparsifier\\n    with `enable-runtime-library=false`).\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = tensor.extract_slice %s[%v1, %v2][64, 64][1, 1] : tensor<128x128xf64, #DCSR>\\n                                                        to tensor<64x64xf64, #Slice>\\n\\n    %1 = sparse_tensor.slice.offset %0 at 0 : tensor<64x64xf64, #Slice>\\n    %2 = sparse_tensor.slice.offset %0 at 1 : tensor<64x64xf64, #Slice>\\n    // %1 = %v1\\n    // %2 = %v2\\n    ```\",\n    \"operands\": [\n      { \"name\": \"slice\", \"type\": \"AnySparseTensorSlice\" }\n    ],\n    \"results\": [\n      { \"name\": \"offset\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$slice `at` $dim attr-dict `:` type($slice)\"\n  },\n  {\n    \"name\": \"sparse_tensor.slice.stride\",\n    \"summary\": \"Extracts the stride of the sparse tensor slice at the given dimension\",\n    \"description\": \"Extracts the stride of the sparse tensor slice at the given dimension.\\n\\n    Currently, sparse tensor slices are still a work in progress, and only\\n    works when runtime library is disabled (i.e., running the sparsifier\\n    with `enable-runtime-library=false`).\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = tensor.extract_slice %s[%v1, %v2][64, 64][%s1, %s2] : tensor<128x128xf64, #DCSR>\\n                                                            to tensor<64x64xf64, #Slice>\\n\\n    %1 = sparse_tensor.slice.stride %0 at 0 : tensor<64x64xf64, #Slice>\\n    %2 = sparse_tensor.slice.stride %0 at 1 : tensor<64x64xf64, #Slice>\\n    // %1 = %s1\\n    // %2 = %s2\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"slice\", \"type\": \"AnySparseTensorSlice\" }\n    ],\n    \"results\": [\n      { \"name\": \"stride\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$slice `at` $dim attr-dict `:` type($slice)\"\n  },\n  {\n    \"name\": \"sparse_tensor.sort\",\n    \"summary\": \"Sorts the arrays in xs and ys lexicographically on the integral values found in the xs list\",\n    \"description\": \"Sorts the `xs` values along with some `ys` values that are put in a single linear\\n    buffer `xy`.  The affine map attribute `perm_map` specifies the permutation to be\\n    applied on the `xs` before comparison, the rank of the permutation map\\n    also specifies the number of `xs` values in `xy`.\\n    The optional index attribute `ny` provides the number of `ys` values in `xy`.\\n    When `ny` is not explicitly specified, its value is 0.\\n    This instruction supports a more efficient way to store the COO definition\\n    in sparse tensor type.\\n\\n    The buffer xy should have a dimension not less than n * (rank(perm_map) + ny) while the\\n    buffers in `ys` should have a dimension not less than `n`. The behavior of\\n    the operator is undefined if this condition is not met.\\n\\n    Example:\\n\\n    ```mlir\\n    sparse_tensor.sort insertion_sort_stable %n, %x { perm_map = affine_map<(i,j) -> (j,i)> }\\n      : memref<?xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"n\", \"type\": \"Index\" },\n      { \"name\": \"xy\", \"type\": \"StridedMemRefRankOf<[AnyInteger, Index], [1]>\" },\n      { \"name\": \"ys\", \"type\": \"Variadic<StridedMemRefRankOf<[ AnyType ], [ 1 ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"perm_map\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"ny\", \"type\": \"OptionalAttr<IndexAttr>\" },\n      { \"name\": \"algorithm\", \"type\": \"SparseTensorSortKindAttr{hybrid_quick_sort|insertion_sort_stable|quick_sort|heap_sort}\" }\n    ],\n    \"assemblyFormat\": \"$algorithm $n`,`$xy (`jointly` $ys^)? attr-dict`:` type($xy) (`jointly` type($ys)^)?\"\n  },\n  {\n    \"name\": \"sparse_tensor.storage_specifier.get\",\n    \"description\": \"Returns the requested field of the given storage_specifier.\\n\\n    Example of querying the size of the coordinates array for level 0:\\n\\n    ```mlir\\n    %0 = sparse_tensor.storage_specifier.get %arg0 crd_mem_sz at 0\\n         : !sparse_tensor.storage_specifier<#COO>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"specifier\", \"type\": \"SparseTensorStorageSpecifier\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"specifierKind\", \"type\": \"SparseTensorStorageSpecifierKindAttr{lvl_sz|pos_mem_sz|crd_mem_sz|val_mem_sz|dim_offset|dim_stride}\" },\n      { \"name\": \"level\", \"type\": \"OptionalAttr<LevelAttr>\" }\n    ],\n    \"assemblyFormat\": \"$specifier $specifierKind (`at` $level^)? attr-dict`:` qualified(type($specifier))\"\n  },\n  {\n    \"name\": \"sparse_tensor.storage_specifier.init\",\n    \"description\": \"Returns an initial storage specifier value.  A storage specifier\\n    value holds the level-sizes, position arrays, coordinate arrays,\\n    and the value array.\\n    If this is a specifier for slices, it also holds the extra strides/offsets\\n    for each tensor dimension.\\n\\n    TODO: The sparse tensor slice support is currently in a unstable state, and\\n    is subject to change in the future.\\n\\n    Example:\\n\\n    ```mlir\\n    #CSR = #sparse_tensor.encoding<{\\n      map = (i, j) -> (i : dense, j : compressed)\\n    }>\\n    #CSR_SLICE = #sparse_tensor.encoding<{\\n      map = (d0 : #sparse_tensor<slice(1, 4, 1)>,\\n             d1 : #sparse_tensor<slice(1, 4, 2)>) ->\\n            (d0 : dense, d1 : compressed)\\n    }>\\n\\n    %0 = sparse_tensor.storage_specifier.init :  !sparse_tensor.storage_specifier<#CSR>\\n    %1 = sparse_tensor.storage_specifier.init with %src\\n         : !sparse_tensor.storage_specifier<#CSR> to\\n           !sparse_tensor.storage_specifier<#CSR_SLICE>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Optional<SparseTensorStorageSpecifier>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SparseTensorStorageSpecifier\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`with` $source^)? `:` (`from` qualified(type($source))^ `to`)? qualified(type($result))\"\n  },\n  {\n    \"name\": \"sparse_tensor.storage_specifier.set\",\n    \"description\": \"Set the field of the storage specifier to the given input value. Returns\\n    the updated storage_specifier as a new SSA value.\\n\\n    Example of updating the sizes of the coordinates array for level 0:\\n\\n    ```mlir\\n    %0 = sparse_tensor.storage_specifier.set %arg0 crd_mem_sz at 0 with %new_sz\\n       : !sparse_tensor.storage_specifier<#COO>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"specifier\", \"type\": \"SparseTensorStorageSpecifier\" },\n      { \"name\": \"value\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SparseTensorStorageSpecifier\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"specifierKind\", \"type\": \"SparseTensorStorageSpecifierKindAttr{lvl_sz|pos_mem_sz|crd_mem_sz|val_mem_sz|dim_offset|dim_stride}\" },\n      { \"name\": \"level\", \"type\": \"OptionalAttr<LevelAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['result', 'specifier']>\" }\n    ],\n    \"assemblyFormat\": \"$specifier $specifierKind (`at` $level^)? `with` $value attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"sparse_tensor.unary\",\n    \"summary\": \"Unary set operation utilized within linalg.generic\",\n    \"description\": \"Defines a computation with a `linalg.generic` operation that takes a single\\n      operand and executes one of two regions depending on whether the operand is\\n      nonzero (i.e. stored explicitly in the sparse storage format).\\n\\n      Two regions are defined for the operation must appear in this order:\\n      - present (elements present in the sparse tensor)\\n      - absent (elements not present in the sparse tensor)\\n\\n      Each region contains a single block describing the computation and result.\\n      A non-empty block must end with a sparse_tensor.yield and the return type\\n      must match the type of `output`. The primary region's block has one\\n      argument, while the missing region's block has zero arguments. The\\n      absent region may only generate constants or values already computed\\n      on entry of the `linalg.generic` operation.\\n\\n      A region may also be declared empty (i.e. `absent={}`), indicating that the\\n      region does not contribute to the output.\\n\\n      Due to the possibility of empty regions, i.e. lack of a value for certain\\n      cases, the result of this operation may only feed directly into the output\\n      of the `linalg.generic` operation or into into a custom reduction\\n      `sparse_tensor.reduce` operation that follows in the same region.\\n\\n      Example of A+1, restricted to existing elements:\\n\\n      ```mlir\\n      %C = tensor.empty(...) : tensor<?xf64, #SparseVector>\\n      %0 = linalg.generic #trait\\n         ins(%A: tensor<?xf64, #SparseVector>)\\n        outs(%C: tensor<?xf64, #SparseVector>) {\\n        ^bb0(%a: f64, %c: f64) :\\n          %result = sparse_tensor.unary %a : f64 to f64\\n            present={\\n            ^bb0(%arg0: f64):\\n              %cf1 = arith.constant 1.0 : f64\\n              %ret = arith.addf %arg0, %cf1 : f64\\n              sparse_tensor.yield %ret : f64\\n            }\\n            absent={}\\n          linalg.yield %result : f64\\n      } -> tensor<?xf64, #SparseVector>\\n      ```\\n\\n      Example returning +1 for existing values and -1 for missing values:\\n\\n      ```mlir\\n      %p1 = arith.constant  1 : i32\\n      %m1 = arith.constant -1 : i32\\n      %C = tensor.empty(...) : tensor<?xi32, #SparseVector>\\n      %1 = linalg.generic #trait\\n         ins(%A: tensor<?xf64, #SparseVector>)\\n        outs(%C: tensor<?xi32, #SparseVector>) {\\n        ^bb0(%a: f64, %c: i32) :\\n          %result = sparse_tensor.unary %a : f64 to i32\\n            present={\\n            ^bb0(%x: f64):\\n              sparse_tensor.yield %p1 : i32\\n            }\\n            absent={\\n              sparse_tensor.yield %m1 : i32\\n            }\\n          linalg.yield %result : i32\\n      } -> tensor<?xi32, #SparseVector>\\n      ```\\n\\n      Example showing a structural inversion (existing values become missing in\\n      the output, while missing values are filled with 1):\\n\\n      ```mlir\\n      %c1 = arith.constant 1 : i64\\n      %C = tensor.empty(...) : tensor<?xi64, #SparseVector>\\n      %2 = linalg.generic #trait\\n         ins(%A: tensor<?xf64, #SparseVector>)\\n        outs(%C: tensor<?xi64, #SparseVector>) {\\n        ^bb0(%a: f64, %c: i64) :\\n          %result = sparse_tensor.unary %a : f64 to i64\\n            present={}\\n            absent={\\n              sparse_tensor.yield %c1 : i64\\n            }\\n          linalg.yield %result : i64\\n      } -> tensor<?xi64, #SparseVector>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"presentRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"absentRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$x attr-dict `:` type($x) `to` type($output) `\\\\n`\\n        `present` `=` $presentRegion `\\\\n`\\n        `absent` `=` $absentRegion\"\n  },\n  {\n    \"name\": \"sparse_tensor.values\",\n    \"summary\": \"Extracts numerical values array from a tensor\",\n    \"description\": \"Returns the values array of the sparse storage format for the given\\n    sparse tensor, independent of the actual dimension. This is similar to\\n    the `bufferization.to_buffer` operation in the sense that it provides a bridge\\n    between a tensor world view and a bufferized world view. Unlike the\\n    `bufferization.to_buffer` operation, however, this sparse operation actually\\n    lowers into code that extracts the values array from the sparse storage\\n    scheme (either by calling a support library or through direct code).\\n\\n    Writing into the result of this operation is undefined behavior.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = sparse_tensor.values %0 : tensor<64x64xf64, #CSR> to memref<?xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnySparseTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor) `to` type($result)\"\n  },\n  {\n    \"name\": \"sparse_tensor.yield\",\n    \"summary\": \"Yield from sparse_tensor set-like operations\",\n    \"description\": \"Yields a value from within a `binary`, `unary`, `reduce`,\\n      `select` or `foreach` block.\\n\\n      Example:\\n\\n      ```mlir\\n      %0 = sparse_tensor.unary %a : i64 to i64 {\\n        present={\\n          ^bb0(%arg0: i64):\\n            %cst = arith.constant 1 : i64\\n            %ret = arith.addi %arg0, %cst : i64\\n            sparse_tensor.yield %ret : i64\\n        }\\n      }\\n      ```\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$results attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"spirv.AccessChain\",\n    \"summary\": \"Create a pointer into a composite object.\",\n    \"description\": \"Result Type must be an OpTypePointer. Its Type operand must be the type\\n    reached by walking the Base’s type hierarchy down to the last provided\\n    index in Indexes, and its Storage Class operand must be the same as the\\n    Storage Class of Base.\\n\\n    Base must be a pointer, pointing to the base of a composite object.\\n\\n    Indexes walk the type hierarchy to the desired depth, potentially down\\n    to scalar granularity. The first index in Indexes will select the top-\\n    level member/element/component/element of the base composite. All\\n    composite constituents use zero-based numbering, as described by their\\n    OpType… instruction. The second index will apply similarly to that\\n    result, and so on. Once any non-composite type is reached, there must be\\n    no remaining (unused) indexes.\\n\\n     Each index in Indexes\\n\\n    - must be a scalar integer type,\\n\\n    - is treated as a signed count, and\\n\\n    - must be an OpConstant when indexing into a structure.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = \\\"spirv.Constant\\\"() { value = 1: i32} : () -> i32\\n    %1 = spirv.Variable : !spirv.ptr<!spirv.struct<f32, !spirv.array<4xf32>>, Function>\\n    %2 = spirv.AccessChain %1[%0] : !spirv.ptr<!spirv.struct<f32, !spirv.array<4xf32>>, Function> -> !spirv.ptr<!spirv.array<4xf32>, Function>\\n    %3 = spirv.Load \\\"Function\\\" %2 [\\\"Volatile\\\"] : !spirv.array<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base_ptr\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"component_ptr\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$base_ptr `[` $indices `]` attr-dict `:` type($base_ptr) `,` type($indices) `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.ARM.Graph\",\n    \"summary\": \"Declare or define a SPIR-V graph\",\n    \"description\": \"This op declares or defines a SPIR-V graph using one region, which\\n    contains one or more blocks.\\n\\n    This op is not allowed to implicitly capture global values, and all external\\n    references must use function arguments or symbol references. This op itself\\n    defines a symbol that is unique in the enclosing module op.\\n\\n    Note that this op does not have a 1:1 mapping to the SPIR-V ops representing\\n    a graph. Indeed during serialization a single GraphARMOp is serialized into\\n    several different SPIR-V ops: OpGraphARM, OpGraphInputARM and OpGraphEndARM.\\n    There are as many occurences of OpGraphInputARM ops as many inputs in the\\n    graph. Deserialization maps that set of operations into a single GraphARMOp.\\n\\n    This op itself takes no operands and generates no results. Its region\\n    can take zero or more arguments and return one or more values.\\n\\n    ```\\n    spv-graph-arm-op ::= `spirv.ARM.Graph` function-signature\\n                        region\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ARM.Graph @graph(%arg0: !spirv.arm.tensor<14x19xi16>) -> !spirv.arm.tensor<14x19xi16> {\\n        spirv.ARM.GraphOutputs %arg0 : !spirv.arm.tensor<14x19xi16>\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<GraphType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"entry_point\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ARM.GraphConstant\",\n    \"summary\": \"Declare a graph constant.\",\n    \"description\": \"Declare a graph constant.\\n    Result Type must be an OpTypeTensorARM.\\n    GraphConstantID must be a 32-bit integer literal.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.ARM.GraphConstant { graph_constant_id = 42 : i32 } : !spirv.arm.tensor<2x3xi16>\\n    ```\\n\\n    GraphConstantID is a unique identifier which is use to map the contants\\n    defined by GraphConstantARM in the SPIRV module with the one provided at\\n    shader creation time via the VkDataGraphPipelineShaderModuleCreateInfoARM.\\n    That Vulkan structure provides a list of VkDataGraphPipelineConstantARM\\n    which contains the bindings from id to data. (For more details see\\n    https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#graphs)\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_AnyTensorArm\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"graph_constant_id\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($output)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ARM.GraphEntryPoint\",\n    \"summary\": \"Declare a graph entry point and its interface.\",\n    \"description\": \"Graph Entry Point must be the Result `<id>` of an OpGraphARM instruction.\\n\\n    Name is a name string for the graphentry point. A module cannot have two\\n    OpGraphEntryPointARM instructions with the same Name string.\\n\\n    Interface is a list of symbol references to `spirv.GlobalVariable`\\n    operations. These declare the set of global variables from a\\n    module that form the interface of this entry point. The set of\\n    Interface symbols must be equal to or a superset of the\\n    `spirv.GlobalVariable`s referenced by the entry point’s static call\\n    tree, within the interface’s storage classes.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.GlobalVariable @arg_0 bind(0, 0) : !spirv.ptr<!spirv.arm.tensor<14x19xi16>, UniformConstant>\\n    spirv.GlobalVariable @res_0 bind(0, 1) : !spirv.ptr<!spirv.arm.tensor<14x19xi16>, UniformConstant>\\n    spirv.ARM.GraphEntryPoint @graph, @arg_0, @res_0\\n    spirv.ARM.Graph @graph(%arg0 : !spirv.arm.tensor<14x19xi16>) -> !spirv.arm.tensor<14x19xi16> {\\n        ...\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"interface\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ARM.GraphOutputs\",\n    \"summary\": \"Define graph outputs.\",\n    \"description\": \"Values are the graph outputs values and must match the GraphOutputs Type\\n    operand of the OpTypeGraphARM type of the OpGraphARM body this\\n    instruction is in.\\n\\n    This instruction must be the last instruction in a block.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ARM.Graph @graph(%arg0 : !spirv.arm.tensor<14x19xi16>) -> !spirv.arm.tensor<14x19xi16> {\\n        spirv.ARM.GraphOutputs %arg0 : !spirv.arm.tensor<14x19xi16>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Variadic<SPIRV_AnyTensorArm>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.AtomicAnd\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by the bitwise AND of Original Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicAnd <Device> <None> %pointer, %value :\\n                       !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicCompareExchange\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value from Value only if Original Value equals Comparator,\\n    and\\n\\n    3) store the New Value back through Pointer'only if 'Original Value\\n    equaled Comparator.\\n\\n    The instruction's result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n    Use Equal for the memory semantics of this instruction when Value and\\n    Original Value compare equal.\\n\\n    Use Unequal for the memory semantics of this instruction when Value and\\n    Original Value compare unequal. Unequal must not be set to Release or\\n    Acquire and Release. In addition, Unequal cannot be set to a stronger\\n    memory-order then Equal.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.  This type\\n    must also match the type of Comparator.\\n\\n    Memory is a memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```\\n    %0 = spirv.AtomicCompareExchange <Workgroup> <Acquire> <None>\\n                                    %pointer, %value, %comparator\\n                                    : !spirv.ptr<i32, WorkGroup>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"comparator\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"equal_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" },\n      { \"name\": \"unequal_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'comparator', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $equal_semantics $unequal_semantics operands attr-dict `:`\\n      type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicCompareExchangeWeak\",\n    \"summary\": \"Deprecated (use OpAtomicCompareExchange).\",\n    \"description\": \"Has the same semantics as OpAtomicCompareExchange.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicCompareExchangeWeak <Workgroup> <Acquire> <None>\\n                                       %pointer, %value, %comparator\\n                                       : !spirv.ptr<i32, WorkGroup>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"comparator\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"equal_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" },\n      { \"name\": \"unequal_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'comparator', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $equal_semantics $unequal_semantics operands attr-dict `:`\\n      type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicExchange\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value from copying Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction's result is the Original Value.\\n\\n    Result Type must be a scalar of integer type or floating-point type.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory is a memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicExchange <Workgroup> <Acquire> %pointer, %value,\\n                            : !spirv.ptr<i32, WorkGroup>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Numerical\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Numerical\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicIAdd\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by integer addition of Original Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicIAdd <Device> <None> %pointer, %value :\\n                        !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicIDecrement\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value through integer subtraction of 1 from Original Value,\\n    and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.  The type of the value\\n    pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicIDecrement <Device> <None> %pointer :\\n                              !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicIIncrement\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value through integer addition of 1 to Original Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.  The type of the value\\n    pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicIIncrement <Device> <None> %pointer :\\n                               !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicISub\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by integer subtraction of Value from Original Value,\\n    and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicISub <Device> <None> %pointer, %value :\\n                        !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicOr\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by the bitwise OR of Original Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicOr <Device> <None> %pointer, %value :\\n                      !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicSMax\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by finding the largest signed integer of Original\\n    Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicSMax <Device> <None> %pointer, %value :\\n                        !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicSMin\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by finding the smallest signed integer of Original\\n    Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicSMin <Device> <None> %pointer, %value :\\n                        !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicUMax\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by finding the largest unsigned integer of Original\\n    Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicUMax <Device> <None> %pointer, %value :\\n                        !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicUMin\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by finding the smallest unsigned integer of Original\\n    Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicUMin <Device> <None> %pointer, %value :\\n                        !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.AtomicXor\",\n    \"summary\": \"Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\",\n    \"description\": \"1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by the bitwise exclusive OR of Original Value and\\n    Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction’s result is the Original Value.\\n\\n    Result Type must be an integer type scalar.\\n\\n     The type of Value must be the same as Result Type.  The type of the\\n    value pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.AtomicXor <Device> <None> %pointer, %value :\\n                       !spirv.ptr<i32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\"\n  },\n  {\n    \"name\": \"spirv.Bitcast\",\n    \"summary\": \"Bit pattern-preserving type conversion.\",\n    \"description\": \"Result Type must be an OpTypePointer, or a scalar or vector of\\n    numerical-type.\\n\\n    Operand must have a type of OpTypePointer, or a scalar or vector of\\n    numerical-type. It must be a different type than Result Type.\\n\\n    If either Result Type or Operand is a pointer, the other must be a\\n    pointer (diverges from the SPIR-V spec).\\n\\n    If Result Type has a different number of components than Operand, the\\n    total number of bits in Result Type must equal the total number of bits\\n    in Operand. Let L be the type, either Result Type or Operand's type,\\n    that has the larger number of components. Let S be the other type, with\\n    the smaller number of components. The number of components in L must be\\n    an integer multiple of the number of components in S. The first\\n    component (that is, the only or lowest-numbered component) of S maps to\\n    the first components of L, and so on,  up to the last component of S\\n    mapping to the last components of L. Within this mapping, any single\\n    component of S (mapping to multiple components of L) maps its lower-\\n    ordered bits to the lower-numbered components of L.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.Bitcast %0 : f32 to i32\\n    %1 = spirv.Bitcast %0 : vector<2xf32> to i64\\n    %1 = spirv.Bitcast %0 : !spirv.ptr<f32, Function> to !spirv.ptr<i32, Function>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrPtr\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitCount\",\n    \"summary\": \"Count the number of set bits in an object.\",\n    \"description\": \"Results are computed per component.\\n\\n    Result Type must be a scalar or vector of integer type.  The components\\n    must be wide enough to hold the unsigned Width of Base as an unsigned\\n    value. That is, no sign bit is needed or counted when checking for a\\n    wide enough result width.\\n\\n    Base must be a scalar or vector of integer type.  It must have the same\\n    number of components as Result Type.\\n\\n    The result is the unsigned value that is the number of bits in Base that\\n    are 1.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.BitCount %0: i32\\n    %3 = spirv.BitCount %1: vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitFieldInsert\",\n    \"summary\": \"Make a copy of an object, with a modified bit field that comes from\\n    another object.\",\n    \"description\": \"Results are computed per component.\\n\\n    Result Type must be a scalar or vector of integer type.\\n\\n    The type of Base and Insert must be the same as Result Type.\\n\\n    Any result bits numbered outside [Offset, Offset + Count -  1]\\n    (inclusive) will come from the corresponding bits in Base.\\n\\n    Any result bits numbered in [Offset, Offset + Count -  1] come, in\\n    order, from the bits numbered [0, Count - 1] of Insert.\\n\\n    Count  must be an integer type scalar. Count is the number of bits taken\\n    from Insert. It will be consumed as an unsigned value. Count can be 0,\\n    in which case the result will be Base.\\n\\n    Offset  must be an integer type scalar. Offset is the lowest-order bit\\n    of the bit field.  It will be consumed as an unsigned value.\\n\\n    The resulting value is undefined if Count or Offset or their sum is\\n    greater than the number of bits in the result.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.BitFieldInsert %base, %insert, %offset, %count : vector<3xi32>, i8, i8\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"insert\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"offset\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"count\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['base', 'insert', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($base) `,` type($offset) `,` type($count)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitFieldSExtract\",\n    \"summary\": \"Extract a bit field from an object, with sign extension.\",\n    \"description\": \"Results are computed per component.\\n\\n    Result Type must be a scalar or vector of integer type.\\n\\n    The type of Base must be the same as Result Type.\\n\\n    If Count is greater than 0: The bits of Base numbered in [Offset, Offset\\n    + Count -  1] (inclusive) become the bits numbered [0, Count - 1] of the\\n    result. The remaining bits of the result will all be the same as bit\\n    Offset + Count -  1 of Base.\\n\\n    Count  must be an integer type scalar. Count is the number of bits\\n    extracted from Base. It will be consumed as an unsigned value. Count can\\n    be 0, in which case the result will be 0.\\n\\n    Offset  must be an integer type scalar. Offset is the lowest-order bit\\n    of the bit field to extract from Base.  It will be consumed as an\\n    unsigned value.\\n\\n    The resulting value is undefined if Count or Offset or their sum is\\n    greater than the number of bits in the result.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.BitFieldSExtract %base, %offset, %count : vector<3xi32>, i8, i8\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"offset\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"count\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['base', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($base) `,` type($offset) `,` type($count)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitFieldUExtract\",\n    \"summary\": \"Extract a bit field from an object, without sign extension.\",\n    \"description\": \"The semantics are the same as with OpBitFieldSExtract with the exception\\n    that there is no sign extension. The remaining bits of the result will\\n    all be 0.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.BitFieldUExtract %base, %offset, %count : vector<3xi32>, i8, i8\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"offset\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"count\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['base', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($base) `,` type($offset) `,` type($count)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitReverse\",\n    \"summary\": \"Reverse the bits in an object.\",\n    \"description\": \"Results are computed per component.\\n\\n    Result Type must be a scalar or vector of integer type.\\n\\n    The type of Base must be the same as Result Type.\\n\\n    The bit-number n of the result will be taken from bit-number Width - 1 -\\n    n of Base, where Width is the OpTypeInt operand of the Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.BitReverse %0 : i32\\n    %3 = spirv.BitReverse %1 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitwiseAnd\",\n    \"summary\": \"Result is 1 if both Operand 1 and Operand 2 are 1. Result is 0 if either\\n    Operand 1 or Operand 2 are 0.\",\n    \"description\": \"Results are computed per component, and within each component, per bit.\\n\\n    Result Type must be a scalar or vector of integer type.  The type of\\n    Operand 1 and Operand 2  must be a scalar or vector of integer type.\\n    They must have the same number of components as Result Type. They must\\n    have the same component width as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.BitwiseAnd %0, %1 : i32\\n    %2 = spirv.BitwiseAnd %0, %1 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitwiseOr\",\n    \"summary\": \"Result is 1 if either Operand 1 or Operand 2 is 1. Result is 0 if both\\n    Operand 1 and Operand 2 are 0.\",\n    \"description\": \"Results are computed per component, and within each component, per bit.\\n\\n    Result Type must be a scalar or vector of integer type.  The type of\\n    Operand 1 and Operand 2  must be a scalar or vector of integer type.\\n    They must have the same number of components as Result Type. They must\\n    have the same component width as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.BitwiseOr %0, %1 : i32\\n    %2 = spirv.BitwiseOr %0, %1 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BitwiseXor\",\n    \"summary\": \"Result is 1 if exactly one of Operand 1 or Operand 2 is 1. Result is 0\\n    if Operand 1 and Operand 2 have the same value.\",\n    \"description\": \"Results are computed per component, and within each component, per bit.\\n\\n    Result Type must be a scalar or vector of integer type.  The type of\\n    Operand 1 and Operand 2  must be a scalar or vector of integer type.\\n    They must have the same number of components as Result Type. They must\\n    have the same component width as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.BitwiseXor %0, %1 : i32\\n    %2 = spirv.BitwiseXor %0, %1 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Branch\",\n    \"summary\": \"Unconditional branch to target block.\",\n    \"description\": \"This instruction must be the last instruction in a block.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.Branch ^target\\n    spirv.Branch ^target(%0, %1: i32, f32)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"targetOperands\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"target\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$target (`(` $targetOperands^ `:` type($targetOperands) `)`)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.BranchConditional\",\n    \"summary\": \"If Condition is true, branch to true block, otherwise branch to false\\n    block.\",\n    \"description\": \"Condition must be a Boolean type scalar.\\n\\n    Branch weights are unsigned 32-bit integer literals. There must be\\n    either no Branch Weights or exactly two branch weights. If present, the\\n    first is the weight for branching to True Label, and the second is the\\n    weight for branching to False Label. The implied probability that a\\n    branch is taken is its weight divided by the sum of the two Branch\\n    weights. At least one weight must be non-zero. A weight of zero does not\\n    imply a branch is dead or permit its removal; branch weights are only\\n    hints. The two weights must not overflow a 32-bit unsigned integer when\\n    added together.\\n\\n    This instruction must be the last instruction in a block.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    branch-conditional-op ::= `spirv.BranchConditional` ssa-use\\n                              (`[` integer-literal, integer-literal `]`)?\\n                              `,` successor `,` successor\\n    successor ::= bb-id branch-use-list?\\n    branch-use-list ::= `(` ssa-use-list `:` type-list-no-parens `)`\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.BranchConditional %condition, ^true_branch, ^false_branch\\n    spirv.BranchConditional %condition, ^true_branch(%0: i32), ^false_branch(%1: i32)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"SPIRV_Bool\" },\n      { \"name\": \"trueTargetOperands\", \"type\": \"Variadic<SPIRV_Type>\" },\n      { \"name\": \"falseTargetOperands\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branch_weights\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueTarget\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseTarget\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.acos\",\n    \"summary\": \"Compute the arc cosine of x.\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.acos %0 : f32\\n    %3 = spirv.CL.acos %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.acosh\",\n    \"summary\": \"Compute the inverse hyperbolic cosine of x .\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.acosh %0 : f32\\n    %3 = spirv.CL.acosh %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.asin\",\n    \"summary\": \"Compute the arc sine of x.\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.asin %0 : f32\\n    %3 = spirv.CL.asin %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.asinh\",\n    \"summary\": \"Compute the inverse hyperbolic sine of x.\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.asinh %0 : f32\\n    %3 = spirv.CL.asinh %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.atan\",\n    \"summary\": \"Compute the arc tangent of x.\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.atan %0 : f32\\n    %3 = spirv.CL.atan %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.atan2\",\n    \"summary\": \"Compute the arc tangent of y / x.\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type, y and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.atan2 %0, %1 : f32\\n    %3 = spirv.CL.atan2 %0, %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.atanh\",\n    \"summary\": \"Compute the hyperbolic arc tangent of x.\",\n    \"description\": \"Result is an angle in radians.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.atanh %0 : f32\\n    %3 = spirv.CL.atanh %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.ceil\",\n    \"summary\": \"Round x to integral value using the round to positive infinity rounding\\n    mode.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.ceil %0 : f32\\n    %3 = spirv.CL.ceil %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.cos\",\n    \"summary\": \"Compute the cosine of x radians.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.cos %0 : f32\\n    %3 = spirv.CL.cos %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.cosh\",\n    \"summary\": \"Compute the hyperbolic cosine of x radians.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.cosh %0 : f32\\n    %3 = spirv.CL.cosh %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.erf\",\n    \"summary\": \"Error function of x encountered in integrating the normal distribution.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.erf %0 : f32\\n    %3 = spirv.CL.erf %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.exp\",\n    \"summary\": \"Exponentiation of Operand 1\",\n    \"description\": \"Compute the base-e exponential of x. (i.e. ex)\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand,\\n    must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.exp %0 : f32\\n    %3 = spirv.CL.exp %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.fabs\",\n    \"summary\": \"Absolute value of operand\",\n    \"description\": \"Compute the absolute value of x.\\n\\n    Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand,\\n    must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.fabs %0 : f32\\n    %3 = spirv.CL.fabs %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.floor\",\n    \"summary\": \"Round x to the integral value using the round to negative infinity\\n    rounding mode.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.floor %0 : f32\\n    %3 = spirv.CL.floor %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.fma\",\n    \"summary\": \"Compute the correctly rounded floating-point representation of the sum\\n    of c with the infinitely precise product of a and b. Rounding of\\n    intermediate products shall not occur. Edge case results are per the\\n    IEEE 754-2008 standard.\",\n    \"description\": \"Result Type, a, b and c must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.CL.fma %a, %b, %c : f32\\n    %1 = spirv.CL.fma %a, %b, %c : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"z\", \"type\": \"SPIRV_ScalarOrVectorOf<operandType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.fmax\",\n    \"summary\": \"Return maximum of two floating-point operands\",\n    \"description\": \"Returns y if x < y, otherwise it returns x. If one argument is a NaN,\\n    Fmax returns the other argument. If both arguments are NaNs, Fmax returns a NaN.\\n\\n    Result Type, x and y must be floating-point or vector(2,3,4,8,16)\\n    of floating-point values.\\n\\n    All of the operands, including the Result Type operand,\\n    must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.fmax %0, %1 : f32\\n    %3 = spirv.CL.fmax %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.fmin\",\n    \"summary\": \"Return minimum of two floating-point operands\",\n    \"description\": \"Returns y if y < x, otherwise it returns x. If one argument is a NaN, Fmin returns the other argument.\\n    If both arguments are NaNs, Fmin returns a NaN.\\n\\n    Result Type,x and y must be floating-point or vector(2,3,4,8,16) of floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.fmin %0, %1 : f32\\n    %3 = spirv.CL.fmin %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.log\",\n    \"summary\": \"Compute the natural logarithm of x.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.log %0 : f32\\n    %3 = spirv.CL.log %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.mix\",\n    \"summary\": \"Returns the linear blend of x & y implemented as: x + (y - x) * a\",\n    \"description\": \"Result Type, x, y and a must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    Note: This instruction can be implemented using contractions such as mad\\n    or fma.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.CL.mix %a, %b, %c : f32\\n    %1 = spirv.CL.mix %a, %b, %c : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"z\", \"type\": \"SPIRV_ScalarOrVectorOf<operandType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.pow\",\n    \"summary\": \"Compute x to the power y.\",\n    \"description\": \"Result Type, x and y must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.pow %0, %1 : f32\\n    %3 = spirv.CL.pow %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.printf\",\n    \"summary\": \"The printf extended instruction writes output to an implementation-\\n    defined stream such as stdout under control of the string pointed to by\\n    format that specifies how subsequent arguments are converted for output.\",\n    \"description\": \"printf returns 0 if it was executed successfully and -1 otherwise.\\n\\n    Result Type must be i32.\\n\\n    Format must be a pointer(constant) to i8. If there are insufficient \\n    arguments for the format, the behavior is undefined. If the format \\n    is exhausted while arguments remain, the excess arguments are evaluated\\n    (as always) but are otherwise ignored. The printf instruction returns \\n    when the end of the format string is encountered.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.CL.printf %fmt %1, %2  : !spirv.ptr<i8, UniformConstant>, i32, i32 -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"format\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"assemblyFormat\": \"$format ( $arguments^ )? attr-dict `:`  type($format) ( `,` type($arguments)^ )? `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.rint\",\n    \"summary\": \"Round x to integral value (using round to nearest even rounding mode) in\\n    floating-point format.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.CL.rint %0 : f32\\n    %1 = spirv.CL.rint %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.round\",\n    \"summary\": \"Return the integral value nearest to x rounding halfway cases away from\\n    zero, regardless of the current rounding direction.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.round %0 : f32\\n    %3 = spirv.CL.round %0 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.rsqrt\",\n    \"summary\": \"Compute inverse square root of x.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.rsqrt %0 : f32\\n    %3 = spirv.CL.rsqrt %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.s_abs\",\n    \"summary\": \"Absolute value of operand\",\n    \"description\": \"Returns |x|, where x is treated as signed integer.\\n\\n    Result Type and x must be integer or vector(2,3,4,8,16) of\\n    integer values.\\n\\n    All of the operands, including the Result Type operand,\\n    must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.s_abs %0 : i32\\n    %3 = spirv.CL.s_abs %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.s_max\",\n    \"summary\": \"Return maximum of two signed integer operands\",\n    \"description\": \"Returns y if x < y, otherwise it returns x, where x and y are treated as signed integers.\\n\\n    Result Type,x and y must be integer or vector(2,3,4,8,16) of integer values.\\n\\n    All of the operands, including the Result Type operand, must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.s_max %0, %1 : i32\\n    %3 = spirv.CL.s_max %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.s_min\",\n    \"summary\": \"Return minimum of two signed integer operands\",\n    \"description\": \"Returns y if x < y, otherwise it returns x, where x and y are treated as signed integers.\\n\\n    Result Type,x and y must be integer or vector(2,3,4,8,16) of integer values.\\n\\n    All of the operands, including the Result Type operand, must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.s_min %0, %1 : i32\\n    %3 = spirv.CL.s_min %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.sin\",\n    \"summary\": \"Compute sine of x radians.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.sin %0 : f32\\n    %3 = spirv.CL.sin %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.sinh\",\n    \"summary\": \"Compute hyperbolic sine of x radians.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.sinh %0 : f32\\n    %3 = spirv.CL.sinh %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.sqrt\",\n    \"summary\": \"Compute square root of x.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.sqrt %0 : f32\\n    %3 = spirv.CL.sqrt %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.tan\",\n    \"summary\": \"Compute tangent of x radians.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.tan %0 : f32\\n    %3 = spirv.CL.tan %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.tanh\",\n    \"summary\": \"Compute hyperbolic tangent of x radians.\",\n    \"description\": \"Result Type and x must be floating-point or vector(2,3,4,8,16) of\\n    floating-point values.\\n\\n    All of the operands, including the Result Type operand, must be of the\\n    same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.tanh %0 : f32\\n    %3 = spirv.CL.tanh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.u_max\",\n    \"summary\": \"Return maximum of two unsigned integer operands\",\n    \"description\": \"Returns y if x < y, otherwise it returns x, where x and y are treated as unsigned integers.\\n\\n    Result Type,x and y must be integer or vector(2,3,4,8,16) of integer values.\\n\\n    All of the operands, including the Result Type operand, must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.u_max %0, %1 : i32\\n    %3 = spirv.CL.u_max %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CL.u_min\",\n    \"summary\": \"Return minimum of two unsigned integer operands\",\n    \"description\": \"Returns y if x < y, otherwise it returns x, where x and y are treated as unsigned integers.\\n\\n    Result Type,x and y must be integer or vector(2,3,4,8,16) of integer values.\\n\\n    All of the operands, including the Result Type operand, must be of the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.CL.u_min %0, %1 : i32\\n    %3 = spirv.CL.u_min %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CompositeConstruct\",\n    \"summary\": \"Construct a new composite object from a set of constituent objects.\",\n    \"description\": \"Result Type must be a composite type, whose top-level\\n    members/elements/components/columns have the same type as the types of\\n    the operands, with one exception. The exception is that for constructing\\n    a vector, the operands may also be vectors with the same component type\\n    as the Result Type component type. When constructing a vector, the total\\n    number of components in all the operands must equal the number of\\n    components in Result Type.\\n\\n    Constituents will become members of a structure, or elements of an\\n    array, or components of a vector, or columns of a matrix. There must be\\n    exactly one Constituent for each top-level\\n    member/element/component/column of the result, with one exception. The\\n    exception is that for constructing a vector, a contiguous subset of the\\n    scalars consumed can be represented by a vector operand instead. The\\n    Constituents must appear in the order needed by the definition of the\\n    type of the result. When constructing a vector, there must be at least\\n    two Constituent operands.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %a = spirv.CompositeConstruct %1, %2, %3 : vector<3xf32>\\n    %b = spirv.CompositeConstruct %a, %1 : (vector<3xf32>, f32) -> vector<4xf32>\\n\\n    %c = spirv.CompositeConstruct %1 :\\n      (f32) -> !spirv.coopmatrix<4x4xf32, Subgroup, MatrixA>\\n\\n    %d = spirv.CompositeConstruct %a, %4, %5 :\\n      (vector<3xf32>, !spirv.array<4xf32>, !spirv.struct<(f32)>) ->\\n        !spirv.struct<(vector<3xf32>, !spirv.array<4xf32>, !spirv.struct<(f32)>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"constituents\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Composite\" }\n    ],\n    \"assemblyFormat\": \"$constituents attr-dict `:` `(` type(operands) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CompositeExtract\",\n    \"summary\": \"Extract a part of a composite object.\",\n    \"description\": \"Result Type must be the type of object selected by the last provided\\n    index.  The instruction result is the extracted object.\\n\\n    Composite is the composite to extract from.\\n\\n    Indexes walk the type hierarchy, potentially down to component\\n    granularity, to select the part to extract. All indexes must be in\\n    bounds.  All composite constituents use zero-based numbering, as\\n    described by their OpType… instruction.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    composite-extract-op ::= ssa-id `=` `spirv.CompositeExtract` ssa-use\\n                             `[` integer-literal (',' integer-literal)* `]`\\n                             `:` composite-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>\\n    %1 = spirv.Load \\\"Function\\\" %0 [\\\"Volatile\\\"] : !spirv.array<4x!spirv.array<4xf32>>\\n    %2 = spirv.CompositeExtract %1[1 : i32] : !spirv.array<4x!spirv.array<4xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"composite\", \"type\": \"SPIRV_Composite\" }\n    ],\n    \"results\": [\n      { \"name\": \"component\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CompositeInsert\",\n    \"summary\": \"Make a copy of a composite object, while modifying one part of it.\",\n    \"description\": \"Result Type must be the same type as Composite.\\n\\n    Object is the object to use as the modified part.\\n\\n    Composite is the composite to copy all but the modified part from.\\n\\n    Indexes walk the type hierarchy of Composite to the desired depth,\\n    potentially down to component granularity, to select the part to modify.\\n    All indexes must be in bounds. All composite constituents use zero-based\\n    numbering, as described by their OpType… instruction. The type of the\\n    part selected to modify must match the type of Object.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    composite-insert-op ::= ssa-id `=` `spirv.CompositeInsert` ssa-use, ssa-use\\n                            `[` integer-literal (',' integer-literal)* `]`\\n                            `:` object-type `into` composite-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.CompositeInsert %object, %composite[1 : i32] : f32 into !spirv.array<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"object\", \"type\": \"SPIRV_Type\" },\n      { \"name\": \"composite\", \"type\": \"SPIRV_Composite\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Composite\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Constant\",\n    \"summary\": \"Declare a new integer-type or floating-point-type scalar constant.\",\n    \"description\": \"This op declares a SPIR-V normal constant. SPIR-V has multiple constant\\n    instructions covering different constant types:\\n\\n    * `OpConstantTrue` and `OpConstantFalse` for boolean constants\\n    * `OpConstant` for scalar constants\\n    * `OpConstantComposite` for composite constants\\n    * `OpConstantNull` for null constants\\n    * ...\\n\\n    Having such a plethora of constant instructions renders IR transformations\\n    more tedious. Therefore, we use a single `spirv.Constant` op to represent\\n    them all. Note that conversion between those SPIR-V constant instructions\\n    and this op is purely mechanical; so it can be scoped to the binary\\n    (de)serialization process.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    spirv.Constant-op ::= ssa-id `=` `spirv.Constant` attribute-value\\n                        (`:` spirv-type)?\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Constant true\\n    %1 = spirv.Constant dense<[2.0, 3.0]> : vector<2xf32>\\n    %2 = spirv.Constant [dense<3.0> : vector<2xf32>] : !spirv.array<1xvector<2xf32>>\\n    ```\\n\\n    TODO: support constant structs\",\n    \"results\": [\n      { \"name\": \"constant\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ControlBarrier\",\n    \"summary\": \"Wait for other invocations of this module to reach the current point of\\n    execution.\",\n    \"description\": \"All invocations of this module within Execution scope must reach this\\n    point of execution before any invocation will proceed beyond it.\\n\\n    When Execution is Workgroup or larger, behavior is undefined if this\\n    instruction is used in control flow that is non-uniform within\\n    Execution. When Execution is Subgroup or Invocation, the behavior of\\n    this instruction in non-uniform control flow is defined by the client\\n    API.\\n\\n    If Semantics is not None, this instruction also serves as an\\n    OpMemoryBarrier instruction, and must also perform and adhere to the\\n    description and semantics of an OpMemoryBarrier instruction with the\\n    same Memory and Semantics operands.  This allows atomically specifying\\n    both a control barrier and a memory barrier (that is, without needing\\n    two instructions). If Semantics is None, Memory is ignored.\\n\\n    Before version 1.3, it is only valid to use this instruction with\\n    TessellationControl, GLCompute, or Kernel execution models. There is no\\n    such restriction starting with version 1.3.\\n\\n    When used with the TessellationControl execution model, it also\\n    implicitly synchronizes the Output Storage Class:  Writes to Output\\n    variables performed by any invocation executed prior to a\\n    OpControlBarrier will be visible to any other invocation after return\\n    from that OpControlBarrier.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ControlBarrier <Workgroup>, <Device>, <Acquire|UniformMemory>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope `,` $memory_scope `,` $memory_semantics attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ConvertFToS\",\n    \"summary\": \"Convert value numerically from floating point to signed integer, with\\n    round toward 0.0.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    Float Value must be a scalar or vector of floating-point type.  It must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertFToS %0 : f32 to i32\\n    %3 = spirv.ConvertFToS %2 : vector<3xf32> to vector<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ConvertFToU\",\n    \"summary\": \"Convert value numerically from floating point to unsigned integer, with\\n    round toward 0.0.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type, whose Signedness\\n    operand is 0.\\n\\n    Float Value must be a scalar or vector of floating-point type.  It must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertFToU %0 : f32 to i32\\n    %3 = spirv.ConvertFToU %2 : vector<3xf32> to vector<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ConvertPtrToU\",\n    \"summary\": \"Bit pattern-preserving conversion of a pointer to\\n    an unsigned scalar integer of possibly different bit width.\",\n    \"description\": \"Result Type must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    Pointer must be a physical pointer type. If the bit width of Pointer is\\n    smaller than that of Result Type, the conversion zero extends Pointer.\\n    If the bit width of Pointer is larger than that of Result Type,\\n    the conversion truncates Pointer.\\n\\n    For same bit width Pointer and Result Type, this is the same as OpBitcast.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertPtrToU %0 : !spirv.ptr<i32, Generic> to i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"assemblyFormat\": \"$pointer attr-dict `:` type($pointer) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ConvertSToF\",\n    \"summary\": \"Convert value numerically from signed integer to floating point.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    Signed Value must be a scalar or vector of integer type.  It must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertSToF %0 : i32 to f32\\n    %3 = spirv.ConvertSToF %2 : vector<3xi32> to vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_AnyFloat>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ConvertUToF\",\n    \"summary\": \"Convert value numerically from unsigned integer to floating point.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    Unsigned Value must be a scalar or vector of integer type.  It must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertUToF %0 : i32 to f32\\n    %3 = spirv.ConvertUToF %2 : vector<3xi32> to vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_AnyFloat>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ConvertUToPtr\",\n    \"summary\": \"Bit pattern-preserving conversion of an unsigned scalar integer\\n    to a pointer.\",\n    \"description\": \"Result Type must be a physical pointer type.\\n\\n    Integer Value must be a scalar of integer type, whose Signedness\\n    operand is 0. If the bit width of Integer Value is smaller\\n    than that of Result Type, the conversion zero extends Integer Value.\\n    If the bit width of Integer Value is larger than that of Result Type,\\n    the conversion truncates Integer Value.\\n\\n    For same-width Integer Value and Result Type, this is the same as OpBitcast.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertUToPtr %0 :  i32 to !spirv.ptr<i32, Generic>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.CopyMemory\",\n    \"summary\": \"Copy from the memory pointed to by Source to the memory pointed to by\\n    Target. Both operands must be non-void pointers and having the same `<id>`\\n    Type operand in their OpTypePointer type declaration.  Matching Storage\\n    Class is not required.  The amount of memory copied is the size of the\\n    type pointed to. The copied type must have a fixed size; i.e., it must\\n    not be, nor include, any OpTypeRuntimeArray types.\",\n    \"description\": \"If present, any Memory Operands must begin with a memory operand\\n    literal. If not present, it is the same as specifying the memory operand\\n    None. Before version 1.4, at most one memory operands mask can be\\n    provided. Starting with version 1.4 two masks can be provided, as\\n    described in Memory Operands. If no masks or only one mask is present,\\n    it applies to both Source and Target. If two masks are present, the\\n    first applies to Target and cannot include MakePointerVisible, and the\\n    second applies to Source and cannot include MakePointerAvailable.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    copy-memory-op ::= `spirv.CopyMemory ` storage-class ssa-use\\n                       storage-class ssa-use\\n                       (`[` memory-access `]` (`, [` memory-access `]`)?)?\\n                       ` : ` spirv-element-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Variable : !spirv.ptr<f32, Function>\\n    %1 = spirv.Variable : !spirv.ptr<f32, Function>\\n    spirv.CopyMemory \\\"Function\\\" %0, \\\"Function\\\" %1 : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"source\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_access\", \"type\": \"OptionalAttr<SPIRV_MemoryAccessAttr{None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerVisible|NonPrivatePointer|AliasScopeINTELMask|NoAliasINTELMask}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I32Attr>>\" },\n      { \"name\": \"source_memory_access\", \"type\": \"OptionalAttr<SPIRV_MemoryAccessAttr{None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerVisible|NonPrivatePointer|AliasScopeINTELMask|NoAliasINTELMask}>\" },\n      { \"name\": \"source_alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I32Attr>>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Dot\",\n    \"summary\": \"Dot product of Vector 1 and Vector 2\",\n    \"description\": \"Result Type must be a floating point scalar.\\n\\n    Vector 1 and Vector 2 must be vectors of the same type, and their component\\n    type must be Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Dot %v1, %v2 : vector<4xf32> -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_VectorOf<SPIRV_AnyFloat>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_VectorOf<SPIRV_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyFloat\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EmitVertex\",\n    \"summary\": \"Emits the current values of all output variables to the current output\\n    primitive. After execution, the values of all output variables are\\n    undefined.\",\n    \"description\": \"This instruction must only be used when only one stream is present.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.EmitVertex\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EndPrimitive\",\n    \"summary\": \"Finish the current primitive and start a new one. No vertex is emitted.\",\n    \"description\": \"This instruction must only be used when only one stream is present.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.EndPrimitive\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EntryPoint\",\n    \"summary\": \"Declare an entry point, its execution model, and its interface.\",\n    \"description\": \"Execution Model is the execution model for the entry point and its\\n    static call tree. See Execution Model.\\n\\n    Entry Point must be the Result `<id>` of an OpFunction instruction.\\n\\n    Name is a name string for the entry point. A module cannot have two\\n    OpEntryPoint instructions with the same Execution Model and the same\\n    Name string.\\n\\n    Interface is a list of symbol references to `spirv.GlobalVariable`\\n    operations. These declare the set of global variables from a\\n    module that form the interface of this entry point. The set of\\n    Interface symbols must be equal to or a superset of the\\n    `spirv.GlobalVariable`s referenced by the entry point’s static call\\n    tree, within the interface’s storage classes.  Before version 1.4,\\n    the interface’s storage classes are limited to the Input and\\n    Output storage classes. Starting with version 1.4, the interface’s\\n    storage classes are all storage classes used in declaring all\\n    global variables referenced by the entry point’s call tree.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    execution-model ::= \\\"Vertex\\\" | \\\"TesellationControl\\\" |\\n                        <and other SPIR-V execution models...>\\n\\n    entry-point-op ::= ssa-id `=` `spirv.EntryPoint` execution-model\\n                       symbol-reference (`, ` symbol-reference)*\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.EntryPoint \\\"GLCompute\\\" @foo\\n    spirv.EntryPoint \\\"Kernel\\\" @foo, @var1, @var2\\n\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"execution_model\", \"type\": \"SPIRV_ExecutionModelAttr{Vertex|TessellationControl|TessellationEvaluation|Geometry|Fragment|GLCompute|Kernel|RayGenerationKHR|IntersectionKHR|AnyHitKHR|ClosestHitKHR|MissKHR|CallableKHR|TaskEXT|MeshEXT}\" },\n      { \"name\": \"fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"interface\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ExecutionMode\",\n    \"summary\": \"Declare an execution mode for an entry point.\",\n    \"description\": \"Entry Point must be the Entry Point `<id>` operand of an OpEntryPoint\\n    instruction.\\n\\n    Mode is the execution mode. See Execution Mode.\\n\\n    This instruction is only valid when the Mode operand is an execution\\n    mode that takes no Extra Operands, or takes Extra Operands that are not\\n    `<id>` operands.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    execution-mode ::= \\\"Invocations\\\" | \\\"SpacingEqual\\\" |\\n                       <and other SPIR-V execution modes...>\\n\\n    execution-mode-op ::= `spirv.ExecutionMode ` ssa-use execution-mode\\n                          (integer-literal (`, ` integer-literal)* )?\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ExecutionMode @foo \\\"ContractionOff\\\"\\n    spirv.ExecutionMode @bar \\\"LocalSizeHint\\\", 3, 4, 5\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"execution_mode\", \"type\": \"SPIRV_ExecutionModeAttr{Invocations|SpacingEqual|SpacingFractionalEven|SpacingFractionalOdd|VertexOrderCw|VertexOrderCcw|PixelCenterInteger|OriginUpperLeft|OriginLowerLeft|EarlyFragmentTests|PointMode|Xfb|DepthReplacing|DepthGreater|DepthLess|DepthUnchanged|LocalSize|LocalSizeHint|InputPoints|InputLines|InputLinesAdjacency|Triangles|InputTrianglesAdjacency|Quads|Isolines|OutputVertices|OutputPoints|OutputLineStrip|OutputTriangleStrip|VecTypeHint|ContractionOff|Initializer|Finalizer|SubgroupSize|SubgroupsPerWorkgroup|SubgroupsPerWorkgroupId|LocalSizeId|LocalSizeHintId|SubgroupUniformControlFlowKHR|PostDepthCoverage|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|EarlyAndLateFragmentTestsAMD|StencilRefReplacingEXT|StencilRefUnchangedFrontAMD|StencilRefGreaterFrontAMD|StencilRefLessFrontAMD|StencilRefUnchangedBackAMD|StencilRefGreaterBackAMD|StencilRefLessBackAMD|OutputLinesEXT|OutputPrimitivesEXT|DerivativeGroupQuadsNV|DerivativeGroupLinearNV|OutputTrianglesEXT|PixelInterlockOrderedEXT|PixelInterlockUnorderedEXT|SampleInterlockOrderedEXT|SampleInterlockUnorderedEXT|ShadingRateInterlockOrderedEXT|ShadingRateInterlockUnorderedEXT|SharedLocalMemorySizeINTEL|RoundingModeRTPINTEL|RoundingModeRTNINTEL|FloatingPointModeALTINTEL|FloatingPointModeIEEEINTEL|MaxWorkgroupSizeINTEL|MaxWorkDimINTEL|NoGlobalOffsetINTEL|NumSIMDWorkitemsINTEL|SchedulerTargetFmaxMhzINTEL|StreamingInterfaceINTEL|NamedBarrierCountINTEL}\" },\n      { \"name\": \"values\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ExecutionModeId\",\n    \"summary\": \"Declare an execution mode for an entry point, using <id>s as Extra\\n    Operands.\",\n    \"description\": \"Entry Point must be the Entry Point <id> operand of an OpEntryPoint\\n    instruction.\\n\\n    Mode is the execution mode. See Execution Mode.\\n\\n    This instruction is only valid if the Mode operand is an execution mode\\n    that takes Extra Operands that are <id> operands. Otherwise, use\\n    OpExecutionMode.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    execution-mode ::= \\\"Invocations\\\" | \\\"SpacingEqual\\\" |\\n                           <and other SPIR-V execution modes...>\\n    execution-mode-id-op ::= `spirv.ExecutionMode ` ssa-use execution-mode\\n                              symbol-reference (`, ` symbol-reference)*\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ExecutionModeId @foo \\\"LocalSizeId\\\" @var0, @var1, @var2\\n    spirv.ExecutionModeId @bar \\\"LocalSizeHintId\\\" @x, @y, @z\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"execution_mode\", \"type\": \"SPIRV_ExecutionModeAttr{Invocations|SpacingEqual|SpacingFractionalEven|SpacingFractionalOdd|VertexOrderCw|VertexOrderCcw|PixelCenterInteger|OriginUpperLeft|OriginLowerLeft|EarlyFragmentTests|PointMode|Xfb|DepthReplacing|DepthGreater|DepthLess|DepthUnchanged|LocalSize|LocalSizeHint|InputPoints|InputLines|InputLinesAdjacency|Triangles|InputTrianglesAdjacency|Quads|Isolines|OutputVertices|OutputPoints|OutputLineStrip|OutputTriangleStrip|VecTypeHint|ContractionOff|Initializer|Finalizer|SubgroupSize|SubgroupsPerWorkgroup|SubgroupsPerWorkgroupId|LocalSizeId|LocalSizeHintId|SubgroupUniformControlFlowKHR|PostDepthCoverage|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|EarlyAndLateFragmentTestsAMD|StencilRefReplacingEXT|StencilRefUnchangedFrontAMD|StencilRefGreaterFrontAMD|StencilRefLessFrontAMD|StencilRefUnchangedBackAMD|StencilRefGreaterBackAMD|StencilRefLessBackAMD|OutputLinesEXT|OutputPrimitivesEXT|DerivativeGroupQuadsNV|DerivativeGroupLinearNV|OutputTrianglesEXT|PixelInterlockOrderedEXT|PixelInterlockUnorderedEXT|SampleInterlockOrderedEXT|SampleInterlockUnorderedEXT|ShadingRateInterlockOrderedEXT|ShadingRateInterlockUnorderedEXT|SharedLocalMemorySizeINTEL|RoundingModeRTPINTEL|RoundingModeRTNINTEL|FloatingPointModeALTINTEL|FloatingPointModeIEEEINTEL|MaxWorkgroupSizeINTEL|MaxWorkDimINTEL|NoGlobalOffsetINTEL|NumSIMDWorkitemsINTEL|SchedulerTargetFmaxMhzINTEL|StreamingInterfaceINTEL|NamedBarrierCountINTEL}\" },\n      { \"name\": \"values\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EXT.AtomicFAdd\",\n    \"summary\": \"TBD\",\n    \"description\": \"<!-- End of AutoGen section -->\\n\\n    Perform the following steps atomically with respect to any other atomic\\n    accesses within Scope to the same location:\\n\\n    1) load through Pointer to get an Original Value,\\n\\n    2) get a New Value by float addition of Original Value and Value, and\\n\\n    3) store the New Value back through Pointer.\\n\\n    The instruction's result is the Original Value.\\n\\n    Result Type must be a floating-point type scalar.\\n\\n    The type of Value must be the same as Result Type. The type of the value\\n    pointed to by Pointer must be the same as Result Type.\\n\\n    Memory must be a valid memory Scope.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.EXT.AtomicFAdd <Device> <None> %pointer, %value :\\n                           !spirv.ptr<f32, StorageBuffer>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Float\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'pointer', 'result', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" },\n      { \"type\": \"TypesMatchWith<'pointer', 'value', 'llvm::cast<PointerType>($_self).getPointeeType()'>\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope $semantics operands attr-dict `:` type($pointer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EXT.ConstantCompositeReplicate\",\n    \"summary\": \"Declare a new replicated composite constant op.\",\n    \"description\": \"Represents a splat composite constant i.e., all elements of composite constant\\n    have the same value.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.EXT.ConstantCompositeReplicate [1 : i32] : vector<2xi32>\\n    %1 = spirv.EXT.ConstantCompositeReplicate [1 : i32] : !spirv.array<2 x vector<2xi32>>\\n    %2 = spirv.EXT.ConstantCompositeReplicate [dense<[1, 2]> : vector<2xi32>] : !spirv.array<2 x vector<2xi32>>\\n    ```\",\n    \"results\": [\n      { \"name\": \"replicated_constant\", \"type\": \"SPIRV_Composite\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"` ` `[` $value `]` `:` type($replicated_constant) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EXT.EmitMeshTasks\",\n    \"summary\": \"Defines the grid size of subsequent mesh shader workgroups to generate upon\\n    completion of the task shader workgroup.\",\n    \"description\": \"Defines the grid size of subsequent mesh shader workgroups to generate upon\\n    completion of the task shader workgroup.\\n\\n    Group Count X Y Z must each be a 32-bit unsigned integer value. They\\n    configure the number of local workgroups in each respective dimensions for the\\n    launch of child mesh tasks. See Vulkan API specification for more detail.\\n\\n    Payload is an optional pointer to the payload structure to pass to the\\n    generated mesh shader invocations. Payload must be the result of an OpVariable\\n    with a storage class of TaskPayloadWorkgroupEXT.\\n\\n    The arguments are taken from the first invocation in each workgroup.\\n    Behaviour is undefined if any invocation terminates without executing this\\n    instruction, or if any invocation executes this instruction in non-uniform\\n    control flow.\\n\\n    This instruction also serves as an OpControlBarrier instruction, and also\\n    performs and adheres to the description and semantics of an OpControlBarrier\\n    instruction with the Execution and Memory operands set to Workgroup and the\\n    Semantics operand set to a combination of WorkgroupMemory and AcquireRelease.\\n\\n    Ceases all further processing: Only instructions executed before\\n    OpEmitMeshTasksEXT have observable side effects.\\n\\n    This instruction must be the last instruction in a block.\\n\\n    This instruction is only valid in the TaskEXT Execution Model.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.EmitMeshTasksEXT %x, %y, %z : i32, i32, i32\\n    spirv.EmitMeshTasksEXT %x, %x, %z, %payload : i32, i32, i32, !spirv.ptr<i32, TaskPayloadWorkgroupEXT>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"group_count_x\", \"type\": \"SignlessOrUnsignedIntOfWidths<[32]>\" },\n      { \"name\": \"group_count_y\", \"type\": \"SignlessOrUnsignedIntOfWidths<[32]>\" },\n      { \"name\": \"group_count_z\", \"type\": \"SignlessOrUnsignedIntOfWidths<[32]>\" },\n      { \"name\": \"payload\", \"type\": \"Optional<SPIRV_AnyPtr>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type(operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EXT.SetMeshOutputs\",\n    \"summary\": \"Sets the actual output size of the primitives and vertices that the mesh\\n    shader workgroup will emit upon completion.\",\n    \"description\": \"Vertex Count must be a 32-bit unsigned integer value. It defines the array size\\n    of per-vertex outputs.\\n\\n    Primitive Count must a 32-bit unsigned integer value. It defines the array size\\n    of per-primitive outputs.\\n\\n    The arguments are taken from the first invocation in each workgroup. Behavior\\n    is undefined if any invocation executes this instruction more than once or\\n    under non-uniform control flow. Behavior is undefined if there is any control\\n    flow path to an output write that is not preceded by this instruction.\\n\\n    This instruction is only valid in the MeshEXT Execution Model.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.SetMeshOutputsEXT %vcount, %pcount : i32, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vertex_count\", \"type\": \"SignlessOrUnsignedIntOfWidths<[32]>\" },\n      { \"name\": \"primitive_count\", \"type\": \"SignlessOrUnsignedIntOfWidths<[32]>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type(operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.EXT.SpecConstantCompositeReplicate\",\n    \"summary\": \"Declare a new replicated composite specialization constant op.\",\n    \"description\": \"Represents a splat spec composite constant i.e., all elements of spec composite\\n    constant have the same value. The splat value must come from a symbol reference\\n    of spec constant instruction.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.SpecConstant @sc_i32_1 = 1 : i32\\n    spirv.EXT.SpecConstantCompositeReplicate @scc_splat_array_of_i32 (@sc_i32_1) : !spirv.array<3 x i32>\\n    spirv.EXT.SpecConstantCompositeReplicate @scc_splat_struct_of_i32 (@sc_i32_1) : !spirv.struct<(i32, i32, i32)>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"constituent\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FAdd\",\n    \"summary\": \"Floating-point addition of Operand 1 and Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FAdd %0, %1 : f32\\n    %5 = spirv.FAdd %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FConvert\",\n    \"summary\": \"Convert value numerically from one floating-point width to another\\n    width.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    Float Value must be a scalar or vector of floating-point type.  It must\\n    have the same number of components as Result Type.  The component width\\n    cannot equal the component width in Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.FConvert %0 : f32 to f64\\n    %3 = spirv.FConvert %2 : vector<3xf32> to vector<3xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_AnyFloat>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_AnyFloat>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FDiv\",\n    \"summary\": \"Floating-point division of Operand 1 divided by Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FDiv %0, %1 : f32\\n    %5 = spirv.FDiv %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FMod\",\n    \"summary\": \"The floating-point remainder whose sign matches the sign of Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.  Otherwise, the result is the remainder r of Operand\\n    1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the\\n    sign of Operand 2.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FMod %0, %1 : f32\\n    %5 = spirv.FMod %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FMul\",\n    \"summary\": \"Floating-point multiplication of Operand 1 and Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FMul %0, %1 : f32\\n    %5 = spirv.FMul %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FNegate\",\n    \"summary\": \"Inverts the sign bit of Operand. (Note, however, that OpFNegate is still\\n    considered a floating-point instruction, and so is subject to the\\n    general floating-point rules regarding, for example, subnormals and NaN\\n    propagation).\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The type of Operand must be the same as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.FNegate %0 : f32\\n    %3 = spirv.FNegate %2 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FOrdEqual\",\n    \"summary\": \"Floating-point comparison for being ordered and equal.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FOrdEqual %0, %1 : f32\\n    %5 = spirv.FOrdEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FOrdGreaterThan\",\n    \"summary\": \"Floating-point comparison if operands are ordered and Operand 1 is\\n    greater than  Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FOrdGreaterThan %0, %1 : f32\\n    %5 = spirv.FOrdGreaterThan %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FOrdGreaterThanEqual\",\n    \"summary\": \"Floating-point comparison if operands are ordered and Operand 1 is\\n    greater than or equal to Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FOrdGreaterThanEqual %0, %1 : f32\\n    %5 = spirv.FOrdGreaterThanEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FOrdLessThan\",\n    \"summary\": \"Floating-point comparison if operands are ordered and Operand 1 is less\\n    than Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FOrdLessThan %0, %1 : f32\\n    %5 = spirv.FOrdLessThan %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FOrdLessThanEqual\",\n    \"summary\": \"Floating-point comparison if operands are ordered and Operand 1 is less\\n    than or equal to Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FOrdLessThanEqual %0, %1 : f32\\n    %5 = spirv.FOrdLessThanEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FOrdNotEqual\",\n    \"summary\": \"Floating-point comparison for being ordered and not equal.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FOrdNotEqual %0, %1 : f32\\n    %5 = spirv.FOrdNotEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FRem\",\n    \"summary\": \"The floating-point remainder whose sign matches the sign of Operand 1.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.  Otherwise, the result is the remainder r of Operand\\n    1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the\\n    sign of Operand 1.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FRem %0, %1 : f32\\n    %5 = spirv.FRem %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FSub\",\n    \"summary\": \"Floating-point subtraction of Operand 2 from Operand 1.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FSub %0, %1 : f32\\n    %5 = spirv.FSub %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.func\",\n    \"summary\": \"Declare or define a function\",\n    \"description\": \"This op declares or defines a SPIR-V function using one region, which\\n    contains one or more blocks.\\n\\n    Different from the SPIR-V binary format, this op is not allowed to\\n    implicitly capture global values, and all external references must use\\n    function arguments or symbol references. This op itself defines a symbol\\n    that is unique in the enclosing module op.\\n\\n    This op itself takes no operands and generates no results. Its region\\n    can take zero or more arguments and return zero or one values.\\n\\n    From `SPV_KHR_physical_storage_buffer`:\\n    If a parameter of function is\\n    - a pointer (or contains a pointer) in the PhysicalStorageBuffer storage\\n      class, the function parameter must be decorated with exactly one of\\n      `Aliased` or `Restrict`.\\n    - a pointer (or contains a pointer) and the type it points to is a pointer\\n      in the PhysicalStorageBuffer storage class, the function parameter must\\n      be decorated with exactly one of `AliasedPointer` or `RestrictPointer`.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    spv-function-control ::= \\\"None\\\" | \\\"Inline\\\" | \\\"DontInline\\\" | ...\\n    spv-function-op ::= `spirv.func` function-signature\\n                         spv-function-control region\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.func @foo() -> () \\\"None\\\" { ... }\\n    spirv.func @bar() -> () \\\"Inline|Pure\\\" { ... }\\n\\n    spirv.func @aliased_pointer(%arg0: !spirv.ptr<i32, PhysicalStorageBuffer>,\\n        { spirv.decoration = #spirv.decoration<Aliased> }) -> () \\\"None\\\" { ... }\\n\\n    spirv.func @restrict_pointer(%arg0: !spirv.ptr<i32, PhysicalStorageBuffer>,\\n        { spirv.decoration = #spirv.decoration<Restrict> }) -> () \\\"None\\\" { ... }\\n\\n    spirv.func @aliased_pointee(%arg0: !spirv.ptr<!spirv.ptr<i32,\\n        PhysicalStorageBuffer>, Generic> { spirv.decoration =\\n        #spirv.decoration<AliasedPointer> }) -> () \\\"None\\\" { ... }\\n\\n    spirv.func @restrict_pointee(%arg0: !spirv.ptr<!spirv.ptr<i32,\\n        PhysicalStorageBuffer>, Generic> { spirv.decoration =\\n        #spirv.decoration<RestrictPointer> }) -> () \\\"None\\\" { ... }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"function_control\", \"type\": \"SPIRV_FunctionControlAttr{None|Inline|DontInline|Pure|Const|OptNoneINTEL}\" },\n      { \"name\": \"linkage_attributes\", \"type\": \"OptionalAttr<SPIRV_LinkageAttributesAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FunctionCall\",\n    \"summary\": \"Call a function.\",\n    \"description\": \"Result Type is the type of the return value of the function. It must be\\n    the same as the Return Type operand of the Function Type operand of the\\n    Function operand.\\n\\n    Function is an OpFunction instruction.  This could be a forward\\n    reference.\\n\\n    Argument N is the object to copy to parameter N of Function.\\n\\n    Note: A forward call is possible because there is no missing type\\n    information: Result Type must match the Return Type of the function, and\\n    the calling argument types must match the formal parameter types.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.FunctionCall @f_void(%arg0) : (i32) ->  ()\\n    %0 = spirv.FunctionCall @f_iadd(%arg0, %arg1) : (i32, i32) -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"return_value\", \"type\": \"Optional<SPIRV_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $arguments `)` attr-dict `:`\\n      functional-type($arguments, results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FUnordEqual\",\n    \"summary\": \"Floating-point comparison for being unordered or equal.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FUnordEqual %0, %1 : f32\\n    %5 = spirv.FUnordEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FUnordGreaterThan\",\n    \"summary\": \"Floating-point comparison if operands are unordered or Operand 1 is\\n    greater than  Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FUnordGreaterThan %0, %1 : f32\\n    %5 = spirv.FUnordGreaterThan %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FUnordGreaterThanEqual\",\n    \"summary\": \"Floating-point comparison if operands are unordered or Operand 1 is\\n    greater than or equal to Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FUnordGreaterThanEqual %0, %1 : f32\\n    %5 = spirv.FUnordGreaterThanEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FUnordLessThan\",\n    \"summary\": \"Floating-point comparison if operands are unordered or Operand 1 is less\\n    than Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FUnordLessThan %0, %1 : f32\\n    %5 = spirv.FUnordLessThan %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FUnordLessThanEqual\",\n    \"summary\": \"Floating-point comparison if operands are unordered or Operand 1 is less\\n    than or equal to Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FUnordLessThanEqual %0, %1 : f32\\n    %5 = spirv.FUnordLessThanEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.FUnordNotEqual\",\n    \"summary\": \"Floating-point comparison for being unordered or not equal.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    floating-point type.  They must have the same type, and they must have\\n    the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.FUnordNotEqual %0, %1 : f32\\n    %5 = spirv.FUnordNotEqual %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GenericCastToPtr\",\n    \"summary\": \"Convert a pointer’s Storage Class to a non-Generic class.\",\n    \"description\": \"Result Type must be an OpTypePointer. Its Storage Class must be\\n    Workgroup, CrossWorkgroup, or Function.\\n\\n    Pointer must point to the Generic Storage Class.\\n\\n    Result Type and Pointer must point to the same type.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.GenericCastToPtr %0 : !spirv.ptr<f32, Generic> to\\n         !spirv.ptr<f32, CrossWorkgroup>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$pointer attr-dict `:` type($pointer) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GenericCastToPtrExplicit\",\n    \"summary\": \"Attempts to explicitly convert Pointer to Storage storage-class pointer\\n    value.\",\n    \"description\": \"Result Type must be an OpTypePointer. Its Storage Class must be Storage.\\n\\n    Pointer must have a type of OpTypePointer whose Type is the same as the\\n    Type of Result Type.Pointer must point to the Generic Storage Class. If\\n    the cast fails, the instruction result is an OpConstantNull pointer in\\n    the Storage Storage Class.\\n\\n    Storage must be one of the following literal values from Storage Class:\\n    Workgroup, CrossWorkgroup, or Function.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.GenericCastToPtrExplicit %0 : !spirv.ptr<f32, Generic> to\\n         !spirv.ptr<f32, CrossWorkgroup>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$pointer attr-dict `:` type($pointer) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Acos\",\n    \"summary\": \"Arc Cosine of operand in radians\",\n    \"description\": \"The standard trigonometric arc cosine of x radians.\\n\\n    Result is an angle, in radians, whose cosine is x. The range of result\\n    values is [0, π]. Result is undefined if abs x > 1.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Acos %0 : f32\\n    %3 = spirv.GL.Acos %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Acosh\",\n    \"summary\": \"Arc hyperbolic cosine of operand in radians.\",\n    \"description\": \"Arc hyperbolic cosine; result is the non-negative inverse of cosh. The resulting\\n    value is NaN if x < 1.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Acosh %0 : f32\\n    %3 = spirv.GL.Acosh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Asin\",\n    \"summary\": \"Arc Sine of operand in radians\",\n    \"description\": \"The standard trigonometric arc sine of x radians.\\n\\n    Result is an angle, in radians, whose sine is x. The range of result values\\n    is [-π / 2, π / 2]. Result is undefined if abs x > 1.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Asin %0 : f32\\n    %3 = spirv.GL.Asin %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Asinh\",\n    \"summary\": \"Arc hyperbolic sine of operand in radians.\",\n    \"description\": \"Arc hyperbolic sine; result is the inverse of sinh.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Asinh %0 : f32\\n    %3 = spirv.GL.Asinh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Atan\",\n    \"summary\": \"Arc Tangent of operand in radians\",\n    \"description\": \"The standard trigonometric arc tangent of x radians.\\n\\n    Result is an angle, in radians, whose tangent is y_over_x. The range of\\n    result values is [-π / 2, π / 2].\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Atan %0 : f32\\n    %3 = spirv.GL.Atan %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Atanh\",\n    \"summary\": \"Arc hyperbolic tangent of operand in radians.\",\n    \"description\": \"Arc hyperbolic tangent; result is the inverse of tanh. The resulting value\\n    is NaN if abs x ≥ 1.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Atanh %0 : f32\\n    %3 = spirv.GL.Atanh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Ceil\",\n    \"summary\": \"Rounds up to the next whole number\",\n    \"description\": \"Result is the value equal to the nearest whole number that is greater than\\n    or equal to x.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Ceil %0 : f32\\n    %3 = spirv.GL.Ceil %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Cos\",\n    \"summary\": \"Cosine of operand in radians\",\n    \"description\": \"The standard trigonometric cosine of x radians.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Cos %0 : f32\\n    %3 = spirv.GL.Cos %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Cosh\",\n    \"summary\": \"Hyperbolic cosine of operand in radians\",\n    \"description\": \"Hyperbolic cosine of x radians.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Cosh %0 : f32\\n    %3 = spirv.GL.Cosh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Cross\",\n    \"summary\": \"Return the cross product of two 3-component vectors\",\n    \"description\": \"Result is the cross product of x and y, i.e., the resulting components are, in order:\\n\\n    x[1] * y[2] - y[1] * x[2]\\n\\n    x[2] * y[0] - y[2] * x[0]\\n\\n    x[0] * y[1] - y[0] * x[1]\\n\\n    All the operands must be vectors of 3 components of a floating-point type.\\n\\n    Result Type and the type of all operands must be the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Cross %0, %1 : vector<3xf32>\\n    %3 = spirv.GL.Cross %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Distance\",\n    \"summary\": \"Return distance between two points\",\n    \"description\": \"Result is the distance between p0 and p1, i.e., length(p0 - p1).\\n\\n    The operands must all be a scalar or vector whose component type is floating-point.\\n\\n    Result Type must be a scalar of the same type as the component type of the operands.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Distance %0, %1 : vector<3xf32>, vector<3xf32> -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"p0\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"p1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Float\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['p0', 'p1']>\" },\n      { \"type\": \"TypesMatchWith<'p0', 'result', '::mlir::getElementTypeOrSelf($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($p0) `,` type($p1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Exp\",\n    \"summary\": \"Exponentiation of Operand 1\",\n    \"description\": \"Result is the natural exponentiation of x; e^x.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    16-bit or 32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are\\n    computed per component.\\\";\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Exp %0 : f32\\n    %3 = spirv.GL.Exp %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Exp2\",\n    \"summary\": \"Result is 2 raised to the x power\",\n    \"description\": \"Result is 2 raised to the x power; 2**x.\\n\\n    ```\\n    exp2(Inf) = Inf.\\n    exp2(-Inf) = +0.\\n    ```\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Exp2 %0 : f32\\n    %3 = spirv.GL.Exp2 %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FAbs\",\n    \"summary\": \"Absolute value of operand\",\n    \"description\": \"Result is x if x >= 0; otherwise result is -x.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.FAbs %0 : f32\\n    %3 = spirv.GL.FAbs %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FClamp\",\n    \"summary\": \"Clamp x between min and max values.\",\n    \"description\": \"Result is min(max(x, minVal), maxVal). The resulting value is undefined if\\n    minVal > maxVal. The semantics used by min() and max() are those of FMin and\\n    FMax.\\n\\n    The operands must all be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of all operands must be the same type. Results are\\n    computed per component.\\n\\n    <!-- End of AutoGen section -->\\n    ```\\n    fclamp-op ::= ssa-id `=` `spirv.GL.FClamp` ssa-use, ssa-use, ssa-use `:`\\n               float-scalar-vector-type\\n    ```\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.FClamp %x, %min, %max : f32\\n    %3 = spirv.GL.FClamp %x, %min, %max : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"z\", \"type\": \"SPIRV_ScalarOrVectorOf<type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FindILsb\",\n    \"summary\": \"Integer least-significant bit\",\n    \"description\": \"Results in the bit number of the least-significant 1-bit in the binary\\n    representation of Value. If Value is 0, the result is -1.\\n\\n    Result Type and the type of Value must both be integer scalar or\\n    integer vector types. Result Type and operand types must have the\\n    same number of components with the same component width. Results are\\n    computed per component.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FindSMsb\",\n    \"summary\": \"Signed-integer most-significant bit, with Value interpreted as a signed integer\",\n    \"description\": \"For positive numbers, the result will be the bit number of the most significant\\n    1-bit. For negative numbers, the result will be the bit number of the most\\n    significant 0-bit. For a Value of 0 or -1, the result is -1.\\n\\n    Result Type and the type of Value must both be integer scalar or\\n    integer vector types. Result Type and operand types must have the\\n    same number of components with the same component width. Results are\\n    computed per component.\\n\\n    This instruction is currently limited to 32-bit width components.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Int32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Int32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FindUMsb\",\n    \"summary\": \"Unsigned-integer most-significant bit\",\n    \"description\": \"Results in the bit number of the most-significant 1-bit in the binary\\n    representation of Value. If Value is 0, the result is -1.\\n\\n    Result Type and the type of Value must both be integer scalar or\\n    integer vector types. Result Type and operand types must have the\\n    same number of components with the same component width. Results are\\n    computed per component.\\n\\n    This instruction is currently limited to 32-bit width components.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Int32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Int32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Floor\",\n    \"summary\": \"Rounds down to the next whole number\",\n    \"description\": \"Result is the value equal to the nearest whole number that is less than or\\n    equal to x.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Floor %0 : f32\\n    %3 = spirv.GL.Floor %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Fma\",\n    \"summary\": \"Computes a * b + c.\",\n    \"description\": \"In uses where this operation is decorated with NoContraction:\\n\\n    - fma is considered a single operation, whereas the expression a * b + c\\n      is considered two operations.\\n    - The precision of fma can differ from the precision of the expression\\n      a * b + c.\\n    - fma will be computed with the same precision as any other fma decorated\\n      with NoContraction, giving invariant results for the same input values\\n      of a, b, and c.\\n\\n    Otherwise, in the absence of a NoContraction decoration, there are no\\n    special constraints on the number of operations or difference in precision\\n    between fma and the expression a * b +c.\\n\\n    The operands must all be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of all operands must be the same type. Results\\n    are computed per component.\\n\\n    <!-- End of AutoGen section -->\\n    ```\\n    fma-op ::= ssa-id `=` `spirv.GL.Fma` ssa-use, ssa-use, ssa-use `:`\\n               float-scalar-vector-type\\n    ```\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GL.Fma %a, %b, %c : f32\\n    %1 = spirv.GL.Fma %a, %b, %c : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"z\", \"type\": \"SPIRV_ScalarOrVectorOf<type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FMax\",\n    \"summary\": \"Return maximum of two floating-point operands\",\n    \"description\": \"Result is y if x < y; otherwise result is x. Which operand is the\\n    result is undefined if one of the operands is a NaN.\\n\\n    The operands must all be a scalar or vector whose component type\\n    is floating-point.\\n\\n    Result Type and the type of all operands must be the same\\n    type. Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.FMax %0, %1 : f32\\n    %3 = spirv.GL.FMax %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FMin\",\n    \"summary\": \"Return minimum of two floating-point operands\",\n    \"description\": \"Result is y if y < x; otherwise result is x. Which operand is the result is\\n    undefined if one of the operands is a NaN.\\n\\n    The operands must all be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of all operands must be the same type. Results are\\n    computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.FMin %0, %1 : f32\\n    %3 = spirv.GL.FMin %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FMix\",\n    \"summary\": \"Builds the linear blend of x and y\",\n    \"description\": \"Result is the linear blend of x and y, i.e., x * (1 - a) + y * a.\\n\\n    The operands must all be a scalar or vector whose component type is floating-point.\\n\\n    Result Type and the type of all operands must be the same type. Results are computed per component.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GL.FMix %x : f32, %y : f32, %a : f32 -> f32\\n    %0 = spirv.GL.FMix %x : vector<4xf32>, %y : vector<4xf32>, %a : vector<4xf32> -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"a\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'y', 'a', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $x `:` type($x) `,` $y `:` type($y) `,` $a `:` type($a) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Fract\",\n    \"summary\": \"Returns the `x - floor(x)` of the operand\",\n    \"description\": \"Result is:\\n\\n    ```\\n    fract(x) = x - floor(x)\\n    fract(±0) = +0\\n    fract(±Inf) = NaN\\n    ```\\n\\n    The operand x must be a scalar or vector whose component type is floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %result = spirv.GL.Sqrt %x : f32\\n    %result = spirv.GL.Sqrt %x : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FrexpStruct\",\n    \"summary\": \"Splits x into two components such that x = significand * 2^exponent\",\n    \"description\": \"Result is a structure containing x split into a floating-point significand\\n    in the range (-1.0, 0.5] or [0.5, 1.0) and an integral exponent of 2, such that:\\n\\n    x = significand * 2^exponent\\n\\n    If x is a zero, the exponent is 0.0. If x is an infinity or a NaN, the\\n    exponent is undefined. If x is 0.0, the significand is 0.0. If x is -0.0,\\n    the significand is -0.0\\n\\n    Result Type must be an OpTypeStruct with two members. Member 0 must have\\n    the same type as the type of x. Member 0 holds the significand. Member 1\\n    must be a scalar or vector with integer component type, with 32-bit\\n    component width. Member 1 holds the exponent. These two members and x must\\n    have the same number of components.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.FrexpStruct %0 : f32 -> !spirv.struct<f32, i32>\\n    %3 = spirv.GL.FrexpStruct %0 : vector<3xf32> -> !spirv.struct<vector<3xf32>, vector<3xi32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyStruct\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.FSign\",\n    \"summary\": \"Returns the sign of the operand\",\n    \"description\": \"Result is 1.0 if x > 0, 0.0 if x = 0, or -1.0 if x < 0.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.FSign %0 : f32\\n    %3 = spirv.GL.FSign %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.InverseSqrt\",\n    \"summary\": \"Reciprocal of sqrt(operand)\",\n    \"description\": \"Result is the reciprocal of sqrt x. Result is undefined if x <= 0.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.InverseSqrt %0 : f32\\n    %3 = spirv.GL.InverseSqrt %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Ldexp\",\n    \"summary\": \"Builds y such that y = significand * 2^exponent\",\n    \"description\": \"Builds a floating-point number from x and the corresponding\\n    integral exponent of two in exp:\\n\\n    significand * 2^exponent\\n\\n    If this product is too large to be represented in the floating-point\\n    type, the resulting value is undefined. If exp is greater than +128\\n    (single precision) or +1024 (double precision), the resulting value is\\n    undefined. If exp is less than -126 (single precision) or -1022 (double precision),\\n    the result may be flushed to zero. Additionally, splitting the value\\n    into a significand and exponent using frexp and then reconstructing a\\n    floating-point value using ldexp should yield the original input for\\n    zero and all finite non-denormalized values.\\n\\n    The operand x must be a scalar or vector whose component type is floating-point.\\n\\n    The exp operand must be a scalar or vector with integer component type.\\n    The number of components in x and exp must be the same.\\n\\n    Result Type must be the same type as the type of x. Results are computed per\\n    component.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %y = spirv.GL.Ldexp %x : f32, %exp : i32 -> f32\\n    %y = spirv.GL.Ldexp %x : vector<3xf32>, %exp : vector<3xi32> -> vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"exp\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'y']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $x `:` type($x) `,` $exp `:` type($exp) `->` type($y)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Length\",\n    \"summary\": \"Return the length of a vector x\",\n    \"description\": \"Result is the length of vector x, i.e., sqrt(x[0]**2 + x[1]**2 + ...).\\n\\n    The operand x must be a scalar or vector whose component type is floating-point.\\n\\n    Result Type must be a scalar of the same type as the component type of x.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Length %0 : vector<3xf32> -> f32\\n    %3 = spirv.GL.Length %1 : f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Float\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', '::mlir::getElementTypeOrSelf($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Log\",\n    \"summary\": \"Natural logarithm of the operand\",\n    \"description\": \"Result is the natural logarithm of x, i.e., the value y which satisfies the\\n    equation x = ey. Result is undefined if x <= 0.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Log %0 : f32\\n    %3 = spirv.GL.Log %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Log2\",\n    \"summary\": \"Result is the base-2 logarithm of x\",\n    \"description\": \"Result is the base-2 logarithm of x, i.e., the value y which satisfies the\\n    equation x = 2**y. The resulting value is NaN if x < 0. Moreover:\\n\\n    ```\\n    log(Inf) = Inf\\n    log(1.0) = +0\\n    log(±0) = -Inf\\n    ```\\n    \\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n    \\n    ```mlir\\n    %2 = spirv.GL.Log2 %0 : f32\\n    %3 = spirv.GL.Log2 %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Normalize\",\n    \"summary\": \"Normalizes a vector operand\",\n    \"description\": \"Result is the vector in the same direction as x but with a length of 1.\\n\\n    The operand x must be a scalar or vector whose component type is floating-point.\\n\\n    Result Type and the type of x must be the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Normalize %0 : vector<3xf32>\\n    %3 = spirv.GL.Normalize %1 : vector<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.PackHalf2x16\",\n    \"summary\": \"Pack two-component vector of 32-bit floats into a 32-bit integer\",\n    \"description\": \"Result is the unsigned integer obtained by converting the components of a\\n    two-component floating-point vector to the 16-bit OpTypeFloat, and then packing\\n    these two 16-bit integers into a 32-bit unsigned integer. The first vector\\n    component specifies the 16 least-significant bits of the result; the second\\n    component specifies the 16 most-significant bits.\\n\\n    The RelaxedPrecision Decoration only affects the conversion step of the instruction.\\n\\n    The v operand must be a vector of 2 components whose type is a 32-bit floating-point.\\n\\n    Result Type must be a 32-bit integer type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.GL.PackHalf2x16 %0 : vector<2xf32> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VectorOfLengthAndType<[2], [SPIRV_Float32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Int32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.PackSnorm4x8\",\n    \"summary\": \"Pack four-component vector of normalized 32-bit floats into a 32-bit integer\",\n    \"description\": \"First, converts each component of the normalized floating-point value v into\\n    8-bit integer values. These are then packed into the result.\\n\\n    The conversion for component c of v to fixed point is done as follows:\\n\\n    ```\\n    round(clamp(c, -1, +1) * 127.0)\\n    ```\\n\\n    The RelaxedPrecision Decoration only affects the conversion step of the instruction.\\n\\n    The first component of the vector is written to the least significant bits of the\\n    output; the last component is written to the most significant bits.\\n\\n    The v operand must be a vector of 4 components whose type is a 32-bit floating-point.\\n\\n    Result Type must be a 32-bit integer type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GL.PackSnorm4x8 %1 : vector<4xf32> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VectorOfLengthAndType<[4], [SPIRV_Float32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Int32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Pow\",\n    \"summary\": \"Return x raised to the y power of two operands\",\n    \"description\": \"Result is x raised to the y power; x^y.\\n\\n    Result is undefined if x = 0 and y ≤ 0.\\n\\n    The operand x and y must be a scalar or vector whose component type is\\n    16-bit or 32-bit floating-point.\\n\\n    Result Type and the type of all operands must be the same type. Results are\\n    computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Pow %0, %1 : f32\\n    %3 = spirv.GL.Pow %0, %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Reflect\",\n    \"summary\": \"Calculate reflection direction vector\",\n    \"description\": \"For the incident vector I and surface orientation N, the result is the reflection direction:\\n\\n    I - 2 * dot(N, I) * N\\n\\n    N must already be normalized in order to achieve the desired result.\\n\\n    The operands must all be a scalar or vector whose component type is floating-point.\\n\\n    Result Type and the type of all operands must be the same type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Reflect %0, %1 : f32\\n    %3 = spirv.GL.Reflect %0, %1 : vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Round\",\n    \"summary\": \"Rounds to the nearest whole number\",\n    \"description\": \"Result is the value equal to the nearest whole number to x. The fraction\\n    0.5 will round in a direction chosen by the implementation, presumably\\n    the direction that is fastest. This includes the possibility that\\n    Round x is the same value as RoundEven x for all values of x.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Round %0 : f32\\n    %3 = spirv.GL.Round %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.RoundEven\",\n    \"summary\": \"Rounds to the nearest even whole number\",\n    \"description\": \"Result is the value equal to the nearest whole number to x. A fractional\\n    part of 0.5 will round toward the nearest even whole number. (Both 3.5 and\\n    4.5 for x will be 4.0.)\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.RoundEven %0 : f32\\n    %3 = spirv.GL.RoundEven %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.SAbs\",\n    \"summary\": \"Absolute value of operand\",\n    \"description\": \"Result is x if x ≥ 0; otherwise result is -x, where x is interpreted as a\\n    signed integer.\\n\\n    Result Type and the type of x must both be integer scalar or integer vector\\n    types. Result Type and operand types must have the same number of components\\n    with the same component width. Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.SAbs %0 : i32\\n    %3 = spirv.GL.SAbs %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.SClamp\",\n    \"summary\": \"Clamp x between min and max values.\",\n    \"description\": \"Result is min(max(x, minVal), maxVal), where x, minVal and maxVal are\\n    interpreted as signed integers. The resulting value is undefined if\\n    minVal > maxVal.\\n\\n    Result Type and the type of the operands must both be integer scalar or\\n    integer vector types. Result Type and operand types must have the same number\\n    of components with the same component width. Results are computed per\\n    component.\\n\\n    <!-- End of AutoGen section -->\\n    ```\\n    uclamp-op ::= ssa-id `=` `spirv.GL.UClamp` ssa-use, ssa-use, ssa-use `:`\\n               sgined-scalar-vector-type\\n    ```\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.SClamp %x, %min, %max : si32\\n    %3 = spirv.GL.SClamp %x, %min, %max : vector<3xsi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"z\", \"type\": \"SPIRV_ScalarOrVectorOf<type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Sin\",\n    \"summary\": \"Sine of operand in radians\",\n    \"description\": \"The standard trigonometric sine of x radians.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Sin %0 : f32\\n    %3 = spirv.GL.Sin %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Sinh\",\n    \"summary\": \"Hyperbolic sine of operand in radians\",\n    \"description\": \"Hyperbolic sine of x radians.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Sinh %0 : f32\\n    %3 = spirv.GL.Sinh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.SMax\",\n    \"summary\": \"Return maximum of two signed integer operands\",\n    \"description\": \"Result is y if x < y; otherwise result is x, where x and y are interpreted\\n    as signed integers.\\n\\n    Result Type and the type of x and y must both be integer scalar or integer\\n    vector types. Result Type and operand types must have the same number of\\n    components with the same component width. Results are computed per\\n    component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.SMax %0, %1 : i32\\n    %3 = spirv.GL.SMax %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.SMin\",\n    \"summary\": \"Return minimum of two signed integer operands\",\n    \"description\": \"Result is y if y < x; otherwise result is x, where x and y are interpreted\\n    as signed integers.\\n\\n    Result Type and the type of x and y must both be integer scalar or integer\\n    vector types. Result Type and operand types must have the same number of\\n    components with the same component width. Results are computed per\\n    component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.SMin %0, %1 : i32\\n    %3 = spirv.GL.SMin %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Sqrt\",\n    \"summary\": \"Returns the square root of the operand\",\n    \"description\": \"Result is the square root of x. Result is undefined if x < 0.\\n\\n    The operand x must be a scalar or vector whose component type is\\n    floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Sqrt %0 : f32\\n    %3 = spirv.GL.Sqrt %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.SSign\",\n    \"summary\": \"Returns the sign of the operand\",\n    \"description\": \"Result is 1 if x > 0, 0 if x = 0, or -1 if x < 0, where x is interpreted as\\n    a signed integer.\\n\\n    Result Type and the type of x must both be integer scalar or integer vector\\n    types. Result Type and operand types must have the same number of components\\n    with the same component width. Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.SSign %0 : i32\\n    %3 = spirv.GL.SSign %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Tan\",\n    \"summary\": \"Tangent of operand in radians\",\n    \"description\": \"The standard trigonometric tangent of x radians.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Tan %0 : f32\\n    %3 = spirv.GL.Tan %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.Tanh\",\n    \"summary\": \"Hyperbolic tangent of operand in radians\",\n    \"description\": \"Hyperbolic tangent of x radians.\\n\\n    The operand x must be a scalar or vector whose component type is 16-bit or\\n    32-bit floating-point.\\n\\n    Result Type and the type of x must be the same type. Results are computed\\n    per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.Tanh %0 : f32\\n    %3 = spirv.GL.Tanh %1 : vector<3xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float16or32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.UClamp\",\n    \"summary\": \"Clamp x between min and max values.\",\n    \"description\": \"Result is min(max(x, minVal), maxVal), where x, minVal and maxVal are\\n    interpreted as unsigned integers. The resulting value is undefined if\\n    minVal > maxVal.\\n\\n    Result Type and the type of the operands must both be integer scalar or\\n    integer vector types. Result Type and operand types must have the same number\\n    of components with the same component width. Results are computed per\\n    component.\\n\\n    <!-- End of AutoGen section -->\\n    ```\\n    uclamp-op ::= ssa-id `=` `spirv.GL.UClamp` ssa-use, ssa-use, ssa-use `:`\\n               unsigned-signless-scalar-vector-type\\n    ```\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.UClamp %x, %min, %max : i32\\n    %3 = spirv.GL.UClamp %x, %min, %max : vector<3xui16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"y\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"z\", \"type\": \"SPIRV_ScalarOrVectorOf<type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.UMax\",\n    \"summary\": \"Return maximum of two unsigned integer operands\",\n    \"description\": \"Result is y if x < y; otherwise result is x, where x and y are interpreted\\n    as unsigned integers.\\n\\n    Result Type and the type of x and y must both be integer scalar or integer\\n    vector types. Result Type and operand types must have the same number of\\n    components with the same component width. Results are computed per\\n    component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.UMax %0, %1 : i32\\n    %3 = spirv.GL.UMax %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.UMin\",\n    \"summary\": \"Return minimum of two unsigned integer operands\",\n    \"description\": \"Result is y if y < x; otherwise result is x, where x and y are interpreted\\n    as unsigned integers.\\n\\n    Result Type and the type of x and y must both be integer scalar or integer\\n    vector types. Result Type and operand types must have the same number of\\n    components with the same component width. Results are computed per\\n    component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.GL.UMin %0, %1 : i32\\n    %3 = spirv.GL.UMin %0, %1 : vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"rhs\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.UnpackHalf2x16\",\n    \"summary\": \"Unpack 32-bit integer into two-component vector of 32-bit floats\",\n    \"description\": \"Result is the two-component floating-point vector with components obtained by\\n    unpacking a 32-bit unsigned integer into a pair of 16-bit values, interpreting\\n    those values as 16-bit floating-point numbers according to the OpenGL\\n    Specification, and converting them to 32-bit floating-point values. Subnormal\\n    numbers are either preserved or flushed to zero, consistently within an\\n    implementation.\\n\\n    The first component of the vector is obtained from the 16 least-significant bits\\n    of v; the second component is obtained from the 16 most-significant bits of v.\\n\\n    The RelaxedPrecision Decoration only affects the conversion step of the instruction.\\n\\n    The v operand must be a scalar with 32-bit integer type.\\n\\n    Result Type must be a vector of 2 components whose type is 32-bit floating point.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.GL.UnpackHalf2x16 %0 : i32 -> vector<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_Int32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfLengthAndType<[2], [SPIRV_Float32]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GL.UnpackSnorm4x8\",\n    \"summary\": \"Unpack 32-bit integer into four-component vector of normalized 32-bit floats\",\n    \"description\": \"First, unpacks a single 32-bit unsigned integer p into four 8-bit signed integers.\\n    Then, each component is converted to a normalized floating-point value to generate\\n    the result. The conversion for unpacked fixed-point value f to floating point is\\n    done as follows:\\n\\n    ```\\n    clamp(f / 127.0, -1, +1)\\n    ```\\n\\n    The first component of the result is extracted from the least significant bits of the\\n    input; the last component is extracted from the most significant bits.\\n\\n    The RelaxedPrecision Decoration only affects the conversion step of the instruction.\\n\\n    The p operand must be a scalar with 32-bit integer type.\\n\\n    Result Type must be a vector of 4 components whose type is 32-bit floating point.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GL.UnpackSnorm4x8 %1 : i32 -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_Int32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfLengthAndType<[4], [SPIRV_Float32]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GlobalVariable\",\n    \"summary\": \"Allocate an object in memory at module scope. The object is\\n    referenced using a symbol name.\",\n    \"description\": \"The variable type must be an OpTypePointer. Its type operand is the type of\\n    object in memory.\\n\\n    Storage Class is the Storage Class of the memory holding the object. It\\n    cannot be Generic. It must be the same as the Storage Class operand of\\n    the variable types. Only those storage classes that are valid at module\\n    scope (like Input, Output, StorageBuffer, etc.) are valid.\\n\\n    Initializer is optional.  If Initializer is present, it will be\\n    the initial value of the variable’s memory content. Initializer\\n    must be an symbol defined from a constant instruction or other\\n    `spirv.GlobalVariable` operation in module scope. Initializer must\\n    have the same type as the type of the defined symbol.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    variable-op ::= `spirv.GlobalVariable` spirv-type symbol-ref-id\\n                    (`initializer(` symbol-ref-id `)`)?\\n                    (`bind(` integer-literal, integer-literal `)`)?\\n                    (`built_in(` string-literal `)`)?\\n                    attribute-dict?\\n    ```\\n\\n    where `initializer` specifies initializer and `bind` specifies the\\n    descriptor set and binding number. `built_in` specifies SPIR-V\\n    BuiltIn decoration associated with the op.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.GlobalVariable @var0 : !spirv.ptr<f32, Input>\\n    spirv.GlobalVariable @var1 initializer(@var0) : !spirv.ptr<f32, Output>\\n    spirv.GlobalVariable @var2 bind(1, 2) : !spirv.ptr<f32, Uniform>\\n    spirv.GlobalVariable @var3 built_in(\\\"GlobalInvocationId\\\") : !spirv.ptr<vector<3xi32>, Input>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"initializer\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"location\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"binding\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"descriptor_set\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"built_in\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"linkage_attributes\", \"type\": \"OptionalAttr<SPIRV_LinkageAttributesAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GLSL.Fma\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"spirv.GroupBroadcast\",\n    \"summary\": \"Broadcast the Value of the invocation identified by the local id LocalId\\n    to the result of all invocations in the group.\",\n    \"description\": \"All invocations of this module within Execution must reach this point of\\n    execution.\\n\\n    Behavior is undefined if this instruction is used in control flow that\\n    is non-uniform within Execution.\\n\\n    Result Type  must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    LocalId must be an integer datatype. It can be a scalar, or a vector\\n    with 2 components or a vector with 3 components. LocalId must be the\\n    same for all invocations in the group.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %scalar_value = ... : f32\\n    %vector_value = ... : vector<4xf32>\\n    %scalar_localid = ... : i32\\n    %vector_localid = ... : vector<3xi32>\\n    %0 = spirv.GroupBroadcast <Subgroup> %scalar_value, %scalar_localid : f32, i32\\n    %1 = spirv.GroupBroadcast <Workgroup> %vector_value, %vector_localid :\\n      vector<4xf32>, vector<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" },\n      { \"name\": \"localid\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value) `,` type($localid)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupFAdd\",\n    \"summary\": \"A floating-point add group operation specified for all values of X\\n    specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupFAdd <Workgroup> <Reduce> %value : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupFMax\",\n    \"summary\": \"A floating-point maximum group operation specified for all values of X\\n    specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is -INF.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupFMax <Workgroup> <Reduce> %value : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupFMin\",\n    \"summary\": \"A floating-point minimum group operation specified for all values of X\\n    specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is +INF.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupFMin <Workgroup> <Reduce> %value : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupIAdd\",\n    \"summary\": \"An integer add group operation specified for all values of X specified\\n    by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupIAdd <Workgroup> <Reduce> %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformAll\",\n    \"summary\": \"Evaluates a predicate for all tangled invocations within the Execution\\n    scope, resulting in true if predicate evaluates to true for all tangled\\n    invocations within the Execution scope, otherwise the result is false.\",\n    \"description\": \"Result Type must be a Boolean type.\\n\\n    Execution is the scope defining the scope restricted tangle affected by\\n    this command. It must be Subgroup.\\n\\n    Predicate must be a Boolean type.\\n\\n    An invocation will not execute a dynamic instance of this instruction\\n    (X') until all invocations in its scope restricted tangle have executed\\n    all dynamic instances that are program-ordered before X'.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %predicate = ... : i1\\n    %0 = spirv.GroupNonUniformAll <Subgroup> %predicate : i1\\n    ```\",\n    \"operands\": [\n      { \"name\": \"predicate\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $predicate attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformAllEqual\",\n    \"summary\": \"Evaluates a value for all tangled invocations within the Execution\\n    scope. The result is true if Value is equal for all tangled invocations\\n    within the Execution scope. Otherwise, the result is false.\",\n    \"description\": \"Result Type must be a Boolean type.\\n\\n    Execution is the scope defining the scope restricted tangle affected by\\n    this command. It must be Subgroup.\\n\\n    Value must be a scalar or vector of floating-point type, integer type,\\n    or Boolean type. The compare operation is based on this type, and if it\\n    is a floating-point type, an ordered-and-equal compare is used.\\n\\n    An invocation will not execute a dynamic instance of this instruction\\n    (X') until all invocations in its scope restricted tangle have executed\\n    all dynamic instances that are program-ordered before X'.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %scalar_value = ... : f32\\n    %vector_value = ... : vector<4xf32>\\n    %0 = spirv.GroupNonUniformAllEqual <Subgroup> %scalar_value : f32, i1\\n    %1 = spirv.GroupNonUniformAllEqual <Subgroup> %vector_value : vector<4xf32>, i1\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $value attr-dict `:` type($value) `,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformAny\",\n    \"summary\": \"Evaluates a predicate for all tangled invocations within the Execution\\n    scope, resulting in true if predicate evaluates to true for any tangled\\n    invocations within the Execution scope, otherwise the result is false.\",\n    \"description\": \"Result Type must be a Boolean type.\\n\\n    Execution is the scope defining the scope restricted tangle affected by\\n    this command. It must be Subgroup.\\n\\n    Predicate must be a Boolean type.\\n\\n    An invocation will not execute a dynamic instance of this instruction\\n    (X') until all invocations in its scope restricted tangle have executed\\n    all dynamic instances that are program-ordered before X'.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %predicate = ... : i1\\n    %0 = spirv.GroupNonUniformAny <Subgroup> %predicate : i1\\n    ```\",\n    \"operands\": [\n      { \"name\": \"predicate\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $predicate attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBallot\",\n    \"summary\": \"Result is a bitfield value combining the Predicate value from all\\n    invocations in the group that execute the same dynamic instance of this\\n    instruction. The bit is set to one if the corresponding invocation is\\n    active and the Predicate for that invocation evaluated to true;\\n    otherwise, it is set to zero.\",\n    \"description\": \"Result Type  must be a vector of four components of integer type scalar,\\n    whose Signedness operand is 0.\\n\\n    Result is a set of bitfields where the first invocation is represented\\n    in the lowest bit of the first vector component and the last (up to the\\n    size of the group) is the higher bit number of the last bitmask needed\\n    to represent all bits of the group invocations.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    Predicate must be a Boolean type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformBallot <Subgroup> %predicate : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"predicate\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_IOrUIVec4\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $predicate attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBallotBitCount\",\n    \"summary\": \"Result is the number of bits that are set to 1 in Value, considering\\n    only the bits in Value required to represent all bits of the scope\\n    restricted tangle.\",\n    \"description\": \"Result Type must be a scalar of integer type, whose Signedness operand\\n    is 0.\\n\\n    Execution is the scope defining the scope restricted tangle affected by\\n    this command. It must be Subgroup.\\n\\n    The identity I for Operation is 0.\\n\\n    Value must be a vector of four components of integer type scalar, whose\\n    Width operand is 32 and whose Signedness operand is 0.\\n\\n    Value is a set of bitfields where the first invocation is represented in\\n    the lowest bit of the first vector component and the last (up to the\\n    size of the scope) is the higher bit number of the last bitmask needed\\n    to represent all bits of the invocations in the scope restricted tangle.\\n\\n    An invocation will not execute a dynamic instance of this instruction\\n    (X') until all invocations in its scope restricted tangle have executed\\n    all dynamic instances that are program-ordered before X'.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %count = spirv.GroupNonUniformBallotBitCount <Subgroup> <Reduce> %val : vector<4xi32> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_Vec4<SignlessOrUnsignedIntOfWidths<[ 32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_SignlessOrUnsignedInt\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value attr-dict `:` type($value) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBallotFindLSB\",\n    \"summary\": \"Find the least significant bit set to 1 in Value, considering only the\\n    bits in Value required to represent all bits of the group's invocations.\\n    If none of the considered bits is set to 1, the resulting value is\\n    undefined.\",\n    \"description\": \"Result Type must be a scalar of integer type, whose Signedness operand\\n    is 0.\\n\\n    Execution is a Scope that identifies the group of invocations affected\\n    by this command. It must be Subgroup.\\n\\n    Value must be a vector of four components of integer type scalar, whose\\n    Width operand is 32 and whose Signedness operand is 0.\\n\\n    Value is a set of bitfields where the first invocation is represented in\\n    the lowest bit of the first vector component and the last (up to the\\n    size of the group) is the higher bit number of the last bitmask needed\\n    to represent all bits of the group invocations.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformBallotFindLSB <Subgroup> %vector : vector<4xi32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_IOrUIVec4\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_SignlessOrUnsignedInt\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $value attr-dict `:` type($value) `,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBallotFindMSB\",\n    \"summary\": \"Find the most significant bit set to 1 in Value, considering only the\\n    bits in Value required to represent all bits of the group's invocations.\\n    If none of the considered bits is set to 1, the resulting value is\\n    undefined.\",\n    \"description\": \"Result Type must be a scalar of integer type, whose Signedness operand\\n    is 0.\\n\\n    Execution is a Scope that identifies the group of invocations affected\\n    by this command. It must be Subgroup.\\n\\n    Value must be a vector of four components of integer type scalar, whose\\n    Width operand is 32 and whose Signedness operand is 0.\\n\\n    Value is a set of bitfields where the first invocation is represented in\\n    the lowest bit of the first vector component and the last (up to the\\n    size of the group) is the higher bit number of the last bitmask needed\\n    to represent all bits of the group invocations.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformBallotFindMSB <Subgroup> %vector : vector<4xi32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_IOrUIVec4\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_SignlessOrUnsignedInt\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $value attr-dict `:` type($value) `,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBitwiseAnd\",\n    \"summary\": \"A bitwise `and` group operation of all Value operands contributed by active\\n    invocations in the group.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is ~0. If Operation is ClusteredReduce,\\n    ClusterSize must be present.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformBitwiseAnd <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformBitwiseAnd <Subgroup> <ClusteredReduce>\\n           %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBitwiseOr\",\n    \"summary\": \"A bitwise `or` group operation of all Value operands contributed by active\\n    invocations in the group.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be present.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformBitwiseOr <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformBitwiseOr <Subgroup> <ClusteredReduce>\\n           %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBitwiseXor\",\n    \"summary\": \"A bitwise `xor` group operation of all Value operands contributed by active\\n    invocations in the group.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be present.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformBitwiseXor <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformBitwiseXor <Subgroup> <ClusteredReduce>\\n           %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBroadcast\",\n    \"summary\": \"Result is the Value of the invocation identified by the id Id to all\\n    active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    Id  must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    Before version 1.5, Id must come from a constant instruction. Starting\\n    with version 1.5, Id must be dynamically uniform.\\n\\n    The resulting value is undefined if Id is an inactive invocation, or is\\n    greater than or equal to the size of the group.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %scalar_value = ... : f32\\n    %vector_value = ... : vector<4xf32>\\n    %id = ... : i32\\n    %0 = spirv.GroupNonUniformBroadcast <Subgroup> %scalar_value, %id : f32, i32\\n    %1 = spirv.GroupNonUniformBroadcast <Workgroup> %vector_value, %id :\\n      vector<4xf32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" },\n      { \"name\": \"id\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value) `,` type($id)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformBroadcastFirst\",\n    \"summary\": \"Broadcast the value from the active invocation with the lowest id in\\n    the subgroup.\",\n    \"description\": \"Result is the Value of the invocation from the active invocations with\\n    the lowest id within the Execution scope to all active invocations\\n    within the Execution scope.\\n\\n    Result Type must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution must be Subgroup Scope.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %scalar_value = ... : f32\\n    %vector_value = ... : vector<4xf32>\\n    %0 = spirv.GroupNonUniformBroadcastFirst <Subgroup> %scalar_value : f32\\n    %1 = spirv.GroupNonUniformBroadcastFirst <Subgroup> %vector_value : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformElect\",\n    \"summary\": \"Result is true only in the active invocation with the lowest id in the\\n    group, otherwise result is false.\",\n    \"description\": \"Result Type must be a Boolean type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformElect <Workgroup> : i1\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformFAdd\",\n    \"summary\": \"A floating point add group operation of all Value operands contributed\\n    by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.  The method used to\\n    perform the group operation on the contributed Value(s) from active\\n    invocations is implementation defined.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : f32\\n    %vector = ... : vector<4xf32>\\n    %0 = spirv.GroupNonUniformFAdd <Workgroup> <Reduce> %scalar : f32 -> f32\\n    %1 = spirv.GroupNonUniformFAdd <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xf32>, i32 -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformFMax\",\n    \"summary\": \"A floating point maximum group operation of all Value operands\\n    contributed by active invocations in by group.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is -INF. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.  The method used to\\n    perform the group operation on the contributed Value(s) from active\\n    invocations is implementation defined. From the set of Value(s) provided\\n    by active invocations within a subgroup, if for any two Values one of\\n    them is a NaN, the other is chosen. If all Value(s) that are used by the\\n    current invocation are NaN, then the result is an undefined value.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : f32\\n    %vector = ... : vector<4xf32>\\n    %0 = spirv.GroupNonUniformFMax <Workgroup> <Reduce> %scalar : f32 -> f32\\n    %1 = spirv.GroupNonUniformFMax <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xf32>, i32 -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformFMin\",\n    \"summary\": \"A floating point minimum group operation of all Value operands\\n    contributed by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is +INF. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.  The method used to\\n    perform the group operation on the contributed Value(s) from active\\n    invocations is implementation defined. From the set of Value(s) provided\\n    by active invocations within a subgroup, if for any two Values one of\\n    them is a NaN, the other is chosen. If all Value(s) that are used by the\\n    current invocation are NaN, then the result is an undefined value.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : f32\\n    %vector = ... : vector<4xf32>\\n    %0 = spirv.GroupNonUniformFMin <Workgroup> <Reduce> %scalar : f32 -> i32\\n    %1 = spirv.GroupNonUniformFMin <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xf32>, i32 -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformFMul\",\n    \"summary\": \"A floating point multiply group operation of all Value operands\\n    contributed by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is 1. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.  The method used to\\n    perform the group operation on the contributed Value(s) from active\\n    invocations is implementation defined.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : f32\\n    %vector = ... : vector<4xf32>\\n    %0 = spirv.GroupNonUniformFMul <Workgroup> <Reduce> %scalar : f32 -> f32\\n    %1 = spirv.GroupNonUniformFMul <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xf32>, i32 -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformIAdd\",\n    \"summary\": \"An integer add group operation of all Value operands contributed by\\n    active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of integer type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformIAdd <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformIAdd <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformIMul\",\n    \"summary\": \"An integer multiply group operation of all Value operands contributed by\\n    active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of integer type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is 1. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformIMul <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformIMul <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformLogicalAnd\",\n    \"summary\": \"A logical `and` group operation of all Value operands contributed by active\\n    invocations in the group.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is ~0. If Operation is ClusteredReduce,\\n    ClusterSize must be present.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i1\\n    %vector = ... : vector<4xi1>\\n    %0 = spirv.GroupNonUniformLogicalAnd <Workgroup> <Reduce> %scalar : i1 -> i1\\n    %1 = spirv.GroupNonUniformLogicalAnd <Subgroup> <ClusteredReduce>\\n           %vector cluster_size(%four) : vector<4xi1>, i32 -> vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformLogicalOr\",\n    \"summary\": \"A logical `or` group operation of all Value operands contributed by active\\n    invocations in the group.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be present.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i1\\n    %vector = ... : vector<4xi1>\\n    %0 = spirv.GroupNonUniformLogicalOr <Workgroup> <Reduce> %scalar : i1 -> i1\\n    %1 = spirv.GroupNonUniformLogicalOr <Subgroup> <ClusteredReduce>\\n           %vector cluster_size(%four) : vector<4xi1>, i32 -> vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformLogicalXor\",\n    \"summary\": \"A logical `xor` group operation of all Value operands contributed by active\\n    invocations in the group.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be present.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i1\\n    %vector = ... : vector<4xi1>\\n    %0 = spirv.GroupNonUniformLogicalXor <Workgroup> <Reduce> %scalar : i1 -> i1\\n    %1 = spirv.GroupNonUniformLogicalXor <Subgroup> <ClusteredReduce>\\n           %vector cluster_size(%four) : vector<4xi1>, i32 -> vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformQuadSwap\",\n    \"summary\": \"Swap the Value of the invocation within the quad with another invocation\\n    in the quad using Direction.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type, integer type,\\n    or Boolean type.\\n\\n    Execution is a Scope, but has no effect on the behavior of this instruction.\\n    It must be Subgroup.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    Direction is the kind of swap to perform.\\n\\n    Direction must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    Direction must come from a constant instruction.\\n\\n    The value returned in Result is the value provided to Value by another invocation\\n    in the same quad scope instance. The invocation providing this value is\\n    determined according to Direction.\\n\\n    A Direction of 0 indicates a horizontal swap;\\n    - Invocations with quad indices of 0 and 1 swap values\\n    - Invocations with quad indices of 2 and 3 swap values\\n    A Direction of 1 indicates a vertical swap;\\n    - Invocations with quad indices of 0 and 2 swap values\\n    - Invocations with quad indices of 1 and 3 swap values\\n    A Direction of 2 indicates a diagonal swap;\\n    - Invocations with quad indices of 0 and 3 swap values\\n    - Invocations with quad indices of 1 and 2 swap values\\n\\n    Direction must be one of the above values.\\n\\n    If a tangled invocation within the quad reads Value from an invocation not part\\n    of the tangled invocation within the same quad, the resulting value is undefined.\\n\\n    An invocation will not execute a dynamic instance of this instruction (X') until\\n    all invocations in its quad have executed all dynamic instances that are program-ordered\\n    before X'.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformQuadSwap <Subgroup> <Horizontal> %value : f32\\n    %1 = spirv.GroupNonUniformQuadSwap <Subgroup> <Vertical> %value : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"direction\", \"type\": \"SPIRV_QuadSwapDirectionAttr{Horizontal|Vertical|Diagonal}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $direction $value attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformRotateKHR\",\n    \"summary\": \"Rotate values across invocations within a subgroup.\",\n    \"description\": \"Return the Value of the invocation whose id within the group is calculated\\n    as follows:\\n\\n    LocalId = SubgroupLocalInvocationId if Execution is Subgroup or\\n              LocalInvocationId if Execution is Workgroup\\n    RotationGroupSize = ClusterSize when ClusterSize is present, otherwise\\n    RotationGroupSize = SubgroupMaxSize if the Kernel capability is declared\\n                        and SubgroupSize if not.\\n    Invocation ID = ( (LocalId + Delta) & (RotationGroupSize - 1) ) +\\n                    (LocalId & ~(RotationGroupSize - 1))\\n\\n    Result Type must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The type of Value must be the same as Result Type.\\n\\n    Delta must be a scalar of integer type, whose Signedness operand is 0.\\n    Delta must be dynamically uniform within Execution.\\n\\n    Delta is treated as unsigned and the resulting value is undefined if the\\n    selected lane is inactive.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar of\\n    integer type, whose Signedness operand is 0. ClusterSize must come from a\\n    constant instruction. Behavior is undefined unless ClusterSize is at least\\n    1 and a power of 2. If ClusterSize is greater than the declared\\n    SubGroupSize, executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %0 = spirv.GroupNonUniformRotateKHR <Subgroup> %value, %delta : f32, i32 -> f32\\n    %1 = spirv.GroupNonUniformRotateKHR <Workgroup> %value, %delta,\\n         cluster_size(%four) : f32, i32, i32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" },\n      { \"name\": \"delta\", \"type\": \"SPIRV_SignlessOrUnsignedInt\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_SignlessOrUnsignedInt>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>, SPIRV_ScalarOrVectorOf<SPIRV_Bool>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $value `,` $delta (`,` `cluster_size` `(` $cluster_size^ `)`)? attr-dict `:` type($value) `,` type($delta) (`,` type($cluster_size)^)? `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformShuffle\",\n    \"summary\": \"Result is the Value of the invocation identified by the id Id.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    Id  must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    The resulting value is undefined if Id is an inactive invocation, or is\\n    greater than or equal to the size of the group.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformShuffle <Subgroup> %val, %id : f32, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVector\" },\n      { \"name\": \"id\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value) `,` type($id)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformShuffleDown\",\n    \"summary\": \"Result is the Value of the invocation identified by the current\\n    invocation’s id within the group + Delta.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    Delta  must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    Delta is treated as unsigned and the resulting value is undefined if\\n    Delta is greater than or equal to the size of the group, or if the\\n    current invocation’s id within the group + Delta is either an inactive\\n    invocation or greater than or equal to the size of the group.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformShuffleDown <Subgroup> %val, %delta : f32, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVector\" },\n      { \"name\": \"delta\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value) `,` type($delta)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformShuffleUp\",\n    \"summary\": \"Result is the Value of the invocation identified by the current\\n    invocation’s id within the group - Delta.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    Delta  must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    Delta is treated as unsigned and the resulting value is undefined if\\n    Delta is greater than the current invocation’s id within the group or if\\n    the selected lane is inactive.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformShuffleUp <Subgroup> %val, %delta : f32, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVector\" },\n      { \"name\": \"delta\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value) `,` type($delta)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformShuffleXor\",\n    \"summary\": \"Result is the Value of the invocation identified by the current\\n    invocation’s id within the group xor’ed with Mask.\",\n    \"description\": \"Result Type  must be a scalar or vector of floating-point type, integer\\n    type, or Boolean type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    Mask  must be a scalar of integer type, whose Signedness operand is 0.\\n\\n    The resulting value is undefined if current invocation’s id within the\\n    group xor’ed with Mask is an inactive invocation, or is greater than or\\n    equal to the size of the group.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupNonUniformShuffleXor <Subgroup> %val, %mask : f32, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVector\" },\n      { \"name\": \"mask\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope operands attr-dict `:` type($value) `,` type($mask)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformSMax\",\n    \"summary\": \"A signed integer maximum group operation of all Value operands\\n    contributed by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of integer type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is INT_MIN. If Operation is\\n    ClusteredReduce, ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformSMax <Workgroup> <Reduce> %scalar : i32\\n    %1 = spirv.GroupNonUniformSMax <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformSMin\",\n    \"summary\": \"A signed integer minimum group operation of all Value operands\\n    contributed by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of integer type.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is INT_MAX. If Operation is\\n    ClusteredReduce, ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformSMin <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformSMin <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformUMax\",\n    \"summary\": \"An unsigned integer maximum group operation of all Value operands\\n    contributed by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of integer type, whose\\n    Signedness operand is 0.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is 0. If Operation is ClusteredReduce,\\n    ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformUMax <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformUMax <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupNonUniformUMin\",\n    \"summary\": \"An unsigned integer minimum group operation of all Value operands\\n    contributed by active invocations in the group.\",\n    \"description\": \"Result Type  must be a scalar or vector of integer type, whose\\n    Signedness operand is 0.\\n\\n    Execution must be Workgroup or Subgroup Scope.\\n\\n    The identity I for Operation is UINT_MAX. If Operation is\\n    ClusteredReduce, ClusterSize must be specified.\\n\\n     The type of Value must be the same as Result Type.\\n\\n    ClusterSize is the size of cluster to use. ClusterSize must be a scalar\\n    of integer type, whose Signedness operand is 0. ClusterSize must come\\n    from a constant instruction. ClusterSize must be at least 1, and must be\\n    a power of 2. If ClusterSize is greater than the declared SubGroupSize,\\n    executing this instruction results in undefined behavior.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %four = spirv.Constant 4 : i32\\n    %scalar = ... : i32\\n    %vector = ... : vector<4xi32>\\n    %0 = spirv.GroupNonUniformUMin <Workgroup> <Reduce> %scalar : i32 -> i32\\n    %1 = spirv.GroupNonUniformUMin <Subgroup> <ClusteredReduce> %vector cluster_size(%four) : vector<4xi32>, i32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"cluster_size\", \"type\": \"Optional<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation $value (`cluster_size``(` $cluster_size^ `)`)? attr-dict `:` type($value) (`,` type($cluster_size)^)? `->` type(results)\"\n  },\n  {\n    \"name\": \"spirv.GroupSMax\",\n    \"summary\": \"A signed integer maximum group operation specified for all values of X\\n    specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is INT_MIN when X is 32 bits wide and\\n    LONG_MIN when X is 64 bits wide.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupSMax <Workgroup> <Reduce> %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupSMin\",\n    \"summary\": \"A signed integer minimum group operation specified for all values of X\\n    specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is INT_MAX when X is 32 bits wide and\\n    LONG_MAX when X is 64 bits wide.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupSMin <Workgroup> <Reduce> %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupUMax\",\n    \"summary\": \"An unsigned integer maximum group operation specified for all values of\\n    X specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is 0.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupUMax <Workgroup> <Reduce> %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.GroupUMin\",\n    \"summary\": \"An unsigned integer minimum group operation specified for all values of\\n    X specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    Execution reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within Execution execute\\n    the same dynamic instance of this instruction.\\n\\n    Result Type  must be a scalar or vector of integer type.\\n\\n    Execution is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for Operation is UINT_MAX when X is 32 bits wide and\\n    ULONG_MAX when X is 64 bits wide.\\n\\n    The type of X must be the same as Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.GroupUMin <Workgroup> <Reduce> %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IAdd\",\n    \"summary\": \"Integer addition of Operand 1 and Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same number of components as Result\\n    Type. They must have the same component width as Result Type.\\n\\n    The resulting value will equal the low-order N bits of the correct\\n    result R, where N is the component width and R is computed with enough\\n    precision to avoid overflow and underflow.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.IAdd %0, %1 : i32\\n    %5 = spirv.IAdd %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IAddCarry\",\n    \"summary\": \"Integer addition of Operand 1 and Operand 2, including the carry.\",\n    \"description\": \"Result Type must be from OpTypeStruct.  The struct must have two\\n    members, and the two members must be the same type.  The member type\\n    must be a scalar or vector of integer type, whose Signedness operand is\\n    0.\\n\\n    Operand 1 and Operand 2 must have the same type as the members of Result\\n    Type. These are consumed as unsigned integers.\\n\\n     Results are computed per component.\\n\\n    Member 0 of the result gets the low-order bits (full component width) of\\n    the addition.\\n\\n    Member 1 of the result gets the high-order (carry) bit of the result of\\n    the addition. That is, it gets the value 1 if the addition overflowed\\n    the component width, and 0 otherwise.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.IAddCarry %0, %1 : !spirv.struct<(i32, i32)>\\n    %2 = spirv.IAddCarry %0, %1 : !spirv.struct<(vector<2xi32>, vector<2xi32>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyStruct\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IEqual\",\n    \"summary\": \"Integer comparison for equality.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.IEqual %0, %1 : i32\\n    %5 = spirv.IEqual %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Image\",\n    \"summary\": \"Extract the image from a sampled image.\",\n    \"description\": \"Result Type must be OpTypeImage.\\n\\n    Sampled Image must have type OpTypeSampledImage whose Image Type is the\\n    same as Result Type.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Image %1 : !spirv.sampled_image<!spirv.image<f32, Cube, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sampled_image\", \"type\": \"SPIRV_AnySampledImage\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyImage\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'sampled_image', 'result', '::llvm::cast<spirv::SampledImageType>($_self).getImageType()'>\" }\n    ],\n    \"assemblyFormat\": \"$sampled_image attr-dict `:` type($sampled_image)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageDrefGather\",\n    \"summary\": \"Gathers the requested depth-comparison from four texels.\",\n    \"description\": \"Result Type must be a vector of four components of floating-point type\\n    or integer type. Its components must be the same as Sampled Type of the\\n    underlying OpTypeImage (unless that underlying Sampled Type is\\n    OpTypeVoid). It has one component per gathered texel.\\n\\n    Sampled Image must be an object whose type is OpTypeSampledImage. Its\\n    OpTypeImage must have a Dim of 2D, Cube, or Rect. The MS operand of the\\n    underlying OpTypeImage must be 0.\\n\\n    Coordinate must be a scalar or vector of floating-point type. It\\n    contains (u[, v] ... [, array layer]) as needed by the definition of\\n    Sampled Image.\\n\\n    Dref is the depth-comparison reference value. It must be a 32-bit\\n    floating-point type scalar.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.ImageDrefGather %1, %2, %3 : !spirv.sampled_image<!spirv.image<i32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>>, vector<4xf32>, f32 -> vector<4xi32>\\n    %0 = spirv.ImageDrefGather %1, %2, %3 [\\\"NonPrivateTexel\\\"] : !spirv.sampled_image<!spirv.image<i32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>>, vector<4xf32>, f32 -> vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sampled_image\", \"type\": \"SPIRV_AnySampledImage\" },\n      { \"name\": \"coordinate\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"dref\", \"type\": \"SPIRV_Float32\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_Vec4<SPIRV_Integer>, SPIRV_Vec4<SPIRV_Float>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"OptionalAttr<SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}>\" }\n    ],\n    \"assemblyFormat\": \"$sampled_image `,` $coordinate `,` $dref custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n    `:` type($sampled_image) `,` type($coordinate) `,` type($dref) ( `,` type($operand_arguments)^ )?\\n    `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageFetch\",\n    \"summary\": \"Fetch a single texel from an image whose Sampled operand is 1.\",\n    \"description\": \"Result Type must be a vector of four components of floating-point type or\\n    integer type. Its components must be the same as Sampled Type of the underlying\\n    OpTypeImage (unless that underlying Sampled Type is OpTypeVoid).\\n\\n    Image must be an object whose type is OpTypeImage. Its Dim operand must not be\\n    Cube, and its Sampled operand must be 1.\\n\\n    Coordinate must be a scalar or vector of integer type. It contains (u[, v] … [,\\n    array layer]) as needed by the definition of Sampled Image.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.ImageFetch %1, %2 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, R32f>, vector<2xsi32> -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"SPIRV_AnyImage\" },\n      { \"name\": \"coordinate\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_Vec4<SPIRV_Float>, SPIRV_Vec4<SPIRV_Integer>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"OptionalAttr<SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}>\" }\n    ],\n    \"assemblyFormat\": \"$image `,` $coordinate custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n    `:` type($image) `,` type($coordinate) ( `,` type($operand_arguments)^ )?\\n    `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageQuerySize\",\n    \"summary\": \"Query the dimensions of Image, with no level of detail.\",\n    \"description\": \"Result Type must be an integer type scalar or vector. The number of\\n    components must be:\\n\\n    1 for the 1D and Buffer dimensionalities,\\n\\n    2 for the 2D, Cube, and Rect dimensionalities,\\n\\n    3 for the 3D dimensionality,\\n\\n    plus 1 more if the image type is arrayed. This vector is filled in with\\n    (width [, height] [, elements]) where elements is the number of layers\\n    in an image array or the number of cubes in a cube-map array.\\n\\n    Image must be an object whose type is OpTypeImage. Its Dim operand must\\n    be one of those listed under Result Type, above. Additionally, if its\\n    Dim is 1D, 2D, 3D, or Cube, it must also have either an MS of 1 or a\\n    Sampled of 0 or 2. There is no implicit level-of-detail consumed by this\\n    instruction. See OpImageQuerySizeLod for querying images having level of\\n    detail. This operation is allowed on an image decorated as NonReadable.\\n    See the client API specification for additional image type restrictions.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %3 = spirv.ImageQuerySize %0 : !spirv.image<i32, Dim1D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown> -> i32\\n    %4 = spirv.ImageQuerySize %1 : !spirv.image<i32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown> -> vector<2xi32>\\n    %5 = spirv.ImageQuerySize %2 : !spirv.image<i32, Dim2D, NoDepth, Arrayed, SingleSampled, NoSampler, Unknown> -> vector<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"SPIRV_AnyImage\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"assemblyFormat\": \"$image attr-dict `:` type($image) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageRead\",\n    \"summary\": \"Read a texel from an image without a sampler.\",\n    \"description\": \"Result Type must be a scalar or vector of floating-point type or integer\\n    type. It must be a scalar or vector with component type the same as Sampled\\n    Type of the OpTypeImage (unless that Sampled Type is OpTypeVoid).\\n\\n    Image must be an object whose type is OpTypeImage with a Sampled operand of\\n    0 or 2. If the Arrayed operand is 1, then additional capabilities may be\\n    required; e.g., ImageCubeArray, or ImageMSArray.\\n\\n    Coordinate must be a scalar or vector of floating-point type or integer\\n    type. It contains non-normalized texel coordinates (u[, v] ... [, array\\n    layer]) as needed by the definition of Image. See the client API\\n    specification for handling of coordinates outside the image.\\n\\n    If the Image Dim operand is SubpassData, Coordinate is relative to the\\n    current fragment location. See the client API specification for more detail\\n    on how these coordinates are applied.\\n\\n    If the Image Dim operand is not SubpassData, the Image Format must not be\\n    Unknown, unless the StorageImageReadWithoutFormat Capability was declared.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.ImageRead %1, %2 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, R32f>, vector<2xsi32> -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"SPIRV_AnyImage\" },\n      { \"name\": \"coordinate\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"OptionalAttr<SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}>\" }\n    ],\n    \"assemblyFormat\": \"$image `,` $coordinate custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n    `:` type($image) `,` type($coordinate) ( `,` type($operand_arguments)^ )?\\n    `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageSampleExplicitLod\",\n    \"summary\": \"Sample an image using an explicit level of detail.\",\n    \"description\": \"Result Type must be a vector of four components of floating-point type\\n    or integer type. Its components must be the same as Sampled Type of the\\n    underlying OpTypeImage (unless that underlying Sampled Type is\\n    OpTypeVoid).\\n\\n    Sampled Image must be an object whose type is OpTypeSampledImage. Its\\n    OpTypeImage must not have a Dim of Buffer. The MS operand of the\\n    underlying OpTypeImage must be 0.\\n\\n    Coordinate must be a scalar or vector of floating-point type or integer\\n    type. It contains (u[, v] ... [, array layer]) as needed by the\\n    definition of Sampled Image. Unless the Kernel capability is declared,\\n    it must be floating point. It may be a vector larger than needed, but\\n    all unused components appear after all used components.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n    Either Lod or Grad image operands must be present.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %result = spirv.ImageSampleExplicitLod %image, %coord [\\\"Lod\\\"](%lod) :\\n      !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>,\\n      vector<2xf32> (f32) -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sampled_image\", \"type\": \"SPIRV_AnySampledImage\" },\n      { \"name\": \"coordinate\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_Vec4<SPIRV_Integer>, SPIRV_Vec4<SPIRV_Float>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}\" }\n    ],\n    \"assemblyFormat\": \"$sampled_image `,` $coordinate custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n      `:` type($sampled_image) `,` type($coordinate) ( `,` type($operand_arguments)^ )?\\n      `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageSampleImplicitLod\",\n    \"summary\": \"Sample an image with an implicit level of detail.\",\n    \"description\": \"An invocation will not execute a dynamic instance of this instruction\\n    (X') until all invocations in its derivative group have executed all\\n    dynamic instances that are program-ordered before X'.\\n\\n    Result Type must be a vector of four components of floating-point type\\n    or integer type. Its components must be the same as Sampled Type of the\\n    underlying OpTypeImage (unless that underlying Sampled Type is\\n    OpTypeVoid).\\n\\n    Sampled Image must be an object whose type is OpTypeSampledImage. Its\\n    OpTypeImage must not have a Dim of Buffer. The MS operand of the\\n    underlying OpTypeImage must be 0.\\n\\n    Coordinate must be a scalar or vector of floating-point type. It\\n    contains (u[, v] ... [, array layer]) as needed by the definition of\\n    Sampled Image. It may be a vector larger than needed, but all unused\\n    components appear after all used components.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n\\n    This instruction is only valid in the Fragment Execution Model. In\\n    addition, it consumes an implicit derivative that can be affected by\\n    code motion.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %result = spirv.ImageSampleImplicitLod %image, %coord :\\n      !spirv.sampled_image<!spirv.image<f32, Cube, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>,\\n      vector<3xf32> -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sampled_image\", \"type\": \"SPIRV_AnySampledImage\" },\n      { \"name\": \"coordinate\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_Vec4<SPIRV_Integer>, SPIRV_Vec4<SPIRV_Float>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"OptionalAttr<SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}>\" }\n    ],\n    \"assemblyFormat\": \"$sampled_image `,` $coordinate custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n      `:` type($sampled_image) `,` type($coordinate) ( `,` type($operand_arguments)^ )?\\n      `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageSampleProjDrefImplicitLod\",\n    \"summary\": \"Sample an image with a project coordinate, doing depth-comparison, with\\n    an implicit level of detail.\",\n    \"description\": \"An invocation will not execute a dynamic instance of this instruction\\n    (X') until all invocations in its derivative group have executed all\\n    dynamic instances that are program-ordered before X'.\\n\\n    Result Type must be a scalar of integer type or floating-point type. It\\n    must be the same as Sampled Type of the underlying OpTypeImage.\\n\\n    Sampled Image must be an object whose type is OpTypeSampledImage. The\\n    Dim operand of the underlying OpTypeImage must be 1D, 2D, 3D, or Rect,\\n    and the Arrayed and MS operands must be 0.\\n\\n    Coordinate must be a vector of floating-point type. It contains (u[,\\n    v] [, w], q), as needed by the definition of Sampled Image, with the q\\n    component consumed for the projective division. That is, the actual\\n    sample coordinate is (u/q [, v/q] [, w/q]), as needed by the definition\\n    of Sampled Image. It may be a vector larger than needed, but all unused\\n    components appear after all used components.\\n\\n    Dref/q is the depth-comparison reference value. Dref must be a 32-bit\\n    floating-point type scalar.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n\\n    This instruction is only valid in the Fragment Execution Model. In\\n    addition, it consumes an implicit derivative that can be affected by\\n    code motion.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %result = spirv.ImageSampleProjDrefImplicitLod %image, %coord, %dref :\\n      !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>,\\n      vector<4xf16>, f32 -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"sampled_image\", \"type\": \"SPIRV_AnySampledImage\" },\n      { \"name\": \"coordinate\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>\" },\n      { \"name\": \"dref\", \"type\": \"SPIRV_Float32\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[SPIRV_Integer, SPIRV_Float]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"OptionalAttr<SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'sampled_image', 'result', '::llvm::cast<::mlir::spirv::ImageType>(::llvm::cast<spirv::SampledImageType>($_self).getImageType()).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$sampled_image `,` $coordinate `,` $dref custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n      `:` type($sampled_image) `,` type($coordinate) `,` type($dref) ( `,` type($operand_arguments)^ )?\\n      `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ImageWrite\",\n    \"summary\": \"Write a texel to an image without a sampler.\",\n    \"description\": \"Image must be an object whose type is OpTypeImage with a Sampled operand\\n    of 0 or 2. If the Arrayed operand is 1, then additional capabilities may\\n    be required; e.g., ImageCubeArray, or ImageMSArray. Its Dim operand\\n    must not be SubpassData.\\n\\n    Coordinate must be a scalar or vector of floating-point type or integer\\n    type. It contains non-normalized texel coordinates (u[, v] ... [, array\\n    layer]) as needed by the definition of Image. See the client API\\n    specification for handling of coordinates outside the image.\\n\\n    Texel is the data to write. It must be a scalar or vector with component\\n    type the same as Sampled Type of the OpTypeImage (unless that Sampled\\n    Type is OpTypeVoid).\\n\\n    The Image Format must not be Unknown, unless the\\n    StorageImageWriteWithoutFormat Capability was declared.\\n\\n    Image Operands encodes what operands follow, as per Image Operands.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ImageWrite %0, %1, %2 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, vector<2xsi32>, vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"SPIRV_AnyImage\" },\n      { \"name\": \"coordinate\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>\" },\n      { \"name\": \"texel\", \"type\": \"AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>\" },\n      { \"name\": \"operand_arguments\", \"type\": \"Variadic<SPIRV_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"image_operands\", \"type\": \"OptionalAttr<SPIRV_ImageOperandsAttr{None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelVisible|NonPrivateTexel|VolatileTexel|SignExtend|Offsets|ZeroExtend|Nontemporal}>\" }\n    ],\n    \"assemblyFormat\": \"$image `,` $coordinate `,` $texel custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict\\n    `:` type($image) `,` type($coordinate) `,` type($texel) ( `,` type($operand_arguments)^ )?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IMul\",\n    \"summary\": \"Integer multiplication of Operand 1 and Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same number of components as Result\\n    Type. They must have the same component width as Result Type.\\n\\n    The resulting value will equal the low-order N bits of the correct\\n    result R, where N is the component width and R is computed with enough\\n    precision to avoid overflow and underflow.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.IMul %0, %1 : i32\\n    %5 = spirv.IMul %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.InBoundsPtrAccessChain\",\n    \"summary\": \"Has the same semantics as OpPtrAccessChain, with the addition that the\\n    resulting pointer is known to point within the base object.\",\n    \"description\": \"<!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    func @inbounds_ptr_access_chain(%arg0: !spirv.ptr<f32, CrossWorkgroup>, %arg1 : i64) -> () {\\n      %0 = spirv.InBoundsPtrAccessChain %arg0[%arg1] : !spirv.ptr<f32, CrossWorkgroup>, i64 -> !spirv.ptr<f32, CrossWorkgroup>\\n      ...\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base_ptr\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"element\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$base_ptr `[` $element ($indices^)? `]` attr-dict `:` type($base_ptr) `,` type($element) (`,` type($indices)^)? `->` type($result)\"\n  },\n  {\n    \"name\": \"spirv.INotEqual\",\n    \"summary\": \"Integer comparison for inequality.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.INotEqual %0, %1 : i32\\n    %5 = spirv.INotEqual %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.INTEL.ControlBarrierArrive\",\n    \"summary\": \"See extension SPV_INTEL_split_barrier\",\n    \"description\": \"Indicates that an invocation has arrived at a split control barrier. This\\n    may allow other invocations waiting on the split control barrier to continue\\n    executing.\\n\\n    When `Execution` is `Workgroup` or larger, behavior is undefined unless all\\n    invocations within `Execution` execute the same dynamic instance of this\\n    instruction. When `Execution` is `Subgroup` or `Invocation`, the behavior of\\n    this instruction in non-uniform control flow is defined by the client API.\\n\\n    If `Semantics` is not `None`, this instruction also serves as the start of a\\n    memory barrier similar to an `OpMemoryBarrier` instruction with the same\\n    `Memory` and `Semantics` operands. This allows atomically specifying both a\\n    control barrier and a memory barrier (that is, without needing two\\n    instructions). If `Semantics` is `None`, `Memory` is ignored.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ControlBarrierArrive <Workgroup> <Device> <Acquire|UniformMemory>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $memory_scope $memory_semantics attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.INTEL.ControlBarrierWait\",\n    \"summary\": \"See extension SPV_INTEL_split_barrier\",\n    \"description\": \"Waits for other invocations of this module to arrive at a split control\\n    barrier.\\n\\n    When `Execution` is `Workgroup` or larger, behavior is undefined unless all\\n    invocations within `Execution` execute the same dynamic instance of this\\n    instruction. When `Execution` is `Subgroup` or `Invocation`, the behavior of\\n    this instruction in non-uniform control flow is defined by the client API.\\n\\n    If `Semantics` is not `None`, this instruction also serves as the end of a\\n    memory barrier similar to an `OpMemoryBarrier` instruction with the same\\n    `Memory` and `Semantics` operands. This ensures that memory accesses issued\\n    before arriving at the split barrier are observed before memory accesses\\n    issued after this instruction. This control is ensured only for memory\\n    accesses issued by this invocation and observed by another invocation\\n    executing within `Memory` scope. This allows atomically specifying both a\\n    control barrier and a memory barrier (that is, without needing two\\n    instructions). If `Semantics` is `None`, `Memory` is ignored.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ControlBarrierWait <Workgroup> <Device> <Acquire|UniformMemory>\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $memory_scope $memory_semantics attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.INTEL.ConvertBF16ToF\",\n    \"summary\": \"See extension SPV_INTEL_bfloat16_conversion\",\n    \"description\": \"Interpret a 16-bit integer as bfloat16 and convert the value numerically to 32-bit floating point type.\\n\\n    Result Type must be a scalar or vector of floating-point. The component width must be 32 bits.\\n\\n    Bfloat16 Value must be a scalar or vector of integer type, which is interpreted as a bfloat16 type.\\n    The type must have the same number of components as the Result Type. The component width must be 16 bits.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertBF16ToF %0 : i16 to f32\\n    %3 = spirv.ConvertBF16ToF %2 : vector<3xi16> to vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Int16>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float32>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.INTEL.ConvertFToBF16\",\n    \"summary\": \"See extension SPV_INTEL_bfloat16_conversion\",\n    \"description\": \"Convert value numerically from 32-bit floating point to bfloat16,\\n    which is represented as a 16-bit unsigned integer.\\n\\n    Result Type must be a scalar or vector of integer type.\\n    The component width must be 16 bits. Bit pattern in the Result represents a bfloat16 value.\\n\\n    Float Value must be a scalar or vector of floating-point type.\\n    It must have the same number of components as Result Type. The component width must be 32 bits.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.ConvertFToBF16 %0 : f32 to i16\\n    %3 = spirv.ConvertFToBF16 %2 : vector<3xf32> to vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Int16>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.INTEL.RoundFToTF32\",\n    \"summary\": \"See extension SPV_INTEL_tensor_float32_conversion\",\n    \"description\": \"Convert value numerically from a 32-bit floating point type to tensor float32,\\n    with rounding to the nearest even.\\n\\n    Result Type must be a scalar or vector of 32-bit floating-point type.\\n    The component width must be 32 bits. Bit pattern in the Result represents a tensor float32 value.\\n\\n    Float Value must be a scalar or vector of floating-point type.\\n    It must have the same number of components as Result Type. The component width must be 32 bits.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.RoundFToTF32 %0 : f32 to f32\\n    %3 = spirv.RoundFToTF32 %2 : vector<3xf32> to vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float32>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.INTEL.SubgroupBlockRead\",\n    \"summary\": \"See extension SPV_INTEL_subgroups\",\n    \"description\": \"Reads one or more components of Result data for each invocation in the\\n    subgroup from the specified Ptr as a block operation.\\n\\n    The data is read strided, so the first value read is:\\n    Ptr[ SubgroupLocalInvocationId ]\\n\\n    and the second value read is:\\n    Ptr[ SubgroupLocalInvocationId + SubgroupMaxSize ]\\n    etc.\\n\\n    Result Type may be a scalar or vector type, and its component type must be\\n    equal to the type pointed to by Ptr.\\n\\n    The type of Ptr must be a pointer type, and must point to a scalar type.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    subgroup-block-read-INTEL-op ::= ssa-id `=` `spirv.INTEL.SubgroupBlockRead`\\n                                storage-class ssa_use `:` spirv-element-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.INTEL.SubgroupBlockRead \\\"StorageBuffer\\\" %ptr : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"assemblyFormat\": \"$ptr attr-dict `:` type($ptr) `->` type($value)\"\n  },\n  {\n    \"name\": \"spirv.INTEL.SubgroupBlockWrite\",\n    \"summary\": \"See extension SPV_INTEL_subgroups\",\n    \"description\": \"Writes one or more components of Data for each invocation in the subgroup\\n    from the specified Ptr as a block operation.\\n\\n    The data is written strided, so the first value is written to:\\n    Ptr[ SubgroupLocalInvocationId ]\\n\\n    and the second value written is:\\n    Ptr[ SubgroupLocalInvocationId + SubgroupMaxSize ]\\n    etc.\\n\\n    The type of Ptr must be a pointer type, and must point to a scalar type.\\n\\n    The component type of Data must be equal to the type pointed to by Ptr.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    subgroup-block-write-INTEL-op ::= ssa-id `=` `spirv.INTEL.SubgroupBlockWrite`\\n                      storage-class ssa_use `,` ssa-use `:` spirv-element-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.INTEL.SubgroupBlockWrite \\\"StorageBuffer\\\" %ptr, %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IsFinite\",\n    \"summary\": \"Result is true if x is an IEEE Finite, otherwise result is false\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    x must be a scalar or vector of floating-point type.  It must have the\\n    same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.IsFinite %0: f32\\n    %3 = spirv.IsFinite %1: vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IsInf\",\n    \"summary\": \"Result is true if x is an IEEE Inf, otherwise result is false\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    x must be a scalar or vector of floating-point type.  It must have the\\n    same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.IsInf %0: f32\\n    %3 = spirv.IsInf %1: vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.IsNan\",\n    \"summary\": \"Result is true if x is an IEEE NaN, otherwise result is false.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    x must be a scalar or vector of floating-point type.  It must have the\\n    same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.IsNan %0: f32\\n    %3 = spirv.IsNan %1: vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ISub\",\n    \"summary\": \"Integer subtraction of Operand 2 from Operand 1.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same number of components as Result\\n    Type. They must have the same component width as Result Type.\\n\\n    The resulting value will equal the low-order N bits of the correct\\n    result R, where N is the component width and R is computed with enough\\n    precision to avoid overflow and underflow.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.ISub %0, %1 : i32\\n    %5 = spirv.ISub %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ISubBorrow\",\n    \"summary\": \"Result is the unsigned integer subtraction of Operand 2 from Operand 1,\\n    and what it needed to borrow.\",\n    \"description\": \"Result Type must be from OpTypeStruct.  The struct must have two\\n    members, and the two members must be the same type.  The member type\\n    must be a scalar or vector of integer type, whose Signedness operand is\\n    0.\\n\\n    Operand 1 and Operand 2 must have the same type as the members of Result\\n    Type. These are consumed as unsigned integers.\\n\\n     Results are computed per component.\\n\\n    Member 0 of the result gets the low-order bits (full component width) of\\n    the subtraction. That is, if Operand 1 is larger than Operand 2, member\\n    0 gets the full value of the subtraction;  if Operand 2 is larger than\\n    Operand 1, member 0 gets 2w + Operand 1 - Operand 2, where w is the\\n    component width.\\n\\n    Member 1 of the result gets 0 if Operand 1 ≥ Operand 2, and gets 1\\n    otherwise.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.ISubBorrow %0, %1 : !spirv.struct<(i32, i32)>\\n    %2 = spirv.ISubBorrow %0, %1 : !spirv.struct<(vector<2xi32>, vector<2xi32>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyStruct\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.AssumeTrue\",\n    \"summary\": \"TBD\",\n    \"description\": \"<!-- End of AutoGen section -->\\n\\n    ```\\n    assumetruekhr-op ::= `spirv.KHR.AssumeTrue` ssa-use\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.KHR.AssumeTrue %arg\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"assemblyFormat\": \"$condition attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.CooperativeMatrixLength\",\n    \"summary\": \"Queries the number of cooperative matrix components\",\n    \"description\": \"Number of components of a cooperative matrix type accessible to each\\n    invocation when treated as a composite.\\n\\n    The type attribute must be a cooperative matrix type.\\n\\n    #### Example:\\n\\n    ```\\n    %0 = spirv.KHR.CooperativeMatrixLength :\\n           !spirv.coopmatrix<8x16xi32, Subgroup, MatrixA>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Int32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cooperative_matrix_type\", \"type\": \"TypeAttrOf<SPIRV_AnyCooperativeMatrix>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` $cooperative_matrix_type\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.CooperativeMatrixLoad\",\n    \"summary\": \"Loads a cooperative matrix through a pointer\",\n    \"description\": \"Load a cooperative matrix through a pointer.\\n\\n    Result Type is the type of the loaded object. It must be a cooperative\\n    matrix type.\\n\\n    Pointer is a pointer. Its type must be an OpTypePointer whose Type operand is\\n    a scalar or vector type. If the Shader capability was declared, Pointer must\\n    point into an array and any ArrayStride decoration on Pointer is ignored.\\n\\n    MemoryLayout specifies how matrix elements are laid out in memory. It must\\n    come from a 32-bit integer constant instruction whose value corresponds to a\\n    Cooperative Matrix Layout. See the Cooperative Matrix Layout table for a\\n    description of the layouts and detailed layout-specific rules.\\n\\n    Stride further qualifies how matrix elements are laid out in memory. It must\\n    be a scalar integer type and its exact semantics depend on MemoryLayout.\\n\\n    Memory Operand must be a Memory Operand literal. If not present, it is the\\n    same as specifying None.\\n\\n    NOTE: In earlier versions of the SPIR-V spec, 'Memory Operand' was known\\n    as 'Memory Access'.\\n\\n    For a given dynamic instance of this instruction, all operands of this\\n    instruction must be the same for all invocations in a given scope instance\\n    (where the scope is the scope the cooperative matrix type was created with).\\n    All invocations in a given scope instance must be active or all must be\\n    inactive.\\n\\n    TODO: In the SPIR-V spec, `stride` is an optional argument. We should also\\n    support this optionality in the SPIR-V dialect.\\n\\n    #### Example:\\n\\n    ```\\n    %0 = spirv.KHR.CooperativeMatrixLoad %ptr, %stride, <RowMajor>\\n         : !spirv.ptr<i32, StorageBuffer>, i32\\n             -> !spirv.KHR.coopmatrix<16x8xi32, Workgroup, MatrixA>\\n\\n    %1 = spirv.KHR.CooperativeMatrixLoad %ptr, %stride, <ColumnMajor>, <Volatile>\\n         : !spirv.ptr<f32, StorageBuffer>, i64\\n             -> !spirv.KHR.coopmatrix<8x8xf32, Subgroup, MatrixAcc>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"stride\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyCooperativeMatrix\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"matrix_layout\", \"type\": \"SPIRV_KHR_CooperativeMatrixLayoutAttr{RowMajor|ColumnMajor}\" },\n      { \"name\": \"memory_operand\", \"type\": \"OptionalAttr<SPIRV_MemoryAccessAttr{None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerVisible|NonPrivatePointer|AliasScopeINTELMask|NoAliasINTELMask}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I32Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$pointer `,` $stride `,` $matrix_layout ( `,` $memory_operand^ )? ( `,` $alignment^ )? attr-dict `:`\\n      type(operands) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.CooperativeMatrixMulAdd\",\n    \"summary\": \"Returns the result of `(A x B) + C` of matrices A, B, and C\",\n    \"description\": \"Linear-algebraic matrix multiply of A by B and then component-wise add C.\\n    The order of the operations is implementation-dependent. The internal\\n    precision of floating-point operations is defined by the client API. Integer\\n    operations used in the multiplication of A by B are performed at the\\n    precision of the Result Type and the resulting value will equal the\\n    low-order N bits of the correct result R, where N is the result width and R\\n    is computed with enough precision to avoid overflow and underflow if the\\n    SaturatingAccumulation Cooperative Matrix Operand is not present. If the\\n    SaturatingAccumulation Cooperative Matrix Operand is present and overflow or\\n    underflow occurs as part of calculating that intermediate result, the result\\n    of the instruction is undefined. Integer additions of the elements of that\\n    intermediate result with those of C are performed at the precision of Result\\n    Type, are exact, and are saturating if the SaturatingAccumulation\\n    Cooperative Matrix Operand is present, with the signedness of the saturation\\n    being that of the components of Result Type. If the SaturatingAccumulation\\n    Cooperative Matrix Operand is not present then the resulting value will\\n    equal the low-order N bits of the correct result R, where N is the result\\n    width and R is computed with enough precision to avoid overflow and\\n    underflow.\\n\\n    Result Type must be a cooperative matrix type with M rows and N columns\\n    whose Use must be MatrixAccumulatorKHR.\\n\\n    A is a cooperative matrix with M rows and K columns whose Use must be\\n    MatrixAKHR.\\n\\n    B is a cooperative matrix with K rows and N columns whose Use must be\\n    MatrixBKHR.\\n\\n    C is a cooperative matrix with M rows and N columns whose Use must be\\n    MatrixAccumulatorKHR.\\n\\n    The values of M, N, and K must be consistent across the result and operands.\\n    This is referred to as an MxNxK matrix multiply.\\n\\n    A, B, C, and Result Type must have the same scope, and this defines the\\n    scope of the operation. A, B, C, and Result Type need not necessarily have\\n    the same component type, this is defined by the client API.\\n\\n    If the Component Type of any matrix operand is an integer type, then its\\n    components are treated as signed if the Matrix{A,B,C,Result}SignedComponents\\n    Cooperative Matrix Operand is present and are treated as unsigned otherwise.\\n\\n    Cooperative Matrix Operands is an optional Cooperative Matrix Operand\\n    literal. If not present, it is the same as specifying the Cooperative Matrix\\n    Operand None.\\n\\n    For a given dynamic instance of this instruction, all invocations in a given\\n    scope instance must be active or all must be inactive (where the scope is\\n    the scope of the operation).\\n\\n    ``` {.ebnf}\\n    cooperative-matrixmuladd-op ::= ssa-id `=` `spirv.KHR.CooperativeMatrixMulAdd`\\n                              ssa-use `,` ssa-use `,` ssa-use\\n                              (`<` matrix-operands `>`)? `:`\\n                              a-cooperative-matrix-type `,`\\n                              b-cooperative-matrix-type `->`\\n                                result-cooperative-matrix-type\\n    ```\\n\\n    #### Example:\\n\\n    ```\\n    %0 = spirv.KHR.CooperativeMatrixMulAdd %matA, %matB, %matC :\\n      !spirv.coopmatrix<4x4xf32, Subgroup, MatrixA>,\\n      !spirv.coopmatrix<4x4xf32, Subgroup, MatrixB> ->\\n        !spirv.coopmatrix<4x4xf32, Subgroup, MatrixAcc>\\n\\n    %1 = spirv.KHR.CooperativeMatrixMulAdd %matA, %matB, %matC, <ASigned | AccSat> :\\n      !spirv.coopmatrix<8x16xi32, Subgroup, MatrixA>,\\n      !spirv.coopmatrix<16x4xi32, Subgroup, MatrixB> ->\\n        !spirv.coopmatrix<8x4xi32, Subgroup, MatrixAcc>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"SPIRV_AnyCooperativeMatrix\" },\n      { \"name\": \"b\", \"type\": \"SPIRV_AnyCooperativeMatrix\" },\n      { \"name\": \"c\", \"type\": \"SPIRV_AnyCooperativeMatrix\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyCooperativeMatrix\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"matrix_operands\", \"type\": \"OptionalAttr<SPIRV_KHR_CooperativeMatrixOperandsAttr{None|ASigned|BSigned|CSigned|ResultSigned|AccSat}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['c', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $c ( `,` $matrix_operands^ )? attr-dict `:`\\n      type($a) `,` type($b) `->` type($c)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.CooperativeMatrixStore\",\n    \"summary\": \"Stores a cooperative matrix through a pointer\",\n    \"description\": \"Store a cooperative matrix through a pointer.\\n    Pointer is a pointer. Its type must be an OpTypePointer whose Type operand\\n    is a scalar or vector type. If the Shader capability was declared, Pointer\\n    must point into an array and any ArrayStride decoration on Pointer is\\n    ignored.\\n\\n    Object is the object to store. Its type must be an\\n    OpTypeCooperativeMatrixKHR.\\n\\n    MemoryLayout specifies how matrix elements are laid out in memory. It must\\n    come from a 32-bit integer constant instruction whose value corresponds to a\\n    Cooperative Matrix Layout. See the Cooperative Matrix Layout table for a\\n    description of the layouts and detailed layout-specific rules.\\n\\n    Stride further qualifies how matrix elements are laid out in memory. It must\\n    be a scalar integer type and its exact semantics depend on MemoryLayout.\\n\\n    Memory Operand must be a Memory Operand literal. If not present, it is the\\n    same as specifying None.\\n\\n    NOTE: In earlier versions of the SPIR-V spec, 'Memory Operand' was known\\n    as 'Memory Access'.\\n\\n    For a given dynamic instance of this instruction, all operands of this\\n    instruction must be the same for all invocations in a given scope instance\\n    (where the scope is the scope the cooperative matrix type was created with).\\n    All invocations in a given scope instance must be active or all must be\\n    inactive.\\n\\n    TODO: In the SPIR-V spec, `stride` is an optional argument. We should also\\n    support this optionality in the SPIR-V dialect.\\n\\n    #### Example:\\n\\n    ```\\n      spirv.KHR.CooperativeMatrixStore %ptr, %obj, %stride, <RowMajor> :\\n        !spirv.ptr<i32, StorageBuffer>, !spirv.coopmatrix<16x8xi32, Workgroup, MatrixA>, i32\\n\\n      spirv.KHR.CooperativeMatrixStore %ptr, %obj, %stride, <ColumnMajor>, <Volatile> :\\n        !spirv.ptr<f32, StorageBuffer>, !spirv.coopmatrix<8x8xf32, Subgroup, MatrixAcc>, i64\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"object\", \"type\": \"SPIRV_AnyCooperativeMatrix\" },\n      { \"name\": \"stride\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"matrix_layout\", \"type\": \"SPIRV_KHR_CooperativeMatrixLayoutAttr{RowMajor|ColumnMajor}\" },\n      { \"name\": \"memory_operand\", \"type\": \"OptionalAttr<SPIRV_MemoryAccessAttr{None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerVisible|NonPrivatePointer|AliasScopeINTELMask|NoAliasINTELMask}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I32Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$pointer `,` $object `,` $stride `,` $matrix_layout ( `,` $memory_operand^ )? ( `,` $alignment^ )? attr-dict `:`\\n      type(operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.GroupFMul\",\n    \"summary\": \"A floating-point multiplication group operation specified for all values of\\n    'X' specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    'Execution' reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within 'Execution' execute the\\n    same dynamic instance of this instruction.\\n\\n    'Result Type' must be a scalar or vector of floating-point type.\\n\\n    'Execution' is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for 'Operation' is 1.\\n\\n    The type of 'X' must be the same as 'Result Type'.\\n\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.KHR.GroupFMul <Workgroup> <Reduce> %value : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.GroupIMul\",\n    \"summary\": \"An integer multiplication group operation specified for all values of 'X'\\n    specified by invocations in the group.\",\n    \"description\": \"Behavior is undefined if not all invocations of this module within\\n    'Execution' reach this point of execution.\\n\\n    Behavior is undefined unless all invocations within 'Execution' execute the\\n    same dynamic instance of this instruction.\\n\\n    'Result Type' must be a scalar or vector of integer type.\\n\\n    'Execution' is a Scope. It must be either Workgroup or Subgroup.\\n\\n    The identity I for 'Operation' is 1.\\n\\n    The type of 'X' must be the same as 'Result Type'.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.KHR.GroupIMul <Workgroup> <Reduce> %value : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"execution_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"group_operation\", \"type\": \"SPIRV_GroupOperationAttr{Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$execution_scope $group_operation operands attr-dict `:` type($x)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.KHR.SubgroupBallot\",\n    \"summary\": \"See extension SPV_KHR_shader_ballot\",\n    \"description\": \"Computes a bitfield value combining the Predicate value from all invocations\\n    in the current Subgroup that execute the same dynamic instance of this\\n    instruction. The bit is set to one if the corresponding invocation is active\\n    and the predicate is evaluated to true; otherwise, it is set to zero.\\n\\n    Predicate must be a Boolean type.\\n\\n    Result Type must be a 4 component vector of 32 bit integer types.\\n\\n    Result is a set of bitfields where the first invocation is represented in bit\\n    0 of the first vector component and the last (up to SubgroupSize) is the\\n    higher bit number of the last bitmask needed to represent all bits of the\\n    subgroup invocations.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    subgroup-ballot-op ::= ssa-id `=` `spirv.KHR.SubgroupBallot`\\n                                ssa-use `:` `vector` `<` 4 `x` `i32` `>`\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.KHR.SubgroupBallot %predicate : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"predicate\", \"type\": \"SPIRV_Bool\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Int32Vec4\" }\n    ],\n    \"assemblyFormat\": \"$predicate attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Kill\",\n    \"summary\": \"Deprecated (use OpTerminateInvocation or OpDemoteToHelperInvocation).\",\n    \"description\": \"Fragment-shader discard.\\n\\n    Ceases all further processing in any invocation that executes it: Only\\n    instructions these invocations executed before OpKill have observable\\n    side effects. If this instruction is executed in non-uniform control\\n    flow, all subsequent control flow is non-uniform (for invocations that\\n    continue to execute).\\n\\n    This instruction must be the last instruction in a block.\\n\\n    This instruction is only valid in the Fragment Execution Model.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.Kill\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Load\",\n    \"summary\": \"Load through a pointer.\",\n    \"description\": \"Result Type is the type of the loaded object. It must be a type with\\n    fixed size; i.e., it cannot be, nor include, any OpTypeRuntimeArray\\n    types.\\n\\n    Pointer is the pointer to load through.  Its type must be an\\n    OpTypePointer whose Type operand is the same as Result Type.\\n\\n    If present, any Memory Operands must begin with a memory operand\\n    literal. If not present, it is the same as specifying the memory operand\\n    None.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    memory-access ::= `\\\"None\\\"` | `\\\"Volatile\\\"` | `\\\"Aligned\\\", ` integer-literal\\n                    | `\\\"NonTemporal\\\"`\\n\\n    load-op ::= ssa-id ` = spirv.Load ` storage-class ssa-use\\n                (`[` memory-access `]`)? ` : ` spirv-element-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Variable : !spirv.ptr<f32, Function>\\n    %1 = spirv.Load \\\"Function\\\" %0 : f32\\n    %2 = spirv.Load \\\"Function\\\" %0 [\\\"Volatile\\\"] : f32\\n    %3 = spirv.Load \\\"Function\\\" %0 [\\\"Aligned\\\", 4] : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_access\", \"type\": \"OptionalAttr<SPIRV_MemoryAccessAttr{None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerVisible|NonPrivatePointer|AliasScopeINTELMask|NoAliasINTELMask}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I32Attr>>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.LogicalAnd\",\n    \"summary\": \"Result is true if both Operand 1 and Operand 2 are true. Result is false\\n    if either Operand 1 or Operand 2 are false.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 must be the same as Result Type.\\n\\n    The type of Operand 2 must be the same as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.LogicalAnd %0, %1 : i1\\n    %2 = spirv.LogicalAnd %0, %1 : vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.LogicalEqual\",\n    \"summary\": \"Result is true if Operand 1 and Operand 2 have the same value. Result is\\n    false if Operand 1 and Operand 2 have different values.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 must be the same as Result Type.\\n\\n    The type of Operand 2 must be the same as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.LogicalEqual %0, %1 : i1\\n    %2 = spirv.LogicalEqual %0, %1 : vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.LogicalNot\",\n    \"summary\": \"Result is true if Operand is false.  Result is false if Operand is true.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand must be the same as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.LogicalNot %0 : i1\\n    %2 = spirv.LogicalNot %0 : vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.LogicalNotEqual\",\n    \"summary\": \"Result is true if Operand 1 and Operand 2 have different values. Result\\n    is false if Operand 1 and Operand 2 have the same value.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 must be the same as Result Type.\\n\\n    The type of Operand 2 must be the same as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.LogicalNotEqual %0, %1 : i1\\n    %2 = spirv.LogicalNotEqual %0, %1 : vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.LogicalOr\",\n    \"summary\": \"Result is true if either Operand 1 or Operand 2 is true. Result is false\\n    if both Operand 1 and Operand 2 are false.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 must be the same as Result Type.\\n\\n    The type of Operand 2 must be the same as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.LogicalOr %0, %1 : i1\\n    %2 = spirv.LogicalOr %0, %1 : vector<4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.MatrixTimesMatrix\",\n    \"summary\": \"Linear-algebraic multiply of LeftMatrix X RightMatrix.\",\n    \"description\": \"Result Type must be an OpTypeMatrix whose Column Type is a vector of\\n    floating-point type.\\n\\n    LeftMatrix must be a matrix whose Column Type is the same as the Column\\n    Type in Result Type.\\n\\n    RightMatrix must be a matrix with the same Component Type as the\\n    Component Type in Result Type. Its number of columns must equal the\\n    number of columns in Result Type. Its columns must have the same number\\n    of components as the number of columns in LeftMatrix.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.MatrixTimesMatrix %matrix_1, %matrix_2 :\\n        !spirv.matrix<4 x vector<3xf32>>, !spirv.matrix<3 x vector<4xf32>> ->\\n        !spirv.matrix<4 x vector<4xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"leftmatrix\", \"type\": \"SPIRV_AnyMatrix\" },\n      { \"name\": \"rightmatrix\", \"type\": \"SPIRV_AnyMatrix\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyMatrix\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($leftmatrix) `,` type($rightmatrix) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.MatrixTimesScalar\",\n    \"summary\": \"Scale a floating-point matrix.\",\n    \"description\": \"Result Type must be a matrix type with a float component type.\\n\\n    The type of Matrix must be the same as Result Type. Each component in\\n    each column in Matrix is multiplied by Scalar.\\n\\n    Scalar must have the same type as the Component Type in Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.MatrixTimesScalar %matrix, %scalar :\\n    !spirv.matrix<3 x vector<3xf32>>, f32 -> !spirv.matrix<3 x vector<3xf32>>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"SPIRV_MatrixOrCoopMatrixOf<SPIRV_Float>\" },\n      { \"name\": \"scalar\", \"type\": \"SPIRV_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_MatrixOrCoopMatrixOf<SPIRV_Float>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['matrix', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($matrix) `,` type($scalar)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.MatrixTimesVector\",\n    \"summary\": \"Linear-algebraic Matrix X Vector.\",\n    \"description\": \"Result Type must be a vector of floating-point type.\\n\\n    Matrix must be an OpTypeMatrix whose Column Type is Result Type.\\n\\n    Vector must be a vector with the same Component Type as the Component Type in Result Type. Its number of components must equal the number of columns in Matrix.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.MatrixTimesVector %matrix, %vector : \\n        !spirv.matrix<3 x vector<2xf32>>, vector<3xf32> -> vector<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"SPIRV_MatrixOf<SPIRV_Float>\" },\n      { \"name\": \"vector\", \"type\": \"SPIRV_VectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_VectorOf<SPIRV_Float>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($matrix) `,` type($vector) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.MemoryBarrier\",\n    \"summary\": \"Control the order that memory accesses are observed.\",\n    \"description\": \"Ensures that memory accesses issued before this instruction will be\\n    observed before memory accesses issued after this instruction. This\\n    control is ensured only for memory accesses issued by this invocation\\n    and observed by another invocation executing within Memory scope. If the\\n    Vulkan memory model is declared, this ordering only applies to memory\\n    accesses that use the NonPrivatePointer memory operand or\\n    NonPrivateTexel image operand.\\n\\n    Semantics declares what kind of memory is being controlled and what kind\\n    of control to apply.\\n\\n    To execute both a memory barrier and a control barrier, see\\n    OpControlBarrier.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.MemoryBarrier \\\"Device\\\", \\\"Acquire|UniformMemory\\\"\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"memory_scope\", \"type\": \"SPIRV_ScopeAttr{CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|ShaderCallKHR}\" },\n      { \"name\": \"memory_semantics\", \"type\": \"SPIRV_MemorySemanticsAttr{None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|MakeAvailable|MakeVisible|Volatile}\" }\n    ],\n    \"assemblyFormat\": \"$memory_scope `,` $memory_semantics attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.mlir.addressof\",\n    \"summary\": \"Get the address of a global variable.\",\n    \"description\": \"Variables in module scope are defined using symbol names. This op generates\\n    an SSA value that can be used to refer to the symbol within function scope\\n    for use in ops that expect an SSA value. This operation has no corresponding\\n    SPIR-V instruction; it's merely used for modelling purpose in the SPIR-V\\n    dialect. Since variables in module scope in SPIR-V dialect are of pointer\\n    type, this op returns a pointer type as well, and the type is the same as\\n    the variable referenced.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.mlir.addressof @global_var : !spirv.ptr<f32, Input>\\n    ```\",\n    \"results\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"variable\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$variable attr-dict `:` type($pointer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.mlir.loop\",\n    \"summary\": \"Define a structured loop.\",\n    \"description\": \"SPIR-V can explicitly declare structured control-flow constructs using merge\\n    instructions. These explicitly declare a header block before the control\\n    flow diverges and a merge block where control flow subsequently converges.\\n    These blocks delimit constructs that must nest, and can only be entered\\n    and exited in structured ways. See \\\"2.11. Structured Control Flow\\\" of the\\n    SPIR-V spec for more details.\\n\\n    Instead of having a `spirv.LoopMerge` op to directly model loop merge\\n    instruction for indicating the merge and continue target, we use regions\\n    to delimit the boundary of the loop: the merge target is the next op\\n    following the `spirv.mlir.loop` op and the continue target is the block that\\n    has a back-edge pointing to the entry block inside the `spirv.mlir.loop`'s region.\\n    This way it's easier to discover all blocks belonging to a construct and\\n    it plays nicer with the MLIR system.\\n\\n    The `spirv.mlir.loop` region should contain at least four blocks: one entry block,\\n    one loop header block, one loop continue block, one loop merge block.\\n    The entry block should be the first block and it should jump to the loop\\n    header block, which is the second block. The loop merge block should be the\\n    last block. The merge block should only contain a `spirv.mlir.merge` op.\\n    The continue block should be the second to last block and it should have a\\n    branch to the loop header block. The loop continue block should be the only\\n    block, except the entry block, branching to the header block.\\n\\n    Values defined inside the loop regions cannot be directly used\\n    outside of them; however, the loop region can yield values. These values are\\n    yielded using a `spirv.mlir.merge` op and returned as a result of the loop op.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"loop_control\", \"type\": \"SPIRV_LoopControlAttr{None|Unroll|DontUnroll|DependencyInfinite|DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount|InitiationIntervalINTEL|LoopCoalesceINTEL|MaxConcurrencyINTEL|MaxInterleavingINTEL|DependencyArrayINTEL|SpeculatedIterationsINTEL|PipelineEnableINTEL|NoFusionINTEL}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.mlir.merge\",\n    \"summary\": \"A special terminator for merging a structured selection/loop.\",\n    \"description\": \"We use `spirv.mlir.selection`/`spirv.mlir.loop` for modelling structured selection/loop.\\n    This op is a terminator used inside their regions to mean jumping to the\\n    merge point, which is the next op following the `spirv.mlir.selection` or\\n    `spirv.mlir.loop` op. This op does not have a corresponding instruction in the\\n    SPIR-V binary format; it's solely for structural purpose.\\n\\n    The instruction is also used to yield values from inside the selection/loop region\\n    to the outside, as values that were sunk into the region cannot otherwise escape it.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.mlir.referenceof\",\n    \"summary\": \"Reference a specialization constant.\",\n    \"description\": \"Specialization constants in module scope are defined using symbol names.\\n    This op generates an SSA value that can be used to refer to the symbol\\n    within function scope for use in ops that expect an SSA value.\\n    This operation has no corresponding SPIR-V instruction; it's merely used\\n    for modelling purpose in the SPIR-V dialect. This op's return type is\\n    the same as the specialization constant.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.mlir.referenceof @spec_const : f32\\n    ```\\n\\n    TODO Add support for composite specialization constants.\",\n    \"results\": [\n      { \"name\": \"reference\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"spec_const\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$spec_const attr-dict `:` type($reference)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.mlir.selection\",\n    \"summary\": \"Define a structured selection.\",\n    \"description\": \"SPIR-V can explicitly declare structured control-flow constructs using merge\\n    instructions. These explicitly declare a header block before the control\\n    flow diverges and a merge block where control flow subsequently converges.\\n    These blocks delimit constructs that must nest, and can only be entered\\n    and exited in structured ways. See \\\"2.11. Structured Control Flow\\\" of the\\n    SPIR-V spec for more details.\\n\\n    Instead of having a `spirv.SelectionMerge` op to directly model selection\\n    merge instruction for indicating the merge target, we use regions to delimit\\n    the boundary of the selection: the merge target is the next op following the\\n    `spirv.mlir.selection` op. This way it's easier to discover all blocks belonging to\\n    the selection and it plays nicer with the MLIR system.\\n\\n    The `spirv.mlir.selection` region should contain at least two blocks: one selection\\n    header block, and one selection merge. The selection header block should be\\n    the first block. The selection merge block should be the last block.\\n    The merge block should only contain a `spirv.mlir.merge` op.\\n\\n    Values defined inside the selection regions cannot be directly used\\n    outside of them; however, the selection region can yield values. These values are\\n    yielded using a `spirv.mlir.merge` op and returned as a result of the selection op.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"selection_control\", \"type\": \"SPIRV_SelectionControlAttr{None|Flatten|DontFlatten}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.mlir.yield\",\n    \"summary\": \"Yields the result computed in `spirv.SpecConstantOperation`'s\\n    region back to the parent op.\",\n    \"description\": \"This op is a special terminator whose only purpose is to terminate\\n    an `spirv.SpecConstantOperation`'s enclosed region. It accepts a\\n    single operand produced by the preceeding (and only other) instruction\\n    in its parent block (see SPIRV_SpecConstantOperation for further\\n    details). This op has no corresponding SPIR-V instruction.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = ... (some op supported by SPIR-V OpSpecConstantOp)\\n    spirv.mlir.yield %0\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.module\",\n    \"summary\": \"The top-level op that defines a SPIR-V module\",\n    \"description\": \"This op defines a SPIR-V module using a MLIR region. The region contains\\n    one block. Module-level operations, including functions definitions,\\n    are all placed in this block.\\n\\n    Using an op with a region to define a SPIR-V module enables \\\"embedding\\\"\\n    SPIR-V modules in other dialects in a clean manner: this op guarantees\\n    the validity and serializability of a SPIR-V module and thus serves as\\n    a clear-cut boundary.\\n\\n    This op takes no operands and generates no results. This op should not\\n    implicitly capture values from the enclosing environment.\\n\\n    This op has only one region, which only contains one block. The block\\n    has no terminator.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    addressing-model ::= `Logical` | `Physical32` | `Physical64` | ...\\n    memory-model ::= `Simple` | `GLSL450` | `OpenCL` | `Vulkan` | ...\\n    spv-module-op ::= `spirv.module` addressing-model memory-model\\n                      (requires  spirv-vce-attribute)?\\n                      (`attributes` attribute-dict)?\\n                      region\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.module Logical GLSL450  {}\\n\\n    spirv.module Logical Vulkan\\n        requires #spirv.vce<v1.0, [Shader], [SPV_KHR_vulkan_memory_model]>\\n        attributes { some_additional_attr = ... } {\\n      spirv.func @do_nothing() -> () {\\n        spirv.Return\\n      }\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"addressing_model\", \"type\": \"SPIRV_AddressingModelAttr{Logical|Physical32|Physical64|PhysicalStorageBuffer64}\" },\n      { \"name\": \"memory_model\", \"type\": \"SPIRV_MemoryModelAttr{Simple|GLSL450|OpenCL|Vulkan}\" },\n      { \"name\": \"vce_triple\", \"type\": \"OptionalAttr<SPIRV_VerCapExtAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Not\",\n    \"summary\": \"Complement the bits of Operand.\",\n    \"description\": \"Results are computed per component, and within each component, per bit.\\n\\n    Result Type must be a scalar or vector of integer type.\\n\\n    Operand's type  must be a scalar or vector of integer type.  It must\\n    have the same number of components as Result Type.  The component width\\n    must equal the component width in Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.Not %0 : i32\\n    %3 = spirv.Not %1 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Ordered\",\n    \"summary\": \"Result is true if both x == x and y == y are true, where IEEE comparison\\n    is used, otherwise result is false.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    x must be a scalar or vector of floating-point type.  It must have the\\n    same number of components as Result Type.\\n\\n    y must have the same type as x.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.Ordered %0, %1 : f32\\n    %5 = spirv.Ordered %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.OuterProduct\",\n    \"summary\": \"Linear-algebraic outer product of vector1 and vector2.\",\n    \"description\": \"Result Type must be a Matrix Type whose Column Type is a vector of\\n    floating-point type.\\n\\n    Vector1 must have the same type as the Column Type in Result Type.\\n\\n    Vector2 must be a vector with the same Component Type as the Component\\n    Type in Result Type. Its number of components must equal the number of\\n    columns in Result Type.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.OuterProduct %vector1, %vector2 :\\n        vector<3xf32>, vector<2xf32> -> !spirv.matrix<2 x vector<3xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_VectorOf<SPIRV_Float>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_VectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_MatrixOf<SPIRV_Float>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vector1) `,` type($vector2) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.PtrAccessChain\",\n    \"summary\": \"Has the same semantics as OpAccessChain, with the addition of the\\n    Element operand.\",\n    \"description\": \"Element is used to do an initial dereference of Base: Base is treated as\\n    the address of an element in an array, and a new element address is\\n    computed from Base and Element to become the OpAccessChain Base to\\n    dereference as per OpAccessChain. This computed Base has the same type\\n    as the originating Base.\\n\\n    To compute the new element address, Element is treated as a signed count\\n    of elements E, relative to the original Base element B, and the address\\n    of element B + E is computed using enough precision to avoid overflow\\n    and underflow. For objects in the Uniform, StorageBuffer, or\\n    PushConstant storage classes, the element's address or location is\\n    calculated using a stride, which will be the Base-type's Array Stride if\\n    the Base type is decorated with ArrayStride. For all other objects, the\\n    implementation calculates the element's address or location.\\n\\n    With one exception, undefined behavior results when B + E is not an\\n    element in the same array (same innermost array, if array types are\\n    nested) as B. The exception being when B + E = L, where L is the length\\n    of the array: the address computation for element L is done with the\\n    same stride as any other B + E computation that stays within the array.\\n\\n    Note: If Base is typed to be a pointer to an array and the desired\\n    operation is to select an element of that array, OpAccessChain should be\\n    directly used, as its first Index selects the array element.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    func @ptr_access_chain(%arg0: !spirv.ptr<f32, CrossWorkgroup>, %arg1 : i64) -> () {\\n      %0 = spirv.PtrAccessChain %arg0[%arg1] : !spirv.ptr<f32, CrossWorkgroup>, i64 -> !spirv.ptr<f32, CrossWorkgroup>\\n      ...\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base_ptr\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"element\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$base_ptr `[` $element ($indices^)? `]` attr-dict `:` type($base_ptr) `,` type($element) (`,` type($indices)^)? `->` type($result)\"\n  },\n  {\n    \"name\": \"spirv.PtrCastToGeneric\",\n    \"summary\": \"Convert a pointer’s Storage Class to Generic.\",\n    \"description\": \"Result Type must be an OpTypePointer. Its Storage Class must be Generic.\\n\\n    Pointer must point to the Workgroup, CrossWorkgroup, or Function Storage\\n    Class.\\n\\n    Result Type and Pointer must point to the same type.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.PtrCastToGeneric %0 : !spirv.ptr<f32, CrossWorkgroup> to\\n         !spirv.ptr<f32, Generic>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"assemblyFormat\": \"$pointer attr-dict `:` type($pointer) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Return\",\n    \"summary\": \"Return with no value from a function with void return type.\",\n    \"description\": \"This instruction must be the last instruction in a block.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.Return\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ReturnValue\",\n    \"summary\": \"Return a value from a function.\",\n    \"description\": \"Value is the value returned, by copy, and must match the Return Type\\n    operand of the OpTypeFunction type of the OpFunction body this return\\n    instruction is in.\\n\\n    This instruction must be the last instruction in a block.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.ReturnValue %0 : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SConvert\",\n    \"summary\": \"Convert signed width.  This is either a truncate or a sign extend.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    Signed Value must be a scalar or vector of integer type.  It must have\\n    the same number of components as Result Type.  The component width\\n    cannot equal the component width in Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.SConvert %0 : i32 to i64\\n    %3 = spirv.SConvert %2 : vector<3xi32> to vector<3xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SDiv\",\n    \"summary\": \"Signed-integer division of Operand 1 divided by Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same number of components as Result\\n    Type. They must have the same component width as Result Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SDiv %0, %1 : i32\\n    %5 = spirv.SDiv %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SDot\",\n    \"summary\": \"Signed integer dot product of Vector 1 and Vector 2.\",\n    \"description\": \"Result Type must be an integer type whose Width must be greater than or\\n    equal to that of the components of Vector 1 and Vector 2.\\n\\n    Vector 1 and Vector 2 must have the same type.\\n\\n    Vector 1 and Vector 2 must be either 32-bit integers (enabled by the\\n    DotProductInput4x8BitPacked capability) or vectors of integer type\\n    (enabled by the DotProductInput4x8Bit or DotProductInputAll capability).\\n\\n    When Vector 1 and Vector 2 are scalar integer types, Packed Vector\\n    Format must be specified to select how the integers are to be\\n    interpreted as vectors.\\n\\n    All components of the input vectors are sign-extended to the bit width\\n    of the result's type. The sign-extended input vectors are then\\n    multiplied component-wise and all components of the vector resulting\\n    from the component-wise multiplication are added together. The resulting\\n    value will equal the low-order N bits of the correct result R, where N\\n    is the result width and R is computed with enough precision to avoid\\n    overflow and underflow.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %r = spirv.SDot %a, %b, <PackedVectorFormat4x8Bit> : i32 -> i32\\n    %r = spirv.SDot %a, %b, <PackedVectorFormat4x8Bit> : i32 -> i64\\n    %r = spirv.SDot %a, %b : vector<4xi8> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<SPIRV_PackedVectorFormatAttr{PackedVectorFormat4x8Bit}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" }\n    ],\n    \"assemblyFormat\": \"$vector1 `,` $vector2 ( `,` $format^ )? attr-dict `:`\\n      type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SDotAccSat\",\n    \"summary\": \"Signed integer dot product of Vector 1 and Vector 2 and signed\\n    saturating addition of the result with Accumulator.\",\n    \"description\": \"Result Type must be an integer type whose Width must be greater than or\\n    equal to that of the components of Vector 1 and Vector 2.\\n\\n    Vector 1 and Vector 2 must have the same type.\\n\\n    Vector 1 and Vector 2 must be either 32-bit integers (enabled by the\\n    DotProductInput4x8BitPacked capability) or vectors of integer type\\n    (enabled by the DotProductInput4x8Bit or DotProductInputAll capability).\\n\\n    The type of Accumulator must be the same as Result Type.\\n\\n    When Vector 1 and Vector 2 are scalar integer types, Packed Vector\\n    Format must be specified to select how the integers are to be\\n    interpreted as vectors.\\n\\n    All components of the input vectors are sign-extended to the bit width\\n    of the result's type. The sign-extended input vectors are then\\n    multiplied component-wise and all components of the vector resulting\\n    from the component-wise multiplication are added together. Finally, the\\n    resulting sum is added to the input accumulator. This final addition is\\n    saturating.\\n\\n    If any of the multiplications or additions, with the exception of the\\n    final accumulation, overflow or underflow, the result of the instruction\\n    is undefined.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %r = spirv.SDotAccSat %a, %b, %acc, <PackedVectorFormat4x8Bit> : i32 -> i32\\n    %r = spirv.SDotAccSat %a, %b, %acc, <PackedVectorFormat4x8Bit> : i32 -> i64\\n    %r = spirv.SDotAccSat %a, %b, %acc : vector<4xi8> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"accumulator\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<SPIRV_PackedVectorFormatAttr{PackedVectorFormat4x8Bit}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" },\n      { \"type\": \"AllTypesMatch<['accumulator', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$vector1 `,` $vector2 `,` $accumulator ( `,` $format^ )? attr-dict `:`\\n      type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Select\",\n    \"summary\": \"Select between two objects. Before version 1.4, results are only\\n    computed per component.\",\n    \"description\": \"Before version 1.4, Result Type must be a pointer, scalar, or vector.\\n\\n    The types of Object 1 and Object 2 must be the same as Result Type.\\n\\n    Condition must be a scalar or vector of Boolean type.\\n\\n    If Condition is a scalar and true, the result is Object 1. If Condition\\n    is a scalar and false, the result is Object 2.\\n\\n    If Condition is a vector, Result Type must be a vector with the same\\n    number of components as Condition and the result is a mix of Object 1\\n    and Object 2: When a component of Condition is true, the corresponding\\n    component in the result is taken from Object 1, otherwise it is taken\\n    from Object 2.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %3 = spirv.Select %0, %1, %2 : i1, f32\\n    %3 = spirv.Select %0, %1, %2 : i1, vector<3xi32>\\n    %3 = spirv.Select %0, %1, %2 : vector<3xi1>, vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" },\n      { \"name\": \"true_value\", \"type\": \"SPIRV_SelectType\" },\n      { \"name\": \"false_value\", \"type\": \"SPIRV_SelectType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_SelectType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($condition) `,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SGreaterThan\",\n    \"summary\": \"Signed-integer comparison if Operand 1 is greater than  Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SGreaterThan %0, %1 : i32\\n    %5 = spirv.SGreaterThan %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SGreaterThanEqual\",\n    \"summary\": \"Signed-integer comparison if Operand 1 is greater than or equal to\\n    Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SGreaterThanEqual %0, %1 : i32\\n    %5 = spirv.SGreaterThanEqual %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ShiftLeftLogical\",\n    \"summary\": \"Shift the bits in Base left by the number of bits specified in Shift.\\n    The least-significant bits are zero filled.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of each Base and Shift must be a scalar or vector of integer\\n    type. Base and Shift must have the same number of components.  The\\n    number of components and bit width of the type of Base must be the same\\n    as in Result Type.\\n\\n    Shift is treated as unsigned. The result is undefined if Shift is\\n    greater than or equal to the bit width of the components of Base.\\n\\n    The number of components and bit width of Result Type must match those\\n    Base type. All types must be integer types.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.ShiftLeftLogical %0, %1 : i32, i16\\n    %5 = spirv.ShiftLeftLogical %3, %4 : vector<3xi32>, vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand1) `,` type($operand2)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ShiftRightArithmetic\",\n    \"summary\": \"Shift the bits in Base right by the number of bits specified in Shift.\\n    The most-significant bits are filled with the sign bit from Base.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of each Base and Shift must be a scalar or vector of integer\\n    type. Base and Shift must have the same number of components.  The\\n    number of components and bit width of the type of Base must be the same\\n    as in Result Type.\\n\\n    Shift is treated as unsigned. The result is undefined if Shift is\\n    greater than or equal to the bit width of the components of Base.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.ShiftRightArithmetic %0, %1 : i32, i16\\n    %5 = spirv.ShiftRightArithmetic %3, %4 : vector<3xi32>, vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand1) `,` type($operand2)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ShiftRightLogical\",\n    \"summary\": \"Shift the bits in Base right by the number of bits specified in Shift.\\n    The most-significant bits are zero filled.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of each Base and Shift must be a scalar or vector of integer\\n    type. Base and Shift must have the same number of components.  The\\n    number of components and bit width of the type of Base must be the same\\n    as in Result Type.\\n\\n    Shift is consumed as an unsigned integer. The result is undefined if\\n    Shift is greater than or equal to the bit width of the components of\\n    Base.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.ShiftRightLogical %0, %1 : i32, i16\\n    %5 = spirv.ShiftRightLogical %3, %4 : vector<3xi32>, vector<3xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand1) `,` type($operand2)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SLessThan\",\n    \"summary\": \"Signed-integer comparison if Operand 1 is less than Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SLessThan %0, %1 : i32\\n    %5 = spirv.SLessThan %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SLessThanEqual\",\n    \"summary\": \"Signed-integer comparison if Operand 1 is less than or equal to Operand\\n    2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SLessThanEqual %0, %1 : i32\\n    %5 = spirv.SLessThanEqual %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SMod\",\n    \"summary\": \"Signed remainder operation for the remainder whose sign matches the sign\\n    of Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same number of components as Result\\n    Type. They must have the same component width as Result Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.  Otherwise, the result is the remainder r of Operand\\n    1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the\\n    sign of Operand 2.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SMod %0, %1 : i32\\n    %5 = spirv.SMod %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SMulExtended\",\n    \"summary\": \"Result is the full value of the signed integer multiplication of Operand\\n    1 and Operand 2.\",\n    \"description\": \"Result Type must be from OpTypeStruct.  The struct must have two\\n    members, and the two members must be the same type.  The member type\\n    must be a scalar or vector of integer type.\\n\\n    Operand 1 and Operand 2 must have the same type as the members of Result\\n    Type. These are consumed as signed integers.\\n\\n    Results are computed per component.\\n\\n    Member 0 of the result gets the low-order bits of the multiplication.\\n\\n    Member 1 of the result gets the high-order bits of the multiplication.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.SMulExtended %0, %1 : !spirv.struct<(i32, i32)>\\n    %2 = spirv.SMulExtended %0, %1 : !spirv.struct<(vector<2xi32>, vector<2xi32>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyStruct\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SNegate\",\n    \"summary\": \"Signed-integer subtract of Operand from zero.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    Operand's type  must be a scalar or vector of integer type.  It must\\n    have the same number of components as Result Type.  The component width\\n    must equal the component width in Result Type.\\n\\n     Results are computed per component.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.SNegate %0 : i32\\n    %3 = spirv.SNegate %2 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SpecConstant\",\n    \"summary\": \"Declare a new integer-type or floating-point-type scalar specialization\\n    constant.\",\n    \"description\": \"This op declares a SPIR-V scalar specialization constant. SPIR-V has\\n    multiple constant instructions covering different scalar types:\\n\\n    * `OpSpecConstantTrue` and `OpSpecConstantFalse` for boolean constants\\n    * `OpSpecConstant` for scalar constants\\n\\n    Similar as `spirv.Constant`, this op represents all of the above cases.\\n    `OpSpecConstantComposite` and `OpSpecConstantOp` are modelled with\\n    separate ops.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    spv-spec-constant-op ::= `spirv.SpecConstant` symbol-ref-id\\n                             `spec_id(` integer `)`\\n                             `=` attribute-value (`:` spirv-type)?\\n    ```\\n\\n    where `spec_id` specifies the SPIR-V SpecId decoration associated with\\n    the op.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.SpecConstant @spec_const1 = true\\n    spirv.SpecConstant @spec_const2 spec_id(5) = 42 : i32\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"default_value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SpecConstantComposite\",\n    \"summary\": \"Declare a new composite specialization constant.\",\n    \"description\": \"This op declares a SPIR-V composite specialization constant. This covers\\n    the `OpSpecConstantComposite` SPIR-V instruction. Scalar constants are\\n    covered by `spirv.SpecConstant`.\\n\\n    A constituent of a spec constant composite can be:\\n    - A symbol referring of another spec constant.\\n    - The SSA ID of a non-specialization constant (i.e. defined through\\n      `spirv.SpecConstant`).\\n    - The SSA ID of a `spirv.Undef`.\\n\\n    ```\\n    spv-spec-constant-composite-op ::= `spirv.SpecConstantComposite` symbol-ref-id ` (`\\n                                       symbol-ref-id (`, ` symbol-ref-id)*\\n                                       `) :` composite-type\\n    ```\\n\\n     where `composite-type` is some non-scalar type that can be represented in the `spv`\\n     dialect: `spirv.struct`, `spirv.array`, or `vector`.\\n\\n     #### Example:\\n\\n     ```mlir\\n     spirv.SpecConstant @sc1 = 1   : i32\\n     spirv.SpecConstant @sc2 = 2.5 : f32\\n     spirv.SpecConstant @sc3 = 3.5 : f32\\n     spirv.SpecConstantComposite @scc (@sc1, @sc2, @sc3) : !spirv.struct<i32, f32, f32>\\n     ```\\n\\n    TODO Add support for constituents that are:\\n    - regular constants.\\n    - undef.\\n    - spec constant composite.\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"constituents\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SpecConstantOperation\",\n    \"summary\": \"Declare a new specialization constant that results from doing an operation.\",\n    \"description\": \"This op declares a SPIR-V specialization constant that results from\\n    doing an operation on other constants (specialization or otherwise).\\n\\n    In the `spv` dialect, this op is modelled as follows:\\n\\n    ```\\n    spv-spec-constant-operation-op ::= `spirv.SpecConstantOperation` `wraps`\\n                                         generic-spirv-op `:` function-type\\n    ```\\n\\n    In particular, an `spirv.SpecConstantOperation` contains exactly one\\n    region. In turn, that region, contains exactly 2 instructions:\\n    - One of SPIR-V's instructions that are allowed within an\\n    OpSpecConstantOp.\\n    - An `spirv.mlir.yield` instruction as the terminator.\\n\\n    The following SPIR-V instructions are valid:\\n    - OpSConvert,\\n    - OpUConvert,\\n    - OpFConvert,\\n    - OpSNegate,\\n    - OpNot,\\n    - OpIAdd,\\n    - OpISub,\\n    - OpIMul,\\n    - OpUDiv,\\n    - OpSDiv,\\n    - OpUMod,\\n    - OpSRem,\\n    - OpSMod\\n    - OpShiftRightLogical,\\n    - OpShiftRightArithmetic,\\n    - OpShiftLeftLogical\\n    - OpBitwiseOr,\\n    - OpBitwiseXor,\\n    - OpBitwiseAnd\\n    - OpVectorShuffle,\\n    - OpCompositeExtract,\\n    - OpCompositeInsert\\n    - OpLogicalOr,\\n    - OpLogicalAnd,\\n    - OpLogicalNot,\\n    - OpLogicalEqual,\\n    - OpLogicalNotEqual\\n    - OpSelect\\n    - OpIEqual,\\n    - OpINotEqual\\n    - OpULessThan,\\n    - OpSLessThan\\n    - OpUGreaterThan,\\n    - OpSGreaterThan\\n    - OpULessThanEqual,\\n    - OpSLessThanEqual\\n    - OpUGreaterThanEqual,\\n    - OpSGreaterThanEqual\\n\\n    TODO Add capability-specific ops when supported.\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Constant 1: i32\\n    %1 = spirv.Constant 1: i32\\n\\n    %2 = spirv.SpecConstantOperation wraps \\\"spirv.IAdd\\\"(%0, %1) : (i32, i32) -> i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SRem\",\n    \"summary\": \"Signed remainder operation for the remainder whose sign matches the sign\\n    of Operand 1.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same number of components as Result\\n    Type. They must have the same component width as Result Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.  Otherwise, the result is the remainder r of Operand\\n    1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the\\n    sign of Operand 1.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.SRem %0, %1 : i32\\n    %5 = spirv.SRem %2, %3 : vector<4xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Store\",\n    \"summary\": \"Store through a pointer.\",\n    \"description\": \"Pointer is the pointer to store through.  Its type must be an\\n    OpTypePointer whose Type operand is the same as the type of Object.\\n\\n    Object is the object to store.\\n\\n    If present, any Memory Operands must begin with a memory operand\\n    literal. If not present, it is the same as specifying the memory operand\\n    None.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    store-op ::= `spirv.Store ` storage-class ssa-use `, ` ssa-use `, `\\n                  (`[` memory-access `]`)? `:` spirv-element-type\\n    ```\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Variable : !spirv.ptr<f32, Function>\\n    %1 = spirv.FMul ... : f32\\n    spirv.Store \\\"Function\\\" %0, %1 : f32\\n    spirv.Store \\\"Function\\\" %0, %1 [\\\"Volatile\\\"] : f32\\n    spirv.Store \\\"Function\\\" %0, %1 [\\\"Aligned\\\", 4] : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"SPIRV_AnyPtr\" },\n      { \"name\": \"value\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_access\", \"type\": \"OptionalAttr<SPIRV_MemoryAccessAttr{None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerVisible|NonPrivatePointer|AliasScopeINTELMask|NoAliasINTELMask}>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I32Attr>>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SUDot\",\n    \"summary\": \"Mixed-signedness integer dot product of Vector 1 and Vector 2.\\n    Components of Vector 1 are treated as signed, components of Vector 2 are\\n    treated as unsigned.\",\n    \"description\": \"Result Type must be an integer type whose Width must be greater than or\\n    equal to that of the components of Vector 1 and Vector 2.\\n\\n    Vector 1 and Vector 2 must be either 32-bit integers (enabled by the\\n    DotProductInput4x8BitPacked capability) or vectors of integer type with\\n    the same number of components and same component Width (enabled by the\\n    DotProductInput4x8Bit or DotProductInputAll capability). When Vector 1\\n    and Vector 2 are vectors, the components of Vector 2 must have a\\n    Signedness of 0.\\n\\n    When Vector 1 and Vector 2 are scalar integer types, Packed Vector\\n    Format must be specified to select how the integers are to be\\n    interpreted as vectors.\\n\\n    All components of Vector 1 are sign-extended to the bit width of the\\n    result's type. All components of Vector 2 are zero-extended to the bit\\n    width of the result's type. The sign- or zero-extended input vectors are\\n    then multiplied component-wise and all components of the vector\\n    resulting from the component-wise multiplication are added together. The\\n    resulting value will equal the low-order N bits of the correct result R,\\n    where N is the result width and R is computed with enough precision to\\n    avoid overflow and underflow.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %r = spirv.SUDot %a, %b, <PackedVectorFormat4x8Bit> : i32 -> i32\\n    %r = spirv.SUDot %a, %b, <PackedVectorFormat4x8Bit> : i32 -> i64\\n    %r = spirv.SUDot %a, %b : vector<4xi8> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<SPIRV_PackedVectorFormatAttr{PackedVectorFormat4x8Bit}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" }\n    ],\n    \"assemblyFormat\": \"$vector1 `,` $vector2 ( `,` $format^ )? attr-dict `:`\\n      type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.SUDotAccSat\",\n    \"summary\": \"Mixed-signedness integer dot product of Vector 1 and Vector 2 and signed\\n    saturating addition of the result with Accumulator. Components of Vector\\n    1 are treated as signed, components of Vector 2 are treated as unsigned.\",\n    \"description\": \"Result Type must be an integer type whose Width must be greater than or\\n    equal to that of the components of Vector 1 and Vector 2.\\n\\n    Vector 1 and Vector 2 must be either 32-bit integers (enabled by the\\n    DotProductInput4x8BitPacked capability) or vectors of integer type with\\n    the same number of components and same component Width (enabled by the\\n    DotProductInput4x8Bit or DotProductInputAll capability). When Vector 1\\n    and Vector 2 are vectors, the components of Vector 2 must have a\\n    Signedness of 0.\\n\\n    The type of Accumulator must be the same as Result Type.\\n\\n    When Vector 1 and Vector 2 are scalar integer types, Packed Vector\\n    Format must be specified to select how the integers are to be\\n    interpreted as vectors.\\n\\n    All components of Vector 1 are sign-extended to the bit width of the\\n    result's type. All components of Vector 2 are zero-extended to the bit\\n    width of the result's type. The sign- or zero-extended input vectors are\\n    then multiplied component-wise and all components of the vector\\n    resulting from the component-wise multiplication are added together.\\n    Finally, the resulting sum is added to the input accumulator. This final\\n    addition is saturating.\\n\\n    If any of the multiplications or additions, with the exception of the\\n    final accumulation, overflow or underflow, the result of the instruction\\n    is undefined.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %r = spirv.SUDotAccSat %a, %b, %acc, <PackedVectorFormat4x8Bit> : i32 -> i32\\n    %r = spirv.SUDotAccSat %a, %b, %acc, <PackedVectorFormat4x8Bit> : i32 -> i64\\n    %r = spirv.SUDotAccSat %a, %b, %acc : vector<4xi8> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"accumulator\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<SPIRV_PackedVectorFormatAttr{PackedVectorFormat4x8Bit}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" },\n      { \"type\": \"AllTypesMatch<['accumulator', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$vector1 `,` $vector2 `,` $accumulator ( `,` $format^ )? attr-dict `:`\\n      type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Switch\",\n    \"summary\": \"Multi-way branch to one of the operand label `<id>`.\",\n    \"description\": \"Selector must have a type of OpTypeInt. Selector is compared for equality to\\n    the Target literals.\\n\\n    Default must be the `<id>` of a label. If Selector does not equal any of the\\n    Target literals, control flow branches to the Default label `<id>`.\\n\\n    Target must be alternating scalar integer literals and the `<id>` of a label.\\n    If Selector equals a literal, control flow branches to the following label\\n    `<id>`. It is invalid for any two literal to be equal to each other. If Selector\\n    does not equal any literal, control flow branches to the Default label `<id>`.\\n    Each literal is interpreted with the type of Selector: The bit width of\\n    Selector’s type is the width of each literal’s type. If this width is not a\\n    multiple of 32-bits and the OpTypeInt Signedness is set to 1, the literal values\\n    are interpreted as being sign extended.\\n\\n    If Selector is an OpUndef, behavior is undefined.\\n\\n    This instruction must be the last instruction in a block.\\n\\n    #### Example:\\n\\n    ```mlir\\n    spirv.Switch %selector : si32, [\\n      default: ^bb1(%a : i32),\\n      0: ^bb1(%b : i32),\\n      1: ^bb3(%c : i32)\\n    ]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"selector\", \"type\": \"SPIRV_Integer\" },\n      { \"name\": \"defaultOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"targetOperands\", \"type\": \"VariadicOfVariadic<AnyType, case_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"literals\", \"type\": \"OptionalAttr<AnyIntElementsAttr>\" },\n      { \"name\": \"case_operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultTarget\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"targets\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$selector `:` type($selector) `,` `[` `\\\\n`\\n      custom<SwitchOpCases>(ref(type($selector)),$defaultTarget,\\n                            $defaultOperands,\\n                            type($defaultOperands),\\n                            $literals,\\n                            $targets,\\n                            $targetOperands,\\n                            type($targetOperands))\\n   `]`\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Abs\",\n    \"summary\": \"Absolute value operation.\",\n    \"description\": \"Elementwise Absolute value operation. Input and Output types must match.\\n    Integer element types are always interpreted as signed. The behaviour is\\n    undefined if the input value is min_value<si32>.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_abs\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_abs\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Abs %arg0 : !spirv.arm.tensor<5x1x4x4xi32> -> !spirv.arm.tensor<5x1x4x4xi32>\\n    %0 = spirv.Tosa.Abs %arg0 : !spirv.arm.tensor<3x6x14x8xf16> -> !spirv.arm.tensor<3x6x14x8xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Add\",\n    \"summary\": \"Addition operator.\",\n    \"description\": \"Elementwise Addition of input1 and input2. Axis of size 1 will be broadcast,\\n    as necessary. Rank of input tensors must match. Integer element types are\\n    always interpreted as signed. The behavior is undefined if the integer\\n    addition overflows or underflows the signed integer range.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_add\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_add\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Add %arg0, %arg1 : !spirv.arm.tensor<4x7x3x10xi32>, !spirv.arm.tensor<4x7x3x1xi32> -> !spirv.arm.tensor<4x7x3x10xi32>\\n    %0 = spirv.Tosa.Add %arg0, %arg1 : !spirv.arm.tensor<26x37x18xf16>, !spirv.arm.tensor<1x37x18xf16> -> !spirv.arm.tensor<26x37x18xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.ArgMax\",\n    \"summary\": \"Perform argmax on the input.\",\n    \"description\": \"Returns the index with the largest value across the given axis of the\\n    input tensor. If multiple locations have equal values, returns the first\\n    match along the search axis.\\n    NaN Propagation Mode is ignored for inputs using integer element types.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_argmax\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_argmax\\n\\n    #### Example:\\n    ```mlir\\n    %2 = spirv.Tosa.ArgMax axis = 3, nan_mode = <Propagate>, %arg0 : !spirv.arm.tensor<3x28x17x17xi8> -> !spirv.arm.tensor<3x28x17xi32>\\n    %2 = spirv.Tosa.ArgMax axis = 2, nan_mode = <Propagate>, %arg0 : !spirv.arm.tensor<2x2x7x14xf32> -> !spirv.arm.tensor<2x2x14xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Int32_TensorArmUpTo5D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<5>]>\" },\n      { \"name\": \"nan_mode\", \"type\": \"SPIRV_TosaExtNaNPropagationModeAttr{Propagate|Ignore}\" }\n    ],\n    \"assemblyFormat\": \"`axis` `=` $axis `,`\\n    `nan_mode` `=` $nan_mode `,`\\n    $input\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.ArithmeticRightShift\",\n    \"summary\": \"Arithmetic Right Shift.\",\n    \"description\": \"Elementwise Arithmetic Right Shift of input1 by the amount specified in\\n    input2. Axis of size 1 will be broadcast, as necessary. Rank of input\\n    tensors must match. Integer element types are always interpreted as signed.\\n    The behavior is undefined if the shift value is negative or greater or\\n    equal to the bitwidth of the element type.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_arithmetic_right_shift\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_arithmetic_right_shift\\n\\n    #### Example:\\n    ```mlir\\n    %1 = spirv.Tosa.ArithmeticRightShift round = true, %arg0, %arg1 : !spirv.arm.tensor<1x47x22xi16>, !spirv.arm.tensor<49x47x22xi16> -> !spirv.arm.tensor<49x47x22xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"round\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`round` `=` $round `,`\\n    $input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.AvgPool2D\",\n    \"summary\": \"Performs average pooling on the input.\",\n    \"description\": \"Performs an average pooling over the given input tensor. A sliding\\n    window of size given by <kernel size> is passed over the input tensor, with\\n    the mean value being placed in the output tensor. When calculating the\\n    average, only the number of valid input tensor values, but not padding, are\\n    used to calculate the divisor.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_avg_pool2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_avg_pool2d\\n\\n    #### Example:\\n    ```mlir\\n    %6 = spirv.Tosa.AvgPool2D kernel = [3, 3], stride = [1, 2], pad = [0, 1, 0, 0], acc_type = <INT32>, %arg0, %4, %5 : !spirv.arm.tensor<1x3x65537x1xi8>, !spirv.arm.tensor<1xi8>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<1x2x32768x1xi8>\\n    %6 = spirv.Tosa.AvgPool2D kernel = [2, 2], stride = [1, 1], pad = [1, 0, 0, 0], acc_type = <FP32>, %arg0, %4, %5 : !spirv.arm.tensor<1x2x65533x2xf32>, !spirv.arm.tensor<1xf32>, !spirv.arm.tensor<1xf32> -> !spirv.arm.tensor<1x2x65532x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"input_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"output_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 4 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"acc_type\", \"type\": \"SPIRV_TosaExtAccTypeAttr{INT32|FP16|FP32|INT48}\" }\n    ],\n    \"assemblyFormat\": \"`kernel` `=` custom<SPIRV_I32_1DArmTensor>($kernel) `,`\\n    `stride` `=` custom<SPIRV_I32_1DArmTensor>($stride) `,`\\n    `pad` `=` custom<SPIRV_I32_1DArmTensor>($pad) `,`\\n    `acc_type` `=` $acc_type `,`\\n    $input `,`\\n    $input_zp `,`\\n    $output_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.BitwiseAnd\",\n    \"summary\": \"Bitwise AND operator.\",\n    \"description\": \"Elementwise Bitwise AND of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match. Integer element\\n    types are always interpreted as signed.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_bitwise_and\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_bitwise_and\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.BitwiseAnd %arg0, %arg1 : !spirv.arm.tensor<4x1x7x12xi16>, !spirv.arm.tensor<4x13x7x12xi16> -> !spirv.arm.tensor<4x13x7x12xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.BitwiseNot\",\n    \"summary\": \"Bitwise NOT operator.\",\n    \"description\": \"Elementwise Bitwise NOT of input tensor. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_bitwise_not\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_bitwise_not\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.BitwiseNot %arg0 : !spirv.arm.tensor<12x56x50xi32> -> !spirv.arm.tensor<12x56x50xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.BitwiseOr\",\n    \"summary\": \"Bitwise OR operator.\",\n    \"description\": \"Elementwise Bitwise OR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match. Integer element\\n    types are always interpreted as signed.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_bitwise_or\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_bitwise_or\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.BitwiseOr %arg0, %arg1 : !spirv.arm.tensor<11x30x23xi32>, !spirv.arm.tensor<1x30x23xi32> -> !spirv.arm.tensor<11x30x23xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.BitwiseXor\",\n    \"summary\": \"Bitwise XOR operator.\",\n    \"description\": \"Elementwise Bitwise XOR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match. Integer element\\n    types are always interpreted as signed.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_bitwise_xor\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_bitwise_xor\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.BitwiseXor %arg0, %arg1 : !spirv.arm.tensor<4x8x13x9xi16>, !spirv.arm.tensor<4x8x1x9xi16> -> !spirv.arm.tensor<4x8x13x9xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Ceil\",\n    \"summary\": \"Ceil operator.\",\n    \"description\": \"Elementwise Ceiling operation. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_ceil\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_ceil\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Ceil %arg0 : !spirv.arm.tensor<46x55x53xf16> -> !spirv.arm.tensor<46x55x53xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Clamp\",\n    \"summary\": \"Computes Clamp(min, max).\",\n    \"description\": \"Clamp to an arbitrary minimum and maximum value. Maximum and minimum values\\n    are specified as values in the range of the input type. Integer element\\n    types are always interpreted as signed.\\n    No zero point subtraction is done to the values, thus to clamp to the zero\\n    point value, the zero point itself should be supplied as the minimum value.\\n    NaN Propagation Mode is ignored for inputs using integer element types.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_clamp\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_clamp\\n\\n    #### Example:\\n    ```mlir\\n    %3 = spirv.Tosa.Clamp min_val = -102 : i8, max_val = -100 : i8, nan_mode = <Propagate>, %arg0 : !spirv.arm.tensor<27x44x55xi8> -> !spirv.arm.tensor<27x44x55xi8>\\n    %3 = spirv.Tosa.Clamp min_val = -1.19339396E+38 : f32, max_val = 2.38255944E+38 : f32, nan_mode = <Ignore>, %arg0 : !spirv.arm.tensor<18x5x17x6xf32> -> !spirv.arm.tensor<18x5x17x6xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min_val\", \"type\": \"SPIRV_TosaNumericalAttr\" },\n      { \"name\": \"max_val\", \"type\": \"SPIRV_TosaNumericalAttr\" },\n      { \"name\": \"nan_mode\", \"type\": \"SPIRV_TosaExtNaNPropagationModeAttr{Propagate|Ignore}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"`min_val` `=` $min_val `,`\\n    `max_val` `=` $max_val `,`\\n    `nan_mode` `=` $nan_mode `,`\\n    $input\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Clz\",\n    \"summary\": \"Count Leading Zero operator.\",\n    \"description\": \"Elementwise Count Leading Zeros operation. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_clz\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_clz\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Clz %arg0 : !spirv.arm.tensor<14x10x7x5xi32> -> !spirv.arm.tensor<14x10x7x5xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_Int32_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Int32_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Conv2D\",\n    \"summary\": \"2D Convolution operator.\",\n    \"description\": \"Performs a 2D convolution over the given tensor input, using the weight\\n    tensor. Implementations may choose to skip calculation of multiplies in\\n    the padding area.\\n\\n    Input and weight have respective zero point values provided in input_zp and weight_zp.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_conv2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_conv2d\\n\\n    #### Example:\\n    ```mlir\\n    %7 = spirv.Tosa.Conv2D pad = [1, 0, 0, 0], stride = [1, 2], dilation = [7, 1], acc_type = <INT32>, local_bound = false, %arg0, %arg1, %arg2, %5, %6 : !spirv.arm.tensor<1x65535x3x1xi8>, !spirv.arm.tensor<7x1x1x1xi8>, !spirv.arm.tensor<1xi32>, !spirv.arm.tensor<1xi8>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<1x65536x2x7xi32>\\n    %7 = spirv.Tosa.Conv2D pad = [0, 0, 0, 0], stride = [1, 1], dilation = [1, 1], acc_type = <FP16>, local_bound = true, %arg0, %arg1, %arg2, %5, %6 : !spirv.arm.tensor<1x34x18x27xf16>, !spirv.arm.tensor<11x1x1x27xf16>, !spirv.arm.tensor<11xf16>, !spirv.arm.tensor<1xf16>, !spirv.arm.tensor<1xf16> -> !spirv.arm.tensor<1x34x18x11xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"weight\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"bias\", \"type\": \"SPIRV_TosaNumerical_TensorArm1D\" },\n      { \"name\": \"input_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"weight_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 4 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"dilation\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"acc_type\", \"type\": \"SPIRV_TosaExtAccTypeAttr{INT32|FP16|FP32|INT48}\" },\n      { \"name\": \"local_bound\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`pad` `=` custom<SPIRV_I32_1DArmTensor>($pad) `,`\\n    `stride` `=` custom<SPIRV_I32_1DArmTensor>($stride) `,`\\n    `dilation` `=` custom<SPIRV_I32_1DArmTensor>($dilation) `,`\\n    `acc_type` `=` $acc_type `,`\\n    `local_bound` `=` $local_bound `,`\\n    $input `,`\\n    $weight `,`\\n    $bias `,`\\n    $input_zp `,`\\n    $weight_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Conv3D\",\n    \"summary\": \"3D Convolution operator.\",\n    \"description\": \"Performs a 3D convolution over the given input tensor. Implementations\\n    may choose to skip calculation of multiplies in the padding area.\\n\\n    Input and weight have respective zero point values provided in input_zp and weight_zp.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_conv3d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_conv3d\\n\\n    #### Example:\\n    ```mlir\\n    %7 = spirv.Tosa.Conv3D pad = [0, 0, 0, 0, 0, 0], stride = [1, 1, 1], dilation = [1, 1, 1], acc_type = <INT32>, local_bound = false, %arg0, %arg1, %arg2, %5, %6 : !spirv.arm.tensor<1x9x21x14x1xi8>, !spirv.arm.tensor<2x1x2x1x1xi8>, !spirv.arm.tensor<1xi32>, !spirv.arm.tensor<1xi8>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<1x9x20x14x2xi32>\\n    %7 = spirv.Tosa.Conv3D pad = [0, 1, 1, 0, 0, 1], stride = [1, 1, 1], dilation = [1, 1, 7], acc_type = <FP32>, local_bound = false, %arg0, %arg1, %arg2, %5, %6 : !spirv.arm.tensor<1x2x65539x1x2xf32>, !spirv.arm.tensor<1x1x1x1x2xf32>, !spirv.arm.tensor<1xf32>, !spirv.arm.tensor<1xf32>, !spirv.arm.tensor<1xf32> -> !spirv.arm.tensor<1x3x65540x2x1xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm5D\" },\n      { \"name\": \"weight\", \"type\": \"SPIRV_TosaNumerical_TensorArm5D\" },\n      { \"name\": \"bias\", \"type\": \"SPIRV_TosaNumerical_TensorArm1D\" },\n      { \"name\": \"input_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"weight_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm5D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 6 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 3 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"dilation\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 3 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"acc_type\", \"type\": \"SPIRV_TosaExtAccTypeAttr{INT32|FP16|FP32|INT48}\" },\n      { \"name\": \"local_bound\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`pad` `=` custom<SPIRV_I32_1DArmTensor>($pad) `,`\\n    `stride` `=` custom<SPIRV_I32_1DArmTensor>($stride) `,`\\n    `dilation` `=` custom<SPIRV_I32_1DArmTensor>($dilation) `,`\\n    `acc_type` `=` $acc_type `,`\\n    `local_bound` `=` $local_bound `,`\\n    $input `,`\\n    $weight `,`\\n    $bias `,`\\n    $input_zp `,`\\n    $weight_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Cos\",\n    \"summary\": \"Cosine operator.\",\n    \"description\": \"Elementwise Cosine operation for values given in radians. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_cos\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_cos\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Cos %arg0 : !spirv.arm.tensor<44x49x51xf32> -> !spirv.arm.tensor<44x49x51xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.DepthwiseConv2D\",\n    \"summary\": \"Depthwise 2D Convolution operator.\",\n    \"description\": \"Performs 2D convolutions separately over each channel of the given tensor\\n    input, using the weight tensor. Implementations may choose to skip\\n    calculation of multiplies in the padding area.\\n\\n    Input and weight have respective zero point values provided in input_zp and weight_zp.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_depthwise_conv2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_depthwise_conv2d\\n\\n    #### Example:\\n    ```mlir\\n    %7 = spirv.Tosa.DepthwiseConv2D pad = [0, 0, 0, 0], stride = [1, 2], dilation = [7, 7], acc_type = <INT32>, local_bound = false, %arg0, %arg1, %arg2, %5, %6 : !spirv.arm.tensor<1x4x65537x1xi8>, !spirv.arm.tensor<1x3x1x4xi8>, !spirv.arm.tensor<4xi32>, !spirv.arm.tensor<1xi8>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<1x4x32762x4xi32>\\n    %7 = spirv.Tosa.DepthwiseConv2D pad = [0, 1, 1, 1], stride = [1, 2], dilation = [1, 7], acc_type = <FP32>, local_bound = true, %arg0, %arg1, %arg2, %5, %6 : !spirv.arm.tensor<1x65540x1x3xf32>, !spirv.arm.tensor<1x1x3x1xf32>, !spirv.arm.tensor<1xf32>, !spirv.arm.tensor<1xf32>, !spirv.arm.tensor<1xf32> -> !spirv.arm.tensor<1x65541x2x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"weight\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"bias\", \"type\": \"SPIRV_TosaNumerical_TensorArm1D\" },\n      { \"name\": \"input_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"weight_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 4 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"dilation\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"acc_type\", \"type\": \"SPIRV_TosaExtAccTypeAttr{INT32|FP16|FP32|INT48}\" },\n      { \"name\": \"local_bound\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`pad` `=` custom<SPIRV_I32_1DArmTensor>($pad) `,`\\n    `stride` `=` custom<SPIRV_I32_1DArmTensor>($stride) `,`\\n    `dilation` `=` custom<SPIRV_I32_1DArmTensor>($dilation) `,`\\n    `acc_type` `=` $acc_type `,`\\n    `local_bound` `=` $local_bound `,`\\n    $input `,`\\n    $weight `,`\\n    $bias `,`\\n    $input_zp `,`\\n    $weight_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Equal\",\n    \"summary\": \"Equal comparison operation\",\n    \"description\": \"Elementwise Equal comparison operation: returns the truth value of\\n    (input1 == input2) element-wise.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_equal\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_equal\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Equal %arg0, %arg1 : !spirv.arm.tensor<51x28x59xi32>, !spirv.arm.tensor<51x1x59xi32> -> !spirv.arm.tensor<51x28x59xi1>\\n    %0 = spirv.Tosa.Equal %arg0, %arg1 : !spirv.arm.tensor<16x11x5x3xf32>, !spirv.arm.tensor<16x1x5x3xf32> -> !spirv.arm.tensor<16x11x5x3xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Erf\",\n    \"summary\": \"Gauss Error Function.\",\n    \"description\": \"Gauss Error Function: $ erf(x) = \\\\frac{2}{\\\\sqrt{\\\\pi}} \\\\int_{0}^{x} e^{-t^2} dt $\\n    For quantized integer data types, the `spirv.Tosa.Table` operator should be used instead.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_erf\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_erf\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Erf %arg0 : !spirv.arm.tensor<47x38x51xf32> -> !spirv.arm.tensor<47x38x51xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Exp\",\n    \"summary\": \"Exp operator.\",\n    \"description\": \"Elementwise e to the power of x operation. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_exp\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_exp\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Exp %arg0 : !spirv.arm.tensor<37x53x47xf32> -> !spirv.arm.tensor<37x53x47xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.FFT2D\",\n    \"summary\": \"Performs FFT2D operation on the input.\",\n    \"description\": \"Performs a batched complex 2D Fast Fourier Transform over the input. The\\n    complex input values are constructed from the corresponding values in the\\n    input_real and input_imag tensors. The resulting values in the output are\\n    split into the output_real and output_imag tensors. No normalization is\\n    applied on either the forward or inverse versions of the operation.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_fft2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_fft2d\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.FFT2D inverse = true, local_bound = false, %arg0, %arg1 : !spirv.arm.tensor<1x32x32xf32>, !spirv.arm.tensor<1x32x32xf32> -> !spirv.struct<(!spirv.arm.tensor<1x32x32xf32>, !spirv.arm.tensor<1x32x32xf32>)>\\n    %1 = spirv.CompositeExtract %0[0 : i32] : !spirv.struct<(!spirv.arm.tensor<1x32x32xf32>, !spirv.arm.tensor<1x32x32xf32>)>\\n    %2 = spirv.CompositeExtract %0[1 : i32] : !spirv.struct<(!spirv.arm.tensor<1x32x32xf32>, !spirv.arm.tensor<1x32x32xf32>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input_real\", \"type\": \"SPIRV_Float32_TensorArm3D\" },\n      { \"name\": \"input_imag\", \"type\": \"SPIRV_Float32_TensorArm3D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Struct_2_Float32_TensorArm3D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inverse\", \"type\": \"ConfinedAttr<BoolAttr>\" },\n      { \"name\": \"local_bound\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`inverse` `=` $inverse `,`\\n    `local_bound` `=` $local_bound `,`\\n    $input_real `,`\\n    $input_imag\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Floor\",\n    \"summary\": \"Floor operator.\",\n    \"description\": \"Elementwise Floor operation. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_floor\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_floor\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Floor %arg0 : !spirv.arm.tensor<40x52x42xf32> -> !spirv.arm.tensor<40x52x42xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Greater\",\n    \"summary\": \"Greater comparison operation\",\n    \"description\": \"Elementwise Greater than comparison operation: returns the truth value of\\n    (input1 > input2) element-wise.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_greater\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_greater\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Greater %arg0, %arg1 : !spirv.arm.tensor<11x10x10x2xi32>, !spirv.arm.tensor<11x10x10x1xi32> -> !spirv.arm.tensor<11x10x10x2xi1>\\n    %0 = spirv.Tosa.Greater %arg0, %arg1 : !spirv.arm.tensor<6x3x12x4xf16>, !spirv.arm.tensor<6x3x1x4xf16> -> !spirv.arm.tensor<6x3x12x4xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.GreaterEqual\",\n    \"summary\": \"Greater or Equal comparison operation\",\n    \"description\": \"Elementwise Greater or Equal than comparison operation: returns the truth value of\\n    (input1 >= input2) element-wise.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_greater_equal\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_greater_equal\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.GreaterEqual %arg0, %arg1 : !spirv.arm.tensor<10x17x7x1xi32>, !spirv.arm.tensor<10x17x7x16xi32> -> !spirv.arm.tensor<10x17x7x16xi1>\\n    %0 = spirv.Tosa.GreaterEqual %arg0, %arg1 : !spirv.arm.tensor<3x17x6x3xf32>, !spirv.arm.tensor<1x17x6x3xf32> -> !spirv.arm.tensor<3x17x6x3xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.IntDiv\",\n    \"summary\": \"Integer Divide operator.\",\n    \"description\": \"Elementwise Integer Divide of input1 by input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.  Integer element\\n    types are always interpreted as signed. The behavior is undefined if the\\n    divisor value is equal to zero and if the divisor value is min_value<si32>\\n    and the dividend is -1.\\n\\n    The result of the divide is truncated towards zero. Expected use is for\\n    operations on non-scaled integers. Floating point divide should use\\n    `spirv.Tosa.Reciprocal` and `spirv.Tosa.Mul`. Quantized integer divide\\n    should use `spirv.Tosa.Table`(for $ 1/x $) and `spirv.Tosa.Mul`.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_intdiv\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_intdiv\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.IntDiv %arg0, %arg1 : !spirv.arm.tensor<1x65533x1xi32>, !spirv.arm.tensor<2x65533x1xi32> -> !spirv.arm.tensor<2x65533x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_Int32_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_Int32_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Int32_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Log\",\n    \"summary\": \"Log operator.\",\n    \"description\": \"Elementwise Natural Logarithm operation. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_log\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_log\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Log %arg0 : !spirv.arm.tensor<45x43x36xf16> -> !spirv.arm.tensor<45x43x36xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.LogicalAnd\",\n    \"summary\": \"Logical AND operator.\",\n    \"description\": \"Elementwise Logical AND of input1 and input2. Axis of size 1 will be\\n    broadcast, as necessary. Rank of input tensors must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_logical_and\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_logical_and\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.LogicalAnd %arg0, %arg1 : !spirv.arm.tensor<2x1x7x11xi1>, !spirv.arm.tensor<2x4x7x11xi1> -> !spirv.arm.tensor<2x4x7x11xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_Bool_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.LogicalLeftShift\",\n    \"summary\": \"Logical Left Shift operator.\",\n    \"description\": \"Elementwise Logical Left Shift of input1 by the amount specified in input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors\\n    must match.  Integer element types are always interpreted as signed. The\\n    behavior is undefined if the shift value is negative or greater or equal to\\n    the bitwidth of the element type.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_logical_left_shift\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_logical_left_shift\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.LogicalLeftShift %arg0, %arg1 : !spirv.arm.tensor<7x1x11x4xi8>, !spirv.arm.tensor<7x8x11x4xi8> -> !spirv.arm.tensor<7x8x11x4xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.LogicalNot\",\n    \"summary\": \"Logical NOT operator.\",\n    \"description\": \"Elementwise Logical NOT of input. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_logical_not\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_logical_not\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.LogicalNot %arg0 : !spirv.arm.tensor<54x26x10xi1> -> !spirv.arm.tensor<54x26x10xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.LogicalOr\",\n    \"summary\": \"Logical OR operator.\",\n    \"description\": \"Elementwise logical OR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_logical_or\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_logical_or\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.LogicalOr %arg0, %arg1 : !spirv.arm.tensor<3x6x12x5xi1>, !spirv.arm.tensor<3x6x1x5xi1> -> !spirv.arm.tensor<3x6x12x5xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_Bool_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.LogicalRightShift\",\n    \"summary\": \"Logical Right Shift operator.\",\n    \"description\": \"Elementwise Logical Right Shift of input1 by the amount specified in input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors must\\n    match.  Integer element types are always interpreted as signed. The\\n    behavior is undefined if the shift value is negative or greater or equal to\\n    the bitwidth of the element type.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_logical_right_shift\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_logical_right_shift\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.LogicalRightShift %arg0, %arg1 : !spirv.arm.tensor<6x13x1x19xi8>, !spirv.arm.tensor<6x13x6x19xi8> -> !spirv.arm.tensor<6x13x6x19xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.LogicalXor\",\n    \"summary\": \"Logical XOR operator.\",\n    \"description\": \"Elementwise logical XOR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_logical_xor\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_logical_xor\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.LogicalXor %arg0, %arg1 : !spirv.arm.tensor<11x4x9x12xi1>, !spirv.arm.tensor<11x4x9x1xi1> -> !spirv.arm.tensor<11x4x9x12xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_Bool_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Bool_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.MatMul\",\n    \"summary\": \"Matrix Multiplication operator.\",\n    \"description\": \"Performs two dimensional matrix multiplications.\\n    A, B are the inputs with respective zero point values in A_zp, B_zp.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_matmul\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_matmul\\n\\n    #### Example:\\n    ```mlir\\n    %2 = spirv.Tosa.MatMul %arg0, %arg1, %0, %1 : !spirv.arm.tensor<8x2x3xi8>, !spirv.arm.tensor<8x3x8xi8>, !spirv.arm.tensor<1xi8>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<8x2x8xi32>\\n    %2 = spirv.Tosa.MatMul %arg0, %arg1, %0, %1 : !spirv.arm.tensor<15x39x50xf16>, !spirv.arm.tensor<15x50x24xf16>, !spirv.arm.tensor<1xf16>, !spirv.arm.tensor<1xf16> -> !spirv.arm.tensor<15x39x24xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"SPIRV_TosaNumerical_TensorArm3D\" },\n      { \"name\": \"B\", \"type\": \"SPIRV_TosaNumerical_TensorArm3D\" },\n      { \"name\": \"A_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"B_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm3D\" }\n    ],\n    \"assemblyFormat\": \"$A `,`\\n    $B `,`\\n    $A_zp `,`\\n    $B_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Maximum\",\n    \"summary\": \"Maximum.\",\n    \"description\": \"Elementwise maximum of input1 and input2. Axis of size 1 will be broadcast,\\n    as necessary. Rank of input tensors must match. Integer element types are\\n    always interpreted as signed.\\n    NaN Propagation Mode is ignored for inputs using integer element types.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_maximum\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_maximum\\n\\n    #### Example:\\n    ```mlir\\n    %1 = spirv.Tosa.Maximum nan_mode = <Propagate>, %arg0, %arg1 : !spirv.arm.tensor<1x2x65533x1xi32>, !spirv.arm.tensor<1x2x65533x2xi32> -> !spirv.arm.tensor<1x2x65533x2xi32>\\n    %1 = spirv.Tosa.Maximum nan_mode = <Ignore>, %arg0, %arg1 : !spirv.arm.tensor<1x12x14x7xf16>, !spirv.arm.tensor<11x12x14x7xf16> -> !spirv.arm.tensor<11x12x14x7xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nan_mode\", \"type\": \"SPIRV_TosaExtNaNPropagationModeAttr{Propagate|Ignore}\" }\n    ],\n    \"assemblyFormat\": \"`nan_mode` `=` $nan_mode `,`\\n    $input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.MaxPool2D\",\n    \"summary\": \"Performs max pooling on the input.\",\n    \"description\": \"Performs a max pooling over the given input tensor. A sliding window of\\n    size given by <kernel size> is passed over the input tensor, with the\\n    maximum value being placed in the output tensor.\\n    NaN Propagation Mode is ignored for inputs using integer element types.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_max_pool2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_max_pool2d\\n\\n    #### Example:\\n    ```mlir\\n    %4 = spirv.Tosa.MaxPool2D kernel = [3, 2], stride = [1, 2], pad = [1, 0, 0, 1], nan_mode = <Propagate>, %arg0 : !spirv.arm.tensor<1x3x65537x1xi8> -> !spirv.arm.tensor<1x2x32769x1xi8>\\n    %4 = spirv.Tosa.MaxPool2D kernel = [3, 2], stride = [2, 2], pad = [1, 0, 1, 1], nan_mode = <Propagate>, %arg0 : !spirv.arm.tensor<1x6x65536x1xf32> -> !spirv.arm.tensor<1x3x32769x1xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 4 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"nan_mode\", \"type\": \"SPIRV_TosaExtNaNPropagationModeAttr{Propagate|Ignore}\" }\n    ],\n    \"assemblyFormat\": \"`kernel` `=` custom<SPIRV_I32_1DArmTensor>($kernel) `,`\\n    `stride` `=` custom<SPIRV_I32_1DArmTensor>($stride) `,`\\n    `pad` `=` custom<SPIRV_I32_1DArmTensor>($pad) `,`\\n    `nan_mode` `=` $nan_mode `,`\\n    $input\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Minimum\",\n    \"summary\": \"Minimum.\",\n    \"description\": \"Elementwise minimum of input1 and input2. Axis of size 1 will be broadcast,\\n    as necessary. Rank of input tensors must match. Integer element types are\\n    always interpreted as signed.\\n    NaN Propagation Mode is ignored for inputs using integer element types.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_minimum\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_minimum\\n\\n    #### Example:\\n    ```mlir\\n    %1 = spirv.Tosa.Minimum nan_mode = <Propagate>, %arg0, %arg1 : !spirv.arm.tensor<15x2x10x11xi32>, !spirv.arm.tensor<15x1x10x11xi32> -> !spirv.arm.tensor<15x2x10x11xi32>\\n    %1 = spirv.Tosa.Minimum nan_mode = <Propagate>, %arg0, %arg1 : !spirv.arm.tensor<1x65531x2x1xf32>, !spirv.arm.tensor<1x1x2x1xf32> -> !spirv.arm.tensor<1x65531x2x1xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nan_mode\", \"type\": \"SPIRV_TosaExtNaNPropagationModeAttr{Propagate|Ignore}\" }\n    ],\n    \"assemblyFormat\": \"`nan_mode` `=` $nan_mode `,`\\n    $input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Mul\",\n    \"summary\": \"Multiplication operator.\",\n    \"description\": \"Elementwise Multiplication (Hadamard product) of input1 and input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors must\\n    match.  Integer element types are always interpreted as signed.\\n    The shift value is used to right shift the result (rounded up) and\\n    it is used only if input element type is i32 and it must be zero for the\\n    other element types. The behavior is undefined if the integer\\n    multiplication overflows or underflows the signed integer range or the\\n    shift value exceeds the bitwidth of i32.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_mul\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_mul\\n\\n    #### Example:\\n    ```mlir\\n    %1 = spirv.Tosa.Mul %arg0, %arg1, %0 : !spirv.arm.tensor<34x21x39xi32>, !spirv.arm.tensor<34x21x1xi32>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<34x21x39xi32>\\n    %1 = spirv.Tosa.Mul %arg0, %arg1, %0 : !spirv.arm.tensor<57x1x55xf16>, !spirv.arm.tensor<57x37x55xf16>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<57x37x55xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"shift\", \"type\": \"SPIRV_Int8_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2 `,`\\n    $shift\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Negate\",\n    \"summary\": \"Negate operator.\",\n    \"description\": \"Elementwise Negation operation. Input and Output types must match. Integer\\n    element types are always interpreted as signed. The behaviour is undefined\\n    if the input value is min_value<si32>.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_negate\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_negate\\n\\n    #### Example:\\n    ```mlir\\n    %2 = spirv.Tosa.Negate %arg0, %0, %1 : !spirv.arm.tensor<3x1x65540x1xi8>, !spirv.arm.tensor<1xi8>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<3x1x65540x1xi8>\\n    %2 = spirv.Tosa.Negate %arg0, %0, %1 : !spirv.arm.tensor<2x7x15x13xf16>, !spirv.arm.tensor<1xf16>, !spirv.arm.tensor<1xf16> -> !spirv.arm.tensor<2x7x15x13xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input1_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"output_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input1_zp `,`\\n    $output_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Pow\",\n    \"summary\": \"Power operator.\",\n    \"description\": \"Elementwise input1 value raised to the Power of input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors must\\n    match. The behavior is undefined if the the input1 value is negative, or\\n    both input values are zero or negative, or both input values are NaN or\\n    infinite.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_pow\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_pow\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Pow %arg0, %arg1 : !spirv.arm.tensor<1x52x53xf16>, !spirv.arm.tensor<44x52x53xf16> -> !spirv.arm.tensor<44x52x53xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Reciprocal\",\n    \"summary\": \"Reciprocal operator.\",\n    \"description\": \"Elementwise Reciprocal operation. Input and Output types must match. For\\n    integer operation, a table should be used with the appropriate ranges.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_reciprocal\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_reciprocal\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Reciprocal %arg0 : !spirv.arm.tensor<38x47x44xf32> -> !spirv.arm.tensor<38x47x44xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.RFFT2D\",\n    \"summary\": \"Performs RFFT2D operation on the input.\",\n    \"description\": \"Performs a batched 2D real-valued Fast Fourier Transform over the input where\\n    the input tensor consists of real values producing complex valued output. The\\n    complex output values will be split into the output_real and output_imag\\n    tensor arguments. This operator takes advantage of Hermitian symmetry to only\\n    calculate the first half of the final output axis. Implementations may choose\\n    to skip calculation of the imaginary values at (0,0), (0,W/2), (H/2,0), and\\n    (H/2, W/2). If the calculation is skipped, the result at that location must be\\n    zero.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_rfft2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_rfft2d\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.RFFT2D local_bound = false, %arg0 : !spirv.arm.tensor<1x32x32xf32> -> !spirv.struct<(!spirv.arm.tensor<1x32x17xf32>, !spirv.arm.tensor<1x32x17xf32>)>\\n    %1 = spirv.CompositeExtract %0[0 : i32] : !spirv.struct<(!spirv.arm.tensor<1x32x17xf32>, !spirv.arm.tensor<1x32x17xf32>)>\\n    %2 = spirv.CompositeExtract %0[1 : i32] : !spirv.struct<(!spirv.arm.tensor<1x32x17xf32>, !spirv.arm.tensor<1x32x17xf32>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input_real\", \"type\": \"SPIRV_Float32_TensorArm3D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_Struct_2_Float32_TensorArm3D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"local_bound\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`local_bound` `=` $local_bound `,`\\n    $input_real\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Rsqrt\",\n    \"summary\": \"Reverse Square Root operator.\",\n    \"description\": \"Elementwise Reciprocal Square Root operation ($ 1/sqrt $). Input and\\n    Output types must match. For integer operation, a table should be used\\n    with the appropriate ranges.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_rsqrt\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_rsqrt\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Rsqrt %arg0 : !spirv.arm.tensor<40x57x56xf32> -> !spirv.arm.tensor<40x57x56xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Select\",\n    \"summary\": \"Select operator.\",\n    \"description\": \"Elementwise Select of the output based on a condition.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_select\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_select\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Select %cond, %trueVal, %falseVal : !spirv.arm.tensor<4x1x4x5xi1>, !spirv.arm.tensor<4x6x4x5xi8>, !spirv.arm.tensor<4x6x4x5xi8> -> !spirv.arm.tensor<4x6x4x5xi8>\\n    %0 = spirv.Tosa.Select %cond, %trueVal, %falseVal : !spirv.arm.tensor<9x2x15x8xi1>, !spirv.arm.tensor<9x2x15x8xf16>, !spirv.arm.tensor<9x1x15x8xf16> -> !spirv.arm.tensor<9x2x15x8xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"SPIRV_Bool_TensorArm\" },\n      { \"name\": \"true_value\", \"type\": \"SPIRV_TosaAny_TensorArm\" },\n      { \"name\": \"false_value\", \"type\": \"SPIRV_TosaAny_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaAny_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$condition `,`\\n    $true_value `,`\\n    $false_value\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Sigmoid\",\n    \"summary\": \"Sigmoid operator.\",\n    \"description\": \"Applies the sigmoid logistic function to each element of the input tensor:\\n    $ sigmoid(x) = \\\\frac{1}{1 + e^{-x}} $.\\n\\n    For quantized integer data types, the `spirv.Tosa.Table` operator should be used instead.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_sigmoid\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_sigmoid\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Sigmoid %arg0 : !spirv.arm.tensor<28x43x45xf32> -> !spirv.arm.tensor<28x43x45xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Sin\",\n    \"summary\": \"Sin operator.\",\n    \"description\": \"Elementwise Sine operation for values given in radians. Input and Output types must match.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_sin\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_sin\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Sin %arg0 : !spirv.arm.tensor<49x38x58xf16> -> !spirv.arm.tensor<49x38x58xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input1', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input1\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Sub\",\n    \"summary\": \"Subtraction operator.\",\n    \"description\": \"Elementwise Subtraction of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match. Integer element\\n    types are always interpreted as signed. The behavior is undefined if the\\n    integer subtraction overflows or underflows the signed integer range.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_sub\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_sub\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Sub %arg0, %arg1 : !spirv.arm.tensor<6x10x6x6xi32>, !spirv.arm.tensor<1x10x6x6xi32> -> !spirv.arm.tensor<6x10x6x6xi32>\\n    %0 = spirv.Tosa.Sub %arg0, %arg1 : !spirv.arm.tensor<1x10x13x12xf16>, !spirv.arm.tensor<6x10x13x12xf16> -> !spirv.arm.tensor<6x10x13x12xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" },\n      { \"name\": \"input2\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $input2\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Table\",\n    \"summary\": \"Table lookup operator.\",\n    \"description\": \"Table lookup operation. For int8_t, perform a 256 entry table lookup\\n    returning an int8_t value. For int16_t tables, the int16_t input is treated\\n    as a fixed-point 9.7 value. The most significant 9 bits are used to index\\n    into the table. The fractional 7 bits are used to interpolate based on\\n    table[index] and table[index+1]. The behavior is undefined if during the\\n    interpolation step, the integer subtraction table[index+1] - table[index]\\n    overflows or underflows the signed int16 range.\\n\\n    For int16_t inputs, this operator returns a 16.7 interpolated value in an\\n    int32_t. This value can then be input to the `spirv.Tosa.Rescale` operator\\n    to scale to the required output data type. Note that int16_t table has 513\\n    values to handle table[index+1] when index=511.\\n\\n    An int16_t to int16_t table lookup can be constructed as follows:\\n    * Use the table operator to produce a fixed point 16.7 interpolated result\\n    * Use `spirv.Tosa.Rescale` (in_t=int32_t, out_t=int16_t, scale=1<<14, shift=21)\\n      to scale the output to int16_t range (or alternate scale as required)\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_table\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_table\\n\\n    #### Example:\\n    ```mlir\\n    %1 = spirv.Tosa.Table %arg0, %0 : !spirv.arm.tensor<3x2x15x7xi8>, !spirv.arm.tensor<256xi8> -> !spirv.arm.tensor<3x2x15x7xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"SPIRV_TosaInteger_TensorArm\" },\n      { \"name\": \"table\", \"type\": \"SPIRV_TosaInteger_TensorArm1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaInteger_TensorArm\" }\n    ],\n    \"assemblyFormat\": \"$input1 `,`\\n    $table\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.Tanh\",\n    \"summary\": \"Hyperbolic Tangent operator.\",\n    \"description\": \"Elementwise Parameterized Hyperbolic Tangent: $ tanh(x) = \\\\frac{1 - e^{-2x}}{1 + e^{-2x}} $.\\n\\n    For quantized integer data types, the `spirv.Tosa.Table` operator should be used instead.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_tanh\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_tanh\\n\\n    #### Example:\\n    ```mlir\\n    %0 = spirv.Tosa.Tanh %arg0 : !spirv.arm.tensor<46x50x36xf16> -> !spirv.arm.tensor<46x50x36xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaFloat_TensorArm\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'output']>\" }\n    ],\n    \"assemblyFormat\": \"$input\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Tosa.TransposeConv2D\",\n    \"summary\": \"Transpose 2D Convolution operator.\",\n    \"description\": \"Performs a 2D transposed convolution over the given tensor input, using the\\n    weights tensor. Implementations may choose to skip calculation of multiplies\\n    by zero at fractional input positions.\\n\\n    Input and weight have respective zero point values provided in input_zp and weight_zp.\\n\\n    References:\\n      * https://github.khronos.org/SPIRV-Registry/extended/TOSA.001000.1.html#_transpose_conv2d\\n      * https://www.mlplatform.org/tosa/tosa_spec_1_0_1.html#_transpose_conv2d\\n\\n    #### Example:\\n    ```mlir\\n    %6 = spirv.Tosa.TransposeConv2D out_pad = [0, 0, 0, 0], stride = [1, 1], acc_type = <INT48>, local_bound = false, %arg0, %arg1, %arg2, %4, %5 : !spirv.arm.tensor<1x13x33x3xi16>, !spirv.arm.tensor<11x1x3x3xi8>, !spirv.arm.tensor<1xi64>, !spirv.arm.tensor<1xi16>, !spirv.arm.tensor<1xi8> -> !spirv.arm.tensor<1x13x35x11xi64>\\n    %6 = spirv.Tosa.TransposeConv2D out_pad = [0, 1, 0, 0], stride = [1, 8], acc_type = <FP16>, local_bound = true, %arg0, %arg1, %arg2, %4, %5 : !spirv.arm.tensor<10x24x9x13xf16>, !spirv.arm.tensor<14x1x1x13xf16>, !spirv.arm.tensor<14xf16>, !spirv.arm.tensor<1xf16>, !spirv.arm.tensor<1xf16> -> !spirv.arm.tensor<10x25x65x14xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"weight\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" },\n      { \"name\": \"bias\", \"type\": \"SPIRV_TosaNumerical_TensorArm1D\" },\n      { \"name\": \"input_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" },\n      { \"name\": \"weight_zp\", \"type\": \"SPIRV_TosaNumerical_1DTensorArmOfLength1\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"SPIRV_TosaNumerical_TensorArm4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"out_pad\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 4 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<RankedI32ElementsAttr<[ 2 ]>, [SPIRV_DenseElementAttrsWithTensorArmType]>\" },\n      { \"name\": \"acc_type\", \"type\": \"SPIRV_TosaExtAccTypeAttr{INT32|FP16|FP32|INT48}\" },\n      { \"name\": \"local_bound\", \"type\": \"ConfinedAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`out_pad` `=` custom<SPIRV_I32_1DArmTensor>($out_pad) `,`\\n    `stride` `=` custom<SPIRV_I32_1DArmTensor>($stride) `,`\\n    `acc_type` `=` $acc_type `,`\\n    `local_bound` `=` $local_bound `,`\\n    $input `,`\\n    $weight `,`\\n    $bias `,`\\n    $input_zp `,`\\n    $weight_zp\\n    attr-dict `:` type(operands) `->` type(results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Transpose\",\n    \"summary\": \"Transpose a matrix.\",\n    \"description\": \"Result Type must be an OpTypeMatrix.\\n\\n    Matrix must be an object of type OpTypeMatrix. The number of columns and\\n    the column size of Matrix must be the reverse of those in Result Type.\\n    The types of the scalar components in Matrix and Result Type must be the\\n    same.\\n\\n    Matrix must have of type of OpTypeMatrix.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Transpose %matrix: !spirv.matrix<2 x vector<3xf32>> ->\\n    !spirv.matrix<3 x vector<2xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"SPIRV_AnyMatrix\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyMatrix\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($matrix) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UConvert\",\n    \"summary\": \"Convert unsigned width. This is either a truncate or a zero extend.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type, whose Signedness\\n    operand is 0.\\n\\n    Unsigned Value must be a scalar or vector of integer type.  It must have\\n    the same number of components as Result Type.  The component width\\n    cannot equal the component width in Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %1 = spirv.UConvert %0 : i32 to i64\\n    %3 = spirv.UConvert %2 : vector<3xi32> to vector<3xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UDiv\",\n    \"summary\": \"Unsigned-integer division of Operand 1 divided by Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type, whose Signedness\\n    operand is 0.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.UDiv %0, %1 : i32\\n    %5 = spirv.UDiv %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOrCoopMatrixOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UDot\",\n    \"summary\": \"Unsigned integer dot product of Vector 1 and Vector 2.\",\n    \"description\": \"Result Type must be an integer type with Signedness of 0 whose Width\\n    must be greater than or equal to that of the components of Vector 1 and\\n    Vector 2.\\n\\n    Vector 1 and Vector 2 must have the same type.\\n\\n    Vector 1 and Vector 2 must be either 32-bit integers (enabled by the\\n    DotProductInput4x8BitPacked capability) or vectors of integer type with\\n    Signedness of 0 (enabled by the DotProductInput4x8Bit or\\n    DotProductInputAll capability).\\n\\n    When Vector 1 and Vector 2 are scalar integer types, Packed Vector\\n    Format must be specified to select how the integers are to be\\n    interpreted as vectors.\\n\\n    All components of the input vectors are zero-extended to the bit width\\n    of the result's type. The zero-extended input vectors are then\\n    multiplied component-wise and all components of the vector resulting\\n    from the component-wise multiplication are added together. The resulting\\n    value will equal the low-order N bits of the correct result R, where N\\n    is the result width and R is computed with enough precision to avoid\\n    overflow and underflow.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %r = spirv.UDot %a, %b, <PackedVectorFormat4x8Bit> : i32 -> i32\\n    %r = spirv.UDot %a, %b, <PackedVectorFormat4x8Bit> : i32 -> i64\\n    %r = spirv.UDot %a, %b : vector<4xi8> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<SPIRV_PackedVectorFormatAttr{PackedVectorFormat4x8Bit}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" }\n    ],\n    \"assemblyFormat\": \"$vector1 `,` $vector2 ( `,` $format^ )? attr-dict `:`\\n      type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UDotAccSat\",\n    \"summary\": \"Unsigned integer dot product of Vector 1 and Vector 2 and unsigned\\n    saturating addition of the result with Accumulator.\",\n    \"description\": \"Result Type must be an integer type with Signedness of 0 whose Width\\n    must be greater than or equal to that of the components of Vector 1 and\\n    Vector 2.\\n\\n    Vector 1 and Vector 2 must have the same type.\\n\\n    Vector 1 and Vector 2 must be either 32-bit integers (enabled by the\\n    DotProductInput4x8BitPacked capability) or vectors of integer type with\\n    Signedness of 0 (enabled by the DotProductInput4x8Bit or\\n    DotProductInputAll capability).\\n\\n    The type of Accumulator must be the same as Result Type.\\n\\n    When Vector 1 and Vector 2 are scalar integer types, Packed Vector\\n    Format must be specified to select how the integers are to be\\n    interpreted as vectors.\\n\\n    All components of the input vectors are zero-extended to the bit width\\n    of the result's type. The zero-extended input vectors are then\\n    multiplied component-wise and all components of the vector resulting\\n    from the component-wise multiplication are added together. Finally, the\\n    resulting sum is added to the input accumulator. This final addition is\\n    saturating.\\n\\n    If any of the multiplications or additions, with the exception of the\\n    final accumulation, overflow or underflow, the result of the instruction\\n    is undefined.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %r = spirv.UDotAccSat %a, %b, %acc, <PackedVectorFormat4x8Bit> : i32 -> i32\\n    %r = spirv.UDotAccSat %a, %b, %acc, <PackedVectorFormat4x8Bit> : i32 -> i64\\n    %r = spirv.UDotAccSat %a, %b, %acc : vector<4xi8> -> i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"accumulator\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"OptionalAttr<SPIRV_PackedVectorFormatAttr{PackedVectorFormat4x8Bit}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['vector1', 'vector2']>\" },\n      { \"type\": \"AllTypesMatch<['accumulator', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$vector1 `,` $vector2 `,` $accumulator ( `,` $format^ )? attr-dict `:`\\n      type($vector1) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UGreaterThan\",\n    \"summary\": \"Unsigned-integer comparison if Operand 1 is greater than  Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.UGreaterThan %0, %1 : i32\\n    %5 = spirv.UGreaterThan %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UGreaterThanEqual\",\n    \"summary\": \"Unsigned-integer comparison if Operand 1 is greater than or equal to\\n    Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.UGreaterThanEqual %0, %1 : i32\\n    %5 = spirv.UGreaterThanEqual %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ULessThan\",\n    \"summary\": \"Unsigned-integer comparison if Operand 1 is less than Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.ULessThan %0, %1 : i32\\n    %5 = spirv.ULessThan %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.ULessThanEqual\",\n    \"summary\": \"Unsigned-integer comparison if Operand 1 is less than or equal to\\n    Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    The type of Operand 1 and Operand 2  must be a scalar or vector of\\n    integer type.  They must have the same component width, and they must\\n    have the same number of components as Result Type.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.ULessThanEqual %0, %1 : i32\\n    %5 = spirv.ULessThanEqual %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UMod\",\n    \"summary\": \"Unsigned modulo operation of Operand 1 modulo Operand 2.\",\n    \"description\": \"Result Type must be a scalar or vector of integer type, whose Signedness\\n    operand is 0.\\n\\n    The types of Operand 1 and Operand 2 both must be the same as Result\\n    Type.\\n\\n    Results are computed per component.  The resulting value is undefined\\n    if Operand 2 is 0.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.UMod %0, %1 : i32\\n    %5 = spirv.UMod %2, %3 : vector<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand1', 'operand2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.UMulExtended\",\n    \"summary\": \"Result is the full value of the unsigned integer multiplication of\\n    Operand 1 and Operand 2.\",\n    \"description\": \"Result Type must be from OpTypeStruct.  The struct must have two\\n    members, and the two members must be the same type.  The member type\\n    must be a scalar or vector of integer type, whose Signedness operand is\\n    0.\\n\\n    Operand 1 and Operand 2 must have the same type as the members of Result\\n    Type. These are consumed as unsigned integers.\\n\\n    Results are computed per component.\\n\\n    Member 0 of the result gets the low-order bits of the multiplication.\\n\\n    Member 1 of the result gets the high-order bits of the multiplication.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %2 = spirv.UMulExtended %0, %1 : !spirv.struct<(i32, i32)>\\n    %2 = spirv.UMulExtended %0, %1 : !spirv.struct<(vector<2xi32>, vector<2xi32>)>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Integer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_AnyStruct\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Undef\",\n    \"summary\": \"Make an intermediate object whose value is undefined.\",\n    \"description\": \"Result Type is the type of object to make.\\n\\n    Each consumption of Result `<id>` yields an arbitrary, possibly different\\n    bit pattern or abstract value resulting in possibly different concrete,\\n    abstract, or opaque values.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Undef : f32\\n    %1 = spirv.Undef : !spirv.struct<!spirv.array<4 x vector<4xi32>>>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Type\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Unordered\",\n    \"summary\": \"Result is true if either x or y is an IEEE NaN, otherwise result is\\n    false.\",\n    \"description\": \"Result Type must be a scalar or vector of Boolean type.\\n\\n    x must be a scalar or vector of floating-point type.  It must have the\\n    same number of components as Result Type.\\n\\n    y must have the same type as x.\\n\\n    Results are computed per component.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %4 = spirv.Unordered %0, %1 : f32\\n    %5 = spirv.Unordered %2, %3 : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" },\n      { \"name\": \"operand2\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_ScalarOrVectorOf<SPIRV_Bool>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operand1', 'result', 'getUnaryOpResultType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$operand1 `,` $operand2 `:` type($operand1) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Unreachable\",\n    \"summary\": \"Behavior is undefined if this instruction is executed.\",\n    \"description\": \"This instruction must be the last instruction in a block.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.Variable\",\n    \"summary\": \"Allocate an object in memory, resulting in a pointer to it, which can be\\n    used with OpLoad and OpStore.\",\n    \"description\": \"Result Type must be an OpTypePointer. Its Type operand is the type of\\n    object in memory.\\n\\n    Storage Class is the Storage Class of the memory holding the object.\\n    Since the op is used to model function-level variables, the storage class\\n    must be the `Function` Storage Class.\\n\\n    Initializer is optional. If Initializer is present, it will be the\\n    initial value of the variable's memory content. Initializer must be an\\n    `<id>` from a constant instruction or a global (module scope) OpVariable\\n    instruction. Initializer must have the same type as the type pointed to\\n    by Result Type.\\n\\n    From `SPV_KHR_physical_storage_buffer`:\\n    If an OpVariable's pointee type is a pointer (or array of pointers) in\\n    PhysicalStorageBuffer storage class, then the variable must be decorated\\n    with exactly one of AliasedPointer or RestrictPointer.\\n\\n    <!-- End of AutoGen section -->\\n\\n    ```\\n    variable-op ::= ssa-id `=` `spirv.Variable` (`init(` ssa-use `)`)?\\n                    attribute-dict? `:` spirv-pointer-type\\n    ```\\n\\n    where `init` specifies initializer.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.Constant ...\\n\\n    %1 = spirv.Variable : !spirv.ptr<f32, Function>\\n    %2 = spirv.Variable init(%0): !spirv.ptr<f32, Function>\\n\\n    %3 = spirv.Variable {aliased_pointer} :\\n      !spirv.ptr<!spirv.ptr<f32, PhysicalStorageBuffer>, Function>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"initializer\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"pointer\", \"type\": \"SPIRV_AnyPtr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"storage_class\", \"type\": \"SPIRV_StorageClassAttr{UniformConstant|Input|Uniform|Output|Workgroup|CrossWorkgroup|Private|Function|Generic|PushConstant|AtomicCounter|Image|StorageBuffer|CallableDataKHR|IncomingCallableDataKHR|RayPayloadKHR|HitAttributeKHR|IncomingRayPayloadKHR|ShaderRecordBufferKHR|PhysicalStorageBuffer|TaskPayloadWorkgroupEXT|CodeSectionINTEL|DeviceOnlyINTEL|HostOnlyINTEL}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.VectorExtractDynamic\",\n    \"summary\": \"Extract a single, dynamically selected, component of a vector.\",\n    \"description\": \"Result Type must be a scalar type.\\n\\n    Vector must have a type OpTypeVector whose Component Type is Result\\n    Type.\\n\\n    Index must be a scalar integer. It is interpreted as a 0-based index of\\n    which component of Vector to extract.\\n\\n    Behavior is undefined if Index's value is less than zero or greater than\\n    or equal to the number of components in Vector.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```\\n    %2 = spirv.VectorExtractDynamic %0[%1] : vector<8xf32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"SPIRV_Vector\" },\n      { \"name\": \"index\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Scalar\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'vector', 'result', '::llvm::cast<mlir::VectorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$vector `[` $index `]` attr-dict `:` type($vector) `,` type($index)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.VectorInsertDynamic\",\n    \"summary\": \"Make a copy of a vector, with a single, variably selected, component\\n    modified.\",\n    \"description\": \"Result Type must be an OpTypeVector.\\n\\n    Vector must have the same type as Result Type and is the vector that the\\n    non-written components are copied from.\\n\\n    Component is the value supplied for the component selected by Index. It\\n    must have the same type as the type of components in Result Type.\\n\\n    Index must be a scalar integer. It is interpreted as a 0-based index of\\n    which component to modify.\\n\\n    Behavior is undefined if Index's value is less than zero or greater than\\n    or equal to the number of components in Vector.\\n\\n    #### Example:\\n\\n    ```mlir\\n    %scalar = ... : f32\\n    %2 = spirv.VectorInsertDynamic %scalar, %0[%1] : vector<8xf32>, i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"SPIRV_Vector\" },\n      { \"name\": \"component\", \"type\": \"SPIRV_Scalar\" },\n      { \"name\": \"index\", \"type\": \"SPIRV_Integer\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Vector\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'vector', 'component', '::llvm::cast<mlir::VectorType>($_self).getElementType()'>\" },\n      { \"type\": \"AllTypesMatch<['vector', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$component `,` $vector `[` $index `]` attr-dict `:` type($vector) `,` type($index)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.VectorShuffle\",\n    \"summary\": \"Select arbitrary components from two vectors to make a new vector.\",\n    \"description\": \"Result Type must be an OpTypeVector. The number of components in Result\\n    Type must be the same as the number of Component operands.\\n\\n    Vector 1 and Vector 2 must both have vector types, with the same\\n    Component Type as Result Type. They do not have to have the same number\\n    of components as Result Type or with each other. They are logically\\n    concatenated, forming a single vector with Vector 1's components\\n    appearing before Vector 2's. The components of this logical vector are\\n    logically numbered with a single consecutive set of numbers from 0 to N\\n    - 1, where N is the total number of components.\\n\\n    Components are these logical numbers (see above), selecting which of the\\n    logically numbered components form the result. Each component is an\\n    unsigned 32-bit integer.  They can select the components in any order\\n    and can repeat components. The first component of the result is selected\\n    by the first Component operand,  the second component of the result is\\n    selected by the second Component operand, etc. A Component literal may\\n    also be FFFFFFFF, which means the corresponding result component has no\\n    source and is undefined. All Component literals must either be FFFFFFFF\\n    or in [0, N - 1] (inclusive).\\n\\n    Note: A vector “swizzle” can be done by using the vector for both Vector\\n    operands, or using an OpUndef for one of the Vector operands.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.VectorShuffle [1: i32, 3: i32, 5: i32] %vector1, %vector2 :\\n      vector<4xf32>, vector<2xf32> -> vector<3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector1\", \"type\": \"SPIRV_Vector\" },\n      { \"name\": \"vector2\", \"type\": \"SPIRV_Vector\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_Vector\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"components\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $components $vector1 `,` $vector2 `:`\\n      type($vector1) `,` type($vector2) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.VectorTimesMatrix\",\n    \"summary\": \"Linear-algebraic Vector X Matrix.\",\n    \"description\": \"Result Type must be a vector of floating-point type.\\n\\n    Vector must be a vector with the same Component Type as the Component\\n    Type in Result Type. Its number of components must equal the number of\\n    components in each column in Matrix.\\n\\n    Matrix must be a matrix with the same Component Type as the Component\\n    Type in Result Type. Its number of columns must equal the number of\\n    components in Result Type.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %result = spirv.VectorTimesMatrix %vector, %matrix : vector<4xf32>, !spirv.matrix<4 x vector<4xf32>> -> vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"SPIRV_VectorOf<SPIRV_Float>\" },\n      { \"name\": \"matrix\", \"type\": \"SPIRV_MatrixOf<SPIRV_Float>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SPIRV_VectorOf<SPIRV_Float>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($vector) `,` type($matrix) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"spirv.VectorTimesScalar\",\n    \"summary\": \"Scale a floating-point vector.\",\n    \"description\": \"Result Type must be a vector of floating-point type.\\n\\n     The type of Vector must be the same as Result Type. Each component of\\n    Vector is multiplied by Scalar.\\n\\n    Scalar must have the same type as the Component Type in Result Type.\\n\\n    <!-- End of AutoGen section -->\\n\\n    #### Example:\\n\\n    ```mlir\\n    %0 = spirv.VectorTimesScalar %vector, %scalar : vector<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"VectorOfLengthAndType<[2, 3, 4], [SPIRV_Float]>\" },\n      { \"name\": \"scalar\", \"type\": \"SPIRV_Float\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfLengthAndType<[2, 3, 4], [SPIRV_Float]>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type(operands) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stablehlo.abs\",\n    \"summary\": \"Abs operation\",\n    \"description\": \"Performs element-wise abs operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#abs\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.abs %operand : tensor<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[ HLO_SInt, HLO_Float, HLO_Complex, HLO_QuantizedInt ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[ HLO_SInt, HLO_Float, HLO_QuantizedInt ]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.add\",\n    \"summary\": \"Add operation\",\n    \"description\": \"Performs element-wise addition of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#add\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.add %lhs, %rhs : tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.after_all\",\n    \"summary\": \"AfterAll operation\",\n    \"description\": \"Ensures that the operations producing the `inputs` are executed before any\\n    operations that depend on `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#after_all\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.after_all %input0, %input1 : !stablehlo.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Token>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Token\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict\\n      `:` custom<VariadicSameOperandsAndResultType>(ref($inputs), type($inputs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.all_gather\",\n    \"summary\": \"AllGather operation\",\n    \"description\": \"Within each process group in the process grid, concatenates the values of the\\n    `operand` tensor from each process along `all_gather_dim` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_gather\\n\\n    Example:\\n    ```mlir\\n    %result:2 = \\\"stablehlo.all_gather\\\"(%operand0, %operand1) {\\n      all_gather_dim = 1 : i64,\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<2x2xi64>, tensor<2x2xi64>) -> (tensor<2x4xi64>, tensor<2x4xi64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"all_gather_dim\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<StableHLO_ChannelHandle>\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.all_reduce\",\n    \"summary\": \"AllReduce operation\",\n    \"description\": \"Within each process group in the process grid, applies a reduction function\\n    `computation` to the values of the `operand` tensor from each process and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_reduce\\n\\n    Example:\\n    ```mlir\\n    %result:2 = \\\"stablehlo.all_reduce\\\"(%operand0, %operand0) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n      %0 = \\\"stablehlo.add\\\"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>\\n      \\\"stablehlo.return\\\"(%0) : (tensor<i64>) -> ()\\n    }) {\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<4xi64>, tensor<4xi64>) -> (tensor<4xi64>, tensor<4xi64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<StableHLO_ChannelHandle>\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.all_to_all\",\n    \"summary\": \"AllToAll operation\",\n    \"description\": \"Within each process group in the process grid, splits the values of the\\n    `operand` tensor along `split_dimension` into parts, scatters the split parts\\n    between the processes, concatenates the scattered parts along `concat_dimension`\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_to_all\\n\\n    Example:\\n    ```mlir\\n    %result:2 = \\\"stablehlo.all_to_all\\\"(%operand1, %operand2) {\\n      split_dimension = 1 : i64,\\n      concat_dimension = 0 : i64,\\n      split_count = 2 : i64,\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>\\n    } : (tensor<2x4xi64>, tensor<2x4xi64>) -> (tensor<4x2xi64>, tensor<4x2xi64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"concat_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"split_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<StableHLO_ChannelHandle>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.and\",\n    \"summary\": \"And operation\",\n    \"description\": \"Performs element-wise AND of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#and\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.and %lhs, %rhs : tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_PredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.atan2\",\n    \"summary\": \"Atan2 operation\",\n    \"description\": \"Performs element-wise atan2 operation on `lhs` and `rhs` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#atan2\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.atan2 %lhs, %rhs : tensor<3xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.batch_norm_grad\",\n    \"summary\": \"BatchNormGrad operation\",\n    \"description\": \"Computes gradients of several inputs of BatchNormTrainingOp backpropagating\\n    from `grad_output`, and produces `grad_operand`, `grad_scale` and\\n    `grad_offset` tensors.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#batch_norm_grad\\n\\n    Example:\\n    ```mlir\\n    %grad_operand, %grad_scale, %grad_offset =\\n    \\\"stablehlo.batch_norm_grad\\\"(%operand, %scale, %mean, %variance, %grad_output) {\\n      epsilon = 0.0 : f32,\\n      feature_index = 2 : i64\\n    } : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>,\\n         tensor<2x2x2xf64>) -> (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"scale\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"mean\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"variance\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"grad_output\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_operand\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"grad_scale\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"grad_offset\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"feature_index\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.batch_norm_inference\",\n    \"category\": \"Normalization\",\n    \"summary\": \"BatchNormInference operation\",\n    \"description\": \"Normalizes the `operand` tensor across all dimensions except for the\\n    `feature_index` dimension and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#batch_norm_inference\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.batch_norm_inference\\\"(%operand, %scale, %offset, %mean, %variance) {\\n      epsilon = 0.0 : f32,\\n      feature_index = 2 : i64\\n    } : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>) -> tensor<2x2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"scale\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"offset\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"mean\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"variance\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"feature_index\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.batch_norm_training\",\n    \"summary\": \"BatchNormTraining operation\",\n    \"description\": \"Computes mean and variance across batch and spatial dimensions and\\n    normalizes the `operand` tensor, for each feature in the `feature_index`\\n    dimension and produces `output`, `batch_mean` and `batch_var` tensors.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#batch_norm_training\\n\\n    Example:\\n    ```mlir\\n    %output, %batch_mean, %batch_var = \\\"stablehlo.batch_norm_training\\\"(%operand, %scale, %offset) {\\n      epsilon = 0.0 : f32,\\n      feature_index = 2 : i64\\n    } : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>) ->\\n        (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"scale\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"offset\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"RankedTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"batch_mean\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" },\n      { \"name\": \"batch_var\", \"type\": \"1DTensorOf<[HLO_Float, HLO_QuantizedInt]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"feature_index\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.bitcast_convert\",\n    \"summary\": \"BitcastConvert operation\",\n    \"description\": \"Performs a bitcast operation on `operand` tensor and produces a `result`\\n    tensor where the bits of the entire `operand` tensor are reinterpreted using\\n    the type of the `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#bitcast_convert\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.bitcast_convert %operand : (tensor<f64>) -> tensor<4xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.broadcast\",\n    \"summary\": \"Broadcast operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as XLA's Broadcast:\\n    https://www.tensorflow.org/xla/operation_semantics#broadcast\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.broadcast %operand, sizes = [1, 2] : (tensor<3xi32>) -> tensor<1x2x3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `sizes` `=` $broadcast_sizes\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.broadcast_in_dim\",\n    \"category\": \"Shape\",\n    \"summary\": \"BroadcastInDim operation\",\n    \"description\": \"Expands the dimensions and/or rank of an input tensor by duplicating the\\n    data in the `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#broadcast_in_dim\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.broadcast_in_dim %operand, dims = [2, 1] : (tensor<1x3xi32>) -> tensor<2x3x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_StaticShapeTensorPerAxisQuantizedTensorOrBoundedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dims` `=` $broadcast_dimensions\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.case\",\n    \"summary\": \"Case operation\",\n    \"description\": \"Produces the output from executing exactly one `function` from `branches`\\n    depending on the value of `index`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#case\\n\\n    Example:\\n    ```mlir\\n    %result0, %result1 = \\\"stablehlo.case\\\"(%index) ({\\n      stablehlo.return %result_branch0, %result_branch0 : tensor<2xi64>, tensor<2xi64>\\n    }, {\\n      stablehlo.return %result_branch1, %result_branch1 : tensor<2xi64>, tensor<2xi64>\\n    }) : (tensor<i32>) -> (tensor<2xi64>, tensor<2xi64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"I32RankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrToken>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.cbrt\",\n    \"summary\": \"Cbrt operation\",\n    \"description\": \"Performs element-wise cubic root operation on `operand` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#cbrt\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.cbrt %operand : tensor<4xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.ceil\",\n    \"summary\": \"Ceil operation\",\n    \"description\": \"Performs element-wise ceil of `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#ceil\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.ceil %operand : tensor<5xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.cholesky\",\n    \"summary\": \"Cholesky operation\",\n    \"description\": \"Computes the Cholesky decomposition of a batch of matrices.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#cholesky\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.cholesky %a, lower = true : tensor<3x3xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$a (`,` `lower` `=` $lower^)? attr-dict `:` custom<SameOperandsAndResultType>(type($a), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.clamp\",\n    \"category\": \"Activation\",\n    \"summary\": \"Clamp operation\",\n    \"description\": \"Clamps every element of the `operand` tensor between a minimum and maximum\\n    value and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#clamp\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.clamp %min, %operand, %max : tensor<3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"min\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"max\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$min `,` $operand `,` $max attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($min), type($operand), type($max), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.collective_broadcast\",\n    \"summary\": \"CollectiveBroadcast operation\",\n    \"description\": \"Within each process group in the process grid, send the value of the\\n    `operand` tensor from the source process to the target processes and produce a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#collective_broadcast\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.collective_broadcast\\\"(%operand) {\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<1x2xi64>) -> tensor<1x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<StableHLO_ChannelHandle>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.collective_permute\",\n    \"summary\": \"CollectivePermute operation\",\n    \"description\": \"Within each process group in the process grid, sends the value of the\\n    `operand` tensor from the source process to the target process and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#collective_permute\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.collective_permute\\\"(%operand) {\\n      source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>,\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<2x2xi64>) -> tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_target_pairs\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<StableHLO_ChannelHandle>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.compare\",\n    \"summary\": \"Compare operation\",\n    \"description\": \"Performs element-wise comparison of `lhs` and `rhs` tensors according to\\n    `comparison_direction` and `compare_type`, and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#compare\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.compare LT, %lhs, %rhs, FLOAT : (tensor<2xf32>, tensor<2xf32>) -> tensor<2xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_PredTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"comparison_direction\", \"type\": \"StableHLO_ComparisonDirectionAttr{EQ|NE|GE|GT|LE|LT}\" },\n      { \"name\": \"compare_type\", \"type\": \"OptionalAttr<StableHLO_ComparisonTypeAttr{NOTYPE|FLOAT|TOTALORDER|SIGNED|UNSIGNED}>\" }\n    ],\n    \"assemblyFormat\": \"$comparison_direction `,` $lhs `,` $rhs (`,` $compare_type^)?\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.complex\",\n    \"summary\": \"Complex operation\",\n    \"description\": \"Performs element-wise conversion to a complex value from a pair of real and\\n    imaginary values, `lhs` and `rhs`, and produces a `result` tensor.\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#complex\\n    Example:\\n    ```mlir\\n    %result = stablehlo.complex %lhs, %rhs : tensor<2xcomplex<f64>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Fp32Or64Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Fp32Or64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_ComplexTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\\n      `:` custom<ComplexOpType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.composite\",\n    \"summary\": \"Composite operation\",\n    \"description\": \"Encapsulates an operation made up (composed) of other StableHLO operations,\\n    taking `inputs` and `composite_attributes` and producing `results`. The\\n    semantics of the op are implemented by the `decomposition` attribute. The\\n    `composite` op can be replaced with its decomposition without changing program\\n    semantics. In cases where inlining the decomposition does not provide the same\\n    op semantics, prefer using `custom_call`.\\n\\n    The `version` field (defaults to `0`) is used to denote when a composite's\\n    semantics change.\\n\\n    The intent of `composite_regions` is to only be used to model ops with\\n    bodies, regions are thrown away if the fallback decomposition function gets\\n    inlined.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#composite\\n\\n    Example:\\n    ```mlir\\n    %results = stablehlo.composite \\\"my.op\\\" %input0, %input1 {\\n      composite_attributes = {\\n        my_attribute = \\\"my_value\\\"\\n      },\\n      decomposition = @my_op,\\n      version = 1 : i32\\n    } : (tensor<f32>, tensor<f32>) -> tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrTokenOrTuple>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrTokenOrTuple>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"composite_attributes\", \"type\": \"DefaultValuedOptionalAttr<DictionaryAttr, {}>\" },\n      { \"name\": \"decomposition\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"version\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 0>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"composite_regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"$name operands (` ` `(` $composite_regions^ `)`)? attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.concatenate\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Concatenate operation\",\n    \"description\": \"Concatenates a variadic number of tensors in `inputs` along `dimension`\\n    dimension in the same order as the given arguments and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#concatenate\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.concatenate %input0, %input1, dim = 0 : (tensor<3x2xi64>, tensor<1x2xi64>) -> tensor<4x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"custom<VariadicOperandWithAttribute>($inputs) `dim` `=` $dimension attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.constant\",\n    \"summary\": \"Constant operation\",\n    \"description\": \"Produces an `output` tensor from a constant `value`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#constant\\n\\n    Example:\\n    ```mlir\\n    %output = stablehlo.constant dense<[[0.0, 1.0], [2.0, 3.0]]> : tensor<2x2xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"HLO_StaticShapeTensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stablehlo.convert\",\n    \"summary\": \"Convert operation\",\n    \"description\": \"Performs an element-wise conversion from one element type to another on\\n    `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#convert\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.convert %operand : (tensor<3xi64>) -> tensor<3xcomplex<f64>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_NonQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_NonQuantizedTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.convolution\",\n    \"category\": \"Layer\",\n    \"summary\": \"Convolution operation\",\n    \"description\": \"Computes dot products between windows of `lhs` and slices of `rhs` and\\n    produces `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#convolution\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.convolution(%lhs, %rhs)\\n      dim_numbers = [b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f],\\n      window = {\\n        stride = [4, 4],\\n        pad = [[0, 0], [0, 0]],\\n        lhs_dilate = [2, 2],\\n        rhs_dilate = [1, 1],\\n        reverse = [0, 0]\\n      } {\\n        feature_group_count = 1 : i64,\\n        batch_group_count = 1 : i64,\\n        precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]\\n      } :\\n    (tensor<1x4x4x1xi64>, tensor<3x3x1x1xi64>) -> tensor<1x2x2x1xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"window_reversal\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"StableHLO_ConvDimensionNumbers\" },\n      { \"name\": \"feature_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"batch_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StableHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ],\n    \"assemblyFormat\": \"`(`operands`)`\\n       `dim_numbers` `=` custom<ConvolutionDimensions>($dimension_numbers) `,`\\n       `window` `=` `{` custom<WindowAttributes>($window_strides, $padding,\\n                                                 $lhs_dilation, $rhs_dilation,\\n                                                 $window_reversal) `}`\\n       attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.cosine\",\n    \"summary\": \"Cosine operation\",\n    \"description\": \"Performs element-wise cosine operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#cosine\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.cosine %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.count_leading_zeros\",\n    \"summary\": \"Clz operation\",\n    \"description\": \"Performs element-wise count of the number of leading zero bits in the\\n    `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#count_leading_zeros\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.count_leading_zeros %operand : tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.create_token\",\n    \"summary\": \"CreateToken operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as AfterAllOp with 0 inputs:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#after_all\\n\\n    Example:\\n    ```mlir\\n    %output = stablehlo.create_token : !stablehlo.token\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"HLO_Token\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"stablehlo.cross-replica-sum\",\n    \"summary\": \"CrossReplicaSum operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as AllReduceOp with\\n    `channel_id = 0`, `use_global_device_ids = false` and `computation`\\n    implementing addition:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#all_reduce\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.cross-replica-sum\\\"(%operand) {\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>\\n    } : (tensor<4xf32>) -> tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.custom_call\",\n    \"summary\": \"CustomCall operation\",\n    \"description\": \"Encapsulates an implementation-defined operation `call_target_name` that\\n    takes `inputs` and `called_computations` and produces `results`.\\n\\n    Depending on the API version there are two ways to pass extra bits of static\\n    information to the external function:\\n    1. Use `API_VERSION_TYPED_FFI` which allows passing a dictionary attribute.\\n    2. Use a previous API version with a StringAttr to encode backend config.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#custom_call\\n\\n    Example:\\n    ```mlir\\n    %results = stablehlo.custom_call @foo(%input0) {\\n      backend_config = {bar = 42 : i32},\\n      api_version = 4 : i32,\\n      called_computations = [@foo]\\n    } : (tensor<f64>) -> tensor<f64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_CustomCallValue>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_CustomCallValue>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"call_target_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"has_side_effect\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"backend_config\", \"type\": \"OptionalAttr<AnyAttrOf<[ StrAttr, DictionaryAttr ]>>\" },\n      { \"name\": \"api_version\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_CustomCallApiVersionAttr{API_VERSION_UNSPECIFIED|API_VERSION_ORIGINAL|API_VERSION_STATUS_RETURNING|API_VERSION_STATUS_RETURNING_UNIFIED|API_VERSION_TYPED_FFI}, ::mlir::stablehlo::CustomCallApiVersion::API_VERSION_ORIGINAL>\" },\n      { \"name\": \"called_computations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<FlatSymbolRefAttr>, {}>\" },\n      { \"name\": \"operand_layouts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StableHLO_LayoutAttr>>\" },\n      { \"name\": \"result_layouts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StableHLO_LayoutAttr>>\" },\n      { \"name\": \"output_operand_aliases\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StableHLO_OutputOperandAlias, Aliasing attribute for outputs and operands of CustomCall>, {}>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomCallTarget>($call_target_name) `(` $inputs `)`\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.divide\",\n    \"summary\": \"Div operation\",\n    \"description\": \"Performs element-wise division of dividend `lhs` and divisor `rhs` tensors\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#divide\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.divide %lhs, %rhs : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.dot\",\n    \"summary\": \"Dot operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as XLA's Dot:\\n    https://www.tensorflow.org/xla/operation_semantics#dot\\n\\n    Example:\\n    ```mlir\\n    %0 = stablehlo.dot %arg0, %arg1 : (tensor<1x2xi32>, tensor<2x1xi32>) -> tensor<1x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StableHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `` custom<PrecisionConfig>($precision_config) attr-dict\\n      `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dot_general\",\n    \"summary\": \"DotGeneral operation\",\n    \"description\": \"Computes dot products between slices of `lhs` and slices of `rhs` and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dot_general\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.dot_general %lhs, %rhs,\\n      batching_dims = [0] x [0],\\n      contracting_dims = [2] x [1],\\n      precision = [DEFAULT, DEFAULT],\\n      algorithm = <lhs_precision_type = tf32, rhs_precision_type = tf32, accumulation_type = f32, lhs_component_count = 1, rhs_component_count = 1, num_primitive_operations = 1, allow_imprecise_accumulation = false>\\n      : (tensor<2x2x2xi64>, tensor<2x2x2xi64>) -> tensor<2x2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dot_dimension_numbers\", \"type\": \"StableHLO_DotDimensionNumbers\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StableHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" },\n      { \"name\": \"algorithm\", \"type\": \"OptionalAttr<StableHLO_DotAlgorithm>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `,` custom<DotDimensionNumbers>($dot_dimension_numbers) ``\\n    custom<PrecisionConfigAndAlgorithm>($precision_config, $algorithm) attr-dict\\n      `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dynamic_broadcast_in_dim\",\n    \"summary\": \"DynamicBroadcastInDim operation\",\n    \"description\": \"This operation is functionally identical to\\n    [broadcast_in_dim](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#broadcast_in_dim)\\n    op, but the result shape is specified dynamically via `output_dimensions`.\\n\\n    It also accepts optional attributes to express static knowledge about the\\n    expanding behavior of dimensions. If not specified, all dimensions are\\n    assumed to be possibly expanding. The sets of dimensions that are known to\\n    be expanding and the set of dimensions that are known to be non-expanding\\n    must be disjoint and they must be a subset of the operand's dimensions.\\n\\n    See: https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_broadcast_in_dim\\n\\n    Example:\\n    ```mlir\\n    %operand = stablehlo.constant dense<[[1, 2, 3]]> : tensor<1x3xi64>\\n    %output_dimensions = stablehlo.constant dense<[2, 3, 2]> : tensor<3xi64>\\n    %result = \\\"stablehlo.dynamic_broadcast_in_dim\\\"(%operand, %output_dimensions) {\\n      broadcast_dimensions = array<i64: 2, 1>,\\n      known_expanding_dimensions = array<i64: 0>,\\n      known_nonexpanding_dimensions = array<i64: 1>\\n    } : (tensor<1x3xi64>, tensor<3xi64>) -> tensor<2x3x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" },\n      { \"name\": \"output_dimensions\", \"type\": \"HLO_StaticDimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"known_expanding_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"known_nonexpanding_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $output_dimensions `,` `dims` `=` $broadcast_dimensions\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dynamic_conv\",\n    \"summary\": \"DynamicConv operation\",\n    \"description\": \"This operation is functionally identical to\\n    [convolution](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#convolution)\\n    op, but the padding is specified dynamically via `padding`.\\n\\n    Example:\\n    ```mlir\\n    %padding = stablehlo.constant dense<2> : tensor<2x2xi64>\\n    %result = \\\"stablehlo.dynamic_conv\\\"(%lhs, %rhs, %padding) {\\n      window_strides = array<i64: 4, 4>,\\n      lhs_dilation = array<i64: 2, 2>,\\n      rhs_dilation = array<i64: 1, 1>,\\n      window_reversal = array<i1: false, false>,\\n      dimension_numbers = #stablehlo.conv<[b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f]>,\\n      batch_group_count = 1 : i64,\\n      feature_group_count = 1 : i64,\\n      precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]\\n    } : (tensor<1x4x4x1xi64>, tensor<3x3x1x1xi64>, tensor<2x2xi64>) -> tensor<1x2x2x1xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"padding\", \"type\": \"HLO_Static2DIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"window_reversal\", \"type\": \"OptionalAttr<DenseBoolArrayAttr>\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"StableHLO_ConvDimensionNumbers\" },\n      { \"name\": \"feature_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"batch_group_count\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"precision_config\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StableHLO_PrecisionAttr{DEFAULT|HIGH|HIGHEST}>>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.dynamic_gather\",\n    \"summary\": \"DynamicGather operation\",\n    \"description\": \"This operation is functionally identical to\\n    [gather](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#gather)\\n    op, with the `slice_sizes` specified dynamically as an operand.\\n\\n    Example:\\n    ```mlir\\n    %slice_sizes = stablehlo.constant dense<[1, 2, 2]> : tensor<3xi64>\\n    %result = \\\"stablehlo.dynamic_gather\\\"(%operand, %start_indices, %slice_sizes) {\\n      dimension_numbers = #stablehlo.gather<\\n        offset_dims = [2, 3],\\n        collapsed_slice_dims = [0],\\n        start_index_map = [0, 2],\\n        index_vector_dim = 2>,\\n      indices_are_sorted = false\\n    } : (tensor<3x4x2xi64>, tensor<2x3x2xi64>, tensor<3xi64>) -> tensor<2x3x2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"HLO_IntTensor\" },\n      { \"name\": \"slice_sizes\", \"type\": \"HLO_Static1DIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StableHLO_GatherDimensionNumbers\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.dynamic_iota\",\n    \"summary\": \"DynamicIota operation\",\n    \"description\": \"This operation is functionally identical to\\n    [iota](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#iota)\\n    op, but the result shape is specified dynamically via `output_shape`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_iota\\n\\n    Example:\\n    ```mlir\\n    %output_shape = stablehlo.constant dense<[4, 5]> : tensor<2xi64>\\n    %0 = stablehlo.dynamic_iota %output_shape, dim = 0 : (tensor<2xi64>) -> tensor<4x5xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"output_shape\", \"type\": \"HLO_StaticDimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$output_shape `,` `dim` `=` $iota_dimension attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dynamic_pad\",\n    \"summary\": \"DynamicPad operation\",\n    \"description\": \"This operation is functionally identical to\\n    [pad](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#pad)\\n    https://github.com/openxla/stablehlo/pull/2306#discussion_r1595669709\\n    op, but with `edge_padding_low`, `edge_padding_high` and `interior_padding`\\n    specified dynamically as values.\\n\\n    See: https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_pad\\n\\n    Example:\\n    ```mlir\\n    %edge_padding_low = stablehlo.constant dense<[0, 1]> : tensor<2xi32>\\n    %edge_padding_high = stablehlo.constant dense<[2, 1]> : tensor<2xi32>\\n    %interior_padding = stablehlo.constant dense<[1, 2]> : tensor<2xi32>\\n    %result = stablehlo.dynamic_pad %operand, %padding_value,\\n                %edge_padding_low, %edge_padding_high, %interior_padding\\n                : (tensor<2x3xi64>, tensor<i64>, tensor<2xi64>, tensor<2xi64>, tensor<2xi64>) -> tensor<5x9xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"HLO_ScalarTensor\" },\n      { \"name\": \"edge_padding_low\", \"type\": \"HLO_StaticDimensionTensor\" },\n      { \"name\": \"edge_padding_high\", \"type\": \"HLO_StaticDimensionTensor\" },\n      { \"name\": \"interior_padding\", \"type\": \"HLO_StaticDimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['edge_padding_low', 'edge_padding_high', 'interior_padding']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dynamic_reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"DynamicReshape operation\",\n    \"description\": \"This operation is functionally identical to\\n    [reshape](https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reshape)\\n    op, but the result shape is specified dynamically via `output_shape`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_reshape\\n\\n    Example:\\n    ```mlir\\n    %output_shape = stablehlo.constant dense<[3, 2]> : tensor<2xi64>\\n    %result = stablehlo.dynamic_reshape %operand, %output_shape : (tensor<2x3xi64>, tensor<2xi64>) -> tensor<3x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" },\n      { \"name\": \"output_shape\", \"type\": \"HLO_StaticDimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dynamic_slice\",\n    \"category\": \"Tensor\",\n    \"summary\": \"DynamicSlice operation\",\n    \"description\": \"Extracts a slice from the `operand` using dynamically-computed starting\\n    indices and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_slice\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.dynamic_slice %operand, %start_indices0, %start_indices1, sizes = [2, 2]\\n      : (tensor<4x4xi32>, tensor<i64>, tensor<i64>) -> tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<HLO_ScalarIntTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slice_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` custom<VariadicOperandWithAttribute>($start_indices)\\n      `sizes` `=` $slice_sizes attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.dynamic_update_slice\",\n    \"summary\": \"DynamicUpdateSlice operation\",\n    \"description\": \"Produces a `result` tensor which is equal to the `operand` tensor except\\n    that the slice starting at `start_indices` is updated with the values in\\n    `update`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#dynamic_update_slice\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.dynamic_update_slice %operand, %update, %start_indices0, %start_indices1\\n      : (tensor<4x4xi32>, tensor<2x2xi32>, tensor<i64>, tensor<i64>) -> tensor<4x4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"update\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<HLO_ScalarIntTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.einsum\",\n    \"summary\": \"Einsum operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as TF's einsum:\\n    https://www.tensorflow.org/api_docs/python/tf/einsum\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.einsum\\\"(%lhs, %rhs) {\\n      einsum_config = \\\"ab,bc->ac\\\"\\n    } : (tensor<4x16xf32>, tensor<16x4xf32>) -> tensor<4x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"einsum_config\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `,` `config` `=` $einsum_config attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.exponential\",\n    \"summary\": \"Exp operation\",\n    \"description\": \"Performs element-wise exponential operation on `operand` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#exponential\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.exponential %operand : tensor<2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.exponential_minus_one\",\n    \"summary\": \"Expm1 operation\",\n    \"description\": \"Performs element-wise exponential minus one operation on `operand` tensor\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#exponential_minus_one\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.exponential_minus_one %operand : tensor<2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.fft\",\n    \"summary\": \"Fft operation\",\n    \"description\": \"Performs the forward and inverse Fourier transforms for real and complex\\n    inputs/outputs.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#fft\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.fft %operand, type = FFT, length = [4] : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpOrComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fft_type\", \"type\": \"StableHLO_FftTypeAttr{FFT|IFFT|RFFT|IRFFT}\" },\n      { \"name\": \"fft_length\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `type` `=` $fft_type `,` `length` `=` $fft_length\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.floor\",\n    \"summary\": \"Floor operation\",\n    \"description\": \"Performs element-wise floor of `operand` tensor and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#floor\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.floor %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Gather operation\",\n    \"description\": \"Gathers slices from `operand` tensor from offsets specified in\\n    `start_indices` and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#gather\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.gather\\\"(%operand, %start_indices) {\\n      dimension_numbers = #stablehlo.gather<\\n        offset_dims = [3, 4],\\n        collapsed_slice_dims = [1],\\n        operand_batching_dims = [0],\\n        start_indices_batching_dims = [1],\\n        start_index_map = [2, 1],\\n        index_vector_dim = 3>,\\n      slice_sizes = array<i64: 1, 1, 2, 2>,\\n      indices_are_sorted = false\\n    } : (tensor<2x3x4x2xi64>, tensor<2x2x3x2xi64>) -> tensor<2x2x3x2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StableHLO_GatherDimensionNumbers\" },\n      { \"name\": \"slice_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.get_dimension_size\",\n    \"summary\": \"GetDimensionSize operation\",\n    \"description\": \"Produces the size of the given `dimension` of the `operand`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#get_dimension_size\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.get_dimension_size %operand, dim = 1 : (tensor<2x3xi64>) -> tensor<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32RankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dim` `=` $dimension attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.get_tuple_element\",\n    \"summary\": \"GetTupleElement operation\",\n    \"description\": \"Extracts element at `index` position of the `operand` tuple and produces a\\n    `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#get_tuple_element\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.get_tuple_element %operand[0] : (tuple<tensor<2xf64>, tuple<tensor<i64>>>) -> tensor<2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tuple\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensorOrTokenOrTupleOrBuffer\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `[` $index `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.if\",\n    \"summary\": \"If operation\",\n    \"description\": \"Produces the output from executing exactly one branch from `true_branch` or\\n    `false_branch` depending on the value of `pred`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#if\\n\\n    Example:\\n    %result = \\\"stablehlo.if\\\"(%pred) ({\\n      \\\"stablehlo.return\\\"(%result_true_branch) : (tensor<i32>) -> ()\\n    }, {\\n      \\\"stablehlo.return\\\"(%result_false_branch) : (tensor<i32>) -> ()\\n    }) : (tensor<i1>) -> tensor<i32>\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"HLO_PredTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrToken>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"true_branch\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"false_branch\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.imag\",\n    \"summary\": \"Imag operation\",\n    \"description\": \"Extracts the imaginary part, element-wise, from the `operand` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#imag\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.imag %operand : (tensor<2xcomplex<f32>>) -> tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.infeed\",\n    \"summary\": \"Infeed operation\",\n    \"description\": \"Reads data from the infeed and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#infeed\\n\\n    Example:\\n    ```mlir\\n    %results0:2 = \\\"stablehlo.infeed\\\"(%token) :\\n        (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"HLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_StaticShapeTensorOrPerAxisQuantizedTensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"infeed_config\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.iota\",\n    \"summary\": \"Iota operation\",\n    \"description\": \"Fills an `output` tensor with values in increasing order starting from zero\\n    along the `iota_dimension` dimension.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#iota\\n\\n    Example:\\n    ```mlir\\n    %output = stablehlo.iota dim = 0 : tensor<4x5xi32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"HLO_StaticShapeIntFpComplexOrQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"`dim` `=` $iota_dimension attr-dict `:` type($output)\"\n  },\n  {\n    \"name\": \"stablehlo.is_finite\",\n    \"summary\": \"IsFinite operation\",\n    \"description\": \"Performs element-wise check whether the value in `x` is finite (i.e. is\\n    neither +Inf, -Inf, nor NaN) and produces a `y` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#is_finite\\n\\n    Example:\\n    ```mlir\\n    %y = stablehlo.is_finite %x : (tensor<7xf64>) -> tensor<7xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"HLO_PredTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.log\",\n    \"summary\": \"Log operation\",\n    \"description\": \"Performs element-wise logarithm operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#log\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.log %operand : tensor<2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.log_plus_one\",\n    \"summary\": \"Log1p operation\",\n    \"description\": \"Performs element-wise logarithm plus one operation on `operand` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#log_plus_one\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.log_plus_one %operand : tensor<5xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.logistic\",\n    \"summary\": \"Logistic operation\",\n    \"description\": \"Performs element-wise logistic operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#logistic\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.logistic %operand : tensor<2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.map\",\n    \"summary\": \"Map operation\",\n    \"description\": \"Applies a map function `computation` to `inputs` along the `dimensions` and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#map\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.map\\\"(%input0, %input1) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n        %0 = stablehlo.multiply %arg0, %arg1 : tensor<i64>\\n        stablehlo.return %0 : tensor<i64>\\n    }) {\\n      dimensions = array<i64: 0, 1>\\n    } : (tensor<2x2xi64>, tensor<2x2xi64>) -> tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.maximum\",\n    \"summary\": \"Max operation\",\n    \"description\": \"Performs element-wise max operation on tensors `lhs` and `rhs` and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#maximum\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.maximum %lhs, %rhs : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.minimum\",\n    \"summary\": \"Min operation\",\n    \"description\": \"Performs element-wise min operation on tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#minimum\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.minimum %lhs, %rhs : tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.multiply\",\n    \"summary\": \"Mul operation\",\n    \"description\": \"Performs element-wise product of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#multiply\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.multiply %lhs, %rhs : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.negate\",\n    \"summary\": \"Neg operation\",\n    \"description\": \"Performs element-wise negation of `operand` tensor and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#negate\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.negate %operand : tensor<2x3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.not\",\n    \"summary\": \"Not operation\",\n    \"description\": \"Performs element-wise NOT of tensor `operand` of type integer and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#not\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.not %operand : tensor<5x3x1xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_PredOrIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.optimization_barrier\",\n    \"summary\": \"OptimizationBarrier operation\",\n    \"description\": \"Ensures that the operations that produce the `operand` are executed before any\\n    operations that depend on the `result` and prevents compiler transformations\\n    from moving operations across the barrier. Other than that, the operation is\\n    an identity, i.e. `result` = `operand`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#optimization_barrier\\n\\n    Example:\\n    ```mlir\\n    %result0, %result1 = stablehlo.optimization_barrier %operand0, %operand1 : tensor<f32>, tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<HLO_TensorOrToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_TensorOrToken>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operand^ `:` custom<PairwiseOpType>(type($operand), type($result))):(`(` `)`)?\"\n  },\n  {\n    \"name\": \"stablehlo.or\",\n    \"summary\": \"Or operation\",\n    \"description\": \"Performs element-wise OR of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#or\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.or %lhs, %rhs : tensor<2xi1>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_PredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.outfeed\",\n    \"summary\": \"Outfeed operation\",\n    \"description\": \"Writes `inputs` to the outfeed and produces a `result` token.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#outfeed\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.outfeed\\\"(%input0, %token) :\\n        (tensor<2x2x2xi64>, !stablehlo.token) -> !stablehlo.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensor>\" },\n      { \"name\": \"token\", \"type\": \"HLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Token\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outfeed_config\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.pad\",\n    \"category\": \"Transform\",\n    \"summary\": \"Pad operation\",\n    \"description\": \"Expands `operand` by padding around the tensor as well as between the\\n    elements of the tensor with the given `padding_value`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#pad\\n\\n    Example:\\n    ```mlir\\n    %0 = stablehlo.pad %arg0, %arg1, low = [0, 1], high = [2, 1], interior = [1, 2]\\n      : (tensor<2x3xi32>, tensor<i32>) -> tensor<5x9xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"HLO_ScalarTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"edge_padding_low\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"edge_padding_high\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"interior_padding\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $padding_value `,`\\n      `low` `=` $edge_padding_low `,`\\n      `high` `=` $edge_padding_high `,`\\n      `interior` `=` $interior_padding\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.partition_id\",\n    \"summary\": \"PartitionId operation\",\n    \"description\": \"Produces `partition_id` of the current process.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#partition_id\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.partition_id : tensor<ui32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"UI32RankedTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"stablehlo.popcnt\",\n    \"summary\": \"PopulationCount operation\",\n    \"description\": \"Performs element-wise count of the number of bits set in the `operand`\\n    tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#popcnt\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.popcnt %operand : tensor<4xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.power\",\n    \"summary\": \"Power operation\",\n    \"description\": \"Performs element-wise exponentiation of `lhs` tensor by `rhs` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#power\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.power %lhs, %rhs : tensor<6xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.real\",\n    \"summary\": \"Real operation\",\n    \"description\": \"Extracts the real part, element-wise, from the `operand` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#real\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.real %operand : (tensor<2xcomplex<f32>>) -> tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.real_dynamic_slice\",\n    \"summary\": \"RealDynamicSlice operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/8.\\n\\n    Informally, this operation does the same thing as SliceOp except\\n    that `start_indices`, `limit_indices` and `strides` are specified dynamically:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#slice\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.real_dynamic_slice %operand,\\n                %start_indices, %limit_indices, %strides\\n           : (tensor<256x?xf32>, tensor<2xindex>, tensor<2xindex>, tensor<2xindex>) -> tensor<256x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"HLO_DimensionTensor\" },\n      { \"name\": \"limit_indices\", \"type\": \"HLO_DimensionTensor\" },\n      { \"name\": \"strides\", \"type\": \"HLO_DimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['start_indices', 'limit_indices', 'strides']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.recv\",\n    \"summary\": \"Recv operation\",\n    \"description\": \"Receives data from a channel with `channel_id` and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#recv\\n\\n    Example:\\n    ```mlir\\n    %results:2 = \\\"stablehlo.recv\\\"(%token) {\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 1>,\\n      is_host_transfer = false,\\n      source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>\\n    } : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"HLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_StaticShapeTensorOrPerAxisQuantizedTensorOrToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_handle\", \"type\": \"StableHLO_ChannelHandle\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.reduce\",\n    \"summary\": \"Reduce operation\",\n    \"description\": \"Applies a reduction function `body` to `inputs` and `init_values` along the\\n    `dimensions` and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.reduce\\\"(%input, %init_value) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n        %0 = stablehlo.add %arg0, %arg1 : tensor<i64>\\n        stablehlo.return %0 : tensor<i64>\\n    }) {\\n      dimensions = array<i64: 1>\\n    } : (tensor<1x6xi64>, tensor<i64>) -> tensor<1xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Tensor>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stablehlo.reduce_precision\",\n    \"summary\": \"ReducePrecision operation\",\n    \"description\": \"Performs element-wise conversion of `operand` to another floating-point type\\n    that uses `exponent_bits` and `mantissa_bits` and back to the original\\n    floating-point type and produces an `output` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce_precision\\n\\n    Example:\\n    ```mlir\\n    %output = stablehlo.reduce_precision %operand, format = e5m10 : tensor<6xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exponent_bits\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"mantissa_bits\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `format` `=` custom<ExponentMantissa>($exponent_bits, $mantissa_bits)\\n      attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($output))\"\n  },\n  {\n    \"name\": \"stablehlo.reduce_scatter\",\n    \"summary\": \"ReduceScatter operation\",\n    \"description\": \"Within each process group in the process grid, performs reduction, using\\n     `computations`, over the values of the `operand` tensor from each process,\\n     splits the reduction result along `scatter_dimension` into parts, and\\n     scatters the split parts between the processes to produce the `result`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce_scatter\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.reduce_scatter\\\"(%operand) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n      %0 = stablehlo.add %arg0, %arg1 : tensor<i64>\\n      stablehlo.return %0 : tensor<i64>\\n    }) {\\n      scatter_dimension = 1 : i64,\\n      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>\\n    } : (tensor<2x4xi64>) -> tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" },\n      { \"name\": \"channel_handle\", \"type\": \"OptionalAttr<StableHLO_ChannelHandle>\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.reduce_window\",\n    \"summary\": \"ReduceWindow operation\",\n    \"description\": \"Applies a reduction function `body` to windows of `inputs` and `init_values`\\n    and produces `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reduce_window\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.reduce_window\\\"(%input, %init_value) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n        %0 = stablehlo.add %arg0, %arg1 : tensor<i64>\\n        stablehlo.return %0 : tensor<i64>\\n    }) {\\n      window_dimensions = array<i64: 2, 1>,\\n      window_strides = array<i64: 4, 1>,\\n      base_dilations = array<i64: 2, 1>,\\n      window_dilations = array<i64: 3, 1>,\\n      padding = dense<[[2, 1], [0, 0]]> : tensor<2x2xi64>\\n    } : (tensor<3x2xi64>, tensor<i64>) -> tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Tensor>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"base_dilations\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"window_dilations\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.remainder\",\n    \"summary\": \"Rem operation\",\n    \"description\": \"Performs element-wise remainder of dividend `lhs` and divisor `rhs` tensors\\n    and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#remainder\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.remainder %lhs, %rhs : tensor<4xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.replica_id\",\n    \"summary\": \"ReplicaId operation\",\n    \"description\": \"Produces `replica_id` of the current process.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#replica_id\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.replica_id : tensor<ui32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"UI32RankedTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"stablehlo.reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"Reshape operation\",\n    \"description\": \"Performs reshape of `operand` tensor to a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reshape\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.reshape %operand : (tensor<2xf32>) -> tensor<1x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_StaticShapeTensorPerAxisQuantizedTensorOrBoundedTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.return\",\n    \"summary\": \"This operation is a work in progress, so it is not yet included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/425.\\n\\n    Informally, this operation serves as a terminator for regions defined by\\n    the StableHLO ops. Non-StableHLO ops, e.g. `func.func`, have their own\\n    terminators, e.g. `func.return`.\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.reduce\\\"(%input, %init_value) ({\\n      ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):\\n        %0 = \\\"stablehlo.add\\\"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>\\n        \\\"stablehlo.return\\\"(%0) : (tensor<i32>) -> ()\\n    }) {\\n      dimensions = array<i64: 1>\\n    } : (tensor<1x6xi32>, tensor<i32>) -> tensor<1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrTokenOrBuffer>\" }\n    ],\n    \"assemblyFormat\": \"$results attr-dict (`:` type($results)^)?\"\n  },\n  {\n    \"name\": \"stablehlo.reverse\",\n    \"category\": \"Transform\",\n    \"summary\": \"Reverse operation\",\n    \"description\": \"Reverses the order of elements in the `operand` along the specified\\n    `dimensions` and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#reverse\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.reverse %operand, dims = [1] : tensor<3x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dims` `=` $dimensions\\n      attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.rng\",\n    \"summary\": \"Rng operation\",\n    \"description\": \"Generates random numbers using the `rng_distribution` algorithm and produces\\n    a `result` tensor of a given shape `shape`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#rng\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.rng %a, %b, %shape, distribution = NORMAL : (tensor<i32>, tensor<i32>, tensor<2xi64>) -> tensor<3x3xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"0DTensorOf<[HLO_Pred, HLO_Int, HLO_Float]>\" },\n      { \"name\": \"b\", \"type\": \"0DTensorOf<[HLO_Pred, HLO_Int, HLO_Float]>\" },\n      { \"name\": \"shape\", \"type\": \"HLO_StaticDimensionTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_PredIntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_distribution\", \"type\": \"StableHLO_RngDistributionAttr{UNIFORM|NORMAL}\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $shape `,` `distribution` `=` $rng_distribution\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.rng_bit_generator\",\n    \"summary\": \"RngBitGenerator operation\",\n    \"description\": \"Returns an `output` filled with uniform random data and an updated output\\n    state `output_state` given an initial state `initial_state` using the\\n    pseudorandom number generator algorithm `rng_algorithm`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#rng_bit_generator\\n\\n    Example:\\n    ```mlir\\n    %output_state, %output = stablehlo.rng_bit_generator %initial_state, algorithm = THREE_FRY : (tensor<2xui64>) -> (tensor<2xui64>, tensor<2x2xui64>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"initial_state\", \"type\": \"HLO_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_state\", \"type\": \"HLO_IntOrFpTensor\" },\n      { \"name\": \"output\", \"type\": \"HLO_StaticShapeIntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_algorithm\", \"type\": \"StableHLO_RngAlgorithmAttr{DEFAULT|THREE_FRY|PHILOX}\" }\n    ],\n    \"assemblyFormat\": \"$initial_state `,` `algorithm` `=` $rng_algorithm attr-dict\\n      `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.round_nearest_afz\",\n    \"summary\": \"Round operation\",\n    \"description\": \"Performs element-wise rounding towards the nearest integer, breaking ties\\n    away from zero, on the `operand` tensor and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#round_nearest_afz\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.round_nearest_afz %operand : tensor<5xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.round_nearest_even\",\n    \"summary\": \"RoundNearestEven operation\",\n    \"description\": \"Performs element-wise rounding towards the nearest integer, breaking ties\\n    towards the even integer, on the `operand` tensor and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#round_nearest_even\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.round_nearest_even %operand : tensor<5xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.rsqrt\",\n    \"summary\": \"Rsqrt operation\",\n    \"description\": \"Performs element-wise reciprocal square root operation on `operand` tensor\\n    and produces a `result` tensor, implementing the `rSqrt` operation from the\\n    IEEE-754 specification.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#rsqrt\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.rsqrt %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.scatter\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Scatter operation\",\n    \"description\": \"Produces `results` tensors which are equal to `inputs` tensors except that\\n    several slices specified by `scatter_indices` are updated with the values\\n    `updates` using `update_computation`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#scatter\\n\\n   Example:\\n   ```mlir\\n   %result = \\\"stablehlo.scatter\\\"(%input, %scatter_indices, %update) ({\\n     ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n       %0 = stablehlo.add %arg0, %arg1 : tensor<i64>\\n       stablehlo.return %0 : tensor<i64>\\n   }) {\\n     scatter_dimension_numbers = #stablehlo.scatter<\\n       update_window_dims = [3, 4],\\n       inserted_window_dims = [1],\\n       input_batching_dims = [0],\\n       scatter_indices_batching_dims = [1],\\n       scatter_dims_to_operand_dims = [2, 1],\\n       index_vector_dim = 3>,\\n     indices_are_sorted = false,\\n     unique_indices = false\\n   } : (tensor<2x3x4x2xi64>, tensor<2x2x3x2xi64>, tensor<2x2x3x2x2xi64>) -> tensor<2x3x4x2xi64>\\n   ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Tensor>\" },\n      { \"name\": \"scatter_indices\", \"type\": \"RankedTensorOf<[AnyInteger, Index]>\" },\n      { \"name\": \"updates\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dimension_numbers\", \"type\": \"StableHLO_ScatterDimensionNumbers\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"unique_indices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"update_computation\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.select\",\n    \"summary\": \"Select operation\",\n    \"description\": \"Produces a `result` tensor where each element is selected from `on_true` or\\n    `on_false` tensor based on the value of the corresponding element of `pred`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#select\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.select %pred, %on_true, %on_false : tensor<2x2xi1>, tensor<2x2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"HLO_PredTensor\" },\n      { \"name\": \"on_true\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"on_false\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:`\\n      custom<SelectOpType>(type($pred), type($on_true), type($on_false), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.select_and_scatter\",\n    \"summary\": \"SelectAndScatter operation\",\n    \"description\": \"Scatters the values from the `source` tensor using `scatter` based on the\\n    outcome of `reduce_window` of the `input` tensor using `select` and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#select_and_scatter\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.select_and_scatter\\\"(%operand, %source, %init_value) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n        %0 = stablehlo.compare GE, %arg0, %arg1 : (tensor<i64>, tensor<i64>) -> tensor<i1>\\n        stablehlo.return %0 : tensor<i1>\\n    }, {\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):\\n        %0 = stablehlo.add %arg0, %arg1 : tensor<i64>\\n        stablehlo.return %0 : tensor<i64>\\n    }) {\\n      window_dimensions = array<i64: [3, 1]>,\\n      window_strides = array<i64: [2, 1]>,\\n      padding = dense<[[0, 1], [0, 0]]> : tensor<2x2xi64>\\n    } : (tensor<4x2xi64>, tensor<2x2xi64>, tensor<i64>) -> tensor<4x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"source\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"init_value\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"window_strides\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"padding\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"select\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"scatter\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.send\",\n    \"summary\": \"Send operation\",\n    \"description\": \"Sends `inputs` to a channel `channel_id` and produces a `result` token.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#send\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.send\\\"(%operand, %token) {\\n      channel_handle = #stablehlo.channel_handle<handle = 0, type = 1>,\\n      is_host_transfer = false,\\n      source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>\\n    } : (tensor<2x2xi64>, !stablehlo.token) -> !stablehlo.token\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensor>\" },\n      { \"name\": \"token\", \"type\": \"HLO_Token\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Token\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_handle\", \"type\": \"StableHLO_ChannelHandle\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"OptionalAttr<I64ElementsAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.set_dimension_size\",\n    \"summary\": \"SetDimensionSize operation\",\n    \"description\": \"This operation is a work in progress, so it is not yet included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/8.\\n\\n    Informally, this operation does the same thing as XLA's SetDimensionSize:\\n    https://www.tensorflow.org/xla/operation_semantics#setdimensionsize\\n\\n    Example:\\n    ```mlir\\n    %0 = stablehlo.set_dimension_size %arg0, %arg1, dim = 1 : (tensor<4x2xf32>, tensor<i32>) -> tensor<4x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"size\", \"type\": \"I32RankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $size  `,` `dim` `=` $dimension attr-dict\\n      `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.shift_left\",\n    \"summary\": \"ShiftLeft operation\",\n    \"description\": \"Performs element-wise left-shift operation on the `lhs` tensor by `rhs`\\n    number of bits and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#shift_left\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.shift_left %lhs, %rhs : tensor<3xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.shift_right_arithmetic\",\n    \"summary\": \"ShiftRightArithmetic operation\",\n    \"description\": \"Performs element-wise arithmetic right-shift operation on the `lhs` tensor\\n    by `rhs` number of bits and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#shift_right_arithmetic\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.shift_right_arithmetic %lhs, %rhs : tensor<3xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.shift_right_logical\",\n    \"summary\": \"ShiftRightLogical operation\",\n    \"description\": \"Performs element-wise logical right-shift operation on the `lhs` tensor by\\n    `rhs` number of bits and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#shift_right_logical\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.shift_right_logical %lhs, %rhs : tensor<3xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.sign\",\n    \"summary\": \"Sign operation\",\n    \"description\": \"Returns the sign of the `operand` element-wise and produces a `result`\\n    tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sign\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.sign %operand : tensor<5xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[ HLO_SInt, HLO_Float, HLO_Complex, HLO_QuantizedInt ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[ HLO_SInt, HLO_Float, HLO_Complex, HLO_QuantizedInt ]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.sine\",\n    \"summary\": \"Sine operation\",\n    \"description\": \"Performs element-wise sine operation on `operand` tensor and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sine\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.sine %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.slice\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Slice operation\",\n    \"description\": \"Extracts a slice from the `operand` using statically-computed starting\\n    indices and produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#slice\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.slice %operand [1:3, 4:8:2]\\n       : (tensor<3x8xi64>) -> tensor<2x2xi64>\\n\\n    // Same in generic form: the `1:3` above is mapped to the first entry in\\n    // `start_indices` and `limit_indices`, while `strides` is implicitly 1.\\n    // The `4:8:2` above is parsed into the second entry of `start_indices`,\\n    // `limit_indices` and `strides` respectively.\\n    %result = \\\"stablehlo.slice\\\" (%operand) {\\n      start_indices = array<i64: 1, 4>,\\n      limit_indices = array<i64: 3, 8>,\\n      strides = array<i64: 1, 2>\\n    } : (tensor<3x8xi64>) -> tensor<2x2xi64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start_indices\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"limit_indices\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand custom<SliceRanges>($start_indices, $limit_indices, $strides)\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.sort\",\n    \"summary\": \"Sort operation\",\n    \"description\": \"Sorts a variadic number of tensors in `inputs` together, according to a\\n    custom `comparator`, along the given `dimension` and produces a variadic\\n    number of tensors as `results`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sort\\n\\n    Example:\\n    ```mlir\\n    %result0, %result1 = \\\"stablehlo.sort\\\"(%input0, %input1) ({\\n      ^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>, %arg2: tensor<i64>, %arg3: tensor<i64>):\\n        %predicate = stablehlo.compare GT, %arg0, %arg1 : (tensor<i64>, tensor<i64>) -> tensor<i1>\\n        stablehlo.return %predicate : tensor<i1>\\n    }) {\\n      dimension = 0 : i64,\\n      is_stable = true\\n    } : (tensor<2x3xi64>, tensor<2x3xi64>) -> (tensor<2x3xi64>, tensor<2x3xi64>)\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"is_stable\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"comparator\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.sqrt\",\n    \"summary\": \"Sqrt operation\",\n    \"description\": \"Performs element-wise square root operation on `operand` tensor and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#sqrt\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.sqrt %operand : tensor<2x2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.subtract\",\n    \"summary\": \"Subtract operation\",\n    \"description\": \"Performs element-wise subtraction of two tensors `lhs` and `rhs` and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#subtract\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.subtract %lhs, %rhs : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_IntFpOrComplexOrQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.tan\",\n    \"summary\": \"Tan operation\",\n    \"description\": \"Performs element-wise tangent operation on `operand` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#tan\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.tan %operand : tensor<2x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"Tanh operation\",\n    \"description\": \"Performs element-wise hyperbolic tangent operation on `operand` tensor and\\n    produces a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#tanh\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.tanh %operand : tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpComplexOrQuantizedIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"DefaultValuedOptionalAttr<StableHLO_ResultAccuracyAttr, ::mlir::stablehlo::ResultAccuracyMode::DEFAULT>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.torch_index_select\",\n    \"summary\": \"TorchIndexSelect operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as PyTorch's index_select,\\n    augmented with support for batch dimensions:\\n    https://pytorch.org/docs/stable/generated/torch.index_select.html.\\n\\n    The `batch_dims` attribute specifies the number of major batch dimensions\\n    (0 or more) that act like a multidimensional loop over both the operand and\\n    the index.\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.torch_index_select\\\"(%operand, %index) {\\n      dim = 2 : i64,\\n      batch_dims = 1 : i64\\n    } : (tensor<8x128x3072x64xf32>, tensor<8x16x1024xi32>) -> tensor<8x128x16x1024x64xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" },\n      { \"name\": \"index\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"batch_dims\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"Transpose operation\",\n    \"description\": \"Permutes the dimensions of `operand` tensor using `permutation` and produces\\n    a `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#transpose\\n\\n    Example:\\n    ```mlir\\n    %0 = stablehlo.transpose %arg0, dims = [2, 1, 0] : (tensor<1x2x3xi32>) -> tensor<3x2x1xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_TensorOrPerAxisQuantizedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `dims` `=` $permutation\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.triangular_solve\",\n    \"summary\": \"TriangularSolve operation\",\n    \"description\": \"Solves batches of systems of linear equations with lower or upper triangular\\n    coefficient matrices.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#triangular_solve\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.triangular_solve\\\"(%a, %b) {\\n      left_side = true,\\n      lower = true,\\n      unit_diagonal = false,\\n      transpose_a = #stablehlo<transpose NO_TRANSPOSE>\\n    } : (tensor<3x3xf32>, tensor<3x3xf32>) -> tensor<3x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"HLO_FpOrComplexTensor\" },\n      { \"name\": \"b\", \"type\": \"HLO_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpOrComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_side\", \"type\": \"BoolAttr\" },\n      { \"name\": \"lower\", \"type\": \"BoolAttr\" },\n      { \"name\": \"unit_diagonal\", \"type\": \"BoolAttr\" },\n      { \"name\": \"transpose_a\", \"type\": \"StableHLO_TransposeAttr{TRANSPOSE_INVALID|NO_TRANSPOSE|TRANSPOSE|ADJOINT}\" }\n    ]\n  },\n  {\n    \"name\": \"stablehlo.tuple\",\n    \"summary\": \"Tuple operation\",\n    \"description\": \"Produces a `result` tuple from values `val`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#tuple\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.tuple %val0, %val1 : tuple<tensor<2xf64>, tuple<tensor<i64>>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrTokenOrTupleOrBuffer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tuple\" }\n    ],\n    \"assemblyFormat\": \"$val attr-dict `:` custom<TupleOpType>(type($val), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.unary_einsum\",\n    \"summary\": \"UnaryEinsum operation\",\n    \"description\": \"This operation is on its way out of StableHLO, so it is not included in\\n    the StableHLO specification: https://github.com/openxla/stablehlo/issues/3.\\n\\n    Informally, this operation does the same thing as TF's einsum:\\n    https://www.tensorflow.org/api_docs/python/tf/einsum\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"stablehlo.unary_einsum\\\"(%operand) {\\n      einsum_config = \\\"ab->a\\\"\\n    } : (tensor<4x16xf32>) -> tensor<4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"einsum_config\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` `config` `=` $einsum_config attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stablehlo.uniform_dequantize\",\n    \"summary\": \"UniformDequantize operation\",\n    \"description\": \"Performs element-wise conversion of quantized tensor `operand` to a\\n    floating-point tensor `result` according to the quantization parameters\\n    defined by the `operand` type.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#uniform_dequantize\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.uniform_dequantize %operand : (tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>) -> tensor<2xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_QuantizedIntOrPerAxisQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_FpTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.uniform_quantize\",\n    \"summary\": \"UniformQuantize operation\",\n    \"description\": \"Performs element-wise conversion of floating-point tensor or quantized\\n    tensor `operand` to a quantized tensor `result` according to the\\n    quantization parameters defined by the `result` type.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#uniform_quantize\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.uniform_quantize %operand : (tensor<2xf32>) -> tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"HLO_FloatOrQuantizedIntOrPerAxisQuantizedIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_QuantizedIntOrPerAxisQuantizedIntTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` custom<SameOperandsAndResultType>(type($operand), type($result))\"\n  },\n  {\n    \"name\": \"stablehlo.while\",\n    \"summary\": \"While operation\",\n    \"description\": \"Produces the output from executing `body` function 0 or more times while the\\n    `cond` function outputs `true`.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#while\\n\\n    Example:\\n    ```mlir\\n    %results0, %results1 = stablehlo.while(%arg0 = %init_i, %arg1 = %init_sum) : tensor<i64>, tensor<i64>\\n    cond {\\n      %cond = stablehlo.compare LT, %arg0, %ten : (tensor<i64>, tensor<i64>) -> tensor<i1>\\n      stablehlo.return %cond : tensor<i1>\\n    } do {\\n      %new_sum = stablehlo.add %arg1, %one : tensor<i64>\\n      %new_i = stablehlo.add %arg0, %one : tensor<i64>\\n      stablehlo.return %new_i, %new_sum : tensor<i64>, tensor<i64>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrTokenOrBuffer>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<HLO_TensorOrPerAxisQuantizedTensorOrTokenOrBuffer>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stablehlo.xor\",\n    \"summary\": \"Xor operation\",\n    \"description\": \"Performs element-wise XOR of two tensors `lhs` and `rhs` and produces a\\n    `result` tensor.\\n\\n    See:\\n    https://github.com/openxla/stablehlo/blob/main/docs/spec.md#xor\\n\\n    Example:\\n    ```mlir\\n    %result = stablehlo.xor %lhs, %rhs : tensor<2xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"HLO_PredOrIntTensor\" },\n      { \"name\": \"rhs\", \"type\": \"HLO_PredOrIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HLO_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict\\n      `:` custom<SameOperandsAndResultType>(type($lhs), type($rhs), type($result))\"\n  },\n  {\n    \"name\": \"standalone.foo\",\n    \"summary\": \"Illustrates how to define an operation.\",\n    \"description\": \"The `standalone.foo` operation illustrates how to define a new\\n        operation in a dialect. It uses an operation trait to declare that it\\n        has no side effects.\\n\\n        This operation takes an integer argument and returns an integer.\\n\\n        Example:\\n\\n        ```mlir\\n        %0 = arith.constant 2 : i32\\n        // Apply the foo operation to %0\\n        %1 = standalone.foo %0 : i32\\n        ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"std.add\",\n    \"summary\": \"Polymorphic addition operation (legacy)\",\n    \"description\": \"Generic addition operation from the historical Standard dialect.\\n    This operation takes two operands and returns one result of the same type.\\n    The type may be an integer or floating point scalar type, a vector whose\\n    element type is integer or floating point, or a tensor of integers or floats.\\n\\n    Note: The Standard dialect was split in 2021, with arithmetic operations\\n    moved to the `arith` dialect as `arith.addi` (integer) and `arith.addf`\\n    (floating point). This entry exists for compatibility with legacy MLIR code\\n    and symbolic references in reduction operations.\\n\\n    Example:\\n\\n    ```mlir\\n    // Used symbolically in reduce operations:\\n    %0 = mhlo.reduce(%arg0 init: %arg1) applies std.add across dimensions = [1]\\n      : (tensor<?x?xf32>, tensor<f32>) -> tensor<?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"stdx.acos\",\n    \"summary\": \"arccosine\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.acosh\",\n    \"summary\": \"hyperbolic arccosine\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.asin\",\n    \"summary\": \"arcsine\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.asinh\",\n    \"summary\": \"hyperbolic arcsine\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.atanh\",\n    \"summary\": \"hyperbolic arctangent\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.closure\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stdx.cosh\",\n    \"summary\": \"hyperbolic cosine\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.pack\",\n    \"summary\": \"Pack multiple values into a tuple\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyTuple\" }\n    ],\n    \"assemblyFormat\": \"`(` $in `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.relu\",\n    \"summary\": \"ReLU operation\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.reshape\",\n    \"summary\": \"memref reshape operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor `)` attr-dict `:` functional-type($tensor, results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stdx.round\",\n    \"summary\": \"round to nearest integer\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.sinh\",\n    \"summary\": \"hyperbolic sine\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.subgroup_block_read_intel\",\n    \"summary\": \"See intel_subgroups extension.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOrScalar\" }\n    ],\n    \"assemblyFormat\": \"$memref `[` $indices `]` attr-dict `:` type($memref)`,` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stdx.subgroup_block_write_intel\",\n    \"summary\": \"See intel_subgroups extension.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyVectorOrScalar\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $memref `[` $indices `]` attr-dict `:` type($value) `,` type($memref)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stdx.subgroup_broadcast\",\n    \"summary\": \"broadcast to all elements in subgroup\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyStdScalar\" },\n      { \"name\": \"localid\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStdScalar\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `,` $localid `)` attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stdx.tan\",\n    \"summary\": \"tangent\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.unpack\",\n    \"summary\": \"Unpack multiple values from a tuple\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"AnyTuple\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $in `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"stdx.yield\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.alloca\",\n    \"summary\": \"Allocates a transient value with undefined contents.\",\n    \"description\": \"Allocates a transient value (one that is short-lived and local to the\\n    current computation) with undefined contents. Consumers of the allocated\\n    result must assume nothing of the contents and use `discard` access.\",\n    \"operands\": [\n      { \"name\": \"storage_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    attr-dict `:` type($result) `{` $storage_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.barrier\",\n    \"summary\": \"Indicates a value that must have a specific affinity.\",\n    \"description\": \"Prevents fusion and scheduling of a value across an affinity boundary.\\n    May introduce copy-on-write behavior if the operand value is used as well as\\n    the result and users should try to keep the operand to a single use by this\\n    op.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" },\n      { \"name\": \"size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `:` type($source)\\n    `` `{` $size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.call\",\n    \"summary\": \"Calls a streamable external host function.\",\n    \"description\": \"Calls a function taking/returning resource values with stream semantics.\\n    Asynchronous calls must have no side-effects.\\n\\n    Note that returned resources must have their sizes declared prior to the\\n    call as this is what allows the call to be made on the stream. If external\\n    host logic is required to compute the size (avoid at all costs!) a separate\\n    func.call can be used outside of the stream to do so. If sizes are\\n    unknownable until the operation is performed it should be made as a normal\\n    asynchronous host call with 'coarse-fences' instead.\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_PrimitiveType, AnyType, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"resource_operand_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_operand_ends\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_operand_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_PrimitiveType, ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $callee ``\\n    custom<DispatchOperands>($resource_operands,\\n                             $resource_operand_offsets,\\n                             $resource_operand_ends,\\n                             $resource_operand_lengths) attr-dict `:`\\n    custom<ShapedFunctionType>(ref($resource_operands),\\n                               type($resource_operands), $resource_operand_sizes,\\n                               type($results), $result_sizes,\\n                               $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.clone\",\n    \"summary\": \"Clones the contents of a value.\",\n    \"description\": \"Clones the contents of a value at a snapshot in time. Future changes to the\\n    cloned value will not effect the result. Acts as a copy-on-write operation.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.collective\",\n    \"summary\": \"Performs a collective operation.\",\n    \"description\": \"TODO: document different usage. For now this should be considered a\\n    prototype and that modeling of collective operations may change in the\\n    future to better ensure in-place operations (where send/recv is a subset of\\n    recv/send). We may have dedicated operations for the send and recv verbs as\\n    they have sequencing implications - or we could add optional sequencing to\\n    this base op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"element_count\", \"type\": \"Stream_Size\" },\n      { \"name\": \"channel\", \"type\": \"Stream_Channel\" },\n      { \"name\": \"param\", \"type\": \"Optional<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"Stream_CollectiveAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"`` $op `` `[` $element_count `]`\\n    (`on` `(` $affinity^ `)`)?\\n    `channel` `(` $channel `)`\\n    custom<CollectiveParam>(ref($op), $param) ``\\n    $source `[` $source_offset `to` $source_end `for` $source_length `]` `,`\\n    $target `[` $target_offset `to` $target_end `for` $target_length `]` `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.concurrent\",\n    \"summary\": \"Executes all ops concurrently.\",\n    \"description\": \"Represents a wave of work scheduled concurrently (each op executing at the\\n    same time). All resource inputs must be captured explicitly. All results are\\n    only ready once all nested ops complete execution.\\n\\n    Waves can be nested to create a DAG. For example, take the following graph:\\n    ```\\n                      |\\n            v---------+---------v\\n    +-------|-------+   +-------|-------+\\n    |    v--+--v    |   |    v--+--v    |\\n    | +----+ +----+ |   | +----+ +----+ |\\n    | | %a | | %b | |   | | %c | | %d | |\\n    | +----+ +----+ |   | +----+ +----+ |\\n    |    +--v--+    |   |    +--v--+    |\\n    +-------|-------+   +-------|-------+\\n            +---------v---------+\\n                      |\\n    ```\\n\\n    Represented with nested waves:\\n    ```mlir\\n      %0 = stream.async.concurrent with(%arg) -> ... {\\n        %1 = stream.async.concurrent with(%arg as %arg0) -> ... {\\n          %a = ...\\n          %b = ...\\n          stream.yield %a, %b\\n        }\\n        %2 = stream.async.concurrent with(%arg as %arg1) -> ... {\\n          %c = ...\\n          %d = ...\\n          stream.yield %c, %d\\n        }\\n        stream.yield %1, %2\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    `with` ``\\n    custom<ResourceRegion>($resource_operands,\\n                           type($resource_operands), $resource_operand_sizes,\\n                           type($results), $result_sizes,\\n                           $tied_operands, $body)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.constant\",\n    \"summary\": \"Defines a constant resource.\",\n    \"description\": \"Returns a new resource with the given constant value.\\n\\n    When no await_timepoint is specified the constant may be hoisted and\\n    materialized at any point prior to its first use. When an await_timepoint\\n    is specified the constant will not begin materialization until that\\n    timepoint is reached, allowing for explicit ordering with other timeline\\n    operations.\",\n    \"operands\": [\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    `:`\\n    type($result) `` `{` $result_size `}`\\n    `=`\\n    $value\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.copy\",\n    \"summary\": \"Copies a subview of a stream resource to another.\",\n    \"description\": \"Copies a subview of a resource into a subview of another.\\n    As with memcpy this does not support overlapping updates into the same\\n    resource. Unlike `stream.async.update` copy sources cannot be allocated\\n    in-place.\\n\\n    Equivalent to a stream.async.slice + stream.async.update.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"length\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `[` $source_offset `to` $source_end `]` `,`\\n    $target `[` $target_offset `to` $target_end `]` `,`\\n    $length `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.dispatch\",\n    \"summary\": \"Dispatches a parallelized grid of work.\",\n    \"description\": \"Calls the specified entry point function once for each element in the\\n    specified workgroup count. Each workgroup has access to the same operands\\n    and results and is able to load/store at will.\",\n    \"operands\": [\n      { \"name\": \"workload\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_PrimitiveType, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"resource_operand_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_operand_ends\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_operand_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Stream_AnyStreamResource>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_points\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    custom<DispatchEntryPoints>($entry_points)\\n    (`[` $workload^ `]`)? ``\\n    custom<DispatchOperands>($resource_operands,\\n                             $resource_operand_offsets,\\n                             $resource_operand_ends,\\n                             $resource_operand_lengths) attr-dict `:`\\n    custom<ShapedFunctionType>(ref($resource_operands),\\n                               type($resource_operands), $resource_operand_sizes,\\n                               type($results), $result_sizes,\\n                               $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.execute\",\n    \"summary\": \"Executes a dependency-aware sequence of streamable ops.\",\n    \"description\": \"Evaluates the operations within the region by dependency order while obeying\\n    ties when present. Nested ops execute serially in block order and nested\\n    `stream.async.concurrent` ops can be used to run multiple ops concurrently\\n    within the stream. All resource inputs must be captured explicitly. All\\n    results are only ready once all nested ops complete execution and the\\n    returned timepoint is reached. Zero or more timepoints may be provided to\\n    block execution until they are all reached; zero timepoints indicates that\\n    execution may begin immediately.\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `with` ``\\n    custom<ResourceRegion>($resource_operands,\\n                           type($resource_operands), $resource_operand_sizes,\\n                           type($results), $result_sizes,\\n                           $tied_operands, $body)\\n    `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.fill\",\n    \"summary\": \"Fills a subview of a stream resource with a value.\",\n    \"description\": \"Splats a value into a subview of the given stream resource and returns the\\n    resource with the update applied.\\n\\n    Equivalent to a stream.async.splat + stream.async.update.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"value\", \"type\": \"Stream_FillPatternType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $value `,`\\n    $target `[` $target_offset `to` $target_end `for` $target_length `]` `:`\\n    type($value) `->`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.func\",\n    \"summary\": \"Streamable function declaration.\",\n    \"description\": \"Declares a function that can be called as an asynchronous streaming\\n    operation via `stream.async.call`. Today only external functions are\\n    allowed.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    ``\\n    custom<ShapedFunctionSignature>($function_type,\\n                                    $tied_operands,\\n                                    $arg_attrs,\\n                                    $res_attrs)\\n    attr-dict-with-keyword\\n    ($body^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.load\",\n    \"summary\": \"Loads a value from a resource.\",\n    \"description\": \"Returns the element at the given location from within the resource.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_StagingResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` `:`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.parameter.gather\",\n    \"summary\": \"Gathers multiple resources from parameter archives into a target resource.\",\n    \"description\": \"Reads multiple parameter ranges from parameter archives and gathers them\\n    into a single target resource at specified offsets. This is equivalent to\\n    multiple async.parameter.read operations but allows implementations to\\n    batch operations for better performance.\\n\\n    Example:\\n    ```mlir\\n    %updated, %result_timepoint = stream.async.parameter.gather {\\n      \\\"scope\\\"::\\\"key0\\\"[%offset0] -> %target[%target_offset0 to %target_end0 for %length0],\\n      \\\"scope\\\"::\\\"key1\\\"[%offset1] -> %target[%target_offset1 to %target_end1 for %length1]\\n    } : !stream.resource<staging>{%target_size} => !stream.timepoint\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"target_ends\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"target_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    `{`\\n    custom<AsyncParameterGatherOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        $target, type($target), $target_size, $target_offsets, $target_ends, $target_lengths)\\n    `}` `:` type($result) `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.parameter.load\",\n    \"summary\": \"Allocates and loads a new resource from a parameter archive.\",\n    \"description\": \"Allocates a new resource and populates it with data from a parameter archive\\n    file (or in-memory buffer) at the specified byte offset. Unlike `read` which\\n    writes into an existing allocation, `load` returns a freshly allocated\\n    resource. The implementation may use direct access or memory mapping when\\n    the result resource type allows, avoiding copies entirely.\\n\\n    When no await_timepoint is specified the load may be hoisted and begin at\\n    any point prior to the first use. When an await_timepoint is specified the\\n    load will not begin until that timepoint is reached, allowing for explicit\\n    ordering with other timeline operations.\\n\\n    Example:\\n    ```mlir\\n    %result, %result_timepoint = stream.async.parameter.load \\\"scope\\\"::\\\"key\\\"[%offset]\\n        : !stream.resource<constant>{%size} => !stream.timepoint\\n    %ordered, %ordered_timepoint = stream.async.parameter.load await(%tp) \\\"scope\\\"::\\\"key2\\\"[%offset]\\n        : !stream.resource<constant>{%size} => !stream.timepoint\\n    ```\",\n    \"operands\": [\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" },\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    custom<ParameterReference>($source_scope, $source_key)\\n    `` `[` $source_offset `]` `:`\\n    type($result)  `` `{` $result_size `}` `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.parameter.read\",\n    \"summary\": \"Reads parameter data into an existing resource allocation.\",\n    \"description\": \"Reads data from a parameter archive file (or in-memory buffer) at the\\n    specified byte offset into an existing target resource. Unlike `load` which\\n    allocates a new resource, `read` writes into a caller-provided allocation.\\n    This is useful for partial updates, populating sub-regions of larger\\n    resources, or when the allocation is managed separately (e.g., staging\\n    buffers). The target resource is a tied operand: the input is mutated and\\n    returned with the specified range updated.\\n\\n    Example:\\n    ```mlir\\n    %updated, %result_timepoint = stream.async.parameter.read \\\"scope\\\"::\\\"key\\\"[%param_offset]\\n        -> %target[%target_offset to %target_end for %length]\\n        : !stream.resource<staging>{%target_size} => !stream.timepoint\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    custom<ParameterReference>($source_scope, $source_key)\\n    `` `[` $source_offset `]` `->`\\n    $target `` `[` $target_offset `to` $target_end `for` $target_length `]` `:`\\n    type($target) `` `{` $target_size `}` `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.parameter.scatter\",\n    \"summary\": \"Scatters multiple ranges from a source resource to parameter archives.\",\n    \"description\": \"Writes multiple ranges from a single source resource to parameter archives\\n    at specified offsets. This is equivalent to multiple async.parameter.write\\n    operations but allows implementations to batch operations for better\\n    performance. The source resource is returned unchanged to establish proper\\n    data flow dependencies.\\n\\n    Example:\\n    ```mlir\\n    %result, %result_timepoint = stream.async.parameter.scatter {\\n      %source[%source_offset0 to %source_end0 for %length0] -> \\\"scope\\\"::\\\"key0\\\"[%target_offset0],\\n      %source[%source_offset1 to %source_end1 for %length1] -> \\\"scope\\\"::\\\"key1\\\"[%target_offset1]\\n    } : !stream.resource<staging>{%source_size} => !stream.timepoint\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"source_ends\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"source_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    `{`\\n    custom<AsyncParameterScatterOperations>(\\n        $source, type($source), $source_size, $source_offsets, $source_ends, $source_lengths,\\n        $target_scope, $target_keys, $target_offsets)\\n    `}` `:` type($result) `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.parameter.write\",\n    \"summary\": \"Writes a resource to a parameter archive from a source resource.\",\n    \"description\": \"Writes data from a source resource to a parameter archive file (or in-memory\\n    buffer) at the specified byte offset. This is useful for checkpointing or\\n    saving model weights. The source resource is returned unchanged to establish\\n    proper data flow dependencies.\\n\\n    Example:\\n    ```mlir\\n    %result, %result_timepoint = stream.async.parameter.write %source[%source_offset to %source_end for %length]\\n        -> \\\"scope\\\"::\\\"key\\\"[%param_offset]\\n        : !stream.resource<staging>{%source_size} => !stream.timepoint\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    $source `` `[` $source_offset `to` $source_end `for` $source_length `]` `->`\\n    custom<ParameterReference>($target_scope, $target_key)\\n    `` `[` $target_offset `]` `:`\\n    type($source) `` `{` $source_size `}` `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.slice\",\n    \"summary\": \"Slices out a cloned subview of a value.\",\n    \"description\": \"Slices a subrange of a stream resource based on a byte range. Acts as a\\n    copy-on-write operation.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `[` $source_offset `to` $source_end `]` `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.splat\",\n    \"summary\": \"Splats a value into a resource.\",\n    \"description\": \"Returns a new resource with the given primitive value splatted out to fill\\n    the entire contents.\\n\\n    When no await_timepoint is specified the splat may be hoisted and\\n    materialized at any point prior to its first use. When an await_timepoint\\n    is specified the splat will not begin until that timepoint is reached,\\n    allowing for explicit ordering with other timeline operations.\",\n    \"operands\": [\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" },\n      { \"name\": \"value\", \"type\": \"Stream_FillPatternType\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)`)?\\n    $value `:` type($value) `->` type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.store\",\n    \"summary\": \"Stores a value into a resource.\",\n    \"description\": \"Returns a resource with the element at the given offset set to the given\\n    value.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_StagingResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[Stream_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_StagingResource\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$value `,`\\n    $target `[` $target_offset `]` `:`\\n    type($value)\\n    `->`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.transfer\",\n    \"summary\": \"Transfers a resource from one location/state to another.\",\n    \"description\": \"Transfers a resource between different states (such as a `staging` lifetime\\n    to a `local` lifetime) or different affinities. This is roughly equivalent\\n    to a cast but may have special semantics when later lowered to one or more\\n    devices with discrete memory spaces or pools.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" },\n      { \"name\": \"target_affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"$source `:` type($source)\\n    `` `{` $source_size `}`\\n    (`from` `(` $source_affinity^ `)`)?\\n    `->`\\n    (`to` `(` $target_affinity^ `)`)?\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.async.update\",\n    \"summary\": \"Updates a slice of a subview of a resource in-place.\",\n    \"description\": \"Copies a value into a resource based on a byte range. The returned value\\n    is the entire updated target value. Updates can be turned into placement\\n    allocations and avoid copies.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_end\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"update\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"update_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $update `,`\\n    $target `[` $target_offset `to` $target_end `]` `:`\\n    type($update) `` `{` $update_size `}` `->`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.binding.subspan\",\n    \"summary\": \"Returns an alias to a subspan of interface binding data.\",\n    \"description\": \"Returns a subview to a tensor or memref-like type from a binding. The same\\n    binding may have multiple subviews at different byte offsets.\",\n    \"operands\": [\n      { \"name\": \"binding\", \"type\": \"Stream_AnyBinding\" },\n      { \"name\": \"byte_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"dynamic_dims\", \"type\": \"Variadic<Stream_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$binding `` `[` $byte_offset `]`\\n    attr-dict `:` type($binding) `->` type($result) (`{` $dynamic_dims^ `}`)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.channel.count\",\n    \"summary\": \"Returns the total number of participants in the group.\",\n    \"description\": \"Returns the total participant count in the collective communicator group.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"Stream_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$channel `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.channel.create\",\n    \"summary\": \"Creates a new channel for collective communication.\",\n    \"description\": \"Returns a new channel with the given rank associated with the specified\\n    affinity. Collective operations using this channel must only be submitted on\\n    compatible affinities.\\n\\n    The group and ID are optional and may be null. The rank and count can be\\n    omitted to indicate a default inherited from the environment or device\\n    configuration at runtime.\",\n    \"operands\": [\n      { \"name\": \"id\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"rank\", \"type\": \"Optional<Index>\" },\n      { \"name\": \"count\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_Channel\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`id` `(` $id^ `)`)?\\n    (`group` `(` $group^ `)`)?\\n    (`rank` `(` $rank^ `)`)?\\n    (`count` `(` $count^ `)`)?\\n    `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.channel.rank\",\n    \"summary\": \"Returns the rank of the local participant in the group.\",\n    \"description\": \"Returns the rank the channel represents as a participant in a collective\\n    group in `[0, count)`.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"Stream_Channel\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$channel `:` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.channel.split\",\n    \"summary\": \"Splits a collective communication channel.\",\n    \"description\": \"Partitions the group associated with the given channel into disjoint\\n    subgroups for each unique value of color. Each new subgroup contains all\\n    participants of the same color and within each subgroup the key argument\\n    is used to define the rank order. When multiple participants in a group\\n    use the same key the tie will be broken using their rank in the parent\\n    group. A color of -1 indicates that the rank does not participate in any\\n    subgroup and will return a null channel.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"Stream_Channel\" },\n      { \"name\": \"color\", \"type\": \"Index\" },\n      { \"name\": \"key\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_Channel\" }\n    ],\n    \"assemblyFormat\": \"$channel `,` $color `,` $key\\n    `:` type($channel) `->` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.call\",\n    \"summary\": \"Calls a streamable external host function.\",\n    \"description\": \"Calls a function operating on resource values with stream semantics.\\n    Asynchronous calls must have no side-effects.\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_PrimitiveType, Stream_AnyStreamResource, AnyType, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"resource_operand_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_operand_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Stream_PrimitiveType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"resource_operand_accesses\", \"type\": \"TypedArrayAttrBase<Stream_ResourceAccessBitfieldAttr{None|Read|Write}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee ``\\n    custom<CmdCallOperands>($resource_operands,\\n                            $resource_operand_offsets,\\n                            $resource_operand_lengths,\\n                            $resource_operand_accesses) attr-dict `:`\\n    custom<ShapedFunctionType>(ref($resource_operands),\\n                               type($resource_operands),\\n                               $resource_operand_sizes,\\n                               type($results),\\n                               $result_sizes,\\n                               $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.collective\",\n    \"summary\": \"Dispatches a collective operation.\",\n    \"description\": \"Dispatches a collective operation specified against the device. If grouped\\n    with other collectives in a `stream.cmd.concurrent` region the collective\\n    operations may fuse and execute more efficiently.\",\n    \"operands\": [\n      { \"name\": \"channel\", \"type\": \"Stream_Channel\" },\n      { \"name\": \"element_count\", \"type\": \"Stream_Size\" },\n      { \"name\": \"param\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"resources\", \"type\": \"Variadic<Stream_AnyStreamResource>\" },\n      { \"name\": \"resource_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"resource_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_lengths\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"Stream_CollectiveAttr\" },\n      { \"name\": \"resource_accesses\", \"type\": \"TypedArrayAttrBase<Stream_ResourceAccessBitfieldAttr{None|Read|Write}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`` $op `` `[` $element_count `]`\\n    `channel` `(` $channel `)`\\n    (`param` `(` $param^ `:` type($param) `)`)? `{`\\n    custom<DispatchResources>($resources, type($resources), $resource_sizes,\\n                              $resource_offsets, $resource_lengths,\\n                              $resource_accesses)\\n    `\\\\n` `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.concurrent\",\n    \"summary\": \"Executes all ops concurrently.\",\n    \"description\": \"Represents a wave of work scheduled concurrently (each op executing at the\\n    same time).\\n\\n    Waves can be nested to create a DAG. For example, take the following graph:\\n    ```\\n                      |\\n            v---------+---------v\\n    +-------|-------+   +-------|-------+\\n    |    v--+--v    |   |    v--+--v    |\\n    | +----+ +----+ |   | +----+ +----+ |\\n    | | @a | | @b | |   | | @c | | @d | |\\n    | +----+ +----+ |   | +----+ +----+ |\\n    |    +--v--+    |   |    +--v--+    |\\n    +-------|-------+   +-------|-------+\\n            +---------v---------+\\n                      |\\n    ```\\n\\n    Represented with nested waves:\\n    ```mlir\\n      stream.cmd.concurrent {\\n        stream.cmd.concurrent {\\n          stream.cmd.dispatch @a\\n          stream.cmd.dispatch @b\\n        }\\n        stream.cmd.concurrent {\\n          stream.cmd.dispatch @c\\n          stream.cmd.dispatch @d\\n        }\\n      }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$body\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.copy\",\n    \"summary\": \"Copies a subview of a stream resource to another.\",\n    \"description\": \"Copies a subview of a resource into a subview of another.\\n    As with memcpy this does not support overlapping updates into the same\\n    resource.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"length\", \"type\": \"Stream_Size\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` `,`\\n    $target `[` $target_offset `]` `,`\\n    $length `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.discard\",\n    \"summary\": \"Discards a subview of a resource.\",\n    \"description\": \"Discards a subview of a resource, indicating that after this command the\\n    specified contents are no longer needed. This can be used to trim memory\\n    or invalidate caches.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" }\n    ],\n    \"assemblyFormat\": \"$target `[` $target_offset `for` $target_length `]` `:`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.dispatch\",\n    \"summary\": \"Dispatches a parallelized grid of work.\",\n    \"description\": \"Calls the specified entry point function once for each element in the\\n    specified workgroup count. Each workgroup has access to the same operands\\n    and results and is able to load/store at will.\",\n    \"operands\": [\n      { \"name\": \"workload\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"uniform_operands\", \"type\": \"Variadic<Stream_PrimitiveType>\" },\n      { \"name\": \"resources\", \"type\": \"Variadic<Stream_AnyStreamResource>\" },\n      { \"name\": \"resource_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"resource_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"resource_lengths\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_points\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" },\n      { \"name\": \"resource_accesses\", \"type\": \"TypedArrayAttrBase<Stream_ResourceAccessBitfieldAttr{None|Read|Write}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<DispatchEntryPoints>($entry_points)\\n    (`[` $workload^ `]`)? ``\\n    (`(` $uniform_operands^ `:` type($uniform_operands) `)`)? `{`\\n    custom<DispatchResources>($resources, type($resources), $resource_sizes,\\n                              $resource_offsets, $resource_lengths,\\n                              $resource_accesses)\\n    `\\\\n` `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.execute\",\n    \"summary\": \"Executes a dependency-aware sequence of streamable ops.\",\n    \"description\": \"Evaluates the operations within the region by dependency order while obeying\\n    ties when present. Nested ops execute serially in block order and nested\\n    `stream.cmd.concurrent` ops can be used to run multiple ops concurrently\\n    within the stream. All resource inputs must be captured explicitly. All\\n    results are only ready once all nested ops complete execution and the\\n    returned timepoint is reached. Zero or more timepoints may be provided to\\n    block execution until they are all reached; zero timepoints indicates that\\n    execution may begin immediately.\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"once\", \"type\": \"UnitAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`once` $once^)?\\n    (`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `with` ``\\n    custom<ExplicitResourceRegion>($resource_operands,\\n                                   type($resource_operands), $resource_operand_sizes,\\n                                   $body)\\n    `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.fill\",\n    \"summary\": \"Fills a subview of a stream resource with a value.\",\n    \"description\": \"Splats a value into a subview of the given stream resource and returns the\\n    resource with the update applied.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"value\", \"type\": \"Stream_NativeFillPatternType\" }\n    ],\n    \"assemblyFormat\": \"$value `,`\\n    $target `[` $target_offset `for` $target_length `]` `:`\\n    type($value) `->`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.flush\",\n    \"summary\": \"Flushes a subview of a resource.\",\n    \"description\": \"Transfers a resource to an external target. The resource memory is made\\n    available to the target and can be made visible there using\\n    `stream.cmd.invalidate`.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`to` `(` $source_affinity^ `)`)?\\n    $target `[` $target_offset `for` $target_length `]` `:`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.func\",\n    \"summary\": \"Streamable function declaration.\",\n    \"description\": \"Declares a function that can be called as an asynchronous streaming\\n    operation via `stream.cmd.call`. Today only external functions are\\n    allowed.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name ``\\n    custom<DispatchFunctionSignature>($function_type,\\n                                      $arg_attrs,\\n                                      $res_attrs)\\n    attr-dict-with-keyword\\n    ($body^)?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.invalidate\",\n    \"summary\": \"Invalidates a subview of a resource.\",\n    \"description\": \"Transfers a resource from an external source into the current target. The\\n    resource memory is assumed to have been made available at the source via\\n    `stream.cmd.flush`.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`from` `(` $source_affinity^ `)`)?\\n    $target `[` $target_offset `for` $target_length `]` `:`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.parameter.gather\",\n    \"summary\": \"Gathers multiple resources from a parameter scope.\",\n    \"description\": \"Asynchronously gathers one or more resources into a single target stream\\n    resource. This is equivalent to one `stream.cmd.parameter.read` per\\n    parameter but allows implementations that can batch operations to do so\\n    without additional timeline overhead.\",\n    \"operands\": [\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"target_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `{`\\n    custom<CmdParameterGatherOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        $target, type($target), $target_size, $target_offsets, $target_lengths)\\n    `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.parameter.load\",\n    \"summary\": \"Reads one or more resources from a parameter scope.\",\n    \"description\": \"Asynchronously reads one or more resources from an external parameter\\n    provider and returns the resulting stream resources. Depending on the\\n    resource type this may alias existing cached storage or be directly mapped\\n    to the parameter origin or result in a copy as if `stream.resource.alloca`\\n    and `stream.cmd.parameter.read` had been used per parameter.\",\n    \"operands\": [\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Stream_AnyStreamResource>\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['results']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `{`\\n    custom<ParameterLoadOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        type($results), $result_sizes)\\n    `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.parameter.read\",\n    \"summary\": \"Reads a resource from a parameter scope.\",\n    \"description\": \"Asynchronously reads a resource from an external parameter provider into the\\n    provided target resource range.\",\n    \"operands\": [\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    custom<ParameterReference>($source_scope, $source_key)\\n    `` `[` $source_offset `]` `->`\\n    $target `[` $target_offset `for` $target_length `]` `:`\\n    type($target) `` `{` $target_size `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.parameter.scatter\",\n    \"summary\": \"Scatters multiple resources to a parameter scope.\",\n    \"description\": \"Asynchronously scatters one or more resources from a single source resource\\n    into one or more parameters. This is equivalent to one\\n    `stream.cmd.parameter.write` per parameter but allows implementations that\\n    can batch operations to do so without additional overhead.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic<Stream_Offset>\" },\n      { \"name\": \"source_lengths\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_keys\", \"type\": \"Variadic<Util_BufferType>\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `{`\\n    custom<CmdParameterScatterOperations>(\\n        $source, type($source), $source_size, $source_offsets, $source_lengths,\\n        $target_scope, $target_keys, $target_offsets)\\n    `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.parameter.write\",\n    \"summary\": \"Writes a resource to a parameter scope.\",\n    \"description\": \"Asynchronously writes a resource to an external parameter provider from\\n    the provided source resource range.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    $source `[` $source_offset `for` $source_length `]` `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    custom<ParameterReference>($target_scope, $target_key)\\n    `` `[` $target_offset `]`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.cmd.serial\",\n    \"summary\": \"Executes all ops serially (in-order).\",\n    \"description\": \"Represents a sequence of work scheduled serially (each op executing one\\n    after the other).\\n\\n    Regions can be nested to create a DAG. For example, take the following graph:\\n    ```\\n                      |\\n            v---------+-----v\\n    +-------|-------+   +---|----+\\n    |    v--+--v    |   |   v    |\\n    | +----+ +----+ |   | +----+ |\\n    | | @a | | @b | |   | | @c | |\\n    | +----+ +----+ |   | +----+ |\\n    |    |     |    |   |   |    |\\n    |    |     |    |   | +-v--+ |\\n    |    |     |    |   | | @d | |\\n    |    |     |    |   | +----+ |\\n    |    +--v--+    |   |   |    |\\n    +-------|-------+   +---|----+\\n            +---------v-----+\\n                      |\\n    ```\\n\\n    Represented with nested regions:\\n    ```mlir\\n      stream.cmd.concurrent {\\n        stream.cmd.concurrent {\\n          stream.cmd.dispatch @a\\n          stream.cmd.dispatch @b\\n        }\\n        stream.cmd.serial {\\n          stream.cmd.dispatch @c\\n          stream.cmd.dispatch @d\\n        }\\n      }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$body\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.context.resolve\",\n    \"summary\": \"Resolves low-level context resources based on type.\",\n    \"description\": \"WIP; allows for accessing the implementation details of lower-level dialects\\n    such as the HAL. This will likely be reworked in the future to either\\n    live inside other dialects, use some op interface instead of having a\\n    dedicated op here, or remove the op entirely and make resolution happen\\n    explicitly.\\n\\n    Examples:\\n    ```\\n    // Returns a HAL device.\\n    = stream.context.resolve on(#something) : !hal.device\\n    // Returns a HAL device and (optional) queue affinity.\\n    = stream.context.resolve on(#something) : !hal.device, i64\\n    // Returns a HAL allocator and (optional) queue affinity.\\n    = stream.context.resolve on(#something) : !hal.allocator, i64\\n    ```\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    attr-dict `:` type($results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.dispatch.workgroup.count\",\n    \"summary\": \"Returns the total workgroup count of the grid.\",\n    \"description\": \"The total number of workgroups along each dimension in the dispatch grid.\\n\\n    Represented as a 3D grid classically written as XYZ.\\n    Corresponds to the `NumWorkgroups` SPIR-V built-in and the `gridDim` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = stream.dispatch.workgroup.count[0] : index\\n    %y = stream.dispatch.workgroup.count[1] : index\\n    %z = stream.dispatch.workgroup.count[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.dispatch.workgroup.id\",\n    \"summary\": \"Returns the index of the current workgroup in the grid.\",\n    \"description\": \"The global workgroup ID of the current workgroup in the range of\\n    `[0, stream.dispatch.workgroup.count)` along each dimension.\\n\\n    Represented as a 3D grid classically written as XYZ.\\n    Corresponds to the `WorkgroupId` SPIR-V built-in and the `blockIdx` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = stream.dispatch.workgroup.id[0] : index\\n    %y = stream.dispatch.workgroup.id[1] : index\\n    %z = stream.dispatch.workgroup.id[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.dispatch.workgroup.size\",\n    \"summary\": \"Returns the size of each workgroup in invocations.\",\n    \"description\": \"The number of local invocations within the current workgroup along each\\n    dimension. Depending on backend this may map to the SIMT thread count or\\n    inner loop nest parameters.\\n\\n    Workgroup sizes are not determined at the stream dialect level as they are\\n    dependent on the target backend determined when lowering into the HAL. It's\\n    still possible to use the symbolic workgroup size inside of dispatch\\n    executables as a placeholder for the resolved value once in the HAL.\\n\\n    Represented as a 3D grid classically written as XYZ.\\n    Corresponds to the `WorkgroupSize` SPIR-V built-in and the `blockDim` CUDA\\n    built-in variable.\\n\\n    ```mlir\\n    %x = stream.dispatch.workgroup.size[0] : index\\n    %y = stream.dispatch.workgroup.size[1] : index\\n    %z = stream.dispatch.workgroup.size[2] : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_Dim\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`[` $dimension `]` attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.executable\",\n    \"summary\": \"Generic executable module.\",\n    \"description\": \"An executable module containing one or more public functions. The contents\\n    of the functions are safe to dispatch and can be lowered further to\\n    target-specific backend IR representations.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    attr-dict-with-keyword\\n    regions\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.executable.end\",\n    \"summary\": \"Terminator pseudo-op for the executable op.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.executable.export\",\n    \"summary\": \"Defines an executable entry point for dispatch operations.\",\n    \"description\": \"Specifies an exported function with an externally-visible alias. Multiple\\n    exports can reference the same internal function.\\n\\n    Each entry point can have a unique workgroup count calculation region.\\n    This region takes the workload parameters passed to each flow.dispatch and\\n    produces an XYZ workgroup count for the 3D grid dispatch.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_ref\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"workgroup_count\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    custom<SymbolAlias>($sym_name, $function_ref)\\n    custom<WorkgroupCountRegion>($workgroup_count)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.file.constant\",\n    \"summary\": \"Creates a file backed by the provided constant host memory.\",\n    \"description\": \"Synchronously wraps a host heap buffer into a stream-accessible file handle.\\n    Changing the source buffer after definition has undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_length\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_File\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `[` $source_offset `for` $source_length `]` `:`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.file.read\",\n    \"summary\": \"Reads a segment of a file into a resource.\",\n    \"description\": \"Asynchronously reads a segment of a file into a resource.\\n\\n    Some implementations can stream directly from the source file into\\n    device-local memory and file ops should be preferred to manually staging\\n    memory through host buffers.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_File\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`):(`:`)?\\n    $source `[` $source_offset `]` `,`\\n    $target `[` $target_offset `]` `,`\\n    $length `:`\\n    type($source) `->`\\n    type($target) `` `{` $target_size `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.file.write\",\n    \"summary\": \"Writes a segment of a file from a resource.\",\n    \"description\": \"Asynchronously writes a segment of a resource into a file.\\n    The file range must be valid within the file as this operation cannot\\n    grow the underlying file storage.\\n\\n    Some implementations can stream directly from device-local memory into the\\n    target file and file ops should be preferred to manually staging memory\\n    through host buffers.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target\", \"type\": \"Stream_File\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" },\n      { \"name\": \"length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`):(`:`)?\\n    $source `[` $source_offset `]` `,`\\n    $target `[` $target_offset `]` `,`\\n    $length `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($target)\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.parameter.gather\",\n    \"summary\": \"Gathers multiple resources from a parameter scope.\",\n    \"description\": \"Asynchronously gathers one or more resources into a single target stream\\n    resource. This is equivalent to one `stream.parameter.read` per parameter\\n    but allows implementations that can batch operations to do so without\\n    additional timeline overhead.\",\n    \"operands\": [\n      { \"name\": \"source_offsets\", \"type\": \"Variadic\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic\" },\n      { \"name\": \"target_lengths\", \"type\": \"Variadic\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_scope\", \"type\": \"OptionalAttr\" },\n      { \"name\": \"source_keys\", \"type\": \"StrArrayAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `{`\\n    custom<ParameterGatherOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        $target, type($target), $target_size, $target_offsets, $target_lengths)\\n    `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"stream.parameter.load\",\n    \"summary\": \"Reads one or more resources from a parameter scope.\",\n    \"description\": \"Asynchronously reads one or more resources from an external parameter\\n    provider and returns the resulting stream resources. Depending on the\\n    resource type this may alias existing cached storage or be directly mapped\\n    to the parameter origin or result in a copy as if `stream.resource.alloca`\\n    and `stream.parameter.read` had been used per parameter.\",\n    \"operands\": [\n      { \"name\": \"source_offsets\", \"type\": \"Variadic\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_scope\", \"type\": \"OptionalAttr\" },\n      { \"name\": \"source_keys\", \"type\": \"StrArrayAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `{`\\n    custom<ParameterLoadOperations>(\\n        $source_scope, $source_keys, $source_offsets,\\n        type($results), $result_sizes)\\n    `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"stream.parameter.read\",\n    \"summary\": \"Reads a resource from a parameter scope.\",\n    \"description\": \"Asynchronously reads a resource from an external parameter provider into the\\n    provided target resource range.\",\n    \"operands\": [\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"target_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_scope\", \"type\": \"OptionalAttr\" },\n      { \"name\": \"source_key\", \"type\": \"StrAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    custom<ParameterReference>($source_scope, $source_key)\\n    `` `[` $source_offset `]` `->`\\n    $target `[` $target_offset `for` $target_length `]` `:`\\n    type($target) `` `{` $target_size `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"stream.parameter.scatter\",\n    \"summary\": \"Scatters multiple resources to a parameter scope.\",\n    \"description\": \"Asynchronously scatters one or more resources from a single source resource\\n    into one or more parameters. This is equivalent to one\\n    `stream.parameter.write` per parameter but allows implementations that can\\n    batch operations to do so without additional overhead.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offsets\", \"type\": \"Variadic\" },\n      { \"name\": \"source_lengths\", \"type\": \"Variadic\" },\n      { \"name\": \"target_offsets\", \"type\": \"Variadic\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_scope\", \"type\": \"OptionalAttr\" },\n      { \"name\": \"target_keys\", \"type\": \"StrArrayAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    `{`\\n    custom<ParameterScatterOperations>(\\n        $source, type($source), $source_size, $source_offsets, $source_lengths,\\n        $target_scope, $target_keys, $target_offsets)\\n    `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"stream.parameter.write\",\n    \"summary\": \"Writes a resource to a parameter scope.\",\n    \"description\": \"Asynchronously writes a resource to an external parameter provider from\\n    the provided source resource range.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"source_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_scope\", \"type\": \"OptionalAttr\" },\n      { \"name\": \"target_key\", \"type\": \"StrAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    $source `[` $source_offset `for` $source_length `]` `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    custom<ParameterReference>($target_scope, $target_key)\\n    `` `[` $target_offset `]`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"stream.resource.alloc\",\n    \"summary\": \"Allocates a persistent resource.\",\n    \"description\": \"Allocates a persistent value (one that is long-lived and possibly external\\n    to the program) with undefined contents. Consumers of the allocated\\n    result must assume nothing of the contents and use `discard` access.\\n\\n    Uninitialized allocations will have undefined contents and must only be used\\n    when all bytes are discarded prior to any reads. Runtimes decide what\\n    \\\"undefined contents\\\" means and here it only indicates that execution will be\\n    correct even if the memory starts with non-zero values.\\n\\n    If multiple values are allocated from the same operation it implies that\\n    they have matching lifetimes. When lowering to execution environments the\\n    separate allocations may be fused into one or more slab allocations in order\\n    to reduce overheads. How many allocations can be fused is based on the size\\n    of the individual resources and the target constraints (how large any single\\n    buffer may be, etc).\",\n    \"operands\": [\n      { \"name\": \"storage_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"uninitialized\", \"type\": \"UnitAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`uninitialized` $uninitialized^)?\\n    (`on` `(` $affinity^ `)`)?\\n    attr-dict `:`\\n    type($result) `{` $storage_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.alloca\",\n    \"summary\": \"Allocates a transient value with undefined contents.\",\n    \"description\": \"Allocates a transient value (one that is short-lived and local to the\\n    current computation) with undefined contents. Consumers of the allocated\\n    result must assume nothing of the contents and use `discard` access.\\n\\n    The resource returned is not valid for use until the timepoint is reached;\\n    execution using this resource must await on the timepoint.\\n\\n    If the lifetime of the allocation is unknowable (analysis fails, etc) the\\n    `indeterminate_lifetime` will be set indicating that the resource should not\\n    be deallocated asynchronously and only after all references have been\\n    released.\",\n    \"operands\": [\n      { \"name\": \"storage_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indeterminate_lifetime\", \"type\": \"UnitAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"`uninitialized`\\n    (`indeterminate` $indeterminate_lifetime^)?\\n    (`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`):(`:`)?\\n    attr-dict\\n    type($result) `{` $storage_size `}`\\n    `=` `` `>`\\n    type($result_timepoint)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.constants\",\n    \"summary\": \"Asynchronously uploads or maps constant values.\",\n    \"description\": \"Represents an upload of constant resources that may be packed, suballocated,\\n    and mapped depending on the final lowering target.\\n\\n    In runtime environments where memory is shared between host and device this\\n    turns into a mapping operation that avoids additional memory allocation and\\n    copies. When memory cannot be shared an asynchronous stream will be created\\n    to allocate and copy all of the constant values.\\n\\n    Though this op returns a unique resource for each constant value it's\\n    expected that almost all end up aliasing into the same storage. The exact\\n    packing and number of storage resources that are needed are not known until\\n    lowering to a particular backend, though, so they are separate here for\\n    proper usage tracking.\\n\\n    Both constant and variable resources can be produced; a constant is\\n    immutable while a variable will be treated as a constant-value initializer\\n    for a mutable resource. By modeling these together it's not required that\\n    variable initializers first be allocated, copied to the target, and then\\n    copied into the variable storage if the target is capable of doing a direct\\n    upload or mapping.\",\n    \"operands\": [\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ Stream_ConstantResource, Stream_VariableResource, ]>>\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"TypedArrayAttrBase<AnyAttr, constant value array attribute>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    attr-dict `:`\\n    custom<ConstantValueList>(type($results),\\n                              $result_sizes,\\n                              $values)\\n    `\\\\n` ` ` ` ` `=` `` `>` type($result_timepoint)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.dealloca\",\n    \"summary\": \"Frees a transient value when available.\",\n    \"description\": \"Deallocates a transient value (one that is short-lived and local to the\\n    current computation) previously allocated using `stream.resource.alloca`.\\n\\n    The resource is considered live and valid until the provided timepoint is\\n    reached and the memory is only made available for future requests after\\n    the result timepoint is reached.\\n\\n    If `prefer_origin` is set then the deallocation will be scheduled against\\n    the original placement affinity of the allocation at runtime. In cases where\\n    the original placement is unavailable the affinity of the deallocation op\\n    will be used to perform a barrier operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"operand_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prefer_origin\", \"type\": \"UnitAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`origin` $prefer_origin^)?\\n    (`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>`)?\\n    $operand `:` type($operand) `{` $operand_size `}`\\n    `=` `` `>` type($result_timepoint)\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.is_terminal\",\n    \"summary\": \"Returns true if the resource has no other claims to ownership.\",\n    \"description\": \"Resources may have multiple conceptual owners and are generally only safe to\\n    deallocate if the code performing the deallocation is the last owner. This\\n    op can be used to see if the current owner is the last one claiming\\n    ownership and can deallocate or reuse the resource for other purposes.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"operand_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `{` $operand_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.load\",\n    \"summary\": \"Loads a value from a staging resource.\",\n    \"description\": \"Returns the element(s) at the given offset in the staging resource.\\n    The operation will complete synchronously against the resource though it may\\n    introduce a yield point if the staging resource needs to be transferred.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_StagingResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` `:`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.pack\",\n    \"summary\": \"Packs variable-sized slices into a single slab.\",\n    \"description\": \"Performs a greedy packing of one or more sized slices with specified\\n    lifetimes and returns their relative offsets in an aliased linear space.\\n\\n    Slices are `[start, end] = %slice_byte_size`, where the start and end values\\n    define an inclusive lifetime range and the size is the total number of bytes\\n    required to be live for that range.\\n\\n    ```mlir\\n    // Computes the total length required for the packed values and the offsets\\n    // of the 3 slices requested relative to the base of the packed memory:\\n    %total_length, %offset_0, %offset_1, %offset_2 =\\n        stream.resource.pack\\n            // Each slice gets one result offset:\\n            slices({\\n              // 3 slices where A and B overlap and will get unique offsets\\n              // while B and C do not overlap and are allowed to alias.\\n              [0, 10] = %size_0,  // A => %offset_0\\n              [3,  8] = %size_1,  // B => %offset_1\\n              [9, 10] = %size_2,  // C => %offset_2\\n              ...\\n            }) : index\\n    ```\\n\\n    The lifetime start and end points (inclusive) are only used for relative\\n    comparisons and may originate with any meaning (op order in block, epoch,\\n    phase of the moon, etc). The packing algorithm uses the intervals to\\n    determine slice liveness and when aliasing is safe.\\n\\n    The size of each slice may either be a constant or runtime-computed dynamic\\n    value. Constant slices can achieve more dense packing than the dynamic\\n    values and CSE/canonicalization should be applied to ensure that as many of\\n    the dynamic values are equivalent if possible.\\n\\n    The total length required to pack all slices is returned and can be used to\\n    acquire storage. The individual slice offsets are 0-based and as such if are\\n    directly used as buffer offsets may need additional offsetting. This can\\n    either be applied via the optional `offset` operand or slicing of the\\n    underlying allocation buffer.\",\n    \"operands\": [\n      { \"name\": \"offset\", \"type\": \"Optional<Stream_Offset>\" },\n      { \"name\": \"dynamic_slice_sizes\", \"type\": \"Variadic<Stream_Size>\" }\n    ],\n    \"results\": [\n      { \"name\": \"total_length\", \"type\": \"Stream_Size\" },\n      { \"name\": \"packed_offsets\", \"type\": \"Variadic<Stream_Offset>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lifetime_intervals\", \"type\": \"TypedArrayAttrBase<Stream_IndexAttr>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`offset` `(` $offset^ `)`)?\\n    `slices` `(` `{`\\n    custom<PackSliceRanges>($lifetime_intervals,\\n                            $dynamic_slice_sizes,\\n                            type($packed_offsets))\\n    `}` `)`\\n    `:` type($total_length)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.release\",\n    \"summary\": \"Releases an ownership claim on the resource.\",\n    \"description\": \"A resource is allowed to be deallocated or reused once the last owner\\n    releases their ownership. Returns a boolean indicating whether the owner\\n    releasing their claim was the last owner (equivalent to having used\\n    `stream.resource.is_terminal`).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"operand_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `{` $operand_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.retain\",\n    \"summary\": \"Retains ownership of the resource.\",\n    \"description\": \"Retains ownership of the resource for the parent code until a corresponding\\n    `stream.resource.release` is used to release the ownership claim. A\\n    particular resource may have multiple owners at any given time indicating\\n    that multiple parts of the program are sharing responsibility for\\n    deallocating the resource.\\n\\n    This is primarily only relevant for resources allocated asynchronously and\\n    that need `stream.resource.dealloca` operations scheduled on timelines.\\n    Synchronously allocated resources have their lifetimes tied directly to\\n    their reference-type and do not need additional ownership management.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"operand_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `{` $operand_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.size\",\n    \"summary\": \"Returns the size of the resource storage in bytes.\",\n    \"description\": \"Returns a possibly runtime-dynamic byte size of the resource backing\\n    storage. This may differ from the logical storage size of a value based on\\n    the alignment requirements of the target as well as encoding of higher level\\n    values such as sparse tensor formats.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Stream_AnyResource\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_Size\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"$operand\\n    attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.store\",\n    \"summary\": \"Stores a value into a staging resource.\",\n    \"description\": \"The operation will complete synchronously against the resource though it may\\n    introduce a yield point if the staging resource needs to be acquired.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_StagingResource\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[Stream_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,`\\n    $target `[` $target_offset `]` `:`\\n    type($value)\\n    `->`\\n    type($target) `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.subview\",\n    \"summary\": \"Slices out a subview of a value.\",\n    \"description\": \"Aliases a byte subrange of a resource.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyResource\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.transients\",\n    \"summary\": \"Annotates a resource to use transient storage from provided storage.\",\n    \"description\": \"Annotates that any transient memory used in the production of the given\\n    resource should be suballocated from the provided storage. This allows\\n    users to control transient allocations by providing their own backing\\n    storage enabling zero-allocation execution in steady state.\\n\\n    The storage provided must have sufficient space for all transient\\n    allocations required to produce the resource. Unless otherwise overridden\\n    the compiler will verify that all allocation sizes are computable and\\n    generate size query functions to allow users to query the required storage\\n    size. If size checks are disabled then the user must ensure they pass in\\n    storage with sufficient capacity.\\n\\n    This operation preserves SSA use-def chains by returning the same resource\\n    value it receives. It exists purely for annotation purposes and will be\\n    lowered away during compilation. The operation is timeline-aware and\\n    threads timepoints through to enable proper synchronization.\\n\\n    Example:\\n    ```mlir\\n    %result, %result_timepoint = some.operation(%input) : !stream.resource<*>\\n    %annotated, %annotated_tp = stream.resource.transients\\n        await(%result_timepoint) => %result : !stream.resource<*>{%size}\\n        from %storage : !stream.resource<transient>{%storage_size}\\n        => !stream.timepoint\\n    ```\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"resource_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"storage\", \"type\": \"Stream_AnyResource\" },\n      { \"name\": \"storage_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Optional<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['resource', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`await` `(` $await_timepoint^ `)` `=` `` `>` )?\\n    $resource `:` type($resource) `` `{` $resource_size `}`\\n    `from`\\n    $storage `:` type($storage) `` `{` $storage_size `}`\\n    `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.resource.try_map\",\n    \"summary\": \"Maps read-only memory into a resource.\",\n    \"description\": \"Synchronously maps a host heap buffer into a stream-accessible resource\\n    with the requested lifetime. If the given source cannot be mapped the\\n    `did_map` result will be 0 and users must find another route into memory\\n    (such as file I/O). The resulting resource is not coherent with the source\\n    and behavior is undefined if the underlying contents change.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"Stream_Offset\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"did_map\", \"type\": \"I1\" },\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `[` $source_offset `]` `:`\\n    type($source)\\n    `->`\\n    type($did_map) `,` type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.return\",\n    \"summary\": \"Returns results from a region.\",\n    \"description\": \"The values returned are copied by-value.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    $operands `:` type($operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.clone\",\n    \"summary\": \"Clones the contents of a value.\",\n    \"description\": \"Clones the contents of a value at a snapshot in time. Future changes to the\\n    cloned value will not effect the result. Acts as a copy-on-write operation.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `:`\\n    $source_encoding (`` `{` $source_encoding_dims^ `}`)?\\n    `in`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.constant\",\n    \"summary\": \"Defines a constant tensor value.\",\n    \"description\": \"Returns a typed resource initialized to the given constant value.\",\n    \"operands\": [\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" },\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    `:`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result)\\n    `=`\\n    $value\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.dispatch\",\n    \"summary\": \"Dispatches a parallelized grid of work.\",\n    \"description\": \"Calls the specified entry point function once for each element in the\\n    specified workgroup count. Each workgroup has access to the same operands\\n    and results and is able to load/store at will.\",\n    \"operands\": [\n      { \"name\": \"workload\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mixed_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_PrimitiveType, ]>>\" },\n      { \"name\": \"operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"operand_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Stream_AnyStreamResource>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"entry_points\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" },\n      { \"name\": \"operand_encodings\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"result_encodings\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    custom<DispatchEntryPoints>($entry_points)\\n    (`[` $workload^ `]`)? ``\\n    `(` $mixed_operands `)`\\n    attr-dict `:`\\n    custom<EncodedShapedFunctionType>(\\n        ref($mixed_operands),\\n        type($mixed_operands), $operand_sizes,\\n        $operand_encodings, $operand_encoding_dims,\\n        type($results), $result_sizes,\\n        $result_encodings, $result_encoding_dims,\\n        $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.empty\",\n    \"summary\": \"Defines an empty tensor value.\",\n    \"description\": \"Returns a typed resource initialized with no contents. This still carries\\n    shape metadata and may encode to a non-empty resource such as in cases\\n    where the empty representation still has data (e.g. sparse tensors).\\n    Subsequent writes must populate any ranges of the tensor that are later\\n    read.\",\n    \"operands\": [\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    `:`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.encode\",\n    \"summary\": \"Encodes the contents of a value.\",\n    \"description\": \"Elones the contents of a value at a snapshot in time. Future changes to the\\n    identity encoding will not effect the result. Acts as a copy-on-write\\n    operation. Otherwise, an executable for encoding the value is generated\\n    during lowering.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `:`\\n    $source_encoding (`` `{` $source_encoding_dims^ `}`)?\\n    `in`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.export\",\n    \"summary\": \"Conversion placeholder for stream->other type conversion.\",\n    \"description\": \"Defines a conversion to a higher-level dialect type such as `tensor` that\\n    is resolved during lowering into the stream dialect. This can be used to\\n    interoperate between levels of the stack that require specifying stream\\n    types and those that prior to lowering do not handle them.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" },\n      { \"name\": \"source_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `:`\\n    $source_encoding (`` `{` $source_encoding_dims^ `}`)?\\n    `in`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.fill\",\n    \"summary\": \"Fills a subview of a stream resource with a value.\",\n    \"description\": \"Splats a value into a subview of the given stream resource and returns the\\n    resource with the update applied.\\n\\n    Equivalent to a stream.tensor.splat + stream.tensor.update.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"lengths\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"value\", \"type\": \"Stream_PrimitiveType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $value `,` $target (`[` $start_indices `for` $lengths^ `]`)? `:`\\n    type($value)\\n    `->`\\n    $target_encoding (`` `{` $target_encoding_dims^ `}`)?\\n    `in`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.import\",\n    \"summary\": \"Conversion placeholder for other->stream type conversion.\",\n    \"description\": \"Defines a conversion from a higher-level dialect type such as `tensor` that\\n    is resolved during lowering into the stream dialect. This can be used to\\n    interoperate between levels of the stack that require specifying stream\\n    types and those that prior to lowering do not handle them.\\n\\n    `consume` can be used to indicate a transfer of ownership. Though the\\n    imported value may still have external references when consumed a resource\\n    will be conceptually released from its existing owner and retained by the\\n    importer atomically.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyType\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"consume\", \"type\": \"UnitAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    (`consume` $consume^)?\\n    $source `:`\\n    type($source)\\n    `->`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result) `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.load\",\n    \"summary\": \"Loads a value from a tensor element.\",\n    \"description\": \"Returns the element at the given location from within the tensor.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_StagingResource\" },\n      { \"name\": \"source_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Stream_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source (`[` $indices^ `]`)? `:`\\n    $source_encoding (`` `{` $source_encoding_dims^ `}`)?\\n    `in`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.parameter.load\",\n    \"summary\": \"Loads a new resource from a parameter archive.\",\n    \"description\": \"Allocates a new resource and populates it with data from a parameter archive\\n    file (or in-memory buffer) at the specified byte offset. This is the\\n    tensor-phase equivalent of `stream.async.parameter.load` and retains tensor\\n    encoding metadata for proper size calculation during encoding.\\n\\n    Example:\\n    ```mlir\\n    %r = stream.tensor.parameter.load %key[%offset]\\n        : tensor<4x8xf32> in !stream.resource<*>{%size}\\n    %r = stream.tensor.parameter.load %scope::%key[%offset]\\n        : tensor<?x8xf32>{%dim0} in !stream.resource<*>{%size}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"source_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_offset\", \"type\": \"I64\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    custom<ParameterReference>($source_scope, $source_key)\\n    `` `[` $source_offset `]`\\n    `:` $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in` type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.parameter.write\",\n    \"summary\": \"Writes a resource to a parameter archive.\",\n    \"description\": \"Writes data from a source resource to a parameter archive file (or in-memory\\n    buffer) at the specified byte offset. The source resource is returned\\n    unchanged to establish proper data flow dependencies. This is the\\n    tensor-phase equivalent of `stream.async.parameter.write` and retains tensor\\n    encoding metadata for proper size calculation during encoding.\\n\\n    Example:\\n    ```mlir\\n    %r = stream.tensor.parameter.write %source -> %key[%offset]\\n        : tensor<4x8xf32> in !stream.resource<*>{%size}\\n    %r = stream.tensor.parameter.write %source -> %scope::%key[%offset]\\n        : tensor<?x8xf32>{%dim0} in !stream.resource<*>{%size}\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"target_scope\", \"type\": \"Optional<Util_BufferType>\" },\n      { \"name\": \"target_key\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_offset\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `->` custom<ParameterReference>($target_scope, $target_key)\\n    `` `[` $target_offset `]`\\n    `:` $source_encoding (`` `{` $source_encoding_dims^ `}`)?\\n    `in` type($source) `` `{` $source_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.sizeof\",\n    \"summary\": \"Calculates the storage size of a given high-level type.\",\n    \"description\": \"Target-dependent storage size calculation using a high-level annotated type.\\n    While within the stream dialect the storage size of a value is left as a\\n    placeholder using this op. The requisite target-specific parameters for\\n    expanding the size calculation are only available after affinities have been\\n    assigned.\",\n    \"operands\": [\n      { \"name\": \"encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" }\n    ],\n    \"results\": [\n      { \"name\": \"storage_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $encoding (`{` $encoding_dims^ `}`)?\\n    attr-dict `:` type($storage_size)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.slice\",\n    \"summary\": \"Slices out a cloned subview of a value.\",\n    \"description\": \"Slices a subrange of a stream resource based on a tensor encoding. Acts as a\\n    copy-on-write operation.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"source_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"source_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"lengths\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $source `[` $start_indices `for` $lengths `]` `:`\\n    $source_encoding (`` `{` $source_encoding_dims^ `}`)?\\n    `in`\\n    type($source) `` `{` $source_size `}`\\n    `->`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.splat\",\n    \"summary\": \"Splats a value into a shaped tensor.\",\n    \"description\": \"Returns a typed resource initialized to the given primitive value.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Stream_PrimitiveType\" },\n      { \"name\": \"result_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"result_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $value\\n    `:` type($value)\\n    `->`\\n    $result_encoding (`` `{` $result_encoding_dims^ `}`)?\\n    `in`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.store\",\n    \"summary\": \"Stores a value into a tensor element.\",\n    \"description\": \"Returns a tensor with the element at the given index set to the given value.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_StagingResource\" },\n      { \"name\": \"target_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[Stream_PrimitiveType, AnyVectorOfNonZeroRank]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_StagingResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_encoding\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$value `,`\\n    $target (`[` $indices^ `]`)? `:`\\n    type($value)\\n    `->`\\n    $target_encoding (`` `{` $target_encoding_dims^ `}`)?\\n    `in`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.trace\",\n    \"summary\": \"Traces one or more tensor values at runtime.\",\n    \"description\": \"Traces out to a runtime trace sink (console, log file, etc) the given\\n    tensors. The key is arbitrary and can be used for identifying the set of\\n    values being traced.\",\n    \"operands\": [\n      { \"name\": \"resources\", \"type\": \"Variadic<Stream_StagingResource>\" },\n      { \"name\": \"resource_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"resource_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"resource_encodings\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$key `=` `[`\\n    custom<EncodedResourceOperands>(\\n        $resources, type($resources), $resource_sizes,\\n        $resource_encodings, $resource_encoding_dims)\\n    `]` attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.tensor.update\",\n    \"summary\": \"Updates a slice of a subview of a resource in-place.\",\n    \"description\": \"Copies a value into a resource based on tensor encodings. The returned value\\n    is the entire updated target value.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"target_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"target_size\", \"type\": \"Stream_Size\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"update\", \"type\": \"Stream_AnyStreamResource\" },\n      { \"name\": \"update_encoding_dims\", \"type\": \"Variadic<Stream_Dim>\" },\n      { \"name\": \"update_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Stream_AnyStreamResource\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"update_encoding\", \"type\": \"TypeAttr\" },\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"AllTypesMatch<['target', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $update `,` $target `[` $start_indices `]` `:`\\n    $update_encoding (`` `{` $update_encoding_dims^ `}`)?\\n    `in`\\n    type($update) `` `{` $update_size `}`\\n    `->`\\n    $target_encoding (`` `{` $target_encoding_dims^ `}`)?\\n    `in`\\n    custom<ShapedTiedResult>(type($target), $target_size)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.test.timeline_aware\",\n    \"summary\": \"Test op implementing TimelineAwareOpInterface.\",\n    \"description\": \"Test-only operation that implements TimelineAwareOpInterface directly,\\n    allowing Stream dialect tests to verify timeline-aware behavior without\\n    requiring HAL/etc dialect dependencies.\\n\\n    Mimics util.call with the HAL coarse-fences model:\\n    - Takes wait fences that must complete before execution.\\n    - Takes a signal fence to signal when complete.\\n    - Returns an arbitrary result.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"wait_fence_likes\", \"type\": \"Variadic<Stream_TestFence>\" },\n      { \"name\": \"signal_fence_like\", \"type\": \"Stream_TestFence\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` `waits` `(` $wait_fence_likes `)` `signals` `(` $signal_fence_like `)`\\n    attr-dict `:` functional-type($args, $results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.test.timeline_op\",\n    \"summary\": \"Test op implementing TimelineOpInterface.\",\n    \"description\": \"Test-only operation that implements TimelineOpInterface directly,\\n    allowing Stream dialect tests to verify timeline behavior without\\n    requiring execution regions or specific op semantics.\\n\\n    This op takes zero or more resource operands with their sizes, zero or more\\n    await timepoints, and produces zero or more resource results with a result\\n    timepoint. It has no side effects and no execution region - it purely exists\\n    to test timepoint propagation, coverage analysis, and timeline scheduling.\\n\\n    The `await_limit` attribute (default -1) controls how many await timepoints\\n    this op can accept before forcing join creation:\\n    - await_limit = -1: Unlimited awaits (default, no joins created)\\n    - await_limit = 0: No awaits allowed (all timepoints must be joined)\\n    - await_limit = 1: Max 1 await (mimics stream.async.execute behavior)\\n    - await_limit = N: Max N awaits\\n\\n    Use this op when testing passes that operate on TimelineOpInterface methods.\\n    It's simpler than stream.async.execute (no execution region) but can still\\n    model resource-timepoint flows. For example:\\n    - ElideTimepointsPass coverage analysis (elide_timepoints_coverage.mlir)\\n    - PropagateTimepointsPass scheduling (propagate_timepoints.mlir)\\n    - SCF region handling with resources (elide_timepoints_scf.mlir)\\n\\n    Examples:\\n      // Simple timeline op with no dependencies or resources.\\n      %tp0 = stream.test.timeline_op with() : () -> () => !stream.timepoint\\n\\n      // Timeline op awaiting other timepoints.\\n      %tp1 = stream.test.timeline_op await(%tp0) => with() : () -> () => !stream.timepoint\\n\\n      // Timeline op with resource operands and results.\\n      %r, %tp = stream.test.timeline_op\\n        with(%arg) : (!stream.resource<external>{%size}) -> !stream.resource<external>{%size}\\n        => !stream.timepoint\\n\\n      // Timeline op with await_limit to test join creation.\\n      %r, %tp = stream.test.timeline_op await_limit(1) await(%tp0) =>\\n        with(%arg) : (!stream.resource<external>{%size}) -> !stream.resource<external>{%size}\\n        => !stream.timepoint\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"result_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_operands\", \"type\": \"Variadic<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"await_limit\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`await_limit` `(` $await_limit^ `)`)?\\n    (`await` `(` $await_operands^ `)` `=` `` `>`)?\\n    `with` `(` $resource_operands `)` attr-dict `:`\\n    custom<ShapedFunctionType>(ref($resource_operands),\\n                               type($resource_operands), $resource_operand_sizes,\\n                               type($results), $result_sizes,\\n                               $tied_operands)\\n    `=` `` `>` type($result_timepoint)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.await\",\n    \"summary\": \"Awaits a timepoint before returning a set of resources.\",\n    \"description\": \"After asynchronous execution scheduling resources may exist in different\\n    states at different points in the execution timeline. This op enables\\n    resolving the version of a resource after a particular point in the\\n    timeline. As timepoints transitively chain the timepoint must only cover the\\n    resource availability but not be limited to its original production\\n    timepoint.\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Stream_Size>\" },\n      { \"name\": \"await_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sync\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`sync` $sync^)?\\n    $await_timepoint `=` `` `>`\\n    $resource_operands `:`\\n    custom<ShapedTypeList>(type($resource_operands),\\n                              type($results), $resource_operand_sizes)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.barrier\",\n    \"summary\": \"Returns a timepoint indicating when a resource is available.\",\n    \"description\": \"After asynchronous execution scheduling resources may exist in different\\n    states at different points in the execution timeline. This op enables\\n    identifying when the version of a resource after a particular point in the\\n    timeline is available. As timepoints transitively chain the timepoint must\\n    only cover the resource availability but not be limited to its original\\n    production timepoint.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" },\n      { \"name\": \"resource_size\", \"type\": \"Stream_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Stream_AnyStreamResource, Stream_StagingResource]>\" },\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['resource', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $resource `:` type($resource) `` `{` $resource_size `}`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.chain_external\",\n    \"summary\": \"Exports a timepoint to an external dialect type.\",\n    \"description\": \"Defines a conversion to an external dialect type such as `hal.fence`\\n    that is resolved during lowering into the stream dialect. This can be used\\n    to interoperate between levels of the stack that require specifying stream\\n    types and those that prior to lowering do not handle them.\",\n    \"operands\": [\n      { \"name\": \"await_timepoint\", \"type\": \"Stream_Timepoint\" },\n      { \"name\": \"external_values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $await_timepoint\\n    `=` `` `>`\\n    `(` $external_values `:` type($external_values) `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.export\",\n    \"summary\": \"Exports a timepoint to an external dialect type.\",\n    \"description\": \"Defines a conversion to an external dialect type such as `hal.fence`\\n    that is resolved during lowering into the stream dialect. This can be used\\n    to interoperate between levels of the stack that require specifying stream\\n    types and those that prior to lowering do not handle them.\",\n    \"operands\": [\n      { \"name\": \"await_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $await_timepoint\\n    `=` `` `>`\\n    `(` type($results) `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.immediate\",\n    \"summary\": \"Results an immediately-available timepoint.\",\n    \"description\": \"Timepoints indicate a point in the execution timeline and this op can be\\n    used to get a placeholder representing the start of the timeline. Any waits\\n    on the returned timepoint will resolve immediately. This generally folds\\n    away but can be useful if needing to initialize globals or branch args.\",\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `=` `` `>` type($result_timepoint)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.import\",\n    \"summary\": \"Imports a timepoint from an external dialect type.\",\n    \"description\": \"Defines a conversion from an external dialect type such as `hal.semaphore`\\n    that is resolved during lowering into the stream dialect. This can be used\\n    to interoperate between levels of the stack that require specifying stream\\n    types and those that prior to lowering do not handle them.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"affinity\", \"type\": \"OptionalAttr<Stream_AffinityAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`on` `(` $affinity^ `)`)?\\n    $operands `:` `(` type($operands) `)`\\n    `=` `` `>`\\n    type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.timepoint.join\",\n    \"summary\": \"Joins one or more timepoints into the max of all of them.\",\n    \"description\": \"Returns a timepoint that indicates that all of the input timepoints have\\n    been reached.\",\n    \"operands\": [\n      { \"name\": \"await_timepoints\", \"type\": \"Variadic<Stream_Timepoint>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_timepoint\", \"type\": \"Stream_Timepoint\" }\n    ],\n    \"assemblyFormat\": \"`max` `(` $await_timepoints `)` `=` `` `>` type($result_timepoint)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"stream.yield\",\n    \"summary\": \"Yields stream values from an execution region.\",\n    \"description\": \"The values returned represent the asynchronous value at the point in time\\n    the SSA value is defined (or tied).\",\n    \"operands\": [\n      { \"name\": \"resource_operands\", \"type\": \"Variadic<AnyTypeOf<[ Stream_AnyStreamResource, Stream_StagingResource, ]>>\" },\n      { \"name\": \"resource_operand_sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    ($resource_operands^ `:`\\n        custom<ShapedTypeList>(type($resource_operands),\\n                                  $resource_operand_sizes))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tensor.bitcast\",\n    \"summary\": \"tensor bitcast operation\",\n    \"description\": \"Bitcast a tensor from one type to another type of equivalent element width.\\n    If both are ranked, then the rank should be the same and static dimensions\\n    should match.\\n\\n    Example:\\n\\n    ```mlir\\n    // Bitcast from unsigned to signed or signless integer.\\n    %2 = tensor.bitcast %1 : tensor<4xui32> to tensor<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"TensorOf<[AnySignlessInteger, AnyUnsignedInteger, AnySignedInteger, AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"TensorOf<[AnySignlessInteger, AnyUnsignedInteger, AnySignedInteger, AnyFloat]>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"tensor.cast\",\n    \"summary\": \"tensor cast operation\",\n    \"description\": \"Convert a tensor from one type to an equivalent type without changing any\\n    data elements. The source and destination types must both be tensor types\\n    with the same element type. If both are ranked, then the rank should be the\\n    same and static dimensions should match. The operation is invalid if\\n    converting to a mismatching constant dimension.\\n\\n    Example:\\n\\n    ```mlir\\n    // Convert from unknown rank to rank 2 with unknown dimension sizes.\\n    %2 = tensor.cast %1 : tensor<*xf32> to tensor<?x?xf32>\\n\\n    // Convert to a type with more known dimensions.\\n    %3 = tensor.cast %2 : tensor<?x?xf32> to tensor<4x?xf32>\\n\\n    // Discard static dimension and rank information.\\n    %4 = tensor.cast %3 : tensor<4x?xf32> to tensor<?x?xf32>\\n    %5 = tensor.cast %4 : tensor<?x?xf32> to tensor<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"tensor.collapse_shape\",\n    \"summary\": \"operation to produce a tensor with a smaller rank\",\n    \"description\": \"The `tensor.collapse_shape` op produces a new tensor of lower (or equal)\\n    rank whose dimension sizes are a reassociation of the original `src` dimensions.\\n\\n    A reassociation is defined as a continuous grouping of dimensions and is\\n    represented by an array of DenseI64ArrayAttr attribute. The reassociation\\n    maps are applied to the operand shape to obtain the result shape.\\n\\n\\n    Example:\\n\\n    ```mlir\\n    // Dimension collapse (i, j) -> i' and k -> k'\\n    %b = tensor.collapse_shape %a [[0, 1], [2]]\\n        : tensor<?x?x?xf32> into tensor<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reassociation\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$src $reassociation attr-dict `:` type($src) `into` type($result)\"\n  },\n  {\n    \"name\": \"tensor.concat\",\n    \"summary\": \"tensor concatenation operation\",\n    \"description\": \"The \\\"concat\\\" operation constructs a tensor out of a variadic list of input\\n    tensors, concatenated along a static dimension number. All inputs and the\\n    result type must share the same rank.\\n\\n    `dim` specifies the dimension along which to concatenate. The size of the\\n    concatenated dimension in the result must be equal to the sum of the sizes\\n    of the inputs along that dimension. All other dimensions in both the inputs\\n    and result must be the same size.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = tensor.concat dim(0) %0, %1, %2 :\\n        (tensor<3x6xf32>, tensor<3x6xf32>, tensor<1x6xf32) -> tensor<7x6xf32>\\n\\n    // Dynamic + dynamic -> static\\n    %0 = tensor.concat dim(1) %0, %1, %2 :\\n        (tensor<3x?xf32>, tensor<3x2xf32>, tensor<3x?xf32) -> tensor<3x10xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"`dim` `(` $dim `)` $inputs attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tensor.dim\",\n    \"summary\": \"dimension index operation\",\n    \"description\": \"The `tensor.dim` operation takes a tensor and a dimension operand of type\\n    `index`. It returns the size of the requested dimension of the given\\n    tensor. If the dimension index is out of bounds, the behavior is undefined.\\n\\n    The specified tensor type is that of the first operand.\\n\\n    Example:\\n\\n    ```mlir\\n    // Always returns 4, can be constant folded:\\n    %c0 = arith.constant 0 : index\\n    %x = tensor.dim %A, %c0 : tensor<4x?xf32>\\n\\n    // Return the dynamic dimension of %A.\\n    %c1 = arith.constant 1 : index\\n    %y = tensor.dim %A, %c1 : tensor<4x?xf32>\\n\\n    // Equivalent generic form:\\n    %x = \\\"tensor.dim\\\"(%A, %c0) : (tensor<4x?xf32>, index) -> index\\n    %y = \\\"tensor.dim\\\"(%A, %c1) : (tensor<4x?xf32>, index) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyNon0RankedOrUnrankedTensor\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `,` $index `:` type($source)\"\n  },\n  {\n    \"name\": \"tensor.empty\",\n    \"summary\": \"empty tensor operation\",\n    \"description\": \"`tensor.empty` is an operation that defines a tensor of a particular shape.\\n    The shape could be dynamic or static. The contents of the tensor are\\n    unspecified and the only purpose of the op result is to materialize the\\n    specified shape in IR and make it available to other transformations.\\n\\n    `tensor.empty` is useful in transformations that expect destination style\\n    ops. I.e., ops that implement `DestinationStyleOpInterface`. Ops that are\\n    not in destination style can be made compatible with such transformations\\n    with a `tensor.empty` destination.\\n\\n    Note: This op can be lowered to a `bufferization.alloc_tensor`, at which\\n    point it turns into an explicit buffer allocation.\",\n    \"operands\": [\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"`(`$dynamicSizes`)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tensor.expand_shape\",\n    \"summary\": \"operation to produce a tensor with a higher rank\",\n    \"description\": \"The `tensor.expand_shape` op produces a tensor of higher (or equal)\\n    rank than the operand `src` whose dimension sizes are a reassociation of\\n    `src`.\\n\\n    A reassociation is defined as a continuous grouping of dimensions and is\\n    represented with an array of DenseI64ArrayAttr attribute. The reassociation\\n    maps applied to the result tensor with the higher rank must result in the\\n    operand tensor with the smaller rank.\\n\\n    The representation for the output shape supports a partially-static\\n    specification via attributes specified through the `static_output_shape`\\n    argument. A special sentinel value `ShapedType::kDynamic` encodes that the\\n    corresponding entry has a dynamic value. Both the number of SSA inputs in\\n    `output_shape` and the number of `ShapedType::kDynamic` entries in\\n    `static_output_shape` match the number of dynamic dimensions in the result\\n    type.\\n\\n    Example:\\n\\n    ```mlir\\n    // Dimension expansion i -> (i', j') and (k) -> (k')\\n    %b = tensor.expand_shape %a [[0, 1], [2]] output_shape [%sz0, %sz1, 32]\\n        : tensor<?x32xf32> into tensor<?x?x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"output_shape\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reassociation\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"static_output_shape\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$src $reassociation `output_shape`\\n    custom<DynamicIndexList>($output_shape, $static_output_shape) attr-dict `:`\\n    type($src) `into` type($result)\"\n  },\n  {\n    \"name\": \"tensor.extract\",\n    \"summary\": \"element extraction operation\",\n    \"description\": \"The `tensor.extract` op reads a ranked tensor and returns one element as\\n    specified by the given indices. The result of the op is a value with the\\n    same type as the elements of the tensor. The arity of indices must match\\n    the rank of the accessed value. All indices should all be of `index` type.\\n\\n    Example:\\n\\n    ```mlir\\n    %4 = tensor.extract %t[%1, %2] : tensor<4x4xi32>\\n    %5 = tensor.extract %rt[%1, %2] : tensor<?x?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'tensor', 'result', '::llvm::cast<TensorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$tensor `[` $indices `]` attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"tensor.extract_slice\",\n    \"summary\": \"extract slice operation\",\n    \"description\": \"The \\\"extract_slice\\\" operation extract a tensor from another tensor as\\n    specified by the operation's offsets, sizes and strides arguments.\\n\\n    The extract_slice operation supports the following arguments:\\n\\n    * source: the \\\"base\\\" tensor from which to extract a slice.\\n    * offsets: tensor-rank number of offsets into the \\\"base\\\" tensor from which\\n               to extract the slice.\\n    * sizes: tensor-rank number of sizes which specify the sizes of the result\\n             tensor type.\\n    * strides: tensor-rank number of strides specifying subsampling in each\\n               dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value ShapedType::kDynamic encodes that the corresponding entry has\\n    a dynamic value.\\n\\n    After buffer allocation, the \\\"extract_slice\\\" op is expected to lower into a\\n    memref.subview op.\\n\\n    An extract_slice operation may additionally reduce the rank of the resulting\\n    tensor by removing dimensions that are statically known to be of size 1.\\n    This rank-reduction behavior is not required by the op semantics: this\\n    flexibility allows to progressively drop unit dimensions while lowering\\n    between different flavors of ops on that operate on tensors.\\n\\n    #### Verification vs Inference in the rank-reduced case\\n\\n    Note that there may be multiple ways to infer a resulting rank-reduced type.\\n      e.g. 1x6x1 could potentially rank-reduce to either 1x6 or 6x1 2-D shapes.\\n\\n    To disambiguate, the inference helpers `inferCanonicalRankReducedResultType`\\n    only drop the first unit dimensions, in order:\\n      e.g. 1x6x1 rank-reduced to 2-D will infer the 6x1 2-D shape, but not 1x6.\\n\\n    Verification however has access to result type and does not need to infer.\\n    The verifier calls `isRankReducedType(getSource(), getResult())` to\\n    determine whether the result type is rank-reduced from the source type.\\n    This computes a so-called rank-reduction mask, consisting of dropped unit\\n    dims, to map the rank-reduced type to the source type by dropping ones:\\n      e.g. 1x6 is a rank-reduced version of 1x6x1 by mask {2}\\n           6x1 is a rank-reduced version of 1x6x1 by mask {0}\\n           1x2x1x4 is a rank-reduced version of 1x1x2x1x1x4x1 by mask {1, 4, 6}\\n             (remaining common 1 dimensions are matched eagerly)\\n\\n    Example:\\n\\n    ```mlir\\n    // Rank-reducing extract_slice.\\n    %1 = tensor.extract_slice %0[0, 0, 0][1, 16, 4][1, 1, 1] :\\n      tensor<8x16x4xf32> to tensor<16x4xf32>\\n    %3 = tensor.extract_slice %2[%o0, 4, %o2][1, %sz1, 1][1, %st1, 1] :\\n      tensor<8x16x4xf32> to tensor<1x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensor.from_elements\",\n    \"summary\": \"tensor from elements operation.\",\n    \"description\": \"Create a N-D tensor from a range of same-type arguments. The number of\\n    provided `elements` should equal to the number of the elements in the\\n    result type. The `elements` correspond to a flattened tensor.\\n\\n    Example:\\n\\n    ```mlir\\n    tensor.from_elements %a, %b, %c, %d, %e, %f :  tensor<2x3xindex>\\n    ```\\n\\n    will result in a tensor\\n\\n    [[%a, %b, %c]\\n     [%d, %e, %f]]\",\n    \"operands\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStaticShapeTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'elements', '[object Object],[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$elements attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tensor.gather\",\n    \"summary\": \"gather a subset of a tensor at specified indices\",\n    \"description\": \"The `gather` operation extracts a subset of the elements from a `source`\\n    tensor at the given indices.\\n\\n    In its most general form, the tensor of indices specifies all the coordinates\\n    of every element to extract (i.e. COO format, without the payload).\\n    The indices are expected to be confined to coordinate values that fit the\\n    range of the `source` tensor, otherwise the behavior is undefined.\\n\\n    The leading dimensions of the index tensor give the result tensor its leading\\n    dimensions. The trailing dimensions of the result tensor are obtained from\\n    the source tensor by omitting the dimensions specified in `gather_dims`\\n    (rank-reducing semantics) or setting them to `1` (rank-preserving semantics)\\n    (see examples).\\n    The trailing dimension of the index tensor contains the coordinates and is\\n    expected to have its size equal to the number of dimensions being gathered.\\n    This convention allows an idiomatic specification and lowering of \\\"gathering\\n    multiple N-D slices from the source tensor\\\".\\n\\n    Note: in the examples below, we separate out the indexing part of the tensor\\n    type by a whitespace for readability purposes.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 1x2 triple of coordinates in %indices, extract the\\n        // element (i.e. 0-D subset) at the coordinates triple in %source.\\n        //\\n        %out = tensor.gather %source[%indices] gather_dims([0, 1, 2]) :\\n          (tensor<4x4x4xf32>, tensor<1x2x 3xindex>) -> tensor<1x2x 1x1x1xf32>\\n\\n        // Note: result type may be further rank-reduced to tensor<1x2x f32>.\\n    ```\\n\\n    A slice variant is provided to allow specifying whole slices of the source\\n    tensor.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 5x6 singleton of coordinates in %indices, extract the 2-D\\n        // slice %source[*, %indices[...]:%indices[...] + 1, *] with the indices\\n        // corresponding to the `gather_dims` attribute specified by %indices.\\n        //\\n        %out = tensor.gather %source[%indices] gather_dims([1]) :\\n          (tensor<3x4x5xf32>, tensor<6x7x 1xindex>) -> tensor<6x7x 3x1x5xf32>\\n\\n        // Note: result type may be further rank-reduced to tensor<6x7x 3x5xf32>.\\n    ```\\n\\n    The dimensions specified in the gather_dims attribute are ones for which the\\n    result tensor has size `1`.\\n    I.e. if the source type is `axbxcxd` and the coordinates are [1, 3], then\\n    the shape suffix is `ax1xcx1`.\\n    Gather also allows rank-reducing semantics where the shape `ax1xcx1` can be\\n    further simplified to `axc`.\\n\\n    The elemental type of the indices tensor can be any integer type.\\n    In the absence of target-specific or problem specific information the default\\n    type one should use is `index`.\\n\\n    This operation does not support unranked tensors.\\n\\n    An optional `unique` unit attribute may be specified to indicate that the\\n    coordinates in `indices` are statically guaranteed to be unique at runtime.\\n    Incorrectly setting the `unique` attribute when the coordinates are not truly\\n    unique is undefined behavior.\\n\\n    Only full slices are meant to be supported by this op, if one desires\\n    partial slices (e.g. strided windows) one should compose this op with other\\n    tensor ops (e.g. tensor.extract_slice). This is to avoid a slippery slope of\\n    complexity that would make the op unusable in practice.\\n\\n    At the tensor-level, the index tensor is specified in an AoS form (i.e.\\n    coordinate tuple is the most minor). It is the responsibility of further\\n    lowerings and bufferization to implement various concrete layouts.\\n\\n    Note: As currently specified, the operation must lower to an abstraction that\\n    performs copies to the output tensor. This is because the buffer type system\\n    is currently not rich enough to allow multiple non-contiguous views in the\\n    same type. This is visible more clearly in a notional buffer version of the\\n    op:\\n\\n    ```mlir\\n        // memref<?x4x1xf32> is a contiguous buffer of ?x4x1 elements.\\n        // gather from random source slices must copy to the contiguous output.\\n        %out = memref.gather %source[%indices] gather_dims([1]) :\\n          (memref<4x4xf32>, memref<?x 1xindex>) -> memref<?x 4x1xf32>\\n\\n        // Nested buffer support would allow gather to directly index into the\\n        // source buffer (i.e. represent a jagged view into the source).\\n        %out = memref.gather %source[%indices] gather_dims([1]) :\\n          (memref<4x4xf32>, memref<?x 1xindex>) -> memref<? x memref<4x1xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"RankedTensorOf<[AnySignlessIntegerOrIndex]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"gather_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"unique\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $indices `]`\\n      `gather_dims` `(` $gather_dims `)`\\n      (`unique` $unique^)?\\n      attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tensor.generate\",\n    \"summary\": \"Creates a dynamically sized tensor from elements\",\n    \"description\": \"This operation creates a dynamically sized tensor with elements of any type.\\n    It expects one index operand per dynamic extent of the result tensor.\\n\\n    The body region defines the tensor's elements. It takes index operands as\\n    its region arguments that span the index space. The element at the given\\n    position is yielded with the `yield` operation (see `YieldOp`). There is\\n    no defined ordering to the invocations of the body. It is conceptually\\n    a \\\"parallel map\\\" operation.\\n\\n    Example:\\n\\n    ```mlir\\n      %tnsr = tensor.generate %m, %n {\\n      ^bb0(%i : index, %j : index, %k : index):\\n        ...\\n        yield %elem : f32\\n      } : tensor<?x3x?f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynamicExtents\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$dynamicExtents $body attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tensor.insert\",\n    \"summary\": \"element insertion operation\",\n    \"description\": \"The `tensor.insert` op inserts a scalar into a ranked tensor `dest` as\\n    specified by the operation's indices.\\n\\n    It returns a copy of `dest` with the indexed position updated to the value\\n    of `scalar`.\\n\\n    The arity of `indices `must match the rank of the tensor `dest`. All\\n    indices should be of `index` type.\\n\\n    Example:\\n\\n    ```mlir\\n    %4 = tensor.insert %t into %dest[%1, %2] : tensor<4x4xi32>\\n    %5 = tensor.insert %rt into %dest[%1, %2] : tensor<?x?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"scalar\", \"type\": \"AnyType\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'dest', 'result', '$_self'>\" },\n      { \"type\": \"TypesMatchWith<'dest', 'scalar', '::llvm::cast<TensorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$scalar `into` $dest `[` $indices `]` attr-dict `:` type($dest)\"\n  },\n  {\n    \"name\": \"tensor.insert_slice\",\n    \"summary\": \"insert_slice operation\",\n    \"description\": \"The \\\"insert_slice\\\" operation insert a tensor `source` into another\\n    tensor `dest` as specified by the operation's offsets, sizes and strides\\n    arguments.\\n\\n    It returns a copy of `dest` with the proper slice updated with the value\\n    of `source`.\\n\\n    The insert_slice operation supports the following arguments:\\n\\n    * source: the tensor that is inserted.\\n    * dest: the tensor into which the source tensor is inserted.\\n    * offsets: tensor-rank number of offsets into the `dest` tensor into which\\n               the slice is inserted.\\n    * sizes: tensor-rank number of sizes which specify the sizes of the source\\n             tensor type.\\n    * strides: tensor-rank number of strides that specify subsampling in each\\n               dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value ShapedType::kDynamic encodes that the corresponding entry has\\n    a dynamic value.\\n\\n    After buffer allocation, the \\\"insert_slice\\\" op is expected to lower into a\\n    memref.subview op.\\n\\n    An insert_slice operation may additionally specify insertion into a tensor\\n    of higher rank than the source tensor, along dimensions that are statically\\n    known to be of size 1.\\n    This rank-altering behavior is not required by the op semantics: this\\n    flexibility allows to progressively drop unit dimensions while lowering\\n    between different flavors of ops on that operate on tensors.\\n    The rank-altering behavior of tensor.insert_slice matches the rank-reducing\\n    behavior of tensor.extract_slice.\\n\\n    #### Verification in the rank-reduced case\\n\\n    The same verification discussion and mechanisms apply as for ExtractSliceOp.\\n    Unlike ExtractSliceOp however, there is no need for a specific inference.\\n\\n    Example:\\n\\n    ```mlir\\n    // Rank-altering insert_slice.\\n    %1 = tensor.insert_slice %t into %0[0, 0, 0][1, 16, 4][1, 1, 1] :\\n      tensor<16x4xf32> into tensor<8x16x4xf32>\\n    %3 = tensor.insert_slice %tt into %2[%o0, 4, %o2][1, %sz1, 1][1, %st1, 1] :\\n      tensor<1x?xf32> into tensor<8x16x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'dest', 'result', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `into` type($dest)\"\n  },\n  {\n    \"name\": \"tensor.pad\",\n    \"summary\": \"tensor pad operation\",\n    \"description\": \"`tensor.pad` is an operation that pads the `source` tensor\\n    with given `low` and `high` padding config.\\n\\n    The PadOp operation supports the following arguments:\\n\\n    * source: the \\\"base\\\" tensor on which to pad.\\n    * low: A list contains the padding along the start of each\\n           dimension, i.e., how many padded values are prepended\\n           to the beginning of the tensor in each dimension.\\n    * high: A list contains the padding along the end of each\\n            dimension, i.e., how many padded values are appended\\n            to the end of the tensor in each dimension.\\n    * nofold: indicates that the operation should not be folded when source and\\n              result types are equal.\\n\\n    The result tensor dimensions are `low[i]` + `dim[i]` + `high[i]` for each\\n    dimension `i`. The number of elements of `low` and `high` must match the\\n    rank of the input tensor. They can be either a constant or a dynamic value.\\n\\n    The region of the `tensor.pad` operation returns the value to use\\n    for the padding. The arguments of the region represent the index\\n    of the source being accessed. There should be as many arguments as\\n    the rank of the `source` tensor. The value `yield`-ed by the\\n    region is used as the value of the view at the given position.\\n\\n    If `nofold` is set, the padding operation will not be folded away even\\n    if the source type and the padded type have the same static shape. This can\\n    be used, e.g., for packing or promotion to faster memory.\\n\\n    Example 1: add 3 zeros to the beginning and 5 zeros to the end of a 1D\\n    tensor.\\n\\n    ```mlir\\n      %arg0 = ... : tensor<10xi32>\\n      %c0_i32 = arith.constant 0 : i32\\n      %padded = tensor.pad %arg0 low[3] high[5] {\\n      ^bb0(%arg1: index):\\n        tensor.yield %c0_i32 : i32\\n      } : tensor<10xi32> to tensor<18xi32>\\n    ```\\n\\n    Example 2: add 1 value to the beginning of dimension 0, 2 values to the end\\n    of dimension 0, 2 values to the start of dimension 1, and 3 values to the\\n    end of dimension 1.\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %0 low[1, 2] high[2, 3] {\\n      ^bb0(%arg0 : index, %arg1 : index):\\n        tensor.yield %pad_value : f32\\n      } : tensor<?x?xf32> to tensor<?x?xf32>\\n    ```\\n\\n    Example 3:\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %arg0 low[2, %arg1, 3, 3] high[3, 3, %arg1, 2] {\\n      ^bb0(%arg2: index, %arg3: index, %arg4: index, %arg5: index):\\n          tensor.yield %pad_value : f32\\n      } : tensor<1x2x2x?xf32> to tensor<6x?x?x?xf32>\\n    ```\\n\\n    Example 4:\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %arg0 low[0, 0] high[%ub0, %ub1] {\\n      ^bb0(%arg1: index, %arg2: index):\\n        tensor.yield %pad_value : f32\\n      } : tensor<2x3xf32> to tensor<?x?xf32>\\n    ```\\n\\n    Example 5: Force a padded value to be always exist with `nofold`, even\\n    though the padding config specifies that no new elements will be added to\\n    the tensor.\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %arg0 nofold low[0, 0] high[0, 0] {\\n      ^bb0(%arg1: index, %arg2: index):\\n        tensor.yield %pad_value : f32\\n      } : tensor<2x3xf32> to tensor<2x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"low\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"high\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_low\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_high\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"nofold\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source\\n    (`nofold` $nofold^)?\\n    `low` `` custom<DynamicIndexList>($low, $static_low)\\n    `high` `` custom<DynamicIndexList>($high, $static_high)\\n    $region attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensor.parallel_insert_slice\",\n    \"summary\": \"Specify the tensor slice update of a single thread of a parent\\n    InParallelOpInterface op.\",\n    \"description\": \"The `parallel_insert_slice` yields a subset tensor value to its parent\\n    InParallelOpInterface. These subset tensor values are aggregated to\\n    in some unspecified order into a full tensor value returned by the parent\\n    parallel iterating op.\\n    The `parallel_insert_slice` is one such op allowed in the\\n    InParallelOpInterface op.\\n\\n    Conflicting writes result in undefined semantics, in that the indices written\\n    to by multiple parallel updates might contain data from any of the updates,\\n    or even a malformed bit pattern.\\n\\n    If an index is updated exactly once, the value contained at that index\\n    in the resulting tensor will be equal to the value at a corresponding index\\n    of a slice that was used for the updated. If an index is not updated at all,\\n    its value will be equal to the one in the original tensor.\\n\\n    This op does not create a new value, which allows maintaining a clean\\n    separation between the subset and full tensor.\\n\\n    Note that we cannot mark this operation as pure (Pures), even\\n    though it has no side effects, because it will get DCEd during\\n    canonicalization.\\n\\n    The parallel_insert_slice operation supports the following arguments:\\n\\n    * source: the tensor that is inserted.\\n    * dest: the tensor into which the source tensor is inserted.\\n    * offsets: tensor-rank number of offsets into the `dest` tensor into which\\n               the slice is inserted.\\n    * sizes: tensor-rank number of sizes which specify the sizes of the source\\n             tensor type.\\n    * strides: tensor-rank number of strides that specify subsampling in each\\n               dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value ShapedType::kDynamic encodes that the corresponding entry has\\n    a dynamic value.\\n\\n    After buffer allocation, the \\\"parallel_insert_slice\\\" op is expected to lower\\n    into a memref.subview op.\\n\\n    A parallel_insert_slice operation may additionally specify insertion into a\\n    tensor of higher rank than the source tensor, along dimensions that are\\n    statically known to be of size 1.\\n    This rank-altering behavior is not required by the op semantics: this\\n    flexibility allows to progressively drop unit dimensions while lowering\\n    between different flavors of ops on that operate on tensors.\\n    The rank-altering behavior of tensor.parallel_insert_slice matches the\\n    rank-reducing behavior of tensor.insert_slice and tensor.extract_slice.\\n\\n    #### Verification in the rank-reduced case\\n\\n    The same verification discussion and mechanisms apply as for ExtractSliceOp.\\n    Unlike ExtractSliceOp however, there is no need for a specific inference.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `into` type($dest)\"\n  },\n  {\n    \"name\": \"tensor.rank\",\n    \"summary\": \"rank operation\",\n    \"description\": \"The `tensor.rank` operation takes a tensor operand and returns its rank.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = tensor.rank %arg0 : tensor<*xf32>\\n    %1 = tensor.rank %arg1 : tensor<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"tensor.reshape\",\n    \"summary\": \"tensor reshape operation\",\n    \"description\": \"The `reshape` operation converts a tensor from one type to an equivalent\\n    type with a provided shape. The source and destination types are compatible\\n    if both have the same element type, same number of elements. The following\\n    combinations are possible:\\n\\n    a. Source type is ranked or unranked. Shape argument has static size.\\n    Result type is ranked.\\n\\n    ```mlir\\n    // Reshape statically-shaped tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<4x1xf32>, tensor<1xi32>) -> tensor<4xf32>\\n    %dst0 = tensor.reshape %src(%shape0)\\n             : (tensor<4x1xf32>, tensor<2xi32>) -> tensor<2x2xf32>\\n    // Flatten unranked tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<*xf32>, tensor<1xi32>) -> tensor<?xf32>\\n    ```\\n\\n    b. Source type is ranked or unranked. Shape argument has dynamic size.\\n    Result type is unranked.\\n\\n    ```mlir\\n    // Reshape dynamically-shaped 1D tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<?xf32>, tensor<?xi32>) -> tensor<*xf32>\\n    // Reshape unranked tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<*xf32>, tensor<?xi32>) -> tensor<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shape\", \"type\": \"TensorRankOf<[AnySignlessInteger, Index], [1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$source `(` $shape `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tensor.scatter\",\n    \"summary\": \"scatter a tensor into a destination tensor at specified indices\",\n    \"description\": \"The `scatter` operation inserts a `source` tensor into a `dest` tensor at\\n    the given indices.\\n\\n    In its most general form, the tensor of indices specifies all the coordinates\\n    of every element to insert (i.e. COO format, without the payload).\\n    The indices are expected to be confined to coordinate values that fit the\\n    range of the `dest` tensor, otherwise the behavior is undefined.\\n\\n    The leading dimensions of the index tensor must match that of the dest\\n    tensor. The trailing dimensions of the dest tensor must match those of the\\n    source tensor by omitting the dimensions specified in scatter_dims\\n    (rank-reducing semantics) or setting them to `1` (rank-preserving semantics)\\n    (see examples).\\n    This convention allows an idiomatic specification and lowering of\\n    \\\"scattering multiple N-D slices into the dest tensor\\\".\\n    The result type must match the type of the dest tensor.\\n\\n    Note: in the examples below, we separate out the indexing part of the tensor\\n    type by a whitespace for readability purposes.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 1x2 triple of coordinates in %indices, insert the\\n        // element (i.e. 0-D subset) at the coordinates triple in %dest.\\n        //\\n        %out = tensor.scatter %source into %dest[%indices]\\n            scatter_dims([0, 1, 2]) unique :\\n          (tensor<1x2x 1x1x1xf32>, tensor<4x4x4xf32>, tensor<1x2x 3xindex>)\\n            -> tensor<4x4x4xf32>\\n\\n        // Note: source type may be further rank-reduced to tensor<1x2x f32>.\\n    ```\\n\\n    A slice variant is provided to allow specifying insertion of whole tensor\\n    slices into the `dest` tensor.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 3 singleton of coordinates in %indices, insert the 2-D\\n        // slice into %dest[*, %indices[...]:%indices[...] + 1, *] with the\\n        // indices corresponding to the scatter_dims attribute specified by\\n        // %indices.\\n        //\\n        %out = tensor.scatter %source into %dest[%indices] scatter_dims([1]) unique :\\n          (tensor<3x 4x1x6xf32>, tensor<4x5x6xf32>, tensor<3x 1xindex>)\\n            -> tensor<4x5x6xf32>\\n    ```\\n\\n    The dimensions specified in the scatter_dims attribute are ones for which the\\n    source tensor has size `1`.\\n    I.e. if the dest type is `axbxcxd` and the coordinates are [1, 3], then\\n    the source type suffix is `ax1xcx1`.\\n    Scatter also allows rank-reducing semantics where the shape `ax1xcx1` can be\\n    further simplified to `axc`.\\n\\n    The elemental type of the indices tensor can be any integer type.\\n    In the absence of target-specific or problem specific information the default\\n    type one should use is `index`.\\n\\n    This operation does not support unranked tensors.\\n\\n    A `unique` unit attribute must be be specified to indicate that the\\n    coordinates are statically guaranteed to be unique at runtime. If coordinates\\n    are not truly unique at runtime, the behavior is undefined.\\n\\n    Only full slices are meant to be supported by this op, if one desires\\n    partial slices (e.g. strided windows) one should compose this op with other\\n    tensor ops (e.g. tensor.insert_slice). This is to avoid a slippery slope of\\n    complexity that would make the op unusable in practice.\\n\\n    At the tensor-level, the index tensor is specified in an AoS form (i.e.\\n    coordinate tuple is the most minor). It is the responsibility of further\\n    lowerings and bufferization to implement various concrete layouts.\\n\\n    Note: As currently specified, the operation must lower to an abstraction that\\n    performs copies to the output tensor. This is because the buffer type system\\n    is currently not rich enough to allow multiple non-contiguous views in the\\n    same type. This is visible more clearly in a notional buffer version of the\\n    op:\\n\\n    ```mlir\\n        // memref<?x 4xf32> is a contiguous buffer of ?x4 elements, scatter into\\n        // random dest slices must copy to the contiguous dest.\\n        //\\n        some_side_effecting_op_writing_into %source, ...: memref<3x 4xf32>\\n        memref.scatter %source into %dest[%indices] scatter_dims([1]) unique :\\n          (memref<3x 4xf32>, memref<?x 4xf32>, memref<?x 1xindex>)\\n\\n        // Nested buffer support in the producing op would allow writing directly\\n        // into the dest buffer.\\n        %v = some_nested_buffer_view_op %dest[%indices] scatter_dims([1]) unique :\\n          memref<? x memref<4xf32>>\\n        some_side_effecting_op_writing_into %v, ...: memref<? x memref<4xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"RankedTensorOf<[AnySignlessIntegerOrIndex]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"unique\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest `[` $indices `]`\\n      `scatter_dims` `(` $scatter_dims `)`\\n      (`unique` $unique^)?\\n      attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tensor.splat\",\n    \"summary\": \"tensor splat or broadcast operation\",\n    \"description\": \"Broadcast the operand to all elements of the result tensor.\\n\\n    An additional argument of type `index` must be provided for each dynamic\\n    dimension present in the result type.\\n\\n    Example for a statically shaped tensor:\\n\\n    ```mlir\\n    %s = arith.constant 1.0 : f32\\n    %t = tensor.splat %s : tensor<8x16xf32>\\n    ```\\n\\n    Example for a tensor containing dynamic dimensions:\\n\\n    ```mlir\\n    // Broadcasts %s to a 3D dynamically shaped tensor, with %m and %n binding\\n    // to dimensions 0 and 2 of the resulting tensor, respectively.\\n    %m = arith.constant 10 : index\\n    %n = arith.constant 30 : index\\n    %t = tensor.splat %s[%m, %n] : tensor<?x20x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyType\" },\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"aggregate\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'aggregate', 'input', '::llvm::cast<TensorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$input (`[` $dynamicSizes^ `]`)? attr-dict `:` type($aggregate)\"\n  },\n  {\n    \"name\": \"tensor.yield\",\n    \"summary\": \"Yield a value from a region\",\n    \"description\": \"This operation is used to yield a single value from a within a region. It\\n     is used to create dynamically sized tensors\\n     (see `tensor.generate` and `tensor.pad` ops).\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"tensorrt.activation\",\n    \"summary\": \"TensorRT activation (IActivationLayer) operation\",\n    \"description\": \"The `tensorrt.activation` operation models a unary operation that depends\\n    on up to two parameters (`alpha` and `beta`). The purpose of the two\\n    parameters depends on the `activationType`.\\n\\n    This op applies the `activationType` function on an element-wise basis\\n    to form the result.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"activationType\", \"type\": \"TensorRT_ActivationTypeAttr{kRELU|kSIGMOID|kTANH|kLEAKY_RELU|kELU|kSELU|kSOFTSIGN|kSOFTPLUS|kCLIP|kHARD_SIGMOID|kSCALED_TANH|kTHRESHOLDED_RELU|kGELU_ERF|kGELU_TANH}\" },\n      { \"name\": \"alpha\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"beta\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  $input `:` type($input)\"\n  },\n  {\n    \"name\": \"tensorrt.argmax\",\n    \"summary\": \"Represents an argmax operation\",\n    \"description\": \"The `tensorrt.argmax` operation returns the maximum value as well as\\n    the index for the that value along the specified dimension. The\\n    result types are not rank-reduced.\\n\\n    This operation is a TensorRT dialect extension operation and will be\\n    lowered to a `tensorrt.top_k` operation before translation to a\\n    TensorRT engine.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.argmin\",\n    \"summary\": \"Represents an argmin operation\",\n    \"description\": \"The `tensorrt.argmin` operation returns the minimum value as well as\\n    the index for the that value along the specified dimension. The\\n    result types are not rank-reduced.\\n\\n    This operation is a TensorRT dialect extension operation and will be\\n    lowered to a `tensorrt.top_k` operation before translation to a\\n    TensorRT engine.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.assertion\",\n    \"summary\": \"TensorRT IAssertionLayer operation\",\n    \"description\": \"An assertion layer in a network\\n\\n    The `tensorrt.assertion` operation has an input tensor, `condition` and no output.\\n    The input tensor must be a boolean type of rank 0 or 1.\\n    If any element of the input is provably false at build time, the network is rejected.\\n    If any element of the input is false at runtime for the supplied runtime dimensions,\\n    an error occurs, much the same as if any other runtime error is handled.\\n\\n    The attribute named `message` defines the message to print if the assertion fails.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TensorRT_RankedTensorOf<[I1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)`\"\n  },\n  {\n    \"name\": \"tensorrt.broadcast\",\n    \"summary\": \"Represents a broadcast explicitly that occurs in different TensorRT operations\",\n    \"description\": \"`tensorrt.broadcast` is an explicit representation of the broadcasting\\n    operation that occurs in TensorRT operations such as\\n    `tensorrt.element_wise`. In addition, this broadcast operation is allowed to\\n    perform a rank expansion as well. The semantics are aligned with the\\n    StableHLO `broadcast_in_dim` operation.\\n\\n    The `broadcast_dims` attribute contains a list of indices that such that\\n    input type dimension `i` is mapped to `broadcast_dims[i]` of the result\\n    type. `broadcast_dims` do not have to be increasing; the mapping is allowed\\n    to permute the ordering of the input dimensions.\\n\\n    If the result shape is not fully specified, then the `shape` tensor\\n    containing must be provided to specify the result shape.\\n\\n    This operation is a TensorRT dialect extension operation and will either be\\n    canonicalized away (by absorbing into e.g. `tensorrt.element_wise`) or be lowered\\n    into a reshape operation such as `tensorrt.shuffle`.\\n\\n    #### Example\\n\\n    ```mlir\\n    %result = tensorrt.broadcast %input broadcast_dims<3, 1>\\n                : tensor<1x10xf32> to tensor <4x10x4x28xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_AllTypesTensor\" },\n      { \"name\": \"shape\", \"type\": \"Optional<TensorRT_ShapeTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$input `broadcast_dims` `<` custom<StaticIndexI64Array>($broadcast_dims) `>`\\n      (`shape` `(` $shape^ `:` type($shape) `)`)?\\n      attr-dict `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.call\",\n    \"summary\": \"calls a TensorRT engine defined in a `tensorrt.module`\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyShaped, AnySignlessIntegerOrIndex ]>>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` ($inputs^ `:` type($inputs))? `)`\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    attr-dict (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tensorrt.call_alloc\",\n    \"summary\": \"calls a TensorRT engine defined in a `tensorrt.module` and allocates output tensors\",\n    \"description\": \"This operation calls a TensorRT engine and allocates output tensors. It will be converted to an\\n    `enqueue_alloc` operation in a later pass.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyShaped, AnySignlessIntegerOrIndex ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ AnyMemRef, AnyTensor ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` ($inputs^ `:` type($inputs))? `)`\\n    attr-dict (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tensorrt.cast\",\n    \"summary\": \"TensorRT cast (ICastLayer) operation\",\n    \"description\": \"The `tensorrt.cast` operation performs a cast from the the input tensor\\n    type to the result tensor type, changing only the element type.\\n\\n    This operation supports casting to and from all data types except f8 and i4.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[I1, UI8, TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[I1, UI8, TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.collapse_rank\",\n    \"summary\": \"Collapses the rank of the input tensor by removing 1's from the shape\",\n    \"description\": \"The shape of the tensor is \\\"collapsed\\\" by removing 1's (not necessarily all\\n    of them). This operation achieves the result commonly known as \\\"squeezing\\\"\\n    a tensor in deep learning frameworks.\\n\\n    This operation is a TensorRT dialect extension operation and is lowered\\n    into a TensorRT shuffle operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.concatenation\",\n    \"summary\": \"TensorRT concatenate (IConcatenationLayer) operation\",\n    \"description\": \"The `tensorrt.concatenation` operation concatenates the given `inputs`\\n    along the dimension `axis`. The input types must have equal rank and\\n    the shapes must be such that dimension sizes other than the size for\\n    `axis` must be equal among all inputs.\\n\\n    The concatenation axis is expected to be non-negative.\\n\\n    The result dimension size along the concatenation axis is the sum of\\n    the corresponding input dimensions. Every other output dimension is\\n    the same as the corresponding dimension of the inputs.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorRT_RankedTensorOf<[ I1, TensorRT_I8, I32, I64, TensorRT_F8, F16, BF16, F32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.condition\",\n    \"summary\": \"While loop's continuation condition.\",\n    \"description\": \"The `tensorrt.condition` operation accepts the continuation of\\n    `tensorrt.while` construct. If its first argument is true, the\\n    \\\"body\\\" region of the `tensorrt.while` is executed, with the remaining\\n    arguments forwarded to the entry block of the region. Otherwise,\\n    the loop terminates.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"0DTensorOf<[I1]>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $condition `:` type($condition) `)` attr-dict ($args^ `:` type($args))?\"\n  },\n  {\n    \"name\": \"tensorrt.constant\",\n    \"summary\": \"TensorRT constant (IConstantLayer) operation\",\n    \"description\": \"The `tensorrt.constant` op represents a constant value.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[I1, TensorRT_I4, TensorRT_I8, I32, I64, TensorRT_F8, F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"weights\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['weights', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $weights\"\n  },\n  {\n    \"name\": \"tensorrt.convolution\",\n    \"summary\": \"TensorRT convolution (IConvolutionLayer) operation\",\n    \"description\": \"The `tensorrt.convolution` operation represents a 2D or 3D convolution:\\n    `input`'s spatial dimensions are convolved with the filters of `kernel`\\n    to form the result.\\n\\n    The `input` is assumed to be organized such that the dimensions of the shape\\n    correspond to `[batch_dim, chan_dim, spatial dimensions... ]`.\\n\\n    The `kernel` is assumed to be organized such that the dimensions of the shape\\n    correspond to `[num_filters, chan_dim / num_groups, filter spatial dimensions... ]`.\\n\\n    The `kernel` input must be computable at build time via constant folding.\\n\\n    An optional `bias` is supported, which adds a per-channel constant to each\\n    value in the output. If supplied `bias` must be the result of a\\n    `tensorrt.constant` operation.\\n\\n    TODO: add other padding modes.\\n    TODO: add stride/padding/dilation/groups description.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" },\n      { \"name\": \"kernel\", \"type\": \"Optional<TensorRT_RankedTensorOf<[ F16, BF16, F32 ]>>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<TensorRT_RankedTensorOf<[ F16, BF16, F32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernelStatic\", \"type\": \"OptionalAttr<ElementsAttr>\" },\n      { \"name\": \"biasStatic\", \"type\": \"OptionalAttr<ElementsAttr>\" },\n      { \"name\": \"stride\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"pre_padding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"post_padding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"num_groups\", \"type\": \"DefaultValuedAttr<UI32Attr, 1>\" },\n      { \"name\": \"dilation\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  `in` `(` $input `:` type($input) `)`\\n      (`kernel` `(` $kernel^ `:` type($kernel) `)` )?\\n      (`bias`   `(` $bias^   `:` type($bias)   `)` )?\\n      `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.deconvolution\",\n    \"summary\": \"TensorRT deconvolution (IDeconvolutionLayer) operation\",\n    \"description\": \"The `tensorrt.deconvolution` operation represents a 2D or 3D deconvolution:\\n    `input`'s spatial dimensions are convolved with the filters of `kernelWeights`\\n    to form the result.\\n\\n    The `input` is assumed to be organized such that the dimensions of the shape\\n    correspond to `[batch_dim, chan_dim, spatial dimensions... ]`.\\n\\n    The `kernelWeights` is assumed to be organized such that the dimensions of the shape\\n    correspond to `[chan_dim, num_filters / num_groups, filter spatial dimensions... ]`.\\n\\n    The `kernelWeights` input must be computable at build time via constant folding.\\n\\n    An optional `biasWeights` is supported, which adds a per-channel constant to each\\n    value in the output. If supplied `biasWeights` must be the result of a\\n    `tensorrt.constant` operation.\\n\\n    TODO: add other padding modes.\\n    TODO: add stride/padding/dilation/groups description.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" },\n      { \"name\": \"kernelWeights\", \"type\": \"Optional<TensorRT_RankedTensorOf<[ TensorRT_I8, F16, F32 ]>>\" },\n      { \"name\": \"biasWeights\", \"type\": \"Optional<TensorRT_RankedTensorOf<[ TensorRT_I8, F16, F32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernelWeightsStatic\", \"type\": \"OptionalAttr<ElementsAttr>\" },\n      { \"name\": \"biasWeightsStatic\", \"type\": \"OptionalAttr<ElementsAttr>\" },\n      { \"name\": \"stride\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"pre_padding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"post_padding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"num_groups\", \"type\": \"DefaultValuedAttr<UI32Attr, 1>\" },\n      { \"name\": \"dilation\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  `in` `(` $input `:` type($input) `)`\\n      (`kernelWeights` `(` $kernelWeights^ `:` type($kernelWeights) `)` )?\\n      (`biasWeights`   `(` $biasWeights^   `:` type($biasWeights)   `)` )?\\n      `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.dequantize\",\n    \"summary\": \"TensorRT Dequantize(IDequantizeLayer) operation\",\n    \"description\": \"The `tensorrt.dequantize` operation dequantize an 8-bit signed integer into\\n    a floating-point output tensor using the `scale` input.\\n\\n    NOTE: Although `zero_point` is an optional input for TensorRT\\n    Dequantize(IDequantizeLayer) operation, it is removed here because it's just\\n    a placeholder which is not actually used and cannot be set to other values\\n    other than 0 in TensorRT.\\n    `zero_point` is omitted for the following description.\\n\\n    Dequantization can either be applied uniformly for the entire input\\n    (\\\"per-tensor\\\" manner) using a single scalar \\\"scale\\\" value, or it can be\\n    applied in a \\\"per-channel\\\" manner, meaning that different slices of the input\\n    tensor along a specified `axis` are dequantized using different parameters in\\n    a 1D \\\"scale\\\" tensor, or it can be applied in a \\\"2D block\\\" manner using a 2D\\n    \\\"scale\\\" tensor (supports only `INT4` 2D weight inputs).\\n\\n    #### Caveats\\n\\n    - `scale` must be compile time constants (after constant folding by either\\n        MLIR-TRT or TRT itself).\\n\\n    #### Argument Constraints\\n\\n    If `axis` is not given:\\n\\n    - `scale` must be 2D for INT4 block dequantization. Block dequantization always\\n    happens along `axis` 0.\\n    - `scale` must be a scalar (0D tensor i.e. `tensor<[element type]>`) for\\n    per-tensor dequantization.\\n\\n    If `axis` is given:\\n\\n    - `scale` must be 1D tensors with `input.shape[axis]`\\n        number of elements, for per-channel dequantization.\\n    - Similarly, the size of input dimension `input.shape[axis]` must be\\n      a compile time constant (i.e. it cannot be `?`).\\n    - `axis` must be in the range of `[0, R)`.\\n\\n    #### Dequantization Computation\\n\\n    Let `(i_0, ..., i_{R-1})` represent indices in the index space of the\\n    `input` tensor, which is of rank `R`.\\n\\n    Per-tensor dequantization transforms the input\\n    uniformly as follows:\\n\\n    ```\\n    output[ i_0, ..., i_{R-1} ] := input[ i_0, ..., i_{R-1} ] * (f32)scale\\n    ```\\n\\n    Per-channel dequantization is supported only for weight inputs. Activations\\n    can't be dequantized per-channel. Given a 1D tensor of `scale` values and\\n    `axis`, the input is transformed as follows:\\n\\n    ```\\n    output[i_0, ..., i_{axis}, ..., i_{R-1} ] :=\\n          input[ i_0, ..., i_{axis}, ..., i_{R-1} ] * scale[ i_{axis} ]\\n    ```\\n\\n    Block quantization is supported only for 2-D weight inputs of type `INT4`.\\n    Axis for block quantization is always 0. Let `B` be the block size. Block\\n    quantization transforms the input as follows:\\n\\n    ```\\n    output[i_0, i_1] :=\\n      input[ i_0, i_1 ] * scale[ i_0 // B, i_1 ]\\n    ```\\n\\n    The output shape is the same as the input shape. The dequantization axis is\\n    in reference to the input tensor's dimensions.\\n\\n    Valid conversions are as follows:\\n\\n    ```\\n    (int8 | f8E4M3FN | int4) -> (f32 | f16 | bf16)\\n    ```\\n\\n    #### Examples\\n\\n    ```mlir\\n    %1 = tensorrt.dequantize in(%arg0 : tensor<10x10xi8>)\\n          scale(%arg1 :  tensor<1xf32>) -> tensor<10x10xf32>\\n    %2 = tensorrt.dequantize { axis = 1 : i32 } in(%arg0 : tensor<10x10xi8>)\\n          scale(%arg1 : tensor<10xf32>) -> tensor<10x10xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Non0RankedTensorOf<[TensorRT_I8, TensorRT_F8, TensorRT_F4, TensorRT_I4]>\" },\n      { \"name\": \"scale\", \"type\": \"TensorRT_RankedTensorOf<[F32, F16, BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F32, F16, BF16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `in` `(` $input `:` type($input) `)`\\n    `scale` `(` $scale `:` type($scale) `)`\\n    `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.dynamic_quantize\",\n    \"summary\": \"TensorRT DynamicQuantize(IDynamicQuantize) operation\",\n    \"description\": \"This layer performs dynamic, per-block quantization on the `input` tensor,\\n    converting it to the NVFP4 format. It uses a \\\"double quantization\\\" scheme\\n    to maintain accuracy while minimizing memory usage.\\n\\n    The quantization process involves two levels of scaling:\\n    1. **First-Level Scale (Dynamic, Per-Block)**: For each block of `block_size`\\n    (currently, only block size of 16 is supported) values along the specified `axis`,\\n    the layer dynamically computes a scaling factor.\\n    2. **Second-Level Scale (Static, Per-Tensor)**: A single `FP32` scaling factor,\\n    `double_quant_scale`, is provided as an input to the layer. This\\n    \\\"scale for the scales\\\" is computed offline via calibration and is used\\n    to quantize the first-level scales into the limited `FP8` range `scales`.\\n\\n    Thus, final quantized `result` is in `FP4` format and scales `scales`\\n    is in `FP8` format.\\n\\n    **Constraints:**\\n    - The `block_size` is fixed at 16.\\n    - The dimension of the `axis` must be a compile-time constant and be divisible by 16.\\n\\n    **Example**\\n    ```\\n    %double_quant_scale = tensorrt.constant dense<1.0> : tensor<f32>\\n    %axis = arith.constant 1 : i32\\n    %inp_f32 = tensorrt.constant ... : tensor<2x32xf32>\\n    %out_f4, %scale_f8 = tensorrt.dynamic_quantize {axis = 1, block_size = 16}\\n        in(%inp_f32 : tensor<2x2xf32>) double_quant_scale(%double_quant_scale : tensor<f32>)\\n        -> (tensor<2x32xf4E2M1FN>, tensor<2x2xf8E4M3FN>);\\n\\n    .....\\n\\n    %dequantize_scale = tensorrt.dequantize in(%scale_f8 : tensor<2x2xf8E4M3FN>)\\n        scale(%double_quant_scale : tensor<f32>) -> tensor<2x2xf32>\\n    %dequantize_data = tensorrt.dequantize {axis = 1} in(%out_f4 : tensor<2x32xf4E2M1FN>)\\n        scale(%dequantize_scale : tensor<2x2xf32>) -> tensor<2x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Non0RankedTensorOf<[F32, F16, BF16]>\" },\n      { \"name\": \"double_quant_scale\", \"type\": \"TensorRankOf<[F32, F16, BF16], [0]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_F4]>\" },\n      { \"name\": \"scales\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_F8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"block_size\", \"type\": \"DefaultValuedAttr<I32Attr, 16>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `in` `(` $input `:` type($input) `)`\\n    `double_quant_scale` `(` $double_quant_scale `:` type($double_quant_scale) `)`\\n    `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.einsum\",\n    \"summary\": \"TensorRT einsum (IEinsumLayer) operation\",\n    \"description\": \"The `tensorrt.einsum` op implements a summation over the elements of the\\n    inputs along dimensions specified by the equation parameter, based on the\\n    Einstein summation convention.\\n\\n    The layer can have one or two inputs of rank >= 0. All the inputs must have\\n    `f16` or `f32` data types, but can differ in data type.\\n\\n    The result type has element type`f32` and a shape that is determined by\\n    the einsum equation.\\n\\n    The equation specifies ASCII lower-case letters for each dimension in the\\n    inputs in the same order as the dimensions, separated by comma for each\\n    input. The dimensions labeled with the same subscript must match or be\\n    broadcastable. Repeated subscript labels in one input take the diagonal.\\n    Repeating a label across multiple inputs means that those axes will be\\n    multiplied. Omitting a label from the output means values along those axes\\n    will be reduced (summed).\\n\\n    There are two modes of interpretation of  the equation: implicit and\\n    explicit.\\n\\n    #### Implicit Mode\\n\\n    In implicit mode, the indices which appear once in the expression will be\\n    part of the output in increasing\\n    alphabetical order.\\n\\n    #### Explicit Mode\\n\\n    In explicit mode, the output can be controlled by specifying output\\n    subscript labels by adding an arrow (`->`) followed by subscripts for\\n    the output. For example, “ij,jk->ik” is equivalent to “ij,jk”.\\n\\n    #### Examples\\n\\n    Many common operations can be expressed using the Einsum equation.\\n    For example:\\n    Matrix Transpose:             ij->ji\\n    Sum:                          ij->\\n    Matrix-Matrix Multiplication: ik,kj->ij\\n    Dot Product:                  i,i->\\n    Matrix-Vector Multiplication: ik,k->i\\n    Batch Matrix Multiplication:  ijk,ikl->ijl\\n\\n    #### Unsupported einsum features\\n\\n    The following einsum conventions are not supported by TensorRT\\n    (as of TensorRT 8.5):\\n    - Diagonal (repeated index in one operand)\\n    - Use of ellipsis\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorRT_RankedTensorOf<[ F16, BF16, F32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"equation\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.element_wise\",\n    \"summary\": \"TensorRT element-wise (IElementWiseLayer) operation\",\n    \"description\": \"The `tensorrt.element_wise` operation takes two Tensor-typed inputs\\n    and performs a mathematical operation to yield the result in a per-element\\n    manner. This operation also has broadcast semantics described below.\\n\\n    #### Broadcasting Semantics\\n\\n    The input tensors must have the same rank. For each dimension, their lengths\\n    must match, or one of them must be one. In the latter case, the tensor is\\n    broadcast along that axis.\\n\\n    The output tensor has the same rank as the inputs. For each output dimension,\\n    its length is equal to the lengths of the corresponding input dimensions if they match,\\n    otherwise it is equal to the length that is not one.\\n\\n    Note that during compile time, the length of a dimension may be unknown.\\n    Therefore, it may not be possible to validate broadcasting semantics until\\n    runtime. For example:\\n\\n    ```mlir\\n    tensorrt.element_wise kADD\\n        (%input0, %input1 : tensor<10x128xf32>, tensor<?x128xf32>) -> tensor<10x128xf32>\\n    ```\\n\\n    In this case, the compiler will not reject the IR because it cannot prove\\n    that `?` is not `1`. But at runtime, TensorRT should throw an error if `?`\\n    does not turn out to be 1.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elementwiseOperation\", \"type\": \"TensorRT_ElementWiseOperationAttr{kSUM|kPROD|kMAX|kMIN|kSUB|kDIV|kPOW|kFLOOR_DIV|kAND|kOR|kXOR|kEQUAL|kGREATER|kLESS}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $elementwiseOperation\\n      `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.expand_rank\",\n    \"summary\": \"Expands the rank of the input tensor by inserting 1's in the shape\",\n    \"description\": \"The shape of the tensor is \\\"expanded\\\" by inserting 1's into the shape.\\n\\n    This operation is typically used to ensure that result tensor meets the required\\n    rank for broadcasting in elementwise operations or for certain operations\\n    such as matrix multiplication.\\n\\n    This operation is a TensorRT dialect extension operation and is lowered\\n    into a TensorRT shuffle operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.for\",\n    \"summary\": \"TensorRT Loop (ILoopLayer) operation\",\n    \"description\": \"The `tensorrt.for` operation represents a for-style loop that executes its\\n    body once for each valid value of the induction variable.\\n\\n    The iteration variable takes values in [`start`, `stop`), incrementing by\\n    `step` each iteration. The values `start`, `stop`, and `step` must be\\n    `tensor<i32>` (0-D i32 tensor types).\\n\\n    The loop body is a single-block region. The block arguments represent\\n    the following (in order from first to last):\\n\\n     1. The induction variable.\\n     2. Loop carried dependencies.\\n\\n    #### Loop carried dependencies\\n\\n    The initial values of all loop carried dependencies are given by the op's\\n    `init` arguments (see example). For each loop carried dependency, the loop\\n    body must yield a value, representing the value that should be passed to\\n    the next iteration.\\n\\n    #### Example\\n\\n    The below example constructs a simple loop that adds a tensor of 1's\\n    to the input argument 10 times:\\n\\n    ```mlir\\n    func.func @trt_for_loop(%arg0: tensor<10xf32>) -> tensor<10xf32> {\\n      %lb = tensorrt.constant dense<0> : tensor<i32>\\n      %ub = tensorrt.constant dense<10> : tensor<i32>\\n      %step = tensorrt.constant dense<1> : tensor<i32>\\n      %ones = tensorrt.constant dense<1.0> : tensor<10xf32>\\n      %0 = tensorrt.for %i = %lb to %ub step %step init(%iter0 = %arg0) -> tensor<10xf32> {\\n        %add = tensorrt.element_wise <kSUM>(%iter0, %ones : tensor<10xf32>, tensor<10xf32>) -> tensor<10xf32>\\n        tensorrt.yield %add : tensor<10xf32>\\n      }\\n      return %0 : tensor<10xf32>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lb\", \"type\": \"0DTensorOf<[I32]>\" },\n      { \"name\": \"ub\", \"type\": \"0DTensorOf<[I32]>\" },\n      { \"name\": \"step\", \"type\": \"0DTensorOf<[I32]>\" },\n      { \"name\": \"init\", \"type\": \"Variadic<TensorRT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TensorRT_Tensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tensorrt.gather\",\n    \"summary\": \"TensorRT gather (IGatherLayer with kDEFAULT mode) operation\",\n    \"description\": \"The `tensorrt.gather` operation represents a gather operation on the input\\n    data elements `data` using the indices `indices`. The operation additionally\\n    has two parameters:\\n\\n    1. `numBroadcastDims`: controls how the dimensions of `indices` are\\n        interpreted. It must be either 0 (default) or 1 and follow `numBroadcastDims` <= `axis`.\\n    2. `axis`: The dimension number in the shape of `data`'s type from which\\n        to start gathering data.\\n\\n    The rank of the `indices` tensor has no restrictions.\\n\\n    The result is expected to be equal to\\n    `rank(data) + rank(indices) - 1 - numBroadcastDims`.\\n\\n    First `numBroadcastDims` dimensions of the output are computed by\\n    applying broadcast rules to first `numBroadcastDims` dimensions of\\n    the indices indices and data tensors. Note that `0 <= numBroadcastDims <= 1`.\\n    The rest of dimensions are computed by copying the dimensions of the `data`\\n    and replacing the `axis` dimension with the dimensions of the corresponding\\n    indices.\\n\\n    This op follows the semantics of\\n    [tf.GatherV2](https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/gather-v2)\\n    and [onnx.Gather](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Gather)\\n    and [torch.index_select](https://pytorch.org/docs/stable/generated/torch.index_select.html)\\n    (when the rank of `indices` is constrained to be `1`).\\n\\n    #### Output Computation when `numBroadcastDims = 0`:\\n\\n    For data of rank `D`, indices of rank `I`, the result rank `R := D + I -1`.\\n\\n    Let `J = (r_0, ..., r_{axis-1}, r_{axis},..., r_{axis+I-1}, ..., r_{R-1})` be a point\\n    in the iteration space of `result`.\\n\\n    For each `J`, the slice of these numbers `J[axis, axis+I-1] = (r_{axis}, ..., r_{axis+I-1})`\\n    is an iteration point in the space of `indices`.\\n\\n    Then let `K = index[r_{axis}, ..., r_{axis+I-1} ]` and the result is formed by\\n\\n    ```\\n    result[r_0, ...,  r_{R-1} ]\\n        = data[r_0, ..., r_{axis-1}, K, r_{axis+I}, ..., r_{R-1} ]\\n    ```\\n\\n    #### Caveats\\n\\n    * If an dimension of `data` has dynamic/unknown length, then using a negative\\n      index for it has undefined behavior.\\n    * This layer does not support DLA.\\n    * Zero will be stored for all out-of-bounds (OOB) access.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"numBroadcastDims\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.gather_elements\",\n    \"summary\": \"TensorRT gather (IGatherLayer with kELEMENTS mode) operation\",\n    \"description\": \"The `tensorrt.gather_elements` operation represents a gather operation on\\n    the input data elements `data` using the indices `indices`. The operation\\n    additionally has a parameter`axis`, which is the dimension number in\\n    the shape of `data` from which to start gathering data.\\n\\n    This op follows the semantics of\\n    [onnx.GatherElements](https://github.com/onnx/onnx/blob/main/docs/Operators.md#GatherElements).\\n\\n    The shape of the result is equal to the shape of `indices`.\\n\\n    For each element X of indices:\\n      Let J denote a sequence for the subscripts of X\\n      Let K = sequence J with element [axis] replaced by X\\n        output[J] = data[K]\\n\\n    #### Output Calculation\\n\\n    For each point `(i_0, ..., i_{rank-1})` in the iteration space of `indices`:\\n\\n    Let `idx = indices[i_0, ..., i_{rank-1} ]`.\\n\\n    Then the result values are calculated as follows:\\n\\n    ```\\n    result[i_0, ..., i_{axis}, ..., i_{rank-1} ] = data[i_0, ..., idx, ..., i_rank{-1} ]\\n    ```\\n\\n    #### Example\\n\\n    Given a tensor `input : tensor<2x20xf32>`, suppose you wanted to permute\\n    the elements of `input[0, :]` and `input[1, :]` according to two\\n    separate permutations `perm1 : tensor<20xi64>` and `perm2 : tensor<20xi64>`.\\n\\n    Form the `indices : tensor<2x20xi64>` such that  `indices[0, :] = perm1`\\n    and `indices[1, :] = perm2`.\\n\\n    Then the desired result can be achieved via\\n\\n    ```mlir\\n    %result = tensorrt.gather_elements {\\n        axis = 1 : i64\\n      } ins(%input, %indices : tensor<2x20xf32>, tensor<2x20xi64>)\\n        -> tensor<2x20xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.gather_nd\",\n    \"summary\": \"TensorRT gather-ND operation (IGatherLayer with kND mode)\",\n    \"description\": \"The `tensorrt.gather_nd` operation gathers slices of `data` into the\\n    `result`. The operation can be described using the below pseudo-code.\\n    The key difference between `tensorrt.gather` and `tensorrt.gather_nd` is that\\n    the indices of `tensorrt.gather` specify an scalar offset into a particular\\n    axis while the indices of `tensorrt.gather` specify an N-dimensional index.\\n    `N` is less than or equal to the rank of `data`:\\n\\n    ```\\n    let r = rank(data)\\n    let q = rank(indices)\\n    let index_vector_size = shape(indices)[-1]\\n\\n    let result_shape = concat( shape(indices)[:-1], shape(data)[-index_vector_size:] )\\n    let index_volume = volume(shape(indices)[:-1])\\n\\n    let result = tensor_of(shape=result_shape, element_type=element_type(data))\\n\\n    for i in 0..index_volume:\\n      let index_coord = *delin(i, shape(indices)[:-1])\\n      // Slice 1D 'offsets' from indices.\\n      let offsets = indices[*index_coord]\\n      assert rank(offsets) == 1\\n      // Use `offsets` to select a (r-index_vector_size) slice\\n      // from `data`.\\n      slice_offsets = concat(offsets, [0]*(r-index_vector_size))\\n      slice_sizes = concat([1]*len(offsets), shape(data)[-index_vector_size:])\\n      slice_strides = [1] * r\\n      data_slice = slice(data, slice_offsets, slice_sizes, slice_strides)\\n      result[concat(index_coord, [0] * (r-index_vector_size)] = data_slice\\n    ```\\n\\n    #### Constraints:\\n\\n      - `index_vector_size == shape(indices)[-1] <= rank(data)`\\n      - `rank(result) == q + r - 1 - shape(indices)[-1]`\\n      - `shape(result) == concat(shape(indices)[0:-1], shape(data)[-index_vector_size:])`\\n      - `element_type(result) == element_type(data)`\\n\\n    #### Example:\\n\\n\\n    ```mlir\\n    %0 = tensorrt.gather_nd data(%arg0) indices(%arg1)\\n      : (tensor<1024x32x4xf32>, tensor<16x17x2xi32>) -> tensor<16x17x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `data` `(` $data `)`  `indices` `(` $indices `)`\\n     `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tensorrt.identity\",\n    \"summary\": \"TensorRT identity (IIdentityLayer) operation\",\n    \"description\": \"The `tensorrt.identity` operation performs a cast from the the input tensor\\n    type to the result tensor type, changing only the element type.\\n\\n    This operation corresponds to the TensorRT 8.5 specification.\\n\\n    Valid conversions are as follows:\\n\\n        (f32 | f16 | bf16 | i32 | bool) -> (f32 | f16 | bf16 | i32 | bool)\\n        (f32 | f16) -> (uint8)\\n        (uint8) -> (f32 | f16)\\n\\n    NOTE: When creating this operation, conversions `x -> uint8` and\\n    `uint8 -> x` are allowed even when `x` is not strictly limited to {f32, f16}.\\n    The `ApplyWorkaroundsPass` pass addresses these situations by inserting an\\n    additional `tensorrt.identity` operation for casting through `f32`. This\\n    ensures that the TensorRT graph doesn't break due to a single identity operation\\n    with strictly not supported `uint8` conversion.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[I1, UI8, TensorRT_I8, I32, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[I1, UI8, TensorRT_I8, I32, F16, BF16, F32]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.if\",\n    \"summary\": \"TensorRT if (IIfConditionalLayer) operation\",\n    \"description\": \"The `tensorrt.if` operation represents an \\\"if-then-else\\\" type control flow\\n    operation. The condition determines which of the \\\"true branch\\\" or \\\"false\\n    branch\\\" executes. Only one of the branches execute at runtime (i.e. the\\n    branches are not \\\"eagerly\\\" executed).\\n\\n    The result types yielded from both branches must be equivalent and\\n    equal to the result type of the `tensorrt.if` operation.\\n\\n    This operation obeys the following convention: if an operation is within the\\n    region, then it is lazily executed. By using any SSA value defined above,\\n    that SSA value becomes a \\\"conditional branch input\\\" in the\\n    [terminology of TensorRT API](https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html#work-with-conditionals).\\n\\n    In other words, unlike the TensorRT API, there is not a\\n    \\\"ConditionalInputLayer\\\" abstraction because this is captured implicitly through\\n    the nested structure of the IR. If the intent is to execute an operation\\n    \\\"eagerly\\\" regardless of the conditional value, then it should be\\n    moved out of the conditional body.\\n\\n    #### Example\\n\\n    ```mlir\\n    func.func @trt_if(%arg1: tensor<10xf32>, %arg2: tensor<10xf32>) -> tensor<10xf32> {\\n      %cond = arith.constant dense<1> : tensor<i1>\\n      %result = tensorrt.if (%cond: tensor<i1>) -> tensor<10xf32> {\\n          %add = tensorrt.element_wise <kSUM>(%arg1, %arg2 : tensor<10xf32>, tensor<10xf32>)\\n              -> tensor<10xf32>\\n          tensorrt.yield %arg1: tensor<10xf32>\\n        } else {\\n          %sub = tensorrt.element_wise <kSUB>(%arg1, %arg2 : tensor<10xf32>, tensor<10xf32>)\\n              -> tensor<10xf32>\\n          tensorrt.yield %arg1: tensor<10xf32>\\n        }\\n      return %result: tensor<10xf32>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"0DTensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TensorRT_RankedTensorOf<[ I1, I32, F16, BF16, F32 ]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"trueRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"falseRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $condition `:` type($condition) `)` attr-dict `->` type($results)\\n    $trueRegion\\n    `else`\\n    $falseRegion\"\n  },\n  {\n    \"name\": \"tensorrt.linspace\",\n    \"summary\": \"TensorRT linspace (a variant of FillLayer) operation\",\n    \"description\": \"Generate an output tensor `result` using the \\\"linspace\\\" operation,\\n    described below.\\n\\n    Let the output rank be `n` and let `s` be a tensor that is a\\n    slice of the result along dimension `i`. Then the contents of\\n    `s` are given by:\\n\\n    - If `step` is a tensor:\\n\\n      `s[coord...] = start + dot(step, [coord...])\\n\\n    - If `step` is a static scalar:\\n\\n      `s[j] = start + step * j`\\n\\n    The inputs `start` and `step` must either both be given by\\n    tensor-typed SSA values or both be given by static attributes. One\\n    cannot be static and the other dynamic.\\n\\n    The shape can either be static and given by the shape of the\\n    result type, or it can be given by the `shape` input. If the\\n    result has unknown dimensions, then the `shape` parameter\\n    must be present.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Optional<1DTensorOf<[ I32, I64 ]>>\" },\n      { \"name\": \"start\", \"type\": \"Optional<0DTensorOf<[ I32, I64, F32 ]>>\" },\n      { \"name\": \"step\", \"type\": \"Optional<1DTensorOf<[ I32, I64, F32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_start\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"static_step\", \"type\": \"OptionalAttr<F64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `[`  ($start^ `:` type($start)) : ($static_start)? `]`\\n    `[`  ($shape^ `:` type($shape)) : (`static`)? `]`\\n    `[`  ($step^  `:` type($step)) : ($static_step)? `]`\\n    `:` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.matrix_multiply\",\n    \"summary\": \"TensorRT IMatrixMultiplyLayer operation\",\n    \"description\": \"The `tensorrt.matrix_multiply`layer represents a Matrix Multiplication C = A * B.\\n\\n    When A and B are matrices or vectors, computes the inner product A * B:\\n\\n        matrix * matrix -> matrix\\n        matrix * vector -> vector\\n        vector * matrix -> vector\\n        vector * vector -> scalar\\n\\n    Matrix Operation (tensorrt::MatrixOperation) attribute defines the operations performed in a tensor before multiplication.\\n    - kNONE\\n    Treat x as a matrix if it has two dimensions, or as a collection of matrices if x has more than two dimensions,\\n    where the last two dimensions are the matrix dimensions. x must have at least two dimensions.\\n    - kTRANSPOSE\\n    Like kNONE, but transpose the matrix dimensions.\\n    - kVECTOR\\n    Treat x as a vector if it has one dimension, or as a collection of vectors if x has more than one dimension. x\\n    must have at least one dimension.\\n    The first input tensor with dimensions [M,K] used with MatrixOperation::kVECTOR is equivalent to a tensor\\n    with dimensions [M, 1, K] with MatrixOperation::kNONE.\\n    The second input tensor with dimensions [M,K] used with MatrixOperation::kVECTOR is equivalent to a tensor\\n    with dimensions [M, K, 1] with MatrixOperation::kNONE.\\n\\n    Matrix/Vector dimensions can be thought as combination of collection dimensions and inner product dimensions.\\n    - For Matrices, all but the last two dimensions are collection dimensions.\\n    - For Vectors, all but the last dimension are collection dimensions.\\n    - The number of collection dimensions MUST be equal.\\n    - Broadcast rules* apply to the collection dimensions.\\n\\n    * For each collection dimension, the lengths must match, or one of them must be equal to 1. In the latter case, the tensor\\n    is broadcast along that axis.\\n\\n    The output rank is the number of collection dimensions plus 0..2 dimensions for the inner products. 0 for vector*vector,\\n    1 for vector*matrix or converse and 2 for matrix*matrix.\\n\\n    Inputs MUST have same datatype but can have unequal rank if one of them is kVECTOR.\\n\\n    Example,\\n    ```mlir\\n    func.func @trt_matrix_vector(%arg0: tensor<1x64xf32>, %arg1: tensor<10x64x128xf32>)\\n            -> tensor<10x128xf32> {\\n      %0 = tensorrt.matrix_multiply {\\n        op0 = #tensorrt.matrix_operation<kVECTOR>,\\n        op1 = #tensorrt.matrix_operation<kNONE>\\n      } ins(%arg0, %arg1 : tensor<1x64xf32>, tensor<10x64x128xf32>) -> tensor<10x128xf32>\\n      return %0 : tensor<10x128xf32>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input0\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" },\n      { \"name\": \"input1\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op0\", \"type\": \"TensorRT_MatrixOperationAttr{kNONE|kTRANSPOSE|kVECTOR}\" },\n      { \"name\": \"op1\", \"type\": \"TensorRT_MatrixOperationAttr{kNONE|kTRANSPOSE|kVECTOR}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.module\",\n    \"summary\": \"A top level container for functions describing TensorRT programs\",\n    \"description\": \"A `tensorrt.module` is a container that encapsulates IR defining TensorRT\\n    programs. Each `func.func` in a TensorRT module should compile to a single\\n    TensorRT engine.\\n\\n    The module has a symbol name so that operations outside the module\\n    can refer to the symbols names of nested functions.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict-with-keyword $bodyRegion\"\n  },\n  {\n    \"name\": \"tensorrt.non_zero\",\n    \"summary\": \"TensorRT NonZero (INonZeroLayer) operation\",\n    \"description\": \"`tensorrt.non_zero` layer computes the indices of the input tensor where the value is non zero.\\n    The `result` has shape [input rank, #of non-zero elements] and contains indices of non-zero elements\\n    in row major order.\\n\\n    This operation follows same semantics as that of `onnx.NonZero` and is similar to `tf.Where`.\\n\\n    #### Examples:\\n\\n    ```mlir\\n    %0 = tensorrt.non_zero %input  : tensor<100x200xf32> -> tensor<2x?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[I1, I8, I32, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  $input `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.normalization\",\n    \"summary\": \"TensorRT normalization (INormalizationLayer) operation\",\n    \"description\": \"The `tensorrt.normalization` layer normalizes an input tensor using the\\n    following equation.\\n    ```\\n    result = ((input-E(input, a))/(sqrt(V(input, a))+eps)) * scale + bias\\n    ```\\n    where,\\n    - `input` = input tensor.\\n    - E(input, a) = mean of the input tensor along `a` axis.\\n    - sqrt = square root operation.\\n    - V(input, a) = variance of the input tensor along `a` axis.\\n    - `eps` = a small value added to the denominator for numerical stability.\\n    Default is `1e-5`.\\n    - `scale` = scale tensor.\\n    - `bias` = bias tensor.\\n    - `axis` (a) = axis to perform normalization on.\\n\\n    Value of the attribute `num_groups` (default is 1) decides the type of\\n    normalization. If `num_groups != 1`, the input channels will be split into\\n    `num_groups` before normalization is performed. The channel dimension is\\n    considered to be the second dimension.\\n\\n    In general, the following holds true for different types of normalizations.\\n    1. Batch Normalization\\n        - Input: [N, C, H, W, ..]\\n        - Axis: 0\\n        - Scale and Bias: [1, C, 1, 1, ..., 1]\\n        - Mean and standard-deviation are computed over the batch dimensions.\\n    2. Group Normalization (num_groups = G)\\n        - Input: [N, C, H, W, ...]\\n        - Grouped Input: [N, G, C//G, H, W, ...]\\n        - Axis: [2, 3, 4, ....]\\n        - Scale and Bias: [1, G, 1, 1, ... , 1]\\n        - Input channels are split into `G` groups, each with `C/G` channels. Mean\\n        and standard-deviation are computed for each group separately.\\n        - If G=1, this is equivalent to the Layer Normalization.\\n        - If G=C, this is equivalent to the Instance Normalization.\\n    3. Instance Normalization\\n        - Input: [N, C, H, W, ..]\\n        - Axis: [2, 3, 4, ....]\\n        - Scale and Bias: [1, C, 1, 1, ..., 1]\\n        - Mean and standard-deviation are computed per dimension for each object in\\n        a batch.\\n    4. Layer Normalization\\n        - Input: [D0, D1, D2, D3 .... DN]\\n        - Axis: [2, 3, .. N]\\n        - Scale and Bias: [1, 1, D2, D3, D4 ... DN]\\n        - Mean and standard-deviation are computed over the last D dimensions.\\n        - In general, if axis selected forms `normalized` shape ([Di, Di+1, ...],\\n        starting at index `i`), scale and bias has [1, 1, .. 1i, normalized] shape.\\n        Scale/bias shape has dim 1 up-to `i`th dim from which normalization axis\\n        starts.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" },\n      { \"name\": \"scale\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" },\n      { \"name\": \"bias\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlySorted<DenseI64ArrayAttr>, DenseArrayNonNegative<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"eps\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"num_groups\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `(`$input `:` type($input) `,` $scale `:` type($scale) `,` $bias `:` type($bias)`)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.one_hot\",\n    \"summary\": \"TensorRT IOneHotLayer operation\",\n    \"description\": \"The `tensorrt.one_hot` operation requires 'indices', 'values', 'depth', and 'axis' as as inputs.\\n    The locations represented by the index values in 'indices' will have 'on_value' in the output tensor and\\n    the other locations will have 'off_value'.\\n    Here, 'on_value' and 'off_value' are specified by 'values' of format ['off_value', 'on_value'].\\n    The rank of the output tensor will be one greater than the rank of the input tensor.\\n    The additional dimension in the output tensor is of size 'depth'.\\n    As mentioned before, only one of 'depth' elements in the dimension is 'on_value' and the others are 'off_value'.\\n    The additional dimension will be inserted at the position specified by 'axis'.\\n\\n    Example 1:\\n    When indices = [0, 2, 4], values = [0, 1], depth = 5, and axis = -1 (the innermost dimension)\\n    the output is\\n      [[1  0  0  0  0]\\n       [0  0  1  0  0]\\n       [0  0  0  0  1]].\\n\\n    Example 2:\\n    When indices = [[0, 1], [2, 3], [4, 1]], values = [0, 2], depth = 5, and axis = -1 (the innermost dimension)\\n    the output is\\n      [[[2  0  0  0  0], [0  2  0  0  0]],\\n       [[0  0  2  0  0], [0  0  0  2  0]],\\n       [[0  0  0  0  2], [0  2  0  0  0]]].\\n\\n    Example 3:\\n    When indices = [0, 2, 4], values = [0, 2], depth = 5, and axis = 0\\n    the output is\\n      [[2  0  0]\\n       [0  0  0]\\n       [0  2  0]\\n       [0  0  0]\\n       [0  0  2]].\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" },\n      { \"name\": \"values\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" },\n      { \"name\": \"depth\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.opaque_plugin\",\n    \"summary\": \"a representation of an opaque external TensorRT plugin\",\n    \"description\": \"The `tensorrt.opaque_plugin` operation represents an external TensorRT\\n    plugin that is provided as a dynamic shared object library (DSO).\\n\\n    This operation supports the PluginV3/PluginCreatorV3One API introduced\\n    in TensorRT 10. Older TensorRT plugin APIs are not supported.\\n\\n    The attributes of the plugin specify the path to the DSO as well as the\\n    information needed to construct a plugin instance using the plugin's\\n    PluginCreator implementation. The `creator_params` are serialized into\\n    a PluginFieldCollection in order to\\n\\n    The steps for loading and creating the plugin are executed as follows.\\n    First, a reference to the PluginCreatorV3One for the TensorRT plugin\\n    must be acquired. There are three possible mechanisms for doing this:\\n\\n    1. If both the `dso_path` and the `creator_func` attributes are provided,\\n    then the DSO is loaded (e.g. on POSIX using `dlopen`) and the symbol name\\n    specified by the attribute `creator_func` is searched\\n    for in the loaded library. This must be a function that accepts no\\n    parameters and returns an `nvinfer1::IPluginCreatorV3One*`. In the\\n    event of an error in the function, it is allowed to return `nullptr`.\\n    The compiler takes ownership over the creator and caches it for all\\n    translations of this operation that have the same `plugin_name`, so\\n    the creator class should be stateless.\\n\\n    2. If the `dso_path` is specified, but no `creator_func` is provided,\\n    then the DSO is loaded and it is expected that loading the DSO\\n    triggers registration of the creator with TensorRT's global plugin creator\\n    registry. The plugin creator is then looked up in that registry.\\n\\n    3. Otherwise, if no `dso_path` is given, then it is expected that\\n    that the plugin creator is already registered in the glboal plugin\\n    registry, and we lookup the plugin by name/version/namespace in the\\n    global registry.\\n\\n    After acquiring a reference to the creator, we create the plugin with\\n    the following steps:\\n\\n    1. The plugin creator is instantiated by calling the function with name\\n       specified by `creator_func` and is cache. Subsequent\\n       translations of an operation with the same `plugin_name` will not\\n       create a new PluginCreator.\\n\\n    2. The translator queries the instantiated PluginCreator for the relevant\\n       fields by calling the `PluginCreatorV3One::getFieldNames()` member\\n       function. The plugin must provide an implementation for `getFieldNames`.\\n       All attributes in `creator_params` are validated against the plugin\\n       specifications returned by `getFieldNames()`.\\n\\n    3. The `creator_params` are serialized into a `PluginFieldCollection`\\n       and passed to the creator's `getPlugin` call.\\n\\n\\n    #### Dynamic Shapes and Shape Calculation Region\\n\\n    The plugin has a single region, `shapes_region`, which is allowed to be\\n    empty.\\n\\n    When populated, the `shapes_region` should contain a single block of\\n    scalar arithmetic IR for calculating result shapes. The block arguments should\\n    contain one scalar argument for each input dimension for each tensor operand.\\n    The single block should be terminated by `tensorrt.yield` and yield a scalar\\n    for each dimension for each result tensor.\\n\\n    The `shapes_region` is made optional even when the results have dynamic\\n    extents in order to enable lazy population of the content by directly\\n    querying the actual TensorRT plugin.  The `tensorrt-infer-plugin-shapes`\\n    will load the plugin and use a simple mechanism to construct the right IR\\n    in the shapes region.\\n\\n    #### TODO:\\n\\n    The following items are currently unimplemnted:\\n\\n    1. Any sort of verification by loading the plugin before translation\\n       time.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorRT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TensorRT_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"plugin_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"plugin_version\", \"type\": \"StrAttr\" },\n      { \"name\": \"plugin_namespace\", \"type\": \"StrAttr\" },\n      { \"name\": \"dso_path\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"creator_func\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"creator_params\", \"type\": \"DictionaryAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"shapes_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  `(` ($inputs^)? `)` `:` functional-type($inputs, $results)\\n    ( $shapes_region^ )?\"\n  },\n  {\n    \"name\": \"tensorrt.padding\",\n    \"summary\": \"TensorRT padding(IPaddingLayer) operation\",\n    \"description\": \"The `tensorrt.padding` operation adds zero-padding at the start and end of\\n    the input tensor and store the result in an output tensor.\\n\\n    When `prePadding` and `postPadding` are positive, the tensor is pad with\\n    zeros, otherwise it is trimmed. The amount of padding/trimming to use at\\n    the start and end of each dimension is defined by `prePadding` and\\n    `postPadding` respectively. It only supports padding/trimming along exactly\\n    two innermost dimensions.\\n\\n    Each output dimension `O_{i}` is calculated based on input dimension `I_{i}`\\n    prePadding and postPadding as follows,\\n    n = rank(input)\\n    O_{i} = I_{i}                                  for 0 <= i < (n - 2)\\n    O_{i} = I_{i} + prePadding[j] + postPadding[j] for (n - 2) <= i < n and j = i - ( n- 2)\\n\\n    #### Examples:\\n\\n    ```mlir\\n\\n    %0 = tensorrt.padding {\\n      prePadding = array<i64: 3, -2>,\\n      postPadding = array<i64: 2, -4>\\n    } %input  : tensor<1x1x10x10xf32> -> tensor<1x1x15x4xf32>\\n\\n    ```\\n\\n    #### Caveat\\n    Padding exactly two innermost dimensions is supported.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, F16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, F16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prePadding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"postPadding\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.parametric_relu\",\n    \"summary\": \"TensorRT ParametricReLU(IParametricReLULayer) operation\",\n    \"description\": \"The `tensorrt.parametricrelu` applies the function `f` to each element `x` at indices`i=(i_0, ... i_n)` of the input tensor,\\n    where `f` is given as 'f(x) := x if x > 0, otherwise `slope[i_0,...,i_n]` * x`\\n\\n    #### Example\\n\\n    ```mlir\\n\\n    %result = tensorrt.parametric_relu ins(%input, %slope : tensor<2x20xf32>, tensor<2x20xf32>)\\n        -> tensor<2x20xf32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, BF16, F32]>\" },\n      { \"name\": \"slope\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, BF16, F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.pooling\",\n    \"summary\": \"TensorRT pooling (IPoolingLayer) operation\",\n    \"description\": \"The `tensorrt.pooling` operation applies a windowed reduction over the\\n    input. By convention, the input tensor type's shape dimensions are\\n    assumed to be in the form `[batch_dim, channel_dim, spatial_dims...]`.\\n\\n    The mathematical operation for the windowed reduction is given by the\\n    `poolingType` attribute. See the `PoolingType` enum definition for an\\n    enumeration of the various supported operations.\\n\\n    The reduction window size is given by `windowSize` and should be of\\n    size 2 or size 3.\\n\\n    TODO: Currently only explicit pre/post padding is supported, but the\\n    underlying TensorRT layer also supports automatic padding styles\\n\\n    The `blendFactor` attribute is only relevant when `poolingType` is\\n    set to `kMAX_AVERAGE_BLEND`.\\n\\n    The `averageCountExcludesPassing` is only relevant when `poolingType`\\n    is set to `kMAX_AVERAGE_BLEND` or `kAVERAGE`. When set, elements of\\n    the input that correspond to elements added during padding are not\\n    counted toward the total when performing an average calculation for\\n    a given window position.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32, BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32, BF16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"windowSize\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"prePadding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"postPadding\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"poolingType\", \"type\": \"TensorRT_PoolingTypeAttr{kMAX|kAVERAGE|kMAX_AVERAGE_BLEND}\" },\n      { \"name\": \"blendFactor\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"averageCountExcludesPadding\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` $input `:` type($input) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.quantize\",\n    \"summary\": \"TensorRT Quantize(IQuantizeLayer) operation\",\n    \"description\": \"The `tensorrt.quantize` operation quantize a floating-point input tensor into\\n    an 8-bit signed integer output tensor using the `scale` input.\\n\\n    NOTE: Although `zero_point` is an optional input for TensorRT Quantize(IQuantizeLayer)\\n    operation, it is removed here because it's just a placeholder which is not\\n    actually used and cannot be set to other values other than 0 in TensorRT.\\n    `zero_point` is omitted for the following decryption.\\n\\n    Quantization can either be applied uniformly for the entire input (\\\"per-tensor\\\" manner)\\n    using a single scalar \\\"scale\\\" value, or it can be applied in a \\\"per-channel\\\" manner,\\n    meaning that different slices of the input tensor along a specified `axis` are\\n    quantized using different parameters in a 1D \\\"scale\\\" tensor, or it can be applied\\n    in a \\\"2D block\\\" manner using a 2D \\\"scale\\\" tensor (supports only `INT4` 2D weight inputs).\\n\\n    #### Caveats\\n\\n    - `scale` must be compile time constants (after constant folding by either\\n        MLIR-TRT or TRT itself).\\n\\n    #### Argument Constraints\\n\\n    If `axis` is not given:\\n\\n    - `scale` must be 2D for INT4 block quantization. Block quantization always happens\\n    along `axis` 0.\\n    - `scale` must be a scalar (0D tensor i.e. `tensor<[element type]>`) for per-tensor\\n    quantization.\\n\\n    If `axis` is given:\\n\\n    - `scale` must be 1D tensors with `input.shape[axis]`\\n        number of elements, for per-channel quantization.\\n    - Similarly, the size of input dimension `input.shape[axis]` must be\\n      a compile time constant (i.e. it cannot be `?`).\\n    - `axis` must be in the range of `[0, R)`.\\n\\n    #### Quantization Computation\\n\\n    Let `(i_0, ..., i_{R-1})` represent indices in the index space of the\\n    `input` tensor, which is of rank `R`.\\n\\n    In the below, the `round` function rounds f32 values to i8 values with the\\n    semantic of\\n    [\\\"round-to-nearest-with-ties-to-even\\\"](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even).\\n\\n    Per-tensor quantization transforms the input\\n    uniformly as follows:\\n\\n    ```\\n    output[ i_0, ..., i_{R-1} ] :=\\n      clamp(\\n        round(\\n          input[ i_0, ..., i_{R-1} ] / (f32)scale\\n        ),\\n        min = (i8) -128,\\n        max = (i8) 127\\n      )\\n    ```\\n\\n    Per-channel quantization is supported only for weight inputs. Activations\\n    can't be quantized per-channel. Given a 1D tensor of `scale` values and\\n    `axis`, the input is transformed as follows:\\n\\n    ```\\n    output[i_0, ..., i_{axis}, ..., i_{R-1} ] :=\\n      clamp(\\n        round(\\n          input[ i_0, ..., i_{axis}, ..., i_{R-1} ] /\\n          scale[ i_{axis} ]\\n        ),\\n        min = (i8) -128,\\n        max = (i8) 127\\n      )\\n    ```\\n\\n    Block quantization is supported only for 2-D weight inputs of type\\n    `INT4`. Axis for block quantization is always 0. Let `B` be the block size.\\n    Block quantization transforms the input as follows:\\n\\n    ```\\n    output[i_0, i_1] :=\\n      clamp(\\n        round(\\n          input[ i_0, i_1 ] / scale[ i_0 // B, i_1 ]\\n        ),\\n        min = (i4) -8,\\n        max = (i4) 7\\n      )\\n    ```\\n\\n    The output shape is the same as the input shape. The quantization axis is\\n    in reference to the input tensor's dimensions.\\n\\n    Valid conversions are as follows:\\n\\n    ```\\n    (f32 | f16 | bf16) -> (int8 | f8E4M3FN | int4)\\n    ```\\n\\n    #### Examples\\n\\n    ```mlir\\n    %1 = tensorrt.quantize in(%arg0 : tensor<10x10xf32>)\\n          scale(%arg1 :  tensor<1xf32>) -> tensor<10x10xi8>\\n    %2 = tensorrt.quantize { axis = 1 : i32 } in(%arg0 : tensor<10x10xf32>)\\n          scale(%arg1 : tensor<10xf32>) -> tensor<10x10xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Non0RankedTensorOf<[F32, F16, BF16]>\" },\n      { \"name\": \"scale\", \"type\": \"TensorRT_RankedTensorOf<[F32, F16, BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, TensorRT_F8, TensorRT_I4]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `in` `(` $input `:` type($input) `)`\\n    `scale` `(` $scale `:` type($scale) `)`\\n    `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.ragged_softmax\",\n    \"summary\": \"TensorRT IRaggedSoftMaxLayer operation\",\n    \"description\": \"The `tensorrt.ragged_softmax` operation requires `input` and `bounds` as input tensors\\n    and produces `output` as the output tensor. The `input` is of ZxS and\\n    the `bounds` is Zx1, which specifies the length of each of the Z sequences.\\n    The shape of `output` is the same as `input`.\\n    This layer computes a softmax across each of the Z sequences for the specified length.\\n    Values outside of the specified lengths are set to zero.\\n\\n    As of TRT 8.6.10.0, `input` and `bounds` must be a 3D tensor in the explicit batch mode,\\n    or a 2D tensor in the implicit batch mode, which is deprecated but exists for backward compatibility.\\n\\n    Example:\\n    When `input` is of 1x3x5\\n     [[[1.0, 1.0,  1.0,  1.0, 1.0],\\n       [1.0, 1.0,  1.0,  1.0, 0.5],\\n       [3.0, 4.0, -2.0, 10.0, 5.0]]]\\n    and `bounds` is of 1x3x1\\n     [[[5], [4], [3]]],\\n\\n    the `output` is of 1x3x5\\n     [[[0.2000, 0.2000, 0.2000, 0.2000, 0.2000],\\n       [0.2500, 0.2500, 0.2500, 0.2500, 0.0000],\\n       [0.2685, 0.7297, 0.0018, 0.0000, 0.0000]]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" },\n      { \"name\": \"bounds\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.random_normal\",\n    \"summary\": \"TensorRT random normal (a variant of FillLayer) operation\",\n    \"description\": \"Generates an output tensor with samples drawn from a normal (Gaussian)\\n    distribution. The mean of the normal distribution is give by `mean`\\n    and the standard deviation is given by `std` inputs.\\n\\n    Both of these inputs are either tensor-typed SSA values or static\\n    attributes.If nothing is provided, default value of `mean` is 0 and\\n    `std` is 1 i.e. samples are drawn from the standard normal distribution,\\n    by default.\\n\\n    The shape can either be static and given by the shape of the\\n    result type, or it can be given by the `shape` input. If the\\n    result has unknown dimensions, then the `shape` parameter\\n    must be present.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Optional<1DTensorOf<[ I32 ]>>\" },\n      { \"name\": \"mean\", \"type\": \"Optional<0DTensorOf<[ F32, F16 ]>>\" },\n      { \"name\": \"std\", \"type\": \"Optional<0DTensorOf<[ F32, F16 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F32, F16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_mean\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"static_std\", \"type\": \"OptionalAttr<F64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n      (`mean` `(` $mean^ `:` type($mean) `)` )?\\n      (`std` `(` $std^   `:` type($std)  `)` )?\\n      (`shape` `(` $shape^ `:` type($shape) `)` )?\\n      `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.random_uniform\",\n    \"summary\": \"TensorRT random uniform (a variant of FillLayer) operation\",\n    \"description\": \"Generates an output tensor with samples drawn from a uniform distribution.\\n    Range ([low, high)) of the distribution is give by `low` and `high` inputs.\\n    Both of these inputs are either tensor-typed SSA values or static attributes.\\n    If nothing is provided, default value of `low` is 0 and `high` is 1.\\n\\n    The shape can either be static and given by the shape of the\\n    result type, or it can be given by the `shape` input. If the\\n    result has unknown dimensions, then the `shape` parameter\\n    must be present.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"Optional<1DTensorOf<[ I32 ]>>\" },\n      { \"name\": \"low\", \"type\": \"Optional<0DTensorOf<[ F32, F16 ]>>\" },\n      { \"name\": \"high\", \"type\": \"Optional<0DTensorOf<[ F32, F16 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F32, F16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_low\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"static_high\", \"type\": \"OptionalAttr<F64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n      (`low` `(` $low^ `:` type($low) `)` )?\\n      (`high` `(` $high^   `:` type($high)  `)` )?\\n      (`shape` `(` $shape^ `:` type($shape) `)` )?\\n      `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.reduce\",\n    \"summary\": \"TensorRT reduction operation\",\n    \"description\": \"The `tensorrt.reduce` operation models the TensorRT IReduceLayer semantics.\\n\\n    The operation reduces one or more axes of the `input` tensor as described\\n    by the attribute `reduceAxes`, which is an array of dimension indices.\\n    NOTE: This differs from the underlying TensorRT API, which requires the\\n    reduction axes to be specified as a bitmask. The conversion to a bitmask\\n    occurs automatically during translation to the C++ or TensorRT target.\\n\\n    The `keepDimensions` attribute specifies whether the result should be\\n    rank-reduced (`keepDimensions = false`) or the same rank as the input\\n    (`keepDimensions = true`). When not rank-reduced, the result shape\\n    dimensions that were reduced by the operation are equal to `1`.\\n\\n    The `reduceOperation` attribute specifies what reduction operation is\\n    performed (see the `ReduceOperation` enum definition).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduceAxes\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlySorted<DenseI64ArrayAttr>, DenseArrayNonNegative<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"keepDimensions\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"reduceOperation\", \"type\": \"TensorRT_ReduceOperationAttr{kSUM|kPROD|kMAX|kMIN|kAVG}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$reduceOperation $input attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.reshape\",\n    \"summary\": \"A reshape operation\",\n    \"description\": \"The `tensorrt.reshape` operation performs a reshape operation. The reshape\\n    can be dynamic in the sense that the sizes of the dimensions are unknown,\\n    but all ranks must be known. Reshapes that only add/remove unit dimensions\\n    will be canonicalized to `tensorrt.expand_rank` and `tensorrt.collapse_rank`\\n    respectively.\\n\\n    If the dynamic `shape` operand is not provided, then the result type is\\n    allowed to have at most one dynamic dimensin. Otherwise, the `shape`\\n    operand must be provided.\\n\\n    #### Examples\\n\\n    A static reshape:\\n\\n    ```\\n    %reshaped = tensorrt.reshape %input : tensor<10xf32> to tensor<2x5xf32>\\n    ```\\n\\n    A dynamic reshape:\\n\\n    ```\\n    %reshaped = tensorrt.reshape %input shape(%shape: tensor<2xi32>)\\n        : tensor<?xf32> to tensor<?x?xf32>\\n    ```\\n\\n    A dynamic reshape with only one unknown dimension:\\n\\n    ```\\n    %reshaped = tensorrt.reshape %input\\n        : tensor<?xf32> to tensor<2x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_AllTypesTensor\" },\n      { \"name\": \"shape\", \"type\": \"Optional<1DTensorOf<[ I32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"assemblyFormat\": \"$input (`shape` `(` $shape^ `` `:` type($shape) `)`)? attr-dict\\n      `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.resize_cubic\",\n    \"summary\": \"TensorRT Resize(IResizeLayer with CUBIC mode) operation\",\n    \"description\": \"The `tensorrt.resize_cubic` operation resize an input tensor into an output\\n    tensor with the LINEAR mode. The operation resizes innermost `m` dimensions\\n    of an input tensor of rank N, when 0 <= m <= min(3, N).\\n\\n    For IResizeLayer there are 2 parameters `shape` and `scales` which are used to\\n    determine output shape. If the input has static input/output shapes, then these\\n    2 parameters don't need to be kept as attributes since `tensorrt.resize_cubic`\\n    can directly retrieve the output shape from its output type information to\\n    initialize `shape` parameter. If the input has dynamic shapes, then `scales`\\n    parameter is used as an attribute to determine the output shapes.\\n\\n    `tensorrt.resize_cubic` uses `coordinate_transformation` to control how the\\n    coordinates in the output tensor are mapped to coordinates in the input tensor.\\n    Specifically, for each spatial dimension i, input[..., f(y_i), ...] = result[..., y_i, ...]\\n    where f is given by one of the following equations, depending on the value of\\n    the `coordinate_transformation` attribute:\\n\\n        -   ResizeCoordinateTransformation::kALIGN_CORNERS, in this mode:\\n            f(y_i) = y_i * (shape(input)[i] - 1) / (shape(result)[i] - 1)\\n        -   ResizeCoordinateTransformation::kASYMMETRIC, in this mode:\\n            f(y_i) = y_i * shape(input)[i] / shape(result)[i]\\n        -   ResizeCoordinateTransformation::kHALF_PIXEL, in this mode:\\n            f(y_i) = (y_i + 0.5) * shape(input)[i] / shape(result)[i] - 0.5\\n\\n    There is another parameter `selector_for_single_pixel` for IResizeLayer which\\n     controls selector when resize to single pixel output, it supports 2 modes:\\n\\n        -   FORMULA, use formula to map the original index\\n        -   UPPER, use the upper left pixel\\n\\n    `tensorrt.resize_cubic` uses `cubic_coeff` as coefficient in cubic interpolation.\\n    Two common choice are -0.5 (in some cases of TensorFlow) and -0.75 (in PyTorch).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" },\n      { \"name\": \"output_shape\", \"type\": \"Optional<TensorRT_ShapeTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scales\", \"type\": \"OptionalAttr<DenseF32ArrayAttr>\" },\n      { \"name\": \"coordinateTransformation\", \"type\": \"TensorRT_ResizeCoordinateTransformationAttr{kALIGN_CORNERS|kASYMMETRIC|kHALF_PIXEL}\" },\n      { \"name\": \"selectorForSinglePixel\", \"type\": \"TensorRT_ResizeSelectorAttr{kFORMULA|kUPPER}\" },\n      { \"name\": \"cubicCoeff\", \"type\": \"F32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input ( `,` $output_shape^ )? `:` functional-type(operands,results)\"\n  },\n  {\n    \"name\": \"tensorrt.resize_linear\",\n    \"summary\": \"TensorRT Resize(IResizeLayer with LINEAR mode) operation\",\n    \"description\": \"The `tensorrt.resize_linear` operation resize an input tensor into an output\\n    tensor with the LINEAR mode. The operation resizes innermost `m` dimensions\\n    of an input tensor of rank N, when 0 <= m <= min(3, N).\\n\\n    For IResizeLayer there are 2 parameters `shape` and `scales` which are used to\\n    determine output shape. If the input has static input/output shapes, then these\\n    2 parameters don't need to be kept as attributes since `tensorrt.resize_linear`\\n    can directly retrieve the output shape from its output type information to\\n    initialize `shape` parameter. If the input has dynamic shapes, then `scales`\\n    parameter is used as an attribute to determine the output shapes.\\n\\n    `tensorrt.resize_linear` uses `coordinate_transformation` to control how the\\n    coordinates in the output tensor are mapped to coordinates in the input tensor.\\n    Specifically, for each spatial dimension i, input[..., f(y_i), ...] = result[..., y_i, ...]\\n    where f is given by one of the following equations, depending on the value of\\n    the `coordinate_transformation` attribute:\\n\\n        -   ResizeCoordinateTransformation::kALIGN_CORNERS, in this mode:\\n            f(y_i) = y_i * (shape(input)[i] - 1) / (shape(result)[i] - 1)\\n        -   ResizeCoordinateTransformation::kASYMMETRIC, in this mode:\\n            f(y_i) = y_i * shape(input)[i] / shape(result)[i]\\n        -   ResizeCoordinateTransformation::kHALF_PIXEL, in this mode:\\n            f(y_i) = (y_i + 0.5) * shape(input)[i] / shape(result)[i] - 0.5\\n\\n    There is another parameter `selector_for_single_pixel` for IResizeLayer which\\n     controls selector when resize to single pixel output, it supports 2 modes:\\n\\n        -   FORMULA, use formula to map the original index\\n        -   UPPER, use the upper left pixel\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" },\n      { \"name\": \"output_shape\", \"type\": \"Optional<TensorRT_ShapeTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scales\", \"type\": \"OptionalAttr<DenseF32ArrayAttr>\" },\n      { \"name\": \"coordinateTransformation\", \"type\": \"TensorRT_ResizeCoordinateTransformationAttr{kALIGN_CORNERS|kASYMMETRIC|kHALF_PIXEL}\" },\n      { \"name\": \"selectorForSinglePixel\", \"type\": \"TensorRT_ResizeSelectorAttr{kFORMULA|kUPPER}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input ( `,` $output_shape^ )? `:` functional-type(operands,results)\"\n  },\n  {\n    \"name\": \"tensorrt.resize_nearest\",\n    \"summary\": \"TensorRT Resize(IResizeLayer with NEAREST mode) operation\",\n    \"description\": \"The `tensorrt.resize_nearest` operation resize an input tensor into an output\\n    tensor with the NEAREST mode. The operation resizes innermost `m` dimensions\\n    of an input tensor of rank N, when 0 <= m <= min(3, N).\\n\\n    For IResizeLayer there are 2 parameters `shape` and `scales` which are used to\\n    determine output shape. If the input has static input/output shapes, then these\\n    2 parameters don't need to be kept as attributes since `tensorrt.resize_nearest`\\n    can directly retrieve the output shape from its output type information to\\n    initialize `shape` parameter. If the input has dynamic shapes, then `scales`\\n    parameter is used as an attribute to determine the output shapes.\\n\\n    `tensorrt.resize_nearest` uses `coordinate_transformation` to control how the\\n    coordinates in the output tensor are mapped to coordinates in the input tensor.\\n    Specifically, for each spatial dimension i, input[..., f(y_i), ...] = result[..., y_i, ...]\\n    where f is given by one of the following equations, depending on the value of\\n    the `coordinate_transformation` attribute:\\n\\n        -   ResizeCoordinateTransformation::kALIGN_CORNERS, in this mode:\\n            f(y_i) = y_i * (shape(input)[i] - 1) / (shape(result)[i] - 1)\\n        -   ResizeCoordinateTransformation::kASYMMETRIC, in this mode:\\n            f(y_i) = y_i * shape(input)[i] / shape(result)[i]\\n        -   ResizeCoordinateTransformation::kHALF_PIXEL, in this mode:\\n            f(y_i) = (y_i + 0.5) * shape(input)[i] / shape(result)[i] - 0.5\\n\\n    `tensorrt.resize_nearest` uses `nearest_rounding` to control the rounding mode for\\n    nearest neighbor resize, it indicates how to get \\\"nearest\\\" pixel from the calculated\\n    input coordinate f(y_i) above, it supports following modes:\\n\\n        -   ResizeRoundMode::kHALF_UP, round half up\\n        -   ResizeRoundMode::kHALF_DOWN, round half down\\n        -   ResizeRoundMode::kFLOOR, round to floor\\n        -   ResizeRoundMode::kCEIL, round to ceil\\n\\n    There is another parameter `selector_for_single_pixel` for IResizeLayer which\\n    controls selector when resize to single pixel output, it supports 2 modes:\\n\\n        -   FORMULA, use formula to map the original index, f(y_i) above\\n        -   UPPER, use the upper left pixel\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" },\n      { \"name\": \"output_shape\", \"type\": \"Optional<TensorRT_ShapeTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, F16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scales\", \"type\": \"OptionalAttr<DenseF32ArrayAttr>\" },\n      { \"name\": \"coordinateTransformation\", \"type\": \"TensorRT_ResizeCoordinateTransformationAttr{kALIGN_CORNERS|kASYMMETRIC|kHALF_PIXEL}\" },\n      { \"name\": \"nearestRounding\", \"type\": \"TensorRT_ResizeRoundModeAttr{kHALF_UP|kHALF_DOWN|kFLOOR|kCEIL}\" },\n      { \"name\": \"selectorForSinglePixel\", \"type\": \"TensorRT_ResizeSelectorAttr{kFORMULA|kUPPER}\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input ( `,` $output_shape^ )? `:` functional-type(operands,results)\"\n  },\n  {\n    \"name\": \"tensorrt.scatter_elements\",\n    \"summary\": \"TensorRT scatter (IScatterLayer with kELEMENT mode) operation\",\n    \"description\": \"The `tensorrt.scatter_elements` operation creates an output tensor by\\n    copying values from an input tensor `data` and then updating values at\\n    indices given by the `indices` tensor with values from the `updates` tensor.\\n    Its output shape is the same as the shape of `data`.\\n\\n    This operation takes three inputs:\\n\\n    - A `data` tensor of rank r >= 1, that stores the values to be duplicated in\\n    the output. - An `indices` tensor of the same rank as `data` that determines\\n    which locations in the output to write new data to. The indices are\\n    interpreted as a tensor of rank 1 of indexing tuples. - An `updates` tensor\\n    of the same rank as `data`, that provides the data to write to output, at\\n    the index specified by the corresponding location in the `indices` tensor. -\\n    An optional `axis` attribute that identifies an axis of `data` along which\\n    to scatter on. By default, this is the outermost axis, which is 0.\\n\\n    This operation produces one output: - An `output` tensor of the same\\n    dimensions as `data` that stores the resulting values of the transformation.\\n\\n    This op follows the semantics of\\n    [tf.scatter_nd](https://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_add)\\n    and\\n    [onnx.ScatterElements](https://github.com/onnx/onnx/blob/main/docs/Operators.md#ScatterND)\\n    and\\n    [torch.index_select](https://pytorch.org/docs/stable/generated/torch.scatter.html)\\n\\n    #### Output Computation:\\n\\n    For each entry in `updates`, the target index in `data` is obtained by\\n    combining the corresponding entry in `indices` with the index of the entry\\n    itself: the index-value for dimension = axis is obtained from the value of\\n    the corresponding entry in `indices` and the index-value for dimension !=\\n    axis is obtained from the index of the entry itself.\\n\\n    For each element X of indices:\\n      Let J denote a sequence for the subscripts of X\\n      Let K = sequence J with element[axis] replaced by X\\n      Then,\\n        output[K] = updates[J]\\n\\n    For example, if indices has dimensions [N,C,H,W] and axis is 2, then the\\n    updates happen as:\\n\\n    for n in [0, N)\\n        for c in [0, C)\\n            for h in [0, H)\\n                for w in [0, W)\\n                    output[n,c,indices[n,c,h,w],w] = updates[n,c,h,w]\\n\\n\\n    #### Caveats\\n\\n    Writes to the same output element cause undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64]>\" },\n      { \"name\": \"updates\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `data` `(` $data `:` type($data) `)`\\n    `indices` `(` $indices `:` type($indices) `)`\\n    `updates` `(` $updates `:` type($updates) `)`\"\n  },\n  {\n    \"name\": \"tensorrt.scatter_nd\",\n    \"summary\": \"TensorRT scatter (IScatterLayer with kND mode) operation\",\n    \"description\": \"The `tensorrt.scatter_nd` operation creates an output tensor by copying values\\n    from an input tensor `data` and then updating values by the given `indices`\\n    and `updates` tensors.\\n\\n    This operation takes three inputs:\\n\\n    - A `data` tensor of rank r >= 1, that stores the values to be duplicated in\\n    the output.\\n    - An `indices` tensor of rank q >= 1 that determines which locations in the\\n    output to write new data to. The indices are interpreted as a tensor of\\n    rank q-1 of indexing tuples.\\n    - An `updates` tensor of rank s, that provides the data to write to output,\\n    at the index specified by the corresponding location in the `indices`\\n    tensor. For this operation, rank s = (q - 1) + (r - indices.shape[-1]).\\n\\n    This operation produces one output:\\n    - An `output` tensor of the same dimensions as data that stores the\\n    resulting values of the transformation.\\n\\n    The output of the operation is obtained by updating the data tensor's value\\n    to values specified by updates at specific index positions specified by\\n    indices. Its shape is the same as the shape of data.\\n\\n    The types of data, update, and output shall be the same.\\n\\n    This op follows the semantics of\\n    [tf.scatter_nd](https://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_add)\\n    and\\n    [onnx.ScatterND](https://github.com/onnx/onnx/blob/main/docs/Operators.md#ScatterND)\\n    and\\n    [torch.index_select](https://pytorch.org/docs/stable/generated/torch.scatter.html)\\n\\n    #### Output Computation:\\n\\n    Assuming that data dims are {d_0,...,d_{r-1}} and indices dims are\\n    {i_0,...,i_{q-1}}, define k = indices.shape[q-1], the updates dims must be\\n    {i_0,...,i_{q-2},d_k,...,d_{r-1}}.\\n\\n    The updating can be computed by:\\n        foreach slice in indices[i_0,...i_{q-2} ]\\n            output[indices[slice]] = updates[slice]\\n\\n    #### Caveats\\n    Writes to the same output element cause undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64]>\" },\n      { \"name\": \"updates\", \"type\": \"TensorRT_RankedTensorOf<[TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `data` `(` $data `:` type($data) `)`\\n    `indices` `(` $indices `:` type($indices) `)`\\n    `updates` `(` $updates `:` type($updates) `)`\"\n  },\n  {\n    \"name\": \"tensorrt.select\",\n    \"summary\": \"TensorRT ISelectLayer operation\",\n    \"description\": \"The `tensorrt.select` operation accepts a boolean\\n    tensor and produces an output that is elementwise equal to\\n    `thenInput` where `condition` is true and otherwise equal to\\n    `elseInput`.\\n\\n    The input shapes may be broadcasted according to TensorRT's\\n    broadcasting semantics. The element types of `thenInput` and\\n    `elseInput` must be equal and also equal to the element type of\\n    the result.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TensorRT_RankedTensorOf<[I1]>\" },\n      { \"name\": \"thenInput\", \"type\": \"TensorRT_RankedTensorOf<[I1, TensorRT_I8, I32, I64, F16, BF16, F32]>\" },\n      { \"name\": \"elseInput\", \"type\": \"TensorRT_RankedTensorOf<[I1, TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[I1, TensorRT_I8, I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.shape\",\n    \"summary\": \"TensorRT shape operation\",\n    \"description\": \"The `tensorrt.shape` operation returns the shape of a given `input` tensor\\n    as a `i32` tensor.\\n\\n    The `result` tensor is a rank-1 i32 tensor. The shape of the result tensor\\n    is `tensor<[inputRank]xi32>`. Note that for scalar tensors (e.g. of type\\n    `tensor<f32>`), the result type is `tensor<0xi32>`.\\n\\n    #### Example\\n\\n    ```mlir\\n\\n    %1 = tensorrt.shape %arg0 : tensor<10x?x?xf32> -> tensor<3xi32>\\n    %2 = tensorrt.shape %arg1 : tensor<f32> -> tensor<0xi32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[I1, TensorRT_I4, TensorRT_I8, I32, I64, TensorRT_F8, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"1DTensorOf<[I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.shuffle\",\n    \"summary\": \"TensorRT IShuffleLayer operation\",\n    \"description\": \"The `tensorrt.shuffle` layer applies the following operations in sequence:\\n\\n      1. Transpose the input (`first_transpose`)\\n      2. Reshape the result of (1) - the specified shape may be either\\n         static (`reshape`) or dynamic (`dynamic_reshape`).\\n      3. Transpose the result of (2).\\n\\n    This operation tries to follow exactly the semantics of the underlying\\n    TensorRT \\\"IShuffleLayer\\\" operation. When applying a pure reshape or\\n    transpose, it is recommended to use one of the extension operations\\n    \\\"tensorrt.reshape\\\" or \\\"tensorrt.transpose\\\".\\n\\n    #### Caveats\\n\\n    #### Scalar reshapes\\n\\n    It is legal to shape to a scalar (e.g. `tensor<1xf32>` to `tensor<f32>`)\\n    and vice-versa.\\n\\n    #### `-1` in the Reshape Specification\\n\\n    The value `-1` in the reshape specification infers that dimension\\n    by inspecting the source shape and the rest of the reshape dimensions.\\n\\n    If 'zero_is_placeholder' is false, it is invalid for the specified shape\\n    to contain both a 0 and a -1, since the value of the dimension\\n    corresponding to -1 cannot be determined uniquely.\\n\\n    #### \\\"Zero is Placeholder\\\" Mode\\n\\n    **WARNING**: the \\\"zero is placeholder\\\" mode follows the underlying TRT\\n    mode, which can have surprising and unintuitive behavior. The intent\\n    of this mode historically was allow direct correspondence to frameworks\\n    that also has this mode, e.g. Cafe. Although it is not deprecated as of\\n    TRT 8.5, it is not recommended to use this mode unless absolutely necessary.\\n\\n    When `zero_is_placeholder = true`, 0-values in the reshape specification\\n    are interpreted as being placeholders for input dimensions.\\n\\n    In this mode, an inference procedure is followed to identify which input\\n    dimension corresponds to each \\\"0\\\". The procedure is described as follows:\\n\\n    1. Let `i` be the index of some \\\"0\\\" in the `reshape` array.\\n    2. Let `f(i)` be the corresponding dimension in the source shape (the\\n       transposed input).\\n    3. Let `f` be the identity: `f(i) = i`.\\n\\n    Any case where this results in out-of-bounds access for **any zero**\\n    in the reshape specification is considered invalid.\\n\\n    Any case where this results in a shape whose volume does not equal\\n    the volume of the source shape is considered invalid.\\n\\n    To illustrate this point, consider the following examples, where\\n    \\\"I\\\" is the source shape, \\\"R\\\" is the reshape specification, and \\\"O\\\"\\n    is the shape after reshaping. When the result is invalid (and will\\n    result in verification failure)\\n\\n      1. I: [1, 2, 3, 4]\\n         R: [0, -1, 0]\\n         O: [1, 8, 3]\\n\\n      2. I: [1, 2, 3, 4]\\n         R: [1, 0, 0, 0]\\n         O: [1, 2, 3, 4]\\n\\n      3. I: [1, 2, 3, 4]\\n         R: [0, 2, 0, 0, 1]\\n         O: [1, 2, 3, 4, 1]\\n\\n      4. I: [1, 2, 3, 4]\\n         R: [0, 1, 0, 0]\\n         O: [1, 1, 3, 4] INVALID (VOLUME)\\n\\n      5. I: [30, 20, 10, 1]\\n         R: [600, 0, 0, 0, 0]\\n         O: [1, 2, 3, 4, _] INVALID (OOB)\\n\\n      6. I: [30, 20, 10, 1]\\n         R: [600, 0, 0]\\n         O: [600, 20, 10] INVALID (VOLUME)\\n\\n    #### Examples:\\n\\n    ```mlir\\n    func.func @trt_shuffle(%arg0: tensor<2x224x224x3xf32>) -> tensor<2x3x224x224xf32> {\\n      %0 = tensorrt.shuffle {\\n        first_transpose = array<i64: 0, 1, 2, 3>,\\n        reshape = array<i64: 2, 3, 224, 224>,\\n        second_transpose = array<i64: 0, 1, 2, 3>\\n      } ins(%arg0 : tensor<2x224x224x3xf32>) -> tensor<2x3x224x224xf32>\\n      return %0 : tensor<2x3x224x224xf32>\\n    }\\n\\n    func.func @trt_shuffle_infer(%arg0: tensor<3x4x6xf32>) -> tensor<3x24xf32> {\\n      %0 = tensorrt.shuffle {\\n        first_transpose = array<i64: 0, 1, 2>,\\n        reshape = array<i64: 3, -1>,\\n        second_transpose = array<i64: 0, 1>\\n      } ins(%arg0 : tensor<3x4x6xf32>) -> tensor<3x24xf32>\\n      return %0 : tensor<3x24xf32>\\n    }\\n\\n    func.func @trt_shuffle_reshape_copy(%arg0: tensor<1x10x20x40xf32>) -> tensor<1x10x800xf32> {\\n      %0 = tensorrt.shuffle {\\n        first_transpose = array<i64: 0, 1, 2, 3>,\\n        reshape = array<i64: 0, 0, 800>,\\n        second_transpose = array<i64: 0, 1, 2>\\n      } ins(%arg0 : tensor<1x10x20x40xf32>) -> tensor<1x10x800xf32>\\n      return %0 : tensor<1x10x800xf32>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_AllTypesTensor\" },\n      { \"name\": \"dynamic_reshape\", \"type\": \"Optional<1DTensorOf<[ I32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"first_transpose\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"reshape\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"second_transpose\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"zero_is_placeholder\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `ins` `(` operands `:` type(operands) `)` `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.slice\",\n    \"summary\": \"TensorRT slice (ISliceLayer) operation\",\n    \"description\": \"The `tensorrt.slice` operation slices an input tensor based on\\n    offset, size, and stride values.\\n\\n    The offset, size, and stride values can be either a static list of\\n    i32 values, or each of them can come from a rank-1 i32 tensor-typed\\n    SSA value.\\n\\n    The slice layer selects for each dimension a start location from\\n    within the input tensor specified by `start`/`static_start`, and\\n    copies elements to the output tensor using the specified `stride`/\\n    `static_stride` across the input tensor.\\n\\n    The `mode` attribute specifies how the slice behaves at out-of-bounds\\n    (OOB) access. When `mode` is kCLAMP or kREFLECT, for each input\\n    dimension, if its size is 0 then the corresponding output\\n    dimension must be 0 too.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Tensor\" },\n      { \"name\": \"fill\", \"type\": \"Optional<TensorRT_Tensor>\" },\n      { \"name\": \"start\", \"type\": \"Optional<TensorRT_ShapeTensor>\" },\n      { \"name\": \"size\", \"type\": \"Optional<TensorRT_ShapeTensor>\" },\n      { \"name\": \"stride\", \"type\": \"Optional<TensorRT_ShapeTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_start\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"static_size\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"static_stride\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<TensorRT_SliceModeAttr{kDEFAULT|kWRAP|kCLAMP|kFILL|kREFLECT}, tensorrt::SliceMode::kDEFAULT>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$input\\n     `[` ( $start^ `` `:` type($start) ) : ( `` custom<StaticIndexI32Array>($static_start) ) ? `]` ``\\n     `[` ( $size^ `` `:` type($size) ) : ( `` custom<StaticIndexI32Array>($static_size) ) ? `]` ``\\n     `[` ( $stride^ `` `:` type($stride) ) : ( `` custom<StaticIndexI32Array>($static_stride) ) ? `]`\\n     ( `fill` `(` $fill^ `:` type($fill) `)` )?\\n    attr-dict `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.softmax\",\n    \"summary\": \"TensorRT softmax (ISoftMaxLayer) operation\",\n    \"description\": \"The `tensorrt.softmax` operation applies the \\\"softmax\\\" to the\\n    `axis` dimension of the input tensor. The shape of the result tensor is\\n    equal to the shape of the input tensor. The computation that yields the\\n    result tensor is described below.\\n\\n    Let the input tensor be of type `tensor<d_1 x ... x d_axis x ... x d_n x f32>`.\\n    Let `x := input_{i_1, ..., i_axis, ..., i_n}` be a point in the input\\n    tensor. The point `y` in the result with the same coordinates is given by\\n\\n    ```\\n    y = e^{x} \\\\ ( sum_{i_axis=0}^{d_axis - 1} input_{i_1, ..., i_axis, ..., i_n} )\\n    ```\\n\\n    In other words, the result is the pointwise exponential of the input, normalized\\n    along the `axis` dimension.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_RankedTensorOf<[F16, BF16, F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input)\"\n  },\n  {\n    \"name\": \"tensorrt.top_k\",\n    \"summary\": \"TensorRT top K (ITopKLayer) operation\",\n    \"description\": \"The `tensorrt.top_k` operation finds the top K largest or smallest elements\\n    and their indices from each slice  of the tensor along the `axis`\\n    dimension. The two results correspond to the values and indices,\\n    respectively.\\n\\n    The `topkOperation` is either `kMAX` or `kMIN` and determines whether the\\n    K largest or K smallest values are returned.\\n\\n    The result values and indices are sorted with respect to the values:\\n\\n    `kMAX`: sorted from largest to smallest value\\n    `kMAX`: sorted from smallest to largest value\\n\\n    The result of the operation are never rank-reduced, even if `K=1`.\\n\\n    #### Examples:\\n\\n    ```mlir\\n\\n    %0 = tensorrt.top_k {\\n      topkOperation = #tensorrt.topKOperation<kMAX>,\\n      k = 1 : i64,\\n      axis = 2 : i64\\n    } %input  : tensor<100x200xf32> -> (tensor<100x1xf32>, <100x1xi32>)\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_RankedTensorOf<[I32, I64, F16, BF16, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorRT_RankedTensorOf<[I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I64Attr\" },\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"topkOperation\", \"type\": \"TensorRT_TopKOperationAttr{kMAX|kMIN}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$topkOperation attr-dict  $input `:` type($input) `->` type(results)\"\n  },\n  {\n    \"name\": \"tensorrt.transpose\",\n    \"summary\": \"Permutes the dimensions of the input tensor\",\n    \"description\": \"Permutes the dimensions of the `input` according to `permutation`.\\n\\n    This operation is a TensorRT dialect extension operation and is lowered\\n    into a TensorRT shuffle operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRT_AllTypesTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"AffineMapAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input) `to` type($result)\"\n  },\n  {\n    \"name\": \"tensorrt.unary\",\n    \"summary\": \"TensorRT unary (IUnaryLayer) operation\",\n    \"description\": \"The `tensorrt.unary` operation consists of applying single\\n    operation given by `unaryOperation` to the `input` elementwise.\\n    The result type is identical to the input type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorRT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"unaryOperation\", \"type\": \"TensorRT_UnaryOperationAttr{kEXP|kLOG|kSQRT|kRECIP|kABS|kNEG|kSIN|kCOS|kTAN|kSINH|kCOSH|kASIN|kACOS|kATAN|kASINH|kACOSH|kATANH|kCEIL|kFLOOR|kERF|kNOT|kSIGN|kROUND}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $input `:` type($input)\"\n  },\n  {\n    \"name\": \"tensorrt.while\",\n    \"summary\": \"TensorRT While Loop (ILoopLayer) operation\",\n    \"description\": \"The `tensorrt.while` operation represents a while-style loop that executes its\\n    body while a condition is satisfied.\\n\\n    The `tensorrt.while` operation consists of two regions: \\\"condition\\\" region and\\n    \\\"body\\\" region.\\n\\n    #### Example\\n\\n    The below example constructs a simple while loop that performs an operation while\\n    the given input condition is true and saves the result to an output tensor.\\n    Here, the input condition checks that iter variable is less than limit and\\n    when the condition is satisfied, the sum of iter and one tensors is executed.\\n\\n    ```mlir\\n    func.func @trt_while_loop() -> (tensor<f32>) {\\n      %one = tensorrt.constant dense<1.0> : tensor<f32>\\n      %iter_init = tensorrt.constant dense<1.0> : tensor<f32>\\n      %limit = tensorrt.constant dense<10.0> : tensor<f32>\\n      %result0 = tensorrt.while {} (%iter_init : tensor<f32>) -> tensor<f32>\\n      {\\n        // condition\\n        ^bb0(%iter:tensor<f32>):\\n          %cond = tensorrt.element_wise <kLESS>(%iter, %limit : tensor<f32>, tensor<f32>)\\n                -> tensor<i1>\\n          tensorrt.condition(%cond : tensor<i1>) %iter : tensor<f32>\\n      } ,\\n      {\\n        // body\\n        ^bb1(%iter:tensor<f32>):\\n          %new_iter = tensorrt.element_wise <kSUM> (%one, %iter : tensor<f32>, tensor<f32>) -> tensor<f32>\\n          tensorrt.yield %new_iter: tensor<f32>\\n      }\\n      return %result0 : tensor<f32>\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<TensorRT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TensorRT_Tensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"condRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict  `(` $operands `:` type($operands) `)` `->` type($results)\\n      $condRegion `,`\\n      $bodyRegion\"\n  },\n  {\n    \"name\": \"tensorrt.yield\",\n    \"summary\": \"Yields one or more SSA values from a tensorrt dialect region\",\n    \"description\": \"The `tensorrt.yield` operation yields SSA values from tensorrt dialect op region\\n    and terminate the regions. The semantics of how the values are yielded is\\n    defined by the parent operation.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"test.addi\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"AnyTypeOf<[I32, TestI32]>\" },\n      { \"name\": \"op2\", \"type\": \"AnyTypeOf<[I32, TestI32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, TestI32]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.affine_scope\",\n    \"summary\": \"affine scope operation\",\n    \"description\": \"Test op that defines a new affine scope.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.all_attr_constraint_of1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.all_attr_constraint_of2\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.alloc_with_multiple_results\",\n    \"results\": [\n      { \"name\": \"index\", \"type\": \"Index\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($index) `,` type($memref)\"\n  },\n  {\n    \"name\": \"test.alloca_scope_region\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"test.always_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can always be\\n    speculatively executed.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.another_three_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" },\n      { \"name\": \"result3\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"test.another_two_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"F32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"test.another_type_producer\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.any_attr_of_i32_str\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttrOf<[I32Attr, StrAttr]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.any_cond\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"test.arg_and_res_have_fixed_element_types\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.array_of_attr_op\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"TestArrayOfUglyAttrs\" },\n      { \"name\": \"b\", \"type\": \"TestArrayOfInts\" },\n      { \"name\": \"c\", \"type\": \"TestArrayOfEnums\" }\n    ],\n    \"assemblyFormat\": \"`a` `=` $a `,` `b` `=` $b `,` `c` `=` $c attr-dict\"\n  },\n  {\n    \"name\": \"test.asm_dialect_interface_op\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.asm_interface_op\",\n    \"results\": [\n      { \"name\": \"first\", \"type\": \"AnyType\" },\n      { \"name\": \"middle_results\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"result2\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.attr_sized_operands\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"c\", \"type\": \"I32\" },\n      { \"name\": \"d\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.attr_sized_results\",\n    \"results\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"c\", \"type\": \"I32\" },\n      { \"name\": \"d\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.attr_sized_results_compile_test\",\n    \"results\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"I32\" },\n      { \"name\": \"c\", \"type\": \"Optional<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.attr_with_loc\",\n    \"summary\": \"op's attribute has a location\",\n    \"attributes\": [\n      { \"name\": \"loc\", \"type\": \"AnyAttr\" },\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `` custom<OptionalLoc>($loc) `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.attr_with_trait\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.benchmark\",\n    \"summary\": \"benchmark operation\",\n    \"description\": \"The \\\"tfrt_test.benchmark\\\" operation benchmarks the performance of an MLIR\\n     region by executing the given MLIR region repeatedly up to the\\n     `duratino_secs` seconds or `max_count` times. `num_warmup_runs` specifies\\n     the number of warm up runs to run the given MLIR region before the\\n     benchmark starts.\\n\\n     The target MLIR region can take an arbitrary number of arguments and\\n     should return exactly one value. The arguments for the MLIR region are\\n     provided as the operands of the tfrt_test.benchmark op.\\n\\n     Example:\\n       tfrt_test.benchmark \\\"add.i32\\\"(%c : i32, %d : f32) max_count = 100, duration_secs = 1 {\\n         // code for benchmarking\\n         ...\\n       }\\n\\n       tfrt_test.benchmark \\\"add.i32\\\"(%c : i32)\\n         duration_secs = 1,\\n         max_count = 100,\\n         num_warmup_runs = 10 {\\n         // The MLIR code to be benchmarked goes here.\\n         // The following code benchmarks the tfrt.add.i32 kernel.\\n         %x = tfrt.add.i32 %c, %c\\n         // The benchmarked function needs to return exactly one value.\\n         tfrt.return %x : i32\\n       }\",\n    \"attributes\": [\n      { \"name\": \"duration_secs\", \"type\": \"I32Attr\" },\n      { \"name\": \"max_count\", \"type\": \"I32Attr\" },\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"num_warmup_runs\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 1>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.block_argument_name_from_type\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.block_argument_name_from_type_interface\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.block_names\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.br\",\n    \"operands\": [\n      { \"name\": \"targetOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"target\", \"type\": \"AnySuccessor\" }\n    ]\n  },\n  {\n    \"name\": \"test.broadcastable\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.buffer_based\",\n    \"description\": \"A buffer based operation, that uses memRefs as input and output.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"`in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.call\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"test.call_and_store\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"callee_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"store_before_call\", \"type\": \"BoolAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $callee_operands `)` `,` $address attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.call_on_device\",\n    \"operands\": [\n      { \"name\": \"forwarded_operands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"non_forwarded_device_operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $forwarded_operands `)` `,` $non_forwarded_device_operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.call_with_segments\",\n    \"summary\": \"test call op with segmented args\",\n    \"operands\": [\n      { \"name\": \"prefix\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"suffix\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $prefix `:` type($prefix) `)`\\n            `(` $args `:` type($args) `)`\\n            `(` $suffix `:` type($suffix) `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.cast\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.compare\",\n    \"description\": \"Compare `lhs` and `rhs`. A remark is emitted which indicates whether the\\n    specified comparison operator was proven to hold. The remark also indicates\\n    whether the opposite comparison operator was proven to hold.\\n\\n    `var_operands` must have exactly two operands: one for the LHS operand and\\n    one for the RHS operand. If `lhs_map` is specified, as many operands as\\n    `lhs_map` has inputs are expected instead of the first operand. If `rhs_map`\\n    is specified, as many operands as `rhs_map` has inputs are expected instead\\n    of the second operand.\",\n    \"operands\": [\n      { \"name\": \"var_operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cmp\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"EQ\\\">\" },\n      { \"name\": \"lhs_map\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"rhs_map\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"compose\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.complex_f64\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"ComplexF64\" }\n    ]\n  },\n  {\n    \"name\": \"test.complex_f64_tensor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[ComplexF64]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.conditionally_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can be speculatively\\n    executed if the input to it is an `arith.constant`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.confined_dense_array_attr\",\n    \"attributes\": [\n      { \"name\": \"emptyattr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayStrictlySorted<DenseI16ArrayAttr>]>\" },\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<DenseI32ArrayAttr, [DenseArraySorted<DenseI32ArrayAttr>]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlySorted<DenseI64ArrayAttr>]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.confined_non_negative_attr\",\n    \"attributes\": [\n      { \"name\": \"i8attr\", \"type\": \"ConfinedAttr<DenseI8ArrayAttr, [DenseArrayNonNegative<DenseI8ArrayAttr>]>\" },\n      { \"name\": \"i16attr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayNonNegative<DenseI16ArrayAttr>]>\" },\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<DenseI32ArrayAttr, [DenseArrayNonNegative<DenseI32ArrayAttr>]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayNonNegative<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"f32attr\", \"type\": \"ConfinedAttr<DenseF32ArrayAttr, [DenseArrayNonNegative<DenseF32ArrayAttr>]>\" },\n      { \"name\": \"f64attr\", \"type\": \"ConfinedAttr<DenseF64ArrayAttr, [DenseArrayNonNegative<DenseF64ArrayAttr>]>\" },\n      { \"name\": \"emptyattr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayNonNegative<DenseI16ArrayAttr>]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.confined_strictly_positive_attr\",\n    \"attributes\": [\n      { \"name\": \"i8attr\", \"type\": \"ConfinedAttr<DenseI8ArrayAttr, [DenseArrayStrictlyPositive<DenseI8ArrayAttr>]>\" },\n      { \"name\": \"i16attr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>\" },\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<DenseI32ArrayAttr, [DenseArrayStrictlyPositive<DenseI32ArrayAttr>]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlyPositive<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"f32attr\", \"type\": \"ConfinedAttr<DenseF32ArrayAttr, [DenseArrayStrictlyPositive<DenseF32ArrayAttr>]>\" },\n      { \"name\": \"f64attr\", \"type\": \"ConfinedAttr<DenseF64ArrayAttr, [DenseArrayStrictlyPositive<DenseF64ArrayAttr>]>\" },\n      { \"name\": \"emptyattr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.constant\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.conv_op_not_linalg_op\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"AnyType\" },\n      { \"name\": \"filter\", \"type\": \"AnyType\" },\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.conversion_call_op\",\n    \"operands\": [\n      { \"name\": \"arg_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"test.conversion_func_op\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.convert_block_args\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_legal\", \"type\": \"UnitAttr\" },\n      { \"name\": \"replace_with_operand\", \"type\": \"UnitAttr\" },\n      { \"name\": \"duplicate\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$val\\n    (`is_legal` $is_legal^)?\\n    (`duplicate` $duplicate^)?\\n    (`replace_with_operand` $replace_with_operand^)?\\n    $body attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.copy\",\n    \"description\": \"Represents a copy operation.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"target\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"`(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)`\\n     attr-dict\"\n  },\n  {\n    \"name\": \"test.count3.i32\",\n    \"summary\": \"tfrt_test.count3 operation\",\n    \"description\": \"An operation that takes one input x and returns x+1, x+2, x+3 as the\\n     result.\\n\\n     Example:\\n       %1, %2, %3 = test.count3.i32 %0\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.count3.i64\",\n    \"summary\": \"tfrt_test.count3 operation\",\n    \"description\": \"An operation that takes one input x and returns x+1, x+2, x+3 as the\\n     result.\\n\\n     Example:\\n       %1, %2, %3 = test.count3.i32 %0\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.crashing_return\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"valid\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"($args^ `:` type($args))? attr-dict\"\n  },\n  {\n    \"name\": \"test.create_memref_op\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.create_tensor_op\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.cse_of_single_block_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `inputs` `(` $inputs `)`\\n    $region `:` type($inputs)  `->` type($outputs)\"\n  },\n  {\n    \"name\": \"test.custom_dimension_list_attr\",\n    \"description\": \"Test printing/parsing of dimension list attribute.\",\n    \"attributes\": [\n      { \"name\": \"dimension_list\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`dimension_list` `=` custom<DimensionList>($dimension_list)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.custom_result_name\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"Variadic<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"Variadic<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.data_layout_query\",\n    \"summary\": \"A token op recognized by data layout query test pass\",\n    \"description\": \"The data layout query pass pattern-matches this op and attaches to it an\\n    array attribute containing the result of data layout query of the result\\n    type of this op.\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.decode_jpeg\",\n    \"summary\": \"tfrt_test.decode_jpeg operation\",\n    \"description\": \"The \\\"tfrt_test.decode_jpeg\\\" operation decodes Jpeg-formatted binary and\\n    returns a tensor with the same semantics as tf.image.decode_jpeg(image_encoded, channels=3).\\n\\n    Example:\\n      %image_decoded =  tfrt_test.decode_jpeg %image_encoded\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.default_dialect\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"test\",\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.default_value_print\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value_with_default\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand\"\n  },\n  {\n    \"name\": \"test.dense_array_attr\",\n    \"attributes\": [\n      { \"name\": \"i1attr\", \"type\": \"DenseBoolArrayAttr\" },\n      { \"name\": \"i8attr\", \"type\": \"DenseI8ArrayAttr\" },\n      { \"name\": \"i16attr\", \"type\": \"DenseI16ArrayAttr\" },\n      { \"name\": \"i32attr\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"i64attr\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"f32attr\", \"type\": \"DenseF32ArrayAttr\" },\n      { \"name\": \"f64attr\", \"type\": \"DenseF64ArrayAttr\" },\n      { \"name\": \"emptyattr\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`i1attr` `=` $i1attr `i8attr` `=` $i8attr `i16attr` `=` $i16attr\\n   `i32attr` `=` $i32attr `i64attr` `=` $i64attr  `f32attr` `=` $f32attr\\n   `f64attr` `=` $f64attr `emptyattr` `=` $emptyattr attr-dict\"\n  },\n  {\n    \"name\": \"test.derived_type_attr\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.destination_style_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"other_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    (`outs` `(` $outputs^  `:` type($outputs) `)`)?\\n    (`(` $other_operands^ `:` type($other_operands) `)`)?\\n    (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"test.dialect_canonicalizable\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.do.async\",\n    \"summary\": \"do.async operation\",\n    \"description\": \"The \\\"tfrt_test.do.async\\\" operation allows its body to be executed\\n    asynchronously. It has one region which represents the body.\\n\\n    The body region takes an arbitrary number of arguments and may return\\n    arbitrary number of return values, using a `tfrt.return` operation at the\\n    end of the region.\\n\\n    Example:\\n\\n      tfrt_test.do.async () -> () {\\n        tfrt.return\\n      }\\n\\n      %res = tfrt_test.do.async () -> (i32) {\\n        %val = tfrt.constant.i32 1\\n        tfrt.return %val\\n      }\\n\\n      %res1, %res2 = tfrt_test.do.async %val1, %val2 : (i32, f32) -> (i32, f32) {\\n        tfrt.return %val1, val2 : i32, f32\\n      }\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.dummy_memref_op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.dummy_op_with_region_ref\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$body attr-dict custom<DummyRegionRef>(ref($body))\"\n  },\n  {\n    \"name\": \"test.dummy_op_with_successor_ref\",\n    \"successors\": [\n      { \"name\": \"successor\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$successor attr-dict custom<DummySuccessorRef>(ref($successor))\"\n  },\n  {\n    \"name\": \"test.dummy_tensor_op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.either_helper_op_a\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.either_helper_op_b\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.either_op_a\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg1\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg2\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.either_op_b\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg1\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.either_op_c\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg1\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.elementwise_mappable\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"test.ellipsis\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"variadic\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $operands (`...` $variadic^)? `)` attr-dict `:` type($operands) `...`\"\n  },\n  {\n    \"name\": \"test.else_anchor\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`(` (`?`) : (`` $a^ `:` type($a))? `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.empty_properties\",\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.fill_op_not_linalg_op\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.float_attrs\",\n    \"attributes\": [\n      { \"name\": \"float_attr\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.float_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"scalar_f32_attr\", \"type\": \"RankedF32ElementsAttr<[2]>\" },\n      { \"name\": \"tensor_f64_attr\", \"type\": \"RankedF64ElementsAttr<[4, 8]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.fold_to_call_op\",\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.fold_with_fold_adaptor\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"I32\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"var_of_var\", \"type\": \"VariadicOfVariadic<I32, attr>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$op `,` `[` $variadic `]` `,` `{` $var_of_var `}` $body attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_all_types_match_attr\",\n    \"operands\": [\n      { \"name\": \"value2\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value1\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value1', 'value2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value1 `,` $value2\"\n  },\n  {\n    \"name\": \"test.format_all_types_match_var\",\n    \"operands\": [\n      { \"name\": \"value1\", \"type\": \"AnyType\" },\n      { \"name\": \"value2\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value1', 'value2', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value1 `,` $value2 `:` type($value1)\"\n  },\n  {\n    \"name\": \"test.format_attr_dict_w_keyword\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" },\n      { \"name\": \"opt_attr\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_attr_op\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$attr attr-dict\"\n  },\n  {\n    \"name\": \"test.format_buildable_type_op\",\n    \"operands\": [\n      { \"name\": \"buildable\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"buildable_res\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$buildable attr-dict\"\n  },\n  {\n    \"name\": \"test.format_compound_attr\",\n    \"attributes\": [\n      { \"name\": \"compound\", \"type\": \"CompoundAttrA\" }\n    ],\n    \"assemblyFormat\": \"$compound attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_cpmd_nested_attr\",\n    \"attributes\": [\n      { \"name\": \"nested\", \"type\": \"CompoundNestedOuter\" }\n    ],\n    \"assemblyFormat\": \"`nested` $nested attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_cpmd_nested_type\",\n    \"operands\": [\n      { \"name\": \"nested\", \"type\": \"CompoundNestedOuterType\" }\n    ],\n    \"assemblyFormat\": \"$nested `nested` type($nested) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_attrdict\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" },\n      { \"name\": \"optAttr\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveAttrDict>( attr-dict )\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_attributes\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" },\n      { \"name\": \"optAttr\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveAttributes>(\\n      $attr, $optAttr\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_operands\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" },\n      { \"name\": \"optOperand\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"varOperands\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveOperands>(\\n      $operand, $optOperand, $varOperands\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_operands_and_types\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" },\n      { \"name\": \"optOperand\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"varOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveOperandsAndTypes>(\\n      $operand, $optOperand, $varOperands,\\n      type($operand), type($optOperand), type($varOperands)\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_regions\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" },\n      { \"name\": \"other_regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveRegions>(\\n      $region, $other_regions\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_results\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" },\n      { \"name\": \"optResult\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"varResults\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveResults>(\\n      type($result), type($optResult), type($varResults)\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_results_with_type_refs\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" },\n      { \"name\": \"optResult\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"varResults\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveResults>(\\n      type($result), type($optResult), type($varResults)\\n    )\\n    custom<CustomDirectiveWithTypeRefs>(\\n      ref(type($result)), ref(type($optResult)), ref(type($varResults))\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_spacing\",\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"StrAttr\" },\n      { \"name\": \"attr2\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveSpacing>($attr1)\\n    custom<CustomDirectiveSpacing>($attr2)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_successors\",\n    \"successors\": [\n      { \"name\": \"successor\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"successors\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"custom<CustomDirectiveSuccessors>(\\n      $successor, $successors\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_custom_directive_with_optional_operand_ref\",\n    \"operands\": [\n      { \"name\": \"optOperand\", \"type\": \"Optional<I64>\" }\n    ],\n    \"assemblyFormat\": \"($optOperand^)? `:`\\n    custom<CustomDirectiveOptionalOperandRef>(ref($optOperand))\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.format_implicit_terminator_region_a_op\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"test.format_infer_type\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.format_infer_type_all_operands_and_types\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"test.format_infer_type_all_types\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`(` operands `)` attr-dict `:` type($args)\"\n  },\n  {\n    \"name\": \"test.format_infer_type_all_types_one_operand\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"test.format_infer_type_all_types_two_operands\",\n    \"operands\": [\n      { \"name\": \"args0\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"args1\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"`(` $args0 `)` `(` $args1 `)` attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"test.format_infer_type_regions\",\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"test.format_infer_type_variadic_operands\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" },\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $a `:` type($a) `)` `(` $b `:` type($b) `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.format_infer_type2\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.format_infer_variadic_type_from_non_variadic\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"test.format_literal_following_optional_group\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`(` $value^ `)`)? `:` $type attr-dict\"\n  },\n  {\n    \"name\": \"test.format_literal_op\",\n    \"assemblyFormat\": \"`keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)`\\n    `?` `+` `*` `{` `\\\\n` `}` attr-dict\"\n  },\n  {\n    \"name\": \"test.format_maybe_empty_type\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TestTypeOptionalValueType\" }\n    ],\n    \"assemblyFormat\": \"$in `:` type($in) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_multiple_variadic_operands\",\n    \"operands\": [\n      { \"name\": \"operand0\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"operand1\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.format_multiple_variadic_results\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"result1\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"`:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.format_nested_attr\",\n    \"attributes\": [\n      { \"name\": \"nested\", \"type\": \"CompoundAttrNested\" }\n    ],\n    \"assemblyFormat\": \"$nested attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_operand_a_op\",\n    \"operands\": [\n      { \"name\": \"buildable\", \"type\": \"I64\" },\n      { \"name\": \"operand\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"operands `:` type(operands) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_operand_b_op\",\n    \"operands\": [\n      { \"name\": \"buildable\", \"type\": \"I64\" },\n      { \"name\": \"operand\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"operands `:` type($operand) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_operand_c_op\",\n    \"operands\": [\n      { \"name\": \"buildable\", \"type\": \"I64\" },\n      { \"name\": \"operand\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$buildable `,` $operand `:` type(operands) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_operand_d_op\",\n    \"operands\": [\n      { \"name\": \"buildable\", \"type\": \"I64\" },\n      { \"name\": \"operand\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$buildable `,` $operand `:` type($operand) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_operand_e_op\",\n    \"operands\": [\n      { \"name\": \"buildable\", \"type\": \"I64\" },\n      { \"name\": \"operand\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_opt_attr_op_a\",\n    \"attributes\": [\n      { \"name\": \"opt_attr\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"(`(` $opt_attr^ `)` )? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_opt_attr_op_b\",\n    \"attributes\": [\n      { \"name\": \"opt_attr\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"($opt_attr^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_opt_symbol_name_attr_op\",\n    \"attributes\": [\n      { \"name\": \"opt_attr\", \"type\": \"OptionalAttr<SymbolNameAttr>\" }\n    ],\n    \"assemblyFormat\": \"($opt_attr^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_opt_symbol_ref_attr_op\",\n    \"attributes\": [\n      { \"name\": \"opt_attr\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"assemblyFormat\": \"($opt_attr^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_default_attrs\",\n    \"attributes\": [\n      { \"name\": \"str\", \"type\": \"DefaultValuedStrAttr<StrAttr, default>\" },\n      { \"name\": \"sym\", \"type\": \"DefaultValuedStrAttr<SymbolNameAttr, default>\" },\n      { \"name\": \"e\", \"type\": \"DefaultValuedAttr<SomeI64Enum{case5|case10|caseLarse}, SomeI64Enum::case5>\" }\n    ],\n    \"assemblyFormat\": \"($str^)? ($sym^)? ($e^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_default_enum_attr\",\n    \"attributes\": [\n      { \"name\": \"e\", \"type\": \"DefaultValuedEnumAttr<SomeI64Enum{case5|case10|caseLarse}, I64Case5>\" }\n    ],\n    \"assemblyFormat\": \"($e^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_else\",\n    \"attributes\": [\n      { \"name\": \"isFirstBranchPresent\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`then` $isFirstBranchPresent^):(`else`)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_enum_attr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"OptionalAttr<SomeI64Enum{case5|case10|caseLarse}>\" }\n    ],\n    \"assemblyFormat\": \"($attr^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_operand_result_a_op\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"optional_res\", \"type\": \"Optional<I64>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $optional `:` type($optional) `)` `:` type($optional_res)\\n  (`[` $variadic^ `]`)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_operand_result_b_op\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"optional_res\", \"type\": \"Optional<I64>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res)\\n  (`[` $variadic^ `]`)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_prop_dict\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"OptionalProp<StringProp>\" },\n      { \"name\": \"b\", \"type\": \"DefaultValuedProp<I32Prop, 1>\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_result_a_op\",\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"assemblyFormat\": \"(`:` type($optional)^ `->` type($variadic))? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_result_b_op\",\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"assemblyFormat\": \"(`:` type($optional) `->` type($variadic)^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_result_c_op\",\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"Optional<I64>\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"assemblyFormat\": \"(`:` functional-type($optional, $variadic)^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_result_d_op\",\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"Optional<F80>\" }\n    ],\n    \"assemblyFormat\": \"(`:` type($optional)^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_unit_attribute\",\n    \"attributes\": [\n      { \"name\": \"is_optional\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`is_optional` $is_optional^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_unit_attribute_no_elide\",\n    \"attributes\": [\n      { \"name\": \"is_optional\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"($is_optional^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_unit_property\",\n    \"attributes\": [\n      { \"name\": \"is_optional\", \"type\": \"UnitProp\" }\n    ],\n    \"assemblyFormat\": \"(`is_optional` $is_optional^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_optional_unit_property_no_elide\",\n    \"attributes\": [\n      { \"name\": \"is_optional\", \"type\": \"UnitProp\" }\n    ],\n    \"assemblyFormat\": \"($is_optional^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_qual_cpmd_nested_attr\",\n    \"attributes\": [\n      { \"name\": \"nested\", \"type\": \"CompoundNestedOuter\" }\n    ],\n    \"assemblyFormat\": \"`nested` qualified($nested) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_qual_cpmd_nested_type\",\n    \"operands\": [\n      { \"name\": \"nested\", \"type\": \"CompoundNestedOuterType\" }\n    ],\n    \"assemblyFormat\": \"$nested `nested` qualified(type($nested)) attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.format_region_a_op\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict\"\n  },\n  {\n    \"name\": \"test.format_region_b_op\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict\"\n  },\n  {\n    \"name\": \"test.format_region_c_op\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"(`region` $region^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_result_a_op\",\n    \"results\": [\n      { \"name\": \"buildable_res\", \"type\": \"I64\" },\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"type($result) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_result_b_op\",\n    \"results\": [\n      { \"name\": \"buildable_res\", \"type\": \"I64\" },\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"type(results) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_result_c_op\",\n    \"results\": [\n      { \"name\": \"buildable_res\", \"type\": \"I64\" },\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"functional-type($buildable_res, $result) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_successor_a_op\",\n    \"successors\": [\n      { \"name\": \"targets\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"assemblyFormat\": \"$targets attr-dict\"\n  },\n  {\n    \"name\": \"test.format_symbol_name_attr_op\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"assemblyFormat\": \"$attr attr-dict\"\n  },\n  {\n    \"name\": \"test.format_two_variadic_operands_no_buildable_type_op\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)`  attr-dict\"\n  },\n  {\n    \"name\": \"test.format_types_match_attr\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'result', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value\"\n  },\n  {\n    \"name\": \"test.format_types_match_context\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'result', '::mlir::TupleType::get($_ctxt, $_self)'>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($value)\"\n  },\n  {\n    \"name\": \"test.format_types_match_optional\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'optional', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"(`(` $optional^ `:` type($result) `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_types_match_var\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'result', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($value)\"\n  },\n  {\n    \"name\": \"test.format_types_match_variadic\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'result', 'llvm::make_range($_self.begin(), $_self.end())'>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($value)\"\n  },\n  {\n    \"name\": \"test.format_variadic_of_variadic_operand\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VariadicOfVariadic<I64, operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_variadic_operand\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) attr-dict\"\n  },\n  {\n    \"name\": \"test.format_variadic_region_a_op\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"$regions attr-dict\"\n  },\n  {\n    \"name\": \"test.format_variadic_region_b_op\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"($regions^ `found_regions`)? attr-dict\"\n  },\n  {\n    \"name\": \"test.format_variadic_result\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"assemblyFormat\": \"`:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"test.forward_buffer\",\n    \"description\": \"A pure operation that takes a buffer and returns a buffer. This op does not\\n    have any side effects, so it cannot allocate or read a buffer from memory.\\n    It must return the input buffer (or a view thereof). This op purposely does\\n    does not implement any interface.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"test.functional_region_op\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FunctionType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"test.get_bytes_field_from_example\",\n    \"summary\": \"tfrt_test.get_bytes_field_from_example operation\",\n    \"description\": \"The tfrt_test.get_bytes_field_from_example extracts the bytes field of the\\n    given `key` name from a protobuf object whose format follows example.proto.\\n\\n    Example:\\n      %value = tfrt_test.get_bytes_field_from_example %example, %key\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.get_int64_field_from_example\",\n    \"summary\": \"tfrt_test.get_int64_field_from_example operation\",\n    \"description\": \"The tfrt_test.get_int64_field_from_example extracts the int64 field of the\\n    given `key` name from a protobuf object whose format follows example.proto.\\n\\n    Example:\\n      %value = tfrt_test.get_int64_field_from_example %example, %key\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.get_string\",\n    \"summary\": \"tfrt_test.get_string\",\n    \"description\": \"Get a !tfrt.string value from the given string attribute.\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.get_string_sync\",\n    \"summary\": \"tfrt_test.get_string_sync\",\n    \"description\": \"Get a !tfrt.string value from the given string attribute.\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.get_tuple_element\",\n    \"description\": \"Test op that returns a specified element of the tuple.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.graph_loop\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"rets\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$args $body attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.graph_region\",\n    \"summary\": \"operation with a graph region\",\n    \"description\": \"Test op that defines a graph region.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"test.has_str_value\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.i32_enum_attr\",\n    \"results\": [\n      { \"name\": \"val\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SomeI32Enum{case5|case10|caseSignedMaxPlusOne|caseUnsignedMax}\" }\n    ]\n  },\n  {\n    \"name\": \"test.i32ElementsAttr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I32ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.i64_enum_attr\",\n    \"results\": [\n      { \"name\": \"val\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SomeI64Enum{case5|case10|caseLarse}\" }\n    ]\n  },\n  {\n    \"name\": \"test.if_first_operand_is_none_then_so_is_second\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.ignore_arg_match_dst\",\n    \"operands\": [\n      { \"name\": \"b\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.ignore_arg_match_src\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyType\" },\n      { \"name\": \"b\", \"type\": \"AnyType\" },\n      { \"name\": \"c\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"d\", \"type\": \"AnyAttr\" },\n      { \"name\": \"e\", \"type\": \"AnyAttr\" },\n      { \"name\": \"f\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_a\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_b\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_c\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_d\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_e\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_f\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.illegal_op_g\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.increment\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($result)\"\n  },\n  {\n    \"name\": \"test.indexElementsAttr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"IndexElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.int_attrs\",\n    \"attributes\": [\n      { \"name\": \"any_i32_attr\", \"type\": \"AnyI32Attr\" },\n      { \"name\": \"index_attr\", \"type\": \"IndexAttr\" },\n      { \"name\": \"ui32_attr\", \"type\": \"UI32Attr\" },\n      { \"name\": \"si32_attr\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.int_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"any_i32_attr\", \"type\": \"AnyI32ElementsAttr\" },\n      { \"name\": \"i32_attr\", \"type\": \"I32ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.int_types\",\n    \"results\": [\n      { \"name\": \"any_i16\", \"type\": \"AnyI16\" },\n      { \"name\": \"si32\", \"type\": \"SI32\" },\n      { \"name\": \"ui64\", \"type\": \"UI64\" },\n      { \"name\": \"any_int\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"test.interleaved_operand_attr1\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.interleaved_operand_attr2\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.internal_br\",\n    \"operands\": [\n      { \"name\": \"successOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"errorOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"successPath\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"errorPath\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.isolated_graph_region\",\n    \"summary\": \"isolated from above operation with a graph region\",\n    \"description\": \"Test op that defines a graph region which is isolated from above.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"test.isolated_one_region_op\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"my_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $operands $my_region `:` type($operands) `->` type($results)\"\n  },\n  {\n    \"name\": \"test.isolated_region\",\n    \"summary\": \"isolated region operation\",\n    \"description\": \"Test op with an isolated region, to test passthrough region arguments. Each\\n    argument is of index type.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.isolated_regions\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $regions\"\n  },\n  {\n    \"name\": \"test.legal_op_a\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"status\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.legal_op_b\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.legal_op_c\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.less_than\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"RankedTensorOf<[F32]>\" },\n      { \"name\": \"rhs\", \"type\": \"RankedTensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[I1]>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.linalg_conv_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"test.linalg_fill_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"test.loc_dst\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.loc_dst_no_res\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.loc_src\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.loc_src_no_res\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.loop_block\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"floatResult\", \"type\": \"F32\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$init `:` functional-type($init, $floatResult) $body\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"test.loop_block_term\",\n    \"operands\": [\n      { \"name\": \"nextIterArg\", \"type\": \"I32\" },\n      { \"name\": \"exitArg\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"`iter` $nextIterArg `exit` $exitArg attr-dict\"\n  },\n  {\n    \"name\": \"test.loop_types_compat\",\n    \"operands\": [\n      { \"name\": \"init_args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.make_tuple\",\n    \"description\": \"Test op that creates a tuple value from a list of values.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TupleOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.many_arguments\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" },\n      { \"name\": \"input3\", \"type\": \"I32\" },\n      { \"name\": \"input4\", \"type\": \"I32\" },\n      { \"name\": \"input5\", \"type\": \"I32\" },\n      { \"name\": \"input6\", \"type\": \"I32\" },\n      { \"name\": \"input7\", \"type\": \"I32\" },\n      { \"name\": \"input8\", \"type\": \"I32\" },\n      { \"name\": \"input9\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr3\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr4\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr5\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr6\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr7\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr8\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr9\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.many_regions\",\n    \"summary\": \"operation created with move-only objects\",\n    \"description\": \"Test op with multiple regions with a `create` function that\\n    takes parameters containing move-only objects.\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"test.match_op_attribute1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"required_attr\", \"type\": \"I32Attr\" },\n      { \"name\": \"optional_attr\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"default_valued_attr\", \"type\": \"DefaultValuedAttr<I32Attr, 42>\" },\n      { \"name\": \"more_attr\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.match_op_attribute2\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.match_op_attribute3\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.match_op_attribute4\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"UnitAttr\" },\n      { \"name\": \"attr2\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.merge_blocks\",\n    \"summary\": \"merge_blocks operation\",\n    \"description\": \"Test op with multiple blocks that are merged with Dialect Conversion\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_normal_variadic_operand\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"input2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_normal_variadic_result\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"output2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in_out_i32\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in1\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"F32\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in2\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"F32\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in3\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in4\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in5\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" },\n      { \"name\": \"input3\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" },\n      { \"name\": \"pattern_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_in6\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_optional_in7\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_out1\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"output2\", \"type\": \"F32\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_out2\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"output2\", \"type\": \"F32\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.mixed_variadic_out3\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.multi_slot_alloca\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MemRefOf<[ I32 ]>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.multi_tensor_rank_of\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"TensorRankOf<[I8, I32, F32], [0, 1]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call1\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"choice\", \"type\": \"BoolAttr\" },\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call2\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call3\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call4\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call5\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call6\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.native_code_call7\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.nd_tensor_of\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"0DTensorOf<[F32]>\" },\n      { \"name\": \"arg1\", \"type\": \"1DTensorOf<[F32]>\" },\n      { \"name\": \"arg2\", \"type\": \"2DTensorOf<[I16]>\" },\n      { \"name\": \"arg3\", \"type\": \"3DTensorOf<[I16]>\" },\n      { \"name\": \"arg4\", \"type\": \"4DTensorOf<[I16]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.nested_tuple_32_bit\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"NestedTupleOf<[I32, F32]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.never_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can never be\\n    speculatively executed.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.no_str_value\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"DefaultValuedAttr<StrAttr, >\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.non_negative_int_attr\",\n    \"attributes\": [\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.nvvm_requires_sm_80\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.nvvm_requires_sm_90a\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.nvvm_requires_sm_90a_or_sm_100a\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.oilist_allowed_literal\",\n    \"assemblyFormat\": \"oilist( `foo` | `bar` ) `buzz` attr-dict\"\n  },\n  {\n    \"name\": \"test.oilist_custom\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"optOperand\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nowait\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist( `private` `(` $arg0 `:` type($arg0) `)`\\n          | `reduction` custom<CustomOptionalOperand>($optOperand)\\n          | `nowait` $nowait\\n    ) attr-dict\"\n  },\n  {\n    \"name\": \"test.oilist_variadic_with_parens\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"arg1\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"arg2\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist( `keyword` `(` $arg0 `:` type($arg0) `)`\\n          | `otherKeyword` `(` $arg1 `:` type($arg1) `)`\\n          | `thirdKeyword` `(` $arg2 `:` type($arg2) `)`) attr-dict\"\n  },\n  {\n    \"name\": \"test.oilist_with_keywords_only\",\n    \"attributes\": [\n      { \"name\": \"keyword\", \"type\": \"UnitAttr\" },\n      { \"name\": \"otherKeyword\", \"type\": \"UnitAttr\" },\n      { \"name\": \"diffNameUnitAttrKeyword\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"oilist( `keyword` $keyword\\n          | `otherKeyword` $otherKeyword\\n          | `thirdKeyword` $diffNameUnitAttrKeyword) attr-dict\"\n  },\n  {\n    \"name\": \"test.oilist_with_keywords_only_properties\",\n    \"attributes\": [\n      { \"name\": \"keyword\", \"type\": \"UnitProp\" },\n      { \"name\": \"otherKeyword\", \"type\": \"UnitProp\" },\n      { \"name\": \"diffNameUnitPropKeyword\", \"type\": \"UnitProp\" }\n    ],\n    \"assemblyFormat\": \"oilist( `keyword` $keyword\\n          | `otherKeyword` $otherKeyword\\n          | `thirdKeyword` $diffNameUnitPropKeyword) attr-dict\"\n  },\n  {\n    \"name\": \"test.oilist_with_simple_args\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"arg1\", \"type\": \"Optional<AnyType>\" },\n      { \"name\": \"arg2\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"oilist( `keyword` $arg0 `:` type($arg0)\\n          | `otherKeyword` $arg1 `:` type($arg1)\\n          | `thirdKeyword` $arg2 `:` type($arg2) ) attr-dict\"\n  },\n  {\n    \"name\": \"test.one_i32_out\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_region_with_operands_op\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_region_with_recursive_memory_effects\",\n    \"description\": \"Op that has one region and recursive side effects. The\\n    RegionBranchOpInterface is not implemented on this op.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_result1\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_result2\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_result3\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_to_two\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"result1\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_variadic_out_one_variadic_in1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.one_variadic_out_one_variadic_in2\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_a\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_b\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_c\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_commutative\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" },\n      { \"name\": \"op3\", \"type\": \"I32\" },\n      { \"name\": \"op4\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_commutative2\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_crash_long\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_crash_short\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_d\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_e\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_f\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_funcref\",\n    \"summary\": \"Test op with a reference to a function symbol\",\n    \"description\": \"The \\\"test.op_funcref\\\" is a test op with a reference to a function symbol.\"\n  },\n  {\n    \"name\": \"test.op_g\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_idempotent_trait\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_idempotent_trait_binary\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_in_place_fold\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_in_place_fold_anchor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_in_place_fold_success\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<I1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_in_place_self_fold\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"folded\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_involution_trait_failing_operation_fold\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_involution_trait_no_operation_fold\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_involution_trait_succesful_operation_fold\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_j\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_k\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_large_commutative\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" },\n      { \"name\": \"op3\", \"type\": \"I32\" },\n      { \"name\": \"op4\", \"type\": \"I32\" },\n      { \"name\": \"op5\", \"type\": \"I32\" },\n      { \"name\": \"op6\", \"type\": \"I32\" },\n      { \"name\": \"op7\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_m\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"optional_attr\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_n\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_nonnorm\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"Y\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_norm\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"Y\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_norm_ret\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"Z\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_o\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_optionally_implementing_interface\",\n    \"attributes\": [\n      { \"name\": \"implementsInterface\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_p\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_q\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_r\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_s\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_bit_enum\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestBitEnumAttr{read|write|execute}\" },\n      { \"name\": \"tag\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`tag` $tag^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_bit_enum_prop\",\n    \"attributes\": [\n      { \"name\": \"value1\", \"type\": \"TestBitEnumProp{read|write|execute}\" },\n      { \"name\": \"value2\", \"type\": \"TestBitEnumProp{read|write|execute}\" }\n    ],\n    \"assemblyFormat\": \"$value1 ($value2^)? attr-dict `:` `(``)`\"\n  },\n  {\n    \"name\": \"test.op_with_bit_enum_prop_named\",\n    \"attributes\": [\n      { \"name\": \"value1\", \"type\": \"TestBitEnumPropNamed\" },\n      { \"name\": \"value2\", \"type\": \"TestBitEnumPropNamed\" }\n    ],\n    \"assemblyFormat\": \"$value1 ($value2^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_bit_enum_vbar\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestBitEnumVerticalBarAttr{user|group|other}\" },\n      { \"name\": \"tag\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`tag` $tag^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_data_layout\",\n    \"summary\": \"An op that uses DataLayout implementation from the Target dialect\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_effects_a\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"first\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"second\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"optional_symbol\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_enum\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumAttr{first|second|third}\" },\n      { \"name\": \"tag\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`tag` $tag^)? attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_enum_prop\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumProp{first|second|third}\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_enum_prop_attr_form\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumPropAttrForm{first|second|third}\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_enum_prop_attr_form_always\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumPropAttrFormAlways{first|second|third}\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_infer_type_adaptor_if\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTensor\" },\n      { \"name\": \"y\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_infer_type_if\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_loc_attr\",\n    \"attributes\": [\n      { \"name\": \"loc_attr\", \"type\": \"LocationAttr\" }\n    ],\n    \"assemblyFormat\": \"$loc_attr attr-dict\"\n  },\n  {\n    \"name\": \"test.op_with_memread\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_property_predicates\",\n    \"attributes\": [\n      { \"name\": \"scalar\", \"type\": \"NonNegativeI64Prop\" },\n      { \"name\": \"optional\", \"type\": \"OptionalProp<NonNegativeI64Prop>\" },\n      { \"name\": \"defaulted\", \"type\": \"DefaultValuedProp<NonNegativeI64Prop, 0>\" },\n      { \"name\": \"more_constrained\", \"type\": \"ConfinedProp<NonNegativeI64Prop, CPred<$_self <= 5>, between 0 and 5>\" },\n      { \"name\": \"array\", \"type\": \"ArrayProp<NonNegativeI64Prop>\" },\n      { \"name\": \"non_empty_unconstrained\", \"type\": \"NonEmptyArray<I64Prop>\" },\n      { \"name\": \"non_empty_constrained\", \"type\": \"NonEmptyArray<NonNegativeI64Prop>\" },\n      { \"name\": \"non_empty_optional\", \"type\": \"OptionalProp<NonEmptyArray<NonNegativeI64Prop>>\" },\n      { \"name\": \"unconstrained\", \"type\": \"I64Prop\" }\n    ],\n    \"assemblyFormat\": \"attr-dict prop-dict\"\n  },\n  {\n    \"name\": \"test.op_with_refine_type_if\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_region_fold\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_region_fold_no_side_effect\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_region_pattern\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_result_shape_interface\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_shaped_type_infer_type_adaptor_if\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_shaped_type_infer_type_if\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_with_variadic_results_and_folder\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"test.op_x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"test.op.with_dot_in_name\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.operand_and_result_have_same_element_count_any_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.operand_rank_equals_result_size\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.operand0_and_result_have_same_element_count\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.operand0_and_result_have_same_element_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.operand0_and_result_have_same_rank\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.operand0_and_result_have_same_shape\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.operand0_and_result_have_same_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'res']>\" }\n    ]\n  },\n  {\n    \"name\": \"test.operands_and_result_have_same_rank\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.operands_have_same_element_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.operands_have_same_rank\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"test.operands_have_same_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['x', 'y']>\" }\n    ]\n  },\n  {\n    \"name\": \"test.optional_custom_attr\",\n    \"description\": \"Test using a custom directive as the optional group anchor and the first\\n    element to parse. It is expected to return an `OptionalParseResult`.\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"OptionalAttr<I1Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (custom<OptionalCustomParser>($attr)^) : (`bar`)?\"\n  },\n  {\n    \"name\": \"test.overridden_symbol_visibility\",\n    \"summary\": \"operation overridden symbol visibility accessors\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.parse_b64\",\n    \"attributes\": [\n      { \"name\": \"b64\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.parse_custom_operation_name_api\",\n    \"summary\": \"noop that exercises the parseCustomOperationName API\",\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` custom<CustomOperationNameEntry>($name) `)` attr-dict\"\n  },\n  {\n    \"name\": \"test.parse_example_from_bytes\",\n    \"summary\": \"tfrt_test.parse_example_from_bytes operation\",\n    \"description\": \"The proto.parse_example_from_bytes parses a string into a protobuf object\\n    whose format follows example.proto.\\n\\n    Example:\\n      %example = tfrt_test.parse_example_from_bytes\\\" %bytes\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.parse_integer_literal\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.parse_wrapped_keyword\",\n    \"attributes\": [\n      { \"name\": \"keyword\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.polyfor\",\n    \"summary\": \"polyfor operation\",\n    \"description\": \"Test op with multiple region arguments, each argument of index type.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.positive_int_attr\",\n    \"attributes\": [\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.pretty_printed_region\",\n    \"summary\": \"pretty_printed_region operation\",\n    \"description\": \"Test-op can be printed either in a \\\"pretty\\\" or \\\"non-pretty\\\" way based on\\n    some criteria. The custom parser parsers both the versions while testing\\n    APIs: parseCustomOperationName & parseGenericOperationAfterOpName.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyType\" },\n      { \"name\": \"input2\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.producing_br\",\n    \"operands\": [\n      { \"name\": \"firstOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"secondOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dummy\", \"type\": \"I32\" }\n    ],\n    \"successors\": [\n      { \"name\": \"first\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"second\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.promised_interfaces\",\n    \"operands\": [\n      { \"name\": \"promisedType\", \"type\": \"ConfinedType<AnyType, [HasPromiseOrImplementsTypeInterface<TestExternalTypeInterface>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"promisedAttr\", \"type\": \"ConfinedAttr<AnyAttr, [PromisedAttrInterface<TestExternalAttrInterface>]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.prop\",\n    \"operands\": [\n      { \"name\": \"upperInits\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transforms\", \"type\": \"I32ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.prop_pattern_op_1\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"StringProp\" },\n      { \"name\": \"val\", \"type\": \"I64Prop\" },\n      { \"name\": \"cond\", \"type\": \"BoolProp\" }\n    ],\n    \"assemblyFormat\": \"$tag $val $cond attr-dict\"\n  },\n  {\n    \"name\": \"test.prop_pattern_op_2\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"StringProp\" }\n    ],\n    \"assemblyFormat\": \"$input $tag attr-dict\"\n  },\n  {\n    \"name\": \"test.rank_less_than_2_I8_F32_memref\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"MemRefRankOf<[I8, F32], [0, 1]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.ranked_int_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"vector_i32_attr\", \"type\": \"RankedI32ElementsAttr<[2]>\" },\n      { \"name\": \"matrix_i64_attr\", \"type\": \"RankedI64ElementsAttr<[4, 8]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.ranked_tensor_op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.read_buffer\",\n    \"description\": \"An operation that reads the buffer operand and dumps its contents.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"test.recursive_rewrite\",\n    \"attributes\": [\n      { \"name\": \"depth\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$depth attr-dict\"\n  },\n  {\n    \"name\": \"test.recursively_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can be speculatively\\n    executed only if all the ops in the attached region can be.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.reflect_bounds\",\n    \"description\": \"Integer range analysis will update this op to reflect inferred integer range\\n    of the input, so it can be checked with FileCheck\\n\\n    Example:\\n\\n    ```mlir\\n    CHECK: test.reflect_bounds {smax = 7 : index, smin = 0 : index, umax = 7 : index, umin = 0 : index}\\n    %1 = test.reflect_bounds %0 : index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"umin\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"umax\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"smin\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"smax\", \"type\": \"OptionalAttr<APIntAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($result)\"\n  },\n  {\n    \"name\": \"test.region_buffer_based\",\n    \"description\": \"A buffer based operation, that uses memRefs as input and output.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`\\n    $region attr-dict\"\n  },\n  {\n    \"name\": \"test.region_if\",\n    \"description\": \"Represents an abstract if-then-else-join pattern. In this context, the then\\n    and else regions jump to the join region, which finally returns to its\\n    parent op.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"elseRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"joinRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.region_if_yield\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$results `:` type($results) attr-dict\"\n  },\n  {\n    \"name\": \"test.region_types_compat\",\n    \"operands\": [\n      { \"name\": \"entries\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.region_yield\",\n    \"description\": \"This operation is used in a region and yields the corresponding type for\\n    that operation.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$result `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"test.reify_bound\",\n    \"description\": \"Reify a bound for the given index-typed value or dimension size of a shaped\\n    value. \\\"LB\\\", \\\"EQ\\\" and \\\"UB\\\" bounds are supported. If `scalable` is set,\\n    `vscale_min` and `vscale_max` must be provided, which allows computing\\n    a bound in terms of \\\"vector.vscale\\\" for a given range of vscale.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"type\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"EQ\\\">\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"scalable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"vscale_min\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"vscale_max\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.reify_shaped_type_using_reify_dim_of_result\",\n    \"description\": \"Test that when resolving a single dimension of a result for an operation\\n    that implements `reifyDimOfResult`, which is used to get the required value.\\n    `reifyResultShapes` and `reifyShapeOfResult` are implemented as failures\\n    to ensure they are not called. The op semantics is that the first result has\\n    the same shape as the second operand and the second result has the same shape\\n    as the first operand.\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.reify_shaped_type_using_reify_result_shapes\",\n    \"description\": \"Test that when resolving a single dimension of a result for an operation\\n    that doesnt implement `reifyShapeOfResult` nor implements `reifyDimOfResult`\\n    calls into the implementation of `reifyResultShapes` to get the required value.\\n    The op semantics is that the first result has the same shape as the second operand\\n    and the second result has the same shape as the first operand.\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.reify_shaped_type_using_reify_shape_of_result\",\n    \"description\": \"Test that when resolving a single dimension of a result for an operation\\n    that doesnt implement `reifyDimOfResult` but implements `reifyShapeOfResult`, which\\n    is used to get the required value. `reifyResultShapes` is implemented as a failure\\n    (which is also the default implementation) to ensure it is not called.\\n    The op semantics is that the first result has the same shape as the second operand\\n    and the second result has the same shape as the first operand.\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.remapped_value_region\",\n    \"summary\": \"remapped_value_region operation\",\n    \"description\": \"Test op that remaps values that haven't yet been converted in Dialect\\n    Conversion.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.resize_bilinear\",\n    \"summary\": \"tfrt_test.resize_bilinear operation\",\n    \"description\": \"The tfrt_test.resize_bilinear operation resizes the input tensor based on\\n    the given height and width. It returns a tensor with the same semantics as\\n    tf.compat.v1.image.resize(input, [height, width]).\\n\\n    Example:\\n      %image_resized = tfrt_test.resize_bilinear %image_decoded, %new_height, %new_width\",\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.result_has_same_type_as_attr\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['attr', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$attr `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"test.result_name_from_type\",\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.result_name_from_type_interface\",\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"test.result_type_with_trait\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.return_with_ignored_value\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"unwanted_value\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.rewrite\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.same_operand_and_result_element_type\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"test.same_operand_and_result_shape\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyShaped>\" }\n    ]\n  },\n  {\n    \"name\": \"test.same_operand_and_result_type\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.same_operand_element_type\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.same_operand_result_type\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.side_effect_op\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.side_effect_with_region_op\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`(` $operand`)` $region attr-dict `:`  type($operand)  `->` type($result)\"\n  },\n  {\n    \"name\": \"test.sign\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[SI32]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"test.signless_like_variadic\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"Variadic<SignlessIntegerLike>\" }\n    ]\n  },\n  {\n    \"name\": \"test.single_no_terminator_custom_asm_op\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.single_no_terminator_op\",\n    \"regions\": [\n      { \"name\": \"my_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` $my_region\"\n  },\n  {\n    \"name\": \"test.SingleBlockImplicitTerminator\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.sized_region_op\",\n    \"regions\": [\n      { \"name\": \"my_region\", \"type\": \"SizedRegion<2>\" }\n    ]\n  },\n  {\n    \"name\": \"test.slash_attr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SlashAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.source_op\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"AnyI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.special.op\"\n  },\n  {\n    \"name\": \"test.ssacfg_region\",\n    \"summary\": \"operation with an SSACFG region\",\n    \"description\": \"Test op that defines an SSACFG region.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"test.store_with_a_loop_region\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"store_before_region\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$address attr-dict-with-keyword regions `:` type($address)\"\n  },\n  {\n    \"name\": \"test.store_with_a_region\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"store_before_region\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$address attr-dict-with-keyword regions `:` type($address)\"\n  },\n  {\n    \"name\": \"test.store_with_a_region_terminator\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.string_attr_pretty_name\",\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.string_attr_with_mixed_type\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttrOf<[TypedStrAttr<AnyInteger>, I64Attr]>\" }\n    ],\n    \"assemblyFormat\": \"$attr attr-dict\"\n  },\n  {\n    \"name\": \"test.string_attr_with_type\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedStrAttr<AnyInteger>\" }\n    ],\n    \"assemblyFormat\": \"$attr attr-dict\"\n  },\n  {\n    \"name\": \"test.string_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"scalar_string_attr\", \"type\": \"StringElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.switch_with_no_break\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cases\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"caseRegions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict custom<SwitchCases>($cases, $caseRegions)\"\n  },\n  {\n    \"name\": \"test.symbol\",\n    \"summary\": \"operation which defines a new symbol\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_binding_a\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_binding_b\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_binding_c\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_binding_d\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_binding_no_result\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_scope\",\n    \"summary\": \"operation which defines a new symbol table\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_scope_isolated\",\n    \"summary\": \"operation which defines a new symbol table that is IsolatedFromAbove\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_table_region\",\n    \"summary\": \"operation which defines a new symbol table without a restriction on a terminator\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"test.symbol_with_result\",\n    \"summary\": \"invalid symbol operation that produces an SSA result\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.sync_benchmark\",\n    \"summary\": \"synchronous benchmark operation\",\n    \"description\": \"The \\\"tfrt_test.sync_benchmark\\\" operation benchmarks the performance of an\\n     MLIR synchronous region by executing the given MLIR region repeatedly up\\n     to the `duration_secs` seconds or `max_count` times. `num_warmup_runs`\\n     specifies the number of warm up runs to run the given MLIR region before\\n     the benchmark starts.\\n\\n     The target MLIR region can take an arbitrary number of arguments and\\n     should return no value. The arguments for the MLIR region are\\n     provided as the operands of the tfrt_test.sync_benchmark op.\\n\\n     Example:\\n        // Target sync function to benchmark.\\n        func @fibonacci.i32() -> i32 attributes {hex.sync} {\\n          %0 = \\\"hex.constant_s.i32\\\"() {value = 0 : i32} : () -> i32\\n          %1 = \\\"hex.constant_s.i32\\\"() {value = 1 : i32} : () -> i32\\n\\n          %2 = \\\"hex.add_s.i32\\\"(%0, %1) : (i32, i32) -> i32\\n          %3 = \\\"hex.add_s.i32\\\"(%1, %2) : (i32, i32) -> i32\\n          %4 = \\\"hex.add_s.i32\\\"(%2, %3) : (i32, i32) -> i32\\n          %5 = \\\"hex.add_s.i32\\\"(%3, %4) : (i32, i32) -> i32\\n\\n          hex.return\\n        }\\n\\n       tfrt_test.sync_benchmark @fibonacci.i32()\\n           duration_secs = 1, max_count = 100, num_warmup_runs = 10\",\n    \"attributes\": [\n      { \"name\": \"target_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"duration_secs\", \"type\": \"I32Attr\" },\n      { \"name\": \"max_count\", \"type\": \"I32Attr\" },\n      { \"name\": \"num_warmup_runs\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.takes_static_memref\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyStaticShapeMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_0\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_2\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_3\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"resultA\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"resultB\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_4\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_5\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_6\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_build_7\",\n    \"attributes\": [\n      { \"name\": \"attr0\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.tblgen_constant\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.tensor_based\",\n    \"description\": \"A tensor based operation, that uses a tensor as an input and results in a\\n    tensor again.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"`in` `(` $input`:` type($input) `)` `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"test.test_cost\",\n    \"summary\": \"tfrt_test.test_cost\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I64Attr\" },\n      { \"name\": \"_tfrt_cost\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$args attr-dict `:` type($args)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.test_effects_result\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"test.three_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" },\n      { \"name\": \"result3\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"test.tiling_no_dps_op\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"test.tuple_32_bit\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TupleOf<[I32, F32]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.two_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"test.two_to_one\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"test.type_array_attr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"test.type_array_attr_with_default\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<TypeAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"test.type_attr_of\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttrOf<I64>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $type\"\n  },\n  {\n    \"name\": \"test.type_changer\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.type_producer\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.typed_attr\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"attr\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $type `=` custom<AttrElideType>(ref($type), $attr)\"\n  },\n  {\n    \"name\": \"test.types_compat_yield\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($args^ `:` type($args))? attr-dict\"\n  },\n  {\n    \"name\": \"test.unreifiable_dim_of_result_shape\",\n    \"description\": \"Test handling of case where some dimension of the result cannot be\\n    reified. This tests the path when `reifyDimOfResult` is implemented,\\n    and `reifyDimOfResult` with `reifyResultShapes` are implemented as a failure.\\n\\n    Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but\\n    dim 1 of `result` is not reifiable.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.unreifiable_result_shape\",\n    \"description\": \"Test handling of case where some dimension of the result cannot be\\n    reified. This tests the path when `reifyShapeOfResult` is implemented,\\n    but not `reifyDimOfResult` with `reifyResultShapes` implemented as a failure.\\n\\n    Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but\\n    dim 1 of `result` is not reifiable.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.unreifiable_result_shapes\",\n    \"description\": \"Test handling of case where some dimension of the result cannot be\\n    reified. This tests the path when `reifyResultShapes` is implemented.\\n\\n    Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but\\n    dim 1 of `result` is not reifiable.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.using_int_property_with_worse_bytecode\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"IntPropertyWithWorseBytecode\" }\n    ]\n  },\n  {\n    \"name\": \"test.using_property_in_custom\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"IntArrayProp<I64Prop>\" }\n    ],\n    \"assemblyFormat\": \"custom<UsingPropertyInCustom>($prop) attr-dict\"\n  },\n  {\n    \"name\": \"test.using_property_in_custom_and_other\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"IntArrayProp<I64Prop>\" },\n      { \"name\": \"other\", \"type\": \"I64Prop\" }\n    ],\n    \"assemblyFormat\": \"custom<UsingPropertyInCustom>($prop) prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.using_property_ref_in_custom\",\n    \"attributes\": [\n      { \"name\": \"first\", \"type\": \"IntProp<int64_t>\" },\n      { \"name\": \"second\", \"type\": \"IntProp<int64_t>\" }\n    ],\n    \"assemblyFormat\": \"custom<IntProperty>($first) `+` custom<SumProperty>($second, ref($first)) attr-dict\"\n  },\n  {\n    \"name\": \"test.valid_producer\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"test.value_with_bounds\",\n    \"description\": \"Creates a value with specified [min, max] range for value bounds analysis.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = test.value_with_bounds { min = 4 : index, max = 5 : index}\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"IndexAttr\" },\n      { \"name\": \"max\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"test.variadic_args_types_split\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"str\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$str (`,` $args^)? attr-dict (`:` type($args)^)?\"\n  },\n  {\n    \"name\": \"test.variadic_no_terminator_op\",\n    \"regions\": [\n      { \"name\": \"my_regions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` $my_regions\"\n  },\n  {\n    \"name\": \"test.variadic_region_inferred\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodies\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ]\n  },\n  {\n    \"name\": \"test.variadic_rewrite_dst_op\",\n    \"operands\": [\n      { \"name\": \"brg\", \"type\": \"AnyType\" },\n      { \"name\": \"crg\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"arg\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.variadic_rewrite_src_op\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"brg\", \"type\": \"AnyType\" },\n      { \"name\": \"crg\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"test.variadic_segment_prop\",\n    \"operands\": [\n      { \"name\": \"a1\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"a2\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"b1\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"b2\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$a1 `:` $a2 `:` type($b1) `:` type($b2) prop-dict attr-dict `end`\"\n  },\n  {\n    \"name\": \"test.variadic_with_same_operand_results\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySignlessInteger\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"test.verifiers\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"test.versionedA\",\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"AnyI64Attr\" },\n      { \"name\": \"modifier\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"test.versionedB\",\n    \"attributes\": [\n      { \"name\": \"attribute\", \"type\": \"TestAttrParams\" }\n    ]\n  },\n  {\n    \"name\": \"test.versionedC\",\n    \"attributes\": [\n      { \"name\": \"attribute\", \"type\": \"AnyAttrOf<[TestAttrParams, I32ElementsAttr]>\" }\n    ]\n  },\n  {\n    \"name\": \"test.with_array_properties\",\n    \"attributes\": [\n      { \"name\": \"ints\", \"type\": \"ArrayProp<I64Prop>\" },\n      { \"name\": \"strings\", \"type\": \"ArrayProp<StringProp>\" },\n      { \"name\": \"nested\", \"type\": \"ArrayProp<ArrayProp<I32Prop>>\" },\n      { \"name\": \"opt\", \"type\": \"OptionalProp<ArrayProp<I32Prop>>\" },\n      { \"name\": \"explicitOptions\", \"type\": \"ArrayProp<OptionalProp<I64Prop>>\" },\n      { \"name\": \"explicitUnits\", \"type\": \"ArrayProp<UnitProp>\" },\n      { \"name\": \"hasDefault\", \"type\": \"DefaultValuedProp<ArrayProp<I64Prop>, ::llvm::ArrayRef<int64_t>{}, ::llvm::SmallVector<int64_t>{}>\" }\n    ],\n    \"assemblyFormat\": \"`ints` `=` $ints\\n    `strings` `=` $strings\\n    `nested` `=` $nested\\n    `opt` `=` $opt\\n    `explicitOptions` `=` $explicitOptions\\n    `explicitUnits` `=` $explicitUnits\\n    ($hasDefault^ `thats_has_default`)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.with_bounds\",\n    \"description\": \"Creates a value with specified [min, max] range for integer range analysis.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = test.with_bounds { umin = 4 : index, umax = 5 : index, smin = 4 : index, smax = 5 : index } : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"fakeVal\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"umin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"umax\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smax\", \"type\": \"APIntAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($fakeVal)\"\n  },\n  {\n    \"name\": \"test.with_bounds_region\",\n    \"attributes\": [\n      { \"name\": \"umin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"umax\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smax\", \"type\": \"APIntAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"test.with_default_valued_properties\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"b\", \"type\": \"DefaultValuedProp<StringProp, \\\"\\\">\" },\n      { \"name\": \"c\", \"type\": \"DefaultValuedProp<IntProp<int32_t>, -1>\" },\n      { \"name\": \"unit\", \"type\": \"UnitProp\" }\n    ],\n    \"assemblyFormat\": \"($a^) : (`na`)?\\n    ($b^)?\\n    ($c^)?\\n    ($unit^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.with_nice_properties\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"PropertiesWithCustomPrint\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.with_optional_properties\",\n    \"attributes\": [\n      { \"name\": \"anAttr\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"simple\", \"type\": \"OptionalProp<I64Prop>\" },\n      { \"name\": \"simplei8\", \"type\": \"OptionalProp<IntProp<int8_t>>\" },\n      { \"name\": \"simpleui8\", \"type\": \"OptionalProp<IntProp<uint8_t>>\" },\n      { \"name\": \"nonTrivialStorage\", \"type\": \"OptionalProp<StringProp>\" },\n      { \"name\": \"hasDefault\", \"type\": \"OptionalProp<DefaultValuedProp<I64Prop, 0>>\" },\n      { \"name\": \"nested\", \"type\": \"OptionalProp<OptionalProp<I64Prop>>\" },\n      { \"name\": \"longSyntax\", \"type\": \"OptionalProp<StringProp, 0>\" },\n      { \"name\": \"hasUnit\", \"type\": \"UnitProp\" },\n      { \"name\": \"maybeUnit\", \"type\": \"OptionalProp<UnitProp>\" }\n    ],\n    \"assemblyFormat\": \"(`anAttr` `=` $anAttr^)?\\n    (`simple` `=` $simple^)?\\n    (`simplei8` `=` $simplei8^)?\\n    (`simpleui8` `=` $simpleui8^)?\\n    (`nonTrivialStorage` `=` $nonTrivialStorage^)?\\n    (`hasDefault` `=` $hasDefault^)?\\n    (`nested` `=` $nested^)?\\n    (`longSyntax` `=` $longSyntax^)?\\n    (`hasUnit` $hasUnit^)?\\n    (`maybeUnit` `=` $maybeUnit^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"test.with_properties\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"I64Prop\" },\n      { \"name\": \"b\", \"type\": \"StrAttr\" },\n      { \"name\": \"c\", \"type\": \"StringProp\" },\n      { \"name\": \"flag\", \"type\": \"BoolProp\" },\n      { \"name\": \"array\", \"type\": \"IntArrayProp<I64Prop>\" },\n      { \"name\": \"array32\", \"type\": \"IntArrayProp<I32Prop>\" }\n    ],\n    \"assemblyFormat\": \"`a` `=` $a `,`\\n    `b` `=` $b `,`\\n    `c` `=` $c `,`\\n    `flag` `=` $flag `,`\\n    `array` `=` $array `,`\\n    `array32` `=` $array32 attr-dict\"\n  },\n  {\n    \"name\": \"test.with_properties_and_attr\",\n    \"attributes\": [\n      { \"name\": \"lhs\", \"type\": \"I32Attr\" },\n      { \"name\": \"rhs\", \"type\": \"IntProp<int64_t>\" }\n    ],\n    \"assemblyFormat\": \"$lhs prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.with_properties_and_inferred_type\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs\", \"type\": \"I32Attr\" },\n      { \"name\": \"rhs\", \"type\": \"IntProp<int64_t>\" },\n      { \"name\": \"packed\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.with_versioned_properties\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"VersionedProperties\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.with_wrapped_properties\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"MyStructProperty\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.with_wrapped_properties2\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"MyStructProperty2\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"test.without_bounds\",\n    \"description\": \"Creates a value with uninitialized range for integer range analysis tests.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = test.without_bounds : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"test.wrapping_region\",\n    \"summary\": \"wrapping region operation\",\n    \"description\": \"Test op wrapping another op in a region, to test calling\\n    parseGenericOperation from the custom parser.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_device.cluster\",\n    \"summary\": \"The `tf_device.cluster` op wraps containing operations in a region.\",\n    \"description\": \"This op can be used to group operations, and captures all needed live-in values.\\n\\nOptional policy attribute allows to tag clusters with a policy name that was\\nused to form the cluster.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"policy\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf_device.cluster_func\",\n    \"summary\": \"The `tf_device.cluster_func` launches a function containing the body of a\\ncluster.\",\n    \"description\": \"This op is used for outlining a cluster.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"func\", \"type\": \"FlatSymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf_device.launch\",\n    \"summary\": \"The `tf_device.launch` op launches containing operations on target device.\",\n    \"description\": \"This op captures all needed live-in values.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf_device.launch_func\",\n    \"summary\": \"The `tf_device.launch_func` launches a function on target device.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"func\", \"type\": \"FlatSymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf_device.parallel_execute\",\n    \"description\": \"ParallelExecute op concurrently executes variadic number of regions. Regions\\n    must represent separate sets of instructions to execute concurrently. In\\n    order to represent concurrently executed regions with dependencies, multiple\\n    ParallelExecute ops can be used instead. As so, regions within\\n    ParallelExecute op must not have control/data dependencies.\\n\\n    While explicit dependencies between regions are disallowed, ParallelExecute\\n    op does not prevent implicit communication between regions (e.g.\\n    communication via send/recvs). In this case, users of ParallelExecute op\\n    must provide correct control dependencies between regions to guarantee\\n    correctness. Regions in ParallelExecute may include Resource ops.\\n\\n    In the case where different regions include ops access the same resource,\\n    the users of the ParallelExecute op must provide mechanism (via send/recvs\\n    or via control dependencies) to guarantee correct ordering. Sequential\\n    ordering of ops within a region is guaranteed. Also, sequential ordering of\\n    ops before/after ParallelExecute ops are guaranteed. That is, execution of\\n    regions inside ParallelExecute op is blocked until all inputs to all regions\\n    are materialized and ops following ParallelExecute op are blocked until all\\n    regions are executed.\",\n    \"results\": [\n      { \"name\": \"execute_outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ]\n  },\n  {\n    \"name\": \"tf_device.receive\",\n    \"summary\": \"Rceive a value from a host.\",\n    \"description\": \"Receive a value from the given host with the given rendezvous key.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"src_host\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$key $src_host attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tf_device.remote_run\",\n    \"summary\": \"The `tf_device.remote_run` op launches the containing operations on a specific\\nhost.\",\n    \"description\": \"This op captures all needed live-in values.\",\n    \"operands\": [\n      { \"name\": \"callee_args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"host\", \"type\": \"StrAttr\" },\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$host $callee `(` $callee_args `)` attr-dict `:` functional-type ( $callee_args , $results )\"\n  },\n  {\n    \"name\": \"tf_device.replicate\",\n    \"summary\": \"Wraps an N-way replicated computation.\",\n    \"description\": \"The region held by this operation represents a computation that is replicated\\nacross multiple devices. The number of replications is based on the `n`\\nattribute. Explicit devices can be populated in the `devices` attribute, and it\\nmust be a mapping of device alias to list of explicit or aliased device names\\nfrom the outer scope. The device name map specifies devices on which replicated\\nops inside tf_device.replicate will be executed.\\n\\nA tf_device.parallel_execute inside the tf_device.replicate op region may be\\nused to represent computations across a larger set of devices. In that case, the\\ndevice alias can be used to specify device assignment and replication of each\\nconcurrent execution (i.e. region) defined by tf_device.parallel_execute op.\\nThe size of each value list in the device name map must match `n`. Within a\\nreplica, the execution semantics follow standard sequential behavior. Ops in the\\ntf_device.replicate wrapped with a tf_device.launch will have its device set to\\nthe associated replicated device from `devices` if the tf_device.launch refers\\nto an aliased device name. Otherwise the device already set in tf_device.launch\\nis used instead.\\n\\nOperands are replicated inputs and packed inputs.\\n\\nreplicated_inputs: each group of `n` inputs corresponds to an input for a single\\nindividual replica and is mapped to a single region argument. Inside one group\\nthe operands are matching in order the `devices` attribute. Each replicated\\ninput must have compatible shapes and types.\\npacked_inputs: each input corresponds to an input broadcasted across all\\nreplicas and is mapped to a single region argument.\\n\\nOperands not replicated can be implicitly captured by ops in the region. Results\\nare replicated each from the regions terminator.\\n\\nFor example:\\n```\\n%0 = \\\"tf.opA\\\"() : () -> tensor<i32>\\n%1 = \\\"tf.opB\\\"() : () -> tensor<i32>\\n%2 = \\\"tf.opC\\\"() : () -> tensor<f32>\\n%3 = \\\"tf.opD\\\"() : () -> tensor<f32>\\n%4 = \\\"tf.opE\\\"() : () -> tensor<!tf_type.resource>\\n%5 = \\\"tf.opF\\\"() : () -> tensor<!tf_type.resource>\\n%6 = \\\"tf.opG\\\"() : () -> tensor<!tf_type.string>\\n%7 = \\\"tf.opH\\\"() : () -> tensor<!tf_type.string>\\n%8 = \\\"tf.opI\\\"() : () -> tensor<!tf_type.variant>\\n%9 = \\\"tf.opJ\\\"() : () -> tensor<i1>\\n%output:8 = tf_device.replicate([%0, %1] as %input_0: tensor<i32>,\\n                                [%2, %3] as %input_1: tensor<f32>,\\n                                [%4, %5] as %input_2: tensor<!tf_type.resource>,\\n                                [%6, %7] as %input_3: tensor<!tf_type.string>,\\n                                %8 as %input_4: tensor<!tf_type.variant>)\\n                {n = 2 : i32,\\n                 devices = {DEVICE_ALIAS_0 = [\\\"/DEVICE:0\\\", \\\"/DEVICE:1\\\"],\\n                            DEVICE_ALIAS_1 = [\\\"/DEVICE:2\\\", \\\"/DEVICE:3\\\"]}} {\\n  // Inside the region, %0, %2, %4, and %6 corresponds to\\n  // \\\"/DEVICE:0\\\"/\\\"/DEVICE:2\\\" and %1, %3, %5, and %7 corresponds to\\n  // \\\"/DEVICE:1\\\"/\\\"/DEVICE:3\\\", depending on which device alias is used.\\n  %k = \\\"tf_device.launch\\\"() ( {\\n    %9 = \\\"tf.opK\\\"(%input_0, %input_4, %9) :\\n      (tensor<i32>, tensor<!tf_type.variant>, tensor<i1>) -> tensor<i32>\\n    tf_device.return %9 : tensor<i32>\\n  }) {device = \\\"DEVICE_ALIAS_0\\\"} : () -> tensor<i32>\\n  %l = \\\"tf_device.launch\\\"() ( {\\n    %10 = \\\"tf.opL\\\"(%input_1, %input_4, %9) :\\n      (tensor<f32>, tensor<!tf_type.variant>, tensor<i1>) -> tensor<f32>\\n    tf_device.return %10 : tensor<f32>\\n  }) {device = \\\"DEVICE_ALIAS_1\\\"} : () -> tensor<f32>\\n  %m = \\\"tf_device.launch\\\"() ( {\\n    %11 = \\\"tf.opM\\\"(%input_2, %input_4, %9) :\\n      (tensor<!tf_type.resource>, tensor<!tf_type.variant>, tensor<i1>)\\n        -> tensor<!tf_type.resource>\\n    tf_device.return %11 : tensor<!tf_type.resource>\\n  }) {device = \\\"/DEVICE:4\\\"} : () -> tensor<f32>\\n  %n = \\\"tf.opN\\\"(%input_3, %input_4, %9) :\\n    (tensor<!tf_type.string>, tensor<!tf_type.variant>, tensor<i1>)\\n      -> tensor<!tf_type.string>\\n  tf_device.return %k, %l, %m, %n :\\n    tensor<i32>, tensor<f32>, tensor<!tf_type.resource>, tensor<!tf_type.string>\\n}\\n// %output#0 corresponds to %k returned from \\\"/DEVICE:0\\\"\\n// %output#1 corresponds to %k returned from \\\"/DEVICE:1\\\"\\n// %output#2 corresponds to %l returned from \\\"/DEVICE:2\\\"\\n// %output#3 corresponds to %l returned from \\\"/DEVICE:3\\\"\\n// %output#4, %output#5 corresponds to %m and will be returned from \\\"/DEVICE:4\\\"\\n// %output#6, %output#7 corresponds to %n and will have no device set\\n```\",\n    \"operands\": [\n      { \"name\": \"replicated_inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"packed_inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"replicated_outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"n\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<2>]>\" },\n      { \"name\": \"devices\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_device.return\",\n    \"summary\": \"The `tf_device.return` operation terminates and returns values from a\\n`tf_device` dialect operation.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"tf_device.send\",\n    \"summary\": \"Send a value to a host.\",\n    \"description\": \"Send the value to the given host with the given rendezvous key.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"dst_host\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$value $key $dst_host attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"tf_executor._SwitchN\",\n    \"summary\": \"The \\\"tf_executor._SwitchN\\\" operation takes two inputs, `data` and `index`\\n    and an integer attribute `num_outs` indicating the number of outputs. The\\n    `data` input is copied to output indicated by the `index` input. The other\\n    outputs are marked as dead. If one of the inputs or a control token is\\n    dead, then all of the outputs are marked as dead as well.\",\n    \"description\": \"This is defined in TensorFlow as:\\n\\n    REGISTER_OP(\\\"_SwitchN\\\")\\n        .Input(\\\"data: T\\\")\\n        .Input(\\\"output_index: int32\\\")\\n        .Output(\\\"outputs: num_outs * T\\\")\\n        .Attr(\\\"num_outs: int >= 1\\\")\\n        .Attr(\\\"T: type\\\")\\n        .SetShapeFn(SwitchNShape);\\n\\n    For example:\\n      %2:6 = tf_executor.SwitchN %0, %1 of 5 : tensor<??xf32>\\n\\n    Note: One additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyType\" },\n      { \"name\": \"index\", \"type\": \"TensorOf<[I32]>\" },\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_outs\", \"type\": \"I64Attr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.ControlTrigger\",\n    \"summary\": \"The `tf_executor.ControlTrigger` operation is similar to a no-op except that\\n    it always produces a valid output even when inputs are dead.\",\n    \"description\": \"Its primary use so far is in the scheduling of recvs, where we add\\n    ControlTrigger nodes and use them to trigger recvs. We allow ControlTrigger\\n    nodes to be enabled by dead nodes.\",\n    \"operands\": [\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"assemblyFormat\": \"$controlInputs attr-dict\"\n  },\n  {\n    \"name\": \"tf_executor.Enter\",\n    \"summary\": \"The \\\"tf_executor.Enter\\\" operation forwards its input to Tensorflow while\\n    loop.\",\n    \"description\": \"More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    Each tensor needs its own tf_executor.Enter to be made available inside a\\n    while loop.\\n\\n    This is defined in Tensorflow as:\\n\\n    REGISTER_OP(\\\"Enter\\\")\\n       .Input(\\\"data: T\\\")\\n       .Output(\\\"output: T\\\")\\n       .Attr(\\\"T: type\\\")\\n       .Attr(\\\"frame_name: string\\\")\\n       .Attr(\\\"is_constant: bool = false\\\")\\n       .Attr(\\\"parallel_iterations: int = 10\\\")\\n\\n    For example:\\n       %res:2 = tf_executor.Enter %arg0 frame \\\"some/frame\\\" parallel_iterations 42 constant : tensor<*xf32>\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyType\" },\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"frame_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"is_constant\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"parallel_iterations\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 10>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.Exit\",\n    \"summary\": \"The \\\"tf_executor.Exit\\\" operation forwards a value from an while loop to its\\n    consumer outside of loop. Each returned tensor needs its own\\n    tf_executor.Exit.\",\n    \"description\": \"More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    This is defined in Tensorflow as:\\n\\n    REGISTER_OP(\\\"Exit\\\")\\n       .Input(\\\"data: T\\\")\\n       .Output(\\\"output: T\\\")\\n       .Attr(\\\"T: type\\\")\\n\\n    For example:\\n     %1:2 = tf_executor.Exit %0#0 : tensor<*xi32> {T: \\\"tfdtype$DT_INT32\\\"}\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyType\" },\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.fetch\",\n    \"summary\": \"The `tf_executor.fetch` operation terminates the graph and returns values;\",\n    \"description\": \"The non-control operands of the fetch operation are returned outside of the\\n    graph and must match the return type of the graph.\",\n    \"operands\": [\n      { \"name\": \"fetches\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($fetches^ `:` type($fetches))? attr-dict\"\n  },\n  {\n    \"name\": \"tf_executor.graph\",\n    \"summary\": \"The `tf_executor.graph` operation contains a region with a\\n    single block that lists the operations in a TensorFlow graph.\",\n    \"description\": \"The operations are topologically sorted in-order (no cycles are allowed in\\n    the values). The execution model for operations in this block follows the\\n    TensorFlow executor semantics:\\n      1. Operations that don’t have any transitive dependencies through the\\n         def/use chains may be executed in parallel\\n         (`tf_executor.NextIteration.Source` is the exception).\\n      2. SSA values in this block can be implicitly dead. This means that every\\n         SSA value defined in a `tf_executor.graph` can be considered implicitly\\n         wrapped in a conceptual `dead_or<T>` structure, and includes a runtime\\n         flag indicating if the value is dead or present.\\n      3. Operations may have special case handling of dead values.\\n\\n    The `tf_executor.graph` op only allows specific `tf_executor` dialect\\n    operations in its body: the `tf_executor.graph` verifier will reject any\\n    unknown operation. In order to execute standard `tf` dialect operations\\n    (like `tf.Add`) they must be wrapped in the `tf_executor.island` operation.\\n\\n    The `tf_executor.graph` operation does not accept any operands, inputs are\\n    implicitly captured by the region, representing the feeds to the graph.\\n\\n    The region attached to `tf_executor.graph` is terminated by a\\n    `tf_executor.fetch` operation. The operands of the terminator correspond to\\n    the result values (or fetches) of the `tf_executor.graph` operation. The\\n    behavior is undefined if any of the operands of the `tf_executor.fetch` is\\n    dead.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.island\",\n    \"summary\": \"The `tf_executor.island` operation is a wrapper for operations in other\\n    dialects to be nested in a `tf_executor.graph`.\",\n    \"description\": \"The `tf_executor.graph` operation does not allow `tf` dialect operations to\\n    be immediately nested underneath it. The `tf_executor.island` is introduced\\n    as a wrapper for `tf` dialect operations: this results in a more consistent\\n    representation which makes analysis and transformation simpler.\\n    The `tf_executor.island` operation has a single region with a single block\\n    attached (only functional control flow is allowed). The block is terminated\\n    by a `tf_executor.yield` operation. The operands of the terminator\\n    correspond to the result values of the `tf_executor.island` operation. An\\n    extra result of type `!tf_executor.control` is always produced by every\\n    `tf_executor.island`.\\n    Within an island, execution semantics follow standard sequential behavior as\\n    expected by TF2 and by compiler analyses and transformations, and values\\n    can’t be dead. Other nested `tf_executor.graph` operations can be present in\\n    the region to re-enable the TensorFlow executor for a subsection of the\\n    code.\\n     - Initially the functional control flow operations are calling functions\\n       involving graphs, if `tf_executor.graph` weren’t allowed in an island,\\n       these operations would need to have an equivalent in the `tf_executor`\\n       dialect to be modelled in a graph.\\n     - Nesting also allows forming islands without involving inter-procedural\\n       analyses: any function call may involve a callee with a graph.\\n    The `tf_executor.island` region allows implicit capture. If any value\\n    captured by a `tf_executor.island` is dead, the whole region does not\\n    execute and every produced value is marked as dead as well.\\n    An arbitrary number of `tf_executor.control` operands are accepted by a\\n    `tf_executor.island` operation.\\n    If any operand or implicitly captured value are dead, the region is not\\n    executed and dead values are immediately returned for every result.\",\n    \"operands\": [\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.LoopCond\",\n    \"summary\": \"The \\\"tf_executor.LoopCond\\\" operation forwards a boolean value as loop\\n    condition of Tensorflow while loops.\",\n    \"description\": \"More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    This is defined in Tensorflow as:\\n\\n    REGISTER_OP(\\\"LoopCond\\\")\\n       .Input(\\\"input: bool\\\")\\n       .Output(\\\"output: bool\\\")\\n\\n    For example:\\n      %5:2 = tf_executor.LoopCond %4#0 {name: \\\"while/LoopCond\\\"}\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.Merge\",\n    \"summary\": \"The \\\"tf_executor.Merge\\\" operation takes a list of input operands and returns\\n    a value of the operand type along with the index of the first match encountered.\",\n    \"description\": \"More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    This is defined in TensorFlow as:\\n\\n    REGISTER_OP(\\\"Merge\\\")\\n       .Input(\\\"inputs: N * T\\\")\\n       .Output(\\\"output: T\\\")\\n       .Output(\\\"value_index: int32\\\")\\n\\n    For example:\\n      %2 = tf_executor.Merge %0, %1, %2, %3 : tensor<*xf32>\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"inputs_and_control\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"value_index\", \"type\": \"TensorOf<[I32]>\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.NextIteration.Sink\",\n    \"summary\": \"The \\\"tf_executor.NextIteration.Sink\\\" is paired with a\\n    \\\"tf_executor.NextIteration.source\\\" to represent NextIteration op in\\n    Tensorflow.\",\n    \"description\": \"Tensorflow NextIteration operation forwards its input to the next iteration\\n    of a while loop. Each loop variable needs its own NextIteration op.\\n\\n    More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    In the TF executor dialect, the NextIteration op is broken into\\n    tf_executor.NextIteration.sink and tf_executor.NextIteration.source because\\n    NextIteration is a back-edge in Tensorflow graph, which would form a data\\n    flow cycle if expressed naively in a basic block.\\n    tf_executor.NextIteration.source takes no input but returns results while\\n    tf_executor.NextIteration.sink takes input but doesn't return anything. When\\n    optimizing these ops, they are paired by token and considered as a single\\n    op.\\n\\n    This is defined in Tensorflow as:\\n\\n    REGISTER_OP(\\\"NextIteration\\\")\\n       .Input(\\\"data: T\\\")\\n       .Output(\\\"output: T\\\")\\n       .Attr(\\\"T: type\\\")\\n\\n    For example:\\n      %value, %token, %ctl = tf_executor.NextIteration.Source : tensor<*xi32>\\n      tf_executor.NextIteration.sink [%token] (%value) : tensor<*xi32>\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"TfeTokenType\" },\n      { \"name\": \"input\", \"type\": \"AnyType\" },\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"assemblyFormat\": \"`[` $token `]` $input (`,` $controlInputs^)? `:` type($input) attr-dict\"\n  },\n  {\n    \"name\": \"tf_executor.NextIteration.Source\",\n    \"summary\": \"The \\\"tf_executor.NextIteration.Source\\\" is paired with a\\n    \\\"tf_executor.NextIteration.sink\\\" to represent NextIteration op in\\n    Tensorflow.\",\n    \"description\": \"Tensorflow NextIteration operation forwards its input to the next iteration\\n    of a while loop. Each loop variable needs its own NextIteration op.\\n\\n    More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    In the TF executor dialect, the NextIteration op is broken into\\n    tf_executor.NextIteration.sink and tf_executor.NextIteration.source because\\n    NextIteration is a back-edge in Tensorflow graph, which would form a data\\n    flow cycle if expressed naively in a basic block.\\n    tf_executor.NextIteration.source takes no input but returns results while\\n    tf_executor.NextIteration.sink takes input but doesn't return anything. When\\n    optimizing these ops, they are paired by token and considered as a single\\n    op.\\n\\n    This is defined in Tensorflow as:\\n\\n    REGISTER_OP(\\\"NextIteration\\\")\\n       .Input(\\\"data: T\\\")\\n       .Output(\\\"output: T\\\")\\n       .Attr(\\\"T: type\\\")\\n\\n    For example:\\n      %value, %token, %ctl = tf_executor.NextIteration.Source : tensor<*xi32>\\n      tf_executor.NextIteration.sink [%token] (%value) : tensor<*xi32>\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyType\" },\n      { \"name\": \"token\", \"type\": \"TfeTokenType\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"assemblyFormat\": \"`:` type($output) attr-dict\"\n  },\n  {\n    \"name\": \"tf_executor.Switch\",\n    \"summary\": \"The \\\"tf_executor.Switch\\\" operation takes a data operand and a boolean\\n    predicate condition, and returns two values matching the type of the data\\n    predicate.\",\n    \"description\": \"More details can be found in Tensorflow Control Flow white paper:\\n    https://storage.googleapis.com/download.tensorflow.org/paper/white_paper_tf_control_flow_implementation_2017_11_1.pdf\\n\\n    This is defined in TensorFlow as:\\n\\n    REGISTER_OP(\\\"Switch\\\")\\n       .Input(\\\"data: T\\\")\\n       .Input(\\\"pred: bool\\\")\\n       .Output(\\\"output_false: T\\\")\\n       .Output(\\\"output_true: T\\\")\\n\\n    For example:\\n      %2 = tf_executor.Switch %0, %1 : tensor<*xf32>\\n\\n    Note: Additional result corresponds to the control output.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyType\" },\n      { \"name\": \"predicate\", \"type\": \"TensorOf<[I1]>\" },\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TfeControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"falseOutput\", \"type\": \"AnyType\" },\n      { \"name\": \"trueOutput\", \"type\": \"AnyType\" },\n      { \"name\": \"control\", \"type\": \"TfeControlType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tf_executor.yield\",\n    \"summary\": \"The `tf_executor.yield` operation terminates and returns values for the\\n    `tf_executor.island` operation.\",\n    \"operands\": [\n      { \"name\": \"fetches\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($fetches^ `:` type($fetches))? attr-dict\"\n  },\n  {\n    \"name\": \"tf_framework.alloc\",\n    \"summary\": \"allocation of tensors that uses TF Framework\",\n    \"description\": \"Allocation of tensors during kernel execution in the Compute method.\\n\\n    This should be used to allocate any temporary or output memref. If\\n    `output_index` and `input_indices` are given, attempts to forward one of\\n    the input tensors to the output by calling `OpKernelContext::forward_input`.\\n\\n    If the attributes are missing or the forwarding fails, calls\\n    `Allocator::AllocateRaw` in tensorflow/core/framework/allocator.h.\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"TFFramework_OpKernelContextType\" },\n      { \"name\": \"dyn_sizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_indices\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"output_index\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $ctx (`,` $dyn_sizes^ )? `)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tf_framework.assert\",\n    \"summary\": \"Assert operation with message attribute and error code\",\n    \"description\": \"Assert operation that propagates the error message to TF Framework.\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"TFFramework_OpKernelContextType\" },\n      { \"name\": \"arg\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"error_code\", \"type\": \"TFFramework_ErrorCodeAttr{OK|CANCELLED|UNKNOWN|INVALID_ARGUMENT|DEADLINE_EXCEEDED|NOT_FOUND|ALREADY_EXISTS|PERMISSION_DENIED|UNAUTHENTICATED|RESOURCE_EXHAUSTED|FAILED_PRECONDITION|ABORTED|OUT_OF_RANGE|UNIMPLEMENTED|INTERNAL|UNAVAILABLE|DATA_LOSS}\" },\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$ctx `,` $arg `,` $error_code `,` $msg attr-dict\"\n  },\n  {\n    \"name\": \"tf_framework.dealloc\",\n    \"summary\": \"deallocation of tensors that uses TF Framework\",\n    \"description\": \"Deallocation of tensors during kernel execution in the Compute method.\\n\\n    This should be used to deallocate any temporary memref that was allocated\\n    with `tf_framework.alloc`.\\n    Corresponds to `Allocator::DeallocateRaw` in\\n    tensorflow/core/framework/allocator.h.\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"TFFramework_OpKernelContextType\" },\n      { \"name\": \"memref\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"`(` $ctx `,` $memref `)` attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"tf_framework.is_valid_memref\",\n    \"summary\": \"Op to check if the memref is valid.\",\n    \"description\": \"The op checks if the allocation was successful so that the underlying ptr\\n    in the descriptor is not equal to NULL. Also, we check if the number of\\n    elements is not zero to support empty shapes inputs correctly.\\n\\n    is_valid_memref(memref) = ptr(memref) != NULL || num_elements(memref) == 0\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`(` $arg `)` attr-dict `:` type($arg) `->` type($result)\"\n  },\n  {\n    \"name\": \"tf_framework.jit_compile\",\n    \"summary\": \"Invokes JIT compilation through the TF framework\",\n    \"description\": \"The op takes an optional TF context, so that it can be added at a later\\n    stage in the compilation pipeline. The op's body corresponds to a function\\n    body and the corresponding `tf_framework.jit_compile_yield` represents the\\n    result value(s).\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"Optional<TFFramework_OpKernelContextType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFFramework_JITCallableType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$ctx $body attr-dict\"\n  },\n  {\n    \"name\": \"tf_framework.jit_compile_from_str\",\n    \"summary\": \"Invokes JIT compilation through the TF framework\",\n    \"description\": \"This operation is similar to `tf_framework.jit_compile`. Instead of a body,\\n    the to-be-compiled function is represented as a string attribute. The string\\n    shall be the serialized form of a module with a single function named\\n    `main`.\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"Optional<TFFramework_OpKernelContextType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFFramework_JITCallableType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"code\", \"type\": \"StrAttr\" },\n      { \"name\": \"tileSizes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"unrollFactors\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"enableFtz\", \"type\": \"BoolAttr\" },\n      { \"name\": \"index64Bit\", \"type\": \"BoolAttr\" },\n      { \"name\": \"cpuCodegen\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"($ctx^ `,`)? $code attr-dict\"\n  },\n  {\n    \"name\": \"tf_framework.jit_compile_yield\",\n    \"summary\": \"Yields the results in a `tf_framework.jit_compile` op's body\",\n    \"description\": \"See `tf_framework.jit_compile`.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[AnyRankedOrUnrankedMemRef, AnyTensor]>\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tf_framework.jit_execute\",\n    \"summary\": \"Executes a JIT-compiled function through the TF framework\",\n    \"description\": \"The op takes an optional TF context, so that it can be added at a later\\n    stage in the compilation pipeline. The callable must be a JIT-compiled\\n    function that is the result of either `tf_framework.jit_compile` or\\n    `tf_framework.jit_compile_from_str`. The remaining operands must be tensor\\n    or memref arguments and will be forwarded to the callable function. The\\n    result types must match those of the callable function. Otherwise, the\\n    execution behavior is undefined.\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"Optional<TFFramework_OpKernelContextType>\" },\n      { \"name\": \"callable\", \"type\": \"TFFramework_JITCallableType\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyRankedOrUnrankedMemRef, AnyTensor ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[ AnyRankedOrUnrankedMemRef, AnyTensor ]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`ctx` `(` $ctx^ `)`)? $callable `(` $inputs `)` attr-dict\\n        `:` type($inputs) `->` type($result)\"\n  },\n  {\n    \"name\": \"tf_framework.null_context\",\n    \"summary\": \"Creates a fake TF context that will be lowered to nullptr\",\n    \"description\": \"Needed for testing\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFFramework_OpKernelContextType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tf_framework.null_memref\",\n    \"summary\": \"Op to construct unranked memref with 0-rank\",\n    \"description\": \"The op is needed to construct a throw-away result after error reporting\\n    happened. It constructs a ranked memref descriptor with 0-rank and\\n    {NULL, NULL, 0} underlying ranked descriptor of type memref<elem_type>.\\n    In ranked case it constructs a ranked memref descriptor depending on the\\n    result type, but sets both allocated and aligned pointers to NULL.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tf_framework.report_error\",\n    \"summary\": \"Operation that propagates error message to TF Framework\",\n    \"description\": \"Error reporting operation that corresponds to\\n    `OpKernelContext::CtxFailureWithWarning`.\",\n    \"operands\": [\n      { \"name\": \"ctx\", \"type\": \"TFFramework_OpKernelContextType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"error_code\", \"type\": \"TFFramework_ErrorCodeAttr{OK|CANCELLED|UNKNOWN|INVALID_ARGUMENT|DEADLINE_EXCEEDED|NOT_FOUND|ALREADY_EXISTS|PERMISSION_DENIED|UNAUTHENTICATED|RESOURCE_EXHAUSTED|FAILED_PRECONDITION|ABORTED|OUT_OF_RANGE|UNIMPLEMENTED|INTERNAL|UNAVAILABLE|DATA_LOSS}\" },\n      { \"name\": \"msg\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$ctx `,` $error_code `,` $msg attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.allocate_futures\",\n    \"summary\": \"Allocate futures and promsies for tensorflow tensors\",\n    \"description\": \"Allocate futures and promsies for tensorflow tensors.\\n\\n    $num_futures: The number of futures to be allocated.\\n\\n    $promises: There are $num_futures promises. promises[i] shares the state with futures[i].\\n    $futures: There are $num_futures futures. futures[i] shares the state with promises[i].\",\n    \"results\": [\n      { \"name\": \"promises\", \"type\": \"Variadic<MlrtPromiseType>\" },\n      { \"name\": \"futures\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_futures\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"tf_mlrt.async_executeop\",\n    \"summary\": \"The Fallback ExecuteOp for tensorflow::AsyncOpKernel\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device asynchronously.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` attr-dict `:` functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.async_executeop.device\",\n    \"summary\": \"The Fallback ExecuteOp for tensorflow::AsyncOpKernel\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device asynchronously.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TFDeviceType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $device`)` `(` $args `)` attr-dict `:` functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.async_while\",\n    \"summary\": \"Asynchronously execution of while op for tf_mlrt\",\n    \"description\": \"cond: The boolean to control whether the first iteration should be executed.\\n    arguments: the last $immutable_size elements are invariants between iterations.\\n    results: a list of futures.\\n    body_fn: its input are [predicate_promise, arg0_future, arg0_promise, arg1_future, arg1_promise, ..., invariant_args] and has no returned results.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TFTensorType\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"body_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"invariant_size\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$body_fn `(` $cond `,` $arguments `)` attr-dict `:` `(` type($cond) `,` type($arguments) `)` `->` `(` type(results) `)`\"\n  },\n  {\n    \"name\": \"tf_mlrt.await\",\n    \"summary\": \"Await a tensor from a !mlrt.future\",\n    \"description\": \"Await a tensor from a !mlrt.future.\\n\\n    $future: A value of type !mlrt.future. The underlying value must be a tensorflow tensor.\\n\\n    $result: a tensorflow tensor.\",\n    \"operands\": [\n      { \"name\": \"future\", \"type\": \"MlrtFutureType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.await_all\",\n    \"summary\": \"Await tensors from a list of !mlrt.future\",\n    \"description\": \"Await tensors from a list of !mlrt.future.\\n\\n    $futures: A list of !mlrt.future. The underlying value must be tensorflow tensors.\\n\\n    $results: A list of tensorflow tensors.\",\n    \"operands\": [\n      { \"name\": \"futures\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$futures attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.batch_function\",\n    \"summary\": \"Fallback ExecuteOp specialized for tf.BatchFunction.\",\n    \"description\": \"This kernel executes a variant tf.BatchFunction kernel that supports having\\n    the `f` attribute as a bytecode function.\\n\\n    Example:\\n      %res = tf_mlrt.batch_function(%input, %captured_input)  {\\n          device = \\\"/device:CPU:0\\\",\\n          f = @batch_function,\\n          node_def = \\\"...\\\"\\n        } : (!tf_mlrt.tensor,!tf_mlrt.tensor) -> (!tf_mlrt.tensor)\\n\\n    Note that the trailing number indicates the number of results.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` attr-dict `:` functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.batch_function.device\",\n    \"summary\": \"Fallback ExecuteOp specialized for tf.BatchFunction with custom device.\",\n    \"description\": \"This kernel executes a variant tf.BatchFunction kernel that supports having\\n    the `f` attribute as a bytecode function with a custom device.\\n\\n    Example:\\n      %res = tf_mlrt.batch_function.device(%custom_device, %input, %captured_input)  {\\n          device = \\\"/device:CPU:0\\\",\\n          f = @batch_function,\\n          node_def = \\\"...\\\"\\n        } : (!tf_mlrt.tensor,!tf_mlrt.tensor) -> (!tf_mlrt.tensor)\\n\\n    Note that the trailing number indicates the number of results.\\n    Also note that the custom device argument is not the same as the device attribute. \\n    The latter is just the name in which the enclosure graph is executed.\",\n    \"operands\": [\n      { \"name\": \"custom_device\", \"type\": \"TFDeviceType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MlrtFutureType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $custom_device`)` `(` $args `)` attr-dict `:` functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.bool_to_tensor\",\n    \"summary\": \"Cast a boolean to a tensor.\",\n    \"description\": \"Cast a boolean to a tensor.\\n\\n    Example:\\n      %one = tf_mlrt.bool_to_tensor %src_bool\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.cancel\",\n    \"summary\": \"Handle cancellation request.\",\n    \"description\": \"This kernel will early terminate the program upon cancellation request (e.g. time out).\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"tf_mlrt.constop\",\n    \"summary\": \"The tf_mlrt ConstOp\",\n    \"description\": \"The ConstOp creates a constant tensorflow::Tensor from serialized proto.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_proto\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.createop\",\n    \"summary\": \"The Fallback CreateOp\",\n    \"description\": \"The CreateOp creates the tensorflow::OpKernel in the fallback context.\",\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.executeop\",\n    \"summary\": \"The Fallback ExecuteOp\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `)` attr-dict `:` functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.executeop.device\",\n    \"summary\": \"The Fallback ExecuteOp with custom device\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device using a custom device.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TFDeviceType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(` $device`)` `(` $args `)` attr-dict `:` functional-type($args, $results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.get_resource\",\n    \"summary\": \"get a tensor in resource array\",\n    \"description\": \"Get a tensor in resource array.\\n\\n    indices: the indices in the resource array.\\n    results: the tensor values for the corresponding indices.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.ifrt_load_variable\",\n    \"summary\": \"Loads a variable tensor as an IFRT array for mlrt\",\n    \"description\": \"This op loads a restored variable tensor as a tensor future. It is a\\n    replacement of `tf.ReadVariableOp`.\\n\\n    This op returns a scalar string tensor containing the restored variable name, which can be\\n    used as a key within the runtime, as well as a future for the tensor.\\n\\n    The `tf.IfrtCall` kernel uses the output $array_key.\\n    Other ops executed by TFRT may make use of $tensor_future.\",\n    \"operands\": [\n      { \"name\": \"variable\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"array_key\", \"type\": \"TFTensorType\" },\n      { \"name\": \"tensor_future\", \"type\": \"MlrtFutureType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"used_by_host\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"tf_mlrt.ifrt_resource_deserialize\",\n    \"summary\": \"Deserialize resource vars.\",\n    \"description\": \"This is the MLRT version of the IfrtResourceDeserialize op.\",\n    \"operands\": [\n      { \"name\": \"resource_var\", \"type\": \"TFTensorType\" },\n      { \"name\": \"input_dir\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"tf_mlrt.ifrt_restore_variable\",\n    \"summary\": \"Restore variable tensors\",\n    \"description\": \"This is the MLRT version of tf.IfrtRestoreVariableOp.\\n\\n    This Op is similar to a combination of RestoreV2 and AssignVariable Op, but\\n    this Op's execution is asynchronous.\\n\\n    This Op is specific to MLRT runtime and is not a stable interface for\\n    serialization.\\n\\n    This Op will restore the tensors asynchronously and allow the runtime to look\\n    for them.\\n    The runtime shall handle the possibility that the tensors are not ready when requested\\n    because the tensors are loaded asynchronously.\",\n    \"operands\": [\n      { \"name\": \"prefix\", \"type\": \"TFTensorType\" },\n      { \"name\": \"tensor_names\", \"type\": \"TFTensorType\" },\n      { \"name\": \"shape_and_slices\", \"type\": \"TFTensorType\" },\n      { \"name\": \"var_handles\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"restored_dtypes\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"truncate_in_cast\", \"type\": \"DenseBoolArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"tf_mlrt.map_fn\",\n    \"summary\": \"The Parallel Map for tf_mlrt dialect\",\n    \"description\": \"The Pmap executes body function in parallel for all ranges up to $max_iterations.\\n\\n    The pseudo code:\\n      for(int i = 0; i < $max_iterations; i++) {\\n        body_fn(MlrtFture($tensor_list_or_flow_in[i]),\\n                MlrtPromise($tensor_list_or_flow_in[i+1]),\\n                i, i, $invariant_args);\\n      }\\n\\n      return $tensor_list_or_flow_in[$max_iterations]\",\n    \"operands\": [\n      { \"name\": \"max_iterations\", \"type\": \"TFTensorType\" },\n      { \"name\": \"tensor_list_or_flow_in\", \"type\": \"Variadic<TFTensorType>\" },\n      { \"name\": \"invariant_args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"body_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"num_tensor_list_or_flow_in\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(`$max_iterations`,` $tensor_list_or_flow_in`,` $invariant_args `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tf_mlrt.predicate\",\n    \"summary\": \"Converts a fallback tensor to a bool\",\n    \"description\": \"Note: this kernel is used for CPU tensors.\\n\\n    Converts a fallback tensor to a bool with the following rules:\\n\\n    - For 0D tensors, truthiness is determined by comparing against a \\\"zero\\\"\\n      value. For numerical types it is the obvious zero. For strings it is the\\n      empty string.\\n\\n    - For >0D tensors, truthiness is determined by looking at the number of\\n      elements. If has zero elements, then the result is false. Otherwise the\\n      result is true.\\n\\n    input: a fallback tensor representing the condition.\\n    device: the name of the tensorflow device that is associated with the\\n      input fallback tensor.\\n\\n    output: the converted bool.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.promise\",\n    \"summary\": \"Set a tensor in a promise\",\n    \"description\": \"Set a tensor in a promise.\\n\\n    $promise: A value of type !mlrt.promise. The underlying value must be a tensorflow tensor.\\n    $tensor: A tensorflow tensor.\",\n    \"operands\": [\n      { \"name\": \"promise\", \"type\": \"MlrtPromiseType\" },\n      { \"name\": \"tensor\", \"type\": \"TFTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.promise_future\",\n    \"summary\": \"Set a tensor future in a promise\",\n    \"description\": \"Set a tensor future in a promise.\\n\\n    $promise: A value of type !mlrt.promise. The underlying value must be a tensorflow tensor.\\n    $future: A value of type !mlrt.future. Must represents a tensorflow tensor.\",\n    \"operands\": [\n      { \"name\": \"promise\", \"type\": \"MlrtPromiseType\" },\n      { \"name\": \"tensor\", \"type\": \"MlrtFutureType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.promise_return\",\n    \"summary\": \"Set a tensor in a promise and return from a function with no output\",\n    \"description\": \"Set a tensor in a promise and return from a function with no output.\\n\\n    $promise: A value of type !mlrt.promise. The underlying value must be a tensorflow tensor.\\n    $tensor: A tensorflow tensor.\",\n    \"operands\": [\n      { \"name\": \"promise\", \"type\": \"MlrtPromiseType\" },\n      { \"name\": \"tensor\", \"type\": \"TFTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.set_resource\",\n    \"summary\": \"Set a tensor in resource array\",\n    \"description\": \"Set a tensor in resource array.\\n\\n    arg: the tensor to be set in the resource array.\\n    index: the index in the resource array\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_mlrt.tensor_to_int32\",\n    \"summary\": \"Cast a Tensor to int32.\",\n    \"description\": \"Cast a Tensor to int32.\\n\\n    Example:\\n      %one = tf_mlrt.tensor_to_int32 %src_tenosr\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tf_saved_model.asset\",\n    \"summary\": \"Represents an asset in saved model.\",\n    \"description\": \"Represents an asset in the saved model that points to an external file. It\\n    is a scalar string tensor and it is passed as an argument to the session\\n    initializer functions.\\n\\n    The `sym_name` represents the symbol table name used for internal IR\\n    references.\\n\\n    The `filename` attribute contains the file path to the asset file and it is\\n    relative to saved model directory.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"filename\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf_saved_model.global_tensor\",\n    \"summary\": \"Represents a global tensor value.\",\n    \"description\": \"Represents a tensor that is not bound to the lifetime of any particular\\n    function. Such tensors can be marked as mutable via the `is_mutable`\\n    attribute.\\n\\n    These tensors are bound to the arguments of func ops via the\\n    `tf_saved_model.bound_input` argument attr.\\n\\n    The `sym_name` represents the symbol table name used for internal IR\\n    references. The externally visible names, if any, are represented via\\n    a `tf_saved_model.exported_names` attribute.\\n\\n    The `value` attribute contains the tensor's value (or initial value, in the\\n    case it is mutable).\\n\\n    The `type` attribute contains the tensor's type, which for the case of\\n    mutable tensors might be more general than just the fixed static shape of\\n    the `value` attribute. For example, a global tensor might be unranked such\\n    as `tensor<*xf32>`, or a more complex shape such as `tensor<4x?x27xf32>`.\\n    The shape of `value` must be compatible with the shape of `type` in the\\n    sense of `tf.TensorShape` compatibility. And the element types must match.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"value\", \"type\": \"OptionalAttr<ElementsAttr>\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf_saved_model.session_initializer\",\n    \"summary\": \"Initializes TensorFlow session state.\",\n    \"description\": \"The session initializer op marks one or more functions that must be called\\n    by an external agent exactly once to initialize TensorFlow session state,\\n    and this must happen before any other exported functions are called. There\\n    must be no more than one session initializer op in a saved model.\\n\\n    The `initializers` represents the initialization functions. The function\\n    have no output and this function should be only called once.\\n\\n    This is used, for example, to initialize hash tables stored in resources and\\n    accessed by resource name (rather than as resource handles or bound inputs\\n    which is how `global_tensor`s are referenced)\",\n    \"attributes\": [\n      { \"name\": \"initializers\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._ArrayToList\",\n    \"summary\": \"Converts an array of tensors to a list of tensors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._EagerConst\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf._FusedBatchNormEx\",\n    \"summary\": \"Internal FusedBatchNorm operation: reserved for internal use.\",\n    \"description\": \"Do not invoke this operator directly in Python. A fusion optimization is\\nexpected to create these operators.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"offset\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mean\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"variance\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"side_input\", \"type\": \"Variadic<TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" },\n      { \"name\": \"batch_mean\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"batch_variance\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_3\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"exponential_avg_factor\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"activation_mode\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"Identity\\\">\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._FusedConv2D\",\n    \"summary\": \"Performs a convolution followed by a specified series of operations.\",\n    \"description\": \"The inputs to the convolution are `input` and `filter`. The series of operations\\nthat follows is specified by the `fused_ops` attribute, which is a list of TF op\\nnames specified as strings (e.g. \\\"Relu\\\"). They are performed in order, where the\\n(first) input to each op is the output of the preceding op. The first input and\\nthe output of each fused_op must be of type T.\\n\\nCurrently supported fused_op combinations are: [X] and [X,A], where X is one of\\n{\\\"BiasAdd\\\",\\\"FusedBatchNorm\\\"} and A is one of {\\\"Elu\\\",\\\"Relu\\\",\\\"Relu6\\\"}.\\n\\n* The first input to op X is the Conv2D result, and the additional input(s) to X\\nare specified by `args`.\\n* If there is an op A specified, the output of op X is the input to op A, and op\\nA produces the _FusedConv2D output. Otherwise, op X produces the _FusedConv2D\\noutput.\\n\\n*NOTE*: Do not invoke this operator directly in Python. Grappler is expected to\\ncreate these operators.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int8, TF_Qint8]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int8, TF_Qint8]>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"host_args\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int8, TF_Qint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_args\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NCHW_VECT_C ]>, \\\"NHWC\\\">\" },\n      { \"name\": \"filter_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ HWIO, OIHW, OIHW_VECT_I ]>, \\\"HWIO\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" },\n      { \"name\": \"use_cudnn_on_gpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"fused_ops\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"leakyrelu_alpha\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.2f>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf._FusedMatMul\",\n    \"summary\": \"Performs a MatMul followed by a specified series of operations.\",\n    \"description\": \"The inputs to the MatMul are specified by `a` and `b`. The series of operations\\nthat follows is specified by the `fused_ops` attribute, which is a list of TF op\\nnames specified as strings (e.g. \\\"Relu\\\"). They are performed in order, where the\\n(first) input to each op is the output of the preceding op. The first input and\\nthe output of each fused_op must be of type T.\\n\\nCurrently supported fused_op combinations are: [\\\"BiasAdd\\\"] and [\\\"BiasAdd\\\",A],\\nwhere A is one of {\\\"Elu\\\",\\\"Relu\\\",\\\"Relu6\\\"}.\\n\\n* The first input to BiasAdd is the MatMul result, and the additional BiasAdd\\ninput is specified by `args`.\\n* If there is an op A specified, the output of the BiasAdd is the input to op A,\\nand op A produces the _FusedConv2D output. Otherwise, the BiasAdd produces the\\n_FusedConv2D output.\\n\\n*NOTE*: Do not invoke this operator directly in Python. Grappler is\\nexpected to create these operators.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" },\n      { \"name\": \"b\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"fused_ops\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"leakyrelu_alpha\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.2f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._HostRecv\",\n    \"summary\": \"Receives the named tensor from send_device on recv_device.\",\n    \"description\": \"_HostRecv produces its output on host memory whereas _Recv produces its\\noutput on device memory.\",\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device_incarnation\", \"type\": \"I64Attr\" },\n      { \"name\": \"recv_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"client_terminated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._HostSend\",\n    \"summary\": \"Sends the named tensor from send_device to recv_device.\",\n    \"description\": \"_HostSend requires its input on host memory whereas _Send requires its\\ninput on device memory.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device_incarnation\", \"type\": \"I64Attr\" },\n      { \"name\": \"recv_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"client_terminated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._InternalTestMustExecuteTrait_\",\n    \"summary\": \"Internal op for testing only\"\n  },\n  {\n    \"name\": \"tf._InternalTestNonResourceValueSideEffects_\",\n    \"summary\": \"Internal op for testing only\",\n    \"operands\": [\n      { \"name\": \"key\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf._ListToArray\",\n    \"summary\": \"Converts a list of tensors to an array of tensors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._Recv\",\n    \"summary\": \"Receives the named tensor from send_device on recv_device.\",\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device_incarnation\", \"type\": \"I64Attr\" },\n      { \"name\": \"recv_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"client_terminated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._Send\",\n    \"summary\": \"Sends the named tensor from send_device to recv_device.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device_incarnation\", \"type\": \"I64Attr\" },\n      { \"name\": \"recv_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"client_terminated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._TfrtGetResource\",\n    \"summary\": \"Get values from TFRT runtime's static resource.\",\n    \"description\": \"Getting tensor values from TFRT runtime's static resource manager, using\\n    the indices that are previously set in _TfrtSetResource op.\\n    `shared_name` and `container` are used to store identifying information for\\n    resource tensors that have been hoisted. This is important for resource\\n    alias analysis and side effect analysis. These are empty for non-resource\\n    type tensors.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"shared_name\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"container\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._TfrtSetResource\",\n    \"summary\": \"Set values as TFRT runtime's static resource.\",\n    \"description\": \"Setting a tensor value in TFRT runtime's static resource manager, using\\n    index as its identifier. It can be retrieved by _TfrtGetResource using the\\n    same index.\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf._TPUCompileMlir\",\n    \"summary\": \"Compiles a computations for execution on one or more TPU devices.\",\n    \"description\": \"For the internal use of the distributed TPU compiler.\\n\\n'mlir_module' is a serialized MLIR module with a `main` function that contains\\ntarget computation.\\n'dynamic_shapes' contains dynamic shapes of arguments whose shapes were not\\nknown statically at TPUReplication rewrite time.\\n'metadata' is a serialized TPUCompileMetadataProto describing the shapes and\\ntypes of the inputs to the computation, as well as a mapping onto the TPU pod\\ntopology.\\n'program' output is a string key that is passed to the TPUExecute op and used to\\nlook up the program in the compilation cache.\",\n    \"operands\": [\n      { \"name\": \"dynamic_shapes\", \"type\": \"Variadic<TF_Int64Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"compilation_status\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"program\", \"type\": \"Variadic<TF_StrTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mlir_module\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"metadata\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf._TPUDeviceOrdinalPlaceholder\",\n    \"summary\": \"Placeholder for a device ordinal that depends on its tf_device.replicate ancestor.\",\n    \"description\": \"This op must have a tf_device.replicate ancestor. The ancestor replica_id and\\nlogical_core attribute correspond to a TPU core. This op maps the TPU core to a\\ndevice_ordinal, where the device ordinal is the index of the core relative to\\nits host.\\n\\nThe replicate_to_island pass removes and flattens tf_device.replicate, so it\\nconverts this op to the constant index of the core relative to its host.\",\n    \"results\": [\n      { \"name\": \"device_ordinal\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"logical_core\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf._UnaryOpsComposition\",\n    \"summary\": \"*NOTE*: Do not invoke this operator directly in Python. Graph rewrite pass is\",\n    \"description\": \"expected to create these operators.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaCompile\",\n    \"summary\": \"XLA Compile Op. For use by the XLA JIT only.\",\n    \"description\": \"Compiles a TensorFlow function into an XLA LocalExecutable and returns a key\\nthat _XlaRun can use to look up the LocalExecutable and execute it.\",\n    \"operands\": [\n      { \"name\": \"constants\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"resources\", \"type\": \"Variadic<TF_ResourceTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"compilation_successful\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"must_compile\", \"type\": \"BoolAttr\" },\n      { \"name\": \"function\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaCompileMlirPlaceholderProgramKey\",\n    \"summary\": \"Placeholder program key (compilation cache key) of a XLA `program`.\",\n    \"description\": \"This op can be used when certain rewrite passes materialize ops that require a\\nprogram key but the _TPUCompileMlir or _XlaCompile op has not been added yet.\\nSubsequent rewrite passes must replace this op with `program` output.\",\n    \"results\": [\n      { \"name\": \"program\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaHostComputeMlir\",\n    \"summary\": \"A pseudo-op to represent host-side computation in an XLA program.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"send_key\", \"type\": \"StrAttr\" },\n      { \"name\": \"recv_key\", \"type\": \"StrAttr\" },\n      { \"name\": \"host_mlir_module\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"manual_sharding\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaRecvAtHost\",\n    \"summary\": \"A placeholder op to receive values from a running XLA computation.\",\n    \"operands\": [\n      { \"name\": \"dynamic_key\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"device_ordinal\", \"type\": \"I64Attr\" },\n      { \"name\": \"device_type\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"TPU\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaRecvAtHostV2\",\n    \"summary\": \"A placeholder op to receive values from a running XLA computation with support for a runtime device ordinal.\",\n    \"operands\": [\n      { \"name\": \"dynamic_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"device_ordinal\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"device_type\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"TPU\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaRun\",\n    \"summary\": \"XLA Run Op. For use by the XLA JIT only.\",\n    \"description\": \"Executes a TensorFlow function previously compiled into a LocalExecutable by an\\n_XlaCompile op.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"key\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaSendFromHost\",\n    \"summary\": \"A placeholder op to send values to a running XLA computation.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"dynamic_key\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"device_ordinal\", \"type\": \"I64Attr\" },\n      { \"name\": \"device_type\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"TPU\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf._XlaSendFromHostV2\",\n    \"summary\": \"A placeholder op to send values to a running XLA computation with support for a runtime device ordinal.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"dynamic_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"device_ordinal\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"device_type\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"TPU\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Abs\",\n    \"summary\": \"Computes the absolute value of a tensor.\",\n    \"description\": \"Given a tensor `x`, this operation returns a tensor containing the absolute\\nvalue of each element in `x`. For example, if x is an input element and y is\\nan output element, this operation computes \\\\\\\\(y = |x|\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Acos\",\n    \"summary\": \"Computes acos of x element-wise.\",\n    \"description\": \"Provided an input tensor, the `tf.math.acos` operation returns the inverse cosine of each element of the tensor. If `y = tf.math.cos(x)` then, `x = tf.math.acos(y)`.\\n\\n  Input range is `[-1, 1]` and the output has a range of `[0, pi]`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Acosh\",\n    \"summary\": \"Computes inverse hyperbolic cosine of x element-wise.\",\n    \"description\": \"Given an input tensor, the function computes inverse hyperbolic cosine of every element.\\nInput range is `[1, inf]`. It returns `nan` if the input lies outside the range.\\n\\n```python\\nx = tf.constant([-2, -0.5, 1, 1.2, 200, 10000, float(\\\"inf\\\")])\\ntf.math.acosh(x) ==> [nan nan 0. 0.62236255 5.9914584 9.903487 inf]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Add\",\n    \"summary\": \"Returns x + y element-wise.\",\n    \"description\": \"*NOTE*: `Add` supports broadcasting. `AddN` does not. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\\n\\nGiven two input tensors, the `tf.add` operation computes the sum for every element in the tensor.\\n\\nBoth input and output have a range `(-inf, inf)`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_NumberNotQuantizedOrStrTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_NumberNotQuantizedOrStrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_NumberNotQuantizedOrStrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AddN\",\n    \"summary\": \"Add all input tensors element wise.\",\n    \"description\": \"Inputs must be of same size and shape.\\n\\n  ```python\\n  x = [9, 7, 10]\\n  tf.math.add_n(x) ==> 26\\n  ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8, TF_Variant ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sum\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8, TF_Variant]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AddV2\",\n    \"summary\": \"Returns x + y element-wise.\",\n    \"description\": \"*NOTE*: `Add` supports broadcasting. `AddN` does not. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AdjustContrastv2\",\n    \"summary\": \"Adjust the contrast of one or more images.\",\n    \"description\": \"`images` is a tensor of at least 3 dimensions.  The last 3 dimensions are\\ninterpreted as `[height, width, channels]`.  The other dimensions only\\nrepresent a collection of images, such as `[batch, height, width, channels].`\\n\\nContrast is adjusted independently for each channel of each image.\\n\\nFor each channel, the Op first computes the mean of the image pixels in the\\nchannel and then adjusts each component of each pixel to\\n`(x - mean) * contrast_factor + mean`.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"contrast_factor\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AdjustHue\",\n    \"summary\": \"Adjust the hue of one or more images.\",\n    \"description\": \"`images` is a tensor of at least 3 dimensions.  The last dimension is\\ninterpreted as channels, and must be three.\\n\\nThe input image is considered in the RGB colorspace. Conceptually, the RGB\\ncolors are first mapped into HSV. A delta is then applied all the hue values,\\nand then remapped back to RGB colorspace.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"delta\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AdjustSaturation\",\n    \"summary\": \"Adjust the saturation of one or more images.\",\n    \"description\": \"`images` is a tensor of at least 3 dimensions.  The last dimension is\\ninterpreted as channels, and must be three.\\n\\nThe input image is considered in the RGB colorspace. Conceptually, the RGB\\ncolors are first mapped into HSV. A scale is then applied all the saturation\\nvalues, and then remapped back to RGB colorspace.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.All\",\n    \"summary\": \"Computes the \\\"logical and\\\" of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AllToAll\",\n    \"summary\": \"An Op to exchange data across TPU replicas.\",\n    \"description\": \"On each replica, the input is split into `split_count` blocks along\\n`split_dimension` and send to the other replicas given group_assignment. After\\nreceiving `split_count` - 1 blocks from other replicas, we concatenate the\\nblocks along `concat_dimension` as the output.\\n\\nFor example, suppose there are 2 TPU replicas:\\nreplica 0 receives input: `[[A, B]]`\\nreplica 1 receives input: `[[C, D]]`\\n\\ngroup_assignment=`[[0, 1]]`\\nconcat_dimension=0\\nsplit_dimension=1\\nsplit_count=2\\n\\nreplica 0's output: `[[A], [C]]`\\nreplica 1's output: `[[B], [D]]`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"group_assignment\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"concat_dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"split_dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"split_count\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Angle\",\n    \"summary\": \"Returns the argument of a complex number.\",\n    \"description\": \"Given a tensor `input` of complex numbers, this operation returns a tensor of\\ntype `float` that is the argument of each element in `input`. All elements in\\n`input` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\), where *a*\\nis the real part and *b* is the imaginary part.\\n\\nThe argument returned by this operation is of the form \\\\\\\\(atan2(b, a)\\\\\\\\).\\n\\nFor example:\\n\\n```\\n# tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]\\ntf.math.angle(input) ==> [2.0132, 1.056]\\n```\\n\\n@compatibility(numpy)\\nEquivalent to np.angle.\\n@end_compatibility\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousIterator\",\n    \"summary\": \"A container for an iterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousIteratorV2\",\n    \"summary\": \"A container for an iterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousIteratorV3\",\n    \"summary\": \"A container for an iterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousMemoryCache\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousMultiDeviceIterator\",\n    \"summary\": \"A container for a multi device iterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"devices\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<StrAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousMultiDeviceIteratorV3\",\n    \"summary\": \"A container for a multi device iterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"devices\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<StrAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousRandomSeedGenerator\",\n    \"operands\": [\n      { \"name\": \"seed\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed2\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AnonymousSeedGenerator\",\n    \"operands\": [\n      { \"name\": \"seed\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed2\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"reshuffle\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Any\",\n    \"summary\": \"Computes the \\\"logical or\\\" of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ApproximateEqual\",\n    \"summary\": \"Returns the truth value of abs(x-y) < tolerance element-wise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tolerance\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1e-05f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ApproxTopK\",\n    \"summary\": \"Returns min/max k values and their indices of the input operand in an approximate manner.\",\n    \"description\": \"See https://arxiv.org/abs/2206.14286 for the algorithm details.\\nThis op is only optimized on TPU currently.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"reduction_dimension\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"recall_target\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.95f>\" },\n      { \"name\": \"is_max_k\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"reduction_input_size_override\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"aggregate_to_topk\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ArgMax\",\n    \"summary\": \"Returns the index with the largest value across dimensions of a tensor.\",\n    \"description\": \"Note that in case of ties the identity of the return value is not guaranteed.\\n\\nUsage:\\n  ```python\\n  import tensorflow as tf\\n  a = [1, 10, 26.9, 2.8, 166.32, 62.3]\\n  b = tf.math.argmax(input = a)\\n  c = tf.keras.backend.eval(b)\\n  # c = 4\\n  # here a[4] = 166.32 which is the largest element of a across axis 0\\n  ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"dimension\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Int16, TF_Int32, TF_Int64, TF_Uint16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ArgMin\",\n    \"summary\": \"Returns the index with the smallest value across dimensions of a tensor.\",\n    \"description\": \"Note that in case of ties the identity of the return value is not guaranteed.\\n\\nUsage:\\n  ```python\\n  import tensorflow as tf\\n  a = [1, 10, 26.9, 2.8, 166.32, 62.3]\\n  b = tf.math.argmin(input = a)\\n  c = tf.keras.backend.eval(b)\\n  # c = 0\\n  # here a[0] = 1 which is the smallest element of a across axis 0\\n  ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"dimension\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Asin\",\n    \"summary\": \"Computes the trignometric inverse sine of x element-wise.\",\n    \"description\": \"The `tf.math.asin` operation returns the inverse of `tf.math.sin`, such that\\nif `y = tf.math.sin(x)` then, `x = tf.math.asin(y)`.\\n\\n**Note**: The output of `tf.math.asin` will lie within the invertible range\\nof sine, i.e [-pi/2, pi/2].\\n\\nFor example:\\n\\n```python\\n# Note: [1.047, 0.785] ~= [(pi/3), (pi/4)]\\nx = tf.constant([1.047, 0.785])\\ny = tf.math.sin(x) # [0.8659266, 0.7068252]\\n\\ntf.math.asin(y) # [1.047, 0.785] = x\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Asinh\",\n    \"summary\": \"Computes inverse hyperbolic sine of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes inverse hyperbolic sine\\n  for every element in the tensor. Both input and output has a range of\\n  `[-inf, inf]`.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -2, -0.5, 1, 1.2, 200, 10000, float(\\\"inf\\\")])\\n  tf.math.asinh(x) ==> [-inf -1.4436355 -0.4812118 0.8813736 1.0159732 5.991471 9.903487 inf]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Assert\",\n    \"summary\": \"Asserts that the given condition is true.\",\n    \"description\": \"If `condition` evaluates to false, print the list of tensors in `data`.\\n`summarize` determines how many entries of the tensors to print.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"data\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"summarize\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 3>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Assign\",\n    \"summary\": \"Update 'ref' by assigning 'value' to it.\",\n    \"description\": \"This operation outputs \\\"ref\\\" after the assignment is done.\\nThis makes it easier to chain operations that need to use the reset value.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_ref\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"validate_shape\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AssignAddVariableOp\",\n    \"summary\": \"Adds a value to the current value of a variable.\",\n    \"description\": \"Any ReadVariableOp with a control dependency on this op is guaranteed to\\nsee the incremented value or a subsequent newer one.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AssignSubVariableOp\",\n    \"summary\": \"Subtracts a value from the current value of a variable.\",\n    \"description\": \"Any ReadVariableOp with a control dependency on this op is guaranteed to\\nsee the decremented value or a subsequent newer one.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AssignVariableOp\",\n    \"summary\": \"Assigns a new value to a variable.\",\n    \"description\": \"Any ReadVariableOp with a control dependency on this op is guaranteed to return\\nthis value or a subsequent newer value of the variable.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"validate_shape\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AsString\",\n    \"summary\": \"Converts each entry in the given tensor to strings.\",\n    \"description\": \"Supports many numeric types and boolean.\\n\\nFor Unicode, see the\\n[https://www.tensorflow.org/text/guide/unicode](Working with Unicode text)\\ntutorial.\\n\\nExamples:\\n\\n>>> tf.strings.as_string([3, 2])\\n<tf.Tensor: shape=(2,), dtype=string, numpy=array([b'3', b'2'], dtype=object)>\\n>>> tf.strings.as_string([3.1415926, 2.71828], precision=2).numpy()\\narray([b'3.14', b'2.72'], dtype=object)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Str, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8, TF_Variant]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"precision\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"scientific\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"shortest\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"width\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"fill\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Atan\",\n    \"summary\": \"Computes the trignometric inverse tangent of x element-wise.\",\n    \"description\": \"The `tf.math.atan` operation returns the inverse of `tf.math.tan`, such that\\nif `y = tf.math.tan(x)` then, `x = tf.math.atan(y)`.\\n\\n**Note**: The output of `tf.math.atan` will lie within the invertible range\\nof tan, i.e (-pi/2, pi/2).\\n\\nFor example:\\n\\n```python\\n# Note: [1.047, 0.785] ~= [(pi/3), (pi/4)]\\nx = tf.constant([1.047, 0.785])\\ny = tf.math.tan(x) # [1.731261, 0.99920404]\\n\\ntf.math.atan(y) # [1.047, 0.785] = x\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Atan2\",\n    \"summary\": \"Computes arctangent of `y/x` element-wise, respecting signs of the arguments.\",\n    \"description\": \"This is the angle \\\\\\\\( \\\\theta \\\\in [-\\\\pi, \\\\pi] \\\\\\\\) such that\\n\\\\\\\\[ x = r \\\\cos(\\\\theta) \\\\\\\\]\\nand\\n\\\\\\\\[ y = r \\\\sin(\\\\theta) \\\\\\\\]\\nwhere \\\\\\\\(r = \\\\sqrt{x^2 + y^2} \\\\\\\\).\\n\\nFor example:\\n\\n>>> x = [1., 1.]\\n>>> y = [1., -1.]\\n>>> print((tf.math.atan2(y,x) * (180 / np.pi)).numpy())\\n[ 45. -45.]\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Atanh\",\n    \"summary\": \"Computes inverse hyperbolic tangent of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes inverse hyperbolic tangent\\n  for every element in the tensor. Input range is `[-1,1]` and output range is\\n  `[-inf, inf]`. If input is `-1`, output will be `-inf` and if the\\n  input is `1`, output will be `inf`. Values outside the range will have\\n  `nan` as output.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -1, -0.5, 1, 0, 0.5, 10, float(\\\"inf\\\")])\\n  tf.math.atanh(x) ==> [nan -inf -0.54930615 inf  0. 0.54930615 nan nan]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AvgPool\",\n    \"summary\": \"Performs average pooling on the input.\",\n    \"description\": \"Each entry in `output` is the mean of the corresponding size `ksize`\\nwindow in `value`.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AvgPool3D\",\n    \"summary\": \"Performs 3D average pooling on the input.\",\n    \"description\": \"Each entry in `output` is the mean of the corresponding size `ksize` window in\\n`value`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AvgPool3DGrad\",\n    \"summary\": \"Computes gradients of average pooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input_shape\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.AvgPoolGrad\",\n    \"summary\": \"Computes gradients of the average pooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input_shape\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchDatasetV2\",\n    \"summary\": \"Creates a dataset that batches `batch_size` elements from `input_dataset`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"batch_size\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"drop_remainder\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parallel_copy\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchFunction\",\n    \"summary\": \"Batches all the inputs tensors to the computation done by the function.\",\n    \"description\": \"So, for example, in the following code\\n\\n  ```python\\n\\n  # This input will be captured.\\n  y = tf.placeholder_with_default(1.0, shape=[])\\n\\n  @tf.Defun(tf.float32)\\n  def computation(a):\\n    return tf.matmul(a, a) + y\\n\\n  b = gen_batch_ops.batch_function(\\n          f=computation\\n          in_tensors=[a],\\n          captured_tensors=computation.captured_inputs,\\n          Tout=[o.type for o in computation.definition.signature.output_arg],\\n          num_batch_threads=1,\\n          max_batch_size=10,\\n          batch_timeout_micros=100000,  # 100ms\\n          allowed_batch_sizes=[3, 10],\\n          batching_queue=\\\"\\\")\\n  ```\\n\\nIf more than one session.run call is simultaneously trying to compute `b`\\nthe values of `a` will be gathered, non-deterministically concatenated\\nalong the first axis, and only one thread will run the computation.\\n\\nAssumes that all arguments of the function are Tensors which will be batched\\nalong their first dimension.\\n\\nArguments that are captured, are not batched. The session.run call which does\\nthe concatenation, will use the values of the captured tensors available to it.\\nTherefore, typical uses of captured tensors should involve values which remain\\nunchanged across session.run calls. Inference is a good example of this.\\n\\nSparseTensor is not supported. The return value of the decorated function\\nmust be a Tensor or a list/tuple of Tensors.\",\n    \"operands\": [\n      { \"name\": \"in_tensors\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"captured_tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"num_batch_threads\", \"type\": \"I64Attr\" },\n      { \"name\": \"max_batch_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"batch_timeout_micros\", \"type\": \"I64Attr\" },\n      { \"name\": \"max_enqueued_batches\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 10>\" },\n      { \"name\": \"allowed_batch_sizes\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"batching_queue\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"low_priority_max_batch_size\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"low_priority_batch_timeout_micros\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"low_priority_allowed_batch_sizes\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"low_priority_max_enqueued_batches\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"mixed_priority_policy\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ low_priority_padding_with_max_batch_size, low_priority_padding_with_next_allowed_batch_size, priority_isolation, priority_merge ]>, \\\"low_priority_padding_with_max_batch_size\\\">\" },\n      { \"name\": \"batch_padding_policy\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ PAD_UP, BATCH_DOWN, MINIMIZE_TPU_COST_PER_REQUEST ]>, \\\"PAD_UP\\\">\" },\n      { \"name\": \"enable_large_batch_splitting\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"enable_priority_aware_batch_scheduler\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchMatMul\",\n    \"summary\": \"Multiplies slices of two tensors in batches.\",\n    \"description\": \"Multiplies all slices of `Tensor` `x` and `y` (each slice can be\\nviewed as an element of a batch), and arranges the individual results\\nin a single output tensor of the same batch size. Each of the\\nindividual slices can optionally be adjointed (to adjoint a matrix\\nmeans to transpose and conjugate it) before multiplication by setting\\nthe `adj_x` or `adj_y` flag to `True`, which are by default `False`.\\n\\nThe input tensors `x` and `y` are 2-D or higher with shape `[..., r_x, c_x]`\\nand `[..., r_y, c_y]`.\\n\\nThe output tensor is 2-D or higher with shape `[..., r_o, c_o]`, where:\\n\\n    r_o = c_x if adj_x else r_x\\n    c_o = r_y if adj_y else c_y\\n\\nIt is computed as:\\n\\n    output[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :])\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adj_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"adj_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchMatMulV2\",\n    \"summary\": \"Multiplies slices of two tensors in batches.\",\n    \"description\": \"Multiplies all slices of `Tensor` `x` and `y` (each slice can be\\nviewed as an element of a batch), and arranges the individual results\\nin a single output tensor of the same batch size. Each of the\\nindividual slices can optionally be adjointed (to adjoint a matrix\\nmeans to transpose and conjugate it) before multiplication by setting\\nthe `adj_x` or `adj_y` flag to `True`, which are by default `False`.\\n\\nThe input tensors `x` and `y` are 2-D or higher with shape `[..., r_x, c_x]`\\nand `[..., r_y, c_y]`.\\n\\nThe output tensor is 2-D or higher with shape `[..., r_o, c_o]`, where:\\n\\n    r_o = c_x if adj_x else r_x\\n    c_o = r_y if adj_y else c_y\\n\\nIt is computed as:\\n\\n    output[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :])\\n\\n*NOTE*: `BatchMatMulV2` supports broadcasting in the batch dimensions. More\\nabout broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adj_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"adj_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchMatMulV3\",\n    \"summary\": \"Multiplies slices of two tensors in batches.\",\n    \"description\": \"Multiplies all slices of `Tensor` `x` and `y` (each slice can be\\nviewed as an element of a batch), and arranges the individual results\\nin a single output tensor of the same batch size. Each of the\\nindividual slices can optionally be adjointed (to adjoint a matrix\\nmeans to transpose and conjugate it) before multiplication by setting\\nthe `adj_x` or `adj_y` flag to `True`, which are by default `False`.\\n\\nThe input tensors `x` and `y` are 2-D or higher with shape `[..., r_x, c_x]`\\nand `[..., r_y, c_y]`.\\n\\nThe output tensor is 2-D or higher with shape `[..., r_o, c_o]`, where:\\n\\n    r_o = c_x if adj_x else r_x\\n    c_o = r_y if adj_y else c_y\\n\\nIt is computed as:\\n\\n    output[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :])\\n\\n*NOTE*: `BatchMatMulV3` supports broadcasting in the batch dimensions. More\\nabout broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint8 ]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adj_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"adj_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchNormWithGlobalNormalization\",\n    \"summary\": \"Batch normalization.\",\n    \"description\": \"This op is deprecated. Prefer `tf.nn.batch_normalization`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"m\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"v\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"beta\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"gamma\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"variance_epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"scale_after_normalization\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchToSpace\",\n    \"summary\": \"BatchToSpace for 4-D tensors of type T.\",\n    \"description\": \"This is a legacy version of the more general BatchToSpaceND.\\n\\nRearranges (permutes) data from batch into blocks of spatial data, followed by\\ncropping. This is the reverse transformation of SpaceToBatch. More specifically,\\nthis op outputs a copy of the input tensor where values from the `batch`\\ndimension are moved in spatial blocks to the `height` and `width` dimensions,\\nfollowed by cropping along the `height` and `width` dimensions.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"crops\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<2>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BatchToSpaceND\",\n    \"summary\": \"BatchToSpace for N-D tensors of type T.\",\n    \"description\": \"This operation reshapes the \\\"batch\\\" dimension 0 into `M + 1` dimensions of shape\\n`block_shape + [batch]`, interleaves these blocks back into the grid defined by\\nthe spatial dimensions `[1, ..., M]`, to obtain a result with the same rank as\\nthe input.  The spatial dimensions of this intermediate result are then\\noptionally cropped according to `crops` to produce the output.  This is the\\nreverse of SpaceToBatch.  See below for a precise description.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"block_shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"crops\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BesselI0e\",\n    \"summary\": \"Computes the Bessel i0e function of `x` element-wise.\",\n    \"description\": \"Exponentially scaled modified Bessel function of order 0 defined as\\n`bessel_i0e(x) = exp(-abs(x)) bessel_i0(x)`.\\n\\nThis function is faster and numerically stabler than `bessel_i0(x)`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BesselI1e\",\n    \"summary\": \"Computes the Bessel i1e function of `x` element-wise.\",\n    \"description\": \"Exponentially scaled modified Bessel function of order 0 defined as\\n`bessel_i1e(x) = exp(-abs(x)) bessel_i1(x)`.\\n\\nThis function is faster and numerically stabler than `bessel_i1(x)`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Betainc\",\n    \"summary\": \"Compute the regularized incomplete beta integral \\\\\\\\(I_x(a, b)\\\\\\\\).\",\n    \"description\": \"The regularized incomplete beta integral is defined as:\\n\\n\\n\\\\\\\\(I_x(a, b) = \\\\frac{B(x; a, b)}{B(a, b)}\\\\\\\\)\\n\\nwhere\\n\\n\\n\\\\\\\\(B(x; a, b) = \\\\int_0^x t^{a-1} (1 - t)^{b-1} dt\\\\\\\\)\\n\\n\\nis the incomplete beta function and \\\\\\\\(B(a, b)\\\\\\\\) is the *complete*\\nbeta function.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"b\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"x\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BiasAdd\",\n    \"summary\": \"Adds `bias` to `value`.\",\n    \"description\": \"This is a special case of `tf.add` where `bias` is restricted to be 1-D.\\nBroadcasting is supported, so `value` may have any number of dimensions.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"bias\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BiasAddGrad\",\n    \"summary\": \"The backward operation for \\\"BiasAdd\\\" on the \\\"bias\\\" tensor.\",\n    \"description\": \"It accumulates all the values from out_backprop into the feature dimension.\\nFor NHWC data format, the feature dimension is the last. For NCHW data format,\\nthe feature dimension is the third-to-last.\",\n    \"operands\": [\n      { \"name\": \"out_backprop\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BiasAddV1\",\n    \"summary\": \"Adds `bias` to `value`.\",\n    \"description\": \"This is a deprecated version of BiasAdd and will be soon removed.\\n\\nThis is a special case of `tf.add` where `bias` is restricted to be 1-D.\\nBroadcasting is supported, so `value` may have any number of dimensions.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"bias\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Bincount\",\n    \"summary\": \"Counts the number of occurrences of each value in an integer array.\",\n    \"description\": \"Outputs a vector with length `size` and the same dtype as `weights`. If\\n`weights` are empty, then index `i` stores the number of times the value `i` is\\ncounted in `arr`. If `weights` are non-empty, then index `i` stores the sum of\\nthe value in `weights` at each index where the corresponding value in `arr` is\\n`i`.\\n\\nValues in `arr` outside of the range [0, size) are ignored.\",\n    \"operands\": [\n      { \"name\": \"arr\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TensorOf<[ TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"bins\", \"type\": \"TensorOf<[ TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Bitcast\",\n    \"summary\": \"Bitcasts a tensor from one type to another without copying data.\",\n    \"description\": \"Given a tensor `input`, this operation returns a tensor that has the same buffer\\ndata as `input` with datatype `type`.\\n\\nIf the input datatype `T` is larger than the output datatype `type` then the\\nshape changes from [...] to [..., sizeof(`T`)/sizeof(`type`)].\\n\\nIf `T` is smaller than `type`, the operator requires that the rightmost\\ndimension be equal to sizeof(`type`)/sizeof(`T`). The shape then goes from\\n[..., sizeof(`type`)/sizeof(`T`)] to [...].\\n\\ntf.bitcast() and tf.cast() work differently when real dtype is casted as a complex dtype\\n(e.g. tf.complex64 or tf.complex128) as tf.cast() make imaginary part 0 while tf.bitcast()\\ngives module error.\\nFor example,\\n\\nExample 1:\\n\\n>>> a = [1., 2., 3.]\\n>>> equality_bitcast = tf.bitcast(a, tf.complex128)\\nTraceback (most recent call last):\\n...\\nInvalidArgumentError: Cannot bitcast from 1 to 18 [Op:Bitcast]\\n>>> equality_cast = tf.cast(a, tf.complex128)\\n>>> print(equality_cast)\\ntf.Tensor([1.+0.j 2.+0.j 3.+0.j], shape=(3,), dtype=complex128)\\n\\nExample 2:\\n\\n>>> tf.bitcast(tf.constant(0xffffffff, dtype=tf.uint32), tf.uint8)\\n<tf.Tensor: shape=(4,), dtype=uint8, numpy=array([255, 255, 255, 255], dtype=uint8)>\\n\\nExample 3:\\n\\n>>> x = [1., 2., 3.]\\n>>> y = [0., 2., 3.]\\n>>> equality= tf.equal(x,y)\\n>>> equality_cast = tf.cast(equality,tf.float32)\\n>>> equality_bitcast = tf.bitcast(equality_cast,tf.uint8)\\n>>> print(equality)\\ntf.Tensor([False True True], shape=(3,), dtype=bool)\\n>>> print(equality_cast)\\ntf.Tensor([0. 1. 1.], shape=(3,), dtype=float32)\\n>>> print(equality_bitcast)\\ntf.Tensor(\\n    [[  0   0   0   0]\\n     [  0   0 128  63]\\n     [  0   0 128  63]], shape=(3, 4), dtype=uint8)\\n\\n*NOTE*: Bitcast is implemented as a low-level cast, so machines with different\\nendian orderings will give different results. A copy from input buffer to output\\nbuffer is made on BE machines when types are of different sizes in order to get\\nthe same casting results as on LE machines.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BitwiseAnd\",\n    \"summary\": \"Elementwise computes the bitwise AND of `x` and `y`.\",\n    \"description\": \"The result will have those bits set, that are set in both `x` and `y`. The\\ncomputation is performed on the underlying representations of `x` and `y`.\\n\\nFor example:\\n\\n```python\\nimport tensorflow as tf\\nfrom tensorflow.python.ops import bitwise_ops\\ndtype_list = [tf.int8, tf.int16, tf.int32, tf.int64,\\n              tf.uint8, tf.uint16, tf.uint32, tf.uint64]\\n\\nfor dtype in dtype_list:\\n  lhs = tf.constant([0, 5, 3, 14], dtype=dtype)\\n  rhs = tf.constant([5, 0, 7, 11], dtype=dtype)\\n  exp = tf.constant([0, 0, 3, 10], dtype=tf.float32)\\n\\n  res = bitwise_ops.bitwise_and(lhs, rhs)\\n  tf.assert_equal(tf.cast(res, tf.float32), exp) # TRUE\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BitwiseOr\",\n    \"summary\": \"Elementwise computes the bitwise OR of `x` and `y`.\",\n    \"description\": \"The result will have those bits set, that are set in `x`, `y` or both. The\\ncomputation is performed on the underlying representations of `x` and `y`.\\n\\nFor example:\\n\\n```python\\nimport tensorflow as tf\\nfrom tensorflow.python.ops import bitwise_ops\\ndtype_list = [tf.int8, tf.int16, tf.int32, tf.int64,\\n              tf.uint8, tf.uint16, tf.uint32, tf.uint64]\\n\\nfor dtype in dtype_list:\\n  lhs = tf.constant([0, 5, 3, 14], dtype=dtype)\\n  rhs = tf.constant([5, 0, 7, 11], dtype=dtype)\\n  exp = tf.constant([5, 5, 7, 15], dtype=tf.float32)\\n\\n  res = bitwise_ops.bitwise_or(lhs, rhs)\\n  tf.assert_equal(tf.cast(res,  tf.float32), exp)  # TRUE\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BitwiseXor\",\n    \"summary\": \"Elementwise computes the bitwise XOR of `x` and `y`.\",\n    \"description\": \"The result will have those bits set, that are different in `x` and `y`. The\\ncomputation is performed on the underlying representations of `x` and `y`.\\n\\nFor example:\\n\\n```python\\nimport tensorflow as tf\\nfrom tensorflow.python.ops import bitwise_ops\\ndtype_list = [tf.int8, tf.int16, tf.int32, tf.int64,\\n              tf.uint8, tf.uint16, tf.uint32, tf.uint64]\\n\\nfor dtype in dtype_list:\\n  lhs = tf.constant([0, 5, 3, 14], dtype=dtype)\\n  rhs = tf.constant([5, 0, 7, 11], dtype=dtype)\\n  exp = tf.constant([5, 5, 4, 5],  dtype=tf.float32)\\n\\n  res = bitwise_ops.bitwise_xor(lhs, rhs)\\n  tf.assert_equal(tf.cast(res, tf.float32), exp) # TRUE\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BoostedTreesBucketize\",\n    \"summary\": \"Bucketize each feature based on bucket boundaries.\",\n    \"description\": \"An op that returns a list of float tensors, where each tensor represents the\\nbucketized values for a single feature.\",\n    \"operands\": [\n      { \"name\": \"float_values\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"bucket_boundaries\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"buckets\", \"type\": \"Variadic<TF_Int32Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BroadcastArgs\",\n    \"summary\": \"Return the shape of s0 op s1 with broadcast.\",\n    \"description\": \"Given `s0` and `s1`, tensors that represent shapes, compute `r0`, the\\nbroadcasted shape. `s0`, `s1` and `r0` are all integer vectors.\",\n    \"operands\": [\n      { \"name\": \"s0\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"s1\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"r0\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BroadcastGradientArgs\",\n    \"summary\": \"Return the reduction indices for computing gradients of s0 op s1 with broadcast.\",\n    \"description\": \"This is typically used by gradient computations for a broadcasting operation.\",\n    \"operands\": [\n      { \"name\": \"s0\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"s1\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"r0\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"r1\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.BroadcastTo\",\n    \"summary\": \"Broadcast an array for a compatible shape.\",\n    \"description\": \"Broadcasting is the process of making arrays to have compatible shapes\\nfor arithmetic operations. Two shapes are compatible if for each\\ndimension pair they are either equal or one of them is one.\\n\\nFor example:\\n\\n>>> x = tf.constant([[1, 2, 3]])   # Shape (1, 3,)\\n>>> y = tf.broadcast_to(x, [2, 3])\\n>>> print(y)\\ntf.Tensor(\\n    [[1 2 3]\\n     [1 2 3]], shape=(2, 3), dtype=int32)\\n\\nIn the above example, the input Tensor with the shape of `[1, 3]`\\nis broadcasted to output Tensor with shape of `[2, 3]`.\\n\\nWhen broadcasting, if a tensor has fewer axes than necessary its shape is\\npadded on the left with ones. So this gives the same result as the previous\\nexample:\\n\\n>>> x = tf.constant([1, 2, 3])   # Shape (3,)\\n>>> y = tf.broadcast_to(x, [2, 3])\\n\\n\\nWhen doing broadcasted operations such as multiplying a tensor\\nby a scalar, broadcasting (usually) confers some time or space\\nbenefit, as the broadcasted tensor is never materialized.\\n\\nHowever, `broadcast_to` does not carry with it any such benefits.\\nThe newly-created tensor takes the full memory of the broadcasted\\nshape. (In a graph context, `broadcast_to` might be fused to\\nsubsequent operation and then be optimized away, however.)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Bucketize\",\n    \"summary\": \"Bucketizes 'input' based on 'boundaries'.\",\n    \"description\": \"For example, if the inputs are\\n    boundaries = [0, 10, 100]\\n    input = [[-5, 10000]\\n             [150,   10]\\n             [5,    100]]\\n\\nthen the output will be\\n    output = [[0, 3]\\n              [3, 2]\\n              [1, 3]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundaries\", \"type\": \"TypedArrayAttrBase<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CacheDatasetV2\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"cache\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Case\",\n    \"summary\": \"An n-way switch statement which calls a single branch function.\",\n    \"description\": \"An n-way switch statement, implementing the following:\\n    ```\\n    switch (branch_index) {\\n      case 0:\\n        output = branches[0](input);\\n        break;\\n      case 1:\\n        output = branches[1](input);\\n        break;\\n      ...\\n      case [[nbranches-1]]:\\n      default:\\n        output = branches[nbranches-1](input);\\n        break;\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32Tensor\" },\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branches\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<SymbolRefAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"is_stateless\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CaseRegion\",\n    \"summary\": \"An n-way switch statement which calls a single branch function.\",\n    \"description\": \"An n-way switch statement, implementing the following:\\n    ```\\n    switch (branch_index) {\\n      case 0:\\n        output = branches[0](input);\\n        break;\\n      case 1:\\n        output = branches[1](input);\\n        break;\\n      ...\\n      case [[nbranches-1]]:\\n      default:\\n        output = branches[nbranches-1](input);\\n        break;\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_stateless\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cast\",\n    \"summary\": \"Cast x of type SrcT to y of DstT.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"Truncate\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Ceil\",\n    \"summary\": \"Returns element-wise smallest integer not less than x.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CheckNumerics\",\n    \"summary\": \"Checks a tensor for NaN and Inf values.\",\n    \"description\": \"When run, reports an `InvalidArgument` error if `tensor` has any values\\nthat are not a number (NaN) or infinity (Inf). Otherwise, returns the input\\ntensor.\\n\\nExample usage:\\n\\n``` python\\na = tf.Variable(1.0)\\ntf.debugging.check_numerics(a, message='')\\n\\nb = tf.Variable(np.nan)\\ntry:\\n  tf.debugging.check_numerics(b, message='Checking b')\\nexcept Exception as e:\\n  assert \\\"Checking b : Tensor had NaN values\\\" in e.message\\n\\nc = tf.Variable(np.inf)\\ntry:\\n  tf.debugging.check_numerics(c, message='Checking c')\\nexcept Exception as e:\\n  assert \\\"Checking c : Tensor had Inf values\\\" in e.message\\n```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cholesky\",\n    \"summary\": \"Computes the Cholesky decomposition of one or more square matrices.\",\n    \"description\": \"The input is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions\\nform square matrices.\\n\\nThe input has to be symmetric and positive definite. Only the lower-triangular\\npart of the input will be used for this operation. The upper-triangular part\\nwill not be read.\\n\\nThe output is a tensor of the same shape as the input\\ncontaining the Cholesky decompositions for all input submatrices `[..., :, :]`.\\n\\n**Note**: The gradient computation on GPU is faster for large matrices but\\nnot for large batch dimensions when the submatrices are small. In this\\ncase it might be faster to use the CPU.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ClipByValue\",\n    \"summary\": \"Clips tensor values to a specified min and max.\",\n    \"description\": \"Given a tensor `x`, this operation returns a tensor of the same type and\\nshape as `x` with its values clipped to `clip_value_min` and `clip_value_max`.\\nAny values less than `clip_value_min` are set to `clip_value_min`. Any values\\ngreater than `clip_value_max` are set to `clip_value_max`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"clip_value_min\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"clip_value_max\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CloseSummaryWriter\",\n    \"summary\": \"Flushes and closes the summary writer.\",\n    \"description\": \"Also removes it from the resource manager. To reopen, use another\\nCreateSummaryFileWriter op.\\n\\nwriter: A handle to the summary writer resource.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollateTPUEmbeddingMemory\",\n    \"summary\": \"An op that merges the string-encoded memory config protos from all hosts.\",\n    \"operands\": [\n      { \"name\": \"memory_configs\", \"type\": \"Variadic<TF_StrTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"merged_memory_config\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveAllToAllV2\",\n    \"summary\": \"Mutually exchanges multiple tensors of identical type and shape.\",\n    \"description\": \"`is_stateless` means each op does not need control dependencies to other\\ncollective ops. In this case, keys that are unique at runtime\\n(e.g. `instance_key`) should be used to distinguish collective groups.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FpOrI32OrI64Tensor\" },\n      { \"name\": \"group_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"group_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"instance_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"ordering_token\", \"type\": \"Variadic<TF_ResourceTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" },\n      { \"name\": \"is_stateless\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveAssignGroupV2\",\n    \"summary\": \"Assign group keys based on group assignment.\",\n    \"operands\": [\n      { \"name\": \"group_assignment\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"device_index\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"base_key\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"group_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"group_key\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveBcastRecv\",\n    \"summary\": \"Receives a tensor value broadcast from another device.\",\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TensorOf<[TF_Bool, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"group_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"instance_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveBcastSend\",\n    \"summary\": \"Broadcasts a tensor value to one or more other devices.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Bool, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TensorOf<[TF_Bool, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"group_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"instance_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveGather\",\n    \"summary\": \"Mutually accumulates multiple tensors of identical type and shape.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"group_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"instance_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveGatherV2\",\n    \"summary\": \"Mutually accumulates multiple tensors of identical type and shape.\",\n    \"description\": \"`is_stateless` means each op does not need control dependencies to other\\ncollective ops. In this case, keys that are unique at runtime\\n(e.g. `instance_key`) should be used to distinguish collective groups.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" },\n      { \"name\": \"group_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"group_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"instance_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"ordering_token\", \"type\": \"Variadic<TF_ResourceTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" },\n      { \"name\": \"is_stateless\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectivePermute\",\n    \"summary\": \"An Op to permute tensors across replicated TPU instances.\",\n    \"description\": \"Each instance supplies its own input.\\n\\nFor example, suppose there are 4 TPU instances: `[A, B, C, D]`. Passing\\nsource_target_pairs=`[[0,1],[1,2],[2,3],[3,0]]` gets the outputs:\\n`[D, A, B, C]`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveReduce\",\n    \"summary\": \"Mutually reduces multiple tensors of identical type and shape.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"group_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"instance_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"merge_op\", \"type\": \"TF_AnyStrAttrOf<[Min, Max, Mul, Add]>\" },\n      { \"name\": \"final_op\", \"type\": \"TF_AnyStrAttrOf<[Id, Div]>\" },\n      { \"name\": \"subdiv_offsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"wait_for\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveReduceScatterV2\",\n    \"summary\": \"Mutually reduces multiple tensors of identical type and shape and scatters the result.\",\n    \"description\": \"`is_stateless` means each op does not need control dependencies to other\\ncollective ops. In this case, keys that are unique at runtime\\n(e.g. `instance_key`) should be used to distinguish collective groups.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FpOrI32OrI64Tensor\" },\n      { \"name\": \"group_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"group_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"instance_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"ordering_token\", \"type\": \"Variadic<TF_ResourceTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"merge_op\", \"type\": \"TF_AnyStrAttrOf<[Min, Max, Mul, Add]>\" },\n      { \"name\": \"final_op\", \"type\": \"TF_AnyStrAttrOf<[Id, Div]>\" },\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" },\n      { \"name\": \"is_stateless\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"max_subdivs_per_device\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CollectiveReduceV2\",\n    \"summary\": \"Mutually reduces multiple tensors of identical type and shape.\",\n    \"description\": \"`is_stateless` means each op does not need control dependencies to other\\ncollective ops. In this case, keys that are unique at runtime\\n(e.g. `instance_key`) should be used to distinguish collective groups.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FpOrI32OrI64Tensor\" },\n      { \"name\": \"group_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"group_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"instance_key\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"ordering_token\", \"type\": \"Variadic<TF_ResourceTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"merge_op\", \"type\": \"TF_AnyStrAttrOf<[Min, Max, Mul, Add]>\" },\n      { \"name\": \"final_op\", \"type\": \"TF_AnyStrAttrOf<[Id, Div]>\" },\n      { \"name\": \"communication_hint\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"auto\\\">\" },\n      { \"name\": \"timeout_seconds\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" },\n      { \"name\": \"is_stateless\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"max_subdivs_per_device\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Complex\",\n    \"summary\": \"Converts two real numbers to a complex number.\",\n    \"description\": \"Given a tensor `real` representing the real part of a complex number, and a\\ntensor `imag` representing the imaginary part of a complex number, this\\noperation returns complex numbers elementwise of the form \\\\\\\\(a + bj\\\\\\\\), where\\n*a* represents the `real` part and *b* represents the `imag` part.\\n\\nThe input tensors `real` and `imag` must have the same shape.\\n\\nFor example:\\n\\n```\\n# tensor 'real' is [2.25, 3.25]\\n# tensor `imag` is [4.75, 5.75]\\ntf.complex(real, imag) ==> [[2.25 + 4.75j], [3.25 + 5.75j]]\\n```\",\n    \"operands\": [\n      { \"name\": \"real\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"imag\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ComplexAbs\",\n    \"summary\": \"Computes the complex absolute value of a tensor.\",\n    \"description\": \"Given a tensor `x` of complex numbers, this operation returns a tensor of type\\n`float` or `double` that is the absolute value of each element in `x`. All\\nelements in `x` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\). The absolute\\nvalue is computed as \\\\\\\\( \\\\sqrt{a^2 + b^2}\\\\\\\\).\\n\\nFor example:\\n\\n>>> x = tf.complex(3.0, 4.0)\\n>>> print((tf.raw_ops.ComplexAbs(x=x, Tout=tf.dtypes.float32, name=None)).numpy())\\n5.0\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Concat\",\n    \"summary\": \"Concatenates tensors along one dimension.\",\n    \"operands\": [\n      { \"name\": \"concat_dim\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"values\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConcatOffset\",\n    \"summary\": \"Computes offsets of concat inputs within its output.\",\n    \"description\": \"For example:\\n\\n>>> x = [2, 2, 7]\\n>>> y = [2, 3, 7]\\n>>> z = [2, 9, 7]\\n>>> offsets = concat_offset(1, [x, y, z])\\n>>> [[a.item() for a in list(off.numpy())] for off in offsets]\\n[[0, 0, 0], [0, 2, 0], [0, 5, 0]]\\n\\nThis is typically used by gradient computations for a concat operation.\",\n    \"operands\": [\n      { \"name\": \"concat_dim\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"offset\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConcatV2\",\n    \"summary\": \"Concatenates tensors along one dimension.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConfigureAndInitializeGlobalTPU\",\n    \"summary\": \"An op that initialize the TPU system in a multi-client set up.\",\n    \"description\": \"Initializes global TPU system for mutli-client execution.\\n\\nThis op does the work of both ConfigureDistributedTpuOp and\\nInitializeHostForDistributedTpuOp, and outputs the latter's result.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConfigureDistributedTPU\",\n    \"summary\": \"Sets up the centralized structures for a distributed TPU system.\",\n    \"results\": [\n      { \"name\": \"topology\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"embedding_config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"tpu_embedding_config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"is_global_init\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"enable_whole_mesh_compilations\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"compilation_failure_closes_chips\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"tpu_cancellation_closes_chips\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConfigureTPUEmbedding\",\n    \"summary\": \"Sets up TPUEmbedding in a distributed TPU system.\",\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConfigureTPUEmbeddingHost\",\n    \"summary\": \"An op that configures the TPUEmbedding software on a host.\",\n    \"operands\": [\n      { \"name\": \"common_config\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"memory_config\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"network_config\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConfigureTPUEmbeddingMemory\",\n    \"summary\": \"An op that configures the TPUEmbedding software on a host.\",\n    \"operands\": [\n      { \"name\": \"common_config\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"memory_config\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conj\",\n    \"summary\": \"Returns the complex conjugate of a complex number.\",\n    \"description\": \"Given a tensor `input` of complex numbers, this operation returns a tensor of\\ncomplex numbers that are the complex conjugate of each element in `input`. The\\ncomplex numbers in `input` must be of the form \\\\\\\\(a + bj\\\\\\\\), where *a* is the\\nreal part and *b* is the imaginary part.\\n\\nThe complex conjugate returned by this operation is of the form \\\\\\\\(a - bj\\\\\\\\).\\n\\nFor example:\\n\\n```\\n# tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]\\ntf.conj(input) ==> [-2.25 - 4.75j, 3.25 - 5.75j]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64, TF_Variant]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64, TF_Variant]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConjugateTranspose\",\n    \"summary\": \"Shuffle dimensions of x according to a permutation and conjugate the result.\",\n    \"description\": \"The output `y` has the same rank as `x`. The shapes of `x` and `y` satisfy:\\n  `y.shape[i] == x.shape[perm[i]] for i in [0, 1, ..., rank(x) - 1]`\\n  `y[i,j,k,...,s,t,u] == conj(x[perm[i], perm[j], perm[k],...,perm[s], perm[t], perm[u]])`\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"perm\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConnectTPUEmbeddingHosts\",\n    \"summary\": \"An op that sets up communication between TPUEmbedding host software instances\",\n    \"description\": \"after ConfigureTPUEmbeddingHost has been called on each host.\",\n    \"operands\": [\n      { \"name\": \"network_configs\", \"type\": \"Variadic<TF_StrTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Const\",\n    \"summary\": \"Constant tensor op\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv\",\n    \"category\": \"Layer\",\n    \"summary\": \"Computes a N-D convolution given (N+1+batch_dims)-D `input` and (N+2)-D `filter` tensors.\",\n    \"description\": \"General function for computing a N-D convolution. It is required that\\n`1 <= N <= 3`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ CHANNELS_FIRST, CHANNELS_LAST ]>, \\\"CHANNELS_LAST\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"groups\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv2D\",\n    \"summary\": \"Computes a 2-D convolution given 4-D `input` and `filter` tensors.\",\n    \"description\": \"Given an input tensor of shape `[batch, in_height, in_width, in_channels]`\\nand a filter / kernel tensor of shape\\n`[filter_height, filter_width, in_channels, out_channels]`, this op\\nperforms the following:\\n\\n1. Flattens the filter to a 2-D matrix with shape\\n   `[filter_height * filter_width * in_channels, output_channels]`.\\n2. Extracts image patches from the input tensor to form a *virtual*\\n   tensor of shape `[batch, out_height, out_width,\\n   filter_height * filter_width * in_channels]`.\\n3. For each patch, right-multiplies the filter matrix and the image patch\\n   vector.\\n\\nIn detail, with the default NHWC format,\\n\\n    output[b, i, j, k] =\\n        sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] *\\n                        filter[di, dj, q, k]\\n\\nMust have `strides[0] = strides[3] = 1`.  For the most common case of the same\\nhorizontal and vertices strides, `strides = [1, stride, stride, 1]`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"use_cudnn_on_gpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv2DBackpropFilter\",\n    \"summary\": \"Computes the gradients of convolution with respect to the filter.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"filter_sizes\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"out_backprop\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"use_cudnn_on_gpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv2DBackpropFilterV2\",\n    \"summary\": \"Computes the gradients of convolution with respect to the filter.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"filter\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"out_backprop\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"use_cudnn_on_gpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv2DBackpropInput\",\n    \"summary\": \"Computes the gradients of convolution with respect to the input.\",\n    \"operands\": [\n      { \"name\": \"input_sizes\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" },\n      { \"name\": \"out_backprop\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"use_cudnn_on_gpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv2DBackpropInputV2\",\n    \"summary\": \"Computes the gradients of convolution with respect to the input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" },\n      { \"name\": \"out_backprop\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"use_cudnn_on_gpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv3D\",\n    \"summary\": \"Computes a 3-D convolution given 5-D `input` and `filter` tensors.\",\n    \"description\": \"In signal processing, cross-correlation is a measure of similarity of\\ntwo waveforms as a function of a time-lag applied to one of them. This\\nis also known as a sliding dot product or sliding inner-product.\\n\\nOur Conv3D implements a form of cross-correlation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"filter\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv3DBackpropFilter\",\n    \"summary\": \"Computes the gradients of 3-D convolution with respect to the filter.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"out_backprop\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv3DBackpropFilterV2\",\n    \"summary\": \"Computes the gradients of 3-D convolution with respect to the filter.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"filter_sizes\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"out_backprop\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv3DBackpropInput\",\n    \"summary\": \"Computes the gradients of 3-D convolution with respect to the input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"out_backprop\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Conv3DBackpropInputV2\",\n    \"summary\": \"Computes the gradients of 3-D convolution with respect to the input.\",\n    \"operands\": [\n      { \"name\": \"input_sizes\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"filter\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"out_backprop\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConvertToCooTensor\",\n    \"summary\": \"Op that converts tensors into coo format.\",\n    \"description\": \"This op coverts the dense, sparse and ragged tensor into standard coo tensor\\nformat which contains three 1D tensors.\",\n    \"operands\": [\n      { \"name\": \"indices_or_row_splits\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"row_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"col_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gains\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"combiner\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConvertToListOfSparseCoreCooTensors\",\n    \"summary\": \"An op which converts the sparse/ragged/dense tensor into a list of COO tensor for each SparseCore.\",\n    \"operands\": [\n      { \"name\": \"indices_or_row_splits\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"row_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"col_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"gains_list\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"row_offset\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"col_offset\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"col_shift\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_sc_shards\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"stacked_table_sample_count\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"combiner\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ConvertToSparseCoreCsrWrappedCooTensorOp\",\n    \"summary\": \"An op which converts the sorted coo tensor into sparse core CSR wrapped COO format.\",\n    \"operands\": [\n      { \"name\": \"sorted_row_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"sorted_col_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"sorted_gains_list\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"id_counts_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"splits\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"row_pointers_unpadded_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"ids_unpadded_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_minibatches_per_sc\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count_per_sc\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_replica\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_minibatches_per_sc\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_ids_per_chip_per_sample\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_vocab_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"feature_width\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"allow_id_dropping\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cos\",\n    \"summary\": \"Computes cos of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes cosine of every\\n  element in the tensor. Input range is `(-inf, inf)` and\\n  output range is `[-1,1]`. If input lies outside the boundary, `nan`\\n  is returned.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -9, -0.5, 1, 1.2, 200, 10000, float(\\\"inf\\\")])\\n  tf.math.cos(x) ==> [nan -0.91113025 0.87758255 0.5403023 0.36235774 0.48718765 -0.95215535 nan]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cosh\",\n    \"summary\": \"Computes hyperbolic cosine of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes hyperbolic cosine of every\\n  element in the tensor. Input range is `[-inf, inf]` and output range\\n  is `[1, inf]`.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -9, -0.5, 1, 1.2, 2, 10, float(\\\"inf\\\")])\\n  tf.math.cosh(x) ==> [inf 4.0515420e+03 1.1276259e+00 1.5430807e+00 1.8106556e+00 3.7621956e+00 1.1013233e+04 inf]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CreateSummaryDbWriter\",\n    \"summary\": \"Creates summary database writer accessible by given resource handle.\",\n    \"description\": \"This can be used to write tensors from the execution graph directly\\nto a database. Only SQLite is supported right now. This function\\nwill create the schema if it doesn't exist. Entries in the Users,\\nExperiments, and Runs tables will be created automatically if they\\ndon't already exist.\\n\\nwriter: Handle to SummaryWriter resource to overwrite.\\ndb_uri: For example \\\"file:/tmp/foo.sqlite\\\".\\nexperiment_name: Can't contain ASCII control characters or <>. Case\\n  sensitive. If empty, then the Run will not be associated with any\\n  Experiment.\\nrun_name: Can't contain ASCII control characters or <>. Case sensitive.\\n  If empty, then each Tag will not be associated with any Run.\\nuser_name: Must be valid as both a DNS label and Linux username. If\\n  empty, then the Experiment will not be associated with any User.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"db_uri\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"experiment_name\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"run_name\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"user_name\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CreateSummaryFileWriter\",\n    \"summary\": \"Creates a summary file writer accessible by the given resource handle.\",\n    \"description\": \"writer: A handle to the summary writer resource\\nlogdir: Directory where the event file will be written.\\nmax_queue: Size of the queue of pending events and summaries.\\nflush_millis: How often, in milliseconds, to flush the pending events and\\n  summaries to disk.\\nfilename_suffix: Every event file's name is suffixed with this suffix.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"logdir\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"max_queue\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"flush_millis\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"filename_suffix\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cross\",\n    \"summary\": \"Compute the pairwise cross product.\",\n    \"description\": \"`a` and `b` must be the same shape; they can either be simple 3-element vectors,\\nor any shape where the innermost dimension is 3. In the latter case, each pair\\nof corresponding 3-element vectors is cross-multiplied independently.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"b\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CrossReplicaSum\",\n    \"summary\": \"An Op to sum inputs across replicated TPU instances.\",\n    \"description\": \"Each instance supplies its own input.\\n\\nFor example, suppose there are 8 TPU instances: `[A, B, C, D, E, F, G, H]`.\\nPassing group_assignment=`[[0,2,4,6],[1,3,5,7]]` sets `A, C, E, G` as group 0,\\nand `B, D, F, H` as group 1. Thus we get the outputs:\\n`[A+C+E+G, B+D+F+H, A+C+E+G, B+D+F+H, A+C+E+G, B+D+F+H, A+C+E+G, B+D+F+H]`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Uint32 ]>\" },\n      { \"name\": \"group_assignment\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Uint32 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cumprod\",\n    \"summary\": \"Compute the cumulative product of the tensor `x` along `axis`.\",\n    \"description\": \"By default, this op performs an inclusive cumprod, which means that the first\\nelement of the input is identical to the first element of the output:\\n\\n```python\\ntf.cumprod([a, b, c])  # => [a, a * b, a * b * c]\\n```\\n\\nBy setting the `exclusive` kwarg to `True`, an exclusive cumprod is\\nperformed instead:\\n\\n```python\\ntf.cumprod([a, b, c], exclusive=True)  # => [1, a, a * b]\\n```\\n\\nBy setting the `reverse` kwarg to `True`, the cumprod is performed in the\\nopposite direction:\\n\\n```python\\ntf.cumprod([a, b, c], reverse=True)  # => [a * b * c, b * c, c]\\n```\\n\\nThis is more efficient than using separate `tf.reverse` ops.\\n\\nThe `reverse` and `exclusive` kwargs can also be combined:\\n\\n```python\\ntf.cumprod([a, b, c], exclusive=True, reverse=True)  # => [b * c, c, 1]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"reverse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Cumsum\",\n    \"summary\": \"Compute the cumulative sum of the tensor `x` along `axis`.\",\n    \"description\": \"By default, this op performs an inclusive cumsum, which means that the first\\nelement of the input is identical to the first element of the output:\\n\\n```python\\ntf.cumsum([a, b, c])  # => [a, a + b, a + b + c]\\n```\\n\\nBy setting the `exclusive` kwarg to `True`, an exclusive cumsum is\\nperformed instead:\\n\\n```python\\ntf.cumsum([a, b, c], exclusive=True)  # => [0, a, a + b]\\n```\\n\\nBy setting the `reverse` kwarg to `True`, the cumsum is performed in the\\nopposite direction:\\n\\n```python\\ntf.cumsum([a, b, c], reverse=True)  # => [a + b + c, b + c, c]\\n```\\n\\nThis is more efficient than using separate `tf.reverse` ops.\\n\\nThe `reverse` and `exclusive` kwargs can also be combined:\\n\\n```python\\ntf.cumsum([a, b, c], exclusive=True, reverse=True)  # => [b + c, c, 0]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"reverse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.CumulativeLogsumexp\",\n    \"summary\": \"Compute the cumulative product of the tensor `x` along `axis`.\",\n    \"description\": \"By default, this op performs an inclusive cumulative log-sum-exp,\\nwhich means that the first\\nelement of the input is identical to the first element of the output:\\n```python\\ntf.math.cumulative_logsumexp([a, b, c])  # => [a, log(exp(a) + exp(b)), log(exp(a) + exp(b) + exp(c))]\\n```\\n\\nBy setting the `exclusive` kwarg to `True`, an exclusive cumulative log-sum-exp is\\nperformed instead:\\n```python\\ntf.cumulative_logsumexp([a, b, c], exclusive=True)  # => [-inf, a, log(exp(a) * exp(b))]\\n```\\nNote that the neutral element of the log-sum-exp operation is `-inf`,\\nhowever, for performance reasons, the minimal value representable by the\\nfloating point type is used instead.\\n\\nBy setting the `reverse` kwarg to `True`, the cumulative log-sum-exp is performed in the\\nopposite direction.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"reverse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DataFormatDimMap\",\n    \"summary\": \"Returns the dimension index in the destination data format given the one in\",\n    \"description\": \"the source data format.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src_format\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dst_format\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"NCHW\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DataFormatVecPermute\",\n    \"summary\": \"Permute input tensor from `src_format` to `dst_format`.\",\n    \"description\": \"Given source and destination format strings of length n=4 or 5, the input\\ntensor must be a vector of size n or n-2, or a 2D tensor of shape\\n(n, 2) or (n-2, 2).\\n\\nIf the first dimension of the input tensor is n-2, it is assumed that\\nnon-spatial dimensions are omitted (i.e `N`, `C`).\\n\\nFor example, with `src_format` of `NHWC`, `dst_format` of `NCHW`, and input:\\n```\\n[1, 2, 3, 4]\\n```\\n, the output will be:\\n```\\n[1, 4, 2, 3]\\n```\\nWith `src_format` of `NDHWC`, `dst_format` of `NCDHW`, and input:\\n```\\n[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]\\n```\\n, the output will be:\\n```\\n[[1, 6], [5, 10], [2, 7], [3, 8], [4, 9]]\\n```\\nWith `src_format` of `NHWC`, `dst_format` of `NCHW`, and input:\\n```\\n[1, 2]\\n```\\n, the output will be:\\n```\\n[1, 2]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src_format\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dst_format\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"NCHW\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DebugIdentity\",\n    \"summary\": \"Provides an identity mapping of the non-Ref type input tensor for debugging.\",\n    \"description\": \"Provides an identity mapping of the non-Ref type input tensor for debugging.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"tensor_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"debug_urls\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"gated_grpc\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DebugIdentityV2\",\n    \"summary\": \"Debug Identity V2 Op.\",\n    \"description\": \"Provides an identity mapping from input to output, while writing the content of\\nthe input tensor by calling DebugEventsWriter.\\n\\nThe semantics of the input tensor depends on tensor_debug_mode. In typical\\nusage, the input tensor comes directly from the user computation only when\\ngraph_debug_mode is FULL_TENSOR (see protobuf/debug_event.proto for a\\nlist of all the possible values of graph_debug_mode). For the other debug modes,\\nthe input tensor should be produced by an additional op or subgraph that\\ncomputes summary information about one or more tensors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tfdbg_context_id\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"op_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"output_slot\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"tensor_debug_mode\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"debug_urls\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"circular_buffer_size\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1000>\" },\n      { \"name\": \"tfdbg_run_id\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DecodeAndCropJpeg\",\n    \"summary\": \"Decode and Crop a JPEG-encoded image to a uint8 tensor.\",\n    \"description\": \"The attr `channels` indicates the desired number of color channels for the\\ndecoded image.\\n\\nAccepted values are:\\n\\n*   0: Use the number of channels in the JPEG-encoded image.\\n*   1: output a grayscale image.\\n*   3: output an RGB image.\\n\\nIf needed, the JPEG-encoded image is transformed to match the requested number\\nof color channels.\\n\\nThe attr `ratio` allows downscaling the image by an integer factor during\\ndecoding.  Allowed values are: 1, 2, 4, and 8.  This is much faster than\\ndownscaling the image later.\\n\\n\\nIt is equivalent to a combination of decode and crop, but much faster by only\\ndecoding partial jpeg image.\",\n    \"operands\": [\n      { \"name\": \"contents\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"crop_window\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"image\", \"type\": \"TF_Uint8Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channels\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ratio\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"fancy_upscaling\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"try_recover_truncated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"acceptable_fraction\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"dct_method\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DecodeGif\",\n    \"summary\": \"Decode the frame(s) of a GIF-encoded image to a uint8 tensor.\",\n    \"description\": \"GIF images with frame or transparency compression are not supported.\\nOn Linux and MacOS systems, convert animated GIFs from compressed to\\nuncompressed by running:\\n\\n    convert $src.gif -coalesce $dst.gif\\n\\nThis op also supports decoding JPEGs and PNGs, though it is cleaner to use\\n`tf.io.decode_image`.\",\n    \"operands\": [\n      { \"name\": \"contents\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"image\", \"type\": \"TF_Uint8Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DecodeJpeg\",\n    \"summary\": \"Decode a JPEG-encoded image to a uint8 tensor.\",\n    \"description\": \"The attr `channels` indicates the desired number of color channels for the\\ndecoded image.\\n\\nAccepted values are:\\n\\n*   0: Use the number of channels in the JPEG-encoded image.\\n*   1: output a grayscale image.\\n*   3: output an RGB image.\\n\\nIf needed, the JPEG-encoded image is transformed to match the requested number\\nof color channels.\\n\\nThe attr `ratio` allows downscaling the image by an integer factor during\\ndecoding.  Allowed values are: 1, 2, 4, and 8.  This is much faster than\\ndownscaling the image later.\\n\\n\\nThis op also supports decoding PNGs and non-animated GIFs since the interface is\\nthe same, though it is cleaner to use `tf.io.decode_image`.\",\n    \"operands\": [\n      { \"name\": \"contents\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"image\", \"type\": \"TF_Uint8Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channels\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ratio\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"fancy_upscaling\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"try_recover_truncated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"acceptable_fraction\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"dct_method\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DecodePaddedRaw\",\n    \"summary\": \"Reinterpret the bytes of a string as a vector of numbers.\",\n    \"operands\": [\n      { \"name\": \"input_bytes\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"fixed_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"little_endian\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DecodePng\",\n    \"summary\": \"Decode a PNG-encoded image to a uint8 or uint16 tensor.\",\n    \"description\": \"The attr `channels` indicates the desired number of color channels for the\\ndecoded image.\\n\\nAccepted values are:\\n\\n*   0: Use the number of channels in the PNG-encoded image.\\n*   1: output a grayscale image.\\n*   3: output an RGB image.\\n*   4: output an RGBA image.\\n\\nIf needed, the PNG-encoded image is transformed to match the requested number\\nof color channels.\\n\\nThis op also supports decoding JPEGs and non-animated GIFs since the interface\\nis the same, though it is cleaner to use `tf.io.decode_image`.\",\n    \"operands\": [\n      { \"name\": \"contents\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"image\", \"type\": \"TensorOf<[ TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channels\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeleteIterator\",\n    \"summary\": \"A container for an iterator resource.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeleteMemoryCache\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeleteMultiDeviceIterator\",\n    \"summary\": \"A container for an iterator resource.\",\n    \"operands\": [\n      { \"name\": \"multi_device_iterator\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"iterators\", \"type\": \"Variadic<TF_ResourceTensor>\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeleteRandomSeedGenerator\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeleteSeedGenerator\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"deleter\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DepthToSpace\",\n    \"summary\": \"DepthToSpace for tensors of type T.\",\n    \"description\": \"Rearranges data from depth into blocks of spatial data.\\nThis is the reverse transformation of SpaceToDepth. More specifically,\\nthis op outputs a copy of the input tensor where values from the `depth`\\ndimension are moved in spatial blocks to the `height` and `width` dimensions.\\nThe attr `block_size` indicates the input block size and how the data is moved.\\n\\n  * Chunks of data of size `block_size * block_size` from depth are rearranged\\n    into non-overlapping blocks of size `block_size x block_size`\\n  * The width of the output tensor is `input_depth * block_size`, whereas the\\n    height is `input_height * block_size`.\\n  * The Y, X coordinates within each block of the output image are determined\\n    by the high order component of the input channel index.\\n  * The depth of the input tensor must be divisible by\\n    `block_size * block_size`.\\n\\nThe `data_format` attr specifies the layout of the input and output tensors\\nwith the following options:\\n  \\\"NHWC\\\": `[ batch, height, width, channels ]`\\n  \\\"NCHW\\\": `[ batch, channels, height, width ]`\\n  \\\"NCHW_VECT_C\\\":\\n      `qint8 [ batch, channels / 4, height, width, 4 ]`\\n\\nIt is useful to consider the operation as transforming a 6-D Tensor.\\ne.g. for data_format = NHWC,\\n     Each element in the input tensor can be specified via 6 coordinates,\\n     ordered by decreasing memory layout significance as:\\n     n,iY,iX,bY,bX,oC  (where n=batch index, iX, iY means X or Y coordinates\\n                        within the input image, bX, bY means coordinates\\n                        within the output block, oC means output channels).\\n     The output would be the input transposed to the following layout:\\n     n,iY,bY,iX,bX,oC\\n\\nThis operation is useful for resizing the activations between convolutions\\n(but keeping all data), e.g. instead of pooling. It is also useful for training\\npurely convolutional models.\\n\\nFor example, given an input of shape `[1, 1, 1, 4]`, data_format = \\\"NHWC\\\" and\\nblock_size = 2:\\n\\n```\\nx = [[[[1, 2, 3, 4]]]]\\n\\n```\\n\\nThis operation will output a tensor of shape `[1, 2, 2, 1]`:\\n\\n```\\n   [[[[1], [2]],\\n     [[3], [4]]]]\\n```\\n\\nHere, the input has a batch of 1 and each batch element has shape `[1, 1, 4]`,\\nthe corresponding output will have 2x2 elements and will have a depth of\\n1 channel (1 = `4 / (block_size * block_size)`).\\nThe output element shape is `[2, 2, 1]`.\\n\\nFor an input tensor with larger depth, here of shape `[1, 1, 1, 12]`, e.g.\\n\\n```\\nx = [[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]]\\n```\\n\\nThis operation, for block size of 2, will return the following tensor of shape\\n`[1, 2, 2, 3]`\\n\\n```\\n   [[[[1, 2, 3], [4, 5, 6]],\\n     [[7, 8, 9], [10, 11, 12]]]]\\n\\n```\\n\\nSimilarly, for the following input of shape `[1 2 2 4]`, and a block size of 2:\\n\\n```\\nx =  [[[[1, 2, 3, 4],\\n       [5, 6, 7, 8]],\\n      [[9, 10, 11, 12],\\n       [13, 14, 15, 16]]]]\\n```\\n\\nthe operator will return the following tensor of shape `[1 4 4 1]`:\\n\\n```\\nx = [[[ [1],   [2],  [5],  [6]],\\n      [ [3],   [4],  [7],  [8]],\\n      [ [9],  [10], [13],  [14]],\\n      [ [11], [12], [15],  [16]]]]\\n\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<2>]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NCHW_VECT_C ]>, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DepthwiseConv2dNative\",\n    \"summary\": \"Computes a 2-D depthwise convolution given 4-D `input` and `filter` tensors.\",\n    \"description\": \"Given an input tensor of shape `[batch, in_height, in_width, in_channels]`\\nand a filter / kernel tensor of shape\\n`[filter_height, filter_width, in_channels, channel_multiplier]`, containing\\n`in_channels` convolutional filters of depth 1, `depthwise_conv2d` applies\\na different filter to each input channel (expanding from 1 channel to\\n`channel_multiplier` channels for each), then concatenates the results\\ntogether. Thus, the output has `in_channels * channel_multiplier` channels.\\n\\n```\\nfor k in 0..in_channels-1\\n  for q in 0..channel_multiplier-1\\n    output[b, i, j, k * channel_multiplier + q] =\\n      sum_{di, dj} input[b, strides[1] * i + di, strides[2] * j + dj, k] *\\n                        filter[di, dj, k, q]\\n```\\n\\nMust have `strides[0] = strides[3] = 1`.  For the most common case of the same\\nhorizontal and vertices strides, `strides = [1, stride, stride, 1]`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"filter\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DepthwiseConv2dNativeBackpropFilter\",\n    \"summary\": \"Computes the gradients of depthwise convolution with respect to the filter.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"filter_sizes\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"out_backprop\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DepthwiseConv2dNativeBackpropInput\",\n    \"summary\": \"Computes the gradients of depthwise convolution with respect to the input.\",\n    \"operands\": [\n      { \"name\": \"input_sizes\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"filter\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"out_backprop\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Dequantize\",\n    \"summary\": \"Dequantize the 'input' tensor into a float or bfloat16 Tensor.\",\n    \"description\": \"[min_range, max_range] are scalar floats that specify the range for\\nthe output. The 'mode' attribute controls exactly which calculations are\\nused to convert the float values to their quantized equivalents.\\n\\nIn 'MIN_COMBINED' mode, each value of the tensor will undergo the following:\\n\\n```\\nif T == qint8: in[i] += (range(T) + 1)/ 2.0\\nout[i] = min_range + (in[i]* (max_range - min_range) / range(T))\\n```\\nhere `range(T) = numeric_limits<T>::max() - numeric_limits<T>::min()`\\n\\n*MIN_COMBINED Mode Example*\\n\\nIf the input comes from a QuantizedRelu6, the output type is\\nquint8 (range of 0-255) but the possible range of QuantizedRelu6 is\\n0-6.  The min_range and max_range values are therefore 0.0 and 6.0.\\nDequantize on quint8 will take each value, cast to float, and multiply\\nby 6 / 255.\\nNote that if quantizedtype is qint8, the operation will additionally add\\neach value by 128 prior to casting.\\n\\nIf the mode is 'MIN_FIRST', then this approach is used:\\n\\n```c++\\nnum_discrete_values = 1 << (# of bits in T)\\nrange_adjust = num_discrete_values / (num_discrete_values - 1)\\nrange = (range_max - range_min) * range_adjust\\nrange_scale = range / num_discrete_values\\nconst double offset_input = static_cast<double>(input) - lowest_quantized;\\nresult = range_min + ((input - numeric_limits<T>::min()) * range_scale)\\n```\\n\\nIf the mode is `SCALED`, dequantization is performed by multiplying each\\ninput value by a scaling_factor. (Thus an input of 0 always maps to 0.0).\\n\\nThe scaling_factor is determined from `min_range`, `max_range`, and\\n`narrow_range` in a way that is compatible with `QuantizeAndDequantize{V2|V3}`\\nand `QuantizeV2`, using the following algorithm:\\n\\n```c++\\n\\n  const int min_expected_T = std::numeric_limits<T>::min() +\\n    (narrow_range ? 1 : 0);\\n  const int max_expected_T = std::numeric_limits<T>::max();\\n  const float max_expected_T = std::numeric_limits<float>::max();\\n\\n  const float scale_factor =\\n    (std::numeric_limits<T>::min() == 0) ? (max_range / max_expected_T)\\n                                         : std::max(min_range / min_expected_T,\\n                                                    max_range / max_expected_T);\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8]>\" },\n      { \"name\": \"min_range\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"max_range\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ MIN_COMBINED, MIN_FIRST, SCALED ]>, \\\"MIN_COMBINED\\\">\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeserializeIterator\",\n    \"summary\": \"Converts the given variant tensor to an iterator and stores it in the given resource.\",\n    \"operands\": [\n      { \"name\": \"resource_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"serialized\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeserializeSparse\",\n    \"summary\": \"Deserialize `SparseTensor` objects.\",\n    \"description\": \"The input `serialized_sparse` must have the shape `[?, ?, ..., ?, 3]` where\\nthe last dimension stores serialized `SparseTensor` objects and the other N\\ndimensions (N >= 0) correspond to a batch. The ranks of the original\\n`SparseTensor` objects must all match. When the final `SparseTensor` is\\ncreated, its rank is the rank of the incoming `SparseTensor` objects plus N;\\nthe sparse tensors have been concatenated along new dimensions, one for each\\nbatch.\\n\\nThe output `SparseTensor` object's shape values for the original dimensions\\nare the max across the input `SparseTensor` objects' shape values for the\\ncorresponding dimensions. The new dimensions match the size of the batch.\\n\\nThe input `SparseTensor` objects' indices are assumed ordered in\\nstandard lexicographic order.  If this is not the case, after this\\nstep run `SparseReorder` to restore index ordering.\\n\\nFor example, if the serialized input is a `[2 x 3]` matrix representing two\\noriginal `SparseTensor` objects:\\n\\n    index = [ 0]\\n            [10]\\n            [20]\\n    values = [1, 2, 3]\\n    shape = [50]\\n\\nand\\n\\n    index = [ 2]\\n            [10]\\n    values = [4, 5]\\n    shape = [30]\\n\\nthen the final deserialized `SparseTensor` will be:\\n\\n    index = [0  0]\\n            [0 10]\\n            [0 20]\\n            [1  2]\\n            [1 10]\\n    values = [1, 2, 3, 4, 5]\\n    shape = [2 50]\",\n    \"operands\": [\n      { \"name\": \"serialized_sparse\", \"type\": \"TensorOf<[ TF_Str, TF_Variant ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sparse_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"sparse_values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"sparse_shape\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DestroyResourceOp\",\n    \"summary\": \"Deletes the resource specified by the handle.\",\n    \"description\": \"All subsequent operations using the resource will result in a NotFound\\nerror status.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ignore_lookup_error\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DeviceIndex\",\n    \"summary\": \"Return the index of device the op runs.\",\n    \"description\": \"Given a list of device names, this operation returns the index of the device\\nthis op runs. The length of the list is returned in two cases:\\n(1) Device does not exist in the given device list.\\n(2) It is in XLA compilation.\",\n    \"results\": [\n      { \"name\": \"index\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Diag\",\n    \"summary\": \"Returns a diagonal tensor with a given diagonal values.\",\n    \"description\": \"Given a `diagonal`, this operation returns a tensor with the `diagonal` and\\neverything else padded with zeros. The diagonal is computed as follows:\\n\\nAssume `diagonal` has dimensions [D1,..., Dk], then the output is a tensor of\\nrank 2k with dimensions [D1,..., Dk, D1,..., Dk] where:\\n\\n`output[i1,..., ik, i1,..., ik] = diagonal[i1, ..., ik]` and 0 everywhere else.\\n\\nFor example:\\n\\n```\\n# 'diagonal' is [1, 2, 3, 4]\\ntf.diag(diagonal) ==> [[1, 0, 0, 0]\\n                       [0, 2, 0, 0]\\n                       [0, 0, 3, 0]\\n                       [0, 0, 0, 4]]\\n```\",\n    \"operands\": [\n      { \"name\": \"diagonal\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DiagPart\",\n    \"summary\": \"Returns the diagonal part of the tensor.\",\n    \"description\": \"This operation returns a tensor with the `diagonal` part\\nof the `input`. The `diagonal` part is computed as follows:\\n\\nAssume `input` has dimensions `[D1,..., Dk, D1,..., Dk]`, then the output is a\\ntensor of rank `k` with dimensions `[D1,..., Dk]` where:\\n\\n`diagonal[i1,..., ik] = input[i1, ..., ik, i1,..., ik]`.\\n\\nFor example:\\n\\n```\\n# 'input' is [[1, 0, 0, 0]\\n              [0, 2, 0, 0]\\n              [0, 0, 3, 0]\\n              [0, 0, 0, 4]]\\n\\ntf.diag_part(input) ==> [1, 2, 3, 4]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"diagonal\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Digamma\",\n    \"summary\": \"Computes Psi, the derivative of Lgamma (the log of the absolute value of\",\n    \"description\": \"`Gamma(x)`), element-wise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DisableCopyOnRead\",\n    \"summary\": \"Turns off the copy-on-read mode.\",\n    \"description\": \"Turns off the copy-on-read mode of a resource variable. If the variable is not in copy-on-read mode, this op has no effect.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Div\",\n    \"summary\": \"Returns x / y element-wise.\",\n    \"description\": \"*NOTE*: `Div` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DivNoNan\",\n    \"summary\": \"Returns 0 if the denominator is zero.\",\n    \"description\": \"*NOTE*: `DivNoNan` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DummyMemoryCache\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DummySeedGenerator\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DynamicEnqueueTPUEmbeddingArbitraryTensorBatch\",\n    \"summary\": \"Eases the porting of code that uses tf.nn.embedding_lookup_sparse().\",\n    \"description\": \"embedding_indices[i] and aggregation_weights[i] correspond\\nto the ith feature.\\n\\nThe tensors at corresponding positions in the three input lists (sample_indices,\\nembedding_indices and aggregation_weights) must have the same shape, i.e. rank 1\\nwith dim_size() equal to the total number of lookups into the table described by\\nthe corresponding feature.\",\n    \"operands\": [\n      { \"name\": \"sample_indices_or_row_splits\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"embedding_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"aggregation_weights\", \"type\": \"Variadic<TF_F32OrF64Tensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"device_ordinal\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"combiners\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DynamicPartition\",\n    \"summary\": \"Partitions `data` into `num_partitions` tensors using indices from `partitions`.\",\n    \"description\": \"For each index tuple `js` of size `partitions.ndim`, the slice `data[js, ...]`\\nbecomes part of `outputs[partitions[js]]`.  The slices with `partitions[js] = i`\\nare placed in `outputs[i]` in lexicographic order of `js`, and the first\\ndimension of `outputs[i]` is the number of entries in `partitions` equal to `i`.\\nIn detail,\\n\\n```python\\n    outputs[i].shape = [sum(partitions == i)] + data.shape[partitions.ndim:]\\n\\n    outputs[i] = pack([data[js, ...] for js if partitions[js] == i])\\n```\\n\\n`data.shape` must start with `partitions.shape`.\\n\\nFor example:\\n\\n```python\\n    # Scalar partitions.\\n    partitions = 1\\n    num_partitions = 2\\n    data = [10, 20]\\n    outputs[0] = []  # Empty with shape [0, 2]\\n    outputs[1] = [[10, 20]]\\n\\n    # Vector partitions.\\n    partitions = [0, 0, 1, 1, 0]\\n    num_partitions = 2\\n    data = [10, 20, 30, 40, 50]\\n    outputs[0] = [10, 20, 50]\\n    outputs[1] = [30, 40]\\n```\\n\\nSee `dynamic_stitch` for an example on how to merge partitions back.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/DynamicPartition.png\\\" alt>\\n</div>\\n\\n\\nRaises:\\n  * `InvalidArgumentError` in following cases:\\n    - If partitions is not in range `[0, num_partiions)`\\n    - If `partitions.shape` does not match prefix of `data.shape` argument.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"partitions\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.DynamicStitch\",\n    \"summary\": \"Interleave the values from the `data` tensors into a single tensor.\",\n    \"description\": \"Builds a merged tensor such that\\n\\n```python\\n    merged[indices[m][i, ..., j], ...] = data[m][i, ..., j, ...]\\n```\\n\\nFor example, if each `indices[m]` is scalar or vector, we have\\n\\n```python\\n    # Scalar indices:\\n    merged[indices[m], ...] = data[m][...]\\n\\n    # Vector indices:\\n    merged[indices[m][i], ...] = data[m][i, ...]\\n```\\n\\nEach `data[i].shape` must start with the corresponding `indices[i].shape`,\\nand the rest of `data[i].shape` must be constant w.r.t. `i`.  That is, we\\nmust have `data[i].shape = indices[i].shape + constant`.  In terms of this\\n`constant`, the output shape is\\n\\n    merged.shape = [max(indices) + 1] + constant\\n\\nValues are merged in order, so if an index appears in both `indices[m][i]` and\\n`indices[n][j]` for `(m,i) < (n,j)` the slice `data[n][j]` will appear in the\\nmerged result. If you do not need this guarantee, ParallelDynamicStitch might\\nperform better on some devices.\\n\\nFor example:\\n\\n```python\\n    indices[0] = 6\\n    indices[1] = [4, 1]\\n    indices[2] = [[5, 2], [0, 3]]\\n    data[0] = [61, 62]\\n    data[1] = [[41, 42], [11, 12]]\\n    data[2] = [[[51, 52], [21, 22]], [[1, 2], [31, 32]]]\\n    merged = [[1, 2], [11, 12], [21, 22], [31, 32], [41, 42],\\n              [51, 52], [61, 62]]\\n```\\n\\nThis method can be used to merge partitions created by `dynamic_partition`\\nas illustrated on the following example:\\n\\n```python\\n    # Apply function (increments x_i) on elements for which a certain condition\\n    # apply (x_i != -1 in this example).\\n    x=tf.constant([0.1, -1., 5.2, 4.3, -1., 7.4])\\n    condition_mask=tf.not_equal(x,tf.constant(-1.))\\n    partitioned_data = tf.dynamic_partition(\\n        x, tf.cast(condition_mask, tf.int32) , 2)\\n    partitioned_data[1] = partitioned_data[1] + 1.0\\n    condition_indices = tf.dynamic_partition(\\n        tf.range(tf.shape(x)[0]), tf.cast(condition_mask, tf.int32) , 2)\\n    x = tf.dynamic_stitch(condition_indices, partitioned_data)\\n    # Here x=[1.1, -1., 6.2, 5.3, -1, 8.4], the -1. values remain\\n    # unchanged.\\n```\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/DynamicStitch.png\\\" alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"data\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"merged\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Einsum\",\n    \"summary\": \"Tensor contraction according to Einstein summation convention.\",\n    \"description\": \"Implements generalized Tensor contraction and reduction. Each input Tensor must\\nhave a corresponding input subscript appearing in the comma-separated left-hand\\nside of the equation. The right-hand side of the equation consists of the\\noutput subscript. The input subscripts and the output subscript should consist\\nof zero or more named axis labels and at most one ellipsis (`...`).\\n\\nThe named axis labels may be any single character other than those having\\nspecial meaning, namely `,.->`. The behavior of this Op is undefined if it\\nreceives an ill-formatted equation; since the validation is done at\\ngraph-building time, we omit format validation checks at runtime.\\n\\nNote: This Op is *not* intended to be called by the user; instead users should\\ncall `tf.einsum` directly. It is a hidden Op used by `tf.einsum`.\\n\\nOperations are applied to the input(s) according to the following rules:\\n\\n (a) Generalized Diagonals: For input dimensions corresponding to axis labels\\n     appearing more than once in the same input subscript, we take the\\n     generalized (`k`-dimensional) diagonal.\\n     For example, in the equation `iii->i` with input shape `[3, 3, 3]`, the\\n     generalized diagonal would consist of `3` elements at indices `(0, 0, 0)`,\\n     `(1, 1, 1)` and `(2, 2, 2)` to create a Tensor of shape `[3]`.\\n\\n (b) Reduction: Axes corresponding to labels appearing only in one input\\n     subscript but not in the output subscript are summed over prior to Tensor\\n     contraction.\\n     For example, in the equation `ab,bc->b`, the axis labels `a` and `c` are\\n     the reduction axis labels.\\n\\n (c) Batch Dimensions: Axes corresponding to labels appearing in each of the\\n     input subscripts and also in the output subscript make up the batch\\n     dimensions in Tensor contraction. Unnamed axis labels corresponding to\\n     ellipsis (`...`) also correspond to batch dimensions.\\n     For example, for the equation denoting batch matrix multiplication,\\n     `bij,bjk->bik`, the axis label `b` corresponds to a batch dimension.\\n\\n (d) Contraction: In case of binary einsum, axes corresponding to labels\\n     appearing in two different inputs (and not in the output) are contracted\\n     against each other.\\n     Considering the batch matrix multiplication equation again\\n     (`bij,bjk->bik`), the contracted axis label is `j`.\\n\\n (e) Expand Diagonal: If the output subscripts contain repeated (explicit) axis\\n     labels, the opposite operation of (a) is applied. For example, in the\\n     equation `i->iii`, and input shape `[3]`, the output of shape `[3, 3, 3]`\\n     are all zeros, except for the (generalized) diagonal which is populated\\n     with values from the input.\\n     Note: This operation is not supported by `np.einsum` or `tf.einsum`; it is\\n     provided to enable computing the symbolic gradient of `tf.einsum`.\\n\\nThe output subscripts must contain only labels appearing in at least one of the\\ninput subscripts. Furthermore, all dimensions mapping to the same axis label\\nmust be equal.\\n\\nAny of the input and output subscripts may contain at most a single ellipsis\\n(`...`). These ellipsis are mapped against dimensions not corresponding to any\\nnamed axis label. If two inputs contain ellipsis, then they are broadcasted\\naccording to standard NumPy broadcasting\\n[rules](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html).\\n\\nThe broadcasted dimensions are placed in the corresponding location of the\\nellipsis in the output subscript. If the broadcasted dimensions are non-empty\\nand the output subscripts do not contain ellipsis, then an InvalidArgument error\\nis raised.\\n\\n@compatibility(numpy)\\nSimilar to [`numpy.einsum`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html).\\n\\nComparison with `numpy.einsum`:\\n\\n * This Op only supports unary and binary forms of `numpy.einsum`.\\n * This Op does not support implicit form. (i.e. equations without `->`).\\n * This Op also supports repeated indices in the output subscript, which is not\\n   supported by `numpy.einsum`.\\n@end_compatibility\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"equation\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Elu\",\n    \"summary\": \"Computes the exponential linear function.\",\n    \"description\": \"The ELU function is defined as:\\n\\n * $ e ^ x - 1 $ if $ x < 0 $\\n * $ x $ if $ x >= 0 $\\n\\nExamples:\\n\\n>>> tf.nn.elu(1.0)\\n<tf.Tensor: shape=(), dtype=float32, numpy=1.0>\\n>>> tf.nn.elu(0.0)\\n<tf.Tensor: shape=(), dtype=float32, numpy=0.0>\\n>>> tf.nn.elu(-1000.0)\\n<tf.Tensor: shape=(), dtype=float32, numpy=-1.0>\\n\\nSee [Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)\\n](http://arxiv.org/abs/1511.07289)\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EluGrad\",\n    \"summary\": \"Computes gradients for the exponential linear (Elu) operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"outputs\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Empty\",\n    \"summary\": \"Creates a tensor with the given shape.\\n\\nThis operation creates a tensor of `shape` and `dtype`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"init\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EmptyTensorList\",\n    \"summary\": \"Creates and returns an empty tensor list.\",\n    \"description\": \"All list elements must be tensors of dtype element_dtype and shape compatible\\nwith element_shape.\\n\\nhandle: an empty tensor list.\\nelement_dtype: the type of elements in the list.\\nelement_shape: a shape compatible with that of elements in the list.\",\n    \"operands\": [\n      { \"name\": \"element_shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"max_num_elements\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EncodePng\",\n    \"summary\": \"PNG-encode an image.\",\n    \"description\": \"`image` is a 3-D uint8 or uint16 Tensor of shape `[height, width, channels]`\\nwhere `channels` is:\\n\\n*   1: for grayscale.\\n*   2: for grayscale + alpha.\\n*   3: for RGB.\\n*   4: for RGBA.\\n\\nThe ZLIB compression level, `compression`, can be -1 for the PNG-encoder\\ndefault or a value from 0 to 9.  9 is the highest compression level, generating\\nthe smallest output, but is slower.\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"TensorOf<[ TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"contents\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"compression\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnqueueTPUEmbeddingArbitraryTensorBatch\",\n    \"summary\": \"Eases the porting of code that uses tf.nn.embedding_lookup_sparse().\",\n    \"description\": \"embedding_indices[i] and aggregation_weights[i] correspond\\nto the ith feature.\\n\\nThe tensors at corresponding positions in the three input lists (sample_indices,\\nembedding_indices and aggregation_weights) must have the same shape, i.e. rank 1\\nwith dim_size() equal to the total number of lookups into the table described by\\nthe corresponding feature.\",\n    \"operands\": [\n      { \"name\": \"sample_indices_or_row_splits\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"embedding_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"aggregation_weights\", \"type\": \"Variadic<TF_F32OrF64Tensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"combiners\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnqueueTPUEmbeddingBatch\",\n    \"summary\": \"An op that enqueues a list of input batch tensors to TPUEmbedding.\",\n    \"description\": \"An op that enqueues a list of input batch tensors to TPUEmbedding.\",\n    \"operands\": [\n      { \"name\": \"batch\", \"type\": \"Variadic<TF_StrTensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"combiners\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnqueueTPUEmbeddingIntegerBatch\",\n    \"summary\": \"An op that enqueues a list of input batch tensors to TPUEmbedding.\",\n    \"operands\": [\n      { \"name\": \"batch\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnqueueTPUEmbeddingRaggedTensorBatch\",\n    \"summary\": \"Eases the porting of code that uses tf.nn.embedding_lookup().\",\n    \"description\": \"sample_splits[i], embedding_indices[i] and aggregation_weights[i] correspond\\nto the ith feature. table_ids[i] indicates which embedding table to look up ith\\nfeature.\\n\\nThe tensors at corresponding positions in two of the input lists,\\nembedding_indices and aggregation_weights, must have the same shape, i.e. rank 1\\nwith dim_size() equal to the total number of lookups into the table described by\\nthe corresponding feature.\",\n    \"operands\": [\n      { \"name\": \"sample_splits\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"embedding_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"aggregation_weights\", \"type\": \"Variadic<TF_F32OrF64Tensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"combiners\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"table_ids\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"max_sequence_lengths\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"num_features\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnqueueTPUEmbeddingSparseBatch\",\n    \"summary\": \"An op that enqueues TPUEmbedding input indices from a SparseTensor.\",\n    \"description\": \"This Op eases the porting of code that uses embedding_lookup_sparse(),\\nalthough some Python preprocessing of the SparseTensor arguments to\\nembedding_lookup_sparse() is required to produce the arguments to this Op,\\nsince only a single EnqueueTPUEmbeddingSparseBatch Op is allowed per training\\nstep.\\n\\nThe tensors at corresponding positions in the three input lists\\nmust have the same shape, i.e. rank 1 with dim_size() equal to the total\\nnumber of lookups into the table described by the corresponding table_id.\",\n    \"operands\": [\n      { \"name\": \"sample_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"embedding_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"aggregation_weights\", \"type\": \"Variadic<TF_F32OrF64Tensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"combiners\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnqueueTPUEmbeddingSparseTensorBatch\",\n    \"summary\": \"Eases the porting of code that uses tf.nn.embedding_lookup_sparse().\",\n    \"description\": \"sample_indices[i], embedding_indices[i] and aggregation_weights[i] correspond\\nto the ith feature. table_ids[i] indicates which embedding table to look up ith\\nfeature.\\n\\nThe tensors at corresponding positions in the three input lists (sample_indices,\\nembedding_indices and aggregation_weights) must have the same shape, i.e. rank 1\\nwith dim_size() equal to the total number of lookups into the table described by\\nthe corresponding feature.\",\n    \"operands\": [\n      { \"name\": \"sample_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"embedding_indices\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"aggregation_weights\", \"type\": \"Variadic<TF_F32OrF64Tensor>\" },\n      { \"name\": \"mode_override\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"combiners\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"table_ids\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"max_sequence_lengths\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"num_features\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.EnsureShape\",\n    \"summary\": \"Ensures that the tensor's shape matches the expected shape.\",\n    \"description\": \"Raises an error if the input tensor's shape does not match the specified shape.\\nReturns the input tensor otherwise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Equal\",\n    \"summary\": \"Returns the truth value of (x == y) element-wise.\",\n    \"description\": \"*NOTE*: `Equal` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\\n\\n```python\\nx = tf.constant([2, 4])\\ny = tf.constant(2)\\ntf.math.equal(x, y) ==> array([True, False])\\n\\nx = tf.constant([2, 4])\\ny = tf.constant([2, 4])\\ntf.math.equal(x, y) ==> array([True,  True])\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"incompatible_shape_error\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Erf\",\n    \"summary\": \"Computes the [Gauss error function](https://en.wikipedia.org/wiki/Error_function) of `x` element-wise. In statistics, for non-negative values of $x$, the error function has the following interpretation: for a random variable $Y$ that is normally distributed with mean 0 and variance $1/\\\\sqrt{2}$, $erf(x)$ is the probability that $Y$ falls in the range $[−x, x]$.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Erfc\",\n    \"summary\": \"Computes the complementary error function of `x` element-wise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Erfinv\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ExecuteTPUEmbeddingPartitioner\",\n    \"summary\": \"An op that executes the TPUEmbedding partitioner on the central configuration\",\n    \"description\": \"device and computes the HBM size (in bytes) required for TPUEmbedding operation.\",\n    \"results\": [\n      { \"name\": \"common_config\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Exp\",\n    \"summary\": \"Computes exponential of x element-wise.  \\\\\\\\(y = e^x\\\\\\\\).\",\n    \"description\": \"This function computes the exponential of every element in the input tensor.\\n  i.e. `exp(x)` or `e^(x)`, where `x` is the input tensor.\\n  `e` denotes Euler's number and is approximately equal to 2.718281.\\n  Output is positive for any real input.\\n\\n  ```python\\n  x = tf.constant(2.0)\\n  tf.math.exp(x) ==> 7.389056\\n\\n  x = tf.constant([2.0, 8.0])\\n  tf.math.exp(x) ==> array([7.389056, 2980.958], dtype=float32)\\n  ```\\n\\n  For complex numbers, the exponential value is calculated as follows:\\n\\n  ```\\n  e^(x+iy) = e^x * e^iy = e^x * (cos y + i sin y)\\n  ```\\n\\n  Let's consider complex number 1+1j as an example.\\n  e^1 * (cos 1 + i sin 1) = 2.7182818284590 * (0.54030230586+0.8414709848j)\\n\\n  ```python\\n  x = tf.constant(1 + 1j)\\n  tf.math.exp(x) ==> 1.4686939399158851+2.2873552871788423j\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ExpandDims\",\n    \"summary\": \"Inserts a dimension of 1 into a tensor's shape.\",\n    \"description\": \"Given a tensor `input`, this operation inserts a dimension of 1 at the\\ndimension index `axis` of `input`'s shape. The dimension index `axis` starts at\\nzero; if you specify a negative number for `axis` it is counted backward from\\nthe end.\\n\\nThis operation is useful if you want to add a batch dimension to a single\\nelement. For example, if you have a single image of shape `[height, width,\\nchannels]`, you can make it a batch of 1 image with `expand_dims(image, 0)`,\\nwhich will make the shape `[1, height, width, channels]`.\\n\\nOther examples:\\n\\n```\\n# 't' is a tensor of shape [2]\\nshape(expand_dims(t, 0)) ==> [1, 2]\\nshape(expand_dims(t, 1)) ==> [2, 1]\\nshape(expand_dims(t, -1)) ==> [2, 1]\\n\\n# 't2' is a tensor of shape [2, 3, 5]\\nshape(expand_dims(t2, 0)) ==> [1, 2, 3, 5]\\nshape(expand_dims(t2, 2)) ==> [2, 3, 1, 5]\\nshape(expand_dims(t2, 3)) ==> [2, 3, 5, 1]\\n```\\n\\nThis operation requires that:\\n\\n`-1-input.dims() <= dim <= input.dims()`\\n\\nThis operation is related to `squeeze()`, which removes dimensions of\\nsize 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"dim\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Expm1\",\n    \"summary\": \"Computes `exp(x) - 1` element-wise.\",\n    \"description\": \"i.e. `exp(x) - 1` or `e^(x) - 1`, where `x` is the input tensor.\\n  `e` denotes Euler's number and is approximately equal to 2.718281.\\n\\n  ```python\\n  x = tf.constant(2.0)\\n  tf.math.expm1(x) ==> 6.389056\\n\\n  x = tf.constant([2.0, 8.0])\\n  tf.math.expm1(x) ==> array([6.389056, 2979.958], dtype=float32)\\n\\n  x = tf.constant(1 + 1j)\\n  tf.math.expm1(x) ==> (0.46869393991588515+2.2873552871788423j)\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ExtractImagePatches\",\n    \"summary\": \"Extract `patches` from `images` and put them in the \\\"depth\\\" output dimension.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"patches\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksizes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"rates\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeParam\",\n    \"summary\": \"This op is used as a placeholder in If branch functions. It doesn't provide a\\n  valid output when run, so must either be removed (e.g. replaced with a\\n  function input) or guaranteed not to be used (e.g. if mirroring an\\n  intermediate output needed for the gradient computation of the other branch).\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeQuantWithMinMaxArgs\",\n    \"summary\": \"Fake-quantize the 'inputs' tensor, type float to 'outputs' tensor of same shape and type.\",\n    \"description\": \"Quantization is called fake since the output is still in floating point.\\n  The API converts inputs into values within the range [min and max] and returns\\n  as output.\\n\\nAttributes\\n\\n*   `[min; max]` define the clamping range for the `inputs` data.\\n*   `inputs` values are quantized into the quantization range (\\n`[0; 2^num_bits - 1]` when `narrow_range` is false and `[1; 2^num_bits - 1]`\\nwhen it is true) and then de-quantized and output as floats in `[min; max]`\\ninterval.\\n*   `num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive.\\n\\nBefore quantization, `min` and `max` values are adjusted with the following\\nlogic.\\nIt is suggested to have `min <= 0 <= max`. If `0` is not in the range of values,\\nthe behavior can be unexpected:\\n\\n*   If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`.\\n*   If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`.\\n*   If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `,\\n`min_adj = scale * round(min / scale)` and `max_adj = max + min_adj - min`.\\n\\n\\nExamples\\n\\n```python\\n\\ninp = tf.constant ([10.03, -10.23, 3])\\nout = tf.quantization.fake_quant_with_min_max_args(inp, min=-5, max=5,\\n                                                   num_bits=16)\\nprint(out)\\n\\n#  Output:\\n#  tf.Tensor([ 4.9999237 -5.0000763  3.0000763], shape=(3,), dtype=float32)\\n```\\n\\nRaises:\\n  * InvalidArgumentError:\\n    - If num_bits are outside of range [2, 16].\\n    - If min >= max.\\n  * ValueError: If `inputs` are of any other type than float32.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, -6.0f>\" },\n      { \"name\": \"max\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 6.0f>\" },\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeQuantWithMinMaxArgsGradient\",\n    \"summary\": \"Compute gradients for a FakeQuantWithMinMaxArgs operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"inputs\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, -6.0f>\" },\n      { \"name\": \"max\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 6.0f>\" },\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeQuantWithMinMaxVars\",\n    \"summary\": \"Fake-quantize the 'inputs' tensor of type float via global float scalars\",\n    \"description\": \"Fake-quantize the `inputs` tensor of type float via global float scalars\\n`min` and `max` to `outputs` tensor of same shape as `inputs`.\\n\\nAttributes\\n\\n*   `[min; max]` define the clamping range for the `inputs` data.\\n*   `inputs` values are quantized into the quantization range (\\n`[0; 2^num_bits - 1]` when `narrow_range` is false and `[1; 2^num_bits - 1]`\\nwhen it is true) and then de-quantized and output as floats in `[min; max]`\\ninterval.\\n*   `num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive.\\n\\nBefore quantization, `min` and `max` values are adjusted with the following\\nlogic.\\nIt is suggested to have `min <= 0 <= max`. If `0` is not in the range of values,\\nthe behavior can be unexpected:\\n\\n*   If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`.\\n*   If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`.\\n*   If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `,\\n`min_adj = scale * round(min / scale)` and `max_adj = max + min_adj - min`.\\n\\nThis operation has a gradient and thus allows for training `min` and `max`\\nvalues.\\n\\n>>> constant_input = tf.constant([[1.2, -0.3, 0.7], [2.1, 0.5, -1.0]], dtype=tf.float32)\\n>>>\\n>>> min_val = -0.5\\n>>> max_val = 0.8\\n>>> num_bits = 8\\n>>> narrow_range = False #False:for the quantization range [0; 2^num_bits - 1]\\n>>>\\n>>> quantized_data = tf.quantization.fake_quant_with_min_max_vars(\\n...   inputs=constant_input, min=min_val, max=max_val, num_bits=num_bits, narrow_range=narrow_range\\n... )\\n>>>\\n>>> print(\\\"Input:\\\\n\\\", constant_input.numpy())\\nInput:\\n[[ 1.2 -0.3  0.7]\\n[ 2.1  0.5 -1. ]]\\n>>> print(\\\"Output:\\\\n\\\", quantized_data.numpy())\\nOutput:\\n[[ 0.8003921 -0.3007843  0.6984313]\\n[ 0.8003921  0.4996078 -0.4996078]]\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeQuantWithMinMaxVarsGradient\",\n    \"summary\": \"Compute gradients for a FakeQuantWithMinMaxVars operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"inputs\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops_wrt_input\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"backprop_wrt_min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"backprop_wrt_max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeQuantWithMinMaxVarsPerChannel\",\n    \"summary\": \"Fake-quantize the 'inputs' tensor of type float via per-channel floats\",\n    \"description\": \"Fake-quantize the `inputs` tensor of type float per-channel and one of the\\nshapes: `[d]`, `[b, d]` `[b, h, w, d]` via per-channel floats `min` and `max`\\nof shape `[d]` to `outputs` tensor of same shape as `inputs`.\\n\\nAttributes\\n\\n*   `[min; max]` define the clamping range for the `inputs` data.\\n*   `inputs` values are quantized into the quantization range (\\n`[0; 2^num_bits - 1]` when `narrow_range` is false and `[1; 2^num_bits - 1]`\\nwhen it is true) and then de-quantized and output as floats in `[min; max]`\\ninterval.\\n*   `num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive.\\n\\nBefore quantization, `min` and `max` values are adjusted with the following\\nlogic.\\nIt is suggested to have `min <= 0 <= max`. If `0` is not in the range of values,\\nthe behavior can be unexpected:\\n\\n*   If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`.\\n*   If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`.\\n*   If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `,\\n`min_adj = scale * round(min / scale)` and `max_adj = max + min_adj - min`.\\n\\nThis operation has a gradient and thus allows for training `min` and `max`\\nvalues.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FakeQuantWithMinMaxVarsPerChannelGradient\",\n    \"summary\": \"Compute gradients for a FakeQuantWithMinMaxVarsPerChannel operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"inputs\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops_wrt_input\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"backprop_wrt_min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"backprop_wrt_max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FFT\",\n    \"summary\": \"Fast Fourier transform.\",\n    \"description\": \"Computes the 1-dimensional discrete Fourier transform over the inner-most\\ndimension of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FFT2D\",\n    \"summary\": \"2D fast Fourier transform.\",\n    \"description\": \"Computes the 2-dimensional discrete Fourier transform over the inner-most\\n2 dimensions of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FFT3D\",\n    \"summary\": \"3D fast Fourier transform.\",\n    \"description\": \"Computes the 3-dimensional discrete Fourier transform over the inner-most 3\\ndimensions of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Fill\",\n    \"summary\": \"Creates a tensor filled with a scalar value.\",\n    \"description\": \"This operation creates a tensor of shape `dims` and fills it with `value`.\\n\\nFor example:\\n\\n```\\n# Output tensor has shape [2, 3].\\nfill([2, 3], 9) ==> [[9, 9, 9]\\n                     [9, 9, 9]]\\n```\\n\\n`tf.fill` differs from `tf.constant` in a few ways:\\n\\n*   `tf.fill` only supports scalar contents, whereas `tf.constant` supports\\n    Tensor values.\\n*   `tf.fill` creates an Op in the computation graph that constructs the actual\\n    Tensor value at runtime. This is in contrast to `tf.constant` which embeds\\n    the entire Tensor into the graph with a `Const` node.\\n*   Because `tf.fill` evaluates at graph runtime, it supports dynamic shapes\\n    based on other runtime Tensors, unlike `tf.constant`.\",\n    \"operands\": [\n      { \"name\": \"dims\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FinalizeDataset\",\n    \"summary\": \"Creates a dataset by applying `tf.data.Options` to `input_dataset`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"has_captured_ref\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FinalizeTPUEmbedding\",\n    \"summary\": \"An op that finalizes the TPUEmbedding configuration.\",\n    \"operands\": [\n      { \"name\": \"common_config\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"memory_config\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FlatMapDataset\",\n    \"summary\": \"Creates a dataset that applies `f` to the outputs of `input_dataset`.\",\n    \"description\": \"Unlike MapDataset, the `f` in FlatMapDataset is expected to return a\\nDataset variant, and FlatMapDataset will flatten successive results\\ninto a single Dataset.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Floor\",\n    \"summary\": \"Returns element-wise largest integer not greater than x.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FloorDiv\",\n    \"summary\": \"Returns x // y element-wise.\",\n    \"description\": \"*NOTE*: `FloorDiv` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FloorMod\",\n    \"summary\": \"Returns element-wise remainder of division.\",\n    \"description\": \"This follows Python semantics in that the\\nresult here is consistent with a flooring divide. E.g.\\n`floor(x / y) * y + floormod(x, y) = x`, regardless of the signs of x and y.\\n\\n*NOTE*: `FloorMod` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FlushSummaryWriter\",\n    \"summary\": \"Flushes the writer's unwritten events.\",\n    \"description\": \"writer: A handle to the summary writer resource.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedBatchNorm\",\n    \"summary\": \"Batch normalization.\",\n    \"description\": \"Note that the size of 4D Tensors are defined by either \\\"NHWC\\\" or \\\"NCHW\\\".\\nThe size of 1D Tensors matches the dimension C of the 4D Tensors.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"offset\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mean\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"variance\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"batch_mean\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"batch_variance\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"exponential_avg_factor\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedBatchNormGrad\",\n    \"summary\": \"Gradient for batch normalization.\",\n    \"description\": \"Note that the size of 4D Tensors are defined by either \\\"NHWC\\\" or \\\"NCHW\\\".\\nThe size of 1D Tensors matches the dimension C of the 4D Tensors.\",\n    \"operands\": [\n      { \"name\": \"y_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"x\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"x_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"scale_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"offset_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_3\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_4\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedBatchNormGradV2\",\n    \"summary\": \"Gradient for batch normalization.\",\n    \"description\": \"Note that the size of 4D Tensors are defined by either \\\"NHWC\\\" or \\\"NCHW\\\".\\nThe size of 1D Tensors matches the dimension C of the 4D Tensors.\",\n    \"operands\": [\n      { \"name\": \"y_backprop\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"x_backprop\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"offset_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_3\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_4\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedBatchNormGradV3\",\n    \"summary\": \"Gradient for batch normalization.\",\n    \"description\": \"Note that the size of 4D Tensors are defined by either \\\"NHWC\\\" or \\\"NCHW\\\".\\nThe size of 1D Tensors matches the dimension C of the 4D Tensors.\",\n    \"operands\": [\n      { \"name\": \"y_backprop\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_3\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"x_backprop\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"offset_backprop\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_4\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_5\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NDHWC, NCDHW ]>, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedBatchNormV2\",\n    \"summary\": \"Batch normalization.\",\n    \"description\": \"Note that the size of 4D Tensors are defined by either \\\"NHWC\\\" or \\\"NCHW\\\".\\nThe size of 1D Tensors matches the dimension C of the 4D Tensors.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"offset\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mean\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"variance\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"batch_mean\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"batch_variance\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"exponential_avg_factor\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedBatchNormV3\",\n    \"summary\": \"Batch normalization.\",\n    \"description\": \"Note that the size of 4D Tensors are defined by either \\\"NHWC\\\" or \\\"NCHW\\\".\\nThe size of 1D Tensors matches the dimension C of the 4D Tensors.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scale\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"offset\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"mean\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"variance\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"batch_mean\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"batch_variance\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"reserve_space_1\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"reserve_space_2\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" },\n      { \"name\": \"reserve_space_3\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0001f>\" },\n      { \"name\": \"exponential_avg_factor\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NDHWC, NCDHW ]>, \\\"NHWC\\\">\" },\n      { \"name\": \"is_training\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.FusedConv2DBiasActivation\",\n    \"summary\": \"Computes a fused kernel which implements: 2-D convolution, adds side input,\",\n    \"description\": \"with separate scaling on convolution and side inputs, then adds bias and\\n    applies the RELU activation function to the result. Supports both float and\\n    qint8 data formats. In the case of qint8, the output is clipped to [0..127].\\n\\n    conv_input: A tensor with format as specified by `data_format` (see below).\\n    filter: A tensor with format depending on `data_format` as follows:\\n        \\\"NHWC\\\", \\\"NCHW\\\":\\n             `float [ filter_height, filter_width, in_channels, out_channels ]`\\n        \\\"NCHW_VECT_C\\\":\\n             `qint8 [ out_channels, in_channels, filter_height, filter_width ]`\\n    bias: 1-D float tensor with size matching the `out_channels` dimension of\\n        `filter`.\\n        Note: this tensor is still float, even if other inputs are qint8.\\n    side_input: A tensor with format as specified by `data_format` (see below).\\n        This tensor will be ignored and can be [] if side_input_scale == 0.\\n        Otherwise, the size of each dimension must match the `output` tensor.\\n    conv_input_scale: scalar float value to be multiplied by `conv_input`.\\n        (conceptually.. in reality it is applied after convolution).\\n        For the CPU version, this can also be a 1-D Tensor of per output-channel\\n        scales.\\n    side_input_scale: scalar float value to be multiplied by `side_input`.\\n    output: A tensor with format as specified by `data_format` (see below).\\n        The dimension sizes are determined automatically based on other inputs\\n        and attributes.\\n    T: The element data type of `conv_input`, `side_input` and `output` tensors.\\n        Note: must match with the `data_format`.\\n    Tbias: The element data type of `bias`.\\n    strides: 1-D tensor of length 4.  The stride of the sliding window for each\\n        dimension of `input`. The dimension order is determined by the value of\\n        `data_format`, see below for details.\\n        Note: the stride for batch and channel dimensions must be 1.\\n    padding: The type of padding algorithm to use.\\n    data_format: A string specifying the data format of `conv_input`,\\n        `side_input` and `output` tensors with the following options:\\n        \\\"NHWC\\\": `float [ batch, height, width, channels ]`\\n        \\\"NCHW\\\": `float [ batch, channels, height, width ]`\\n        \\\"NCHW_VECT_C\\\":\\n            `qint8 [ batch, channels / 4, height, width, channels % 4 ]`\\n        Note: for \\\"NCHW_VECT_C\\\", `channels` must be a multiple of 4.\\n    filter_format: A string specifying the data format of `filter`,\\n        \\\"HWIO\\\": `float [ kernel_height, kernel_width, input_channels,\\n                         output_channels ]`\\n        \\\"OIHW_VECT_I\\\":\\n            `qint8 [ output_channels, input_channels / 4,\\n                     kernel_height, kernel_width, input_channels % 4 ]`\\n    activation_mode: The activation applied to the output.\\n        Must be \\\"Relu\\\" or \\\"None\\\".\\n    dilations: 1-D tensor of length 4.  The dilation factor for each dimension\\n        of `input`. If set to k > 1, there will be k-1 skipped cells between\\n        each filter element on that dimension. The dimension order is determined\\n        by the value of `data_format`, see above for details. Dilations in the\\n        batch and depth dimensions must be 1.\",\n    \"operands\": [\n      { \"name\": \"conv_input\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Qint8]>\" },\n      { \"name\": \"filter\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Qint8]>\" },\n      { \"name\": \"bias\", \"type\": \"TensorOf<[TF_Float16, TF_Float32]>\" },\n      { \"name\": \"side_input\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Qint8]>\" },\n      { \"name\": \"conv_input_scale\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"side_input_scale\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Qint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NCHW_VECT_C ]>, \\\"NHWC\\\">\" },\n      { \"name\": \"filter_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ HWIO, OIHW, OIHW_VECT_I ]>, \\\"HWIO\\\">\" },\n      { \"name\": \"activation_mode\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ Relu, None ]>, \\\"Relu\\\">\" },\n      { \"name\": \"dilations\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {1, 1, 1, 1}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Gather slices from `params` according to `indices`.\",\n    \"description\": \"`indices` must be an integer tensor of any dimension (usually 0-D or 1-D).\\nProduces an output tensor with shape `indices.shape + params.shape[1:]` where:\\n\\n```python\\n    # Scalar indices\\n    output[:, ..., :] = params[indices, :, ... :]\\n\\n    # Vector indices\\n    output[i, :, ..., :] = params[indices[i], :, ... :]\\n\\n    # Higher rank indices\\n    output[i, ..., j, :, ... :] = params[indices[i, ..., j], :, ..., :]\\n```\\n\\nIf `indices` is a permutation and `len(indices) == params.shape[0]` then\\nthis operation will permute `params` accordingly.\\n\\n`validate_indices`: DEPRECATED. If this operation is assigned to CPU, values in\\n`indices` are always validated to be within range. If assigned to GPU,\\nout-of-bound indices result in safe but unspecified behavior, which may include\\nraising an error.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/Gather.png\\\" alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"validate_indices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GatherNd\",\n    \"summary\": \"Gather slices from `params` into a Tensor with shape specified by `indices`.\",\n    \"description\": \"`indices` is a K-dimensional integer tensor, best thought of as a\\n(K-1)-dimensional tensor of indices into `params`, where each element defines a\\nslice of `params`:\\n\\n    output[\\\\\\\\(i_0, ..., i_{K-2}\\\\\\\\)] = params[indices[\\\\\\\\(i_0, ..., i_{K-2}\\\\\\\\)]]\\n\\nWhereas in `tf.gather` `indices` defines slices into the `axis`\\ndimension of `params`, in `tf.gather_nd`, `indices` defines slices into the\\nfirst `N` dimensions of `params`, where `N = indices.shape[-1]`.\\n\\nThe last dimension of `indices` can be at most the rank of\\n`params`:\\n\\n    indices.shape[-1] <= params.rank\\n\\nThe last dimension of `indices` corresponds to elements\\n(if `indices.shape[-1] == params.rank`) or slices\\n(if `indices.shape[-1] < params.rank`) along dimension `indices.shape[-1]`\\nof `params`.  The output tensor has shape\\n\\n    indices.shape[:-1] + params.shape[indices.shape[-1]:]\\n\\nIf `indices` contains any out-of-bound indices, depending on\\n`bad_indices_policy`, the op will either return an error or ignore the\\nout-of-bound indices. `bad_indices_policy` can be one of the following values:\\n1. \\\"\\\" or \\\"DEFAULT\\\": raises on CPU and ignore on GPU. This is because\\n   historically on CPU and GPU we handle errors in different ways, and for\\n   backward compatibility we keep the default behavior.\\n2. \\\"ERROR\\\": raises error; GPU does not support this value.\\n3. \\\"IGNORE\\\": ignore error and set the corresponding output to 0;\\n   supported on both CPU and GPU.\\n\\nSome examples below.\\n\\nSimple indexing into a matrix:\\n\\n```python\\n    indices = [[0, 0], [1, 1]]\\n    params = [['a', 'b'], ['c', 'd']]\\n    output = ['a', 'd']\\n```\\n\\nSlice indexing into a matrix:\\n\\n```python\\n    indices = [[1], [0]]\\n    params = [['a', 'b'], ['c', 'd']]\\n    output = [['c', 'd'], ['a', 'b']]\\n```\\n\\nIndexing into a 3-tensor:\\n\\n```python\\n    indices = [[1]]\\n    params = [[['a0', 'b0'], ['c0', 'd0']],\\n              [['a1', 'b1'], ['c1', 'd1']]]\\n    output = [[['a1', 'b1'], ['c1', 'd1']]]\\n\\n\\n    indices = [[0, 1], [1, 0]]\\n    params = [[['a0', 'b0'], ['c0', 'd0']],\\n              [['a1', 'b1'], ['c1', 'd1']]]\\n    output = [['c0', 'd0'], ['a1', 'b1']]\\n\\n\\n    indices = [[0, 0, 1], [1, 0, 1]]\\n    params = [[['a0', 'b0'], ['c0', 'd0']],\\n              [['a1', 'b1'], ['c1', 'd1']]]\\n    output = ['b0', 'b1']\\n```\\n\\nBatched indexing into a matrix:\\n\\n```python\\n    indices = [[[0, 0]], [[0, 1]]]\\n    params = [['a', 'b'], ['c', 'd']]\\n    output = [['a'], ['b']]\\n```\\n\\nBatched slice indexing into a matrix:\\n\\n```python\\n    indices = [[[1]], [[0]]]\\n    params = [['a', 'b'], ['c', 'd']]\\n    output = [[['c', 'd']], [['a', 'b']]]\\n```\\n\\nBatched indexing into a 3-tensor:\\n\\n```python\\n    indices = [[[1]], [[0]]]\\n    params = [[['a0', 'b0'], ['c0', 'd0']],\\n              [['a1', 'b1'], ['c1', 'd1']]]\\n    output = [[[['a1', 'b1'], ['c1', 'd1']]],\\n              [[['a0', 'b0'], ['c0', 'd0']]]]\\n\\n    indices = [[[0, 1], [1, 0]], [[0, 0], [1, 1]]]\\n    params = [[['a0', 'b0'], ['c0', 'd0']],\\n              [['a1', 'b1'], ['c1', 'd1']]]\\n    output = [[['c0', 'd0'], ['a1', 'b1']],\\n              [['a0', 'b0'], ['c1', 'd1']]]\\n\\n\\n    indices = [[[0, 0, 1], [1, 0, 1]], [[0, 1, 1], [1, 1, 0]]]\\n    params = [[['a0', 'b0'], ['c0', 'd0']],\\n              [['a1', 'b1'], ['c1', 'd1']]]\\n    output = [['b0', 'b1'], ['d0', 'c1']]\\n```\\n\\nSee also `tf.gather` and `tf.batch_gather`.\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GatherV2\",\n    \"summary\": \"Gather slices from `params` axis `axis` according to `indices`.\",\n    \"description\": \"`indices` must be an integer tensor of any dimension (usually 0-D or 1-D).\\nProduces an output tensor with shape `params.shape[:axis] +\\nindices.shape[batch_dims:] + params.shape[axis + 1:]` where:\\n\\n```python\\n    # Scalar indices (output is rank(params) - 1).\\n    output[a_0, ..., a_n, b_0, ..., b_n] =\\n      params[a_0, ..., a_n, indices, b_0, ..., b_n]\\n\\n    # Vector indices (output is rank(params)).\\n    output[a_0, ..., a_n, i, b_0, ..., b_n] =\\n      params[a_0, ..., a_n, indices[i], b_0, ..., b_n]\\n\\n    # Higher rank indices (output is rank(params) + rank(indices) - 1).\\n    output[a_0, ..., a_n, i, ..., j, b_0, ... b_n] =\\n      params[a_0, ..., a_n, indices[i, ..., j], b_0, ..., b_n]\\n```\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/Gather.png\\\" alt>\\n</div>\\n\\nNote that on CPU, if an out of bound index is found, an error is returned.\\nOn GPU, if an out of bound index is found, a 0 is stored in the\\ncorresponding output value.\\n\\nNote that on TPU, if any dimension of `params` is of size 0 then the output will\\nbe the expected shape filled with zeros. On CPU and GPU an error will be\\nreturned.\\n\\nSee also `tf.batch_gather` and `tf.gather_nd`.\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GeneratorDataset\",\n    \"summary\": \"Creates a dataset that invokes a function to generate elements.\",\n    \"operands\": [\n      { \"name\": \"init_func_other_args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"next_func_other_args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"finalize_func_other_args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"init_func\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"next_func\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"finalize_func\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GeneratorDatasetRegion\",\n    \"summary\": \"Regional version of GeneratorDataset\",\n    \"description\": \"Creates a dataset that invokes its 'next' region to generate elements. Conceptually,\\nwithin MLIR, we treat this op as if it fills a buffer with all the results right away,\\nand those results are then passed (through the variant tensor result) to\\nMakeIterator / IteratorGetNext. Note that the actual TF implementation differs: It\\ngenerates the next element just in time, during IteratorGetNext.\\n\\ninit_extra_args: Additional arguments to pass to 'init'.\\nnext_extra_args: Additional arguments to pass to 'next'. (Passed after the\\n                 normal arguments which are from the return values of 'init'.)\\nfinalize_extra_args: Additional arguments to pass to 'finalize'. (Passed after\\n                 the normal arguments which are from the return values of 'init'.)\",\n    \"operands\": [\n      { \"name\": \"init_func_other_args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"next_func_other_args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"finalize_func_other_args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ],\n    \"regions\": [\n      { \"name\": \"init\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"next\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"finalize\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GetMinibatchesInCsrWithPhysicalReplica\",\n    \"operands\": [\n      { \"name\": \"program_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"row_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"col_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"splits\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"id_counts\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"row_pointers_unpadded_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"ids_unpadded_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_replica\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_minibatches_per_sc\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_ids_per_chip_per_sample\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_vocab_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"feature_width\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_sc_per_chip\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"mini_batch_in_csr\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GetMinibatchSplitsWithPhysicalReplica\",\n    \"operands\": [\n      { \"name\": \"program_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"row_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"col_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gains\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"sorted_row_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_col_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"splits\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"id_counts\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"max_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"max_uniques\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_replica\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_vocab_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"feature_width\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_sc_per_chip\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"mini_batch_splits\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GetStatsFromListOfSparseCoreCooTensors\",\n    \"summary\": \"An op which computes the max_ids/uniques for a given table.\",\n    \"operands\": [\n      { \"name\": \"row_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"col_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"gains_list\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count_list\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"col_offset_list\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"num_replica\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_vocab_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"feature_width\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_sc_per_chip\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GlobalIterId\",\n    \"summary\": \"Op that gets the global step id.\",\n    \"description\": \"This op gets the step id for each loop iteration.\",\n    \"results\": [\n      { \"name\": \"iter_id\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Greater\",\n    \"summary\": \"Returns the truth value of (x > y) element-wise.\",\n    \"description\": \"*NOTE*: `Greater` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\\n\\nExample:\\n\\n```python\\nx = tf.constant([5, 4, 6])\\ny = tf.constant([5, 2, 5])\\ntf.math.greater(x, y) ==> [False, True, True]\\n\\nx = tf.constant([5, 4, 6])\\ny = tf.constant([5])\\ntf.math.greater(x, y) ==> [False, False, True]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.GreaterEqual\",\n    \"summary\": \"Returns the truth value of (x >= y) element-wise.\",\n    \"description\": \"*NOTE*: `GreaterEqual` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\\n\\nExample:\\n\\n```python\\nx = tf.constant([5, 4, 6, 7])\\ny = tf.constant([5, 2, 5, 10])\\ntf.math.greater_equal(x, y) ==> [True, True, True, False]\\n\\nx = tf.constant([5, 4, 6, 7])\\ny = tf.constant([5])\\ntf.math.greater_equal(x, y) ==> [True, False, True, True]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.HashTable\",\n    \"summary\": \"Creates a non-initialized hash table.\",\n    \"description\": \"This op creates a hash table, specifying the type of its keys and values.\\nBefore using the table you will have to initialize it.  After initialization the\\ntable will be immutable.\",\n    \"results\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"use_node_name_sharing\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"key_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_dtype\", \"type\": \"TypeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.HashTableV2\",\n    \"summary\": \"Creates a non-initialized hash table.\",\n    \"description\": \"This op creates a hash table, specifying the type of its keys and values.\\nBefore using the table you will have to initialize it.  After initialization the\\ntable will be immutable.\",\n    \"results\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"use_node_name_sharing\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"key_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_dtype\", \"type\": \"TypeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.HSVToRGB\",\n    \"summary\": \"Convert one or more images from HSV to RGB.\",\n    \"description\": \"Outputs a tensor of the same shape as the `images` tensor, containing the RGB\\nvalue of the pixels. The output is only well defined if the value in `images`\\nare in `[0,1]`.\\n\\nSee `rgb_to_hsv` for a description of the HSV encoding.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Identity\",\n    \"summary\": \"Return a tensor with the same shape and contents as the input tensor or value.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IdentityN\",\n    \"summary\": \"Returns a list of tensors with the same shapes and contents as the input\",\n    \"description\": \"tensors.\\n\\nThis op can be used to override the gradient for complicated functions. For\\nexample, suppose y = f(x) and we wish to apply a custom function g for backprop\\nsuch that dx = g(dy). In Python,\\n\\n```python\\nwith tf.get_default_graph().gradient_override_map(\\n    {'IdentityN': 'OverrideGradientWithG'}):\\n  y, _ = identity_n([f(x), x])\\n\\n@tf.RegisterGradient('OverrideGradientWithG')\\ndef ApplyG(op, dy, _):\\n  return [None, g(dy)]  # Do not backprop to f(x).\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.If\",\n    \"summary\": \"output = cond ? then_branch(input) : else_branch(input)\",\n    \"description\": \"output = cond ? then_branch(input) : else_branch(input)\\n\\ncond: A Tensor. If the tensor is a scalar of non-boolean type, the\\n    scalar is converted to a boolean according to the\\n    following rule: if the scalar is a numerical value, non-zero means\\n    True and zero means False; if the scalar is a string, non-empty\\n    means True and empty means False. If the tensor is not a scalar,\\n    being empty means False and being non-empty means True.\\ninput: A list of input tensors.\\nthen_branch: A function that takes 'inputs' and returns a list of\\n    tensors, whose types are the same as what else_branch returns.\\nelse_branch: A function that takes 'inputs' and returns a list of\\n    tensors.  whose types are the same as what then_branch returns.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_branch\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"else_branch\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"is_stateless\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IFFT\",\n    \"summary\": \"Inverse fast Fourier transform.\",\n    \"description\": \"Computes the inverse 1-dimensional discrete Fourier transform over the\\ninner-most dimension of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IFFT2D\",\n    \"summary\": \"Inverse 2D fast Fourier transform.\",\n    \"description\": \"Computes the inverse 2-dimensional discrete Fourier transform over the\\ninner-most 2 dimensions of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IFFT3D\",\n    \"summary\": \"Inverse 3D fast Fourier transform.\",\n    \"description\": \"Computes the inverse 3-dimensional discrete Fourier transform over the\\ninner-most 3 dimensions of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IfRegion\",\n    \"summary\": \"output = cond ? then_branch output : else_branch output\",\n    \"description\": \"\\\"output = cond ? then_branch output : else_branch output\\\"\\n\\ncond: A Tensor. If the tensor is a scalar of non-boolean type, the\\n    scalar is converted to a boolean according to the\\n    following rule: if the scalar is a numerical value, non-zero means\\n    True and zero means False; if the scalar is a string, non-empty\\n    means True and empty means False. If the tensor is not a scalar,\\n    being empty means False and being non-empty means True.\\nthen_branch: A region that computes the outputs of the op if cond = true.\\n    It returns a list of tensors using tf.yield (as the terminator). The\\n    types of these returned tensors is same as that of the else_branch\\nelse_branch: A region that computes the outputs of the op if cond = false.\\n    It returns a list of tensors using tf.yield (as the terminator). The\\n    types of these returned tensors is same as that of the then_branch\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"0DTensorOf<[I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_stateless\", \"type\": \"BoolAttr\" },\n      { \"name\": \"_then_func_name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"_else_func_name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_branch\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_branch\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IfrtCall\",\n    \"summary\": \"Invokes a program via IFRT on a device\",\n    \"description\": \"This op calls an IFRT program uniquely identified by the given program id.\\n\\n    During lowering from a `tf_device.cluster_func` op to a `tf.IfrtCall` op,\\n    the region owned by the former will be outlined to a function with a\\n    `tfrt_ifrt_serving.program_id` attribute. After that, the runtime ensures\\n    that the outlined function is compiled into an executable and is available\\n    for lookup from `IfrtCall` TF ops.\\n\\n    `variable_arg_indices` is a sorted (ascending order) array and indicates which\\n    element of `args` is a key to a loaded array corresponding to a variable.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"static_shapes\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"program_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"variable_arg_indices\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IfrtLoadVariable\",\n    \"summary\": \"Loads a restored variable tensor as a tensor future\",\n    \"description\": \"This op loads a restored variable tensor as a tensor future. It is a\\n    replacement of `tf.ReadVariableOp`.\\n\\n    This op returns a scalar string tensor containing the restored variable name, which \\n    is composed from `container_name` and `shared_name` from a `var_handle` and can be\\n    used as a key within the runtime, as well as a future for the tensor.\\n\\n    The `tf.IfrtCall` kernel uses the output $array_key.\\n    Other ops executed by TFRT may make use of $tensor_future.\",\n    \"operands\": [\n      { \"name\": \"variable\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"array_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_future\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"used_by_host\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IfrtResourceDeserialize\",\n    \"summary\": \"Deserialize resource vars.\",\n    \"description\": \"This Op is a variant of IfrtResourceDeserialize for use with the\\n     TFRT/IFRT runtime. It is not a stable interface.\",\n    \"operands\": [\n      { \"name\": \"resource_var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"input_dir\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"require_matching_crc\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"tensor_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IfrtRestoreVariableOp\",\n    \"summary\": \"Restore variable tensors\",\n    \"description\": \"This Op is similar to a combination of RestoreV2 and AssignVariable Op, but\\n    this Op's execution is asynchronous.\\n\\n    This Op is specific to TFRT + IFRT runtime and is not a stable interface for\\n    serialization.\\n\\n    This Op will restore the tensors asynchronously. There are N restored tensors\\n    corresponding to N $var_handle. Each restored tensor is given a unique name,\\n    typically a concatenation of `container_name` and `shared_name` from a `var_handle`.\\n    The runtime shall handle the possibility that the tensors are not ready when requested\\n    because the tensors are loaded asynchronously.\",\n    \"operands\": [\n      { \"name\": \"prefix\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"shape_and_slices\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"var_handles\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"restored_dtypes\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"truncate_in_cast\", \"type\": \"DenseBoolArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Igamma\",\n    \"summary\": \"Compute the lower regularized incomplete Gamma function `P(a, x)`.\",\n    \"description\": \"The lower regularized incomplete Gamma function is defined as:\\n\\n\\n\\\\\\\\(P(a, x) = gamma(a, x) / Gamma(a) = 1 - Q(a, x)\\\\\\\\)\\n\\nwhere\\n\\n\\\\\\\\(gamma(a, x) = \\\\int_{0}^{x} t^{a-1} exp(-t) dt\\\\\\\\)\\n\\nis the lower incomplete Gamma function.\\n\\nNote, above `Q(a, x)` (`Igammac`) is the upper regularized complete\\nGamma function.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Igammac\",\n    \"summary\": \"Compute the upper regularized incomplete Gamma function `Q(a, x)`.\",\n    \"description\": \"The upper regularized incomplete Gamma function is defined as:\\n\\n\\\\\\\\(Q(a, x) = Gamma(a, x) / Gamma(a) = 1 - P(a, x)\\\\\\\\)\\n\\nwhere\\n\\n\\\\\\\\(Gamma(a, x) = \\\\int_{x}^{\\\\infty} t^{a-1} exp(-t) dt\\\\\\\\)\\n\\nis the upper incomplete Gamma function.\\n\\nNote, above `P(a, x)` (`Igamma`) is the lower regularized complete\\nGamma function.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IgammaGradA\",\n    \"summary\": \"Computes the gradient of `igamma(a, x)` wrt `a`.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"x\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Imag\",\n    \"summary\": \"Returns the imaginary part of a complex number.\",\n    \"description\": \"Given a tensor `input` of complex numbers, this operation returns a tensor of\\ntype `float` that is the imaginary part of each element in `input`. All\\nelements in `input` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\), where *a*\\nis the real part and *b* is the imaginary part returned by this operation.\\n\\nFor example:\\n\\n```\\n# tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]\\ntf.imag(input) ==> [4.75, 5.75]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ImportEvent\",\n    \"summary\": \"Outputs a `tf.Event` protocol buffer.\",\n    \"description\": \"When CreateSummaryDbWriter is being used, this op can be useful for\\nimporting data from event logs.\\n\\nwriter: A handle to a summary writer.\\nevent: A string containing a binary-encoded tf.Event proto.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"event\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InfeedDequeue\",\n    \"summary\": \"A placeholder op for a value that will be fed into the computation.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InfeedDequeueTuple\",\n    \"summary\": \"Fetches multiple values from infeed as an XLA tuple.\",\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"_XlaSharding\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"layouts\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InfeedEnqueueTuple\",\n    \"summary\": \"Feeds multiple Tensor values into the computation as an XLA tuple.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtypes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"shapes\", \"type\": \"TypedArrayAttrBase<TF_ShapeAttr>\" },\n      { \"name\": \"layouts\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"device_ordinal\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InitializeTable\",\n    \"summary\": \"Table initializer that takes two tensors for keys and values respectively.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InitializeTableFromDataset\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"dataset\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InitializeTableFromTextFile\",\n    \"summary\": \"Initializes a table from a text file.\",\n    \"description\": \"It inserts one key-value pair into the table for each line of the file.\\nThe key and value is extracted from the whole line content, elements from the\\nsplit line based on `delimiter` or the line number (starting from zero).\\nWhere to extract the key and value from a line is specified by `key_index` and\\n`value_index`.\\n\\n- A value of -1 means use the line number(starting from zero), expects `int64`.\\n- A value of -2 means use the whole line content, expects `string`.\\n- A value >= 0 means use the index (starting at zero) of the split line based\\n  on `delimiter`.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key_index\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<-2>]>\" },\n      { \"name\": \"value_index\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<-2>]>\" },\n      { \"name\": \"vocab_size\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, -1>, [IntMinValue<-1>]>\" },\n      { \"name\": \"delimiter\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\\t\\\">\" },\n      { \"name\": \"offset\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InitializeTableFromTextFileV2\",\n    \"summary\": \"Initializes a table from a text file.\",\n    \"description\": \"It inserts one key-value pair into the table for each line of the file.\\nThe key and value is extracted from the whole line content, elements from the\\nsplit line based on `delimiter` or the line number (starting from zero).\\nWhere to extract the key and value from a line is specified by `key_index` and\\n`value_index`.\\n\\n- A value of -1 means use the line number(starting from zero), expects `int64`.\\n- A value of -2 means use the whole line content, expects `string`.\\n- A value >= 0 means use the index (starting at zero) of the split line based\\n  on `delimiter`.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key_index\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<-2>]>\" },\n      { \"name\": \"value_index\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<-2>]>\" },\n      { \"name\": \"vocab_size\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, -1>, [IntMinValue<-1>]>\" },\n      { \"name\": \"delimiter\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\\t\\\">\" },\n      { \"name\": \"offset\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InitializeTableV2\",\n    \"summary\": \"Table initializer that takes two tensors for keys and values respectively.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InplaceAdd\",\n    \"summary\": \"Adds v into specified rows of x.\",\n    \"description\": \"Computes y = x; y[i, :] += v; return y.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"i\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"v\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InplaceUpdate\",\n    \"summary\": \"Updates specified rows 'i' with values 'v'.\",\n    \"description\": \"Computes `x[i, :] = v; return x`.\\n\\nOriginally this function is mutative however for compilation we make this\\noperation create / operate on a copy of `x`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"i\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"v\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InTopKV2\",\n    \"summary\": \"Says whether the targets are in the top `K` predictions.\",\n    \"description\": \"This outputs a `batch_size` bool array, an entry `out[i]` is `true` if the\\nprediction for the target class is among the top `k` predictions among\\nall predictions for example `i`. Note that the behavior of `InTopK` differs\\nfrom the `TopK` op in its handling of ties; if multiple classes have the\\nsame prediction value and straddle the top-`k` boundary, all of those\\nclasses are considered to be in the top `k`.\\n\\nMore formally, let\\n\\n  \\\\\\\\(predictions_i\\\\\\\\) be the predictions for all classes for example `i`,\\n  \\\\\\\\(targets_i\\\\\\\\) be the target class for example `i`,\\n  \\\\\\\\(out_i\\\\\\\\) be the output for example `i`,\\n\\n$$out_i = predictions_{i, targets_i} \\\\in TopKIncludingTies(predictions_i)$$\",\n    \"operands\": [\n      { \"name\": \"predictions\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"targets\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"k\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"precision\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Inv\",\n    \"summary\": \"Computes the reciprocal of x element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = 1 / x\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Invert\",\n    \"summary\": \"Invert (flip) each bit of supported types; for example, type `uint8` value 01010101 becomes 10101010.\",\n    \"description\": \"Flip each bit of supported types.  For example, type `int8` (decimal 2) binary 00000010 becomes (decimal -3) binary 11111101.\\nThis operation is performed on each element of the tensor argument `x`.\\n\\nExample:\\n```python\\nimport tensorflow as tf\\nfrom tensorflow.python.ops import bitwise_ops\\n\\n# flip 2 (00000010) to -3 (11111101)\\ntf.assert_equal(-3, bitwise_ops.invert(2))\\n\\ndtype_list = [dtypes.int8, dtypes.int16, dtypes.int32, dtypes.int64,\\n              dtypes.uint8, dtypes.uint16, dtypes.uint32, dtypes.uint64]\\n\\ninputs = [0, 5, 3, 14]\\nfor dtype in dtype_list:\\n  # Because of issues with negative numbers, let's test this indirectly.\\n  # 1. invert(a) and a = 0\\n  # 2. invert(a) or a = invert(0)\\n  input_tensor = tf.constant([0, 5, 3, 14], dtype=dtype)\\n  not_a_and_a, not_a_or_a, not_0 = [bitwise_ops.bitwise_and(\\n                                      input_tensor, bitwise_ops.invert(input_tensor)),\\n                                    bitwise_ops.bitwise_or(\\n                                      input_tensor, bitwise_ops.invert(input_tensor)),\\n                                    bitwise_ops.invert(\\n                                      tf.constant(0, dtype=dtype))]\\n\\n  expected = tf.constant([0, 0, 0, 0], dtype=tf.float32)\\n  tf.assert_equal(tf.cast(not_a_and_a, tf.float32), expected)\\n\\n  expected = tf.cast([not_0] * 4, tf.float32)\\n  tf.assert_equal(tf.cast(not_a_or_a, tf.float32), expected)\\n\\n  # For unsigned dtypes let's also check the result directly.\\n  if dtype.is_unsigned:\\n    inverted = bitwise_ops.invert(input_tensor)\\n    expected = tf.constant([dtype.max - x for x in inputs], dtype=tf.float32)\\n    tf.assert_equal(tf.cast(inverted, tf.float32), tf.cast(expected, tf.float32))\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.InvertPermutation\",\n    \"summary\": \"Computes the inverse permutation of a tensor.\",\n    \"description\": \"This operation computes the inverse of an index permutation. It takes a 1-D\\ninteger tensor `x`, which represents the indices of a zero-based array, and\\nswaps each value with its index position. In other words, for an output tensor\\n`y` and an input tensor `x`, this operation computes the following:\\n\\n`y[x[i]] = i for i in [0, 1, ..., len(x) - 1]`\\n\\nThe values must include 0. There can be no duplicate values or negative values.\\n\\nFor example:\\n\\n```\\n# tensor `x` is [3, 4, 0, 2, 1]\\ninvert_permutation(x) ==> [2, 4, 3, 0, 1]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IRFFT\",\n    \"summary\": \"Inverse real-valued fast Fourier transform.\",\n    \"description\": \"Computes the inverse 1-dimensional discrete Fourier transform of a real-valued\\nsignal over the inner-most dimension of `input`.\\n\\nThe inner-most dimension of `input` is assumed to be the result of `RFFT`: the\\n`fft_length / 2 + 1` unique components of the DFT of a real-valued signal. If\\n`fft_length` is not provided, it is computed from the size of the inner-most\\ndimension of `input` (`fft_length = 2 * (inner - 1)`). If the FFT length used to\\ncompute `input` is odd, it should be provided since it cannot be inferred\\nproperly.\\n\\nAlong the axis `IRFFT` is computed on, if `fft_length / 2 + 1` is smaller\\nthan the corresponding dimension of `input`, the dimension is cropped. If it is\\nlarger, the dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" },\n      { \"name\": \"fft_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IRFFT2D\",\n    \"summary\": \"Inverse 2D real-valued fast Fourier transform.\",\n    \"description\": \"Computes the inverse 2-dimensional discrete Fourier transform of a real-valued\\nsignal over the inner-most 2 dimensions of `input`.\\n\\nThe inner-most 2 dimensions of `input` are assumed to be the result of `RFFT2D`:\\nThe inner-most dimension contains the `fft_length / 2 + 1` unique components of\\nthe DFT of a real-valued signal. If `fft_length` is not provided, it is computed\\nfrom the size of the inner-most 2 dimensions of `input`. If the FFT length used\\nto compute `input` is odd, it should be provided since it cannot be inferred\\nproperly.\\n\\nAlong each axis `IRFFT2D` is computed on, if `fft_length` (or\\n`fft_length / 2 + 1` for the inner-most dimension) is smaller than the\\ncorresponding dimension of `input`, the dimension is cropped. If it is larger,\\nthe dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" },\n      { \"name\": \"fft_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IRFFT3D\",\n    \"summary\": \"Inverse 3D real-valued fast Fourier transform.\",\n    \"description\": \"Computes the inverse 3-dimensional discrete Fourier transform of a real-valued\\nsignal over the inner-most 3 dimensions of `input`.\\n\\nThe inner-most 3 dimensions of `input` are assumed to be the result of `RFFT3D`:\\nThe inner-most dimension contains the `fft_length / 2 + 1` unique components of\\nthe DFT of a real-valued signal. If `fft_length` is not provided, it is computed\\nfrom the size of the inner-most 3 dimensions of `input`. If the FFT length used\\nto compute `input` is odd, it should be provided since it cannot be inferred\\nproperly.\\n\\nAlong each axis `IRFFT3D` is computed on, if `fft_length` (or\\n`fft_length / 2 + 1` for the inner-most dimension) is smaller than the\\ncorresponding dimension of `input`, the dimension is cropped. If it is larger,\\nthe dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" },\n      { \"name\": \"fft_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IsFinite\",\n    \"summary\": \"Returns which elements of x are finite.\",\n    \"description\": \"@compatibility(numpy)\\nEquivalent to np.isfinite\\n@end_compatibility\\n\\nExample:\\n\\n```python\\nx = tf.constant([5.0, 4.8, 6.8, np.inf, np.nan])\\ntf.math.is_finite(x) ==> [True, True, True, False, False]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IsInf\",\n    \"summary\": \"Returns which elements of x are Inf.\",\n    \"description\": \"@compatibility(numpy)\\nEquivalent to np.isinf\\n@end_compatibility\\n\\nExample:\\n\\n```python\\nx = tf.constant([5.0, np.inf, 6.8, np.inf])\\ntf.math.is_inf(x) ==> [False, True, False, True]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IsNan\",\n    \"summary\": \"Returns which elements of x are NaN.\",\n    \"description\": \"@compatibility(numpy)\\nEquivalent to np.isnan\\n@end_compatibility\\n\\nExample:\\n\\n```python\\nx = tf.constant([5.0, np.nan, 6.8, np.nan, np.inf])\\ntf.math.is_nan(x) ==> [False, True, False, True, False]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Iterator\",\n    \"summary\": \"A container for an iterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shared_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"container\", \"type\": \"StrAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorFromStringHandle\",\n    \"summary\": \"Converts the given string representing a handle to an iterator to a resource.\",\n    \"operands\": [\n      { \"name\": \"string_handle\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"resource_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<TypeAttr>, {}>\" },\n      { \"name\": \"output_shapes\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<TF_ShapeAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorFromStringHandleV2\",\n    \"operands\": [\n      { \"name\": \"string_handle\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"resource_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<TypeAttr>, {}>\" },\n      { \"name\": \"output_shapes\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<TF_ShapeAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorGetNext\",\n    \"summary\": \"Gets the next output from the given iterator .\",\n    \"operands\": [\n      { \"name\": \"iterator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorGetNextAsOptional\",\n    \"summary\": \"Gets the next output from the given iterator as an Optional variant.\",\n    \"operands\": [\n      { \"name\": \"iterator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorGetNextSync\",\n    \"summary\": \"Gets the next output from the given iterator.\",\n    \"description\": \"This operation is a synchronous version IteratorGetNext. It should only be used\\nin situations where the iterator does not block the calling thread, or where\\nthe calling thread is not a member of the thread pool used to execute parallel\\noperations (e.g. in eager mode).\",\n    \"operands\": [\n      { \"name\": \"iterator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorToStringHandle\",\n    \"summary\": \"Converts the given `resource_handle` representing an iterator to a string.\",\n    \"operands\": [\n      { \"name\": \"resource_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"string_handle\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.IteratorV2\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shared_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"container\", \"type\": \"StrAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.KthOrderStatistic\",\n    \"summary\": \"Computes the Kth order statistic of a data set. The current\",\n    \"description\": \"implementation uses a binary search requiring exactly 32 passes over\\nthe input data. The running time is linear with respect to input\\nsize. The median-of-medians algorithm is probably faster, but is\\ndifficult to implement efficiently in XLA. The implementation imposes\\na total ordering on floats. The ordering is consistent with the usual\\npartial order.  Positive NaNs are greater than positive\\ninfinity. Negative NaNs are less than negative infinity. NaNs with\\ndistinct payloads are treated as distinct. Subnormal numbers are\\npreserved (not flushed to zero). Positive infinity is greater than all\\nnumbers. Negative infinity is less than all numbers. Positive is\\ngreater than negative zero. There are less than k values greater than\\nthe kth order statistic. There are at least k values greater than or\\nequal to the Kth order statistic. The semantics are not the same as\\ntop_k_unique.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.L2Loss\",\n    \"summary\": \"L2 Loss.\",\n    \"description\": \"Computes half the L2 norm of a tensor without the `sqrt`:\\n\\n    output = sum(t ** 2) / 2\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LeakyRelu\",\n    \"summary\": \"Computes rectified linear: `max(features, features * alpha)`.\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.2f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LeakyReluGrad\",\n    \"summary\": \"Computes rectified linear gradients for a LeakyRelu operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.2f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LeftShift\",\n    \"summary\": \"Elementwise computes the bitwise left-shift of `x` and `y`.\",\n    \"description\": \"If `y` is negative, or greater than or equal to the width of `x` in bits the\\nresult is implementation defined.\\n\\nExample:\\n\\n```python\\nimport tensorflow as tf\\nfrom tensorflow.python.ops import bitwise_ops\\nimport numpy as np\\ndtype_list = [tf.int8, tf.int16, tf.int32, tf.int64]\\n\\nfor dtype in dtype_list:\\n  lhs = tf.constant([-1, -5, -3, -14], dtype=dtype)\\n  rhs = tf.constant([5, 0, 7, 11], dtype=dtype)\\n\\n  left_shift_result = bitwise_ops.left_shift(lhs, rhs)\\n\\n  print(left_shift_result)\\n\\n# This will print:\\n# tf.Tensor([ -32   -5 -128    0], shape=(4,), dtype=int8)\\n# tf.Tensor([   -32     -5   -384 -28672], shape=(4,), dtype=int16)\\n# tf.Tensor([   -32     -5   -384 -28672], shape=(4,), dtype=int32)\\n# tf.Tensor([   -32     -5   -384 -28672], shape=(4,), dtype=int64)\\n\\nlhs = np.array([-2, 64, 101, 32], dtype=np.int8)\\nrhs = np.array([-1, -5, -3, -14], dtype=np.int8)\\nbitwise_ops.left_shift(lhs, rhs)\\n# <tf.Tensor: shape=(4,), dtype=int8, numpy=array([ -2,  64, 101,  32], dtype=int8)>\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LegacyCall\",\n    \"summary\": \"returns `f(inputs)`, where `f` is a function.\",\n    \"description\": \"The LegacyCall operation represents a direct call to a function that is\\n    within the same symbol scope as the call and is mapped to a GraphDef node\\n    with the function name as the op name. Unlike a PartitionedCall which\\n    represents asynchronously executing a function across multiple devices, a\\n    LegacyCall ignores specification for ops in the attached function and\\n    instead executes it on the device assigned to this op.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"f\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"_disable_call_shape_inference\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Less\",\n    \"summary\": \"Returns the truth value of (x < y) element-wise.\",\n    \"description\": \"*NOTE*: `Less` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\\n\\nExample:\\n\\n```python\\nx = tf.constant([5, 4, 6])\\ny = tf.constant([5])\\ntf.math.less(x, y) ==> [False, True, False]\\n\\nx = tf.constant([5, 4, 6])\\ny = tf.constant([5, 6, 7])\\ntf.math.less(x, y) ==> [False, True, True]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LessEqual\",\n    \"summary\": \"Returns the truth value of (x <= y) element-wise.\",\n    \"description\": \"*NOTE*: `LessEqual` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\\n\\nExample:\\n\\n```python\\nx = tf.constant([5, 4, 6])\\ny = tf.constant([5])\\ntf.math.less_equal(x, y) ==> [True, True, False]\\n\\nx = tf.constant([5, 4, 6])\\ny = tf.constant([5, 6, 6])\\ntf.math.less_equal(x, y) ==> [True, True, True]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Lgamma\",\n    \"summary\": \"Computes the log of the absolute value of `Gamma(x)` element-wise.\",\n    \"description\": \"For positive numbers, this function computes log((input - 1)!) for every element in the tensor.\\n  `lgamma(5) = log((5-1)!) = log(4!) = log(24) = 3.1780539`\\n\\nExample:\\n\\n```python\\nx = tf.constant([0, 0.5, 1, 4.5, -4, -5.6])\\ntf.math.lgamma(x) ==> [inf, 0.5723649, 0., 2.4537368, inf, -4.6477685]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LinSpace\",\n    \"summary\": \"Generates values in an interval.\",\n    \"description\": \"A sequence of `num` evenly-spaced values are generated beginning at `start`.\\nIf `num > 1`, the values in the sequence increase by\\n`(stop - start) / (num - 1)`, so that the last one is exactly `stop`.\\n\\nFor example:\\n\\n```\\ntf.linspace(10.0, 12.0, 3, name=\\\"linspace\\\") => [ 10.0  11.0  12.0]\\n```\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"stop\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"num\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ListDiff\",\n    \"summary\": \"Computes the difference between two lists of numbers or strings.\",\n    \"description\": \"Given a list `x` and a list `y`, this operation returns a list `out` that\\nrepresents all values that are in `x` but not in `y`. The returned list `out`\\nis sorted in the same order that the numbers appear in `x` (duplicates are\\npreserved). This operation also returns a list `idx` that represents the\\nposition of each `out` element in `x`. In other words:\\n\\n`out[i] = x[idx[i]] for i in [0, 1, ..., len(out) - 1]`\\n\\nFor example, given this input:\\n\\n```\\nx = [1, 2, 3, 4, 5, 6]\\ny = [1, 3, 5]\\n```\\n\\nThis operation would return:\\n\\n```\\nout ==> [2, 4, 6]\\nidx ==> [1, 3, 5]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"idx\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingAdadeltaParameters\",\n    \"summary\": \"Load Adadelta embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingAdadeltaParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingAdagradParameters\",\n    \"summary\": \"Load Adagrad embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingAdagradParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingADAMParameters\",\n    \"summary\": \"Load ADAM embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocities\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingADAMParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocities\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingCenteredRMSPropParameters\",\n    \"summary\": \"Load centered RMSProp embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mg\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingFTRLParameters\",\n    \"summary\": \"Load FTRL embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linears\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingFTRLParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linears\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingMDLAdagradLightParameters\",\n    \"summary\": \"Load MDL Adagrad Light embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"benefits\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingMomentumParameters\",\n    \"summary\": \"Load Momentum embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingMomentumParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingProximalAdagradParameters\",\n    \"summary\": \"Load proximal Adagrad embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingProximalAdagradParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingProximalYogiParameters\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"v\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"m\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingProximalYogiParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"v\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"m\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingRMSPropParameters\",\n    \"summary\": \"Load RMSProp embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingRMSPropParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingStochasticGradientDescentParameters\",\n    \"summary\": \"Load SGD embedding parameters.\",\n    \"description\": \"An op that loads optimization parameters into HBM for embedding. Must be\\npreceded by a ConfigureTPUEmbeddingHost op that sets up the correct\\nembedding table configuration. For example, this op is used to install\\nparameters that are loaded from a checkpoint before a training loop is\\nexecuted.\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LoadTPUEmbeddingStochasticGradientDescentParametersGradAccumDebug\",\n    \"operands\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Log\",\n    \"summary\": \"Computes natural logarithm of x element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = \\\\log_e x\\\\\\\\).\\n\\nExample:\\n\\n```python\\nx = tf.constant([0, 0.5, 1, 5])\\ntf.math.log(x) ==> [-inf, -0.6931472,  0. ,  1.609438]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Log1p\",\n    \"summary\": \"Computes natural logarithm of (1 + x) element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = \\\\log_e (1 + x)\\\\\\\\).\\n\\nExample:\\n\\n```python\\nx = tf.constant([0, 0.5, 1, 5])\\ntf.math.log1p(x) ==> [0., 0.4054651, 0.6931472, 1.7917595]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LogicalAnd\",\n    \"summary\": \"Returns the truth value of x AND y element-wise.\",\n    \"description\": \"*NOTE*: `LogicalAnd` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LogicalNot\",\n    \"summary\": \"Returns the truth value of `NOT x` element-wise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LogicalOr\",\n    \"summary\": \"Returns the truth value of x OR y element-wise.\",\n    \"description\": \"*NOTE*: `LogicalOr` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LogSoftmax\",\n    \"summary\": \"Computes log softmax activations.\",\n    \"description\": \"For each batch `i` and class `j` we have\\n\\n    logsoftmax[i, j] = logits[i, j] - log(sum(exp(logits[i])))\",\n    \"operands\": [\n      { \"name\": \"logits\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"logsoftmax\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableExportV2\",\n    \"summary\": \"Outputs all keys and values in the table.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableFind\",\n    \"summary\": \"Looks up keys in a table, outputs the corresponding values.\",\n    \"description\": \"The tensor `keys` must of the same type as the keys of the table.\\nThe output `values` is of the type of the table values.\\n\\nThe scalar `default_value` is the value output for keys not present in the\\ntable. It must also be of the same type as the table values.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"default_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableFindV2\",\n    \"summary\": \"Looks up keys in a table, outputs the corresponding values.\",\n    \"description\": \"The tensor `keys` must of the same type as the keys of the table.\\nThe output `values` is of the type of the table values.\\n\\nThe scalar `default_value` is the value output for keys not present in the\\ntable. It must also be of the same type as the table values.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"default_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableImportV2\",\n    \"summary\": \"Replaces the contents of the table with the specified keys and values.\",\n    \"description\": \"The tensor `keys` must be of the same type as the keys of the table.\\nThe tensor `values` must be of the type of the table values.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableInsertV2\",\n    \"summary\": \"Updates the table to associates keys with values.\",\n    \"description\": \"The tensor `keys` must be of the same type as the keys of the table.\\nThe tensor `values` must be of the type of the table values.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableRemoveV2\",\n    \"summary\": \"Removes keys and its associated values from a table.\",\n    \"description\": \"The tensor `keys` must of the same type as the keys of the table. Keys not\\nalready in the table are silently ignored.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableSize\",\n    \"summary\": \"Computes the number of elements in the given table.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"size\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LookupTableSizeV2\",\n    \"summary\": \"Computes the number of elements in the given table.\",\n    \"operands\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"size\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LowerBound\",\n    \"summary\": \"Applies lower_bound(sorted_search_values, values) along each row.\",\n    \"description\": \"Each set of rows with the same index in (sorted_inputs, values) is treated\\nindependently.  The resulting row is the equivalent of calling\\n`np.searchsorted(sorted_inputs, values, side='left')`.\\n\\nThe result is not a global index to the entire\\n`Tensor`, but rather just the index in the last dimension.\\n\\nA 2-D example:\\n  sorted_sequence = [[0, 3, 9, 9, 10],\\n                     [1, 2, 3, 4, 5]]\\n  values = [[2, 4, 9],\\n            [0, 2, 6]]\\n\\n  result = LowerBound(sorted_sequence, values)\\n\\n  result == [[1, 2, 2],\\n             [0, 1, 5]]\",\n    \"operands\": [\n      { \"name\": \"sorted_inputs\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LRN\",\n    \"summary\": \"Local Response Normalization.\",\n    \"description\": \"The 4-D `input` tensor is treated as a 3-D array of 1-D vectors (along the last\\ndimension), and each vector is normalized independently.  Within a given vector,\\neach component is divided by the weighted, squared sum of inputs within\\n`depth_radius`.  In detail,\\n\\n    sqr_sum[a, b, c, d] =\\n        sum(input[a, b, c, d - depth_radius : d + depth_radius + 1] ** 2)\\n    output = input / (bias + alpha * sqr_sum) ** beta\\n\\nFor details, see [Krizhevsky et al., ImageNet classification with deep\\nconvolutional neural networks (NIPS 2012)](http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depth_radius\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 5>\" },\n      { \"name\": \"bias\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.5f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.LRNGrad\",\n    \"summary\": \"Gradients for Local Response Normalization.\",\n    \"operands\": [\n      { \"name\": \"input_grads\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"input_image\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"output_image\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depth_radius\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 5>\" },\n      { \"name\": \"bias\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 1.0f>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.5f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MakeIterator\",\n    \"summary\": \"Makes a new iterator from the given `dataset` and stores it in `iterator`.\",\n    \"description\": \"This operation may be executed multiple times. Each execution will reset the\\niterator in `iterator` to the first element of `dataset`.\",\n    \"operands\": [\n      { \"name\": \"dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"iterator\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MakeUnique\",\n    \"summary\": \"Make all elements in the non-Batch dimension unique, but \\\\\\\"close\\\\\\\" to\",\n    \"description\": \"their initial value. Never returns a sub-normal number. Never returns\\nzero. The sign of each input element is always identical to the sign\\nof the corresponding output element. Behavior for infinite elements is\\nundefined. Behavior for subnormal elements is undefined.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Float32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MapAndBatchDataset\",\n    \"summary\": \"Creates a dataset that fuses mapping with batching.\",\n    \"description\": \"Creates a dataset that applies `f` to the outputs of `input_dataset` and then\\nbatches `batch_size` of them.\\n\\nUnlike a \\\"MapDataset\\\", which applies `f` sequentially, this dataset invokes up\\nto `batch_size * num_parallel_batches` copies of `f` in parallel.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"batch_size\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"num_parallel_calls\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"drop_remainder\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"preserve_cardinality\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MapDataset\",\n    \"summary\": \"Creates a dataset that applies `f` to the outputs of `input_dataset`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"use_inter_op_parallelism\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"preserve_cardinality\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"force_synchronous\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatMul\",\n    \"summary\": \"Multiply the matrix \\\"a\\\" by the matrix \\\"b\\\".\",\n    \"description\": \"The inputs must be two-dimensional matrices and the inner dimension of\\n\\\"a\\\" (after being transposed if transpose_a is true) must match the\\nouter dimension of \\\"b\\\" (after being transposed if transposed_b is\\ntrue).\\n\\n*Note*: The default kernel implementation for MatMul on GPUs uses\\ncublas.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"b\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_a\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"grad_b\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixBandPart\",\n    \"summary\": \"Copy a tensor setting everything outside a central band in each innermost matrix to zero.\",\n    \"description\": \"The `band` part is computed as follows:\\nAssume `input` has `k` dimensions `[I, J, K, ..., M, N]`, then the output is a\\ntensor with the same shape where\\n\\n`band[i, j, k, ..., m, n] = in_band(m, n) * input[i, j, k, ..., m, n]`.\\n\\nThe indicator function\\n\\n`in_band(m, n) = (num_lower < 0 || (m-n) <= num_lower)) &&\\n                 (num_upper < 0 || (n-m) <= num_upper)`.\\n\\nFor example:\\n\\n```\\n# if 'input' is [[ 0,  1,  2, 3]\\n#                [-1,  0,  1, 2]\\n#                [-2, -1,  0, 1]\\n#                [-3, -2, -1, 0]],\\n\\ntf.linalg.band_part(input, 1, -1) ==> [[ 0,  1,  2, 3]\\n                                       [-1,  0,  1, 2]\\n                                       [ 0, -1,  0, 1]\\n                                       [ 0,  0, -1, 0]],\\n\\ntf.linalg.band_part(input, 2, 1) ==> [[ 0,  1,  0, 0]\\n                                      [-1,  0,  1, 0]\\n                                      [-2, -1,  0, 1]\\n                                      [ 0, -2, -1, 0]]\\n```\\n\\nUseful special cases:\\n\\n```\\n tf.linalg.band_part(input, 0, -1) ==> Upper triangular part.\\n tf.linalg.band_part(input, -1, 0) ==> Lower triangular part.\\n tf.linalg.band_part(input, 0, 0) ==> Diagonal.\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"num_lower\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_upper\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"band\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixDiag\",\n    \"summary\": \"Returns a batched diagonal tensor with a given batched diagonal values.\",\n    \"description\": \"Given a `diagonal`, this operation returns a tensor with the `diagonal` and\\neverything else padded with zeros. The diagonal is computed as follows:\\n\\nAssume `diagonal` has `k` dimensions `[I, J, K, ..., N]`, then the output is a\\ntensor of rank `k+1` with dimensions [I, J, K, ..., N, N]` where:\\n\\n`output[i, j, k, ..., m, n] = 1{m=n} * diagonal[i, j, k, ..., n]`.\\n\\nFor example:\\n\\n```\\n# 'diagonal' is [[1, 2, 3, 4], [5, 6, 7, 8]]\\n\\nand diagonal.shape = (2, 4)\\n\\ntf.matrix_diag(diagonal) ==> [[[1, 0, 0, 0]\\n                                     [0, 2, 0, 0]\\n                                     [0, 0, 3, 0]\\n                                     [0, 0, 0, 4]],\\n                                    [[5, 0, 0, 0]\\n                                     [0, 6, 0, 0]\\n                                     [0, 0, 7, 0]\\n                                     [0, 0, 0, 8]]]\\n\\nwhich has shape (2, 4, 4)\\n```\",\n    \"operands\": [\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixDiagPartV3\",\n    \"summary\": \"Returns the batched diagonal part of a batched tensor.\",\n    \"description\": \"Returns a tensor with the `k[0]`-th to `k[1]`-th diagonals of the batched\\n`input`.\\n\\nAssume `input` has `r` dimensions `[I, J, ..., L, M, N]`.\\nLet `max_diag_len` be the maximum length among all diagonals to be extracted,\\n`max_diag_len = min(M + min(k[1], 0), N + min(-k[0], 0))`\\nLet `num_diags` be the number of diagonals to extract,\\n`num_diags = k[1] - k[0] + 1`.\\n\\nIf `num_diags == 1`, the output tensor is of rank `r - 1` with shape\\n`[I, J, ..., L, max_diag_len]` and values:\\n\\n```\\ndiagonal[i, j, ..., l, n]\\n  = input[i, j, ..., l, n+y, n+x] ; if 0 <= n+y < M and 0 <= n+x < N,\\n    padding_value                 ; otherwise.\\n```\\nwhere `y = max(-k[1], 0)`, `x = max(k[1], 0)`.\\n\\nOtherwise, the output tensor has rank `r` with dimensions\\n`[I, J, ..., L, num_diags, max_diag_len]` with values:\\n\\n```\\ndiagonal[i, j, ..., l, m, n]\\n  = input[i, j, ..., l, n+y, n+x] ; if 0 <= n+y < M and 0 <= n+x < N,\\n    padding_value                 ; otherwise.\\n```\\nwhere `d = k[1] - m`, `y = max(-d, 0) - offset`, and `x = max(d, 0) - offset`.\\n\\n`offset` is zero except when the alignment of the diagonal is to the right.\\n```\\noffset = max_diag_len - diag_len(d) ; if (`align` in {RIGHT_LEFT, RIGHT_RIGHT}\\n                                           and `d >= 0`) or\\n                                         (`align` in {LEFT_RIGHT, RIGHT_RIGHT}\\n                                           and `d <= 0`)\\n         0                          ; otherwise\\n```\\nwhere `diag_len(d) = min(cols - max(d, 0), rows + min(d, 0))`.\\n\\nThe input must be at least a matrix.\\n\\nFor example:\\n\\n```\\ninput = np.array([[[1, 2, 3, 4],  # Input shape: (2, 3, 4)\\n                   [5, 6, 7, 8],\\n                   [9, 8, 7, 6]],\\n                  [[5, 4, 3, 2],\\n                   [1, 2, 3, 4],\\n                   [5, 6, 7, 8]]])\\n\\n# A main diagonal from each batch.\\ntf.matrix_diag_part(input) ==> [[1, 6, 7],  # Output shape: (2, 3)\\n                                [5, 2, 7]]\\n\\n# A superdiagonal from each batch.\\ntf.matrix_diag_part(input, k = 1)\\n  ==> [[2, 7, 6],  # Output shape: (2, 3)\\n       [4, 3, 8]]\\n\\n# A band from each batch.\\ntf.matrix_diag_part(input, k = (-1, 2))\\n  ==> [[[0, 3, 8],  # Output shape: (2, 4, 3)\\n        [2, 7, 6],\\n        [1, 6, 7],\\n        [5, 8, 0]],\\n       [[0, 3, 4],\\n        [4, 3, 8],\\n        [5, 2, 7],\\n        [1, 6, 0]]]\\n\\n# LEFT_RIGHT alignment.\\ntf.matrix_diag_part(input, k = (-1, 2), align=\\\"LEFT_RIGHT\\\")\\n  ==> [[[3, 8, 0],  # Output shape: (2, 4, 3)\\n        [2, 7, 6],\\n        [1, 6, 7],\\n        [0, 5, 8]],\\n       [[3, 4, 0],\\n        [4, 3, 8],\\n        [5, 2, 7],\\n        [0, 1, 6]]]\\n\\n# max_diag_len can be shorter than the main diagonal.\\ntf.matrix_diag_part(input, k = (-2, -1))\\n  ==> [[[5, 8],\\n        [9, 0]],\\n       [[1, 6],\\n        [5, 0]]]\\n\\n# padding_value = 9\\ntf.matrix_diag_part(input, k = (1, 3), padding_value = 9)\\n  ==> [[[9, 9, 4],  # Output shape: (2, 3, 3)\\n        [9, 3, 8],\\n        [2, 7, 6]],\\n       [[9, 9, 2],\\n        [9, 3, 4],\\n        [4, 3, 8]]]\\n\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"k\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ LEFT_RIGHT, RIGHT_LEFT, LEFT_LEFT, RIGHT_RIGHT ]>, \\\"RIGHT_LEFT\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixDiagV2\",\n    \"summary\": \"Returns a batched diagonal tensor with given batched diagonal values.\",\n    \"description\": \"Returns a tensor with the contents in `diagonal` as `k[0]`-th to `k[1]`-th\\ndiagonals of a matrix, with everything else padded with `padding`. `num_rows`\\nand `num_cols` specify the dimension of the innermost matrix of the output. If\\nboth are not specified, the op assumes the innermost matrix is square and infers\\nits size from `k` and the innermost dimension of `diagonal`. If only one of them\\nis specified, the op assumes the unspecified value is the smallest possible\\nbased on other criteria.\\n\\nLet `diagonal` have `r` dimensions `[I, J, ..., L, M, N]`. The output tensor has\\nrank `r+1` with shape `[I, J, ..., L, M, num_rows, num_cols]` when only one\\ndiagonal is given (`k` is an integer or `k[0] == k[1]`). Otherwise, it has rank\\n`r` with shape `[I, J, ..., L, num_rows, num_cols]`.\\n\\nThe second innermost dimension of `diagonal` has double meaning.\\nWhen `k` is scalar or `k[0] == k[1]`, `M` is part of the batch size\\n[I, J, ..., M], and the output tensor is:\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, n-max(d_upper, 0)] ; if n - m == d_upper\\n    padding_value                             ; otherwise\\n```\\n\\nOtherwise, `M` is treated as the number of diagonals for the matrix in the\\nsame batch (`M = k[1]-k[0]+1`), and the output tensor is:\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, diag_index, index_in_diag] ; if k[0] <= d <= k[1]\\n    padding_value                                     ; otherwise\\n```\\nwhere `d = n - m`, `diag_index = k[1] - d`, and `index_in_diag = n - max(d, 0)`.\\n\\nFor example:\\n\\n```\\n# The main diagonal.\\ndiagonal = np.array([[1, 2, 3, 4],            # Input shape: (2, 4)\\n                     [5, 6, 7, 8]])\\ntf.matrix_diag(diagonal) ==> [[[1, 0, 0, 0],  # Output shape: (2, 4, 4)\\n                               [0, 2, 0, 0],\\n                               [0, 0, 3, 0],\\n                               [0, 0, 0, 4]],\\n                              [[5, 0, 0, 0],\\n                               [0, 6, 0, 0],\\n                               [0, 0, 7, 0],\\n                               [0, 0, 0, 8]]]\\n\\n# A superdiagonal (per batch).\\ndiagonal = np.array([[1, 2, 3],  # Input shape: (2, 3)\\n                     [4, 5, 6]])\\ntf.matrix_diag(diagonal, k = 1)\\n  ==> [[[0, 1, 0, 0],  # Output shape: (2, 4, 4)\\n        [0, 0, 2, 0],\\n        [0, 0, 0, 3],\\n        [0, 0, 0, 0]],\\n       [[0, 4, 0, 0],\\n        [0, 0, 5, 0],\\n        [0, 0, 0, 6],\\n        [0, 0, 0, 0]]]\\n\\n# A band of diagonals.\\ndiagonals = np.array([[[1, 2, 3],  # Input shape: (2, 2, 3)\\n                       [4, 5, 0]],\\n                      [[6, 7, 9],\\n                       [9, 1, 0]]])\\ntf.matrix_diag(diagonals, k = (-1, 0))\\n  ==> [[[1, 0, 0],  # Output shape: (2, 3, 3)\\n        [4, 2, 0],\\n        [0, 5, 3]],\\n       [[6, 0, 0],\\n        [9, 7, 0],\\n        [0, 1, 9]]]\\n\\n# Rectangular matrix.\\ndiagonal = np.array([1, 2])  # Input shape: (2)\\ntf.matrix_diag(diagonal, k = -1, num_rows = 3, num_cols = 4)\\n  ==> [[0, 0, 0, 0],  # Output shape: (3, 4)\\n       [1, 0, 0, 0],\\n       [0, 2, 0, 0]]\\n\\n# Rectangular matrix with inferred num_cols and padding_value = 9.\\ntf.matrix_diag(diagonal, k = -1, num_rows = 3, padding_value = 9)\\n  ==> [[9, 9],  # Output shape: (3, 2)\\n       [1, 9],\\n       [9, 2]]\\n```\",\n    \"operands\": [\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"k\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_rows\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_cols\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixDiagV3\",\n    \"summary\": \"Returns a batched diagonal tensor with given batched diagonal values.\",\n    \"description\": \"Returns a tensor with the contents in `diagonal` as `k[0]`-th to `k[1]`-th\\ndiagonals of a matrix, with everything else padded with `padding`. `num_rows`\\nand `num_cols` specify the dimension of the innermost matrix of the output. If\\nboth are not specified, the op assumes the innermost matrix is square and infers\\nits size from `k` and the innermost dimension of `diagonal`. If only one of them\\nis specified, the op assumes the unspecified value is the smallest possible\\nbased on other criteria.\\n\\nLet `diagonal` have `r` dimensions `[I, J, ..., L, M, N]`. The output tensor has\\nrank `r+1` with shape `[I, J, ..., L, M, num_rows, num_cols]` when only one\\ndiagonal is given (`k` is an integer or `k[0] == k[1]`). Otherwise, it has rank\\n`r` with shape `[I, J, ..., L, num_rows, num_cols]`.\\n\\nThe second innermost dimension of `diagonal` has double meaning.\\nWhen `k` is scalar or `k[0] == k[1]`, `M` is part of the batch size\\n[I, J, ..., M], and the output tensor is:\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, n-max(d_upper, 0)] ; if n - m == d_upper\\n    padding_value                             ; otherwise\\n```\\n\\nOtherwise, `M` is treated as the number of diagonals for the matrix in the\\nsame batch (`M = k[1]-k[0]+1`), and the output tensor is:\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, diag_index, index_in_diag] ; if k[0] <= d <= k[1]\\n    padding_value                                     ; otherwise\\n```\\nwhere `d = n - m`, `diag_index = [k] - d`, and\\n`index_in_diag = n - max(d, 0) + offset`.\\n\\n`offset` is zero except when the alignment of the diagonal is to the right.\\n```\\noffset = max_diag_len - diag_len(d) ; if (`align` in {RIGHT_LEFT, RIGHT_RIGHT}\\n                                           and `d >= 0`) or\\n                                         (`align` in {LEFT_RIGHT, RIGHT_RIGHT}\\n                                           and `d <= 0`)\\n         0                          ; otherwise\\n```\\nwhere `diag_len(d) = min(cols - max(d, 0), rows + min(d, 0))`.\\n\\nFor example:\\n\\n```\\n# The main diagonal.\\ndiagonal = np.array([[1, 2, 3, 4],            # Input shape: (2, 4)\\n                     [5, 6, 7, 8]])\\ntf.matrix_diag(diagonal) ==> [[[1, 0, 0, 0],  # Output shape: (2, 4, 4)\\n                               [0, 2, 0, 0],\\n                               [0, 0, 3, 0],\\n                               [0, 0, 0, 4]],\\n                              [[5, 0, 0, 0],\\n                               [0, 6, 0, 0],\\n                               [0, 0, 7, 0],\\n                               [0, 0, 0, 8]]]\\n\\n# A superdiagonal (per batch).\\ndiagonal = np.array([[1, 2, 3],  # Input shape: (2, 3)\\n                     [4, 5, 6]])\\ntf.matrix_diag(diagonal, k = 1)\\n  ==> [[[0, 1, 0, 0],  # Output shape: (2, 4, 4)\\n        [0, 0, 2, 0],\\n        [0, 0, 0, 3],\\n        [0, 0, 0, 0]],\\n       [[0, 4, 0, 0],\\n        [0, 0, 5, 0],\\n        [0, 0, 0, 6],\\n        [0, 0, 0, 0]]]\\n\\n# A tridiagonal band (per batch).\\ndiagonals = np.array([[[0, 8, 9],  # Input shape: (2, 2, 3)\\n                       [1, 2, 3],\\n                       [4, 5, 0]],\\n                      [[0, 2, 3],\\n                       [6, 7, 9],\\n                       [9, 1, 0]]])\\ntf.matrix_diag(diagonals, k = (-1, 1))\\n  ==> [[[1, 8, 0],  # Output shape: (2, 3, 3)\\n        [4, 2, 9],\\n        [0, 5, 3]],\\n       [[6, 2, 0],\\n        [9, 7, 3],\\n        [0, 1, 9]]]\\n\\n# LEFT_RIGHT alignment.\\ndiagonals = np.array([[[8, 9, 0],  # Input shape: (2, 2, 3)\\n                       [1, 2, 3],\\n                       [0, 4, 5]],\\n                      [[2, 3, 0],\\n                       [6, 7, 9],\\n                       [0, 9, 1]]])\\ntf.matrix_diag(diagonals, k = (-1, 1), align=\\\"LEFT_RIGHT\\\")\\n  ==> [[[1, 8, 0],  # Output shape: (2, 3, 3)\\n        [4, 2, 9],\\n        [0, 5, 3]],\\n       [[6, 2, 0],\\n        [9, 7, 3],\\n        [0, 1, 9]]]\\n\\n# Rectangular matrix.\\ndiagonal = np.array([1, 2])  # Input shape: (2)\\ntf.matrix_diag(diagonal, k = -1, num_rows = 3, num_cols = 4)\\n  ==> [[0, 0, 0, 0],  # Output shape: (3, 4)\\n       [1, 0, 0, 0],\\n       [0, 2, 0, 0]]\\n\\n# Rectangular matrix with inferred num_cols and padding_value = 9.\\ntf.matrix_diag(diagonal, k = -1, num_rows = 3, padding_value = 9)\\n  ==> [[9, 9],  # Output shape: (3, 2)\\n       [1, 9],\\n       [9, 2]]\\n\\n```\",\n    \"operands\": [\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"k\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_rows\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_cols\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ LEFT_RIGHT, RIGHT_LEFT, LEFT_LEFT, RIGHT_RIGHT ]>, \\\"RIGHT_LEFT\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixInverse\",\n    \"summary\": \"Computes the inverse of one or more square invertible matrices or their adjoints (conjugate transposes).\",\n    \"description\": \"The input is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions\\nform square matrices. The output is a tensor of the same shape as the input\\ncontaining the inverse for all input submatrices `[..., :, :]`.\\n\\nThe op uses LU decomposition with partial pivoting to compute the inverses.\\n\\nIf a matrix is not invertible there is no guarantee what the op does. It\\nmay detect the condition and raise an exception or it may simply return a\\ngarbage result.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adjoint\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixSetDiag\",\n    \"summary\": \"Returns a batched matrix tensor with new batched diagonal values.\",\n    \"description\": \"Given `input` and `diagonal`, this operation returns a tensor with the\\nsame shape and values as `input`, except for the main diagonal of the\\ninnermost matrices.  These will be overwritten by the values in `diagonal`.\\n\\nThe output is computed as follows:\\n\\nAssume `input` has `k+1` dimensions `[I, J, K, ..., M, N]` and `diagonal` has\\n`k` dimensions `[I, J, K, ..., min(M, N)]`.  Then the output is a\\ntensor of rank `k+1` with dimensions `[I, J, K, ..., M, N]` where:\\n\\n  * `output[i, j, k, ..., m, n] = diagonal[i, j, k, ..., n]` for `m == n`.\\n  * `output[i, j, k, ..., m, n] = input[i, j, k, ..., m, n]` for `m != n`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixSetDiagV2\",\n    \"summary\": \"Returns a batched matrix tensor with new batched diagonal values.\",\n    \"description\": \"Given `input` and `diagonal`, this operation returns a tensor with the\\nsame shape and values as `input`, except for the specified diagonals of the\\ninnermost matrices. These will be overwritten by the values in `diagonal`.\\n\\n`input` has `r+1` dimensions `[I, J, ..., L, M, N]`. When `k` is scalar or\\n`k[0] == k[1]`, `diagonal` has `r` dimensions `[I, J, ..., L, max_diag_len]`.\\nOtherwise, it has `r+1` dimensions `[I, J, ..., L, num_diags, max_diag_len]`.\\n`num_diags` is the number of diagonals, `num_diags = k[1] - k[0] + 1`.\\n`max_diag_len` is the longest diagonal in the range `[k[0], k[1]]`,\\n`max_diag_len = min(M + min(k[1], 0), N + min(-k[0], 0))`\\n\\nThe output is a tensor of rank `k+1` with dimensions `[I, J, ..., L, M, N]`.\\nIf `k` is scalar or `k[0] == k[1]`:\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, n-max(k[1], 0)] ; if n - m == k[1]\\n    input[i, j, ..., l, m, n]              ; otherwise\\n```\\n\\nOtherwise,\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, diag_index, index_in_diag] ; if k[0] <= d <= k[1]\\n    input[i, j, ..., l, m, n]                         ; otherwise\\n```\\nwhere `d = n - m`, `diag_index = k[1] - d`, and `index_in_diag = n - max(d, 0)`.\\n\\nFor example:\\n\\n```\\n# The main diagonal.\\ninput = np.array([[[7, 7, 7, 7],              # Input shape: (2, 3, 4)\\n                   [7, 7, 7, 7],\\n                   [7, 7, 7, 7]],\\n                  [[7, 7, 7, 7],\\n                   [7, 7, 7, 7],\\n                   [7, 7, 7, 7]]])\\ndiagonal = np.array([[1, 2, 3],               # Diagonal shape: (2, 3)\\n                     [4, 5, 6]])\\ntf.matrix_set_diag(diagonal) ==> [[[1, 7, 7, 7],  # Output shape: (2, 3, 4)\\n                                   [7, 2, 7, 7],\\n                                   [7, 7, 3, 7]],\\n                                  [[4, 7, 7, 7],\\n                                   [7, 5, 7, 7],\\n                                   [7, 7, 6, 7]]]\\n\\n# A superdiagonal (per batch).\\ntf.matrix_set_diag(diagonal, k = 1)\\n  ==> [[[7, 1, 7, 7],  # Output shape: (2, 3, 4)\\n        [7, 7, 2, 7],\\n        [7, 7, 7, 3]],\\n       [[7, 4, 7, 7],\\n        [7, 7, 5, 7],\\n        [7, 7, 7, 6]]]\\n\\n# A band of diagonals.\\ndiagonals = np.array([[[1, 2, 3],  # Diagonal shape: (2, 2, 3)\\n                       [4, 5, 0]],\\n                      [[6, 1, 2],\\n                       [3, 4, 0]]])\\ntf.matrix_set_diag(diagonals, k = (-1, 0))\\n  ==> [[[1, 7, 7, 7],  # Output shape: (2, 3, 4)\\n        [4, 2, 7, 7],\\n        [0, 5, 3, 7]],\\n       [[6, 7, 7, 7],\\n        [3, 1, 7, 7],\\n        [7, 4, 2, 7]]]\\n\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"k\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixSetDiagV3\",\n    \"summary\": \"Returns a batched matrix tensor with new batched diagonal values.\",\n    \"description\": \"Given `input` and `diagonal`, this operation returns a tensor with the\\nsame shape and values as `input`, except for the specified diagonals of the\\ninnermost matrices. These will be overwritten by the values in `diagonal`.\\n\\n`input` has `r+1` dimensions `[I, J, ..., L, M, N]`. When `k` is scalar or\\n`k[0] == k[1]`, `diagonal` has `r` dimensions `[I, J, ..., L, max_diag_len]`.\\nOtherwise, it has `r+1` dimensions `[I, J, ..., L, num_diags, max_diag_len]`.\\n`num_diags` is the number of diagonals, `num_diags = k[1] - k[0] + 1`.\\n`max_diag_len` is the longest diagonal in the range `[k[0], k[1]]`,\\n`max_diag_len = min(M + min(k[1], 0), N + min(-k[0], 0))`\\n\\nThe output is a tensor of rank `k+1` with dimensions `[I, J, ..., L, M, N]`.\\nIf `k` is scalar or `k[0] == k[1]`:\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, n-max(k[1], 0)] ; if n - m == k[1]\\n    input[i, j, ..., l, m, n]              ; otherwise\\n```\\n\\nOtherwise,\\n\\n```\\noutput[i, j, ..., l, m, n]\\n  = diagonal[i, j, ..., l, diag_index, index_in_diag] ; if k[0] <= d <= k[1]\\n    input[i, j, ..., l, m, n]                         ; otherwise\\n```\\nwhere `d = n - m`, `diag_index = k[1] - d`, and\\n`index_in_diag = n - max(d, 0) + offset`.\\n\\n`offset` is zero except when the alignment of the diagonal is to the right.\\n```\\noffset = max_diag_len - diag_len(d) ; if (`align` in {RIGHT_LEFT, RIGHT_RIGHT}\\n                                           and `d >= 0`) or\\n                                         (`align` in {LEFT_RIGHT, RIGHT_RIGHT}\\n                                           and `d <= 0`)\\n         0                          ; otherwise\\n```\\nwhere `diag_len(d) = min(cols - max(d, 0), rows + min(d, 0))`.\\n\\nFor example:\\n\\n```\\n# The main diagonal.\\ninput = np.array([[[7, 7, 7, 7],              # Input shape: (2, 3, 4)\\n                   [7, 7, 7, 7],\\n                   [7, 7, 7, 7]],\\n                  [[7, 7, 7, 7],\\n                   [7, 7, 7, 7],\\n                   [7, 7, 7, 7]]])\\ndiagonal = np.array([[1, 2, 3],               # Diagonal shape: (2, 3)\\n                     [4, 5, 6]])\\ntf.matrix_set_diag(input, diagonal)\\n  ==> [[[1, 7, 7, 7],  # Output shape: (2, 3, 4)\\n        [7, 2, 7, 7],\\n        [7, 7, 3, 7]],\\n       [[4, 7, 7, 7],\\n        [7, 5, 7, 7],\\n        [7, 7, 6, 7]]]\\n\\n# A superdiagonal (per batch).\\ntf.matrix_set_diag(input, diagonal, k = 1)\\n  ==> [[[7, 1, 7, 7],  # Output shape: (2, 3, 4)\\n        [7, 7, 2, 7],\\n        [7, 7, 7, 3]],\\n       [[7, 4, 7, 7],\\n        [7, 7, 5, 7],\\n        [7, 7, 7, 6]]]\\n\\n# A band of diagonals.\\ndiagonals = np.array([[[0, 9, 1],  # Diagonal shape: (2, 4, 3)\\n                       [6, 5, 8],\\n                       [1, 2, 3],\\n                       [4, 5, 0]],\\n                      [[0, 1, 2],\\n                       [5, 6, 4],\\n                       [6, 1, 2],\\n                       [3, 4, 0]]])\\ntf.matrix_set_diag(input, diagonals, k = (-1, 2))\\n  ==> [[[1, 6, 9, 7],  # Output shape: (2, 3, 4)\\n        [4, 2, 5, 1],\\n        [7, 5, 3, 8]],\\n       [[6, 5, 1, 7],\\n        [3, 1, 6, 2],\\n        [7, 4, 2, 4]]]\\n\\n# LEFT_RIGHT alignment.\\ndiagonals = np.array([[[9, 1, 0],  # Diagonal shape: (2, 4, 3)\\n                       [6, 5, 8],\\n                       [1, 2, 3],\\n                       [0, 4, 5]],\\n                      [[1, 2, 0],\\n                       [5, 6, 4],\\n                       [6, 1, 2],\\n                       [0, 3, 4]]])\\ntf.matrix_set_diag(input, diagonals, k = (-1, 2), align=\\\"LEFT_RIGHT\\\")\\n  ==> [[[1, 6, 9, 7],  # Output shape: (2, 3, 4)\\n        [4, 2, 5, 1],\\n        [7, 5, 3, 8]],\\n       [[6, 5, 1, 7],\\n        [3, 1, 6, 2],\\n        [7, 4, 2, 4]]]\\n\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"diagonal\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"k\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ LEFT_RIGHT, RIGHT_LEFT, LEFT_LEFT, RIGHT_RIGHT ]>, \\\"RIGHT_LEFT\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixSolve\",\n    \"summary\": \"Solves systems of linear equations.\",\n    \"description\": \"`Matrix` is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions\\nform square matrices. `Rhs` is a tensor of shape `[..., M, K]`. The `output` is\\na tensor shape `[..., M, K]`.  If `adjoint` is `False` then each output matrix\\nsatisfies `matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]`.\\nIf `adjoint` is `True` then each output matrix satisfies\\n`adjoint(matrix[..., :, :]) * output[..., :, :] = rhs[..., :, :]`.\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"rhs\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adjoint\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MatrixTriangularSolve\",\n    \"summary\": \"Solves systems of linear equations with upper or lower triangular matrices by backsubstitution.\",\n    \"description\": \"`matrix` is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions form\\nsquare matrices. If `lower` is `True` then the strictly upper triangular part\\nof each inner-most matrix is assumed to be zero and not accessed.\\nIf `lower` is False then the strictly lower triangular part of each inner-most\\nmatrix is assumed to be zero and not accessed.\\n`rhs` is a tensor of shape `[..., M, N]`.\\n\\nThe output is a tensor of shape `[..., M, N]`. If `adjoint` is\\n`True` then the innermost matrices in `output` satisfy matrix equations\\n`matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]`.\\nIf `adjoint` is `False` then the strictly then the  innermost matrices in\\n`output` satisfy matrix equations\\n`adjoint(matrix[..., i, k]) * output[..., k, j] = rhs[..., i, j]`.\\n\\nNote, the batch shapes for the inputs only need to broadcast.\\n\\nExample:\\n```python\\n\\na = tf.constant([[3,  0,  0,  0],\\n                 [2,  1,  0,  0],\\n                 [1,  0,  1,  0],\\n                 [1,  1,  1,  1]], dtype=tf.float32)\\n\\nb = tf.constant([[4],\\n                 [2],\\n                 [4],\\n                 [2]], dtype=tf.float32)\\n\\nx = tf.linalg.triangular_solve(a, b, lower=True)\\nx\\n# <tf.Tensor: shape=(4, 1), dtype=float32, numpy=\\n# array([[ 1.3333334 ],\\n#        [-0.66666675],\\n#        [ 2.6666665 ],\\n#        [-1.3333331 ]], dtype=float32)>\\n\\n# in python3 one can use `a@x`\\ntf.matmul(a, x)\\n# <tf.Tensor: shape=(4, 1), dtype=float32, numpy=\\n# array([[4.       ],\\n#        [2.       ],\\n#        [4.       ],\\n#        [1.9999999]], dtype=float32)>\\n```\",\n    \"operands\": [\n      { \"name\": \"matrix\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"adjoint\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Max\",\n    \"summary\": \"Computes the maximum of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Maximum\",\n    \"summary\": \"Returns the max of x and y (i.e. x > y ? x : y) element-wise.\",\n    \"description\": \"*NOTE*: `Maximum` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPool\",\n    \"summary\": \"Performs max pooling on the input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint8, TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint8, TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NCHW_VECT_C ]>, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPool3D\",\n    \"summary\": \"Performs 3D max pooling on the input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPool3DGrad\",\n    \"summary\": \"Computes gradients of 3D max pooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"orig_output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"grad\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPool3DGradGrad\",\n    \"summary\": \"Computes second-order gradients of the maxpooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"orig_output\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<5>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NDHWC, NCDHW ]>, \\\"NDHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPoolGrad\",\n    \"summary\": \"Computes gradients of the maxpooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"orig_output\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID, EXPLICIT]>\" },\n      { \"name\": \"explicit_paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPoolGradGrad\",\n    \"summary\": \"Computes second-order gradients of the maxpooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"orig_output\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksize\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"strides\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<4>]>\" },\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPoolGradGradV2\",\n    \"summary\": \"Computes second-order gradients of the maxpooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"orig_output\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"ksize\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPoolGradV2\",\n    \"summary\": \"Computes gradients of the maxpooling function.\",\n    \"operands\": [\n      { \"name\": \"orig_input\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"orig_output\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"ksize\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_ConvnetDataFormatAttr, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MaxPoolV2\",\n    \"summary\": \"Performs max pooling on the input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint8, TF_Uint16, TF_Uint8 ]>\" },\n      { \"name\": \"ksize\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint8, TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TF_AnyStrAttrOf<[SAME, VALID]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NCHW_VECT_C ]>, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Mean\",\n    \"summary\": \"Computes the mean of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MergeSummary\",\n    \"summary\": \"Merges summaries.\",\n    \"description\": \"This op creates a\\n[`Summary`](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto)\\nprotocol buffer that contains the union of all the values in the input\\nsummaries.\\n\\nWhen the Op is run, it reports an `InvalidArgument` error if multiple values\\nin the summaries to merge use the same tag.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_StrTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"summary\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MergeV2Checkpoints\",\n    \"summary\": \"V2 format specific: merges the metadata files of sharded checkpoints.  The\",\n    \"description\": \"result is one logical checkpoint, with one physical metadata file and renamed\\ndata files.\\n\\nIntended for \\\"grouping\\\" multiple checkpoints in a sharded checkpoint setup.\\n\\nIf delete_old_dirs is true, attempts to delete recursively the dirname of each\\npath in the input checkpoint_prefixes.  This is useful when those paths are non\\nuser-facing temporary locations.\\n\\nIf allow_missing_files is true, merges the checkpoint prefixes as long as\\nat least one file exists. Otherwise, if no files exist, an error will be thrown.\\nThe default value for allow_missing_files is false.\",\n    \"operands\": [\n      { \"name\": \"checkpoint_prefixes\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"destination_prefix\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"delete_old_dirs\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"allow_missing_files\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Min\",\n    \"summary\": \"Computes the minimum of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Minimum\",\n    \"summary\": \"Returns the min of x and y (i.e. x < y ? x : y) element-wise.\",\n    \"description\": \"*NOTE*: `Minimum` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MirrorPad\",\n    \"summary\": \"Pads a tensor with mirrored values.\",\n    \"description\": \"This operation pads a `input` with mirrored values according to the `paddings`\\nyou specify. `paddings` is an integer tensor with shape `[n, 2]`, where n is\\nthe rank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates\\nhow many values to add before the contents of `input` in that dimension, and\\n`paddings[D, 1]` indicates how many values to add after the contents of `input`\\nin that dimension. Both `paddings[D, 0]` and `paddings[D, 1]` must be no greater\\nthan `input.dim_size(D)` (or `input.dim_size(D) - 1`) if `copy_border` is true\\n(if false, respectively).\\n\\nThe padded size of each dimension D of the output is:\\n\\n`paddings(D, 0) + input.dim_size(D) + paddings(D, 1)`\\n\\nFor example:\\n\\n```\\n# 't' is [[1, 2, 3], [4, 5, 6]].\\n# 'paddings' is [[1, 1]], [2, 2]].\\n# 'mode' is SYMMETRIC.\\n# rank of 't' is 2.\\npad(t, paddings) ==> [[2, 1, 1, 2, 3, 3, 2]\\n                      [2, 1, 1, 2, 3, 3, 2]\\n                      [5, 4, 4, 5, 6, 6, 5]\\n                      [5, 4, 4, 5, 6, 6, 5]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"TF_AnyStrAttrOf<[REFLECT, SYMMETRIC]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MirrorPadGrad\",\n    \"summary\": \"Gradient op for `MirrorPad` op. This op folds a mirror-padded tensor.\",\n    \"description\": \"This operation folds the padded areas of `input` by `MirrorPad` according to the\\n`paddings` you specify. `paddings` must be the same as `paddings` argument\\ngiven to the corresponding `MirrorPad` op.\\n\\nThe folded size of each dimension D of the output is:\\n\\n`input.dim_size(D) - paddings(D, 0) - paddings(D, 1)`\\n\\nFor example:\\n\\n```\\n# 't' is [[1, 2, 3], [4, 5, 6], [7, 8, 9]].\\n# 'paddings' is [[0, 1]], [0, 1]].\\n# 'mode' is SYMMETRIC.\\n# rank of 't' is 2.\\npad(t, paddings) ==> [[ 1,  5]\\n                      [11, 28]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"TF_AnyStrAttrOf<[REFLECT, SYMMETRIC]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MlirLocalVarOp\",\n    \"summary\": \"Creates a handle to an in-scope variable.\",\n    \"description\": \"Used by internal passes for temporary representation of local state, which will\\nbe eventually removed.\",\n    \"results\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MlirPassthroughOp\",\n    \"summary\": \"Wraps an arbitrary MLIR computation expressed as a module with a main() function.\",\n    \"description\": \"This operation does not have an associated kernel and is not intended to be\\nexecuted in a regular TensorFlow session. Instead it is intended to be used for\\ntesting or for special case where a user intends to pass custom MLIR computation\\nthrough a TensorFlow graph with the intent of having custom tooling processing\\nit downstream (when targeting a different environment, like TensorFlow lite for\\nexample).\\nThe MLIR module is expected to have a main() function that will be used as an\\nentry point. The inputs to the operations will be passed as argument to the\\nmain() function and the returned values of the main function mapped to the\\noutputs.\\nExample usage:\\n\\n```\\nimport tensorflow as tf\\nfrom tensorflow.compiler.mlir.tensorflow.gen_mlir_passthrough_op import mlir_passthrough_op\\n\\nmlir_module = '''python\\nfunc @main(%arg0 : tensor<10xf32>, %arg1 : tensor<10xf32>) -> tensor<10x10xf32> {\\n   %add = \\\"magic.op\\\"(%arg0, %arg1) : (tensor<10xf32>, tensor<10xf32>) -> tensor<10x10xf32>\\n   return %ret : tensor<10x10xf32>\\n}\\n'''\\n\\n@tf.function\\ndef foo(x, y):\\n  return mlir_passthrough_op([x, y], mlir_module, Toutputs=[tf.float32])\\n\\ngraph_def = foo.get_concrete_function(tf.TensorSpec([10], tf.float32), tf.TensorSpec([10], tf.float32)).graph.as_graph_def()\\n```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mlir_module\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Mod\",\n    \"summary\": \"Returns element-wise remainder of division. This emulates C semantics in that\",\n    \"description\": \"the result here is consistent with a truncating divide. E.g.\\n`tf.truncatediv(x, y) * y + truncate_mod(x, y) = x`.\\n\\n*NOTE*: `Mod` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrI32OrI64Tensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ModelDataset\",\n    \"summary\": \"Identity transformation that models performance.\",\n    \"description\": \"Identity transformation that models performance.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"algorithm\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"cpu_budget\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ram_budget\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Mul\",\n    \"summary\": \"Returns x * y element-wise.\",\n    \"description\": \"*NOTE*: `Multiply` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MulNoNan\",\n    \"summary\": \"Returns x * y element-wise. Returns zero if y is zero, even if x if infinite or NaN.\",\n    \"description\": \"*NOTE*: `MulNoNan` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MultiDeviceIterator\",\n    \"summary\": \"Creates a MultiDeviceIterator resource.\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"devices\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<StrAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"shared_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"container\", \"type\": \"StrAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MultiDeviceIteratorFromStringHandle\",\n    \"summary\": \"Generates a MultiDeviceIterator resource from its provided string handle.\",\n    \"operands\": [\n      { \"name\": \"string_handle\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"multi_device_iterator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<TypeAttr>, {}>\" },\n      { \"name\": \"output_shapes\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<TF_ShapeAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MultiDeviceIteratorGetNextFromShard\",\n    \"summary\": \"Gets next element for the provided shard number.\",\n    \"operands\": [\n      { \"name\": \"multi_device_iterator\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"shard_num\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"incarnation_id\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MultiDeviceIteratorInit\",\n    \"summary\": \"Initializes the multi device iterator with the given dataset.\",\n    \"operands\": [\n      { \"name\": \"dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"multi_device_iterator\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"max_buffer_size\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"incarnation_id\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MultiDeviceIteratorToStringHandle\",\n    \"summary\": \"Produces a string handle for the given MultiDeviceIterator.\",\n    \"operands\": [\n      { \"name\": \"multi_device_iterator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"string_handle\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Multinomial\",\n    \"summary\": \"Draws samples from a multinomial distribution.\",\n    \"operands\": [\n      { \"name\": \"logits\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"num_samples\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MutableDenseHashTableV2\",\n    \"summary\": \"Creates an empty hash table that uses tensors as the backing store.\",\n    \"description\": \"It uses \\\"open addressing\\\" with quadratic reprobing to resolve\\ncollisions.\\n\\nThis op creates a mutable hash table, specifying the type of its keys and\\nvalues. Each value must be a scalar. Data can be inserted into the table using\\nthe insert operations. It does not support the initialization operation.\",\n    \"operands\": [\n      { \"name\": \"empty_key\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"deleted_key\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"use_node_name_sharing\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"value_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_shape\", \"type\": \"DefaultValuedOptionalAttr<TF_ShapeAttr, llvm::ArrayRef<int64_t>({})>\" },\n      { \"name\": \"initial_num_buckets\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 131072>\" },\n      { \"name\": \"max_load_factor\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.8f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MutableHashTableOfTensorsV2\",\n    \"summary\": \"Creates an empty hash table.\",\n    \"description\": \"This op creates a mutable hash table, specifying the type of its keys and\\nvalues. Each value must be a vector. Data can be inserted into the table using\\nthe insert operations. It does not support the initialization operation.\",\n    \"results\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"use_node_name_sharing\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"key_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_shape\", \"type\": \"DefaultValuedOptionalAttr<TF_ShapeAttr, llvm::ArrayRef<int64_t>({})>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.MutableHashTableV2\",\n    \"summary\": \"Creates an empty hash table.\",\n    \"description\": \"This op creates a mutable hash table, specifying the type of its keys and\\nvalues. Each value must be a scalar. Data can be inserted into the table using\\nthe insert operations. It does not support the initialization operation.\",\n    \"results\": [\n      { \"name\": \"table_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"use_node_name_sharing\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"key_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_dtype\", \"type\": \"TypeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.NcclAllReduce\",\n    \"summary\": \"Outputs a tensor containing the reduction across all input tensors.\",\n    \"description\": \"Outputs a tensor containing the reduction across all input tensors passed to ops\\nwithin the same `shared_name.\\n\\nThe graph should be constructed so if one op runs with shared_name value `c`,\\nthen `num_devices` ops will run with shared_name value `c`.  Failure to do so\\nwill cause the graph execution to fail to complete.\\n\\ninput: the input to the reduction\\ndata: the value of the reduction across all `num_devices` devices.\\nreduction: the reduction operation to perform.\\nnum_devices: The number of devices participating in this reduction.\\nshared_name: Identifier that shared between ops of the same reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"data\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"TF_AnyStrAttrOf<[min, max, prod, sum]>\" },\n      { \"name\": \"num_devices\", \"type\": \"I64Attr\" },\n      { \"name\": \"shared_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Ndtri\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Neg\",\n    \"summary\": \"Computes numerical negative value element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = -x\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.NextAfter\",\n    \"summary\": \"Returns the next representable value of `x1` in the direction of `x2`, element-wise.\",\n    \"description\": \"This operation returns the same result as the C++ std::nextafter function.\\n\\nIt can also return a subnormal number.\\n\\n@compatibility(cpp)\\nEquivalent to C++ std::nextafter function.\\n@end_compatibility\",\n    \"operands\": [\n      { \"name\": \"x1\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"x2\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.NonMaxSuppressionV3\",\n    \"summary\": \"Greedily selects a subset of bounding boxes in descending order of score,\",\n    \"description\": \"pruning away boxes that have high intersection-over-union (IOU) overlap\\nwith previously selected boxes.  Bounding boxes with score less than\\n`score_threshold` are removed.  Bounding boxes are supplied as\\n[y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any\\ndiagonal pair of box corners and the coordinates can be provided as normalized\\n(i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm\\nis agnostic to where the origin is in the coordinate system and more\\ngenerally is invariant to orthogonal transformations and translations\\nof the coordinate system; thus translating or reflections of the coordinate\\nsystem result in the same boxes being selected by the algorithm.\\nThe output of this operation is a set of integers indexing into the input\\ncollection of bounding boxes representing the selected boxes.  The bounding\\nbox coordinates corresponding to the selected indices can then be obtained\\nusing the `tf.gather operation`.  For example:\\n  selected_indices = tf.image.non_max_suppression_v2(\\n      boxes, scores, max_output_size, iou_threshold, score_threshold)\\n  selected_boxes = tf.gather(boxes, selected_indices)\",\n    \"operands\": [\n      { \"name\": \"boxes\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scores\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"max_output_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"iou_threshold\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"score_threshold\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_indices\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.NonMaxSuppressionV4\",\n    \"summary\": \"Greedily selects a subset of bounding boxes in descending order of score,\",\n    \"description\": \"pruning away boxes that have high intersection-over-union (IOU) overlap\\nwith previously selected boxes.  Bounding boxes with score less than\\n`score_threshold` are removed.  Bounding boxes are supplied as\\n[y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any\\ndiagonal pair of box corners and the coordinates can be provided as normalized\\n(i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm\\nis agnostic to where the origin is in the coordinate system and more\\ngenerally is invariant to orthogonal transformations and translations\\nof the coordinate system; thus translating or reflections of the coordinate\\nsystem result in the same boxes being selected by the algorithm.\\nThe output of this operation is a set of integers indexing into the input\\ncollection of bounding boxes representing the selected boxes.  The bounding\\nbox coordinates corresponding to the selected indices can then be obtained\\nusing the `tf.gather operation`.  For example:\\n  selected_indices = tf.image.non_max_suppression_v2(\\n      boxes, scores, max_output_size, iou_threshold, score_threshold)\\n  selected_boxes = tf.gather(boxes, selected_indices)\",\n    \"operands\": [\n      { \"name\": \"boxes\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scores\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"max_output_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"iou_threshold\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"score_threshold\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"valid_outputs\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad_to_max_output_size\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.NonMaxSuppressionV5\",\n    \"summary\": \"Greedily selects a subset of bounding boxes in descending order of score,\",\n    \"description\": \"pruning away boxes that have high intersection-over-union (IOU) overlap\\nwith previously selected boxes.  Bounding boxes with score less than\\n`score_threshold` are removed.  Bounding boxes are supplied as\\n[y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any\\ndiagonal pair of box corners and the coordinates can be provided as normalized\\n(i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm\\nis agnostic to where the origin is in the coordinate system and more\\ngenerally is invariant to orthogonal transformations and translations\\nof the coordinate system; thus translating or reflections of the coordinate\\nsystem result in the same boxes being selected by the algorithm.\\nThe output of this operation is a set of integers indexing into the input\\ncollection of bounding boxes representing the selected boxes.  The bounding\\nbox coordinates corresponding to the selected indices can then be obtained\\nusing the `tf.gather operation`.  For example:\\n  selected_indices = tf.image.non_max_suppression_v2(\\n      boxes, scores, max_output_size, iou_threshold, score_threshold)\\n  selected_boxes = tf.gather(boxes, selected_indices)\\nThis op also supports a Soft-NMS (with Gaussian weighting) mode (c.f.\\nBodla et al, https://arxiv.org/abs/1704.04503) where boxes reduce the score\\nof other overlapping boxes instead of directly causing them to be pruned.\\nTo enable this Soft-NMS mode, set the `soft_nms_sigma` parameter to be\\nlarger than 0.\",\n    \"operands\": [\n      { \"name\": \"boxes\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"scores\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"max_output_size\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"iou_threshold\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"score_threshold\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"soft_nms_sigma\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"selected_scores\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32 ]>\" },\n      { \"name\": \"valid_outputs\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad_to_max_output_size\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.NoOp\",\n    \"summary\": \"Does nothing. Only useful as a placeholder for control edges.\"\n  },\n  {\n    \"name\": \"tf.NotEqual\",\n    \"summary\": \"Returns the truth value of (x != y) element-wise.\",\n    \"description\": \"*NOTE*: `NotEqual` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"incompatible_shape_error\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OneHot\",\n    \"summary\": \"Returns a one-hot tensor.\",\n    \"description\": \"The locations represented by indices in `indices` take value `on_value`,\\nwhile all other locations take value `off_value`.\\n\\nIf the input `indices` is rank `N`, the output will have rank `N+1`,\\nThe new axis is created at dimension `axis` (default: the new axis is\\nappended at the end).\\n\\nIf `indices` is a scalar the output shape will be a vector of length `depth`.\\n\\nIf `indices` is a vector of length `features`, the output shape will be:\\n```\\n  features x depth if axis == -1\\n  depth x features if axis == 0\\n```\\n\\nIf `indices` is a matrix (batch) with shape `[batch, features]`,\\nthe output shape will be:\\n```\\n  batch x features x depth if axis == -1\\n  batch x depth x features if axis == 1\\n  depth x batch x features if axis == 0\\n```\\n\\n\\nExamples\\n=========\\n\\nSuppose that\\n```\\n  indices = [0, 2, -1, 1]\\n  depth = 3\\n  on_value = 5.0\\n  off_value = 0.0\\n  axis = -1\\n```\\n\\nThen output is `[4 x 3]`:\\n```\\noutput =\\n  [5.0 0.0 0.0]  // one_hot(0)\\n  [0.0 0.0 5.0]  // one_hot(2)\\n  [0.0 0.0 0.0]  // one_hot(-1)\\n  [0.0 5.0 0.0]  // one_hot(1)\\n```\\n\\nSuppose that\\n```\\n  indices = [0, 2, -1, 1]\\n  depth = 3\\n  on_value = 0.0\\n  off_value = 3.0\\n  axis = 0\\n```\\n\\nThen output is `[3 x 4]`:\\n```\\noutput =\\n  [0.0 3.0 3.0 3.0]\\n  [3.0 3.0 3.0 0.0]\\n  [3.0 3.0 3.0 3.0]\\n  [3.0 0.0 3.0 3.0]\\n//  ^                one_hot(0)\\n//      ^            one_hot(2)\\n//          ^        one_hot(-1)\\n//              ^    one_hot(1)\\n```\\n\\nSuppose that\\n```\\n  indices = [[0, 2], [1, -1]]\\n  depth = 3\\n  on_value = 1.0\\n  off_value = 0.0\\n  axis = -1\\n```\\n\\nThen output is `[2 x 2 x 3]`:\\n```\\noutput =\\n  [\\n    [1.0, 0.0, 0.0]  // one_hot(0)\\n    [0.0, 0.0, 1.0]  // one_hot(2)\\n  ][\\n    [0.0, 1.0, 0.0]  // one_hot(1)\\n    [0.0, 0.0, 0.0]  // one_hot(-1)\\n  ]\\n```\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Int8, TF_Uint8 ]>\" },\n      { \"name\": \"depth\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"on_value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"off_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OneShotIterator\",\n    \"summary\": \"Makes a \\\"one-shot\\\" iterator that can be iterated only once.\",\n    \"description\": \"A one-shot iterator bundles the logic for defining the dataset and\\nthe state of the iterator in a single op, which allows simple input\\npipelines to be defined without an additional initialization\\n(\\\"MakeIterator\\\") step.\\n\\nOne-shot iterators have the following limitations:\\n\\n* They do not support parameterization: all logic for creating the underlying\\n  dataset must be bundled in the `dataset_factory` function.\\n* They are not resettable. Once a one-shot iterator reaches the end of its\\n  underlying dataset, subsequent \\\"IteratorGetNext\\\" operations on that\\n  iterator will always produce an `OutOfRange` error.\\n\\nFor greater flexibility, use \\\"Iterator\\\" and \\\"MakeIterator\\\" to define\\nan iterator using an arbitrary subgraph, which may capture tensors\\n(including fed values) as parameters, and which may be reset multiple\\ntimes by rerunning \\\"MakeIterator\\\".\",\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dataset_factory\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OnesLike\",\n    \"summary\": \"Returns a tensor of ones with the same shape and type as x.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OptimizeDatasetV2\",\n    \"summary\": \"Creates a dataset by applying related optimizations to `input_dataset`.\",\n    \"description\": \"Creates a dataset by applying related optimizations to `input_dataset`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"optimizations_enabled\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"optimizations_disabled\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"optimizations_default\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"optimization_configs\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OptionalFromValue\",\n    \"summary\": \"Constructs an Optional variant from a tuple of tensors.\",\n    \"operands\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OptionalGetValue\",\n    \"summary\": \"Returns the value stored in an Optional variant or raises an error if none exists.\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OptionalHasValue\",\n    \"summary\": \"Returns true if and only if the given Optional variant has a value.\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"has_value\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OptionalNone\",\n    \"summary\": \"Creates an Optional variant with no value.\",\n    \"results\": [\n      { \"name\": \"optional\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OutfeedEnqueue\",\n    \"summary\": \"Enqueue a Tensor on the computation outfeed.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.OutfeedEnqueueTuple\",\n    \"summary\": \"Enqueue multiple Tensor values on the computation outfeed.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Pack\",\n    \"summary\": \"Packs a list of `N` rank-`R` tensors into one rank-`(R+1)` tensor.\",\n    \"description\": \"Packs the `N` tensors in `values` into a tensor with rank one higher than each\\ntensor in `values`, by packing them along the `axis` dimension.\\nGiven a list of tensors of shape `(A, B, C)`;\\n\\nif `axis == 0` then the `output` tensor will have the shape `(N, A, B, C)`.\\nif `axis == 1` then the `output` tensor will have the shape `(A, N, B, C)`.\\nEtc.\\n\\nFor example:\\n\\n```\\n# 'x' is [1, 4]\\n# 'y' is [2, 5]\\n# 'z' is [3, 6]\\npack([x, y, z]) => [[1, 4], [2, 5], [3, 6]]  # Pack along first dim.\\npack([x, y, z], axis=1) => [[1, 2, 3], [4, 5, 6]]\\n```\\n\\nThis is the opposite of `unpack`.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Pad\",\n    \"category\": \"Transform\",\n    \"summary\": \"Pads a tensor with zeros.\",\n    \"description\": \"This operation pads a `input` with zeros according to the `paddings` you\\nspecify. `paddings` is an integer tensor with shape `[Dn, 2]`, where n is the\\nrank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates\\nhow many zeros to add before the contents of `input` in that dimension, and\\n`paddings[D, 1]` indicates how many zeros to add after the contents of `input`\\nin that dimension.\\n\\nThe padded size of each dimension D of the output is:\\n\\n`paddings(D, 0) + input.dim_size(D) + paddings(D, 1)`\\n\\nFor example:\\n\\n```\\n# 't' is [[1, 1], [2, 2]]\\n# 'paddings' is [[1, 1], [2, 2]]\\n# rank of 't' is 2\\npad(t, paddings) ==> [[0, 0, 0, 0, 0, 0]\\n                      [0, 0, 1, 1, 0, 0]\\n                      [0, 0, 2, 2, 0, 0]\\n                      [0, 0, 0, 0, 0, 0]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PadV2\",\n    \"summary\": \"Pads a tensor.\",\n    \"description\": \"This operation pads `input` according to the `paddings` and `constant_values`\\nyou specify. `paddings` is an integer tensor with shape `[Dn, 2]`, where n is\\nthe rank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates\\nhow many padding values to add before the contents of `input` in that dimension,\\nand `paddings[D, 1]` indicates how many padding values to add after the contents\\nof `input` in that dimension. `constant_values` is a scalar tensor of the same\\ntype as `input` that indicates the value to use for padding `input`.\\n\\nThe padded size of each dimension D of the output is:\\n\\n`paddings(D, 0) + input.dim_size(D) + paddings(D, 1)`\\n\\nFor example:\\n\\n```\\n# 't' is [[1, 1], [2, 2]]\\n# 'paddings' is [[1, 1], [2, 2]]\\n# 'constant_values' is 0\\n# rank of 't' is 2\\npad(t, paddings) ==> [[0, 0, 0, 0, 0, 0]\\n                      [0, 0, 1, 1, 0, 0]\\n                      [0, 0, 2, 2, 0, 0]\\n                      [0, 0, 0, 0, 0, 0]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"constant_values\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ParallelDynamicStitch\",\n    \"summary\": \"Interleave the values from the `data` tensors into a single tensor.\",\n    \"description\": \"Builds a merged tensor such that\\n\\n```python\\n    merged[indices[m][i, ..., j], ...] = data[m][i, ..., j, ...]\\n```\\n\\nFor example, if each `indices[m]` is scalar or vector, we have\\n\\n```python\\n    # Scalar indices:\\n    merged[indices[m], ...] = data[m][...]\\n\\n    # Vector indices:\\n    merged[indices[m][i], ...] = data[m][i, ...]\\n```\\n\\nEach `data[i].shape` must start with the corresponding `indices[i].shape`,\\nand the rest of `data[i].shape` must be constant w.r.t. `i`.  That is, we\\nmust have `data[i].shape = indices[i].shape + constant`.  In terms of this\\n`constant`, the output shape is\\n\\n    merged.shape = [max(indices)] + constant\\n\\nValues may be merged in parallel, so if an index appears in both `indices[m][i]`\\nand `indices[n][j]`, the result may be invalid. This differs from the normal\\nDynamicStitch operator that defines the behavior in that case.\\n\\nFor example:\\n\\n```python\\n    indices[0] = 6\\n    indices[1] = [4, 1]\\n    indices[2] = [[5, 2], [0, 3]]\\n    data[0] = [61, 62]\\n    data[1] = [[41, 42], [11, 12]]\\n    data[2] = [[[51, 52], [21, 22]], [[1, 2], [31, 32]]]\\n    merged = [[1, 2], [11, 12], [21, 22], [31, 32], [41, 42],\\n              [51, 52], [61, 62]]\\n```\\n\\nThis method can be used to merge partitions created by `dynamic_partition`\\nas illustrated on the following example:\\n\\n```python\\n    # Apply function (increments x_i) on elements for which a certain condition\\n    # apply (x_i != -1 in this example).\\n    x=tf.constant([0.1, -1., 5.2, 4.3, -1., 7.4])\\n    condition_mask=tf.not_equal(x,tf.constant(-1.))\\n    partitioned_data = tf.dynamic_partition(\\n        x, tf.cast(condition_mask, tf.int32) , 2)\\n    partitioned_data[1] = partitioned_data[1] + 1.0\\n    condition_indices = tf.dynamic_partition(\\n        tf.range(tf.shape(x)[0]), tf.cast(condition_mask, tf.int32) , 2)\\n    x = tf.dynamic_stitch(condition_indices, partitioned_data)\\n    # Here x=[1.1, -1., 6.2, 5.3, -1, 8.4], the -1. values remain\\n    # unchanged.\\n```\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/DynamicStitch.png\\\" alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"data\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"merged\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ParallelMapDataset\",\n    \"summary\": \"Creates a dataset that applies `f` to the outputs of `input_dataset`.\",\n    \"description\": \"Unlike a \\\"MapDataset\\\", which applies `f` sequentially, this dataset invokes up\\nto `num_parallel_calls` copies of `f` in parallel.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"num_parallel_calls\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"use_inter_op_parallelism\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"sloppy\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"preserve_cardinality\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ParallelMapDatasetV2\",\n    \"summary\": \"Creates a dataset that applies `f` to the outputs of `input_dataset`.\",\n    \"description\": \"Unlike a \\\"MapDataset\\\", which applies `f` sequentially, this dataset invokes up\\nto `num_parallel_calls` copies of `f` in parallel.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"num_parallel_calls\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"use_inter_op_parallelism\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"deterministic\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"default\\\">\" },\n      { \"name\": \"preserve_cardinality\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_unbounded_threadpool\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ParameterizedTruncatedNormal\",\n    \"summary\": \"Outputs random values from a normal distribution. The parameters may each be a\",\n    \"description\": \"scalar which applies to the entire output, or a vector of length shape[0] which\\nstores the parameters for each batch.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"means\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"stdevs\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"minvals\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"maxvals\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ParseExample\",\n    \"summary\": \"Transforms a vector of tf.Example protos (as strings) into typed tensors.\",\n    \"operands\": [\n      { \"name\": \"serialized\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"sparse_keys\", \"type\": \"Variadic<TF_StrTensor>\" },\n      { \"name\": \"dense_keys\", \"type\": \"Variadic<TF_StrTensor>\" },\n      { \"name\": \"dense_defaults\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sparse_indices\", \"type\": \"Variadic<TF_Int64Tensor>\" },\n      { \"name\": \"sparse_values\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" },\n      { \"name\": \"sparse_shapes\", \"type\": \"Variadic<TF_Int64Tensor>\" },\n      { \"name\": \"dense_values\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dense_shapes\", \"type\": \"TypedArrayAttrBase<TF_ShapeAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ParseExampleV2\",\n    \"summary\": \"Transforms a vector of tf.Example protos (as strings) into typed tensors.\",\n    \"operands\": [\n      { \"name\": \"serialized\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"sparse_keys\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"dense_keys\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"ragged_keys\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"dense_defaults\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sparse_indices\", \"type\": \"Variadic<TF_Int64Tensor>\" },\n      { \"name\": \"sparse_values\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" },\n      { \"name\": \"sparse_shapes\", \"type\": \"Variadic<TF_Int64Tensor>\" },\n      { \"name\": \"dense_values\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" },\n      { \"name\": \"ragged_values\", \"type\": \"Variadic<TensorOf<[ TF_Float32, TF_Int64, TF_Str ]>>\" },\n      { \"name\": \"ragged_row_splits\", \"type\": \"Variadic<TensorOf<[ TF_Int32, TF_Int64 ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_sparse\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"dense_shapes\", \"type\": \"TypedArrayAttrBase<TF_ShapeAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PartitionedCall\",\n    \"summary\": \"returns `f(inputs)`, where `f`'s body is placed and partitioned.\",\n    \"description\": \"Asynchronously executes a function, potentially across multiple devices but\\nwithin a single process. The kernel places and partitions a given function's\\nunderlying graph, and executes each of the partitioned subgraphs as a function.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"config_proto\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"executor_type\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Placeholder\",\n    \"summary\": \"Placeholder op\",\n    \"description\": \"Inserts a placeholder for a tensor that will be always fed.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PlaceholderWithDefault\",\n    \"summary\": \"Placeholder op\",\n    \"description\": \"A placeholder op that passes through input when its output is not fed.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Polygamma\",\n    \"summary\": \"Compute the polygamma function \\\\\\\\(\\\\psi^{(n)}(x)\\\\\\\\).\",\n    \"description\": \"The polygamma function is defined as:\\n\\n\\n\\\\\\\\(\\\\psi^{(a)}(x) = \\\\frac{d^a}{dx^a} \\\\psi(x)\\\\\\\\)\\n\\nwhere \\\\\\\\(\\\\psi(x)\\\\\\\\) is the digamma function.\\nThe polygamma function is defined only for non-negative integer orders \\\\\\\\a\\\\\\\\.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"x\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PopulationCount\",\n    \"summary\": \"Computes element-wise population count (a.k.a. popcount, bitsum, bitcount).\",\n    \"description\": \"For each entry in `x`, calculates the number of `1` (on) bits in the binary\\nrepresentation of that entry.\\n\\n**NOTE**: It is more efficient to first `tf.bitcast` your tensors into\\n`int32` or `int64` and perform the bitcount on the result, than to feed in\\n8- or 16-bit inputs and then aggregate the resulting counts.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Uint8Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PostProcessPrediction\",\n    \"summary\": \"Performs post-processing on prediction inputs. This op has no tensor outputs.\",\n    \"description\": \"Send an rpc to the external service that builds rpc payload based on prediction result.\",\n    \"operands\": [\n      { \"name\": \"steps\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"gaia_id\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"video_id\", \"type\": \"TF_Uint64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Pow\",\n    \"summary\": \"Computes the power of one value to another.\",\n    \"description\": \"Given a tensor `x` and a tensor `y`, this operation computes \\\\\\\\(x^y\\\\\\\\) for\\ncorresponding elements in `x` and `y`. For example:\\n\\n```\\n# tensor 'x' is [[2, 2]], [3, 3]]\\n# tensor 'y' is [[8, 16], [2, 3]]\\ntf.pow(x, y) ==> [[256, 65536], [9, 27]]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PrefetchDataset\",\n    \"summary\": \"Creates a dataset that asynchronously prefetches elements from `input_dataset`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"buffer_size\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"slack_period\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"legacy_autotune\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"buffer_size_min\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PreventGradient\",\n    \"summary\": \"An identity op that triggers an error if a gradient is requested.\",\n    \"description\": \"When executed in a graph, this op outputs its input tensor as-is.\\n\\nWhen building ops to compute gradients, the TensorFlow gradient system\\nwill return an error when trying to lookup the gradient of this op,\\nbecause no gradient must ever be registered for this function.  This\\nop exists to prevent subtle bugs from silently returning unimplemented\\ngradients in some corner cases.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Print\",\n    \"summary\": \"Prints a list of tensors.\",\n    \"description\": \"Passes `input` through to `output` and prints `data` when evaluating.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"data\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"first_n\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"summarize\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 3>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PrintV2\",\n    \"summary\": \"Prints a string scalar.\",\n    \"description\": \"Prints a string scalar to the desired output_stream.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_stream\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"stderr\\\">\" },\n      { \"name\": \"end\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\\n\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Prod\",\n    \"summary\": \"Computes the product of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.PwStreamResults\",\n    \"summary\": \"Streams results back to the controller\",\n    \"description\": \"This op is a TensorFlow op that represents \\\"streamed outputs\\\", where\\n    intermediate results can be returned immediately without waiting for the\\n    entire signature computation to complete.\\n\\n    This op takes `args` with their `names` (their cardinality must match) and\\n    sends the given argument tensors back to the serving controller. This\\n    triggers a controller-side stream callback (see `ScopedStreamCallback`).\\n\\n    In addition to the listed attributes, this op has two \\\"hidden\\\" attributes\\n    that do not exist in SavedModel but are dynamically populated by the serving\\n    runtime:\\n\\n    * `_controller_address`: Address of the remote instance to which tensors\\n      will be sent via e.g. RPC.\\n    * `_callback_id`: Identifier for the callback to be called from the\\n      controller. See `ScopedStreamCallback`.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Qr\",\n    \"summary\": \"Computes the QR decompositions of one or more matrices.\",\n    \"description\": \"Computes the QR decomposition of each inner matrix in `tensor` such that\\n`tensor[..., :, :] = q[..., :, :] * r[..., :,:])`\\n\\nCurrently, the gradient for the QR decomposition is well-defined only when\\nthe first `P` columns of the inner matrix are linearly independent, where\\n`P` is the minimum of `M` and `N`, the 2 inner-most dimmensions of `tensor`.\\n\\n```python\\n# a is a tensor.\\n# q is a tensor of orthonormal matrices.\\n# r is a tensor of upper triangular matrices.\\nq, r = qr(a)\\nq_full, r_full = qr(a, full_matrices=True)\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"q\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"r\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"full_matrices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.QuantizeAndDequantize\",\n    \"summary\": \"Use QuantizeAndDequantizeV2 instead.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signed_input\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"range_given\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"input_min\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" },\n      { \"name\": \"input_max\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.QuantizeAndDequantizeV2\",\n    \"summary\": \"Quantizes then dequantizes a tensor.\",\n    \"description\": \"This op simulates the precision loss from the quantized forward pass by:\\n\\n1. Quantizing the tensor to fixed point numbers, which should match the target\\n   quantization method when it is used in inference.\\n2. Dequantizing it back to floating point numbers for the following ops, most\\n   likely matmul.\\n\\nThere are different ways to quantize. This version uses only scaling, so 0.0\\nmaps to 0.\\n\\nFrom the specified 'num_bits' in the quantized output type, it determines\\nminimum and maximum representable quantized values.\\n\\ne.g.\\n\\n*   [-128, 127] for signed, num_bits = 8, or\\n*   [0, 255] for unsigned, num_bits = 8.\\n\\nIf range_given == False, the initial input_min, input_max will be determined\\nautomatically as the minimum and maximum values in the input tensor, otherwise\\nthe specified values of input_min, input_max are used.\\n\\nNote: If the input_min, input_max are specified, they do not need to equal the\\nactual minimum and maximum values in the tensor. e.g. in some cases it may be\\nbeneficial to specify these values such that the low probability extremes of the\\ninput distribution are clipped.\\n\\nThis op determines the maximum scale_factor that would map the initial\\n[input_min, input_max] range to a range that lies within the representable\\nquantized range.\\n\\nIt determines the scale from one of input_min and input_max, then updates the\\nother one to maximize the representable range.\\n\\ne.g.\\n\\n*   if the output is signed, num_bits = 8, [input_min, input_max] = [-10.0,\\n    5.0]: it would use a scale_factor of -128 / -10.0 = 12.8 In this case, it\\n    would update input_max to be 127 / 12.8 = 9.921875\\n*   if the output is signed, num_bits = 8, [input_min, input_max] = [-10.0,\\n    10.0]: it would use a scale_factor of 127 / 10.0 = 12.7 In this case, it\\n    would update input_min to be 128.0 / 12.7 = -10.07874\\n*   if the output is unsigned, input_min is forced to be 0, and only the\\n    specified input_max is used.\\n\\nAfter determining the scale_factor and updating the input range, it applies the\\nfollowing to each value in the 'input' tensor.\\n\\noutput = round(clamp(value, input_min, input_max) * scale_factor) / scale_factor.\\n\\nThe above round function rounds the value based on the given round_mode.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"input_min\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"input_max\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signed_input\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"range_given\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ HALF_TO_EVEN, HALF_UP ]>, \\\"HALF_TO_EVEN\\\">\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.QuantizeAndDequantizeV3\",\n    \"summary\": \"Quantizes then dequantizes a tensor.\",\n    \"description\": \"This is almost identical to QuantizeAndDequantizeV2, except that num_bits is a\\ntensor, so its value can change during training.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"input_min\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"input_max\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"num_bits\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signed_input\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"range_given\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.QuantizeAndDequantizeV4\",\n    \"summary\": \"Quantizes then dequantizes a tensor.\",\n    \"description\": \"This is almost identical to QuantizeAndDequantizeV2, except that it returns a\\ngradient of 1 for inputs that are within the quantization range, or 0 otherwise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"input_min\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"input_max\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"signed_input\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"num_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 8>\" },\n      { \"name\": \"range_given\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ HALF_TO_EVEN, HALF_UP ]>, \\\"HALF_TO_EVEN\\\">\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.QuantizeV2\",\n    \"summary\": \"Quantize the 'input' tensor of type float to 'output' tensor of type 'T'.\",\n    \"description\": \"[min_range, max_range] are scalar floats that specify the range for\\nthe 'input' data. The 'mode' attribute controls exactly which calculations are\\nused to convert the float values to their quantized equivalents.  The\\n'round_mode' attribute controls which rounding tie-breaking algorithm is used\\nwhen rounding float values to their quantized equivalents.\\n\\nIn 'MIN_COMBINED' mode, each value of the tensor will undergo the following:\\n\\n```\\nout[i] = (in[i] - min_range) * range(T) / (max_range - min_range)\\nif T == qint8: out[i] -= (range(T) + 1) / 2.0\\n```\\n\\nhere `range(T) = numeric_limits<T>::max() - numeric_limits<T>::min()`\\n\\n*MIN_COMBINED Mode Example*\\n\\nAssume the input is type float and has a possible range of [0.0, 6.0] and the\\noutput type is quint8 ([0, 255]). The min_range and max_range values should be\\nspecified as 0.0 and 6.0. Quantizing from float to quint8 will multiply each\\nvalue of the input by 255/6 and cast to quint8.\\n\\nIf the output type was qint8 ([-128, 127]), the operation will additionally\\nsubtract each value by 128 prior to casting, so that the range of values aligns\\nwith the range of qint8.\\n\\nIf the mode is 'MIN_FIRST', then this approach is used:\\n\\n```\\nnum_discrete_values = 1 << (# of bits in T)\\nrange_adjust = num_discrete_values / (num_discrete_values - 1)\\nrange = (range_max - range_min) * range_adjust\\nrange_scale = num_discrete_values / range\\nquantized = round(input * range_scale) - round(range_min * range_scale) +\\n  numeric_limits<T>::min()\\nquantized = max(quantized, numeric_limits<T>::min())\\nquantized = min(quantized, numeric_limits<T>::max())\\n```\\n\\nThe biggest difference between this and MIN_COMBINED is that the minimum range\\nis rounded first, before it's subtracted from the rounded value. With\\nMIN_COMBINED, a small bias is introduced where repeated iterations of quantizing\\nand dequantizing will introduce a larger and larger error.\\n\\n*SCALED mode Example*\\n\\n`SCALED` mode matches the quantization approach used in\\n`QuantizeAndDequantize{V2|V3}`.\\n\\nIf the mode is `SCALED`, the quantization is performed by multiplying each\\ninput value by a scaling_factor.\\nThe scaling_factor is determined from `min_range` and `max_range` to be as large\\nas possible such that the range from `min_range` to `max_range` is representable\\nwithin values of type T.\\n\\n```c++\\n\\n  const int min_T = std::numeric_limits<T>::min();\\n  const int max_T = std::numeric_limits<T>::max();\\n  const float max_float = std::numeric_limits<float>::max();\\n\\n  const float scale_factor_from_min_side =\\n      (min_T * min_range > 0) ? min_T / min_range : max_float;\\n  const float scale_factor_from_max_side =\\n      (max_T * max_range > 0) ? max_T / max_range : max_float;\\n\\n  const float scale_factor = std::min(scale_factor_from_min_side,\\n                                      scale_factor_from_max_side);\\n```\\n\\nWe next use the scale_factor to adjust min_range and max_range as follows:\\n\\n```c++\\n      min_range = min_T / scale_factor;\\n      max_range = max_T / scale_factor;\\n```\\n\\n\\ne.g. if T = qint8, and initially min_range = -10, and max_range = 9, we would\\ncompare -128/-10.0 = 12.8 to 127/9.0 = 14.11, and set scaling_factor = 12.8\\nIn this case, min_range would remain -10, but max_range would be adjusted to\\n127 / 12.8 = 9.921875\\n\\nSo we will quantize input values in the range (-10, 9.921875) to (-128, 127).\\n\\nThe input tensor can now be quantized by clipping values to the range\\n`min_range` to `max_range`, then multiplying by scale_factor as follows:\\n\\n```c++\\nresult = round(min(max_range, max(min_range, input)) * scale_factor)\\n```\\n\\nThe adjusted `min_range` and `max_range` are returned as outputs 2 and 3 of\\nthis operation. These outputs should be used as the range for any further\\ncalculations.\\n\\n\\n*narrow_range (bool) attribute*\\n\\nIf true, we do not use the minimum quantized value.\\ni.e. for int8 the quantized output, it would be restricted to the range\\n-127..127 instead of the full -128..127 range.\\nThis is provided for compatibility with certain inference backends.\\n(Only applies to SCALED mode)\\n\\n\\n*axis (int) attribute*\\n\\nAn optional `axis` attribute can specify a dimension index of the input tensor,\\nsuch that quantization ranges will be calculated and applied separately for each\\nslice of the tensor along that dimension. This is useful for per-channel\\nquantization.\\n\\nIf axis is specified, min_range and max_range\\n\\nif `axis`=None, per-tensor quantization is performed as normal.\\n\\n\\n*ensure_minimum_range (float) attribute*\\n\\nEnsures the minimum quantization range is at least this value.\\nThe legacy default value for this is 0.01, but it is strongly suggested to\\nset it to 0 for new uses.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"min_range\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"max_range\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8 ]>\" },\n      { \"name\": \"output_min\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"output_max\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ MIN_COMBINED, MIN_FIRST, SCALED ]>, \\\"MIN_COMBINED\\\">\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ HALF_AWAY_FROM_ZERO, HALF_TO_EVEN ]>, \\\"HALF_AWAY_FROM_ZERO\\\">\" },\n      { \"name\": \"narrow_range\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"ensure_minimum_range\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.01f>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.QueueDequeueV2\",\n    \"summary\": \"Dequeues a tuple of one or more tensors from the given queue.\",\n    \"description\": \"This operation has k outputs, where k is the number of components\\nin the tuples stored in the given queue, and output i is the ith\\ncomponent of the dequeued tuple.\\n\\nN.B. If the queue is empty, this operation will block until an element\\nhas been dequeued (or 'timeout_ms' elapses, if specified).\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"timeout_ms\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RaggedGather\",\n    \"summary\": \"Gather ragged slices from `params` axis `0` according to `indices`.\",\n    \"description\": \"Outputs a `RaggedTensor` output composed from `output_dense_values` and\\n`output_nested_splits`, such that:\\n\\n```python\\noutput.shape = indices.shape + params.shape[1:]\\noutput.ragged_rank = indices.shape.ndims + params.ragged_rank\\noutput[i...j, d0...dn] = params[indices[i...j], d0...dn]\\n```\\n\\nwhere\\n\\n* `params =\\n   ragged.from_nested_row_splits(params_dense_values, params_nested_splits)`\\n   provides the values that should be gathered.\\n* `indices` ia a dense tensor with dtype `int32` or `int64`, indicating which\\n   values should be gathered.\\n* `output =\\n   ragged.from_nested_row_splits(output_dense_values, output_nested_splits)`\\n   is the output tensor.\\n\\n(Note: This c++ op is used to implement the higher-level python\\n`tf.ragged.gather` op, which also supports ragged indices.)\",\n    \"operands\": [\n      { \"name\": \"params_nested_splits\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"params_dense_values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_nested_splits\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" },\n      { \"name\": \"output_dense_values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RaggedRange\",\n    \"summary\": \"Returns a `RaggedTensor` containing the specified sequences of numbers.\",\n    \"description\": \"Returns a `RaggedTensor` `result` composed from `rt_dense_values` and\\n`rt_nested_splits`, such that\\n`result[i] = range(starts[i], limits[i], deltas[i])`.\\n\\n```python\\n(rt_nested_splits, rt_dense_values) = ragged_range(\\n      starts=[2, 5, 8], limits=[3, 5, 12], deltas=1)\\nresult = tf.ragged.from_row_splits(rt_dense_values, rt_nested_splits)\\nprint(result)\\n<tf.RaggedTensor [[2], [], [8, 9, 10, 11]] >\\n```\\n\\nThe input tensors `starts`, `limits`, and `deltas` may be scalars or vectors.\\nThe vector inputs must all have the same size.  Scalar inputs are broadcast\\nto match the size of the vector inputs.\",\n    \"operands\": [\n      { \"name\": \"starts\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"limits\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"deltas\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"rt_nested_splits\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"rt_dense_values\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomGamma\",\n    \"summary\": \"Outputs random values from the Gamma distribution(s) described by alpha.\",\n    \"description\": \"This op uses the algorithm by Marsaglia et al. to acquire samples via\\ntransformation-rejection from pairs of uniform and normal random variables.\\nSee http://dl.acm.org/citation.cfm?id=358414\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"alpha\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomGammaGrad\",\n    \"summary\": \"Computes the derivative of a Gamma random sample w.r.t. `alpha`.\",\n    \"operands\": [\n      { \"name\": \"alpha\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"sample\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomPoisson\",\n    \"summary\": \"Use RandomPoissonV2 instead.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"rate\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Float64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomPoissonV2\",\n    \"summary\": \"Outputs random values from the Poisson distribution(s) described by rate.\",\n    \"description\": \"This op uses two algorithms, depending on rate. If rate >= 10, then\\nthe algorithm by Hormann is used to acquire samples via\\ntransformation-rejection.\\nSee http://www.sciencedirect.com/science/article/pii/0167668793909974.\\n\\nOtherwise, Knuth's algorithm is used to acquire samples via multiplying uniform\\nrandom variables.\\nSee Donald E. Knuth (1969). Seminumerical Algorithms. The Art of Computer\\nProgramming, Volume 2. Addison Wesley\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"rate\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomShuffle\",\n    \"summary\": \"Randomly shuffles a tensor along its first dimension.\",\n    \"description\": \"The tensor is shuffled along dimension 0, such that each `value[j]` is mapped\\n  to one and only one `output[i]`. For example, a mapping that might occur for a\\n  3x2 tensor is:\\n\\n```\\n[[1, 2],       [[5, 6],\\n [3, 4],  ==>   [1, 2],\\n [5, 6]]        [3, 4]]\\n```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomStandardNormal\",\n    \"summary\": \"Outputs random values from a normal distribution.\",\n    \"description\": \"The generated values will have mean 0 and standard deviation 1.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomUniform\",\n    \"summary\": \"Outputs random values from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[0, 1)`. The\\nlower bound 0 is included in the range, while the upper bound 1 is excluded.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RandomUniformInt\",\n    \"summary\": \"Outputs random integers from a uniform distribution.\",\n    \"description\": \"The generated values are uniform integers in the range `[minval, maxval)`.\\nThe lower bound `minval` is included in the range, while the upper bound\\n`maxval` is excluded.\\n\\nThe random integers are slightly biased unless `maxval - minval` is an exact\\npower of two.  The bias is small for values of `maxval - minval` significantly\\nsmaller than the range of the output (either `2^32` or `2^64`).\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"minval\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"maxval\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Range\",\n    \"summary\": \"Creates a sequence of numbers.\",\n    \"description\": \"This operation creates a sequence of numbers that begins at `start` and\\nextends by increments of `delta` up to but not including `limit`.\\n\\nFor example:\\n\\n```\\n# 'start' is 3\\n# 'limit' is 18\\n# 'delta' is 3\\ntf.range(start, limit, delta) ==> [3, 6, 9, 12, 15]\\n```\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64 ]>\" },\n      { \"name\": \"limit\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64 ]>\" },\n      { \"name\": \"delta\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RangeDataset\",\n    \"summary\": \"Creates a dataset with a range of values. Corresponds to python's xrange.\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"stop\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"replicate_on_split\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Rank\",\n    \"summary\": \"Returns the rank of a tensor.\",\n    \"description\": \"This operation returns an integer representing the rank of `input`.\\n\\nFor example:\\n\\n```\\n# 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]\\n# shape of tensor 't' is [2, 2, 3]\\nrank(t) ==> 3\\n```\\n\\n**Note**: The rank of a tensor is not the same as the rank of a matrix. The rank\\nof a tensor is the number of indices required to uniquely select each element\\nof the tensor. Rank is also known as \\\"order\\\", \\\"degree\\\", or \\\"ndims.\\\"\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReadFile\",\n    \"summary\": \"Reads and outputs the entire contents of the input filename.\",\n    \"operands\": [\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"contents\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReadVariableOp\",\n    \"summary\": \"Reads the value of a variable.\",\n    \"description\": \"The tensor returned by this operation is immutable.\\n\\nThe value returned by this operation is guaranteed to be influenced by all the\\nwrites on which this operation depends directly or indirectly, and to not be\\ninfluenced by any of the writes which depend directly or indirectly on this\\noperation.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Real\",\n    \"summary\": \"Returns the real part of a complex number.\",\n    \"description\": \"Given a tensor `input` of complex numbers, this operation returns a tensor of\\ntype `float` that is the real part of each element in `input`. All elements in\\n`input` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\), where *a* is the real\\n part returned by this operation and *b* is the imaginary part.\\n\\nFor example:\\n\\n```\\n# tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]\\ntf.real(input) ==> [-2.25, 3.25]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Complex128, TF_Complex64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RealDiv\",\n    \"summary\": \"Returns x / y element-wise for real types.\",\n    \"description\": \"If `x` and `y` are reals, this will return the floating-point division.\\n\\n*NOTE*: `Div` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Reciprocal\",\n    \"summary\": \"Computes the reciprocal of x element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = 1 / x\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReciprocalGrad\",\n    \"summary\": \"Computes the gradient for the inverse of `x` wrt its input.\",\n    \"description\": \"Specifically, `grad = -dy * y*y`, where `y = 1/x`, and `dy`\\nis the corresponding input gradient.\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"dy\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RecordEventMetricForTensor\",\n    \"summary\": \"Records an event to a streamz RecordEventMetric (i.e. distribution) for all the\",\n    \"description\": \"values of the input tensors. The streamz can be found at\\n/video/youtube/discovery/tensorflow/ops/streamz/events.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"label\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Recv\",\n    \"summary\": \"Receives the named tensor from send_device on recv_device.\",\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device_incarnation\", \"type\": \"I64Attr\" },\n      { \"name\": \"recv_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"client_terminated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RecvTPUEmbeddingActivations\",\n    \"summary\": \"An op that receives embedding activations on the TPU.\",\n    \"description\": \"The TPU system performs the embedding lookups and aggregations specified by\\nthe arguments to TPUEmbeddingEnqueue(Integer/Sparse/SparseTensor)Batch. The\\nresults of these aggregations are visible to the Tensorflow Graph as the\\noutputs of a RecvTPUEmbeddingActivations op. This op returns a list containing\\none Tensor of activations per table specified in the model. There can be at\\nmost one RecvTPUEmbeddingActivations op in the TPU graph.\",\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReduceDataset\",\n    \"summary\": \"Reduces the input dataset to a singleton using a reduce function.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"initial_state\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"Tstate\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"Targuments\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<0>]>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"use_inter_op_parallelism\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReduceJoin\",\n    \"summary\": \"Joins a string Tensor across the given dimensions.\",\n    \"description\": \"Computes the string join across dimensions in the given string Tensor of shape\\n`[\\\\\\\\(d_0, d_1, ..., d_{n-1}\\\\\\\\)]`.  Returns a new Tensor created by joining the input\\nstrings with the given separator (default: empty string).  Negative indices are\\ncounted backwards from the end, with `-1` being equivalent to `n - 1`.  If\\nindices are not specified, joins across all dimensions beginning from `n - 1`\\nthrough `0`.\\n\\nFor example:\\n\\n```python\\n# tensor `a` is [[\\\"a\\\", \\\"b\\\"], [\\\"c\\\", \\\"d\\\"]]\\ntf.reduce_join(a, 0) ==> [\\\"ac\\\", \\\"bd\\\"]\\ntf.reduce_join(a, 1) ==> [\\\"ab\\\", \\\"cd\\\"]\\ntf.reduce_join(a, -2) = tf.reduce_join(a, 0) ==> [\\\"ac\\\", \\\"bd\\\"]\\ntf.reduce_join(a, -1) = tf.reduce_join(a, 1) ==> [\\\"ab\\\", \\\"cd\\\"]\\ntf.reduce_join(a, 0, keep_dims=True) ==> [[\\\"ac\\\", \\\"bd\\\"]]\\ntf.reduce_join(a, 1, keep_dims=True) ==> [[\\\"ab\\\"], [\\\"cd\\\"]]\\ntf.reduce_join(a, 0, separator=\\\".\\\") ==> [\\\"a.c\\\", \\\"b.d\\\"]\\ntf.reduce_join(a, [0, 1]) ==> \\\"acbd\\\"\\ntf.reduce_join(a, [1, 0]) ==> \\\"abcd\\\"\\ntf.reduce_join(a, []) ==> [[\\\"a\\\", \\\"b\\\"], [\\\"c\\\", \\\"d\\\"]]\\ntf.reduce_join(a) = tf.reduce_join(a, [1, 0]) ==> \\\"abcd\\\"\\n```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"separator\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Relu\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes rectified linear: `max(features, 0)`.\",\n    \"description\": \"See: https://en.wikipedia.org/wiki/Rectifier_(neural_networks)\\nExample usage:\\n>>> tf.nn.relu([-2., 0., 3.]).numpy()\\narray([0., 0., 3.], dtype=float32)\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Relu6\",\n    \"summary\": \"Computes rectified linear 6: `min(max(features, 0), 6)`.\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Relu6Grad\",\n    \"summary\": \"Computes rectified linear 6 gradients for a Relu6 operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"features\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReluGrad\",\n    \"summary\": \"Computes rectified linear gradients for a Relu operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"features\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RemoteCall\",\n    \"summary\": \"Runs function `f` on a remote device indicated by `target`.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RepeatDataset\",\n    \"summary\": \"Creates a dataset that emits the outputs of `input_dataset` `count` times.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"count\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"Reshapes a tensor.\",\n    \"description\": \"Given `tensor`, this operation returns a tensor that has the same values\\nas `tensor` with shape `shape`.\\n\\nIf one component of 1-D tensor `shape` is the special value -1, the size of that\\ndimension is computed so that the total size remains constant.  In particular, a\\n`shape` of `[-1]` flattens into 1-D.  At most one component of `shape` may be\\nunknown.\\n\\nThe `shape` must be 1-D and the operation returns a tensor with shape\\n`shape` filled with the values of `tensor`. In this case, the number of elements\\nimplied by `shape` must be the same as the number of elements in `tensor`.\\n\\nIt is an error if `shape` is not 1-D.\\n\\nFor example:\\n\\n```\\n# tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9]\\n# tensor 't' has shape [9]\\nreshape(t, [3, 3]) ==> [[1, 2, 3],\\n                        [4, 5, 6],\\n                        [7, 8, 9]]\\n\\n# tensor 't' is [[[1, 1], [2, 2]],\\n#                [[3, 3], [4, 4]]]\\n# tensor 't' has shape [2, 2, 2]\\nreshape(t, [2, 4]) ==> [[1, 1, 2, 2],\\n                        [3, 3, 4, 4]]\\n\\n# tensor 't' is [[[1, 1, 1],\\n#                 [2, 2, 2]],\\n#                [[3, 3, 3],\\n#                 [4, 4, 4]],\\n#                [[5, 5, 5],\\n#                 [6, 6, 6]]]\\n# tensor 't' has shape [3, 2, 3]\\n# pass '[-1]' to flatten 't'\\nreshape(t, [-1]) ==> [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]\\n\\n# -1 can also be used to infer the shape\\n\\n# -1 is inferred to be 9:\\nreshape(t, [2, -1]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],\\n                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]\\n# -1 is inferred to be 2:\\nreshape(t, [-1, 9]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],\\n                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]\\n# -1 is inferred to be 3:\\nreshape(t, [ 2, -1, 3]) ==> [[[1, 1, 1],\\n                              [2, 2, 2],\\n                              [3, 3, 3]],\\n                             [[4, 4, 4],\\n                              [5, 5, 5],\\n                              [6, 6, 6]]]\\n\\n# tensor 't' is [7]\\n# shape `[]` reshapes to a scalar\\nreshape(t, []) ==> 7\\n```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResizeBilinear\",\n    \"summary\": \"Resize `images` to `size` using bilinear interpolation.\",\n    \"description\": \"Input images can be of different types but output images are always float.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint8 ]>\" },\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"resized_images\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"half_pixel_centers\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResizeBilinearGrad\",\n    \"summary\": \"Computes the gradient of bilinear interpolation.\",\n    \"operands\": [\n      { \"name\": \"grads\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"original_image\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"half_pixel_centers\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResizeNearestNeighbor\",\n    \"summary\": \"Resize `images` to `size` using nearest neighbor interpolation.\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint8 ]>\" },\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"resized_images\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"half_pixel_centers\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResizeNearestNeighborGrad\",\n    \"summary\": \"Computes the gradient of nearest neighbor interpolation.\",\n    \"operands\": [\n      { \"name\": \"grads\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int8, TF_Uint8 ]>\" },\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int8, TF_Uint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"half_pixel_centers\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAdadelta\",\n    \"summary\": \"Update '*var' according to the adadelta scheme.\",\n    \"description\": \"accum = rho() * accum + (1 - rho()) * grad.square();\\nupdate = (update_accum + epsilon).sqrt() * (accum + epsilon()).rsqrt() * grad;\\nupdate_accum = rho() * update_accum + (1 - rho()) * update.square();\\nvar -= update;\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum_update\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rho\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAdagrad\",\n    \"summary\": \"Update '*var' according to the adagrad scheme.\",\n    \"description\": \"accum += grad * grad\\nvar -= lr * grad * (1 / sqrt(accum))\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"update_slots\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAdagradDA\",\n    \"summary\": \"Update '*var' according to the proximal adagrad scheme.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"gradient_accumulator\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"gradient_squared_accumulator\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"global_step\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAdagradV2\",\n    \"summary\": \"Update '*var' according to the adagrad scheme.\",\n    \"description\": \"accum += grad * grad\\nvar -= lr * grad * (1 / (sqrt(accum) + epsilon))\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"update_slots\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAdam\",\n    \"summary\": \"Update '*var' according to the Adam algorithm.\",\n    \"description\": \"$$\\\\text{lr}_t := \\\\mathrm{lr} \\\\cdot \\\\frac{\\\\sqrt{1 - \\\\beta_2^t}}{1 - \\\\beta_1^t}$$\\n$$m_t := \\\\beta_1 \\\\cdot m_{t-1} + (1 - \\\\beta_1) \\\\cdot g$$\\n$$v_t := \\\\beta_2 \\\\cdot v_{t-1} + (1 - \\\\beta_2) \\\\cdot g^2$$\\n$$\\\\text{var} := \\\\begin{cases} \\\\text{var} - (m_t \\\\beta_1 + g \\\\cdot (1 - \\\\beta_1))\\\\cdot\\\\text{lr}_t/(\\\\sqrt{v_t} + \\\\epsilon), &\\\\text{if use_nesterov}\\\\\\\\\\\\\\\\  \\\\text{var} - m_t \\\\cdot \\\\text{lr}_t /(\\\\sqrt{v_t} + \\\\epsilon), &\\\\text{otherwise} \\\\end{cases}$$\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"m\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"v\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"beta1_power\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta2_power\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_nesterov\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAdaMax\",\n    \"summary\": \"Update '*var' according to the AdaMax algorithm.\",\n    \"description\": \"m_t <- beta1 * m_{t-1} + (1 - beta1) * g\\nv_t <- max(beta2 * v_{t-1}, abs(g))\\nvariable <- variable - learning_rate / (1 - beta1^t) * m_t / (v_t + epsilon)\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"m\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"v\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"beta1_power\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyAddSign\",\n    \"summary\": \"Update '*var' according to the AddSign update.\",\n    \"description\": \"m_t <- beta1 * m_{t-1} + (1 - beta1) * g\\nupdate <- (alpha + sign_decay * sign(g) *sign(m)) * g\\nvariable <- variable - lr_t * update\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"m\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"alpha\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"sign_decay\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyCenteredRMSProp\",\n    \"summary\": \"Update '*var' according to the centered RMSProp algorithm.\",\n    \"description\": \"The centered RMSProp algorithm uses an estimate of the centered second moment\\n(i.e., the variance) for normalization, as opposed to regular RMSProp, which\\nuses the (uncentered) second moment. This often helps with training, but is\\nslightly more expensive in terms of computation and memory.\\n\\nNote that in dense implementation of this algorithm, mg, ms, and mom will\\nupdate even if the grad is zero, but in this sparse implementation, mg, ms,\\nand mom will not update in iterations during which the grad is zero.\\n\\nmean_square = decay * mean_square + (1-decay) * gradient ** 2\\nmean_grad = decay * mean_grad + (1-decay) * gradient\\n\\nDelta = learning_rate * gradient / sqrt(mean_square + epsilon - mean_grad ** 2)\\n\\nmg <- rho * mg_{t-1} + (1-rho) * grad\\nms <- rho * ms_{t-1} + (1-rho) * grad * grad\\nmom <- momentum * mom_{t-1} + lr * grad / sqrt(ms - mg * mg + epsilon)\\nvar <- var - mom\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"mg\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rho\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"momentum\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyFtrl\",\n    \"summary\": \"Update '*var' according to the Ftrl-proximal scheme.\",\n    \"description\": \"accum_new = accum + grad * grad\\nlinear += grad - (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var\\nquadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2\\nvar = (sign(linear) * l1 - linear) / quadratic if |linear| > l1 else 0.0\\naccum = accum_new\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr_power\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"multiply_linear_by_lr\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyFtrlV2\",\n    \"summary\": \"Update '*var' according to the Ftrl-proximal scheme.\",\n    \"description\": \"accum_new = accum + grad * grad\\ngrad_with_shrinkage = grad + 2 * l2_shrinkage * var\\nlinear += grad_with_shrinkage +\\n    (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var\\nquadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2\\nvar = (sign(linear) * l1 - linear) / quadratic if |linear| > l1 else 0.0\\naccum = accum_new\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2_shrinkage\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr_power\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"multiply_linear_by_lr\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyGradientDescent\",\n    \"summary\": \"Update '*var' by subtracting 'alpha' * 'delta' from it.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"alpha\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"delta\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyKerasMomentum\",\n    \"summary\": \"Update '*var' according to the momentum scheme.\",\n    \"description\": \"Set use_nesterov = True if you want to use Nesterov momentum.\\n\\naccum = accum * momentum - lr * grad\\nvar += accum\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"momentum\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_nesterov\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyMomentum\",\n    \"summary\": \"Update '*var' according to the momentum scheme.\",\n    \"description\": \"Set use_nesterov = True if you want to use Nesterov momentum.\\n\\naccum = accum * momentum + grad\\nvar -= lr * accum\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"momentum\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_nesterov\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyPowerSign\",\n    \"summary\": \"Update '*var' according to the AddSign update.\",\n    \"description\": \"m_t <- beta1 * m_{t-1} + (1 - beta1) * g\\nupdate <- exp(logbase * sign_decay * sign(g) * sign(m_t)) * g\\nvariable <- variable - lr_t * update\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"m\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"logbase\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"sign_decay\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"beta\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyProximalAdagrad\",\n    \"summary\": \"Update '*var' and '*accum' according to FOBOS with Adagrad learning rate.\",\n    \"description\": \"accum += grad * grad\\nprox_v = var - lr * grad * (1 / sqrt(accum))\\nvar = sign(prox_v)/(1+lr*l2) * max{|prox_v|-lr*l1,0}\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyProximalGradientDescent\",\n    \"summary\": \"Update '*var' as FOBOS algorithm with fixed learning rate.\",\n    \"description\": \"prox_v = var - alpha * delta\\nvar = sign(prox_v)/(1+alpha*l2) * max{|prox_v|-alpha*l1,0}\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"alpha\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"delta\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceApplyRMSProp\",\n    \"summary\": \"Update '*var' according to the RMSProp algorithm.\",\n    \"description\": \"Note that in dense implementation of this algorithm, ms and mom will\\nupdate even if the grad is zero, but in this sparse implementation, ms\\nand mom will not update in iterations during which the grad is zero.\\n\\nmean_square = decay * mean_square + (1-decay) * gradient ** 2\\nDelta = learning_rate * gradient / sqrt(mean_square + epsilon)\\n\\nms <- rho * ms_{t-1} + (1-rho) * grad * grad\\nmom <- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)\\nvar <- var - mom\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rho\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"momentum\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceGather\",\n    \"summary\": \"Gather slices from the variable pointed to by `resource` according to `indices`.\",\n    \"description\": \"`indices` must be an integer tensor of any dimension (usually 0-D or 1-D).\\nProduces an output tensor with shape `indices.shape + params.shape[1:]` where:\\n\\n```python\\n    # Scalar indices\\n    output[:, ..., :] = params[indices, :, ... :]\\n\\n    # Vector indices\\n    output[i, :, ..., :] = params[indices[i], :, ... :]\\n\\n    # Higher rank indices\\n    output[i, ..., j, :, ... :] = params[indices[i, ..., j], :, ..., :]\\n```\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"validate_indices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceGatherNd\",\n    \"summary\": \"GatherNd on a resource.\",\n    \"description\": \"This op reads the variable referenced by the first argument, and\\nthen performs a GatherNd operation on it.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterAdd\",\n    \"summary\": \"Adds sparse updates to the variable referenced by `resource`.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] += updates[...]\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] += updates[i, ...]\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] += updates[i, ..., j, ...]\\n\\nDuplicate entries are handled correctly: if multiple `indices` reference\\nthe same location, their contributions add.\\n\\nRequires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape = []`.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterDiv\",\n    \"summary\": \"Divides sparse updates into the variable referenced by `resource`.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] /= updates[...]\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] /= updates[i, ...]\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] /= updates[i, ..., j, ...]\\n\\nDuplicate entries are handled correctly: if multiple `indices` reference\\nthe same location, their contributions multiply.\\n\\nRequires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape = []`.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterMax\",\n    \"summary\": \"Reduces sparse updates into the variable referenced by `resource` using the `max` operation.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] = max(ref[indices, ...], updates[...])\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] = max(ref[indices[i], ...], updates[i, ...])\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] = max(ref[indices[i, ..., j], ...], updates[i, ..., j, ...])\\n\\nDuplicate entries are handled correctly: if multiple `indices` reference\\nthe same location, their contributions are combined.\\n\\nRequires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape = []`.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterMin\",\n    \"summary\": \"Reduces sparse updates into the variable referenced by `resource` using the `min` operation.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] = min(ref[indices, ...], updates[...])\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] = min(ref[indices[i], ...], updates[i, ...])\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] = min(ref[indices[i, ..., j], ...], updates[i, ..., j, ...])\\n\\nDuplicate entries are handled correctly: if multiple `indices` reference\\nthe same location, their contributions are combined.\\n\\nRequires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape = []`.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterMul\",\n    \"summary\": \"Multiplies sparse updates into the variable referenced by `resource`.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] *= updates[...]\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] *= updates[i, ...]\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] *= updates[i, ..., j, ...]\\n\\nDuplicate entries are handled correctly: if multiple `indices` reference\\nthe same location, their contributions multiply.\\n\\nRequires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape = []`.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterNdAdd\",\n    \"summary\": \"Applies sparse addition to individual values or slices in a Variable.\",\n    \"description\": \"`ref` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`.\\n\\n`indices` must be integer tensor, containing indices into `ref`.\\nIt must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`.\\n\\nThe innermost dimension of `indices` (with length `K`) corresponds to\\nindices into elements (if `K = P`) or slices (if `K < P`) along the `K`th\\ndimension of `ref`.\\n\\n`updates` is `Tensor` of rank `Q-1+P-K` with shape:\\n\\n```\\n[d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]]\\n```\\n\\nFor example, say we want to add 4 scattered elements to a rank-1 tensor to\\n8 elements. In Python, that addition would look like this:\\n\\n```python\\nref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8], use_resource=True)\\nindices = tf.constant([[4], [3], [1], [7]])\\nupdates = tf.constant([9, 10, 11, 12])\\nadd = tf.scatter_nd_add(ref, indices, updates)\\nwith tf.Session() as sess:\\n  print sess.run(add)\\n```\\n\\nThe resulting update to ref would look like this:\\n\\n    [1, 13, 3, 14, 14, 6, 7, 20]\\n\\nSee `tf.scatter_nd` for more details about how to make updates to\\nslices.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterNdSub\",\n    \"summary\": \"Applies sparse subtraction to individual values or slices in a Variable.\",\n    \"description\": \"`ref` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`.\\n\\n`indices` must be integer tensor, containing indices into `ref`.\\nIt must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`.\\n\\nThe innermost dimension of `indices` (with length `K`) corresponds to\\nindices into elements (if `K = P`) or slices (if `K < P`) along the `K`th\\ndimension of `ref`.\\n\\n`updates` is `Tensor` of rank `Q-1+P-K` with shape:\\n\\n```\\n[d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]]\\n```\\n\\nFor example, say we want to subtract 4 scattered elements from a rank-1 tensor\\nwith 8 elements. In Python, that subtraction would look like this:\\n\\n```python\\nref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8], use_resource=True)\\nindices = tf.constant([[4], [3], [1], [7]])\\nupdates = tf.constant([9, 10, 11, 12])\\nsub = tf.scatter_nd_sub(ref, indices, updates)\\nwith tf.Session() as sess:\\n  print sess.run(sub)\\n```\\n\\nThe resulting update to ref would look like this:\\n\\n    [1, -9, 3, -6, -4, 6, 7, -4]\\n\\nSee `tf.scatter_nd` for more details about how to make updates to\\nslices.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterNdUpdate\",\n    \"summary\": \"Applies sparse `updates` to individual values or slices within a given\",\n    \"description\": \"variable according to `indices`.\\n\\n`ref` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`.\\n\\n`indices` must be integer tensor, containing indices into `ref`.\\nIt must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`.\\n\\nThe innermost dimension of `indices` (with length `K`) corresponds to\\nindices into elements (if `K = P`) or slices (if `K < P`) along the `K`th\\ndimension of `ref`.\\n\\n`updates` is `Tensor` of rank `Q-1+P-K` with shape:\\n\\n```\\n[d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].\\n```\\n\\nFor example, say we want to update 4 scattered elements to a rank-1 tensor to\\n8 elements. In Python, that update would look like this:\\n\\n```python\\n    ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])\\n    indices = tf.constant([[4], [3], [1] ,[7]])\\n    updates = tf.constant([9, 10, 11, 12])\\n    update = tf.scatter_nd_update(ref, indices, updates)\\n    with tf.Session() as sess:\\n      print sess.run(update)\\n```\\n\\nThe resulting update to ref would look like this:\\n\\n    [1, 11, 3, 10, 9, 6, 7, 12]\\n\\nSee `tf.scatter_nd` for more details about how to make updates to\\nslices.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterSub\",\n    \"summary\": \"Subtracts sparse updates from the variable referenced by `resource`.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] -= updates[...]\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] -= updates[i, ...]\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] -= updates[i, ..., j, ...]\\n\\nDuplicate entries are handled correctly: if multiple `indices` reference\\nthe same location, their contributions add.\\n\\nRequires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape = []`.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>\\n</div>\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceScatterUpdate\",\n    \"summary\": \"Assigns sparse updates to the variable referenced by `resource`.\",\n    \"description\": \"This operation computes\\n\\n    # Scalar indices\\n    ref[indices, ...] = updates[...]\\n\\n    # Vector indices (for each i)\\n    ref[indices[i], ...] = updates[i, ...]\\n\\n    # High rank indices (for each i, ..., j)\\n    ref[indices[i, ..., j], ...] = updates[i, ..., j, ...]\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceSparseApplyAdagrad\",\n    \"summary\": \"Update relevant entries in '*var' and '*accum' according to the adagrad scheme.\",\n    \"description\": \"That is for rows we have grad for, we update var and accum as follows:\\naccum += grad * grad\\nvar -= lr * grad * (1 / sqrt(accum))\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"update_slots\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceSparseApplyAdagradV2\",\n    \"summary\": \"Update relevant entries in '*var' and '*accum' according to the adagrad scheme.\",\n    \"description\": \"That is for rows we have grad for, we update var and accum as follows:\\naccum += grad * grad\\nvar -= lr * grad * (1 / sqrt(accum))\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"update_slots\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceSparseApplyFtrl\",\n    \"summary\": \"Update relevant entries in '*var' according to the Ftrl-proximal scheme.\",\n    \"description\": \"That is for rows we have grad for, we update var, accum and linear as follows:\\naccum_new = accum + grad * grad\\nlinear += grad - (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var\\nquadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2\\nvar = (sign(linear) * l1 - linear) / quadratic if |linear| > l1 else 0.0\\naccum = accum_new\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"accum\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"grad\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"lr\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l1\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"l2\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"lr_power\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"multiply_linear_by_lr\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ResourceStridedSliceAssign\",\n    \"summary\": \"Assign `value` to the sliced l-value reference of `ref`.\",\n    \"description\": \"The values of `value` are assigned to the positions in the variable\\n`ref` that are selected by the slice parameters. The slice parameters\\n`begin, `end`, `strides`, etc. work exactly as in `StridedSlice`.\\n\\nNOTE this op currently does not support broadcasting and so `value`'s\\nshape must be exactly the shape produced by the slice of `ref`.\",\n    \"operands\": [\n      { \"name\": \"ref\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"begin\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"end\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"end_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Restore\",\n    \"summary\": \"Restores a tensor from checkpoint files.\",\n    \"description\": \"Reads a tensor stored in one or several files. If there are several files (for\\ninstance because a tensor was saved as slices), `file_pattern` may contain\\nwildcard symbols (`*` and `?`) in the filename portion only, not in the\\ndirectory portion.\\n\\nIf a `file_pattern` matches several files, `preferred_shard` can be used to hint\\nin which file the requested tensor is likely to be found. This op will first\\nopen the file at index `preferred_shard` in the list of matching files and try\\nto restore tensors from that file.  Only if some tensors or tensor slices are\\nnot found in that first file, then the Op opens all the files. Setting\\n`preferred_shard` to match the value passed as the `shard` input\\nof a matching `Save` Op may speed up Restore.  This attribute only affects\\nperformance, not correctness.  The default value -1 means files are processed in\\norder.\\n\\nSee also `RestoreSlice`.\",\n    \"operands\": [\n      { \"name\": \"file_pattern\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_name\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"preferred_shard\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RestoreV2\",\n    \"summary\": \"Restores tensors from a V2 checkpoint.\",\n    \"description\": \"For backward compatibility with the V1 format, this Op currently allows\\nrestoring from a V1 checkpoint as well:\\n  - This Op first attempts to find the V2 index file pointed to by \\\"prefix\\\", and\\n    if found proceed to read it as a V2 checkpoint;\\n  - Otherwise the V1 read path is invoked.\\nRelying on this behavior is not recommended, as the ability to fall back to read\\nV1 might be deprecated and eventually removed.\\n\\nBy default, restores the named tensors in full.  If the caller wishes to restore\\nspecific slices of stored tensors, \\\"shape_and_slices\\\" should be non-empty\\nstrings and correspondingly well-formed.\\n\\nCallers must ensure all the named tensors are indeed stored in the checkpoint.\",\n    \"operands\": [\n      { \"name\": \"prefix\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"shape_and_slices\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingAdadeltaParameters\",\n    \"summary\": \"Retrieve Adadelta embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingAdadeltaParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingAdagradParameters\",\n    \"summary\": \"Retrieve Adagrad embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingAdagradParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingADAMParameters\",\n    \"summary\": \"Retrieve ADAM embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocities\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingADAMParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocities\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingCenteredRMSPropParameters\",\n    \"summary\": \"Retrieve centered RMSProp embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mg\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingFTRLParameters\",\n    \"summary\": \"Retrieve FTRL embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linears\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingFTRLParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linears\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingMDLAdagradLightParameters\",\n    \"summary\": \"Retrieve MDL Adagrad Light embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"benefits\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingMomentumParameters\",\n    \"summary\": \"Retrieve Momentum embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingMomentumParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingProximalAdagradParameters\",\n    \"summary\": \"Retrieve proximal Adagrad embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingProximalAdagradParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulators\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingProximalYogiParameters\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"v\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"m\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingProximalYogiParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"v\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"m\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingRMSPropParameters\",\n    \"summary\": \"Retrieve RMSProp embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingRMSPropParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"ms\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"mom\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingStochasticGradientDescentParameters\",\n    \"summary\": \"Retrieve SGD embedding parameters.\",\n    \"description\": \"An op that retrieves optimization parameters from embedding to host\\nmemory. Must be preceded by a ConfigureTPUEmbeddingHost op that sets up\\nthe correct embedding table configuration. For example, this op is\\nused to retrieve updated parameters before saving a checkpoint.\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RetrieveTPUEmbeddingStochasticGradientDescentParametersGradAccumDebug\",\n    \"results\": [\n      { \"name\": \"parameters\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"gradient_accumulators\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"table_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"num_shards\", \"type\": \"I64Attr\" },\n      { \"name\": \"shard_id\", \"type\": \"I64Attr\" },\n      { \"name\": \"config\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Reverse\",\n    \"summary\": \"Reverses specific dimensions of a tensor.\",\n    \"description\": \"Given a `tensor`, and a `bool` tensor `dims` representing the dimensions\\nof `tensor`, this operation reverses each dimension i of `tensor` where\\n`dims[i]` is `True`.\\n\\n`tensor` can have up to 8 dimensions. The number of dimensions\\nof `tensor` must equal the number of elements in `dims`. In other words:\\n\\n`rank(tensor) = size(dims)`\\n\\nFor example:\\n\\n```\\n# tensor 't' is [[[[ 0,  1,  2,  3],\\n#                  [ 4,  5,  6,  7],\\n#                  [ 8,  9, 10, 11]],\\n#                 [[12, 13, 14, 15],\\n#                  [16, 17, 18, 19],\\n#                  [20, 21, 22, 23]]]]\\n# tensor 't' shape is [1, 2, 3, 4]\\n\\n# 'dims' is [False, False, False, True]\\nreverse(t, dims) ==> [[[[ 3,  2,  1,  0],\\n                        [ 7,  6,  5,  4],\\n                        [ 11, 10, 9, 8]],\\n                       [[15, 14, 13, 12],\\n                        [19, 18, 17, 16],\\n                        [23, 22, 21, 20]]]]\\n\\n# 'dims' is [False, True, False, False]\\nreverse(t, dims) ==> [[[[12, 13, 14, 15],\\n                        [16, 17, 18, 19],\\n                        [20, 21, 22, 23]\\n                       [[ 0,  1,  2,  3],\\n                        [ 4,  5,  6,  7],\\n                        [ 8,  9, 10, 11]]]]\\n\\n# 'dims' is [False, False, True, False]\\nreverse(t, dims) ==> [[[[8, 9, 10, 11],\\n                        [4, 5, 6, 7],\\n                        [0, 1, 2, 3]]\\n                       [[20, 21, 22, 23],\\n                        [16, 17, 18, 19],\\n                        [12, 13, 14, 15]]]]\\n```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Str, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"dims\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Str, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReverseSequence\",\n    \"summary\": \"Reverses variable length slices.\",\n    \"description\": \"This op first slices `input` along the dimension `batch_dim`, and for each\\nslice `i`, reverses the first `seq_lengths[i]` elements along\\nthe dimension `seq_dim`.\\n\\nThe elements of `seq_lengths` must obey `seq_lengths[i] <= input.dims[seq_dim]`,\\nand `seq_lengths` must be a vector of length `input.dims[batch_dim]`.\\n\\nThe output slice `i` along dimension `batch_dim` is then given by input\\nslice `i`, with the first `seq_lengths[i]` slices along dimension\\n`seq_dim` reversed.\\n\\nFor example:\\n\\n```\\n# Given this:\\nbatch_dim = 0\\nseq_dim = 1\\ninput.dims = (4, 8, ...)\\nseq_lengths = [7, 2, 3, 5]\\n\\n# then slices of input are reversed on seq_dim, but only up to seq_lengths:\\noutput[0, 0:7, :, ...] = input[0, 7:0:-1, :, ...]\\noutput[1, 0:2, :, ...] = input[1, 2:0:-1, :, ...]\\noutput[2, 0:3, :, ...] = input[2, 3:0:-1, :, ...]\\noutput[3, 0:5, :, ...] = input[3, 5:0:-1, :, ...]\\n\\n# while entries past seq_lens are copied through:\\noutput[0, 7:, :, ...] = input[0, 7:, :, ...]\\noutput[1, 2:, :, ...] = input[1, 2:, :, ...]\\noutput[2, 3:, :, ...] = input[2, 3:, :, ...]\\noutput[3, 2:, :, ...] = input[3, 2:, :, ...]\\n```\\n\\nIn contrast, if:\\n\\n```\\n# Given this:\\nbatch_dim = 2\\nseq_dim = 0\\ninput.dims = (8, ?, 4, ...)\\nseq_lengths = [7, 2, 3, 5]\\n\\n# then slices of input are reversed on seq_dim, but only up to seq_lengths:\\noutput[0:7, :, 0, :, ...] = input[7:0:-1, :, 0, :, ...]\\noutput[0:2, :, 1, :, ...] = input[2:0:-1, :, 1, :, ...]\\noutput[0:3, :, 2, :, ...] = input[3:0:-1, :, 2, :, ...]\\noutput[0:5, :, 3, :, ...] = input[5:0:-1, :, 3, :, ...]\\n\\n# while entries past seq_lens are copied through:\\noutput[7:, :, 0, :, ...] = input[7:, :, 0, :, ...]\\noutput[2:, :, 1, :, ...] = input[2:, :, 1, :, ...]\\noutput[3:, :, 2, :, ...] = input[3:, :, 2, :, ...]\\noutput[2:, :, 3, :, ...] = input[2:, :, 3, :, ...]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"seq_lengths\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seq_dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"batch_dim\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ReverseV2\",\n    \"summary\": \"Reverses specific dimensions of a tensor.\",\n    \"description\": \"Given a `tensor`, and a `int32` tensor `axis` representing the set of\\ndimensions of `tensor` to reverse. This operation reverses each dimension\\n`i` for which there exists `j` s.t. `axis[j] == i`.\\n\\n`tensor` can have up to 8 dimensions. The number of dimensions specified\\nin `axis` may be 0 or more entries. If an index is specified more than\\nonce, a InvalidArgument error is raised.\\n\\nFor example:\\n\\n```\\n# tensor 't' is [[[[ 0,  1,  2,  3],\\n#                  [ 4,  5,  6,  7],\\n#                  [ 8,  9, 10, 11]],\\n#                 [[12, 13, 14, 15],\\n#                  [16, 17, 18, 19],\\n#                  [20, 21, 22, 23]]]]\\n# tensor 't' shape is [1, 2, 3, 4]\\n\\n# 'dims' is [3] or 'dims' is [-1]\\nreverse(t, dims) ==> [[[[ 3,  2,  1,  0],\\n                        [ 7,  6,  5,  4],\\n                        [ 11, 10, 9, 8]],\\n                       [[15, 14, 13, 12],\\n                        [19, 18, 17, 16],\\n                        [23, 22, 21, 20]]]]\\n\\n# 'dims' is '[1]' (or 'dims' is '[-3]')\\nreverse(t, dims) ==> [[[[12, 13, 14, 15],\\n                        [16, 17, 18, 19],\\n                        [20, 21, 22, 23]\\n                       [[ 0,  1,  2,  3],\\n                        [ 4,  5,  6,  7],\\n                        [ 8,  9, 10, 11]]]]\\n\\n# 'dims' is '[2]' (or 'dims' is '[-2]')\\nreverse(t, dims) ==> [[[[8, 9, 10, 11],\\n                        [4, 5, 6, 7],\\n                        [0, 1, 2, 3]]\\n                       [[20, 21, 22, 23],\\n                        [16, 17, 18, 19],\\n                        [12, 13, 14, 15]]]]\\n```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Str, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Str, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RFFT\",\n    \"summary\": \"Real-valued fast Fourier transform.\",\n    \"description\": \"Computes the 1-dimensional discrete Fourier transform of a real-valued signal\\nover the inner-most dimension of `input`.\\n\\nSince the DFT of a real signal is Hermitian-symmetric, `RFFT` only returns the\\n`fft_length / 2 + 1` unique components of the FFT: the zero-frequency term,\\nfollowed by the `fft_length / 2` positive-frequency terms.\\n\\nAlong the axis `RFFT` is computed on, if `fft_length` is smaller than the\\ncorresponding dimension of `input`, the dimension is cropped. If it is larger,\\nthe dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"fft_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RFFT2D\",\n    \"summary\": \"2D real-valued fast Fourier transform.\",\n    \"description\": \"Computes the 2-dimensional discrete Fourier transform of a real-valued signal\\nover the inner-most 2 dimensions of `input`.\\n\\nSince the DFT of a real signal is Hermitian-symmetric, `RFFT2D` only returns the\\n`fft_length / 2 + 1` unique components of the FFT for the inner-most dimension\\nof `output`: the zero-frequency term, followed by the `fft_length / 2`\\npositive-frequency terms.\\n\\nAlong each axis `RFFT2D` is computed on, if `fft_length` is smaller than the\\ncorresponding dimension of `input`, the dimension is cropped. If it is larger,\\nthe dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"fft_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RFFT3D\",\n    \"summary\": \"3D real-valued fast Fourier transform.\",\n    \"description\": \"Computes the 3-dimensional discrete Fourier transform of a real-valued signal\\nover the inner-most 3 dimensions of `input`.\\n\\nSince the DFT of a real signal is Hermitian-symmetric, `RFFT3D` only returns the\\n`fft_length / 2 + 1` unique components of the FFT for the inner-most dimension\\nof `output`: the zero-frequency term, followed by the `fft_length / 2`\\npositive-frequency terms.\\n\\nAlong each axis `RFFT3D` is computed on, if `fft_length` is smaller than the\\ncorresponding dimension of `input`, the dimension is cropped. If it is larger,\\nthe dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"fft_length\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RGBToHSV\",\n    \"summary\": \"Converts one or more images from RGB to HSV.\",\n    \"description\": \"Outputs a tensor of the same shape as the `images` tensor, containing the HSV\\nvalue of the pixels. The output is only well defined if the value in `images`\\nare in `[0,1]`.\\n\\n`output[..., 0]` contains hue, `output[..., 1]` contains saturation, and\\n`output[..., 2]` contains value. All HSV values are in `[0,1]`. A hue of 0\\ncorresponds to pure red, hue 1/3 is pure green, and 2/3 is pure blue.\\n\\nUsage Example:\\n\\n>>> blue_image = tf.stack([\\n...    tf.zeros([5,5]),\\n...    tf.zeros([5,5]),\\n...    tf.ones([5,5])],\\n...    axis=-1)\\n>>> blue_hsv_image = tf.image.rgb_to_hsv(blue_image)\\n>>> blue_hsv_image[0,0].numpy()\\narray([0.6666667, 1. , 1. ], dtype=float32)\",\n    \"operands\": [\n      { \"name\": \"images\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RightShift\",\n    \"summary\": \"Elementwise computes the bitwise right-shift of `x` and `y`.\",\n    \"description\": \"Performs a logical shift for unsigned integer types, and an arithmetic shift\\nfor signed integer types.\\n\\nIf `y` is negative, or greater than or equal to than the width of `x` in bits\\nthe result is implementation defined.\\n\\nExample:\\n\\n```python\\nimport tensorflow as tf\\nfrom tensorflow.python.ops import bitwise_ops\\nimport numpy as np\\ndtype_list = [tf.int8, tf.int16, tf.int32, tf.int64]\\n\\nfor dtype in dtype_list:\\n  lhs = tf.constant([-1, -5, -3, -14], dtype=dtype)\\n  rhs = tf.constant([5, 0, 7, 11], dtype=dtype)\\n\\n  right_shift_result = bitwise_ops.right_shift(lhs, rhs)\\n\\n  print(right_shift_result)\\n\\n# This will print:\\n# tf.Tensor([-1 -5 -1 -1], shape=(4,), dtype=int8)\\n# tf.Tensor([-1 -5 -1 -1], shape=(4,), dtype=int16)\\n# tf.Tensor([-1 -5 -1 -1], shape=(4,), dtype=int32)\\n# tf.Tensor([-1 -5 -1 -1], shape=(4,), dtype=int64)\\n\\nlhs = np.array([-2, 64, 101, 32], dtype=np.int8)\\nrhs = np.array([-1, -5, -3, -14], dtype=np.int8)\\nbitwise_ops.right_shift(lhs, rhs)\\n# <tf.Tensor: shape=(4,), dtype=int8, numpy=array([ -2,  64, 101,  32], dtype=int8)>\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_IntTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Rint\",\n    \"summary\": \"Returns element-wise integer closest to x.\",\n    \"description\": \"If the result is midway between two representable values,\\nthe even representable is chosen.\\nFor example:\\n\\n```\\nrint(-1.5) ==> -2.0\\nrint(0.5000001) ==> 1.0\\nrint([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) ==> [-2., -2., -0., 0., 2., 2., 2.]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RiscAdd\",\n    \"summary\": \"Returns x + y element-wise.\",\n    \"description\": \"*NOTE*: `RiscAdd` does not supports broadcasting.\\n\\nGiven two input tensors, the `tf.risc_add` operation computes the sum for every element in the tensor.\\n\\nBoth input and output have a range `(-inf, inf)`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RiscDot\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"b\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RngReadAndSkip\",\n    \"summary\": \"Advance the counter of a counter-based RNG.\",\n    \"description\": \"The state of the RNG after\\n`rng_read_and_skip(n)` will be the same as that after `uniform([n])`\\n(or any other distribution). The actual increment added to the\\ncounter is an unspecified implementation choice.\\n\\nIn the case that the input algorithm is RNG_ALG_AUTO_SELECT, the counter in the state needs to be of size int64[2], the current maximal counter size among algorithms. In this case, this op will manage the counter as if it is an 128-bit integer with layout [lower_64bits, higher_64bits]. If an algorithm needs less than 128 bits for the counter, it should use the left portion of the int64[2]. In this way, the int64[2] is compatible with all current RNG algorithms (Philox, ThreeFry and xla::RandomAlgorithm::RNG_DEFAULT). Downstream RNG ops can thus use this counter with any RNG algorithm.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"delta\", \"type\": \"TF_Uint64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Roll\",\n    \"summary\": \"Rolls the elements of a tensor along an axis.\",\n    \"description\": \"The elements are shifted positively (towards larger indices) by the offset of\\n`shift` along the dimension of `axis`. Negative `shift` values will shift\\nelements in the opposite direction. Elements that roll passed the last position\\nwill wrap around to the first and vice versa. Multiple shifts along multiple\\naxes may be specified.\\n\\nFor example:\\n\\n```\\n# 't' is [0, 1, 2, 3, 4]\\nroll(t, shift=2, axis=0) ==> [3, 4, 0, 1, 2]\\n\\n# shifting along multiple dimensions\\n# 't' is [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]\\nroll(t, shift=[1, -2], axis=[0, 1]) ==> [[7, 8, 9, 5, 6], [2, 3, 4, 0, 1]]\\n\\n# shifting along the same axis multiple times\\n# 't' is [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]\\nroll(t, shift=[2, -3], axis=[1, 1]) ==> [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"shift\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Round\",\n    \"summary\": \"Rounds the values of a tensor to the nearest integer, element-wise.\",\n    \"description\": \"Rounds half to even.  Also known as bankers rounding. If you want to round\\naccording to the current system rounding mode use std::cint.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Rsqrt\",\n    \"summary\": \"Computes reciprocal of square root of x element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = 1 / \\\\sqrt{x}\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.RsqrtGrad\",\n    \"summary\": \"Computes the gradient for the rsqrt of `x` wrt its input.\",\n    \"description\": \"Specifically, `grad = dy * -0.5 * y^3`, where `y = rsqrt(x)`, and `dy`\\nis the corresponding input gradient.\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"dy\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Save\",\n    \"summary\": \"Saves the input tensors to disk.\",\n    \"description\": \"The size of `tensor_names` must match the number of tensors in `data`. `data[i]`\\nis written to `filename` with name `tensor_names[i]`.\\n\\nSee also `SaveSlices`.\",\n    \"operands\": [\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"data\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SaveSlices\",\n    \"summary\": \"Saves input tensors slices to disk.\",\n    \"description\": \"This is like `Save` except that tensors can be listed in the saved file as being\\na slice of a larger tensor.  `shapes_and_slices` specifies the shape of the\\nlarger tensor and the slice that this tensor covers. `shapes_and_slices` must\\nhave as many elements as `tensor_names`.\\n\\nElements of the `shapes_and_slices` input must either be:\\n\\n*  The empty string, in which case the corresponding tensor is\\n   saved normally.\\n*  A string of the form `dim0 dim1 ... dimN-1 slice-spec` where the\\n   `dimI` are the dimensions of the larger tensor and `slice-spec`\\n   specifies what part is covered by the tensor to save.\\n\\n`slice-spec` itself is a `:`-separated list: `slice0:slice1:...:sliceN-1`\\nwhere each `sliceI` is either:\\n\\n*  The string `-` meaning that the slice covers all indices of this dimension\\n*  `start,length` where `start` and `length` are integers.  In that\\n   case the slice covers `length` indices starting at `start`.\\n\\nSee also `Save`.\",\n    \"operands\": [\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"shapes_and_slices\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"data\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SaveV2\",\n    \"summary\": \"Saves tensors in V2 checkpoint format.\",\n    \"description\": \"By default, saves the named tensors in full.  If the caller wishes to save\\nspecific slices of full tensors, \\\"shape_and_slices\\\" should be non-empty strings\\nand correspondingly well-formed.\",\n    \"operands\": [\n      { \"name\": \"prefix\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor_names\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"shape_and_slices\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ScatterNd\",\n    \"summary\": \"Scatters `updates` into a tensor of shape `shape` according to `indices`.\",\n    \"description\": \"Scatter sparse `updates` according to individual values at the specified\\n`indices`. This op returns an output tensor with the `shape` you specify. This\\nop is the inverse of the `tf.gather_nd` operator which extracts values or slices\\nfrom a given tensor.\\n\\nThis operation is similar to `tf.tensor_scatter_nd_add`, except that the tensor\\nis zero-initialized. Calling `tf.scatter_nd(indices, updates, shape)`\\nis identical to calling\\n`tf.tensor_scatter_nd_add(tf.zeros(shape, updates.dtype), indices, updates)`\\n\\nIf `indices` contains duplicates, the associated `updates` are accumulated\\n(summed) into the output tensor.\\n\\n**WARNING**: For floating-point data types, the output may be nondeterministic.\\nThis is because the order in which the updates are applied is nondeterministic\\nand when floating-point numbers are added in different orders the resulting\\nnumerical approximation error can be slightly different. However, the output\\nwill be deterministic if op determinism is enabled via\\n`tf.config.experimental.enable_op_determinism`.\\n\\n`indices` is an integer tensor containing indices into the output tensor. The\\nlast dimension of `indices` can be at most the rank of `shape`:\\n\\n    indices.shape[-1] <= shape.rank\\n\\nThe last dimension of `indices` corresponds to indices of elements\\n(if `indices.shape[-1] = shape.rank`) or slices\\n(if `indices.shape[-1] < shape.rank`) along dimension `indices.shape[-1]` of\\n`shape`.\\n\\n`updates` is a tensor with shape:\\n\\n    indices.shape[:-1] + shape[indices.shape[-1]:]\\n\\nThe simplest form of the scatter op is to insert individual elements in\\na tensor by index. Consider an example where you want to insert 4 scattered\\nelements in a rank-1 tensor with 8 elements.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/ScatterNd1.png\\\" alt>\\n</div>\\n\\nIn Python, this scatter operation would look like this:\\n\\n```python\\n    indices = tf.constant([[4], [3], [1], [7]])\\n    updates = tf.constant([9, 10, 11, 12])\\n    shape = tf.constant([8])\\n    scatter = tf.scatter_nd(indices, updates, shape)\\n    print(scatter)\\n```\\n\\nThe resulting tensor would look like this:\\n\\n    [0, 11, 0, 10, 9, 0, 0, 12]\\n\\nYou can also insert entire slices of a higher rank tensor all at once. For\\nexample, you can insert two slices in the first dimension of a rank-3 tensor\\nwith two matrices of new values.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/ScatterNd2.png\\\" alt>\\n</div>\\n\\nIn Python, this scatter operation would look like this:\\n\\n```python\\n    indices = tf.constant([[1], [3]])\\n    updates = tf.constant([[[5, 5, 5, 5], [6, 6, 6, 6],\\n                            [7, 7, 7, 7], [8, 8, 8, 8]],\\n                           [[5, 5, 5, 5], [6, 6, 6, 6],\\n                            [7, 7, 7, 7], [8, 8, 8, 8]]])\\n    shape = tf.constant([4, 4, 4])\\n    scatter = tf.scatter_nd(indices, updates, shape)\\n    print(scatter)\\n```\\n\\nThe resulting tensor would look like this:\\n\\n    [[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],\\n     [[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],\\n     [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],\\n     [[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]]]\\n\\nIf `indices` contains any out-of-bound indices, depending on\\n`bad_indices_policy`, the op will either return an error or ignore the\\nout-of-bound indices. `bad_indices_policy` can be one of the following values:\\n1. \\\"\\\" or \\\"DEFAULT\\\": raises on CPU and ignore on GPU. This is because\\n   historically on CPU and GPU we handle errors in different ways, and for\\n   backward compatibility we keep the default behavior.\\n2. \\\"ERROR\\\": raises error; GPU does not support this value.\\n3. \\\"IGNORE\\\": ignore the bad indices; supported on both CPU and GPU.\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentMax\",\n    \"summary\": \"Computes the maximum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\max_j(data_j)\\\\\\\\) where `max` is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the max is empty for a given segment ID `i`, `output[i] = 0`.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as the same as a smaller following index.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/SegmentMax.png\\\" alt>\\n</div>\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> tf.math.segment_max(c, tf.constant([0, 0, 1])).numpy()\\narray([[4, 3, 3, 4],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentMaxV2\",\n    \"summary\": \"Computes the maximum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\max_j(data_j)\\\\\\\\) where `max` is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the maximum is empty for a given segment ID `i`, it outputs the smallest\\npossible value for the specific numeric type,\\n`output[i] = numeric_limits<T>::lowest()`.\\n\\nNote: That this op is currently only supported with jit_compile=True.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as the same as a smaller following index.\\n\\nThe only difference with SegmentMax is the additional input  `num_segments`.\\nThis helps in evaluating the output shape in compile time.\\n`num_segments` should be consistent with segment_ids.\\ne.g. Max(segment_ids) should be equal to `num_segments` - 1 for a 1-d segment_ids\\nWith inconsistent num_segments, the op still runs. only difference is,\\nthe output takes the size of num_segments irrespective of size of segment_ids and data.\\nfor num_segments less than expected output size, the last elements are ignored\\nfor num_segments more than the expected output size, last elements are assigned \\nsmallest possible value for the specific numeric type.\\n\\nFor example:\\n\\n>>> @tf.function(jit_compile=True)\\n... def test(c):\\n...   return tf.raw_ops.SegmentMaxV2(data=c, segment_ids=tf.constant([0, 0, 1]), num_segments=2)\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> test(c).numpy()\\narray([[4, 3, 3, 4],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentMean\",\n    \"summary\": \"Computes the mean along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\frac{\\\\sum_j data_j}{N}\\\\\\\\) where `mean` is\\nover `j` such that `segment_ids[j] == i` and `N` is the total number of\\nvalues summed.\\n\\nIf the mean is empty for a given segment ID `i`, `output[i] = 0`.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as a smaller following index when computing the numerator\\nof the mean.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/SegmentMean.png\\\" alt>\\n</div>\\n\\nFor example:\\n\\n>>> c = tf.constant([[1.0,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> tf.math.segment_mean(c, tf.constant([0, 0, 1])).numpy()\\narray([[2.5, 2.5, 2.5, 2.5],\\n       [5., 6., 7., 8.]], dtype=float32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentMin\",\n    \"summary\": \"Computes the minimum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\min_j(data_j)\\\\\\\\) where `min` is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the min is empty for a given segment ID `i`, `output[i] = 0`.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as the same as a smaller following index.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/SegmentMin.png\\\" alt>\\n</div>\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> tf.math.segment_min(c, tf.constant([0, 0, 1])).numpy()\\narray([[1, 2, 2, 1],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentMinV2\",\n    \"summary\": \"Computes the minimum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\min_j(data_j)\\\\\\\\) where `min` is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the minimum is empty for a given segment ID `i`, it outputs the largest\\npossible value for the specific numeric type,\\n`output[i] = numeric_limits<T>::max()`.\\n\\nNote: That this op is currently only supported with jit_compile=True.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as the same as a smaller following index.\\n\\nThe only difference with SegmentMin is the additional input  `num_segments`.\\nThis helps in evaluating the output shape in compile time.\\n`num_segments` should be consistent with segment_ids.\\ne.g. Max(segment_ids) should be equal to `num_segments` - 1 for a 1-d segment_ids\\nWith inconsistent num_segments, the op still runs. only difference is,\\nthe output takes the size of num_segments irrespective of size of segment_ids and data.\\nfor num_segments less than expected output size, the last elements are ignored\\nfor num_segments more than the expected output size, last elements are assigned \\nthe largest possible value for the specific numeric type.\\n\\nFor example:\\n\\n>>> @tf.function(jit_compile=True)\\n... def test(c):\\n...   return tf.raw_ops.SegmentMinV2(data=c, segment_ids=tf.constant([0, 0, 1]), num_segments=2)\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> test(c).numpy()\\narray([[1, 2, 2, 1],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentProd\",\n    \"summary\": \"Computes the product along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\prod_j data_j\\\\\\\\) where the product is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the product is empty for a given segment ID `i`, `output[i] = 1`.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as the same as a smaller following index.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/SegmentProd.png\\\" alt>\\n</div>\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> tf.math.segment_prod(c, tf.constant([0, 0, 1])).numpy()\\narray([[4, 6, 6, 4],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentProdV2\",\n    \"summary\": \"Computes the product along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\prod_j data_j\\\\\\\\) where the product is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the product is empty for a given segment ID `i`, `output[i] = 1`.\\n\\nNote: That this op is currently only supported with jit_compile=True.\\n\\nThe only difference with SegmentProd is the additional input  `num_segments`.\\nThis helps in evaluating the output shape in compile time.\\n`num_segments` should be consistent with segment_ids.\\ne.g. Max(segment_ids) - 1 should be equal to `num_segments` for a 1-d segment_ids\\nWith inconsistent num_segments, the op still runs. only difference is, \\nthe output takes the size of num_segments irrespective of size of segment_ids and data.\\nfor num_segments less than expected output size, the last elements are ignored\\nfor num_segments more than the expected output size, last elements are assigned 1.\\n\\nFor example:\\n\\n>>> @tf.function(jit_compile=True)\\n... def test(c):\\n...   return tf.raw_ops.SegmentProdV2(data=c, segment_ids=tf.constant([0, 0, 1]), num_segments=2)\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> test(c).numpy()\\narray([[4, 6, 6, 4],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentSum\",\n    \"summary\": \"Computes the sum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\sum_j data_j\\\\\\\\) where sum is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the sum is empty for a given segment ID `i`, `output[i] = 0`.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be sorted,\\nand an error is thrown for indices that are not increasing. On GPU, this\\ndoes not throw an error for unsorted indices. On GPU, out-of-order indices\\nresult in safe but unspecified behavior, which may include treating\\nout-of-order indices as the same as a smaller following index.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/SegmentSum.png\\\" alt>\\n</div>\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [4, 3, 2, 1], [5,6,7,8]])\\n>>> tf.math.segment_sum(c, tf.constant([0, 0, 1])).numpy()\\narray([[5, 5, 5, 5],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SegmentSumV2\",\n    \"summary\": \"Computes the sum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output_i = \\\\sum_j data_j\\\\\\\\) where sum is over `j` such\\nthat `segment_ids[j] == i`.\\n\\nIf the sum is empty for a given segment ID `i`, `output[i] = 0`.\\n\\nNote that this op is currently only supported with jit_compile=True.\\n</div>\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Select\",\n    \"summary\": \"Selects elements from `x` or `y`, depending on `condition`.\",\n    \"description\": \"The `x`, and `y` tensors must all have the same shape, and the\\noutput will also have that shape.\\n\\nThe `condition` tensor must be a scalar if `x` and `y` are scalars.\\nIf `x` and `y` are vectors or higher rank, then `condition` must be either a\\nscalar, a vector with size matching the first dimension of `x`, or must have\\nthe same shape as `x`.\\n\\nThe `condition` tensor acts as a mask that chooses, based on the value at each\\nelement, whether the corresponding element / row in the output should be\\ntaken from `x` (if true) or `y` (if false).\\n\\nIf `condition` is a vector and `x` and `y` are higher rank matrices, then\\nit chooses which row (outer dimension) to copy from `x` and `y`.\\nIf `condition` has the same shape as `x` and `y`, then it chooses which\\nelement to copy from `x` and `y`.\\n\\nFor example:\\n\\n```python\\n# 'condition' tensor is [[True,  False]\\n#                        [False, True]]\\n# 't' is [[1, 2],\\n#         [3, 4]]\\n# 'e' is [[5, 6],\\n#         [7, 8]]\\nselect(condition, t, e)  # => [[1, 6], [7, 4]]\\n\\n\\n# 'condition' tensor is [True, False]\\n# 't' is [[1, 2],\\n#         [3, 4]]\\n# 'e' is [[5, 6],\\n#         [7, 8]]\\nselect(condition, t, e) ==> [[1, 2],\\n                             [7, 8]]\\n\\n```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"then_value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"else_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SelectV2\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"then_value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"else_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SelfAdjointEigV2\",\n    \"summary\": \"Computes the eigen decomposition of one or more square self-adjoint matrices.\",\n    \"description\": \"Computes the eigenvalues and (optionally) eigenvectors of each inner matrix in\\n`input` such that `input[..., :, :] = v[..., :, :] * diag(e[..., :])`. The eigenvalues\\nare sorted in non-decreasing order.\\n\\n```python\\n# a is a tensor.\\n# e is a tensor of eigenvalues.\\n# v is a tensor of eigenvectors.\\ne, v = self_adjoint_eig(a)\\ne = self_adjoint_eig(a, compute_v=False)\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"e\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"v\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"compute_v\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Selu\",\n    \"summary\": \"Computes scaled exponential linear: `scale * alpha * (exp(features) - 1)`\",\n    \"description\": \"if < 0, `scale * features` otherwise.\\n\\nTo be used together with\\n`initializer = tf.variance_scaling_initializer(factor=1.0, mode='FAN_IN')`.\\nFor correct dropout, use `tf.contrib.nn.alpha_dropout`.\\n\\nSee [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515)\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SeluGrad\",\n    \"summary\": \"Computes gradients for the scaled exponential linear (Selu) operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"outputs\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Send\",\n    \"summary\": \"Sends the named tensor from send_device to recv_device.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_device_incarnation\", \"type\": \"I64Attr\" },\n      { \"name\": \"recv_device\", \"type\": \"StrAttr\" },\n      { \"name\": \"client_terminated\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SendTPUEmbeddingGradients\",\n    \"summary\": \"Performs gradient updates of embedding tables.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"learning_rates\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SerializeIterator\",\n    \"summary\": \"Converts the given `resource_handle` representing an iterator to a variant tensor.\",\n    \"operands\": [\n      { \"name\": \"resource_handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"serialized\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"external_state_policy\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SerializeSparse\",\n    \"summary\": \"Serialize a `SparseTensor` into a `[3]` `Tensor` object.\",\n    \"operands\": [\n      { \"name\": \"sparse_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"sparse_values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"sparse_shape\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"serialized_sparse\", \"type\": \"TensorOf<[TF_Str, TF_Variant]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SetStaticDimensionBounds\",\n    \"summary\": \"Op used to indicate to the compiler and runtime the static bounds of a tensor.\",\n    \"description\": \"The information passed through this op can possibly be used by the compiler and\\nruntime to perform certain optimizations such as more efficient DMAs. The\\nbounds passed via this op should be considered advisory only, and depending on\\nthe implementation, might do nothing and simply be an identity\\n\\n`input`: The tensor that has dynamic dimensions.\\n`static_shape`: The static shape of the tensor, corresponds to the maximum bounds of each dimension.\\n`output` is the input tensor with no changes done to it.\\n\\nExample usage:\\n\\ndef tpu_call(args):\\n  def model_fn(args):\\n    # do something with dynamic tensor\\n\\n  @function.Defun(capture_resource_var_by_value=False)\\n  def tpu_subgraph():\\n      return tf.tpu.rewrite(model_fn, args)\\n\\n  return tf.raw_ops.TPUPartitionedCall(\\n      args=tpu_subgraph.captured_inputs,\\n      Tout=[o.type for o in tpu_subgraph.definition.signature.output_arg],\\n      f=tpu_subgraph,\\n      device_ordinal=[0])\\n\\nstatic_shape = tf.placeholder(tf.int32, shape=([3]), name='static_size')\\n\\nw = tf.Variable(tf.constant([[1.0], [2.0], [3.0]]), name='w')\\n\\nw_dyn = tf.SetDynamicDimensionBounds(w, static_size])\\ntpu_call([w_dyn])\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"static_shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Shape\",\n    \"category\": \"Shape\",\n    \"summary\": \"Returns the shape of a tensor.\",\n    \"description\": \"This operation returns a 1-D integer tensor representing the shape of `input`.\\n\\nFor example:\\n\\n```\\n# 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]\\nshape(t) ==> [2, 2, 3]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use32Bit\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ShapeN\",\n    \"summary\": \"Returns shape of tensors.\",\n    \"description\": \"This operation returns N 1-D integer tensors representing shape of `input[i]s`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_I32OrI64Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ShardedFilename\",\n    \"summary\": \"Generate a sharded filename. The filename is printf formatted as\",\n    \"description\": \"%s-%05d-of-%05d, basename, shard, num_shards.\",\n    \"operands\": [\n      { \"name\": \"basename\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"shard\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"num_shards\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"filename\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ShuffleAndRepeatDatasetV2\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"buffer_size\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed2\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"count\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed_generator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reshuffle_each_iteration\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ShuffleDatasetV2\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"buffer_size\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed_generator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ShuffleDatasetV3\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"buffer_size\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed2\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"seed_generator\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reshuffle_each_iteration\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ShutdownDistributedTPU\",\n    \"summary\": \"Shuts down a running distributed TPU system.\",\n    \"description\": \"The op returns an error if no system is running.\"\n  },\n  {\n    \"name\": \"tf.ShutdownTPUSystem\",\n    \"summary\": \"An op that shuts down the TPU system.\",\n    \"results\": [\n      { \"name\": \"success\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sigmoid\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes sigmoid of `x` element-wise.\",\n    \"description\": \"Specifically, `y = 1 / (1 + exp(-x))`.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SigmoidGrad\",\n    \"summary\": \"Computes the gradient of the sigmoid of `x` wrt its input.\",\n    \"description\": \"Specifically, `grad = dy * y * (1 - y)`, where `y = sigmoid(x)`, and\\n`dy` is the corresponding input gradient.\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"dy\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sign\",\n    \"summary\": \"Returns an element-wise indication of the sign of a number.\",\n    \"description\": \"`y = sign(x) = -1` if `x < 0`; 0 if `x == 0`; 1 if `x > 0`.\\n\\nFor complex numbers, `y = sign(x) = x / |x|` if `x != 0`, otherwise `y = 0`.\\n\\nExample usage:\\n>>> tf.math.sign([0., 2., -3.])\\n<tf.Tensor: shape=(3,), dtype=float32, numpy=array([ 0.,  1., -1.], dtype=float32)>\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sin\",\n    \"summary\": \"Computes sine of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes sine of every\\n  element in the tensor. Input range is `(-inf, inf)` and\\n  output range is `[-1,1]`.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -9, -0.5, 1, 1.2, 200, 10, float(\\\"inf\\\")])\\n  tf.math.sin(x) ==> [nan -0.4121185 -0.47942555 0.84147096 0.9320391 -0.87329733 -0.54402107 nan]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sinh\",\n    \"summary\": \"Computes hyperbolic sine of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes hyperbolic sine of every\\n  element in the tensor. Input range is `[-inf,inf]` and output range\\n  is `[-inf,inf]`.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -9, -0.5, 1, 1.2, 2, 10, float(\\\"inf\\\")])\\n  tf.math.sinh(x) ==> [-inf -4.0515420e+03 -5.2109528e-01 1.1752012e+00 1.5094614e+00 3.6268604e+00 1.1013232e+04 inf]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Size\",\n    \"category\": \"Shape\",\n    \"summary\": \"Returns the size of a tensor.\",\n    \"description\": \"This operation returns an integer representing the number of elements in\\n`input`.\\n\\nFor example:\\n\\n```\\n# 't' is [[[1, 1,, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]]\\nsize(t) ==> 12\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Slice\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Return a slice from 'input'.\",\n    \"description\": \"The output tensor is a tensor with dimensions described by 'size'\\nwhose values are extracted from 'input' starting at the offsets in\\n'begin'.\\n\\n*Requirements*:\\n  0 <= begin[i] <= begin[i] + size[i] <= Di  for i in [0, n)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"begin\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"size\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Snapshot\",\n    \"summary\": \"Returns a copy of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Softmax\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes softmax activations.\",\n    \"description\": \"For each batch `i` and class `j` we have\\n\\n    $$softmax[i, j] = exp(logits[i, j]) / sum_j(exp(logits[i, j]))$$\",\n    \"operands\": [\n      { \"name\": \"logits\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"softmax\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SoftmaxCrossEntropyWithLogits\",\n    \"summary\": \"Computes softmax cross entropy cost and gradients to backpropagate.\",\n    \"description\": \"Inputs are the logits, not probabilities.\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"labels\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"loss\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"backprop\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Softplus\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SoftplusGrad\",\n    \"summary\": \"Computes softplus gradients for a softplus operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Softsign\",\n    \"summary\": \"Computes softsign: `features / (abs(features) + 1)`.\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SoftsignGrad\",\n    \"summary\": \"Computes softsign gradients for a softsign operation.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"backprops\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SortListOfSparseCoreCooTensors\",\n    \"summary\": \"An op which sorts each COO tensors in the list by which SparseCore the id will go to. This op should be used along with the ConvertToSparseCoreCsrWrappedCooTensorOp.\",\n    \"operands\": [\n      { \"name\": \"row_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"col_ids_list\", \"type\": \"Variadic<TF_Int32Tensor>\" },\n      { \"name\": \"gains_list\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sorted_row_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_col_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"id_counts\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count_list\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"col_offset_list\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"num_replica\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_vocab_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"feature_width\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_sc_per_chip\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SpaceToBatch\",\n    \"summary\": \"SpaceToBatch for 4-D tensors of type T.\",\n    \"description\": \"This is a legacy version of the more general SpaceToBatchND.\\n\\nZero-pads and then rearranges (permutes) blocks of spatial data into batch.\\nMore specifically, this op outputs a copy of the input tensor where values from\\nthe `height` and `width` dimensions are moved to the `batch` dimension. After\\nthe zero-padding, both `height` and `width` of the input must be divisible by the\\nblock size.\\n\\nThe attr `block_size` must be greater than one. It indicates the block size.\\n\\n  * Non-overlapping blocks of size `block_size x block size` in the height and\\n    width dimensions are rearranged into the batch dimension at each location.\\n  * The batch of the output tensor is `batch * block_size * block_size`.\\n  * Both height_pad and width_pad must be divisible by block_size.\\n\\nThe shape of the output will be:\\n\\n    [batch*block_size*block_size, height_pad/block_size, width_pad/block_size,\\n     depth]\\n\\nSome examples:\\n\\n(1) For the following input of shape `[1, 2, 2, 1]` and block_size of 2:\\n\\n```\\nx = [[[[1], [2]], [[3], [4]]]]\\n```\\n\\nThe output tensor has shape `[4, 1, 1, 1]` and value:\\n\\n```\\n[[[[1]]], [[[2]]], [[[3]]], [[[4]]]]\\n```\\n\\n(2) For the following input of shape `[1, 2, 2, 3]` and block_size of 2:\\n\\n```\\nx = [[[[1, 2, 3], [4, 5, 6]],\\n      [[7, 8, 9], [10, 11, 12]]]]\\n```\\n\\nThe output tensor has shape `[4, 1, 1, 3]` and value:\\n\\n```\\n[[[[1, 2, 3]]], [[[4, 5, 6]]], [[[7, 8, 9]]], [[[10, 11, 12]]]]\\n```\\n\\n(3) For the following input of shape `[1, 4, 4, 1]` and block_size of 2:\\n\\n```\\nx = [[[[1],   [2],  [3],  [4]],\\n      [[5],   [6],  [7],  [8]],\\n      [[9],  [10], [11],  [12]],\\n      [[13], [14], [15],  [16]]]]\\n```\\n\\nThe output tensor has shape `[4, 2, 2, 1]` and value:\\n\\n```\\nx = [[[[1], [3]], [[9], [11]]],\\n     [[[2], [4]], [[10], [12]]],\\n     [[[5], [7]], [[13], [15]]],\\n     [[[6], [8]], [[14], [16]]]]\\n```\\n\\n(4) For the following input of shape `[2, 2, 4, 1]` and block_size of 2:\\n\\n```\\nx = [[[[1],   [2],  [3],  [4]],\\n      [[5],   [6],  [7],  [8]]],\\n     [[[9],  [10], [11],  [12]],\\n      [[13], [14], [15],  [16]]]]\\n```\\n\\nThe output tensor has shape `[8, 1, 2, 1]` and value:\\n\\n```\\nx = [[[[1], [3]]], [[[9], [11]]], [[[2], [4]]], [[[10], [12]]],\\n     [[[5], [7]]], [[[13], [15]]], [[[6], [8]]], [[[14], [16]]]]\\n```\\n\\nAmong others, this operation is useful for reducing atrous convolution into\\nregular convolution.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<2>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SpaceToBatchND\",\n    \"summary\": \"SpaceToBatch for N-D tensors of type T.\",\n    \"description\": \"This operation divides \\\"spatial\\\" dimensions `[1, ..., M]` of the input into a\\ngrid of blocks of shape `block_shape`, and interleaves these blocks with the\\n\\\"batch\\\" dimension (0) such that in the output, the spatial dimensions\\n`[1, ..., M]` correspond to the position within the grid, and the batch\\ndimension combines both the position within a spatial block and the original\\nbatch position.  Prior to division into blocks, the spatial dimensions of the\\ninput are optionally zero padded according to `paddings`. See below for a\\nprecise description.\\n\\nThis operation is equivalent to the following steps:\\n\\n1. Zero-pad the start and end of dimensions `[1, ..., M]` of the\\n   input according to `paddings` to produce `padded` of shape `padded_shape`.\\n\\n2. Reshape `padded` to `reshaped_padded` of shape:\\n\\n     [batch] +\\n     [padded_shape[1] / block_shape[0],\\n       block_shape[0],\\n      ...,\\n      padded_shape[M] / block_shape[M-1],\\n      block_shape[M-1]] +\\n     remaining_shape\\n\\n3. Permute dimensions of `reshaped_padded` to produce\\n   `permuted_reshaped_padded` of shape:\\n\\n     block_shape +\\n     [batch] +\\n     [padded_shape[1] / block_shape[0],\\n      ...,\\n      padded_shape[M] / block_shape[M-1]] +\\n     remaining_shape\\n\\n4. Reshape `permuted_reshaped_padded` to flatten `block_shape` into the batch\\n   dimension, producing an output tensor of shape:\\n\\n     [batch * prod(block_shape)] +\\n     [padded_shape[1] / block_shape[0],\\n      ...,\\n      padded_shape[M] / block_shape[M-1]] +\\n     remaining_shape\\n\\nSome examples:\\n\\n(1) For the following input of shape `[1, 2, 2, 1]`, `block_shape = [2, 2]`, and\\n    `paddings = [[0, 0], [0, 0]]`:\\n\\n```\\nx = [[[[1], [2]], [[3], [4]]]]\\n```\\n\\nThe output tensor has shape `[4, 1, 1, 1]` and value:\\n\\n```\\n[[[[1]]], [[[2]]], [[[3]]], [[[4]]]]\\n```\\n\\n(2) For the following input of shape `[1, 2, 2, 3]`, `block_shape = [2, 2]`, and\\n    `paddings = [[0, 0], [0, 0]]`:\\n\\n```\\nx = [[[[1, 2, 3], [4, 5, 6]],\\n      [[7, 8, 9], [10, 11, 12]]]]\\n```\\n\\nThe output tensor has shape `[4, 1, 1, 3]` and value:\\n\\n```\\n[[[[1, 2, 3]]], [[[4, 5, 6]]], [[[7, 8, 9]]], [[[10, 11, 12]]]]\\n```\\n\\n(3) For the following input of shape `[1, 4, 4, 1]`, `block_shape = [2, 2]`, and\\n    `paddings = [[0, 0], [0, 0]]`:\\n\\n```\\nx = [[[[1],   [2],  [3],  [4]],\\n      [[5],   [6],  [7],  [8]],\\n      [[9],  [10], [11],  [12]],\\n      [[13], [14], [15],  [16]]]]\\n```\\n\\nThe output tensor has shape `[4, 2, 2, 1]` and value:\\n\\n```\\nx = [[[[1], [3]], [[9], [11]]],\\n     [[[2], [4]], [[10], [12]]],\\n     [[[5], [7]], [[13], [15]]],\\n     [[[6], [8]], [[14], [16]]]]\\n```\\n\\n(4) For the following input of shape `[2, 2, 4, 1]`, block_shape = `[2, 2]`, and\\n    paddings = `[[0, 0], [2, 0]]`:\\n\\n```\\nx = [[[[1],   [2],  [3],  [4]],\\n      [[5],   [6],  [7],  [8]]],\\n     [[[9],  [10], [11],  [12]],\\n      [[13], [14], [15],  [16]]]]\\n```\\n\\nThe output tensor has shape `[8, 1, 3, 1]` and value:\\n\\n```\\nx = [[[[0], [1], [3]]], [[[0], [9], [11]]],\\n     [[[0], [2], [4]]], [[[0], [10], [12]]],\\n     [[[0], [5], [7]]], [[[0], [13], [15]]],\\n     [[[0], [6], [8]]], [[[0], [14], [16]]]]\\n```\\n\\nAmong others, this operation is useful for reducing atrous convolution into\\nregular convolution.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"block_shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SpaceToDepth\",\n    \"summary\": \"SpaceToDepth for tensors of type T.\",\n    \"description\": \"Rearranges blocks of spatial data, into depth. More specifically,\\nthis op outputs a copy of the input tensor where values from the `height`\\nand `width` dimensions are moved to the `depth` dimension.\\nThe attr `block_size` indicates the input block size.\\n\\n  * Non-overlapping blocks of size `block_size x block size` are rearranged\\n    into depth at each location.\\n  * The depth of the output tensor is `block_size * block_size * input_depth`.\\n  * The Y, X coordinates within each block of the input become the high order\\n    component of the output channel index.\\n  * The input tensor's height and width must be divisible by block_size.\\n\\nThe `data_format` attr specifies the layout of the input and output tensors\\nwith the following options:\\n  \\\"NHWC\\\": `[ batch, height, width, channels ]`\\n  \\\"NCHW\\\": `[ batch, channels, height, width ]`\\n  \\\"NCHW_VECT_C\\\":\\n      `qint8 [ batch, channels / 4, height, width, 4 ]`\\n\\nIt is useful to consider the operation as transforming a 6-D Tensor.\\ne.g. for data_format = NHWC,\\n     Each element in the input tensor can be specified via 6 coordinates,\\n     ordered by decreasing memory layout significance as:\\n     n,oY,bY,oX,bX,iC  (where n=batch index, oX, oY means X or Y coordinates\\n                        within the output image, bX, bY means coordinates\\n                        within the input block, iC means input channels).\\n     The output would be a transpose to the following layout:\\n     n,oY,oX,bY,bX,iC\\n\\nThis operation is useful for resizing the activations between convolutions\\n(but keeping all data), e.g. instead of pooling. It is also useful for training\\npurely convolutional models.\\n\\nFor example, given an input of shape `[1, 2, 2, 1]`, data_format = \\\"NHWC\\\" and\\nblock_size = 2:\\n\\n```\\nx = [[[[1], [2]],\\n      [[3], [4]]]]\\n```\\n\\nThis operation will output a tensor of shape `[1, 1, 1, 4]`:\\n\\n```\\n[[[[1, 2, 3, 4]]]]\\n```\\n\\nHere, the input has a batch of 1 and each batch element has shape `[2, 2, 1]`,\\nthe corresponding output will have a single element (i.e. width and height are\\nboth 1) and will have a depth of 4 channels (1 * block_size * block_size).\\nThe output element shape is `[1, 1, 4]`.\\n\\nFor an input tensor with larger depth, here of shape `[1, 2, 2, 3]`, e.g.\\n\\n```\\nx = [[[[1, 2, 3], [4, 5, 6]],\\n      [[7, 8, 9], [10, 11, 12]]]]\\n```\\n\\nThis operation, for block_size of 2, will return the following tensor of shape\\n`[1, 1, 1, 12]`\\n\\n```\\n[[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]]\\n```\\n\\nSimilarly, for the following input of shape `[1 4 4 1]`, and a block size of 2:\\n\\n```\\nx = [[[[1],   [2],  [5],  [6]],\\n      [[3],   [4],  [7],  [8]],\\n      [[9],  [10], [13],  [14]],\\n      [[11], [12], [15],  [16]]]]\\n```\\n\\nthe operator will return the following tensor of shape `[1 2 2 4]`:\\n\\n```\\nx = [[[[1, 2, 3, 4],\\n       [5, 6, 7, 8]],\\n      [[9, 10, 11, 12],\\n       [13, 14, 15, 16]]]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<2>]>\" },\n      { \"name\": \"data_format\", \"type\": \"DefaultValuedOptionalAttr<TF_AnyStrAttrOf<[ NHWC, NCHW, NCHW_VECT_C ]>, \\\"NHWC\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseAdd\",\n    \"summary\": \"Adds two `SparseTensor` objects to produce another `SparseTensor`.\",\n    \"description\": \"The input `SparseTensor` objects' indices are assumed ordered in standard\\nlexicographic order.  If this is not the case, before this step run\\n`SparseReorder` to restore index ordering.\\n\\nBy default, if two values sum to zero at some index, the output `SparseTensor`\\nwould still include that particular location in its index, storing a zero in the\\ncorresponding value slot.  To override this, callers can specify `thresh`,\\nindicating that if the sum has a magnitude strictly smaller than `thresh`, its\\ncorresponding value and index would then not be included.  In particular,\\n`thresh == 0` (default) means everything is kept and actual thresholding happens\\nonly for a positive value.\\n\\nIn the following shapes, `nnz` is the count after taking `thresh` into account.\",\n    \"operands\": [\n      { \"name\": \"a_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"a_values\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"a_shape\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"b_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"b_values\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"b_shape\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"thresh\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"sum_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"sum_values\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"sum_shape\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseFillEmptyRows\",\n    \"summary\": \"Fills empty rows in the input 2-D `SparseTensor` with a default value.\",\n    \"description\": \"The input `SparseTensor` is represented via the tuple of inputs\\n(`indices`, `values`, `dense_shape`).  The output `SparseTensor` has the\\nsame `dense_shape` but with indices `output_indices` and values\\n`output_values`.\\n\\nThis op inserts a single entry for every row that doesn't have any values.\\nThe index is created as `[row, 0, ..., 0]` and the inserted value\\nis `default_value`.\\n\\nFor example, suppose `sp_input` has shape `[5, 6]` and non-empty values:\\n\\n    [0, 1]: a\\n    [0, 3]: b\\n    [2, 0]: c\\n    [3, 1]: d\\n\\nRows 1 and 4 are empty, so the output will be of shape `[5, 6]` with values:\\n\\n    [0, 1]: a\\n    [0, 3]: b\\n    [1, 0]: default_value\\n    [2, 0]: c\\n    [3, 1]: d\\n    [4, 0]: default_value\\n\\nThe output `SparseTensor` will be in row-major order and will have the\\nsame shape as the input.\\n\\nThis op also returns an indicator vector shaped `[dense_shape[0]]` such that\\n\\n    empty_row_indicator[i] = True iff row i was an empty row.\\n\\nAnd a reverse index map vector shaped `[indices.shape[0]]` that is used during\\nbackpropagation,\\n\\n    reverse_index_map[j] = out_j s.t. indices[j, :] == output_indices[out_j, :]\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"dense_shape\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"default_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"output_values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"empty_row_indicator\", \"type\": \"TF_BoolTensor\" },\n      { \"name\": \"reverse_index_map\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseMatMul\",\n    \"summary\": \"Multiply matrix \\\"a\\\" by matrix \\\"b\\\".\",\n    \"description\": \"The inputs must be two-dimensional matrices and the inner dimension of \\\"a\\\" must\\nmatch the outer dimension of \\\"b\\\". Both \\\"a\\\" and \\\"b\\\" must be `Tensor`s not\\n`SparseTensor`s.  This op is optimized for the case where at least one of \\\"a\\\" or\\n\\\"b\\\" is sparse, in the sense that they have a large proportion of zero values.\\nThe breakeven for using this versus a dense matrix multiply on one platform was\\n30% zero values in the sparse matrix.\\n\\nThe gradient computation of this operation will only take advantage of sparsity\\nin the input gradient when that gradient comes from a Relu.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float32]>\" },\n      { \"name\": \"b\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"a_is_sparse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"b_is_sparse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseReduceSum\",\n    \"summary\": \"Computes the sum of elements across dimensions of a SparseTensor.\",\n    \"description\": \"This Op takes a SparseTensor and is the sparse counterpart to\\n`tf.reduce_sum()`.  In particular, this Op also returns a dense `Tensor`\\ninstead of a sparse one.\\n\\nReduces `sp_input` along the dimensions given in `reduction_axes`.  Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`reduction_axes`. If `keep_dims` is true, the reduced dimensions are retained\\nwith length 1.\\n\\nIf `reduction_axes` has no entries, all dimensions are reduced, and a tensor\\nwith a single element is returned.  Additionally, the axes can be negative,\\nwhich are interpreted according to the indexing rules in Python.\",\n    \"operands\": [\n      { \"name\": \"input_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"input_values\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"input_shape\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"reduction_axes\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseReshape\",\n    \"summary\": \"Reshapes a SparseTensor to represent values in a new dense shape.\",\n    \"description\": \"This operation has the same semantics as reshape on the represented dense\\ntensor.  The `input_indices` are recomputed based on the requested `new_shape`.\\n\\nIf one component of `new_shape` is the special value -1, the size of that\\ndimension is computed so that the total dense size remains constant.  At\\nmost one component of `new_shape` can be -1.  The number of dense elements\\nimplied by `new_shape` must be the same as the number of dense elements\\noriginally implied by `input_shape`.\\n\\nReshaping does not affect the order of values in the SparseTensor.\\n\\nIf the input tensor has rank `R_in` and `N` non-empty values, and `new_shape`\\nhas length `R_out`, then `input_indices` has shape `[N, R_in]`,\\n`input_shape` has length `R_in`, `output_indices` has shape `[N, R_out]`, and\\n`output_shape` has length `R_out`.\",\n    \"operands\": [\n      { \"name\": \"input_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"input_shape\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"new_shape\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_indices\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"output_shape\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentMean\",\n    \"summary\": \"Computes the mean along sparse segments of a tensor.\",\n    \"description\": \"See `tf.sparse.segment_sum` for usage examples.\\n\\nLike `SegmentMean`, but `segment_ids` can have rank less than `data`'s first\\ndimension, selecting a subset of dimension 0, specified by `indices`.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sparse_gradient\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentMeanGrad\",\n    \"summary\": \"Computes gradients for SparseSegmentMean.\",\n    \"description\": \"Returns tensor \\\"output\\\" with same shape as grad, except for dimension 0 whose\\nvalue is output_dim0.\",\n    \"operands\": [\n      { \"name\": \"grad\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"output_dim0\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentMeanWithNumSegments\",\n    \"summary\": \"Computes the mean along sparse segments of a tensor.\",\n    \"description\": \"Like `SparseSegmentMean`, but allows missing ids in `segment_ids`. If an id is\\nmissing, the `output` tensor at that position will be zeroed.\\n\\nRead\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sparse_gradient\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentSqrtN\",\n    \"summary\": \"Computes the sum along sparse segments of a tensor divided by the sqrt of N.\",\n    \"description\": \"N is the size of the segment being reduced.\\n\\nSee `tf.sparse.segment_sum` for usage examples.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sparse_gradient\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentSqrtNGrad\",\n    \"summary\": \"Computes gradients for SparseSegmentSqrtN.\",\n    \"description\": \"Returns tensor \\\"output\\\" with same shape as grad, except for dimension 0 whose\\nvalue is output_dim0.\",\n    \"operands\": [\n      { \"name\": \"grad\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"output_dim0\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentSqrtNWithNumSegments\",\n    \"summary\": \"Computes the sum along sparse segments of a tensor divided by the sqrt of N.\",\n    \"description\": \"N is the size of the segment being reduced.\\n\\nLike `SparseSegmentSqrtN`, but allows missing ids in `segment_ids`. If an id is\\nmissing, the `output` tensor at that position will be zeroed.\\n\\nRead\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sparse_gradient\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSegmentSum\",\n    \"summary\": \"Computes the sum along sparse segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nLike `SegmentSum`, but `segment_ids` can have rank less than `data`'s first\\ndimension, selecting a subset of dimension 0, specified by `indices`.\\n\\nFor example:\\n\\n```python\\nc = tf.constant([[1,2,3,4], [-1,-2,-3,-4], [5,6,7,8]])\\n\\n# Select two rows, one segment.\\ntf.sparse_segment_sum(c, tf.constant([0, 1]), tf.constant([0, 0]))\\n# => [[0 0 0 0]]\\n\\n# Select two rows, two segment.\\ntf.sparse_segment_sum(c, tf.constant([0, 1]), tf.constant([0, 1]))\\n# => [[ 1  2  3  4]\\n#     [-1 -2 -3 -4]]\\n\\n# Select all rows, two segments.\\ntf.sparse_segment_sum(c, tf.constant([0, 1, 2]), tf.constant([0, 0, 1]))\\n# => [[0 0 0 0]\\n#     [5 6 7 8]]\\n\\n# Which is equivalent to:\\ntf.segment_sum(c, tf.constant([0, 0, 1]))\\n```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sparse_gradient\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseSoftmaxCrossEntropyWithLogits\",\n    \"summary\": \"Computes softmax cross entropy cost and gradients to backpropagate.\",\n    \"description\": \"Unlike `SoftmaxCrossEntropyWithLogits`, this operation does not accept\\na matrix of label probabilities, but rather a single label per row\\nof features.  This label is considered to have probability 1.0 for the\\ngiven row.\\n\\nInputs are the logits, not probabilities.\",\n    \"operands\": [\n      { \"name\": \"features\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"labels\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"loss\", \"type\": \"TF_FloatTensor\" },\n      { \"name\": \"backprop\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseTensorDenseMatMul\",\n    \"summary\": \"Multiply SparseTensor (of rank 2) \\\"A\\\" by dense matrix \\\"B\\\".\",\n    \"description\": \"No validity checking is performed on the indices of A.  However, the following\\ninput format is recommended for optimal behavior:\\n\\nif adjoint_a == false:\\n  A should be sorted in lexicographically increasing order.  Use SparseReorder\\n  if you're not sure.\\nif adjoint_a == true:\\n  A should be sorted in order of increasing dimension 1 (i.e., \\\"column major\\\"\\n  order instead of \\\"row major\\\" order).\",\n    \"operands\": [\n      { \"name\": \"a_indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"a_values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"a_shape\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"b\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adjoint_a\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"adjoint_b\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SparseToDense\",\n    \"summary\": \"Converts a sparse representation into a dense tensor.\",\n    \"description\": \"Builds an array `dense` with shape `output_shape` such that\\n\\n```\\n# If sparse_indices is scalar\\ndense[i] = (i == sparse_indices ? sparse_values : default_value)\\n\\n# If sparse_indices is a vector, then for each i\\ndense[sparse_indices[i]] = sparse_values[i]\\n\\n# If sparse_indices is an n by d matrix, then for each i in [0, n)\\ndense[sparse_indices[i][0], ..., sparse_indices[i][d-1]] = sparse_values[i]\\n```\\n\\nAll other values in `dense` are set to `default_value`.  If `sparse_values` is a\\nscalar, all sparse indices are set to this single value.\\n\\nIndices should be sorted in lexicographic order, and indices must not\\ncontain any repeats. If `validate_indices` is true, these properties\\nare checked during execution.\",\n    \"operands\": [\n      { \"name\": \"sparse_indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"output_shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"sparse_values\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"default_value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dense\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"validate_indices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Split\",\n    \"summary\": \"Splits a tensor into `num_split` tensors along one dimension.\",\n    \"operands\": [\n      { \"name\": \"split_dim\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SplitV\",\n    \"summary\": \"Splits a tensor into `num_split` tensors along one dimension.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"size_splits\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Int8 ]>\" },\n      { \"name\": \"split_dim\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sqrt\",\n    \"summary\": \"Computes square root of x element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = \\\\sqrt{x} = x^{1/2}\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SqrtGrad\",\n    \"summary\": \"Computes the gradient for the sqrt of `x` wrt its input.\",\n    \"description\": \"Specifically, `grad = dy * 0.5 / y`, where `y = sqrt(x)`, and `dy`\\nis the corresponding input gradient.\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"dy\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Square\",\n    \"summary\": \"Computes square of x element-wise.\",\n    \"description\": \"I.e., \\\\\\\\(y = x * x = x^2\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SquaredDifference\",\n    \"summary\": \"Returns conj(x - y)(x - y) element-wise.\",\n    \"description\": \"*NOTE*: `SquaredDifference` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Squeeze\",\n    \"summary\": \"Removes dimensions of size 1 from the shape of a tensor.\",\n    \"description\": \"Given a tensor `input`, this operation returns a tensor of the same type with\\nall dimensions of size 1 removed. If you don't want to remove all size 1\\ndimensions, you can remove specific size 1 dimensions by specifying\\n`axis`.\\n\\nFor example:\\n\\n```\\n# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]\\nshape(squeeze(t)) ==> [2, 3]\\n```\\n\\nOr, to remove specific size 1 dimensions:\\n\\n```\\n# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]\\nshape(squeeze(t, [2, 4])) ==> [1, 2, 3, 1]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"squeeze_dims\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StackCloseV2\",\n    \"summary\": \"Delete the stack from its resource container.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StackPopV2\",\n    \"summary\": \"Pop the element at the top of the stack.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"elem\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StackPushV2\",\n    \"summary\": \"Push an element onto the stack.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"elem\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"swap_memory\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StackV2\",\n    \"summary\": \"A stack that produces elements in first-in last-out order.\",\n    \"operands\": [\n      { \"name\": \"max_size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elem_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"stack_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatefulPartitionedCall\",\n    \"summary\": \"returns `f(inputs)`, where `f`'s body is placed and partitioned.\",\n    \"description\": \"Asynchronously executes a function, potentially across multiple devices but\\nwithin a single process. The kernel places and partitions a given function's\\nunderlying graph, and executes each of the partitioned subgraphs as a function.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"f\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"config\", \"type\": \"StrAttr\" },\n      { \"name\": \"config_proto\", \"type\": \"StrAttr\" },\n      { \"name\": \"executor_type\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatefulStandardNormalV2\",\n    \"summary\": \"Outputs random values from a normal distribution.\",\n    \"description\": \"The generated values will have mean 0 and standard deviation 1.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"algorithm\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatefulTruncatedNormal\",\n    \"summary\": \"Outputs random values from a truncated normal distribution.\",\n    \"description\": \"The generated values follow a normal distribution with mean 0 and standard\\ndeviation 1, except that values whose magnitude is more than 2 standard\\ndeviations from the mean are dropped and re-picked.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"algorithm\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatefulUniform\",\n    \"summary\": \"Outputs random values from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[0, 1)`. The\\nlower bound 0 is included in the range, while the upper bound 1 is excluded.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"algorithm\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatefulUniformFullInt\",\n    \"summary\": \"Outputs random integers from a uniform distribution.\",\n    \"description\": \"The generated values are uniform integers covering the whole range of `dtype`.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"algorithm\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Int32, TF_Int64, TF_Uint32, TF_Uint64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatefulUniformInt\",\n    \"summary\": \"Outputs random integers from a uniform distribution.\",\n    \"description\": \"The generated values are uniform integers in the range `[minval, maxval)`.\\nThe lower bound `minval` is included in the range, while the upper bound\\n`maxval` is excluded.\\n\\nThe random integers are slightly biased unless `maxval - minval` is an exact\\npower of two.  The bias is small for values of `maxval - minval` significantly\\nsmaller than the range of the output (either `2^32` or `2^64`).\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"algorithm\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"minval\", \"type\": \"TensorOf<[TF_Int32, TF_Int64, TF_Uint32, TF_Uint64]>\" },\n      { \"name\": \"maxval\", \"type\": \"TensorOf<[TF_Int32, TF_Int64, TF_Uint32, TF_Uint64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Int32, TF_Int64, TF_Uint32, TF_Uint64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessMultinomial\",\n    \"summary\": \"Draws samples from a multinomial distribution.\",\n    \"operands\": [\n      { \"name\": \"logits\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"num_samples\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessParameterizedTruncatedNormal\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"means\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"stddevs\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"minvals\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"maxvals\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomBinomial\",\n    \"summary\": \"Outputs deterministic pseudorandom random numbers from a binomial distribution.\",\n    \"description\": \"Outputs random values from a binomial distribution.\\n\\nThe outputs are a deterministic function of `shape`, `seed`, `counts`, and `probs`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"counts\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"probs\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomGammaV2\",\n    \"summary\": \"Outputs deterministic pseudorandom random numbers from a gamma distribution.\",\n    \"description\": \"Outputs random values from a gamma distribution.\\n\\nThe outputs are a deterministic function of `shape`, `seed`, and `alpha`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"alpha\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomGetAlg\",\n    \"summary\": \"Picks the best counter-based RNG algorithm based on device.\",\n    \"description\": \"This op picks the best counter-based RNG algorithm based on device.\",\n    \"results\": [\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomGetKeyCounter\",\n    \"summary\": \"Scrambles seed into key and counter, using the best algorithm based on device.\",\n    \"description\": \"This op scrambles a shape-[2] seed into a key and a counter, both needed by counter-based RNG algorithms. The scrambing uses the best algorithm based on device. The scrambling is opaque but approximately satisfies the property that different seed results in different key/counter pair (which will in turn result in different random numbers).\",\n    \"operands\": [\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomGetKeyCounterAlg\",\n    \"summary\": \"Picks the best algorithm based on device, and scrambles seed into key and counter.\",\n    \"description\": \"This op picks the best counter-based RNG algorithm based on device, and scrambles a shape-[2] seed into a key and a counter, both needed by the counter-based algorithm. The scrambling is opaque but approximately satisfies the property that different seed results in different key/counter pair (which will in turn result in different random numbers).\",\n    \"operands\": [\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomNormal\",\n    \"summary\": \"Outputs deterministic pseudorandom values from a normal distribution.\",\n    \"description\": \"The generated values will have mean 0 and standard deviation 1.\\n\\nThe outputs are a deterministic function of `shape` and `seed`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomNormalV2\",\n    \"summary\": \"Outputs deterministic pseudorandom values from a normal distribution.\",\n    \"description\": \"The generated values will have mean 0 and standard deviation 1.\\n\\nThe outputs are a deterministic function of `shape`, `key`, `counter` and `alg`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomPoisson\",\n    \"summary\": \"Outputs deterministic pseudorandom random numbers from a Poisson distribution.\",\n    \"description\": \"Outputs random values from a Poisson distribution.\\n\\nThe outputs are a deterministic function of `shape`, `seed`, and `lam`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"lam\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Float16, TF_Float32, TF_Float64, TF_Int32, TF_Int64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomUniform\",\n    \"summary\": \"Outputs deterministic pseudorandom random values from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[0, 1)`. The\\nlower bound 0 is included in the range, while the upper bound 1 is excluded.\\n\\nThe outputs are a deterministic function of `shape` and `seed`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomUniformFullInt\",\n    \"summary\": \"Outputs deterministic pseudorandom random integers from a uniform distribution.\",\n    \"description\": \"The generated values are uniform integers covering the whole range of `dtype`.\\n\\nThe outputs are a deterministic function of `shape` and `seed`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Uint32, TF_Uint64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Uint32, TF_Uint64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomUniformFullIntV2\",\n    \"summary\": \"Outputs deterministic pseudorandom random integers from a uniform distribution.\",\n    \"description\": \"The generated values are uniform integers covering the whole range of `dtype`.\\n\\nThe outputs are a deterministic function of `shape`, `key`, `counter` and `alg`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Uint32, TF_Uint64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomUniformInt\",\n    \"summary\": \"Outputs deterministic pseudorandom random integers from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[minval, maxval)`.\\n\\nThe outputs are a deterministic function of `shape`, `seed`, `minval`, and `maxval`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"minval\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"maxval\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomUniformIntV2\",\n    \"summary\": \"Outputs deterministic pseudorandom random integers from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[minval, maxval)`.\\n\\nThe outputs are a deterministic function of `shape`, `key`, `counter`, `alg`, `minval` and `maxval`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"minval\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Uint32, TF_Uint64 ]>\" },\n      { \"name\": \"maxval\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Uint32, TF_Uint64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Int32, TF_Int64, TF_Uint32, TF_Uint64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessRandomUniformV2\",\n    \"summary\": \"Outputs deterministic pseudorandom random values from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[0, 1)`. The\\nlower bound 0 is included in the range, while the upper bound 1 is excluded.\\n\\nThe outputs are a deterministic function of `shape`, `key`, `counter` and `alg`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessTruncatedNormal\",\n    \"summary\": \"Outputs deterministic pseudorandom values from a truncated normal distribution.\",\n    \"description\": \"The generated values follow a normal distribution with mean 0 and standard\\ndeviation 1, except that values whose magnitude is more than 2 standard\\ndeviations from the mean are dropped and re-picked.\\n\\nThe outputs are a deterministic function of `shape` and `seed`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"seed\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StatelessTruncatedNormalV2\",\n    \"summary\": \"Outputs deterministic pseudorandom values from a truncated normal distribution.\",\n    \"description\": \"The generated values follow a normal distribution with mean 0 and standard\\ndeviation 1, except that values whose magnitude is more than 2 standard\\ndeviations from the mean are dropped and re-picked.\\n\\nThe outputs are a deterministic function of `shape`, `key`, `counter` and `alg`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"counter\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"alg\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StaticRegexFullMatch\",\n    \"summary\": \"Check if the input matches the regex pattern.\",\n    \"description\": \"The input is a string tensor of any shape. The pattern is the\\nregular expression to be matched with every element of the input tensor.\\nThe boolean values (True or False) of the output tensor indicate\\nif the input matches the regex pattern provided.\\n\\nThe pattern follows the re2 syntax (https://github.com/google/re2/wiki/Syntax)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StopGradient\",\n    \"summary\": \"Stops gradient computation.\",\n    \"description\": \"When executed in a graph, this op outputs its input tensor as-is.\\n\\nWhen building ops to compute gradients, this op prevents the contribution of\\nits inputs to be taken into account.  Normally, the gradient generator adds ops\\nto a graph to compute the derivatives of a specified 'loss' by recursively\\nfinding out inputs that contributed to its computation.  If you insert this op\\nin the graph it inputs are masked from the gradient generator.  They are not\\ntaken into account for computing gradients.\\n\\nThis is useful any time you want to compute a value with TensorFlow but need\\nto pretend that the value was a constant. For example, the softmax function\\nfor a vector x can be written as\\n\\n```python\\n\\n  def softmax(x):\\n    numerator = tf.exp(x)\\n    denominator = tf.reduce_sum(numerator)\\n    return numerator / denominator\\n```\\n\\nThis however is susceptible to overflow if the values in x are large. An\\nalternative more stable way is to subtract the maximum of x from each of the\\nvalues.\\n\\n```python\\n\\n  def stable_softmax(x):\\n    z = x - tf.reduce_max(x)\\n    numerator = tf.exp(z)\\n    denominator = tf.reduce_sum(numerator)\\n    return numerator / denominator\\n```\\n\\nHowever, when we backprop through the softmax to x, we dont want to backprop\\nthrough the `tf.reduce_max(x)` (if the max values are not unique then the\\ngradient could flow to the wrong input) calculation and treat that as a\\nconstant. Therefore, we should write this out as\\n\\n```python\\n\\n  def stable_softmax(x):\\n    z = x - tf.stop_gradient(tf.reduce_max(x))\\n    numerator = tf.exp(z)\\n    denominator = tf.reduce_sum(numerator)\\n    return numerator / denominator\\n```\\n\\nSome other examples include:\\n\\n*  The *EM* algorithm where the *M-step* should not involve backpropagation\\n   through the output of the *E-step*.\\n*  Contrastive divergence training of Boltzmann machines where, when\\n   differentiating the energy function, the training must not backpropagate\\n   through the graph that generated the samples from the model.\\n*  Adversarial training, where no backprop should happen through the adversarial\\n   example generation process.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StoreMinibatchStatisticsInFdo\",\n    \"summary\": \"Store the number of IDs and unique IDs in an FDO table.\",\n    \"operands\": [\n      { \"name\": \"program_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"max_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"max_uniques\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sample_count\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_replica\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"feature_width\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"num_sc_per_chip\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"mini_batch_splits\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StridedSlice\",\n    \"summary\": \"Return a strided slice from `input`.\",\n    \"description\": \"Note, most python users will want to use the Python `Tensor.__getitem__`\\nor `Variable.__getitem__` rather than this op directly.\\n\\nThe goal of this op is to produce a new tensor with a subset of\\nthe elements from the `n` dimensional `input` tensor. The subset is chosen using\\na sequence of `m` sparse range specifications encoded into the arguments\\nof this function. Note, in some cases\\n`m` could be equal to `n`, but this need not be the case. Each\\nrange specification entry can be one of the following:\\n\\n- An ellipsis (...). Ellipses are used to imply zero or more\\n  dimensions of full-dimension selection and are produced using\\n  `ellipsis_mask`. For example, `foo[...]` is the identity slice.\\n\\n- A new axis. This is used to insert a new shape=1 dimension and is\\n  produced using `new_axis_mask`. For example, `foo[:, ...]` where\\n  `foo` is shape `(3, 4)` produces a `(1, 3, 4)` tensor.\\n\\n\\n- A range `begin:end:stride`. This is used to specify how much to choose from\\n  a given dimension. `stride` can be any integer but 0.  `begin` is an integer\\n  which represents the index of the first value to select while `end` represents\\n  the index of the last value to select. The number of values selected in each\\n  dimension is `end - begin` if `stride > 0` and `begin - end` if `stride < 0`.\\n  `begin` and `end` can be negative where `-1` is the last element, `-2` is\\n  the second to last. `begin_mask` controls whether to replace the explicitly\\n  given `begin` with an implicit effective value of `0` if `stride > 0` and\\n  `-1` if `stride < 0`. `end_mask` is analogous but produces the number\\n  required to create the largest open interval. For example, given a shape\\n  `(3,)` tensor `foo[:]`, the effective `begin` and `end` are `0` and `3`. Do\\n  not assume this is equivalent to `foo[0:-1]` which has an effective `begin`\\n  and `end` of `0` and `2`. Another example is `foo[-2::-1]` which reverses the\\n  first dimension of a tensor while dropping the last two (in the original\\n  order elements). For example `foo = [1,2,3,4]; foo[-2::-1]` is `[4,3]`.\\n\\n- A single index. This is used to keep only elements that have a given\\n  index. For example (`foo[2, :]` on a shape `(5,6)` tensor produces a\\n  shape `(6,)` tensor. This is encoded in `begin` and `end` and\\n  `shrink_axis_mask`.\\n\\nEach conceptual range specification is encoded in the op's argument. This\\nencoding is best understand by considering a non-trivial example. In\\nparticular,\\n`foo[1, 2:4, None, ..., :-3:-1, :]` will be encoded as\\n\\n```\\nbegin = [1, 2, x, x, 0, x] # x denotes don't care (usually 0)\\nend = [2, 4, x, x, -3, x]\\nstrides = [1, 1, x, x, -1, 1]\\nbegin_mask = 1<<4 | 1<<5 = 48\\nend_mask = 1<<5 = 32\\nellipsis_mask = 1<<3 = 8\\nnew_axis_mask = 1<<2 = 4\\nshrink_axis_mask = 1<<0 = 1\\n```\\n\\nIn this case if `foo.shape` is (5, 5, 5, 5, 5, 5) the final shape of\\nthe slice becomes (2, 1, 5, 5, 2, 5).\\nLet us walk step by step through each argument specification.\\n\\n1.  The first argument in the example slice is turned into `begin = 1` and\\n`end = begin + 1 = 2`. To disambiguate from the original spec `2:4` we\\nalso set the appropriate bit in `shrink_axis_mask`.\\n\\n2. `2:4` is contributes 2, 4, 1 to begin, end, and stride. All masks have\\nzero bits contributed.\\n\\n3. None is a synonym for `tf.newaxis`. This means insert a dimension of size 1\\ndimension in the final shape. Dummy values are contributed to begin,\\nend and stride, while the new_axis_mask bit is set.\\n\\n4. `...` grab the full ranges from as many dimensions as needed to\\nfully specify a slice for every dimension of the input shape.\\n\\n5. `:-3:-1` shows the use of negative indices. A negative index `i` associated\\nwith a dimension that has shape `s` is converted to a positive index\\n`s + i`. So `-1` becomes `s-1` (i.e. the last element). This conversion\\nis done internally so begin, end and strides receive x, -3, and -1.\\nThe appropriate begin_mask bit is set to indicate the start range is the\\nfull range (ignoring the x).\\n\\n6. `:` indicates that the entire contents of the corresponding dimension\\nis selected. This is equivalent to `::` or `0::1`. begin, end, and strides\\nreceive 0, 0, and 1, respectively. The appropriate bits in `begin_mask` and\\n`end_mask` are also set.\\n\\n*Requirements*:\\n  `0 != strides[i] for i in [0, m)`\\n  `ellipsis_mask must be a power of two (only one ellipsis)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"begin\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"end\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"strides\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"end_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StridedSliceGrad\",\n    \"summary\": \"Returns the gradient of `StridedSlice`.\",\n    \"description\": \"Since `StridedSlice` cuts out pieces of its `input` which is size\\n`shape`, its gradient will have the same shape (which is passed here\\nas `shape`). The gradient will be zero in any element that the slice\\ndoes not select.\\n\\nArguments are the same as StridedSliceGrad with the exception that\\n`dy` is the input gradient to be propagated and `shape` is the\\nshape of `StridedSlice`'s `input`.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"begin\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"end\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"dy\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"end_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StringFormat\",\n    \"summary\": \"Formats a string template using a list of tensors.\",\n    \"description\": \"Formats a string template using a list of tensors, pretty-printing tensor summaries.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strtemplate\", \"type\": \"DefaultValuedStrAttr<StrAttr, %s>\" },\n      { \"name\": \"placeholder\", \"type\": \"DefaultValuedStrAttr<StrAttr, %s>\" },\n      { \"name\": \"summarize\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 3>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StringJoin\",\n    \"summary\": \"Joins the strings in the given list of string tensors into one tensor;\",\n    \"description\": \"with the given separator (default is an empty separator).\\n\\nExamples:\\n\\n>>> s = [\\\"hello\\\", \\\"world\\\", \\\"tensorflow\\\"]\\n>>> tf.strings.join(s, \\\" \\\")\\n<tf.Tensor: shape=(), dtype=string, numpy=b'hello world tensorflow'>\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_StrTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"separator\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StringStrip\",\n    \"summary\": \"Strip leading and trailing whitespaces from the Tensor.\",\n    \"description\": \"Examples:\\n\\n>>> tf.strings.strip([\\\"\\\\nTensorFlow\\\", \\\"     The python library    \\\"]).numpy()\\narray([b'TensorFlow', b'The python library'], dtype=object)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.StringToHashBucketFast\",\n    \"summary\": \"Converts each string in the input Tensor to its hash mod by a number of buckets.\",\n    \"description\": \"The hash function is deterministic on the content of the string within the\\nprocess and will never change. However, it is not suitable for cryptography.\\nThis function may be used when CPU time is scarce and inputs are trusted or\\nunimportant. There is a risk of adversaries constructing inputs that all hash\\nto the same bucket. To prevent this problem, use a strong hash function with\\n`tf.string_to_hash_bucket_strong`.\\n\\nExamples:\\n\\n>>> tf.strings.to_hash_bucket_fast([\\\"Hello\\\", \\\"TensorFlow\\\", \\\"2.x\\\"], 3).numpy()\\narray([0, 2, 2])\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_buckets\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sub\",\n    \"summary\": \"Returns x - y element-wise.\",\n    \"description\": \"*NOTE*: `Subtract` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Sum\",\n    \"summary\": \"Computes the sum of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SummaryWriter\",\n    \"summary\": \"Returns a handle to be used to access a summary writer.\",\n    \"description\": \"The summary writer is an in-graph resource which can be used by ops to write\\nsummaries to event files.\\n\\nwriter: the summary writer resource. Scalar handle.\",\n    \"results\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shared_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"container\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Svd\",\n    \"summary\": \"Computes the singular value decompositions of one or more matrices.\",\n    \"description\": \"Computes the SVD of each inner matrix in `input` such that\\n`input[..., :, :] = u[..., :, :] * diag(s[..., :, :]) * transpose(v[..., :, :])`\\n\\n```python\\n# a is a tensor containing a batch of matrices.\\n# s is a tensor of singular values for each matrix.\\n# u is the tensor containing the left singular vectors for each matrix.\\n# v is the tensor containing the right singular vectors for each matrix.\\ns, u, v = svd(a)\\ns, _, _ = svd(a, compute_uv=False)\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"s\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"u\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"v\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"compute_uv\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"full_matrices\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.SymbolicGradient\",\n    \"summary\": \"Computes the gradient function for function f via backpropagation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TakeDataset\",\n    \"summary\": \"Creates a dataset that contains `count` elements from the `input_dataset`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"count\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TakeWhileDataset\",\n    \"summary\": \"Creates a dataset that stops iteration when predicate` is false.\",\n    \"description\": \"The `predicate` function must return a scalar boolean and accept the\\nfollowing arguments:\\n\\n* One tensor for each component of an element of `input_dataset`.\\n* One tensor for each value in `other_arguments`.\",\n    \"operands\": [\n      { \"name\": \"input_dataset\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"other_arguments\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"output_types\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TypeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Tan\",\n    \"summary\": \"Computes tan of x element-wise.\",\n    \"description\": \"Given an input tensor, this function computes tangent of every\\n  element in the tensor. Input range is `(-inf, inf)` and\\n  output range is `(-inf, inf)`. If input lies outside the boundary, `nan`\\n  is returned.\\n\\n  ```python\\n  x = tf.constant([-float(\\\"inf\\\"), -9, -0.5, 1, 1.2, 200, 10000, float(\\\"inf\\\")])\\n  tf.math.tan(x) ==> [nan 0.45231566 -0.5463025 1.5574077 2.572152 -1.7925274 0.32097113 nan]\\n  ```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes hyperbolic tangent of `x` element-wise.\",\n    \"description\": \"Given an input tensor, this function computes hyperbolic tangent of every\\n  element in the tensor. Input range is `[-inf, inf]` and\\n  output range is `[-1,1]`.\\n\\n  >>> x = tf.constant([-float(\\\"inf\\\"), -5, -0.5, 1, 1.2, 2, 3, float(\\\"inf\\\")])\\n  >>> tf.math.tanh(x)\\n  <tf.Tensor: shape=(8,), dtype=float32, numpy=\\n  array([-1.0, -0.99990916, -0.46211717,  0.7615942 ,  0.8336547 ,\\n          0.9640276 ,  0.9950547 ,  1.0], dtype=float32)>\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TanhGrad\",\n    \"summary\": \"Computes the gradient for the tanh of `x` wrt its input.\",\n    \"description\": \"Specifically, `grad = dy * (1 - y*y)`, where `y = tanh(x)`, and `dy`\\nis the corresponding input gradient.\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"dy\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayCloseV3\",\n    \"summary\": \"Delete the TensorArray from its resource container.\",\n    \"description\": \"This enables the user to close and release the resource in the middle\\nof a step/run.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayConcatV3\",\n    \"summary\": \"Concat the elements from the TensorArray into value `value`.\",\n    \"description\": \"Takes `T` elements of shapes\\n\\n  ```\\n  (n0 x d0 x d1 x ...), (n1 x d0 x d1 x ...), ..., (n(T-1) x d0 x d1 x ...)\\n  ```\\n\\nand concatenates them into a Tensor of shape:\\n\\n  ```\\n  (n0 + n1 + ... + n(T-1) x d0 x d1 x ...)\\n  ```\\n\\nAll elements must have the same shape (excepting the first dimension).\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"lengths\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_shape_except0\", \"type\": \"DefaultValuedOptionalAttr<TF_ShapeAttr, std::nullopt>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayGatherV3\",\n    \"summary\": \"Gather specific elements from the TensorArray into output `value`.\",\n    \"description\": \"All elements selected by `indices` must have the same shape.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_shape\", \"type\": \"DefaultValuedOptionalAttr<TF_ShapeAttr, std::nullopt>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayGradV3\",\n    \"summary\": \"Creates a TensorArray for storing the gradients of values in the given handle.\",\n    \"description\": \"If the given TensorArray gradient already exists, returns a reference to it.\\n\\nLocks the size of the original TensorArray by disabling its dynamic size flag.\\n\\n**A note about the input flow_in:**\\n\\nThe handle flow_in forces the execution of the gradient lookup to occur\\nonly after certain other operations have occurred.  For example, when\\nthe forward TensorArray is dynamically sized, writes to this TensorArray\\nmay resize the object.  The gradient TensorArray is statically sized based\\non the size of the forward TensorArray when this operation executes.\\nFurthermore, the size of the forward TensorArray is frozen by this call.\\nAs a result, the flow is used to ensure that the call to generate the gradient\\nTensorArray only happens after all writes are executed.\\n\\nIn the case of dynamically sized TensorArrays, gradient computation should\\nonly be performed on read operations that have themselves been chained via\\nflow to occur only after all writes have executed. That way the final size\\nof the forward TensorArray is known when this operation is called.\\n\\n**A note about the source attribute:**\\n\\nTensorArray gradient calls use an accumulator TensorArray object.  If\\nmultiple gradients are calculated and run in the same session, the multiple\\ngradient nodes may accidentally flow through the same accumulator TensorArray.\\nThis double counts and generally breaks the TensorArray gradient flow.\\n\\nThe solution is to identify which gradient call this particular\\nTensorArray gradient is being called in.  This is performed by identifying\\na unique string (e.g. \\\"gradients\\\", \\\"gradients_1\\\", ...) from the input\\ngradient Tensor's name.  This string is used as a suffix when creating\\nthe TensorArray gradient object here (the attribute `source`).\\n\\nThe attribute `source` is added as a suffix to the forward TensorArray's\\nname when performing the creation / lookup, so that each separate gradient\\ncalculation gets its own TensorArray accumulator.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"flow_out\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayReadV3\",\n    \"summary\": \"Read an element from the TensorArray into output `value`.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"index\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayScatterV3\",\n    \"summary\": \"Scatter the data from the input value into specific TensorArray elements.\",\n    \"description\": \"`indices` must be a vector, its length must match the first dim of `value`.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"flow_out\", \"type\": \"TF_Float32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArraySizeV3\",\n    \"summary\": \"Get the current size of the TensorArray.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArraySplitV3\",\n    \"summary\": \"Split the data from the input value into TensorArray elements.\",\n    \"description\": \"Assuming that `lengths` takes on values\\n\\n  ```\\n  (n0, n1, ..., n(T-1))\\n  ```\\n\\nand that `value` has shape\\n\\n  ```\\n  (n0 + n1 + ... + n(T-1) x d0 x d1 x ...),\\n  ```\\n\\nthis splits values into a TensorArray with T tensors.\\n\\nTensorArray index t will be the subtensor of values with starting position\\n\\n  ```\\n  (n0 + n1 + ... + n(t-1), 0, 0, ...)\\n  ```\\n\\nand having size\\n\\n  ```\\n  nt x d0 x d1 x ...\\n  ```\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"lengths\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"flow_out\", \"type\": \"TF_Float32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayV3\",\n    \"summary\": \"An array of Tensors of given size.\",\n    \"description\": \"Write data via Write and read via Read or Pack.\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"flow\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"element_shape\", \"type\": \"DefaultValuedOptionalAttr<TF_ShapeAttr, std::nullopt>\" },\n      { \"name\": \"dynamic_size\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"clear_after_read\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"identical_element_shapes\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"tensor_array_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorArrayWriteV3\",\n    \"summary\": \"Push an element onto the tensor_array.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"index\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"flow_in\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"flow_out\", \"type\": \"TF_Float32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListConcatV2\",\n    \"summary\": \"Concats all tensors in the list along the 0th dimension.\",\n    \"description\": \"Requires that all tensors have the same shape except the first dimension.\\n\\ninput_handle: The input list.\\nelement_shape: The shape of the uninitialized elements in the list. If the first\\n  dimension is not -1, it is assumed that all list elements have the same\\n  leading dim.\\nleading_dims: The list of leading dims of uninitialized list elements. Used if\\n  the leading dim of input_handle.element_shape or the element_shape input arg\\n  is not already set.\\ntensor: The concated result.\\nlengths: Output tensor containing sizes of the 0th dimension of tensors in the list, used for computing the gradient.\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"element_shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"leading_dims\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"lengths\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListElementShape\",\n    \"summary\": \"The shape of the elements of the given list, as a tensor.\",\n    \"description\": \"input_handle: the list\\n  element_shape: the shape of elements of the list\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"element_shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListFromTensor\",\n    \"summary\": \"Creates a TensorList which, when stacked, has the value of `tensor`.\",\n    \"description\": \"Each tensor in the result list corresponds to one row of the input tensor.\\n\\ntensor: The input tensor.\\noutput_handle: The list.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"element_shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_handle\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListGather\",\n    \"summary\": \"Creates a Tensor by indexing into the TensorList.\",\n    \"description\": \"Each row in the produced Tensor corresponds to the element in the TensorList\\nspecified by the given index (see `tf.gather`).\\n\\ninput_handle: The input tensor list.\\nindices: The indices used to index into the list.\\nvalues: The tensor.\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"element_shape\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListGetItem\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"index\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"element_shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"item\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListLength\",\n    \"summary\": \"Returns the number of tensors in the input tensor list.\",\n    \"description\": \"input_handle: the input list\\nlength: the number of tensors in the list\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"length\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListPopBack\",\n    \"summary\": \"Returns the last element of the input list as well as a list with all but that element.\",\n    \"description\": \"Fails if the list is empty.\\n\\ninput_handle: the input list\\ntensor: the withdrawn last element of the list\\nelement_dtype: the type of elements in the list\\nelement_shape: the shape of the output tensor\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"element_shape\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListPushBack\",\n    \"summary\": \"Returns a list which has the passed-in `Tensor` as last element and the other elements of the given list in `input_handle`.\",\n    \"description\": \"tensor: The tensor to put on the list.\\ninput_handle: The old list.\\noutput_handle: A list with the elements of the old list followed by tensor.\\nelement_dtype: the type of elements in the list.\\nelement_shape: a shape compatible with that of elements in the list.\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_handle\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListReserve\",\n    \"summary\": \"List of the given size with empty elements.\",\n    \"description\": \"element_shape: the shape of the future elements of the list\\nnum_elements: the number of elements to reserve\\nhandle: the output list\\nelement_dtype: the desired type of elements in the list.\",\n    \"operands\": [\n      { \"name\": \"element_shape\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_elements\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListResize\",\n    \"summary\": \"Resizes the list.\",\n    \"description\": \"input_handle: the input list\\nsize: size of the output list\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_handle\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListScatterIntoExistingList\",\n    \"summary\": \"Scatters tensor at indices in an input list.\",\n    \"description\": \"Each member of the TensorList corresponds to one row of the input tensor,\\nspecified by the given index (see `tf.gather`).\\n\\ninput_handle: The list to scatter into.\\ntensor: The input tensor.\\nindices: The indices used to index into the list.\\noutput_handle: The TensorList.\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_handle\", \"type\": \"TF_VariantTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListSetItem\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"index\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"item\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"resize_if_index_out_of_bounds\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorListStack\",\n    \"summary\": \"Stacks all tensors in the list.\",\n    \"description\": \"Requires that all tensors have the same shape.\\n\\ninput_handle: the input list\\ntensor: the gathered result\\nnum_elements: optional. If not -1, the number of elements in the list.\",\n    \"operands\": [\n      { \"name\": \"input_handle\", \"type\": \"TF_VariantTensor\" },\n      { \"name\": \"element_shape\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_elements\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorScatterAdd\",\n    \"summary\": \"Adds sparse `updates` to an existing tensor according to `indices`.\",\n    \"description\": \"This operation creates a new tensor by adding sparse `updates` to the passed\\nin `tensor`.\\nThis operation is very similar to `tf.compat.v1.scatter_nd_add`, except that the\\nupdates are added onto an existing tensor (as opposed to a variable). If the\\nmemory for the existing tensor cannot be re-used, a copy is made and updated.\\n\\n`indices` is an integer tensor containing indices into a new tensor of shape\\n`tensor.shape`.  The last dimension of `indices` can be at most the rank of\\n`tensor.shape`:\\n\\n```\\nindices.shape[-1] <= tensor.shape.rank\\n```\\n\\nThe last dimension of `indices` corresponds to indices into elements\\n(if `indices.shape[-1] = tensor.shape.rank`) or slices\\n(if `indices.shape[-1] < tensor.shape.rank`) along dimension\\n`indices.shape[-1]` of `tensor.shape`.  `updates` is a tensor with shape\\n\\n```\\nindices.shape[:-1] + tensor.shape[indices.shape[-1]:]\\n```\\n\\nThe simplest form of `tensor_scatter_nd_add` is to add individual elements to a\\ntensor by index. For example, say we want to add 4 elements in a rank-1\\ntensor with 8 elements.\\n\\nIn Python, this scatter add operation would look like this:\\n\\n>>> indices = tf.constant([[4], [3], [1], [7]])\\n>>> updates = tf.constant([9, 10, 11, 12])\\n>>> tensor = tf.ones([8], dtype=tf.int32)\\n>>> updated = tf.tensor_scatter_nd_add(tensor, indices, updates)\\n>>> updated\\n<tf.Tensor: shape=(8,), dtype=int32,\\nnumpy=array([ 1, 12,  1, 11, 10,  1,  1, 13], dtype=int32)>\\n\\nWe can also, insert entire slices of a higher rank tensor all at once. For\\nexample, if we wanted to insert two slices in the first dimension of a\\nrank-3 tensor with two matrices of new values.\\n\\nIn Python, this scatter add operation would look like this:\\n\\n>>> indices = tf.constant([[0], [2]])\\n>>> updates = tf.constant([[[5, 5, 5, 5], [6, 6, 6, 6],\\n...                         [7, 7, 7, 7], [8, 8, 8, 8]],\\n...                        [[5, 5, 5, 5], [6, 6, 6, 6],\\n...                         [7, 7, 7, 7], [8, 8, 8, 8]]])\\n>>> tensor = tf.ones([4, 4, 4],dtype=tf.int32)\\n>>> updated = tf.tensor_scatter_nd_add(tensor, indices, updates)\\n>>> updated\\n<tf.Tensor: shape=(4, 4, 4), dtype=int32,\\nnumpy=array([[[6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8], [9, 9, 9, 9]],\\n             [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],\\n             [[6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8], [9, 9, 9, 9]],\\n             [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]], dtype=int32)>\\n\\n\\nIf `indices` contains any out-of-bound indices, depending on\\n`bad_indices_policy`, the op will either return an error or ignore the\\nout-of-bound indices. `bad_indices_policy` can be one of the following values:\\n1. \\\"\\\" or \\\"DEFAULT\\\": raises on CPU and ignore on GPU. This is because\\n   historically on CPU and GPU we handle errors in different ways, and for\\n   backward compatibility we keep the default behavior.\\n2. \\\"ERROR\\\": raises error; GPU does not support this value.\\n3. \\\"IGNORE\\\": ignore the bad indices; supported on both CPU and GPU.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorScatterMax\",\n    \"summary\": \"Apply a sparse update to a tensor taking the element-wise maximum.\",\n    \"description\": \"Returns a new tensor copied from `tensor` whose values are element-wise maximum between\\ntensor and updates according to the indices.\\n\\n>>> tensor = [0, 0, 0, 0, 0, 0, 0, 0]\\n>>> indices = [[1], [4], [5]]\\n>>> updates = [1, -1, 1]\\n>>> tf.tensor_scatter_nd_max(tensor, indices, updates).numpy()\\narray([0, 1, 0, 0, 0, 1, 0, 0], dtype=int32)\\n\\nRefer to `tf.tensor_scatter_nd_update` for more details.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorScatterMin\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorScatterSub\",\n    \"summary\": \"Subtracts sparse `updates` from an existing tensor according to `indices`.\",\n    \"description\": \"This operation creates a new tensor by subtracting sparse `updates` from the\\npassed in `tensor`.\\nThis operation is very similar to `tf.scatter_nd_sub`, except that the updates\\nare subtracted from an existing tensor (as opposed to a variable). If the memory\\nfor the existing tensor cannot be re-used, a copy is made and updated.\\n\\n`indices` is an integer tensor containing indices into a new tensor of shape\\n`shape`.  The last dimension of `indices` can be at most the rank of `shape`:\\n\\n    indices.shape[-1] <= shape.rank\\n\\nThe last dimension of `indices` corresponds to indices into elements\\n(if `indices.shape[-1] = shape.rank`) or slices\\n(if `indices.shape[-1] < shape.rank`) along dimension `indices.shape[-1]` of\\n`shape`.  `updates` is a tensor with shape\\n\\n    indices.shape[:-1] + shape[indices.shape[-1]:]\\n\\nThe simplest form of tensor_scatter_sub is to subtract individual elements\\nfrom a tensor by index. For example, say we want to insert 4 scattered elements\\nin a rank-1 tensor with 8 elements.\\n\\nIn Python, this scatter subtract operation would look like this:\\n\\n```python\\n    indices = tf.constant([[4], [3], [1], [7]])\\n    updates = tf.constant([9, 10, 11, 12])\\n    tensor = tf.ones([8], dtype=tf.int32)\\n    updated = tf.tensor_scatter_nd_sub(tensor, indices, updates)\\n    print(updated)\\n```\\n\\nThe resulting tensor would look like this:\\n\\n    [1, -10, 1, -9, -8, 1, 1, -11]\\n\\nWe can also, insert entire slices of a higher rank tensor all at once. For\\nexample, if we wanted to insert two slices in the first dimension of a\\nrank-3 tensor with two matrices of new values.\\n\\nIn Python, this scatter add operation would look like this:\\n\\n```python\\n    indices = tf.constant([[0], [2]])\\n    updates = tf.constant([[[5, 5, 5, 5], [6, 6, 6, 6],\\n                            [7, 7, 7, 7], [8, 8, 8, 8]],\\n                           [[5, 5, 5, 5], [6, 6, 6, 6],\\n                            [7, 7, 7, 7], [8, 8, 8, 8]]])\\n    tensor = tf.ones([4, 4, 4],dtype=tf.int32)\\n    updated = tf.tensor_scatter_nd_sub(tensor, indices, updates)\\n    print(updated)\\n```\\n\\nThe resulting tensor would look like this:\\n\\n    [[[-4, -4, -4, -4], [-5, -5, -5, -5], [-6, -6, -6, -6], [-7, -7, -7, -7]],\\n     [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],\\n     [[-4, -4, -4, -4], [-5, -5, -5, -5], [-6, -6, -6, -6], [-7, -7, -7, -7]],\\n     [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]]\\n\\nNote that on CPU, if an out of bound index is found, an error is returned.\\nOn GPU, if an out of bound index is found, the index is ignored.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorScatterUpdate\",\n    \"summary\": \"Scatter `updates` into an existing tensor according to `indices`.\",\n    \"description\": \"This operation creates a new tensor by applying sparse `updates` to the passed\\nin `tensor`.\\nThis operation is very similar to `tf.scatter_nd`, except that the updates are\\nscattered onto an existing tensor (as opposed to a zero-tensor). If the memory\\nfor the existing tensor cannot be re-used, a copy is made and updated.\\n\\nIf `indices` contains duplicates, then we pick the last update for the index.\\n\\n**WARNING**: There are some GPU specific semantics for this operation.\\n- If an out of bound index is found, the index is ignored.\\n- The order in which updates are applied is nondeterministic, so the output\\nwill be nondeterministic if `indices` contains duplicates.\\n\\n`indices` is an integer tensor containing indices into a new tensor of shape\\n`shape`.\\n\\n* `indices` must have at least 2 axes: `(num_updates, index_depth)`.\\n* The last axis of `indices` is how deep to index into `tensor` so  this index\\n  depth must be less than the rank of `tensor`: `indices.shape[-1] <= tensor.ndim`\\n\\nif `indices.shape[-1] = tensor.rank` this Op indexes and updates scalar elements.\\nif `indices.shape[-1] < tensor.rank` it indexes and updates slices of the input\\n`tensor`.\\n\\nEach `update` has a rank of `tensor.rank - indices.shape[-1]`.\\nThe overall shape of `updates` is:\\n\\n```\\nindices.shape[:-1] + tensor.shape[indices.shape[-1]:]\\n```\\n\\nIf `indices` contains any out-of-bound indices, depending on\\n`bad_indices_policy`, the op will either return an error or ignore the\\nout-of-bound indices. `bad_indices_policy` can be one of the following values:\\n1. \\\"\\\" or \\\"DEFAULT\\\": raises on CPU and ignore on GPU. This is because\\n   historically on CPU and GPU we handle errors in different ways, and for\\n   backward compatibility we keep the default behavior.\\n2. \\\"ERROR\\\": raises error; GPU does not support this value.\\n3. \\\"IGNORE\\\": ignore the bad indices; supported on both CPU and GPU.\\n\\nFor usage examples see the python [tf.tensor_scatter_nd_update](\\nhttps://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_update) function\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64, TF_Uint16 ]>\" },\n      { \"name\": \"updates\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bad_indices_policy\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorSliceDataset\",\n    \"summary\": \"Creates a dataset that emits each dim-0 slice of `components` once.\",\n    \"operands\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"handle\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_shapes\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<TF_ShapeAttr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"is_files\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"metadata\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"replicate_on_split\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TensorStridedSliceUpdate\",\n    \"summary\": \"Assign `value` to the sliced l-value reference of `input`.\",\n    \"description\": \"The values of `value` are assigned to the positions in the tensor `input` that\\nare selected by the slice parameters. The slice parameters `begin` `end`\\n`strides` etc. work exactly as in `StridedSlice`.\\n\\nNOTE this op currently does not support broadcasting and so `value`'s shape\\nmust be exactly the shape produced by the slice of `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"begin\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"end\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"end_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Tile\",\n    \"summary\": \"Constructs a tensor by tiling a given tensor.\",\n    \"description\": \"This operation creates a new tensor by replicating `input` `multiples` times.\\nThe output tensor's i'th dimension has `input.dims(i) * multiples[i]` elements,\\nand the values of `input` are replicated `multiples[i]` times along the 'i'th\\ndimension. For example, tiling `[a b c d]` by `[2]` produces\\n`[a b c d a b c d]`.\\n\\n>>> a = tf.constant([[1,2,3],[4,5,6]], tf.int32)\\n>>> b = tf.constant([1,2], tf.int32)\\n>>> tf.tile(a, b)\\n<tf.Tensor: shape=(2, 6), dtype=int32, numpy=\\narray([[1, 2, 3, 1, 2, 3],\\n       [4, 5, 6, 4, 5, 6]], dtype=int32)>\\n>>> c = tf.constant([2,1], tf.int32)\\n>>> tf.tile(a, c)\\n<tf.Tensor: shape=(4, 3), dtype=int32, numpy=\\narray([[1, 2, 3],\\n       [4, 5, 6],\\n       [1, 2, 3],\\n       [4, 5, 6]], dtype=int32)>\\n>>> d = tf.constant([2,2], tf.int32)\\n>>> tf.tile(a, d)\\n<tf.Tensor: shape=(4, 6), dtype=int32, numpy=\\narray([[1, 2, 3, 1, 2, 3],\\n       [4, 5, 6, 4, 5, 6],\\n       [1, 2, 3, 1, 2, 3],\\n       [4, 5, 6, 4, 5, 6]], dtype=int32)>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"multiples\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Timestamp\",\n    \"summary\": \"Provides the time since epoch in seconds.\",\n    \"description\": \"Returns the timestamp as a `float64` for seconds since the Unix epoch.\\n\\nCommon usages include:\\n* Logging\\n* Providing a random number seed\\n* Debugging graph execution\\n* Generating timing information, mainly through comparison of timestamps\\n\\nNote: In graph mode, the timestamp is computed when the op is executed,\\nnot when it is added to the graph.  In eager mode, the timestamp is computed\\nwhen the op is eagerly executed.\",\n    \"results\": [\n      { \"name\": \"ts\", \"type\": \"TF_Float64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.ToBool\",\n    \"summary\": \"Converts a tensor to a scalar predicate.\",\n    \"description\": \"Converts a tensor to a scalar predicate with the following rules:\\n\\n- For 0D tensors, truthiness is determined by comparing against a \\\"zero\\\"\\n  value. For numerical types it is the obvious zero. For strings it is the\\n  empty string.\\n\\n- For >0D tensors, truthiness is determined by looking at the number of\\n  elements. If has zero elements, then the result is false. Otherwise the\\n  result is true.\\n\\nThis matches the behavior of If and While for determining if a tensor counts\\nas true/false for a branch condition.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I1Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TopKUnique\",\n    \"summary\": \"Returns the TopK unique values in the array in sorted order.\",\n    \"description\": \"The running time is proportional to the product of K and the input\\nsize. Sorting the whole array is more efficient for sufficiently large\\nvalues of K. The median-of-medians algorithm is probably faster, but\\ndifficult to implement efficiently in XLA. If there are fewer than K\\nunique numbers (not NANs), the results are padded with negative\\ninfinity. NaNs are never returned. Subnormal numbers are flushed to\\nzero. If an element appears at multiple indices, the highest index is\\nreturned. If a TopK element never appears in the input due to padding\\nvalues, the indices are padded with negative one. If a padding value\\nappears in the input and padding is needed, the highest index of the\\npadding value will be returned. The semantics are not the same as\\nkth_order_statistic.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"topk\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"topk_indices\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TopKV2\",\n    \"summary\": \"Finds values and indices of the `k` largest elements for the last dimension.\",\n    \"description\": \"If the input is a vector (rank-1), finds the `k` largest entries in the vector\\nand outputs their values and indices as vectors.  Thus `values[j]` is the\\n`j`-th largest entry in `input`, and its index is `indices[j]`.\\n\\nFor matrices (resp. higher rank input), computes the top `k` entries in each\\nrow (resp. vector along the last dimension).  Thus,\\n\\n    values.shape = indices.shape = input.shape[:-1] + [k]\\n\\nIf two elements are equal, the lower-index element appears first.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"k\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"indices\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TopKWithUnique\",\n    \"summary\": \"Returns the TopK values in the array in sorted order.\",\n    \"description\": \"This is a combination of MakeUnique and TopKUnique. The returned top-K will\\nhave its lower bits replaced by iota, thus it will be close to the original\\nvalue but not exactly the same. The running time is proportional to the product\\nof K and the input size. NaNs are never returned. Subnormal numbers are flushed\\nto zero.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"topk\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"topk_indices\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUAnnotateTensorsWithDynamicShape\",\n    \"summary\": \"Placeholder op which takes the output of TPUCopyWithDynamicShapeOp and pass\\nthem to the following tpu ops.\",\n    \"description\": \"This op serves as an annotation for the dynamic shaped tensor and will be\\nremoved during the bridge rewrite.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tpu_tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUCompilationResult\",\n    \"summary\": \"Returns the result of a TPU compilation.\",\n    \"description\": \"This operation returns the result of a TPU compilation as a serialized\\nCompilationResultProto, which holds a status and an error message if an error\\noccurred during compilation.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUCompileMlirAndExecute\",\n    \"summary\": \"Op that compiles a computation in MLIR into a TPU program, and loads and executes it on a TPU device.\",\n    \"description\": \"For the internal use of the TPU compiler.\\n\\n'static_shapes' are tensors specifying the maximum dimension sizes for the tensors specified in `dynamic_operands`.\\n'args' are inputs to the TPU computation.\\n'operands_with_static_shape' are the indices of the operands that have a maximal static shape specified.\\n'mlir_module' is a serialized MLIR module with a `main` function that contains\\ntarget computation.\\n'metadata' is a serialized TPUCompileMetadataProto describing the shapes and\\ntypes of the inputs to the computation, as well as a mapping onto the TPU pod\\ntopology.\\n'producer_name' is a string describing the name of the framework that add support for running this portion of the model on TPUs.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"static_shapes\", \"type\": \"Variadic<TF_Int64Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"rendezvous_key_base\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operands_with_static_shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"mlir_module\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"metadata\", \"type\": \"StrAttr\" },\n      { \"name\": \"producer_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUCompileSucceededAssert\",\n    \"summary\": \"Asserts that compilation succeeded.\",\n    \"description\": \"This op produces no output and closes the device during failure to ensure all\\npending device interactions fail.\\n\\n'compilation_status' is a serialized CompilationResultProto.\",\n    \"operands\": [\n      { \"name\": \"compilation_status\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUCopyWithDynamicShape\",\n    \"summary\": \"Op that copies host tensors to device with bounded dynamic shape support.\",\n    \"description\": \"This op copies the padded tensor on cpu to TPU without the padded data. `tensors`\\nis a list of cpu tensors with padded data. `unpadded_sizes` is a list of shape\\ntensors which describes unpadded size of each dimension for each cpu tensor.\\nThe size of the `unpadded_sizes` should be the same as `tensors`. They are both\\non host. `tpu_tensors` are list of tpu device tensors without the padded data.\\n`tpu_tensors` also has the same size of the `tensors` and the shapes of\\n`tpu_tensors` are determined by the `unpadded_sizes`.\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"unpadded_sizes\", \"type\": \"Variadic<TF_Int32Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tpu_tensors\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUCopyWithLayout\",\n    \"summary\": \"Op that copies host tensor to device with specified layout.\",\n    \"description\": \"For internal use only.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"layout\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUDummyInput\",\n    \"summary\": \"Generates a zero-valued tensor for use as a dummy input to a TPU.\",\n    \"description\": \"For the internal use of the TF2XLA bridge in the XLA Broadcast pass. This op\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUEmbeddingActivations\",\n    \"summary\": \"An op enabling differentiation of TPU Embeddings.\",\n    \"description\": \"This op simply returns its first input, which is assumed to have been sliced\\nfrom the Tensors returned by TPUEmbeddingDequeueActivations. The presence of\\nthis op, and its first argument being a trainable Variable, enables automatic\\ndifferentiation of graphs containing embeddings via the TPU Embedding Python\\nlibraries.\",\n    \"operands\": [\n      { \"name\": \"embedding_variable\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"sliced_activations\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"lookup_id\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUExecute\",\n    \"summary\": \"Op that loads and executes a TPU program on a TPU device.\",\n    \"description\": \"For the internal use of the distributed TPU compiler.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"key\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUExecuteAndUpdateVariables\",\n    \"summary\": \"Op that executes a program with optional in-place variable updates.\",\n    \"description\": \"It (optionally) reads device variables, loads and executes a TPU program on a\\nTPU device, and then (optionally) in-place updates variables using the program\\noutputs, as specified in attributes device_var_reads_indices (program input\\nindices from directly reading variables) and device_var_updates_indices (program\\noutput indices used to update variables, -1 means no-update/read-only). Such\\nprogram outputs are consumed by these variables will not appear in the op\\noutput. For the internal use of the distributed TPU compiler.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"key\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_var_reads_indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"device_var_updates_indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUGetLayoutOp\",\n    \"summary\": \"Op that retrieves the layout of an input or output determined by TPUCompile.\",\n    \"description\": \"For internal use only.\",\n    \"operands\": [\n      { \"name\": \"cache_key\", \"type\": \"TF_StrTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"layout\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" },\n      { \"name\": \"is_output\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUOrdinalSelector\",\n    \"summary\": \"A TPU core selector Op.\",\n    \"description\": \"This Op produces a set of TPU cores (for warm-up) or a single TPU core\\n(for regular inference) to execute the TPU program on. The output is\\nconsumed by TPUPartitionedCall.\",\n    \"results\": [\n      { \"name\": \"device_ordinals\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUPartitionedCall\",\n    \"summary\": \"Calls a function placed on a specified TPU device.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"device_ordinal\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"autotuner_thresh\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUPartitionedInput\",\n    \"summary\": \"An op that groups a list of partitioned inputs together. This op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"partition_dim\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"_XlaSharding\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"_XlaShardingV2\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUPartitionedInputV2\",\n    \"summary\": \"An op that groups a list of partitioned inputs together. Supports ND sharding.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"partition_dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"is_packed\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"_XlaSharding\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"_XlaShardingV2\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUPartitionedOutput\",\n    \"summary\": \"An op that demultiplexes a tensor to be sharded by XLA to a list of partitioned\",\n    \"description\": \"outputs outside the XLA computation.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"partition_dim\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"_XlaSharding\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"_XlaShardingV2\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUPartitionedOutputV2\",\n    \"summary\": \"An op that demultiplexes a tensor to be sharded by XLA to a list of partitioned\",\n    \"description\": \"outputs outside the XLA computation. Supports ND sharding.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"partition_dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"_XlaSharding\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"_XlaShardingV2\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUReplicatedInput\",\n    \"summary\": \"Connects N inputs to an N-way replicated TPU computation.\",\n    \"description\": \"This operation holds a replicated input to a `tpu.replicate()` computation subgraph.\\nEach replicated input has the same shape and type alongside the output.\\n\\nFor example:\\n```\\n%a = \\\"tf.opA\\\"()\\n%b = \\\"tf.opB\\\"()\\n%replicated_input = \\\"tf.TPUReplicatedInput\\\"(%a, %b)\\n%computation = \\\"tf.Computation\\\"(%replicated_input)\\n```\\nThe above computation has a replicated input of two replicas.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_mirrored_variable\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"index\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"is_packed\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUReplicatedOutput\",\n    \"summary\": \"Connects N outputs from an N-way replicated TPU computation.\",\n    \"description\": \"This operation holds a replicated output from a `tpu.replicate()` computation subgraph.\\nEach replicated output has the same shape and type alongside the input.\\n\\nFor example:\\n```\\n%computation = \\\"tf.Computation\\\"()\\n%replicated_output:2 = \\\"tf.TPUReplicatedOutput\\\"(%computation)\\n```\\nThe above computation has a replicated output of two replicas.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUReplicateMetadata\",\n    \"summary\": \"Metadata indicating how the TPU computation should be replicated.\",\n    \"description\": \"This operation holds the metadata common to operations of a `tpu.replicate()` computation subgraph.\",\n    \"attributes\": [\n      { \"name\": \"num_replicas\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_cores_per_replica\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"topology\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"use_tpu\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"device_assignment\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"computation_shape\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"host_compute_core\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"padding_map\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"step_marker_location\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"STEP_MARK_AT_ENTRY\\\">\" },\n      { \"name\": \"allow_soft_placement\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_spmd_for_xla_partitioning\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_shardy_partitioner\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"tpu_compile_options_proto\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPUReshardVariables\",\n    \"summary\": \"Op that reshards on-device TPU variables to specified state.\",\n    \"description\": \"Op that reshards on-device TPU variables to specified state. Internal use only.\\n\\nThe sharding state is represented as the key of the compilation that generated\\nthe sharding/unsharding programs along with the main program. new_format_key\\nspecifies the desired state, and format_state_var is the current state of the\\nvariables.\",\n    \"operands\": [\n      { \"name\": \"vars\", \"type\": \"Variadic<TF_ResourceTensor>\" },\n      { \"name\": \"new_format_key\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"format_state_var\", \"type\": \"TF_ResourceTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TPURoundRobin\",\n    \"summary\": \"Round-robin load balancing on TPU cores.\",\n    \"description\": \"A load balancing op that round-robins among TPU cores.\\n\\nThis op round-robins between the integers in [0, NumTPUCoresVisiblePerHost]. It\\nis useful for interfacing with TensorFlow ops that take as input a TPU core on\\nwhich to execute computations, such as `TPUPartitionedCall`.\\n\\ndevice_ordinal: An integer in [0, NumTPUCoresVisiblePerHost].\",\n    \"results\": [\n      { \"name\": \"device_ordinal\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"Shuffle dimensions of x according to a permutation.\",\n    \"description\": \"The output `y` has the same rank as `x`. The shapes of `x` and `y` satisfy:\\n  `y.shape[i] == x.shape[perm[i]] for i in [0, 1, ..., rank(x) - 1]`\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"perm\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TridiagonalMatMul\",\n    \"summary\": \"Calculate product with tridiagonal matrix.\",\n    \"description\": \"Calculates product of two matrices, where left matrix is a tridiagonal matrix.\",\n    \"operands\": [\n      { \"name\": \"superdiag\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"maindiag\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"subdiag\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"rhs\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TridiagonalSolve\",\n    \"summary\": \"Solves tridiagonal systems of equations.\",\n    \"description\": \"Solves tridiagonal systems of equations.\\n  Supports batch dimensions and multiple right-hand sides per each left-hand\\n  side.\\n  On CPU, solution is computed via Gaussian elimination with or without partial\\n  pivoting, depending on `partial_pivoting` attribute. On GPU, Nvidia's cuSPARSE\\n  library is used: https://docs.nvidia.com/cuda/cusparse/index.html#gtsv\\n  Partial pivoting is not yet supported by XLA backends.\",\n    \"operands\": [\n      { \"name\": \"diagonals\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" },\n      { \"name\": \"rhs\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Complex128, TF_Complex64, TF_Float32, TF_Float64 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"partial_pivoting\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" },\n      { \"name\": \"perturb_singular\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TruncateDiv\",\n    \"summary\": \"Returns x / y element-wise, rounded towards zero.\",\n    \"description\": \"Truncation designates that negative numbers will round fractional quantities\\ntoward zero. I.e. -7 / 5 = -1. This matches C semantics but it is different\\nthan Python semantics. See `FloorDiv` for a division function that matches\\nPython Semantics.\\n\\n*NOTE*: `TruncateDiv` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" },\n      { \"name\": \"y\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TruncatedNormal\",\n    \"summary\": \"Outputs random values from a truncated normal distribution.\",\n    \"description\": \"The generated values follow a normal distribution with mean 0 and standard\\ndeviation 1, except that values whose magnitude is more than 2 standard\\ndeviations from the mean are dropped and re-picked.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.TruncateMod\",\n    \"summary\": \"Returns element-wise remainder of division. This emulates C semantics in that\",\n    \"description\": \"the result here is consistent with a truncating divide. E.g. `truncate(x / y) *\\ny + truncate_mod(x, y) = x`.\\n\\n*NOTE*: `TruncateMod` supports broadcasting. More about broadcasting\\n[here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrI32OrI64Tensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrI32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UncompressElement\",\n    \"summary\": \"Uncompresses a compressed dataset element.\",\n    \"operands\": [\n      { \"name\": \"compressed\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"components\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformDequantize\",\n    \"summary\": \"Perform dequantization on the quantized Tensor `input`.\",\n    \"description\": \"Given quantized `input` which was quantized using `scales` and `zero_points`, performs dequantization using the formula:\\ndequantized_data = (quantized_data - zero_point) * scale.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Qint32, TF_Qint8, TF_Quint8 ]>\" },\n      { \"name\": \"scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantize\",\n    \"summary\": \"Perform quantization on Tensor `input`.\",\n    \"description\": \"Given `input`, `scales` and `zero_points`, performs quantization using the formula:\\nquantized_data = floor(input_data * (1.0f / scale) + 0.5f) + zero_point\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Qint32, TF_Qint8, TF_Quint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantizedAdd\",\n    \"summary\": \"Perform quantized add of quantized Tensor `lhs` and quantized Tensor `rhs` to make quantized `output`.\",\n    \"description\": \"Given quantized `lhs` and quantized `rhs`, performs quantized add on `lhs` and `rhs` to make quantized `output`.\\n\\n`UniformQuantizedAdd` follows Numpy broadcasting rules.\\nThe two input array shapes are compared element-wise.\\nStarting with the trailing dimensions, the two dimensions either have to be equal or one of them needs to be 1.\\n\\n`lhs` and `rhs` must be quantized Tensor, where data value is quantized using the formula:\\n```\\nquantized_data = clip(original_data / scale + zero_point, quantization_min_val, quantization_max_val)\\n```\\n`output` is also quantized, using the same formula.\\n\\nIf `lhs` and `output` is both per-axis quantized, the quantization axis must match.\\nAlso, if `rhs` and `output` is both per-axis quantized, the quantization axis must match.\\n*Match* means the axis must match when adding, regarding the broadcasting.\\ni.e. For both operands `lhs` and `rhs`,\\nif `operand.quantization_axis` >= 0 and `output.quantization_axis` >= 0,\\n`operand.dims` - `operand.quantization_axis` must be equal to `output.dims` - `output.quantization_axis`.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_Qint32Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_Qint32Tensor\" },\n      { \"name\": \"lhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"lhs_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"rhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"output_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"output_zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Qint32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"lhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"lhs_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"rhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"output_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantizedClipByValue\",\n    \"summary\": \"Perform clip by value on the quantized Tensor `operand`.\",\n    \"description\": \"Given quantized `operand` which was quantized using `scales` and `zero_points`, performs clip by value using `min` and `max` values.\\nIf quantization_axis is -1 (per-tensor quantized), the entire operand is clipped using scalar min, max.\\nOtherwise (per-channel quantized), the clipping is also done per-channel.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TF_Qint32Tensor\" },\n      { \"name\": \"min\", \"type\": \"TF_Qint32Tensor\" },\n      { \"name\": \"max\", \"type\": \"TF_Qint32Tensor\" },\n      { \"name\": \"scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Qint32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantizedConvolution\",\n    \"summary\": \"Perform quantized convolution of quantized Tensor `lhs` and quantized Tensor `rhs`. to make quantized `output`.\",\n    \"description\": \"Given quantized `lhs` and quantized `rhs`, performs quantized dot on `lhs` and `rhs` to make quantized `output`.\\n\\n`lhs` and `rhs` must be Tensors of same rank, and meet following shape conditions.\\n- `lhs_feature` % `feature_group_count` == 0\\n- `lhs_feature` % `rhs_input_feature` == 0\\n- `lhs_feature` / `feature_group_count` == `rhs_input_feature`\\n- `rhs_output_feature` % `feature_group_count` == 0\\n- `lhs_batch` % `batch_group_count` == 0\\n- `rhs_output_feature` % `batch_group_count` == 0\\n\\n`lhs` and `rhs` must be quantized Tensor, where data value is quantized using the formula:\\n```\\nquantized_data = clip(original_data / scale + zero_point, quantization_min_val, quantization_max_val)\\n```\\n`output` is also quantized, using the same formula.\\nIf `rhs` is per-tensor quantized, `output` must be also per-tensor quantized.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_Qint8Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_Qint8Tensor\" },\n      { \"name\": \"lhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"lhs_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"rhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"output_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"output_zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Qint32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"padding\", \"type\": \"StrAttr\" },\n      { \"name\": \"explicit_padding\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"batch_group_count\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"feature_group_count\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"lhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"lhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"lhs_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"rhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"output_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantizedConvolutionHybrid\",\n    \"summary\": \"Perform hybrid quantized convolution of float Tensor `lhs` and quantized Tensor `rhs`.\",\n    \"description\": \"Given float `lhs` and quantized `rhs`, internally performs quantization on `lhs`,\\nand then performs quantized convolution on quantized `lhs` and `rhs`.\\n\\nThe internal quantization on `lhs` is a quantization to `Trhs`, dynamic range,\\nper-batch (per-axis along axis `dimension_numbers.input_batch_dimension`), asymmetric,\\nand not narrow range (the range is [Trhs_MIN, Trhs_MAX]).\\n\\n`lhs` and `rhs` must be Tensors of same rank, and meet following shape conditions.\\n- lhs_feature % feature_group_count == 0\\n- lhs_feature % rhs_input_feature == 0\\n- lhs_feature / feature_group_count == rhs_input_feature\\n- rhs_output_feature % feature_group_count == 0\\n- lhs_batch % batch_group_count == 0\\n- rhs_output_feature % batch_group_count == 0\\n\\n`rhs` must be quantized Tensor, where its data value is quantized using the formula:\\nquantized_data = clip(original_data / scale + zero_point, quantization_min_val, quantization_max_val).\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_Qint8Tensor\" },\n      { \"name\": \"rhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs_zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"padding\", \"type\": \"StrAttr\" },\n      { \"name\": \"explicit_padding\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"batch_group_count\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"feature_group_count\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"rhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"rhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantizedDot\",\n    \"summary\": \"Perform quantized dot of quantized Tensor `lhs` and quantized Tensor `rhs` to make quantized `output`.\",\n    \"description\": \"Given quantized `lhs` and quantized `rhs`, performs quantized dot on `lhs` and `rhs` to make quantized `output`.\\n`lhs` and `rhs` must be 2D Tensors and the lhs.dim_size(1) must match rhs.dim_size(0).\\n`lhs` and `rhs` must be quantized Tensor, where data value is quantized using the formula:\\nquantized_data = clip(original_data / scale + zero_point, quantization_min_val, quantization_max_val).\\n`output` is also quantized, using the same formula.\\nIf `rhs` is per-tensor quantized, `output` must be also per-tensor quantized.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_Qint8Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_Qint8Tensor\" },\n      { \"name\": \"lhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"lhs_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"rhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"output_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"output_zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Qint32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"lhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"lhs_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"rhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"output_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformQuantizedDotHybrid\",\n    \"summary\": \"Perform hybrid quantized dot of float Tensor `lhs` and quantized Tensor `rhs`.\",\n    \"description\": \"Given float `lhs` and quantized `rhs`, internally performs quantization on `lhs`, and then performs quantized dot on quantized lhs and `rhs`.\\nThe internal quantization on `lhs` is a quantization to qint8, dynamic range, per-batch (per-axis along axis 0), asymmetric, and not narrow range (the range is [-128, 127]).\\n`lhs` and `rhs` must be 2D Tensors and the lhs.dim_size(1) must match rhs.dim_size(0).\\n`rhs` must be quantized Tensor, where its data value is quantized using the formula:\\nquantized_data = clip(original_data / scale + zero_point, quantization_min_val, quantization_max_val).\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_Qint8Tensor\" },\n      { \"name\": \"rhs_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"rhs_zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rhs_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"rhs_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"rhs_quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniformRequantize\",\n    \"summary\": \"Given quantized tensor `input`, requantize it with new quantization parameters.\",\n    \"description\": \"Given quantized tensor `input`, which was quantized using {input_scales, input_zero_points, input_quantization_axis, input_quantization_min_val, input_quantization_max_val},\\nrequantize it to a tensor, which is quantized using {output_scales, output_zero_points, output_quantization_axis, output_quantization_min_val, output_quantization_max_val}.\\nThe requantization is done by using the formula:\\noutput_quantized_data = clip(\\n  (input_quantized_data - input_zero_point) * (input_scale / output_scale) + output_zero_point,\\n  output_quantization_min_val,\\n  output_quantization_max_val)\\n\\nPer-tensor and per-axis quantization supported cases are followings:\\n* per-tensor -> per-tensor\\n* per-tensor -> per-axis\\n* per-axis -> per-axis where input_quantization_axis equals output_quantization_axis.\\ni.e. At least one among input_quantization_axis and output_quantization_axis must be -1, or two must be equal.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Qint32, TF_Qint8 ]>\" },\n      { \"name\": \"input_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"input_zero_points\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"output_scales\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"output_zero_points\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[ TF_Qint32, TF_Qint8 ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"input_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_quantization_max_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"output_quantization_min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_quantization_max_val\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Unique\",\n    \"summary\": \"Finds unique elements in a 1-D tensor.\",\n    \"description\": \"This operation returns a tensor `y` containing all of the unique elements of `x`\\nsorted in the same order that they occur in `x`; `x` does not need to be sorted.\\nThis operation also returns a tensor `idx` the same size as `x` that contains\\nthe index of each value of `x` in the unique output `y`. In other words:\\n\\n`y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]`\\n\\nExamples:\\n\\n```\\n# tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8]\\ny, idx = unique(x)\\ny ==> [1, 2, 4, 7, 8]\\nidx ==> [0, 0, 1, 2, 2, 2, 3, 4, 4]\\n```\\n\\n```\\n# tensor 'x' is [4, 5, 1, 2, 3, 3, 4, 5]\\ny, idx = unique(x)\\ny ==> [4, 5, 1, 2, 3]\\nidx ==> [0, 1, 2, 3, 4, 4, 0, 1]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"idx\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UniqueV2\",\n    \"summary\": \"Finds unique elements along an axis of a tensor.\",\n    \"description\": \"This operation either returns a tensor `y` containing unique elements\\nalong the `axis` of a tensor. The returned unique elements is sorted\\nin the same order as they occur along `axis` in `x`.\\nThis operation also returns a tensor `idx` that is the same size as\\nthe number of the elements in `x` along the `axis` dimension. It\\ncontains the index in the unique output `y`.\\nIn other words, for an `1-D` tensor `x` with `axis = None:\\n\\n`y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]`\\n\\nFor example:\\n\\n```\\n# tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8]\\ny, idx = unique(x)\\ny ==> [1, 2, 4, 7, 8]\\nidx ==> [0, 0, 1, 2, 2, 2, 3, 4, 4]\\n```\\n\\nFor an `2-D` tensor `x` with `axis = 0`:\\n\\n```\\n# tensor 'x' is [[1, 0, 0],\\n#                [1, 0, 0],\\n#                [2, 0, 0]]\\ny, idx = unique(x, axis=0)\\ny ==> [[1, 0, 0],\\n       [2, 0, 0]]\\nidx ==> [0, 0, 1]\\n```\\n\\nFor an `2-D` tensor `x` with `axis = 1`:\\n\\n```\\n# tensor 'x' is [[1, 0, 0],\\n#                [1, 0, 0],\\n#                [2, 0, 0]]\\ny, idx = unique(x, axis=1)\\ny ==> [[1, 0],\\n       [1, 0],\\n       [2, 0]]\\nidx ==> [0, 1, 1]\\n```\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"axis\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"idx\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Unpack\",\n    \"summary\": \"Unpacks a given dimension of a rank-`R` tensor into `num` rank-`(R-1)` tensors.\",\n    \"description\": \"Unpacks `num` tensors from `value` by chipping it along the `axis` dimension.\\nFor example, given a tensor of shape `(A, B, C, D)`;\\n\\nIf `axis == 0` then the i'th tensor in `output` is the slice `value[i, :, :, :]`\\n  and each tensor in `output` will have shape `(B, C, D)`. (Note that the\\n  dimension unpacked along is gone, unlike `split`).\\n\\nIf `axis == 1` then the i'th tensor in `output` is the slice `value[:, i, :, :]`\\n  and each tensor in `output` will have shape `(A, C, D)`.\\nEtc.\\n\\nThis is the opposite of `pack`.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UnsortedSegmentMax\",\n    \"summary\": \"Computes the maximum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nThis operator is similar to `tf.math.unsorted_segment_sum`,\\nInstead of computing the sum over segments, it computes the maximum such that:\\n\\n\\\\\\\\(output_i = \\\\max_{j...} data[j...]\\\\\\\\) where max is over tuples `j...` such\\nthat `segment_ids[j...] == i`.\\n\\nIf the maximum is empty for a given segment ID `i`, it outputs the smallest\\npossible value for the specific numeric type,\\n`output[i] = numeric_limits<T>::lowest()`.\\n\\nIf the given segment ID `i` is negative, then the corresponding value is\\ndropped, and will not be included in the result.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be less than\\n`num_segments`, and an error is thrown for out-of-bound indices. On GPU, this\\ndoes not throw an error for out-of-bound indices. On Gpu, out-of-bound indices\\nresult in safe but unspecified behavior, which may include ignoring\\nout-of-bound indices or outputting a tensor with a 0 stored in the first\\ndimension of its shape if `num_segments` is 0.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/UnsortedSegmentMax.png\\\" alt>\\n</div>\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [5,6,7,8], [4,3,2,1]])\\n>>> tf.math.unsorted_segment_max(c, tf.constant([0, 1, 0]), num_segments=2).numpy()\\narray([[4, 3, 3, 4],\\n       [5,  6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UnsortedSegmentMin\",\n    \"summary\": \"Computes the minimum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nThis operator is similar to `tf.math.unsorted_segment_sum`,\\nInstead of computing the sum over segments, it computes the minimum such that:\\n\\n\\\\\\\\(output_i = \\\\min_{j...} data_[j...]\\\\\\\\) where min is over tuples `j...` such\\nthat `segment_ids[j...] == i`.\\n\\nIf the minimum is empty for a given segment ID `i`, it outputs the largest\\npossible value for the specific numeric type,\\n`output[i] = numeric_limits<T>::max()`.\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [5,6,7,8], [4,3,2,1]])\\n>>> tf.math.unsorted_segment_min(c, tf.constant([0, 1, 0]), num_segments=2).numpy()\\narray([[1, 2, 2, 1],\\n       [5, 6, 7, 8]], dtype=int32)\\n\\nIf the given segment ID `i` is negative, then the corresponding value is\\ndropped, and will not be included in the result.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be less than\\n`num_segments`, and an error is thrown for out-of-bound indices. On GPU, this\\ndoes not throw an error for out-of-bound indices. On Gpu, out-of-bound indices\\nresult in safe but unspecified behavior, which may include ignoring\\nout-of-bound indices or outputting a tensor with a 0 stored in the first\\ndimension of its shape if `num_segments` is 0.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UnsortedSegmentProd\",\n    \"summary\": \"Computes the product along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nThis operator is similar to `tf.math.unsorted_segment_sum`,\\nInstead of computing the sum over segments, it computes the product of all\\nentries belonging to a segment such that:\\n\\n\\\\\\\\(output_i = \\\\prod_{j...} data[j...]\\\\\\\\) where the product is over tuples\\n`j...` such that `segment_ids[j...] == i`.\\n\\nFor example:\\n\\n>>> c = tf.constant([[1,2,3,4], [5,6,7,8], [4,3,2,1]])\\n>>> tf.math.unsorted_segment_prod(c, tf.constant([0, 1, 0]), num_segments=2).numpy()\\narray([[4, 6, 6, 4],\\n       [5, 6, 7, 8]], dtype=int32)\\n\\nIf there is no entry for a given segment ID `i`, it outputs 1.\\n\\nIf the given segment ID `i` is negative, then the corresponding value is\\ndropped, and will not be included in the result.\\nCaution: On CPU, values in `segment_ids` are always validated to be less than\\n`num_segments`, and an error is thrown for out-of-bound indices. On GPU, this\\ndoes not throw an error for out-of-bound indices. On Gpu, out-of-bound indices\\nresult in safe but unspecified behavior, which may include ignoring\\nout-of-bound indices or outputting a tensor with a 0 stored in the first\\ndimension of its shape if `num_segments` is 0.\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UnsortedSegmentSum\",\n    \"summary\": \"Computes the sum along segments of a tensor.\",\n    \"description\": \"Read\\n[the section on segmentation](https://tensorflow.org/api_docs/python/tf/math#Segmentation)\\nfor an explanation of segments.\\n\\nComputes a tensor such that\\n\\\\\\\\(output[i] = \\\\sum_{j...} data[j...]\\\\\\\\) where the sum is over tuples `j...` such\\nthat `segment_ids[j...] == i`.  Unlike `SegmentSum`, `segment_ids`\\nneed not be sorted and need not cover all values in the full\\nrange of valid values.\\n\\nIf the sum is empty for a given segment ID `i`, `output[i] = 0`.\\nIf the given segment ID `i` is negative, the value is dropped and will not be\\nadded to the sum of the segment.\\n\\n`num_segments` should equal the number of distinct segment IDs.\\n\\nCaution: On CPU, values in `segment_ids` are always validated to be less than\\n`num_segments`, and an error is thrown for out-of-bound indices. On GPU, this\\ndoes not throw an error for out-of-bound indices. On Gpu, out-of-bound indices\\nresult in safe but unspecified behavior, which may include ignoring\\nout-of-bound indices or outputting a tensor with a 0 stored in the first\\ndimension of its shape if `num_segments` is 0.\\n\\n<div style=\\\"width:70%; margin:auto; margin-bottom:10px; margin-top:20px;\\\">\\n<img style=\\\"width:100%\\\" src=\\\"https://www.tensorflow.org/images/UnsortedSegmentSum.png\\\" alt>\\n</div>\\n\\n>>> c = [[1,2,3,4], [5,6,7,8], [4,3,2,1]]\\n>>> tf.math.unsorted_segment_sum(c, [0, 1, 0], num_segments=2).numpy()\\narray([[5, 5, 5, 5],\\n       [5, 6, 7, 8]], dtype=int32)\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"segment_ids\", \"type\": \"TensorOf<[ TF_Int16, TF_Int32, TF_Int64 ]>\" },\n      { \"name\": \"num_segments\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.UpperBound\",\n    \"summary\": \"Applies upper_bound(sorted_search_values, values) along each row.\",\n    \"description\": \"Each set of rows with the same index in (sorted_inputs, values) is treated\\nindependently.  The resulting row is the equivalent of calling\\n`np.searchsorted(sorted_inputs, values, side='right')`.\\n\\nThe result is not a global index to the entire\\n`Tensor`, but rather just the index in the last dimension.\\n\\nA 2-D example:\\n  sorted_sequence = [[0, 3, 9, 9, 10],\\n                     [1, 2, 3, 4, 5]]\\n  values = [[2, 4, 9],\\n            [0, 2, 6]]\\n\\n  result = UpperBound(sorted_sequence, values)\\n\\n  result == [[1, 2, 4],\\n             [0, 2, 5]]\",\n    \"operands\": [\n      { \"name\": \"sorted_inputs\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.VarHandleOp\",\n    \"summary\": \"Creates a handle to a Variable resource from its name.\",\n    \"description\": \"container: the container this variable is placed in.\\nshared_name: the name by which this variable is referred to.\\ndtype and shape: attributes representing the data type and shape held in the\\n  variable.\\n\\nExample:\\n    resource_variable_ops.var_handle_op(\\n          dtype=dtypes.int32, shape=[8, 16], container=\\\"foo\\\", shared_name=\\\"bar\\\")\\n  returns a handle for a variable with name \\\"bar\\\" in container \\\"foo\\\", and the\\n  variable holds a tensor of shape [8, 16] and dtype int32.\",\n    \"results\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Variable\",\n    \"summary\": \"Use VariableV2 instead.\",\n    \"results\": [\n      { \"name\": \"ref\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.VariableShape\",\n    \"summary\": \"Returns the shape of the variable pointed to by `resource`.\",\n    \"description\": \"This operation returns a 1-D integer tensor representing the shape of `input`.\\n\\nFor example:\\n\\n```\\n# 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]\\nshape(t) ==> [2, 2, 3]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.VariableV2\",\n    \"summary\": \"Holds state in the form of a tensor that persists across steps.\",\n    \"description\": \"Outputs a ref to the tensor state so it may be read or modified.\\nTODO(zhifengc/mrry): Adds a pointer to a more detail document\\nabout sharing states in tensorflow.\",\n    \"results\": [\n      { \"name\": \"ref\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"container\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedOptionalAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tf.VarIsInitializedOp\",\n    \"summary\": \"Checks whether a resource handle-based variable has been initialized.\",\n    \"operands\": [\n      { \"name\": \"resource\", \"type\": \"TF_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"is_initialized\", \"type\": \"TF_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Where\",\n    \"summary\": \"Returns locations of nonzero / true values in a tensor.\",\n    \"description\": \"This operation returns the coordinates of true elements in `condition`. The\\ncoordinates are returned in a 2-D tensor where the first dimension (rows)\\nrepresents the number of true elements, and the second dimension (columns)\\nrepresents the coordinates of the true elements. Keep in mind, the shape of\\nthe output tensor can vary depending on how many true values there are in\\n`condition`. Indices are output in row-major order.\\n\\nFor example:\\n\\n```\\n# 'input' tensor is [[True, False]\\n#                    [True, False]]\\n# 'input' has two true values, so output has two coordinates.\\n# 'input' has rank of 2, so coordinates have two indices.\\nwhere(input) ==> [[0, 0],\\n                  [1, 0]]\\n\\n# `condition` tensor is [[[True, False]\\n#                     [True, False]]\\n#                    [[False, True]\\n#                     [False, True]]\\n#                    [[False, False]\\n#                     [False, True]]]\\n# 'input' has 5 true values, so output has 5 coordinates.\\n# 'input' has rank of 3, so coordinates have three indices.\\nwhere(input) ==> [[0, 0, 0],\\n                  [0, 1, 0],\\n                  [1, 0, 1],\\n                  [1, 1, 1],\\n                  [2, 1, 1]]\\n\\n# `condition` tensor is [[[1.5,  0.0]\\n#                     [-0.5, 0.0]]\\n#                    [[0.0,  0.25]\\n#                     [0.0,  0.75]]\\n#                    [[0.0,  0.0]\\n#                     [0.0,  0.01]]]\\n# 'input' has 5 nonzero values, so output has 5 coordinates.\\n# 'input' has rank of 3, so coordinates have three indices.\\nwhere(input) ==> [[0, 0, 0],\\n                  [0, 1, 0],\\n                  [1, 0, 1],\\n                  [1, 1, 1],\\n                  [2, 1, 1]]\\n\\n# `condition` tensor is [[[1.5 + 0.0j, 0.0  + 0.0j]\\n#                     [0.0 + 0.5j, 0.0  + 0.0j]]\\n#                    [[0.0 + 0.0j, 0.25 + 1.5j]\\n#                     [0.0 + 0.0j, 0.75 + 0.0j]]\\n#                    [[0.0 + 0.0j, 0.0  + 0.0j]\\n#                     [0.0 + 0.0j, 0.01 + 0.0j]]]\\n# 'input' has 5 nonzero magnitude values, so output has 5 coordinates.\\n# 'input' has rank of 3, so coordinates have three indices.\\nwhere(input) ==> [[0, 0, 0],\\n                  [0, 1, 0],\\n                  [1, 0, 1],\\n                  [1, 1, 1],\\n                  [2, 1, 1]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"index\", \"type\": \"TF_Int64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.While\",\n    \"summary\": \"output = input; While (Cond(output)) { output = Body(output) }\",\n    \"description\": \"output = input; While (Cond(output)) { output = Body(output) }\\n\\ninput: A list of input tensors whose types are T.\\noutput: A list of output tensors whose types are T.\\ncond: A function that takes 'input' and returns a tensor.  If the tensor is\\n    a scalar of non-boolean, the scalar is converted to a boolean\\n    according to the following rule: if the scalar is a numerical\\n    value, non-zero means True and zero means False; if the scalar is\\n    a string, non-empty means True and empty means False. If the\\n    tensor is not a scalar, non-emptiness means True and False\\n    otherwise.\\nbody: A function that takes a list of tensors and returns another\\n      list of tensors. Both lists have the same types as specified\\n      by T.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cond\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"body\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"parallel_iterations\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, 10>, [IntMinValue<1>]>\" },\n      { \"name\": \"is_stateless\", \"type\": \"BoolAttr\" },\n      { \"name\": \"shape_invariant\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WhileRegion\",\n    \"summary\": \"while operation\",\n    \"description\": \"The tf.WhileRegion op represents a while loop using 2 regions and a set of\\n  iteration variables. The iteration variables maintained by this Op have the\\n  same types as the inputs. The Op executes a while loop described by the\\n  following pseudo code:\\n\\n  ```\\n     func WhileRegionOp(inputs) {\\n       iteration_vars = inputs;\\n       while (cond(iteration_vars)) {\\n           iteration_vars = body(iteration_vars);\\n       }\\n       return iteration_vars;\\n     }\\n  ```\\n\\n  `cond` is the condition region and `body` is the body region. Both these\\n  regions accept the current value of the iteration variables as inputs.\\n\\n  The condition region yields a tensor<i1> which, if false, will exit the loop.\\n  It can also, optionally and additionally, yield the iteration variables, which\\n  must be unchanged.\\n\\n  The body region always has to yield the (possibly updated) iteration variables.\\n\\n  The iteration variables are initialized to the Op input, and the results of the\\n  tf.WhileRegion op are the final values of the iteration variables.\\n\\n  This implies that the operand and result types for tf.WhileRegion should be\\n  the same. Note that the condition and body regions can implicitly capture\\n  loop invariant values directly. In canonical form, iteration variables that\\n  pass through the loop body unmodified are converted to implicitly captured\\n  references to their values outside the loop.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parallel_iterations\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, 10>, [IntMinValue<1>]>\" },\n      { \"name\": \"is_stateless\", \"type\": \"BoolAttr\" },\n      { \"name\": \"shape_invariant\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteAudioSummary\",\n    \"summary\": \"Writes a `Summary` protocol buffer with audio.\",\n    \"description\": \"The summary has up to `max_outputs` summary values containing audio. The\\naudio is built from `tensor` which must be 3-D with shape `[batch_size,\\nframes, channels]` or 2-D with shape `[batch_size, frames]`. The values are\\nassumed to be in the range of `[-1.0, 1.0]` with a sample rate of `sample_rate`.\\n\\nThe `tag` argument is a scalar `Tensor` of type `string`.  It is used to\\nbuild the `tag` of the summary values:\\n\\n*  If `max_outputs` is 1, the summary value tag is '*tag*/audio'.\\n*  If `max_outputs` is greater than 1, the summary value tags are\\n   generated sequentially as '*tag*/audio/0', '*tag*/audio/1', etc.\\n\\nwriter: A handle to a summary writer.\\nstep: The step to write the summary for.\\ntag: Scalar. Used to build the `tag` attribute of the summary values.\\ntensor: 2-D of shape `[batch_size, frames]`.\\nsample_rate: The sample rate of the signal in hertz.\\nmax_outputs: Max number of batch elements to generate audio for.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tag\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"sample_rate\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_outputs\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, 3>, [IntMinValue<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteGraphSummary\",\n    \"summary\": \"Writes a `GraphDef` protocol buffer to a `SummaryWriter`.\",\n    \"description\": \"writer: Handle of `SummaryWriter`.\\nstep: The step to write the summary for.\\ntensor: A scalar string of the serialized tf.GraphDef proto.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteHistogramSummary\",\n    \"summary\": \"Writes a histogram summary.\",\n    \"description\": \"The generated\\n[`Summary`](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto)\\nhas one summary value containing a histogram for `values`.\\n\\nThis op reports an `InvalidArgument` error if any value is not finite.\\n\\nwriter: A handle to a summary writer.\\nstep: The step to write the summary for.\\ntag: Scalar.  Tag to use for the `Summary.Value`.\\nvalues: Any shape. Values to use to build the histogram.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tag\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"values\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteImageSummary\",\n    \"summary\": \"Writes a `Summary` protocol buffer with images.\",\n    \"description\": \"The summary has up to `max_images` summary values containing images. The\\nimages are built from `tensor` which must be 4-D with shape `[batch_size,\\nheight, width, channels]` and where `channels` can be:\\n\\n*  1: `tensor` is interpreted as Grayscale.\\n*  3: `tensor` is interpreted as RGB.\\n*  4: `tensor` is interpreted as RGBA.\\n\\nThe images have the same number of channels as the input tensor. For float\\ninput, the values are normalized one image at a time to fit in the range\\n`[0, 255]`.  `uint8` values are unchanged.  The op uses two different\\nnormalization algorithms:\\n\\n*  If the input values are all positive, they are rescaled so the largest one\\n   is 255.\\n\\n*  If any input value is negative, the values are shifted so input value 0.0\\n   is at 127.  They are then rescaled so that either the smallest value is 0,\\n   or the largest one is 255.\\n\\nThe `tag` argument is a scalar `Tensor` of type `string`.  It is used to\\nbuild the `tag` of the summary values:\\n\\n*  If `max_images` is 1, the summary value tag is '*tag*/image'.\\n*  If `max_images` is greater than 1, the summary value tags are\\n   generated sequentially as '*tag*/image/0', '*tag*/image/1', etc.\\n\\nThe `bad_color` argument is the color to use in the generated images for\\nnon-finite input values.  It is a `unit8` 1-D tensor of length `channels`.\\nEach element must be in the range `[0, 255]` (It represents the value of a\\npixel in the output image).  Non-finite values in the input tensor are\\nreplaced by this tensor in the output image.  The default value is the color\\nred.\\n\\nwriter: A handle to a summary writer.\\nstep: The step to write the summary for.\\ntag: Scalar. Used to build the `tag` attribute of the summary values.\\ntensor: 4-D of shape `[batch_size, height, width, channels]` where\\n  `channels` is 1, 3, or 4.\\nmax_images: Max number of batch elements to generate images for.\\nbad_color: Color to use for pixels with non-finite values.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tag\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"tensor\", \"type\": \"TensorOf<[TF_Float16, TF_Float32, TF_Uint8]>\" },\n      { \"name\": \"bad_color\", \"type\": \"TF_Uint8Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_images\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<I64Attr, 3>, [IntMinValue<1>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteRawProtoSummary\",\n    \"summary\": \"Writes a `Summary` protocol buffer with serialized string `Summary` protocol buffers.\",\n    \"description\": \"writer: A handle to a summary writer.\\nstep: The step to write the summary for.\\ntensor: A tensor holding one or more serialized `Summary` protobufs to write.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteScalarSummary\",\n    \"summary\": \"Writes a `Summary` protocol buffer with scalar values.\",\n    \"description\": \"The input `tag` and `value` must have the scalars.\\n\\nwriter: A handle to a summary writer.\\nstep: The step to write the summary for.\\ntag: Tag for the summary.\\nvalue: Value for the summary.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tag\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"value\", \"type\": \"TF_IntOrFpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteSummary\",\n    \"summary\": \"Outputs a `Summary` protocol buffer with a tensor.\",\n    \"description\": \"writer: A handle to a summary writer.\\nstep: The step to write the summary for.\\ntensor: A tensor to serialize.\\ntag: The summary's tag.\\nsummary_metadata: Serialized SummaryMetadata protocol buffer containing\\n plugin-related metadata for this summary.\",\n    \"operands\": [\n      { \"name\": \"writer\", \"type\": \"TF_ResourceTensor\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"tag\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"summary_metadata\", \"type\": \"TF_StrTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.WriteTrainingPredictions\",\n    \"summary\": \"Writes the given predictions into a RecordIO file using a previously\",\n    \"description\": \"initialized global TrainingPredictionWriter. The predictions are transformed\\ninto a PredictionData proto before they are written to the file.\",\n    \"operands\": [\n      { \"name\": \"keys\", \"type\": \"TF_StrTensor\" },\n      { \"name\": \"predictions_list\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"step\", \"type\": \"TF_Int64Tensor\" },\n      { \"name\": \"timestamp_usec\", \"type\": \"TF_Int64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prediction_names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"training\", \"type\": \"BoolAttr\" },\n      { \"name\": \"file_path\", \"type\": \"StrAttr\" },\n      { \"name\": \"write_vector_predictions\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Xdivy\",\n    \"summary\": \"Returns 0 if x == 0, and x / y otherwise, elementwise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaAllReduce\",\n    \"summary\": \"Wraps the XLA AllReduce operator\",\n    \"description\": \"documented at https://www.tensorflow.org/xla/operation_semantics#allreduce.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Int32, TF_Uint32 ]>\" },\n      { \"name\": \"group_assignment\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32, TF_Int32, TF_Uint32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_op\", \"type\": \"TF_AnyStrAttrOf<[Min, Max, Mul, Add, Mean]>\" },\n      { \"name\": \"mode\", \"type\": \"TF_AnyStrAttrOf<[CrossReplica, CrossReplicaAndPartition]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaBroadcastHelper\",\n    \"summary\": \"Helper operator for performing XLA-style broadcasts\",\n    \"description\": \"Broadcasts `lhs` and `rhs` to the same rank, by adding size 1 dimensions to\\nwhichever of `lhs` and `rhs` has the lower rank, using XLA's broadcasting rules\\nfor binary operators.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"broadcast_dims\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"lhs_output\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rhs_output\", \"type\": \"TF_NumberTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaCallModule\",\n    \"summary\": \"Invokes a StableHLO module.\",\n    \"description\": \"This op is used with JAX native serialization in a TensorFlow context with\\nstability guarantees.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"version\", \"type\": \"I64Attr\" },\n      { \"name\": \"module\", \"type\": \"StrAttr\" },\n      { \"name\": \"Sout\", \"type\": \"TypedArrayAttrBase<TF_ShapeAttr>\" },\n      { \"name\": \"dim_args_spec\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"platforms\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"function_list\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<SymbolRefAttr>, {}>\" },\n      { \"name\": \"has_token_input_output\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"disabled_checks\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<StrAttr>, {}>\" },\n      { \"name\": \"use_shardy_partitioner\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaClusterOutput\",\n    \"summary\": \"Operator that connects the output of an XLA computation to other consumer graph nodes.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaConcatND\",\n    \"summary\": \"Concats input tensor across all dimensions.\",\n    \"description\": \"An op which merges slices the input tensor based on the given num_splits\\nattribute, strips paddings optionally, and returns the merged tensor without\\npaddings.\\n\\nThis op may be generated via the TPU bridge.\\n\\nFor example, with `input` tensor:\\n```\\n[[0, 1],\\n [4, 5]]\\n[[2, 3],\\n [6, 7]]\\n[[8, 9],\\n [12, 13]]\\n[[10, 11],\\n [14, 15]]\\n```\\n`num_splits`:\\n```\\n[2, 2]\\n```\\nand `paddings`:\\n```\\n[1, 1]\\n```\\nthe expected `outputs` is:\\n```\\n[[0, 1, 2],\\n [4, 5, 6],\\n [8, 9, 10]]\\n```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_concats\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaConv\",\n    \"summary\": \"Wraps the XLA ConvGeneralDilated operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#conv_convolution\\n.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"window_strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"padding\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"feature_group_count\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StrAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaConvV2\",\n    \"summary\": \"Wraps the XLA ConvGeneralDilated operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#conv_convolution\\n.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"window_strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"padding\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"feature_group_count\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StrAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"StrAttr\" },\n      { \"name\": \"batch_group_count\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaCustomCallV2\",\n    \"summary\": \"Emits an HLO `CustomCall` operation with multiple outputs.\",\n    \"description\": \"As opposed to `XlaCustomCall`, this operation supports multiple outputs.\\n\\nSee `CustomCall` specification at\\n  https://tensorflow.org/xla/operation_semantics#customcall,\\nand `mhlo.custom_call` specification at\\n  https://tensorflow.org/mlir/hlo_ops#mhlocustom_call_mlirmhlocustomcallop.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"call_target_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"backend_config\", \"type\": \"StrAttr\" },\n      { \"name\": \"has_side_effect\", \"type\": \"BoolAttr\" },\n      { \"name\": \"result_shapes\", \"type\": \"TypedArrayAttrBase<TF_ShapeAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaDot\",\n    \"summary\": \"Wraps the XLA DotGeneral operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#dotgeneral\\n.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StrAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaDotV2\",\n    \"summary\": \"Wraps the XLA DotGeneral operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#dotgeneral\\n.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StrAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaDynamicSlice\",\n    \"summary\": \"Wraps the XLA DynamicSlice operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#dynamicslice\\n.\\n\\nDynamicSlice extracts a sub-array from the input array at dynamic\\nstart_indices. The size of the slice in each dimension is passed in\\nsize_indices, which specify the end point of exclusive slice intervals in each\\ndimension -- [start, start + size). The shape of start_indices must have rank 1,\\nwith dimension size equal to the rank of operand.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"start_indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"size_indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaDynamicUpdateSlice\",\n    \"summary\": \"Wraps the XLA DynamicUpdateSlice operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#dynamicupdateslice\\n.\\n\\nXlaDynamicUpdateSlice generates a result which is the value of the `input`\\noperand, with a slice update overwritten at `indices`. The shape of `update`\\ndetermines the shape of the sub-array of the result which is updated. The shape\\nof indices must be rank == 1, with dimension size equal to the rank of `input`.\\n\\nHandling of out-of-bounds slice indices is implementation-defined.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"update\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaEinsum\",\n    \"summary\": \"An op which supports basic einsum op with 2 inputs and 1 output.\",\n    \"description\": \"This op has better TPU performance since it doesn't have explicitly reshape and\\ntranspose operations as tf.einsum does.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex64, TF_Float32]>\" },\n      { \"name\": \"b\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex64, TF_Float32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"product\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Complex64, TF_Float32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"equation\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaGather\",\n    \"summary\": \"Wraps the XLA Gather operator documented at\",\n    \"description\": \"https://www.tensorflow.org/xla/operation_semantics#gather\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"start_indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"slice_sizes\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_numbers\", \"type\": \"StrAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaHostCompute\",\n    \"summary\": \"A pseudo-op to represent host-side computation in an XLA program.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ancestors\", \"type\": \"TypedArrayAttrBase<StrAttr>\" },\n      { \"name\": \"shapes\", \"type\": \"TypedArrayAttrBase<TF_ShapeAttr>\" },\n      { \"name\": \"shape_inference_graph\", \"type\": \"OptionalAttr<SymbolRefAttr>\" },\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"send_key\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"recv_key\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"cost_estimate_ns\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1000000>\" },\n      { \"name\": \"tpu_core\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaKeyValueSort\",\n    \"summary\": \"Wraps the XLA Sort operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#sort\\n.\\n\\nSorts a tensor. Currently only sorts in ascending order are supported.\",\n    \"operands\": [\n      { \"name\": \"keys\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"values\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"sorted_keys\", \"type\": \"TF_IntOrFpTensor\" },\n      { \"name\": \"sorted_values\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaLaunch\",\n    \"summary\": \"XLA Launch Op. For use by the XLA JIT only.\",\n    \"operands\": [\n      { \"name\": \"constants\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"resources\", \"type\": \"Variadic<TF_ResourceTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaLaunchV2\",\n    \"summary\": \"XLA Launch Op. For use by the XLA JIT only.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"constants\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"resources\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"function\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaLocalSparseDenseMatmul\",\n    \"summary\": \"Performs embedding lookup on SparseCore for a single table.\",\n    \"operands\": [\n      { \"name\": \"embedding_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0x7fffffff>\" },\n      { \"name\": \"is_univalent\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"T\", \"type\": \"TypeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaOptimizationBarrier\",\n    \"summary\": \"Wraps the XLA OptimizationBarrier operator.\",\n    \"description\": \"Documented at https://www.tensorflow.org/xla/operation_semantics#optimizationbarrier.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TF_Tensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaPad\",\n    \"summary\": \"Wraps the XLA Pad operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#pad\\n.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"padding_value\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"padding_low\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"padding_high\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"padding_interior\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaRecv\",\n    \"summary\": \"Receives the named tensor from another XLA computation. Wraps the XLA Recv\",\n    \"description\": \"operator documented at\\n https://www.tensorflow.org/performance/xla/operation_semantics#recv .\",\n    \"results\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaRecvFromHost\",\n    \"summary\": \"An op to receive a tensor from the host.\",\n    \"description\": \"output: the tensor that will be received from the host.\\nToutput: element type for output.\\nshape: shape for output.\\nkey: A unique identifier for this region used to match up host transfers.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"key\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaRecvTPUEmbeddingActivations\",\n    \"summary\": \"An op that receives embedding activations on the TPU.\",\n    \"description\": \"The TPU system performs the embedding lookups and aggregations. The results of\\nthese aggregations are visible to the Tensorflow Graph as the outputs of a\\nXlaRecvTPUEmbeddingActivations Op. This op returns a list containing one\\nTensor of activations per table specified in the model.\",\n    \"operands\": [\n      { \"name\": \"deduplication_data\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Float32Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaRecvTPUEmbeddingDeduplicationData\",\n    \"summary\": \"Receives deduplication data (indices and weights) from the embedding core.\",\n    \"description\": \"The deduplication data is a Tensor with type=DT_VARIANT. The tensor itself is an\\nXLA nested tuple containing N elements (where N is the ratio of the number of\\nembedding to tensor cores per TPU chip). Each element of the nested tuple is a\\ntuple of rank 1 tensors. Each tensor either contains indices (DT_UINT32) for\\nembedding lookup on the TensorCore or weights (DT_FLOAT) to apply to the output\\nof the embedding lookup operation.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaReduce\",\n    \"summary\": \"Wraps the XLA Reduce operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#reduce .\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"init_value\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions_to_reduce\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"reducer\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaReducePrecision\",\n    \"summary\": \"Wraps the XLA ReducePrecision operator\",\n    \"description\": \"documented at https://www.tensorflow.org/xla/operation_semantics#reduceprecision.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exponent_bits\", \"type\": \"I64Attr\" },\n      { \"name\": \"mantissa_bits\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaReduceScatter\",\n    \"summary\": \"Wraps the XLA ReduceScatter operator\",\n    \"description\": \"documented at https://www.tensorflow.org/xla/operation_semantics#reducescatter.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Float16, TF_Float32, TF_Int32, TF_Uint32 ]>\" },\n      { \"name\": \"group_assignment\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"scatter_dimension\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Float16, TF_Float32, TF_Int32, TF_Uint32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_op\", \"type\": \"TF_AnyStrAttrOf<[Min, Max, Mul, Add, Mean]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaReduceWindow\",\n    \"summary\": \"Wraps the XLA ReduceWindow operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#reducewindow .\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"init_value\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"window_dimensions\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"window_strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"base_dilations\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"window_dilations\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"padding\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"computation\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaRemoveDynamicDimensionSize\",\n    \"summary\": \"Inverse of XlaSetDynamicDimensionSize.\",\n    \"description\": \"Make an xla bounded dynamic dimension into a static dimension. The bound of the\\nsize of dimension `dim_index` becomes the static dimension size.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"dim_index\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaReplicaId\",\n    \"summary\": \"Replica ID.\",\n    \"results\": [\n      { \"name\": \"id\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaRngBitGenerator\",\n    \"summary\": \"Stateless PRNG bit generator.\",\n    \"description\": \"Wraps the XLA RngBitGenerator operator, documented at\\n https://www.tensorflow.org/performance/xla/operation_semantics#rngbitgenerator.\",\n    \"operands\": [\n      { \"name\": \"algorithm\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"initial_state\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"shape\", \"type\": \"TF_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_key\", \"type\": \"TF_Uint64Tensor\" },\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Int32, TF_Int64, TF_Int8, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaScatter\",\n    \"summary\": \"Wraps the XLA Scatter operator documented at\",\n    \"description\": \"https://www.tensorflow.org/xla/operation_semantics#scatter.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" },\n      { \"name\": \"scatter_indices\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"updates\", \"type\": \"TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TensorOf<[TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"update_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"dimension_numbers\", \"type\": \"StrAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSelectAndScatter\",\n    \"summary\": \"Wraps the XLA SelectAndScatter operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#selectandscatter\\n.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"window_dimensions\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"window_strides\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"padding\", \"type\": \"TF_I32OrI64Tensor\" },\n      { \"name\": \"source\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"init_value\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"select\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"scatter\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSelfAdjointEig\",\n    \"summary\": \"Computes the eigen decomposition of a batch of self-adjoint matrices\",\n    \"description\": \"(Note: Only real inputs are supported).\\n\\nComputes the eigenvalues and eigenvectors of the innermost N-by-N matrices in\\ntensor such that tensor[...,:,:] * v[..., :,i] = e[..., i] * v[...,:,i], for\\ni=0...N-1.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"w\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"v\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower\", \"type\": \"BoolAttr\" },\n      { \"name\": \"max_iter\", \"type\": \"I64Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSend\",\n    \"summary\": \"Sends the named tensor to another XLA computation. Wraps the XLA Send operator\",\n    \"description\": \"documented at\\n https://www.tensorflow.org/performance/xla/operation_semantics#send .\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tensor_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSendToHost\",\n    \"summary\": \"An op to send a tensor to the host.\",\n    \"description\": \"input: the tensor that will be sent to the host.\\nTinput: element type for input.\\nkey: A unique identifier for this region used to match up host transfers.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSendTPUEmbeddingGradients\",\n    \"summary\": \"An op that performs gradient updates of embedding tables.\",\n    \"description\": \"The gradients argument is a TensorList having the same length and shapes as the\\nreturn value of XlaRecvTPUEmbeddingActivations, but contains gradients of the\\nmodel's loss with respect to the embedding activations. The embedding tables are\\nupdated from these gradients via the optimizer specified in the\\nTPUEmbeddingConfiguration proto given to tpu.initialize_system.\",\n    \"operands\": [\n      { \"name\": \"gradients\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"learning_rates\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"deduplication_data\", \"type\": \"TF_VariantTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"config\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSetBound\",\n    \"summary\": \"Set a bound for the given input value as a hint to Xla compiler,\",\n    \"description\": \"returns the same value.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"bound\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Int32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSetDynamicDimensionSize\",\n    \"summary\": \"Make a static dimension into a xla bounded dynamic dimension.\",\n    \"description\": \"The current static dimension size will become the bound and the second\\n        operand becomes the dynamic size of the dimension.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"dim_index\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"size\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSharding\",\n    \"summary\": \"An op which shards the input based on the given sharding attribute.\\n\\nSince TF runtime still relies on V1 sharding but the compiler requires V2\\nSharding to support the new partitioner Shardy, when the op can reach both the\\ncompiler and the runtime, we record V1 sharding attribute in _XlaSharding and V2\\nsharding attribute in _XlaShardingV2, and verify that they are equivalent when\\nthey both exist and _XlaShardingV2 is used.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sharding\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"_XlaSharding\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"_XlaShardingV2\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSort\",\n    \"summary\": \"Wraps the XLA Sort operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#sort\\n.\\n\\nSorts a tensor. Currently only sorts in ascending order are supported.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseActivationsUnstack\",\n    \"summary\": \"XlaSparseActivationsUnstackOp attempts to fuse transpose, relayout,\\n    conversion, stacking and optionally interleaving of the embedding\\n    activations, while also offloading this work to SparseCore.\\n\\n    The op assumes its operand is in SparseCore layout.\\n    The output is a tuple of tensors in TensorCore layout.\",\n    \"operands\": [\n      { \"name\": \"stacked_activations\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"unstacked_embedding_activations\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_tables\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"sample_counts\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"features\", \"type\": \"ConfinedAttr<TypedArrayAttrBase<I64Attr>, [ArrayMinCount<1>]>\" },\n      { \"name\": \"interleaved\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseCoreAdagrad\",\n    \"summary\": \"aaa\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gradient\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"feature_width\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseCoreAdagradMomentum\",\n    \"summary\": \"aaa\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gradient\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"beta_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momentum\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momentum\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"feature_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"use_nesterov\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta_2\", \"type\": \"F32Attr\" },\n      { \"name\": \"exponent\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseCoreAdam\",\n    \"summary\": \"aaa\",\n    \"operands\": [\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gradient\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momentum\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocity\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"beta_1\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"beta_2\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"epsilon\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_velocity\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momentum\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"feature_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"use_sum_inside_sqrt\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseCoreFtrl\",\n    \"summary\": \"aaa\",\n    \"operands\": [\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gradient\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"beta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate_power\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"l2_regularization_strength\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_linear\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"feature_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"multiply_linear_by_learning_rate\", \"type\": \"BoolAttr\" },\n      { \"name\": \"l1_regularization_strength\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseCoreSgd\",\n    \"summary\": \"aaa\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"gradient\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"feature_width\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcGradWithAdagradAndCsrInput\",\n    \"summary\": \"This op back-propagates the activation gradients to the embedding table and the combiner weights.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"combiner_weights_learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"combiner_table_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"combiner_weights_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcGradWithAdagradMomentumAndCsrInput\",\n    \"summary\": \"This op back-propagates the activation gradients to the embedding table and the combiner weights.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"combiner_weights_learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"use_nesterov\", \"type\": \"BoolAttr\" },\n      { \"name\": \"exponent\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta1\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta2\", \"type\": \"F32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"combiner_table_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"combiner_weights_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcGradWithAdamAndCsrInput\",\n    \"summary\": \"This op back-propagates the activation gradients to the embedding table and the combiner weights.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"combiner_weights_learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocity\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_velocity\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"use_sum_inside_sqrt\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta1\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta2\", \"type\": \"F32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"combiner_table_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"combiner_weights_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcGradWithCsrInput\",\n    \"summary\": \"This op back-propagates the activation gradients to the embedding table and the combiner weights.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"tables\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"hyperparameters\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"combiner_weights_learning_rate\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_tables\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"updated_weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"combiner_table_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"combiner_weights_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"optimizer_custom_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcGradWithFtrlAndCsrInput\",\n    \"summary\": \"This op back-propagates the activation gradients to the embedding table and the combiner weights.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"combiner_weights_learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_linear\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"multiply_linear_by_learning_rate\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta\", \"type\": \"F32Attr\" },\n      { \"name\": \"learning_rate_power\", \"type\": \"F32Attr\" },\n      { \"name\": \"l1_regularization_strength\", \"type\": \"F32Attr\" },\n      { \"name\": \"l2_regularization_strength\", \"type\": \"F32Attr\" },\n      { \"name\": \"combiner_table_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"combiner_weights_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcGradWithSgdAndCsrInput\",\n    \"summary\": \"This op back-propagates the activation gradients to the embedding table and the combiner weights.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_weights\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"combiner_weights_learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"combiner_table_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"combiner_weights_vjp_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulCustomCombinerOnTcWithCsrInput\",\n    \"summary\": \"This op looks up the embedding vectors on SparseCores and performs the given combiner computation on TensorCores.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_pos_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"preserved_valencies\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"preserved_vectors\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"max_valency\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"num_weights\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"quantization_config_low\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"quantization_config_high\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"quantization_config_num_buckets\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"combiner_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithAdagradAndCsrInput\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithAdagradAndStaticBufferSize\",\n    \"summary\": \"A XLA op which performs the Adagrad optimizer update for the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithAdagradMomentumAndCsrInput\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momenta\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_nesterov\", \"type\": \"BoolAttr\" },\n      { \"name\": \"exponent\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta1\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta2\", \"type\": \"F32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithAdagradMomentumAndStaticBufferSize\",\n    \"summary\": \"A XLA op which performs the Adagrad momentumoptimizer update for the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momenta\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_nesterov\", \"type\": \"BoolAttr\" },\n      { \"name\": \"exponent\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta1\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta2\", \"type\": \"F32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithAdamAndCsrInput\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocity\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_velocity\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_sum_inside_sqrt\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta1\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta2\", \"type\": \"F32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithAdamAndStaticBufferSize\",\n    \"summary\": \"A XLA op which performs the Adam optimizer update for the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"velocity\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_momenta\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_velocity\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_sum_inside_sqrt\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta1\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta2\", \"type\": \"F32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithCsrInput\",\n    \"summary\": \"A XLA op which performs the custom optimizer per-row update for the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"tables\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"hyperparameters\", \"type\": \"Variadic<TF_Float32Tensor>\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_tables\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"custom_computation\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithFtrlAndCsrInput\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_linear\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiply_linear_by_learning_rate\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta\", \"type\": \"F32Attr\" },\n      { \"name\": \"learning_rate_power\", \"type\": \"F32Attr\" },\n      { \"name\": \"l1_regularization_strength\", \"type\": \"F32Attr\" },\n      { \"name\": \"l2_regularization_strength\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithFtrlAndStaticBufferSize\",\n    \"summary\": \"A XLA op which performs the Ftrl optimizer update for the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"linear\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_accumulator\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"updated_linear\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiply_linear_by_learning_rate\", \"type\": \"BoolAttr\" },\n      { \"name\": \"beta\", \"type\": \"F32Attr\" },\n      { \"name\": \"learning_rate_power\", \"type\": \"F32Attr\" },\n      { \"name\": \"l1_regularization_strength\", \"type\": \"F32Attr\" },\n      { \"name\": \"l2_regularization_strength\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithSgdAndCsrInput\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulGradWithSgdAndStaticBufferSize\",\n    \"summary\": \"A XLA op which performs the SGD optimizer update for the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"activation_gradients\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"learning_rate\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated_embedding_table\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"clip_weight_min\", \"type\": \"F32Attr\" },\n      { \"name\": \"clip_weight_max\", \"type\": \"F32Attr\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulWithCsrInput\",\n    \"summary\": \"aaa\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"quantization_config_low\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"quantization_config_high\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"quantization_config_num_buckets\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseDenseMatmulWithStaticBufferSize\",\n    \"summary\": \"A XLA op which performs the dense-sparse matrix multiplication.\",\n    \"operands\": [\n      { \"name\": \"row_pointers\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_sample_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_token_ids\", \"type\": \"TF_Int32Tensor\" },\n      { \"name\": \"sorted_gains\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"embedding_table\", \"type\": \"TF_Float32Tensor\" },\n      { \"name\": \"num_minibatches_per_physical_sparse_core\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"activations\", \"type\": \"TF_Float32Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_size\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<0>]>\" },\n      { \"name\": \"quantization_config_low\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"quantization_config_high\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"quantization_config_num_buckets\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"max_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"max_unique_ids_per_sparse_core\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"table_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSparseGradientsStack\",\n    \"summary\": \"XlaSparseGradientsStackOp attempts to fuse transpose, relayout, conversion,\\n    unstacking and optionally interleaving of the embedding gradients, while\\n    also offloading this work to SparseCore.\\n\\n    The op assumes its operands are in TensoreCore layout.\\n    The output is in SparseCore layout.\",\n    \"operands\": [\n      { \"name\": \"unstacked_gradients\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"stacked_gradients\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_tables\", \"type\": \"ConfinedAttr<I64Attr, [IntMinValue<1>]>\" },\n      { \"name\": \"interleaved\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSplitND\",\n    \"summary\": \"Splits input tensor across all dimensions.\",\n    \"description\": \"An op which slices the input tensor based on the given num_splits attribute,\\npads slices optionally, and returned the slices. Slices are returned in\\nrow-major order.\\n\\nThis op may be generated via the TPU bridge.\\n\\nFor example, with `input` tensor:\\n```\\n[[0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8]]\\n```\\n`num_splits`:\\n```\\n[2, 2]\\n```\\nand `paddings`:\\n```\\n[1, 1]\\n```\\nthe expected `outputs` is:\\n```\\n[[0, 1],\\n [3, 4]]\\n[[2, 0],\\n [5, 0]]\\n[[6, 7],\\n [0, 0]]\\n[[8, 0],\\n [0, 0]]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_splits\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"paddings\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSpmdFullToShardShape\",\n    \"summary\": \"An op used by XLA SPMD partitioner to switch from automatic partitioning to\",\n    \"description\": \"manual partitioning. It annotates the input (full-shape, to be automatically\\npartitioned) with the same sharding used by manual partitioning, and outputs a\\nshard-shaped tensor to be consumed by later manually-partitioned ops. If the\\nshape is not evenly partitionable, the padding region will be masked with 0s.\\nThe conversion can happen partially in subgroups, by specifying the dim\\nattribute, where only that dim will be converted.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"manual_sharding\", \"type\": \"StrAttr\" },\n      { \"name\": \"dim\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"unspecified_dims\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSpmdShardToFullShape\",\n    \"summary\": \"An op used by XLA SPMD partitioner to switch from manual partitioning to\",\n    \"description\": \"automatic partitioning. It converts the shard-shaped, manually partitioned input\\ninto full-shaped tensor to be partitioned automatically with the same sharding\\nused by manual partitioning. The conversion can happen partially in subgroups,\\nby specifying the dim attribute, where only that dim will be converted.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TF_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"manual_sharding\", \"type\": \"StrAttr\" },\n      { \"name\": \"full_shape\", \"type\": \"TF_ShapeAttr\" },\n      { \"name\": \"dim\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, -1>\" },\n      { \"name\": \"unspecified_dims\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaSvd\",\n    \"summary\": \"Computes the eigen decomposition of a batch of self-adjoint matrices\",\n    \"description\": \"(Note: Only real inputs are supported).\\n\\nComputes the eigenvalues and eigenvectors of the innermost M-by-N matrices in\\ntensor such that tensor[...,:,:] = u[..., :, :] * Diag(s[..., :]) * Transpose(v[...,:,:]).\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"s\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"u\", \"type\": \"TF_NumberTensor\" },\n      { \"name\": \"v\", \"type\": \"TF_NumberTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_iter\", \"type\": \"I64Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"precision_config\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaVariadicReduce\",\n    \"summary\": \"Wraps the variadic XLA Reduce operator.\",\n    \"description\": \"Semantics are documented at\\n https://www.tensorflow.org/performance/xla/operation_semantics#variadic_reduce.\\n\\nThis version is limited to operands of the same dtype.\\nXlaVariadicReduceV2 is a version that supports heterogeneous operands.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TensorOf < [ TF_Bfloat16 , TF_Bool , TF_Complex128 , TF_Complex64 , TF_Float16 , TF_Float32 , TF_Float64 , TF_Int16 , TF_Int32 , TF_Int64 , TF_Int8 , TF_Qint16 , TF_Qint32 , TF_Qint8 , TF_Quint16 , TF_Quint8 , TF_Uint16 , TF_Uint32 , TF_Uint64 , TF_Uint8 ] >>\" },\n      { \"name\": \"init_value\", \"type\": \"Variadic<TensorOf < [ TF_Bfloat16 , TF_Bool , TF_Complex128 , TF_Complex64 , TF_Float16 , TF_Float32 , TF_Float64 , TF_Int16 , TF_Int32 , TF_Int64 , TF_Int8 , TF_Qint16 , TF_Qint32 , TF_Qint8 , TF_Quint16 , TF_Quint8 , TF_Uint16 , TF_Uint32 , TF_Uint64 , TF_Uint8 ] >>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<TensorOf<[ TF_Bfloat16, TF_Bool, TF_Complex128, TF_Complex64, TF_Float16, TF_Float32, TF_Float64, TF_Int16, TF_Int32, TF_Int64, TF_Int8, TF_Qint16, TF_Qint32, TF_Qint8, TF_Quint16, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8 ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions_to_reduce\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"reducer\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaVariadicReduceV2\",\n    \"summary\": \"Wraps the variadic XLA Reduce operator.\",\n    \"description\": \"Semantics are documented at\\n https://www.tensorflow.org/performance/xla/operation_semantics#variadic_reduce.\\n\\nThis is an expanded version of XlaVariadicReduce, with support for\\noperands of different dtypes, and improved shape inference.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions_to_reduce\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"reducer\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"tf.XlaVariadicSort\",\n    \"summary\": \"Wraps the XLA Sort operator, documented at\",\n    \"description\": \"https://www.tensorflow.org/performance/xla/operation_semantics#sort\\n.\\n\\nSorts one or more tensors, with support for custom comparator, dimension, and\\nis_stable attributes.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TF_Tensor>\" },\n      { \"name\": \"dimension\", \"type\": \"TF_Int32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TF_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"comparator\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"is_stable\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Xlog1py\",\n    \"summary\": \"Returns 0 if x == 0, and x * log1p(y) otherwise, elementwise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Xlogy\",\n    \"summary\": \"Returns 0 if x == 0, and x * log(y) otherwise, elementwise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_FpOrComplexTensor\" },\n      { \"name\": \"y\", \"type\": \"TF_FpOrComplexTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_FpOrComplexTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Yield\",\n    \"summary\": \"Yield operation\",\n    \"description\": \"The \\\"yield\\\" operation represents a return operation within the conditional\\n    and body of structured control flow (e.g., if and while). The operation\\n    takes a variable number of operands and produces no results. The number and\\n    types of inputs must match the signature of the operation that contains the\\n    region.\"\n  },\n  {\n    \"name\": \"tf.ZerosLike\",\n    \"summary\": \"Returns a tensor of zeros with the same shape and type as x.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TF_Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tf.Zeta\",\n    \"summary\": \"Compute the Hurwitz zeta function \\\\\\\\(\\\\zeta(x, q)\\\\\\\\).\",\n    \"description\": \"The Hurwitz zeta function is defined as:\\n\\n\\n\\\\\\\\(\\\\zeta(x, q) = \\\\sum_{n=0}^{\\\\infty} (q + n)^{-x}\\\\\\\\)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TF_F32OrF64Tensor\" },\n      { \"name\": \"q\", \"type\": \"TF_F32OrF64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"z\", \"type\": \"TF_F32OrF64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfd.convert_tft_to_dht\",\n    \"summary\": \"convert TF tensor to TFRT DHT tensor operation\",\n    \"description\": \"The \\\"tfd.convert_tft_to_dht\\\" operation converts a TF tensor to a TFRT\\n    DenseHostTensor.\\n\\n    It takes as input a TF Tensor and an input chain, and returns a converted\\n    TFRT DHT tensor and an output chain.\\n\\n    Example:\\n      %dht, %c0 = \\\"tfd.convert_tft_to_dht\\\"(%tft, %c)\\n      : (!tfd.tf_tensor, !tfrt.chain) -> (!dht.host_tensor, !tfrt.chain)\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ]\n  },\n  {\n    \"name\": \"tfd.delegate_kernel\",\n    \"summary\": \"delegate kernel operation\",\n    \"description\": \"The \\\"tfd.delegate_kernel\\\" operation takes an input chain, and arbitrary\\n    number of input arguments, and runs a specified TF op via TFE C API. It\\n    returns an output chain and variable number of outputs from the TF op.\\n\\n    The input arguments and attributes are passed to the TF op. The outputs are\\n    outputs of the TF op.\\n\\n    Note that `_name` is a required attribute specifying the TF op to run.\\n    TFRT attributes are sorted alphabetically, passed in as positional\\n    attributes to the TFRT kernel, rather than as named attributes.\\n\\n    Example:\\n      To run \\\"tf.MatMul\\\" op, which has two boolean attributes,\\n        1. Set _name = \\\"MatMul\\\"\\n        2. For each TF attribute, split it into two attributes, one for name of\\n           the TF attribute, and the other for the type and value of the\\n           attribute value. Attribute value is a string with the format of\\n           \\\"type$val\\\", where type can be \\\"bool\\\", \\\"string\\\", \\\"tfdtype\\\", \\\"tfshape\\\",\\n           \\\"tftensor\\\".\\n           The value serialization format can be found in attr_util.h.\\n\\n      %out_c, %out_tensor = \\\"tfd.delegate_kernel\\\"(\\n        %in_c, %in1_tensor, %in2_tensor) {\\n        _name = \\\"MatMul\\\",\\n        attr1_name = \\\"transpose_a\\\", attr1_value = \\\"bool$false\\\",\\n        attr2_name = \\\"transpose_b\\\", attr2_value = \\\"bool$false\\\"\\n      } : (!tfrt.chain, !tfd.tf_tensor, !tfd.tf_tensor) -> (\\n        !tfrt.chain, !tfd.tf_tensor)\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"result1\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfd.init_eager_context\",\n    \"summary\": \"eager context initialization operation\",\n    \"description\": \"The \\\"tfd.init_eager_context\\\" operation takes an input chain, creates and\\n    initializes the TF EagerContext and returns an output chain.\\n\\n    Example:\\n      %c1 = \\\"tfd.init_eager_context\\\"(%c0): (!tfrt.chain) -> !tfrt.chain\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ]\n  },\n  {\n    \"name\": \"tfd.move_dht_to_tft\",\n    \"summary\": \"convert TFRT DHT tensor to DHT tensor operation\",\n    \"description\": \"The \\\"tfd.move_dht_to_tft\\\" operation moves a TFRT tensor into a TF Tensor.\\n\\n    It takes as input a TFRT Tensor and an input chain, and returns a TF tensor\\n    with the same underlying buffer and an output chain.\\n\\n    Example:\\n      %dht, %c0 = \\\"tfd.convert_tft_to_dht\\\"(%tft, %c)\\n        : (!tfd.tf_tensor, !tfrt.chain) -> (!dht.host_tensor, !tfrt.chain)\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TfTensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ]\n  },\n  {\n    \"name\": \"tfd.print_tft\",\n    \"summary\": \"print TF tensor operation\",\n    \"description\": \"The \\\"tfd.print_tft\\\" operation prints the input TF tensor. It takes an input\\n    TF tensor to be printed and an input chain, and returns an output chain.\\n\\n    Example:\\n      %c1 = \\\"tfd.print_tft\\\"(%t, %c) : (!tfd.tf_tensor, !tfrt.chain) -> !tfrt.chain\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.Case\",\n    \"summary\": \"A case operation, in functional form\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"TFGraph_OpaqueTensorOr<I32Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branches\", \"type\": \"TypedArrayAttrBase<TFType_FuncAttr, an array of functions>\" },\n      { \"name\": \"Tin\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"Tout\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.CaseRegion\",\n    \"summary\": \"A case op with graph regions.\",\n    \"description\": \"A `Case` operation in region form. `Case` takes one data operand, an index,\\n    and executes the region corresponding to that index. The execution of any\\n    of its regions is blocked on the operation's control operands.\\n\\n    The regions have no block arguments; everything that escapes the scope is an\\n    implicit capture. All regions return values of the same types which are\\n    compatible with the result types of the `Case` operation.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes in arrays. There are never region argument attributes, and\\n    the number of result attributes must match the number of data results.\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32Tensor\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branch_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"region_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFGraph_RegionAttrs, case region preserved attributes>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"assemblyFormat\": \"$branch_index (` ` `[` $ctls^ `]`)?\\n      $branches\\n    attr-dict `:` functional-type($branch_index, $outs)\"\n  },\n  {\n    \"name\": \"tfg.condition\",\n    \"summary\": \"TF graph terminator op for while-loop condition regions.\",\n    \"description\": \"The `condition` operation is a special terminator for the condition region\\n    of while loops. Its only purpose is to support reasoning about region\\n    control-flow by forwarding the arguments to the condition region to the body\\n    region or back to the parent operation's results.\\n\\n    The `condition` operation accepts one `cond` data input, which if true, will\\n    cause the execution to branch to the loop body, and if false, will cause the\\n    execution to return to the parent operation.\\n\\n    There must be the same number of arguments `args` as there are operands and\\n    results in the parent `While` loop.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1Tensor\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$cond `:` type($cond) (` ` `(` $args^ `)`)?\\n                          (`[` $ctls^ `]`)? attr-dict (`:` type($args)^)?\"\n  },\n  {\n    \"name\": \"tfg.For\",\n    \"summary\": \"A functional for-loop operation.\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"TFGraph_OpaqueTensorOr<I32Tensor>\" },\n      { \"name\": \"limit\", \"type\": \"TFGraph_OpaqueTensorOr<I32Tensor>\" },\n      { \"name\": \"delta\", \"type\": \"TFGraph_OpaqueTensorOr<I32Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"body\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"T\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.ForRegion\",\n    \"description\": \"A `For` operation in region form. The operation takes three scalar `i32`\\n    operands: a lower bound, an upper bound, and a step. As well, it takes N\\n    operands and produces N results of the same types. The loop body region has\\n    a scalar `i32` block argument and its corresponding control token and N data\\n    block arguments of the same types as the N data operands and N results. The\\n    scalar `i32` block argument is the current loop index.\\n\\n    The operation is blocked on its control operands. The execution enters the\\n    loop body, which must return N data results. The values are either fed into\\n    the next iteration of the body or taken as the operation's results.\\n\\n    For the body region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. The number of argument attributes must match the number\\n    of data operands and the number of result attributes must match the number\\n    of data results.\\n\\n    Values can be propagated through the loop bodies as iteration variables,\\n    but the regions allow implicitly captured values as well.\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"I32Tensor\" },\n      { \"name\": \"limit\", \"type\": \"I32Tensor\" },\n      { \"name\": \"delta\", \"type\": \"I32Tensor\" },\n      { \"name\": \"init\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"body_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`(` $init^ `)`)? (`[` $ctls^ `]`)?\\n    `from` $start `to` $limit `by` $delta\\n      $body_region\\n    attr-dict `:` `(` type($start) `,` type($limit) `,` type($delta)\\n    (`,` type($init)^)? `)` (`->` `(` type($outs)^ `)`)?\"\n  },\n  {\n    \"name\": \"tfg.func\",\n    \"summary\": \"Define a function as modeled by FunctionDef.\",\n    \"description\": \"This operation is modeling a function definition, corresponding to the\\n    FunctionDef proto. It defines a region `body` which contains an unordered\\n    list of nodes forming a TensorFlow graph.\\n    The body still has a return operation as terminator which must always be\\n    the last operation.\\n\\n    A function can be generic if it specifies the `generic` attribute. Such\\n    function is akin to a C++ template: it need \\\"instantiation attributes\\\" to be\\n    specified at each call site in order to make it into a concrete function,\\n    see `tensorflow::InstantiateFunction()` for more info.\",\n    \"attributes\": [\n      { \"name\": \"generic\", \"type\": \"UnitAttr\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"description\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"is_stateful\", \"type\": \"UnitAttr\" },\n      { \"name\": \"gradient\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"resource_arg_unique_ids_keys\", \"type\": \"OptionalAttr<I32ElementsAttr>\" },\n      { \"name\": \"resource_arg_unique_ids_values\", \"type\": \"OptionalAttr<I32ElementsAttr>\" },\n      { \"name\": \"control_output\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfg.get_result\",\n    \"summary\": \"Extract a value out of an opaque tensor in a generic Function.\",\n    \"description\": \"The `get_result` operation exists in generic functions before instantiation,\\n    when the number of output per node isn't known yet. In generic function\\n    nodes define a single SSA value which is then \\\"unpacked\\\" by name using this\\n    operation.\\n    Example:\\n\\n    ```mlir\\n    %Switch, %ctl_1 = tfg.Switch(%G_z, %G_z) name = \\\"cond/Switch\\\"\\n    %s_true = tfg.get_result %Switch \\\"output_true” : 0\\n    %s_false = tfg.get_result %Switch \\\"output_false” : 0\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"OpaqueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"OpaqueTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"number\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` $name `:` $number attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tfg.graph\",\n    \"summary\": \"Define a flat graph of operations\",\n    \"description\": \"This operation is modeling a unordered list of nodes forming a TensorFlow\\n    graph. This corresponds to the GraphDef proto definition minus the\\n    FunctionDefLibrary.\",\n    \"attributes\": [\n      { \"name\": \"version\", \"type\": \"TFType_VersionAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"nodes\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"qualified($version) attr-dict-with-keyword $nodes\"\n  },\n  {\n    \"name\": \"tfg.If\",\n    \"summary\": \"An if operation, in functional form.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TFGraph_OpaqueTensorOr<I1Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_branch\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"else_branch\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"Tcond\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"Tin\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"Tout\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.IfRegion\",\n    \"summary\": \"An if-then-else op with graph regions.\",\n    \"description\": \"An `If` operation in region form. `If` takes on data operand, which if true,\\n    executes the `then` region, otherwise the `else` region. The execution of\\n    either region is blocked on the operation's control operands.\\n\\n    The regions have no block arguments; everything that escapes the scope is an\\n    implicit capture. Both regions return values of the same types which are\\n    compatible with the result types of the `If` operation.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. There are never region argument attributes, and the\\n    number of result attributes must match the number of data results.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1Tensor\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"else_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"then_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" },\n      { \"name\": \"else_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"assemblyFormat\": \"$cond (` ` `[` $ctls^ `]`)? `then`\\n      $then_region\\n    `else`\\n      $else_region\\n    attr-dict `:` functional-type($cond, $outs)\"\n  },\n  {\n    \"name\": \"tfg.return\",\n    \"summary\": \"Return values from a Function.\",\n    \"description\": \"The `return` operation represents a return operation within a function.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number must match the signature of the function that contains\\n    the operation. The types of the input to the call must be compatible with\\n    the function signature in terms of shape and matching the element type, and\\n    similarly for the function results,\",\n    \"attributes\": [\n      { \"name\": \"control_ret_attrs\", \"type\": \"TypedArrayAttrBase<DictionaryAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfg.StatefulCase\",\n    \"summary\": \"A stateful case operation, in functional form\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"TFGraph_OpaqueTensorOr<I32Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branches\", \"type\": \"TypedArrayAttrBase<TFType_FuncAttr, an array of functions>\" },\n      { \"name\": \"Tin\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"Tout\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.StatefulCaseRegion\",\n    \"summary\": \"A stateful case op with graph regions.\",\n    \"description\": \"A `Case` operation in region form. `Case` takes one data operand, an index,\\n    and executes the region corresponding to that index. The execution of any\\n    of its regions is blocked on the operation's control operands.\\n\\n    The regions have no block arguments; everything that escapes the scope is an\\n    implicit capture. All regions return values of the same types which are\\n    compatible with the result types of the `Case` operation.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes in arrays. There are never region argument attributes, and\\n    the number of result attributes must match the number of data results.\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32Tensor\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branch_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"region_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFGraph_RegionAttrs, case region preserved attributes>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"assemblyFormat\": \"$branch_index (` ` `[` $ctls^ `]`)?\\n      $branches\\n    attr-dict `:` functional-type($branch_index, $outs)\"\n  },\n  {\n    \"name\": \"tfg.StatefulIf\",\n    \"summary\": \"A stateful if operation, in functional form.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TFGraph_OpaqueTensorOr<I1Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_branch\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"else_branch\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"Tcond\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"Tin\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"Tout\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.StatefulIfRegion\",\n    \"summary\": \"A stateful if-then-else op with graph regions.\",\n    \"description\": \"An `If` operation in region form. `If` takes on data operand, which if true,\\n    executes the `then` region, otherwise the `else` region. The execution of\\n    either region is blocked on the operation's control operands.\\n\\n    The regions have no block arguments; everything that escapes the scope is an\\n    implicit capture. Both regions return values of the same types which are\\n    compatible with the result types of the `If` operation.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. There are never region argument attributes, and the\\n    number of result attributes must match the number of data results.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1Tensor\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"else_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"then_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" },\n      { \"name\": \"else_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"assemblyFormat\": \"$cond (` ` `[` $ctls^ `]`)? `then`\\n      $then_region\\n    `else`\\n      $else_region\\n    attr-dict `:` functional-type($cond, $outs)\"\n  },\n  {\n    \"name\": \"tfg.StatefulWhile\",\n    \"summary\": \"A functional stateful while loop operation.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cond\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"body\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" },\n      { \"name\": \"T\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.StatefulWhileRegion\",\n    \"summary\": \"A stateful region-based while loop operation.\",\n    \"description\": \"A `While` operation in region form. The operation takes N operands and\\n    produces N results of the same types. Each region has N data block arguments\\n    and N corresponding control tokens.\\n\\n    The entry into the condition region is blocked on the operation's control\\n    operands. The operation always executes the condition region at least once\\n    with the arguments as the operation's data operands. If the condition region\\n    returns `true`, the body region is executed with the arguments provided to\\n    the condition region. The body region will branch back to the condition\\n    region with N results. If `false`, the condition region will branch back to\\n    the parent `While` operation with the argument values as results.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. The number of argument attributes must match the number\\n    of data operands and the number of result attributes must match the number\\n    of data results.\\n\\n    Values can be propagated through the loop bodies as iteration variables,\\n    but the regions allow implicitly captured values as well.\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" },\n      { \"name\": \"cond_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"body_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"cond_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" },\n      { \"name\": \"body_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`(` $init^ `)`)? (`[` $ctls^ `]`)?\\n      $cond_region\\n    `do`\\n      $body_region\\n    attr-dict (`:` functional-type($init, $outs)^)?\"\n  },\n  {\n    \"name\": \"tfg.StatelessCase\",\n    \"summary\": \"A stateless case operation, in functional form\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"TFGraph_OpaqueTensorOr<I32Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branches\", \"type\": \"TypedArrayAttrBase<TFType_FuncAttr, an array of functions>\" },\n      { \"name\": \"Tin\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"Tout\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.StatelessCaseRegion\",\n    \"summary\": \"A stateless case op with graph regions.\",\n    \"description\": \"A `Case` operation in region form. `Case` takes one data operand, an index,\\n    and executes the region corresponding to that index. The execution of any\\n    of its regions is blocked on the operation's control operands.\\n\\n    The regions have no block arguments; everything that escapes the scope is an\\n    implicit capture. All regions return values of the same types which are\\n    compatible with the result types of the `Case` operation.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes in arrays. There are never region argument attributes, and\\n    the number of result attributes must match the number of data results.\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32Tensor\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branch_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"region_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFGraph_RegionAttrs, case region preserved attributes>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"assemblyFormat\": \"$branch_index (` ` `[` $ctls^ `]`)?\\n      $branches\\n    attr-dict `:` functional-type($branch_index, $outs)\"\n  },\n  {\n    \"name\": \"tfg.StatelessIf\",\n    \"summary\": \"A stateless if operation, in functional form.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TFGraph_OpaqueTensorOr<I1Tensor>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_branch\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"else_branch\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"Tcond\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"Tin\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"Tout\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.StatelessIfRegion\",\n    \"summary\": \"A stateless if-then-else op with graph regions.\",\n    \"description\": \"An `If` operation in region form. `If` takes on data operand, which if true,\\n    executes the `then` region, otherwise the `else` region. The execution of\\n    either region is blocked on the operation's control operands.\\n\\n    The regions have no block arguments; everything that escapes the scope is an\\n    implicit capture. Both regions return values of the same types which are\\n    compatible with the result types of the `If` operation.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. There are never region argument attributes, and the\\n    number of result attributes must match the number of data results.\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1Tensor\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"then_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"else_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"then_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" },\n      { \"name\": \"else_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"assemblyFormat\": \"$cond (` ` `[` $ctls^ `]`)? `then`\\n      $then_region\\n    `else`\\n      $else_region\\n    attr-dict `:` functional-type($cond, $outs)\"\n  },\n  {\n    \"name\": \"tfg.StatelessWhile\",\n    \"summary\": \"A functional stateless while loop operation.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cond\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"body\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" },\n      { \"name\": \"T\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.StatelessWhileRegion\",\n    \"summary\": \"A stateless region-based while loop operation.\",\n    \"description\": \"A `While` operation in region form. The operation takes N operands and\\n    produces N results of the same types. Each region has N data block arguments\\n    and N corresponding control tokens.\\n\\n    The entry into the condition region is blocked on the operation's control\\n    operands. The operation always executes the condition region at least once\\n    with the arguments as the operation's data operands. If the condition region\\n    returns `true`, the body region is executed with the arguments provided to\\n    the condition region. The body region will branch back to the condition\\n    region with N results. If `false`, the condition region will branch back to\\n    the parent `While` operation with the argument values as results.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. The number of argument attributes must match the number\\n    of data operands and the number of result attributes must match the number\\n    of data results.\\n\\n    Values can be propagated through the loop bodies as iteration variables,\\n    but the regions allow implicitly captured values as well.\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" },\n      { \"name\": \"cond_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"body_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"cond_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" },\n      { \"name\": \"body_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`(` $init^ `)`)? (`[` $ctls^ `]`)?\\n      $cond_region\\n    `do`\\n      $body_region\\n    attr-dict (`:` functional-type($init, $outs)^)?\"\n  },\n  {\n    \"name\": \"tfg.While\",\n    \"summary\": \"A functional while loop operation.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_TensorOrControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cond\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"body\", \"type\": \"TFType_FuncAttr\" },\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" },\n      { \"name\": \"T\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" },\n      { \"name\": \"output_shapes\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TFType_ShapeAttrDef>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfg.WhileRegion\",\n    \"summary\": \"A region-based while loop operation.\",\n    \"description\": \"A `While` operation in region form. The operation takes N operands and\\n    produces N results of the same types. Each region has N data block arguments\\n    and N corresponding control tokens.\\n\\n    The entry into the condition region is blocked on the operation's control\\n    operands. The operation always executes the condition region at least once\\n    with the arguments as the operation's data operands. If the condition region\\n    returns `true`, the body region is executed with the arguments provided to\\n    the condition region. The body region will branch back to the condition\\n    region with N results. If `false`, the condition region will branch back to\\n    the parent `While` operation with the argument values as results.\\n\\n    For each region, the operation contains optional \\\"call\\\" attributes and\\n    region attributes. The number of argument attributes must match the number\\n    of data operands and the number of result attributes must match the number\\n    of data results.\\n\\n    Values can be propagated through the loop bodies as iteration variables,\\n    but the regions allow implicitly captured values as well.\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctl\", \"type\": \"ControlType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" },\n      { \"name\": \"cond_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"body_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"cond_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" },\n      { \"name\": \"body_region_attrs\", \"type\": \"OptionalAttr<TFGraph_RegionAttrs>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"tfg\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`(` $init^ `)`)? (`[` $ctls^ `]`)?\\n      $cond_region\\n    `do`\\n      $body_region\\n    attr-dict (`:` functional-type($init, $outs)^)?\"\n  },\n  {\n    \"name\": \"tfg.yield\",\n    \"summary\": \"TF graph terminator for control-flow regions.\",\n    \"description\": \"The `yield` operation is the terminator for control-flow regions. The\\n    operation takes data operands and control results. All data operands are\\n    inputs for successor regions. Typically, this means that the number of\\n    data operands matches the number of results of the parent operation.\\n\\n    The semantics of function calls in TensorFlow mean that the region \\\"returns\\\"\\n    data operands as they become available so that users can start executing\\n    immediately. All functional control-flow operations behave as multi-device\\n    function calls, which means that the control result of the parent operation\\n    depends on the control operands of the `yield`.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFGraph_Tensor>\" },\n      { \"name\": \"ctls\", \"type\": \"Variadic<ControlType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`(` $args^ `)`)? (`[` $ctls^ `]`)? attr-dict\\n                          (`:` type($args)^)?\"\n  },\n  {\n    \"name\": \"tfl.abs\",\n    \"summary\": \"Absolute value operator\",\n    \"description\": \"Given a tensor `x`, this operation returns a tensor containing the absolute\\nvalue of each element in `x`. For example, if x is an input element and y is\\nan output element, this operation computes \\\\\\\\(y = |x|\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[I16, I32, F32, QI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[I16, I32, F32, QI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.add\",\n    \"summary\": \"Addition operator\",\n    \"description\": \"Element-wise addition operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QI8, QUI8, QI16]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QI8, QUI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.add_n\",\n    \"summary\": \"add_n operator\",\n    \"description\": \"Adds all input tensors element-wise.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"TFL_VariadicTensorOf<[F32, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"sum\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.arg_max\",\n    \"summary\": \"ArgMax operator\",\n    \"description\": \"Returns the index with the largest value across dimensions of a tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[I1, F32, I32, I8, UI8, QI8, QUI8]>\" },\n      { \"name\": \"dim\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.arg_min\",\n    \"summary\": \"ArgMin operator\",\n    \"description\": \"Returns the index with the smallest value across dimensions of a tensor.\\n      a = [1, 10, 26.9, 2.8, 166.32, 62.3]\\n      b = tf.math.argmin(input = a)\\n      c = tf.keras.backend.eval(b)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[I1, F32, I32, I8, UI8, QI8, QUI8]>\" },\n      { \"name\": \"dim\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.assign_variable\",\n    \"summary\": \"Assigns a new value to a variable.\",\n    \"description\": \"Any ReadVariableOp with a control dependency on this op is guaranteed to return\\nthis value or a subsequent newer value of the variable.\",\n    \"operands\": [\n      { \"name\": \"resource_id\", \"type\": \"TFL_ResourceTensor\" },\n      { \"name\": \"value\", \"type\": \"TFL_TensorOf<[F32, F64, I1, UI8, I8, QI8, QUI8, I32, I64, QI16, Complex<F<32>>, Complex<F<64>>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.atan2\",\n    \"summary\": \"Atan2 operation\",\n    \"description\": \"The \\\"atan2\\\" operation computes the arctangent of y/x element-wise,\\n    respecting signs of the arguments.\",\n    \"operands\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, F64]>\" },\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, F64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, F64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.average_pool_2d\",\n    \"summary\": \"Average_pool_2d operator\",\n    \"description\": \"Performs average-pooling operation on input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"filter_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"filter_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_h\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_w\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.basic_lstm\",\n    \"summary\": \"The basic lstm operator\",\n    \"description\": \"basic LSTM Cell Operator.\",\n    \"operands\": [\n      { \"name\": \"data_input\", \"type\": \"TFL_TensorOf<[F32, QUI8]>\" },\n      { \"name\": \"prev_activ_input\", \"type\": \"TFL_TensorOf<[F32, QUI8]>\" },\n      { \"name\": \"weights_input\", \"type\": \"TFL_TensorOf<[F32, QUI8]>\" },\n      { \"name\": \"biases_input\", \"type\": \"TFL_TensorOf<[F32, QI32]>\" },\n      { \"name\": \"prev_state_input\", \"type\": \"TFL_TensorOf<[F32, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"activ_output\", \"type\": \"TFL_2DTensorOf<[F32, QUI8]>\" },\n      { \"name\": \"state_output\", \"type\": \"TFL_2DTensorOf<[F32, QUI16]>\" },\n      { \"name\": \"concat_temp\", \"type\": \"TFL_2DTensorOf<[F32, QUI8]>\" },\n      { \"name\": \"activ_temp\", \"type\": \"TFL_2DTensorOf<[F32, QUI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"DefaultValuedStrAttr<TFL_AFAttr, TANH>\" },\n      { \"name\": \"cell_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"proj_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"kernel_type\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<TFL_LSTMKernelTypeAttr{FULL|BASIC}, mlir::TFL::LSTMKernelType::BASIC>, [TFL_LSTMKernelTypeEqualsTo<mlir::TFL::LSTMKernelType::BASIC>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.batch_matmul\",\n    \"category\": \"Layer\",\n    \"summary\": \"Batch Matrix Multiply Operator\",\n    \"description\": \"Performs a batched matrix multiplication on the inputs. Follows the\\nconventions of TensorFlow BatchMatMulV2, with support for unknown dimensions\\nin the batch dimensions and broadcasting.\\n\\n    Inputs:\\n      `inputs[0]`: required: input LHS\\n      `inputs[1]`: required: input RHS\\n      `adjoint_lhs`: optional: Transpose LHS (default false)\\n      `adjoint_rhs`: optional: Transpose RHS (default false)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16, I8]>\" },\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16, I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16, I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adj_x\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"adj_y\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.batch_to_space_nd\",\n    \"summary\": \"BatchToSpaceNd operator\",\n    \"description\": \"This operation reshapes the \\\"batch\\\" dimension 0 into space dimensions.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I8, I32, I64, UI8, QI8, QUI8, QI16]>\" },\n      { \"name\": \"block_shape\", \"type\": \"TFL_TensorOf<[I32]>\" },\n      { \"name\": \"indices\", \"type\": \"TFL_TensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, UI8, QI8, QUI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.bidirectional_sequence_lstm\",\n    \"summary\": \"Bidirectional sequence lstm operator\",\n    \"description\": \"Bidirectional lstm is essentially two lstms, one running forward & the\\n    other running backward. And the output is the concatenation of the two\\n    lstms.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_input_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_input_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_input_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_input_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_recurrent_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_recurrent_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_recurrent_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_recurrent_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"fw_cell_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_cell_to_forget_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_cell_to_output_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_input_gate_bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" },\n      { \"name\": \"fw_forget_gate_bias\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"fw_cell_bias\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"fw_output_gate_bias\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"fw_projection_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_projection_bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" },\n      { \"name\": \"bw_input_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_input_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"bw_input_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"bw_input_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"bw_recurrent_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_recurrent_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"bw_recurrent_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"bw_recurrent_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, I8]>\" },\n      { \"name\": \"bw_cell_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_cell_to_forget_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_cell_to_output_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_input_gate_bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" },\n      { \"name\": \"bw_forget_gate_bias\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"bw_cell_bias\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"bw_output_gate_bias\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"bw_projection_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_projection_bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" },\n      { \"name\": \"fw_input_activation_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"fw_input_cell_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"bw_input_activation_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"bw_input_cell_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"aux_input\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_aux_input_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_aux_input_to_forget_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_aux_input_to_cell_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"fw_aux_input_to_output_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_aux_input_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_aux_input_to_forget_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_aux_input_to_cell_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" },\n      { \"name\": \"bw_aux_input_to_output_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"fw_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bw_output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"cell_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"proj_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"merge_outputs\", \"type\": \"BoolAttr\" },\n      { \"name\": \"time_major\", \"type\": \"BoolAttr\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.bitcast\",\n    \"summary\": \"Bitcast operator\",\n    \"description\": \"Bitcasts a tensor from one type to another.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.bitwise_xor\",\n    \"summary\": \"Bitwise Xor operator\",\n    \"description\": \"Elementwise computes the bitwise XOR of `lhs` and `rhs`.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[I8, UI8, I16, UI16, I32, UI32]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[I8, UI8, I16, UI16, I32, UI32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I8, UI8, I16, UI16, I32, UI32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.broadcast_args\",\n    \"summary\": \"Return the shape of s0 op s1 with broadcast.\",\n    \"description\": \"Given `s0` and `s1`, tensors that represent shapes, compute `r0`, the\\nbroadcasted shape. `s0`, `s1` and `r0` are all integer vectors.\",\n    \"operands\": [\n      { \"name\": \"s0\", \"type\": \"TFL_I32OrI64Tensor\" },\n      { \"name\": \"s1\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"r0\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.broadcast_to\",\n    \"summary\": \"Broadcast an array for a compatible shape.\",\n    \"description\": \"Broadcasting is the process of making arrays to have compatible shapes\\nfor arithmetic operations. Two shapes are compatible if for each\\ndimension pair they are either equal or one of them is one. When trying\\nto broadcast a Tensor to a shape, it starts with the trailing dimensions,\\nand works its way forward.\\n\\nFor example,\\n\\n>>> x = tf.constant([1, 2, 3])\\n>>> y = tf.broadcast_to(x, [3, 3])\\n>>> print(y)\\ntf.Tensor(\\n    [[1 2 3]\\n     [1 2 3]\\n     [1 2 3]], shape=(3, 3), dtype=int32)\\n\\nIn the above example, the input Tensor with the shape of `[1, 3]`\\nis broadcasted to output Tensor with shape of `[3, 3]`.\\n\\nWhen doing broadcasted operations such as multiplying a tensor\\nby a scalar, broadcasting (usually) confers some time or space\\nbenefit, as the broadcasted tensor is never materialized.\\n\\nHowever, `broadcast_to` does not carry with it any such benefits.\\nThe newly-created tensor takes the full memory of the broadcasted\\nshape. (In a graph context, `broadcast_to` might be fused to\\nsubsequent operation and then be optimized away, however.)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I1, TFL_I4, I8, QI8, UI8, UI32, QUI8, I16, QI16, I64, Complex<F<32>>]>\" },\n      { \"name\": \"shape\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I1, TFL_I4, I8, QI8, UI8, UI32, QUI8, I16, QI16, I64, Complex<F<32>>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.bucketize\",\n    \"summary\": \"Bucketizes 'input' based on 'boundaries'.\",\n    \"description\": \"Example:\\n\\nIf the inputs are `boundaries = [0, 10, 100]` and\\n`input = [[-5, 10000][150, 10][5, 100]]`,\\nthen the output will be `output = [[0, 3][3, 2][1, 3]]`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, F64, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"boundaries\", \"type\": \"TypedArrayAttrBase<F32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.call_once\",\n    \"summary\": \"Invokes an initialization function\",\n    \"description\": \"This operation invokes the given initialization function for the session\\ninitializer in tf saved model dialect.\",\n    \"attributes\": [\n      { \"name\": \"session_init_function\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.cast\",\n    \"summary\": \"Cast operator\",\n    \"description\": \"Casts input from input type to output type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F16, BF16, F32, F64, I1, TFL_I2, TFL_I4, UI<4>, I16, UI16, I32, UI32, I64, TFL_Quint8, UI8, I8, Complex<F<32>>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F16, BF16, F32, F64, I1, TFL_I2, TFL_I4, UI<4>, I16, UI16, I32, UI32, I64, TFL_Quint8, UI8, I8, Complex<F<32>>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.ceil\",\n    \"summary\": \"Ceil operator\",\n    \"description\": \"Returns element-wise ceil value of the input.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.complex_abs\",\n    \"summary\": \"Computes the complex absolute value of a tensor.\",\n    \"description\": \"Given a tensor `x` of complex numbers, this operation returns a tensor of type\\n`float` or `double` that is the absolute value of each element in `x`. All\\nelements in `x` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\). The absolute\\nvalue is computed as \\\\\\\\( \\\\sqrt{a^2 + b^2}\\\\\\\\).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[Complex<F<32>>, Complex<F<64>>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, F64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.concatenation\",\n    \"summary\": \"Concatenation operator\",\n    \"description\": \"Concatenates tensors along one dimension\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"TFL_VariadicTensorOf<[F32, I64, I32, I16, QI4, I8, QI8, QUI8, UI8, UI32, I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I64, I32, I16, QI4, I8, QI8, QUI8, UI8, UI32, I1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.control_node\",\n    \"summary\": \"The `TFL.control_node` operation wraps single-block operations in order to attach control edges.\",\n    \"description\": \"This is used to wrap regions and attach control dependencies to them. Typically,\\n    this will happen in one of the last steps before emitting the flatbuffer model\\n    in order to enable optimizations that rely on a fixed order of operations (such\\n    as rematerialization.)\\n    The flatbuffer exporter will unwrap the wrapped region and annotate the generated\\n    model with metadata such that any runtime reorderings will respect the order\\n    given by the control dependencies.\",\n    \"operands\": [\n      { \"name\": \"controlInputs\", \"type\": \"Variadic<TFL_Control>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"control\", \"type\": \"TFL_Control\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.conv_2d\",\n    \"category\": \"Layer\",\n    \"summary\": \"Convolution operator\",\n    \"description\": \"Performs convolution operation on inputs.\\n\\n    Inputs:\\n      `inputs[0]`: required: the input activation tensor\\n      `inputs[1]`: required: the filter weight tensor\\n      `inputs[2]`: optional: the bias tensor\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" },\n      { \"name\": \"filter\", \"type\": \"TFL_TensorOf<[F32, QI4, QI8, QUI8]>\" },\n      { \"name\": \"bias\", \"type\": \"TFL_1DTensorOfOrNone<[F32, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dilation_h_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"dilation_w_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_h\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_w\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.conv_3d\",\n    \"summary\": \"Convolution 3D operator\",\n    \"description\": \"Performs convolution operation on 3D inputs.\\n    Inputs:\\n      `inputs[0]`: required: the input activation tensor\\n      `inputs[1]`: required: the filter weight tensor\\n      `inputs[2]`: optional: the bias tensor\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"filter\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dilation_d_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"dilation_h_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"dilation_w_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_d\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_h\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_w\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.conv_3d_transpose\",\n    \"summary\": \"Transposed Convolution 3D operator\",\n    \"description\": \"Performs transposed convolution operation on 3D inputs.\\n    Inputs:\\n      `inputs[0]`: required: the shape of output tensor\\n      `inputs[1]`: required: the filter weight tensor\\n      `inputs[2]`: required: the input activation tensor\\n      `inputs[3]`: optional: the bias tensor\",\n    \"operands\": [\n      { \"name\": \"output_shape\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"filter\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32]>\" },\n      { \"name\": \"bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dilation_d_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"dilation_h_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"dilation_w_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_d\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_h\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_w\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.cos\",\n    \"summary\": \"Cosine operator\",\n    \"description\": \"Computes element-wise Cosine of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.cumsum\",\n    \"summary\": \"Cumsum operator\",\n    \"description\": \"Compute the cumulative sum of the tensor x along axis.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64]>\" },\n      { \"name\": \"axis\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"reverse\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.custom\",\n    \"summary\": \"Custom op\",\n    \"description\": \"A generic op for any TFLite custom operation.\\n\\n    input: A list of inputs in the original op.\\n    custom_code: A string used to identify which exactly this op is, which\\n                 corresponds to operator_codes.custom_code in the flatbuffer.\\n    custom_option: a holder to save the op attributes in bytes fashion.\\n    output: A list of outputs in the original op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TFL_TensorOfOrNone<[ AnyType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"custom_code\", \"type\": \"StrAttr\" },\n      { \"name\": \"custom_option\", \"type\": \"TFL_ConstBytesAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.custom_tf\",\n    \"summary\": \"Wrapper Op for TF custom ops.\",\n    \"description\": \"A wrapper op around any Custom TF op. These includes ops defined using\\n    custom_opdefs or linked which are not defined in TF dialect.\\n    This Op just wraps the custom op inside a region.\\n    Note #1, this Op will not include TF Lite custom ops defined using CustomOp.\\n    Note #2, this op is just internal representation inside the converter and\\n    are not exposed/exported when the model is exported to Flatbuffer.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<TFL_TensorOfOrNone<[ AnyType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.densify\",\n    \"summary\": \"Densify operator\",\n    \"description\": \"Converts sparse tensor to dense format.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.depth_to_space\",\n    \"summary\": \"DepthToSpace operator\",\n    \"description\": \"Rearranges data from depth into blocks of spatial data.\\n    This is the reverse transformation of SpaceToDepth. More specifically,\\n    this op outputs a copy of the input tensor where values from the `depth`\\n    dimension are moved in spatial blocks to the `height` and `width`\\n    dimensions. The attr `block_size` indicates the input block size and how\\n    the data is moved.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I8, I32, I64, TFL_Quint8, UI8, QI8, QUI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8, I32, I64, TFL_Quint8, UI8, QI8, QUI8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.depthwise_conv_2d\",\n    \"summary\": \"Depthwise-separable convolution operator\",\n    \"description\": \"Performs convolution operation on inputs.\\n\\n    Inputs:\\n      `inputs[0]`: required: the input activation tensor\\n      `inputs[1]`: required: the filter weight tensor\\n      `inputs[2]`: optional: the bias tensor\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" },\n      { \"name\": \"filter\", \"type\": \"TFL_TensorOf<[F32, QI4, QI8, QUI8]>\" },\n      { \"name\": \"bias\", \"type\": \"TFL_1DTensorOfOrNone<[F32, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dilation_h_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"dilation_w_factor\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_h\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_w\", \"type\": \"I32Attr\" },\n      { \"name\": \"depth_multiplier\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.dequantize\",\n    \"summary\": \"Dequantize operator\",\n    \"description\": \"Converts quantized array of integers to floating-points according to the\\n    quantization parameters.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[QI2, QI4, QUI4, QI8, QUI8, QI16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.dilate\",\n    \"summary\": \"Dilation operator\",\n    \"description\": \"Extends a tensor by adding new elements between the existing ones.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[I8, I16, I32, I64, UI8, UI16, UI32, UI64, F32, F64]>\" },\n      { \"name\": \"dilations\", \"type\": \"TFL_TensorOf<[I32]>\" },\n      { \"name\": \"padding_value\", \"type\": \"TFL_0DTensorOf<[I8, I16, I32, I64, UI8, UI16, UI32, UI64, F32, F64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I8, I16, I32, I64, UI8, UI16, UI32, UI64, F32, F64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.div\",\n    \"summary\": \"Division operator\",\n    \"description\": \"Element-wise division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32, QUI8, QI8, QI16]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32, QUI8, QI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, QUI8, QI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.dynamic_update_slice\",\n    \"summary\": \"DynamicUpdateSlice.\",\n    \"description\": \"DynamicUpdateSlice op that have the same semantics with XLA\\n    DynamicUpdateSlice.\\n    Generates a result which is the value of the input array\\n    operand, with a slice update overwritten at start_indices.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#dynamicupdateslice.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TFL_TensorOf<[I1, TFL_I4, QI4, QI8, I8, I16, I32, I64, F32, F16]>\" },\n      { \"name\": \"update\", \"type\": \"TFL_TensorOf<[I1, TFL_I4, QI4, QI8, I8, I16, I32, I64, F32, F16]>\" },\n      { \"name\": \"start_indices\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I1, TFL_I4, QI4, QI8, I8, I16, I32, I64, F32, F16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.elu\",\n    \"summary\": \"Exponential Linear Unit operator\",\n    \"description\": \"Computes the exponential linear\\n      f(x) -> exp(x) - 1 for x < 0, x for x >= 0.\\n    element-wise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, I8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.embedding_lookup\",\n    \"summary\": \"Embedding lookup operator\",\n    \"description\": \"Looks up ids in a list of embedding tensors.\",\n    \"operands\": [\n      { \"name\": \"lookup\", \"type\": \"TFL_TensorOf<[I32]>\" },\n      { \"name\": \"value\", \"type\": \"TFL_TensorOf<[F32, I8, UI8, QI8, QUI8, QI4, QI2]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8, UI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.equal\",\n    \"summary\": \"Equal operator\",\n    \"description\": \"Returns the truth element of x == y element-wise\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[I1, F32, I16, I32, I64, QI8, QUI8, QI16, UI8, TFL_Str]>\" },\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[I1, F32, I16, I32, I64, QI8, QUI8, QI16, UI8, TFL_Str]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.exp\",\n    \"summary\": \"Natural exponentiation operator\",\n    \"description\": \"Performs element-wise natural exponentiation operation on input.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.expand_dims\",\n    \"summary\": \"Inserts a dimension of 1 into a tensor's shape.\",\n    \"description\": \"Given a tensor `input`, this operation inserts a dimension of 1 at the\\ndimension index `axis` of `input`'s shape. The dimension index `axis` starts at\\nzero; if you specify a negative number for `axis` it is counted backward from\\nthe end.\\n\\nThis operation is useful if you want to add a batch dimension to a single\\nelement. For example, if you have a single image of shape `[height, width,\\nchannels]`, you can make it a batch of 1 image with `expand_dims(image, 0)`,\\nwhich will make the shape `[1, height, width, channels]`.\\n\\nOther examples:\\n\\n```\\n# 't' is a tensor of shape [2]\\nshape(expand_dims(t, 0)) ==> [1, 2]\\nshape(expand_dims(t, 1)) ==> [2, 1]\\nshape(expand_dims(t, -1)) ==> [2, 1]\\n\\n# 't2' is a tensor of shape [2, 3, 5]\\nshape(expand_dims(t2, 0)) ==> [1, 2, 3, 5]\\nshape(expand_dims(t2, 2)) ==> [2, 3, 1, 5]\\nshape(expand_dims(t2, 3)) ==> [2, 3, 5, 1]\\n```\\n\\nThis operation requires that:\\n\\n`-1-input.dims() <= dim <= input.dims()`\\n\\nThis operation is related to `squeeze()`, which removes dimensions of\\nsize 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"dim\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.external_const\",\n    \"summary\": \"External const op.\",\n    \"description\": \"External const op that can hold :\\n    - `buffer_index` which points to a constant in the flatbuffer.\\n    - `external_buffer` which contains metadata for external buffer outside flatbuffer.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"buffer_index\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"external_buffer\", \"type\": \"OptionalAttr<TFL_ExternalBufferAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.fake_quant\",\n    \"summary\": \"FakeQuant operator\",\n    \"description\": \"Fake-quantize the 'inputs' tensor of type float via float scalars min and\\n    max to 'outputs' tensor of same shape as inputs.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"F32Attr\" },\n      { \"name\": \"max\", \"type\": \"F32Attr\" },\n      { \"name\": \"num_bits\", \"type\": \"ConfinedAttr<I32Attr, [IntMinValue<2>, IntMaxValue<16>]>\" },\n      { \"name\": \"narrow_range\", \"type\": \"ConfinedAttr<BoolAttr, [TFL_BoolFalse]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.fill\",\n    \"summary\": \"Fill the tensor with given value.\",\n    \"description\": \"Fill the tensor with given value.\",\n    \"operands\": [\n      { \"name\": \"dims\", \"type\": \"TFL_I32OrI64Tensor\" },\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, F16, I32, I64, I1, QI8, QI16, TFL_Str]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFL_TensorOf<[F32, F16, I32, I64, I1, QI8, QI16, TFL_Str]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.floor\",\n    \"summary\": \"Floor operator\",\n    \"description\": \"Returns element-wise floor value of the input.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.floor_div\",\n    \"summary\": \"Floor div operator\",\n    \"description\": \"Element-wise floor div operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32]>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.floor_mod\",\n    \"summary\": \"Division reminder\",\n    \"description\": \"Element-wise division reminder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[I8, I16, I32, I64, F32]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[I8, I16, I32, I64, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I8, I16, I32, I64, F32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.fully_connected\",\n    \"category\": \"Layer\",\n    \"summary\": \"Fully connected op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16, QUI16]>\" },\n      { \"name\": \"filter\", \"type\": \"TFL_TensorOf<[F32, QI2, QI4, QI8, QUI8, QI16]>\" },\n      { \"name\": \"bias\", \"type\": \"TFL_TensorOfOrNone<[F32, QI32, QUI32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_VariadicTensorOf<[F32, QI8, QUI8, QI16, QUI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"weights_format\", \"type\": \"TFL_FullyConnectedOptionsWeightFormatAttr\" },\n      { \"name\": \"keep_num_dims\", \"type\": \"BoolAttr\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Gather operator\",\n    \"description\": \"Gather slices from `params` axis `axis` according to `indices`.\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"TFL_TensorOf<[F32, I1, TFL_I4, I8, I16, I32, I64, TFL_Str, UI8, QI8, QUI8, QI16]>\" },\n      { \"name\": \"indices\", \"type\": \"TFL_TensorOf<[I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, TFL_I4, I8, I16, I32, I64, TFL_Str, UI8, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.gather_nd\",\n    \"summary\": \"Gather_nd operator\",\n    \"description\": \"Gather slices from `params` into a Tensor with shape specified by `indices`.\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I64, I32, UI8, QI8, TFL_Str]>\" },\n      { \"name\": \"indices\", \"type\": \"TFL_TensorOf<[I16, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I64, I32, UI8, QI8, TFL_Str]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.gelu\",\n    \"summary\": \"GELU activation function.\",\n    \"description\": \"Computes GELU activation function element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"approximate\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.greater\",\n    \"summary\": \"Greater operator\",\n    \"description\": \"Element-wise greater operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QUI8, QI8, TFL_Quint8]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QUI8, QI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.greater_equal\",\n    \"summary\": \"Greater_equal operator\",\n    \"description\": \"Element-wise greater_equal operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QUI8, QI8]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QUI8, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.hard_swish\",\n    \"summary\": \"Hardswish activation function.\",\n    \"description\": \"Computes hard-swish activation function\\n      f(x) -> (x * relu6(x+3))/6\\n    element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.hashtable\",\n    \"summary\": \"Creates a non-initialized hash table.\",\n    \"description\": \"This op creates a hash table, specifying the type of its keys and values.\\nBefore using the table you will have to initialize it.  After initialization the\\ntable will be immutable.\",\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFL_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_id\", \"type\": \"I32Attr\" },\n      { \"name\": \"key_dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_dtype\", \"type\": \"TypeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.hashtable_find\",\n    \"summary\": \"Looks up keys in a table, outputs the corresponding values.\",\n    \"description\": \"The tensor `keys` must of the same type as the keys of the table.\\nThe output `values` is of the type of the table values.\\n\\nThe scalar `default_value` is the value output for keys not present in the\\ntable. It must also be of the same type as the table values.\",\n    \"operands\": [\n      { \"name\": \"hash_table\", \"type\": \"TFL_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TFL_TensorOf<[I32, TFL_Str, I64]>\" },\n      { \"name\": \"default_value\", \"type\": \"TFL_TensorOf<[F32, I32, TFL_Str, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFL_TensorOf<[F32, I32, TFL_Str, I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.hashtable_import\",\n    \"summary\": \"Replaces the contents of the table with the specified keys and values.\",\n    \"description\": \"The tensor `keys` must be of the same type as the keys of the table.\\nThe tensor `values` must be of the type of the table values.\",\n    \"operands\": [\n      { \"name\": \"hash_table\", \"type\": \"TFL_ResourceTensor\" },\n      { \"name\": \"keys\", \"type\": \"TFL_TensorOf<[I32, TFL_Str, I64]>\" },\n      { \"name\": \"values\", \"type\": \"TFL_TensorOf<[F32, I32, TFL_Str, I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.hashtable_size\",\n    \"summary\": \"Computes the number of elements in the given table.\",\n    \"operands\": [\n      { \"name\": \"hash_table\", \"type\": \"TFL_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFL_I64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.if\",\n    \"summary\": \"if-then-else operation\",\n    \"description\": \"The `tfl.if` operation represents an if-then-else construct for\\n    conditionally executing two regions of code. The operand to an if operation\\n    is a boolean value. For example:\\n\\n    ```mlir\\n    tfl.if %b  {\\n      ...\\n    } else {\\n      ...\\n    }\\n    ```\\n\\n    `tfl.if` may also return results that are defined in its regions. The\\n    values defined are determined by which execution path is taken.\\n\\n    Example:\\n\\n    ```mlir\\n    %x, %y = tfl.if %b -> (tensor<f32>, tensor<f32>) {\\n      %x_true = ...\\n      %y_true = ...\\n      tfl.yield %x_true, %y_true : tensor<f32>, tensor<f32>\\n    } else {\\n      %x_false = ...\\n      %y_false = ...\\n      tfl.yield %x_false, %y_false : tensor<f32>, tensor<f32>\\n    }\\n    ```\\n\\n    `tfl.if` regions are always terminated with \\\"tfl.yield\\\". If \\\"tfl.if\\\"\\n    defines no values, the \\\"tfl.yield\\\" can be left out, and will be inserted\\n    implicitly. Otherwise, it must be explicit.\\n    Also, if \\\"tfl.if\\\" defines one or more values, the 'else' block cannot be\\n    omitted.\\n\\n    Example:\\n\\n    ```mlir\\n    tfl.if %b  {\\n      ...\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_region\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.imag\",\n    \"summary\": \"Returns the imaginary part of a complex number.\",\n    \"description\": \"Given a tensor `input` of complex numbers, this operation returns a tensor of\\ntype `float` that is the imaginary part of each element in `input`. All\\nelements in `input` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\), where *a*\\nis the real part and *b* is the imaginary part returned by this operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[Complex<F<32>>, Complex<F<64>>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, F64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.l2_normalization\",\n    \"summary\": \"L2 Normalize Operator\",\n    \"description\": \"L2Normalization Op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, QUI16, QI16, I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, QUI16, QI16, I8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.leaky_relu\",\n    \"summary\": \"Leaky Relu operator\",\n    \"description\": \"Element-wise Leaky ReLU operator\\n      x -> x >= 0 ? x : (alpha * x)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.less\",\n    \"summary\": \"Less operator\",\n    \"description\": \"Element-wise less operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QUI8, QI8, TFL_Quint8]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, QUI8, QI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.less_equal\",\n    \"summary\": \"Less_equal operator\",\n    \"description\": \"Element-wise less_equal operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.local_response_normalization\",\n    \"summary\": \"Local Response Normalization.\",\n    \"description\": \"The 4-D `input` tensor is treated as a 3-D array of 1-D vectors (along the last\\ndimension), and each vector is normalized independently.  Within a given vector,\\neach component is divided by the weighted, squared sum of inputs within\\n`depth_radius`.  In detail,\\n\\n    sqr_sum[a, b, c, d] =\\n        sum(input[a, b, c, d - depth_radius : d + depth_radius + 1] ** 2)\\n    output = input / (bias + alpha * sqr_sum) ** beta\\n\\nFor details, see [Krizhevsky et al., ImageNet classification with deep\\nconvolutional neural networks (NIPS 2012)](http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"radius\", \"type\": \"I32Attr\" },\n      { \"name\": \"bias\", \"type\": \"F32Attr\" },\n      { \"name\": \"alpha\", \"type\": \"F32Attr\" },\n      { \"name\": \"beta\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.log\",\n    \"summary\": \"Natural logarithm operator\",\n    \"description\": \"Performs element-wise natural logarithm operation on input.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.log_softmax\",\n    \"summary\": \"Log softmax operator\",\n    \"description\": \"Computes element-wise log softmax activations with the following formula\\n\\n      input - log(reduce_sum(exp(input), dim))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.logical_and\",\n    \"summary\": \"Logical AND operator\",\n    \"description\": \"Element-wise logical AND operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_BoolTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.logical_not\",\n    \"summary\": \"Logical NOT operator\",\n    \"description\": \"Element-wise logical NOT operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.logical_or\",\n    \"summary\": \"Logical OR operator\",\n    \"description\": \"Element-wise logical OR operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_BoolTensor\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.logistic\",\n    \"summary\": \"Logistic operator\",\n    \"description\": \"Computes element-wise Sigmoid of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.lstm\",\n    \"summary\": \"The full lstm operator\",\n    \"description\": \"Long short-term memory unit (LSTM) recurrent network layer.\\nThe default non-peephole implementation is based on:\\nhttp://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf\\nS. Hochreiter and J. Schmidhuber. 'Long Short-Term Memory'. Neural Computation,\\n9(8):1735-1780, 1997.\\nThe peephole implementation is based on:\\nhttps://research.google.com/pubs/archive/43905.pdf\\nHasim Sak, Andrew Senior, and Francoise Beaufays. 'Long short-term memory\\nrecurrent neural network architectures for large scale acoustic modeling.'\\nINTERSPEECH, 2014.\\nThe coupling of input and forget gate (CIFG) is based on:\\nhttp://arxiv.org/pdf/1503.04069.pdf\\nGreff et al. 'LSTM: A Search Space Odyssey'\\nThe layer normalization is based on:\\nhttps://arxiv.org/pdf/1607.06450.pdf\\nBa et al. 'Layer Normalization'\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" },\n      { \"name\": \"input_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"input_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"input_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"input_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"cell_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8, QI16]>\" },\n      { \"name\": \"cell_to_forget_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8, QI16]>\" },\n      { \"name\": \"cell_to_output_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8, QI16]>\" },\n      { \"name\": \"input_gate_bias\", \"type\": \"TFL_TensorOfOrNone<[F32, QI32]>\" },\n      { \"name\": \"forget_gate_bias\", \"type\": \"TFL_TensorOf<[F32, QI32]>\" },\n      { \"name\": \"cell_bias\", \"type\": \"TFL_TensorOf<[F32, QI32]>\" },\n      { \"name\": \"output_gate_bias\", \"type\": \"TFL_TensorOf<[F32, QI32]>\" },\n      { \"name\": \"projection_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"projection_bias\", \"type\": \"TFL_TensorOfOrNone<[F32, QI32]>\" },\n      { \"name\": \"input_activation_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"input_cell_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"input_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI16]>\" },\n      { \"name\": \"forget_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI16]>\" },\n      { \"name\": \"cell_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI16]>\" },\n      { \"name\": \"output_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"cell_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"proj_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"kernel_type\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<TFL_LSTMKernelTypeAttr{FULL|BASIC}, mlir::TFL::LSTMKernelType::FULL>, [TFL_LSTMKernelTypeEqualsTo<mlir::TFL::LSTMKernelType::FULL>]>\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"input_to_input_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"input_to_forget_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"input_to_cell_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"input_to_output_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"effective_hidden_scale_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"internal\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.matrix_diag\",\n    \"summary\": \"Returns a tensor with the provided diagonal and everything else padded with zeros.\",\n    \"description\": \"Given a diagonal, returns a tensor with the diagonal and everything else padded with zeros.\\n    Assume diagonal has k dimensions `[I, J, K, ..., N]`, then the output is a tensor of rank `k+1`\\n    with dimensions `[I, J, K, ..., N, N]` where:\\n       `output[i, j, k, ..., m, n] = 1{m=n} * diagonal[i, j, k, ..., n].`\",\n    \"operands\": [\n      { \"name\": \"diagonal\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QUI8, QI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QUI8, QI8, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.matrix_set_diag\",\n    \"summary\": \"Returns a batched matrix tensor with new batched diagonal values.\",\n    \"description\": \"Given `input` and `diagonal`, this operation returns a tensor with the\\nsame shape and values as `input`, except for the main diagonal of the\\ninnermost matrices.  These will be overwritten by the values in `diagonal`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QI8, QI16, QUI8, TFL_Quint8]>\" },\n      { \"name\": \"diagonal\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QI8, QI16, QUI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QI8, QI16, QUI8, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.max_pool_2d\",\n    \"summary\": \"Max Pool 2D op\",\n    \"description\": \"Performs max pool 2D on input.\\n\\n    Inputs:\\n      `inputs[0]`: required: the input tensor\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_w\", \"type\": \"I32Attr\" },\n      { \"name\": \"stride_h\", \"type\": \"I32Attr\" },\n      { \"name\": \"filter_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"filter_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.maximum\",\n    \"summary\": \"Max operator\",\n    \"description\": \"Element-wise max operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, TFL_Int32Or64, QI8, QUI8, QI16]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, TFL_Int32Or64, QI8, QUI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"max\", \"type\": \"TFL_TensorOf<[F32, TFL_Int32Or64, QI8, QUI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.mean\",\n    \"summary\": \"Mean operator\",\n    \"description\": \"Computes the mean of elements across dimensions of a tensor.\\n    Reduces input_tensor along the dimensions given in axis.\\n    Unless keepdims is true, the rank of the tensor is reduced by 1 for\\n    each entry in axis. If keepdims is true, the reduced dimensions are retained\\n    with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, UI8, QI16]>\" },\n      { \"name\": \"axis\", \"type\": \"TFL_TensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, UI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.minimum\",\n    \"summary\": \"Min operator\",\n    \"description\": \"Element-wise min operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, TFL_Int32Or64, QI8, QUI8, QI16]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, TFL_Int32Or64, QI8, QUI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"min\", \"type\": \"TFL_TensorOf<[F32, TFL_Int32Or64, QI8, QUI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.mirror_pad\",\n    \"summary\": \"MirrorPad Operator. Pads a tensor with mirrored values.\",\n    \"description\": \"This operation pads a input with mirrored values according to the paddings\\n    you specify. paddings is an integer tensor with shape [n, 2],\\n    where n is the rank of input.\\n    For each dimension D of input, paddings[D, 0] indicates how many values\\n    to add before the contents of input in that dimension,\\n    and paddings[D, 1] indicates how many values to add after the contents of\\n    input in that dimension.\\n\\n    Both paddings[D, 0] and paddings[D, 1] must be no greater than\\n    input.dim_size(D) (or input.dim_size(D) - 1)\\n    if copy_border is true (if false, respectively).\\n\\n    The padded size of each dimension D of the output is:\\n\\n    paddings(D, 0) + input.dim_size(D) + paddings(D, 1)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I8, UI8, QI8, QUI8, QI16]>\" },\n      { \"name\": \"pad\", \"type\": \"TFL_TensorOf<[I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I8, UI8, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"TFL_MirrorPaddingAttr{REFLECT|SYMMETRIC}\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.mul\",\n    \"summary\": \"Multiplication operator\",\n    \"description\": \"Element-wise multiplication operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32, UI32, I64, QI8, QUI8, QI16, I16, Complex<F<32>>]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32, UI32, I64, QI8, QUI8, QI16, I16, Complex<F<32>>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, UI32, I64, QI8, QUI8, QI16, I16, Complex<F<32>>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.multinomial\",\n    \"summary\": \"Draws samples from a categorical distribution.\",\n    \"description\": \"The generated values will have a categorical distribution based on the `logits`\\nor unnormalized log-probabilities provided for all classes.\",\n    \"operands\": [\n      { \"name\": \"logits\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"num_samples\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFL_TensorOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.neg\",\n    \"summary\": \"Negation operator\",\n    \"description\": \"Computes element-wise negation of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, I32, I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.no_value\",\n    \"summary\": \"constant representing no value.\",\n    \"description\": \"No value constant op.\",\n    \"results\": [\n      { \"name\": \"none_val\", \"type\": \"NoneType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.non_max_suppression_v4\",\n    \"summary\": \"Greedily selects a subset of bounding boxes in descending order of score,\",\n    \"description\": \"pruning away boxes that have high intersection-over-union (IOU) overlap\\nwith previously selected boxes.  Bounding boxes with score less than\\n`score_threshold` are removed.  Bounding boxes are supplied as\\n[y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any\\ndiagonal pair of box corners and the coordinates can be provided as normalized\\n(i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm\\nis agnostic to where the origin is in the coordinate system and more\\ngenerally is invariant to orthogonal transformations and translations\\nof the coordinate system; thus translating or reflections of the coordinate\\nsystem result in the same boxes being selected by the algorithm.\\nThe output of this operation is a set of integers indexing into the input\\ncollection of bounding boxes representing the selected boxes.  The bounding\\nbox coordinates corresponding to the selected indices can then be obtained\\nusing the `tf.gather operation`.  For example:\\n  selected_indices = tf.image.non_max_suppression_v2(\\n      boxes, scores, max_output_size, iou_threshold, score_threshold)\\n  selected_boxes = tf.gather(boxes, selected_indices)\",\n    \"operands\": [\n      { \"name\": \"boxes\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"scores\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"max_output_size\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"iou_threshold\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"score_threshold\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_indices\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"valid_outputs\", \"type\": \"TFL_I32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.non_max_suppression_v5\",\n    \"summary\": \"Greedily selects a subset of bounding boxes in descending order of score,\",\n    \"description\": \"pruning away boxes that have high intersection-over-union (IOU) overlap\\nwith previously selected boxes.  Bounding boxes with score less than\\n`score_threshold` are removed.  Bounding boxes are supplied as\\n[y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any\\ndiagonal pair of box corners and the coordinates can be provided as normalized\\n(i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm\\nis agnostic to where the origin is in the coordinate system and more\\ngenerally is invariant to orthogonal transformations and translations\\nof the coordinate system; thus translating or reflections of the coordinate\\nsystem result in the same boxes being selected by the algorithm.\\nThe output of this operation is a set of integers indexing into the input\\ncollection of bounding boxes representing the selected boxes.  The bounding\\nbox coordinates corresponding to the selected indices can then be obtained\\nusing the `tf.gather operation`.  For example:\\n  selected_indices = tf.image.non_max_suppression_v2(\\n      boxes, scores, max_output_size, iou_threshold, score_threshold)\\n  selected_boxes = tf.gather(boxes, selected_indices)\\nThis op also supports a Soft-NMS (with Gaussian weighting) mode (c.f.\\nBodla et al, https://arxiv.org/abs/1704.04503) where boxes reduce the score\\nof other overlapping boxes instead of directly causing them to be pruned.\\nTo enable this Soft-NMS mode, set the `soft_nms_sigma` parameter to be\\nlarger than 0.\",\n    \"operands\": [\n      { \"name\": \"boxes\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"scores\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"max_output_size\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"iou_threshold\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"score_threshold\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"soft_nms_sigma\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"selected_indices\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"selected_scores\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"valid_outputs\", \"type\": \"TFL_I32Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.not_equal\",\n    \"summary\": \"Not_equal operator\",\n    \"description\": \"Element-wise not_equal operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[I1, F32, I32, I64, QUI8, QI8, QI16, TFL_Quint8, TFL_Str]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[I1, F32, I32, I64, QUI8, QI8, QI16, TFL_Quint8, TFL_Str]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.NumericVerify\",\n    \"summary\": \"Verifies the numericals of the two operands\",\n    \"description\": \"The NumericVerify op is a debugging op to verify the numericals of the two\\n    activations. It is a custom op in TFLite.\\n    If log_if_failed is true, the NumericVerify op calculates statistics on\\n    differences between float and quantized activations, output\\n    logs, set differences to the output tensors, and throws an error if errors\\n    above tolerance exist. If log_if_failed = false, then it doesn't care about\\n    errors.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[QI8, QUI8, QI16, F16, TFL_Quint8]>\" },\n      { \"name\": \"ref\", \"type\": \"TFL_TensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tolerance\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.1>\" },\n      { \"name\": \"log_if_failed\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.one_hot\",\n    \"summary\": \"OneHot operator\",\n    \"description\": \"Returns a one-hot tensor.The locations represented by indices in `indices`\\n    take value `on_value`, while all other locations take value `off_value`.\\n\\n    If the input `indices` is rank `N`, the output will have rank `N+1`,\\n    The new axis is created at dimension `axis` (default: the new axis is\\n    appended at the end).\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TFL_TensorOf<[I32, I64]>\" },\n      { \"name\": \"depth\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"on_value\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I1, I8, UI8]>\" },\n      { \"name\": \"off_value\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I1, I8, UI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I1, I8, UI8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pack\",\n    \"summary\": \"Packs a list of tensors along a dimension into one tensor\",\n    \"description\": \"Packs a list of `values_count` rank-`R` tensors into one rank-`(R+1)`\\n    tensor.\\n\\n    Packs the `values_count` tensors in `values` into a tensor with rank one\\n    higher than each tensor in `values`, by packing them along the `axis`\\n    dimension.\\n\\n    Given a list of tensors of shape `(A, B, C)`;\\n\\n    if `axis == 0` then the `output` tensor will have the shape `(N, A, B, C)`.\\n    if `axis == 1` then the `output` tensor will have the shape `(A, N, B, C)`.\\n    Etc.\\n\\n    For example:\\n\\n    ```\\n    # 'x' is [1, 4]\\n    # 'y' is [2, 5]\\n    # 'z' is [3, 6]\\n    pack([x, y, z]) => [[1, 4], [2, 5], [3, 6]]  # Pack along first dim.\\n    pack([x, y, z], axis=1) => [[1, 2, 3], [4, 5, 6]]\\n    ```\\n\\n    This is the opposite of `unpack`.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"TFL_VariadicTensorOf<[F32, I8, I16, I32, I64, UI8, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values_count\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pad\",\n    \"category\": \"Transform\",\n    \"summary\": \"Padding operator\",\n    \"description\": \"This operation pads a `input` with zeros according to the `paddings` you\\n    specify. `paddings` is an integer tensor with shape `[Dn, 2]`, where n is\\n    the rank of `input`. For each dimension D of `input`, `paddings[D, 0]`\\n    indicates how many zeros to add before the contents of `input` in that\\n    dimension, and `paddings[D, 1]` indicates how many zeros to add after the\\n    contents of `input` in that dimension.\\n\\n    The padded size of each dimension D of the output is:\\n\\n      `paddings(D, 0) + input.dim_size(D) + paddings(D, 1)`\\n\\n    For example:\\n\\n    ```\\n    # 't' is [[1, 1], [2, 2]]\\n    # 'paddings' is [[1, 1], [2, 2]]\\n    # rank of 't' is 2\\n    pad(t, paddings) ==> [[0, 0, 0, 0, 0, 0]\\n                          [0, 0, 1, 1, 0, 0]\\n                          [0, 0, 2, 2, 0, 0]\\n                          [0, 0, 0, 0, 0, 0]]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"padding\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.padv2\",\n    \"summary\": \"Padding operator v2\",\n    \"description\": \"This operation pads a `input` according to the `paddings` and\\n    `constant_values` you specify. `paddings` is an integer tensor with shape\\n    `[Dn, 2]`, where n is the rank of `input`. For each dimension D of `input`,\\n    `paddings[D, 0]` indicates how many zeros to add before the contents of\\n    `input` in that dimension, and `paddings[D, 1]` indicates how many zeros to\\n    add after the contents of `input` in that dimension. `constant_values` is a\\n    scalar tensor of the same type as `input` that indicates the value to use\\n    for padding `input`.\\n\\n    The padded size of each dimension D of the output is:\\n\\n      `paddings(D, 0) + input.dim_size(D) + paddings(D, 1)`\\n\\n    For example:\\n\\n    ```\\n    # 't' is [[1, 1], [2, 2]]\\n    # 'paddings' is [[1, 1], [2, 2]]\\n    # rank of 't' is 2\\n    pad(t, paddings) ==> [[0, 0, 0, 0, 0, 0]\\n                          [0, 0, 1, 1, 0, 0]\\n                          [0, 0, 2, 2, 0, 0]\\n                          [0, 0, 0, 0, 0, 0]]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, UI8, QI8, QUI8, TFL_Quint8]>\" },\n      { \"name\": \"padding\", \"type\": \"TFL_I32OrI64Tensor\" },\n      { \"name\": \"constant_values\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, UI8, QI8, QUI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, UI8, QI8, QUI8, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.poly_call\",\n    \"summary\": \"Poly call\",\n    \"description\": \"Have multiple function bodies for the same computation. This allows a\\n    program compiler/interpreter to choose one of the available options to\\n    execute the program based on which one is most suitable for the target\\n    backend.\\n\\n    input:  A list of input tensors whose types are T.\\n    output: A list of output tensors whose types are T.\\n\\n    call:  Multiple regions, each of which encapsulates the same semantic\\n           computation but in different forms.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"calls\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pow\",\n    \"summary\": \"Power operator\",\n    \"description\": \"Element-wise power operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.prelu\",\n    \"summary\": \"Parameterized Relu operator\",\n    \"description\": \"Parameterized Relu operator\\n      x -> x >= 0 ? x : (alpha * x)\\n    where alpha is a trainable tensor.\\n    input and alpha should be the same size as input or be broadcastable.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, TFL_Quint8]>\" },\n      { \"name\": \"alpha\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pseudo_const\",\n    \"summary\": \"Constant pseudo op.\",\n    \"description\": \"Represents a constant value in TensorFlow Lite dialect. This is not an\\n    actual operation and it will be lowered to buffer instead.\\n\\n    The op is allowed to have all the same type of attributes as tf.Const does\\n    (e.g., opaque TF attributes are allowed).\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pseudo_qconst\",\n    \"summary\": \"Quantized constant pseudo op\",\n    \"description\": \"Represents a quantized constant value in TensorFlow Lite dialect. This is\\n    not an actual operation and it will be lowered to buffer instead. The\\n    quantization parameters are stored as a type attribute in this constant.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[QUI8, QI8, QUI4, QI16, QUI16, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"qtype\", \"type\": \"TensorTypeAttr\" },\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pseudo_sparse_const\",\n    \"summary\": \"Sparse constant pseudo op.\",\n    \"description\": \"Represents a sparse constant value in TensorFlow Lite dialect. This is not\\n    an actual operation and it will be lowered to buffer instead.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" },\n      { \"name\": \"s_param\", \"type\": \"SparsityParameterAttr\" },\n      { \"name\": \"compressed_data\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.pseudo_sparse_qconst\",\n    \"summary\": \"Sparse quantized constant pseudo op\",\n    \"description\": \"Represents a sparse quantized constant value in TensorFlow Lite dialect.\\n    This is not an actual operation and it will be lowered to buffer instead.\\n    The quantization parameters are stored as a type attribute in this constant.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[QUI8, QI8, QUI4, QI16, QUI16, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"qtype\", \"type\": \"TensorTypeAttr\" },\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" },\n      { \"name\": \"s_param\", \"type\": \"SparsityParameterAttr\" },\n      { \"name\": \"compressed_data\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.quantize\",\n    \"summary\": \"Quantize operator\",\n    \"description\": \"Converts floating point tensors to quantized integer tensors according to\\n    the quantization parameters defined in the type attribute.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI4, QUI4, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[QI4, QUI4, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"qtype\", \"type\": \"TensorTypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.random_standard_normal\",\n    \"summary\": \"Outputs random values from a normal distribution.\",\n    \"description\": \"The generated values will have mean 0 and standard deviation 1.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFL_TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.random_uniform\",\n    \"summary\": \"Outputs random values from a uniform distribution.\",\n    \"description\": \"The generated values follow a uniform distribution in the range `[0, 1)`. The\\nlower bound 0 is included in the range, while the upper bound 1 is excluded.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFL_TensorOf<[F32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"seed2\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.range\",\n    \"summary\": \"Range operator\",\n    \"description\": \"Returns a 1D tensor defined by a sequence from `start` to `limit` with\\n    a given `delta`.\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"TFL_TensorOf<[I32, F32, I64]>\" },\n      { \"name\": \"limit\", \"type\": \"TFL_TensorOf<[I32, F32, I64]>\" },\n      { \"name\": \"delta\", \"type\": \"TFL_TensorOf<[I32, F32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFL_TensorOf<[I32, F32, I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.rank\",\n    \"summary\": \"Rank operator.\",\n    \"description\": \"Returns the rank of a tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_IntTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.read_variable\",\n    \"summary\": \"Reads variable value.\",\n    \"description\": \"Read variable data identified by 'resource_id'.\",\n    \"operands\": [\n      { \"name\": \"resource_id\", \"type\": \"TFL_ResourceTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFL_TensorOf<[F32, F64, I1, UI8, I8, QI8, QUI8, I32, I64, QI16, Complex<F<32>>, Complex<F<64>>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.real\",\n    \"summary\": \"Returns the real part of a complex number.\",\n    \"description\": \"Given a tensor `input` of complex numbers, this operation returns a tensor of\\ntype `float` that is the real part of each element in `input`. All elements in\\n`input` must be complex numbers of the form \\\\\\\\(a + bj\\\\\\\\), where *a* is the real\\n part returned by this operation and *b* is the imaginary part.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[Complex<F<32>>, Complex<F<64>>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, F64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reduce_all\",\n    \"summary\": \"Computes the \\\"logical and\\\" of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_BoolTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reduce_any\",\n    \"summary\": \"Computes the \\\"logical or\\\" of elements across dimensions of a tensor.\",\n    \"description\": \"Reduces `input` along the dimensions given in `axis`. Unless\\n`keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in\\n`axis`. If `keep_dims` is true, the reduced dimensions are\\nretained with length 1.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_BoolTensor\" },\n      { \"name\": \"reduction_indices\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_BoolTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reduce_max\",\n    \"summary\": \"Max-reduction operator\",\n    \"description\": \"Computes the max reduction along the specified axes\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"axes\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reduce_min\",\n    \"summary\": \"Min-reduction operator\",\n    \"description\": \"Computes the min reduction along the specified axes\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"axes\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reduce_prod\",\n    \"summary\": \"Prod-reduction operator\",\n    \"description\": \"Computes the product along the specified axes\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"axes\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.relu\",\n    \"category\": \"Activation\",\n    \"summary\": \"Relu operator\",\n    \"description\": \"Element-wise Relu operator\\n      x -> max(0, x)\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.relu_0_to_1\",\n    \"summary\": \"Relu0To1 operator\",\n    \"description\": \"Element-wise Relu0To1 operator\\n      x -> max(0, min(1, x))\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.relu_n1_to_1\",\n    \"summary\": \"Relu1 operator\",\n    \"description\": \"Element-wise Relu1 operator\\n      x -> max(-1, min(1, x))\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.relu6\",\n    \"summary\": \"Relu6 operator\",\n    \"description\": \"Element-wise Relu6 operator\\n      x -> max(0, min(6, x))\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QUI8, QI8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"Reshape operator\",\n    \"description\": \"Produces a tensor with the same values but different static shape defined\\n    by the output type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shape\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.resize_bilinear\",\n    \"summary\": \"ResizeBilinear Op\",\n    \"description\": \"Resize `images` to `size` using bilinear interpolation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, TFL_Quint8, QUI8, QI8, QI16]>\" },\n      { \"name\": \"size\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, TFL_Quint8, QUI8, QI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" },\n      { \"name\": \"half_pixel_centers\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.resize_nearest_neighbor\",\n    \"summary\": \"ResizeNearestNeighbor Op\",\n    \"description\": \"Resize `images` to `size` using nearest neighbor interpolation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, TFL_Quint8, QUI8, QI8, QI16]>\" },\n      { \"name\": \"size\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, TFL_Quint8, QUI8, QI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" },\n      { \"name\": \"half_pixel_centers\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reverse_sequence\",\n    \"summary\": \"Reverses variable length slices.\",\n    \"description\": \"This op first slices `input` along the dimension `batch_dim`, and for each\\nslice `i`, reverses the first `seq_lengths[i]` elements along\\nthe dimension `seq_dim`.\\n\\nThe elements of `seq_lengths` must obey `seq_lengths[i] <= input.dims[seq_dim]`,\\nand `seq_lengths` must be a vector of length `input.dims[batch_dim]`.\\n\\nThe output slice `i` along dimension `batch_dim` is then given by input\\nslice `i`, with the first `seq_lengths[i]` slices along dimension\\n`seq_dim` reversed.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI16, QUI8, TFL_Quint8]>\" },\n      { \"name\": \"seq_lengths\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI16, QUI8, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seq_dim\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" },\n      { \"name\": \"batch_dim\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.reverse_v2\",\n    \"summary\": \"ReverseV2 Operator\",\n    \"description\": \"Reverses specific dimensions of a tensor.\\n\\n    Given a tensor, and a int32/int64 tensor axis representing the set\\n    of dimensions of tensor to reverse.\\n    This operation reverses each dimension i for\\n    which there exists j s.t. axis[j] == i.\\n\\n    Args:\\n      tensor: A Tensor. Must be one of the following types:\\n      uint8, int8, int16, int32, int64, float32, bool Up to 8-D.\\n\\n      axis: A Tensor. Must be one of the following types: int32, int64.\\n      with only 1 element which is the axis index.\\n      TODO: Add support for multiple elements.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, UI8, I16, I32, I64, QI16, QUI8, QI8, TFL_Quint8, I1]>\" },\n      { \"name\": \"axis\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, UI8, I16, I32, I64, QI16, QUI8, QI8, TFL_Quint8, I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.rfft2d\",\n    \"summary\": \"2D real-valued fast Fourier transform.\",\n    \"description\": \"Computes the 2-dimensional discrete Fourier transform of a real-valued signal\\nover the inner-most 2 dimensions of `input`.\\n\\nSince the DFT of a real signal is Hermitian-symmetric, `RFFT2D` only returns the\\n`fft_length / 2 + 1` unique components of the FFT for the inner-most dimension\\nof `output`: the zero-frequency term, followed by the `fft_length / 2`\\npositive-frequency terms.\\n\\nAlong each axis `RFFT2D` is computed on, if `fft_length` is smaller than the\\ncorresponding dimension of `input`, the dimension is cropped. If it is larger,\\nthe dimension is padded with zeros.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"fft_length\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_Complex64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.right_shift\",\n    \"summary\": \"Right Shift operator\",\n    \"description\": \"Elementwise computes the bitwise right-shift of `lhs` by `rhs`.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[I8, UI8, I16, UI16, I32, UI32]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[I8, UI8, I16, UI16, I32, UI32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I8, UI8, I16, UI16, I32, UI32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.round\",\n    \"summary\": \"Round operator\",\n    \"description\": \"Rounds the values of a tensor to the nearest integer, element-wise.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.rsqrt\",\n    \"summary\": \"Reciprocal of square root operator\",\n    \"description\": \"Computes element-wise reverse square root of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.scatter_nd\",\n    \"summary\": \"Scatter_nd operator\",\n    \"description\": \"Scatter `updates` into a new tensor according to `indices`\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TFL_TensorOf<[I32]>\" },\n      { \"name\": \"updates\", \"type\": \"TFL_TensorOf<[F32, I8, I64, I32, UI8, I1]>\" },\n      { \"name\": \"shape\", \"type\": \"TFL_1DTensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I8, I64, I32, UI8, I1]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.segment_sum\",\n    \"summary\": \"SegmentSum operator\",\n    \"description\": \"Computes the sum along segments of a tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32]>\" },\n      { \"name\": \"segment_ids\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.select\",\n    \"summary\": \"Select operator\",\n    \"description\": \"Select values of 'x' if the corresponding value of 'condition' is true or\\n    the value of 'y' if false. There are valid condition input sizes:\\n\\n    1. Either the same shape (in which case the select is elementwise), or\\n    2. condition must be Rank 1 and match over the first dimension.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TFL_BoolTensor\" },\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I32, I64, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" },\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I32, I64, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I32, I64, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.select_v2\",\n    \"summary\": \"SelectV2 operator\",\n    \"description\": \"Select values of 'x' if the corresponding value of 'condition' is true or\\n    the value of 'y' if false. There are valid condition input sizes:\\n\\n    1. Either the same shape (in which case the select is elementwise), or\\n    2. Broadcastable shapes between 'condition', 'x' and 'y'.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TFL_BoolTensor\" },\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I32, I64, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" },\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I32, I64, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, I8, I16, I32, I64, UI32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.shape\",\n    \"summary\": \"Shape operator\",\n    \"description\": \"Returns the shape of a tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I32, I64]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.sign\",\n    \"summary\": \"Sign operation\",\n    \"description\": \"Returns NaN if x is NaN, 0 if x is 0, -1 if x < 0 and 1 if x > 0.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, F64, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, F64, I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.sin\",\n    \"summary\": \"Sine operator\",\n    \"description\": \"Computes element-wise Sine of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.slice\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Return a slice from 'input'.\",\n    \"description\": \"The output tensor is a tensor with dimensions described by 'size'\\nwhose values are extracted from 'input' starting at the offsets in\\n'begin'.\\n\\n`begin` is zero-based; `size` is one-based. If size[i] is -1, all remaining\\nelements in dimension i are included in the slice. In other words, this is\\nequivalent to setting:\\n  size[i] = input.dim_size(i) - begin[i]\\n\\n*Requirements*:\\n  0 <= begin[i] <= begin[i] + size[i] <= Di  for i in [0, n)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI4, I8, UI8, UI32, I1, TFL_Str, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"begin\", \"type\": \"TFL_I32OrI64Tensor\" },\n      { \"name\": \"size\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI4, I8, UI8, UI32, I1, TFL_Str, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.softmax\",\n    \"category\": \"Activation\",\n    \"summary\": \"Softmax operator\",\n    \"description\": \"Computes element-wise softmax activations with the following formula\\n\\n      exp(input * beta) / tf.reduce_sum(exp(input * beta), dim)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"beta\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.space_to_batch_nd\",\n    \"summary\": \"SpaceToBatchNd operator\",\n    \"description\": \"This operation reshapes space dimensions into the \\\"batch\\\" dimension 0\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"block_shape\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"paddings\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.space_to_depth\",\n    \"summary\": \"SpaceToDepth operator\",\n    \"description\": \"Rearranges blocks of spatial data, into depth. More specifically,\\n    this op outputs a copy of the input tensor where values from the `height`\\n    and `width` dimensions are moved to the `depth` dimension.\\n    `block_size` indicates the input block size.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.sparse_to_dense\",\n    \"summary\": \"Converts a sparse representation into a dense tensor.\",\n    \"description\": \"Builds an array `dense` with shape `output_shape` such that\\n\\n```\\n# If sparse_indices is scalar\\ndense[i] = (i == sparse_indices ? sparse_values : default_value)\\n\\n# If sparse_indices is a vector, then for each i\\ndense[sparse_indices[i]] = sparse_values[i]\\n\\n# If sparse_indices is an n by d matrix, then for each i in [0, n)\\ndense[sparse_indices[i][0], ..., sparse_indices[i][d-1]] = sparse_values[i]\\n```\\n\\nAll other values in `dense` are set to `default_value`.  If `sparse_values` is a\\nscalar, all sparse indices are set to this single value.\\n\\nIndices should be sorted in lexicographic order, and indices must not\\ncontain any repeats. If `validate_indices` is true, these properties\\nare checked during execution.\",\n    \"operands\": [\n      { \"name\": \"sparse_indices\", \"type\": \"TFL_I32OrI64Tensor\" },\n      { \"name\": \"output_shape\", \"type\": \"TFL_I32OrI64Tensor\" },\n      { \"name\": \"sparse_values\", \"type\": \"TFL_TensorOf<[I32, I64, I8, QI8, UI8, QUI8, TFL_Quint8, F32]>\" },\n      { \"name\": \"default_value\", \"type\": \"TFL_TensorOf<[I32, I64, I8, QI8, UI8, QUI8, TFL_Quint8, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dense\", \"type\": \"TFL_TensorOf<[I32, I64, I8, QI8, UI8, QUI8, TFL_Quint8, F32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.split\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Splits a tensor into `num_split` tensors along one dimension.\",\n    \"description\": \"Splits the `value` tensor along `split_dim` into a number of sub-tensors\\n    with same shape as the original one, except for `split_dim`. Same as\\n    tf.Split.\",\n    \"operands\": [\n      { \"name\": \"split_dim\", \"type\": \"TFL_TensorOf<[I32]>\" },\n      { \"name\": \"value\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I8, UI8, QI8, QUI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TFL_VariadicTensorOf<[F32, I16, I32, I8, UI8, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_splits\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.split_v\",\n    \"summary\": \"Splits a tensor into `num_split` tensors along one dimension.\",\n    \"description\": \"Splits the `value` tensor along `split_dim` into a number of sub-tensors\\n    with same shape as the original one, except for `split_dim`. The grouping\\n    of the resultant sub-tensors is decided by `size-splits`. Same as tf.SplitV.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TFL_TensorOf<[F32, I16, I32, I64, I8, UI8, QI8, QUI8, QI16]>\" },\n      { \"name\": \"size_splits\", \"type\": \"TFL_1DTensorOf<[I32], [I32]>\" },\n      { \"name\": \"split_dim\", \"type\": \"TFL_0DTensorOf<[I32], [I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TFL_VariadicTensorOf<[F32, I16, I32, I64, I8, UI8, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_splits\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.sqrt\",\n    \"summary\": \"Square root operator\",\n    \"description\": \"Computes element-wise Square root of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_TensorOf<[F32, QI8, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.square\",\n    \"summary\": \"Square operator\",\n    \"description\": \"Computes element-wise Square of input\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"TFL_FpTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.squared_difference\",\n    \"summary\": \"Squared difference operator\",\n    \"description\": \"Element-wise squared difference operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32, QI8]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, QI8]>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.squeeze\",\n    \"summary\": \"Removes dimensions of size 1 from the shape of a tensor.\",\n    \"description\": \"Given a tensor `input`, this operation returns a tensor of the same type with\\nall dimensions of size 1 removed. If you don't want to remove all size 1\\ndimensions, you can remove specific size 1 dimensions by specifying\\n`squeeze_dims`.\\n\\nFor example:\\n\\n```\\n# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]\\nshape(squeeze(t)) ==> [2, 3]\\n```\\n\\nOr, to remove specific size 1 dimensions:\\n\\n```\\n# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]\\nshape(squeeze(t, [2, 4])) ==> [1, 2, 3, 1]\\n```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"squeeze_dims\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>, [TFL_ArrayMaxCount<8>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.strided_slice\",\n    \"summary\": \"StridedSlice Op\",\n    \"description\": \"Return a strided slice from `input`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I8, UI8, UI32, QI8, QUI8, I1, I16, QI16, TFL_Quint8, TFL_Str]>\" },\n      { \"name\": \"begin\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"end\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"strides\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, I8, UI8, UI32, QI8, QUI8, I1, I16, QI16, TFL_Quint8, TFL_Str]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"end_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"I32Attr\" },\n      { \"name\": \"offset\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.sub\",\n    \"summary\": \"Subtraction operator\",\n    \"description\": \"Element-wise subtraction operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, QI16]>\" },\n      { \"name\": \"rhs\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfl.sum\",\n    \"summary\": \"Sum operator\",\n    \"description\": \"Computes the sum reduction along the specified axes\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" },\n      { \"name\": \"axes\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32, I64, QI8, QUI8, TFL_Quint8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.svdf\",\n    \"summary\": \"Single value decomposition filter operator\",\n    \"description\": \"The SVDF op is a decomposition of a densely connected op into low rank\\n    filters.\\n    For details: https://research.google.com/pubs/pub43813.html\\n                 https://arxiv.org/abs/1812.02802\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"feature_weights\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8]>\" },\n      { \"name\": \"time_weights\", \"type\": \"TFL_TensorOf<[F32, QI16]>\" },\n      { \"name\": \"input_gate_bias\", \"type\": \"TFL_TensorOfOrNone<[F32, QI32]>\" },\n      { \"name\": \"activation_state\", \"type\": \"TFL_StatefulTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rank\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"Hyperbolic tangent operator\",\n    \"description\": \"Computes element-wise Hyperbolic tangent of input\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16, TFL_Quint8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.tile\",\n    \"summary\": \"Tile operator.\",\n    \"description\": \"Constructs a tensor by tiling a given tensor.\\n\\n   This operation creates a new tensor by replicating input\\n   multiples times. The output tensor's i'th dimension has\\n   input.dims(i) * multiples[i] elements, and the values of input\\n   are replicated multiples[i] times along the 'i'th dimension.\\n   For example, tiling [a b c d] by [2] produces [a b c d a b c d].\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, UI8, QI8, QUI8, TFL_Str]>\" },\n      { \"name\": \"multiples\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I1, I32, I64, UI8, QI8, QUI8, TFL_Str]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.topk_v2\",\n    \"summary\": \"TopK operator\",\n    \"description\": \"Returns the top `k` largest element along each last dimensional slice of\\n    `input` and the indices of values within the last dimension of the input\\n    tensor.\\n\\n    Results are always sorted in the descending order.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QI8, QUI8]>\" },\n      { \"name\": \"k\", \"type\": \"TFL_TensorOf<[I16, I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"TFL_TensorOf<[F32, I8, I16, I32, I64, UI8, QI8, QUI8]>\" },\n      { \"name\": \"indices\", \"type\": \"TFL_TensorOf<[I16, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"Transpose operator\",\n    \"description\": \"Returns the Transpose of x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[I32, F32, I8, UI8, QI8, QUI8, TFL_I4, QI4, TFL_Quint8, I1, I64, QI16]>\" },\n      { \"name\": \"perm\", \"type\": \"TFL_TensorOf<[I32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I32, F32, I8, UI8, QI8, QUI8, TFL_I4, QI4, TFL_Quint8, I1, I64, QI16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.transpose_conv\",\n    \"summary\": \"Transpose convolution operator\",\n    \"description\": \"Performs transpose convolution operation on input.\",\n    \"operands\": [\n      { \"name\": \"output_shape\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"weights\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" },\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" },\n      { \"name\": \"bias\", \"type\": \"TFL_TensorOfOrNone<[F32, QI32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8, QUI8, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"TFL_PaddingAttr\" },\n      { \"name\": \"stride_h\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"stride_w\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unidirectional_sequence_lstm\",\n    \"summary\": \"Unidirectional sequence lstm operator\",\n    \"description\": \"A recurrent neural network specified by an LSTM cell. This Op supports\\n    unrolling the input along the time or batch dimensions, and\\n    implements the following operation for\\n    each element in the sequence s = 1...sequence_length:\\n      outputs[s] = state = activation(LSTMOp(inputs[s]))\\n\\n    where LSTMOp is LSTM TF Lite Op and the “activation” is the function passed\\n    as the “fused_activation_function” argument (if not “NONE”).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"input_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"input_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"input_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"input_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_forget_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_cell_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_output_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"cell_to_input_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"cell_to_forget_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"cell_to_output_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"input_gate_bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" },\n      { \"name\": \"forget_gate_bias\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"cell_bias\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"output_gate_bias\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"projection_weights\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"projection_bias\", \"type\": \"TFL_TensorOfOrNone<[F32]>\" },\n      { \"name\": \"input_activation_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"input_cell_state\", \"type\": \"TFL_StatefulTensor\" },\n      { \"name\": \"input_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"forget_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"cell_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" },\n      { \"name\": \"output_layer_norm_coefficients\", \"type\": \"TFL_TensorOfOrNone<[F32, QI8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"cell_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"proj_clip\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<F32Attr, 0.0f>, [TFL_FloatNonNegative]>\" },\n      { \"name\": \"time_major\", \"type\": \"BoolAttr\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"diagonal_recurrent_tensors\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"input_to_input_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"input_to_forget_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"input_to_cell_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"input_to_output_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"effective_hidden_scale_intermediate\", \"type\": \"OptionalAttr<TypeAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unidirectional_sequence_rnn\",\n    \"summary\": \"Unidirectional sequence rnn operator\",\n    \"description\": \"A recurrent neural network specified by an RNN cell. This Op takes in input\\n    in a format {batch_size, seq_len, input_size} or\\n    {seq_len, batch_size, input_size} if it's time-majored.\\n\\n    It implements the following operation for\\n    each element in the sequence s = 1...sequence_length:\\n      outputs[s] = state = activation(RNNOp(inputs[s]))\\n\\n    where RNNOp is RNNOp TF Lite Op and the “activation” is the function passed\\n    as the “fused_activation_function” argument (if not “NONE”).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"input_to_input_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"recurrent_to_input_weights\", \"type\": \"TFL_TensorOf<[F32, QI8]>\" },\n      { \"name\": \"input_gate_bias\", \"type\": \"TFL_FpTensor\" },\n      { \"name\": \"hidden_state\", \"type\": \"TFL_StatefulTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_FpTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"time_major\", \"type\": \"BoolAttr\" },\n      { \"name\": \"fused_activation_function\", \"type\": \"TFL_AFAttr\" },\n      { \"name\": \"asymmetric_quantize_inputs\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unique\",\n    \"summary\": \"Unique Op.\",\n    \"description\": \"This operation returns a tensor `output` containing all of the unique elements\\nof `input` sorted in the same order that they occur in `input`. This operation\\nalso returns a tensor `idx` the same size as `x` that contains the index of each\\nvalue of `input` in the unique output `output`. In other words:\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[I8, QI8, UI8, QUI8, I16, QI16, I32, I64, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I8, QI8, UI8, QUI8, I16, QI16, I32, I64, F32]>\" },\n      { \"name\": \"idx\", \"type\": \"TFL_I32OrI64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unpack\",\n    \"summary\": \"Unpacks a tensor along a dimension into multiple tensors\",\n    \"description\": \"Unpacks a given dimension of a rank-`R` tensor into `num` rank-`(R-1)` tensors.\\n\\n    Unpacks `num` tensors from `value` by chipping it along the `axis` dimension.\\n    For example, given a tensor of shape `(A, B, C, D)`;\\n\\n    If `axis == 0` then the i'th tensor in `output` is the slice `value[i, :, :, :]`\\n      and each tensor in `output` will have shape `(B, C, D)`. (Note that the\\n      dimension unpacked along is gone, unlike `split`).\\n\\n    If `axis == 1` then the i'th tensor in `output` is the slice `value[:, i, :, :]`\\n      and each tensor in `output` will have shape `(A, C, D)`.\\n    Etc.\\n\\n    This is the opposite of `pack`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, F16, BF16, I1, I8, UI8, I32, QI8, QUI8, I16, QI16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"TFL_VariadicTensorOf<[F32, F16, BF16, I1, I8, UI8, I32, QI8, QUI8, I16, QI16]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" },\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unsorted_segment_max\",\n    \"summary\": \"UnsortedSegmentMax operator\",\n    \"description\": \"Computes the maximum value along segments of a tensor such that\\n    output[i] = max(data[j....]) where segment_ids[j...] = i\\n    if the maximum is empty for a given segment ID i,\\n    it outputs the smallest possible value for the specific numeric type,\\n    output[i] = numeric_limits::lowest().\\n    Note the values of segment_ids are always validated to be less than\\n    num_segments and an error is thrown for out-of-bound indices.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32]>\" },\n      { \"name\": \"segment_ids\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unsorted_segment_min\",\n    \"summary\": \"UnsortedSegmentMin operator\",\n    \"description\": \"Computes the minimum value along segments of a tensor such that\\n    output[i] = min(data[j....]) where segment_ids[j...] = i\\n    if the minimum is empty for a given segment ID i,\\n    it outputs the largest possible value for the specific numeric type,\\n    output[i] = numeric_limits::max().\\n    Note the values of segment_ids are always validated to be less than\\n    num_segments and an error is thrown for out-of-bound indices.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32]>\" },\n      { \"name\": \"segment_ids\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unsorted_segment_prod\",\n    \"summary\": \"UnsortedSegmentProd operator\",\n    \"description\": \"Computes the product along segments of a tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32]>\" },\n      { \"name\": \"segment_ids\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.unsorted_segment_sum\",\n    \"summary\": \"UnsortedSegmentSum operator\",\n    \"description\": \"From a tensor segmentation, computes the `output` resulting from\\n    summing together elements mapped to the same segment_id. I.e. `output[i]` is\\n    equal to the tensor sum of all elements from the input tensor mapped to\\n    segment_id `i`. If no tensors are mapped to a particular included\\n    segment_id, the output at that indice will be a zero tensor with the\\n    appropriate shape. Note the values of segment_ids are always validated to be\\n    less than num_segments and an error is thrown for out-of-bound indices\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[F32, I32]>\" },\n      { \"name\": \"segment_ids\", \"type\": \"TFL_I32Tensor\" },\n      { \"name\": \"num_segments\", \"type\": \"TFL_I32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[F32, I32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.var_handle\",\n    \"summary\": \"Returns a handle to a variable resource from its name.\",\n    \"description\": \"Returns a handle for a variable resource from its name.\\n    container: the container this variable is placed in.\\n    shared_name: the name by which this variable is referred to.\",\n    \"results\": [\n      { \"name\": \"resource_handle\", \"type\": \"TFL_ResourceTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"container\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" },\n      { \"name\": \"shared_name\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.where\",\n    \"summary\": \"Returns locations of nonzero / true values in a tensor.\",\n    \"description\": \"This operation returns the coordinates of true elements in `condition`. The\\ncoordinates are returned in a 2-D tensor where the first dimension (rows)\\nrepresents the number of true elements, and the second dimension (columns)\\nrepresents the coordinates of the true elements. Keep in mind, the shape of\\nthe output tensor can vary depending on how many true values there are in\\n`condition`. Indices are output in row-major order.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"TFL_TensorOf<[I1, F32, TFL_Int32Or64, I8, UI8, UI32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"index\", \"type\": \"TFL_I64Tensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.while\",\n    \"summary\": \"While loop\",\n    \"description\": \"output = input; while (cond(output)) { output = body(output) }\\n\\n    While loop where all values are passes through arguments with implicit\\n    capture.\\n\\n    input: A list of input tensors whose types are T.\\n    output: A list of output tensors whose types are T.\\n    cond: A region that takes 'input' and returns a boolean scalar tensor.\\n    body: A region that takes a list of tensors and returns another\\n          list of tensors. Both lists have the same types.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_stateless\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfl.yield\",\n    \"summary\": \"Yield operation\",\n    \"description\": \"The \\\"yield\\\" operation represents a return operation within the conditional\\n    and body of structured control flow (e.g., while), and a terminator for ControlNodeOp.\\n    The operation takes a variable number of operands and produces no results.\\n    The operand number and types must match the signature of the region that contains the operation.\"\n  },\n  {\n    \"name\": \"tfl.zeros_like\",\n    \"summary\": \"ZerosLike operator\",\n    \"description\": \"Returns a tensor of zeros with the same shape and type as the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFL_TensorOf<[I64, I32, F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFL_TensorOf<[I64, I32, F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfr.build_list\",\n    \"description\": \"The `build_list` operation builds a tensor list from a list of tensors, or\\n   an tfr.attr from a list of scalars.\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = tfr.build_list(%2, %1, %0) :\\n      (tfr.tensor, tfr.tensor, tfr.tensor) -> tfr.tensor_list\\n    %3 = tfr.build_list(%2, %1, %0) : (i32, i32, i32) -> tfr.attr\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"Variadic<TFR_allowedBuiltListType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFR_allowedListResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tfr.call\",\n    \"description\": \"The `call` operation represents a direct call to a function that is within\\n    the same symbol scope as the callee. The operands and result types of the\\n    call must match the specified function type. The callee is encoded as a\\n    symbol reference attribute named \\\"callee\\\".\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = tfr.call @my_add(%0, %1) : (tfr.tensor, f32) -> tfr.tensor_list\\n    ```\\n\\n    Note that the operands of the `call` operation can only be with tfr.tensor,\\n    tfr.tensor_list, tfr.attr and mlir float and integer types. The results of\\n    the `call` operation can only be with tfr.tensor and tfr.tensor_list types.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFR_allowedArgType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<TFR_allowedResultType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $args `)` attr-dict `:` functional-type($args, results)\"\n  },\n  {\n    \"name\": \"tfr.cast\",\n    \"description\": \"The `cast` operation converts the operand with built-in tensor type to\\n    tfr.tensor type, or vice versa.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = tfr.cast(%0) : tensor<f32> -> !tfr.tensor\\n    %3 = tfr.cast(%1) : !tfr.tensor -> tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFR_singleTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFR_singleTensorType\" }\n    ]\n  },\n  {\n    \"name\": \"tfr.constant\",\n    \"description\": \"The `attr` operation stores TF op's attribute, which doesn't support\\n    arithmetic operations.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = \\\"tfr.constant\\\"() { value: i32 } : () -> !tfr.attr\\n    %2 = \\\"tfr.constant\\\"() { value: [i32, f32] } : () -> !tfr.attr\\n    %3 = tfr.constant [i32, f32] -> !tfr.attr\\n    %4 = tfr.constant f32 -> !tfr.attr\\n    ```\",\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFR_AttrType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TFR_allowedConstValues\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `->` type($out)\"\n  },\n  {\n    \"name\": \"tfr.constant_tensor\",\n    \"description\": \"The `constant_tensor` operation converts the operand with non-built-in\\n    tensor type to built-in tensor type or tfr.tensor type. If it is built-in\\n    tensor type, the shape shouldn't be changed during the conversion.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = tfr.constant_tensor(%0) : f32 -> tensor<f32>\\n    %3 = tfr.constant_tensor(%2) : vector<1xf32> -> tensor<1xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFR_AllAttrTypes\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFR_singleTensorType\" }\n    ]\n  },\n  {\n    \"name\": \"tfr.equal\",\n    \"description\": \"The `equal` operation compares the values of the tfr.attr type arguments.\\n    The operation returns an i1 boolean indicating if the two values are the\\n    same.\\n    Example:\\n\\n    ```mlir\\n    %x = tfr.equal %lhs, %rhs -> i1\\n    %x = \\\"tfr.equal\\\"(%lhs, %rhs) : (!tfr.attr, !tfr.attr) -> i1\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TFR_AttrType\" },\n      { \"name\": \"rhs\", \"type\": \"TFR_AttrType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BoolLike\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `->` type($result)\"\n  },\n  {\n    \"name\": \"tfr.func\",\n    \"summary\": \"TFR Function defines a composition of other ops\",\n    \"description\": \"Defines a function that can be used to decompose an TF function call to\\n    the invocation of a set of other TF ops.\\n\\n    Syntax:\\n\\n    ```\\n    op ::= `tfr.func` visibility? symbol-ref-id `(` argument-list `)` (`->`\\n    function-result-list)? function-attributes? region\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    tfr.func @foo(%arg0: !tfr.tensor, %arg1: !tfr.tensor_list<T>,\\n                  %arg2: int {tfr.name=\\\"T\\\", tfr.default=1})\\n        attributes {qux: \\\"quux\\\"} {\\n      tfr.return\\n    }\\n    ```\\n\\n    Note the arguments are ordered by the following rule:\\n      tfr.tensor > tfr.tensor_list > tfr.attr/i32/...,\\n    and only one trfr.tensor_list argument is allowed.\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfr.get_element\",\n    \"description\": \"The `get_element` operation extracts one tfr.tensor element from a\\n    tfr.tensor_list.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = tfr.get_element %1[%0] : (tfr.tensor, index) -> tfr.tensor\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor_list\", \"type\": \"TFR_TensorListType\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"assemblyFormat\": \"$tensor_list `[` $index `]` attr-dict `:`\\n      `(` type($tensor_list) `,` type($index) `)` `->` type($out)\"\n  },\n  {\n    \"name\": \"tfr.get_element_type\",\n    \"description\": \"The `get_element_type` operation gets the element type of a tfr.tensor and\\n    returns !tfr.attr.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = \\\"tfr.get_element_type\\\"(%0) : !tfr.tensor -> !tfr.attr\\n    %1 = tfr.get_element_type %0 -> !tfr.attr\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TFR_AttrType\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `->` type($out)\"\n  },\n  {\n    \"name\": \"tfr.get_length\",\n    \"description\": \"The `get_length` operation returns the number of tensors for a\\n    tfr.tensor_list.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = tfr.get_length(%1) : tfr.tensor -> index\\n    %2 = tfr.get_length %1 -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor_list\", \"type\": \"TFR_TensorListType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"$tensor_list attr-dict `->` type($out)\"\n  },\n  {\n    \"name\": \"tfr.get_shape\",\n    \"description\": \"The `get_shape` operation gets the shape of a tfr.tensor and returns\\n    !shape.shape type.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = \\\"tfr.get_shape\\\"(%0) : !tfr.tensor -> !shape.shape\\n    %1 = tfr.get_shape %0 -> !shape.shape\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"Shape_ShapeType\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict `->` type($out)\"\n  },\n  {\n    \"name\": \"tfr.quant_act_range\",\n    \"description\": \"The `quant_act_range` returns the a pair of integers to indicate the fixed\\n   range for the fused activation `act` with the quantization defined by the\\n   `scale` and `zero point`. Currently, the allowed activations are\\n   `NONE`, `RELU`, `RELU6` and `RELU_N1_TO_1`.\\n\\n    Example:\\n\\n    ```mlir\\n    %3, %4 = tfr.quant_act_range(%2, %1, %0) :\\n        (tfr.attr, float, i64) -> (tfr.tensor, tfr.tensor)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"act\", \"type\": \"TFR_AttrType\" },\n      { \"name\": \"scale\", \"type\": \"F32\" },\n      { \"name\": \"zp\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"min\", \"type\": \"TFR_TensorType\" },\n      { \"name\": \"max\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"assemblyFormat\": \"`(` $act `,` $scale `,` $zp `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfr.quant_qparam\",\n    \"description\": \"The `quant_qparam` returns the quantization parameter of the input\\n   tensors.\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = tfr.quant_qparam(%0) : (tfr.tensor) -> (float, tfr.tensor)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"scale\", \"type\": \"TFR_TensorType\" },\n      { \"name\": \"zp\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"assemblyFormat\": \"`(` $input `)` attr-dict `:` functional-type($input, results)\"\n  },\n  {\n    \"name\": \"tfr.quant_raw_data\",\n    \"description\": \"The `quant_raw_data` removes the quantization parameter from the intput\\n   tensor(s).\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = tfr.quant_raw_data(%0) : (tfr.tensor) -> (tfr.tensor)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFR_AllTensorTypes\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFR_AllTensorTypes\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $input `)` attr-dict `:` functional-type($input, results)\"\n  },\n  {\n    \"name\": \"tfr.quant_rescale\",\n    \"description\": \"The `quant_rescale` rescales the elements of the integer tensor by the\\n   floating-point rescale factor. This op needs to be legalized to the preferred\\n   operations of the backends.\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = tfr.quant_rescale(%2, %1, %0) :\\n        (tfr.tensor, tfr.tensor, i64) -> (tfr.tensor)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFR_TensorType\" },\n      { \"name\": \"scale\", \"type\": \"TFR_TensorType\" },\n      { \"name\": \"zp\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"assemblyFormat\": \"`(` $input `,` $scale `,` $zp `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfr.quant_scale_factor\",\n    \"description\": \"The `quant_scale_factor` computes the effective scale factor according to the\\n   output scale and input scales.\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = tfr.quant_scale_factor(%0) : (f32, tfr.tensor_list) -> (tfr.tensor)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"out_scale\", \"type\": \"F32\" },\n      { \"name\": \"in_scales\", \"type\": \"TFR_TensorListType\" }\n    ],\n    \"results\": [\n      { \"name\": \"scale_factor\", \"type\": \"TFR_TensorType\" }\n    ],\n    \"assemblyFormat\": \"`(` $out_scale `,` $in_scales `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfr.return\",\n    \"description\": \"A terminator operation for regions that appear in the body of  `tfr.func`\\n    functions. The operands to the `tfr.return` are the result values returned\\n    by an invocation of the `tfr.func`.\\n\\n    Note that only the tfr.tensor and tfr.tensor_list can be returned.\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<TFR_allowedResultType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($arguments^ `:` type($arguments))?\"\n  },\n  {\n    \"name\": \"tfrt_dht.allocate_buffer\",\n    \"summary\": \"tfrt_dht.allocate_buffer operation\",\n    \"description\": \"An operation that creates an buffer.\\n    It takes in the size of the buffer in bytes and the alignment in bytes and\\n    outputs a buffer of that size.\\n\\n    Example:\\n      %size = tfrt.constant.i64 164\\n      %alignment = tfrt.constant.i64 8\\n      %buf = tfrt_dht.allocate %size, %alignment\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HostBufferType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.bool.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.bool.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.bool.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.bool.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.bool.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex128.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex128.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex128.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex128.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex128.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex64.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex64.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex64.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex64.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.complex64.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.f32.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.f32.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.f32.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.f32.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.f32.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i32.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i32.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i32.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i32.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i32.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i64.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i64.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i64.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i64.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.i64.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui16.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui16.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui16.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui16.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui16.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui32.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui32.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui32.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui32.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui32.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui64.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui64.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui64.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui64.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui64.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui8.0\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui8.1\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui8.2\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui8.3\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.create_uninitialized_tensor.ui8.4\",\n    \"summary\": \"tfrt_dht.create_uninitialized_tensor operation\",\n    \"description\": \"An operation that creates an uninitialized tensor.\\n    It takes a shape attribute and outputs a tensor as output.\\n\\n    Example:\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.0 []\\n      %3 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i64, 2 : i64]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$shape attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.bool\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.complex128\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.complex64\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.f32\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.i32\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.i64\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.ui16\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.ui32\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.ui64\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.fill_tensor_with_constant.ui8\",\n    \"summary\": \"tfrt_dht.fill_tensor_with_constant operation\",\n    \"description\": \"An operation that fills an input tensor with a value. It takes an input\\n    tensor and a chain as inputs and a constant value attribute, and outputs a\\n    chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %3 = tfrt_dht.fill_tensor_with_constant.i32 %2, %1 0 : i32\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.get_buffer\",\n    \"summary\": \"tfrt_dht.get_buffer operation\",\n    \"description\": \"tfrt_dht.get_buffer returns the HostBuffer that backs the given dense host\\n    tensor.\\n\\n    Example:\\n      %t = tfrt_dht.create_uninitialized_tensor.i32.2 [3 : i32, 2 : i32]\\n      %ch1 = tfrt.new.chain\\n      %buf, %ch2 = tfrt_dht.get_buffer %t, %ch1\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"HostBufferType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.get_buffer_slice\",\n    \"summary\": \"tfrt_dht.get_buffer_slice operation\",\n    \"description\": \"An operation that gets a slice of a buffer.\\n    It takes in the parent buffer and the size and offset of the new buffer. It\\n    returns a buffer that points to the data allocated by the parent buffer.\\n\\n    Example:\\n      %parent_buf = tfrt_dht.allocate %parent_size, %alignment\\n      %offset = tfrt.constant.i64 0\\n      %size = tfrt.constant.i64 64\\n      %buf_a = tfrt_dht.get_buffer_slice %parent_buf, %offset, %size\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"HostBufferType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.get_tensor_shape\",\n    \"summary\": \"tfrt_dht.get_tensor_shape operation\",\n    \"description\": \"An operation that returns the shape of the dense host tensor.\\n\\n    Example:\\n      %0 = tfrt_dht.get_tensor_shape %t\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TS_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.bool\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.complex128\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.complex64\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.f32\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.i32\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.i64\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.ui16\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.ui32\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.ui64\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.make_tensor.ui8\",\n    \"summary\": \"tfrt_dht.make_tensor operation\",\n    \"description\": \"An operation that creates a tensor from the given shape and buffer.\\n    Created tensor shares the memory with the given buffer.\\n\\n    The size of the buffer must match the size needed to hold the tensor,\\n    i.e. the number of elements, of requested dtype, in the given shape.\\n\\n    Example:\\n      %ch0 = tfrt.new.chain\\n      %cuda_host_buf, %ch1 = cuda.mem.allocate_host %size, %alignment, %ch0\\n      %tensor, %ch2 = tfrt_dht.make_tensor.f32 %cuda_host_buf, %shape, %ch0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"TensorType\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.print_buffer\",\n    \"summary\": \"tfrt_dht.print_buffer operation\",\n    \"description\": \"An operation that prints a buffer.\\n\\n    Example:\\n      %chain1 = tfrt_dht.print_buffer %buffer, %chain0\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.print_tensor\",\n    \"summary\": \"tfrt_dht.print_tensor operation\",\n    \"description\": \"An operation that prints a tensor. It takes a tensor and chain as input and\\n    outputs a chain.\\n\\n    Example:\\n      %3 = tfrt_dht.print_tensor %1, %2\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.bool\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.complex128\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.complex64\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.f32\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.i32\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.i64\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.ui16\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.ui32\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.ui64\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.set_tensor_with_constant_values.ui8\",\n    \"summary\": \"tfrt_dht.set_tensor_with_constant_values operation\",\n    \"description\": \"An operation that sets an input tensor with given values. It takes an input\\n    tensor and a chain as inputs and a list of values as attribute (for complex\\n    element type, real and complex values are interleaved, resulting in twice\\n    the number of values overall). This operation outputs a chain.\\n\\n    Example:\\n      %1 = tfrt.new.chain\\n      %2 = tfrt_dht.create_uninitialized_tensor.i32.2 [1 : i32, 2 : i32]\\n      %3 = tfrt_dht.set_tensor_with_constant_values.i32 %2, %1 [8 : i32, 9 : i32]\\n      %4 = tfrt_dht.create_uninitialized_tensor.complex64.2 [1 : i32, 2 : i32]\\n      %5 = tfrt_dht.set_tensor_with_constant_values.complex64 %2, %1\\n          [8.000e+00 : f32, 0.000e+00 : f32, 9.000e+00 : f32, 0.000e+00 : f32]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands $values attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.bool\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.complex128\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.complex64\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.f32\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.i32\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.i64\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.ui16\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.ui32\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.ui64\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_dht.tensor_equal.ui8\",\n    \"summary\": \"tfrt_dht.tensor_equal operation\",\n    \"description\": \"An operation that checks if two input tensors are equal. It takes two input\\n    tensors and a chain as inputs and outputs an i1 result and a chain output.\\n\\n    The chain output value is needed to prevent write-after-read hazard.\\n\\n    Example:\\n      %4, %5 = tfrt_dht.tensor_equal.i32 %1, %2, %3\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I1\" },\n      { \"name\": \"result1\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.batch_function\",\n    \"summary\": \"Fallback ExecuteOp specialized for tf.BatchFunction.\",\n    \"description\": \"This kernel executes a variant tf.BatchFunction kernel that supports having\\n    the `f` attribute as a BEF function.\\n\\n    Example:\\n      %res = tfrt_fallback_async.batch_function device(\\\"/CPU:0\\\") @f(%input, %captured_input)  {\\n          num_batch_threads = 1,\\n          max_batch_size = 4,\\n          allowed_batch_sizes = [2 , 4],\\n          batch_timeout_micros = 50,\\n          container = \\\"container\\\",\\n          shared_name = \\\"shared_name\\\",\\n          batching_queue = \\\"batching_queue\\\",\\n          enable_large_batch_splitting = false,\\n          Tin = [f32],\\n          Tcaptured = [f32],\\n          Tout = [f32]} : 1\\n\\n    Note that the trailing number indicates the number of results.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"f\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_fallback_async.const_dense_tensor\",\n    \"summary\": \"Create a constant dense tensorflow tensor.\",\n    \"description\": \"ConstDenseTensorOp creates a constant dense tensorflow tensor.\\n\\n    Example:\\n      %tensor = tfrt_fallback_async.const_dense_tensor dense<[0, 1, 2]> : tensor<3xi32>\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.const_string_tensor\",\n    \"summary\": \"Create a constant string tensorflow tensor.\",\n    \"description\": \"ConstStringTensorOp creates a constant string tensorflow tensor.\\n\\n    Example:\\n      %tensor = tfrt_fallback_async.const_string_tensor {shape = [1, 2], value = [\\\"const\\\", \\\"string\\\"]}\\n\\n    Note: if the entries in `value` are all the same, we can just keep one copy.\\n      In other words, the following two lines are effectively the same.\\n      %tensor = tfrt_fallback_async.const_string_tensor {shape = [1, 2], value = [\\\"string\\\", \\\"string\\\"]}\\n      %tensor = tfrt_fallback_async.const_string_tensor {shape = [1, 2], value = [\\\"string\\\"]}\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"value\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.const_tensor_proto\",\n    \"summary\": \"Create a tensorflow tensor from serialized tensor proto\",\n    \"description\": \"Create a tensorflow tensor from serilaized tensor proto.\\n\\n    Example:\\n      %tensor = tfrt_fallback_async.const_tensor_proto \\\"<serialized proto content>\\\"\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"serialized_tensor_proto\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$serialized_tensor_proto attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.copy_if_small\",\n    \"summary\": \"Copy the CPU fallback tensor if it is small\",\n    \"description\": \"This kernel performs deep copy on the input tensor if it is small, to avoid\\n    atomic contention on its refcount.\\n\\n    Note that this kernel always create a new AsyncValue for each result to\\n    avoid atomic contention on AsyncValue's refcount.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` `(` type($operand) `)` `->` `(` type($results) `)`\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.corert_tensorhandle_to_fallback_tensor\",\n    \"summary\": \"Convert corert tensorhandle to fallback tensor\",\n    \"description\": \"Convert the corert tensorhandle to the fallback tensor.\\n\\n    args: a list of corert tensorhandles.\\n    device: the name of the tensorflow device that is associated with the\\n      output fallback tensor.\\n\\n    results: the converted fallback tensors.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($args) `)` `->` `(` type($results) `)`\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.createop\",\n    \"summary\": \"The Fallback CreateOp\",\n    \"description\": \"The CreateOp creates the tensorflow::OpKernel in the fallback context.\\n\\n    op_key: The unique key to identify this op.\\n    num_args: The number of inputs.\\n    device: The tensorflow device. eg. \\\"/CPU:0\\\"\\n    op_attrs: The tensorflow attributes excluding the func attrs.\\n    op_func_attrs: The func attrs.\\n    op_name: The tensorflow op name. eg. \\\"tf.AddV2\\\"\\n\\n    Example:\\n      %out_ch = tfrt_fallback_async.createop(%in_ch) key(0) device(\\\"/CPU:0\\\")\\n        \\\"some.op\\\"() {attr1 = value, attr2 = value2} {f_attr1 = \\\"fn1\\\", f_attr2 = \\\"fn2\\\"} num_args(1)\",\n    \"operands\": [\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_args\", \"type\": \"I64Attr\" },\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_fallback_async.executeop\",\n    \"summary\": \"The Fallback ExecuteOp\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device.\\n\\n    Example:\\n      %res = tfrt_fallback_async.executeop key(0) cost(100) device(\\\"/CPU:0\\\") \\\"some.op\\\"(%arg) : 1\\n\\n    Note that the trailing number indicates the number of results.\\n\\n    The func attrs and op attrs are placed in two separate regions.\\n\\n    Example:\\n      %res = tfrt_fallback_async.executeop key(0) device(\\\"/CPU:0\\\") \\\"some.op\\\"(%arg)\\n          {attr1 = value, attr2 = value2} {f_attr1 = \\\"fn1\\\", f_attr2 = \\\"fn2\\\"} : 1\\n\\n    Note that in this case, the first bracket contains op attributes other than\\n    function attributes, and the second braket contains function attributes,\\n    which represent function names.\\n\\n    Refer to b/172597167 for approaches considered for supporting function\\n    attributes.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"_tfrt_cost\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_fallback_async.executeop.allocator\",\n    \"summary\": \"The Fallback ExecuteOp with custom allocator\",\n    \"description\": \"Similar to ExecuteOp but takes a custom allocator for allocating output tensors.\",\n    \"operands\": [\n      { \"name\": \"allocator\", \"type\": \"TFAllocatorType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"_tfrt_cost\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_fallback_async.executeop.seq\",\n    \"summary\": \"The sequenced version of Fallback ExecuteOp\",\n    \"description\": \"The ExecuteOpSeq executes an operation on the specified device, similar to\\n    ExecuteOp. In addition, it takes an in_op_chain and produces an out_op_chain\\n    that can be used to sequence op executions. ExecuteOpSeq is nonstrict on\\n    in_op_chain.\\n\\n    Example:\\n      %op_ch_out, %res = tfrt_fallback_async.executeop.seq(%op_ch_in)\\n        key(0) cost(100) device(\\\"/CPU:0\\\") \\\"some.op\\\"(%arg) : 1\\n\\n    Note that the trailing number indicates the number of results.\\n\\n    The func attrs and op attrs are placed in two separate regions.\\n\\n    Example:\\n      %op_ch_out, %res = tfrt_fallback_async.executeop.seq(%op_ch_in)\\n        key(0) cost(100) device(\\\"/CPU:0\\\") \\\"some.op\\\"(%arg)\\n        {fn = function_1} {attr1 = value, attr2 = value2} : 1\\n\\n    Note that in this case, the first braket contains op attributes other than\\n    function attributes, and the second braket contains function attributes,\\n    which represent function names.\\n\\n    Refer to b/172597167 for approaches considered for supporting function\\n    attributes.\",\n    \"operands\": [\n      { \"name\": \"in_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"_tfrt_cost\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_fallback_async.executeop.seq.allocator\",\n    \"summary\": \"The sequenced version of Fallback ExecuteOp with custom allocator\",\n    \"description\": \"Similar to ExecuteOpSeq but takes a custom allocator for allocating output tensors.\\n\\n    Example:\\n      %op_ch_out, %res = tfrt_fallback_async.executeop.seq.allocator(%op_ch_in, %allocator)\\n        key(0) cost(100) device(\\\"/CPU:0\\\") \\\"some.op\\\"(%arg) : 1\",\n    \"operands\": [\n      { \"name\": \"in_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"allocator\", \"type\": \"TFAllocatorType\" },\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_op_chain\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_func_attrs\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I64Attr\" },\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"_tfrt_cost\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_fallback_async.fallback_tensor_to_corert_tensorhandle\",\n    \"summary\": \"Convert fallback tensor to corert tensorhandle\",\n    \"description\": \"Convert the fallback tensor to corert tensorhandle.\\n\\n    args: a list of fallback tensors.\\n    device: the name of the tensorflow device that is associated with the\\n      input fallback tensors.\\n\\n    results: the converted corert tensorhandles.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<CoreRT_TensorHandleType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($args) `)` `->` `(` type($results) `)`\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.get_resource\",\n    \"summary\": \"get a tensor in resource array\",\n    \"description\": \"Get a tensor in resource array.\\n\\n    indices: the indices in the resource array.\\n    results: the tensor values for the corresponding indices.\\n\\n    in_ch and out_ch are for control dependencies.\",\n    \"operands\": [\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($in_ch) `)` `->` `(` type($out_ch) `,` type($results) `)`\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.predicate\",\n    \"summary\": \"Converts a fallback tensor to a bool\",\n    \"description\": \"Note: this kernel is used for CPU tensors.\\n\\n    Converts a fallback tensor to a bool with the following rules:\\n\\n    - For 0D tensors, truthiness is determined by comparing against a \\\"zero\\\"\\n      value. For numerical types it is the obvious zero. For strings it is the\\n      empty string.\\n\\n    - For >0D tensors, truthiness is determined by looking at the number of\\n      elements. If has zero elements, then the result is false. Otherwise the\\n      result is true.\\n\\n    input: a fallback tensor representing the condition.\\n    device: the name of the tensorflow device that is associated with the\\n      input fallback tensor.\\n\\n    output: the converted bool.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_async.set_resource\",\n    \"summary\": \"Set a tensor in resource array\",\n    \"description\": \"Set a tensor in resource array.\\n\\n    arg: the tensor to be set in the resource array.\\n    index: the index in the resource array\\n\\n    in_ch and out_ch are for control dependencies.\",\n    \"operands\": [\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" },\n      { \"name\": \"arg\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device\", \"type\": \"StrAttr\" },\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.convert_dht_to_fallback_tensor\",\n    \"summary\": \"convert a DHT to a fallback tensor\",\n    \"description\": \"Convert a TFRT DHT to a fallback tensor.\\n\\n    dht: the input DHT.\\n    fallback_tensor: The output fallback tensor\",\n    \"operands\": [\n      { \"name\": \"dht\", \"type\": \"TensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"fallback_tensor\", \"type\": \"TFTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($fallback_tensor)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.convert_fallback_tensor_to_dht\",\n    \"summary\": \"convert fallback tensor to a DHT\",\n    \"description\": \"Convert a fallback tensor to a TFRT DHT.\\n\\n    fallback_tensor: The input fallback tensor\\n    dht: the output DHT.\",\n    \"operands\": [\n      { \"name\": \"fallback_tensor\", \"type\": \"TFTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"dht\", \"type\": \"TensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($dht)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.convert_sht_to_fallback_tensor\",\n    \"summary\": \"convert a SHT to a fallback tensor\",\n    \"description\": \"Convert a TFRT SHT to a fallback tensor.\\n\\n    sht: the input SHT.\\n    fallback_tensor: The output fallback tensor\",\n    \"operands\": [\n      { \"name\": \"sht\", \"type\": \"TensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"fallback_tensor\", \"type\": \"TFTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($fallback_tensor)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.createop\",\n    \"summary\": \"The Fallback CreateOp\",\n    \"description\": \"The CreateOp creates the tensorflow::OpKernel in the fallback context.\\n\\n    op_key: The unique key to identify this op.\\n    num_args: The number of inputs.\\n    device: The tensorflow device. eg. \\\"/CPU:0\\\"\\n    op_attrs: The tensorflow attributes excluding the func attrs.\\n    op_name: The tensorflow op name. eg. \\\"tf.AddV2\\\"\\n\\n    Example:\\n      tfrt_fallback_sync.createop() key(0) device(\\\"/CPU:0\\\")\\n        \\\"some.op\\\"() {attr1 = value, attr2 = value2} {f_attr1 = \\\"fn1\\\", f_attr2 = \\\"fn2\\\"} num_args(1)\",\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.executeop\",\n    \"summary\": \"The Fallback Sync ExecuteOp\",\n    \"description\": \"The ExecuteOp executes an operation on the specified device.\\n\\n    Example:\\n      %res = tfrt_fallback_sync.executeop \\\"some.op\\\"(%arg) : 1\\n\\n    Note that the trailing number indicates the number of results.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"node_def\", \"type\": \"StrAttr\" },\n      { \"name\": \"op_key\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"`(`operands`)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.get_resource\",\n    \"summary\": \"get a tensor in resource array\",\n    \"description\": \"Get a tensor in resource array.\\n\\n    indices: the indices in the resource array.\\n    results: the tensor values for the corresponding indices.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.get_resource_dht\",\n    \"summary\": \"get a DHT in resource array\",\n    \"description\": \"Get a tensor in resource array.\\n\\n    indices: the indices in the resource array.\\n    results: the tensor values for the corresponding indices.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.get_sparse_matrix_resource\",\n    \"summary\": \"get a sparse matrix from resource array\",\n    \"description\": \"Get a sparse matrix from resource array.\\n\\n    indices: the indices in the resource array.\\n    results: the tensor values for the corresponding indices.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TFTensorType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.set_resource\",\n    \"summary\": \"Set a tensor in resource array\",\n    \"description\": \"Set a tensor in resource array.\\n\\n    arg: the tensor to be set in the resource array.\\n    index: the index in the resource array\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.set_resource_dht\",\n    \"summary\": \"Set a DHT in resource array\",\n    \"description\": \"Set a DHT in resource array.\\n\\n    arg: the tensor to be set in the resource array.\\n    index: the index in the resource array\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_fallback_sync.set_sparse_matrix_resource\",\n    \"summary\": \"Set a Sparse matrix in resource array\",\n    \"description\": \"Set a sparse matrix in resource array.\\n\\n    arg: the matrix to be set in the resource array.\\n    index: the index in the resource array\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"TFTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_tensor.bitcast\",\n    \"summary\": \"tensor bitcast operation\",\n    \"description\": \"Bitcast a tensor from one type to another type of equivalent element width.\\n    If both are ranked, then the rank should be the same and static dimensions\\n    should match.\\n\\n    Example:\\n\\n    ```mlir\\n    // Bitcast from unsigned to signed or signless integer.\\n    %2 = tensor.bitcast %1 : tensor<4xui32> to tensor<4xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"TensorOf<[AnySignlessInteger, AnyUnsignedInteger, AnySignedInteger, AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"TensorOf<[AnySignlessInteger, AnyUnsignedInteger, AnySignedInteger, AnyFloat]>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.cast\",\n    \"summary\": \"tensor cast operation\",\n    \"description\": \"Convert a tensor from one type to an equivalent type without changing any\\n    data elements. The source and destination types must both be tensor types\\n    with the same element type. If both are ranked, then the rank should be the\\n    same and static dimensions should match. The operation is invalid if\\n    converting to a mismatching constant dimension.\\n\\n    Example:\\n\\n    ```mlir\\n    // Convert from unknown rank to rank 2 with unknown dimension sizes.\\n    %2 = tensor.cast %1 : tensor<*xf32> to tensor<?x?xf32>\\n\\n    // Convert to a type with more known dimensions.\\n    %3 = tensor.cast %2 : tensor<?x?xf32> to tensor<4x?xf32>\\n\\n    // Discard static dimension and rank information.\\n    %4 = tensor.cast %3 : tensor<4x?xf32> to tensor<?x?xf32>\\n    %5 = tensor.cast %4 : tensor<?x?xf32> to tensor<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.collapse_shape\",\n    \"summary\": \"operation to produce a tensor with a smaller rank\",\n    \"description\": \"The `tensor.collapse_shape` op produces a new tensor of lower (or equal)\\n    rank whose dimension sizes are a reassociation of the original `src` dimensions.\\n\\n    A reassociation is defined as a continuous grouping of dimensions and is\\n    represented by an array of DenseI64ArrayAttr attribute. The reassociation\\n    maps are applied to the operand shape to obtain the result shape.\\n\\n\\n    Example:\\n\\n    ```mlir\\n    // Dimension collapse (i, j) -> i' and k -> k'\\n    %b = tensor.collapse_shape %a [[0, 1], [2]]\\n        : tensor<?x?x?xf32> into tensor<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reassociation\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$src $reassociation attr-dict `:` type($src) `into` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.concat\",\n    \"summary\": \"tensor concatenation operation\",\n    \"description\": \"The \\\"concat\\\" operation constructs a tensor out of a variadic list of input\\n    tensors, concatenated along a static dimension number. All inputs and the\\n    result type must share the same rank.\\n\\n    `dim` specifies the dimension along which to concatenate. The size of the\\n    concatenated dimension in the result must be equal to the sum of the sizes\\n    of the inputs along that dimension. All other dimensions in both the inputs\\n    and result must be the same size.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = tensor.concat dim(0) %0, %1, %2 :\\n        (tensor<3x6xf32>, tensor<3x6xf32>, tensor<1x6xf32) -> tensor<7x6xf32>\\n\\n    // Dynamic + dynamic -> static\\n    %0 = tensor.concat dim(1) %0, %1, %2 :\\n        (tensor<3x?xf32>, tensor<3x2xf32>, tensor<3x?xf32) -> tensor<3x10xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"`dim` `(` $dim `)` $inputs attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.dim\",\n    \"summary\": \"dimension index operation\",\n    \"description\": \"The `tensor.dim` operation takes a tensor and a dimension operand of type\\n    `index`. It returns the size of the requested dimension of the given\\n    tensor. If the dimension index is out of bounds, the behavior is undefined.\\n\\n    The specified tensor type is that of the first operand.\\n\\n    Example:\\n\\n    ```mlir\\n    // Always returns 4, can be constant folded:\\n    %c0 = arith.constant 0 : index\\n    %x = tensor.dim %A, %c0 : tensor<4x?xf32>\\n\\n    // Return the dynamic dimension of %A.\\n    %c1 = arith.constant 1 : index\\n    %y = tensor.dim %A, %c1 : tensor<4x?xf32>\\n\\n    // Equivalent generic form:\\n    %x = \\\"tensor.dim\\\"(%A, %c0) : (tensor<4x?xf32>, index) -> index\\n    %y = \\\"tensor.dim\\\"(%A, %c1) : (tensor<4x?xf32>, index) -> index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyNon0RankedOrUnrankedTensor\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $source `,` $index `:` type($source)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.empty\",\n    \"summary\": \"empty tensor operation\",\n    \"description\": \"`tensor.empty` is an operation that defines a tensor of a particular shape.\\n    The shape could be dynamic or static. The contents of the tensor are\\n    unspecified and the only purpose of the op result is to materialize the\\n    specified shape in IR and make it available to other transformations.\\n\\n    `tensor.empty` is useful in transformations that expect destination style\\n    ops. I.e., ops that implement `DestinationStyleOpInterface`. Ops that are\\n    not in destination style can be made compatible with such transformations\\n    with a `tensor.empty` destination.\\n\\n    Note: This op can be lowered to a `bufferization.alloc_tensor`, at which\\n    point it turns into an explicit buffer allocation.\",\n    \"operands\": [\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"`(`$dynamicSizes`)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.expand_shape\",\n    \"summary\": \"operation to produce a tensor with a higher rank\",\n    \"description\": \"The `tensor.expand_shape` op produces a tensor of higher (or equal)\\n    rank than the operand `src` whose dimension sizes are a reassociation of\\n    `src`.\\n\\n    A reassociation is defined as a continuous grouping of dimensions and is\\n    represented with an array of DenseI64ArrayAttr attribute.  The reassociation\\n    maps applied to the result tensor with the higher rank must result in the\\n    operand tensor with the smaller rank.\\n\\n    The representation for the output shape supports a partially-static\\n    specification via attributes specified through the `static_output_shape`\\n    argument.  A special sentinel value `ShapedType::kDynamic` encodes that the\\n    corresponding entry has a dynamic value.  There must be exactly as many SSA\\n    inputs in `output_shape` as there are `ShapedType::kDynamic` entries in\\n    `static_output_shape`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Dimension expansion i -> (i', j') and (k) -> (k')\\n    %b = tensor.expand_shape %a [[0, 1], [2]] output_shape [%sz0, %sz1, 32]\\n        : tensor<?x32xf32> into tensor<?x?x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTensor\" },\n      { \"name\": \"output_shape\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reassociation\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"static_output_shape\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$src $reassociation `output_shape`\\n    custom<DynamicIndexList>($output_shape, $static_output_shape) attr-dict `:`\\n    type($src) `into` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.extract\",\n    \"summary\": \"element extraction operation\",\n    \"description\": \"The `tensor.extract` op reads a ranked tensor and returns one element as\\n    specified by the given indices. The result of the op is a value with the\\n    same type as the elements of the tensor. The arity of indices must match\\n    the rank of the accessed value. All indices should all be of `index` type.\\n\\n    Example:\\n\\n    ```mlir\\n    %4 = tensor.extract %t[%1, %2] : tensor<4x4xi32>\\n    %5 = tensor.extract %rt[%1, %2] : tensor<?x?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$tensor `[` $indices `]` attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.extract_slice\",\n    \"summary\": \"extract slice operation\",\n    \"description\": \"The \\\"extract_slice\\\" operation extract a tensor from another tensor as\\n    specified by the operation's offsets, sizes and strides arguments.\\n\\n    The extract_slice operation supports the following arguments:\\n\\n    * source: the \\\"base\\\" tensor from which to extract a slice.\\n    * offsets: tensor-rank number of offsets into the \\\"base\\\" tensor from which\\n               to extract the slice.\\n    * sizes: tensor-rank number of sizes which specify the sizes of the result\\n             tensor type.\\n    * strides: tensor-rank number of strides specifying subsampling in each\\n               dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value ShapedType::kDynamic encodes that the corresponding entry has\\n    a dynamic value.\\n\\n    After buffer allocation, the \\\"extract_slice\\\" op is expected to lower into a\\n    memref.subview op.\\n\\n    An extract_slice operation may additionally reduce the rank of the resulting\\n    tensor by removing dimensions that are statically known to be of size 1.\\n    This rank-reduction behavior is not required by the op semantics: this\\n    flexibility allows to progressively drop unit dimensions while lowering\\n    between different flavors of ops on that operate on tensors.\\n\\n    #### Verification vs Inference in the rank-reduced case\\n\\n    Note that there may be multiple ways to infer a resulting rank-reduced type.\\n      e.g. 1x6x1 could potentially rank-reduce to either 1x6 or 6x1 2-D shapes.\\n\\n    To disambiguate, the inference helpers `inferCanonicalRankReducedResultType`\\n    only drop the first unit dimensions, in order:\\n      e.g. 1x6x1 rank-reduced to 2-D will infer the 6x1 2-D shape, but not 1x6.\\n\\n    Verification however has access to result type and does not need to infer.\\n    The verifier calls `isRankReducedType(getSource(), getResult())` to\\n    determine whether the result type is rank-reduced from the source type.\\n    This computes a so-called rank-reduction mask, consisting of dropped unit\\n    dims, to map the rank-reduced type to the source type by dropping ones:\\n      e.g. 1x6 is a rank-reduced version of 1x6x1 by mask {2}\\n           6x1 is a rank-reduced version of 1x6x1 by mask {0}\\n           1x2x1x4 is a rank-reduced version of 1x1x2x1x1x4x1 by mask {1, 4, 6}\\n             (remaining common 1 dimensions are matched eagerly)\\n\\n    Example:\\n\\n    ```mlir\\n    // Rank-reducing extract_slice.\\n    %1 = tensor.extract_slice %0[0, 0, 0][1, 16, 4][1, 1, 1] :\\n      tensor<8x16x4xf32> to tensor<16x4xf32>\\n    %3 = tensor.extract_slice %2[%o0, 4, %o2][1, %sz1, 1][1, %st1, 1] :\\n      tensor<8x16x4xf32> to tensor<1x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.from_elements\",\n    \"summary\": \"tensor from elements operation.\",\n    \"description\": \"Create a N-D tensor from a range of same-type arguments. The number of\\n    provided `elements` should equal to the number of the elements in the\\n    result type. The `elements` correspond to a flattened tensor.\\n\\n    Example:\\n\\n    ```mlir\\n    tensor.from_elements %a, %b, %c, %d, %e, %f :  tensor<2x3xindex>\\n    ```\\n\\n    will result in a tensor\\n\\n    [[%a, %b, %c]\\n     [%d, %e, %f]]\",\n    \"operands\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStaticShapeTensor\" }\n    ],\n    \"assemblyFormat\": \"$elements attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.gather\",\n    \"summary\": \"gather a subset of a tensor at specified indices\",\n    \"description\": \"The `gather` operation extracts a subset of the elements from a `source`\\n    tensor at the given indices.\\n\\n    In its most general form, the tensor of indices specifies all the coordinates\\n    of every element to extract (i.e. COO format, without the payload).\\n    The indices are expected to be confined to coordinate values that fit the\\n    range of the `source` tensor, otherwise the behavior is undefined.\\n\\n    The leading dimensions of the index tensor give the result tensor its leading\\n    dimensions. The trailing dimensions of the result tensor are obtained from\\n    the source tensor by omitting the dimensions specified in `gather_dims`\\n    (rank-reducing semantics) or setting them to `1` (rank-preserving semantics)\\n    (see examples).\\n    The trailing dimension of the index tensor contains the coordinates and is\\n    expected to have its size equal to the number of dimensions being gathered.\\n    This convention allows an idiomatic specification and lowering of \\\"gathering\\n    multiple N-D slices from the source tensor\\\".\\n\\n    Note: in the examples below, we separate out the indexing part of the tensor\\n    type by a whitespace for readability purposes.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 1x2 triple of coordinates in %indices, extract the\\n        // element (i.e. 0-D subset) at the coordinates triple in %source.\\n        //\\n        %out = tensor.gather %source[%indices] gather_dims([0, 1, 2]) :\\n          (tensor<4x4x4xf32>, tensor<1x2x 3xindex>) -> tensor<1x2x 1x1x1xf32>\\n\\n        // Note: result type may be further rank-reduced to tensor<1x2x f32>.\\n    ```\\n\\n    A slice variant is provided to allow specifying whole slices of the source\\n    tensor.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 5x6 singleton of coordinates in %indices, extract the 2-D\\n        // slice %source[*, %indices[...]:%indices[...] + 1, *] with the indices\\n        // corresponding to the `gather_dims` attribute specified by %indices.\\n        //\\n        %out = tensor.gather %source[%indices] gather_dims([1]) :\\n          (tensor<3x4x5xf32>, tensor<6x7x 1xindex>) -> tensor<6x7x 3x1x5xf32>\\n\\n        // Note: result type may be further rank-reduced to tensor<6x7x 3x5xf32>.\\n    ```\\n\\n    The dimensions specified in the gather_dims attribute are ones for which the\\n    result tensor has size `1`.\\n    I.e. if the source type is `axbxcxd` and the coordinates are [1, 3], then\\n    the shape suffix is `ax1xcx1`.\\n    Gather also allows rank-reducing semantics where the shape `ax1xcx1` can be\\n    further simplified to `axc`.\\n\\n    The elemental type of the indices tensor can be any integer type.\\n    In the absence of target-specific or problem specific information the default\\n    type one should use is `index`.\\n\\n    This operation does not support unranked tensors.\\n\\n    An optional `unique` unit attribute may be specified to indicate that the\\n    coordinates in `indices` are statically guaranteed to be unique at runtime.\\n    Incorrectly setting the `unique` attribute when the coordinates are not truly\\n    unique is undefined behavior.\\n\\n    Only full slices are meant to be supported by this op, if one desires\\n    partial slices (e.g. strided windows) one should compose this op with other\\n    tensor ops (e.g. tensor.extract_slice). This is to avoid a slippery slope of\\n    complexity that would make the op unusable in practice.\\n\\n    At the tensor-level, the index tensor is specified in an AoS form (i.e.\\n    coordinate tuple is the most minor). It is the responsibility of further\\n    lowerings and bufferization to implement various concrete layouts.\\n\\n    Note: As currently specified, the operation must lower to an abstraction that\\n    performs copies to the output tensor. This is because the buffer type system\\n    is currently not rich enough to allow multiple non-contiguous views in the\\n    same type. This is visible more clearly in a notional buffer version of the\\n    op:\\n\\n    ```mlir\\n        // memref<?x4x1xf32> is a contiguous buffer of ?x4x1 elements.\\n        // gather from random source slices must copy to the contiguous output.\\n        %out = memref.gather %source[%indices] gather_dims([1]) :\\n          (memref<4x4xf32>, memref<?x 1xindex>) -> memref<?x 4x1xf32>\\n\\n        // Nested buffer support would allow gather to directly index into the\\n        // source buffer (i.e. represent a jagged view into the source).\\n        %out = memref.gather %source[%indices] gather_dims([1]) :\\n          (memref<4x4xf32>, memref<?x 1xindex>) -> memref<? x memref<4x1xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"RankedTensorOf<[AnySignlessIntegerOrIndex]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"gather_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"unique\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $indices `]`\\n      `gather_dims` `(` $gather_dims `)`\\n      (`unique` $unique^)?\\n      attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.generate\",\n    \"summary\": \"Creates a dynamically sized tensor from elements\",\n    \"description\": \"This operation creates a dynamically sized tensor with elements of any type.\\n    It expects one index operand per dynamic extent of the result tensor.\\n\\n    The body region defines the tensor's elements. It takes index operands as\\n    its region arguments that span the index space. The element at the given\\n    position is yielded with the `yield` operation (see `YieldOp`). There is\\n    no defined ordering to the invocations of the body. It is conceptually\\n    a \\\"parallel map\\\" operation.\\n\\n    Example:\\n\\n    ```mlir\\n      %tnsr = tensor.generate %m, %n {\\n      ^bb0(%i : index, %j : index, %k : index):\\n        ...\\n        yield %elem : f32\\n      } : tensor<?x3x?f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dynamicExtents\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$dynamicExtents $body attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.insert\",\n    \"summary\": \"element insertion operation\",\n    \"description\": \"The `tensor.insert` op inserts a scalar into a ranked tensor `dest` as\\n    specified by the operation's indices.\\n\\n    It returns a copy of `dest` with the indexed position updated to the value\\n    of `scalar`.\\n\\n    The arity of `indices `must match the rank of the tensor `dest`. All\\n    indices should be of `index` type.\\n\\n    Example:\\n\\n    ```mlir\\n    %4 = tensor.insert %t into %dest[%1, %2] : tensor<4x4xi32>\\n    %5 = tensor.insert %rt into %dest[%1, %2] : tensor<?x?xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"scalar\", \"type\": \"AnyType\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$scalar `into` $dest `[` $indices `]` attr-dict `:` type($dest)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.insert_slice\",\n    \"summary\": \"insert_slice operation\",\n    \"description\": \"The \\\"insert_slice\\\" operation insert a tensor `source` into another\\n    tensor `dest` as specified by the operation's offsets, sizes and strides\\n    arguments.\\n\\n    It returns a copy of `dest` with the proper slice updated with the value\\n    of `source`.\\n\\n    The insert_slice operation supports the following arguments:\\n\\n    * source: the tensor that is inserted.\\n    * dest: the tensor into which the source tensor is inserted.\\n    * offsets: tensor-rank number of offsets into the `dest` tensor into which\\n               the slice is inserted.\\n    * sizes: tensor-rank number of sizes which specify the sizes of the source\\n             tensor type.\\n    * strides: tensor-rank number of strides that specify subsampling in each\\n               dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value ShapedType::kDynamic encodes that the corresponding entry has\\n    a dynamic value.\\n\\n    After buffer allocation, the \\\"insert_slice\\\" op is expected to lower into a\\n    memref.subview op.\\n\\n    An insert_slice operation may additionally specify insertion into a tensor\\n    of higher rank than the source tensor, along dimensions that are statically\\n    known to be of size 1.\\n    This rank-altering behavior is not required by the op semantics: this\\n    flexibility allows to progressively drop unit dimensions while lowering\\n    between different flavors of ops on that operate on tensors.\\n    The rank-altering behavior of tensor.insert_slice matches the rank-reducing\\n    behavior of tensor.extract_slice.\\n\\n    #### Verification in the rank-reduced case\\n\\n    The same verification discussion and mechanisms apply as for ExtractSliceOp.\\n    Unlike ExtractSliceOp however, there is no need for a specific inference.\\n\\n    Example:\\n\\n    ```mlir\\n    // Rank-altering insert_slice.\\n    %1 = tensor.insert_slice %t into %0[0, 0, 0][1, 16, 4][1, 1, 1] :\\n      tensor<16x4xf32> into tensor<8x16x4xf32>\\n    %3 = tensor.insert_slice %tt into %2[%o0, 4, %o2][1, %sz1, 1][1, %st1, 1] :\\n      tensor<1x?xf32> into tensor<8x16x4xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `into` type($dest)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.pad\",\n    \"summary\": \"tensor pad operation\",\n    \"description\": \"`tensor.pad` is an operation that pads the `source` tensor\\n    with given `low` and `high` padding config.\\n\\n    The PadOp operation supports the following arguments:\\n\\n    * source: the \\\"base\\\" tensor on which to pad.\\n    * low: A list contains the padding along the start of each\\n           dimension, i.e., how many padded values are prepended\\n           to the beginning of the tensor in each dimension.\\n    * high: A list contains the padding along the end of each\\n            dimension, i.e., how many padded values are appended\\n            to the end of the tensor in each dimension.\\n    * nofold: indicates that the operation should not be folded when source and\\n              result types are equal.\\n\\n    The result tensor dimensions are `low[i]` + `dim[i]` + `high[i]` for each\\n    dimension `i`. The number of elements of `low` and `high` must match the\\n    rank of the input tensor. They can be either a constant or a dynamic value.\\n\\n    The region of the `tensor.pad` operation returns the value to use\\n    for the padding. The arguments of the region represent the index\\n    of the source being accessed. There should be as many arguments as\\n    the rank of the `source` tensor. The value `yield`-ed by the\\n    region is used as the value of the view at the given position.\\n\\n    If `nofold` is set, the padding operation will not be folded away even\\n    if the source type and the padded type have the same static shape. This can\\n    be used, e.g., for packing or promotion to faster memory.\\n\\n    Example 1: add 3 zeros to the beginning and 5 zeros to the end of a 1D\\n    tensor.\\n\\n    ```mlir\\n      %arg0 = ... : tensor<10xi32>\\n      %c0_i32 = arith.constant 0 : i32\\n      %padded = tensor.pad %arg0 low[3] high[5] {\\n      ^bb0(%arg1: index):\\n        tensor.yield %c0_i32 : i32\\n      } : tensor<10xi32> to tensor<18xi32>\\n    ```\\n\\n    Example 2: add 1 value to the beginning of dimension 0, 2 values to the end\\n    of dimension 0, 2 values to the start of dimension 1, and 3 values to the\\n    end of dimension 1.\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %0 low[1, 2] high[2, 3] {\\n      ^bb0(%arg0 : index, %arg1 : index):\\n        tensor.yield %pad_value : f32\\n      } : tensor<?x?xf32> to tensor<?x?xf32>\\n    ```\\n\\n    Example 3:\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %arg0 low[2, %arg1, 3, 3] high[3, 3, %arg1, 2] {\\n      ^bb0(%arg2: index, %arg3: index, %arg4: index, %arg5: index):\\n          tensor.yield %pad_value : f32\\n      } : tensor<1x2x2x?xf32> to tensor<6x?x?x?xf32>\\n    ```\\n\\n    Example 4:\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %arg0 low[0, 0] high[%ub0, %ub1] {\\n      ^bb0(%arg1: index, %arg2: index):\\n        tensor.yield %pad_value : f32\\n      } : tensor<2x3xf32> to tensor<?x?xf32>\\n    ```\\n\\n    Example 5: Force a padded value to be always exist with `nofold`, even\\n    though the padding config specifies that no new elements will be added to\\n    the tensor.\\n\\n    ```mlir\\n      %pad_value = ... : f32\\n      %0 = tensor.pad %arg0 nofold low[0, 0] high[0, 0] {\\n      ^bb0(%arg1: index, %arg2: index):\\n        tensor.yield %pad_value : f32\\n      } : tensor<2x3xf32> to tensor<2x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"low\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"high\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_low\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_high\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"nofold\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$source\\n    (`nofold` $nofold^)?\\n    `low` `` custom<DynamicIndexList>($low, $static_low)\\n    `high` `` custom<DynamicIndexList>($high, $static_high)\\n    $region attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.parallel_insert_slice\",\n    \"summary\": \"Specify the tensor slice update of a single thread of a parent\\n    InParallelOpInterface op.\",\n    \"description\": \"The `parallel_insert_slice` yields a subset tensor value to its parent\\n    InParallelOpInterface. These subset tensor values are aggregated to\\n    in some unspecified order into a full tensor value returned by the parent\\n    parallel iterating op.\\n    The `parallel_insert_slice` is one such op allowed in the\\n    InParallelOpInterface op.\\n\\n    Conflicting writes result in undefined semantics, in that the indices written\\n    to by multiple parallel updates might contain data from any of the updates,\\n    or even a malformed bit pattern.\\n\\n    If an index is updated exactly once, the value contained at that index\\n    in the resulting tensor will be equal to the value at a corresponding index\\n    of a slice that was used for the updated. If an index is not updated at all,\\n    its value will be equal to the one in the original tensor.\\n\\n    This op does not create a new value, which allows maintaining a clean\\n    separation between the subset and full tensor.\\n\\n    Note that we cannot mark this operation as pure (Pures), even\\n    though it has no side effects, because it will get DCEd during\\n    canonicalization.\\n\\n    The parallel_insert_slice operation supports the following arguments:\\n\\n    * source: the tensor that is inserted.\\n    * dest: the tensor into which the source tensor is inserted.\\n    * offsets: tensor-rank number of offsets into the `dest` tensor into which\\n               the slice is inserted.\\n    * sizes: tensor-rank number of sizes which specify the sizes of the source\\n             tensor type.\\n    * strides: tensor-rank number of strides that specify subsampling in each\\n               dimension.\\n\\n    The representation based on offsets, sizes and strides support a\\n    partially-static specification via attributes specified through the\\n    `static_offsets`, `static_sizes` and `static_strides` arguments. A special\\n    sentinel value ShapedType::kDynamic encodes that the corresponding entry has\\n    a dynamic value.\\n\\n    After buffer allocation, the \\\"parallel_insert_slice\\\" op is expected to lower\\n    into a memref.subview op.\\n\\n    A parallel_insert_slice operation may additionally specify insertion into a\\n    tensor of higher rank than the source tensor, along dimensions that are\\n    statically known to be of size 1.\\n    This rank-altering behavior is not required by the op semantics: this\\n    flexibility allows to progressively drop unit dimensions while lowering\\n    between different flavors of ops on that operate on tensors.\\n    The rank-altering behavior of tensor.parallel_insert_slice matches the\\n    rank-reducing behavior of tensor.insert_slice and tensor.extract_slice.\\n\\n    #### Verification in the rank-reduced case\\n\\n    The same verification discussion and mechanisms apply as for ExtractSliceOp.\\n    Unlike ExtractSliceOp however, there is no need for a specific inference.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest ``\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($source) `into` type($dest)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.rank\",\n    \"summary\": \"rank operation\",\n    \"description\": \"The `tensor.rank` operation takes a tensor operand and returns its rank.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = tensor.rank %arg0 : tensor<*xf32>\\n    %1 = tensor.rank %arg1 : tensor<?x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.reshape\",\n    \"summary\": \"tensor reshape operation\",\n    \"description\": \"The `reshape` operation converts a tensor from one type to an equivalent\\n    type with a provided shape. The source and destination types are compatible\\n    if both have the same element type, same number of elements. The following\\n    combinations are possible:\\n\\n    a. Source type is ranked or unranked. Shape argument has static size.\\n    Result type is ranked.\\n\\n    ```mlir\\n    // Reshape statically-shaped tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<4x1xf32>, tensor<1xi32>) -> tensor<4xf32>\\n    %dst0 = tensor.reshape %src(%shape0)\\n             : (tensor<4x1xf32>, tensor<2xi32>) -> tensor<2x2xf32>\\n    // Flatten unranked tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<*xf32>, tensor<1xi32>) -> tensor<?xf32>\\n    ```\\n\\n    b. Source type is ranked or unranked. Shape argument has dynamic size.\\n    Result type is unranked.\\n\\n    ```mlir\\n    // Reshape dynamically-shaped 1D tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<?xf32>, tensor<?xi32>) -> tensor<*xf32>\\n    // Reshape unranked tensor.\\n    %dst = tensor.reshape %src(%shape)\\n             : (tensor<*xf32>, tensor<?xi32>) -> tensor<*xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shape\", \"type\": \"TensorRankOf<[AnySignlessInteger, Index], [1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$source `(` $shape `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.scatter\",\n    \"summary\": \"scatter a tensor into a destination tensor at specified indices\",\n    \"description\": \"The `scatter` operation inserts a `source` tensor into a `dest` tensor at\\n    the given indices.\\n\\n    In its most general form, the tensor of indices specifies all the coordinates\\n    of every element to insert (i.e. COO format, without the payload).\\n    The indices are expected to be confined to coordinate values that fit the\\n    range of the `dest` tensor, otherwise the behavior is undefined.\\n\\n    The leading dimensions of the index tensor must match that of the dest\\n    tensor. The trailing dimensions of the dest tensor must match those of the\\n    source tensor by omitting the dimensions specified in scatter_dims\\n    (rank-reducing semantics) or setting them to `1` (rank-preserving semantics)\\n    (see examples).\\n    This convention allows an idiomatic specification and lowering of\\n    \\\"scattering multiple N-D slices into the dest tensor\\\".\\n    The result type must match the type of the dest tensor.\\n\\n    Note: in the examples below, we separate out the indexing part of the tensor\\n    type by a whitespace for readability purposes.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 1x2 triple of coordinates in %indices, insert the\\n        // element (i.e. 0-D subset) at the coordinates triple in %dest.\\n        //\\n        %out = tensor.scatter %source into %dest[%indices]\\n            scatter_dims([0, 1, 2]) unique :\\n          (tensor<1x2x 1x1x1xf32>, tensor<4x4x4xf32>, tensor<1x2x 3xindex>)\\n            -> tensor<4x4x4xf32>\\n\\n        // Note: source type may be further rank-reduced to tensor<1x2x f32>.\\n    ```\\n\\n    A slice variant is provided to allow specifying insertion of whole tensor\\n    slices into the `dest` tensor.\\n\\n    Example:\\n\\n    ```mlir\\n        // For each 3 singleton of coordinates in %indices, insert the 2-D\\n        // slice into %dest[*, %indices[...]:%indices[...] + 1, *] with the\\n        // indices corresponding to the scatter_dims attribute specified by\\n        // %indices.\\n        //\\n        %out = tensor.scatter %source into %dest[%indices] scatter_dims([1]) unique :\\n          (tensor<3x 4x1x6xf32>, tensor<4x5x6xf32>, tensor<3x 1xindex>)\\n            -> tensor<4x5x6xf32>\\n    ```\\n\\n    The dimensions specified in the scatter_dims attribute are ones for which the\\n    source tensor has size `1`.\\n    I.e. if the dest type is `axbxcxd` and the coordinates are [1, 3], then\\n    the source type suffix is `ax1xcx1`.\\n    Scatter also allows rank-reducing semantics where the shape `ax1xcx1` can be\\n    further simplified to `axc`.\\n\\n    The elemental type of the indices tensor can be any integer type.\\n    In the absence of target-specific or problem specific information the default\\n    type one should use is `index`.\\n\\n    This operation does not support unranked tensors.\\n\\n    A `unique` unit attribute must be be specified to indicate that the\\n    coordinates are statically guaranteed to be unique at runtime. If coordinates\\n    are not truly unique at runtime, the behavior is undefined.\\n\\n    Only full slices are meant to be supported by this op, if one desires\\n    partial slices (e.g. strided windows) one should compose this op with other\\n    tensor ops (e.g. tensor.insert_slice). This is to avoid a slippery slope of\\n    complexity that would make the op unusable in practice.\\n\\n    At the tensor-level, the index tensor is specified in an AoS form (i.e.\\n    coordinate tuple is the most minor). It is the responsibility of further\\n    lowerings and bufferization to implement various concrete layouts.\\n\\n    Note: As currently specified, the operation must lower to an abstraction that\\n    performs copies to the output tensor. This is because the buffer type system\\n    is currently not rich enough to allow multiple non-contiguous views in the\\n    same type. This is visible more clearly in a notional buffer version of the\\n    op:\\n\\n    ```mlir\\n        // memref<?x 4xf32> is a contiguous buffer of ?x4 elements, scatter into\\n        // random dest slices must copy to the contiguous dest.\\n        //\\n        some_side_effecting_op_writing_into %source, ...: memref<3x 4xf32>\\n        memref.scatter %source into %dest[%indices] scatter_dims([1]) unique :\\n          (memref<3x 4xf32>, memref<?x 4xf32>, memref<?x 1xindex>)\\n\\n        // Nested buffer support in the producing op would allow writing directly\\n        // into the dest buffer.\\n        %v = some_nested_buffer_view_op %dest[%indices] scatter_dims([1]) unique :\\n          memref<? x memref<4xf32>>\\n        some_side_effecting_op_writing_into %v, ...: memref<? x memref<4xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"RankedTensorOf<[AnySignlessIntegerOrIndex]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"unique\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $dest `[` $indices `]`\\n      `scatter_dims` `(` $scatter_dims `)`\\n      (`unique` $unique^)?\\n      attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.splat\",\n    \"summary\": \"tensor splat or broadcast operation\",\n    \"description\": \"Broadcast the operand to all elements of the result tensor.\\n\\n    An additional argument of type `index` must be provided for each dynamic\\n    dimension present in the result type.\\n\\n    Example for a statically shaped tensor:\\n\\n    ```mlir\\n    %s = arith.constant 1.0 : f32\\n    %t = tensor.splat %s : tensor<8x16xf32>\\n    ```\\n\\n    Example for a tensor containing dynamic dimensions:\\n\\n    ```mlir\\n    // Broadcasts %s to a 3D dynamically shaped tensor, with %m and %n binding\\n    // to dimensions 0 and 2 of the resulting tensor, respectively.\\n    %m = arith.constant 10 : index\\n    %n = arith.constant 30 : index\\n    %t = tensor.splat %s[%m, %n] : tensor<?x20x?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyType\" },\n      { \"name\": \"dynamicSizes\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"aggregate\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"$input (`[` $dynamicSizes^ `]`)? attr-dict `:` type($aggregate)\"\n  },\n  {\n    \"name\": \"tfrt_tensor.yield\",\n    \"summary\": \"Yield a value from a region\",\n    \"description\": \"This operation is used to yield a single value from a within a region. It\\n     is used to create dynamically sized tensors\\n     (see `tensor.generate` and `tensor.pad` ops).\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value)\"\n  },\n  {\n    \"name\": \"tfrt_test.addi\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"AnyTypeOf<[I32, TestI32]>\" },\n      { \"name\": \"op2\", \"type\": \"AnyTypeOf<[I32, TestI32]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.affine_scope\",\n    \"summary\": \"affine scope operation\",\n    \"description\": \"Test op that defines a new affine scope.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.all_attr_constraint_of1\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.all_attr_constraint_of2\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.alloc_with_multiple_results\",\n    \"results\": [\n      { \"name\": \"index\", \"type\": \"Index\" },\n      { \"name\": \"memref\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($index) `,` type($memref)\"\n  },\n  {\n    \"name\": \"tfrt_test.alloca_scope_region\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"tfrt_test.always_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can always be\\n    speculatively executed.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.another_three_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" },\n      { \"name\": \"result3\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.another_two_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"F32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.any_attr_of_i32_str\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttrOf<[I32Attr, StrAttr]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.any_cond\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.arg_and_res_have_fixed_element_types\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.array_of_attr_op\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"TestArrayOfUglyAttrs\" },\n      { \"name\": \"b\", \"type\": \"TestArrayOfInts\" },\n      { \"name\": \"c\", \"type\": \"TestArrayOfEnums\" }\n    ],\n    \"assemblyFormat\": \"`a` `=` $a `,` `b` `=` $b `,` `c` `=` $c attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.asm_interface_op\",\n    \"results\": [\n      { \"name\": \"first\", \"type\": \"AnyType\" },\n      { \"name\": \"middle_results\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.attr_sized_operands\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"c\", \"type\": \"I32\" },\n      { \"name\": \"d\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.attr_sized_results\",\n    \"results\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"c\", \"type\": \"I32\" },\n      { \"name\": \"d\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.attr_sized_results_compile_test\",\n    \"results\": [\n      { \"name\": \"a\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"b\", \"type\": \"I32\" },\n      { \"name\": \"c\", \"type\": \"Optional<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.attr_with_trait\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.benchmark\",\n    \"summary\": \"benchmark operation\",\n    \"description\": \"The \\\"tfrt_test.benchmark\\\" operation benchmarks the performance of an MLIR\\n     region by executing the given MLIR region repeatedly up to the\\n     `duratino_secs` seconds or `max_count` times. `num_warmup_runs` specifies\\n     the number of warm up runs to run the given MLIR region before the\\n     benchmark starts.\\n\\n     The target MLIR region can take an arbitrary number of arguments and\\n     should return exactly one value. The arguments for the MLIR region are\\n     provided as the operands of the tfrt_test.benchmark op.\\n\\n     Example:\\n       tfrt_test.benchmark \\\"add.i32\\\"(%c : i32, %d : f32) max_count = 100, duration_secs = 1 {\\n         // code for benchmarking\\n         ...\\n       }\\n\\n       tfrt_test.benchmark \\\"add.i32\\\"(%c : i32)\\n         duration_secs = 1,\\n         max_count = 100,\\n         num_warmup_runs = 10 {\\n         // The MLIR code to be benchmarked goes here.\\n         // The following code benchmarks the tfrt.add.i32 kernel.\\n         %x = tfrt.add.i32 %c, %c\\n         // The benchmarked function needs to return exactly one value.\\n         tfrt.return %x : i32\\n       }\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"duration_secs\", \"type\": \"I32Attr\" },\n      { \"name\": \"max_count\", \"type\": \"I32Attr\" },\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"num_warmup_runs\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 1>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.block_argument_name_from_type\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tfrt_test.block_argument_name_from_type_interface\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tfrt_test.block_names\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tfrt_test.br\",\n    \"operands\": [\n      { \"name\": \"targetOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"successors\": [\n      {\n        \"name\": \"target\"\n      }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.buffer_based\",\n    \"description\": \"A buffer based operation, that uses memRefs as input and output.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"`in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`\\n    attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.call\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.call_and_store\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"callee_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"store_before_call\", \"type\": \"BoolAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $callee_operands `)` `,` $address attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.call_on_device\",\n    \"operands\": [\n      { \"name\": \"forwarded_operands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"non_forwarded_device_operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $forwarded_operands `)` `,` $non_forwarded_device_operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.call_with_segments\",\n    \"summary\": \"test call op with segmented args\",\n    \"operands\": [\n      { \"name\": \"prefix\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"suffix\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $prefix `:` type($prefix) `)`\\n            `(` $args `:` type($args) `)`\\n            `(` $suffix `:` type($suffix) `)` attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.compare\",\n    \"description\": \"Compare `lhs` and `rhs`. A remark is emitted which indicates whether the\\n    specified comparison operator was proven to hold. The remark also indicates\\n    whether the opposite comparison operator was proven to hold.\\n\\n    `var_operands` must have exactly two operands: one for the LHS operand and\\n    one for the RHS operand. If `lhs_map` is specified, as many operands as\\n    `lhs_map` has inputs are expected instead of the first operand. If `rhs_map`\\n    is specified, as many operands as `rhs_map` has inputs are expected instead\\n    of the second operand.\",\n    \"operands\": [\n      { \"name\": \"var_operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cmp\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"EQ\\\">\" },\n      { \"name\": \"lhs_map\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"rhs_map\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"compose\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.conditionally_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can be speculatively\\n    executed if the input to it is an `arith.constant`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.confined_dense_array_attr\",\n    \"attributes\": [\n      { \"name\": \"emptyattr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayStrictlySorted<DenseI16ArrayAttr>]>\" },\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<DenseI32ArrayAttr, [DenseArraySorted<DenseI32ArrayAttr>]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlySorted<DenseI64ArrayAttr>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.confined_non_negative_attr\",\n    \"attributes\": [\n      { \"name\": \"i8attr\", \"type\": \"ConfinedAttr<DenseI8ArrayAttr, [DenseArrayNonNegative<DenseI8ArrayAttr>]>\" },\n      { \"name\": \"i16attr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayNonNegative<DenseI16ArrayAttr>]>\" },\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<DenseI32ArrayAttr, [DenseArrayNonNegative<DenseI32ArrayAttr>]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayNonNegative<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"f32attr\", \"type\": \"ConfinedAttr<DenseF32ArrayAttr, [DenseArrayNonNegative<DenseF32ArrayAttr>]>\" },\n      { \"name\": \"f64attr\", \"type\": \"ConfinedAttr<DenseF64ArrayAttr, [DenseArrayNonNegative<DenseF64ArrayAttr>]>\" },\n      { \"name\": \"emptyattr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayNonNegative<DenseI16ArrayAttr>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.confined_strictly_positive_attr\",\n    \"attributes\": [\n      { \"name\": \"i8attr\", \"type\": \"ConfinedAttr<DenseI8ArrayAttr, [DenseArrayStrictlyPositive<DenseI8ArrayAttr>]>\" },\n      { \"name\": \"i16attr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>\" },\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<DenseI32ArrayAttr, [DenseArrayStrictlyPositive<DenseI32ArrayAttr>]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlyPositive<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"f32attr\", \"type\": \"ConfinedAttr<DenseF32ArrayAttr, [DenseArrayStrictlyPositive<DenseF32ArrayAttr>]>\" },\n      { \"name\": \"f64attr\", \"type\": \"ConfinedAttr<DenseF64ArrayAttr, [DenseArrayStrictlyPositive<DenseF64ArrayAttr>]>\" },\n      { \"name\": \"emptyattr\", \"type\": \"ConfinedAttr<DenseI16ArrayAttr, [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.constant\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.conv_op_not_linalg_op\",\n    \"operands\": [\n      { \"name\": \"image\", \"type\": \"AnyType\" },\n      { \"name\": \"filter\", \"type\": \"AnyType\" },\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.conversion_call_op\",\n    \"operands\": [\n      { \"name\": \"arg_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.conversion_func_op\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.convert_block_args\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_legal\", \"type\": \"UnitAttr\" },\n      { \"name\": \"replace_with_operand\", \"type\": \"UnitAttr\" },\n      { \"name\": \"duplicate\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$val\\n    (`is_legal` $is_legal^)?\\n    (`duplicate` $duplicate^)?\\n    (`replace_with_operand` $replace_with_operand^)?\\n    $body attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.copy\",\n    \"description\": \"Represents a copy operation.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"target\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"`(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)`\\n     attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.count3.i32\",\n    \"summary\": \"tfrt_test.count3 operation\",\n    \"description\": \"An operation that takes one input x and returns x+1, x+2, x+3 as the\\n     result.\\n\\n     Example:\\n       %1, %2, %3 = test.count3.i32 %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I32\" },\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.count3.i64\",\n    \"summary\": \"tfrt_test.count3 operation\",\n    \"description\": \"An operation that takes one input x and returns x+1, x+2, x+3 as the\\n     result.\\n\\n     Example:\\n       %1, %2, %3 = test.count3.i32 %0\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I64\" },\n      { \"name\": \"result1\", \"type\": \"I64\" },\n      { \"name\": \"result2\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.create_memref_op\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.create_tensor_op\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.cse_of_single_block_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `inputs` `(` $inputs `)`\\n    $region `:` type($inputs)  `->` type($outputs)\"\n  },\n  {\n    \"name\": \"tfrt_test.custom_dimension_list_attr\",\n    \"description\": \"Test printing/parsing of dimension list attribute.\",\n    \"attributes\": [\n      { \"name\": \"dimension_list\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`dimension_list` `=` custom<DimensionList>($dimension_list)\\n    attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.custom_result_name\",\n    \"operands\": [\n      { \"name\": \"optional\", \"type\": \"Variadic<AnyInteger>\" }\n    ],\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"Variadic<AnyInteger>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.data_layout_query\",\n    \"summary\": \"A token op recognized by data layout query test pass\",\n    \"description\": \"The data layout query pass pattern-matches this op and attaches to it an\\n    array attribute containing the result of data layout query of the result\\n    type of this op.\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.decode_jpeg\",\n    \"summary\": \"tfrt_test.decode_jpeg operation\",\n    \"description\": \"The \\\"tfrt_test.decode_jpeg\\\" operation decodes Jpeg-formatted binary and\\n    returns a tensor with the same semantics as tf.image.decode_jpeg(image_encoded, channels=3).\\n\\n    Example:\\n      %image_decoded =  tfrt_test.decode_jpeg %image_encoded\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.default_dialect\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"regions attr-dict-with-keyword\",\n    \"defaultDialect\": \"test\"\n  },\n  {\n    \"name\": \"tfrt_test.default_value_print\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value_with_default\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $operand\"\n  },\n  {\n    \"name\": \"tfrt_test.dense_array_attr\",\n    \"attributes\": [\n      { \"name\": \"i1attr\", \"type\": \"DenseBoolArrayAttr\" },\n      { \"name\": \"i8attr\", \"type\": \"DenseI8ArrayAttr\" },\n      { \"name\": \"i16attr\", \"type\": \"DenseI16ArrayAttr\" },\n      { \"name\": \"i32attr\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"i64attr\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"f32attr\", \"type\": \"DenseF32ArrayAttr\" },\n      { \"name\": \"f64attr\", \"type\": \"DenseF64ArrayAttr\" },\n      { \"name\": \"emptyattr\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"`i1attr` `=` $i1attr `i8attr` `=` $i8attr `i16attr` `=` $i16attr\\n   `i32attr` `=` $i32attr `i64attr` `=` $i64attr  `f32attr` `=` $f32attr\\n   `f64attr` `=` $f64attr `emptyattr` `=` $emptyattr attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.derived_type_attr\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.destination_style_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"other_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    (`outs` `(` $outputs^  `:` type($outputs) `)`)?\\n    (`(` $other_operands^ `:` type($other_operands) `)`)?\\n    (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tfrt_test.do.async\",\n    \"summary\": \"do.async operation\",\n    \"description\": \"The \\\"tfrt_test.do.async\\\" operation allows its body to be executed\\n    asynchronously. It has one region which represents the body.\\n\\n    The body region takes an arbitrary number of arguments and may return\\n    arbitrary number of return values, using a `tfrt.return` operation at the\\n    end of the region.\\n\\n    Example:\\n\\n      tfrt_test.do.async () -> () {\\n        tfrt.return\\n      }\\n\\n      %res = tfrt_test.do.async () -> (i32) {\\n        %val = tfrt.constant.i32 1\\n        tfrt.return %val\\n      }\\n\\n      %res1, %res2 = tfrt_test.do.async %val1, %val2 : (i32, f32) -> (i32, f32) {\\n        tfrt.return %val1, val2 : i32, f32\\n      }\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.dummy_memref_op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_BufferLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.dummy_op_with_region_ref\",\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$body attr-dict custom<DummyRegionRef>(ref($body))\"\n  },\n  {\n    \"name\": \"tfrt_test.dummy_op_with_successor_ref\",\n    \"successors\": [\n      {\n        \"name\": \"successor\"\n      }\n    ],\n    \"assemblyFormat\": \"$successor attr-dict custom<DummySuccessorRef>(ref($successor))\"\n  },\n  {\n    \"name\": \"tfrt_test.dummy_tensor_op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Bufferization_TensorLikeTypeInterface\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.either_helper_op_a\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.either_helper_op_b\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.either_op_a\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg1\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg2\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.either_op_b\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg1\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.either_op_c\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"AnyInteger\" },\n      { \"name\": \"arg1\", \"type\": \"AnyInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.empty_properties\",\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.fill_op_not_linalg_op\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"output\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.float_attrs\",\n    \"attributes\": [\n      { \"name\": \"float_attr\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.float_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"scalar_f32_attr\", \"type\": \"RankedF32ElementsAttr<[2]>\" },\n      { \"name\": \"tensor_f64_attr\", \"type\": \"RankedF64ElementsAttr<[4, 8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.fold_to_call_op\",\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.fold_with_fold_adaptor\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"I32\" },\n      { \"name\": \"variadic\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"var_of_var\", \"type\": \"VariadicOfVariadic<I32, attr>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$op `,` `[` $variadic `]` `,` `{` $var_of_var `}` $body attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tfrt_test.forward_buffer\",\n    \"description\": \"A pure operation that takes a buffer and returns a buffer. This op does not\\n    have any side effects, so it cannot allocate or read a buffer from memory.\\n    It must return the input buffer (or a view thereof). This op purposely does\\n    does not implement any interface.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.functional_region_op\",\n    \"attributes\": [\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.get_bytes_field_from_example\",\n    \"summary\": \"tfrt_test.get_bytes_field_from_example operation\",\n    \"description\": \"The tfrt_test.get_bytes_field_from_example extracts the bytes field of the\\n    given `key` name from a protobuf object whose format follows example.proto.\\n\\n    Example:\\n      %value = tfrt_test.get_bytes_field_from_example %example, %key\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_StringType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.get_int64_field_from_example\",\n    \"summary\": \"tfrt_test.get_int64_field_from_example operation\",\n    \"description\": \"The tfrt_test.get_int64_field_from_example extracts the int64 field of the\\n    given `key` name from a protobuf object whose format follows example.proto.\\n\\n    Example:\\n      %value = tfrt_test.get_int64_field_from_example %example, %key\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.get_string\",\n    \"summary\": \"tfrt_test.get_string\",\n    \"description\": \"Get a !tfrt.string value from the given string attribute.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_StringType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.get_string_sync\",\n    \"summary\": \"tfrt_test.get_string_sync\",\n    \"description\": \"Get a !tfrt.string value from the given string attribute.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_StringType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.get_tuple_element\",\n    \"description\": \"Test op that returns a specified element of the tuple.\",\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.graph_loop\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"rets\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$args $body attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.graph_region\",\n    \"summary\": \"operation with a graph region\",\n    \"description\": \"Test op that defines a graph region.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"tfrt_test.has_str_value\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"DefaultValuedStrAttr<StrAttr, >\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.i32_enum_attr\",\n    \"results\": [\n      { \"name\": \"val\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SomeI32Enum{case5|case10|caseSignedMaxPlusOne|caseUnsignedMax}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.i32ElementsAttr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I32ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.i64_enum_attr\",\n    \"results\": [\n      { \"name\": \"val\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SomeI64Enum{case5|case10|caseLarse}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.if_first_operand_is_none_then_so_is_second\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.ignore_arg_match_dst\",\n    \"operands\": [\n      { \"name\": \"b\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"f\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.ignore_arg_match_src\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyType\" },\n      { \"name\": \"b\", \"type\": \"AnyType\" },\n      { \"name\": \"c\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"d\", \"type\": \"AnyAttr\" },\n      { \"name\": \"e\", \"type\": \"AnyAttr\" },\n      { \"name\": \"f\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.increment\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_test.indexElementsAttr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"IndexElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.int_attrs\",\n    \"attributes\": [\n      { \"name\": \"any_i32_attr\", \"type\": \"AnyI32Attr\" },\n      { \"name\": \"index_attr\", \"type\": \"IndexAttr\" },\n      { \"name\": \"ui32_attr\", \"type\": \"UI32Attr\" },\n      { \"name\": \"si32_attr\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.int_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"any_i32_attr\", \"type\": \"AnyI32ElementsAttr\" },\n      { \"name\": \"i32_attr\", \"type\": \"I32ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.int_types\",\n    \"results\": [\n      { \"name\": \"any_i16\", \"type\": \"AnyI16\" },\n      { \"name\": \"si32\", \"type\": \"SI32\" },\n      { \"name\": \"ui64\", \"type\": \"UI64\" },\n      { \"name\": \"any_int\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.interleaved_operand_attr1\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.interleaved_operand_attr2\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.internal_br\",\n    \"operands\": [\n      { \"name\": \"successOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"errorOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"successors\": [\n      {\n        \"name\": \"successPath\"\n      },\n      {\n        \"name\": \"errorPath\"\n      }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.isolated_graph_region\",\n    \"summary\": \"isolated from above operation with a graph region\",\n    \"description\": \"Test op that defines a graph region which is isolated from above.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"tfrt_test.isolated_one_region_op\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"my_region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $operands $my_region `:` type($operands) `->` type($results)\"\n  },\n  {\n    \"name\": \"tfrt_test.isolated_region\",\n    \"summary\": \"isolated region operation\",\n    \"description\": \"Test op with an isolated region, to test passthrough region arguments. Each\\n    argument is of index type.\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.isolated_regions\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $regions\"\n  },\n  {\n    \"name\": \"tfrt_test.legal_op_a\",\n    \"attributes\": [\n      { \"name\": \"status\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.less_than\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"RankedTensorOf<[F32]>\" },\n      { \"name\": \"rhs\", \"type\": \"RankedTensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[I1]>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.linalg_conv_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tfrt_test.linalg_fill_op\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tfrt_test.loc_dst\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.loc_dst_no_res\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.loc_src\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.loc_src_no_res\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.loop_block\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"floatResult\", \"type\": \"F32\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$init `:` functional-type($init, $floatResult) $body\\n    attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tfrt_test.loop_block_term\",\n    \"operands\": [\n      { \"name\": \"nextIterArg\", \"type\": \"I32\" },\n      { \"name\": \"exitArg\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"`iter` $nextIterArg `exit` $exitArg attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.make_tuple\",\n    \"description\": \"Test op that creates a tuple value from a list of values.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.many_arguments\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" },\n      { \"name\": \"input3\", \"type\": \"I32\" },\n      { \"name\": \"input4\", \"type\": \"I32\" },\n      { \"name\": \"input5\", \"type\": \"I32\" },\n      { \"name\": \"input6\", \"type\": \"I32\" },\n      { \"name\": \"input7\", \"type\": \"I32\" },\n      { \"name\": \"input8\", \"type\": \"I32\" },\n      { \"name\": \"input9\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr3\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr4\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr5\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr6\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr7\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr8\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr9\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.many_regions\",\n    \"summary\": \"operation created with move-only objects\",\n    \"description\": \"Test op with multiple regions with a `create` function that\\n    takes parameters containing move-only objects.\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.match_op_attribute1\",\n    \"attributes\": [\n      { \"name\": \"required_attr\", \"type\": \"I32Attr\" },\n      { \"name\": \"optional_attr\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"default_valued_attr\", \"type\": \"DefaultValuedAttr<I32Attr, 42>\" },\n      { \"name\": \"more_attr\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.match_op_attribute3\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.match_op_attribute4\",\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"UnitAttr\" },\n      { \"name\": \"attr2\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.merge_blocks\",\n    \"summary\": \"merge_blocks operation\",\n    \"description\": \"Test op with multiple blocks that are merged with Dialect Conversion\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_normal_variadic_operand\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"input2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_normal_variadic_result\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"output2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in_out_i32\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in1\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"F32\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in2\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"F32\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in3\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input3\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in4\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in5\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" },\n      { \"name\": \"input3\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" },\n      { \"name\": \"pattern_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_in6\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_optional_in7\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"input2\", \"type\": \"Optional<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr1\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_out1\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"output2\", \"type\": \"F32\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_out2\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"output2\", \"type\": \"F32\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<I32>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.mixed_variadic_out3\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"output3\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.multi_slot_alloca\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<MemRefOf<[ I32 ]>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.multi_tensor_rank_of\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"TensorRankOf<[I8, I32, F32], [0, 1]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call1\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"choice\", \"type\": \"BoolAttr\" },\n      { \"name\": \"attr1\", \"type\": \"I64Attr\" },\n      { \"name\": \"attr2\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call2\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call3\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call4\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call5\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call6\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"I32\" },\n      { \"name\": \"output2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.native_code_call7\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.nd_tensor_of\",\n    \"operands\": [\n      { \"name\": \"arg0\", \"type\": \"0DTensorOf<[F32]>\" },\n      { \"name\": \"arg1\", \"type\": \"1DTensorOf<[F32]>\" },\n      { \"name\": \"arg2\", \"type\": \"2DTensorOf<[I16]>\" },\n      { \"name\": \"arg3\", \"type\": \"3DTensorOf<[I16]>\" },\n      { \"name\": \"arg4\", \"type\": \"4DTensorOf<[I16]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.never_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can never be\\n    speculatively executed.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.no_str_value\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"DefaultValuedAttr<StrAttr, >\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.non_negative_int_attr\",\n    \"attributes\": [\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.nvvm_requires_sm_80\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.nvvm_requires_sm_90a\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.nvvm_requires_sm_90a_or_sm_100a\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.one_region_with_operands_op\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.one_region_with_recursive_memory_effects\",\n    \"description\": \"Op that has one region and recursive side effects. The\\n    RegionBranchOpInterface is not implemented on this op.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.one_result1\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.one_result2\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.one_result3\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_a\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_b\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_commutative\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" },\n      { \"name\": \"op3\", \"type\": \"I32\" },\n      { \"name\": \"op4\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_commutative2\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_funcref\",\n    \"summary\": \"Test op with a reference to a function symbol\",\n    \"description\": \"The \\\"test.op_funcref\\\" is a test op with a reference to a function symbol.\"\n  },\n  {\n    \"name\": \"tfrt_test.op_idempotent_trait\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_idempotent_trait_binary\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_in_place_fold\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_in_place_self_fold\",\n    \"attributes\": [\n      { \"name\": \"folded\", \"type\": \"UnitAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_involution_trait_failing_operation_fold\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_involution_trait_no_operation_fold\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_involution_trait_succesful_operation_fold\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_large_commutative\",\n    \"operands\": [\n      { \"name\": \"op1\", \"type\": \"I32\" },\n      { \"name\": \"op2\", \"type\": \"I32\" },\n      { \"name\": \"op3\", \"type\": \"I32\" },\n      { \"name\": \"op4\", \"type\": \"I32\" },\n      { \"name\": \"op5\", \"type\": \"I32\" },\n      { \"name\": \"op6\", \"type\": \"I32\" },\n      { \"name\": \"op7\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_m\",\n    \"attributes\": [\n      { \"name\": \"optional_attr\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_nonnorm\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"Y\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_norm\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"Y\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_norm_ret\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"Z\", \"type\": \"AnyMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_optionally_implementing_interface\",\n    \"attributes\": [\n      { \"name\": \"implementsInterface\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_s\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_bit_enum\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestBitEnumAttr{read|write|execute}\" },\n      { \"name\": \"tag\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`tag` $tag^)? attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_bit_enum_prop\",\n    \"attributes\": [\n      { \"name\": \"value1\", \"type\": \"TestBitEnumProp{read|write|execute}\" },\n      { \"name\": \"value2\", \"type\": \"TestBitEnumProp{read|write|execute}\" }\n    ],\n    \"assemblyFormat\": \"$value1 ($value2^)? attr-dict `:` `(``)`\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_bit_enum_prop_named\",\n    \"attributes\": [\n      { \"name\": \"value1\", \"type\": \"TestBitEnumPropNamed\" },\n      { \"name\": \"value2\", \"type\": \"TestBitEnumPropNamed\" }\n    ],\n    \"assemblyFormat\": \"$value1 ($value2^)? attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_bit_enum_vbar\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestBitEnumVerticalBarAttr{user|group|other}\" },\n      { \"name\": \"tag\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`tag` $tag^)? attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_data_layout\",\n    \"summary\": \"An op that uses DataLayout implementation from the Target dialect\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_effects_a\",\n    \"operands\": [\n      { \"name\": \"optional_symbol\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"first\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"second\", \"type\": \"SymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_enum\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumAttr{first|second|third}\" },\n      { \"name\": \"tag\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`tag` $tag^)? attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_enum_prop\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumProp{first|second|third}\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_enum_prop_attr_form\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumPropAttrForm{first|second|third}\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_enum_prop_attr_form_always\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TestEnumPropAttrFormAlways{first|second|third}\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_infer_type_adaptor_if\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTensor\" },\n      { \"name\": \"y\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_loc_attr\",\n    \"attributes\": [\n      { \"name\": \"loc_attr\", \"type\": \"LocationAttr\" }\n    ],\n    \"assemblyFormat\": \"$loc_attr attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_property_predicates\",\n    \"attributes\": [\n      { \"name\": \"scalar\", \"type\": \"NonNegativeI64Prop\" },\n      { \"name\": \"optional\", \"type\": \"OptionalProp<NonNegativeI64Prop>\" },\n      { \"name\": \"defaulted\", \"type\": \"DefaultValuedProp<NonNegativeI64Prop, 0>\" },\n      { \"name\": \"more_constrained\", \"type\": \"ConfinedProp<NonNegativeI64Prop, CPred<$_self <= 5>, between 0 and 5>\" },\n      { \"name\": \"array\", \"type\": \"ArrayProp<NonNegativeI64Prop>\" },\n      { \"name\": \"non_empty_unconstrained\", \"type\": \"NonEmptyArray<I64Prop>\" },\n      { \"name\": \"non_empty_constrained\", \"type\": \"NonEmptyArray<NonNegativeI64Prop>\" },\n      { \"name\": \"non_empty_optional\", \"type\": \"OptionalProp<NonEmptyArray<NonNegativeI64Prop>>\" },\n      { \"name\": \"unconstrained\", \"type\": \"I64Prop\" }\n    ],\n    \"assemblyFormat\": \"attr-dict prop-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.op_with_region_fold\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_region_fold_no_side_effect\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_region_pattern\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_result_shape_interface\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_with_shaped_type_infer_type_adaptor_if\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.op_x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyInteger\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operand_rank_equals_result_size\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operand0_and_result_have_same_element_count\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operand0_and_result_have_same_element_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operand0_and_result_have_same_rank\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operand0_and_result_have_same_shape\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operand0_and_result_have_same_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operands_and_result_have_same_rank\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operands_have_same_element_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operands_have_same_rank\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyShaped\" },\n      { \"name\": \"y\", \"type\": \"AnyShaped\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.operands_have_same_type\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyType\" },\n      { \"name\": \"y\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.optional_custom_attr\",\n    \"description\": \"Test using a custom directive as the optional group anchor and the first\\n    element to parse. It is expected to return an `OptionalParseResult`.\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"OptionalAttr<I1Attr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (custom<OptionalCustomParser>($attr)^) : (`bar`)?\"\n  },\n  {\n    \"name\": \"tfrt_test.overridden_symbol_visibility\",\n    \"summary\": \"operation overridden symbol visibility accessors\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.parse_b64\",\n    \"attributes\": [\n      { \"name\": \"b64\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.parse_example_from_bytes\",\n    \"summary\": \"tfrt_test.parse_example_from_bytes operation\",\n    \"description\": \"The proto.parse_example_from_bytes parses a string into a protobuf object\\n    whose format follows example.proto.\\n\\n    Example:\\n      %example = tfrt_test.parse_example_from_bytes\\\" %bytes\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"ProtoExampleType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.parse_integer_literal\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.parse_wrapped_keyword\",\n    \"attributes\": [\n      { \"name\": \"keyword\", \"type\": \"StrAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.positive_int_attr\",\n    \"attributes\": [\n      { \"name\": \"i32attr\", \"type\": \"ConfinedAttr<I32Attr, [IntPositive]>\" },\n      { \"name\": \"i64attr\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.producing_br\",\n    \"operands\": [\n      { \"name\": \"firstOperands\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"secondOperands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dummy\", \"type\": \"I32\" }\n    ],\n    \"successors\": [\n      {\n        \"name\": \"first\"\n      },\n      {\n        \"name\": \"second\"\n      }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.promised_interfaces\",\n    \"operands\": [\n      { \"name\": \"promisedType\", \"type\": \"ConfinedType<AnyType, [HasPromiseOrImplementsTypeInterface<TestExternalTypeInterface>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"promisedAttr\", \"type\": \"ConfinedAttr<AnyAttr, [PromisedAttrInterface<TestExternalAttrInterface>]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.prop\",\n    \"operands\": [\n      { \"name\": \"upperInits\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transforms\", \"type\": \"I32ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.prop_pattern_op_1\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"StringProp\" },\n      { \"name\": \"val\", \"type\": \"I64Prop\" },\n      { \"name\": \"cond\", \"type\": \"BoolProp\" }\n    ],\n    \"assemblyFormat\": \"$tag $val $cond attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.prop_pattern_op_2\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"StringProp\" }\n    ],\n    \"assemblyFormat\": \"$input $tag attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.ranked_int_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"vector_i32_attr\", \"type\": \"RankedI32ElementsAttr<[2]>\" },\n      { \"name\": \"matrix_i64_attr\", \"type\": \"RankedI64ElementsAttr<[4, 8]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.ranked_tensor_op\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.read_buffer\",\n    \"description\": \"An operation that reads the buffer operand and dumps its contents.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.recursive_rewrite\",\n    \"attributes\": [\n      { \"name\": \"depth\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$depth attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.recursively_speculatable_op\",\n    \"description\": \"Op used to test conditional speculation.  This op can be speculatively\\n    executed only if all the ops in the attached region can be.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.reflect_bounds\",\n    \"description\": \"Integer range analysis will update this op to reflect inferred integer range\\n    of the input, so it can be checked with FileCheck\\n\\n    Example:\\n\\n    ```mlir\\n    CHECK: test.reflect_bounds {smax = 7 : index, smin = 0 : index, umax = 7 : index, umin = 0 : index}\\n    %1 = test.reflect_bounds %0 : index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"umin\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"umax\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"smin\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"smax\", \"type\": \"OptionalAttr<APIntAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $value `:` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_test.region_buffer_based\",\n    \"description\": \"A buffer based operation, that uses memRefs as input and output.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedOrUnrankedMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`\\n    $region attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.region_if\",\n    \"description\": \"Represents an abstract if-then-else-join pattern. In this context, the then\\n    and else regions jump to the join region, which finally returns to its\\n    parent op.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"elseRegion\", \"type\": \"AnyRegion\" },\n      { \"name\": \"joinRegion\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.region_if_yield\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$results `:` type($results) attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.region_yield\",\n    \"description\": \"This operation is used in a region and yields the corresponding type for\\n    that operation.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$result `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.reify_bound\",\n    \"description\": \"Reify a bound for the given index-typed value or dimension size of a shaped\\n    value. \\\"LB\\\", \\\"EQ\\\" and \\\"UB\\\" bounds are supported. If `scalable` is set,\\n    `vscale_min` and `vscale_max` must be provided, which allows computing\\n    a bound in terms of \\\"vector.vscale\\\" for a given range of vscale.\",\n    \"operands\": [\n      { \"name\": \"var\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"type\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"EQ\\\">\" },\n      { \"name\": \"constant\", \"type\": \"UnitAttr\" },\n      { \"name\": \"scalable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"vscale_min\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"vscale_max\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.reify_shaped_type_using_reify_dim_of_result\",\n    \"description\": \"Test that when resolving a single dimension of a result for an operation\\n    that implements `reifyDimOfResult`, which is used to get the required value.\\n    `reifyResultShapes` and `reifyShapeOfResult` are implemented as failures\\n    to ensure they are not called. The op semantics is that the first result has\\n    the same shape as the second operand and the second result has the same shape\\n    as the first operand.\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.reify_shaped_type_using_reify_result_shapes\",\n    \"description\": \"Test that when resolving a single dimension of a result for an operation\\n    that doesnt implement `reifyShapeOfResult` nor implements `reifyDimOfResult`\\n    calls into the implementation of `reifyResultShapes` to get the required value.\\n    The op semantics is that the first result has the same shape as the second operand\\n    and the second result has the same shape as the first operand.\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.reify_shaped_type_using_reify_shape_of_result\",\n    \"description\": \"Test that when resolving a single dimension of a result for an operation\\n    that doesnt implement `reifyDimOfResult` but implements `reifyShapeOfResult`, which\\n    is used to get the required value. `reifyResultShapes` is implemented as a failure\\n    (which is also the default implementation) to ensure it is not called.\\n    The op semantics is that the first result has the same shape as the second operand\\n    and the second result has the same shape as the first operand.\",\n    \"operands\": [\n      { \"name\": \"operand1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"operand2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result2\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.remapped_value_region\",\n    \"summary\": \"remapped_value_region operation\",\n    \"description\": \"Test op that remaps values that haven't yet been converted in Dialect\\n    Conversion.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.resize_bilinear\",\n    \"summary\": \"tfrt_test.resize_bilinear operation\",\n    \"description\": \"The tfrt_test.resize_bilinear operation resizes the input tensor based on\\n    the given height and width. It returns a tensor with the same semantics as\\n    tf.compat.v1.image.resize(input, [height, width]).\\n\\n    Example:\\n      %image_resized = tfrt_test.resize_bilinear %image_decoded, %new_height, %new_width\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.result_has_same_type_as_attr\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"assemblyFormat\": \"$attr `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.result_name_from_type\",\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.result_name_from_type_interface\",\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.same_operand_result_type\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.side_effect_op\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.side_effect_with_region_op\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"`(` $operand`)` $region attr-dict `:`  type($operand)  `->` type($result)\"\n  },\n  {\n    \"name\": \"tfrt_test.sign\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"RankedTensorOf<[F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[SI32]>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tfrt_test.signless_like_variadic\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"Variadic<SignlessIntegerLike>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.single_no_terminator_custom_asm_op\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.single_no_terminator_op\",\n    \"regions\": [\n      { \"name\": \"my_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` $my_region\"\n  },\n  {\n    \"name\": \"tfrt_test.SingleBlockImplicitTerminator\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.sized_region_op\",\n    \"regions\": [\n      { \"name\": \"my_region\", \"type\": \"SizedRegion<2>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.slash_attr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"SlashAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.source_op\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"AnyInteger\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tag\", \"type\": \"AnyI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.ssacfg_region\",\n    \"summary\": \"operation with an SSACFG region\",\n    \"description\": \"Test op that defines an SSACFG region.\",\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.store_with_a_loop_region\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"store_before_region\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$address attr-dict-with-keyword regions `:` type($address)\"\n  },\n  {\n    \"name\": \"tfrt_test.store_with_a_region\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"AnyMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"store_before_region\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$address attr-dict-with-keyword regions `:` type($address)\"\n  },\n  {\n    \"name\": \"tfrt_test.store_with_a_region_terminator\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.string_attr_pretty_name\",\n    \"results\": [\n      { \"name\": \"r\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.string_attr_with_mixed_type\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttrOf<[TypedStrAttr<AnyInteger>, I64Attr]>\" }\n    ],\n    \"assemblyFormat\": \"$attr attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.string_attr_with_type\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedStrAttr<AnyInteger>\" }\n    ],\n    \"assemblyFormat\": \"$attr attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.string_elements_attr\",\n    \"attributes\": [\n      { \"name\": \"scalar_string_attr\", \"type\": \"StringElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.switch_with_no_break\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cases\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"caseRegions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"$arg attr-dict custom<SwitchCases>($cases, $caseRegions)\"\n  },\n  {\n    \"name\": \"tfrt_test.symbol\",\n    \"summary\": \"operation which defines a new symbol\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_binding_a\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_binding_b\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_binding_c\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_binding_d\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"I32\" },\n      { \"name\": \"input2\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_binding_no_result\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_scope\",\n    \"summary\": \"operation which defines a new symbol table\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_scope_isolated\",\n    \"summary\": \"operation which defines a new symbol table that is IsolatedFromAbove\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_table_region\",\n    \"summary\": \"operation which defines a new symbol table without a restriction on a terminator\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.symbol_with_result\",\n    \"summary\": \"invalid symbol operation that produces an SSA result\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.sync_benchmark\",\n    \"summary\": \"synchronous benchmark operation\",\n    \"description\": \"The \\\"tfrt_test.sync_benchmark\\\" operation benchmarks the performance of an\\n     MLIR synchronous region by executing the given MLIR region repeatedly up\\n     to the `duration_secs` seconds or `max_count` times. `num_warmup_runs`\\n     specifies the number of warm up runs to run the given MLIR region before\\n     the benchmark starts.\\n\\n     The target MLIR region can take an arbitrary number of arguments and\\n     should return no value. The arguments for the MLIR region are\\n     provided as the operands of the tfrt_test.sync_benchmark op.\\n\\n     Example:\\n        // Target sync function to benchmark.\\n        func @fibonacci.i32() -> i32 attributes {hex.sync} {\\n          %0 = \\\"hex.constant_s.i32\\\"() {value = 0 : i32} : () -> i32\\n          %1 = \\\"hex.constant_s.i32\\\"() {value = 1 : i32} : () -> i32\\n\\n          %2 = \\\"hex.add_s.i32\\\"(%0, %1) : (i32, i32) -> i32\\n          %3 = \\\"hex.add_s.i32\\\"(%1, %2) : (i32, i32) -> i32\\n          %4 = \\\"hex.add_s.i32\\\"(%2, %3) : (i32, i32) -> i32\\n          %5 = \\\"hex.add_s.i32\\\"(%3, %4) : (i32, i32) -> i32\\n\\n          hex.return\\n        }\\n\\n       tfrt_test.sync_benchmark @fibonacci.i32()\\n           duration_secs = 1, max_count = 100, num_warmup_runs = 10\",\n    \"attributes\": [\n      { \"name\": \"target_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"duration_secs\", \"type\": \"I32Attr\" },\n      { \"name\": \"max_count\", \"type\": \"I32Attr\" },\n      { \"name\": \"num_warmup_runs\", \"type\": \"DefaultValuedOptionalAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.takes_static_memref\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyStaticShapeMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_0\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_2\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_3\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"resultA\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"resultB\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_4\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_5\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_6\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"b\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tblgen_build_7\",\n    \"attributes\": [\n      { \"name\": \"attr0\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tensor_based\",\n    \"description\": \"A tensor based operation, that uses a tensor as an input and results in a\\n    tensor again.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"`in` `(` $input`:` type($input) `)` `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.test_cost\",\n    \"summary\": \"tfrt_test.test_cost\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I64Attr\" },\n      { \"name\": \"_tfrt_cost\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$args attr-dict `:` type($args)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.three_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" },\n      { \"name\": \"result3\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.tiling_no_dps_op\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.two_result\",\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"I32\" },\n      { \"name\": \"result2\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"MultiResultOpEnum{kind1|kind2|kind3|kind4|kind5|kind6}\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.type_array_attr\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.type_array_attr_with_default\",\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<TypeAttr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.type_attr_of\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttrOf<I64>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $type\"\n  },\n  {\n    \"name\": \"tfrt_test.typed_attr\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"attr\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $type `=` custom<AttrElideType>(ref($type), $attr)\"\n  },\n  {\n    \"name\": \"tfrt_test.unreifiable_dim_of_result_shape\",\n    \"description\": \"Test handling of case where some dimension of the result cannot be\\n    reified. This tests the path when `reifyDimOfResult` is implemented,\\n    and `reifyDimOfResult` with `reifyResultShapes` are implemented as a failure.\\n\\n    Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but\\n    dim 1 of `result` is not reifiable.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.unreifiable_result_shape\",\n    \"description\": \"Test handling of case where some dimension of the result cannot be\\n    reified. This tests the path when `reifyShapeOfResult` is implemented,\\n    but not `reifyDimOfResult` with `reifyResultShapes` implemented as a failure.\\n\\n    Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but\\n    dim 1 of `result` is not reifiable.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.unreifiable_result_shapes\",\n    \"description\": \"Test handling of case where some dimension of the result cannot be\\n    reified. This tests the path when `reifyResultShapes` is implemented.\\n\\n    Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but\\n    dim 1 of `result` is not reifiable.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"2DTensorOf<[AnyType]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.using_int_property_with_worse_bytecode\",\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"IntPropertyWithWorseBytecode\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.using_property_in_custom\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"IntArrayProp<I64Prop>\" }\n    ],\n    \"assemblyFormat\": \"custom<UsingPropertyInCustom>($prop) attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.using_property_in_custom_and_other\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"IntArrayProp<I64Prop>\" },\n      { \"name\": \"other\", \"type\": \"I64Prop\" }\n    ],\n    \"assemblyFormat\": \"custom<UsingPropertyInCustom>($prop) prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.using_property_ref_in_custom\",\n    \"attributes\": [\n      { \"name\": \"first\", \"type\": \"IntProp<int64_t>\" },\n      { \"name\": \"second\", \"type\": \"IntProp<int64_t>\" }\n    ],\n    \"assemblyFormat\": \"custom<IntProperty>($first) `+` custom<SumProperty>($second, ref($first)) attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.value_with_bounds\",\n    \"description\": \"Creates a value with specified [min, max] range for value bounds analysis.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = test.value_with_bounds { min = 4 : index, max = 5 : index}\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"IndexAttr\" },\n      { \"name\": \"max\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.variadic_no_terminator_op\",\n    \"regions\": [\n      { \"name\": \"my_regions\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` $my_regions\"\n  },\n  {\n    \"name\": \"tfrt_test.variadic_region_inferred\",\n    \"regions\": [\n      { \"name\": \"bodies\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.variadic_rewrite_dst_op\",\n    \"operands\": [\n      { \"name\": \"brg\", \"type\": \"AnyType\" },\n      { \"name\": \"crg\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"arg\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.variadic_rewrite_src_op\",\n    \"operands\": [\n      { \"name\": \"arg\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"brg\", \"type\": \"AnyType\" },\n      { \"name\": \"crg\", \"type\": \"Variadic<AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.variadic_segment_prop\",\n    \"operands\": [\n      { \"name\": \"a1\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"a2\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"b1\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"b2\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"assemblyFormat\": \"$a1 `:` $a2 `:` type($b1) `:` type($b2) prop-dict attr-dict `end`\"\n  },\n  {\n    \"name\": \"tfrt_test.variadic_with_same_operand_results\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnySignlessInteger\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.verifiers\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.versionedA\",\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"AnyI64Attr\" },\n      { \"name\": \"modifier\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.versionedB\",\n    \"attributes\": [\n      { \"name\": \"attribute\", \"type\": \"TestAttrParams\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.versionedC\",\n    \"attributes\": [\n      { \"name\": \"attribute\", \"type\": \"AnyAttrOf<[TestAttrParams, I32ElementsAttr]>\" }\n    ]\n  },\n  {\n    \"name\": \"tfrt_test.with_array_properties\",\n    \"attributes\": [\n      { \"name\": \"ints\", \"type\": \"ArrayProp<I64Prop>\" },\n      { \"name\": \"strings\", \"type\": \"ArrayProp<StringProp>\" },\n      { \"name\": \"nested\", \"type\": \"ArrayProp<ArrayProp<I32Prop>>\" },\n      { \"name\": \"opt\", \"type\": \"OptionalProp<ArrayProp<I32Prop>>\" },\n      { \"name\": \"explicitOptions\", \"type\": \"ArrayProp<OptionalProp<I64Prop>>\" },\n      { \"name\": \"explicitUnits\", \"type\": \"ArrayProp<UnitProp>\" },\n      { \"name\": \"hasDefault\", \"type\": \"DefaultValuedProp<ArrayProp<I64Prop>, ::llvm::ArrayRef<int64_t>{}, ::llvm::SmallVector<int64_t>{}>\" }\n    ],\n    \"assemblyFormat\": \"`ints` `=` $ints\\n    `strings` `=` $strings\\n    `nested` `=` $nested\\n    `opt` `=` $opt\\n    `explicitOptions` `=` $explicitOptions\\n    `explicitUnits` `=` $explicitUnits\\n    ($hasDefault^ `thats_has_default`)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_bounds\",\n    \"description\": \"Creates a value with specified [min, max] range for integer range analysis.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = test.with_bounds { umin = 4 : index, umax = 5 : index, smin = 4 : index, smax = 5 : index } : index\\n    ```\",\n    \"results\": [\n      { \"name\": \"fakeVal\", \"type\": \"InferIntRangeType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"umin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"umax\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smax\", \"type\": \"APIntAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($fakeVal)\"\n  },\n  {\n    \"name\": \"tfrt_test.with_bounds_region\",\n    \"attributes\": [\n      { \"name\": \"umin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"umax\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smin\", \"type\": \"APIntAttr\" },\n      { \"name\": \"smax\", \"type\": \"APIntAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt_test.with_default_valued_properties\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"b\", \"type\": \"DefaultValuedProp<StringProp, \\\"\\\">\" },\n      { \"name\": \"c\", \"type\": \"DefaultValuedProp<IntProp<int32_t>, -1>\" },\n      { \"name\": \"unit\", \"type\": \"UnitProp\" }\n    ],\n    \"assemblyFormat\": \"($a^) : (`na`)?\\n    ($b^)?\\n    ($c^)?\\n    ($unit^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_nice_properties\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"PropertiesWithCustomPrint\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_optional_properties\",\n    \"attributes\": [\n      { \"name\": \"anAttr\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"simple\", \"type\": \"OptionalProp<I64Prop>\" },\n      { \"name\": \"simplei8\", \"type\": \"OptionalProp<IntProp<int8_t>>\" },\n      { \"name\": \"simpleui8\", \"type\": \"OptionalProp<IntProp<uint8_t>>\" },\n      { \"name\": \"nonTrivialStorage\", \"type\": \"OptionalProp<StringProp>\" },\n      { \"name\": \"hasDefault\", \"type\": \"OptionalProp<DefaultValuedProp<I64Prop, 0>>\" },\n      { \"name\": \"nested\", \"type\": \"OptionalProp<OptionalProp<I64Prop>>\" },\n      { \"name\": \"longSyntax\", \"type\": \"OptionalProp<StringProp, 0>\" },\n      { \"name\": \"hasUnit\", \"type\": \"UnitProp\" },\n      { \"name\": \"maybeUnit\", \"type\": \"OptionalProp<UnitProp>\" }\n    ],\n    \"assemblyFormat\": \"(`anAttr` `=` $anAttr^)?\\n    (`simple` `=` $simple^)?\\n    (`simplei8` `=` $simplei8^)?\\n    (`simpleui8` `=` $simpleui8^)?\\n    (`nonTrivialStorage` `=` $nonTrivialStorage^)?\\n    (`hasDefault` `=` $hasDefault^)?\\n    (`nested` `=` $nested^)?\\n    (`longSyntax` `=` $longSyntax^)?\\n    (`hasUnit` $hasUnit^)?\\n    (`maybeUnit` `=` $maybeUnit^)?\\n    attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_properties\",\n    \"attributes\": [\n      { \"name\": \"a\", \"type\": \"I64Prop\" },\n      { \"name\": \"b\", \"type\": \"StrAttr\" },\n      { \"name\": \"c\", \"type\": \"StringProp\" },\n      { \"name\": \"flag\", \"type\": \"BoolProp\" },\n      { \"name\": \"array\", \"type\": \"IntArrayProp<I64Prop>\" },\n      { \"name\": \"array32\", \"type\": \"IntArrayProp<I32Prop>\" }\n    ],\n    \"assemblyFormat\": \"`a` `=` $a `,`\\n    `b` `=` $b `,`\\n    `c` `=` $c `,`\\n    `flag` `=` $flag `,`\\n    `array` `=` $array `,`\\n    `array32` `=` $array32 attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_properties_and_attr\",\n    \"attributes\": [\n      { \"name\": \"lhs\", \"type\": \"I32Attr\" },\n      { \"name\": \"rhs\", \"type\": \"IntProp<int64_t>\" }\n    ],\n    \"assemblyFormat\": \"$lhs prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_properties_and_inferred_type\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs\", \"type\": \"I32Attr\" },\n      { \"name\": \"rhs\", \"type\": \"IntProp<int64_t>\" },\n      { \"name\": \"packed\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_versioned_properties\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"VersionedProperties\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_wrapped_properties\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"MyStructProperty\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt_test.with_wrapped_properties2\",\n    \"attributes\": [\n      { \"name\": \"prop\", \"type\": \"MyStructProperty2\" }\n    ],\n    \"assemblyFormat\": \"prop-dict attr-dict\"\n  },\n  {\n    \"name\": \"tfrt.add.f32\",\n    \"summary\": \"tfrt.add operation\",\n    \"description\": \"An operation that takes two inputs and returns their sum as the result.\\n\\n     Example:\\n       %2 = tfrt.add.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.add.f64\",\n    \"summary\": \"tfrt.add operation\",\n    \"description\": \"An operation that takes two inputs and returns their sum as the result.\\n\\n     Example:\\n       %2 = tfrt.add.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.add.i32\",\n    \"summary\": \"tfrt.add operation\",\n    \"description\": \"An operation that takes two inputs and returns their sum as the result.\\n\\n     Example:\\n       %2 = tfrt.add.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.add.i64\",\n    \"summary\": \"tfrt.add operation\",\n    \"description\": \"An operation that takes two inputs and returns their sum as the result.\\n\\n     Example:\\n       %2 = tfrt.add.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.and.i1\",\n    \"summary\": \"tfrt.and operation\",\n    \"description\": \"An operation that takes two inputs and returns their conjunction as the\\n     result.\\n\\n     Example:\\n       %2 = tfrt.and.i1 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.call\",\n    \"summary\": \"host executor call operation\",\n    \"description\": \"The \\\"tfrt.call\\\" operation represents a direct call to a function.  The\\n    operands and result types of the call must match the specified function\\n    type.  The callee is encoded as a function attribute named \\\"callee\\\".\\n\\n      %2 = tfrt.call @my_add(%0, %1) : (f32, f32) -> f32\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.case\",\n    \"summary\": \"An n-way switch statement which calls a single branch function.\",\n    \"description\": \"An n-way switch statement, implementing the following:\\n        ```\\n        switch (branch_index) {\\n          case 0:\\n            outputs = branches[0](inputs);\\n            break;\\n          case 1:\\n            outputs = branches[1](inputs);\\n            break;\\n          ...\\n          case [[nbranches-1]]:\\n          default:\\n            outputs = branches[nbranches-1](inputs);\\n            break;\\n        }\\n        ```\\n    Example: %res = tfrt.case %branch_idx [@branch0, @branch1] (%arg0, %arg1) : (i32, i32) -> (i32)\",\n    \"operands\": [\n      { \"name\": \"branch_index\", \"type\": \"I32\" },\n      { \"name\": \"branch_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"branch_outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"branches\", \"type\": \"ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$branch_index $branches `(` $branch_operands `)` attr-dict `:` `(` type($branch_operands) `)` `->` `(` type($branch_outputs) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.cond\",\n    \"summary\": \"conditional operation\",\n    \"description\": \"The \\\"tfrt.cond\\\" operation takes an i1 condition, a 'true' function and a\\n    'false' function.  If the condition is true, the 'true' function is called\\n    and the \\\"tfrt.cond\\\" operation returns the results of that function, otherwise\\n    the \\\"false\\\" function is called and its values are returned.\\n\\n    The 'true' and 'false' functions must have the same signature, but they may\\n    take an arbitrary number of arguments and return values with the same types\\n    as the op return types. Both functions are encoded as function attribute,\\n    named true_fn and false_fn. The a_ and b_ prefix prevent reordering by BEF\\n    since BEF orders attribute by name alphabetically.\\n\\n    This operation is safe to use as a 'nonstrict' op, which dispatches its body\\n    whenever the condition and any dependent arguments are resolved.\\n\\n    Example:\\n\\n      %res = tfrt.cond %cond @true_fn @false_fn (%x, %y) : (i32, f32) -> (i32)\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1\" },\n      { \"name\": \"fn_operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_true_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"b_false_fn\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$cond $a_true_fn $b_false_fn `(` $fn_operands `)` attr-dict `:` `(` type($fn_operands) `)` `->` `(` type($outputs) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant_s.f16\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F16\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F16Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant_s.f32\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant_s.f64\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant_s.i64\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.bf16\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"BF16\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"BF16Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.complex128\",\n    \"summary\": \"host executor complex constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<F64>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"real\", \"type\": \"F64Attr\" },\n      { \"name\": \"imaginary\", \"type\": \"F64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$real `,` $imaginary attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.complex64\",\n    \"summary\": \"host executor complex constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Complex<F32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"real\", \"type\": \"F32Attr\" },\n      { \"name\": \"imaginary\", \"type\": \"F32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$real `,` $imaginary attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.f16\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F16\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F16Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.f32\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.f64\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.i1\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"I1Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.i32\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.i64\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.ui32\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"UI32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UI32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.constant.ui64\",\n    \"summary\": \"host executor constant value constructor\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"UI64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UI64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.div.i32\",\n    \"summary\": \"tfrt.div operation\",\n    \"description\": \"An operation that takes two inputs and returns their quotient and remainder\\n     as the result.\\n\\n     Example:\\n       %2, %3 = tfrt.div.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I32\" },\n      { \"name\": \"result1\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.div.i64\",\n    \"summary\": \"tfrt.div operation\",\n    \"description\": \"An operation that takes two inputs and returns their quotient and remainder\\n     as the result.\\n\\n     Example:\\n       %2, %3 = tfrt.div.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"I64\" },\n      { \"name\": \"result1\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.equal.i32\",\n    \"summary\": \"tfrt.equal operation\",\n    \"description\": \"An operation that takes two inputs and returns their equality as the\\n     result.\\n\\n     Example:\\n       %2 = tfrt.equal.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.equal.i64\",\n    \"summary\": \"tfrt.equal operation\",\n    \"description\": \"An operation that takes two inputs and returns their equality as the\\n     result.\\n\\n     Example:\\n       %2 = tfrt.equal.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.get_device\",\n    \"summary\": \"Get the device object from the given device name\",\n    \"description\": \"Get the device object from the given device name.\\n\\n    Example:\\n      %result = tfrt.get_device %chain { device_name=\\\"GPU:0\\\" }\",\n    \"operands\": [\n      { \"name\": \"chain_in\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_DeviceType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"device_name\", \"type\": \"StrAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.if\",\n    \"summary\": \"if operation\",\n    \"description\": \"The \\\"tfrt.if\\\" operation takes an i1 condition, a 'then' body and an 'else'\\n    body.  If the condition is true, the 'then' body is run and the \\\"tfrt.if\\\"\\n    operation returns the results of that region, otherwise the \\\"else\\\" body is\\n    run and its values are returned.\\n\\n    The body regions must have the same signature, but they may take an\\n    arbitrary number of arguments and return values with the same types as the\\n    op return types, using a 'tfrt.return' operation at the end of the\\n    region.  The initial values are specified as operands of \\\"tfrt.if\\\" (along\\n    with the condition), and the types of the values are specified with a\\n    function type.\\n\\n    This operation is safe to use as a 'nonstrict' op, which dispatches its body\\n    whenever the condition and any dependent arguments are resolved.\\n\\n    Example:\\n\\n      %res = tfrt.if %cond, %x, %y : (i32, f32) -> i32 {\\n        %v1 = \\\"use\\\"(%x, %y) : (i32, f32) -> i32\\n        tfrt.return %v1 : i32\\n      } else {\\n        %v2 = \\\"abuse\\\"(%x, %y) : (i32, f32) -> i32\\n        tfrt.return %v2 : i32\\n      }\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_region\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.merge.chains\",\n    \"summary\": \"host executor merge chain\",\n    \"description\": \"The \\\"tfrt.merge.chains\\\" operation merges variadic number of inputs and\\n    outputs a single !tfrt.chain output.\\n\\n    Example:\\n\\n        %c1 = tfrt.new.chain\\n        %c2 = tfrt.new.chain\\n        %c3 = tfrt.new.chain\\n        %merged_c = tfrt.merge.chains %c1, %c2, %c3\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` type($inputs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.mul_s.i32\",\n    \"summary\": \"tfrt.mul operation\",\n    \"description\": \"An operation that takes two inputs and returns their product.\\n\\n     Example:\\n       %2 = tfrt.mul.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.mul_s.i64\",\n    \"summary\": \"tfrt.mul operation\",\n    \"description\": \"An operation that takes two inputs and returns their product.\\n\\n     Example:\\n       %2 = tfrt.mul.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.mul.i32\",\n    \"summary\": \"tfrt.mul operation\",\n    \"description\": \"An operation that takes two inputs and returns their product.\\n\\n     Example:\\n       %2 = tfrt.mul.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.mul.i64\",\n    \"summary\": \"tfrt.mul operation\",\n    \"description\": \"An operation that takes two inputs and returns their product.\\n\\n     Example:\\n       %2 = tfrt.mul.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.new.chain\",\n    \"summary\": \"host executor chain constructor\",\n    \"description\": \"The \\\"tfrt.new.chain\\\" operation returns a !tfrt.chain value, which can be fed\\n    into a side-effecting operation that does not depend on anything.\\n    For example:\\n\\n      func @foo() {\\n        ...\\n        %x = tfrt.new.chain\\n        \\\"side.effecting.thing\\\"(%x) : (!tfrt.chain) -> ()\\n      }\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.once\",\n    \"summary\": \"once operation\",\n    \"description\": \"Calls 'function' exactly once and stores the result in the resource context.\\n    Subsequent calls return the same result without calling the function again.\\n\\n    Example:\\n\\n    func @once(%arg0 : int32) -> i32 {\\n      tfrt.return %arg0 : i32\\n    }\\n\\n    // %1 always has the same value as %0 of the first execution.\\n    %1 = tfrt.once @once(%0)\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$function `(` operands `)` attr-dict\\n    `:` `(` type(operands) `)` `->` `(` type(results) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.parallel_call.i32\",\n    \"summary\": \"parallel_call.i32 operation\",\n    \"description\": \"The \\\"tfrt.parallel_call.i32\\\" is an alternative to \\\"tfrt.parallel_for.i32\\\" with\\n    a parallel region defined as a standalone function.\\n\\n    Example:\\n\\n      func @compute(%start : i32, %end : i32, %val : !my_type) -> !tfrt.chain {\\n        ...\\n      }\\n\\n      %from       = tfrt.constant.i32 0\\n      %to         = tfrt.constant.i32 100\\n      %block_size = tfrt.constant.i32 10\\n\\n      %val = ... : !my.type\\n\\n      %done = tfrt.parallel_call.i32 %from to %to fixed %block_size\\n              @compute(%val) : !my.type\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"I32\" },\n      { \"name\": \"end\", \"type\": \"I32\" },\n      { \"name\": \"block_size\", \"type\": \"I32\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.parallel_for.i32\",\n    \"summary\": \"parallel_for.i32 operation\",\n    \"description\": \"The \\\"tfrt.parallel_for.i32\\\" operation is a parallel for loop that executes\\n    its body function for non overlapping sub ranges. It has one region which\\n    represents the loop body function (see host_context/parallel_for.h C++\\n    equivalent).\\n\\n    The body region takes an arbitrary number of arguments and must return a\\n    single chain value using a 'tfrt.return' operation at the end of the region\\n    if it completes asynchronously. If the body region completes synchronously\\n    it must have empty returns (`tfrt.return` without operands).\\n\\n    Inside the loop region `%start` and `%end` values are bound to the parallel\\n    block start and end offsets (see example below).\\n\\n    This is a TFRT counterpart of the native C++ ParallelFor operation defined\\n    in: `host_context/parallel_for.h`.\\n\\n    Example:\\n\\n      %from       = tfrt.constant.i32 0\\n      %to         = tfrt.constant.i32 100\\n      %block_size = tfrt.constant.i32 10\\n\\n      %val = ... : !my.type\\n\\n      %done = tfrt.parallel_for.i32 %from to %to fixed %block_size,\\n                                   %val : !my.type {\\n        // Possible values for [%start, %end) are: [0, 10), [10, 20), ...\\n        \\\"use\\\"(%start, %end, %val) : (i32, i32, !my.type) -> ()\\n\\n        // Async regions must return a chain to signal completion.\\n        tfrt.return %chain : !tfrt.chain\\n\\n        // Sync regions must have an empty return.\\n        tfrt.return\\n      }\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"I32\" },\n      { \"name\": \"end\", \"type\": \"I32\" },\n      { \"name\": \"block_size\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.print.f32\",\n    \"summary\": \"tfrt.print operation\",\n    \"description\": \"An operation takes a number input and a chain input.\\n     It prints the number to stdout and returns a chain output.\\n     The chain input must be the second operand.\\n\\n     Example:\\n       %2 = tfrt.print.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.print.f64\",\n    \"summary\": \"tfrt.print operation\",\n    \"description\": \"An operation takes a number input and a chain input.\\n     It prints the number to stdout and returns a chain output.\\n     The chain input must be the second operand.\\n\\n     Example:\\n       %2 = tfrt.print.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.print.i1\",\n    \"summary\": \"tfrt.print operation\",\n    \"description\": \"An operation takes a number input and a chain input.\\n     It prints the number to stdout and returns a chain output.\\n     The chain input must be the second operand.\\n\\n     Example:\\n       %2 = tfrt.print.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.print.i32\",\n    \"summary\": \"tfrt.print operation\",\n    \"description\": \"An operation takes a number input and a chain input.\\n     It prints the number to stdout and returns a chain output.\\n     The chain input must be the second operand.\\n\\n     Example:\\n       %2 = tfrt.print.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.print.i64\",\n    \"summary\": \"tfrt.print operation\",\n    \"description\": \"An operation takes a number input and a chain input.\\n     It prints the number to stdout and returns a chain output.\\n     The chain input must be the second operand.\\n\\n     Example:\\n       %2 = tfrt.print.i32 %0, %1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.repeat.i32\",\n    \"summary\": \"repeat.i32 operation\",\n    \"description\": \"The \\\"tfrt.repeat.i32\\\" operation is a repeat loop that executes its body N\\n    times, where N is a 32-bit value specified by its first operand.  It has one\\n    region which represents the loop body.\\n\\n    The body region takes an arbitrary number of arguments and must return\\n    values with the same types, using a 'tfrt.return' operation at the end of the\\n    region.  The initial values for the loop are specified as operands (along\\n    with the trip count), and the types of the loop values are specified with a\\n    type list.  The operation returns the results of the final iteration.\\n\\n    This operation is safe to use as a 'nonstrict' op, which dispatches its body\\n    whenever dependent arguments are resolved.\\n\\n    Example:\\n\\n      %res1, %res2 = tfrt.repeat.i32 %i, %loopval1, %loopval2 : i32, f32 {\\n        \\\"use\\\"(%loopval1, %loopval2) : (i32, f32) -> ()\\n        ...\\n        tfrt.return %loopval1, %loopval2 : i32, f32\\n      }\",\n    \"operands\": [\n      { \"name\": \"trip_count\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.return\",\n    \"summary\": \"host executor return operation\",\n    \"description\": \"The \\\"tfrt.return\\\" operation represents a return operation within a function.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number and types must match the signature of the function\\n    that contains the operation. For example:\\n\\n      func @foo() : (i32, f8) {\\n        ...\\n        tfrt.return %0, %1 : i32, f8\",\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tfrt.while\",\n    \"summary\": \"while operation\",\n    \"description\": \"cond: The boolean to control whether the first iteration should be\\n      executed.\\n    operands: The arguments to the first iteration.\\n    results: The results of the last iteration. The number and types of results\\n      are the same as the number and types of operands.\\n    body_fn: The body function that takes the arguments and returns the results\\n      and an I1 value to indicate whether next iteration should be executed.\\n    parallel_iterations: The max number of iterations that can be dispatched in parallel.\\n\\n    The pseudo code:\\n\\n    while(cond) {\\n      results, cond = body_fn(operands)\\n      operands = results\\n    }\\n    return results\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"I1\" },\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"body_fn\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"parallel_iterations\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$cond $body_fn `(` $arguments `)` attr-dict `parallel_iterations` `(` $parallel_iterations `)` `:` `(` type($arguments) `)` `->` `(` type(results) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.concatenate\",\n    \"summary\": \"Destination-style twin for `mhlo.concatenate`\",\n    \"description\": \"tHLO ConcatenateOp composes a tensor or a memref from multiple tensors or\\n    memrefs.\\n\\n    Example:\\n    ```\\n      %concat = thlo.concatenate\\n        ins(%T1 : tensor<100x?xf32>, %T2 : tensor<300x?xf32>)\\n        outs(%init : tensor<400x?xf32>)\\n        dimension = 0\\n    ```\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#concatenate\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorOrMemref>\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.dynamic_broadcast_in_dim\",\n    \"summary\": \"Destination-style twin for `mhlo.dynamic_broadcast_in_dim`\",\n    \"description\": \"tHLO DynamicBroadcastInDimOp specifies a map how to broadcast input\\n    dimensions. It also supports broadcasting size-1 dimensions.\\n\\n    Example:\\n    ```\\n      %dyn_bcast = thlo.dynamic_broadcast_in_dim\\n        ins(%input : tensor<?x?xf32>)\\n        outs(%init : tensor<?x?x?xf32>)\\n        broadcast_dimensions = [0, 2]\\n    ```\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#broadcastindim\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TensorOrMemref\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"known_expanding_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"known_nonexpanding_dimensions\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.gather\",\n    \"summary\": \"Destination-style twin for `mhlo.gather`\",\n    \"description\": \"tHLO GatherOp corresponds to the canonicalized mHLO GatherOp, i.e.\\n\\n    - start_indices is a two-dimensional tensor.\\n    - index_vector_dim is 1\\n    - offset_dims is [1, 2, ...]\\n    - collapsed_slice_dims is []\\n    - start_index_map is range(start_indices.shape[1])\\n\\n    Example:\\n    ```\\n      %gathered = thlo.gather\\n        ins(%input : tensor<100xf32>, %indices : tensor<42x1xindex>)\\n        outs(%init : tensor<42xf32>)\\n    ```\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#gather.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TensorOrMemref\" },\n      { \"name\": \"start_indices\", \"type\": \"TensorOrMemrefOf<[Index]>\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.reverse\",\n    \"summary\": \"Destination-style twin for the `mhlo.reverse`\",\n    \"description\": \"Reverses the specified dimensions of `input` according to the given\\n    `dimensions`.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#rev_reverse.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TensorOrMemref\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reverse_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.scatter\",\n    \"summary\": \"Destination-style twin for `mhlo.scatter`\",\n    \"description\": \"tHLO ScatterOp corresponds to the canonicalized mHLO ScatterOp, i.e.\\n\\n    - update_window_dims is range(1, rank(update_window_dims))\\n    - inserted_window_dims is []\\n    - scatter_dims_to_operand_dims is range(0, rank(indices))\\n    - index_vector_dim is rank(indices) - 1\\n\\n    At the moment, the variadic case is not supported.\\n\\n    Example:\\n    ```\\n      %scattered = thlo.scatter\\n        ins(%indices : tensor<2x2xindex>, %input : tensor<2x1x3xf32>)\\n        outs(%init : tensor<3x3xf32>)\\n        (%arg3: f32, %arg4: f32) {\\n          %0 = arith.addf %arg3, %arg4 : f32\\n          thlo.yield %0 : f32\\n        }\\n    ```\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#scatter.\",\n    \"operands\": [\n      { \"name\": \"indices\", \"type\": \"TensorOrMemrefOf<[Index]>\" },\n      { \"name\": \"updates\", \"type\": \"TensorOrMemref\" },\n      { \"name\": \"init\", \"type\": \"TensorOrMemref\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"update_computation\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.sort\",\n    \"summary\": \"Destination-style twin for the `mhlo.sort`\",\n    \"description\": \"Sorts the given `operands` along the given `dimension` using the given\\n    `comparator`.\\n\\n    Example:\\n    ```\\n      %sorted1, %sorted2 = thlo.sort\\n        ins(%input1: tensor<?x?xf32>, %input2: tensor<?x?xi32>)\\n        outs(%init1: tensor<?x?xf32>, %init2: tensor<?x?xi32>)\\n        dimension = 0\\n        is_stable = true\\n        (%lhs0: f32, %rhs0: f32, %lhs1: i32, %rhs1: i32) {\\n          %0 = arith.cmpf ogt, %lhs0, %rhs0 : f32\\n          thlo.yield %0 : i1\\n        }\\n    ```\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#sort.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TensorOrMemref>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<TensorOrMemref>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"IndexAttr\" },\n      { \"name\": \"is_stable\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"comparator\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"thlo.yield\",\n    \"summary\": \"Yield operation for tHLO ops with regions.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $values `:` type($values)\"\n  },\n  {\n    \"name\": \"tile.abs\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.acos\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.acosh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.add\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.argsort\",\n    \"summary\": \"tensor sort index operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[I32, SI32]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"IndexAttr\" },\n      { \"name\": \"direction\", \"type\": \"SortDirection{asc|desc}\" }\n    ],\n    \"assemblyFormat\": \"$direction $tensor `[` $axis `]` attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.asin\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.asinh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.assign\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.atan\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.atanh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.bit_and\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseInteger\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.bit_not\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.bit_or\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseInteger\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.bit_shl\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseInteger\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.bit_shr\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseInteger\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.bit_xor\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseInteger\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseInteger\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.cast\",\n    \"summary\": \"cast operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` functional-type($tensor, $result)\"\n  },\n  {\n    \"name\": \"tile.ceil\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.cmp_eq\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.cmp_ge\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.cmp_gt\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.cmp_le\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.cmp_lt\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.cmp_ne\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.constant\",\n    \"summary\": \"constant\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tile.contract\",\n    \"operands\": [\n      { \"name\": \"init\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"operands\", \"type\": \"Variadic<EltwiseAny>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[AnyScalar]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"agg\", \"type\": \"AggregationKind{assign|add|max|min|mul}\" },\n      { \"name\": \"combo\", \"type\": \"CombinationKind{none|add|cond|eq|mul}\" },\n      { \"name\": \"sink\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"srcs\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" },\n      { \"name\": \"cons\", \"type\": \"OptionalAttr<IntegerSetAttr>\" },\n      { \"name\": \"shape\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"lowerBounds\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"upperBounds\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tile.cos\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.cosh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.div\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.erf\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.exp\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.floor\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.gather\",\n    \"summary\": \"special gather operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" },\n      { \"name\": \"indices\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<IndexAttr, 0>\" },\n      { \"name\": \"interpolationMode\", \"type\": \"DefaultValuedAttr<InterpolationMode{nearest|linear|cubic|none}, InterpolationMode::linear>\" },\n      { \"name\": \"nearestMode\", \"type\": \"DefaultValuedAttr<NearestMode{round_prefer_floor|round_prefer_ceil|floor|ceil|simple|none}, NearestMode::round_prefer_floor>\" },\n      { \"name\": \"cubeCoeff\", \"type\": \"DefaultValuedAttr<F64Attr, -0.75>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<GatherMode{normal|nd}, GatherMode::normal>\" },\n      { \"name\": \"batchDims\", \"type\": \"DefaultValuedAttr<IndexAttr, 0>\" },\n      { \"name\": \"OutOfBoundsMode\", \"type\": \"DefaultValuedAttr<OutOfBoundsMode{gather_edge_padded_input|return_zero}, OutOfBoundsMode::gather_edge_padded_input>\" }\n    ],\n    \"assemblyFormat\": \"$tensor $indices attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.ident\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.index\",\n    \"summary\": \"tensor index lookup operation\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseIndex\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"$axis attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tile.log\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.logical_and\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.logical_not\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.logical_or\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.logical_xor\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseBool\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.max\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.min\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.mod\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.mul\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.neg\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.pow\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.pragma\",\n    \"summary\": \"pragma operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op\", \"type\": \"StrAttr\" },\n      { \"name\": \"attrs\", \"type\": \"DictionaryAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['tensor', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$tensor $op $attrs attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"tile.prng\",\n    \"summary\": \"pseudorandom number generator\",\n    \"operands\": [\n      { \"name\": \"state\", \"type\": \"RankedTensorOf<[I32, UI32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[AnyFloat]>\" },\n      { \"name\": \"new_state\", \"type\": \"RankedTensorOf<[I32, UI32]>\" }\n    ],\n    \"assemblyFormat\": \"$state attr-dict `:` functional-type($state, results)\"\n  },\n  {\n    \"name\": \"tile.relu\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.reshape\",\n    \"summary\": \"tensor reshape operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"RankedTensorOf<[AnyScalar]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[AnyScalar]>\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` functional-type($tensor, $result)\"\n  },\n  {\n    \"name\": \"tile.round\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.scatter\",\n    \"summary\": \"special scatter operation\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" },\n      { \"name\": \"indices\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" },\n      { \"name\": \"updates\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[AnyInteger, AnyScalar]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<IndexAttr, 0>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<ScatterMode{normal|update_slice|update_elt|update_nd}, ScatterMode::normal>\" }\n    ],\n    \"assemblyFormat\": \"$data $indices $updates attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.select\",\n    \"summary\": \"conditional selection\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"EltwiseBool\" },\n      { \"name\": \"tcase\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"fcase\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$cond `,` $tcase `,` $fcase attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.shape\",\n    \"summary\": \"tensor shape operation\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"RankedTensorOf<[AnyScalar]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[SI32]>\" }\n    ],\n    \"assemblyFormat\": \"$tensor attr-dict `:` functional-type($tensor, $result)\"\n  },\n  {\n    \"name\": \"tile.sign\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.sin\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.sinh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.sqrt\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.sub\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"EltwiseAny\" },\n      { \"name\": \"rhs\", \"type\": \"EltwiseAny\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseAny\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tile.tan\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tile.tanh\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"EltwiseFloat\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $result)\"\n  },\n  {\n    \"name\": \"tm_tensor.attention\",\n    \"summary\": \"Attention operator\",\n    \"description\": \"This operator takes in 3 to 4 tensors: query(Q), key(K), value(V), and an\\n    optional mask(M) to compute the attention. These tensors must take on shapes\\n    BxMxK1 for Q, BxK2xK1 for K, BxK2xN for V, and BxMxK2 for M. For all these\\n    shapes, B represents the batch dimension, M represents sequence length, N\\n    represents head dimension, and K1 and K2 are hidden dimensions.\\n    Attention is defined as matmul(softmax(matmul(Q, transpose(K))+M), V) and\\n    has shape BxMxN. Usually, this operator also performs scaling, masking and\\n    dropout, but we leave that out of the current implementation.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyShaped>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `ins` `(` $inputs `:` type($inputs) `)`\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    (`->` type($result)^)?\"\n  },\n  {\n    \"name\": \"tm_tensor.scan\",\n    \"summary\": \"Scan operator\",\n    \"description\": \"Computes the inclusive/exclusive scan along a given dimension.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyShaped>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"inclusive\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`dimension` `(` $dimension `)`\\n    `inclusive` `(` $inclusive `)`\\n    attr-dict\\n    `ins` `(` $inputs `:` type($inputs) `)`\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tm_tensor.scatter\",\n    \"summary\": \"Scatter operator\",\n    \"description\": \"Based on XLA operation semantics, takes two `inputs` (`update` and\\n    `indices`) and `outputs` value (`original`). The operation updates\\n    the value at the slices specified by `indices` by combining the\\n    current value with the value in `updates` using the computation\\n    specified in `region`. The `region` specifies a binary operation\\n    of signature (T, T) -> T, where `T` is the element-type of\\n    `updates` (and `original`). The first argument correspond the\\n    value to be updated (i.e. from `updates`), and the second the\\n    current value (i.e. value from `original`).\\n\\n    The `indices` is a 2D tensor/memref type. The first dim is the number of\\n    updates, and the second dim is index depth. The index depth should always be\\n    static.\\n\\n    The first dim of `updates` and `indices` is identical, since they represent\\n    the number of updates.\\n\\n    The rank of the `original`/`result` is at least\\n    `index_depth + rank(%updates) - 1`. The first `index_depth` indices are\\n    derived from `indices` and the shape of update value has the last\\n    rank(%original) - index_depth values match %(originals) last dimensions,\\n    with the previous dims extending from the index offsets.\\n\\n    The unique_indices attribute carries the information whether all the indices\\n    are unique. If there are repeated indices, the first iteration loop will be\\n    marked as reduction.\\n\\n    The shapes definition follows tensorflow operations execept that it force\\n    batch dims to be 1D. See more information in\\n      https://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_update\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensorOrMemRefType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensorOrMemRefType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension_map\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"unique_indices\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `unique_indices` `(` $unique_indices `)`\\n    (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tm_tensor.sort\",\n    \"summary\": \"Sort operator\",\n    \"description\": \"Based on XLA operation semantics, sorts the given `operands` at the given\\n    `dimension` with the given `comparator`.\\n\\n    See https://www.tensorflow.org/xla/operation_semantics#sort.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    (`ins` `(` $inputs^ `:` type($inputs) `)`)?\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tm_tensor.topk\",\n    \"summary\": \"Top-K operator\",\n    \"description\": \"A Top-K operation for N-D tensors. Reduces the target dimension from the input\\n    size N down to K elements based on the supplied binary region.\\n\\n    Accepts an N-D tensor input consisting of values and an optioanl N-D tensor\\n    for indices of those values (i32 type). If input indices aren't provided, the\\n    index mapping is inferred based on the k dim.  Both input values/indices\\n    tensors and output values/indicies tensors must have the same shape. Top-K is\\n    computed along the target dimension (from dimension()). Returns two output\\n    tensors of values and the indicies of Top-K results. The output dimensions\\n    must match the input save for the dimension that is reduced to K results.\\n\\n    Region accepts lhs=[next N input] and rhs=[exiting K output] and yeilds an\\n    i1. If true, the two values are swapped:\\n      - For Top-K compoarision: >\\n      - For Min-K comparision: <\\n    Note: when the two values are equal, the first occurence is always selected.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyShaped>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    `dimension` `(` $dimension `)`\\n    `ins` `(` $inputs `:` type($inputs) `)`\\n    `outs` `(` $outputs `:` type($outputs) `)`\\n    $region (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"tm_tensor.yield\",\n    \"summary\": \"TMTensor yield op\",\n    \"description\": \"`tm_tensor.yield` is a special terminator operation for blocks inside\\n    regions in `tm_tensor` ops.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"top.A16MatMul\",\n    \"summary\": \"w8a16 / w4a16 matmul operator\",\n    \"description\": \"The special matrix multiplication designed for LLM Linear Layer.\\r\\n    Weight is saved in int8 with f16 per-channel quant scale.\\r\\n\\r\\n    y_f16 = x_f16 x (quantized_w.to(f16) * scale_f16)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyTensor\" },\n      { \"name\": \"zp\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"right_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"q_group_size\", \"type\": \"DefaultValuedAttr<I64Attr, 128>\" },\n      { \"name\": \"weight_bits\", \"type\": \"DefaultValuedAttr<I64Attr, 8>\" },\n      { \"name\": \"dq_type\", \"type\": \"DefaultValuedAttr<DqTypeAttr, \\\"NONE\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.Abs\",\n    \"summary\": \"Abs operator\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the absolute value of each element in the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = abs(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.AdaptiveAvgPool\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        {output}(N_i, C_j, p, q) = pool(input(N_i, C_j, start_h, start_w), kernel_size)\\r\\n    ```\\r\\n    start_h and start_w are the starting indices for the pooling window in the height and width dimensions.\\r\\n    pool can be any pooling function (max pooling, average pooling) applied over the region defined by the kernel size.\\r\\n    N is a batch size, C denotes a number of channels,\\r\\n    Shape:\\r\\n    - Input: (N, C_{in}, H_{in}, W_{in})\\r\\n    - Output: (N, C_{out}, H_{out}, W_{out})\\r\\n        ```math\\r\\n        H_{output} = {H_{in} + {padding}[0] + {padding}[2] - {kernel_shape}[0]} / {stride}[0] + 1\\r\\n        ```\\r\\n        ```math\\r\\n        W_{output} = {W_{in} + {padding}[1] + {padding}[3] - {kernel_shape}[1]} / {stride}[1] + 1\\r\\n        ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    auto_pad: It can be set to different modes (e.g., SAME, VALID) to automatically calculate the necessary padding based on\\r\\n              the input size,kernel size, and stride.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_size\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Add\",\n    \"summary\": \"add operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise addition of input1 and input2. Axis of size 1 will be broadcast,\\r\\n    as necessary.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReLU((input1 + input2; dim))\\r\\n    ```\\r\\n    Axis of size 1 will be broadcast if necessary.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    coeff: It is an array and allows for scaling the output of the addition operation.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"coeff\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.AddConst\",\n    \"summary\": \"Add Const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The AddConst operator is designed to perform an element-wise addition of a constant value to an input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input + const_val\\r\\n    ```\\r\\n    Where input1, input2, ..., inputN are the input tensors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Arange\",\n    \"summary\": \"Arange operator\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch aten::arange.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = [x | x = start + n * step, n is an integer, and start ≤ x < end]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    start(act.): The starting value of the sequence. This can be a tensor or None. If None, it defaults to 0.;\\r\\n    end(act.): The exclusive upper limit of the sequence.;\\r\\n    step(act.): The increment between each value in the sequence. This can be a tensor or None. If None, it defaults to 1.;\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"end\", \"type\": \"AnyTensor\" },\n      { \"name\": \"step\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Arccos\",\n    \"summary\": \"Arccos operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the Arccos of the given input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Arccos(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Arctanh\",\n    \"summary\": \"Arctanh operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the Arctanh of the given input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Arctanh(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Arg\",\n    \"summary\": \"Arg operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Computes the indices of the min/max/ of the input tensor's element along the provided axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        maximum operation:\\r\\n            output_max[i_1, i_2, i_3,..., i_k] = arg max{j}(input[i_1, i_2,..., i_k, j])\\r\\n        minimum operation:\\r\\n            output_min[i_1, i_2, i_3,..., i_k] = arg min{j}(input[i_1, i_2,..., i_k, j])\\r\\n    ```\\r\\n    where, ( j ) represents the index along the specified axis.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    select_last_index: select the last index of the minimum or maximum value when multiple  along the specified axis.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"keepdims\", \"type\": \"BoolAttr\" },\n      { \"name\": \"mode\", \"type\": \"ArgModeAttr\" },\n      { \"name\": \"select_last_index\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Attention\",\n    \"summary\": \"Attention operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs a multi head attention block. https://en.wikipedia.org/wiki/Attention_(machine_learning)\\r\\n    This block has Q_w, K_w,V_w, O_w and mask;\\r\\n    This operator utilizes query, key, and value weights (denoted as (Q_w), (K_w), and (V_w), respectively) to compute attention scores and\\r\\n    generate output representations.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        Attention(Q, K, V) = softmax(((Q x K^T) / \\\\sqrt{d_k}) + musk) x V;\\r\\n        head_i = Attention(Q x queries_weight, K x keys_weight, V x values_weight);\\r\\n        MultiHead(Q, K, V) = Concat(head_1, head_2, ..., head_h) x out_weight + out_bias;\\r\\n        output = MultiHead(input x queries_weight + queries_bias, input x keys_weight + keys_bias, input x values_weight + values_bias).\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    keys(act.): The keys are derived from the input data and help the model determine which parts of the input are relevant for each query.;\\r\\n    values(act.): The values are the actual information that will be aggregated based on the attention scores computed from the queries and keys.;\\r\\n    queries_weight(w.): Queries are the features that the model uses to ask questions about the input data.;\\r\\n    queries_bias(w.): added to the query representations after the weight transformation.;\\r\\n    keys_weight(w.): This weight tensor transforms the input into key representations.;\\r\\n    keys_bias(w.): added to the key representations after the weight transformation, providing further adjustment.;\\r\\n    values_weight(w.): used to transform the input into value representations.;\\r\\n    values_bias(w.): added to the value representations after the weight transformation.;\\r\\n    out_weight(w.): used to transform the concatenated output of the attention heads into the final output representation.;\\r\\n    out_bias(w.): added to the output representation after the final weight transformation.;\\r\\n    musk(w.):  apply masking during the attention computation, Masks can prevent the model from attending to certain positions in the input.;\\r\\n\\r\\n\\r\\n    4.attribute\\r\\n    scale: a scaling factor applied to the attention scores before they are passed through the softmax function.;\\r\\n    head: the number of attention heads to use in the multi-head attention mechanism.;\\r\\n    dim: the size of the input features or the size of the query, key, and value vectors.;\\r\\n    scale_param: adjust the scaling factor for the attention scores, It allows for flexibility in tuning the attention mechanism.;\\r\\n    zp_param: the zero-point parameters for quantization,;\\r\\n    has_bias: whether the attention mechanism includes bias terms in its computations.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"keys\", \"type\": \"AnyTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyTensor\" },\n      { \"name\": \"queries_weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"queries_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keys_weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"keys_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"values_weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"values_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"out_weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"out_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"head\", \"type\": \"I64Attr\" },\n      { \"name\": \"dim\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"scale_param\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<F64Attr>, {1.0}>\" },\n      { \"name\": \"zp_param\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {0}>\" },\n      { \"name\": \"has_bias\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.AvgPool\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        {output}(N_i, C_j, p, q) = pool(input(N_i, C_j, start_h, start_w), kernel_size)\\r\\n    ```\\r\\n    start_h and start_w are the starting indices for the pooling window in the height and width dimensions.\\r\\n    pool can be any pooling function (max pooling, average pooling) applied over the region defined by the kernel size.\\r\\n    N is a batch size, C denotes a number of channels,\\r\\n    Shape:\\r\\n    - Input: (N, C_{in}, H_{in}, W_{in})\\r\\n    - Output: (N, C_{out}, H_{out}, W_{out})\\r\\n        ```math\\r\\n        H_{output} = {H_{in} + {padding}[0] + {padding}[2] - {kernel_shape}[0]} / {stride}[0] + 1\\r\\n        ```\\r\\n        ```math\\r\\n        W_{output} = {W_{in} + {padding}[1] + {padding}[3] - {kernel_shape}[1]} / {stride}[1] + 1\\r\\n        ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    auto_pad: It can be set to different modes (e.g., SAME, VALID) to automatically calculate the necessary padding based on\\r\\n              the input size,kernel size, and stride.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"auto_pad\", \"type\": \"OptionalAttr<AutoPadModeAttr>\" },\n      { \"name\": \"is_adaptive\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.BatchNorm\",\n    \"summary\": \"BatchNormalization operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs with additional channel dimension)\\r\\n    as described in the paper Batch Normalization: Accelerating Deep Network Training by Reducing\\r\\n    Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = \\\\frac{input - \\\\mathrm{E}[input]}{ \\\\variance + \\\\epsilon} * \\\\gamma + \\\\beta\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    mean(w.): mean of input tensor in dim C;\\r\\n    variance(w.):  quantifies the spread of the input tensor values along the channel dimension (dimension C) for each mini-batch.;\\r\\n    gamma(w.): scalar;\\r\\n    beta(w.): scalar;\\r\\n    The mean and standard-deviation are calculated per-dimension over\\r\\n    the mini-batches and $$\\\\gamma$$ and $$\\\\beta$$ are learnable parameter vectors\\r\\n    of size C (where C is the input channel size).\\r\\n\\r\\n    4.attribute\\r\\n    epsilon;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"variance\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gamma\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"beta\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F64Attr, 1e-05>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.BatchNormBwd\",\n    \"summary\": \"BatchNormalization backward operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs\\r\\n    with additional channel dimension) as described in the paper\\r\\n    Batch Normalization: Accelerating Deep Network Training by Reducing\\r\\n    Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        y = \\\\frac{x - \\\\mathrm{E}[x]}{ \\\\sqrt{\\\\mathrm{Var}[x] + \\\\epsilon}} * \\\\gamma + \\\\beta\\r\\n    ```\\r\\n    The mean and standard-deviation are calculated per-dimension over\\r\\n    the mini-batches and $$\\\\gamma$$ and $$\\\\beta$$ are learnable parameter vectors\\r\\n    of size C (where C is the input channel size).\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grad_out(w.): the gradient of the loss with respect to the output of the layer normalization.;\\r\\n\\r\\n    4.attributes\\r\\n    weight_opt: the optimal scaling for the normalized output.;\\r\\n    saved_mean: the mean of the input tensor calculated.;\\r\\n    saved_invstd: the inverse standard deviation of the input tensor calculated.;\\r\\n    epsilon;\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_opt\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"saved_mean\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"saved_invstd\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_in\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_grad\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_grad\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F64Attr, 1e-05>\" }\n    ]\n  },\n  {\n    \"name\": \"top.BatchNormTrain\",\n    \"summary\": \"BatchNormalization train operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs\\r\\n    with additional channel dimension) as described in the paper\\r\\n    Batch Normalization: Accelerating Deep Network Training by Reducing\\r\\n    Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        y = \\\\frac{x - \\\\mathrm{E}[x]}{ \\\\sqrt{\\\\mathrm{Var}[x] + \\\\epsilon}} * \\\\gamma + \\\\beta\\r\\n    ```\\r\\n    The mean and standard-deviation are calculated per-dimension over\\r\\n    the mini-batches and $$\\\\gamma$$ and $$\\\\beta$$ are learnable parameter vectors\\r\\n    of size C (where C is the input channel size).\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    mean(w.): mean values to subtract from each channel for normalization.;\\r\\n    variance(w.): adjust the predicted boxes during the training process.;\\r\\n\\r\\n    4.attributes\\r\\n    gamma;\\r\\n    beta;\\r\\n    epsilon;\\r\\n    momentum: hyperparameter;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"var\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gamma\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"beta\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"saved_invstd\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F64Attr, 1e-05>\" },\n      { \"name\": \"momentum\", \"type\": \"DefaultValuedAttr<F64Attr, 0.1>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.BinaryConstShift\",\n    \"summary\": \"Binary Const with shift operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The BinaryConstShift operator is a specialized tensor operation that combines binary arithmetic with constant scaling and shifting.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = saturation(input +/-/* scale >> -shift)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    scale: a scaling factor multiplies the input tensor.;\\r\\n    shift: a shift value applied to the quantized data before scaling.;\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    saturation: whether the output should be saturated.\\r\\n                When set true, the output will be clamped to a predefined range to prevent overflow or underflow during the operation.;\\r\\n    round_mode: It determines how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"SI32Attr\" },\n      { \"name\": \"mode\", \"type\": \"BinaryShiftAttr\" },\n      { \"name\": \"shift\", \"type\": \"SI32Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.BinaryShift\",\n    \"summary\": \"Binary with shift operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The BinaryShift operator is designed to perform binary operations on two input tensors with an additional shift operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = saturation(input1 +/-/* input2 >> -shift)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input1(act.): input tensor;\\r\\n    input2(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    shift: a shift value applied to the quantized data before scaling.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    saturation: whether the output should be saturated.\\r\\n                When set to true, the output will be clamped to a predefined range to prevent overflow or underflow during the operation.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input2\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"BinaryShiftAttr\" },\n      { \"name\": \"shift\", \"type\": \"SI32Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.Cast\",\n    \"summary\": \"Cast operation\",\n    \"description\": \"1.Op Introduction\\r\\n    quant::UniformQuantizedType cast to float type; or float type cast to quant::UniformQuantizedType\\r\\n\\r\\n    2.Math formula\\r\\n    Float(output) = Cast (input, dtype=UniformQuantizedType);\\r\\n    UniformQuantizedType(output) = Cast (input, dtype=Float);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"to\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.Ceil\",\n    \"summary\": \"Ceil operator\",\n    \"description\": \"1.Op Introduction\\r\\n    y = ceil(x)\\r\\n    rounds each element of the input tensor up to the nearest integer.\\r\\n\\r\\n     2.Math formula\\r\\n     ```math\\r\\n            output = ceil(input)\\r\\n     ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Clip\",\n    \"summary\": \"Clip operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The operator limits the given input to a certain range.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = min      if input[i] < min;\\r\\n                        input[i] if input[i] >= min && input[i] <= max;\\r\\n                        max      if input[i] > max;\\r\\n\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    min: the minimum value that the elements of the input tensor can take.;\\r\\n    max: the maximum value that the elements of the input tensor can take.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"F64Attr\" },\n      { \"name\": \"max\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Compare\",\n    \"summary\": \"Compare operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the tensor resulted from performing the compare\\r\\n    operation elementwise on the input tensors A and B.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = 1 if lhs[i] mode rhs[i] is true\\r\\n                        0 otherwise\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    lhs(act.): the first input tensor used as the left operand in the element-wise comparison.;\\r\\n    rhs(act.): the second input tensor used as the right operand in the element-wise comparison.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of comparison to be performed between the two input tensors.\\r\\n          mdoe include Equal, Not Equal, Less Than, Less Than or Equal, Greater Than and Greater Than or Equal;\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CompareModeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.CompareConst\",\n    \"summary\": \"CompareConst operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the tensor resulted from performing the compare\\r\\n    operation elementwise on the input tensors A and Const.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = 1 if input[i] mode const_val is true\\r\\n                        0 otherwise\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of comparison to be performed between the two input tensors.\\r\\n          mdoe include Equal, Not Equal, Less Than, Less Than or Equal, Greater Than and Greater Than or Equal;\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    inversed: whether the mask should be inverted.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CompareModeAttr\" },\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"inversed\", \"type\": \"BoolAttr\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Concat\",\n    \"summary\": \"Concat operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Concatenates the given sequence of seq tensors in the given dimension.\\r\\n    All tensors must either have the same shape (except in the concatenating dimension) or be empty.\\r\\n\\r\\n    2.Math formula\\r\\n    output = Concat(input1, input2, axis)\\r\\n           = input1[axis] + input2[axis];\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension along which the input tensors will be concated together.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    round_mode: This determines how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"only_merge\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.ConstantFill\",\n    \"summary\": \"constant fill operator\",\n    \"description\": \"1.Op Introduction\\r\\n    fill the constant value\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = value * ones(shape(input))\\r\\n    ```\\r\\n    where, ones(shape(input)) generates a tensor of the same shape as the input tensor, filled with ones.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    value: the constant value that will fill the output tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Conv\",\n    \"summary\": \"Convolution operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Top_ConvOp is a convolution operator designed to perform convolution operations on input tensors.\\r\\n    The operation transforms an input tensor with shape ((N, C_{\\\\text{in}}, H_{\\\\text{in}}, W_{\\\\text{in}})) into\\r\\n    an output tensor with shape ((N, C_{\\\\text{out}}, H_{\\\\text{out}}, W_{\\\\text{out}})).\\r\\n    The output is computed using learnable weights (filters) and optional biases,\\r\\n    following the mathematical formula for convolution, which incorporates parameters such as kernel size, strides, padding, and dilation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C_{out}, H, H) = \\\\sum_{C_{in}} input(N, C_{in}, H + sH * kH, W + sW * kW) * filter(C_{in}, C_{out}, kH, kW) + bias(C_{out}) + bisa(C_{out})\\r\\n    ```\\r\\n    where, kH and kW are the height and width of the filter (kernel), sH and sW are the vertical and horizontal strides.\\r\\n            N is a batch size, C denotes a number of channels, H is a height of input, and W is width.\\r\\n    Shape:\\r\\n    - Input: (N, C_{in}, H_{in}, W_{in})\\r\\n    - Output: (N, C_{out}, H_{out}, W_{out})\\r\\n        ```math\\r\\n        H_{output} = {H_{in} + {padding}[0] + {padding}[2] - {dilation}[0] x ({kernel_size}[0] - 1) - 1} / {stride}[0] + 1\\r\\n        ```\\r\\n        ```math\\r\\n        W_{output} = {W_{in} + {padding}[1] + {padding}[3] - {dilation}[1] x ({kernel_size}[1] - 1) - 1} / {stride}[1] + 1\\r\\n        ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array. ;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    groups: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    dilation: controls the spacing between the kernel points;\\r\\n    inserts: additional parameters that may be used for specific optimizations or configurations.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    dynweight_reorderd: whether the weights (filters) should be reordered dynamically.;\\r\\n    weight_is_coeff: whether the weights should be treated as coefficients.;\\r\\n    do_winograd: whether to use the Winograd algorithm for convolution,\\r\\n                 which can speed up the computation by reducing the number of multiplications needed.;\\r\\n    auto_pad: It can be set to different modes (e.g., SAME, VALID) to automatically calculate the necessary padding based on\\r\\n              the input size,kernel size, and stride.;\\r\\n    in_int4_scale: This attribute defines the scaling factor for input tensors represented in 4-bit integer format (INT4).;\\r\\n    in_int4_zp: The in_int4_zp attribute specifies the zero-point for the input tensors in INT4 format.;\\r\\n    out_int8_scale: This attribute defines the scaling factor for output tensors represented in 8-bit integer format (INT8).;\\r\\n    out_int8_zp: The out_int8_zp attribute specifies the zero-point for the output tensors in INT8 format.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"inserts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"dynweight_reorderd\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"weight_is_coeff\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"do_winograd\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"auto_pad\", \"type\": \"OptionalAttr<AutoPadModeAttr>\" },\n      { \"name\": \"in_int4_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"in_int4_zp\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"out_int8_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"out_int8_zp\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"weight_bits\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Convbwd\",\n    \"summary\": \"convolution backward\",\n    \"description\": \"1.Op Introduction\\r\\n    calculate grad_input,grad_weight,grad_bias of convolution operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        \\\\text{grad\\\\_input} = \\\\sum_{k=0}^{K-1} \\\\text{grad\\\\_out} \\\\ast \\\\text{kernel}_{k}\\r\\n        where \\\\( K \\\\) is the number of output channels and \\\\( \\\\ast \\\\) denotes the convolution operation.\\r\\n\\r\\n        \\\\text{grad\\\\_weight} = \\\\sum_{n=0}^{N-1} \\\\text{input}_{n} \\\\ast \\\\text{grad\\\\_out}\\r\\n        where \\\\( N \\\\) is the number of input channels.\\r\\n\\r\\n        \\\\text{grad\\\\_bias} = \\\\sum_{i=0}^{M-1} \\\\text{grad\\\\_out}_{i}\\r\\n        where \\\\( M \\\\) is the number of output channels.\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grad_out(w.): the gradient of the loss with respect to the output of the layer normalization.;\\r\\n    kernel(w.): convolution kernel (filter) tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    groups: Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    input_shape: The shape of the input tensor.;\\r\\n    grad_out_shape: The shape of the gradient output tensor.;\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    padding: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    inserts: selectively enabling or disabling the calculation of gradients;\\r\\n    grad_input_enable: whether to compute the gradient for the input tensor.;\\r\\n    grad_weight_enable: whether to compute the gradient for the weight tensor (kernel).;\\r\\n    grad_bias_enable: whether to compute the gradient for the bias term as well.;\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"kernel\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_out_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"inserts\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_input_enable\", \"type\": \"BoolAttr\" },\n      { \"name\": \"grad_weight_enable\", \"type\": \"BoolAttr\" },\n      { \"name\": \"grad_bias_enable\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.ConvBwd_Weight\",\n    \"summary\": \"Convolution Backward operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Gradient of Weight in Convolution Backward.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            \\\\frac{\\\\partial L}{\\\\partial W} = \\\\sum_{n=1}^{N} \\\\sum_{c=1}^{C_{in}} \\\\sum_{h=1}^{H} \\\\sum_{w=1}^{W} \\\\text{input}[n, c, h, w] \\\\cdot \\\\text{grad\\\\_out}[n, :, h', w']\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    gradout_transpose(w.): The transposed gradient of the output tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    groups: Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    input_shape: The shape of the input tensor.;\\r\\n    grad_out_shape: The shape of the gradient output tensor.;\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    padding: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    grad_bias_enable: whether to compute the gradient for the bias term as well.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gradout\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gradout_transpose\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_out_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_bias_enable\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Copy\",\n    \"summary\": \"Copy operator\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"output_stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Correlation\",\n    \"summary\": \"Custom operator correlation\",\n    \"description\": \"Multiply the sliced left_feature and right_feature based on max_disp;\\r\\n  then perform a reduce operation;\\r\\n  and finally concatenate the results.\\r\\n\\r\\n  2.Math formula\\r\\n  for i in range(max_disp):\\r\\n    if i > 0:\\r\\n        output[:, i, :, i:] = (left_feature[:, :, :, i:] * right_feature[:, :, :, :-i]).mean(dim=1)\\r\\n    else:\\r\\n        output[:, i, :, :] = (left_feature * right_feature).mean(dim=1)\\r\\n\\r\\n  3.activation and weight\\r\\n  input(act.): input tensor;\\r\\n\\r\\n  4.attribute\\r\\n  max_disp: The number of slicing iterations, which is also the size of the output dimension C.\\r\\n  num_groups: The number of batch groups.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_disp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"num_groups\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Cos\",\n    \"summary\": \"Cos operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the Cos of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = cos(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Cosh\",\n    \"summary\": \"Cosh operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the Cosh of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = cosh(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Csc\",\n    \"summary\": \"Color space convert for model's inputs\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs csc operation on inputs.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Csc(input, pixel_format, y_align, w_align, channel_align)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    pixel_format: required, pixel format type.;\\r\\n    y_align: width alignment of channel y.;\\r\\n    w_align: width alignment of channel uv.;\\r\\n    channel_align: alignment of channel.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pixel_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"aligned\", \"type\": \"BoolAttr\" },\n      { \"name\": \"y_align\", \"type\": \"I64Attr\" },\n      { \"name\": \"w_align\", \"type\": \"I64Attr\" },\n      { \"name\": \"channel_align\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.CumSum\",\n    \"summary\": \"CumSum operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the cumulative sum of elements of input in the dimension dim.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = \\\\sum{j=0, i}input[j]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    dim(w.): If set to 0, computed across rows, If set to 1, computed across columns.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"dim\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Custom\",\n    \"summary\": \"Custom operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Custom operator\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = CustomFunction(inputs, name, params)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    name: the name of the custom operation to be executed.;\\r\\n    params: A dictionary of parameters.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"params\", \"type\": \"TypedArrayAttrBase<DictionaryAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Deconv\",\n    \"summary\": \"Deconvolution operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform Deconvolution operation.\\r\\n\\r\\n    2.Math formula\\r\\n    The height and width of the output tensor can be calculated using the following formulas:\\r\\n    ```math\\r\\n            H_{out} = H_{in - 1} x stride[0] - 2 x pads[0] + H_k + output_padding[0]\\r\\n            W_{out} = W_{in - 1} x stride[1] - 2 x pads[1] + W_k + output_padding[1]\\r\\n    ```\\r\\n    The output tensor is computed as:\\r\\n    ```math\\r\\n            output(N, C_out, H_out, W_out) = \\\\sum(c_in) {\\\\sum(h_k) {\\\\sum(w_k){input(n, c_in, h_in, w_in) x filter(c_out, c_in, h_k, w_k)}}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array. ;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    group: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    output_padding: The value can be provided as a single integer or a tuple, allowing for different padding values for height and width.;\\r\\n    dynweight_reorderd: whether the weights (filters) should be reordered dynamically.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"output_padding\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"dynweight_reorderd\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.DeformConv2D\",\n    \"summary\": \"Deformable Convolution Operator\",\n    \"description\": \"1.Op Introduction\\r\\n    In the simplest case, the output value of the layer with input size\\r\\n    $$(N, C_{\\\\text{in}}, H, W)$$ and output $$(N, C_{\\\\text{out}}, H_{\\\\text{out}}, W_{\\\\text{out}})$$\\r\\n    can be precisely described as:\\r\\n\\r\\n    2.Math formula\\r\\n        - Input: $$(N, C_{in}, H_{in}, W_{in})$$\\r\\n        - Output: $$(N, C_{out}, H_{out}, W_{out})$$ where\\r\\n            weight (Tensor): the learnable weights of the module of shape\\r\\n            $$(\\\\text{out\\\\_channels}, \\\\frac{\\\\text{in\\\\_channels}}{\\\\text{groups}},\\r\\n            \\\\text{kernel\\\\_size[0]}, \\\\text{kernel\\\\_size[1]})$$\\r\\n\\r\\n            offset (Tensor): the learnable offsets of the module of shape\\r\\n            $$(\\\\text{N}, \\\\times{\\\\text{2}}{\\\\text{offset\\\\_groups}{\\\\text{kernel\\\\_size[0]}}{\\\\text{kernel\\\\_size[1]}}},\\r\\n            \\\\text{H_{\\\\text{out}}}, \\\\text{W_{\\\\text{out}}})$$\\r\\n\\r\\n            mask (Tensor): the learnable masks of the module of shape\\r\\n            $$(\\\\text{N}, \\\\times{\\\\text{offset\\\\_groups}{\\\\text{kernel\\\\_size[0]}}{\\\\text{kernel\\\\_size[1]}}},\\r\\n            \\\\text{H_{\\\\text{out}}}, \\\\text{W_{\\\\text{out}}})$$\\r\\n\\r\\n            bias (Tensor optional): the learnable bias of the module of shape (out_channels).\\r\\n\\r\\n          ```math\\r\\n              H_{out} = \\\\left\\\\lfloor\\\\frac{H_{in}  + \\\\text{padding}[0] + \\\\text{padding}[2] - \\\\text{dilation}[0]\\r\\n                        \\\\times (\\\\text{kernel\\\\_size}[0] - 1) - 1}{\\\\text{stride}[0]} + 1\\\\right\\\\rfloor\\r\\n          ```\\r\\n          ```math\\r\\n              W_{out} = \\\\left\\\\lfloor\\\\frac{W_{in}  + \\\\text{padding}[1] + \\\\text{padding}[3] - \\\\text{dilation}[1]\\r\\n                        \\\\times (\\\\text{kernel\\\\_size}[1] - 1) - 1}{\\\\text{stride}[1]} + 1\\\\right\\\\rfloor\\r\\n          ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    offset(w.): the learnable offsets of the module of shape.;\\r\\n    mask(w.): the learnable masks of the module of shape.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    group: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    deform_group: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    use_mask: whether use mask for input tensor.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensor\" },\n      { \"name\": \"offset\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"deform_group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"use_mask\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.DepackRaw\",\n    \"summary\": \"Postprocess for raw image.\",\n    \"description\": \"1.Op Introduction\\r\\n    postprocess raw image from 4 channels to mixed pixel pattern,\\r\\n    remove padding first if padded before,\\r\\n    then for each channel depack to 2 * 2 image block.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Depack(RemovePadding(input, padding_h, padding_w), channel_order)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    padding_h: The height of the padding.;\\r\\n    padding_w: The width of the padding.;\\r\\n    white_level: The maximum intensity value for white in the image data.;\\r\\n    black_level: The minimum intensity value for black in the image data.;\\r\\n    channel_order: The order of color channels in the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"white_level\", \"type\": \"F64Attr\" },\n      { \"name\": \"black_level\", \"type\": \"F64Attr\" },\n      { \"name\": \"channel_order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Depth2Space\",\n    \"summary\": \"Depth2Space operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Refer to `https://github.com/onnx/onnx/blob/main/docs/Operators.md#depthtospace`\\r\\n    [n, c, h, w] => [n, c / (block_h * block_w), h * block_h, w * block_w];\\r\\n    if inversed, [n, c, h, w] => [n, c * block_h * block_w, h / block_h, w / block_w];\\r\\n    if DCR(depth-column-row), channel ordered by block_h * block_w * c;\\r\\n    else CRD(column-row-depth), channel ordered by c * block_h * block_w;\\r\\n    The format of input or output is NCHW or NHWC.\\r\\n\\r\\n    2.Math formula\\r\\n\\r\\n    (1)Standard Transformation:\\r\\n    Given an input tensor of shape ( (N, C, H, W) ):\\r\\n    The output tensor after applying the Depth2Space operation can be calculated as:\\r\\n    ```math\\r\\n        {output}(N_i, C_j', H_k, W_l) = input(N_i, C_j, k / block_h, l / block_w)\\r\\n    ```\\r\\n    where k / block_h and l / block_w are rounded down.\\r\\n\\r\\n    (2)Inverse Transformation:\\r\\n    Given an input tensor of shape ( (N, C, H, W) ):\\r\\n    The output tensor after applying the Depth2Space operation can be calculated as:\\r\\n    ```math\\r\\n        {output}(N_i, C_j, H_k, W_l) = input(N_i, C_j', (k x block_h + j / (C / (block_h x block_w))), (l x block_w + j % (C / (block_h x block_w))))\\r\\n    ```\\r\\n    where C / (block_h x block_w) is rounded down.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    block_h: The height of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    block_w: The width of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    is_CRD: whether the channel ordering is in Column-Row-Depth format.;\\r\\n    is_inversed: whether the channel ordering is in Column-Row-Depth format.;\\r\\n    in_is_NCHW: whether the input tensor is in NCHW format.;\\r\\n    out_is_NCHW: whether the output tensor should be in NCHW format.;\\r\\n    swap_cr: swaps the height and width dimensions in the output tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"block_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"is_CRD\", \"type\": \"BoolAttr\" },\n      { \"name\": \"is_inversed\", \"type\": \"BoolAttr\" },\n      { \"name\": \"in_is_NCHW\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"out_is_NCHW\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"swap_cr\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.DequantInt\",\n    \"summary\": \"dequant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Dequant 8 bit data to 32/16 bit data.\\r\\n\\r\\n    2.Math formula\\r\\n    32/16bit(output) = DequantIntOp((8bit(input), shift) x multiplier) ≪ lshift;\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    shift: a shift value applied to the quantized data before scaling.;\\r\\n    lshift: a left shift operation applied to the dequantized data after scaling.;\\r\\n    quant_mode: the mode or method used for quantization during the requantization operation.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiplier\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"shift\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"lshift\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DequantModeAttr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.DequantizeLinear\",\n    \"summary\": \"Linear dequantize operation\",\n    \"description\": \"1.Op Introduction\\r\\n    DequantizeLinear(x) := (x - x_zero_point) * x_scale\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = (input - x_zero_point) * x_scale\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    x_scale: convert the quantized values back original;\\r\\n    x_zero_point: adjust the zero point of quantized values, represents4 that corresponds to the original value of zero.;\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"x_scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"x_zero_point\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.DetectionOutput\",\n    \"summary\": \"DetectionOutput operation\",\n    \"description\": \"1.Op Introduction\\r\\n    takes the predicted bounding boxes, class scores, and other relevant information to produce the final detection results.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Raw Detection Output\\r\\n            raw_output = {(b_i, c_i) | i = 1, 2,...,N}\\r\\n            b_i is the bounding box coordinates, c_i is the i-th confidence score.\\r\\n        2.Apply Confidence threshold\\r\\n            filtered_output = {(b_i, c_i) | c_i >= confidence_threshold}\\r\\n        3.Non-Maximum Suppression(NMS)\\r\\n            nms_output = NMS(filtered_output, nms_threshold)\\r\\n        4.Top K detections\\r\\n            output = top_k(nms_output, top_k)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    num_classes: total number of classes, including the background class.;\\r\\n    background_label_id: background class, differentiate between detected objects and the background.;\\r\\n    nms_threshold: The threshold used for Non-Maximum Suppression (NMS).;\\r\\n    top_k: The maximum number of predictions to be considered for each image.;\\r\\n    code_type: the encoding type for the bounding box coordinates.;\\r\\n    keep_top_k: The number of top scoring detections to keep after applying NMS.;\\r\\n    confidence_threshold: The minimum confidence score required for a detection to be considered valid.;\\r\\n    share_location: whether the bounding box locations are shared across different classes.;\\r\\n    variance_encoded_in_target: whether the variance for bounding box predictions is encoded in the target.;\\r\\n    eta: adjusts the confidence scores during NMS.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_classes\", \"type\": \"I64Attr\" },\n      { \"name\": \"background_label_id\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"top_k\", \"type\": \"I64Attr\" },\n      { \"name\": \"code_type\", \"type\": \"DetectionOutputCodeTypeAttr\" },\n      { \"name\": \"keep_top_k\", \"type\": \"I64Attr\" },\n      { \"name\": \"confidence_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"share_location\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"variance_encoded_in_target\", \"type\": \"DefaultValuedAttr<F64Attr, 0>\" },\n      { \"name\": \"eta\", \"type\": \"DefaultValuedAttr<F64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Div\",\n    \"summary\": \"Div operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs element-wise binary division.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = \\\\frac{inputs[i]}{divisor}\\r\\n            if is_reverse == True;\\r\\n            output[i] = \\\\frac{divisor}{inputs[i]}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.DivConst\",\n    \"summary\": \"Div Const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The DivConst operator is designed to perform element-wise division of an input tensor by a constant value.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input/const_val or const_val/input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.DtypeCast\",\n    \"summary\": \"Cast F32 to F16\",\n    \"description\": \"1.Op Introduction\\r\\n    Cast F32 to F16\\r\\n\\r\\n    2.Math formula\\r\\n    FLOAT16(output) = DtypeCastOp (FLOAT32(input));\\r\\n\\r\\n    3.activation\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Einsum\",\n    \"summary\": \"Einsum operator\",\n    \"description\": \"1.Op Introduction\\r\\n    # https://pytorch.org/docs/1.13/generated/torch.einsum.html?highlight=einsum#torch.einsum\\r\\n    The Einsum operator implements Einstein summation notation, which provides a concise way to specify tensor operations.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        \\\\mathrm{Output}=\\\\sum_{i\\\\in I}A_iB_j\\\\ldots\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    mode: determines how the input tensors will be combined based on the specified subscripts. ;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"EinsumModeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Elu\",\n    \"summary\": \"Elu operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Elu takes input data (Tensor<T>) and an argument alpha,\\r\\n    and produces one output data (Tensor<T>)\\r\\n    where the function f(x) = alpha * (e^x - 1) for x <= 0, f(x) = x for x > 0,\\r\\n    is applied to the data tensor elementwise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = alpha * (e ^ input - 1) if input[i] < 0 && input[i] == 0\\r\\n                        input[i]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    alpha: scalar.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.EmbDenseBwd\",\n    \"summary\": \"EmbDenseBwd operation for train\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = grad_output[indices]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    indices(w.): the indices of the input tokens or items.;\\r\\n\\r\\n    4.attributes\\r\\n    num_weights: the total number of embedding weights.;\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_weights\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Erf\",\n    \"summary\": \"Erf operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Computes the error function of the given input tensor element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Erf(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Exp\",\n    \"summary\": \"Exp operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the exponent of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = exp(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Expand\",\n    \"summary\": \"Expand operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Broadcast the input tensor following the given shape and the broadcast rule.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i1, i2, i3,...in] = input[j1, j2, j3,...jn]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    shape: An array of the target shape to which the input tensor will be expanded.;\\r\\n    shapeT: An optional tensor that can be used to specify the shape dynamically.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shapeT\", \"type\": \"Optional<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"top.FAttention\",\n    \"summary\": \"Flash Attention operator\",\n    \"description\": \"Performs a two dimensional matrix multiplication. This allows both inputs to\\r\\n    be activations, rather than reserving weights as an attribute in the\\r\\n    FULLY_CONNECTED operator.\",\n    \"operands\": [\n      { \"name\": \"queries\", \"type\": \"AnyTensor\" },\n      { \"name\": \"keys\", \"type\": \"AnyTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"batch\", \"type\": \"I64Attr\" },\n      { \"name\": \"q_head\", \"type\": \"I64Attr\" },\n      { \"name\": \"kv_head\", \"type\": \"I64Attr\" },\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"mq\", \"type\": \"I64Attr\" },\n      { \"name\": \"mk\", \"type\": \"I64Attr\" },\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Flatten\",\n    \"summary\": \"Flatten operation\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch aten::flatten or onnx, the flatten operation collapses the specified dimensions of the tensor into a single dimension,\\r\\n    effectively reducing the number of dimensions of the tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = FlattenOp(input, start_dim, end_dim)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    start_dim: the first dimension to flatten.;\\r\\n    end_dim: the last dimension to flatten.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"end_dim\", \"type\": \"DefaultValuedAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Floor\",\n    \"summary\": \"Floor operation\",\n    \"description\": \"1.Op Introduction\\r\\n    the Floor function rounds down each element of the input tensor to the nearest integer less than or equal to that element.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = floor(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.FrcnDetection\",\n    \"summary\": \"Faster rcnn detection operator\",\n    \"description\": \"1.Op Introduction\\r\\n    outputs the detected classes and their corresponding bounding boxes,\\r\\n    filtering results based on specified thresholds.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = FrcnDetection(inputs, class_num, obj_threshold, nms_threshold, keep_topk)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    class_num: detection class num.;\\r\\n    obj_threshold: object threshold.;\\r\\n    nms_threshold: nms threshold.;\\r\\n    keep_topk: keep top k.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"class_num\", \"type\": \"I64Attr\" },\n      { \"name\": \"obj_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"keep_topk\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Gather\",\n    \"summary\": \"Gather operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform Gather operation on the given axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input[indices]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    indices(w.): the indices of the elements to be gathered from the input tensor. ;\\r\\n\\r\\n    4.attributes\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    axis: the dimension of the input tensor.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"is_lora\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.GatherElements\",\n    \"summary\": \"GatherElements operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform GatherElements operation on the given axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i_1, i_2, i_3,...i_k] = input[i_1, i_2, i_3,..., indices[i_k]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    indices(w.): the indices of the elements to be gathered from the input tensor. ;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<I64Attr, 2>\" }\n    ]\n  },\n  {\n    \"name\": \"top.GatherND\",\n    \"summary\": \"GatherND operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This operator is the inverse of ScatterND.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output_i = input[indices_i]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    indices(w.): which elements to gather from the input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    indice_dims: the number of dimensions in the indices tensor.;\\r\\n    batch_dims: the number of batch dimensions in the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indice_dims\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.GELU\",\n    \"summary\": \"GELU operator,  0.5x * (1.0 + tf.erf(x / tf.sqrt(2.0)))\",\n    \"description\": \"1.Op Introduction\\r\\n    An activation function based on Gaussian error function.;\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        Y = 0.5*input * (1.0 + tf.erf(input / tf.sqrt(2.0)))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    approx_mode: include three mode.\\r\\n                  normal: This mode uses the exact mathematical form of the GELU function;\\r\\n                  tanh: This mode uses tanh to speed up computation;\\r\\n                  sigm: This mode uses sigmoid to speed up computation;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"approx_mode\", \"type\": \"DefaultValuedAttr<GELUModeAttr, \\\"normal\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.GridSampler\",\n    \"summary\": \"GridSampler operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Given an input and a flow-field grid, computes the output\\r\\n    using input values and pixel locations from grid.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[N, C, H', W'] = input[C, grid[N, H', W', 1], grid[N, H', W', 0]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grid(w.): The flow-field grid tensor that defines the pixel locations for sampling.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    padding_mode: padding mode for outside grid values, Int attribute [0, 1, 2],\\r\\n                                representing 'zero' | 'boundary' | 'reflection't.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"grid\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.GroupNorm\",\n    \"summary\": \"GroupNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    group normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            mean_g = 1 / ((C / num_groups) * H * W) \\\\sum{i=1, C/num_groups} \\\\sum{j=1, H} \\\\sum{k=1, W} input_{n,c,j,k}\\r\\n            var_g = 1 / ((C / num_groups) * H * W) \\\\sum{i=1, C/num_groups} \\\\sum{j=1, H} \\\\sum{k=1, W} (input_{n,c,j,k} - mean_g) ^ 2\\r\\n            output_{n,c,j,k} = weight * (input_{n,c,j,k} - mean_g) / sqrt(var_g + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    num_groups: the number of groups to divide the input channels into for normalization.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.GroupNormTrain\",\n    \"summary\": \"GroupNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    group normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\frac{input - mean}{\\\\sqrt{\\\\sigma^2 + eps}} \\\\cdot weight + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    num_groups: number of groups to divide the channels into for normalization.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rstd\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.GRU\",\n    \"summary\": \"GRU operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform RNN GRU operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        update gate(z_t):\\r\\n            z_t = Sigma(W_z · x_t + U_z ·h_(t-1) + b_z)\\r\\n        reset gate(r_t):\\r\\n            r_t = Sigma(W_r · x_t + U_r ·h_(t-1) + b_r)\\r\\n        Candidate Activation(h_t):\\r\\n            h_t = tanh(W_h · x_t + r_t \\\\odot (U_h · h_(t-1)) + b_h)\\r\\n        final output:\\r\\n            output = (1 - z_t) \\\\odot h_(t-1) + z_t \\\\odot h_t\\r\\n    ```\\r\\n    where, x_t is the input at time step (t), h_(t-1) is the hidden state from the previous time step.\\r\\n           W_z, W_r, W_h are the weight matrices for the input.\\r\\n           U_z, U_r, U_h are the weight matrices for the hidden state.\\r\\n           b_z, b_r, b_h are the bias vectors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    recurrence(w.): the previous hidden state influences the current hidden state.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    initial_h(w.): the initial hidden state, which can be provided to start the GRU computation.;\\r\\n\\r\\n    4.attributes\\r\\n    hidden_size: the number of units in the GRU cell,;\\r\\n    bidirectional: whether the GRU should be bidirectional;\\r\\n    linear_before_reset: whether to apply a linear transformation to the input before applying the reset gate.;\\r\\n    batch_first: the input and output tensors are provided in the shape (batch_size, seq_length, input_size).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensor\" },\n      { \"name\": \"recurrence\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hidden_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"bidirectional\", \"type\": \"BoolAttr\" },\n      { \"name\": \"linear_before_reset\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"batch_first\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.HardSigmoid\",\n    \"summary\": \"HardSigmoid operation\",\n    \"description\": \"1.Op Introduction\\r\\n    a piecewise linear function to the input tensor element-wise.\\r\\n    hardsigmoid(x; alpha, beta) := min(max(alpha*x + beta, 0), 1).\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = min(max(alpha * input[i] + beta, 0), 1)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    alpha: scalar;\\r\\n    beta: scalar;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"F64Attr\" },\n      { \"name\": \"beta\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.HardSwish\",\n    \"summary\": \"HardSwish operation\",\n    \"description\": \"1.Op Introduction\\r\\n    hardswish(x) := x * hardsigmoid(x; 1/6, 0.5)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[i] * min(max(1/6 * input[i] + 0.5, 0), 1)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.If\",\n    \"summary\": \"if operation\",\n    \"description\": \"1.Op Introduction\\r\\n    If conditional\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = then_branch if cond is true\\r\\n                     else_branch if cond is false\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    cond(act.): which branch of execution to follow.;\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_branch\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_branch\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.IndexPut\",\n    \"summary\": \"Index_put_ operation\",\n    \"description\": \"1.Op Introduction\\r\\n    update specific elements of an input tensor at given indices with new values.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        if accumulate\\r\\n            input[indices] += values\\r\\n        else\\r\\n            input[indices] = values\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    indices(w.): the indices of the elements in the input tensor that should be updated.;\\r\\n    values(w.): the new values that will replace the existing values in the input tensor at the specified indices.;\\r\\n\\r\\n    4.attributes\\r\\n    accumulate: whether the operation should accumulate values at the specified indices or replace them.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"accumulate\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Input\",\n    \"summary\": \"Input operator\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape_tensor\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_preprocess\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"pixel_format\", \"type\": \"OptionalAttr<PixelFormatAttr>\" },\n      { \"name\": \"channel_format\", \"type\": \"OptionalAttr<ChannelFormatAttr>\" },\n      { \"name\": \"resize_dims\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"keep_aspect_ratio\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"keep_ratio_mode\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"pad_value\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"pad_type\", \"type\": \"OptionalAttr<PadModeAttr>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"mean\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"customization_format\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"aligned\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"yuv_type\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Insert\",\n    \"summary\": \"Insert the rhs tensor into input tensor at the specified axis and position.\",\n    \"description\": \"1.Op Introduction\\r\\n    insert the rhs tensor into input tensor at the specified axis and position.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Insert(input, rhs, axis, offset)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    rhs(w.): the tensor to be inserted;\\r\\n    axis: the axis along which to insert the rhs tensor.\\r\\n    offset: the position at which the rhs tensor is inserted.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"offset\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.InstanceNorm\",\n    \"summary\": \"Instance Norm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    instance normalization.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output[i] = weight * (input[i] - mean) / sprt(var + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Interp\",\n    \"summary\": \"Interp operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform linear upsample on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            H' = H x scale_h\\r\\n            W' = W x scale_w\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    target_shape(w.): the desired shape of the output tensor after interpolation.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    coord_mode: whether the coordinates are normalized (ranging from 0 to 1) or absolute (based on pixel indices).;\\r\\n    scale_h: the scaling factor for the height (number of rows) of the input tensor.;\\r\\n    scale_w: the scaling factor for the width (number of columns) of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"target_shape\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"InterpModeAttr\" },\n      { \"name\": \"coord_mode\", \"type\": \"InterpCoordModeAttr\" },\n      { \"name\": \"scale_h\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"scale_w\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.LayerNorm\",\n    \"summary\": \"LayerNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Normalization\\r\\n            mean = 1 / H \\\\sum{j=1, H} input[j]\\r\\n            var = 1 / H \\\\sum{j=1, H} (input[j] - mean) ^ 2\\r\\n        2.Layer Normalized Output\\r\\n            output[i] = weight * (input[i] - mean) / sprt(var + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    normalized_shape: the shape of the input tensor that will be normalized.;\\r\\n    axis: the dimension of the input tensor.;\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.LayerNormBwd\",\n    \"summary\": \"LayerNorm operation for train\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.gradient input\\r\\n            grad_input = 1 / N(weight / sqrt(variance + eps) 1 / N \\\\sum{i=1, N}grad_out)\\r\\n                            - (input - mean) / N * \\\\sum(i=1, N)weight * grad_out / sqrt(variance + eps)\\r\\n        2.gradient weight\\r\\n            grad_weight = \\\\sum(i=1, N)grad_out * (input - mean) / sqrt(variance + eps)\\r\\n        3.gradient bias\\r\\n            grad_bias = \\\\sum(i=1, N)grad_out\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grad_out(w.): the gradient of the loss with respect to the output of the layer normalization.;\\r\\n    mean(w.): mean values to subtract from each channel for normalization.;\\r\\n    variance(w.): adjust the predicted boxes during the training process.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    normalized_shape:  the shape of the input tensor dimensions.;\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"variance\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.LayerNormTrain\",\n    \"summary\": \"LayerNorm operation for train\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization in train.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Normalization\\r\\n            mean = 1 / H \\\\sum{j=1, H} input[j]\\r\\n            var = 1 / H \\\\sum{j=1, H} (input[j] - mean) ^ 2\\r\\n        2.Layer Normalized Output\\r\\n            output[i] = weight * (input[i] - mean) / sprt(var + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    normalized_shape: the shape of the input tensor dimensions.;\\r\\n    axis: the dimension of the input tensor.;\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"variance\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.LeakyRelu\",\n    \"summary\": \"LeakyRelu operation\",\n    \"description\": \"1.Op Introduction\\r\\n    LeakyRelu takes input data (Tensor<T>) and an argument alpha,\\r\\n    and produces one output data (Tensor<T>)\\r\\n    where the function f(x) = alpha * x for x < 0, f(x) = x for x >= 0,\\r\\n    is applied to the data tensor elementwise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = alpha * input, if input < 0\\r\\n            output = input, if input >= 0\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    alpha: a scalar factor.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"F64Attr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.List\",\n    \"summary\": \"List operator\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch prim::ListConstruct, y = [a, b]\\r\\n    output shape is [1]\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = [input1, input2, ..., inputN]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Log\",\n    \"summary\": \"Log operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the natural log of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ln(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.LogB\",\n    \"summary\": \"LogB operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the log of the given input tensor to the base B, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ln(input) / ln(B)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"base\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.LogicalAnd\",\n    \"summary\": \"logical and operation\",\n    \"description\": \"1.Op Introduction\\r\\n    logical and operation between two variables\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input1 and input2\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Loop\",\n    \"summary\": \"Loop operation\",\n    \"description\": \"Generic Looping construct. This loop has multiple termination conditions:\\r\\n\\r\\n  1. Trip count. Iteration count specified at runtime. Set by\\r\\n     specifying the input M. Optional. Set to empty string to omit.\\r\\n     Note that a static trip count (specified at graph construction time) can be\\r\\n     specified by passing in a constant node for input M.\\r\\n  2. Loop termination condition. This is an input to the op that determines\\r\\n     whether to run the first iteration and also a loop-carried dependency for\\r\\n     the body graph. The body graph must yield a value for the condition variable,\\r\\n     whether this input is provided or not.\\r\\n\\r\\n  This table summarizes the operating modes of this operator with equivalent\\r\\n  C-style code:\\r\\n\\r\\n      Operator inputs defined as (max_trip_count, condition_var).\\r\\n\\r\\n      input (\\\\\\\"\\\\\\\", \\\\\\\"\\\\\\\"):\\r\\n          for (int i=0; ; ++i) {\\r\\n            cond = ... // Note this value is ignored, but is required in the body\\r\\n          }\\r\\n\\r\\n      input (\\\\\\\"\\\\\\\", cond) // Note this is analogous to a while loop\\r\\n          bool cond = ...;\\r\\n          for (int i=0; cond; ++i) {\\r\\n            cond = ...;\\r\\n          }\\r\\n\\r\\n      input (\\\\\\\"\\\\\\\", 1) // Note this is analogous to a do-while loop\\r\\n          bool cond = true\\r\\n          for (int i=0; cond; ++i) {\\r\\n            cond = ...;\\r\\n          }\\r\\n\\r\\n      input (trip_count, \\\\\\\"\\\\\\\") // Note this is analogous to a for loop\\r\\n          int trip_count = ...\\r\\n          for (int i=0; i < trip_count; ++i) {\\r\\n            cond = ...; // ignored\\r\\n          }\\r\\n\\r\\n      input (trip_count, cond)\\r\\n          int trip_count = ...;\\r\\n          bool cond = ...;\\r\\n          for (int i=0; i < trip_count && cond; ++i) {\\r\\n            cond = ...;\\r\\n          }\\r\\n\\r\\n\\r\\n  *Sample usage - cond as well as trip count*\\r\\n\\r\\n      graph predict-net {\\r\\n        %a = Constant[value = <Scalar Tensor [3]>]()\\r\\n        %b = Constant[value = <Scalar Tensor [6]>]()\\r\\n        %keepgoing = Constant[value = <Scalar Tensor [1]>]()\\r\\n        %max_trip_count = Constant[value = <Scalar Tensor [10]>]()\\r\\n        %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)\\r\\n        return\\r\\n      }\\r\\n\\r\\n      graph body-net (\\r\\n        %i[INT32, scalar]           // iteration number\\r\\n        %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used\\r\\n        %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b\\r\\n      ) {\\r\\n        %my_local = Add(%a, %b_in)\\r\\n        %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b\\r\\n        %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition\\r\\n        %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated\\r\\n        return %keepgoing_out, %b_out, %user_defined_val\\r\\n      }\\r\\n\\r\\n  *Sample equivalent C code*\\r\\n\\r\\n      {\\r\\n        /* User-defined code (enclosing scope) */\\r\\n        int a = 3, b = 6;\\r\\n        bool keepgoing = true; // Analogous to input cond\\r\\n        /* End user-defined code */\\r\\n\\r\\n        /* Implicitly-defined code */\\r\\n        const int max_trip_count = 10; // Analogous to input M\\r\\n        int user_defined_vals[]; // Imagine this is resizable\\r\\n        /* End implicitly-defined code */\\r\\n        /* initialize loop-carried variables and scan-output variables */\\r\\n        bool keepgoing_out = keepgoing\\r\\n        int b_out = b\\r\\n\\r\\n        for (int i=0; i < max_trip_count && keepgoing_out; ++i) {\\r\\n          /* Implicitly-defined code: bind actual parameter values\\r\\n             to formal parameter variables of loop-body */\\r\\n          bool keepgoing_in = keepgoing_out;\\r\\n          bool b_in = b_out;\\r\\n\\r\\n          /* User-defined code (loop body) */\\r\\n          int my_local = a + b_in; // Reading value \\\\\\\"a\\\\\\\" from the enclosing scope is fine\\r\\n          b_out = a - b_in;\\r\\n          keepgoing_out = my_local > b_out;\\r\\n          user_defined_val = b_in + b_in; // b_in and b_out are different variables\\r\\n          /* End user-defined code */\\r\\n\\r\\n          /* Implicitly defined-code */\\r\\n          user_defined_vals[i] = user_defined_val // accumulate scan-output values\\r\\n        }\\r\\n        // int t = my_local; // Can't do this. my_local is not accessible here.\\r\\n\\r\\n        // The values below are bound to the output variables of the loop and therefore accessible\\r\\n        // b_out; user_defined_vals; keepgoing_out;\\r\\n      }\\r\\n\\r\\n  There are several things of note in this code snippet:\\r\\n\\r\\n  1. Values from the enclosing scope (i.e. variable \\\\\\\"a\\\\\\\" here) are in scope and can\\r\\n     be referenced in the inputs of the loop.\\r\\n  2. Any values computed in the loop body that needs to be used in a subsequent\\r\\n     iteration or after the loop are modelled using a pair of variables in the loop-body,\\r\\n     consisting of an input variable (eg., b_in) and an output variable (eg., b_out).\\r\\n     These are referred to as loop-carried dependences. The loop operation node\\r\\n     supplies the input value of the input variable for the first iteration, and\\r\\n     returns the output value of the output variable produced by the final\\r\\n     iteration.\\r\\n  3. Scan_output variables are used to implicitly concatenate values computed across\\r\\n     all the iterations. In the above example, the value of user_defined_val computed\\r\\n     over all iterations are concatenated and returned as the value of user_defined_vals\\r\\n     after the loop.\\r\\n  4. Values created in the body cannot be accessed in the enclosing scope,\\r\\n     except using the mechanism described above.\\r\\n\\r\\n  Note that the semantics of this op support \\\\\\\"diagonal\\\\\\\" or \\\\\\\"wavefront\\\\\\\" execution.\\r\\n  (See Step 3 here for an example:\\r\\n  https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/).\\r\\n  Frontends should emit multi-layer RNNs as a series of While operators (with\\r\\n  time being the inner looping dimension), with each successive layer consuming\\r\\n  the scan_outputs from the previous layer, possibly going through several\\r\\n  point-wise operators (e.g. dropout, residual connections, linear layer).\\r\\n\\r\\n  The input/output of subgraph (produced by loop node) matching is based on order instead of name. The implementation will figure out the names based on this order.\",\n    \"operands\": [\n      { \"name\": \"M\", \"type\": \"AnyTypeOf<[AnyTensor, NoneType]>\" },\n      { \"name\": \"cond\", \"type\": \"AnyTypeOf<[AnyTensor, NoneType]>\" },\n      { \"name\": \"v_initial\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, NoneType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"v_final_and_scan_outputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, NoneType ]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.LRN\",\n    \"summary\": \"Local Response Normalization\",\n    \"description\": \"1.Op Introduction\\r\\n    It normalizes over local input regions. The local region is defined across the channels.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i, j, k] = \\\\frac{input[i, j, k]}{(bias + \\\\alpha \\\\sum_{c=\\\\max(0,k-\\\\text{size})}^{\\\\min(N-1,k+\\\\text{size})} input[i, j, c]^2)^{\\\\beta}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    size: how many neighboring channels are considered during the normalization process.;\\r\\n    alpha: a scaling factor;\\r\\n    beta: a scaling factor;\\r\\n    bias: A floating-point value added to the normalization denominator to prevent division by zero.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I64Attr\" },\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0001>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F64Attr, 0.75>\" },\n      { \"name\": \"bias\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.LSTM\",\n    \"summary\": \"LSTM operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform RNN LSTM operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        forget gate(f_t):\\r\\n            f_t = Sigma(W_f · x_t + U_f · h_(t-1) + b_f)\\r\\n        input gate(i_t):\\r\\n            i_t = Sigma(W_i · x_t + U_i · h_(t-1) + b_i)\\r\\n        Candidate cell state(C_t):\\r\\n            C_t = tanh(W_C · x_t + U_C · h_(t-1) + b_C)\\r\\n        cell state update(c_t):\\r\\n            c_t = f_t \\\\odot c_(t-1) + i_t \\\\odot C_t\\r\\n        output gate(o_t):\\r\\n            o_t = Sigma(W_o · x_t + U_o · h_(t-1) + b_o)\\r\\n        hidden state output(h_t):\\r\\n            h_t = o_t \\\\odot tanh(c_t)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    recurrence(w.): the previous hidden state influences the current hidden state.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    initial_h(w.): the initial hidden state, which can be provided to start the LSTM computation.;\\r\\n    initial_c(w.): the initial cell state, which can be provided to start the LSTM computation.;\\r\\n    cont(w.): control weights or additional context that may be provided to influence the LSTM's behavior.;\\r\\n\\r\\n    4.attributes\\r\\n    hidden_size: the number of units in the LSTM cell, ;\\r\\n    bidirectional: A boolean indicating whether the LSTM should be bidirectional;\\r\\n    batch_first: the input and output tensors are provided in the shape (batch_size, seq_length, input_size).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensor\" },\n      { \"name\": \"recurrence\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"initial_c\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"cont\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"Y_c\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hidden_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"bidirectional\", \"type\": \"BoolAttr\" },\n      { \"name\": \"batch_first\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Lut\",\n    \"summary\": \"Lut operator\",\n    \"description\": \"1.Op Introduction\\r\\n    lookup table in index [0-255], y[i] = table(x[i])\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = table(input[i])\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    table(w.): map input values to corresponding output values.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaskedFill\",\n    \"summary\": \"MaskedFill operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Return elements, either from X or Const, depending on condition.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n                     brn                if inversed and cond=0\\r\\n            output = brn + const_val    if inversed and cond!=0\\r\\n                     brn + const_val    if !inversed and cond!=0\\r\\n                     brn                if !inversed and cond=0\\r\\n    ```\\r\\n        If inversed is true, the operation fills the elements of brn where cond is zero with const_val, while leaving other elements unchanged.\\r\\n        If inversed is false, the operation fills the elements of brn where cond is non-zero with const_val, while leaving other elements unchanged.\\r\\n\\r\\n    3.activation and weight\\r\\n    cond(act.): a tensor that serves as the condition for selecting elements from the true branch (tbrn) or the false branch (fbrn).;\\r\\n    brn(w.): the input tensor from which elements will be selected based on the condition provided by the cond tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    inversed: whether the mask should be inverted.;\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"AnyTensor\" },\n      { \"name\": \"brn\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inversed\", \"type\": \"BoolAttr\" },\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaskRCNN_BboxPooler\",\n    \"summary\": \"BBox_Pooler gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    MaskRCNN_BBox_Pooler, the 1st ROIAlign in MaskRCNN.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ROIAlign(feature map, rois_multi_batch)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    ptr_feat0(act.): Pointer to the feature map at level 0.;\\r\\n    ptr_feat1(act.): Pointer to the feature map at level 1.;\\r\\n    ptr_feat2(act.): Pointer to the feature map at level 2.;\\r\\n    ptr_feat3(act.): Pointer to the feature map at level 3.;\\r\\n    rois_multi_batch(w.): ROIs (Regions of Interest) for multiple batches.;\\r\\n\\r\\n    4.attributes\\r\\n    ROI_NUM_LEVELS: The number of levels in the ROI feature pyramid.;\\r\\n    ROI_H: The height of the pooled ROI features.;\\r\\n    ROI_W: The width of the pooled ROI features.;\\r\\n    CHANNEL_ROI: The number of channels in the pooled ROI features.;\\r\\n    ROI_SLICE: The number of slices or segments;\\r\\n    ROI_PH: The height of the ROI in the feature map.;\\r\\n    ROI_PW: The width of the ROI in the feature map.;\\r\\n    ROI_LEN: The length of the ROIs being processed.;\",\n    \"operands\": [\n      { \"name\": \"ptr_feat0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_feat1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_feat2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_feat3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rois_multi_batch\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_res\", \"type\": \"AnyTensor\" },\n      { \"name\": \"result_rois\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ROI_NUM_LEVELS\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_H\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_W\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_ROI\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_SLICE\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PH\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PW\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_LEN\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaskRCNN_GetBboxB\",\n    \"summary\": \"MaskRCNN GetBboxB gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    Mask rcnn consist of three part: backbone to get proposals, bbox head to get bbox pred, mask_head to get mask pred, GetBboxB is final part in bbox head\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\text{NMS}\\\\Bigl( \\\\text{Decode}\\\\Bigl( \\\\text{ptr\\\\_rois},\\\\, \\\\text{ptr\\\\_bbox},\\\\, \\\\text{max\\\\_val},\\\\, \\\\text{scale\\\\_factor},\\\\, \\\\text{delta2bbox\\\\_means},\\\\, \\\\text{delta2bbox\\\\_stds} \\\\Bigr),\\\\, \\\\text{ptr\\\\_score},\\\\, \\\\text{threshold\\\\_score\\\\_eq},\\\\, \\\\text{nms\\\\_iou\\\\_thr} \\\\Bigr)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    ptr_rois(act.): candidate regions of interest for possible objects.;\\r\\n    ptr_bbox(act.): the bounding box predictions.;\\r\\n    ptr_score(act.): confidence scores associated with each proposal.;\\r\\n    max_val(w.): max scores the bbox predictions.;\\r\\n    scale_factor(w.): scale the decoded bounding box coordinates.;\\r\\n\\r\\n    4.attributes\\r\\n    threshold_score_eq: A threshold value used to filter out proposals with a low confidence score before applying NMS.;\\r\\n    wh_ratio_log: A logarithmic scaling factor, adjust the width-to-height ratio during decoding of bounding boxes.;\\r\\n    nms_iou_thr: IoU (Intersection over Union) threshold.;\\r\\n    delta2bbox_means: Mean values used to decode the bounding box regression.;\\r\\n    delta2bbox_stds_0: Standard deviation (first component) for scaling the decoded bbox values.;\\r\\n    delta2bbox_stds_1: Standard deviation (second component) for scaling the decoded bbox values.;\\r\\n    NUM_INDEXES: the number of indexes (or anchors).;\\r\\n    NUM_CLASSES: The total number of object classes.;\\r\\n    TOPK_ONNX_NMS: to select a fixed number of candidates.;\\r\\n    NUM_CLASSES_getBboxB: Number of classes used in this bounding box decoding step.;\\r\\n    MAX_NMS_LENGTH_GetBboxB: Maximum number of bounding box candidates.;\\r\\n    MAX_PER_IMG: The maximum number of detections allowed per image.;\\r\\n    MAX_PER_IMG_GetBboxB: maximum number of bounding boxes after the final processing.;\",\n    \"operands\": [\n      { \"name\": \"ptr_rois\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_bbox\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_score\", \"type\": \"AnyTensor\" },\n      { \"name\": \"max_val\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale_factor\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_det_bboxes\", \"type\": \"AnyTensor\" },\n      { \"name\": \"result_det_labels\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"threshold_score_eq\", \"type\": \"F64Attr\" },\n      { \"name\": \"wh_ratio_log\", \"type\": \"F64Attr\" },\n      { \"name\": \"nms_iou_thr\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_means\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_stds_0\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_stds_1\", \"type\": \"F64Attr\" },\n      { \"name\": \"NUM_INDEXES\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_CLASSES\", \"type\": \"I64Attr\" },\n      { \"name\": \"TOPK_ONNX_NMS\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_CLASSES_getBboxB\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_NMS_LENGTH_GetBboxB\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_PER_IMG\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_PER_IMG_GetBboxB\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaskRCNN_MaskPooler\",\n    \"summary\": \"Mask_Pooler gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    MaskRCNN_Mask_Pooler, the 2st ROIAlign in MaskRCNN\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\text{ROIAlign}\\\\Bigl( \\\\{x_i\\\\}_{i=0}^3, \\\\, \\\\text{det\\\\_bboxes\\\\_multi\\\\_batch}, \\\\, \\\\text{det\\\\_labels\\\\_multi\\\\_batch}, \\\\, \\\\text{scale\\\\_factor}, \\\\, ROI\\\\_NUM\\\\_LEVELS, \\\\, ROI\\\\_H, \\\\, ROI\\\\_W, \\\\, CHANNEL\\\\_ROI, \\\\, ROI\\\\_SLICE, \\\\, ROI\\\\_PH, \\\\, ROI\\\\_PW, \\\\, ROI\\\\_LEN \\\\Bigr)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    x_0(act.): first level of the feature pyramid.;\\r\\n    x_1(act.): second level of the feature pyramid.;\\r\\n    x_2(act.): third level of the feature pyramid.;\\r\\n    x_3(act.): fourth level of the feature pyramid.;\\r\\n    det_bboxes_multi_batch(act.): detected bounding boxes over multiple batches.;\\r\\n    det_labels_multi_batch(act.): class labels associated with the detected bounding boxes across multiple batches.;\\r\\n    scale_factor(w.): scale the decoded bounding box coordinates.;\\r\\n\\r\\n    4.attributes\\r\\n    ROI_NUM_LEVELS: the number of feature levels (or pyramid levels) available for ROI pooling.;\\r\\n    ROI_H: target height of the pooled region for each ROI.;\\r\\n    ROI_W: target width of the pooled region for each ROI.;\\r\\n    CHANNEL_ROI: number of channels to be kept or considered when performing ROIAlign.;\\r\\n    ROI_SLICE: slicing strategy for ROIs, if the ROI needs to be segmented into sub-regions for finer pooling.;\\r\\n    ROI_PH: Padding height for the ROI.;\\r\\n    ROI_PW: Padding width for the ROI.;\\r\\n    ROI_LEN: total length (or area) of the ROI.;\",\n    \"operands\": [\n      { \"name\": \"x_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"x_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"x_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"x_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"det_bboxes_multi_batch\", \"type\": \"AnyTensor\" },\n      { \"name\": \"det_labels_multi_batch\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale_factor\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_res\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ROI_NUM_LEVELS\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_H\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_W\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_ROI\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_SLICE\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PH\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PW\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_LEN\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaskRCNN_RPNGetBboxes\",\n    \"summary\": \"RPN_get_bboxes gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    MaskRCNN_RPN_get_bboxes, the sub-block with 1st NMS between RPN_head and 1st ROIAlign.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Score Filtering\\r\\n            valid_indices_i = cls_scores_i > conf_threshold (for each level i)\\r\\n        2.Bounding Box Adjustment\\r\\n            adjusted_bboxes_i = anchors_i + bbox_preds_i * delta2bbox_std_i + delta2bbox_mean_i\\r\\n        3.IoU Calculation\\r\\n            iou = calculate_iou(adjusted_bboxes_i, ground_truth_boxes)\\r\\n        4.NMS Application\\r\\n            final_bboxes = nms(adjusted_bboxes_i[valid_indices_i], iou_threshold)\\r\\n        5.final output\\r\\n            output = concatenate(final_bboxes)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    cls_scores_0: the class scores0 for each anchor;\\r\\n    cls_scores_1: the class scores1 for each anchor;\\r\\n    cls_scores_2: the class scores2 for each anchor;\\r\\n    cls_scores_3: the class scores3 for each anchor;\\r\\n    cls_scores_4: the class scores4 for each anchor;\\r\\n    bbox_preds_0: the bounding box0 predictions;\\r\\n    bbox_preds_1: the bounding box1 predictions;\\r\\n    bbox_preds_2: the bounding box2 predictions;\\r\\n    bbox_preds_3: the bounding box3 predictions;\\r\\n    bbox_preds_4: the bounding box4 predictions;\\r\\n    max_shape: the maximum dimensions of the output bounding boxes.;\\r\\n    mlvl_anchors_0: the multi-level anchors0 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_1: the multi-level anchors1 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_2: the multi-level anchors2 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_3: the multi-level anchors3 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_4: the multi-level anchors4 used for generating bounding box proposals.;\\r\\n\\r\\n    4.attribute\\r\\n    delta2bbox_mean_0: the means used to normalize the bounding box0 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_mean_1: the means used to normalize the bounding box1 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_mean_2: the means used to normalize the bounding box2 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_mean_3: the means used to normalize the bounding box3 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_0: the standard deviations used to normalize the bounding box0 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_1: the standard deviations used to normalize the bounding box1 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_2: the standard deviations used to normalize the bounding box2 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_3: the standard deviations used to normalize the bounding box3 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_max_scalar_c: a scalar value;\\r\\n    iou_threshold: filtering out low-quality proposals during NMS.;\\r\\n    conf_threshold: a confidence score threshold.;\\r\\n    MAX_LENGTH_STATIC_STRECHED: the maximum length for the output list of bounding boxes after processing.;\\r\\n    NUM_INDEXES: the number of indexes.;\\r\\n    NUM_CLASSES: the number of classes.;\\r\\n    CHANNEL_RPN_BBOXES: the number of channels for the bounding box predictions.;\\r\\n    CHANNEL_RPN_SCORES: the number of channels used for the class score predictions.;\\r\\n    NMS_PRE: the number of proposals to be considered before NMS.;\\r\\n    HARDWARE_FACTOR_TOPK: how many top proposals to keep.;\\r\\n    NMS_MAX_LENGTH: the maximum number of boxes after NMS.;\\r\\n    TOPK_ONNX_NMS: the number of top proposals when using ONNX format for NMS.;\\r\\n    H_RPN_DYN_MAX: the maximum height for the dynamic RPN output.;\\r\\n    W_RPN_DYN_MAX: the maximum width for the dynamic RPN output.;\\r\\n    MAX_PER_IMG: the maximum number of proposals to be generated per image.;\",\n    \"operands\": [\n      { \"name\": \"cls_scores_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_4\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_4\", \"type\": \"AnyTensor\" },\n      { \"name\": \"max_shape\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_4\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_list\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"delta2bbox_mean_0\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_mean_1\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_mean_2\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_mean_3\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_0\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_1\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_2\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_3\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_max_scalar_c\", \"type\": \"F64Attr\" },\n      { \"name\": \"iou_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"conf_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"MAX_LENGTH_STATIC_STRECHED\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_INDEXES\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_CLASSES\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_RPN_BBOXES\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_RPN_SCORES\", \"type\": \"I64Attr\" },\n      { \"name\": \"NMS_PRE\", \"type\": \"I64Attr\" },\n      { \"name\": \"HARDWARE_FACTOR_TOPK\", \"type\": \"I64Attr\" },\n      { \"name\": \"NMS_MAX_LENGTH\", \"type\": \"I64Attr\" },\n      { \"name\": \"TOPK_ONNX_NMS\", \"type\": \"I64Attr\" },\n      { \"name\": \"H_RPN_DYN_MAX\", \"type\": \"I64Attr\" },\n      { \"name\": \"W_RPN_DYN_MAX\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_PER_IMG\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MatchTemplate\",\n    \"summary\": \"opencv MatchTemplate operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform opencv MatchTemplate operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            R(x, y) = \\\\sum_{i=0}^{T_w-1} \\\\sum_{j=0}^{T_h-1} I(x+i, y+j) \\\\cdot T(i, j)\\r\\n    ```\\r\\n    where:\\r\\n    R(x, y) is the result of the match at position(x, y).\\r\\n    I is the input image.\\r\\n    T is the template image.\\r\\n    T_w and T_h are the width and height of the template.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    match(w.): the template image that will be matched against the input image.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the method of template matching to be used (e.g., correlation, squared difference, etc.).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"match\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"MatchTemplateModeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MatMul\",\n    \"summary\": \"matmul operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The MatMul operator performs two-dimensional matrix multiplication between two input tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input x right + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): the first input tensor;\\r\\n    right(act.): the second input tensor;\\r\\n    bias(w.):  an optional tensor can be added to the result of the matrix multiplication. ;\\r\\n\\r\\n    4.attribute\\r\\n    right_transpose: whether to transpose the right input tensor before performing the multiplication.;\\r\\n    left_transpose: whether to transpose the input tensor before performing the multiplication.;\\r\\n    output_transpose: whether to transpose the output tensor after the multiplication.;\\r\\n    hdim_is_batch: whether the first dimension of the input tensor represents the batch size.;\\r\\n    keep_dims: whether to keep the dimensions of the output tensor the same as the input tensors.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    weight_bits: the bit-width for quantizing the weights.;\\r\\n    in_int4_scale: the scaling factor for input tensors that are quantized to 4 bits.;\\r\\n    in_int4_zp: the zero point for input tensors that are quantized to 4 bits.;\\r\\n    out_int8_scale:the scaling factor for the output tensor when quantized to 8 bits.;\\r\\n    out_int8_zp: This optional attribute specifies the zero point for the output tensor that is quantized to 8 bits.;\\r\\n    dq_type: the quantized data type for dynamic quantization.;\\r\\n    q_group_size: the group size for per-group quantization.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"right\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"right_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"left_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"output_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"hdim_is_batch\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_lora\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"weight_bits\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"in_int4_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"in_int4_zp\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"out_int8_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"out_int8_zp\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"dq_type\", \"type\": \"DefaultValuedAttr<DqTypeAttr, \\\"NONE\\\">\" },\n      { \"name\": \"q_group_size\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Max\",\n    \"summary\": \"max operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Element-wise max of each of the input tensors. All inputs and outputs must have the same data type.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = max(input1,input2, ..., inputN)\\r\\n    ```\\r\\n    Where input1, input2, ..., inputN are the input tensors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaxConst\",\n    \"summary\": \"Max Const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    max of one input and one const.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Max(input, const_val)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaxPool\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        {output}(N_i, C_j, p, q) = pool(input(N_i, C_j, start_h, start_w), kernel_size)\\r\\n    ```\\r\\n    start_h and start_w are the starting indices for the pooling window in the height and width dimensions.\\r\\n    pool can be any pooling function (max pooling, average pooling) applied over the region defined by the kernel size.\\r\\n    N is a batch size, C denotes a number of channels,\\r\\n    Shape:\\r\\n    - Input: (N, C_{in}, H_{in}, W_{in})\\r\\n    - Output: (N, C_{out}, H_{out}, W_{out})\\r\\n        ```math\\r\\n        H_{output} = {H_{in} + {padding}[0] + {padding}[2] - {kernel_shape}[0]} / {stride}[0] + 1\\r\\n        ```\\r\\n        ```math\\r\\n        W_{output} = {W_{in} + {padding}[1] + {padding}[3] - {kernel_shape}[1]} / {stride}[1] + 1\\r\\n        ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    auto_pad: It can be set to different modes (e.g., SAME, VALID) to automatically calculate the necessary padding based on\\r\\n              the input size,kernel size, and stride.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"auto_pad\", \"type\": \"OptionalAttr<AutoPadModeAttr>\" },\n      { \"name\": \"is_adaptive\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaxPoolingIndicesBwd\",\n    \"summary\": \"MaxPoolingIndicesBwd operator\",\n    \"description\": \"1.Op Introduction\\r\\n    MaxPoolingIndicesBwd operator\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = grad_output[indices]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    indices(w.): the indices of the input tokens or items.;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    input_shape: The shape of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaxPoolWithMask\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        {output}(N_i, C_j, p, q) = pool(input(N_i, C_j, start_h, start_w), kernel_size)\\r\\n    ```\\r\\n    start_h and start_w are the starting indices for the pooling window in the height and width dimensions.\\r\\n    pool can be any pooling function (max pooling, average pooling) applied over the region defined by the kernel size.\\r\\n    N is a batch size, C denotes a number of channels,\\r\\n    Shape:\\r\\n    - Input: (N, C_{in}, H_{in}, W_{in})\\r\\n    - Output: (N, C_{out}, H_{out}, W_{out})\\r\\n        ```math\\r\\n        H_{output} = {H_{in} + {padding}[0] + {padding}[2] - {kernel_shape}[0]} / {stride}[0] + 1\\r\\n        ```\\r\\n        ```math\\r\\n        W_{output} = {W_{in} + {padding}[1] + {padding}[3] - {kernel_shape}[1]} / {stride}[1] + 1\\r\\n        ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    auto_pad: It can be set to different modes (e.g., SAME, VALID) to automatically calculate the necessary padding based on\\r\\n              the input size,kernel size, and stride.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"auto_pad\", \"type\": \"OptionalAttr<AutoPadModeAttr>\" },\n      { \"name\": \"is_adaptive\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"keepdims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.MaxUnpool\",\n    \"summary\": \"MaxUnpool operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform  MaxUnpool on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i, j] = Upsample(input[i / scale_h, j / scale_w])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    mask(act.): the positions of the maximum values that were retained during the max pooling operation.;\\r\\n\\r\\n    4.attributes\\r\\n    scale_h: the scaling factor for the height (number of rows) of the input tensor.;\\r\\n    scale_w: the scaling factor for the width (number of columns) of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"scale_w\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MeanRstd\",\n    \"summary\": \"Compute Mean, Rstd, Running_mean, Running_var in batchnorm train op\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the mean, reverse standard deviation (Rstd), running mean, and running variance.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        mean(x),1/sqrt(var+eps),(1-momentum)*running_mean + momentum*mean,(1-momentum)*running_var + momentum*var\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    running_mean(w.): mean during running.;\\r\\n    running_var(w.): variances during running.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    momentum: hyperparameter;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rstd\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_mean_update\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_var_update\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias_new\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"momentum\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MeanStdScale\",\n    \"summary\": \"MeanStdScale, it's for preprocess.\",\n    \"description\": \"1.Op Introduction\\r\\n    for preprocess, do multiplier&rshift quantize.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = (input - mean) / std * scale + zero_points\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    quant_mode: the mode or method used for quantization during the requantization operation.;\\r\\n    customization_format: custom format for the input data.;\\r\\n    channel_order: The order of color channels in the input tensor.;\\r\\n    scale: each channel scale.;\\r\\n    mean: mean values to subtract from each channel for normalization.;\\r\\n    sign: if output is signed.;\\r\\n    std: standard deviation values for each channel.;\\r\\n    zero_points: zero point values for each channel.;\\r\\n    resize_dims: resize the input tensor' dimensions.;\\r\\n    rounding_mode: The rounding method to use during quantization.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"customization_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"channel_order\", \"type\": \"StrAttr\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"std\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"mean\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"zero_points\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"resize_dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"rounding_mode\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.MeshGrid\",\n    \"summary\": \"MeshGrid operation\",\n    \"description\": \"1.Op Introduction\\r\\n    torch mesh grid operation\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            X[i] = x[i mod m] for i = 0, 1, ..., m · n-1\\r\\n            Y[i] = y[j // m] for j = 0, 1, ..., m · n-1\\r\\n    ```\\r\\n    where X, Y will have shape (m, n);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_reverse\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Min\",\n    \"summary\": \"min operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Element-wise min of each of the input tensors. All inputs and outputs must have the same data type.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = min(input1,input2, ..., inputN)\\r\\n    ```\\r\\n    Where input1, input2, ..., inputN are the input tensors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.MinConst\",\n    \"summary\": \"Min Const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    min of one input and one const.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Min(input, const_val)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Mish\",\n    \"summary\": \"Mish operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the mish of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[i] x tanh(softplus(input[i]))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Mlp\",\n    \"summary\": \"w8a16 / w4a16 / a16 mlp operator\",\n    \"description\": \"to do\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_gate\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_up\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_down\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias_gate\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_up\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_down\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"scale_gate\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"scale_up\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"scale_down\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp_gate\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp_up\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp_down\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"right_transpose_gate\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"right_transpose_up\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"right_transpose_down\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"quantized\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"q_group_size\", \"type\": \"DefaultValuedAttr<I64Attr, 128>\" },\n      { \"name\": \"weight_bits\", \"type\": \"DefaultValuedAttr<I64Attr, 8>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Mmap2Rgbmap\",\n    \"summary\": \"isp mmap2rgbmap.\",\n    \"description\": \"isp mmap2rgbmap.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Mod\",\n    \"summary\": \"Mod operator\",\n    \"description\": \"1.Op Introduction\\r\\n    a mathematical operation that calculates the remainder of the division of two numbers (or tensors) element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            f(x, y) = Mod(x, y)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Mul\",\n    \"summary\": \"Mul operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise multiplication of input1 and input2. input1 and input2 are tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReLU((input1 * input2))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.MulConst\",\n    \"summary\": \"Mul Const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise mul of input1 and input2. Input2 is constant.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input * const_val\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Nms\",\n    \"summary\": \"NMS operator\",\n    \"description\": \"1.Op Introduction\\r\\n    onnx nms\\r\\n    used to eliminate redundant overlapping bounding boxes by selecting only the most relevant ones based on their confidence scores.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        IOU(a, b) = Area(a \\\\cap b) / Area(a \\\\cup b)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    center_point_box: whether the bounding boxes are defined by their center points.;\\r\\n    max_output_size: the maximum number of boxes to be output after NMS.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"center_point_box\", \"type\": \"I64Attr\" },\n      { \"name\": \"max_output_size\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.None\",\n    \"summary\": \"none operator\",\n    \"description\": \"A none Op to return a NoneType.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"NoneType\" }\n    ]\n  },\n  {\n    \"name\": \"top.NonZero\",\n    \"summary\": \"NonZero operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the indices of the elements that are non-zero\\r\\n    (in row-major order - by dimension).\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input[i1, i2, i3,...in] != 0\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    order: the order in which the non-zero indices should be returned.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"NonZeroOrderAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Normalize\",\n    \"summary\": \"Normalize operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Normalizes an array across batch and spatial dimensions.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ((input - Mu) / (Sigma + Epsilon)) x scale\\r\\n    ```\\r\\n    where, Mu is the mean of the input values calculated across the specified dimensions.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    scale(w.): the scale weight tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    across_spatial: determines whether the normalization is performed across the spatial dimensions of the input tensor.;\\r\\n    channel_shared: indicates whether the scaling weight tensor should be shared across channels.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"across_spatial\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"channel_shared\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Pack\",\n    \"summary\": \"Pack operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Pack a list of tensors in the given dimension, All tensors must have the same shape.\\r\\n\\r\\n    2.Math formula\\r\\n    output = Pack(input1, input2, input3; axis)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    axis: It specifies the dimension along which the input tensors will be packed together.;\\r\\n    values_count: It indicates the number of tensors being packed.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"values_count\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Pad\",\n    \"summary\": \"Pad operation\",\n    \"description\": \"1.Op Introduction\\r\\n    This operation pads a tensor according to the paddings you specify.\\r\\n    paddings is an integer tensor with shape [2, n], where n is the rank of tensor.\\r\\n    For each dimension D of input, paddings[0, D] indicates how many values to add\\r\\n    before the contents of tensor in that dimension, and paddings[1, D] indicates\\r\\n    how many values to add after the contents of tensor in that dimension.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input(padding, val, mode)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    paddingsT(act.):  the padding values for each dimension.;\\r\\n\\r\\n    4.attribute\\r\\n    paddings: defines how much padding to add before and after the contents of the input tensor for each dimension. ;\\r\\n    val: the value to be used for padding the input tensor. ;\\r\\n    mode: the padding mode include constant(Pads with a constant value); reflect(Pads with a reflection of the tensor values); replicate(Pads by replicating the edge values of the tensor).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"paddingsT\", \"type\": \"Optional<AnyTensorOrNone>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"paddings\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"val\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"mode\", \"type\": \"PaddingModeAttr{default_|same|valid}\" }\n    ]\n  },\n  {\n    \"name\": \"top.Permute\",\n    \"summary\": \"Permute operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform permute on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(...dim2, dim1, dim0) = PermuteOp(input(dim0, dim1, dim2...order))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    order: An array of integers specifying the permutation order of the input tensor's dimensions.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.PixelNorm\",\n    \"summary\": \"PixelNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    pixel normalization (normalize along c-axis)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            norm_{n, i, j} = sqrt(1 /C \\\\sum{c=1, C}input_{n, c, i, j} ^ 2) + eps\\r\\n            output_{n, c, i, j} = weight * input_{n, c, i, j} / norm_{n, i, j} + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.PoolMask\",\n    \"summary\": \"pool mask operator\",\n    \"description\": \"1.Op Introduction\\r\\n    pooling mask on input\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        {output}(N_i, C_j, p, q) = scale x pool(input(N_i, C_j, start_h, start_w), kernel_size)\\r\\n    ```\\r\\n    start_h and start_w are the starting indices for the pooling window in the height and width dimensions.\\r\\n    pool can be any pooling function (max pooling, average pooling) applied over the region defined by the kernel size.\\r\\n    N is a batch size, C denotes a number of channels,\\r\\n    Shape:\\r\\n    - Input: (N, C_{in}, H_{in}, W_{in})\\r\\n    - Output: (N, C_{out}, H_{out}, W_{out})\\r\\n        ```math\\r\\n        H_{output} = {H_{in} + {padding}[0] + {padding}[2] - {kernel_shape}[0]} / {stride}[0] + 1\\r\\n        ```\\r\\n        ```math\\r\\n        W_{output} = {W_{in} + {padding}[1] + {padding}[3] - {kernel_shape}[1]} / {stride}[1] + 1\\r\\n        ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    scale: a scaling factor is applied to the output of the pooling operation, can adjust the intensity or magnitude of the output mask.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Pow\",\n    \"summary\": \"Pow operation\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the element-wise power of an input tensor raised to a specified exponent.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input ^ n\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    exponent: the power to which each element of the input tensor will be raised.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exponent\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Pow2\",\n    \"summary\": \"Pow2 operation\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the result of raising a constant value ( n ) to the power of each element in the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = n ^ input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Pow3\",\n    \"summary\": \"Pow3 operation\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the element-wise power of two input tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input1 ^ input2\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.PRelu\",\n    \"summary\": \"PRelu operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Parametric Rectified Linear Unit is an activation function.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            f(x) = slope * x   for x < 0\\r\\n            f(x) = x           for x >= 0\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    slope(w.): the activation function for negative input values.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"slope\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Preprocess\",\n    \"summary\": \"FusePreprcess, it's just a placeholder op.\",\n    \"description\": \"1.Op Introduction\\r\\n    It may be divided to permute + slice + scale/scale_lut ops.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Scale(Slice(Permute(input,channel_order), resize_dims), scale) - mean.\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    quant_mode: the mode or method used for quantization during the requantization operation.;\\r\\n    customization_format: custom format for the input data.;\\r\\n    channel_order: The order of color channels in the input tensor.;\\r\\n    resize_dims: resize the input tensor' dimensions.;\\r\\n    scale: each channel scale.;\\r\\n    mean: mean values to subtract from each channel for normalization.;\\r\\n    sign: if output is signed.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"customization_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"channel_order\", \"type\": \"StrAttr\" },\n      { \"name\": \"resize_dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"mean\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.PriorBox\",\n    \"summary\": \"PriorBox operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Intended for use with MultiBox detection method to generate prior.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input(x, y, w, h) i in [0, num_priors]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    min_size: the minimum size of the prior boxes.;\\r\\n    max_size: the maximum size of the prior boxes.;\\r\\n    aspect_ratios: A list of aspect ratios for the generated prior boxes.;\\r\\n    variance: adjust the predicted boxes during the training process.;\\r\\n    clip: whether the prior boxes should be clipped to the image boundaries.;\\r\\n    step_h: The vertical step size for generating prior boxes.;\\r\\n    step_w: The horizontal step size for generating prior boxes.;\\r\\n    img_h: The height of the input image.;\\r\\n    img_w: The width of the input image.;\\r\\n    offset: A value used to offset the prior boxes from their calculated positions.;\\r\\n    num_priors: The number of prior boxes to be generated for each location in the feature map.;\\r\\n    use_default_aspect_ratio: whether to use a default aspect ratio (1.0);\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min_size\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"max_size\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"aspect_ratios\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"variance\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"clip\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"step_h\", \"type\": \"F64Attr\" },\n      { \"name\": \"step_w\", \"type\": \"F64Attr\" },\n      { \"name\": \"img_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"img_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"offset\", \"type\": \"DefaultValuedAttr<F64Attr, 0.5>\" },\n      { \"name\": \"num_priors\", \"type\": \"I64Attr\" },\n      { \"name\": \"use_default_aspect_ratio\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Proposal\",\n    \"summary\": \"Proposal operator\",\n    \"description\": \"1.Op Introduction\\r\\n    generate candidate bounding boxes primarily in object detection tasks.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.anchor box generation and regression\\r\\n            a_i = (x + \\\\delta(x), y + \\\\delta(y), w * e ^ \\\\delta(w), e ^ \\\\delta(h))\\r\\n        2.obj score\\r\\n            s_i = sigmoid(output_ModelPredict(a_i))\\r\\n        3.Final select output\\r\\n            output = NMS(s_i)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    net_input_h: net input height.;\\r\\n    net_input_w: net input width.;\\r\\n    feat_stride: anchor box stride size.;\\r\\n    anchor_base_size: anchor box base size.;\\r\\n    rpn_obj_threshold: obj threshold.;\\r\\n    rpn_nms_threshold: nms threshold for generate proposal boxes.;\\r\\n    rpn_nms_post_top_n: keep num boxes after nms.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"net_input_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"net_input_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"feat_stride\", \"type\": \"I64Attr\" },\n      { \"name\": \"anchor_base_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"rpn_obj_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"rpn_nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"rpn_nms_post_top_n\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.QuantizeLinear\",\n    \"summary\": \"Linear quantize operation\",\n    \"description\": \"1.Op Introduction\\r\\n    QuantizeLinear(x) := saturate ((x / y_scale) + y_zero_point)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output[i] = saturate((input[i] / y_scale[j]) + y_zero_point[j])\\r\\n    ```\\r\\n    i indexes the elements of the input tensor, and j corresponds to the specific dimension or channel.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    y_scale: Each element to a specific output channel or dimension, determining how much to scale the input values.;\\r\\n    y_zero_point: an array of zero points used in the quantization process.;\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"y_scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"y_zero_point\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.RandnLike\",\n    \"summary\": \"randn_like operator, y = randn_like(x)\",\n    \"description\": \"1.Op Introduction\\r\\n    create a tensor with the same shape as input, and fill with value from normal distribution\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = randn(shape(input))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    randn_data(w.): the characteristics of the normal distribution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"randn_data\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Range\",\n    \"summary\": \"Range operator\",\n    \"description\": \"1.Op Introduction\\r\\n    onnx range op.\\r\\n    generates a sequence of evenly spaced values within a specified range.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = [x | x = start + n * delta, n is an integer, and start ≤ x < limit]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    start(act.): The starting value of the sequence. This can be a tensor or None. If None, it defaults to 0.;\\r\\n    limit(w.): The exclusive upper limit of the sequence.;\\r\\n    delta(w.): The increment between each value;\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"limit\", \"type\": \"AnyTensor\" },\n      { \"name\": \"delta\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Reciprocal\",\n    \"summary\": \"Constant scalar divide tensor operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Reciprocal operator is a tensor operation that performs division of a constant scalar value by an input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = const_val / input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Reduce\",\n    \"summary\": \"Reduce operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Computes the mean/max/prod/sum of the input tensor's element along the provided axes.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            1.Sum\\r\\n                output[i_1, i_2, i_3,..., i_k] = \\\\sum{j in A}input[i_1, i_2,..., j, ..., i_n]\\r\\n                where ( A ) is the set of axes to reduce.\\r\\n            2.Mean\\r\\n                output[i_1, i_2, i_3,..., i_k] = 1 / count (\\\\sum{j in A}input[i_1, i_2,..., j, ..., i_n])\\r\\n                where count is the number of elements being summed along the axes ( A ).\\r\\n            3.Max\\r\\n                output[i_1, i_2, i_3,..., i_k] = max{j in A}input[i_1, i_2,..., j, ..., i_n]\\r\\n            4.Product\\r\\n                output[i_1, i_2, i_3,..., i_k] = \\\\prod_{j=1}^m(input[i_1, i_2,..., i_k, j])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grid(w.): The flow-field grid tensor that defines the pixel locations for sampling.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"keepdims\", \"type\": \"BoolAttr\" },\n      { \"name\": \"mode\", \"type\": \"ReduceModeAttr\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Relu\",\n    \"summary\": \"Relu operator\",\n    \"description\": \"1.Op Introduction\\r\\n    ReLU with a scalar maximum value. if limit is zero, do not use upper limit.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReluOp(input) -> (0, 1)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Remainder\",\n    \"summary\": \"Remainder operator\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the element-wise remainder of division between two tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            quo = x / y;\\r\\n            floor_quo = floor(quo);\\r\\n            output = torch.remainder(x, y) = x - y * floor_quo.\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Repeat\",\n    \"summary\": \"Repeat operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform aten::repeat operation on the given tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i_1, i_2, i_3,...i_k] = input[i_1 / r_1, i_2 / r_2, i_3 / r_3,..., i_k mod r_k]\\r\\n    ```\\r\\n    where r_j represents the corresponding value from the repeats tensor for dimension ( j ).\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    repeats(w.): the number of times to repeat the input tensor along each dimension.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"repeats\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.RequantFp\",\n    \"summary\": \"requant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Requant 32/16/8 bit data to int8 or uint8 data, by scale\\r\\n\\r\\n    2.Math formula\\r\\n    int8/uint8/fp8(output) = round(float32/float16/float8(input) x scale + offset);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    scale: Scalar;\\r\\n    offset: Scalar;\\r\\n    quant_mode: the mode or method used for quantization during the requantization operation.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"quant_mode\", \"type\": \"RequantModeAttr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfUp\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.RequantInt\",\n    \"summary\": \"requant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Requant 32/16/8 bit data to int8 or uint8 data, by int multiplier and int shift;\\r\\n\\r\\n    2.Math formula\\r\\n    int8/uint8(output) = RequantIntOp (int32/16/8(input));\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    quant_mode: the mode or method used for quantization during the requantization operation.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    rq_axis: the axis along which the requantization operation is applied.;\\r\\n    fuse_rq: whether to fuse the requantization operation with a preceding operation (such as a convolution or activation function).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiplier\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"rshift\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"quant_mode\", \"type\": \"RequantModeAttr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"rq_axis\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"fuse_rq\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Reshape\",\n    \"summary\": \"Reshape operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns a tensor with the same type/values as the input, with a new shape\\r\\n    specified by the shape argument. Reshape may operate on tensors of any rank.\\r\\n    No data conversion happens during a reshape operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReshapeOp(input, shape)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    shapeT(act.): an optional input tensor that specifies the desired shape for the output tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    shape: 0: keep dim from input; -1: left dim from input.;\\r\\n    flatten_start_dim: the starting dimension from which to begin flattening the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shapeT\", \"type\": \"Optional<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"flatten_start_dim\", \"type\": \"DefaultValuedAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"top.RetinaFaceDetection\",\n    \"summary\": \"RetinaFaceDetection operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform retinaface detection on feature map\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = NMS(Filter(Detect(inputs), confidence_threshold), nms_threshold, keep_topk)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    nms_threshold: nms threshold.;\\r\\n    confidence_threshold: classification confidence threshold.;\\r\\n    keep_topk: after nms, keep bbox num.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"confidence_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"keep_topk\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Reverse\",\n    \"summary\": \"Reverse operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Reverse on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReverseOp(input, axis)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension of reverse;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.RMSNorm\",\n    \"summary\": \"RMSNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    A simplification of the original layer normalization (LayerNorm).\\r\\n    Only normalize the last dimension of tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = gamma * input / sqrt(mean(input ^ 2) + epsilon)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    gamma(w.): scalar.;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gamma\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"weight_keep_f32\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.RoiAlign\",\n    \"summary\": \"RoiAlign operator\",\n    \"description\": \"1.Op Introduction\\r\\n    RoiAlign consumes an input tensor X and region of interests\\r\\n    (rois) to apply pooling across each RoI.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.ROI coordinate scaling[x1, y1, x2, y2]\\r\\n            x_scaled = x x spatial_scale\\r\\n            y_scaled = y x spatial_scale\\r\\n        2.Delineation of grid sub-areas\\r\\n            bin_height = (y2_scaled - y1_scaled) / output_height\\r\\n            bin_width  = (x2_scaled - x1_scaled) / output_width\\r\\n        3.align_corners -> true\\r\\n            x_grid = x1_scaled + (i + 0.5) x bin_width\\r\\n            y_grid = y1_scaled + (j + 0.5) x bin_height\\r\\n        output = RoiAlign(input, rois, output_height, output_width, sampling_ratio, spatial_scale, align_corners)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor(4D);\\r\\n    rois(w.): RoIs (Regions of Interest) to pool over.;\\r\\n          rois is 2-D input of shape (num_rois, 4) given as [[x1, y1, x2, y2], ...].;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of comparison to be performed between the two input tensors.\\r\\n          mdoe include Equal, Not Equal, Less Than, Less Than or Equal, Greater Than and Greater Than or Equal;\\r\\n    output_height: the height of the output feature maps.;\\r\\n    output_width: the width of the output feature maps.;\\r\\n    sampling_ratio: the number of sampling points in each direction (height and width).;\\r\\n    spatial_scale: a scaling factor that maps the input coordinates (RoIs) to the input feature map's scale.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\\r\\n    batch_indices: 1-D tensor with each element denoting the index of the corresponding image in the batch.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rois\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"RoiAlignModeAttr\" },\n      { \"name\": \"output_height\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"sampling_ratio\", \"type\": \"I64Attr\" },\n      { \"name\": \"spatial_scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.RoiExtractor\",\n    \"summary\": \"RoiExtractor operator\",\n    \"description\": \"1.Op Introduction\\r\\n    RoiExtractor consumes an input tensor X and region of interests\\r\\n    (rois) to apply pooling across each RoI.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.ROI coordinate scaling[x1, y1, x2, y2]\\r\\n            x_scaled = x x spatial_scale\\r\\n            y_scaled = y x spatial_scale\\r\\n        2.Delineation of grid sub-areas\\r\\n            bin_height = (y2_scaled - y1_scaled) / output_height\\r\\n            bin_width  = (x2_scaled - x1_scaled) / output_width\\r\\n        3.align_corners -> true\\r\\n            x_grid = x1_scaled + (i + 0.5) x bin_width\\r\\n            y_grid = y1_scaled + (j + 0.5) x bin_height\\r\\n        output_i = RoiAlign(input, rois_i, output_height, output_width, sampling_ratio, spatial_scale, align_corners)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n    rois(w.): RoIs (Regions of Interest) to pool over.;\\r\\n          rois is 2-D input of shape (num_rois, 4) given as [[x1, y1, x2, y2], ...].;\\r\\n    target_lvls(w.): 1-D tensor with each element denoting the index of the corresponding image in the batch.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of comparison to be performed between the two input tensors.\\r\\n          mdoe include Equal, Not Equal, Less Than, Less Than or Equal, Greater Than and Greater Than or Equal;\\r\\n    num_levels: The number of levels in the feature pyramid.;\\r\\n    output_height: the height of the output feature maps.;\\r\\n    output_width: the width of the output feature maps.;\\r\\n    sampling_ratio: the number of sampling points in each direction (height and width).;\\r\\n    spatial_scale: a scaling factor that maps the input coordinates (RoIs) to the input feature map's scale.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\\r\\n    is_static: whether the operation has a static shape.;\",\n    \"operands\": [\n      { \"name\": \"rois\", \"type\": \"AnyTensor\" },\n      { \"name\": \"target_lvls\", \"type\": \"AnyTensor\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"RoiAlignModeAttr\" },\n      { \"name\": \"num_levels\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_height\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"sampling_ratio\", \"type\": \"I64Attr\" },\n      { \"name\": \"spatial_scales\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" },\n      { \"name\": \"is_static\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"top.ROIPooling\",\n    \"summary\": \"ROIPooling operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Max pooling on ROI.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output(pooled_h, pooled_w) = max_pooling(input(h, w) in ROI(spatial_scale))\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    pooled_h: pooled output height.;\\r\\n    pooled_w: pooled output width.;\\r\\n    spatial_scale: adjust the ROI coordinates.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pooled_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"pooled_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"spatial_scale\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Rope\",\n    \"summary\": \"Rope operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Rope operator is a specialized tensor operation designed for efficient computations involving multiple input tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output=saturation((input1 x shift(input2, mul1_shift))⊕(input3 x shift(input2, mul2_shift))) + shift(input3, dd_shift)\\r\\n    ```\\r\\n    The operator ⊕ represents the addition of the two multiplicative results.\\r\\n    The function shift(input,shift_value) applies a shift to the input tensor based on the provided shift value.\\r\\n    The saturation function ensures that the output remains within a defined range, preventing overflow or underflow.\\r\\n\\r\\n    3.activation and weight\\r\\n    input1(act.): input tensor;\\r\\n    input2(act.): input tensor;\\r\\n    input3(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    is_permute_optimize:whether to apply optimization for permuting the input tensors.;\\r\\n    mul1_round_mode: the rounding mode to be used for the first multiplication operation.;\\r\\n    mul2_round_mode: Similar to mul1_round_mode, this attribute defines the rounding mode for the second multiplication operation.;\\r\\n    add_round_mode: the rounding mode for the addition operation.;\\r\\n    mul1_shift: the number of bits to shift the result of the first multiplication.;\\r\\n    mul2_shift: Similar to mul1_shift, this attribute defines the number of bits to shift for the second multiplication operation.;\\r\\n    add_shift: the number of bits to shift the result of the addition operation.;\\r\\n    mul1_saturation: whether the output of the first multiplication should be saturated.\\r\\n                     When set to true, the result will be clamped to prevent overflow or underflow.;\\r\\n    mul2_saturation: Similar to mul1_saturation, this attribute specifies whether saturation should be applied to the second multiplication's output.;\\r\\n    add_saturation: whether to apply saturation to the output of the addition operation.;\\r\\n    force_f32: when set to true, forces the computations to be performed in 32-bit floating point format, regardless of the input tensor formats.;\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input3\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rope_mode\", \"type\": \"DefaultValuedAttr<RopeModeAttr, \\\"interleaved_pairs\\\">\" },\n      { \"name\": \"is_permute_optimize\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"mul1_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"mul2_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"add_round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" },\n      { \"name\": \"mul1_shift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"mul2_shift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"add_shift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"mul1_saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"mul2_saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"add_saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"force_f32\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Round\",\n    \"summary\": \"Round operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Round takes one input Tensor and rounds the values, element-wise,\\r\\n    meaning it finds the nearest integer for each value. In case of halfs,\\r\\n    the rule is to round them to the nearest even integer.\\r\\n    If input x is integral, +0, -0, NaN, or infinite, x itself is returned.\\r\\n    The output tensor has the same shape and type as the input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Round(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Rsqrt\",\n    \"summary\": \"Rsqrt Operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Reverse square root.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\frac{1}{\\\\sqrt{input}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Scale\",\n    \"summary\": \"Scale operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Y = X * S + B,\\r\\n    where the shape of X/Y is [n, c, h, w] and the shape of S/B is [1, c, 1, 1].\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input x scale + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    scale(w.): scalar;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.ScaleDotProductAttention\",\n    \"summary\": \"ScaleDotProductAttention operator (pytorch)\",\n    \"description\": \"1.Op Introduction\\r\\n    Scale_Dot_Product_Attention Operation for pytorch.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = (softmax(Q * K^T) / sqrt(d_k) + mask) * V\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    query(act.): queries input tensor.;\\r\\n    key(act.): keys input tensor.;\\r\\n    value(act.): values input tensor.;\\r\\n    mask(w.): the learnable masks of the module of shape.;\\r\\n\\r\\n    4.attributes\\r\\n    dropout_p: the dropout probability for attention weights.;\\r\\n    is_causal: whether the attention should be causal.;\\r\\n    scale: the scaling factor.;\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dropout_p\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.ScaleLut\",\n    \"summary\": \"Scale by lut operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs scale on input, y = input * scale + bias.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input * scale + bias\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    scale: each channel scale.;\\r\\n    bias: each channel bias.;\\r\\n    sign: if output is signed.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"bias\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.ScatterElements\",\n    \"summary\": \"ScatterElements op\",\n    \"description\": \"1.Op Introduction\\r\\n    ScatterElements takes three inputs data, updates, and indices of the same rank r >= 1 and an optional attribute axis that\\r\\n    identifies an axis of data (by default, the outer-most axis, that is axis 0). The output of the operation is produced by\\r\\n    creating a copy of the input data, and then updating its value to values specified by updates at specific index\\r\\n    positions specified by indices. Its output shape is the same as the shape of data.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ScatterElements(input[axis], updates, indices)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    indices(w.): Tensor of int32/int64 indices, of r >= 1 (same rank as input).\\r\\n             All index values are expected to be within bounds [-s, s-1] along axis of size s.\\r\\n    updates(w.): Tensor of rank r >=1 (same rank and shape as indices).\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" },\n      { \"name\": \"updates\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"nc_can_split\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.ScatterND\",\n    \"summary\": \"ScatterND operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The output of the operation is produced by creating a copy of the input data,\\r\\n    and then updating its value to values specified by updates at\\r\\n    specific index positions specified by indices.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ScatterND(input_data[indices], updates, reduction)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input_data(act.): input tensor;\\r\\n    indices(w.): Tensor of rank q >= 1.;\\r\\n    updates(w.): Tensor of rank q + r - indices_shape[-1] - 1.;\\r\\n\\r\\n    4.attributes\\r\\n    reduction: Type of reduction to apply: none (0 default), add(1), sub(2), max(3), min(4), mul(5).;\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" },\n      { \"name\": \"updates\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.SelectiveScan\",\n    \"summary\": \"2D Selective Scan Operator (specialized for VMamba)\",\n    \"description\": \"1. Op Introduction\\r\\n    Performs structured state space modeling (SSM) on 2D image data using a bidirectional scanning mechanism.\\r\\n    Core component of the VMamba architecture that enables efficient long-range dependency modeling in visual data.\\r\\n\\r\\n    2. Math formula\\r\\n    For each scanning direction:\\r\\n    ```\\r\\n    h_t = δA_t ⊙ h_{t-1} + δB_t ⊙ u_t\\r\\n    y_t = c_t ⊙ h_t\\r\\n    ```\\r\\n    Final output:\\r\\n    ```\\r\\n    output = concat(y_forward, y_backward) + u ⊙ D\\r\\n    ```\\r\\n    code:\\r\\n\\r\\n    for i in range(L):\\r\\n        x_up = deltaA_up[:, :, i, :] * x_up + deltaB_u_up[:, :, i, :]\\r\\n        x_down = deltaA_down[:, :, L - 1 - i, :] * x_down + deltaB_u_down[:, :, L - 1 - i, :]\\r\\n        y_up[i, :, :] = x_up[0, :, :] * c_up[i, :, 0, :]\\r\\n        y_down[L - 1 - i, :, :] = x_down[0, :, :] * c_down[L - 1 - i, :, 0, :]\\r\\n\\r\\n    y = concat((y_up, y_down), dim=1)\\r\\n    out = y if D is None else y + u * D\\r\\n\\r\\n    3. Input parameters:\\r\\n    u: Input feature map tensor (after linear projection) [N, C, L, Batch]\\r\\n    c: State-to-output projection weights [N, C, L, Batch]\\r\\n    D: Residual connection weights (optional) [N, C]\\r\\n    δA: Discretized state transition matrix [N, C, L, Batch]\\r\\n    δB_u: Combined input projection and discretized control matrix [N, C, L, Batch]\\r\\n\\r\\n    4. Attributes:\\r\\n    direction: Bidirectional scanning scheme (forward & reverse)\\r\\n    time_dim: Sequence length dimension (L = H × W)\\r\\n    channel_split: Channel dimension partitioning factor (C → C//2)\\r\\n    residual: Whether to apply residual connection (D term)\",\n    \"operands\": [\n      { \"name\": \"Cs\", \"type\": \"AnyTensor\" },\n      { \"name\": \"deltaA\", \"type\": \"AnyTensor\" },\n      { \"name\": \"deltaB_u\", \"type\": \"AnyTensor\" },\n      { \"name\": \"us\", \"type\": \"AnyTensor\" },\n      { \"name\": \"Ds\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Shape\",\n    \"summary\": \"Shape operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Takes a tensor as input and outputs an 1D int tensor containing the shape of the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = shape(input[d1, d2,...,dn])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    start(w.): the ending indices for slicing along each axis.;\\r\\n    step: the step sizes for slicing along each axis.;\\r\\n    end: the ending indices for slicing along each axis.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"end\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"step\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.ShuffleChannel\",\n    \"summary\": \"ShuffleChannel operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform ShuffleChannel on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C, H, W) = input(N, Shuffle(C), H, W)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    group: An integer specifying the number of groups to divide the channels into.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sigmoid\",\n    \"summary\": \"Exp operator,  scale * Sigmoid + bias\",\n    \"description\": \"1.Op Introduction\\r\\n    Y = scale * Sigmoid(x) + bias\\r\\n    if log --> Y = Log(scale * Sigmoid(x) + bias)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = scale * Sigmoid(input) + bias\\r\\n\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    scale: a scaling factor applied to the attention scores before they are passed through the softmax function.;\\r\\n    bias: added to the result of the matrix multiplication. ;\\r\\n    log: whether the output should be computed using the logarithm of the scaled sigmoid function. ;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F64Attr, 1>\" },\n      { \"name\": \"bias\", \"type\": \"DefaultValuedAttr<F64Attr, 0>\" },\n      { \"name\": \"log\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sign\",\n    \"summary\": \"Sign Operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculate the sign of the given input tensor element-wise.\\r\\n    If input > 0, output 1. if input < 0, output -1. if input == 0,\\r\\n    output 0.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = SignOp(input) -> 0/1\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.SiLU\",\n    \"summary\": \"SiLU operator,  y = x * Sigmoid(x)\",\n    \"description\": \"1.Op Introduction\\r\\n    An activation function.\\r\\n    Smooth nonlinear transformation is provided to avoid the gradient disappearance problem of ReLU.;\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input * Sigmoid(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sin\",\n    \"summary\": \"Sin operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the Sin of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = sin(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sinh\",\n    \"summary\": \"Sinh operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the Sinh of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = sinh(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Size\",\n    \"summary\": \"Size operator\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch aten::size. The Size operation retrieves the size (or shape) of the given input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = SizeOp(input) ->[dim0, dim1, dim2..., dimN]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension of reverse;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<SI32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Slice\",\n    \"summary\": \"Slice operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Slice Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[offset[j] : ends[j] : steps[j]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    offsetT(w.): the starting indices for each slice along the specified axes.;\\r\\n    endsT(w.): the ending indices for each slice along the specified axes.;\\r\\n    stepsT(w.): the step sizes for each slice along the specified axes.;\\r\\n\\r\\n    4.attribute\\r\\n    offset: An array of the starting indices for slicing along each axis.;\\r\\n    steps: An array of the step sizes for slicing along each axis.;\\r\\n    ends: An array of the ending indices for slicing along each axis.;\\r\\n    axes: An array of the axes along which to perform the slicing operation.;\\r\\n    hasparamConvert_axes: whether parameter conversion is needed for the specified axes.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"offsetT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"endsT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"stepsT\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"steps\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ends\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"axes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"hasparamConvert_axes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"top.SliceAxis\",\n    \"summary\": \"Slice operator on one axis\",\n    \"description\": \"1.Op Introduction\\r\\n    Slice Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[starts[j] + i * strides[j]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    axis(w.): the dimension of the input tensor.;\\r\\n    start(w.): the ending indices for slicing along each axis.;\\r\\n    step: the step sizes for slicing along each axis.;\\r\\n    end: the ending indices for slicing along each axis.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"axis\", \"type\": \"AnyTensor\" },\n      { \"name\": \"start\", \"type\": \"AnyTensor\" },\n      { \"name\": \"step\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"end\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Softmax\",\n    \"summary\": \"Softmax operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to softmax.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            \\\\text{output}[i] = \\\\frac{e^{\\\\text{input}[i]}}{\\\\sum_{j} e^{\\\\text{input}[j]}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    log: when set to true, indicates that the output should be computed in log space.;\\r\\n    beta: scaling factor.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"log\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.SoftmaxBwd\",\n    \"summary\": \"softmax backward operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to softmax backward.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            grad_input[i] = softmax(output)[i] * (grad_output[i] - \\\\sum{j}grad_output[j] * softmax(output)[j])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    output(act.): output tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    dim: If set to 0, computed across rows, If set to 1, computed across columns.;\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Softplus\",\n    \"summary\": \"Softplus operation\",\n    \"description\": \"1.Op Introduction\\r\\n    a smooth approximation of the ReLU (Rectified Linear Unit) activation function.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ln(exp(input) + 1)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Softsign\",\n    \"summary\": \"Softsign Operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Softsign operation is an activation function that provides a smooth approximation of the sign function.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input / (1 + |input|)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sort\",\n    \"summary\": \"Sort operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to Sort.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Sort(input, axis, descending)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    descending: the order of sorting.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"descending\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Split\",\n    \"summary\": \"Split operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Split input tensor into a list of tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input[i * split_size: (i + 1) * split_size] for i = 0, 1, ... num - 1\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension of split;\\r\\n    num: the number of equal parts to split the input tensor into along the specified axis.;\\r\\n    split_size: the exact sizes of each split along the specified axis.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"num\", \"type\": \"I64Attr\" },\n      { \"name\": \"split_size\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sqrt\",\n    \"summary\": \"Sqrt operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Computes the square root of the input tensor's element.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Sqrt(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Squeeze\",\n    \"summary\": \"Squeeze operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The operator squeeze the input shapes by given axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = squeeze(input, axes)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.StridedSlice\",\n    \"summary\": \"Strided Slice operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Strided Slice Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[starts[j] + i * strides[j]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    starts(w.): the starting indices for each dimension of the input tensor.;\\r\\n    ends(w.): the ending indices for each dimension of the input tensor.;\\r\\n    strides(w.):  the stride values for each dimension, determining the step size between indices in the slicing operation.;\\r\\n\\r\\n    4.attribute\\r\\n    begin_mask: If set, the start index for that dimension is considered as 0.;\\r\\n    end_mask: If set, the end index for that dimension is considered as the size of the dimension.;\\r\\n    ellipsis_mask: whether allowing for the selection of all dimensions in between specified slices.;\\r\\n    new_axis_mask: which dimensions should be added as new axes in the output tensor.;\\r\\n    shrink_axis_mask: which dimensions should be removed from the output tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"starts\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ends\", \"type\": \"AnyTensor\" },\n      { \"name\": \"strides\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"end_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Sub\",\n    \"summary\": \"sub operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise subtraction of input1 and input2. Axis of size 1 will be broadcast,\\r\\n    as necessary.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReLU((input1 - input2; dim))\\r\\n    ```\\r\\n    Axis of size 1 will be broadcast if necessary.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    coeff: It is an array and allows for scaling the output of the addition operation.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"coeff\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.SubConst\",\n    \"summary\": \"Sub Const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise subtraction of input1 and input2. Input1 or Input2 is constant.\\r\\n    as necessary.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input - const_val or const_val - input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    is_reverse: This boolean attribute indicates whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    is_scalar: whether the addition operation is performed with scalar values or tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"is_scalar\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.SwapChannel\",\n    \"summary\": \"swap channel operator, normally RGB <=> BGR\",\n    \"description\": \"1.Op Introduction\\r\\n    Swap Channel on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output(h, w, c) = input(h, w, channel_order)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    channel_order: channel swap order.;\\r\\n    quant: a QuantParam struct attributes.;\\r\\n    name: name for calibration, comparing, or debug.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.SwapDimInner\",\n    \"summary\": \"if offset is not 0, split there and swap first part and second part of it\",\n    \"description\": \"1.Op Introduction\\r\\n    a dimension-swapping operation based on a specified offset.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = SwapDimInner(input, offset)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    offset: the position at which the input tensor is split.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Swish\",\n    \"summary\": \"Swish operation\",\n    \"description\": \"1.Op Introduction\\r\\n    hardswish(x) := x * sigmoid(x * beta)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[i] * sigmoid(input[i] * beta)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    beta: scalar;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"beta\", \"type\": \"F64Attr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.Tan\",\n    \"summary\": \"Tan operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the tan of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Tan(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Tanh\",\n    \"summary\": \"Tanh operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Calculates the tanh of the given input tensor, element-wise.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Tan(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"top.Tile\",\n    \"summary\": \"Tile operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform Tile operation on the given tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i_1, i_2, i_3,...i_k] = input[i_1 mod d_1, i_2 mod d_2, i_3 mod d_3,..., i_k mod d_k]\\r\\n    ```\\r\\n    where d_j represents the corresponding dimension size of the input tensor after tiling.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    tileT(w.): how many times to replicate the input tensor along each dimension.;\\r\\n\\r\\n    4.attributes\\r\\n    tile: the number of times to replicate the input tensor along each dimension.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"tileT\", \"type\": \"Optional<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"top.TopK\",\n    \"summary\": \"TopK operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to topk.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output_values, output_indices = TopK(input, K, axis, largest, sorted)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    K: how many of the largest (or smallest, depending on the largest attribute) values will be returned. defaults is -1;\\r\\n    largest: whether to retrieve the largest or smallest values.;\\r\\n    sorted: whether the output values should be sorted in descending order (if largest is true) or ascending order (if largest is false).;\\r\\n    kT: provide a specific tensor for K values. This allows for dynamic specification of K.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"kT\", \"type\": \"Optional<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"K\", \"type\": \"DefaultValuedAttr<I64Attr, -1>\" },\n      { \"name\": \"largest\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"replace_topk_indices\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Transpose\",\n    \"summary\": \"Transpose operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Transpose on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(dim1, dim0) = TransposeOp(input(dim0, dim1))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    dim0: the first dimension of input tensor.;\\r\\n    dim1: the second dimension of input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim0\", \"type\": \"SI32Attr\" },\n      { \"name\": \"dim1\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Trilu\",\n    \"summary\": \"Trilu operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the upper or lower triangular part of input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Triu(input, diagonal) if upper = 1\\r\\n            output = Tril(input, diagonal) if upper = 0\\r\\n    ```\\r\\n    where, Triu() return the upper triangular part of the input tensor.\\r\\n           Tril() return the lower triangular part of the input tensor.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    upper: whether to extract the upper or lower triangular part of the input tensor.;\\r\\n    diagonal: 0 refers to the main diagonal, positive values indicate diagonals above the main diagonal,\\r\\n              and negative values indicate diagonals below the main diagonal.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper\", \"type\": \"SI32Attr\" },\n      { \"name\": \"diagonal\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Tuple\",\n    \"summary\": \"Tuple operator\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch prim::TupleConstruct, y = (a, b)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = TupleOp(input1, input2)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Unpack\",\n    \"summary\": \"Unpack operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Unpack a tensor to list of tensors in the given dimension.\\r\\n\\r\\n    2.Math formula\\r\\n    output1, output2, output3 = UnPack(input; axis)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    axis: It specifies the dimension along which the input tensors will be packed together.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"top.Unsqueeze\",\n    \"summary\": \"Unsqueeze operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The operator unsqueeze the input shapes by given axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = unsqueeze(input, axes)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.UnTuple\",\n    \"summary\": \"UnTuple operator\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch prim::TupleUnpack, a, b = y\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output1, output2 = UnTupleOp(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Upsample\",\n    \"summary\": \"Upsample operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform nearest upsample on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i, j] = Upsample(input[i / scale_h, j / scale_w])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    scale_h: the scaling factor for the height (number of rows) of the input tensor.;\\r\\n    scale_w: the scaling factor for the width (number of columns) of the input tensor.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"scale_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Variance\",\n    \"summary\": \"Compute Variance operator\",\n    \"description\": \"1.Op Introduction\\r\\n    variance\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\frac{1}{N} \\\\sum_{i=1}^{N} (input_i - mean)^2\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    reduce_list: A list of dimensions along which to compute the variance.;\\r\\n    correction: correction factor.;\\r\\n    keep_dims: whether to keep the dimensions of the output tensor the same as the input tensors.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_list\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"correction\", \"type\": \"F64Attr\" },\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.View\",\n    \"summary\": \"View operation\",\n    \"description\": \"1.Op Introduction\\r\\n    gen by torch aten::view, the view operation allows for changing the shape of the tensor without altering its data.\\r\\n    0: keep dim from input\\r\\n    -1: left dim from input\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ViewOp(input, shape)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    shape(w.): 0: keep dim from input; -1: left dim from input.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shape\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"top.Weight\",\n    \"summary\": \"weight operator\",\n    \"description\": \"If `inline_bytes` is not defined or `inline_bytes` is a null string:\\r\\n      Load weight from a file. The file should be a valid .npz format file.\\r\\n      This Op does not take any input, and the location captures the tensor name.\\r\\n      The Output is an n-dimensional tensor whose type matches\\r\\n      the tensor type in the .npz file.\\r\\n    Else:\\r\\n      Load weight from `inline_bytes`.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"store_mode\", \"type\": \"OptionalAttr<StoreModeAttr>\" },\n      { \"name\": \"allow_split\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"indices_idx\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"indices_slice\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"path\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"do_compress\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"bias0\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"bias1\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"is_signed\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"zero_guard\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"inline_bytes\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"top.WeightReorder\",\n    \"summary\": \"WeightReorder operator\",\n    \"description\": \"1.Op Introduction\\r\\n    reorder Weight.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Reorder(input, reorder_mode)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    reorder_mode: rearranging the weight tensor, such as sorting, shuffling, or applying a specific permutation.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reorder_mode\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Where\",\n    \"summary\": \"Where operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Return elements, either from X or Y, depending on condition.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = tbrn if condition else fbrn\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    cond(act.): a tensor that serves as the condition for selecting elements from the true branch (tbrn) or the false branch (fbrn).;\\r\\n    tbrn(w.): the tensor that will be selected when the condition is true.;\\r\\n    fbrn(w.): the tensor that will be selected when the condition is false.;\\r\\n\\r\\n    4.attributes\\r\\n    x_is_const: the tensor for the true branch (tbrn) is a constant.;\\r\\n    y_is_const: the tensor for the false branch (fbrn) is a constant.;\\r\\n    x_const_val: the constant value to be used for the true branch if tbrn is not provided or is constant.;\\r\\n    y_const_val: the constant value to be used for the false branch if fbrn is not provided or is constant.;\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"AnyTensor\" },\n      { \"name\": \"tbrn\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"fbrn\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"x_is_const\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"y_is_const\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"x_const_val\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"y_const_val\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Yield\",\n    \"summary\": \"Yield operation\",\n    \"description\": \"1.Op Introduction\\r\\n    The `top.Yield` operation represents a return operation within an subgraph.\\r\\n    The operation takes variable number of operands and produces no results.\\r\\n    This operation is not part of the standard and was added to assist tpu-mlr.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Yield(operands)\\r\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"top.YoloDetection\",\n    \"summary\": \"YoloDetection operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform yolo detection on feature map.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Feature Map output\\r\\n            raw_predictions = {(b_i, c_i, p_i) | i = 1, 2,...,N}\\r\\n            b_i is the bounding box coordinates, c_i is the i-th class score, p_i is the i-th obj score.\\r\\n        2.Apply Objectness Threshold\\r\\n            filtered_predictions = {(b_i, c_i, p_i) | p_i >= obj_threshold}\\r\\n        3.Non-Maximum Suppression(NMS)\\r\\n            nms_output = NMS(filtered_predictions, nms_threshold)\\r\\n        4.Top K Detections\\r\\n            output = top_k(nms_output, keep_topk)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    net_input_h: The height of the input image.;\\r\\n    net_input_w: The width of the input image;\\r\\n    nms_threshold: The threshold used for Non-Maximum Suppression (NMS).;\\r\\n    obj_threshold: The minimum confidence score required for an object detection to be considered valid.;\\r\\n    keep_topk: The maximum number of detections to keep after applying NMS.;\\r\\n    anchors: A list of anchor box dimensions.;\\r\\n    version: The version of the YOLO model being used.;\\r\\n    class_num: The number of classes that the YOLO model can predict.;\\r\\n    num_boxes: The number of bounding boxes that the model predicts for each grid cell in the feature map.;\\r\\n    agnostic_nms: whether to use class-agnostic NMS.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"net_input_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"net_input_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"obj_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"keep_topk\", \"type\": \"I64Attr\" },\n      { \"name\": \"anchors\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"version\", \"type\": \"YoloVersionAttr\" },\n      { \"name\": \"class_num\", \"type\": \"DefaultValuedAttr<I64Attr, 80>\" },\n      { \"name\": \"num_boxes\", \"type\": \"DefaultValuedAttr<I64Attr, 3>\" },\n      { \"name\": \"agnostic_nms\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"top.Yuv2rgbFormula\",\n    \"summary\": \"Yuv2rgb formula operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Yuv2rgb formula Operator.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            (R) = (Y + 1.402 x (V - 128))\\r\\n            (G) = (Y - 0.344136 x (U - 128) - 0.714136 x (V - 128))\\r\\n            (B) = (Y + 1.772 x (U - 128))\\r\\n\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    YUV(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    src_format: the source format of the input YUV data.;\\r\\n    dst_format: the desired destination format for the output RGB data.;\\r\\n    image_format: how the YUV data should be processed and how the output RGB data should be structured.;\\r\\n    formula_mode: the mode of the conversion formula used for the YUV to RGB transformation. ;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\",\n    \"operands\": [\n      { \"name\": \"YUV\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src_format\", \"type\": \"UI32Attr\" },\n      { \"name\": \"dst_format\", \"type\": \"UI32Attr\" },\n      { \"name\": \"image_format\", \"type\": \"ImageOutFormatAttr\" },\n      { \"name\": \"formula_mode\", \"type\": \"Yuv2rgbFormulaAttr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<RoundModeAttr, \\\"HalfAwayFromZero\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"torch_c.from_builtin_tensor\",\n    \"summary\": \"Convert a `tensor` to a `!torch.vtensor`\",\n    \"description\": \"This op only operates on ValueTensorType, to avoid conflating conversions\\n    between value-semantic and non-value-semantic types.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_ValueTensorType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($operand)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch_c.from_f64\",\n    \"summary\": \"Convert an `f64` to a `!torch.float`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.from_i1\",\n    \"summary\": \"Convert an `i1` to a `!torch.bool`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.from_i64\",\n    \"summary\": \"Convert an `i64` to a `!torch.int`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.generator_to_i64\",\n    \"summary\": \"Convert a `Generator` to a `i64`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_GeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.get_next_seed\",\n    \"summary\": \"Get the next global seed\",\n    \"description\": \"This op is for getting the next global seed for RNG\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` `(``)` `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch_c.i64_to_generator\",\n    \"summary\": \"Convert an `i64` to an `Generator`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_GeneratorType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.to_builtin_tensor\",\n    \"summary\": \"Convert a `!torch.vtensor` to a `tensor`\",\n    \"description\": \"This op only operates on ValueTensorType, to avoid conflating conversions\\n    between value-semantic and non-value-semantic types.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_ValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($operand)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch_c.to_f64\",\n    \"summary\": \"Convert a `!torch.float` to an `f64`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.to_i1\",\n    \"summary\": \"Convert a `!torch.bool` to an `i1`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch_c.to_i64\",\n    \"summary\": \"Convert a `!torch.int` to an `i64`\",\n    \"description\": \"This op is primarily useful as a materialization during dialect conversion.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict\"\n  },\n  {\n    \"name\": \"torch.aten.__and__.bool\",\n    \"summary\": \"Generated op for `aten::__and__.bool : (bool, bool) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"b\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__and__.Scalar\",\n    \"summary\": \"Generated op for `aten::__and__.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__and__.Tensor\",\n    \"summary\": \"Generated op for `aten::__and__.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__contains__.int_list\",\n    \"summary\": \"Generated op for `aten::__contains__.int_list : (int[], int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"item\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__contains__.str\",\n    \"summary\": \"Generated op for `aten::__contains__.str : (Dict(str, t), str) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"dict\", \"type\": \"Torch_DictType\" },\n      { \"name\": \"key\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__contains__.str_list\",\n    \"summary\": \"Generated op for `aten::__contains__.str_list : (str[], str) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"AnyTorchListOfTorchStringType\" },\n      { \"name\": \"item\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__derive_index\",\n    \"summary\": \"Generated op for `aten::__derive_index : (int, int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__getitem__.Dict_str\",\n    \"summary\": \"Generated op for `aten::__getitem__.Dict_str : (Dict(str, t), str) -> (t)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_DictType\" },\n      { \"name\": \"key\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__getitem__.t\",\n    \"summary\": \"Generated op for `aten::__getitem__.t : (t[], int) -> (t)`\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"idx\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__interpolate.size_list_scale_list\",\n    \"summary\": \"Generated op for `aten::__interpolate.size_list_scale_list : (Tensor, int[]?, float[]?, str, bool?, bool?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"scale_factor\", \"type\": \"AnyTorchOptionalListOfTorchFloatType\" },\n      { \"name\": \"mode\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"align_corners\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"recompute_scale_factor\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"antialias\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__is__\",\n    \"summary\": \"Generated op for `aten::__is__ : (t1, t2) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchType\" },\n      { \"name\": \"obj\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__isnot__\",\n    \"summary\": \"Generated op for `aten::__isnot__ : (t1, t2) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchType\" },\n      { \"name\": \"obj\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__lshift__.Scalar\",\n    \"summary\": \"Generated op for `aten::__lshift__.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__not__\",\n    \"summary\": \"Generated op for `aten::__not__ : (bool) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__or__.bool\",\n    \"summary\": \"Generated op for `aten::__or__.bool : (bool, bool) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"b\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__or__.Tensor\",\n    \"summary\": \"Generated op for `aten::__or__.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__range_length\",\n    \"summary\": \"Generated op for `aten::__range_length : (int, int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"lo\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"hi\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.__rshift__.Scalar\",\n    \"summary\": \"Generated op for `aten::__rshift__.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._adaptive_avg_pool2d\",\n    \"summary\": \"Generated op for `aten::_adaptive_avg_pool2d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._adaptive_avg_pool2d_backward\",\n    \"summary\": \"Generated op for `aten::_adaptive_avg_pool2d_backward : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._adaptive_avg_pool3d\",\n    \"summary\": \"Generated op for `aten::_adaptive_avg_pool3d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._adaptive_avg_pool3d_backward\",\n    \"summary\": \"Generated op for `aten::_adaptive_avg_pool3d_backward : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._assert_scalar\",\n    \"summary\": \"Generated op for `aten::_assert_scalar : (Scalar, str) -> ()`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"assert_msg\", \"type\": \"Torch_StringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._assert_tensor_metadata\",\n    \"summary\": \"Generated op for `aten::_assert_tensor_metadata : (Tensor, int[]?, int[]?, int?, Device?, int?) -> ()`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._cast_Float\",\n    \"summary\": \"Generated op for `aten::_cast_Float : (Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._cast_Long\",\n    \"summary\": \"Generated op for `aten::_cast_Long : (Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._convolution\",\n    \"summary\": \"Generated op for `aten::_convolution : (Tensor, Tensor, Tensor?, int[], int[], int[], bool, int[], int, bool, bool, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"transposed\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"benchmark\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"deterministic\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"cudnn_enabled\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"allow_tf32\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._convolution.deprecated\",\n    \"summary\": \"Generated op for `aten::_convolution.deprecated : (Tensor, Tensor, Tensor?, int[], int[], int[], bool, int[], int, bool, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"transposed\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"benchmark\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"deterministic\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"cudnn_enabled\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._embedding_bag\",\n    \"summary\": \"Generated op for `aten::_embedding_bag : (Tensor, Tensor, Tensor, bool, int, bool, Tensor?, bool, int) -> (Tensor, Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offsets\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale_grad_by_freq\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"mode\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"sparse\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"per_sample_weights\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"include_last_offset\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"padding_idx\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result3\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._fake_quantize_per_tensor_affine_cachemask_tensor_qparams\",\n    \"summary\": \"Generated op for `aten::_fake_quantize_per_tensor_affine_cachemask_tensor_qparams : (Tensor, Tensor, Tensor, Tensor, int, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"fake_quant_enabled\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"quant_min\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_max\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._index_put_impl\",\n    \"summary\": \"Generated op for `aten::_index_put_impl : (Tensor, Tensor?[], Tensor, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfOptionalTensorType\" },\n      { \"name\": \"values\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"unsafe\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._index_put_impl_\",\n    \"summary\": \"Generated op for `aten::_index_put_impl_ : (Tensor, Tensor?[], Tensor, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfOptionalNonValueTensorType\" },\n      { \"name\": \"values\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"unsafe\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._int_mm\",\n    \"summary\": \"Generated op for `aten::_int_mm : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mat2\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._linalg_det\",\n    \"summary\": \"Generated op for `aten::_linalg_det : (Tensor) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"LU\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"pivots\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._log_softmax\",\n    \"summary\": \"Generated op for `aten::_log_softmax : (Tensor, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"half_to_float\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._log_softmax_backward_data\",\n    \"summary\": \"Generated op for `aten::_log_softmax_backward_data : (Tensor, Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"input_dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._make_per_channel_quantized_tensor\",\n    \"summary\": \"Generated op for `aten::_make_per_channel_quantized_tensor : (Tensor, Tensor, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"axis\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._make_per_tensor_quantized_tensor\",\n    \"summary\": \"Generated op for `aten::_make_per_tensor_quantized_tensor : (Tensor, float, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"zero_point\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._reshape_alias\",\n    \"summary\": \"Generated op for `aten::_reshape_alias : (Tensor, int[], int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._reshape_alias_copy\",\n    \"summary\": \"Generated op for `aten::_reshape_alias_copy : (Tensor, int[], int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._safe_softmax\",\n    \"summary\": \"Generated op for `aten::_safe_softmax : (Tensor, int, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._set_item.str\",\n    \"summary\": \"Generated op for `aten::_set_item.str : (Dict(str, t), str, t) -> ()`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"Torch_DictType\" },\n      { \"name\": \"idx\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"v\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._set_item.t\",\n    \"summary\": \"Generated op for `aten::_set_item.t : (t[], int, t) -> (t[])`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"idx\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"el\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._shape_as_tensor\",\n    \"summary\": \"Generated op for `aten::_shape_as_tensor : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._softmax\",\n    \"summary\": \"Generated op for `aten::_softmax : (Tensor, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"half_to_float\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._softmax_backward_data\",\n    \"summary\": \"Generated op for `aten::_softmax_backward_data : (Tensor, Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"input_dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._to_copy\",\n    \"summary\": \"Generated op for `aten::_to_copy : (Tensor, int?, int?, Device?, bool?, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._trilinear\",\n    \"summary\": \"Generated op for `aten::_trilinear : (Tensor, Tensor, Tensor, int[], int[], int[], int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"i1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"i2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"i3\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"expand1\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"expand2\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"expand3\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"sumdim\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"unroll_dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._unsafe_index_put.hacked_twin\",\n    \"summary\": \"Generated op for `aten::_unsafe_index_put.hacked_twin : (Tensor, Tensor[], Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfTensorType\" },\n      { \"name\": \"values\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._unsafe_view\",\n    \"summary\": \"Generated op for `aten::_unsafe_view : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten._weight_norm_interface\",\n    \"summary\": \"Generated op for `aten::_weight_norm_interface : (Tensor, Tensor, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"v\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"g\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.abs\",\n    \"summary\": \"Generated op for `aten::abs : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.abs_\",\n    \"summary\": \"Generated op for `aten::abs_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.acos\",\n    \"summary\": \"Generated op for `aten::acos : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.acos_\",\n    \"summary\": \"Generated op for `aten::acos_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.acosh\",\n    \"summary\": \"Generated op for `aten::acosh : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.acosh_\",\n    \"summary\": \"Generated op for `aten::acosh_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.adaptive_avg_pool1d\",\n    \"summary\": \"Generated op for `aten::adaptive_avg_pool1d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.adaptive_avg_pool2d\",\n    \"summary\": \"Generated op for `aten::adaptive_avg_pool2d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.adaptive_avg_pool3d\",\n    \"summary\": \"Generated op for `aten::adaptive_avg_pool3d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.adaptive_max_pool1d\",\n    \"summary\": \"Generated op for `aten::adaptive_max_pool1d : (Tensor, int[]) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.adaptive_max_pool2d\",\n    \"summary\": \"Generated op for `aten::adaptive_max_pool2d : (Tensor, int[]) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.adaptive_max_pool3d\",\n    \"summary\": \"Generated op for `aten::adaptive_max_pool3d : (Tensor, int[]) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add\",\n    \"summary\": \"Generated op for `aten::add : (Scalar, Scalar) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add_.Scalar\",\n    \"summary\": \"Generated op for `aten::add_.Scalar : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add_.Tensor\",\n    \"summary\": \"Generated op for `aten::add_.Tensor : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add.float_int\",\n    \"summary\": \"Generated op for `aten::add.float_int : (float, int) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add.int\",\n    \"summary\": \"Generated op for `aten::add.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add.Scalar\",\n    \"summary\": \"Generated op for `aten::add.Scalar : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add.str\",\n    \"summary\": \"Generated op for `aten::add.str : (str, str) -> (str)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"b\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_StringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add.t\",\n    \"summary\": \"Generated op for `aten::add.t : (t[], t[]) -> (t[])`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.add.Tensor\",\n    \"summary\": \"Generated op for `aten::add.Tensor : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.addcdiv\",\n    \"summary\": \"Generated op for `aten::addcdiv : (Tensor, Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"tensor1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"tensor2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.addcdiv_\",\n    \"summary\": \"Generated op for `aten::addcdiv_ : (Tensor, Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"tensor1\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"tensor2\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.addcmul\",\n    \"summary\": \"Generated op for `aten::addcmul : (Tensor, Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"tensor1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"tensor2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.addcmul_\",\n    \"summary\": \"Generated op for `aten::addcmul_ : (Tensor, Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"tensor1\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"tensor2\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.addmm\",\n    \"summary\": \"Generated op for `aten::addmm : (Tensor, Tensor, Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mat1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mat2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"beta\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.alias\",\n    \"summary\": \"Generated op for `aten::alias : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.alias_copy\",\n    \"summary\": \"Generated op for `aten::alias_copy : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.all\",\n    \"summary\": \"Generated op for `aten::all : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.all.bool\",\n    \"summary\": \"Generated op for `aten::all.bool : (bool[]) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListOfTorchBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.all.dim\",\n    \"summary\": \"Generated op for `aten::all.dim : (Tensor, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.amax\",\n    \"summary\": \"Generated op for `aten::amax : (Tensor, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.amin\",\n    \"summary\": \"Generated op for `aten::amin : (Tensor, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.aminmax\",\n    \"summary\": \"Generated op for `aten::aminmax : (Tensor, int?, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.any\",\n    \"summary\": \"Generated op for `aten::any : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.any.bool\",\n    \"summary\": \"Generated op for `aten::any.bool : (bool[]) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListOfTorchBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.any.dim\",\n    \"summary\": \"Generated op for `aten::any.dim : (Tensor, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.any.dims\",\n    \"summary\": \"Generated op for `aten::any.dims : (Tensor, int[]?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.append.t\",\n    \"summary\": \"Generated op for `aten::append.t : (t[], t) -> (t[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"el\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.arange\",\n    \"summary\": \"Generated op for `aten::arange : (Scalar, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"end\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.arange.start\",\n    \"summary\": \"Generated op for `aten::arange.start : (Scalar, Scalar, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.arange.start_out\",\n    \"summary\": \"Generated op for `aten::arange.start_out : (Scalar, Scalar, Scalar, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"step\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"out\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.arange.start_step\",\n    \"summary\": \"Generated op for `aten::arange.start_step : (Scalar, Scalar, Scalar, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"step\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.argmax\",\n    \"summary\": \"Generated op for `aten::argmax : (Tensor, int?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.argmin\",\n    \"summary\": \"Generated op for `aten::argmin : (Tensor, int?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.argsort\",\n    \"summary\": \"Generated op for `aten::argsort : (Tensor, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"descending\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.as_strided\",\n    \"summary\": \"Generated op for `aten::as_strided : (Tensor, int[], int[], int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"storage_offset\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.as_strided_copy\",\n    \"summary\": \"Generated op for `aten::as_strided_copy : (Tensor, int[], int[], int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"storage_offset\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.as_strided_scatter\",\n    \"summary\": \"Generated op for `aten::as_strided_scatter : (Tensor, Tensor, int[], int[], int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"storage_offset\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.asin\",\n    \"summary\": \"Generated op for `aten::asin : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.asin_\",\n    \"summary\": \"Generated op for `aten::asin_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.asinh\",\n    \"summary\": \"Generated op for `aten::asinh : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.asinh_\",\n    \"summary\": \"Generated op for `aten::asinh_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atan\",\n    \"summary\": \"Generated op for `aten::atan : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atan_\",\n    \"summary\": \"Generated op for `aten::atan_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atan2\",\n    \"summary\": \"Generated op for `aten::atan2 : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atan2_\",\n    \"summary\": \"Generated op for `aten::atan2_ : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atanh\",\n    \"summary\": \"Generated op for `aten::atanh : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atanh_\",\n    \"summary\": \"Generated op for `aten::atanh_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atleast_1d\",\n    \"summary\": \"Generated op for `aten::atleast_1d : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.atleast_2d\",\n    \"summary\": \"Generated op for `aten::atleast_2d : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.avg_pool1d\",\n    \"summary\": \"Generated op for `aten::avg_pool1d : (Tensor, int[], int[], int[], bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"count_include_pad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.avg_pool2d\",\n    \"summary\": \"Generated op for `aten::avg_pool2d : (Tensor, int[], int[], int[], bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"count_include_pad\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"divisor_override\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.avg_pool2d_backward\",\n    \"summary\": \"Generated op for `aten::avg_pool2d_backward : (Tensor, Tensor, int[], int[], int[], bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"count_include_pad\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"divisor_override\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.avg_pool3d\",\n    \"summary\": \"Generated op for `aten::avg_pool3d : (Tensor, int[], int[], int[], bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"count_include_pad\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"divisor_override\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.avg_pool3d_backward\",\n    \"summary\": \"Generated op for `aten::avg_pool3d_backward : (Tensor, Tensor, int[], int[], int[], bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"count_include_pad\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"divisor_override\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.baddbmm\",\n    \"summary\": \"Generated op for `aten::baddbmm : (Tensor, Tensor, Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"batch1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"batch2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"beta\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.baddbmm_\",\n    \"summary\": \"Generated op for `aten::baddbmm_ : (Tensor, Tensor, Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"batch1\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"batch2\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"beta\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.batch_norm\",\n    \"summary\": \"Generated op for `aten::batch_norm : (Tensor, Tensor?, Tensor?, Tensor?, Tensor?, bool, float, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"momentum\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"cudnn_enabled\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bernoulli\",\n    \"summary\": \"Generated op for `aten::bernoulli : (Tensor, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bernoulli_.float\",\n    \"summary\": \"Generated op for `aten::bernoulli_.float : (Tensor, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bernoulli_.Tensor\",\n    \"summary\": \"Generated op for `aten::bernoulli_.Tensor : (Tensor, Tensor, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bernoulli.p\",\n    \"summary\": \"Generated op for `aten::bernoulli.p : (Tensor, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bernoulli.Tensor\",\n    \"summary\": \"Generated op for `aten::bernoulli.Tensor : (Tensor, Tensor, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.binary_cross_entropy\",\n    \"summary\": \"Generated op for `aten::binary_cross_entropy : (Tensor, Tensor, Tensor?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.binary_cross_entropy_backward\",\n    \"summary\": \"Generated op for `aten::binary_cross_entropy_backward : (Tensor, Tensor, Tensor, Tensor?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.binary_cross_entropy_with_logits\",\n    \"summary\": \"Generated op for `aten::binary_cross_entropy_with_logits : (Tensor, Tensor, Tensor?, Tensor?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"pos_weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bincount\",\n    \"summary\": \"Generated op for `aten::bincount : (Tensor, Tensor?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weights\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"minlength\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_and_.Scalar\",\n    \"summary\": \"Generated op for `aten::bitwise_and_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_and_.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_and_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_and.Scalar\",\n    \"summary\": \"Generated op for `aten::bitwise_and.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_and.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_and.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_left_shift_.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_left_shift_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_left_shift.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_left_shift.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_not\",\n    \"summary\": \"Generated op for `aten::bitwise_not : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_not_\",\n    \"summary\": \"Generated op for `aten::bitwise_not_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_or_.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_or_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_or.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_or.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_right_shift_.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_right_shift_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_right_shift.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_right_shift.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_xor_.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_xor_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bitwise_xor.Tensor\",\n    \"summary\": \"Generated op for `aten::bitwise_xor.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bmm\",\n    \"summary\": \"Generated op for `aten::bmm : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mat2\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Bool.float\",\n    \"summary\": \"Generated op for `aten::Bool.float : (float) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Bool.int\",\n    \"summary\": \"Generated op for `aten::Bool.int : (int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Bool.Tensor\",\n    \"summary\": \"Generated op for `aten::Bool.Tensor : (Tensor) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.broadcast_tensors\",\n    \"summary\": \"Generated op for `aten::broadcast_tensors : (Tensor[]) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.broadcast_to\",\n    \"summary\": \"Generated op for `aten::broadcast_to : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.bucketize.Tensor\",\n    \"summary\": \"Generated op for `aten::bucketize.Tensor : (Tensor, Tensor, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"boundaries\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"out_int32\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"right\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cat\",\n    \"summary\": \"Generated op for `aten::cat : (Tensor[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ceil\",\n    \"summary\": \"Generated op for `aten::ceil : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ceil_\",\n    \"summary\": \"Generated op for `aten::ceil_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ceil.float\",\n    \"summary\": \"Generated op for `aten::ceil.float : (float) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ceil.Scalar\",\n    \"summary\": \"Generated op for `aten::ceil.Scalar : (Scalar) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.celu\",\n    \"summary\": \"Generated op for `aten::celu : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.celu_\",\n    \"summary\": \"Generated op for `aten::celu_ : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.channel_shuffle\",\n    \"summary\": \"Generated op for `aten::channel_shuffle : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.chunk\",\n    \"summary\": \"Generated op for `aten::chunk : (Tensor, int, int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"chunks\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp\",\n    \"category\": \"Activation\",\n    \"summary\": \"Generated op for `aten::clamp : (Tensor, Scalar?, Scalar?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_\",\n    \"summary\": \"Generated op for `aten::clamp_ : (Tensor, Scalar?, Scalar?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_.Tensor\",\n    \"summary\": \"Generated op for `aten::clamp_.Tensor : (Tensor, Tensor?, Tensor?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalNonValueTensorType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_max\",\n    \"summary\": \"Generated op for `aten::clamp_max : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_max_\",\n    \"summary\": \"Generated op for `aten::clamp_max_ : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_max_.Tensor\",\n    \"summary\": \"Generated op for `aten::clamp_max_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"max\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_max.Tensor\",\n    \"summary\": \"Generated op for `aten::clamp_max.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_min\",\n    \"summary\": \"Generated op for `aten::clamp_min : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_min_\",\n    \"summary\": \"Generated op for `aten::clamp_min_ : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_min_.Tensor\",\n    \"summary\": \"Generated op for `aten::clamp_min_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"min\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp_min.Tensor\",\n    \"summary\": \"Generated op for `aten::clamp_min.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clamp.Tensor\",\n    \"summary\": \"Generated op for `aten::clamp.Tensor : (Tensor, Tensor?, Tensor?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.clone\",\n    \"summary\": \"Generated op for `aten::clone : (Tensor, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.col2im\",\n    \"summary\": \"Generated op for `aten::col2im : (Tensor, int[], int[], int[], int[], int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.column_stack\",\n    \"summary\": \"Generated op for `aten::column_stack : (Tensor[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.complex\",\n    \"summary\": \"Generated op for `aten::complex : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"real\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"imag\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.constant_pad_nd\",\n    \"summary\": \"Generated op for `aten::constant_pad_nd : (Tensor, int[], Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"pad\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.contiguous\",\n    \"summary\": \"Generated op for `aten::contiguous : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"memory_format\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv_tbc\",\n    \"summary\": \"Generated op for `aten::conv_tbc : (Tensor, Tensor, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"pad\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv_tbc_backward\",\n    \"summary\": \"Generated op for `aten::conv_tbc_backward : (Tensor, Tensor, Tensor, Tensor, int) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"pad\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv_transpose1d\",\n    \"summary\": \"Generated op for `aten::conv_transpose1d : (Tensor, Tensor, Tensor?, int[], int[], int[], int, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv_transpose2d.input\",\n    \"summary\": \"Generated op for `aten::conv_transpose2d.input : (Tensor, Tensor, Tensor?, int[], int[], int[], int, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv_transpose3d.input\",\n    \"summary\": \"Generated op for `aten::conv_transpose3d.input : (Tensor, Tensor, Tensor?, int[], int[], int[], int, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv1d\",\n    \"summary\": \"Generated op for `aten::conv1d : (Tensor, Tensor, Tensor?, int[], int[], int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv1d.padding\",\n    \"summary\": \"Generated op for `aten::conv1d.padding : (Tensor, Tensor, Tensor?, int[], str, int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv2d\",\n    \"category\": \"Layer\",\n    \"summary\": \"Generated op for `aten::conv2d : (Tensor, Tensor, Tensor?, int[], int[], int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv2d.padding\",\n    \"summary\": \"Generated op for `aten::conv2d.padding : (Tensor, Tensor, Tensor?, int[], str, int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv3d\",\n    \"category\": \"Layer\",\n    \"summary\": \"Generated op for `aten::conv3d : (Tensor, Tensor, Tensor?, int[], int[], int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.conv3d.padding\",\n    \"summary\": \"Generated op for `aten::conv3d.padding : (Tensor, Tensor, Tensor?, int[], str, int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.convolution\",\n    \"category\": \"Layer\",\n    \"summary\": \"Generated op for `aten::convolution : (Tensor, Tensor, Tensor?, int[], int[], int[], bool, int[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"transposed\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.convolution_backward\",\n    \"summary\": \"Generated op for `aten::convolution_backward : (Tensor, Tensor, Tensor, int[]?, int[], int[], int[], bool, int[], int, bool[]) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias_sizes\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"transposed\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"output_mask\", \"type\": \"AnyTorchListOfTorchBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.copy\",\n    \"summary\": \"Generated op for `aten::copy : (Tensor, Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.copy_\",\n    \"summary\": \"Generated op for `aten::copy_ : (Tensor, Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"src\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.copysign_.Tensor\",\n    \"summary\": \"Generated op for `aten::copysign_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.copysign.Tensor\",\n    \"summary\": \"Generated op for `aten::copysign.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cos\",\n    \"summary\": \"Generated op for `aten::cos : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cos_\",\n    \"summary\": \"Generated op for `aten::cos_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cosh\",\n    \"summary\": \"Generated op for `aten::cosh : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cosh_\",\n    \"summary\": \"Generated op for `aten::cosh_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cosine_embedding_loss\",\n    \"summary\": \"Generated op for `aten::cosine_embedding_loss : (Tensor, Tensor, Tensor, float, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"input2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"margin\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cosine_similarity\",\n    \"summary\": \"Generated op for `aten::cosine_similarity : (Tensor, Tensor, int, float) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"x1\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"x2\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.count_nonzero\",\n    \"summary\": \"Generated op for `aten::count_nonzero : (Tensor, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.count_nonzero.dim_IntList\",\n    \"summary\": \"Generated op for `aten::count_nonzero.dim_IntList : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cpu\",\n    \"summary\": \"Generated op for `aten::cpu : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cross_entropy_loss\",\n    \"summary\": \"Generated op for `aten::cross_entropy_loss : (Tensor, Tensor, Tensor?, int, int, float) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"ignore_index\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"label_smoothing\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cuda\",\n    \"summary\": \"Generated op for `aten::cuda : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cumprod\",\n    \"summary\": \"Generated op for `aten::cumprod : (Tensor, int, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.cumsum\",\n    \"summary\": \"Generated op for `aten::cumsum : (Tensor, int, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.deg2rad\",\n    \"summary\": \"Generated op for `aten::deg2rad : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Delete.Dict_str\",\n    \"summary\": \"Generated op for `aten::Delete.Dict_str : (Dict(str, t), str) -> ()`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_DictType\" },\n      { \"name\": \"key\", \"type\": \"Torch_StringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.dequantize.self\",\n    \"summary\": \"Generated op for `aten::dequantize.self : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.dequantize.tensor\",\n    \"summary\": \"Generated op for `aten::dequantize.tensor : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"qtensor\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.detach\",\n    \"summary\": \"Generated op for `aten::detach : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.detach_copy\",\n    \"summary\": \"Generated op for `aten::detach_copy : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.device.with_index\",\n    \"summary\": \"Generated op for `aten::device.with_index : (str, int) -> (Device)`\",\n    \"operands\": [\n      { \"name\": \"type\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"index\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_DeviceType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.diag_embed\",\n    \"summary\": \"Generated op for `aten::diag_embed : (Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim1\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim2\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.diagonal\",\n    \"summary\": \"Generated op for `aten::diagonal : (Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim1\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim2\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.diagonal_copy\",\n    \"summary\": \"Generated op for `aten::diagonal_copy : (Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim1\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim2\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.diagonal_scatter\",\n    \"summary\": \"Generated op for `aten::diagonal_scatter : (Tensor, Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim1\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim2\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.dim\",\n    \"summary\": \"Generated op for `aten::dim : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div\",\n    \"summary\": \"Generated op for `aten::div : (Scalar, Scalar) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div_.Scalar\",\n    \"summary\": \"Generated op for `aten::div_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div_.Scalar_mode\",\n    \"summary\": \"Generated op for `aten::div_.Scalar_mode : (Tensor, Scalar, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"rounding_mode\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div_.Tensor\",\n    \"summary\": \"Generated op for `aten::div_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div_.Tensor_mode\",\n    \"summary\": \"Generated op for `aten::div_.Tensor_mode : (Tensor, Tensor, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"rounding_mode\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div.float\",\n    \"summary\": \"Generated op for `aten::div.float : (float, float) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div.int\",\n    \"summary\": \"Generated op for `aten::div.int : (int, int) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div.Scalar\",\n    \"summary\": \"Generated op for `aten::div.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div.Scalar_mode\",\n    \"summary\": \"Generated op for `aten::div.Scalar_mode : (Tensor, Scalar, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"rounding_mode\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div.Tensor\",\n    \"summary\": \"Generated op for `aten::div.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.div.Tensor_mode\",\n    \"summary\": \"Generated op for `aten::div.Tensor_mode : (Tensor, Tensor, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"rounding_mode\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.dot\",\n    \"summary\": \"Generated op for `aten::dot : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"tensor\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.dropout\",\n    \"summary\": \"Generated op for `aten::dropout : (Tensor, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"train\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.dropout_\",\n    \"summary\": \"Generated op for `aten::dropout_ : (Tensor, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"train\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.einsum\",\n    \"summary\": \"Generated op for `aten::einsum : (str, Tensor[], int[]?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"equation\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" },\n      { \"name\": \"path\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.elu\",\n    \"summary\": \"Generated op for `aten::elu : (Tensor, Scalar, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"input_scale\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.elu_\",\n    \"summary\": \"Generated op for `aten::elu_ : (Tensor, Scalar, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"input_scale\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.elu_backward\",\n    \"summary\": \"Generated op for `aten::elu_backward : (Tensor, Scalar, Scalar, Scalar, bool, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"input_scale\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"is_result\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"self_or_result\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.embedding\",\n    \"summary\": \"Generated op for `aten::embedding : (Tensor, Tensor, int, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding_idx\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"scale_grad_by_freq\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"sparse\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.embedding_bag.padding_idx\",\n    \"summary\": \"Generated op for `aten::embedding_bag.padding_idx : (Tensor, Tensor, Tensor, bool, int, bool, Tensor?, bool, int?) -> (Tensor, Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offsets\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale_grad_by_freq\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"mode\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"sparse\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"per_sample_weights\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"include_last_offset\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"padding_idx\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result3\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.embedding_dense_backward\",\n    \"summary\": \"Generated op for `aten::embedding_dense_backward : (Tensor, Tensor, int, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"num_weights\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"padding_idx\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"scale_grad_by_freq\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.empty_like\",\n    \"summary\": \"Generated op for `aten::empty_like : (Tensor, int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.empty_strided\",\n    \"summary\": \"Generated op for `aten::empty_strided : (int[], int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.empty.memory_format\",\n    \"summary\": \"Generated op for `aten::empty.memory_format : (int[], int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq_.Scalar\",\n    \"summary\": \"Generated op for `aten::eq_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq_.Tensor\",\n    \"summary\": \"Generated op for `aten::eq_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.bool\",\n    \"summary\": \"Generated op for `aten::eq.bool : (bool, bool) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"b\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.device\",\n    \"summary\": \"Generated op for `aten::eq.device : (Device, Device) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_DeviceType\" },\n      { \"name\": \"b\", \"type\": \"Torch_DeviceType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.float\",\n    \"summary\": \"Generated op for `aten::eq.float : (float, float) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.int\",\n    \"summary\": \"Generated op for `aten::eq.int : (int, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.int_list\",\n    \"summary\": \"Generated op for `aten::eq.int_list : (int[], int[]) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.Scalar\",\n    \"summary\": \"Generated op for `aten::eq.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.str\",\n    \"summary\": \"Generated op for `aten::eq.str : (str, str) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"b\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eq.Tensor\",\n    \"summary\": \"Generated op for `aten::eq.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.erf\",\n    \"summary\": \"Generated op for `aten::erf : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.erf_\",\n    \"summary\": \"Generated op for `aten::erf_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.erfinv\",\n    \"summary\": \"Generated op for `aten::erfinv : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.erfinv_\",\n    \"summary\": \"Generated op for `aten::erfinv_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.exp\",\n    \"summary\": \"Generated op for `aten::exp : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.exp_\",\n    \"summary\": \"Generated op for `aten::exp_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.exp2\",\n    \"summary\": \"Generated op for `aten::exp2 : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.exp2_\",\n    \"summary\": \"Generated op for `aten::exp2_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.expand\",\n    \"summary\": \"Generated op for `aten::expand : (Tensor, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"implicit\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.expand_as\",\n    \"summary\": \"Generated op for `aten::expand_as : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.expand_copy\",\n    \"summary\": \"Generated op for `aten::expand_copy : (Tensor, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"implicit\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.expm1\",\n    \"summary\": \"Generated op for `aten::expm1 : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.expm1_\",\n    \"summary\": \"Generated op for `aten::expm1_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.exponential\",\n    \"summary\": \"Generated op for `aten::exponential : (Tensor, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lambd\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eye\",\n    \"summary\": \"Generated op for `aten::eye : (int, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"n\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.eye.m\",\n    \"summary\": \"Generated op for `aten::eye.m : (int, int, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"n\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"m\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fake_quantize_per_channel_affine\",\n    \"summary\": \"Generated op for `aten::fake_quantize_per_channel_affine : (Tensor, Tensor, Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"axis\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_min\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_max\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fake_quantize_per_channel_affine_cachemask\",\n    \"summary\": \"Generated op for `aten::fake_quantize_per_channel_affine_cachemask : (Tensor, Tensor, Tensor, int, int, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"axis\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_min\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_max\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fake_quantize_per_tensor_affine\",\n    \"summary\": \"Generated op for `aten::fake_quantize_per_tensor_affine : (Tensor, float, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"zero_point\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_min\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_max\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fake_quantize_per_tensor_affine_cachemask\",\n    \"summary\": \"Generated op for `aten::fake_quantize_per_tensor_affine_cachemask : (Tensor, float, int, int, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"zero_point\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_min\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_max\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fake_quantize_per_tensor_affine.tensor_qparams\",\n    \"summary\": \"Generated op for `aten::fake_quantize_per_tensor_affine.tensor_qparams : (Tensor, Tensor, Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"quant_min\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"quant_max\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fft_fft\",\n    \"summary\": \"Generated op for `aten::fft_fft : (Tensor, int?, int, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"n\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"norm\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fft_ifft\",\n    \"summary\": \"Generated op for `aten::fft_ifft : (Tensor, int?, int, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"n\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"norm\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fft_rfft\",\n    \"summary\": \"Generated op for `aten::fft_rfft : (Tensor, int?, int, str?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"n\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"norm\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fill_.Scalar\",\n    \"summary\": \"Generated op for `aten::fill_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fill_.Tensor\",\n    \"summary\": \"Generated op for `aten::fill_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fill.Scalar\",\n    \"summary\": \"Generated op for `aten::fill.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fill.Tensor\",\n    \"summary\": \"Generated op for `aten::fill.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fix\",\n    \"summary\": \"Generated op for `aten::fix : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fix_\",\n    \"summary\": \"Generated op for `aten::fix_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.flatten.using_ints\",\n    \"summary\": \"Generated op for `aten::flatten.using_ints : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"start_dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"end_dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.flip\",\n    \"summary\": \"Generated op for `aten::flip : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fliplr\",\n    \"summary\": \"Generated op for `aten::fliplr : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.flipud\",\n    \"summary\": \"Generated op for `aten::flipud : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.float_power.Tensor_Tensor\",\n    \"summary\": \"Generated op for `aten::float_power.Tensor_Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"exponent\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Float.Scalar\",\n    \"summary\": \"Generated op for `aten::Float.Scalar : (Scalar) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Float.str\",\n    \"summary\": \"Generated op for `aten::Float.str : (str) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Float.Tensor\",\n    \"summary\": \"Generated op for `aten::Float.Tensor : (Tensor) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.FloatImplicit\",\n    \"summary\": \"Generated op for `aten::FloatImplicit : (Tensor) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.floor\",\n    \"summary\": \"Generated op for `aten::floor : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.floor_\",\n    \"summary\": \"Generated op for `aten::floor_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.floor_divide\",\n    \"summary\": \"Generated op for `aten::floor_divide : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.floor_divide.Scalar\",\n    \"summary\": \"Generated op for `aten::floor_divide.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.floordiv.int\",\n    \"summary\": \"Generated op for `aten::floordiv.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fmax\",\n    \"summary\": \"Generated op for `aten::fmax : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fmin\",\n    \"summary\": \"Generated op for `aten::fmin : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fmod_.Scalar\",\n    \"summary\": \"Generated op for `aten::fmod_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fmod.Scalar\",\n    \"summary\": \"Generated op for `aten::fmod.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.fmod.Tensor\",\n    \"summary\": \"Generated op for `aten::fmod.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.format\",\n    \"summary\": \"Generated op for `aten::format : (...) -> (str)`\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_StringType\" }\n    ],\n    \"assemblyFormat\": \"`(` $operands `)` attr-dict `:` qualified(type($operands)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.aten.frac\",\n    \"summary\": \"Generated op for `aten::frac : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.frac_\",\n    \"summary\": \"Generated op for `aten::frac_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.frobenius_norm.dim\",\n    \"summary\": \"Generated op for `aten::frobenius_norm.dim : (Tensor, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.full\",\n    \"summary\": \"Generated op for `aten::full : (int[], Scalar, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"fill_value\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.full_like\",\n    \"summary\": \"Generated op for `aten::full_like : (Tensor, Scalar, int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"fill_value\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Generated op for `aten::gather : (Tensor, int, Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"sparse_grad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge_.Scalar\",\n    \"summary\": \"Generated op for `aten::ge_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge_.Tensor\",\n    \"summary\": \"Generated op for `aten::ge_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge.float\",\n    \"summary\": \"Generated op for `aten::ge.float : (float, float) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge.float_int\",\n    \"summary\": \"Generated op for `aten::ge.float_int : (float, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge.int\",\n    \"summary\": \"Generated op for `aten::ge.int : (int, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge.Scalar\",\n    \"summary\": \"Generated op for `aten::ge.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ge.Tensor\",\n    \"summary\": \"Generated op for `aten::ge.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gelu\",\n    \"summary\": \"Generated op for `aten::gelu : (Tensor, str) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"approximate\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gelu_backward\",\n    \"summary\": \"Generated op for `aten::gelu_backward : (Tensor, Tensor, str) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"approximate\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.get.default_str\",\n    \"summary\": \"Generated op for `aten::get.default_str : (Dict(str, t), str, t) -> (t)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_DictType\" },\n      { \"name\": \"key\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"default_value\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.glu\",\n    \"summary\": \"Generated op for `aten::glu : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.grid_sampler\",\n    \"summary\": \"Generated op for `aten::grid_sampler : (Tensor, Tensor, int, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"grid\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"interpolation_mode\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"padding_mode\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"align_corners\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.group_norm\",\n    \"summary\": \"Generated op for `aten::group_norm : (Tensor, int, Tensor?, Tensor?, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"num_groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"cudnn_enabled\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt_.Scalar\",\n    \"summary\": \"Generated op for `aten::gt_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt_.Tensor\",\n    \"summary\": \"Generated op for `aten::gt_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt.float\",\n    \"summary\": \"Generated op for `aten::gt.float : (float, float) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt.float_int\",\n    \"summary\": \"Generated op for `aten::gt.float_int : (float, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt.int\",\n    \"summary\": \"Generated op for `aten::gt.int : (int, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt.Scalar\",\n    \"summary\": \"Generated op for `aten::gt.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.gt.Tensor\",\n    \"summary\": \"Generated op for `aten::gt.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hann_window.periodic\",\n    \"summary\": \"Generated op for `aten::hann_window.periodic : (int, bool, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"window_length\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"periodic\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardshrink\",\n    \"summary\": \"Generated op for `aten::hardshrink : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lambd\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardsigmoid\",\n    \"summary\": \"Generated op for `aten::hardsigmoid : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardsigmoid_\",\n    \"summary\": \"Generated op for `aten::hardsigmoid_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardswish\",\n    \"summary\": \"Generated op for `aten::hardswish : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardswish_\",\n    \"summary\": \"Generated op for `aten::hardswish_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardtanh\",\n    \"summary\": \"Generated op for `aten::hardtanh : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"min_val\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"max_val\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardtanh_\",\n    \"summary\": \"Generated op for `aten::hardtanh_ : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"min_val\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"max_val\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hardtanh_backward\",\n    \"summary\": \"Generated op for `aten::hardtanh_backward : (Tensor, Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"min_val\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"max_val\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.heaviside\",\n    \"summary\": \"Generated op for `aten::heaviside : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"values\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.heaviside_\",\n    \"summary\": \"Generated op for `aten::heaviside_ : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"values\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.hstack\",\n    \"summary\": \"Generated op for `aten::hstack : (Tensor[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.im2col\",\n    \"summary\": \"Generated op for `aten::im2col : (Tensor, int[], int[], int[], int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.imag\",\n    \"summary\": \"Generated op for `aten::imag : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index_put\",\n    \"summary\": \"Generated op for `aten::index_put : (Tensor, Tensor?[], Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfOptionalTensorType\" },\n      { \"name\": \"values\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index_put_\",\n    \"summary\": \"Generated op for `aten::index_put_ : (Tensor, Tensor?[], Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfOptionalNonValueTensorType\" },\n      { \"name\": \"values\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index_put_.hacked_twin\",\n    \"summary\": \"Generated op for `aten::index_put_.hacked_twin : (Tensor, Tensor[], Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfNonValueTensorType\" },\n      { \"name\": \"values\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index_put.hacked_twin\",\n    \"summary\": \"Generated op for `aten::index_put.hacked_twin : (Tensor, Tensor[], Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfTensorType\" },\n      { \"name\": \"values\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"accumulate\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index_select\",\n    \"summary\": \"Generated op for `aten::index_select : (Tensor, int, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index.Tensor\",\n    \"summary\": \"Generated op for `aten::index.Tensor : (Tensor, Tensor?[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfOptionalTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.index.Tensor_hacked_twin\",\n    \"summary\": \"Generated op for `aten::index.Tensor_hacked_twin : (Tensor, Tensor[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.insert.t\",\n    \"summary\": \"Generated op for `aten::insert.t : (t[], int, t) -> ()`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"idx\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"el\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.instance_norm\",\n    \"summary\": \"Generated op for `aten::instance_norm : (Tensor, Tensor?, Tensor?, Tensor?, Tensor?, bool, float, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"use_input_stats\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"momentum\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"cudnn_enabled\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.int_repr\",\n    \"summary\": \"Generated op for `aten::int_repr : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Int.bool\",\n    \"summary\": \"Generated op for `aten::Int.bool : (bool) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Int.float\",\n    \"summary\": \"Generated op for `aten::Int.float : (float) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Int.Scalar\",\n    \"summary\": \"Generated op for `aten::Int.Scalar : (Scalar) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.Int.Tensor\",\n    \"summary\": \"Generated op for `aten::Int.Tensor : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.IntImplicit\",\n    \"summary\": \"Generated op for `aten::IntImplicit : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.is_floating_point\",\n    \"summary\": \"Generated op for `aten::is_floating_point : (Tensor) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.isclose\",\n    \"summary\": \"Generated op for `aten::isclose : (Tensor, Tensor, float, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"rtol\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"atol\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"equal_nan\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.isfinite\",\n    \"summary\": \"Generated op for `aten::isfinite : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.isinf\",\n    \"summary\": \"Generated op for `aten::isinf : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.isnan\",\n    \"summary\": \"Generated op for `aten::isnan : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.isneginf\",\n    \"summary\": \"Generated op for `aten::isneginf : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.isposinf\",\n    \"summary\": \"Generated op for `aten::isposinf : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.item\",\n    \"summary\": \"Generated op for `aten::item : (Tensor) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.join\",\n    \"summary\": \"Generated op for `aten::join : (str, str[]) -> (str)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"values\", \"type\": \"AnyTorchListOfTorchStringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_StringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.keys.str\",\n    \"summary\": \"Generated op for `aten::keys.str : (Dict(str, t)) -> (str[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_DictType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTorchStringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.kl_div\",\n    \"summary\": \"Generated op for `aten::kl_div : (Tensor, Tensor, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"log_target\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.kthvalue\",\n    \"summary\": \"Generated op for `aten::kthvalue : (Tensor, int, int, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"k\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.l1_loss\",\n    \"summary\": \"Generated op for `aten::l1_loss : (Tensor, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.layer_norm\",\n    \"summary\": \"Generated op for `aten::layer_norm : (Tensor, int[], Tensor?, Tensor?, float, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"normalized_shape\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"cudnn_enable\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ldexp.Tensor\",\n    \"summary\": \"Generated op for `aten::ldexp.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.le_.Scalar\",\n    \"summary\": \"Generated op for `aten::le_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.le_.Tensor\",\n    \"summary\": \"Generated op for `aten::le_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.le.int\",\n    \"summary\": \"Generated op for `aten::le.int : (int, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.le.Scalar\",\n    \"summary\": \"Generated op for `aten::le.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.le.Tensor\",\n    \"summary\": \"Generated op for `aten::le.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.leaky_relu\",\n    \"summary\": \"Generated op for `aten::leaky_relu : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"negative_slope\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.leaky_relu_\",\n    \"summary\": \"Generated op for `aten::leaky_relu_ : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"negative_slope\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.leaky_relu_backward\",\n    \"summary\": \"Generated op for `aten::leaky_relu_backward : (Tensor, Tensor, Scalar, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"negative_slope\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"self_is_result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.len.str\",\n    \"summary\": \"Generated op for `aten::len.str : (str) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"s\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.len.t\",\n    \"summary\": \"Generated op for `aten::len.t : (t[]) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.len.Tensor\",\n    \"summary\": \"Generated op for `aten::len.Tensor : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"t\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lerp_.Scalar\",\n    \"summary\": \"Generated op for `aten::lerp_.Scalar : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"end\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lerp_.Tensor\",\n    \"summary\": \"Generated op for `aten::lerp_.Tensor : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"end\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"weight\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lerp.Scalar\",\n    \"summary\": \"Generated op for `aten::lerp.Scalar : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lerp.Tensor\",\n    \"summary\": \"Generated op for `aten::lerp.Tensor : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lift_fresh_copy\",\n    \"summary\": \"Generated op for `aten::lift_fresh_copy : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linalg_cross\",\n    \"summary\": \"Generated op for `aten::linalg_cross : (Tensor, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linalg_det\",\n    \"summary\": \"Generated op for `aten::linalg_det : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linalg_norm\",\n    \"summary\": \"Generated op for `aten::linalg_norm : (Tensor, Scalar?, int[]?, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"ord\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linalg_qr\",\n    \"summary\": \"Generated op for `aten::linalg_qr : (Tensor, str) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mode\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"Q\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"R\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linalg_slogdet\",\n    \"summary\": \"Generated op for `aten::linalg_slogdet : (Tensor) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"A\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"sign\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"logabsdet\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linalg_vector_norm\",\n    \"summary\": \"Generated op for `aten::linalg_vector_norm : (Tensor, Scalar, int[]?, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"ord\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linear\",\n    \"summary\": \"Generated op for `aten::linear : (Tensor, Tensor, Tensor?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.linspace\",\n    \"summary\": \"Generated op for `aten::linspace : (Scalar, Scalar, int, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"steps\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.list.t\",\n    \"summary\": \"Generated op for `aten::list.t : (t[]) -> (t[])`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log\",\n    \"summary\": \"Generated op for `aten::log : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log_\",\n    \"summary\": \"Generated op for `aten::log_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log_sigmoid\",\n    \"summary\": \"Generated op for `aten::log_sigmoid : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log_sigmoid_backward\",\n    \"summary\": \"Generated op for `aten::log_sigmoid_backward : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log_sigmoid_forward\",\n    \"summary\": \"Generated op for `aten::log_sigmoid_forward : (Tensor) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log_softmax.int\",\n    \"summary\": \"Generated op for `aten::log_softmax.int : (Tensor, int, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log.int\",\n    \"summary\": \"Generated op for `aten::log.int : (int) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log10\",\n    \"summary\": \"Generated op for `aten::log10 : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log10_\",\n    \"summary\": \"Generated op for `aten::log10_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log1p\",\n    \"summary\": \"Generated op for `aten::log1p : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log1p_\",\n    \"summary\": \"Generated op for `aten::log1p_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log2\",\n    \"summary\": \"Generated op for `aten::log2 : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.log2_\",\n    \"summary\": \"Generated op for `aten::log2_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logaddexp\",\n    \"summary\": \"Generated op for `aten::logaddexp : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logaddexp2\",\n    \"summary\": \"Generated op for `aten::logaddexp2 : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logcumsumexp\",\n    \"summary\": \"Generated op for `aten::logcumsumexp : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_and\",\n    \"summary\": \"Generated op for `aten::logical_and : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_and_\",\n    \"summary\": \"Generated op for `aten::logical_and_ : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_not\",\n    \"summary\": \"Generated op for `aten::logical_not : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_not_\",\n    \"summary\": \"Generated op for `aten::logical_not_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_or\",\n    \"summary\": \"Generated op for `aten::logical_or : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_or_\",\n    \"summary\": \"Generated op for `aten::logical_or_ : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_xor\",\n    \"summary\": \"Generated op for `aten::logical_xor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logical_xor_\",\n    \"summary\": \"Generated op for `aten::logical_xor_ : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logit\",\n    \"summary\": \"Generated op for `aten::logit : (Tensor, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"eps\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logit_\",\n    \"summary\": \"Generated op for `aten::logit_ : (Tensor, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"eps\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.logsumexp\",\n    \"summary\": \"Generated op for `aten::logsumexp : (Tensor, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt_.Scalar\",\n    \"summary\": \"Generated op for `aten::lt_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt_.Tensor\",\n    \"summary\": \"Generated op for `aten::lt_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt.float\",\n    \"summary\": \"Generated op for `aten::lt.float : (float, float) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt.float_int\",\n    \"summary\": \"Generated op for `aten::lt.float_int : (float, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt.int\",\n    \"summary\": \"Generated op for `aten::lt.int : (int, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt.Scalar\",\n    \"summary\": \"Generated op for `aten::lt.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.lt.Tensor\",\n    \"summary\": \"Generated op for `aten::lt.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_fill_.Scalar\",\n    \"summary\": \"Generated op for `aten::masked_fill_.Scalar : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"mask\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_fill_.Tensor\",\n    \"summary\": \"Generated op for `aten::masked_fill_.Tensor : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"mask\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_fill.Scalar\",\n    \"summary\": \"Generated op for `aten::masked_fill.Scalar : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_fill.Tensor\",\n    \"summary\": \"Generated op for `aten::masked_fill.Tensor : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_scatter\",\n    \"summary\": \"Generated op for `aten::masked_scatter : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"source\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_scatter_\",\n    \"summary\": \"Generated op for `aten::masked_scatter_ : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"mask\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"source\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.masked_select\",\n    \"summary\": \"Generated op for `aten::masked_select : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.matmul\",\n    \"summary\": \"Generated op for `aten::matmul : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max\",\n    \"summary\": \"Generated op for `aten::max : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool1d\",\n    \"summary\": \"Generated op for `aten::max_pool1d : (Tensor, int[], int[], int[], int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool1d_with_indices\",\n    \"summary\": \"Generated op for `aten::max_pool1d_with_indices : (Tensor, int[], int[], int[], int[], bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool2d\",\n    \"category\": \"Pool\",\n    \"summary\": \"Generated op for `aten::max_pool2d : (Tensor, int[], int[], int[], int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool2d_with_indices\",\n    \"summary\": \"Generated op for `aten::max_pool2d_with_indices : (Tensor, int[], int[], int[], int[], bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool2d_with_indices_backward\",\n    \"summary\": \"Generated op for `aten::max_pool2d_with_indices_backward : (Tensor, Tensor, int[], int[], int[], int[], bool, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool3d\",\n    \"summary\": \"Generated op for `aten::max_pool3d : (Tensor, int[], int[], int[], int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool3d_with_indices\",\n    \"summary\": \"Generated op for `aten::max_pool3d_with_indices : (Tensor, int[], int[], int[], int[], bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_pool3d_with_indices_backward\",\n    \"summary\": \"Generated op for `aten::max_pool3d_with_indices_backward : (Tensor, Tensor, int[], int[], int[], int[], bool, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"kernel_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dilation\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"ceil_mode\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_unpool2d\",\n    \"summary\": \"Generated op for `aten::max_unpool2d : (Tensor, Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max_unpool3d\",\n    \"summary\": \"Generated op for `aten::max_unpool3d : (Tensor, Tensor, int[], int[], int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max.dim\",\n    \"summary\": \"Generated op for `aten::max.dim : (Tensor, int, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.max.other\",\n    \"summary\": \"Generated op for `aten::max.other : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.maximum\",\n    \"summary\": \"Generated op for `aten::maximum : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mean\",\n    \"summary\": \"Generated op for `aten::mean : (Tensor, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mean.dim\",\n    \"summary\": \"Generated op for `aten::mean.dim : (Tensor, int[]?, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.meshgrid\",\n    \"summary\": \"Generated op for `aten::meshgrid : (Tensor[]) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.meshgrid.indexing\",\n    \"summary\": \"Generated op for `aten::meshgrid.indexing : (Tensor[], str) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" },\n      { \"name\": \"indexing\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.min\",\n    \"summary\": \"Generated op for `aten::min : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.min.dim\",\n    \"summary\": \"Generated op for `aten::min.dim : (Tensor, int, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.min.other\",\n    \"summary\": \"Generated op for `aten::min.other : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.minimum\",\n    \"summary\": \"Generated op for `aten::minimum : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mish\",\n    \"summary\": \"Generated op for `aten::mish : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mm\",\n    \"summary\": \"Generated op for `aten::mm : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mat2\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.movedim.int\",\n    \"summary\": \"Generated op for `aten::movedim.int : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"source\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"destination\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mse_loss\",\n    \"summary\": \"Generated op for `aten::mse_loss : (Tensor, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mse_loss_backward\",\n    \"summary\": \"Generated op for `aten::mse_loss_backward : (Tensor, Tensor, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul\",\n    \"summary\": \"Generated op for `aten::mul : (Scalar, Scalar) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul_.Scalar\",\n    \"summary\": \"Generated op for `aten::mul_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul_.Tensor\",\n    \"summary\": \"Generated op for `aten::mul_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.float\",\n    \"summary\": \"Generated op for `aten::mul.float : (float, float) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.float_int\",\n    \"summary\": \"Generated op for `aten::mul.float_int : (float, int) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.int\",\n    \"summary\": \"Generated op for `aten::mul.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.int_float\",\n    \"summary\": \"Generated op for `aten::mul.int_float : (int, float) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.left_t\",\n    \"summary\": \"Generated op for `aten::mul.left_t : (t[], int) -> (t[])`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"n\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.Scalar\",\n    \"summary\": \"Generated op for `aten::mul.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mul.Tensor\",\n    \"summary\": \"Generated op for `aten::mul.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.multinomial\",\n    \"summary\": \"Generated op for `aten::multinomial : (Tensor, int, bool, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"num_samples\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"replacement\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.mv\",\n    \"summary\": \"Generated op for `aten::mv : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"vec\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nan_to_num\",\n    \"summary\": \"Generated op for `aten::nan_to_num : (Tensor, float?, float?, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"nan\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"posinf\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"neginf\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.narrow\",\n    \"summary\": \"Generated op for `aten::narrow : (Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"length\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.narrow.Tensor\",\n    \"summary\": \"Generated op for `aten::narrow.Tensor : (Tensor, int, Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"length\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_batch_norm\",\n    \"summary\": \"Generated op for `aten::native_batch_norm : (Tensor, Tensor?, Tensor?, Tensor?, Tensor?, bool, float, float) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"momentum\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_batch_norm_backward\",\n    \"summary\": \"Generated op for `aten::native_batch_norm_backward : (Tensor, Tensor, Tensor?, Tensor?, Tensor?, Tensor?, Tensor?, bool, float, bool[]) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"save_mean\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"save_invstd\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"train\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"output_mask\", \"type\": \"AnyTorchListOfTorchBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_dropout\",\n    \"summary\": \"Generated op for `aten::native_dropout : (Tensor, float, bool?) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"train\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_dropout_backward\",\n    \"summary\": \"Generated op for `aten::native_dropout_backward : (Tensor, Tensor, float) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_group_norm\",\n    \"summary\": \"Generated op for `aten::native_group_norm : (Tensor, Tensor?, Tensor?, int, int, int, int, float) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"N\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"C\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"HxW\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"group\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_group_norm_backward\",\n    \"summary\": \"Generated op for `aten::native_group_norm_backward : (Tensor, Tensor, Tensor, Tensor, Tensor?, int, int, int, int, bool[]) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mean\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"rstd\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"N\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"C\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"HxW\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"group\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"output_mask\", \"type\": \"AnyTorchListOfTorchBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_layer_norm\",\n    \"summary\": \"Generated op for `aten::native_layer_norm : (Tensor, int[], Tensor?, Tensor?, float) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"normalized_shape\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.native_layer_norm_backward\",\n    \"summary\": \"Generated op for `aten::native_layer_norm_backward : (Tensor, Tensor, int[], Tensor, Tensor, Tensor?, Tensor?, bool[]) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"normalized_shape\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"mean\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"rstd\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"output_mask\", \"type\": \"AnyTorchListOfTorchBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne_.Scalar\",\n    \"summary\": \"Generated op for `aten::ne_.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne_.Tensor\",\n    \"summary\": \"Generated op for `aten::ne_.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.bool\",\n    \"summary\": \"Generated op for `aten::ne.bool : (bool, bool) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"b\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.float_int\",\n    \"summary\": \"Generated op for `aten::ne.float_int : (float, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.int\",\n    \"summary\": \"Generated op for `aten::ne.int : (int, int) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.int_list\",\n    \"summary\": \"Generated op for `aten::ne.int_list : (int[], int[]) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.Scalar\",\n    \"summary\": \"Generated op for `aten::ne.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.str\",\n    \"summary\": \"Generated op for `aten::ne.str : (str, str) -> (bool)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"b\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ne.Tensor\",\n    \"summary\": \"Generated op for `aten::ne.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.neg\",\n    \"summary\": \"Generated op for `aten::neg : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.neg_\",\n    \"summary\": \"Generated op for `aten::neg_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.neg.float\",\n    \"summary\": \"Generated op for `aten::neg.float : (float) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.neg.int\",\n    \"summary\": \"Generated op for `aten::neg.int : (int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.new_empty\",\n    \"summary\": \"Generated op for `aten::new_empty : (Tensor, int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.new_empty_strided\",\n    \"summary\": \"Generated op for `aten::new_empty_strided : (Tensor, int[], int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"stride\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.new_full\",\n    \"summary\": \"Generated op for `aten::new_full : (Tensor, int[], Scalar, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"fill_value\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.new_ones\",\n    \"summary\": \"Generated op for `aten::new_ones : (Tensor, int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.new_zeros\",\n    \"summary\": \"Generated op for `aten::new_zeros : (Tensor, int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nll_loss_backward\",\n    \"summary\": \"Generated op for `aten::nll_loss_backward : (Tensor, Tensor, Tensor, Tensor?, int, int, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"ignore_index\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"total_weight\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nll_loss_forward\",\n    \"summary\": \"Generated op for `aten::nll_loss_forward : (Tensor, Tensor, Tensor?, int, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"ignore_index\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"total_weight\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nll_loss2d_backward\",\n    \"summary\": \"Generated op for `aten::nll_loss2d_backward : (Tensor, Tensor, Tensor, Tensor?, int, int, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"ignore_index\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"total_weight\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nll_loss2d_forward\",\n    \"summary\": \"Generated op for `aten::nll_loss2d_forward : (Tensor, Tensor, Tensor?, int, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"ignore_index\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"total_weight\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nonzero\",\n    \"summary\": \"Generated op for `aten::nonzero : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nonzero_numpy\",\n    \"summary\": \"Generated op for `aten::nonzero_numpy : (Tensor) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.nonzero_static\",\n    \"summary\": \"Generated op for `aten::nonzero_static : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"fill_value\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.norm.Scalar\",\n    \"summary\": \"Generated op for `aten::norm.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.norm.ScalarOpt_dim\",\n    \"summary\": \"Generated op for `aten::norm.ScalarOpt_dim : (Tensor, Scalar?, int[], bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.normal_functional\",\n    \"summary\": \"Generated op for `aten::normal_functional : (Tensor, float, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mean\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"std\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.numel\",\n    \"summary\": \"Generated op for `aten::numel : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.numpy_T\",\n    \"summary\": \"Generated op for `aten::numpy_T : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.one_hot\",\n    \"summary\": \"Generated op for `aten::one_hot : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"num_classes\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ones\",\n    \"summary\": \"Generated op for `aten::ones : (int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ones_like\",\n    \"summary\": \"Generated op for `aten::ones_like : (Tensor, int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.outer\",\n    \"summary\": \"Generated op for `aten::outer : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"vec2\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pad\",\n    \"category\": \"Transform\",\n    \"summary\": \"Generated op for `aten::pad : (Tensor, int[], str, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"pad\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"mode\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.permute\",\n    \"summary\": \"Generated op for `aten::permute : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.permute_copy\",\n    \"summary\": \"Generated op for `aten::permute_copy : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pixel_shuffle\",\n    \"summary\": \"Generated op for `aten::pixel_shuffle : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"upscale_factor\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pixel_unshuffle\",\n    \"summary\": \"Generated op for `aten::pixel_unshuffle : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"downscale_factor\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.poisson_nll_loss\",\n    \"summary\": \"Generated op for `aten::poisson_nll_loss : (Tensor, Tensor, bool, bool, float, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"target\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"log_input\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"full\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"eps\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"reduction\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.polar\",\n    \"summary\": \"Generated op for `aten::polar : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"abs\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"angle\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pow.int_float\",\n    \"summary\": \"Generated op for `aten::pow.int_float : (int, float) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pow.Scalar\",\n    \"summary\": \"Generated op for `aten::pow.Scalar : (Scalar, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"exponent\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pow.Tensor_Scalar\",\n    \"summary\": \"Generated op for `aten::pow.Tensor_Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"exponent\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.pow.Tensor_Tensor\",\n    \"summary\": \"Generated op for `aten::pow.Tensor_Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"exponent\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.prelu\",\n    \"summary\": \"Generated op for `aten::prelu : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.prod\",\n    \"summary\": \"Generated op for `aten::prod : (Tensor, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.prod.dim_int\",\n    \"summary\": \"Generated op for `aten::prod.dim_int : (Tensor, int, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.quantize_per_channel\",\n    \"summary\": \"Generated op for `aten::quantize_per_channel : (Tensor, Tensor, Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scales\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"zero_points\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"axis\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.quantize_per_tensor\",\n    \"summary\": \"Generated op for `aten::quantize_per_tensor : (Tensor, float, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"zero_point\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rad2deg\",\n    \"summary\": \"Generated op for `aten::rad2deg : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rand\",\n    \"summary\": \"Generated op for `aten::rand : (int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rand_like\",\n    \"summary\": \"Generated op for `aten::rand_like : (Tensor, int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.randint\",\n    \"summary\": \"Generated op for `aten::randint : (int, int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"high\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.randint.low\",\n    \"summary\": \"Generated op for `aten::randint.low : (int, int, int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"low\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"high\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.randn\",\n    \"summary\": \"Generated op for `aten::randn : (int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.randn_like\",\n    \"summary\": \"Generated op for `aten::randn_like : (Tensor, int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.randn.generator\",\n    \"summary\": \"Generated op for `aten::randn.generator : (int[], Generator?, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.random\",\n    \"summary\": \"Generated op for `aten::random : (Tensor, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.random.from\",\n    \"summary\": \"Generated op for `aten::random.from : (Tensor, int, int?, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"from\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"to\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.real\",\n    \"summary\": \"Generated op for `aten::real : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reciprocal\",\n    \"summary\": \"Generated op for `aten::reciprocal : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reciprocal_\",\n    \"summary\": \"Generated op for `aten::reciprocal_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reflection_pad1d\",\n    \"summary\": \"Generated op for `aten::reflection_pad1d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reflection_pad2d\",\n    \"summary\": \"Generated op for `aten::reflection_pad2d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reflection_pad3d\",\n    \"summary\": \"Generated op for `aten::reflection_pad3d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.relu\",\n    \"category\": \"Activation\",\n    \"summary\": \"Generated op for `aten::relu : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.relu_\",\n    \"summary\": \"Generated op for `aten::relu_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.relu6\",\n    \"summary\": \"Generated op for `aten::relu6 : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.relu6_\",\n    \"summary\": \"Generated op for `aten::relu6_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.remainder.int\",\n    \"summary\": \"Generated op for `aten::remainder.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.remainder.Scalar\",\n    \"summary\": \"Generated op for `aten::remainder.Scalar : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.remainder.Tensor\",\n    \"summary\": \"Generated op for `aten::remainder.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.renorm\",\n    \"summary\": \"Generated op for `aten::renorm : (Tensor, Scalar, int, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"maxnorm\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.repeat\",\n    \"summary\": \"Generated op for `aten::repeat : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"repeats\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.repeat_interleave.self_int\",\n    \"summary\": \"Generated op for `aten::repeat_interleave.self_int : (Tensor, int, int?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"repeats\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.replication_pad1d\",\n    \"summary\": \"Generated op for `aten::replication_pad1d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.replication_pad2d\",\n    \"summary\": \"Generated op for `aten::replication_pad2d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.replication_pad3d\",\n    \"summary\": \"Generated op for `aten::replication_pad3d : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"padding\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"Generated op for `aten::reshape : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"shape\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.reshape_as\",\n    \"summary\": \"Generated op for `aten::reshape_as : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.resize\",\n    \"summary\": \"Generated op for `aten::resize : (Tensor, int[], int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.resize_\",\n    \"summary\": \"Generated op for `aten::resize_ : (Tensor, int[], int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rms_norm\",\n    \"summary\": \"Generated op for `aten::rms_norm : (Tensor, int[], Tensor?, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"normalized_shape\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"eps\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.roll\",\n    \"summary\": \"Generated op for `aten::roll : (Tensor, int[], int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"shifts\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rot90\",\n    \"summary\": \"Generated op for `aten::rot90 : (Tensor, int, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"k\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.round\",\n    \"summary\": \"Generated op for `aten::round : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.round_\",\n    \"summary\": \"Generated op for `aten::round_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.round_.decimals\",\n    \"summary\": \"Generated op for `aten::round_.decimals : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"decimals\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.round.decimals\",\n    \"summary\": \"Generated op for `aten::round.decimals : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"decimals\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rrelu\",\n    \"summary\": \"Generated op for `aten::rrelu : (Tensor, Scalar, Scalar, bool, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lower\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"upper\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rrelu_\",\n    \"summary\": \"Generated op for `aten::rrelu_ : (Tensor, Scalar, Scalar, bool, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"lower\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"upper\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rrelu_with_noise\",\n    \"summary\": \"Generated op for `aten::rrelu_with_noise : (Tensor, Tensor, Scalar, Scalar, bool, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"noise\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lower\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"upper\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rrelu_with_noise_\",\n    \"summary\": \"Generated op for `aten::rrelu_with_noise_ : (Tensor, Tensor, Scalar, Scalar, bool, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"noise\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"lower\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"upper\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rrelu_with_noise_backward\",\n    \"summary\": \"Generated op for `aten::rrelu_with_noise_backward : (Tensor, Tensor, Tensor, Scalar, Scalar, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"noise\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lower\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"upper\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"self_is_result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rrelu_with_noise_functional\",\n    \"summary\": \"Generated op for `aten::rrelu_with_noise_functional : (Tensor, Tensor, Scalar, Scalar, bool, Generator?) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"noise\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lower\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"upper\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"training\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"noise_out\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rsqrt\",\n    \"summary\": \"Generated op for `aten::rsqrt : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rsqrt_\",\n    \"summary\": \"Generated op for `aten::rsqrt_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.rsub.Scalar\",\n    \"summary\": \"Generated op for `aten::rsub.Scalar : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scalar_tensor\",\n    \"summary\": \"Generated op for `aten::scalar_tensor : (Scalar, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"s\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.ScalarImplicit\",\n    \"summary\": \"Generated op for `aten::ScalarImplicit : (Tensor) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scaled_dot_product_attention\",\n    \"summary\": \"Generated op for `aten::scaled_dot_product_attention : (Tensor, Tensor, Tensor, Tensor?, float, bool, float?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"key\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"attn_mask\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"dropout_p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"is_causal\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"enable_gqa\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter_.src\",\n    \"summary\": \"Generated op for `aten::scatter_.src : (Tensor, int, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"src\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter_.value\",\n    \"summary\": \"Generated op for `aten::scatter_.value : (Tensor, int, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter_add\",\n    \"summary\": \"Generated op for `aten::scatter_add : (Tensor, int, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter_add_\",\n    \"summary\": \"Generated op for `aten::scatter_add_ : (Tensor, int, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"src\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter_reduce_.two\",\n    \"summary\": \"Generated op for `aten::scatter_reduce_.two : (Tensor, int, Tensor, Tensor, str, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"src\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"reduce\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"include_self\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter_reduce.two\",\n    \"summary\": \"Generated op for `aten::scatter_reduce.two : (Tensor, int, Tensor, Tensor, str, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"reduce\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"include_self\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter.reduce\",\n    \"summary\": \"Generated op for `aten::scatter.reduce : (Tensor, int, Tensor, Tensor, str) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"reduce\", \"type\": \"Torch_StringType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter.src\",\n    \"summary\": \"Generated op for `aten::scatter.src : (Tensor, int, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.scatter.value\",\n    \"summary\": \"Generated op for `aten::scatter.value : (Tensor, int, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.select_copy.int\",\n    \"summary\": \"Generated op for `aten::select_copy.int : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.select_scatter\",\n    \"summary\": \"Generated op for `aten::select_scatter : (Tensor, Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.select.int\",\n    \"summary\": \"Generated op for `aten::select.int : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"index\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.selu\",\n    \"summary\": \"Generated op for `aten::selu : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.selu_\",\n    \"summary\": \"Generated op for `aten::selu_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sgn\",\n    \"summary\": \"Generated op for `aten::sgn : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sgn_\",\n    \"summary\": \"Generated op for `aten::sgn_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sigmoid\",\n    \"category\": \"Activation\",\n    \"summary\": \"Generated op for `aten::sigmoid : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sigmoid_\",\n    \"summary\": \"Generated op for `aten::sigmoid_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sigmoid_backward\",\n    \"summary\": \"Generated op for `aten::sigmoid_backward : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sign\",\n    \"summary\": \"Generated op for `aten::sign : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sign_\",\n    \"summary\": \"Generated op for `aten::sign_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.signbit\",\n    \"summary\": \"Generated op for `aten::signbit : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.silu\",\n    \"summary\": \"Generated op for `aten::silu : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.silu_\",\n    \"summary\": \"Generated op for `aten::silu_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sin\",\n    \"summary\": \"Generated op for `aten::sin : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sin_\",\n    \"summary\": \"Generated op for `aten::sin_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sinh\",\n    \"summary\": \"Generated op for `aten::sinh : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sinh_\",\n    \"summary\": \"Generated op for `aten::sinh_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.size\",\n    \"summary\": \"Generated op for `aten::size : (Tensor) -> (int[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.size.int\",\n    \"summary\": \"Generated op for `aten::size.int : (Tensor, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.slice_copy.Tensor\",\n    \"summary\": \"Generated op for `aten::slice_copy.Tensor : (Tensor, int, int?, int?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.slice_scatter\",\n    \"summary\": \"Generated op for `aten::slice_scatter : (Tensor, Tensor, int, int?, int?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"src\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.slice.t\",\n    \"summary\": \"Generated op for `aten::slice.t : (t[], int?, int?, int) -> (t[])`\",\n    \"operands\": [\n      { \"name\": \"l\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"start\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.slice.Tensor\",\n    \"summary\": \"Generated op for `aten::slice.Tensor : (Tensor, int, int?, int?, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"end\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.softmax.int\",\n    \"summary\": \"Generated op for `aten::softmax.int : (Tensor, int, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.softplus\",\n    \"summary\": \"Generated op for `aten::softplus : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"beta\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"threshold\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.softshrink\",\n    \"summary\": \"Generated op for `aten::softshrink : (Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"lambd\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sort\",\n    \"summary\": \"Generated op for `aten::sort : (Tensor, int, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"descending\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sort.int\",\n    \"summary\": \"Generated op for `aten::sort.int : (int[], bool) -> ()`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"reverse\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.special_expm1\",\n    \"summary\": \"Generated op for `aten::special_expm1 : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.split_copy.Tensor\",\n    \"summary\": \"Generated op for `aten::split_copy.Tensor : (Tensor, int, int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"split_size\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.split_with_sizes\",\n    \"summary\": \"Generated op for `aten::split_with_sizes : (Tensor, int[], int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"split_sizes\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.split_with_sizes_copy\",\n    \"summary\": \"Generated op for `aten::split_with_sizes_copy : (Tensor, int[], int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"split_sizes\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.split.sizes\",\n    \"summary\": \"Generated op for `aten::split.sizes : (Tensor, int[], int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"split_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.split.Tensor\",\n    \"summary\": \"Generated op for `aten::split.Tensor : (Tensor, int, int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"split_size\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sqrt\",\n    \"summary\": \"Generated op for `aten::sqrt : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sqrt_\",\n    \"summary\": \"Generated op for `aten::sqrt_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sqrt.int\",\n    \"summary\": \"Generated op for `aten::sqrt.int : (int) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.square\",\n    \"summary\": \"Generated op for `aten::square : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.square_\",\n    \"summary\": \"Generated op for `aten::square_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.squeeze\",\n    \"summary\": \"Generated op for `aten::squeeze : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.squeeze_copy\",\n    \"summary\": \"Generated op for `aten::squeeze_copy : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.squeeze_copy.dim\",\n    \"summary\": \"Generated op for `aten::squeeze_copy.dim : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.squeeze.dim\",\n    \"summary\": \"Generated op for `aten::squeeze.dim : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.stack\",\n    \"summary\": \"Generated op for `aten::stack : (Tensor[], int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"tensors\", \"type\": \"AnyTorchListOfTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.std\",\n    \"summary\": \"Generated op for `aten::std : (Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"unbiased\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.std.correction\",\n    \"summary\": \"Generated op for `aten::std.correction : (Tensor, int[]?, Scalar?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"correction\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.std.dim\",\n    \"summary\": \"Generated op for `aten::std.dim : (Tensor, int[]?, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"unbiased\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.stft\",\n    \"summary\": \"Generated op for `aten::stft : (Tensor, int, int?, int?, Tensor?, bool, bool?, bool?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"n_fft\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"hop_length\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"win_length\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"window\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"normalized\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"onesided\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"return_complex\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"align_to_window\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.stft.center\",\n    \"summary\": \"Generated op for `aten::stft.center : (Tensor, int, int?, int?, Tensor?, bool, str, bool, bool?, bool?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"n_fft\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"hop_length\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"win_length\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"window\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"center\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"pad_mode\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"normalized\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"onesided\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"return_complex\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"align_to_window\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.str\",\n    \"summary\": \"Generated op for `aten::str : (t) -> (str)`\",\n    \"operands\": [\n      { \"name\": \"elem\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_StringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub\",\n    \"summary\": \"Generated op for `aten::sub : (Scalar, Scalar) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"b\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub_.Scalar\",\n    \"summary\": \"Generated op for `aten::sub_.Scalar : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub_.Tensor\",\n    \"summary\": \"Generated op for `aten::sub_.Tensor : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"other\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub.float\",\n    \"summary\": \"Generated op for `aten::sub.float : (float, float) -> (float)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"b\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub.int\",\n    \"summary\": \"Generated op for `aten::sub.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub.Scalar\",\n    \"summary\": \"Generated op for `aten::sub.Scalar : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sub.Tensor\",\n    \"summary\": \"Generated op for `aten::sub.Tensor : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"alpha\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sum\",\n    \"summary\": \"Generated op for `aten::sum : (Tensor, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sum.dim_IntList\",\n    \"summary\": \"Generated op for `aten::sum.dim_IntList : (Tensor, int[]?, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sym_constrain_range\",\n    \"summary\": \"Generated op for `aten::sym_constrain_range : (Scalar, int?, int?) -> ()`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.sym_constrain_range_for_size\",\n    \"summary\": \"Generated op for `aten::sym_constrain_range_for_size : (Scalar, int?, int?) -> ()`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"min\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"max\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.t\",\n    \"summary\": \"Generated op for `aten::t : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.t_copy\",\n    \"summary\": \"Generated op for `aten::t_copy : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tan\",\n    \"summary\": \"Generated op for `aten::tan : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tan_\",\n    \"summary\": \"Generated op for `aten::tan_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"Generated op for `aten::tanh : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tanh_\",\n    \"summary\": \"Generated op for `aten::tanh_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tanh_backward\",\n    \"summary\": \"Generated op for `aten::tanh_backward : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tensor\",\n    \"summary\": \"Generated op for `aten::tensor : (t[], int?, Device?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTorchListType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"requires_grad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tensor_split.sections\",\n    \"summary\": \"Generated op for `aten::tensor_split.sections : (Tensor, int, int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"sections\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tensor.bool\",\n    \"summary\": \"Generated op for `aten::tensor.bool : (bool, int?, Device?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"t\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"requires_grad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tensor.float\",\n    \"summary\": \"Generated op for `aten::tensor.float : (float, int?, Device?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"t\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"requires_grad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tensor.int\",\n    \"summary\": \"Generated op for `aten::tensor.int : (int, int?, Device?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"t\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"requires_grad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.threshold\",\n    \"summary\": \"Generated op for `aten::threshold : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"threshold\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.threshold_\",\n    \"summary\": \"Generated op for `aten::threshold_ : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"threshold\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.threshold_backward\",\n    \"summary\": \"Generated op for `aten::threshold_backward : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"threshold\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tile\",\n    \"summary\": \"Generated op for `aten::tile : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.to.device\",\n    \"summary\": \"Generated op for `aten::to.device : (Tensor, Device, int, bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"device\", \"type\": \"Torch_DeviceType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"copy\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.to.dtype\",\n    \"summary\": \"Generated op for `aten::to.dtype : (Tensor, int, bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"copy\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.to.dtype_layout\",\n    \"summary\": \"Generated op for `aten::to.dtype_layout : (Tensor, int?, int?, Device?, bool?, bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"copy\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.to.other\",\n    \"summary\": \"Generated op for `aten::to.other : (Tensor, Tensor, bool, bool, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"copy\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.to.prim_Device\",\n    \"summary\": \"Generated op for `aten::to.prim_Device : (Tensor, Device?, int?, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"non_blocking\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"copy\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.topk\",\n    \"summary\": \"Generated op for `aten::topk : (Tensor, int, int, bool, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"k\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"largest\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"sorted\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"indices\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.trace\",\n    \"summary\": \"Generated op for `aten::trace : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.transpose_copy.int\",\n    \"summary\": \"Generated op for `aten::transpose_copy.int : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim0\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim1\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.transpose.int\",\n    \"summary\": \"Generated op for `aten::transpose.int : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim0\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dim1\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tril\",\n    \"summary\": \"Generated op for `aten::tril : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"diagonal\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tril_\",\n    \"summary\": \"Generated op for `aten::tril_ : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"diagonal\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.tril_indices\",\n    \"summary\": \"Generated op for `aten::tril_indices : (int, int, int, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"row\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"col\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.triu\",\n    \"summary\": \"Generated op for `aten::triu : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"diagonal\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.triu_\",\n    \"summary\": \"Generated op for `aten::triu_ : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"diagonal\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.triu_indices\",\n    \"summary\": \"Generated op for `aten::triu_indices : (int, int, int, int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"row\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"col\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.trunc\",\n    \"summary\": \"Generated op for `aten::trunc : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.trunc_\",\n    \"summary\": \"Generated op for `aten::trunc_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.type_as\",\n    \"summary\": \"Generated op for `aten::type_as : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unbind_copy.int\",\n    \"summary\": \"Generated op for `aten::unbind_copy.int : (Tensor, int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unbind.int\",\n    \"summary\": \"Generated op for `aten::unbind.int : (Tensor, int) -> (Tensor[])`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListOfTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unflatten.int\",\n    \"summary\": \"Generated op for `aten::unflatten.int : (Tensor, int, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"sizes\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unfold\",\n    \"summary\": \"Generated op for `aten::unfold : (Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dimension\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"size\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unfold_copy\",\n    \"summary\": \"Generated op for `aten::unfold_copy : (Tensor, int, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dimension\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"size\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.uniform\",\n    \"summary\": \"Generated op for `aten::uniform : (Tensor, float, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"from\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"to\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.uniform_\",\n    \"summary\": \"Generated op for `aten::uniform_ : (Tensor, float, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"from\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"to\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unique_consecutive\",\n    \"summary\": \"Generated op for `aten::unique_consecutive : (Tensor, bool, bool, int?) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"return_inverse\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"return_counts\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unique_dim\",\n    \"summary\": \"Generated op for `aten::unique_dim : (Tensor, int, bool, bool, bool) -> (Tensor, Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"sorted\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"return_inverse\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"return_counts\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result2\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unsqueeze\",\n    \"summary\": \"Generated op for `aten::unsqueeze : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unsqueeze_\",\n    \"summary\": \"Generated op for `aten::unsqueeze_ : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.unsqueeze_copy\",\n    \"summary\": \"Generated op for `aten::unsqueeze_copy : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_bilinear2d\",\n    \"summary\": \"Generated op for `aten::upsample_bilinear2d : (Tensor, int[], bool, float?, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"align_corners\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"scales_h\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"scales_w\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_bilinear2d.vec\",\n    \"summary\": \"Generated op for `aten::upsample_bilinear2d.vec : (Tensor, int[]?, bool, float[]?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"align_corners\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"scale_factors\", \"type\": \"AnyTorchOptionalListOfTorchFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_nearest1d\",\n    \"summary\": \"Generated op for `aten::upsample_nearest1d : (Tensor, int[], float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"scales\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_nearest1d.vec\",\n    \"summary\": \"Generated op for `aten::upsample_nearest1d.vec : (Tensor, int[]?, float[]?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"scale_factors\", \"type\": \"AnyTorchOptionalListOfTorchFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_nearest2d\",\n    \"summary\": \"Generated op for `aten::upsample_nearest2d : (Tensor, int[], float?, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"scales_h\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"scales_w\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_nearest2d_backward\",\n    \"summary\": \"Generated op for `aten::upsample_nearest2d_backward : (Tensor, int[], int[], float?, float?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"input_size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"scales_h\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"scales_w\", \"type\": \"AnyTorchOptionalFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.upsample_nearest2d.vec\",\n    \"summary\": \"Generated op for `aten::upsample_nearest2d.vec : (Tensor, int[]?, float[]?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"output_size\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"scale_factors\", \"type\": \"AnyTorchOptionalListOfTorchFloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.var\",\n    \"summary\": \"Generated op for `aten::var : (Tensor, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"unbiased\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.var_mean\",\n    \"summary\": \"Generated op for `aten::var_mean : (Tensor, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"unbiased\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.var_mean.correction\",\n    \"summary\": \"Generated op for `aten::var_mean.correction : (Tensor, int[]?, Scalar?, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"correction\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.var_mean.dim\",\n    \"summary\": \"Generated op for `aten::var_mean.dim : (Tensor, int[]?, bool, bool) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"unbiased\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.var.correction\",\n    \"summary\": \"Generated op for `aten::var.correction : (Tensor, int[]?, Scalar?, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"correction\", \"type\": \"AnyTorchOptionalScalarType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.var.dim\",\n    \"summary\": \"Generated op for `aten::var.dim : (Tensor, int[]?, bool, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"unbiased\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"keepdim\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.view\",\n    \"summary\": \"Generated op for `aten::view : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.view_as_complex\",\n    \"summary\": \"Generated op for `aten::view_as_complex : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.view_as_real\",\n    \"summary\": \"Generated op for `aten::view_as_real : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.view_copy\",\n    \"summary\": \"Generated op for `aten::view_copy : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.view_copy.dtype\",\n    \"summary\": \"Generated op for `aten::view_copy.dtype : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.view.dtype\",\n    \"summary\": \"Generated op for `aten::view.dtype : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.warn\",\n    \"summary\": \"Generated op for `aten::warn : (str, int) -> ()`\",\n    \"operands\": [\n      { \"name\": \"message\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"stacklevel\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.where.Scalar\",\n    \"summary\": \"Generated op for `aten::where.Scalar : (Tensor, Scalar, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.where.ScalarOther\",\n    \"summary\": \"Generated op for `aten::where.ScalarOther : (Tensor, Tensor, Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.where.ScalarSelf\",\n    \"summary\": \"Generated op for `aten::where.ScalarSelf : (Tensor, Scalar, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchScalarType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.where.self\",\n    \"summary\": \"Generated op for `aten::where.self : (Tensor, Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.xlogy.Tensor\",\n    \"summary\": \"Generated op for `aten::xlogy.Tensor : (Tensor, Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"other\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.zero\",\n    \"summary\": \"Generated op for `aten::zero : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.zero_\",\n    \"summary\": \"Generated op for `aten::zero_ : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalNonValueTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.zeros\",\n    \"summary\": \"Generated op for `aten::zeros : (int[], int?, int?, Device?, bool?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"size\", \"type\": \"AnyTorchListOfTorchIntType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.aten.zeros_like\",\n    \"summary\": \"Generated op for `aten::zeros_like : (Tensor, int?, int?, Device?, bool?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"layout\", \"type\": \"AnyTorchOptionalIntType\" },\n      { \"name\": \"device\", \"type\": \"AnyTorchOptionalDeviceType\" },\n      { \"name\": \"pin_memory\", \"type\": \"AnyTorchOptionalBoolType\" },\n      { \"name\": \"memory_format\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.attr\",\n    \"summary\": \"Declare an attribute of a torch.class_type\",\n    \"description\": \"This op declaratively specifies that torch.nn.Module's of the parent\\n    torch.class_type must have an attribute `name` of type `type`.\\n\\n    If `private` is present, it indicates that the value of this attribute\\n    cannot be accessed externally.\",\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"isPrivate\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`private` $isPrivate^)? $name `:` $type attr-dict\"\n  },\n  {\n    \"name\": \"torch.bind_symbolic_shape\",\n    \"summary\": \"Binds shape expressions to tensors using an affine map indexed by shape symbols\",\n    \"description\": \"The `torch.bind_symbolic_shape` operation binds shape expressions\\n    useful to compute the dynamic dimensions of a tensor. It takes a\\n    variadic of SSA symbols that map 1:1 to the local symbols declared\\n    in the affine map. The affine map contains a list of affine shape\\n    expressions for each dim where the terminals are from the declared\\n    symbols.\\n\\n    Example:\\n    ```\\n    torch.bind_symbolic_shape %arg0, [%0, %1], affine_map<()[s0, s1] -> (s0, s1, 3)> : !torch.vtensor<[?,?,3],f32>\\n    torch.bind_symbolic_shape %out0, [%0, %1, %2], affine_map<()[s0, s1, s2] -> (s0, s1 * 2 + s2, 3)> : !torch.vtensor<[?,?,3],f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_ValueTensorType\" },\n      { \"name\": \"shape_symbols\", \"type\": \"Variadic<Torch_IntType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape_expressions\", \"type\": \"Builtin_AffineMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.class_type\",\n    \"summary\": \"Constructs a torch.ClassType\",\n    \"description\": \"Declares a class type. Class types are the types used to describe\\n    TorchScript `torch.nn.Module`'s. The terminology \\\"class type\\\" is for\\n    consistency with TorchScript (a better name in our context might be\\n    \\\"nn module subtype\\\"). The `syn_name` of this op is the same string\\n    as in the `!torch.nn.Module<\\\"...\\\">` type.\\n\\n    Example:\\n\\n    ```mlir\\n    // A simple empty torch.class_type, with corresponding torch.nn_module.\\n    torch.class_type @empty {}\\n    %submodule = torch.nn_module {} : !torch.nn.Module<\\\"empty\\\">\\n\\n    // A class type with many members.\\n    torch.class_type @test {\\n      torch.attr \\\"b\\\" : !torch.bool\\n      torch.attr \\\"i\\\" : !torch.int\\n      torch.attr \\\"f\\\" : !torch.float\\n      torch.attr \\\"t\\\" : !torch.tensor\\n      torch.attr \\\"submodule\\\" : !torch.nn.Module<\\\"empty\\\">\\n      torch.method \\\"method\\\", @f\\n    }\\n    torch.nn_module {\\n      // These must match the order and names in the `torch.class_type`.\\n      torch.slot \\\"b\\\", %bool_true : !torch.bool\\n      torch.slot \\\"i\\\", %int3 : !torch.int\\n      torch.slot \\\"f\\\", %float : !torch.float\\n      torch.slot \\\"t\\\", %t : !torch.tensor\\n      torch.slot \\\"submodule\\\", %submodule : !torch.nn.Module<\\\"empty\\\">\\n    } : !torch.nn.Module<\\\"test\\\">\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name $region attr-dict\"\n  },\n  {\n    \"name\": \"torch.class_type_terminator\",\n    \"summary\": \"Implicit terminator for torch.class_type\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"torch.constant.bool\",\n    \"summary\": \"Materialize a constant `bool` value.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"torch.constant.device\",\n    \"summary\": \"Materialize a constant Device value.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_DeviceType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"torch.constant.float\",\n    \"summary\": \"Materialize a constant `float` value.\",\n    \"description\": \"Note: TorchScript represents `float` as 64-bit floating point values.\\n\\n    TODO: Add a `!torch.float` type.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F64Attr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"torch.constant.int\",\n    \"summary\": \"Materialize a constant `int` value.\",\n    \"description\": \"Note: TorchScript represents integers as 64-bit signed values, unlike\\n    Python where they are arbitrary precision.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"I64Attr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.constant.none\",\n    \"summary\": \"Get the singleton None value.\",\n    \"description\": \"Not to be confused with the `mlir::NoneType`. Be careful to use\\n    `Torch::NoneType` to avoid namespace ambiguity.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NoneType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"torch.constant.number\",\n    \"summary\": \"Materialize a constant `number` value.\",\n    \"description\": \"This op is used as a workaround to the fact that the constant\\n    materialization in MLIR must materialize a constant with a single op.\\n    To materialize ops with a static `!torch.number` type, we must use this op,\\n    even though we statically know if it is an integer or a float.\\n\\n    Note: This op unconditionally canonicalizes to\\n    `torch.constant.{float,int}` + `torch.derefine`\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NumberType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttrOf<[F64Attr, I64Attr]>\" }\n    ]\n  },\n  {\n    \"name\": \"torch.constant.str\",\n    \"summary\": \"Materialize a constant str value.\",\n    \"description\": \"Note: Strings in Python (and TorchScript) are immutable.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_StringType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"torch.copy.to_tensor\",\n    \"summary\": \"Create a !torch.tensor with the same contents as the operand\",\n    \"description\": \"This op is used to convert from !torch.vtensor to !torch.tensor.\\n    It does so by allocating a new !torch.tensor and filling it with\\n    the contents of the operand.\\n\\n    However, this op *does not* allow adding/removing static information about\\n    sizes/dtype. For that, use `torch.tensor_static_info_cast`.\\n\\n    This op does not have the AllowsTypeRefinement trait because the operand\\n    and result types are coupled. Only places that know how to simultaneously\\n    update both types should be changing the type of this op.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_ValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'operand', 'cast<NonValueTensorType>($_self).getWithValueSemantics()'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.copy.to_vtensor\",\n    \"summary\": \"Create a !torch.vtensor with the same contents as the operand\",\n    \"description\": \"This op is used to convert from !torch.tensor to !torch.vtensor.\\n\\n    However, this op *does not* allow adding/removing static information about\\n    sizes/dtype. For that, use `torch.tensor_static_info_cast`.\\n\\n    This op does not have the AllowsTypeRefinement trait because the operand\\n    and result types are coupled. Only places that know how to simultaneously\\n    update both types should be changing the type of this op.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_ValueTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'operand', 'cast<ValueTensorType>($_self).getWithoutValueSemantics()'>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.derefine\",\n    \"summary\": \"De-refine a type\",\n    \"description\": \"In terms of IR structure, TorchScript allows types to vary in many\\n    circumstances where MLIR requires pointer-identical types. In particular,\\n    it is valid to pass any subtype in place of a type. For example, if an\\n    `Optional[int]` is required somewhere in the IR, it is legal to pass a\\n    value of just `int` (but not the other way around; see\\n    `torch.prim.unchecked_cast`). In effect, every *use* can have a different\\n    type.\\n\\n    This op bridges that impedance mismatch. This op allows casting a value\\n    from one type to a type that it is a subtype of to model this behavior.\\n    This op uses the TorchScript notion of subtype, which matches the\\n    Python notion of subtype presented in PEP 483.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($operand)) `to` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.dtype.calculate\",\n    \"summary\": \"Dtype calculation encapsulation op\",\n    \"description\": \"The `torch.dtype.calculate` op captures a dtype calculation\\n    (in the region `calculation`) which calculates the dtypes for\\n    the set of values yielded by the `body` region.\\n\\n    The `calculation` region yields a `!torch.int` for each\\n    value yielded by the `body` region.\\n\\n    Conceptually, the `calculation` region executes first, then `body`\\n    region. So the `calculation` region can also contain arbitrary\\n    assertions or side-effecting code which guard the validity of the execution\\n    of the body (typically by terminating the program with a\\n    torch.prim.RaiseException op).\\n\\n    The program has undefined behavior if the values yielded by the `body`\\n    region do not have the dtypes yielded by the `calculation` region.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"calculation\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$body `dtypes` $calculation attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"torch.dtype.calculate.yield\",\n    \"summary\": \"yield-like terminator for torch.dtype.calculate\",\n    \"description\": \"This op terminates the `body` region of a `torch.dtype.calculate` op.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"torch.dtype.calculate.yield.dtypes\",\n    \"summary\": \"yield-like terminator for torch.dtype.calculate shape region\",\n    \"description\": \"This op terminates the `dtypeCalculation` region of a\\n    `torch.dtype.calculate` op.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Torch_IntType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"torch.global_slot\",\n    \"summary\": \"A slot with global storage\",\n    \"description\": \"Represents a slot with global storage. The slot semantics are the same\\n    as Python's: getting or setting a slot is done by object identity.\\n\\n    The `typeBound` is a type that the contained type is a subtype of.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"typeBound\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"($sym_visibility^)? $sym_name attr-dict `:` $typeBound\"\n  },\n  {\n    \"name\": \"torch.global_slot.get\",\n    \"summary\": \"Get the value stored in a torch.global_slot\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slot\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$slot attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.global_slot.init\",\n    \"summary\": \"yield-like terminator for torch.initialize.global_slotsr region\",\n    \"description\": \"The operand to this op becomes the initial value of the parent\\n    torch.global_slot.\",\n    \"operands\": [\n      { \"name\": \"initialValue\", \"type\": \"AnyTorchType\" }\n    ],\n    \"assemblyFormat\": \"$initialValue attr-dict `:` qualified(type($initialValue))\"\n  },\n  {\n    \"name\": \"torch.global_slot.module_initializer\",\n    \"summary\": \"Module initializer for all `torch.global_slot` ops\",\n    \"description\": \"Initializer function that runs once at program startup to initialize\\n    all `torch.global_slot` ops in the module.\\n\\n    The only ops that should be in the module initializer should be ops\\n    generated by the IValue importer. This set avoids the need to define\\n    the behavior in case of certain kinds of side effects in the initializer\\n    (except for the side effect of updating the torch.global_slot ops with the\\n    `torch.initialize.global_slots` op).\",\n    \"regions\": [\n      { \"name\": \"initializer\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$initializer attr-dict\"\n  },\n  {\n    \"name\": \"torch.global_slot.set\",\n    \"summary\": \"Set the value stored in a torch.global_slot\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slot\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$slot `=` $value attr-dict `:` qualified(type($value))\"\n  },\n  {\n    \"name\": \"torch.hop_flex_attention\",\n    \"summary\": \"Computes the flex_attention operation (1-1 with torch._higher_order_ops.flex_attention)\",\n    \"description\": \"FlexAttention operation with flexible block-sparse attention patterns.\\n\\n    Args:\\n      query: Query tensor [B, H, M, K]\\n      key: Key tensor [B, H, N, K]\\n      value: Value tensor [B, H, N, Ev]\\n      scale: Optional float for scaling attention scores (None means 1/sqrt(head_dim))\\n      return_lse: Bool to return log-sum-exp values\\n\\n    Attributes:\\n      score_mod_fn: Optional function symbol reference for score modification\\n      mask_mod_fn: Optional function symbol reference for mask modification\\n\\n    # TODO: kernel_options: Dict attributes for performance tuning (block_size, num_warps, etc.)\\n\\n    Returns:\\n      output: Result tensor [B, H, M, Ev]\\n      logsumexp: Optional log-sum-exp tensor [B, H, M] (if return_lse=True)\\n      max_scores: Optional max-scores tensor [B, H, M] (if return_max_scores=True)\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"key\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"return_lse\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"return_max_scores\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"logsumexp\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"max_scores\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"score_mod_fn\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" },\n      { \"name\": \"mask_mod_fn\", \"type\": \"OptionalAttr<FlatSymbolRefAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.initialize.global_slots\",\n    \"summary\": \"Terminator for torch.global_slot.module_initializer region\",\n    \"description\": \"Atomically updates the value of all the global slots named in `slotSymNames`\\n    with the corresponding values provided in `initialValues`.\",\n    \"operands\": [\n      { \"name\": \"initialValues\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slotSymNames\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.linear_params.create\",\n    \"summary\": \"Create a `!torch.LinearParams`\",\n    \"operands\": [\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyTorchTensorType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_LinearParamsType\" }\n    ],\n    \"assemblyFormat\": \"$weight (`,` $bias^)? attr-dict `:` qualified(type($weight)) (`,` qualified(type($bias))^)?\"\n  },\n  {\n    \"name\": \"torch.method\",\n    \"summary\": \"Declare a method of a torch.class_type\",\n    \"description\": \"This op declaratively specifies that the parent torch.class_type has a\\n    method `name` which calls `function`. `function` is an unbound function.\\n    That is, it explicitly takes the torch.nn.Module as a parameter (no implicit\\n    \\\"self\\\" object).\\n\\n    If `private` is present, it indicates that external calls cannot be made\\n    to this method.\",\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"function\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"isPrivate\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`private` $isPrivate^)? $name `,` $function attr-dict\"\n  },\n  {\n    \"name\": \"torch.nn_module\",\n    \"summary\": \"Constructs a torch.nn.Module\",\n    \"description\": \"This op is used to represent a torch.nn.Module when importing a\\n    graph of Python objects.\\n\\n    This op returns a new torch.nn.Module as an SSA value, with a set of\\n    declaratively specified properties.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = torch.nn_module {\\n      torch.slot \\\"b\\\", %bool_true : !torch.bool\\n      torch.slot \\\"i\\\", %int3 : !torch.int\\n      torch.slot \\\"f\\\", %float : !torch.float\\n      torch.slot \\\"t\\\", %t : !torch.tensor\\n      torch.slot \\\"submodule\\\", %1 : !torch.nn.Module\\n    } : !torch.nn.Module<\\\"my_class_name\\\">\\n    ```\\n\\n    This op is tightly coupled to the `torch.class_type` op named in the\\n    `!torch.nn.Module<\\\"my_class_name\\\">` type. Each slot must match precisely\\n    with the corresponding `torch.attr` in the `torch.class_type`.\\n    See the documentation for `torch.class_type` for information.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NnModuleType\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$region attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.nn_module_terminator\",\n    \"summary\": \"Implicit terminator for torch.nn_module\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"torch.onnx.rotary_embedding\",\n    \"summary\": \"`rotary_embedding op : (Tensor, Tensor, Tensor, Tensor, int, int, int, int, float) -> (Tensor)`\",\n    \"description\": \"The `torch.onnx.rotary_embedding` operation is an op which is used\\n    specifically for supporting the Onnx's Rotary Embedding op. The\\n    reason for this is that the Onnx ops can't be directly lowered to\\n    Linalg and we have to map them to a legal Torch Dialect op, hence\\n    this op is used for that purpose.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"position_ids\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"cos_cache\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"sin_cache\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"interleaved\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"is_packed_batching\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"num_heads\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"rotary_embedding_dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.operator\",\n    \"summary\": \"Opaque torch operator\",\n    \"description\": \"Represents an invocation of a `torch::jit::Operator` for which we don't\\n    have a registered MLIR operation.\\n\\n    The `name` attribute contains the name that the MLIR op would have\\n    (excluding `torch.`) if we did have it registered, which allows easy\\n    cross referencing with `JITOperatorRegistryDump.txt`.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"regions\", \"type\": \"VariadicRegion<AnyRegion>\" }\n    ],\n    \"assemblyFormat\": \"$name `(` $operands `)` attr-dict `:` functional-type($operands, $results) $regions\"\n  },\n  {\n    \"name\": \"torch.operator_terminator\",\n    \"summary\": \"Implicit terminator for torch.operator\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict `:` type($operands)\"\n  },\n  {\n    \"name\": \"torch.overwrite.tensor.contents\",\n    \"summary\": \"Ovewrite the contents of tensor with values from another.\",\n    \"description\": \"Replaces the contents of `overwritten` with corresponding values from\\n    `value`.\\n\\n    Immediately after this op has completed, indexing `overwritten` will result\\n    in identical values as indexing into `value`. Of course, later ops\\n    might mutate `overwritten`, so this relationship need not hold for the\\n    entire program. This op only updates the tensor data (not metadata).\\n    In other words, it cannot change the (dynamic) shape of the overwritten tensor.\\n\\n    This op does not have the AllowsTypeRefinement trait because the types of the\\n    two operands are coupled. Only places that know how to simultaneously update\\n    both types should be changing the type of this op.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Torch_ValueTensorType\" },\n      { \"name\": \"overwritten\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'value', 'overwritten', 'cast<ValueTensorType>($_self).getWithoutValueSemantics()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `overwrites` $overwritten attr-dict\\n      `:` qualified(type($value)) `,` qualified(type($overwritten))\"\n  },\n  {\n    \"name\": \"torch.per_tensor_affine.create\",\n    \"summary\": \"Create a per-tensor-affine quantized tensor\",\n    \"description\": \"Create a quantized tensor.\\n\\n    Quantization formula is:\\n    ```\\n    Q(x, scale, zero_point) = round(x/scale + zero_point)\\n    ```\\n\\n    See:\\n    https://pytorch.org/docs/stable/quantization.html#quantized-tensors\",\n    \"operands\": [\n      { \"name\": \"int_repr\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"offset\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"assemblyFormat\": \"$int_repr `,` $scale `,` $offset attr-dict\\n    `:` qualified(type($int_repr)) `,` qualified(type($scale)) `,` qualified(type($offset)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.abs.Scalar\",\n    \"summary\": \"Generated op for `prim::abs.Scalar : (Scalar) -> (Scalar)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.CallMethod\",\n    \"summary\": \"TorchScript prim::CallMethod op\",\n    \"operands\": [\n      { \"name\": \"receiver\", \"type\": \"Torch_NnModuleType\" },\n      { \"name\": \"methodOperands\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$receiver `[` $name `]` `(` $methodOperands `)` attr-dict `:` qualified(type($receiver)) `,` functional-type($methodOperands, $result)\"\n  },\n  {\n    \"name\": \"torch.prim.CreateObject\",\n    \"summary\": \"TorchScript prim::CreateObject op\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NnModuleType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.device\",\n    \"summary\": \"Generated op for `prim::device : (Tensor) -> (Device)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_DeviceType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.DictConstruct\",\n    \"summary\": \"TorchScript prim::DictConstruct op\",\n    \"operands\": [\n      { \"name\": \"keys\", \"type\": \"Variadic<AnyTorchDictKeyType>\" },\n      { \"name\": \"values\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_DictType\" }\n    ],\n    \"assemblyFormat\": \"`keys` `(` ($keys^ `:` qualified(type($keys)))? `)` `values` `(` ($values^ `:` qualified(type($values)))? `)` attr-dict `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.dtype\",\n    \"summary\": \"Generated op for `prim::dtype : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.Enter\",\n    \"summary\": \"enter operation\",\n    \"description\": \"This op represents a prim::Enter node in the Python object graph.\",\n    \"operands\": [\n      { \"name\": \"inp\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NoneType\" }\n    ],\n    \"assemblyFormat\": \"$inp attr-dict `:` qualified(type($inp))\"\n  },\n  {\n    \"name\": \"torch.prim.Exit\",\n    \"summary\": \"exit operation\",\n    \"description\": \"This op represents a prim::Exit node in the Python object graph.\",\n    \"operands\": [\n      { \"name\": \"inp\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"assemblyFormat\": \"$inp attr-dict `:` qualified(type($inp)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.GetAttr\",\n    \"summary\": \"TorchScript prim::GetAttr op\",\n    \"operands\": [\n      { \"name\": \"receiver\", \"type\": \"Torch_NnModuleType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$receiver `[` $name `]` attr-dict `:` qualified(type($receiver)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.If\",\n    \"summary\": \"TorchScript prim::If op\",\n    \"description\": \"This op (together with prim.If.yield) define a conditional control flow\\n    construct. It is analogous to `scf.if` for MLIR folks that are familiar\\n    with that. The main differences from that op are:\\n\\n    - `!torch.bool` condition value.\\n    - The \\\"else\\\" region is always present. This is reflective of invariants of\\n      the TorchScript IR.\\n    - No special prettiness for the \\\"no yielded values\\\" case. These are\\n      interesting for modeling mostly-non-SSA programs, but TorchScript IR\\n      is already in SSA form.\\n\\n    See: https://github.com/pytorch/pytorch/blob/master/torch/csrc/jit/OVERVIEW.md#if\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"thenRegion\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"elseRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.If.yield\",\n    \"summary\": \"yield-like terminator for torch.prim.If\",\n    \"description\": \"Does not correspond to any torch prim op directly (the way that they model\\n    blocks has a built-in notion of yield-like terminator).\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` qualified(type($results)))?\"\n  },\n  {\n    \"name\": \"torch.prim.layout\",\n    \"summary\": \"Generated op for `prim::layout : (Tensor) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.ListConstruct\",\n    \"summary\": \"TorchScript prim::ListConstruct op\",\n    \"operands\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchListType\" }\n    ],\n    \"assemblyFormat\": \"$elements attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"torch.prim.ListUnpack\",\n    \"summary\": \"TorchScript prim::ListUnpack op\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($operand)) `->` qualified(type($results))\"\n  },\n  {\n    \"name\": \"torch.prim.Load\",\n    \"summary\": \"load operation\",\n    \"description\": \"This op represents a prim::Load node in the Python object graph.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.Loop\",\n    \"summary\": \"TorchScript prim::Loop op\",\n    \"description\": \"This op (together with prim.Loop.condition) define a looping construct\\n    that combines `for` and `while` behavior.\\n\\n    See: https://github.com/pytorch/pytorch/blob/master/torch/csrc/jit/OVERVIEW.md#loops\",\n    \"operands\": [\n      { \"name\": \"maxTripCount\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"initialCondition\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"iterArgsInit\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$maxTripCount `,` $initialCondition `,` `init` `(` $iterArgsInit `)` $region\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"torch.prim.Loop.condition\",\n    \"summary\": \"yield-like terminator for torch.prim.Loop\",\n    \"description\": \"Does not correspond to any torch prim op directly (the way that they model\\n    blocks has a built-in notion of yield-like terminator).\",\n    \"operands\": [\n      { \"name\": \"shouldContinue\", \"type\": \"Torch_BoolType\" },\n      { \"name\": \"iterArgs\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"$shouldContinue `,`\\n    `iter` `(` ($iterArgs^ `:` qualified(type($iterArgs)))? `)` attr-dict\"\n  },\n  {\n    \"name\": \"torch.prim.max.int\",\n    \"summary\": \"Generated op for `prim::max.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.max.self_int\",\n    \"summary\": \"Generated op for `prim::max.self_int : (int[]) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.min.int\",\n    \"summary\": \"Generated op for `prim::min.int : (int, int) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"b\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.min.self_int\",\n    \"summary\": \"Generated op for `prim::min.self_int : (int[]) -> (int)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.NumToTensor.Scalar\",\n    \"summary\": \"Generated op for `prim::NumToTensor.Scalar : (Scalar) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchScalarType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.Print\",\n    \"summary\": \"Generated op for `prim::Print : (...) -> ()`\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $operands `)` attr-dict `:` qualified(type($operands))\"\n  },\n  {\n    \"name\": \"torch.prim.RaiseException\",\n    \"summary\": \"Generated op for `prim::RaiseException : (str, str?) -> ()`\",\n    \"operands\": [\n      { \"name\": \"msg\", \"type\": \"Torch_StringType\" },\n      { \"name\": \"cls\", \"type\": \"AnyTorchOptionalStringType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.SetAttr\",\n    \"summary\": \"TorchScript prim::SetAttr op\",\n    \"operands\": [\n      { \"name\": \"receiver\", \"type\": \"Torch_NnModuleType\" },\n      { \"name\": \"value\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$receiver `[` $name `]` `=` $value attr-dict `:` qualified(type($receiver)) `,` qualified(type($value))\"\n  },\n  {\n    \"name\": \"torch.prim.Store\",\n    \"summary\": \"store operation\",\n    \"description\": \"This op represents a prim::Store node in the Python object graph.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name `,` $value attr-dict `:` qualified(type($value))\"\n  },\n  {\n    \"name\": \"torch.prim.tolist\",\n    \"summary\": \"Generated op for `prim::tolist : (...) -> (...)`\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"`(` $operands `)` attr-dict `:` qualified(type($operands)) `->` qualified(type($results))\"\n  },\n  {\n    \"name\": \"torch.prim.TupleConstruct\",\n    \"summary\": \"TorchScript prim::TupleConstruct op\",\n    \"description\": \"Note: This op does not allow trivial type refinement, because the\\n    operand types and the result types must be in correspondence.\",\n    \"operands\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_TupleType\" }\n    ],\n    \"assemblyFormat\": \"$elements attr-dict `:` qualified(type($elements)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.prim.TupleIndex\",\n    \"summary\": \"Generated op for `prim::TupleIndex : (Any, int) -> (Any)`\",\n    \"operands\": [\n      { \"name\": \"tup\", \"type\": \"AnyTorchType\" },\n      { \"name\": \"i\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.TupleUnpack\",\n    \"summary\": \"Generated op for `prim::TupleUnpack : (Any) -> (...)`\",\n    \"operands\": [\n      { \"name\": \"tup\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"$tup attr-dict `:` qualified(type($tup)) `->` qualified(type($results))\"\n  },\n  {\n    \"name\": \"torch.prim.unchecked_cast\",\n    \"summary\": \"Generated op for `prim::unchecked_cast : (t) -> (t)`\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"AnyTorchType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prim.Uninitialized\",\n    \"summary\": \"Generated op for `prim::Uninitialized : () -> (Any)`\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.collapse\",\n    \"summary\": \"Generated op for `prims::collapse : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"start\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"end\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.convert_element_type\",\n    \"summary\": \"Generated op for `prims::convert_element_type : (Tensor, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.iota\",\n    \"summary\": \"Generated op for `prims::iota : (int, int, int, int, Device, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"length\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"start\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"step\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dtype\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"device\", \"type\": \"Torch_DeviceType\" },\n      { \"name\": \"requires_grad\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.split_dim\",\n    \"summary\": \"Generated op for `prims::split_dim : (Tensor, int, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dim\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"outer_length\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.sqrt\",\n    \"summary\": \"Generated op for `prims::sqrt : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.squeeze\",\n    \"summary\": \"Generated op for `prims::squeeze : (Tensor, int[]) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dimensions\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.sum\",\n    \"summary\": \"Generated op for `prims::sum : (Tensor, int[]?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"inp\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"output_dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.var\",\n    \"summary\": \"Generated op for `prims::var : (Tensor, int[]?, float?, int?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"inp\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"dims\", \"type\": \"AnyTorchOptionalListOfTorchIntType\" },\n      { \"name\": \"correction\", \"type\": \"AnyTorchOptionalFloatType\" },\n      { \"name\": \"output_dtype\", \"type\": \"AnyTorchOptionalIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.prims.view_of\",\n    \"summary\": \"Generated op for `prims::view_of : (Tensor) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.promote_dtypes\",\n    \"summary\": \"`promote_dtypes op : (int?[], int[]) -> (int)`\",\n    \"description\": \"This op is generated when the python function\\n    `__torch_mlir_internal_promote_dtypes` is used in a dtype refinement\\n    function. It represents the type promotion logic used by PyTorch to\\n    determine result types.\\n\\n    The first argument is a list of optional ranks for each of the inputs\\n    being used for promotion. The ranks are optional to allow representing\\n    `Scalar` inputs, which follow their own set of promotion rules.\\n\\n    The second argument is a list of dtypes for each of the inputs being used\\n    for promotion.\\n\\n    The order of the values in each list must be the same. In other words,\\n    the ith rank and the ith dtype must be from the same Scalar/Tensor.\\n\\n    It is an error to call this op with empty lists or lists of different size.\",\n    \"operands\": [\n      { \"name\": \"ranks\", \"type\": \"AnyTorchListOfOptionalIntType\" },\n      { \"name\": \"dtypes\", \"type\": \"AnyTorchListOfTorchIntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"assemblyFormat\": \"$ranks `,` $dtypes attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"torch.quantized.linear\",\n    \"summary\": \"Generated op for `quantized::linear : (Tensor, __torch__.torch.classes.quantized.LinearPackedParamsBase, float, int) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"W_prepack\", \"type\": \"Torch_LinearParamsType\" },\n      { \"name\": \"Y_scale_i\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"Y_zero_point_i\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.runtime.assert\",\n    \"summary\": \"Runtime Assertion\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$condition `,` $message attr-dict\"\n  },\n  {\n    \"name\": \"torch.shape.calculate\",\n    \"summary\": \"Shape calculation encapsulation op\",\n    \"description\": \"The `torch.shape.calculate` op captures a shape calculation\\n    (in the region `calculation`) which calculates the shapes for\\n    the set of values yielded by the `body` region.\\n\\n    The `calculation` region yields a `!torch.list<int>` for each\\n    value yielded by the `body` region.\\n\\n    Conceptually, the `calculation` region executes first, then `body`\\n    region. So the `calculation` region can also contain arbitrary\\n    assertions or side-effecting code which guard the validity of the execution\\n    of the body (typically by terminating the program with a\\n    torch.prim.RaiseException op).\\n\\n    The program has undefined behavior if the values yielded by the `body`\\n    region do not have the shapes yielded by the `calculation` region.\",\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"calculation\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$body `shapes` $calculation attr-dict `:` type($results)\"\n  },\n  {\n    \"name\": \"torch.shape.calculate.yield\",\n    \"summary\": \"yield-like terminator for torch.shape.calculate\",\n    \"description\": \"This op terminates the `body` region of a `torch.shape.calculate` op.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"torch.shape.calculate.yield.shapes\",\n    \"summary\": \"yield-like terminator for torch.shape.calculate shape region\",\n    \"description\": \"This op terminates the `shapeCalculation` region of a\\n    `torch.shape.calculate` op.\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTorchListOfTorchIntType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($results^ `:` type($results))?\"\n  },\n  {\n    \"name\": \"torch.slot\",\n    \"summary\": \"Define the value of a slot of a torch.nn.Module\",\n    \"description\": \"This op specifies that the initial value of the slot `name` of the\\n    parent torch.nn_module should be `value`, which is allowed to be an\\n    arbitrary Torch-compatible SSA value, including other !torch.nn.Module's.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTorchType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$name `,` $value attr-dict `:` qualified(type($value))\"\n  },\n  {\n    \"name\": \"torch.symbolic_int\",\n    \"summary\": \"Symbolic int representing a dynamic dimension\",\n    \"description\": \"The `torch.symbolic_int` operation captures a dynamic dimension on the\\n    global function arguments as exported by TorchDynamo (torch.export).\\n    It associates the shape symbols (i.e. \\\"s0\\\", \\\"s1\\\") with the\\n    global SSA values (i.e. `%0`, `%1`) that is then referenced\\n    to bind shapes on op results.\\n\\n    Additionally, the operation annotates `min_val` and `max_val` attributes\\n    denoting the range constraints for the dynamic dimension. This may be\\n    useful for modeling runtime shape guards, or compile-time optimizations\\n    based on the shape bounds (min, opt, max) on results of ops / regions.\\n\\n    Example:\\n    ```\\n    %0 = torch.symbolic_int \\\"s0\\\" {min_val = 5, max_val = 10} : !torch.int\\n    %1 = torch.symbolic_int \\\"s1\\\" {min_val = 2, max_val = 20} : !torch.int\\n    ```\\n\\n    In this case, we see that `s0` has the range [5, 10] and `s1` has the\\n    range [2, 20]. When unspecified, the range constraints feeding in from\\n    TorchDynamo default to [0, INT_MAX] (or [2, INT_MAX] in older PyTorch\\n    releases). In either case, the interpretation (as specified by TorchDynamo)\\n    is that the dynamic dimension is assumed to be not 0 or 1. This is not a\\n    bug, and does not necessarily mean that the exported program will not work\\n    for dimensions 0 or 1. For an in-depth discussion of this topic, see\\n    [The 0/1 Specialization Problem](https://docs.google.com/document/d/16VPOa3d-Liikf48teAOmxLc92rgvJdfosIy-yoT38Io/edit?fbclid=IwAR3HNwmmexcitV0pbZm_x1a4ykdXZ9th_eJWK-3hBtVgKnrkmemz6Pm5jRQ#heading=h.ez923tomjvyk).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_IntType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"symbol_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"min_val\", \"type\": \"I64Attr\" },\n      { \"name\": \"max_val\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$symbol_name ` ` `{` `min_val` `=` $min_val `,` `max_val` `=` $max_val `}` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"torch.tensor_static_info_cast\",\n    \"summary\": \"Adds/removes static information from a tensor type.\",\n    \"description\": \"This op does not imply any runtime code. Semantically it is an identity\\n    function. However, it statically annotates (or erases) shape and dtype\\n    information from a tensor type.\\n\\n    This op *cannot* be used to add/remove value semantics from a tensor.\\n    For converting between the value-semantic and non-value-semantic domains,\\n    use `torch.copy.to_tensor` and `torch.copy.from_tensor`. This op is kept\\n    separate to prevent canonicalizations from accidentally dropping static\\n    information. In most cases, after running the `torch-refine-types` pass,\\n    this op becomes a no-op (the pass will incorporate the static information\\n    into other ops that allow type refinement).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` qualified(type($operand)) `to` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.tensor.literal\",\n    \"summary\": \"Create a value of !torch.tensor type from a literal\",\n    \"description\": \"Example:\\n    ```\\n    %0 = torch.tensor.literal(dense<0.0> : tensor<3x5xf32>) : !torch.tensor\\n    %1 = torch.tensor.literal(dense<0.0> : tensor<3xf32>) : !torch.tensor<[3],f32>\\n    ```\\n\\n    This op covers a typical frontend use case of creating a type-erased\\n    `!torch.tensor`. Inside the compiler, we decompose it into\\n    `torch.vtensor.literal` which is easier to analyze and transform.\\n\\n    Note: This op is not called \\\"constant\\\" because the created tensor is not\\n    \\\"constant\\\" in any meaning of that word.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_NonValueTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"torch.torchvision.deform_conv2d\",\n    \"summary\": \"Generated op for `torchvision::deform_conv2d : (Tensor, Tensor, Tensor, Tensor, Tensor, int, int, int, int, int, int, int, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"weight\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"offset\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"mask\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"bias\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"stride_h\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"stride_w\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"pad_h\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"pad_w\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dilation_h\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"dilation_w\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"offset_groups\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"use_mask\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.torchvision.nms\",\n    \"summary\": \"Generated op for `torchvision::nms : (Tensor, Tensor, float) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"dets\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"scores\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"iou_threshold\", \"type\": \"Torch_FloatType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.torchvision.roi_align\",\n    \"summary\": \"Generated op for `torchvision::roi_align : (Tensor, Tensor, float, int, int, int, bool) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"rois\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"spatial_scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"pooled_height\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"pooled_width\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"sampling_ratio\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"aligned\", \"type\": \"Torch_BoolType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.torchvision.roi_pool\",\n    \"summary\": \"Generated op for `torchvision::roi_pool : (Tensor, Tensor, float, int, int) -> (Tensor, Tensor)`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"rois\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"spatial_scale\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"pooled_height\", \"type\": \"Torch_IntType\" },\n      { \"name\": \"pooled_width\", \"type\": \"Torch_IntType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result0\", \"type\": \"AnyTorchOptionalTensorType\" },\n      { \"name\": \"result1\", \"type\": \"AnyTorchOptionalTensorType\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"torch.valsem.aten.bernoulli.float\",\n    \"summary\": \"`bernoulli.float op : (Tensor, float, Generator?) -> (Tensor)`\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"AnyTorchTensorType\" },\n      { \"name\": \"p\", \"type\": \"Torch_FloatType\" },\n      { \"name\": \"generator\", \"type\": \"AnyTorchOptionalGeneratorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTorchTensorType\" }\n    ],\n    \"assemblyFormat\": \"$self `,` $p `,` $generator attr-dict `:` type($self) `,` type($p) `,` type($generator) `->` type($result)\"\n  },\n  {\n    \"name\": \"torch.vtensor.literal\",\n    \"summary\": \"Create a value of !torch.vtensor type from a literal\",\n    \"description\": \"Example:\\n    ```\\n    %0 = torch.vtensor.literal(dense<0.0> : tensor<3x5xf32>) : !torch.vtensor<[3,5],f32>\\n    %1 = torch.vtensor.literal(dense<0.0> : tensor<3xf32>) : !torch.vtensor<[3],f32>\\n    ```\\n\\n    Unlike `torch.tensor.literal`, which covers a typical frontend use case\\n    and allows type refinement, this op always has a maximally resolved type\\n    (which is always possible, because it is created from a literal). This\\n    has a stronger set of invariants that better fit the needs of the\\n    compiler internals.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Torch_ValueTensorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `)` attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"tosa.abs\",\n    \"summary\": \"Elementwise abs operator.\",\n    \"description\": \"Elementwise absolute value operation.\\n\\n    This operation is not pure. Undefined behaviour may occur if the\\n    calculated result underflows.\\n\\n    Example:\\n\\n    ```mlir\\n    %output = tosa.abs(%input1) : (tensor<21x3xf32>) -> tensor<21x3xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.add\",\n    \"summary\": \"Elementwise addition operator.\",\n    \"description\": \"Elementwise addition of input1 and input2. Axis of size 1 will be broadcast,\\n    as necessary. Rank of input tensors must match.\\n\\n    This operation is not pure. Undefined behaviour may occur if the calculated\\n    result overflows.\\n\\n    Example:\\n\\n    ```mlir\\n    // Elementwise addition.\\n    %out = tosa.add %input1, %input2 : tensor<12x6xf32>, tensor<12x6xf32> -> tensor<12x6xf32>\\n\\n    // Elementwise addition with broadcasting.\\n    %out = tosa.add %input1, %input2 : tensor<12x6xsi32>, tensor<1x1xsi32> -> tensor<12x6xsi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.add_shape\",\n    \"summary\": \"Elementwise addition of shapes.\",\n    \"description\": \"Elementwise addition of input1 and input2. Size of shapes must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.apply_scale\",\n    \"summary\": \"Rescale scalar operator for Tosa tensor operators\",\n    \"description\": \"Applies rescaling for fixed point values. This behavior is replicated in\\n    multiple quantized operations (mul, convolution, rescale, matmul, pooling).\\n\\n    The commonplace implementation is to use i64 operations to avoid integer\\n    overflow with target specific implementations can use native operations to\\n    avoid wider than necessary types.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"Tosa_IntLike\" },\n      { \"name\": \"multiplier\", \"type\": \"Tosa_IntLike\" },\n      { \"name\": \"shift\", \"type\": \"Tosa_Int8Like\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_IntLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rounding_mode\", \"type\": \"Tosa_RoundingModeAttr{SINGLE_ROUND|INEXACT_ROUND|DOUBLE_ROUND}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.argmax\",\n    \"summary\": \"Perform argmax on the input.\",\n    \"description\": \"This returns the index with the largest value across the given axis of the\\n    input tensor. If multiple locations have equal values, returns the first\\n    match along the search axis.\\n\\n    This operation is not pure. Undefined behaviour may occur if the max index\\n    is out of bounds for the output data type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.arithmetic_right_shift\",\n    \"summary\": \"Elementwise Arithmetic Right Shift.\",\n    \"description\": \"Elementwise arithmetic right shift of input1 by the amount specified in\\n    input2. Axis of size 1 will be broadcast, as necessary. Rank of input tensors\\n    must match.\\n\\n    This operation is not pure. Undefined behaviour may occur if the specified\\n    shift is out of range.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"round\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.assert_equal_shape\",\n    \"summary\": \"Verify two shapes are equal.\",\n    \"description\": \"Verify input1 and input2 are equal. If allow_broadcast is set, shapes which\\n      are broadcast compatible are allowed.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"allow_broadcast\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.avg_pool2d\",\n    \"summary\": \"Performs average pooling on the input.\",\n    \"description\": \"This performs an average pooling over the given input tensor. A sliding\\n    window of size given by <kernel size> is passed over the input tensor, with\\n    the mean value being placed in the output tensor. When calculating the\\n    average, only the number of valid input tensor values, but not padding, are\\n    used to calculate the divisor.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"input_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"output_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<4>]>\" },\n      { \"name\": \"acc_type\", \"type\": \"TypeAttrOf<Tosa_AccType>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.bitwise_and\",\n    \"summary\": \"Bitwise AND operator.\",\n    \"description\": \"Elementwise bitwise AND of input1 and input2. Axis of size 1\\n    will be broadcast as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.bitwise_not\",\n    \"summary\": \"Bitwise NOT operator.\",\n    \"description\": \"Elementwise bitwise NOT of input tensor.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.bitwise_or\",\n    \"summary\": \"Bitwise OR operator.\",\n    \"description\": \"Elementwise bitwise OR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.bitwise_xor\",\n    \"summary\": \"Bitwise XOR operator.\",\n    \"description\": \"Elementwise bitwise XOR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.cast\",\n    \"summary\": \"Cast operation.\",\n    \"description\": \"Casts a tensor from one data type to another.\\n    * This table is showing the supported conversions from the TOSA Specification.\\n    * The MLIR dialect here can be used to represent other conversions.\\n\\n    | Mode                     | Input   | Output  |\\n    |--------------------------|---------|---------|\\n    | fp16 to fp32             | float16 | float32 |\\n    | fp16 to int 16           | float16 | int16   |\\n    | fp16 to int 32           | float16 | int32   |\\n    | fp16 to int 8            | float16 | int8    |\\n    | fp32 to fp16             | float32 | float16 |\\n    | fp32 to int 16           | float32 | int16   |\\n    | fp32 to int 32           | float32 | int32   |\\n    | fp32 to int 8            | float32 | int8    |\\n    | int 16 to fp16           | int16   | float16 |\\n    | int 16 to fp32           | int16   | float32 |\\n    | int 32 to fp16           | int32   | float16 |\\n    | int 32 to fp32           | int32   | float32 |\\n    | int 8 to fp16            | int8    | float16 |\\n    | int 8 to fp32            | int8    | float32 |\\n    | bool to int 16           | Boolean | int16   |\\n    | bool to int 32           | Boolean | int32   |\\n    | bool to int 8            | Boolean | int8    |\\n    | int 16 to bool           | int16   | Boolean |\\n    | int 16 to int 32         | int16   | int32   |\\n    | int 16 to int 8          | int16   | int8    |\\n    | int 32 to bool           | int32   | Boolean |\\n    | int 32 to int 16         | int32   | int16   |\\n    | int 32 to int 8          | int32   | int8    |\\n    | int 8 to bool            | int8    | Boolean |\\n    | int 8 to int 16          | int8    | int16   |\\n    | int 8 to int 32          | int8    | int32   |\\n    | bf16 to fp32             | bf16    | float32 |\\n    | bf16 to int 16           | bf16    | int16   |\\n    | bf16 to int 32           | bf16    | int32   |\\n    | bf16 to int 8            | bf16    | int8    |\\n    | fp32 to bf16             | float32 | bf16    |\\n    | int 16 to bf16           | int16   | bf16    |\\n    | int 32 to bf16           | int32   | bf16    |\\n    | int 8 to bf16            | int8    | bf16    |\\n    | bf16 to fp8e4m3          | bf16    | fp8e4m3 |\\n    | fp8e4m3 to bf16          | fp8e4m3 | bf16    |\\n    | bf16 to fp8e5m2          | bf16    | fp8e5m2 |\\n    | fp8e5m2 to bf16          | fp8e5m2 | bf16    |\\n    | fp16 to fp8e4m3          | float16 | fp8e4m3 |\\n    | fp32 to fp8e4m3          | float32 | fp8e4m3 |\\n    | fp8e4m3 to fp16          | fp8e4m3 | float16 |\\n    | fp8e4m3 to fp32          | fp8e4m3 | float32 |\\n    | fp16 to fp8e5m2          | float16 | fp8e5m2 |\\n    | fp32 to fp8e5m2          | float32 | fp8e5m2 |\\n    | fp8e5m2 to fp16          | fp8e5m2 | float16 |\\n    | fp8e5m2 to fp32          | fp8e5m2 | float32 |\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.cast_from_block_scaled\",\n    \"summary\": \"Apply scales from a scale tensor to the values in a value tensor\",\n    \"description\": \"Apply the scales from a scale tensor to the values in a value tensor, casting\\n    the result to the output type. The block dimension must be the last dimension\\n    of the tensor.\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"Tosa_MXFPDataTensorAtLeast1D\" },\n      { \"name\": \"input_scale\", \"type\": \"Tosa_MXFPScaleTensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_data\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"Tosa_BlockSizeAttr{BLOCK_SIZE_32}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.cast_to_block_scaled\",\n    \"summary\": \"Calculate scale tensor values per block, output to separate scale and data tensors.\",\n    \"description\": \"Calculate a scale value per block of input values and use that to calculate\\n    scaled data values from an input tensor. The output tensors are cast to the\\n    specified scale and value types. The block dimension will be the last dimension\\n    of the tensor.\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_data\", \"type\": \"Tosa_MXFPDataTensorAtLeast1D\" },\n      { \"name\": \"output_scale\", \"type\": \"Tosa_MXFPScaleTensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"Tosa_BlockSizeAttr{BLOCK_SIZE_32}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.ceil\",\n    \"summary\": \"Elementwise ceil operator.\",\n    \"description\": \"Elementwise ceiling operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.clamp\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes clamp(features, min, max).\",\n    \"description\": \"Clamp to an arbitrary minimum and maximum value.\\n    Maximum and minimum values are specified as values in the range of the\\n    input type.\\n    No zero point subtraction is done to the values, thus to clamp to the zero\\n    point value, the zero point itself should be supplied as the minimum value.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min_val\", \"type\": \"Tosa_IntOrFloatAttr\" },\n      { \"name\": \"max_val\", \"type\": \"Tosa_IntOrFloatAttr\" },\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.clz\",\n    \"summary\": \"Elementwise count leading zero operator.\",\n    \"description\": \"Elementwise count leading zeros operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.concat\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Concatenates tensors along one dimension.\",\n    \"description\": \"Concatenate a list of tensors along a given axis.\\n    No data conversion happens during a concat operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Variadic<Tosa_TensorAtLeast1D>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.concat_shape\",\n    \"summary\": \"Concatenates a list of shapes.\",\n    \"description\": \"Concatenates a list of shapes into a new shape with length equal to the sum\\n    of the lengths of the inputs.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<Tosa_Shape>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.cond_if\",\n    \"summary\": \"Conditional if operator.\",\n    \"description\": \"Evaluates a Boolean condition and then takes one of two distinct execution\\n    paths. This implements the semantic If-then-else structure.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"Tosa_I1Tensor\" },\n      { \"name\": \"input_list\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_list\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_graph\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_graph\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.const\",\n    \"summary\": \"Constant operator.\",\n    \"description\": \"A node containing constant data for use as the input to an operation. May\\n    hold data in any of the supported data formats.\\n\\n    Example:\\n\\n    ```mlir\\n    // Generic form\\n    %out = \\\"tosa.const\\\"() {values = dense<0> : tensor<2x3xi32>} : () -> tensor<2x3xi32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"ElementsAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"FirstAttrDerivedResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tosa.const_shape\",\n    \"summary\": \"Constant Shape operator.\",\n    \"description\": \"A node containing a constant shape.\\n\\n    Example:\\n\\n    ```mlir\\n    // Generic form\\n    %out = \\\"tosa.const_shape\\\"() {values = dense<0> : tensor<4xindex>} : () -> !tosa.shape<4>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"values\", \"type\": \"IndexElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.conv2d\",\n    \"category\": \"Layer\",\n    \"summary\": \"2D Convolution operator.\",\n    \"description\": \"Performs a 2D convolution over the given tensor input, using the weight\\n    tensor. Implementations may choose to skip calculation of multiplies in\\n    the padding area.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"weight\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"bias\", \"type\": \"Tosa_Tensor1D\" },\n      { \"name\": \"input_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"weight_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<4>]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"dilation\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"acc_type\", \"type\": \"TypeAttrOf<Tosa_AccType>\" },\n      { \"name\": \"local_bound\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.conv2d_block_scaled\",\n    \"summary\": \"Performs two dimensional convolution using block scaled tensors.\",\n    \"description\": \"Performs a 2D convolution over the given input data and scales, using\\n    the weight data and scales. Implementations may choose to skip calculation\\n    of multiplies in the padding area.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"Tosa_MXFPDataTensor4D\" },\n      { \"name\": \"input_scale\", \"type\": \"Tosa_MXFPScaleTensor4D\" },\n      { \"name\": \"weight_data\", \"type\": \"Tosa_MXFPDataTensor4D\" },\n      { \"name\": \"weight_scale\", \"type\": \"Tosa_MXFPScaleTensor4D\" },\n      { \"name\": \"bias\", \"type\": \"Tosa_Tensor1D\" },\n      { \"name\": \"pad\", \"type\": \"Rank4TosaShape\" },\n      { \"name\": \"stride\", \"type\": \"Rank2TosaShape\" },\n      { \"name\": \"dilation\", \"type\": \"Rank2TosaShape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"Tosa_BlockSizeAttr{BLOCK_SIZE_32}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.conv3d\",\n    \"category\": \"Layer\",\n    \"summary\": \"3D Convolution operator.\",\n    \"description\": \"Performs a 3D convolution over the given input tensor. Implementations\\n    may choose to skip calculation of multiplies in the padding area.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor5D\" },\n      { \"name\": \"weight\", \"type\": \"Tosa_Tensor5D\" },\n      { \"name\": \"bias\", \"type\": \"Tosa_Tensor1D\" },\n      { \"name\": \"input_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"weight_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor5D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<6>]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<3>]>\" },\n      { \"name\": \"dilation\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<3>]>\" },\n      { \"name\": \"acc_type\", \"type\": \"TypeAttrOf<Tosa_AccType>\" },\n      { \"name\": \"local_bound\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.cos\",\n    \"summary\": \"Elementwise cos operator.\",\n    \"description\": \"Elementwise cosine operation for values given in radians.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_FloatTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.custom\",\n    \"summary\": \"Custom operator wrapper for Tosa\",\n    \"description\": \"Hardware implementing TOSA may choose to add additional custom operators\\n    that are not expressed in the existing TOSA operations. These operators are\\n    not expected to be portable across TOSA implementations. The input and\\n    output signatures must be expressed in the corresponding TOSA node.\\n\\n    `operator_name` is a string that tells the backend which custom operator is\\n    being called.\\n\\n    `domain_name` is a string identifier which can help avoid name collisions on\\n    the identifier field.\\n\\n    `implementation_attrs` is a string which is a backend and identifier specific\\n    set of attributes to the custom operator.\\n\\n    `input_list` is the set of tensor inputs to the custom operator.\\n\\n    `output_list` is the list of tensors returned by the operator. The number of operators\\n    is backend specific.\\n\\n    Example:\\n\\n    ```mlir\\n    %out = tosa.custom %in {domain_name = \\\"tosa_mlir_test\\\", operator_name =\\n           \\\"custom_test\\\", implementation_attrs = \\\"\\\"}: (tensor<10xi32>) ->\\n           (tensor<10xi32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input_list\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_list\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operator_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"domain_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"implementation_attrs\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.depthwise_conv2d\",\n    \"summary\": \"Depthwise 2D Convolution operator.\",\n    \"description\": \"Performs 2D convolutions separately over each channel of the given tensor\\n    input, using the weight tensor. Implementations may choose to skip\\n    calculation of multiplies in the padding area.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"weight\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"bias\", \"type\": \"Tosa_Tensor1D\" },\n      { \"name\": \"input_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"weight_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<4>]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"dilation\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"acc_type\", \"type\": \"TypeAttrOf<Tosa_AccType>\" },\n      { \"name\": \"local_bound\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.dim\",\n    \"summary\": \"Extract size of dimension from input tensor.\",\n    \"description\": \"Returns a length 1 shape_t of the size of the input tensor for the given axis.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.div_ceil_shape\",\n    \"summary\": \"Elementwise ceiling divide of shapes.\",\n    \"description\": \"Elementwise divide of input1 by input2. The result of the divide is rounded up.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.div_floor_shape\",\n    \"summary\": \"Elementwise floor divide of shapes.\",\n    \"description\": \"Elementwise integer divide of input1 by input2. The result of the divide is rounded down.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.equal\",\n    \"summary\": \"Returns the truth value of (input1 == input2) element-wise.\",\n    \"description\": \"Elementwise comparison operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.erf\",\n    \"summary\": \"Computes gauss error function of input.\",\n    \"description\": \"Gauss error function: $ erf(x) = \\\\frac{2}{\\\\sqrt{\\\\pi}} \\\\int_{0}^{x} e^{-t^2} dt $\\n    For quantized integer data types, the TABLE operator should be used instead\\n    with the following definition. The ERF table has 513 entries each of\\n    16-bit precision and covering the input range -4.0 to +4.0 in steps of 1/64.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.exp\",\n    \"summary\": \"Elementwise exp operator.\",\n    \"description\": \"Elementwise e to the x operation\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.exp2_shape\",\n    \"summary\": \"Elementwise base-2 exponential of shapes.\",\n    \"description\": \"Computation of raising two to the power of each element in input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.fft2d\",\n    \"summary\": \"Performs FFT2D operation on the input.\",\n    \"description\": \"Performs a batched complex 2D Fast Fourier Transform over the input. The\\n    complex input values are constructed from the corresponding values in the\\n    input_real and input_imag tensors. The resulting values in the output are\\n    split into the output_real and output_imag tensors. No normalization is\\n    applied on either the forward or inverse versions of the operation.\\n\\n    Example:\\n\\n    ```mlir\\n     %output_real, %output_imag = tosa.fft2d %input_real, %input_imag : (tensor<8x9xf32>, tensor<8x9xf32>) -> (tensor<8x9xf32>, tensor<8x9xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input_real\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"input_imag\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_real\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"output_imag\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inverse\", \"type\": \"BoolAttr\" },\n      { \"name\": \"local_bound\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.floor\",\n    \"summary\": \"Elementwise floor operator.\",\n    \"description\": \"Elementwise floor operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Gather operation.\",\n    \"description\": \"Generate a tensor for which each element in the output is a subtensor of the\\n    values tensor based on the indices. N is the number of batches, W the number\\n    of indices in each batch, K the range of each index and C the number data\\n    channels for each index.\\n\\n    This operation is not pure. Undefined behaviour may occur if the specified\\n    indices are out of range.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"indices\", \"type\": \"Tosa_IndexTensor2D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.greater\",\n    \"summary\": \"Returns the truth value of (input1 > input2) element-wise.\",\n    \"description\": \"Elementwise greater than comparison operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.greater_equal\",\n    \"summary\": \"Returns the truth value of (input1 >= input2) element-wise.\",\n    \"description\": \"Elementwise comparison operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.identity\",\n    \"summary\": \"Identity operator.\",\n    \"description\": \"Returns a tensor with the same shape, type, and contents as the input.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.intdiv\",\n    \"summary\": \"Integer divide operator.\",\n    \"description\": \"Elementwise integer divide of input1 by input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match. The result of the\\n    divide is truncated towards zero. Expected use is for operations on\\n    non-scaled integers. Floating point divide should use RECIPROCAL and MUL.\\n    Quantized integer divide should use TABLE (for 1/x) and MUL.\\n\\n    This operation is not pure. Undefined behaviour may occur on division by zero.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Int32Or64Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Int32Or64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Int32Or64Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.log\",\n    \"summary\": \"Elementwise log operator.\",\n    \"description\": \"Elementwise natural logarithm operation\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.log2_ceil_shape\",\n    \"summary\": \"Elementwise ceil base-2 logarithm of shapes.\",\n    \"description\": \"Computation of the base two logarithm of each element in input. Result is rounded up.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.log2_floor_shape\",\n    \"summary\": \"Elementwise floor base-2 logarithm of shapes.\",\n    \"description\": \"Computation of the base two logarithm of each element in input. Result is rounded down.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.logical_and\",\n    \"summary\": \"Returns the truth value of input1 AND input2 element-wise.\",\n    \"description\": \"Elementwise logical AND of input1 and input2. Axis of size 1 will be\\n    broadcast, as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_I1Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.logical_left_shift\",\n    \"summary\": \"Elementwise Logical Left Shift.\",\n    \"description\": \"Elementwise logical left-shift of input1 by the amount specified in input2.\\n    Axis of size 1 will be broadcast, as necessary.\\n    Rank of input tensors must match.\\n\\n    This operation is not pure. Undefined behaviour may occur if the specified\\n    shift is out of range.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.logical_not\",\n    \"summary\": \"Returns the truth value of NOT input1 element-wise.\",\n    \"description\": \"Elementwise logical NOT of input.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.logical_or\",\n    \"summary\": \"Returns the truth value of x OR y element-wise.\",\n    \"description\": \"Elementwise logical OR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_I1Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.logical_right_shift\",\n    \"summary\": \"Elementwise Logical Right Shift.\",\n    \"description\": \"Elementwise logical right shift of input1 by the amount specified in input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors must\\n    match.\\n\\n    This operation is not pure. Undefined behaviour may occur if the specified\\n    shift is out of range.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.logical_xor\",\n    \"summary\": \"Returns the truth value of input1 XOR input2 element-wise.\",\n    \"description\": \"Elementwise logical XOR of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_I1Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_I1Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.matmul\",\n    \"summary\": \"Matrix multiplication operator.\",\n    \"description\": \"Performs two dimensional matrix multiplications.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"b\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"a_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"b_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.matmul_t_block_scaled\",\n    \"summary\": \"Performs two dimensional matrix multiplications using block scaled tensors.\",\n    \"description\": \"Performs two dimensional matrix multiplications using block scaled tensors. The block\\n    dimension is always the the last dimension of the tensor, so the result is effectively\\n    a matrix multiply of A by the transposed B matrix. If the N dimension of input B is of\\n    size 1, the B matrix will be broadcast.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"a_data\", \"type\": \"Tosa_MXFPDataTensor3D\" },\n      { \"name\": \"a_scale\", \"type\": \"Tosa_MXFPScaleTensor3D\" },\n      { \"name\": \"b_data\", \"type\": \"Tosa_MXFPDataTensor3D\" },\n      { \"name\": \"b_scale\", \"type\": \"Tosa_MXFPScaleTensor3D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_data\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\", \"type\": \"Tosa_BlockSizeAttr{BLOCK_SIZE_32}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.max_pool2d\",\n    \"category\": \"Pool\",\n    \"summary\": \"Performs max pooling on the input.\",\n    \"description\": \"This performs a max pooling over the given input tensor. A sliding window of\\n    size given by <kernel size> is passed over the input tensor, with the\\n    maximum value being placed in the\\n    output tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"pad\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<4>]>\" },\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.max_shape\",\n    \"summary\": \"Elementwise maximum of shapes.\",\n    \"description\": \"Elementwise maximum of input1 and input2.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.maximum\",\n    \"summary\": \"Elementwise Maximum.\",\n    \"description\": \"Elementwise max of input1 and input2. Axis of size 1 will be broadcast, as\\n    necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.min_shape\",\n    \"summary\": \"Elementwise minimum of shapes.\",\n    \"description\": \"Elementwise minimum of input1 and input2.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.minimum\",\n    \"summary\": \"Elementwise Minimum.\",\n    \"description\": \"Elementwise minimum of input1 and input2. Axis of size 1\\n    will be broadcast, as necessary. Rank of input tensors must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.mod_shape\",\n    \"summary\": \"Elementwise modulo of shapes.\",\n    \"description\": \"Elementwise modulo of input1 divided by input2.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.mul\",\n    \"summary\": \"Multiplication operator.\",\n    \"description\": \"Elementwise multiplication (Hadamard product) of input1 and input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors must\\n    match.\\n\\n    This operation is not pure. Undefined behaviour may occur if the specifed\\n    shift is out of range or the result overflows.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"shift\", \"type\": \"Tosa_ScalarInt8Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.mul_shape\",\n    \"summary\": \"Elementwise multiplication of shapes.\",\n    \"description\": \"Elementwise multiplication of input1 and input2.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.negate\",\n    \"summary\": \"Elementwise negate operator.\",\n    \"description\": \"Elementwise negation operation.\\n\\n    This operation is not pure. Undefined behaviour may occur if the calculated\\n    result underflows or overflows.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input1_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"output_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.pad\",\n    \"category\": \"Transform\",\n    \"summary\": \"Pads a tensor with value specified.\",\n    \"description\": \"Pads a tensor along the borders of each dimension with a supplied value.\\n    Returns a new tensor with the padding included. The pad_const value includes\\n    the zero point if the tensor uses a zero point.\\n\\n    Example:\\n\\n    ```mlir\\n    %pad_const = \\\"tosa.const\\\"() {values = dense<3.14> : tensor<1xf32>} : () -> tensor<1xf32>\\n    %padding = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>\\n    tosa.pad %arg0, %padding, %pad_const: (tensor<1x2xf32>, !tosa.shape<4>, tensor<1xf32>)  -> (tensor<4x9xf32>)\\n    ```\\n\\n    Example 2:\\n\\n    ```mlir\\n    %pad_const = \\\"tosa.const\\\"() {values = dense<3.14> : tensor<1xf32>} : () -> tensor<1xf32>\\n    %padding = tosa.const_shape {values = dense<[-1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>\\n    tosa.pad %arg0, %padding, %pad_const : (tensor<1x2xf32>, !tosa.shape<4>, tensor<1xf32>)  -> (tensor<?x9xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_TensorAtLeast1D\" },\n      { \"name\": \"padding\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"pad_const\", \"type\": \"Tosa_ScalarTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.pow\",\n    \"summary\": \"Computes the power of one value to another.\",\n    \"description\": \"Elementwise input1 value raised to the power of input2.\\n    Axis of size 1 will be broadcast, as necessary. Rank of input tensors must\\n    match.\\n\\n    This operation is not pure. Undefined behaviour may occur if specified\\n    exponent is negative.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.reciprocal\",\n    \"summary\": \"Elementwise reciprocal operator.\",\n    \"description\": \"Elementwise reciprocal operation. For integer operation, a TABLE should be\\n    used with the appropriate ranges.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.reduce_all\",\n    \"summary\": \"Reduce All operator.\",\n    \"description\": \"Reduce a tensor along the given axis with a logical AND operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.reduce_any\",\n    \"summary\": \"Reduce Any operator.\",\n    \"description\": \"Reduce a tensor along the given axis with a logical OR operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.reduce_max\",\n    \"summary\": \"Reduce Max operator.\",\n    \"description\": \"Reduce a tensor along the given axis with a maximum operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.reduce_min\",\n    \"summary\": \"Reduce Min operator.\",\n    \"description\": \"Reduce a tensor along the given axis with a minimum operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"nan_mode\", \"type\": \"DefaultValuedAttr<Tosa_NanPropagationModeAttr{PROPAGATE|IGNORE}, ::mlir::tosa::NanPropagationMode::PROPAGATE>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.reduce_product\",\n    \"summary\": \"Reduce Product operator.\",\n    \"description\": \"Reduce a tensor along the given axis by computing the product of the axis.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.reduce_sum\",\n    \"summary\": \"Reduce Sum operator.\",\n    \"description\": \"Reduce a tensor along the given axis by computing the sum of the axis.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.rescale\",\n    \"summary\": \"Tosa rescale operator.\",\n    \"description\": \"RESCALE is defined using an integer multiply, add, and shift.\\n\\n    Rescale supports two precisions of multiplier: 16-bit and 32-bit. The 32-bit multiplier\\n    version supports two rounding modes to enable simpler lowering of existing frameworks\\n    that use two stage rounding. All arithmetic is designed so that it does not overflow a\\n    64-bit accumulator and that the result fits in 32 bits. In particular, a 48-bit value\\n    cannot be scaled with the 32-bit multiplier because the accumulator would need to have\\n    80 bits.\\n\\n    The shift and value range are limited to allow a variety of implementations. The limit\\n    of 62 on shift allows the shift to be decomposed as two right shifts of 31.\\n\\n    This operation is not pure. Undefined behaviour may occur if the calculated\\n    result underflows or overflows.\\n\\n    Supported rescalings:\\n    * This table is showing the supported conversions from the TOSA Specification.\\n    * The MLIR dialect here can be used to represent other conversions.\\n\\n    | Mode                   | Input | Output | Unsigned input | Unsigned output |\\n    |------------------------|-------|--------|----------------|-----------------|\\n    | signed 16 to 16        | int16 | int16  |  false         |  false          |\\n    | signed 16 to 32        | int16 | int32  |  false         |  false          |\\n    | signed 16 to 8         | int16 | int8   |  false         |  false          |\\n    | signed 32 to 16        | int32 | int16  |  false         |  false          |\\n    | signed 32 to 32        | int32 | int32  |  false         |  false          |\\n    | signed 32 to 8         | int32 | int8   |  false         |  false          |\\n    | signed 8 to 16         | int8  | int16  |  false         |  false          |\\n    | signed 8 to 32         | int8  | int32  |  false         |  false          |\\n    | signed 8 to 8          | int8  | int8   |  false         |  false          |\\n    | signed 48 to 16        | int48 | int16  |  false         |  false          |\\n    | signed 48 to 32        | int48 | int32  |  false         |  false          |\\n    | signed 48 to 8         | int48 | int8   |  false         |  false          |\\n    | unsigned 8 to signed 8 | uint8 | int8   |  true          |  false          |\\n    | signed 8 to unsigned 8 | int8  | uint8  |  false         |  true           |\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"multiplier\", \"type\": \"Tosa_1DInt16Or32Tensor\" },\n      { \"name\": \"shift\", \"type\": \"Tosa_1DInt8Tensor\" },\n      { \"name\": \"input_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"output_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale32\", \"type\": \"BoolAttr\" },\n      { \"name\": \"rounding_mode\", \"type\": \"Tosa_RoundingModeAttr{SINGLE_ROUND|INEXACT_ROUND|DOUBLE_ROUND}\" },\n      { \"name\": \"per_channel\", \"type\": \"BoolAttr\" },\n      { \"name\": \"input_unsigned\", \"type\": \"BoolAttr\" },\n      { \"name\": \"output_unsigned\", \"type\": \"BoolAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.reshape\",\n    \"category\": \"Shape\",\n    \"summary\": \"Reshape operator.\",\n    \"description\": \"Returns a tensor with the same type/values as the input, with a new shape\\n    specified by the shape argument. Reshape may operate on tensors of any rank.\\n    No data conversion happens during a reshape operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"shape\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.resize\",\n    \"summary\": \"Resize operation, supports various resize/upsample modes.\",\n    \"description\": \"Resizes a tensor. Resize is only allowed in the H and W dimensions.\\n\\n    The height dimension is scaled by factor (scale_y_n/scale_y_d). The width\\n    dimension is scaled by factor (scale_x_n/scale_x_d).\\n\\n    The NEAREST_NEIGHBOR mode returns the value of the input tensor closest to\\n    the calculated sample position for both floating-point and integer data\\n    formats.\\n\\n    Floating-point BILINEAR mode returns a bilinearly interpolated output value\\n    based on the four closest input sample positions.\\n\\n    For integer BILINEAR interpolation mode, the output value must be scaled by\\n    1/(scale_y_n * scale_x_n) in a following operation to complete the\\n    interpolation (for example with a RESCALE operator).\\n\\n    The output dimensions can be derived from the input dimensions by inverting\\n    the scale as described in the pseudocode. The [border_y, border_x] values\\n    adjust the output size to allow fractional sampling beyond integer input\\n    position (IH - 1,IW - 1).\\n\\n    The limit MAX_SCALE is applied to each scale ratio after reduction of the\\n    ratio. Individual scale numerator and denominator values are allowed to be\\n    larger than MAX_SCALE.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"scale\", \"type\": \"Rank4TosaShape\" },\n      { \"name\": \"offset\", \"type\": \"Rank2TosaShape\" },\n      { \"name\": \"border\", \"type\": \"Rank2TosaShape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"Tosa_ResizeModeAttr{NEAREST_NEIGHBOR|BILINEAR}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.reverse\",\n    \"category\": \"Transform\",\n    \"summary\": \"Reverse operator.\",\n    \"description\": \"Returns a tensor with the same type/values as the input, with the data\\n    reversed along the given axis. No data conversion happens during a reverse\\n    operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.rfft2d\",\n    \"summary\": \"Performs RFFT2D operation on the input.\",\n    \"description\": \"Performs a batched 2D real-valued Fast Fourier Transform over the input where\\n    the input tensor consists of real values producing complex valued output. The\\n    complex output values will be split into the output_real and output_imag\\n    tensor arguments. RFFT2D takes advantage of Hermitian symmetry to only\\n    calculate the first half of the final output axis. Implementations may choose\\n    to skip calculation of the imaginary values at (0,0), (0,W/2), (H/2,0), and\\n    (H/2, W/2). If the calculation is skipped, the result at that location must be\\n    zero.\\n\\n    Example:\\n\\n    ```mlir\\n     %ouput_real, %output_imag = tosa.rfft2d %input_real : (tensor<8x16xf32>) -> (tensor<8x9xf32>, tensor<8x9xf32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input_real\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_real\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"output_imag\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"local_bound\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.rsqrt\",\n    \"summary\": \"Elementwise 1/sqrt operator.\",\n    \"description\": \"Elementwise reciprocal square root operation. For integer operation, a TABLE\\n    should be used with the appropriate ranges.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.scatter\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Scatter operation.\",\n    \"description\": \"The values_out tensor is set to the values_in tensor with data modified as\\n    follows: data from the input tensor is inserted at the positions specified\\n    by the indices tensor. N is the number of batches, W the number of indices\\n    in each batch, K the range of each index and C the number data channels for\\n    each index. It is not permitted to repeat the same output index within a\\n    single SCATTER operation and so each output index occurs at most once. It\\n    follows that K >= W. In use cases that require multiple updates to the same\\n    output position, these must be decomposed into multiple SCATTER operations.\\n\\n    This operation is not pure. Undefined behaviour may occur if the specified\\n    indices are out of range or duplicate indices are provided.\",\n    \"operands\": [\n      { \"name\": \"values_in\", \"type\": \"Tosa_Tensor3D\" },\n      { \"name\": \"indices\", \"type\": \"Tosa_IndexTensor2D\" },\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"results\": [\n      { \"name\": \"values_out\", \"type\": \"Tosa_Tensor3D\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.select\",\n    \"summary\": \"Elementwise select operator.\",\n    \"description\": \"Elementwise select of the output based on a condition.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_I1Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input3\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.sigmoid\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes elementwise sigmoid of input.\",\n    \"description\": \"Applies the sigmoid logistic function to each element of the input tensor:\\n    $ sigmoid(x) = \\\\frac{1}{1 + e^{-x}} $.\\n\\n    For quantized integer data types, the TABLE operator should be used instead.\\n    Each implementation may choose an appropriate TABLE given the scale and zero\\n    point of the input data. Eight or sixteen bit precision tables may be used\\n    based on the input tensor to the sigmoid function.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.sin\",\n    \"summary\": \"Elementwise sin operator.\",\n    \"description\": \"Elementwise sine operation for values given in radians.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_FloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_FloatTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.slice\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Slice operator.\",\n    \"description\": \"Extracts a slice of input1, beginning at the start coordinates,\\n    and extending for size elements in each direction.\\n    No data conversion happens during a slice operation.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_TensorAtLeast1D\" },\n      { \"name\": \"start\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"size\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.slice_shape\",\n    \"summary\": \"Extract slice of a shape.\",\n    \"description\": \"Extract a shape of size from input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"start\", \"type\": \"Tosa_ScalarInt32Tensor\" },\n      { \"name\": \"size\", \"type\": \"Tosa_ScalarInt32Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.sub\",\n    \"summary\": \"Elementwise subtraction operator.\",\n    \"description\": \"Elementwise subtraction of input1 and input2. Axis of size 1 will be\\n    broadcast as necessary. Rank of input tensors must match.\\n\\n    This operation is not pure. Undefined behaviour may occur if the calculated\\n    result underflows.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.sub_shape\",\n    \"summary\": \"Elementwise subtraction of shapes.\",\n    \"description\": \"Elementwise subtraction of input1 and input2. Size of shapes must match.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Shape\" },\n      { \"name\": \"input2\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.table\",\n    \"summary\": \"Table lookup operator.\",\n    \"description\": \"Table lookup operation. For int8_t TABLE operation, perform a 256 entry\\n    table lookup returning an int8_t value. For int16_t tables, the int16_t\\n    input is treated as a fixed-point 9.7 value. The most significant 9 bits\\n    are used to index into the table. The fractional 7 bits are used to\\n    interpolate based on table[index] and table[index+1]. For int16_t inputs,\\n    the TABLE operator returns a 16.7 interpolated value in an int32_t. This\\n    value can then be input to the RESCALE operator to scale to the required\\n    output data type. Note that int16_t table has 513 values to handle\\n    table[index+1] when index=511.\\n\\n    An int16_t to int16_t table lookup can be constructed in TOSA as follows:\\n    * Use the TABLE operator to produce a fixed point 16.7 interpolated result\\n    * Use RESCALE (in_t=int32_t, out_t=int16_t, scale=1<<14, shift=21) to\\n      scale the output to int16_t range (or alternate scale as required)\\n\\n    This operation is not pure. Undefined behaviour may occur if the calculated\\n    slope is out of range.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" },\n      { \"name\": \"table\", \"type\": \"Tosa_Tensor1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.tanh\",\n    \"category\": \"Activation\",\n    \"summary\": \"Computes elementwise hyperbolic tangent of input.\",\n    \"description\": \"Parameterized hyperbolic tangent: $ tanh(x) = \\\\frac{1 - e^{-2x}}{1 + e^{-2x}} $.\\n\\n    For quantized integer data types, the TABLE operator should be used instead.\\n    Each implementation may choose an appropriate TABLE given the scale and zero\\n    point of the input data. Eight or sixteen bit precision tables may be used\\n    based on the input tensor to the tanh function.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.tile\",\n    \"summary\": \"Tile operator.\",\n    \"description\": \"Replicates input1 multiples times along each dimension.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_TensorAtLeast1D\" },\n      { \"name\": \"multiples\", \"type\": \"Tosa_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"Transpose operator.\",\n    \"description\": \"Permutes the dimensions of the input tensor input1 based on the perms\\n    argument. Each value in the perms list must be a valid dimension of the\\n    input tensor and may not be repeated.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_TensorAtLeast1D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"perms\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.transpose_conv2d\",\n    \"summary\": \"Transpose 2D Convolution operator.\",\n    \"description\": \"Performs a 2D transposed convolution over the given tensor input, using the\\n    weights tensor. Implementations may choose to skip calculation of multiplies\\n    by zero at fractional input positions.\\n\\n    This operation is not pure. Undefined behaviour may occur if the accumulated\\n    result overflows.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"weight\", \"type\": \"Tosa_Tensor4D\" },\n      { \"name\": \"bias\", \"type\": \"Tosa_Tensor1D\" },\n      { \"name\": \"input_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" },\n      { \"name\": \"weight_zp\", \"type\": \"Tosa_ScalarIntOrFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Tosa_Tensor4D\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"out_pad\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<4>]>\" },\n      { \"name\": \"stride\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayCount<2>]>\" },\n      { \"name\": \"acc_type\", \"type\": \"TypeAttrOf<Tosa_AccType>\" },\n      { \"name\": \"local_bound\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tosa.variable\",\n    \"summary\": \"Defines a variable\",\n    \"description\": \"Defines a new TOSA variable. This is a persistent mutable value across multiple\\n    TOSA graph invocations. Modifications are expressed using read/write semantics.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"var_shape\", \"type\": \"IndexElementsAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name\\n    attr-dict\\n    custom<VariableOpTypeOrInitialValue>($var_shape, $type, $initial_value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.variable_read\",\n    \"summary\": \"read_buffer operator\",\n    \"description\": \"Reads the value from a pseudo-buffer resource holding a persistent mutable tensor.\",\n    \"results\": [\n      { \"name\": \"output1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"assemblyFormat\": \"$name attr-dict `:` type($output1)\"\n  },\n  {\n    \"name\": \"tosa.variable_write\",\n    \"summary\": \"write_buffer operator\",\n    \"description\": \"Assigns a value to the pseudo-buffer resource holding a persistent mutable tensor.\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"Tosa_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"assemblyFormat\": \"$name attr-dict `,` $input1 `:` type($input1)\"\n  },\n  {\n    \"name\": \"tosa.while_loop\",\n    \"summary\": \"output = input; While (Cond(output)) {output = Body(output)}\",\n    \"description\": \"Generates and evaluates a Boolean condition and either executes a loop body\\n    or exits the loop. This action is performed repeatedly after\\n    updating and re-evaluating the Boolean condition every iteration. This\\n    implements the semantic foreach or while iterative loop structure.\",\n    \"operands\": [\n      { \"name\": \"input_list\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_list\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond_graph\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"body_graph\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tosa.yield\",\n    \"summary\": \"yield operator\",\n    \"description\": \"return operation within the conditional and body of\\n    structured control flow. Operation takes variadic operands\\n    but produces no results of its own.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Tosa_Tensor>\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` type($inputs)\"\n  },\n  {\n    \"name\": \"toy.add\",\n    \"summary\": \"element-wise addition operation\",\n    \"description\": \"The \\\"add\\\" operation performs element-wise addition between two tensors.\\n    The shapes of the tensor operands are expected to match.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"F64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64Tensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"toy.cast\",\n    \"summary\": \"shape cast operation\",\n    \"description\": \"The \\\"cast\\\" operation converts a tensor from one type to an equivalent type\\n    without changing any data elements. The source and destination types must\\n    both be tensor types with the same element type. If both are ranked, then\\n    shape is required to match. The operation is invalid if converting to a\\n    mismatching constant dimension.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"F64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"F64Tensor\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($output)\"\n  },\n  {\n    \"name\": \"toy.constant\",\n    \"summary\": \"constant\",\n    \"description\": \"Constant operation turns a literal into an SSA value. The data is attached\\n    to the operation as an attribute. For example:\\n\\n    ```mlir\\n      %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>\\n                        : tensor<2x3xf64>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F64ElementsAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"toy.func\",\n    \"summary\": \"user defined function operation\",\n    \"description\": \"The \\\"toy.func\\\" operation represents a user defined function. These are\\n    callable SSA-region operations that contain toy computations.\\n\\n    Example:\\n\\n    ```mlir\\n    toy.func @main() {\\n      %0 = toy.constant dense<5.500000e+00> : tensor<f64>\\n      %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>\\n      toy.print %1 : tensor<2x2xf64>\\n      toy.return\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"toy.generic_call\",\n    \"summary\": \"generic call operation\",\n    \"description\": \"Generic calls represent calls to a user defined function that needs to\\n    be specialized for the shape of its arguments. The callee name is attached\\n    as a symbol reference via an attribute. The arguments list must match the\\n    arguments expected by the callee. For example:\\n\\n    ```mlir\\n     %4 = toy.generic_call @my_func(%1, %3)\\n           : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>\\n    ```\\n\\n    This is only valid if a function named \\\"my_func\\\" exists and takes two\\n    arguments.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Toy_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Toy_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)\"\n  },\n  {\n    \"name\": \"toy.mul\",\n    \"summary\": \"element-wise multiplication operation\",\n    \"description\": \"The \\\"mul\\\" operation performs element-wise multiplication between two\\n    tensors. The shapes of the tensor operands are expected to match.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"F64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64Tensor\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"toy.print\",\n    \"summary\": \"print operation\",\n    \"description\": \"The \\\"print\\\" builtin operation prints a given input tensor, and produces\\n    no results.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[F64Tensor, F64MemRef]>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input)\"\n  },\n  {\n    \"name\": \"toy.reshape\",\n    \"summary\": \"tensor reshape operation\",\n    \"description\": \"Reshape operation is transforming its input tensor into a new tensor with\\n    the same number of elements but different shapes. For example:\\n\\n    ```mlir\\n       %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"F64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"StaticShapeTensorOf<[F64]>\" }\n    ],\n    \"assemblyFormat\": \"`(` $input `:` type($input) `)` attr-dict `to` type(results)\"\n  },\n  {\n    \"name\": \"toy.return\",\n    \"summary\": \"return operation\",\n    \"description\": \"The \\\"return\\\" operation represents a return operation within a function.\\n    The operation takes an optional operand and produces no results.\\n    The operand type must match the signature of the function that contains\\n    the operation. For example:\\n\\n    ```mlir\\n      toy.func @foo() -> tensor<2xf64> {\\n        ...\\n        toy.return %0 : tensor<2xf64>\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<Toy_Type>\" }\n    ],\n    \"assemblyFormat\": \"($input^ `:` type($input))? attr-dict\"\n  },\n  {\n    \"name\": \"toy.struct_access\",\n    \"summary\": \"struct access\",\n    \"description\": \"Access the Nth element of a value returning a struct type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Toy_StructType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Toy_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$input `[` $index `]` attr-dict `:` type($input) `->` type($output)\"\n  },\n  {\n    \"name\": \"toy.struct_constant\",\n    \"summary\": \"struct constant\",\n    \"description\": \"Constant operation turns a literal struct value into an SSA value. The data\\n    is attached to the operation as an attribute. The struct constant is encoded\\n    as an array of other constant values. For example:\\n\\n    ```mlir\\n      %0 = toy.struct_constant [\\n        dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>\\n      ] : !toy.struct<tensor<*xf64>>\\n    ```\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Toy_StructType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($output)\"\n  },\n  {\n    \"name\": \"toy.transpose\",\n    \"summary\": \"transpose operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"F64Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64Tensor\" }\n    ],\n    \"assemblyFormat\": \"`(` $input `:` type($input) `)` attr-dict `to` type(results)\"\n  },\n  {\n    \"name\": \"tpu.A16MatMul\",\n    \"summary\": \"w8a16 / w4a16 matmul operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The special matrix multiplication designed for LLM Linear Layer.\\r\\n    Weight is saved in int8 with f16 per-channel quant scale.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            y_f16 = x_f16 x (quantized_w.to(f16) * scale_f16)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    weight(w.): weight tensor.;\\r\\n    scale(w.): scalar.;\\r\\n    zp(w.): zero points for weight quant.;\\r\\n    bias(w.): an optional tensor can be added to the result of the matrix multiplication. ;\\r\\n\\r\\n    4.attributes\\r\\n    weight_bits: the bit-width used to represent the weight values.;\\r\\n    sign: if output is signed.;\\r\\n    w_transpose: whether the weight tensor should be transposed;\\r\\n    q_group_size: the group size for per-group quantization.;\\r\\n    multicore: whether op supports multicore execution.;\\r\\n    dq_type: the quantized data type for dynamic quantization.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"weight_bits\", \"type\": \"I64Attr\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"w_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"q_group_size\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"dq_type\", \"type\": \"DefaultValuedAttr<DqTypeAttr, \\\"NONE\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Active\",\n    \"summary\": \"Active operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The operator for activation function.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Active(input),for example:Relu, Silu...\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the specific activation mode or function to be applied by the operator.;\\r\\n    coeffs: an array of float64 values as coefficients for activation functions.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"Tpu_ActiveModeAttr{TANH|SIGMOID|RELU|EXP|ELU|SQRT|SQUARE|RSQRT|ABSVAL|LN|ROUND|CEIL|FLOOR|SIN|COS|IS_FINITE|MISH|SWISH|HSWISH|SILU|ARCSIN|ARCCOS|ARCSINH|ARCCOSH|ARCTANH|SINH|COSH|TAN|SIGN|GELU|ERF|HSIGMOID|LOG_SIGMOID|SOFT_PLUS|SOFT_SIGN|LOG2|TGELU|QGELU}\" },\n      { \"name\": \"coeffs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Add\",\n    \"summary\": \"add operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise addition of input1 and input2. Axis of size 1 will be broadcast,\\r\\n    as necessary.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReLU((input1 + input2; dim))\\r\\n    ```\\r\\n    Axis of size 1 will be broadcast if necessary.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    coeff: It is an array and allows for scaling the output of the addition operation.;\\r\\n    // early stride param\\r\\n    do_early_stride: whether to apply early stride optimization during the addition operation.;\\r\\n    early_stride_h: the height of the early stride.;\\r\\n    early_stride_w: the width of the early stride.;\\r\\n    // quant param\\r\\n    multipliers: an array of multipliers used for quantization, It allows for scaling the input values before the addition operation.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    f8_scales: scaling factors for FP8 (8-bit floating point) quantization.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"coeff\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"do_early_stride\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"early_stride_h\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"early_stride_w\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"multipliers\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshifts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"f8_scales\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.AddConst\",\n    \"summary\": \"add const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise add of input1 and input2. Input2 is constant.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input + const_val\\r\\n    ```\\r\\n    Where input1, input2, ..., inputN are the input tensors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    f8_scale: the scaling factor for FP8 (8-bit floating point) quantization.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"f8_scale\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Arg\",\n    \"summary\": \"Arg operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Computes the indices of the min/max/ of the input tensor's element along the provided axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        maximum operation:\\r\\n            output_max[i_1, i_2, i_3,..., i_k] = arg max{j}(input[i_1, i_2,..., i_k, j])\\r\\n        minimum operation:\\r\\n            output_min[i_1, i_2, i_3,..., i_k] = arg min{j}(input[i_1, i_2,..., i_k, j])\\r\\n    ```\\r\\n    where, ( j ) represents the index along the specified axis.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    select_last_index: select the last index of the minimum or maximum value when multiple  along the specified axis.;\\r\\n    use_int_input: choose if use i32/i16 as input, due to BF16 chip arch limit.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"keepdims\", \"type\": \"BoolAttr\" },\n      { \"name\": \"mode\", \"type\": \"ArgModeAttr\" },\n      { \"name\": \"select_last_index\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"use_int_input\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Attention\",\n    \"summary\": \"Attention operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs a multi head attention block. https://en.wikipedia.org/wiki/Attention_(machine_learning)\\r\\n    This block has Q_w, K_w,V_w, O_w and mask\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        Attention(Q, K, V) = softmax(((Q x K^T) / \\\\sqrt{d_k}) + musk) x V;\\r\\n        head_i = Attention(Q x queries_weight, K x keys_weight, V x values_weight);\\r\\n        MultiHead(Q, K, V) = Concat(head_1, head_2, ..., head_h) x out_weight + out_bias;\\r\\n        output = MultiHead(input x queries_weight + queries_bias, input x keys_weight + keys_bias, input x values_weight + values_bias).\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    keys(act.): The keys are derived from the input data and help the model determine which parts of the input are relevant for each query.;\\r\\n    values(act.): The values are the actual information that will be aggregated based on the attention scores computed from the queries and keys.;\\r\\n    queries_weight(w.): Queries are the features that the model uses to ask questions about the input data.;\\r\\n    queries_bias(w.): added to the query representations after the weight transformation.;\\r\\n    keys_weight(w.): This weight tensor transforms the input into key representations.;\\r\\n    keys_bias(w.): added to the key representations after the weight transformation, providing further adjustment.;\\r\\n    values_weight(w.): used to transform the input into value representations.;\\r\\n    values_bias(w.): added to the value representations after the weight transformation.;\\r\\n    out_weight(w.): used to transform the concatenated output of the attention heads into the final output representation.;\\r\\n    out_bias(w.): added to the output representation after the final weight transformation.;\\r\\n    musk(w.):  apply masking during the attention computation, Masks can prevent the model from attending to certain positions in the input.;\\r\\n    table(w.): additional computations or transformations during the softmax operation.;\\r\\n\\r\\n    4.attribute\\r\\n    quant_param: used to reduce the precision of the numbers used in computations.;\\r\\n    scale: a scaling factor applied to the attention scores before they are passed through the softmax function.;\\r\\n    head: the number of attention heads to use in the multi-head attention mechanism.;\\r\\n    dim: the size of the input features or the size of the query, key, and value vectors.;;\\r\\n    has_bias: whether the attention mechanism includes bias terms in its computations.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"keys\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"queries_weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"queries_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keys_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keys_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"values_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"values_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"out_weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"out_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_param\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {0}>\" },\n      { \"name\": \"scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"head\", \"type\": \"I64Attr\" },\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"has_bias\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.AutoIncrease\",\n    \"summary\": \"Auto increase\",\n    \"description\": \"1.Op Introduction\\r\\n    increase by 1 in-place\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = AutoIncrease(input, const_val)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Batch2Space\",\n    \"summary\": \"Batch2Space operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Refer to `https://www.tensorflow.org/api_docs/python/tf/batch_to_space`\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        h_croping = h * block_h - crop_top - crop_bottom,\\r\\n        w_croping = w * block_w - crop_left - crop_right,\\r\\n        [n, c, h, w] => [n / (block_h * block_w), c, h * block_h, w * block_w]\\r\\n        => [n / (block_h * block_w), c, h_croping, w_croping];\\r\\n        The format of input or output is NCHW.\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    block_h: The height of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    block_w: The width of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    crops: It contains four ints with top, left, bottom, right.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"block_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"crops\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.BatchNormBwd\",\n    \"summary\": \"BatchNormalization operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs\\r\\n    with additional channel dimension) as described in the paper\\r\\n    Batch Normalization: Accelerating Deep Network Training by Reducing\\r\\n    Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = \\\\frac{input - \\\\mathrm{E}[input]}{ \\\\variance + \\\\epsilon} * \\\\gamma + \\\\beta\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_out(act.): the gradients of the output of the Batch Normalization layer with respect to the loss. ;\\r\\n    input(act.): input tensor;\\r\\n    weight_opt(w.): the optimized weight (or scale) parameter.;\\r\\n    saved_mean(w.): the mean of the input tensor calculated during the forward pass.;\\r\\n    saved_invstd(w.): the saved inverse standard deviation (or the reciprocal of the standard deviation) of the input tensor,\\r\\n                      also computed during the forward pass.;\\r\\n    buffer(w.): serve as a temporary storage or workspace that may be used during the computation of gradients.;\\r\\n    The mean and standard-deviation are calculated per-dimension over\\r\\n    the mini-batches and $$\\\\gamma$$ and $$\\\\beta$$ are learnable parameter vectors\\r\\n    of size C (where C is the input channel size).\\r\\n\\r\\n    4.attribute\\r\\n    epsilon;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_opt\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"saved_mean\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"saved_invstd\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_in\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_grad\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_grad\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F64Attr, 1e-05>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.BatchNormTrain\",\n    \"summary\": \"BatchNormalization operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs\\r\\n    with additional channel dimension) as described in the paper\\r\\n    Batch Normalization: Accelerating Deep Network Training by Reducing\\r\\n    Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = \\\\frac{input - \\\\mathrm{E}[input]}{ \\\\variance + \\\\epsilon} * \\\\gamma + \\\\beta\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    mean(w.): mean of input tensor in dim C;\\r\\n    variance(w.): the spread of the input tensor values along the channel dimension for each mini-batch.;\\r\\n    gamma(w.): scalar;\\r\\n    beta(w.): scalar;\\r\\n    The mean and standard-deviation are calculated per-dimension over\\r\\n    the mini-batches and $$\\\\gamma$$ and $$\\\\beta$$ are learnable parameter vectors\\r\\n    of size C (where C is the input channel size).\\r\\n\\r\\n    4.attribute\\r\\n    epsilon;\\r\\n    momentum: Momentum is a hyperparameter that controls the moving average of the mean and variance of the input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"var\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gamma\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"beta\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"running_status_buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"saved_invstd\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F64Attr, 1e-05>\" },\n      { \"name\": \"momentum\", \"type\": \"DefaultValuedAttr<F64Attr, 0.1>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.BinaryConstShift\",\n    \"summary\": \"Binary Const with shift operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The BinaryConstShift operator is a specialized tensor operation that combines binary arithmetic with constant scaling and shifting.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = saturation(input +/-/* scale >> -shift)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    scale: a scaling factor multiplies the input tensor.;\\r\\n    shift: a shift value applied to the quantized data before scaling.;\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    saturation: whether the output should be saturated.\\r\\n                When set true, the output will be clamped to a predefined range to prevent overflow or underflow during the operation.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"SI32Attr\" },\n      { \"name\": \"mode\", \"type\": \"BinaryShiftAttr\" },\n      { \"name\": \"shift\", \"type\": \"SI32Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.BinaryShift\",\n    \"summary\": \"Binary with shift operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The BinaryShift operator is designed to perform binary operations on two input tensors with an additional shift operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = saturation(input1 +/-/* input2 >> -shift)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input1(act.): input tensor;\\r\\n    input2(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    shift: a shift value applied to the quantized data before scaling.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    saturation: whether the output should be saturated.\\r\\n                When set to true, the output will be clamped to a predefined range to prevent overflow or underflow during the operation.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input2\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"BinaryShiftAttr\" },\n      { \"name\": \"shift\", \"type\": \"SI32Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Buffer\",\n    \"summary\": \"buffer operator\",\n    \"description\": \"1.Op Introduction\\r\\n    A global buffer for operation, and free after op\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = \\\\text{buffer}(\\\\text{data})\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    none\\r\\n\\r\\n    4.attribute\\r\\n    buffer_type: the type of buffer to be used for the operation.\\r\\n                 include Global memory buffer(GMEM)y, Local memory buffer(LMEM), Tensor memory buffer(TMEM);\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"buffer_type\", \"type\": \"DefaultValuedAttr<Tpu_BufferTypeAttr{GMEM|L2}, tpu::BufferType::GMEM>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Cast\",\n    \"summary\": \"Cast operation\",\n    \"description\": \"1.Op Introduction\\r\\n    The Tpu_CastOp is a tensor operation that performs type casting on the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    output = Cast(input);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    extra_input: whether additional input is required for the casting operation.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    with_scale: whether the casting operation should include a scaling factor.;\\r\\n    round_mode: the rounding mode to be used during the casting operation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"extra_input\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"with_scale\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CastAdd\",\n    \"summary\": \"add operator\",\n    \"description\": \"Cast + Add; One of original Add is casted. Elementwise addition of input1 and input2. Axis of size 1 will be broadcast,\\r\\n    as necessary.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Clip\",\n    \"summary\": \"Clip operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The operator limits the given input to a certain range.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = min      if input[i] < min;\\r\\n                        input[i] if input[i] >= min && input[i] <= max;\\r\\n                        max      if input[i] > max;\\r\\n\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    min: the minimum value that the elements of the input tensor can take.;\\r\\n    max: the maximum value that the elements of the input tensor can take.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"F64Attr\" },\n      { \"name\": \"max\", \"type\": \"F64Attr\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Compare\",\n    \"summary\": \"Compare operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the tensor resulted from performing the compare\\r\\n    operation elementwise on the input tensors A and B.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = 1 if lhs[i] mode rhs[i] is true\\r\\n                        0 otherwise\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    lhs(act.): the first input tensor used as the left operand in the element-wise comparison.;\\r\\n    rhs(act.): the second input tensor used as the right operand in the element-wise comparison.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of comparison to be performed between the two input tensors.\\r\\n          mdoe include Equal, Not Equal, Less Than, Less Than or Equal, Greater Than and Greater Than or Equal;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CompareModeAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CompareConst\",\n    \"summary\": \"CompareConst operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the tensor resulted from performing the compare\\r\\n    operation elementwise on the input tensors A and Const.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = 1 if input[i] mode const_val is true\\r\\n                        0 otherwise\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of comparison to be performed between the two input tensors.\\r\\n          mdoe include Equal, Not Equal, Less Than, Less Than or Equal, Greater Than and Greater Than or Equal;\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    inversed: whether the mask should be inverted.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"CompareModeAttr\" },\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"inversed\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Concat\",\n    \"summary\": \"Concatate operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Concatenates the given sequence of seq tensors in the given dimension.\\r\\n    All tensors must either have the same shape (except in the concatenating dimension) or be empty.\\r\\n\\r\\n    2.Math formula\\r\\n    output = Concat(input1, input2, axis)\\r\\n           = input1[axis] + input2[axis];\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension along which the input tensors will be concatenated.;\\r\\n    only_merge: whether the operation should only perform a merge of tensors without additional processing.;\\r\\n    // param for cv18xx\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // for group\\r\\n    ginfo: contains layer group information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"only_merge\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multipliers\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshifts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ConstantFill\",\n    \"summary\": \"constant fill operator\",\n    \"description\": \"1.Op Introduction\\r\\n    fill the constant value\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = value * ones(shape(input))\\r\\n    ```\\r\\n    where, ones(shape(input)) generates a tensor of the same shape as the input tensor, filled with ones.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    value: the constant value that will fill the output tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Conv2D\",\n    \"summary\": \"convolution 2d operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Tpu_Conv2DOp operation implements a 2D convolution, which is a fundamental operation in many neural networks,particularly in convolutional neural networks (CNNs).\\r\\n    This operation takes an input tensor (often representing an image or feature map) and applies a set of learnable filters (kernels) to produce an output tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C_{out}, H, W) = \\\\sum_{C_{in}} input(N, C_{in}, H + sH * kH, W + sW * kW) * filter(C_{in}, C_{out}, kH, kW) + bias(C_{out})\\r\\n    ```\\r\\n    where, kH and kW are the height and width of the filter (kernel), sH and sW are the vertical and horizontal strides.\\r\\n            N is a batch size, C denotes a number of channels, H is a height of input, and W is width.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    groups: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    dilation: controls the spacing between the kernel points;\\r\\n    inserts: additional parameters that may be used for specific optimizations or configurations.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    //new param\\r\\n    with_bias: whether to include a bias term in the convolution operation.;\\r\\n    weight_is_coeff: whether the weights (filters) are coefficients.;\\r\\n    coeff_merged: whether the coefficients have been merged.;\\r\\n    use_3ic_optimize: whether to use 3-input channel optimization.;\\r\\n      This Options call `use_3ic_optimize` is useful for speed up convolution computation:\\r\\n      use_3ic_optimize & 0x3 == 1  means merge kh to ic\\r\\n      use_3ic_optimize & 0x3 == 2  means merge kw to ic\\r\\n      use_3ic_optimize & 0x3 == 3  means merge kh and kw to ic\\r\\n      use_3ic_optimize & 0x10 != 0 means using tiu to do channel broadcast instead of gdma\\r\\n      use_3ic_optimize & 0x20 != 0 means input bcast addr use buffer (e.g. current op is used by more than one ops)\\r\\n      use_3ic_optimize & 0x20 != 0 means using tiu to do channel broadcast instead of gdma and input bcast addr use buffer\\r\\n                                         (e.g. current op is used by more than one ops)\\r\\n    kernel_zp: the zero-point for the kernel.It is used in quantized models to adjust the range of the weights.;\\r\\n    use_winograd: This attribute indicates whether to use the Winograd algorithm for convolution.;\\r\\n    multiplier: This parameter is used for scaling the output values.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    ginfo: This attribute contains information about layer grouping, which can be useful for organizing layers in a neural network.;\\r\\n    // fuse leakyRelu\\r\\n    do_leaky_relu: whether to apply the Leaky ReLU activation function after the convolution operation.;\\r\\n    neg_slope: sets the slope for the negative part of the Leaky ReLU function, determining how much the output can be negative.;\\r\\n    multiplier_pos: This parameter specifies the multiplier for the positive part of the output, used in the context of quantization.;\\r\\n    multiplier_neg: This parameter specifies the multiplier for the negative part of the output, used in the context of quantization.;\\r\\n    rshift_pos: This attribute defines the right shift for the positive output values during quantization.;\\r\\n    rshift_neg: This attribute defines the right shift for the negative output values during quantization.;\\r\\n    out_f8_scales: This parameter contains the scaling factors for the output in FP8 (8-bit floating point) format.;\\r\\n    //nnvlc\\r\\n    support_compress: whether the operation supports compression.;\\r\\n    compress_info: contains information about the compression method used.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"inserts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_kernel_rotate\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"with_bias\", \"type\": \"BoolAttr\" },\n      { \"name\": \"weight_is_coeff\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"coeff_merged\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"use_3ic_optimize\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"kernel_zp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"use_winograd\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"weight_bits\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfUp>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"do_leaky_relu\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"neg_slope\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"multiplier_pos\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"multiplier_neg\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift_pos\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift_neg\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"out_f8_scales\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"support_compress\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"compress_info\", \"type\": \"OptionalAttr<Tpu_CompressAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Conv3D\",\n    \"summary\": \"convolution 2d operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Tpu_Conv2DOp operation implements a 2D convolution, which is a fundamental operation in many neural networks,particularly in convolutional neural networks (CNNs).\\r\\n    This operation takes an input tensor (often representing an image or feature map) and applies a set of learnable filters (kernels) to produce an output tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C_{out}, D, H, H) = \\\\sum_{C_{in}} input(N, C_{in}, D + sD * kD, H + sH * kH, W + sW * kW) * filter(C_{in}, C_{out}, kD, kH, kW) + bias(C_{out})\\r\\n    ```\\r\\n    where, kD, kH and kW are the depth, height and width of the filter (kernel), sH and sW are the vertical and horizontal strides.\\r\\n            N is a batch size, C denotes a number of channels, H is a height of input, and W is width.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    groups: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    dilation: controls the spacing between the kernel points;\\r\\n    inserts: additional parameters that may be used for specific optimizations or configurations.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    //new param\\r\\n    with_bias: whether to include a bias term in the convolution operation.;\\r\\n    kernel_zp: the zero-point for the kernel.It is used in quantized models to adjust the range of the weights.;\\r\\n    multiplier: This parameter is used for scaling the output values.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    ginfo: This attribute contains information about layer grouping, which can be useful for organizing layers in a neural network.;\\r\\n    out_f8_scale: This parameter contains the scaling factors for the output in FP8 (8-bit floating point) format.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"inserts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"with_bias\", \"type\": \"BoolAttr\" },\n      { \"name\": \"kernel_zp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"weight_bits\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfUp>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"out_f8_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Convbwd\",\n    \"summary\": \"convolution backward\",\n    \"description\": \"1.Op Introduction\\r\\n    calculate grad_input,grad_weight,grad_bias of convolution operation;\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        input(N, C_{in}, D, H, W) = \\\\sum_{C_{out}} output(N, C_{output}, D + sD, H + sH * kH, W + sW * kW) * kernel(C_{in}, C_{out}, kD, kH, kW)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    grad_out(act.): how the loss changes with respect to the output of the convolution operation.;\\r\\n    input(act.): input tensor;\\r\\n    kernel(w.): weights (filters) ;\\r\\n    buffer(act.): intermediate computations or storage during the backward pass;\\r\\n\\r\\n    4.attribute\\r\\n    groups: the number of groups for grouped convolutions.;\\r\\n    input_shape: the shape of the input tensor.;\\r\\n    grad_out_shape: the shape of the tensor that is being backpropagated.;\\r\\n    kernel_shape: an array of integers.;\\r\\n    stride: an array of integers for each dimension.;\\r\\n    dilations: dilation rate for the convolution, controls the spacing between kernel elements.;\\r\\n    padding: an array of integers.;\\r\\n    inserts: additional parameters;\\r\\n    grad_input_enable: whether to compute the gradient with respect to the input tensor.;\\r\\n    grad_weight_enable: whether to compute the gradient with respect to the kernel tensor.;\\r\\n    grad_bias_enable: whether to compute the gradient with respect to the bias tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"kernel\", \"type\": \"AnyTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_out_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"inserts\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_input_enable\", \"type\": \"BoolAttr\" },\n      { \"name\": \"grad_weight_enable\", \"type\": \"BoolAttr\" },\n      { \"name\": \"grad_bias_enable\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ConvBwd_Weight\",\n    \"summary\": \"Convolution Backward operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Gradient of Weight in Convolution Backward.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            \\\\frac{\\\\partial L}{\\\\partial W} = \\\\sum_{n=1}^{N} \\\\sum_{c=1}^{C_{in}} \\\\sum_{h=1}^{H} \\\\sum_{w=1}^{W} \\\\text{input}[n, c, h, w] \\\\cdot \\\\text{grad\\\\_out}[n, :, h', w']\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    gradout_transpose(w.): The transposed gradient of the output tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    groups: Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    input_shape: The shape of the input tensor.;\\r\\n    grad_out_shape: The shape of the gradient output tensor.;\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    padding: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    grad_bias_enable: whether to compute the gradient for the bias term as well.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gradout\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gradout_transpose\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_out_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"padding\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grad_bias_enable\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Copy\",\n    \"summary\": \"TG copy operator.\",\n    \"description\": \"1.Op Introduction\\r\\n    duplicating tensor data from an input to an output buffer.\\r\\n\\r\\n    2.Math formula\\r\\n    output = Copy(input, shape, input_stride, output_stride)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    shape: 0: keep dim from input; -1: left dim from input.;\\r\\n    input_stride: input data stride(saved as I64ArrayAttr).\\r\\n    output_stride: output data stride(saved as I64ArrayAttr).\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"output_stride\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CoreBegin\",\n    \"summary\": \"Begin op parallel to multi cores\",\n    \"description\": \"1.Op Introduction\\r\\n    Begin of pattern to multi cores\\r\\n\\r\\n    2.Math formula\\r\\n        output = CoreBegin(input, pattern)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    pattern: the core operation pattern used for initializing parallel execution across multiple cores.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"Tpu_CorePatternAttr{Common}\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CoreEnd\",\n    \"summary\": \"End op parallel to multi cores\",\n    \"description\": \"1.Op Introduction\\r\\n    End of pattern to multi cores\\r\\n\\r\\n    2.Math formula\\r\\n        output = CoreEnd(input, pattern)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    pattern: the core operation pattern used for initializing parallel execution across multiple cores.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"Tpu_CorePatternAttr{Common}\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CoreJoin\",\n    \"summary\": \"Join tensor to continues pieces\",\n    \"description\": \"1.Op Introduction\\r\\n    The ops in one parallel should run in parallel.\\r\\n\\r\\n    2.Math formula\\r\\n        output = concat(input)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"multicore\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CoreParallel\",\n    \"summary\": \"Parallel execution region in multi cores\",\n    \"description\": \"1.Op Introduction\\r\\n    The ops in one parallel should run in parallel.\\r\\n\\r\\n    2.Math formula\\r\\n        output = CoreParallel(input, offset, size)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    offset: scalar;\\r\\n    size: the number of elements.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensorOrNone>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"I64Attr\" },\n      { \"name\": \"size\", \"type\": \"I64Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CoreSplit\",\n    \"summary\": \"split tensor to continues pieces\",\n    \"description\": \"1.Op Introduction\\r\\n    The ops in one parallel should run in parallel.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input[i * split_size: (i + 1) * split_size] for i = 0, 1, ... num - 1\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"multicore\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Correlation\",\n    \"summary\": \"Custom operator correlation\",\n    \"description\": \"Multiply the sliced left_feature and right_feature based on max_disp;\\r\\n  then perform a reduce operation;\\r\\n  and finally concatenate the results.\\r\\n\\r\\n  2.Math formula\\r\\n  for i in range(max_disp):\\r\\n    if i > 0:\\r\\n        output[:, i, :, i:] = (left_feature[:, :, :, i:] * right_feature[:, :, :, :-i]).mean(dim=1)\\r\\n    else:\\r\\n        output[:, i, :, :] = (left_feature * right_feature).mean(dim=1)\\r\\n\\r\\n  3.activation and weight\\r\\n  input(act.): input tensor;\\r\\n\\r\\n  4.attribute\\r\\n  max_disp: The number of slicing iterations, which is also the size of the output dimension C.\\r\\n  num_groups: The number of batch groups.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_disp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"num_groups\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Csc\",\n    \"summary\": \"Color space convert for model's inputs\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs csc operation on inputs.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Csc(input, pixel_format, y_align, w_align, channel_align)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    channel_order: the order of the color channels in the output tensor.(e.g., RGB, BGR).;\\r\\n    pixel_format: required, pixel format type.;\\r\\n    aligned:  whether the pixel data should be aligned.;\\r\\n    pixel_type: the type of pixel data.;\\r\\n    y_align: width alignment of channel y.;\\r\\n    w_align: width alignment of channel uv.;\\r\\n    channel_align: alignment of channel.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_order\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"pixel_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"aligned\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"pixel_type\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"y_align\", \"type\": \"DefaultValuedAttr<I64Attr, 64>\" },\n      { \"name\": \"w_align\", \"type\": \"DefaultValuedAttr<I64Attr, 64>\" },\n      { \"name\": \"channel_align\", \"type\": \"DefaultValuedAttr<I64Attr, 64>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.CumSum\",\n    \"summary\": \"CumSum operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the cumulative sum of elements of input in the dimension dim.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = \\\\sum{j=0, i}input[j]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    dim(w.): If set to 0, computed across rows, If set to 1, computed across columns.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"dim\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Custom\",\n    \"summary\": \"Custom operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Custom operator\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = CustomFunction(inputs, name, params)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    name: the name of the custom operation to be executed.;\\r\\n    params: A dictionary of parameters.;\\r\\n    ginfo: associated with layer grouping information.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"params\", \"type\": \"TypedArrayAttrBase<DictionaryAttr>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.D2D\",\n    \"summary\": \"Copy WeightOp to Device Mem\",\n    \"description\": \"1.Op Introduction\\r\\n    for to alloc address, and can modify the data(with WeightOp to init it)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = D2D(input, const_val)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Deconv\",\n    \"summary\": \"deconvolution operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform Deconvolution operation.\\r\\n\\r\\n    2.Math formula\\r\\n    The height and width of the output tensor can be calculated using the following formulas:\\r\\n    ```math\\r\\n            H_{out} = H_{in - 1} x stride[0] - 2 x pads[0] + H_k + output_padding[0]\\r\\n            W_{out} = W_{in - 1} x stride[1] - 2 x pads[1] + W_k + output_padding[1]\\r\\n    ```\\r\\n    The output tensor is computed as:\\r\\n    ```math\\r\\n            output(N, C_out, H_out, W_out) = \\\\sum(c_in) {\\\\sum(h_k) {\\\\sum(w_k){input(n, c_in, h_in, w_in) x filter(c_out, c_in, h_k, w_k)}}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array. ;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    group: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    output_padding: The value can be provided as a single integer or a tuple, allowing for different padding values for height and width.;\\r\\n    dynweight_reorderd: whether the weights (filters) should be reordered dynamically.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    with_bias: whether to include a bias term in the convolution operation.;\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"output_padding\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"with_bias\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Deconv3D\",\n    \"summary\": \"3D deconvolution operator\",\n    \"description\": \"1.Op Introduction\\r\\n    \\\"Perform 3D deconvolution operation.\\\"\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        O(n, d, h, w) = \\\\sum_{c=0}^{C_{\\\\text{in}}-1} \\\\sum_{k_d=0}^{K_d-1} \\\\sum_{k_h=0}^{K_h-1} \\\\sum_{k_w=0}^{K_w-1}I\\\\big(n, c, d' \\\\, , h' \\\\, , w'\\\\big) \\\\times F\\\\big(c, :, k_d, k_h, k_w\\\\big)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.;\\r\\n    group: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    output_padding: The value can be provided as a single integer or a tuple, allowing for different padding values for height and width.;\\r\\n    dynweight_reorderd: whether the weights (filters) should be reordered dynamically.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    with_bias: whether to include a bias term in the convolution operation.;\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"dilations\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"output_padding\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"with_bias\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DeformGather\",\n    \"summary\": \"Deform gather operator\",\n    \"description\": \"1.Op Introduction\\r\\n     The deform gather operator for deform_conv2d.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input(offset) * use_mask * mask\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    offset(w.): the learnable offsets of the module of shape.;\\r\\n    mask(act.): place the pooled values in the output tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.;\\r\\n    deform_group: (optional)Number of blocked connections from input channels to output channels. Default: 1.;\\r\\n    use_mask: whether use mask for input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offset\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"use_mask\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"deform_group\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DepackRaw\",\n    \"summary\": \"Postprocess for raw image.\",\n    \"description\": \"1.Op Introduction\\r\\n    (1) depack channel (b, bh * bw, ih + ph, iw + pw) -> (b, 1, oh * bh, ow * bw)\\r\\n    (2) cast to INT16 then postprocess img to raw pattern ( 3 byte 2 pixel )\\r\\n    (3) (b, bh * bw, ih + ph, iw + pw) 16bit -> (b, 1, oh * bh, ow * bw * 3 / 2) 8bit\\r\\n\\r\\n    2.Math formula\\r\\n    (1)Depacking:\\r\\n    The depacking operation can be represented as:\\r\\n    ```math\\r\\n        depacked_tensor = reshape(input, (b, 1, oh · bh,ow · bw));\\r\\n    ```\\r\\n    Here, input is the packed tensor, and depacked_tensor is the resulting tensor after reshaping.\\r\\n    (2)Casting to INT16:\\r\\n    After reshaping, the values are cast to 16-bit integers:\\r\\n    ```math\\r\\n        int16_tensor = cast(depacked_tensor, int16);\\r\\n    ```\\r\\n    (3)Postprocessing to Raw Pattern:\\r\\n    The conversion from INT16 back to the raw image format can be described as:\\r\\n    ```math\\r\\n        raw_image = int16_tensor x (255 / (white_level - black_level));\\r\\n    ```\\r\\n    This scaling ensures that the pixel values are appropriately adjusted based on the specified white and black levels.\\r\\n    (4)Final Output Tensor:\\r\\n    Finally, the output tensor is formed by packing the processed values into the required format:\\r\\n    ```math\\r\\n        output=reshape(raw_image, (b, 1, oh · bh, ow · bw · 2/3));\\r\\n    ```\\r\\n    This ensures that the output tensor has the correct dimensions and format for further processing.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    padding_h: the height of the padding applied to the input image.;\\r\\n    padding_w: the width of the padding applied to the input image.;\\r\\n    white_level: the maximum intensity level for normalization.;\\r\\n    black_level: the minimum intensity level for normalization.;\\r\\n    channel_order: the order of the color channels in the output tensor.(e.g., RGB, BGR).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"white_level\", \"type\": \"F64Attr\" },\n      { \"name\": \"black_level\", \"type\": \"F64Attr\" },\n      { \"name\": \"channel_order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Depth2Space\",\n    \"summary\": \"Depth2Space operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Refer to `https://github.com/onnx/onnx/blob/main/docs/Operators.md#depthtospace`\\r\\n    [n, c, h, w] => [n, c / (block_h * block_w), h * block_h, w * block_w];\\r\\n    if inversed, [n, c, h, w] => [n, c * block_h * block_w, h / block_h, w / block_w];\\r\\n    if DCR(depth-column-row), channel ordered by block_h * block_w * c;\\r\\n    else CRD(column-row-depth), channel ordered by c * block_h * block_w;\\r\\n    The format of input or output is NCHW or NHWC.\\r\\n\\r\\n    2.Math formula\\r\\n\\r\\n    (1)Standard Transformation:\\r\\n    Given an input tensor of shape ( (N, C, H, W) ):\\r\\n    The output tensor after applying the Depth2Space operation can be calculated as:\\r\\n    ```math\\r\\n        {output}(N_i, C_j', H_k, W_l) = input(N_i, C_j, k / block_h, l / block_w)\\r\\n    ```\\r\\n    where k / block_h and l / block_w are rounded down.\\r\\n\\r\\n    (2)Inverse Transformation:\\r\\n    Given an input tensor of shape ( (N, C, H, W) ):\\r\\n    The output tensor after applying the Depth2Space operation can be calculated as:\\r\\n    ```math\\r\\n        {output}(N_i, C_j, H_k, W_l) = input(N_i, C_j', (k x block_h + j / (C / (block_h x block_w))), (l x block_w + j % (C / (block_h x block_w))))\\r\\n    ```\\r\\n    where C / (block_h x block_w) is rounded down.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    block_h: The height of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    block_w: The width of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    is_CRD: whether the channel ordering is in Column-Row-Depth format.;\\r\\n    is_inversed: whether the channel ordering is in Column-Row-Depth format.;\\r\\n    in_is_NCHW: whether the input tensor is in NCHW format.;\\r\\n    out_is_NCHW: whether the output tensor should be in NCHW format.;\\r\\n    swap_cr: swaps the height and width dimensions in the output tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"block_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"is_CRD\", \"type\": \"BoolAttr\" },\n      { \"name\": \"is_inversed\", \"type\": \"BoolAttr\" },\n      { \"name\": \"in_is_NCHW\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"out_is_NCHW\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"swap_cr\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DequantInt\",\n    \"summary\": \"dequant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Dequant 8 bit data to 32/16 bit data.\\r\\n\\r\\n    2.Math formula\\r\\n    32/16bit(output) = DequantIntOp((8bit(input), shift) x multiplier) ≪ lshift;\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    shift: a shift value applied to the quantized data before scaling.;\\r\\n    lshift: a left shift operation applied to the dequantized data after scaling.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiplier\", \"type\": \"SI32Attr\" },\n      { \"name\": \"shift\", \"type\": \"I64Attr\" },\n      { \"name\": \"lshift\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"Tpu_DequantModeAttr{Normal|TFLite}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DequantIntAxis\",\n    \"summary\": \"dequant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Dequant 8 bit data to 32/16 bit data, PerAxis(or PerChannel)\\r\\n\\r\\n    2.Math formula\\r\\n    32/16bit(output) = DequantIntAxisOp((8bit(input), quant, shift) x multiplier) ≪ lshift;\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    quant(act.): This attribute represents the quantization parameters tensor.\\r\\n                 It contains the values used for requantization, such as multipliers and shifts,\\r\\n                 which are specific to each axis or channel.;\\r\\n\\r\\n    4.attribute\\r\\n    lshift: a left shift operation applied to the dequantized data after scaling.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"quant\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lshift\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"Tpu_DequantModeAttr{Normal|TFLite}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DetectionOutput\",\n    \"summary\": \"DetectionOutput operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Intended for use with MultiBox detection method to generate prior.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Raw Detection Output\\r\\n            raw_output = {(b_i, c_i) | i = 1, 2,...,N}\\r\\n            b_i is the bounding box coordinates, c_i is the i-th confidence score.\\r\\n        2.Apply Confidence threshold\\r\\n            filtered_output = {(b_i, c_i) | c_i >= confidence_threshold}\\r\\n        3.Non-Maximum Suppression(NMS)\\r\\n            nms_output = NMS(filtered_output, nms_threshold)\\r\\n        4.Top K detections\\r\\n            output = top_k(nms_output, top_k)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    num_classes: total number of classes, including the background class.;\\r\\n    background_label_id: background class, differentiate between detected objects and the background.;\\r\\n    nms_threshold: The threshold used for Non-Maximum Suppression (NMS).;\\r\\n    top_k: The maximum number of predictions to be considered for each image.;\\r\\n    code_type: the encoding type for the bounding box coordinates.;\\r\\n    keep_top_k: The number of top scoring detections to keep after applying NMS.;\\r\\n    confidence_threshold: The minimum confidence score required for a detection to be considered valid.;\\r\\n    share_location: whether the bounding box locations are shared across different classes.;\\r\\n    variance_encoded_in_target: whether the variance for bounding box predictions is encoded in the target.;\\r\\n    eta: adjusts the confidence scores during NMS.;\\r\\n    onnx_nms: configuration for ONNX compatibility (default is 1).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_classes\", \"type\": \"I64Attr\" },\n      { \"name\": \"background_label_id\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"top_k\", \"type\": \"I64Attr\" },\n      { \"name\": \"code_type\", \"type\": \"DetectionOutputCodeTypeAttr\" },\n      { \"name\": \"keep_top_k\", \"type\": \"I64Attr\" },\n      { \"name\": \"confidence_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"share_location\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"variance_encoded_in_target\", \"type\": \"DefaultValuedAttr<F64Attr, 0>\" },\n      { \"name\": \"eta\", \"type\": \"DefaultValuedAttr<F64Attr, 1>\" },\n      { \"name\": \"onnx_nms\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DevBegin\",\n    \"summary\": \"Begin distribution tensors to multi device\",\n    \"description\": \"1.Op Introduction\\r\\n    Tensors split to distributed device\\r\\n\\r\\n    2.Math formula\\r\\n        output = DevBegin(inputs, pattern, begin_methods, num_head, done)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    pattern: the core operation pattern used for initializing parallel execution across multiple cores.;\\r\\n    begin_methods: an array of strategies used to begin the distribution process across devices.;\\r\\n    num_head: the number of primary channels that are processed first or in parallel.;\\r\\n    done: a flag whether the distribution initialization process is completed.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"Tpu_DevPatternAttr{MatMulColumn|MatMulRow|MatMulMerge|MatMulSliceMerge|MatMulTopK|MatMulSliceMerge2|MatMulSliceMerge3|AttentionSliceMerge|AttentionSliceMerge2|EmbeddingSliceMerge|FAttentionSliceMerge}\" },\n      { \"name\": \"begin_methods\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"num_head\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"done\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DevEnd\",\n    \"summary\": \"End distribution tensors from outputs\",\n    \"description\": \"1.Op Introduction\\r\\n    Tensors from distributed device connect together.\\r\\n\\r\\n    2.Math formula\\r\\n        output = DevBegin(inputs, pattern, begin_methods, num_head, done)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    pattern: the core operation pattern used for initializing parallel execution across multiple cores.;\\r\\n    end_methods: an array of strategies used to end the distribution process across devices.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"Tpu_DevPatternAttr{MatMulColumn|MatMulRow|MatMulMerge|MatMulSliceMerge|MatMulTopK|MatMulSliceMerge2|MatMulSliceMerge3|AttentionSliceMerge|AttentionSliceMerge2|EmbeddingSliceMerge|FAttentionSliceMerge}\" },\n      { \"name\": \"end_methods\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Device2Host\",\n    \"summary\": \"Device2Host Operation\",\n    \"description\": \"1.Op Introduction\\r\\n    takes data from device mem to host mem\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Device2Host(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Div\",\n    \"summary\": \"div operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs element-wise binary division.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input/const_val or const_val/input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.DtypeCast\",\n    \"summary\": \"Cast F32 to F16\",\n    \"description\": \"1.Op Introduction\\r\\n    Cast F32 to F16\\r\\n    The Tpu_DtypeCastOp is a specialized operation designed to cast floating-point tensors from 32-bit precision (F32) to 16-bit precision (F16).\\r\\n\\r\\n    2.Math formula\\r\\n    FLOAT16(output) = DtypeCastOp (FLOAT32(input));\\r\\n\\r\\n    3.activation\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    extra_input: whether additional input is required for the casting operation.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    with_scale: whether the casting operation should include a scaling factor.;\\r\\n    round_mode: the rounding mode to be used during the casting operation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"extra_input\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"with_scale\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.EmbDenseBwd\",\n    \"summary\": \"EmbDenseBwd operation for train\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = grad_output[indices]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    indices(w.): the indices of the input tokens or items.;\\r\\n\\r\\n    4.attributes\\r\\n    num_weights: the total number of embedding weights.;\\r\\n    padding_idx: a index for padding.;\\r\\n    scale_grad_by_freq: whether the gradient should be scaled by the inverse frequency of that token.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_weights\", \"type\": \"SI32Attr\" },\n      { \"name\": \"padding_idx\", \"type\": \"SI32Attr\" },\n      { \"name\": \"scale_grad_by_freq\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.FAttention\",\n    \"summary\": \"Flash Attention operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs a two dimensional matrix multiplication. This allows both inputs to\\r\\n    be activations, rather than reserving weights as an attribute in the\\r\\n    FULLY_CONNECTED operator.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        Attention(Q, K, V) = softmax(((Q x K^T) / \\\\sqrt{d_k}) + musk) x V;\\r\\n        head_i = Attention(Q x queries_weight, K x keys_weight, V x values_weight);\\r\\n        MultiHead(Q, K, V) = Concat(head_1, head_2, ..., head_h) x out_weight + out_bias;\\r\\n        output = MultiHead(input x queries_weight + queries_bias, input x keys_weight + keys_bias, input x values_weight + values_bias).\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    queries(act.): input tensor.;\\r\\n    keys(act.): The keys are derived from the input data and help the model determine which parts of the input are relevant for each query.;\\r\\n    values(act.): The values are the actual information that will be aggregated based on the attention scores computed from the queries and keys.;\\r\\n    mask(w.): apply masking during the attention computation, Masks can prevent the model from attending to certain positions in the input.;;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    scale: scalar.;\\r\\n    batch: batch size.;\\r\\n    q_head: the number of query heads in the multi-head attention mechanism.;\\r\\n    kv_head: the number of key/value heads.;\\r\\n    dim: the size of the input features or the size of the query, key, and value vectors.;\\r\\n    mq: a dimension or a modifier related to the query matrix.;\\r\\n    mk: the key matrix.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"queries\", \"type\": \"AnyTensor\" },\n      { \"name\": \"keys\", \"type\": \"AnyTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"batch\", \"type\": \"I64Attr\" },\n      { \"name\": \"q_head\", \"type\": \"I64Attr\" },\n      { \"name\": \"kv_head\", \"type\": \"I64Attr\" },\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"mq\", \"type\": \"I64Attr\" },\n      { \"name\": \"mk\", \"type\": \"I64Attr\" },\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.FusedActiveCast\",\n    \"summary\": \"Active + Cast\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"Tpu_ActiveModeAttr{TANH|SIGMOID|RELU|EXP|ELU|SQRT|SQUARE|RSQRT|ABSVAL|LN|ROUND|CEIL|FLOOR|SIN|COS|IS_FINITE|MISH|SWISH|HSWISH|SILU|ARCSIN|ARCCOS|ARCSINH|ARCCOSH|ARCTANH|SINH|COSH|TAN|SIGN|GELU|ERF|HSIGMOID|LOG_SIGMOID|SOFT_PLUS|SOFT_SIGN|LOG2|TGELU|QGELU}\" },\n      { \"name\": \"coeffs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Gather\",\n    \"summary\": \"Gather operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform Gather operation on the given axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input[indices]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    indices(w.): the indices of the elements to be gathered from the input tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the computation.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    if_neg_index: how negative indices should be handled.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"if_neg_index\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"is_lora\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GatherElements\",\n    \"summary\": \"GatherElements operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform GatherElements operation on the given axis.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i_1, i_2, i_3,...i_k] = input[i_1, i_2, i_3,..., indices[i_k]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    indices(w.): the indices of the elements to be gathered from the input tensor.;\\r\\n    indices_coeff(w.): a scaling or modifying factor for the indices.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the computation.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices_coeff\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"DefaultValuedAttr<I64Attr, 2>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GatherND\",\n    \"summary\": \"GatherND operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This operator is the inverse of ScatterND.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output_i = input[indices_i]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input_data(act.): input tensor.;\\r\\n    indices(w.): which elements to gather from the input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    indice_dims: the number of dimensions in the indices tensor.;\\r\\n    batch_dims: the number of batch dimensions in the input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indice_dims\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"batch_dims\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GenericCpu\",\n    \"summary\": \"generic cpu operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Generic Cpu Op.\\r\\n\\r\\n    2.Math formula\\r\\n    output = GenericCpu(inputs, param)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    cpu_op_name: the name of the CPU-specific operator to be executed.;\\r\\n    param: a set of parameters.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensorOrNone>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyTensorOrNone>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cpu_op_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"param\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GridSampleInDeformableAttn\",\n    \"summary\": \"GridSampleInDeformableAttn operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Given an input and a flow-field grid, computes the output\\r\\n    using input values and pixel locations from grid.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[N, C, H', W'] = input[C, grid[N, H', W', 1], grid[N, H', W', 0]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grid(w.): The flow-field grid tensor that defines the pixel locations for sampling.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    padding_mode: padding mode for outside grid values, Int attribute [0, 1, 2],\\r\\n                                representing 'zero' | 'boundary' | 'reflection't.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\\r\\n    scale: scalar.;\\r\\n    mean: mean values to subtract from each channel for normalization.;\\r\\n    need_permute: whether permutation of the output tensor is required;\",\n    \"operands\": [\n      { \"name\": \"input_global_addr\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"grid_global_addr\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"attn_global_addr\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_global_addr\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_grid_samples\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_dims\", \"type\": \"I64Attr\" },\n      { \"name\": \"input_n\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_c\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_d\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_h\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_w\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"grid_dout\", \"type\": \"I64Attr\" },\n      { \"name\": \"grid_hout\", \"type\": \"I64Attr\" },\n      { \"name\": \"grid_wout\", \"type\": \"I64Attr\" },\n      { \"name\": \"interp_mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GridSampler\",\n    \"summary\": \"GridSampler operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Given an input and a flow-field grid, computes the output\\r\\n    using input values and pixel locations from grid.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[N, C, H', W'] = input[C, grid[N, H', W', 1], grid[N, H', W', 0]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grid(w.): The flow-field grid tensor that defines the pixel locations for sampling.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    padding_mode: padding mode for outside grid values, Int attribute [0, 1, 2],\\r\\n                                representing 'zero' | 'boundary' | 'reflection't.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\\r\\n    scale: scalar.;\\r\\n    mean: mean values to subtract from each channel for normalization.;\\r\\n    need_permute: whether permutation of the output tensor is required;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"grid\", \"type\": \"AnyTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" },\n      { \"name\": \"mean\", \"type\": \"DefaultValuedAttr<F64Attr, 0>\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F64Attr, 1>\" },\n      { \"name\": \"need_permute\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Group\",\n    \"summary\": \"Group operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Make ops in one group to inferece by local mem\\r\\n\\r\\n    2.Math formula\\r\\n        output = Group(nsecs, hsecs, dsecs, wsecs, csecs; swpipl_stage_num, group_type, flow, self_up_overlap_op, self_down_overlap_op, other_up_overlap_op, other_down_overlap_op, support_compress, run_core_id, core_slice_ncdhw)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    nsecs: the number of sections in the \\\"n\\\" (batch or number) dimension.;\\r\\n    hsecs: the number of sections in the \\\"h\\\" (height) dimension.;\\r\\n    dsecs: the number of sections in the \\\"d\\\" (depth) dimension.;\\r\\n    wsecs: the number of sections in the \\\"w\\\" (width) dimension.;\\r\\n    csecs: the number of sections in the \\\"c\\\" (channel) dimension.;\\r\\n    swpipl_stage_num: the number of stages in the pipeline, which related to swappable operations or pipelined processing.;\\r\\n    group_type: the type of the grouping strategy.;\\r\\n    flow: store both negative timestep indices and positive operation identifiers.;\\r\\n    self_up_overlap_op: overlapped in the upward (or previous) direction within the same group.;\\r\\n    self_down_overlap_op: overlapped in the downward (or subsequent) direction within the same group.;\\r\\n    other_up_overlap_op: Holds the operation identifiers in other groups overlapping in the upward direction.;\\r\\n    other_down_overlap_op: Holds the operation identifiers in other groups overlapping in the downward direction.;\\r\\n    support_compress: whether compression is supported for the load operation.;\\r\\n    run_core_id: an array of core IDs for running.;\\r\\n    core_slice_ncdhw: the tensor's dimensions (n, c, d, h, w) are partitioned.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nsecs\", \"type\": \"I64Attr\" },\n      { \"name\": \"hsecs\", \"type\": \"I64Attr\" },\n      { \"name\": \"dsecs\", \"type\": \"I64Attr\" },\n      { \"name\": \"wsecs\", \"type\": \"I64Attr\" },\n      { \"name\": \"csecs\", \"type\": \"I64Attr\" },\n      { \"name\": \"swpipl_stage_num\", \"type\": \"I64Attr\" },\n      { \"name\": \"group_type\", \"type\": \"I64Attr\" },\n      { \"name\": \"flow\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {0}>\" },\n      { \"name\": \"self_up_overlap_op\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"self_down_overlap_op\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"other_up_overlap_op\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"other_down_overlap_op\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"support_compress\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"run_core_id\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"core_slice_ncdhw\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GroupNorm\",\n    \"summary\": \"GroupNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    group normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            mean_g = 1 / ((C / num_groups) * H * W) \\\\sum{i=1, C/num_groups} \\\\sum{j=1, H} \\\\sum{k=1, W} input_{n,c,j,k}\\r\\n            var_g = 1 / ((C / num_groups) * H * W) \\\\sum{i=1, C/num_groups} \\\\sum{j=1, H} \\\\sum{k=1, W} (input_{n,c,j,k} - mean_g) ^ 2\\r\\n            output_{n,c,j,k} = weight * (input_{n,c,j,k} - mean_g) / sqrt(var_g + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    // cv18xx\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n    mantissa_table(w.): stores a table of mantissa values used in calculations to improve precision or to handle specific numerical representations.;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    num_groups: the number of groups to divide the input channels into for normalization.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mantissa_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GroupNormTrain\",\n    \"summary\": \"GroupNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    group normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\frac{input - mean}{\\\\sqrt{\\\\sigma^2 + eps}} \\\\cdot weight + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    num_groups: number of groups to divide the channels into for normalization.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rstd\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GroupParallel\",\n    \"summary\": \"Mutiple regions run in parallel.\",\n    \"description\": \"1.Op Introduction\\r\\n    This operation is composed of numerous regions, with each region corresponding\\r\\n    to a subgraph. These subgraphs share identical computational patterns and are\\r\\n    distributed across various cores of a multi-core TPU for processing.\\r\\n\\r\\n    2.Math formula\\r\\n        output = GroupParallel(input)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"parallel\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.GRU\",\n    \"summary\": \"GRU operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform RNN GRU operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        update gate(z_t):\\r\\n            z_t = Sigma(W_z · x_t + U_z ·h_(t-1) + b_z)\\r\\n        reset gate(r_t):\\r\\n            r_t = Sigma(W_r · x_t + U_r ·h_(t-1) + b_r)\\r\\n        Candidate Activation(h_t):\\r\\n            h_t = tanh(W_h · x_t + r_t \\\\odot (U_h · h_(t-1)) + b_h)\\r\\n        final output:\\r\\n            output = (1 - z_t) \\\\odot h_(t-1) + z_t \\\\odot h_t\\r\\n    ```\\r\\n    where, x_t is the input at time step (t), h_(t-1) is the hidden state from the previous time step.\\r\\n           W_z, W_r, W_h are the weight matrices for the input.\\r\\n           U_z, U_r, U_h are the weight matrices for the hidden state.\\r\\n           b_z, b_r, b_h are the bias vectors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    recurrence(w.): the previous hidden state influences the current hidden state.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    initial_h(w.): the initial hidden state, which can be provided to start the GRU computation.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the GRU computation.;\\r\\n    sigmoid_table: a lookup table that contains pre-computed values for the sigmoid activation function.;\\r\\n    sigmoid_slope_table: This table contains pre-computed slopes (derivatives) of the sigmoid function, enhancing the training efficiency of the LSTM.;\\r\\n    tanh_table: contains pre-computed values for the hyperbolic tangent (tanh) activation function.;\\r\\n    tanh_slope_table: This table contains pre-computed slopes (derivatives) of the tanh function;\\r\\n\\r\\n    4.attributes\\r\\n    hidden_size: the number of units in the GRU cell,;\\r\\n    bidirectional: whether the GRU should be bidirectional;\\r\\n    linear_before_reset: whether to apply a linear transformation to the input before applying the reset gate.;\\r\\n    batch_first: the input and output tensors are provided in the shape (batch_size, seq_length, input_size).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"recurrence\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"sigmoid_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"sigmoid_slope_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"tanh_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"tanh_slope_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hidden_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"bidirectional\", \"type\": \"BoolAttr\" },\n      { \"name\": \"linear_before_reset\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"batch_first\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Host2Device\",\n    \"summary\": \"Host2Device Operation\",\n    \"description\": \"1.Op Introduction\\r\\n    takes data from host mem to device mem\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Host2Device(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Identity\",\n    \"summary\": \"identity operator\",\n    \"description\": \"1.Op Introduction\\r\\n     identity operator.\\r\\n\\r\\n     2.Math formula\\r\\n    ```math\\r\\n        output = Identity(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.If\",\n    \"summary\": \"if operation\",\n    \"description\": \"1.Op Introduction\\r\\n    If conditional\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = then_branch if cond is true\\r\\n                     else_branch if cond is false\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    cond(act.): which branch of execution to follow.;\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"then_branch\", \"type\": \"SizedRegion<1>\" },\n      { \"name\": \"else_branch\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.IndexPut\",\n    \"summary\": \"IndexPut operation\",\n    \"description\": \"1.Op Introduction\\r\\n    aten::index_put_\\r\\n    update specific elements of an input tensor at given indices with new values.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        if accumulate\\r\\n            input[indices] += values\\r\\n        else\\r\\n            input[indices] = values\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    indices(w.): the indices of the elements in the input tensor that should be updated.;\\r\\n    values(w.): the new values that will replace the existing values in the input tensor at the specified indices.;\\r\\n    //for accumulate is True\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    accumulate: whether the operation should accumulate values at the specified indices or replace them.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"values\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"accumulate\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Insert\",\n    \"summary\": \"Insert operator.\",\n    \"description\": \"1.Op Introduction\\r\\n    insert the rhs tensor into input tensor at the specified axis and position.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Insert(input, rhs, axis, offset)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    rhs(w.): the tensor to be inserted;\\r\\n    axis: the axis along which to insert the rhs tensor.\\r\\n    offset: the position at which the rhs tensor is inserted.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"offset\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.InstanceNorm\",\n    \"summary\": \"InstanceNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    instance normalization.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output[i] = weight * (input[i] - mean) / sprt(var + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    // cv18xx\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n    mantissa_table(w.): stores a table of mantissa values used in calculations to improve precision or to handle specific numerical representations.;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mantissa_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Interp\",\n    \"summary\": \"Interp operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform Interp on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            H' = H x scale_h\\r\\n            W' = W x scale_w\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    shapeT(act.): an optional input tensor that specifies the desired shape for the output tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the computation.;\\r\\n\\r\\n    4.attributes\\r\\n    scale_h: the scaling factor for the height (number of rows) of the input tensor.;\\r\\n    scale_w: the scaling factor for the width (number of columns) of the input tensor.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    coord_mode: whether the coordinates are normalized (ranging from 0 to 1) or absolute (based on pixel indices).;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"shapeT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_h\", \"type\": \"F64Attr\" },\n      { \"name\": \"scale_w\", \"type\": \"F64Attr\" },\n      { \"name\": \"mode\", \"type\": \"Tpu_ResizeModeAttr{nearest|linear}\" },\n      { \"name\": \"coord_mode\", \"type\": \"Tpu_ResizeCoordModeAttr{align_corners|half_pixel|pytorch_half_pixel|asymmetric}\" },\n      { \"name\": \"ppl_flag\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Join\",\n    \"summary\": \"Join tensor to continues pieces\",\n    \"description\": \"1.Op Introduction\\r\\n    The ops in one parallel should run in parallel.\\r\\n\\r\\n    2.Math formula\\r\\n        output = concat(input)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LayerNorm\",\n    \"summary\": \"LayerNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Normalization\\r\\n            mean = 1 / H \\\\sum{j=1, H} input[j]\\r\\n            var = 1 / H \\\\sum{j=1, H} (input[j] - mean) ^ 2\\r\\n        2.Layer Normalized Output\\r\\n            output[i] = weight * (input[i] - mean) / sprt(var + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    // cv18xx\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n    mantissa_table(w.): stores a table of mantissa values used in calculations to improve precision or to handle specific numerical representations.;\\r\\n\\r\\n    4.attributes\\r\\n    normalized_shape: the shape of the input tensor that will be normalized.;\\r\\n    axis: the dimension of the input tensor.;\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mantissa_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LayerNormBwd\",\n    \"summary\": \"LayerNorm operation for train\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.gradient input\\r\\n            grad_input = 1 / N(weight / sqrt(variance + eps) 1 / N \\\\sum{i=1, N}grad_out)\\r\\n                            - (input - mean) / N * \\\\sum(i=1, N)weight * grad_out / sqrt(variance + eps)\\r\\n        2.gradient weight\\r\\n            grad_weight = \\\\sum(i=1, N)grad_out * (input - mean) / sqrt(variance + eps)\\r\\n        3.gradient bias\\r\\n            grad_bias = \\\\sum(i=1, N)grad_out\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    grad_out(w.): the gradient of the loss with respect to the output of the layer normalization.;\\r\\n    mean(w.): mean values to subtract from each channel for normalization.;\\r\\n    variance(w.): adjust the predicted boxes during the training process.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    normalized_shape:  the shape of the input tensor dimensions.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"variance\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"grad_bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LayerNormCast\",\n    \"summary\": \"LayerNorm + Requant\",\n    \"description\": \"LayerNorm + Requant\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"isCastAtEnd\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LayerNormTrain\",\n    \"summary\": \"LayerNorm operation for train\",\n    \"description\": \"1.Op Introduction\\r\\n    layer normalization in train.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Normalization\\r\\n            mean = 1 / H \\\\sum{j=1, H} input[j]\\r\\n            var = 1 / H \\\\sum{j=1, H} (input[j] - mean) ^ 2\\r\\n        2.Layer Normalized Output\\r\\n            output[i] = weight * (input[i] - mean) / sprt(var + eps) + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    normalized_shape: the shape of the input tensor dimensions.;\\r\\n    axis: the dimension of the input tensor.;\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"variance\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LeakyRelu\",\n    \"summary\": \"leakyrelu operation\",\n    \"description\": \"1.Op Introduction\\r\\n    The LeakyRelu operation multiples alpha with negative values, and the others keep changeless.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = alpha * input, if input < 0\\r\\n            output = input, if input >= 0\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    alpha: a scalar factor.;\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    multiplier_neg: specify the multiplier for negative input values.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    rshift_neg: specifies the number of bits to right-shift the quantized negative values.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"multiplier_neg\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift_neg\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Load\",\n    \"summary\": \"Load operation\",\n    \"description\": \"1.Op Introduction\\r\\n    load input or weight from gmem to lmem;\\r\\n    if do_bcast, [1,1,1,w] will load to [1,npu,1,w]\\r\\n\\r\\n    2.Math formula\\r\\n    output = Load(input, do_bcast, use_3ic_optimize, lmem_type, support_compress);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    do_bcast: whether broadcasting.;\\r\\n    use_3ic_optimize: whether the 3-IC (Three Input Channels) optimization;\\r\\n    lmem_type: the type of local memory (lmem) to be used when loading data from global memory (gmem).;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    support_compress: whether compression is supported for the load operation.;\\r\\n    compress_info: used in conjunction with support_compress to specify details like compression schemes, ratios, or any relevant metadata.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_bcast\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"use_3ic_optimize\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"lmem_type\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"support_compress\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"is_idx_weight\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"compress_info\", \"type\": \"OptionalAttr<Tpu_CompressAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LoadToL2M\",\n    \"summary\": \"Load operation\",\n    \"description\": \"1.Op Introduction\\r\\n    load weight from gmem to l2mem;\\r\\n\\r\\n    2.Math formula\\r\\n    output = Load(input, id, l2m_addr);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    id: differentiate or index various instances of the load operation, ensuring correctly matched.;\\r\\n    l2m_addr: the address or offset within the local L2 memory (l2mem).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LogicalAnd\",\n    \"summary\": \"logical and operation\",\n    \"description\": \"1.Op Introduction\\r\\n    logical and operation between two variables\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input1 and input2\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Loop\",\n    \"summary\": \"Loop operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Generic Looping construct, support while/do_while/for/forerver etc:\\r\\n\\r\\n    2.Math formula\\r\\n    none\\r\\n\\r\\n    3.activation and weight\\r\\n    AnyTensor;\",\n    \"operands\": [\n      { \"name\": \"M\", \"type\": \"AnyTypeOf<[AnyTensor, NoneType]>\" },\n      { \"name\": \"cond\", \"type\": \"AnyTypeOf<[AnyTensor, NoneType]>\" },\n      { \"name\": \"v_initial\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, NoneType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"v_final_and_scan_outputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyTensor, NoneType ]>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LRN\",\n    \"summary\": \"Local Response Normalization\",\n    \"description\": \"1.Op Introduction\\r\\n    It normalizes over local input regions. The local region is defined across the channels.\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i, j, k] = \\\\frac{input[i, j, k]}{(bias + \\\\alpha \\\\sum_{c=\\\\max(0,k-\\\\text{size})}^{\\\\min(N-1,k+\\\\text{size})} input[i, j, c]^2)^{\\\\beta}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n    mantissa(w.): store the mantissa values, which can be part of the normalization process.;\\r\\n\\r\\n    4.attributes\\r\\n    size: how many neighboring channels are considered during the normalization process.;\\r\\n    alpha: a scaling factor;\\r\\n    beta: a scaling factor;\\r\\n    bias: A floating-point value added to the normalization denominator to prevent division by zero.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mantissa\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I64Attr\" },\n      { \"name\": \"alpha\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0001>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F64Attr, 0.75>\" },\n      { \"name\": \"bias\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LSTM\",\n    \"summary\": \"LSTM operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform RNN LSTM operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        forget gate(f_t):\\r\\n            f_t = Sigma(W_f · x_t + U_f · h_(t-1) + b_f)\\r\\n        input gate(i_t):\\r\\n            i_t = Sigma(W_i · x_t + U_i · h_(t-1) + b_i)\\r\\n        Candidate cell state(C_t):\\r\\n            C_t = tanh(W_C · x_t + U_C · h_(t-1) + b_C)\\r\\n        cell state update(c_t):\\r\\n            c_t = f_t \\\\odot c_(t-1) + i_t \\\\odot C_t\\r\\n        output gate(o_t):\\r\\n            o_t = Sigma(W_o · x_t + U_o · h_(t-1) + b_o)\\r\\n        hidden state output(h_t):\\r\\n            h_t = o_t \\\\odot tanh(c_t)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    filter(w.): the learnable weights of the convolution 2d operation.;\\r\\n    recurrence(w.): the previous hidden state influences the current hidden state.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    initial_h(w.): the initial hidden state, which can be provided to start the LSTM computation.;\\r\\n    initial_c(w.): the initial cell state, which can be provided to start the LSTM computation.;\\r\\n    cont(w.): control weights or additional context that may be provided to influence the LSTM's behavior.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n    sigmoid_table: a lookup table that contains pre-computed values for the sigmoid activation function.;\\r\\n    sigmoid_slope_table: This table contains pre-computed slopes (derivatives) of the sigmoid function, enhancing the training efficiency of the LSTM.;\\r\\n    tanh_table: contains pre-computed values for the hyperbolic tangent (tanh) activation function.;\\r\\n    tanh_slope_table: This table contains pre-computed slopes (derivatives) of the tanh function;\\r\\n\\r\\n    4.attributes\\r\\n    hidden_size: the number of units in the LSTM cell, ;\\r\\n    bidirectional: A boolean indicating whether the LSTM should be bidirectional;\\r\\n    batch_first: the input and output tensors are provided in the shape (batch_size, seq_length, input_size).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"filter\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"recurrence\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"initial_h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"initial_c\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"cont\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"sigmoid_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"sigmoid_slope_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"tanh_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"tanh_slope_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"Y_h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"Y_c\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"hidden_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"bidirectional\", \"type\": \"BoolAttr\" },\n      { \"name\": \"batch_first\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Lut\",\n    \"summary\": \"Lut operator\",\n    \"description\": \"1.Op Introduction\\r\\n    lookup table in index [0-255], y[i] = table(x[i])\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = table(input[i])\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    table(w.): map input values to corresponding output values.;\\r\\n\\r\\n    4.attributes\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.LutBF16\",\n    \"summary\": \"LutBF16 operator\",\n    \"description\": \"1.Op Introduction\\r\\n    input and output is BF16, input BF16 split as exponent and mantissa,\\r\\n    get output by exponent table and mantissa table\\r\\n    BF16 mode, lookup table in index [0-255], y[i] = table(x[i]).\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = table(input[i])\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    table(w.): map input values to corresponding output values.;\\r\\n    mantissa(w.): the mantissa component of the lookup table weights.;\\r\\n\\r\\n    4.attributes\\r\\n    max_range: the maximum value in the range of valid input values.;\\r\\n    min_range: the minimum value in the range of valid input values.;\\r\\n    lut_mode: the mode of operation for the lookup table.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mantissa\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_range\", \"type\": \"DefaultValuedAttr<F64Attr, 8>\" },\n      { \"name\": \"min_range\", \"type\": \"DefaultValuedAttr<F64Attr, -8>\" },\n      { \"name\": \"lut_mode\", \"type\": \"DefaultValuedAttr<Tpu_LutBF16ModeAttr{Other|Mantissa|Slope|Log|Exp}, tpu::LutBF16Mode::Other>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaskedFill\",\n    \"summary\": \"MaskedFill operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Return elements, either from X or Const, depending on condition.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n                     brn                if inversed and cond=0\\r\\n            output = brn + const_val    if inversed and cond!=0\\r\\n                     brn + const_val    if !inversed and cond!=0\\r\\n                     brn                if !inversed and cond=0\\r\\n    ```\\r\\n        If inversed is true, the operation fills the elements of brn where cond is zero with const_val, while leaving other elements unchanged.\\r\\n        If inversed is false, the operation fills the elements of brn where cond is non-zero with const_val, while leaving other elements unchanged.\\r\\n\\r\\n    3.activation and weight\\r\\n    cond(act.): a tensor that serves as the condition for selecting elements from the true branch (tbrn) or the false branch (fbrn).;\\r\\n    brn(w.): the input tensor from which elements will be selected based on the condition provided by the cond tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    inversed: whether the mask should be inverted.;\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"brn\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inversed\", \"type\": \"BoolAttr\" },\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaskRCNN_BboxPooler\",\n    \"summary\": \"Bbox_Pooler gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    MaskRCNN_BBox_Pooler, the 1st ROIAlign in MaskRCNN.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ROIAlign(feature map, rois_multi_batch)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    ptr_feat0(act.): Pointer to the feature map at level 0.;\\r\\n    ptr_feat1(act.): Pointer to the feature map at level 1.;\\r\\n    ptr_feat2(act.): Pointer to the feature map at level 2.;\\r\\n    ptr_feat3(act.): Pointer to the feature map at level 3.;\\r\\n    rois_multi_batch(w.): ROIs (Regions of Interest) for multiple batches.;\\r\\n\\r\\n    4.attributes\\r\\n    ROI_NUM_LEVELS: The number of levels in the ROI feature pyramid.;\\r\\n    ROI_H: The height of the pooled ROI features.;\\r\\n    ROI_W: The width of the pooled ROI features.;\\r\\n    CHANNEL_ROI: The number of channels in the pooled ROI features.;\\r\\n    ROI_SLICE: The number of slices or segments;\\r\\n    ROI_PH: The height of the ROI in the feature map.;\\r\\n    ROI_PW: The width of the ROI in the feature map.;\\r\\n    ROI_LEN: The length of the ROIs being processed.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"ptr_feat0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_feat1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_feat2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_feat3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rois_multi_batch\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_tmp_res\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"ptr_rois_tmp\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_res\", \"type\": \"AnyTensor\" },\n      { \"name\": \"result_rois\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ROI_NUM_LEVELS\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_H\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_W\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_ROI\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_SLICE\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PH\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PW\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_LEN\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaskRCNN_GetBboxB\",\n    \"summary\": \"GetBboxB operator\",\n    \"description\": \"1.Op Introduction\\r\\n     MaskRCNN_GetBboxB, the 2nd onnx_nms in MaskRCNN\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            decode_bbox_i = bbox_means + scale_factor x (ptr_bbox[i] x bbox_stds + [res_bbox0[i] res_bbox1[i] res_bbox[i]])\\r\\n            score_i = ptr_score[i] (or a combination of res_score0,res_score1,res_score2,res_score3)\\r\\n            {bboxs, lables} = NMS({decode_bbox_i}, {score_i}, nms_iou_thr)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    ptr_rois(act.): candidate regions of interest for possible objects.;\\r\\n    ptr_bbox(act.): the bounding box predictions.;\\r\\n    ptr_score(act.): confidence scores associated with each proposal.;\\r\\n    max_val(w.): max scores the bbox predictions.;\\r\\n    scale_factor(w.): scale the decoded bounding box coordinates.;\\r\\n    stds(w.): standard deviation values for each channel.;\\r\\n    means(w.): mean values to subtract from each channel for normalization.;\\r\\n    res_bbox(w.): bounding box prediction values.;\\r\\n    res_bbox1(w.): one branch of the processed bounding box predictions.;\\r\\n    res_bbox0(w.): another branch or variant of the bounding box decoding results.;\\r\\n    res_score0(w.): one set of confidence scores associated with the proposals.;\\r\\n    res_score1(w.): an additional set of confidence scores.;\\r\\n    res_score2(w.): another set of scoring values.;\\r\\n    res_score3(w.):  final selection of bounding boxes.;\\r\\n    res_label2(w.): the predicted class labels.;\\r\\n    result_list(w.): the final list of processed results or proposal indices after filtering and ranking.;\\r\\n    keep_3nch(w.): whether retains proposals having three-channel inputs.;\\r\\n    keep_u32_1h(w.): whether using a single 32-bit unsigned integer per element.;\\r\\n    glb_buffer_boxes(w.): A global temporary buffer used to store bounding box.;\\r\\n    glb_buffer_scores(w.): A global temporary buffer for storing scores associated with the candidate bounding boxes.;\\r\\n    glb_buffer_nms(w.): This global buffer holds intermediate NMS-related information.;\\r\\n    glb_buffer_nonzero(w.): stores the non-zero elements (or valid indices) from processed tensors.;\\r\\n    result_valid_ind(w.): the indices of proposals.;\\r\\n    glb_lables(w.): A global buffer dedicated to storing the class labels.;\\r\\n    glb_lables_expand(w.): an expanded version of the global labels.;\\r\\n\\r\\n    4.attributes\\r\\n    threshold_score_eq: A threshold value used to filter out proposals with a low confidence score before applying NMS.;\\r\\n    wh_ratio_log: A logarithmic scaling factor, adjust the width-to-height ratio during decoding of bounding boxes.;\\r\\n    nms_iou_thr: IoU (Intersection over Union) threshold.;\\r\\n    delta2bbox_means: Mean values used to decode the bounding box regression.;\\r\\n    delta2bbox_stds_0: Standard deviation (first component) for scaling the decoded bbox values.;\\r\\n    delta2bbox_stds_1: Standard deviation (second component) for scaling the decoded bbox values.;\\r\\n    NUM_INDEXES: the number of indexes (or anchors).;\\r\\n    NUM_CLASSES: The total number of object classes.;\\r\\n    TOPK_ONNX_NMS: to select a fixed number of candidates.;\\r\\n    NUM_CLASSES_getBboxB: Number of classes used in this bounding box decoding step.;\\r\\n    MAX_NMS_LENGTH_GetBboxB: Maximum number of bounding box candidates.;\\r\\n    MAX_PER_IMG: The maximum number of detections allowed per image.;\\r\\n    MAX_PER_IMG_GetBboxB: maximum number of bounding boxes after the final processing.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"ptr_rois\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_bbox\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_score\", \"type\": \"AnyTensor\" },\n      { \"name\": \"max_val\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale_factor\", \"type\": \"AnyTensor\" },\n      { \"name\": \"means\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"stds\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_bbox\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_bbox1\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_bbox0\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_score0\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_score1\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_score2\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_score3\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"res_label2\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"result_list\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keep_3nch\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keep_u32_1h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_boxes\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_scores\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_nms\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_nonzero\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"result_valid_ind\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_lables\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_lables_expand\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_det_bboxes\", \"type\": \"AnyTensor\" },\n      { \"name\": \"result_det_labels\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"threshold_score_eq\", \"type\": \"F64Attr\" },\n      { \"name\": \"wh_ratio_log\", \"type\": \"F64Attr\" },\n      { \"name\": \"nms_iou_thr\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_means\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_stds_0\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_stds_1\", \"type\": \"F64Attr\" },\n      { \"name\": \"NUM_INDEXES\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_CLASSES\", \"type\": \"I64Attr\" },\n      { \"name\": \"TOPK_ONNX_NMS\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_CLASSES_getBboxB\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_NMS_LENGTH_GetBboxB\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_PER_IMG\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_PER_IMG_GetBboxB\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaskRCNN_MaskPooler\",\n    \"summary\": \"Mask_Pooler gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    MaskRCNN_Mask_Pooler, the 2st ROIAlign in MaskRCNN\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = \\\\text{ROIAlign}\\\\Bigl( \\\\{x_i\\\\}_{i=0}^3, \\\\, \\\\text{det\\\\_bboxes\\\\_multi\\\\_batch}, \\\\, \\\\text{det\\\\_labels\\\\_multi\\\\_batch}, \\\\, \\\\text{scale\\\\_factor}, \\\\, ROI\\\\_NUM\\\\_LEVELS, \\\\, ROI\\\\_H, \\\\, ROI\\\\_W, \\\\, CHANNEL\\\\_ROI, \\\\, ROI\\\\_SLICE, \\\\, ROI\\\\_PH, \\\\, ROI\\\\_PW, \\\\, ROI\\\\_LEN \\\\Bigr)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    x_0(act.): first level of the feature pyramid.;\\r\\n    x_1(act.): second level of the feature pyramid.;\\r\\n    x_2(act.): third level of the feature pyramid.;\\r\\n    x_3(act.): fourth level of the feature pyramid.;\\r\\n    det_bboxes_multi_batch(act.): detected bounding boxes over multiple batches.;\\r\\n    det_labels_multi_batch(act.): class labels associated with the detected bounding boxes across multiple batches.;\\r\\n    scale_factor(w.): scale the decoded bounding box coordinates.;\\r\\n    ptr_rois_buff(w.): a temporary buffer that holds precomputed or intermediate Regions of Interest (ROIs).;\\r\\n    result_filled_det_bboxes(w.): stores the processed or “filled” detection bounding boxes.;\\r\\n    result_filled_det_labels(w.): corresponding class labels that have been associated with the detected bounding boxes.;\\r\\n    ptr_tmp_res(w.):  temporary result buffer used internally during the pooling process.;\\r\\n    ptr_rois_tmp(w.): a temporary workspace that stores intermediate ROI values.;\\r\\n\\r\\n    4.attributes\\r\\n    ROI_NUM_LEVELS: the number of feature levels (or pyramid levels) available for ROI pooling.;\\r\\n    ROI_H: target height of the pooled region for each ROI.;\\r\\n    ROI_W: target width of the pooled region for each ROI.;\\r\\n    CHANNEL_ROI: number of channels to be kept or considered when performing ROIAlign.;\\r\\n    ROI_SLICE: slicing strategy for ROIs, if the ROI needs to be segmented into sub-regions for finer pooling.;\\r\\n    ROI_PH: Padding height for the ROI.;\\r\\n    ROI_PW: Padding width for the ROI.;\\r\\n    ROI_LEN: total length (or area) of the ROI.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"x_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"x_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"x_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"x_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"det_bboxes_multi_batch\", \"type\": \"AnyTensor\" },\n      { \"name\": \"det_labels_multi_batch\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale_factor\", \"type\": \"AnyTensor\" },\n      { \"name\": \"ptr_rois_buff\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"result_filled_det_bboxes\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"result_filled_det_labels\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"ptr_tmp_res\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"ptr_rois_tmp\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_res\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ROI_NUM_LEVELS\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_H\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_W\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_ROI\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_SLICE\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PH\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_PW\", \"type\": \"I64Attr\" },\n      { \"name\": \"ROI_LEN\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaskRCNN_RPNGetBboxes\",\n    \"summary\": \"RPN_get_bboxes gen by PPL\",\n    \"description\": \"1.Op Introduction\\r\\n    MaskRCNN_RPN_get_bboxes, the sub-block with 1st NMS between RPN_head and 1st ROIAlign.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Score Filtering\\r\\n            valid_indices_i = cls_scores_i > conf_threshold (for each level i)\\r\\n        2.Bounding Box Adjustment\\r\\n            adjusted_bboxes_i = anchors_i + bbox_preds_i * delta2bbox_std_i + delta2bbox_mean_i\\r\\n        3.IoU Calculation\\r\\n            iou = calculate_iou(adjusted_bboxes_i, ground_truth_boxes)\\r\\n        4.NMS Application\\r\\n            final_bboxes = nms(adjusted_bboxes_i[valid_indices_i], iou_threshold)\\r\\n        5.final output\\r\\n            output = concatenate(final_bboxes)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    cls_scores_0: the class scores0 for each anchor;\\r\\n    cls_scores_1(act.): the class scores1 for each anchor;\\r\\n    cls_scores_2: the class scores2 for each anchor;\\r\\n    cls_scores_3: the class scores3 for each anchor;\\r\\n    cls_scores_4: the class scores4 for each anchor;\\r\\n    bbox_preds_0: the bounding box0 predictions;\\r\\n    bbox_preds_1: the bounding box1 predictions;\\r\\n    bbox_preds_2: the bounding box2 predictions;\\r\\n    bbox_preds_3: the bounding box3 predictions;\\r\\n    bbox_preds_4: the bounding box4 predictions;\\r\\n    max_shape: the maximum dimensions of the output bounding boxes.;\\r\\n    mlvl_anchors_0: the multi-level anchors0 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_1: the multi-level anchors1 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_2: the multi-level anchors2 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_3: the multi-level anchors3 used for generating bounding box proposals.;\\r\\n    mlvl_anchors_4: the multi-level anchors4 used for generating bounding box proposals.;\\r\\n    batch_mlvl_scores: the class scores for all anchors across multiple feature levels in a batch.;\\r\\n    batch_mlvl_anchors: the multi-level anchors generated for the entire batch.;\\r\\n    batch_mlvl_rpn_bbox_pred: the bounding box predictions for each anchor across multiple levels in the batch.;\\r\\n    batch_mlvl_proposals: the proposed bounding boxes generated for the entire batch after processing;\\r\\n    batch_mlvl_ids: the ids associated with the proposals for each anchor across the batch.;\\r\\n    glb_buffer_tmp_scores_stretched: the stretched class scores for processing before NMS.;\\r\\n    glb_buffer_ranked_scores: The buffer stores the ranked class scores after sorting the top proposals.;\\r\\n    glb_buffer_rank_inds_int32: the indices of the ranked scores in 32-bit integer format;\\r\\n    glb_buffer_rank_inds_u32: stores the indices in 32-bit unsigned integer format.;\\r\\n    glb_topk_inds: This buffer holds the indices of the top K proposals after the ranking process.;\\r\\n    glb_buffer_gather_1: gathering specific data from the ranked scores or proposals.;\\r\\n    glb_buffer_gather_2: Similar to glb_buffer_gather_1;\\r\\n    glb_buffer_rpn_bbox_permuted: the permuted bounding box predictions.;\\r\\n    glb_buffer_nonzero: non-zero entries from the scores or proposals.;\\r\\n    result_valid_ind: the valid indices of the resulting proposals after processing.;\\r\\n    glb_buffer_gather_boxes: gather the final bounding boxes from the proposals after NMS.;\\r\\n    glb_buffer_gather_scores: holds the final scores associated with the gathered bounding boxes.;\\r\\n    keep_3nch: maintain a specific format or structure for the gathered results(three-channel format).;\\r\\n    keep_u32_1h: manage the format or structure of the output in a specific way.;\\r\\n    glb_buffer_boxes: the final bounding boxes ready for output after all processing steps.;\\r\\n    glb_buffer_scores: the final class scores corresponding to the output bounding boxes.;\\r\\n    glb_buffer_nms: This buffer is used during the Non-Maximum Suppression process to manage overlapping proposals.;\\r\\n    gather_mlvl_proposals: gather proposals from multiple levels for final processing.;\\r\\n    gather_mlvl_scores: gather scores from multiple levels for the final proposal selection.;\\r\\n    gather_mlvl_ids: gather ids from multiple levels to track proposals across the batch.;\\r\\n    glb_buffer_result_list: the final list of results.;\\r\\n\\r\\n    4.attribute\\r\\n    delta2bbox_mean_0: the means used to normalize the bounding box0 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_mean_1: the means used to normalize the bounding box1 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_mean_2: the means used to normalize the bounding box2 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_mean_3: the means used to normalize the bounding box3 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_0: the standard deviations used to normalize the bounding box0 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_1: the standard deviations used to normalize the bounding box1 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_2: the standard deviations used to normalize the bounding box2 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_std_3: the standard deviations used to normalize the bounding box3 deltas for the corresponding feature levels.;\\r\\n    delta2bbox_max_scalar_c: a scalar value;\\r\\n    iou_threshold: filtering out low-quality proposals during NMS.;\\r\\n    conf_threshold: a confidence score threshold.;\\r\\n    MAX_LENGTH_STATIC_STRECHED: the maximum length for the output list of bounding boxes after processing.;\\r\\n    NUM_INDEXES: the number of indexes.;\\r\\n    NUM_CLASSES: the number of classes.;\\r\\n    CHANNEL_RPN_BBOXES: the number of channels for the bounding box predictions.;\\r\\n    CHANNEL_RPN_SCORES: the number of channels used for the class score predictions.;\\r\\n    NMS_PRE: the number of proposals to be considered before NMS.;\\r\\n    HARDWARE_FACTOR_TOPK: how many top proposals to keep.;\\r\\n    NMS_MAX_LENGTH: the maximum number of boxes after NMS.;\\r\\n    TOPK_ONNX_NMS: the number of top proposals when using ONNX format for NMS.;\\r\\n    H_RPN_DYN_MAX: the maximum height for the dynamic RPN output.;\\r\\n    W_RPN_DYN_MAX: the maximum width for the dynamic RPN output.;\\r\\n    MAX_PER_IMG: the maximum number of proposals to be generated per image.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"cls_scores_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"cls_scores_4\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bbox_preds_4\", \"type\": \"AnyTensor\" },\n      { \"name\": \"max_shape\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_0\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_1\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_2\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_3\", \"type\": \"AnyTensor\" },\n      { \"name\": \"mlvl_anchors_4\", \"type\": \"AnyTensor\" },\n      { \"name\": \"batch_mlvl_scores\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"batch_mlvl_anchors\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"batch_mlvl_rpn_bbox_pred\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"batch_mlvl_proposals\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"batch_mlvl_ids\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_tmp_scores_stretched\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_ranked_scores\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_rank_inds_int32\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_rank_inds_u32\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_topk_inds\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_gather_1\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_gather_2\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_rpn_bbox_permuted\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_nonzero\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"result_valid_ind\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_gather_boxes\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_gather_scores\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keep_3nch\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"keep_u32_1h\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_boxes\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_scores\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_nms\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"gather_mlvl_proposals\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"gather_mlvl_scores\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"gather_mlvl_ids\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"glb_buffer_result_list\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"result_list\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"delta2bbox_mean_0\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_mean_1\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_mean_2\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_mean_3\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_0\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_1\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_2\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_std_3\", \"type\": \"F64Attr\" },\n      { \"name\": \"delta2bbox_max_scalar_c\", \"type\": \"F64Attr\" },\n      { \"name\": \"iou_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"conf_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"MAX_LENGTH_STATIC_STRECHED\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_INDEXES\", \"type\": \"I64Attr\" },\n      { \"name\": \"NUM_CLASSES\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_RPN_BBOXES\", \"type\": \"I64Attr\" },\n      { \"name\": \"CHANNEL_RPN_SCORES\", \"type\": \"I64Attr\" },\n      { \"name\": \"NMS_PRE\", \"type\": \"I64Attr\" },\n      { \"name\": \"HARDWARE_FACTOR_TOPK\", \"type\": \"I64Attr\" },\n      { \"name\": \"NMS_MAX_LENGTH\", \"type\": \"I64Attr\" },\n      { \"name\": \"TOPK_ONNX_NMS\", \"type\": \"I64Attr\" },\n      { \"name\": \"H_RPN_DYN_MAX\", \"type\": \"I64Attr\" },\n      { \"name\": \"W_RPN_DYN_MAX\", \"type\": \"I64Attr\" },\n      { \"name\": \"MAX_PER_IMG\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MatchTemplate\",\n    \"summary\": \"Opencv MatchTemplate operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform opencv MatchTemplate operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            R(x, y) = \\\\sum_{i=0}^{T_w-1} \\\\sum_{j=0}^{T_h-1} I(x+i, y+j) \\\\cdot T(i, j)\\r\\n    ```\\r\\n    where:\\r\\n    R(x, y) is the result of the match at position(x, y).\\r\\n    I is the input image.\\r\\n    T is the template image.\\r\\n    T_w and T_h are the width and height of the template.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor(source image).;\\r\\n    match(w.): the template image that will be matched against the input image.;\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n    mantissa_table(w.): stores a table of mantissa values used in calculations to improve precision or to handle specific numerical representations.;\\r\\n\\r\\n    4.attributes\\r\\n    mode: the method of template matching to be used (e.g., correlation, squared difference, etc.).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"match\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mantissa_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"MatchTemplateModeAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MatMul\",\n    \"summary\": \"matmul operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs a two dimensional matrix multiplication. This allows both inputs to\\r\\n    be activations, rather than reserving weights as an attribute in the\\r\\n    FULLY_CONNECTED operator.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input x right + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): the first input tensor;\\r\\n    right(act.): the second input tensor;\\r\\n    bias(w.): an optional tensor can be added to the result of the matrix multiplication. ;\\r\\n    multi(w.): used during the matrix multiplication operation.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attribute\\r\\n    right_transpose: whether to transpose the right input tensor before performing the multiplication.;\\r\\n    left_transpose: whether to transpose the input tensor before performing the multiplication.;\\r\\n    output_transpose: whether to transpose the output tensor after the multiplication.;\\r\\n    hdim_is_batch: whether the first dimension of the input tensor represents the batch size.;\\r\\n    keep_dims: whether to keep the dimensions of the output tensor the same as the input tensors.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    multipliers: an integer array that specifies scaling factors to be applied to the results of the matrix multiplication.;\\r\\n    rshifts: an integer array that indicates the right shift values.;\\r\\n    right_zp: the zero point for the right input tensor.;\\r\\n    input_zp: the zero point for the left input tensor.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multi_core: executed using multiple cores.;\\r\\n    fuse_rq: fuse the requantization step with the matrix multiplication operation.;\\r\\n    round_mode: the rounding mode to be used during the casting operation.;\\r\\n    multicore: whether op supports multicore execution.;\\r\\n    dq_type: the quantized data type for dynamic quantization.;\\r\\n    q_group_size: the group size for per-group quantization.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"right\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"multi\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"right_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"output_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"hdim_is_batch\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multipliers\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {1}>\" },\n      { \"name\": \"rshifts\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {0}>\" },\n      { \"name\": \"right_zp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"input_zp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"left_reuse\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"out_f8_scales\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multi_core\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"fuse_rq\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"is_lora\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"weight_bits\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"dq_type\", \"type\": \"DefaultValuedAttr<DqTypeAttr, \\\"NONE\\\">\" },\n      { \"name\": \"q_group_size\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MatMulLut\",\n    \"summary\": \"MatMul + Lut\",\n    \"description\": \"MatMul + Lut\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"right\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"multi\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"right_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"output_transpose\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"hdim_is_batch\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"keep_dims\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multipliers\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {1}>\" },\n      { \"name\": \"rshifts\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {0}>\" },\n      { \"name\": \"right_zp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"input_zp\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"left_reuse\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"out_f8_scales\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multi_core\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"fuse_rq\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Max\",\n    \"summary\": \"max operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise max of input1 and input2. All inputs and outputs must have the same data type.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = max(input1,input2, ..., inputN)\\r\\n    ```\\r\\n    Where input1, input2, ..., inputN are the input tensors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    coeff: It is an array and allows for scaling the output of the addition operation.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"coeff\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"multipliers\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshifts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaxConst\",\n    \"summary\": \"max_const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    max of one input and one const.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Max(input, const_val)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaxPoolingIndicesBwd\",\n    \"summary\": \"MaxPoolingIndicesBwd operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to MaxPoolingIndicesBwd.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n          grad\\\\_input(p) = \\\\sum_{q} \\\\delta\\\\big(p = indices[q]\\\\big) \\\\times grad\\\\_output(q)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    indices(w.): the indices of the input tokens or items.;\\r\\n\\r\\n    4.attributes\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    dilations: controls the spacing between the kernel points;\\r\\n    input_shape: The shape of the input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"dilations\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"input_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaxPoolWithMask\",\n    \"summary\": \"max pool with operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  max pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n    get output tensor and mask tensor\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C, H', W') = MaxPool(max(input(N, C, H, W)))\\r\\n        maskOutput(N, C, H', W') = MaxPoolWithMask(argmax(input(N, C, H, W)))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    strides: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    layer_group: multiple layers to be processed together or treated as a single unit during computation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"layer_group\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MaxUnpool\",\n    \"summary\": \"MaxUnpool operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform MaxUnpool on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output1(N, C, H', W') = input(N, C, H, W) #if (h,w) is the index of the max value in the mask, otherwise is 0;\\r\\n        output = scale * output1\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    mask(act.): place the pooled values in the output tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    scale_h: scaling factor for the height dimension of the output tensor.;\\r\\n    scale_w: scaling factor for the width dimension of the output tensor.;\\r\\n    ginfo: group information for layer grouping;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mask\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"scale_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MeanRstd\",\n    \"summary\": \"Compute Mean, Rstd, Running_mean, Running_var in batchnorm train op\",\n    \"description\": \"1.Op Introduction\\r\\n    computes the mean, reverse standard deviation (Rstd), running mean, and running variance.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        mean(x),1/sqrt(var+eps),(1-momentum)*running_mean + momentum*mean,(1-momentum)*running_var + momentum*var\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    running_mean(w.): mean during running.;\\r\\n    running_var(w.): variances during running.;\\r\\n    weight(w.): weight tensor.;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    momentum: hyperparameter;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_var\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"mean\", \"type\": \"AnyTensor\" },\n      { \"name\": \"rstd\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_mean_update\", \"type\": \"AnyTensor\" },\n      { \"name\": \"running_var_update\", \"type\": \"AnyTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bias_new\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"momentum\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MeanStdScale\",\n    \"summary\": \"MeanStdScale, it's for preprocess.\",\n    \"description\": \"1.Op Introduction\\r\\n    for preprocess, do multiplier&rshift quantize.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = (input - mean) / std * scale + zero_points\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    f32_param(w.): a weight tensor parameter of type float32.;\\r\\n\\r\\n    4.attributes\\r\\n    quant_mode: the mode or method used for quantization during the requantization operation.;\\r\\n    customization_format: custom format for the input data.;\\r\\n    channel_order: The order of color channels in the input tensor.;\\r\\n    sign: if output is signed.;\\r\\n    scale: scalar.;\\r\\n    std: standard deviation values for each channel.;\\r\\n    mean: mean values to subtract from each channel for normalization.;\\r\\n    zero_points: zero point values for each channel.;\\r\\n    resize_dims: resize the input tensor' dimensions.;\\r\\n    multi: used during the matrix multiplication operation.;\\r\\n    rshift: right shift values corresponding to each input tensor.;\\r\\n    offset: Scalar;\\r\\n    rounding_mode: The rounding method to use during quantization.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"f32_param\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"customization_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"channel_order\", \"type\": \"StrAttr\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"std\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"mean\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"zero_points\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"resize_dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multi\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"rshift\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"rounding_mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Min\",\n    \"summary\": \"min operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise min of input1 and input2. All inputs and outputs must have the same data type.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = min(input1,input2, ..., inputN)\\r\\n    ```\\r\\n    Where input1, input2, ..., inputN are the input tensors.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    coeff: It is an array and allows for scaling the output of the addition operation.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"coeff\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"multipliers\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshifts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MinConst\",\n    \"summary\": \"min_const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    min of one input and one const.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Min(input, const_val)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Mlp\",\n    \"summary\": \"w8a16 / w4a16 / a16 mlp operator\",\n    \"description\": \"to do\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight_gate\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale_gate\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp_gate\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_gate\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"weight_up\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale_up\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp_up\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_up\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"weight_down\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale_down\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"zp_down\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_down\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"w_transpose_gate\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"w_transpose_up\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"w_transpose_down\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"quantized\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"q_group_size\", \"type\": \"DefaultValuedAttr<I64Attr, 128>\" },\n      { \"name\": \"weight_bits\", \"type\": \"DefaultValuedAttr<I64Attr, 8>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Mmap2Rgbmap\",\n    \"summary\": \"Postprocess for isp mmap2rgbmap.\",\n    \"description\": \"1.Op Introduction\\r\\n    Postprocess for isp mmap2rgbmap.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Postprocess(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Move\",\n    \"summary\": \"local mem move op for layer group lmem alloc\",\n    \"description\": \"1.Op Introduction\\r\\n    local mem move op for layer group lmem alloc\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = Move(input, move_src_add, move_dest_add, move_size, ts_id)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    name: a human-readable identifier for the move operation.;\\r\\n    move_src_add: source addresses (offsets) in the local memory.;\\r\\n    move_dest_add: destination addresses (offsets) in the local memory.;\\r\\n    move_size: A list of sizes corresponding to each move operation.;\\r\\n    ts_id: A unique identifier (timestamp id or task id);\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"move_src_add\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"move_dest_add\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"move_size\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ts_id\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Mul\",\n    \"summary\": \"mul operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise multiplication of input1 and input2. input1 and input2 are tensors.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReLU((input1 * input2))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    out_f8_scales: This parameter contains the scaling factors for the output in FP8 (8-bit floating point) format.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"DefaultValuedAttr<Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}, tpu::RequantMode::MultiplierShift>\" },\n      { \"name\": \"out_f8_scales\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MulConst\",\n    \"summary\": \"mul const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise mul of input1 and input2. Input2 is constant.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input * const_val\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.MulShift\",\n    \"summary\": \"MulShift operator\",\n    \"description\": \"1.Op Introduction\\r\\n    performs an element-wise multiplication of the input tensor (after adjusting for a zero-point offset)\\r\\n\\r\\n    2.Math formula\\r\\n        output = int8(input-zx) * multiplier >> rshift + zy\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiplier\", \"type\": \"SI32Attr\" },\n      { \"name\": \"rshift\", \"type\": \"SI32Attr\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Nms\",\n    \"summary\": \"NMS operator\",\n    \"description\": \"1.Op Introduction\\r\\n    tpu nms\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        IOU(a, b) = Area(a \\\\cap b) / Area(a \\\\cup b)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): Variadic input tensor.;\\r\\n    buffer(w.): a temporary storage area for intermediate calculations or results during the NMS process.;\\r\\n\\r\\n    4.attributes\\r\\n    center_point_box: whether the bounding boxes are defined by their center points.;\\r\\n    max_output_size: the maximum number of boxes to be output after NMS.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"center_point_box\", \"type\": \"I64Attr\" },\n      { \"name\": \"max_output_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.NonZero\",\n    \"summary\": \"NonZero operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the indices of the elements that are non-zero\\r\\n    (in row-major order - by dimension).\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input[i1, i2, i3,...in] != 0\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    order: the order in which the non-zero indices should be returned.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"NonZeroOrderAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.OutBuffer\",\n    \"summary\": \"OutBuffer for store op\",\n    \"description\": \"1.Op Introduction\\r\\n     This operation stores storeOp output data on DDR when some tentor in layer-group\\r\\n     is not output to returnOp but storeAndLoad is needed.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = storeOp_output\\r\\n        \\\"storeOp_output\\\" represents the data produced by the store operation that is saved on DDR.\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    none\\r\\n\\r\\n    4.attributes\\r\\n    need_dump: whether the stored output data should be additionally dumped for debugging or analysis.;\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"need_dump\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.PackRaw\",\n    \"summary\": \"Preprocess for raw image.\",\n    \"description\": \"1.Op Introduction\\r\\n    (1) preprocess raw image from 3 byte 2 pixel to 2 byte 1 pixel,\\r\\n        for each row pixel fill 0 in top 4 bits;\\r\\n        for each img block pack to 4 channels pattern;\\r\\n    (2) cast to float then normalize and clip by black & white level;\\r\\n    (3) cast to odtype then pad img to align padding param and move to ddr;\\r\\n\\r\\n    2.Math formula\\r\\n    (1)Pixel Conversion:\\r\\n    For each pixel in the input tensor, the conversion can be represented as:\\r\\n    ```math\\r\\n        packed_pixel = (input & 0x3FF) (keeping lower 10 bits) (with top 4 bits set to 0);\\r\\n    ```\\r\\n    Here, input_pixel is the original pixel value, and packed_pixel is the newly formatted pixel value.\\r\\n    (2)Normalization:\\r\\n    The normalization step can be described as:\\r\\n    ```math\\r\\n        normalized_value = (packed_pixel - black_level) / (white_level - black_level);\\r\\n    ```\\r\\n    This formula ensures that the pixel values are scaled between 0 and 1 based on the specified black and white levels.\\r\\n    (3)Clipping:\\r\\n    After normalization, the values are clipped to ensure they remain within the valid range:\\r\\n    ```math\\r\\n        clipped_value = clip(normalized_value, 0, 1);\\r\\n    ```\\r\\n    (4)Output Casting and Padding:\\r\\n    Finally, the output tensor is formed by casting the clipped values to the desired output data type and applying padding:\\r\\n    ```math\\r\\n        output = pad(cast(clipped_value), padding_params);\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    high_table(w.): defines the upper bounds for pixel values during normalization.;\\r\\n    low_table(w.): defines the lower bounds for pixel values.;\\r\\n\\r\\n    4.attribute\\r\\n    white_level: the maximum intensity level for normalization.;\\r\\n    black_level: the minimum intensity level for normalization.;\\r\\n    threshold: a threshold value that can be used during the normalization or clipping stages.;\\r\\n    channel_order: the order of the color channels in the output tensor.(e.g., RGB, BGR).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"high_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"low_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"white_level\", \"type\": \"F64Attr\" },\n      { \"name\": \"black_level\", \"type\": \"F64Attr\" },\n      { \"name\": \"threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"channel_order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Pad\",\n    \"summary\": \"Pad operation\",\n    \"description\": \"1.Op Introduction\\r\\n    This operation pads a tensor according to the paddings you specify.\\r\\n    paddings is an integer tensor with shape [2, n], where n is the rank of tensor.\\r\\n    For each dimension D of input, paddings[0, D] indicates how many values to add\\r\\n    before the contents of tensor in that dimension, and paddings[1, D] indicates\\r\\n    how many values to add after the contents of tensor in that dimension.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input(padding, val, mode)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    paddingsT(act.):  the padding values for each dimension.;\\r\\n    // for cv18xx reflect mode\\r\\n    left_select(w.):reflect the tensor values when adding padding on the left side.;\\r\\n    right_select(w.):reflect the tensor values when adding padding on the right side.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attribute\\r\\n    paddings: defines how much padding to add before and after the contents of the input tensor for each dimension. ;\\r\\n    val: the value to be used for padding the input tensor. ;\\r\\n    mode: the padding mode include constant(Pads with a constant value); reflect(Pads with a reflection of the tensor values); replicate(Pads by replicating the edge values of the tensor).;\\r\\n    with_insert_zero : When with_insert_zero is true, it means that the PadOp first performs the insert zero operation, and then conducts the Padding expansion. In this case, the mode can only be PaddingMode::constant. When with_insert_zero is false, the insert zero operation is not performed.\\r\\n    inserts : When with_insert_zero is true, the number of zeros inserted between points in the h and w dimensions.\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"paddingsT\", \"type\": \"Optional<AnyTensorOrNone>\" },\n      { \"name\": \"left_select\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"right_select\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"paddings\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"val\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<Tpu_PaddingModeAttr{constant|reflect|symmetric|edge}, tpu::PaddingMode::constant>\" },\n      { \"name\": \"with_insert_zero\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"insert_zeros\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Permute\",\n    \"summary\": \"Permute operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform permute on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(...dim2, dim1, dim0) = PermuteOp(input(dim0, dim1, dim2...order))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attribute\\r\\n    order: An array of integers specifying the permutation order of the input tensor's dimensions.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.PixelNorm\",\n    \"summary\": \"PixelNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    pixel normalization (normalize along c-axis)\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            norm_{n, i, j} = sqrt(1 /C \\\\sum{c=1, C}input_{n, c, i, j} ^ 2) + eps\\r\\n            output_{n, c, i, j} = weight * input_{n, c, i, j} / norm_{n, i, j} + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    weight(w.): weight tensor;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    // cv18xx\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n    mantissa_table(w.): stores a table of mantissa values used in calculations to improve precision or to handle specific numerical representations.;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"mantissa_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Pool1D\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C, H', W') = Pool(max(input(N, C, H, W)))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    pool_mode: ;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    /// symmetric quantize param\\r\\n    multipliers: an array of multipliers used for quantization, It allows for scaling the input values before the addition operation.;\\r\\n    rshift: right shift values corresponding to each input tensor.;\\r\\n    /// asymmetric quantize param\\r\\n    scale: Scalar;\\r\\n    offset: Scalar;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\\r\\n    layer_group: multiple layers to be processed together or treated as a single unit during computation.;\\r\\n    /// fp8 quantize param\\r\\n    fp8_out_scale: scaling factor used for the output tensor when utilizing 8-bit floating-point (FP8) representation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pool_mode\", \"type\": \"Tpu_PoolModeAttr{Avg|Max}\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"is_adaptive\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"offset\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"layer_group\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"fp8_out_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Pool2D\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C, H', W') = Pool(max(input(N, C, H, W)))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    pool_mode: ;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    /// symmetric quantize param\\r\\n    multipliers: an array of multipliers used for quantization, It allows for scaling the input values before the addition operation.;\\r\\n    rshift: right shift values corresponding to each input tensor.;\\r\\n    /// asymmetric quantize param\\r\\n    scale: Scalar;\\r\\n    offset: Scalar;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\\r\\n    layer_group: multiple layers to be processed together or treated as a single unit during computation.;\\r\\n    /// fp8 quantize param\\r\\n    fp8_out_scale: scaling factor used for the output tensor when utilizing 8-bit floating-point (FP8) representation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pool_mode\", \"type\": \"Tpu_PoolModeAttr{Avg|Max}\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"is_adaptive\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"offset\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"layer_group\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"fp8_out_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Pool3D\",\n    \"summary\": \"pool operator\",\n    \"description\": \"1.Op Introduction\\r\\n    This performs an  pooling over the given input tensor. A sliding\\r\\n    window of size given by <kernel size> is passed over the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C, H', W') = Pool(max(input(N, C, H, W)))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    kernel_shape: the size of the convolution kernel (filter) as an array.;\\r\\n    stride: the stride for the cross-correlation, a single number or a tuple.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.\\r\\n    pool_mode: ;\\r\\n    pad_value: whether to retain the dimensions of the input tensor in the output.\\r\\n                If true, will have the same number of dimensions as the input tensor.;\\r\\n    is_adaptive: whether the pooling operation is adaptive.\\r\\n                 If true, adjusts the kernel size based on the input size to produce a specified output size.\\r\\n    count_include_pad: whether to include the padded values in the pooling count.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    ceil_mode: whether to use ceiling or floor when calculating the output size.;\\r\\n    /// symmetric quantize param\\r\\n    multipliers: an array of multipliers used for quantization, It allows for scaling the input values before the addition operation.;\\r\\n    rshift: right shift values corresponding to each input tensor.;\\r\\n    /// asymmetric quantize param\\r\\n    scale: Scalar;\\r\\n    offset: Scalar;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\\r\\n    layer_group: multiple layers to be processed together or treated as a single unit during computation.;\\r\\n    /// fp8 quantize param\\r\\n    fp8_out_scale: scaling factor used for the output tensor when utilizing 8-bit floating-point (FP8) representation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel_shape\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"pool_mode\", \"type\": \"Tpu_PoolModeAttr{Avg|Max}\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"offset\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"layer_group\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"fp8_out_scale\", \"type\": \"OptionalAttr<F64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.PoolMask\",\n    \"summary\": \"pool mask operator\",\n    \"description\": \"1.Op Introduction\\r\\n    pooling mask on input\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output1(N, C, H', W') = Pool(max(input(N, C, H, W)))\\r\\n        maskOutput(N, C, H', W') = PoolMask(argmax(input(N, C, H, W)))\\r\\n        output = scale * output1\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    scale: a scaling factor is applied to the output of the pooling operation, can adjust the intensity or magnitude of the output mask.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.PReluOp\",\n    \"summary\": \"PReluOp operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Parametric Rectified Linear Unit is an activation function.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            f(x) = slope * x   for x < 0\\r\\n            f(x) = x           for x >= 0\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    slope(w.): the activation function for negative input values.;\\r\\n\\r\\n    4.attributes\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    rshift_pos: This attribute defines the right shift for the positive output values during quantization.;\\r\\n    multiplier_pos: This parameter specifies the multiplier for the positive part of the output, used in the context of quantization.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"slope\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"rshift_pos\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"multiplier_pos\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Preprocess\",\n    \"summary\": \"FusePreprocess, it's just a placeholder op.\",\n    \"description\": \"1.Op Introduction\\r\\n    It may be divided to permute + slice + scale/scale_lut ops.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = \\\\text{Preprocess}(input, \\\\text{resize_dims}, \\\\text{mean}, \\\\text{scale}, \\\\text{channel_order})\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    customization_format: define how input data should be structured or formatted before being processed by the model.;\\r\\n    channel_order: the order of the color channels in the output tensor.(e.g., RGB, BGR).;\\r\\n    resize_dims: the target dimensions to which the input tensor should be resized.;\\r\\n    scale: a scaling factor applied to the attention scores before they are passed through the softmax function.;\\r\\n    mean: the mean values that should be subtracted from the input tensor during normalization.;\\r\\n    sign: whether the preprocessing operation should include a sign adjustment.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_mode\", \"type\": \"StrAttr\" },\n      { \"name\": \"customization_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"channel_order\", \"type\": \"StrAttr\" },\n      { \"name\": \"resize_dims\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"mean\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RandnLike\",\n    \"summary\": \"RandnLike operator\",\n    \"description\": \"1.Op Introduction\\r\\n    create a tensor with the same shape as input, and fill with value from normal distribution\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = randn(shape(input))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    randn_data(w.): the characteristics of the normal distribution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"randn_data\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Range\",\n    \"summary\": \"Range operator\",\n    \"description\": \"1.Op Introduction\\r\\n    range op.\\r\\n    generates a sequence of evenly spaced values within a specified range.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = [x | x = start + n * delta, n is an integer, and start ≤ x < limit]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    start(act.): The starting value of the sequence. This can be a tensor or None. If None, it defaults to 0.;\\r\\n    limit(w.): The exclusive upper limit of the sequence.;\\r\\n    delta(w.): The increment between each value;\",\n    \"operands\": [\n      { \"name\": \"start\", \"type\": \"AnyTensor\" },\n      { \"name\": \"limit\", \"type\": \"AnyTensor\" },\n      { \"name\": \"delta\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Reciprocal\",\n    \"summary\": \"ConstantBinary (Div) operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The Reciprocal operator is a tensor operation that performs division of a constant scalar value by an input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = const_val / input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: specifies the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Reduce\",\n    \"summary\": \"Reduce operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Computes the mean/max/prod/sum of the input tensor's element along the provided axes.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            1.Sum\\r\\n                output[i_1, i_2, i_3,..., i_k] = \\\\sum{j in A}input[i_1, i_2,..., j, ..., i_n]\\r\\n                where ( A ) is the set of axes to reduce.\\r\\n            2.Mean\\r\\n                output[i_1, i_2, i_3,..., i_k] = 1 / count (\\\\sum{j in A}input[i_1, i_2,..., j, ..., i_n])\\r\\n                where count is the number of elements being summed along the axes ( A ).\\r\\n            3.Max\\r\\n                output[i_1, i_2, i_3,..., i_k] = max{j in A}input[i_1, i_2,..., j, ..., i_n]\\r\\n            4.Product\\r\\n                output[i_1, i_2, i_3,..., i_k] = \\\\prod_{j=1}^m(input[i_1, i_2,..., i_k, j])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    reciprocal_mantissa_table(w.): store the mantissa values of the reciprocal.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"reciprocal_mantissa_table\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"keepdims\", \"type\": \"BoolAttr\" },\n      { \"name\": \"mode\", \"type\": \"ReduceModeAttr\" },\n      { \"name\": \"multiplier\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshift\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Relu\",\n    \"summary\": \"Relu operator\",\n    \"description\": \"1.Op Introduction\\r\\n    ReLU with a scalar maximum value.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReluOp(input) -> (0, 1)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RequantFp\",\n    \"summary\": \"requant float operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Requant 32/16/8 bit data to int8 or uint8 or fp8 data, by float scale and float offset, when to fp8 data, offset is not used;\\r\\n\\r\\n    2.Math formula\\r\\n    int8/uint8/fp8(output) = round(float32/float16/float8(input) x scale + offset);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    scale: Scalar;\\r\\n    offset: Scalar;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"offset\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"quant_mode\", \"type\": \"Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RequantFpAxis\",\n    \"summary\": \"requant float operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Requant 32/16/8 bit data to int8 or uint8 data, PerAxis(or PerChannel);\\r\\n\\r\\n    2.Math formula\\r\\n    int8/uint8(output) = RequantFpAxisOp(float32/float16/float8(input),quant);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    quant(act.): This attribute represents the quantization parameters tensor.\\r\\n                 It contains the values used for requantization, such as multipliers and shifts,\\r\\n                 which are specific to each axis or channel.;\\r\\n\\r\\n    4.attribute\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    first_round_mode: the rounding behavior applied to the scaled value before the offset is added.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"quant\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_mode\", \"type\": \"Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"first_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RequantInt\",\n    \"summary\": \"requant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Requant 32/16/8 bit data to int8 or uint8 data, by int multiplier and int shift;\\r\\n\\r\\n    2.Math formula\\r\\n    int8/uint8(output) = RequantIntOp (int32/16/8(input));\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    multiplier: Floating-point multiplication operations are usually converted to fixed-point multiplication operations.;\\r\\n    rshift: the number of bits to right-shift the quantized values.;\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multiplier\", \"type\": \"SI32Attr\" },\n      { \"name\": \"rshift\", \"type\": \"SI32Attr\" },\n      { \"name\": \"quant_mode\", \"type\": \"Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RequantIntAxis\",\n    \"summary\": \"requant operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Requant 32/16/8 bit data to int8 or uint8 data, PerAxis(or PerChannel);\\r\\n\\r\\n    2.Math formula\\r\\n    int8/uint8(output) = RequantIntAxisOp(int32/16/8(input), quant);\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    quant(act.): the quantization parameters tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    quant_mode: It determines how the output tensor should be quantized.;\\r\\n    round_mode: This parameter specifies the rounding mode to be used during quantization.;\\r\\n    ginfo: contains layer grouping information.;\\r\\n    rq_axis: the axis along which the requantization is performed.;\\r\\n    fuse_rq_axis: whether to fuse the requantization operation with subsequent operations along the specified axis.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"quant\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"quant_mode\", \"type\": \"Tpu_RequantModeAttr{TFLite_LShift|TFLite|MultiplierShift|OnlyShift|QDM|OnlyScale}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"rq_axis\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"fuse_rq_axis\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Reshape\",\n    \"summary\": \"Reshape operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns a tensor with the same type/values as the input, with a new shape\\r\\n    specified by the shape argument. Reshape may operate on tensors of any rank.\\r\\n    No data conversion happens during a reshape operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReshapeOp(input, shape)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attribute\\r\\n    shape: 0: keep dim from input; -1: left dim from input.;\\r\\n    flatten_start_dim: the starting dimension from which to begin flattening the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"Optional<AnyTensorOrNone>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"flatten_start_dim\", \"type\": \"DefaultValuedAttr<I64Attr, -1>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Reverse\",\n    \"summary\": \"Reverse operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Reverse on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReverseOp(input, axis)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension of reverse;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RMSNorm\",\n    \"summary\": \"RMSNorm operation\",\n    \"description\": \"1.Op Introduction\\r\\n    A simplification of the original layer normalization (LayerNorm).\\r\\n    Only normalize the last dimension of tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = gamma * input / sqrt(mean(input ^ 2) + epsilon)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    gamma(w.): scalar.;\\r\\n\\r\\n    4.attributes\\r\\n    eps: a small constant added to the denominator during normalization to prevent division by zero.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"gamma\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"F64Attr\" },\n      { \"name\": \"weight_keep_f32\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RoiAlign\",\n    \"summary\": \"RoiAlign operator\",\n    \"description\": \"1.Op Introduction\\r\\n    RoiAlign consumes an input tensor X and region of interests\\r\\n    (rois) to apply pooling across each RoI.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.ROI coordinate scaling[x1, y1, x2, y2]\\r\\n            x_scaled = x x spatial_scale\\r\\n            y_scaled = y x spatial_scale\\r\\n        2.Delineation of grid sub-areas\\r\\n            bin_height = (y2_scaled - y1_scaled) / output_height\\r\\n            bin_width  = (x2_scaled - x1_scaled) / output_width\\r\\n        3.align_corners -> true\\r\\n            x_grid = x1_scaled + (i + 0.5) x bin_width\\r\\n            y_grid = y1_scaled + (j + 0.5) x bin_height\\r\\n        output = RoiAlign(input, rois, output_height, output_width, sampling_ratio, spatial_scale, align_corners)\\r\\n    ```\\r\\n\\r\\n    3.activated and weight\\r\\n    input(act.): input tensor(4D);\\r\\n    rois: RoIs (Regions of Interest) to pool over;\\r\\n          rois is 2-D input of shape (num_rois, 4) given as [[x1, y1, x2, y2], ...].\\r\\n\\r\\n    4.attributes\\r\\n    mode: the pooling mode to be used when extracting features from the RoIs on the input feature maps.;\\r\\n    output_height: the height of the output feature maps.;\\r\\n    output_width: the width of the output feature maps.;\\r\\n    sampling_ratio: the number of sampling points in each direction (height and width).;\\r\\n    spatial_scale: a scaling factor that maps the input coordinates (RoIs) to the input feature map's scale.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rois\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"RoiAlignModeAttr\" },\n      { \"name\": \"output_height\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"sampling_ratio\", \"type\": \"I64Attr\" },\n      { \"name\": \"spatial_scale\", \"type\": \"F64Attr\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.RoiExtractor\",\n    \"summary\": \"RoiExtractor operator\",\n    \"description\": \"1.Op Introduction\\r\\n    RoiExtractor consumes an input tensor X and region of interests\\r\\n    (rois) to apply pooling across each RoI.\\r\\n\\r\\n    2.Math formula\\r\\n      ```math\\r\\n        1.ROI coordinate scaling[x1, y1, x2, y2]\\r\\n            x_scaled = x x spatial_scale\\r\\n            y_scaled = y x spatial_scale\\r\\n        2.Delineation of grid sub-areas\\r\\n            bin_height = (y2_scaled - y1_scaled) / output_height\\r\\n            bin_width  = (x2_scaled - x1_scaled) / output_width\\r\\n        3.align_corners -> true\\r\\n            x_grid = x1_scaled + (i + 0.5) x bin_width\\r\\n            y_grid = y1_scaled + (j + 0.5) x bin_height\\r\\n        output = RoiAlign(input, rois, output_height, output_width, sampling_ratio, spatial_scale, align_corners)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    rois(act.): RoIs (Regions of Interest) to pool over;\\r\\n                rois is 2-D input of shape (num_rois, 4) given as [[x1, y1, x2, y2], ...]\\r\\n    target_lvls(act.): 1-D tensor with each element denoting the index of the corresponding image in the batch.\\r\\n\\r\\n    4.attributes\\r\\n    mode: the pooling mode to be used when extracting features from the RoIs on the input feature maps.;\\r\\n    num_levels: the number of feature levels.;\\r\\n    output_height: the height of the output feature maps.;\\r\\n    output_width: the width of the output feature maps.;\\r\\n    sampling_ratio: the number of sampling points in each direction (height and width).;\\r\\n    spatial_scale: a scaling factor that maps the input coordinates (RoIs) to the input feature map's scale.;\\r\\n    align_corners: whether to align the corners of the input and output tensors.;\\r\\n    is_static: whether the RoI extraction process has a fixed (static) configuration.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"rois\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"target_lvls\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"RoiAlignModeAttr\" },\n      { \"name\": \"num_levels\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_height\", \"type\": \"I64Attr\" },\n      { \"name\": \"output_width\", \"type\": \"I64Attr\" },\n      { \"name\": \"sampling_ratio\", \"type\": \"I64Attr\" },\n      { \"name\": \"spatial_scales\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"align_corners\", \"type\": \"BoolAttr\" },\n      { \"name\": \"is_static\", \"type\": \"BoolAttr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Rope\",\n    \"summary\": \"Rope Operator\",\n    \"description\": \"1.Op Introduction\\r\\n    rope operator.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output=saturation((input1 x shift(input2, mul1_shift))⊕(input3 x shift(input2, mul2_shift))) + shift(input3, dd_shift)\\r\\n    ```\\r\\n    The operator ⊕ represents the addition of the two multiplicative results.\\r\\n    The function shift(input,shift_value) applies a shift to the input tensor based on the provided shift value.\\r\\n    The saturation function ensures that the output remains within a defined range, preventing overflow or underflow.\\r\\n\\r\\n    3.activation and weight\\r\\n    input1(act.): input tensor;\\r\\n    input2(act.): input tensor;\\r\\n    input3(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    is_permute_optimize:whether to apply optimization for permuting the input tensors.;\\r\\n    mul1_round_mode: the rounding mode to be used for the first multiplication operation.;\\r\\n    mul2_round_mode: Similar to mul1_round_mode, this attribute defines the rounding mode for the second multiplication operation.;\\r\\n    add_round_mode: the rounding mode for the addition operation.;\\r\\n    mul1_shift: the number of bits to shift the result of the first multiplication.;\\r\\n    mul2_shift: Similar to mul1_shift, this attribute defines the number of bits to shift for the second multiplication operation.;\\r\\n    add_shift: the number of bits to shift the result of the addition operation.;\\r\\n    mul1_saturation: whether the output of the first multiplication should be saturated.\\r\\n                     When set to true, the result will be clamped to prevent overflow or underflow.;\\r\\n    mul2_saturation: Similar to mul1_saturation, this attribute specifies whether saturation should be applied to the second multiplication's output.;\\r\\n    add_saturation: whether to apply saturation to the output of the addition operation.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input1\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input2\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input3\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rope_mode\", \"type\": \"DefaultValuedAttr<Tpu_RopeModeAttr{interleaved_pairs|contiguous_halves}, tpu::RopeMode::interleaved_pairs>\" },\n      { \"name\": \"is_permute_optimize\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"mul1_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"mul2_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"add_round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"mul1_shift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"mul2_shift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"add_shift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"mul1_saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"mul2_saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"add_saturation\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"force_f32\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Scale\",\n    \"summary\": \"Scale operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Y = X * S + B,\\r\\n    where the shape of X/Y is [n, c, h, w] and the shape of S/B is [1, c, 1, 1].\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input x scale + bias\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    scale(w.): scalar;\\r\\n    bias(w.): the learnable bias of the module of shape (out_channels).;\\r\\n    lshift: a left shift operation applied to the dequantized data after scaling.;\\r\\n\\r\\n    4.attributes\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"lshift\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ScaleLut\",\n    \"summary\": \"scale lut operator.\",\n    \"description\": \"1.Op Introduction\\r\\n    Performs scale on input, y = input * scale + bias.\\r\\n\\r\\n    Interfaces or Traits:\\r\\n      `NoSideEffect`\\r\\n      `TpuOpCommonInterface`    : support common TPU TG Op interface.\\r\\n      `TpuTGOpCodegenInterface` : support generate TPU instuctions.\\r\\n\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = input * scale + bias\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    table(w.): store a lookup table that may assist in optimizing the matching process.;\\r\\n\\r\\n    4.attributes\\r\\n    scale: each channel scale.;\\r\\n    bias: each channel bias.;\\r\\n    sign: if output is signed.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"bias\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"sign\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ScatterElements\",\n    \"summary\": \"ScatterElements op\",\n    \"description\": \"1.Op Introduction\\r\\n    ScatterElements takes three inputs data, updates, and indices of the same rank r >= 1 and an optional attribute axis that\\r\\n    identifies an axis of data (by default, the outer-most axis, that is axis 0). The output of the operation is produced by\\r\\n    creating a copy of the input data, and then updating its value to values specified by updates at specific index\\r\\n    positions specified by indices. Its output shape is the same as the shape of data.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ScatterElements(input[axis], updates, indices)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    indices(w.): Tensor of int32/int64 indices, of r >= 1 (same rank as input).\\r\\n             All index values are expected to be within bounds [-s, s-1] along axis of size s.\\r\\n    updates(w.): Tensor of rank r >=1 (same rank and shape as indices).\\r\\n    indices_coeff(w.): a scaling or modifying factor for the indices.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"updates\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices_coeff\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"nc_can_split\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ScatterND\",\n    \"summary\": \"ScatterND operator\",\n    \"description\": \"1.Op Introduction\\r\\n    The output of the operation is produced by creating a copy of the input data,\\r\\n    and then updating its value to values specified by updates at\\r\\n    specific index positions specified by indices.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ScatterND(input_data[indices], updates, reduction)\\r\\n    ```\\r\\n\\r\\n    3.activated and weight\\r\\n    input_data(act.): input tensor;\\r\\n    indices(w.): Tensor of rank q >= 1.;\\r\\n    updates(w.): Tensor of rank q + r - indices_shape[-1] - 1.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    reduction: Type of reduction to apply: none (0 default), add(1), sub(2), max(3), min(4), mul(5).;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input_data\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"updates\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SelectiveScan\",\n    \"summary\": \"2D Selective Scan Operator (specialized for VMamba)\",\n    \"description\": \"1. Op Introduction\\r\\n    Performs structured state space modeling (SSM) on 2D image data using a bidirectional scanning mechanism.\\r\\n    Core component of the VMamba architecture that enables efficient long-range dependency modeling in visual data.\\r\\n\\r\\n    2. Math formula\\r\\n    For each scanning direction:\\r\\n    ```\\r\\n    h_t = δA_t ⊙ h_{t-1} + δB_t ⊙ u_t\\r\\n    y_t = c_t ⊙ h_t\\r\\n    ```\\r\\n    Final output:\\r\\n    ```\\r\\n    output = concat(y_forward, y_backward) + u ⊙ D\\r\\n    ```\\r\\n    code:\\r\\n\\r\\n    for i in range(L):\\r\\n        x_up = deltaA_up[:, :, i, :] * x_up + deltaB_u_up[:, :, i, :]\\r\\n        x_down = deltaA_down[:, :, L - 1 - i, :] * x_down + deltaB_u_down[:, :, L - 1 - i, :]\\r\\n        y_up[i, :, :] = x_up[0, :, :] * c_up[i, :, 0, :]\\r\\n        y_down[L - 1 - i, :, :] = x_down[0, :, :] * c_down[L - 1 - i, :, 0, :]\\r\\n\\r\\n    y = concat((y_up, y_down), dim=1)\\r\\n    out = y if D is None else y + u * D\\r\\n\\r\\n    3. Input parameters:\\r\\n    u: Input feature map tensor (after linear projection) [N, C, L, Batch]\\r\\n    c: State-to-output projection weights [N, C, L, Batch]\\r\\n    D: Residual connection weights (optional) [N, C]\\r\\n    δA: Discretized state transition matrix [N, C, L, Batch]\\r\\n    δB_u: Combined input projection and discretized control matrix [N, C, L, Batch]\\r\\n\\r\\n    4. Attributes:\\r\\n    direction: Bidirectional scanning scheme (forward & reverse)\\r\\n    time_dim: Sequence length dimension (L = H × W)\\r\\n    channel_split: Channel dimension partitioning factor (C → C//2)\\r\\n    residual: Whether to apply residual connection (D term)\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"Cs\", \"type\": \"AnyTensor\" },\n      { \"name\": \"deltaA\", \"type\": \"AnyTensor\" },\n      { \"name\": \"deltaB_u\", \"type\": \"AnyTensor\" },\n      { \"name\": \"us\", \"type\": \"AnyTensor\" },\n      { \"name\": \"Ds\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Shape\",\n    \"summary\": \"Shape operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Takes a tensor as input and outputs an 1D int tensor containing the shape of the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = shape(input[d1, d2,...,dn])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeArith\",\n    \"summary\": \"Cpu data operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Arithmetic implementation for simple data in host memory such as 'Shape, Index, Stride' etc.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ShapeArith(input, type)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    type: the kind of arithmetic operation.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeAssign\",\n    \"summary\": \"ShapeAssign operator\",\n    \"description\": \"1.Op Introduction\\r\\n    reshape for dynamic shape\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ShapeAssign(input, shape)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    shape(w.): 0: keep dim from input; -1: left dim from input.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"shape\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeCast\",\n    \"summary\": \"Shape Cast operation\",\n    \"description\": \"1.Op Introduction\\r\\n    designed to perform shape casting, which allows the transformation of the shape of an input tensor while preserving its data type.\\r\\n\\r\\n    2.Math formula\\r\\n    output = reshape(input, new_shape);\\r\\n\\r\\n    3.activation\\r\\n    input(act.): input tensor;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeClip\",\n    \"summary\": \"ShapeClip operation running on CPU\",\n    \"description\": \"1.Op Introduction\\r\\n    The operator limits the given input to a certain range.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = min      if input[i] < min;\\r\\n                        input[i] if input[i] >= min && input[i] <= max;\\r\\n                        max      if input[i] > max;\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    min: the minimum value that the elements of the input tensor can take.;\\r\\n    max: the maximum value that the elements of the input tensor can take.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"F32Attr\" },\n      { \"name\": \"max\", \"type\": \"F32Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapePack\",\n    \"summary\": \"Shape Concatate operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Concatenates the given sequence of seq tensors in the given dimension.\\r\\n    All tensors must either have the same shape (except in the concatenating dimension) or be empty.\\r\\n\\r\\n    2.Math formula\\r\\n    output = ShapePack(input, axis)\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapePow\",\n    \"summary\": \"ShapePow operation running on CPU\",\n    \"description\": \"1.Op Introduction\\r\\n    perform an element-wise power calculation on the input tensor.\\r\\n\\r\\n    2.Math formula\\r\\n        output = input ^ n\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    exponent:;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exponent\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeReduce\",\n    \"summary\": \"ShapeReduce operator\",\n    \"description\": \"1.Op Introduction\\r\\n    ShapeReduce Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    \\\\text{output} = \\\\text{scale} \\\\times \\\\mathrm{reduce}\\\\left(\\\\text{input}, \\\\text{axes}; \\\\, \\\\text{mode}\\\\right)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\\r\\n    keepdims: whether to retain the dimensions of the input tensor in the output.\\r\\n               If true, will have the same number of dimensions as the input tensor.;\\r\\n    mode: the type of binary operation to be performed, addition, subtraction, or other types of binary operations.;\\r\\n    scale: scalar.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"keepdims\", \"type\": \"BoolAttr\" },\n      { \"name\": \"mode\", \"type\": \"ReduceModeAttr\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeReshape\",\n    \"summary\": \"ShapeReshape operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns a tensor with the same type/values as the input, with a new shape\\r\\n    specified by the shape argument. Reshape may operate on tensors of any rank.\\r\\n    No data conversion happens during a reshape operation.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ShapeReshapeOp(input, shape)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    shape: 0: keep dim from input; -1: left dim from input.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeReverse\",\n    \"summary\": \"ShapeReverse operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Reverse on input\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ShapeReverse(input, axis)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axis: the dimension of reverse;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeScatterElements\",\n    \"summary\": \"ScatterElements op\",\n    \"description\": \"1.Op Introduction\\r\\n    ScatterElements takes three inputs data, updates, and indices of the same rank r >= 1 and an optional attribute axis that\\r\\n    identifies an axis of data (by default, the outer-most axis, that is axis 0). The output of the operation is produced by\\r\\n    creating a copy of the input data, and then updating its value to values specified by updates at specific index\\r\\n    positions specified by indices. Its output shape is the same as the shape of data.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = ScatterElements(input[axis], updates, indices)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    indices(w.): Tensor of int32/int64 indices, of r >= 1 (same rank as input).\\r\\n             All index values are expected to be within bounds [-s, s-1] along axis of size s.\\r\\n    updates(w.): Tensor of rank r >=1 (same rank and shape as indices).\\r\\n    indices_coeff(w.): a scaling or modifying factor for the indices.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" },\n      { \"name\": \"updates\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"reduction\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"nc_can_split\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeSlice\",\n    \"summary\": \"ShapeSlice operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Slice Operation on shape-type tensor.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[offset[j] : ends[j] : steps[j]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    offsetT(w.): the starting indices for each slice along the specified axes.;\\r\\n    endsT(w.): the ending indices for each slice along the specified axes.;\\r\\n    stepsT(w.): the step sizes for each slice along the specified axes.;\\r\\n\\r\\n    4.attribute\\r\\n    offset: An array of the starting indices for slicing along each axis.;\\r\\n    steps: An array of the step sizes for slicing along each axis.;\\r\\n    ends: An array of the ending indices for slicing along each axis.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsetT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"endsT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"stepsT\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"steps\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ends\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeSqueeze\",\n    \"summary\": \"Onnx-Style ShapeSqueeze operator\",\n    \"description\": \"1.Op Introduction\\r\\n    ShapeSqueeze Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n        output = ShapeSqueeze(input, axes)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axes: An array of the axes along which to perform the slicing operation.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeTile\",\n    \"summary\": \"Shape Tile operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns a tensor with the same type as the input, with a new shape\\r\\n    specified by the shape argument.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i_1, i_2, i_3,...i_k] = input[i_1 mod d_1, i_2 mod d_2, i_3 mod d_3,..., i_k mod d_k]\\r\\n    ```\\r\\n    where d_j represents the corresponding dimension size of the input tensor after tiling.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    tileT(w.): how many times to replicate the input tensor along each dimension.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the computation.;\\r\\n\\r\\n    4.attributes\\r\\n    tile: the number of times to replicate the input tensor along each dimension.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"tileT\", \"type\": \"Optional<AnyTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeTranspose\",\n    \"summary\": \"ShapeTransposeOp operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform permute on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(dim1, dim0) = TransposeOp(input(dim0, dim1))\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    order: the order in which the non-zero indices should be returned.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShapeUnsqueeze\",\n    \"summary\": \"Onnx-Style ShapeUnsqueeze operator\",\n    \"description\": \"1.Op Introduction\\r\\n    ShapeUnsqueeze Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n        output = ShapeUnsqueeze(input, axes)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    axes: An array of the axes along which to perform the slicing operation.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.ShuffleChannel\",\n    \"summary\": \"ShuffleChannel operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform ShuffleChannel on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output(N, C, H, W) = input(N, Shuffle(C), H, W)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attribute\\r\\n    group: An integer specifying the number of groups to divide the channels into.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"I64Attr\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Slice\",\n    \"summary\": \"Slice operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Slice Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[offset[j] : ends[j] : steps[j]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    offsetT(w.): the starting indices for each slice along the specified axes.;\\r\\n    endsT(w.): the ending indices for each slice along the specified axes.;\\r\\n    stepsT(w.): the step sizes for each slice along the specified axes.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attribute\\r\\n    offset: An array of the starting indices for slicing along each axis.;\\r\\n    steps: An array of the step sizes for slicing along each axis.;\\r\\n    ends: An array of the ending indices for slicing along each axis.;\\r\\n    axes: An array of the axes along which to perform the slicing operation.;\\r\\n    hasparamConvert_axes: whether parameter conversion is needed for the specified axes.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offsetT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"endsT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"stepsT\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"steps\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ends\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"axes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {1}>\" },\n      { \"name\": \"hasparamConvert_axes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SliceMerge\",\n    \"summary\": \"SliceMerge\",\n    \"description\": \"1.Op Introduction\\r\\n    When there are multiple slices in the layer-group,\\r\\n    this operation combines the store op output of each slice to output to the yield op.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output =  SliceMerge(input)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Softmax\",\n    \"summary\": \"softmax operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to softmax.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            \\\\text{output}[i] = \\\\frac{e^{\\\\text{input}[i]}}{\\\\sum_{j} e^{\\\\text{input}[j]}}\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    table(w.): additional computations or transformations during the softmax operation.;\\r\\n    slope_table(w.): contain scaling factors or slopes that can adjust the output.;\\r\\n    reciprocal_table(w.): holds precomputed reciprocal values that can be used to optimize the division operations;\\r\\n    reciprocal_mantissa_table(w.): store the mantissa values of the reciprocal.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    log: when set to true, indicates that the output should be computed in log space.;\\r\\n    beta: scaling factor.;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"slope_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"reciprocal_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"reciprocal_mantissa_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"log\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SoftmaxBwd\",\n    \"summary\": \"softmax backward operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to softmax backward.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            grad_input[i] = softmax(output)[i] * (grad_output[i] - \\\\sum{j}grad_output[j] * softmax(output)[j])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    grad_output(act.): the gradient of the loss with respect to the output.;\\r\\n    output(act.): output tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    dim: If set to 0, computed across rows, If set to 1, computed across columns.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"grad_output\", \"type\": \"AnyTensor\" },\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SoftmaxCast\",\n    \"summary\": \"softmax operator\",\n    \"description\": \"Softmax + Requant\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"slope_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"reciprocal_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"reciprocal_mantissa_table\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"SI32Attr\" },\n      { \"name\": \"log\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"beta\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Sort\",\n    \"summary\": \"Sort operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to Sort.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Sort(input, axis, descending)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    buffer(w.): a temporary storage area for intermediate calculations or results during the NMS process.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    descending: the order of sorting.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"descending\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Space2Batch\",\n    \"summary\": \"Space2Batch operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Refer to `https://www.tensorflow.org/api_docs/python/tf/space_to_batch`\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        h_padding = h + pad_top + pad_bottom,\\r\\n        w_padding = w + pad_left + pad_right,\\r\\n        [n, c, h, w] => [n, c, h_padding, w_padding]\\r\\n        =>[n * block_h * block_w, c, h_padding / block_h, w / block_w];\\r\\n        h_padding and w_padding should satisfy:\\r\\n        h_padding % block_h = 0, w_padding % block_w = 0\\r\\n        The format of input or output is NCHW.\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during computation.;\\r\\n\\r\\n    4.attributes\\r\\n    block_h: The height of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    block_w: The width of the blocks used to rearrange the depth into spatial dimensions.;\\r\\n    pads: the amount of padding applied to the input. It contains four ints with top, left, bottom, right.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"block_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"pads\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Split\",\n    \"summary\": \"split tensor to continues pieces\",\n    \"description\": \"1.Op Introduction\\r\\n    The ops in one parallel should run in parallel.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input[i * split_size: (i + 1) * split_size] for i = 0, 1, ... num - 1\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Squeeze\",\n    \"summary\": \"Onnx-Style Squeeze operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Squeeze Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = squeeze(input, axes)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Store\",\n    \"summary\": \"Store operation\",\n    \"description\": \"1.Op Introduction\\r\\n    store weight from gmem to l2mem;\\r\\n\\r\\n    2.Math formula\\r\\n    output = store(input, input_gmem, ginfo, support_compress, compress_info, l2m_addr)\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n    input_gmem(w.): the input tensor containing the weights stored in global memory (gmem).;\\r\\n\\r\\n    4.attributes\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    support_compress: whether compression is supported for the load operation.;\\r\\n    compress_info: used in conjunction with support_compress to specify details like compression schemes, ratios, or any relevant metadata.;\\r\\n    l2m_addr: the address or offset within the local L2 memory (l2mem).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"support_compress\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"compress_info\", \"type\": \"OptionalAttr<Tpu_CompressAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.StridedSlice\",\n    \"summary\": \"Strided Slice operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Strided Slice Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i] = input[starts[j] + i * strides[j]]\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    starts(w.): the starting indices for each dimension of the input tensor.;\\r\\n    ends(w.): the ending indices for each dimension of the input tensor.;\\r\\n    strides(w.):  the stride values for each dimension, determining the step size between indices in the slicing operation.;\\r\\n\\r\\n    4.attribute\\r\\n    begin_mask: If set, the start index for that dimension is considered as 0.;\\r\\n    end_mask: If set, the end index for that dimension is considered as the size of the dimension.;\\r\\n    ellipsis_mask: whether allowing for the selection of all dimensions in between specified slices.;\\r\\n    new_axis_mask: which dimensions should be added as new axes in the output tensor.;\\r\\n    shrink_axis_mask: which dimensions should be removed from the output tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"starts\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"ends\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"strides\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"end_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"ellipsis_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"new_axis_mask\", \"type\": \"I64Attr\" },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Sub\",\n    \"summary\": \"sub operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise subtraction of input1 and input2. Axis of size 1 will be broadcast,\\r\\n    as necessary.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = ReLU((input1 - input2; dim))\\r\\n    ```\\r\\n    Axis of size 1 will be broadcast if necessary.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    is_reverse: whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    coeff: It is an array and allows for scaling the output of the addition operation.;\\r\\n    // quant param\\r\\n    multipliers: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshifts: an array of right shift values corresponding to each input tensor.;\\r\\n    f8_scales: scaling factors for FP8 (8-bit floating point) quantization.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"coeff\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"multipliers\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"rshifts\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I64Attr>>\" },\n      { \"name\": \"f8_scales\", \"type\": \"OptionalAttr<TypedArrayAttrBase<F64Attr>>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SubConst\",\n    \"summary\": \"sub const operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Elementwise subtraction of input1 and input2. Input1 or Input2 is constant.\\r\\n    as necessary.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = input - const_val or const_val - input\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attribute\\r\\n    const_val: the constant value to be added to each element of the input tensor(positive, negative, or zero).;\\r\\n    is_reverse: This boolean attribute indicates whether the subtraction operation is performed in reverse order.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    // quant param\\r\\n    multiplier: applied during the concatenation process to adjust the values of the input tensors.;\\r\\n    rshift: right shift values corresponding to each input tensor.;\\r\\n    f8_scale: scaling factors for FP8 (8-bit floating point) quantization.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_val\", \"type\": \"F64Attr\" },\n      { \"name\": \"is_reverse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"multiplier\", \"type\": \"DefaultValuedAttr<SI32Attr, 1>\" },\n      { \"name\": \"rshift\", \"type\": \"DefaultValuedAttr<SI32Attr, 0>\" },\n      { \"name\": \"f8_scale\", \"type\": \"DefaultValuedAttr<F64Attr, 1.0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SwapChannel\",\n    \"summary\": \"SwapChannel operator.\",\n    \"description\": \"1.Op Introduction\\r\\n    Swap Channel on input.\\r\\n\\r\\n    Interfaces or Traits:\\r\\n      `NoSideEffect`\\r\\n      `TpuOpCommonInterface`    : support common TPU TG Op interface.\\r\\n      `TpuTGOpCodegenInterface` : support generate TPU instuctions.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output(h, w, c) = input(h, w, channel_order)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    channel_order: channel swap order.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_order\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.SwapDimInner\",\n    \"summary\": \"SwapDimInner operator.\",\n    \"description\": \"1.Op Introduction\\r\\n    a dimension-swapping operation based on a specified offset.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = SwapDimInner(input, offset)\\r\\n    ```\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor;\\r\\n\\r\\n    4.attributes\\r\\n    offset: the position at which the input tensor is split.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Tile\",\n    \"summary\": \"Tile operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns a tensor with the same type as the input, with a new shape\\r\\n    specified by the shape argument.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i_1, i_2, i_3,...i_k] = input[i_1 mod d_1, i_2 mod d_2, i_3 mod d_3,..., i_k mod d_k]\\r\\n    ```\\r\\n    where d_j represents the corresponding dimension size of the input tensor after tiling.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    tileT(w.): how many times to replicate the input tensor along each dimension.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the computation.;\\r\\n\\r\\n    4.attributes\\r\\n    tile: the number of times to replicate the input tensor along each dimension.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"tileT\", \"type\": \"Optional<AnyTensor>\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.TopK\",\n    \"summary\": \"TopK operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Integrates some operations related to topk.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output_values, output_indices = TopK(input, K, axis, largest, sorted)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n    kT(w.): provide a specific tensor for K values. This allows for dynamic specification of K.;\\r\\n\\r\\n    4.attributes\\r\\n    axis: the dimension of the input tensor.;\\r\\n    K: how many of the largest (or smallest, depending on the largest attribute) values will be returned. defaults is -1;\\r\\n    largest: whether to retrieve the largest or smallest values.;\\r\\n    sorted: whether the output values should be sorted in descending order (if largest is true) or ascending order (if largest is false).;\\r\\n    values_used_only: whether to return only the values of the top K elements without their corresponding indices.;\\r\\n    buffer_val: the provision of a buffer tensor where the output values can be stored.;\\r\\n    buffer_idx: the provision of a buffer tensor for storing the output indices of the top K elements.;\\r\\n    replace_topk_indices: whether to replace the indices of the top K elements in the output with new indices.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"kT\", \"type\": \"Optional<AnyTensor>\" },\n      { \"name\": \"buffer_val\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer_idx\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"K\", \"type\": \"I64Attr\" },\n      { \"name\": \"largest\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"values_used_only\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"replace_topk_indices\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Trilu\",\n    \"summary\": \"Trilu operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Returns the upper or lower triangular part of input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Triu(input, diagonal) if upper = 1\\r\\n            output = Tril(input, diagonal) if upper = 0\\r\\n    ```\\r\\n    where, Triu() return the upper triangular part of the input tensor.\\r\\n           Tril() return the lower triangular part of the input tensor.\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    upper: whether to extract the upper or lower triangular part of the input tensor.;\\r\\n    diagonal: 0 refers to the main diagonal, positive values indicate diagonals above the main diagonal,\\r\\n              and negative values indicate diagonals below the main diagonal.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"upper\", \"type\": \"SI32Attr\" },\n      { \"name\": \"diagonal\", \"type\": \"SI32Attr\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Unsqueeze\",\n    \"summary\": \"Onnx-Style Unsqueeze operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Unsqueeze Operation on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = unsqueeze(input, axes)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    axes: the dimensions (axes) of the input tensor that should be squeezed (removed).;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Upsample\",\n    \"summary\": \"Upsample operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform nearest upsample on input.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output[i, j] = Upsample(input[i / scale_h, j / scale_w])\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    scale_h: the scaling factor for the height (number of rows) of the input tensor.;\\r\\n    scale_w: the scaling factor for the width (number of columns) of the input tensor.;\\r\\n    do_relu: If set true, the output will be activated via the ReLU function after the calculation is complete.;\\r\\n    relu_limit: If set -1.0, it means that there is no upper limit and the output will only be affected by the ReLU function.;\\r\\n    ginfo: associated with layer grouping information.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"scale_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"do_relu\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"relu_limit\", \"type\": \"DefaultValuedAttr<F64Attr, -1.0>\" },\n      { \"name\": \"ginfo\", \"type\": \"OptionalAttr<Tpu_LayerGroupAttr>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Weight2Activation\",\n    \"summary\": \"Weight to activation operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Convert weight tensor to activation tensor\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            \\\\text{output}[i] = \\\\text{input}[i] \\\\quad \\\\forall i\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.WeightReorder\",\n    \"summary\": \"WeightReorder operator\",\n    \"description\": \"1.Op Introduction\\r\\n    reorder Weight.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = Reorder(input, reorder_mode)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    input(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    reorder_mode: rearranging the weight tensor, such as sorting, shuffling, or applying a specific permutation.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reorder_mode\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Where\",\n    \"summary\": \"Where operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Return elements, either from X or Y, depending on condition.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            output = tbrn if condition else fbrn\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    cond(act.): a tensor that serves as the condition for selecting elements from the true branch (tbrn) or the false branch (fbrn).;\\r\\n    tbrn(w.): the tensor that will be selected when the condition is true.;\\r\\n    fbrn(w.): the tensor that will be selected when the condition is false.;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    x_is_const: the tensor for the true branch (tbrn) is a constant.;\\r\\n    y_is_const: the tensor for the false branch (fbrn) is a constant.;\\r\\n    x_const_val: the constant value to be used for the true branch if tbrn is not provided or is constant.;\\r\\n    y_const_val: the constant value to be used for the false branch if fbrn is not provided or is constant.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"cond\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"tbrn\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"fbrn\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"x_is_const\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"y_is_const\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"x_const_val\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"y_const_val\", \"type\": \"DefaultValuedAttr<F64Attr, 0.0>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"do_core_parallel\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.WhereBnbwdOp\",\n    \"summary\": \"WhereBnbwd operation\",\n    \"description\": \"1.Op Introduction\\r\\n    Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs\\r\\n    with additional channel dimension) as described in the paper\\r\\n    Batch Normalization: Accelerating Deep Network Training by Reducing\\r\\n    Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        output = \\\\frac{input - \\\\mathrm{E}[input]}{ \\\\sqrt{\\\\mathrm{Var}[input] + \\\\epsilon}} * \\\\gamma + \\\\beta\\r\\n    ```\\r\\n    The mean and standard-deviation are calculated per-dimension over\\r\\n    the mini-batches and $$\\\\gamma$$ and $$\\\\beta$$ are learnable parameter vectors\\r\\n    of size C (where C is the input channel size).\\r\\n\\r\\n    3.activation and weight\\r\\n    where_output(act.): an optional intermediate output from a \\\"where\\\" operation applied during the forward pass.;\\r\\n    where_grad_out(act.): the gradients computed with respect to the \\\"where\\\" output.;\\r\\n    bnbwd_input(act.): the primary input to the batch normalization backward operation.;\\r\\n    bnbwd_weight(w.): re-scale the normalized input.;\\r\\n    bnbwd_bias(w.): re-centering the normalized values.;\\r\\n    bnbwd_saved_mean(w.): the per-dimension mean values computed during the forward pass.;\\r\\n    bnbwd_saved_invstd(w.): stores the inverse standard deviation computed during the forward pass.;\\r\\n    buffer(w.): serve as a temporary storage or workspace that may be used during the computation of gradients.;\\r\\n\\r\\n    4.attributes\\r\\n    epsilon:;\\r\\n    do_recompute: whether recomputed during the backward pass instead of being stored from the forward pass.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"where_output\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"where_grad_out\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bnbwd_input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"bnbwd_weight\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bnbwd_bias\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bnbwd_saved_mean\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bnbwd_saved_invstd\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_in\", \"type\": \"AnyTensor\" },\n      { \"name\": \"weight_grad\", \"type\": \"AnyTensorOrNone\" },\n      { \"name\": \"bias_grad\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F64Attr, 1e-05>\" },\n      { \"name\": \"do_recompute\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Yield\",\n    \"summary\": \"Yield values to parent operation\",\n    \"description\": \"1.Op Introduction\\r\\n    yields values to its parent operation.\\r\\n\\r\\n    2.Math formula\\r\\n        output_i = input_i i = 1, 2, ..., N\\r\\n\\r\\n    3.activation and weight\\r\\n    operands(act.): a variadic number of input tensors.;\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.YoloDetection\",\n    \"summary\": \"YoloDetection operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Perform yolo detection on feature map.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n        1.Feature Map output\\r\\n            raw_predictions = {(b_i, c_i, p_i) | i = 1, 2,...,N}\\r\\n            b_i is the bounding box coordinates, c_i is the i-th class score, p_i is the i-th obj score.\\r\\n        2.Apply Objectness Threshold\\r\\n            filtered_predictions = {(b_i, c_i, p_i) | p_i >= obj_threshold}\\r\\n        3.Non-Maximum Suppression(NMS)\\r\\n            nms_output = NMS(filtered_predictions, nms_threshold)\\r\\n        4.Top K Detections\\r\\n            output = top_k(nms_output, keep_topk)\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    inputs(act.): input tensor;\\r\\n    buffer(w.): temporary storage of intermediate results or states during the LSTM computation.;\\r\\n\\r\\n    4.attributes\\r\\n    net_input_h: The height of the input image.;\\r\\n    net_input_w: The width of the input image;\\r\\n    nms_threshold: The threshold used for Non-Maximum Suppression (NMS).;\\r\\n    obj_threshold: The minimum confidence score required for an object detection to be considered valid.;\\r\\n    keep_topk: The maximum number of detections to keep after applying NMS.;\\r\\n    anchors: A list of anchor box dimensions.;\\r\\n    version: The version of the YOLO model being used.;\\r\\n    class_num: The number of classes that the YOLO model can predict.;\\r\\n    num_boxes: The number of bounding boxes that the model predicts for each grid cell in the feature map.;\\r\\n    agnostic_nms: whether to use class-agnostic NMS.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" },\n      { \"name\": \"buffer\", \"type\": \"AnyTensorOrNone\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"net_input_h\", \"type\": \"I64Attr\" },\n      { \"name\": \"net_input_w\", \"type\": \"I64Attr\" },\n      { \"name\": \"nms_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"obj_threshold\", \"type\": \"F64Attr\" },\n      { \"name\": \"keep_topk\", \"type\": \"I64Attr\" },\n      { \"name\": \"anchors\", \"type\": \"TypedArrayAttrBase<F64Attr>\" },\n      { \"name\": \"version\", \"type\": \"YoloVersionAttr\" },\n      { \"name\": \"class_num\", \"type\": \"DefaultValuedAttr<I64Attr, 80>\" },\n      { \"name\": \"num_boxes\", \"type\": \"DefaultValuedAttr<I64Attr, 3>\" },\n      { \"name\": \"agnostic_nms\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"tpu.Yuv2rgbFormula\",\n    \"summary\": \"Yuv2rgbFormulaOp operator\",\n    \"description\": \"1.Op Introduction\\r\\n    Yuv2rgbFormulaOp operator.\\r\\n\\r\\n    2.Math formula\\r\\n    ```math\\r\\n            (R) = (Y + 1.402 x (V - 128))\\r\\n            (G) = (Y - 0.344136 x (U - 128) - 0.714136 x (V - 128))\\r\\n            (B) = (Y + 1.772 x (U - 128))\\r\\n\\r\\n    ```\\r\\n\\r\\n    3.activation and weight\\r\\n    YUV(act.): input tensor.;\\r\\n\\r\\n    4.attributes\\r\\n    src_format: the source format of the input YUV data.;\\r\\n    dst_format: the desired destination format for the output RGB data.;\\r\\n    image_format: how the YUV data should be processed and how the output RGB data should be structured.;\\r\\n    formula_mode: the mode of the conversion formula used for the YUV to RGB transformation. ;\\r\\n    round_mode: how values are rounded during the conversion from higher precision to lower precision.;\\r\\n    multicore: whether op supports multicore execution.;\",\n    \"operands\": [\n      { \"name\": \"YUV\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src_format\", \"type\": \"UI32Attr\" },\n      { \"name\": \"dst_format\", \"type\": \"UI32Attr\" },\n      { \"name\": \"image_format\", \"type\": \"Tpu_ImageOutFormatAttr{FLOAT32|UINT8}\" },\n      { \"name\": \"formula_mode\", \"type\": \"Tpu_Yuv2rgbFormulaAttr{_601_limited|_601_full}\" },\n      { \"name\": \"round_mode\", \"type\": \"DefaultValuedAttr<Tpu_RoundModeAttr{HalfAwayFromZero|HalfUp|HalfDown|HalfToEven|HalfToOdd|HalfTowardsZero|TowardsZero|Up|Down}, tpu::RoundMode::HalfAwayFromZero>\" },\n      { \"name\": \"multicore\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"transform.affine.simplify_bounded_affine_ops\",\n    \"description\": \"Simplify the targeted affine.min / affine.max ops given the supplied\\n    lower and upper bounds for values that may be used as target op operands.\\n\\n    Example:\\n    ```\\n    %0 = transform.structured.match ops{[\\\"affine.min\\\", \\\"affine.max\\\"]} in %arg1\\n    %1 = transform.structured.match ops{[\\\"gpu.lane_id\\\"]} in %arg1\\n    transform.affine.simplify_bounded_affine_ops %0 with [%1] within [0] and [32]\\n\\n    // Multiple bounds can be specified.\\n    transform.affine.simplify_bounded_affine_ops %0 with [%1, %2] within [0, 5] and [32, 50]\\n    ```\\n\\n    Bounded op handles (`%1` and `%2) must be mapped to ops that have a single\\n    result of index type. The sets of target ops and bounded ops must not\\n    overlap.\\n\\n    #### Return modes\\n\\n    Target ops must be affine.min or affine.max ops. This transform consumes the\\n    target handle and does not produce any handle. It reads the bounded op\\n    handles.\\n\\n    TODO: Support affine.apply targets.\\n    TODO: Allow mixed PDL_Operation/int64_t for lower_bounds and upper_bounds.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"bounded_values\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower_bounds\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"upper_bounds\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$target `with` `[` ($bounded_values^ `:` type($bounded_values))? `]`\\n          `within` $lower_bounds `and` $upper_bounds attr-dict\\n          `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.affine.simplify_min_max_affine_ops\",\n    \"description\": \"Simplify the targeted `affine.min` / `affine.max` ops using the\\n    `mlir::affine::simplifyAffineMinMaxOps` transform.\\n\\n    Example:\\n    ```\\n    %0 = transform.structured.match ops{[\\\"affine.max\\\"]} in %arg1\\n    transform.affine.simplify_min_max_affine_ops %0 : !transform.any_op\\n    ```\\n\\n    #### Return modes\\n\\n    This transform consumes the target handle and does not produce any results.\\n    This transforms definitely fails if any of the targeted operations is not an\\n    `affine.min` or `affine.max` operation, or if the canonicalization patterns\\n    failed to converge.\\n    This transform silently fails if none of the operations were simplified.\\n    Otherwise, it succeeds.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.affine.super_vectorize\",\n    \"description\": \"Vectorize to a target independent n-D vector abstraction.\\n    This operation is an exposition to the transform dialect of the affine-super-vectorize pass.\\n    To make its usage easier, it ignores inputs which are children of an affine.for op (itself excluded),\\n    this way the matcher can be simpler.\\n\\n    This operation may generate operations from the vector dialect.\\n\\n    Example:\\n    ```\\n    %0 = transform.structured.match ops{[\\\"affine.for\\\"]} in %arg1 : (!transform.any_op) -> !transform.any_op\\n    transform.affine.super_vectorize %0 [8, 16] fastest_varying_pattern=[1,0] vectorize_reductions=true : !transform.any_op\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"vector_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"fastest_varying_pattern\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"vectorize_reductions\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$target $vector_sizes\\n          (`fastest_varying_pattern` `=` $fastest_varying_pattern^)? \\n          (`vectorize_reductions` `=` $vectorize_reductions^)? \\n          attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.alternatives\",\n    \"summary\": \"Attempts sequences of transforms until one succeeds\",\n    \"description\": \"This op may have an arbitrary number of regions, each of which represents a\\n    sequence of transform operations to be applied to the same payload IR. The\\n    regions are visited in order of appearance, and transforms in them are\\n    applied in their respective order of appearance. If one of these transforms\\n    fails to apply, the remaining ops in the same region are skipped an the next\\n    region is attempted. If all transformations in a region succeed, the\\n    remaining regions are skipped and the entire \\\"alternatives\\\" transformation\\n    succeeds. If all regions contained a failing transformation, the entire\\n    \\\"alternatives\\\" transformation fails.\\n\\n    It is up to the nested operations to define which errors are \\\"recoverable\\\"\\n    (or \\\"silenceable\\\") and allow another alternatives to be attempted, and which\\n    errors should be propagated without attempting the other alternatives.\\n\\n    The single operand of this operation is the scope in which the alternative\\n    transformation sequences are attempted, that is, an operation in the payload\\n    IR that contains all the other operations that may be modified by the\\n    transformations. The scope operation must be isolated from above. There is\\n    no check that the transforms are indeed scoped as their \\\"apply\\\" methods can\\n    be arbitrarily complex. Therefore it is the responsibility of the user to\\n    ensure that the transforms are scoped correctly, or to produce an\\n    irrecoverable error and thus abort the execution without attempting the\\n    remaining alternatives. Note that the payload IR outside of the given scope\\n    is not necessarily in the valid state, or even accessible to the\\n    transformation.\\n\\n    The changes to the IR within the scope performed by transforms in the failed\\n    alternative region are reverted before attempting the next region.\\n    Practically, this is achieved by cloning the scope. Therefore it is advised\\n    to limit the scope as much as possible and place the most likely\\n    alternatives early in the region list. The operation is also isolated from\\n    above and requires rediscovering the operations within the given scope to\\n    avoid additional handle invalidation. The latter restriction may be lifted\\n    in the future.\\n\\n    Each of the regions may yield transform IR handles. The handles of the first\\n    successful alternative region are returned as the results of the\\n    \\\"alternatives\\\" op. Therefore, each alternative region must yield the same\\n    number of results, which should also match the number and the types of the\\n    \\\"alternatives\\\" op results.\\n\\n    Remark: this op allows one to implement a simple \\\"try\\\" construct as follows:\\n\\n    ```mlir\\n    %result = transform.alternatives %scope {\\n    ^bb0(%arg0: !transform.any_op):\\n      // Try a fallible transformation.\\n      %0 = transform.fallible %arg0 // ...\\n      // If succeeded, yield the the result of the transformation.\\n      transform.yield %0 : !transform.any_op\\n    }, {\\n    ^bb0(%arg0: !transform.any_op):\\n      // Otherwise, the second alternative is tried and it always succeeds by\\n      // returning the original handle.\\n      transform.yield %arg0 : !transform.any_op\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"scope\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"alternatives\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"($scope^ `:` type($scope))? (`->` type($results)^)? attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.annotate\",\n    \"summary\": \"Annotates the target operation with an attribute by name\",\n    \"description\": \"Adds an attribute with the given `name` to the `target` operation. An\\n    optional `param` handle can be provided to give the attribute a specific\\n    value, else a UnitAttr is added. A single attribute will be broadcasted to\\n    all target operations, otherwise the attributes will be mapped 1:1 based on\\n    the order within the handles.\\n\\n    Produces a silenceable failure if the length of the parameter payload does\\n    not match the length of the target payload. Does not consume the provided\\n    handles.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"param\", \"type\": \"Optional<TransformParamTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$target $name attr-dict (`=` $param^)?`:` type($target) (`,` type($param)^)?\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns\",\n    \"summary\": \"Applies conversion patterns to the body of the targeted op\",\n    \"description\": \"This transform applies the specified conversion patterns to the targeted op\\n    and all nested ops. By default, this transform applies a \\\"full\\\" dialect\\n    conversion. If the `partial_conversion` unit attribute is present, this\\n    transform applies a partial dialect conversion.\\n\\n    The patterns that should be applied are specified in the first graph region\\n    of this op. They must implement the\\n    `ConversionPatternDescriptorOpInterface`. The order in which patterns are\\n    applied is unspecified; i.e., the ordering of ops in the region of this op\\n    is irrelevant.\\n\\n    The second, optional graph region contains exactly one op that specifies\\n    default type converter that should be used with this dialect conversion. If\\n    provided, this op must implement the `TypeConverterBuilderOpInterface`.\\n    Type converters are a property of conversion patterns: each conversion\\n    pattern stores the type converter that should be used in its C++ class. Each\\n    conversion pattern descriptor can optionally specify a type converter in its\\n    `getTypeConverter` interface method. If no type converter is specified in\\n    this method, the default type converter of the dialect conversion is used.\\n    Default type converters are useful if the same type converter should be used\\n    for multiple sets of conversion patterns. (Patterns that should not use this\\n    default type converter specify their own type converter.)\\n\\n    The `legal_ops`, `illegal_ops`, `legal_dialects`, `illegal_dialects`\\n    attributes specify the conversion target.\\n\\n    This transform modifies the payload. By default, it consumes the `target`\\n    handle. It does not produce any handles.\\n\\n    If the `preserve_handles` attribute is set, this transform does not consume\\n    the `target` handle and instead updates handles based on notifications from\\n    a tracking listener that is attached to the dialect conversion, similar to\\n    `transform.apply_patterns`. Only replacements via `RewriterBase::replaceOp`\\n    or `replaceOpWithNewOp` are considered \\\"payload op replacements\\\". In\\n    contrast to `transform.apply_patterns`, we allow replacement ops even if the\\n    op name has changed. This is because conversion patterns are expected to\\n    lower ops to different ops (from a different dialect). More details can be\\n    found at the documentation site of `TrackingListener`.\\n\\n    This transform produces a silenceable failure if the dialect conversion was\\n    unsuccessful or the tracking listener failed to find a replacement op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"legal_ops\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"illegal_ops\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"legal_dialects\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"illegal_dialects\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"partial_conversion\", \"type\": \"UnitAttr\" },\n      { \"name\": \"preserve_handles\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"patterns\", \"type\": \"MaxSizedRegion<1>\" },\n      { \"name\": \"default_type_converter_region\", \"type\": \"VariadicRegion<MaxSizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"`to` $target $patterns\\n    (`with` `type_converter` $default_type_converter_region^)?\\n    attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.dialect_to_llvm\",\n    \"description\": \"Collects patterns that convert ops from the specified dialect to LLVM\\n    dialect ops. These patterns require an \\\"LLVMTypeConverter\\\".\\n\\n    Note: Only dialects that implement the `ConvertToLLVMPatternInterface` are\\n    supported. Any conversion target modifications by interface implementations\\n    are currently ignored. The conversion target is fully specified by the\\n    enclosing \\\"apply_conversion_patterns\\\" op.\",\n    \"attributes\": [\n      { \"name\": \"dialect_name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$dialect_name attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.func.func_to_llvm\",\n    \"description\": \"Collects patterns that convert Func dialect ops to LLVM dialect ops.\\n    These patterns require an \\\"LLVMTypeConverter\\\".\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.gpu.gpu_subgroup_reduce_to_nvvm\",\n    \"description\": \"Collects patterns that convert GPU dialect ops related to wmma ops\\n    to NVVM dialect ops.\\n    These patterns require an \\\"LLVMTypeConverter\\\".\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.gpu.gpu_to_nvvm\",\n    \"description\": \"Collects patterns that convert GPU dialect ops to NVVM dialect ops. These\\n    patterns require an \\\"LLVMTypeConverter\\\".\",\n    \"attributes\": [\n      { \"name\": \"benefit\", \"type\": \"DefaultValuedAttr<I16Attr, 1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.gpu.gpu_to_rocdl\",\n    \"description\": \"Collects patterns that convert GPU dialect ops to ROCDL dialect ops. These\\n    patterns require an \\\"LLVMTypeConverter\\\".\",\n    \"attributes\": [\n      { \"name\": \"chipset\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`chipset` `=` $chipset attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.gpu.gpu_wmma_to_nvvm\",\n    \"description\": \"Collects patterns that convert GPU dialect ops related to wmma ops\\n    to NVVM dialect ops.\\n    These patterns require an \\\"LLVMTypeConverter\\\".\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter\",\n    \"description\": \"This operation provides an \\\"LLVMTypeConverter\\\" that lowers memref types to\\n    LLVM types.\\n\\n    The type converter can be customized as follows:\\n    - `use_aligned_alloc`: Use aligned_alloc in place of malloc for heap\\n      allocations.\\n    - `index_bitwidth`: Bitwidth of the index type, \\\"0\\\" indicates the size of a\\n      machine word.\\n    - `use_generic_functions`: Use generic allocation and deallocation functions\\n      instead of the classic \\\"malloc\\\", \\\"aligned_alloc\\\" and \\\"free\\\" functions.\\n    // TODO: the following two options don't really make sense for \\n    // memref_to_llvm_type_converter specifically.\\n    // We should have a single to_llvm_type_converter.\\n    - `use_bare_ptr_call_conv`: Replace FuncOp's MemRef arguments with bare \\n      pointers to the MemRef element types.\\n    - `data-layout`: String description (LLVM format) of the data layout that is\\n      expected on the produced module.\",\n    \"attributes\": [\n      { \"name\": \"use_aligned_alloc\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"index_bitwidth\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 64>\" },\n      { \"name\": \"use_generic_functions\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"use_bare_ptr_call_conv\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"data_layout\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.nvgpu.nvgpu_to_nvvm\",\n    \"description\": \"Collects patterns that convert NVGPU dialect ops to NVVM dialect ops. These\\n    patterns require an \\\"LLVMTypeConverter\\\".\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.scf.scf_to_control_flow\",\n    \"description\": \"Collects patterns that lower structured control flow ops to unstructured\\n    control flow.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.scf.structural_conversions\",\n    \"description\": \"Collects patterns for performing structural conversions of SCF operations.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.transform.test_conversion_patterns\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.transform.test_type_converter\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_conversion_patterns.vector.vector_to_llvm\",\n    \"description\": \"Collects patterns that convert vector dialect ops to LLVM dialect ops. These\\n    patterns require an \\\"LLVMTypeConverter\\\".\\n\\n    The patterns can be customized as follows:\\n    - `reassociate_fp_reductions`: Allows LLVM to reassociate floating-point\\n      reductions for speed.\\n    - `force_32bit_vector_indices`: Allows the compiler to assume that vector\\n      indices fit in 32-bit if that yields faster code.\",\n    \"attributes\": [\n      { \"name\": \"reassociate_fp_reductions\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"force_32bit_vector_indices\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"use_vector_alignment\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_cse\",\n    \"summary\": \"Eliminate common subexpressions in the body of the target op\",\n    \"description\": \"This transform applies common subexpression elimination (CSE) to the body\\n    of the targeted op.\\n\\n    This transform reads the target handle and modifies the payload. Existing\\n    handles to operations inside of the targeted op are retained and updated if\\n    necessary. Note that this can lead to situations where a handle, that was\\n    previously mapped to multiple distinct (but equivalent) operations, is now\\n    mapped to the same operation multiple times.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"`to` $target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.apply_dce\",\n    \"summary\": \"Eliminate dead operations in the body of the target op\",\n    \"description\": \"This transform applies dead code elimination (DCE) to the body of the\\n    targeted op.\\n\\n    Note: \\\"transform.apply_patterns\\\" with an empty region can also be used to\\n    remove dead ops. However, that op applies additional simplifications such as\\n    op folding and region simplification.\\n\\n    This transform reads the target handle and modifies the payload. Note that\\n    this transform may silently remove payload ops from handles.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"`to` $target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.apply_licm\",\n    \"summary\": \"Move loop-invariant code out of a loop-like op\",\n    \"description\": \"This transform moves side-effect free, loop invariant code out of the\\n    targeted loop-like op. The targeted op must implement the\\n    `LoopLikeOpInterface`.\\n\\n    Note: To move invariant ops from a loop nest, this transform must be applied\\n    to each loop of the loop nest, starting with the inner-most loop.\\n\\n    This transform reads the target handle and modifies the payload.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"`to` $target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.apply_patterns\",\n    \"summary\": \"Greedily applies patterns to the body of the targeted op\",\n    \"description\": \"This transform greedily applies the specified patterns to the body of the\\n    targeted op until a fixpoint was reached. Patterns are not applied to the\\n    targeted op itself.\\n\\n    The patterns that should be applied are specified in the graph region of\\n    this op. They must implement the `PatternDescriptorOpInterface`. The order\\n    in which patterns are applied is unspecified; i.e., the ordering of ops in\\n    the region of this op is irrelevant.\\n\\n    If `apple_cse` is set, the greedy pattern rewrite is interleaved with\\n    common subexpression elimination (CSE): both are repeated until a fixpoint\\n    is reached.\\n\\n    This transform only reads the target handle and modifies the payload. If a\\n    pattern erases or replaces a tracked op, the mapping is updated accordingly.\\n\\n    Only replacements via `RewriterBase::replaceOp` or `replaceOpWithNewOp` are\\n    considered \\\"payload op replacements\\\". Furthermore, only if the replacement\\n    values are defined by the same op and that op has the same type as the\\n    original op, the mapping is updated. Otherwise, this transform produces a\\n    silenceable failure. More details can be found at the documentation site of\\n    `TrackingListener`.\\n\\n    This transform also produces a silenceable failure if the pattern\\n    application did not converge within the default number of\\n    iterations/rewrites of the greedy pattern rewrite driver.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"apply_cse\", \"type\": \"UnitAttr\" },\n      { \"name\": \"max_iterations\", \"type\": \"DefaultValuedAttr<I64Attr, static_cast<uint64_t>(-1)>\" },\n      { \"name\": \"max_num_rewrites\", \"type\": \"DefaultValuedAttr<I64Attr, static_cast<uint64_t>(-1)>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"patterns\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`to` $target $patterns attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.arm_neon.vector_contract_to_bfmmla\",\n    \"description\": \"Indicates that vector contract operations should be lowered to\\n    to ArmNeon dialect operations mapping to instructions from FEAT_BF16.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.arm_neon.vector_contract_to_i8mm\",\n    \"description\": \"Indicates that vector contract operations should be lowered to\\n    to ArmNeon dialect operations mapping to instructions from FEAT_I8MM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.arm_sve.vector_contract_to_bfmmla\",\n    \"description\": \"Indicates that vector contract operations should be lowered to\\n    ArmSVE dialect operations mapping to instructions from FEAT_BF16.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.arm_sve.vector_contract_to_i8mm\",\n    \"description\": \"Indicates that vector contract operations should be lowered to\\n    to ArmSVE dialect operations mapping to instructions from FEAT_I8MM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.canonicalization\",\n    \"summary\": \"Populates canonicalization patterns\",\n    \"description\": \"This op populates all canonicalization patterns of all loaded dialects in\\n    an `apply_patterns` transform.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.gpu.eliminate_barriers\",\n    \"description\": \"Removes unnecessary GPU barriers from the function. If a barrier does not\\n    enforce any conflicting pair of memory effects, including a pair that is\\n    enforced by another barrier, it is unnecessary and can be removed.\\n\\n    The approach is based on \\\"High-Performance GPU-to-CPU Transpilation and\\n    Optimization via High-Level Parallel Constructs\\\" by  Moses, Ivanov,\\n    Domke, Endo, Doerfert, and Zinenko in PPoPP 2023. Specifically, it\\n    analyzes the memory effects of the operations before and after the given\\n    barrier and checks if the barrier enforces any of the memory\\n    effect-induced dependencies that aren't already enforced by another\\n    barrier.\\n\\n    For example, in the following code\\n\\n    ```mlir\\n      store %A\\n      barrier  // enforces load-after-store\\n      load %A\\n      barrier  // load-after-store already enforced by the previous barrier\\n      load %A\\n    ```\\n\\n    the second barrier can be removed.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.gpu.gpu_rewrite_patterns\",\n    \"description\": \"Collects GPU rewrite patterns comprising:\\n      1. GpuAllReduceRewrite patterns\\n      2. GpuGlobalIdRewriter patterns\\n      3. GpuShuffleRewriter patterns\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.gpu.gpu_shuffle_to_amdgpu\",\n    \"description\": \"Collects patterns that are tryin to promote `gpu.shuffle`s to specialized\\n    AMDGPU intrinsics.\",\n    \"attributes\": [\n      { \"name\": \"chipset\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`chipset` `=` $chipset^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.gpu.unroll_vectors_subgroup_mma\",\n    \"description\": \"Unrolls contractions to the target `m`, `n`, and `k` native vector size,\\n    along with other vector operations based on expected usage. `transfer_read`\\n    ops unroll based on the extract slice shape introduced by unrolling the\\n    contractions, while elementwise and `transfer_write` ops unroll to the shape of\\n    the C matrix (`m x n`).\\n\\n    This operation applies to pure vector operations and should be applied before\\n    lowering to subgroup_mma ops.\",\n    \"attributes\": [\n      { \"name\": \"m\", \"type\": \"I64Attr\" },\n      { \"name\": \"n\", \"type\": \"I64Attr\" },\n      { \"name\": \"k\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"`[` $m `,` $n `,` $k `]` attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.bubble_collapse\",\n    \"description\": \"Populate patterns to fold an expanding tensor.expand_shape operation with\\n    its producer generic operation by collapsing the dimensions of the generic\\n    op.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.bubble_expand\",\n    \"description\": \"Populate patterns to fold an expanding (collapsing) tensor_reshape\\n    operation with its producer (consumer) generic operation by expanding\\n    the dimensionality of the loop in the generic op.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.bubble_pack_unpack\",\n    \"description\": \"Populate patterns to bubble up or down data layout ops across other\\n    operations.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.drop_inner_tiled_unit_dims\",\n    \"description\": \"Populate patterns to drop the unit dims from inner_tiled ops with\\n    only unit iteration bounds.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.fold_fill_into_pad\",\n    \"description\": \"Populates a pattern that folds\\n    \\\"tensor.pad(cst, tensor.extract*(linalg.fill(cst)))\\\" into\\n    \\\"linalg.fill(cst, empty)\\\" when the padding constant and the fill constant\\n    are the same.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.fold_reshape_into_tensor_hal_interface\",\n    \"description\": \"Populate patterns that fold tensor.expand_shape/tensor.collapse_shape into\\n    the source hal.interface.binding.subspan op.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.fold_tensor_slice_into_transfer\",\n    \"description\": \"Indicates that tensor.extract_slice -> vector.transfer_read and\\n    vector.transfer_write -> tensor.insert_slice op chains should be folded into\\n    vector transfer read and write ops\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.hoist_forall_from_for\",\n    \"description\": \"Hoists perfectly nested `scf.forall` ops from parent `scf.for` ops if\\n    the slice the forall loop operates on is loop invariant w.r.t. the for loop.\\n\\n    This pattern only applies to forall ops that yield tensors. For bufferized\\n    loops the parallel loop is always trivially hoistable with a barrier and\\n    happens automatically when lowering the `scf.forall`.\\n\\n    Currently only supports a single result tensor.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.linalg_elementwise_greedy_fusion\",\n    \"description\": \"Populate patterns to fuse `linalg.generic` -> `linalg.generic` operations\\n    when both operations are fusable elementwise operations.\\n\\n    Note: This pattern set is parameterized for usage in IREE, therefore\\n    it is called \\\"iree.linalg_elementwise_greedy_fusion\\\".\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.lower_barrier_region\",\n    \"description\": \"Populate patterns that lowers iree_gpu.barrier_region ops to allocations\\n    and copies.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.lower_inner_tiled\",\n    \"description\": \"Populate patterns to lowering inner_tiled ops to the intrinsic specified by\\n    the |kind| attribute.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.lower_value_barrier\",\n    \"description\": \"Populate patterns to convert value barriers on vectors into gpu.barrier ops.\\n    Barriers on tensors are ignored.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.prepare_vector_to_mma\",\n    \"description\": \"Populate patterns that transform vector ops into a canonical form to\\n    convert to MMA matrix operations. If `useNvGpu` is true, then the patterns\\n    will populated will prepare for conversion to `nvgpu` mma operations\\n    rather than the `gpu` dialect WMMA operations.\",\n    \"attributes\": [\n      { \"name\": \"useNvGpu\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.unroll_multi_mma\",\n    \"description\": \"Populate patterns to unroll iree_gpu.multi_mma ops to a single intrinsic.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.unroll_vectors_gpu_mma_sync\",\n    \"description\": \"Populate patterns that unroll vectors. TODO: better documentation.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.unroll_vectors_gpu_wmma_sync\",\n    \"description\": \"Populate patterns that unroll vectors. TODO: better documentation.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.iree.vectorize_iree_gpu\",\n    \"description\": \"Populate patterns to vectorize various iree_gpu ops. Expected to run\\n    before or as a part of a larger vectorization pass.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.kernel.affine_bounds_optimization\",\n    \"description\": \"Apply simplification patterns for `arith` and `affine.apply|min|max`\\n    based on constraint information derived from\\n    `ValueBoundsConstraintSet`/`ValueBoundsOpInterface`.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.kernel.interchange_for_and_forall\",\n    \"description\": \"Includes patterns to interchange `scf.for` and `scf.forall` so that\\n    the `scf.forall` is outer-most. This is possible if the `scf.forall`\\n    effectively implements a subset insertion/extraction on the `scf.for`\\n    iteration arguments. In that case, we can hoist the `scf.forall` up\\n    without changing the semantics of the program.\\n\\n    Finds instances of the following pattern:\\n\\n    ```\\n    %result = for ... iter_args(%iter = $init) {\\n      %update = forall ... outs(%out = %iter) {\\n        %0 = extract_slice %out[%o][%s][1]\\n        ...\\n        %tile = ...\\n        parallel_insert_slice %tile into %out[%o][%s][1]\\n      }\\n      yield %update\\n    }\\n    ```\\n\\n    And produces:\\n\\n    ```\\n    %result = forall ... outs(%out = %init) {\\n      %0 = extract_slice %out[%o][%s][1]\\n      %1 = for ... iter_args(%iter = $0) {\\n        ...\\n        %tile = ...\\n        yield %tile\\n      }\\n      parallel_insert_slice %1 into %out[%o][%s][1]\\n    }\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.data_layout_propagation\",\n    \"description\": \"Collection of patterns to bubble up or down data layout ops across other\\n    operations.\",\n    \"attributes\": [\n      { \"name\": \"poison_padding\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.decompose_pack_unpack\",\n    \"description\": \"Collect patterns to decompose linalg.pack and linalg.unpack into e.g.\\n    tensor::PadOp, linalg::transposeOp Ops. Requires all outer dims to be unit.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.decompose_pad\",\n    \"description\": \"Collect patterns to decompose tensor.pad into e.g. tensor::EmptyOp,\\n    linalg::FillOp and tensor::InsertSliceOp.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.erase_unnecessary_inputs\",\n    \"description\": \"Collects patterns that promote inputs to outputs and remove unused inputs of\\n    `linalg.generic` ops.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.extract_slice_sinking\",\n    \"description\": \"Patterns to sink extract slice across other operations.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.fold_add_into_dest\",\n    \"description\": \"Collects patterns to replace linalg.add when destination passing suffices\\n    for achieving the sum.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.fold_pack_unpack_into_empty\",\n    \"description\": \"// TODO:\",\n    \"attributes\": [\n      { \"name\": \"fold_single_use_only\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.fold_unit_extent_dims_via_reshapes\",\n    \"description\": \"Collects patterns to fold unit-extent dimensions in operands/results of\\n    linalg ops on tensors via reassociative reshape ops.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.fold_unit_extent_dims_via_slices\",\n    \"description\": \"Collects patterns to fold unit-extent dimensions in operands/results of\\n    linalg ops on tensors via rank-reducing slices.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.pad_vectorization\",\n    \"description\": \"Apply patterns that vectorize tensor.pad.\\n\\n    These patterns rewrite tensor.pad Ops using vector.transfer_read and\\n    vector.transfer_write operations. This is done either by:\\n      1. Folding tensor.pad with an existing vector.transfer_read /\\n      vector.transfer_write Op (generated prior to running these patterns). \\n      2. Rewriting it (when matched together with q tensor.insert_slice\\n      consumer Op) as a vector.transfer_read + vector.transfer_write pair.\\n\\n    In both cases, these patterns look at producers and consumers for the\\n    matched tensor.pad Op to find opportunities for vectorization.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.linalg.tiling_canonicalization\",\n    \"description\": \"Collects canonicalization patterns relevant to apply after tiling patterns.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.memref.alloc_to_alloca\",\n    \"description\": \"Collects patterns to rewrite scoped dynamic allocation (`alloc`/`dealloc`\\n    pairs) into automatic allocation (`alloca`) in the same scope, for memrefs\\n    of static shape.\\n\\n    The `size_limit` attribute controls the maximum allocated memory (in bytes,\\n    subject to data layout) for which the pattern applies.\",\n    \"attributes\": [\n      { \"name\": \"size_limit\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"(`size_limit` `(` $size_limit^ `)`)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.memref.expand_ops\",\n    \"description\": \"Collects patterns to rewrite ops within the memref dialect.\\n\\n    - Converts `atomic_rmw` that cannot be lowered to a simple atomic op with\\n      AtomicRMWOpLowering pattern, e.g. with \\\"minf\\\" or \\\"maxf\\\" attributes, to\\n      `memref.generic_atomic_rmw` with the expanded code.\\n    - Converts `memref.reshape` that has a target shape of a statically-known\\n      size to `memref.reinterpret_cast`.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.memref.expand_strided_metadata\",\n    \"description\": \"Collects patterns for expanding memref operations that modify the metadata\\n    (sizes, offset, strides) of a memref into easier to analyze constructs.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.memref.extract_address_computations\",\n    \"description\": \"Collects patterns for extracting address computations from operations\\n    with memory accesses such that these memory accesses use only a base\\n    pointer.\\n\\n    For instance,\\n    ```mlir\\n    memref.load %base[%off0, ...]\\n    ```\\n\\n    Will be rewritten in:\\n    ```mlir\\n    %new_base = memref.subview %base[%off0,...][1,...][1,...]\\n    memref.load %new_base[%c0,...]\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.memref.fold_memref_alias_ops\",\n    \"description\": \"Collects patterns for folding memref aliasing ops (memref.subview) into\\n    consumer load/store ops (affine.load, memref.load, nvgpu.ldmatrix,\\n    vector.load, vector.transfer_read, affine.store, memref.store, etc.) and\\n    other ops (e.g., memref.subview).\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.memref.resolve_ranked_shaped_type_result_dims\",\n    \"description\": \"Collects patterns that resolve `memref.dim` operations with values that are\\n    defined by operations that implement the `ReifyRankedShapedTypeOpInterface`,\\n    in terms of shapes of its input operands.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.scf.for_loop_canonicalization\",\n    \"description\": \"Collects patterns for canonicalizing operations inside SCF loop bodies.\\n    At the moment, only affine.min/max computations with iteration variables,\\n    loop bounds and loop steps are canonicalized.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.bubble_up_extract_slice\",\n    \"description\": \"Indicates that producers of tensor.extract_slice should swap and operate on \\n    the result of the slice.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.decompose_concat\",\n    \"description\": \"Indicates that tensor.concat ops should be decomposed into a chain of\\n    tensor.insert_slice operations inserting into a materialized destination.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.drop_redundant_insert_slice_rank_expansion\",\n    \"description\": \"Indicates that redundant tensor.insert_slice rank reductions should be\\n    dropped. E.g., cases where a tensor.extract_slice rank reduction immediately\\n    follows an inverse tensor.insert_slice rank expansion.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.fold_into_pack_and_unpack\",\n    \"description\": \"Indicates that operations like tensor.pad and tensor.extract_slice should\\n    be folded into linalg.pack and linalg.unpack operations, respectively.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.fold_tensor_empty\",\n    \"description\": \"Indicates that tensor.extract_slice and reassociative reshapes should be\\n    folded into tensor.empty.\\n\\n    If `fold_single_use_only` is set to \\\"true\\\", only tensor.empty that have a\\n    single use are folded.\",\n    \"attributes\": [\n      { \"name\": \"fold_single_use_only\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.fold_tensor_subset_ops\",\n    \"description\": \"Indicates that tensor.empty should be folded with tensor.extract_slice,\\n    tensor.expand_shape and tensor.collapse_shape.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.fold_tensor_subset_ops_into_vector_transfers\",\n    \"description\": \"Indicates that tensor.extract_slice -> vector.transfer_read and\\n    vector.transfer_write -> tensor.insert_slice op chains should be folded into\\n    vector tranfer read and write ops\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.merge_consecutive_insert_extract_slice\",\n    \"description\": \"Indicates that consecutive tensor.extract_slice/tensor.insert_slice ops\\n    should be merged into a single op. These patterns are not canonicalizations\\n    because the bufferization is sensitive to IR structure.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.reassociative_reshape_folding\",\n    \"description\": \"Indicates that reassociative reshapes (tensor.collapse_shape /\\n    tensor.expand_shape) should be folded with inverse rank expansions / rank\\n    reductions (via tensor.insert_slice / tensor.extract_slice).\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.tensor.rewrite_as_constant\",\n    \"description\": \"Indicates that tensor ops (such as tensor.generate) should be replaced with\\n    constants (arith.constant) when possible.\",\n    \"attributes\": [\n      { \"name\": \"aggressive\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`aggressive` $aggressive^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.transform.test_patterns\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.cast_away_vector_leading_one_dim\",\n    \"description\": \"Collect a set of leading one dimension removal patterns.\\n\\n    These patterns insert vector.shape_cast to remove leading one dimensions\\n    to expose more canonical forms of read/write/insert/extract operations.\\n    With them, there are more chances that we can cancel out extract-insert\\n    pairs or forward write-read pairs.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.drop_inner_most_unit_dims_from_xfer_ops\",\n    \"description\": \"Apply vector patterns to drop the inner most unit dims from\\n    vector.transfer_read and vector.transfer_write Ops by taking a subview (via\\n    memref.subview) of the original source/destination MemRef. Since it\\n    requires the input/ouptu to be MemRefs, this Op is only helpful\\n    past-bufferization.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.drop_unit_dims_with_shape_cast\",\n    \"description\": \"Apply vector patterns to fold unit dims with vector.shape_cast Ops:\\n      - DropUnitDimFromElementwiseOps\\n      - DropUnitDimsFromScfForOp\\n      - DropUnitDimsFromTransposeOp\\n\\n    Excludes patterns for vector.transfer Ops. This is complemented by\\n    shape_cast folding patterns.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.elementwise_to_vector\",\n    \"description\": \"Collect a set of patterns that fold elementwise op on vectors to the vector\\n    dialect.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.flatten_vector_transfer_ops\",\n    \"description\": \"Collect patterns to rewrite contiguous row-major vector.transfer_read or \\n    vector.transfer_write operations to a 1D operation.\",\n    \"attributes\": [\n      { \"name\": \"target_vector_bitwidth\", \"type\": \"DefaultValuedAttr<UI32Attr, std::numeric_limits<unsigned>::max()>\" }\n    ],\n    \"assemblyFormat\": \"(`target_vector_bitwidth` `=` $target_vector_bitwidth^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.fold_arith_extension\",\n    \"description\": \"Collect a set of patterns that fold arithmetic extension on floating point\\n    into vector contract for the backends with native support.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.interleave_to_shuffle\",\n    \"description\": \"Indicates that 1D vector interleave operations should be rewritten as\\n    vector shuffle operations.\\n\\n    This is motivated by some current codegen backends not handling vector\\n    interleave operations.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_bitcast\",\n    \"description\": \"Indicates that vector bitcast operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usally a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_broadcast\",\n    \"description\": \"Indicates that vector broadcast operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usally a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_contraction\",\n    \"description\": \"Indicates that vector contraction-like operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorContractLoweringAttr{dot|llvmintr|outerproduct|parallelarith}, vector::VectorContractLowering::OuterProduct>\" }\n    ],\n    \"assemblyFormat\": \"(`lowering_strategy` `=` $lowering_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_create_mask\",\n    \"description\": \"Indicates that vector create_mask-like operations should be lowered to\\n    finer-grained vector primitives.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_gather\",\n    \"description\": \"Indicates that vector.gather operations should be lowered to\\n    finer-grained vector primitives.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_interleave\",\n    \"description\": \"Indicates that vector interleave operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usally a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_masked_transfers\",\n    \"description\": \"Apply opt-in patterns that lower vector.mask operations surrounding\\n    side-effecting ops:\\n      - MaskedTransferReadOpPattern\\n      - MaskedTransferWriteOpPattern\\n      - MaskedGatherOpPattern\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_masks\",\n    \"description\": \"Indicates that vector.create_mask and vector.constant_mask operations\\n    should be lowered to finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_multi_reduction\",\n    \"description\": \"Indicates that vector multi_reduction-like operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorMultiReductionLoweringAttr{innerparallel|innerreduction}, vector::VectorMultiReductionLowering::InnerParallel>\" }\n    ],\n    \"assemblyFormat\": \"(`lowering_strategy` `=` $lowering_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_outerproduct\",\n    \"description\": \"Indicates that the vector outerproduct operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_scan\",\n    \"description\": \"Indicates that vector.scan operations should be lowered to\\n    finer-grained vector primitives.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_shape_cast\",\n    \"description\": \"Indicates that vector shape_cast operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_transfer\",\n    \"description\": \"Indicates that vector transfer operations should be lowered to finer-grained\\n    vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"attributes\": [\n      { \"name\": \"max_transfer_rank\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" }\n    ],\n    \"assemblyFormat\": \"(`max_transfer_rank` `=` $max_transfer_rank^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.lower_transpose\",\n    \"description\": \"Indicates that vector transpose-like operations should be lowered to\\n    finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorTransposeLoweringAttr{eltwise|llvmintr|shuffle_1d|shuffle_16x16}, vector::VectorTransposeLowering::EltWise>\" },\n      { \"name\": \"avx2_lowering_strategy\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"oilist (\\n      `lowering_strategy` `=` $lowering_strategy\\n      | `avx2_lowering_strategy` `=` $avx2_lowering_strategy\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.materialize_masks\",\n    \"description\": \"Indicates that mask operations should be lowered to fine-grained arithemtic\\n    operations.\\n\\n    This is usually the last step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.multi_reduction_flattening\",\n    \"description\": \"Indicates that vector multi_reduction operations should be flattened from\\n    more than 2-D to 2-D.\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorMultiReductionLoweringAttr{innerparallel|innerreduction}, vector::VectorMultiReductionLowering::InnerParallel>\" }\n    ],\n    \"assemblyFormat\": \"(`lowering_strategy` `=` $lowering_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.multi_reduction_unrolling\",\n    \"description\": \"Indicates that vector multi_reduction operations should be unrolled.\\n    1-D multi_reductions are converted directly to vector.reduction.\\n    2-D multi_reductions are unrolled into either a sequence of\\n    vector.reduction ops (innerreduction) or element-wise arith ops\\n    (innerparallel).\\n\\n    This populates the patterns from\\n    `populateVectorMultiReductionUnrollingPatterns`, i.e.:\\n    * `OneDimMultiReductionToReduction`\\n    * `TwoDimMultiReductionToReduction` (innerreduction)\\n    * `TwoDimMultiReductionToElementWise` (innerparallel)\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorMultiReductionLoweringAttr{innerparallel|innerreduction}, vector::VectorMultiReductionLowering::InnerParallel>\" }\n    ],\n    \"assemblyFormat\": \"(`lowering_strategy` `=` $lowering_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.rank_reducing_subview_patterns\",\n    \"description\": \"Apply opt-in vector transfer permutation patterns that include:\\n      - TransferReadDropUnitDimsPattern\\n      - TransferWriteDropUnitDimsPattern\\n\\n    These patterns have the effect of rewriting a vector.transfer with unit\\n    dimensions into a rank-reduced version thanks to subview operations.\\n    This is complemented by shape_cast folding patterns.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.reduction_to_contract\",\n    \"description\": \"Apply opt-in patterns that convert reductions to contract:\\n      - MultiReduceToContract\\n      - CombineContractBroadcast\\n      - CombineContractABTranspose\\n      - CombineContractResultTranspose\\n      - ReorderElementwiseOpsOnTranspose\\n      - ReorderElementwiseOpsOnBroadcast\\n      - ReorderCastOpsOnBroadcast\\n\\n    These patterns have the effect of rewriting a vector.multi_reduce into a\\n    vector.contract.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.reorder_and_expand_multi_reduction_dims\",\n    \"description\": \"Indicates that vector multi_reduction-like operations should be\\n    transformed such that all reduction dimensions become innermost or\\n    outermost, and 1-D reductions are lifted to 2-D.\\n\\n    This populates the patterns from\\n    `populateVectorMultiReductionReorderAndExpandPatterns`, i.e.:\\n    * `InnerOuterDimReductionConversion`\\n    * `OneDimMultiReductionToTwoDim`\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorMultiReductionLoweringAttr{innerparallel|innerreduction}, vector::VectorMultiReductionLowering::InnerParallel>\" }\n    ],\n    \"assemblyFormat\": \"(`lowering_strategy` `=` $lowering_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.reorder_multi_reduction_dims\",\n    \"description\": \"Indicates that vector multi_reduction-like operations should be\\n    transformed such that all reduction dimensions become innermost or\\n    outermost, depending on `lowering_strategy`.\\n\\n    This populates the patterns from\\n    `populateVectorMultiReductionReorderPatterns`, i.e.:\\n    * `InnerOuterDimReductionConversion`\",\n    \"attributes\": [\n      { \"name\": \"lowering_strategy\", \"type\": \"DefaultValuedAttr<VectorMultiReductionLoweringAttr{innerparallel|innerreduction}, vector::VectorMultiReductionLowering::InnerParallel>\" }\n    ],\n    \"assemblyFormat\": \"(`lowering_strategy` `=` $lowering_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.rewrite_narrow_types\",\n    \"description\": \"Indicates that vector narrow rewrite operations should be applied.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\\n\\n    Warning: these patterns currently only work for little endian targets.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.rewrite_vector_transfer_read_to_constant\",\n    \"description\": \"Includes a vector simplification pattern in the set. The pattern\\n    detects when a `vector.transfer_read` is reading from the result of\\n    a `vector.transfer_write` which has an overwrite/fill-like effect.\\n\\n    Such `vector.transfer_reads` are then replaced with `arith.constant`\\n    with a splat constant value.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.sink_mem_ops\",\n    \"description\": \"Patterns that replace redundant Vector Ops (followed by\\n    `vector.load`/`vector.store`) with either vector.load/vector.store or\\n    `memref.load`/`memref.store`. Currently limited to 1-element vectors.\\n\\n    Example:\\n    ```\\n    vector.load %arg0[%arg1] : memref<?xf32>, vector<4xf32>\\n    vector.extract %0[1] : f32 from vector<4xf32>\\n    ```\\n    Gets converted to:\\n    ```\\n    %c1 = arith.constant 1 : index\\n    %0 = arith.addi %arg1, %c1 overflow<nsw> : index\\n    %1 = memref.load %arg0[%0] : memref<?xf32>\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.sink_ops\",\n    \"description\": \"Patterns that remove redundant Vector Ops by re-ordering them with\\n    e.g. elementwise Ops.\\n\\n    Example:\\n    ```\\n    %at = vector.transpose %a, [1, 0]: vector<4x2xf32> to vector<2x4xf32>\\n    %bt = vector.transpose %b, [1, 0]: vector<4x2xf32> to vector<2x4xf32>\\n    %r = arith.addf %at, %bt : vector<2x4xf32>\\n    ```\\n    gets converted to:\\n    ```\\n    %0 = arith.addf %a, %b : vector<4x2xf32>\\n    %r = vector.transpose %0, [1, 0] : vector<2x4xf32>\\n    ```\\n    At the moment, these patterns are limited to vector.broadcast,\\n    vector.transpose and vector.extract.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.split_transfer_full_partial\",\n    \"description\": \"Indicates that vector transfer operations should be split to full and\\n    partial parts.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"attributes\": [\n      { \"name\": \"split_transfer_strategy\", \"type\": \"DefaultValuedAttr<VectorTransferSplitAttr{none|vector-transfer|linalg-copy|force-in-bounds}, vector::VectorTransferSplit::LinalgCopy>\" }\n    ],\n    \"assemblyFormat\": \"(`split_transfer_strategy` `=` $split_transfer_strategy^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.transfer_permutation_patterns\",\n    \"description\": \"Apply opt-in vector transfer permutation patterns that include:\\n      - TransferReadPermutationLowering\\n      - TransferWritePermutationLowering\\n      - TransferOpReduceRank\\n      - TransferWriteNonPermutationLowering\\n\\n    These patterns have the effect of rewriting a vector.transfer with an\\n    arbitrary permutation_map to a vector.transfer with a permutation_map that\\n    is a minor identity followed by a vector.transpose.\\n\\n    In other words, this makes the vector.transfer contiguous on the most minor\\n    dimensions and materializes the permutation_map as a vector.transpose.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.transfer_to_scf\",\n    \"description\": \"Indicates that vector transfer operations should be rewritten with scf.for\\n    loops over finer-grained vector primitives.\\n\\n    This is usually a late step that is run after bufferization as part of the\\n    process of lowering to e.g. LLVM or NVVM.\",\n    \"attributes\": [\n      { \"name\": \"max_transfer_rank\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"full_unroll\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"oilist (\\n        `max_transfer_rank` `=` $max_transfer_rank\\n      | `full_unroll` `=` $full_unroll\\n    )\\n    attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.unroll_from_elements\",\n    \"description\": \"Indicates that vector from_elements operations should be unrolled\\n    along the outermost dimension.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.vector.unroll_to_elements\",\n    \"description\": \"Indicates that vector to_elements operations should be unrolled\\n    along the outermost dimension.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86.shuffle_vector_fma_ops\",\n    \"description\": \"Collect patterns to shuffle FMAs with x86 operations as operands \\n    such that FMAs are grouped with respect to odd/even packed index.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86.sink_vector_producer_ops\",\n    \"description\": \"Collect patterns to sink vector producer operations forward in a block to \\n         place them immediately before their first use.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86.vector_contract_bf16_to_fma\",\n    \"description\": \"Collect patterns to lower a BF16 type vector.contract operation\\n        to a FMA via emulation lowering using BF16 packed operations.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86.vector_contract_to_amx_dot_product\",\n    \"description\": \"Collect patterns to lower a BF16/Int8 type vector.contract operation \\n\\tto a BF16/Int8 AMX tiled dot-product.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86.vector_contract_to_fma\",\n    \"description\": \"Collect patterns to lower a F32 type vector.contract operation to a FMA.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86.vector_contract_to_packed_type_dot_product\",\n    \"description\": \"Collect patterns to lower a BF16/Int8 type vector.contract operation \\n\\tto a BF16/Int8 dot-product.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86vector.shuffle_vector_fma_ops\",\n    \"description\": \"Collect patterns to shuffle FMAs with x86vector operations as operands \\n    such that FMAs are grouped with respect to odd/even packed index.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86vector.sink_vector_producer_ops\",\n    \"description\": \"Collect patterns to sink vector producer operations forward in a block to \\n         place them immediately before their first use.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86vector.vector_contract_bf16_to_fma\",\n    \"description\": \"Collect patterns to lower a BF16 type vector.contract operation\\n        to a FMA via emulation lowering using BF16 packed operations.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86vector.vector_contract_to_fma\",\n    \"description\": \"Collect patterns to lower a F32 type vector.contract operation to a FMA.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_patterns.x86vector.vector_contract_to_packed_type_dot_product\",\n    \"description\": \"Collect patterns to lower a BF16/Int8 type vector.contract operation \\n\\tto a BF16/Int8 dot-product.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.apply_registered_pass\",\n    \"summary\": \"Applies the specified registered pass or pass pipeline\",\n    \"description\": \"This transform applies the specified pass or pass pipeline to the targeted\\n    ops. The name of the pass/pipeline is specified as a string attribute, as\\n    set during pass/pipeline registration.\\n\\n    Optionally, pass options may be specified via a DictionaryAttr. This\\n    dictionary is converted to a string -- formatted `key=value ...` -- which\\n    is expected to be in the exact format used by the pass on the commandline.\\n    Values are either attributes or (SSA-values of) Transform Dialect params.\\n    For example:\\n\\n    ```mlir\\n    transform.apply_registered_pass \\\"canonicalize\\\"\\n        with options = { \\\"top-down\\\" = false,\\n                         \\\"max-iterations\\\" = %max_iter,\\n                         \\\"test-convergence\\\" = true,\\n                         \\\"max-num-rewrites\\\" = %max_rewrites }\\n        to %module\\n    : (!transform.any_param, !transform.any_param, !transform.any_op) -> !transform.any_op\\n    ```\\n\\n    Options' values which are `ArrayAttr`s are converted to comma-separated\\n    lists of options. Likewise for params which associate multiple values.\\n\\n    This op first looks for a pass pipeline with the specified name. If no such\\n    pipeline exists, it looks for a pass with the specified name. If no such\\n    pass exists either, this op fails definitely.\\n\\n    This transform consumes the target handle and produces a new handle that is\\n    mapped to the same op. Passes are not allowed to remove/modify the operation\\n    that they operate on, so the target op is guaranteed to still exist. The\\n    target handle is invalidated because a pass may arbitrarily modify the body\\n    of targeted ops.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"dynamic_options\", \"type\": \"Variadic<TransformParamTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pass_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"options\", \"type\": \"DefaultValuedAttr<DictionaryAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$pass_name (`with` `options` `=`\\n      custom<ApplyRegisteredPassOptions>($options, $dynamic_options)^)?\\n      `to` $target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.bufferization.buffer_loop_hoisting\",\n    \"description\": \"Hoist buffer allocations (\\\"memref.alloc\\\" and \\\"memref.alloca\\\") from loops\\n    within the targeted op. This transform assumes that there are no buffer\\n    deallocation ops in the IR.\\n\\n    This transform reads the `target` handle and modifies the payload.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.bufferization.eliminate_empty_tensors\",\n    \"description\": \"Try to eliminate all `tensor.empty` ops within the targeted op by replacing\\n    them with another destination tensor.\\n\\n    \\\"tensor.empty\\\" ops cannot be bufferized. They can either be converted to\\n    \\\"bufferization.alloc_tensor\\\" or replaced with another tensor (via this\\n    transform). \\\"tensor.empty\\\" does not specify the contents of the returned\\n    tensor so their results can be replaced with arbitrary tensor values as long\\n    as the dimensions match.\\n\\n    This transformation looks for subset ops that insert a tensor that\\n    originates from a \\\"tensor.empty\\\" (as per the reverse use-def chain). Such\\n    \\\"tensor.empty\\\" ops are replaced with the destination subset.\\n\\n    Example:\\n\\n    ```\\n    %0 = tensor.empty() : tensor<5xf32>\\n    %1 = linalg.fill ... outs(%0)\\n    %2 = tensor.insert_slice %1 into %t[1][5][1]\\n    ```\\n\\n    Is rewritten with:\\n    ```\\n    %0 = tensor.extract_slice %t[1][5][1]\\n    %1 = linalg.fill ... outs(%0)\\n    %2 = tensor.insert_slice %1 into %t[1][5][1]\\n    ```\\n\\n    In the above example, the subset op is \\\"tensor.insert_slice\\\". When tracing\\n    back the reverse use-def chain of a the source, we end up at a\\n    \\\"tensor.empty\\\" op.\\n\\n    The above example can bufferize without an allocation (in the absence of\\n    other conflicts) because there is no longer a `tensor.empty` op.\\n\\n    See `-eliminate-empty-tensors` for more details.\\n\\n    #### Return modes\\n\\n    This transform reads the target handle and modifies the payload. It does\\n    not produce any handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.bufferization.empty_tensor_to_alloc_tensor\",\n    \"description\": \"Replace a tensor.empty with a bufferization.tensor_alloc.\\n\\n    #### Return modes\\n\\n    This operation consumes the `target` handle and produces the `transformed`\\n    handle. `target` is expected to be a `tensor.empty` operation. The transform\\n    always succeeds.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Transform_EmptyOp\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"Transform_AllocTensorOp\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.bufferization.one_shot_bufferize\",\n    \"description\": \"Indicates that the given `target` op should be bufferized with One-Shot\\n    Bufferize. The bufferization can be configured with various attributes that\\n    corresponding to options in `BufferizationOptions` and the\\n    `one-shot-bufferize` pass. More information can be found in the pass\\n    documentation.\\n\\n    The targeted ops must be modules or functions. This is because there is\\n    always a single, bufferized replacement op for such targets.\\n\\n    Note: Only ops that implement `BufferizableOpInterface` are bufferized. All\\n    other ops are ignored if `allow_unknown_ops`. If `allow_unknown_ops` is\\n    unset, this transform fails when an unknown/non-bufferizable op is found.\\n    Many ops implement `BufferizableOpInterface` via an external model. These\\n    external models must be registered when applying this transform op;\\n    otherwise, said ops would be considered non-bufferizable.\\n\\n    #### Return modes\\n\\n    This operation consumes the `target` handle and produces the `transformed`\\n    handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function_boundary_type_conversion\", \"type\": \"OptionalAttr<LayoutMapOption{InferLayoutMap|IdentityLayoutMap|FullyDynamicLayoutMap}>\" },\n      { \"name\": \"allow_return_allocs_from_loops\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"allow_unknown_ops\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"bufferize_function_boundaries\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"dump_alias_sets\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"test_analysis_only\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"print_conflicts\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"check_parallel_regions\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"memcpy_op\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"memref.copy\\\">\" }\n    ],\n    \"assemblyFormat\": \"(`layout` `{` $function_boundary_type_conversion^ `}`)?\\n    $target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.cast\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `to` type($output)\"\n  },\n  {\n    \"name\": \"transform.collect_matching\",\n    \"summary\": \"Collects all payload ops that match the given named matcher\",\n    \"description\": \"Collects operations or other payload IR objects nested under `root`\\n    (inclusive) that match the given matcher expressed as a named sequence. The\\n    matcher sequence must accept exactly one argument that it is not allowed to\\n    modify. It must yield as many values as this op has results. Each of the\\n    yielded values must be associated with exactly one payload object. If any\\n    operation in the matcher sequence produces a silenceable failure, the\\n    matcher advances to the next payload operation in the walk order without\\n    finishing the sequence.\\n\\n    The i-th result of this operation is constructed by concatenating the i-th\\n    yielded payload IR objects of all successful matcher sequence applications.\\n    All results are guaranteed to be mapped to the same number of payload IR\\n    objects.\\n\\n    The operation succeeds unless the matcher sequence produced a definite\\n    failure for any invocation.\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"matcher\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$matcher `in` $root attr-dict `:` functional-type($root, $results)\"\n  },\n  {\n    \"name\": \"transform.debug.emit_param_as_remark\",\n    \"summary\": \"Prints the parameter as a diagnostic remark\",\n    \"description\": \"This operation emits a diagnostic remark containing the string form of the\\n    attributes associated with the parameter provided as attribute. It takes\\n    as optional arguments:\\n      - an additional message text to prepend;\\n      - a handle pointing to operations the location of which will be used to\\n        emit the diagnostic; if multiple operations are associated, the\\n        diagnostic is emitted for all of their respective locations.\\n\\n    This operation always succeeds.\",\n    \"operands\": [\n      { \"name\": \"param\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"anchor\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$param (`,` $message^)?  (`at` $anchor^)?attr-dict `:` type($param) (`,` type($anchor)^)?\"\n  },\n  {\n    \"name\": \"transform.debug.emit_remark_at\",\n    \"summary\": \"Print a message as diagnostic remark attached to payload\",\n    \"description\": \"This operation emits a diagnostic remark with the given message at the\\n    location of each payload object associated with the argument. The argument\\n    may be an operation or a value handle.\\n\\n    This operation always succeeds.\",\n    \"operands\": [\n      { \"name\": \"at\", \"type\": \"Transform_AnyHandleType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$at `,` $message attr-dict `:` type($at)\"\n  },\n  {\n    \"name\": \"transform.dlti.query\",\n    \"summary\": \"Return attribute (as param) associated to key via DTLI\",\n    \"description\": \"This op queries data layout and target information associated to payload\\n    IR by way of the DLTI dialect.\\n\\n    A lookup is performed for the given `keys` at `target` op - or its closest\\n    interface-implementing ancestor - by way of the `DLTIQueryInterface`, which\\n    returns an attribute for a key. Each key should be either a (quoted) string\\n    or a type. If more than one key is provided, the lookup continues\\n    recursively, now on the returned attributes, with the condition that these\\n    implement the above interface. For example if the payload IR is\\n\\n    ```\\n    module attributes {#dlti.map = #dlti.map<#dlti.dl_entry<\\\"A\\\",\\n                                     #dlti.map<#dlti.dl_entry<\\\"B\\\", 42: int>>>} {\\n      func.func private @f()\\n    }\\n    ```\\n    and we have that `%func` is a Tranform handle to op `@f`, then\\n    `transform.dlti.query [\\\"A\\\", \\\"B\\\"] at %func` returns 42 as a param and\\n    `transform.dlti.query [\\\"A\\\"] at %func` returns the `#dlti.map` attribute\\n    containing just the key \\\"B\\\" and its value. Using `[\\\"B\\\"]` or `[\\\"A\\\",\\\"C\\\"]` as\\n    `keys` will yield an error.\\n\\n    #### Return modes\\n\\n    When successful, the result, `associated_attr`, associates one attribute as\\n    a param for each op in `target`'s payload.\\n\\n    If the lookup fails - as no DLTI attributes/interfaces are found or entries\\n    with the right names are missing - a silenceable failure is returned.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"associated_attr\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keys\", \"type\": \"ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$keys `at` $target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.foreach\",\n    \"summary\": \"Executes the body for each element of the payload\",\n    \"description\": \"Execute the op's body - its single region block - exactly once per\\n    element of the payload associated to a target handle. The body's\\n    transformations are applied in order of appearance until reaching the\\n    (implicit) YieldOp terminator.\\n\\n    Each iteration gets executed by co-indexing the payloads of the arguments\\n    and mapping the body's arguments to these tuples, as though iterating over\\n    the zipped together `targets`. As such, in each iteration, the size of the\\n    payload of each of the body's block arguments is exactly one. The attribute\\n    `zip_shortest` can be used if the targets vary in their number of payloads;\\n    this will limit the iterations to only the number of payloads found in the\\n    shortest target.\\n\\n    This op always reads the target handles. Furthermore, it consumes a handle\\n    if there is a transform op in the body that consumes the corresponding\\n    block argument. Handles can point to ops, values, or parameters.\\n\\n    #### Return Modes\\n\\n    This op produces as many result handles as the body's terminating YieldOp\\n    has operands. For each result, the payloads of the corresponding YieldOp\\n    operand are merged and mapped to the same resulting handle.\\n\\n    If the target handles do not associate payloads of the same size, a\\n    silencable failure will be generated.\\n\\n    During application, if any transformation in the sequence fails, the entire\\n    sequence fails immediately with the same failure, leaving the payload IR in\\n    a potentially invalid state, i.e., this operation offers no transformation\\n    rollback capabilities.\",\n    \"operands\": [\n      { \"name\": \"targets\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"with_zip_shortest\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"transform\",\n    \"assemblyFormat\": \"$targets oilist(`with_zip_shortest` $with_zip_shortest) `:` type($targets) (`->` type($results)^)? $body attr-dict\"\n  },\n  {\n    \"name\": \"transform.foreach_match\",\n    \"summary\": \"Applies named sequences when a named matcher succeeds\",\n    \"description\": \"Given a pair of co-indexed lists of transform dialect symbols (such as\\n    `transform.named_sequence`), walks the payload IR associated with the root\\n    handle and interprets the symbols as matcher/action pairs by applying the\\n    body of the corresponding symbol definition. The symbol from the first list\\n    is the matcher part: if it results in a silenceable error, the error is\\n    silenced and the next matcher is attempted. Definite failures from any\\n    matcher stop the application immediately and are propagated unconditionally.\\n    If none of the matchers succeeds, the next payload operation in walk order\\n    (post-order at the moment of writing, double check `Operation::walk`) is\\n    matched. If a matcher succeeds, the co-indexed action symbol is applied and\\n    the following matchers are not applied to the same payload operation. If the\\n    action succeeds, the next payload operation in walk order is matched. If it\\n    fails, both silenceable and definite errors are propagated as the result of\\n    this op; propagation of silenceable errors is postponed until the end of the\\n    walk.\\n\\n    The matcher symbol must take at least one operand of a type that implements\\n    the same transform dialect interface as the `root` operand (a check is\\n    performed at application time to see if the associated payload satisfies the\\n    constraints of the actual type), and may take additional operands with a\\n    similar type requirement. It must not consume operands as multiple matchers\\n    may be applied. The matcher may produce any number of results. The action\\n    symbol paired with the matcher must take the same number of arguments as the\\n    matcher has results, and these arguments must implement the same transform\\n    dialect interfaces, but not necessarily have the exact same type (again, a\\n    check is performed at application time to see if the associated payload\\n    satisfies the constraints of actual types on both sides).\\n\\n    The action symbol may have results that are accumulated from all actions and\\n    returned from the `foreach_match` operation on success. Unless the\\n    `flatten_results` attribute is present, each action result must be\\n    associated with exactly one payload entity. The actions are expected to only\\n    modify payload operations nested in the `root` payload operations associated\\n    with the operand of this transform operation. Furthermore, the actions may\\n    not modify operations outside of the currently matched payload operation,\\n    e.g., they may not modify sibling or parent operations. If such behavior is\\n    desired, the parent must be matched first and the nested operations obtained\\n    by traversing the IR from the parent. This is due to the matching being\\n    performed as a post-order IR walk.\\n\\n    This operation consumes the operand and produces a new handle associated\\n    with the same payload. This is necessary to trigger invalidation of handles\\n    to any of the payload operations nested in the payload operations associated\\n    with the operand, as those are likely to be modified by actions.\\n\\n    By default, the root payload operation associated with the operand is not\\n    matched. This is to support the conservative case where applied actions may\\n    invalidate the root payload operation. If the optional `restrict_root`\\n    attribute is set, the root operand is guaranteed to not be invalidated by any\\n    of the applied actions. In such cases, the root payload operation is also\\n    matched. This is useful because matching the root payload operation is a\\n    common idiom, when e.g. matching a func.func directly and operations nested\\n    under it.\\n\\n    The operation succeeds if none of the matchers produced a definite failure\\n    during application and if all of the applied actions produced success. Note\\n    that it also succeeds if all the matchers failed on all payload operations,\\n    i.e. failure to apply is not an error. The operation produces a silenceable\\n    failure if any applied action produced a silenceable failure. In this case,\\n    the resulting handle is associated with an empty payload. The operation\\n    produces a definite failure if any of the applied matchers or actions\\n    produced a definite failure.\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"forwarded_inputs\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"updated\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"forwarded_outputs\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"restrict_root\", \"type\": \"UnitAttr\" },\n      { \"name\": \"flatten_results\", \"type\": \"UnitAttr\" },\n      { \"name\": \"matchers\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" },\n      { \"name\": \"actions\", \"type\": \"TypedArrayAttrBase<SymbolRefAttr>\" }\n    ],\n    \"assemblyFormat\": \"oilist( `restrict_root` $restrict_root\\n          | `flatten_results` $flatten_results\\n          )\\n    `in`\\n    $root (`,` $forwarded_inputs^)?\\n    custom<ForeachMatchSymbols>($matchers, $actions)\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.func.cast_and_call\",\n    \"summary\": \"Casts values to the signature of a function and replaces them with a call\",\n    \"description\": \"This transform takes value handles to a set of `inputs` and `outputs` and\\n    attempts to cast them to the function signature of the attached function\\n    op, then builds a call to the function and replaces the users of the\\n    outputs. It is the responsibility of the user to ensure that the slice of\\n    the program replaced by this operation makes sense, i.e. there is no\\n    verification that the inputs to this operation have any relation to the\\n    outputs outside of basic dominance requirements needed for the call.\\n\\n    The casting materialization functions are specified in the graph region of\\n    this op. They must implement the `TypeConverterBuilderOpInterface`. The\\n    order of ops within the region is irrelevant.\\n\\n    The target function can be specified by a symbol name or by a handle to the\\n    operation.\\n\\n    This transform only reads the operand handles and only replaces the users of\\n    the outputs with the results of the call. No handles are consumed and no\\n    operations are removed. Users are expected to run cleanup separately if\\n    desired.\\n\\n    Warning: The replacement of the uses of the outputs could invalidate certain\\n    restricted value handle types (e.g. `transform.block_arg` if it existed, by\\n    replacing the use with something not coming from a block argument). The\\n    value will still exist in such cases but wouldn't verify against the type.\\n    See the discussion here for more information:\\n    https://github.com/llvm/llvm-project/pull/78398#discussion_r1455070087\\n\\n    This transform will emit a silenceable failure if:\\n     - The set of outputs isn't unique\\n     - The handle for the insertion point does not include exactly one operation\\n     - The insertion point op does not dominate any of the output users\\n     - The insertion point op is not dominated by any of the inputs\\n     - The function signature does not match the number of inputs/outputs\\n\\n    This transform will emit a definite failure if it fails to resolve the\\n    target function, or if it fails to materialize the conversion casts of\\n    either the inputs to the function argument types, or the call results to\\n    the output types.\",\n    \"operands\": [\n      { \"name\": \"insertion_point\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"inputs\", \"type\": \"Optional<TransformValueHandleTypeInterface>\" },\n      { \"name\": \"outputs\", \"type\": \"Optional<TransformValueHandleTypeInterface>\" },\n      { \"name\": \"function\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"insert_after\", \"type\": \"UnitAttr\" },\n      { \"name\": \"function_name\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"conversions\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"($function_name^)? ($function^)?\\n    ( `(` $inputs^ `)` )?\\n    ( `->` $outputs^ )?\\n    (`after` $insert_after^):(`before`)? $insertion_point\\n    ($conversions^)? attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.func.deduplicate_func_args\",\n    \"description\": \"This transform takes a module and a function name, and deduplicates\\n      the arguments of the function. The function is expected to be defined in\\n      the module.\\n\\n      This transform will emit a silenceable failure if:\\n       - The function with the given name does not exist in the module.\\n       - The function does not have duplicate arguments.\\n       - The function does not have a single call.\",\n    \"operands\": [\n      { \"name\": \"module\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed_module\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"transformed_function\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function_name\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$function_name\\n    `at` $module attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.func.replace_func_signature\",\n    \"description\": \"This transform takes a module and a function name, and replaces the\\n      signature of the function by reordering the arguments and results\\n      according to the interchange arrays. The function is expected to be\\n      defined in the module, and the interchange arrays must match the number\\n      of arguments and results of the function.\\n\\n      The `adjust_func_calls` attribute indicates whether the function calls\\n      should be adjusted to match the new signature. If set to `true`, the\\n      function calls will be adjusted to match the new signature, otherwise\\n      they will not be adjusted.\\n\\n      This transform will emit a silenceable failure if:\\n       - The function with the given name does not exist in the module.\\n       - The interchange arrays do not match the number of arguments/results.\\n       - The interchange arrays contain out of bound indices.\",\n    \"operands\": [\n      { \"name\": \"module\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed_module\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"transformed_function\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"function_name\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"args_interchange\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"results_interchange\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"adjust_func_calls\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$function_name\\n    `args_interchange` `=` $args_interchange\\n    `results_interchange` `=` $results_interchange\\n    `at` $module attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_consumers_of_result\",\n    \"summary\": \"Get handle to the consumers of this operation's result number\",\n    \"description\": \"The handle defined by this Transform op corresponds to all operations that\\n    consume the SSA value defined by the `target` and `result_number`\\n    arguments.\\n    This operation applies to a single payload operation, otherwise it produces\\n    a definite failure.\\n    The return handle points to the consuming operations operations, which can\\n    be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"consumers\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_number\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target `[` $result_number `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_defining_op\",\n    \"summary\": \"Get handle to the defining op of a value\",\n    \"description\": \"The handle defined by this Transform op corresponds to the defining op of\\n    the targeted value.\\n\\n    This transform produces a silenceable failure if the targeted value is a\\n    block argument.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_operand\",\n    \"summary\": \"Get a handle to the operand(s) of the targeted op\",\n    \"description\": \"The handle defined by this Transform op corresponds to the operands of the\\n    given `target` operation specified by the given set of positions. There are\\n    three possible modes:\\n\\n     - Position list directly, i.e. `%target[0, 1, 2]`. This will return the\\n       operands at the specified positions.\\n     - Inverted position list, i.e. `%target[except(0, 1, 2)]`. This will return\\n       all operands except those at the given positions.\\n     - All, i.e. `%target[all]`. This will return all operands of the operation.\\n    \\n    This transform produces a silenceable failure if any of the operand indices\\n    exceeds the number of operands in the target. It reads the target handle and\\n    produces the result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"raw_position_list\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"is_inverted\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_all\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target `[`custom<TransformMatchDims>($raw_position_list, $is_inverted, $is_all)`]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_parent_op\",\n    \"summary\": \"Gets handles to the closest parent ops\",\n    \"description\": \"The handle defined by this Transform op corresponds to the parents of the\\n    targeted payload ops (in the same order).\\n\\n    Requirements that parent ops must fulfill can be optionally specified. In\\n    that case for each target op, the closest parent op that fulfills all\\n    requirements, is returned.\\n    - `isolated_from_above`: the parent op must be isolated from above\\n    - `allow_empty_results`: get_parent_op is allowed to return an empty list\\n      and still succeeds. In such a case, if `get_parent_op` fails for any\\n      operation in the list, the entire transform returns an empty handle.\\n    - `op_name`: the parent op must have the specified name\\n    - `nth_parent`: get the n-th parent of that satisfies the above requirements\\n\\n    If `deduplicate` is set, the result handle does not contain any duplicate\\n    ops. For example, given the list\\n    \\\"(childof(A), childof(B), childof(B), childof(A), childof(B))\\\", the\\n    resulting list will be just \\\"(A, B)\\\". Note that no other semantic ordering\\n    is applied, e.g., \\\"B\\\" may itself be a parent of \\\"A\\\". This may have an impact\\n    on the further transformation applied to the handle produced here.\\n\\n    If any of the given Payload IR ops has no such suitable parent, then:\\n      - if `allow_empty_results` is set, the result handle is empty\\n      - otherwise, the transformation produces a silenceable failure.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"parent\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isolated_from_above\", \"type\": \"UnitAttr\" },\n      { \"name\": \"allow_empty_results\", \"type\": \"UnitAttr\" },\n      { \"name\": \"op_name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"deduplicate\", \"type\": \"UnitAttr\" },\n      { \"name\": \"nth_parent\", \"type\": \"DefaultValuedAttr<ConfinedAttr<I64Attr, [ IntPositive ]>, 1>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_producer_of_operand\",\n    \"summary\": \"Get handle to the producer of this operation's operand number\",\n    \"description\": \"The handle defined by this Transform op corresponds to operation that\\n    produces the SSA value defined by the `target` and `operand_number`\\n    arguments. If the origin of the SSA value is not an operations (i.e. it is\\n    a block argument), the transform produces a silenceable failure.\\n    The return handle points to only the subset of successfully produced\\n    computational operations, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"producer\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operand_number\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target `[` $operand_number `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_result\",\n    \"summary\": \"Get a handle to the result(s) of the targeted op\",\n    \"description\": \"The handle defined by this Transform op correspond to the OpResults of the\\n    given `target` operation. Optionally `result_number` can be specified to\\n    select a specific result.\\n    \\n    This transform fails silently if the targeted operation does not have enough\\n    results. It reads the target handle and produces the result handle.\\n\\n    The handle defined by this Transform op corresponds to the results of the\\n    given `target` operation specified by the given set of positions. There are\\n    three possible modes:\\n\\n     - Position list directly, i.e. `%target[0, 1, 2]`. This will return the\\n       results at the specified positions.\\n     - Inverted position list, i.e. `%target[except(0, 1, 2)]`. This will return\\n       all results except those at the given positions.\\n     - All, i.e. `%target[all]`. This will return all results of the operation.\\n    \\n    This transform produces a silenceable failure if any of the result indices\\n    exceeds the number of results returned by the target. It reads the target\\n    handle and produces the result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"raw_position_list\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"is_inverted\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_all\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target `[`custom<TransformMatchDims>($raw_position_list, $is_inverted, $is_all)`]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.get_type\",\n    \"summary\": \"Get a parameter containing the type of the given value\",\n    \"description\": \"This operation creates a new Transform parameter containing the\\n    type(s) of the value(s) associated with the operand handle.\\n\\n    This transform never fails.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"type_param\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elemental\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`elemental` $elemental^)? $value attr-dict `:`functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.gpu.map_forall_to_blocks\",\n    \"description\": \"Target the gpu_launch op and rewrite the top level `scf.forall`\\n    to distributed gpu.block_id attribute. If `generate_gpu_launch` attribute\\n    is set, then first generates `gpu_launch` and moves the top level\\n    `scf.forall` inside.\\n\\n    The operation searches top level `scf.forall` ops under\\n    `gpu_launch` and maps each such op to GPU blocks. Mapping is\\n    one-to-one and the induction variables of `scf.forall` are\\n    rewritten to gpu.block_id according to the `thread_dim_mapping` attribute.\\n\\n    Dynamic, `scf.forall` trip counts are currently not supported.\\n    Dynamic block dim sizes are currently not supported.\\n\\n    Only **bufferized** scf.forall are currently supported.\\n    Only scf.forall distributed to **at most 3 dimensions** are\\n    currently supported.\\n\\n    The operation alters the block size of the given gpu_launch using the\\n    grid_dims argument.\\n\\n    #### Return modes:\\n\\n    This operation ignores non-gpu_launch ops and drops them in the return.\\n\\n    If any scf.forall with tensors is found, the transform definitely\\n    fails.\\n\\n    If all the `scf.forall` operations contained within the LaunchOp\\n    referred to by the `target` handle lower to GPU properly, the\\n    transform succeeds. Otherwise the transform definitely fails.\\n\\n    The returned handle points to the same LaunchOp operand, consuming it and\\n    producing a new SSA value to satisfy chaining and linearity of the IR\\n    properties.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"grid_dims\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"generate_gpu_launch\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    (`generate_gpu_launch` $generate_gpu_launch^)?\\n    (`grid_dims` `=` $grid_dims^)?\\n    attr-dict\\n    `:` functional-type($target, $result)\"\n  },\n  {\n    \"name\": \"transform.gpu.map_nested_forall_to_threads\",\n    \"description\": \"Target the `gpu.launch op` and rewrite all `scf.forall` nested in it to\\n      distributed `gpu.thread_id` attribute.\\n\\n      The operation searches for `scf.forall` ops nested under `target` and maps\\n      each such op to GPU threads.\\n\\n      `scf.forall` induction variables are rewritten to `gpu.thread_id` according\\n      to the `mapping` attribute.\\n\\n      Different types of mappings attributes are supported:\\n        - the block_dims is a list of integers that specifies the number of\\n          threads in each dimension. This is a mandatory attribute that is used\\n          to constrain the number of threads in each dimension. If an\\n          `scf.forall` op is mapped to fewer threads, predication occurs.\\n        - the warp_dims is a list of integers that specifies the number of\\n          warps in each dimension. This is an optional attribute that is used\\n          to constrain the number of warps in each dimension. When present, this\\n          attribute must be specified in a way that is compatible with the\\n          block_dims attribute. If an `scf.forall` op is mapped to fewer warps,\\n          predication occurs.\\n\\n      Dynamic `scf.forall` trip counts are currently not supported.\\n      Dynamic block dim sizes are currently not supported.\\n\\n      Only **bufferized** `scf.forall` are currently supported.\\n      Only `scf.forall` distributed to **at most 3 dimensions** are\\n      currently supported.\\n\\n      The `sync_after_distribute`attribute controls whether a `gpu.barrier` is\\n      inserted after each scf.forall op. At this time, this is an all or nothing\\n      choice. This will need to be tightened in the future.\\n\\n      The operation alters the block size of the given gpu_launch using the\\n      mandatory block_dims argument.\\n\\n      #### Return modes:\\n\\n      This operation ignores non-`gpu_launch` ops and drops them in the return.\\n\\n      If any scf.forall with tensors is found, the transform definitely\\n      fails.\\n\\n      If all the `scf.forall` operations with gpu.thread mapping contained\\n      within the `LaunchOp` referred to by the `target` handle lower to GPU\\n      properly, the transform succeeds. Otherwise the transform definitely\\n      fails.\\n\\n      scf.forall operations with mappings other than gpu.thread are\\n      ignored.\\n\\n      The returned handle points to the same LaunchOp operand, consuming it and\\n      producing a new SSA value to satisfy chaining and linearity of the IR\\n      properties.\\n\\n      #### Example:\\n\\n      ```\\n      gpu.launch blocks(%bx, %by, %bz) in (%x = %0, %y = %1, %z = %2)\\n                 threads(%tx, %ty, %tz) in (%tx = %3, %ty = %4, %tz = %5) {\\n        scf.forall (%i, %j) in (7, 9) {\\n          ... // body 1\\n        } {mapping = [#gpu.thread<x>, #gpu.thread<y>, #gpu.thread<z>]}\\n        scf.forall (%i) in (12) {\\n          ... // body 2\\n        } {mapping = [#gpu.thread<x>]}\\n        gpu.terminator\\n      }\\n      ```\\n\\n      is translated to:\\n\\n      ```\\n      %bdimX = arith.constant 12 : index\\n      %bdimY = arith.constant 9 : index\\n      gpu.launch blocks(%bx, %by, %bz) in (%x = %0, %y = %1, %z = %2)\\n             threads(%tx, %ty, %tz) in (%tx = %bdimX, %ty = %bdimY, %tz = %5) {\\n        if (threadIdx.x < 9 && threadIdx.y < 7) {\\n          ... // body 1\\n        }\\n        gpu.barrier\\n        if (threadIdx.y < 1) {\\n          ... // body 2\\n        }\\n        gpu.barrier\\n        gpu.terminator\\n      }\\n      ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_dims\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"sync_after_distribute\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"warp_size\", \"type\": \"DefaultValuedAttr<I64Attr, 32>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `block_dims` `=` $block_dims\\n    (`sync_after_distribute` `=` $sync_after_distribute^)?\\n    (`warp_size` `=` $warp_size^)?\\n    attr-dict\\n    `:` functional-type($target, $result)\"\n  },\n  {\n    \"name\": \"transform.include\",\n    \"summary\": \"Includes a named transform sequence\",\n    \"description\": \"The application of this transform operation is equivalent to applying the\\n    operations contained in the named transform sequence with operands being\\n    remapped to block arguments. The behavior of the operation when a\\n    transformation in the included named sequence produces a silenceable error\\n    is controlled by the `failure_propagation_mode` attribute. When set to\\n    `propagate`, the failure of any nested transformation in the sequence\\n    implies immediate failure of the entire sequence with a silenceable error,\\n    and no further transformation is attempted. When set to `suppress`,\\n    silenceable errors in nested operations are ignored and further\\n    transformations are applied. Beware that even silenceable errors may leave\\n    the payload IR in a state unsuitable for further transformations. It is the\\n    responsibility of the user to ensure the following transformations are\\n    robust enough when errors are suppressed. Definite errors are propagated\\n    immediately regardless of the mode. The objects associated with the results\\n    of this operation are the same as those associated with the operands of the\\n    `transform.yield` in the referenced named sequence.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"failure_propagation_mode\", \"type\": \"FailurePropagationMode{propagate|suppress}\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$target `failures` `(` $failure_propagation_mode `)``(` $operands `)` attr-dict `:` functional-type($operands, $results)\"\n  },\n  {\n    \"name\": \"transform.irdl.collect_matching\",\n    \"summary\": \"Finds ops that match the IRDL definition without registering them.\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"matched\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`in` $root `:` functional-type(operands, results) attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.iree.amdgpu_distribute_vectors\",\n    \"description\": \"Run AMDGPU Vector Contraction distribution on the target as the root.\\n\\n    The anchor points are set by using the attribute\\n    \\\"__vector_layout_test_anchor_operand_x\\\" and\\n    \\\"__vector_layout_test_anchor_result_x\\\", where \\\"x\\\" is the operand/result\\n    number.\\n\\n    This op produces amdgpu MFMA ops.\\n\\n    #### Return modes\\n\\n    This transform does not consume the target handle and always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"test_conversion\", \"type\": \"UnitAttr\" },\n      { \"name\": \"workgroup_size\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"subgroup_size\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 64>\" }\n    ],\n    \"assemblyFormat\": \"$target (`test_conversion` $test_conversion^)?\\n      attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.apply_licm\",\n    \"description\": \"Apply loop-independent code motion and single iteration loop promotion.\\n    This transform is applied to all FuncOps within the target. Distinguished\\n    from the upstream `apply_licm` op that only applies to a single loop with\\n    the `iree` prefix.\\n\\n    #### Return modes\\n\\n    This operation does not consume the target handle and does not produce any\\n    handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.iree.bufferize\",\n    \"description\": \"Target the whole hal.executable_variant op and call upstream comprehensive\\n    bufferize with extra IREE hooks.\\n\\n    By default, CPU allocations are emitted. This behavior can be modified by\\n    using the following attributes:\\n      - target_gpu: if set, GPU allocations are emitted.\\n\\n    #### Return modes\\n\\n    This operation calls the upstream one-shot bufferization pass with extra\\n    registered patterns for IREE.\\n\\n    The pass is ran on all the ModuleOp nested under the top-level op on which\\n    the transform dialect interpreter pass is applied.\\n\\n    If any of the pass on any of the ModuleOp fails, the transformation\\n    definitely fails. Otherwise the transformation succeeds.\\n\\n    This transform consumes the target handle and produces a result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_gpu\", \"type\": \"UnitAttr\" },\n      { \"name\": \"test_analysis_only\", \"type\": \"UnitAttr\" },\n      { \"name\": \"print_conflicts\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $target `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.iree.convert_to_multi_mma\",\n    \"description\": \"Converts the target linalg op to a multi_mma operation based on the\\n    given intrinsic kind.\\n\\n    #### Return modes\\n    Emits a definite failure if the target is not a contraction like linalg\\n    op or the conversion to the target mma fails.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"intrinsic_kind\", \"type\": \"IREEGPU_AnyMmaAttr\" }\n    ],\n    \"assemblyFormat\": \"$target `,` `kind` `(` $intrinsic_kind `)` attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.convert_to_online_attention\",\n    \"description\": \"Target iree_linalg_ext.attention ops and decompose them.\\n    This transform consumes the target handle and produces a result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.copy_tensor_operand\",\n    \"summary\": \"Create a linalg copy of a specified value.\",\n    \"description\": \"Inserts a copy of the specified operand of the target operation.\\n\\n    #### Return modes\\n    Returns a handle to the new copy.\\n\\n    It does not consume the target handle and emits a definite failure if the\\n    operand index is out of range or if the operand is not a tensor type.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operand_index\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target `[` $operand_index `]` attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.create_async_groups\",\n    \"description\": \"Convert copies to shared memory to async copies. This creates groups\\n    of consecutive copies and emit wait operation right after.\\n    The input operation is a `func.func`.\\n\\n    `use_mma_sync` specifies whether `bypassL1` attributes should be added to the\\n    async copies.\\n\\n    #### Return modes\\n    This op returns a handle to the transformed function, even if nothing\\n    changed.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_mma_sync\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.create_matmul_mfma_tile_sizes\",\n    \"description\": \"Create param of tile sizes based on the matmul sizes.\\n    This operation won't succeed if the matmul shape size is not 2.\\n    Now it only covers the shape of [256*, 128*], [128, 64*], [8192, 320].\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"workgroup_tile_sizes\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"problem_specific_sizes\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.decompose_aggregate_op\",\n    \"description\": \"Target iree_linalg_ext.attention ops and decompose them.\\n    This transform consumes the target handle and produces a result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile_size\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.distribute_inner_tiled\",\n    \"description\": \"Distributes the target inner_tiled op to lanes.\\n\\n    #### Return modes\\n    Emits a definite failure if the target is not an iree_codegen.inner_tiled op or\\n    if it fails to distribute.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.eliminate_empty_tensors\",\n    \"description\": \"This is a pre-processing pass for iree.bufferize. It tries to remove\\n    tensor.empty ops by replacing them with suitable destination tensors,\\n    which can reduce the number of allocations when bufferizing.\\n\\n    This transform is not part of iree.bufferize because additional\\n    canonicalization are sometimes possible after eliminate_empty_tensors but\\n    before iree.bufferize.\\n\\n    #### Return modes\\n\\n    This transform does not consume the target handle and always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $target `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.iree.eliminate_gpu_barriers\",\n    \"description\": \"Removes unnecessary GPU barriers from the function. If a barrier does not\\n    enforce any conflicting pair of memory effects, including a pair that is\\n    enforced by another barrier, it is unnecessary and can be removed.\\n\\n    #### Return modes\\n\\n    Consumes the operand handle and produces a new handle to the function after\\n    rewriting.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.emit_remark\",\n    \"description\": \"Emits a diagnostic remark with the given message located at payload ops\\n    associated with the given handle. This can be used, e.g., for debugging.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$message `at` $handle attr-dict `:` type($handle)\"\n  },\n  {\n    \"name\": \"transform.iree.flatten_forall_mapping\",\n    \"description\": \"Flattens the thread mapping of an `scf.forall` op.\\n\\n    #### Return modes\\n    Emits a definite failure if the target is not an scf.forall op or if\\n    the mapping type is not `gpu.thread` or `gpu.warp` with linear dims in\\n    descending order.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.forall_to_flow\",\n    \"description\": \"Rewrite an scf.forall to Flow::DispatchWorkgroups.\\n\\n    #### Return modes\\n\\n    This operation ignores non-scf::ForeachThread ops and drops them in the\\n    return.\\n\\n    If any rewrite fails, the transform definitely fails.\\n\\n    If all the operations referred to by the `target` operand generalize\\n    properly, the transform succeeds. Otherwise the transform silently fails.\\n\\n    The return handle points to only the subset of successfully produced\\n    equivalent flow::DispatchWorkgroups operations, which can be empty.\\n\\n    This operation consumes the `target` handle and produces the `transformed`\\n    handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.forall_to_lanes\",\n    \"description\": \"Collect all of the scf.forall ops in the target that are distributed to\\n    lanes.\\n\\n    Only scf.forall distributed to exactly a single lane id are currently\\n    supported.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.iree.forall_to_workgroup\",\n    \"description\": \"Target the whole hal.executable_variant op and rewrite the unique topLevel\\n    scf.forall to distributed workgroup_id and workgroup_count.\\n\\n    The mapping of threads to workgroup_id is currently one-to-one and in order.\\n    Only **bufferized** scf.forall are currently supported.\\n    Only scf.forall distributed to **at most 3 dimensions** are currently\\n    supported.\\n\\n    Return modes:\\n    =============\\n    This operation ignores non-Func ops and drops them in the return.\\n\\n    If no unique scf.forall topLevel operation is found, then the\\n    transform definitely fails.\\n    If the unique topLevel scf.forall has results (i.e. tensors), then\\n    the transform definitely fails.\\n\\n    If the unique topLevel scf.forall maps to a dynamic number of\\n    threads, then the transform definitely fails. This is a temporary\\n    limitation until the backward slice computing scf.forall.num_threads\\n    can be extracted into the hal::executable_export workgroup_count region.\\n    This region may require arbitrary computations and cannot magically match\\n    what the `stream.cmd.dispatch` has already imposed on us at a distance.\\n    For now we must specify the number of values properly when applying the\\n    topLevel tile_using_forall.\\n\\n    If the unique topLevel scf.forall operation contained within the\\n    FuncOp referred to by the `target` transform handle lowers to workgroup\\n    properly, the transform succeeds.\\n\\n    Otherwise the transform definitely fails.\\n\\n    This transform does not consume its input handle and produces no result.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.iree.fuse_collapse_shape_into_forall\",\n    \"description\": \"Fuses a consumer tensor.collapse_shape op into a producer scf.forall op.\\n    The users of the block argument for the corresponding forall output operand\\n    should be only a tensor.parallel_insert_slice op, and tensor.extract_slice\\n    ops that extract an equivalent subset. After the fusion, the output of the\\n    forall will be collapsed, and all users of this block arg will also be\\n    collapsed. Additional tensor.expand_shape ops will be inserted after any\\n    tensor.extract_slice users inside the forall so that types match. Similarly,\\n    a tensor.collapse_shape will be inserted before the\\n    tensor.parallel_insert_slice.\\n\\n    #### Return modes\\n    Emits a definite failure if either the producer is not an scf.forall op or\\n    if the consumer is not a tensor.collapse_shape op.\",\n    \"operands\": [\n      { \"name\": \"producer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"consumer\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$consumer `into` $producer attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.fuse_consumer\",\n    \"description\": \"Fuses the consumer of the operation pointed to by the target handle\\n    using the options provided as attributes.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"consumer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"fused_consumer\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target `in` `(` $loops `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.fuse_extract_slice_into_forall\",\n    \"description\": \"Fuses a consumer tensor.extract_slice op into a producer scf.forall op.\\n    This transform is supported if the extract_slice op has all zero offsets,\\n    and if all the offsets, sizes, and strides dominate the scf.forall op.\\n    After the transformation, the forall loop output argument corresponding\\n    to the sliced result will be replaced with a slice of it with the same\\n    offsets, sizes, and strides as the original extract_slice. The source of\\n    the corresponding tensor.parallel_insert_slice of the scf.forall will also\\n    become a slice of the original parallel insert source, clamped to fit within\\n    the new sliced result tensor.\\n\\n    #### Return modes\\n    Emits a definite failure if either the producer is not an scf.forall op or\\n    if the consumer is not a tensor.extract_slice op.\",\n    \"operands\": [\n      { \"name\": \"producer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"consumer\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$consumer `into` $producer attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.fuse_forall\",\n    \"description\": \"Fuses a producer-consumer pair of scf.forall ops that share the same\\n    iterator mapping types and trip counts. An allocation is created to\\n    bridge the `parallel.insert_slice` of the producer with the per-thread\\n    `extract_slice` of the consumer. If specified, uses |address_space| for\\n    the intermediate allocation.\\n\\n    The mapping attributes of both the producer and consumer `scf.forall` ops\\n    must be in a relative descending order, for example:\\n     [#gpu.thread<z>, #gpu.thread<y>, #gpu.thread<x>]\\n    or\\n     [#gpu.thread<linear_dim_1>, #gpu.thread<linear_dim_0>]\\n\\n    NOTE: This pattern implicitly REQUIRES that the resulting scf.forall\\n    is capable of synchronizing all threads at the point of fusion (i.e.\\n    inserting a barrier). This invalidates certain kinds of lowerings of\\n    scf.forall ops such as lowering it to loops.\\n\\n    #### Return modes\\n    Emits a definite failure if either the producer or consumer are not\\n    scf.forall ops.\",\n    \"operands\": [\n      { \"name\": \"producer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"consumer\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"address_space\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"$producer `into` $consumer attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.gpu_distribute_shared_memory_copy\",\n    \"summary\": \"Distribute shared memory copies.\",\n    \"description\": \"Find copies to/from shared memory and distribute the copies based on the\\n    workgroup size.\\n\\n    #### Return modes\\n    This operation applies to the entire function and does not consume the\\n    target handle. It always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.hoist_static_alloc\",\n    \"summary\": \"Hoist static allocations.\",\n    \"description\": \"Find static allocations and hoist them to the top level.\\n\\n    #### Return modes\\n    This transform applies static alloc hoisting the whole region of the operand.\\n\\n    It does not consume the target handle and always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.map_nested_forall_to_gpu_threads\",\n    \"description\": \"Target the whole hal.executable_variant op and rewrite all scf.forall\\n    to distributed gpu.thread_id and translation_info attribute.\\n\\n    This op will handle all the scf.forall using gpu.thread or gpu.warp\\n    mapping.\\n\\n    The mapping of threads to gpu.thread_id is currently one-to-one and in order.\\n    Only **bufferized** scf.forall are currently supported.\\n    Only scf.forall distributed to **at most 3 dimensions** are currently\\n    supported.\\n\\n    Multiple scf.forall are supported per function in which case, the\\n    max of all the threads is computed and taken for the global gpu.thread_id.\\n    If necessary, scf.forall that do not use the whole thread range\\n    result in predicated computations.\\n\\n    Barriers are inserted after each scf.forall op\\n    if `sync_after_distribution` is true.\\n\\n    Return modes:\\n    =============\\n    This operation ignores non-Func ops and drops them in the return.\\n\\n    If any scf.forall with tensors is found, the transform definitely\\n    fails.\\n\\n    If all the scf.forall operations contained within the FuncOp\\n    referred to by the `target` operand lower to GPU properly, the\\n    transform succeeds. Otherwise the transform definitely fails.\\n\\n    The returned handle points to the same FuncOp operand, consuming it and\\n    producing a new SSA value to satisfy chaining and linearity of the IR\\n    properties.\\n\\n    Example:\\n    ========\\n\\n    ```\\n    hal.executable {\\n      hal.executable.variant {\\n        hal.executable.export {\\n          func @foo() {\\n            scf.forall (%i, %j) in (7, 9) {\\n              ... // body 1\\n            }\\n            scf.forall (%i) in (12) {\\n              ... // body 2\\n            }\\n          }\\n    ```\\n\\n    is translated to:\\n\\n    ```\\n    hal.executable {\\n      hal.executable.variant {\\n        hal.executable.export ... workgroup_size = [12 : index, 9 : index, 1 : index] {\\n          func @foo() {\\n            if (threadIdx.x < 7) {\\n              ... // body 1\\n            }\\n            if (threadIdx.y < 1) {\\n              ... // body 2\\n            }\\n          }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"workgroup_dims\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"subgroup_size\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 32>\" },\n      { \"name\": \"sync_after_distribution\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, true>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `workgroup_dims` `=` $workgroup_dims\\n    (`subgroup_size` `=` $subgroup_size^)?\\n    (`sync_after_distribution` `=` $sync_after_distribution^)?\\n    attr-dict\\n    `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.iree.match_callback\",\n    \"description\": \"Performs payload IR matching using a C++ callback registered beforehand.\\n    The callback is identified by name and is passed the current transform\\n    state and the list of handle operands, along with information necessary\\n    for error propagation. See `register_match_callbacks` for the description\\n    of the callback contract.\\n\\n    If `failure_propagation_mode` is set to `suppress`, any silenceable errors\\n    in the callback (typically, \\\"failure to match\\\") will be ignored and the\\n    resulting handles will be associated with empty lists of payload\\n    operations. Otherwise, silenceable failures are propagated.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callback_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"failure_propagation_mode\", \"type\": \"FailurePropagationMode{propagate|suppress}\" }\n    ],\n    \"assemblyFormat\": \"`failures` `(` $failure_propagation_mode `)` $callback_name `(` $inputs `)` attr-dict `:` functional-type($inputs, $outputs)\"\n  },\n  {\n    \"name\": \"transform.iree.match.attention\",\n    \"summary\": \"Check whether the op is an attention operation.\",\n    \"description\": \"Matches operations from the IREELinalgExt dialect that implement\\n    attention: iree_linalg_ext.attention.\\n\\n    ### Example\\n\\n    ```mlir\\n    #map_query = affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d2, d4)>\\n    #map_key = affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d5, d4)>\\n    #map_value = affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d3, d5)>\\n    #map_scale = affine_map<(d0, d1, d2, d3, d4, d5) -> ()>\\n    #map_output = affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d2, d3)>\\n\\n    %batch_dims, %m_dims, %n_dims, %k1_dims, %k2_dims =\\n      transform.iree.match.attention %attn_op,\\n        query_type = f32, key_type = f32, value_type = f32, output_type = f32,\\n        indexing_maps = [#map_query, #map_key, #map_value, #map_scale, #map_output] :\\n        !transform.any_op -> !transform.param<i64>\\n    ```\\n\\n    This succeeds when `%attn_op` is an attention operation with f32 element\\n    types for query, key, value, and output tensors, and matches the specified\\n    indexing maps pattern.\\n\\n    #### Return modes\\n\\n    Succeeds if the operation is an attention operation, and\\n    produces a silenceable failure otherwise.\\n\\n    #### Results\\n\\n    Returns arrays of dimension sizes extracted from the iteration domain:\\n    - batch_dims: Array of batch dimension sizes.\\n    - m_dims: Array of query sequence length dimension sizes.\\n    - n_dims: Array of number of heads dimension sizes.\\n    - k1_dims: Array of key/value sequence length dimension sizes.\\n    - k2_dims: Array of key embedding dimension sizes.\\n\\n    The exact interpretation depends on the indexing maps of the attention op.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"batch_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"m_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"n_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"k1_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"k2_dims\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"query_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"key_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"value_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"output_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"indexing_maps\", \"type\": \"TypedArrayAttrBase<AffineMapAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['batch_dims', 'm_dims', 'n_dims', 'k1_dims', 'k2_dims']>\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle\\n    `,` `query_type` `=` $query_type\\n    `,` `key_type` `=` $key_type\\n    `,` `value_type` `=` $value_type\\n    `,` `output_type` `=` $output_type\\n    `,` `indexing_maps` `=` $indexing_maps\\n    attr-dict `:` type($operand_handle) `->` type($batch_dims)\"\n  },\n  {\n    \"name\": \"transform.iree.match.cast_compatible_dag_from_root\",\n    \"summary\": \"Checks if the body of the target op matches an operation dag starting\\n      at the given root.\",\n    \"description\": \"Checks whether the given root op matches an operation dag specified in the\\n    body of this op. Enforces cast compatibility between types rather than a\\n    strict equality, similar to `iree.match.cast_compatible_type`.\\n\\n    Note: This operation is experimental and subject to change. General subgraph\\n    matching is difficult and can spawn various DSLs and a slew of transforms.\\n    This op tries to keep it relatively simple an inflexible, reflecting the\\n    expected use case of splicing in hand written kernels that can be equally\\n    inflexible.\\n\\n    #### Return modes\\n\\n    Succeeds if the root operation matches the dag given by this op, and\\n    produces a silenceable failure otherwise. Produces a definite failure\\n    if the operand is not associated with a single payload value.\\n\\n    On success, this operation produces a handle to the inputs and outputs\\n    of the operation dag based on the outputs of the root op and the block\\n    arguments of this operations body.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"inputs\", \"type\": \"TransformValueHandleTypeInterface\" },\n      { \"name\": \"outputs\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict-with-keyword regions `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.match.cast_compatible_type\",\n    \"summary\": \"Checks if the payload value is cast compatible with a target type.\",\n    \"description\": \"Checks whether the given value is cast-compatible with the given target\\n    type attribute.\\n\\n    Currently this operation only allows casting of tensor types. Other types\\n    must match exactly.\\n\\n    #### Return modes\\n\\n    Succeeds if the value's type is compatible with the target type, and\\n    produces a silenceable failure otherwise. Produces a definite failure\\n    if the operand is not associated with a single payload value.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_type\", \"type\": \"TypeAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `=` $target_type attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.iree.match.contraction\",\n    \"summary\": \"Check whether the op is a contraction operation.\",\n    \"description\": \"Matches operations that implement the ContractionOpInterface.\\n    This includes operations like linalg.matmul, linalg.batch_matmul, etc.\\n\\n    Optionally matches specific indexing maps patterns.\\n\\n    ### Example\\n\\n    ```mlir\\n    #map_lhs = affine_map<(d0, d1, d2) -> (d0, d2)>\\n    #map_rhs = affine_map<(d0, d1, d2) -> (d1, d2)>\\n    #map_output = affine_map<(d0, d1, d2) -> (d0, d1)>\\n\\n    %batch_dims, %m_dims, %n_dims, %k_dims =\\n      transform.iree.match.contraction %matmul_op,\\n        lhs_type = f32, rhs_type = f32, output_type = f32,\\n        indexing_maps = [#map_lhs, #map_rhs, #map_output] :\\n        !transform.any_op -> !transform.param<i64>\\n    ```\\n\\n    This succeeds when `%matmul_op` is a contraction operation with f32 input\\n    types and f32 output type, and matches the specified indexing maps pattern.\\n\\n    #### Return modes\\n\\n    Succeeds if the operation is a contraction operation, and\\n    produces a silenceable failure otherwise.\\n\\n    #### Results\\n\\n    Returns arrays of dimension sizes for each contraction dimension:\\n    - batch_dims: Array of batch dimension sizes.\\n    - m_dims: Array of M dimension sizes.\\n    - n_dims: Array of N dimension sizes.\\n    - k_dims: Array of K dimension sizes.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"batch_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"m_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"n_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"k_dims\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"rhs_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"output_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"indexing_maps\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AffineMapAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['batch_dims', 'm_dims', 'n_dims', 'k_dims']>\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle\\n    `,` `lhs_type` `=` $lhs_type\\n    `,` `rhs_type` `=` $rhs_type\\n    `,` `output_type` `=` $output_type\\n    (`,` `indexing_maps` `=` $indexing_maps^)?\\n    attr-dict `:` type($operand_handle) `->` type($batch_dims)\"\n  },\n  {\n    \"name\": \"transform.iree.match.convolution\",\n    \"summary\": \"Check whether the op is a convolution operation.\",\n    \"description\": \"Matches operations that implement the ConvolutionOpInterface.\\n    This includes operations like linalg.conv_2d_nhwc_hwcf,\\n    linalg.conv_2d_nchw_fchw, linalg.depthwise_conv_2d_nhwc_hwc, etc.\\n\\n    Optionally matches specific indexing maps patterns.\\n\\n    ### Example\\n\\n    ```mlir\\n    #map_input = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d0, d1 + d4, d2 + d5, d6)>\\n    #map_filter = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d4, d5, d6, d3)>\\n    #map_output = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d0, d1, d2, d3)>\\n\\n    %batch_dims, %output_image_dims, %output_channel_dims, %filter_dims,\\n    %input_channel_dims, %depth_dims, %strides, %dilations =\\n      transform.iree.match.convolution %conv_op,\\n        lhs_type = f32, rhs_type = f32, output_type = f32,\\n        indexing_maps = [#map_input, #map_filter, #map_output] :\\n        !transform.any_op -> !transform.param<i64>\\n    ```\\n\\n    This succeeds when `%conv_op` is a convolution operation with f32 element\\n    types for input, filter, and output tensors.\\n\\n    #### Return modes\\n\\n    Succeeds if the operation is a convolution operation, and\\n    produces a silenceable failure otherwise.\\n\\n    #### Results\\n\\n    Returns arrays of dimension sizes for each convolution dimension:\\n    - batch_dims: Array of batch dimension sizes.\\n    - output_image_dims: Array of output spatial dimension sizes.\\n    - output_channel_dims: Array of output channel dimension sizes.\\n    - filter_dims: Array of filter spatial dimension sizes.\\n    - input_channel_dims: Array of input channel dimension sizes.\\n    - depth_dims: Array of depth dimension sizes (for depthwise convolutions).\\n    - strides: Array of stride values.\\n    - dilations: Array of dilation values.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"batch_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"output_image_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"output_channel_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"filter_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"input_channel_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"depth_dims\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"strides\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"dilations\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"rhs_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"output_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"indexing_maps\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AffineMapAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['batch_dims', 'output_image_dims', 'output_channel_dims', 'filter_dims', 'input_channel_dims', 'depth_dims', 'strides', 'dilations']>\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle\\n    `,` `lhs_type` `=` $lhs_type\\n    `,` `rhs_type` `=` $rhs_type\\n    `,` `output_type` `=` $output_type\\n    (`,` `indexing_maps` `=` $indexing_maps^)?\\n    attr-dict `:` type($operand_handle) `->` type($batch_dims)\"\n  },\n  {\n    \"name\": \"transform.iree.match.dim_bounds\",\n    \"summary\": \"Checks whether the size of a dim is within given bounds.\",\n    \"description\": \"Checks whether a dim is within a specified lower and upper bound.\\n\\n    #### Return modes\\n\\n    Succeeds if the value's type is compatible with the target type, and\\n    produces a silenceable failure otherwise. Produces a definite failure\\n    if the operand is not associated with a single payload value.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"lower_bound\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"upper_bound\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `[` $dim `]` `,` (`umin` `=` $lower_bound^):(`none`)?\\n    `,` (`umax` `=` $upper_bound^):(`none`)?  attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.iree.match.dim_is_multiple_of\",\n    \"summary\": \"Checks the static size of a dim is divisible by a given value.\",\n    \"description\": \"Checks whether the given dimension given shaped value is a multiple of the\\n    given size.\\n\\n    #### Return modes\\n\\n    Succeeds if the value's type is compatible with the target type, and\\n    produces a silenceable failure otherwise. Produces a definite failure\\n    if the operand is not associated with a single payload value.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"size\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `[` $dim `]` `,` $size attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.iree.match.dims_equal\",\n    \"summary\": \"Check whether transform parameters match expected size values exactly.\",\n    \"description\": \"Matches dimension sizes against expected values.\\n    Each position in the dimension sizes array must match the corresponding\\n    expected value exactly.\\n\\n    ### Example\\n\\n    ```mlir\\n    transform.iree.match.size_equals %m, [512, 256] : !transform.param<i64>\\n    ```\\n\\n    This succeeds when `%m` has exactly two dimensions, 512 and 256.\\n\\n    #### Return modes\\n\\n    Succeeds if all parameters match their corresponding expected values, and\\n    produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"dimension_sizes\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"expected_values\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$dimension_sizes `,` $expected_values\\n    attr-dict `:` type($dimension_sizes)\"\n  },\n  {\n    \"name\": \"transform.iree.match.has_no_lowering_config\",\n    \"summary\": \"Checks that the payload op does not carry a lowering config or compilation info.\",\n    \"description\": \"Verifies that the payload does not have a \\\"compilation_info\\\" or\\n    \\\"lowering_config\\\" attribute. This is a very common check needed for external\\n    matchers to avoid overwriting already configured ops.\\n\\n    #### Return modes\\n\\n    Succeeds if the payload lacks a configuration. Produces a silenceable\\n    failure otherwise. Produces a definite failure if the operand is not\\n    associated with a single payload op.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.iree.match.regions\",\n    \"summary\": \"Checks if the body of the target op matches the body of the single contained op.\",\n    \"description\": \"Does a structural comparison of the regions of the single op contained\\n    within the region of this op against the regions of the target operation.\\n\\n    #### Return modes\\n\\n    Succeeds if the operation body satisfies the specified criteria, produces a\\n    silenceable failure otherwise. Produces a definite failure if the operand is\\n    not associated with a single payload op.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` type($operand_handle) regions\"\n  },\n  {\n    \"name\": \"transform.iree.pack_shared_memory_alloc\",\n    \"summary\": \"Pack shared memory allocation to reduce memory usage.\",\n    \"description\": \"Looks for allocs in shared memory space with overlapping liveness and\\n    groups them, then packs all the allocations in each group into one i8\\n    alloc. Also adds barriers to make sure we are done writing/reading\\n    from the previous alias group before starting a new one.\\n\\n    #### Return modes\\n\\n    It does not consume the target handle and always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.pipeline_shared_memory_copies\",\n    \"description\": \"This applies software pipelining to a given scf.for loop. The pipelining\\n    strategy will look for a copy to shared memory and pipeline it to overlap\\n    it with the rest of the loop.\\n    It is user responsibility to ensure that there are no dependency between\\n    `depth` iterations of the loop by using multi-buffering.\\n\\n    `depth` will indicate how many stages the software pipeline should have.\\n    `peel_epilogue` allows to force the epilogue to be peeled out instead of\\n    potentially using predicated operations for the epilogue phase.\\n\\n    #### Return modes\\n    This transform consumes the scf.for handle and produces a result handle\\n    which points to a) the new scf.for loop generated (success case) or b) the\\n    existing scf.for loop (failure case).\",\n    \"operands\": [\n      { \"name\": \"for_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depth\", \"type\": \"I64Attr\" },\n      { \"name\": \"peel_epilogue\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_mma_sync\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$for_op\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.populate_workgroup_count_region_using_num_threads_slice\",\n    \"description\": \"Populate the workgroup_count region on the `hal.executable.export` op.\\n\\n    The default dispatch region formation expects that the workgroup count\\n    be computed from within the dispatch by using a program slice. The utility\\n    method `lowerWorkgroupCountFromSliceOp` handles populating the\\n    workgroup count region given the values in the dispatch that represent the\\n    number of workgroups. This transform op calls the underlying function using\\n    the `num_threads` value from the `scf.for_all` op that distributes the work\\n    to different workgroups.\",\n    \"operands\": [\n      { \"name\": \"for_all_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $for_all_op `:` functional-type($for_all_op, results)\"\n  },\n  {\n    \"name\": \"transform.iree.prefetch_shared_memory_copies\",\n    \"description\": \"#### Return modes\\n    This transform consumes the scf.for handle and produces a result handle\\n    which points to a) the new scf.for loop generated (success case) or b) the\\n    existing scf.for loop (failure case).\",\n    \"operands\": [\n      { \"name\": \"for_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$for_op\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.promote_operands\",\n    \"description\": \"This op promotes the specified operands of the provided target handle.\\n\\n    #### Return modes\\n    This op consume its target handle and returns a new handle to its target handle\\n    as well as an allocTensorOp for each of the provided valid indices.\\n\\n    If the promotion of any specified operand fails to occur, the op definitely\\n    fails.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indices\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target $indices attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.reduce_shared_memory_bank_conflicts\",\n    \"summary\": \"Add padding to 'memref.alloc' ops reduce shared memory bank conflicts.\",\n    \"description\": \"The `paddingSizeBits` argument should be picked based on the target\\n    architecture, striking balance between minimizing bank conflicts and keeping\\n    the data aligned. Smaller values (close to the bank bitwidth) achieve the\\n    former, while larger (~= widest load size) the latter. We want to **misalign**\\n    the rows, but not too much. For gfx942, 64 is a good default.\\n\\n    #### Return modes\\n\\n    This transform does not consume the target handle and always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding_size_bits\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 64>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.region_to_workgroups\",\n    \"description\": \"Convert a flow.dispatch.region op into a flow.dispatch.workgroups op.\\n\\n    Region ops can capture any values that are in scope in their body, whereas\\n    workgroup ops are isolated from above and all values must be explicitly\\n    captured via operands.\\n\\n    #### Return modes\\n\\n    This operation consumes the `target` handle and produces the `transformed`\\n    handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.register_match_callbacks\",\n    \"description\": \"Registers named structured op matcher callbacks specific for IREE to use\\n    with `transform.iree.match_callback`. This should be called before first\\n    `match_callback` may be executed following the transform dialect control\\n    flow.\\n\\n    The callbacks must have a unique name and a signature compatible with\\n    `MatchCallbacksRegistry::MatchCallbackFn`, which currently means\\n    `DiagnosedSilenceableFailure(MatchCallbackResult &, Location,\\n     const TransformState &, ValueRange)`. The callback receives a \\\"result\\\",\\n     followed by a location at which errors should be reported, a transform\\n     state at the moment of the _match_ (not registration) and a list of\\n     handle values passed as operands to the `match_callback` operation.\\n     It is expected to populate the \\\"result\\\" object with lists of payload\\n     operations that will be bound to the handles produced by the\\n     `match_callback` operation. The callback may fail, at which point\\n     it should produce a silenceable error. The callback currently is not\\n     allowed to modify the payload IR (though this may be revised in the\\n     future for the purpose of communicating the properties of the IR\\n     captured by the match). Therefore, it should not have a reason to\\n     produce a definite error.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.iree.reorder_transpose\",\n    \"description\": \"Targets the whole func op and finds transpose ops whose source\\n    comes from an elementwise op. For each of those transpose ops,\\n    it moves the transpose before the elementwise op by first\\n    transposing the operands of the elementwise op and then redoing\\n    the elementwise op using the transposed operands. It then\\n    replaces all uses of the original transpose op with the result\\n    of the new elementwise op.\\n\\n    More specifically, given IR that looks like below,\\n      %0 = arith.subf %a, %b : vector<16x8xf16>\\n      %1 = vector.transpose %0 [1, 0] : vector<16x8xf16> to vector<8x16xf16>\\n\\n    It moves the transpose before the elementwise op to produce\\n      %transposed_a = vector.transpose %a [1, 0] : vector<16x8xf16> to vector<8x16xf16>\\n      %transposed_b = vector.transpose %b [1, 0] : vector<16x8xf16> to vector<8x16xf16>\\n      %0 = arith.subf %transposed_a, %transposed_b : vector<8x16xf16>\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.share_forall_operands\",\n    \"description\": \"Target a single scf.forall op and shares all uses of the specified\\n    `share_operands` operand indices.\\n\\n    Sharing can be thought of as the inverse of traditional privatization.\\n    Privatization consists in determining that a part of memory is only accessed\\n    by a single thread to and subsequently slicing out that part into a\\n    thread_private storage that has smaller footprint, better locality and better\\n    alignment properties.\\n    In the case of scf.forall on tensors, tensor values are immutable\\n    and the same tensor value may be passed as `shared_outs` and also captured\\n    for internal uses.\\n    Due to the immutability property, the whole tensor values are private by\\n    construction and result in alloc + copy of the whole tensor on every thread\\n    to maintain the original SSA value after bufferizing.\\n\\n    An analysis similar to privatization is needed to ensure that only a private\\n    slice is needed and that the whole tensor can be shared.\\n    This transformation amounts to injecting the result of such an analysis as\\n    static information in the program.\\n    The transformation checks that the values captured are `tensor.extract_slice`\\n    with a matching `tensor.parallel_insert_slice`, to approximate the lack of\\n    a cross-thread dependence analysis.\\n    However this can still be unsafe wrt parallelism so use carefully!\\n\\n    Sharing consists in rewriting all uses of the operands passed as\\n    `shared_outs` that are also captured within the `scf.forall` region\\n    into the matching `shared_outs` bbarg.\\n\\n    Only those operands whose indices are specified in `share_operands` are\\n    shared. An empty `share_operands` specification considers all operands to\\n    be shared.\\n\\n    #### Return modes\\n\\n    If any of the `share_operands` indices overflow, a definite error is produced.\\n\\n    If a `share_operands` fails a sharing precondition, it is ignored.\\n    In the future, we should emit a notification.\\n\\n    This transform consumes the target handle and produces a result handle to\\n    the modified `scf.forall` op.\",\n    \"operands\": [\n      { \"name\": \"forall_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"share_operands\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$forall_op (`share_operands` `=` $share_operands^ )? attr-dict\\n      `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.synchronize_loop\",\n    \"description\": \"This inserts a gpu.barrier after a given scf.for loop.\\n\\n    #### Return modes\\n    This transform consumes the scf.for handle and produces a result handle\\n    which points to the new scf.for loop generated. It will fail if the loop\\n    cannot be pipelined or if there are no shared memory copies.\",\n    \"operands\": [\n      { \"name\": \"for_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$for_op\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.iree.take_first\",\n    \"description\": \"Given an arbitrary list of handles associated with potentially empty lists\\n    of payload operations, produces two new handles:\\n\\n      - a handle pointing to the same payload operations as the first operand\\n        handle with a non-empty list of payload operations;\\n      - a handle pointing to the concatenated list of payload operations\\n        associated with any other handle.\\n\\n    Note that this does not perform any deduplication.\\n\\n    This operation is useful to select a single target after some potentially\\n    unsuccessful matches.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"first\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"rest\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` functional-type($inputs, results)\"\n  },\n  {\n    \"name\": \"transform.iree.test_gpu_vector_distribution\",\n    \"description\": \"Run GPUVectorDistribution on the target as the root.\\n\\n    The anchor points are set by using the attribute\\n    \\\"__vector_layout_test_anchor_operand_x\\\" and\\n    \\\"__vector_layout_test_anchor_result_x\\\", where \\\"x\\\" is the operand/result\\n    number.\\n\\n    The distribution is done for a single warp using gpu.thread x as the lane\\n    ID. The optional experimental attribute enabled experimental distribution\\n    patterns.\\n\\n    #### Return modes\\n\\n    This transform does not consume the target handle and always return success.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"experimental\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"workgroup_size\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"subgroup_size\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 64>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.iree.vector.to_warp_execute_on_lane_0\",\n    \"description\": \"Given an scf.if target predicated by `if (threadIdx.x == 0)`, rewrite its\\n    body to vector.execute_on_lane_0 running ***on a single warp***.\\n\\n    The warp size is determined by the `warp_size` attribute (it is generally\\n    32 but we do not want to hardcode it).\\n\\n    This rewrite only applies if it can be determined from the IR (i.e. from\\n    the surrounding IREE::HAL::ExecutableExportOp) that the number of threads\\n    along the warp dimension is a multiple of the warp size. The transformation\\n    bails on non-perfect multiples of the warp size that would not properly\\n    distribute.\\n\\n    This is the first of two step towards apply vector distribution to a single\\n    warp.\\n\\n\\n    Return modes:\\n    =============\\n    This operation ignores non-scf::IfOp ops and drops them in the return.\\n\\n    If all the operations referred to by the `target` operand are properly\\n    properly, the transform succeeds. Otherwise the transform silently fails.\\n\\n    If the transform is anchored at a top-level that is not isolated from above,\\n    the transform definitely fails.\\n\\n    If the transform cannot find a proper HAL::ExecutableExportOp with a\\n    well-formed workgroup_size 3-entry attribute such that the threadIdx.x\\n    component is a multiple of warp_size, the transform silently fails.\\n    If the scf::ForOp predicate does not predicate on threadIdx.x == 0, the\\n    transform silently fails.\\n\\n    Otherwise the transformation succeeds and the returned handle points to the\\n    produced vector::WarpExecuteOnThread0Op.\\n\\n\\n    Example:\\n    ========\\n\\n    ```\\n    hal.executable.export public @foo ... { workgroup_size = [64: index, 1: index, 1: index] }\\n    builtin.module {\\n      func.func @foo() {\\n        %c0 = arith.constant 0 : index\\n        %c1 = arith.constant 1 : index\\n        %0 = hal.interface.binding.subspan layout(#pipeline_layout) binding(1) alignment(64) offset(%c0) : memref<128xf32>\\n        %1 = gpu.thread_id  x\\n        %2 = arith.cmpi ult, %1, %c1 : index\\n        scf.if %2 {\\n          %3 = arith.constant dense<1.0> : vector<128xf32>\\n          vector.transfer_write %3, %0[%c0] : vector<128xf32>, memref<128xf32>\\n        }\\n      }\\n    }\\n    ```\\n\\n    rewrites to:\\n\\n    ```\\n    hal.executable.export public @foo ... { workgroup_size = [64: index, 1: index, 1: index] }\\n    builtin.module {\\n      func.func @foo() {\\n        %c0 = arith.constant 0 : index\\n        %c4 = arith.constant 4 : index\\n        %c32 = arith.constant 32 : index\\n        %cst = arith.constant dense<1.000000e+00> : vector<128xf32>\\n        %0 = hal.interface.binding.subspan layout(#pipeline_layout) binding(1) alignment(64) offset(%c0) : memref<128xf32>\\n        %1 = gpu.thread_id  x\\n        %2 = arith.cmpi ult, %1, %c32 : index\\n        // Single-warp guard filters out threads 32-63.\\n        scf.if %2 {\\n          vector.warp_execute_on_lane_0(%1)[32] {\\n            %cst = arith.constant dense<1.000000e+00> : vector<128xf32>\\n            vector.transfer_write %cst, %0[%c0] : vector<128xf32>, memref<128xf32>\\n          }\\n        }\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"warp_size\", \"type\": \"DefaultValuedAttr<I64Attr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, $result)\"\n  },\n  {\n    \"name\": \"transform.iree.vector.vector_to_mma_conversion\",\n    \"description\": \"This converts slices of operations containing vector.contract op into\\n    mma operations, targeting warp level tensorcore operations. If the vector\\n    operations are bigger than the native mma size it will first split up those\\n    vector operations.\\n\\n    Exactly one of use_wmma or use_mma_sync must be specified.\\n\\n    #### Return modes\\n\\n    This transform consumes the target handle and produces a result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_mma_sync\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_wmma\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    attr-dict\\n    `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.iree.vector.warp_distribute\",\n    \"description\": \"Given a vector.warp_execute_on_lane_0, apply the patterns to rewrite into\\n    distributed form with warp synchronization. This produces IR that runs\\n    ***on a single warp***.\\n\\n    IR that cannot be distributed will be predicated by `if (threadIdx.x == 0)`.\\n\\n    This is the second step of two for applying vector distribution to a single\\n    warp.\\n\\n\\n    Return modes:\\n    =============\\n    This operation applies a number of patterns to rewrite vector IR into\\n    distributed warp form. To apply these patterns, this operation must target\\n    an operation that is isolated from above, otherwise the transform definitely\\n    fails.\\n\\n    Patterns sets are applied in the following order:\\n      - applyMultiReductionLoweringPatterns\\n      - applyVectorTransferWriteDistribution\\n      - applyPropagateVectorDistribution\\n      - applyWarpExecuteOnLane0ToScf\\n\\n    If any of the pattern sets fail to apply, the transformation definitely\\n    fails.\\n\\n    Otherwise the transformation is successful and no result is returned.\\n\\n\\n    Example:\\n    ========\\n\\n    ```\\n    hal.executable.export public @foo ... { workgroup_size = [64: index, 1: index, 1: index] }\\n    builtin.module {\\n      func.func @foo() {\\n        %c0 = arith.constant 0 : index\\n        %c4 = arith.constant 4 : index\\n        %c32 = arith.constant 32 : index\\n        %cst = arith.constant dense<1.000000e+00> : vector<128xf32>\\n        %0 = hal.interface.binding.subspan layout(#pipeline_layout) binding(1) alignment(64) offset(%c0) : memref<128xf32>\\n        %1 = gpu.thread_id  x\\n        %2 = arith.cmpi ult, %1, %c32 : index\\n        // Single-warp guard filters out threads 32-63.\\n        scf.if %2 {\\n          vector.warp_execute_on_lane_0(%1)[32] {\\n            %cst = arith.constant dense<1.000000e+00> : vector<128xf32>\\n            vector.transfer_write %cst, %0[%c0] : vector<128xf32>, memref<128xf32>\\n          }\\n      }\\n      }\\n    }\\n    ```\\n\\n    distributes to:\\n\\n    ```\\n    hal.executable.export public @foo ... { workgroup_size = [64: index, 1: index, 1: index] }\\n    builtin.module {\\n      func.func @foo() {\\n        %c0 = arith.constant 0 : index\\n        %c4 = arith.constant 4 : index\\n        %c32 = arith.constant 32 : index\\n        %cst = arith.constant dense<1.000000e+00> : vector<128xf32>\\n        %0 = hal.interface.binding.subspan layout(#pipeline_layout) binding(1) alignment(64) offset(%c0) : memref<128xf32>\\n        %1 = gpu.thread_id  x\\n        %2 = arith.cmpi ult, %1, %c32 : index\\n        // Single-warp guard filters out threads 32-63.\\n        scf.if %2 {\\n          %3 = arith.cmpi eq, %1, %c0 : index\\n          %4 = memref.alloc() : memref<128xf32, 3>\\n          // Single-thread guard runs on thread 0 only.\\n          scf.if %3 {\\n            vector.store %cst, %4[%c0] : memref<128xf32, 3>, vector<128xf32>\\n          }\\n          %5 = arith.muli %1, %c4 : index\\n          %6 = vector.load %4[%5] : memref<128xf32, 3>, vector<4xf32>\\n          %7 = affine.apply #map()[%1]\\n          vector.transfer_write %6, %0[%7] {in_bounds = [true]} : vector<4xf32>, memref<128xf32>\\n        }\\n      }\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    attr-dict\\n    `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.forall_to_kernel\",\n    \"description\": \"Outlines the body of an `scf.forall` operation to a new `func.func` nested\\n    under a `gpu.module` operation. The `scf.forall` operation is replaced by\\n    a `kernel.call` operation that represents \\\"launching\\\" the kernel.\\n\\n    The block arguments for the `scf.forall` body representing the indices of\\n    the processing elements are replaced by `gpu.block_id` operations inserted\\n    at the start of the body block. Up to three indices are replaced by\\n    `gpu.block_id` with the position arguments `x`, `y`, and `z` corresponding\\n    to the first, second, and third block arguments representing procesing\\n    element indices. Having more than three distribution indices is considered a\\n    definite error.\\n\\n    All `shared_outs` parameters and well as used-values-defined-above become\\n    arguments to the created `func.func`. The only exception is scalar and\\n    vector constants, which are inlined into the body.\\n\\n    The result is a `func.func` that represents a thead-block level SPMD\\n    program.\\n\\n    If `reuse_existing_gpu_module` is true, then the kernel function will\\n    be inserted into the first existing `gpu.module` that is found. If\\n    no existing `gpu.module` is found or if `reuse_existing_gpu_module` is\\n    false, then a new `gpu.module` will be created.\\n\\n    If `extra_module_attrs` is provided, then the attributes will be added\\n    to the created `gpu.module` only if `reuse_existing_gpu_module` is true.\\n\\n    #### Example\\n\\n    ```mlir\\n    func.func @main(%arg0: tensor<1024x1024xf32>,\\n                %arg1: tensor<1024x1024xf32>,\\n                %arg2: tensor<1024x1024xf32>) -> tensor<1024x1024xf32> {\\n      %c8 = arith.constant 8 : index\\n      %c0 = arith.constant 0 : index\\n      %0 = scf.forall (%i, %j) in (%c8, %c8) shared_outs(%out = %arg2) -> tensor<1024x1024xf32> {\\n        ... body ...\\n      }\\n      return %0 : tensor<1024x1024xf32>\\n    }\\n    ```\\n\\n    is transformed to\\n\\n    ```mlir\\n    func.func @main(%arg0: tensor<1024x1024xf32>, %arg1: tensor<1024x1024xf32>,\\n                    %arg2: tensor<1024x1024xf32>) -> tensor<1024x1024xf32> {\\n      %c8 = arith.constant 8 : index\\n      %0 = kernel.call @kernels::@main_kernel[%c8, %c8] (%arg0, %arg1) outs(%arg2)\\n        : (tensor<1024x1024xf32>, tensor<1024x1024xf32>) -> tensor<1024x1024xf32>\\n      return %0 : tensor<1024x1024xf32>\\n    }\\n    gpu.module @kernels {\\n      func.func @main_kernel(%arg0: tensor<1024x1024xf32>, %arg1: tensor<1024x1024xf32>,\\n                             %arg2: tensor<1024x1024xf32>) -> tensor<1024x1024xf32> {\\n        %0 = gpu.block_id  x\\n        %1 = gpu.block_id  y\\n        ... body ...\\n      }\\n    }\\n    ```\\n\\n    #### Return modes\\n\\n    If `target` is not a top-level `scf.forall` operation, then it is silently\\n    ignored.\\n\\n    The operation consumes the `target` (`scf.forall`) handle and produces\\n    handles for the created `kernel.call`, `gpu.module`, and `func.func`\\n    operations.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"kernel_call\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"kernel_module\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"kernel_func\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_threads\", \"type\": \"I64Attr\" },\n      { \"name\": \"reuse_existing_gpu_module\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"extra_module_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" }\n    ],\n    \"assemblyFormat\": \"$target `threads` `(` $num_threads `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.forall_to_subgroups\",\n    \"description\": \"Inlines the body of an `scf.forall` operation immediately above the op\\n    itself and then deletes the `scf.forall` operation. The block arguments\\n    representing distribution indices are replaced by a calculation on\\n    `gpu.thread_idx x` representing the calculation of the subgroup id and then\\n    the subgroup id is delinearized to the shape of the total indices in each\\n    index dimension of the `scf.forall` operation.\\n\\n    Let x = gpu.thread_id x, then the subgroup id will be:\\n    (x mod (prod(loop_upper_bound) * subgroup_size)) floor_div subgroup_size.\\n    This subgroup id will be delinearized to the dimension of the\\n    loop and to replace the loop iterator variable.\\n\\n    Usage:\\n      `transform.kernel.forall_to_subgroups %forall subgroup_size(s)`\\n\\n    Thus, this transformation assumes that the threadblock is launched as a 1D\\n    linear array of threads. For example, if the number of threads is `128`,\\n    then the threadblock shape at launch time should be given as `(NumThreads,\\n    1, 1)`, otherwise the result of this transformation is undefined.\\n\\n    #### Example\\n\\n    Given `%1 = transform.kernel.forall_to_subgroups %arg0 subgroup_size(32)`\\n    ```mlir\\n    func.func @kernel(%arg0: tensor<128x32xf32>,\\n                  %arg1: tensor<32x128xf32>,\\n                  %arg2: tensor<128x128xf32>) -> tensor<128x128xf32> {\\n      %c2 = arith.constant 2: index\\n      %0 = scf.forall (%i, %j) in (%c2, %c2) shared_outs(%out = %arg2) -> tensor<128x128xf32> {\\n        ... body ...\\n      }\\n      return %0 : tensor<128x128xf32>\\n    }\\n    ```\\n\\n    is transformed to\\n\\n    ```\\n    func.func @kernel(%arg0: tensor<128x32xf32>,\\n                      %arg1: tensor<32x128xf32>,\\n                      %arg2: tensor<128x128xf32>) -> tensor<128x128xf32> {\\n      %c2 = arith.constant 2 : index\\n      %0 = gpu.thread_id  x\\n      %1 = affine.apply affine_map<()[s0] -> ((s0 mod 128) floordiv 32)>()[%0]\\n      %2:2 = affine.delinearize_index %1 into (%c2, %c2) : index, index\\n      ... body ...\\n    }\\n    ```\\n    where the constant 128 in the affine_map is by subgroup_size (32)*%c2*%c2.\\n\\n    #### Return modes\\n\\n    The operatin consumes the `target` (`scf.forall`) handle and produces\\n    handles for the created operation representing the `group_id` (before\\n    delinearization to the different dimensions).\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"group_id\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"subgroup_size\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target `subgroup_size` `(` $subgroup_size `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.fuse_greedily_op\",\n    \"description\": \"The `kernel.fuse_greedily_op` operation loops over all operands in the given\\n    `target` op and tries to replace any operands that are the result of a\\n    `tensor.extract_slice` with an equivalent inlined computation based on the\\n    slices' input operand. An example would be to replace a slice of a\\n    `linalg.matmul` with an instance of `linalg.matmul` that computes the slice.\\n\\n    This procedure is called \\\"fusion\\\" because the target op is typically\\n    located within the body of a loop nest.\\n\\n    Example:\\n\\n    ```\\n    %0 = linalg.matmul ins(%arg0, %arg1 : ... ) ... -> tensor<?x?xf32>\\n    %1 = scf.forall (...) -> tensor<?x?xf32> {\\n      %2 = tensor.extract_slice %0[...][...][...] : tensor<?x?xf32> to tensor<128x64xf32>\\n      %3 = linalg.matmul ins(%2, %arg1 : tensor<128x64xf32>, tensor<64x64xf32f32>)\\n              ... -> tensor <128x64xf32>\\n      scf.forall.in_parallel {\\n        tensor.parallel_insert_slice %3 into ...\\n      }\\n    }\\n    ```\\n\\n    can be transformed to\\n\\n    ```\\n    %1 = scf.forall (...) -> tensor<?x?xf32> {\\n      %arg0_slice = tensor.extract_slice %arg0 ....\\n      %arg1_slice = tensor.extract_slice %arg1 ....\\n      %2 = linalg.matmul ins(%arg0_slice, %arg1_slice : ... ) ... -> tensor<128x64xf32>\\n      %3 = linalg.matmul ins(%2, %arg1 : tensor<128x64xf32>, tensor<64x64xf32f32>)\\n              ... -> tensor <128x64xf32>\\n      scf.forall.in_parallel {\\n        tensor.parallel_insert_slice %3 into ...\\n      }\\n    }\\n    ```\\n\\n    The transformation is made generic by leveraging the `TilingInterface`. Any\\n    operation that implements the `TilingInterface` specifies how to replace a\\n    slice of the operation's result(s) with a new inlined computation.\\n    Therefore, any operation that implements `TilingInterface` can potentially\\n    be fused.\\n\\n    This inlining/fusion process is applied greedily by repeating the procedure\\n    on all fused operations until no fusions can be made. In the above example,\\n    the procedure is applied at first to `%3`, which is the initial `target`.\\n    Then, it would be applied to `%2`. Since `%2`'s operands are slices of block\\n    arguments, no further fusion is possible and the procedure terminates.\\n\\n    The initial `target` op is usually a `linalg.generic`, but it can be any\\n    operation that accepts tensor parameters.\\n\\n    More specifically, an operand of the `target` is a fusion candidate if:\\n\\n    1. It is produced by a `tensor.extract_slice` operation\\n    2. The input to the `tensor.extract_slice` is produced by a `TilingInterface` operation.\\n\\n    #### Example usage:\\n\\n    ```\\n    %1 = transform.kernel.fuse_producers_greedily %0\\n    ```\\n\\n    #### Return Modes\\n\\n    This operation consumes the `target` handle and returns a new handle\\n    representing the same operation as the `target`.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.lower_to_loops\",\n    \"description\": \"Lower the given operation to SCF loops.\\n\\n    #### Return modes\\n\\n    This operation consumes the target handle and produces a new handle\\n    representing the outer-most loop of the `scf.for` loop nest used\\n    to replace the target.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.nest_scalar_linalg_in_forall\",\n    \"description\": \"The `transform.kernel.nest_scalar_linalg_in_forall` operation nests the given\\n    `linalg.generic` target under a single-iteration `scf.forall` operation.\\n    The target is replaced by the results of the `scf.forall` operation.\\n\\n    The purpose is to enable generating `scf.forall` that represent single-CTA,\\n    single-warp kernels for a given `linalg.generic` operation that may have no\\n    loops (and thus cannot use the `transform.structured.tile_to_forall` op\\n    to accomplish the same thing).\\n\\n\\n    #### Return Modes\\n\\n    The operation returns new handles to the `scf.forall` operation and the\\n    nested clone of the Linalg target op. The target handle is consumed.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"forall_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"linalg_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.vectorize_children_and_apply_patterns\",\n    \"description\": \"This is a clone of the upstream linalg transform op\\n    \\\"transform.structured.vectorize_children_and_apply_patterns\\\", but it\\n    removes the \\\"insert slice vectorization\\\" which was added in upstream\\n    PR https://github.com/llvm/llvm-project/pull/111349.\\n\\n    It is not allowed for us to \\\"vectorize\\\" the `tensor.insert_slice` operation\\n    in the manner introduced in that PR because we treat `tensor.insert_slice`\\n    as a concurrent operation in our compiler (e.g. more like\\n    `tensor.parallel_insert_slice`, which is currently only allowed within\\n    a \\\"ParallelCombiningOp\\\" region).\\n\\n    To resolve these discrepancies we need to fix our usage of\\n    the `tensor.insert_slice` operation, which we create during outlining\\n    of `scf.forall`. Instead, we should introduce our own parallel combining\\n    operation in the Kernel dialect and use `tensor.parallel_insert_slice`.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"vectorize_padding\", \"type\": \"UnitAttr\" },\n      { \"name\": \"vectorize_nd_extract\", \"type\": \"UnitAttr\" },\n      { \"name\": \"flatten_1d_depthwise_conv\", \"type\": \"UnitAttr\" },\n      { \"name\": \"disable_multi_reduction_to_contract_patterns\", \"type\": \"UnitAttr\" },\n      { \"name\": \"disable_transfer_permutation_map_lowering_patterns\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:`functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.kernel.verify_post_tiling\",\n    \"description\": \"Performs checks that should occur after tiling and fusion have occurred\\n    but prior to distributing/outlining the `scf.forall` operations.\\n\\n    The `forall` parameter should be the outer-most `scf.forall` (which\\n    is mapped to blocks in the grid).\\n\\n    #### Return modes\\n\\n    Reads the target handle and produces no results. If errors are discovered,\\n    an error is emitted and a definite failure is returned.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.loop.coalesce\",\n    \"summary\": \"Coalesces the perfect loop nest enclosed by a given loop\",\n    \"description\": \"Given a perfect loop nest identified by the outermost loop,\\n    perform loop coalescing in a bottom-up one-by-one manner.\\n\\n    #### Return modes\\n\\n    The return handle points to the coalesced loop if coalescing happens, or\\n    the given input loop if coalescing does not happen.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, $transformed)\"\n  },\n  {\n    \"name\": \"transform.loop.coalesce_nested\",\n    \"summary\": \"Coalesces nested loops including imperfectly nested ones\",\n    \"description\": \"Given a loop, collects all nested loops (including imperfectly nested\\n    loops with operations between them) and coalesces them directly using\\n    coalesceLoops.\\n\\n    #### Return modes\\n\\n    The return handle points to the coalesced loop.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, $transformed)\"\n  },\n  {\n    \"name\": \"transform.loop.forall_to_for\",\n    \"summary\": \"Converts scf.forall into a nest of scf.for operations\",\n    \"description\": \"Converts the `scf.forall` operation pointed to by the given handle into a\\n    set of nested `scf.for` operations. Each new operation corresponds to one\\n    induction variable of the original \\\"multifor\\\" loop.\\n\\n    The operand handle must be associated with exactly one payload operation.\\n\\n    Loops with shared outputs are currently not supported.\\n\\n    #### Return Modes\\n\\n    Consumes the operand handle. Produces a silenceable failure if the operand\\n    is not associated with a single `scf.forall` payload operation.\\n    Returns as many handles as the given `forall` op has induction variables\\n    that are associated with the generated `scf.for` loops.\\n    Produces a silenceable failure if another number of resulting handles is\\n    requested.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.forall_to_parallel\",\n    \"summary\": \"Converts scf.forall into a nest of scf.for operations\",\n    \"description\": \"Converts the `scf.forall` operation pointed to by the given handle into an\\n    `scf.parallel` operation.\\n\\n    The operand handle must be associated with exactly one payload operation.\\n\\n    Loops with outputs are not supported.\\n\\n    #### Return Modes\\n\\n    Consumes the operand handle. Produces a silenceable failure if the operand\\n    is not associated with a single `scf.forall` payload operation.\\n    Returns a handle to the new `scf.parallel` operation.\\n    Produces a silenceable failure if another number of resulting handles is\\n    requested.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.fuse_sibling\",\n    \"summary\": \"Fuse a loop into another loop, assuming the fusion is legal.\",\n    \"description\": \"Fuses the `target` loop into the `source` loop assuming they are\\n    independent of each other. In the fused loop, the arguments, body and\\n    results of `target` are placed _before_ those of `source`.\\n\\n    For fusion of two `scf.for` loops, the bounds and step size must match. For\\n    fusion of two `scf.forall` loops, the bounds and the mapping must match.\\n    Otherwise a silencable failure is produced.\\n\\n    The `target` and `source` handles must refer to exactly one operation,\\n    otherwise a definite failure is produced. It is the responsibility of the\\n    user to ensure that the `target` and `source` loops are independent of each\\n    other -- this op will only perform rudimentary legality checks.\\n\\n    #### Return modes\\n\\n    This operation consumes the `target` and `source` handles and produces the\\n    `fused_loop` handle, which points to the fused loop.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"source\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"fused_loop\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target `into` $source attr-dict  `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.hoist_loop_invariant_subsets\",\n    \"summary\": \"Hoist loop invariant subset ops\",\n    \"description\": \"This transform hoists loop-invariant subset ops out of the targeted\\n    loop-like op. It looks for matching subset extraction/insertion op pairs and\\n    hoists them. The loop body operates on a newly introduced region iter_arg.\\n\\n    Subset ops are hoisted only from the targeted op. If subset ops should be\\n    hoisted from an entire loop nest, this transformation must be applied to\\n    each loop-like op of the loop nest, starting with the innermost loop and\\n    ending with the outermost loop.\\n\\n    Example:\\n    ```\\n    %r = scf.for ... iter_args(%t = %a) -> (tensor<?xf32>) {\\n      %0 = tensor.extract_slice %t[0][5][1] : tensor<?xf32> to tensor<5xf32>\\n      %1 = \\\"test.foo\\\"(%0) : (tensor<5xf32>) -> (tensor<5xf32>)\\n      %2 = tensor.insert_slice %1 into %t[0][5][1]\\n          : tensor<5xf32> into tensor<?xf32>\\n      scf.yield %2 : tensor<?xf32>\\n    }\\n    ```\\n    Is transformed to:\\n    ```\\n    %0 = tensor.extract_slice %a[0][5][1] : tensor<?xf32> to tensor<5xf32>\\n    %new_loop:2 = scf.for ... iter_args(%t = %a, %h = %0) -> (tensor<?xf32>) {\\n      %1 = \\\"test.foo\\\"(%h) : (tensor<5xf32>) -> (tensor<5xf32>)\\n      scf.yield %t, %2 : tensor<?xf32>, tensor<5xf32>\\n    }\\n    %r = tensor.insert_slice %new_loop#1 into %new_loop#0\\n        : tensor<5xf32> into tensor<?xf32>\\n    ```\\n\\n    Subset ops are hoisted only if there are no conflicting subset ops. E.g.,\\n    if there were a second overlapping extraction in the above example, no ops\\n    could be hoisted safely.\\n\\n    This transform reads the target handle and modifies the payload. This\\n    transform does not invalidate any handles, but loop-like ops are replaced\\n    with new loop-like ops when a subset op is hoisted. The transform rewriter\\n    updates all handles accordingly.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.loop.outline\",\n    \"summary\": \"Outlines a loop into a named function\",\n    \"description\": \"Moves the loop into a separate function with the specified name and replaces\\n    the loop in the Payload IR with a call to that function. Takes care of\\n    forwarding values that are used in the loop as function arguments. If the\\n    operand is associated with more than one loop, each loop will be outlined\\n    into a separate function. The provided name is used as a _base_ for forming\\n    actual function names following `SymbolTable` auto-renaming scheme to avoid\\n    duplicate symbols. Expects that all ops in the Payload IR have a\\n    `SymbolTable` ancestor (typically true because of the top-level module).\\n\\n    #### Return Modes\\n\\n    Returns a handle to the list of outlined functions and a handle to the\\n    corresponding function call operations in the same order as the operand\\n    handle.\\n\\n    Produces a definite failure if outlining failed for any of the targets.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"function\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"call\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"func_name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.parallel_for_to_nested_fors\",\n    \"summary\": \"Converts scf.parallel into a nest of scf.for operations\",\n    \"description\": \"Converts the `scf.parallel` operation pointed to by the given handle into a\\n    set of nested `scf.for` operations. Each new operation corresponds to one\\n    dimension of the original parallel loop.\\n\\n    The operand handle must be associated with exactly one payload operation.\\n\\n    Loops with shared outputs are currently not supported.\\n\\n    #### Return Modes\\n\\n    Consumes the operand handle. Produces a silenceable failure if the operand\\n    is not associated with a single `scf.parallel` payload operation.\\n    Returns as many handles as the given `parallel` op has dimensions that are\\n    associated with the generated `scf.for` loops.\\n    Produces a silenceable failure if another number of resulting handles is\\n    requested.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.peel\",\n    \"summary\": \"Peels the first or last iteration of the loop\",\n    \"description\": \"Rewrite the given loop with a main loop and a partial (first or last) loop.\\n     When the `peelFront` option is set to true, the first iteration is peeled off.\\n     Otherwise, updates the given loop so that its step evenly divides its range and puts\\n     the remaining iteration into a separate loop or a conditional.\\n\\n     In the absence of sufficient static information, this op may peel a loop,\\n     even if the step always divides the range evenly at runtime.\\n\\n     #### Return modes\\n\\n     This operation ignores non-scf::ForOp ops and drops them in the return.\\n     The op returns two loops, the peeled loop which has trip count divisible\\n     by the step, and the remainder loop.\\n\\n     When `peelFront` is true, the first result (remainder loop) executes all\\n     but the first iteration of the target loop. The second result (peeled\\n     loop) corresponds to the first iteration of the loop which can be\\n     canonicalized away in the following optimizations.\\n\\n     When `peelFront` is false, the first result (peeled loop) is the portion\\n     of the target loop with the highest upper bound that is divisible by the\\n     step. The second result (remainder loop) contains the remaining iterations. \\n     \\n     Note that even though the Payload IR modification may be performed\\n     in-place, this operation consumes the operand handle and produces a new one.\\n\\n     #### Return Modes\\n\\n     Produces a definite failure if peeling fails.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Transform_ScfForOp\" }\n    ],\n    \"results\": [\n      { \"name\": \"peeled_loop\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"remainder_loop\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"peel_front\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"fail_if_already_divisible\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.pipeline\",\n    \"summary\": \"Applies software pipelining to the loop\",\n    \"description\": \"Transforms the given loops one by one to achieve software pipelining for\\n    each of them. That is, performs some amount of reads from memory before the\\n    loop rather than inside the loop, the same amount of writes into memory\\n    after the loop, and updates each iteration to read the data for a following\\n    iteration rather than the current one.\\n\\n    The amount is specified by the attributes.\\n\\n    The values read and about to be stored are transferred as loop iteration\\n    arguments. Currently supports memref and vector transfer operations as\\n    memory reads/writes.\\n\\n    #### Return modes\\n\\n    This operation ignores non-scf::For ops and drops them in the return.\\n    If all the operations referred to by the `target` PDLOperation pipeline\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.  The return handle points to only the subset of\\n    successfully produced pipelined loops, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Transform_ScfForOp\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iteration_interval\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"read_latency\", \"type\": \"DefaultValuedAttr<I64Attr, 10>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.loop.promote_if_one_iteration\",\n    \"summary\": \"Promote loop if it has one iteration\",\n    \"description\": \"Promotes the given target loop op if it has a single iteration. I.e., the\\n    loop op is removed and only the body remains.\\n\\n    #### Return modes\\n\\n    This transform fails if the target is mapped to ops that are loops. Ops are\\n    considered loops if they implement the `LoopLikeOpInterface`. Otherwise,\\n    this transform always succeeds. The transform consumes the target handle and\\n    modifies the payload.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.loop.unroll\",\n    \"summary\": \"Unrolls the given loop with the given unroll factor\",\n    \"description\": \"Unrolls each loop associated with the given handle to have up to the given\\n    number of loop body copies per iteration. If the unroll factor is larger\\n    than the loop trip count, the latter is used as the unroll factor instead.\\n\\n    #### Return modes\\n\\n    This operation ignores non-`scf.for`, non-`affine.for` ops and drops them\\n    in the return. If all the operations referred to by the `target` operand\\n    unroll properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.\\n\\n    Does not return handles as the operation may result in the loop being\\n    removed after a full unrolling.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"factor\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.loop.unroll_and_jam\",\n    \"summary\": \"Unrolls and jam the given loop with the given unroll factor\",\n    \"description\": \"Unrolls & jams each loop associated with the given handle to have up to the given\\n    number of loop body copies per iteration. If the unroll factor is larger\\n    than the loop trip count, the latter is used as the unroll factor instead.\\n\\n    #### Return modes\\n\\n    This operation ignores non-`scf.for`, non-`affine.for` ops and drops them\\n    in the return. If all the operations referred to by the `target` operand\\n    unroll properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.\\n\\n    Does not return handles as the operation may result in the loop being\\n    removed after a full unrolling.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"factor\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.match.my.has_operand_satisfying\",\n    \"summary\": \"Succeed if any of the operands matches all nested criteria\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"position\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"results\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"$op `:` functional-type($op, results) attr-dict-with-keyword $body\"\n  },\n  {\n    \"name\": \"transform.match.operation_empty\",\n    \"summary\": \"Matches if the handle is not associated to any op\",\n    \"description\": \"Succeeds if the handle is not associated to any op.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.match.operation_name\",\n    \"summary\": \"Matches a single operation of one of the given kinds\",\n    \"description\": \"Succeeds if the operation associated with the operand handle has one of the\\n    given operation names. Produces a silenceable failure otherwise.\\n\\n    If more than one payload operation is associated with the operand handle,\\n    produces a definite failure.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_names\", \"type\": \"TypedArrayAttrBase<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle $op_names attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.match.param.cmpi\",\n    \"summary\": \"Matches if two parameter lists are associated with the same value\",\n    \"description\": \"Succeeds if all of the co-indexed values associated with the given\\n    parameters relate as specified by the predicate (greater than, less than,\\n    equal to, or their combinations). Comparison treats all values as signed.\\n    Produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"param\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"reference\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"predicate\", \"type\": \"MatchCmpIPredicateAttr{eq|ne|lt|le|gt|ge}\" }\n    ],\n    \"assemblyFormat\": \"$predicate $param `,` $reference attr-dict `:` type($param)\"\n  },\n  {\n    \"name\": \"transform.match.structured\",\n    \"summary\": \"Matches a structured (linalg) operation with additional conditions\",\n    \"description\": \"Checks if the payload operation associated with the operand handle is a\\n    structured operation, that is, an operation that implements\\n    `LinalgOpInterface`, and that all conditions listed in the body of this\\n    operation are satisfied. Produces a silenceable failure if the payload\\n    operation is not structured.\\n\\n    The transform operations nested in the body region are applied one by one.\\n    If any of them produces a failure, silenceable or definite, the following\\n    operations are not applied. If the failure propagation mode is \\\"propagate\\\",\\n    silenceable failures are forwarded as the result of this operation. If it is\\n    \\\"suppress\\\", they are ignored and this operation immediately succeeds.\\n    Definite failures are always propagated immediately.\\n\\n    In case of success, the transform values produced by this operation are\\n    associated with the same payload as the operands of the block terminator. If\\n    any of the nested operations produced a silenceable failure, regardless of\\n    the failure propagation mode, the transform values produced by this\\n    operation that correspond to the already defined terminator operands are\\n    associated with the same payload as the already defined terminator operands.\\n    Other values produced by this operation are associated with empty payloads.\\n\\n    If the failure propagation mode is not specified, it is considered\\n    \\\"propagate\\\" by default. The \\\"suppress\\\" mode can be used to specify optional\\n    matches.\\n\\n    #### Return modes\\n\\n    This operation only reads all operand handles and produces all resulting\\n    handles. It succeeds in \\\"propagate\\\" mode if the payload operation is a\\n    structured operation and if all the nested operations succeed. It succeeds\\n    in \\\"suppress\\\" mode as long as the operand handle is associated with exactly\\n    one payload operation. It produces a definite failure when the handle is\\n    not associated with exactly one payload operation.\",\n    \"operands\": [\n      { \"name\": \"current\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"failure_propagation_mode\", \"type\": \"OptionalAttr<FailurePropagationMode{propagate|suppress}>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body_region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"(`failures` `(` $failure_propagation_mode^ `)`)?$current `:` custom<SemiFunctionType>(type($current), type($outputs))attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.match.structured.body\",\n    \"summary\": \"Checks if the body of the structured op satisfies some criteria\",\n    \"description\": \"Checks if the body of the structured payload op satisfies one of the\\n    following mutually exclusive criteria specified by attributes:\\n\\n      * `reduction_position`: the body of the structured payload op implements\\n        a reduction of the `n`-th operand (`n` is the value of the attribute)\\n        using a single combiner operation;\\n\\n      * `passthrough`: the body of the structured payload op only forwards\\n        inputs to the outputs (copy or broadcast).\\n\\n      * `elementwise`: the body of the structured payload op represents an\\n        elementwise operation.\\n\\n      * `contraction`: the body of the structured payload op is a contraction\\n        of the form `<red>(<elem>(bbarg0, bbarg1), bbarg2)` where `<elem>` and\\n        `<red>` are binary operations whose names are specified in the attribute\\n        and operands can be permuted and optionally forwarded through a chain of\\n        unary side effect-free operations.#### Return modes\\n\\n    Succeeds if the operation body satisfies the specified criteria, produces a\\n    silenceable failure otherwise. Produces a definite failure if the operand is\\n    not associated with a single payload op.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_position\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"passthrough\", \"type\": \"UnitAttr\" },\n      { \"name\": \"elementwise\", \"type\": \"UnitAttr\" },\n      { \"name\": \"contraction\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.match.structured.classify_contraction_dims\",\n    \"summary\": \"Checks if an operation has contraction-like dimensions and returns them\",\n    \"description\": \"Checks if the structured payload op has contraction-like dimensions as\\n    follows:\\n\\n      C(batch, m, n) += A(batch, m, k) * B(batch, k, n)\\n\\n    That is:\\n    \\n      - 'batch' are parallel dimensions used in inputs and result;\\n      - 'm' are parallel dimensions used in the LHS and result;\\n      - 'n' are parallel dimensions used in rhe RHS and result;\\n      - 'k' are reduction dimensions present only in LHS and RHS.\\n\\n    Note that this doesn't check the operation in the body.#### Return modes\\n\\n    Succeeds if the operation has the contraction-like dimensions, produces a\\n    silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"batch\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"m\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"n\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"k\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.match.structured.classify_convolution_dims\",\n    \"summary\": \"Checks if an operation has convolution-like dimensions and returns them\",\n    \"description\": \"Checks if the structured payload op has convolution-like dimensions as\\n    follows:\\n\\n      C(batch, depth, oi, oc) += A(batch, depth, oi, ic) * B(fl, depth, ic, oc)\\n\\n    That is:\\n\\n      - 'batch' are parallel dimensions used in the input and result;\\n      - 'output_image' ('oi') are parallel dimensions used in the input and result;\\n      - 'output_channel' ('oc') are parallel dimensions used in the filter and result;\\n      - 'filter_loop' ('fl') are reduction dimensions representing the dimensions of the sliding window;\\n      - 'input_channel' ('ic') are reduction dimensions present only in the input and filter.\\n      - 'depth' ('ic') are parallel dimensions present in the input, filter, and output.\\n\\n    Additionally this will match stride and dilation information for the convolution:\\n      - 'strides' are the static strides per convolution window dimension;\\n      - 'dilations' are the static dilations per convolution window dimension.\\n\\n    Note that this doesn't check the operation in the body.#### Return modes\\n\\n    Succeeds if the operation has the convolution-like dimensions, produces a\\n    silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"batch\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"output_image\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"output_channel\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"filter_loop\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"input_channel\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"depth\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"strides\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"dilations\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.match.structured.dim\",\n    \"summary\": \"Checks if the dimensions of the structured op satisfy some criteria\",\n    \"description\": \"Checks if the dimensions (loop ranges) of the structured payload op satisfy\\n    the criteria specified as attributes. May capture the numeric value of the\\n    dimension into a parameter that it returns.The following mutually exclusive conditions are available as unit\\n    attributes:\\n\\n      * `parallel`: the dimension corresponds to a parallel loop;\\n      * `reduction`: the dimension corresponds to a reduction loop.\\n\\n    If the result type is specified, associates the parameter with the (static)\\n    values of dimensions in the same order as listed and preserving the natural\\n    order for `all` and `except`. Specifically, if `-1, -2` are specified, the\\n    parameter will be associated with the value of the second-to-last dimension\\n    followed by the last dimension. If the dimension is dynamic, the parameter\\n    will contain a negative value corresponding to kDynamic in C++.#### Return modes\\n\\n    Succeeds if the specified dimensions satisfy the specified criteria,\\n    produces a silenceable failure otherwise. Produces a definite failure if\\n    the operand is not associated with a single payload op.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<TransformParamTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"raw_dim_list\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"is_inverted\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_all\", \"type\": \"UnitAttr\" },\n      { \"name\": \"parallel\", \"type\": \"UnitAttr\" },\n      { \"name\": \"reduction\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `[`custom<TransformMatchDims>($raw_dim_list, $is_inverted, $is_all)`]` attr-dict `:` custom<SemiFunctionType>(type($operand_handle), type($result))\"\n  },\n  {\n    \"name\": \"transform.match.structured.elemental_bitwidth\",\n    \"summary\": \"Captures the bitwidth of the value's elemental type as a parameter\",\n    \"description\": \"Produces a transform dialect parameter associated with the bitwidth of the\\n    elemental type of the payload value passed as the operand.#### Return modes\\n\\n    Succeeds if the operand is associated with exactly one payload value of\\n    `ShapedType`. Produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.match.structured.init\",\n    \"summary\": \"Captures init operand(s) of a structured operation\",\n    \"description\": \"Produces a transform dialect value depending on the result type:\\n      - If the result type is a value handle, it will be associated with the init\\n        operand(s) of the payload operation associated with the operand handle.\\n      - If the result type is an operation handle, it will be associated with the\\n        operation defining the init operand(s) of the payload operation associated\\n        with the operand handle.\\n      - If the result type is an affine map parameter type, it will be associated\\n        with the indexing map that corresponds to the init operand(s) of the\\n        payload operation associated with the operand handle.\\n\\n    For example, given the following operation:\\n\\n    ```mlir\\n    %arg3 = linalg.fill\\n    linalg.matmul ins(%arg1, %arg2 : ...) outs(%arg3 : ...)\\n    ```\\n\\n    in case of a successful match for init operand 0 this operation will return,\\n    for each of the respective cases above:\\n\\n      - A handle to `%arg3` if the result is a value handle.\\n      - A handle to `linalg.fill` if the result is an operation handle.\\n      - A parameter containing the result map of the matrix multiplication, i.e.\\n        `affine_map<(d0, d1, d2) -> (d0, d1)>` if the result is an affine\\n        map parameter.\\n\\n    The match succeeds if the conditions specified as attributes succeed.#### Return modes\\n\\n    Succeeds if all init(outs) indexes are in bounds, produces a silenceable\\n    failure otherwise. Additionally, when the result is an operation handle,\\n    produces a silenceable failure if the init(outs) specification defines\\n    more than one init(outs) or if the operand is not an operation result.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyTypeOf<[ TransformAnyHandle, Transform_AffineMapParamType ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"raw_position_list\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"is_inverted\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_all\", \"type\": \"UnitAttr\" },\n      { \"name\": \"permutation\", \"type\": \"UnitAttr\" },\n      { \"name\": \"projected_permutation\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `[`custom<TransformMatchDims>($raw_position_list, $is_inverted, $is_all)`]` attr-dict `:` custom<SemiFunctionType>(type($operand_handle), type($result))\"\n  },\n  {\n    \"name\": \"transform.match.structured.input\",\n    \"summary\": \"Captures input operand(s) of a structured operation\",\n    \"description\": \"Produces a transform dialect value depending on the result type:\\n    \\n      - If the result type is a value handle, it will be associated with the input\\n        operand(s) of the payload operation associated with the operand handle.\\n      - If the result type is an operation handle, it will be associated with the\\n        operation defining the input operand(s) of the payload operation associated\\n        with the operand handle.\\n      - If the result type is an affine map parameter type, it will be associated\\n        with the indexing map that corresponds to the input operand(s) of the\\n        payload operation associated with the operand handle.\\n\\n    For example, given the following operation:\\n\\n    ```mlir\\n    %arg1 = some.op\\n    linalg.matmul ins(%arg1, %arg2 : ...) outs(%arg3 : ...)\\n    ```\\n\\n    in case of a successful match for operand 0 this operation will return, for\\n    each of the respective cases above:\\n\\n      - A handle to `%arg1` if the result is a value handle.\\n      - A handle to `some.op` if the result is an operation handle.\\n      - A parameter containing the LHS map of the matrix multiplication, i.e.\\n        `affine_map<(d0, d1, d2) -> (d0, d2)>` if the result is an affine\\n        map parameter.\\n\\n    The match succeeds if the conditions specified as attributes succeed.#### Return modes\\n\\n    Succeeds if all input indexes are in bounds, produces a silenceable failure\\n    otherwise. Additionally, when the result is an operation handle, produces a\\n    silenceable failure if the input specification defines more than one input\\n    or if the operand is not an operation result.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyTypeOf<[ TransformAnyHandle, Transform_AffineMapParamType ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"raw_position_list\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"is_inverted\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_all\", \"type\": \"UnitAttr\" },\n      { \"name\": \"permutation\", \"type\": \"UnitAttr\" },\n      { \"name\": \"projected_permutation\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `[`custom<TransformMatchDims>($raw_position_list, $is_inverted, $is_all)`]` attr-dict `:` custom<SemiFunctionType>(type($operand_handle), type($result))\"\n  },\n  {\n    \"name\": \"transform.match.structured.num_inits\",\n    \"summary\": \"Captures the number of init(outs) operands of a structuredoperation as parameter\",\n    \"description\": \"Produces a transform dialect parameter value associated with an integer\\n    attribute containing the number of init(outs) operands of the payload\\n    operation associated with the operand handle.#### Return modes\\n\\n    Succeeds if the operand is associated with exactly one structured payload\\n    operation. Produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.match.structured.num_inputs\",\n    \"summary\": \"Captures the number of input operands of a structured operation as parameter\",\n    \"description\": \"Produces a transform dialect parameter value associated with an integer\\n    attribute containing the number of input operands of the payload operation\\n    associated with the operand handle.#### Return modes\\n\\n    Succeeds if the operand is associated with exactly one structured payload\\n    operation. Produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.match.structured.rank\",\n    \"summary\": \"Captures the rank of a structured operation as parameter\",\n    \"description\": \"Produces a transform dialect parameter value associated with an integer\\n    attribute containing the rank of the structured payload operation associated\\n    with the operand handle.#### Return modes\\n\\n    Succeeds if the operand is associated with exactly one structured payload\\n    operation. Produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"rank\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle attr-dict `:`\\n      custom<SemiFunctionType>(type($operand_handle), type($rank), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.match.structured.result\",\n    \"summary\": \"Captures the result of a structured payload operation in an op or value handle\",\n    \"description\": \"Produces a transform dialect value handle associated with the payload value\\n    defined as a result of the payload operation associated with the operand\\n    handle, or an operation handle to an operation using the produced result\\n    with additional constraints specified by the attributes as follows.\\n\\n      * If `any` is specified, binds the resulting handle to any operation using\\n        the result and succeeds.\\n      * If `single` is specified, binds the resulting handle to the only\\n        operation using the result or fails if there is more than one (or no)\\n        such operation.\\n\\n    The number of the result is specified as `position` attribute. It may take\\n    positive and negative values. Negative values are interpreted as counting\\n    results from backwards, e.g., `-1` means the last result and `-2` means the\\n    second-to-last result. In any case, the position must be in bounds for the\\n    given payload operation. A silenceable failure is produced for out-of-bounds\\n    positions.#### Return modes\\n\\n    Succeeds if the position is in bounds and if the user operation could be\\n    found when requested. Produces a silenceable failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformAnyHandle\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"position\", \"type\": \"I64Attr\" },\n      { \"name\": \"any\", \"type\": \"UnitAttr\" },\n      { \"name\": \"single\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `[` $position `]` (`any` $any^)? (`single` $single^)?attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.match.structured.yield\",\n    \"summary\": \"Terminator for transform.match.structured blocks\",\n    \"description\": \"Forwards the payload association from the operands to the results of the\\n    parent op. Always succeeds.\",\n    \"operands\": [\n      { \"name\": \"handles\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"assemblyFormat\": \"$handles attr-dict (`:` type($handles)^)?\"\n  },\n  {\n    \"name\": \"transform.memref.alloca_to_global\",\n    \"description\": \"Inserts a new `memref.global` for each provided `memref.alloca` into the\\n    nearest symbol table (e.g., a `builtin.module`) and replaces it with a\\n    `memref.get_global`. This is useful, for example, for allocations that\\n    should reside in the shared memory of a GPU, which have to be declared as\\n    globals.\\n\\n    #### Example\\n\\n    Consider the following transform op:\\n\\n    ```mlir\\n    %get_global, %global =\\n        transform.memref.alloca_to_global %alloca\\n          : (!transform.op<\\\"memref.alloca\\\">)\\n            -> (!transform.any_op, !transform.any_op)\\n    ```\\n\\n    and the following input payload:\\n\\n    ```mlir\\n    module {\\n      func.func @func() {\\n        %alloca = memref.alloca() : memref<2x32xf32>\\n        // usages of %alloca...\\n      }\\n    }\\n    ```\\n\\n    then applying the transform op to the payload would result in the following\\n    output IR:\\n\\n    ```mlir\\n    module {\\n      memref.global \\\"private\\\" @alloc : memref<2x32xf32>\\n      func.func @func() {\\n        %alloca = memref.get_global @alloc : memref<2x32xf32>\\n        // usages of %alloca...\\n      }\\n    }\\n    ```\\n\\n    #### Return modes\\n\\n    Succeeds always. The returned handles refer to the `memref.get_global` and\\n    `memref.global` ops that were inserted by the transformation.\",\n    \"operands\": [\n      { \"name\": \"alloca\", \"type\": \"Transform_MemRefAllocaOp\" }\n    ],\n    \"results\": [\n      { \"name\": \"getGlobal\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"global\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$alloca attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.memref.erase_dead_alloc_and_stores\",\n    \"description\": \"This applies memory optimization on memref. In particular it does store to\\n    load forwarding, dead store elimination and dead alloc/alloca elimination.\\n\\n    #### Return modes\\n\\n    This operation applies a set of memory optimization on the whole region of\\n    the operand.\\n\\n    The transformation does not consume the target handle. It modifies the\\n    payload. Dead allocations, loads and stores are silently dropped from all\\n    mappings.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.memref.make_loop_independent\",\n    \"description\": \"Rewrite the targeted ops such that their index-typed operands no longer\\n    depend on any loop induction variable of the `num_loop` enclosing `scf.for`\\n    loops. I.e., compute an upper bound that is independent of any such loop IV\\n    for every tensor dimension. The transformed op could then be hoisted from\\n    the `num_loop` enclosing loops. To preserve the original semantics, place a\\n    `memref.subview` inside the loop.\\n\\n    Currently supported operations are:\\n    - memref.alloca: Replaced with a new memref.alloca with upper bound sizes,\\n      followed by a memref.subview.\\n\\n    #### Return modes\\n\\n    This operation fails if at least one induction variable could not be\\n    eliminated. In case the targeted op is already independent of induction\\n    variables, this transform succeeds and returns the unmodified target op.\\n\\n    Otherwise, the returned handle points to a subset of the produced ops:\\n    - memref.alloca: The returned handle points to the memref.subview op.\\n\\n    This transform op consumes the target handle and produces a result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_loops\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, $transformed)\"\n  },\n  {\n    \"name\": \"transform.memref.multibuffer\",\n    \"summary\": \"Multibuffers an allocation\",\n    \"description\": \"Transformation to do multi-buffering/array expansion to remove\\n     dependencies on the temporary allocation between consecutive loop\\n     iterations. This transform expands the size of an allocation by\\n     a given multiplicative factor and fixes up any users of the\\n     multibuffered allocation.\\n     If skip analysis is not set the transformation will only apply\\n     if it can prove that there is no data being carried across loop\\n     iterations.\\n\\n     #### Return modes\\n\\n     This operation returns the new allocation if multi-buffering\\n     succeeds, and failure otherwise.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Transform_MemRefAllocOp\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"factor\", \"type\": \"ConfinedAttr<I64Attr, [IntPositive]>\" },\n      { \"name\": \"skip_analysis\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.merge_handles\",\n    \"summary\": \"Merges handles into one pointing to the union of payload ops\",\n    \"description\": \"Creates a new Transform IR handle value that points to the same Payload IR\\n    operations/values/parameters as the operand handles. The Payload IR elements\\n    are listed in the same order as they are in the operand handles, grouped by\\n    operand handle, e.g., all Payload IR associated with the first handle comes\\n    first, then all Payload IR associated with the second handle and so on. If\\n    `deduplicate` is set, do not add the given Payload IR operation, value, or\\n    parameter more than once to the final list regardless of it coming from the\\n    same or different handles. Consumes the operands and produces a new handle.\",\n    \"operands\": [\n      { \"name\": \"handles\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Transform_AnyHandleOrParamType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"deduplicate\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`deduplicate` $deduplicate^)? $handles attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"transform.my.call_to_op\",\n    \"operands\": [\n      { \"name\": \"call\", \"type\": \"CallOpInterfaceHandle\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$call attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.my.change_call_target\",\n    \"summary\": \"Changes the callee of a call operation to the specified one\",\n    \"description\": \"For each `func.call` payload operation associated with the handle, changes its \\n    callee to be the symbol whose name is provided as an attribute to this operation.\\n\\n    Generates a silenceable failure if the operand is associated with payload operations \\n    that are not `func.call`.\\n    Only reads the operand.\",\n    \"operands\": [\n      { \"name\": \"call\", \"type\": \"AnyTypeOf<[Transform_ConcreteOpType<func.call>, CallOpInterfaceHandle]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"new_target\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$call `,` $new_target attr-dict `:` qualified(type($call))\"\n  },\n  {\n    \"name\": \"transform.named_sequence\",\n    \"summary\": \"Named transform sequence that can be included elsewhere\",\n    \"description\": \"Defines a named (callable, function-like) sequence of other Transform\\n    dialect operations that can be included using `transform.include` as part of\\n    another Transform dialect construct. This sequence is not processed\\n    immediately but rather dispatched to when the inclusion is processed. The\\n    arguments and results can be used to communicate a subset of mapping into\\n    the named sequence. The sequence must consist of a single block and end with\\n    a `transform.yield` terminator. The operands of the terminator become the\\n    results of the `transform.include`.\\n\\n    When dispatched to, the operations in the named sequence are executed one by\\n    one, similarly to the regular unnamed sequence. The failure propagation mode\\n    is specified on the `transform.include`. Different inclusions may use\\n    different failure propagation modes. This transform operation always\\n    succeeds by itself, but the inclusion may fail if any of the operations\\n    fail.\\n\\n    Named sequences can only appear at the top-level of the Transform dialect\\n    nesting structure. That is, they cannot be nested in other Transform dialect\\n    operations. Furthermore, one of the ancestors must have the `SymbolTable`\\n    trait and have the `transform.with_named_sequence` attribute attached.\\n\\n    Named sequences may include other named sequences via `transform.include`,\\n    but recursion is *not* allowed.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrBase<::mlir::FunctionType, function type attribute>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"transform.num_associations\",\n    \"summary\": \"Returns the number of payload objects associated with the argument\",\n    \"description\": \"Given an argument, handle or parameter, returns a new parameter associated\\n    with a single 64-bit number that corresponds to the number of payload\\n    objects (operations or values for a handle, attributes for a parameter)\\n    associated with the argument.\\n\\n    Always succeeds.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"Transform_AnyHandleOrParamType\" }\n    ],\n    \"results\": [\n      { \"name\": \"num\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.nvgpu.create_async_groups\",\n    \"description\": \"Look for global to shared memory copies within the targeted op in the form\\n    of vector transfer ops and convert them to async copies when possible.\\n    Consecutive copies are put into the same group. A \\\"wait\\\" operation is\\n    inserted right at the of end the group.\\n\\n    `bypass_l1` specifies whether `bypassL1` attributes should be added to\\n    the async copies. `bypass_l1` is a compiler hint: only 16 byte transfers\\n    can bypass the L1 cache, so this attribute is not set for any other transfer\\n    sizes.\\n\\n    #### Return modes\\n\\n    This op consumes the `target` handle and produces the `result` handle, which\\n    is mapped to the same payload operations as the `target` handle. The op\\n    modifies the payload.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bypass_l1\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.nvgpu.pipeline_shared_memory_copies\",\n    \"summary\": \"Applies software pipelining to a given loop with shared memory copies\",\n    \"description\": \"Applies software pipelining to a given scf.for loop. The pipelining\\n    strategy will look for a load into shared memory and pipeline it to overlap\\n    it with the rest of the loop.\\n    \\n    NOTE: It is user responsibility to ensure that there are no dependency\\n    between `depth` iterations of the loop by using multi-buffering. It is\\n    also user responsibility to ensure a sufficient amount of shared memory\\n    is allocated to cover eventual writes by `depth-1` speculative\\n    iterations.\\n\\n    `depth` will indicate how many stages the software pipeline should have.\\n    `peel_epilogue` allows to force the epilogue to be peeled out instead of\\n    potentially using predicated operations for the epilogue phase.\\n\\n    #### Return modes\\n\\n    Consumes the operand handle and produces a result handle pointing to the\\n    loop, which may or may not have been pipelined. Produces a definite failure\\n    if the loop pipeliner mutated the IR before failing to pipeline, in\\n    particular if `peel_epilogue` is not set and the loop body doesn't support\\n    predication. If failure propagation mode is set to \\\"propagate\\\", produces a\\n    silenceable failure when pipelining preconditions, e.g., loop bound being\\n    static, are not met or when the loop wasn't pipelined because due to the\\n    lack of loads into shared memory. If the failure propagation mode is set\\n    to \\\"suppress\\\" (default), succeeds in these case and associates the result\\n    handle with the original loop.\\n\\n    TODO: the shared memory part and behavior specific to NVGPU should be\\n    made orthogonal to pipelining so that `transform.loop.pipeline` becomes\\n    usable here.\",\n    \"operands\": [\n      { \"name\": \"for_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depth\", \"type\": \"I64Attr\" },\n      { \"name\": \"peel_epilogue\", \"type\": \"UnitAttr\" },\n      { \"name\": \"failure_propagation_mode\", \"type\": \"DefaultValuedAttr<FailurePropagationMode{propagate|suppress}, ::mlir::transform::FailurePropagationMode::Suppress>\" }\n    ],\n    \"assemblyFormat\": \"`failures` `(` $failure_propagation_mode `)`\\n    $for_op\\n    attr-dict \\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.nvgpu.rewrite_copy_as_tma\",\n    \"description\": \"Rewrite a copy operation on memref to tma operations that transit through\\n    shared memory.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.nvgpu.rewrite_matmul_as_mma_sync\",\n    \"description\": \"Rewrite a matmul operation on memref to an mma.sync operation on vectors.\\n\\n    Memory copies with the required access patterns are automatically inserted.\\n    Operations that do not have a 1-1 mapping to mma.sync operations are left\\n    unchanged.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.param.constant\",\n    \"summary\": \"Produces a new transform dialect parameter value associated with the given attribute\",\n    \"description\": \"Produces a new transform dialect parameter associated with the singleton\\n    list containing the given attribute. The operation itself always succeeds,\\n    but the general association check may fail if the parameter type does not\\n    accept the given kind of attribute as valid.\",\n    \"results\": [\n      { \"name\": \"param\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `->` type($param)\"\n  },\n  {\n    \"name\": \"transform.pdl_match\",\n    \"summary\": \"Finds ops that match the named PDL pattern\",\n    \"description\": \"Find Payload IR ops nested within the Payload IR op associated with the\\n    operand that match the PDL pattern identified by its name. The pattern is\\n    expected to be defined in the closest surrounding `WithPDLPatternsOp`.\\n\\n    Produces a Transform IR value associated with the list of Payload IR ops\\n    that matched the pattern. The order of results in the list is that of the\\n    Operation::walk, clients are advised not to rely on a specific order though.\\n    If the operand is associated with multiple Payload IR ops, finds matching\\n    ops nested within each of those and produces a single list containing all\\n    of the matched ops.\\n\\n    The transformation is considered successful regardless of whether some\\n    Payload IR ops actually matched the pattern and only fails if the pattern\\n    could not be looked up or compiled.\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"matched\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern_name\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$pattern_name `in` $root attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.print\",\n    \"summary\": \"Dump each payload op\",\n    \"description\": \"Prints each payload op that is associated with the `target` operand to\\n    `stdout`. It also prints the `name` string attribute. If no target is\\n    specified, the top-level op is dumped.\\n\\n    This op is useful for printf-style debugging.\\n\\n    Supported printing flag attributes:\\n    * `assume_verified` -- skips verification when the unit attribute is\\n      specified. This improves performace but may lead to crashes and\\n      unexpected behavior when the printed payload op is invalid.\\n    * `use_local_scope` -- prints in local scope when the unit attribute is\\n      specified. This improves performance but may not be identical to\\n      printing within the full module.\\n    * `skip_regions` -- does not print regions of operations when the unit\\n      attribute is specified.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"assume_verified\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"use_local_scope\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"skip_regions\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict (`:` type($target)^)?\"\n  },\n  {\n    \"name\": \"transform.replicate\",\n    \"summary\": \"Lists payload ops multiple times in the new handle\",\n    \"description\": \"Produces a new handle associated with a list of payload IR ops that is\\n    computed by repeating the list of payload IR ops associated with the\\n    operand handle as many times as the \\\"pattern\\\" handle has associated\\n    operations. For example, if pattern is associated with [op1, op2] and the\\n    operand handle is associated with [op3, op4, op5], the resulting handle\\n    will be associated with [op3, op4, op5, op3, op4, op5].\\n\\n    This transformation is useful to \\\"align\\\" the sizes of payload IR lists\\n    before a transformation that expects, e.g., identically-sized lists. For\\n    example, a transformation may be parameterized by same notional per-target\\n    size computed at runtime and supplied as another handle, the replication\\n    allows this size to be computed only once and used for every target instead\\n    of replicating the computation itself.\\n\\n    Note that it is undesirable to pass a handle with duplicate operations to\\n    an operation that consumes the handle. Handle consumption often indicates\\n    that the associated payload IR ops are destroyed, so having the same op\\n    listed more than once will lead to double-free. Single-operand\\n    MergeHandlesOp may be used to deduplicate the associated list of payload IR\\n    ops when necessary. Furthermore, a combination of ReplicateOp and\\n    MergeHandlesOp can be used to construct arbitrary lists with repetitions.\",\n    \"operands\": [\n      { \"name\": \"pattern\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"handles\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"replicated\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['handles', 'replicated']>\" }\n    ],\n    \"assemblyFormat\": \"`num` `(` $pattern `)` $handles attr-dict `:` type($pattern) `,` type($handles)\"\n  },\n  {\n    \"name\": \"transform.scf.take_assumed_branch\",\n    \"description\": \"Given an scf.if conditional, inject user-defined information that it is\\n    always safe to execute only the if or else branch.\\n\\n    This is achieved by just replacing the scf.if by the content of one of its\\n    branches.\\n\\n    This is particularly useful for user-controlled rewriting of conditionals\\n    that exist solely to guard against out-of-bounds behavior.\\n\\n    At the moment, no assume or assert operation is emitted as it is not always\\n    desirable. In the future, this may be controlled by a dedicated attribute.\\n\\n    #### Return modes\\n\\n    The transform only consumes its operand and does not produce any result.\\n    The transform definitely fails if `take_else_branch` is specified and the\\n    `else` region is empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"take_else_branch\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n      (`take_else_branch` $take_else_branch^)?\\n      attr-dict\\n       `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.select\",\n    \"summary\": \"Select payload ops by name\",\n    \"description\": \"The handle defined by this Transform op corresponds to all operations among\\n    `target` that have the specified properties. Currently the following\\n    properties are supported:\\n\\n    - `op_name`: The op must have the specified name.\\n\\n    The result payload ops are in the same relative order as the targeted ops.\\n    This transform op reads the `target` handle and produces the `result`\\n    handle. It reads the payload, but does not modify it.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$op_name `in` $target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.sequence\",\n    \"summary\": \"Contains a sequence of other transform ops to apply\",\n    \"description\": \"The transformations indicated by the sequence are applied in order of their\\n    appearance. Each value produced by a transformation within the sequence\\n    corresponds to a group of operations or values in the payload IR, or to a\\n    group of parameters, depending on the type of the value. The behavior of the\\n    operation when a nested transformation produces a silenceable error is\\n    controlled by the `failure_propagation_mode` attribute. When set to\\n    `propagate`, the failure of any nested transformation in the sequence\\n    implies immediate failure of the entire sequence with a silenceable error,\\n    and no further transformation is attempted. When set to `suppress`,\\n    silenceable errors in nested operations are ignored and further\\n    transformations are applied. Beware that even silenceable errors may leave\\n    the payload IR in a state unsuitable for further transformations. It is the\\n    responsibility of the caller to ensure the following transformations are\\n    robust enough when errors are suppressed. Definite errors reported by nested\\n    transformations abort the sequence regardless of the propagation mode. The\\n    set of modes may be extended in the future, e.g., to collect silenceable\\n    errors and report them after attempting all transformations in the sequence.\\n\\n    The entry block of this operation has a single argument that maps to either\\n    the operand if provided or the top-level container operation of the payload\\n    IR, typically the root operation of the pass interpreting the transform\\n    dialect. Operand omission is only allowed for sequences not contained in\\n    another sequence.\\n\\n    The type of the block argument must match the type of the operand. If the\\n    sequence is a top-level transform (without an operand), it can be used for\\n    matching operations if the specified type within the top-level container\\n    payload IR (including the container op itself). E.g.:\\n\\n    ```mlir\\n    transform.sequence failures(propagate) {\\n    ^bb1(%arg1: !transform.any_op):\\n      // %arg1 is mapped to the top-level container of the payload IR, which is\\n      // typically a module\\n    }\\n\\n    transform.sequence failures(propagate) {\\n    ^bb1(%arg1: !transform.op<\\\"func.func>\\\"):\\n      // %arg1 is mapped to all \\\"func.func\\\" ops within and including the\\n      // top-level container of the payload IR. Nested operations that have the\\n      // specified op type are not included.\\n    }\\n    ```\\n\\n    The body of the sequence terminates with an implicit or explicit\\n    `transform.yield` op. The operands of the terminator are returned as the\\n    results of the sequence op.\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"Optional<TransformHandleTypeInterface>\" },\n      { \"name\": \"extra_bindings\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"failure_propagation_mode\", \"type\": \"FailurePropagationMode{propagate|suppress}\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"transform\",\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"custom<SequenceOpOperands>($root, type($root), $extra_bindings, type($extra_bindings)) (`->` type($results)^)? `failures` `(` $failure_propagation_mode `)` attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.smt.constrain_params\",\n    \"summary\": \"Express contraints on params interpreted as symbolic values\",\n    \"description\": \"Allows expressing constraints on params using the SMT dialect.\\n\\n    Each Transform-dialect param provided as an operand has a corresponding\\n    argument of SMT-type in the region. The SMT-Dialect ops in the region use\\n    these params-as-SMT-vars as operands, thereby expressing relevant\\n    constraints on their allowed values.\\n\\n    Computations w.r.t. passed-in params can also be expressed through the\\n    region's SMT-ops. Namely, the constraints express relationships to other\\n    SMT-variables which can then be yielded from the region (with `smt.yield`).\\n\\n    The semantics of this op is that all the ops in the region together express\\n    a constraint on the params-interpreted-as-smt-vars. The op fails in case the\\n    expressed constraint is not satisfiable per SMTLIB semantics. Otherwise the\\n    op succeeds and any one satisfying assignment is used to map the\\n    SMT-variables yielded in the region to `transform.param`s.\\n\\n    ---\\n\\n    TODO: currently the operational semantics per the Transform interpreter is\\n    to always fail. The intention is build out support for hooking in your own\\n    operational semantics so you can invoke your favourite solver to determine\\n    satisfiability of the corresponding constraint problem.\",\n    \"operands\": [\n      { \"name\": \"params\", \"type\": \"Variadic<TransformParamTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<TransformParamTypeInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"`(` $params `)` attr-dict `:` functional-type(operands, results) $body\"\n  },\n  {\n    \"name\": \"transform.sparse_tensor.match.sparse_inout\",\n    \"description\": \"Checks if the payload op has any sparse inputs and/or outputs.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:`\\n    custom<SemiFunctionType>(type($target), type($result), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.split_handle\",\n    \"summary\": \"Splits a handle or parameter into multiple values\",\n    \"description\": \"Splits `handle` into one or multiple handles, as specified by the number\\n    of results of this operation. `handle` should be mapped to as many payload\\n    ops, values or parameteres as there are results. Otherwise, this transform\\n    will fail producing a silenceable failure by default. Each result handle\\n    is mapped to exactly one payload unless specified otherwise by attributes\\n    described below. The order of the payloads is preserved,  i.e., the i-th\\n    payload is mapped to the i-th result handle.\\n\\n    This operation is useful for ensuring a statically known number of\\n    payloads are tracked by the source `handle` and to extract them into\\n    individual handles that can be further manipulated in isolation.\\n\\n    If there are more payloads than results, the remaining payloads are mapped to\\n    the result with index `overflow_result`. If no `overflow_result` is\\n    specified, the transform produces a silenceable failure.\\n\\n    If there are fewer payload ops than results, the transform produces a\\n    silenceable failure if `fail_on_payload_too_small` is set to \\\"true\\\".\\n    Otherwise, it succeeds and the remaining result handles are not mapped to\\n    anything. It also succeeds if `handle` is empty and\\n    `pass_through_empty_handle` is set to \\\"true\\\", regardless of\\n    `fail_on_payload_too_small`.\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"Transform_AnyHandleOrParamType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pass_through_empty_handle\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"fail_on_payload_too_small\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"overflow_result\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.bufferize_to_allocation\",\n    \"description\": \"This transform bufferizes the targeted operation and materializes the\\n    result in a new allocation. It replaces all original uses of the target\\n    result with the newly allocated buffer, wrapped in a\\n    `bufferization.to_tensor` op. It returns a handle to the newly allocated\\n    buffer. Furthermore, it returns a handle that is mapped to all newly created\\n    ops.\\n\\n    Only bufferizable ops are that bufferize to a memory write or have an\\n    aliasing OpOperand (and do not themselves bufferize to an allocation) are\\n    supported. They are bufferized using their BufferizableOpInterface\\n    implementation. E.g.:\\n\\n    ```\\n    %0 = tensor.insert %f into %dest[%pos] : tensor<10xf32>\\n    ```\\n\\n    Is bufferized to:\\n\\n    ```\\n    %alloc = memref.alloc() : memref<10xf32>\\n    bufferization.materialize_in_destination %dest in %alloc\\n    memref.store %f, %alloc[%pos] : memref<10xf32>\\n    %0 = bufferization.to_tensor %alloc restrict writable : memref<10xf32>\\n    ```\\n\\n    Selected ops that bufferize to an allocation (or need special handling) are\\n    also supported:\\n    - `tensor.pad` is lowered to an allocation, followed by a `linalg.fill` and\\n      and a buffer copy (all on memrefs).\\n    - `vector.mask` is bufferized together with its region. The allocation is\\n      placed in front of the `vector.mask` op.\\n\\n    An optional memory space attribute can be specified for the materialized\\n    buffer allocation.\\n\\n    If a memory copy is needed, a \\\"bufferization.materialize_in_destination\\\" is\\n    used when possible. This is an op with tensor semantics that will bufferize\\n    to a memory copy later. Which concrete op will be used for the memory copy\\n    is up to the bufferization framework. Alternatively, a custom memcpy op can\\n    be specified via `memcpy_op`. Currently supported are \\\"memref.copy\\\" and\\n    \\\"linalg.copy\\\". In that case, the source of each memcpy must not have a\\n    custom memory space. Furthermore, because the future buffer layout unknown\\n    for a given tensor, a fully dynamic layout is assumed for best\\n    compatibility. Users should use \\\"bufferization.materialize_in_destination\\\"\\n    when possible.\\n\\n    \\\"memref.alloc\\\" is used for new buffer allocations. The buffer is deallocated\\n    at the end of the block if the \\\"emit_dealloc\\\" attribute is present. If this\\n    attribute is not present, the allocated memory will be leaked. However,\\n    running the `-buffer-deallocation-pipeline` after all bufferization is done\\n    will properly insert the corresponding deallocation(s). Custom allocation\\n    ops can be specified via `alloc_op`. Currently supported are \\\"memref.alloc\\\"\\n    and \\\"memref.alloca\\\". In case of a \\\"memref.alloca\\\", the buffer is not\\n    deallocated.\\n\\n    If `bufferize_destination_only` is set, only the destination operands of the\\n    op are bufferized to a new memory allocation, but not the op itself.\\n\\n    #### Return modes\\n\\n    This operation consumes the `target` handle and produces the\\n    `allocated_buffer` and `new_ops` handles. It always succeeds.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"allocated_buffer\", \"type\": \"Transform_AnyValue\" },\n      { \"name\": \"new_ops\", \"type\": \"Transform_AnyOpType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_space\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"memcpy_op\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"bufferization.materialize_in_destination\\\">\" },\n      { \"name\": \"alloc_op\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"memref.alloc\\\">\" },\n      { \"name\": \"bufferize_destination_only\", \"type\": \"UnitAttr\" },\n      { \"name\": \"emit_dealloc\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.structured.continuous_tile_sizes\",\n    \"description\": \"This transform emits the IR computing the list of (1) exponentially\\n    diminishing tile sizes that are powers of 2; and (2) the corresponding\\n    chunk-sizes the target op should be split into along the given dimension.\\n\\n    For example, for `target_size` 9, and `dimension` 0 for the following\\n    linalg op as target\\n\\n    ```\\n      %0 = linalg.matmul  ins(%arg0, %arg1: tensor<25x34xf32>, tensor<34x25xf32>)\\n                      outs(%arg2: tensor<25x25xf32>)\\n    ```\\n\\n    the first result `tile_sizes` will be a list of diminishing tile sizes\\n    9, 4, 2, 1; and the second result will be a list of chunk sizes\\n    18, 4, 2, 1 that the corresponding dimension should be split into.\\n\\n    After the target op has been split along the given dimension (for example\\n    using multiway split), each chunk can be tiled with the corresponding tile\\n    size in the `tile_sizes` list generated as a result of this op.\\n\\n    Specifying the output type as !transform.param<i64> will cause `tile_sizes`\\n    and `chunk_sizes` to be computed statically and not dynamically.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"tile_sizes\", \"type\": \"TransformAnyParamTypeOrAnyHandle\" },\n      { \"name\": \"chunk_sizes\", \"type\": \"TransformAnyParamTypeOrAnyHandle\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" },\n      { \"name\": \"target_size\", \"type\": \"ConfinedAttr<I64Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` custom<ContinuousTileSizeTypes>(type($target), type($tile_sizes), type($chunk_sizes))\"\n  },\n  {\n    \"name\": \"transform.structured.convert_conv2d_to_img2col\",\n    \"description\": \"Convert linalg.conv_2d_xxx into linalg.generic (for img2col packing)\\n    and linalg.matmul.\\n\\n    A convolution operation can be written as a matrix-matrix multiplication by\\n    unfolding the cross-correlation between input and filter and explicitly copy\\n    overlapped sliding window inputs.\\n\\n    Consider 2D input X with single channel input and output and 2x2 filter W:\\n    ```\\n    [x(0, 0)  , x(0, 1)  , ...,   x(0, n)  ]\\n    [x(1, 0)  , x(1, 1)  , ...,   x(1, n)  ]\\n    [.        ,  .       ,.   ,      .     ]            [w(0, 0), w(0, 1)]\\n    [.        ,  .       , .  ,      .     ]    (conv)  [w(1, 0), w(1, 1)]\\n    [.        ,  .       ,   .,      .     ]\\n    [x(n-1, 0), x(n-1, 1), ..., x(n-1, n-1)]\\n    ```\\n\\n    The packed input data (img2col) is a matrix with |rows| = output spatial\\n    size, |columns| = filter spatial size. To compute the output Y(i, j) we need\\n    to calculate the dot product between filter window at input X(x, y)) and the\\n    filter which will look like the following where r.h.s is the img2col matrix\\n    and l.h.s is the flattned filter:\\n    ```\\n    [x(0,0), x(0,1), x(1,0), x(1,1)]\\n    [x(0,1), x(1,1), x(0,2), x(1,2)] (matmul) [w(0,0), w(0,1), w(1,0), w(1,1)]\\n    [x(0,1), x(1,1), x(0,2), x(1,2)]\\n    [   .  ,    .  ,    .  ,    .  ]\\n    ```\\n\\n    In general for 2D case with (N, H, W, C) input and (Kh, Kw, C, D) filter\\n    and output (N, Ho, Wo, D) the convolution is the following matrix-matrix\\n    multiplication (Ho x Wo, Kh x Kw x C) * (Kh x Kw x C, D) for each input in\\n    the N input. For the case where N > 1 its a batched matrxi-matrix\\n    multplication.\\n\\n    Returns two handles:\\n    - One on the operation that produces the img2col tensor.\\n    - One on the final operation of the sequence that replaces the original\\n      convolution.\\n\\n    #### Return modes:\\n\\n    Returns a definite failure if target is not isolated from above.\\n    Returns a silenceable failure if the pattern application failed.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"img2col_tensor\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.convert_to_loops\",\n    \"description\": \"For operations that implement the `TilingInterface`, and implement\\n    the `generateScalarImplementation` method, lowers the operation to\\n    loops. The return handle points to all generated loops.\\n    Fails if the payload ops cannot be lowered to loops.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.decompose\",\n    \"description\": \"Decomposes higher-dimensional convolution ops into lower-dimensional\\n    equivalents when possible. This operates on both named ops and equivalent\\n    `linalg.generic` ops that have convolution-like structure (as determined\\n    by `inferConvolutionDims`).\\n\\n    The transformation always attempts to specialize the result back to a named\\n    op when possible.\\n\\n    #### Return modes\\n\\n    This operation ignores non-Linalg ops and drops them in the return.\\n    If all the operations referred to by the `target` handle decompose\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure. The return handle points to only the subset of\\n    successfully produced computational operations, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.decompose_interface\",\n    \"description\": \"TODO\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.decompose_winograd_op\",\n    \"description\": \"Decompose winograd operations. It will convert filter, input and output\\n    transform operations into a combination of scf, tensor, and linalg\\n    equivalent operations. Before applying this transform operations, users\\n    need to tile winograd transform operations into supported sizes.\\n\\n    #### Return modes:\\n\\n    This operation fails if `target` is unsupported. Otherwise, the operation\\n    succeeds and returns a handle of the sequence that replaces the original\\n    operations.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.eliminate_empty_tensors\",\n    \"description\": \"Try to eliminate all `tensor.empty` op uses that are anchored on a LinalgOp\\n    within the targeted op.\\n\\n    This op is similar to `bufferization.eliminate_empty_tensors`, but specific\\n    to LinalgOps.\\n\\n    `tensor.empty` ops cannot be bufferized. They can either be converted to\\n    `bufferization.alloc_tensor` or replaced with another tensor (via this\\n    transform). `tensor.empty` does not specify the contents of the returned\\n    tensor so their results can be replaced with arbitrary tensor values as long\\n    as the dimensions match.\\n\\n    This transform looks for `tensor.empty` ops where the SSA use-def chain of\\n    the result ends in a supported LinalgOp (always following the aliasing\\n    OpOperand/OpResult chain). The following LinalgOps are supported:\\n    - Only parallel iterator types.\\n    - The use-def chain ends in an input operand of the LinalgOp.\\n    - The LinalgOp has an unused output operand with the same shape and\\n      indexing map.\\n\\n    Example:\\n\\n    ```\\n    %0 = tensor.empty()\\n    %1 = linalg.matmul ins(...) outs(%0)\\n    %2 = linalg.generic ins(%1) outs(%dest) {\\n      ^bb0(%in: f32, %out: f32):\\n      // out not used\\n    }\\n    ```\\n\\n    Is rewritten with:\\n    ```\\n    %0 = tensor.empty()\\n    %1 = linalg.matmul ins(...) outs(%dest)\\n    %2 = linalg.generic ins(%0) outs(%1) {\\n      ^bb0(%in: f32, %out: f32):\\n      // Use %out instead of %in\\n    }\\n    ```\\n\\n    After this transformation, the \\\"ins\\\" operand has no uses inside the body of\\n    the LinalgOp and can be folded away with existing cleanup patterns.\\n    Afterwards, the tensor::EmptyOp can also fold away, so that the example can\\n    bufferize without an allocation (in the absence of other conflicts).\\n\\n    #### Return modes\\n\\n    This transform reads the target handle and modifies the payload. It does\\n    not produce any handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.structured.flatten_elementwise\",\n    \"description\": \"Flattens the iteration space and (applicable) operands of elementwise\\n    linalg ops to a single dimension.\\n\\n    Returns one handle:\\n    - Flattened linalg operation.\\n\\n    #### Return modes:\\n\\n    Returns a definite failure if target is not isolated from above.\\n    Returns a silenceable failure if the pattern application failed.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.fuse\",\n    \"description\": \"Tiles the operations pointed to by the target handle and fuses their\\n    producers greedily using the options provided as attributes. Tile sizes\\n    and loop interchange permutation can be provided as either static\\n    attributes or dynamic values (transform parameters or payload handles).\\n\\n    If `apply_cleanup` is true then slice canonicalization is applied between\\n    fusion steps. If `use_forall` is true then tiling method generates a\\n    `scf.forall` loop instead of `scf.for` loops.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"tile_sizes\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"tile_interchange\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_tile_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_tile_interchange\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"apply_cleanup\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_forall\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$target oilist(\\n      `tile_sizes` custom<DynamicIndexList>($tile_sizes, $static_tile_sizes) |\\n      `interchange` custom<DynamicIndexList>($tile_interchange, $static_tile_interchange)\\n    )\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.fuse_into_containing_op\",\n    \"summary\": \"Fuse a producer into a containing operation.\",\n    \"description\": \"Fuses the `producer_op` into the `containing_op`.\\n    Returns a handle to the fused ops and the `new_containing_op`.\\n\\n    The producer is typically a slice of a tileable op (i.e., implements\\n    TilingInterface). In that case, this transform computes the accessed\\n    producer slice inside of the containing op (\\\"tile and fuse\\\") and if required,\\n    creates a new containing op with outputs from the fused producer. Otherwise,\\n    the entire producer is cloned inside the containing op (\\\"clone and fuse\\\").\\n\\n    The containing op handle must be associated with exactly one payload op. The\\n    producer op handle may be associated with multiple payload ops. This\\n    transform fuses producers one-by-one, always picking an unspecified producer\\n    that has at least one use inside the containing op among the\\n    producers. A producer can be listed multiple times in the handle.\\n\\n    Note: If a producer has multiple uses inside the containing op, it is\\n    currently tiled and/or cloned multiple times into the containing op.\\n    TODO: Reuse already fused OpResults instead of tiling/cloning a second time\\n    when possible. Fuse producers according to a topological sorting to achieve\\n    the largest amount of reuse.\\n\\n    #### Return modes\\n\\n    If at least one producer could not be fused, this operation produces a\\n    silenceable failure.  This is the case when tiling fails or when no\\n    producer op could be found among the remaining producers that has at least\\n    one use within the containing op. I.e., \\\"producers\\\" that are not consumed\\n    within the containing op are rejected by this operation.\\n\\n    This operation consumes the producer handle.\\n    This operation only reads the containing op handle.\",\n    \"operands\": [\n      { \"name\": \"producer_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"containing_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"fused_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"new_containing_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$producer_op `into` $containing_op attr-dict  `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.generalize\",\n    \"description\": \"Transforms a named structured operation into the generic form with the\\n    explicit attached region.\\n\\n    #### Return modes\\n\\n    This operation ignores non-Linalg ops and drops them in the return.\\n    If all the operations referred to by the `target` handle generalize\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.  The return handle points to only the subset of\\n    successfully produced equivalent generic operations, which can be empty or\\n    contain the original ops if they were already in generic form.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` \\n      custom<SemiFunctionType>(type($target), type($transformed), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.structured.gpu.map_copy_to_threads\",\n    \"description\": \"Targeted mapping of a linalg.copy / tensor.pad operation on tensors to a GPU\\n    thread mapping.\\n\\n    This operation implements a greedy heuristic that determines a good\\n    distribution of threads to break down the copy/pad operation into.\\n    The heuristic is driven by considerations related to the underlying\\n    architecture for which good high-level decisions are needed assuming certain\\n    hardware features. Relevant features are exposed via first-class attributes\\n    to control the behavior of the transformation at a high level.\\n\\n    For now, a single heuristic is implemented and can be extended on a per-need\\n    basis.\\n\\n    #### Return modes\\n\\n    This operation fails definitely if there is an unsupported op (i.e., not\\n    linalg.copy / tensor.pad) among the targeted op. Otherwise, the operation\\n    always succeeds and returns a handle to the relevant tiled linalg.copy /\\n    tensor.pad op and the enclosing scf.forall op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"forall_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"tiled_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"total_num_threads\", \"type\": \"I64Attr\" },\n      { \"name\": \"desired_bit_alignment\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `total_num_threads` `=` $total_num_threads\\n    `desired_bit_alignment` `=` $desired_bit_alignment\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.hoist_pad\",\n    \"description\": \"Hoist the tensor.pad target operation by at most the given number of loops.\\n    Optionally apply the transpose attribute to the inner dimensions.\\n\\n    TODO: In the future, we should consider rewriting as a linalg.pack after\\n    hoisting since this abstraction is now available.\\n    TODO: Maybe also return the linalg.generic transpose created at some point.\\n\\n    #### Return modes\\n\\n    This operation ignores non-tensor.pad ops and drops them in the result.\\n    If any non-tensor.pad is passed, the transform emits a silenceable failure.\\n\\n    If all the operations referred to by the `target` handle padproperly, the\\n    transform succeeds. Otherwise the transform produces a silenceable failure.\\n\\n    The return handle points to only the subset of successfully hoisted\\n    tensor.pad operations, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_loops\", \"type\": \"I64Attr\" },\n      { \"name\": \"transpose\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `by` $num_loops `loops`\\n    (`,` `transpose` `by` $transpose^)?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.hoist_pad.build_packing_loop_nest\",\n    \"description\": \"Helper transform used to hoist a tensor.pad target operation. This operation\\n    creates the packing loop nest required by the hoist_pad operation and makes\\n    that functionality available independently.\\n\\n    TODO: In the future, we should consider rewriting as a linalg.pack after\\n    hoisting since this abstraction is now available.\\n\\n    #### Return modes\\n\\n    This operation ignores non-tensor.pad ops and drops them in the result.\\n    If any non-tensor.pad is passed, the transform emits a silenceable failure.\\n\\n    The return handle points to only the subset of successfully created packing\\n    loop nests, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loop\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"packing_loop\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `above` $loop\\n    (`,` `transpose` `by` $transpose^)?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.hoist_redundant_vector_broadcasts\",\n    \"description\": \"Hoist vector.extract / vector.broadcasts pairs out of immediately\\n    enclosing scf::ForOp iteratively.\\n\\n    #### Return modes:\\n\\n    The operation always succeeds and returns a handle to the transformed\\n    function op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.hoist_redundant_vector_transfers\",\n    \"description\": \"Hoist vector.transfer_read / vector.transfer_write pairs out of immediately\\n    enclosing scf::ForOp iteratively, if the following conditions are true:\\n       1. The 2 ops access the same memref with the same indices.\\n       2. All operands are invariant under the enclosing scf::ForOp.\\n       3. No uses of the memref either dominate the transfer_read or are\\n       dominated by the transfer_write (i.e. no aliasing between the write and\\n       the read across the loop)\\n\\n    WARNING: This hoisting does not model parallelism and is generally incorrect\\n    when used on distributed loops with memref semantics!\\n    TODO: obsolete and should be retired.\\n\\n    #### Return modes:\\n\\n    The operation always succeeds and returns a handle to the transformed\\n    function op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"verify_non_zero_trip\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.insert_slice_to_copy\",\n    \"description\": \"Targeted rewrite of an tensor.insert_slice to linalg.copy.\\n    This is useful to materialize copies explicitly before bufferization and\\n    transform them, avoiding the need to rediscover them after bufferization.\\n\\n    If the insert_slice source is already a linalg.copy, only return the source\\n    op (i.e. do not create an additional linalg.copy op).\\n\\n    #### Return modes:\\n\\n    The operation always succeeds and returns a handle to the relevant\\n    linalg.copy op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.interchange\",\n    \"description\": \"Interchanges the iterators of the operations pointed to by the target handle\\n    using the iterator interchange attribute.\\n\\n    #### Return modes\\n\\n    This operation ignores non-linalg::Generic ops and drops them in the return.\\n    This operation fails if the interchange attribute is invalid.\\n    If all the operations referred to by the `target` handle interchange\\n    properly, the transform succeeds.\\n    If any interchange fails, the transform produces a definite failure.\\n    The return handle points to only the subset of successfully produced\\n    interchanged operations, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iterator_interchange\", \"type\": \"ConfinedAttr<DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>, [DenseArrayNonNegative<DenseI64ArrayAttr>]>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    (`iterator_interchange` `=` $iterator_interchange^)? attr-dict\\n    `:` custom<SemiFunctionType>(type($target), type($transformed), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.structured.linalg_copy_to_memref\",\n    \"description\": \"Targeted rewrite of a linalg.copy on memrefs to a memref.copy.\\n    This is useful when bufferizing copies to a linalg.copy, later applying some\\n    transformations, and then rewriting the copy into a memref.copy.\\n    If the element types of the source and destination differ, or if the source\\n    is a scalar, the transform produces a silenceable failure.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.lower_pack\",\n    \"description\": \"Rewrite a linalg.pack into tensor.pad + tensor.expand_shape + linalg.transpose.\\n\\n    #### Return modes\\n\\n    This operation ignores non-pack ops and drops them in the return. This\\n    operation produces a silenceable failure if the rewrite fails for any\\n    reason. If all the operations referred to by the `target` are rewritten,\\n    the transform succeeds. Return handles to the newly produced pad,\\n    expand_shape and transpose ops.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Transform_ConcreteOpType<linalg.pack>\" }\n    ],\n    \"results\": [\n      { \"name\": \"pad_op\", \"type\": \"Transform_ConcreteOpType<tensor.pad>\" },\n      { \"name\": \"expand_shape_op\", \"type\": \"Transform_ConcreteOpType<tensor.expand_shape>\" },\n      { \"name\": \"transpose_op\", \"type\": \"Transform_ConcreteOpType<linalg.transpose>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lowerPadLikeWithInsertSlice\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.lower_unpack\",\n    \"description\": \"Lower a linalg.unpack into empty + linalg.transpose + tensor.collapse_shape +\\n    tensor.extract_slice + linalg.copy.\\n\\n    #### Return modes\\n\\n    This operation ignores non-unpack ops and drops them in the return. This\\n    operation produces a silenceable failure if the rewrite fails for any\\n    reason. If all the operations referred to by the `target` are rewritten,\\n    the transform succeeds. Return handles to the newly produced empty,\\n    transpose, collapse_shape, extract_slice and copy ops.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"Transform_ConcreteOpType<linalg.unpack>\" }\n    ],\n    \"results\": [\n      { \"name\": \"empty_op\", \"type\": \"Transform_ConcreteOpType<tensor.empty>\" },\n      { \"name\": \"transpose_op\", \"type\": \"Transform_ConcreteOpType<linalg.transpose>\" },\n      { \"name\": \"collapse_shape_op\", \"type\": \"Transform_ConcreteOpType<tensor.collapse_shape>\" },\n      { \"name\": \"extract_slice_op\", \"type\": \"Transform_ConcreteOpType<tensor.extract_slice>\" },\n      { \"name\": \"copy_op\", \"type\": \"Transform_ConcreteOpType<linalg.copy>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lowerUnpadLikeWithExtractSlice\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.match\",\n    \"description\": \"Match op with the specified constraints, within the target op.\\n\\n    The following constraints are supported:\\n      - interface: an optional MatchInterfaceEnum specifying an enum\\n        representation for an interface to target.\\n      - ops: an optional StrArrayAttr specifying the concrete name of an op.\\n        Multiple names can be specified. Matched ops must have one of specified\\n        names.\\n      - attribute: the matched op must have all specified attributes (with their\\n        specified values).\\n      - filter_result_type: the matched op must return exactly this one type.\\n      - filter_operand_types: all the operands of the matched op must must be of\\n        this type. If more than a type is specified, then the length of the list\\n        must be equal to the number of operands in the matched op, and the match\\n        will succeed only if the operand types match all the types in the list\\n        in the order in which they are specified.\\n\\n    Note: Only ops that satisfy all specified constraints are matched.\\n\\n    TODO: Extend with regions to allow a limited form of constraints.\\n\\n    #### Return modes\\n\\n    This op traverses the ops nested under `target` and returns the handles to\\n    all the operations that match the requirements.\\n\\n    This op fails if the target is not a handle to exactly one operation.\\n    Otherwise it succeeds.\\n\\n    This operation does not consume the target handle and produces new handles:\\n    it is a navigation op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ops\", \"type\": \"OptionalAttr<TypedArrayAttrBase<StrAttr>>\" },\n      { \"name\": \"interface\", \"type\": \"OptionalAttr<MatchInterfaceEnum{LinalgOp|TilingInterface|LoopLikeInterface}>\" },\n      { \"name\": \"op_attrs\", \"type\": \"OptionalAttr<DictionaryAttr>\" },\n      { \"name\": \"filter_result_type\", \"type\": \"OptionalAttr<TypeAttr>\" },\n      { \"name\": \"filter_operand_types\", \"type\": \"OptionalAttr<TypedArrayAttrBase<TypeAttr>>\" }\n    ],\n    \"assemblyFormat\": \"(`ops` `{` $ops^ `}`)?\\n    (`interface` `{` $interface^ `}`)?\\n    (`attributes` $op_attrs^)?\\n    (`filter_result_type` `=` $filter_result_type^)?\\n    (`filter_operand_types` `=` $filter_operand_types^)?\\n    `in` $target attr-dict\\n    `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.multitile_sizes\",\n    \"description\": \"Emits the IR computing the tile sizes `s1` and `s2` such that:\\n\\n      - there exists a combination of `n` tiles of size `s1` and `m` tiles of\\n        size `s2` that covers the entirety of the iteration space `dimension` of\\n        the target structured op;\\n      - `s1`, `s2` is less than or equal to `target_size`;\\n      - `s1` and `s2` are divisible by `divisor.\\n\\n    For example, for a dimension of size 54 with target size 12 and divisor 2,\\n    this can emit the IR computing the tile size 10, used for 3 tiles, and 12,\\n    used for 2 tiles, totally 10*3 + 12*2 = 54. Note that when the divisor does\\n    not divide the original dimension size, it is impossible to compute such\\n    tile sizes. An assertion is emitted to guard against this in the dynamic\\n    case.\\n\\n    Expects the target size and the divisor to be strictly positive. Folds the\\n    IR as much as possible, normally obtaining constant sizes and numbers of\\n    tiles for a statically known dimension.\\n\\n    This does *not* consume the target handle and produces three handles each\\n    pointing to single-result index-typed operations (which may be arithmetic\\n    constant operations) defining the two respective tile sizes and the product\\n    of the first tile size with the number of tiles of that size (useful for\\n    splitting the iteration space).\\n\\n    This operation composes with the regular tiling when applied per-dimension:\\n\\n    ```mlir\\n    %sz1, %sz2, %split = structured.multitile_sizes %target\\n                         { target_size = 10, dimension = 1 }\\n                       : !transform.any_op, !transform.param<i64>,\\n                         !transform.param<i64>, !transform.param<i64>\\n    %handles = structured.split %target after %split { dimension = 1 }\\n                : !transform.any_op, !transform.param<i64>\\n    %low, %high = transform.split_handle %handles : (!transform.any_op)\\n                      -> (!transform.any_op, !transform.any_op)\\n    %tiled_low, %loop1 = structured.tile_using_for %low [0, %sz1]\\n                       : (!transform.any_op, !transform.param<i64>)\\n                      -> (!transform.any_op, !transform.any_op)\\n    %tiled_high, %loop2 = structured.tile_using_for %high [0, %sz2]\\n                        : (!transform.any_op, !transform.param<i64>)\\n                       -> (!transform.any_op, !transform.any_op)\\n    %common = merge_handles %tiled_low, %tiled_high : !transform.any_op\\n\\n    %sz3, %sz4, %split = structured.multitile_size %target\\n                         { target_size = 42, dimension = 0 }\\n                       : !transform.any_op, !transform.any_op,\\n                         !transform.any_op, !transform.any_op\\n    %sz3r, %sz4r, %splitr = replicate num(%common) %sz3, %sz4, %splitr\\n             : !transform.any_op, !transform.any_op, !transform.any_op\\n    structured.split %common after %splitr { dimension = 0 }\\n             : !transform.any_op, !transform.any_op\\n    // ...\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"low_size\", \"type\": \"TransformAnyParamTypeOrAnyHandle\" },\n      { \"name\": \"high_size\", \"type\": \"TransformAnyParamTypeOrAnyHandle\" },\n      { \"name\": \"split_point\", \"type\": \"TransformAnyParamTypeOrAnyHandle\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"target_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"divisor\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` custom<MultitileSizesTypes>(type($target), type($low_size), type($high_size), type($split_point))\"\n  },\n  {\n    \"name\": \"transform.structured.pack\",\n    \"description\": \"Pack a LinalgOp by applying a data tiling transformation on the op and\\n    packing the operands according to the `packed_sizes` specification.\\n\\n    Iterator dimensions are tiled in their canonical order in the op spec.\\n    Operands are packed according to the same canonical order of the op iterator\\n    dimensions.\\n\\n    Specifying a packed size of 0 for an iterator removes it from consideration\\n    for packing.\\n\\n    `linalg.pack` (resp. `linalg.unpack`) operations are inserted for the operands\\n    (resp. results) that need to be packed (resp. unpacked) according to the\\n    `packed_sizes` specification.\\n\\n    #### Example\\n\\n    Consider a `linalg.matmul` with indexing maps:\\n    ```\\n      //              M   N   K       M   K\\n      // affine_map<(d0, d1, d2) -> (d0, d2)>\\n      //                              K   N\\n      // affine_map<(d0, d1, d2) -> (d2, d1)>\\n      //                              M   N\\n      // affine_map<(d0, d1, d2) -> (d0, d1)>\\n      %0 = linalg.matmul  ins(%A, %B: tensor<?x?xf32>, tensor<?x?xf32>)\\n                         outs(    %C: tensor<?x?xf32>)\\n    ```\\n\\n    Specifying packed_sizes [2, 3, 4] results in tiling the iterator dimensions\\n    M, N and K, in this order, in both the op and its operands.\\n    ```\\n      //              M   N   K   m   n   k       M   K   m   k\\n      // affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d2, d3, d5)>\\n      //                                          K   N   n   k\\n      // affine_map<(d0, d1, d2, d3, d4, d5) -> (d2, d1, d4, d5)>\\n      //                                          M   N   m   n\\n      // affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d3, d4)>\\n      %0 = linalg.generic_representing_some_higher_d_matmul\\n            ins(%A, %B: tensor<?x?x2x4xf32>, tensor<?x?x4x3xf32>)\\n           outs(    %C: tensor<?x?x2x3xf32>)\\n    ```\\n    In particular, note that the second operand `B` has shape `KxNxnxk` (and not\\n    `KxNxkxn` as one could expect by looking **only** at the operand).\\n\\n    Other layouts can be obtained unsurprisingly from this canonical\\n    transformation by composing the resulting operation with a\\n    `transform.structured.pack_transpose` op.\\n    This composition allows separating concerns and composes better compared\\n    to adding additional permutation attributes to this transform op.\\n\\n    #### Return modes\\n\\n    This operation applies to a single Linalg op, otherwise it fails.\\n    This operation may produce a definite failure if the packing fails for any\\n    reason.\\n\\n    The returned handle point to the packed LinalgOp.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"packed_sizes\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"packed_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_packed_sizes\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `packed_sizes` `=` custom<DynamicIndexList>($packed_sizes,\\n                                                $static_packed_sizes)\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.pack_greedily\",\n    \"description\": \"Target a Linalg op and rewrite it into packed LinalgOp form by trying to\\n    infer whether a known suboperation is embedded\\n\\n    Different packing strategies are applied in order, when one applies\\n    successfully, the transform returns:\\n      1. Matmul packing: Try to infer a matmul operation embedded in the target op.\\n         Specifically, this looks for 2 parallel dimensions that participate in\\n         an outer-product and 1 reduction dimension.\\n         These dimensions are referred as (m, n, k) to match canonical matmul\\n         terminology.\\n\\n         The packed sizes for (m, n, k) are specified by `matmul_packed_sizes`\\n         and the optional `matmul_padded_sizes_next_multiple_of`.\\n         When an entry `matmul_packed_sizes[i]` is non-0, the corresponding\\n         dimension is packed by `matmul_packed_sizes[i]`.\\n         Otherwise, the dimension is merely padded to the next multiple of\\n         `matmul_padded_sizes_next_multiple_of[i]`.\\n\\n         `matmul_padded_sizes_next_multiple_of` is optional and is expected to\\n         either be empty or of size `3`, matching the size of `matmul_packed_sizes`.\\n         For each individual element of `matmul_packed_sizes` and\\n         `matmul_padded_sizes_next_multiple_of`, only one of them is allowed to\\n         be non-zero.\\n\\n         The ordering of the packed dimensions (mm, nn, kk) is specified by the\\n         `matmul_inner_dims_order` attribute.\\n\\n    Packing occurs as follows:\\n      1. Find the dimensions to pack according to the strategy.\\n      2. The target is converted to linalg.generic form.\\n      3. An interchange transform is applied to isolate the dimensions to pack as\\n         the most minor indexing dimensions of the linalg.generic. The most minor\\n         dimensions are themselves ordered according to `inner_dims_order`.\\n      4. An elementwise traversal of `matmul_packed_sizes` and\\n         `matmul_padded_sizes_next_multiple_of` is performed and for each\\n         dimension `d`, either pack to `matmul_packed_sizes[d]` or pad to the\\n         `matmul_padded_sizes_next_multiple_of[d]`.\\n      5. Packing/padding is performed by the amounts determined in step 4. and\\n         following `inner_dims_order`.\\n\\n    By normalizing the most minor dimensions to `inner_dims_order`, the transform\\n    guarantees that packing immediately generates inner dimensions in a desirable\\n    layout.\\n\\n    Outer dimension layout permutations are not controlled by this transform op\\n    at the moment and can be obtained by composing with the pack_transpose\\n    transformation.\\n\\n    #### Return modes\\n\\n    This operation ignores non-Linalg ops and drops them in the return.\\n    It returns the list of packed Linalg ops or the original op when all available\\n    packing strategies failed to apply.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"matmul_packed_sizes\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"packed_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_matmul_packed_sizes\", \"type\": \"ConfinedAttr<DefaultValuedAttr<DenseI64ArrayAttr, {}>, [DenseArrayCount<3>]>\" },\n      { \"name\": \"matmul_padded_sizes_next_multiple_of\", \"type\": \"ConfinedAttr<DefaultValuedAttr<DenseI64ArrayAttr, {}>, [Attr<Or<[ DenseArrayCount < 0 > . predicate, DenseArrayCount < 3 > . predicate ]>, with 0 or 3 elements>]>\" },\n      { \"name\": \"matmul_inner_dims_order\", \"type\": \"ConfinedAttr<DefaultValuedAttr<DenseI64ArrayAttr, {}>, [DenseArrayCount<3>]>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    oilist(\\n      `matmul_packed_sizes` `=` custom<DynamicIndexList>($matmul_packed_sizes,\\n                                                         $static_matmul_packed_sizes)\\n      (`matmul_padded_sizes_next_multiple_of` `=`\\n        $matmul_padded_sizes_next_multiple_of^)?\\n      `matmul_inner_dims_order` `=` $matmul_inner_dims_order\\n    )\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.pack_transpose\",\n    \"description\": \"Apply a transposition to a single `linalg.pack` (resp. `linalg.unpack`) and\\n    update the `linalg.generic` op that consumes (resp. produces) the operation.\\n\\n    This transform allows composing a simple `structured.pack` with additional\\n    transpositions to e.g. match the data format required by a specific library\\n    call or ISA instruction.\\n\\n    The transpose spec must specify at least one of `outer_perm` or `inner_perm`\\n    attributes, which will act upon the `outer_dims_perm` or `inner_dims_pos` of\\n    the specified `linalg.pack` or `linalg.unpack` op.\\n\\n    If the `target` of this op is a `linalg.pack` then a new `tensor.empty` will\\n    be created along with transposed versions of the `linalg.pack` and the\\n    consuming `linalg.generic`, which is expected to be the sole consumer.\\n\\n    If the `target` of this op is a `linalg.unpack` then the whole pack / compute\\n    / unpack chain will be transposed and transposed clones of `linalg.pack`,\\n    the consuming `linalg.generic` and the tail `linalg.pack` will be created.\\n\\n    #### Return modes\\n\\n    This operation targets a single `linalg.pack` / `linalg.unpack` op and a\\n    single matching `linalg.generic` that consumes / produces the op. Otherwise,\\n    it produces a silenceableFailure.\\n\\n    This operation may produce a silenceableFailure if the transpose spec is\\n    ill-formed (i.e. `outer_perm` or `inner_perm` are not permutations of the\\n    proper rank) or if the transposition of all involved operations fails for any\\n    reason.\\n\\n    This operation returns 3 handles, one to the transformed LinalgOp, one to\\n    the transformed `linalg.pack` and one to the transformed `linalg.unpack`.\\n    The last handle for `linalg.unpack` is empty if `target_pack_or_unpack_op`\\n    was not itself a `linalg.unpack`.\",\n    \"operands\": [\n      { \"name\": \"target_pack_or_un_pack_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"target_linalg_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"packed_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"pack_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"un_pack_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outer_perm\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"inner_perm\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target_pack_or_un_pack_op\\n    `with_compute_op` `(` $target_linalg_op `)`\\n    (`outer_perm` `=` $outer_perm^ )?\\n    (`inner_perm` `=` $inner_perm^ )?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.pad\",\n    \"description\": \"Pads the operations pointed to by the target handle using the options\\n    provides as operation attributes. The operation returns a handle to the\\n    padded operation and to the padding operation (\\\"tensor.pad\\\").\\n\\n    To preserve tensor SSA use-def chains, the unpadded result is copied back to\\n    the original destination tensor of the targeted op. The op that copies back\\n    the result can be customized with `copy_back_op`:\\n\\n    * \\\"bufferization.materialize_in_destination\\\" (default)\\n    * \\\"linalg.copy\\\"\\n    * \\\"none\\\" (no copy back)\\n\\n    #### Return modes\\n\\n    This operation ignores non-Linalg ops and drops them in the return.\\n    This operation may produce a definite failure if the padding fails for any\\n    reason.\\n\\n    If all the operations referred to by the `target` handle pad\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.\\n    The return handle points to only the subset of successfully produced\\n    padded operations, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"pad_to_multiple_of\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"padded\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"pad\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"copy\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding_values\", \"type\": \"DefaultValuedAttr<ArrayAttr, {}>\" },\n      { \"name\": \"padding_dimensions\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"static_pad_to_multiple_of\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"nofold_flags\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"transpose_paddings\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<TypedArrayAttrBase<I64Attr>, array of arrays of i64>, {}>\" },\n      { \"name\": \"copy_back_op\", \"type\": \"DefaultValuedAttr<StrAttr, ::mlir::bufferization::MaterializeInDestinationOp::getOperationName()>\" },\n      { \"name\": \"use_prescribed_tensor_shapes\", \"type\": \"DefaultValuedAttr<UnitAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$target \\n    (`pad_to_multiple_of` custom<DynamicIndexList>($pad_to_multiple_of, $static_pad_to_multiple_of)^)?\\n    (`use_prescribed_tensor_shapes` $use_prescribed_tensor_shapes^)?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.pad_tiling_interface\",\n    \"description\": \"Pads the **iteration domain** of the operations pointed to by the target\\n    handle using the options provided as operation attributes. Padding the\\n    iteration domain induces a padding of the operands that is consistent\\n    across the op semantics and, unlike for simple elementwise ops, may not be\\n    trivially deducible or specifiable on operands only (e.g. convolutions).\\n    Currently, only a limited set of projected permutation maps are supported.\\n    \\n    The specification of `padding_sizes` follows that of `tile_sizes` during\\n    tiling: the value \\\"0\\\" on a particular iterator encode \\\"no padding\\\". Like in\\n    the case of tiling, an automatic completion by 0 to the operation rank\\n    occurs.\\n    \\n    This transformation returns a handle to the padded operation and to the\\n    padding operation (\\\"tensor.pad\\\").\\n\\n    TODO: in the future this should be moved out of a specific Linalg\\n    implementation file and into a more general \\\"Structured\\\" file.\\n\\n    #### Return modes\\n\\n    This operation ignores non-IndexingMapOpInterface ops and drops them in the\\n    return. In the future, this operation will support all TilingInterfaceOps\\n    for which the contract between iteration domain and operands can be \\n    reified.    \\n\\n    This operation may produce a definite failure if the padding fails for any\\n    reason.\\n\\n    If all the operations referred to by the `target` handle pad properly, the\\n    transform succeeds. Otherwise the transform produces a silenceable failure.\\n    The return handle points to only the subset of successfully produced\\n    padded operations, which can be empty.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"padding_sizes\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"padded\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"pad\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding_values\", \"type\": \"DefaultValuedAttr<ArrayAttr, {}>\" },\n      { \"name\": \"static_padding_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"pad_to_multiple_of\", \"type\": \"DefaultValuedAttr<UnitAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `to`\\n    (`padding_sizes` custom<DynamicIndexList>($padding_sizes, $static_padding_sizes)^)?\\n    (`pad_to_multiple_of` $pad_to_multiple_of^)?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.promote\",\n    \"description\": \"Promotes the specified operands of the target into a separate memory buffer.\\n\\n    At this point, this transform does not allow customizing alloc/dealloc\\n    functions nor the behavior on copy in/out operations.\\n\\n    #### Return modes\\n\\n    This operation applies to a single Linalg op that satisfies the\\n    `promoteSubviewsPrecondition`, otherwise it fails.\\n\\n    If the operations referred to by the `target` handle promote\\n    properly, the transform succeeds.\\n\\n    When successful, the return handle points to the $target operation that\\n    was modified inplace.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operands_to_promote\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"use_full_tile_buffers\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<BoolAttr>, {}>\" },\n      { \"name\": \"use_full_tiles_by_default\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_original_subview_size\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_alloca\", \"type\": \"UnitAttr\" },\n      { \"name\": \"memory_space\", \"type\": \"OptionalAttr<AnyAttr>\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:`\\n    custom<SemiFunctionType>(type($target), type($transformed), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.structured.promote_tensor\",\n    \"summary\": \"Request a tensor value to live in a specific memory space after bufferization\",\n    \"description\": \"Requests that a tensor value lives in a specific memory space for its\\n    lifetime. This is achieved by allocating a new tensor in the desired\\n    memory space with `bufferization.alloc_tensor` and optionally materializing\\n    the source value into that allocation with\\n    `bufferization.materialize_in_destination`. All uses of the original value\\n    are then redirected to the promoted value.\\n\\n    The generated code for promoting tensor value %0 resembles the following:\\n\\n      %1 = bufferization.alloc_tensor(<dynamic dims of %0>)\\n           { memory_space = memory_space }\\n      // Note: the materialization is omitted if %0 is never read and is only\\n      // written into (i.e., it behaves as a result tensor).\\n      %2 = bufferization.materialize_in_destination %0 in %1\\n      // ...\\n      <all users of %0 now use %2 instead>\\n\\n    Deallocation is not handled by this transform.\\n\\n    Return modes:\\n    - Produces a silenceable failure if the given handle does not point to\\n      tensor-typed values.\\n    - Succeeds otherwise and returns a handle to the promoted value(s), i.e.,\\n      the result of materialization if present and the allocation otherwise.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"promoted\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_space\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"(`to` $memory_space^)? $tensor attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"transform.structured.replace\",\n    \"description\": \"Replace all `target` payload ops with the single op that is contained in\\n    this op's region. All targets must have zero arguments and must be isolated\\n    from above.\\n\\n    This op is for debugging/experiments only.\\n\\n    #### Return modes\\n\\n    This operation consumes the `target` handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"replacement\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict-with-keyword regions `:`\\n      custom<SemiFunctionType>(type($target), type($replacement), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.structured.rewrite_in_destination_passing_style\",\n    \"description\": \"Rewrite a supported tensor operation that is not in destination-passing style\\n    into a form that is in destination-passing style.\\n    Currently supported operations are:\\n      - tensor.pad\\n      - tensor.generate\\n      - tensor.from_elements\\n    This dichotomy hints at a future interface, for now the implementation just\\n    switches between different implementation.\\n\\n    #### Return modes\\n\\n    This operation ignores non-unsupported ops and drops them from the return.\\n    If all the operations referred to by the `target` handle generalize\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.\\n    The return handle points to a subset of successfully produced operations:\\n      - `tensor.pad` case, the returned handle points to the tensor.insert_slice.\\n      - `tensor.generate` case, the returned handle points to the linalg.generic.\\n      - `tensor.from_elements` case, the returned handle points to the last\\n        `tensor.insert`.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict\\n    `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.scalarize\",\n    \"description\": \"Indicates that ops of a specific kind in the given function should be\\n    scalarized (i.e. their dynamic dimensions tiled by 1).\\n\\n    #### Return modes:\\n\\n    This operation ignores non-Linalg ops and drops them in the return.\\n    This operation produces definite failure if the scalarization fails for any\\n    reason.\\n    If all the operations referred to by the `target` handle scalarize\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.\\n\\n    The return handle points to only the subset of successfully produced\\n    tiled-by-1 operations, which can be empty.\\n\\n    This operation does not return handles to the tiled loop.\\n    We make this design choice because it is hard to know ahead of time the\\n    number of loops that will be produced (it depends on the number of dynamic\\n    dimensions after multiple transformations have been applied).\\n    Loops can always be recovered by navigating from the tiled operations if\\n    needed.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:`\\n    custom<SemiFunctionType>(type($target), type($result), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.structured.specialize\",\n    \"description\": \"Transforms a generic operation into the equivalent named form.\\n\\n    #### Return modes\\n\\n    This operation ignores non-Linalg ops and drops them in the return. If all\\n    the operations referred to by the `target` handle specialize, the transform\\n    succeeds; otherwise, the operation produces a silenceable failure.  The return\\n    handle points to only the subset of successfully produced equivalent named\\n    operations, which can be empty or contain the original ops if they were already\\n    in named form. The supported specialization to named Linalg operations are:\\n    - linalg.copy of any rank.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` \\n      custom<SemiFunctionType>(type($target), type($transformed), \\\"false\\\")\"\n  },\n  {\n    \"name\": \"transform.structured.split\",\n    \"description\": \"Splits the given `target` op into two or more complementary\\n    parts, which combined cover the entire iteration domain of the original op.\\n    The split is performed along the iteration space dimension provided as\\n    chunk size attribute specifying the size of the lower part; the remaining\\n    range in the iteration space is assigned as the upper part. In case of\\n    dimension overflow, the transformation fails. The split is performed at the\\n    dimension iterator value specified as either the static chunk size\\n    attribute when it is known at transform IR construction time or\\n    as the handle to an operation producing a single index-typed value\\n    when it is computed by payload IR. In the latter case, the chunk size\\n    point must be set to `ShapedType::kDynamic` and the dynamic size handle\\n    must point to as many value-producing operations as there are structured\\n    operations pointed to by the target handle.\\n\\n    The operation consumes the target handle, but preserves the chunk size\\n    handle if provided. Without the `multiway` attribute, it produces a\\n    new handle that is a list of the two parts of the structured op after\\n    splitting, whose lower index part corresponding to the part with lower\\n    iteration space indices.\\n\\n    Multiway split mode is enabled by specifying the `multiway` attribute.\\n    In this mode a single `target` op is split into multiple parts covering\\n    the iteration space of the specified dimension. `static_chunk_sizes` and\\n    `dynamic_chunk_sizes` in this case is a list of chunk sizes that the given\\n    dimension should be split into. With `multiway` it also produces a handle;\\n    The result handle is a list of the multiple parts of the structured op\\n    after splitting, where the target dimensions for each linalg op in the\\n    list corresponds to the chunk sizes specfied in the input split list.\\n    If the chunk sizes do not cover the entire iteration space, the leftover\\n    chunk is the last payload in the result handle.\\n\\n    As the result handle is most of time a list, an `transform.split_handle`\\n    is needed to access individual handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"dynamic_chunk_sizes\", \"type\": \"Optional<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"split_list\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I64Attr\" },\n      { \"name\": \"static_chunk_sizes\", \"type\": \"I64Attr\" },\n      { \"name\": \"multiway\", \"type\": \"UnitAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"transform.structured.split_reduction\",\n    \"description\": \"Indicates that the given `target` op should be transformed with the\\n    `splitReduction` transformation and split factor provided as attribute.\\n\\n    The `splitReduction` transformation splits the first single linalg op\\n    reduction into a parallel and reduction dimension.\\n    A new `linalg.generic` op is created to perform the rest of the reduction.\\n\\n    The transformation supports different configurations attributes:\\n      - split_factor: the factor by which to split (i.e. the size of the\\n        remaining reduction after splitting).\\n      - insert_split_dimension: the dimension in the temporary tensor into\\n        which the new parallel dimension is inserted.\\n      - inner_parallel: specifies whether the parallel dimension is before or\\n        after the reduction dimension in the splitting op.\\n      - use_scaling_algorithm: whether to use a scaling based formulation that\\n        does not create an ExpandShapeOp (default: do not use scaling)\\n      - use_alloc: whether to use an alloc op to allocate the temporary\\n        tensor (default: do not use alloc op)\\n\\n    #### Return modes\\n\\n    This operation ignores non-Linalg ops and drops them in the return.\\n    This operation produces a definite failure if the splitting fails for any\\n    reason.\\n\\n    If all the operations referred to by the `target` handle split\\n    properly, the transform succeeds. Otherwise the transform produces a\\n    silenceable failure.  The 4 returned handles points to only the subset of\\n    successfully produced computational operations, which can all be empty.\\n    This 4 returned handles point to:\\n      - the init op (or tensor_alloc op if use_alloc = true),\\n      - the fill op used to initialize the neutral element,\\n      - the split op and\\n      - the result-combining op.\\n\\n    #### Example (default: `use_scaling_algorithm = false, use_alloc = false`):\\n\\n    ```\\n      %r = linalg.generic {indexing_maps = [affine_map<(d0) -> (d0)>,\\n                                            affine_map<(d0) -> ()>],\\n            iterator_types = [\\\"reduction\\\"]}\\n      ins(%in : tensor<32xf32>)\\n      outs(%out : tensor<f32>) {\\n      ^bb0(%arg1: f32, %arg2: f32):\\n        %y = arith.addf %arg1, %arg2 : f32\\n        linalg.yield %y : f32\\n      } -> tensor<f32>\\n    ```\\n\\n    is split into:\\n\\n    ```\\n      %cst = arith.constant 0.000000e+00 : f32\\n      %0 = tensor.expand_shape %in [[0, 1]] : tensor<32xf32> into tensor<4x8xf32>\\n      %1 = tensor.empty() : tensor<4xf32>\\n      %2 = linalg.fill ins(%cst : f32) outs(%1 : tensor<4xf32>) -> tensor<4xf32>\\n      %3 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,\\n                                            affine_map<(d0, d1) -> (d0)>],\\n        iterator_types = [\\\"parallel\\\", \\\"reduction\\\"]}\\n        ins(%0 : tensor<4x8xf32>) outs(%2 : tensor<4xf32>) {\\n        ^bb0(%arg3: f32, %arg5: f32):\\n        %5 = arith.addf %arg3, %arg4 : f32\\n        linalg.yield %5 : f32\\n      } -> tensor<4xf32>\\n      %r = linalg.generic {indexing_maps = [affine_map<(d0) -> (d0)>,\\n                                            affine_map<(d0) -> ()>],\\n        iterator_types = [\\\"reduction\\\"]}\\n        ins(%3 : tensor<4xf32>) outs(%out : tensor<f32>) {\\n        ^bb0(%arg3: f32, %arg4: f32):\\n        %5 = arith.addf %arg3, %arg4 : f32\\n        linalg.yield %5 : f32\\n      } -> tensor<f32>\\n    ```\\n\\n    #### Example (`use_scaling_algorithm = true, use_alloc = true`):\\n\\n    Instead of introducing an ExpandShapeOp, this scaling-based implementation\\n    rewrites a reduction dimension `k` into `k * split_factor + kk`.\\n    The dimension `kk` is added as an extra parallel dimension to the\\n    intermediate output tensor at position `insert_split_dimension`.\\n\\n    Consider a minimal example where `k` is reduced:\\n        O(i, j) += I(i, j, k)\\n    Assume i=3, j=5, k=128, split_factor=16 and insert_split_dimension=0.\\n    The compute is rewritten as:\\n      a. O_i(kk, i, j) += I(i, j, 16 * k + kk)\\n      b. O(i, j) += O_i(kk, i, j)\\n    The intermediate tensor O_i is of shape (128/16)x3x5 == 8x3x5.\\n\\n    #### Example:\\n\\n    ```\\n     %0 = linalg.matmul ins(%A, %B: tensor<16x256xf32>, tensor<256x32xf32>)\\n       outs(%C: tensor<16x32xf32>) -> tensor<16x32xf32>\\n    ```\\n\\n    Is transformed to:\\n\\n    ```\\n     #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d2 * 4 + d3)>\\n     #map1 = affine_map<(d0, d1, d2, d3) -> (d2 * 4 + d3, d1)>\\n     #map2 = affine_map<(d0, d1, d2, d3) -> (d2, d3)>\\n     #map3 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2)>\\n     #map4 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>\\n     #map5 = affine_map<(d0, d1, d2) -> (d0, d1)>\\n     %0 = tensor.empty() : tensor<16x32x64xf32>\\n     %cst = arith.constant 0.000000e+00 : f32\\n     %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<16x32x64xf32>) ->\\n        tensor<16x32x64xf32>\\n     %2 = tensor.empty() : tensor<64x4xi1>\\n\\n     %3 = linalg.generic {indexing_maps = [#map0, #map1, #map2, #map3],\\n       iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"parallel\\\", \\\"reduction\\\"]}\\n       ins(%A, %B, %2 : tensor<16x256xf32>, tensor<256x32xf32>, tensor<64x4xi1>)\\n       outs(%1 : tensor<16x32x64xf32>) {\\n         ^bb0(%arg3: f32, %arg4: f32, %arg5: i1, %arg6: f32):\\n           %5 = arith.mulf %arg3, %arg4 : f32\\n           %6 = arith.addf %arg6, %5 : f32\\n           linalg.yield %6 : f32\\n     } -> tensor<16x32x64xf32>\\n\\n     %4 = linalg.generic {indexing_maps = [#map4, #map5],\\n       iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"reduction\\\"]}\\n       ins(%3 : tensor<16x32x64xf32>)\\n       outs(%C : tensor<16x32xf32>) {\\n         ^bb0(%arg3: f32, %arg4: f32):\\n           %5 = arith.addf %arg3, %arg4 : f32\\n           linalg.yield %5 : f32\\n     } -> tensor<16x32xf32>\\n\\n     return %4 : tensor<16x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"init_or_alloc_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"fill_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"split_linalg_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"combining_linalg_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_factor\", \"type\": \"DefaultValuedAttr<I64Attr, {}>\" },\n      { \"name\": \"insert_split_dimension\", \"type\": \"DefaultValuedAttr<I64Attr, {}>\" },\n      { \"name\": \"inner_parallel\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_scaling_algorithm\", \"type\": \"UnitAttr\" },\n      { \"name\": \"use_alloc\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:`functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.tile_reduction_using_for\",\n    \"description\": \"Indicates that the given `target` op should be transformed with the\\n    `tileReduction` transformation with the tile size provided as attribute.\\n\\n    This transformation tiles the `target` along the reduction dimensions. It\\n    creates a tensor initialized with the identity value. Then it creates nested\\n    loops with a parallel version of `target` op inside. The parallel op\\n    dimensions are less or equal to the tile size passed by user.\\n    After the loop a merge operation is created to do a final reduction with the\\n    partial reductions.\\n    The initial tensor always uses the tile size dimension. This may overallocate\\n    if the tile size is greater than the reduction dimension.\\n\\n    #### Return modes\\n\\n    Returns 4 handles associated with (in order):\\n      - the fill op used to initialize the neutral element,\\n      - the parallel tiled op and\\n      - the result-combining op,\\n      - the parent `for` op.\\n\\n    The `reduction_dims` can be used to specify the subset of reduction dimensions\\n    of the operation to tile. If left unspecified, all reduction dimensions are\\n    tiled.\\n\\n    #### Example:\\n\\n    ```\\n      %red = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,\\n                                              affine_map<(d0, d1) -> (d0)>],\\n      iterator_types = [\\\"parallel\\\", \\\"reduction\\\"]}\\n      ins(%arg0 : tensor<?x?xf32>)\\n      outs(%out : tensor<?xf32>) {\\n        ^bb0(%arg7: f32, %arg9: f32):\\n        %1 = arith.addf %arg7, %arg9 : f32\\n        linalg.yield %1 : f32\\n      } -> tensor<?xf32>\\n      return %red : tensor<?xf32>\\n    ```\\n\\n    is transformed into:\\n\\n    ```\\n      %0 = tensor.empty(%dim_1) : tensor<?x5xf32>\\n      %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<?x5xf32>) -> tensor<?x5xf32>\\n      %2 = scf.for %arg2 = %c0 to %dim_0 step %c5 iter_args(%arg3 = %1) -> (tensor<?x5xf32>) {\\n        %extracted_slice = tensor.extract_slice %1[0, 0] [%dim, 5] [1, 1] : tensor<?x5xf32> to tensor<?x5xf32>\\n        %extracted_slice_2 = tensor.extract_slice %arg0[0, %arg2] [%dim, 5] [1, 1] : tensor<?x?xf32> to tensor<?x5xf32>\\n        %4 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,\\n                                              affine_map<(d0, d1) -> (d0, d1)>],\\n        iterator_types = [\\\"parallel\\\", \\\"parallel\\\"]}\\n        ins(%extracted_slice_2 : tensor<?x5xf32>)\\n        outs(%extracted_slice : tensor<?x5xf32>) {\\n        ^bb0(%in: f32, %out: f32):\\n          %5 = arith.addf %in, %out : f32\\n          linalg.yield %5 : f32\\n        } -> tensor<?x5xf32>\\n        %dim_3 = tensor.dim %1, %c0 : tensor<?x5xf32>\\n        %inserted_slice = tensor.insert_slice %4 into %arg3[0, 0] [%dim_3, 5] [1, 1] : tensor<?x5xf32> into tensor<?x5xf32>\\n        scf.yield %inserted_slice : tensor<?x5xf32>\\n      }\\n      %3 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,\\n                                            affine_map<(d0, d1) -> (d0)>],\\n      iterator_types = [\\\"parallel\\\", \\\"reduction\\\"]}\\n      ins(%2 : tensor<?x5xf32>)\\n      outs(%arg1 : tensor<?xf32>) {\\n      ^bb0(%in: f32, %out: f32):\\n        %4 = arith.addf %in, %out : f32\\n        linalg.yield %4 : f32\\n      } -> tensor<?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"fill_op\", \"type\": \"Variadic<TransformHandleTypeInterface>\" },\n      { \"name\": \"split_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"combining_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"for_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_dims\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    (`reduction_dims` `=` $reduction_dims^)?\\n    `by` `tile_sizes` `=` $tile_sizes\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.tile_reduction_using_forall\",\n    \"description\": \"Tile a PartialReductionOpInterface op to a tiled `scf.forall` doing\\n    partial reduction.\\n\\n    This transformation tiles the `target` along the reduction dimensions. It\\n    creates a tensor initialized with the identity value. Then it creates a\\n    `scf.forall` loops with the number threads given by `num_threads`.\\n    The op is tiled op with a size equal to `floordiv(size, num_threads)`.\\n    All the partial reduction value is are parallel inserted to create a new\\n    tensor. After the loop a merge operation is created to do a final reduction\\n    with the partial reductions tensor.\\n    If an extra `tile_sizes` parameter is passed the tiles are cyclically\\n    distributed on the threads of the `scf.foralls` loop.\\n\\n    #### Return modes\\n\\n    Returns 4 handles associated with (in order):\\n      - the fill op used to initialize the neutral element,\\n      - the parallel tiled op and\\n      - the result-combining op,\\n      - the parent `forall` op.\\n\\n    #### Example:\\n\\n    ```\\n      %red = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,\\n                                              affine_map<(d0, d1) -> (d0)>],\\n      iterator_types = [\\\"parallel\\\", \\\"reduction\\\"]}\\n      ins(%arg0 : tensor<?x?xf32>)\\n      outs(%out : tensor<?xf32>) {\\n        ^bb0(%arg7: f32, %arg9: f32):\\n        %1 = arith.addf %arg7, %arg9 : f32\\n        linalg.yield %1 : f32\\n      } -> tensor<?xf32>\\n      return %red : tensor<?xf32>\\n    ```\\n\\n    is transformed into:\\n\\n    ```\\n      %0 = tensor.empty(%dim_1) : tensor<?x5xf32>\\n      %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<?x5xf32>) -> tensor<?x5xf32>\\n      %2 = scf.forall (%arg2) in (%c5) shared_outs(%arg3 = %1) -> (tensor<?x5xf32>) {\\n        %4 = affine.min #map(%arg2)[%dim_0]\\n        %5 = affine.max #map1(%4)\\n        %extracted_slice = tensor.extract_slice %arg3[0, %arg2] [%dim, 1] [1, 1] : tensor<?x5xf32> to tensor<?xf32>\\n        %6 = affine.apply #map2(%arg2)[%dim_0]\\n        %extracted_slice_2 = tensor.extract_slice %arg0[0, %6] [%dim, %5] [1, 1] : tensor<?x?xf32> to tensor<?x?xf32>\\n        %extracted_slice_3 = tensor.extract_slice %extracted_slice[0] [%dim] [1] : tensor<?xf32> to tensor<?xf32>\\n        %7 = linalg.generic {indexing_maps = [#map3, #map4], iterator_types = [\\\"parallel\\\", \\\"reduction\\\"]} ins(%extracted_slice_2 : tensor<?x?xf32>) outs(%extracted_slice_3 : tensor<?xf32>) {\\n        ^bb0(%in: f32, %out: f32):\\n          %9 = arith.addf %in, %out : f32\\n          linalg.yield %9 : f32\\n        } -> tensor<?xf32>\\n        scf.forall.in_parallel {\\n          tensor.parallel_insert_slice %7 into %arg3[0, %arg2] [%dim, 1] [1, 1] : tensor<?xf32> into tensor<?x5xf32>\\n        }\\n      } {mapping = []}\\n      %3 = linalg.generic {indexing_maps = [#map3, #map4], iterator_types = [\\\"parallel\\\", \\\"reduction\\\"]} ins(%2 : tensor<?x5xf32>) outs(%arg1 : tensor<?xf32>) {\\n      ^bb0(%in: f32, %out: f32):\\n        %4 = arith.addf %in, %out : f32\\n        linalg.yield %4 : f32\\n      } -> tensor<?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"fill_op\", \"type\": \"Variadic<TransformHandleTypeInterface>\" },\n      { \"name\": \"split_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"combining_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"forall_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_dims\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"num_threads\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    (`reduction_dims` `=` $reduction_dims^)?\\n    `by`\\n    (`num_threads` `=` $num_threads^)?\\n    (`tile_sizes` `=` $tile_sizes^)?\\n    (`mapping` `=` $mapping^)?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.tile_using_for\",\n    \"description\": \"Indicates that the given `target` op should be tiled with the given sizes.\\n    This transform generates a loop nest with a smaller (\\\"tiled\\\") target\\n    operation in its body. Currently limited to LinalgOps.\\n\\n    Tile sizes may be known at transformation time, in which case they are\\n    expected to be provided in the `static_size` attribute, or not, in which\\n    case the tile value must be computed by the payload IR and the handle to the\\n    operation computing it must be provided through `dynamic_sizes`. When the\\n    sizes are not known statically, the corresponding entry in the\\n    `static_sizes` attribute must be set to `ShapedType::kDynamic`. Only\\n    the dynamic sizes must be provided in `dynamic_sizes`, i.e., there should\\n    be as many handles as `ShapedType::kDynamic` values in the\\n    `static_sizes` attribute. A static size of `0` indicates that the dimension\\n    should not be tiled. No loop will be generated for such dimensions. If all\\n    tile sizes are `0`, this transform is effectively a no-op.\\n\\n    This op returns handles to the tiled op (in the generated loop nest) and the\\n    generated loops. The number of loops is the number of tile sizes that are\\n    statically known to be non-zero.\\n\\n    #### Return modes\\n\\n    On success, the resulting handles are associated with co-indexed lists of\\n    tiled operations and loops around them.\\n\\n    This operation only supports Linalg ops and produces a silenceable failure\\n    if the input contains any non-Linalg ops. The ops preceding it in the list\\n    associated with the `target` handle will have been tiled.\\n\\n    This operation produces a silenceable failure if the `dynamic_sizes` handles\\n    are associated with lists of payload operations of a size different than\\n    that of the list associated with the `target` handle.\\n\\n    If the internal implementation of tiling for any of the operations fails,\\n    produces a definite failure.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"dynamic_sizes\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tiled_linalg_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"interchange\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"scalable_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseBoolArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n      `tile_sizes` custom<DynamicIndexList>(\\n        $dynamic_sizes,\\n        $static_sizes,\\n        $scalable_sizes)\\n      (`interchange` `=` $interchange^)?\\n    attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.tile_using_forall\",\n    \"description\": \"Tile a TilingInterface op to a tiled `scf.forall`.\\n\\n    Tiling is applied by either specifying `num_threads` or `tile_size`. If\\n    `num_threads` is specified, then the tile size for each dimension `i` is\\n    calculated dynamically via `ceilDiv(dimSize[i], num_threads[i])`.\\n    `num_threads` and `tile_size` can be either static index attributes or\\n    operation handles (or a mix thereof). Operation handles must be mapped to\\n    exactly one op that has exactly one result of index type.\\n\\n    Static zero tile sizes indicate that the dimension is not tiled and can be\\n    thought of as tiling by the full size of data.\\n\\n    It is the user's responsibility to ensure that `num_threads/tile_sizes` is\\n    a valid tiling specification (i.e. that only tiles parallel dimensions,\\n    e.g. in the Linalg case). If the dimension is not parallelizable, a warning\\n    is issued to notify the user that the generated code is not safe to\\n    parallelize.\\n\\n    If non-empty, the `mapping` is added as an attribute to the\\n    resulting `scf.forall`.\\n\\n    Note: `tile_sizes` and `num_threads` are variadic. Each tile size/number of\\n    threads can be an index attribute or a transform handle that is mapped to\\n    exactly one payload op with exactly one index result.\\n\\n    #### Return modes\\n\\n    This operation ignores ops that do not implement the TilingInterface and\\n    drops them in the return.\\n\\n    If all the operations referred to by the `target` handle tile\\n    successfully, the transform succeeds.\\n    Otherwise the transform produces a silenceable failure.\\n\\n    The two returned handles point to only the subset of successfully produced\\n    tiled operations, which can all be empty.\\n\\n    These two returned handles point to:\\n      - the tiled op that implements TilingInterface,\\n      - the new scf.forall op.\\n\\n    #### Example using `num_threads`\\n\\n    ```\\n    %0 = transform.structured.match ops{[\\\"linalg.matmul\\\"]} in %arg1\\n       : (!transform.any_op) -> !transform.any_op\\n    %3:2 = transform.structured.tile_using_forall %0 num_threads [10, 20]\\n       : (!transform.any_op) -> (!transform.any_op, !transform.any_op)\\n    ```\\n\\n    #### Example using `tile_sizes`\\n\\n    ```\\n    %0 = transform.structured.match ops{[\\\"linalg.matmul\\\"]} in %arg1\\n       : (!transform.any_op) -> !transform.any_op\\n    %sz = transform.structured.match ...\\n    %3:2 = transform.structured.tile_using_forall %0 tile_sizes [0, %sz, 20]\\n       : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"num_threads\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"tile_sizes\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"packed_num_threads\", \"type\": \"Optional<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"packed_tile_sizes\", \"type\": \"Optional<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"tiled_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"forall_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_num_threads\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_tile_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$target oilist(\\n        `num_threads` custom<PackedOrDynamicIndexList>($packed_num_threads,\\n                                                       $num_threads,\\n                                                       $static_num_threads) |\\n         `tile_sizes` custom<PackedOrDynamicIndexList>($packed_tile_sizes,\\n                                                       $tile_sizes,\\n                                                       $static_tile_sizes))\\n    (`(` `mapping` `=` $mapping^ `)`)? attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.transpose_conv2d\",\n    \"description\": \"Convert linalg.conv_2d_nhwc_fhwc into linalg.conv_2d_nhwc_hwcf by introducing\\n    a linalg.transpose on the filter tensor/memref.\\n\\n    Whilst the fhwc filter channel ordering can be desirable for certain targets\\n    and is a more direct mapping to higher level dialects such as TOSA (which only\\n    supports this ordering) hwcf is better suited for transformations such as\\n    img2col which can make use of optimized BLAS routines such as GEMM.\\n\\n    Returns one handle:\\n    - The final operation of the sequence that replaces the original\\n      convolution.\\n\\n    #### Return modes:\\n\\n    Returns a definite failure if target is not isolated from above.\\n    Returns a silenceable failure if the pattern application failed.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.transpose_matmul\",\n    \"description\": \"Convert Linalg matmul ops to transposed variants.\\n\\n    By default the LHS matrix is transposed. Specify `<rhs>` to instead\\n    transpose RHS matrix.\\n\\n    #### Return modes:\\n\\n    This operation fails if `target` is unsupported, i.e., not a\\n    `linalg.matmul` or `linalg.batch_matmul`. Otherwise, the operation succeeds\\n    and returns a handle to the transposed matmul op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inputToTranspose\", \"type\": \"DefaultValuedAttr<TransposeMatmulInput{lhs|rhs}, TransposeMatmulInput::lhs>\" }\n    ],\n    \"assemblyFormat\": \"$target (`<` $inputToTranspose^ `>`)?\\n    attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.structured.vectorize\",\n    \"description\": \"Vectorize the target ops, which must be Linalg ops.\\n\\n    Use the optional vector sizes to specify exactly what configuration the\\n    vectorizer should use. It will then use masked vectors of the specified\\n    size to enforce this configuration (\\\"masked vectorization\\\"). If no vector\\n    sizes are specified, the vectorizer will infer the shapes to use from the\\n    target Linalg ops (\\\"regular vectorization\\\"). More specifically:\\n\\n    ```mlir\\n    # Masked vectorization - vector sizes are specified explicitly\\n    transform.structured.vectorize %target vector_sizes [1, 4] : !transform.any_op\\n    # Regular vectorization - vector sizes are inferred from the target Op\\n    transform.structured.vectorize %target : !transform.any_op\\n    ```\\n\\n    The vector sizes can be either static or dynamic (SSA values). In case of\\n    SSA values, the handle must be mapped to exactly one payload op with\\n    exactly one index-typed result.\\n\\n    Note: The input vector sizes must be bigger than or equal to their\\n    counterpart iteration space sizes.\\n\\n    Typically this operator should be applied to linalg operations that have\\n    already been tiled to the appropriate sizes.\\n\\n    #### Return modes:\\n\\n    This operation produces a silenceable failure if at least one target op is\\n    not a Linalg op or fails to vectorize. It produces a definite failure if\\n    the dynamic vector sizes (SSA values) do not satisfy the constraints\\n    mentioned above.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"vector_sizes\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_vector_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"vectorize_nd_extract\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"assume_dynamic_dims_match_vec_sizes\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"create_named_contraction\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"scalable_sizes\", \"type\": \"DefaultValuedOptionalAttr<DenseBoolArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target oilist(\\n      `vector_sizes` custom<DynamicIndexList>(\\n        $vector_sizes,\\n        $static_vector_sizes,\\n        $scalable_sizes))\\n    attr-dict\\n    `:` type($target)(`,`type($vector_sizes)^)?\"\n  },\n  {\n    \"name\": \"transform.structured.vectorize_children_and_apply_patterns\",\n    \"description\": \"Vectorizes all children contained in the given `target` using the\\n    configuration specified by the attributes of this op. This only vectorizes\\n    structured ops that operate on shaped types and does not vectorize loops or\\n    straight-line. Internally, it applies a set of rewrite patterns, some of\\n    which enable vectorization and some of which clean up the results.\\n    Therefore, it can only be applied to an op with the \\\"isolated from above\\\"\\n    property. This transformation only fails if the entire pattern rewriting\\n    failed, i.e., it does **not** fail when no ops were vectorized.\\n\\n    Finer granularity can be achieved either with the `VectorizeOp` for\\n    individual ops or by outlining the target part of the payload IR into, e.g.,\\n    a function, performing this transformation, and inlining it back.\\n\\n    Note that this transformation invalidates the handles to any payload IR\\n    operation that is contained inside the vectorization target.\\n\\n    This transformation supports the following attributes:\\n    - `fold_type_extensions_into_contract`: a `UnitAttr` to enable the folding of\\n      type extension operations into `vector.contract` to create a mixed precision\\n      operation.\\n    - `vectorize_padding`: a `UnitAttr` to activate the vectorization of\\n      `tensor.pad` ops. Different pipelines may prefer to lower such ops to\\n      loops.\\n    - `disable_multi_reduction_to_contract_patterns`: a `UnitAttr` to deactivate\\n      the rewrite of `vector.multi_reduction` to `vector.contract`. This is\\n      intended to be used in tests only.\\n    - `disable_transfer_permutation_map_lowering_patterns`: a `UnitAttr` to\\n      deactivate the rewrite of `vector.transfer` with permutation maps into\\n      explicit `vector.transpose` operations. This is intended to be used in\\n      tests only but may be promoted to a first class attribute in the future.\\n\\n    #### Return modes:\\n\\n    This operation produces a definite failure if vectorization fails for any\\n    reason.\\n    The operation always returns the handle to the target op that is expected\\n    to be isolated from above.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fold_type_extensions_into_contract\", \"type\": \"UnitAttr\" },\n      { \"name\": \"vectorize_padding\", \"type\": \"UnitAttr\" },\n      { \"name\": \"vectorize_nd_extract\", \"type\": \"UnitAttr\" },\n      { \"name\": \"flatten_1d_depthwise_conv\", \"type\": \"UnitAttr\" },\n      { \"name\": \"disable_multi_reduction_to_contract_patterns\", \"type\": \"UnitAttr\" },\n      { \"name\": \"disable_transfer_permutation_map_lowering_patterns\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:`functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.structured.winograd_conv2d\",\n    \"description\": \"Winograd Conv2D algorithm will convert linalg Conv2D operation into batched\\n    matrix multiply. Before the matrix multiply, it will convert filter and\\n    input into a format suitable for batched matrix multiply. After the matrix\\n    multiply, it will convert output to the final result tensor.\\n\\n    The algorithm F(m x m, r x r) is\\n\\n    Y = A^T x [(G x g x G^T) @ (B^T x d x B)] x A\\n\\n    The size of output Y is m x m. The size of filter g is r x r. The size of\\n    input d is (m + r - 1) x (m + r - 1). A^T, A, G^T, G, B^T, and B are\\n    transformation matrices.\\n\\n    #### Return modes:\\n\\n    This operation produces a silenceable failure if `target` is unsupported.\\n    Otherwise, the operation succeeds and returns a handle of the sequence that\\n    replaces the original convolution.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmr\", \"type\": \"WinogradConv2DFmr{F_2_3|F_4_3|F_2_5}\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, results)\"\n  },\n  {\n    \"name\": \"transform.tensor.make_loop_independent\",\n    \"description\": \"Rewrite the targeted ops such that their index-typed operands no longer\\n    depend on any loop induction variable of the `num_loop` enclosing `scf.for`\\n    loops. I.e., compute an upper bound that is independent of any such loop IV\\n    for every tensor dimension. The transformed op could then be hoisted from\\n    the `num_loop` enclosing loops. To preserve the original semantics, place a\\n    `tensor.extract_slice` inside the loop.\\n\\n    Currently supported operations are:\\n    - tensor.empty: Replaced with a new tensor.empty with upper bound sizes,\\n      followed by a tensor.extract_slice.\\n    - tensor.pad: Replaced by an upper bound padding, followed by a\\n      tensor.extract_slice.\\n\\n    #### Return modes\\n\\n    This operation fails if at least one induction variable could not be\\n    eliminated. In case the targeted op is already independent of induction\\n    variables, this transform succeeds and returns the unmodified target op.\\n\\n    Otherwise, the returned handle points to a subset of the produced ops:\\n    - tensor.empty: The returned handle points to the tensor.extract_slice op.\\n    - tensor.pad: The returned handle points to the tensor.extract_slice op.\\n\\n    This transform op consumes the target handle and produces a result handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_loops\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, $transformed)\"\n  },\n  {\n    \"name\": \"transform.test_add_test_extension\",\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$message attr-dict\"\n  },\n  {\n    \"name\": \"transform.test_add_to_param\",\n    \"operands\": [\n      { \"name\": \"param\", \"type\": \"Optional<TestTransformTestDialectParamType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TestTransformTestDialectParamType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"addendum\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"($param^ `,`)? $addendum attr-dict\"\n  },\n  {\n    \"name\": \"transform.test_branching_transform_op_terminator\",\n    \"successors\": [\n      { \"name\": \"succ\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ]\n  },\n  {\n    \"name\": \"transform.test_check_if_test_extension_present\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"transform.test_consume_operand\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Transform_AnyHandleOrParamType\" },\n      { \"name\": \"second_operand\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"allow_repeated_handles\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand (`,` $second_operand^)? attr-dict `:` type($operand)(`,` type($second_operand)^)?\"\n  },\n  {\n    \"name\": \"transform.test_consume_operand_each\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test_consume_operand_of_op_kind_or_fail\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_kind\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $op_kind attr-dict `:` type($operand)\"\n  },\n  {\n    \"name\": \"transform.test_copy_payload\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"copy\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_correct_number_of_multi_results\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result1\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"result2\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_dummy_payload_op\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fail_to_verify\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$args attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_emit_remark_and_erase_operand\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"remark\", \"type\": \"StrAttr\" },\n      { \"name\": \"fail_after_erase\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$target `,` $remark attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test_initializer_extension\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$type attr-dict\"\n  },\n  {\n    \"name\": \"transform.test_mixed_null_and_non_null_results\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"null\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"non_null\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_mixed_success_and_silenceable\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test_notify_payload_op_replaced\",\n    \"operands\": [\n      { \"name\": \"original\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"replacement\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$original `,` $replacement attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_produce_empty_payload\",\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($out)\"\n  },\n  {\n    \"name\": \"transform.test_produce_invalid_ir\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test_produce_null_param\",\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($out)\"\n  },\n  {\n    \"name\": \"transform.test_produce_null_payload\",\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($out)\"\n  },\n  {\n    \"name\": \"transform.test_produce_null_value\",\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($out)\"\n  },\n  {\n    \"name\": \"transform.test_produce_param\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"attr\", \"type\": \"AnyAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $attr `)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"transform.test_produce_param_with_number_of_test_ops\",\n    \"operands\": [\n      { \"name\": \"handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TestTransformTestDialectParamType\" }\n    ],\n    \"assemblyFormat\": \"$handle attr-dict `:` type($handle)\"\n  },\n  {\n    \"name\": \"transform.test_produce_self_handle_or_forward_operand\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"($operand^)? attr-dict `:` functional-type($operand, $res)\"\n  },\n  {\n    \"name\": \"transform.test_produce_transform_param_or_forward_operand\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"AnyType\" },\n      { \"name\": \"param\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"first_result_is_param\", \"type\": \"UnitAttr\" },\n      { \"name\": \"first_result_is_null\", \"type\": \"UnitAttr\" },\n      { \"name\": \"second_result_is_handle\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_produce_value_handle_to_argument_of_parent_block\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"number\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$in `,` $number attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_produce_value_handle_to_result\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"number\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$in `,` $number attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_produce_value_handle_to_self_operand\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_re_enter_region\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"($args^ `:` type($args))? attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.test_remap_operand_to_self\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` functional-type($operand, $out)\"\n  },\n  {\n    \"name\": \"transform.test_remove_test_extension\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"transform.test_report_number_of_tracked_handles_nested_under\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test_required_memory_effects\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"out\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"has_operand_effect\", \"type\": \"UnitAttr\" },\n      { \"name\": \"has_result_effect\", \"type\": \"UnitAttr\" },\n      { \"name\": \"modifies_payload\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_reverse_payload_ops\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_succeed_if_operand_of_op_kind\",\n    \"operands\": [\n      { \"name\": \"operand_handle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"op_kind\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$operand_handle `,` $op_kind attr-dict `:` type($operand_handle)\"\n  },\n  {\n    \"name\": \"transform.test_tracked_rewrite\",\n    \"operands\": [\n      { \"name\": \"in\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$in attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test_transform_op\"\n  },\n  {\n    \"name\": \"transform.test_transform_op_with_regions\",\n    \"regions\": [\n      { \"name\": \"first\", \"type\": \"AnyRegion\" },\n      { \"name\": \"second\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.test_wrong_number_of_multi_results\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type($target, $result)\"\n  },\n  {\n    \"name\": \"transform.test_wrong_number_of_results\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"a\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"b\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"c\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.fuse_and_yield\",\n    \"description\": \"Tiles the operations pointed to by the target handle, fuses their\\n    producers greedily using the options provided as attributes.\\n    It also yields some of the fused producers for testing.\\n\\n    On success returns the tiled operations as well as generated loops. Emits\\n    a definite failure if tiling fails.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"transfomed\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"tile_interchange\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"use_forall\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"$target ($tile_sizes^)? (`interchange` $tile_interchange^)?\\n    (`use_forall` $use_forall^)? attr-dict \\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.fuse_consumer\",\n    \"description\": \"For the `consumer` that uses the result of the outer-most loop of a loop nest passed in \\n    as `loops` (that are typically generated through tiling), fuse the consumer into the\\n    loop.\\n\\n    Returns a handle to the consumer operation after fusion and the loops that might be\\n    modified.\",\n    \"operands\": [\n      { \"name\": \"consumer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"fused_consumer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"result_loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"assemblyFormat\": \"$consumer `into` `(` $loops `)`\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.fuse_consumer_using_slice\",\n    \"description\": \"For the `insert_slice`-like operations (that are typically generated through tiling),\\n    within the loop nests passed in as `loops` (that are typically generated through tiling),\\n    find the consumer that these slices map to (have to be the same consumer) and fuse\\n    the consumer into the loop.\\n\\n    Returns a handle to the original consumer operation and the consumer operation after\\n    fusion.\",\n    \"operands\": [\n      { \"name\": \"targets\", \"type\": \"Variadic<TransformHandleTypeInterface>\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"consumer\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"fused_consumer\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_consumer_to_fuse\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$targets `in` `(` $loops `)`\\n    (`num_consumer_to_fuse` `=` $num_consumer_to_fuse^)? \\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.fuse_using_forall\",\n    \"description\": \"Test operation to tile the operation pointed to by the target handle and\\n    fuses their producers greedily using the options provided as attributes.\\n    This operation uses scf.forall for the loop construct.\",\n    \"operands\": [\n      { \"name\": \"root_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"tiled_ops\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"interchange\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" }\n    ],\n    \"assemblyFormat\": \"$root_op ($tile_sizes^)? (`interchange` $interchange^)?\\n    (`mapping` `=` $mapping^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.make_composed_folded_affine_apply\",\n    \"description\": \"Rewrite an affine_apply by using the makeComposedFoldedAffineApply API.\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"composed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$op attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.move_operand_deps\",\n    \"description\": \"Moves all dependencies of on operation before another operation.\",\n    \"operands\": [\n      { \"name\": \"op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"insertion_point\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$op `before` $insertion_point attr-dict\\n    `:` type($op) `,` type($insertion_point)\"\n  },\n  {\n    \"name\": \"transform.test.move_value_defns\",\n    \"description\": \"Moves all dependencies of a list of values before another operation.\\n    Only pure operations are moved. If there is a side effecting op in the\\n    dependency chain no operations are moved.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<TransformValueHandleTypeInterface>\" },\n      { \"name\": \"insertion_point\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$values `before` $insertion_point attr-dict\\n    `:` `(` type($values) `)` `` `,` type($insertion_point)\"\n  },\n  {\n    \"name\": \"transform.test.query_consumer_fusability\",\n    \"description\": \"Test operation for the consumer fusability query method in the\\n    TilingInterface.\\n\\n    For each operation in the target handle, this looks for tensor.extract_slice\\n    ops that consume results of the tilable op. The offset/sizes from those\\n    extracts is used as the arguments to `isOpFusableWithConsumerSlice` and\\n    emits a remark with the result of the query.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test.query_producer_fusability\",\n    \"description\": \"Test operation for the producer fusability query method in the\\n    TilingInterface.\\n\\n    For each operation in the target handle, this looks for tensor.insert_slice\\n    ops that produce operands to the tilable op. The offset/sizes from those\\n    inserts is used as the arguments to `isOpFusableWithProducerSlices` and\\n    emits a remark with the result of the query.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.test.tile_and_fuse_outer_parallel_partial_reduction\",\n    \"description\": \"Test operation to tile an operation using partial reduction with\\n    outer parallel strategy, and to fuse its producers.\",\n    \"operands\": [\n      { \"name\": \"root_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"tiled_ops\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_dims\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" }\n    ],\n    \"assemblyFormat\": \"$root_op (`reduction_dims` `=` $reduction_dims^)?\\n    (`tile_sizes` `=` $tile_sizes^)? (`mapping` `=` $mapping^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.tile_using_custom_loop\",\n    \"description\": \"Test Transform op to tile an operation using custom loops.\\n\\n    The test just folds all the loops and into a single loop and then\\n    delinearizes the indices.\",\n    \"operands\": [\n      { \"name\": \"root_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"tiled_ops\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" }\n    ],\n    \"assemblyFormat\": \"$root_op `tile_sizes` `=` $tile_sizes\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.test.tile_using_forall\",\n    \"description\": \"Test operation use to test tiling using TilingInterface and scf.forall for\\n    the loop constructs. This is similar to\\n    `transform.structured.tile_using_for`. Use of this operation is an\\n    intermediate state and will be replaced in due course with either\\n    `transform.structured.tile_using_for` or\\n    `transform.structured.tile_using_forall`.\\n\\n    On success returns the tiled operations as well as generated loops. Emits\\n    a definite failure if tiling fails.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"tiled_op\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"loops\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile_sizes\", \"type\": \"DefaultValuedAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"interchange\", \"type\": \"DefaultValuedOptionalAttr<TypedArrayAttrBase<I64Attr>, {}>\" },\n      { \"name\": \"mapping\", \"type\": \"OptionalAttr<TypedArrayAttrBase<AnyAttrOf<[ DeviceMappingAttrInterface, DeviceMaskingAttrInterface ]>>>\" }\n    ],\n    \"assemblyFormat\": \"$target ($tile_sizes^)? (`interchange` `=` $interchange^)?\\n    (`mapping` `=` $mapping^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.tune.alternatives\",\n    \"summary\": \"Represents a choice among its regions, i.e. sub-schedules\",\n    \"description\": \"This op represents a choice over which of its regions is to be used.\\n\\n    When `selected_region` is provided, the semantics are that this op is to be\\n    substituted for by the selected region, meaning the region's results become\\n    the results of this op. Without a provided `selected_region`, the semantics\\n    are that this non-deterministic choice is yet to be resolved -- which in\\n    terms of the op's interpreted semantics is a failure.\\n\\n    The `selected_region` argument is either an `IntegerAttr` or a param holding\\n    an `IntegerAttr`, which should provide a valid zero-based index with respect\\n    to the number of alternatives, i.e. regions.\",\n    \"operands\": [\n      { \"name\": \"selected_region_param\", \"type\": \"Optional<TransformParamTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"Builtin_StringAttr\" },\n      { \"name\": \"selected_region_attr\", \"type\": \"OptionalAttr<APIntAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"alternatives\", \"type\": \"VariadicRegion<SizedRegion<1>>\" }\n    ],\n    \"assemblyFormat\": \"`<` $name `>`\\n    (`selected_region` `=` custom<AlternativesOpSelectedRegion>(\\n        $selected_region_attr, $selected_region_param)^)?\\n    attr-dict-with-keyword\\n    (`:` type($selected_region_param)^)?\\n    (`->` type($results)^)?\\n    regions\"\n  },\n  {\n    \"name\": \"transform.tune.knob\",\n    \"summary\": \"Represents a tunable parameter with a set of options\",\n    \"description\": \"Provides a representation for \\\"tunables\\\" within schedules.\\n\\n    Each op represents a single tunable, which has a `name` and a set\\n    of valid `options` described by an attribute. Without a specified\\n    `selected` option, this op represents a non-deterministic choice\\n    that has yet to be resolved -- as such, the interpreter runtime\\n    semantics is to raise a failure.\\n\\n    The non-deterministic choice is resolved through providing a\\n    `selected` attribute. When provided, the interpreter runtime\\n    semantics are to return the `selected` attribute as a param through\\n    the op's result.\\n\\n    -----\\n\\n    In case the `options` attribute is an `ArrayAttr`, the verifier\\n    checks that the provided `selected` attribute occurs in `options`.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"Builtin_StringAttr\" },\n      { \"name\": \"options\", \"type\": \"AnyAttr\" },\n      { \"name\": \"selected\", \"type\": \"OptionalAttr<AnyAttr>\" }\n    ],\n    \"assemblyFormat\": \"`<` $name `>` (`=` $selected^ `from`)? `options` `=` $options attr-dict `->` type(results)\"\n  },\n  {\n    \"name\": \"transform.type_conversion.tensor.cast_shape_dynamic_dims\",\n    \"description\": \"Populates a type converter with conversion materialization functions that\\n    cast a tensor value between two cast-compatible tensors. See `tensor.cast`\\n    for more information on cast compatibility between tensors.\\n\\n    If `ignore_dynamic_info` is not set, this will set an additional constraint\\n    that source materializations do not cast dynamic dimensions to static ones.\",\n    \"attributes\": [\n      { \"name\": \"ignore_dynamic_info\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`ignore_dynamic_info` $ignore_dynamic_info^)? attr-dict\"\n  },\n  {\n    \"name\": \"transform.util.cast_and_call\",\n    \"summary\": \"Casts values to the signature of a function and replaces them with a call.\",\n    \"description\": \"This transform takes value handles to a set of `inputs` and `outputs` and\\n    attempts to cast them to the function signature of the attached function\\n    op, then builds a call to the function and replaces the users of the\\n    outputs. It is the responsibility of the user to ensure that the slice of\\n    the program replaced by this operation makes sense, i.e. there is no\\n    verification that the inputs to this operation have any relation to the\\n    outputs outside of basic dominance requirements needed for the call.\\n\\n    The casting materialization functions are specified in the graph region of\\n    this op. They must implement the `TypeConverterBuilderOpInterface`. The\\n    order of ops within the region is irrelevant.\\n\\n    The target function can be specified by a symbol name or by a handle to the\\n    operation.\\n\\n    If |inline_call| is set, the function body will be inlined at the insertion\\n    point instead of called. This will lead to a definite failure if the\\n    function exists but does not contain a single basic block (0 or > 1).\\n\\n    This transform only reads the operand handles and only replaces the users of\\n    the outputs with the results of the call. No handles are consumed and no\\n    operations are removed. Users are expected to run cleanup separately if\\n    desired.\\n\\n    Warning: The replacement of the uses of the outputs could invalidate certain\\n    restricted value handle types (e.g. `transform.block_arg` if it existed, by\\n    replacing the use with something not coming from a block argument). The\\n    value will still exist in such cases but wouldn't verify against the type.\\n    See the discussion here for more information:\\n    https://github.com/llvm/llvm-project/pull/78398#discussion_r1455070087\\n\\n    This transform will emit a silenceable failure if:\\n     - The set of outputs isn't unique\\n     - The handle for the insertion point does not include exactly one operation\\n     - The insertion point op does not dominate any of the output users\\n     - The insertion point op is not dominated by any of the inputs\\n     - The function signature does not match the number of inputs/outputs\\n\\n    This transform will emit a definite failure if it fails to resolve the\\n    target function, or if it fails to materialize the conversion casts of\\n    either the inputs to the function argument types, or the call results to\\n    the output types.\",\n    \"operands\": [\n      { \"name\": \"insertion_point\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"inputs\", \"type\": \"Optional<TransformValueHandleTypeInterface>\" },\n      { \"name\": \"outputs\", \"type\": \"Optional<TransformValueHandleTypeInterface>\" },\n      { \"name\": \"function\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TransformHandleTypeInterface>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"insert_after\", \"type\": \"UnitAttr\" },\n      { \"name\": \"inline_call\", \"type\": \"UnitAttr\" },\n      { \"name\": \"function_name\", \"type\": \"OptionalAttr<SymbolRefAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"conversions\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"(`inline_call` $inline_call^)?\\n    ($function_name^)? ($function^)?\\n    ( `(` $inputs^ `)` )?\\n    ( `->` $outputs^ )?\\n    (`after` $insert_after^):(`before`)? $insertion_point\\n    ($conversions^)? attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.util.create_serialized_module\",\n    \"summary\": \"Creates a serialized module op using the transform region.\",\n    \"description\": \"This op creates an owning op reference to a module op and executes the\\n    transforms contained within this operations body on it. Then the serialized\\n    module is returned.\\n\\n    The body of this op provides a single block argument providing the temporary\\n    module for modification. No transform on the module is allowed to consume\\n    it.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformParamTypeInterface\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword regions `->` type($result)\"\n  },\n  {\n    \"name\": \"transform.util.deserialize_module\",\n    \"description\": \"Deserializes |module| to a ModuleOp and inserts it at the end of\\n    |container|. This operation is currently only used for testing purposes.\",\n    \"operands\": [\n      { \"name\": \"module\", \"type\": \"TransformParamTypeInterface\" },\n      { \"name\": \"container\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$module `into` $container attr-dict `:` type($module) `,` type($container)\"\n  },\n  {\n    \"name\": \"transform.util.get_nearest_symbol_table\",\n    \"description\": \"Returns the nearest symbol table op for each op in the payload, inclusive.\\n\\n    This operation reads the `target` handle and produces the `result`\\n    handle. This operation emits a definite failure if the nearest symbol table\\n    is unknown.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.util.import_symbol\",\n    \"description\": \"Clones the op defined by the given symbol into the given symbol table and\\n    returns the cloned symbol. If `force_import` is set, this will (unsafely)\\n    overwrite any pre-existing definitions of the same symbol. If\\n    `if_undefined` is set, this will return a handle to the pre-existing symbol\\n    in the payload if found instead of failing.\\n\\n    #### Return modes\\n\\n    This operation reads the `symbol_table` handle and produces the\\n    `cloned_symbol` handle. This operation emits a definite failure if the if\\n    the `symbol_table` op does not define a symbol table.\\n\\n    This will emit a definite failure if the symbol already exists in the\\n    symbol table and neither `force_import` and `if_undefined` are set.\",\n    \"operands\": [\n      { \"name\": \"symbol_table\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"cloned_symbol\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"symbol\", \"type\": \"SymbolRefAttr\" },\n      { \"name\": \"if_undefined\", \"type\": \"UnitAttr\" },\n      { \"name\": \"force_import\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`force` $force_import^)? $symbol `into` $symbol_table\\n    (`if` `undefined` $if_undefined^)? attr-dict\\n    `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.util.lookup_nearest_symbol_from_self\",\n    \"description\": \"Returns a reference to the symbol with the specified name within the nearest\\n    symbol table to this operation.\\n\\n    #### Return modes\\n\\n    This operation produces the `target_symbol` handle based on `symbol` and\\n    the nearest symbol table. This operation emits a definite failure if the\\n    symbol does not exist.\",\n    \"results\": [\n      { \"name\": \"target_symbol\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"symbol\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$symbol attr-dict `:` type($target_symbol)\"\n  },\n  {\n    \"name\": \"transform.verify\",\n    \"summary\": \"Verifies the targeted ops\",\n    \"description\": \"This transform verifies the targeted ops. If at least one op fails to\\n    verify, the transform produces a definite failure.\\n\\n    Note: This op was designed for debugging purposes and should be used like an\\n    assertion. It is intentional that this op produces a definite failure and\\n    not a silenceable one. Correctness of the program should not depend on this\\n    op.\\n\\n    This transform reads the target handle.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` type($target)\"\n  },\n  {\n    \"name\": \"transform.with_pdl_patterns\",\n    \"summary\": \"Contains PDL patterns available for use in transforms\",\n    \"description\": \"This op contains a set of named PDL patterns that are available for the\\n    Transform dialect operations to be used for pattern matching. For example,\\n    PDLMatchOp can be used to produce a Transform IR value associated with all\\n    Payload IR operations that match the pattern as follows:\\n\\n    ```mlir\\n    transform.with_pdl_patterns {\\n    ^bb0(%arg0: !transform.any_op):\\n      pdl.pattern @my_pattern : benefit(1) {\\n        %0 = pdl.operation //...\\n        // Regular PDL goes here.\\n        pdl.rewrite %0 with \\\"transform.dialect\\\"\\n      }\\n\\n      sequence %arg0 failures(propagate) {\\n      ^bb0(%arg1: !transform.any_op):\\n        %1 = pdl_match @my_pattern in %arg1\\n        // Use %1 as handle\\n      }\\n    }\\n    ```\\n\\n    Note that the pattern is expected to finish with a `pdl.rewrite` terminator\\n    that points to the custom rewriter named \\\"transform.dialect\\\". The rewriter\\n    actually does nothing, but the transform application will keep track of the\\n    operations that matched the pattern.\\n\\n    This op is expected to contain `pdl.pattern` operations and exactly one\\n    another Transform dialect operation that gets executed with all patterns\\n    available. This op is a possible top-level Transform IR op, the argument of\\n    its entry block corresponds to either the root op of the payload IR or the\\n    ops associated with its operand when provided.\",\n    \"operands\": [\n      { \"name\": \"root\", \"type\": \"Optional<TransformHandleTypeInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"defaultDialect\": \"transform\",\n    \"assemblyFormat\": \"($root^ `:` type($root))? attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"transform.xegpu.convert_layout\",\n    \"summary\": \"Convert xegpu.layout attribute for a value.\",\n    \"description\": \"Adds an `xegpu.convert_layout` op to convert the `xegpu.layout` attribute\\n    of a value. The input and target layouts are defined by the `*sg_layout`,\\n    `*sg_data` and optional `*inst_data` attributes. Returns a handle to the\\n    emitted `xegpu.convert_layout` op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformValueHandleTypeInterface\" },\n      { \"name\": \"input_sg_layout\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"input_sg_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"input_inst_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"target_sg_layout\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"target_sg_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"target_inst_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"newConvertOp\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_order\", \"type\": \"DefaultValuedOptionalAttr<DenseI32ArrayAttr, {}>\" },\n      { \"name\": \"static_input_sg_layout\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_input_sg_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_input_inst_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_target_sg_layout\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_target_sg_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_target_inst_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"target_order\", \"type\": \"DefaultValuedOptionalAttr<DenseI32ArrayAttr, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `input_sg_layout` `=` custom<DynamicIndexList>($input_sg_layout, $static_input_sg_layout)\\n    `input_sg_data` `=` custom<DynamicIndexList>($input_sg_data, $static_input_sg_data)\\n    (`input_inst_data` `=` custom<DynamicIndexList>($input_inst_data, $static_input_inst_data)^)?\\n    (`input_order` `=` $input_order^)?\\n    `target_sg_layout` `=` custom<DynamicIndexList>($target_sg_layout, $static_target_sg_layout)\\n    `target_sg_data` `=` custom<DynamicIndexList>($target_sg_data, $static_target_sg_data)\\n    (`target_inst_data` `=` custom<DynamicIndexList>($target_inst_data, $static_target_inst_data)^)?\\n    (`target_order` `=` $target_order^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.xegpu.get_desc_op\",\n    \"summary\": \"Get a handle to the descriptor op of a value.\",\n    \"description\": \"Traces the producers of the given value until an `xegpu.create_nd_tdesc`\\n    descriptor op is found. Returns a handle to it. Currently traces\\n    producers by following only the first operand of producer ops.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformValueHandleTypeInterface\" }\n    ],\n    \"results\": [\n      { \"name\": \"descHandle\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"assemblyFormat\": \"$target attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.xegpu.insert_prefetch\",\n    \"summary\": \"Adds xegpu prefetch ops to matmul operand tiles.\",\n    \"description\": \"Given a target value (e.g., `vector`) residing in a `scf.for` loop, this\\n    transform finds the corresponding `xegpu.load_nd` op and inserts\\n    `xegpu.prefetch_nd` operations for the tile. The load op must reside within\\n    the `scf.for` loop. Number of prefetch steps is set by the `nb_prefetch`\\n    argument (default value is 1). Returns a handle to the created\\n    `xegpu.create_nd_desc` op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformValueHandleTypeInterface\" },\n      { \"name\": \"dynamic_nb_prefetch\", \"type\": \"Optional<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"desc_op\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_nb_prefetch\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 1>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `nb_prefetch` `=` ($dynamic_nb_prefetch^):($static_nb_prefetch)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.xegpu.set_desc_layout\",\n    \"summary\": \"Set xegpu.layout attribute to a xegpu.create_nd_desc op result.\",\n    \"description\": \"Given an `xegpu.create_nd_desc` operation, this transform adds\\n    `xegpu.layout` attribute to the result tensor descriptor. The layout is\\n    defined by the `sg_layout`, and `sg_data` and optional `inst_data`\\n    attributes. If `slice_dims` is provided, the `xegpu.layout` attribute is\\n    wrapped in an `xegpu.slice<..., dims=slice_dims>` attribute. Returns a handle to\\n    the transformed op.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"sg_layout\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"sg_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"inst_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"results\": [\n      { \"name\": \"transformed\", \"type\": \"TransformHandleTypeInterface\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_sg_layout\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_sg_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_inst_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"order\", \"type\": \"DefaultValuedOptionalAttr<DenseI32ArrayAttr, {}>\" },\n      { \"name\": \"slice_dims\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `sg_layout` `=` custom<DynamicIndexList>($sg_layout, $static_sg_layout)\\n    `sg_data` `=` custom<DynamicIndexList>($sg_data, $static_sg_data)\\n    (`inst_data` `=` custom<DynamicIndexList>($inst_data, $static_inst_data)^)?\\n    (`order` `=` $order^)?\\n    (`slice_dims` `=` $slice_dims^)?\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"transform.xegpu.set_gpu_launch_threads\",\n    \"summary\": \"Set number of threads for a given gpu.launch operation\",\n    \"description\": \"Overrides the x,y,z threads operands of a given `gpu.launch` operation in-place.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"threads\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_threads\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" }\n    ],\n    \"assemblyFormat\": \"$target\\n    `threads` `=` custom<DynamicIndexList>($threads, $static_threads)\\n    attr-dict `:` qualified(type(operands))\"\n  },\n  {\n    \"name\": \"transform.xegpu.set_op_layout_attr\",\n    \"summary\": \"Set xegpu.layout attribute of an op.\",\n    \"description\": \"Sets the `xegpu.layout` attribute of an op. By default it sets the anchor\\n    layout for XeGPU ops that support it. If `result=true` or `operand=true`,\\n    it sets the `layout_result_{index}` or `layout_operand_{index}` attribute,\\n    respectively, applicable to any op. The target operand/result value is\\n    defined by the `index` argument. The layout is defined by the `sg_layout`,\\n    `sg_data` and optional `inst_data` attributes. If `slice_dims` is provided,\\n    the `xegpu.layout` attribute is wrapped in an `xegpu.slice<..., dims=slice_dims>`\\n    attribute.\",\n    \"operands\": [\n      { \"name\": \"target\", \"type\": \"TransformHandleTypeInterface\" },\n      { \"name\": \"sg_layout\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"sg_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" },\n      { \"name\": \"inst_data\", \"type\": \"Variadic<TransformAnyParamTypeOrAnyHandle>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"DefaultValuedOptionalAttr<I64Attr, 0>\" },\n      { \"name\": \"static_sg_layout\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_sg_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"static_inst_data\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"order\", \"type\": \"DefaultValuedOptionalAttr<DenseI32ArrayAttr, {}>\" },\n      { \"name\": \"slice_dims\", \"type\": \"DefaultValuedOptionalAttr<DenseI64ArrayAttr, {}>\" },\n      { \"name\": \"result\", \"type\": \"DefaultValuedAttr<UnitAttr, false>\" },\n      { \"name\": \"operand\", \"type\": \"DefaultValuedAttr<UnitAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$target (`result` $result^)? (`operand` $operand^)? (`index` `=` $index^)?\\n    `sg_layout` `=` custom<DynamicIndexList>($sg_layout, $static_sg_layout)\\n    `sg_data` `=` custom<DynamicIndexList>($sg_data, $static_sg_data)\\n    (`inst_data` `=` custom<DynamicIndexList>($inst_data, $static_inst_data)^)?\\n    (`order` `=` $order^)?\\n    (`slice_dims` `=` $slice_dims^)?\\n    attr-dict `:` qualified(type(operands))\"\n  },\n  {\n    \"name\": \"transform.yield\",\n    \"summary\": \"Yields operation handles from a transform IR region\",\n    \"description\": \"This terminator operation yields operation handles from regions of the\\n    transform IR ops back to the containing op. It is not itself associated with\\n    any transformation on the payload IR and is used for flow purposes only.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Transform_AnyHandleOrParamType>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict (`:` type($operands)^)?\"\n  },\n  {\n    \"name\": \"triton_xla.atomic_spin_wait\",\n    \"summary\": \"Spin-wait while reading u32 value(s) atomically.\",\n    \"description\": \"Atomically read u32 value(s) from the memory location(s) specified by\\n      $ptr. The memory ordering guarantees are specified by the\\n      $mem_sync_(scope|semantic) attributes.\\n\\n      The loaded value is compared to $expected using the $comparator.\\n      As long as the comparison returns true, the spin-wait loop continues.\\n      If the comparison returns false, the spin-wait loop is finished.\\n\\n      NB: In the end only a single lane/thread within a program will\\n      write to (or read from) a given memory location so the synchronization\\n      happens between a single writing lane with a single reading lane. However,\\n      the operation will wait until all lanes within the block have synchronized\\n      so the end result is a block level memory synchronization.\\n\\n      For Memory Synchronization Scope, see comment on TTXLA_AtomicWriteOp.\\n      The following memory synchronization semantics are allowed:\\n        - relaxed: No memory ordering guarantees.\\n        - acquire: No reads or writes in the current block/program can be\\n          reordered before this wait. All writes in other programs that\\n          `release` the same memory location are visible in the current block.\\n\\n      Internally this operation expands into elementwise\\n      `ld.global.<semantic>.<scope>.u32` and a labelled loop.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"expected\", \"type\": \"TT_I32Like\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolLike>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mem_sync_scope\", \"type\": \"TT_MemSyncScopeAttr{gpu|cta|sys}\" },\n      { \"name\": \"mem_sync_semantic\", \"type\": \"TT_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" },\n      { \"name\": \"comparator\", \"type\": \"TTXLA_ComparatorAttr{equal_to|less_than}\" }\n    ],\n    \"assemblyFormat\": \"$mem_sync_scope `,` $mem_sync_semantic `,`\\n      $ptr `,` $comparator `,` $expected (`,` $mask^) ?  attr-dict `:`\\n      functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"triton_xla.atomic_write\",\n    \"summary\": \"Atomically write u32 value(s) to memory location(s).\",\n    \"description\": \"Atomically write u32 value(s) to the memory location(s) specified by\\n      $ptr. The memory ordering guarantees are specified by the\\n      $mem_sync_(scope|semantic) attribute.\\n\\n      An optional $mask argument can be provided to specify which of the\\n      sublanes/threads should be updated. The mask must be the same shape as\\n      the $ptr.\\n\\n      Memory Synchronization Scope:\\n        - cta: The write is visible to all threads within the same compute\\n          thread-block.\\n        - gpu: The write is visible to all threads within the same GPU.\\n        - sys: The write is visible to all threads within the system.\\n\\n      The following memory synchronization semantics are allowed:\\n        - relaxed: No memory ordering guarantees.\\n        - release: All writes that are issued before this one will be\\n          completed before the store is visible to other threads.\\n\\n      Internally this operation expands into st.global.<scope>.<semantic>.u32\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"value\", \"type\": \"TT_I32Like\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolLike>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mem_sync_scope\", \"type\": \"TT_MemSyncScopeAttr{gpu|cta|sys}\" },\n      { \"name\": \"mem_sync_semantic\", \"type\": \"TT_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" }\n    ],\n    \"assemblyFormat\": \"$mem_sync_scope `,` $mem_sync_semantic `,`\\n    $ptr `,` $value (`,` $mask^) ? attr-dict `:`\\n    functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"triton_xla.block_barrier\",\n    \"summary\": \"A block-level barrier for inter-GPU synchronization.\",\n    \"description\": \"This operation implements a block-level barrier between multiple GPUs.\\n    It takes a pointer of pointers to signal buffers (one from each\\n    participating GPU), the rank of the current device, and a signal value to\\n    write/wait for. The signal values on consequent calls to this operation must\\n    increase monotonically for the same signal buffers pointer. A block on one\\n    GPU synchronizes with blocks on other GPUs with the same block id.\\n\\n    *NOTE* Block orchestration order is not guaranteed across GPUs,\\n    so there is a chance of a deadlock should the number of blocks be greater\\n    than the number of SMs on a GPU. That is to say that if BlockN is launched\\n    on GPU0 and BlockM on GPU1 and they both wait for each other to finish,\\n    and there is no place to schedule more blocks on either GPU, then we\\n    will have a deadlock. In general, the user of this operation should avoid\\n    this by not oversubscribing the number of available SMs on a GPU. There is\\n    also a secondary restriction that the number of threads per block must\\n    exceed the number of participating GPUs. In the nominal case, where we are\\n    within a single NV Link domain, this should not be an issue since the number\\n    of participating GPUs would usually be much smaller than the number of\\n    threads per block.\\n\\n    The synchronization logic is as follows:\\n    1. Each GPU (identified by `device_rank`) writes the `signal` value to an\\n       index `blockId * world_size + device_rank` in *every* buffer provided in\\n       `$signal_buffers`.\\n    2. After writing, GPU `r` polls its own buffer (`$signal_buffers[r]`).\\n    3. It waits until the values at locations corresponding to all other ranks\\n       (i.e., `blockId * world_size + [0..world_size)` are greater than or equal\\n       to the `signal` value.\\n    4. When the wait is over, all GPUs working on the same `blockId` have\\n       successfully synchronized.\\n\\n    This operation ensures that GPUs in the same synchronization group do not\\n    get more than one \\\"wave\\\" (or chunk) of data processing ahead of each other.\\n    For clarity, a wave here is a set of work items that are processed together.\\n    A single thread block for instance can process multiple waves. In such a\\n    scenario, any given GPU can be at most 1 wave ahead of the other GPUs for\\n    the same block id.\\n\\n    Internally, this operation uses TTXLA_Atomic(Write|SpinWait)Op on signal\\n    buffers to synchronize all participating GPUs.\",\n    \"operands\": [\n      { \"name\": \"signal_buffers\", \"type\": \"TT_PtrOf<[TT_PtrOf<[I32]>]>\" },\n      { \"name\": \"device_rank\", \"type\": \"I32\" },\n      { \"name\": \"signal_value\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"world_size\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$signal_buffers `,` $device_rank `,` $signal_value `,` attr-dict `:`\\n    functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"triton_xla.extract\",\n    \"summary\": \"Extract a tile from a pointer.\",\n    \"description\": \"Offsets, strides, and sizes operands specify the result tensor tile\\n    to extract. Shape and minor-to-major layout specify the layout of the source\\n    pointer.\\n\\n    Assembly format:\\n      from %src as memref<...> [%offsets] [%sizes] [%strides] : tensor_type\\n\\n    Example:\\n      ```\\n      %extracted_tensor = triton_xla.extract from %src\\n        as memref<512x128xbf16, #xtile.layout<[1, 0]>>\\n        [0, 0] [16, 64] [128, 1] : tensor<16x64xbf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"src_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"src_layout\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"`from` $src `as` custom<AsMemRefType>(type($src), $src_shape, $src_layout)\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"triton_xla.get_peer_ptr\",\n    \"summary\": \"Extract the pointer to the given symmetric memory `address` on the given\\n    `peer` device. An `address` should point to the memory of the given kernel\\n    argument with `argument_index`. The result is calculated using the symmetric\\n    memory `metadata` constructed at the runtime.\\n    To calculate offsets operation also need to know the number of devices\\n    participating in the collective operation (`world_size`).\",\n    \"operands\": [\n      { \"name\": \"address\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"peer_id\", \"type\": \"I64\" },\n      { \"name\": \"metadata\", \"type\": \"TT_PtrLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_PtrLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"argument_index\", \"type\": \"I32Attr\" },\n      { \"name\": \"world_size\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$address `,` $peer_id `,` $metadata `,` attr-dict `:`\\n    functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"triton_xla.get_rank\",\n    \"summary\": \"Extract the device rank from the collectives metadata.\",\n    \"operands\": [\n      { \"name\": \"metadata\", \"type\": \"TT_PtrLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$metadata attr-dict `:` type($metadata) `->` type($result)\"\n  },\n  {\n    \"name\": \"triton_xla.get_tid\",\n    \"summary\": \"Get the thread ID within a triton kernel.\",\n    \"description\": \"This operation returns the thread ID within a kernel.\\n    Only the X dimension is supported. The result is a 32-bit\\n    integer which in CUDA terms is threadIdx.x.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"triton_xla.insert\",\n    \"summary\": \"Insert a tile into a pointer.\",\n    \"description\": \"Offsets, strides, and source tensor size are used to specify the tile to\\n    insert. Shape and minor-to-major layout specify the layout of the\\n    destination pointer.\\n\\n    Assembly format:\\n      %src into %dst as memref<...> [%offsets] [%sizes] [%strides] : tensor_type\\n\\n    Example:\\n      ```\\n      triton_xla.insert %src into %dst\\n        as memref<512x128xbf16, #xtile.layout<[1, 0]>>\\n        [0, 0] [8, 8] [1, 1] : tensor<8x8xbf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyStaticShapeTensor\" },\n      { \"name\": \"dst\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"static_strides\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"dst_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"dst_layout\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$src `into`\\n    $dst `as` custom<AsMemRefType>(type($dst), $dst_shape, $dst_layout)\\n    custom<DynamicIndexList>($offsets, $static_offsets)\\n    custom<DynamicIndexList>($sizes, $static_sizes)\\n    custom<DynamicIndexList>($strides, $static_strides)\\n    attr-dict `:` type($src)\"\n  },\n  {\n    \"name\": \"triton_xla.memref_to_ptr\",\n    \"summary\": \"A specialized version of unrealized_conversion_cast that converts a\\n    memref to a pointer.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Ptr\" }\n    ],\n    \"assemblyFormat\": \"$src `from` type($src) `to` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"triton_xla.ptr_to_memref\",\n    \"summary\": \"A specialized version of unrealized_conversion_cast that converts a\\n    pointer to a memref.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Ptr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$src `from` type($src) `to` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"triton_xla.squeeze_dims\",\n    \"summary\": \"Remove a size-1 dimension from a tensor.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"trtrt.compiled_func\",\n    \"summary\": \"represents a serialized TensorRT plan file\",\n    \"description\": \"The `trtrt.compiled_func` op is a global operation that represents\\n    a compiled TensorRT function (an \\\"engine\\\" or \\\"plan file\\\")\\n    Its binary data is contained in `value`, which is the output of the\\n    TensorRT builder.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $sym_name $value\"\n  },\n  {\n    \"name\": \"trtrt.enqueue\",\n    \"description\": \"Asynchronously executes the computation represented by the\\n    `execution_context` on the specified CUDA stream. This operation\\n    is a bufferizable destination-passing-style (DPS) operation.\\n\\n    This means that the `inputs` and `outputs` can accept either\\n    all `tensor` types or all `memref` types. If the types are `tensor`\\n    types, then the the values passed to the `outs` parameter must\\n    be equal in type and number to the operation's results.\\n\\n    When the `inputs` and `outputs` are `memref` types, then the\\n    operation should have no results.\\n\\n    The `host_tensor_args` attribute is a list of indices into the\\n    `inputs` list indicating which arguments should be host tensors.\",\n    \"operands\": [\n      { \"name\": \"execution_context\", \"type\": \"TensorRTRuntime_Context\" },\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyShaped>\" },\n      { \"name\": \"outs\", \"type\": \"Variadic<AnyShaped>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"host_tensor_args\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$execution_context `stream` `(` $stream `)` ` `\\n    (`host_tensor_args` $host_tensor_args^ ` ` )?\\n    `(` $inputs `)` `outs` `(` $outs `)`\\n    attr-dict `:` functional-type($inputs, $outs)\"\n  },\n  {\n    \"name\": \"trtrt.enqueue_alloc\",\n    \"description\": \"Asynchronously executes the computation represented by the\\n    `execution_context` on the specified CUDA stream. This operation\\n    can accept inputs of either tensor or memref types and returns\\n    results of either tensor or memref types.\",\n    \"operands\": [\n      { \"name\": \"execution_context\", \"type\": \"TensorRTRuntime_Context\" },\n      { \"name\": \"stream\", \"type\": \"CUDA_Stream\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyTypeOf<[ AnyMemRef, AnyTensor ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyTypeOf<[ AnyMemRef, AnyTensor ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"host_tensor_args\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"assemblyFormat\": \"$execution_context `stream` `(` $stream `)` ` `\\n    (`host_tensor_args` $host_tensor_args^ ` ` )?\\n    `(` $inputs `)`\\n    attr-dict `:` functional-type($inputs, $results)\"\n  },\n  {\n    \"name\": \"trtrt.get_function\",\n    \"summary\": \"retrieves a TensorRT function handle from a compiled module\",\n    \"description\": \"The `cuda.get_function` operation references a `trtrt.compiled_func`\\n    and returns an opaque `func.func` (representing an \\\"execution context\\\"\\n    from the TensorRT runtime API).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorRTRuntime_Context\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"module\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict $module `:` type($result)\"\n  },\n  {\n    \"name\": \"ts.as_fixed_rank_shape.0\",\n    \"summary\": \"Convert TensorShape to FixedRankShape operation\",\n    \"description\": \"An operation that converts a TensorShape to a FixedRankShape\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_FixedRankShape<0>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.as_fixed_rank_shape.1\",\n    \"summary\": \"Convert TensorShape to FixedRankShape operation\",\n    \"description\": \"An operation that converts a TensorShape to a FixedRankShape\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_FixedRankShape<1>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.as_fixed_rank_shape.2\",\n    \"summary\": \"Convert TensorShape to FixedRankShape operation\",\n    \"description\": \"An operation that converts a TensorShape to a FixedRankShape\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_FixedRankShape<2>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.as_fixed_rank_shape.3\",\n    \"summary\": \"Convert TensorShape to FixedRankShape operation\",\n    \"description\": \"An operation that converts a TensorShape to a FixedRankShape\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_FixedRankShape<3>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.build_partial_shape\",\n    \"summary\": \"Build partial tensor shape operation\",\n    \"description\": \"An operation that builds a partial tensor shape.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_PartialShape\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"ts.build_shape\",\n    \"summary\": \"Build tensor shape operation\",\n    \"description\": \"An operation that builds a tensor shape of a given rank and extents.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_Shape\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"ts.build_unranked_partial_shape\",\n    \"summary\": \"Build unranked partial tensor shape operation\",\n    \"description\": \"An operation that builds an unranked partial tensor shape.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_PartialShape\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ts.equal_shape\",\n    \"summary\": \"Checks if two tensor shapes are equal\",\n    \"description\": \"An operation that checks if two tensor shapes are equal.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.get_dimension\",\n    \"summary\": \"Returns the dimension size at the given shape index\",\n    \"description\": \"An operation that returns the dimension size at the given shape index.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.get_num_elements\",\n    \"summary\": \"Returns the number of elements in the shape\",\n    \"description\": \"An operation that returns the number of elements in the shape.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.print_fixed_rank_shape.0\",\n    \"summary\": \"Print FixedRankShape operation\",\n    \"description\": \"An operation that prints a FixedRankShape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_FixedRankShape<0>\" },\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.print_fixed_rank_shape.1\",\n    \"summary\": \"Print FixedRankShape operation\",\n    \"description\": \"An operation that prints a FixedRankShape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_FixedRankShape<1>\" },\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.print_fixed_rank_shape.2\",\n    \"summary\": \"Print FixedRankShape operation\",\n    \"description\": \"An operation that prints a FixedRankShape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_FixedRankShape<2>\" },\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.print_fixed_rank_shape.3\",\n    \"summary\": \"Print FixedRankShape operation\",\n    \"description\": \"An operation that prints a FixedRankShape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_FixedRankShape<3>\" },\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.print_partial_shape\",\n    \"summary\": \"Prints the shape of the given partial tensor shape\",\n    \"description\": \"An operation that prints the shape of the given partial tensor shape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_PartialShape\" },\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.print_shape\",\n    \"summary\": \"Print tensor shape operation\",\n    \"description\": \"An operation that prints a tensor shape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_Shape\" },\n      { \"name\": \"in_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"results\": [\n      { \"name\": \"out_ch\", \"type\": \"TFRT_ChainType\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.to_partial_shape\",\n    \"summary\": \"Converts tensor shape to partial tensor shape operation\",\n    \"description\": \"An operation that converts a tensor shape to partial tensor shape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_Shape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_PartialShape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"ts.to_shape\",\n    \"summary\": \"Converts partial tensor shape to tensor shape operation\",\n    \"description\": \"An operation that converts a partial tensor shape to tensor shape.\",\n    \"operands\": [\n      { \"name\": \"shape\", \"type\": \"TS_PartialShape\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"TS_Shape\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict\"\n  },\n  {\n    \"name\": \"tt.addptr\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"offset\", \"type\": \"TT_IntLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_PtrLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'ptr', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $offset attr-dict `:` type($result) `,` type($offset)\"\n  },\n  {\n    \"name\": \"tt.advance\",\n    \"summary\": \"Advance a tensor pointer by offsets\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_TensorPtr\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_TensorPtr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'ptr', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` `[` $offsets `]` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.assert\",\n    \"summary\": \"Device-side assert, as in CUDA for correctness checking\",\n    \"description\": \"`tt.assert` takes a condition tensor and a message string.\\n    If the condition is false, the message is printed, and the program is aborted.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"AnyTypeOf<[I1, I1Tensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$condition `,` $message attr-dict `:` type($condition)\"\n  },\n  {\n    \"name\": \"tt.atomic_cas\",\n    \"summary\": \"atomic cas\",\n    \"description\": \"compare $cmp with data $old at location $ptr,\\n\\n        if $old == $cmp, store $val to $ptr,\\n\\n        else store $old to $ptr,\\n\\n        return $old\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"cmp\", \"type\": \"TT_Type\" },\n      { \"name\": \"val\", \"type\": \"TT_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sem\", \"type\": \"TT_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" },\n      { \"name\": \"scope\", \"type\": \"TT_MemSyncScopeAttr{gpu|cta|sys}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'cmp', 'ptr', 'getPointerTypeSameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'val', 'ptr', 'getPointerTypeSameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$sem `,` $scope `,` $ptr `,` $cmp `,` $val attr-dict `:`\\n      functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tt.atomic_rmw\",\n    \"summary\": \"atomic rmw\",\n    \"description\": \"load data at $ptr, do $rmw_op with $val, and store result to $ptr.\\n\\n        return old value at $ptr\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"val\", \"type\": \"TT_Type\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolLike>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"atomic_rmw_op\", \"type\": \"TT_AtomicRMWAttr{and|or|xor|add|fadd|max|min|umax|umin|exch}\" },\n      { \"name\": \"sem\", \"type\": \"TT_MemSemanticAttr{relaxed|acquire|release|acq_rel}\" },\n      { \"name\": \"scope\", \"type\": \"TT_MemSyncScopeAttr{gpu|cta|sys}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'val', 'ptr', 'getPointerTypeSameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'val', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$atomic_rmw_op `,` $sem `,` $scope `,` $ptr `,` $val (`,` $mask^)?  attr-dict `:`\\n      functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tt.bitcast\",\n    \"summary\": \"Cast between types of the same bitwidth\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Type\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.broadcast\",\n    \"summary\": \"broadcast a tensor\",\n    \"description\": \"For a given tensor, broadcast changes one or more dimensions with size 1\\n      to a new size, e.g. tensor<1x32x1xf32> -> tensor<2x32x4xf32>.  You cannot\\n      change the size of a non-1 dimension.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.call\",\n    \"summary\": \"call operation\",\n    \"description\": \"The `tt.call` operation represents a direct call to a function that is\\n    within the same symbol scope as the call. The operands and result types of\\n    the call must match the specified function type. The callee is encoded as a\\n    symbol reference attribute named \\\"callee\\\".\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = tt.call @my_add(%0, %1) : (f32, f32) -> f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"tt.cat\",\n    \"summary\": \"concatenate 2 tensors\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.clampf\",\n    \"summary\": \"Clamp operation for floating point types\",\n    \"description\": \"Clamp operation for floating point types.\\n\\n        The operation takes three arguments: x, min, and max. It returns a tensor of the same shape as x with its values clamped to the range [min, max].\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TT_FloatLike\" },\n      { \"name\": \"min\", \"type\": \"TT_FloatLike\" },\n      { \"name\": \"max\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"propagateNan\", \"type\": \"TT_PropagateNanAttr{none|all}\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $min `,` $max `,` `propagateNan` `=` $propagateNan attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.descriptor_gather\",\n    \"summary\": \"gather multiple rows from a descriptor into a single tensor\",\n    \"description\": \"The `tt.descriptor_gather` op will be lowered to NVIDIA TMA\\n    gather operations on targets that support it.\\n\\n    `desc_ptr` is a pointer to the TMA descriptor allocated in global memory.\\n    The descriptor block must have 1 row and the indices must be a 1D tensor.\\n    Accordingly, the result is a 2D tensor multiple rows.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"x_offsets\", \"type\": \"RankedTensorOf<[I32]>\" },\n      { \"name\": \"y_offset\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $x_offsets `,` $y_offset `]`\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tt.descriptor_load\",\n    \"summary\": \"Load from descriptor\",\n    \"description\": \"This operation will be lowered to Nvidia TMA load operation on targets supporting it.\\n    `desc` is a tensor descriptor object.\\n    The destination tensor type and shape must match the descriptor otherwise the result is undefined.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, ::mlir::triton::EvictionPolicy::NORMAL>\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $indices `]`\\n    oilist(\\n      `cacheModifier` `=` $cache |\\n      `evictionPolicy` `=` $evict\\n    )\\n    attr-dict `:` qualified(type($desc)) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.descriptor_reduce\",\n    \"summary\": \"performs a reducing store operation based on a descriptor\",\n    \"description\": \"This operation will be lowered to Nvidia TMA store operation on targets supporting it.\\n    `desc` is a tensor descriptor object.\\n    The shape and types of `src` must match the descriptor otherwise the result is undefined.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"TT_DescriptorReduceKindAttr{add|min|max|inc|dec|and|or|xor}\" }\n    ],\n    \"assemblyFormat\": \"$kind `,` $desc `[` $indices `]` `,` $src\\n    attr-dict `:` qualified(type($desc)) `,` type($src)\"\n  },\n  {\n    \"name\": \"tt.descriptor_scatter\",\n    \"summary\": \"scatter multiple rows to a descriptor from a single tensor\",\n    \"description\": \"The `tt.descriptor_scatter` op will be lowered to NVIDIA TMA\\n    scatter operations on targets that support it.\\n\\n    `desc_ptr` is a pointer to the TMA descriptor allocated in global memory.\\n    The descriptor block must have 1 row and the indices must be a 1D tensor.\\n    Accordingly, the result is a 2D tensor multiple rows.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"x_offsets\", \"type\": \"RankedTensorOf<[I32]>\" },\n      { \"name\": \"y_offset\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $x_offsets `,` $y_offset `]` `,` $src\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"tt.descriptor_store\",\n    \"summary\": \"store value based on descriptor\",\n    \"description\": \"This operation will be lowered to Nvidia TMA store operation on targets supporting it.\\n    `desc` is a tensor descriptor object.\\n    The shape and types of `src` must match the descriptor otherwise the result is undefined.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $indices `]` `,` $src\\n    attr-dict `:` qualified(type($desc)) `,` type($src)\"\n  },\n  {\n    \"name\": \"tt.dot\",\n    \"summary\": \"dot\",\n    \"description\": \"$d = matrix_multiply($a, $b) + $c. $inputPrecision describes how to exercise the TC\\n        when the inputs are f32. It can be one of: tf32, tf32x3, ieee, bf16x3, bf16x6.\\n        tf32: use TC with tf32 ops.\\n        tf32x3: implement the 3xTF32 trick. For more info see the pass in F32DotTC.cpp\\n        bf16x3: implement the 3xBF16 trick. For more info see the pass in F32DotTC.cpp\\n        bf16x6: implement the 6xBF16 trick. For more info see the pass in F32DotTC.cpp\\n        ieee: don't use TC, implement dot in software.\\n        If the GPU does not have Tensor cores or the inputs are not f32, this flag is ignored.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TT_FpIntTensor\" },\n      { \"name\": \"b\", \"type\": \"TT_FpIntTensor\" },\n      { \"name\": \"c\", \"type\": \"TT_FpIntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"d\", \"type\": \"TT_FpIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inputPrecision\", \"type\": \"DefaultValuedAttr<TT_InputPrecisionAttr{tf32|tf32x3|ieee|bf16x3|bf16x6}, ::mlir::triton::InputPrecision::IEEE>\" },\n      { \"name\": \"maxNumImpreciseAcc\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'d', 'c', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$a`,` $b`,` $c (`,` `inputPrecision` `=` $inputPrecision^)? attr-dict `:`\\n      type($a) `*` type($b) `->` type($d)\"\n  },\n  {\n    \"name\": \"tt.dot_scaled\",\n    \"summary\": \"dot_scaled\",\n    \"description\": \"$d = matrix_multiply(scale($a, $a_scale), scale($b, $b_scale)) + $c.\\n        Where scale(x, s) is a function that applies the scale per block following microscaling spec.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"RankedTensorOf<[TT_Float, I8]>\" },\n      { \"name\": \"b\", \"type\": \"RankedTensorOf<[TT_Float, I8]>\" },\n      { \"name\": \"c\", \"type\": \"TT_FloatTensor\" },\n      { \"name\": \"a_scale\", \"type\": \"Optional<RankedTensorOf<[ TT_Float, I8 ]>>\" },\n      { \"name\": \"b_scale\", \"type\": \"Optional<RankedTensorOf<[ TT_Float, I8 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"d\", \"type\": \"TT_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_elem_type\", \"type\": \"TT_ScaleDotElemTypeAttr{e4m3|e5m2|e2m3|e3m2|e2m1|bf16|fp16}\" },\n      { \"name\": \"b_elem_type\", \"type\": \"TT_ScaleDotElemTypeAttr{e4m3|e5m2|e2m3|e3m2|e2m1|bf16|fp16}\" },\n      { \"name\": \"fastMath\", \"type\": \"BoolAttr\" },\n      { \"name\": \"lhs_k_pack\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"rhs_k_pack\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'d', 'c', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$a (`scale` $a_scale^)? `,` $b (`scale` $b_scale^)? `,` $c\\n      `lhs` `=` $a_elem_type `rhs` `=` $b_elem_type attr-dict\\n      `:` type($a) (`,` type($a_scale)^)? `*` type($b) (`,` type($b_scale)^)? `->` type($d)\"\n  },\n  {\n    \"name\": \"tt.elementwise_inline_asm\",\n    \"summary\": \"inline assembly applying an elementwise operation to a group of packed elements.\",\n    \"description\": \"Runs an inline asm block to generate one or more tensors.\\n\\n    The asm block is given `packed_element` elements at a time.  Exactly which\\n    elems it receives is unspecified.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyTypeOf<[ TT_Type ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TT_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"asm_string\", \"type\": \"StrAttr\" },\n      { \"name\": \"constraints\", \"type\": \"StrAttr\" },\n      { \"name\": \"pure\", \"type\": \"BoolAttr\" },\n      { \"name\": \"packed_element\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$asm_string attr-dict ($args^ `:` type($args))? `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.expand_dims\",\n    \"summary\": \"expand_dims\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.extern_elementwise\",\n    \"description\": \"call an external function $symbol implemented in $libpath/$libname with $args\\n        return $libpath/$libname:$symbol($args...)\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<TT_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"libname\", \"type\": \"StrAttr\" },\n      { \"name\": \"libpath\", \"type\": \"StrAttr\" },\n      { \"name\": \"symbol\", \"type\": \"StrAttr\" },\n      { \"name\": \"pure\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, $result)\"\n  },\n  {\n    \"name\": \"tt.fp_to_fp\",\n    \"summary\": \"Floating point casting for custom types\",\n    \"description\": \"Floating point casting for custom types (F8), and non-default rounding modes.\\n\\n        F8 <-> FP16, BF16, FP32, FP64\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rounding\", \"type\": \"OptionalAttr<TT_RoundingModeAttr{rtz|rtne}>\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict  (`,` `rounding` `=` $rounding^)? `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.func\",\n    \"summary\": \"An operation with a name containing a single `SSACFG` region\",\n    \"description\": \"Operations within the function cannot implicitly capture values defined\\n    outside of the function, i.e. Functions are `IsolatedFromAbove`. All\\n    external references must use function arguments or attributes that establish\\n    a symbolic connection (e.g. symbols referenced by name via a string\\n    attribute like SymbolRefAttr). An external function declaration (used when\\n    referring to a function declared in some other module) has no body. While\\n    the MLIR textual form provides a nice inline syntax for function arguments,\\n    they are internally represented as “block arguments” to the first block in\\n    the region.\\n\\n    Only dialect attribute names may be specified in the attribute dictionaries\\n    for function arguments, results, or the function itself.\\n\\n    Example:\\n\\n    ```mlir\\n    // External function definitions.\\n    tt.func @abort()\\n    tt.func @scribble(i32, i64, memref<? x 128 x f32, #layout_map0>) -> f64\\n\\n    // A function that returns its argument twice:\\n    tt.func @count(%x: i64) -> (i64, i64)\\n      attributes {fruit: \\\"banana\\\"} {\\n      return %x, %x: i64, i64\\n    }\\n\\n    // A function with an argument attribute\\n    tt.func @example_fn_arg(%x: i32 {swift.self = unit})\\n\\n    // A function with a result attribute\\n    tt.func @example_fn_result() -> (f64 {dialectName.attrName = 0 : i64})\\n\\n    // A function with an attribute\\n    tt.func @example_fn_attr() attributes {dialectName.attrName = false}\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"tt.gather\",\n    \"summary\": \"local gather operation\",\n    \"description\": \"Gather elements from the input tensor using the indices tensor along a\\n    single specified axis. The output tensor has the same shape as the indices\\n    tensor. The input and indices tensors must have the same number of\\n    dimension, and each dimension of the indices tensor that is not the gather\\n    dimension cannot be greater than the corresponding dimension in the input\\n    tensor.\\n\\n    The `efficient_layout` attribute is set when the compiler has determined an\\n    optimized layout for the operation, indicating that it should not be\\n    changed.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TT_IntTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"efficient_layout\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $indices `]` attr-dict `:`\\n    functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"tt.get_num_programs\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"TT_ProgramDim{x|y|z}\" }\n    ],\n    \"assemblyFormat\": \"$axis attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.get_program_id\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"TT_ProgramDim{x|y|z}\" }\n    ],\n    \"assemblyFormat\": \"$axis attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.histogram\",\n    \"summary\": \"return a histogram of the inputs.\",\n    \"description\": \"Return the histogram of the input tensor. The number of bins is equal to\\n    the dimension of the output tensor. Each bins has a width of 1 and bins\\n    start at 0.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_IntTensor\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolLike>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_IntTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'src', 'mask', 'getI1SameShape($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$src (`,` $mask^)? attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.int_to_ptr\",\n    \"summary\": \"Cast int64 to pointer\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_I64Like\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_PtrLike\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.join\",\n    \"summary\": \"join two tensors along a new, minor dimension\",\n    \"description\": \"For example, if the two input tensors are 4x8xf32, returns a tensor of\\n        shape 4x8x2xf32.\\n\\n        Because Triton tensors always have a power-of-two number of elements,\\n        the two input tensors must have the same shape.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"rhs\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs attr-dict `:` type($lhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.load\",\n    \"summary\": \"Load from a pointer or tensor of pointers\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolLike>\" },\n      { \"name\": \"other\", \"type\": \"Optional<TT_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Type\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, ::mlir::triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, ::mlir::triton::EvictionPolicy::NORMAL>\" },\n      { \"name\": \"isVolatile\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'ptr', 'result', 'getPointeeType($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'ptr', 'mask', 'getI1SameShape(getPointeeType($_self))'>\" },\n      { \"type\": \"TypesMatchWith<'ptr', 'other', 'getPointeeType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr (`,` $mask^)? (`,` $other^)?\\n      oilist(\\n        `cacheModifier` `=` $cache |\\n        `evictionPolicy` `=` $evict\\n      )\\n      attr-dict `:` type($ptr)\"\n  },\n  {\n    \"name\": \"tt.make_range\",\n    \"summary\": \"make range\",\n    \"description\": \"Returns an 1D int32 tensor.\\n\\n        Values span from $start to $end (exclusive), with step = 1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_IntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start\", \"type\": \"I32Attr\" },\n      { \"name\": \"end\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.make_tensor_descriptor\",\n    \"summary\": \"Make a tensor descriptor type with meta information of the parent tensor and block size\",\n    \"description\": \"`tt.make_tensor_descriptor` takes both meta information of the parent tensor and the block size,\\n      and returns a descriptor object which can be used to load/store from the tensor in global memory.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_TensorDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"DefaultValuedAttr<TT_PaddingOptionAttr{zero|nan}, ::mlir::triton::PaddingOption::PAD_ZERO>\" }\n    ],\n    \"assemblyFormat\": \"$base `,` `[` $shape `]` `,` `[` $strides `]` attr-dict `:` type($base) `,` type($result)\"\n  },\n  {\n    \"name\": \"tt.make_tensor_ptr\",\n    \"summary\": \"Make a tensor pointer type with meta information of the parent tensor and the block specified\",\n    \"description\": \"`tt.make_tensor_ptr` takes both meta information of the parent tensor and the block tensor, then it returns a\\n      pointer to the block tensor, e.g. returns a type of `tt.ptr<tensor<8x8xf16>>`.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"TT_Ptr\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_TensorPtr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'base', 'getPointerType(getElementTypeOfTensorPointerType($_self), getAddressSpace($_self))'>\" }\n    ],\n    \"assemblyFormat\": \"$base `,` `[` $shape `]` `,` `[` $strides `]` `,` `[` $offsets `]` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.map_elementwise\",\n    \"summary\": \"Map a scalar subregion over a tensor\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TT_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pack\", \"type\": \"I32Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"scalarOp\", \"type\": \"AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"tt.map_elementwise.return\",\n    \"summary\": \"terminator for map elementwise operator\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($result^ `:` type($result))?\"\n  },\n  {\n    \"name\": \"tt.mulhiui\",\n    \"summary\": \"Most significant N bits of the 2N-bit product of two integers\",\n    \"description\": \"Most significant N bits of the 2N-bit product of two integers.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TT_IntLike\" },\n      { \"name\": \"y\", \"type\": \"TT_IntLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_IntLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $y attr-dict `:` type($x)\"\n  },\n  {\n    \"name\": \"tt.precise_divf\",\n    \"summary\": \"Precise div for floating point types\",\n    \"description\": \"Precise div for floating point types.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TT_FloatLike\" },\n      { \"name\": \"y\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$x `,` $y attr-dict `:` type($x)\"\n  },\n  {\n    \"name\": \"tt.precise_sqrt\",\n    \"summary\": \"Precise sqrt for floating point types\",\n    \"description\": \"Precise sqrt for floating point types.\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_FloatLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$x attr-dict `:` type($x)\"\n  },\n  {\n    \"name\": \"tt.print\",\n    \"summary\": \"Device-side print, as in CUDA for debugging\",\n    \"description\": \"`tt.print` takes a literal string prefix and an arbitrary number of scalar or tensor arguments that should be printed.\\n    format are generated automatically from the arguments.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyTypeOf<[ TT_Type ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prefix\", \"type\": \"StrAttr\" },\n      { \"name\": \"hex\", \"type\": \"BoolAttr\" },\n      { \"name\": \"isSigned\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$prefix attr-dict (`:` $args^ `:` type($args))?\"\n  },\n  {\n    \"name\": \"tt.ptr_to_int\",\n    \"summary\": \"Cast pointer to int64\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_PtrLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_I64Like\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.reduce\",\n    \"summary\": \"Reduction using generic combination algorithm\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TT_Type>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"combineOp\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tt.reduce.return\",\n    \"summary\": \"terminator for reduce operator\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.reshape\",\n    \"summary\": \"reinterpret a tensor to a different shape. It may change elements order if the attribute is set.\",\n    \"description\": \"reinterpret a tensor to a different shape.\\n\\n        If allow_reorder is set the compiler is free to change the order of\\n        elements to generate more efficient code.\\n\\n        If efficient_layout is set, this is a hint that the destination layout should be kept for performance reason.\\n        The compiler is still free to change it for better performance.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"allow_reorder\", \"type\": \"UnitAttr\" },\n      { \"name\": \"efficient_layout\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$src (`allow_reorder` $allow_reorder^)? (`efficient_layout` $efficient_layout^)? attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.return\",\n    \"summary\": \"Function return operation\",\n    \"description\": \"The `tt.return` operation represents a return operation within a function.\\n    The operation takes variable number of operands and produces no results.\\n    The operand number and types must match the signature of the function\\n    that contains the operation.\\n\\n    Example:\\n\\n    ```mlir\\n    tt.func @foo() : (i32, f8) {\\n      ...\\n      tt.return %0, %1 : i32, f8\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($srcs^ `:` type($srcs))?\"\n  },\n  {\n    \"name\": \"tt.scan\",\n    \"summary\": \"Associative scan using generic combination algorithm\",\n    \"operands\": [\n      { \"name\": \"srcs\", \"type\": \"Variadic<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<TT_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" },\n      { \"name\": \"reverse\", \"type\": \"BoolAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"combineOp\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"tt.scan.return\",\n    \"summary\": \"terminator for scan operator\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tt.splat\",\n    \"summary\": \"splat\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Type\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.split\",\n    \"summary\": \"splits a tensor into two, along its last dimension\",\n    \"description\": \"The input must be a tensor whose last dimension has size 2.  Returns two\\n        tensors, src[..., 0] and src[..., 1].\\n\\n        For example, if the input shape is 4x8x2xf32, returns two tensors of\\n        shape 4x8xf32.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"outLHS\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"outRHS\", \"type\": \"TT_Tensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'outLHS', 'outRHS', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($outLHS)\"\n  },\n  {\n    \"name\": \"tt.store\",\n    \"summary\": \"Store through a pointer or tensor of pointers\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"value\", \"type\": \"TT_Type\" },\n      { \"name\": \"mask\", \"type\": \"Optional<TT_BoolLike>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, triton::EvictionPolicy::NORMAL>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'ptr', 'value', 'getPointeeType($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'ptr', 'mask', 'getI1SameShape(getPointeeType($_self))'>\" }\n    ],\n    \"assemblyFormat\": \"$ptr `,` $value (`,` $mask^)?\\n      oilist(`cacheModifier` `=` $cache | `evictionPolicy` `=` $evict)\\n      attr-dict `:` type($ptr)\"\n  },\n  {\n    \"name\": \"tt.trans\",\n    \"summary\": \"rearrange the dimensions of a tensor\",\n    \"description\": \"For example, given a tensor x with shape [1,2,4], transpose(x) with\\n      order=[2,0,1] rearranges the tensor to have shape [4,1,2].\\n\\n      Although this op is called \\\"trans\\\", it implements both tl.trans() and\\n      tl.permute().  (\\\"permute\\\" might be a better name, but it's called \\\"trans\\\"\\n      because originally it only supported 2D tensors.)\\n\\n      ## Implementation note on encodings:\\n\\n      In the TritonGPU dialect (and probably others), an encoding is chosen for\\n      this op's output so it's a nop from the perspective of code generation.\\n\\n      For example, suppose tensor x has an encoding such that GPU thread [i,j,k]\\n      has a register containing element [i,j,k] of the tensor.  Now we transpose\\n      x with order [2,1,0], i.e. we reverse the order of its dimensions.  In\\n      TritonGPU, we will choose a layout for the output of the transpose so that\\n      GPU thread [i,j,k] has element [k,j,i] of transpose(x).  But this is the\\n      same element it had before!  All we've done is \\\"rename\\\" the element that\\n      thread [i,j,k] has.\\n\\n      The \\\"real\\\" transpose -- i.e. moving data between GPU threads -- occurs in\\n      convertLayout ops that appear before and/or after the operation.\\n\\n      We do this so that you can chain multiple data-movement ops (e.g.\\n      transpose+reshape+concat) without going to shared memory after each one.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"tt.unsplat\",\n    \"summary\": \"convert a tensor with a single element to a scalar\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Type\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src)\"\n  },\n  {\n    \"name\": \"ttcore.cpu_module\",\n    \"summary\": \"Module-wrapper operation for CPU ops\",\n    \"description\": \"Custom module operation that can a single ModuleOp, which should contain all funcs which should be run on CPU.\\n\\n    Example:\\n    ```mlir\\n    ttcore.cpu_module {\\n      module {\\n        func.func foo() { ... }\\n      }\\n    }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword regions\"\n  },\n  {\n    \"name\": \"ttcore.device\",\n    \"summary\": \"Named device\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"device_attr\", \"type\": \"TTCore_DeviceAttr\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `=` $device_attr attr-dict\"\n  },\n  {\n    \"name\": \"ttcore.device_module\",\n    \"summary\": \"Module-wrapper operation for device ops\",\n    \"description\": \"Custom module operation that can a single ModuleOp, which should contain all funcs which should be run on device.\\n\\n    Example:\\n    ```mlir\\n    ttcore.device_module {\\n      module {\\n        func.func foo() { ... }\\n      }\\n    }\\n    ```\",\n    \"regions\": [\n      { \"name\": \"bodyRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $bodyRegion\"\n  },\n  {\n    \"name\": \"ttcore.get_global\",\n    \"summary\": \"Named global\",\n    \"description\": \"Retrieves a named global value declared with `ttcore.global`\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" }\n    ],\n    \"assemblyFormat\": \"$sym_name attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"ttcore.get_key_value\",\n    \"summary\": \"Get dictionary value\",\n    \"description\": \"Retrieves the value(s) stored under the given key from the dictionary.\\n    The key can either be a string or an index.\\n\\n    Example:\\n    ```mlir\\n    %0 = ttcore.get_key_value %dict[3 : index] : (!ttcore.dict) -> tensor<32x32xbf16>\\n    %0, %1 = ttcore.get_key_value %dict[\\\"key\\\"]\\n        : (!ttcore.dict) -> (tensor<32x32xbf16>, tensor<64x64xbf16>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dict\", \"type\": \"TTCore_DictType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"AnyAttrOf<[StrAttr, IndexAttr]>\" }\n    ],\n    \"assemblyFormat\": \"$dict `[` $key `]` attr-dict `:`\\n    functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttcore.get_tuple_element\",\n    \"summary\": \"GetTupleElement operation\",\n    \"description\": \"Extracts element at `index` position of the `operand` tuple and produces a `result`.\\n\\n      Example:\\n      ```mlir\\n      %result = ttcore.get_tuple_element %operand[0] : (tuple<tensor<32x32xbf16>, tensor<1x32xf32>>) -> tensor<32x32xbf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"TTCore_Tuple\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTCore_TupleMemberType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative]>\" }\n    ],\n    \"assemblyFormat\": \"$operand `[` $index `]` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttcore.global\",\n    \"summary\": \"Named global\",\n    \"description\": \"Declares a global variable with an optional index.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"index\", \"type\": \"OptionalAttr<SI32Attr>\" }\n    ],\n    \"assemblyFormat\": \"$sym_name `=` $type (` ` `[` $index^ `]`)? attr-dict\"\n  },\n  {\n    \"name\": \"ttcore.load_cached\",\n    \"summary\": \"Load cached results from a previously computed function\",\n    \"description\": \"The load_cached operation calls a precomputed function with given arguments\\n    and returns its results. This is typically used to load constant or hoisted\\n    computation results.\\n\\n    Example:\\n    ```mlir\\n    %0, %1, %2 = \\\"ttcore.load_cached\\\"(@forward_const_eval_1, [%arg0, %arg2])\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $callee `,` `[` $inputs `]` `)` attr-dict `:` functional-type($inputs, $results)\"\n  },\n  {\n    \"name\": \"ttcore.optimization_barrier\",\n    \"summary\": \"Optimization barrier operation.\",\n    \"description\": \"The `optimization_barrier` operation prevents compiler optimizations from reordering or eliminating\\n    the values passed through it. It acts as a barrier for optimization passes.\\n\\n    Inputs:\\n    - `inputs` (Variadic): Values of tensor type.\\n\\n    Outputs:\\n    - `results` (Variadic): Same values as inputs, passed through unchanged.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"ttcore.set_key_value\",\n    \"summary\": \"Set or update dictionary value\",\n    \"description\": \"Sets or updates a value(s) for the given key in the dictionary.\\n    The key can either be a string or an index.\\n\\n    Example:\\n    ```mlir\\n    ttcore.set_key_value %dict[3 : index] = %0\\n        : !ttcore.dict, tensor<32x32xbf16>\\n    ttcore.set_key_value %dict[\\\"key\\\"] = %0, %1\\n        : !ttcore.dict, tensor<32x32xbf16>, tensor<64x64xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dict\", \"type\": \"TTCore_DictType\" },\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"AnyAttrOf<[StrAttr, IndexAttr]>\" }\n    ],\n    \"assemblyFormat\": \"$dict `[` $key `]` `=` $values attr-dict `:`\\n    type($dict) `,` type($values)\"\n  },\n  {\n    \"name\": \"ttcore.tuple\",\n    \"summary\": \"Tuple operation\",\n    \"description\": \"Produces a `result` tuple from operands `operands`.\\n\\n    Example:\\n    ```mlir\\n    %result = ttcore.tuple %operand0, %operand1 : tuple<tensor<32xbf16, tensor<1x32xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<TTCore_TupleMemberType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTCore_Tuple\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict `:` custom<TupleOpType>(type($operands), type($result))\"\n  },\n  {\n    \"name\": \"ttg.async_commit_group\",\n    \"summary\": \"Commit pending async copies into an async group that can be waited on\",\n    \"description\": \"Closes the current batch of async_copy_* operations\\n    and allows for them to be waited on with `ttg.async_wait`.\\n    This is required in order to ensure async copy operations can be waited on.\",\n    \"operands\": [\n      { \"name\": \"inputTokens\", \"type\": \"Variadic<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"asyncToken\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"assemblyFormat\": \"(`tokens` $inputTokens^)? attr-dict\"\n  },\n  {\n    \"name\": \"ttg.async_copy_global_to_local\",\n    \"summary\": \"Copy data from global memory to local memory asynchronously\",\n    \"description\": \"This operation copies data from global memory to local memory asynchronously.\\n    This is analogue to `tt.load` except the data are copied to local memory pointed\\n    to by the memory descriptor instead of a distributed tensor. The rest of the\\n    operands are the same as `tt.load`.\\n    Contiguity is the maximum number of elements that can be loaded in a single vector with\\n    the given layout and mask.\\n    This allows op to use `async_copy_global_to_local` even if the alignment cannot be proven based on IR.\\n\\n    The data will only be available in local memory after `ttg.async_wait` is issued to wait on the\\n    completion of `async_copy_global_to_local`. The async copy operations must be committed using\\n    `ttg.async_commit_group` to close the batch and allow for them to be waited on.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_PtrTensor\" },\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"mask\", \"type\": \"Optional<I1Tensor>\" },\n      { \"name\": \"other\", \"type\": \"Optional<TT_Type>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, triton::EvictionPolicy::NORMAL>\" },\n      { \"name\": \"isVolatile\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"contiguity\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" },\n      { \"type\": \"TypesMatchWith<'src', 'mask', 'getI1SameShape($_self)'>\" },\n      { \"type\": \"TypesMatchWith<'src', 'other', 'getPointeeType($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $result (`mask` $mask^)? (`other` $other^)?\\n    oilist(`cacheModifier` `=` $cache | `evictionPolicy` `=` $evict)\\n    attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttg.async_wait\",\n    \"summary\": \"Ensure all specified async_copy_* operations are complete.\",\n    \"description\": \"The `async_wait` op waits until at most \\\"num\\\" async copy groups are outstanding without synchronising CTA execution.\\n    It takes zero or more `asyncToken` plus an integer `num` that specifies how many async copy groups can remain\\n    outstanding after the `async_wait` op is completed. `num = 0` waits until all groups of async copies are complete.\\n\\n    This operation does not provide any syncronisation in the CTA, if syncronisation is needed use `ttg.local_barrier`\\n    in addition to this operation.\",\n    \"operands\": [\n      { \"name\": \"asyncToken\", \"type\": \"Variadic<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"retToken\", \"type\": \"TTG_AsyncToken\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"($asyncToken^)? attr-dict\"\n  },\n  {\n    \"name\": \"ttg.barrier\",\n    \"summary\": \"Synchronizes execution and reads/writes to the selected address spaces for all threads in the CTA.\",\n    \"description\": \"The `barrier` op synchronises the execution and all operations between the selected address spaces for all\\n    threads in the CTA. It is used to coordinate communication between threads in the CTA.\\n\\n    This operation waits until all threads in the CTA have reached a `barrier` (for syncronisation) and operations\\n    between the selected address spaces made by these threads prior to the op are visible to all threads in the CTA.\\n\\n    Data hazards between threads accessing the same memory can be avoided by synchronising the\\n    specified scope in-between these accesses with a `barrier`.\\n\\n    A `barrier` operation only provides syncronisation and memory guarantees on the selected address spaces in the CTA.\\n\\n    The mandatory `addrspace` attribute is a bitmask describing which address spaces will be visible when the `barrier` completes:\\n\\n    * `none`         control-only syncronisation (no memory ordering).\\n    * `local`        shared-memory operations are complete and visible CTA-wide.\\n    * `global_read`  global memory reads are complete and visible CTA-wide.\\n    * `global_write` global memory writes are complete and visible CTA-wide.\\n    * `tensor_read`  tensor memory read operations are complete and visible CTA-wide.\\n    * `tensor_write` tensor memory write operations are complete and visible CTA-wide.\\n    * `all`          convenience alias for `[\\\"local\\\", \\\"global_read\\\", \\\"global_write\\\", \\\"tensor_read\\\", \\\"tensor_write\\\"]`.\\n\\n    Multiple address spaces can be combined (e.g. `local|tensor_write`). `none` cannot be combined with other address spaces.\\n\\n    Example:\\n\\n    ```mlir\\n    ttg.barrier local\\n    ttg.barrier local|global_read|global_write\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"addrSpace\", \"type\": \"TTG_AddrSpace{none|local|global_read|global_write|tensor_read|tensor_write|all}\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"ttg.convert_layout\",\n    \"summary\": \"convert layout\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttg.fp4_to_fp\",\n    \"summary\": \"Upcast fp4 (e2m1) to fp\",\n    \"description\": \"Upcast fp4 (e2m1) represented packed as i8s to fp.\\n\\n    The lower 4 bits of the i8s represent the first fp4 element, and the upper 4 bits\\n    the second fp4 element.\\n\\n    The `axis` attribute specifies the axis along which the fp4 elements are packed.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"RankedTensorOf<[I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_FloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` type($src) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttg.global_scratch_alloc\",\n    \"summary\": \"allocate a global memory buffer\",\n    \"description\": \"This operation allocates a buffer in global memory that is private to the current program.\\n    A custom third-party allocation can be marked using the optional\\n    `third_party_allocation` unit attribute.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Ptr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nbytes\", \"type\": \"I32Attr\" },\n      { \"name\": \"alignment\", \"type\": \"I32Attr\" },\n      { \"name\": \"third_party_allocation\", \"type\": \"OptionalAttr<UnitAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttg.local_alloc\",\n    \"summary\": \"allocate tensor\",\n    \"description\": \"This operation allocates buffer in shared memory and return a descriptor\\n    containing the address and a view of the buffer.\\n\\n    Explicitly deallocating a buffer is optional; see local_dealloc.\\n\\n    The `src` operand is an optional initializer for the allocated buffer. It\\n    must have the element type as the buffer. If `src` is not specified, the\\n    returned buffer must be mutable.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"Optional<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"assemblyFormat\": \"($src^)? attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttg.local_barrier\",\n    \"summary\": \"Synchronizes execution and shared memory reads/writes for all threads in a CTA.\",\n    \"description\": \"The `local_barrier` op synchronizes the execution and all operations\\n    between shared memory and registers for all threads in a CTA.\\n    It is used to coordinate communication between the threads of the CTA.\\n\\n    This operation waits until all threads in the CTA have reached a `local_barrier`\\n    and operations between shared memory and registers made by these threads prior\\n    to the op are visible to all threads in the CTA.\\n\\n    Data hazards between threads accessing the same memory can be avoided by synchronizing the\\n    CTA in-between these accesses with a `local_barrier`.\\n\\n    A `local_barrier` operation does not provide syncronization guarantees on global memory.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttg.local_dealloc\",\n    \"summary\": \"dealloc buffer\",\n    \"description\": \"This operation deallocates a buffer explicitly. Using the buffer after this\\n    operation is undefined.\\n\\n    This operation is optional.  If you don't explicitly dealloc a buffer, the\\n    compiler assumes it's deallocated at the first point that post-dominates all\\n    uses of the alloc.\\n\\n    Because we assume a memdesc is dead at the first point that post-dominates\\n    its uses, ops that wait for an async operation on a memdesc to complete\\n    (such as ttng.warp_group_dot_wait) should also take the memdesc as an\\n    operand.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` qualified(type($src))\"\n  },\n  {\n    \"name\": \"ttg.local_gather\",\n    \"summary\": \"Gather elements from shared memory along a specified axis\",\n    \"description\": \"Gather elements from a shared memory descriptor using an indices tensor along a\\n    single specified axis. The output tensor has the same shape as the indices tensor.\\n\\n    For each output position I, the operation reads from src where the coordinate at\\n    the gather axis is replaced by indices[I]:\\n      result[I] = src[I[0], ..., indices[I], ..., I[n]]\\n    where the axis dimension is replaced by the index value.\\n\\n    This matches the behavior of tt.gather but operates on shared memory descriptors.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"indices\", \"type\": \"TT_IntTensor\" },\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $indices `]` (`token` $token^)? attr-dict `:` qualified(type($src)) `,` type($indices) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttg.local_load\",\n    \"summary\": \"Load a buffer from local memory into a distributed tensor\",\n    \"description\": \"Load a tensor from the local memory descriptor into a distributed tensor.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"assemblyFormat\": \"$src (`token` $token^)? attr-dict `:` qualified(type($src)) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttg.local_scatter\",\n    \"summary\": \"Scatter elements to shared memory along a specified axis\",\n    \"description\": \"Scatter elements to a shared memory descriptor using an indices tensor along a\\n    single specified axis. The values tensor has the same shape as the indices tensor.\\n\\n    For each input position I, the operation writes to dst where the coordinate at\\n    the scatter axis is replaced by indices[I]:\\n      dst[I[0], ..., indices[I], ..., I[n]] = values[I]\\n    where the axis dimension is replaced by the index value.\\n\\n    This is the inverse of local_gather and writes to shared memory at runtime-computed indices.\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"values\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"indices\", \"type\": \"TT_IntTensor\" },\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$dst `[` $indices `]` `,` $values (`token` $token^)? attr-dict `:` qualified(type($dst)) `,` type($indices) `,` type($values)\"\n  },\n  {\n    \"name\": \"ttg.local_store\",\n    \"summary\": \"Store a distributed tensor into a buffer in local memory\",\n    \"description\": \"Store a distributed tensor into a buffer in local memory.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"dst\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $dst attr-dict `:` type($src) `->` qualified(type($dst))\"\n  },\n  {\n    \"name\": \"ttg.mask\",\n    \"summary\": \"mask op for pipelining\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ]\n  },\n  {\n    \"name\": \"ttg.mask.return\",\n    \"summary\": \"terminator for mask operator\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"ttg.memdesc_index\",\n    \"summary\": \"take a subview of the descriptor.\",\n    \"description\": \"This operation returns a new descriptor pointing to the `i`-th element of the\\n    input descriptor along the 0-th dimension.\\n\\n    It doesn't affect the underlying memory.\\n\\n    For example, suppose that\\n     - the input shape is 2x4x16xf16,\\n     - the output shape is 4x16xf16, and\\n     - index = 1.\\n    Then the output descriptor is equivalent to input[1], where input is the logical tensor.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"index\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $index `]` attr-dict `:` qualified(type($src)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttg.memdesc_reinterpret\",\n    \"summary\": \"reinterpret a memory descriptor as a different type and shape\",\n    \"description\": \"The `ttg.memdesc_reinterpret` operation reinterprets a memory descriptor\\n    as one with a different shape and element type. Because memory descriptors\\n    lack strides, this operation is only valid if the original memory descriptor\\n    is contiguous.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` qualified(type($src)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttg.memdesc_reshape\",\n    \"summary\": \"creates a descriptor for the new shape\",\n    \"description\": \"This operation returns a new descriptor representing a reshaped view of the underlying buffer.\\n    This doesn't affect the memory.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` qualified(type($src)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttg.memdesc_subslice\",\n    \"summary\": \"take a subview of the descriptor.\",\n    \"description\": \"This operation returns a new descriptor representing a subview of the logical tensor.\\n    It doesn't affect the underlying memory.\\n\\n    For example, suppose that\\n     - the input shape is 32x16xf16,\\n     - the output shape is 8x16xf16, and\\n     - offsets = [2, 1].\\n    Then in Python syntax, the subview covers input[2:8+2, 1:16+1] where input is\\n    the logical tensor.\\n\\n    The offsets must be larger or equal to the tile of the tensor (or zero).\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offsets\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$src `[` custom<Offsets>($offsets) `]` attr-dict `:` qualified(type($src))\\n    `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttg.memdesc_trans\",\n    \"summary\": \"transpose the descriptor\",\n    \"description\": \"This operation returns a new descriptor\\n    representing a transposed view of the buffer.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` qualified(type($src)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttg.predicate_stage\",\n    \"summary\": \"pipeliner stage predicate\",\n    \"operands\": [\n      { \"name\": \"iv\", \"type\": \"AnySignlessIntegerOrIndex\" },\n      { \"name\": \"ub\", \"type\": \"AnySignlessIntegerOrIndex\" },\n      { \"name\": \"step\", \"type\": \"AnySignlessIntegerOrIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"maxStage\", \"type\": \"I32Attr\" },\n      { \"name\": \"stage\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['iv', 'ub', 'step']>\" }\n    ],\n    \"assemblyFormat\": \"$iv `,` $ub `,` $step `maxStage` $maxStage `stage` $stage attr-dict `:` type($iv) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttg.warp_id\",\n    \"summary\": \"Return the GPU warp ID\",\n    \"description\": \"This operation returns the GPU warp ID. This can translate to reading\\n    hardware registers if there are, or just thread ID divided by warp size.\\n\\n    The `omitUniformHint` attribute is indicating in NVIDIA backend whether to\\n    omit emitting nvvm.shfl.sync idx 0 for LLVM.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"omitUniformHint\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttg.warp_return\",\n    \"summary\": \"implicit terminator from partition regions\",\n    \"description\": \"The `ttg.warp_return` operation is the implicit terminator that ends the\\n    partition regions of a `ttg.warp_specialize` op. It has no operands as these\\n    regions cannot return anything.\\n\\n    TODO: Support returning uniform values from partition regions.\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttg.warp_specialize\",\n    \"summary\": \"asynchronously execute code on multiple warpgroups\",\n    \"description\": \"The `ttg.warp_specialize` op represents executing different code\\n    simultaneously on different warp groups. A warp group is a group of\\n    power-of-2 warps, which can be a different number of warps than in the\\n    enclosing region.\\n\\n    The \\\"default\\\" region of the op represents the code executed by the currently\\n    executing warp group. This region is allowed to implicitly capture. The op\\n    contains a number of \\\"partition\\\" regions that are isolated from above. They\\n    must be isolated because these regions represent different layout domains,\\n    as the number of warps is different.\\n\\n    Semantically, execution of each region starts simultaneously for each warp\\n    group, and all warp groups are joined at the end of the op.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = ttg.warp_specialize(%a, %b)\\n    default {\\n      %out = some_operation(%a) // implicit capture of `%a`\\n      ttg.warp_yield %out : i32\\n    }\\n    partition0(%arg0: i32, %arg1: i32) num_warps(8) {\\n      some_async_dispatch(%arg0, %arg1)\\n      ttg.warp_return\\n    }\\n    partition1(%arg0: i32, %arg1: i32) num_warps(1) {\\n      some_async_dispatch(%arg0, %arg1)\\n      ttg.warp_return\\n    } : (i32, i32) -> i32\\n    ```\",\n    \"results\": [\n      { \"name\": \"defaultPassthrough\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"partitionNumWarps\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"warpGroupStartIds\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"requestedRegisters\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" },\n      { \"name\": \"actualRegisters\", \"type\": \"OptionalAttr<DenseI32ArrayAttr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"defaultRegion\", \"type\": \"MinSizedRegion<1>\" },\n      { \"name\": \"partitionOpHolder\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"ttg.warp_specialize.partitions\",\n    \"summary\": \"container op for `ttg.warp_specialize`\",\n    \"description\": \"Because MLIR requires entire operations be isolated from above, this op\\n    contains the actual isolated from above regions of `ttg.warp_specialize`.\",\n    \"operands\": [\n      { \"name\": \"explicitCaptures\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"partitionRegions\", \"type\": \"VariadicRegion<MinSizedRegion<1>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ]\n  },\n  {\n    \"name\": \"ttg.warp_yield\",\n    \"summary\": \"yield from the default region of `ttg.warp_specialize`\",\n    \"description\": \"The `ttg.warp_yield` operation is the terminator for the \\\"default\\\" region of\\n    a `ttg.warp_specialize` operation. The operands are passed transparently as\\n    the SSA results of the `ttg.warp_specialize` operation.\\n\\n    Example:\\n\\n    ```mlir\\n    ttg.warp_yield %a, %b : i32, tensor<32xbf16, #blocked>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"($values^)? attr-dict (`:` type($values)^)?\"\n  },\n  {\n    \"name\": \"tti.experimental_assert_in_thread\",\n    \"summary\": \"assert the condition within the current thread\",\n    \"description\": \"Assert that the condition is true given all the values are available in the current thread.\\n    If the condition is false, the message is printed, and the program is aborted.\\n    If check_any is true, any of the values in the condition must be true. Otherwise, all the\\n    values in the condition must be true.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"AnyTypeOf<[I1, I1Tensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" },\n      { \"name\": \"check_any\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"$condition `,` $message attr-dict `:` type($condition)\"\n  },\n  {\n    \"name\": \"tti.experimental_assert_uniform\",\n    \"summary\": \"assert the uniform condition\",\n    \"description\": \"Assert that the condition is true given all threads in the warp group have\\n    the same value, so only one thread needs to evaluate the assert and print\\n    the message.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$condition `,` $message attr-dict-with-keyword\"\n  },\n  {\n    \"name\": \"tti.experimental_buffer_descriptors\",\n    \"summary\": \"define an array of buffer descriptors\",\n    \"description\": \"Create a tensor of buffer descriptors packing 32-bit pointer offsets and\\n    32-bit lengths into 64-bit elements.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offsets\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"lengths\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"memType\", \"type\": \"TT_MemTypeAttr{shared_mem|tensor_mem}\" }\n    ],\n    \"assemblyFormat\": \"$offsets `,` $lengths `,` $memType attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"tti.experimental_lock_acquire\",\n    \"summary\": \"Acquire a lock.\",\n    \"description\": \"Enter a critical section by acquiring a lock with single thread.\",\n    \"operands\": [\n      { \"name\": \"lock\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"pred\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$lock (`,` $pred^)? attr-dict `:` type($lock)\"\n  },\n  {\n    \"name\": \"tti.experimental_lock_release\",\n    \"summary\": \"Release a lock.\",\n    \"description\": \"Leave a critical section by releasing a lock with single thread.\",\n    \"operands\": [\n      { \"name\": \"lock\", \"type\": \"TT_PtrLike\" },\n      { \"name\": \"pred\", \"type\": \"Optional<I1>\" }\n    ],\n    \"assemblyFormat\": \"$lock (`,` $pred^)? attr-dict `:` type($lock)\"\n  },\n  {\n    \"name\": \"tti.experimental_memdesc_to_i32\",\n    \"summary\": \"Convert a memdesc into its base pointer as i32\",\n    \"description\": \"Extract the base pointer from the given memdesc and return it as a 32-bit\\n    integer. This can be used to compare the memdesc against tensors of barrier\\n    pointers maintained by the concurrency sanitizer.\",\n    \"operands\": [\n      { \"name\": \"memdesc\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$memdesc attr-dict `:` type($memdesc)\"\n  },\n  {\n    \"name\": \"ttir.abs\",\n    \"summary\": \"Elementwise absolute value operation.\",\n    \"description\": \"The `abs` operation computes the absolute value of each element in the input tensor.\\n\\n      For each element, it returns the magnitude of the value without regard to its sign:\\n      - For real numbers, it returns |x| (the non-negative value without sign)\\n\\n      This operation has the idempotence property, meaning that applying it multiple times\\n      produces the same result as applying it once: abs(abs(x)) = abs(x). The operation\\n      preserves the data type of the input.\\n\\n      Example:\\n      ```mlir\\n      // Compute absolute values of all elements in %input\\n      %result = ttir.abs(%input) : tensor<4x4xf32> -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[-2.5,  3.7,  0.0,  1.2], ... ]\\n      // Output tensor:\\n      // [[2.5, 3.7, 0.0, 1.2], ... ]\\n\\n      // Example with integer tensor\\n      %result = ttir.abs(%int_input) : (tensor<10xi32>) -> tensor<10xi32>\\n      // Input tensor:\\n      // [-5, 0, 3, -2, ...]\\n      // Output tensor:\\n      // [5, 0, 3, 2, ...]\\n      ```\\n\\n      Mathematical definition: abs(x) = |x| = {\\n        x  if x ≥ 0\\n        -x if x < 0\\n      }\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.add\",\n    \"summary\": \"Elementwise addition operation.\",\n    \"description\": \"The `add` operation performs an elementwise addition between two tensors.\\n\\n      For each pair of corresponding elements, it adds the elements and places the result in the output tensor.\\n\\n      Example:\\n      ```mlir\\n      // Addition operation\\n      %result = ttir.add(%lhs, %rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>\\n      // Input tensors:\\n      // %lhs: [10, 20, 30]\\n      // %rhs: [1, 2, 3]\\n      // Output tensor:\\n      // [11, 22, 33]\\n\\n      // Example with floating point values\\n      %result = ttir.add(%float_lhs, %float_rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %float_lhs: [3.5, 0.0, -1.2]\\n      // %float_rhs: [1.5, 2.0, -3.2]\\n      // Output tensor:\\n      // [5.0, 2.0, -2.0]\\n      ```\\n\\n      Note: The data type of the output tensor matches the data type of the input tensors.\\n\\n      Mathematical definition: add(x, y) = x + y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.all_gather\",\n    \"summary\": \"All gather operation.\",\n    \"description\": \"All gather op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"all_gather_dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.all_reduce\",\n    \"summary\": \"AllReduce operation.\",\n    \"description\": \"AllReduce op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_type\", \"type\": \"TTCore_ReduceTypeAttr{sum|mean|max|min|std|var|prod|invalid}\" },\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.all_to_all\",\n    \"summary\": \"All to All operation.\",\n    \"description\": \"The all_to_all operation redistributes slices of a tensor across a cluster of devices. It splits each local tensor along split_dimension, sends\\n      the resulting slices to other devices along cluster_axis, and then concatenates the received slices along concat_dimension.\\n\\n      Example:\\n        For a 1x2 mesh and a local input of shape [8, 4]:\\n          - split_dimension = 1\\n          - concat_dimension = 0\\n          - split_count = 2\\n          - cluster_axis = 1\\n\\n        Each device splits its [8, 4] tensor into two [8, 2] slices. After the exchange, each device concatenates the two received [8, 2] slices\\n        into a [16, 2] output tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"concat_dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"split_count\", \"type\": \"SI32Attr\" },\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.all_to_all_combine\",\n    \"summary\": \"Combine expert outputs back to original token positions.\",\n    \"description\": \"Inverse of dispatch: gathers expert computation results from expert devices\\n      and restores tokens to their original device and order.\\n\\n      Input shapes:\\n      - input_tensor: [E_local, B*D, S, H]\\n      - expert_metadata: [1, B*D, S, K]\\n      - expert_mapping: [1, 1, E, D]\\n\\n      Output shape:\\n      - result: [K, B, S, H]\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_metadata\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_mapping\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_devices\", \"type\": \"I64Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"num_experts_per_tok\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.all_to_all_dispatch\",\n    \"summary\": \"Dispatch tokens to expert devices for MoE computation.\",\n    \"description\": \"Routes tokens to devices holding their selected experts via all-to-all\\n      communication. Used before sparse_matmul in the MoE dispatch/combine flow.\\n\\n      Input shapes:\\n      - input_tensor: [B, S, 1, H]\\n      - expert_indices: [B, S, 1, K]\\n      - expert_mapping: [1, 1, E, D]\\n\\n      Output shapes:\\n      - dispatched: [1, B*D, S, H]\\n      - metadata: [1, B*D, S, K]\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_mapping\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dispatched\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"metadata\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_devices\", \"type\": \"I64Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.alloc\",\n    \"summary\": \"Alloc op.\",\n    \"description\": \"Tensor Alloc operation\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"address\", \"type\": \"I64Attr\" },\n      { \"name\": \"size\", \"type\": \"I64Attr\" },\n      { \"name\": \"memory_space\", \"type\": \"TTCore_MemorySpaceAttr{system|mmio|dram|l1|dst}\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.arange\",\n    \"summary\": \"Tensor range generation operation.\",\n    \"description\": \"The `arange` operation generates a tensor with evenly spaced values within a given interval.\\n\\n    This operation creates a tensor with values from `start` to `end` (exclusive) with a step size of `step`,\\n    along the dimension specified by `arange_dimension`. It's similar to NumPy's arange function and is useful\\n    for creating tensors with regular sequences of values.\\n\\n    Example:\\n    ```mlir\\n    // Generate a 1D tensor with values [0, 1, 2, 3, 4]\\n    %result = ttir.arange() {\\n        start = 0 : si64,\\n        end = 5 : si64,\\n        step = 1 : si64,\\n        arange_dimension = 0 : i64\\n    } : () -> tensor<5xi64>\\n\\n    // Generate a 1D tensor with values [0.0, 2.0, 4.0, 6.0, 8.0]\\n    %result = ttir.arange() {\\n        start = 0 : si64,\\n        end = 10 : si64,\\n        step = 2 : si64,\\n        arange_dimension = 0 : i64\\n    } : () -> tensor<5xf32>\\n\\n    // Generate a 2D tensor with the sequence along dimension 0\\n    %result = ttir.arange() {\\n        start = 0 : si64,\\n        end = 5 : si64,\\n        step = 1 : si64,\\n        arange_dimension = 0 : i64\\n    } : () -> tensor<5x3xi64>\\n    // Result:\\n    // [[0, 0, 0],\\n    //  [1, 1, 1],\\n    //  [2, 2, 2],\\n    //  [3, 3, 3],\\n    //  [4, 4, 4]]\\n\\n    // Generate a 2D tensor with the sequence along dimension 1\\n    %result = ttir.arange() {\\n        start = 0 : si64,\\n        end = 3 : si64,\\n        step = 1 : si64,\\n        arange_dimension = 1 : i64\\n    } : () -> tensor<5x3xi64>\\n    // Result:\\n    // [[0, 1, 2],\\n    //  [0, 1, 2],\\n    //  [0, 1, 2],\\n    //  [0, 1, 2],\\n    //  [0, 1, 2]]\\n    ```\\n\\n    Attributes:\\n    - `start` (Integer): The start value of the sequence.\\n    - `end` (Integer): The end value of the sequence (exclusive).\\n    - `step` (Integer): The step size between values in the sequence.\\n    - `arange_dimension` (Integer): The dimension along which to generate the sequence.\\n\\n    Output:\\n    - `result` (Tensor): The generated tensor containing the sequence.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start\", \"type\": \"SI64Attr\" },\n      { \"name\": \"end\", \"type\": \"SI64Attr\" },\n      { \"name\": \"step\", \"type\": \"SI64Attr\" },\n      { \"name\": \"arange_dimension\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.argmax\",\n    \"summary\": \"Argmax reduction op.\",\n    \"description\": \"Determine the indices of the maximum values along a specified dimension of a tensor or over all elements\\n    in a tensor.\\n\\n    This operation reduces the input tensor by finding the index of the maximum value along the dimensions\\n    specified in `dim_arg`. If `dim_arg` is not provided, the argmax is computed over all dimensions,\\n    resulting in a scalar index. If `keep_dim` is set to true, the reduced dimensions are retained\\n    with a size of 1.\\n\\n    ### Example IR Usage:\\n    ```mlir\\n    // Argmax along dimension 1\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.argmax(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<2x3xf32>) -> tensor<2xi32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [2.0, 4.0, 6.0]]\\n    // Output tensor:\\n    // [1, 2]  // Index of maximum value in each row (5.0 in first row, 6.0 in second row)\\n\\n    // Argmax along dimension 0\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.argmax(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<2x3xf32>) -> tensor<3xi32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [2.0, 4.0, 6.0]]\\n    // Output tensor:\\n    // [1, 0, 1]  // Index of maximum value in each column\\n\\n    // Argmax over all dimensions\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.argmax(%input) {keep_dim = false} : (tensor<2x3xf32>) -> tensor<i32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [2.0, 4.0, 6.0]]\\n    // Output tensor:\\n    // 5  // Flattened index of the maximum value (6.0)\\n    ```\\n\\n    Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n      - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n      Output:\\n      - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.atan\",\n    \"summary\": \"Eltwise arctangent op.\",\n    \"description\": \"The `atan` operation computes the arctangent (inverse tangent) of each element in the input tensor.\\n\\n      For each element, it returns the angle in radians whose tangent is the input value. The operation\\n      returns values in the range [-π/2, π/2].\\n\\n      Example:\\n      ```mlir\\n      // Compute arctangent of all elements in %input\\n      %result = ttir.atan(%input) : (tensor<4xf32>) -> tensor<4xf32>\\n      // Input tensor:\\n      // [1.0, 0.5, 0.0, -1.0]\\n      // Output tensor:\\n      // [0.785, 0.464, 0.0, -0.785]  // values in radians\\n\\n      // Example with different values\\n      %result = ttir.atan(%float_input) : (tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensor:\\n      // [0.0, 1.0, 1000.0]\\n      // Output tensor:\\n      // [0.0, 0.785, 1.571]  // values approach π/2 as input grows\\n      ```\\n\\n      Mathematical definition: atan(x) = tan⁻¹(x), where the result is in the range [-π/2, π/2]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.atan2\",\n    \"summary\": \"Elementwise atan2 operation.\",\n    \"description\": \"The `atan2` operation performs an elementwise arc tangent (inverse tangent) operation between two tensors.\\n\\n      For each pair of corresponding elements, it computes the angle in radians between the positive x-axis\\n      and the vector from the origin to the point (x, y) in the Cartesian plane. This operation is\\n      typically used in trigonometric calculations and supports partial broadcasting, allowing operands\\n      of different shapes to be combined.\\n\\n      Example:\\n      ```mlir\\n      // %lhs: [0.0, 1.0, -1.0]\\n      // %rhs: [1.0, 0.0, 0.0]\\n      %result = ttir.atan2(%lhs, %rhs) : (tensor<3xf64>, tensor<3xf64>) -> tensor<3xf64>\\n      // %result: [0.0, 1.57079637, -1.57079637] // [0.0, pi/2, -pi/2]\\n      ```\\n      Mathematical definition: atan2(x, y) = arctan(y / x)\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.avg_pool2d\",\n    \"summary\": \"2D average pooling operation.\",\n    \"description\": \"The `avg_pool2d` operation applies a 2D average pooling over an input tensor composed of several input planes.\\n\\n    This operation performs downsampling by dividing the input into local regions and computing the average value\\n    of each region. It reduces the spatial dimensions (height and width) of an input tensor while preserving the\\n    batch and channel dimensions. This is commonly used in neural networks to reduce the spatial size of feature maps.\\n\\n    Example:\\n    ```mlir\\n    // Basic 2D average pooling with a 2x2 kernel and stride 1\\n    %input = ... : tensor<1x3x3x1xf32>  // 3x3 input tensor with values:\\n                                        // [[[1, 2, 3],\\n                                        //   [4, 5, 6],\\n                                        //   [7, 8, 9]]]\\n    %result = ttir.avg_pool2d(%input) {\\n        kernel = [2, 2],\\n        stride = [1, 1],\\n        dilation = [1, 1],\\n        padding = [0, 0, 0, 0],\\n        ceil_mode = false\\n    } : (tensor<1x3x3x1xf32>) -> tensor<1x2x2x1xf32>\\n    // Result: [[[3, 4],\\n    //           [6, 7]]]\\n    // Where: 3 = (1+2+4+5)/4, 4 = (2+3+5+6)/4, 6 = (4+5+7+8)/4, 7 = (5+6+8+9)/4\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): Input tensor in NHWC format (batch, height, width, channels).\\n\\n    Attributes:\\n    - `kernel` (i32 | array<2xi32>):\\n        - i32: Same kernel size for height and width dimensions (kH = kW = value).\\n        - array<2xi32>: [kH, kW] where kH is kernel size for height and kW is kernel size for width.\\n    - `stride` (i32 | array<2xi32>):\\n        - i32: Same stride for height and width dimensions (sH = sW = value).\\n        - array<2xi32>: [sH, sW] where sH is stride for height and sW is stride for width.\\n    - `dilation` (i32 | array<2xi32>):\\n        - i32: Same dilation for height and width dimensions (dH = dW = value).\\n        - array<2xi32>: [dH, dW] where dH is dilation for height and dW is dilation for width.\\n    - `padding` (i32 | array<2xi32> | array<4xi32>):\\n        - i32: Same padding for all sides (pT = pL = pB = pR = value).\\n        - array<2xi32>: [pH, pW] where pH is padding for height (top/bottom) and pW is padding for width (left/right).\\n        - array<4xi32>: [pT, pL, pB, pR] for top, left, bottom, and right padding respectively.\\n    - `ceil_mode` (Boolean): When true, uses ceil instead of floor for output shape calculation.\\n    - `count_include_pad` (Boolean): When true, include padding in the average calculation (default: True)\\n\\n    Output:\\n    - `result` (Tensor): Output tensor after average pooling.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"stride\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"dilation\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"flattened_compat_info\", \"type\": \"DefaultValuedAttr<TTIR_FlattenedCompatInfoAttr, nullptr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.batch_norm_inference\",\n    \"summary\": \"BatchNormInference operation\",\n    \"description\": \"Performs batch normalization inference on the input tensor. Normalizes the `operand` tensor\\n    across all dimensions except for the specified `dimension` (feature dimension) and\\n    produces the normalized result using pre-computed mean and variance.\\n\\n    Inputs:\\n    - `operand` (Tensor): The input tensor to be normalized.\\n    - `scale` (Tensor): The scale parameter (gamma).\\n    - `offset` (Tensor): The offset parameter (beta).\\n    - `mean` (Tensor): The pre-computed mean of the input.\\n    - `variance` (Tensor): The pre-computed variance of the input.\\n\\n    Attributes:\\n    - `epsilon` is a small constant added to variance for numerical stability.\\n    - `dimension` specifies which dimension represents the features/channels.\\n\\n    Output:\\n    - `result` (Tensor): The normalized output tensor.\\n\\n    Example:\\n    ```mlir\\n      // Normalize a batch of activations\\n      %result = ttir.batch_norm(%operand, %scale, %offset, %mean, %variance,\\n                              epsilon = 0.001, dimension = 1) :\\n            (tensor<8x16x32x32xf32>, tensor<16xf32>, tensor<16xf32>,\\n              tensor<16xf32>, tensor<16xf32>) -> tensor<8x16x32x32xf32>\\n    ```\\n\\n    Mathematical definition: batch_norm(x, scale, offset, mean, variance, epsilon, dimension) =\\n      (x - mean) / sqrt(variance + epsilon) * scale + offset\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offset\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mean\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"variance\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"dimension\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.batch_norm_training\",\n    \"summary\": \"BatchNormTraining operation\",\n    \"description\": \"Performs batch normalization during training on the input tensor. Normalizes the `operand` tensor\\n    across all dimensions except for the specified `dimension` (feature dimension) and\\n    produces the normalized result along with batch statistics. Updates the running mean and variance.\\n\\n    Inputs:\\n    - `operand` (Tensor): The input tensor to be normalized.\\n    - `scale` (Tensor): The scale parameter (gamma).\\n    - `offset` (Tensor): The offset parameter (beta).\\n    - `running_mean` (Tensor): The running mean (updated during training).\\n    - `running_variance` (Tensor): The running variance (updated during training).\\n\\n    Attributes:\\n    - `epsilon` is a small constant added to variance for numerical stability.\\n    - `dimension` specifies which dimension represents the features/channels.\\n    - `momentum` is the momentum factor for updating running statistics.\\n\\n    Outputs:\\n    - `result` (Tensor): The normalized output tensor.\\n    - `batch_mean` (Tensor): The computed batch mean.\\n    - `batch_variance` (Tensor): The computed batch variance.\\n\\n    Example:\\n    ```mlir\\n      // Normalize a batch of activations (training)\\n      %result, %batch_mean, %batch_variance = ttir.batch_norm_training(%operand, %scale, %offset, %running_mean, %running_variance,\\n                                           %output, %batch_mean_output, %batch_variance_output :\\n                                           epsilon = 0.001, dimension = 1, momentum = 0.1) :\\n            (tensor<8x16x32x32xf32>, tensor<16xf32>, tensor<16xf32>,\\n              tensor<16xf32>, tensor<16xf32>, tensor<8x16x32x32xf32>,\\n              tensor<16xf32>, tensor<16xf32>, tensor<16xf32>, tensor<16xf32>) ->\\n            (tensor<8x16x32x32xf32>, tensor<16xf32>, tensor<16xf32>)\\n    ```\\n\\n    Mathematical definition:\\n      batch_mean = mean(x, dimension)\\n      batch_variance = variance(x, dimension)\\n      normalized = (x - batch_mean) / sqrt(batch_variance + epsilon) * scale + offset\\n      running_mean = momentum * batch_mean + (1 - momentum) * running_mean\\n      running_variance = momentum * batch_variance + (1 - momentum) * running_variance\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"offset\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"running_variance\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"batch_mean\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"batch_variance\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"F32Attr\" },\n      { \"name\": \"dimension\", \"type\": \"I32Attr\" },\n      { \"name\": \"momentum\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.bitwise_and\",\n    \"summary\": \"Elementwise bitwise AND.\",\n    \"description\": \"The `bitwise_and` operation performs an elementwise bitwise AND operation between two tensors.\\n\\n      For each pair of corresponding elements, it computes the bitwise AND of their binary\\n      representations. This operation is typically used with integer data types and has the\\n      idempotence property, meaning that applying it twice with the same second operand\\n      returns the original result: bitwise_and(bitwise_and(x, y), y) = bitwise_and(x, y).\\n\\n      Example:\\n      ```mlir\\n      // Bitwise AND operation\\n      %result = ttir.bitwise_and(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n      // Input tensors:\\n      // %lhs: [[1, 2], [3, 4]]\\n      // %rhs: [[5, 6], [7, 8]]\\n      // Output tensor:\\n      // [[1, 2], [3, 0]]\\n\\n      // Example with binary representation (for 8-bit integers)\\n      %result = ttir.bitwise_and(%int8_lhs, %int8_rhs) : (tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>\\n      // Input tensors:\\n      // %int8_lhs: [0x0F, 0xAA, 0xFF, 0x00]  (binary: [00001111, 10101010, 11111111, 00000000])\\n      // %int8_rhs: [0xF0, 0x55, 0xFF, 0x00]  (binary: [11110000, 01010101, 11111111, 00000000])\\n      // Output tensor:\\n      // [0x00, 0x00, 0xFF, 0x00]  (binary: [00000000, 00000000, 11111111, 00000000])\\n      ```\\n\\n      Mathematical definition: bitwise_and(x, y) = x & y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.bitwise_not\",\n    \"summary\": \"Elementwise bitwise NOT.\",\n    \"description\": \"The `bitwise_not` operation computes the bitwise NOT (one's complement) of each element in the input tensor.\\n\\n      For each element, it flips all the bits in the binary representation of the value. This operation\\n      is typically used with integer data types and has the involution property, meaning that\\n      applying it twice returns the original value: bitwise_not(bitwise_not(x)) = x.\\n\\n      Example:\\n      ```mlir\\n      // Bitwise operation with with integer tensors\\n      %result = \\\"ttir.bitwise_not\\\"(%operand) : (tensor<2x2xi32>) -> tensor<2x2xi32>\\n      // %operand: [[1, 2], [3, 4]]\\n      // %result: [[-2, -3], [-4, -5]]\\n\\n      // Example with binary representation (for 8-bit integers)\\n      %result = ttir.bitwise_not(%int8_input) : (tensor<3xi8>) -> tensor<3xi8>\\n      // Input %int8_input:\\n      // [0, 5, 255]  (binary: [00000000, 00000101, 11111111])\\n      // Output %int8_output:\\n      // [255, 250, 0]  (binary: [11111111, 11111010, 00000000])\\n      ```\\n\\n      Mathematical definition: bitwise_not(x) = ~x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.bitwise_or\",\n    \"summary\": \"Elementwise bitwise OR operation.\",\n    \"description\": \"The `bitwise_or` operation performs an elementwise bitwise OR operation between two tensors.\\n\\n      For each pair of corresponding elements, it computes the bitwise OR of their binary\\n      representations. This operation is typically used with integer data types and has the\\n      idempotence property, meaning that applying it twice with the same second operand\\n      returns the original result: bitwise_or(bitwise_or(x, y), y) = bitwise_or(x, y).\\n\\n      Example:\\n      ```mlir\\n      // Bitwise OR operation\\n      %result = ttir.bitwise_or(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n      // Input tensors:\\n      // %lhs: [[1, 2], [3, 4]]\\n      // %rhs: [[5, 6], [7, 8]]\\n      // Output tensor:\\n      // [[5, 6], [7, 12]]\\n\\n      // Example with binary representation (for 8-bit integers)\\n      %result = ttir.bitwise_or(%int8_lhs, %int8_rhs) : (tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>\\n      // Input tensors:\\n      // %int8_lhs: [0x0F, 0xAA, 0x00, 0x55]  (binary: [00001111, 10101010, 00000000, 01010101])\\n      // %int8_rhs: [0xF0, 0x55, 0x00, 0xAA]  (binary: [11110000, 01010101, 00000000, 10101010])\\n      // Output tensor:\\n      // [0xFF, 0xFF, 0x00, 0xFF]  (binary: [11111111, 11111111, 00000000, 11111111])\\n      ```\\n\\n      Mathematical definition: bitwise_or(x, y) = x | y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.bitwise_xor\",\n    \"summary\": \"Elementwise bitwise XOR operation.\",\n    \"description\": \"The `bitwise_xor` operation performs an elementwise bitwise XOR (exclusive OR) operation between two tensors.\\n\\n      For each pair of corresponding elements, it computes the bitwise XOR of their binary\\n      representations. This operation is typically used with integer data types and has the\\n      property that when applied twice with the same second operand, it returns the original input:\\n      bitwise_xor(bitwise_xor(x, y), y) = x.\\n\\n      Example:\\n      ```mlir\\n      // Bitwise XOR operation\\n      %result = ttir.bitwise_xor(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n      // Input tensors:\\n      // %lhs: [[1, 2], [3, 4]]\\n      // %rhs: [[5, 6], [7, 8]]\\n      // Output tensor:\\n      // [[4, 4], [4, 12]]\\n\\n      // Example with binary representation (for 8-bit integers)\\n      %result = ttir.bitwise_xor(%int8_lhs, %int8_rhs) : (tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>\\n      // Input tensors:\\n      // %int8_lhs: [0x0F, 0xAA, 0xFF, 0x00]  (binary: [00001111, 10101010, 11111111, 00000000])\\n      // %int8_rhs: [0xF0, 0x55, 0xFF, 0x00]  (binary: [11110000, 01010101, 11111111, 00000000])\\n      // Output tensor:\\n      // [0xFF, 0xFF, 0x00, 0x00]  (binary: [11111111, 11111111, 00000000, 00000000])\\n      ```\\n\\n      Mathematical definition: bitwise_xor(x, y) = x ^ y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.broadcast\",\n    \"summary\": \"Broadcast operation.\",\n    \"description\": \"The `broadcast` operation expands the dimensions of an input tensor according to specified broadcast dimensions.\\n\\n      This operation takes an input tensor and broadcasts it to a larger shape by repeating elements along\\n      dimensions where the input has size 1 and the output has a larger size. This is commonly used to\\n      make tensors compatible for elementwise operations.\\n\\n      Example:\\n      ```mlir\\n      // Broadcast a tensor from shape [1, 1, 32] to [1, 16, 32]\\n      %input = ... : tensor<1x1x32xf32>\\n      %result = ttir.broadcast(%input) {broadcast_dimensions = [1, 16, 1]} : (tensor<1x1x32xf32>) -> tensor<1x16x32xf32>\\n      // The input tensor is repeated 16 times along the second dimension\\n\\n      // Broadcast a tensor from shape [1, 3] to [2, 3]\\n      %input = ... : tensor<1x3xf32>\\n      %result = ttir.broadcast(%input) {broadcast_dimensions = [2, 1]} : (tensor<1x3xf32>) -> tensor<2x3xf32>\\n      // The input tensor is repeated 2 times along the first dimension\\n      ```\\n\\n      Note: Currently, when generating a TTNN executable, the broadcast and repeat operations share the same\\n      semantics due to the lack of tensor view support in TTNN. As a result, the broadcast operation is\\n      lowered to a repeat operation in the TTNN compilation pipeline.\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to broadcast.\\n\\n      Attributes:\\n      - `broadcast_dimensions` (Array of Integer): The number of times to broadcast the tensor along each dimension.\\n\\n      Output:\\n      - `result` (Tensor): The broadcasted tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.cbrt\",\n    \"summary\": \"Elementwise cubic root operation.\",\n    \"description\": \"The `cbrt` operation computes the cubic root (∛) of each element in the input tensor.\\n\\n      For each element, it returns the real-valued number that, when cubed, equals the input value.\\n      Unlike square root, cubic root is defined for negative numbers as well as positive numbers.\\n\\n      Example:\\n      ```mlir\\n      // Compute cubic root of all elements in %input\\n      %result = ttir.cbrt(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[8.0, 27.0, -8.0, 1.0], ... ]\\n      // Output tensor:\\n      // [[2.0, 3.0, -2.0, 1.0], ... ]\\n\\n      // Example with different values\\n      %result = ttir.cbrt(%float_input) : (tensor<3x2xf32>) -> tensor<3x2xf32>\\n      // Input tensor:\\n      // [[125.0, -27.0],\\n      //  [0.0, 0.001],\\n      //  [1000.0, -1.0]]\\n      // Output tensor:\\n      // [[5.0, -3.0],\\n      //  [0.0, 0.1],\\n      //  [10.0, -1.0]]\\n      ```\\n\\n      Mathematical definition: cbrt(x) = ∛x = x^(1/3)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.ceil\",\n    \"summary\": \"Elementwise ceiling operation.\",\n    \"description\": \"The `ceil` operation computes the ceiling (smallest integer greater than or equal to x)\\n      of each element in the input tensor.\\n\\n      For each element, it rounds the value up to the nearest integer. The operation preserves\\n      the data type of the input.\\n\\n      This operation has the idempotence property, meaning that applying it multiple times\\n      produces the same result as applying it once: ceil(ceil(x)) = ceil(x).\\n\\n      Example:\\n      ```mlir\\n      // Compute ceiling of all elements in %input\\n      %result = ttir.ceil(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[2.0, 2.0, 0.0, 5.0], ... ]\\n\\n      // Example with different values\\n      %result = ttir.ceil(%float_input) : (tensor<3x2xf32>) -> tensor<3x2xf32>\\n      // Input tensor:\\n      // [[3.14, -2.5],\\n      //  [0.0, 0.001],\\n      //  [9.999, -0.0]]\\n      // Output tensor:\\n      // [[4.0, -2.0],\\n      //  [0.0, 1.0],\\n      //  [10.0, 0.0]]\\n      ```\\n\\n      Mathematical definition: ceil(x) = ⌈x⌉ = min{n ∈ ℤ | n ≥ x}\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.clamp_scalar\",\n    \"summary\": \"Scalar value clamping operation.\",\n    \"description\": \"The `clamp_scalar` operation constrains all elements of a tensor to be within a specified range.\\n\\n      This operation applies element-wise clamping to the input tensor, ensuring that all values fall within\\n      the range [min, max]. Values less than `min` are set to `min`, and values greater than `max` are set to `max`.\\n      This is commonly used to ensure that tensor values stay within a valid range.\\n\\n      Example:\\n      ```mlir\\n      // Clamp values to the range [2.0, 5.0]\\n      %input = ... : tensor<1x8xf32>  // Input tensor with values:\\n                                      // [[0, 1, 2, 3, 4, 5, 6, 7]]\\n      %result = ttir.clamp_scalar(%input) {\\n          min = 2.0 : f32,  // Minimum value\\n          max = 5.0 : f32   // Maximum value\\n      } : (tensor<1x8xf32>) -> tensor<1x8xf32>\\n      // Result: [[2, 2, 2, 3, 4, 5, 5, 5]]\\n      // Values < 2.0 are clamped to 2.0, values > 5.0 are clamped to 5.0\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to clamp.\\n\\n      Attributes:\\n      - `min` (Float): The minimum value for clamping.\\n      - `max` (Float): The maximum value for clamping.\\n\\n      Output:\\n      - `result` (Tensor): The clamped tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" },\n      { \"name\": \"max\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.clamp_tensor\",\n    \"summary\": \"Tensor value clamping operation.\",\n    \"description\": \"The `clamp_tensor` operation constrains elements of a tensor to be within ranges specified by min and max tensors.\\n\\n    Unlike `clamp_scalar`, which uses scalar values for min and max, this operation uses tensor values for\\n    element-wise clamping. Each element in the input tensor is clamped between the corresponding elements\\n    in the min and max tensors. This allows for different clamping ranges for different elements.\\n\\n    Example:\\n    ```mlir\\n    // Clamp values using min and max tensors\\n    %input = ... : tensor<1x8xf32>  // Input tensor with values:\\n                                    // [[0, 1, 2, 3, 4, 5, 6, 7]]\\n    %min = ... : tensor<1x8xf32>    // Min tensor with values:\\n                                    // [[2, 2, 2, 3, 3, 3, 0, 0]]\\n    %max = ... : tensor<1x8xf32>    // Max tensor with values:\\n                                    // [[5, 5, 5, 9, 9, 9, 6, 6]]\\n    %result = ttir.clamp_tensor(%input, %min, %max) :\\n        (tensor<1x8xf32>, tensor<1x8xf32>, tensor<1x8xf32>) -> tensor<1x8xf32>\\n    // Result: [[2, 2, 2, 3, 4, 5, 6, 6]]\\n    // Each element is clamped between its corresponding min and max values\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to clamp.\\n    - `min` (Tensor): The tensor containing minimum values for clamping.\\n    - `max` (Tensor): The tensor containing maximum values for clamping.\\n\\n    Output:\\n    - `result` (Tensor): The clamped tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"min\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"max\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.collective_broadcast\",\n    \"summary\": \"Collective Broadcast op\",\n    \"description\": \"The collective_broadcast operation distributes a tensor from a single source device to all\\n    other devices within each replica group. Each replica group defines a subset of devices that\\n    participate in the broadcast, and the operation is applied independently within each group.\\n\\n    By convention, the first device listed in each replica group is treated as the broadcast source.\\n    The value of the `input` tensor on that source device is sent to all other devices in the same\\n    group. The `input` tensor values on non-source devices are ignored and will be overwritten\\n    during the operation.\\n\\n    Inputs:\\n      - input: The tensor to broadcast. Only the value on the first device of each replica group\\n              (the source) is used; values on other devices are ignored.\\n      - replica_groups: A list of replica groups. Each group is a list of device IDs, and the first\\n                        ID in each group is treated as the broadcast source for that group.\\n\\n    Result:\\n      - result: The output tensor containing the broadcasted value, identical across all devices\\n                in the same replica group.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.collective_permute\",\n    \"summary\": \"Collective permute operation.\",\n    \"description\": \"Collective permute op. This operation ingests a multi-device tensor spread across multi-devices and will shuffle the data according to source_target_pairs [['src', 'dest']].\\n\\n      Example:\\n        For a 1x2 mesh, the following will take the device shard living in device 0 and move it to device 1. The device shard living in device 1 will move to device 0.\\n        %source_target_pairs: [[0, 1], [1, 0]]\\n\\n        In the case of missing 'dest', the device shard living on that device will contain values of 0. For example, device shard living in device 0 will contain 0 values.\\n        %source_target_pairs: [[0, 1]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_target_pairs\", \"type\": \"I64ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.concat\",\n    \"summary\": \"Tensor concatenation operation.\",\n    \"description\": \"The `concat` operation joins multiple tensors along a specified dimension.\\n\\n      This operation concatenates a list of tensors along the dimension specified by `dim`.\\n      All input tensors must have the same shape except for the dimension being concatenated,\\n      and the output tensor's shape will match the input tensors except for the concatenated\\n      dimension, which will be the sum of the input dimensions.\\n\\n      Example:\\n      ```mlir\\n      // Concatenate along dimension 0\\n      %input1 = ... : tensor<2x3xf32>\\n      %input2 = ... : tensor<3x3xf32>\\n      %result = ttir.concat(%input1, %input2) {dim = 0 : i32} : (tensor<2x3xf32>, tensor<3x3xf32>) -> tensor<5x3xf32>\\n      // Input1 shape: [2, 3]\\n      // Input2 shape: [3, 3]\\n      // Output shape: [5, 3]\\n\\n      // Concatenate along dimension 1\\n      %input1 = ... : tensor<2x3xf32>\\n      %input2 = ... : tensor<2x2xf32>\\n      %result = ttir.concat(%input1, %input2) {dim = 1 : i32} : (tensor<2x3xf32>, tensor<2x2xf32>) -> tensor<2x5xf32>\\n      // Input1 shape: [2, 3]\\n      // Input2 shape: [2, 2]\\n      // Output shape: [2, 5]\\n      ```\\n\\n      Inputs:\\n      - `inputs` (Variadic Tensor): A list of input tensors to concatenate.\\n\\n      Attributes:\\n      - `dim` (Integer): The dimension along which to concatenate the tensors.\\n\\n      Output:\\n      - `result` (Tensor): The concatenated tensor.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.concatenate_heads\",\n    \"summary\": \"Concatenate heads operation.\",\n    \"description\": \"The `concatenate_heads` operation concatenates multiple heads of a multi-head attention tensor into a single tensor.\\n\\n    This operation is typically used in transformer models where the attention mechanism is split into multiple heads.\\n    It combines the outputs of these heads into a single tensor, allowing further processing.\\n\\n    It takes an input tensor with shape `[batch_size, num_heads, sequence_size, head_size]`\\n    and produces an output tensor with shape `[batch_size, sequence_size, num_heads * head_size]`.\\n\\n    It corresponds to a sequence of permute and reshape operations.\\n\\n    Example:\\n    ```mlir\\n    // Concatenate heads from a multi-head attention output\\n    %input = ... : tensor<1x24x32x128xbf16> // batch_size: 1, num_heads: 24, sequence_size: 32, head_size: 128\\n    %result = ttir.concatenate_heads(%input) : (tensor<1x24x32x128xbf16>) -> tensor<1x32x3072xbf16>\\n    // Input tensor shape: [1, 24, 32, 128]\\n    // Output tensor shape: [1, 32, 3072]\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor containing multiple heads.\\n\\n    Output:\\n    - `result` (Tensor): The concatenated output tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.constant\",\n    \"summary\": \"Tensor constant creation operation.\",\n    \"description\": \"The `constant` operation creates a tensor with values specified by a constant attribute.\\n\\n      This operation is used to create tensors with predefined values that remain constant\\n      throughout program execution. It's commonly used for initializing model weights, biases,\\n      and other fixed parameters in neural networks.\\n\\n      Example:\\n      ```mlir\\n      // Create a 2D tensor of zeros\\n      %result = ttir.constant() {\\n          value = dense<0> : tensor<2x3xi32>\\n      } : () -> tensor<2x3xi32>\\n      // Result: [[0, 0, 0], [0, 0, 0]]\\n\\n      // Create a 1D tensor with specific floating-point values\\n      %result = ttir.constant() {\\n          value = dense<[0.2, 1.3]> : tensor<2xf32>\\n      } : () -> tensor<2xf32>\\n      // Result: [0.2, 1.3]\\n\\n      // Create a scalar constant\\n      %result = ttir.constant() {\\n          value = dense<5.0> : tensor<f32>\\n      } : () -> tensor<f32>\\n      // Result: 5.0\\n\\n      // Create a 2D tensor with different values\\n      %result = ttir.constant() {\\n          value = dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>\\n      } : () -> tensor<2x3xi32>\\n      // Result: [[1, 2, 3], [4, 5, 6]]\\n      ```\\n\\n      Attributes:\\n      - `value` (DenseElementsAttr): The constant value of the tensor.\\n\\n      Output:\\n      - `result` (Tensor): The tensor with the specified constant values.\\n\\n      Note: The shape and element type of the result tensor are determined by the `value` attribute.\\n      The `constant` operation is typically folded during compilation, allowing for optimizations\\n      such as constant propagation.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.conv_transpose2d\",\n    \"summary\": \"ConvTranspose2d operation.\",\n    \"description\": \"Applies a 2D transposed convolution operator over an input image composed of several input planes.\\n\\n      This operation performs the gradient of a 2D convolution with respect to the input, which is useful\\n      for tasks like upsampling feature maps in neural networks. It supports configurable stride, padding,\\n      dilation, output padding, and grouping parameters.\\n\\n      Example:\\n      ```mlir\\n      // Basic 2D transposed convolution\\n      %input = ... : tensor<1x14x14x16xf32>   // Batch size 1, 14x14 feature map, 16 channels\\n      %weight = ... : tensor<16x8x3x3xf32>    // 16 input channels, 8 output channels, 3x3 kernel\\n      %bias = ... : tensor<1x1x1x8xf32>       // Bias for 8 output channels\\n      %result = ttir.conv_transpose2d(%input, %weight, %bias) {\\n          stride = [2, 2],\\n          padding = [0, 0, 0, 0],\\n          dilation = [1, 1],\\n          output_padding = [0, 0],\\n          groups = 1\\n      } : (tensor<1x14x14x16xf32>, tensor<16x8x3x3xf32>, tensor<1x1x1x8xf32>) -> tensor<1x28x28x8xf32>\\n\\n      // Transposed convolution with padding and output padding\\n      %input = ... : tensor<1x14x14x16xf32>   // Batch size 1, 14x14 feature map, 16 channels\\n      %weight = ... : tensor<16x8x4x4xf32>    // 16 input channels, 8 output channels, 4x4 kernel\\n      %bias = ... : tensor<1x1x1x8xf32>       // Bias for 8 output channels\\n      %result = ttir.conv_transpose2d(%input, %weight, %bias) {\\n          stride = [2, 2],\\n          padding = [1, 1, 1, 1],\\n          dilation = [1, 1],\\n          output_padding = [1, 1],\\n          groups = 1\\n      } : (tensor<1x14x14x16xf32>, tensor<16x8x4x4xf32>, tensor<1x1x1x8xf32>) -> tensor<1x29x29x8xf32>\\n      ```\\n\\n      Inputs:\\n      - `input` AnyRankedTensor: 4D tensor where dimension indices are controlled by `batch_dim`, `height_dim`,\\n        `width_dim`, and `channel_dim` attributes. Default layout is NHWC (N, H_in, W_in, C) where:\\n        - N is the batch size\\n        - H_in is the height of the input planes\\n        - W_in is the width of the input planes\\n        - C is the number of channels\\n      - `weight` (AnyRankedTensor): expected in the following format (C, O/G, K_H, K_W) where:\\n        - C is the number of input channels\\n        - O is the number of output channels\\n        - G is the number of groups\\n        - K_H is the height of the kernel\\n        - K_W is the width of the kernel\\n      - `bias` Optional<AnyRankedTensor>: bias tensor with output channels at position specified by `channel_dim`.\\n        Default format is (1, 1, 1, O).\\n\\n      Attributes:\\n      - `stride` (i32 | array<2xi32>): Controls the stride for the cross-correlation.\\n      - `padding` (i32 | array<2xi32> | array<4xi32>): Controls the amount of implicit zero padding on both sides for dilation * (kernel_size - 1) - padding number of points.\\n      - `output_padding` (i32 | array<2xi32>): Controls the additional size added to one side of the output shape.\\n      - `dilation` (i32 | array<2xi32>): Controls the spacing between the kernel points\\n      - `groups` i32: Controls the connections between inputs and outputs. Must be divisible by input and output channels.\\n      - `batch_dim` (i64): Index of the batch dimension in input/output tensors. Default: 0.\\n      - `height_dim` (i64): Index of the height dimension in input/output tensors. Default: 1.\\n      - `width_dim` (i64): Index of the width dimension in input/output tensors. Default: 2.\\n      - `channel_dim` (i64): Index of the channel dimension in input/output tensors. Default: 3.\\n\\n      Output:\\n      - `result` AnyRankedTensor: 4D tensor with same layout as input (controlled by dimension attributes).\\n        Default format is (N, H_out, W_out, O) where:\\n        - H_out = (H_in - 1) * stride[0] - (padding_top + padding_bottom) + dilation[0] * (K_H - 1) + output_padding[0] + 1\\n        - W_out = (W_in - 1) * stride[1] - (padding_left + padding_right) + dilation[1] * (K_W - 1) + output_padding[1] + 1\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"stride\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"output_padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"dilation\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"height_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"width_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 2>\" },\n      { \"name\": \"channel_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 3>\" },\n      { \"name\": \"flattened_compat_info\", \"type\": \"DefaultValuedAttr<TTIR_FlattenedCompatInfoAttr, nullptr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.conv2d\",\n    \"summary\": \"Conv2d operation.\",\n    \"description\": \"Applies a 2D convolution over an input image composed of several input planes.\\n\\n      This operation performs a 2D convolution on the input tensor using the provided weight tensor\\n      and optional bias. It supports configurable stride, padding, dilation, and grouping parameters\\n      to control the convolution behavior.\\n\\n      Example:\\n      ```mlir\\n      // Basic 2D convolution\\n      %input = ... : tensor<1x28x28x3xf32>    // Batch size 1, 28x28 image, 3 channels\\n      %weight = ... : tensor<16x3x3x3xf32>    // 16 output channels, 3 input channels, 3x3 kernel\\n      %bias = ... : tensor<1x1x1x16xf32>      // Bias for 16 output channels\\n      %result = ttir.conv2d(%input, %weight, %bias) {\\n          stride = [1, 1],\\n          padding = [0, 0, 0, 0],\\n          dilation = [1, 1],\\n          groups = 1\\n      } : (tensor<1x28x28x3xf32>, tensor<16x3x3x3xf32>, tensor<1x1x1x16xf32>) -> tensor<1x26x26x16xf32>\\n\\n      // Convolution with stride 2 and padding\\n      %input = ... : tensor<1x28x28x3xf32>    // Batch size 1, 28x28 image, 3 channels\\n      %weight = ... : tensor<16x3x3x3xf32>    // 16 output channels, 3 input channels, 3x3 kernel\\n      %bias = ... : tensor<1x1x1x16xf32>      // Bias for 16 output channels\\n      %result = ttir.conv2d(%input, %weight, %bias) {\\n          stride = [2, 2],\\n          padding = [1, 1, 1, 1],\\n          dilation = [1, 1],\\n          groups = 1\\n      } : (tensor<1x28x28x3xf32>, tensor<16x3x3x3xf32>, tensor<1x1x1x16xf32>) -> tensor<1x14x14x16xf32>\\n      ```\\n\\n      Inputs:\\n      - `input` (AnyRankedTensor): 4D tensor where dimension indices are controlled by `batch_dim`, `height_dim`,\\n        `width_dim`, and `channel_dim` attributes. Default layout is NHWC (N, H_in, W_in, C) where:\\n        - N is the batch size\\n        - H_in is the height of the input planes\\n        - W_in is the width of the input planes\\n        - C is the number of channels\\n      - `weight` (AnyRankedTensor): expected in the following format (O, C/G, K_H, K_W) where:\\n        - C is the number of input channels\\n        - O is the number of output channels\\n        - G is the number of groups\\n        - K_H is the height of the kernel\\n        - K_W is the width of the kernel\\n      - `bias` Optional<AnyRankedTensor>: bias tensor with output channels at position specified by `channel_dim`.\\n        Default format is (1, 1, 1, O).\\n\\n      Attributes:\\n      - `stride` (i32 | array<2xi32>):\\n        - i32: Same stride for height and width dimensions (sH = sW = value).\\n        - array<2xi32>: [sH, sW] where sH is stride for height and sW is stride for width.\\n      - `padding` (i32 | array<2xi32> | array<4xi32>):\\n        - i32: Same padding for all sides (pT = pL = pB = pR = value).\\n        - array<2xi32>: [pH, pW] where pH is padding for height (top/bottom) and pW is padding for width (left/right).\\n        - array<4xi32>: [pT, pL, pB, pR] for top, left, bottom, and right padding respectively.\\n      - `dilation` (i32 | array<2xi32>): Spacing between kernel elements.\\n        - i32: Same dilation for height and width dimensions (dH = dW = value).\\n        - array<2xi32>: [dH, dW] where dH is dilation for height and dW is dilation for width.\\n      - `groups` (i32): Number of blocked connections from input channels to output channels. Input and output channels must both be divisible by groups.\\n      - `batch_dim` (i64): Index of the batch dimension in input/output tensors. Default: 0.\\n      - `height_dim` (i64): Index of the height dimension in input/output tensors. Default: 1.\\n      - `width_dim` (i64): Index of the width dimension in input/output tensors. Default: 2.\\n      - `channel_dim` (i64): Index of the channel dimension in input/output tensors. Default: 3.\\n\\n      Output:\\n      - `result` AnyRankedTensor: 4D tensor with same layout as input (controlled by dimension attributes).\\n        Default format is (N, H_out, W_out, O) where:\\n        - `H_out = (H_in + pT + pB - dH * (K_H - 1) - 1) / sH + 1`\\n        - `W_out = (W_in + pL + pR - dW * (K_W - 1) - 1) / sW + 1`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"stride\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"dilation\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"height_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"width_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 2>\" },\n      { \"name\": \"channel_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 3>\" },\n      { \"name\": \"flattened_compat_info\", \"type\": \"DefaultValuedAttr<TTIR_FlattenedCompatInfoAttr, nullptr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.conv3d\",\n    \"summary\": \"Conv3d operation.\",\n    \"description\": \"Applies a 3D convolution over an input volume composed of several input planes.\\n\\n      This operation performs a 3D convolution on the input tensor using the provided weight tensor\\n      and optional bias. It supports configurable stride, padding, padding_mode and grouping parameters\\n      to control the convolution behavior. This is commonly used for video or volumetric data processing.\\n\\n      Example:\\n      ```mlir\\n      // Basic 3D convolution with 3x3x3 kernel\\n      %input = ... : tensor<1x8x28x28x4xf32>     // Batch=1, Depth=8, H=28, W=28, Channels=4\\n      %weight = ... : tensor<16x4x3x3x3xf32>     // 16 output channels, 4 input channels, 3x3x3 kernel\\n      %bias = ... : tensor<1x1x1x1x16xf32>       // Bias for 16 output channels\\n      %result = ttir.conv3d(%input, %weight, %bias) {\\n          stride = [1, 1, 1],\\n          padding = [0, 0, 0],\\n          groups = 1,\\n          padding_mode = \\\"zeros\\\"\\n      } : (tensor<1x8x28x28x4xf32>, tensor<16x4x3x3x3xf32>, tensor<1x1x1x1x16xf32>) -> tensor<1x6x26x26x16xf32>\\n\\n      // Convolution with stride 2 and padding\\n      %input = ... : tensor<1x8x28x28x4xf32>     // Batch size 1, Depth=8, H=28, W=28, Channels=4\\n      %weight = ... : tensor<16x4x3x3x3xf32>     // 16 output channels, 4 input channels, 3x3x3 kernel\\n      %bias = ... : tensor<1x1x1x1x16xf32>       // Bias for 16 output channels\\n      %result = ttir.conv3d(%input, %weight, %bias) {\\n          stride = [2, 2, 2],\\n          padding = [1, 1, 1],\\n          groups = 1,\\n          padding_mode = \\\"zeros\\\"\\n      } : (tensor<1x8x28x28x4xf32>, tensor<16x4x3x3x3xf32>, tensor<1x1x1x1x16xf32>) -> tensor<1x4x14x14x16xf32>\\n      ```\\n\\n      Inputs:\\n      - `input` (AnyRankedTensor): expected in the following format (N, D, H, W, C) where:\\n        - N is the batch size\\n        - D is the depth of the input volume\\n        - H is the height of the input planes\\n        - W is the width of the input planes\\n        - C is the number of input channels\\n      - `weight` (AnyRankedTensor): expected in the following format (C_out, C_in, K_D, K_H, K_W) where:\\n        - C_out is the number of output channels\\n        - C_in is the number of input channels\\n        - K_D is the depth of the kernel\\n        - K_H is the height of the kernel\\n        - K_W is the width of the kernel\\n      - `bias` Optional<AnyRankedTensor>: expected in the following format (1, 1, 1, 1, C_out).\\n\\n      Attributes:\\n      - `stride` (i32 | array<3xi32>): [sD, sH, sW] where sD is stride for depth, sH for height, sW for width.\\n      - `padding` (i32 |array<3xi32>): [pD, pH, pW] where pD is padding for depth, pH for height, pW for width.\\n        Padding is symmetric (same on both sides of each dimension).\\n      - `padding_mode` (StrAttr): \\\"zeros\\\" or \\\"replicate\\\" - padding fill strategy.\\n      - `groups` (i32): Number of blocked connections from input channels to output channels.\\n\\n      Output:\\n      - `result` AnyRankedTensor: 5D tensor in format (N, D_out, H_out, W_out, C_out) where:\\n        - `D_out = (D_in + 2*pD - K_D) / sD + 1`\\n        - `H_out = (H_in + 2*pH - K_H) / sH + 1`\\n        - `W_out = (W_in + 2*pW - K_W) / sW + 1`\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"stride\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 0>\" },\n      { \"name\": \"depth_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 1>\" },\n      { \"name\": \"height_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 2>\" },\n      { \"name\": \"width_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 3>\" },\n      { \"name\": \"channel_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 4>\" },\n      { \"name\": \"padding_mode\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"zeros\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.cos\",\n    \"summary\": \"Elementwise cosine operation.\",\n    \"description\": \"The `cos` operation computes the cosine of each element in the input tensor.\\n\\n      For each element, it returns the cosine of the angle in radians.\\n\\n      Example:\\n      ```mlir\\n      // Compute cosine of all elements in %input\\n      %result = ttir.cos(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.9601, 0.5403, -0.9553, -0.1365], ... ]\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.cumsum\",\n    \"summary\": \"Cumulative sum operation.\",\n    \"description\": \"The `cumsum` operation computes the cumulative sum of elements along a specified dimension of the input tensor.\\n\\n    For each position in the output tensor, this operation computes the sum of all elements in the input tensor\\n    along the specified dimension up to and including that position. The shape of the output tensor matches\\n    the shape of the input tensor.\\n\\n    Example:\\n    ```mlir\\n    // Cumulative sum along dimension 0\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.cumsum(%input) {dim = 0 : i64} : (tensor<2x3xf32>) -> tensor<2x3xf32>\\n    // Input tensor:\\n    // [[1, 2, 3],\\n    //  [4, 5, 6]]\\n    // Output tensor:\\n    // [[1, 2, 3],   // first row remains the same\\n    //  [5, 7, 9]]   // each element is the sum of the corresponding column up to this point\\n\\n    // Cumulative sum along dimension 1\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.cumsum(%input) {dim = 1 : i64} : (tensor<2x3xf32>) -> tensor<2x3xf32>\\n    // Input tensor:\\n    // [[1, 2, 3],\\n    //  [4, 5, 6]]\\n    // Output tensor:\\n    // [[1, 3, 6],   // each element is the sum of the corresponding row up to this point\\n    //  [4, 9, 15]]\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor.\\n\\n    Attributes:\\n    - `dim` (Integer): The dimension along which to compute the cumulative sum.\\n\\n    Output:\\n    - `result` (Tensor): The tensor containing the cumulative sums.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.dealloc\",\n    \"summary\": \"Dealloc op.\",\n    \"description\": \"Tensor Dealloc operation\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.dequantize\",\n    \"summary\": \"Dequantize operation.\",\n    \"description\": \"The Dequantize operation converts a quantized tensor back into a floating-point tensor using the `quant.uniform` type from the MLIR Quant dialect.\\n    The input tensor is expected to be of type `quant.uniform.`\\n    The output tensor will be a floating-point tensor, where each element is computed as:\\n    ```\\n    output[i] = (input[i] - zero_point) * scale\\n    ```\\n    Example:\\n    ```mlir\\n    %input = ttir.empty() : () -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n    %dequantized = \\\"ttir.dequantize\\\"(%input) : (tensor<64x128x!quant.uniform<i32:f32, 0.1>>) -> tensor<64x128xf32>\\n\\n    // In this example:\\n    // - The input is a 64x128 tensor of 32-bit quantized values\\n    // - The output is a 64x128 tensor of 32-bit floating-point values\\n    // - The scale is 0.1 (each step represents 0.1 in the original scale)\\n    // - The zero point is 128 (the value 128 in the quantized space represents 0.0 in the original space)\\n    ```\\n\\n    Inputs:\\n    - `input` (Quantized Tensor): The quantized tensor to be dequantized.\\n\\n    Results:\\n    - `result` (Tensor): The floating-point tensor after dequantization.\\n\\n    Note: The quantization parameters (scale and zero point) are specified in the input tensor type.\\n    Dequantization is the reverse process of quantization, converting quantized values back to floating-point values.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.dequantize_unrolled\",\n    \"summary\": \"Dequantize operation unrolled (scale and zero point as input operands).\",\n    \"description\": \"The DequantizeUnrolledOp dequantizes a tensor using the scale and zero point provided as input operands.\\n\\n    Inputs:\\n      - `input` AnyRankedTensor: The input tensor to be dequantized. Must have quantized element type.\\n      - `scale` AnyRankedTensor: The scale factor (or factors for per-axis quantization).\\n      - `zero_point` AnyRankedTensor: The zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n      - `axis` Optional<i32>: The axis along which quantization is applied. Must be in range [0, rank) where rank is the rank of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.distributed_rms_norm\",\n    \"summary\": \"Distributed RMS normalization with all-gather operation\",\n    \"description\": \"Fused distributed RMS normalization across mesh devices. Each device\\n    computes local RMS statistics (E(x²)), the statistics are all-gathered\\n    along cluster_axis to obtain globally-correct values, and each device\\n    then normalizes its local shard. The steps are:\\n    1. Optional residual addition (input + residual)\\n    2. Compute local E(x²) and all-gather statistics across cluster_axis\\n    3. RMS normalization: output = input * rsqrt(E(x²) + epsilon) * weight\\n\\n    Only statistics are communicated across devices — the input data itself\\n    is not all-gathered. Each device's output shape equals its input shape.\\n\\n    This is a multi-device operation that requires the tensor to be sharded\\n    across a device mesh.\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to be normalized.\\n    - `weight` (Optional Tensor): The scale parameter (gamma).\\n    - `residual` (Optional Tensor): Residual tensor for fused add before\\n        normalization.\\n\\n    Attributes:\\n    - `cluster_axis` specifies which mesh dimension to all-gather the\\n        statistics across (0 or 1).\\n    - `epsilon` is a small constant added for numerical stability\\n        (default: 1e-05).\\n\\n    Output:\\n    - `result` (Tensor): The normalized output tensor (same shape as input).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"residual\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.div\",\n    \"summary\": \"Elementwise division operation.\",\n    \"description\": \"The `div` operation performs an elementwise division between two tensors.\\n\\n      For each pair of corresponding elements, it divides the element in the first tensor (dividend) by\\n      the element in the second tensor (divisor) and places the result in the output tensor.\\n\\n      Example:\\n      ```mlir\\n      // Division operation\\n      %result = ttir.div(%lhs, %rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>\\n      // Input tensors:\\n      // %lhs: [10, 20, 20]\\n      // %rhs: [1, 2, 3]\\n      // Output tensor:\\n      // [10, 10, 6]\\n\\n      // Example with floating point values\\n      %result = ttir.div(%float_lhs, %float_rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %float_lhs: [3.5, 0.0, -1.2]\\n      // %float_rhs: [1.5, 2.0, -3.2]\\n      // Output tensor:\\n      // [2.333333333, 0.0, -0.375]\\n      ```\\n\\n      Note: Division by zero typically results in undefined behavior or NaN for floating-point types.\\n\\n      Mathematical definition: div(x, y) = x / y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.dot_general\",\n    \"summary\": \"Dot general operation.\",\n    \"description\": \"Flexible tensor operation that generalizes matrix multiplication by allowing user to specify which\\n      dimensions of two tensors to contract. Matrix multiplication is a special case of this operation,\\n      where the contraction happens along the last axis of the first tensor and the second-to-last axis of the second tensor.\\n      From StableHLO DotGeneral Op https://openxla.org/stablehlo/spec#dot_general\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_dims_lhs\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"contract_dims_lhs\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"batch_dims_rhs\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"contract_dims_rhs\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.dropout\",\n    \"summary\": \"Dropout operation.\",\n    \"description\": \"Applies dropout to the input tensor element-wise.\\n\\n    During training, randomly zeroes some elements of the input tensor with\\n    probability `prob` using samples from a Bernoulli distribution. The\\n    remaining elements are scaled by `scale` (typically 1/(1-prob)) to maintain\\n    the expected sum.\\n\\n    Example:\\n      %result = \\\"ttir.dropout\\\"(%input) <{prob = 0.2 : f32, scale = 1.25 : f32, seed = 42 : ui32}> : (tensor<64x128xbf16>) -> tensor<64x128xbf16>\\n\\n    Attributes:\\n      - `prob` (Float): Dropout probability. Elements are zeroed with this probability [Default: 0.0].\\n      - `scale` (Float): Scale factor applied to non-zeroed elements. Typically 1/(1-prob) [Default: 1.0].\\n      - `seed` (Integer): Seed for the random number generator [Default: 0].\\n      - `use_per_device_seed` (Bool): Whether to use a different seed per device [Default: true].\\n\\n    Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n    Output:\\n      - `result` (Tensor): The output tensor with dropout applied.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prob\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"seed\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" },\n      { \"name\": \"use_per_device_seed\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.embedding\",\n    \"summary\": \"Embedding lookup operation.\",\n    \"description\": \"The `embedding` operation performs a lookup in an embedding table (weight matrix) using integer indices.\\n\\n      This operation takes an input tensor of indices and a weight tensor representing the embedding table.\\n      For each index in the input tensor, it retrieves the corresponding row from the weight tensor.\\n      The result is a tensor where each input index is replaced by its corresponding embedding vector.\\n\\n      Example:\\n      ```mlir\\n      // Embedding lookup\\n      %input = ... : tensor<2x3xi32>  // Batch of indices\\n      %weight = ... : tensor<10x4xf32>  // Embedding table with 10 entries of dimension 4\\n      %result = ttir.embedding(%input, %weight) : (tensor<2x3xi32>, tensor<10x4xf32>) -> tensor<2x3x4xf32>\\n\\n      // Input tensor (indices):\\n      // [[0, 2, 5],\\n      //  [7, 1, 9]]\\n\\n      // Weight tensor (embedding table):\\n      // [[0.1, 0.2, 0.3, 0.4],  // embedding vector for index 0\\n      //  [0.5, 0.6, 0.7, 0.8],  // embedding vector for index 1\\n      //  [0.9, 1.0, 1.1, 1.2],  // embedding vector for index 2\\n      //  ...\\n      //  [1.7, 1.8, 1.9, 2.0]]  // embedding vector for index 9\\n\\n      // Output tensor:\\n      // [[[0.1, 0.2, 0.3, 0.4],  // embedding for index 0\\n      //   [0.9, 1.0, 1.1, 1.2],  // embedding for index 2\\n      //   [...]],                 // embedding for index 5\\n      //  [[...],                  // embedding for index 7\\n      //   [0.5, 0.6, 0.7, 0.8],  // embedding for index 1\\n      //   [...]]]                 // embedding for index 9\\n      ```\\n\\n      Note: The indices in the input tensor must be valid indices into the first dimension of the weight tensor.\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor containing indices.\\n      - `weight` (Tensor): The embedding table tensor.\\n\\n      Output:\\n      - `result` (Tensor): The resulting tensor containing the embeddings.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.embedding_backward\",\n    \"summary\": \"Embedding backward operation.\",\n    \"description\": \"The `embedding_backward` operation computes the gradient of the embedding operation with respect to the weight tensor.\\n\\n      This operation takes an input tensor of indices, the original weight tensor, and the gradient tensor from previous backpropagation steps.\\n      It computes how the embedding weights should be updated during backpropagation by accumulating gradients at the appropriate\\n      indices in the weight tensor.\\n\\n      Example:\\n      ```mlir\\n      // Embedding backward\\n      %input = ... : tensor<2x3xi32>  // Original indices used in the forward pass\\n      %weight = ... : tensor<10x4xf32>  // Original embedding table\\n      %in_gradient = ... : tensor<2x3x4xf32>  // Gradient from previous backpropagation steps\\n      %result = ttir.embedding_backward(%input, %weight, %in_gradient) :\\n          (tensor<2x3xi32>, tensor<10x4xf32>, tensor<2x3x4xf32>) -> tensor<10x4xf32>\\n\\n      // Input tensor (indices):\\n      // [[0, 2, 5],\\n      //  [7, 1, 9]]\\n\\n      // Input gradient tensor (from previous backpropagation steps):\\n      // [[[0.1, 0.2, 0.3, 0.4],  // gradient for embedding of index 0\\n      //   [0.5, 0.6, 0.7, 0.8],  // gradient for embedding of index 2\\n      //   [...]],                 // gradient for embedding of index 5\\n      //  [[...],                  // gradient for embedding of index 7\\n      //   [0.9, 1.0, 1.1, 1.2],  // gradient for embedding of index 1\\n      //   [...]]]                 // gradient for embedding of index 9\\n\\n      // Output tensor (gradient for the embedding table):\\n      // The gradients are accumulated at the corresponding indices in the weight tensor.\\n      // For example, at index 0, the gradient is [0.1, 0.2, 0.3, 0.4]\\n      ```\\n\\n      Note: If the same index appears multiple times in the input tensor, the gradients are accumulated (added) at that index in the output tensor.\\n\\n      Inputs:\\n      - `input` (Tensor): The original input tensor containing indices used in the forward pass.\\n      - `weight` (Tensor): The original embedding table tensor.\\n      - `in_gradient` (Tensor): The gradient tensor from the forward pass.\\n\\n      Output:\\n      - `result` (Tensor): The gradient tensor for the embedding table.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"in_gradient\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.empty\",\n    \"summary\": \"Empty tensor allocation operation.\",\n    \"description\": \"The `empty` operation creates an uninitialized tensor with the specified shape and element type.\\n\\n      This operation allocates memory for a tensor but does not initialize its values. It's commonly used\\n      as a first step before filling the tensor with computed values. The shape and element type of the\\n      tensor are determined by the return type.\\n\\n      Example:\\n      ```mlir\\n      // Create an uninitialized 2D tensor with shape [3, 4]\\n      %result = ttir.empty() : tensor<3x4xf32>\\n\\n      // Create an uninitialized 3D tensor with shape [2, 3, 4]\\n      %result = ttir.empty() : tensor<2x3x4xi32>\\n\\n      // Use empty to create a tensor for storing computation results\\n      %input = ... : tensor<10x20xf32>\\n      %result = ttir.some_computation(%input) : (tensor<10x20xf32>) -> tensor<10x20xf32>\\n      ```\\n\\n      Output:\\n      - `result` (Tensor): The uninitialized tensor.\\n\\n      Note: Since the tensor is uninitialized, reading from it before writing may yield undefined values.\\n      This operation is typically used in conjunction with other operations that will fill the tensor with\\n      meaningful values. The `empty` operation is more efficient than `zeros` or `ones` when the tensor\\n      will be completely overwritten, as it avoids the initialization step.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"ttir.eq\",\n    \"summary\": \"Elementwise equality comparison operation.\",\n    \"description\": \"The `eq` operation performs an elementwise equality comparison between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if the elements are equal\\n      - 0 (false) if the elements are not equal\\n\\n      Note that special handling may be required for floating-point NaN values, as NaN is not\\n      equal to any value, including itself.\\n\\n      Example:\\n      ```mlir\\n      // Compare elements for equality\\n      %result = ttir.eq(%lhs, %rhs) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1.0, 2.0, 3.0, 2.0], ... ]\\n      // %rhs: [[1.0, 2.0, 4.0, 5.0], ... ]\\n      // Output tensor:\\n      // [[1, 1, 0, 0], ... ]  // 1 where equal, 0 where not equal\\n\\n      // Example with integer tensors\\n      %result = ttir.eq(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, -5, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [1, 0, 0]  // Only the first elements are equal\\n      ```\\n\\n      Mathematical definition: equal(x, y) = x == y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.erf\",\n    \"summary\": \"Element-wise error function operation.\",\n    \"description\": \"Element-wise error function (erf) operation. Calculates erf(x) for each element of the input tensor.\\n\\n    Example:\\n    ```mlir\\n    // Compute error function for all elements in %input\\n    %result = ttir.erf(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n    // Input tensor with values [0.0, 1.0, -1.0, 2.0]\\n    // Output tensor with values [0.0, 0.8427, -0.8427, 0.9953]\\n    ```\\n\\n    Mathematical definition: erf(x) = (2/√π) ∫₀ˣ e^(-t²) dt\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.erfc\",\n    \"summary\": \"Element-wise complementary error function operation.\",\n    \"description\": \"Element-wise complementary error function (erfc) operation. Calculates erfc(x) = 1 - erf(x) for each element of the input tensor.\\n\\n    Example:\\n    ```mlir\\n    // Compute complementary error function for all elements in %input\\n    %result = ttir.erfc(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n    // Input tensor with values [0.0, 1.0, -1.0, 2.0]\\n    // Output tensor with values [1.0, 0.1573, 1.8427, 0.0047]\\n    ```\\n\\n    Mathematical definition: erfc(x) = 1 - erf(x) = 1 - (2/√π) ∫ₓ^∞ e^(-t²) dt\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.exp\",\n    \"summary\": \"Elementwise exponential op.\",\n    \"description\": \"The `exp` operation computes the exponential of each element in the input tensor.\\n\\n      For each element, it returns e^x, where e is the base of natural logarithms (approximately 2.71828).\\n\\n      Example:\\n      ```mlir\\n      // Compute exponential of all elements in %input\\n      %result = ttir.exp(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.0, 2.0, -3.0, 4.0], ... ]\\n      // Output tensor:\\n      // [[2.71828, 7.389056, 0.090031, 54.59815], ... ]\\n      ```\\n\\n      Mathematical definition: exp(x) = e^x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.expm1\",\n    \"summary\": \"Elementwise exponential minus one operation.\",\n    \"description\": \"The `expm1` operation computes the exponential of each element in the input tensor and subtracts one.\\n\\n    For each element x, it returns e^x - 1. This operation is more accurate than computing\\n    exp(x) - 1 directly for x values close to zero, where catastrophic cancellation can occur\\n    in the subtraction.\\n\\n    Example:\\n    ```mlir\\n    // Compute expm1 of all elements in %input\\n    %result = ttir.expm1(%input) : (tensor<2x2xf32>) -> tensor<2x2xf32>\\n    // Input tensor:\\n    // [[0.0, 1.0],\\n    //  [0.0, 0.0]]\\n    // Output tensor:\\n    // [[0.0, 1.71828],\\n    //  [0.0, 0.0]]\\n\\n    // Example with small values where expm1 is more accurate than exp(x)-1\\n    %result = ttir.expm1(%small_input) : (tensor<3xf32>) -> tensor<3xf32>\\n    // Input tensor:\\n    // [1e-10, 1e-7, 1e-5]\\n    // Output tensor:\\n    // [1e-10, 1e-7, 1e-5]  // Approximately equal to the input for very small values\\n    ```\\n\\n    Mathematical definition: expm1(x) = e^x - 1\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.fill_cache\",\n    \"summary\": \"Cache filling operation.\",\n    \"description\": \"The `fill_cache` operation fills a cache tensor with values from an input tensor.\\n\\n    Unlike `update_cache` which updates specific positions, this operation fills the entire cache\\n    or a contiguous section of it with values from the input tensor. This is commonly used to\\n    initialize a cache in sequence models.\\n\\n    Example:\\n    ```mlir\\n    // Fill cache with input values\\n    %cache = ... : tensor<2x16x64xf32>  // Batch size 2, sequence length 16, hidden dim 64\\n    %input = ... : tensor<2x16x64xf32>  // Initial values for the entire cache\\n    %result = ttir.fill_cache(%cache, %input) {batch_offset = 0 : i32} :\\n        tensor<2x16x64xf32>, tensor<2x16x64xf32> -> tensor<2x16x64xf32>\\n    // The entire cache tensor is filled with values from input\\n\\n    // Fill a portion of the cache\\n    %cache = ... : tensor<2x16x64xf32>  // Batch size 2, sequence length 16, hidden dim 64\\n    %input = ... : tensor<2x8x64xf32>   // Values for half of the cache\\n    %result = ttir.fill_cache(%cache, %input) {batch_offset = 0 : i32} :\\n        tensor<2x16x64xf32>, tensor<2x8x64xf32> -> tensor<2x16x64xf32>\\n    // The first 8 positions of the cache are filled with values from input\\n    ```\\n\\n    Inputs:\\n    - `cache` (Tensor): The cache tensor to be filled.\\n    - `input` (Tensor): The input tensor containing the values to fill the cache with.\\n\\n    Attributes:\\n    - `batch_offset` (Integer): Offset in the batch dimension.\\n\\n    Output:\\n    - `result` (Tensor): The filled cache tensor.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_offset\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.floor\",\n    \"summary\": \"Elementwise floor operation.\",\n    \"description\": \"The `floor` operation computes the floor (greatest integer less than or equal to x)\\n      of each element in the input tensor.\\n\\n      For each element, it rounds the value down to the nearest integer. The operation preserves\\n      the data type of the input.\\n\\n      This operation has the idempotence property, meaning that applying it multiple times\\n      produces the same result as applying it once: floor(floor(x)) = floor(x).\\n\\n      Example:\\n      ```mlir\\n      // Compute floor of all elements in %input\\n      %result = ttir.floor(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[1.0, 2.0, -1.0, 4.0], ... ]\\n      ```\\n\\n      Mathematical definition: floor(x) = ⌊x⌋ = max{n ∈ ℤ | n ≤ x}\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.full\",\n    \"summary\": \"Creates a tensor filled with the specified value\",\n    \"description\": \"Tensor operation to create a tensor filled with a specified value.\\n\\n    Given a `shape` and a `fill_value`, produces a tensor with the shape, filled with the specified value.\\n\\n    Example:\\n      %0 = \\\"ttir.full\\\"() <{shape = array<i32: 64, 32, 32>, fill_value = 7 : i32}> : () -> tensor<64x32x32xi32>\\n      // %0: [[[7, 7, 7, ..., 7], [7, 7, 7, ..., 7], ..., [7, 7, 7, ..., 7]]]\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"fill_value\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.gather\",\n    \"summary\": \"Gather operation.\",\n    \"description\": \"The `gather` operation collects slices from an input tensor at positions specified by start indices.\\n\\n      This operation is based on the StableHLO Gather operation (https://openxla.org/stablehlo/spec#gather) and\\n      allows for flexible slicing and indexing of tensors. It can be used to implement operations like array\\n      indexing, slicing, dynamic indexing, and more complex gathering patterns.\\n\\n      Example:\\n      ```mlir\\n      // Basic gather example: gather elements from a 2D tensor using indices\\n      %input = ... : tensor<5x3xf32>         // Input tensor with shape [5,3]\\n      %indices = ... : tensor<2xi64>         // Indices tensor with values [2, 1]\\n      %result = ttir.gather(%input, %indices) {\\n          offset_dims = [0],                 // Output dimensions that are gathered from input\\n          collapsed_slice_dims = [0],        // Input dimensions that are collapsed\\n          operand_batching_dims = [],        // Batch dimensions of the input\\n          start_indices_batching_dims = [],  // Batch dimensions of the indices\\n          start_index_map = [0],             // Maps indices to input dimensions\\n          index_vector_dim = 0,              // Which dimension of indices contains the index vector\\n          slice_sizes = [1, 3],              // Size of the slice to extract from each position\\n          indices_are_sorted = false         // Whether indices are sorted\\n      } : (tensor<5x3xf32>, tensor<2xi64>) -> tensor<3xf32>\\n\\n      // This gathers a slice of size [1,3] starting at position [2,0] from the input tensor,\\n      // which results in the values from the third row of the input tensor.\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The tensor from which to gather values.\\n      - `start_indices` (Tensor): Tensor containing the starting indices for slices.\\n\\n      Attributes:\\n      - `offset_dims` (Array of Integer): Output dimensions that correspond to dimensions of the gathered slice.\\n      - `collapsed_slice_dims` (Array of Integer): Input dimensions that are collapsed when gathering.\\n      - `operand_batching_dims` (Array of Integer): Batch dimensions of the input tensor.\\n      - `start_indices_batching_dims` (Array of Integer): Batch dimensions of the indices tensor.\\n      - `start_index_map` (Array of Integer): Maps index values to input dimensions.\\n      - `index_vector_dim` (Integer): Which dimension of indices contains the index vector.\\n      - `slice_sizes` (Array of Integer): Size of the slice to extract from each position.\\n      - `indices_are_sorted` (Boolean): Whether indices are sorted (for optimization).\\n\\n      Output:\\n      - `result` (Tensor): The gathered tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"start_indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"collapsed_slice_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"operand_batching_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"start_indices_batching_dims\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"start_index_map\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"SI64Attr\" },\n      { \"name\": \"slice_sizes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.ge\",\n    \"summary\": \"Elementwise greater than or equal to.\",\n    \"description\": \"The `ge` operation performs an elementwise greater than or equal to comparison between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if the left element is greater than or equal to the right element\\n      - 0 (false) if the left element is less than the right element\\n\\n      Example:\\n      ```mlir\\n      // Compare elements for greater than or equal to\\n      %result = ttir.ge(%lhs, %rhs) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1.0, 2.0, 3.0, 2.0], ... ]\\n      // %rhs: [[1.0, 2.0, 4.0, 5.0], ... ]\\n      // Output tensor:\\n      // [[1, 1, 0, 0], ... ]  // 1 where greater or equal, 0 where less\\n\\n      // Example with integer tensors\\n      %result = ttir.ge(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, -5, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [1, 0, 0]  // Only the first elements are greater or equal\\n      ```\\n\\n      Mathematical definition: greater_equal(x, y) = x >= y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.gelu\",\n    \"summary\": \"Elementwise GELU operation.\",\n    \"description\": \"The `gelu` operation computes the GELU (Gaussian Error Linear Unit) of each element in the input tensor.\\n\\n    For each element, it returns the GELU value, which is a smooth, non-monotonic function that approximates the\\n    cumulative distribution function of a standard normal distribution. The operation preserves the data type of the\\n    input.\\n\\n    Example:\\n    ```mlir\\n    // Compute GELU of all elements in %input\\n    %result = ttir.gelu(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n    // Input tensor:\\n    // [[1.7, 2.0, -0.3, 4.5], ... ]\\n    // Output tensor:\\n    // [[0.9601, 0.5403, -0.3, 4.5], ... ]\\n    ```\\n\\n    Mathematical definition: gelu(x) = 0.5 * x * (1 + erf(x / sqrt(2)))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.gelu_bw\",\n    \"summary\": \"Backward pass operation for the GELU activation function.\",\n    \"description\": \"The `gelu_bw` operation computes the gradient of the GELU (Gaussian Error Linear Unit)\\n    activation function with respect to its input during backpropagation. This is an elementwise\\n    binary operation that multiplies the incoming gradient with the derivative of GELU.\\n\\n    Inputs:\\n    - `lhs` (Tensor): The gradient tensor flowing back from the loss (grad_output).\\n    - `rhs` (Tensor): The original input tensor that was fed to the forward GELU operation.\\n\\n    Attributes:\\n    - `approximate` (string): The GELU approximation algorithm to use. Can be \\\"none\\\" (exact)\\n      or \\\"tanh\\\" (tanh approximation). Defaults to \\\"none\\\".\\n\\n    Output:\\n    - `result` (Tensor): The gradient with respect to the input tensor.\\n\\n    Example:\\n    ```mlir\\n    // Compute GELU backward pass\\n    %result = ttir.gelu_bw(%grad, %input) :\\n      (tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>\\n\\n    // With tanh approximation\\n    %result = ttir.gelu_bw(%grad, %input) {approximate = \\\"tanh\\\"} :\\n      (tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>\\n    ```\\n\\n    Mathematical definition (approximate = \\\"none\\\"):\\n      gelu_bw(grad, x) = grad * (cdf(x) + x * pdf(x))\\n    where cdf is the cumulative distribution function and pdf is the probability density\\n    function of the standard normal distribution.\\n\\n    Mathematical definition (approximate = \\\"tanh\\\"):\\n      gelu_bw(grad, x) = grad * d/dx[0.5 * x * (1 + tanh(sqrt(2/pi) * (x + 0.044715 * x^3)))]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"approximate\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"none\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.get_dimension_size\",\n    \"summary\": \"GetDimensionSize op.\",\n    \"description\": \"Produces the size of the given `dimension` of the `operand`.\\n\\n      Example:\\n        %operand: [[3, 2, 7], [1, 4, 4]]\\n        \\\"ttir.get_dimension_size\\\"(%operand, value = dense<0>, %out) -> %out: [[3]]\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.global_avg_pool2d\",\n    \"summary\": \"A global average pooling 2d operation\",\n    \"description\": \"The `global_avg_pool2d` operation applies global average pooling over the spatial dimensions\\n    (height and width) of a 4D input tensor. In essence, it should be realised as the sum-reduce style operation\\n    under the hood, for performance reasons (since we include all elements, there is no need for kernel allocation).\\n    It reduces spatial dimensions to 1.\\n\\n    This operation yields the same result as the standard avg_pool_2d operation when kernel_size == [input_height, input_width].\\n    However, it is much more memory efficient, as the underlying implementation doesn't need to allocate\\n    the kernel for pooling (since the operation boils down to a simple sum-reduce).\\n\\n    Example:\\n    ```mlir\\n    // Basic global average pooling reducing 32x32 spatial dimensions to 1x1\\n    %input = ... : tensor<1x32x32x64xbf16>  // Input tensor with values in NHWC format\\n                                            // N=1 (batch), H=32 (height), W=32 (width), C=64 (channels)\\n    %result = \\\"ttir.global_avg_pool2d\\\"(%input) : (tensor<1x32x32x64xbf16>) -> tensor<1x1x1x64xbf16>\\n    // Result: tensor<1x1x1x64xbf16> where each channel contains the average of all 32*32=1024 spatial locations\\n\\n    // Example with different input sizes\\n    %large_input = ... : tensor<1x128x128x32xbf16>  // Large spatial dimensions\\n    %large_result = \\\"ttir.global_avg_pool2d\\\"(%large_input) : (tensor<1x128x128x32xbf16>) -> tensor<1x1x1x32xbf16>\\n    // Each output channel averages across 128*128=16384 spatial locations\\n    ```\\n\\n    Inputs:\\n    - `input`: 4D tensor with shape [N, H, W, C] where N is batch size, H is height, W is width, and C is channels\\n    - `output`: Pre-allocated output tensor with shape [N, 1, 1, C] to store the result\\n\\n    Attributes:\\n    - None (this operation has no configurable attributes, unlike regular pooling operations)\\n\\n    Outputs:\\n    - `result`: 4D tensor with shape [N, 1, 1, C] containing the global average pooled values\\n\\n    Note: The operation reduces spatial dimensions (H, W) to (1, 1) by computing the average across\\n    all spatial locations for each channel independently. This is equivalent to avg_pool2d with\\n    kernel_size=[H, W], stride=[1, 1], and no padding, but implemented more efficiently.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.group_norm\",\n    \"summary\": \"Group normalization operation\",\n    \"description\": \"Computes group normalization over the input tensor. The input tensor's channels\\n    are split into groups, and mean and variance are computed per group. The result\\n    is normalized by subtracting the mean and dividing by the standard deviation,\\n    then optionally scaled and shifted by weight (gamma) and bias (beta).\\n\\n    Input tensor is expected to have shape [N, 1, H*W, C], where C is the dimension\\n    along which groups are formed. Groups are formed using the tensor's last dimension.\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to be normalized (4D, shape [N, 1, H*W, C]).\\n    - `input_mask` (Optional Tensor): When processing the inputs, the mask is used to\\n      only look at the elements of the current group. Defaults to None.\\n    - `weight` (Optional Tensor): The scale parameter (gamma). If provided, the\\n      normalized result is element-wise multiplied by this weight.\\n    - `bias` (Optional Tensor): The shift parameter (beta). If provided, this bias\\n      is added to the scaled result.\\n\\n    Attributes:\\n    - `num_groups` (int): Number of groups to split the tensor's channels into.\\n      C must divide evenly into num_groups.\\n    - `epsilon`: Small constant added for numerical stability (default: 1e-12).\\n    - `channel_dim` (int): The index of the channel dimension in the input\\n      tensor. Default is 3 (channels-last / NHWC). Set to 1 for NCHW layout.\\n      During TTIR-to-TTNN conversion, the input is permuted and reshaped to\\n      [N, 1, H*W, C] based on this attribute.\\n\\n    Output:\\n    - `result` (Tensor): The group normalized output tensor.\\n\\n    Example:\\n    ```mlir\\n      // Group norm with 8 groups, input shape [1, 1, 64, 480]\\n      %result = ttir.group_norm(%input, %input_mask, %weight, %bias) : <{ num_groups = 8, epsilon = 1e-12 }> :\\n            (tensor<1x1x64x480xf32>, tensor<1x8x32x32xf32>, tensor<1x1x15x32xf32>, tensor<1x1x15x32xf32>) -> tensor<1x1x64x480xf32>\\n    ```\\n\\n    Mathematical definition: group_norm(x, weight, bias, epsilon) =\\n      ((x - mu) / sqrt(sigma^2 + epsilon)) * weight + bias\\n    where mu and sigma^2 are the mean and variance computed per group.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input_mask\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-12>\" },\n      { \"name\": \"channel_dim\", \"type\": \"DefaultValuedAttr<I64Attr, 3>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.gt\",\n    \"summary\": \"Elementwise greater than.\",\n    \"description\": \"The `gt` operation performs an elementwise greater than comparison between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if the left element is greater than the right element\\n      - 0 (false) if the left element is less than or equal to the right element\\n\\n      Example:\\n      ```mlir\\n      // Compare elements for greater than\\n      %result = ttir.gt(%lhs, %rhs) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1.0, 2.0, 3.0, 2.0], ... ]\\n      // %rhs: [[1.0, 2.0, 4.0, 5.0], ... ]\\n      // Output tensor:\\n      // [[0, 0, 0, 1], ... ]  // 1 where greater, 0 where less or equal\\n\\n      // Example with integer tensors\\n      %result = ttir.gt(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, -5, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [0, 0, 0]  // Only the last element is greater\\n      ```\\n\\n      Mathematical definition: greater_than(x, y) = x > y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.hardsigmoid\",\n    \"summary\": \"Elementwise hard sigmoid operation.\",\n    \"description\": \"The `hardsigmoid` operation computes the hard sigmoid activation function of each element in the input tensor.\\n\\n    The hard sigmoid function is a piecewise linear approximation of the sigmoid function that is computationally\\n    more efficient. It is defined as:\\n    - 0 if x <= -3\\n    - (x + 3) / 6 if -3 < x < 3\\n    - 1 if x >= 3\\n\\n    This activation function is commonly used in neural networks as a computationally efficient alternative to\\n    the standard sigmoid function, particularly in mobile and embedded applications where computational resources\\n    are limited.\\n\\n    Example:\\n    ```mlir\\n    // Compute hard sigmoid of all elements in %input\\n    %result = ttir.hardsigmoid(%input, %output) : tensor<4x4xf32>, tensor<4x4xf32> -> tensor<4x4xf32>\\n    // Input tensor:\\n    // [-3.0, -1.0, 0.0, 3.0]\\n    // Output tensor:\\n    // [0.0, 0.333, 0.5, 1.0]\\n    ```\\n\\n    Mathematical definition: hardsigmoid(x) = max(0, min(1, (x + 3) / 6))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.index\",\n    \"summary\": \"Tensor indexing operation.\",\n    \"description\": \"The `index` operation extracts a sub-tensor (slice) from the input tensor along a specified dimension.\\n\\n      This operation selects elements from the input tensor along a single dimension based on the specified\\n      begin, end, and step indices. It's similar to Python's slicing notation `tensor[:, begin:end:step, :]`\\n      where the slicing is applied only to the specified dimension.\\n\\n      Example:\\n      ```mlir\\n      // Extract elements with indices 1, 3, 5 from dimension 0 of a 1D tensor\\n      %input = ... : tensor<6xf32>  // Input tensor with values: [1, 2, 3, 4, 5, 6]\\n      %result = ttir.index(%input) {\\n          dim = 0 : i32,    // Dimension to index\\n          begin = 1 : i32,  // Start index\\n          end = 6 : i32,    // End index (exclusive)\\n          step = 2 : i32    // Step size\\n      } : (tensor<6xf32>) -> tensor<3xf32>\\n      // Result: [2, 4, 6]\\n\\n      // Extract columns 0 and 2 from a 2D tensor\\n      %input = ... : tensor<3x4xf32>  // Input tensor with values:\\n                                      // [[1, 2, 3, 4],\\n                                      //  [5, 6, 7, 8],\\n                                      //  [9, 10, 11, 12]]\\n      %result = ttir.index(%input) {\\n          dim = 1 : i32,    // Index along columns (dimension 1)\\n          begin = 0 : i32,  // Start from first column\\n          end = 3 : i32,    // End at third column (exclusive)\\n          step = 2 : i32    // Take every other column\\n      } : (tensor<3x4xf32>) -> tensor<3x2xf32>\\n      // Result:\\n      // [[1, 3],\\n      //  [5, 7],\\n      //  [9, 11]]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to index.\\n\\n      Attributes:\\n      - `dim` (Integer): The dimension along which to index.\\n      - `begin` (Integer): The starting index.\\n      - `end` (Integer): The ending index (exclusive).\\n      - `step` (Integer): The step size between indices.\\n\\n      Output:\\n      - `result` (Tensor): The indexed tensor.\\n\\n      Note: The shape of the output tensor is the same as the input tensor except for the indexed dimension,\\n      which will have size `ceil((end - begin) / step)`. The indices selected will be `begin`, `begin + step`,\\n      `begin + 2*step`, etc., up to but not including `end`.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I32Attr\" },\n      { \"name\": \"begin\", \"type\": \"I32Attr\" },\n      { \"name\": \"end\", \"type\": \"I32Attr\" },\n      { \"name\": \"step\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.index_select\",\n    \"summary\": \"Tensor selection operation.\",\n    \"description\": \"The `index_select` operation extracts a sub-tensor (slice) from the input tensor along a specified dimension.\\n\\n      Unlike the more general `slice` operation, `index_select` operates on a single dimension with a specified\\n      starting index, length, and optional stride. This is useful for extracting specific segments of a tensor\\n      along a particular axis.\\n\\n      Example:\\n      ```mlir\\n      // Select elements 2, 3, 4 from a 1D tensor along dimension 0\\n      %input = ... : tensor<6xf32>  // Input tensor with values: [1, 2, 3, 4, 5, 6]\\n      %result = ttir.index_select(%input) {\\n          dim = 0 : i32,     // Dimension to select from\\n          begin = 2 : i32,   // Start index\\n          length = 3 : i32,  // Number of elements to select\\n          stride = 0 : i32   // No stride (consecutive elements)\\n      } : (tensor<6xf32>) -> tensor<3xf32>\\n      // Result: [3, 4, 5]\\n\\n      // Select every other row from a 2D tensor\\n      %input = ... : tensor<4x3xf32>  // Input tensor with values:\\n                                      // [[1, 2, 3],\\n                                      //  [4, 5, 6],\\n                                      //  [7, 8, 9],\\n                                      //  [10, 11, 12]]\\n      %result = ttir.index_select(%input) {\\n          dim = 0 : i32,     // Select along rows\\n          begin = 0 : i32,   // Start from the first row\\n          length = 2 : i32,  // Select 2 rows\\n          stride = 2 : i32   // Select every other row\\n      } : (tensor<4x3xf32>) -> tensor<2x3xf32>\\n      // Result:\\n      // [[1, 2, 3],\\n      //  [7, 8, 9]]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to select from.\\n\\n      Attributes:\\n      - `dim` (Integer): The dimension along which to select elements.\\n      - `begin` (Integer): The starting index for selection.\\n      - `length` (Integer): The number of elements to select.\\n      - `stride` (Integer, default=0): The step size for selection. A value of 0 means no stride (consecutive elements).\\n\\n      Output:\\n      - `result` (Tensor): The selected tensor.\\n\\n      Note: The shape of the output tensor is the same as the input tensor except for the selected dimension,\\n      which will have size `length`. If `stride` is non-zero, the elements selected will be at indices\\n      `begin`, `begin + stride`, `begin + 2*stride`, etc., up to `length` elements.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"begin\", \"type\": \"SI32Attr\" },\n      { \"name\": \"length\", \"type\": \"SI32Attr\" },\n      { \"name\": \"stride\", \"type\": \"DefaultValuedOptionalAttr<SI32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.isfinite\",\n    \"summary\": \"Elementwise isfinite operation.\",\n    \"description\": \"The `isfinite` operation checks if each element in the input tensor is finite (neither infinite nor NaN).\\n\\n      For each element, it returns a boolean value indicating whether the element is finite.\\n\\n      Example:\\n      ```mlir\\n      // Check if all elements in %input are finite\\n      %result = ttir.isfinite(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, Inf, 4.5], ... ]\\n      // Output tensor:\\n      // [[true, true, false, true], ... ]\\n      ```\\n\\n      Mathematical definition: isfinite(x) = x ∈ ℝ\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.layer_norm\",\n    \"summary\": \"Layer normalization operation\",\n    \"description\": \"Performs layer normalization on the input tensor. This operation normalizes\\n    the input tensor by computing the mean and variance of elements across\\n    the specified dimensions, then normalizes by subtracting the mean and\\n    dividing by the standard deviation, optionally scaling and shifting the result.\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to be normalized.\\n    - `weight` (Optional Tensor): The scale parameter (gamma). If provided, the normalized\\n      result is element-wise multiplied by this weight.\\n    - `bias` (Optional Tensor): The shift parameter (beta). If provided, this bias is\\n      added to the scaled result.\\n\\n    Attributes:\\n    - `normalized_shape` specifies the dimensions over which to normalize. Typically\\n      the last few dimensions of the input tensor.\\n    - `epsilon` is a small constant added for numerical stability (default: 1e-05).\\n\\n    Output:\\n    - `result` (Tensor): The layer normalized output tensor.\\n\\n    Example:\\n    ```mlir\\n      // Layer normalization over last dimension (shape: [2, 4, 8] -> normalize over [8])\\n      %result = ttir.layer_norm(%input, %weight, %bias) : <{ normalized_shape = [8], epsilon = 1e-05 }> :\\n            (tensor<2x4x8xf32>, tensor<2x4x8xf32>, tensor<8xf32>) -> tensor<2x4x8xf32>\\n\\n      // Layer normalization over last two dimensions (shape: [2, 4, 8] -> normalize over [4, 8])\\n      %result = ttir.layer_norm(%input, %weight, %bias) : <{ normalized_shape = [4, 8], epsilon = 1e-05 }> :\\n            (tensor<2x4x8xf32>, tensor<2x4x8xf32>, tensor<4x8xf32>) -> tensor<2x4x8xf32>\\n    ```\\n\\n    Mathematical definition: layer_norm(x, weight, bias, epsilon) =\\n      ((x - mean(x, dims=normalized_dims)) / sqrt(var(x, dims=normalized_dims) + epsilon)) * weight + bias\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.le\",\n    \"summary\": \"Elementwise less than or equal to.\",\n    \"description\": \"The `le` operation performs an elementwise less than or equal to comparison between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if the left element is less than or equal to the right element\\n      - 0 (false) if the left element is greater than the right element\\n\\n      Example:\\n      ```mlir\\n      // Compare elements for less than or equal to\\n      %result = ttir.le(%lhs, %rhs) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1.0, 2.0, 3.0, 2.0], ... ]\\n      // %rhs: [[1.0, 2.0, 4.0, 5.0], ... ]\\n      // Output tensor:\\n      // [[1, 1, 1, 0], ... ]  // 1 where less or equal, 0 where greater\\n\\n      // Example with integer tensors\\n      %result = ttir.le(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, -5, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [1, 1, 1]  // All elements are less or equal\\n      ```\\n\\n      Mathematical definition: less_equal(x, y) = x <= y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.leaky_relu\",\n    \"summary\": \"Eltwise leaky relu operation.\",\n    \"description\": \"The Leaky ReLU (Rectified Linear Unit) operation computes an element-wise\\n      activation function over its input tensor. It is defined as:\\n\\n      y = x if x > 0\\n      y = parameter * x if x <= 0\\n\\n      where `parameter` is a small, user-defined constant that determines the slope for\\n      negative inputs.\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to be activated.\\n\\n      Output:\\n      - `result` (Tensor): The tensor after applying the Leaky ReLU activation.\\n\\n      Attributes:\\n      - `parameter` (float): The slope for negative values.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parameter\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.linear\",\n    \"summary\": \"Linear transformation operation.\",\n    \"description\": \"The `linear` operation performs a linear transformation by computing the matrix multiplication\\n      of tensors `a` and `b` with an optional addition of a `bias` tensor.\\n\\n      This operation is commonly used in neural networks to implement fully connected layers. It computes\\n      the matrix multiplication of the input tensor with a weight tensor and adds an optional bias.\\n\\n      Example:\\n      ```mlir\\n      // Linear transformation with bias\\n      %a = ... : tensor<10x64x32xbf16>  // Input tensor: batch_size=10, sequence_length=64, input_dim=32\\n      %b = ... : tensor<32x128xbf16>    // Weight tensor: input_dim=32, output_dim=128\\n      %bias = ... : tensor<128xbf16>    // Bias tensor: output_dim=128\\n      %result = ttir.linear(%a, %b, %bias) :\\n          (tensor<10x64x32xbf16>, tensor<32x128xbf16>, tensor<128xbf16>) -> tensor<10x64x128xbf16>\\n\\n      // Linear transformation without bias\\n      %a = ... : tensor<10x64x32xf32>  // Input tensor\\n      %b = ... : tensor<32x128xf32>    // Weight tensor\\n      %result = ttir.linear(%a, %b) :\\n          (tensor<10x64x32xf32>, tensor<32x128xf32>) -> tensor<10x64x128xf32>\\n      ```\\n\\n      Inputs:\\n      - `a` (Tensor): The input tensor.\\n      - `b` (Tensor): The weight tensor.\\n      - `bias` (Optional Tensor): The bias tensor to add to the result of the matrix multiplication.\\n\\n      Attributes:\\n      - `transpose_a` (Boolean, default=false): Whether to transpose tensor `a` before multiplication.\\n      - `transpose_b` (Boolean, default=false): Whether to transpose tensor `b` before multiplication.\\n\\n      Output:\\n      - `result` (Tensor): The result of the linear transformation.\\n\\n      The operation computes: result = matmul(a, b) + bias\\n\\n      Note: The shapes of the tensors must be compatible for matrix multiplication. For a 3D input tensor\\n      with shape [batch_size, sequence_length, input_dim], the weight tensor should have shape [input_dim, output_dim],\\n      and the bias tensor should have shape [output_dim]. The resulting tensor will have shape\\n      [batch_size, sequence_length, output_dim].\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"b\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.log\",\n    \"summary\": \"Elementwise natural logarithm operation.\",\n    \"description\": \"The `log` operation computes the natural logarithm of each element in the input tensor.\\n\\n      For each element, it returns the natural logarithm (base e) of the value. This operation\\n      is defined only for positive values; the behavior for zero or negative inputs\\n      depends on the implementation (may return NaN, infinity, or other special values).\\n\\n      Example:\\n      ```mlir\\n      // Compute natural logarithm of all elements in %input\\n      %result = ttir.log(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.0, 2.718, 7.389, 20.086], ... ]\\n      // Output tensor:\\n      // [[0.0, 1.0, 2.0, 3.0], ... ]\\n\\n      // Example with different values\\n      %result = ttir.log(%float_input) : (tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensor:\\n      // [10.0, 100.0, 1000.0]\\n      // Output tensor:\\n      // [2.303, 4.605, 6.908]  // ln(10), ln(100), ln(1000)\\n      ```\\n\\n      Mathematical definition: log(x) = ln(x), where ln is the natural logarithm\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.log1p\",\n    \"summary\": \"Elementwise natural logarithm of one plus input operation.\",\n    \"description\": \"The `log1p` operation computes the natural logarithm of one plus each element in the input tensor.\\n\\n      For each element x, it returns ln(1 + x). This operation is more accurate than computing\\n      log(1 + x) directly for x values close to zero, and it is defined for x > -1. For values\\n      less than or equal to -1, the behavior depends on the implementation (may return NaN or\\n      negative infinity).\\n\\n      Example:\\n      ```mlir\\n      // Compute log1p of all elements in %input\\n      %result = ttir.log1p(%input) : (tensor<5xf32>) -> tensor<5xf32>\\n      // Input tensor:\\n      // [0.0, -0.999, 7.0, 6.38905621, 15.0]\\n      // Output tensor:\\n      // [0.0, -6.90776825, 2.07944155, 2.0, 2.77258873]\\n\\n      // Example with small values where log1p is more accurate than log(1+x)\\n      %result = ttir.log1p(%small_input) : (tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensor:\\n      // [1e-10, 1e-7, 1e-5]\\n      // Output tensor:\\n      // [1e-10, 1e-7, 1e-5]  // Approximately equal to the input for very small values\\n      ```\\n\\n      Mathematical definition: log1p(x) = ln(1 + x)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.logical_and\",\n    \"summary\": \"Elementwise logical and.\",\n    \"description\": \"The `logical_and` operation performs an elementwise logical AND operation between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if both elements are 1 (true)\\n      - 0 (false) if at least one element is 0 (false)\\n\\n      Example:\\n      ```mlir\\n      // Logical AND operation\\n      %result = ttir.logical_and(%lhs, %rhs) : (tensor<4x4xi1>, tensor<4x4xi1>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1, 0, 1, 0], ... ]\\n      // %rhs: [[1, 1, 0, 1], ... ]\\n      // Output tensor:\\n      // [[1, 0, 0, 0], ... ]  // 1 where both are 1, 0 otherwise\\n\\n      // Example with integer tensors\\n      %result = ttir.logical_and(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, 0, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [1, 0, 0]  // Only the first element is true\\n      ```\\n\\n      Mathematical definition: logical_and(x, y) = x && y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.logical_left_shift\",\n    \"summary\": \"Eltwise Logical Left Shift operation\",\n    \"description\": \"The `logical_left_shift` operation performs an elementwise logical left shift\\n      on the elements of the first tensor by the corresponding shift amounts in the\\n      second tensor.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.logical_not\",\n    \"summary\": \"Elementwise logical not operation.\",\n    \"description\": \"The `logical_not` operation computes the logical negation of each element in the input tensor.\\n\\n      For each element, it returns a boolean value indicating whether the element is false (zero) or true (non-zero).\\n\\n      Example:\\n      ```mlir\\n      // Compute logical negation of all elements in %input\\n      %result = ttir.logical_not(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.0, 4.5], ... ]\\n      // Output tensor:\\n      // [[false, false, true, false], ... ]\\n      ```\\n\\n      Mathematical definition: logical_not(x) = !x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.logical_or\",\n    \"summary\": \"Elementwise logical or.\",\n    \"description\": \"The `logical_or` operation performs an elementwise logical OR operation between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if at least one element is 1 (true)\\n      - 0 (false) if both elements are 0 (false)\\n\\n      Example:\\n      ```mlir\\n      // Logical OR operation\\n      %result = ttir.logical_or(%lhs, %rhs) : (tensor<4x4xi1>, tensor<4x4xi1>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1, 0, 1, 0], ... ]\\n      // %rhs: [[1, 1, 0, 1], ... ]\\n      // Output tensor:\\n      // [[1, 1, 1, 1], ... ]  // 1 where at least one is 1, 0 otherwise\\n\\n      // Example with integer tensors\\n      %result = ttir.logical_or(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, 0, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [1, 1, 1]  // All elements are true\\n      ```\\n\\n      Mathematical definition: logical_or(x, y) = x || y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.logical_right_shift\",\n    \"summary\": \"Eltwise Logical Right Shift operation\",\n    \"description\": \"The `logical_right_shift` operation performs an elementwise logical right shift\\n      on the elements of the first tensor by the corresponding shift amounts in the\\n      second tensor.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.logical_xor\",\n    \"summary\": \"Elementwise logical xor.\",\n    \"description\": \"The `logical_xor` operation performs an elementwise logical XOR operation between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if exactly one element is 1 (true)\\n      - 0 (false) if both elements are 0 (false) or both are 1 (true)\\n\\n      Example:\\n      ```mlir\\n      // Logical XOR operation\\n      %result = ttir.logical_xor(%lhs, %rhs) : (tensor<4x4xi1>, tensor<4x4xi1>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1, 0, 1, 0], ... ]\\n      // %rhs: [[1, 1, 0, 1], ... ]\\n      // Output tensor:\\n      // [[0, 1, 1, 1], ... ]  // 1 where exactly one is 1, 0 otherwise\\n\\n      // Example with integer tensors\\n      %result = ttir.logical_xor(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, 0, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [0, 1, 1]  // Only the last element is true\\n      ```\\n\\n      Mathematical definition: logical_xor(x, y) = x ^^ y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.lt\",\n    \"summary\": \"Elementwise less than.\",\n    \"description\": \"The `lt` operation performs an elementwise less than comparison between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if the left element is less than the right element\\n      - 0 (false) if the left element is greater than or equal to the right element\\n\\n      Example:\\n      ```mlir\\n      // Compare elements for less than\\n      %result = ttir.lt(%lhs, %rhs) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1.0, 2.0, 3.0, 2.0], ... ]\\n      // %rhs: [[1.0, 2.0, 4.0, 5.0], ... ]\\n      // Output tensor:\\n      // [[0, 0, 0, 1], ... ]  // 1 where less, 0 where greater or equal\\n\\n      // Example with integer tensors\\n      %result = ttir.lt(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, -5, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [0, 0, 0]  // Only the last element is less\\n      ```\\n\\n      Mathematical definition: less_than(x, y) = x < y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.matmul\",\n    \"summary\": \"Matrix multiplication operation.\",\n    \"description\": \"The `matmul` operation computes the matrix multiplication of two tensors.\\n\\n      This operation performs matrix multiplication between tensors `a` and `b`. It supports optional\\n      transposition of either input tensor before multiplication. For 2D tensors, this computes the standard\\n      matrix product. For tensors with more dimensions, it applies batched matrix multiplication.\\n\\n      Example:\\n      ```mlir\\n      // Basic matrix multiplication of 2D tensors\\n      %a = ... : tensor<3x4xf32>  // Matrix A with shape [3,4]\\n      %b = ... : tensor<4x5xf32>  // Matrix B with shape [4,5]\\n      %result = ttir.matmul(%a, %b) :\\n          (tensor<3x4xf32>, tensor<4x5xf32>) -> tensor<3x5xf32>\\n\\n      // Batched matrix multiplication with transposition\\n      %a = ... : tensor<2x3x4xf32>  // Batch of 2 matrices with shape [3,4]\\n      %b = ... : tensor<2x5x4xf32>  // Batch of 2 matrices with shape [5,4]\\n      %result = ttir.matmul(%a, %b) {\\n          transpose_a = false,  // Don't transpose A\\n          transpose_b = true    // Transpose B before multiplication\\n      } : (tensor<2x3x4xf32>, tensor<2x5x4xf32>) -> tensor<2x3x5xf32>\\n      ```\\n\\n      Inputs:\\n      - `a` (Tensor): The first input tensor.\\n      - `b` (Tensor): The second input tensor.\\n\\n      Attributes:\\n      - `transpose_a` (Boolean, default=false): Whether to transpose tensor `a` before multiplication.\\n      - `transpose_b` (Boolean, default=false): Whether to transpose tensor `b` before multiplication.\\n\\n      Output:\\n      - `result` (Tensor): The result of the matrix multiplication.\\n\\n      Note: The inner dimensions of the input tensors must be compatible for matrix multiplication.\\n      If `a` has shape [..., m, k] and `b` has shape [..., k, n], then the result will have shape [..., m, n].\\n      If `transpose_a` is true, then `a` is treated as having shape [..., k, m].\\n      If `transpose_b` is true, then `b` is treated as having shape [..., n, k].\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"b\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.max\",\n    \"summary\": \"Maximum reduction operation.\",\n    \"description\": \"The `max` operation computes the maximum value of elements along specified dimensions of the input tensor.\\n\\n    This operation reduces the input tensor by finding the maximum value of all elements along the dimensions\\n    specified in `dim_arg`. If `dim_arg` is not provided, the maximum is computed over all dimensions,\\n    resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n    with a size of 1.\\n\\n    Example:\\n    ```mlir\\n    // Maximum along dimension 1\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.max(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<2x3xf32>) -> tensor<2xf32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [4.0, 2.0, 6.0]]\\n    // Output tensor:\\n    // [5.0, 6.0]  // Maximum of each row\\n\\n    // Maximum along dimension 0\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.max(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<2x3xf32>) -> tensor<3xf32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [4.0, 2.0, 6.0]]\\n    // Output tensor:\\n    // [4.0, 5.0, 6.0]  // Maximum of each column\\n\\n    // Maximum over all dimensions\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.max(%input) {keep_dim = false} : (tensor<2x3xf32>) -> tensor<f32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [4.0, 2.0, 6.0]]\\n    // Output tensor:\\n    // 6.0  // Maximum of all elements\\n    ```\\n\\n    Note: When comparing with NaN values, NaN is typically not selected as the maximum value.\\n\\n    Mathematical definition: max(x, dim) = max(x[i]) for all i in dimension dim\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor.\\n\\n    Attributes:\\n    - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n    - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n    Output:\\n    - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.max_pool2d\",\n    \"summary\": \"2D maximum pooling operation.\",\n    \"description\": \"The `max_pool2d` operation applies a 2D maximum pooling over an input tensor composed of several input planes.\\n\\n    This operation performs downsampling by dividing the input into local regions and computing the maximum value\\n    of each region. It reduces the spatial dimensions (height and width) of an input tensor while preserving the\\n    batch and channel dimensions. This is commonly used in neural networks to reduce the spatial size of feature\\n    maps while retaining the most important features.\\n\\n    Example:\\n    ```mlir\\n    // Basic 2D max pooling with a 2x2 kernel and stride 1\\n    %input = ... : tensor<1x3x3x1xf32>  // 3x3 input tensor with values:\\n                                        // [[[1, 2, 3],\\n                                        //   [4, 5, 6],\\n                                        //   [7, 8, 9]]]\\n    %result = ttir.max_pool2d(%input) {\\n        kernel = [2, 2],\\n        stride = [1, 1],\\n        dilation = [1, 1],\\n        padding = [0, 0, 0, 0],\\n        ceil_mode = false\\n    } : (tensor<1x3x3x1xf32>) -> tensor<1x2x2x1xf32>\\n    // Result: [[[5, 6],\\n    //           [8, 9]]]\\n    // Where: 5 = max(1,2,4,5), 6 = max(2,3,5,6), 8 = max(4,5,7,8), 9 = max(5,6,8,9)\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): Input tensor in NHWC format (batch, height, width, channels).\\n\\n    Attributes:\\n    - `kernel` (i32 | array<2xi32>):\\n        - i32: Same kernel size for height and width dimensions (kH = kW = value).\\n        - array<2xi32>: [kH, kW] where kH is kernel size for height and kW is kernel size for width.\\n    - `stride` (i32 | array<2xi32>):\\n        - i32: Same stride for height and width dimensions (sH = sW = value).\\n        - array<2xi32>: [sH, sW] where sH is stride for height and sW is stride for width.\\n    - `dilation` (i32 | array<2xi32>):\\n        - i32: Same dilation for height and width dimensions (dH = dW = value).\\n        - array<2xi32>: [dH, dW] where dH is dilation for height and dW is dilation for width.\\n    - `padding` (i32 | array<2xi32> | array<4xi32>):\\n        - i32: Same padding for all sides (pT = pL = pB = pR = value).\\n        - array<2xi32>: [pH, pW] where pH is padding for height (top/bottom) and pW is padding for width (left/right).\\n        - array<4xi32>: [pT, pL, pB, pR] for top, left, bottom, and right padding respectively.\\n    - `ceil_mode` (Boolean): When true, uses ceil instead of floor for output shape calculation.\\n\\n    Output:\\n    - `result` (Tensor): Output tensor after maximum pooling.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"stride\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"dilation\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"flattened_compat_info\", \"type\": \"DefaultValuedAttr<TTIR_FlattenedCompatInfoAttr, nullptr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.max_pool2d_with_indices\",\n    \"summary\": \"2D maximum pooling operation with indices.\",\n    \"description\": \"The `max_pool2d_with_indices` operation applies a 2D maximum pooling over an input tensor composed of several input planes\\n      and also returns the indices of the maximum values within each pooling window.\\n\\n    This operation performs downsampling by dividing the input into local regions and computing the maximum value\\n    of each region, along with the index (location) of that maximum value within the original input tensor. It reduces the\\n    spatial dimensions (height and width) of an input tensor while preserving the batch and channel dimensions.\\n    This is commonly used in neural networks to reduce the spatial size of feature maps while retaining the most\\n    important features, and the indices can be used for unpooling operations or gradient computation.\\n\\n    Example:\\n    ```mlir\\n    // Basic 2D max pooling with indices using a 2x2 kernel and stride 1\\n    %input = ... : tensor<1x3x3x1xf32>  // 3x3 input tensor with values:\\n                                        // [[[1, 2, 3],\\n                                        //   [4, 5, 6],\\n                                        //   [7, 8, 9]]]]\\n    %output = ttir.empty() : tensor<1x2x2x1xf32>\\n    %indices_output = ttir.empty() : tensor<1x2x2x1xi32>\\n    %result, %indices = ttir.max_pool2d_with_indices(%input, %output, %indices_output) {\\n        kernel = [2, 2],\\n        stride = [1, 1],\\n        dilation = [1, 1],\\n        padding = [0, 0, 0, 0],\\n        ceil_mode = false\\n    } : tensor<1x3x3x1xf32>, tensor<1x2x2x1xf32>, tensor<1x2x2x1xi32> -> tensor<1x2x2x1xf32>, tensor<1x2x2x1xi32>\\n    // Result values: [[[5, 6],\\n    //                  [8, 9]]]]\\n    // Result indices: [[[4, 5],    // 5 is at index 4, 6 is at index 5\\n    //                   [7, 8]]]]   // 8 is at index 7, 9 is at index 8\\n    // Where: 5 = max(1,2,4,5), 6 = max(2,3,5,6), 8 = max(4,5,7,8), 9 = max(5,6,8,9)\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): Input tensor in NHWC format (batch, height, width, channels).\\n    - `output` (Tensor): Output tensor for the pooled values.\\n    - `indices_output` (Tensor): Output tensor for the indices of maximum values.\\n\\n    Attributes:\\n    - `kernel` (i32 | array<2xi32>):\\n        - i32: Same kernel size for height and width dimensions (kH = kW = value).\\n        - array<2xi32>: [kH, kW] where kH is kernel size for height and kW is kernel size for width.\\n    - `stride` (i32 | array<2xi32>):\\n        - i32: Same stride for height and width dimensions (sH = sW = value).\\n        - array<2xi32>: [sH, sW] where sH is stride for height and sW is stride for width.\\n    - `dilation` (i32 | array<2xi32>):\\n        - i32: Same dilation for height and width dimensions (dH = dW = value).\\n        - array<2xi32>: [dH, dW] where dH is dilation for height and dW is dilation for width.\\n    - `padding` (i32 | array<2xi32> | array<4xi32>):\\n        - i32: Same padding for all sides (pT = pL = pB = pR = value).\\n        - array<2xi32>: [pH, pW] where pH is padding for height (top/bottom) and pW is padding for width (left/right).\\n        - array<4xi32>: [pT, pL, pB, pR] for top, left, bottom, and right padding respectively.\\n    - `ceil_mode` (Boolean): When true, uses ceil instead of floor for output shape calculation.\\n\\n    Outputs:\\n    - `result` (Tensor): Output tensor after maximum pooling.\\n    - `indices` (Tensor): Output tensor containing the indices of the maximum values in the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"output\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result_indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kernel\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"stride\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"dilation\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"padding\", \"type\": \"AnyAttrOf<[I32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"flattened_compat_info\", \"type\": \"DefaultValuedAttr<TTIR_FlattenedCompatInfoAttr, nullptr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.maximum\",\n    \"summary\": \"Elementwise maximum operation.\",\n    \"description\": \"The `maximum` operation calculates the elementwise maximum between two tensors.\\n\\n      For each pair of corresponding elements, it selects the larger value and places it in the\\n      output tensor. This operation has the idempotence property, meaning that applying it twice\\n      with the same second operand returns the original result: maximum(maximum(x, y), y) = maximum(x, y).\\n\\n      Example:\\n      ```mlir\\n      // Maximum operation\\n      %result = ttir.maximum(%lhs, %rhs) : (tensor<3x3xi32>, tensor<3x3xi32>) -> tensor<3x3xi32>\\n      // Input tensors:\\n      // %lhs: [[3, 2, 7], [1, 4, 4]]\\n      // %rhs: [[1, 4, 2], [1, 2, 3]]\\n      // Output tensor:\\n      // [[3, 4, 7], [1, 4, 4]]\\n      ```\\n\\n      Note: When comparing with NaN values, NaN is typically not selected as the maximum value.\\n\\n      Mathematical definition: maximum(x, y) = max(x, y)\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.mean\",\n    \"summary\": \"Mean reduction op.\",\n    \"description\": \"The `mean` operation computes the arithmetic mean of elements along specified dimensions of the input tensor.\\n\\n    This operation reduces the input tensor by computing the average of all elements along the dimensions\\n    specified in `dim_arg`. If `dim_arg` is not provided, the mean is computed over all dimensions,\\n    resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n    with a size of 1.\\n\\n    Example:\\n    ```mlir\\n    // Mean along dimension 1\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.mean(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<2x3xf32>) -> tensor<2xf32>\\n    // Input tensor:\\n    // [[1.0, 2.0, 3.0],\\n    //  [4.0, 5.0, 6.0]]\\n    // Output tensor:\\n    // [2.0, 5.0]  // Mean of each row\\n\\n    // Mean along dimension 0\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.mean(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<2x3xf32>) -> tensor<3xf32>\\n    // Input tensor:\\n    // [[1.0, 2.0, 3.0],\\n    //  [4.0, 5.0, 6.0]]\\n    // Output tensor:\\n    // [2.5, 3.5, 4.5]  // Mean of each column\\n\\n    // Mean over all dimensions\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.mean(%input) {keep_dim = false} : (tensor<2x3xf32>) -> tensor<f32>\\n    // Input tensor:\\n    // [[1.0, 2.0, 3.0],\\n    //  [4.0, 5.0, 6.0]]\\n    // Output tensor:\\n    // 3.5  // Mean of all elements\\n    ```\\n\\n    Note: For integer input tensors, the result is typically rounded to the nearest integer according to the rounding mode.\\n\\n    Mathematical definition: mean(x, dim) = (∑ x[i]) / n for all i in dimension dim, where n is the number of elements in dimension dim\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor.\\n\\n    Attributes:\\n    - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n    - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n    Output:\\n    - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.mesh_partition\",\n    \"summary\": \"Mesh partition operation.\",\n    \"description\": \"Mesh partition op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"OptionalAttr<UI32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.mesh_shard\",\n    \"summary\": \"Mesh shard operation.\",\n    \"description\": \"MeshShard op shards the inputs (FullToShard) or concatnates the outputs (ShardToFull) for ccl ops.\\n\\n      shard_direction attribute determines whether to shard or concat.\\n\\n      shard_type attribute determines how to shard or concat.\\n        manual: no sharding\\n        replicate: all devices have identical data\\n        maximal: only one device contains full data\\n        devices: shard_shape/shard_dims determine particular sharding\\n\\n      shard_dims attribute determines row and column sharding dimension of input tensor\\n\\n      For example, on 2x4 mesh hardware, following op shards arg0 to 8 slices, row divided by 2\\n      and col divided by 4.\\n\\n        %1 = \\\"ttir.mesh_shard\\\"(%arg0) <\\n          {... shard_direction = #ttcore.shard_direction<full_to_shard>,\\n               shard_shape = array<i64: 2, 4>,\\n               shard_dims = array<i64: 0, 1>,\\n               shard_type = #ttcore.shard_type<devices>}> :  (tensor<8192x784xf32>, ...) -> tensor<4096x196xf32>\\n\\n      On the other hand, this op concatnates %4 to single tensor by concatnating\\n      one of the top row tensor with one of the bottom row tensor.\\n\\n        %6 = \\\"ttir.mesh_shard\\\"(%4) <\\n          {..., shard_direction = #ttcore.shard_direction<shard_to_full>,\\n                shard_shape = array<i64: 2, 1>,\\n                shard_dims = array<i64: 1, -1>,\\n                shard_type = #ttcore.shard_type<devices>}> : (tensor<4096x16384xf32>, ...) -> tensor<8192x16384xf32>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shard_type\", \"type\": \"TTCore_MeshShardTypeAttr{identity|replicate|maximal|devices}\" },\n      { \"name\": \"shard_direction\", \"type\": \"TTCore_MeshShardDirectionAttr{full_to_shard|shard_to_full}\" },\n      { \"name\": \"shard_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"shard_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.min\",\n    \"summary\": \"Minimum reduction operation.\",\n    \"description\": \"The `min` operation computes the minimum value of elements along specified dimensions of the input tensor.\\n\\n    This operation reduces the input tensor by finding the minimum value of all elements along the dimensions\\n    specified in `dim_arg`. If `dim_arg` is not provided, the minimum is computed over all dimensions,\\n    resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n    with a size of 1.\\n\\n    Example:\\n    ```mlir\\n    // Minimum along dimension 1\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.min(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<2x3xf32>) -> tensor<2xf32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [4.0, 2.0, 6.0]]\\n    // Output tensor:\\n    // [1.0, 2.0]  // Minimum of each row\\n\\n    // Minimum along dimension 0\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.min(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<2x3xf32>) -> tensor<3xf32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [4.0, 2.0, 6.0]]\\n    // Output tensor:\\n    // [1.0, 2.0, 3.0]  // Minimum of each column\\n\\n    // Minimum over all dimensions\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.min(%input) {keep_dim = false} : (tensor<2x3xf32>) -> tensor<f32>\\n    // Input tensor:\\n    // [[1.0, 5.0, 3.0],\\n    //  [4.0, 2.0, 6.0]]\\n    // Output tensor:\\n    // 1.0  // Minimum of all elements\\n    ```\\n\\n    Note: When comparing with NaN values, NaN is typically not selected as the minimum value.\\n\\n    Mathematical definition: min(x, dim) = min(x[i]) for all i in dimension dim\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor.\\n\\n    Attributes:\\n    - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n    - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n    Output:\\n    - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.minimum\",\n    \"summary\": \"Elementwise minimum operation.\",\n    \"description\": \"The `minimum` operation computes the elementwise minimum between two tensors.\\n\\n      For each pair of corresponding elements, it selects the smaller value and places it in the\\n      output tensor. This operation has the idempotence property, meaning that applying it twice\\n      with the same second operand returns the original result: minimum(minimum(x, y), y) = minimum(x, y).\\n\\n      Example:\\n      ```mlir\\n      // Minimum operation\\n      %result = ttir.minimum(%lhs, %rhs) : (tensor<2x3xi32>, tensor<2x3xi32>) -> tensor<2x3xi32>\\n      // Input tensors:\\n      // %lhs: [[3, 2, 7], [1, 4, 4]]\\n      // %rhs: [[1, 4, 2], [1, 2, 3]]\\n      // Output tensor:\\n      // [[1, 2, 2], [1, 2, 3]]\\n\\n      // Example with floating point values\\n      %result = ttir.minimum(%float_lhs, %float_rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %float_lhs: [3.5, -2.1, 0.0]\\n      // %float_rhs: [1.2, -5.0, 0.0]\\n      // Output tensor:\\n      // [1.2, -5.0, 0.0]\\n      ```\\n\\n      Note: When comparing with NaN values, NaN is typically not selected as the minimum value.\\n\\n      Mathematical definition: minimum(x, y) = min(x, y)\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.mish\",\n    \"summary\": \"Elementwise Mish activation operation.\",\n    \"description\": \"The `mish` operation computes the Mish activation function of each element in the input tensor.\\n\\n    Mish is a smooth, self-regularized, non-monotonic activation function that combines\\n    properties of both ReLU-like and smooth activation functions. It has been shown to improve\\n    performance in deep learning applications, particularly in computer vision tasks.\\n\\n    Example:\\n    ```mlir\\n    // Compute Mish of all elements in %input\\n    %result = ttir.mish(%input, %output) : tensor<4x4xf32>, tensor<4x4xf32> -> tensor<4x4xf32>\\n    // Input tensor:\\n    // [[-2.0, -1.0, 0.0, 1.0], ... ]\\n    // Output tensor:\\n    // [[-0.252, -0.303, 0.0, 0.865], ... ]\\n    ```\\n\\n    Mathematical definition: mish(x) = x * tanh(softplus(x)) = x * tanh(ln(1 + e^x))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.moe_expert_token_remap\",\n    \"summary\": \"Remap global expert routing to local device experts with sparsity.\",\n    \"description\": \"Converts global expert routing scores to local per-device expert mapping\\n      and creates a sparsity pattern for efficient sparse_matmul. Used after\\n      all_to_all_dispatch in the MoE dispatch/compute/combine flow.\\n\\n      Input shapes:\\n      - topk_tensor: [D, B, S, E] (bf16 routing scores)\\n      - expert_mapping: [1, 1, E, D] (uint16 one-hot mapping)\\n      - expert_metadata: [D, B, S, K] (uint16 expert indices)\\n\\n      Output shapes:\\n      - mapping: [1, B, S, E_local] (bf16 local routing weights)\\n      - reduced: [1, 1, ceil(B*S/reduction_size), E_local] (uint16 sparsity)\",\n    \"operands\": [\n      { \"name\": \"topk_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_mapping\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_metadata\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"mapping\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"reduced\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_size\", \"type\": \"I64Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.multiply\",\n    \"summary\": \"Elementwise multiplication operation.\",\n    \"description\": \"The `multiply` operation performs an elementwise multiplication between two tensors.\\n\\n      For each pair of corresponding elements, it multiplies the elements and places the result in the output tensor.\\n\\n      Example:\\n      ```mlir\\n      // Multiplication operation\\n      %result = ttir.multiply(%lhs, %rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>\\n      // Input tensors:\\n      // %lhs: [10, 20, 30]\\n      // %rhs: [1, 2, 3]\\n      // Output tensor:\\n      // [10, 40, 90]\\n\\n      // Example with floating point values\\n      %result = ttir.multiply(%float_lhs, %float_rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %float_lhs: [3.5, 0.0, -1.2]\\n      // %float_rhs: [1.5, 2.0, -3.2]\\n      // Output tensor:\\n      // [5.25, 0.0, -3.84]\\n      ```\\n\\n      Note: The data type of the output tensor matches the data type of the input tensors.\\n\\n      Mathematical definition: multiply(x, y) = x * y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.ne\",\n    \"summary\": \"Elementwise inequality comparison operation.\",\n    \"description\": \"The `ne` operation performs an elementwise inequality comparison between two tensors.\\n\\n      For each pair of corresponding elements, it returns:\\n      - 1 (true) if the elements are not equal\\n      - 0 (false) if the elements are equal\\n\\n      Note that special handling may be required for floating-point NaN values, as NaN is not\\n      equal to any value, including itself. This means ne(NaN, NaN) should return true.\\n\\n      Example:\\n      ```mlir\\n      // Compare elements for inequality\\n      %result = ttir.ne(%lhs, %rhs) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xi1>\\n      // Input tensors:\\n      // %lhs: [[1.0, 2.0, 3.0, 2.0], ... ]\\n      // %rhs: [[1.0, 2.0, 4.0, 5.0], ... ]\\n      // Output tensor:\\n      // [[0, 0, 1, 1], ... ]  // 0 where equal, 1 where not equal\\n\\n      // Example with integer tensors\\n      %result = ttir.ne(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>\\n      // Input tensors:\\n      // %int_lhs: [10, -5, 0]\\n      // %int_rhs: [10, 5, 1]\\n      // Output tensor:\\n      // [0, 1, 1]  // Only the first elements are equal, so their result is 0\\n      ```\\n\\n      Mathematical definition: not_equal(x, y) = x != y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.neg\",\n    \"summary\": \"Elementwise negate operation.\",\n    \"description\": \"The `neg` operation negates each element in the input tensor.\\n\\n      For each element, it returns the negation of the value. The operation preserves\\n      the data type of the input.\\n\\n      Example:\\n      ```mlir\\n      // Compute negation of all elements in %input\\n      %result = ttir.neg(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[-1.7, -2.0, 0.3, -4.5], ... ]\\n      ```\\n\\n      Mathematical definition: neg(x) = -x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.ones\",\n    \"summary\": \"Creates a tensor filled with ones.\",\n    \"description\": \"The `ones` operation creates a tensor filled with ones of the specified shape.\\n\\n    This operation is commonly used to initialize tensors with one values. It takes a shape attribute\\n    and produces a tensor of that shape with all elements set to one.\\n\\n    Example:\\n    ```mlir\\n    // Create a 3D tensor of ones with shape [64, 28, 28]\\n    %result = ttir.ones() {\\n        shape = [64, 28, 28]\\n    } : () -> tensor<64x28x28xbf16>\\n    // Result: A tensor of shape [64, 28, 28] filled with ones\\n\\n    // Create a 2D tensor of ones with shape [3, 4]\\n    %result = ttir.ones() {\\n        shape = [3, 4]\\n    } : () -> tensor<3x4xf32>\\n    // Result: [[1.0, 1.0, 1.0, 1.0],\\n    //          [1.0, 1.0, 1.0, 1.0],\\n    //          [1.0, 1.0, 1.0, 1.0]]\\n    ```\\n\\n    Attributes:\\n    - `shape` (Array of Integer): The shape of the tensor to create.\\n\\n    Output:\\n    - `result` (Tensor): The tensor filled with ones.\\n\\n    Note: The element type of the result tensor is determined by the return type specified in the operation.\\n    This operation is useful for initializing tensors before scaling them or as a starting point for\\n    operations that require tensors filled with ones, such as creating masks or constant multipliers.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DenseI32ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.pad\",\n    \"summary\": \"Tensor padding operation.\",\n    \"description\": \"The `pad` operation adds padding to the edges of an input tensor with a specified constant value.\\n\\n      This operation extends the dimensions of the input tensor by adding padding elements with a constant value.\\n      The padding is specified for each dimension as the number of elements to add at the beginning (low) and\\n      end (high) of that dimension.\\n\\n      The `padding` attribute must be a sequence of integers that is twice the size as the rank of the input.\\n      Each pair of integers in the padding attribute represents the amount of padding to add to the low and high\\n      of that dimension. For example, for a 2D tensor, the padding attribute would have 4 values: [dim0_low, dim0_high, dim1_low, dim1_high].\\n\\n      Example:\\n      ```mlir\\n      // Pad a 2x3 tensor with different padding on each dimension\\n      %input = ... : tensor<2x3xf32>  // Input tensor with values:\\n                                      // [[1, 2, 3],\\n                                      //  [4, 5, 6]]\\n      %result = ttir.pad(%input) {\\n          padding = [1, 0, 1, 1],  // Format: [dim0_low, dim0_high, dim1_low, dim1_high]\\n          value = 0.0 : f32\\n      } : (tensor<2x3xf32>) -> tensor<3x5xf32>\\n      // Result:\\n      // [[0, 0, 0, 0, 0],\\n      //  [0, 1, 2, 3, 0],\\n      //  [0, 4, 5, 6, 0]]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to pad.\\n\\n      Attributes:\\n      - `padding` (Array of Integer): The padding values for each dimension, specified as [dim0_low, dim0_high, dim1_low, dim1_high, ...].\\n      - `value` (Float): The constant value to use for the padding elements.\\n\\n      Output:\\n      - `result` (Tensor): The padded tensor.\\n\\n      Note: The shape of the output tensor must match the shape of the input tensor plus the padding specified\\n      in the padding attribute. For example, if the input shape is [2,3] and the padding is [1,0,1,1], then\\n      the output shape must be [3,5].\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"value\", \"type\": \"F32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.paged_fill_cache\",\n    \"summary\": \"Paged fill cache op.\",\n    \"description\": \"Fills the `cache` tensor in-place with values from `input` at `batch_idx_tensor`.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"page_table\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"batch_idx_tensor\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.paged_scaled_dot_product_attention_decode\",\n    \"summary\": \"Paged scaled dot product attention decode operation.\",\n    \"description\": \"Paged scaled dot product attention decode operation.\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"page_table\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_mask\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"cur_pos_tensor\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"attention_sink\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.paged_update_cache\",\n    \"summary\": \"Paged update cache op.\",\n    \"description\": \"Inputs:\\n        - `cache`: The cache tensor to be updated. This tensor is modified in place [max_num_blocks, num_heads, block_size, head_dim]\\n        - `input`: The input tensor containing new values. [1, num_users, num_heads (padded to 32), head_dim]\\n        - `update_index`: Indices specifying where to update the cache. [num_users]\\n        - `share_cache`: Whether the cache tensors share memory regions. Defaults to False.\\n        - `page_table`: The page table for managing memory regions during updates. [num_users, max_num_blocks_per_seq]\\n\\n      Outputs:\\n        - `result`: The updated cache tensor.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"update_index\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"page_table\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"share_cache\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.permute\",\n    \"summary\": \"Tensor dimension permutation operation.\",\n    \"description\": \"The `permute` operation reorders the dimensions of the input tensor according to the specified permutation.\\n\\n      This operation is similar to transpose but generalizes to tensors of any rank. It rearranges the\\n      dimensions of the input tensor based on the permutation attribute, which specifies the new order\\n      of dimensions.\\n\\n      Example:\\n      ```mlir\\n      // Transpose a 2D tensor (swap dimensions 0 and 1)\\n      %input = ... : tensor<3x4xf32>  // Input tensor with shape [3,4]\\n      %result = ttir.permute(%input) {\\n          permutation = [1, 0]  // Swap dimensions 0 and 1\\n      } : (tensor<3x4xf32>) -> tensor<4x3xf32>\\n      // Result: tensor with shape [4,3], equivalent to transposing the input\\n\\n      // Permute a 3D tensor\\n      %input = ... : tensor<2x3x4xf32>  // Input tensor with shape [2,3,4]\\n      %result = ttir.permute(%input) {\\n          permutation = [1, 2, 0]  // Reorder dimensions to [1,2,0]\\n      } : (tensor<2x3x4xf32>) -> tensor<3x4x2xf32>\\n      // Result: tensor with shape [3,4,2]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to permute.\\n\\n      Attributes:\\n      - `permutation` (Array of Integer): The permutation of the input tensor dimensions.\\n        This must be a valid permutation of the indices [0, 1, ..., rank-1].\\n\\n      Output:\\n      - `result` (Tensor): The permuted tensor.\\n\\n      Note: The permutation attribute must contain exactly one occurrence of each integer in the range\\n      [0, rank-1], where rank is the number of dimensions in the input tensor. The shape of the output\\n      tensor is determined by permuting the dimensions of the input tensor according to the permutation.\\n      For example, if the input shape is [2,3,4] and the permutation is [1,2,0], then the output shape\\n      will be [3,4,2].\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.pooling\",\n    \"summary\": \"General pooling operation.\",\n    \"description\": \"The `pooling` operation is a generalized pooling operation that can implement various pooling methods\\n    such as max pooling, average pooling, and sum pooling.\\n\\n    Pooling operations are commonly used in neural networks to reduce the spatial dimensions of feature maps\\n    by applying a specific function (like maximum or average) over local regions of the input tensor.\\n\\n    Example:\\n    ```mlir\\n    // Max pooling with 2x2 window and stride 2\\n    %input = ... : tensor<1x32x32x16xf32>    // Batch size 1, 32x32 feature map, 16 channels\\n    %result = ttir.pooling(%input) {\\n        pooling_method = \\\"MAX\\\",\\n        window_dimensions = [1, 2, 2, 1],\\n        window_strides = [1, 2, 2, 1],\\n        base_dilations = [1, 1, 1, 1],\\n        window_dilations = [1, 1, 1, 1],\\n        padding = [0, 0, 0, 0, 0, 0, 0, 0]\\n    } : (tensor<1x32x32x16xf32>) -> tensor<1x16x16x16xf32>\\n\\n    // Average pooling with 3x3 window and stride 2\\n    %input = ... : tensor<1x32x32x16xf32>    // Batch size 1, 32x32 feature map, 16 channels\\n    %result = ttir.pooling(%input) {\\n        pooling_method = \\\"AVG\\\",\\n        window_dimensions = [1, 3, 3, 1],\\n        window_strides = [1, 2, 2, 1],\\n        base_dilations = [1, 1, 1, 1],\\n        window_dilations = [1, 1, 1, 1],\\n        padding = [0, 0, 0, 0, 0, 0, 0, 0]\\n    } : (tensor<1x32x32x16xf32>) -> tensor<1x15x15x16xf32>\\n    ```\\n\\n    Inputs:\\n    - `inputs` (Variadic Tensor): Input tensors to be pooled.\\n\\n    Attributes:\\n    - `pooling_method` (Enum): The pooling method to use (MAX, AVG, SUM).\\n    - `window_dimensions` (Array of Integer): Dimensions of the pooling window. The rank of this array is the same as the rank of the input tensors.\\n    - `window_strides` (Array of Integer): Stride of the pooling window. The rank of this array is the same as the rank of the input tensors.\\n    - `base_dilations` (Array of Integer): Dilation factors for the input. The rank of this array is the same as the rank of the input tensors.\\n    - `window_dilations` (Array of Integer): Dilation factors for the pooling window. The rank of this array is the same as the rank of the input tensors.\\n    - `padding` (Array of Integer): Padding to apply to the input. The rank of this array is twice the rank of the input tensors, representing padding for each dimension.\\n\\n    Outputs:\\n    - `results` (Variadic Tensor): Output tensors after pooling.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pooling_method\", \"type\": \"TTIR_PoolingMethodAttr{Average|Max|Sum}\" },\n      { \"name\": \"window_dimensions\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"window_strides\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"base_dilations\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"window_dilations\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.pow\",\n    \"summary\": \"Elementwise power operation.\",\n    \"description\": \"The `pow` operation performs an elementwise exponentiation between two tensors.\\n\\n      For each pair of corresponding elements, it raises the element in the first tensor (base)\\n      to the power of the element in the second tensor (exponent) and places the result in the\\n      output tensor.\\n\\n      Example:\\n      ```mlir\\n      // Power operation\\n      %result = ttir.pow(%lhs, %rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %lhs: [2.0, 3.0, 4.0]  // Bases\\n      // %rhs: [2.0, 2.0, 0.5]  // Exponents\\n      // Output tensor:\\n      // [4.0, 9.0, 2.0]\\n\\n      // Example with integer values\\n      %result = ttir.pow(%int_lhs, %int_rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>\\n      // Input tensors:\\n      // %int_lhs: [2, 3, 5]\\n      // %int_rhs: [3, 2, 1]\\n      // Output tensor:\\n      // [8, 9, 5]\\n      ```\\n\\n      Special cases:\\n      - 0^0 is typically defined as 1\\n      - For integer types, negative bases with non-integer exponents may result in complex numbers,\\n        which are typically not supported and may result in undefined behavior\\n\\n      Mathematical definition: pow(x, y) = x^y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.prod\",\n    \"summary\": \"Product reduction op.\",\n    \"description\": \"The `prod` operation computes the product of elements along specified dimensions of the input tensor.\\n\\n    This operation reduces the input tensor by multiplying all elements along the dimensions\\n    specified in `dim_arg`. If `dim_arg` is not provided, the product is computed over all dimensions,\\n    resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n    with a size of 1.\\n\\n    Example:\\n    ```mlir\\n    // Product along dimension 0\\n    %input = ... : tensor<2x3xi32>\\n    %result = ttir.prod(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<2x3xi32>) -> tensor<3xi32>\\n    // Input tensor:\\n    // [[1, 2, 3],\\n    //  [4, 5, 6]]\\n    // Output tensor:\\n    // [4, 10, 18]  // Product of each column\\n\\n    // Product along dimension 1\\n    %input = ... : tensor<2x3xi32>\\n    %result = ttir.prod(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<2x3xi32>) -> tensor<2xi32>\\n    // Input tensor:\\n    // [[1, 2, 3],\\n    //  [4, 5, 6]]\\n    // Output tensor:\\n    // [6, 120]  // Product of each row\\n\\n    // Product over all dimensions\\n    %input = ... : tensor<2x3xi32>\\n    %result = ttir.prod(%input) {keep_dim = false} : (tensor<2x3xi32>) -> tensor<i32>\\n    // Input tensor:\\n    // [[1, 2, 3],\\n    //  [4, 5, 6]]\\n    // Output tensor:\\n    // 720  // Product of all elements\\n    ```\\n\\n    Note: For floating-point inputs, the order of multiplication may affect the result due to floating-point precision issues.\\n\\n    Mathematical definition: prod(x, dim) = ∏ x[i] for all i in dimension dim\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor.\\n\\n    Attributes:\\n    - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n    - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n    Output:\\n    - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.quantize\",\n    \"summary\": \"Quantize operation.\",\n    \"description\": \"The Quantize operation converts a tensor into a quantized tensor using the `quant.uniform` type from the MLIR Quant dialect.\\n      This type encapsulates the scale and zero-point metadata directly within the tensor type.\\n      The output tensor will be of type 'quant.uniform', where each element is computed as:\\n      ```\\n      output[i] = (input[i] / scale) + zero_point\\n      ```\\n\\n      Example:\\n      ```mlir\\n      %input = ttir.empty() : () -> tensor<64x128xf32>\\n      %quantized = \\\"ttir.quantize\\\"(%input) : (tensor<64x128xf32>) -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n\\n      // In this example:\\n      // - The input is a 64x128 tensor of 32-bit floating-point values\\n      // - The output is a 64x128 tensor of 32-bit quantized values\\n      // - The scale is 0.1 (each step represents 0.1 in the original scale)\\n      // - The zero point is 128 (the value 128 in the quantized space represents 0.0 in the original space)\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): Input tensor to be quantized.\\n\\n      Results:\\n      - `result` (Quantized Tensor): The quantized tensor with type `quant.uniform`.\\n\\n      Note: The quantization parameters (scale and zero point) are specified in the result type.\\n      Quantization helps reduce model size and computational requirements by representing\\n      floating-point values with lower-precision integers, which is particularly useful for\\n      deployment on resource-constrained devices.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.quantize_unrolled\",\n    \"summary\": \"Quantize operation unrolled (scale and zero point as input operands).\",\n    \"description\": \"The QuantizeUnrolledOp quantizes a tensor using the scale and zero point provided as input operands.\\n\\n    Inputs:\\n      - `input` AnyRankedTensor: The input tensor to be quantized. Must have floating-point element type.\\n      - `scale` AnyRankedTensor: The scale factor (or factors for per-axis quantization). Must be either a scalar (for per-tensor quantization) or a 1D tensor with size matching the dimension of the specified axis (for per-axis quantization).\\n      - `zero_point` AnyRankedTensor: The zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n      - `axis` Optional<i32>: The axis along which quantization is applied. Must be in range [0, rank) where rank is the rank of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.rand\",\n    \"summary\": \"Random number generation operation.\",\n    \"description\": \"Returns a tensor filled with random numbers drawn from a uniform distribution over given interval [low, high) [Default: [0, 1)].\\n\\n    Example:\\n      %0 = \\\"ttir.rand\\\"() <{dtype = bf16, high = 1.000000e+00 : f32, low = 0.000000e+00 : f32, seed = 0 : ui32, size = [32 : i32, 32 : i32]}> : () -> tensor<32x32xbf16>\\n\\n    Attributes:\\n      - `size` (Array of Integer): The shape of the tensor to create.\\n      - `dtype` (mlir:Type): Data type of the returned tensor.\\n      - `low` (Float): The lower bound of the range (inclusive) [Default: 0.0].\\n      - `high` (Float): The upper bound of the range (exclusive) [Default: 1.0].\\n      - `seed` (Integer): Value to initialize the random number generator for reproducible results [Default: 0].\\n\\n    Output:\\n      - `result` (Tensor): The generated tensor containing the random values.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"dtype\", \"type\": \"TypeAttr\" },\n      { \"name\": \"low\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"high\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"seed\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.rearrange\",\n    \"summary\": \"Tensor rearrange operation.\",\n    \"description\": \"The `rearrange` operation reshapes, transposes, and reorganizes tensor dimensions using an\\n      intuitive notation inspired by Einstein notation. This operation takes an input tensor and\\n      transforms it according to a pattern string that describes how dimensions should be rearranged.\\n      The pattern uses named axes and supports splitting, merging, and reordering dimensions in a\\n      single operation. This operation is commonly used in neural networks for dimension manipulation,\\n      such as converting between different data layouts, splitting/merging dimensions, or transposing\\n      axes.\\n\\n      Example:\\n      ```mlir\\n      // Transpose a 2D tensor (equivalent to transpose)\\n      %input = ... : tensor<2x3xf32>  // Input tensor with shape [2,3]\\n      %result = ttir.rearrange(%input) {pattern = \\\"h w -> w h\\\"} : (tensor<2x3xf32>) -> tensor<3x2xf32>\\n\\n      // Flatten spatial dimensions of a 4D tensor (batch, channel, height, width)\\n      %input = ... : tensor<1x3x4x4xf32>  // Input tensor with shape [1,3,4,4]\\n      %result = ttir.rearrange(%input) {pattern = \\\"b c h w -> b c (h w)\\\"} :\\n                (tensor<1x3x4x4xf32>) -> tensor<1x3x16xf32>\\n\\n      // Split a dimension into two dimensions\\n      %input = ... : tensor<2x12xf32>  // Input tensor with shape [2,12]\\n      %result = ttir.rearrange(%input) {pattern = \\\"b (h w) -> b h w\\\", axes_lengths = {h = 3, w = 4}} :\\n                (tensor<2x12xf32>) -> tensor<2x3x4xf32>\\n\\n      // Rearrange image patches (batch, height, width, channels) to sequence format\\n      %input = ... : tensor<8x16x16x3xf32>  // Input tensor with shape [8,16,16,3]\\n      %result = ttir.rearrange(%input) {pattern = \\\"b h w c -> b (h w) c\\\"} :\\n                (tensor<8x16x16x3xf32>) -> tensor<8x256x3xf32>\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to rearrange.\\n\\n      Attributes:\\n      - `pattern` (String): A string describing the rearrangement pattern. The pattern consists of\\n        two parts separated by \\\"->\\\": the left side describes the input axes and the right side\\n        describes the output axes. Named axes can be reordered, merged using parentheses \\\"()\\\",\\n        or split using parentheses with known dimensions. Examples: \\\"b c h w -> b (c h w)\\\",\\n        \\\"b (h w) -> b h w\\\", \\\"h w c -> c h w\\\".\\n      - `axes_lengths` (UNSUPPORTED #6339): A mapping of axis names to their lengths when splitting\\n        dimensions. Required when decomposing a dimension into multiple dimensions. Example:\\n        {h = 3, w = 4} when splitting a dimension of size 12 into h and w.\\n\\n      Output:\\n      - `result` (Tensor): The rearranged tensor.\\n\\n      Note: The total number of elements in the input tensor must equal the total number of elements\\n      in the output tensor. When merging dimensions, their sizes are multiplied. When splitting\\n      dimensions, the product of the split dimensions must equal the original dimension size. All\\n      axis names in the pattern must be unique within each side of the arrow, and axes can be\\n      reordered freely between input and output patterns.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pattern\", \"type\": \"Builtin_StringAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.reciprocal\",\n    \"summary\": \"Eltwise reciprocal.\",\n    \"description\": \"The `reciprocal` operation computes the reciprocal (1/x) of each element in the input tensor.\\n\\n      For each element, it returns the reciprocal of the value.\\n\\n      Example:\\n      ```mlir\\n      // Compute reciprocal of all elements in %input\\n      %result = ttir.reciprocal(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.5882, 0.5, -3.3333, 0.2173], ... ]\\n      ```\\n\\n      Mathematical definition: reciprocal(x) = 1 / x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.reduce_and\",\n    \"summary\": \"Logical AND reduction operation.\",\n    \"description\": \"The `reduce_and` operation performs a logical AND reduction along specified dimensions of the input tensor.\\n\\n      This operation reduces the input tensor by applying a logical AND operation to all elements along the dimensions\\n      specified in `dim_arg`. If `dim_arg` is not provided, the reduction is computed over all dimensions,\\n      resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n      with a size of 1.\\n\\n      The operation treats non-zero values as True and zero values as False when performing the logical AND.\\n\\n      Example:\\n      ```mlir\\n      // Logical AND reduction along dimension 0\\n      %input = ... : tensor<4x4xi1>\\n      %result = ttir.reduce_and(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<4x4xi1>) -> tensor<4xi1>\\n      // Input tensor (where 1 represents True and 0 represents False):\\n      // [[1, 0, 1, 0],\\n      //  [1, 1, 1, 1],\\n      //  [0, 0, 1, 1],\\n      //  [0, 1, 1, 0]]\\n      // Output tensor:\\n      // [0, 0, 1, 0]  // Logical AND of each column\\n\\n      // Logical AND reduction along dimension 1\\n      %input = ... : tensor<4x4xi1>\\n      %result = ttir.reduce_and(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<4x4xi1>) -> tensor<4xi1>\\n      // Input tensor:\\n      // [[1, 0, 1, 0],\\n      //  [1, 1, 1, 1],\\n      //  [0, 0, 1, 1],\\n      //  [0, 1, 1, 0]]\\n      // Output tensor:\\n      // [0, 1, 0, 0]  // Logical AND of each row\\n\\n      // Logical AND reduction over all dimensions\\n      %input = ... : tensor<4x4xi1>\\n      %result = ttir.reduce_and(%input) {keep_dim = false} : (tensor<4x4xi1>) -> tensor<i1>\\n      // Input tensor:\\n      // [[1, 0, 1, 0],\\n      //  [1, 1, 1, 1],\\n      //  [0, 0, 1, 1],\\n      //  [0, 1, 1, 0]]\\n      // Output tensor:\\n      // 0  // Logical AND of all elements\\n      ```\\n\\n      Mathematical definition: reduce_and(x, dim) = AND(x[i]) for all i in dimension dim\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n      - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n      Output:\\n      - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.reduce_or\",\n    \"summary\": \"Logical OR reduction operation.\",\n    \"description\": \"The `reduce_or` operation performs a logical OR reduction along specified dimensions of the input tensor.\\n\\n      This operation reduces the input tensor by applying a logical OR operation to all elements along the dimensions\\n      specified in `dim_arg`. If `dim_arg` is not provided, the reduction is computed over all dimensions,\\n      resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n      with a size of 1.\\n\\n      The operation treats non-zero values as True and zero values as False when performing the logical OR.\\n\\n      Example:\\n      ```mlir\\n      // Logical OR reduction along dimension 0\\n      %input = ... : tensor<4x4xi1>\\n      %result = ttir.reduce_or(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<4x4xi1>) -> tensor<4xi1>\\n      // Input tensor (where 1 represents True and 0 represents False):\\n      // [[1, 0, 0, 0],\\n      //  [1, 1, 0, 1],\\n      //  [0, 0, 0, 1],\\n      //  [0, 0, 0, 0]]\\n      // Output tensor:\\n      // [1, 1, 0, 1]  // Logical OR of each column\\n\\n      // Logical OR reduction along dimension 1\\n      %input = ... : tensor<4x4xi1>\\n      %result = ttir.reduce_or(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<4x4xi1>) -> tensor<4xi1>\\n      // Input tensor:\\n      // [[1, 0, 0, 0],\\n      //  [1, 1, 0, 1],\\n      //  [0, 0, 0, 1],\\n      //  [0, 0, 0, 0]]\\n      // Output tensor:\\n      // [1, 1, 1, 0]  // Logical OR of each row\\n\\n      // Logical OR reduction over all dimensions\\n      %input = ... : tensor<4x4xi1>\\n      %result = ttir.reduce_or(%input) {keep_dim = false} : (tensor<4x4xi1>) -> tensor<i1>\\n      // Input tensor:\\n      // [[1, 0, 0, 0],\\n      //  [1, 1, 0, 1],\\n      //  [0, 0, 0, 1],\\n      //  [0, 0, 0, 0]]\\n      // Output tensor:\\n      // 1  // Logical OR of all elements\\n      ```\\n\\n      Mathematical definition: reduce_or(x, dim) = OR(x[i]) for all i in dimension dim\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n      - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n      Output:\\n      - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.reduce_scatter\",\n    \"summary\": \"Reduce scatter operation.\",\n    \"description\": \"Reduce scatter op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_type\", \"type\": \"TTCore_ReduceTypeAttr{sum|mean|max|min|std|var|prod|invalid}\" },\n      { \"name\": \"scatter_dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.relu\",\n    \"summary\": \"Eltwise ReLU.\",\n    \"description\": \"The `relu` operation computes the rectified linear unit (ReLU) of each element in the input tensor.\\n\\n      For each element, it returns the maximum of 0 and the value. The operation preserves\\n      the data type of the input.\\n\\n      Example:\\n      ```mlir\\n      // Compute ReLU of all elements in %input\\n      %result = ttir.relu(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[1.7, 2.0, 0.0, 4.5], ... ]\\n      ```\\n\\n      Mathematical definition: relu(x) = max(0, x)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.relu6\",\n    \"summary\": \"Eltwise ReLU6.\",\n    \"description\": \"The `relu6` operation computes the ReLU6 activation function of each element in the input tensor.\\n\\n    For each element, it returns the minimum of 6 and the maximum of 0 and the value. The operation preserves\\n    the data type of the input.\\n\\n    This operation has the idempotence property, meaning that applying it multiple times\\n    produces the same result as applying it once: relu6(relu6(x)) = relu6(x).\\n\\n    Example:\\n    ```mlir\\n    // Compute ReLU6 of all elements in %input\\n    %result = ttir.relu6(%input, %output) : tensor<4x4xf32>, tensor<4x4xf32> -> tensor<4x4xf32>\\n    // Input tensor:\\n    // [[1.7, 2.0, -0.3, 7.0], ... ]\\n    // Output tensor:\\n    // [[1.7, 2.0, 0.0, 6.0], ... ]\\n    ```\\n\\n    Mathematical definition: relu6(x) = min(6, max(0, x))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.remainder\",\n    \"summary\": \"Elementwise remainder operation.\",\n    \"description\": \"The `remainder` operation performs an elementwise remainder (modulo) operation between two tensors.\\n\\n      For each pair of corresponding elements, it computes the remainder when dividing the element\\n      in the first tensor (dividend) by the element in the second tensor (divisor) and places the\\n      result in the output tensor.\\n\\n      Example:\\n      ```mlir\\n      // Remainder operation\\n      %result = ttir.remainder(%lhs, %rhs) : (tensor<4xi64>, tensor<4xi64>) -> tensor<4xi64>\\n      // Input tensors:\\n      // %lhs: [17, -17, 17, -17]  // Dividends\\n      // %rhs: [3, 3, -3, -3]      // Divisors\\n      // Output tensor:\\n      // [2, -2, 2, -2]\\n\\n      // Example with floating point values\\n      %result = ttir.remainder(%float_lhs, %float_rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %float_lhs: [10.5, -10.5, 3.0]\\n      // %float_rhs: [3.0, 3.0, 2.0]\\n      // Output tensor:\\n      // [1.5, -1.5, 1.0]\\n      ```\\n\\n      Note: Division by zero typically results in undefined behavior or NaN for floating-point types.\\n\\n      Mathematical definition: remainder(x, y) = x % y (where % is the remainder operator)\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.repeat\",\n    \"summary\": \"Repeat operation.\",\n    \"description\": \"The `repeat` operation creates a new tensor by replicating the input tensor's elements\\n    along specified dimensions.\\n\\n    This operation repeats the entire input tensor along each dimension according to the\\n    values specified in the `repeat_dimensions` attribute. The resulting tensor's shape\\n    is the product of the input tensor's shape and the corresponding repeat values.\\n\\n    Example:\\n    ```mlir\\n    // Repeat a 2x3 tensor with repeat dimensions [2, 2]\\n    %input = ... : tensor<2x3xf32>\\n    %result = ttir.repeat(%input) {repeat_dimensions = [2, 2]} : (tensor<2x3xf32>) -> tensor<4x6xf32>\\n    // Input tensor:\\n    // [[1.0, 2.0, 3.0],\\n    //  [4.0, 5.0, 6.0]]\\n    // Output tensor:\\n    // [[1.0, 2.0, 3.0, 1.0, 2.0, 3.0],\\n    //  [4.0, 5.0, 6.0, 4.0, 5.0, 6.0],\\n    //  [1.0, 2.0, 3.0, 1.0, 2.0, 3.0],\\n    //  [4.0, 5.0, 6.0, 4.0, 5.0, 6.0]]\\n\\n    // Repeat a 2x2 tensor with repeat dimensions [1, 3]\\n    %input = ... : tensor<2x2xf32>\\n    %result = ttir.repeat(%input) {repeat_dimensions = [1, 3]} : (tensor<2x2xf32>) -> tensor<2x6xf32>\\n    // Input tensor:\\n    // [[1.0, 2.0],\\n    //  [3.0, 4.0]]\\n    // Output tensor:\\n    // [[1.0, 2.0, 1.0, 2.0, 1.0, 2.0],\\n    //  [3.0, 4.0, 3.0, 4.0, 3.0, 4.0]]\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to repeat.\\n\\n    Attributes:\\n    - `repeat_dimensions` (Array of Integer): The number of times to repeat the tensor along each dimension.\\n\\n    Output:\\n    - `result` (Tensor): The repeated tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"repeat_dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.repeat_interleave\",\n    \"summary\": \"Tensor repeat interleave operation.\",\n    \"description\": \"The `repeat_interleave` operation repeats elements of a tensor along a specified dimension.\\n\\n      Unlike the `repeat` operation which repeats the entire tensor, this operation repeats each individual\\n      element of the input tensor the specified number of times along the given dimension. This creates an\\n      interleaved pattern of repeated values.\\n\\n      Example:\\n      ```mlir\\n      // Repeat interleave along dimension 0 with repeats=2\\n      %input = ... : tensor<2x3xf32>\\n      %result = ttir.repeat_interleave(%input) {repeats = 2 : ui32, dim = 0 : i32} : (tensor<2x3xf32>) -> tensor<4x3xf32>\\n      // Input tensor:\\n      // [[1.0, 2.0, 3.0],\\n      //  [4.0, 5.0, 6.0]]\\n      // Output tensor:\\n      // [[1.0, 2.0, 3.0],  // First row repeated\\n      //  [1.0, 2.0, 3.0],\\n      //  [4.0, 5.0, 6.0],  // Second row repeated\\n      //  [4.0, 5.0, 6.0]]\\n\\n      // Repeat interleave along dimension 1 with repeats=3\\n      %input = ... : tensor<2x2xf32>\\n      %result = ttir.repeat_interleave(%input) {repeats = 3 : ui32, dim = 1 : i32} : (tensor<2x2xf32>) -> tensor<2x6xf32>\\n      // Input tensor:\\n      // [[1.0, 2.0],\\n      //  [3.0, 4.0]]\\n      // Output tensor:\\n      // [[1.0, 1.0, 1.0, 2.0, 2.0, 2.0],  // Each element repeated 3 times\\n      //  [3.0, 3.0, 3.0, 4.0, 4.0, 4.0]]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `repeats` (Integer): The number of times to repeat each element.\\n      - `dim` (Integer): The dimension along which to repeat elements.\\n\\n      Output:\\n      - `result` (Tensor): The tensor with repeated elements.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"repeats\", \"type\": \"UI32Attr\" },\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.requantize\",\n    \"summary\": \"Requantize operation.\",\n    \"description\": \"The Requantize operation converts a quantized tensor from one scale and zero-point to another, using the `quant.uniform` type from the MLIR Quant dialect.\\n    The input tensor is expected to be of type `quant.uniform.`\\n    The output tensor will also be of type `quant.uniform.`\\n    Each element in the output tensor is computed as:\\n    ```\\n    output[i] = round((input[i] - input_zero_point) * (input_scale / output_scale)) + output_zero_point\\n    ```\\n    Example:\\n    ```mlir\\n    %input = ttir.empty() : () -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n    %requantized = \\\"ttir.requantize\\\"(%input) : (tensor<64x128x!quant.uniform<i32:f32, 0.1>>) -> tensor<64x128x!quant.uniform<i32:f32, 0.2>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.requantize_unrolled\",\n    \"summary\": \"Requantize operation unrolled (scale and zero point as input operands).\",\n    \"description\": \"The RequantizeUnrolledOp requantizes a tensor using the scale and zero point provided as input operands.\\n\\n    Inputs:\\n      - `input` AnyRankedTensor: The input tensor to be requantized. Must have quantized element type.\\n      - `in_scale` AnyRankedTensor: The input scale factor (or factors for per-axis quantization). Must be either a scalar (for per-tensor quantization) or a 1D tensor with size matching the dimension of the specified axis (for per-axis quantization).\\n      - `in_zero_point` AnyRankedTensor: The input zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n      - `out_scale` AnyRankedTensor: The output scale factor (or factors for per-axis quantization). Must be either a scalar (for per-tensor quantization) or a 1D tensor with size matching the dimension of the specified axis (for per-axis quantization).\\n      - `out_zero_point` AnyRankedTensor: The output zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n      - `axis` Optional<i32>: The axis along which quantization is applied. Must be in range [0, rank) where rank is the rank of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"in_scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"in_zero_point\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"out_scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"out_zero_point\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.reshape\",\n    \"summary\": \"Tensor reshape operation.\",\n    \"description\": \"The `reshape` operation changes the shape of a tensor without changing the data or number of elements.\\n\\n      This operation takes an input tensor and reshapes it to a new shape specified by the shape attribute.\\n      The total number of elements in the tensor must remain the same after reshaping. This operation is\\n      commonly used in neural networks to change the dimensionality of tensors between layers.\\n\\n      Example:\\n      ```mlir\\n      // Reshape a 2x3 tensor to a 1x6 tensor\\n      %input = ... : tensor<2x3xf32>  // Input tensor with shape [2,3]\\n      %result = ttir.reshape(%input) {shape = [1, 6]} : (tensor<2x3xf32>) -> tensor<1x6xf32>\\n\\n      // Reshape a 3D tensor to a 2D tensor\\n      %input = ... : tensor<2x3x4xf32>  // Input tensor with shape [2,3,4]\\n      %result = ttir.reshape(%input) {shape = [6, 4]} : (tensor<2x3x4xf32>) -> tensor<6x4xf32>\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to reshape.\\n\\n      Attributes:\\n      - `shape` (Array of Integer): The new shape for the tensor.\\n\\n      Output:\\n      - `result` (Tensor): The reshaped tensor.\\n\\n      Note: The total number of elements in the input tensor must equal the total number of elements\\n      in the output tensor. For example, a tensor of shape [2,3] (6 elements) can be reshaped to [1,6],\\n      [6,1], [2,1,3], etc., but not to [2,4] (8 elements).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.reverse\",\n    \"summary\": \"Tensor reversal operation.\",\n    \"description\": \"The `reverse` operation reverses the order of elements in the input tensor along the specified dimensions.\\n\\n    This operation flips the elements of a tensor along one or more axes, which is useful for operations\\n    like sequence reversal, matrix transposition with reversal, and other tensor manipulations that require\\n    changing the order of elements.\\n\\n    Example:\\n    ```mlir\\n    // Reverse a 3x2 tensor along dimension 1 (columns)\\n    %input = ... : tensor<3x2xi32>  // Input tensor with values:\\n                                    // [[1, 2],\\n                                    //  [3, 4],\\n                                    //  [5, 6]]\\n    %result = ttir.reverse(%input) {\\n        dimensions = [1]  // Reverse along columns\\n    } : (tensor<3x2xi32>) -> tensor<3x2xi32>\\n    // Result:\\n    // [[2, 1],\\n    //  [4, 3],\\n    //  [6, 5]]\\n\\n    // Reverse a 3x2 tensor along both dimensions\\n    %input = ... : tensor<3x2xi64>  // Input tensor with values:\\n                                    // [[1, 2],\\n                                    //  [3, 4],\\n                                    //  [5, 6]]\\n    %result = ttir.reverse(%input) {\\n        dimensions = [0, 1]  // Reverse along both rows and columns\\n    } : (tensor<3x2xi64>) -> tensor<3x2xi64>\\n    // Result:\\n    // [[6, 5],\\n    //  [4, 3],\\n    //  [2, 1]]\\n    ```\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to reverse.\\n\\n    Attributes:\\n    - `dimensions` (Array of Integer): The dimensions along which to reverse the tensor.\\n\\n    Output:\\n    - `result` (Tensor): The reversed tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.rms_norm\",\n    \"summary\": \"RMS normalization operation\",\n    \"description\": \"Performs RMS (Root Mean Square) normalization on the input tensor. This operation\\n    normalizes the input tensor by computing the root mean square of elements across\\n    the specified dimensions and dividing by that value, optionally scaling and\\n    shifting the result.\\n\\n    Inputs:\\n    - `input` (Tensor): The input tensor to be normalized.\\n    - `weight` (Optional Tensor): The scale parameter (gamma). If provided, the normalized\\n      result is element-wise multiplied by this weight.\\n    - `bias` (Optional Tensor): The shift parameter (beta). If provided, this bias is\\n      added to the scaled result.\\n\\n    Attributes:\\n    - `normalized_shape` specifies the dimensions over which to normalize. Typically\\n      the last few dimensions of the input tensor.\\n    - `epsilon` is a small constant added for numerical stability (default: 1e-05).\\n\\n    Output:\\n    - `result` (Tensor): The RMS normalized output tensor.\\n\\n    Example:\\n    ```mlir\\n      // RMS normalization over last dimension (shape: [2, 4, 8] -> normalize over [8])\\n      %result = ttir.rms_norm(%input, %weight, %bias) : <{ normalized_shape = [8], epsilon = 1e-05 }> :\\n            (tensor<2x4x8xf32>, tensor<2x4x8xf32>, tensor<8xf32>) -> tensor<2x4x8xf32>\\n\\n      // RMS normalization over last two dimensions (shape: [2, 4, 8] -> normalize over [4, 8])\\n      %result = ttir.rms_norm(%input, %weight, %bias) : <{ normalized_shape = [4, 8], epsilon = 1e-05) }> :\\n            (tensor<2x4x8xf32>, tensor<2x4x8xf32>, tensor<4x8xf32>) -> tensor<2x4x8xf32>\\n    ```\\n\\n    Mathematical definition: rms_norm(x, weight, bias, epsilon) =\\n      (x / sqrt(mean(x^2, dims=normalized_dims) + epsilon)) * weight + bias\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalized_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.rsqrt\",\n    \"summary\": \"Eltwise reciprocal square root.\",\n    \"description\": \"The `rsqrt` operation computes the reciprocal square root of each element in the input tensor.\\n\\n      For each element, it returns the reciprocal of the square root of the value.\\n\\n      Example:\\n      ```mlir\\n      // Compute reciprocal square root of all elements in %input\\n      %result = ttir.rsqrt(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.5882, 0.5, -3.3333, 0.2173], ... ]\\n      ```\\n\\n      Mathematical definition: rsqrt(x) = 1 / sqrt(x)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.scaled_dot_product_attention\",\n    \"summary\": \"Scaled dot product attention operation.\",\n    \"description\": \"Scaled dot product attention.\\n    The implementation is FlashAttention-2.\\n\\n    Args:\\n        query (AnyRankedTensor): The query tensor.          [batch x num_heads x query_seq_len x head_size]\\n        key (AnyRankedTensor): The key tensor.              [batch x num_kv_heads x kv_seq_len x head_size]\\n        value (AnyRankedTensor): The value tensor.          [batch x num_kv_heads x kv_seq_len x head_size]\\n        attention_mask (AnyRankedTensor, optional): Defaults to `None`. [batch x 1 x query_seq_len x kv_seq_len]. Head broadcasting is implied.\\n        output (AnyRankedTensor): The output DPS operand [batch x num_heads x query_seq_len x head_size].\\n        is_causal (bool): Whether The attention is causal. Defaults to `true`.\\n        scale (float, optional): Defaults to `None`.\\n        sliding_window_size (uint, optional): Defaults to `None`. Size of sliding window for attention. If provided && is_causal, only attends to the last `sliding_window_size` tokens. If provided && !is_causal, attends to a window of size `sliding_window_size` centered at the current position.\\n\\n    Returns:\\n        AnyRankedTensor: The output tensor [batch x num_heads x seq_len x head_size].\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_mask\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"sliding_window_size\", \"type\": \"OptionalAttr<UI32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.scaled_dot_product_attention_decode\",\n    \"summary\": \"A version of scaled dot product attention specifically for decode.\",\n    \"description\": \"A version of scaled dot product attention specifically for decode.\\n        The implementation is Flash-Decode and it currently only supports MQA on decoding single token.\\n\\n        Args:\\n            query (AnyRankedTensor): The query tensor [1 x batch x num_heads x head_size]. Note that there is no sequence length dimension as this op is intended for processing a single query token.\\n            key (AnyRankedTensor): The key tensor [batch x num_kv_heads x seq_len x head_size].\\n            value (AnyRankedTensor): The value tensor [batch x num_kv_heads x seq_len x head_size].\\n            is_causal (bool, optional): Whether the attention is causal. Defaults to `true`.\\n            attention_mask (AnyRankedTensor, optional): The attention mask [batch x 1 x num_heads x seq_len].\\n            cur_pos_tensor (AnyRankedTensor): [batch] Tensor of integers of length batch.\\n            attention_sink (AnyRankedTensor, optional): The attention sink [num_heads, 32] (must be a single tile wide).\\n            output (AnyRankedTensor): The output DPS operand [1 x batch x num_heads x head_size].\\n            scale (float, optional): Defaults to `None`.\\n\\n        Returns:\\n            AnyRankedTensor: The output tensor [1 x batch x num_heads x head_size].\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_mask\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"cur_pos_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_sink\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F32Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.scatter\",\n    \"summary\": \"Scatter operation with simplified dimension attributes\",\n    \"description\": \"The `scatter` operation introduces torch style scatter in TTIR so that\\n    we can lower ttir scatter -> ttnn scatter.\\n\\n    Embeds the values of the source tensor into the input tensor at locations specified by the index tensor along the given dimension.\\n\\n    This is a simplified scatter operation that operates along a single dimension, making it more straightforward\\n    to use than the general scatter operation when you only need to scatter along one axis.\\n\\n    Parameters:\\n      - `input` (Tensor): The tensor being updated.\\n      - `index` (Tensor): Indices where values will be written to.\\n      - `source` (Tensor): The values to scatter into the input tensor.\\n      - `dim` (int32_t): The dimension along which to scatter.\\n      - `scatter_reduce_type` (Enum): The scatter reduce type to use (SUM, PROD, MIN, MAX, INVALID).\\n\\n\\n    Example:\\n    ```mlir\\n    // Scatter values along dimension 0\\n    %input = ... : tensor<8xf32>        // Input tensor\\n    %indices = ... : tensor<3xi32>      // Indices tensor\\n    %source = ... : tensor<3xf32>       // Source values to scatter\\n    %result = ttir.scatter_in_dim(%input, %indices, %source) {\\n        dim = 0, scatter_reduce_type = \\\"SUM\\\"\\n    } : tensor<8xf32>, tensor<3xi32>, tensor<3xf32> -> tensor<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"index\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I32Attr\" },\n      { \"name\": \"scatter_reduce_type\", \"type\": \"TTCore_ReduceTypeAttr{sum|mean|max|min|std|var|prod|invalid}\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sigmoid\",\n    \"summary\": \"Eltwise sigmoid.\",\n    \"description\": \"The `sigmoid` operation computes the sigmoid of each element in the input tensor.\\n\\n      For each element, it returns the sigmoid of the value.\\n\\n      Example:\\n      ```mlir\\n      // Compute sigmoid of all elements in %input\\n      %result = ttir.sigmoid(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.8391, 0.9641, 0.5793, 0.9899], ... ]\\n      ```\\n\\n      Mathematical definition: sigmoid(x) = 1 / (1 + exp(-x))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sign\",\n    \"summary\": \"Eltwise sign operation.\",\n    \"description\": \"The `sign` operation computes the sign of each element in the input tensor.\\n\\n      For each element, it returns:\\n      - 1 if the value is positive\\n      - 0 if the value is zero\\n      - -1 if the value is negative\\n\\n      This operation has the idempotence property, meaning that applying it multiple times\\n      produces the same result as applying it once: sign(sign(x)) = sign(x).\\n\\n      Example:\\n      ```mlir\\n      // Compute sign of all elements in %input\\n      %result = ttir.sign(%input) : (tensor<2x3xi32>) -> tensor<2x3xi32>\\n      // Input tensor:\\n      // [[3, -2, 0],\\n      //  [1, -4, 4]]\\n      // Output tensor:\\n      // [[1, -1, 0],\\n      //  [1, -1, 1]]\\n\\n      // Example with floating-point values\\n      %result = ttir.sign(%float_input) : (tensor<4xf32>) -> tensor<4xf32>\\n      // Input tensor:\\n      // [5.7, -0.0, 0.001, -3.14]\\n      // Output tensor:\\n      // [1.0, 0.0, 1.0, -1.0]\\n      ```\\n\\n      Mathematical definition: sign(x) = {\\n        1  if x > 0\\n        0  if x = 0\\n        -1 if x < 0\\n      }\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.silu\",\n    \"summary\": \"Elementwise SiLU (Sigmoid Linear Unit) operation.\",\n    \"description\": \"The `silu` operation computes the SiLU (Sigmoid Linear Unit) activation function of each element in the input tensor.\\n\\n    SiLU, also known as Swish, is defined as x * sigmoid(x). It combines the properties of both\\n    linear and sigmoid functions, providing smooth, non-monotonic activation that has shown good\\n    performance in deep learning applications.\\n\\n    Example:\\n    ```mlir\\n    // Compute SiLU of all elements in %input\\n    %result = ttir.silu(%input, %output) : tensor<4x4xf32>, tensor<4x4xf32> -> tensor<4x4xf32>\\n    // Input tensor:\\n    // [[-2.0, -1.0, 0.0, 1.0], ... ]\\n    // Output tensor:\\n    // [[-0.238, -0.269, 0.0, 0.731], ... ]\\n    ```\\n\\n    Mathematical definition: silu(x) = x * sigmoid(x) = x * (1 / (1 + exp(-x)))\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sin\",\n    \"summary\": \"Eltwise sin operation.\",\n    \"description\": \"The `sin` operation computes the sine of each element in the input tensor.\\n\\n      For each element, it returns the sine of the angle in radians.\\n\\n      Example:\\n      ```mlir\\n      // Compute sine of all elements in %input\\n      %result = ttir.sin(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.9601, 0.5403, -0.3, 4.5], ... ]\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.slice_dynamic\",\n    \"summary\": \"Tensor slice operation with dynamic parameters.\",\n    \"description\": \"The `slice_dynamic` operation extracts a sub-tensor (slice) from the input tensor across one or more dimensions.\\n\\n      This operation selects a subset of elements from the input tensor based on the specified begin, end, and\\n      step indices for each dimension. It's similar to Python's slicing notation `tensor[begin:end:step]` but\\n      extended to multiple dimensions. The `begins` and `ends` parameters are tensor inputs determined at runtime.\\n\\n      Example:\\n      ```mlir\\n      // Extract a 2x2 slice from a 4x4 tensor with dynamic begin/end indices\\n      %input = ... : tensor<4x4xf32>  // Input tensor with values:\\n                                      // [[1,  2,  3,  4],\\n                                      //  [5,  6,  7,  8],\\n                                      //  [9,  10, 11, 12],\\n                                      //  [13, 14, 15, 16]]\\n      %begins = ... : tensor<2xi32>   // Tensor with values [1, 1]\\n      %ends = ... : tensor<2xi32>     // Tensor with values [3, 3]\\n      %result = ttir.slice_dynamic(%input, %begins, %ends) <{\\n          step = [1, 1]     // Step size for each dimension\\n      }> : (tensor<4x4xf32>, tensor<2xi32>, tensor<2xi32>) -> tensor<2x2xf32>\\n      // Result:\\n      // [[6,  7],\\n      //  [10, 11]]\\n\\n      // Extract elements with a step of 2 using dynamic indices\\n      %input = ... : tensor<5xf32>    // Input tensor with values: [1, 2, 3, 4, 5]\\n      %begins = ... : tensor<1xi32>   // Tensor with values [0]\\n      %ends = ... : tensor<1xi32>     // Tensor with values [5]\\n      %result = ttir.slice_dynamic(%input, %begins, %ends) <{\\n          step = [2]        // Step size\\n      }> : (tensor<5xf32>, tensor<1xi32>, tensor<1xi32>) -> tensor<3xf32>\\n      // Result: [1, 3, 5]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to slice.\\n      - `begins` (Tensor): The starting indices for the slice in each dimension.\\n      - `ends` (Tensor): The ending indices (exclusive) for the slice in each dimension.\\n\\n      Attributes:\\n      - `step` (Array of Integer): The step sizes for the slice in each dimension.\\n\\n      Outputs:\\n      - `result` (Tensor): The sliced tensor.\\n\\n      Note: The `begins` and `ends` tensors must have the same length as the rank of the input tensor.\\n      The output tensor shape may contain dynamic dimensions when slice parameters are runtime-determined.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"begins\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"ends\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"step\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.slice_static\",\n    \"summary\": \"Tensor slice operation with constant parameters.\",\n    \"description\": \"The `slice_static` operation extracts a sub-tensor (slice) from the input tensor across one or more dimensions.\\n\\n      This operation selects a subset of elements from the input tensor based on the specified begin, end, and\\n      step indices for each dimension. It's similar to Python's slicing notation `tensor[begin:end:step]` but\\n      extended to multiple dimensions. The `begins` and `ends` parameters are attributes with fixed values.\\n\\n      Example:\\n      ```mlir\\n      // Extract a 2x2 slice from a 4x4 tensor\\n      %input = ... : tensor<4x4xf32>  // Input tensor with values:\\n                                      // [[1,  2,  3,  4],\\n                                      //  [5,  6,  7,  8],\\n                                      //  [9,  10, 11, 12],\\n                                      //  [13, 14, 15, 16]]\\n      %result = ttir.slice_static(%input) {\\n          begins = [1, 1],  // Start indices for each dimension\\n          ends = [3, 3],    // End indices for each dimension (exclusive)\\n          step = [1, 1]     // Step size for each dimension\\n      } : (tensor<4x4xf32>) -> tensor<2x2xf32>\\n      // Result:\\n      // [[6,  7],\\n      //  [10, 11]]\\n\\n      // Extract elements with a step of 2\\n      %input = ... : tensor<5xf32>  // Input tensor with values: [1, 2, 3, 4, 5]\\n      %result = ttir.slice_static(%input) {\\n          begins = [0],  // Start index\\n          ends = [5],    // End index (exclusive)\\n          step = [2]     // Step size\\n      } : (tensor<5xf32>) -> tensor<3xf32>\\n      // Result: [1, 3, 5]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to slice.\\n\\n      Attributes:\\n      - `begins` (Array of Integer): The starting indices for the slice in each dimension.\\n      - `ends` (Array of Integer): The ending indices (exclusive) for the slice in each dimension.\\n      - `step` (Array of Integer): The step sizes for the slice in each dimension.\\n\\n      Output:\\n      - `result` (Tensor): The sliced tensor.\\n\\n      Note: The shape of the output tensor is determined by the slice parameters. For each dimension i,\\n      the output size is calculated as `ceil((ends[i] - begins[i]) / step[i])`. The `begins`, `ends`, and\\n      `step` arrays must have the same length as the rank of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begins\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"ends\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"step\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.softmax\",\n    \"summary\": \"Softmax normalization operation.\",\n    \"description\": \"The `softmax` operation applies the softmax function along a specified dimension of the input tensor.\\n\\n      The softmax function transforms each element of the input tensor to a value between 0 and 1, such that\\n      the sum of all elements along the specified dimension equals 1. This is commonly used to convert a vector\\n      of real numbers into a probability distribution.\\n\\n      The softmax function is defined as:\\n      softmax(x_i) = exp(x_i) / sum(exp(x_j)) for all j in the specified dimension\\n\\n      Example:\\n      ```mlir\\n      // Softmax along dimension 1\\n      %input = ... : tensor<2x3xf32>\\n      %result = ttir.softmax(%input) {dimension = 1 : i32} : (tensor<2x3xf32>) -> tensor<2x3xf32>\\n      // Input tensor:\\n      // [[1.0, 2.0, 3.0],\\n      //  [4.0, 1.0, 2.0]]\\n      // Output tensor (approximate values):\\n      // [[0.09, 0.24, 0.67],  // sum = 1.0\\n      //  [0.71, 0.09, 0.20]]  // sum = 1.0\\n      ```\\n\\n      Note: For numerical stability, the implementation typically subtracts the maximum value in each slice\\n      before applying the exponential function.\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `dimension` (Integer): The dimension along which to apply the softmax function.\\n      - `numericStable` (Boolean, default=false): Whether to use numerically stable computation.\\n\\n      Output:\\n      - `result` (Tensor): The tensor after applying the softmax function.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"SI32Attr\" },\n      { \"name\": \"numericStable\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sort\",\n    \"summary\": \"Sort operation.\",\n    \"description\": \"Sorts elements of a tensor along a given dimension.\\n\\n    Input:\\n      - input: AnyRankedTensor\\n\\n    Attributes:\\n      - dim (int32): The dimension to sort along (default: -1, the last dim).\\n      - descending (bool): If True, sort in descending order (default: False).\\n      - stable (bool): If True, ensures stable sort (equal elements keep order).\\n\\n    Returns a tuple:\\n      - values: the sorted tensor.\\n      - indices: the original indices of the sorted values.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"DefaultValuedAttr<SI32Attr, -1>\" },\n      { \"name\": \"descending\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"stable\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sparse_matmul\",\n    \"summary\": \"Sparse block matrix multiplication with sparsity mask.\",\n    \"description\": \"The `sparse_matmul` operation performs batched matrix multiplication where\\n      computation is selectively skipped for blocks marked as zero in the sparsity\\n      tensor. Input `b` is organized as a collection of weight matrices indexed by\\n      a block dimension (dim 1), and the sparsity tensor controls which blocks\\n      participate in the computation.\\n\\n      The operation supports three sparsity modes that determine which input\\n      carries the block structure:\\n\\n      Inputs:\\n      - `a` (Tensor): The first input tensor (activations or sparse input).\\n      - `b` (Tensor): The second input tensor, always [1, num_blocks, K, N].\\n      - `sparsity` (Tensor): 4D binary mask indicating active blocks.\\n\\n      Attributes:\\n      - `is_input_a_sparse` (Boolean, default=false): Whether `a` has block structure.\\n      - `is_input_b_sparse` (Boolean, default=true): Whether `b` has block structure.\\n      - `nnz` (Optional Integer): Number of non-zero blocks per row. If 0 or absent,\\n        inferred at runtime.\\n\\n      Supported Modes:\\n      - is_input_a_sparse=false, is_input_b_sparse=true (column-parallel):\\n        a: [A, B, M, K], b: [1, E, K, N], sparsity: [A, B, 1, E]\\n        -> output: [A, B, 1, E, M, N]\\n      - is_input_a_sparse=true, is_input_b_sparse=false (row-parallel):\\n        a: [A, E, M, K], b: [1, E, K, N], sparsity: [1, 1, A, E]\\n        -> output: [A, E, M, N]\\n      - is_input_a_sparse=true, is_input_b_sparse=true (both sparse):\\n        a: [1, E, M, K], b: [1, E, K, N], sparsity: [1, 1, 1, E]\\n        -> output: [1, E, M, N]\\n\\n      Example (Mixture of Experts gate/up projection):\\n      ```mlir\\n      %result = \\\"ttir.sparse_matmul\\\"(%activations, %expert_weights, %sparsity) <{\\n          is_input_a_sparse = false, is_input_b_sparse = true, nnz = 2\\n      }> : (tensor<2x4x32x2880xbf16>, tensor<1x4x2880x5760xbf16>,\\n            tensor<2x4x1x4xbf16>) -> tensor<2x4x1x4x32x5760xbf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"b\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"sparsity\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_input_a_sparse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"is_input_b_sparse\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"nnz\", \"type\": \"OptionalAttr<I64Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.split_query_key_value_and_split_heads\",\n    \"summary\": \"Split query, key, values and split heads op used in attention layer.\",\n    \"description\": \"Splits input_tensor of shape [batch_size, sequence_size, 3 * hidden_size] into 3 tensors (Query, Key, Value) of shape [batch_size, sequence_size, hidden_size]. Then, reshapes and permutes the output tensors, to make them ready for computing attention scores.\\n      If kv_input_tensor is passed in, then input_tensor of shape [batch_size, sequence_size, hidden_size] is only used for Query, and kv_input_tensor of shape [batch_size, sequence_size, 2 * hidden_size] is used for Key and Value.\\n      For the sharded implementation, the input query, key and value are expected to be concatenated such that the heads are interleaved (q1 k1 v1…qn kn vn).\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"kv_input_tensor\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_heads\", \"type\": \"UI32Attr\" },\n      { \"name\": \"num_kv_heads\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"transpose_key\", \"type\": \"BoolAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sqrt\",\n    \"summary\": \"Eltwise square root.\",\n    \"description\": \"The `sqrt` operation computes the square root of each element in the input tensor.\\n\\n      For each element, it returns the square root of the value.\\n\\n      Example:\\n      ```mlir\\n      // Compute square root of all elements in %input\\n      %result = ttir.sqrt(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.5882, 0.5, -3.3333, 0.2173], ... ]\\n      ```\\n\\n      Mathematical definition: sqrt(x) = √x\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.squeeze\",\n    \"summary\": \"Tensor dimension squeezing operation.\",\n    \"description\": \"The `squeeze` operation removes a dimension of size 1 from the shape of a tensor.\\n\\n      This operation is commonly used to eliminate unnecessary singleton dimensions from a tensor's shape.\\n      It specifies which dimension to remove using the `dim` attribute. The specified dimension must have size 1.\\n\\n      Example:\\n      ```mlir\\n      // Squeeze dimension 0 from a tensor of shape [1, 3, 4]\\n      %input = ... : tensor<1x3x4xf32>  // Input tensor with shape [1, 3, 4]\\n      %result = ttir.squeeze(%input) {\\n          dim = 0 : i32  // Dimension to squeeze\\n      } : (tensor<1x3x4xf32>) -> tensor<3x4xf32>\\n      // Result: tensor with shape [3, 4]\\n\\n      // Squeeze dimension 1 from a tensor of shape [2, 1, 3]\\n      %input = ... : tensor<2x1x3xf32>  // Input tensor with shape [2, 1, 3]\\n      %result = ttir.squeeze(%input) {\\n          dim = 1 : i32  // Dimension to squeeze\\n      } : (tensor<2x1x3xf32>) -> tensor<2x3xf32>\\n      // Result: tensor with shape [2, 3]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to squeeze.\\n\\n      Attributes:\\n      - `dim` (Integer): The dimension to squeeze.\\n\\n      Output:\\n      - `result` (Tensor): The squeezed tensor.\\n\\n      Note: The specified dimension must have size 1. The shape of the output tensor is the same as the\\n      input tensor with the specified dimension removed. For example, squeezing dimension 1 of a tensor\\n      with shape [2, 1, 3] results in a tensor with shape [2, 3].\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.subtract\",\n    \"summary\": \"Elementwise subtract operation.\",\n    \"description\": \"The `subtract` operation performs an elementwise subtraction between two tensors.\\n\\n      For each pair of corresponding elements, it subtracts the element in the second tensor from\\n      the element in the first tensor and places the result in the output tensor.\\n\\n      Example:\\n      ```mlir\\n      // Subtraction operation\\n      %result = ttir.subtract(%lhs, %rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>\\n      // Input tensors:\\n      // %lhs: [10, 20, 30]\\n      // %rhs: [1, 2, 3]\\n      // Output tensor:\\n      // [9, 18, 27]\\n\\n      // Example with floating point values\\n      %result = ttir.subtract(%float_lhs, %float_rhs) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>\\n      // Input tensors:\\n      // %float_lhs: [3.5, 0.0, -1.2]\\n      // %float_rhs: [1.5, 2.0, -3.2]\\n      // Output tensor:\\n      // [2.0, -2.0, 2.0]\\n      ```\\n\\n      Note: The data type of the output tensor matches the data type of the input tensors.\\n\\n      Mathematical definition: subtract(x, y) = x - y\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.sum\",\n    \"summary\": \"Sum reduction operation.\",\n    \"description\": \"The `sum` operation computes the sum of elements along specified dimensions of the input tensor.\\n\\n      This operation reduces the input tensor by computing the sum of all elements along the dimensions\\n      specified in `dim_arg`. If `dim_arg` is not provided, the sum is computed over all dimensions,\\n      resulting in a scalar value. If `keep_dim` is set to true, the reduced dimensions are retained\\n      with a size of 1.\\n\\n      Example:\\n      ```mlir\\n      // Sum along dimension 1\\n      %input = ... : tensor<2x3xf32>\\n      %result = ttir.sum(%input) {keep_dim = false, dim_arg = [1: i32]} : (tensor<2x3xf32>) -> tensor<2xf32>\\n      // Input tensor:\\n      // [[1.0, 2.0, 3.0],\\n      //  [4.0, 5.0, 6.0]]\\n      // Output tensor:\\n      // [6.0, 15.0]  // Sum of each row\\n\\n      // Sum along dimension 0\\n      %input = ... : tensor<2x3xf32>\\n      %result = ttir.sum(%input) {keep_dim = false, dim_arg = [0: i32]} : (tensor<2x3xf32>) -> tensor<3xf32>\\n      // Input tensor:\\n      // [[1.0, 2.0, 3.0],\\n      //  [4.0, 5.0, 6.0]]\\n      // Output tensor:\\n      // [5.0, 7.0, 9.0]  // Sum of each column\\n\\n      // Sum over all dimensions\\n      %input = ... : tensor<2x3xf32>\\n      %result = ttir.sum(%input) {keep_dim = false} : (tensor<2x3xf32>) -> tensor<f32>\\n      // Input tensor:\\n      // [[1.0, 2.0, 3.0],\\n      //  [4.0, 5.0, 6.0]]\\n      // Output tensor:\\n      // 21.0  // Sum of all elements\\n      ```\\n\\n      Mathematical definition: sum(x, dim) = ∑ x[i] for all i in dimension dim\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `keep_dim` (Bool): Whether to keep the reduced dimensions or not.\\n      - `dim_arg` (Array of Int32): Dimensions to reduce along.\\n\\n      Output:\\n      - `result` (Tensor): The result tensor after applying the reduction.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.tan\",\n    \"summary\": \"Elementwise tan operation.\",\n    \"description\": \"The `tan` operation computes the tangent of each element in the input tensor.\\n\\n      For each element, it returns the tangent of the angle in radians.\\n\\n      Example:\\n      ```mlir\\n      // Compute tangent of all elements in %input\\n      %result = ttir.tan(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.9601, 0.5403, -0.3, 4.5], ... ]\\n      ```\\n\\n      Mathematical definition: tan(x) = sin(x) / cos(x)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.tanh\",\n    \"summary\": \"Elementwise hyperbolic tangent operation.\",\n    \"description\": \"The `tanh` operation computes the hyperbolic tangent of each element in the input tensor.\\n\\n      For each element, it returns the hyperbolic tangent of the value.\\n\\n      Example:\\n      ```mlir\\n      // Compute hyperbolic tangent of all elements in %input\\n      %result = ttir.tanh(%input) : (tensor<4x4xf32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1.7, 2.0, -0.3, 4.5], ... ]\\n      // Output tensor:\\n      // [[0.9601, 0.5403, -0.3, 4.5], ... ]\\n      ```\\n\\n      Mathematical definition: tanh(x) = (e^x - e^-x) / (e^x + e^-x)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.to_layout\",\n    \"summary\": \"Layout op.\",\n    \"description\": \"ToLayout operation, transition tensors from one layout to another.  Some examples include:\\n        - Transitioning between different memory spaces, e.g. DRAM to L1.\\n        - Transitioning between different data types, e.g. f32 to f16.\\n        - Transitioning between different tile sizes, e.g. 1x16 to 32x32\\n        - Transitioning between different tensor sharding\\n        - Some combination of the above\\n\\n      ```llvm\\n      #layout = #ttcore.metal_layout<8192x128x1, undef, <1x1>, memref<64x128xf32, #system>>\\n      #layout1 = #ttcore.metal_layout<8192x128x1, undef, <1x1>, memref<64x128xf32, #l1_>>\\n      %1 = \\\"ttir.to_layout\\\"(%arg0, %0) : (tensor<64x128xf32, #layout>, tensor<64x128xf32, #layout1>) -> tensor<64x128xf32, #layout1>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensorOrMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<TTCore_MetalLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$input `,` $output `:` type($input) `into` type($output) (`hostInfo` `=` $layout^)? attr-dict (`->` type($results)^)?\"\n  },\n  {\n    \"name\": \"ttir.topk\",\n    \"summary\": \"Top-K selection operation.\",\n    \"description\": \"Returns the `k` largest or `k` smallest elements of the `input_tensor` along a given dimension `dim`.\\n    If `dim` is not provided, the last dimension of the input_tensor is used.\\n    If `largest` is True, the `k` largest elements are returned. Otherwise, the `k` smallest elements are returned.\\n    The boolean option `sorted` if True, will make sure that the returned `k` elements are sorted.\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I32Attr\" },\n      { \"name\": \"dim\", \"type\": \"DefaultValuedAttr<I32Attr, -1>\" },\n      { \"name\": \"largest\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.transpose\",\n    \"summary\": \"Tensor transpose operation.\",\n    \"description\": \"The `transpose` operation swaps two dimensions of a tensor.\\n\\n      This operation exchanges the positions of two specified dimensions in the input tensor,\\n      effectively transposing those dimensions. The shape of the output tensor is the same as\\n      the input tensor, except that the dimensions specified by `dim0` and `dim1` are swapped.\\n\\n      Example:\\n      ```mlir\\n      // Transpose dimensions 0 and 1\\n      %input = ... : tensor<2x3x4xf32>\\n      %result = ttir.transpose(%input) {dim0 = 0 : i32, dim1 = 1 : i32} : (tensor<2x3x4xf32>) -> tensor<3x2x4xf32>\\n      // Input tensor shape: [2, 3, 4]\\n      // Output tensor shape: [3, 2, 4]\\n\\n      // Transpose dimensions 1 and 2\\n      %input = ... : tensor<2x3x4xf32>\\n      %result = ttir.transpose(%input) {dim0 = 1 : i32, dim1 = 2 : i32} : (tensor<2x3x4xf32>) -> tensor<2x4x3xf32>\\n      // Input tensor shape: [2, 3, 4]\\n      // Output tensor shape: [2, 4, 3]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n      Attributes:\\n      - `dim0` (Integer): The first dimension to swap.\\n      - `dim1` (Integer): The second dimension to swap.\\n\\n      Output:\\n      - `result` (Tensor): The transposed tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim0\", \"type\": \"SI32Attr\" },\n      { \"name\": \"dim1\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.ttnn_metal_layout_cast\",\n    \"summary\": \"Cast TTNN layout-encoded tensor to/from TTCore metal layout-encoded tensor\",\n    \"description\": \"Purely representational op that reinterprets a tensor's layout encoding from `#ttnn.ttnn_layout<...>`\\n    to/from `#ttcore.metal_layout<...>` without modifying the underlying data.\\n\\n    Pre-bufferization, the input and output must be a RankedTensorType where one holds a\\n    `ttnn::TTNNLayoutAttr` and the other, a `ttcore::MetalLayoutAttr`. Post bufferization,\\n    the tensor encoded with a `ttcore::MetalLayoutAttr` is bufferized to a memref.\\n\\n    Examples:\\n    ```\\n    %cast_to_metal = ttir.ttnn_metal_layout_cast %arg0\\n                      : tensor<32x32xf32, #ttnn.ttnn_layout<...>>\\n                    -> tensor<32x32xf32, #ttcore.metal_layout<...>>\\n\\n    %cast_to_metal_bufferized = ttir.ttnn_metal_layout_cast %arg0\\n                            : tensor<32x32xf32, #ttnn.ttnn_layout<...>>\\n                          -> memref<32x32xf32, ...>\\n\\n    %cast_to_ttnn = ttir.ttnn_metal_layout_cast %arg0\\n                    : tensor<32x32xf32, #ttcore.metal_layout<...>>\\n                  -> tensor<32x32xf32, #ttnn.ttnn_layout<...>>\\n\\n    %cast_to_ttnn_bufferized = ttir.ttnn_metal_layout_cast %arg0\\n                            : memref<32x32xf32, ...>\\n                          -> tensor<32x32xf32, #ttnn.ttnn_layout<...>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensorOrMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"virtual_grid_inverse_mapping\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"virtual_grid_forward_mapping\", \"type\": \"OptionalAttr<AffineMapAttr>\" }\n    ],\n    \"assemblyFormat\": \"$input attr-dict `:` type($input) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttir.typecast\",\n    \"summary\": \"Elementwise type casting operation.\",\n    \"description\": \"The `typecast` operation converts each element in the input tensor to a different data type.\\n\\n      This operation performs element-wise type conversion, such as converting from integers to\\n      floating-point values or between different floating-point precisions. The conversion follows\\n      the standard type conversion rules for the target platform.\\n\\n      Example:\\n      ```mlir\\n      // Cast from int32 to float32\\n      %result = ttir.typecast(%input) : (tensor<4x4xi32>) -> tensor<4x4xf32>\\n      // Input tensor:\\n      // [[1, 2, -3, 4], ... ]\\n      // Output tensor:\\n      // [[1.0, 2.0, -3.0, 4.0], ... ]\\n\\n      // Cast from float32 to int32\\n      %result = ttir.typecast(%float_input) : (tensor<3xf32>) -> tensor<3xi32>\\n      // Input tensor:\\n      // [1.7, -2.3, 3.0]\\n      // Output tensor:\\n      // [1, -2, 3]  // Note: truncation, not rounding\\n\\n      // Cast from float32 to float64 (higher precision)\\n      %result = ttir.typecast(%f32_input) : (tensor<2xf32>) -> tensor<2xf64>\\n      // Input tensor:\\n      // [3.14159, 2.71828]\\n      // Output tensor:\\n      // [3.14159, 2.71828]  // Same values but with higher precision\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"conservative_folding\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.unsqueeze\",\n    \"summary\": \"Tensor dimension insertion operation.\",\n    \"description\": \"The `unsqueeze` operation inserts a dimension of size 1 into the shape of a tensor.\\n\\n      This operation is the inverse of the `squeeze` operation and is commonly used to add a singleton dimension\\n      to a tensor's shape. It specifies which position to insert the new dimension using the `dim` attribute.\\n\\n      Example:\\n      ```mlir\\n      // Insert a dimension at position 0 of a tensor with shape [3, 4]\\n      %input = ... : tensor<3x4xf32>  // Input tensor with shape [3, 4]\\n      %result = ttir.unsqueeze(%input) {\\n          dim = 0 : i32  // Position to insert the new dimension\\n      } : (tensor<3x4xf32>) -> tensor<1x3x4xf32>\\n      // Result: tensor with shape [1, 3, 4]\\n\\n      // Insert a dimension at position 1 of a tensor with shape [2, 3]\\n      %input = ... : tensor<2x3xf32>  // Input tensor with shape [2, 3]\\n      %result = ttir.unsqueeze(%input) {\\n          dim = 1 : i32  // Position to insert the new dimension\\n      } : (tensor<2x3xf32>) -> tensor<2x1x3xf32>\\n      // Result: tensor with shape [2, 1, 3]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to unsqueeze.\\n\\n      Attributes:\\n      - `dim` (Integer): The position to insert the new dimension.\\n\\n      Output:\\n      - `result` (Tensor): The unsqueezed tensor.\\n\\n      Note: The shape of the output tensor is the same as the input tensor with a new dimension of size 1\\n      inserted at the specified position. For example, unsqueezing at position 1 of a tensor with shape [2, 3]\\n      results in a tensor with shape [2, 1, 3].\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.update_cache\",\n    \"summary\": \"Cache update operation.\",\n    \"description\": \"The `update_cache` operation updates a cache tensor with values from an input tensor at specific indices.\\n\\n    This operation is commonly used in sequence models like transformers to update a key-value cache\\n    with new token information. It takes a cache tensor, an input tensor, and update indices, and\\n    updates the cache at the specified positions.\\n\\n    Example:\\n    ```mlir\\n    // Update cache at specific indices\\n    %cache = ... : tensor<2x16x64xf32>  // Batch size 2, sequence length 16, hidden dim 64\\n    %input = ... : tensor<2x1x64xf32>   // New token embeddings\\n    %update_index = ... : tensor<1xi32> // Update at position [15]\\n    %result = ttir.update_cache(%cache, %input, %update_index) {batch_offset = 0 : i32} :\\n        tensor<2x16x64xf32>, tensor<2x1x64xf32>, tensor<1xi32> -> tensor<2x16x64xf32>\\n    // The cache tensor is updated at position 15 for both batches with the values from input\\n    ```\\n\\n    Inputs:\\n    - `cache` (Tensor): The cache tensor to be updated.\\n    - `input` (Tensor): The input tensor containing new values.\\n    - `update_index` (Tensor): Indices specifying where to update the cache.\\n\\n    Attributes:\\n    - `batch_offset` (Integer): Offset in the batch dimension.\\n\\n    Output:\\n    - `result` (Tensor): The updated cache tensor.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"update_index\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_offset\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.upsample2d\",\n    \"summary\": \"Upsample 2D operation.\",\n    \"description\": \"The `upsample2d` operation increases the spatial dimensions (height and width) of an input tensor.\\n\\n      This operation is commonly used in neural networks to increase the spatial resolution of feature maps.\\n      It supports different upsampling algorithms such as \\\"nearest\\\" and \\\"bilinear\\\" interpolation.\\n      The input tensor is assumed to be in NHWC format (batch, height, width, channels).\\n\\n      Example:\\n      ```mlir\\n      // Upsample a tensor with different scale factors for height and width\\n      %input = ... : tensor<10x64x32x3xbf16>  // Input tensor: [batch=10, height=64, width=32, channels=3]\\n      %result = ttir.upsample2d(%input) {\\n          scale_factor = [2, 4],  // Scale height by 2, width by 4\\n          mode = \\\"bilinear\\\"       // Use bilinear interpolation\\n      } : (tensor<10x64x32x3xbf16>) -> tensor<10x128x128x3xbf16>\\n      // Result: tensor with shape [10,128,128,3]\\n\\n      // Upsample with the same scale factor for both dimensions\\n      %input = ... : tensor<1x32x32x16xf32>  // Input tensor\\n      %result = ttir.upsample2d(%input) {\\n          scale_factor = 2,     // Scale both height and width by 2\\n          mode = \\\"nearest\\\"      // Use nearest neighbor interpolation\\n      } : (tensor<1x32x32x16xf32>) -> tensor<1x64x64x16xf32>\\n      // Result: tensor with shape [1,64,64,16]\\n      ```\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to upsample, in NHWC format.\\n\\n      Attributes:\\n      - `scale_factor` (Integer or Array of Integer): The scale factor for upsampling in height and width dimensions.\\n        If a single integer is provided, it's used for both dimensions. If an array is provided, the first value\\n        is used for height and the second for width.\\n      - `mode` (String, default=\\\"nearest\\\"): The upsampling algorithm to use. Currently supported values are\\n        \\\"nearest\\\" for nearest neighbor interpolation and \\\"bilinear\\\" for bilinear interpolation.\\n\\n      Output:\\n      - `result` (Tensor): The upsampled tensor.\\n\\n      Note: The output height is calculated as input_height * scale_factor[0] and the output width as\\n      input_width * scale_factor[1]. The batch and channel dimensions remain unchanged.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_factor\", \"type\": \"AnyAttrOf<[SI32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"nearest\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.where\",\n    \"summary\": \"Elementwise conditional selection operation based on a predicate.\",\n    \"description\": \"The `where` operation performs element-wise conditional selection based on a predicate.\\n\\n      For each element position, it selects between two values based on a boolean condition in first tensor:\\n      - If the condition is true (non-zero), it selects the corresponding element from the second tensor\\n      - If the condition is false (zero), it selects the corresponding element from the third tensor\\n\\n      This operation supports broadcasting, allowing inputs of different shapes to be combined\\n      according to standard broadcasting rules.\\n\\n      Example:\\n      ```mlir\\n      // Select elements from %true_values where %condition is true,\\n      // otherwise select from %false_values\\n      %result = ttir.where(%condition, %true_values, %false_values) : (tensor<4x4xi1>, tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>\\n\\n      // With broadcasting (condition is a scalar)\\n      %result = ttir.where(%scalar_condition, %true_values, %false_values) : (tensor<1xi1>, tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>\\n      ```\\n\\n      This operation is equivalent to the ternary conditional operator (`condition ? true_value : false_value`)\\n      in many programming languages, applied elementwise across tensors.\",\n    \"operands\": [\n      { \"name\": \"first\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"second\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"third\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttir.zeros\",\n    \"summary\": \"Creates a tensor filled with zeros.\",\n    \"description\": \"The `zeros` operation creates a tensor filled with zeros of the specified shape.\\n\\n    This operation is commonly used to initialize tensors with zero values. It takes a shape attribute\\n    and produces a tensor of that shape with all elements set to zero.\\n\\n    Example:\\n    ```mlir\\n    // Create a 3D tensor of zeros with shape [64, 28, 28]\\n    %result = ttir.zeros() {\\n        shape = [64, 28, 28]\\n    } : () -> tensor<64x28x28xbf16>\\n    // Result: A tensor of shape [64, 28, 28] filled with zeros\\n\\n    // Create a 2D tensor of zeros with shape [3, 4]\\n    %result = ttir.zeros() {\\n        shape = [3, 4]\\n    } : () -> tensor<3x4xf32>\\n    // Result: [[0.0, 0.0, 0.0, 0.0],\\n    //          [0.0, 0.0, 0.0, 0.0],\\n    //          [0.0, 0.0, 0.0, 0.0]]\\n    ```\\n\\n    Attributes:\\n    - `shape` (Array of Integer): The shape of the tensor to create.\\n\\n    Output:\\n    - `result` (Tensor): The tensor filled with zeros.\\n\\n    Note: The element type of the result tensor is determined by the return type specified in the operation.\\n    This operation is useful for initializing tensors before filling them with computed values or as a\\n    starting point for accumulation operations.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"DenseI32ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttkernel.abs_tile\",\n    \"summary\": \"Absolute value tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of absolute value operation\\n      DST[dst0_index] <- abs(DST[dst0_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.abs_tile_init\",\n    \"summary\": \"Init function for abs_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before abs_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.abs_tile_int32\",\n    \"summary\": \"Absolute value i32 tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of absolute value operation\\n      DST[dst0_index] <- abs(DST[dst0_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_binary_tile\",\n    \"summary\": \"Addition operation between two tiles\",\n    \"description\": \"Performs element-wise computation of addition operation\\n      DST[odst_index] <- DST[dst0_index] + DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_binary_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before add_binary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_int_tile\",\n    \"summary\": \"Integer addition operation between two tiles\",\n    \"description\": \"Performs element-wise computation of integer addition operation\\n      DST[odst_index] <- DST[dst0_index] + DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      Supported data formats are: Int32, UInt32, UInt16.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_int_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before add_int_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_tiles\",\n    \"summary\": \"Add operation\",\n    \"description\": \"Performs element-wise addition C=A+B of tiles in two CBs at given indices\\n      and writes the result to the DST register at index dst_tile_index. The DST\\n      register buffer must be in acquired state via *tile_regs_acquire* call. This call\\n      is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in0_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"in1_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `,` $in0_tile_index `,` $in1_tile_index `,` $dst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_tiles_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before add_tiles.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.add_unary_tile\",\n    \"summary\": \"Add by scalar operation\",\n    \"description\": \"Performs element-wise addition of a tile by a scalar value.\\n      DST[dst0_index] <- DST[dst0_index] + scalar\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_bitwise_tile_init\",\n    \"summary\": \"Init function for binary bitwise operations (AND, OR, XOR). Refer to documentation for any init function.\",\n    \"description\": \"Must be run before bitwise_and_binary_tile, bitwise_or_binary_tile, or bitwise_xor_binary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_dest_reuse_tiles\",\n    \"summary\": \"Binary op with one operand from DST\",\n    \"description\": \"Performs element-wise binary op where one operand comes from DST and one\\n      from a CB. If reuse_type is dest_to_srca, DST[dst_tile_index] is loaded\\n      to SRCA and CB tile is loaded to SRCB. If dest_to_srcb, the opposite.\\n      Result is written back to DST[dst_tile_index].\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      `eltwise_binary_type` specifies the operation (add/sub/mul).\",\n    \"operands\": [\n      { \"name\": \"in_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eltwise_binary_type\", \"type\": \"TTKernel_EltwiseBinaryTypeAttr{add|sub|mul}\" },\n      { \"name\": \"reuse_type\", \"type\": \"TTKernel_BinaryDestReuseTypeAttr{dest_to_srca|dest_to_srcb}\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_cb `,` $in_tile_index `,` $dst_tile_index `,` $eltwise_binary_type `,` $reuse_type `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_dest_reuse_tiles_init\",\n    \"summary\": \"Init for binary op with dest reuse\",\n    \"description\": \"Init function for binary_dest_reuse_tiles operation.\\n      Must be run before binary_dest_reuse_tiles.\\n      `eltwise_binary_type` specifies the operation (add/sub/mul).\\n      `reuse_type` specifies which source register gets the DST operand.\",\n    \"operands\": [\n      { \"name\": \"in_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"eltwise_binary_type\", \"type\": \"TTKernel_EltwiseBinaryTypeAttr{add|sub|mul}\" },\n      { \"name\": \"reuse_type\", \"type\": \"TTKernel_BinaryDestReuseTypeAttr{dest_to_srca|dest_to_srcb}\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_cb `,` $eltwise_binary_type `,` $reuse_type `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_max_int32_tile\",\n    \"summary\": \"Integer elementwise maximum operation between two tiles\",\n    \"description\": \"Performs element-wise computation of integer maximum operation\\n      DST[odst_index] <- max(DST[dst0_index], DST[dst1_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *acquire_dst* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_max_int32_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before binary_max_int32_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_max_tile\",\n    \"summary\": \"Elementwise maximum operation\",\n    \"description\": \"Performs element-wise computation of maximum operation\\n      DST[odst_index] <- max(DST[dst0_index], DST[dst1_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *acquire_dst* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_max_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before binary_max_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_min_int32_tile\",\n    \"summary\": \"Integer elementwise minimum operation between two tiles\",\n    \"description\": \"Performs element-wise computation of integer minimum operation\\n      DST[odst_index] <- min(DST[dst0_index], DST[dst1_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *acquire_dst* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_min_int32_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before binary_min_int32_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_min_tile\",\n    \"summary\": \"Elementwise minimum operation\",\n    \"description\": \"Performs element-wise computation of minimum operation\\n      DST[odst_index] <- min(DST[dst0_index], DST[dst1_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *acquire_dst* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_min_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before binary_min_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binary_op_init_common\",\n    \"summary\": \"Init function for all binary ops\",\n    \"description\": \"Followed by the specific init required with an opcode (binrary_op_specific_init).\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"out_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `,` $out_cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.binop_with_scalar_tile_init\",\n    \"summary\": \"Init function for binary operations with scalar tile operations.\",\n    \"description\": \"Must be run before binary operations with scalar like mul_unary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.bitwise_and_binary_tile\",\n    \"summary\": \"Bitwise AND operation between two tiles\",\n    \"description\": \"Performs element-wise computation of bitwise AND operation\\n      DST[odst_index] <- DST[dst0_index] & DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.bitwise_not_tile\",\n    \"summary\": \"Bitwise Not operation on tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of sign operation\\n      DST[tile_index] <- bitwise_not(DST[tile_index])\\n      on DST register operands.\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.bitwise_not_tile_init\",\n    \"summary\": \"Init function for bitwise_not_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before bitwise_not_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.bitwise_or_binary_tile\",\n    \"summary\": \"Bitwise OR operation between two tiles\",\n    \"description\": \"Performs element-wise computation of bitwise OR operation\\n      DST[odst_index] <- DST[dst0_index] | DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.bitwise_xor_binary_tile\",\n    \"summary\": \"Bitwise XOR operation between two tiles\",\n    \"description\": \"Performs element-wise computation of bitwise XOR operation\\n      DST[odst_index] <- DST[dst0_index] ^ DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.cb_pop_front\",\n    \"summary\": \"CBPopFront call.\",\n    \"description\": \"CBPopFront operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numPages\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `,` $numPages `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.cb_port\",\n    \"summary\": \"Get a CB by its hardware port index.\",\n    \"description\": \"Produces a CB value for the given hardware port index.  Unlike\\n      `get_compile_time_arg_val`, the port is resolved directly at\\n      code-generation time rather than going through the compile-time\\n      argument indirection.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"port\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`(` $port `)` attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"ttkernel.cb_push_back\",\n    \"summary\": \"CBPushBack call.\",\n    \"description\": \"CBPushBack operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numPages\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `,` $numPages `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.cb_reserve_back\",\n    \"summary\": \"CBReserveBack call.\",\n    \"description\": \"CBReserveBack operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numPages\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `,` $numPages `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.cb_wait_front\",\n    \"summary\": \"CBWaitFront call.\",\n    \"description\": \"CBWaitFront operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numPages\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `,` $numPages `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.ceil_tile\",\n    \"summary\": \"Ceil tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of ceil operation\\n      DST[dst0_index] <- ceil(DST[dst0_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.clamp_tile\",\n    \"summary\": \"Clamp tile elements to scalar range\",\n    \"description\": \"Performs element-wise clamping of tile values to the range [min, max]\\n      DST[dst_index] <- clamp(DST[dst_index], min, max)\\n      on DST register operand. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      min and max are uint 32-bit representations of the float values.\",\n    \"operands\": [\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"min_param\", \"type\": \"I32\" },\n      { \"name\": \"max_param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_index `,` $min_param `,` $max_param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.clamp_tile_init\",\n    \"summary\": \"Init function for clamp_scalar_tile operation.\",\n    \"description\": \"Must be run before clamp_scalar_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.clamp_tile_int32\",\n    \"summary\": \"Clamp int32 tile elements to scalar range\",\n    \"description\": \"Performs element-wise clamping of int32 tile values to the range [min, max]\\n      DST[dst_index] <- clamp(DST[dst_index], min, max)\\n      on DST register operand. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      min and max are int32 values.\",\n    \"operands\": [\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"min_param\", \"type\": \"I32\" },\n      { \"name\": \"max_param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_index `,` $min_param `,` $max_param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.compute_kernel_hw_startup\",\n    \"summary\": \"compute_kernel_hw_startup\",\n    \"description\": \"Must be run at the start of compute kernel.\",\n    \"operands\": [\n      { \"name\": \"icb0\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"icb1\", \"type\": \"Optional<TTKernel_CB>\" },\n      { \"name\": \"ocb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $icb0 (`,` $icb1^)? `,` $ocb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.copy_dest_values\",\n    \"summary\": \"Copies all values from the tile in idst1 to the tile in idst0 in the DST register buffer.\",\n    \"description\": \"Copies all values from the tile in idst1 to the tile in idst0 in the DST\\n      register buffer. Performs element-wise computation of copy operation\\n      DST[dst0_index] <- DST[dst1_index]\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.copy_dest_values_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before copy_dest_values.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.copy_tile\",\n    \"summary\": \"Copy tile from specified CB to DST.\",\n    \"description\": \"Copies a single tile from the specified input CB and writes the result to\\n      DST at a specified index. The function will employ unpacker to first unpack into SRC\\n      registers and then perform move into DST registers, at a specified index.\\n      For the in_tile_index to be valid for this call, cb_wait_front(n) had to be\\n      previously called to ensure that at least some number n>0 of tiles are available\\n      in the input CB. The CB index 0 then references the first tile in the received section of the CB,\\n      up to index n-1 (in a FIFO order). The DST register buffer must be in acquired state via\\n      tile_regs_acquire call. This call is blocking and is only available on the compute\\n      engine.\",\n    \"operands\": [\n      { \"name\": \"cb0\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"tile_index_cb\", \"type\": \"IndexLike\" },\n      { \"name\": \"tile_index_dst\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb0 `,` $tile_index_cb `,` $tile_index_dst `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.copy_tile_init\",\n    \"summary\": \"Perform the init for copy tile. This does not reconfigure the unpacker data types.\",\n    \"description\": \"Must be called before copy_tile.\",\n    \"operands\": [\n      { \"name\": \"cb0\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb0 `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.cos_tile\",\n    \"summary\": \"Cos operation\",\n    \"description\": \"Performs element-wise computation of the trigonometric cosine operation on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.cos_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of cos_tile.\",\n    \"description\": \"Must be run before cos_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.div_binary_tile\",\n    \"summary\": \"Divide operation between two tiles\",\n    \"description\": \"Performs element-wise computation of division operation\\n      DST[odst_index] <- DST[dst0_index] / DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.div_binary_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before div_binary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:`functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.div_unary_tile\",\n    \"summary\": \"Divide by scalar operation\",\n    \"description\": \"Performs element-wise division of a tile by a scalar value.\\n      DST[dst0_index] <- DST[dst0_index] / scalar\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.dprint\",\n    \"summary\": \"Print to output stream from kernel.\",\n    \"description\": \"std::format style format string:\\n      ```c++\\n      rewriter.create<ttkernel::DPrintOp>(loc, \\\"nocY={} nocX={} addr={}\\\\\\\\n\\\",\\n                                        nocY, nocX, addr);\\n      ```\\n      ```\\n      ttkernel.dprint(\\\"virtY {} virtX {} addr {}\\\\\\\\n\\\", %14, %15, %13) : (index, index, i32)\\n      ```\\n      Notes:\\n        - Only trivial format specifier currently supported, i.e. `{}`.\\n        - Must double escape newline character or other special characters.\\n        - When a CB operand is provided, calls print_cb_details, printing underlying CB pointers and details.\",\n    \"operands\": [\n      { \"name\": \"argv\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fmt\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $fmt (`,` $argv^)? `)` attr-dict `:` functional-type($argv, results)\"\n  },\n  {\n    \"name\": \"ttkernel.eqz_tile\",\n    \"summary\": \"Equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise equality on DST register tiles.\\n      DST[dst0_index] <- (DST[dst0_index] == 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.eqz_tile_init\",\n    \"summary\": \"Init function for eqz() operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before eqz_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.eqz_tile_int32\",\n    \"summary\": \"Equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise equality on DST register tiles for int32 data type.\\n      DST[dst0_index] <- (DST[dst0_index] == 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.erf_tile\",\n    \"summary\": \"Erf operation\",\n    \"description\": \"Performs element-wise computation of error function (erf) on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.erf_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of erf_tile.\",\n    \"description\": \"Must be run before erf_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.erfc_tile\",\n    \"summary\": \"Erfc operation\",\n    \"description\": \"Performs element-wise computation of complementary error function (erfc) on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.erfc_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of erfc_tile.\",\n    \"description\": \"Must be run before erfc_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.exp_tile\",\n    \"summary\": \"Exp operation\",\n    \"description\": \"Performs element-wise computation of exponential on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.exp_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of exp_tile.\",\n    \"description\": \"Must be run before exp_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::close_fabric_connections\",\n    \"summary\": \"CloseFabricConnections\",\n    \"description\": \"Close fabric connections.\",\n    \"operands\": [\n      { \"name\": \"fabric_connection_manager\", \"type\": \"TTKernel_FabricConnectionManager\" }\n    ],\n    \"assemblyFormat\": \"`(` $fabric_connection_manager `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::convert_logical_x_to_translated\",\n    \"summary\": \"ConvertLogicalToTranslatedX\",\n    \"description\": \"this converts the x coordinate from the LOGICAL coordinate system to TRANSLATED\",\n    \"operands\": [\n      { \"name\": \"logical_x\", \"type\": \"IndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"virtual_x\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $logical_x `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::convert_logical_y_to_translated\",\n    \"summary\": \"ConvertLogicalToTranslatedY\",\n    \"description\": \"this converts the y coordinate from the LOGICAL coordinate system to TRANSLATED\",\n    \"operands\": [\n      { \"name\": \"logical_y\", \"type\": \"IndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"virtual_y\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $logical_y `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::create_fabric_connection_manager\",\n    \"summary\": \"CreateFabricConnectionManager\",\n    \"description\": \"Create fabric connection manager. The fabric connection manager is required for all fabric operations.\",\n    \"results\": [\n      { \"name\": \"fabric_connection_manager\", \"type\": \"TTKernel_FabricConnectionManager\" }\n    ],\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::fabric_fast_write_any_len\",\n    \"summary\": \"FabricWriteOp\",\n    \"description\": \"FabricWriteOp\",\n    \"operands\": [\n      { \"name\": \"fabric_connection_manager\", \"type\": \"TTKernel_FabricConnectionManager\" },\n      { \"name\": \"dst_mesh_id\", \"type\": \"I16\" },\n      { \"name\": \"dst_dev_id\", \"type\": \"I16\" },\n      { \"name\": \"dst_addr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"src_addr\", \"type\": \"I32\" },\n      { \"name\": \"len_bytes\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $fabric_connection_manager `,` $dst_mesh_id `,` $dst_dev_id `,` $dst_addr `,` $src_addr `,` $len_bytes `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::fabric_mcast_fast_write_any_len\",\n    \"summary\": \"FabricMulticastWriteOp\",\n    \"description\": \"FabricMulticastWriteOp\",\n    \"operands\": [\n      { \"name\": \"fabric_connection_manager\", \"type\": \"TTKernel_FabricConnectionManager\" },\n      { \"name\": \"dst_mesh_id\", \"type\": \"I16\" },\n      { \"name\": \"dst_dev_id_start\", \"type\": \"I16\" },\n      { \"name\": \"dst_dev_id_end\", \"type\": \"I16\" },\n      { \"name\": \"dst_addr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"src_addr\", \"type\": \"I32\" },\n      { \"name\": \"len_bytes\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $fabric_connection_manager `,` $dst_mesh_id `,` $dst_dev_id_start `,` $dst_dev_id_end `,` $dst_addr `,` $src_addr `,` $len_bytes `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::fabric_sem_inc\",\n    \"summary\": \"FabricSemIncOp\",\n    \"description\": \"FabricSemIncOp. This operation increments a semaphore on a remote device.\",\n    \"operands\": [\n      { \"name\": \"fabric_connection_manager\", \"type\": \"TTKernel_FabricConnectionManager\" },\n      { \"name\": \"dst_mesh_id\", \"type\": \"I16\" },\n      { \"name\": \"dst_dev_id\", \"type\": \"I16\" },\n      { \"name\": \"semaphore_addr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"incr\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $fabric_connection_manager `,` $dst_mesh_id `,` $dst_dev_id `,` $semaphore_addr `,` $incr `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::fill_arange_tile\",\n    \"summary\": \"Experimental Write Full Linear Index Tile Op\",\n    \"description\": \"Writes a full linear index tile pattern to a CB, where element[i,j] = i * 32 + j\\n      (linear index as float, 0-1023). This is used for arange operations to generate\\n      index tiles directly in L1 memory.\\n\\n      The resulting tile looks like:\\n      [[  0,   1,   2, ...,  31],\\n       [ 32,  33,  34, ...,  63],\\n       ...\\n       [992, 993, 994, ..., 1023]]\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::get_device_id_from_logical_mesh_position\",\n    \"summary\": \"GetDeviceIdFromLogicalMeshPosition\",\n    \"description\": \"Get the device ID for a given logical mesh position.\\n    Takes a MeshPosition and returns the corresponding device ID.\\n    Maps to get_device_id_from_logical_mesh_position(fcm, position) in device code.\",\n    \"operands\": [\n      { \"name\": \"fcm\", \"type\": \"TTKernel_FabricConnectionManager\" },\n      { \"name\": \"position\", \"type\": \"TTKernel_MeshPosition\" }\n    ],\n    \"results\": [\n      { \"name\": \"device_id\", \"type\": \"I16\" }\n    ],\n    \"assemblyFormat\": \"`(` $fcm `,` $position `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::get_logical_mesh_position\",\n    \"summary\": \"GetLogicalMeshPosition\",\n    \"description\": \"Get the logical mesh position for a given device ID.\",\n    \"operands\": [\n      { \"name\": \"fcm\", \"type\": \"TTKernel_FabricConnectionManager\" },\n      { \"name\": \"device_id\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"position\", \"type\": \"TTKernel_MeshPosition\" }\n    ],\n    \"assemblyFormat\": \"`(` $fcm `,` $device_id `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::get_my_device_id\",\n    \"summary\": \"GetMyDeviceId\",\n    \"description\": \"Get my device id. This is a 16 bit value.\",\n    \"results\": [\n      { \"name\": \"my_device_id\", \"type\": \"I16\" }\n    ],\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::get_noc_multicast_addr\",\n    \"summary\": \"Experimental GetNocMulticastAddr\",\n    \"description\": \"Default tt-metal get_noc_multicast_addr, but flips mcast start and end coordinates on NOC1.\",\n    \"operands\": [\n      { \"name\": \"noc_x_start\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_y_start\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_x_end\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_y_end\", \"type\": \"IndexLike\" },\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[I32, TTKernel_L1Addr, TTKernel_Semaphore]>\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"mcastNocAddr\", \"type\": \"TTKernel_NocAddr\" }\n    ],\n    \"assemblyFormat\": \"`(` $noc_x_start `,` $noc_y_start `,` $noc_x_end `,` $noc_y_end `,` $addr (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::matmul_block\",\n    \"summary\": \"Matmul tiles operation\",\n    \"description\": \"Performs block-sized matrix multiplication *C=A\\\\*B* between the blocks in two\\n      different input CBs and writes the result to DST. The DST register buffer\\n      must be in acquired state via *acquire_dst* call. This call is blocking and\\n      is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in0_cb_id\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb_id\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in0_tile_idx\", \"type\": \"IndexLike\" },\n      { \"name\": \"in1_tile_idx\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_tile_idx\", \"type\": \"IndexLike\" },\n      { \"name\": \"transpose\", \"type\": \"I32\" },\n      { \"name\": \"ct_dim\", \"type\": \"I32\" },\n      { \"name\": \"rt_dim\", \"type\": \"I32\" },\n      { \"name\": \"kt_dim\", \"type\": \"I32\" },\n      { \"name\": \"nt_dim\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"ttkernel.experimental::pack_untilize_block\",\n    \"summary\": \"Experimental PackUntilizeBlockOp call.\",\n    \"description\": \"Custom pack untilize block LLK that takes the dimensions of the block.\\n      Uses `pack_untilize_init` for initialization and calls\\n      `pack_untilize_block<cols_per_dst_pass, total_col_tiles>(icb, ocb, block_r, block_c)`.\\n      `cols_per_dst_pass` is the number of column tiles processed per DST pass\\n      (constrained by DST capacity), and `total_col_tiles` is the total number\\n      of column tiles in the untilized row.\\n      For correctness, `cols_per_dst_pass` must divide `total_col_tiles`, and\\n      `block_c` is expected to be compatible with the chosen\\n      `cols_per_dst_pass` (the implementation processes\\n      `block_c / cols_per_dst_pass` column blocks).\\n      Use this op in the sequence:\\n      `pack_untilize_init -> experimental::pack_untilize_block -> pack_untilize_uninit`.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"blockR\", \"type\": \"I32\" },\n      { \"name\": \"blockC\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"colsPerDstPass\", \"type\": \"I32Attr\" },\n      { \"name\": \"totalColTiles\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $cbOut `,` $blockR `,` $blockC `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::setup_fabric_connections\",\n    \"summary\": \"SetupFabricConnections\",\n    \"description\": \"Setup fabric connections for inter-device communication. The connection scheme\\n    is derived from the attribute `TTMetal_FabricConnectionConfigAttr` in the\\n    `EnqueueProgramOp`.\\n\\n   `TTMetal_FabricConnectionConfigAttr` specifies:\\n      - `noc_index`: Which NOC the fabric uses (must match kernel's NocConfig)\\n      - `topology`: The routing scheme to use for the mesh device (e.g. Line, Ring)\\n      - `cluster_axis`: The axis along which the to route for 1D topologies\\n      - `num_links`: Number of routing planes (connections to fabric routers)\\n\\n    After setup, the `FabricConnectionManager` can be used with ops like\\n    `fabric_fast_write_any_len` to send data to other devices in the mesh.\",\n    \"operands\": [\n      { \"name\": \"fabric_connection_manager\", \"type\": \"TTKernel_FabricConnectionManager\" }\n    ],\n    \"assemblyFormat\": \"`(` $fabric_connection_manager `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::tile_fill\",\n    \"summary\": \"Experimental Tile Fill Op\",\n    \"description\": \"Creates a tile in DST filled with a constant scalar value. All elements in the\\n      resulting tile will have the same value as the input scalar. The DST register\\n      buffer must be in acquired state via *tile_regs_acquire* call. This call is\\n      blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"value\", \"type\": \"AnyFloat\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_index `,` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::tilize_block\",\n    \"summary\": \"Experimental TilizeBlockOp call.\",\n    \"description\": \"This is a custom tilize block LLK that takes the dimensions of the block, and properly tilizes each row.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"blockR\", \"type\": \"I32\" },\n      { \"name\": \"blockC\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $cbOut `,` $blockR `,` $blockC `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::untilize_block\",\n    \"summary\": \"Experimental UntilizeBlockOp call.\",\n    \"description\": \"This is a custom untilize block LLK that takes the dimensions of the block.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"blockR\", \"type\": \"I32\" },\n      { \"name\": \"blockC\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $cbOut `,` $blockR `,` $blockC `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::write_col_mask_tile\",\n    \"summary\": \"Experimental Write Col Mask Tile Op\",\n    \"description\": \"Writes a column mask tile pattern to a CB, where element[i,j] = 1.0 if j < validCols, else 0.0.\\n      This is used in dataflow kernels to generate OOB mask tiles directly in L1 memory,\\n      avoiding DST register pressure in the compute kernel.\",\n    \"operands\": [\n      { \"name\": \"validCols\", \"type\": \"I32\" },\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $validCols `,` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.experimental::write_row_mask_tile\",\n    \"summary\": \"Experimental Write Row Mask Tile Op\",\n    \"description\": \"Writes a row mask tile pattern to a CB, where element[i,j] = 1.0 if i < validRows, else 0.0.\\n      This is used in dataflow kernels to generate OOB mask tiles directly in L1 memory,\\n      avoiding DST register pressure in the compute kernel.\",\n    \"operands\": [\n      { \"name\": \"validRows\", \"type\": \"I32\" },\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $validRows `,` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.fill_tile\",\n    \"summary\": \"Fill tile with specified value.\",\n    \"description\": \"Fills supplied DST register tile with a supplied f32 value. The DST\\n      register must be in acquired state via *tile_regs_acquire* call.\\n\\n      Example:\\n      ```\\n      ttkernel.fill_tile(%dst_index, %value);\\n      ```\",\n    \"operands\": [\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"value\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_index `,` $value `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.fill_tile_init\",\n    \"summary\": \"Init function for fill_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before fill_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.floor_tile\",\n    \"summary\": \"Floor tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of floor operation\\n      DST[dst0_index] <- floor(DST[dst0_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gelu_tile\",\n    \"summary\": \"GELU operation\",\n    \"description\": \"Performs element-wise computation of GELU on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gelu_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of gelu_tile.\",\n    \"description\": \"Must be run before gelu_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_arg_val\",\n    \"summary\": \"Get runtime arg value.\",\n    \"description\": \"Get runtime argument value at specified index.\",\n    \"operands\": [\n      { \"name\": \"arg_index\", \"type\": \"IndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"arg_val\", \"type\": \"TTKernel_ArgResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $arg_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_common_arg_val\",\n    \"summary\": \"Get common runtime arg value.\",\n    \"description\": \"Get runtime argument value at specified index. (Indexes from different location compared to get_arg_val)\",\n    \"operands\": [\n      { \"name\": \"arg_index\", \"type\": \"IndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"arg_val\", \"type\": \"TTKernel_ArgResultType\" }\n    ],\n    \"assemblyFormat\": \"`(` $arg_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_compile_time_arg_val\",\n    \"summary\": \"Get compile-time arg value.\",\n    \"description\": \"Get compile-time argument value at specified index.\",\n    \"results\": [\n      { \"name\": \"arg_val\", \"type\": \"TTKernel_ArgResultType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"arg_index\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"`(` $arg_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_dataformat\",\n    \"summary\": \"Get the data format of a given CB\",\n    \"description\": \"get_dataformat operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"results\": [\n      { \"name\": \"dataFormat\", \"type\": \"TTKernel_DataFormat\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_interleaved_addr_gen_fast\",\n    \"summary\": \"GetInterleavedAddrGenFastOp\",\n    \"description\": \"Returns an InterleavedAddrGenFast type.\",\n    \"operands\": [\n      { \"name\": \"DRAM\", \"type\": \"I1\" },\n      { \"name\": \"bank_base_address\", \"type\": \"I32\" },\n      { \"name\": \"page_size\", \"type\": \"I32\" },\n      { \"name\": \"data_format\", \"type\": \"TTKernel_DataFormat\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTKernel_InterleavedAddrGenFast\" }\n    ],\n    \"assemblyFormat\": \"`(` $DRAM `,` $bank_base_address `,` $page_size `,` $data_format `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_noc_addr\",\n    \"summary\": \"GetNocAddr\",\n    \"description\": \"GetNocAddr api including core coordinates\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"IndexLike\" },\n      { \"name\": \"y\", \"type\": \"IndexLike\" },\n      { \"name\": \"l1Address\", \"type\": \"AnyTypeOf<[I32, TTKernel_L1Addr, TTKernel_Semaphore]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"nocAddr\", \"type\": \"TTKernel_NocAddr\" }\n    ],\n    \"assemblyFormat\": \"`(` $x `,` $y `,` $l1Address `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_noc_addr_from_bank_id\",\n    \"summary\": \"GetNocAddrFromBankID\",\n    \"description\": \"GetNocAddrFromBankID api\",\n    \"operands\": [\n      { \"name\": \"bank_id\", \"type\": \"I32\" },\n      { \"name\": \"bankAddressOffset\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"nocAddr\", \"type\": \"TTKernel_NocAddr\" }\n    ],\n    \"assemblyFormat\": \"`(` $bank_id `,` $bankAddressOffset `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_noc_multicast_addr\",\n    \"summary\": \"GetNocMulticastAddr\",\n    \"description\": \"Default tt-metal get_noc_multicast_addr\",\n    \"operands\": [\n      { \"name\": \"noc_x_start\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_y_start\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_x_end\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_y_end\", \"type\": \"IndexLike\" },\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[I32, TTKernel_L1Addr, TTKernel_Semaphore]>\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"mcastNocAddr\", \"type\": \"TTKernel_NocAddr\" }\n    ],\n    \"assemblyFormat\": \"`(` $noc_x_start `,` $noc_y_start `,` $noc_x_end `,` $noc_y_end `,` $addr (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_read_ptr\",\n    \"summary\": \"GetReadPtr\",\n    \"description\": \"GetReadPtr operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"results\": [\n      { \"name\": \"readPtr\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_semaphore\",\n    \"summary\": \"GetSemaphoreOp\",\n    \"description\": \"Get L1 addr of the semaphore with specified semaphore id\",\n    \"operands\": [\n      { \"name\": \"semaphore\", \"type\": \"IndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"sem_addr\", \"type\": \"TTKernel_Semaphore\" }\n    ],\n    \"assemblyFormat\": \"`(` $semaphore `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_tile_size\",\n    \"summary\": \"Get the tile size in bytes of a given CB\",\n    \"description\": \"get_tile_size operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"results\": [\n      { \"name\": \"tileSizeBytes\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.get_write_ptr\",\n    \"summary\": \"GetWritePtr\",\n    \"description\": \"GetWritePtr operation\",\n    \"operands\": [\n      { \"name\": \"cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"results\": [\n      { \"name\": \"writePtr\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gez_tile\",\n    \"summary\": \"Greater than or equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise greater than or equal to zero comparison on DST register tiles.\\n      DST[dst0_index] <- (DST[dst0_index] >= 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gez_tile_init\",\n    \"summary\": \"Init function for gez() operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before gez_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gez_tile_int32\",\n    \"summary\": \"Greater than or equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise greater than or equal to zero comparison on DST register tiles for int32 data type.\\n      DST[dst0_index] <- (DST[dst0_index] >= 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gtz_tile\",\n    \"summary\": \"Greater than zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise greater than zero comparison on DST register tiles.\\n      DST[dst0_index] <- (DST[dst0_index] > 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gtz_tile_init\",\n    \"summary\": \"Init function for gtz() operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before gtz_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.gtz_tile_int32\",\n    \"summary\": \"Greater than zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise greater than zero comparison on DST register tiles for int32 data type.\\n      DST[dst0_index] <- (DST[dst0_index] > 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.hardsigmoid_tile\",\n    \"summary\": \"Hardsigmoid operation\",\n    \"description\": \"Performs element-wise computation of hardsigmoid on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.hardsigmoid_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of hardsigmoid_tile.\",\n    \"description\": \"Must be run before hardsigmoid_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.init_sfpu\",\n    \"summary\": \"Initialization function for SFPU operations.\",\n    \"description\": \"This operation initializes all necessary components for SFPU operations,\\n      including unpacking, packing, and math configurations.\",\n    \"operands\": [\n      { \"name\": \"icb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"ocb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $icb `,` $ocb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.interleaved_addr_gen_fast.get_noc_addr\",\n    \"summary\": \"InterleavedAddrGenFastGetNocAddr\",\n    \"description\": \"Returns an raw noc address from an interleaved addr gen struct.\",\n    \"operands\": [\n      { \"name\": \"self\", \"type\": \"TTKernel_InterleavedAddrGenFast\" },\n      { \"name\": \"id\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTKernel_NocAddr\" }\n    ],\n    \"assemblyFormat\": \"`(` $self `,` $id `,` $offset `,` $noc `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.invoke_sfpi\",\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"attr-dict-with-keyword $region\"\n  },\n  {\n    \"name\": \"ttkernel.lez_tile\",\n    \"summary\": \"Less than or equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise less than or equal to zero comparison on DST register tiles.\\n      DST[dst0_index] <- (DST[dst0_index] <= 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.lez_tile_init\",\n    \"summary\": \"Init function for lez() operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before lez_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.lez_tile_int32\",\n    \"summary\": \"Less than or equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise less than or equal to zero comparison on DST register tiles for int32 data type.\\n      DST[dst0_index] <- (DST[dst0_index] <= 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.log_tile\",\n    \"summary\": \"Log operation\",\n    \"description\": \"Performs element-wise computation of log on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.log_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of log_tile.\",\n    \"description\": \"Must be run before log_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.logical_not_tile\",\n    \"summary\": \"Logical negation tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of logical negation operation\\n      DST[dst0_index] <- !DST[dst0_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      The DataFormat template parameter specifies the data type.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.logical_not_tile_init\",\n    \"summary\": \"Init function for logical_not_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before logical_not_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.logical_not_unary_tile\",\n    \"summary\": \"Logical negation tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of logical negation operation\\n      DST[dst0_index] <- !DST[dst0_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.logical_not_unary_tile_init\",\n    \"summary\": \"Init function for logical_not_unary_tile(_int32) operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before logical_not_unary_tile(_int32).\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.logical_not_unary_tile_int32\",\n    \"summary\": \"Logical negation tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of logical negation operation for the int32 data type\\n      DST[dst0_index] <- !DST[dst0_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.ltz_tile\",\n    \"summary\": \"Less than zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise less than zero comparison on DST register tiles.\\n      DST[dst0_index] <- (DST[dst0_index] < 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.ltz_tile_init\",\n    \"summary\": \"Init function for ltz() operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before ltz_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.ltz_tile_int32\",\n    \"summary\": \"Less than zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise less than zero comparison on DST register tiles for int32 data type.\\n      DST[dst0_index] <- (DST[dst0_index] < 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.matmul_tiles\",\n    \"summary\": \"Matmul tiles operation\",\n    \"description\": \"Performs tile-sized matrix multiplication *C=A\\\\*B* between the tiles in two\\n      specified input CBs and writes the result to DST. The DST register buffer\\n      must be in acquired state via ttkernel.tile_regs_acquire call. This call is blocking and\\n      is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in0_cb_id\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb_id\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in0_tile_idx\", \"type\": \"IndexLike\" },\n      { \"name\": \"in1_tile_idx\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_tile_idx\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb_id `,` $in1_cb_id `,` $in0_tile_idx `,` $in1_tile_idx `,` $dst_tile_idx `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mem_zeros_base\",\n    \"summary\": \"Op corresponding to MEM_ZEROS_BASE macro in kernels.\",\n    \"description\": \"Op corresponding to MEM_ZEROS_BASE macro in kernels.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mem_zeros_size\",\n    \"summary\": \"Op corresponding to MEM_ZEROS_SIZE macro in kernels.\",\n    \"description\": \"Op corresponding to MEM_ZEROS_SIZE macro in kernels.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mm_block_init\",\n    \"summary\": \"Matmul init function\",\n    \"description\": \"Initialization for matmul_block operation. Must be called before matmul_block.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"out_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"transpose\", \"type\": \"I32\" },\n      { \"name\": \"ct_dim\", \"type\": \"I32\" },\n      { \"name\": \"rt_dim\", \"type\": \"I32\" },\n      { \"name\": \"kt_dim\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"ttkernel.mm_block_init_short\",\n    \"summary\": \"Matmul short init function\",\n    \"description\": \"A short version of matmul_block initialization.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"transpose\", \"type\": \"I32\" },\n      { \"name\": \"ct_dim\", \"type\": \"I32\" },\n      { \"name\": \"rt_dim\", \"type\": \"I32\" },\n      { \"name\": \"kt_dim\", \"type\": \"I32\" }\n    ]\n  },\n  {\n    \"name\": \"ttkernel.mm_init\",\n    \"summary\": \"Matmul init function\",\n    \"description\": \"Can only be run ONCE per kernel. Should be run before matmul.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"out_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"transpose\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `,` $out_cb `,` $transpose `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mm_init_short\",\n    \"summary\": \"Matmul short init function\",\n    \"description\": \"Can be run MULTIPLE times per kernel. Should be run before matmul. Use this if some other init was called between mm_init and matmul_tiles. (i.e. in a loop)\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"transpose\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `,` $transpose `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_binary_tile\",\n    \"summary\": \"Multiplication operation between two tiles\",\n    \"description\": \"Performs element-wise computation of multiplication operation\\n      DST[odst_index] <- DST[dst0_index] * DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_binary_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before mul_binary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_int_tile\",\n    \"summary\": \"Integer multiplication operation between two tiles\",\n    \"description\": \"Performs element-wise computation of integer multiplication operation\\n      DST[odst_index] <- DST[dst0_index] * DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      Supported data formats are: Int32, UInt32, UInt16.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_int_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before mul_int_tile.\",\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_tiles\",\n    \"summary\": \"Mul operation\",\n    \"description\": \"Performs element-wise multiplication C=A*B of tiles in two CBs at given\\n      indices and writes the result to the DST register at index dst_tile_index.\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in0_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"in1_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `,` $in0_tile_index `,` $in1_tile_index `,` $dst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_tiles_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before mul_tiles.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.mul_unary_tile\",\n    \"summary\": \"Multiply by scalar operation\",\n    \"description\": \"Performs element-wise multiplication of a tile by a scalar value.\\n      DST[dst0_index] <- DST[dst0_index] * scalar\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.my_logical_x_\",\n    \"summary\": \"MyLogicalX\",\n    \"description\": \"Lowers to the tt-metal supported my_logical_x_ global. This represents the logical X coordinate of the current core.\",\n    \"results\": [\n      { \"name\": \"x\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.my_logical_y_\",\n    \"summary\": \"MyLogicalY\",\n    \"description\": \"Lowers to the tt-metal supported my_logical_y_ global. This represents the logical Y coordinate of the current core.\",\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.my_x\",\n    \"summary\": \"MyX\",\n    \"description\": \"Lowers to the tt-metal supported MY_X macro. This represents the virtual X coordinate of the current core.\",\n    \"operands\": [\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"x\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"`(` ($noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.my_y\",\n    \"summary\": \"MyY\",\n    \"description\": \"Lowers to the tt-metal supported MY_Y macro. This represents the virtual Y coordinate of the current core.\",\n    \"operands\": [\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"`(` ($noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.negative_tile\",\n    \"summary\": \"Negative operation\",\n    \"description\": \"Performs element-wise computation of the negative on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.negative_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of negative_tile.\",\n    \"description\": \"Must be run before negative_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.negative_tile_int32\",\n    \"summary\": \"Negative i32 tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of negation operation\\n      DST[dst0_index] <- -DST[dst0_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.nez_tile\",\n    \"summary\": \"Not equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise inequality on DST register tiles.\\n      DST[dst0_index] <- (DST[dst0_index] != 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.nez_tile_init\",\n    \"summary\": \"Init function for nez() operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before nez_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.nez_tile_int32\",\n    \"summary\": \"Not equal to zero tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise inequality on DST register tiles for int32 data type.\\n      DST[dst0_index] <- (DST[dst0_index] != 0)\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read\",\n    \"summary\": \"NocAsyncRead\",\n    \"description\": \"NocAsyncRead\",\n    \"operands\": [\n      { \"name\": \"srcNocAddr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"dstLocalL1Addr\", \"type\": \"I32\" },\n      { \"name\": \"size\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcNocAddr `,` $dstLocalL1Addr `,` $size `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_barrier\",\n    \"summary\": \"NocAsyncReadBarrier\",\n    \"description\": \"NocAsyncReadBarrier\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_barrier_with_trid\",\n    \"summary\": \"NocAsyncReadBarrierWithTrid\",\n    \"description\": \"Waits for outstanding read transactions matching a transaction ID. TRID is 0-15, NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      ttkernel.noc_async_read_barrier_with_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"trid\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $trid (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_one_packet_set_state\",\n    \"summary\": \"NocAsyncReadOnePacketSetState\",\n    \"description\": \"NocAsyncReadOnePacketSetState\",\n    \"operands\": [\n      { \"name\": \"srcNocAddr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"size\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcNocAddr `,` $size `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_one_packet_with_state\",\n    \"summary\": \"NocAsyncReadOnePacketWithState\",\n    \"description\": \"NocAsyncReadOnePacketWithState\",\n    \"operands\": [\n      { \"name\": \"srcNocAddr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"dstLocalL1Addr\", \"type\": \"AnyTypeOf<[I32, TTKernel_L1Addr]>\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcNocAddr `,` $dstLocalL1Addr `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_one_packet_with_state_with_trid\",\n    \"summary\": \"NocAsyncReadOnePacketWithStateWithTrid\",\n    \"description\": \"Issues a one-packet NOC read with a specific transaction ID. TRID is 0-15, NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      // Must set TRID before calling.\\n      // ttkernel.noc_async_read_set_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ttkernel.noc_async_read_one_packet_with_state_with_trid(%src_base, %src_addr, %dst_l1, %trid, %noc_idx) : (i32, i32, i32, i32, i8) -> ()\\n      // TRID-specific barrier should follow.\\n      // ttkernel.noc_async_read_barrier_with_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"srcBaseAddr\", \"type\": \"I32\" },\n      { \"name\": \"srcAddr\", \"type\": \"I32\" },\n      { \"name\": \"dstLocalL1Addr\", \"type\": \"AnyTypeOf<[I32, TTKernel_L1Addr]>\" },\n      { \"name\": \"trid\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcBaseAddr `,` $srcAddr `,` $dstLocalL1Addr `,` $trid (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_set_trid\",\n    \"summary\": \"NocAsyncReadSetTrid\",\n    \"description\": \"Sets the transaction ID for subsequent NOC reads. TRID is 0-15, NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      ttkernel.noc_async_read_set_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"trid\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $trid (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_read_tile\",\n    \"summary\": \"NocAsyncReadTile\",\n    \"description\": \"NocAsyncReadTile\",\n    \"operands\": [\n      { \"name\": \"id\", \"type\": \"I32\" },\n      { \"name\": \"addrGenStruct\", \"type\": \"AnyTypeOf<[TTKernel_InterleavedAddrGenFast, TTKernel_TensorAccessor]>\" },\n      { \"name\": \"dstLocalL1Addr\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $id `,` $addrGenStruct `,` $dstLocalL1Addr `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write\",\n    \"summary\": \"NocAsyncWrite\",\n    \"description\": \"NocAsyncWrite\",\n    \"operands\": [\n      { \"name\": \"srcLocalL1Addr\", \"type\": \"I32\" },\n      { \"name\": \"dstNocAddr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"size\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcLocalL1Addr `,` $dstNocAddr `,` $size `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_barrier\",\n    \"summary\": \"NocAsyncWriteBarrier\",\n    \"description\": \"NocAsyncWriteBarrier\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_barrier_with_trid\",\n    \"summary\": \"NocAsyncWriteBarrierWithTrid\",\n    \"description\": \"Waits for outstanding write transactions matching a transaction ID. TRID is 0-15, NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      ttkernel.noc_async_write_barrier_with_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"trid\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $trid (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_multicast\",\n    \"summary\": \"NocAsyncWriteMulticast\",\n    \"description\": \"Initiates an asynchronous write from a source address in L1 memory on the\\n    Tensix core executing this function call to a rectangular destination grid.\\n    The destinations are specified using a uint64_t encoding referencing an\\n    on-chip grid of nodes located at NOC coordinate range\\n    (x_start,y_start,x_end,y_end) and a local address created using\\n    *get_noc_multicast_addr* function. Also, *see noc_async_write_barrier*.\\n\\n    The destination nodes can only be a set of Tensix cores + L1 memory address.\\n    The destination nodes must form a rectangular grid. The destination L1\\n    memory address must be the same on all destination nodes.\\n\\n    With this API, the multicast sender cannot be part of the multicast\\n    destinations. If the multicast sender has to be in the multicast\\n    destinations (i.e. must perform a local L1 write), the other API variant\\n    *noc_async_write_multicast_loopback_src* can be used.\\n\\n    Note: The number of destinations needs to be non-zero. Besides that,\\n    there is no restriction on the number of destinations, i.e. the\\n    multicast destinations can span the full chip. However, as mentioned\\n    previously, the multicast source cannot be part of the destinations. So, the\\n    maximum number of destinations is 119.\",\n    \"operands\": [\n      { \"name\": \"srcLocalL1Addr\", \"type\": \"I32\" },\n      { \"name\": \"dstNocAddrMulticast\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"num_dests\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"linked\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"multicast_path_reserve\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcLocalL1Addr `,` $dstNocAddrMulticast `,` $size `,` $num_dests (`,` $linked^)? (`,` $multicast_path_reserve^)? (`,` $noc^)? `)` attr-dict `:`functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_multicast_loopback_src\",\n    \"summary\": \"NocAsyncWriteMulticastLoopbackSrc\",\n    \"description\": \"NocAsyncWriteMulticastLoopbackSrc\",\n    \"operands\": [\n      { \"name\": \"srcLocalL1Addr\", \"type\": \"I32\" },\n      { \"name\": \"dstNocAddrMulticast\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"num_dests\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"linked\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"multicast_path_reserve\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcLocalL1Addr `,` $dstNocAddrMulticast `,` $size `,` $num_dests (`,` $linked^)? (`,` $multicast_path_reserve^)? (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_multicast_one_packet\",\n    \"summary\": \"NocAsyncWriteMulticastOnePacket\",\n    \"description\": \"NocAsyncWriteMulticastOnePacket\\n    this issues only a single packet with size <= NOC_MAX_BURST_SIZE (ie maximum packet size)\",\n    \"operands\": [\n      { \"name\": \"srcLocalL1Addr\", \"type\": \"I32\" },\n      { \"name\": \"dstNocAddrMulticast\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"num_dests\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"linked\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"multicast_path_reserve\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcLocalL1Addr `,` $dstNocAddrMulticast `,` $size `,` $num_dests (`,` $linked^)? (`,` $multicast_path_reserve^)? (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_one_packet_with_trid\",\n    \"summary\": \"NocAsyncWriteOnePacketWithTrid\",\n    \"description\": \"Issues a one-packet NOC write with a specific transaction ID. TRID is 0-15, NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      // Must set TRID before calling.\\n      // ttkernel.noc_async_write_set_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ttkernel.noc_async_write_one_packet_with_trid(%l1_src, %dst_noc, %size, %trid, %noc_idx) : (i32, !ttkernel.noc_addr, i32, i32, i8) -> ()\\n      // TRID-specific barrier should follow.\\n      // ttkernel.noc_async_write_barrier_with_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"srcLocalL1Addr\", \"type\": \"I32\" },\n      { \"name\": \"dstNocAddr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"size\", \"type\": \"I32\" },\n      { \"name\": \"trid\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $srcLocalL1Addr `,` $dstNocAddr `,` $size `,` $trid (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_set_trid\",\n    \"summary\": \"NocAsyncWriteSetTrid\",\n    \"description\": \"Sets the transaction ID for subsequent NOC writes. TRID is 0-15, NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      ttkernel.noc_async_write_set_trid(%trid, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"trid\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $trid (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_async_write_tile\",\n    \"summary\": \"NocAsyncWriteTile\",\n    \"description\": \"NocAsyncWriteTilie\",\n    \"operands\": [\n      { \"name\": \"id\", \"type\": \"IndexLike\" },\n      { \"name\": \"addrGenStruct\", \"type\": \"AnyTypeOf<[TTKernel_InterleavedAddrGenFast, TTKernel_TensorAccessor]>\" },\n      { \"name\": \"srcLocalL1Addr\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $id `,` $addrGenStruct `,` $srcLocalL1Addr `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_semaphore_inc\",\n    \"summary\": \"NocSemaphoreInc\",\n    \"description\": \"The Tensix core executing this function call initiates an atomic increment\\n      (with 32-bit wrap) of a remote Tensix core L1 memory address. This L1 memory\\n      address is used as a semaphore of size 4 Bytes, as a synchronization\\n      mechanism.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"incr\", \"type\": \"IndexLike\" },\n      { \"name\": \"noc_id\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $addr `,` $incr (`,` $noc_id^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_semaphore_set\",\n    \"summary\": \"NocSemaphoreSet\",\n    \"description\": \"Sets the value of a local L1 memory address on the Tensix core executing\\n      this function to a specific value. This L1 memory address is used as a\\n      semaphore of size 4 Bytes, as a synchronization mechanism. Also, see\\n      *noc_semaphore_wait*.\",\n    \"operands\": [\n      { \"name\": \"sem_addr\", \"type\": \"TTKernel_L1AddrPtr\" },\n      { \"name\": \"val\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $sem_addr `,` $val `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_semaphore_set_multicast\",\n    \"summary\": \"NocSemaphoreSetMulticast\",\n    \"description\": \"Initiates an asynchronous write from a source address in L1 memory on the\\n      Tensix core executing this function call to a rectangular destination grid.\\n      The destinations are specified using a uint64_t encoding referencing an\\n      on-chip grid of nodes located at NOC coordinate range\\n      (x_start,y_start,x_end,y_end) and a local address created using\\n      *get_noc_multicast_addr* function. The size of data that is sent is 4 Bytes.\\n      This is usually used to set a semaphore value at the destination nodes, as a\\n      way of a synchronization mechanism. The same as *noc_async_write_multicast*\\n      with preset size of 4 Bytes.\\n      With this API, the multicast sender cannot be part of the multicast\\n      destinations. If the multicast sender has to be in the multicast\\n      destinations (i.e. must perform a local L1 write), the other API variant\\n      *noc_semaphore_set_multicast_loopback_src* can be used.\",\n    \"operands\": [\n      { \"name\": \"src_local_l1_addr\", \"type\": \"AnyTypeOf<[TTKernel_L1Addr, TTKernel_Semaphore]>\" },\n      { \"name\": \"dst_noc_addr_multicast\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"num_dests\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"linked\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"multicast_path_reserve\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $src_local_l1_addr `,` $dst_noc_addr_multicast `,` $num_dests (`,` $linked^)? (`,` $multicast_path_reserve^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_semaphore_set_multicast_loopback_src\",\n    \"summary\": \"NocSemaphoreSetMulticastLoopback\",\n    \"description\": \"Initiates an asynchronous write from a source address in L1 memory on the\\n      Tensix core executing this function call to a rectangular destination grid.\\n      The destinations are specified using a uint64_t encoding referencing an\\n      on-chip grid of nodes located at NOC coordinate range\\n      (x_start,y_start,x_end,y_end) and a local address created using\\n      *get_noc_multicast_addr* function. The size of data that is sent is 4 Bytes.\\n      This is usually used to set a semaphore value at the destination nodes, as a\\n      way of a synchronization mechanism. The same as *noc_async_write_multicast*\\n      with preset size of 4 Bytes.\\n      Note: With this API, sending data only to the source node (when num_dests\\n      is 1) may result in unexpected behaviour. For some parameters, hangs have\\n      been observed. For some other parameters, nothing may happen. Consider using\\n      regular non multicast operations such as *noc_async_write* in this case.\",\n    \"operands\": [\n      { \"name\": \"src_local_l1_addr\", \"type\": \"AnyTypeOf<[TTKernel_L1Addr, TTKernel_Semaphore]>\" },\n      { \"name\": \"dst_noc_addr_multicast\", \"type\": \"TTKernel_NocAddr\" },\n      { \"name\": \"num_dests\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"linked\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"`(` $src_local_l1_addr `,` $dst_noc_addr_multicast `,` $num_dests (`,` $linked^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_semaphore_wait\",\n    \"summary\": \"NocSemaphoreWait\",\n    \"description\": \"A blocking call that waits until the value of a local L1 memory address on\\n      the Tensix core executing this function becomes equal to a target value.\\n      This L1 memory address is used as a semaphore of size 4 Bytes, as a\\n      synchronization mechanism. Also, see *noc_semaphore_set*.\",\n    \"operands\": [\n      { \"name\": \"sem_addr\", \"type\": \"TTKernel_L1AddrPtr\" },\n      { \"name\": \"val\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $sem_addr `,` $val `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.noc_semaphore_wait_min\",\n    \"summary\": \"NocSemaphoreWaitMin\",\n    \"description\": \"A blocking call that waits until the value of a local L1 memory address on\\n      the Tensix core executing this function becomes equal or greater than a target value.\\n      This L1 memory address is used as a semaphore of size 4 Bytes, as a\\n      synchronization mechanism. Also, see *noc_semaphore_set*.\",\n    \"operands\": [\n      { \"name\": \"sem_addr\", \"type\": \"TTKernel_L1AddrPtr\" },\n      { \"name\": \"val\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $sem_addr `,` $val `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.pack_reconfig_l1_acc\",\n    \"summary\": \"Reconfigure packer to L1 accumulation mode.\",\n    \"description\": \"Reconfigures the packer to accumulate when packing from DST to L1.\",\n    \"operands\": [\n      { \"name\": \"l1_acc_en\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $l1_acc_en `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.pack_tile\",\n    \"summary\": \"PackTile op.\",\n    \"description\": \"Copies a single tile from the DST register buffer at a specified index to a\\n      specified CB at a given index. For the out_tile_index to be valid for this\\n      call, cb_reserve_back(n) has to be called first to reserve at least some\\n      number n > 0 of tiles in the output CB. out_tile_index = 0 then references\\n      the first tile in the reserved section of the CB, up to index n - 1, which will\\n      then be visible to the consumer in the same order after a cb_push_back call.\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\\n\\n      Each subsequent pack call will increment the write pointer in the cb by single\\n      tile size. The pointer is then again set to a valid position with space for n\\n      reserved tiles by another cb_reserve_back call.\\n\\n      Operates in tandem with functions cb_reserve_back and cb_push_back.\\n\\n      A typical use case is first the producer ensures that there is a number of\\n      tiles available in the buffer via cb_reserve_back, then the producer uses\\n      the pack_tile call to copy a tile from one of DST slots to a slot in\\n      reserved space and finally cb_push_back is called to announce visibility of\\n      the reserved section of the circular buffer to the consumer.\",\n    \"operands\": [\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"out_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"out_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"out_of_order\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_index `,` $out_cb `,` $out_index `,` $out_of_order`)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.pack_untilize_init\",\n    \"summary\": \"PackUntilizeInitOp call.\",\n    \"description\": \"Initializes UNPACK, MATH, and PACK threads for the pack untilize\\n      operation.  Maps to the official tt-metal\\n      `pack_untilize_init<block_ct_dim, full_ct_dim>(icb, ocb)` API.\\n      `cols_per_dst_pass` is the number of column tiles processed per DST pass\\n      (`block_ct_dim` in the tt-metal template), and `total_col_tiles` is the\\n      total number of column tiles (`full_ct_dim` in the tt-metal template).\\n      For correctness, `cols_per_dst_pass` must divide `total_col_tiles`, and\\n      `cols_per_dst_pass` must fit\\n      in DST capacity for the target data type. Both default to 1.\\n      This op is expected to be paired with\\n      `experimental::pack_untilize_block` and finalized by\\n      `pack_untilize_uninit`.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"colsPerDstPass\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" },\n      { \"name\": \"totalColTiles\", \"type\": \"DefaultValuedAttr<I32Attr, 1>\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.pack_untilize_uninit\",\n    \"summary\": \"PackUntilizeUninitOp call.\",\n    \"description\": \"Uninitializes the pack untilize operation.  Maps to the official tt-metal\\n      `pack_untilize_uninit(ocb)` API.\",\n    \"operands\": [\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.power_binary_tile\",\n    \"summary\": \"Power operation between two tiles\",\n    \"description\": \"Performs element-wise computation of power operation\\n      DST[odst_index] <- DST[dst0_index] ^ DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.power_binary_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of power_binary_tile.\",\n    \"description\": \"Must be run before power_binary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.power_tile\",\n    \"summary\": \"Power by scalar operation\",\n    \"description\": \"Performs element-wise exponentiation of a tile by a scalar value.\\n      DST[dst0_index] <- DST[dst0_index] ^ scalar\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.power_tile_init\",\n    \"summary\": \"Init function for power_tile operation.\",\n    \"description\": \"Must be run before power_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.recip_tile\",\n    \"summary\": \"Recip tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of the reciprocal on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\\n      Only works for Float32, Float16_b, Bfp8_b data formats for full accuracy.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.recip_tile_init\",\n    \"summary\": \"Init function for recip_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be called before recip_tile function.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.reduce_init\",\n    \"summary\": \"Init function\",\n    \"description\": \"Must be run before reduce_tile.\",\n    \"operands\": [\n      { \"name\": \"in_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"scaling_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"out_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_type\", \"type\": \"TTKernel_ReduceTypeAttr{reduce_sum|reduce_max}\" },\n      { \"name\": \"reduce_dim\", \"type\": \"TTKernel_ReduceDimAttr{reduce_dim_row|reduce_dim_col|reduce_dim_scalar}\" },\n      { \"name\": \"full_fp32\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_cb `,` $scaling_cb `,` $out_cb `,` $reduce_type `,` $reduce_dim `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.reduce_tile\",\n    \"summary\": \"Reduce operation\",\n    \"description\": \"Performs a reduction operation *B = reduce(A)* using reduce_func for\\n      dimension reduction on a tile in the CB at a given index and writes the\\n      result to the DST register at index *dst_tile_index*. Reduction can be\\n      either of type *Reduce::R*, *Reduce::C* or *Reduce::RC*, identifying the\\n      dimension(s) to be reduced in size to 1. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      The templates takes reduce_type which can be ReduceFunc::Sum, ReduceFunc::Max\\n      and reduce_dim which can be Reduce::R, Reduce::C, Reduce::RC.\\n      They can also be specified by defines REDUCE_OP and REDUCE_DIM.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"scaling_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"scaling_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_type\", \"type\": \"TTKernel_ReduceTypeAttr{reduce_sum|reduce_max}\" },\n      { \"name\": \"reduce_dim\", \"type\": \"TTKernel_ReduceDimAttr{reduce_dim_row|reduce_dim_col|reduce_dim_scalar}\" },\n      { \"name\": \"full_fp32\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_cb `,` $scaling_cb `,` $in_tile_index `,` $scaling_tile_index `,` $dst_index `,` $reduce_type `,` $reduce_dim `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.reduce_uninit\",\n    \"summary\": \"Init function for reduce_uninit operation.\",\n    \"description\": \"Resets the packer edge mask configuration to its default state by clearing any previously set masks. Needs to be called after\\n       reduce_tile if the next operation requires default packer state. In case that the next operation is reduce operation across the\\n       same dimension, this call can be omitted. If this function is not called, the packer will continue to use the edge masks set\\n       by the latest reduce_init call, which may lead to incorrect packing behavior in subsequent operations.\\n\\n       This function is not in line with our programming mode. To be removed by end of 2025. tt-metal#22904.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.reinterpret_cast<volatile tt_l1_ptr uint32_t*>\",\n    \"summary\": \"CastToL1Ptr\",\n    \"description\": \"Cast specified addr to L1 pointer.\",\n    \"operands\": [\n      { \"name\": \"addr\", \"type\": \"AnyTypeOf<[I32, TTKernel_L1Addr, TTKernel_Semaphore]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"l1_ptr\", \"type\": \"TTKernel_L1AddrPtr\" }\n    ],\n    \"assemblyFormat\": \"`(` $addr `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.relu_tile\",\n    \"summary\": \"Relu operation\",\n    \"description\": \"Performs element-wise computation of relu on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.relu_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of relu_tile(_int32).\",\n    \"description\": \"Must be run before relu_tile(_int32).\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.relu_tile_int32\",\n    \"summary\": \"Relu operation (for int32 type)\",\n    \"description\": \"Performs element-wise computation of relu on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.reset_noc_trid_barrier_counter\",\n    \"summary\": \"ResetNocTridBarrierCounter\",\n    \"description\": \"Resets the barrier counters for a set of transaction IDs on a given NOC. Mask bits correspond to TRIDs 0-15; NOC is 0 or 1.\\n\\n      Example:\\n      ```\\n      ttkernel.reset_noc_trid_barrier_counter(%mask, %noc_idx) : (i32, i8) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"idMask\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"assemblyFormat\": \"`(` $idMask (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.rounding_op_tile_init\",\n    \"summary\": \"Init function for ceil/floor/round_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before ceil/floor/round_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.rsqrt_tile\",\n    \"summary\": \"Rsqrt operation\",\n    \"description\": \"Performs element-wise computation of reciprocal sqrt on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.rsqrt_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of rsqrt_tile.\",\n    \"description\": \"Must be run before rsqrt_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sigmoid_tile\",\n    \"summary\": \"Sigmoid operation\",\n    \"description\": \"Performs element-wise computation of sigmoid on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sigmoid_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of sigmoid_tile.\",\n    \"description\": \"Must be run before sigmoid_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sign_tile\",\n    \"summary\": \"Sign operation\",\n    \"description\": \"Performs element-wise computation of sign on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sign_tile_init\",\n    \"summary\": \"Init function for sign_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before sign_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.silu_tile\",\n    \"summary\": \"Silu operation\",\n    \"description\": \"Performs element-wise computation of silu on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.silu_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of silu_tile.\",\n    \"description\": \"Must be run before silu_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sin_tile\",\n    \"summary\": \"Sine tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise computation of sine operation\\n      DST[dst0_index] <- sin(DST[dst0_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sin_tile_init\",\n    \"summary\": \"Init function for sin_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before sin_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sqrt_tile\",\n    \"summary\": \"Sqrt operation\",\n    \"description\": \"Performs element-wise computation of sqrt on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sqrt_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of sqrt_tile.\",\n    \"description\": \"Must be run before sqrt_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.store_to_l1\",\n    \"summary\": \"StoreToL1\",\n    \"description\": \"Store value to L1.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I32\" },\n      { \"name\": \"l1_ptr\", \"type\": \"TTKernel_L1AddrPtr\" },\n      { \"name\": \"offset\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $value `,` $l1_ptr `,` $offset `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_binary_tile\",\n    \"summary\": \"Subtraction operation between two tiles\",\n    \"description\": \"Performs element-wise computation of subtraction operation\\n      DST[odst_index] <- DST[dst0_index] - DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_binary_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before sub_binary_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_int_tile\",\n    \"summary\": \"Integer subtraction operation between two tiles\",\n    \"description\": \"Performs element-wise computation of integer subtraction operation\\n      DST[odst_index] <- DST[dst0_index] - DST[dst1_index]\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\\n      Supported data formats are: Int32, UInt32, UInt16.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst1_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $dst1_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_int_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before sub_int_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_tiles\",\n    \"summary\": \"Sub operation\",\n    \"description\": \"Performs element-wise subtraction C=A-B of tiles in two CBs at given\\n      indices and writes the result to the DST register at index dst_tile_index.\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in0_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"in1_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `,` $in0_tile_index `,` $in1_tile_index `,` $dst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_tiles_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before sub_tiles.\",\n    \"operands\": [\n      { \"name\": \"in0_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in1_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $in0_cb `,` $in1_cb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.sub_unary_tile\",\n    \"summary\": \"Subtract by scalar operation\",\n    \"description\": \"Performs element-wise subtraction of a tile by a scalar value.\\n      DST[dst0_index] <- DST[dst0_index] - scalar\\n      The DST register buffer must be in acquired state via *tile_regs_acquire* call.\\n      This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"param\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $param `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tan_tile\",\n    \"summary\": \"Tan operation\",\n    \"description\": \"Performs element-wise computation of the trigonometric tangent operation on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $tile_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tan_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of tan_tile.\",\n    \"description\": \"Must be run before tan_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tanh_tile\",\n    \"summary\": \"Tanh operation\",\n    \"description\": \"Performs element-wise computation of the hyperbolic tangent operation on each element of a tile\\n      in DST register at index tile_index. The DST register buffer must be in\\n      acquired state via *acquire_dst* call. This call is blocking and is only\\n      available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tanh_tile_init\",\n    \"summary\": \"Short init function which configures compute unit for execution of tanh_tile.\",\n    \"description\": \"Must be run before tanh_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.get_bank_and_offset\",\n    \"summary\": \"TensorAccessor's get_bank_and_offset\",\n    \"description\": \"Returns bank id and page offset.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"page_id\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"bank_id_and_offset\", \"type\": \"TTKernel_TensorAccessorPageMapping\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $page_id `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.get_noc_addr\",\n    \"summary\": \"TensorAccessor's get_noc_addr\",\n    \"description\": \"get_noc_addr using information stored in the TensorAccessor.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"id\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"nocAddr\", \"type\": \"TTKernel_NocAddr\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $id `,` $offset (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.get_shard_noc_addr\",\n    \"summary\": \"TensorAccessor's get_shard_noc_addr\",\n    \"description\": \"Returns noc addr of a shard.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"shard_id\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"shardNocAddr\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $shard_id `,` $offset (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.is_local_addr\",\n    \"summary\": \"TensorAccessor's is_local_addr\",\n    \"description\": \"Returns bool indicating addr locality.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"virtual_x\", \"type\": \"I32\" },\n      { \"name\": \"virtual_y\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $virtual_x `,` $virtual_y (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.is_local_bank\",\n    \"summary\": \"TensorAccessor's is_local_bank\",\n    \"description\": \"Returns bool indicating bank locality.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"id\", \"type\": \"I32\" },\n      { \"name\": \"offset\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $id `,` $offset (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.is_local_page\",\n    \"summary\": \"TensorAccessor's is_local_page\",\n    \"description\": \"Returns bool indicating page locality.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"page_id\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $page_id (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tensor_accessor.is_local_shard\",\n    \"summary\": \"TensorAccessor's is_local_shard\",\n    \"description\": \"Returns bool indicating shard locality.\",\n    \"operands\": [\n      { \"name\": \"tensor_accessor\", \"type\": \"TTKernel_TensorAccessor\" },\n      { \"name\": \"shard_id\", \"type\": \"I32\" },\n      { \"name\": \"noc\", \"type\": \"Optional<I8>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"`(` $tensor_accessor `,` $shard_id (`,` $noc^)? `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.TensorAccessor\",\n    \"summary\": \"MakeTensorAccessorFromArgs\",\n    \"description\": \"TensorAccessor constructor.\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"TTKernel_TensorAccessorArgs\" },\n      { \"name\": \"bank_base_address_in\", \"type\": \"I32\" },\n      { \"name\": \"page_size_in\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTKernel_TensorAccessor\" }\n    ],\n    \"assemblyFormat\": \"`(` $args `,` $bank_base_address_in `,` $page_size_in `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.TensorAccessorArgs\",\n    \"summary\": \"TensorAccessorArgs\",\n    \"description\": \"TensorAccessorArgs struct constructor.\\n\\n    CTA (compile-time args) and CRTA (compile/runtime args) offsets are determined as follows.\\n    1. If cta_expr is provided: use the constexpr string expression.\\n    2. Else if `prev_args` is provided, use chaining:\\n      `prev_args.next_compile_time_args_offset()` (for CTA) or\\n      `prev_args.next_common_runtime_args_offset()` (for CRTA).\\n    3. Otherwise, use cta_base/crta_base integer constants.\\n\\n    Examples:\\n    ```mlir\\n    // Literal offsets\\n    %c0 = arith.constant 0 : i32\\n    %args = ttkernel.TensorAccessorArgs(%c0, %c0) : (i32, i32) -> !ttkernel.TensorAccessorArgs\\n    // Generates: TensorAccessorArgs<0, 0>()\\n\\n    // CTA+CRTA chaining (common pattern)\\n    %args_src = ttkernel.TensorAccessorArgs(%c0, %c0) : (i32, i32) -> !ttkernel.TensorAccessorArgs\\n    %args_dst = ttkernel.TensorAccessorArgs(prev = %args_src) : (!ttkernel.TensorAccessorArgs) -> !ttkernel.TensorAccessorArgs\\n    // Generates: TensorAccessorArgs<args_src.next_compile_time_args_offset(), args_src.next_common_runtime_args_offset()>()\\n\\n    // Selective override: chain CTA from prev, use literal CRTA\\n    %args_custom = ttkernel.TensorAccessorArgs(prev = %args_src) {crta_expr = \\\"0\\\"} : (!ttkernel.TensorAccessorArgs) -> !ttkernel.TensorAccessorArgs\\n    // Generates: TensorAccessorArgs<args_src.next_compile_time_args_offset(), 0>()\\n\\n    // Constexpr expression (no chaining)\\n    %args_expr = ttkernel.TensorAccessorArgs(%c0, %c0) {cta_expr = \\\"get_offset()\\\"} : (i32, i32) -> !ttkernel.TensorAccessorArgs\\n    // Generates: TensorAccessorArgs<get_offset(), 0>()\\n    ```\",\n    \"operands\": [\n      { \"name\": \"cta_base\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"crta_base\", \"type\": \"Optional<I32>\" },\n      { \"name\": \"prev_args\", \"type\": \"Optional<TTKernel_TensorAccessorArgs>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTKernel_TensorAccessorArgs\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cta_expr\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"crta_expr\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"ttkernel.tile_regs_acquire\",\n    \"summary\": \"tile_regs_acquire\",\n    \"description\": \"Acquire an exclusive lock on the DST register for the MATH thread.\\n      This register is an array of 16 tiles of 32x32 elements each.\\n      This is a blocking function, i.e. this function will wait until the lock is acquired.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tile_regs_commit\",\n    \"summary\": \"tile_regs_commit\",\n    \"description\": \"Release lock on DST register by MATH thread. The lock had to be previously acquired with tile_regs_acquire.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tile_regs_release\",\n    \"summary\": \"tile_regs_release\",\n    \"description\": \"Release lock on DST register by PACK thread. The lock had to be previously acquired with tile_regs_wait.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tile_regs_wait\",\n    \"summary\": \"tile_regs_wait\",\n    \"description\": \"Acquire an exclusive lock on the DST register for the PACK thread.\\n      It waits for the MATH thread to commit the DST register.\\n      This is a blocking function, i.e. this function will wait until the lock is acquired.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tilize_block\",\n    \"summary\": \"TilizeBlockOp call.\",\n    \"description\": \"TilizeBlockOp operation\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numTiles\", \"type\": \"I32\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $numTiles `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tilize_init\",\n    \"summary\": \"TilizeInitOp call.\",\n    \"description\": \"Initialize the tilize operation. To be called once at beginning of a\\n      kernel.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numTiles\", \"type\": \"I32\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $numTiles `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.tilize_uninit\",\n    \"summary\": \"TilizeUninitOp call.\",\n    \"description\": \"Uninitialize tilize operation before re-initializing for another operation.\",\n    \"operands\": [\n      { \"name\": \"cbI\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbI `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.transpose_wh_init\",\n    \"summary\": \"TransposeInitOp call.\",\n    \"description\": \"Initialize the transpose operation. To be called once at beginning of a\\n      kernel before transpose operations.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.transpose_wh_tile\",\n    \"summary\": \"Transpose WH tile operation\",\n    \"description\": \"Performs a 32x32 transpose operation on a tile in the CB\\n      at a given index and writes the result to the DST register at index\\n      dst_tile_index.\",\n    \"operands\": [\n      { \"name\": \"icb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"itile\", \"type\": \"IndexLike\" },\n      { \"name\": \"idst\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $icb `,` $itile `,` $idst `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.transpose_wh_uninit\",\n    \"summary\": \"TransposeUninitOp call.\",\n    \"description\": \"Uninitialize transpose operation before re-initializing for another operation.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.typecast_tile\",\n    \"summary\": \"Cast the dataformat of the tile in the DST at specified index.\",\n    \"description\": \"Performs element-wise typecast operation\\n      DST[dst0_index] <- typecast<in_dataformat, out_dataformat>(DST[dst0_index])\\n      on DST register operands. The DST register buffer must be in\\n      acquired state via *tile_regs_acquire* call.\",\n    \"operands\": [\n      { \"name\": \"dst0_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"out_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst0_index `,` $in_dtype `,` $out_dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.typecast_tile_init\",\n    \"summary\": \"Init function for typecast_tile operation. Refer to documentation for any init function.\",\n    \"description\": \"Must be run before typecast_tile.\",\n    \"attributes\": [\n      { \"name\": \"in_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"out_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_dtype `,` $out_dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.unary_bcast\",\n    \"summary\": \"Broadcast operation\",\n    \"description\": \"Performs a broadcast operation *B = broadcast(A)* using bcast_dim for\\n      dimension expansion on a tile in the CB at a given index and writes the\\n      result to the DST register at index *dst_tile_index*. The supported\\n      broadcast dimensions are `row`, `col`, `scalar` (both row and column). The\\n      DST register buffer must be in acquired state via *tile_regs_acquire*\\n      call. This call is blocking and is only available on the compute engine.\",\n    \"operands\": [\n      { \"name\": \"in_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"in_tile_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_tile_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bcast_type\", \"type\": \"TTKernel_BcastTypeAttr{none|col|row|scalar}\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_cb `,` $in_tile_index `,` $dst_tile_index `,` $bcast_type `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.unary_bcast_init\",\n    \"summary\": \"Init function\",\n    \"description\": \"Must be run before bcast_tile.\",\n    \"operands\": [\n      { \"name\": \"in_cb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"out_cb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bcast_type\", \"type\": \"TTKernel_BcastTypeAttr{none|col|row|scalar}\" }\n    ],\n    \"assemblyFormat\": \"`(` $in_cb `,` $out_cb `,` $bcast_type `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.unary_op_init_common\",\n    \"summary\": \"Initialization function for unary operations.\",\n    \"description\": \"This operation initializes all necessary components for unary operations,\\n      including unpacking, packing, and math configurations.\",\n    \"operands\": [\n      { \"name\": \"icb\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"ocb\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $icb `,` $ocb `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.unreachable\",\n    \"summary\": \"Unreachable op.\",\n    \"description\": \"Unreachable operation\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.untilize_block\",\n    \"summary\": \"UntilizeBlockOp call.\",\n    \"description\": \"UntilizeBlockOp operation\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" },\n      { \"name\": \"numTiles\", \"type\": \"I32\" },\n      { \"name\": \"cbOut\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `,` $numTiles `,` $cbOut `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.untilize_init\",\n    \"summary\": \"UntilizeInitOp call.\",\n    \"description\": \"Init function for untilize operations, to be used at the beginning of the\\n      kernel.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.untilize_uninit\",\n    \"summary\": \"UntilizeUninitOp call.\",\n    \"description\": \"Uninitialize untilize operation, to allow initializing another operation.\",\n    \"operands\": [\n      { \"name\": \"cbIn\", \"type\": \"TTKernel_CB\" }\n    ],\n    \"assemblyFormat\": \"`(` $cbIn `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.where_fp32_tile\",\n    \"summary\": \"Conditional selection operation\",\n    \"description\": \"Performs element-wise conditional selection\\n      DST[odst_index] <- condition ? DST[dst_true_index] : DST[dst_false_index]\\n      For each element, if condition is non-zero, selects from dst_true_index,\\n      otherwise selects from dst_false_index.\\n      The DST register buffer must be in acquired state via *acquire_dst* call.\",\n    \"operands\": [\n      { \"name\": \"dst_cond_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_true_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_false_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_cond_index `,` $dst_true_index `,` $dst_false_index `,` $odst_index `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.where_tile\",\n    \"summary\": \"Conditional selection operation\",\n    \"description\": \"Performs element-wise conditional selection\\n      DST[odst_index] <- condition ? DST[dst_true_index] : DST[dst_false_index]\\n      For each element, if condition is non-zero, selects from dst_true_index,\\n      otherwise selects from dst_false_index.\\n      The DST register buffer must be in acquired state via *acquire_dst* call.\",\n    \"operands\": [\n      { \"name\": \"dst_cond_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_true_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"dst_false_index\", \"type\": \"IndexLike\" },\n      { \"name\": \"odst_index\", \"type\": \"IndexLike\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ],\n    \"assemblyFormat\": \"`(` $dst_cond_index `,` $dst_true_index `,` $dst_false_index `,` $odst_index `,` $dtype `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttkernel.where_tile_init\",\n    \"summary\": \"Short init function\",\n    \"description\": \"Must be run before where_tile.\",\n    \"assemblyFormat\": \"`(` `)` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttmetal.create_buffer\",\n    \"summary\": \"Create buffer op.\",\n    \"description\": \"Create buffer operation.\\n\\n      When this buffer uses a virtual grid, `virtualGridInverseMapping` stores the\\n      inverse affine map (physical to virtual grid coordinates) and\\n      `virtualGridForwardMapping` stores the forward affine map (virtual to\\n      physical grid coordinates).  Both are propagated from d2m.empty through\\n      bufferization.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"address\", \"type\": \"I64Attr\" },\n      { \"name\": \"virtualGridInverseMapping\", \"type\": \"OptionalAttr<AffineMapAttr>\" },\n      { \"name\": \"virtualGridForwardMapping\", \"type\": \"OptionalAttr<AffineMapAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.create_global_semaphore\",\n    \"summary\": \"Create global semaphore op.\",\n    \"description\": \"Create global semaphore operation\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTMetal_GlobalSemaphore\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"address\", \"type\": \"I64Attr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"core_range\", \"type\": \"TTMetal_CoreRangeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.deallocate_buffer\",\n    \"summary\": \"Deallocate buffer op.\",\n    \"description\": \"Deallocate buffer operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.enqueue_program\",\n    \"summary\": \"Enqueue program op.\",\n    \"description\": \"Enqueue program operation\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyType>\" },\n      { \"name\": \"cbs\", \"type\": \"Variadic<AnyNon0RankedMemRef>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cb_ports\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"kernelConfigs\", \"type\": \"TypedArrayAttrBase<TTMetal_KernelConfigAttr>\" },\n      { \"name\": \"fabricConnectionConfig\", \"type\": \"OptionalAttr<TTMetal_FabricConnectionConfigAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.enqueue_read_buffer\",\n    \"summary\": \"Enqueue read buffer op.\",\n    \"description\": \"Enqueue read buffer operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyNon0RankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.enqueue_write_buffer\",\n    \"summary\": \"Enqueue write buffer op.\",\n    \"description\": \"Enqueue write buffer operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedMemRef\" },\n      { \"name\": \"output\", \"type\": \"AnyNon0RankedMemRef\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.finish\",\n    \"summary\": \"Finish op for command queue.\",\n    \"description\": \"Global barrier op, used to wait for all commands on queue to finish.\"\n  },\n  {\n    \"name\": \"ttmetal.mesh_shard\",\n    \"summary\": \"Nd sharding or (partial) concat op\",\n    \"description\": \"Nd sharding or (partial) concat op in D2M runtime.\\n      ShardToFull: Nd sharding in host memory.\\n      FullToshard: (partial) concat in host memory.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyNon0RankedMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shard_type\", \"type\": \"TTCore_MeshShardTypeAttr{identity|replicate|maximal|devices}\" },\n      { \"name\": \"shard_direction\", \"type\": \"TTCore_MeshShardDirectionAttr{full_to_shard|shard_to_full}\" },\n      { \"name\": \"shard_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"shard_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttmetal.reset_global_semaphore\",\n    \"summary\": \"Reset global semaphore op.\",\n    \"description\": \"Reset global semaphore operation\",\n    \"operands\": [\n      { \"name\": \"semaphore\", \"type\": \"TTMetal_GlobalSemaphore\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttng.arrive_barrier\",\n    \"summary\": \"perform the arrive operation on an mbarrier\",\n    \"description\": \"The `ttng.arrive_barrier` operation performs the \\\"arrive\\\" operation on an\\n    mbarrier object in shared memory. The operation requires a `count` attribute\\n    of at least 1, and decreasing the pending arrival count of the mbarrier by\\n    the specific count.\\n\\n    The operation accepts an optional predicate.\\n\\n    Example:\\n\\n    ```mlir\\n    ttng.arrive_barrier %barrier, 2 : !ttg.memdesc<1xi64, #shared, #smem, mutable>\\n    ttng.arrive_barrier %barrier, 1, %pred : !ttg.memdesc<1xi64, #shared, #smem, mutable>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"Optional<I1>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $count (`,` $pred^)? attr-dict `:` qualified(type($alloc))\"\n  },\n  {\n    \"name\": \"ttng.async_copy_mbarrier_arrive\",\n    \"summary\": \"arrive on mbarrier once all previously issued copies are completed\",\n    \"operands\": [\n      { \"name\": \"barrier\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"noIncrement\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"$barrier attr-dict `:` qualified(type($barrier))\"\n  },\n  {\n    \"name\": \"ttng.async_tma_copy_global_to_local\",\n    \"summary\": \"copy data based on descriptor from global memory to local memory asynchronously\",\n    \"description\": \"This operation copies data from global memory to local memory\\n    asynchronously.  This is analogue to tt.load except the data are copied to\\n    local memory pointed by the memory descriptor instead of a distributed\\n    tensor. The data copied depends on the global memory descriptor pointed to\\n    by `desc`.\\n\\n    The tensor mode is determined by the descriptor type:\\n    - tt.tensordesc: TILED mode - Regular tiled tensor memory access\\n      - See: https://docs.nvidia.com/cuda/parallel-thread-execution/#tensor-tiled-mode\\n    - ttng.tensordesc_im2col: IM2COL mode - Im2col mode for convolution-friendly access patterns\\n      - In IM2COL mode, 'coord' is the coordinates in the input tensor\\n        - For example, for a 4D tensor (NHWC), 'coord' is [batch_idx, channel_idx, h, w]\\n      - In IM2COL mode, additional `offsets` must be provided (uint16 values)\\n        - For 3D tensors (NWC): 1 offset (offset_w)\\n        - For 4D tensors (NHWC): 2 offsets (offset_w, offset_h)\\n        - For 5D tensors (NDHWC): 3 offsets (offset_w, offset_h, offset_d)\\n        - General rule: number of offsets = coord.size() - 2\\n      - See: https://docs.nvidia.com/cuda/parallel-thread-execution/#tensor-im2col-mode\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_AnyTensorDescType\" },\n      { \"name\": \"coord\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<I16>\" },\n      { \"name\": \"barrier\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multicast\", \"type\": \"UnitAttr\" },\n      { \"name\": \"cache\", \"type\": \"DefaultValuedAttr<TT_CacheModifierAttr{none|ca|cg|wb|cs|wt|cv}, triton::CacheModifier::NONE>\" },\n      { \"name\": \"evict\", \"type\": \"DefaultValuedAttr<TT_EvictionPolicyAttr{evict_normal|evict_first|evict_last}, triton::EvictionPolicy::NORMAL>\" },\n      { \"name\": \"isVolatile\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $coord `]` (`offsets` `=` `[` $offsets^ `]`)? $result `,` $barrier `,` $pred\\n    oilist(`cacheModifier` `=` $cache | `evictionPolicy` `=` $evict)\\n    attr-dict `:` qualified(type($desc)) `,` qualified(type($barrier)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttng.async_tma_copy_local_to_global\",\n    \"summary\": \"copy data based on descriptor from local memory to global memory asynchronously\",\n    \"description\": \"This operation copies data from local memory to global memory\\n    asynchronously.  This is analogue to tt.store except the data are copied from\\n    local memory pointed by the memory descriptor instead of a distributed\\n    tensor. The data copied depends on the global memory descriptor pointed to\\n    by `desc`.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"coord\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $coord `]` $src\\n    attr-dict `:` qualified(type($desc)) `,` qualified(type($src))\"\n  },\n  {\n    \"name\": \"ttng.async_tma_gather\",\n    \"summary\": \"gather data based on descriptor from global memory to local memory asynchronously\",\n    \"description\": \"This operation gathers multiple rows of data from global memory matrix to\\n    local memory asynchronously.  This is similar to\\n    async_tma_copy_global_to_local except that each row is indexed independently.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"x_offsets\", \"type\": \"RankedTensorOf<[I32]>\" },\n      { \"name\": \"y_offset\", \"type\": \"I32\" },\n      { \"name\": \"barrier\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $x_offsets `,` $y_offset `]` $result `,` $barrier `,` $pred\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"ttng.async_tma_reduce\",\n    \"summary\": \"reduce result in gmem based on a TMA descriptor\",\n    \"description\": \"This operation copies data from local memory to global memory\\n    asynchronously, and atomically performs the specified reduction kind.\\n    Atomicity is at the granularity of individual elements, and only relaxed\\n    semantics are implied.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"coord\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"TT_DescriptorReduceKindAttr{add|min|max|inc|dec|and|or|xor}\" }\n    ],\n    \"assemblyFormat\": \"$kind `,` $desc `[` $coord `]` $src\\n    attr-dict `:` qualified(type($desc)) `,` qualified(type($src))\"\n  },\n  {\n    \"name\": \"ttng.async_tma_scatter\",\n    \"summary\": \"scatter data from local memory into global memory based on a descriptor asynchronously\",\n    \"description\": \"The `ttng.async_tma_scatter` operation scatters multiple separately-indexed\\n    rows of data from local memory into global memory asynchronously. The\\n    operation scatters a 2D tensor in shared memory, laid out by core tensor\\n    tiles nvmma_shared layout into separately indexed rows in global\\n    memory at a given `y` offset.\",\n    \"operands\": [\n      { \"name\": \"desc\", \"type\": \"TT_TensorDescType\" },\n      { \"name\": \"x_offsets\", \"type\": \"RankedTensorOf<[I32]>\" },\n      { \"name\": \"y_offset\", \"type\": \"I32\" },\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$desc `[` $x_offsets `,` $y_offset `]` $src\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"ttng.async_tma_store_wait\",\n    \"summary\": \"wait until all the inputs are read.\",\n    \"description\": \"Wait until all the read operations are done from the associated store operations.\\n    This is needed before the shared memory can be written to.\",\n    \"attributes\": [\n      { \"name\": \"pendings\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttng.barrier_expect\",\n    \"summary\": \"Signal a barrier of an expected number of bytes to be copied.\",\n    \"description\": \"This signal the barrier that `size` bytes are expected to be copied. The\\n    associated barrier wait will block until the expected number of bytes are copied.\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $size attr-dict `,` $pred `:` qualified(type($alloc))\"\n  },\n  {\n    \"name\": \"ttng.clc_get_program_id\",\n    \"summary\": \"Get CTA ID coordinate from CLC response\",\n    \"description\": \"Decodes the CLC response to get the first CTA ID coordinate of the\\n    canceled cluster. The dim attribute specifies which dimension (0=x, 1=y, 2=z).\",\n    \"operands\": [\n      { \"name\": \"clcResult\", \"type\": \"I128\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"TT_ProgramDim{x|y|z}\" }\n    ],\n    \"assemblyFormat\": \"$clcResult `,` $dim attr-dict `:` type($clcResult) `->` type($result)\"\n  },\n  {\n    \"name\": \"ttng.clc_is_canceled\",\n    \"summary\": \"Check if CLC response indicates successful cancellation\",\n    \"description\": \"Decodes the CLC response to check if a cluster was successfully\\n    canceled. Returns true if canceled, false otherwise.\",\n    \"operands\": [\n      { \"name\": \"clcResult\", \"type\": \"I128\" }\n    ],\n    \"results\": [\n      { \"name\": \"is_canceled\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$clcResult attr-dict `:` type($clcResult) `->` type($is_canceled)\"\n  },\n  {\n    \"name\": \"ttng.clc_load_result\",\n    \"summary\": \"Load CLC response from shared memory into registers\",\n    \"description\": \"Loads the 128-bit CLC response from shared memory into two i64 registers.\\n    This allows subsequent is_canceled and get_first_ctaid operations to\\n    operate on registers without re-reading shared memory.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"clcResult\", \"type\": \"I128\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` qualified(type($src)) `->` type($clcResult)\"\n  },\n  {\n    \"name\": \"ttng.clc_try_cancel\",\n    \"summary\": \"Issue CLC try_cancel to cancel a pending cluster\",\n    \"description\": \"Issues a clusterlaunchcontrol.try_cancel instruction to atomically cancel\\n    a pending cluster launch. The result is written asynchronously to the\\n    result buffer and the mbarrier is signaled on completion.\\n\\n    This is used for dynamic persistent kernels on Blackwell (SM100+).\\n\\n    The result buffer must be 16-byte aligned shared memory.\\n    The mbarrier must be 8-byte aligned shared memory.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"mbarrier\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"multicast\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"$result `,` $mbarrier attr-dict `:` qualified(type($result)) `,` qualified(type($mbarrier))\"\n  },\n  {\n    \"name\": \"ttng.cluster_arrive\",\n    \"attributes\": [\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttng.cluster_barrier\",\n    \"summary\": \"Synchronize all warps at cluster scope\",\n    \"description\": \"Lowers to a cluster arrive/wait pair.\\n\\n    In warp-specialized kernels, lowering wraps the barrier in a synthetic\\n    `ttg.warp_specialize` region so worker warps also execute the barrier.\\n    This op cannot be placed inside an existing `ttg.warp_specialize`.\",\n    \"attributes\": [\n      { \"name\": \"relaxed\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttng.cluster_wait\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttng.fence_async_shared\",\n    \"summary\": \"fence proxy async\",\n    \"attributes\": [\n      { \"name\": \"bCluster\", \"type\": \"BoolAttr\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttng.fence_mbarrier_init_release_cluster\",\n    \"summary\": \"fence mbarrier init release.cluster\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"ttng.init_barrier\",\n    \"summary\": \"Initialize a barrier in the given shared memory allocation.\",\n    \"description\": \"Initializes a shared memory allocation with mbarrier information.\\n      `alloc` is a descriptor to the shared memory allocation. `count` is the\\n      number of arrives expected by the barrier.\\n\\n      This lowers to PTX mbarrier.init.shared::cta.b64.\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"count\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $count attr-dict `:` qualified(type($alloc))\"\n  },\n  {\n    \"name\": \"ttng.inval_barrier\",\n    \"summary\": \"Invalidate a barrier allocation.\",\n    \"description\": \"Invalidate a barrier allocation so that it can be re-used. According to PTX\\n    spec this has to be done before any reuse of the memory used by mbarrier.\\n\\n    https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-inval\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"assemblyFormat\": \"$alloc attr-dict `:` qualified(type($alloc))\"\n  },\n  {\n    \"name\": \"ttng.reinterpret_tensor_descriptor\",\n    \"summary\": \"Reinterpret a pointer as a tensor descriptor\",\n    \"description\": \"This Op exists to help the transition from untyped raw TMA objects to typed Tensor descriptor objects.\\n     Ideally, we can remove this once the APIs are fully fleshed out.\",\n    \"operands\": [\n      { \"name\": \"rawDesc\", \"type\": \"TT_Ptr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_TensorDescType\" }\n    ],\n    \"assemblyFormat\": \"$rawDesc attr-dict `:` qualified(type($rawDesc))  `to` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttng.tc_gen5_commit\",\n    \"summary\": \"make an mbarrier track completion of all prior async tcgen5 ops\",\n    \"description\": \"The `ttng.tc_gen5_commit` is an asynchronous operation that makes the\\n    mbarrier object track the completion of all prior asynchronous tcgen5\\n    operations. Upon completion of all asynchronous operations, the mbarrier\\n    arrive operation is performed on the mbarrier with a count of 1.\\n\\n    If `descs` are provided, the commit will be multicast across the CTA cluster\\n    based on the shared layouts of those descriptors. This should be used when\\n    the inputs to the tcgen5 MMA come from TMA descriptors using multicast.\\n\\n    Note that the completion mechanisms are guaranteed to occur sequentially in\\n    the order the commit operations were issued. This means, for example:\\n\\n    ```mlir\\n    ttng.tmem_copy\\n    ttng.tc_gen5_mma\\n    ttng.tc_gen5_commit %barrierA\\n    ttng.tc_gen5_commit %barrierB\\n    ```\\n\\n    `%barrierA` tracks the completion of the previous TMEM copy and MMA\\n    operations, but since the commit groups are sequential, the arrive-on\\n    operation on `%barrierA` is guaranteed to be performed before the arrive-on\\n    operation on `%barrierB`, even though its commit group is empty.\",\n    \"operands\": [\n      { \"name\": \"barrier\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"pred\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"descs\", \"type\": \"Variadic<TTG_MemDescType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$barrier (`,` $pred^)? (`descs` $descs^)? attr-dict `:`\\n    qualified(type($barrier)) (`,` qualified(type($descs))^)?\"\n  },\n  {\n    \"name\": \"ttng.tc_gen5_mma\",\n    \"summary\": \"block level op mapping to tensorcore gen5 mma\",\n    \"description\": \"$d += matrix_multiply($a, $b).\\n    if is_async is false, the op executes synchronously. The barrier operands must not be present in that case.\\n    Otherwise, if a barrier is given, the op will trigger a commit/arrive on it. The result will be safe to read after a barrier wait.\\n    If $two_ctas is set the op will execute a matmul across two contiguous CTAs, it will read the data distributed across the two CTAs.\\n    and syncronize both CTAs if the op is synchronous.\\n\\n    This operation takes and produces an optional token to indicate TMEM read\\n    and write on its accumulator operand. When the tokens are present, they can\\n    be used to check aliasing and modref on the accumulator memory.\\n\\n    The `isUnsigned` attribute is only relevant when performing an integer MMA operation.\\n    If true, the integer values are treated as unsigned, otherwise they are treated as signed.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"b\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"d\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"acc_dep\", \"type\": \"Optional<TTG_AsyncToken>\" },\n      { \"name\": \"useD\", \"type\": \"I1\" },\n      { \"name\": \"pred\", \"type\": \"I1\" },\n      { \"name\": \"barriers\", \"type\": \"Variadic<TTG_MemDescType>\" },\n      { \"name\": \"barrier_preds\", \"type\": \"Variadic<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_async\", \"type\": \"UnitAttr\" },\n      { \"name\": \"two_ctas\", \"type\": \"UnitAttr\" },\n      { \"name\": \"multicast\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_unsigned\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $d `` custom<Token>($acc_dep, type($token)) `,` $useD`,`\\n    $pred `` custom<BarriersAndPreds>($barriers, $barrier_preds)\\n    attr-dict `:` qualified(type($a)) `,` qualified(type($b)) `,`\\n    qualified(type($d)) (`,` qualified(type($barriers))^)?\"\n  },\n  {\n    \"name\": \"ttng.tc_gen5_mma_scaled\",\n    \"summary\": \"block level op mapping to tensorcore gen5 mma\",\n    \"description\": \"$d += matrix_multiply(scale($lhs, $lhs_scale), scale(rlhs, $rhs_scale))\\n    If $two_ctas is set the op will execute a matmul across two contiguous CTAs, it will read the data distributed across the two CTAs\\n    and synchronize both CTAs if the op is synchronous.\\n    If is_async is false, the op executes synchronously. The barrier operands must not be present in that case.\\n    Otherwise, if a barrier is given, the op will trigger a commit/arrive on it.\\n    The result will be safe to read after a barrier wait.\\n\\n    This operation takes and produces an optional token to indicate TMEM read\\n    and write on its accumulator operand. When the tokens are present, they can\\n    be used to check aliasing and modref on the accumulator memory.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"b\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"d\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"acc_dep\", \"type\": \"Optional<TTG_AsyncToken>\" },\n      { \"name\": \"a_scale\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"b_scale\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"useD\", \"type\": \"I1\" },\n      { \"name\": \"pred\", \"type\": \"I1\" },\n      { \"name\": \"barriers\", \"type\": \"Variadic<TTG_MemDescType>\" },\n      { \"name\": \"barrier_preds\", \"type\": \"Variadic<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"a_type\", \"type\": \"TT_ScaleDotElemTypeAttr{e4m3|e5m2|e2m3|e3m2|e2m1|bf16|fp16}\" },\n      { \"name\": \"b_type\", \"type\": \"TT_ScaleDotElemTypeAttr{e4m3|e5m2|e2m3|e3m2|e2m1|bf16|fp16}\" },\n      { \"name\": \"two_ctas\", \"type\": \"UnitAttr\" },\n      { \"name\": \"is_async\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $d `` custom<Token>($acc_dep, type($token)) `,` $a_scale `,`\\n    $b_scale `,` $useD `,` $pred `lhs` `=` $a_type `rhs` `=` $b_type\\n    `` custom<BarriersAndPreds>($barriers, $barrier_preds)\\n    attr-dict `:` qualified(type($a)) `,` qualified(type($b)) `,`\\n    qualified(type($d)) `,` qualified(type($a_scale)) `,`\\n    qualified(type($b_scale)) (`,` qualified(type($barriers))^)?\"\n  },\n  {\n    \"name\": \"ttng.tensormap_create\",\n    \"summary\": \"Create a new TMA descriptor on device\",\n    \"operands\": [\n      { \"name\": \"desc_ptr\", \"type\": \"TT_PtrType\" },\n      { \"name\": \"global_address\", \"type\": \"TT_PtrType\" },\n      { \"name\": \"box_dim\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"global_dim\", \"type\": \"Variadic<I32>\" },\n      { \"name\": \"global_stride\", \"type\": \"Variadic<I64>\" },\n      { \"name\": \"element_stride\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elem_type\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<15>]>\" },\n      { \"name\": \"interleave_layout\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<2>]>\" },\n      { \"name\": \"swizzle_mode\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<3>]>\" },\n      { \"name\": \"fill_mode\", \"type\": \"ConfinedAttr<I32Attr, [IntNonNegative, IntMaxValue<1>]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$desc_ptr `,` $global_address `,`\\n    `[` $box_dim `]` `,`\\n    `[` $global_dim `]` `,`\\n    `[` $global_stride `]` `,`\\n    `[` $element_stride `]`\\n    attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttng.tensormap_fenceproxy_acquire\",\n    \"summary\": \"Acquire fence on a tensormap object\",\n    \"operands\": [\n      { \"name\": \"desc_ptr\", \"type\": \"TT_PtrType\" }\n    ],\n    \"assemblyFormat\": \"$desc_ptr attr-dict `:` qualified(type($desc_ptr))\"\n  },\n  {\n    \"name\": \"ttng.tmem_alloc\",\n    \"summary\": \"allocate tensor memory\",\n    \"description\": \"This operation allocates buffer in tensor memory and return a descriptor\\n    containing the address and a view of the buffer.\\n    This is similar to ttg.local_alloc except the buffer is allocated in tensor memory.\\n\\n    Explicitly deallocating a buffer is optional; see local_dealloc.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"Optional<TT_Tensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"($src^)? attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"ttng.tmem_copy\",\n    \"summary\": \"Initiate an asynchronous copy operation from shared memory to the Tensor Memory.\",\n    \"description\": \"2D blocks stored contiguously in SMEM are copied into TMEM as specified by the destination address.\\n    The completion of the copy can be observed by waiting on the optional barrier. If this op is used\\n    together with an MMA op, one barrier can be used to wait for both copy and MMA. We do not need to wait\\n    for the completion of the copy before MMA, since tcgen05.cp followed by tcgen05.mma is guaranteed to\\n    execute in that order.\\n\\n    This op lowers to the PTX instruction tcgen05.cp. This supports writing either to scales tmem layout as well as default tmem layout.\\n    Currently the semantic is different when writing to tmem scale layout.\\n\\n    In case of default layout the copy doesn't change the logical elements between the source and destination memdesc.\\n\\n    In case of scale layout:\\n    Each 32x128b block in SMEM is duplicated over 4 warps and stored into 128 rows\\n    and 4 columns of TMEM. The primary use case of this op is to copy blocked scales from SMEM to TMEM.\\n\\n    The shape of the input SMEM can be flexibily chosen depending on use cases. In the simplest case (e.g. unit test),\\n    the source SMEM can be of shape (32 x num_blocks, 16), and the destination TMEM should be of shape (128, 16 x num_blocks),\\n    for copying 8 bit values. For scaled GEMM, rep_m x rep_k copies of a 32x128b block need to be stored in SMEM, where\\n    rep_m = BLOCK_M / 128, rep_k = BLOCK_K / scale_vec_size / 4, and scale_vec_size = 32 for MXFP.\\n    Conceptually, the SMEM is organized in a high-dimensional layout, (rep_m, rep_k, 32, 4, 4B).\\n    Some of axes can be flattened into one, to reduce the rank of the load. For example, the following patterns are supported:\\n     * (rep_m, rep_k * 32 x 4 x 4B), 2D scale load with cp.async\\n     * (rep_m, rep_k, 32, 16B), 4D scale load with TMA\\n     * (rep_m, rep_k, 32, 4, 4B), 5D scale load with cp.async\\n    Since rep_m blocks are not contiguous in SMEM, this axis cannot be flattened into inner ones.\\n\\n    In Triton, the TMEM memdesc for blocked scales must be of the following form:\\n    * Its shape must be (BLOCK_MN, BLOCK_K / scale_vec_size), representing the logical shape of blocked scales.\\n    * It must be attached with `tensor_memory_scales_encoding` to indicate the chunk-based layout and its duplication over 4 warps.\\n\\n    In contrast, the src SMEM must be in the explicit chunk-based layout as described above. So the IR might look like this:\\n\\n    %0 = ttng.tmem_alloc : () -> !ttg.memdesc<128x4xi8, #tmem_scales, #ttng.tensor_memory>\\n    ttng.tmem_copy %1, %0 : (!ttg.memdesc<1x1x32x4x4xi8, #shared1, #smem>, !ttg.memdesc<128x4xi8, #tmem_scales, #ttng.tensor_memory>) -> ()\\n\\n    We interpret the semantics of this copy operation as follows. The chunk-based layout in SMEM implies that\\n    the logical shape (BLOCK_MN, BLOCK_K / scale_vec_size) in TMEM is the result of certain reshape and transpose operations.\\n    In practice, to take an advantage of the native scale layout and the TMEM copy op,  users need to do\\n    `scales5D.trans(0, 3, 2, 1, 4).reshape(BLOCK_M, BLOCK_K // scale_vec_size)` before feeding scales into dot_scaled.\\n    When we use tmem_copy in the IR, such reshape and transpose operations are removed. But the change in the logical shape they have caused on\\n    registers is now understood to be incorporated into tmem_copy itself. Ideally, we would lift reshape / transpose done on registers onto\\n    the SMEM memdesc, making tmem_copy a straightforward 2D copy operation: (BLOCK_MN, BLOCK_K / scale_vec_size) -> (BLOCK_MN, BLOCK_K / scale_vec_size).\\n    In the absence of such operations on memdesc, we resort to implicitly encoding the reshape/transpose semantics in tmem_copy.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"dst\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"barrier\", \"type\": \"Optional<TTG_MemDescType>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $dst (`,` $barrier^)? attr-dict `:` qualified(type(operands))\"\n  },\n  {\n    \"name\": \"ttng.tmem_load\",\n    \"summary\": \"Load a buffer from tensor memory into a distributed tensor\",\n    \"description\": \"This is similar to ttg.local_load except the result layout is restricted to only few possibility.\\n    Therefore we cannot combine this op with any convert layout like local_load.\\n\\n    This operation takes and produces an optional token to indicate TMEM read\\n    on its source operand. When the tokens are present, they can\\n    be used to check aliasing and modref on the TMEM buffer.\\n\\n    Optional reduction modifier:\\n    When `redOp` is specified, the load operation additionally performs an\\n    element-wise reduction along the N-dimension of the input and produces a\\n    second result tensor `red`. For a input of shape `[M, N]`, the\\n    reduced result has shape `[M]`, containing one reduced value per \\\"slice\\\"\\n    of the N-dimension.\\n\\n    Currently restricted to f32 element type.\\n\\n    - redOp: Specifies the reduction operation (MIN or MAX) to apply along\\n             the N-dimension. When set, the `red` result must be present.\\n    - abs:   When true, applies absolute value to each element before performing\\n             the reduction. Only valid when `redOp` is specified.\\n    - NaN:   When true, the reduction propagates NaN values (if any input element\\n             in a slice is NaN, the corresponding reduced value is NaN).\\n             When false, NaN values are ignored during reduction.\\n             Only valid when `redOp` is specified.\\n\\n    Example:\\n      Input in TMEM of shape[M=2, N=4]:\\n        [[ 1.0, 3.0, 2.0, 4.0],\\n         [-5.0, 1.0, 8.0, 2.0]]\\n\\n      With redOp=MAX:\\n        result = [[ 1.0, 3.0, 2.0, 4.0],   // unchanged\\n                  [-5.0, 1.0, 8.0, 2.0]]\\n        red    = [4.0, 8.0]               // max along N per row\\n\\n      With redOp=MIN, abs=true:\\n        red    = [1.0, 1.0]               // min of |values| per row\\n\\n    This operation lowers to hardware-accelerated reduction via the PTX\\n    tcgen05.ld.red instruction on supported architectures, e.g. Blackwell Ultra.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"dep\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" },\n      { \"name\": \"red\", \"type\": \"Optional<TT_Tensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"redOp\", \"type\": \"OptionalAttr<TTNG_TMEMLoadReduceModifierEnum{min|max}>\" },\n      { \"name\": \"abs\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"NaN\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ],\n    \"assemblyFormat\": \"$src `` custom<Token>($dep, type($token))\\n    attr-dict `:` qualified(type($src)) `->` type($result) (`,` type($red)^)?\"\n  },\n  {\n    \"name\": \"ttng.tmem_store\",\n    \"summary\": \"Store a distributed tensor into a buffer in tensor memory\",\n    \"description\": \"This is similar to ttg.local_store except the source layout is restricted to only few possibility.\\n\\n    This operation takes and produces an optional token to indicate TMEM write\\n    on its source operand. When the tokens are present, they can\\n    be used to check aliasing and modref on the TMEM buffer.\",\n    \"operands\": [\n      { \"name\": \"dst\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"dep\", \"type\": \"Optional<TTG_AsyncToken>\" },\n      { \"name\": \"src\", \"type\": \"TT_Tensor\" },\n      { \"name\": \"pred\", \"type\": \"I1\" }\n    ],\n    \"results\": [\n      { \"name\": \"token\", \"type\": \"Optional<TTG_AsyncToken>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $dst `` custom<Token>($dep, type($token)) `,` $pred\\n    attr-dict `:` type($src) `->` qualified(type($dst))\"\n  },\n  {\n    \"name\": \"ttng.tmem_subslice\",\n    \"summary\": \"Take a subslice of a tensor memory allocation\",\n    \"description\": \"This operation takes a subslice of a tensor memory allocation and returns a new descriptor\\n    containing the address and a view of the subslice.\\n    This is similar to ttg.memdesc_subslice except we can only slice along the inner dimension\\n    of a 2D memdesc as this is the only one we can do for TMem.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTG_MemDescType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"N\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$src attr-dict `:` qualified(type($src)) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"ttng.wait_barrier\",\n    \"summary\": \"wait until the mbarrier phase completes.\",\n    \"description\": \"Blocks the program progress until the mbarrier object in `alloc` completes\\n    its current phase.\\n\\n    This lowers a waitloop using PTX instruction\\n    mbarrier.try_wait.parity.shared::cta.b64.\\n\\n    Accepts optional list of memory. If present, it is assumed that any of the\\n    dependencies may be accessed until the barrier completes.\\n\\n    The barrier behavior is described here:\\n    https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-asynchronous-copy-completion-mechanisms\",\n    \"operands\": [\n      { \"name\": \"alloc\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"phase\", \"type\": \"I32\" },\n      { \"name\": \"pred\", \"type\": \"Optional<I1>\" },\n      { \"name\": \"deps\", \"type\": \"Variadic<TTG_MemDescType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$alloc `,` $phase (`,` $pred^)? (`deps` $deps^)?\\n    attr-dict `:` qualified(type($alloc)) (`,` type($deps)^)?\"\n  },\n  {\n    \"name\": \"ttng.warp_group_dot\",\n    \"summary\": \"warp group dot\",\n    \"description\": \"$d = matrix_multiply($a, $b) + $c. For docs on InputPrecisionAttr, see TT_DotOp\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"TTG_TensorOrMemDesc\" },\n      { \"name\": \"b\", \"type\": \"TTG_MemDescType\" },\n      { \"name\": \"c\", \"type\": \"TT_FpIntTensor\" },\n      { \"name\": \"useC\", \"type\": \"Optional<I1>\" }\n    ],\n    \"results\": [\n      { \"name\": \"d\", \"type\": \"TT_FpIntTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"inputPrecision\", \"type\": \"DefaultValuedAttr<TT_InputPrecisionAttr{tf32|tf32x3|ieee|bf16x3|bf16x6}, ::mlir::triton::InputPrecision::IEEE>\" },\n      { \"name\": \"maxNumImpreciseAcc\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" },\n      { \"name\": \"isAsync\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'d', 'c', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$a`,` $b`,` $c (`,` $useC^)? attr-dict\\n    `:` type($a) `*` qualified(type($b)) `->` type($d)\"\n  },\n  {\n    \"name\": \"ttng.warp_group_dot_wait\",\n    \"summary\": \"warp group dot wait\",\n    \"description\": \"Waits until there are $pendings or fewer outstanding async dot operations.\\n\\n    $inputs must be the tensors corresponding to the async dot ops that we're\\n    waiting on.  For example, if there are N pending async dot ops and we call\\n    `warp_group_dot_wait 1`, then $inputs must be the result of the first dot op.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<TTG_TensorOrMemDesc>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<TTG_TensorOrMemDesc>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pendings\", \"type\": \"I32Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['inputs', 'outputs']>\" }\n    ],\n    \"assemblyFormat\": \"$inputs attr-dict `:` type($inputs)\"\n  },\n  {\n    \"name\": \"ttnn.abs\",\n    \"summary\": \"Eltwise absolute.\",\n    \"description\": \"Eltwise absolute operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.add\",\n    \"summary\": \"Eltwise add.\",\n    \"description\": \"Eltwise add operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.aggregate_tensor\",\n    \"summary\": \"Aggregate distributed tensor back to host\",\n    \"description\": \"Aggregates a multi-device tensor back into a single host-side tensor\\n    according to the specified composer configuration.\\n\\n    This operation takes a distributed tensor and creates a single-device\\n    host tensor aggregated according to the MeshComposerConfig configuration.\\n\\n    // Note: In the ttnn API, the aggregate_tensor op takes an input tensor and a MeshToTensor object as its arguments.\\n    // To create a MeshToTensor object, the API create_mesh_composer is used, which requires both MeshComposerConfig and MeshDevice.\\n    // Instead of modeling create_mesh_composer as a separate op in the IR, these two strongly coupled APIs are combined into one aggregate_tensor op\\n    // to keep the IR simple and less cluttered. If a clear need arises in the future, splitting them into separate ops can be considered.\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"ttnn.aggregate_tensor\\\"(%input, %device) <{\\n      composer_config = #ttnn.mesh_composer_config<\\n        dims = [1],\\n        mesh_shape_override = #ttnn.mesh_shape<2x2>\\n      >\\n    }> : (tensor<32x64xbf16>, !ttnn.device) -> tensor<32x64xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mesh_device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"composer_config\", \"type\": \"TTNN_MeshComposerConfigAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.all_gather\",\n    \"summary\": \"All gather op.\",\n    \"description\": \"Tensor All Gather operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"all_gather_dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" },\n      { \"name\": \"sub_device_id\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"num_links\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"topology\", \"type\": \"OptionalAttr<TTCore_TopologyAttr{ring|linear|mesh|torus|disabled}>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.all_reduce\",\n    \"summary\": \"All reduce op.\",\n    \"description\": \"Tensor All Reduce operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_type\", \"type\": \"TTCore_ReduceTypeAttr{sum|mean|max|min|std|var|prod|invalid}\" },\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" },\n      { \"name\": \"sub_device_id\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"num_links\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"topology\", \"type\": \"OptionalAttr<TTCore_TopologyAttr{ring|linear|mesh|torus|disabled}>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.all_to_all_combine\",\n    \"summary\": \"Combine expert outputs back to original token positions.\",\n    \"description\": \"Inverse of dispatch: gathers expert computation results from expert devices\\n      and restores tokens to their original device and order.\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_metadata\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_mapping\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_devices\", \"type\": \"I64Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"num_experts_per_tok\", \"type\": \"I64Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.all_to_all_dispatch\",\n    \"summary\": \"Dispatch tokens to expert devices for MoE computation.\",\n    \"description\": \"Routes tokens to devices holding their selected experts via all-to-all\\n      communication. Used before sparse_matmul in the MoE dispatch/combine flow.\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_indices\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_mapping\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"dispatched\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"metadata\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_devices\", \"type\": \"I64Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.alloc\",\n    \"summary\": \"Alloc op.\",\n    \"description\": \"Tensor Alloc operation\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"address\", \"type\": \"I64Attr\" },\n      { \"name\": \"size\", \"type\": \"I64Attr\" },\n      { \"name\": \"buffer_type\", \"type\": \"TTNN_BufferTypeAttr{dram|l1|system_memory|l1_small|trace}\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.arange\",\n    \"summary\": \"Arange operation.\",\n    \"description\": \"Tensor arange operation.\\n\\n    Produces a (1, 1, 1, N)-shaped tensor with values from `start` to `end` (exclusive) with a step size of `step`.\\n\\n    Examples:\\n      %0 = \\\"ttnn.arange\\\"() {start = 0 : i64, end = 5 : i64 step = 1 : i64} : () -> tensor<1x1x1x5xi64>\\n      // %0: [[[[0, 1, 2, 3, 4]]]]\\n\\n      %1 = \\\"ttnn.arange\\\"() {start = 0 : i64, end = 10 : i64, step = 2 : i64} : () -> tensor<1x1x1x5xf32>\\n      // %1: [[[[0.0, 2.0, 4.0, 6.0, 8.0]]]]\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<TTNN_Device>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start\", \"type\": \"I64Attr\" },\n      { \"name\": \"end\", \"type\": \"I64Attr\" },\n      { \"name\": \"step\", \"type\": \"I64Attr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<TTNN_LayoutAttr{row_major|tile|invalid}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.argmax\",\n    \"summary\": \"Argmax reduction op.\",\n    \"description\": \"Determine the indices of the maximum values along a specified dimension of a tensor or over all elements in a tensor.\\n\\n    Parameters:\\n      - `input`: The input tensor.\\n      - `dim`: Specifies the dimension along which the argmax is applied.\\n      - `keep_dim`: If set to true, the output tensor will have the same number of dimensions as the input tensor.\\n      - `use_multicore`: Whether to use multiple cores or not.\\n\\n    IR usage:\\n    // Input tensor of shape (128, 28, 28, 64)\\n    %input = ... : tensor<128x28x28x64xbf16>\\n\\n    %empty = \\\"ttnn.empty\\\"(%0) <{dtype = #ttcore.supportedDataTypes<u32>, ....}> : -> tensor<128x28x28xi32>\\n    %4 = \\\"ttnn.argmax\\\"(%input, %empty) <{dim = 3 : i32, use_multicore = false}> : (tensor<128x28x28xbf16>, tensor<128x28x28xi32) -> tensor<128x28x28xi32>\\n\\n    Example:\\n      input: [[1, 5, 3],\\n              [2, 4, 6]]\\n\\n      // Computing along dim 0\\n      output: [1, 0, 1]\\n\\n      // Computing along dim 1\\n      output: [1, 2]\\n\\n      // Computing for entire tensor\\n      output: 5\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"keep_dim\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"use_multicore\", \"type\": \"BoolAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.assign\",\n    \"summary\": \"Assign Tensor\",\n    \"description\": \"Returns a new tensor which is a new copy of input tensor.\\n      Alternatively, copies input tensor ``input`` to ``optional_output_tensor``\\n      if their shapes and memory layouts match, and returns input_b tensor.\\n      Input tensors can be of any data type.\\n      Output tensor will be of same data type as Input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.atan\",\n    \"summary\": \"Eltwise arctangent op.\",\n    \"description\": \"Performs an elementwise arctangent (`atan`) operation on the input tensor.\\n      This operation computes the inverse tangent of each element, returning\\n      values in the range [-π/2, π/2]. Supports floating-point tensor types.\\n\\n      Example:\\n\\n      ```mlir\\n      %input = tensor<4xf32> {1.0, 0.5, 0.0, -1.0}\\n      %result = \\\"ttir.atan\\\"(%input) : (tensor<4xf32>) -> tensor<4xf32>\\n      ```\\n\\n      Given the input `[1.0, 0.5, 0.0, -1.0]`, the result would be approximately:\\n      `[0.785, 0.464, 0.0, -0.785]` (values in radians).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.atan2\",\n    \"summary\": \"Eltwise atan2 OP.\",\n    \"description\": \"Performs element-wise atan2 operation on lhs and rhs tensor and produces a result\\n      tensor.\\n\\n      Example:\\n      ```\\n        // %lhs: [0.0, 1.0, -1.0]\\n        // %rhs: [1.0, 0.0, 0.0]\\n        %result = \\\"ttnn.atan2\\\"(%lhs, %rhs) : (tensor<3xf64>, tensor<3xf64>) -> tensor<3xf64>\\n        // %result: [0.0, 1.57079637, -1.57079637] // [0.0, pi/2, -pi/2]\\n      ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.avg_pool2d\",\n    \"summary\": \"Applies a 2D average pooling over an input signal composed of several input planes.\",\n    \"description\": \"It is a downsampling operation to reduce the spatial dimensions (height and width) of a input tensor by computing averages with in a window.\\n\\n    Example:\\n      // 3x3 input tensor\\n      input: [[1, 2, 3],\\n              [4, 5, 6],\\n              [7, 8, 9]]\\n      kernel_height: 2\\n      kernel_width: 2\\n      stride_height: 1\\n      stride_width: 1\\n      dilation_height: 1\\n      dilation_width: 1\\n      output: [[3, 4],\\n               [6, 7]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_size\", \"type\": \"SI32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"SI32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"SI32Attr\" },\n      { \"name\": \"channels\", \"type\": \"SI32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"applied_shard_scheme\", \"type\": \"OptionalAttr<TTNN_TensorMemoryLayoutAttr{interleaved|height_sharded|width_sharded|block_sharded|nd_sharded}>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"reallocate_halo_output\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"count_include_pad\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"config_tensors_in_dram\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.batch_norm_inference\",\n    \"summary\": \"Batch normalization inference op.\",\n    \"description\": \"Batch normalization operation for inference over each channel on input tensor.\\n      Uses pre-computed mean and variance.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"running_var\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.batch_norm_training\",\n    \"summary\": \"Batch normalization training op.\",\n    \"description\": \"Batch normalization operation for training over each channel on input tensor.\\n      Computes batch statistics and updates running mean and variance.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"running_mean\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"running_var\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-05>\" },\n      { \"name\": \"momentum\", \"type\": \"DefaultValuedAttr<F32Attr, 0.1>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.begin_trace_capture\",\n    \"summary\": \"Begin trace capture.\",\n    \"description\": \"Begins trace capture. Returns a scalar tensor containing the trace id.\\n    Inputs:\\n      - `device` TTNN_Device: The device to capture the trace on.\\n      - `cq_id` ui32: The command queue to capture the trace with. Must be 0 or 1.\\n    Outputs:\\n      - `trace_id` AnyRankedTensor: The scalar trace id tensor containing the trace id.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"trace_id\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cq_id\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.bitwise_and\",\n    \"summary\": \"Eltwise bitwise AND.\",\n    \"description\": \"Performs element-wise bitwise AND of two tensors `lhs` and `rhs`\\n        and produces a `result` tensor.\\n\\n        Example:\\n            // %lhs: [[1, 2], [3, 4]]\\n            // %rhs: [[5, 6], [7, 8]]\\n            %result = \\\"ttnn.bitwise_and\\\"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n            // %result: [[1, 2], [3, 0]]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.bitwise_not\",\n    \"summary\": \"Eltwise bitwise NOT.\",\n    \"description\": \"Performs element-wise NOT of tensor `operand` and produces a `result` tensor.\\n\\n        Example:\\n            // Bitwise operation with with integer tensors\\n            // %operand: [[1, 2], [3, 4]]\\n            %result = \\\"ttnn.bitwise_not\\\"(%operand) : (tensor<2x2xi32>) -> tensor<2x2xi32>\\n            // %result: [[-2, -3], [-4, -5]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.bitwise_or\",\n    \"summary\": \"Eltwise bitwise OR.\",\n    \"description\": \"Performs element-wise bitwise OR of two tensors `lhs` and `rhs`\\n        and produces a `result` tensor.\\n\\n        Example:\\n            // %lhs: [[1, 2], [3, 4]]\\n            // %rhs: [[5, 6], [7, 8]]\\n            %result = \\\"ttnn.bitwise_or\\\"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n            // %result: [[5, 6], [7, 12]]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.bitwise_xor\",\n    \"summary\": \"Eltwise bitwise XOR.\",\n    \"description\": \"Performs element-wise bitwise XOR of two tensors `lhs` and `rhs`\\n        and produces a `result` tensor.\\n\\n        Example:\\n          // %lhs: [[1, 2], [3, 4]]\\n          // %rhs: [[5, 6], [7, 8]]\\n          %result = \\\"ttnn.bitwise_xor\\\"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>\\n          // %result: [[4, 4], [4, 12]]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.capture_or_execute_trace\",\n    \"summary\": \"Capture or execute trace.\",\n    \"description\": \"Captures or executes the trace. Will have read/write memory effects on the cached trace data.\\n    If the trace data exists (meaning the trace was captured previously), it will be executed with\\n    the execute_callee function. Otherwise, the trace will be captured with the capture_callee function.\\n\\n    Inputs:\\n      - `device` TTNN_Device: The device where the trace was captured.\\n      - `capture_callee` FlatSymbolRefAttr: The symbol of the capture trace function.\\n      - `execute_callee` FlatSymbolRefAttr: The symbol of the execute trace function.\\n      - `inputs` Variadic<AnyRankedTensor>: The input tensors to the trace function.\\n    Outputs:\\n      - `results` Variadic<AnyRankedTensor>: The output tensors from the trace function.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"capture_callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"execute_callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.cbrt\",\n    \"summary\": \"Eltwise cubic root.\",\n    \"description\": \"Eltwise cubic root operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.ceil\",\n    \"summary\": \"Eltwise ceil.\",\n    \"description\": \"Eltwise ceil operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.clamp_scalar\",\n    \"summary\": \"Clamp op.\",\n    \"description\": \"Clamp tensor values to a specified range.\\n\\n      Example:\\n        min: 2.000000+00\\n        input: [[0, 1, 2, 3, 4, 5, 6, 7]]\\n        max: 5.000000+00\\n\\n        \\\"ttnn.clamp_scalar\\\"(%arg0) <{max = 2.000000e+00 : f32, min = 5.000000e+00 : f32}>\\n        -> %out = [[2, 2, 2, 3, 4, 5, 5, 5]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" },\n      { \"name\": \"max\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.clamp_tensor\",\n    \"summary\": \"Clamp op.\",\n    \"description\": \"Clamp tensor values to a specified range using min/max as tensor.\\n\\n    Example:\\n      min:   [[2, 2, 2, 3, 3, 3, 0, 0]]\\n      input: [[0, 1, 2, 3, 4, 5, 6, 7]]\\n      max:   [[5, 5, 5, 9, 9, 9, 6, 6]]\\n\\n      \\\"ttnn.clamp_tensor\\\"(%input, %min, %max)\\n      %out:  [[2, 2, 2, 3, 4, 5, 6, 6]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"min\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"max\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.concat\",\n    \"summary\": \"Concat op.\",\n    \"description\": \"Concat tensors along a given dimension.\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.concatenate_heads\",\n    \"summary\": \"Concatenate heads op used in attention layer.\",\n    \"description\": \"Takes in a tensor of shape [batch_size, num_heads, sequence_size, head_size],\\n      concatenates heads back along the width dimension and returns the tensor\\n      of shape [batch_size, sequence_size, num_heads * head_size].\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.constant\",\n    \"summary\": \"Constant op.\",\n    \"description\": \"Produces tensor filled with given constant value.\\n\\n      Examples:\\n        %0 = \\\"ttnn.constant\\\"() {value = dense<[[3, 4, 2], [1, 7, 8]]> : tensor<2x3xui16>} : () -> tensor<2x3xui16>\\n        // %0: [[3, 4, 2], [1, 7, 8]]\\n        %1 = \\\"ttnn.constant\\\"() {value = dense<[0.2, 1.3]> : tensor<2xf32>} : () -> tensor<2xf32>\\n        // %1: [0.2, 1.3]\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<TTNN_Device>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"ElementsAttr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<TTNN_LayoutAttr{row_major|tile|invalid}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.conv_transpose2d\",\n    \"summary\": \"ConvTranspose2d operation.\",\n    \"description\": \"Applies a 2D transposed convolution operator over an input image composed of several input planes.\\n\\n      Inputs:\\n        - `input` AnyRankedTensor: expected in the following format (N, H_in, W_in, C) where:\\n          - N is the batch size\\n          - H_in is the height of the input planes\\n          - W_in is the width of the input planes\\n          - C is the number of channels\\n\\n        - `weight` AnyRankedTensor: expected in the following format (C, O/G, K_H, K_W).\\n        - `bias` Optional<AnyRankedTensor>: expected in the following format (1, 1, 1, O) where:\\n          - C is the number of input channels\\n          - O is the number of output channels\\n          - G is the number of groups\\n          - K_H is the height of the kernel\\n          - K_W is the width of the kernel\\n\\n        - `output` AnyRankedTensor: expected in the following format (N, H_out, W_out, O) where:\\n          - H_out = (H_in - 1) * stride[0] - 2 * padding[0] + dilation[0] * (K_H - 1) + output_padding[0] + 1\\n          - W_out = (W_in - 1) * stride[1] - 2 * padding[1] + dilation[1] * (K_W - 1) + output_padding[1] + 1\\n\\n      Attributes:\\n        - `in_channels` i32: The number of input channels.\\n        - `out_channels` i32: The number of output channels.\\n        - `batch_size` i32: The batch size.\\n        - `input_height` i32: The input height.\\n        - `input_width` i32: The input width.\\n        - `kernel_size` array<2xi32>: The kernel size.\\n        - `stride` array<2xi32>: Controls the stride for the cross-correlation.\\n        - `padding` array<2xi32>: Controls the amount of implicit zero padding on both sides for dilation * (kernel_size - 1) - padding number of points.\\n        - `output_padding` array<2xi32>: Controls the additional size added to one side of the output shape.\\n        - `dilation` array<2xi32>: Controls the spacing between the kernel points\\n        - `groups` i32: Controls the connections between inputs and outputs. Must be divisible by input and output channels.\\n\\n      Example:\\n        // %input: tensor<3x8x8x256xbf16>\\n        // %weight: tensor<256x256x3x3xbf16>\\n        // %bias: tensor<1x1x1x256xbf16>\\n        // %output: tensor<3x10x10x256xbf16>\\n        %0 = \\\"ttnn.conv_transpose2d\\\"(%input, %weight, %bias, %output, %device)\\n          <{\\n            batch_size = 3: i32,\\n            dilation = array<i32: 1, 1>,\\n            groups = 1: i32,\\n            in_channels = 256: i32,\\n            input_height = 8: i32,\\n            input_width = 8: i32,\\n            kernel_size = array<i32: 3, 3>,\\n            out_channels = 256: i32,\\n            output_padding = array<i32: 0, 0>,\\n            padding = array<i32: 0, 0>,\\n            stride = array<i32: 1, 1>\\n          }> : (tensor<3x8x8x256xbf16>, tensor<256x256x3x3xbf16>, tensor<1x1x1x256xbf16>, tensor<3x10x10x256xbf16>) -> tensor<3x10x10x256xbf16>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"output_padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv2d_config\", \"type\": \"OptionalAttr<TTNN_Conv2dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"conv2d_slice_config\", \"type\": \"OptionalAttr<TTNN_Conv2dSliceConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.conv2d\",\n    \"summary\": \"Conv2d operation.\",\n    \"description\": \"Applies a 2D convolution over an input image composed of several input planes.\\n\\n      Inputs:\\n      - `input` (AnyRankedTensor): expected in the following flattened format (1, 1, N * H_in * W_in, C) where:\\n        - N is the batch size\\n        - H_in is the height of the input planes\\n        - W_in is the width of the input planes\\n        - C is the number of channels\\n      - `weight` (AnyRankedTensor): expected in the following format (O, C/G, K_H, K_W).\\n      - `bias` (Optional<AnyRankedTensor>): expected in the following format (1, 1, 1, O) where:\\n        - C is the number of input channels\\n        - O is the number of output channels\\n        - G is the number of groups\\n        - K_H is the height of the kernel\\n        - K_W is the width of the kernel\\n\\n      Attributes:\\n      - `in_channels` (i32): The number of input channels.\\n      - `out_channels` (i32): The number of output channels.\\n      - `batch_size` (i32): The batch size.\\n      - `input_height` (i32): The input height.\\n      - `input_width` (i32): The input width.\\n      - `kernel_size` (array<2xi32>): [K_H, K_W] where K_H is the kernel height and K_W is the kernel width.\\n      - `stride` (array<2xi32>): [sH, sW] where sH is stride for height and sW is stride for width.\\n      - `padding` (array<2xi32> | array<4xi32>):\\n        - array<2xi32>: [pH, pW] where pH is padding for height (top/bottom) and pW is padding for width (left/right).\\n        - array<4xi32>: [pT, pB, pL, pR] for top, bottom, left, and right padding respectively.\\n      - `dilation` (array<2xi32>): [dH, dW] where dH is dilation for height and dW is dilation for width.\\n      - `groups` (i32): Number of blocked connections from input channels to output channels. Input and output channels must both be divisible by groups.\\n\\n      Outputs:\\n      - `result` (AnyRankedTensor): returned in the following flattened format (1, 1, N * H_out * W_out, O) where:\\n        - `H_out = (H_in + pT + pB - dH * (K_H - 1) - 1) / sH + 1`\\n        - `W_out = (W_in + pL + pR - dW * (K_W - 1) - 1) / sW + 1`\\n\\n      Example:\\n        %input = ttir.empty() : () -> tensor<1x1x1024x64xbf16>\\n        %weight = ttir.empty() : () -> tensor<64x64x3x3xbf16>\\n        %bias = ttir.empty() : () -> tensor<1x1x1x64xbf16>\\n        %device = \\\"ttnn.get_device\\\"() <{mesh_shape = #ttnn<mesh_shape 1x1>}> : () -> !ttnn.device\\n        %0 = \\\"ttnn.conv2d\\\"(%input, %weight, %bias, %device)\\n          <{\\n            in_channels = 64: i32,\\n            out_channels = 64: i32,\\n            batch_size = 1: i32,\\n            input_height = 32: i32,\\n            input_width = 32: i32,\\n            kernel_size = array<i32: 3, 3>,\\n            stride = array<i32: 1, 1>,\\n            padding = array<i32: 0, 0>,\\n            dilation = array<i32: 1, 1>,\\n            groups = 1: i32\\n          }> : (tensor<1x1x1024x64xbf16>, tensor<64x64x3x3xbf16>, tensor<1x1x1x64xbf16>, !ttnn.device) -> tensor<1x1x900x64xbf16>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv2d_config\", \"type\": \"OptionalAttr<TTNN_Conv2dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"conv2d_slice_config\", \"type\": \"OptionalAttr<TTNN_Conv2dSliceConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.conv3d\",\n    \"summary\": \"Conv3d operation.\",\n    \"description\": \"Applies a 3D convolution over an input volume composed of several input planes.\\n\\n      Inputs:\\n      - `input` (AnyRankedTensor): expected in the following format (N, D, H, W, C) where:\\n        - N is the batch size\\n        - D is the depth of the input volume\\n        - H is the height of the input planes\\n        - W is the width of the input planes\\n        - C is the number of input channels\\n      - `weight` (AnyRankedTensor): expected in the following format (K_D * K_H * K_W * C / G, O) where:\\n        - K_D is the depth of the kernel\\n        - K_H is the height of the kernel\\n        - K_W is the width of the kernel\\n        - C is the number of input channels\\n        - O is the number of output channels\\n        - G is the number of groups\\n        The spatial kernel dimensions and input channels are flattened together into a 2D tensor.\\n      - `bias` (Optional<AnyRankedTensor>): expected in the following format (1, O) where:\\n        - O is the number of output channels\\n\\n      Attributes:\\n      - `in_channels` (i32): The number of input channels.\\n      - `out_channels` (i32): The number of output channels.\\n      - `batch_size` (i32): The batch size.\\n      - `input_depth` (i32): The input depth.\\n      - `input_height` (i32): The input height.\\n      - `input_width` (i32): The input width.\\n      - `kernel_size` (array<3xi32>): [K_D, K_H, K_W] where K_D is the kernel depth, K_H is the kernel height and K_W is the kernel width.\\n      - `stride` (array<3xi32>): [sD, sH, sW] where sD is stride for depth, sH for height and sW is stride for width.\\n      - `padding` (array<3xi32>): [pD, pH, pW] where pD is padding for depth, pH is padding for height and pW is padding for width.\\n        Padding is symmetric (same on both sides of each dimension).\\n      - `padding_mode` (StrAttr): \\\"zeros\\\" or \\\"replicate\\\" - padding fill strategy.\\n      - `groups` (i32): Number of blocked connections from input channels to output channels. Input and output channels must both be divisible by groups.\\n\\n      Outputs:\\n      - `result` (AnyRankedTensor): returned in the following format (N, D_out, H_out, W_out, O) where:\\n        - `D_out = (D_in + 2*pD - K_D) / sD + 1`\\n        - `H_out = (H_in + 2*pH - K_H) / sH + 1`\\n        - `W_out = (W_in + 2*pW - K_W) / sW + 1`\\n\\n      Example:\\n        %input = ttir.empty() : () -> tensor<1x28x28x28x32xbf16>\\n        %weight = ttir.empty() : () -> tensor<864x64xbf16>  // 864 = 3*3*3*32 (2D tensor)\\n        %bias = ttir.empty() : () -> tensor<1x64xbf16>      // 2D tensor\\n        %device = \\\"ttnn.get_device\\\"() <{mesh_shape = #ttnn<mesh_shape 1x1>}> : () -> !ttnn.device\\n        %0 = \\\"ttnn.conv3d\\\"(%input, %weight, %bias, %device)\\n          <{\\n            in_channels = 32: i32,\\n            out_channels = 64: i32,\\n            batch_size = 1: i32,\\n            input_depth = 28: i32,\\n            input_height = 28: i32,\\n            input_width = 28: i32,\\n            kernel_size = array<i32: 3, 3, 3>,\\n            stride = array<i32: 1, 1, 1>,\\n            padding = array<i32: 0, 0, 0>,\\n            padding_mode = \\\"zeros\\\",\\n            groups = 1: i32\\n          }> : (tensor<1x28x28x28x32xbf16>, tensor<864x64xbf16>, tensor<1x64xbf16>, !ttnn.device) -> tensor<1x26x26x26x64xbf16>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_depth\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding_mode\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"zeros\\\">\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv3d_config\", \"type\": \"OptionalAttr<TTNN_Conv3dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.cos\",\n    \"summary\": \"Eltwise cosine.\",\n    \"description\": \"Eltwise cosine operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.create_global_semaphore\",\n    \"summary\": \"Create global semaphore op.\",\n    \"description\": \"Creates a global semaphore with the specified core range and initial value.\\n\\n      Global semaphores are similar to normal semaphores but differ in a couple of ways:\\n      1) their lifetime exists beyond the scope of an op (and thus must created/deallocated separately like tensors)\\n      2) they can be initialized before an op is even dispatched (whereas normal semaphores are initialized at dispatch time)\\n\\n      This is needed for CCLs (and multichip communication in general) to synchronize devices or for normal signalling where normal semaphores\\n      cannot be used. This is because the different devices in a mesh are not running ops in a synchronized manner\\n      (devices can be running different ops in the program) so the existence/initialization of normal semaphores\\n      cannot be guaranteed on a different device that we need to communicate with.\\n\\n      For example, if we have to run a matmul then an all gather,\\n      device x could be doing the matmul whereas device y has completed the matmul and begun an all gather.\\n      Now, if device y has to do a remote semaphore increment on device x as part of the all gather,\\n      this would lead to undefined behaviour\\n      since device x is still executing the matmul and it's semaphore for the all gather op does not even exist yet.\\n\\n      Example:\\n      ```mlir\\n      %semaphore = \\\"ttnn.create_global_semaphore\\\"() <{initial_value = 0 : ui32, core_range = #ttnn.core_range<(0,0), (7,7)>}> : () -> !ttnn.global_semaphore\\n      ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TTNN_GlobalSemaphore\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"core_range\", \"type\": \"TTNN_CoreRangeAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.cumsum\",\n    \"summary\": \"Cumulative sum op.\",\n    \"description\": \"Computes the cumulative sum of elements of a tensor along specified dimension.\\n\\n    Example:\\n      input: [[1, 2, 3],\\n              [4, 5, 6]]\\n\\n      // Cumulative sum along dim=0:\\n      output: [[1, 2, 3],\\n               [5, 7, 9]]\\n\\n      // Cumulative sum along dim=1:\\n      output: [[1, 3, 6],\\n               [4, 9, 15]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I32Attr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.d2m_subgraph\",\n    \"summary\": \"Dispatch D2M compiled subgraph.\",\n    \"description\": \"References a D2M-compiled subgraph function containing ttnn.generic ops.\\n    The function is a private function in the same module.\\n\\n    Before TTNNMaterializeD2M runs, the referenced function contains a TTNN subgraph\\n    to be compiled via D2M.\\n\\n    After TTNNMaterializeD2M runs, the referenced function contains:\\n    - ttnn.generic ops (the compiled subgraph)\\n    - Kernel functions are generated at module scope\\n\\n    TTNNCollaspeD2M will inline the D2M function body at the call site.\\n\\n    Example:\\n    ```mlir\\n    // Before D2M compilation\\n    %result = ttnn.d2m_subgraph @d2m_subgraph\\n        ins(%a : tensor<...>)\\n        outs(%out : tensor<...>) : tensor<...>\\n\\n    func.func private @d2m_subgraph(...) -> tensor<...> {\\n      // ttnn subgraph\\n    }\\n\\n    // After D2M compilation\\n    %result = ttnn.d2m_subgraph @d2m_subgraph\\n        ins(%a : tensor<...>)\\n        outs(%out : tensor<...>) : tensor<...>\\n\\n    func.func private @d2m_subgraph(...) -> tensor<...> {\\n      ttnn.generic ...\\n      // more generic ops if subgraph didn't fully fuse\\n    }\\n    func.func private @kernel0() { ... }\\n    ... other kernel functions at module scope\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" },\n      { \"name\": \"outputs\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"d2m_func\", \"type\": \"SymbolRefAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$d2m_func attr-dict `\\\\n`\\n    `ins` `(` $inputs `:` type($inputs) `)` `\\\\n`\\n    `outs` `(` $outputs `:` type($outputs) `)` (`:` type($results)^)?\"\n  },\n  {\n    \"name\": \"ttnn.deallocate\",\n    \"summary\": \"Deallocate op.\",\n    \"description\": \"Tensor Deallocate operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"force\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.dequantize\",\n    \"summary\": \"Dequantize operation.\",\n    \"description\": \"Applies dequantization to the input tensor.\\n\\n      Inputs:\\n        - `input` AnyRankedTensor: The input tensor to be dequantized. Must have quantized element type.\\n        - `scale` AnyRankedTensor: The scale factor (or factors for per-axis quantization).\\n        - `zero_point` AnyRankedTensor: The zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n        - `axis` Optional<i32>: The axis along which quantization is applied. Must be in range [0, rank) where rank is the rank of the input tensor.\\n        - `output_dtype` Optional<TTCore_DataTypeAttr>: The data type of the output tensor.\\n        - `memory_config` Optional<TTNN_MemoryConfigAttr>: The memory configuration for the output tensor.\\n      ```\\n      // For per-tensor dequantization:\\n      output[i] = (input[i] - zero_point) * scale\\n      // For per-axis dequantization:\\n      output[i0, i1, ..., ia, ..., in] = (input[i0, i1, ..., ia, ..., in] - zero_point[ia]) * scale[ia]\\n      ```\\n      Example:\\n      ```mlir\\n      %input = ttir.empty() : () -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n      %output = ttir.empty() : () -> tensor<64x128xf32>\\n      %dequantized = \\\"ttnn.dequantize\\\"(%input, %output) : (tensor<64x128x!quant.uniform<i32:f32, 0.1>, tensor<64x128xf32>) -> tensor<64x128xf32>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.distribute_tensor\",\n    \"summary\": \"Distribute tensor across mesh devices\",\n    \"description\": \"Distributes a host-side tensor across multiple devices in a mesh\\n    according to the specified mapping configuration.\\n\\n    This operation takes a single-device tensor and creates a multi-device\\n    tensor distributed according to the MeshMapperConfig configuration.\\n\\n    // Note: In the ttnn API, the distribute_tensor op takes an input tensor and a TensorToMesh object as its arguments.\\n    // To create a TensorToMesh object, the API create_mesh_mapper is used, which requires both MeshMapperConfig and MeshDevice.\\n    // Instead of modeling create_mesh_mapper as a separate op in the IR, these two strongly coupled APIs are combined into one distribute_tensor op\\n    // to keep the IR simple and less cluttered. If a clear need arises in the future, splitting them into separate ops can be considered.\\n\\n    Example:\\n    ```mlir\\n    %result = \\\"ttnn.distribute_tensor\\\"(%input, %device) <{\\n      mapper_config = #ttnn.mesh_mapper_config<\\n        placements = [#ttnn.placement<replicate>, #ttnn.placement<shard, 1>],\\n        mesh_shape_override = #ttnn.mesh_shape<2x2>\\n      >,\\n      cq_id = 0 : ui32\\n    }> : (tensor<32x64xbf16>, !ttnn.device) -> tensor<32x64xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"mesh_device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mapper_config\", \"type\": \"TTNN_MeshMapperConfigAttr\" },\n      { \"name\": \"cq_id\", \"type\": \"OptionalAttr<UI32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.distributed_rms_norm\",\n    \"summary\": \"Distributed RMS normalization with all-gather op.\",\n    \"description\": \"Fused distributed RMS normalization operation across mesh devices.\\n      Computes local RMS statistics (the mean of squared values, E(x²)),\\n      all-gathers the statistics along the specified cluster_axis to obtain\\n      globally-correct values, then normalizes each element by\\n      x / sqrt(E(x²) + epsilon) and applies optional weight scaling locally\\n      on each device.\\n\\n      Only statistics are communicated across devices — the input data itself\\n      is not all-gathered. Each device's output shape equals its input shape.\\n\\n      Maps to ttnn::fused_rms_minimal at runtime.\\n\\n      This operation requires the input tensor to be width-sharded across devices.\\n\\n      Inputs:\\n        - input: Input tensor. Must be width-sharded in L1 with shape\\n            (1,1,32,M) where M is a multiple of 32. Tiled layout required.\\n        - weight: Optional gamma (scale) tensor applied after normalization.\\n            Must be in ROW_MAJOR layout with width equal to tile_width (32),\\n            i.e. reshaped from 1D (N,) to 2D (N/32, 32).\\n        - residual: Optional residual tensor to add to input before\\n            normalization (x + residual). Must have the same shard spec as\\n            input.\\n        - stats: Scratch tensor for intermediate RMS statistics exchanged\\n            across devices via all-gather. Shape (1,1,32,32), width-sharded\\n            on core (0,0) in L1. Dtype is Float32 when fp32_dest_acc_en is\\n            set, otherwise BFloat16.\\n\\n      Attributes:\\n        - cluster_axis: Mesh dimension (0 or 1) along which to all-gather\\n            the RMS statistics across devices.\\n        - epsilon: Small constant added to the denominator for numerical\\n            stability. Defaults to 1e-12.\\n        - sub_device_id: Optional sub-device targeting for kernel placement.\\n        - memory_config: Output memory configuration. Typically matches the\\n            input's width-sharded shard spec.\\n        - num_links: Optional number of links for the all-gather\\n            communication.\\n        - topology: CCL topology for all-gather (Linear or Ring).\\n        - compute_config: Device compute kernel configuration. Controls math\\n            fidelity, fp32_dest_acc_en, and packer L1 accumulation.\\n        - program_config: LayerNormShardedMultiCoreProgramConfig derived from\\n            the input's shard spec (core grid, block_h, block_w).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"residual\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"stats\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-12>\" },\n      { \"name\": \"sub_device_id\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"num_links\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"topology\", \"type\": \"OptionalAttr<TTCore_TopologyAttr{ring|linear|mesh|torus|disabled}>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"program_config\", \"type\": \"OptionalAttr<TTNN_LayerNormShardedMultiCoreProgramConfigAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.divide\",\n    \"summary\": \"Eltwise divide.\",\n    \"description\": \"Eltwise divide operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.dropout\",\n    \"summary\": \"Dropout operation.\",\n    \"description\": \"Applies dropout to the input tensor element-wise.\\n\\n    Example:\\n      %result = \\\"ttnn.dropout\\\"(%input) <{prob = 0.2 : f32, scale = 1.25 : f32, seed = 42 : ui32}> : (tensor<64x128xbf16>) -> tensor<64x128xbf16>\\n\\n    Attributes:\\n      - `prob` (Float): Dropout probability. Elements are zeroed with this probability [Default: 0.0].\\n      - `scale` (Float): Scale factor applied to non-zeroed elements. Typically 1/(1-prob) [Default: 1.0].\\n      - `seed` (Integer): Seed for the random number generator [Default: 0].\\n      - `use_per_device_seed` (Bool): Whether to use a different seed per device [Default: true].\\n      - `memory_config` (MemoryConfig): Memory configuration for the output tensor.\\n\\n    Inputs:\\n      - `input` (Tensor): The input tensor.\\n\\n    Output:\\n      - `result` (Tensor): The output tensor with dropout applied.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"prob\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"scale\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"seed\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" },\n      { \"name\": \"use_per_device_seed\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.dump_tensor\",\n    \"summary\": \"Saves a tensor to disk in the TTNN binary format\",\n    \"description\": \"Saves a tensor to disk in the TTNN binary format. Files must use the `.tensorbin` extension.\\n\\n    Inputs:\\n      - `file_path` StrAttr: Path of the file where tensor should be dumped. Must end with `.tensorbin` extension.\\n      - `input` AnyRankedTensor: Tensor to serialize.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"file_path\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.embedding\",\n    \"summary\": \"Embedding op.\",\n    \"description\": \"Embedding operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.embedding_bw\",\n    \"summary\": \"Embedding backward op.\",\n    \"description\": \"Embedding backward operation. Generates the gradient of the embedding operation with respect to the input.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"in_gradient\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.empty\",\n    \"summary\": \"Empty op.\",\n    \"description\": \"Tensor empty operation\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TTNN_ShapeAttr\" },\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"layout\", \"type\": \"TTNN_LayoutAttr{row_major|tile|invalid}\" },\n      { \"name\": \"memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.end_trace_capture\",\n    \"summary\": \"End trace capture.\",\n    \"description\": \"Ends trace capture for the given trace id. Consumes a scalar tensor containing the trace id.\\n    Has no output, but will have memory effects on the trace region of the device, modelled by\\n    trace resource in the compiler.\\n    Inputs:\\n      - `device` TTNN_Device: The device to end the trace capture on.\\n      - `trace_id` AnyRankedTensor: The trace id tensor to end the capture for. Must be a scalar.\\n      - `cq_id` ui32: The command queue to end the capture with. Must be 0 or 1.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" },\n      { \"name\": \"trace_id\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cq_id\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.eq\",\n    \"summary\": \"Eltwise equal to.\",\n    \"description\": \"Eltwise equal to operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.erf\",\n    \"summary\": \"Eltwise erf op.\",\n    \"description\": \"Eltwise erf operation. Calculates erf(x) for each element of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.erfc\",\n    \"summary\": \"Eltwise erfc op.\",\n    \"description\": \"Eltwise erfc operation. Calculates erfc(x) for each element of the input tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.execute_trace\",\n    \"summary\": \"Execute trace.\",\n    \"description\": \"Executes the captured trace. Consumes a scalar tensor containing the trace id.\\n    Has no output, but will have read/write memory effects on the cached trace input/output tensors\\n    created when capturing the trace.\\n    Inputs:\\n      - `device` TTNN_Device: The device where the trace was captured.\\n      - `trace_id` AnyRankedTensor: The trace id tensor to execute. Must be a scalar.\\n      - `cq_id` ui32: The command queue to execute the trace with. Must be 0 or 1.\\n      - `blocking` bool: Whether the trace should be executed synchronously.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" },\n      { \"name\": \"trace_id\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cq_id\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" },\n      { \"name\": \"blocking\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.exp\",\n    \"summary\": \"Eltwise exponential.\",\n    \"description\": \"Eltwise exponential operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.expm1\",\n    \"summary\": \"Eltwise unary op.\",\n    \"description\": \"Performs element-wise exponential minus one operation on `operand` tensor\\n    and stores the result in the output tensor.\\n\\n    Example:\\n        %a: [[0, 1], [0, 0]]\\n        \\\"ttnn.exmp1\\\"(%a, %out) -> %out: [[0, 1.71828], [0, 0]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.fill_cache\",\n    \"summary\": \"Fill static cache tensor.\",\n    \"description\": \"Fills the `cache` tensor in-place with values from `input` at `batch_offset`.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_offset\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.floor\",\n    \"summary\": \"Eltwise floor op.\",\n    \"description\": \"Eltwise floor operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.from_device\",\n    \"summary\": \"FromDevice op.\",\n    \"description\": \"This op retrieves the input tensor from the given device.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.full\",\n    \"summary\": \"Creates a tensor filled with the specified value\",\n    \"description\": \"Tensor operation to create a tensor filled with a specified value.\\n\\n    Given a `shape` and a `fill_value`, produces a tensor with the shape, filled with the specified value.\\n\\n    Example:\\n      %0 = \\\"ttnn.full\\\"() <{\\n        dtype = #ttcore.supportedDataTypes<u32>,\\n        fill_value = 7 : i32,\\n        layout = #ttnn.layout<tile>,\\n        shape = #ttnn.shape<64x128>\\n      }> : () -> tensor<64x128xui32>\\n      // %0: [[[7, 7, 7, ..., 7], [7, 7, 7, ..., 7], ..., [7, 7, 7, ..., 7]]]\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<TTNN_Device>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TTNN_ShapeAttr\" },\n      { \"name\": \"fill_value\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<TTNN_LayoutAttr{row_major|tile|invalid}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.ge\",\n    \"summary\": \"Eltwise greater than or equal to.\",\n    \"description\": \"Eltwise greater than or equal to operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.gelu\",\n    \"summary\": \"Eltwise GELU.\",\n    \"description\": \"Eltwise GELU operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.gelu_bw\",\n    \"summary\": \"Backward pass operation for the GELU activation function.\",\n    \"description\": \"Computes the gradient of the GELU (Gaussian Error Linear Unit) activation\\n    function with respect to its input during backpropagation.\\n\\n    This operation corresponds to ttnn.experimental.gelu_bw.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"approximate\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"none\\\">\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.generic\",\n    \"summary\": \"Generic operation.\",\n    \"description\": \"Generic operation capable of running a program with custom kernels. Each kernel is described with a\\n      symbol reference to its function in EmitC dialect plus compile and runtime arguments. Generic operation\\n      is supplied with concatenated input and output `ios` tensors.\\n\\n      Inputs:\\n        - `inputs_and_outputs` Variadic<AnyRankedTensor>: The input and output tensors.\\n        - `program` ProgramAttr: Program descriptor that includes a description of each kernels, array of CBs and array of semaphores.\",\n    \"operands\": [\n      { \"name\": \"inputs_and_outputs\", \"type\": \"Variadic<AnyRankedTensor>\" },\n      { \"name\": \"additional_args\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"program\", \"type\": \"TTNN_GenericProgramAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.get_device\",\n    \"summary\": \"Get Device op.\",\n    \"description\": \"This op returns a submesh carved out from the parent runtime device.\\n      Mesh shape and mesh offset define the size and offset of the submesh.\",\n    \"results\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mesh_shape\", \"type\": \"OptionalAttr<TTNN_MeshShapeAttr>\" },\n      { \"name\": \"mesh_offset\", \"type\": \"OptionalAttr<TTNN_MeshOffsetAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.global_avg_pool2d\",\n    \"summary\": \"A global average pooling 2d operation\",\n    \"description\": \"The `global_avg_pool2d` operation applies global average pooling over the spatial dimensions\\n    (height and width) of a 4D input tensor. In essence, it should be realised as the sum-reduce style operation\\n    under the hood, for performance reasons (since we include all elements, there is no need for kernel allocation).\\n    It reduces spatial dimensions to 1.\\n\\n    Example:\\n    ```mlir\\n    %device = \\\"ttnn.get_device\\\"() <{mesh_shape = #ttnn<mesh_shape 1x1>}> : () -> !ttnn.device\\n\\n    %result = \\\"ttnn.global_avg_pool2d\\\"(%input) <{memory_config = #ttnn.memory_config<#dram, <interleaved>>,\\n                                                           dtype = #ttcore.supportedDataTypes<bf16>}>\\n              : (tensor<1x128x128x32xbf16>) -> tensor<1x1x1x32xbf16>\\n    ```\\n\\n    Inputs:\\n    - `input`: 4D tensor with shape [N, H, W, C] where N is batch size, H is height, W is width, and C is channels\\n\\n    Attributes:\\n    - `memory_config` (optional): Memory configuration specifying where the operation should be performed\\n    - `dtype` (optional): Data type for the output tensor (e.g., bf16, f32)\\n\\n    Outputs:\\n    - `result`: 4D tensor with shape [N, 1, 1, C] containing the global average pooled values\\n\\n    Note: The operation reduces spatial dimensions (H, W) to (1, 1) by computing the average across\\n    all spatial locations for each channel independently.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.group_norm\",\n    \"summary\": \"Group normalization op.\",\n    \"description\": \"Computes group normalization over the input tensor. The input tensor's channels\\n      are split into groups, and mean and variance are computed per group. The result\\n      is normalized by subtracting the mean and dividing by the standard deviation,\\n      then optionally scaled and shifted by weight (gamma) and bias (beta).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input_mask\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"I64Attr\" },\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-12>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"core_grid\", \"type\": \"OptionalAttr<TTNN_CoreCoordAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.gt\",\n    \"summary\": \"Eltwise greater than.\",\n    \"description\": \"Eltwise greater than operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.hardsigmoid\",\n    \"summary\": \"Eltwise hardsigmoid.\",\n    \"description\": \"Eltwise hardsigmoid operation. Computes hardsigmoid(x) = max(0, min(1, (x + 3) / 6)).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.isfinite\",\n    \"summary\": \"Eltwise isfinite op.\",\n    \"description\": \"Eltwise isfinite operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.layer_norm\",\n    \"summary\": \"Layer normalization op.\",\n    \"description\": \"Performs layer normalization on the input tensor. This operation normalizes\\n      the input tensor by computing the mean and variance of elements across\\n      the specified dimensions, then normalizes by subtracting the mean and\\n      dividing by the standard deviation, optionally scaling and shifting the result.\\n\\n      This operation performs normalization over the last dimension of the input tensor,\\n      matching the TTNN runtime implementation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-12>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.le\",\n    \"summary\": \"Eltwise less than or equal to.\",\n    \"description\": \"Eltwise less than or equal to operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.leaky_relu\",\n    \"summary\": \"Eltwise leaky relu operation.\",\n    \"description\": \"The Leaky ReLU (Rectified Linear Unit) operation computes an element-wise\\n      activation function over its input tensor. It is defined as:\\n\\n      y = x if x > 0\\n      y = parameter * x if x <= 0\\n\\n      where `parameter` is a small, user-defined constant that determines the slope for\\n      negative inputs.\\n\\n      Attributes:\\n      - `parameter` (float): The slope for negative values.\\n\\n      Inputs:\\n      - `input` (Tensor): The input tensor to be activated.\\n\\n      Outputs:\\n      - `output` (Tensor): The tensor after applying the Leaky ReLU activation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"parameter\", \"type\": \"F32Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.linear\",\n    \"summary\": \"Linear transformation of inputs.\",\n    \"description\": \"Produces the matmul of tensors `a` and `b` with optional addition with `bias`.\\n\\n      Example:\\n        // %a = [[1., 2.], [2., 1.]]\\n        // %b = [[0., 1.], [1., 0.]]\\n        // %bias = [[1.]]\\n        \\\"ttnn.linear\\\"(%a, %b, %bias, %result) : (tensor<2x2xf16>, tensor<2x2xf16>, tensor<1xf16>, tensor<2x2xf16>) -> tensor<2x2xf16>\\n        // %result = [[3., 2.], [2., 3.]]\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"b\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"matmul_program_config\", \"type\": \"OptionalAttr<AnyAttrOf<[ TTNN_MatmulMultiCoreReuseProgramConfigAttr, TTNN_MatmulMultiCoreReuseMultiCastProgramConfigAttr, TTNN_MatmulMultiCoreReuseMultiCast1DProgramConfigAttr, TTNN_MatmulMultiCoreReuseMultiCastDRAMShardedProgramConfigAttr ]>>\" },\n      { \"name\": \"activation\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.load_tensor\",\n    \"summary\": \"Loads a tensor from disk\",\n    \"description\": \"Loads a tensor from disk, optionally placing it directly on a device.\\n\\n    Inputs:\\n      - `file_path` StrAttr: Path of the file of the serialized tensor. Must end with `.tensorbin` extension.\\n      - `device` Optional<TTNN_Device>: Device where tensor should be deserialized. It has to be provided iff the serialized tensor is a device tensor.\\n    Outputs:\\n      - `result` AnyRankedTensor: Deserialized tensor from the `file_path`.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<TTNN_Device>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"file_path\", \"type\": \"StrAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.log\",\n    \"summary\": \"Eltwise logarithm.\",\n    \"description\": \"Eltwise logarithm operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.log1p\",\n    \"summary\": \"Eltwise log1p operation.\",\n    \"description\": \"Performs element-wise logarithm plus one operation on `operand` tensor and\\n        puts the result in the output tensor.\\n\\n        Example:\\n          %a: [0.0, -0.999, 7.0, 6.38905621, 15.0]\\n          \\\"ttnn.logp1\\\"(%a, %out) -> %out: [0.0, -6.90776825, 2.07944155, 2.0, 2.77258873]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.logical_and\",\n    \"summary\": \"Eltwise logical and.\",\n    \"description\": \"Eltwise logical and operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.logical_left_shift\",\n    \"summary\": \"Eltwise Logical Left Shift operation\",\n    \"description\": \"The `logical_left_shift` operation performs an elementwise logical left shift\\n    on the elements of the first tensor by the corresponding shift amounts in the\\n    second tensor.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.logical_not\",\n    \"summary\": \"Eltwise logical not op.\",\n    \"description\": \"Eltwise logical not operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.logical_or\",\n    \"summary\": \"Eltwise logical or.\",\n    \"description\": \"Eltwise logical or operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.logical_right_shift\",\n    \"summary\": \"Eltwise Logical Right Shift operation\",\n    \"description\": \"The `logical_right_shift` operation performs an elementwise logical right shift\\n    on the elements of the first tensor by the corresponding shift amounts in the\\n    second tensor.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.logical_xor\",\n    \"summary\": \"Eltwise logical xor.\",\n    \"description\": \"Eltwise logical xor operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.lt\",\n    \"summary\": \"Eltwise less than.\",\n    \"description\": \"Eltwise less than operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.matmul\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"b\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"transpose_b\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"matmul_program_config\", \"type\": \"OptionalAttr<AnyAttrOf<[ TTNN_MatmulMultiCoreReuseProgramConfigAttr, TTNN_MatmulMultiCoreReuseMultiCastProgramConfigAttr, TTNN_MatmulMultiCoreReuseMultiCast1DProgramConfigAttr, TTNN_MatmulMultiCoreReuseMultiCastDRAMShardedProgramConfigAttr ]>>\" },\n      { \"name\": \"activation\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.max\",\n    \"summary\": \"Max reduction op.\",\n    \"description\": \"Max reduction op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.max_pool2d\",\n    \"summary\": \"Applies a 2D max pooling over an input signal composed of several input planes.\",\n    \"description\": \"Applies a 2D max pooling over an input signal composed of several input planes.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_size\", \"type\": \"SI32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"SI32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"SI32Attr\" },\n      { \"name\": \"channels\", \"type\": \"SI32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"applied_shard_scheme\", \"type\": \"OptionalAttr<TTNN_TensorMemoryLayoutAttr{interleaved|height_sharded|width_sharded|block_sharded|nd_sharded}>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"reallocate_halo_output\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"config_tensors_in_dram\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.max_pool2d_with_indices\",\n    \"summary\": \"Applies a 2D max pooling over an input signal composed of several input planes, returning both values and indices.\",\n    \"description\": \"Applies a 2D max pooling over an input signal composed of several input planes.\\n      Returns both the maximum values and the indices of where those values were found in the input tensor.\\n      The indices can be used for unpooling operations or gradient computation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"result_indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_size\", \"type\": \"SI32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"SI32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"SI32Attr\" },\n      { \"name\": \"channels\", \"type\": \"SI32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"applied_shard_scheme\", \"type\": \"OptionalAttr<TTNN_TensorMemoryLayoutAttr{interleaved|height_sharded|width_sharded|block_sharded|nd_sharded}>\" },\n      { \"name\": \"ceil_mode\", \"type\": \"BoolAttr\" },\n      { \"name\": \"reallocate_halo_output\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"config_tensors_in_dram\", \"type\": \"OptionalAttr<BoolAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.maximum\",\n    \"summary\": \"Eltwise maximum OP.\",\n    \"description\": \"Calculates maximum of input tensors' values element-wise and stores result in output tensor.\\n\\n      Example:\\n        %lhs: [[3, 2, 7], [1, 4, 4]]\\n        %rhs: [[1, 4, 2], [1, 2, 3]]\\n        \\\"ttnn.maximum\\\"(%lhs, %rhs, %out) -> %out: [[3, 4, 7], [1, 4, 4]]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.mean\",\n    \"summary\": \"Mean reduction op.\",\n    \"description\": \"Mean reduction op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.mesh_partition\",\n    \"summary\": \"Mesh partition operation.\",\n    \"description\": \"Mesh partition op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.mesh_shard\",\n    \"summary\": \"Mesh shard op.\",\n    \"description\": \"Tensor Mesh Shard operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shard_direction\", \"type\": \"TTCore_MeshShardDirectionAttr{full_to_shard|shard_to_full}\" },\n      { \"name\": \"shard_type\", \"type\": \"TTCore_MeshShardTypeAttr{identity|replicate|maximal|devices}\" },\n      { \"name\": \"shard_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"shard_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.min\",\n    \"summary\": \"Min reduction op.\",\n    \"description\": \"This op computes the minimum of all elements of the tensor or along\\n    specified dimension.\\n\\n    Example:\\n      input: [[1, 5, 3],\\n              [4, 2, 6]]\\n\\n      // Computing along dim 0\\n      output: [1, 2, 3]\\n\\n      // Computing along dim 1\\n      output: [1, 2]\\n\\n      // Computing for entire tensor\\n      output: 1\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.minimum\",\n    \"summary\": \"Eltwise minimum OP.\",\n    \"description\": \"Calculates minimum of input tensors' values element-wise and stores result\\n      in output tensor.\\n\\n      Example:\\n        %lhs: [[3, 2, 7], [1, 4, 4]]\\n        %rhs: [[1, 4, 2], [1, 2, 3]]\\n        \\\"ttnn.minimum\\\"(%lhs, %rhs, %out) -> %out: [[1, 2, 2], [1, 2, 3]]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.mish\",\n    \"summary\": \"Eltwise Mish.\",\n    \"description\": \"Eltwise Mish operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.moe_expert_token_remap\",\n    \"summary\": \"Remap global expert routing to local device experts with sparsity.\",\n    \"description\": \"Converts global expert routing scores to local per-device expert mapping\\n      and creates a sparsity pattern for efficient sparse_matmul.\",\n    \"operands\": [\n      { \"name\": \"topk_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_mapping\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"expert_metadata\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"mapping\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"reduced\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduction_size\", \"type\": \"I64Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.moreh_cumsum\",\n    \"summary\": \"Moreh cumulative sum op.\",\n    \"description\": \"Computes the cumulative sum of elements of a tensor along specified dimension.\\n\\n    Example:\\n      input: [[1, 2, 3],\\n              [4, 5, 6]]\\n\\n      // Cumulative sum along dim=0:\\n      output: [[1, 2, 3],\\n               [5, 7, 9]]\\n\\n      // Cumulative sum along dim=1:\\n      output: [[1, 3, 6],\\n               [4, 9, 15]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.multiply\",\n    \"summary\": \"Eltwise multiply.\",\n    \"description\": \"Eltwise multiply operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.ne\",\n    \"summary\": \"Eltwise not equal to.\",\n    \"description\": \"Eltwise not equal to operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.neg\",\n    \"summary\": \"Eltwise negate.\",\n    \"description\": \"Eltwise negate operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.nlp_concat_heads\",\n    \"summary\": \"nlp_concat_heads op in TTNN dialect.\",\n    \"description\": \"\\\"This op targets specific case of concatenate heads operation where input tensor\\n    [B, num_heads, S, head_dim] is permuted and reshaped into [B, 1, S, num_heads * head_dim].\\\"\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.nlp_concat_heads_decode\",\n    \"summary\": \"Concatenate heads op used in attention layer.\",\n    \"description\": \"Shuffles [S=1, B=32, 32(num_heads), head_dim] tensor into tensor with shape [S=1, 1, B=32, num_heads * head_dim].\\n      This operation assumes that input num_heads is padded to at most 32. When invoking this op,\\n      we specify the actual num_heads via the attribute `num_heads` and it should be less than input padded num_heads.\\n      Operation will unpad the input num_heads to the actual num_heads.\\n      The output is default width sharded by num heads.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_heads\", \"type\": \"UI32Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.nlp_create_qkv_heads_decode\",\n    \"summary\": \"nlp_create_qkv_heads_decode op in TTNN dialect.\",\n    \"description\": \"Shuffles [1, S=1, B, head_dim * (num_heads + 2*num_kv_heads)] fused qkv matrix into Q, K, and V heads with shape [S, B, num_heads, head_dim] for Q and [S, B, num_kv_heads, head_dim] for K and V, where num_heads and num_kv_heads will be padded to nearest 32.\\n      - Input must be sharded, B=32 and S=1.\\n      - overlap_qk_coregrid is a boolean flag that determines whether the output Q and K heads are on same core grid. If true, then Q, K, and V heads are on the same core grid. If false, the Q and K heads are on non-overlapping core-grid useful for processing Q and K in parallel.\\n      - Batch offset is used to fuse batch slicing. If provided slice size must also be provided in which batch dim of QKV output will be slice_size.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"batch_offset\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_heads\", \"type\": \"UI32Attr\" },\n      { \"name\": \"num_kv_heads\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"overlap_qk_coregrid\", \"type\": \"OptionalAttr<BoolAttr>\" },\n      { \"name\": \"slice_size\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.ones\",\n    \"summary\": \"Creates a tensor filled with ones.\",\n    \"description\": \"Tensor operation to create a tensor filled with ones.\\n\\n    Given a ShapeAttr `shape`, produces a tensor with the same shape, filled with ones.\\n\\n    Example:\\n      %0 = \\\"ttnn.ones\\\"() <{shape = array<i32:64, 28, 28>}> : () -> tensor<64x28x28xbf16>\\n      // %0: [[[1, 1, 1, ..., 1], [1, 1, 1, ..., 1], ..., [1, 1, 1, ..., 1]]]\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<TTNN_Device>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TTNN_ShapeAttr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<TTNN_LayoutAttr{row_major|tile|invalid}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.pad\",\n    \"summary\": \"Pad op.\",\n    \"description\": \"Pad input tensor by padding the input_shape to output_shape using the provided value.\\n\\n    The `padding` attribute must be a sequence of integers that is twice the size as the rank of the input.\\n    Each pair of integers in the padding attribute represents the amount of padding to add to the low and high of that dimension.\\n    I.e: an input tensor of shape <1x30x30x64xf32> with padding attribute <0, 0, 1, 1, 1, 1, 0, 0> will return a tensor of shape <1x32x32x64xf32>,\\n    and so will a padding attribute of <0, 0, 0, 2, 0, 2, 0, 0>.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"value\", \"type\": \"F32Attr\" },\n      { \"name\": \"use_multicore\", \"type\": \"BoolAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.paged_fill_cache\",\n    \"summary\": \"Paged fill cache op.\",\n    \"description\": \"Fills the `cache` tensor in-place with values from `input` at `batch_offset`.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"page_table\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"batch_idx_tensor\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.paged_scaled_dot_product_attention_decode\",\n    \"summary\": \"Paged scaled dot product attention decode operation.\",\n    \"description\": \"Paged scaled dot product attention decode operation.\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"page_table\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_mask\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"cur_pos_tensor\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"attention_sink\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.paged_update_cache\",\n    \"summary\": \"Paged update cache op.\",\n    \"description\": \"Inputs:\\n        - `cache`: The cache tensor to be updated. This tensor is modified in place [max_num_blocks, num_heads, block_size, head_dim]\\n        - `input`: The input tensor containing new values. [1, num_users, num_heads (padded to 32), head_dim]\\n        - `update_index`: Indices specifying where to update the cache. [num_users]\\n        - `share_cache`: Whether the cache tensors share memory regions. Defaults to False.\\n        - `page_table`: The page table for managing memory regions during updates. [num_users, max_num_blocks_per_seq]\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"update_index\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"page_table\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"share_cache\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.permute\",\n    \"summary\": \"Permute operation.\",\n    \"description\": \"Permute input tensor dimensions.\\n\\n      Attributes:\\n        - `permutation` array<i64>: The permutation of the input tensor dimensions.\\n\\n      Example:\\n      %a = ttir.empty() : () -> tensor<2x3x4xi32>\\n      %0 = \\\"ttir.permute\\\"(%a) {permutation = array<i64: 1, 2, 0>} : (tensor<2x3x4xi32>) -> tensor<3x4x2xi32>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"pad_value\", \"type\": \"DefaultValuedOptionalAttr<F32Attr, 0.0f>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.point_to_point\",\n    \"summary\": \"Point To Point operation.\",\n    \"description\": \"Performs point-to-point communication by copying a tensor shard from one device to another\\n    within a multi-device mesh. This operation is typically used for explicit data movement in\\n    distributed tensor computations, where a specific device (send_coord) sends its local tensor\\n    data to a target device (receive_coord).\\n\\n    If `optional_output_tensor` is not provided, a new output tensor will be allocated automatically\\n    at the receiver. If provided, the data will be written into the specified output tensor.\\n\\n    The operation returns a multi-device tensor whose buffer layout follows the mesh configuration.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"optional_output_tensor\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sender_coord\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"receiver_coord\", \"type\": \"DenseI64ArrayAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.pow_scalar\",\n    \"summary\": \"Eltwise power OP.\",\n    \"description\": \"The `pow_scalar` operation performs an exponentiation of each element of an\\n    input tensor with a scalar exponent and returns the result.\\n\\n    Example:\\n    ```mlir\\n    %result = ttnn.pow_scalar(%input) <{exponent = 2.0 : f32}> : tensor<4xf32>, tensor<4xf32> -> tensor<4xf32>\\n    // Input tensors:\\n    // %input: [2.0, 3.0, 4.0, 5.0]  // Bases\\n    // %exponent: 2.0  // Power\\n    // Output tensor: [4.0, 9.0, 16.0, 25.0]\\n    ```\\n\\n    Restriction: TTNN API supports expoenent ≥ 0 only.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rhs\", \"type\": \"AnyAttrOf<[F32Attr, I32Attr]>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.pow_tensor\",\n    \"summary\": \"Eltwise power OP.\",\n    \"description\": \"Performs element-wise exponentiation of lhs tensor by rhs tensor and produces a\\n      result tensor. Tensors must be of same shape.\\n\\n      Example:\\n      ```\\n        %result = \\\"ttnn.pow_tensor\\\"(%lhs, %rhs) : (tensor<6xf64>, tensor<6xf64>) -> tensor<6xf64>\\n\\n        %lhs: [-2.0, -0.0, -36.0, 5.0, 3.0, 10000.0]\\n        %rhs: [2.0, 2.0, 1.1, 2.0, -1.0, 10.0]\\n        %result: [4.0, 0.0, -nan, 25.0, 0.333333343, inf]\\n      ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.prepare_conv_transpose2d_bias\",\n    \"summary\": \"Prepares conv_transpose2d bias so that it can be consumed by the conv_transpose2d op.\",\n    \"operands\": [\n      { \"name\": \"bias_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" },\n      { \"name\": \"input_tensor_layout\", \"type\": \"TTNN_LayoutAttr{row_major|tile|invalid}\" },\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv2d_config\", \"type\": \"OptionalAttr<TTNN_Conv2dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"conv2d_slice_config\", \"type\": \"OptionalAttr<TTNN_Conv2dSliceConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.prepare_conv_transpose2d_weights\",\n    \"summary\": \"Prepares conv_transpose2d weights so that they can be consumed by the conv_transpose2d op.\",\n    \"operands\": [\n      { \"name\": \"weight_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" },\n      { \"name\": \"input_tensor_layout\", \"type\": \"TTNN_LayoutAttr{row_major|tile|invalid}\" },\n      { \"name\": \"weights_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"has_bias\", \"type\": \"BoolAttr\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv2d_config\", \"type\": \"OptionalAttr<TTNN_Conv2dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"conv2d_slice_config\", \"type\": \"OptionalAttr<TTNN_Conv2dSliceConfigAttr>\" },\n      { \"name\": \"mirror_kernel\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.prepare_conv2d_bias\",\n    \"summary\": \"Prepares conv2d bias so that it can be consumed by the conv2d op.\",\n    \"operands\": [\n      { \"name\": \"bias_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" },\n      { \"name\": \"input_tensor_layout\", \"type\": \"TTNN_LayoutAttr{row_major|tile|invalid}\" },\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv2d_config\", \"type\": \"OptionalAttr<TTNN_Conv2dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"conv2d_slice_config\", \"type\": \"OptionalAttr<TTNN_Conv2dSliceConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.prepare_conv2d_weights\",\n    \"summary\": \"Prepares conv2d weights so that they can be consumed by the conv2d op.\",\n    \"operands\": [\n      { \"name\": \"weight_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" },\n      { \"name\": \"input_tensor_layout\", \"type\": \"TTNN_LayoutAttr{row_major|tile|invalid}\" },\n      { \"name\": \"weights_format\", \"type\": \"StrAttr\" },\n      { \"name\": \"in_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"out_channels\", \"type\": \"I32Attr\" },\n      { \"name\": \"batch_size\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"kernel_size\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"stride\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"padding\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"dilation\", \"type\": \"DenseI32ArrayAttr\" },\n      { \"name\": \"has_bias\", \"type\": \"BoolAttr\" },\n      { \"name\": \"groups\", \"type\": \"I32Attr\" },\n      { \"name\": \"input_dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"conv2d_config\", \"type\": \"OptionalAttr<TTNN_Conv2dConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" },\n      { \"name\": \"conv2d_slice_config\", \"type\": \"OptionalAttr<TTNN_Conv2dSliceConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.prod\",\n    \"summary\": \"Product reduction op.\",\n    \"description\": \"This op computes the product of all elements of the tensor (full product)\\n    or along a specific dimension.\\n\\n    Example:\\n      input: [[1, 2, 3],\\n              [4, 5, 6]]\\n\\n      // Computing along dim 0\\n      output: [4, 10, 18]\\n\\n      // Computing along dim 1\\n      output: [6, 120]\\n\\n      // Computing full product\\n      output: 720\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.quantize\",\n    \"summary\": \"Quantize operation.\",\n    \"description\": \"Applies quantization to the input tensor.\\n\\n      Inputs:\\n        - `input` AnyRankedTensor: The input tensor to be quantized. Must have floating-point element type.\\n        - `scale` AnyRankedTensor: The scale factor (or factors for per-axis quantization). Must be either a scalar (for per-tensor quantization) or a 1D tensor with size matching the dimension of the specified axis (for per-axis quantization).\\n        - `zero_point` AnyRankedTensor: The zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n        - `axis` Optional<i32>: The axis along which quantization is applied. Must be in range [0, rank) where rank is the rank of the input tensor.\\n        - `output_dtype` Optional<TTCore_DataTypeAttr>: The data type of the output tensor.\\n        - `memory_config` Optional<TTNN_MemoryConfigAttr>: The memory configuration for the output tensor.\\n\\n      ```\\n      // For per-tensor quantization:\\n      output[i] = round(input[i] / scale) + zero_point\\n      // For per-axis quantization:\\n      output[i0, i1, ..., ia, ..., in] = round(input[i0, i1, ..., ia, ..., in] / scale[ia]) + zero_point[ia]\\n      ```\\n      Example:\\n      ```mlir\\n      %input = ttir.empty() : () -> tensor<64x128xf32>\\n      %output = ttir.empty() : () -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n      %quantized = \\\"ttir.quantize\\\"(%input, %output) : (tensor<64x128xf32>, tensor<64x128x!quant.uniform<i32:f32, 0.1>>) -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"zero_point\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.rand\",\n    \"summary\": \"Random number generation operation.\",\n    \"description\": \"Returns a tensor filled with random numbers drawn from a uniform distribution over given interval [low, high) [Default: [0, 1)].\\n\\n    Example:\\n      %0 = \\\"ttnn.get_device\\\"() <{mesh_offset = #ttnn<mesh_offset 0x0>, mesh_shape = #ttnn<mesh_shape 1x1>}> : () -> !ttnn.device\\n      %1 = \\\"ttnn.rand\\\"(%0) <{dtype = #ttcore.supportedDataTypes<bf16>, high = 1.000000e+00 : f32, layout = #ttnn.layout<tile>, low = 0.000000e+00 : f32, memory_config = #ttnn.memory_config<#dram, <interleaved>>, seed = 0 : ui32, size = [32 : i32, 32 : i32]}> : (!ttnn.device) -> tensor<32x32xbf16, #ttnn_layout1>\\n\\n    Attributes:\\n      - `size` (TTNN_ShapeAttr): The shape of the tensor to create.\\n      - `device` (TTNN_Device): The device where the trace was captured.\\n      - `dtype` (mlir:Type): Data type of the returned tensor.\\n      - `layout` (TTNN_LayoutAttr): The layout for the output tensor.\\n      - `memory_config` (TTNN_MemoryConfigAttr): The memory configuration for the output tensor.\\n      - `low` (Float): The lower bound of the range (inclusive) [Default: 0.0].\\n      - `high` (Float): The upper bound of the range (exclusive) [Default: 1.0].\\n      - `seed` (Integer): Value to initialize the random number generator for reproducible results [Default: 0].\\n\\n    Outputs:\\n      - `result` (Tensor): The generated tensor containing the random values.\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"size\", \"type\": \"TTNN_ShapeAttr\" },\n      { \"name\": \"low\", \"type\": \"DefaultValuedAttr<F32Attr, 0.0>\" },\n      { \"name\": \"high\", \"type\": \"DefaultValuedAttr<F32Attr, 1.0>\" },\n      { \"name\": \"seed\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" },\n      { \"name\": \"dtype\", \"type\": \"DefaultValuedAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}, mlir::tt::ttcore::DataType::BFloat16>\" },\n      { \"name\": \"layout\", \"type\": \"DefaultValuedAttr<TTNN_LayoutAttr{row_major|tile|invalid}, mlir::tt::ttnn::Layout::Tile>\" },\n      { \"name\": \"memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.reciprocal\",\n    \"summary\": \"Eltwise reciprocal.\",\n    \"description\": \"Eltwise reciprocal operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.reduce_scatter\",\n    \"summary\": \"Reduce scatter op.\",\n    \"description\": \"Tensor Reduce Scatter operation\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"reduce_type\", \"type\": \"TTCore_ReduceTypeAttr{sum|mean|max|min|std|var|prod|invalid}\" },\n      { \"name\": \"scatter_dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"cluster_axis\", \"type\": \"UI32Attr\" },\n      { \"name\": \"sub_device_id\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"num_links\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"topology\", \"type\": \"OptionalAttr<TTCore_TopologyAttr{ring|linear|mesh|torus|disabled}>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.relu\",\n    \"summary\": \"Eltwise ReLU.\",\n    \"description\": \"Eltwise ReLU operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.relu6\",\n    \"summary\": \"Eltwise ReLU6.\",\n    \"description\": \"Eltwise ReLU6 operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.remainder\",\n    \"summary\": \"Eltwise remainder.\",\n    \"description\": \"Performs element-wise remainder of dividend lhs and divisor rhs tensors and produces a\\n      result tensor.\\n\\n      Example:\\n\\n      // %lhs: [17, -17, 17, -17]\\n      // %rhs: [3, 3, -3, -3]\\n      %result = \\\"ttnn.remainder\\\"(%lhs, %rhs) : (tensor<4xi64>, tensor<4xi64>) -> tensor<4xi64>\\n      // %result: [2, -2, 2, -2]\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.repeat\",\n    \"summary\": \"Repeat op.\",\n    \"description\": \"Returns a new tensor filled with repetition of input tensor according to number of times specified in repeat_dims.\\n\\n      Parameters:\\n        - `input_tensor` (ttnn.Tensor): the input tensor.\\n        - `repeat_dims` (number): The number of repetitions for each element.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"repeat_dims\", \"type\": \"TTNN_ShapeAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.repeat_interleave\",\n    \"summary\": \"Repeat interleave op.\",\n    \"description\": \"Repeats elements of a tensor along a specified dimension.\\n      It allows for flexible repetition patterns, where each element can be repeated a different number of times.\\n      This is particularly useful for tasks that require duplicating elements in a non-uniform manner.\\n\\n      Parameters:\\n      - `input`: The input tensor.\\n      - `repeats`: Specifies the number of repetitions for each element, each element is repeated that number of times.\\n      - `dim`: The dimension along which to repeat values.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"repeats\", \"type\": \"UI32Attr\" },\n      { \"name\": \"dim\", \"type\": \"SI32Attr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.requantize\",\n    \"summary\": \"Requantize operation.\",\n    \"description\": \"Applies requantization to the input tensor.\\n\\n      Inputs:\\n        - `input` AnyRankedTensor: The input tensor to be requantized. Must have quantized element type.\\n        - `in_scale` AnyRankedTensor: The input scale factor (or factors for per-axis quantization). Must be either a scalar (for per-tensor quantization) or a 1D tensor with size matching the dimension of the specified axis (for per-axis quantization).\\n        - `in_zero_point` AnyRankedTensor: The input zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n        - `out_scale` AnyRankedTensor: The output scale factor (or factors for per-axis quantization). Must be either a scalar (for per-tensor quantization) or a 1D tensor with size matching the dimension of the specified axis (for per-axis quantization).\\n        - `out_zero_point` AnyRankedTensor: The output zero point value (or values for per-axis quantization). Must be in range of the quantized storage type.\\n        - `axis` Optional<i32>: The axis along which quantization is applied. Must be in range [0, rank) where rank is the rank of the input tensor.\\n        - `output_dtype` Optional<TTCore_DataTypeAttr>: The data type of the output tensor.\\n        - `memory_config` Optional<TTNN_MemoryConfigAttr>: The memory configuration for the output tensor.\\n      ```\\n      // For per-tensor requantization:\\n      output[i] = round((input[i] - input_zero_point) * (input_scale / output_scale)) + output_zero_point\\n      // For per-axis requantization:\\n      output[i0, i1, ..., ia, ..., in] = round((input[i0, i1, ..., ia, ..., in] - in_zero_point[ia]) * (in_scale[ia] / out_scale[ia])) + out_zero_point[ia]\\n      ```\\n      Example:\\n      ```mlir\\n      %input = ttir.empty() : () -> tensor<64x128x!quant.uniform<i32:f32, 0.1>>\\n      %output = ttir.empty() : () -> tensor<64x128x!quant.uniform<i32:f32, 0.2>>\\n      %requantized = \\\"ttnn.requantize\\\"(%input, %output) : (tensor<64x128x!quant.uniform<i32:f32, 0.1>, tensor<64x128x!quant.uniform<i32:f32, 0.2>>) -> tensor<64x128x!quant.uniform<i32:f32, 0.2>>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"in_scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"in_zero_point\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"out_scale\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"out_zero_point\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"OptionalAttr<I32Attr>\" },\n      { \"name\": \"output_dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.reset_global_semaphore\",\n    \"summary\": \"Reset global semaphore op.\",\n    \"description\": \"Resets a global semaphore to the specified value.\\n\\n      Example:\\n      ```mlir\\n      \\\"ttnn.reset_global_semaphore\\\"(%semaphore) <{value = 0 : ui32}> : (!ttnn.global_semaphore) -> ()\\n      ```\",\n    \"operands\": [\n      { \"name\": \"semaphore\", \"type\": \"TTNN_GlobalSemaphore\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"UI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.reshape\",\n    \"summary\": \"Reshape op.\",\n    \"description\": \"Reshape tensor.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.rms_norm\",\n    \"summary\": \"RMS normalization op.\",\n    \"description\": \"RMS (Root Mean Square) normalization operation over the input tensor.\\n      Normalizes the input by computing the root mean square of elements and\\n      dividing by that value, optionally scaling and shifting the result.\\n\\n      This operation performs normalization over the last dimension of the input tensor,\\n      matching the TTNN runtime implementation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"weight\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"bias\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"DefaultValuedAttr<F32Attr, 1e-12>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.rotary_embedding\",\n    \"summary\": \"Rotary embedding op in TTNN dialect.\",\n    \"description\": \"Applies rotary embedding to the input tensor using precomputed cosine and sine caches.\\n    Formula used:\\n      x_rotated = x * cos + rotate_half(x) * sin\\n      where rotate_half(x) swaps the first and second halves of the last dimension of x.\\n\\n    Example:\\n      ```mlir\\n      %result = ttnn.rotary_embedding(%input, %cos_cache, %sin_cache)\\n        {memory_config = #ttnn.memory_config<interleaved>}\\n        : tensor<1x32x1024x64xf16>, tensor<1x1x1024x64xf16>, tensor<1x1x1024x64xf16>\\n        -> tensor<1x32x1024x64xf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"cos_cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"sin_cache\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"token_index\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.rotary_embedding_llama\",\n    \"summary\": \"Rotary embedding llama operation.\",\n    \"description\": \"Applies rotary embedding to the input tensor using precomputed cosine and sine caches along with a transformation matrix.\\n\\n      The operation supports both prefill and decode modes:\\n      - Prefill mode: Uses interleaved memory layout\\n      - Decode mode: Uses height-sharded memory layout\\n\\n      Example:\\n      ```mlir\\n      %result = ttnn.rotary_embedding_llama(%input, %cos_cache, %sin_cache, %trans_mat)\\n        {is_decode_mode = false, memory_config = #ttnn.memory_config<interleaved>}\\n        : tensor<1x32x128xbf16>, tensor<1x32x128xbf16>, tensor<1x32x128xbf16>,\\n        tensor<1x1x32x32xbf16> -> tensor<1x32x128xbf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"cos_cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"sin_cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"trans_mat\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_decode_mode\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.rsqrt\",\n    \"summary\": \"Eltwise rsqrt.\",\n    \"description\": \"Eltwise rsqrt operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.scaled_dot_product_attention\",\n    \"summary\": \"Scaled dot product attention operation.\",\n    \"description\": \"Scaled dot product attention.\\n      The implementation is FlashAttention-2.\\n\\n      Args:\\n          query (AnyRankedTensor): The query tensor.          [batch x num_heads x query_seq_len x head_size]\\n          key (AnyRankedTensor): The key tensor.              [batch x num_kv_heads x kv_seq_len x head_size]\\n          value (AnyRankedTensor): The value tensor.          [batch x num_kv_heads x kv_seq_len x head_size]\\n          attention_mask (AnyRankedTensor, optional): Defaults to `None`. [batch x 1 x query_seq_len x kv_seq_len]. Head broadcasting is implied.\\n          is_causal (bool): Whether the attention is causal. Defaults to `true`.\\n          scale (float, optional): Defaults to `None`.\\n          sliding_window_size (uint, optional): Defaults to `None`. Size of sliding window for attention. If provided && is_causal, only attends to the last `sliding_window_size` tokens. If provided && !is_causal, attends to a window of size `sliding_window_size` centered at the current position.\\n          memory_config (MemoryConfigAttr, optional): Memory configuration for the operation. Defaults to `None`.\\n\\n\\n      Returns:\\n          AnyRankedTensor: The output tensor [batch x num_heads x query_seq_len x head_size].\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_mask\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"sliding_window_size\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.scaled_dot_product_attention_decode\",\n    \"summary\": \"A version of scaled dot product attention specifically for decode.\",\n    \"description\": \"A version of scaled dot product attention specifically for decode.\\n        The implementation is Flash-Decode and it currently only supports MQA on decoding single token.\\n\\n        Args:\\n            input_tensor_q (AnyRankedTensor): The input tensor [1 x batch x num_heads x head_size]. Note that there is no sequence length dimension as this op is intended for processing a single query token.\\n            input_tensor_k (AnyRankedTensor): The input tensor [batch x num_kv_heads x   seq_len x head_size].\\n            input_tensor_v (AnyRankedTensor): The input tensor [b x num_kv_heads x   seq_len x head_size].\\n            is_causal (bool, optional): Whether the attention is causal. Defaults to `true`.\\n            attention_mask (AnyRankedTensor, optional): The attention mask [batch x 1 x query_seq_len x kv_seq_len].\\n            cur_pos_tensor (AnyRankedTensor): [batch] Tensor of integers of length batch.\\n            attention_sink (AnyRankedTensor, optional): The attention sink [num_heads, 32] (must be a single tile wide).\\n            scale (float, optional): Defaults to `None`.\\n            memory_config (MemoryConfigAttr, optional): Memory configuration for the operation. Defaults to `None`.\\n\\n        Returns:\\n            AnyRankedTensor: The output tensor [1 x b x pnh x dh].\",\n    \"operands\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"attention_mask\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"cur_pos_tensor\", \"type\": \"Optional<AnyRankedTensor>\" },\n      { \"name\": \"attention_sink\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_causal\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"scale\", \"type\": \"OptionalAttr<F32Attr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"program_config\", \"type\": \"OptionalAttr<TTNN_SDPAProgramConfigAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.scatter\",\n    \"summary\": \"Scatter op.\",\n    \"description\": \"Embeds the values of the source tensor into the input tensor at locations specified by the index tensor along the given dimension.\\n\\n      Parameters:\\n        - `input` (ttnn.Tensor): The tensor being updated.\\n        - `index` (ttnn.Tensor): Indices where values will be written to.\\n        - `source` (ttnn.Tensor): The values to scatter into the input tensor.\\n        - `dim` (int32_t): The dimension along which to scatter.\\n        - `scatter_reduce_type` (Enum): The scatter reduce type to use (SUM, PROD, MIN, MAX, INVALID).\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"index\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I32Attr\" },\n      { \"name\": \"scatter_reduce_type\", \"type\": \"TTCore_ReduceTypeAttr{sum|mean|max|min|std|var|prod|invalid}\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sigmoid\",\n    \"summary\": \"Eltwise sigmoid.\",\n    \"description\": \"Eltwise sigmoid operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sign\",\n    \"summary\": \"Eltwise sign operation.\",\n    \"description\": \"Returns the sign of the `operand` element-wise and produces a `result`\\n      tensor.\\n\\n      Example:\\n        %a: [[3, -2, 0], [1, -4, 4]]\\n        \\\"ttnn.sign\\\"(%a, %out) -> %out: [[1, -1, 0], [1, -1, 1]]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.silu\",\n    \"summary\": \"Eltwise SiLU.\",\n    \"description\": \"Eltwise SiLU (Swish) operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sin\",\n    \"summary\": \"Eltwise sine.\",\n    \"description\": \"Eltwise sine operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.slice_dynamic\",\n    \"summary\": \"Dynamic slice op.\",\n    \"description\": \"Extract a portion of a tensor based on the specified start (`begins`), stop (`ends`), and step\\n      indices for each dimension. Maps to ttnn::slice.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"begins\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"ends\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"step\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.slice_static\",\n    \"summary\": \"Slice op.\",\n    \"description\": \"Extract a portion of a tensor based on the specified start (`begins`), stop (`ends`), and step\\n      indices for each dimension. The `begins` and `ends` parameters are attributes with fixed values.\\n      Maps to ttnn::slice.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begins\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"ends\", \"type\": \"TypedArrayAttrBase<I32Attr>\" },\n      { \"name\": \"step\", \"type\": \"TypedArrayAttrBase<I32Attr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.softmax\",\n    \"summary\": \"Softmax op.\",\n    \"description\": \"Softmax operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"SI32Attr\" },\n      { \"name\": \"numericStable\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sort\",\n    \"summary\": \"Sort op.\",\n    \"description\": \"Sorts elements of a tensor along a given dimension.\\n\\n    Input:\\n      - input: AnyRankedTensor\\n\\n    Attributes:\\n      - dim (int8): The dimension to sort along (default: -1, the last dim).\\n      - descending (bool): If True, sort in descending order (default: False).\\n      - stable (bool): If True, ensures stable sort (equal elements keep order).\\n\\n    Returns a tuple:\\n      - values: the sorted tensor.\\n      - indices: the original indices of the sorted values.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"DefaultValuedAttr<SI8Attr, -1>\" },\n      { \"name\": \"descending\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"stable\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sparse_matmul\",\n    \"summary\": \"Sparse block matrix multiplication with sparsity mask.\",\n    \"description\": \"The `sparse_matmul` operation performs batched matrix multiplication where\\n      computation is selectively skipped for blocks marked as zero in the sparsity\\n      tensor. Input `b` is organized as a collection of weight matrices indexed by\\n      a block dimension (dim 1), and the sparsity tensor controls which blocks\\n      participate in the computation.\\n\\n      Supported Modes:\\n      - is_input_a_sparse=false, is_input_b_sparse=true (column-parallel):\\n        a: [A, B, M, K], b: [1, E, K, N], sparsity: [A, B, 1, E]\\n        -> output: [A, B, 1, E, M, N]\\n      - is_input_a_sparse=true, is_input_b_sparse=false (row-parallel):\\n        a: [A, E, M, K], b: [1, E, K, N], sparsity: [1, 1, A, E]\\n        -> output: [A, E, M, N]\\n      - is_input_a_sparse=true, is_input_b_sparse=true (both sparse):\\n        a: [1, E, M, K], b: [1, E, K, N], sparsity: [1, 1, 1, E]\\n        -> output: [1, E, M, N]\\n\\n      Example:\\n      ```mlir\\n      %result = \\\"ttnn.sparse_matmul\\\"(%activations, %weights, %sparsity) <{\\n          is_input_a_sparse = false, is_input_b_sparse = true, nnz = 2\\n      }> : (tensor<2x4x32x2880xbf16>, tensor<1x4x2880x5760xbf16>,\\n            tensor<2x4x1x4xbf16>) -> tensor<2x4x1x4x32x5760xbf16>\\n      ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"b\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"sparsity\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_input_a_sparse\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"is_input_b_sparse\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"nnz\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"program_config\", \"type\": \"OptionalAttr<TTNN_MatmulMultiCoreReuseMultiCast1DProgramConfigAttr>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.split_query_key_value_and_split_heads\",\n    \"summary\": \"Split query, key, values and split heads op used in attention layer.\",\n    \"description\": \"Splits input_tensor of shape [batch_size, sequence_size, 3 * hidden_size] into 3 tensors (Query, Key, Value) of shape [batch_size, sequence_size, hidden_size]. Then, reshapes and permutes the output tensors, to make them ready for computing attention scores.\\n      If kv_input_tensor is passed in, then input_tensor of shape [batch_size, sequence_size, hidden_size] is only used for Query, and kv_input_tensor of shape [batch_size, sequence_size, 2 * hidden_size] is used for Key and Value.\\n      For the sharded implementation, the input query, key and value are expected to be concatenated such that the heads are interleaved (q1 k1 v1…qn kn vn).\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"kv_input_tensor\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"query\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"key\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_heads\", \"type\": \"UI32Attr\" },\n      { \"name\": \"num_kv_heads\", \"type\": \"OptionalAttr<UI32Attr>\" },\n      { \"name\": \"transpose_key\", \"type\": \"BoolAttr\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sqrt\",\n    \"summary\": \"Eltwise sqrt.\",\n    \"description\": \"Eltwise sqrt operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.subtract\",\n    \"summary\": \"Eltwise subtract.\",\n    \"description\": \"Eltwise subtract operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"rhs\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.sum\",\n    \"summary\": \"Sum reduction op.\",\n    \"description\": \"Sum reduction op.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dim\", \"type\": \"BoolAttr\" },\n      { \"name\": \"dim_arg\", \"type\": \"OptionalAttr<TypedArrayAttrBase<I32Attr>>\" },\n      { \"name\": \"compute_config\", \"type\": \"OptionalAttr<TTNN_DeviceComputeKernelConfig>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.tan\",\n    \"summary\": \"Eltwise tan op.\",\n    \"description\": \"Eltwise tan operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.tanh\",\n    \"summary\": \"Eltwise tanh op.\",\n    \"description\": \"Eltwise tanh operation.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.to_device\",\n    \"summary\": \"ToDevice op.\",\n    \"description\": \"This op sends the input tensor to the given device with the given memory config.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device\", \"type\": \"TTNN_Device\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.to_dtype\",\n    \"summary\": \"ToDType op.\",\n    \"description\": \"This op converts the data type of the input tensor based on the given data type on the host.\\n\\n      Args:\\n        - :attr:`input`: the ttnn.Tensor\\n        - :attr:`dtype`: `ttnn` data type.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.to_layout\",\n    \"summary\": \"ToLayout op.\",\n    \"description\": \"This op wraps all layout information gathered from ttir.toLayout. It is used/updated by the optimizer\\n      to perform optimizations, and later broken down into specific memory/layout operations (toDevice, toMemoryConfig etc.).\\n      Currently in the TTNN backend, we use this op solely for tilize/untilize, therefore marking all other attrs as optional.\\n      Once ttnn::to_layout supports other attrs, we can remove the optional tag.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"TTNN_LayoutAttr{row_major|tile|invalid}\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.to_memory_config\",\n    \"summary\": \"ToMemoryConfig op.\",\n    \"description\": \"This op converts the memory config of the input tensor based on the given memory config.\\n      It handles:\\n        - Dram to L1\\n        - L1 to Dram\\n        - Interleaved to sharded\\n        - Sharded to interleaved\\n        - Sharded to sharded (reshard)\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"TTNN_MemoryConfigAttr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.topk\",\n    \"summary\": \"Top-K selection operation.\",\n    \"description\": \"Returns the `k` largest or `k` smallest elements of the `input_tensor` along a given dimension `dim`.\\n    If `dim` is not provided, the last dimension of the input_tensor is used.\\n    If `largest` is True, the `k` largest elements are returned. Otherwise, the `k` smallest elements are returned.\\n    The boolean option `sorted` if True, will make sure that the returned `k` elements are sorted.\\n    the `memory_config` parameter is optional which represents the memory configuration for the operation.\",\n    \"operands\": [\n      { \"name\": \"input_tensor\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"values\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"I32Attr\" },\n      { \"name\": \"dim\", \"type\": \"DefaultValuedAttr<I32Attr, -1>\" },\n      { \"name\": \"largest\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"sorted\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.transpose\",\n    \"summary\": \"Transpose op.\",\n    \"description\": \"Transpose tensor along two given dimensions.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim0\", \"type\": \"SI32Attr\" },\n      { \"name\": \"dim1\", \"type\": \"SI32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.typecast\",\n    \"summary\": \"Typecast op.\",\n    \"description\": \"This op converts the data type of the input tensor based on the given data type.\\n      It handles:\\n        - conversions of data types.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\", \"type\": \"TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.update_cache\",\n    \"summary\": \"Update static cache tensor.\",\n    \"description\": \"Updates the `cache` tensor in-place with values from `input` at `update_index` and `batch_offset`.\",\n    \"operands\": [\n      { \"name\": \"cache\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"update_index\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"batch_offset\", \"type\": \"I32Attr\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.upsample\",\n    \"summary\": \"Upsample 2D op.\",\n    \"description\": \"Upsample 2D operation. Input tensor is assumed to be in NHWC format.\\n\\n      Attributes:\\n      - `scale_factor` (si32 | array<i32>): The scale factor for upsampling in H and W dimensions respectively.\\n      - `mode` (str): The upsampling algorithm. Currently only \\\"nearest\\\" and \\\"bilinear\\\" are supported. Default is \\\"nearest\\\".\\n\\n      Example:\\n        // %a: tensor<10x64x32xbf16>\\n        %0 = \\\"ttnn.upsample\\\"(%a) <{scale_factor = array<i32: 2, 4>}> : (tensor<10x64x32x3xbf16>) -> tensor<10x128x128x3xbf16>\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale_factor\", \"type\": \"AnyAttrOf<[SI32Attr, DenseI32ArrayAttr]>\" },\n      { \"name\": \"mode\", \"type\": \"DefaultValuedAttr<StrAttr, \\\"nearest\\\">\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.where\",\n    \"summary\": \"Eltwise where.\",\n    \"description\": \"Eltwise where operation.\",\n    \"operands\": [\n      { \"name\": \"first\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"second\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"third\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.write_tensor\",\n    \"summary\": \"Write tensor op.\",\n    \"description\": \"Copies host_tensor data into device_tensor through cq_id.\\n    Memory copy is done in place, thus no output is returned.\\n    Inputs:\\n      - `host_tensor` AnyRankedTensor: The host tensor to copy.\\n      - `device_tensor` AnyRankedTensor: The device tensor to copy into.\\n      - `blocking` bool: Whether the copy should be executed synchronously.\\n      - `cq_id` i32: The command queue to copy the tensor with. Must be 0 or 1.\",\n    \"operands\": [\n      { \"name\": \"host_tensor\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"device_tensor\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blocking\", \"type\": \"DefaultValuedAttr<BoolAttr, false>\" },\n      { \"name\": \"cq_id\", \"type\": \"DefaultValuedAttr<UI32Attr, 0>\" }\n    ]\n  },\n  {\n    \"name\": \"ttnn.zeros\",\n    \"summary\": \"Creates a tensor filled with zeros.\",\n    \"description\": \"Tensor operation to create a tensor filled with zeros.\\n\\n    Given a ShapeAttr `shape`, produces a tensor with the same shape, filled with zeros.\\n\\n    Example:\\n      %0 = \\\"ttnn.zeros\\\"() <{shape = array<i32:64, 28, 28>}> : () -> tensor<64x28x28xbf16>\\n      // %0: [[[0, 0, 0, ..., 0], [0, 0, 0, ..., 0], ..., [0, 0, 0, ..., 0]]]\",\n    \"operands\": [\n      { \"name\": \"device\", \"type\": \"Optional<TTNN_Device>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"TTNN_ShapeAttr\" },\n      { \"name\": \"dtype\", \"type\": \"OptionalAttr<TTCore_DataTypeAttr{f32|f16|bf16|bfp_f8|bfp_bf8|bfp_f4|bfp_bf4|bfp_f2|bfp_bf2|u32|u16|u8|si32|i1}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<TTNN_LayoutAttr{row_major|tile|invalid}>\" },\n      { \"name\": \"memory_config\", \"type\": \"OptionalAttr<TTNN_MemoryConfigAttr>\" }\n    ]\n  },\n  {\n    \"name\": \"ub.poison\",\n    \"summary\": \"Poisoned constant operation.\",\n    \"description\": \"The `poison` operation materializes a compile-time poisoned constant value\\n    to indicate deferred undefined behavior.\\n    `value` attribute is needed to indicate an optional additional poison\\n    semantics (e.g. partially poisoned vectors), default value indicates results\\n    is fully poisoned.\\n\\n    Examples:\\n\\n    ```\\n    // Short form\\n    %0 = ub.poison : i32\\n    // Long form\\n    %1 = ub.poison <#custom_poison_elements_attr> : vector<4xi64>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"DefaultValuedAttr<PoisonAttrInterface, {}>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict (`<` $value^ `>`)? `:` type($result)\"\n  },\n  {\n    \"name\": \"ub.unreachable\",\n    \"summary\": \"Unreachable operation.\",\n    \"description\": \"The `unreachable` operation triggers immediate undefined behavior if\\n    executed.\\n\\n    Example:\\n\\n    ```\\n    ub.unreachable\\n    ```\",\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"util.align\",\n    \"summary\": \"Aligns up to a power-of-two alignment if required.\",\n    \"description\": \"Aligns |value| up to the given power-of-two |alignment| if required.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"SignlessIntegerOrIndexLike\" },\n      { \"name\": \"alignment\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"SignlessIntegerOrIndexLike\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $alignment attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.assume.int\",\n    \"summary\": \"Memorializes assumptions about index/integer values.\",\n    \"description\": \"This op is used to memorialize the result of some integer analysis or\\n    outside knowledge across a boundary beyond which such information can\\n    not be easily recovered. Assumptions are made per op/result pair.\\n\\n    Assumptions are tied to operands as rows of permutations of an\\n    `#util.assume.int` per operand. The number of permutations is the rank.\\n    Typically multiple permutations record a specific subset of assumptions\\n    broken down per call-site in some way that is meaningful to the receiver.\\n    Implementations can use this information to specialize on each\\n    permutation if it is meaningful to do so (i.e. vs unioning across them).\\n    In such cases, there will typically be one such op at the top of a\\n    function or scope which passes all covered operands through it.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnySignlessIntegerOrIndex>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnySignlessIntegerOrIndex>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"assumptions\", \"type\": \"TypedArrayAttrBase<TypedArrayAttrBase<Util_IntAssumptionAttr>>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operands', 'results']>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.alloc\",\n    \"summary\": \"Allocates a buffer with undefined contents.\",\n    \"description\": \"Allocates a buffer with undefined contents. Consumers of the allocated\\n    result must assume nothing of the contents.\",\n    \"operands\": [\n      { \"name\": \"storage_size\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_BufferType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"assemblyFormat\": \"`uninitialized`\\n    attr-dict\\n    `:`\\n    type($result) `` `{` $storage_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.compare\",\n    \"summary\": \"Compares a range of two buffers.\",\n    \"description\": \"Returns true if the two ranges are bitwise equivalent, somewhat like memcmp.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"lhs_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"lhs_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"rhs\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"rhs_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"rhs_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"length\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"assemblyFormat\": \"$lhs `[` $lhs_offset `]` `,`\\n    $rhs `[` $rhs_offset `]` `,`\\n    $length `:`\\n    type($lhs) `` `{` $lhs_size `}` `,`\\n    type($rhs) `` `{` $rhs_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.constant\",\n    \"summary\": \"Constant host-side byte buffer.\",\n    \"description\": \"Defines a compile-time byte buffer based on the given attribute value.\\n    The attribute will be serialized into the canonical IREE format for the\\n    chosen host target.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_BufferType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"value\", \"type\": \"Util_AnySerializableAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IndexAttr>\" },\n      { \"name\": \"mime_type\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($name^)? attr-dict `:` type($result) `=` $value\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.copy\",\n    \"summary\": \"Copies a range of bytes between buffers.\",\n    \"description\": \"Copies a range of bytes as with memcpy (no overlapping).\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"target\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"length\", \"type\": \"Util_Size\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` `,`\\n    $target `[` $target_offset `]` `,`\\n    $length `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.dealloc\",\n    \"summary\": \"Deallocates a buffer.\",\n    \"description\": \"Hints that the buffer contents can be discarded. Buffers are reference\\n    counted and other owners may keep it live beyond the dealloc.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"operand_size\", \"type\": \"Util_Size\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) `{` $operand_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.fill\",\n    \"summary\": \"Fills a range of bytes with a value.\",\n    \"description\": \"Fills the contents of the buffer in the given byte range with a pattern.\\n    The offset and length must match the natural alignment of the pattern type.\",\n    \"operands\": [\n      { \"name\": \"pattern\", \"type\": \"Util_FillPattern\" },\n      { \"name\": \"target\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"length\", \"type\": \"Util_Size\" }\n    ],\n    \"assemblyFormat\": \"$pattern `,`\\n    $target `[` $target_offset `for` $length `]` `:`\\n    type($pattern) `->`\\n    type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.hash\",\n    \"summary\": \"Computes the hash of a byte range of a buffer.\",\n    \"description\": \"Computes the SipHash-2-4 of a value at a byte offset with the given length.\\n    This always uses a seed of `0x0001020304...0e0f` and produces a single 64\\n    bit value.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"length\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `for` $length `]`\\n    `:` type($source) `` `{` $source_size `}` `->` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.load\",\n    \"summary\": \"Loads a value from a buffer.\",\n    \"description\": \"Loads a value at a byte offset. Must be aligned to the natural size of the\\n    result type.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"length\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_Primitive\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `for` $length `]`\\n    `:` type($source) `` `{` $source_size `}` `->` type($result)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.size\",\n    \"summary\": \"Returns the total buffer storage size in bytes.\",\n    \"description\": \"Returns the total length of the buffer in bytes from its base offset.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Util_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_Size\" }\n    ],\n    \"assemblyFormat\": \"$operand\\n    `:` type($operand)\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.slice\",\n    \"summary\": \"Clones a subregion of a buffer.\",\n    \"description\": \"Returns a copy of the contents from the source buffer.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"result_size\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_BufferType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IndexAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` attr-dict `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($result) `` `{` $result_size `}`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.storage\",\n    \"summary\": \"Returns the underlying buffer storage range.\",\n    \"description\": \"Returns the buffer storage as a memref that must be offset and restricted to\\n    the returned range. The memref may be of any type and the user is\\n    responsible for ensuring that the reinterpret_cast-like behavior makes sense\\n    for the data they are accessing.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"operand_size\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"offset\", \"type\": \"Util_Offset\" }\n    ],\n    \"assemblyFormat\": \"$operand\\n    `:` type($operand) `` `{` $operand_size `}` `->` `(` type($result) `,` type($offset) `)`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.store\",\n    \"summary\": \"Stores a value into a buffer.\",\n    \"description\": \"Stores a value at a byte offset. Must be aligned to the natural size of the\\n    source type.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_Primitive\" },\n      { \"name\": \"target\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"target_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"target_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"length\", \"type\": \"Util_Size\" }\n    ],\n    \"assemblyFormat\": \"$source `,`\\n    $target `[` $target_offset `for` $length `]`\\n    `:` type($source) `->` type($target) `` `{` $target_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.buffer.subspan\",\n    \"summary\": \"Returns a reference to a subrange of a buffer.\",\n    \"description\": \"Returns a logical view into an underlying source buffer. This induces\\n    aliasing and multiple SSA values may allow access to the same underlying\\n    buffer storage.\\n\\n    Subspans are a compiler-only concept and are propagated by an analysis pass\\n    to result in absolute offsets on accesses any place the subrange would have\\n    been used.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"source_size\", \"type\": \"Util_Size\" },\n      { \"name\": \"source_offset\", \"type\": \"Util_Offset\" },\n      { \"name\": \"result_size\", \"type\": \"Util_Size\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_BufferType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $source_offset `]` `:`\\n    type($source) `` `{` $source_size `}` `->`\\n    type($result) `` `{` $result_size `}`\\n    attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.call\",\n    \"summary\": \"Function call operation.\",\n    \"description\": \"Represents a direct call to a function that is within the same symbol scope\\n    as the call. The operands and result types of the call must match the\\n    specified function type.\\n\\n    Calls support tied operands which indicate that specific results alias\\n    a specific operand. The operand and result types are allowed to differ if\\n    a cast is performed within the callee.\\n\\n    Example:\\n    ```mlir\\n    util.func @fn(%arg0: i32, %arg1: tensor<f32>) -> (f32, %arg1 as tensor<i32>)\\n    ...\\n    %0 = util.call @fn(%0, %1) : (i32, tensor<f32>) -> (f32, %1 as tensor<i32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)`\\n    attr-dict `:`\\n    custom<OperandTypeList>(type($operands))\\n    `->`\\n    custom<TiedFunctionResultList>(ref($operands),\\n                                   ref(type($operands)),\\n                                   type($results),\\n                                   $tied_operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.cast\",\n    \"summary\": \"Casts one util type to another ala static_cast/dynamic_cast.\",\n    \"description\": \"Performs a type cast between object types known to the util dialect.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `to` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.cmp.eq\",\n    \"summary\": \"Compares two values for equality.\",\n    \"description\": \"Compares two operands for equality. This is intended for comparing IREE\\n    reference types (like !util.buffer) that cannot be used with std.cmpi.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.cmp.ne\",\n    \"summary\": \"Compares two values for inequality.\",\n    \"description\": \"Compares two operands for inequality. This is intended for comparing IREE\\n    reference types (like !util.buffer) that cannot be used with std.cmpi.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I1\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.func\",\n    \"summary\": \"Function operation containing a CFG region.\",\n    \"description\": \"An operation declaring a callable function.\\n\\n    An external function declaration (used when referring to a function declared\\n    in some other module) has no body.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"tied_operands\", \"type\": \"OptionalAttr<TypedArrayAttrBase<Util_IndexAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.global\",\n    \"summary\": \"Stateful global variable declaration.\",\n    \"description\": \"Declares a global variable that maintains its value across invocations.\\n    The value is tied to the execution context of the module and different\\n    contexts will have different variable storage.\\n\\n    Globals can be initialized with an `initial_value` attribute that specifies\\n    their value at module initialization time. This initial value is evaluated\\n    in module definition order: a global with an initial value is considered\\n    initialized at its definition point in the module, not when first accessed.\\n\\n    During module initialization:\\n    * Globals with `initial_value` attributes conceptually have their value\\n      materialized and stored before any subsequent initialization points\\n    * Initialization order follows module definition order exactly\\n    * Globals are visible to initializers but only after their definition point\\n\\n    Example:\\n    ```mlir\\n    // A is initialized to 1 at this point in module initialization.\\n    util.global @A = 1 : i32\\n\\n    // This initializer can read A (it's defined above).\\n    util.initializer {\\n      %a = util.global.load @A : i32  // Loads 1\\n    }\\n\\n    // B is initialized to 2 here, after the above initializer runs.\\n    util.global @B = 2 : i32\\n    ```\\n\\n    Globals marked as mutable can be modified by stores anywhere in the program.\\n    Immutable globals have strict initialization rules:\\n    * Can only be initialized once - either by `initial_value` or by stores\\n      in initializers, never both.\\n    * Stores to immutable globals are only allowed in:\\n      - `util.initializer` ops directly\\n      - Functions that are only called from initializers (initializer-only)\\n    * Stores from externally-reachable functions are forbidden.\\n    * Initialization must respect module order - initializers can only\\n      access globals defined before them.\\n\\n    Stores to immutable globals inside control flow regions (scf.if, scf.for,\\n    scf.while, etc) in initializer-only functions will generate warnings as\\n    they may indicate complex initialization patterns that could be fragile:\\n    ```mlir\\n    util.func private @init_func() {\\n      scf.if %cond {\\n        // Warning: conditional store in initializer-only function\\n        util.global.store %val, @immutable_global : i32\\n      }\\n    }\\n    ```\\n    While such patterns are allowed they should be used with caution as the\\n    initialization behavior depends on runtime control flow and the compiler\\n    may disable optimizations on those globals.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<TypedAttrInterface>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name\\n    attr-dict\\n    custom<TypeOrAttr>($type, $initial_value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.global.address\",\n    \"summary\": \"Returns an address reference to a global.\",\n    \"description\": \"Returns the address of a global as a typed reference. Can be used with the\\n    global load and store indirect ops.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_AnyGlobalPtr\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"Util_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` qualified(type($result))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.global.load\",\n    \"summary\": \"Loads a value from a global variable.\",\n    \"description\": \"Returns a global variable value. |is_immutable| is a reflection of the\\n    mutability of the loaded global to minimize the need to traverse symbol\\n    tables.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"Util_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.global.load.indirect\",\n    \"summary\": \"Loads a value from a global variable.\",\n    \"description\": \"Returns a copy of the global variable value.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"Util_AnyGlobalPtr\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` qualified(type($global)) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.global.store\",\n    \"summary\": \"Stores a value into a global variable.\",\n    \"description\": \"Stores a copy of the value into a global variable.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"Util_GlobalRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.global.store.indirect\",\n    \"summary\": \"Stores a value into a global variable.\",\n    \"description\": \"Stores a copy of the value into a global variable.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"global\", \"type\": \"Util_AnyGlobalPtr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value) `->` qualified(type($global))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.initializer\",\n    \"summary\": \"Global initialization function.\",\n    \"description\": \"A function that is called in definition order upon module initialization.\\n    Must not load any globals that are defined or initialized after it in the\\n    module.\\n\\n    Module initialization follows a strict execution order to ensure\\n    correctness:\\n    * Initialization points: two types of operations define initialization:\\n      - `util.initializer` ops: explicit initialization functions\\n      - `util.global` ops with initial values: implicit initialization via\\n        attributes\\n    * Execution order: initialization proceeds in exact module definition order:\\n      - Operations execute sequentially from top to bottom\\n      - Each `util.global` with an initial value conceptually materializes its\\n        value and stores it before the next initialization point\\n      - Each `util.initializer` executes its entire body before proceeding\\n    * Dependency rules:\\n      - Initializers may only access globals defined before them in module order\\n      - Globals with initial values are considered \\\"initialized\\\" at their\\n        definition point, not when first accessed\\n      - Function calls within initializers observe the current initialization\\n        state when the call is made\\n    * Transformation guarantees:\\n      - Combining passes preserve exact initialization order\\n      - Globals with initial values may be converted to explicit initialization\\n        while maintaining their position in the initialization sequence\\n      - The final initialization state must be identical to sequential execution\\n\\n    Example execution:\\n    ```mlir\\n    util.global @A = 1 : i32           // A = 1\\n    util.initializer { ... }           // Executes with A = 1\\n    util.global @B = 2 : i32           // B = 2\\n    util.initializer {\\n      %a = util.global.load @A : i32   // Loads 1\\n      %b = util.global.load @B : i32   // Loads 2\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.list.construct\",\n    \"summary\": \"Constructs a list with the given initial values.\",\n    \"description\": \"Creates a new list with the given values added in order. The list will be\\n    allocated with an initial capacity equal to the number of values. This is a\\n    pseudo-operation that expands to a list create, resize, and a series of\\n    sets.\",\n    \"operands\": [\n      { \"name\": \"values\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_AnyListType\" }\n    ],\n    \"assemblyFormat\": \"custom<ValueTypeList>($values, type($values))\\n    attr-dict `:` qualified(type($result))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.list.create\",\n    \"summary\": \"Creates a new empty list.\",\n    \"description\": \"Creates a new empty list with an optional initial capacity.\",\n    \"operands\": [\n      { \"name\": \"initial_capacity\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_AnyListType\" }\n    ],\n    \"assemblyFormat\": \"($initial_capacity^)? attr-dict `:` qualified(type($result))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.list.get\",\n    \"summary\": \"Element accessor.\",\n    \"description\": \"Returns the value of the element at the given index. Note that the value\\n    may be null if the element is null or the type does not match.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"Util_AnyListType\" },\n      { \"name\": \"index\", \"type\": \"Index\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$list `[` $index `]` attr-dict `:` custom<ListTypeGet>(type($list), type($result))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.list.resize\",\n    \"summary\": \"Resizes the list to a new count in elements.\",\n    \"description\": \"Resizes the list to contain `new_size` elements. This will either truncate\\n    the list if the existing size is greater than `new_size` or extend the list\\n    with the default list value of the element type.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"Util_AnyListType\" },\n      { \"name\": \"new_size\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` qualified(type($list))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.list.set\",\n    \"summary\": \"Element mutator.\",\n    \"description\": \"Sets the element at the given index to the new value.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"Util_AnyListType\" },\n      { \"name\": \"index\", \"type\": \"Index\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"$list `[` $index `]` `,` $value attr-dict `:` custom<ListTypeSet>(type($list), type($value))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.list.size\",\n    \"summary\": \"The size of the list in elements.\",\n    \"description\": \"Returns the current size of the list in elements.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"Util_AnyListType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` qualified(type($list))\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.null\",\n    \"summary\": \"Returns a null type value.\",\n    \"description\": \"Defines an SSA value that is lowered into dialects supporting\\n    null/undefined/optional/etc values.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.numeric.optional_narrow\",\n    \"summary\": \"memorializes an optional numeric narrowing that is valid.\",\n    \"description\": \"Serves as a placeholder for points in the computation where an optional\\n    numeric narrowing can be performed without loss of information. Such ops\\n    can guide optimization passes wishing to perform precision reduction.\\n\\n    In addition to the operand and result type, this op takes an additional\\n    `semantic_type` attribute representing the semantic target type which can\\n    be:\\n      * FloatType\\n      * Signed IntegerType\\n      * Unsigned IntegerType\\n\\n    Note that this `semantic_type` must be a sign-carrying integer if using an\\n    integer type and cannot be IndexType (i.e. it can be used to indicate a\\n    possible narrowing of an IndexType to a specific integer).\\n\\n    If the operand is a TensorType, then the result must be a TensorType. The\\n    `semantic_type` constrains the element type.\\n\\n    Optionally, the minimum and maximum integer values (for integer semantic\\n    types) are tracked if known.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"AnyTypeOf<[Util_Element, Util_Tensor]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Util_Element, Util_Tensor]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"semantic_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"min_value\", \"type\": \"OptionalAttr<APIntAttr>\" },\n      { \"name\": \"max_value\", \"type\": \"OptionalAttr<APIntAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operand `:` type($operand) `as` $semantic_type attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.optimization_barrier\",\n    \"summary\": \"Prevents compiler optimizations across a value.\",\n    \"description\": \"Wraps any operands in an unoptimizable identity to prevent its results from\\n    being folded. It will be dropped during the final step in compilation and\\n    has no effect at runtime.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operands', 'results']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.range.extents\",\n    \"summary\": \"Returns the min/max of a union of a set of ranges.\",\n    \"description\": \"Computes min(offsets) and max(offsets + lengths). Though it's possible to\\n    express this with standard arithmetic this op enables more semantically\\n    meaningful folding/optimizations.\",\n    \"operands\": [\n      { \"name\": \"offsets\", \"type\": \"Variadic<Util_Range>\" },\n      { \"name\": \"lengths\", \"type\": \"Variadic<Util_Range>\" }\n    ],\n    \"results\": [\n      { \"name\": \"min\", \"type\": \"Util_Range\" },\n      { \"name\": \"max\", \"type\": \"Util_Range\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"custom<RangeList>($offsets, $lengths) attr-dict `:` type($min)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.range.max\",\n    \"summary\": \"Returns the max of all values.\",\n    \"description\": \"Computes the max of a variadic list of operands. Though it's possible to\\n    express this with standard arithmetic this op enables more semantically\\n    meaningful folding/optimizations.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Util_Range>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_Range\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.range.min\",\n    \"summary\": \"Returns the min of all values.\",\n    \"description\": \"Computes the min of a variadic list of operands. Though it's possible to\\n    express this with standard arithmetic this op enables more semantically\\n    meaningful folding/optimizations.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Util_Range>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_Range\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.return\",\n    \"summary\": \"Return from a util.initializer.\",\n    \"description\": \"Returns control from an initializer function.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\\n    ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.scf.unreachable\",\n    \"summary\": \"Non-terminator unreachable for use in SCF regions.\",\n    \"description\": \"Marks a point as unreachable within SCF regions. Unlike `util.unreachable`\\n    this is not a terminator and must be followed by appropriate region\\n    terminators (e.g. `scf.yield`).\\n\\n    When not in an SCF region (e.g. `util.func`) this op canonicalizes to an\\n    `util.unreachable` terminator that preserves the intended behavior.\\n\\n    Note that this op has side effects to prevent code motion: reaching this op\\n    at runtime is observable indirectly (by way of what ops _don't_ execute). At\\n    minimum presence of the op indicates all following ops in the same region\\n    are unreachable and depending on the parent op may indicate the entire\\n    parent op is unreachable. The behavior is roughly equivalent to having\\n    lowered SCF to CFG and used `util.unreachable`.\\n\\n    Example:\\n    ```mlir\\n    scf.while (...) {\\n      ...\\n      scf.condition(%true) ...\\n    } do {\\n      ...\\n      util.scf.unreachable \\\"infinite loop body\\\"\\n      scf.yield  // Required terminator with poison values\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($message^)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.sizeof\",\n    \"summary\": \"Returns the size in bytes of a datatype.\",\n    \"description\": \"Most datatypes have a static size at all layers of the compilation stack.\\n    However, those that only have a size for certain lowering flows can be\\n    challenging. This op represents such sizes in a way that can be specialized\\n    later.\\n\\n    Returns the size in bytes, rounded up to the next whole byte of the\\n    specified type. This op will fold to a constant index value for IntegerType\\n    and FloatType. All others are not folded.\",\n    \"results\": [\n      { \"name\": \"size\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sizedType\", \"type\": \"TypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$sizedType attr-dict-with-keyword\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.status.check_ok\",\n    \"summary\": \"Raises a global failure if a status is not 'ok'.\",\n    \"description\": \"When the status is not 'ok' this signals a runtime failure that causes the\\n    entire active invocation - and possibly *all* in-flight and pending\\n    invocations - to fail with the given status. The status will be propagated\\n    back via the available runtime error handling mechanisms such as semaphores\\n    or synchronous invocation results.\\n\\n    As the IREE execution model is deeply pipelined it's possible that failures\\n    have a latency between when they are emitted and when the application can\\n    observe the failure. It's also possible that other work that is in-flight\\n    or pending when the failure occurs will complete.\",\n    \"operands\": [\n      { \"name\": \"status\", \"type\": \"Util_Status\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$status (`,` $message^)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.string.format\",\n    \"summary\": \"Formats a string from a template and arguments.\",\n    \"description\": \"Produces a `!util.buffer` containing the formatted string. Uses `{}`-style\\n    substitution: `{}` for sequential args, `{N}` for explicit ordinal. `{{`\\n    and `}}` produce literal braces. Cannot mix `{}` and `{N}` in the same\\n    format string.\\n\\n    Integer args are converted to unsigned decimal. Buffer args are copied\\n    as-is. Folds to `util.buffer.constant` when all arguments are constant.\\n    Partially folds when some arguments are constant by merging constant\\n    segments into the format string literals.\\n\\n    Example:\\n    ```mlir\\n    %key = util.string.format \\\"blk.{}.attn_q.weight\\\"(%idx) : (index) -> !util.buffer\\n    %multi = util.string.format \\\"blk.{}.ffn.{}.weight\\\"(%a, %b) : (index, index) -> !util.buffer\\n    ```\",\n    \"operands\": [\n      { \"name\": \"args\", \"type\": \"Variadic<AnyTypeOf<[ Index, AnySignlessInteger, Util_BufferType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_BufferType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$format `(` $args `)` attr-dict `:` functional-type($args, $result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.string.itoa\",\n    \"summary\": \"Converts an integer to its decimal string representation.\",\n    \"description\": \"Produces a `!util.buffer` containing the unsigned decimal string\\n    representation of the input integer value. Folds to `util.buffer.constant`\\n    when the input is constant.\\n\\n    Example:\\n    ```mlir\\n    %str = util.string.itoa %value : index -> !util.buffer\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[Index, AnySignlessInteger]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_BufferType\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict `:` type($value) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.switch\",\n    \"summary\": \"Primitive switch operation.\",\n    \"description\": \"Returns the value with the given `index` in `values` or `default_value` if\\n    the index is out of bounds.\\n\\n    ```mlir\\n    // Switch %index to cases of %c100/%c200/%c300 if index==0, ==1, ==2.\\n    // If %index is out of range (<0 or >2) then default to %c5.\\n    %0 = util.switch %index[%c100, %c200, %c300] else %c5 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"Index\" },\n      { \"name\": \"default_value\", \"type\": \"Util_Primitive\" },\n      { \"name\": \"values\", \"type\": \"Variadic<Util_Primitive>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Util_Primitive\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['default_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"type($default_value) `from`\\n    custom<TypedValueList>(ref(type($default_value)), $values, type($values))\\n    `at` $index\\n    `else` $default_value\\n    attr-dict\\n    `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.unfoldable_constant\",\n    \"summary\": \"A constant that cannot be folded by the compiler.\",\n    \"description\": \"Similar to a std.constant, but is declared as having a side effect and has\\n    no folder. This is really just syntactic sugar as it is canonicalized to a\\n    std.constant wrapped in an util.optimization_barrier.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"AnyAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"util.unreachable\",\n    \"summary\": \"Unreachable assertion op.\",\n    \"description\": \"Signals to the compiler that the parent block should not be reachable.\\n    This may be converted into a runtime assertion, though ideally they are\\n    stripped during translation.\\n\\n    ```mlir\\n    ^bb0:\\n      %true = arith.constant true\\n      cond_br %true, ^bb2, ^bb1\\n    ^bb1:\\n      // Indicates that this branch should never be taken.\\n      util.unreachable \\\"shouldn't be here\\\"\\n    ^bb2:\\n      ...\\n\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($message^)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vector.bitcast\",\n    \"summary\": \"bitcast casts between vectors\",\n    \"description\": \"The bitcast operation casts between vectors of the same rank, the minor 1-D\\n    vector size is casted to a vector with a different element type but same\\n    bitwidth. In case of 0-D vectors, the bitwidth of element types must be\\n    equal.\\n\\n    Example:\\n\\n    ```mlir\\n    // Example casting to a smaller element type.\\n    %1 = vector.bitcast %0 : vector<5x1x4x3xf32> to vector<5x1x4x6xi16>\\n\\n    // Example casting to a bigger element type.\\n    %3 = vector.bitcast %2 : vector<10x12x8xi8> to vector<10x12x2xi32>\\n\\n    // Example casting to an element type of the same size.\\n    %5 = vector.bitcast %4 : vector<5x1x4x3xf32> to vector<5x1x4x3xi32>\\n\\n    // Example casting of 0-D vectors.\\n    %7 = vector.bitcast %6 : vector<f32> to vector<i32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfNonI0Elem\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonI0Elem\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"vector.broadcast\",\n    \"summary\": \"broadcast operation\",\n    \"description\": \"Broadcasts the scalar or k-D vector value in the source operand\\n    to a n-D result vector such that the broadcast makes sense, i.e.,\\n    the source operand is duplicated to match the given rank and sizes\\n    in the result vector. The legality rules are:\\n    * the source operand must have the same element type as the result type\\n    * a k-D vector <s_1 x .. x s_k x type> can be broadcast to\\n      a n-D vector <t_1 x .. x t_n x type> if\\n       * k <= n, and\\n       * the sizes in the trailing dimensions n-k < i <= n with j=i+k-n\\n          match exactly as s_j = t_i or s_j = 1:\\n       ```\\n           t_1 x   ..  t_n-k x t_n-k+1 x .. x t_i x .. x t_n\\n                               s_1     x .. x s_j x .. x s_k\\n               <duplication>         <potential stretch>\\n       ```\\n       * in addition, any scalable unit dimension, `[1]`, must match exactly.\\n\\n    The source operand is duplicated over all the missing leading dimensions\\n    and stretched over the trailing dimensions where the source has a non-equal\\n    dimension of 1 (stretching a trailing dimension is also referred to as\\n    \\\"dim-1\\\" broadcasting). These rules imply that any scalar broadcast (k=0) to\\n    any shaped vector with the same element type is always legal.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = arith.constant 0.0 : f32\\n    %1 = vector.broadcast %0 : f32 to vector<16xf32>\\n    %2 = vector.broadcast %1 : vector<16xf32> to vector<4x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($vector)\"\n  },\n  {\n    \"name\": \"vector.compressstore\",\n    \"summary\": \"writes elements selectively from a vector as defined by a mask\",\n    \"description\": \"The compress store operation writes elements from a vector into memory as\\n    defined by a base with indices and a mask vector. Compression only applies\\n    to the innermost dimension. When the mask is set, the corresponding element\\n    from the vector is written next to memory.  Otherwise, no action is taken\\n    for the element. Informally the semantics are:\\n\\n    ```\\n    index = i\\n    if (mask[0]) base[index++] = value[0]\\n    if (mask[1]) base[index++] = value[1]\\n    etc.\\n    ```\\n\\n    Note that the index increment is done conditionally.\\n\\n    If a mask bit is set and the corresponding index is out-of-bounds for the\\n    given base, the behavior is undefined. If a mask bit is not set, no value\\n    is stored regardless of the index, and the index is allowed to be\\n    out-of-bounds.\\n\\n    The compress store can be used directly where applicable, or can be used\\n    during progressively lowering to bring other memory operations closer to\\n    hardware ISA support for a compress. The semantics of the operation closely\\n    correspond to those of the `llvm.masked.compressstore`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#llvm-masked-compressstore-intrinsics).\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    store operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\\n\\n    Note, at the moment this Op is only available for fixed-width vectors.\\n\\n    Examples:\\n\\n    ```mlir\\n    vector.compressstore %base[%i], %mask, %value\\n      : memref<?xf32>, vector<8xi1>, vector<8xf32>\\n\\n    vector.compressstore %base[%i, %j], %mask, %value\\n      : memref<?x?xf32>, vector<16xi1>, vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mask\", \"type\": \"FixedVectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"valueToStore\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $mask `,` $valueToStore attr-dict `:` type($base) `,` type($mask) `,` type($valueToStore)\"\n  },\n  {\n    \"name\": \"vector.constant_mask\",\n    \"summary\": \"creates a constant vector mask\",\n    \"description\": \"Creates and returns a vector mask where elements of the result vector\\n    are set to '0' or '1', based on whether the element indices are contained\\n    within a hyper-rectangular region specified by the 'mask_dim_sizes'\\n    array attribute argument. Each element of the 'mask_dim_sizes' array,\\n    specifies an exclusive upper bound [0, mask-dim-size-element-value)\\n    for a unique dimension in the vector result. The conjunction of the ranges\\n    define a hyper-rectangular region within which elements values are set to 1\\n    (otherwise element values are set to 0). Each value of 'mask_dim_sizes' must\\n    be non-negative and not greater than the size of the corresponding vector\\n    dimension (as opposed to vector.create_mask which allows this). Sizes that\\n    correspond to scalable dimensions are implicitly multiplied by vscale,\\n    though currently only zero (none set) or the size of the dim/vscale\\n    (all set) are supported.\\n\\n    Example:\\n\\n    ```mlir\\n    // create a constant vector mask of size 4x3xi1 with elements in range\\n    // 0 <= row <= 2 and 0 <= col <= 1 are set to 1 (others to 0).\\n    %1 = vector.constant_mask [3, 2] : vector<4x3xi1>\\n\\n    print %1\\n                  columns\\n                0    1    2\\n              |------------\\n            0 | 1    1    0\\n      rows  1 | 1    1    0\\n            2 | 1    1    0\\n            3 | 0    0    0\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfAnyRankOf<[I1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mask_dim_sizes\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$mask_dim_sizes attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"vector.contract\",\n    \"summary\": \"vector contraction operation\",\n    \"description\": \"Computes the sum of products of vector elements along contracting\\n    dimension pairs from 2 vectors of rank M and N respectively, adds this\\n    intermediate result to the accumulator argument of rank K, and returns a\\n    vector result of rank K (where K = num_lhs_free_dims + num_rhs_free_dims +\\n    num_batch_dims (see dimension type descriptions below)). For K = 0 (no\\n    free or batch dimensions), the accumulator and output are a scalar.\\n\\n    If operands and the result have types of different bitwidths, operands are\\n    promoted to have the same bitwidth as the result before performing the\\n    contraction. For integer types, only signless integer types are supported,\\n    and the promotion happens via sign extension.\\n\\n    An iterator type attribute list must be specified, where each element of\\n    the list represents an iterator with one of the following types:\\n\\n    *   \\\"reduction\\\": reduction dimensions are present in the lhs and rhs\\n        arguments but not in the output (and accumulator\\n        argument). These are the dimensions along which the vector\\n        contraction op computes the sum of products, and\\n        contracting dimension pair dimension sizes must match\\n        between lhs/rhs.\\n\\n    *   \\\"parallel\\\": Batch dimensions are iterator type \\\"parallel\\\", and\\n        are non-contracting dimensions present in the lhs, rhs and\\n        output. The lhs/rhs co-iterate along the batch dimensions,\\n        which should be expressed in their indexing maps.\\n\\n        Free dimensions are iterator type \\\"parallel\\\", and are\\n        non-contraction, non-batch dimensions accessed by either the\\n        lhs or rhs (but not both). The lhs and rhs free dimensions\\n        are unrelated to each other and do not co-iterate, which\\n        should be expressed in their indexing maps.\\n\\n    An indexing map attribute list must be specified with an entry for lhs, rhs\\n    and acc arguments. An indexing map attribute specifies a mapping from each\\n    iterator in the iterator type list, to each dimension of an N-D vector.\\n\\n    An optional kind attribute may be used to specify the combining function\\n    between the intermediate result and accumulator argument of rank K. This\\n    attribute can take the values `add`/`mul`/`minsi`/`minui`/`maxsi`/`maxui`\\n    /`and`/`or`/`xor` for integers, and `add`/`mul`/`minnumf`/`maxnumf`\\n    /`minimumf`/`maximumf` for floats. The default is `add`.\\n\\n    Example:\\n\\n    ```mlir\\n    // Simple DOT product (K = 0).\\n    #contraction_accesses = [\\n     affine_map<(i) -> (i)>,\\n     affine_map<(i) -> (i)>,\\n     affine_map<(i) -> ()>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [\\\"reduction\\\"]\\n    }\\n    %3 = vector.contract #contraction_trait %0, %1, %2\\n      : vector<10xf32>, vector<10xf32> into f32\\n\\n    // 2D vector contraction with one contracting dimension (matmul, K = 2).\\n    #contraction_accesses = [\\n      affine_map<(i, j, k) -> (i, k)>,\\n      affine_map<(i, j, k) -> (k, j)>,\\n      affine_map<(i, j, k) -> (i, j)>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"reduction\\\"]\\n    }\\n\\n    %3 = vector.contract #contraction_trait %0, %1, %2\\n      : vector<4x3xf32>, vector<3x7xf32> into vector<4x7xf32>\\n\\n    // 4D to 3D vector contraction with two contracting dimensions and\\n    // one batch dimension (K = 3).\\n    #contraction_accesses = [\\n      affine_map<(b0, f0, f1, c0, c1) -> (c0, b0, c1, f0)>,\\n      affine_map<(b0, f0, f1, c0, c1) -> (b0, c1, c0, f1)>,\\n      affine_map<(b0, f0, f1, c0, c1) -> (b0, f0, f1)>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [\\\"parallel\\\", \\\"parallel\\\", \\\"parallel\\\",\\n                        \\\"reduction\\\", \\\"reduction\\\"]\\n    }\\n\\n    %4 = vector.contract #contraction_trait %0, %1, %2\\n        : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x15x5xf32>\\n\\n    // Vector contraction with mixed typed. lhs/rhs have different element\\n    // types than accumulator/result.\\n    %5 = vector.contract #contraction_trait %0, %1, %2\\n      : vector<10xf16>, vector<10xf16> into f32\\n\\n    // Contract with max (K = 0).\\n    #contraction_accesses = [\\n     affine_map<(i) -> (i)>,\\n     affine_map<(i) -> (i)>,\\n     affine_map<(i) -> ()>\\n    ]\\n    #contraction_trait = {\\n      indexing_maps = #contraction_accesses,\\n      iterator_types = [\\\"reduction\\\"],\\n      kind = #vector.kind<maxnumf>\\n    }\\n    %6 = vector.contract #contraction_trait %0, %1, %2\\n      : vector<10xf32>, vector<10xf32> into f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" },\n      { \"name\": \"acc\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_maps\", \"type\": \"ArrayAttr\" },\n      { \"name\": \"iterator_types\", \"type\": \"TypedArrayAttrBase<Vector_IteratorTypeEnum{parallel|reduction}>\" },\n      { \"name\": \"kind\", \"type\": \"DefaultValuedAttr<Vector_CombiningKindAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|maximumf|minimumf}, CombiningKind::ADD>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vector.create_mask\",\n    \"summary\": \"creates a vector mask\",\n    \"description\": \"Creates and returns a vector mask where elements of the result vector\\n    are set to '0' or '1', based on whether the element indices are contained\\n    within a hyper-rectangular region specified by the operands. Specifically,\\n    each operand specifies a range [0, operand-value) for a unique dimension in\\n    the vector result. The conjunction of the operand ranges define a\\n    hyper-rectangular region within which elements values are set to 1\\n    (otherwise element values are set to 0). If operand-value is negative, it is\\n    treated as if it were zero, and if it is greater than the corresponding\\n    dimension size, it is treated as if it were equal to the dimension size.\\n\\n    Example:\\n\\n    ```mlir\\n    // create a vector mask of size 4x3xi1 where elements in range\\n    // 0 <= row <= 2 and 0 <= col <= 1 are set to 1 (others to 0).\\n    %1 = vector.create_mask %c3, %c2 : vector<4x3xi1>\\n\\n    print %1\\n                  columns\\n                0    1    2\\n              |------------\\n            0 | 1    1    0\\n      rows  1 | 1    1    0\\n            2 | 1    1    0\\n            3 | 0    0    0\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfAnyRankOf<[I1]>\" }\n    ],\n    \"assemblyFormat\": \"$operands attr-dict `:` type(results)\"\n  },\n  {\n    \"name\": \"vector.deinterleave\",\n    \"summary\": \"constructs two vectors by deinterleaving an input vector\",\n    \"description\": \"The deinterleave operation constructs two vectors from a single input\\n        vector. The first result vector contains the elements from even indexes\\n        of the input, and the second contains elements from odd indexes. This is\\n        the inverse of a `vector.interleave` operation.\\n\\n        Each output's trailing dimension is half of the size of the input\\n        vector's trailing dimension. This operation requires the input vector\\n        to have a rank > 0 and an even number of elements in its trailing\\n        dimension.\\n\\n        The operation supports scalable vectors.\\n\\n        Example:\\n        ```mlir\\n        %0, %1 = vector.deinterleave %a\\n                   : vector<8xi8> -> vector<4xi8>\\n        %2, %3 = vector.deinterleave %b\\n                   : vector<2x8xi8> -> vector<2x4xi8>\\n        %4, %5 = vector.deinterleave %c\\n                   : vector<2x8x4xi8> -> vector<2x8x2xi8>\\n        %6, %7 = vector.deinterleave %d\\n                   : vector<[8]xf32> -> vector<[4]xf32>\\n        %8, %9 = vector.deinterleave %e\\n                   : vector<2x[6]xf64> -> vector<2x[3]xf64>\\n        %10, %11 = vector.deinterleave %f\\n                   : vector<2x4x[6]xf64> -> vector<2x4x[3]xf64>\\n        ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"res1\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"res2\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'source', 'res1', '[&]() -> ::mlir::VectorType {\\n      auto vectorType = ::llvm::cast<mlir::VectorType>($_self);\\n      ::mlir::VectorType::Builder builder(vectorType);\\n      auto lastDim = vectorType.getRank() - 1;\\n      auto newDimSize = vectorType.getDimSize(lastDim) / 2;;\\n      if (newDimSize <= 0)\\n         return vectorType; // (invalid input type)\\n      return builder.setDim(lastDim, newDimSize);\\n    }()'>\" },\n      { \"type\": \"AllTypesMatch<['res1', 'res2']>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `->` type($res1)\"\n  },\n  {\n    \"name\": \"vector.expandload\",\n    \"summary\": \"reads elements from memory and spreads them into a vector as defined by a mask\",\n    \"description\": \"The expand load reads elements from memory into a vector as defined by a\\n    base with indices and a mask vector. Expansion only applies to the innermost\\n    dimension. When the mask is set, the next element is read from memory.\\n    Otherwise, the corresponding element is taken from a pass-through vector.\\n    Informally the semantics are:\\n\\n    ```\\n    index = i\\n    result[0] := if mask[0] then base[index++] else pass_thru[0]\\n    result[1] := if mask[1] then base[index++] else pass_thru[1]\\n    etc.\\n    ```\\n\\n    Note that the index increment is done conditionally.\\n\\n    If a mask bit is set and the corresponding index is out-of-bounds for the\\n    given base, the behavior is undefined. If a mask bit is not set, the value\\n    comes from the pass-through vector regardless of the index, and the index is\\n    allowed to be out-of-bounds.\\n\\n    The expand load can be used directly where applicable, or can be used\\n    during progressively lowering to bring other memory operations closer to\\n    hardware ISA support for an expand. The semantics of the operation closely\\n    correspond to those of the `llvm.masked.expandload`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#llvm-masked-expandload-intrinsics).\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    load operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\\n\\n    Note, at the moment this Op is only available for fixed-width vectors.\\n\\n    Examples:\\n\\n    ```mlir\\n    %0 = vector.expandload %base[%i], %mask, %pass_thru\\n       : memref<?xf32>, vector<8xi1>, vector<8xf32> into vector<8xf32>\\n\\n    %1 = vector.expandload %base[%i, %j], %mask, %pass_thru\\n       : memref<?x?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mask\", \"type\": \"FixedVectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"pass_thru\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $mask `,` $pass_thru attr-dict `:` type($base) `,` type($mask) `,` type($pass_thru) `into` type($result)\"\n  },\n  {\n    \"name\": \"vector.extract\",\n    \"summary\": \"extract operation\",\n    \"description\": \"Extracts an (n − k)-D result sub-vector from an n-D source vector at a\\n    specified k-D position. When n = k, the result degenerates to a scalar\\n    element.\\n\\n    Static and dynamic indices must be greater or equal to zero and less than\\n    the size of the corresponding dimension. The result is undefined if any\\n    index is out-of-bounds. The value `-1` represents a poison index, which\\n    specifies that the extracted element is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = vector.extract %0[3]: vector<8x16xf32> from vector<4x8x16xf32>\\n    %2 = vector.extract %0[2, 1, 3]: f32 from vector<4x8x16xf32>\\n    %4 = vector.extract %0[%a, %b, %c]: f32 from vector<4x8x16xf32>\\n    %5 = vector.extract %0[2, %b]: vector<16xf32> from vector<4x8x16xf32>\\n    %6 = vector.extract %10[-1, %c]: f32 from vector<4x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"dynamic_position\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_position\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<DynamicIndexList>($dynamic_position, $static_position)\\n    attr-dict `:` type($result) `from` type($source)\"\n  },\n  {\n    \"name\": \"vector.extract_strided_slice\",\n    \"summary\": \"extract_strided_slice operation\",\n    \"description\": \"Takes an n-D vector, k-D `offsets` integer array attribute, a k-sized\\n    `sizes` integer array attribute, a k-sized `strides` integer array\\n    attribute and extracts the n-D subvector at the proper offset.\\n\\n    At the moment strides must contain only 1s.\\n\\n    Returns an n-D vector where the first k-D dimensions match the `sizes`\\n    attribute. The returned subvector contains the elements starting at offset\\n    `offsets` and ending at `offsets + sizes`.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = vector.extract_strided_slice %0\\n        {offsets = [0, 2], sizes = [2, 4], strides = [1, 1]}:\\n      vector<4x8x16xf32> to vector<2x4x16xf32>\\n\\n    // TODO: Evolve to a range form syntax similar to:\\n    %1 = vector.extract_strided_slice %0[0:2:1][2:4:1]\\n      vector<4x8x16xf32> to vector<2x4x16xf32>\\n    ```\\n\\n    TODO: Implement support for poison indices.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"sizes\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type(results)\"\n  },\n  {\n    \"name\": \"vector.fma\",\n    \"summary\": \"vector fused multiply-add\",\n    \"description\": \"Multiply-add expressions operate on n-D vectors and compute a fused\\n    pointwise multiply-and-accumulate: `$result = $lhs * $rhs + $acc`.\\n    All operands and result have the same vector type. The semantics\\n    of the operation correspond to those of the `llvm.fma`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#int-fma). In the\\n    particular case of lowering to LLVM, this is guaranteed to lower\\n    to the `llvm.fma.*` intrinsic.\\n\\n    Example:\\n\\n    ```mlir\\n    %3 = vector.fma %0, %1, %2: vector<8x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VectorOfAnyRankOf<[AnyFloat]>\" },\n      { \"name\": \"rhs\", \"type\": \"VectorOfAnyRankOf<[AnyFloat]>\" },\n      { \"name\": \"acc\", \"type\": \"VectorOfAnyRankOf<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfAnyRankOf<[AnyFloat]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'acc', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `,` $acc attr-dict `:` type($lhs)\"\n  },\n  {\n    \"name\": \"vector.from_elements\",\n    \"summary\": \"operation that defines a vector from scalar elements\",\n    \"description\": \"This operation defines a vector from one or multiple scalar elements. The\\n    scalar elements are arranged in row-major within the vector. The number of\\n    elements must match the number of elements in the result type. All elements\\n    must have the same type, which must match the element type of the result\\n    vector type. Scalable vectors are not supported.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Define a 0-D vector.\\n    %0 = vector.from_elements %f1 : vector<f32>\\n    // [%f1]\\n\\n    // Define a 1-D vector.\\n    %1 = vector.from_elements %f1, %f2 : vector<2xf32>\\n    // [%f1, %f2]\\n\\n    // Define a 2-D vector.\\n    %2 = vector.from_elements %f1, %f2, %f3, %f4, %f5, %f6 : vector<2x3xf32>\\n    // [[%f1, %f2, %f3], [%f4, %f5, %f6]]\\n\\n    // Define a 3-D vector.\\n    %3 = vector.from_elements %f1, %f2, %f3, %f4, %f5, %f6 : vector<3x1x2xf32>\\n    // [[[%f1, %f2]], [[%f3, %f4]], [[%f5, %f6]]]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyFixedVectorOfAnyRank\" }\n    ],\n    \"assemblyFormat\": \"$elements attr-dict `:` type($dest)\"\n  },\n  {\n    \"name\": \"vector.gather\",\n    \"category\": \"Tensor\",\n    \"summary\": \"Gathers elements from memory or ranked tensor into a vector as defined by an\\n    index vector and a mask vector.\",\n    \"description\": \"The gather operation returns an n-D vector whose elements are either loaded\\n    from a k-D memref or tensor, or taken from an n-D pass-through vector, depending\\n    on the values of an n-D mask vector.\\n\\n    If a mask bit is set, the corresponding result element is taken from `base`\\n    at an index defined by k indices and n-D `index_vec`. Otherwise, the element\\n    is taken from the pass-through vector. As an example, suppose that `base` is\\n    3-D and the result is 2-D:\\n\\n    ```mlir\\n    func.func @gather_3D_to_2D(\\n        %base: memref<?x10x?xf32>, %ofs_0: index, %ofs_1: index, %ofs_2: index,\\n        %indices: vector<2x3xi32>, %mask: vector<2x3xi1>,\\n        %fall_thru: vector<2x3xf32>) -> vector<2x3xf32> {\\n            %result = vector.gather %base[%ofs_0, %ofs_1, %ofs_2]\\n                                   [%indices], %mask, %fall_thru : [...]\\n            return %result : vector<2x3xf32>\\n    }\\n    ```\\n\\n    The indexing semantics are then,\\n\\n    ```\\n    result[i,j] := if mask[i,j] then base[i0, i1, i2 + indices[i,j]]\\n                   else pass_thru[i,j]\\n    ```\\n    The index into `base` only varies in the innermost ((k-1)-th) dimension.\\n\\n    If a mask bit is set and the corresponding index is out-of-bounds for the\\n    given base, the behavior is undefined. If a mask bit is not set, the value\\n    comes from the pass-through vector regardless of the index, and the index is\\n    allowed to be out-of-bounds.\\n\\n    The gather operation can be used directly where applicable, or can be used\\n    during progressively lowering to bring other memory operations closer to\\n    hardware ISA support for a gather.\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    gather operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\\n\\n    Examples:\\n\\n    ```mlir\\n    // 1-D memref gathered to 2-D vector.\\n    %0 = vector.gather %base[%c0][%v], %mask, %pass_thru\\n       : memref<?xf32>, vector<2x16xi32>, vector<2x16xi1>, vector<2x16xf32> into vector<2x16xf32>\\n\\n    // 2-D memref gathered to 1-D vector.\\n    %1 = vector.gather %base[%i, %j][%v], %mask, %pass_thru\\n       : memref<16x16xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"TensorOrMemRef<[ AnyType ]>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"indices\", \"type\": \"VectorOfNonZeroRankOf<[AnyInteger, Index]>\" },\n      { \"name\": \"mask\", \"type\": \"VectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"pass_thru\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $offsets `]` `[` $indices `]` `,` $mask `,` $pass_thru attr-dict `:` type($base) `,` type($indices)  `,` type($mask) `,` type($pass_thru) `into` type($result)\"\n  },\n  {\n    \"name\": \"vector.insert\",\n    \"summary\": \"insert operation\",\n    \"description\": \"Inserts an (n - k)-D sub-vector (value-to-store) into an n-D destination\\n    vector at a specified k-D position. When n = 0, value-to-store degenerates\\n    to a scalar element inserted into the n-D destination vector.\\n\\n    Static and dynamic indices must be greater or equal to zero and less than\\n    the size of the corresponding dimension. The result is undefined if any\\n    index is out-of-bounds. The value `-1` represents a poison index, which\\n    specifies that the resulting vector is poison.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = vector.insert %0, %1[3] : vector<8x16xf32> into vector<4x8x16xf32>\\n    %5 = vector.insert %3, %4[2, 1, 3] : f32 into vector<4x8x16xf32>\\n    %11 = vector.insert %9, %10[%a, %b, %c] : f32 into vector<4x8x16xf32>\\n    %12 = vector.insert %4, %10[2, %b] : vector<16xf32> into vector<4x8x16xf32>\\n    %13 = vector.insert %20, %1[-1, %c] : f32 into vector<4x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueToStore\", \"type\": \"AnyType\" },\n      { \"name\": \"dest\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"dynamic_position\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"static_position\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dest', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$valueToStore `,` $dest custom<DynamicIndexList>($dynamic_position, $static_position)\\n    attr-dict `:` type($valueToStore) `into` type($dest)\"\n  },\n  {\n    \"name\": \"vector.insert_strided_slice\",\n    \"summary\": \"strided_slice operation\",\n    \"description\": \"Takes a k-D valueToStore vector, an n-D destination vector (n >= k), n-sized\\n    `offsets` integer array attribute, a k-sized `strides` integer array attribute\\n    and inserts the k-D valueToStore vector as a strided subvector at the proper offset\\n    into the n-D destination vector.\\n\\n    At the moment strides must contain only 1s.\\n\\n    Returns an n-D vector that is a copy of the n-D destination vector in which\\n    the last k-D dimensions contain the k-D valueToStore vector elements strided at\\n    the proper location as specified by the offsets.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = vector.insert_strided_slice %0, %1\\n        {offsets = [0, 0, 2], strides = [1, 1]}:\\n      vector<2x4xf32> into vector<16x4x8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueToStore\", \"type\": \"AnyVectorOfNonZeroRank\" },\n      { \"name\": \"dest\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strides\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dest', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$valueToStore `,` $dest attr-dict `:` type($valueToStore) `into` type($dest)\"\n  },\n  {\n    \"name\": \"vector.interleave\",\n    \"summary\": \"constructs a vector by interleaving two input vectors\",\n    \"description\": \"The interleave operation constructs a new vector by interleaving the\\n    elements from the trailing (or final) dimension of two input vectors,\\n    returning a new vector where the trailing dimension is twice the size.\\n\\n    Note that for the n-D case this differs from the interleaving possible with\\n    `vector.shuffle`, which would only operate on the leading dimension.\\n\\n    Another key difference is this operation supports scalable vectors, though\\n    currently a general LLVM lowering is limited to the case where only the\\n    trailing dimension is scalable.\\n\\n    Example:\\n    ```mlir\\n    %a = arith.constant dense<[0, 1]> : vector<2xi32>\\n    %b = arith.constant dense<[2, 3]> : vector<2xi32>\\n    // The value of `%0` is `[0, 2, 1, 3]`.\\n    %0 = vector.interleave %a, %b : vector<2xi32> -> vector<4xi32>\\n\\n    // Examples showing allowed input and result types.\\n    %1 = vector.interleave %c, %d : vector<f16> -> vector<2xf16>\\n    %2 = vector.interleave %e, %f : vector<6x3xf32> -> vector<6x6xf32>\\n    %3 = vector.interleave %g, %h : vector<[4]xi32> -> vector<[8]xi32>\\n    %4 = vector.interleave %i, %j : vector<2x4x[2]xf64> -> vector<2x4x[4]xf64>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"rhs\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs  attr-dict `:` type($lhs) `->` type($result)\"\n  },\n  {\n    \"name\": \"vector.load\",\n    \"summary\": \"reads an n-D slice of memory into an n-D vector\",\n    \"description\": \"The 'vector.load' operation reads an n-D slice of memory into an n-D\\n    vector. It takes a 'base' memref, an index for each memref dimension and a\\n    result vector type as arguments. It returns a value of the result vector\\n    type. The 'base' memref and indices determine the start memory address from\\n    which to read. Each index provides an offset for each memref dimension\\n    based on the element type of the memref. The shape of the result vector\\n    type determines the shape of the slice read from the start memory address.\\n    The elements along each dimension of the slice are strided by the memref\\n    strides. When loading more than 1 element, only unit strides are allowed\\n    along the most minor memref dimension. These constraints guarantee that\\n    elements read along the first dimension of the slice are contiguous in\\n    memory.\\n\\n    The memref element type can be a scalar or a vector type. If the memref\\n    element type is a scalar, it should match the element type of the result\\n    vector. If the memref element type is vector, it should match the result\\n    vector type.\\n\\n    Example: 0-D vector load on a scalar memref.\\n    ```mlir\\n    %result = vector.load %base[%i, %j] : memref<100x100xf32>, vector<f32>\\n    ```\\n\\n    Example: 1-D vector load on a scalar memref.\\n    ```mlir\\n    %result = vector.load %base[%i, %j] : memref<100x100xf32>, vector<8xf32>\\n    ```\\n\\n    Example: 1-D vector load on a vector memref.\\n    ```mlir\\n    %result = vector.load %memref[%i, %j] : memref<200x100xvector<8xf32>>, vector<8xf32>\\n    ```\\n\\n    Example:  2-D vector load on a scalar memref.\\n    ```mlir\\n    %result = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<4x8xf32>\\n    ```\\n\\n    Example:  2-D vector load on a vector memref.\\n    ```mlir\\n    %result = vector.load %memref[%i, %j] : memref<200x100xvector<4x8xf32>>, vector<4x8xf32>\\n    ```\\n\\n    Representation-wise, the 'vector.load' operation permits out-of-bounds\\n    reads. Support and implementation of out-of-bounds vector loads is\\n    target-specific. No assumptions should be made on the value of elements\\n    loaded out of bounds. Not all targets may support out-of-bounds vector\\n    loads.\\n\\n    Example:  Potential out-of-bound vector load.\\n    ```mlir\\n    %result = vector.load %memref[%index] : memref<?xf32>, vector<8xf32>\\n    ```\\n\\n    Example:  Explicit out-of-bound vector load.\\n    ```mlir\\n    %result = vector.load %memref[%c0] : memref<7xf32>, vector<8xf32>\\n    ```\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    load operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nontemporal\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` attr-dict `:` type($base) `,` type($result)\"\n  },\n  {\n    \"name\": \"vector.mask\",\n    \"summary\": \"Predicates a maskable vector operation\",\n    \"description\": \"The `vector.mask` is a `MaskingOpInterface` operation that predicates the\\n    execution of another operation. It takes an `i1` vector mask and an\\n    optional passthru vector as arguments.\\n\\n    A implicitly `vector.yield`-terminated region encloses the operation to be\\n    masked. Values used within the region are captured from above. Only one\\n    *maskable* operation can be masked with a `vector.mask` operation at a time.\\n    An operation is *maskable* if it implements the `MaskableOpInterface`. The\\n    terminator yields all results from the maskable operation to the result of\\n    this operation. No other values are allowed to be yielded.\\n\\n    An empty `vector.mask` operation is currently legal to enable optimizations\\n    across the `vector.mask` region. However, this might change in the future\\n    once vector transformations gain better support for `vector.mask`.\\n    TODO: Consider making empty `vector.mask` illegal.\\n\\n    The vector mask argument holds a bit for each vector lane and determines\\n    which vector lanes should execute the maskable operation and which ones\\n    should not. The `vector.mask` operation returns the value produced by the\\n    masked execution of the nested operation, if any. The masked-off lanes in\\n    the result vector are taken from the corresponding lanes of the pass-thru\\n    argument, if provided, or left unmodified, otherwise. At this point, 0-D\\n    vectors are not supported by `vector.mask`. They may be supported in the\\n    future.\\n\\n    The `vector.mask` operation does not prescribe how a maskable operation\\n    should be masked or how a masked operation should be lowered. Masking\\n    constraints and some semantic details are provided by each maskable\\n    operation through the `MaskableOpInterface`. Lowering of masked operations\\n    is implementation defined. For instance, scalarizing the masked operation\\n    or executing the operation for the masked-off lanes are valid lowerings as\\n    long as the execution of masked-off lanes does not change the observable\\n    behavior of the program.\\n\\n    Examples:\\n\\n    ```\\n      %0 = vector.mask %mask { vector.reduction <add>, %a : vector<8xi32> into i32 } : vector<8xi1> -> i32\\n    ```\\n\\n    ```\\n      %0 = vector.mask %mask, %passthru { arith.divsi %a, %b : vector<8xi32> } : vector<8xi1> -> vector<8xi32>\\n    ```\\n\\n    ```\\n      vector.mask %mask { vector.transfer_write %val, %t0[%idx] : vector<16xf32>, memref<?xf32> } : vector<16xi1>\\n    ```\\n\\n    ```\\n      vector.mask %mask { vector.transfer_write %val, %t0[%idx] : vector<16xf32>, tensor<?xf32> } : vector<16xi1> -> tensor<?xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"mask\", \"type\": \"VectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"passthru\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"maskRegion\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vector.maskedload\",\n    \"summary\": \"loads elements from memory into a vector as defined by a mask vector\",\n    \"description\": \"The masked load reads elements from memory into a vector as defined\\n    by a base with indices and a mask vector. When the mask is set, the\\n    element is read from memory. Otherwise, the corresponding element is taken\\n    from a pass-through vector. Informally the semantics are:\\n    ```\\n    result[0] := if mask[0] then base[i + 0] else pass_thru[0]\\n    result[1] := if mask[1] then base[i + 1] else pass_thru[1]\\n    etc.\\n    ```\\n\\n    If a mask bit is set and the corresponding index is out-of-bounds for the\\n    given base, the behavior is undefined. If a mask bit is not set, the value\\n    comes from the pass-through vector regardless of the index, and the index is\\n    allowed to be out-of-bounds.\\n\\n    The masked load can be used directly where applicable, or can be used\\n    during progressively lowering to bring other memory operations closer to\\n    hardware ISA support for a masked load. The semantics of the operation\\n    closely correspond to those of the `llvm.masked.load`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#llvm-masked-load-intrinsics).\\n\\n    Examples:\\n\\n    ```mlir\\n    %0 = vector.maskedload %base[%i], %mask, %pass_thru\\n       : memref<?xf32>, vector<8xi1>, vector<8xf32> into vector<8xf32>\\n\\n    %1 = vector.maskedload %base[%i, %j], %mask, %pass_thru\\n       : memref<?x?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>\\n    ```\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    load operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mask\", \"type\": \"VectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"pass_thru\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $mask `,` $pass_thru attr-dict `:` type($base) `,` type($mask) `,` type($pass_thru) `into` type($result)\"\n  },\n  {\n    \"name\": \"vector.maskedstore\",\n    \"summary\": \"stores elements from a vector into memory as defined by a mask vector\",\n    \"description\": \"The masked store operation writes elements from a vector into memory\\n    as defined by a base with indices and a mask vector. When the mask is\\n    set, the corresponding element from the vector is written to memory. Otherwise,\\n    no action is taken for the element. Informally the semantics are:\\n    ```\\n    if (mask[0]) base[i+0] = value[0]\\n    if (mask[1]) base[i+1] = value[1]\\n    etc.\\n    ```\\n\\n    If a mask bit is set and the corresponding index is out-of-bounds for the\\n    given base, the behavior is undefined. If a mask bit is not set, no value\\n    is stored regardless of the index, and the index is allowed to be\\n    out-of-bounds.\\n\\n    The masked store can be used directly where applicable, or can be used\\n    during progressively lowering to bring other memory operations closer to\\n    hardware ISA support for a masked store. The semantics of the operation\\n    closely correspond to those of the `llvm.masked.store`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#llvm-masked-store-intrinsics).\\n\\n    Examples:\\n\\n    ```mlir\\n    vector.maskedstore %base[%i], %mask, %value\\n      : memref<?xf32>, vector<8xi1>, vector<8xf32>\\n\\n    vector.maskedstore %base[%i, %j], %mask, %value\\n      : memref<?x?xf32>, vector<16xi1>, vector<16xf32>\\n    ```\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    store operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mask\", \"type\": \"VectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"valueToStore\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $mask `,` $valueToStore attr-dict `:` type($base) `,` type($mask) `,` type($valueToStore)\"\n  },\n  {\n    \"name\": \"vector.multi_reduction\",\n    \"summary\": \"Multi-dimensional reduction operation\",\n    \"description\": \"Reduces an n-D vector into an (n-k)-D vector (or a scalar when k == n)\\n    using the given operation: `add`/`mul`/`minsi`/`minui`/`maxsi`/`maxui`\\n    /`and`/`or`/`xor` for integers, and `add`/`mul`/`minnumf`/`maxnumf`/`minimumf`\\n    /`maximumf` for floats.\\n    Takes an initial accumulator operand.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = vector.multi_reduction <add>, %0, %acc0 [1, 3] :\\n      vector<4x8x16x32xf32> to vector<4x16xf32>\\n    %2 = vector.multi_reduction <add>, %1, %acc1 [0, 1] :\\n      vector<4x16xf32> to f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" },\n      { \"name\": \"acc\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Vector_CombiningKindAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|maximumf|minimumf}\" },\n      { \"name\": \"reduction_dims\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dest', 'acc']>\" }\n    ],\n    \"assemblyFormat\": \"$kind `,` $source `,` $acc attr-dict $reduction_dims `:` type($source) `to` type($dest)\"\n  },\n  {\n    \"name\": \"vector.outerproduct\",\n    \"summary\": \"vector outerproduct with optional fused add\",\n    \"description\": \"Takes 2 1-D vectors and returns the 2-D vector containing the outer-product,\\n    as illustrated below:\\n    ```\\n     outer |   [c, d]\\n     ------+------------\\n       [a, | [ [a*c, a*d],\\n        b] |   [b*c, b*d] ]\\n    ```\\n    This operation also accepts a 1-D vector lhs and a scalar rhs. In this\\n    case a simple AXPY operation is performed, which returns a 1-D vector.\\n    ```\\n        [a, b] * c = [a*c, b*c]\\n    ```\\n\\n    An optional extra vector argument with the same shape as the output\\n    vector may be specified in which case the operation returns the sum of\\n    the outer-product and the extra vector. In this multiply-accumulate\\n    scenario for floating-point arguments, the rounding mode is enforced\\n    by guaranteeing that a fused-multiply add operation is emitted. When\\n    lowered to the LLVMIR dialect, this form emits `llvm.intr.fma`, which\\n    is guaranteed to lower to actual `fma` instructions on x86.\\n\\n    An optional kind attribute may be specified to be: `add`/`mul`/`minsi`\\n    /`minui`/`maxsi`/`maxui`/`and`/`or`/`xor` for integers, and `add`/`mul`\\n    /`minnumf`/`maxnumf`/`minimumf`/`maximumf` for floats. The default is\\n    `add`.\\n\\n    Example:\\n\\n    ```\\n    %2 = vector.outerproduct %0, %1: vector<4xf32>, vector<8xf32>\\n    return %2: vector<4x8xf32>\\n\\n    %3 = vector.outerproduct %0, %1, %2:\\n      vector<4xf32>, vector<8xf32>, vector<4x8xf32>\\n    return %3: vector<4x8xf32>\\n\\n    %4 = vector.outerproduct %0, %1, %2 {kind = #vector.kind<maxnumf>}:\\n      vector<4xf32>, vector<8xf32>, vector<4x8xf32>\\n    return %3: vector<4x8xf32>\\n\\n    %6 = vector.outerproduct %4, %5: vector<10xf32>, f32\\n    return %6: vector<10xf32>\\n\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" },\n      { \"name\": \"rhs\", \"type\": \"AnyType\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyVectorOfNonZeroRankNonI0Elem>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"DefaultValuedAttr<Vector_CombiningKindAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|maximumf|minimumf}, CombiningKind::ADD>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vector.print\",\n    \"summary\": \"print operation (for testing and debugging)\",\n    \"description\": \"Prints the source vector (or scalar) to stdout in a human-readable format\\n    (for testing and debugging). No return value.\\n\\n    Example:\\n\\n    ```mlir\\n    %v = arith.constant dense<0.0> : vector<4xf32>\\n    vector.print %v : vector<4xf32>\\n    ```\\n\\n    When lowered to LLVM, the vector print is decomposed into elementary\\n    printing method calls that at runtime will yield:\\n\\n    ```\\n    ( 0.0, 0.0, 0.0, 0.0 )\\n    ```\\n\\n    This is printed to stdout via a small runtime support library, which only\\n    needs to provide a few printing methods (single value for all data\\n    types, opening/closing bracket, comma, newline).\\n\\n    By default `vector.print` adds a newline after the vector, but this can be\\n    controlled by the `punctuation` attribute. For example, to print a comma\\n    after instead do:\\n\\n    ```mlir\\n    vector.print %v : vector<4xf32> punctuation <comma>\\n    ```\\n\\n    Note that it is possible to use the punctuation attribute alone. The\\n    following will print a single newline:\\n\\n    ```mlir\\n    vector.print punctuation <newline>\\n    ```\\n\\n    Additionally, to aid with debugging and testing `vector.print` can also\\n    print constant strings:\\n\\n    ```mlir\\n    vector.print str \\\"Hello, World!\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"Optional<Type<Or < [ AnyVectorOfAnyRank.predicate , AnyInteger.predicate , Index.predicate , AnyFloat.predicate ] >>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"punctuation\", \"type\": \"DefaultValuedAttr<Vector_PrintPunctuation{no_punctuation|newline|comma|open|close}, ::mlir::vector::PrintPunctuation::NewLine>\" },\n      { \"name\": \"stringLiteral\", \"type\": \"OptionalAttr<Builtin_StringAttr>\" }\n    ],\n    \"assemblyFormat\": \"($source^ `:` type($source))?\\n        oilist(\\n            `str` $stringLiteral\\n          | `punctuation` $punctuation)\\n        attr-dict\"\n  },\n  {\n    \"name\": \"vector.reduction\",\n    \"summary\": \"reduction operation\",\n    \"description\": \"Reduces an 1-D vector \\\"horizontally\\\" into a scalar using the given\\n    operation: `add`/`mul`/`minsi`/`minui`/`maxsi`/`maxui`/`and`/`or`/`xor` for\\n    integers, and `add`/`mul`/`minnumf`/`maxnumf`/`minimumf`/`maximumf` for\\n    floats. Reductions also allow an optional fused accumulator.\\n\\n    Note that these operations are restricted to 1-D vectors to remain\\n    close to the corresponding LLVM intrinsics:\\n\\n    http://llvm.org/docs/LangRef.html#vector-reduction-intrinsics\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = vector.reduction <add>, %0 : vector<16xf32> into f32\\n\\n    %3 = vector.reduction <xor>, %2 : vector<4xi32> into i32\\n\\n    %4 = vector.reduction <mul>, %0, %1 : vector<16xf32> into f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfNonI0Elem\" },\n      { \"name\": \"acc\", \"type\": \"Optional<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Vector_CombiningKindAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|maximumf|minimumf}\" },\n      { \"name\": \"fastmath\", \"type\": \"DefaultValuedAttr<Arith_FastMathAttr{none|reassoc|nnan|ninf|nsz|arcp|contract|afn|fast}, ::mlir::arith::FastMathFlags::none>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'dest', 'acc', '::llvm::cast<Type>($_self)'>\" }\n    ],\n    \"assemblyFormat\": \"$kind `,` $vector (`,` $acc^)? (`fastmath` `` $fastmath^)? attr-dict `:` type($vector) `into` type($dest)\"\n  },\n  {\n    \"name\": \"vector.scalable.extract\",\n    \"summary\": \"extract subvector from scalable vector operation\",\n    \"description\": \"Takes rank-1 source vector and a position `pos` within the source\\n    vector, and extracts a subvector starting from that position.\\n\\n    The extraction position must be a multiple of the minimum size of the result\\n    vector. For the operation to be well defined, the destination vector must\\n    fit within the source vector from the specified position. Since the source\\n    vector is scalable and its runtime length is unknown, the validity of the\\n    operation can't be verified nor guaranteed at compile time.\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = vector.scalable.extract %0[8] : vector<4xf32> from vector<[8]xf32>\\n    %3 = vector.scalable.extract %2[0] : vector<[4]xf32> from vector<[8]xf32>\\n    ```\\n\\n    Invalid example:\\n    ```mlir\\n    %1 = vector.scalable.extract %0[5] : vector<4xf32> from vector<[16]xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"ScalableVectorOfRank<[1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfRank<[1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pos\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $pos `]` attr-dict `:` type($result) `from` type($source)\"\n  },\n  {\n    \"name\": \"vector.scalable.insert\",\n    \"summary\": \"insert subvector into scalable vector operation\",\n    \"description\": \"This operations takes a rank-1 fixed-length or scalable subvector and\\n    inserts it within the destination scalable vector starting from the\\n    position specificed by `pos`. If the source vector is scalable, the\\n    insertion position will be scaled by the runtime scaling factor of the\\n    source subvector.\\n\\n    The insertion position must be a multiple of the minimum size of the source\\n    vector. For the operation to be well defined, the source vector must fit in\\n    the destination vector from the specified position. Since the destination\\n    vector is scalable and its runtime length is unknown, the validity of the\\n    operation can't be verified nor guaranteed at compile time.\\n\\n    Example:\\n\\n    ```mlir\\n    %2 = vector.scalable.insert %0, %1[8] : vector<4xf32> into vector<[16]xf32>\\n    %5 = vector.scalable.insert %3, %4[0] : vector<8xf32> into vector<[4]xf32>\\n    %8 = vector.scalable.insert %6, %7[0] : vector<[4]xf32> into vector<[8]xf32>\\n    ```\\n\\n    Invalid example:\\n    ```mlir\\n    %2 = vector.scalable.insert %0, %1[5] : vector<4xf32> into vector<[16]xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueToStore\", \"type\": \"VectorOfRank<[1]>\" },\n      { \"name\": \"dest\", \"type\": \"ScalableVectorOfRank<[1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"ScalableVectorOfRank<[1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pos\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['dest', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$valueToStore `,` $dest `[` $pos `]` attr-dict `:` type($valueToStore) `into` type($dest)\"\n  },\n  {\n    \"name\": \"vector.scan\",\n    \"summary\": \"Scan operation\",\n    \"description\": \"Performs an inclusive/exclusive scan on an n-D vector along a single\\n    dimension returning an n-D result vector using the given\\n    operation (`add`/`mul`/`minsi`/`minui`/`maxsi`/`maxui`/`and`/`or`/`xor` for\\n    integers, and `add`/`mul`/`minnumf`/`maxnumf`/`minimumf`/`maximumf` for\\n    floats), and a specified value for the initial value. The operator returns\\n    the result of scan as well as the result of the last reduction in the scan.\\n\\n    Example:\\n\\n    ```mlir\\n    %1:2 = vector.scan <add>, %0, %acc {inclusive = false, reduction_dim = 1 : i64} :\\n      vector<4x8x16x32xf32>, vector<4x16x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" },\n      { \"name\": \"initial_value\", \"type\": \"AnyVectorOfNonI0Elem\" }\n    ],\n    \"results\": [\n      { \"name\": \"dest\", \"type\": \"AnyVectorOfNonZeroRankNonI0Elem\" },\n      { \"name\": \"accumulated_value\", \"type\": \"AnyVectorOfNonI0Elem\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"Vector_CombiningKindAttr{add|mul|minui|minsi|minnumf|maxui|maxsi|maxnumf|and|or|xor|maximumf|minimumf}\" },\n      { \"name\": \"reduction_dim\", \"type\": \"I64Attr\" },\n      { \"name\": \"inclusive\", \"type\": \"BoolAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'dest']>\" },\n      { \"type\": \"AllTypesMatch<['initial_value', 'accumulated_value']>\" }\n    ],\n    \"assemblyFormat\": \"$kind `,` $source `,` $initial_value attr-dict `:` type($source) `,` type($initial_value)\"\n  },\n  {\n    \"name\": \"vector.scatter\",\n    \"category\": \"Tensor\",\n    \"summary\": \"scatters elements from a vector into memory or ranked tensor as defined by an index vector\\n    and a mask vector\",\n    \"description\": \"The scatter operation stores elements from a n-D vector into memory or ranked tensor as\\n    defined by a base with indices and an additional n-D index vector, but\\n    only if the corresponding bit in a n-D mask vector is set. Otherwise, no\\n    action is taken for that element. Informally the semantics are:\\n    ```\\n    if (mask[0]) base[index[0]] = value[0]\\n    if (mask[1]) base[index[1]] = value[1]\\n    etc.\\n    ```\\n\\n    If a mask bit is set and the corresponding index is out-of-bounds for the\\n    given base, the behavior is undefined. If a mask bit is not set, no value\\n    is stored regardless of the index, and the index is allowed to be\\n    out-of-bounds.\\n\\n    If the index vector contains two or more duplicate indices, the behavior is\\n    undefined. Underlying implementation may enforce strict sequential\\n    semantics.\\n    TODO: always enforce strict sequential semantics?\\n\\n    The scatter operation can be used directly where applicable, or can be used\\n    during progressively lowering to bring other memory operations closer to\\n    hardware ISA support for a scatter. The semantics of the operation closely\\n    correspond to those of the `llvm.masked.scatter`\\n    [intrinsic](https://llvm.org/docs/LangRef.html#llvm-masked-scatter-intrinsics).\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    scatter operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\\n\\n    Examples:\\n\\n    ```mlir\\n    vector.scatter %base[%c0][%v], %mask, %value\\n        : memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32>\\n\\n    vector.scatter %base[%i, %j][%v], %mask, %value\\n        : memref<16x16xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"TensorOrMemRef<[ AnyType ]>\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"indices\", \"type\": \"VectorOfNonZeroRankOf<[AnyInteger, Index]>\" },\n      { \"name\": \"mask\", \"type\": \"VectorOfNonZeroRankOf<[I1]>\" },\n      { \"name\": \"valueToStore\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $offsets `]` `[` $indices `]` `,` $mask `,` $valueToStore attr-dict `:` type($base) `,` type($indices)  `,` type($mask) `,` type($valueToStore) (`->` type($result)^)?\"\n  },\n  {\n    \"name\": \"vector.shape_cast\",\n    \"summary\": \"shape_cast casts between vector shapes\",\n    \"description\": \"Casts to a vector with the same number of elements, element type, and\\n    number of scalable dimensions.\\n\\n    It is currently assumed that this operation does not require moving data,\\n    and that it will be folded away before lowering vector operations.\\n\\n    There is an exception to the folding expectation when targeting\\n    llvm.intr.matrix operations. We need a type conversion back and forth from a\\n    2-D MLIR vector to a 1-D flattened LLVM vector.shape_cast lowering to LLVM\\n    is supported in that particular case, for now.\\n\\n    Examples:\\n\\n    ```mlir\\n    %1 = vector.shape_cast %0 : vector<4x3xf32> to vector<3x2x2xf32>\\n\\n    // with 2 scalable dimensions (number of which must be preserved).\\n    %3 = vector.shape_cast %2 : vector<[2]x3x[4]xi8> to vector<3x[1]x[8]xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `to` type($result)\"\n  },\n  {\n    \"name\": \"vector.shuffle\",\n    \"summary\": \"shuffle operation\",\n    \"description\": \"The shuffle operation constructs a permutation (or duplication) of elements\\n    from two input vectors, returning a vector with the same element type as\\n    the input and a length that is the same as the shuffle mask. The two input\\n    vectors must have the same element type, same rank, and trailing dimension\\n    sizes and shuffles their values in the leading dimension (which may differ\\n    in size) according to the given mask. The legality rules are:\\n    * the two operands must have the same element type as the result\\n      - Either, the two operands and the result must have the same\\n        rank and trailing dimension sizes, viz. given two k-D operands\\n                v1 : <s_1 x s_2 x .. x s_k x type> and\\n                v2 : <t_1 x t_2 x .. x t_k x type>\\n        we have s_i = t_i for all 1 < i <= k\\n      - Or, the two operands must be 0-D vectors and the result is a 1-D vector.\\n    * the mask length equals the leading dimension size of the result\\n    * numbering the input vector indices left to right across the operands, all\\n      mask values must be within range, viz. given two k-D operands v1 and v2\\n      above, all mask values are in the range [0,s_1+t_1). The value `-1`\\n      represents a poison mask value, which specifies that the selected element\\n      is poison.\\n\\n    Note, scalable vectors are not supported.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = vector.shuffle %a, %b[0, 3]\\n               : vector<2xf32>, vector<2xf32>       ; yields vector<2xf32>\\n    %1 = vector.shuffle %c, %b[0, 1, 2]\\n               : vector<2x16xf32>, vector<1x16xf32> ; yields vector<3x16xf32>\\n    %2 = vector.shuffle %a, %b[3, 2, 1, 0]\\n               : vector<2xf32>, vector<2xf32>       ; yields vector<4xf32>\\n    %3 = vector.shuffle %a, %b[0, 1]\\n               : vector<f32>, vector<f32>           ; yields vector<2xf32>\\n    %4 = vector.shuffle %a, %b[0, 4, -1, -1, -1, -1]\\n               : vector<4xf32>, vector<4xf32>       ; yields vector<6xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"v1\", \"type\": \"AnyFixedVectorOfAnyRank\" },\n      { \"name\": \"v2\", \"type\": \"AnyFixedVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfNonZeroRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mask\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"operands $mask attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"vector.splat\",\n    \"hasCustomAssemblyFormat\": 1\n  },\n  {\n    \"name\": \"vector.step\",\n    \"summary\": \"A linear sequence of values from 0 to N\",\n    \"description\": \"A `step` operation produces an index vector, i.e. a 1-D vector of values of\\n    index type that represents a linear sequence from 0 to N-1, where N is the\\n    number of elements in the `result` vector.\\n\\n    Supports fixed-width and scalable vectors.\\n\\n    Examples:\\n\\n    ```mlir\\n    %0 = vector.step : vector<4xindex> ; [0, 1, 2, 3]\\n    %1 = vector.step : vector<[4]xindex> ; [0, 1, .., <vscale * 4 - 1>]\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VectorOfRankAndType<[1], [Index]>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"vector.store\",\n    \"summary\": \"writes an n-D vector to an n-D slice of memory\",\n    \"description\": \"The 'vector.store' operation writes an n-D vector to an n-D slice of memory.\\n    It takes the vector value to be stored, a 'base' memref and an index for\\n    each memref dimension. The 'base' memref and indices determine the start\\n    memory address from which to write. Each index provides an offset for each\\n    memref dimension based on the element type of the memref. The shape of the\\n    vector value to store determines the shape of the slice written from the\\n    start memory address. The elements along each dimension of the slice are\\n    strided by the memref strides. When storing more than 1 element, only unit\\n    strides are allowed along the most minor memref dimension. These constraints\\n    guarantee that elements written along the first dimension of the slice are\\n    contiguous in memory.\\n\\n    The memref element type can be a scalar or a vector type. If the memref\\n    element type is a scalar, it should match the element type of the value\\n    to store. If the memref element type is vector, it should match the type\\n    of the value to store.\\n\\n    Example: 0-D vector store on a scalar memref.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%i, %j] : memref<200x100xf32>, vector<f32>\\n    ```\\n\\n    Example: 1-D vector store on a scalar memref.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>\\n    ```\\n\\n    Example: 1-D vector store on a vector memref.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%i, %j] : memref<200x100xvector<8xf32>>, vector<8xf32>\\n    ```\\n\\n    Example:  2-D vector store on a scalar memref.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%i, %j] : memref<200x100xf32>, vector<4x8xf32>\\n    ```\\n\\n    Example:  2-D vector store on a vector memref.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%i, %j] : memref<200x100xvector<4x8xf32>>, vector<4x8xf32>\\n    ```\\n\\n    Representation-wise, the 'vector.store' operation permits out-of-bounds\\n    writes. Support and implementation of out-of-bounds vector stores are\\n    target-specific. No assumptions should be made on the memory written out of\\n    bounds. Not all targets may support out-of-bounds vector stores.\\n\\n    Example:  Potential out-of-bounds vector store.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%index] : memref<?xf32>, vector<8xf32>\\n    ```\\n\\n    Example:  Explicit out-of-bounds vector store.\\n    ```mlir\\n    vector.store %valueToStore, %memref[%c0] : memref<7xf32>, vector<8xf32>\\n    ```\\n\\n    An optional `alignment` attribute allows to specify the byte alignment of the\\n    store operation. It must be a positive power of 2. The operation must access\\n    memory at an address aligned to this boundary. Violating this requirement\\n    triggers immediate undefined behavior.\",\n    \"operands\": [\n      { \"name\": \"valueToStore\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"nontemporal\", \"type\": \"DefaultValuedOptionalAttr<BoolAttr, false>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<IntValidAlignment<I64Attr>>\" }\n    ],\n    \"assemblyFormat\": \"$valueToStore `,` $base `[` $indices `]` attr-dict `:` type($base) `,` type($valueToStore)\"\n  },\n  {\n    \"name\": \"vector.to_elements\",\n    \"summary\": \"operation that decomposes a vector into all its scalar elements\",\n    \"description\": \"This operation decomposes all the scalar elements from a vector. The\\n    decomposed scalar elements are returned in row-major order. The number of\\n    scalar results must match the number of elements in the input vector type.\\n    All the result elements have the same result type, which must match the\\n    element type of the input vector. Scalable vectors are not supported.\\n\\n    Examples:\\n\\n    ```mlir\\n    // Decompose a 0-D vector.\\n    %0 = vector.to_elements %v0 : vector<f32>\\n    // %0 = %v0[0]\\n\\n    // Decompose a 1-D vector.\\n    %0:2 = vector.to_elements %v1 : vector<2xf32>\\n    // %0#0 = %v1[0]\\n    // %0#1 = %v1[1]\\n\\n    // Decompose a 2-D.\\n    %0:6 = vector.to_elements %v2 : vector<2x3xf32>\\n    // %0#0 = %v2[0, 0]\\n    // %0#1 = %v2[0, 1]\\n    // %0#2 = %v2[0, 2]\\n    // %0#3 = %v2[1, 0]\\n    // %0#4 = %v2[1, 1]\\n    // %0#5 = %v2[1, 2]\\n\\n    // Decompose a 3-D vector.\\n    %0:6 = vector.to_elements %v3 : vector<3x1x2xf32>\\n    // %0#0 = %v3[0, 0, 0]\\n    // %0#1 = %v3[0, 0, 1]\\n    // %0#2 = %v3[1, 0, 0]\\n    // %0#3 = %v3[1, 0, 1]\\n    // %0#4 = %v3[2, 0, 0]\\n    // %0#5 = %v3[2, 0, 1]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"elements\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"InferTypeOpInterface\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source)\"\n  },\n  {\n    \"name\": \"vector.transfer_read\",\n    \"summary\": \"Reads a supervector from memory into an SSA vector value.\",\n    \"description\": \"The `vector.transfer_read` op performs a read from a slice within a\\n    [MemRef](../LangRef.md#memref-type) or a Ranked\\n    [Tensor](../LangRef.md#tensor-type) supplied as its first operand\\n    into a [vector](../LangRef.md#vector-type) of the same base elemental type.\\n\\n    A memref/tensor operand with vector element type, must have its vector\\n    element type match a suffix (shape and element type) of the vector (e.g.\\n    memref<3x2x6x4x3xf32>, vector<1x1x4x3xf32>).\\n\\n    The slice is further defined by a full-rank index within the MemRef/Tensor,\\n    supplied as the operands `[1 .. 1 + rank(memref/tensor))` that defines the\\n    starting point of the transfer (e.g. `%A[%i0, %i1, %i2]`).\\n\\n    The permutation_map [attribute](../LangRef.md#attributes) is an\\n    [affine-map](Affine.md#affine-maps) which specifies the transposition on the\\n    slice to match the vector shape. The permutation map may be implicit and\\n    omitted from parsing and printing if it is the canonical minor identity map\\n    (i.e. if it does not permute or broadcast any dimension).\\n\\n    The size of the slice is specified by the size of the vector, given as the\\n    return type.\\n\\n    An SSA value `padding` of the same elemental type as the MemRef/Tensor is\\n    provided to specify a fallback value in the case of out-of-bounds accesses\\n    and/or masking.\\n\\n    An optional SSA value `mask` may be specified to mask out elements read from\\n    the MemRef/Tensor. The `mask` type is an `i1` vector with a shape that\\n    matches how elements are read from the MemRef/Tensor, *before* any\\n    permutation or broadcasting. Elements whose corresponding mask element is\\n    `0` are masked out and replaced with `padding`.\\n\\n    For every vector dimension, the boolean array attribute `in_bounds`\\n    specifies if the transfer is guaranteed to be within the source bounds. If\\n    set to \\\"false\\\", accesses (including the starting point) may run\\n    out-of-bounds along the respective vector dimension as the index increases.\\n    Non-vector dimensions *must* always be in-bounds. The `in_bounds` array\\n    length has to be equal to the vector rank. This attribute has a default\\n    value: `false` (i.e. \\\"out-of-bounds\\\"). When skipped in the textual IR, the\\n    default value is assumed. Similarly, the OP printer will omit this\\n    attribute when all dimensions are out-of-bounds (i.e. the default value is\\n    used).\\n\\n    A `vector.transfer_read` can be lowered to a simple load if all dimensions\\n    are specified to be within bounds and no `mask` was specified.\\n\\n    This operation is called 'read' by opposition to 'load' because the\\n    super-vector granularity is generally not representable with a single\\n    hardware register. A `vector.transfer_read` is thus a mid-level abstraction\\n    that supports super-vectorization with non-effecting padding for full-tile\\n    only operations.\\n\\n    More precisely, let's dive deeper into the permutation_map for the following\\n    MLIR:\\n\\n    ```mlir\\n    vector.transfer_read %A[%expr1, %expr2, %expr3, %expr4]\\n      { permutation_map : (d0,d1,d2,d3) -> (d2,0,d0) } :\\n      memref<?x?x?x?xf32>, vector<3x4x5xf32>\\n    ```\\n\\n    This operation always reads a slice starting at `%A[%expr1, %expr2, %expr3,\\n    %expr4]`. The size of the slice can be inferred from the resulting vector\\n    shape and walking back through the permutation map: 3 along d2 and 5 along\\n    d0, so the slice is: `%A[%expr1 : %expr1 + 5, %expr2, %expr3:%expr3 + 3, %expr4]`\\n\\n    That slice needs to be read into a `vector<3x4x5xf32>`. Since the\\n    permutation map is not full rank, there must be a broadcast along vector\\n    dimension `1`.\\n\\n    A notional lowering of vector.transfer_read could generate code resembling:\\n\\n    ```mlir\\n    // %expr1, %expr2, %expr3, %expr4 defined before this point\\n    // alloc a temporary buffer for performing the \\\"gather\\\" of the slice.\\n    %tmp = memref.alloc() : memref<vector<3x4x5xf32>>\\n    for %i = 0 to 3 {\\n      affine.for %j = 0 to 4 {\\n        affine.for %k = 0 to 5 {\\n          // Note that this load does not involve %j.\\n          %a = load %A[%expr1 + %k, %expr2, %expr3 + %i, %expr4] : memref<?x?x?x?xf32>\\n          // Update the temporary gathered slice with the individual element\\n          %slice = memref.load %tmp : memref<vector<3x4x5xf32>> -> vector<3x4x5xf32>\\n          %updated = vector.insert %a, %slice[%i, %j, %k] : f32 into vector<3x4x5xf32>\\n          memref.store %updated, %tmp : memref<vector<3x4x5xf32>>\\n    }}}\\n    // At this point we gathered the elements from the original\\n    // memref into the desired vector layout, stored in the `%tmp` allocation.\\n    %vec = memref.load %tmp : memref<vector<3x4x5xf32>> -> vector<3x4x5xf32>\\n    ```\\n\\n    On a GPU one could then map `i`, `j`, `k` to blocks and threads. Notice that\\n    the temporary storage footprint could conceptually be only `3 * 5` values but\\n    `3 * 4 * 5` values are actually transferred between `%A` and `%tmp`.\\n\\n    Alternatively, if a notional vector broadcast operation were available, we\\n    could avoid the loop on `%j` and the lowered code would resemble:\\n\\n    ```mlir\\n    // %expr1, %expr2, %expr3, %expr4 defined before this point\\n    %tmp = memref.alloc() : memref<vector<3x4x5xf32>>\\n    for %i = 0 to 3 {\\n      affine.for %k = 0 to 5 {\\n        %a = load %A[%expr1 + %k, %expr2, %expr3 + %i, %expr4] : memref<?x?x?x?xf32>\\n        %slice = memref.load %tmp : memref<vector<3x4x5xf32>> -> vector<3x4x5xf32>\\n        // Here we only store to the first element in dimension one\\n        %updated = vector.insert %a, %slice[%i, 0, %k] : f32 into vector<3x4x5xf32>\\n        memref.store %updated, %tmp : memref<vector<3x4x5xf32>>\\n    }}\\n    // At this point we gathered the elements from the original\\n    // memref into the desired vector layout, stored in the `%tmp` allocation.\\n    // However we haven't replicated them alongside the first dimension, we need\\n    // to broadcast now.\\n    %partialVec = load %tmp : memref<vector<3x4x5xf32>> -> vector<3x4x5xf32>\\n    %vec = broadcast %tmpvec, 1 : vector<3x4x5xf32>\\n    ```\\n\\n    where `broadcast` broadcasts from element 0 to all others along the\\n    specified dimension. This time, the number of loaded element is `3 * 5`\\n    values.\\n    An additional `1` broadcast is required. On a GPU this broadcast could be\\n    implemented using a warp-shuffle if loop `j` were mapped to `threadIdx.x`.\\n\\n    Syntax\\n    ```\\n    operation ::= ssa-id `=` `vector.transfer_read` ssa-use-list\\n      `{` attribute-entry `} :` memref-type `,` vector-type\\n    ```\\n\\n    Example:\\n\\n    ```mlir\\n    // Read the slice `%A[%i0, %i1:%i1+256, %i2:%i2+32]` into vector<32x256xf32>\\n    // and pad with %f0 to handle the boundary case:\\n    %f0 = arith.constant 0.0f : f32\\n    affine.for %i0 = 0 to %0 {\\n      affine.for %i1 = 0 to %1 step 256 {\\n        affine.for %i2 = 0 to %2 step 32 {\\n          %v = vector.transfer_read %A[%i0, %i1, %i2], (%f0)\\n               {permutation_map: (d0, d1, d2) -> (d2, d1)} :\\n               memref<?x?x?xf32>, vector<32x256xf32>\\n    }}}\\n\\n    // or equivalently (rewrite with vector.transpose)\\n    %f0 = arith.constant 0.0f : f32\\n    affine.for %i0 = 0 to %0 {\\n      affine.for %i1 = 0 to %1 step 256 {\\n        affine.for %i2 = 0 to %2 step 32 {\\n          %v0 = vector.transfer_read %A[%i0, %i1, %i2], (%f0)\\n               {permutation_map: (d0, d1, d2) -> (d1, d2)} :\\n               memref<?x?x?xf32>, vector<256x32xf32>\\n          %v = vector.transpose %v0, [1, 0] :\\n              vector<256x32xf32> to vector<32x256f32>\\n    }}}\\n\\n    // Read the slice `%A[%i0, %i1]` (i.e. the element `%A[%i0, %i1]`) into\\n    // vector<128xf32>. The underlying implementation will require a 1-D vector\\n    // broadcast:\\n    affine.for %i0 = 0 to %0 {\\n      affine.for %i1 = 0 to %1 {\\n        %3 = vector.transfer_read %A[%i0, %i1]\\n             {permutation_map: (d0, d1) -> (0)} :\\n             memref<?x?xf32>, vector<128xf32>\\n      }\\n    }\\n\\n    // Read from a memref with vector element type.\\n    %4 = vector.transfer_read %arg1[%c3, %c3], %vf0\\n      {permutation_map = (d0, d1)->(d0, d1)}\\n        : memref<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>\\n\\n    // Read from a tensor with vector element type.\\n    %4 = vector.transfer_read %arg1[%c3, %c3], %vf0\\n      {permutation_map = (d0, d1)->(d0, d1)}\\n        : tensor<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>\\n\\n    // Special encoding for 0-d transfer with 0-d tensor/memref, vector shape\\n    // {1} and permutation_map () -> (0).\\n    %0 = vector.transfer_read %arg0[], %f0 {permutation_map = affine_map<()->(0)>} :\\n      tensor<f32>, vector<1xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyShaped\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"padding\", \"type\": \"AnyType\" },\n      { \"name\": \"mask\", \"type\": \"Optional<VectorOfNonZeroRankOf<[ I1 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation_map\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"in_bounds\", \"type\": \"TypedArrayAttrBase<BoolAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vector.transfer_write\",\n    \"summary\": \"The vector.transfer_write op writes a supervector to memory.\",\n    \"description\": \"The `vector.transfer_write` op performs a write from a\\n    [vector](../LangRef.md#vector-type), supplied as its first operand, into a\\n    slice within a [MemRef](../LangRef.md#memref-type) or a Ranked\\n    [Tensor](../LangRef.md#tensor-type) of the same base elemental type,\\n    supplied as its second operand.\\n\\n    A vector memref/tensor operand must have its vector element type match a\\n    suffix (shape and element type) of the vector (e.g. memref<3x2x6x4x3xf32>,\\n    vector<1x1x4x3xf32>). If the operand is a tensor, the operation returns a\\n    new tensor of the same type.\\n\\n    The slice is further defined by a full-rank index within the MemRef/Tensor,\\n    supplied as the operands `[2 .. 2 + rank(memref/tensor))` that defines the\\n    starting point of the transfer (e.g. `%A[%i0, %i1, %i2, %i3]`).\\n\\n    The permutation_map [attribute](../LangRef.md#attributes) is an\\n    [affine-map](Affine.md#affine-maps) which specifies the transposition on the\\n    slice to match the vector shape. The permutation map may be implicit and\\n    omitted from parsing and printing if it is the canonical minor identity map\\n    (i.e. if it does not permute any dimension). In contrast to `transfer_read`,\\n    write ops cannot have broadcast dimensions.\\n\\n    The size of the slice is specified by the size of the vector.\\n\\n    An optional SSA value `mask` may be specified to mask out elements written\\n    to the MemRef/Tensor. The `mask` type is an `i1` vector with a shape that\\n    matches how elements are written into the MemRef/Tensor, *after* applying\\n    any permutation. Elements whose corresponding mask element is `0` are\\n    masked out.\\n\\n    For every vector dimension, the boolean array attribute `in_bounds`\\n    specifies if the transfer is guaranteed to be within the source bounds. If\\n    set to \\\"false\\\", accesses (including the starting point) may run\\n    out-of-bounds along the respective vector dimension as the index increases.\\n    Non-vector dimensions *must* always be in-bounds. The `in_bounds` array\\n    length has to be equal to the vector rank. This attribute has a default\\n    value: `false` (i.e. \\\"out-of-bounds\\\"). When skipped in the textual IR, the\\n    default value is assumed. Similarly, the OP printer will omit this\\n    attribute when all dimensions are out-of-bounds (i.e. the default value is\\n    used).\\n\\n     A `vector.transfer_write` can be lowered to a simple store if all\\n     dimensions are specified to be within bounds and no `mask` was specified.\\n\\n    This operation is called 'write' by opposition to 'store' because the\\n    super-vector granularity is generally not representable with a single\\n    hardware register. A `vector.transfer_write` is thus a\\n    mid-level abstraction that supports super-vectorization with non-effecting\\n    padding for full-tile-only code. It is the responsibility of\\n    `vector.transfer_write`'s implementation to ensure the memory writes are\\n    valid. Different lowerings may be pertinent depending on the hardware\\n    support.\\n\\n    Example:\\n\\n    ```mlir\\n    // write vector<16x32x64xf32> into the slice\\n    //   `%A[%i0, %i1:%i1+32, %i2:%i2+64, %i3:%i3+16]`:\\n    for %i0 = 0 to %0 {\\n      affine.for %i1 = 0 to %1 step 32 {\\n        affine.for %i2 = 0 to %2 step 64 {\\n          affine.for %i3 = 0 to %3 step 16 {\\n            %val = `ssa-value` : vector<16x32x64xf32>\\n            vector.transfer_write %val, %A[%i0, %i1, %i2, %i3]\\n              {permutation_map: (d0, d1, d2, d3) -> (d3, d1, d2)} :\\n              vector<16x32x64xf32>, memref<?x?x?x?xf32>\\n    }}}}\\n\\n    // or equivalently (rewrite with vector.transpose)\\n    for %i0 = 0 to %0 {\\n      affine.for %i1 = 0 to %1 step 32 {\\n        affine.for %i2 = 0 to %2 step 64 {\\n          affine.for %i3 = 0 to %3 step 16 {\\n            %val = `ssa-value` : vector<16x32x64xf32>\\n            %valt = vector.transpose %val, [1, 2, 0] :\\n                  vector<16x32x64xf32> -> vector<32x64x16xf32>\\n            vector.transfer_write %valt, %A[%i0, %i1, %i2, %i3]\\n              {permutation_map: (d0, d1, d2, d3) -> (d1, d2, d3)} :\\n              vector<32x64x16xf32>, memref<?x?x?x?xf32>\\n    }}}}\\n\\n    // write to a memref with vector element type.\\n    vector.transfer_write %4, %arg1[%c3, %c3]\\n      {permutation_map = (d0, d1)->(d0, d1)}\\n        : vector<1x1x4x3xf32>, memref<?x?xvector<4x3xf32>>\\n\\n    // return a tensor where the vector is inserted into the source tensor.\\n    %5 = vector.transfer_write %4, %arg1[%c3, %c3]\\n      {permutation_map = (d0, d1)->(d0, d1)}\\n        : vector<1x1x4x3xf32>, tensor<?x?xvector<4x3xf32>>\\n\\n    // Special encoding for 0-d transfer with 0-d tensor/memref, vector shape\\n    // {1} and permutation_map () -> (0).\\n    %1 = vector.transfer_write %0, %arg0[] {permutation_map = affine_map<()->(0)>} :\\n      vector<1xf32>, tensor<f32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"valueToStore\", \"type\": \"AnyVectorOfAnyRank\" },\n      { \"name\": \"base\", \"type\": \"AnyShaped\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"mask\", \"type\": \"Optional<VectorOfNonZeroRankOf<[ I1 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Optional<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation_map\", \"type\": \"AffineMapAttr\" },\n      { \"name\": \"in_bounds\", \"type\": \"TypedArrayAttrBase<BoolAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vector.transpose\",\n    \"category\": \"Transform\",\n    \"summary\": \"vector transpose operation\",\n    \"description\": \"Takes a n-D vector and returns the transposed n-D vector defined by\\n    the permutation of ranks in the n-sized integer array attribute (in case\\n    of 0-D vectors the array attribute must be empty).\\n\\n    In the operation\\n\\n    ```mlir\\n    %1 = vector.transpose %0, [i_1, .., i_n]\\n      : vector<d_1 x .. x d_n x f32>\\n      to vector<d_trans[0] x .. x d_trans[n-1] x f32>\\n    ```\\n\\n    the `permutation` array [i_1, .., i_n] must be a permutation of [0, .., n-1].\\n\\n    Example:\\n\\n    ```mlir\\n    %1 = vector.transpose %0, [1, 0] : vector<2x3xf32> to vector<3x2xf32>\\n\\n     [ [a, b, c],       [ [a, d],\\n       [d, e, f] ]  ->    [b, e],\\n                          [c, f] ]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"vector\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyVectorOfAnyRank\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$vector `,` $permutation attr-dict `:` type($vector) `to` type($result)\"\n  },\n  {\n    \"name\": \"vector.type_cast\",\n    \"summary\": \"type_cast op converts a scalar memref to a vector memref\",\n    \"description\": \"Performs a conversion from a memref with scalar element to a memref with a\\n    *single* vector element, copying the shape of the memref to the vector. This\\n    is the minimal viable operation that is required to makeke\\n    super-vectorization operational. It can be seen as a special case of the\\n    `view` operation but scoped in the super-vectorization context.\\n\\n    Example:\\n\\n    ```mlir\\n    %A  = memref.alloc() : memref<5x4x3xf32>\\n    %VA = vector.type_cast %A : memref<5x4x3xf32> to memref<vector<5x4x3xf32>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"StaticShapeMemRefOf<[AnyType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyMemRef\" }\n    ],\n    \"assemblyFormat\": \"$memref attr-dict `:` type($memref) `to` type($result)\"\n  },\n  {\n    \"name\": \"vector.vscale\",\n    \"summary\": \"Load vector scale size\",\n    \"description\": \"The `vscale` op returns the scale of the scalable vectors, a positive\\n    integer value that is constant at runtime but unknown at compile-time.\\n    The scale of the vector indicates the multiplicity of the vectors and\\n    vector operations. For example, a `vector<[4]xi32>` is equivalent to\\n    `vscale` consecutive `vector<4xi32>`; and an operation on a\\n    `vector<[4]xi32>` is equivalent to performing that operation `vscale`\\n    times, once on each `<4xi32>` segment of the scalable vector. The `vscale`\\n    op can be used to calculate the step in vector-length agnostic (VLA) loops.\\n    Right now we only support one contiguous set of scalable dimensions, all of\\n    them grouped and scaled with the value returned by 'vscale'.\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"Index\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\"\n  },\n  {\n    \"name\": \"vector.yield\",\n    \"summary\": \"Terminates and yields values from vector regions.\",\n    \"description\": \"\\\"vector.yield\\\" yields an SSA value from the Vector dialect op region and\\n    terminates the regions. The semantics of how the values are yielded is\\n    defined by the parent operation.\\n    If \\\"vector.yield\\\" has any operands, the operands must correspond to the\\n    parent operation's results.\\n    If the parent operation defines no value the vector.yield may be omitted\\n    when printing the region.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"vhlo.abs_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.add_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.after_all_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.all_gather_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"all_gather_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.all_gather_v2\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"all_gather_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.all_reduce_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.all_reduce_v2\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.all_to_all_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"concat_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"split_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.all_to_all_v2\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"concat_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"split_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.and_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.atan2_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.batch_norm_grad_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"scale\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"mean\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"variance\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"grad_output\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"grad_operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"grad_scale\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"grad_offset\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"feature_index\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.batch_norm_inference_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"scale\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"offset\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"mean\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"variance\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"feature_index\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.batch_norm_training_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"scale\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"offset\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"batch_mean\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"batch_var\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"feature_index\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.bitcast_convert_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.broadcast_in_dim_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.broadcast_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_sizes\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.call_v1\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.case_v1\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"branches\", \"type\": \"VariadicRegion<VHLO_AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.cbrt_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.cbrt_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.ceil_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.cholesky_v1\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lower\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.clamp_v1\",\n    \"operands\": [\n      { \"name\": \"min\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"max\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.collective_broadcast_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.collective_permute_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"source_target_pairs\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.compare_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"comparison_direction\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"compare_type\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.complex_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.composite_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"composite_attributes\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"decomposition\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"version\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.composite_v2\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"composite_attributes\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"decomposition\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"version\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"composite_regions\", \"type\": \"VariadicRegion<VHLO_AnyRegion>\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.concatenate_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.constant_v1\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.convert_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.convolution_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"padding\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"window_reversal\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_batch_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_input_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_output_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_batch_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"feature_group_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"batch_group_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.cosine_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.cosine_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.count_leading_zeros_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.create_token_v1\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.cross-replica-sum_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.custom_call_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"call_target_name\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"has_side_effect\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"backend_config\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"api_version\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"called_computations\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"operand_layouts\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"result_layouts\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_operand_aliases\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.divide_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dot_general_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_batching_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_batching_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_contracting_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_contracting_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dot_general_v2\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"lhs_batching_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_batching_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_contracting_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_contracting_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_precision_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_precision_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"accumulation_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_component_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_component_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"num_primitive_operations\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"allow_imprecise_accumulation\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dot_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"precision_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_broadcast_in_dim_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"output_dimensions\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"broadcast_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"known_expanding_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"known_nonexpanding_dimensions\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_conv_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"d_padding\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"padding\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"window_reversal\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_batch_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_input_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_output_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_batch_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"feature_group_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"batch_group_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_conv_v2\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"padding\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_strides\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lhs_dilation\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"rhs_dilation\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"window_reversal\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_batch_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_input_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_output_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"kernel_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_batch_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_feature_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"output_spatial_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"feature_group_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"batch_group_count\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"precision_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_gather_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"slice_sizes\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"collapsed_slice_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"start_index_map\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_gather_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"slice_sizes\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"collapsed_slice_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"operand_batching_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"start_indices_batching_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"start_index_map\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_iota_v1\",\n    \"operands\": [\n      { \"name\": \"output_shape\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_pad_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"padding_value\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"edge_padding_low\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"edge_padding_high\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"interior_padding\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_reshape_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"output_shape\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_slice_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"slice_sizes\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.dynamic_update_slice_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"update\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.einsum_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"einsum_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.exponential_minus_one_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.exponential_minus_one_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.exponential_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.exponential_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.fft_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fft_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"fft_length\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.floor_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.func_v1\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"function_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"res_attrs\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"VHLO_AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"custom<FunctionBody>($sym_name, $body, $function_type) attr-dict\"\n  },\n  {\n    \"name\": \"vhlo.gather_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"collapsed_slice_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"start_index_map\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"slice_sizes\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.gather_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"offset_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"collapsed_slice_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"operand_batching_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"start_indices_batching_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"start_index_map\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"slice_sizes\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.get_dimension_size_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.get_tuple_element_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.if_v1\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"true_branch\", \"type\": \"VHLO_AnyRegion\" },\n      { \"name\": \"false_branch\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.imag_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.infeed_v1\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"infeed_config\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"layout\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.iota_v1\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"iota_dimension\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.is_finite_v1\",\n    \"operands\": [\n      { \"name\": \"x\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"y\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.log_plus_one_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.log_plus_one_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.log_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.log_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.logistic_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.logistic_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.map_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.maximum_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.minimum_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.multiply_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.negate_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.not_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.optimization_barrier_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.or_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.outfeed_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"token\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"outfeed_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.pad_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"padding_value\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"edge_padding_low\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"edge_padding_high\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"interior_padding\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.partition_id_v1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.popcnt_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.power_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.real_dynamic_slice_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"start_indices\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"limit_indices\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"strides\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.real_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.recv_v1\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.recv_v2\",\n    \"operands\": [\n      { \"name\": \"token\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.reduce_precision_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exponent_bits\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"mantissa_bits\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.reduce_scatter_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scatter_dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"replica_groups\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"use_global_device_ids\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.reduce_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.reduce_window_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"init_values\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"window_strides\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"base_dilations\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"window_dilations\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"padding\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.remainder_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.replica_id_v1\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.reshape_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.return_v1\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.reverse_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.rng_bit_generator_v1\",\n    \"operands\": [\n      { \"name\": \"initial_state\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"output_state\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"output\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_algorithm\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.rng_v1\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"b\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"shape\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rng_distribution\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.round_nearest_afz_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.round_nearest_even_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.rsqrt_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.rsqrt_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.scatter_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"scatter_indices\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"updates\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"update_window_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"inserted_window_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"scatter_dims_to_operand_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"unique_indices\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"update_computation\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.scatter_v2\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"scatter_indices\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"updates\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"update_window_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"inserted_window_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"input_batching_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"scatter_indices_batching_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"scatter_dims_to_operand_dims\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"index_vector_dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"indices_are_sorted\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"unique_indices\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"update_computation\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.select_and_scatter_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"source\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"init_value\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"window_dimensions\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"window_strides\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"padding\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"select\", \"type\": \"VHLO_AnyRegion\" },\n      { \"name\": \"scatter\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.select_v1\",\n    \"operands\": [\n      { \"name\": \"pred\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"on_true\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"on_false\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.send_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"token\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.send_v2\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" },\n      { \"name\": \"token\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"channel_id\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"channel_type\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"is_host_transfer\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"source_target_pairs\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.set_dimension_size_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"size\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.shift_left_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.shift_right_arithmetic_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.shift_right_logical_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.sign_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.sine_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.sine_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.slice_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"start_indices\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"limit_indices\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"strides\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.sort_v1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"is_stable\", \"type\": \"VHLO_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"comparator\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.sqrt_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.sqrt_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.subtract_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.tan_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.tan_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.tanh_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.tanh_v2\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"result_accuracy\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.torch_index_select_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"index\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"batch_dims\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.transpose_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"permutation\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.triangular_solve_v1\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"b\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_side\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"lower\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"unit_diagonal\", \"type\": \"VHLO_AnyAttr\" },\n      { \"name\": \"transpose_a\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.tuple_v1\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.unary_einsum_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"einsum_config\", \"type\": \"VHLO_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.uniform_dequantize_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.uniform_quantize_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.while_v1\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VHLO_AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"cond\", \"type\": \"VHLO_AnyRegion\" },\n      { \"name\": \"body\", \"type\": \"VHLO_AnyRegion\" }\n    ]\n  },\n  {\n    \"name\": \"vhlo.xor_v1\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VHLO_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VHLO_AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VHLO_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.AfterV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"control_output\", \"type\": \"Vifrt_AnyType\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.AssembleV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"Vifrt_AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.BitcastArraysV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"donated\", \"type\": \"Vifrt_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.CallFuncV1\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"Vifrt_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.CallLoadedExecutableV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_output\", \"type\": \"Vifrt_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"io_aliases\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"donated_input_indices\", \"type\": \"Vifrt_AnyAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.CallV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_output\", \"type\": \"Vifrt_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"devices\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"io_aliases\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"donated_input_indices\", \"type\": \"Vifrt_AnyAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.CopyArraysV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_output\", \"type\": \"Vifrt_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"donated\", \"type\": \"Vifrt_AnyAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.DisassembleV1\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"Vifrt_AnyType\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.FuncV1\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"function_type\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"sym_visibility\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"res_attrs\", \"type\": \"Vifrt_AnyAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"Vifrt_AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"custom<FunctionBody>($sym_name, $body, $function_type) attr-dict\"\n  },\n  {\n    \"name\": \"vifrt.LoadedExecutableV1\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"function_type\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"devices\", \"type\": \"Vifrt_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.RemapArraysV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mappings\", \"type\": \"Vifrt_AnyAttr\" },\n      { \"name\": \"donated\", \"type\": \"Vifrt_AnyAttr\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.ReshardV1\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_inputs\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"outputs\", \"type\": \"Variadic<Vifrt_AnyType>\" },\n      { \"name\": \"control_output\", \"type\": \"Vifrt_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"donated\", \"type\": \"Vifrt_AnyAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ]\n  },\n  {\n    \"name\": \"vifrt.ReturnV1\",\n    \"operands\": [\n      { \"name\": \"results\", \"type\": \"Variadic<Vifrt_AnyType>\" }\n    ]\n  },\n  {\n    \"name\": \"vm.abs.f32\",\n    \"summary\": \"Floating point absolute-value operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.abs.f64\",\n    \"summary\": \"Floating point absolute-value operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.abs.i32\",\n    \"summary\": \"Integer absolute-value operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.abs.i64\",\n    \"summary\": \"Integer absolute-value operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.add.f32\",\n    \"summary\": \"Floating-point add operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.add.f64\",\n    \"summary\": \"Floating-point add operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.add.i32\",\n    \"summary\": \"Integer add operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.add.i64\",\n    \"summary\": \"Integer add operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.and.i32\",\n    \"summary\": \"Integer binary and operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.and.i64\",\n    \"summary\": \"Integer binary and operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.assign.ref\",\n    \"summary\": \"Assigns a ref value between registers.\",\n    \"description\": \"Assigns a reference value from one register to another. This is a runtime\\n    operation that performs retain/move semantics based on the MOVE bit.\\n\\n    This operation exists to support efficient ref-to-ref assignments where\\n    the source and destination may have the same or different registers. When\\n    the source and destination registers are the same, this operation becomes\\n    a no-op and is elided during bytecode encoding.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type($source) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.atan.f32\",\n    \"summary\": \"Arcus tangent of the given value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.atan.f64\",\n    \"summary\": \"Arcus tangent of the given value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.atan2.f32\",\n    \"summary\": \"2-argument arcus tangent of the given values.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.atan2.f64\",\n    \"summary\": \"2-argument arcus tangent of the given values.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.bitcast.f32.i32\",\n    \"summary\": \"Bitcast from a 32-bit float-point value to a 32-bit integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.bitcast.f64.i64\",\n    \"summary\": \"Bitcast from a 64-bit float-point value to a 64-bit integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.bitcast.i32.f32\",\n    \"summary\": \"Bitcast from a 32-bit integer to a 32-bit float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.bitcast.i64.f64\",\n    \"summary\": \"Bitcast from a 64-bit integer to a 64-bit float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.br\",\n    \"summary\": \"Unconditional branch operation.\",\n    \"description\": \"Represents an unconditional branch operation that branches to a target block\\n    with the given set of arguments.\\n\\n    ```\\n    ^bb0(...):\\n      vm.br ^bb1(%a)\\n    ^bb1(%blockArg1):\\n      ...\\n   ```\",\n    \"operands\": [\n      { \"name\": \"destOperands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.br_table\",\n    \"summary\": \"Branch table operation.\",\n    \"description\": \"Represents a branch table instructing execution to branch to the block with\\n    the specified index. If the index is out of bounds then execution will\\n    branch to the default block.\\n\\n    ```\\n    vm.br_table %index {\\n      default: ^bb1(%a : i64),\\n      0: ^bb2,\\n      1: ^bb3(%c : i64)\\n    }\\n   ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"I32\" },\n      { \"name\": \"defaultOperands\", \"type\": \"Variadic<VM_AnyType>\" },\n      { \"name\": \"caseOperands\", \"type\": \"VariadicOfVariadic<VM_AnyType, case_operand_segments>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"case_operand_segments\", \"type\": \"DenseI32ArrayAttr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"defaultDestination\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"caseDestinations\", \"type\": \"VariadicSuccessor<AnySuccessor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$index ` ` `{` `\\\\n`\\n    custom<BranchTableCases>(\\n        $defaultDestination, $defaultOperands, type($defaultOperands),\\n        $caseDestinations, $caseOperands, type($caseOperands))\\n    `}`\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.break\",\n    \"summary\": \"Unconditional debug break operation.\",\n    \"description\": \"Breaks into the attached debugger or asks for attaching a debugger. After\\n    resuming (or if a debugger is not attached) execution will continue at the\\n    target block.\",\n    \"operands\": [\n      { \"name\": \"destOperands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.alloc\",\n    \"summary\": \"Allocates a new zero-initialized buffer.\",\n    \"description\": \"Allocates a new zero-initialized buffer with the given size in bytes.\",\n    \"operands\": [\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"alignment\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_RefOf<VM_BufferType>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.clone\",\n    \"summary\": \"Clones a buffer.\",\n    \"description\": \"Clones a range of the source buffer to produce a mutable buffer with the\\n    same contents.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"alignment\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_RefOf<VM_BufferType>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.compare\",\n    \"summary\": \"Compares a range of a buffer to another.\",\n    \"description\": \"Returns 1 if the two ranges are bitwise equivalent, somewhat like memcmp.\",\n    \"operands\": [\n      { \"name\": \"lhs_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"lhs_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"rhs_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"rhs_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs_buffer) `,` type($rhs_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.copy\",\n    \"summary\": \"Copies a range of a buffer to another.\",\n    \"description\": \"Copies a range of one buffer to another, like memcpy.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($source_buffer) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.fill.f32\",\n    \"summary\": \"Fills the buffer with the given repeating 32-bit value.\",\n    \"description\": \"Fills an element range of the buffer with the given value, like memset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[F32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$target_buffer `,` $target_offset `,` $length `,` $value\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.fill.f64\",\n    \"summary\": \"Fills the buffer with the given repeating 64-bit value.\",\n    \"description\": \"Fills an element range of the buffer with the given value, like memset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[F64, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$target_buffer `,` $target_offset `,` $length `,` $value\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.fill.i16\",\n    \"summary\": \"Fills the buffer with the given repeating 16-bit value.\",\n    \"description\": \"Fills an element range of the buffer with the given value, like memset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I16, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$target_buffer `,` $target_offset `,` $length `,` $value\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.fill.i32\",\n    \"summary\": \"Fills the buffer with the given repeating 32-bit value.\",\n    \"description\": \"Fills an element range of the buffer with the given value, like memset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$target_buffer `,` $target_offset `,` $length `,` $value\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.fill.i64\",\n    \"summary\": \"Fills the buffer with the given repeating 64-bit value.\",\n    \"description\": \"Fills an element range of the buffer with the given value, like memset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I64, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$target_buffer `,` $target_offset `,` $length `,` $value\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.fill.i8\",\n    \"summary\": \"Fills the buffer with the given repeating 8-bit value.\",\n    \"description\": \"Fills an element range of the buffer with the given value, like memset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I8, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$target_buffer `,` $target_offset `,` $length `,` $value\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.hash\",\n    \"description\": \"Computes the SipHash-2-4 of the source buffer at the given offset for\\n    |length| bytes using seed `0x0001020304...0e0f`.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"length\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `,` $source_offset `,` $length\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.length\",\n    \"summary\": \"Returns the byte length of a buffer.\",\n    \"description\": \"Returns the total byte length of the given buffer. This is the exact value\\n    as specified during buffer allocation though the underlying system buffer\\n    may have additional padding.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.f32\",\n    \"summary\": \"32-bit floating-point load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[F32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.f64\",\n    \"summary\": \"64-bit floating-point load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[F64, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.i16.s\",\n    \"summary\": \"Signed 16-bit integer load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.i16.u\",\n    \"summary\": \"Unsigned 16-bit integer load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.i32\",\n    \"summary\": \"32-bit integer load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.i64\",\n    \"summary\": \"64-bit integer load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I64, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.i8.s\",\n    \"summary\": \"Signed 8-bit integer load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.load.i8.u\",\n    \"summary\": \"Unsigned 8-bit integer load.\",\n    \"description\": \"Loads a value from the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"source_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"source_offset\", \"type\": \"VM_BufferIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$source_buffer `[` $source_offset `]`\\n    attr-dict `:` type($source_buffer) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.store.f32\",\n    \"summary\": \"32-bit floating-point store.\",\n    \"description\": \"Stores a value to the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[F32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target_buffer `[` $target_offset `]`\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.store.f64\",\n    \"summary\": \"64-bit floating-point store.\",\n    \"description\": \"Stores a value to the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[F64, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target_buffer `[` $target_offset `]`\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.store.i16\",\n    \"summary\": \"Unsigned 16-bit integer store.\",\n    \"description\": \"Stores a value to the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target_buffer `[` $target_offset `]`\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.store.i32\",\n    \"summary\": \"32-bit integer store.\",\n    \"description\": \"Stores a value to the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target_buffer `[` $target_offset `]`\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.store.i64\",\n    \"summary\": \"64-bit integer store.\",\n    \"description\": \"Stores a value to the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I64, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target_buffer `[` $target_offset `]`\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.buffer.store.i8\",\n    \"summary\": \"Unsigned 8-bit integer store.\",\n    \"description\": \"Stores a value to the buffer at the given element offset.\",\n    \"operands\": [\n      { \"name\": \"target_buffer\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"target_offset\", \"type\": \"VM_BufferIndex\" },\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[I32, I32]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $target_buffer `[` $target_offset `]`\\n    attr-dict `:` type($value) `->` type($target_buffer)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.call\",\n    \"summary\": \"Call operation.\",\n    \"description\": \"Calls an internal VM function with the given arguments.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"VM_FuncRefAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` operands `)` attr-dict `:` functional-type(operands, results)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.call.variadic\",\n    \"summary\": \"Call operation with variadic arguments.\",\n    \"description\": \"Calls an internal VM function with the given arguments. One or more of the\\n    arguments may be variadic, encoded as segmented sized operand lists.\\n\\n    Variadic arguments must be specified with a total count in the segment_sizes\\n    attribute.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"VM_FuncRefAttr\" },\n      { \"name\": \"segment_sizes\", \"type\": \"SignlessIntElementsAttr<16>\" },\n      { \"name\": \"segment_types\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.call.variadic.yieldable\",\n    \"summary\": \"Variadic call operation that may yield.\",\n    \"description\": \"Calls a variadic VM import function that may yield. If the call yields,\\n    execution resumes at the specified successor block with the call results\\n    as block arguments. If the call completes synchronously, control branches\\n    to the successor with the results.\\n\\n    Variadic arguments must be specified with a total count in the segment_sizes\\n    attribute. Only imports are supported (not internal functions).\\n\\n    ```\\n    ^bb0:\\n      vm.call.variadic.yieldable @import(%a, %b, %c) {segment_sizes = dense<[1, 2]> : vector<2xi16>}\\n        : (i32, i32, i32) -> ^resume(i32)\\n    ^resume(%result : i32):\\n      vm.return %result\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"VM_FuncRefAttr\" },\n      { \"name\": \"segment_sizes\", \"type\": \"SignlessIntElementsAttr<16>\" },\n      { \"name\": \"segment_types\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"result_types\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` `(` type($operands) `)`\\n    `->` $dest custom<ResultTypeList>($result_types)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.call.yieldable\",\n    \"summary\": \"Call operation that may yield.\",\n    \"description\": \"Calls a VM function (internal or imported) that may yield. If the call\\n    yields execution resumes at the specified successor block with the call\\n    results as block arguments. If the call completes synchronously control\\n    branches to the successor with the results.\\n\\n    This op is a terminator that combines a call with an explicit resume point,\\n    making the yield/resume semantics visible in the IR.\\n\\n    ```\\n    ^bb0:\\n      vm.call.yieldable @hal.fence.await(%timeout, %fence) : (i32, !vm.ref<?>) -> ^resume(i32)\\n    ^resume(%result : i32):\\n      vm.return %result\\n    ```\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"VM_FuncRefAttr\" },\n      { \"name\": \"result_types\", \"type\": \"TypedArrayAttrBase<TypeAttr>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $arguments `)` attr-dict `:` `(` type($arguments) `)`\\n    `->` $dest custom<ResultTypeList>($result_types)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.any.ref\",\n    \"summary\": \"Casts from any ref to a specific ref type.\",\n    \"description\": \"Performs a runtime cast of an opaque `!vm.ref<?>` to a specific `!vm.ref<T>`\\n    and raises an error if the operand does not match the expected type.\\n    Null refs can always be cast between types.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.f32.si32\",\n    \"summary\": \"Cast from a float-point value to a signed 32-bit integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.f32.si64\",\n    \"summary\": \"Cast from a float-point value to a signed 64-bit integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.f32.ui32\",\n    \"summary\": \"Cast from an float-point value to an unsigned 32-bit integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.f32.ui64\",\n    \"summary\": \"Cast from an float-point value to an unsigned 64-bit integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.f64.si64\",\n    \"summary\": \"Cast from a float-point value to a signed integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.f64.ui64\",\n    \"summary\": \"Cast from an float-point value to an unsigned integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.ref.any\",\n    \"summary\": \"Casts from a specific ref to any ref type.\",\n    \"description\": \"Performs a compile-time widening cast of a specific `!vm.ref<T>` to an\\n    opaque `!vm.ref<?>`. At runtime this is equivalent to a ref assignment\\n    since all refs have the same representation. Uses the same encoding as\\n    vm.assign.ref.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.si32.f32\",\n    \"summary\": \"Cast from a signed integer to a float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.si64.f32\",\n    \"summary\": \"Cast from a signed integer to a float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.si64.f64\",\n    \"summary\": \"Cast from a signed integer to a float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.ui32.f32\",\n    \"summary\": \"Cast from an unsigned integer to a float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.ui64.f32\",\n    \"summary\": \"Cast from an unsigned integer to a float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cast.ui64.f64\",\n    \"summary\": \"Cast from an unsigned integer to a float-point value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ceil.f32\",\n    \"summary\": \"Floating point ceiling operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ceil.f64\",\n    \"summary\": \"Floating point ceiling operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.check.eq\",\n    \"summary\": \"Raises a global failure if the condition is true.\",\n    \"description\": \"When the condition is true this signals a runtime failure that causes the\\n    entire active invocation - and possibly *all* in-flight and pending\\n    invocations - to fail. The status will be propagated back via the available\\n    runtime error handling mechanisms such as semaphores or synchronous\\n    invocation results.\\n\\n    This is implemented as a pseudo-op that transforms into a vm.cond_fail\\n    operation.\\n\\n    ```\\n    vm.check.eq %a, %b, \\\"a == b\\\" : i32\\n    vm.check.nz %ref, \\\"!null\\\" : !vm.ref<?>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VM_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VM_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`,` $message^)? attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.check.ne\",\n    \"summary\": \"Raises a global failure if the condition is true.\",\n    \"description\": \"When the condition is true this signals a runtime failure that causes the\\n    entire active invocation - and possibly *all* in-flight and pending\\n    invocations - to fail. The status will be propagated back via the available\\n    runtime error handling mechanisms such as semaphores or synchronous\\n    invocation results.\\n\\n    This is implemented as a pseudo-op that transforms into a vm.cond_fail\\n    operation.\\n\\n    ```\\n    vm.check.eq %a, %b, \\\"a == b\\\" : i32\\n    vm.check.nz %ref, \\\"!null\\\" : !vm.ref<?>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VM_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VM_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`,` $message^)? attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.check.nearly_eq\",\n    \"summary\": \"Raises a global failure if the condition is true.\",\n    \"description\": \"When the condition is true this signals a runtime failure that causes the\\n    entire active invocation - and possibly *all* in-flight and pending\\n    invocations - to fail. The status will be propagated back via the available\\n    runtime error handling mechanisms such as semaphores or synchronous\\n    invocation results.\\n\\n    This is implemented as a pseudo-op that transforms into a vm.cond_fail\\n    operation.\\n\\n    ```\\n    vm.check.eq %a, %b, \\\"a == b\\\" : i32\\n    vm.check.nz %ref, \\\"!null\\\" : !vm.ref<?>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VM_AnyType\" },\n      { \"name\": \"rhs\", \"type\": \"VM_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`,` $message^)? attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.check.nz\",\n    \"summary\": \"Raises a global failure if the condition is true.\",\n    \"description\": \"When the condition is true this signals a runtime failure that causes the\\n    entire active invocation - and possibly *all* in-flight and pending\\n    invocations - to fail. The status will be propagated back via the available\\n    runtime error handling mechanisms such as semaphores or synchronous\\n    invocation results.\\n\\n    This is implemented as a pseudo-op that transforms into a vm.cond_fail\\n    operation.\\n\\n    ```\\n    vm.check.eq %a, %b, \\\"a == b\\\" : i32\\n    vm.check.nz %ref, \\\"!null\\\" : !vm.ref<?>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"VM_AnyType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value (`,` $message^)? attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.f32.near\",\n    \"summary\": \"Near floating-point equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.f32.o\",\n    \"summary\": \"Ordered floating-point equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.f32.u\",\n    \"summary\": \"Unordered floating-point equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.f64.near\",\n    \"summary\": \"Near floating-point equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.f64.o\",\n    \"summary\": \"Ordered floating-point equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.f64.u\",\n    \"summary\": \"Unordered floating-point equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.i32\",\n    \"summary\": \"Integer equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.i64\",\n    \"summary\": \"Integer equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.eq.ref\",\n    \"summary\": \"ref<T> equality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VM_AnyRef\" },\n      { \"name\": \"rhs\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.f32.o\",\n    \"summary\": \"Ordered floating-point greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.f32.u\",\n    \"summary\": \"Unordered floating-point greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.f64.o\",\n    \"summary\": \"Ordered floating-point greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.f64.u\",\n    \"summary\": \"Unordered floating-point greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.i32.s\",\n    \"summary\": \"Signed integer greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.i32.u\",\n    \"summary\": \"Unsigned integer greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.i64.s\",\n    \"summary\": \"Signed integer greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gt.i64.u\",\n    \"summary\": \"Unsigned integer greater-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.f32.o\",\n    \"summary\": \"Ordered floating-point greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.f32.u\",\n    \"summary\": \"Unordered floating-point greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.f64.o\",\n    \"summary\": \"Ordered floating-point greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.f64.u\",\n    \"summary\": \"Unordered floating-point greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.i32.s\",\n    \"summary\": \"Signed integer greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.i32.u\",\n    \"summary\": \"Unsigned integer greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.i64.s\",\n    \"summary\": \"Signed integer greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.gte.i64.u\",\n    \"summary\": \"Unsigned integer greater-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.f32.o\",\n    \"summary\": \"Ordered floating-point less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.f32.u\",\n    \"summary\": \"Unordered floating-point less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.f64.o\",\n    \"summary\": \"Ordered floating-point less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.f64.u\",\n    \"summary\": \"Unordered floating-point less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.i32.s\",\n    \"summary\": \"Signed integer less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.i32.u\",\n    \"summary\": \"Unsigned integer less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.i64.s\",\n    \"summary\": \"Signed integer less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lt.i64.u\",\n    \"summary\": \"Unsigned integer less-than comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.f32.o\",\n    \"summary\": \"Ordered floating-point less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.f32.u\",\n    \"summary\": \"Unordered floating-point less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.f64.o\",\n    \"summary\": \"Ordered floating-point less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.f64.u\",\n    \"summary\": \"Unordered floating-point less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.i32.s\",\n    \"summary\": \"Signed integer less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.i32.u\",\n    \"summary\": \"Unsigned integer less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.i64.s\",\n    \"summary\": \"Signed integer less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.lte.i64.u\",\n    \"summary\": \"Unsigned integer less-than-or-equal comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nan.f32\",\n    \"summary\": \"Floating-point NaN comparison operation.\",\n    \"description\": \"Returns 1 if the value is NaN.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nan.f64\",\n    \"summary\": \"Floating-point NaN comparison operation.\",\n    \"description\": \"Returns 1 if the value is NaN.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.f32.o\",\n    \"summary\": \"Ordered floating-point inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.f32.u\",\n    \"summary\": \"Unordered floating-point inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.f64.o\",\n    \"summary\": \"Ordered floating-point inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.f64.u\",\n    \"summary\": \"Unordered floating-point inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.i32\",\n    \"summary\": \"Integer inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.i64\",\n    \"summary\": \"Integer inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.ne.ref\",\n    \"summary\": \"ref<T> inequality comparison operation.\",\n    \"description\": \"Compares two operands with the specified predicate.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"VM_AnyRef\" },\n      { \"name\": \"rhs\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($lhs)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.f32.o\",\n    \"summary\": \"Ordered floating-point non-zero comparison operation.\",\n    \"description\": \"Compares the given floating-point operand for a non-zero value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.f32.u\",\n    \"summary\": \"Unordered floating-point non-zero comparison operation.\",\n    \"description\": \"Compares the given floating-point operand for a non-zero value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.f64.o\",\n    \"summary\": \"Ordered floating-point non-zero comparison operation.\",\n    \"description\": \"Compares the given floating-point operand for a non-zero value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.f64.u\",\n    \"summary\": \"Unordered floating-point non-zero comparison operation.\",\n    \"description\": \"Compares the given floating-point operand for a non-zero value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.i32\",\n    \"summary\": \"Integer non-zero comparison operation.\",\n    \"description\": \"Compares the given integer operand for a non-zero value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.i64\",\n    \"summary\": \"Integer non-zero comparison operation.\",\n    \"description\": \"Compares the given integer operand for a non-zero value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cmp.nz.ref\",\n    \"summary\": \"ref<T> non-zero comparison operation.\",\n    \"description\": \"Compares the given ref operand for a non-zero/null value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cond_br\",\n    \"summary\": \"Conditional branch operation.\",\n    \"description\": \"Represents a conditional branch operation that branches to one of the two\\n    target blocks with the given set of arguments.\\n\\n    ```\\n    ^bb0(...):\\n      vm.cond_br %condition, ^bb1(%a), ^bb2(%b)\\n    ^bb1(%blockArg1):\\n      ...\\n    ^bb2(%blockArg2):\\n      ...\\n   ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"trueDestOperands\", \"type\": \"Variadic<VM_AnyType>\" },\n      { \"name\": \"falseDestOperands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"trueDest\", \"type\": \"AnySuccessor\" },\n      { \"name\": \"falseDest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$condition `,`\\n    $trueDest (`(` $trueDestOperands^ `:` type($trueDestOperands) `)`)? `,`\\n    $falseDest (`(` $falseDestOperands^ `:` type($falseDestOperands) `)`)?\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cond_break\",\n    \"summary\": \"Conditional debug break operation.\",\n    \"description\": \"Breaks into the attached debugger or asks for attaching a debugger if the\\n    provided condition is true. After resuming (or if a debugger is not\\n    attached) execution will continue at the target block.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"destOperands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$condition `,` $dest (`(` $destOperands^ `:` type($destOperands) `)`)?\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cond_fail\",\n    \"summary\": \"Raises a global failure if the condition is true.\",\n    \"description\": \"When the condition is true this signals a runtime failure that causes the\\n    entire active invocation - and possibly *all* in-flight and pending\\n    invocations - to fail with the given status. The status will be propagated\\n    back via the available runtime error handling mechanisms such as semaphores\\n    or synchronous invocation results.\\n\\n    As the IREE execution model is deeply pipelined it's possible that failures\\n    have a latency between when they are emitted and when the application can\\n    observe the failure. It's also possible that other work that is in-flight\\n    or pending when the failure occurs will complete.\\n\\n    This is implemented as a pseudo-op that transforms into a vm.fail operation\\n    guarded by the condition.\\n\\n    ```\\n    %nz = vm.cmp.nz.i32 %value : i32\\n    %statusCode = vm.const.i32 9\\n    vm.cond_fail %nz, %statusCode, \\\"expected non-zero\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"status\", \"type\": \"Util_Status\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.f32\",\n    \"summary\": \"32-bit floating-point constant operation.\",\n    \"description\": \"Defines a constant value that is treated as a scalar literal at runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"VM_ConstantFloatValueAttr<F32>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.f32.zero\",\n    \"summary\": \"32-bit floating-point constant zero operation.\",\n    \"description\": \"Defines a constant zero primitive.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.f64\",\n    \"summary\": \"64-bit floating-point constant operation.\",\n    \"description\": \"Defines a constant value that is treated as a scalar literal at runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"VM_ConstantFloatValueAttr<F64>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.f64.zero\",\n    \"summary\": \"64-bit floating-point constant zero operation.\",\n    \"description\": \"Defines a constant zero primitive.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.i32\",\n    \"summary\": \"32-bit integer constant operation.\",\n    \"description\": \"Defines a constant value that is treated as a scalar literal at runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"VM_ConstantIntegerValueAttr<I32>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.i32.zero\",\n    \"summary\": \"32-bit integer constant zero operation.\",\n    \"description\": \"Defines a constant zero primitive.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.i64\",\n    \"summary\": \"64-bit integer constant operation.\",\n    \"description\": \"Defines a constant value that is treated as a scalar literal at runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"VM_ConstantIntegerValueAttr<I64>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.i64.zero\",\n    \"summary\": \"64-bit integer constant zero operation.\",\n    \"description\": \"Defines a constant zero primitive.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.ref.rodata\",\n    \"summary\": \"Constant rodata access operation.\",\n    \"description\": \"Returns a reference to a read-only buffer.\",\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"VM_RefOf<VM_BufferType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rodata\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$rodata attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.const.ref.zero\",\n    \"summary\": \"null ref constant operation.\",\n    \"description\": \"Defines a constant null ref that can be used in comparisons and\\n    initialization.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"assemblyFormat\": \"`:` type($result) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cos.f32\",\n    \"summary\": \"Cosine of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.cos.f64\",\n    \"summary\": \"Cosine of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ctlz.i32\",\n    \"summary\": \"Counts the leading zeros in an integer value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ctlz.i64\",\n    \"summary\": \"Counts the leading zeros in an integer value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.discard.refs\",\n    \"summary\": \"Discards reference values, releasing them.\",\n    \"description\": \"Explicitly releases reference values. This is used by the compiler to insert\\n    early releases at ref death points, enabling functions to be marked as\\n    \\\"refs clean\\\" so the runtime can skip cleanup on the success path.\\n\\n    The encode method is implemented manually in C++ to support per-operand\\n    elision based on register allocation analysis. Operands that have already\\n    been released via a MOVE bit on a preceding use are elided from encoding.\",\n    \"operands\": [\n      { \"name\": \"refs\", \"type\": \"Variadic<VM_AnyRef>\" }\n    ],\n    \"assemblyFormat\": \"($refs^ `:` type($refs))? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.div.f32\",\n    \"summary\": \"Floating point division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.div.f64\",\n    \"summary\": \"Floating point division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.div.i32.s\",\n    \"summary\": \"Signed integer division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.div.i32.u\",\n    \"summary\": \"Unsigned integer division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.div.i64.s\",\n    \"summary\": \"Signed integer division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.div.i64.u\",\n    \"summary\": \"Unsigned integer division operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.erf.f32\",\n    \"summary\": \"Computes the error function of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.erf.f64\",\n    \"summary\": \"Computes the error function of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.exp.f32\",\n    \"summary\": \"Base-e exponential of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.exp.f64\",\n    \"summary\": \"Base-e exponential of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.exp2.f32\",\n    \"summary\": \"Base-2 exponential of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.exp2.f64\",\n    \"summary\": \"Base-2 exponential of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.expm1.f32\",\n    \"summary\": \"Base-e exponential of the specified value minus 1.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.expm1.f64\",\n    \"summary\": \"Base-e exponential of the specified value minus 1.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.export\",\n    \"summary\": \"Exports a function from the module.\",\n    \"description\": \"Specifies an exported function with an externally-visible alias. Multiple\\n    exports can reference the same internal functions.\",\n    \"attributes\": [\n      { \"name\": \"function_ref\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"export_name\", \"type\": \"StrAttr\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.f32.f64\",\n    \"summary\": \"Floating-point zero extend 32 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i16.i32.s\",\n    \"summary\": \"Integer sign extend 16 bits to 32 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i16.i32.u\",\n    \"summary\": \"Integer zero extend 16 bits to 32 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i16.i64.s\",\n    \"summary\": \"Integer sign extend 16 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i16.i64.u\",\n    \"summary\": \"Integer zero extend 16 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i32.i64.s\",\n    \"summary\": \"Integer sign extend 32 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i32.i64.u\",\n    \"summary\": \"Integer zero extend 32 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i8.i32.s\",\n    \"summary\": \"Integer sign extend 8 bits to 32 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i8.i32.u\",\n    \"summary\": \"Integer zero extend 8 bits to 32 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i8.i64.s\",\n    \"summary\": \"Integer sign extend 8 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.ext.i8.i64.u\",\n    \"summary\": \"Integer zero extend 8 bits to 64 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.fail\",\n    \"summary\": \"Raises a global failure.\",\n    \"description\": \"Signals a runtime failure that causes the entire active invocation - and\\n    possibly *all* in-flight and pending invocations - to fail with the given\\n    status. The status will be propagated back via the available runtime error\\n    handling mechanisms such as semaphores or synchronous invocation results.\\n\\n    As the IREE execution model is deeply pipelined it's possible that failures\\n    have a latency between when they are emitted and when the application can\\n    observe the failure. It's also possible that other work that is in-flight\\n    or pending when the failure occurs will complete.\\n\\n    ```\\n    %statusCode = vm.const.i32 9\\n    vm.fail %statusCode, \\\"oh no!\\\"\\n    ```\",\n    \"operands\": [\n      { \"name\": \"status\", \"type\": \"Util_Status\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$status (`,` $message^)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.floor.f32\",\n    \"summary\": \"Floating point floor operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.floor.f64\",\n    \"summary\": \"Floating point floor operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.fma.f32\",\n    \"summary\": \"Floating point fused multiply-add operation (a*b+c).\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"F32\" },\n      { \"name\": \"b\", \"type\": \"F32\" },\n      { \"name\": \"c\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b', 'c', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.fma.f64\",\n    \"summary\": \"Floating point fused multiply-add operation (a*b+c).\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"F64\" },\n      { \"name\": \"b\", \"type\": \"F64\" },\n      { \"name\": \"c\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b', 'c', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.fma.i32\",\n    \"summary\": \"Integer fused-multiply add operation (a*b+c).\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"I32\" },\n      { \"name\": \"b\", \"type\": \"I32\" },\n      { \"name\": \"c\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b', 'c', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.fma.i64\",\n    \"summary\": \"Integer fused-multiply add operation (a*b+c).\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"I64\" },\n      { \"name\": \"b\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b', 'c', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.func\",\n    \"summary\": \"Function defined with VM control flow ops.\",\n    \"description\": \"Represents a function containing VM ops and those of compatible dialects.\\n    All flow control is performed by VM ops.\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.address\",\n    \"summary\": \"Returns an address reference to a global.\",\n    \"description\": \"Returns an indirect address reference to the given global. During export the\\n    address will be converted to the natural format of the global table (for\\n    example, ordinals for refs and byte offsets for primitive types).\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_AnyPtrType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.f32\",\n    \"summary\": \"32-bit floating-point global declaration.\",\n    \"description\": \"Defines a global value that is treated as a scalar literal at runtime.\\n    Initialized to zero unless an initial value is specified.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<VM_ConstantFloatValueAttr<F32>>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name\\n    attr-dict\\n    custom<TypeOrAttr>($type, $initial_value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.f64\",\n    \"summary\": \"64-bit floating-point global declaration.\",\n    \"description\": \"Defines a global value that is treated as a scalar literal at runtime.\\n    Initialized to zero unless an initial value is specified.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<VM_ConstantFloatValueAttr<F64>>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name\\n    attr-dict\\n    custom<TypeOrAttr>($type, $initial_value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.i32\",\n    \"summary\": \"32-bit integer global declaration.\",\n    \"description\": \"Defines a global value that is treated as a scalar literal at runtime.\\n    Initialized to zero unless an initial value is specified.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<VM_ConstantIntegerValueAttr<I32>>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name\\n    attr-dict\\n    custom<TypeOrAttr>($type, $initial_value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.i64\",\n    \"summary\": \"64-bit integer global declaration.\",\n    \"description\": \"Defines a global value that is treated as a scalar literal at runtime.\\n    Initialized to zero unless an initial value is specified.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"initial_value\", \"type\": \"OptionalAttr<VM_ConstantIntegerValueAttr<I64>>\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name\\n    attr-dict\\n    custom<TypeOrAttr>($type, $initial_value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.f32\",\n    \"summary\": \"Global 32-bit floating-point load operation.\",\n    \"description\": \"Loads the value of a global containing an primitive value.\",\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.f64\",\n    \"summary\": \"Global 64-bit floating-point load operation.\",\n    \"description\": \"Loads the value of a global containing an primitive value.\",\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"F64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.i32\",\n    \"summary\": \"Global 32-bit integer load operation.\",\n    \"description\": \"Loads the value of a global containing an primitive value.\",\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.i64\",\n    \"summary\": \"Global 64-bit integer load operation.\",\n    \"description\": \"Loads the value of a global containing an primitive value.\",\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.indirect.f32\",\n    \"summary\": \"Global 32-bit floating-point load operation.\",\n    \"description\": \"Loads the value of a global containing a primitive value.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<F32>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($global) `->` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.indirect.f64\",\n    \"summary\": \"Global 64-bit floating-point load operation.\",\n    \"description\": \"Loads the value of a global containing a primitive value.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<F64>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"F64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($global) `->` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.indirect.i32\",\n    \"summary\": \"Global 32-bit integer load operation.\",\n    \"description\": \"Loads the value of a global containing a primitive value.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<I32>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($global) `->` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.indirect.i64\",\n    \"summary\": \"Global 64-bit integer load operation.\",\n    \"description\": \"Loads the value of a global containing a primitive value.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<I64>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($global) `->` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.indirect.ref\",\n    \"summary\": \"Global ref<T> load operation.\",\n    \"description\": \"Loads the value of a global containing a ref of the given type.\",\n    \"operands\": [\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<VM_AnyRef>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($global) `->` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.load.ref\",\n    \"summary\": \"Global ref<T> load operation.\",\n    \"description\": \"Loads the value of a global containing a ref of the given type.\",\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" },\n      { \"name\": \"is_immutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`immutable` $is_immutable^)?\\n    $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.ref\",\n    \"summary\": \"ref<T> global declaration.\",\n    \"description\": \"Defines a global value that is a ref of a specific type. The global will\\n    retain the ref object for the lifetime of the context or until the value is\\n    replaced with a store or reset.\\n    Initialized to null unless an initial value is specified.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"is_mutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"inlining_policy\", \"type\": \"OptionalAttr<Util_InliningPolicyAttrInterface>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    (`mutable` $is_mutable^)?\\n    $sym_name\\n    attr-dict\\n    `:` $type\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.f32\",\n    \"summary\": \"Global 32-bit floating-point store operation.\",\n    \"description\": \"Stores a primitive value value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"F32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.f64\",\n    \"summary\": \"Global 64-bit floating-point store operation.\",\n    \"description\": \"Stores a primitive value value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"F64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.i32\",\n    \"summary\": \"Global 32-bit integer store operation.\",\n    \"description\": \"Stores a primitive value value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.i64\",\n    \"summary\": \"Global 64-bit integer store operation.\",\n    \"description\": \"Stores a primitive value value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.indirect.f32\",\n    \"summary\": \"Global 32-bit floating-point store operation.\",\n    \"description\": \"Stores a primitive value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"F32\" },\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<F32>]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value) `->` type($global)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.indirect.f64\",\n    \"summary\": \"Global 64-bit floating-point store operation.\",\n    \"description\": \"Stores a primitive value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"F64\" },\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<F64>]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value) `->` type($global)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.indirect.i32\",\n    \"summary\": \"Global 32-bit integer store operation.\",\n    \"description\": \"Stores a primitive value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I32\" },\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<I32>]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value) `->` type($global)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.indirect.i64\",\n    \"summary\": \"Global 64-bit integer store operation.\",\n    \"description\": \"Stores a primitive value to a global.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"I64\" },\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<I64>]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value) `->` type($global)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.indirect.ref\",\n    \"summary\": \"Global ref<T> stores operation.\",\n    \"description\": \"Stores a ref<T> to a global, retaining it until the global is reset.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"VM_AnyRef\" },\n      { \"name\": \"global\", \"type\": \"AnyTypeOf<[VM_Ptr, Util_PtrOf<VM_AnyRef>]>\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value) `->` type($global)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.global.store.ref\",\n    \"summary\": \"Global ref<T> stores operation.\",\n    \"description\": \"Stores a ref<T> to a global, retaining it until the global is reset.\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"VM_GlobalRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$value `,` $global attr-dict `:` type($value)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.import\",\n    \"summary\": \"Imports a function from an external module.\",\n    \"description\": \"Specifies a function that should be imported from either the runtime or\\n    an external VM module.\\n\\n    Required imports can be declared with a minimum version of the module that\\n    contains the import. The maximum declared minimum version of all required\\n    imports from the module will become the required minimum version at runtime.\\n\\n    Optional imports not present at runtime will be invalid to call and whether\\n    they were resolved can be queried with `vm.import.resolved`.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" },\n      { \"name\": \"is_optional\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"minimum_version\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.import.resolved\",\n    \"summary\": \"Returns true if an optional import was resolved at runtime.\",\n    \"description\": \"Allows for checking whether a optional import was resolved at runtime. If\\n    this returns false then attempting to call the imported function will result\\n    in a failure at runtime.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_CondValue\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"import\", \"type\": \"VM_FuncRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$import attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.initializer\",\n    \"summary\": \"Global initialization function.\",\n    \"description\": \"A function that is called in definition order upon module initialization.\\n    Must not load any globals that are defined or initialized after it in the\\n    module.\",\n    \"attributes\": [\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.alloc\",\n    \"summary\": \"Allocates a new empty list.\",\n    \"description\": \"Allocates a new typed list with a minimum initial_capacity.\",\n    \"operands\": [\n      { \"name\": \"initial_capacity\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyList\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($initial_capacity) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.get.f32\",\n    \"summary\": \"Primitive type element accessor.\",\n    \"description\": \"Returns the value of the element at the given index.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.get.f64\",\n    \"summary\": \"Primitive type element accessor.\",\n    \"description\": \"Returns the value of the element at the given index.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.get.i32\",\n    \"summary\": \"Primitive type element accessor.\",\n    \"description\": \"Returns the value of the element at the given index.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.get.i64\",\n    \"summary\": \"Primitive type element accessor.\",\n    \"description\": \"Returns the value of the element at the given index.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.get.ref\",\n    \"summary\": \"ref type element accessor.\",\n    \"description\": \"Returns the ref value of the element at the given index. Note that the value\\n    may be null if the element is null or the type does not match.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_AnyList\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.reserve\",\n    \"summary\": \"Reserves capacity for list growth.\",\n    \"description\": \"Reserves storage for at least minimum_capacity elements. If the list already\\n    has at least the specified capacity the operation is ignored.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_AnyList\" },\n      { \"name\": \"minimum_capacity\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($minimum_capacity) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.resize\",\n    \"summary\": \"Resizes the list to a new count in elements.\",\n    \"description\": \"Resizes the list to contain new_size elements. This will either truncate\\n    the list if the existing size is greater than new_size or extend the list\\n    with the default list value of 0 if storing primitives and null if refs.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_AnyList\" },\n      { \"name\": \"new_size\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($new_size) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.set.f32\",\n    \"summary\": \"Primitive type element mutator.\",\n    \"description\": \"Sets the element at the given index to the new value.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" },\n      { \"name\": \"value\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `,` type($value) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.set.f64\",\n    \"summary\": \"Primitive type element mutator.\",\n    \"description\": \"Sets the element at the given index to the new value.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" },\n      { \"name\": \"value\", \"type\": \"F64\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `,` type($value) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.set.i32\",\n    \"summary\": \"Primitive type element mutator.\",\n    \"description\": \"Sets the element at the given index to the new value.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" },\n      { \"name\": \"value\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `,` type($value) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.set.i64\",\n    \"summary\": \"Primitive type element mutator.\",\n    \"description\": \"Sets the element at the given index to the new value.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_ListOf<VM_PrimitiveType>\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" },\n      { \"name\": \"value\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `,` type($value) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.set.ref\",\n    \"summary\": \"ref type element mutator.\",\n    \"description\": \"Sets the element at the given index to the new ref value (possibly null).\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_AnyList\" },\n      { \"name\": \"index\", \"type\": \"VM_ListIndex\" },\n      { \"name\": \"value\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `,` type($index) `,` type($value) `)`\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.list.size\",\n    \"summary\": \"The size of the list in elements.\",\n    \"description\": \"Returns the current size of the list in elements.\",\n    \"operands\": [\n      { \"name\": \"list\", \"type\": \"VM_AnyList\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_ListIndex\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` `(` type($list) `)` `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log.f32\",\n    \"summary\": \"Base-e logarithm of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log.f64\",\n    \"summary\": \"Base-e logarithm of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log10.f32\",\n    \"summary\": \"Base-10 logarithm of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log10.f64\",\n    \"summary\": \"Base-10 logarithm of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log1p.f32\",\n    \"summary\": \"Natural logarithm of one plus the given value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log1p.f64\",\n    \"summary\": \"Natural logarithm of one plus the given value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log2.f32\",\n    \"summary\": \"Base-2 logarithm of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.log2.f64\",\n    \"summary\": \"Base-2 logarithm of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.max.f32\",\n    \"summary\": \"Floating point maximum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.max.f64\",\n    \"summary\": \"Floating point maximum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.max.i32.s\",\n    \"summary\": \"Signed integer maximum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.max.i32.u\",\n    \"summary\": \"Unsigned integer maximum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.max.i64.s\",\n    \"summary\": \"Signed integer maximum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.max.i64.u\",\n    \"summary\": \"Unsigned integer maximum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.min.f32\",\n    \"summary\": \"Floating point minimum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.min.f64\",\n    \"summary\": \"Floating point minimum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.min.i32.s\",\n    \"summary\": \"Signed integer minimum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.min.i32.u\",\n    \"summary\": \"Unsigned integer minimum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.min.i64.s\",\n    \"summary\": \"Signed integer minimum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.min.i64.u\",\n    \"summary\": \"Unsigned integer minimum operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.module\",\n    \"summary\": \"Module containing VM functions and variables.\",\n    \"description\": \"Top-level container for VM functions.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"ordinal_counts\", \"type\": \"OptionalAttr<VM_OrdinalCountsAttr>\" },\n      { \"name\": \"version\", \"type\": \"OptionalAttr<I32Attr>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility)\\n    $sym_name\\n    attr-dict-with-keyword\\n    regions\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.module_terminator\",\n    \"summary\": \"Terminator pseudo-op for the module op.\",\n    \"assemblyFormat\": \"attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.mul.f32\",\n    \"summary\": \"Floating point multiplication operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.mul.f64\",\n    \"summary\": \"Floating point multiplication operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.mul.i32\",\n    \"summary\": \"Integer multiplication operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.mul.i64\",\n    \"summary\": \"Integer multiplication operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.neg.f32\",\n    \"summary\": \"Floating point negation operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.neg.f64\",\n    \"summary\": \"Floating point negation operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.not.i32\",\n    \"summary\": \"Integer binary not operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.not.i64\",\n    \"summary\": \"Integer binary not operation.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.optimization_barrier\",\n    \"summary\": \"Prevents compiler optimizations across a value.\",\n    \"description\": \"Wraps any operands in an unoptimizable identity to prevent its results from\\n    being folded. It will be dropped during the final step in compilation and\\n    has no effect at runtime.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operands', 'results']>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.or.i32\",\n    \"summary\": \"Integer binary or operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.or.i64\",\n    \"summary\": \"Integer binary or operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.pow.f32\",\n    \"summary\": \"Floating point raised to the power of operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.pow.f64\",\n    \"summary\": \"Floating point raised to the power of operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.print\",\n    \"summary\": \"Message printing operation.\",\n    \"description\": \"Prints the given string message and zero or more values.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"message\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$message `(` operands `)` attr-dict `:` type(operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rem.f32\",\n    \"summary\": \"Floating point remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rem.f64\",\n    \"summary\": \"Floating point remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rem.i32.s\",\n    \"summary\": \"Signed integer division remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rem.i32.u\",\n    \"summary\": \"Unsigned integer division remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rem.i64.s\",\n    \"summary\": \"Signed integer division remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rem.i64.u\",\n    \"summary\": \"Unsigned integer division remainder operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.return\",\n    \"summary\": \"Return operation.\",\n    \"description\": \"Represents a return operation within a function.\\n\\n    ```\\n    vm.func @foo(%0: i32, %1: f8) -> (i32, f8) {\\n      vm.return %0, %1 : i32, f8\\n    }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rodata\",\n    \"summary\": \"Read-only data definition operation.\",\n    \"description\": \"Defines a blob of read-only constant data that can be represented as a\\n    ref. This can be used to store arbitrary data within modules such as\\n    large constant buffers and other file contents.\\n\\n    Note that the data is reference counted as a way to track its usage once the\\n    value leaves the module. For example, returning rodata from an exported\\n    function must keep the data (possibly backed by mmap) valid for its entire\\n    lifetime.\\n\\n    By default all rodata will be aligned in the final module output at a\\n    16-byte granularity. An optional alignment can be specified to override the\\n    default for cases where larger or smaller alignments are needed.\",\n    \"attributes\": [\n      { \"name\": \"sym_visibility\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"value\", \"type\": \"Util_AnySerializableAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"ordinal\", \"type\": \"OptionalAttr<VM_Ordinal>\" },\n      { \"name\": \"mime_type\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"assemblyFormat\": \"custom<SymbolVisibility>($sym_visibility) $sym_name attr-dict $value\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rodata.inline\",\n    \"summary\": \"Inlined constant rodata.\",\n    \"description\": \"vm.rodata that can be embedded inline in functions. See vm.rodata for more\\n    information.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_RefOf<VM_BufferType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"value\", \"type\": \"Util_AnySerializableAttr\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"mime_type\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"($name^)? attr-dict `:` type($result) `=` $value\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rodata.table.inline\",\n    \"summary\": \"Inlined constant rodata table.\",\n    \"description\": \"vm.rodata with another associated vm.rodata table specifying byte offsets\\n    and sizes as a subview into the flattened data. The table is a flat array\\n    of 32 or 64-bit integers storing (offset, size) in element order.\\n\\n    The optional alignment attribute applies to both the table and data rodata.\\n    The data_alignment attribute can be used to specify an alignment for the\\n    elements of the table, padding to the data alignment with zeros. The element\\n    sizes reflect the unpadded attribute storage sizes.\\n\\n    See vm.rodata for more information.\",\n    \"results\": [\n      { \"name\": \"table_result\", \"type\": \"VM_RefOf<VM_BufferType>\" },\n      { \"name\": \"data_result\", \"type\": \"VM_RefOf<VM_BufferType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"table_name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"data_name\", \"type\": \"OptionalAttr<StrAttr>\" },\n      { \"name\": \"table_type\", \"type\": \"TypeAttrOf<VM_AnyIntegerType>\" },\n      { \"name\": \"data_array\", \"type\": \"TypedArrayAttrBase<Util_AnySerializableAttr>\" },\n      { \"name\": \"alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"data_alignment\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"mime_type\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"$table_type attr-dict `:` type($table_result) `,` type($data_result) `=` $data_array\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.round.f32\",\n    \"summary\": \"Rounds the value to the nearest integer away from zero.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.round.f32.even\",\n    \"summary\": \"Rounds the value to the nearest even integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.round.f64\",\n    \"summary\": \"Rounds the value to the nearest integer away from zero.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.round.f64.even\",\n    \"summary\": \"Rounds the value to the nearest even integer.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rsqrt.f32\",\n    \"summary\": \"Reciprocal of sqrt (1 / sqrt of the specified value).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.rsqrt.f64\",\n    \"summary\": \"Reciprocal of sqrt (1 / sqrt of the specified value).\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.select.f32\",\n    \"summary\": \"Floating-point select operation.\",\n    \"description\": \"Chooses one value based on a binary condition supplied as its first operand.\\n    If the value of the condition is true the `true_value` operand is chosen,\\n    otherwise the `false_value` operand is chosen. The true and false values\\n    must have the same types. For example, the maximum operation is obtained by\\n    combining \\\"select\\\" with \\\"cmpi\\\" as follows:\\n\\n    ```\\n    %2 = vm.cmp.gt.i32.s %0, %1 : i32\\n    %3 = vm.select.i32 %2, %0, %1 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"true_value\", \"type\": \"F32\" },\n      { \"name\": \"false_value\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.select.f64\",\n    \"summary\": \"Floating-point select operation.\",\n    \"description\": \"Chooses one value based on a binary condition supplied as its first operand.\\n    If the value of the condition is true the `true_value` operand is chosen,\\n    otherwise the `false_value` operand is chosen. The true and false values\\n    must have the same types. For example, the maximum operation is obtained by\\n    combining \\\"select\\\" with \\\"cmpi\\\" as follows:\\n\\n    ```\\n    %2 = vm.cmp.gt.i32.s %0, %1 : i32\\n    %3 = vm.select.i32 %2, %0, %1 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"true_value\", \"type\": \"F64\" },\n      { \"name\": \"false_value\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.select.i32\",\n    \"summary\": \"Integer select operation.\",\n    \"description\": \"Chooses one value based on a binary condition supplied as its first operand.\\n    If the value of the condition is true the `true_value` operand is chosen,\\n    otherwise the `false_value` operand is chosen. The true and false values\\n    must have the same types. For example, the maximum operation is obtained by\\n    combining \\\"select\\\" with \\\"cmpi\\\" as follows:\\n\\n    ```\\n    %2 = vm.cmp.gt.i32.s %0, %1 : i32\\n    %3 = vm.select.i32 %2, %0, %1 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"true_value\", \"type\": \"I32\" },\n      { \"name\": \"false_value\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.select.i64\",\n    \"summary\": \"Integer select operation.\",\n    \"description\": \"Chooses one value based on a binary condition supplied as its first operand.\\n    If the value of the condition is true the `true_value` operand is chosen,\\n    otherwise the `false_value` operand is chosen. The true and false values\\n    must have the same types. For example, the maximum operation is obtained by\\n    combining \\\"select\\\" with \\\"cmpi\\\" as follows:\\n\\n    ```\\n    %2 = vm.cmp.gt.i32.s %0, %1 : i32\\n    %3 = vm.select.i32 %2, %0, %1 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"true_value\", \"type\": \"I64\" },\n      { \"name\": \"false_value\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.select.ref\",\n    \"summary\": \"ref<T> select operation.\",\n    \"description\": \"Chooses one value based on a binary condition supplied as its first operand.\\n    If the value of the condition is true the `true_value` operand is chosen,\\n    otherwise the `false_value` operand is chosen.\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"VM_CondValue\" },\n      { \"name\": \"true_value\", \"type\": \"VM_AnyRef\" },\n      { \"name\": \"false_value\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['true_value', 'false_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.shl.i32\",\n    \"summary\": \"Integer shift left operation.\",\n    \"description\": \"Shifts the operand in a direction by the number of bits specified.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" },\n      { \"name\": \"amount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $amount attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.shl.i64\",\n    \"summary\": \"Integer shift left operation.\",\n    \"description\": \"Shifts the operand in a direction by the number of bits specified.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" },\n      { \"name\": \"amount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $amount attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.shr.i32.s\",\n    \"summary\": \"Signed integer (arithmetic) shift right operation.\",\n    \"description\": \"Shifts the operand in a direction by the number of bits specified.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" },\n      { \"name\": \"amount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $amount attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.shr.i32.u\",\n    \"summary\": \"Unsigned integer (logical) shift right operation.\",\n    \"description\": \"Shifts the operand in a direction by the number of bits specified.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" },\n      { \"name\": \"amount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $amount attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.shr.i64.s\",\n    \"summary\": \"Signed integer (arithmetic) shift right operation.\",\n    \"description\": \"Shifts the operand in a direction by the number of bits specified.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" },\n      { \"name\": \"amount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $amount attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.shr.i64.u\",\n    \"summary\": \"Unsigned integer (logical) shift right operation.\",\n    \"description\": \"Shifts the operand in a direction by the number of bits specified.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" },\n      { \"name\": \"amount\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand `,` $amount attr-dict `:` type($operand)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sin.f32\",\n    \"summary\": \"Sine of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sin.f64\",\n    \"summary\": \"Sine of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sqrt.f32\",\n    \"summary\": \"Sqrt of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sqrt.f64\",\n    \"summary\": \"Sqrt of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sub.f32\",\n    \"summary\": \"Floating point subtraction operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F32\" },\n      { \"name\": \"rhs\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sub.f64\",\n    \"summary\": \"Floating point subtraction operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"F64\" },\n      { \"name\": \"rhs\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sub.i32\",\n    \"summary\": \"Integer subtract operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.sub.i64\",\n    \"summary\": \"Integer subtract operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.switch.f32\",\n    \"summary\": \"Floating-point switch operation.\",\n    \"description\": \"Returns the value with the given `index` in `values` or `default_value` if\\n    the index is out of bounds.\\n\\n    ```mlir\\n    // Switch %index to cases of %c100/%c200/%c300 if index==0, ==1, ==2.\\n    // If %index is out of range (<0 or >2) then default to %c5.\\n    %0 = vm.switch.f32 %index[%c100, %c200, %c300] else %c5 : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"VM_Index\" },\n      { \"name\": \"default_value\", \"type\": \"F32\" },\n      { \"name\": \"values\", \"type\": \"Variadic<F32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['default_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$index `[` $values `]` `else` $default_value attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.switch.f64\",\n    \"summary\": \"Floating-point switch operation.\",\n    \"description\": \"Returns the value with the given `index` in `values` or `default_value` if\\n    the index is out of bounds.\\n\\n    ```mlir\\n    // Switch %index to cases of %c100/%c200/%c300 if index==0, ==1, ==2.\\n    // If %index is out of range (<0 or >2) then default to %c5.\\n    %0 = vm.switch.f32 %index[%c100, %c200, %c300] else %c5 : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"VM_Index\" },\n      { \"name\": \"default_value\", \"type\": \"F64\" },\n      { \"name\": \"values\", \"type\": \"Variadic<F64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['default_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$index `[` $values `]` `else` $default_value attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.switch.i32\",\n    \"summary\": \"Integer switch operation.\",\n    \"description\": \"Returns the value with the given `index` in `values` or `default_value` if\\n    the index is out of bounds.\\n\\n    ```mlir\\n    // Switch %index to cases of %c100/%c200/%c300 if index==0, ==1, ==2.\\n    // If %index is out of range (<0 or >2) then default to %c5.\\n    %0 = vm.switch.i32 %index[%c100, %c200, %c300] else %c5 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"VM_Index\" },\n      { \"name\": \"default_value\", \"type\": \"I32\" },\n      { \"name\": \"values\", \"type\": \"Variadic<I32>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['default_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$index `[` $values `]` `else` $default_value attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.switch.i64\",\n    \"summary\": \"Integer switch operation.\",\n    \"description\": \"Returns the value with the given `index` in `values` or `default_value` if\\n    the index is out of bounds.\\n\\n    ```mlir\\n    // Switch %index to cases of %c100/%c200/%c300 if index==0, ==1, ==2.\\n    // If %index is out of range (<0 or >2) then default to %c5.\\n    %0 = vm.switch.i32 %index[%c100, %c200, %c300] else %c5 : i32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"VM_Index\" },\n      { \"name\": \"default_value\", \"type\": \"I64\" },\n      { \"name\": \"values\", \"type\": \"Variadic<I64>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['default_value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$index `[` $values `]` `else` $default_value attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.switch.ref\",\n    \"summary\": \"ref<T> switch operation.\",\n    \"description\": \"Returns the value with the given `index` in `values` or `default_value` if\\n    the index is out of bounds.\\n\\n    ```mlir\\n    // Switch %arg0 to cases of %r0/%r1/%r2 if arg0==0, ==1, ==2.\\n    // If %arg0 is out of range (<0 or >2) then default to %null.\\n    %0 = vm.switch.ref %index[%r0, %r1, %r2] else %null : vm.ref<!foo>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"index\", \"type\": \"VM_Index\" },\n      { \"name\": \"default_value\", \"type\": \"VM_AnyRef\" },\n      { \"name\": \"values\", \"type\": \"Variadic<VM_AnyRef>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"VM_AnyRef\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['default_value', 'result']>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.tanh.f32\",\n    \"summary\": \"Hyperbolic tangent of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.tanh.f64\",\n    \"summary\": \"Hyperbolic tangent of the specified value.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['operand', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trace\",\n    \"summary\": \"Trace value(s) operation.\",\n    \"description\": \"Traces one or more values at the time the operation is executed.\\n    These values will be encoded into the active trace depending on the active\\n    trace verbosity setting.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"event_name\", \"type\": \"StrAttr\" }\n    ],\n    \"assemblyFormat\": \"$event_name `(` operands `)` attr-dict `:` type(operands)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.f64.f32\",\n    \"summary\": \"Floating-point truncate to 32 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"F64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"F32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.i16.i8\",\n    \"summary\": \"Integer truncate to 8 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.i32.i16\",\n    \"summary\": \"Integer truncate to 16 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.i32.i8\",\n    \"summary\": \"Integer truncate to 8 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.i64.i16\",\n    \"summary\": \"Integer truncate to 16 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.i64.i32\",\n    \"summary\": \"Integer truncate to 32 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.trunc.i64.i8\",\n    \"summary\": \"Integer truncate to 8 bits.\",\n    \"operands\": [\n      { \"name\": \"operand\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$operand attr-dict `:` type($operand) `->` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.xor.i32\",\n    \"summary\": \"Integer binary exclusive-or operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I32\" },\n      { \"name\": \"rhs\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.xor.i64\",\n    \"summary\": \"Integer binary exclusive-or operation.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"I64\" },\n      { \"name\": \"rhs\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($result)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vm.yield\",\n    \"summary\": \"Unconditional fiber yield operation.\",\n    \"description\": \"Yields the fiber for some (likely short) amount of time. This can be used to\\n    perform cooperative scheduling and ensure fair (enough) execution. Execution\\n    resumes at the specified target branch.\\n\\n    ```\\n    ^bb0:\\n      vm.yield ^on_resume\\n    ^on_resume:\\n      ...\\n   ```\",\n    \"operands\": [\n      { \"name\": \"destOperands\", \"type\": \"Variadic<VM_AnyType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"dest\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vmvx.binary\",\n    \"summary\": \"Performs a strided elementwise operation on two same-rank buffers.\",\n    \"description\": \"Performs the operation in-place as if:\\n    ```\\n      OUT = OP(LHS, RHS)\\n    ```\\n\\n    Where `OP` is a concrete operation name as defined in ukernel/elementwise.h\",\n    \"operands\": [\n      { \"name\": \"lhs_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"lhs_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"lhs_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"rhs_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"rhs_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"rhs_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"out_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"out_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"out_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<VMVX_Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"opcode\", \"type\": \"StrAttr\" },\n      { \"name\": \"element_type\", \"type\": \"VMVX_ElementTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`op` `` `(` $opcode `:` $element_type `)`\\n    `lhs` `` `(` $lhs_buffer `offset` $lhs_offset `strides` `[` $lhs_strides `]` `:` type($lhs_buffer) `)`\\n    `rhs` `` `(` $rhs_buffer `offset` $rhs_offset `strides` `[` $rhs_strides `]` `:` type($rhs_buffer) `)`\\n    `out` `` `(` $out_buffer `offset` $out_offset `strides` `[` $out_strides `]` `:` type($out_buffer) `)`\\n    `sizes` `` `(` $sizes `)`\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vmvx.copy\",\n    \"summary\": \"Copy from one buffer to another.\",\n    \"operands\": [\n      { \"name\": \"in_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"in_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"in_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"out_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"out_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"out_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<VMVX_Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"element_type\", \"type\": \"VMVX_ElementTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`in` `` `(` $in_buffer `offset` $in_offset `strides` `[` $in_strides `]` `:` type($in_buffer) `)`\\n    `out` `` `(` $out_buffer `offset` $out_offset `strides` `[` $out_strides `]` `:` type($out_buffer) `)`\\n    `sizes` `` `(` $sizes `)`\\n    `:` $element_type\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vmvx.fill2d\",\n    \"summary\": \"Fill a tile with a scalar.\",\n    \"description\": \"Fills a tile with dimensions [m, n] with a scalar.\",\n    \"operands\": [\n      { \"name\": \"scalar\", \"type\": \"VMVX_ElementType\" },\n      { \"name\": \"out_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"out_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"out_row_stride\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"m\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"n\", \"type\": \"VMVX_Index\" }\n    ],\n    \"assemblyFormat\": \"`scalar` `` `(` $scalar `:` type($scalar) `)`\\n    `out` `` `(` $out_buffer `offset` $out_offset `row_stride` $out_row_stride `:` type($out_buffer) `)`\\n    `sizes` `` `(` $m `,` $n `)`\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vmvx.get_buffer_descriptor\",\n    \"summary\": \"Late binds a base buffer/offset/strides.\",\n    \"description\": \"Queries a base buffer, offset and strides. This op is late bound to its\\n    source (alloca, binding, etc), allowing additional layers of\\n    transformations to be added as lowering progresses (or for buffers to be\\n    combined).\\n\\n    This op has canonicalization rules which will bubble it up through the\\n    view stack. A final reconciliation pass is used explicitly to bind it to\\n    concrete sources.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"base_buffer\", \"type\": \"Util_BufferType\" },\n      { \"name\": \"offset\", \"type\": \"Index\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"assemblyFormat\": \"$source `:` type($source) `->` type(results) attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vmvx.get_raw_interface_binding_buffer\",\n    \"summary\": \"Gets the raw buffer associated with a binding.\",\n    \"description\": \"Normally, a slice of a binding buffer is returned via\\n    hal.interface.binding.subspan. However, the normal VMVX lowering flow for\\n    this presumes that the result is a memref, and upon final conversion, it\\n    will offset the memref automatically to make it consistent.\\n\\n    This op is used in situations where earlier in a lowering, we have fully\\n    resolved the binding to a buffer and would just like the raw backing\\n    buffer as passed to the interface.\",\n    \"results\": [\n      { \"name\": \"buffer\", \"type\": \"Util_BufferType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout\", \"type\": \"HAL_PipelineLayoutAttr\" },\n      { \"name\": \"binding\", \"type\": \"IndexAttr\" }\n    ],\n    \"assemblyFormat\": \"`layout` `(` $layout `)`\\n    `binding` `(` $binding `)`\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"vmvx.unary\",\n    \"summary\": \"Performs a strided elementwise unary operation.\",\n    \"description\": \"Performs the operation in-place as if:\\n    ```\\n      OUT = OP(IN)\\n    ```\\n\\n    Where `OP` is a concrete operation name as defined in ukernel/elementwise.h\",\n    \"operands\": [\n      { \"name\": \"in_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"in_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"in_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"out_buffer\", \"type\": \"VMVX_Buffer\" },\n      { \"name\": \"out_offset\", \"type\": \"VMVX_Index\" },\n      { \"name\": \"out_strides\", \"type\": \"Variadic<VMVX_Index>\" },\n      { \"name\": \"sizes\", \"type\": \"Variadic<VMVX_Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"opcode\", \"type\": \"StrAttr\" },\n      { \"name\": \"element_type\", \"type\": \"VMVX_ElementTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`op` `` `(` $opcode `:` $element_type `)`\\n    `in` `` `(` $in_buffer `offset` $in_offset `strides` `[` $in_strides `]` `:` type($in_buffer) `)`\\n    `out` `` `(` $out_buffer `offset` $out_offset `strides` `[` $out_strides `]` `:` type($out_buffer) `)`\\n    `sizes` `` `(` $sizes `)`\\n    attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"wasmssa.abs\",\n    \"summary\": \"Floating point absolute value\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.abs %b : f32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.add\",\n    \"summary\": \"Sum two values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.add %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.and\",\n    \"summary\": \"Compute the bitwise AND between two values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.and %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.block\",\n    \"summary\": \"Create a nesting level with a label at its exit.\",\n    \"description\": \"Defines a Wasm block, creating a new nested scope.\\n  A block contains a body region and an optional list of input values.\\n  Control can enter the block and later branch out to the block target.\\n  Example:\\n\\n  ```mlir\\n  wasmssa.block {\\n\\n    // instructions\\n\\n  } > ^successor\\n  ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"target\", \"type\": \"AnySuccessor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"(`(`$inputs^`)` `:` type($inputs))? attr-dict  `:` $body `>` $target\"\n  },\n  {\n    \"name\": \"wasmssa.block_return\",\n    \"summary\": \"Return from the current block\",\n    \"description\": \"Escape from the current nesting level and return the control flow to its successor.\\n    Optionally, mark the arguments that should be transfered to the successor block.\\n\\n    This shouldn't be confused with branch operations that targets the label defined\\n    by the nesting level operation.\\n\\n    For instance, a `wasmssa.block_return` in a loop will give back control to the\\n    successor of the loop, where a `branch` targeting the loop will flow back to the entry block of the loop.\\n\\n    Example:\\n\\n    ```mlir\\n    wasmssa.block_return\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"assemblyFormat\": \"($inputs^ `:` type($inputs))? attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.branch_if\",\n    \"summary\": \"Jump to target level if condition has non-zero value\",\n    \"description\": \"Jump to target level if the condition is has a non-zero value.\\n\\n     Example:\\n\\n     ```mlir\\n     wasmssa.branch_if %a to level 0 with args(%b : i32) else ^bb1\\n     ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I32\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exitLevel\", \"type\": \"UI32Attr\" }\n    ],\n    \"successors\": [\n      { \"name\": \"elseSuccessor\", \"type\": \"AnySuccessor\" }\n    ],\n    \"assemblyFormat\": \"$condition `to` `level` $exitLevel (`with` `args`  `(`$inputs^ `:` type($inputs)`)`)?  `else` $elseSuccessor  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.call\",\n    \"summary\": \"Calling a Wasm function\",\n    \"description\": \"Emits a call to a defined function\\n\\n     Example:\\n\\n     ```mlir\\n     %a = wasmssa.call @func_0 : () -> i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee (`(`$operands^`)`)? attr-dict `:` functional-type($operands, $results)\"\n  },\n  {\n    \"name\": \"wasmssa.ceil\",\n    \"summary\": \"Ceil rounding of floating point value\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.ceil %b : f32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.clz\",\n    \"summary\": \"Count leading zeroes of an integer\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.clz %b : i32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.const\",\n    \"summary\": \"Operator that represents a constant value\",\n    \"description\": \"Defines a constant value.\\n\\n     Example:\\n\\n     ```mlir\\n     // Example of integer constant\\n     %a = wasmssa.const 1 : i32\\n\\n     // Example of floating point constant\\n     %b = wasmssa.const 9.000000e+00 : f64\\n     ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_NumericType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\", \"type\": \"TypedAttrInterface\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['value', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$value attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.convert_s\",\n    \"summary\": \"Convert integer interpreted as 2's complement signed value to floating-point value.\\n\\n    Consume an integer and produces a floating point value containing the rounded value of the original operand. Rounding is round to nearest, tie to even.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.convert_s %b : i32 to f64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($input) `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.convert_u\",\n    \"summary\": \"Convert integer, interpreted as binary encoded positive value, to floating-point value.\\n\\n    Consume an integer and produces a floating point value containing the rounded value of the original operand. Rounding is round to nearest, tie to even.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.convert_u %b : i32 to f64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($input) `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.copysign\",\n    \"summary\": \"Copy sign from one floating point value to the other.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.copysign %b %c : f32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.ctz\",\n    \"summary\": \"Count trailing zeroes of an integer\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.ctz %b : i32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.demote\",\n    \"summary\": \"Convert a f64 value to f32\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.demote %b : f64 to f32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[F64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[F32]>\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($input) `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.div\",\n    \"summary\": \"Division between floating point values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.div %b %c : f32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.div_si\",\n    \"summary\": \"Divide values interpreted as signed int\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.div_si %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.div_ui\",\n    \"summary\": \"Divide values interpreted as unsigned int\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.div_ui %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.eq\",\n    \"summary\": \"Check if two values are equal\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.eq %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.eqz\",\n    \"summary\": \"Check if the given value is equal to zero\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.eqz %b : i64 -> i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"assemblyFormat\": \"$input`:` type($input) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.extend\",\n    \"description\": \"Extend low bytes of a value to fit a given width.\\n  For instance, signed extension from 8 low bits of the 32-bits integer value\\n  254 (0x000000FE) would produce the value -2 (0xFFFFFFFE).\\n\\n  This corresponds to the `extendnn` instruction of Wasm, which shouldn't be\\n  confused with the `extend_inn` Wasm instruction, for which all input bits\\n  are used and widened to wider output type.\\n  In this operation, input and output types are the same.\\n\\n  Example:\\n\\n  ```mlir\\n  %a = wasmssa.extend 16 low bits from %[[VAL_0]]: i64\\n  ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bitsToTake\", \"type\": \"Builtin_IntegerAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['input', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$bitsToTake `low` `bits` `from` $input `:` type($input) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.extend_i32_s\",\n    \"summary\": \"Sign extend i32 to i64.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.extend_i32_s %b to i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$input `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.extend_i32_u\",\n    \"summary\": \"Zero extend i32 to i64.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.extend_i32_s %b to i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I64\" }\n    ],\n    \"assemblyFormat\": \"$input `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.floor\",\n    \"summary\": \"Floor rounding of floating point value\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.floor %b : f32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.func\",\n    \"description\": \"Represents a Wasm function definition.\\n\\n    In Wasm function, locals and function arguments are interchangeable.\\n    They are for instance both accessed using `local.get` instruction.\\n\\n    On the other hand, a function type is defined as a pair of tuples of Wasm value types.\\n    To model this, the wasm.func operation has:\\n\\n    - A function type that represents the corresponding Wasm type (tuples of value types)\\n\\n    - Arguments of the entry block of type `!wasm<local T>`, with T the corresponding type\\n     in the function type.\\n\\n    By default, `wasmssa.func` have nested visibility. Functions exported by the module\\n    are marked with the exported attribute. This gives them public visibility.\\n\\n     Example:\\n\\n     ```mlir\\n     // Internal function with no arguments that returns a float32\\n     wasmssa.func @my_f32_func() -> f32\\n\\n     // Exported function with no arguments that returns a float32\\n     wasmssa.func exported @my_f32_func() -> f32\\n\\n     // A function that takes a local ref argument\\n     wasmssa.func @i64_wrap(%a: !wasmssa<local ref to i64>) -> i32\\n     ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"functionType\", \"type\": \"WasmSSA_FuncTypeAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"exported\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"wasmssa.ge\",\n    \"summary\": \"Check if a float value is greater or equal to another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.ge %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.ge_si\",\n    \"summary\": \"Check if a signed integer value is greater or equal to another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.ge_si %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.ge_ui\",\n    \"summary\": \"Check if an unsigned integer value is greater or equal to another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.ge_ui %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.global\",\n    \"summary\": \"WebAssembly global value\",\n    \"description\": \"WebAssembly global variable.\\n    Body contains the initialization instructions for the variable value.\\n    The body must contain only instructions considered `const` in a webassembly context,\\n    such as `wasmssa.const` or `global.get`.\\n\\n    By default, `wasmssa.global` have nested visibility. Global exported by the module\\n    are marked with the exported attribute. This gives them public visibility.\\n\\n    Example:\\n\\n    ```mlir\\n    // Define module_global_var, an internal mutable i32 global variable equal to 10.\\n    wasmssa.global @module_global_var i32 mutable : {\\n          %[[VAL_0:.*]] = wasmssa.const 10 : i32\\n          wasmssa.return %[[VAL_0]] : i32\\n    }\\n\\n    // Define global_var, an exported constant i32 global variable equal to 42.\\n    wasmssa.global @global_var i32 : {\\n          %[[VAL_0:.*]] = wasmssa.const 42 : i32\\n          wasmssa.return %[[VAL_0]] : i32\\n    }\\n    ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"WasmSSA_ValTypeAttr\" },\n      { \"name\": \"isMutable\", \"type\": \"UnitAttr\" },\n      { \"name\": \"exported\", \"type\": \"UnitAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"initializer\", \"type\": \"AnyRegion\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"wasmssa.global_get\",\n    \"summary\": \"Returns the value of the global passed as argument.\",\n    \"description\": \"Retrieves the value of the global passed as argument and stores it in a\\n     variable\\n\\n     Example:\\n\\n     ```mlir\\n     // Gets the value of `@global_0` and stores its value in %a\\n     %a = wasmssa.global_get @global_0 : i32\\n     ```\",\n    \"results\": [\n      { \"name\": \"global_val\", \"type\": \"WasmSSA_ValType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"global\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$global attr-dict `:` type($global_val)\"\n  },\n  {\n    \"name\": \"wasmssa.gt\",\n    \"summary\": \"Check if a float value is greater than another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.gt %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.gt_si\",\n    \"summary\": \"Check if a signed integer value is greater than another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.gt_si %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.gt_ui\",\n    \"summary\": \"Check if an unsigned integer value is greater than another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.gt_ui %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.if\",\n    \"summary\": \"Execute the if region if condition value is non-zero, the else region otherwise.\",\n    \"description\": \"Execute the if region if the condition is non-zero. Otherwise the else region is executed.\\n    The else region can be empty but must return the same datatype as the if region.\\n    If clauses can be nested.\\n\\n     Example:\\n\\n     ```mlir\\n     // Runs the if clause is %a is non-zero\\n     wasmssa.if %a {\\n        // Execute if %a is non-zero\\n     } else {\\n        // else clause\\n     }\\n     ```\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I32\" },\n      { \"name\": \"inputs\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"target\", \"type\": \"AnySuccessor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"if\", \"type\": \"AnyRegion\" },\n      { \"name\": \"else\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"$condition (`(`$inputs^`)` `:` type($inputs))? attr-dict  `:` $if custom<ElseRegion>($else) `>` $target\"\n  },\n  {\n    \"name\": \"wasmssa.import_func\",\n    \"summary\": \"Importing a function variable\",\n    \"description\": \"Imports a function from another module\\n\\n     Example:\\n\\n     ```mlir\\n     // Imports foo(i32) -> () from the module my_module\\n     wasmssa.import_func \\\"foo\\\" from \\\"my_module\\\" as @func_0 {sym_visibility = \\\"nested\\\", type = (i32) -> ()}\\n     ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"moduleName\", \"type\": \"StrAttr\" },\n      { \"name\": \"importName\", \"type\": \"StrAttr\" },\n      { \"name\": \"type\", \"type\": \"WasmSSA_FuncTypeAttr\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" }\n    ],\n    \"assemblyFormat\": \"$importName `from` $moduleName `as` $sym_name attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.import_global\",\n    \"summary\": \"Importing a global variable\",\n    \"description\": \"Imports a global from another module\\n\\n     Example:\\n\\n     ```mlir\\n     // Imports the \\\"glob\\\" i32 global from the module my_module as \\\"global_0\\\"\\n     wasmssa.import_global \\\"glob\\\" from \\\"my_module\\\" as @global_0 nested : i32\\n     ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"moduleName\", \"type\": \"StrAttr\" },\n      { \"name\": \"importName\", \"type\": \"StrAttr\" },\n      { \"name\": \"type\", \"type\": \"WasmSSA_ValTypeAttr\" },\n      { \"name\": \"isMutable\", \"type\": \"UnitAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"wasmssa.import_mem\",\n    \"summary\": \"Importing a memory\",\n    \"description\": \"Import a memory from another module.\\n\\n     Example:\\n\\n     ```mlir\\n     // Import the memory `mem` from `my_module` as @mem_0\\n     wasmssa.import_mem \\\"mem\\\" from \\\"my_module\\\" as @mem_0 {limits = !wasmssa<limit[2:]>}\\n     ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"moduleName\", \"type\": \"StrAttr\" },\n      { \"name\": \"importName\", \"type\": \"StrAttr\" },\n      { \"name\": \"limits\", \"type\": \"WasmSSA_LimitTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$importName `from` $moduleName `as` $sym_name attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.import_table\",\n    \"summary\": \"Importing a table\",\n    \"description\": \"Import a table from another module.\\n\\n     Example:\\n\\n     ```mlir\\n     // Import the table `table` from `my_module` as @table_0\\n     wasmssa.import_table \\\"table\\\" from \\\"my_module\\\" as @table_0 {type = !wasmssa<tabletype !wasmssa.funcref [2:]>}\\n     ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"moduleName\", \"type\": \"StrAttr\" },\n      { \"name\": \"importName\", \"type\": \"StrAttr\" },\n      { \"name\": \"type\", \"type\": \"WasmSSA_TableTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$importName `from` $moduleName `as` $sym_name attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.le\",\n    \"summary\": \"Check if a float value is less or equal to another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.le %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.le_si\",\n    \"summary\": \"Check if a signed integer value is less or equal to another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.le_si %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.le_ui\",\n    \"summary\": \"Check if an unsigned integer value is less or equal to another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.le_ui %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.local\",\n    \"summary\": \"Declaration of local variable\",\n    \"description\": \"Declares a local variable\\n\\n     Example:\\n\\n     ```mlir\\n     // Declares `%a`, a float32 local\\n     %a = wasmssa.local of type f32\\n     ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_LocalRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"WasmSSA_ValTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"`of` `type` $type attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.local_get\",\n    \"summary\": \"Set local to value and return the operand.\",\n    \"description\": \"Gets the value of a local variable and returns a reference to it.\\n\\n     Example:\\n\\n     ```mlir\\n     // Retrieves a reference to `%a`, a float32 local\\n     %b = wasmssa.local_get %a : ref to f32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"localVar\", \"type\": \"WasmSSA_LocalRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_ValType\" }\n    ],\n    \"assemblyFormat\": \"$localVar `:` type($localVar) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.local_set\",\n    \"summary\": \"Set local to given value\",\n    \"description\": \"Sets the value of a local variable.\\n\\n     Example:\\n\\n     ```mlir\\n     // Sets `%d`, to the value of `%c`\\n     wasmssa.local_set %d :  ref to i32 to %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"localVar\", \"type\": \"WasmSSA_LocalRef\" },\n      { \"name\": \"value\", \"type\": \"WasmSSA_ValType\" }\n    ],\n    \"assemblyFormat\": \"$localVar `:` type($localVar) `to` $value `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.local_tee\",\n    \"summary\": \"Set local to value and return the operand.\",\n    \"description\": \"Sets the value of a local variable and returns it.\\n\\n     Example:\\n\\n     ```mlir\\n     // Sets `%b`, to the value of `%c` and returns it in %a\\n      %a = wasmssa.local_tee %b :  ref to i32 to %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"localVar\", \"type\": \"WasmSSA_LocalRef\" },\n      { \"name\": \"value\", \"type\": \"WasmSSA_ValType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_ValType\" }\n    ],\n    \"assemblyFormat\": \"$localVar `:` type($localVar) `to` $value `:` type($value) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.loop\",\n    \"summary\": \"Create a nesting level that define its entry as jump target.\",\n    \"description\": \"Represents a Wasm loop construct. This defines a nesting level with\\n  a label at the entry of the region.\\n\\n  Example:\\n\\n  ```mlir\\n  wasmssa.loop {\\n\\n  } > ^successor\\n  ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"successors\": [\n      { \"name\": \"target\", \"type\": \"AnySuccessor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"AnyRegion\" }\n    ],\n    \"assemblyFormat\": \"(`(`$inputs^`)` `:` type($inputs))? attr-dict  `:` $body `>` $target\"\n  },\n  {\n    \"name\": \"wasmssa.lt\",\n    \"summary\": \"Check if a float value is less than another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.lt %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.lt_si\",\n    \"summary\": \"Check if a signed integer value is less than another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.lt_si %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.lt_ui\",\n    \"summary\": \"Check if an unsigned integer value is less than another\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.lt_ui %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.max\",\n    \"summary\": \"Compute the minimum of two floating point values.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.max %b %c : f32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.memory\",\n    \"summary\": \"WebAssembly memory definition\",\n    \"description\": \"Define a memory to be used by the program.\\n    Multiple memories can be defined in the same module.\\n\\n    By default, `wasmssa.memory` have nested visibility. Memory exported by\\n    the module are marked with the exported attribute. This gives them public\\n    visibility.\\n\\n     Example:\\n\\n     ```mlir\\n     // Define the `mem_0` (internal)  memory with defined size bounds of [0:65536]\\n     wasmssa.memory @mem_0 !wasmssa<limit[0:65536]>\\n\\n     // Define the `mem_1` exported  memory with minimal size of 512\\n     wasmssa.memory exported @mem_1 !wasmssa<limit[512:]>\\n     ```\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"limits\", \"type\": \"WasmSSA_LimitTypeAttr\" },\n      { \"name\": \"exported\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`exported` $exported^)? $sym_name $limits attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.min\",\n    \"summary\": \"Compute the minimum of two floating point values.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.min %b %c : f32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.mul\",\n    \"summary\": \"Multiply two values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.mul %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.ne\",\n    \"summary\": \"Check if two values are different\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.ne %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.neg\",\n    \"summary\": \"Floating point negation\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.neg %b : f32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.or\",\n    \"summary\": \"Compute the bitwise OR of two values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.or %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.popcnt\",\n    \"summary\": \"Population count of an integer.\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.popcnt %b : i32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.promote\",\n    \"summary\": \"Get f64 representation of a f32 value.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.promote %b : f32 to f64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[Builtin_Float32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[Builtin_Float64]>\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($input) `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.reinterpret\",\n    \"summary\": \"Reinterpret the value represented by a bit vector by\\n      bit-casting it to another type of same representation width.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.reinterpret %b : f32 as i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($input) `as` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.rem_si\",\n    \"summary\": \"Calculate the remainder of dividing two integer values as signed integer\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.rem_si %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.rem_ui\",\n    \"summary\": \"Calculate the remainder of dividing two integer values as an unsigned integer\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.rem_ui %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_IntegerType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.return\",\n    \"summary\": \"Return from the current function frame\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<WasmSSA_ValType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"wasmssa.rotl\",\n    \"summary\": \"Rotate left.\\n\\n    Consume an integer and an integer rotate. The first\\n    integer shall be rotated left by N bits, where N is the value of the\\n    second integer.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.rotl %b by %c bits : i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"WasmSSA_IntegerType\" },\n      { \"name\": \"bits\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['val', 'bits', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$val `by` $bits `bits` `:` type($val) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.rotr\",\n    \"summary\": \"Rotate right.\\n\\n    Consume an integer, and an integer rotate. The first\\n    integer shall be rotated right by N bits, where N is the value of the\\n    second integer.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.rotr %b by %c bits : i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"WasmSSA_IntegerType\" },\n      { \"name\": \"bits\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['val', 'bits', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$val `by` $bits `bits` `:` type($val) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.shl\",\n    \"summary\": \"Consume an integer and an integer shift amount. The first\\n    integer shall be shifted left by N bits, where N is the value of the second\\n    integer.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.shl %b by %c bits : i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"WasmSSA_IntegerType\" },\n      { \"name\": \"bits\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['val', 'bits', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$val `by` $bits `bits` `:` type($val) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.shr_s\",\n    \"summary\": \"Arithmetic right shift.\\n\\n    Consume an integer and an integer shift amount. The first\\n    integer shall be shifted right by N bits, where N is the value of the\\n    second integer.\\n\\n    Vacated bits on the left shall be filled with the sign bit.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.shr_s %b by %c bits : i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"WasmSSA_IntegerType\" },\n      { \"name\": \"bits\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['val', 'bits', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$val `by` $bits `bits` `:` type($val) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.shr_u\",\n    \"summary\": \"Logical right shift.\\n\\n    Consume an integer, and an integer shift amount. The first\\n    integer shall be shifted right by N bits, where N is the value of the\\n    second integer.\\n\\n    Vacated bits on the left shall be filled with zeroes.\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.shr_u %b by %c bits : i64\\n     ```\",\n    \"operands\": [\n      { \"name\": \"val\", \"type\": \"WasmSSA_IntegerType\" },\n      { \"name\": \"bits\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"WasmSSA_IntegerType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['val', 'bits', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$val `by` $bits `bits` `:` type($val) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.sqrt\",\n    \"summary\": \"Floating point square root\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.sqrt %b : f32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.sub\",\n    \"summary\": \"Subtract two values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.sub %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.table\",\n    \"summary\": \"WebAssembly table value\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"type\", \"type\": \"WasmSSA_TableTypeAttr\" },\n      { \"name\": \"exported\", \"type\": \"UnitAttr\" }\n    ],\n    \"assemblyFormat\": \"(`exported` $exported^)? $sym_name $type attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.trunc\",\n    \"summary\": \"Trunc of floating point value\",\n    \"description\": \"Example:\\n\\n                                         ```mlir\\n                                         %a = wasmssa.trunc %b : f32\\n                                         ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_FPType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$src`:` type($src) attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.wrap\",\n    \"summary\": \"Cast an i64 to i32 by using a wrapping mechanism: y = x mod 2^32\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.wrap %b : i64 to i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTypeOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[I32]>\" }\n    ],\n    \"assemblyFormat\": \"$input `:` type($input) `to` type($result)  attr-dict\"\n  },\n  {\n    \"name\": \"wasmssa.xor\",\n    \"summary\": \"Compute the bitwise XOR of two values\",\n    \"description\": \"Example:\\n\\n     ```mlir\\n     %a = wasmssa.xor %b %c : i32\\n     ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" },\n      { \"name\": \"rhs\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyTypeOf<[WasmSSA_NumericType]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['lhs', 'rhs', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs $rhs `:` type($lhs) attr-dict\"\n  },\n  {\n    \"name\": \"x86.amx.tile_load\",\n    \"summary\": \"tile load operation\",\n    \"description\": \"Loads a tile from memory defined by a `base` and `indices`, with the\\n    shape defined by the 2-dim vector type of the result.\\n    The tile's rows are populated by reading contiguous elements starting\\n    at the `base`. For each tile row, the `base` is incremented by `stride`\\n    number of elements.\\n\\n    The tile is loaded using the following indexing scheme:\\n\\n    ```\\n    for row in enumerate(tile_rows):\\n      mem_row = base[i0, i1, ..., iN + row * stride]\\n      for col in enumerate(tile_cols):\\n        tile[row, col] = mem_row[col]\\n    ```\\n\\n    If the `stride` is not provided, then the `base` buffer must be at least\\n    2-dimensional, and the `stride` is automatically inferred and corresponds\\n    to the stride of the buffer's second innermost dimension.\\n\\n    The operation is eventually lowered into the \\\"tileloadd\\\" instruction\\n    with the corresponding tile configuration.\\n\\n    With the write memory effect, each `x86.amx.tile_load` operation serves as\\n    a compilation hint to use a separate tile register.\\n\\n    Example:\\n\\n    ```mlir\\n      // Tile load from a 2-D memref with implicit stride.\\n      %0 = x86.amx.tile_load %arg0[%c0, %c0] : memref<?x?xi8> into !x86.amx.tile<16x64xi8>\\n\\n      // Tile load from a 1-D memref with explicit stride.\\n      %0 = x86.amx.tile_load %arg0[%c0], %stride : memref<?xi8> into !x86.amx.tile<16x64xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"stride\", \"type\": \"Optional<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyAMXTile\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` (`,` $stride^ )? attr-dict`:` type($base) `into` qualified(type($res))\"\n  },\n  {\n    \"name\": \"x86.amx.tile_mulf\",\n    \"summary\": \"tile multiplication operation (floating-point)\",\n    \"description\": \"Multiplies a \\\"m x k\\\" tile with a \\\"k x n\\\" tile and accumulates the results\\n    into a \\\"m x n\\\" destination tile. Supports \\\"f32 <- bf16 x bf16\\\" (with\\n    pairs of \\\"bf16\\\").\\n    \\n    The operation is eventually lowered into the \\\"tdpbf16ps\\\" instruction with\\n    the corresponding tile configuration.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = x86.amx.tile_mulf %a, %b, %c\\n        : !x86.amx.tile<16x32xbf16>, !x86.amx.tile<16x32xbf16>, !x86.amx.tile<16x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AMXTileF16OrBF16\" },\n      { \"name\": \"rhs\", \"type\": \"AMXTileF16OrBF16\" },\n      { \"name\": \"acc\", \"type\": \"AMXTileF32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AMXTileF32\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs `,` $acc attr-dict `:` qualified(type($lhs)) `,` qualified(type($rhs)) `,` qualified(type($acc))\"\n  },\n  {\n    \"name\": \"x86.amx.tile_muli\",\n    \"summary\": \"tile multiplication operation (integer)\",\n    \"description\": \"Multiplies a \\\"m x k\\\" tile with a \\\"k x n\\\" tile and accumulates the results\\n    into a \\\"m x n\\\" destination tile. Supports all \\\"si32 <- s/ui8 x s/ui8\\\"\\n    combinations (4 bytes packed into dwords in the columns of both the\\n    source operand tiles; the zero or sign extension is specified with\\n    the attributes and default to sign extended).\\n    \\n    The operation is eventually lowered into one of the \\\"tdpbssd\\\",\\n    \\\"tdpbsud\\\", \\\"tdpbusd\\\", or \\\"tdpbuud\\\" instructions with the corresponding\\n    tile configuration.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = x86.amx.tile_muli %a zext, %b zext, %c\\n        : !x86.amx.tile<16x64xi8>, !x86.amx.tile<16x64xi8>, !x86.amx.tile<16x16xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"AMXTileI8\" },\n      { \"name\": \"rhs\", \"type\": \"AMXTileI8\" },\n      { \"name\": \"acc\", \"type\": \"AMXTileI32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AMXTileI32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"isZextLhs\", \"type\": \"UnitAttr\" },\n      { \"name\": \"isZextRhs\", \"type\": \"UnitAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['acc', 'res']>\" }\n    ],\n    \"assemblyFormat\": \"$lhs (`zext` $isZextLhs^)? `,` $rhs (`zext` $isZextRhs^)? `,` $acc attr-dict `:` qualified(type($lhs)) `,` qualified(type($rhs)) `,` qualified(type($acc))\"\n  },\n  {\n    \"name\": \"x86.amx.tile_store\",\n    \"summary\": \"tile store operation\",\n    \"description\": \"Stores a tile to memory defined by a `base` and `indices`, with the\\n    shape defined by the 2-dim vector type of the value.\\n    The tile's rows are written contiguously to the buffer starting at\\n    the `base`. For each tile row, the `base` is incremented by `stride`\\n    number of elements.\\n\\n    The tile is stored using the following indexing scheme:\\n\\n    ```\\n    for row in enumerate(tile_rows):\\n      mem_row = base[i0, i1, ..., iN + row * stride]\\n      for col in enumerate(tile_cols):\\n        mem_row[col] = tile[row, col]\\n    ```\\n\\n    If the `stride` is not provided, then the `base` buffer must be at least\\n    2-dimensional, and the `stride` is automatically inferred and corresponds\\n    to the stride of the buffer's second innermost dimension.\\n\\n    The operation is eventually lowered into the \\\"tilestored\\\" instruction\\n    with the corresponding tile configuration.\\n\\n    Example:\\n\\n    ```mlir\\n      // Tile store to a 2-D memref with implicit stride.\\n      x86.amx.tile_store %arg1[%c0, %c0], %0 : memref<?x?xi8>, !x86.amx.tile<16x64xi8>\\n\\n      // Tile store to a 1-D memref with explicit stride.\\n      x86.amx.tile_store %arg1[%c0], %0, %stride : memref<?xi8>, !x86.amx.tile<16x64xi8>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"base\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"val\", \"type\": \"AnyAMXTile\" },\n      { \"name\": \"stride\", \"type\": \"Optional<Index>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$base `[` $indices `]` `,` $val (`,` $stride^ )?attr-dict `:` type($base) `,` qualified(type($val))\"\n  },\n  {\n    \"name\": \"x86.amx.tile_zero\",\n    \"summary\": \"tile zero operation\",\n    \"description\": \"Zeroes the destination tile, with the shape defined by the 2-dim\\n    vector type of the result.\\n    \\n    The operation is eventually lowered into the \\\"tilezero\\\" instruction\\n    with the corresponding tile configuration.\\n    \\n    With the write memory effect, each `x86.amx.tile_zero` operation serves as\\n    a compilation hint to use a separate tile register.\\n\\n    Example:\\n\\n    ```mlir\\n      %0 = x86.amx.tile_zero : !x86.amx.tile<16x16xbf16>\\n    ```\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyAMXTile\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` qualified(type($res))\"\n  },\n  {\n    \"name\": \"x86.avx.bcst_to_f32.packed\",\n    \"summary\": \"AVX: Broadcasts BF16/F16 into packed F32 Data.\",\n    \"description\": \"#### From the Intel Intrinsics Guide:\\n\\n    Convert scalar BF16 or F16 (16-bit) floating-point element stored at memory locations\\n    starting at location `__A` to a single-precision (32-bit) floating-point,\\n    broadcast it to packed single-precision (32-bit) floating-point elements,\\n    and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx.bcst_to_f32.packed %a : memref<1xbf16> -> vector<8xf32>\\n    %dst = x86.avx.bcst_to_f32.packed %a : memref<1xf16> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MemRefOf<[BF16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [F32]>\" }\n    ],\n    \"assemblyFormat\": \"$a  attr-dict`:` type($a)`->` type($dst)\"\n  },\n  {\n    \"name\": \"x86.avx.cvt.packed.even.indexed_to_f32\",\n    \"summary\": \"AVX: Convert packed BF16/F16 even-indexed elements into packed F32 Data.\",\n    \"description\": \"#### From the Intel Intrinsics Guide:\\n\\n    Convert packed BF16 or F16 (16-bit) floating-point even-indexed elements stored at\\n    memory locations starting at location `__A` to packed single-precision\\n    (32-bit) floating-point elements, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx.cvt.packed.even.indexed_to_f32 %a : memref<16xbf16> -> vector<8xf32>\\n    %dst = x86.avx.cvt.packed.even.indexed_to_f32 %a : memref<16xf16> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MemRefOf<[BF16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [F32]>\" }\n    ],\n    \"assemblyFormat\": \"$a  attr-dict`:` type($a)`->` type($dst)\"\n  },\n  {\n    \"name\": \"x86.avx.cvt.packed.odd.indexed_to_f32\",\n    \"summary\": \"AVX: Convert packed BF16/F16 odd-indexed elements into packed F32 Data.\",\n    \"description\": \"#### From the Intel Intrinsics Guide:\\n\\n    Convert packed BF16 or F16 (16-bit) floating-point odd-indexed elements stored at\\n    memory locations starting at location `__A` to packed single-precision\\n    (32-bit) floating-point elements, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx.cvt.packed.odd.indexed_to_f32 %a : memref<16xbf16> -> vector<8xf32>\\n    %dst = x86.avx.cvt.packed.odd.indexed_to_f32 %a : memref<16xf16> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MemRefOf<[BF16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [F32]>\" }\n    ],\n    \"assemblyFormat\": \"$a  attr-dict`:` type($a)`->` type($dst)\"\n  },\n  {\n    \"name\": \"x86.avx.dot.i8\",\n    \"summary\": \"Dot Int8 op\",\n    \"description\": \"The `dot` op is an AVX2-Int8 specific op that can lower to the proper\\n    LLVMAVX2-INT8 operation `llvm.vpdpbssd` depending on the width of MLIR\\n    vectors it is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Multiply groups of 4 adjacent pairs of signed 8-bit integers in `a` with \\n    corresponding signed 8-bit integers in `b`, producing 4 intermediate signed 16-bit \\n    results. Sum these 4 results with the corresponding 32-bit integer in `w`, and \\n    store the packed 32-bit results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx.dot.i8 %w, %a, %b : vector<32xi8> -> vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"w\", \"type\": \"VectorOfLengthAndType<[4, 8], [I32]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 32], [I8]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 32], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"AllTypesMatch<['w', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'w', 'a', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$w `,` $a `,` $b attr-dict `:` type($a) `->` type($w)\"\n  },\n  {\n    \"name\": \"x86.avx.intr.dot\",\n    \"summary\": \"Dot\",\n    \"description\": \"Computes the 4-way dot products of the lower and higher parts of the source\\n    vectors and broadcasts the two results to the lower and higher elements of\\n    the destination vector, respectively. Adding one element of the lower part\\n    to one element of the higher part in the destination vector yields the full\\n    dot product of the two source vectors.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = x86.avx.intr.dot %a, %b : vector<8xf32>\\n    %1 = vector.extract %0[%i0] : f32 from vector<8xf32>\\n    %2 = vector.extract %0[%i4] : f32 from vector<8xf32>\\n    %d = arith.addf %1, %2 : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"x86.avx.rsqrt\",\n    \"summary\": \"Rsqrt\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$a attr-dict `:` type($a)\"\n  },\n  {\n    \"name\": \"x86.avx10.dot.i8\",\n    \"summary\": \"AVX10 Dot Int8 op\",\n    \"description\": \"The `dot` op is an AVX10-Int8 specific op that can lower to the proper\\n    LLVMAVX10-INT8 operation `llvm.vpdpbssd.512`.\\n\\n    Multiply groups of 4 adjacent pairs of signed 8-bit integers in `a` with\\n    corresponding signed 8-bit integers in `b`, producing 4 intermediate signed 16-bit\\n    results. Sum these 4 results with the corresponding 32-bit integer in `w`, and\\n    store the packed 32-bit results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx10.dot.i8 %w, %a, %b : vector<64xi8> -> vector<16xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"w\", \"type\": \"VectorOfLengthAndType<[16], [I32]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[64], [I8]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[64], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"AllTypesMatch<['w', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'w', 'a', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$w `,` $a `,` $b attr-dict `:` type($a) `->` type($w)\"\n  },\n  {\n    \"name\": \"x86.avx512.cvt.packed.f32_to_bf16\",\n    \"summary\": \"Convert packed F32 to packed BF16 Data.\",\n    \"description\": \"The `convert_f32_to_bf16` op is an AVX512-BF16 specific op that can lower\\n    to the proper LLVMAVX512BF16 operation `llvm.cvtneps2bf16` depending on\\n    the width of MLIR vectors it is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Convert packed single-precision (32-bit) floating-point elements in `a` to\\n    packed BF16 (16-bit) floating-point elements, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx512.cvt.packed.f32_to_bf16 %a : vector<8xf32> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8, 16], [F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[8, 16], [BF16]>\" }\n    ],\n    \"assemblyFormat\": \"$a attr-dict `:` type($a) `->` type($dst)\"\n  },\n  {\n    \"name\": \"x86.avx512.dot\",\n    \"summary\": \"Dot BF16 op\",\n    \"description\": \"The `dot` op is an AVX512-BF16 specific op that can lower to the proper\\n    LLVMAVX512BF16 operation `llvm.dpbf16ps` depending on the width of MLIR\\n    vectors it is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Compute dot-product of BF16 (16-bit) floating-point pairs in `a` and `b`,\\n    accumulating the intermediate single-precision (32-bit) floating-point\\n    elements with elements in `src`, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86.avx512.dot %src, %a, %b : vector<32xbf16> -> vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[4, 8, 16], [F32]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8, 16, 32], [BF16]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8, 16, 32], [BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8, 16], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"AllTypesMatch<['src', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'src', 'a', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $a `,` $b attr-dict `:` type($a) `->` type($src)\"\n  },\n  {\n    \"name\": \"x86.avx512.mask.compress\",\n    \"summary\": \"Masked compress op\",\n    \"description\": \"The mask.compress op is an AVX512 specific op that can lower to the\\n  `llvm.mask.compress` instruction. Instead of `src`, a constant vector\\n  vector attribute `constant_src` may be specified. If neither `src` nor\\n  `constant_src` is specified, the remaining elements in the result vector are\\n  set to zero.\\n\\n  #### From the Intel Intrinsics Guide:\\n\\n  Contiguously store the active integer/floating-point elements in `a` (those\\n  with their respective bit set in writemask `k`) to `dst`, and pass through the\\n  remaining elements from `src`.\",\n    \"operands\": [\n      { \"name\": \"k\", \"type\": \"VectorOfLengthAndType<[16, 8], [I1]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, I32, F64, I64]>\" },\n      { \"name\": \"src\", \"type\": \"Optional<VectorOfLengthAndType<[ 16, 8 ], [ F32, I32, F64, I64 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, I32, F64, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"constant_src\", \"type\": \"OptionalAttr<ElementsAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'dst', 'k', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$k `,` $a (`,` $src^)? attr-dict `:` type($dst) (`,` type($src)^)?\"\n  },\n  {\n    \"name\": \"x86.avx512.mask.rndscale\",\n    \"summary\": \"Masked roundscale op\",\n    \"description\": \"The mask.rndscale op is an AVX512 specific op that can lower to the proper\\n    LLVMAVX512 operation: `llvm.mask.rndscale.ps.512` or\\n    `llvm.mask.rndscale.pd.512` instruction depending on the type of vectors it\\n    is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Round packed floating-point elements in `a` to the number of fraction bits\\n    specified by `imm`, and store the results in `dst` using writemask `k`\\n    (elements are copied from src when the corresponding mask bit is not set).\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"k\", \"type\": \"I32\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"imm\", \"type\": \"AnyTypeOf<[I16, I8]>\" },\n      { \"name\": \"rounding\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'a', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'dst', 'imm', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $k `,` $a `,` $imm `,` $rounding attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"x86.avx512.mask.scalef\",\n    \"summary\": \"ScaleF op\",\n    \"description\": \"The `mask.scalef` op is an AVX512 specific op that can lower to the proper\\n    LLVMAVX512 operation: `llvm.mask.scalef.ps.512` or\\n    `llvm.mask.scalef.pd.512` depending on the type of MLIR vectors it is\\n    applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Scale the packed floating-point elements in `a` using values from `b`, and\\n    store the results in `dst` using writemask `k` (elements are copied from src\\n    when the corresponding mask bit is not set).\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"k\", \"type\": \"AnyTypeOf<[I16, I8]>\" },\n      { \"name\": \"rounding\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'a', 'b', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'dst', 'k', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $a `,` $b `,` $k `,` $rounding attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"x86.avx512.vp2intersect\",\n    \"summary\": \"Vp2Intersect op\",\n    \"description\": \"The `vp2intersect` op is an AVX512 specific op that can lower to the proper\\n    LLVMAVX512 operation: `llvm.vp2intersect.d.512` or\\n    `llvm.vp2intersect.q.512` depending on the type of MLIR vectors it is\\n    applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Compute intersection of packed integer vectors `a` and `b`, and store\\n    indication of match in the corresponding bit of two mask registers\\n    specified by `k1` and `k2`. A match in corresponding elements of `a` and\\n    `b` is indicated by a set bit in the corresponding bit of the mask\\n    registers.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [I32, I64]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 8], [I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"k1\", \"type\": \"VectorOfLengthAndType<[16, 8], [I1]>\" },\n      { \"name\": \"k2\", \"type\": \"VectorOfLengthAndType<[16, 8], [I1]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"TypesMatchWith<'a', 'k1', '[object Object],[object Object]'>\" },\n      { \"type\": \"TypesMatchWith<'a', 'k2', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($a)\"\n  },\n  {\n    \"name\": \"x86vector.avx.bcst_to_f32.packed\",\n    \"summary\": \"AVX: Broadcasts BF16/F16 into packed F32 Data.\",\n    \"description\": \"#### From the Intel Intrinsics Guide:\\n\\n    Convert scalar BF16 or F16 (16-bit) floating-point element stored at memory locations\\n    starting at location `__A` to a single-precision (32-bit) floating-point,\\n    broadcast it to packed single-precision (32-bit) floating-point elements,\\n    and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx.bcst_to_f32.packed %a : memref<1xbf16> -> vector<8xf32>\\n    %dst = x86vector.avx.bcst_to_f32.packed %a : memref<1xf16> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MemRefOf<[BF16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [F32]>\" }\n    ],\n    \"assemblyFormat\": \"$a  attr-dict`:` type($a)`->` type($dst)\"\n  },\n  {\n    \"name\": \"x86vector.avx.cvt.packed.even.indexed_to_f32\",\n    \"summary\": \"AVX: Convert packed BF16/F16 even-indexed elements into packed F32 Data.\",\n    \"description\": \"#### From the Intel Intrinsics Guide:\\n\\n    Convert packed BF16 or F16 (16-bit) floating-point even-indexed elements stored at\\n    memory locations starting at location `__A` to packed single-precision\\n    (32-bit) floating-point elements, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx.cvt.packed.even.indexed_to_f32 %a : memref<16xbf16> -> vector<8xf32>\\n    %dst = x86vector.avx.cvt.packed.even.indexed_to_f32 %a : memref<16xf16> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MemRefOf<[BF16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [F32]>\" }\n    ],\n    \"assemblyFormat\": \"$a  attr-dict`:` type($a)`->` type($dst)\"\n  },\n  {\n    \"name\": \"x86vector.avx.cvt.packed.odd.indexed_to_f32\",\n    \"summary\": \"AVX: Convert packed BF16/F16 odd-indexed elements into packed F32 Data.\",\n    \"description\": \"#### From the Intel Intrinsics Guide:\\n\\n    Convert packed BF16 or F16 (16-bit) floating-point odd-indexed elements stored at\\n    memory locations starting at location `__A` to packed single-precision\\n    (32-bit) floating-point elements, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx.cvt.packed.odd.indexed_to_f32 %a : memref<16xbf16> -> vector<8xf32>\\n    %dst = x86vector.avx.cvt.packed.odd.indexed_to_f32 %a : memref<16xf16> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"MemRefOf<[BF16, F16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [F32]>\" }\n    ],\n    \"assemblyFormat\": \"$a  attr-dict`:` type($a)`->` type($dst)\"\n  },\n  {\n    \"name\": \"x86vector.avx.dot.i8\",\n    \"summary\": \"Dot Int8 op\",\n    \"description\": \"The `dot` op is an AVX2-Int8 specific op that can lower to the proper\\n    LLVMAVX2-INT8 operation `llvm.vpdpbssd` depending on the width of MLIR\\n    vectors it is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Multiply groups of 4 adjacent pairs of signed 8-bit integers in `a` with \\n    corresponding signed 8-bit integers in `b`, producing 4 intermediate signed 16-bit \\n    results. Sum these 4 results with the corresponding 32-bit integer in `w`, and \\n    store the packed 32-bit results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx.dot.i8 %w, %a, %b : vector<32xi8> -> vector<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"w\", \"type\": \"VectorOfLengthAndType<[4, 8], [I32]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 32], [I8]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 32], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"AllTypesMatch<['w', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'w', 'a', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$w `,` $a `,` $b attr-dict `:` type($a) `->` type($w)\"\n  },\n  {\n    \"name\": \"x86vector.avx.intr.dot\",\n    \"summary\": \"Dot\",\n    \"description\": \"Computes the 4-way dot products of the lower and higher parts of the source\\n    vectors and broadcasts the two results to the lower and higher elements of\\n    the destination vector, respectively. Adding one element of the lower part\\n    to one element of the higher part in the destination vector yields the full\\n    dot product of the two source vectors.\\n\\n    Example:\\n\\n    ```mlir\\n    %0 = x86vector.avx.intr.dot %a, %b : vector<8xf32>\\n    %1 = vector.extract %0[%i0] : f32 from vector<8xf32>\\n    %2 = vector.extract %0[%i4] : f32 from vector<8xf32>\\n    %d = arith.addf %1, %2 : f32\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"x86vector.avx.rsqrt\",\n    \"summary\": \"Rsqrt\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"SameOperandsAndResultType\" }\n    ],\n    \"assemblyFormat\": \"$a attr-dict `:` type($a)\"\n  },\n  {\n    \"name\": \"x86vector.avx10.dot.i8\",\n    \"summary\": \"AVX10 Dot Int8 op\",\n    \"description\": \"The `dot` op is an AVX10-Int8 specific op that can lower to the proper\\n    LLVMAVX10-INT8 operation `llvm.vpdpbssd.512`.\\n\\n    Multiply groups of 4 adjacent pairs of signed 8-bit integers in `a` with\\n    corresponding signed 8-bit integers in `b`, producing 4 intermediate signed 16-bit\\n    results. Sum these 4 results with the corresponding 32-bit integer in `w`, and\\n    store the packed 32-bit results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx10.dot.i8 %w, %a, %b : vector<64xi8> -> vector<16xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"w\", \"type\": \"VectorOfLengthAndType<[16], [I32]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[64], [I8]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[64], [I8]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16], [I32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"AllTypesMatch<['w', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'w', 'a', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$w `,` $a `,` $b attr-dict `:` type($a) `->` type($w)\"\n  },\n  {\n    \"name\": \"x86vector.avx512.cvt.packed.f32_to_bf16\",\n    \"summary\": \"Convert packed F32 to packed BF16 Data.\",\n    \"description\": \"The `convert_f32_to_bf16` op is an AVX512-BF16 specific op that can lower\\n    to the proper LLVMAVX512BF16 operation `llvm.cvtneps2bf16` depending on\\n    the width of MLIR vectors it is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Convert packed single-precision (32-bit) floating-point elements in `a` to\\n    packed BF16 (16-bit) floating-point elements, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx512.cvt.packed.f32_to_bf16 %a : vector<8xf32> -> vector<8xbf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8, 16], [F32]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[8, 16], [BF16]>\" }\n    ],\n    \"assemblyFormat\": \"$a attr-dict `:` type($a) `->` type($dst)\"\n  },\n  {\n    \"name\": \"x86vector.avx512.dot\",\n    \"summary\": \"Dot BF16 op\",\n    \"description\": \"The `dot` op is an AVX512-BF16 specific op that can lower to the proper\\n    LLVMAVX512BF16 operation `llvm.dpbf16ps` depending on the width of MLIR\\n    vectors it is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Compute dot-product of BF16 (16-bit) floating-point pairs in `a` and `b`,\\n    accumulating the intermediate single-precision (32-bit) floating-point\\n    elements with elements in `src`, and store the results in `dst`.\\n\\n    Example:\\n    ```mlir\\n    %dst = x86vector.avx512.dot %src, %a, %b : vector<32xbf16> -> vector<16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[4, 8, 16], [F32]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[8, 16, 32], [BF16]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[8, 16, 32], [BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[4, 8, 16], [F32]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"AllTypesMatch<['src', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'src', 'a', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $a `,` $b attr-dict `:` type($a) `->` type($src)\"\n  },\n  {\n    \"name\": \"x86vector.avx512.mask.compress\",\n    \"summary\": \"Masked compress op\",\n    \"description\": \"The mask.compress op is an AVX512 specific op that can lower to the\\n  `llvm.mask.compress` instruction. Instead of `src`, a constant vector\\n  vector attribute `constant_src` may be specified. If neither `src` nor\\n  `constant_src` is specified, the remaining elements in the result vector are\\n  set to zero.\\n\\n  #### From the Intel Intrinsics Guide:\\n\\n  Contiguously store the active integer/floating-point elements in `a` (those\\n  with their respective bit set in writemask `k`) to `dst`, and pass through the\\n  remaining elements from `src`.\",\n    \"operands\": [\n      { \"name\": \"k\", \"type\": \"VectorOfLengthAndType<[16, 8], [I1]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, I32, F64, I64]>\" },\n      { \"name\": \"src\", \"type\": \"Optional<VectorOfLengthAndType<[ 16, 8 ], [ F32, I32, F64, I64 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, I32, F64, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"constant_src\", \"type\": \"OptionalAttr<ElementsAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'dst', 'k', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$k `,` $a (`,` $src^)? attr-dict `:` type($dst) (`,` type($src)^)?\"\n  },\n  {\n    \"name\": \"x86vector.avx512.mask.rndscale\",\n    \"summary\": \"Masked roundscale op\",\n    \"description\": \"The mask.rndscale op is an AVX512 specific op that can lower to the proper\\n    LLVMAVX512 operation: `llvm.mask.rndscale.ps.512` or\\n    `llvm.mask.rndscale.pd.512` instruction depending on the type of vectors it\\n    is applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Round packed floating-point elements in `a` to the number of fraction bits\\n    specified by `imm`, and store the results in `dst` using writemask `k`\\n    (elements are copied from src when the corresponding mask bit is not set).\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"k\", \"type\": \"I32\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"imm\", \"type\": \"AnyTypeOf<[I16, I8]>\" },\n      { \"name\": \"rounding\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'a', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'dst', 'imm', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $k `,` $a `,` $imm `,` $rounding attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"x86vector.avx512.mask.scalef\",\n    \"summary\": \"ScaleF op\",\n    \"description\": \"The `mask.scalef` op is an AVX512 specific op that can lower to the proper\\n    LLVMAVX512 operation: `llvm.mask.scalef.ps.512` or\\n    `llvm.mask.scalef.pd.512` depending on the type of MLIR vectors it is\\n    applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Scale the packed floating-point elements in `a` using values from `b`, and\\n    store the results in `dst` using writemask `k` (elements are copied from src\\n    when the corresponding mask bit is not set).\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" },\n      { \"name\": \"k\", \"type\": \"AnyTypeOf<[I16, I8]>\" },\n      { \"name\": \"rounding\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"VectorOfLengthAndType<[16, 8], [F32, F64]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['src', 'a', 'b', 'dst']>\" },\n      { \"type\": \"TypesMatchWith<'dst', 'k', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$src `,` $a `,` $b `,` $k `,` $rounding attr-dict `:` type($dst)\"\n  },\n  {\n    \"name\": \"x86vector.avx512.vp2intersect\",\n    \"summary\": \"Vp2Intersect op\",\n    \"description\": \"The `vp2intersect` op is an AVX512 specific op that can lower to the proper\\n    LLVMAVX512 operation: `llvm.vp2intersect.d.512` or\\n    `llvm.vp2intersect.q.512` depending on the type of MLIR vectors it is\\n    applied to.\\n\\n    #### From the Intel Intrinsics Guide:\\n\\n    Compute intersection of packed integer vectors `a` and `b`, and store\\n    indication of match in the corresponding bit of two mask registers\\n    specified by `k1` and `k2`. A match in corresponding elements of `a` and\\n    `b` is indicated by a set bit in the corresponding bit of the mask\\n    registers.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"VectorOfLengthAndType<[16, 8], [I32, I64]>\" },\n      { \"name\": \"b\", \"type\": \"VectorOfLengthAndType<[16, 8], [I32, I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"k1\", \"type\": \"VectorOfLengthAndType<[16, 8], [I1]>\" },\n      { \"name\": \"k2\", \"type\": \"VectorOfLengthAndType<[16, 8], [I1]>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['a', 'b']>\" },\n      { \"type\": \"TypesMatchWith<'a', 'k1', '[object Object],[object Object]'>\" },\n      { \"type\": \"TypesMatchWith<'a', 'k2', '[object Object],[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b attr-dict `:` type($a)\"\n  },\n  {\n    \"name\": \"xegpu.alloc_nbarrier\",\n    \"summary\": \"It allocates a set of named barriers.\",\n    \"description\": \"AllocNbarrier is to create a set of named barriers as\\n  specified by `nbarrier_num`. Named barriers are workgroup level resources,\\n    and are shared by all threads in the workgroup. For example, there are\\n    up to 32 barriers (range 0-31) for each XeCore on PVC. A typical use case\\n    is that a workgroup is partitioned into N subgroups of threads (N <= 32),\\n    and each subgroup coordinating their work with a separate barrier with id\\n    range from 0 to N respectively.\",\n    \"attributes\": [\n      { \"name\": \"nbarrier_num\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$nbarrier_num attr-dict\"\n  },\n  {\n    \"name\": \"xegpu.atomic_rmw\",\n    \"summary\": \"Atomic read-modify-write operation on the TensorDesc.\",\n    \"description\": \"The `xegpu.atomic_rmw` operation provides a way to perform a read-modify-write\\n    operation on the region described by the `TensorDesc` free from data races. The\\n    `kind` enumeration specifies the modification to be performed, The `mask` operand\\n    has the same shape with `TensorDesc`, and is used to enable or disable specific\\n    data points of the `TensorDesc`. The `value` operand represents the new value to\\n    be applied during the modification.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n    - `kind`: An attribute that specifies the atomic operation to be performed\\n      (e.g., add, min, max, exchange, etc.).\\n\\n    - `tensorDesc`: A `TensorDesc` describing the memory region on which the atomic\\n      read-modify-write is performed.\\n\\n    - `mask`: A predicate mask with the same shape as `tensorDesc`. Only elements\\n      with a true (non-zero) mask value participate in the atomic operation;\\n      masked-out elements are not modified.\\n\\n    - `value`: The input values used by the atomic operation. It must have the same\\n      shape and element type as `tensorDesc` and `result`.\\n\\n    - `layout`: [optional] An attribute that identifies the operation as an anchor,\\n      enabling users to assign a layout that governs distribution at the subgroup\\n      and/or lane level. Only valid at workgroup and subgroup levels.\",\n    \"operands\": [\n      { \"name\": \"tensorDesc\", \"type\": \"XeGPU_TensorDesc\" },\n      { \"name\": \"mask\", \"type\": \"XeGPU_MaskType\" },\n      { \"name\": \"value\", \"type\": \"XeGPU_ValueType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_ValueType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"AtomicRMWKindAttr{addf|addi|andi|assign|maximumf|maxnumf|maxs|maxu|minimumf|minnumf|mins|minu|mulf|muli|ori|xori}\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$kind $tensorDesc `,` $mask `,` $value attr-dict `:`\\n    qualified(type($tensorDesc)) `,` type($mask) `,` type($value) `->` type($result)\"\n  },\n  {\n    \"name\": \"xegpu.convert_layout\",\n    \"summary\": \"Convert the layout of the input operand\",\n    \"description\": \"`convert_layout` redistribute data across subgroups and/or lanes from the `input_layout` to\\n      the `target_layout`. Both `input_layout` and `target_layout` must correspond to the same programming\\n      scope, such as workgroup level (wg) or subgroup level (sg) code. This operation is not valid once\\n      the IR is lowered to WI level because that is the end result of all distributions.\\n\\n      This operation serves as an anchor through which users assign a layout attribute\\n      to govern computation distribution.\\n\\n      Arguments:\\n      - `source`: The input vector whose data is to be redistributed. The source and\\n      result types must match.\\n      - `input_layout`: The layout attribute describing the current distribution of `source`\\n      across subgroups and/or lanes.\\n      - `target_layout`: The layout attribute describing the desired distribution of the result\\n      across subgroups and/or lanes.\\n\\n      Example (Subgroup level):\\n        ```mlir\\n          %coop_a = xegpu.convert_layout %a <{\\n                input_layout = #xegpu.layout<sg_layout = [8, 8], sg_data = [16, 128]>,\\n                target_layout = #xegpu.layout<sg_layout = [8, 8], sg_data = [16, 16]>}>\\n            : vector<128x128xf16>\\n        ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"XeGPU_VectorOrOffsetVectorType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_VectorOrOffsetVectorType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_layout\", \"type\": \"DistributeLayoutAttr\" },\n      { \"name\": \"target_layout\", \"type\": \"DistributeLayoutAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$source prop-dict attr-dict `:` type($source)\"\n  },\n  {\n    \"name\": \"xegpu.create_mem_desc\",\n    \"summary\": \"Create a memory descriptor.\",\n    \"description\": \"Creates a memory descriptor from a shared local memory (SLM) buffer, and xegpu\\n    specific memory layout. The resulting memory descriptor has to have the same size\\n    as the underlying shared local memory.\\n\\n    Arguments:\\n     - `source` : 1D or 2D statically shape memref, representing the raw SLM buffer. The provided memref must be contiguous.\\n\\n    Results:\\n     - `mem_desc` : the memory descriptor.\\n\\n    Example:\\n    ```mlir\\n      %mdesc = xegpu.create_mem_desc %mref\\n        : memref<4096xi8, 3>\\n          -> !xegpu.mem_desc<32x64xf16, #xegpu.mem_layout<stride = [1, 32], block = [16, 16]>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyTypeOf<[StaticShared1DMemRefOf<[XeGPU_ScalarType]>, StaticShared2DMemRefOf<[XeGPU_ScalarType]>]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"mem_desc\", \"type\": \"XeGPU_MemDesc\" }\n    ],\n    \"assemblyFormat\": \"$source prop-dict attr-dict `` `:` type($source) `->` qualified(type($mem_desc))\"\n  },\n  {\n    \"name\": \"xegpu.create_nd_tdesc\",\n    \"summary\": \"Create nd-tensor descriptor operation\",\n    \"description\": \"The \\\"create_nd_tdesc\\\" operation creates a TensorDescType which represents\\n    a sub-view of a 1D/2D memory region inside the one or two innermost dimensions\\n    of the source. (It can be extended to support n-D memory region if needed in\\n    future). Elements in the subview continuous in each dimension. It encodes the\\n    following important information for supporting Intel hardware features:\\n\\n    Arguments:\\n    - `source`: an object representing (starting address/pointer of) a memory region.\\n       It can be either a memref object, or simply a pointer represented by uint64_t type.\\n       For the case of dynamic memrefs or pointer, the shape and layout information of the\\n       memory region should be explicitly passed via `shape` and `strides` parameters.\\n\\n    - `offsets`: [optional] index values represents offsets from the \\\"source\\\" at the each dimension\\n        at which the subview of the target memory will be created. It is encoded via\\n        \\\"offsets\\\" and \\\"const_offsets\\\", such that it can accept various forms, such as,\\n        operands (e.g., [%c0, %c]) and attributes (e.g., [2, 4]). Offsets is optional and may be set at load_nd, store_nd, and prefetch_nd.\\n\\n    - `shape`: the shape information of the memory region pointed by the \\\"source\\\". It is\\n         typically encoded via the MemRefType of the source, e.g., memref<4096x4096xf16>.\\n        But if \\\"source\\\" is simply a pointer represented as uint64_t type, or a memref\\n        type without shape information e.g., memref<?x?xf16>, the shape information has\\n        to be explicitly passed via the \\\"shape\\\" and \\\"const_shape\\\" arguments.\\n\\n    - `strides`: the strides of the memory region pointed by the \\\"source\\\". Similar to shape,\\n        it is typically encoded via the MemRefType of the source too. But if \\\"source\\\" is\\n        simply a pointer represented as uint64_t type, or a memref type without shape\\n        information e.g., memref<?x?xf16>, the strides information has to be explicitly\\n        passed via the \\\"strides\\\" and \\\"const_strides\\\" argument.\\n\\n    Results:\\n    - `res`: nd tensor descriptor\\n\\n    Example 1 (suppose the tensor shape inferred by the compiler is 8x16):\\n    ```mlir\\n    %0 = memref.alloc() : memref<1024x1024xf32>\\n    %c0 = arith.constant 0 : index\\n    %c1 = arith.constant 1 : index\\n    %1 = xegpu.create_nd_tdesc %0[%c0, %c0]: memref<1024x1024xf32> -> TensorDesc<8x16xf32>\\n    ```\\n\\n    Example 2 (suppose the tensor shape inferred by the compiler is 8x16):\\n    ```mlir\\n    %0 = memref.alloc(%h, %w) : memref<?x?xf32>\\n    %c0 = arith.constant 0 : index\\n    %c1 = arith.constant 1 : index\\n    %1 = xegpu.create_nd_tdesc %0[%c0, %c0], [%h, %w], [%w, %c1]: memref<?x?xf32> -> TensorDesc<8x16xf32>\\n    ```\\n\\n    Example 3 (suppose the tensor shape inferred by the compiler is 8x16):\\n    ```mlir\\n    %0 = ... : ui64\\n    %c0 = arith.constant 0 : index\\n    %c1 = arith.constant 1 : index\\n    %1 = xegpu.create_nd_tdesc %0[%c0, %c0], [%h, %w], [%w, %c1]: ui64 -> TensorDesc<8x16xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"XeGPU_BaseAddrType\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"shape\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"strides\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"const_shape\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"const_strides\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$source ``\\n    custom<OptionalDynamicIndexList>($offsets, $const_offsets)\\n    (`,` `shape` `:` custom<DynamicIndexList>($shape, $const_shape)^\\n     `,` `strides``:` custom<DynamicIndexList>($strides, $const_strides))?\\n    attr-dict `:` type($source) `->` qualified(type($TensorDesc))\"\n  },\n  {\n    \"name\": \"xegpu.create_tdesc\",\n    \"summary\": \"create scattered tensor descriptors (TensorDesc).\",\n    \"description\": \"\\\"create_tdesc\\\" is similar to \\\"create_nd_tdesc\\\" in terms that it creates\\n    a Tensor Descriptor (TensorDescType) for a memory region. While \\\"create_nd_tdesc\\\"\\n    is for creating continuous subviews, \\\"create_tdesc\\\" is for creating non-continuous\\n    (scattered) subviews, allowing each lane in a subgroup specifying their own offset.\\n    It accepts the following parameters:\\n\\n    Arguments:\\n\\n    - `source`: a 1D memref or pointer (i64, i32, ui64, ui32) represents the flattened\\n      memory object.\\n\\n    - `offsets`: a vector containing offsets of each access point. Its size\\n      is fixed to the hardware supportted subgroup size, e.g., 16 on PVC,\\n      implying each element in the vector corresponds to a SIMT lane in the subgroup.\\n\\n    Results:\\n    - `res`: scattered tensor descriptor\\n\\n    The first dimension of the result TensorDesc corresponds to lanes, so it should\\n    match the dimension of offsets. It may also has a second dimension corresponding to\\n    the chunk_size if the chunk size is larger than 1.\\n\\n    Example 1: It assumes subgroup size is 4, and accesses a[0], a[16], a[32], a[64]\\n    ```mlir\\n    %a = memref.alloc() : memref<1024xf32>\\n    %0 = arith.constant dense<[0, 16, 32, 64]> : vector<4xindex>\\n    %1 = xegpu.create_tdesc %a, %0: memref<1024xf32>, vector<4xindex> -> TensorDesc<4xf32>\\n    ```\\n\\n    Example 2: It assumes subgroup size is 4, and each workitem access 8 elements.\\n               It will access totally 32 data elements: a[0:7], a[16:23], a[32:39], a[64:71]\\n    ```mlir\\n    %0 = memref.alloc() : memref<1024xf32>\\n    %off = arith.constant dense<[0, 16, 32, 64]> : vector<4xindex>\\n    %1 = xegpu.create_tdesc %0, %off : memref<1024xf32>, vector<4xindex>\\n          -> TensorDesc<4x8xf32, #xegpu.scattered_tdesc_attr<chunk_size = 8>>\\n    ```\\n\\n    Example 3: It is similar to Example 2, but there is some overlaps among workitems.\\n               It accesses: a[0:7], a[4:11], a[8:15], a[12:19]\\n    ```mlir\\n    %0 = memref.alloc() : memref<1024xf32>\\n    %off = arith.constant dense<[0, 4, 8, 12]> : vector<4xindex>\\n    %1 = xegpu.create_tdesc %0, %off : memref<1024xf32>, vector<4xindex>\\n          -> TensorDesc<4x8xf32, #xegpu.scattered_tdesc_attr<chunk_size = 8>>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"XeGPU_GatherScatterBaseAddrType\" },\n      { \"name\": \"offsets\", \"type\": \"XeGPU_OffsetType\" }\n    ],\n    \"results\": [\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" }\n    ],\n    \"assemblyFormat\": \"$source `,` $offsets attr-dict `:`  type($source) `,` type($offsets) `->` qualified(type($TensorDesc))\"\n  },\n  {\n    \"name\": \"xegpu.dpas\",\n    \"summary\": \"It performs mma computation\",\n    \"description\": \"DPAS performs matrix multiplication on matrix A of `mxk`\\n    size, B of `kxn` size, and accumulate on matrix C of `mxn` to the same size\\n    matrix , `m=8`, `n=16` and `k=8 * 32/bit_width_of_elem_type`. So for fp16\\n    data type, the matrices are `A: vector<8x16xf16>`, `B: vector<16x16xf16>`,\\n    and `C/D: vector<8x16xf32>`.\\n\\n    In lane level code, each lane from a subgroup holds a data fragment for A, B, C and the result,\\n    which are represented as 1D vectors. Please refer to [OpenCL Intel extentions]\\n    (https://registry.khronos.org/OpenCL/extensions/intel/cl_intel_subgroup_matrix_multiply_accumulate.html)\\n    for more details about the fragment distribution.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `lhs`: A vector value representing the left-hand-side matrix tile (A) participating in the\\n      matrix multiply.\\n\\n    - `rhs`: A vector value representing the right-hand-side matrix tile (B).\\n\\n    - `acc`: [optional] A vector value representing the accumulator matrix tile (C). When present, the\\n      result is computed as `lhs * rhs + acc`; otherwise, the accumulator is implicitly assumed to be zero.\\n\\n    - `layout_a`, `layout_b`, `layout_cd`: [optional] Attributes that identify this\\n      operation as anchor for operands A, B, and the accumulator/result, enabling users to assign layouts\\n      that govern distribution at the subgroup and/or lane level. Only valid at workgroup and subgroup\\n      level.\\n\\n    Example 1 (Workgroup level):\\n\\n    ```mlir\\n      %d = xegpu.dpas %a, %b, %c <{\\n          layout_a = #xegpu.layout<sg_layout = [4, 8], sg_data = [16, 128]>,\\n          layout_b = #xegpu.layout<sg_layout = [4, 8], sg_data = [128, 16]>,\\n          layout_cd = #xegpu.layout<sg_layout = [4, 8], sg_data = [16, 16]>}\\n          : vector<64x128xf16>, vector<128x128xf16>, vector<64x128xf32> -> vector<64x128xf32>\\n    ```\\n\\n    Example 2 (Lane level):\\n\\n    ```mlir\\n      %d = xegpu.dpas %a, %b, %c\\n            :  vector<8xf16>, vector<16xf16>, vector<8xf32> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"XeGPU_DpasOprType\" },\n      { \"name\": \"rhs\", \"type\": \"XeGPU_DpasOprType\" },\n      { \"name\": \"acc\", \"type\": \"Optional<XeGPU_DpasResType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_DpasResType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout_a\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" },\n      { \"name\": \"layout_b\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" },\n      { \"name\": \"layout_cd\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$lhs `,` $rhs (`,` $acc^)? attr-dict `:` type($lhs)`,` type($rhs) (`,` type($acc)^)?  `->` type($result)\"\n  },\n  {\n    \"name\": \"xegpu.dpas_mx\",\n    \"summary\": \"It performs scaled mma computation\",\n    \"description\": \"DPAS MX performs matrix multiplication on matrix A and Matrix B\\n    of low precision data type. A is of size`mxk`\\n    size, B is of size `kxn`, and accumulate on matrix C of size `mxn` to the same size\\n    matrix.\\n\\n    In lane level code, each lane from a subgroup holds a data fragment for A, B, Acc and the result,\\n    which are represented as 1D vectors.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `a`: A vector value representing the left-hand-side matrix tile (A) participating in the\\n      matrix multiply.\\n\\n    - `b`: A vector value representing the right-hand-side matrix tile (B).\\n\\n    - `acc`: A vector value representing the accumulator matrix tile (C). The\\n      result is computed as `a * b + acc`.\\n\\n    - `scale_a`: A floating point vector/scalar value used to scale `a` for\\n      matrix multiplication.\\n\\n    - `scale_b`: A floating point vector/scalar value used to scale `b` for\\n      matrix multiplication.\\n\\n    - `layout_a`, `layout_b`, `layout_cd`: [optional] Attributes that identify this\\n      operation as anchor for operands A, B, and the accumulator/result, enabling users to assign layouts\\n      that govern distribution at the subgroup and/or lane level. Only valid at workgroup and subgroup\\n      level.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"XeGPU_DpasOprType\" },\n      { \"name\": \"b\", \"type\": \"XeGPU_DpasOprType\" },\n      { \"name\": \"acc\", \"type\": \"Optional<XeGPU_DpasResType>\" },\n      { \"name\": \"scale_a\", \"type\": \"Optional<AnyTypeOf<[ F8E8M0FNU, VectorOfRankAndType < [ 1 , 2 ] , [ F8E8M0FNU ] > ]>>\" },\n      { \"name\": \"scale_b\", \"type\": \"Optional<AnyTypeOf<[ F8E8M0FNU, VectorOfRankAndType < [ 1 , 2 ] , [ F8E8M0FNU ] > ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_DpasResType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"layout_a\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" },\n      { \"name\": \"layout_b\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" },\n      { \"name\": \"layout_cd\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b (`,` $acc^)?\\n    (`scale_a` `=` $scale_a^)?\\n    (`scale_b` `=` $scale_b^)?\\n    attr-dict `:` type($a)`,` type($b)\\n    (`,` type($acc)^)?\\n    (`,` type($scale_a)^)?\\n    (`,` type($scale_b)^)? `->` type($result)\"\n  },\n  {\n    \"name\": \"xegpu.fence\",\n    \"summary\": \"It synchronizes memory accesses.\",\n    \"description\": \"It synchronizes the memory access between\\n    write and following read or write.\\n    1. `Memory_kind` describes the memory kind. \\\"global\\\" means the global memory,\\n        \\\"slm\\\" means the share local memory.\\n    2. `Fence_scope` describes the scope of fence. \\\"Workgroup\\\" means that the scope would be\\n        within each workgroup. \\\"GPU\\\" means the scope would be across workgroups within the GPU.\",\n    \"attributes\": [\n      { \"name\": \"memory_kind\", \"type\": \"XeGPU_MemorySpaceAttr{global|slm}\" },\n      { \"name\": \"fence_scope\", \"type\": \"XeGPU_FenceScopeAttr{workgroup|gpu}\" }\n    ],\n    \"assemblyFormat\": \"`memory_kind` `=` $memory_kind `,` `fence_scope` `=` $fence_scope attr-dict\"\n  },\n  {\n    \"name\": \"xegpu.init_nbarrier\",\n    \"summary\": \"It assigns a named barrier to the current thread.\",\n    \"description\": \"InitNbarrierOp assigns the named barrier with the specified\\n      barrier ID (0~31) to the current thread. Multiple threads may bind to the\\n      same named barrier, and the `participant_thread_num` specifies the total\\n      number of threads associated with the nbarrier. It returns an object of\\n      NbarrierType representing the barrier\",\n    \"operands\": [\n      { \"name\": \"nbarrier_id\", \"type\": \"I8\" },\n      { \"name\": \"participant_thread_num\", \"type\": \"I8\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_Nbarrier\" }\n    ],\n    \"assemblyFormat\": \"$nbarrier_id `,` $participant_thread_num attr-dict `:`\\n    type($nbarrier_id) `,` type($participant_thread_num) `->` qualified(type($result))\"\n  },\n  {\n    \"name\": \"xegpu.load\",\n    \"summary\": \"load a set of scattered data points from memory.\",\n    \"description\": \"It (aka. load) load data per each lane. The output\\n    describes the data being loaded at the subgroup level, so its size is\\n    consistent with the number of lanes in a subgroup. When the chunk size\\n    is larger than 2, the output vector is a 2D vector, with dim-0 correspoding\\n    to lanes, and dim-1 corresponding to the chunk size loaded by each lane.\\n    The mask operand masks out memory access so that it is safe to pass out-of-boundary\\n    addresses/offsets as long as they are masked. Each mask element applies to one lane.\\n\\n    In lane level, the result is a 1D vector that represents the data to be loaded by\\n    each lane. If size is not 1, size should be equal to the chunk size.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `source`: represents the memory region to be loaded from, which can be either a\\n        tensor_desc or a 1D memref or pointer (ui64, ui32, i64 or i32).\\n        In case of tensor_desc, offsets come from the producer create_tdesc op.\\n        tensor_desc cannot be used at lane level.\\n\\n    - `offsets`: represents offsets from source. required if `source` in not a TensorDescType.\\n        offsets is a vector of `index` type and vector length is either the subgroup size\\n        or 1 at lane level. scalar offset is also valid for lane level.\\n\\n    - `mask`: is a vector of `i1` type, which is used to mask out the memory access.\\n        mask is a vector of size equal to the subgroup size, or 1 at lane level.\\n        scalar mask is also valid for lane level.\\n\\n    - `chunk_size`: [optional] represents contiguous number of elements to load from per work item.\\n\\n    - `l1_hint`, `l2_hint`, `l3_hint`: [optional] cache hints for each level of cache.\\n\\n    - `layout`: [optional] Describes the expected layout of the `tensor_desc` operand or the result\\n      of load. Only valid at workgroup and subgroup levels.\\n\\n    Results:\\n    - `res`: represents loaded data\\n\\n\\n  Example 1 (Workgroup level):\\n  ```mlir\\n    %2 = xegpu.load %1, %0 <{l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<uncached>,\\n                             l3_hint = #xegpu.cache_hint<uncached>},\\n                             layout = #xegpu.layout<sg_layout = [8], sg_data = [32]>>\\n          : !xegpu.tensor_desc<256xf32, #xegpu.scatter_tdesc_attr<memory_space=global>>,\\n            vector<256xi1> -> vector<256xf32>\\n  ```\\n\\n  Example 2 (Subgroup level):\\n  ```mlir\\n    %2 = xegpu.load %1, %0 <{l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<uncached>,\\n                             l3_hint = #xegpu.cache_hint<uncached>},\\n                             layout = #xegpu.layout<lane_layout = [16, 1], lane_data = [1, 8]>>\\n          : !xegpu.tensor_desc<16x8xf32, #xegpu.scatter_tdesc_attr<memory_space=global, chunk_size=8>>,\\n            vector<16xi1> -> vector<16x8xf32>\\n  ```\\n\\n  Example 3 (Subgroup level):\\n  A variant accepts memref as base pointer and an offset instead of scattered TensorTdesc.\\n  It combines \\\"create scattered TensorTdesc\\\" and \\\"load with scattered TensorTdesc\\\".\\n  The source operand could be a raw pointer (ui64, ui32, i64, i32). Please refer to create_tdesc\\n  for the restriction of memref.\\n  ```mlir\\n    %a = memref.alloc() : memref<1024xf32>\\n    %offsets = vector.step : vector<16xindex>\\n    %mask = vector.constant_mask [16]: vector<16xi1>\\n    %val = xegpu.load %a[%offsets], %mask {l1_hint = #xegpu.cache_hint<cached>,\\n                           l2_hint = #xegpu.cache_hint<cached>,\\n                           l3_hint = #xegpu.cache_hint<cached>,\\n                           layout = #xegpu.layout<lane_layout = [16], lane_data = [1]>}\\n      : memref<1024xf32>, vector<16xi1>, vector<16xindex> -> vector<16xf32>\\n  ```\\n\\n  Example 4 (lane level):\\n  lane level only accepts the offsets variant. chunk_size can be inferred from result\\n  type. In this example, chunk_size is 8.\\n  ```mlir\\n    %2 = xegpu.load %1[%2], %0 <{l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<uncached>,\\n                             l3_hint = #xegpu.cache_hint<uncached>}>\\n          : memref<128xf32>, vector<1xindex>, vector<1xi1> -> vector<8xf32>\\n  ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"XeGPU_GatherScatterSourceType\" },\n      { \"name\": \"offsets\", \"type\": \"Optional<AnyTypeOf<[ XeGPU_OffsetType, Index ]>>\" },\n      { \"name\": \"mask\", \"type\": \"AnyTypeOf<[XeGPU_MaskType, I1]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[XeGPU_ValueType, XeGPU_ScalarType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"chunk_size\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"l1_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l2_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l3_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$source\\n    (`[` $offsets^ `]`)? `,`\\n    $mask prop-dict\\n    attr-dict `:` type(operands) `->` type($value)\"\n  },\n  {\n    \"name\": \"xegpu.load_matrix\",\n    \"description\": \"This operation loads an nD block of data from shared local memory (SLM) as specified\\n    by the provided nD `mem_desc`. Memory descriptors of any rank are supported.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n     - `mem_desc`: the memory descriptor identifying the SLM region.\\n     - `offsets`: the coordinates within the matrix to read from.\\n     - `subgroup_block_io`: [optional] An attribute indicating that the operation can be lowered\\n        to a subgroup block load. When this attribute is present, the offsets are subgroup-uniform\\n        across all lanes. Only used on subgroup and lane level.\\n     - `layout`: [optional] Describes the expected layout of the `mem_desc` operand as well as\\n      the result of load (they are identical).\\n        Only valid at workgroup and subgroup levels.\\n\\n    Results:\\n     - `res`: the matrix elements loaded from SLM.\\n\\n    Example (Workgroup level):\\n    ```mlir\\n        %c0 = arith.constant 0 : index\\n        %1 = xegpu.load_matrix %0[%c0, %c0] <{\\n                layout = #xegpu.layout<sg_layout = [4, 8], sg_data = [32, 16]> }>\\n          : !xegpu.mem_desc<128x128xf16, #xegpu.mem_layout<stride = [1, 128], block = [16, 16]>>\\n          , index, index -> vector<128x128xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"mem_desc\", \"type\": \"XeGPU_MemDesc\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[XeGPU_ValueType, XeGPU_ScalarType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"subgroup_block_io\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$mem_desc `` custom<DynamicIndexList>($offsets, $const_offsets)\\n    prop-dict attr-dict `` `:` type(operands) `->` type(results)\"\n  },\n  {\n    \"name\": \"xegpu.load_nd\",\n    \"summary\": \"loads a n-D block from memory (represented by TensorDesc)to registers (represented by vector)\",\n    \"description\": \"LoadNdOp essentially mimics the hardware block read instruction to read\\n    a block of data from memory to register. It takes a set of optional cache\\n    hints for each level of cache, L1, L2 and L3. If hardware does not have a\\n    correspoding cache, Corresponding cache hint attribute will be masked.\\n\\n    On Intel GPUs, hardware-supported packing rearranges data elements during\\n    the load of the B operand when the element bit-width is less than 32 bits\\n    (for example, fp16). The transpose feature reorders data during the load\\n    when the element type is fp32 or fp64. These two features are mutually\\n    exclusive and shall not be enabled simultaneously. Both features support only\\n    2D blocked tensor_desc.\\n\\n    At lane level, result vector represents the data to be loaded by each lane.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `TensorDesc`: A tensor descriptor specifying the base nd-region of memory\\n      and the tensor tile to be loaded.\\n\\n    - `offsets`: Index values representing per-dimension offsets from the base position\\n      encoded in `TensorDesc`. They are encoded via `offsets` and `const_offsets`.\\n\\n    - `packed`: [optional] A unit attribute indicating that packing is applied\\n      during the load when supported by the hardware. Only valid at lane level.\\n\\n    - `transpose`: [optional] An attribute describing a hardware-supported transpose\\n      to be applied during the load. Only valid at Lane level.\\n\\n    - `l1_hint`, `l2_hint`, `l3_hint`: [optional] Cache-hint attributes indicating the\\n      desired behavior at the L1, L2, and L3 cache levels.\\n\\n    - `layout`: [optional] Describes the expected layout of the `tensor_desc` operand as well as the result of the load (they are identical). Only valid at workgroup and subgroup levels.\\n\\n    Example 1 (Workgroup level):\\n    ```mlir\\n      xegpu.load_nd %1 {transpose = [1, 0],\\n                        l1_hint = #xegpu.cache_hint<cached>,\\n                        l2_hint = #xegpu.cache_hint<uncached>,\\n                        l3_hint = #xegpu.cache_hint<streaming>,\\n                        layout = #xegpu.layout<sg_layout = [4, 8], sg_data = [8, 32]>}\\n              : !xegpu.tensor_desc<32x256xf32> -> vector<32x256xf32>\\n    ```\\n    Example 2 (lane level):\\n    ```mlir\\n      xegpu.load_nd %1 {l1_hint = #xegpu.cache_hint<cached>,\\n                        l2_hint = #xegpu.cache_hint<uncached>}>\\n        : !xegpu.tensor_desc<8x16xf32> -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"value\", \"type\": \"XeGPU_ValueType\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"packed\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"transpose\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"l1_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l2_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l3_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$TensorDesc ``\\n    custom<OptionalDynamicIndexList>($offsets, $const_offsets)\\n    prop-dict attr-dict `:` qualified(type($TensorDesc)) `->` type($value)\"\n  },\n  {\n    \"name\": \"xegpu.nbarrier_arrive\",\n    \"summary\": \"It signals the arrival at the named barrier.\",\n    \"description\": \"NbarrierArriveOp signals the hardware (or other threads)\\n    that the current thread has produced its data for the consumer threads. When\\n    the hardware signalled by `participant_thread_num` threads for the named barrier,\\n    it will notify the threads waiting for the named barrier to continue their work.\",\n    \"operands\": [\n      { \"name\": \"nbarrier\", \"type\": \"XeGPU_Nbarrier\" }\n    ],\n    \"assemblyFormat\": \"$nbarrier attr-dict `:` qualified(type($nbarrier))\"\n  },\n  {\n    \"name\": \"xegpu.nbarrier_wait\",\n    \"summary\": \"It waits for a named barrier.\",\n    \"description\": \"NbarrierWaitOp signals the hardware which named barrier\\n    the current thread is waiting for, such that it can get notified when the\\n    named barrier is completed.\",\n    \"operands\": [\n      { \"name\": \"nbarrier\", \"type\": \"XeGPU_Nbarrier\" }\n    ],\n    \"assemblyFormat\": \"$nbarrier attr-dict `:` qualified(type($nbarrier))\"\n  },\n  {\n    \"name\": \"xegpu.prefetch\",\n    \"summary\": \"prefetches a set of scattered data points to cache\",\n    \"description\": \"It issues instructions to prefetch a set of scattered data points\\n    from memory to each level of the cache based on their cache policy.\\n    As compared to prefetch_nd, which works on non-scattered TensorDesc,\\n    it works on scattered TensorDesc instead.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `source`: represents the memory region to be loaded from, which can be either a\\n        tensor_desc or a 1D memref or pointer (ui64, ui32, i64 or i32).\\n        In case of tensor_desc, offsets come from the producer create_tdesc op.\\n        tensor_desc cannot be used at lane level.\\n\\n    - `offsets`: represents offsets from source. required if `source` in not a TensorDescType.\\n        offsets is a vector of `index` type and vector length is either the subgroup size\\n        or 1 at lane level. scalar offset is also valid for lane level.\\n\\n    - `l1_hint`, `l2_hint`, `l3_hint`: [optional] cache hints for each level of cache.\\n\\n    - `offset_align_byte`: [optional] required if `source` is a pointer. If `source` is not a pointer,\\n        it is not allowed. Represents the alignment in bytes of each offset in offsets.\\n\\n    - `layout`: [optional] Describes the expected layout of the `tensor_desc` or `offsets`\\n      operand. Only valid at workgroup and subgroup levels.\\n\\n    Example 1 (Workgroup level):\\n    ```mlir\\n      xegpu.prefetch %tdesc {l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<cached>,\\n                             l3_hint = #xegpu.cache_hint<cached>,\\n                             layout = #xegpu.layout<sg_layout = [8], sg_data = [32]>\\n                             }\\n        : !xegpu.tensor_desc<256xf16>\\n    ```\\n\\n    Example 2 (lane level):\\n    A variant accepts memref as base pointer and an offset instead of scattered TensorTdesc.\\n    It combines \\\"create scattered TensorTdesc\\\" and \\\"prefetch with scattered TensorTdesc\\\".\\n    The source operand could be a raw pointer (ui64, ui32, i64, i32).\\n    Please refer to create_tdesc for the restriction of memref.\\n    ```mlir\\n      %a = memref.alloc() : memref<1024xf32>\\n      %0 = arith.constant dense<[0, 16, 32, 64]> : vector<4xindex>\\n      xegpu.prefetch %a[%0] {l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<cached>,\\n                             l3_hint = #xegpu.cache_hint<cached>}\\n        : memref<1024xf32>, vector<4xindex>\\n    ```\\n\\n    Example 3 (lane level):\\n    lane level only accepts the offsets variant.\\n    ```mlir\\n      xegpu.prefetch %0[%1] {l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<cached>,\\n                             l3_hint = #xegpu.cache_hint<cached>}\\n        : memref<256xf32>, vector<1xindex>\\n    ```\\n\\n    Example 4 (lane level):\\n    lane level only accepts the offsets variant.\\n    ```mlir\\n      xegpu.prefetch %0[%1] {l1_hint = #xegpu.cache_hint<cached>,\\n                             l2_hint = #xegpu.cache_hint<cached>,\\n                             l3_hint = #xegpu.cache_hint<cached>,\\n                             offset_align_byte = 2}\\n        : i64, vector<1xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"XeGPU_GatherScatterSourceType\" },\n      { \"name\": \"offsets\", \"type\": \"Optional<AnyTypeOf<[ XeGPU_OffsetType, Index ]>>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"l1_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l2_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l3_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"offset_align_byte\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$source\\n    (`[` $offsets^ `]`)?\\n    prop-dict\\n    attr-dict `:` type(operands)\"\n  },\n  {\n    \"name\": \"xegpu.prefetch_nd\",\n    \"summary\": \"prefetches a n-D block to cache\",\n    \"description\": \"It issues an instruction to prefetch a block of data from continuous\\n    memory regions to each level of the cache based on their cache policy.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n    - `TensorDesc`: A tensor descriptor specifying the base nd-region of\\n      memory and tensor tile to be prefetched.\\n\\n    - `offsets`: [optional] index values representing per-dimension offsets from the\\n      base position encoded in `TensorDesc`. It is encoded via \\\"offsets\\\"\\n      and \\\"const_offsets\\\".\\n\\n    - `l1_hint`, `l2_hint`, `l3_hint`: [optional] An cache-hint attribute\\n      indicating the desired behavior at the L1, L2, and L3 cache levels.\\n\\n    - `layout`: [optional] Describes the expected layout of the `tensor_desc` operand.\\n       Only valid at the workgroup and subgroup levels.\\n\\n    Example (Workgroup level):\\n    ```mlir\\n      %c0 = arith.constant 0 : index\\n      %c1 = arith.constant 1 : index\\n      xegpu.prefetch_nd %tdesc[%c0, %c1] {l1_hint = #xegpu.cache_hint<cached>,\\n                                l2_hint = #xegpu.cache_hint<cached>,\\n                                l3_hint = #xegpu.cache_hint<cached>,\\n                                layout = #xegpu.layout<sg_layout = [4, 8], sg_data = [8, 32]> }\\n        : !xegpu.tensor_desc<32x256xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"l1_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l2_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l3_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$TensorDesc ``\\n    custom<OptionalDynamicIndexList>($offsets, $const_offsets)\\n    prop-dict attr-dict `:` qualified(type($TensorDesc))\"\n  },\n  {\n    \"name\": \"xegpu.store\",\n    \"summary\": \"store data to scattered memory locations.\",\n    \"description\": \"It (aka. store) stores data to scattered memory locations. The value is\\n  typically a 1D vector. But when the chunk size of the TensorDesc is larger than 1, it will be\\n  a 2D vector instead. For the later case, dim-1 of the value correspods to the simd lanes\\n  and the dim-0 of the value corresponds to the chunk size stored per lane. So `store_scatter`\\n  has transpose effect, which is similar to `load_gather`. Therefore, a transpose attribute is\\n  introduced on purpose, making sure users are aware of this implicit transformation.\\n\\n  In lane level, the result is a 1D vector that represents the data to be stored by\\n  each lane. If size is not 1, size should be equal to the chunk size.\\n\\n  This operation serves as an anchor through which users assign a layout attribute\\n  to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `value`: represents the data to be stored.\\n\\n    - `dest`: represents the memory region to be stored to, which can be either a\\n        tensor_desc or a 1D memref or pointer (ui64, ui32, i64 or i32).\\n        In case of tensor_desc, offsets come from the producer create_tdesc op.\\n        tensor_desc cannot be used at lane level.\\n\\n    - `offsets`: represents offsets from dest. required if `source` in not a TensorDescType.\\n        offsets is a vector of `index` type and vector length is either the subgroup size\\n        or 1 at lane level. scalar offset is also valid for lane level.\\n\\n    - `mask`: is a vector of `i1` type, which is used to mask out the memory access.\\n        mask is a vector of size equal to the subgroup size, or 1 at lane level.\\n        scalar mask is also valid for lane level.\\n\\n    - `chunk_size`: [optional] represents contiguous number of elements to store to per work item.\\n\\n    - `l1_hint`, `l2_hint`, `l3_hint`: [optional] cache hints for each level of cache.\\n\\n    - `layout`: [optional] Describes the expected layout of the `tensor_desc` operand or the value\\n      to be stored. Only valid at workgroup and subgroup levels.\\n\\n\\n  Example 1 (Workgroup level):\\n  ```mlir\\n    xegpu.store %0, %1, %2 <{l1_hint = #xegpu.cache_hint<uncached>,\\n                             l2_hint = #xegpu.cache_hint<write_back>,\\n                             l3_hint = #xegpu.cache_hint<write_through>,\\n                             layout = #xegpu.layout<sg_layout = [8], sg_data = [16]>}>\\n          : vector<256xf32>, !xegpu.tensor_desc<256xf32, #xegpu.scattered_tdesc_attr<>>, vector<256xi1>\\n  ```\\n\\n  Example 2 (Subgroup level):\\n  ```mlir\\n    xegpu.store %0, %1, %2 <{l1_hint = #xegpu.cache_hint<uncached>,\\n                             l2_hint = #xegpu.cache_hint<write_back>,\\n                             l3_hint = #xegpu.cache_hint<write_through>,\\n                             layout = #xegpu.layout<lane_layout = [16, 1], lane_data = [1, 8]>}>\\n          : vector<16x8xf32>, !xegpu.tensor_desc<16x8xf32, #xegpu.scattered_tdesc_attr<chunk_size=8>>, vector<16xi1>\\n  ```\\n\\n  Example 3 (Subgroup level):\\n  A variant accepts memref as base pointer and an offset instead of scattered TensorTdesc.\\n  It combines \\\"create scattered TensorTdesc\\\" and \\\"store with scattered TensorTdesc\\\".\\n  The dest operand could be a raw pointer (uint64_t).\\n  Please refer to create_tdesc for the restriction of memref.\\n  ```mlir\\n    %a = memref.alloc() : memref<1024xf32>\\n    %val = arith.constant dense<0.0> : vector<16xf32>\\n    %offsets = vector.step : vector<16xindex>\\n    %mask = vector.constant_mask [16]: vector<16xi1>\\n    xegpu.store %val, %a[%offsets], %mask {l1_hint = #xegpu.cache_hint<cached>,\\n                           l2_hint = #xegpu.cache_hint<cached>,\\n                           l3_hint = #xegpu.cache_hint<cached>,\\n                           layout = #xegpu.layout<lane_layout = [16], lane_data = [1]>}\\n      : vector<16xf32>, memref<1024xf32>, vector<16xi1>, vector<16xindex>\\n  ```\\n\\n  Example 4 (Lane level):\\n  Lane level IR only accepts the offsets variant. chunk_size can be inferred from value\\n  type. In this example, chunk_size is 8.\\n  ```mlir\\n    xegpu.store %0, %1[%2], %3 <{l1_hint = #xegpu.cache_hint<uncached>,\\n                             l2_hint = #xegpu.cache_hint<write_back>,\\n                             l3_hint = #xegpu.cache_hint<write_through>}>\\n          : vector<8xf32>, memref<256xf32>, vector<1xindex>, vector<1xi1>\\n  ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"AnyTypeOf<[XeGPU_ValueType, XeGPU_ScalarType]>\" },\n      { \"name\": \"dest\", \"type\": \"XeGPU_GatherScatterSourceType\" },\n      { \"name\": \"offsets\", \"type\": \"Optional<AnyTypeOf<[ XeGPU_OffsetType, Index ]>>\" },\n      { \"name\": \"mask\", \"type\": \"AnyTypeOf<[XeGPU_MaskType, I1]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"chunk_size\", \"type\": \"OptionalAttr<I64Attr>\" },\n      { \"name\": \"l1_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l2_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l3_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value `,`\\n    $dest\\n    (`[` $offsets^ `]`)? `,`\\n    $mask\\n    prop-dict\\n    attr-dict `:`  type(operands)\"\n  },\n  {\n    \"name\": \"xegpu.store_matrix\",\n    \"description\": \"This operation stores an nD `data` fragment into the shared local memory region\\n    specified by an nD `mem_desc`. Memory descriptors of any rank are supported.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n     - `mem_desc`: the memory descriptor specifying the SLM region.\\n     - `offsets`: the coordinates within the matrix where the data will be written.\\n     - `data`: the values to be stored in the matrix.\\n     - `subgroup_block_io`: [optional] An attribute indicating that the operation can be lowered\\n        to a subgroup block load. When this attribute is present, the offsets are subgroup-uniform\\n        across all lanes. Only used on subgroup and lane level.\\n     - `layout`: [optional] Describes the expected layout of the `tensor_desc` operand as well as\\n        the value to be stored (they are identical). Only valid at workgroup and subgroup levels.\\n\\n    Example (Workgroup level):\\n    ```mlir\\n        %c0 = arith.constant 0 : index\\n        xegpu.store_matrix %1, %0[%c0, %c0] <{\\n                layout = #xegpu.layout<sg_layout = [4, 8], sg_data = [32, 16]> }>\\n          : vector<128x128xf16>, !xegpu.mem_desc<128x128xf16>>, index, index\\n    ```\",\n    \"operands\": [\n      { \"name\": \"data\", \"type\": \"AnyTypeOf<[XeGPU_ValueType, XeGPU_ScalarType]>\" },\n      { \"name\": \"mem_desc\", \"type\": \"XeGPU_MemDesc\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"subgroup_block_io\", \"type\": \"OptionalAttr<UnitAttr>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$data `,` $mem_desc `` custom<DynamicIndexList>($offsets, $const_offsets)\\n                          prop-dict attr-dict `` `:` type(operands)\"\n  },\n  {\n    \"name\": \"xegpu.store_nd\",\n    \"summary\": \"stores a n-D block register region back to memory, currently only supports 2D\",\n    \"description\": \"StoreNdOp essentially mimics the hardware block write instruction io\\n    write a block of data from register into the memory region as described\\n    by the TensorDesc. It takes a set of optional cache hints for each level\\n    of cache, L1, L2 and L3. If hardware does not have a correspoding cache,\\n    Corresponding cache hint attribute will be masked.\\n    It is only available to 1D or 2D blocked tensor_desc.\\n\\n    At lane level, the input vector represents the data to be stored by each lane.\\n\\n    This operation serves as an anchor through which users assign a layout attribute\\n    to govern computation distribution.\\n\\n    Arguments:\\n\\n    - `value`: A vector value representing the tensor tile to be stored.\\n\\n    - `TensorDesc`: A tensor descriptor specifying the base nd-region of memory and\\n      the tensor tile to be stored.\\n\\n    - `offsets`: Index values representing per-dimension offsets from the base position\\n      encoded in `TensorDesc`. They are encoded via `offsets` and `const_offsets`.\\n\\n    - `l1_hint`, `l2_hint`, `l3_hint`: [optional] Cache-hint attributes indicating the\\n      desired behavior at the L1, L2, and L3 cache levels.\\n\\n    - `layout`: [optional] Describes the expected layout of the `tensor_desc` operand as well as\\n      the value to be stored (they are identical). Only valid at workgroup and subgroup levels.\\n\\n    Example 1 (Workgroup level):\\n    ```mlir\\n      xegpu.store_nd %3, %2 {l1_hint = #xegpu.cache_hint<uncached>,\\n                             l2_hint = #xegpu.cache_hint<write_back>,\\n                             l3_hint = #xegpu.cache_hint<write_through>,\\n                             layout = #xegpu.layout<sg_layout = [4, 8], sg_data = [8, 32]>}\\n                             : vector<32x256xf16>, !xegpu.tensor_desc<32x256xf16>\\n    ```\\n    Example 2 (lane level):\\n    ```mlir\\n      xegpu.store_nd %3, %2 {l1_hint = #xegpu.cache_hint<uncached>,\\n                             l2_hint = #xegpu.cache_hint<write_back>,\\n                             l3_hint = #xegpu.cache_hint<write_through>}\\n                             : vector<8xf16>, !xegpu.tensor_desc<8x16xf16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"value\", \"type\": \"XeGPU_ValueType\" },\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"OptionalAttr<DenseI64ArrayAttr>\" },\n      { \"name\": \"l1_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l2_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"l3_hint\", \"type\": \"OptionalAttr<XeGPU_CacheHintAttr{cached|uncached|streaming|read_invalidate|write_back|write_through}>\" },\n      { \"name\": \"layout\", \"type\": \"OptionalAttr<DistributeLayoutAttr>\" }\n    ],\n    \"assemblyFormat\": \"$value `,`\\n    $TensorDesc ``\\n    custom<OptionalDynamicIndexList>($offsets, $const_offsets)\\n    prop-dict attr-dict `:`  type($value) `,` qualified(type($TensorDesc))\"\n  },\n  {\n    \"name\": \"xegpu.truncf\",\n    \"summary\": \"It performs floating point truncation from higher precision to lower precision.\",\n    \"description\": \"The `xegpu.truncf` operation truncates floating point values from a higher\\n    precision type to a lower precision type.\\n    Converts `f16` and `bf16` to microscaling float types.\\n    Rounding mode defaults to round to nearest even.\\n\\n    Example:\\n    ```mlir\\n      %res = xegpu.truncf %src : vector<16xf16> -> vector<16xf8E5M2>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"FixedVectorOfNonZeroRankOf<[XeGPU_FloatType]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"FixedVectorOfNonZeroRankOf<[XeGPU_FloatType]>\" }\n    ],\n    \"assemblyFormat\": \"$source attr-dict `:` type(operands) `->` type(results)\"\n  },\n  {\n    \"name\": \"xegpu.update_nd_offset\",\n    \"summary\": \"It updates the offsets for the TensorDesc.\",\n    \"description\": \"The op updates the offset of the given TensorDesc.\\n    The offsets are relative offset to the current position in the number\\n    of elements. It will result in a same type TensorDesc as the input.\\n\\n  Example:\\n  ```\\n    %2 = xegpu.update_nd_offset %1, [0, 16]: !xegpu.tensor_desc<8x16xf32>\\n  ```\",\n    \"operands\": [\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_TensorDesc\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"const_offsets\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['TensorDesc', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$TensorDesc `,`\\n    custom<DynamicIndexList>($offsets, $const_offsets)\\n    attr-dict `:` qualified(type($result))\"\n  },\n  {\n    \"name\": \"xegpu.update_offset\",\n    \"summary\": \"It updates the offsets for the given tensor descriptor\",\n    \"description\": \"It behaves similar to `update_nd_offset` in terms that\\n    it updates offset of a TensorDesc, and the offsets are relative offset to\\n    the current position in the number of elements. However, `update_nd_offset`\\n    is to update the start point of a 2D block, so its offset constains two\\n    elements representing the shift in each dimension. `update_offset` is to\\n    update the offset per lane, so its offsets contains values representing\\n    shifts for each lane.\\n\\n    Example:\\n    ```mlir\\n      %off = arith.constant dense<[32, 32, 32, 32]> : vector<4xindex>\\n      %2 = xegpu.update_offset %1, %off :\\n              !xegpu.tensor_desc<4x2xf32, #xegpu.scattered_tdesc_attr<chunk_size=2>>, vector<4xindex>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"TensorDesc\", \"type\": \"XeGPU_TensorDesc\" },\n      { \"name\": \"offsets\", \"type\": \"XeGPU_OffsetType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XeGPU_TensorDesc\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['TensorDesc', 'result']>\" }\n    ],\n    \"assemblyFormat\": \"$TensorDesc `,` $offsets attr-dict `:` qualified(type($TensorDesc)) `,` type($offsets)\"\n  },\n  {\n    \"name\": \"xevm.blockload\",\n    \"summary\": \"subgroup block load\",\n    \"description\": \"Reads one or more components of Result data for each invocation\\n    in the subgroup from the specified `ptr` as a block operation.\\n    The data is read strided, so the first value read is:\\n    ```\\n      ptr[ SubgroupLocalInvocationId ]\\n    ```\\n    and the second value read is:\\n    ```\\n      ptr[ SubgroupLocalInvocationId + SubgroupMaxSize ]\\n    ```\\n    Result type may be a scalar or vector type of scalar element type.\\n\\n    The parameters are:\\n      * `ptr` - the base address to load from. Must be uniform across subgroup.\\n      * `cache_control` - an enumerator that sets the cache behaviour\\n\\n    Example:\\n    ```mlir\\n      %loaded_a = xevm.blockload %src,\\n                      <{cache_control=#xevm.load_cache_control<L1uc_L2uc_L3uc>}>\\n                    : (!llvm.ptr<1>) -> vector<4xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[XeVM_1DBlockElemType, FixedVectorOfRankAndType<[1], [XeVM_1DBlockElemType]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache_control\", \"type\": \"OptionalAttr<XeVM_LoadCacheControlAttr{L1uc_L2uc_L3uc|L1uc_L2uc_L3c|L1uc_L2c_L3uc|L1uc_L2c_L3c|L1c_L2uc_L3uc|L1c_L2uc_L3c|L1c_L2c_L3uc|L1c_L2c_L3c|L1s_L2uc_L3uc|L1s_L2uc_L3c|L1s_L2c_L3uc|L1s_L2c_L3c|ir}>\" }\n    ],\n    \"assemblyFormat\": \"operands prop-dict attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xevm.blockload2d\",\n    \"summary\": \"2D block load\",\n    \"description\": \"The `xevm.blockload2d` operation loads a two dimensional matrix tile\\n    from a base matrix residing in global memory. The parameters are:\\n      * `ptr` - the base address of the base matrix containing the tile to load\\n      * `base_width` - the width of the base matrix in number of bytes.\\n      * `base_height` - the number of rows in the base matrix\\n      * `base_pitch` - the physical stride between the first columns of the current\\n        row and the subsequent row in number of bytes.\\n      * `x`, `y`, `tile_width`, `tile_height` - the starting offsets and shape of\\n        the tile to load in number of elements.\\n      * `elem_size_in_bits` - the size in bits of the matrix element type\\n        - 32 for f32, tf32\\n        - 16 for f16, int16, bf16\\n        - 8 for int8\\n      * `v_blocks` - number of consecutive tiles in innermost dimension direction to load\\n      * `transpose` - transpose the tile in registers (useful for 32 bit element type)\\n      * `pack_register` - pack element types narrower than register bit width.\\n        [M, N] => [M/factor, N, factor] where factor is register_size_in_bits / elem_size_in_bits\\n      * `cache_control` - an enumerator that sets the cache behaviour\\n\\n    Notes:\\n      - the `transpose` and `pack_register` parameters are mutual exclusive\\n      - transposing the tile loaded is used for A matrix in backward path or used for the B matrix operand\\n        (D = C + A * B), where A has row-major layout and B should have column-major layout in memory.\\n      - if the tile loaded contains out of bound elements of the matrix, they are filled with 0.\\n\\n    Example:\\n    ```mlir\\n      %base_width_a = arith.constant 32 : i32\\n      %base_height_a = arith.constant 8 : i32\\n      %base_pitch_a = arith.constant 32 : i32\\n      %x = arith.constant 0 : i32\\n      %y = arith.constant 0 : i32\\n      %loaded_a = xevm.blockload2d %src, %base_width_a, %base_height_a, %base_pitch_a, %x, %y\\n                    <{elem_size_in_bits=16 : i32, tile_width=16 : i32, tile_height=8 : i32,\\n                      v_blocks=1 : i32, transpose=false : i32, pack_register=false,\\n                      cache_control=#xevm.load_cache_control<Default>}>\\n                    : (!llvm.ptr<1>, i32, i32, i32, i32, i32) -> vector<8xi16>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"base_width\", \"type\": \"I32\" },\n      { \"name\": \"base_height\", \"type\": \"I32\" },\n      { \"name\": \"base_pitch\", \"type\": \"I32\" },\n      { \"name\": \"x\", \"type\": \"I32\" },\n      { \"name\": \"y\", \"type\": \"I32\" }\n    ],\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_ElemType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elem_size_in_bits\", \"type\": \"I32Attr\" },\n      { \"name\": \"tile_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"tile_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"v_blocks\", \"type\": \"I32Attr\" },\n      { \"name\": \"transpose\", \"type\": \"I1Attr\" },\n      { \"name\": \"pack_register\", \"type\": \"I1Attr\" },\n      { \"name\": \"cache_control\", \"type\": \"OptionalAttr<XeVM_LoadCacheControlAttr{L1uc_L2uc_L3uc|L1uc_L2uc_L3c|L1uc_L2c_L3uc|L1uc_L2c_L3c|L1c_L2uc_L3uc|L1c_L2uc_L3c|L1c_L2c_L3uc|L1c_L2c_L3c|L1s_L2uc_L3uc|L1s_L2uc_L3c|L1s_L2c_L3uc|L1s_L2c_L3c|ir}>\" }\n    ],\n    \"assemblyFormat\": \"operands prop-dict attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xevm.blockprefetch2d\",\n    \"summary\": \"2D block prefetch\",\n    \"description\": \"The `xevm.blockprefetch2d` operation prefetches a two dimensional tile\\n    from a larger base matrix residing in global memory. The parameters are:\\n      * `ptr` - the base address of the base matrix containing the tile to prefetch\\n      * `base_width` - the width of the base matrix in number of bytes.\\n      * `base_height` - the number of rows in the base matrix\\n      * `base_pitch` - the physical stride between the first columns of the current\\n        row and the subsequent row in number of bytes.\\n      * `x`, `y`, `tile_width`, `tile_height` - the starting offsets and shape of tile\\n        to prefetch in number of elements.\\n      * `elem_size_in_bits` - the size in bits of the matrix element\\n        - 32 for f32, bf32\\n        - 16 for f16, int16, bf16\\n        - 8 for int8, int4, int2\\n      * `v_blocks` - number of tiles in innermost dimension direction to prefetch\\n      * `cache_control` - an enumerator that sets the cache behaviour\\n\\n    Example:\\n    ```mlir\\n      xevm.blockprefetch2d %ptr, %base_width, %base_height, %base_pitch, %x, %y\\n        <{elem_size_in_bits=8 : i32, tile_width=32 : i32, tile_height=8 : i32,\\n          v_blocks=1 : i32, cache_control=#xevm.load_cache_control<L1uc_L2uc_L3uc>}>\\n        : (!llvm.ptr<1>, i32, i32, i32, i32, i32)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"base_width\", \"type\": \"I32\" },\n      { \"name\": \"base_height\", \"type\": \"I32\" },\n      { \"name\": \"base_pitch\", \"type\": \"I32\" },\n      { \"name\": \"x\", \"type\": \"I32\" },\n      { \"name\": \"y\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elem_size_in_bits\", \"type\": \"I32Attr\" },\n      { \"name\": \"tile_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"tile_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"v_blocks\", \"type\": \"I32Attr\" },\n      { \"name\": \"cache_control\", \"type\": \"OptionalAttr<XeVM_LoadCacheControlAttr{L1uc_L2uc_L3uc|L1uc_L2uc_L3c|L1uc_L2c_L3uc|L1uc_L2c_L3c|L1c_L2uc_L3uc|L1c_L2uc_L3c|L1c_L2c_L3uc|L1c_L2c_L3c|L1s_L2uc_L3uc|L1s_L2uc_L3c|L1s_L2c_L3uc|L1s_L2c_L3c|ir}>\" }\n    ],\n    \"assemblyFormat\": \"operands prop-dict attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"xevm.blockstore\",\n    \"summary\": \"subgroup block store\",\n    \"description\": \"Writes one or more components of `val` for each invocation\\n    in the subgroup to the specified `ptr` as a block operation.\\n    The data is written strided, so the first value is written to:\\n    ```\\n      ptr[ SubgroupLocalInvocationId ]\\n    ```\\n    and the second value is written to:\\n    ```\\n      ptr[ SubgroupLocalInvocationId + SubgroupMaxSize ]\\n    ```\\n    `val` type may be a scalar or vector type of scalar element type.\\n\\n    The parameters are:\\n      * `ptr` - the base address to store to. Must be uniform across subgroup.\\n      * `val` - the value to store\\n      * `cache_control` - an enumerator that sets the cache behaviour\\n\\n    Example:\\n    ```mlir\\n      xevm.blockstore %ptr, %val\\n        <{cache_control=#xevm.store_cache_control<L1uc_L2uc_L3uc>}>\\n        : (!llvm.ptr<1>, vector<4xi16>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"val\", \"type\": \"AnyTypeOf<[XeVM_1DBlockElemType, FixedVectorOfRankAndType<[1], [XeVM_1DBlockElemType]>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache_control\", \"type\": \"OptionalAttr<XeVM_StoreCacheControlAttr{L1uc_L2uc_L3uc|L1uc_L2uc_L3wb|L1uc_L2wb_L3uc|L1uc_L2wb_L3wb|L1wt_L2uc_L3uc|L1wt_L2uc_L3wb|L1wt_L2wb_L3uc|L1wt_L2wb_L3wb|L1s_L2uc_L3uc|L1s_L2uc_L3wb|L1s_L2wb_L3uc|L1s_L2wb_L3wb|L1wb_L2uc_L3uc|L1wb_L2wb_L3uc|L1wb_L2uc_L3wb}>\" }\n    ],\n    \"assemblyFormat\": \"operands prop-dict attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"xevm.blockstore2d\",\n    \"summary\": \"2D block store\",\n    \"description\": \"The `xevm.blockstore2d` operation stores a two dimensional tile into a\\n    larger matrix residing in global memory. The parameters are:\\n      * `ptr` - the base address of the target matrix where to store the tile\\n      * `base_width` - the width of the base matrix in number of bytes.\\n      * `base_height` - the number of rows in the base matrix\\n      * `base_pitch` - the physical stride between the first columns of the current\\n        row and the subsequent row in number of bytes.\\n      * `x`, `y`, `tile_width`, `tile_height` - the starting offsets and shape of the tile to store\\n      in number of elements.\\n      * `elem_size_in_bits` - the size in bits of the matrix element\\n        - 32 for f32, tf32\\n        - 16 for f16, int16, bf16\\n        - 8 for int8\\n      * `cache_control` - an enumerator that sets the cache behaviour\\n      * `stored_val` - the tile to store\\n\\n    Example:\\n    ```mlir\\n      %base_width_c = arith.constant 64 : i32\\n      %base_height_c = arith.constant 8 : i32\\n      %base_pitch_c = arith.constant 64 : i32\\n      %x = arith.constant 0 : i32\\n      %y = arith.constant 0 : i32\\n      xevm.blockstore2d %dst, %base_width_c, %base_height_c, %base_pitch_c, %x, %y, %src\\n        <{elem_size_in_bits=32 : i32, tile_width=16 : i32, tile_height=8 : i32,\\n          cache_control=#xevm.load_cache_control<Default>}>\\n        : (!llvm.ptr<1>, i32, i32, i32, i32, i32, vector<8xi32>)\\n    ```\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"LLVM_AnyPointer\" },\n      { \"name\": \"base_width\", \"type\": \"I32\" },\n      { \"name\": \"base_height\", \"type\": \"I32\" },\n      { \"name\": \"base_pitch\", \"type\": \"I32\" },\n      { \"name\": \"x\", \"type\": \"I32\" },\n      { \"name\": \"y\", \"type\": \"I32\" },\n      { \"name\": \"stored_val\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_ElemType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"elem_size_in_bits\", \"type\": \"I32Attr\" },\n      { \"name\": \"tile_width\", \"type\": \"I32Attr\" },\n      { \"name\": \"tile_height\", \"type\": \"I32Attr\" },\n      { \"name\": \"cache_control\", \"type\": \"OptionalAttr<XeVM_StoreCacheControlAttr{L1uc_L2uc_L3uc|L1uc_L2uc_L3wb|L1uc_L2wb_L3uc|L1uc_L2wb_L3wb|L1wt_L2uc_L3uc|L1wt_L2uc_L3wb|L1wt_L2wb_L3uc|L1wt_L2wb_L3wb|L1s_L2uc_L3uc|L1s_L2uc_L3wb|L1s_L2wb_L3uc|L1s_L2wb_L3wb|L1wb_L2uc_L3uc|L1wb_L2wb_L3uc|L1wb_L2uc_L3wb}>\" }\n    ],\n    \"assemblyFormat\": \"operands prop-dict attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"xevm.group_count.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.group_count.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.group_count.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.group_id.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.group_id.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.group_id.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.lane_id\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.local_id.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.local_id.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.local_id.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.local_size.x\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.local_size.y\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.local_size.z\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.memfence\",\n    \"summary\": \"Work-item's memory fence.\",\n    \"description\": \"This operation ensures that all prior memory accesses of this\\n    work-item to `addrspace` are visible to all other work-items in `scope`.\\n    Parameters description:\\n      * `scope` - specify the memory scope at which all other work-items should observe\\n        memory operations prior to the fence.\\n      * `addrspace` - specify the address space of work-item's memory accesses\\n        to be affected by the fence.\",\n    \"attributes\": [\n      { \"name\": \"scope\", \"type\": \"XeVM_MemScopeAttr{lane|subgroup|workgroup|cluster|device|system}\" },\n      { \"name\": \"addrspace\", \"type\": \"DefaultValuedAttr<XeVM_AddrSpaceAttr{private|global|constant|shared|generic}, mlir::xevm::AddrSpace::GENERIC>\" }\n    ],\n    \"assemblyFormat\": \"prop-dict  attr-dict\"\n  },\n  {\n    \"name\": \"xevm.mma\",\n    \"summary\": \"Subgroup matrix multiply-add\",\n    \"description\": \"The `xevm.mma` is a cooperative operation where all threads/lanes in\\n    a subgroup participates and carries out matrix multiplication plus accumulation:\\n\\n      D = C + A x B\\n\\n      where the A, B, C input matrices and the result D have shapes:\\n        - D : MxN\\n        - C : MxN\\n        - A : MxK\\n        - B : KxN\\n\\n    Parameters:\\n      * `a` - vector of matrix A elements.\\n      * `b` - vector of matrix B elements.\\n      * `c` - (optional) vector of matrix C elements.\\n      * `shape` - the shape of the matrices, specified as `M`, `N`, and `K` values.\\n      * `types` - the data types of the matrices, specified as `D`, `A`, `B`, and optionally `C`.\\n\\n    Example:\\n    ```mlir\\n      %d = xevm.mma %a, %b, %c { shape=<m=8, n=16, k=16>, types=<d=f32, a=f16, b=f16, c=f32> }\\n             : (vector<8xi16>, vector<8xi32>, vector<8xf32>) -> vector<8xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_MatrixElemType]>\" },\n      { \"name\": \"b\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_MatrixElemType]>\" },\n      { \"name\": \"c\", \"type\": \"Optional<FixedVectorOfRankAndType<[ 1 ], [ XeVM_MatrixElemType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"d\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_MatrixElemType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"XeVM_MMAShapeAttr\" },\n      { \"name\": \"types\", \"type\": \"XeVM_MMATypesAttr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b (`,` $c^)? ` `\\n    `{`\\n      `shape` `=` $shape `,`\\n      `types` `=` $types\\n    `}` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xevm.mma_mx\",\n    \"summary\": \"Subgroup matrix multiply-add with MxN shape and MX scaling\",\n    \"description\": \"The `xevm.mma_mx` is similar to `xevm.mma` has scale operands for A and B matrices.\\n    It is a cooperative operation where all threads/lanes in a subgroup participates\\n    and carries out matrix multiplication plus accumulation:\\n\\n      D = C + A x B\\n\\n      where the A, B, C input matrices and the result D have shapes:\\n        - D : MxN\\n        - C : MxN\\n        - A : MxK\\n        - B : KxN\\n\\n    Parameters:\\n      * `a` - vector of matrix A elements.\\n      * `b` - vector of matrix B elements.\\n      * `scale_a` - vector of scaling factors for matrix A.\\n      * `scale_b` - vector of scaling factors for matrix B.\\n      * `c` - (optional) vector of matrix C elements.\\n      * `shape` - the shape of the matrices, specified as `M`, `N`, and `K` values.\\n      * `types` - the data types of the matrices, specified as `D`, `A`, `B`, and optionally `C`.\",\n    \"operands\": [\n      { \"name\": \"a\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_MatrixElemType]>\" },\n      { \"name\": \"b\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_MatrixElemType]>\" },\n      { \"name\": \"scale_a\", \"type\": \"FixedVectorOfRankAndType<[1], [I8]>\" },\n      { \"name\": \"scale_b\", \"type\": \"FixedVectorOfRankAndType<[1], [I8]>\" },\n      { \"name\": \"c\", \"type\": \"Optional<FixedVectorOfRankAndType<[ 1 ], [ XeVM_MatrixElemType ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"d\", \"type\": \"FixedVectorOfRankAndType<[1], [XeVM_MatrixElemType]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shape\", \"type\": \"XeVM_MMAShapeAttr\" },\n      { \"name\": \"types\", \"type\": \"XeVM_MMATypesAttr\" }\n    ],\n    \"assemblyFormat\": \"$a `,` $b `,` $scale_a `,` $scale_b (`,` $c^)? ` `\\n    `{`\\n      `shape` `=` $shape `,`\\n      `types` `=` $types\\n    `}` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xevm.prefetch\",\n    \"summary\": \"Prefetch data into a cache subsystem.\",\n    \"description\": \"Work-item issues a prefetch from global memory to cache:\\n      * `ptr` - LLVM pointer with address space. Address space must be 1 (global)\\n        or 4 (generic)\\n      * `cache_control` - specify caching options\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"AnyTypeOf<[ LLVM_PointerInAddressSpace < 1 >, LLVM_PointerInAddressSpace < 4 > ]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"cache_control\", \"type\": \"OptionalAttr<XeVM_LoadCacheControlAttr{L1uc_L2uc_L3uc|L1uc_L2uc_L3c|L1uc_L2c_L3uc|L1uc_L2c_L3c|L1c_L2uc_L3uc|L1c_L2uc_L3c|L1c_L2c_L3uc|L1c_L2c_L3c|L1s_L2uc_L3uc|L1s_L2uc_L3c|L1s_L2c_L3uc|L1s_L2c_L3c|ir}>\" }\n    ],\n    \"assemblyFormat\": \"operands prop-dict attr-dict `:` `(` type(operands) `)`\"\n  },\n  {\n    \"name\": \"xevm.subgroup_id\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.subgroup_size\",\n    \"results\": [\n      { \"name\": \"res\", \"type\": \"AnyTypeOf<[I32, I64]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"range\", \"type\": \"OptionalAttr<LLVM_ConstantRangeAttr>\" }\n    ],\n    \"assemblyFormat\": \"(`range` $range^)? attr-dict `:` type($res)\"\n  },\n  {\n    \"name\": \"xevm.truncf\",\n    \"summary\": \"Floating point truncation from f16/bf16 to f8/bf8/f4\",\n    \"description\": \"The `xevm.truncf` operation truncates a floating point value from\\n    f16/bf16 to f8/bf8/f4 format.\",\n    \"operands\": [\n      { \"name\": \"src\", \"type\": \"AnyTypeOf<[VectorOfRankAndType<[1], [F16, BF16]>, F16, BF16]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"dst\", \"type\": \"AnyTypeOf<[VectorOfRankAndType<[1], [I8, I<4>]>, I8, I<4>]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src_etype\", \"type\": \"XeVM_TruncfSrcElemTypeAttr\" },\n      { \"name\": \"dst_etype\", \"type\": \"XeVM_TruncfDstElemTypeAttr\" }\n    ],\n    \"assemblyFormat\": \"$src ` ` `{` $src_etype `,` $dst_etype `}` attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xla_cpu.extract_workgroup_id\",\n    \"summary\": \"Extracts the workgroup id from the call frame\",\n    \"description\": \"Given a call frame, returns the workgroup id in the dimension provided.\\n\\n    ```mlir\\n    %0 = xla_cpu.extract_workgroup_id %call_frame, x\\n    %1 = xla_cpu.extract_workgroup_id %call_frame, y\\n    %2 = xla_cpu.extract_workgroup_id %call_frame, z\\n    ```\",\n    \"operands\": [\n      { \"name\": \"call_frame\", \"type\": \"XLACPU_CallFrame\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"WorkGroupDimensionAttr{x|y|z}\" }\n    ],\n    \"assemblyFormat\": \"$call_frame `,` $dimension attr-dict\"\n  },\n  {\n    \"name\": \"xla_cpu.load\",\n    \"summary\": \"Loads a tensor from an XLA:CPU call frame\",\n    \"description\": \"Loads a tensor from an XLA:CPU call frame at the given index.\\n\\n    ```mlir\\n    %0 = xla_cpu.load %call_frame, 0 : tensor<32x32xf32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"call_frame\", \"type\": \"XLACPU_CallFrame\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"TensorOrMemRef\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$call_frame `,` $index attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"xla_cpu.success\",\n    \"summary\": \"Creates an !xla_cpu.error in the 'success' state.\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"XLACPU_Error\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"xla_framework.buffer_to_mem\",\n    \"summary\": \"Creation of memref from XLA buffer pointer\",\n    \"description\": \"This convert's between XLA's representation of a buffer and standard MLIR's\\n    representation of memrefs.\\n\\n    This will be lowered to LLVM logic that will take a pointer and create a\\n    memref descriptor based on the static information for the memref.\",\n    \"operands\": [\n      { \"name\": \"buffer\", \"type\": \"XLAFramework_BufferType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"assemblyFormat\": \"$buffer attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"xla_framework.mem_to_buffer\",\n    \"summary\": \"Creation of XLA buffer pointer from memref\",\n    \"description\": \"This convert's between XLA's and standard MLIR's representations of memrefs.\\n\\n    This will be lowered to LLVM logic that will pass through a memref's\\n    pointer.\",\n    \"operands\": [\n      { \"name\": \"memref\", \"type\": \"AnyRankedOrUnrankedMemRef\" }\n    ],\n    \"results\": [\n      { \"name\": \"buffer\", \"type\": \"XLAFramework_BufferType\" }\n    ],\n    \"assemblyFormat\": \"$memref attr-dict `:` type($memref)\"\n  },\n  {\n    \"name\": \"xla_gpu.allocate_shared\",\n    \"summary\": \"Allocates a shared memory tile.\",\n    \"description\": \"Allocates a shared memory tensor. The tensor is shared among all threads in\\n    a block.\\n\\n    ```mlir\\n    %shared = xla_gpu.allocate_shared : tensor<32x32xf32>\\n    ```\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStaticShapeTensor\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"xla_gpu.insert\",\n    \"summary\": \"Inserts an indexed vector into a tensor\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"XLAGPU_IndexedVectorType\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"dest\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"map\", \"type\": \"XLA_IndexingMapAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'result', 'dest', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$source `(` $indices `)` `into` $dest `at` $map attr-dict `:` type($source) `->` type($result)\"\n  },\n  {\n    \"name\": \"xla_gpu.pdl_wait\",\n    \"summary\": \"Waits for upstream dependencies.\"\n  },\n  {\n    \"name\": \"xla_gpu.reduce\",\n    \"summary\": \"Performs a reduction\",\n    \"description\": \"The `xla_gpu.reduce` op performs a variadic reduction of the provided\\n    operands using the list of dimensions and a symbol for a combiner function.\\n\\n    ```mlir\\n    func.func @add(%a_acc: f32, %b_acc: i32, %a: f32, %b: i32)\\n        -> (f32, i32) {\\n      %0 = arith.addf %a_acc, %a : f32\\n      %1 = arith.addi %b_acc, %b : i32\\n      func.return %0, %1 : f32, i32\\n    }\\n    %sum:2 = xla_gpu.reduce (%in0, %in1) inits(%init0, %init1) dimensions=[0, 2]\\n      combiner=@add : tensor<16x8x4xf32>, tensor<16x8x4xi32>\\n        to tensor<8xf32>, tensor<8xi32>\\n    ```\",\n    \"operands\": [\n      { \"name\": \"inputs\", \"type\": \"Variadic<AnyRankedTensor>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimensions\", \"type\": \"ConfinedAttr<DenseI64ArrayAttr, [DenseArrayStrictlySorted<DenseI64ArrayAttr>]>\" },\n      { \"name\": \"combiner\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xla_gpu.shuffle_reduce\",\n    \"summary\": \"Performs a full warp shuffle and reduces the values\",\n    \"description\": \"This op performs a full warp shuffle and reduces the results using the given\\n    function. The function is invoked with the operands from the low lanes,\\n    followed by the operands from the high lanes. For example:\\n\\n    ```\\n    %result:2 = xla_gpu.shuffle_reduce (%in0, %in1) to 16 combiner=@argmax\\n    ```\\n\\n    Will perform shuffles with distance 16, 8, 4, 2 and 1, and will invoke\\n    @argmax five times. The first invocations will be\\n\\n    ```\\n    @argmax(%in0[i], %in1[i], %in0[16+i], %in1[16+i])\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"combiner\", \"type\": \"FlatSymbolRefAttr\" },\n      { \"name\": \"max_distance\", \"type\": \"I64Attr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operands', 'results', '$_self'>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xla_gpu.sync_threads\",\n    \"summary\": \"Synchronizes threads.\",\n    \"description\": \"Synchronizes threads, taking any number of distributed tensors and returning\\n    the synchronized state.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyRankedTensor>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'operands', 'results', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` type($operands)\"\n  },\n  {\n    \"name\": \"xla.apply_indexing\",\n    \"summary\": \"Applies indexing map to a list of SSA values\",\n    \"description\": \"The `apply_indexing` operation applies an indexing_map to a list\\n    of SSA values, yielding a single SSA value. The number of dimension and\\n    symbol arguments must be equal to the respective number of dimensional and\\n    symbolic inputs in the indexing_map. The index mapping can be\\n    multi-dimensional, and so the `apply_indexing` operation always returns one\\n    value. The operands and results must all have ‘index’ type.\\n\\n    Example:\\n\\n    ```mlir\\n    #map = #xla.indexing_map<(d0, d1)[s0] -> (d0 floordiv 8 + d1 floordiv 128, s0)>\\n    %results:2 = xla_ops.apply_indexing #map (%0 in [0, 10], %1 in [0, 11])[%2 in [11, 32]]\\n    ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_map_attr\", \"type\": \"XLA_IndexingMapAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xla.atomic_rmw\",\n    \"summary\": \"Atomically updates an element of a tensor.\",\n    \"description\": \"Reads an element from a tensor, computes the updated value for it, and\\n    writes back the result.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"regions\": [\n      { \"name\": \"computation\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'input', 'result', '$_self'>\" }\n    ],\n    \"assemblyFormat\": \"$input `[` $indices `]` `:` type($input) $computation attr-dict\"\n  },\n  {\n    \"name\": \"xla.get_dynamic_dim_size\",\n    \"summary\": \"Returns the dynamic size of a dimension. The dynamic sizes are stored in the same buffer, after the main values as an array of s32. The `dim` argument can be larger than `tensor`'s rank, because XLA has passes like flatten_tensors that only change the view of the memory.\",\n    \"operands\": [\n      { \"name\": \"tensor\", \"type\": \"AnyStaticShapeTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"I32\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$tensor $dim attr-dict `:` type($tensor)\"\n  },\n  {\n    \"name\": \"xla.loop\",\n    \"summary\": \"Loop nest that iterates over all feasible values of RangeVars.\",\n    \"description\": \"```mlir\\n      #map = #xla.indexing_map<(d0)[s0, s1] -> (d0 + s0, s1),\\n        domain:\\n        d0 in [0, 3],\\n        s0 in [0, 1024],\\n        s1 in [0, 32]\\n      >\\n      // Initial sum set to 0.\\n      %sum_0 = arith.constant 0.0 : f32\\n      %dim = arith.constant 1 : index\\n      // iter_args binds initial values to the loop's region arguments.\\n      %sum = xla.loop (%dim)[%i, %j] -> (%r0, %r1)\\n          in #map iter_args(%sum_iter = %sum_0) -> (f32) {\\n        %t = tensor.extract %buffer[%i, %j] : tensor<1024x32xf32>\\n        %sum_next = arith.addf %sum_iter, %t : f32\\n        // Yield current iteration sum to next iteration %sum_iter or to %sum\\n        // if final iteration.\\n        xla.yield %sum_next : f32\\n      }\\n    ```\",\n    \"operands\": [\n      { \"name\": \"dims\", \"type\": \"Variadic<Index>\" },\n      { \"name\": \"inits\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"indexing_map_attr\", \"type\": \"XLA_IndexingMapAttr\" }\n    ],\n    \"regions\": [\n      { \"name\": \"region\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xla.predicated_extract\",\n    \"summary\": \"Extracts a value from a tensor if a condition holds\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"fallback\", \"type\": \"AnyType\" },\n      { \"name\": \"src\", \"type\": \"AnyStaticShapeTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyType\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'src', 'fallback', '::llvm::cast<mlir::TensorType>($_self).getElementType()'>\" },\n      { \"type\": \"TypesMatchWith<'src', 'result', '::llvm::cast<mlir::TensorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$src `[` $indices `]` `if` $condition `else` $fallback attr-dict `:` type($src)\"\n  },\n  {\n    \"name\": \"xla.predicated_insert\",\n    \"summary\": \"Inserts a value into a tensor if a condition holds\",\n    \"operands\": [\n      { \"name\": \"condition\", \"type\": \"I1\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" },\n      { \"name\": \"dest\", \"type\": \"AnyStaticShapeTensor\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyStaticShapeTensor\" }\n    ],\n    \"traits\": [\n      { \"type\": \"TypesMatchWith<'dest', 'result', '$_self'>\" },\n      { \"type\": \"TypesMatchWith<'dest', 'value', '::llvm::cast<mlir::TensorType>($_self).getElementType()'>\" }\n    ],\n    \"assemblyFormat\": \"$value `into` $dest `[` $indices `]` `if` $condition attr-dict `:` type($dest)\"\n  },\n  {\n    \"name\": \"xla.pure_call\",\n    \"summary\": \"Function call without side effects.\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"callee\", \"type\": \"FlatSymbolRefAttr\" }\n    ],\n    \"assemblyFormat\": \"$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)\"\n  },\n  {\n    \"name\": \"xla.workgroup_id\",\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"Index\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dimension\", \"type\": \"WorkGroupDimensionAttr{x|y|z}\" }\n    ],\n    \"assemblyFormat\": \"$dimension attr-dict\"\n  },\n  {\n    \"name\": \"xla.yield\",\n    \"summary\": \"Terminator for atomic_rmw ops.\",\n    \"operands\": [\n      { \"name\": \"result\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"$result attr-dict `:` type($result)\"\n  },\n  {\n    \"name\": \"xsmm.binary.dispatch\",\n    \"summary\": \"Generate a binary kernel for a specific tile size.\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"XSMM_BinaryKind{NONE|ADD|MUL|SUB|DIV|MULADD|MATMUL|MUL_AND_REDUCE_TO_SCALAR_OP_ADD|PACK}\" },\n      { \"name\": \"compute_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ldi1\", \"type\": \"I64Attr\" },\n      { \"name\": \"ldi2\", \"type\": \"I64Attr\" },\n      { \"name\": \"ldo\", \"type\": \"I64Attr\" },\n      { \"name\": \"func_type\", \"type\": \"FuncTypeAttr\" },\n      { \"name\": \"bcastType1\", \"type\": \"I32Attr\" },\n      { \"name\": \"bcastType2\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$kind `(` `bcast1` $bcastType1 `bcast2` $bcastType2 `ldo`\\n              $ldo `ldi2` $ldi2 `ldi1` $ldi1 `tile` $tile `compute` $compute_type `func` $func_type `)` attr-dict `:` type($ptr)\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.binary.invoke\",\n    \"summary\": \"Invoke a previously generated binary kernel.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"output\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"input1\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"input2\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.beta.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strideA\", \"type\": \"I64Attr\" },\n      { \"name\": \"strideB\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.bias.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strideA\", \"type\": \"I64Attr\" },\n      { \"name\": \"strideB\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.bias.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strideA\", \"type\": \"I64Attr\" },\n      { \"name\": \"strideB\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.bias.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.bias.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" },\n      { \"name\": \"aOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"bOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" },\n      { \"name\": \"aOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"bOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.relu.beta1.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.relu.beta1.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" },\n      { \"name\": \"aOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"bOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.relu.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.offs.relu.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" },\n      { \"name\": \"aOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"bOffsets\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.relu.beta.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.relu.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"strideA\", \"type\": \"I64Attr\" },\n      { \"name\": \"strideB\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.brgemm.relu.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"numBatches\", \"type\": \"I64Attr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.bias.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM and relu shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.bias.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.relu.beta.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM and relu shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.relu.beta.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.relu.dispatch.f32\",\n    \"summary\": \"query LIBXSMM's code registry based on GEMM and relu shape\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"tileld\", \"type\": \"TypedArrayAttrBase<I64Attr>\" }\n    ],\n    \"assemblyFormat\": \"$tile `,` $tileld attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.gemm.relu.invoke.f32\",\n    \"summary\": \"invoke a previously queried LIBXSMM kernel\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"c\", \"type\": \"F32MemRef\" },\n      { \"name\": \"a\", \"type\": \"F32MemRef\" },\n      { \"name\": \"b\", \"type\": \"F32MemRef\" },\n      { \"name\": \"d\", \"type\": \"F32MemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.unary.dispatch\",\n    \"summary\": \"Generate a unary kernel for a specific tile size.\",\n    \"results\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"kind\", \"type\": \"XSMM_UnaryKind{NONE|IDENTITY|XOR|X2|SQRT|RELU|RELU_INV|TANH|TANH_INV|SIGMOID|SIGMOID_INV|GELU|GELU_INV|NEGATE|INC|RECIPROCAL|RECIPROCAL_SQRT|EXP|REDUCE_X_OP_ADD|REDUCE_X2_OP_ADD|REDUCE_X_X2_OP_ADD|REDUCE_X_OP_MAX|REDUCE_X_OP_MUL|REDUCE_X_OP_ADD_NCNC_FORMAT|REDUCE_TO_SCALAR_OP_ADD|DROPOUT|DROPOUT_INV|REPLICATE_COL_VAR|TRANSFORM_NORM_TO_VNNI|TRANSFORM_NORM_TO_NORMT|TRANSFORM_VNNI_TO_VNNIT|TRANSFORM_NORM_TO_VNNIT|TRANSFORM_NORM_TO_VNNI_PAD|UNPACK_TO_BLOCKS|LEAKY_RELU|LEAKY_RELU_INV|ELU|ELU_INV|STOCHASTIC_ROUND}\" },\n      { \"name\": \"compute_type\", \"type\": \"TypeAttr\" },\n      { \"name\": \"tile\", \"type\": \"TypedArrayAttrBase<I64Attr>\" },\n      { \"name\": \"ldi\", \"type\": \"I64Attr\" },\n      { \"name\": \"ldo\", \"type\": \"I64Attr\" },\n      { \"name\": \"func_type\", \"type\": \"FuncTypeAttr\" },\n      { \"name\": \"bcastType\", \"type\": \"I32Attr\" }\n    ],\n    \"assemblyFormat\": \"$kind `(` $compute_type `,` $tile `,` $ldi `,` $ldo `,` $bcastType `)`\\n    `:` $func_type attr-dict\",\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xsmm.unary.invoke\",\n    \"summary\": \"Invoke a previously generated unary kernel.\",\n    \"operands\": [\n      { \"name\": \"ptr\", \"type\": \"I64\" },\n      { \"name\": \"output\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"input\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"indices\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xten_nn.atan2\",\n    \"summary\": \"Calculate the atan2 of input/other of a given pair of tensor element-wise.\",\n    \"description\": \"Calculate the arctangent of input/other of a given pair of tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"XTenNN_AnyFloatTensor\" },\n      { \"name\": \"other\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.ConvTranspose\",\n    \"summary\": \"Perform ConvTranspose operation\",\n    \"description\": \"This operation is equivalent to `onnx.ConvTranspose` and computes the ConvTranspose.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"4DTensorOf<[AnyFloat]>\" },\n      { \"name\": \"weights\", \"type\": \"4DTensorOf<[AnyFloat]>\" },\n      { \"name\": \"bias\", \"type\": \"1DTensorOf<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"4DTensorOf<[AnyFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ArrayAttr<2>\" },\n      { \"name\": \"output_padding\", \"type\": \"I64DenseArrayAttr<2>\" },\n      { \"name\": \"stride\", \"type\": \"I64DenseArrayAttr<2>\" },\n      { \"name\": \"dilation\", \"type\": \"I64DenseArrayAttr<2>\" },\n      { \"name\": \"group\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.depth_to_space\",\n    \"summary\": \"Performs resizing to an image.\",\n    \"description\": \"Permutes data from depth into blocks of spatial data.\\n    Outputs a copy of the input tensor where values from the depth dim are moved to the H and W dimension.\\n    Blocksize: The size of the blocks being moved.\\n    Mode:\\n    - 1: DCR: Elements are rearranged in order Depth - Column - Row\\n    - 2: CRD: Elements rearranged in order Column - Row - Depth\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"4DTensorOf<[XTenNN_AnyIntegerOrFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"4DTensorOf<[XTenNN_AnyIntegerOrFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"blocksize\", \"type\": \"I64Attr\" },\n      { \"name\": \"mode\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.dequantize\",\n    \"summary\": \"Dequantizes a signless/unsigned integer tensor of given bitwidth to a float tensor.\",\n    \"description\": \"Dequantizes a signless/unsigned integer tensor of given bitwidth to a float tensor.\\n    Since tosa is using signless/unsigned types currently, we also consider signless integer types for\\n    signed ones when the type is not unsigned until tosa support signed integers.\\n\\n    Applies the following linear dequantization to the input tensor x:\\n      y = (x - zero_point) * scale\\n\\n    Iff log2(scale) is representable as si32 and zero_point == 0, shift is set to log2(scale).\\n    In this case the dequantization is equal to:\\n      y = x  * ( 2^shift )\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"XTenNN_AnySignlessOrUnsignedIntegerTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shift\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"scale\", \"type\": \"F32Attr\" },\n      { \"name\": \"zero_point\", \"type\": \"XTenNN_AnyIntegerAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xten_nn.elu\",\n    \"summary\": \"Calculate the elu operation of the given input tensor element-wise\",\n    \"description\": \"Calculate the elu operation (Exponential Linear Unit) of the given input tensor element-wise.\\n    ELU(x) =  x,                  if x >  0\\n              alpha * (exp(x)-1), if x <= 0\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"F32Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.grid_sample\",\n    \"summary\": \"Performs gridsampling given an input and a flow-field grid.\",\n    \"description\": \"This operation is equivalent to `onnx.GridSample`, and computes the output value through\\n    the interpolation of the flow-field grid and the input.\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"AnyTensor\" },\n      { \"name\": \"grid\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\", \"type\": \"I64Attr\" },\n      { \"name\": \"mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"padding_mode\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.group_conv2d\",\n    \"summary\": \"Grouped convolution with multiple channel outputs per layer\",\n    \"description\": \"Calculates separates convolutions with multiple channel outputs per layer.\\n\\n    This operations expects the same TORCH/ONNX's Conv2d datalayout specification for input and\\n    weight [NxCxHxW].\\n\\n    Pad attribute is expected to be two arrays of i64 values, eg: [[0,1], [2,2]]. First and second\\n    arrays denote the initial and end padding for H and W dimensions respectively.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"4DTensorOf<[AnyFloat]>\" },\n      { \"name\": \"weights\", \"type\": \"4DTensorOf<[AnyFloat]>\" },\n      { \"name\": \"bias\", \"type\": \"1DTensorOf<[AnyFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"4DTensorOf<[AnyFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pad\", \"type\": \"ArrayAttr<2>\" },\n      { \"name\": \"stride\", \"type\": \"I64DenseArrayAttr<2>\" },\n      { \"name\": \"dilation\", \"type\": \"I64DenseArrayAttr<2>\" },\n      { \"name\": \"group\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.group_dequantize\",\n    \"summary\": \"Group dequantizes an integer tensor of given width to a float32 tensor.\",\n    \"description\": \"Dequantizes an integer tensor of given width to a float32 tensor.\\n\\n    Scales and zeros must have a shape that is broadcastable to the quants shape.\\n    Output and scales most have the same dtype, as must zeros and quants.\\n    The range of values in zeros and quants is given by the min and max attributes,\\n    and the bits attribute gives the number of integer bits required for that range.\\n\\n    Applies the following linear dequantization to the input tensor x:\\n      output[a][b][c] = (quants[a][b][c] - zeros[a][b][c]) * scales[a][b][c]\",\n    \"operands\": [\n      { \"name\": \"quants\", \"type\": \"XTenNN_AnySignlessOrUnsignedIntegerTensor\" },\n      { \"name\": \"scales\", \"type\": \"XTenNN_AnyFloatTensor\" },\n      { \"name\": \"zeros\", \"type\": \"XTenNN_AnySignlessOrUnsignedIntegerTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"SI32Attr\" },\n      { \"name\": \"max\", \"type\": \"SI32Attr\" },\n      { \"name\": \"bits\", \"type\": \"SI32Attr\" }\n    ],\n    \"assemblyFormat\": \"`(`$quants `:` type($quants) `,` $scales `:` type($scales)`,` $zeros `:` type($zeros)`)` attr-dict `->` type($output)\"\n  },\n  {\n    \"name\": \"xten_nn.group_quantize\",\n    \"summary\": \"Group quantizes a float32 tensor to an integer tensor of given width.\",\n    \"description\": \"Quantizes a given float32 tensor into a integer tensor of given width.\\n\\n    Scales and zeros must have a shape that is broadcastable to the input shape.\\n    Input and scales most have the same dtype, as must zeros and quants.\\n    The range of values in zeros and quants is given by the min and max attributes,\\n    and the bits attribute gives the number of integer bits required for that range.\\n\\n    Applies the following linear quantization:\\n      quants[a][b][c] = round( (input[a][b][c] / scales[a][b][c]) + zeros[a][b][c] )\\n\\n    Round will saturate to the range of the output type and the rounding mode is set to half\\n    to nearest even.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"XTenNN_AnyFloatTensor\" },\n      { \"name\": \"scales\", \"type\": \"XTenNN_AnyFloatTensor\" },\n      { \"name\": \"zeros\", \"type\": \"XTenNN_AnySignlessOrUnsignedIntegerTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"quants\", \"type\": \"XTenNN_AnySignlessOrUnsignedIntegerTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"SI32Attr\" },\n      { \"name\": \"max\", \"type\": \"SI32Attr\" },\n      { \"name\": \"bits\", \"type\": \"SI32Attr\" }\n    ],\n    \"assemblyFormat\": \"`(`$input `:` type($input) `,` $scales `:` type($scales) `,` $zeros `:` type($zeros)`)` attr-dict `->` type($quants)\"\n  },\n  {\n    \"name\": \"xten_nn.kernel\",\n    \"summary\": \"An opaque kernel\",\n    \"description\": \"The `xten_nn.kernel` operation defines an opaque computation with a name.\\n        Example:\\n        ```\\n          %c = xten_nn.kernel \\\"myKernel\\\" (%arg0 : tensor<2xi64>) {attr = 4 : i32} -> tensor<2xi64>\\n          %d:2 = xten_nn.kernel \\\"frob\\\" (%arg0 : tensor<2xi64>, %arg1 : tensor<4xi64>) -> tensor<2xi64>, tensor<1xi64>\\n          %e = xten_nn.kernel \\\"matmul\\\" (%arg0 : tensor<2xi64>) instantiation_args {N = 42 : i32} {attr = 4 : i32} -> tensor<2xi64>\\n        ```\",\n    \"operands\": [\n      { \"name\": \"arguments\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"name\", \"type\": \"StrAttr\" },\n      { \"name\": \"instantiation_args\", \"type\": \"OptionalAttr<ArrayAttr>\" },\n      { \"name\": \"instantiation_arg_names\", \"type\": \"OptionalAttr<ArrayAttr>\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xten_nn.load_external_const\",\n    \"summary\": \"Loads a constant from an external source as a const operator.\",\n    \"description\": \"Represents a constant value that can be provided by a `method`, but the values are not otherwise available.\\n    The `method` is compiler-known and implemented, and not defined by this operation.\\n    The default conceptual `method` is \\\"h5\\\", indicating that the value is stored in an h5 `file` at index `key`.\\n\\n    Unfortunately, this operation cannot carry the ConstantLike trait as a Fold operation\\n    is required to be implemented for constants. For this particular operation we cannot return\\n    a sensible value as other dialect constants do since the value is stored within a file.\\n\\n    This implementation follows closely to what `ml_program.global_load_const` implements. As it too\\n    does not implement the ConstantLike trait.\",\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"key\", \"type\": \"StrAttr\" },\n      { \"name\": \"file\", \"type\": \"StrAttr\" },\n      { \"name\": \"method\", \"type\": \"OptionalAttr<StrAttr>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict `->` type($output)\"\n  },\n  {\n    \"name\": \"xten_nn.mish\",\n    \"summary\": \"Calculate the mish operation of the given input tensor element-wise\",\n    \"description\": \"Calculate the mish operation (Self Regularized Non-Monotonic Neural Activation Function) of the given input tensor element-wise.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.output\",\n    \"summary\": \"Defines the output value of a subgraph or node\",\n    \"description\": \"The `xten_nn.output` operation serves as the terminator for XTenNN operations\\n        that declare a region that produces result values.\\n\\n        Example:\\n        ```mlir\\n        %sum = xten_nn.subgraph (%c0 = %arg0 :  tensor<2xi64>) {\\n            // Implementation...\\n            xten_nn.output %result : tensor<120xi64>\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"operands\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"assemblyFormat\": \"attr-dict ($operands^ `:` type($operands))?\"\n  },\n  {\n    \"name\": \"xten_nn.quantize\",\n    \"summary\": \"Quantizes a float tensor to a signless or unsigned integer tensor of given width.\",\n    \"description\": \"Quantizes a given float tensor into a signless or unsigned integer tensor of given width.\\n    Since tosa is using signless/unsigned types currently, we also consider signless integer types for\\n    signed ones when the type is not unsigned until tosa support signed integers.\\n\\n    Applies the following linear quantization to the input tensor x:\\n      y = round((x / scale) + zero_point)\\n\\n    Iff log2(scale) is representable as si32 and zero_point == 0, shift is set to log2(scale).\\n    In this case the quantization is equal to:\\n      y = round( x / 2^shift )\\n\\n    Round will saturate to the range of the output type and the rounding mode is set to half\\n    to nearest even.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"XTenNN_AnyFloatTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"XTenNN_AnySignlessOrUnsignedIntegerTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"shift\", \"type\": \"OptionalAttr<SI32Attr>\" },\n      { \"name\": \"scale\", \"type\": \"F32Attr\" },\n      { \"name\": \"zero_point\", \"type\": \"XTenNN_AnyIntegerAttr\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xten_nn.reduce_mean\",\n    \"summary\": \"Reduce Mean operation\",\n    \"description\": \"This operation is equivalent to `onnx.ReduceMean` and computes the mean of\\n    the input tensor's elements along the provided axes.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"keepdims\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.reflect_pad\",\n    \"summary\": \"Performs reflective padding over a tensor input.\",\n    \"description\": \"Apply a padding with `reflect` mode meaning that the ifm is reflected where the padding is applied:\\n    data = [\\n          [1, 2],\\n          [3, 4],\\n          [5, 6],\\n      ]\\n      pads = [0, 2, 0, 0]\\n      output = [\\n          [1, 2, 1, 2],\\n          [3, 4, 3, 4],\\n          [5, 6, 5, 6],\\n      ]\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"pads\", \"type\": \"TensorOf<[I64]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.resize\",\n    \"summary\": \"Performs resizing to an image.\",\n    \"description\": \"Performs resizing to input image. Some constrains and information:\\n      - It does not perform 'antialias' for linear mode (ONNX's antialias==0)\\n      - It performs the resize in all dimensions (ONNX's axes==None)\\n      - No sampling is perfomed outside the tensor (ONNX's exclude_outside==0)\\n      - The input is always stretched to meet the new required dimensions (ONNX's keep_aspect_ratio_policy==stretch)\\n      - Scales\\n        - 1D vector with four values specifing the scale for the resize on each dimension\\n      - Cordinate Transformation Mode:\\n        - 0: half_pixel\\n        - 1: pytorch_half_pixel\\n        - 2: asymmetric\\n        - 3: align_corners\\n      - Mode:\\n        - 0: Nearest\\n        - 1: Linear\\n      - Nearest mode:\\n        - 0: floor\\n        - 1: round_prefer_ceil\\n        - 2: round_prefer_floor\",\n    \"operands\": [\n      { \"name\": \"X\", \"type\": \"4DTensorOf<[XTenNN_AnyIntegerOrFloat]>\" }\n    ],\n    \"results\": [\n      { \"name\": \"Y\", \"type\": \"4DTensorOf<[XTenNN_AnyIntegerOrFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scales\", \"type\": \"DenseF32ArrayAttr\" },\n      { \"name\": \"coordinate_transformation_mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"mode\", \"type\": \"I64Attr\" },\n      { \"name\": \"nearest_mode\", \"type\": \"I64Attr\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.round\",\n    \"summary\": \"Calculate the round operation of the given input tensor element-wise.\",\n    \"description\": \"Calculate the round operation of the given input tensor element-wise.\\n    In case of halves, the rule is to round them to the nearest even integer as does the 'round' operation in torch and onnx.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.sign\",\n    \"summary\": \"Calculate the sign of the given input tensor element-wise\",\n    \"description\": \"Calculate the sign of the given input tensor element-wise. If input > 0, output 1. if input < 0, output -1. if input == 0, output 0.\\n    If the input is a NaN, the output will be a copy of the input element.\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyTensor\" }\n    ],\n    \"assemblyFormat\": \"operands attr-dict `:` functional-type(operands, results)\"\n  },\n  {\n    \"name\": \"xten_nn.subgraph\",\n    \"summary\": \"Separates a subgraph inside a graph\",\n    \"description\": \"The `xten_nn.subgraph` operation declares its body to be an isolated sub-\\n        graph, separated from the surrounding graph.\\n\\n        This allows code motion between the parent and anonymous\\n        subgraphs.\\n\\n        The meaning of the subgraph is described using both attributes and its\\n        body. If the body is present, the contents of the body can replace the\\n        subgraph operation without any change to what would be computed.\\n        The body is not required: in that case the attributes must be enough\\n        to identify the operation of the subgraph. (This resembles an func.func\\n        without a body: there may be a body in a different module or the\\n        compiler may know how to implement it when it is an intrinsic.)\\n\\n        Example:\\n        ```mlir\\n        func.func @subgraph(%arg0:  tensor<2xi64>) ->  tensor<2xi64> {\\n            %sum = xten_nn.subgraph (%c0 = %arg0 :  tensor<2xi64>) {\\n                // Implementation...\\n                xten_nn.output %out :  tensor<120xi64>\\n            } -> tensor<120xi64>\\n        return %sum :  tensor<120xi64>\\n        }\\n        ```\",\n    \"operands\": [\n      { \"name\": \"captures\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"results\": [\n      { \"name\": \"results\", \"type\": \"Variadic<AnyType>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"content\", \"type\": \"MaxSizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xten_nn.topk\",\n    \"summary\": \"Calculate the topk\",\n    \"description\": \"Follows the specification of ONNX TopK at opset 11\",\n    \"operands\": [\n      { \"name\": \"input\", \"type\": \"AnyTensor\" },\n      { \"name\": \"k\", \"type\": \"I64\" }\n    ],\n    \"results\": [\n      { \"name\": \"output\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"indices\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"I64Attr\" },\n      { \"name\": \"largest\", \"type\": \"I1Attr\" },\n      { \"name\": \"sorted\", \"type\": \"I1Attr\" }\n    ],\n    \"assemblyFormat\": \"`(`$input `:` type($input) `,` $k `:` type($k)`)` attr-dict `->` type($output) `,` type($indices)\"\n  },\n  {\n    \"name\": \"xtile.dot_scaled\",\n    \"summary\": \"dot_scaled\",\n    \"description\": \"$result = matrix_multiply(scale($lhs, $lhs_scale), scale($rhs, $rhs_scale)).\\n        Where scale(x, s) is a function that applies the scale per block following microscaling spec.\",\n    \"operands\": [\n      { \"name\": \"lhs\", \"type\": \"RankedTensorOf<[AnyFloat, I8]>\" },\n      { \"name\": \"rhs\", \"type\": \"RankedTensorOf<[AnyFloat, I8]>\" },\n      { \"name\": \"lhs_scale\", \"type\": \"Optional<RankedTensorOf<[ AnyFloat, I8 ]>>\" },\n      { \"name\": \"rhs_scale\", \"type\": \"Optional<RankedTensorOf<[ AnyFloat, I8 ]>>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"RankedTensorOf<[AnyFloat]>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"fastMath\", \"type\": \"BoolAttr\" },\n      { \"name\": \"lhs_k_pack\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" },\n      { \"name\": \"rhs_k_pack\", \"type\": \"DefaultValuedAttr<BoolAttr, true>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AttrSizedOperandSegments\" }\n    ],\n    \"assemblyFormat\": \"$lhs (`scale` $lhs_scale^)? `,` $rhs (`scale` $rhs_scale^)? attr-dict\\n      `:` type($lhs) (`,` type($lhs_scale)^)? `*` type($rhs) (`,` type($rhs_scale)^)? `->` type($result)\"\n  },\n  {\n    \"name\": \"xtile.entry_func\",\n    \"summary\": \"My custom entry function operation\",\n    \"description\": \"This operation defines a custom entry function that is the starting\\n    point for execution. It has a single-block region, takes a\\n    variadic list of memrefs and exactly one tile id index arguments,\\n    it has no return values.\",\n    \"attributes\": [\n      { \"name\": \"sym_name\", \"type\": \"SymbolNameAttr\" },\n      { \"name\": \"function_type\", \"type\": \"TypeAttrOf<FunctionType>\" },\n      { \"name\": \"arg_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"tile_info\", \"type\": \"OptionalAttr<XTile_TilingInfoAttr>\" },\n      { \"name\": \"res_attrs\", \"type\": \"OptionalAttr<TypedArrayAttrBase<DictionaryAttr>>\" },\n      { \"name\": \"num_opaque_args\", \"type\": \"DefaultValuedAttr<I32Attr, 0>\" }\n    ],\n    \"regions\": [\n      { \"name\": \"body\", \"type\": \"SizedRegion<1>\" }\n    ],\n    \"traits\": [\n      { \"type\": \"IsolatedFromAbove\" }\n    ],\n    \"hasCustomAssemblyFormat\": true\n  },\n  {\n    \"name\": \"xtile.extract\",\n    \"summary\": \"Extract a tile from a memref.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"full_tile_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `[` $offsets `]` $full_tile_shape $strides\\n    `:` type($source) `->` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"xtile.insert\",\n    \"summary\": \"Insert a tile into a memref.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"destination\", \"type\": \"AnyMemRef\" },\n      { \"name\": \"offsets\", \"type\": \"Variadic<Index>\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"full_tile_shape\", \"type\": \"DenseI64ArrayAttr\" },\n      { \"name\": \"strides\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"assemblyFormat\": \"$source `into` $destination `[` $offsets `]` $full_tile_shape $strides\\n    `:` type($source) `->` type($destination) attr-dict\"\n  },\n  {\n    \"name\": \"xtile.mask\",\n    \"summary\": \"Mask the values of a tensor.\",\n    \"description\": \"Masks out the values of the input tensor that are outside the range of the\\n    given mask upper bound. Masked values are set to the provided value.\",\n    \"operands\": [\n      { \"name\": \"source\", \"type\": \"AnyRankedTensor\" },\n      { \"name\": \"value\", \"type\": \"AnyType\" }\n    ],\n    \"results\": [\n      { \"name\": \"result\", \"type\": \"AnyRankedTensor\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"bounds\", \"type\": \"DenseI64ArrayAttr\" }\n    ],\n    \"traits\": [\n      { \"type\": \"AllTypesMatch<['source', 'result']>\" },\n      { \"type\": \"TypesMatchWith<'result', 'value', '[object Object]'>\" }\n    ],\n    \"assemblyFormat\": \"$source `bounds` $bounds `,` $value `:` type($result) attr-dict\"\n  },\n  {\n    \"name\": \"xtile.return\",\n    \"summary\": \"Terminates the entry function\",\n    \"description\": \"This operation terminates the entry function block. It has no operands\\n    and produces no results.\",\n    \"assemblyFormat\": \"attr-dict\"\n  }\n]"
  },
  {
    "path": "source/mlir.js",
    "content": "\n// Experimental\n\nimport * as base from './base.js';\nimport * as text from './text.js';\n\nconst mlir = {};\nconst _ = {};\n\nmlir.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        const identifier = context.identifier;\n        const extension = identifier.split('.').pop().toLowerCase();\n        if (stream && stream.length > 4) {\n            const buffer = stream.peek(4);\n            const signature = String.fromCharCode.apply(null, buffer);\n            if (signature === 'ML\\xEFR') {\n                return context.set('mlir.binary');\n            }\n        }\n        try {\n            const reader = await context.read('text', 0x10000);\n            let whitespace = true;\n            for (let line = reader.read('\\n'); line !== undefined; line = reader.read('\\n')) {\n                if (/module\\s+(@\\w+|\\w+|attributes|\\{)/.test(line) ||\n                    /tensor<[\\w\\d]+>/.test(line) ||\n                    /func[.\\s]*@\\w+/.test(line) ||\n                    /%\\w+\\s*=\\s*\"[\\w.]+/.test(line) ||\n                    /%\\w+\\s*=\\s*\\w+\\./.test(line) ||\n                    /!\\w+\\s*=\\s*![\\w.]+</.test(line) ||\n                    /#\\w+\\s*=\\s*#[\\w.]+</.test(line) ||\n                    /#\\w+\\s*=\\s*loc\\s*\\(/.test(line) ||\n                    /\\w+\\.\\w+(?:\\s+\\w+)*\\s+@\\w+/.test(line) ||\n                    /\\w+\\.\\w+\\s+#[\\w.]+</.test(line) ||\n                    /\\w+\\.\\w+\\s*<?\\{/.test(line) ||\n                    /:\\s*![\\w.]+/.test(line) ||\n                    /(%\\w+|\\w{2,}|[)])\\s*:\\s*(\\[|tensor<)/.test(line) ||\n                    /->\\s*(![\\w.]+|\\(|tensor<)/.test(line)) {\n                    return context.set('mlir.text');\n                }\n                if (line && !line.trim().startsWith('//')) {\n                    whitespace = false;\n                }\n            }\n            if (extension === 'mlir' && whitespace) {\n                return context.set('mlir.text');\n            }\n        } catch {\n            // continue\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await mlir.Metadata.open(context);\n        switch (context.type) {\n            case 'mlir.text': {\n                const decoder = await context.read('text.decoder');\n                const config = new _.ParserConfig(new _.DialectContext(metadata));\n                const state = new _.ParserState(decoder, config);\n                const parser = new _.TopLevelOperationParser(state);\n                const block = new _.Block();\n                parser.parse(block);\n                const model = new mlir.Model(config, 'MLIR', '', block, state.attributeAliasDefinitions);\n                return model;\n            }\n            case 'mlir.binary': {\n                const binary = await context.read('binary');\n                const config = new _.ParserConfig(new _.DialectContext(metadata));\n                const reader = new _.BytecodeReader(binary, config);\n                const block = reader.read();\n                const format = `MLIR Bytecode v${reader.version.value}`;\n                const producer = reader.producer;\n                const model = new mlir.Model(config, format, producer, block, new Map());\n                return model;\n            }\n            default: {\n                throw new mlir.Error(`Unsupported MLIR format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nmlir.Model = class {\n\n    constructor(config, format, producer, block, attributeAliasDefinitions) {\n        this.format = format;\n        this.producer = producer || '';\n        this.modules = [];\n        this.functions = [];\n        this.metadata = [];\n        const modules = [];\n        const isFunc = (name) => name.endsWith('.func') || /\\.func_v\\d+$/.test(name);\n        const isModule = (name) => name.endsWith('.module');\n        const collectModules = (operations, path, attributes) => {\n            let identifier = 0;\n            const funcs = [];\n            const ops = [];\n            for (const op of operations) {\n                if (isFunc(op.name.getStringRef())) {\n                    funcs.push(op);\n                } else if (isModule(op.name.getStringRef())) {\n                    let name = op.getAttr('sym_name');\n                    name = name ? name.value : `$${identifier++}`;\n                    const modulePath = [...path, name];\n                    for (const region of op.regions || []) {\n                        for (const blk of region.blocks || []) {\n                            collectModules(blk.operations || [], modulePath, op.getAttrDictionary());\n                        }\n                    }\n                } else {\n                    ops.push(op);\n                }\n            }\n            if (funcs.length > 0 || ops.length > 0) {\n                let name = null;\n                if (attributes.get('sym_name')) {\n                    name = attributes.get('sym_name');\n                    name = `@${name.value}`;\n                }\n                modules.push({ path, symName: name, funcs, ops, attributes });\n            }\n        };\n        collectModules(block.operations, [], new Map());\n        const formatPrefix = (path, symName) => {\n            if (symName) {\n                return symName;\n            }\n            if (modules.length !== 1 && path.length > 0) {\n                return path.map((path) => `${path}`).join('::');\n            }\n            return '';\n        };\n        const functions = new Map();\n        let identifier = 0;\n        for (const module of modules) {\n            const prefix = formatPrefix(module.path, module.symName);\n            for (const func of module.funcs) {\n                const sym_name = func.getAttr('sym_name');\n                const base = sym_name ? sym_name.value : `$${identifier}`;\n                identifier++;\n                const name = prefix ? `${prefix}::@${base}` : `@${base}`;\n                functions.set(name, { func, prefix, base, module });\n            }\n        }\n        const context = new mlir.Context(functions);\n        for (const [name, info] of functions) {\n            const graph = context.graph(info.func, name);\n            this.functions.push(graph);\n        }\n        for (const module of modules) {\n            if (module.ops.length > 0 || module.attributes.size > 0) {\n                const name = formatPrefix(module.path, module.symName) || '';\n                const opName = _.RegisteredOperationName.lookup('builtin.module', config.context);\n                const state = new _.OperationState(null, opName);\n                state.attributes = module.attributes;\n                state.regions = [{ blocks: [{ operations: module.ops, arguments: [] }] }];\n                const op = _.Operation.create(state);\n                const graph = context.graph(op, name);\n                this.modules.push(graph);\n            }\n        }\n        for (const [name, attribute] of attributeAliasDefinitions) {\n            let value = attribute.type;\n            if (!value) {\n                value = typeof attribute.value === 'string' ? attribute.value : attribute.toString();\n            }\n            const metadata = new mlir.Argument(name, value, 'attribute');\n            this.metadata.push(metadata);\n        }\n    }\n};\n\nmlir.Graph = class {\n\n    constructor(func, context, name) {\n        this.name = name || '';\n        if (!name && func.attributes.has('sym_name')) {\n            const sym_name = func.attributes.get('sym_name');\n            this.name = sym_name.value;\n        }\n        this.type = 'graph';\n        if (func.name === 'func' || func.name.getStringRef().endsWith('.func') || /\\.func_v\\d+$/.test(func.name.getStringRef())) {\n            this.type = 'function';\n        }\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        this.metadata = [];\n        const tensors = new Map();\n        if (func.attributes.has('function_type')) {\n            const function_type = func.attributes.get('function_type');\n            const args = func.regions && func.regions[0] && func.regions[0].blocks && func.regions[0].blocks[0] && func.regions[0].blocks[0].arguments ? func.regions[0].blocks[0].arguments : [];\n            const inputs = function_type.type.inputs;\n            const results = function_type.type.results;\n            for (let i = 0; i < inputs.length; i++) {\n                const input = inputs[i];\n                const name = args[i] && args[i].name ? args[i].name : `%arg${i}`;\n                const type = mlir.Utility.valueType(input.type || input);\n                const value = new mlir.Value(name, type, '', null);\n                const argument = new mlir.Argument(name, [value]);\n                this.inputs.push(argument);\n            }\n            for (let i = 0; i < results.length; i++) {\n                const output = results[i];\n                const name = output.value || i.toString();\n                const type = mlir.Utility.valueType(output.type);\n                const valueName = output.value || output.name || `%result${i}`;\n                const value = new mlir.Value(valueName, type, '', null);\n                const argument = new mlir.Argument(name, [value]);\n                this.outputs.push(argument);\n            }\n        }\n        const values = new Map();\n        values.map = (name) => {\n            if (!values.has(name)) {\n                values.set(name, { name, to: [], from: [] });\n            }\n            return values.get(name);\n        };\n        const operations = [];\n        for (const region of func.regions) {\n            for (const block of region.blocks) {\n                for (const op of block.operations) {\n                    const operation = {\n                        identifier: op.identifier,\n                        name: op.name,\n                        label: op.label,\n                        attributes: op.getAttrDictionary(),\n                        operands: [],\n                        results: [],\n                        inputs: [],\n                        outputs: [],\n                        regions: op.regions,\n                        delete: false,\n                    };\n                    const opMetadata = op.name.metadata;\n                    const operands = op.operands;\n                    let lastVariadicIndex = -1;\n                    let lastVariadicName = null;\n                    if (opMetadata && opMetadata.operands) {\n                        for (let j = opMetadata.operands.length - 1; j >= 0; j--) {\n                            const metaOp = opMetadata.operands[j];\n                            if (metaOp.type && metaOp.type.name === 'Variadic') {\n                                lastVariadicIndex = j;\n                                lastVariadicName = metaOp.name;\n                                break;\n                            }\n                        }\n                    }\n                    for (let i = 0; i < operands.length; i++) {\n                        const input = op.operands[i];\n                        let inputName = null;\n                        const isVariadicOverflow = lastVariadicIndex >= 0 && i >= lastVariadicIndex;\n                        if (opMetadata && opMetadata.operands && opMetadata.operands[i]) {\n                            inputName = opMetadata.operands[i].name;\n                        } else if (isVariadicOverflow) {\n                            inputName = lastVariadicName;\n                        } else {\n                            inputName = input.name || i.toString();\n                        }\n                        if (typeof input.name !== 'string' || !input.name) {\n                            throw new mlir.Error(`Invalid operand name '${JSON.stringify(input.name)}'.`);\n                        }\n                        const value = values.map(input.name);\n                        value.to.push(operation);\n                        const arg = { name: input.name, type: input.type };\n                        operation.operands.push(arg);\n                        if (isVariadicOverflow && operation.inputs.length > 0 && operation.inputs[operation.inputs.length - 1].name === inputName) {\n                            operation.inputs[operation.inputs.length - 1].value.push(arg);\n                        } else {\n                            operation.inputs.push({ name: inputName, value: [arg] });\n                        }\n                    }\n                    const results = op.results;\n                    let lastVariadicResultIndex = -1;\n                    let lastVariadicResultName = null;\n                    if (opMetadata && opMetadata.results) {\n                        for (let j = opMetadata.results.length - 1; j >= 0; j--) {\n                            const metaRes = opMetadata.results[j];\n                            if (metaRes.type && metaRes.type.name === 'Variadic') {\n                                lastVariadicResultIndex = j;\n                                lastVariadicResultName = metaRes.name;\n                                break;\n                            }\n                        }\n                    }\n                    for (let i = 0; i < results.length; i++) {\n                        const output = results[i];\n                        if (!output.name) {\n                            continue;\n                        }\n                        const value = values.map(output.name);\n                        value.type = mlir.Utility.valueType(output.type);\n                        value.from.push(operation);\n                        let outputName = null;\n                        const isVariadicOverflow = lastVariadicResultIndex >= 0 && i >= lastVariadicResultIndex;\n                        if (opMetadata && opMetadata.results && opMetadata.results[i]) {\n                            outputName = opMetadata.results[i].name;\n                        } else if (isVariadicOverflow) {\n                            outputName = lastVariadicResultName;\n                        } else {\n                            outputName = output.name;\n                        }\n                        operation.results.push(value);\n                        if (isVariadicOverflow && operation.outputs.length > 0 && operation.outputs[operation.outputs.length - 1].name === outputName) {\n                            operation.outputs[operation.outputs.length - 1].value.push(value);\n                        } else {\n                            operation.outputs.push({\n                                name: outputName,\n                                value: [value]\n                            });\n                        }\n                    }\n                    operations.push(operation);\n                }\n            }\n        }\n        const constantMap = new Map();\n        const constantTypes = new Set([\n            'tosa.const', 'stablehlo.constant', 'arith.constant',\n            'mhlo.constant', 'torch.constant.tensor', 'onnx.Constant'\n        ]);\n        for (const op of operations) {\n            if (constantTypes.has(op.name.getStringRef()) &&\n                op.operands.length === 0 &&\n                op.attributes.size === 1 &&\n                op.results.length === 1) {\n                const result = op.results[0];\n                if (result.to && result.to.length === 1) {\n                    if (result.to[0].name.getStringRef().endsWith('.return')) {\n                        continue;\n                    }\n                    const valueAttr = op.attributes.get('value') || op.attributes.get('values');\n                    if ((valueAttr instanceof _.DenseElementsAttr || valueAttr instanceof _.DenseResourceElementsAttr) && valueAttr.value !== null && valueAttr.type && valueAttr.type instanceof _.RankedTensorType) {\n                        const type = mlir.Utility.valueType(valueAttr.type);\n                        if (type instanceof mlir.TensorType && !type.dataType.startsWith('!')) {\n                            constantMap.set(result.name, new mlir.Tensor(type, valueAttr.value));\n                            op.delete = true;\n                        }\n                    }\n                }\n            }\n        }\n        const torchConstantMap = new Map();\n        for (const op of operations) {\n            const opName = op.name.getStringRef();\n            if (opName === 'torch.constant.int' ||\n                opName === 'torch.constant.bool' ||\n                opName === 'torch.constant.float' ||\n                opName === 'torch.constant.str' ||\n                opName === 'torch.constant.none') {\n                if (op.operands.length === 0 &&\n                    op.results.length === 1) {\n                    const result = op.results[0];\n                    if (result.to && result.to.length === 1) {\n                        let value = null;\n                        let type = null;\n                        const attr = op.attributes.get('value');\n                        const attrValue = attr && typeof attr === 'object' ? attr.value : attr;\n                        if (opName === 'torch.constant.int') {\n                            value = attrValue === undefined ? 0 : attrValue;\n                            type = 'int64';\n                        } else if (opName === 'torch.constant.bool') {\n                            value = attrValue === undefined ? false : attrValue;\n                            type = 'boolean';\n                        } else if (opName === 'torch.constant.float') {\n                            value = attrValue === undefined ? 0.0 : attrValue;\n                            type = 'float64';\n                        } else if (opName === 'torch.constant.str') {\n                            value = attrValue === undefined ? '' : attrValue;\n                            type = 'string';\n                        } else if (opName === 'torch.constant.none') {\n                            value = null;\n                            type = 'none';\n                        }\n                        torchConstantMap.set(result.name, { value, type });\n                        op.delete = true;\n                    }\n                }\n            }\n        }\n        for (const op of operations) {\n            if (op.name === 'torch.prim.ListConstruct' &&\n                op.results.length === 1) {\n                const result = op.results[0];\n                if (result.to && result.to.length === 1) {\n                    const inputValues = [];\n                    let allConstant = true;\n                    for (const operand of op.operands) {\n                        if (torchConstantMap.has(operand.name)) {\n                            inputValues.push(torchConstantMap.get(operand.name).value);\n                        } else {\n                            allConstant = false;\n                            break;\n                        }\n                    }\n                    if (allConstant) {\n                        torchConstantMap.set(result.name, { value: inputValues, type: 'list' });\n                        op.delete = true;\n                    }\n                }\n            }\n        }\n        const tensor = (arg) => {\n            if (!tensors.has(arg.name)) {\n                const initializer = constantMap.get(arg.name) || null;\n                let type = null;\n                if (arg.type instanceof mlir.TensorType) {\n                    type = arg.type;\n                } else if (arg.type) {\n                    type = mlir.Utility.valueType(arg.type);\n                }\n                tensors.set(arg.name, new mlir.Value(arg.name, type, null, initializer));\n            }\n            return tensors.get(arg.name);\n        };\n        for (const input of this.inputs) {\n            for (const arg of input.value) {\n                if (!tensors.has(arg.name)) {\n                    tensors.set(arg.name, arg);\n                }\n            }\n        }\n        const returnOp = operations.find((op) => op.name.getStringRef().endsWith('.return'));\n        if (returnOp) {\n            for (let i = 0; i < this.outputs.length && i < returnOp.operands.length; i++) {\n                const returnValue = returnOp.operands[i];\n                if (returnValue && typeof returnValue.name === 'string' && returnValue.name.startsWith('%')) {\n                    const output = this.outputs[i];\n                    const returnType = mlir.Utility.valueType(returnValue.type);\n                    const initializer = constantMap.get(returnValue.name) || null;\n                    output.value[0] = new mlir.Value(returnValue.name, returnType, '', initializer);\n                }\n            }\n            returnOp.delete = true;\n        }\n        for (const output of this.outputs) {\n            for (let i = 0; i < output.value.length; i++) {\n                const arg = output.value[i];\n                if (tensors.has(arg.name)) {\n                    output.value[i] = tensors.get(arg.name);\n                } else {\n                    tensors.set(arg.name, arg);\n                }\n            }\n        }\n        for (const op of operations.filter((op) => !op.delete)) {\n            const node = new mlir.Node(op, context, tensor, torchConstantMap);\n            this.nodes.push(node);\n        }\n        for (const [name, value] of func.attributes) {\n            if (name === 'sym_name' || name === 'function_type') {\n                continue;\n            }\n            const metadata = new mlir.Argument(name, value, 'attribute');\n            this.metadata.push(metadata);\n        }\n    }\n};\n\nmlir.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        if (this.type) {\n            const typeStr = this.type instanceof _.Type ? this.type.toString() : this.type;\n            switch (typeStr) {\n                case 'i64': case 'si64': this.type = 'int64'; break;\n                case 'i48': case 'si48': this.type = 'int48'; break;\n                case 'i32': case 'si32': this.type = 'int32'; break;\n                case 'i16': case 'si16': this.type = 'int16'; break;\n                case 'i8': case 'si8': this.type = 'int8'; break;\n                case 'i1': this.type = 'int1'; break;\n                case 'f32': case 'float32': this.type = 'float32'; break;\n                case 'f64': case 'float64': this.type = 'float64'; break;\n                case 'f16': this.type = 'float16'; break;\n                case 'f80': this.type = 'float80'; break;\n                case 'f128': this.type = 'float128'; break;\n                case null:\n                case 'attribute':\n                case 'boolean':\n                case 'string':\n                case 'int64':\n                case 'int32':\n                case 'int16':\n                case 'int8':\n                case 'float16':\n                case 'tensor':\n                case 'type':\n                case 'dense':\n                case 'function':\n                case 'symbol':\n                case 'graph':\n                case 'list':\n                case 'none':\n                    break;\n                default:\n                    if (/^[usi]i?[0-9]+$/.test(typeStr) || /^f[0-9]+$/.test(typeStr) ||\n                        /^f\\d+E\\d+M\\d+/.test(typeStr) ||\n                        typeStr === 'bf16' || typeStr === 'tf32' || typeStr === 'index' || typeStr === 'none' ||\n                        typeStr === 'unit' || typeStr.startsWith('!') || typeStr.startsWith('tensor<') ||\n                        typeStr.startsWith('memref<') || typeStr.startsWith('vector<')) {\n                        this.type = typeStr;\n                        break;\n                    }\n                    throw new mlir.Error(`Unsupported argument type '${typeStr}'.`);\n            }\n        }\n    }\n};\n\nmlir.Value = class {\n\n    constructor(name, type, description, initializer) {\n        if (typeof name !== 'string') {\n            throw new mlir.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.description = description || null;\n        this.initializer = initializer || null;\n    }\n};\n\nmlir.Node = class {\n\n    constructor(op, context, tensor, torchConstantMap) {\n        if (!op.name) {\n            throw new mlir.Error('Undefined node type.');\n        }\n        this.name = '';\n        this.type = { ...op.name.getRegisteredInfo()?.metadata };\n        this.type.name = op.label || op.identifier || '';\n        this.type.identifier = op.name.getStringRef() || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        this.blocks = [];\n        torchConstantMap = torchConstantMap || new Map();\n        const segmentSizes = op.attributes.get('operandSegmentSizes');\n        const operandMeta = this.type && this.type.operands;\n        const operands = op.inputs || [];\n        if (segmentSizes && operandMeta && segmentSizes.value.length === operandMeta.length) {\n            let offset = 0;\n            for (let i = 0; i < segmentSizes.value.length; i++) {\n                const size = segmentSizes.value[i];\n                const name = operandMeta[i].name;\n                for (let j = 0; j < size; j++) {\n                    if (offset + j < operands.length) {\n                        operands[offset + j] = { ...operands[offset + j], name };\n                    }\n                }\n                offset += size;\n            }\n        }\n        const operandGroups = new Map();\n        const operandOrder = [];\n        for (const input of operands) {\n            if (!operandGroups.has(input.name)) {\n                operandGroups.set(input.name, []);\n                operandOrder.push(input.name);\n            }\n            operandGroups.get(input.name).push(input);\n        }\n        for (const name of operandOrder) {\n            const inputs = operandGroups.get(name);\n            let argument = null;\n            if (inputs.length === 1) {\n                const [input] = inputs;\n                if (Array.isArray(input.value) && input.value.length === 1) {\n                    const val = input.value[0];\n                    if (val && typeof val.name === 'string' && torchConstantMap.has(val.name)) {\n                        const constant = torchConstantMap.get(val.name);\n                        argument = new mlir.Argument(input.name, constant.value, constant.type);\n                        this.inputs.push(argument);\n                        continue;\n                    }\n                }\n                if (input.type) {\n                    const typeStr = input.type instanceof _.Type ? input.type.toString() : input.type;\n                    if (typeStr.startsWith('tensor<')) {\n                        const type = mlir.Utility.valueType(typeStr);\n                        const value = new mlir.Tensor(type, input.value);\n                        argument = new mlir.Argument(input.name, value, 'tensor');\n                    } else {\n                        argument = new mlir.Argument(input.name, input.value, input.type);\n                    }\n                } else if (Array.isArray(input.value) && !input.value.every((value) => typeof value.name === 'string' && value.name.startsWith('%'))) {\n                    argument = new mlir.Argument(input.name, input.value, input.type || 'attribute');\n                } else if (Array.isArray(input.value)) {\n                    argument = new mlir.Argument(input.name, input.value.map((arg) => tensor(arg)));\n                } else {\n                    argument = new mlir.Argument(input.name, input.value, input.type || 'attribute');\n                }\n            } else {\n                let allConstants = true;\n                const constantValues = [];\n                for (const input of inputs) {\n                    if (Array.isArray(input.value)) {\n                        for (const arg of input.value) {\n                            if (arg && typeof arg.name === 'string' && torchConstantMap.has(arg.name)) {\n                                constantValues.push(torchConstantMap.get(arg.name).value);\n                            } else {\n                                allConstants = false;\n                                break;\n                            }\n                        }\n                    } else {\n                        allConstants = false;\n                    }\n                    if (!allConstants) {\n                        break;\n                    }\n                }\n                if (allConstants && constantValues.length > 0) {\n                    argument = new mlir.Argument(name, constantValues, 'list');\n                } else {\n                    const values = [];\n                    for (const input of inputs) {\n                        if (Array.isArray(input.value)) {\n                            values.push(...input.value.map((arg) => tensor(arg)));\n                        } else {\n                            values.push(tensor({ name: input.value, type: input.type }));\n                        }\n                    }\n                    argument = new mlir.Argument(name, values);\n                }\n            }\n            this.inputs.push(argument);\n        }\n        for (const output of op.outputs || []) {\n            const argument = new mlir.Argument(output.name, output.value.map((arg) => tensor(arg)));\n            this.outputs.push(argument);\n        }\n        if (op.attributes) {\n            for (const [name, attr] of op.attributes) {\n                let value = attr;\n                let type = null;\n                if (attr instanceof _.SymbolRefAttr && context) {\n                    const graph = context.function(`${value.value}`);\n                    if (graph) {\n                        value = graph;\n                        type = 'function';\n                    }\n                } else if (attr instanceof _.DenseElementsAttr) {\n                    const tensorType = mlir.Utility.valueType(attr.type);\n                    if (tensorType instanceof mlir.TensorType && tensorType.dataType.startsWith('!')) {\n                        value = `dense<${attr.type}>`;\n                    } else {\n                        value = new mlir.Tensor(tensorType, attr.value);\n                        type = 'tensor';\n                    }\n                } else if (attr instanceof _.DenseResourceElementsAttr) {\n                    value = new mlir.Tensor(mlir.Utility.valueType(attr.type), attr.value);\n                    type = 'tensor';\n                } else if (attr instanceof _.SparseElementsAttr) {\n                    value = new mlir.Tensor(mlir.Utility.valueType(attr.type), attr.values);\n                    type = 'tensor';\n                } else if (attr instanceof _.DenseArrayAttr) {\n                    value = attr.value;\n                } else if (Array.isArray(attr)) {\n                    value = attr;\n                } else if (attr) {\n                    value = attr.toString();\n                }\n                const attribute = new mlir.Argument(name, value, type || 'attribute');\n                this.attributes.push(attribute);\n            }\n        }\n        if (op.regions && op.regions.length > 0) {\n            const opMetadata = this.type;\n            for (let i = 0; i < op.regions.length; i++) {\n                const region = op.regions[i];\n                if (region.blocks && region.blocks.length > 0) {\n                    const name = (opMetadata.regions && opMetadata.regions[i] ? opMetadata.regions[i].name : null) || i.toString();\n                    const blockName = region.blocks[0].name || '';\n                    const func = { name: 'func', attributes: new Map(), regions: [region] };\n                    const graph = new mlir.Graph(func, context, blockName);\n                    const argument = new mlir.Argument(name, graph, 'graph');\n                    this.blocks.push(argument);\n                }\n            }\n        }\n    }\n};\n\nmlir.Tensor = class {\n\n    constructor(type, data) {\n        this.type = type;\n        this.values = data;\n        this.encoding = data instanceof Uint8Array ? '<' : '|';\n    }\n};\n\nmlir.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = mlir.Utility.dataType(dataType); // string\n        this.shape = shape || new mlir.TensorShape([]);  // mlir.TensorShape\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmlir.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.map((dimension) => dimension.toString()).join(', ')}]`;\n    }\n};\n\nmlir.Context = class {\n\n    constructor(functions) {\n        this._functions = functions; // Map of fullName -> {func, prefix, base, module}\n        this._graphs = new Map();\n        this._constructing = new Set();\n    }\n\n    graph(module, name) {\n        if (!this._graphs.has(name)) {\n            this._constructing.add(name);\n            const graph = new mlir.Graph(module, this, name);\n            this._graphs.set(name, graph);\n            this._constructing.delete(name);\n        }\n        return this._graphs.get(name);\n    }\n\n    function(name) {\n        if (this._graphs.has(name)) {\n            return this._graphs.get(name);\n        }\n        if (this._constructing.has(name)) {\n            return { name, type: 'function', nodes: [], inputs: [], outputs: [] };\n        }\n        if (this._functions.has(name)) {\n            const info = this._functions.get(name);\n            return this.graph(info.func, name);\n        }\n        for (const [fullName, info] of this._functions) {\n            if (info.base === name) {\n                if (this._graphs.has(fullName)) {\n                    return this._graphs.get(fullName);\n                }\n                if (this._constructing.has(fullName)) {\n                    return { name: fullName, type: 'function', nodes: [], inputs: [], outputs: [] };\n                }\n                return this.graph(info.func, fullName);\n            }\n        }\n        return null;\n    }\n};\n\nmlir.Utility = class {\n\n    static dataType(value) {\n        if (value instanceof _.ComplexType) {\n            const elementType = mlir.Utility.dataType(value.elementType);\n            return `complex<${elementType}>`;\n        }\n        if (value instanceof _.Type) {\n            value = value.toString();\n        }\n        switch (value) {\n            case 'index': return 'int64';\n            case 'f16': return 'float16';\n            case 'f32': return 'float32';\n            case 'f64': return 'float64';\n            case 'f80': return 'float80';\n            case 'f128': return 'float128';\n            case 'bf16': return 'bfloat16';\n            case 'fp8': return 'float8';\n            case 'fp8e4m3': return 'float8e4m3';\n            case 'fp8_e4m3': return 'float8e4m3';\n            case 'fp8e4m3fn': return 'float8e4m3fn';\n            case 'fp8e5m2': return 'float8e5m2';\n            case 'fp8_e5m2': return 'float8e5m2';\n            case 'f4E2M1FN': return 'float4e2m1fn';\n            case 'f6E2M3FN': return 'float6e2m3fn';\n            case 'f6E3M2FN': return 'float6e3m2fn';\n            case 'f8E3M4': return 'float8e3m4';\n            case 'f8E4M3': return 'float8e4m3';\n            case 'f8E4M3B11FNUZ': return 'float8e4m3b11fnuz';\n            case 'f8E4M3FN': return 'float8e4m3fn';\n            case 'f8E4M3FNUZ': return 'float8e4m3fnuz';\n            case 'f8E5M2': return 'float8e5m2';\n            case 'f8E5M2FNUZ': return 'float8e5m2fnuz';\n            case 'f8E8M0FNU': return 'float8e8m0fnu';\n            case 'float8': return 'float8';\n            case 'tf32': return 'tf32';\n            case 'i1': return 'int1';\n            case 'i2': return 'int2';\n            case 'i4': return 'int4';\n            case 'i8': return 'int8';\n            case 'i16': return 'int16';\n            case 'i32': return 'int32';\n            case 'i48': return 'int48';\n            case 'i64': return 'int64';\n            case 'si8': return 'int8';\n            case 'si16': return 'int16';\n            case 'si32': return 'int32';\n            case 'si64': return 'int64';\n            case 'ui1': return 'uint1';\n            case 'ui2': return 'uint2';\n            case 'ui4': return 'uint4';\n            case 'ui8': return 'uint8';\n            case 'ui16': return 'uint16';\n            case 'ui32': return 'uint32';\n            case 'ui64': return 'uint64';\n            case 'b8': return 'int8';\n            case 'unk': return 'unk'; // torch dialect unknown dtype\n            case '!tf_type.string': return 'string';\n            case '!tosa.mxint8': return 'int8';\n            case '!onnx.String': return 'string';\n            default:\n                if (value && value.startsWith('!')) {\n                    return value;\n                }\n                if (value && value.startsWith('vector<') && value.endsWith('>')) {\n                    return value;\n                }\n                if (value && value.startsWith('memref<') && value.endsWith('>')) {\n                    return value;\n                }\n                if (value && value.startsWith('tuple<') && value.endsWith('>')) {\n                    return value;\n                }\n                if (value && value.startsWith('complex<') && value.endsWith('>')) {\n                    const elementTypeStr = value.substring(8, value.length - 1);\n                    const convertedElementType = mlir.Utility.dataType(elementTypeStr);\n                    return `complex<${convertedElementType}>`;\n                }\n                if (value && /^[su]?i[0-9]+$/.test(value)) {\n                    const match = value.match(/^(s|u)?i([0-9]+)$/);\n                    if (match) {\n                        const [, signed, widthStr] = match;\n                        const width = parseInt(widthStr, 10);\n                        if (signed === 'u') {\n                            return `uint${width}`;\n                        } else if (signed === 's') {\n                            return `int${width}`;\n                        }\n                        return `int${width}`;\n                    }\n                }\n                throw new mlir.Error(`Unknown data type '${value}'.`);\n        }\n    }\n\n    static valueType(type) {\n        if (type === undefined) {\n            return null;\n        }\n        const typeStr = type instanceof _.Type ? type.toString() : type;\n        if (typeStr.startsWith('!') && !typeStr.startsWith('!torch.vtensor<')) {\n            return typeStr;\n        }\n        if (typeStr.startsWith('tensor<') && typeStr.endsWith('>')) {\n            const spec = typeStr.substring(7, typeStr.length - 1).trim();\n            if (spec.startsWith('!')) {\n                return mlir.Utility.valueType(spec);\n            }\n            let i = 0;\n            const shape = [];\n            while (i < spec.length) {\n                if (spec[i] === '?' || spec[i] === '*') {\n                    shape.push('?');\n                    i++;\n                } else if (/[0-9]/.test(spec[i])) {\n                    let numStr = '';\n                    while (i < spec.length && /[0-9]/.test(spec[i])) {\n                        numStr += spec[i];\n                        i++;\n                    }\n                    shape.push(BigInt(numStr));\n                } else {\n                    break;\n                }\n                if (i < spec.length && spec[i] === 'x') {\n                    i++;\n                } else {\n                    break;\n                }\n            }\n            let dataType = spec.substring(i);\n            // Find encoding comma, but skip commas inside angle brackets\n            let depth = 0;\n            let encodingIndex = -1;\n            for (let j = 0; j < dataType.length; j++) {\n                if (dataType[j] === '<') {\n                    depth++;\n                } else if (dataType[j] === '>') {\n                    depth--;\n                } else if (dataType[j] === ',' && depth === 0) {\n                    encodingIndex = j;\n                    break;\n                }\n            }\n            if (encodingIndex !== -1) {\n                dataType = dataType.substring(0, encodingIndex).trim();\n            }\n            return new mlir.TensorType(dataType, new mlir.TensorShape(shape));\n        }\n        if (typeStr.startsWith('!torch.vtensor<') && typeStr.endsWith('>')) {\n            const spec = typeStr.substring(15, typeStr.length - 1);\n            let shape = null;\n            let dataType = null;\n            if (spec.startsWith('[')) {\n                const bracketEnd = spec.indexOf(']');\n                const shapeStr = spec.substring(0, bracketEnd + 1);\n                const jsonStr = shapeStr.replace(/\\?/g, '\"?\"');\n                shape = JSON.parse(jsonStr);\n                const rest = spec.substring(bracketEnd + 1);\n                if (rest.startsWith(',')) {\n                    const parts = rest.substring(1).split(',');\n                    dataType = parts[0].trim();\n                }\n            } else if (spec.startsWith('*')) {\n                if (spec.includes(',')) {\n                    const parts = spec.split(',');\n                    dataType = parts[1].trim();\n                }\n            } else {\n                const parts = spec.split(',');\n                dataType = parts[0].trim();\n            }\n            return new mlir.TensorType(dataType, shape ? new mlir.TensorShape(shape) : null);\n        }\n        if (typeStr.startsWith('tuple<') && typeStr.endsWith('>')) {\n            return typeStr;\n        }\n        return typeStr;\n    }\n};\n\n_.Block = class {\n\n    constructor() {\n        this.operations = [];\n    }\n};\n\n_.OperationState = class {\n\n    constructor(location, name) {\n        this.location = location;\n        this.name = name;\n        if (this.name instanceof _.OperationName === false) {\n            throw new mlir.Error('Invalid operation name.');\n        }\n        this.identifier = name.identifier || name.getStringRef();\n        delete name.identifier;\n        this.attributes = new Map();\n        this.operands = [];\n        this.types = [];\n        this.regions = [];\n        this.propertiesAttr = null;\n    }\n\n    get op() {\n        return this.name.getStringRef(); // Workaround\n    }\n\n    addRegion() {\n        const region = {};\n        this.regions.push(region);\n        return region;\n    }\n\n    addTypes(newTypes) {\n        if (!Array.isArray(newTypes) || !newTypes.every((type) => type instanceof _.Type)) {\n            throw new mlir.Error(`Invalid types '${JSON.stringify(newTypes.filter((type) => type instanceof _.Type === false))}'.`);\n        }\n        for (const type of newTypes) {\n            this.types.push(type);\n        }\n    }\n\n    addAttribute(name, value) {\n        if (typeof name !== 'string' || name.length === 0) {\n            throw new mlir.Error(`Invalid attribute name '${JSON.stringify(name)}'.`);\n        }\n        this.attributes.set(name, value);\n    }\n\n    getAttr(name) {\n        if (this.propertiesAttr instanceof _.DictionaryAttr) {\n            const value = this.propertiesAttr.get(name);\n            if (value !== undefined) {\n                return value;\n            }\n        }\n        return this.attributes.get(name);\n    }\n\n    getAttrDictionary() {\n        if (this.propertiesAttr instanceof _.DictionaryAttr) {\n            const result = new Map(this.attributes);\n            for (const [name, value] of this.propertiesAttr.value) {\n                result.set(name, value);\n            }\n            return result;\n        }\n        return this.attributes;\n    }\n};\n\n_.OperationName = class {\n\n    constructor(dialect, name) {\n        this.dialect = dialect;\n        this.name = name;\n    }\n\n    getStringRef() {\n        return this.name;\n    }\n\n    getRegisteredInfo() {\n        return null;\n    }\n};\n\n_.RegisteredOperationName = class extends _.OperationName {\n\n    constructor(dialect, name, metadata) {\n        super(dialect, name);\n        this.metadata = metadata;\n        if (metadata.assemblyFormat) {\n            const parser = new _.AssemblyFormatParser(metadata);\n            this.directives = parser.parse();\n        }\n    }\n\n    static lookup(name, context) {\n        const index = name.indexOf('.');\n        if (index !== -1) {\n            const dialectName = name.substring(0, index);\n            const dialect = context.getOrLoadDialect(dialectName);\n            if (dialect) {\n                return dialect.getOperation(name);\n            }\n        }\n        return null;\n    }\n\n    getRegisteredInfo() {\n        return this;\n    }\n\n    hasTrait(type) {\n        if (this.metadata && Array.isArray(this.metadata.traits)) {\n            for (const trait of this.metadata.traits) {\n                if (trait.type && trait.type.name === type) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n};\n\n_.Operation = class {\n\n    static create(state) {\n        return new _.Operation(state);\n    }\n\n    constructor(state) {\n        this.name = state.name; // registered operation name\n        this.identifier = state.identifier; // original parsed identifier\n        this.label = state.label; // human-readable name\n        this.attributes = state.attributes;\n        this.operands = state.operands;\n        this.regions = state.regions;\n        this.propertiesAttr = state.propertiesAttr;\n        this.loc = state.loc;\n        this.results = [];\n        if (Array.isArray(state.types)) {\n            for (let i = 0; i < state.types.length; i++) {\n                const result = new _.OpResult(this, i, state.types[i]);\n                this.results.push(result);\n            }\n        }\n    }\n\n    getAttr(name) {\n        if (this.propertiesAttr instanceof _.DictionaryAttr) {\n            const value = this.propertiesAttr.get(name);\n            if (value !== undefined) {\n                return value;\n            }\n        }\n        return this.attributes.get(name);\n    }\n\n    getAttrDictionary() {\n        if (this.propertiesAttr instanceof _.DictionaryAttr) {\n            const result = new Map(this.attributes);\n            for (const [key, value] of this.propertiesAttr.value) {\n                result.set(key, value);\n            }\n            return result;\n        }\n        return this.attributes;\n    }\n};\n\n_.UnresolvedOperand = class {\n\n    constructor(location, name, number) {\n        this.location = location;\n        this.name = name;\n        this.number = number;\n    }\n\n    toString() {\n        return this.number > 0 ? `${this.name}#${this.number}` : this.name;\n    }\n};\n\n_.Value = class {\n\n    constructor(name, type) {\n        this.name = name;\n        this.type = type;\n    }\n\n    toString() {\n        return this.name;\n    }\n};\n\n_.OpResult = class extends _.Value {\n\n    constructor(owner, resultNumber, type) {\n        super(null, type);\n        this.owner = owner;\n        this.resultNumber = resultNumber;\n    }\n};\n\n_.Attribute = class {\n};\n\n_.TypedAttr = class extends _.Attribute {\n\n    constructor(value, type) {\n        super();\n        this.value = value;\n        this.type = type;\n    }\n\n    toString() {\n        return this.value;\n    }\n};\n\n_.StringAttr = class extends _.TypedAttr {\n\n    constructor(value, type) {\n        super(value, type || new _.PrimitiveType('string'));\n    }\n\n    toString() {\n        return this.value;\n    }\n};\n\n_.UnitAttr = class extends _.Attribute {\n\n    toString() {\n        return '';\n    }\n};\n\n_.IntegerAttr = class extends _.Attribute {\n\n    constructor(type, value) {\n        super();\n        this.value = value;\n        this.type = type;\n    }\n\n    toString() {\n        return this.value.toString();\n    }\n};\n\n_.BoolAttr = class extends _.Attribute {\n\n    constructor(value) {\n        super();\n        this.value = value;\n        this.type = new _.IntegerType('i1');\n    }\n\n    toString() {\n        return this.value ? 'true' : 'false';\n    }\n};\n\n_.FloatAttr = class extends _.Attribute {\n\n    constructor(type, value) {\n        super();\n        this.value = value;\n        this.type = type;\n    }\n\n    toString() {\n        return String(this.value);\n    }\n};\n\n_.MemRefLayoutAttr = class extends _.Attribute {\n};\n\n_.AffineMapAttr = class extends _.MemRefLayoutAttr {\n\n    constructor(map) {\n        super();\n        this._map = map;\n    }\n\n    get value() {\n        return this._map;\n    }\n\n    toString() {\n        return `affine_map<${this._map.toString()}>`;\n    }\n};\n\n_.IntegerSetAttr = class extends _.Attribute {\n\n    constructor(set) {\n        super();\n        this._set = set;\n    }\n\n    get value() {\n        return this._set;\n    }\n\n    toString() {\n        return `affine_set<${this._set.toString()}>`;\n    }\n};\n\n_.StridedLayoutAttr = class extends _.MemRefLayoutAttr {\n\n    constructor(offset, strides) {\n        super();\n        this.offset = offset;\n        this.strides = strides;\n    }\n\n    toString() {\n        const strides = `[${this.strides.join(', ')}]`;\n        if (this.offset !== null) {\n            return `strided<${strides}, offset: ${this.offset}>`;\n        }\n        return `strided<${strides}>`;\n    }\n};\n\n_.SymbolRefAttr = class extends _.Attribute {\n\n    constructor(rootReference, nestedReferences) {\n        super();\n        this.rootReference = rootReference;\n        this.nestedReferences = nestedReferences;\n    }\n\n    get value() {\n        if (this.nestedReferences && this.nestedReferences.length > 0) {\n            return `${this.rootReference}${this.nestedReferences.map((ref) => `::${ref}`).join('')}`;\n        }\n        return this.rootReference;\n    }\n\n    toString() {\n        return this.value;\n    }\n};\n\n_.DenseElementsAttr = class extends _.Attribute {\n\n    constructor(value, type) {\n        super();\n        this.value = value;\n        this.type = type;\n    }\n};\n\n_.SparseElementsAttr = class extends _.Attribute {\n\n    constructor(type, indices, values) {\n        super();\n        this.type = type;\n        this.indices = indices;\n        this.values = values;\n    }\n};\n\n_.DenseResourceElementsHandle = class {\n\n    constructor(key, blob = null) {\n        this.key = key;\n        this.blob = blob;\n    }\n};\n\n_.DenseResourceElementsAttr = class extends _.Attribute {\n\n    constructor(type, handle) {\n        super();\n        this.type = type;\n        this.rawHandle = handle;\n    }\n\n    get value() {\n        return this.rawHandle ? this.rawHandle.blob : null;\n    }\n\n    toString() {\n        const key = this.rawHandle ? this.rawHandle.key : 'unknown';\n        return `dense_resource<${key}>`;\n    }\n};\n\n_.OpaqueAttr = class extends _.Attribute {\n\n    constructor(dialectName, symbolData, type) {\n        super();\n        this.dialectName = dialectName;\n        this.symbolData = symbolData;\n        this.type = type;\n    }\n\n    get value() {\n        return this.toString();\n    }\n\n    toString() {\n        if (this.symbolData) {\n            return `${this.dialectName}.${this.symbolData}`;\n        }\n        return this.dialectName;\n    }\n};\n\n_.AffineLowPrecOp = {\n    LNoOp: '',\n    Add: 'Add',\n    Sub: 'Sub'\n};\n\n_.AffineHighPrecOp = {\n    HNoOp: '',\n    Mul: 'Mul',\n    FloorDiv: 'FloorDiv',\n    CeilDiv: 'CeilDiv',\n    Mod: 'Mod'\n};\n\n_.AffineExprKind = {\n    Add: 'Add',\n    Mul: 'Mul',\n    Mod: 'Mod',\n    FloorDiv: 'FloorDiv',\n    CeilDiv: 'CeilDiv',\n    Constant: 'Constant',\n    DimId: 'DimId',\n    SymbolId: 'SymbolId'\n};\n\n_.AffineExpr = class {\n\n    constructor(kind) {\n        this.kind = kind;\n    }\n\n    isSymbolicOrConstant() {\n        return this.kind === _.AffineExprKind.Constant || this.kind === _.AffineExprKind.SymbolId;\n    }\n\n    printAffineExprInternal(/* enclosingStrong */) {\n        return '';\n    }\n\n    toString() {\n        return this.printAffineExprInternal(false);\n    }\n};\n\n_.AffineDimExpr = class extends _.AffineExpr {\n\n    constructor(position) {\n        super(_.AffineExprKind.DimId);\n        this._position = position;\n    }\n\n    getPosition() {\n        return this._position;\n    }\n\n    toString() {\n        return `d${this._position}`;\n    }\n};\n\n_.AffineSymbolExpr = class extends _.AffineExpr {\n\n    constructor(position) {\n        super(_.AffineExprKind.SymbolId);\n        this._position = position;\n    }\n\n    getPosition() {\n        return this._position;\n    }\n\n    toString() {\n        return `s${this._position}`;\n    }\n};\n\n_.AffineConstantExpr = class extends _.AffineExpr {\n\n    constructor(value) {\n        super(_.AffineExprKind.Constant);\n        this.value = value;\n    }\n\n    toString() {\n        return String(this.value);\n    }\n};\n\n_.AffineBinaryOpExpr = class extends _.AffineExpr {\n\n    constructor(kind, lhs, rhs) {\n        super(kind);\n        this.lhs = lhs;\n        this.rhs = rhs;\n    }\n\n    isSymbolicOrConstant() {\n        return this.lhs.isSymbolicOrConstant() && this.rhs.isSymbolicOrConstant();\n    }\n\n    printAffineExprInternal(enclosingStrong) {\n        let op = '';\n        switch (this.kind) {\n            case _.AffineExprKind.Add: op = ' + '; break;\n            case _.AffineExprKind.Mul: op = ' * '; break;\n            case _.AffineExprKind.Mod: op = ' mod '; break;\n            case _.AffineExprKind.FloorDiv: op = ' floordiv '; break;\n            case _.AffineExprKind.CeilDiv: op = ' ceildiv '; break;\n            default: throw new Error(`Unexpected affine expression kind '${this.kind}'.`);\n        }\n        const isAdd = this.kind === _.AffineExprKind.Add;\n        const needsParens = enclosingStrong === true;\n        if (!isAdd) {\n            if (this.kind === _.AffineExprKind.Mul && this.rhs instanceof _.AffineConstantExpr && this.rhs.value === -1) {\n                const inner = `-${this.lhs.printAffineExprInternal(true)}`;\n                return needsParens ? `(${inner})` : inner;\n            }\n            const inner = `${this.lhs.printAffineExprInternal(true)}${op}${this.rhs.printAffineExprInternal(true)}`;\n            return needsParens ? `(${inner})` : inner;\n        }\n        if (this.rhs instanceof _.AffineBinaryOpExpr && this.rhs.kind === _.AffineExprKind.Mul &&\n            this.rhs.rhs instanceof _.AffineConstantExpr && this.rhs.rhs.value === -1) {\n            const lhsStr = this.lhs.printAffineExprInternal(false);\n            const rhsNeedsParens = this.rhs.lhs instanceof _.AffineBinaryOpExpr && this.rhs.lhs.kind === _.AffineExprKind.Add;\n            const rhsStr = this.rhs.lhs.printAffineExprInternal(rhsNeedsParens);\n            const inner = `${lhsStr} - ${rhsStr}`;\n            return needsParens ? `(${inner})` : inner;\n        }\n        if (this.rhs instanceof _.AffineConstantExpr && this.rhs.value < 0) {\n            const inner = `${this.lhs.printAffineExprInternal(false)} - ${-this.rhs.value}`;\n            return needsParens ? `(${inner})` : inner;\n        }\n        const inner = `${this.lhs.printAffineExprInternal(false)}${op}${this.rhs.printAffineExprInternal(false)}`;\n        return needsParens ? `(${inner})` : inner;\n    }\n};\n\n_.AffineMap = class {\n\n    constructor(numDims, numSymbols, results) {\n        this._numDims = numDims;\n        this._numSymbols = numSymbols;\n        this._results = results; // Array of AffineExpr or string for backward compat\n    }\n\n    getNumResults() {\n        return this._results.length;\n    }\n\n    toString() {\n        const dims = [];\n        for (let i = 0; i < this._numDims; i++) {\n            dims.push(`d${i}`);\n        }\n        const symbols = [];\n        for (let i = 0; i < this._numSymbols; i++) {\n            symbols.push(`s${i}`);\n        }\n        const dimsStr = `(${dims.join(', ')})`;\n        const symbolsStr = symbols.length > 0 ? `[${symbols.join(', ')}]` : '';\n        const resultsStr = this._results.map((r) => r.toString ? r.toString() : String(r)).join(', ');\n        return `${dimsStr}${symbolsStr} -> (${resultsStr})`;\n    }\n\n    static get(numDims, numSymbols, results) {\n        return new _.AffineMap(numDims, numSymbols, results);\n    }\n\n    // Backward compatible string-based parse\n    static parse(str) {\n        const arrowIdx = str.indexOf('->');\n        if (arrowIdx === -1) {\n            return new _.AffineMap(0, 0, [str]);\n        }\n        let resultPart = str.substring(arrowIdx + 2).trim();\n        const domainIdx = resultPart.indexOf(', domain:');\n        if (domainIdx !== -1) {\n            resultPart = resultPart.substring(0, domainIdx).trim();\n        }\n        // Parse result expressions from the result part (e.g., \"(d0, d1 + s0)\")\n        const results = [];\n        if (resultPart.startsWith('(')) {\n            let depth = 0;\n            let start = 1; // Skip opening paren\n            for (let i = 0; i < resultPart.length; i++) {\n                const ch = resultPart[i];\n                if (ch === '(' || ch === '[') {\n                    depth++;\n                } else if (ch === ')' || ch === ']') {\n                    depth--;\n                    if (depth === 0) {\n                        const expr = resultPart.substring(start, i).trim();\n                        if (expr) {\n                            results.push(expr);\n                        }\n                        break;\n                    }\n                } else if (ch === ',' && depth === 1) {\n                    const expr = resultPart.substring(start, i).trim();\n                    if (expr) {\n                        results.push(expr);\n                    }\n                    start = i + 1;\n                }\n            }\n        } else {\n            results.push(resultPart);\n        }\n        // For backward compat, store string representation of results\n        return new _.AffineMap(0, 0, results.length > 0 ? results : [str]);\n    }\n};\n\n// Integer set for affine_set constraints\n_.IntegerSet = class {\n\n    constructor(numDims, numSymbols, constraints, eqFlags) {\n        this._numDims = numDims;\n        this._numSymbols = numSymbols;\n        this._constraints = constraints; // Array of AffineExpr\n        this._eqFlags = eqFlags; // Array of bool (true = equality, false = inequality)\n    }\n\n    getNumConstraints() {\n        return this._constraints.length;\n    }\n\n    getConstraints() {\n        return this._constraints;\n    }\n\n    getConstraint(idx) {\n        return this._constraints[idx];\n    }\n\n    getEqFlags() {\n        return this._eqFlags;\n    }\n\n    isEq(idx) {\n        return this._eqFlags[idx];\n    }\n\n    toString() {\n        const dims = [];\n        for (let i = 0; i < this._numDims; i++) {\n            dims.push(`d${i}`);\n        }\n        const symbols = [];\n        for (let i = 0; i < this._numSymbols; i++) {\n            symbols.push(`s${i}`);\n        }\n        const dimsStr = `(${dims.join(', ')})`;\n        const symbolsStr = symbols.length > 0 ? `[${symbols.join(', ')}]` : '';\n        const constraintsStr = this._constraints.map((c, i) => {\n            const exprStr = c.toString ? c.toString() : String(c);\n            return this._eqFlags[i] ? `${exprStr} == 0` : `${exprStr} >= 0`;\n        }).join(', ');\n        return `${dimsStr}${symbolsStr} : (${constraintsStr})`;\n    }\n\n    static get(numDims, numSymbols, constraints, eqFlags) {\n        return new _.IntegerSet(numDims, numSymbols, constraints, eqFlags);\n    }\n};\n\n_.IndexingMap = class {\n\n    constructor(affineMap) {\n        this._affineMap = affineMap;\n    }\n\n    GetAffineMap() {\n        return this._affineMap;\n    }\n};\n\n_.IndexingMapAttr = class extends _.Attribute {\n\n    constructor(indexingMap) {\n        super();\n        this._indexingMap = indexingMap;\n    }\n\n    get value() {\n        return this.toString();\n    }\n\n    getIndexingMap() {\n        return this._indexingMap;\n    }\n\n    static parse(parser /*, type */) {\n        parser.parseLess();\n        const indexingMap = _.IndexingMapAttr.parseChainOfStringsAsIndexingMap(parser);\n        parser.parseGreater();\n        return new _.IndexingMapAttr(indexingMap);\n    }\n\n    static parseChainOfStringsAsIndexingMap(parser) {\n        let indexingMapStr = '';\n        let str = parser.parseOptionalString();\n        while (str !== null) {\n            indexingMapStr += str;\n            str = parser.parseOptionalString();\n        }\n        return _.IndexingMapAttr.parseIndexingMap(indexingMapStr);\n    }\n\n    static parseIndexingMap(str) {\n        const domainIdx = str.indexOf(', domain:');\n        const mapStr = domainIdx >= 0 ? str.substring(0, domainIdx) : str.replace(/,$/, '');\n        const affineMap = _.AffineMap.parse(mapStr);\n        return new _.IndexingMap(affineMap);\n    }\n\n    toString() {\n        return `#xla.indexing_map<\"${this._indexingMap.GetAffineMap().toString()}\">`;\n    }\n};\n\n_.ArrayAttr = class extends _.Attribute {\n\n    constructor(elements) {\n        super();\n        this.elements = elements; // Array of Attribute objects\n    }\n\n    get value() {\n        return this.elements.map((e) => e && e.value !== undefined ? e.value : e);\n    }\n\n    toString() {\n        return `${this.elements.map((e) => e && e.toString ? e.toString() : String(e)).join(', ')}`;\n    }\n};\n\n_.DenseI64ArrayAttr = class extends _.Attribute {\n\n    constructor(values) {\n        super();\n        this._values = values; // Array of i64 integers\n    }\n\n    get value() {\n        return this._values;\n    }\n\n    toString() {\n        return `[${this._values.join(', ')}]`;\n    }\n\n    static parse(parser) {\n        if (!parser.parseOptionalLSquare()) {\n            return null;\n        }\n        const values = [];\n        while (!parser.parseOptionalRSquare()) {\n            const value = parser.parseOptionalInteger();\n            if (value === null) {\n                break;\n            }\n            values.push(value);\n            parser.parseOptionalComma();\n        }\n        return new _.DenseI64ArrayAttr(values);\n    }\n};\n\n_.DictionaryAttr = class extends _.Attribute {\n\n    constructor(value) {\n        super();\n        this._value = value; // Map of name -> Attribute\n    }\n\n    get value() {\n        return this._value;\n    }\n\n    get(name) {\n        return this._value.get(name);\n    }\n\n    toString() {\n        const entries = Array.from(this._value.entries())\n            .map(([k, v]) => `${k} = ${v && v.toString ? v.toString() : String(v)}`);\n        return `{${entries.join(', ')}}`;\n    }\n};\n\n_.DenseArrayAttr = class extends _.Attribute {\n\n    constructor(type, size, data) {\n        super();\n        this.type = type;\n        this.size = size;\n        if (data instanceof Uint8Array) {\n            this.values = null;\n            this.data = data;\n        } else {\n            this.values = data;\n        }\n    }\n\n    get value() {\n        if (this.values === null) {\n            const blob = this.data;\n            const typeStr = this.type.toString();\n            const view = new DataView(blob.buffer, blob.byteOffset, blob.length);\n            const values = [];\n            if (typeStr.startsWith('i') || typeStr.startsWith('si') || typeStr.startsWith('ui') || typeStr === 'index') {\n                const match = typeStr.match(/[su]?i(\\d+)/);\n                const bitWidth = match ? parseInt(match[1], 10) : 64;\n                const unsigned = typeStr.startsWith('ui');\n                const byteWidth = Math.ceil(bitWidth / 8);\n                const size = blob.length / byteWidth;\n                for (let i = 0; i < size; i++) {\n                    if (bitWidth <= 8) {\n                        values.push(unsigned ? view.getUint8(i * byteWidth) : view.getInt8(i * byteWidth));\n                    } else if (bitWidth <= 16) {\n                        values.push(unsigned ? view.getUint16(i * byteWidth, true) : view.getInt16(i * byteWidth, true));\n                    } else if (bitWidth <= 32) {\n                        values.push(unsigned ? view.getUint32(i * byteWidth, true) : view.getInt32(i * byteWidth, true));\n                    } else {\n                        values.push(unsigned ? view.getBigUint64(i * byteWidth, true) : view.getBigInt64(i * byteWidth, true));\n                    }\n                }\n            } else if (typeStr === 'f32') {\n                const size = blob.length / 4;\n                for (let i = 0; i < size; i++) {\n                    values.push(view.getFloat32(i * 4, true));\n                }\n            } else if (typeStr === 'f64') {\n                const size = blob.length / 8;\n                for (let i = 0; i < size; i++) {\n                    values.push(view.getFloat64(i * 8, true));\n                }\n            } else if (typeStr === 'f16') {\n                const size = blob.length / 2;\n                for (let i = 0; i < size; i++) {\n                    values.push(view.getFloat16(i * 2, true));\n                }\n            }\n            this.values = values;\n            this.data = null;\n        }\n        return this.values;\n    }\n\n    toString() {\n        const typeStr = this.type ? this.type.toString() : '';\n        return `array<${typeStr}: ${this.value.join(', ')}>`;\n    }\n};\n\n_.DenseI32ArrayAttr = class extends _.DenseArrayAttr {\n\n    constructor(data) {\n        super(new _.IntegerType('i32'), Array.isArray(data) ? data.length : 0, data);\n    }\n};\n\n_.TypeAttrOf = class extends _.Attribute {\n    constructor(type) {\n        super();\n        this.type = type;  // the type IS the value\n    }\n\n    toString() {\n        return this.type.toString();\n    }\n};\n\n_.ConvDimensionNumbersAttr = class extends _.Attribute {\n    constructor(input, kernel, output) {\n        super();\n        this.input = input;\n        this.kernel = kernel;\n        this.output = output;\n    }\n\n    toString() {\n        const formatDim = (dims) => `[${dims.join(', ')}]`;\n        return `${formatDim(this.input)}x${formatDim(this.kernel)}->${formatDim(this.output)}`;\n    }\n};\n\n_.StringRef = class {\n\n    constructor(value, position) {\n        this.value = value;\n        this.position = position;\n    }\n\n    data() {\n        return this.position;\n    }\n\n    str() {\n        return this.value;\n    }\n\n    drop_front(n = 1) {\n        return this.value.substring(n);\n    }\n\n    getAsInteger(radix) {\n        const str = this.value;\n        if (str.length === 0) {\n            return null;\n        }\n        const value = radix === 0 ? Number(str) : parseInt(str, radix);\n        if (!Number.isInteger(value)) {\n            return null;\n        }\n        return value;\n    }\n\n    toString() {\n        return this.value;\n    }\n};\n\n_.Type = class {\n\n    constructor(value) {\n        if (value && value instanceof _.RankedTensorType === false && value.startsWith('tensor<')) {\n            // Do not remove. Investigate why RankedTensorType is not getting parsed.\n            throw new mlir.Error(`Invalid type '${value}'.`);\n        }\n        this._value = value;\n    }\n\n    get name() {\n        return this._value;\n    }\n\n    toString() {\n        return this._value;\n    }\n};\n\n_.OpaqueType = class extends _.Type {\n\n    constructor(dialect, symbolData) {\n        super();\n        this.dialect = dialect;\n        this.symbolData = symbolData;\n    }\n\n    toString() {\n        return `!${this.dialect}${this.symbolData}`;\n    }\n};\n\n_.util = {};\n\n_.util.VariantType = class extends _.Type {\n\n    toString() {\n        return '?';\n    }\n};\n\n_.util.ListType = class extends _.Type {\n\n    constructor(elementType) {\n        super();\n        this.elementType = elementType;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const elementType = parser.parseOptionalQuestion()\n            ? new _.util.VariantType()\n            : parser.parseType();\n        parser.parseGreater();\n        return new _.util.ListType(elementType);\n    }\n\n    toString() {\n        return `!util.list<${this.elementType}>`;\n    }\n};\n\n_.PrimitiveType = class extends _.Type {\n};\n\n_.IntegerType = class extends _.Type {\n};\n\n_.IntegerType.kMaxWidth = (1 << 24) - 1;\n\n_.FloatType = class extends _.Type {\n};\n\n_.NoneType = class extends _.Type {\n\n    constructor() {\n        super('none');\n    }\n};\n\n_.IndexType = class extends _.Type {\n\n    constructor() {\n        super('index');\n    }\n};\n\n_.FunctionType = class extends _.Type {\n\n    constructor(inputs, results) {\n        super(null);\n        this.inputs = inputs || [];\n        this.results = results || [];\n    }\n\n    toString() {\n        const inputs = this.inputs.map((t) => t.toString());\n        const results = this.results.map((t) => t.toString());\n        const result = results.length === 1 ? results[0] : `(${results.join(', ')})`;\n        return `(${inputs.join(', ')}) -> ${result}`;\n    }\n};\n\n_.ComplexType = class extends _.Type {\n\n    constructor(elementType) {\n        super(null);\n        this.elementType = elementType;\n    }\n\n    toString() {\n        const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;\n        return `complex<${elementTypeStr}>`;\n    }\n};\n\n_.ShapedType = class extends _.Type {\n\n    getNumElements() {\n        if (this.shape.some((d) => d < 0n || d === _.ShapedType.kDynamic)) {\n            return 0n;\n        }\n        return this.shape.length === 0 ? 1n : this.shape.reduce((a, b) => a * b, 1n);\n    }\n};\n\n_.ShapedType.kDynamic = -9223372036854775808n;\n\n_.RankedTensorType = class extends _.ShapedType {\n\n    constructor(shape, elementType, encoding) {\n        super(null);\n        this.shape = shape || [];\n        this.elementType = elementType;\n        this.encoding = encoding;\n    }\n\n    toString() {\n        const shapeStr = this.shape.map((d) => d < 0n ? '?' : d.toString()).join('x');\n        const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;\n        const prefix = shapeStr ? `${shapeStr}x` : '';\n        if (this.encoding) {\n            return `tensor<${prefix}${elementTypeStr}, ${this.encoding}>`;\n        }\n        return `tensor<${prefix}${elementTypeStr}>`;\n    }\n};\n\n_.UnrankedTensorType = class extends _.Type {\n\n    constructor(elementType) {\n        super(null);\n        this.elementType = elementType;\n    }\n\n    toString() {\n        const elementTypeStr = this.elementType.toString();\n        return `tensor<*x${elementTypeStr}>`;\n    }\n};\n\n_.VectorType = class extends _.ShapedType {\n\n    constructor(shape, elementType, scalableDims) {\n        super(null);\n        this.shape = shape || [];\n        this.elementType = elementType;\n        this.scalableDims = scalableDims || [];\n    }\n\n    toString() {\n        const parts = this.shape.map((d, i) => {\n            const isScalable = this.scalableDims[i];\n            return isScalable ? `[${d}]` : String(d);\n        });\n        const shapeStr = parts.join('x');\n        const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;\n        const prefix = shapeStr ? `${shapeStr}x` : '';\n        return `vector<${prefix}${elementTypeStr}>`;\n    }\n};\n\n_.MemRefType = class extends _.ShapedType {\n\n    constructor(shape, elementType, layout, memorySpace) {\n        super(null);\n        this.shape = shape || [];\n        this.elementType = elementType;\n        this.layout = layout || null;\n        this.memorySpace = memorySpace || null;\n    }\n\n    toString() {\n        const shapeStr = this.shape.map((d) => d < 0n ? '?' : d.toString()).join('x');\n        const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;\n        const prefix = shapeStr ? `${shapeStr}x` : '';\n        let result = `memref<${prefix}${elementTypeStr}`;\n        if (this.layout) {\n            result += `, ${this.layout.toString()}`;\n        }\n        if (this.memorySpace) {\n            result += `, ${this.memorySpace.toString()}`;\n        }\n        result += '>';\n        return result;\n    }\n};\n\n_.UnrankedMemRefType = class extends _.Type {\n\n    constructor(elementType, memorySpace) {\n        super(null);\n        this.elementType = elementType;\n        this.memorySpace = memorySpace || null;\n    }\n\n    toString() {\n        const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;\n        let result = `memref<*x${elementTypeStr}`;\n        if (this.memorySpace) {\n            result += `, ${this.memorySpace.toString()}`;\n        }\n        result += '>';\n        return result;\n    }\n};\n\n_.TupleType = class extends _.Type {\n\n    constructor(types) {\n        super(null);\n        this.types = types || [];\n    }\n\n    getTypes() {\n        return this.types;\n    }\n\n    getNumTypes() {\n        return this.types.length;\n    }\n\n    getType(index) {\n        return this.types[index];\n    }\n\n    toString() {\n        const typeStrs = this.types.map((t) => t?.toString ? t.toString() : t);\n        return `tuple<${typeStrs.join(', ')}>`;\n    }\n};\n\n_.SMLoc = class {\n\n    constructor(decoder, position) {\n        this.decoder = decoder;\n        this.position = position || 0;\n    }\n\n    copy() {\n        return new _.SMLoc(this.decoder, this.position);\n    }\n\n    toString() {\n        let line = 1;\n        let column = 1;\n        const position = this.decoder.position;\n        this.decoder.position = 0;\n        let c = '';\n        do {\n            if (this.decoder.position === this.position) {\n                this.decoder.position = position;\n                return `at ${line}:${column}.`;\n            }\n            c = this.decoder.decode();\n            if (c === '\\n') {\n                line++;\n                column = 1;\n            } else {\n                column++;\n            }\n        }\n        while (c !== undefined);\n        this.decoder.position = position;\n        return `at ${line}:${column}.`;\n    }\n};\n\n_.Token = class {\n\n    constructor(decoder) {\n        this.loc = new _.SMLoc(decoder);\n        this.kind = null;\n        this.spelling = new _.StringRef('', decoder.position);\n    }\n\n    is(kind) {\n        return this.kind === kind;\n    }\n\n    isAny(...args) {\n        return args.some((kind) => this.kind === kind);\n    }\n\n    isNot(kind) {\n        return this.kind !== kind;\n    }\n\n    isKeyword() {\n        return this.kind.startsWith('kw_');\n    }\n\n    getSpelling() {\n        return this.spelling;\n    }\n\n    getUnsignedIntegerValue() {\n        const isHex = this.spelling.str().length > 1 && this.spelling.str()[1] === 'x';\n        const value = this.spelling.getAsInteger(isHex ? 0 : 10);\n        if (value === null || value < 0 || value > 0xFFFFFFFF) {\n            return null;\n        }\n        return value;\n    }\n\n    getUInt64IntegerValue() {\n        const spelling = this.spelling.str();\n        if (/^-?(\\d+|0x[\\da-f]+|0o[0-7]+|0b[01]+)$/i.test(spelling)) {\n            return BigInt(spelling);\n        }\n        return null;\n    }\n\n    getFloatingPointValue() {\n        const result = parseFloat(this.spelling.str());\n        if (isNaN(result)) {\n            return null;\n        }\n        return result;\n    }\n\n    getIntTypeBitwidth() {\n        const spelling = this.spelling.str();\n        const start = spelling[0] === 'i' ? 1 : 2;\n        const result = parseInt(spelling.slice(start), 10);\n        if (isNaN(result)) {\n            return null;\n        }\n        return result;\n    }\n\n    getIntTypeSignedness() {\n        const spelling = this.spelling.str();\n        if (spelling[0] === 'i') {\n            return null;\n        }\n        if (spelling[0] === 's') {\n            return true;\n        }\n        return false;\n    }\n\n    getHexStringValue() {\n        const spelling = this.spelling.str();\n        const bytes = spelling.slice(1, -1);\n        if (!bytes.startsWith('0x') || (bytes.length - 2) % 2 !== 0) {\n            return null;\n        }\n        const hex = bytes.slice(2);\n        const result = [];\n        for (let i = 0; i < hex.length; i += 2) {\n            const hi = parseInt(hex[i], 16);\n            const lo = parseInt(hex[i + 1], 16);\n            if (isNaN(hi) || isNaN(lo)) {\n                return null;\n            }\n            result.push((hi << 4) | lo);\n        }\n        return result;\n    }\n\n    getSymbolReference() {\n        const nameStr = this.spelling.str().slice(1);\n        if (nameStr[0] === '\"') {\n            return this.getStringValue();\n        }\n        return nameStr;\n    }\n\n    getHashIdentifierNumber() {\n        const str = this.spelling.str().slice(1);\n        const result = parseInt(str, 10);\n        if (isNaN(result)) {\n            return null;\n        }\n        return result;\n    }\n\n    getStringValue() {\n        let bytes = this.spelling.str();\n        bytes = bytes.slice(1);\n        bytes = bytes.slice(0, -1);\n        if (this.kind === _.Token.at_identifier) {\n            bytes = bytes.slice(1);\n        }\n        if (!bytes.includes('\\\\')) {\n            return bytes;\n        }\n        const parts = [];\n        for (let i = 0; i < bytes.length;) {\n            const c = bytes[i++];\n            if (c !== '\\\\') {\n                parts.push(c);\n                continue;\n            }\n            const c1 = bytes[i++];\n            switch (c1) {\n                case '\"':\n                case '\\\\':\n                    parts.push(c1);\n                    continue;\n                case 'n':\n                    parts.push('\\n');\n                    continue;\n                case 't':\n                    parts.push('\\t');\n                    continue;\n                default:\n                    break;\n            }\n            const c2 = bytes[i++];\n            const hexValue = (parseInt(c1, 16) << 4) | parseInt(c2, 16);\n            parts.push(String.fromCharCode(hexValue));\n        }\n        return parts.join('');\n    }\n};\n\n_.Token.arrow = '->';\n_.Token.at_identifier = '@';\n_.Token.bare_identifier = 'id';\n_.Token.caret_identifier = '^';\n_.Token.colon = ':';\n_.Token.comma = ',';\n_.Token.ellipsis = 'ellipsis';\n_.Token.eof = 'eof';\n_.Token.equal = '=';\n_.Token.exclamation_identifier = '!';\n_.Token.file_metadata_begin = '{-#';\n_.Token.file_metadata_end = '#-}';\n_.Token.floatliteral = 'float';\n_.Token.greater = '>';\n_.Token.hash_identifier = '#';\n_.Token.integer = 'int';\n_.Token.inttype = 'inttype';\n_.Token.kw_ceildiv = 'kw_ceildiv';\n_.Token.kw_floordiv = 'kw_floordiv';\n_.Token.kw_mod = 'kw_mod';\n_.Token.l_brace = '{';\n_.Token.l_paren = '(';\n_.Token.l_square = '[';\n_.Token.less = '<';\n_.Token.minus = 'minus';\n_.Token.percent_identifier = '%';\n_.Token.plus = 'plus';\n_.Token.question = '?';\n_.Token.r_brace = '}';\n_.Token.r_paren = ')';\n_.Token.r_square = ']';\n_.Token.slash = '/';\n_.Token.star = '*';\n_.Token.string = 'string';\n_.Token.vertical_bar = '|';\n_.Token.kw_affine_map = 'kw_affine_map';\n_.Token.kw_affine_set = 'kw_affine_set';\n_.Token.kw_array = 'kw_array';\n_.Token.kw_dense = 'kw_dense';\n_.Token.kw_dense_resource = 'kw_dense_resource';\n_.Token.kw_distinct = 'kw_distinct';\n_.Token.kw_false = 'kw_false';\n_.Token.kw_loc = 'kw_loc';\n_.Token.kw_offset = 'kw_offset';\n_.Token.kw_sparse = 'kw_sparse';\n_.Token.kw_strided = 'kw_strided';\n_.Token.kw_symbol = 'kw_symbol';\n_.Token.kw_true = 'kw_true';\n_.Token.kw_unit = 'kw_unit';\n\n_.Lexer = class {\n\n    constructor(decoder) {\n        this._decoder = decoder;\n        this._currentPosition = this._decoder.position;\n        this._current = this._decoder.decode();\n        this._nextPosition = this._decoder.position;\n        this._next = this._decoder.decode();\n        this._tokens = [new _.Token(decoder), new _.Token(decoder), new _.Token(decoder), new _.Token(decoder)];\n        this._index = 0;\n        this._errorLoc = new _.SMLoc(decoder);\n    }\n\n    location() {\n        const loc = new _.SMLoc(this._decoder, this._position);\n        return loc.toString();\n    }\n\n    lexToken() {\n        this._position = this._currentPosition;\n        while (this._current) {\n            switch (this._current) {\n                case ' ':\n                case '\\t':\n                case '\\n':\n                case '\\r':\n                    this._skipWhitespace();\n                    this._position = this._currentPosition;\n                    continue;\n                case '/':\n                    if (this._peek() !== '/') {\n                        this._read();\n                        return this.formToken('/', '/');\n                    }\n                    this.lexComment();\n                    this._position = this._currentPosition;\n                    continue;\n                case '.':\n                    this._read();\n                    if (this._current === '.' && this._next === '.') {\n                        this._read();\n                        this._read();\n                        return this.formToken('ellipsis', '...');\n                    }\n                    throw new mlir.Error(`Expected three consecutive dots for an ellipsis ${this.location()}`);\n                case '-':\n                    if (this._peek() === '>') {\n                        this._read();\n                        this._read();\n                        return this.formToken('->', '->');\n                    }\n                    this._read();\n                    return this.formToken('minus', '-');\n                case '+':\n                    this._read();\n                    return this.formToken('plus', '+');\n                case '\"':\n                    return this.lexString();\n                case '@':\n                    return this.lexPrefixedIdentifier('@');\n                case '%':\n                    return this.lexPrefixedIdentifier('%');\n                case '#':\n                    if (this._peek() === '-') {\n                        const position = this._decoder.position;\n                        const next = this._decoder.decode();\n                        this._decoder.position = position;\n                        if (next === '}') {\n                            this._read();\n                            this._read();\n                            this._read();\n                            return this.formToken('#-}', '#-}');\n                        }\n                    }\n                    return this.lexPrefixedIdentifier('#');\n                case '!':\n                    return this.lexPrefixedIdentifier('!');\n                case '^':\n                    return this.lexPrefixedIdentifier('^');\n                case '=':\n                    this._read();\n                    return this.formToken('=', '=');\n                case ':':\n                    this._read();\n                    return this.formToken(':', ':');\n                case ',':\n                case '(':\n                case ')':\n                case '}':\n                case '[':\n                case ']':\n                case '<':\n                case '>':\n                case '?':\n                case '*':\n                case '|': {\n                    const value = this._read();\n                    return this.formToken(value, value);\n                }\n                case '{':\n                    if (this._peek() === '-') {\n                        const position = this._decoder.position;\n                        const next = this._decoder.decode();\n                        this._decoder.position = position;\n                        if (next === '#') {\n                            this._read();\n                            this._read();\n                            this._read();\n                            return this.formToken('{-#', '{-#');\n                        }\n                    }\n                    this._read();\n                    return this.formToken('{', '{');\n                default:\n                    if (/[a-zA-Z_]/.test(this._current)) {\n                        return this.lexBareIdentifierOrKeyword();\n                    }\n                    if (/[0-9]/.test(this._current)) {\n                        return this.lexNumber();\n                    }\n                    throw new mlir.Error(`Unexpected character '${this._current}' ${this.location()}`);\n            }\n        }\n        return this.formToken('eof', null);\n    }\n\n    resetPointer(newPointer) {\n        if (newPointer < 0) {\n            throw new mlir.Error('Invalid negative offset.');\n        }\n        this._decoder.position = newPointer;\n        this._nextPosition = this._decoder.position;\n        this._next = this._decoder.decode();\n        this._read();\n    }\n\n    _read() {\n        const current = this._current;\n        this._current = this._next;\n        this._currentPosition = this._nextPosition;\n        this._nextPosition = this._decoder.position;\n        this._next = this._decoder.decode();\n        return current;\n    }\n\n    _peek() {\n        return this._next;\n    }\n\n    _eat(value) {\n        if (this._current === value) {\n            this._read();\n            return true;\n        }\n        return false;\n    }\n\n    _skipWhitespace() {\n        while (this._current !== undefined && (this._current === ' ' || this._current === '\\t' || this._current === '\\n' || this._current === '\\r')) {\n            this._read();\n        }\n    }\n\n    lexComment() {\n        this._read('/');\n        if (this._current !== '/') {\n            throw new mlir.Error(`Invalid comment.`);\n        }\n        while (this._current && this._current !== '\\n' && this._current !== '\\r') {\n            this._read();\n        }\n    }\n\n    lexNumber() {\n        let v = '';\n        let type = 'int';\n        while (this._current && /[0-9]/.test(this._current)) {\n            v += this._read();\n        }\n        if (v === '0' && this._current === 'x' && /[0-9a-fA-F]/.test(this._peek())) {\n            v += this._read();\n            while (this._current && /[0-9a-fA-F]/.test(this._current)) {\n                v += this._read();\n            }\n            return this.formToken(type, v);\n        }\n        if (this._current === '.') {\n            v += this._read();\n            type = 'float';\n            while (this._current && /[0-9]/.test(this._current)) {\n                v += this._read();\n            }\n            if (this._current === 'e' || this._current === 'E') {\n                const next1 = this._peek();\n                let next2 = '';\n                if (next1 === '+' || next1 === '-') {\n                    const position = this._decoder.position;\n                    next2 = this._decoder.decode();\n                    this._decoder.position = position;\n                }\n                if (/[0-9]/.test(next1) || ((next1 === '+' || next1 === '-') && /[0-9]/.test(next2))) {\n                    v += this._read();\n                    if (this._current === '+' || this._current === '-') {\n                        v += this._read();\n                    }\n                    while (this._current && /[0-9]/.test(this._current)) {\n                        v += this._read();\n                    }\n                }\n            }\n            return this.formToken(type, v);\n        }\n        return this.formToken(type, v);\n    }\n\n    lexString() {\n        const parts = ['\"'];\n        this._read();\n        let chunk = '';\n        while (this._current && this._current !== '\"') {\n            if (this._current === '\\n' || this._current === '\\v' ||\n                this._current === '\\f' || this._current === '\\r') {\n                throw new mlir.Error(`Expected '\"' in string literal ${this.location()}`);\n            }\n            if (this._current === '\\\\') {\n                if (chunk) {\n                    parts.push(chunk);\n                    chunk = '';\n                }\n                parts.push(this._current);\n                this._read();\n                if (this._current === '\"' || this._current === '\\\\' || this._current === 'n' || this._current === 't') {\n                    parts.push(this._current);\n                    this._read();\n                } else if (this._current && /[0-9a-fA-F]/.test(this._current) && this._next && /[0-9a-fA-F]/.test(this._next)) {\n                    parts.push(this._current);\n                    this._read();\n                    parts.push(this._current);\n                    this._read();\n                } else {\n                    throw new mlir.Error(`Unknown escape in string literal ${this.location()}`);\n                }\n            } else {\n                chunk += this._current;\n                if (chunk.length >= 4096) {\n                    parts.push(chunk);\n                    chunk = '';\n                }\n                this._read();\n            }\n        }\n        if (chunk) {\n            parts.push(chunk);\n        }\n        if (this._eat('\"')) {\n            parts.push('\"');\n            return this.formToken(_.Token.string, parts.join(''));\n        }\n        throw new mlir.Error('Unterminated string literal');\n    }\n\n    lexBareIdentifierOrKeyword() {\n        let result = '';\n        while (this._current && (/[a-zA-Z_$.]/.test(this._current) || /[0-9]/.test(this._current))) {\n            result += this._read();\n        }\n        const isAllDigit = (str) => /^[0-9]+$/.test(str);\n        if ((result.length > 1 && result[0] === 'i' && isAllDigit(result.slice(1))) ||\n            (result.length > 2 && result[1] === 'i' && (result[0] === 's' || result[0] === 'u') && isAllDigit(result.slice(2)))) {\n            return this.formToken('inttype', result);\n        }\n        switch (result) {\n            case 'affine_map':\n            case 'affine_set':\n            case 'array':\n            case 'ceildiv':\n            case 'dense':\n            case 'dense_resource':\n            case 'distinct':\n            case 'floordiv':\n            case 'loc':\n            case 'mod':\n            case 'offset':\n            case 'sparse':\n            case 'strided':\n            case 'symbol':\n            case 'unit':\n                return this.formToken(`kw_${result}`, result);\n            case 'true':\n                return this.formToken(_.Token.kw_true, result);\n            case 'false':\n                return this.formToken(_.Token.kw_false, result);\n            default:\n                return this.formToken(_.Token.bare_identifier, result);\n        }\n    }\n\n    lexPrefixedIdentifier(prefix) {\n        let result = prefix;\n        this._read();\n        if (prefix === '@' && this._current === '\"') {\n            result += this.lexString().getSpelling().str();\n            return this.formToken(prefix, result);\n        }\n        if (prefix === '@') {\n            // symbol-ref-id ::= `@` (bare-id | string-literal)\n            // bare-id ::= (letter|[_]) (letter|digit|[_$.])*\n            if (this._current && /[a-zA-Z_]/.test(this._current)) {\n                while (this._current && /[a-zA-Z0-9_$.]/.test(this._current)) {\n                    result += this._read();\n                }\n            } else if (result.length === 1) {\n                throw new mlir.Error(`@ identifier expected to start with letter or '_' ${this.location()}`);\n            }\n        } else if (this._current && /[0-9]/.test(this._current)) {\n            // suffix-id ::= digit+ | ...\n            while (this._current && /[0-9]/.test(this._current)) {\n                result += this._read();\n            }\n        } else if (this._current && /[a-zA-Z_$.-]/.test(this._current)) {\n            // suffix-id ::= ... | (letter|id-punct) (letter|id-punct|digit)*\n            while (this._current && /[a-zA-Z_$0-9.-]/.test(this._current)) {\n                if (this._current === '-' && this._peek() === '>') {\n                    break;\n                }\n                result += this._read();\n            }\n        } else if (result.length === 1) {\n            const errorKinds = { '#': 'Invalid attribute name', '%': 'Invalid SSA name', '^': 'Invalid block name', '!': 'Invalid type identifier' };\n            throw new mlir.Error(`${errorKinds[prefix] || 'Invalid identifier'} ${this.location()}`);\n        }\n        if (prefix === '@' && this._current === ':' && this._peek() === ':') {\n            result += this._read();\n            result += this._read();\n            result += this.lexPrefixedIdentifier('@').getSpelling().str();\n        }\n        const kind = prefix === '$' ? '%' : prefix;\n        return this.formToken(kind, result);\n    }\n\n    formToken(kind, value) {\n        const token = this._tokens[this._index];\n        this._index = (this._index + 1) % this._tokens.length;\n        token.loc.position = this._position;\n        token.kind = kind;\n        token.spelling.value = value;\n        token.spelling.position = this._position;\n        return token;\n    }\n};\n\n_.AsmResourceParser = class {\n\n    constructor(name) {\n        this.name = name;\n    }\n};\n\n_.ParsedResourceEntry = {};\n\n_.ParsedResourceEntry.Text = class {\n\n    constructor(key, keyLoc, value, parser) {\n        this.key = key;\n        this.keyLoc = keyLoc;\n        this.value = value;\n        this.parser = parser;\n    }\n\n    parseAsBool() {\n        if (this.value.kind === 'boolean') {\n            return this.value.value;\n        }\n        throw new mlir.Error(`Expected boolean value for resource entry '${this.key}'`);\n    }\n\n    parseAsString() {\n        if (this.value.kind === _.Token.string) {\n            return this.value.getStringValue();\n        }\n        throw new mlir.Error(`Expected string value for resource entry '${this.key}'`);\n    }\n\n    parseAsBlob() {\n        if (this.value.kind === _.Token.string) {\n            const hexStr = this.value.getStringValue();\n            if (hexStr.startsWith('0x')) {\n                const hex = hexStr.slice(2);\n                const bytes = new Uint8Array(hex.length / 2);\n                for (let i = 0; i < bytes.length; i++) {\n                    bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n                }\n                if (bytes.length >= 4) {\n                    return bytes.slice(4);\n                }\n                return bytes;\n            }\n        }\n        throw new mlir.Error(`Expected hex string blob value for resource entry '${this.key}'`);\n    }\n};\n\n_.ParserConfig = class {\n\n    constructor(context) {\n        this.context = context;\n        this.resourceParsers = new Map();\n    }\n\n    getResourceParser(name) {\n        return this.resourceParsers.get(name);\n    }\n\n    attachResourceParser(parser) {\n        this.resourceParsers.set(parser.name, parser);\n    }\n};\n\n_.ParserState = class {\n\n    constructor(decoder, config) {\n        this.config = config;\n        this.defaultDialectStack = ['builtin'];\n        this.attributeAliasDefinitions = new Map();\n        this.typeAliasDefinitions = new Map();\n        this.dialectResources = new Map();\n        this.deferredLocsReferences = [];\n        this.lex = new _.Lexer(decoder);\n        this.curToken = this.lex.lexToken();\n    }\n};\n\n_.IsolatedSSANameScope = class {\n\n    constructor() {\n        this.values = new Map();\n        this.definitionsPerScope = [];\n    }\n\n    recordDefinition(def) {\n        this.definitionsPerScope[this.definitionsPerScope.length - 1].add(def);\n    }\n\n    pushSSANameScope() {\n        this.definitionsPerScope.push(new Set());\n    }\n\n    popSSANameScope() {\n        for (const def of this.definitionsPerScope.pop()) {\n            this.values.delete(def);\n        }\n    }\n};\n\n_.Parser = class {\n\n    constructor(state) {\n        this.state = state;\n    }\n\n    get context() {\n        return this.state.config.context;\n    }\n\n    parseCommaSeparatedListUntil(rightToken, parseElement, allowEmptyList = true) {\n        if (this.getToken().is(rightToken)) {\n            if (!allowEmptyList) {\n                throw new mlir.Error(`Expected list element ${this.location()}`);\n            }\n            this.consumeToken(rightToken);\n            return;\n        }\n        this.parseCommaSeparatedList('none', parseElement);\n        this.parseToken(rightToken, `Expected '${rightToken}'`);\n    }\n\n    parseResourceFileMetadata(parseBody) {\n        this.parseToken(_.Token.l_brace, \"Expected '{'\");\n        this.parseCommaSeparatedListUntil(_.Token.r_brace, () => {\n            const nameLoc = this.getToken().loc;\n            const name = this.parseOptionalKeyword();\n            if (!name) {\n                throw new mlir.Error(`Expected identifier key for 'resource' entry ${this.location()}`);\n            }\n            this.parseToken(_.Token.colon);\n            this.parseToken(_.Token.l_brace);\n            parseBody(name, nameLoc);\n        });\n    }\n\n    parseDialectResourceFileMetadata() {\n        this.parseResourceFileMetadata((name /*, nameLoc */) => {\n            const dialect = this.context.getOrLoadDialect(name);\n            if (!dialect) {\n                throw new mlir.Error(`Dialect '${name}' is unknown ${this.location()}`);\n            }\n            this.parseCommaSeparatedListUntil(_.Token.r_brace, () => {\n                const keyLoc = this.getToken().loc.copy();\n                const handle = this.parseResourceHandle(dialect);\n                const key = dialect.getResourceKey(handle);\n                this.parseToken(_.Token.colon, \"Expected ':'\");\n                const valueTok = this.getToken();\n                this.consumeToken();\n                const entry = new _.ParsedResourceEntry.Text(key, keyLoc, valueTok, this);\n                dialect.parseResource(entry);\n            });\n        });\n    }\n\n    parseExternalResourceFileMetadata() {\n        this.parseResourceFileMetadata((name /*, nameLoc */) => {\n            const handler = this.state.config.getResourceParser(name);\n            this.parseCommaSeparatedListUntil(_.Token.r_brace, () => {\n                const keyLoc = this.getToken().loc;\n                const key = this.parseOptionalKeywordOrString();\n                if (!key) {\n                    throw new mlir.Error(`Expected identifier key for 'external_resources' entry ${this.location()}`);\n                }\n                this.parseToken(_.Token.colon, \"Expected ':'\");\n                const valueTok = this.getToken();\n                this.consumeToken();\n                if (handler && handler.parseResource) {\n                    const entry = new _.ParsedResourceEntry.Text(key, keyLoc, valueTok, this);\n                    handler.parseResource(entry);\n                }\n            });\n        });\n    }\n\n    parseOptionalKeywordOrString() {\n        const keyword = this.parseOptionalKeyword();\n        if (keyword) {\n            return keyword;\n        }\n        return this.parseOptionalString();\n    }\n\n    finalize(/* block */) {\n    }\n\n    isCurrentTokenAKeyword() {\n        return this.getToken().isAny(_.Token.bare_identifier, _.Token.inttype) || this.getToken().isKeyword();\n    }\n\n    parseOptionalKeyword() {\n        if (!this.isCurrentTokenAKeyword()) {\n            return null;\n        }\n        const keyword = this.getTokenSpelling().str();\n        this.consumeToken();\n        return keyword;\n    }\n\n    parseTypeListNoParens() {\n        return this.parseCommaSeparatedList('none', () => this.parseType());\n    }\n\n    parseTypeListParens() {\n        this.parseToken(_.Token.l_paren, \"Expected '('\");\n        if (this.consumeIf(_.Token.r_paren)) {\n            return [];\n        }\n        const types = this.parseTypeListNoParens();\n        this.parseToken(_.Token.r_paren, \"Expected ')'\");\n        return types;\n    }\n\n    parseSuccessors(successors) {\n        const parsed = this.parseCommaSeparatedList('square', () => {\n            const label = this.getTokenSpelling().str();\n            this.consumeToken(_.Token.caret_identifier);\n            return { label };\n        });\n        if (parsed.length === 0) {\n            throw new mlir.Error(`Expected at least one successor ${this.location()}`);\n        }\n        for (const s of parsed) {\n            successors.push(s);\n        }\n    }\n\n    parseAttributeDict(attributes) {\n        const seenKeys = new Set();\n        this.parseCommaSeparatedList('brace', () => {\n            // The name of an attribute can either be a bare identifier, or a string.\n            let name = null;\n            if (this.getToken().is(_.Token.string)) {\n                name = this.getToken().getStringValue();\n            } else if (this.getToken().isAny(_.Token.bare_identifier, _.Token.inttype) || this.getToken().isKeyword()) {\n                name = this.getTokenSpelling().str();\n            } else {\n                throw new mlir.Error(`Expected attribute name ${this.location()}`);\n            }\n            if (!name) {\n                throw new mlir.Error(`Expected attribute name ${this.location()}`);\n            }\n            this.consumeToken();\n            if (seenKeys.has(name)) {\n                throw new mlir.Error(`Duplicate key '${name}' in dictionary attribute ${this.location()}`);\n            }\n            seenKeys.add(name);\n            if (!this.consumeIf(_.Token.equal)) {\n                attributes.set(name, new _.UnitAttr());\n                return;\n            }\n            const attr = this.parseAttribute();\n            attributes.set(name, attr);\n        });\n    }\n\n    parseLocationInstance() {\n        if (this.getToken().is(_.Token.hash_identifier)) {\n            const locAttr = this.parseExtendedAttr();\n            if (locAttr instanceof _.LocationAttr === false && locAttr instanceof _.OpaqueAttr === false) {\n                throw new mlir.Error(`Expected location attribute, but got '${locAttr}' ${this.location()}`);\n            }\n            return locAttr;\n        }\n        if (this.getToken().is(_.Token.string)) {\n            return this.parseNameOrFileLineColRange();\n        }\n        if (!this.getToken().is(_.Token.bare_identifier)) {\n            throw new mlir.Error(`Expected location instance, got '${this.getTokenSpelling().str()}' ${this.location()}`);\n        }\n        if (this.getToken().spelling.str() === 'callsite') {\n            return this.parseCallSiteLocation();\n        }\n        if (this.getToken().spelling.str() === 'fused') {\n            return this.parseFusedLocation();\n        }\n        if (this.getToken().spelling.str() === 'unknown') {\n            this.consumeToken(_.Token.bare_identifier);\n            return new _.UnknownLoc();\n        }\n        throw new mlir.Error(`Expected location instance, got '${this.getTokenSpelling().str()}' ${this.location()}`);\n    }\n\n    parseCallSiteLocation() {\n        this.consumeToken(_.Token.bare_identifier);\n        this.parseToken(_.Token.l_paren, \"Expected '(' in callsite location\");\n        const callee = this.parseLocationInstance();\n        if (this.getToken().isNot(_.Token.bare_identifier) || this.getToken().getSpelling().str() !== 'at') {\n            throw new mlir.Error(`Expected 'at' in callsite location ${this.location()}`);\n        }\n        this.consumeToken(_.Token.bare_identifier);\n        const caller = this.parseLocationInstance();\n        this.parseToken(_.Token.r_paren, \"Expected ')' in callsite location\");\n        return new _.CallSiteLoc(callee, caller);\n    }\n\n    parseFusedLocation() {\n        this.consumeToken(_.Token.bare_identifier);\n        let metadata = null;\n        if (this.consumeIf(_.Token.less)) {\n            metadata = this.parseAttribute();\n            if (!metadata) {\n                throw new mlir.Error(`Expected attribute in fused location metadata ${this.location()}`);\n            }\n            this.parseToken(_.Token.greater, \"Expected '>' after fused location metadata\");\n        }\n        const locations = this.parseCommaSeparatedList('square', () => this.parseLocationInstance());\n        return new _.FusedLoc(locations, metadata);\n    }\n\n    parseNameOrFileLineColRange() {\n        const str = this.getToken().getStringValue();\n        this.consumeToken(_.Token.string);\n        if (this.consumeIf(_.Token.colon)) {\n            if (this.getToken().isNot(_.Token.integer)) {\n                throw new mlir.Error(`Expected integer line number in FileLineColRange ${this.location()}`);\n            }\n            const startLine = this.getToken().getUnsignedIntegerValue();\n            if (startLine === null) {\n                throw new mlir.Error(`Expected integer line number in FileLineColRange ${this.location()}`);\n            }\n            this.consumeToken(_.Token.integer);\n            if (this.getToken().isNot(_.Token.colon)) {\n                return new _.FileLineColRange(str, startLine);\n            }\n            this.consumeToken(_.Token.colon);\n            if (this.getToken().isNot(_.Token.integer)) {\n                throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);\n            }\n            const startCol = this.getToken().getUnsignedIntegerValue();\n            if (startCol === null) {\n                throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);\n            }\n            this.consumeToken(_.Token.integer);\n            if (!this.isCurrentTokenAKeyword() || this.getTokenSpelling().str() !== 'to') {\n                return new _.FileLineColLoc(str, startLine, startCol);\n            }\n            this.consumeToken();\n            let endLine = null;\n            if (this.getToken().is(_.Token.integer)) {\n                endLine = this.getToken().getUnsignedIntegerValue();\n                if (endLine === null) {\n                    throw new mlir.Error(`Expected integer line number in FileLineColRange ${this.location()}`);\n                }\n                this.consumeToken(_.Token.integer);\n            }\n            if (this.getToken().isNot(_.Token.colon)) {\n                throw new mlir.Error(`Expected either integer or ':' post 'to' in FileLineColRange ${this.location()}`);\n            }\n            this.consumeToken(_.Token.colon);\n            if (this.getToken().isNot(_.Token.integer)) {\n                throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);\n            }\n            const endCol = this.getToken().getUnsignedIntegerValue();\n            if (endCol === null) {\n                throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);\n            }\n            this.consumeToken(_.Token.integer);\n            if (endLine !== null) {\n                return new _.FileLineColRange(str, startLine, startCol, endLine, endCol);\n            }\n            return new _.FileLineColRange(str, startLine, startCol, undefined, endCol);\n        }\n        if (this.consumeIf(_.Token.l_paren)) {\n            const childLoc = this.parseLocationInstance();\n            this.parseToken(_.Token.r_paren, \"Expected ')' after child location of NameLoc\");\n            return new _.NameLoc(str, childLoc);\n        }\n        return new _.NameLoc(str);\n    }\n\n    parseLocationAlias() {\n        const tok = this.getToken();\n        this.consumeToken(_.Token.hash_identifier);\n        const identifier = tok.getSpelling().str().substring(1); // drop_front - remove '#' prefix\n        const attr = this.state.attributeAliasDefinitions.get(tok.getSpelling().str());\n        if (attr) {\n            if (attr instanceof _.LocationAttr) {\n                return attr;\n            }\n            return attr;\n        }\n        const index = this.state.deferredLocsReferences.length;\n        this.state.deferredLocsReferences.push({ loc: tok.loc, identifier });\n        return new _.OpaqueLoc(index, identifier, new _.UnknownLoc());\n    }\n\n    parseOptionalLocationSpecifier() {\n        if (!this.consumeIf(_.Token.kw_loc)) {\n            return null;\n        }\n        this.parseToken(_.Token.l_paren, \"expected '(' in location\");\n        const tok = this.getToken();\n        let directLoc = null;\n        if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {\n            directLoc = this.parseLocationAlias();\n        } else {\n            directLoc = this.parseLocationInstance();\n        }\n        this.parseToken(_.Token.r_paren, \"expected ')' in location\");\n        return directLoc;\n    }\n\n    parseXInDimensionList() {\n        // Matches ref impl: if token is 'xf32', reset lexer to after 'x'\n        if (this.getToken().isNot(_.Token.bare_identifier)) {\n            return false;\n        }\n        const token = this.getToken().getSpelling().str();\n        if (!token.startsWith('x')) {\n            return false;\n        }\n        // If we had a prefix of 'x' (e.g., 'xf32'), reset lexer to after the 'x'\n        if (token.length > 1) {\n            this.state.lex.resetPointer(this.getToken().loc.position + 1);\n        }\n        this.state.curToken = this.state.lex.lexToken();\n        return true;\n    }\n\n    parseIntegerInDimensionList() {\n        const spelling = this.getTokenSpelling().str();\n        if (spelling[0] === '0' && spelling.length > 1 && spelling[1] === 'x') {\n            this.state.lex.resetPointer(this.getToken().loc.position + 1);\n            this.state.curToken = this.state.lex.lexToken();\n            return 0n;\n        }\n        const dimension = this.getToken().getUInt64IntegerValue();\n        if (dimension === null) {\n            throw new mlir.Error(`Invalid dimension ${this.location()}`);\n        }\n        this.consumeToken(_.Token.integer);\n        return dimension;\n    }\n\n    parseVectorDimensionList() {\n        const dimensions = [];\n        const scalableDims = [];\n        while (this.getToken().is(_.Token.integer) || this.getToken().is(_.Token.l_square)) {\n            const scalable = this.consumeIf(_.Token.l_square);\n            dimensions.push(this.parseIntegerInDimensionList());\n            if (scalable) {\n                if (!this.consumeIf(_.Token.r_square)) {\n                    throw new mlir.Error(`Missing ']' closing scalable dimension ${this.location()}`);\n                }\n            }\n            scalableDims.push(scalable);\n            if (!this.parseXInDimensionList()) {\n                break;\n            }\n        }\n        return { dimensions, scalableDims };\n    }\n\n    parseDimensionListRanked(allowDynamic = true, withTrailingX = true) {\n        const dimensions = [];\n        const parseDim = () => {\n            if (allowDynamic && this.consumeIf(_.Token.question)) {\n                dimensions.push(_.ShapedType.kDynamic);\n                return true;\n            }\n            if (this.getToken().is(_.Token.integer)) {\n                dimensions.push(this.parseIntegerInDimensionList());\n                return true;\n            }\n            return false;\n        };\n        const hasDimToken = () => this.getToken().isAny(_.Token.integer, _.Token.question);\n        if (withTrailingX) {\n            while (hasDimToken()) {\n                if (!parseDim() || !this.parseXInDimensionList()) {\n                    break;\n                }\n            }\n        } else if (parseDim()) {\n            while (this.getToken().is(_.Token.bare_identifier) && this.getTokenSpelling().str().startsWith('x')) {\n                if (!this.parseXInDimensionList() || !parseDim()) {\n                    break;\n                }\n            }\n        }\n        return { dimensions };\n    }\n\n    parseTensorType() {\n        this.parseToken(_.Token.less, \"Expected '<' in tensor type\");\n        let isUnranked = false;\n        let dimensions = [];\n        if (this.consumeIf(_.Token.star)) {\n            isUnranked = true;\n            this.parseXInDimensionList();\n        } else {\n            const dimInfo = this.parseDimensionListRanked();\n            dimensions = dimInfo.dimensions;\n        }\n        const elementType = this.parseType();\n        let encoding = null;\n        if (this.consumeIf(_.Token.comma)) {\n            encoding = this.parseAttribute();\n        }\n        this.parseToken(_.Token.greater, \"Expected '>' in tensor type\");\n        if (elementType instanceof _.NoneType || elementType instanceof _.FunctionType ||\n            elementType instanceof _.TupleType || elementType instanceof _.RankedTensorType ||\n            elementType instanceof _.UnrankedTensorType || elementType instanceof _.MemRefType ||\n            elementType instanceof _.UnrankedMemRefType) {\n            throw new mlir.Error(`Invalid tensor element type ${this.location()}`);\n        }\n        if (isUnranked) {\n            if (encoding) {\n                throw new mlir.Error(`Cannot apply encoding to unranked tensor ${this.location()}`);\n            }\n            return new _.UnrankedTensorType(elementType);\n        }\n        return new _.RankedTensorType(dimensions, elementType, encoding);\n    }\n\n    parseMemRefType() {\n        this.parseToken(_.Token.less, \"Expected '<' in memref type\");\n        let isUnranked = false;\n        let dimensions = [];\n        if (this.consumeIf(_.Token.star)) {\n            isUnranked = true;\n            this.parseXInDimensionList();\n        } else {\n            const dimInfo = this.parseDimensionListRanked();\n            dimensions = dimInfo.dimensions;\n        }\n        const elementType = this.parseType();\n        if (elementType instanceof _.NoneType || elementType instanceof _.FunctionType ||\n            elementType instanceof _.TupleType || elementType instanceof _.RankedTensorType ||\n            elementType instanceof _.UnrankedTensorType) {\n            throw new mlir.Error(`Invalid memref element type ${this.location()}`);\n        }\n        let layout = null;\n        let memorySpace = null;\n        while (this.consumeIf(_.Token.comma)) {\n            const attr = this.parseAttribute();\n            if (attr instanceof _.MemRefLayoutAttr) {\n                layout = attr;\n                if (isUnranked) {\n                    throw new mlir.Error(`Cannot have affine map for unranked memref type ${this.location()}`);\n                }\n                if (memorySpace) {\n                    throw new mlir.Error(`Expected memory space to be last in memref type ${this.location()}`);\n                }\n            } else {\n                if (memorySpace) {\n                    throw new mlir.Error(`Multiple memory spaces specified in memref type ${this.location()}`);\n                }\n                memorySpace = attr;\n            }\n        }\n        this.parseToken(_.Token.greater, \"Expected '>' in memref type\");\n        if (isUnranked) {\n            return new _.UnrankedMemRefType(elementType, memorySpace);\n        }\n        return new _.MemRefType(dimensions, elementType, layout, memorySpace);\n    }\n\n    parseVectorType() {\n        this.parseToken(_.Token.less, \"Expected '<' in vector type\");\n        const dimInfo = this.parseVectorDimensionList();\n        const elementType = this.parseType();\n        this.parseToken(_.Token.greater, \"Expected '>' in vector type\");\n        return new _.VectorType(dimInfo.dimensions, elementType, dimInfo.scalableDims);\n    }\n\n    parseComplexType() {\n        this.parseToken(_.Token.less, \"Expected '<' in complex type\");\n        const elementType = this.parseType();\n        if (!(elementType instanceof _.FloatType) && !(elementType instanceof _.IntegerType)) {\n            throw new mlir.Error(`Invalid element type for complex ${this.location()}`);\n        }\n        this.parseToken(_.Token.greater, \"Expected '>' in complex type\");\n        return new _.ComplexType(elementType);\n    }\n\n    parseTupleType() {\n        this.parseToken(_.Token.less, \"Expected '<' in tuple type\");\n        if (this.consumeIf(_.Token.greater)) {\n            return new _.TupleType([]);\n        }\n        const types = this.parseCommaSeparatedList('none', () => this.parseType());\n        this.parseToken(_.Token.greater, \"Expected '>' in tuple type\");\n        return new _.TupleType(types);\n    }\n\n    parseType() {\n        if (this.getToken().is(_.Token.l_paren)) {\n            return this.parseFunctionType();\n        }\n        return this.parseNonFunctionType();\n    }\n\n    parseOptionalType() {\n        switch (this.getToken().kind) {\n            case _.Token.l_paren:\n            case _.Token.exclamation_identifier:\n            case _.Token.inttype:\n                return this.parseType();\n            case _.Token.bare_identifier: {\n                switch (this.getToken().getSpelling().str()) {\n                    case 'memref':\n                    case 'tensor':\n                    case 'complex':\n                    case 'tuple':\n                    case 'vector':\n                    case 'f4E2M1FN':\n                    case 'f6E2M3FN':\n                    case 'f6E3M2FN':\n                    case 'f8E5M2':\n                    case 'f8E4M3':\n                    case 'f8E4M3FN':\n                    case 'f8E5M2FNUZ':\n                    case 'f8E4M3FNUZ':\n                    case 'f8E4M3B11FNUZ':\n                    case 'f8E3M4':\n                    case 'f8E8M0FNU':\n                    case 'bf16':\n                    case 'f16':\n                    case 'tf32':\n                    case 'f32':\n                    case 'f64':\n                    case 'f80':\n                    case 'f128':\n                    case 'index':\n                    case 'none':\n                        return this.parseType();\n                    default:\n                        break;\n                }\n                break;\n            }\n            default: {\n                break;\n            }\n        }\n        return null;\n    }\n\n    parseNonFunctionType() {\n        switch (this.getToken().kind) {\n            case _.Token.inttype: {\n                const width = this.getToken().getIntTypeBitwidth();\n                if (width === null) {\n                    throw new mlir.Error(`Invalid integer width ${this.location()}`);\n                }\n                if (width > _.IntegerType.kMaxWidth) {\n                    throw new mlir.Error(`Integer bitwidth is limited to ${_.IntegerType.kMaxWidth} bits ${this.location()}`);\n                }\n                const signedness = this.getToken().getIntTypeSignedness();\n                this.consumeToken(_.Token.inttype);\n                let prefix = 'i';\n                if (signedness === true) {\n                    prefix = 'si';\n                } else if (signedness === false) {\n                    prefix = 'ui';\n                }\n                return new _.IntegerType(`${prefix}${width}`);\n            }\n            case _.Token.exclamation_identifier: {\n                return this.parseExtendedType();\n            }\n            case _.Token.bare_identifier: {\n                const value = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.bare_identifier);\n                switch (value) {\n                    case 'tensor':\n                        return this.parseTensorType();\n                    case 'vector':\n                        return this.parseVectorType();\n                    case 'memref':\n                        return this.parseMemRefType();\n                    case 'complex':\n                        return this.parseComplexType();\n                    case 'tuple':\n                        return this.parseTupleType();\n                    case 'none':\n                        return new _.NoneType();\n                    case 'index':\n                        return new _.IndexType();\n                    case 'bf16':\n                    case 'f16':\n                    case 'f32':\n                    case 'f64':\n                    case 'f80':\n                    case 'f128':\n                    case 'tf32':\n                    case 'f8E5M2':\n                    case 'f8E4M3':\n                    case 'f8E4M3FN':\n                    case 'f8E5M2FNUZ':\n                    case 'f8E4M3FNUZ':\n                    case 'f8E4M3B11FNUZ':\n                    case 'f8E3M4':\n                    case 'f8E8M0FNU':\n                    case 'f4E2M1FN':\n                    case 'f6E2M3FN':\n                    case 'f6E3M2FN':\n                        return new _.FloatType(value);\n                    default:\n                        throw new mlir.Error(`Invalid type '${value}' ${this.location()}`);\n                }\n            }\n            default: {\n                break;\n            }\n        }\n        throw new mlir.Error(`Invalid type '${this.getTokenSpelling().str()}' ${this.location()}`);\n    }\n\n    parseExtendedType() {\n        return this.parseExtendedSymbol(this.state.asmState, this.state.typeAliasDefinitions, (dialectName, symbolData) => {\n            const dialect = this.context.getOrLoadDialect(dialectName);\n            if (dialect) {\n                const curLexerPos = this.getToken().loc.position;\n                this.resetToken(symbolData.data());\n                const customParser = new _.CustomDialectAsmParser(symbolData, this);\n                const type = dialect.parseType(customParser, dialectName);\n                this.resetToken(curLexerPos);\n                return type;\n            }\n            return new _.OpaqueType(dialectName, symbolData);\n        });\n    }\n\n    parseExtendedSymbol(asmState, aliases, createSymbol) {\n        const tok = this.getToken();\n        const startPos = tok.loc.position;\n        const tokSpelling = tok.getSpelling().str();\n        const isType = tokSpelling.startsWith('!');\n        const identifier = tok.getSpelling().drop_front();\n        this.consumeToken();\n        const dotIndex = identifier.indexOf('.');\n        let dialectName = identifier;\n        let symbolData = '';\n        if (dotIndex !== -1) {\n            dialectName = identifier.substring(0, dotIndex);\n            symbolData = identifier.substring(dotIndex + 1);\n        }\n        const isPrettyName = symbolData.length > 0 || identifier.endsWith('.');\n        const hasTrailingData = this.getToken().is(_.Token.less) && (startPos + tokSpelling.length) === this.getToken().loc.position;\n        if (!hasTrailingData && !isPrettyName) {\n            if (!aliases.has(tokSpelling)) {\n                throw new mlir.Error(`Undefined symbol alias '${identifier}' ${this.location()}`);\n            }\n            if (asmState) {\n                if (isType) {\n                    asmState.addTypeAliasUses(identifier);\n                } else {\n                    asmState.addAttrAliasUses(identifier);\n                }\n            }\n            return aliases.get(tokSpelling);\n        }\n        if (hasTrailingData) {\n            if (this.getToken().is(_.Token.less)) {\n                symbolData += this.parseDialectSymbolBody();\n            }\n            if (!isPrettyName) {\n                symbolData = symbolData.slice(1, -1);\n            }\n        }\n        const posOffset = dotIndex === -1 ? dialectName.length : dotIndex;\n        symbolData = new _.StringRef(symbolData, startPos + 1 + posOffset + 1);\n        return createSymbol(dialectName, symbolData);\n    }\n\n    parseFunctionType() {\n        const inputs = this.parseTypeListParens();\n        this.parseToken(_.Token.arrow, \"Expected '->' in function type\");\n        const results = this.parseFunctionResultTypes();\n        return new _.FunctionType(inputs, results);\n    }\n\n    parseFunctionResultTypes() {\n        if (this.getToken().is(_.Token.l_paren)) {\n            return this.parseTypeListParens();\n        }\n        const type = this.parseNonFunctionType();\n        if (type) {\n            return [type];\n        }\n        return [];\n    }\n\n    parseCommaSeparatedList(delimiter, parseElement) {\n        const results = [];\n        const delimiters = {\n            none: [null, null],\n            paren: [_.Token.l_paren, _.Token.r_paren],\n            square: [_.Token.l_square, _.Token.r_square],\n            angle: [_.Token.less, _.Token.greater],\n            brace: [_.Token.l_brace, _.Token.r_brace],\n            optionalParen: [_.Token.l_paren, _.Token.r_paren],\n            optionalSquare: [_.Token.l_square, _.Token.r_square],\n            optionalAngle: [_.Token.less, _.Token.greater],\n            optionalBrace: [_.Token.l_brace, _.Token.r_brace]\n        };\n        const [open, close] = delimiters[delimiter] || [null, null];\n        const isOptional = delimiter && delimiter.startsWith('optional');\n        if (open) {\n            if (isOptional) {\n                if (!this.consumeIf(open)) {\n                    return results;\n                }\n            } else {\n                this.parseToken(open, `Expected '${open}'`);\n            }\n            if (close && this.consumeIf(close)) {\n                return results;\n            }\n        }\n        const first = parseElement();\n        if (first !== null && first !== undefined) {\n            results.push(first);\n        }\n        while (this.consumeIf(_.Token.comma)) {\n            const elem = parseElement();\n            if (elem !== null && elem !== undefined) {\n                results.push(elem);\n            }\n        }\n        if (close) {\n            this.parseToken(close, `Expected '${close}'`);\n        }\n        return results;\n    }\n\n    parseFloatAttr(type = null, isNegative = false) {\n        const val = this.getToken().getFloatingPointValue();\n        if (val === null) {\n            throw new mlir.Error(`Floating point value too large for attribute ${this.location()}`);\n        }\n        this.consumeToken(_.Token.floatliteral);\n        if (!type) {\n            if (this.consumeIf(_.Token.colon)) {\n                type = this.parseType();\n            } else {\n                type = new _.FloatType('f64');\n            }\n        }\n        if (type instanceof _.FloatType === false) {\n            throw new mlir.Error(`Floating point value not valid for specified type ${this.location()}`);\n        }\n        return new _.FloatAttr(type, isNegative ? -val : val);\n    }\n\n    parseDecOrHexAttr(type = null, isNegative = false) {\n        const tok = this.getToken();\n        const spelling = tok.getSpelling().str();\n        this.consumeToken(_.Token.integer);\n        if (!type) {\n            if (this.consumeIf(_.Token.colon)) {\n                type = this.parseType();\n            } else {\n                type = new _.IntegerType('i64');\n            }\n        }\n        if (type instanceof _.FloatType) {\n            return new _.FloatAttr(type, isNegative ? -spelling : spelling);\n        }\n        if (!(type instanceof _.IntegerType) && !(type instanceof _.IndexType)) {\n            throw new mlir.Error(`Integer literal not valid for specified type ${this.location()}`);\n        }\n        if (isNegative && type instanceof _.IntegerType && type.name.startsWith('ui')) {\n            throw new mlir.Error(`Negative integer literal not valid for unsigned integer type ${this.location()}`);\n        }\n        const val = tok.spelling.getAsInteger(spelling.length > 1 && spelling[1] === 'x' ? 0 : 10);\n        if (val === null) {\n            throw new mlir.Error(`Integer constant out of range for attribute ${this.location()}`);\n        }\n        return new _.IntegerAttr(type, isNegative ? -val : val);\n    }\n\n    parseAttribute(type = null) {\n        switch (this.getToken().kind) {\n            case _.Token.kw_affine_map: {\n                this.consumeToken(_.Token.kw_affine_map);\n                this.parseToken(_.Token.less, \"Expected '<' in affine map\");\n                const map = this.parseAffineMapReference();\n                this.parseToken(_.Token.greater, \"Expected '>' in affine map\");\n                return new _.AffineMapAttr(map);\n            }\n            case _.Token.kw_affine_set: {\n                this.consumeToken(_.Token.kw_affine_set);\n                this.parseToken(_.Token.less, \"Expected '<' in integer set\");\n                const set = this.parseIntegerSetReference();\n                this.parseToken(_.Token.greater, \"Expected '>' in integer set\");\n                return new _.IntegerSetAttr(set);\n            }\n            case _.Token.l_square: {\n                this.consumeToken(_.Token.l_square);\n                const elements = [];\n                this.parseCommaSeparatedListUntil(_.Token.r_square, () => {\n                    elements.push(this.parseAttribute());\n                });\n                return new _.ArrayAttr(elements);\n            }\n            case _.Token.kw_false:\n                this.consumeToken(_.Token.kw_false);\n                return new _.BoolAttr(false);\n            case _.Token.kw_true:\n                this.consumeToken(_.Token.kw_true);\n                return new _.BoolAttr(true);\n            case _.Token.kw_dense:\n                return this.parseDenseElementsAttr(type);\n            case _.Token.kw_dense_resource:\n                return this.parseDenseResourceElementsAttr(type);\n            case _.Token.kw_array:\n                return this.parseDenseArrayAttr(type);\n            case _.Token.l_brace: {\n                const attributes = new Map();\n                this.parseAttributeDict(attributes);\n                return new _.DictionaryAttr(attributes);\n            }\n            case _.Token.hash_identifier:\n                return this.parseExtendedAttr(type);\n            case _.Token.floatliteral:\n                return this.parseFloatAttr(type, false);\n            case _.Token.integer:\n                return this.parseDecOrHexAttr(type, false);\n            case _.Token.minus: {\n                this.consumeToken(_.Token.minus);\n                if (this.getToken().is(_.Token.integer)) {\n                    return this.parseDecOrHexAttr(type, true);\n                }\n                if (this.getToken().is(_.Token.floatliteral)) {\n                    return this.parseFloatAttr(type, true);\n                }\n                throw new mlir.Error(`Expected constant integer or floating point value ${this.location()}`);\n            }\n            case _.Token.kw_loc:\n                return this.parseOptionalLocationSpecifier();\n            case _.Token.kw_sparse:\n                return this.parseSparseElementsAttr(type);\n            case _.Token.kw_strided:\n                return this.parseStridedLayoutAttr();\n            case _.Token.kw_distinct:\n                return this.parseDistinctAttr(type);\n            case _.Token.string: {\n                const value = this.getToken().getStringValue();\n                this.consumeToken(_.Token.string);\n                if (!type && this.consumeIf(_.Token.colon)) {\n                    type = this.parseType();\n                }\n                return new _.StringAttr(value, type);\n            }\n            case _.Token.at_identifier: {\n                const nameStr = this.getToken().getSymbolReference();\n                this.consumeToken(_.Token.at_identifier);\n                const nestedRefs = [];\n                while (this.getToken().is(_.Token.colon)) {\n                    const curPointer = this.getToken().loc.position;\n                    this.consumeToken(_.Token.colon);\n                    if (!this.consumeIf(_.Token.colon)) {\n                        this.resetToken(curPointer);\n                        break;\n                    }\n                    if (this.getToken().isNot(_.Token.at_identifier)) {\n                        throw new mlir.Error(`Expected nested symbol reference identifier ${this.location()}`);\n                    }\n                    nestedRefs.push(this.getToken().getSymbolReference());\n                    this.consumeToken(_.Token.at_identifier);\n                }\n                return new _.SymbolRefAttr(nameStr, nestedRefs);\n            }\n            case _.Token.kw_unit:\n                this.consumeToken(_.Token.kw_unit);\n                return new _.UnitAttr();\n            case _.Token.bare_identifier: {\n                const tokenValue = this.getTokenSpelling().str();\n                if (tokenValue === 'tensor' || tokenValue === 'vector' || tokenValue === 'memref' ||\n                    tokenValue === 'none' || tokenValue === 'index' || /^[su]?i[0-9]+$/.test(tokenValue) ||\n                    /^f[0-9]+$/.test(tokenValue) || tokenValue === 'bf16' || tokenValue === 'tf32' ||\n                    /^f\\d+E\\d+M\\d+/.test(tokenValue) || tokenValue === 'complex' || tokenValue === 'tuple') {\n                    const parsedType = this.parseType();\n                    return { value: parsedType, type: new _.PrimitiveType('type') };\n                }\n                if (tokenValue === 'DEFAULT') {\n                    this.consumeToken(_.Token.bare_identifier);\n                    return { value: tokenValue };\n                }\n                this.consumeToken(_.Token.bare_identifier);\n                return { value: tokenValue };\n            }\n            case _.Token.exclamation_identifier: {\n                const parsedType = this.parseType();\n                return { value: parsedType, type: new _.PrimitiveType('type') };\n            }\n            case _.Token.percent_identifier: {\n                const value = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.percent_identifier);\n                return { value };\n            }\n            case _.Token.less: {\n                const value = this.parseDialectSymbolBody();\n                return { value };\n            }\n            default: {\n                const parsedType = this.parseOptionalType();\n                if (parsedType) {\n                    return new _.TypeAttrOf(parsedType);\n                }\n                throw new mlir.Error(`Unexpected attribute token '${this.getTokenSpelling().str()}' ${this.location()}`);\n            }\n        }\n    }\n\n    parseExtendedAttr(type = null) {\n        const attr = this.parseExtendedSymbol(this.state.asmState, this.state.attributeAliasDefinitions, (dialectName, symbolData) => {\n            let attrType = type;\n            if (this.consumeIf(_.Token.colon)) {\n                attrType = this.parseType();\n                if (!attrType) {\n                    return new _.Attribute();\n                }\n            }\n            const dialect = this.context.getOrLoadDialect(dialectName);\n            if (dialect) {\n                const curLexerPos = this.getToken().loc.position;\n                this.resetToken(symbolData.data());\n                const customParser = new _.CustomDialectAsmParser(symbolData, this);\n                const attr = dialect.parseAttribute(customParser, attrType);\n                this.resetToken(curLexerPos);\n                if (attr) {\n                    return attr;\n                }\n            }\n            return new _.OpaqueAttr(`#${dialectName}`, symbolData, attrType);\n        });\n        return attr;\n    }\n\n    parseResourceHandle(dialect) {\n        const name = this.parseOptionalKeywordOrString();\n        if (!name) {\n            throw new mlir.Error(`Expected identifier key for 'resource' entry ${this.location()}`);\n        }\n        const resources = this.state.dialectResources;\n        if (!resources.has(dialect)) {\n            resources.set(dialect, new Map());\n        }\n        const dialectEntries = resources.get(dialect);\n        if (!dialectEntries.has(name)) {\n            const handle = dialect.declareResource(name);\n            const key = dialect.getResourceKey(handle);\n            dialectEntries.set(name, { key, handle });\n        }\n        const entry = dialectEntries.get(name);\n        return entry.handle;\n    }\n\n    parseDenseElementsAttr(attrType) {\n        this.consumeToken(_.Token.kw_dense);\n        this.parseToken(_.Token.less, \"Expected '<' after 'dense'\");\n        // Type-first syntax: dense<TYPE : [ATTR, ...]>\n        // Reference: AttributeParser.cpp parseDenseElementsAttrTyped()\n        if (!this.getToken().is(_.Token.l_paren)) {\n            const type = this.parseDenseElementsAttrTyped();\n            if (type) {\n                return type;\n            }\n        }\n        // Literal-first syntax: dense<[values]> : type\n        let literalParser = null;\n        if (!this.consumeIf(_.Token.greater)) {\n            literalParser = new _.TensorLiteralParser(this);\n            literalParser.parse(/* allowHex */ true);\n            this.parseToken(_.Token.greater, \"Expected '>'\");\n        }\n        const type = this.parseElementsLiteralType(attrType);\n        const value = literalParser ? literalParser.getAttr(type) : null;\n        return new _.DenseElementsAttr(value, type);\n    }\n\n    parseDenseElementsAttrTyped() {\n        const type = this.parseOptionalType();\n        if (!type) {\n            return null;\n        }\n        if (!this.consumeIf(_.Token.colon)) {\n            throw new mlir.Error(`Expected ':' after type in dense attribute ${this.location()}`);\n        }\n        if (!(type instanceof _.RankedTensorType) && !(type instanceof _.VectorType)) {\n            throw new mlir.Error(`Expected a shaped type for dense elements ${this.location()}`);\n        }\n        const values = [];\n        const parseElement = () => {\n            values.push(this.parseAttribute());\n        };\n        if (this.getToken().is(_.Token.l_square)) {\n            const parseElements = (shape) => {\n                if (shape.length <= 1) {\n                    this.parseCommaSeparatedList('square', parseElement);\n                } else {\n                    this.parseCommaSeparatedList('square', () => parseElements(shape.slice(1)));\n                }\n            };\n            parseElements(type.shape || []);\n        } else {\n            parseElement();\n        }\n        this.parseToken(_.Token.greater, \"Expected '>' to close dense attribute\");\n        const extractedValues = values.map((v) => {\n            if (v instanceof _.IntegerAttr) {\n                return typeof v.value === 'bigint' ? v.value : Number(v.value);\n            }\n            if (v instanceof _.FloatAttr) {\n                return parseFloat(v.value);\n            }\n            return v;\n        });\n        return new _.DenseElementsAttr(extractedValues, type);\n    }\n\n    parseDenseResourceElementsAttr(attrType) {\n        this.consumeToken(_.Token.kw_dense_resource);\n        this.parseToken(_.Token.less, \"Expected '<' after 'dense_resource'\");\n        const rawHandle = this.parseResourceHandle(this.context.getOrLoadDialect('builtin'));\n        this.parseToken(_.Token.greater, \"Expected '>'\");\n        let type = attrType;\n        if (!type) {\n            this.parseToken(_.Token.colon, \"Expected ':'\");\n            type = this.parseType();\n        }\n        return new _.DenseResourceElementsAttr(type, rawHandle);\n    }\n\n    parseDenseArrayAttr(/* attrType */) {\n        this.consumeToken(_.Token.kw_array);\n        this.parseToken(_.Token.less, \"Expected '<' after 'array'\");\n        const arrayType = this.parseType();\n        if (!(arrayType instanceof _.IntegerType) && !(arrayType instanceof _.FloatType)) {\n            throw new mlir.Error(`Expected integer or float type, got '${arrayType}' ${this.location()}`);\n        }\n        if (this.consumeIf(_.Token.greater)) {\n            return new _.DenseArrayAttr(arrayType, 0, []);\n        }\n        this.parseToken(_.Token.colon, \"Expected ':' after dense array type\");\n        const arrayValues = [];\n        while (this.getToken().isNot(_.Token.greater)) {\n            const val = this.parseAttribute();\n            arrayValues.push(val && val.value !== undefined ? val.value : val);\n            this.consumeIf(_.Token.comma);\n        }\n        this.parseToken(_.Token.greater, \"Expected '>' to close an array attribute\");\n        return new _.DenseArrayAttr(arrayType, arrayValues.length, arrayValues);\n    }\n\n    parseSparseElementsAttr(attrType) {\n        this.consumeToken(_.Token.kw_sparse);\n        this.parseToken(_.Token.less, \"Expected '<' after 'sparse'\");\n        let indices = null;\n        let values = null;\n        if (!this.consumeIf(_.Token.greater)) {\n            const indiceParser = new _.TensorLiteralParser(this);\n            indiceParser.parse(/* allowHex */ false);\n            indices = indiceParser._storage.map((elem) => {\n                const val = elem.isNegative ? -elem.value : elem.value;\n                return typeof val === 'string' ? parseInt(val, 10) : val;\n            });\n            this.parseToken(_.Token.comma, \"Expected ','\");\n            const valuesParser = new _.TensorLiteralParser(this);\n            valuesParser.parse(/* allowHex */ true);\n            if (valuesParser._hexStorage) {\n                values = valuesParser._hexStorage;\n            } else {\n                values = valuesParser._storage.map((elem) => {\n                    if (elem.kind === 'float') {\n                        const val = parseFloat(elem.value);\n                        return elem.isNegative ? -val : val;\n                    }\n                    const val = elem.isNegative ? -elem.value : elem.value;\n                    return typeof val === 'string' ? parseFloat(val) : val;\n                });\n            }\n            this.parseToken(_.Token.greater, \"Expected '>'\");\n        }\n        const type = this.parseElementsLiteralType(attrType);\n        return new _.SparseElementsAttr(type, indices, values);\n    }\n\n    parseStridedLayoutAttr() {\n        this.consumeToken(_.Token.kw_strided);\n        this.parseToken(_.Token.less, \"Expected '<' after 'strided'\");\n        this.parseToken(_.Token.l_square, \"Expected '['\");\n        // Parse dimension list: integer or '?' separated by commas\n        const strides = [];\n        while (this.getToken().isNot(_.Token.r_square)) {\n            const value = this.parseOptionalInteger();\n            if (value !== null) {\n                strides.push(value);\n            } else if (this.consumeIf(_.Token.question)) {\n                strides.push('?');\n            } else {\n                throw new mlir.Error(`Expected a 64-bit signed integer or '?' in strided layout ${this.location()}`);\n            }\n            if (this.getToken().isNot(_.Token.r_square)) {\n                this.consumeIf(_.Token.comma);\n            }\n        }\n        this.parseToken(_.Token.r_square, \"Expected ']'\");\n        let offset = null;\n        if (this.consumeIf(_.Token.comma)) {\n            this.parseToken(_.Token.kw_offset, \"Expected 'offset' after comma\");\n            this.parseToken(_.Token.colon, \"Expected ':' after 'offset'\");\n            offset = this.parseOptionalInteger();\n            if (offset === null) {\n                if (this.consumeIf(_.Token.question)) {\n                    offset = '?';\n                } else {\n                    throw new mlir.Error(`Expected a 64-bit signed integer or '?' for offset in strided layout ${this.location()}`);\n                }\n            }\n        }\n        this.parseToken(_.Token.greater, \"Expected '>'\");\n        return new _.StridedLayoutAttr(offset, strides);\n    }\n\n    // Parse an affine map reference using AffineParser\n    // Following reference: Parser::parseAffineMapReference\n    parseAffineMapReference() {\n        const affineParser = new _.AffineParser(this.state);\n        const result = affineParser.parseAffineMapOrIntegerSetInline();\n        if (result.set) {\n            throw new mlir.Error(`Expected AffineMap, but got IntegerSet ${this.location()}`);\n        }\n        return result.map;\n    }\n\n    // Parse an integer set reference using AffineParser\n    // Following reference: Parser::parseIntegerSetReference\n    parseIntegerSetReference() {\n        const affineParser = new _.AffineParser(this.state);\n        const result = affineParser.parseAffineMapOrIntegerSetInline();\n        if (result.map) {\n            throw new mlir.Error(`Expected IntegerSet, but got AffineMap ${this.location()}`);\n        }\n        return result.set;\n    }\n\n    // Parse an AffineMap where dims/symbols are SSA ids\n    // Following reference: Parser::parseAffineMapOfSSAIds\n    parseAffineMapOfSSAIds(parseElement, delimiter = 'Paren') {\n        const affineParser = new _.AffineParser(this.state, true, parseElement);\n        return affineParser.parseAffineMapOfSSAIds(delimiter);\n    }\n\n    // Parse an AffineExpr where dims/symbols are SSA ids\n    // Following reference: Parser::parseAffineExprOfSSAIds\n    parseAffineExprOfSSAIds(parseElement) {\n        const affineParser = new _.AffineParser(this.state, true, parseElement);\n        return affineParser.parseAffineExprOfSSAIds();\n    }\n\n    parseDistinctAttr(type) {\n        this.consumeToken(_.Token.kw_distinct);\n        this.parseToken(_.Token.l_square, \"Expected '[' after 'distinct'\");\n        if (this.getToken().isNot(_.Token.integer)) {\n            throw new mlir.Error(`Expected distinct ID ${this.location()}`);\n        }\n        const token = this.getToken();\n        const id = token.getUInt64IntegerValue();\n        if (id === null) {\n            throw new mlir.Error(`Expected an unsigned 64-bit integer ${this.location()}`);\n        }\n        this.consumeToken(_.Token.integer);\n        this.parseToken(_.Token.r_square, \"Expected ']' to close distinct ID\");\n        this.parseToken(_.Token.less, \"Expected '<' after distinct ID\");\n        let referencedAttr = null;\n        if (this.consumeIf(_.Token.greater)) {\n            referencedAttr = new _.UnitAttr();\n        } else {\n            referencedAttr = this.parseAttribute(type);\n            this.parseToken(_.Token.greater, \"Expected '>' to close distinct attribute\");\n        }\n        return { value: `distinct[${id.toString()}]`, referencedAttr, type: 'distinct' };\n    }\n\n    parseElementsLiteralType(type) {\n        if (!type) {\n            this.parseToken(_.Token.colon, \"Expected ':'\");\n            return this.parseType();\n        }\n        // Type is a concrete type object - use it directly\n        return type;\n    }\n\n    parseOptionalAttribute(type) {\n        switch (this.getToken().kind) {\n            case _.Token.at_identifier:\n            case _.Token.floatliteral:\n            case _.Token.integer:\n            case _.Token.hash_identifier:\n            case _.Token.kw_affine_map:\n            case _.Token.kw_affine_set:\n            case _.Token.kw_dense:\n            case _.Token.kw_dense_resource:\n            case _.Token.kw_false:\n            case _.Token.kw_loc:\n            case _.Token.kw_sparse:\n            case _.Token.kw_true:\n            case _.Token.kw_unit:\n            case _.Token.l_brace:\n            case _.Token.l_square:\n            case _.Token.less:\n            case _.Token.minus:\n            case _.Token.string:\n                return this.parseAttribute(type);\n            default: {\n                const value = this.parseOptionalType(type);\n                if (value) {\n                    return { value, type: 'type' };\n                }\n                return null;\n            }\n        }\n    }\n\n    parseOptionalInteger(type) {\n        // Parse `false` and `true` keywords as 0 and 1 respectively.\n        if (this.consumeIf(_.Token.kw_false)) {\n            return type === 'int64' ? 0n : 0;\n        }\n        if (this.consumeIf(_.Token.kw_true)) {\n            return type === 'int64' ? 1n : 1;\n        }\n        if (this.getToken().isNot(_.Token.integer) && this.getToken().isNot(_.Token.minus)) {\n            return null;\n        }\n        const negative = this.consumeIf(_.Token.minus);\n        const curTok = this.getToken();\n        this.parseToken(_.Token.integer, 'Expected integer value');\n        if (type === 'int64') {\n            const str = curTok.spelling.str();\n            const result = BigInt(str);\n            return negative ? -result : result;\n        }\n        const spelling = curTok.spelling;\n        const isHex = spelling.length > 1 && spelling[1] === 'x';\n        const result = spelling.getAsInteger(isHex ? 0 : 10);\n        if (result === null) {\n            throw new mlir.Error(`Integer value too large ${this.location()}`);\n        }\n        return negative ? -result : result;\n    }\n\n    parseInteger(type) {\n        const result = this.parseOptionalInteger(type);\n        if (result === null) {\n            throw new mlir.Error(`Expected integer value ${this.location()}`);\n        }\n        return result;\n    }\n\n    parseOptionalDecimalInteger() {\n        if (this.getToken().isNot(_.Token.integer) && this.getToken().isNot(_.Token.minus)) {\n            return null;\n        }\n        const negative = this.consumeIf(_.Token.minus);\n        const curTok = this.getToken();\n        this.parseToken(_.Token.integer, 'Expected integer value');\n        const spelling = curTok.spelling.str();\n        if (spelling[0] === '0' && spelling.length > 1 && spelling[1] === 'x') {\n            this.state.lex.resetPointer(curTok.loc.position + 1);\n            this.state.curToken = this.state.lex.lexToken();\n            return 0;\n        }\n        const result = curTok.spelling.getAsInteger(10);\n        if (result === null) {\n            throw new mlir.Error(`Integer value too large ${this.location()}`);\n        }\n        return negative ? -result : result;\n    }\n\n    parseDecimalInteger() {\n        const result = this.parseOptionalDecimalInteger();\n        if (result === null) {\n            throw new mlir.Error(`Expected decimal integer value ${this.location()}`);\n        }\n        return result;\n    }\n\n    parseOptionalVerticalBar() {\n        return this.consumeIf(_.Token.vertical_bar);\n    }\n\n    parseOptionalString() {\n        if (!this.getToken().is(_.Token.string)) {\n            return null;\n        }\n        const string = this.getToken().getStringValue();\n        this.consumeToken();\n        return string;\n    }\n\n    parseDialectSymbolBody() {\n        const closingFor = { '<': '>', '[': ']', '(': ')', '{': '}' };\n        const openingFor = { '>': '<', ']': '[', ')': '(', '}': '{' };\n        const delimiters = new Set(['<', '>', '[', ']', '(', ')', '{', '}', ',', ':', '=']);\n        this.parseToken(_.Token.less, \"expected '<'\");\n        const stack = ['<'];\n        let value = '<';\n        let prevToken = '<';\n        while (stack.length > 0) {\n            if (this.getToken().is(_.Token.eof)) {\n                throw new mlir.Error(`Unbalanced '<' ${this.location()}`);\n            }\n            const token = this.getToken().getSpelling().str();\n            if (closingFor[token]) {\n                stack.push(token);\n            } else if (openingFor[token]) {\n                if (stack[stack.length - 1] === openingFor[token]) {\n                    stack.pop();\n                } else if (token !== '>') {\n                    throw new mlir.Error(`Unbalanced '${stack[stack.length - 1]}' ${this.location()}`);\n                }\n            }\n            const curToken = this.getToken().getSpelling().str();\n            this.consumeToken();\n            if (!delimiters.has(prevToken) && !delimiters.has(curToken)) {\n                value += ' ';\n            }\n            value += curToken;\n            prevToken = curToken;\n        }\n        return value;\n    }\n\n    getToken() {\n        return this.state.curToken;\n    }\n\n    getTokenSpelling() {\n        return this.state.curToken.spelling;\n    }\n\n    resetToken(tokPos) {\n        this.state.lex.resetPointer(tokPos);\n        this.state.curToken = this.state.lex.lexToken();\n    }\n\n    consumeToken(kind) {\n        if (kind !== undefined && this.state.curToken.kind !== kind) {\n            throw new mlir.Error(`consumeToken: Expected '${kind}' ${this.location()}`);\n        }\n        this.state.curToken = this.state.lex.lexToken();\n    }\n\n    parseToken(kind, message) {\n        if (this.consumeIf(kind)) {\n            return;\n        }\n        throw new mlir.Error(`${message || `Expected '${kind}'`} ${this.location()}`);\n    }\n\n    consumeIf(kind) {\n        if (this.state.curToken.isNot(kind)) {\n            return false;\n        }\n        this.consumeToken(kind);\n        return true;\n    }\n\n    location() {\n        return this.getToken().loc.toString();\n    }\n\n    static parseSymbol(inputStr, context, parserFn) {\n        const decoder = text.Decoder.open(inputStr);\n        const config = new _.ParserConfig(context);\n        const state = new _.ParserState(decoder, config);\n        const parser = new _.Parser(state, context);\n        const startPos = state.curToken.position || 0;\n        const symbol = parserFn(parser);\n        if (!symbol) {\n            return { symbol: null, numRead: 0 };\n        }\n        const endPos = parser.getToken().loc.position;\n        const numRead = endPos - startPos;\n        return { symbol, numRead };\n    }\n\n    static parseAttribute(attrStr, context, type = null) {\n        const result = _.Parser.parseSymbol(attrStr, context, (parser) => {\n            return parser.parseAttribute(type);\n        });\n        if (!result.symbol) {\n            return { attribute: null, numRead: 0 };\n        }\n        return { attribute: result.symbol, numRead: result.numRead };\n    }\n\n    static parseType(typeStr, context) {\n        const result = _.Parser.parseSymbol(typeStr, context, (parser) => {\n            return parser.parseType();\n        });\n        if (!result.symbol) {\n            return { type: null, numRead: 0 };\n        }\n        return { type: result.symbol, numRead: result.numRead };\n    }\n};\n\n_.TopLevelOperationParser = class extends _.Parser {\n\n    parse(block) {\n        const opParser = new _.OperationParser(this.state);\n        while (true) {\n            switch (this.getToken().kind) {\n                case _.Token.eof: {\n                    opParser.finalize(block);\n                    return block;\n                }\n                case _.Token.hash_identifier: {\n                    this.parseAttributeAliasDef();\n                    break;\n                }\n                case _.Token.exclamation_identifier: {\n                    this.parseTypeAliasDef();\n                    break;\n                }\n                case _.Token.file_metadata_begin: {\n                    this.parseFileMetadataDictionary();\n                    break;\n                }\n                default: {\n                    const op = opParser.parseOperation();\n                    block.operations.push(op);\n                }\n            }\n        }\n    }\n\n    parseAttributeAliasDef() {\n        const aliasName = this.getToken().getSpelling().str();\n        this.consumeToken(_.Token.hash_identifier);\n        this.parseToken(_.Token.equal, \"Expected '=' in attribute alias definition\");\n        let attr = null;\n        if (this.getToken().is(_.Token.l_paren)) {\n            const map = this.parseAffineMapReference();\n            attr = new _.AffineMapAttr(map);\n        } else {\n            attr = this.parseAttribute();\n        }\n        this.state.attributeAliasDefinitions.set(aliasName, attr);\n    }\n\n    parseTypeAliasDef() {\n        const aliasName = this.getTokenSpelling().str();\n        this.consumeToken(_.Token.exclamation_identifier);\n        this.parseToken(_.Token.equal, \"Expected '=' in type alias definition\");\n        // Legacy MLIR syntax: !alias = type <actual-type>\n        if (this.getToken().is(_.Token.bare_identifier) && this.getTokenSpelling().str() === 'type') {\n            this.consumeToken(_.Token.bare_identifier);\n        }\n        const type = this.parseType();\n        this.state.typeAliasDefinitions.set(aliasName, type);\n    }\n\n    parseFileMetadataDictionary() {\n        this.consumeToken(_.Token.file_metadata_begin);\n        this.parseCommaSeparatedListUntil(_.Token.file_metadata_end, () => {\n            const keyLoc = this.getToken().loc;\n            const key = this.parseOptionalKeyword();\n            if (!key) {\n                throw new mlir.Error(`Expected identifier key in file metadata dictionary ${this.location()}`);\n            }\n            this.parseToken(_.Token.colon, \"Expected ':'\");\n            if (key === 'dialect_resources') {\n                this.parseDialectResourceFileMetadata();\n            } else if (key === 'external_resources') {\n                this.parseExternalResourceFileMetadata();\n            } else {\n                throw new mlir.Error(`Unknown key '${key}' in file metadata dictionary ${keyLoc.toString()}`);\n            }\n        });\n    }\n};\n\n// Specialized parser for affine structures (affine maps, affine expressions, integer sets)\n// Following the reference implementation in AffineParser.cpp\n_.AffineParser = class extends _.Parser {\n\n    constructor(state, allowParsingSSAIds = false, parseElement = null) {\n        super(state);\n        this.allowParsingSSAIds = allowParsingSSAIds;\n        this.parseElement = parseElement;\n        this.dimsAndSymbols = []; // Array of {name, expr} pairs\n        this.numDimOperands = 0;\n        this.numSymbolOperands = 0;\n    }\n\n    // Parse an ambiguous affine map or integer set inline\n    // affine-map-or-integer-set ::= dim-and-symbol-id-lists (`->` | `:`) ...\n    parseAffineMapOrIntegerSetInline() {\n        const { numDims, numSymbols } = this.parseDimAndOptionalSymbolIdList();\n        if (this.consumeIf(_.Token.arrow)) {\n            return { map: this.parseAffineMapRange(numDims, numSymbols), set: null };\n        }\n        if (!this.consumeIf(_.Token.colon)) {\n            throw new mlir.Error(`Expected '->' or ':' ${this.location()}`);\n        }\n        return { map: null, set: this.parseIntegerSetConstraints(numDims, numSymbols) };\n    }\n\n    // Parse dimension and optional symbol identifier lists: (d0, d1, ...)[s0, s1, ...]\n    parseDimAndOptionalSymbolIdList() {\n        const numDims = this.parseDimIdList();\n        let numSymbols = 0;\n        if (this.getToken().is(_.Token.l_square)) {\n            numSymbols = this.parseSymbolIdList();\n        }\n        return { numDims, numSymbols };\n    }\n\n    // Parse dimension identifier list: (d0, d1, ...)\n    parseDimIdList() {\n        let numDims = 0;\n        this.parseToken(_.Token.l_paren, \"Expected '(' in dimensional identifier list\");\n        if (this.getToken().isNot(_.Token.r_paren)) {\n            do {\n                const dimExpr = this.getAffineDimExpr(numDims);\n                this.parseIdentifierDefinition(dimExpr);\n                numDims++;\n            } while (this.consumeIf(_.Token.comma));\n        }\n        this.parseToken(_.Token.r_paren, \"Expected ')' in dimensional identifier list\");\n        return numDims;\n    }\n\n    // Parse symbol identifier list: [s0, s1, ...]\n    parseSymbolIdList() {\n        let numSymbols = 0;\n        this.parseToken(_.Token.l_square, \"Expected '[' in symbol list\");\n        if (this.getToken().isNot(_.Token.r_square)) {\n            do {\n                const symbolExpr = this.getAffineSymbolExpr(numSymbols);\n                this.parseIdentifierDefinition(symbolExpr);\n                numSymbols++;\n            } while (this.consumeIf(_.Token.comma));\n        }\n        this.parseToken(_.Token.r_square, \"Expected ']' in symbol list\");\n        return numSymbols;\n    }\n\n    parseIdentifierDefinition(idExpr) {\n        let name = null;\n        if (this.getToken().is(_.Token.bare_identifier)) {\n            name = this.getTokenSpelling().str();\n            this.consumeToken(_.Token.bare_identifier);\n        } else if (this.getToken().is(_.Token.inttype)) {\n            name = this.getTokenSpelling().str();\n            this.consumeToken(_.Token.inttype);\n        } else if (this.getToken().isKeyword()) {\n            name = this.getToken().getSpelling().str();\n            this.consumeToken();\n        } else {\n            throw new mlir.Error(`Expected bare identifier ${this.location()}`);\n        }\n        for (const entry of this.dimsAndSymbols) {\n            if (entry.name === name) {\n                throw new mlir.Error(`Redefinition of identifier '${name}' ${this.location()}`);\n            }\n        }\n        this.dimsAndSymbols.push({ name, expr: idExpr });\n    }\n\n    parseAffineMapRange(numDims, numSymbols) {\n        const exprs = [];\n        this.parseToken(_.Token.l_paren, \"Expected '('\");\n        if (this.getToken().isNot(_.Token.r_paren)) {\n            do {\n                const expr = this.parseAffineExpr();\n                if (!expr) {\n                    throw new mlir.Error(`Failed to parse affine expression ${this.location()}`);\n                }\n                exprs.push(expr);\n            } while (this.consumeIf(_.Token.comma));\n        }\n        this.parseToken(_.Token.r_paren, \"Expected ')'\");\n        return _.AffineMap.get(numDims, numSymbols, exprs);\n    }\n\n    parseIntegerSetConstraints(numDims, numSymbols) {\n        const constraints = [];\n        const isEqs = [];\n        this.parseToken(_.Token.l_paren, \"Expected '('\");\n        if (this.getToken().isNot(_.Token.r_paren)) {\n            do {\n                const { expr, isEq } = this.parseAffineConstraint();\n                constraints.push(expr);\n                isEqs.push(isEq);\n            } while (this.consumeIf(_.Token.comma));\n        }\n        this.parseToken(_.Token.r_paren, \"Expected ')'\");\n        // If no constraints, return degenerate true set (0 == 0)\n        if (constraints.length === 0) {\n            const zero = this.getAffineConstantExpr(0);\n            return _.IntegerSet.get(numDims, numSymbols, [zero], [true]);\n        }\n        return _.IntegerSet.get(numDims, numSymbols, constraints, isEqs);\n    }\n\n    parseAffineConstraint() {\n        const lhsExpr = this.parseAffineExpr();\n        if (!lhsExpr) {\n            throw new mlir.Error(`Expected affine expression ${this.location()}`);\n        }\n        if (this.consumeIf(_.Token.greater) && this.consumeIf(_.Token.equal)) {\n            const rhsExpr = this.parseAffineExpr();\n            return { expr: this.makeSubExpr(lhsExpr, rhsExpr), isEq: false };\n        }\n        if (this.consumeIf(_.Token.less) && this.consumeIf(_.Token.equal)) {\n            const rhsExpr = this.parseAffineExpr();\n            return { expr: this.makeSubExpr(rhsExpr, lhsExpr), isEq: false };\n        }\n        if (this.consumeIf(_.Token.equal) && this.consumeIf(_.Token.equal)) {\n            const rhsExpr = this.parseAffineExpr();\n            return { expr: this.makeSubExpr(lhsExpr, rhsExpr), isEq: true };\n        }\n        throw new mlir.Error(`Expected '>=', '<=', or '==' after affine expression ${this.location()}`);\n    }\n\n    makeSubExpr(lhs, rhs) {\n        const negOne = this.getAffineConstantExpr(-1);\n        const negRhs = this.getAffineBinaryOpExpr(_.AffineExprKind.Mul, negOne, rhs);\n        return this.getAffineBinaryOpExpr(_.AffineExprKind.Add, lhs, negRhs);\n    }\n\n    parseAffineExpr() {\n        return this.parseAffineLowPrecOpExpr(null, null);\n    }\n\n    parseAffineLowPrecOpExpr(llhs, llhsOp) {\n        const lhs = this.parseAffineOperandExpr(llhs);\n        if (!lhs) {\n            return null;\n        }\n        const lOp = this.consumeIfLowPrecOp();\n        if (lOp) {\n            if (llhs) {\n                const sum = this.makeAffineBinaryOp(llhsOp, llhs, lhs);\n                return this.parseAffineLowPrecOpExpr(sum, lOp);\n            }\n            return this.parseAffineLowPrecOpExpr(lhs, lOp);\n        }\n        const hOp = this.consumeIfHighPrecOp();\n        if (hOp) {\n            const highRes = this.parseAffineHighPrecOpExpr(lhs, hOp);\n            if (!highRes) {\n                return null;\n            }\n            const expr = llhs ? this.makeAffineBinaryOp(llhsOp, llhs, highRes) : highRes;\n            const nextOp = this.consumeIfLowPrecOp();\n            if (nextOp) {\n                return this.parseAffineLowPrecOpExpr(expr, nextOp);\n            }\n            return expr;\n        }\n        if (llhs) {\n            return this.makeAffineBinaryOp(llhsOp, llhs, lhs);\n        }\n        return lhs;\n    }\n\n    parseAffineHighPrecOpExpr(llhs, llhsOp) {\n        const lhs = this.parseAffineOperandExpr(llhs);\n        if (!lhs) {\n            return null;\n        }\n        const op = this.consumeIfHighPrecOp();\n        if (op) {\n            if (llhs) {\n                const expr = this.makeAffineBinaryOp(llhsOp, llhs, lhs);\n                return this.parseAffineHighPrecOpExpr(expr, op);\n            }\n            return this.parseAffineHighPrecOpExpr(lhs, op);\n        }\n        if (llhs) {\n            return this.makeAffineBinaryOp(llhsOp, llhs, lhs);\n        }\n        return lhs;\n    }\n\n    consumeIfLowPrecOp() {\n        switch (this.getToken().kind) {\n            case _.Token.plus:\n                this.consumeToken(_.Token.plus);\n                return _.AffineLowPrecOp.Add;\n            case _.Token.minus:\n                this.consumeToken(_.Token.minus);\n                return _.AffineLowPrecOp.Sub;\n            default:\n                return _.AffineLowPrecOp.LNoOp;\n        }\n    }\n\n    consumeIfHighPrecOp() {\n        switch (this.getToken().kind) {\n            case _.Token.star:\n                this.consumeToken(_.Token.star);\n                return _.AffineHighPrecOp.Mul;\n            case _.Token.kw_floordiv:\n                this.consumeToken(_.Token.kw_floordiv);\n                return _.AffineHighPrecOp.FloorDiv;\n            case _.Token.kw_ceildiv:\n                this.consumeToken(_.Token.kw_ceildiv);\n                return _.AffineHighPrecOp.CeilDiv;\n            case _.Token.kw_mod:\n                this.consumeToken(_.Token.kw_mod);\n                return _.AffineHighPrecOp.Mod;\n            default:\n                return _.AffineHighPrecOp.HNoOp;\n        }\n    }\n\n    // Create affine binary op expression\n    makeAffineBinaryOp(op, lhs, rhs) {\n        if (op === 'Sub') {\n            // Subtraction: lhs - rhs = lhs + (-1 * rhs)\n            const negOne = this.getAffineConstantExpr(-1);\n            const negRhs = this.getAffineBinaryOpExpr(_.AffineExprKind.Mul, negOne, rhs);\n            return this.getAffineBinaryOpExpr(_.AffineExprKind.Add, lhs, negRhs);\n        }\n        return this.getAffineBinaryOpExpr(op, lhs, rhs);\n    }\n\n    parseAffineOperandExpr(lhs) {\n        if (this.getToken().is(_.Token.kw_symbol)) {\n            return this.parseSymbolSSAIdExpr();\n        }\n        if (this.getToken().is(_.Token.percent_identifier)) {\n            return this.parseSSAIdExpr(false);\n        }\n        if (this.getToken().is(_.Token.integer)) {\n            return this.parseIntegerExpr();\n        }\n        if (this.getToken().is(_.Token.l_paren)) {\n            return this.parseParentheticalExpr();\n        }\n        if (this.getToken().is(_.Token.minus)) {\n            return this.parseNegateExpression(lhs);\n        }\n        if (this.getToken().isAny(_.Token.bare_identifier, _.Token.inttype)) {\n            return this.parseBareIdExpr();\n        }\n        if (this.getToken().isKeyword()) {\n            return this.parseBareIdExpr();\n        }\n        if (this.getToken().isAny(_.Token.plus, _.Token.star)) {\n            if (lhs) {\n                throw new mlir.Error(`Missing right operand of binary operator ${this.location()}`);\n            }\n            throw new mlir.Error(`Missing left operand of binary operator ${this.location()}`);\n        }\n        if (lhs) {\n            throw new mlir.Error(`Missing right operand of binary operator ${this.location()}`);\n        }\n        throw new mlir.Error(`Expected affine expression ${this.location()}`);\n    }\n\n    parseSymbolSSAIdExpr() {\n        this.parseToken(_.Token.kw_symbol);\n        this.parseToken(_.Token.l_paren);\n        const symbolExpr = this.parseSSAIdExpr(true);\n        this.parseToken(_.Token.r_paren);\n        return symbolExpr;\n    }\n\n    parseSSAIdExpr(isSymbol) {\n        if (!this.allowParsingSSAIds) {\n            throw new mlir.Error(`Unexpected SSA identifier ${this.location()}`);\n        }\n        if (this.getToken().isNot(_.Token.percent_identifier)) {\n            throw new mlir.Error(`Expected SSA identifier ${this.location()}`);\n        }\n        const name = this.getTokenSpelling().str();\n        for (const entry of this.dimsAndSymbols) {\n            if (entry.name === name) {\n                this.consumeToken(_.Token.percent_identifier);\n                return entry.expr;\n            }\n        }\n        if (this.parseElement) {\n            this.parseElement(isSymbol);\n        } else {\n            this.consumeToken(_.Token.percent_identifier);\n        }\n        const idExpr = isSymbol\n            ? this.getAffineSymbolExpr(this.numSymbolOperands++)\n            : this.getAffineDimExpr(this.numDimOperands++);\n        this.dimsAndSymbols.push({ name, expr: idExpr });\n        return idExpr;\n    }\n\n    parseIntegerExpr() {\n        const val = this.getToken().getUInt64IntegerValue();\n        this.consumeToken(_.Token.integer);\n        return this.getAffineConstantExpr(Number(val));\n    }\n\n    parseParentheticalExpr() {\n        this.parseToken(_.Token.l_paren, \"Expected '('\");\n        if (this.getToken().is(_.Token.r_paren)) {\n            throw new mlir.Error(`No expression inside parentheses ${this.location()}`);\n        }\n        const expr = this.parseAffineExpr();\n        this.parseToken(_.Token.r_paren, \"Expected ')'\");\n        return expr;\n    }\n\n    parseNegateExpression(lhs) {\n        this.parseToken(_.Token.minus, \"Expected '-'\");\n        const operand = this.parseAffineOperandExpr(lhs);\n        if (!operand) {\n            throw new mlir.Error(`Missing operand of negation ${this.location()}`);\n        }\n        const negOne = this.getAffineConstantExpr(-1);\n        return this.getAffineBinaryOpExpr(_.AffineExprKind.Mul, negOne, operand);\n    }\n\n    parseBareIdExpr() {\n        if (!this.isCurrentTokenAKeyword()) {\n            throw new mlir.Error(`Expected bare identifier ${this.location()}`);\n        }\n        const name = this.getTokenSpelling().str();\n        this.consumeToken();\n        for (const entry of this.dimsAndSymbols) {\n            if (entry.name === name) {\n                return entry.expr;\n            }\n        }\n        throw new mlir.Error(`Use of undeclared identifier '${name}' ${this.location()}`);\n    }\n\n    parseAffineMapOfSSAIds(delimiter = 'Paren') {\n        const exprs = [];\n        const open = delimiter === 'Paren' ? _.Token.l_paren : _.Token.l_square;\n        const close = delimiter === 'Paren' ? _.Token.r_paren : _.Token.r_square;\n        this.parseToken(open, `Expected '${open === _.Token.l_paren ? '(' : '['}'`);\n        if (this.getToken().isNot(close)) {\n            do {\n                const expr = this.parseAffineExpr();\n                exprs.push(expr);\n            } while (this.consumeIf(_.Token.comma));\n        }\n        this.parseToken(close, `Expected '${close === _.Token.r_paren ? ')' : ']'}'`);\n        return _.AffineMap.get(this.numDimOperands, this.dimsAndSymbols.length - this.numDimOperands, exprs);\n    }\n\n    parseAffineExprOfSSAIds() {\n        return this.parseAffineExpr();\n    }\n\n    getAffineDimExpr(position) {\n        return new _.AffineDimExpr(position);\n    }\n\n    getAffineSymbolExpr(position) {\n        return new _.AffineSymbolExpr(position);\n    }\n\n    getAffineConstantExpr(constant) {\n        return new _.AffineConstantExpr(constant);\n    }\n\n    getAffineBinaryOpExpr(kind, lhs, rhs) {\n        return new _.AffineBinaryOpExpr(kind, lhs, rhs);\n    }\n};\n\n_.OperationParser = class extends _.Parser {\n\n    constructor(state) {\n        super(state);\n        this.isolatedNameScopes = [];\n        this.pushSSANameScope(/* isIsolated */ true);\n        this._redirect = new Map([\n            ['builtin.func', 'func.func'],\n            ['builtin.constant', 'arith.constant'],\n            ['builtin.return', 'func.return'],\n            ['builtin.select', 'arith.select'],\n            ['scf.select', 'arith.select'],\n            ['scf.call', 'func.call'],\n            ['builtin.view', 'memref.view'],\n            ['builtin.dealloc', 'memref.dealloc'], ['func.dealloc', 'memref.dealloc'],\n            // Arith operations (from both builtin and func default dialects)\n            ['builtin.addi', 'arith.addi'], ['func.addi', 'arith.addi'],\n            ['builtin.subi', 'arith.subi'], ['func.subi', 'arith.subi'],\n            ['builtin.muli', 'arith.muli'], ['func.muli', 'arith.muli'],\n            ['builtin.divi_signed', 'arith.divsi'], ['func.divi_signed', 'arith.divsi'],\n            ['builtin.divi_unsigned', 'arith.divui'], ['func.divi_unsigned', 'arith.divui'],\n            ['builtin.divsi', 'arith.divsi'], ['func.divsi', 'arith.divsi'],\n            ['builtin.divui', 'arith.divui'], ['func.divui', 'arith.divui'],\n            ['builtin.remi_signed', 'arith.remsi'], ['func.remi_signed', 'arith.remsi'],\n            ['builtin.remi_unsigned', 'arith.remui'], ['func.remi_unsigned', 'arith.remui'],\n            ['builtin.andi', 'arith.andi'], ['func.andi', 'arith.andi'],\n            ['builtin.ori', 'arith.ori'], ['func.ori', 'arith.ori'],\n            ['builtin.xori', 'arith.xori'], ['func.xori', 'arith.xori'],\n            ['builtin.shli', 'arith.shli'], ['func.shli', 'arith.shli'],\n            ['builtin.shrsi', 'arith.shrsi'], ['func.shrsi', 'arith.shrsi'],\n            ['builtin.shrui', 'arith.shrui'], ['func.shrui', 'arith.shrui'],\n            ['builtin.addf', 'arith.addf'], ['func.addf', 'arith.addf'],\n            ['builtin.subf', 'arith.subf'], ['func.subf', 'arith.subf'],\n            ['builtin.mulf', 'arith.mulf'], ['func.mulf', 'arith.mulf'],\n            ['builtin.divf', 'arith.divf'], ['func.divf', 'arith.divf'],\n            ['builtin.cmpi', 'arith.cmpi'], ['func.cmpi', 'arith.cmpi'],\n            ['builtin.cmpf', 'arith.cmpf'], ['func.cmpf', 'arith.cmpf'],\n            ['builtin.index_cast', 'arith.index_cast'], ['func.index_cast', 'arith.index_cast'],\n            ['builtin.sitofp', 'arith.sitofp'], ['func.sitofp', 'arith.sitofp'],\n            ['builtin.fptosi', 'arith.fptosi'], ['func.fptosi', 'arith.fptosi'],\n            ['builtin.truncf', 'arith.truncf'], ['func.truncf', 'arith.truncf'],\n            ['builtin.extf', 'arith.extf'], ['func.extf', 'arith.extf'],\n            ['builtin.splat', 'vector.splat'],\n            ['func.splat', 'vector.splat'],\n            ['scf.splat', 'vector.splat'],\n            // Memref operations\n            ['builtin.alloc', 'memref.alloc'], ['func.alloc', 'memref.alloc'],\n            ['builtin.load', 'memref.load'], ['func.load', 'memref.load'],\n            ['builtin.store', 'memref.store'], ['func.store', 'memref.store'],\n            ['builtin.subview', 'memref.subview'], ['func.subview', 'memref.subview'],\n            ['builtin.dim', 'memref.dim'], ['func.dim', 'memref.dim'],\n            ['builtin.view', 'memref.view'], ['func.view', 'memref.view'],\n            // Control flow operations\n            ['builtin.cond_br', 'cf.cond_br'], ['func.cond_br', 'cf.cond_br'],\n            ['builtin.br', 'cf.br'], ['func.br', 'cf.br'],\n            ['builtin.switch', 'cf.switch'], ['func.switch', 'cf.switch'],\n            ['builtin.assert', 'cf.assert'], ['func.assert', 'cf.assert'],\n            // AMX -> X86 AMX redirects\n            ['amx.tile_load', 'x86.amx.tile_load'],\n            ['amx.tile_mulf', 'x86.amx.tile_mulf'],\n            ['amx.tile_muli', 'x86.amx.tile_muli'],\n            ['amx.tile_store', 'x86.amx.tile_store'],\n            ['amx.tile_zero', 'x86.amx.tile_zero'],\n            // Other redirects\n            ['flow.constant', 'flow.tensor.constant'],\n            ['util.initializer.return', 'util.return']\n        ]);\n    }\n\n    finalize(block) {\n        const attributeAliases = this.state.attributeAliasDefinitions;\n        const deferredRefs = this.state.deferredLocsReferences;\n        const resolveLocation = (opOrArgument) => {\n            const fwdLoc = opOrArgument.loc;\n            if (fwdLoc instanceof _.OpaqueLoc) {\n                const locInfo = deferredRefs[fwdLoc.index];\n                const identifier = `#${locInfo.identifier}`;\n                const attr = attributeAliases.get(identifier);\n                if (!attr) {\n                    throw new mlir.Error(`Operation location alias '${locInfo.identifier}' was never defined.`);\n                }\n                if (attr instanceof _.LocationAttr === false) {\n                    throw new mlir.Error(`Expected location but found '${attr}'.`);\n                }\n                opOrArgument.loc = attr;\n            }\n        };\n        // Walk all operations and resolve locations on ops and block arguments\n        const walk = (operations) => {\n            for (const op of operations) {\n                if (op.loc) {\n                    resolveLocation(op);\n                }\n                if (op.body && op.body.blocks) {\n                    for (const blk of op.body.blocks) {\n                        if (blk.arguments) {\n                            for (const arg of blk.arguments) {\n                                if (arg.loc) {\n                                    resolveLocation(arg);\n                                }\n                            }\n                        }\n                        if (blk.operations) {\n                            walk(blk.operations);\n                        }\n                    }\n                }\n            }\n        };\n        walk(block.operations);\n    }\n\n    parseOperation() {\n        const loc = this.getToken().loc.copy();\n        const resultIDs = [];\n        let numExpectedResults = 0;\n        if (this.getToken().is(_.Token.percent_identifier)) {\n            const parseNextResult = () => {\n                const name = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.percent_identifier);\n                let expectedSubResults = 1;\n                if (this.consumeIf(_.Token.colon)) {\n                    if (this.getToken().isNot(_.Token.integer)) {\n                        throw new mlir.Error(`Expected integer number of results ${this.location()}`);\n                    }\n                    const val = parseInt(this.getToken().getSpelling().str(), 10);\n                    if (!Number.isInteger(val) || val < 1) {\n                        throw new mlir.Error(`Expected named operation to have at least 1 result ${this.location()}`);\n                    }\n                    this.consumeToken(_.Token.integer);\n                    expectedSubResults *= val;\n                }\n                resultIDs.push([name, expectedSubResults, null]);\n                numExpectedResults += expectedSubResults;\n                return true;\n            };\n            this.parseCommaSeparatedList('none', parseNextResult);\n            this.parseToken(_.Token.equal, \"Expected '=' after SSA name\");\n        }\n        let op = null;\n        // Reference Parser.cpp:1305: nameTok.is(Token::bare_identifier) || nameTok.isKeyword()\n        const nameTok = this.getToken();\n        if (nameTok.is(_.Token.bare_identifier) || nameTok.isKeyword()) {\n            op = this.parseCustomOperation(resultIDs);\n        } else if (nameTok.is(_.Token.string)) {\n            op = this.parseGenericOperation();\n        } else {\n            throw new mlir.Error(`${this.getToken().is(_.Token.eof) ? 'Unexpected end of input' : `Unexpected operation name '${this.getTokenSpelling().str()}'`} ${this.location()}`);\n        }\n        if (!op) {\n            throw new mlir.Error(`Failed to parse operation ${this.location()}`);\n        }\n        if (resultIDs.length > 0 && op.results.length === 0) {\n            throw new mlir.Error(`Cannot name an operation with no results ${loc.toString()}`);\n        }\n        if (resultIDs.length > 0 && op.results.length !== numExpectedResults) {\n            throw new mlir.Error(`Operation '${op.name.getStringRef()}' defines '${op.results.length}' results but was provided '${numExpectedResults}' to bind ${loc.toString()}`);\n        }\n        let index = 0;\n        for (const resIt of resultIDs) {\n            for (let subRes = 0; subRes < resIt[1]; subRes++) {\n                const result = op.results[index++];\n                if (result.name) {\n                    throw new mlir.Error(`Result '${result.name}' already has name ${this.location()}`);\n                }\n                // Workaround: Visualization-specific addition is to store name on result for display\n                result.name = subRes === 0 ? resIt[0] : `${resIt[0]}.${subRes}`;\n                this.addDefinition(new _.UnresolvedOperand(resIt[2], resIt[0], subRes), result);\n            }\n        }\n        return op;\n    }\n\n    parseCustomOperation(resultIDs) {\n        const opLoc = this.getToken().loc.copy();\n        const opNameInfo = this.parseCustomOperationName();\n        const opState = new _.OperationState(opLoc, opNameInfo);\n        delete opNameInfo.identifier; // Workaround\n        const defaultDialect = (opNameInfo && opNameInfo.metadata && opNameInfo.metadata.defaultDialect) || this.state.defaultDialectStack[this.state.defaultDialectStack.length - 1];\n        this.state.defaultDialectStack.push(defaultDialect);\n        const customParser = new _.CustomOpAsmParser(resultIDs, this);\n        if (!opNameInfo.dialect.parseOperation(customParser, opState)) {\n            this.state.defaultDialectStack.pop();\n            throw new mlir.Error(`Unsupported custom operation '${opState.identifier}' ${this.location()}`);\n        }\n        if (!opNameInfo.metadata.hasParser && !opNameInfo.metadata.hasCustomAssemblyFormat && opNameInfo.metadata.assemblyFormat && opState.compatibility !== true) {\n            throw new mlir.Error(`Operation '${opState.identifier}' has assembly format but was handled by custom dialect code.`);\n        }\n        opState.loc = this.parseTrailingLocationSpecifier() || {};\n        this.state.defaultDialectStack.pop();\n        return _.Operation.create(opState);\n    }\n\n    parseCustomOperationName() {\n        const nameTok = this.getToken();\n        if (nameTok.kind !== _.Token.bare_identifier && !nameTok.isKeyword()) {\n            throw new mlir.Error(`Expected bare identifier or keyword ${this.location()}`);\n        }\n        const identifier = nameTok.getSpelling().str(); // Workaround: keep the original source file identifier\n        this.consumeToken();\n        let opName = this.redirect(identifier);\n        let opInfo = _.RegisteredOperationName.lookup(opName, this.context);\n        if (opInfo) {\n            opInfo.identifier = identifier;\n            return opInfo;\n        }\n        let index = opName.indexOf('.');\n        if (index === -1) {\n            const dialect = this.state.defaultDialectStack[this.state.defaultDialectStack.length - 1];\n            opName = this.redirect(`${dialect}.${opName}`);\n        }\n        index = opName.indexOf('.');\n        if (index === -1) {\n            throw new mlir.Error(`No dialect found '${opName}' ${this.location()}`);\n        }\n        const dialectName = opName.substring(0, index);\n        const dialect = this.context.getOrLoadDialect(dialectName);\n        this.context.checkDialect(dialect, dialectName, 'operation');\n        // Normalize operation name to canonical dialect name for metadata lookup\n        // (e.g., spv.Load -> spirv.Load when dialect.name is spirv)\n        if (dialectName !== dialect.name) {\n            opName = opName.replace(`${dialectName}.`, `${dialect.name}.`);\n        }\n        opInfo = _.RegisteredOperationName.lookup(opName, this.context);\n        if (!opInfo) {\n            throw new mlir.Error(`Unsupported operation '${opName}'.`);\n        }\n        opInfo.identifier = identifier; // Workaround\n        return opInfo;\n    }\n\n    parseGenericOperation() {\n        const srcLocation = this.getToken().loc.copy();\n        const identifier = this.getToken().getStringValue();\n        if (identifier.length === 0) {\n            throw new mlir.Error(`Empty operation name is invalid ${this.location()}`);\n        }\n        if (identifier.indexOf('\\0') !== -1) {\n            throw new mlir.Error(`Null character not allowed in operation name ${this.location()}`);\n        }\n        this.consumeToken(_.Token.string);\n        const name = this.redirect(identifier);\n        let opName = _.RegisteredOperationName.lookup(name, this.context);\n        if (!opName) {\n            const index = name.indexOf('.');\n            const dialect = index === -1 ? null : this.context.getOrLoadDialect(name.substring(0, index));\n            opName = new _.OperationName(dialect || null, name);\n        }\n        opName.identifier = identifier; // Workaround\n        const result = new _.OperationState(srcLocation, opName);\n        this.parseGenericOperationAfterOpName(result);\n        return _.Operation.create(result);\n    }\n\n    parseGenericOperationAfterOpName(result) {\n        this.parseToken(_.Token.l_paren, \"Expected '(' to start operand list\");\n        const unresolvedOperands = [];\n        this.parseOptionalSSAUseList(unresolvedOperands);\n        this.parseToken(_.Token.r_paren, \"Expected ')' to end operand list\");\n        if (this.getToken().is(_.Token.l_square)) {\n            result.successors = [];\n            this.parseSuccessors(result.successors);\n        }\n        if (this.consumeIf(_.Token.less)) {\n            result.propertiesAttr = this.parseAttribute();\n            if (!result.propertiesAttr) {\n                throw new mlir.Error(`Expected attribute as properties ${this.location()}`);\n            }\n            this.parseToken(_.Token.greater, \"Expected '>' to close properties\");\n        }\n        if (this.consumeIf(_.Token.l_paren)) {\n            do {\n                const region = result.addRegion();\n                this.parseRegion(region, undefined, false);\n            } while (this.consumeIf(_.Token.comma));\n            this.parseToken(_.Token.r_paren, \"Expected ')' to end region list\");\n        }\n        if (this.getToken().is(_.Token.l_brace)) {\n            this.parseAttributeDict(result.attributes);\n        }\n        this.parseToken(_.Token.colon, \"Expected ':' followed by operation type\");\n        const fnType = this.parseType();\n        if (fnType instanceof _.FunctionType === false) {\n            throw new mlir.Error(`Expected function type ${this.location()}`);\n        }\n        const operandTypes = fnType.inputs;\n        if (operandTypes.length !== unresolvedOperands.length) {\n            throw new mlir.Error(`Expected ${unresolvedOperands.length} operand type${unresolvedOperands.length === 1 ? '' : 's'} but had ${operandTypes.length} ${this.location()}`);\n        }\n        for (let i = 0; i < unresolvedOperands.length; i++) {\n            const unresolvedOperand = unresolvedOperands[i];\n            const type = operandTypes[i] || null;\n            const value = this.resolveSSAUse(unresolvedOperand, type);\n            result.operands.push(value);\n        }\n        result.addTypes(fnType.results);\n        result.loc = this.parseTrailingLocationSpecifier();\n    }\n\n    pushSSANameScope(isIsolated) {\n        if (isIsolated) {\n            this.isolatedNameScopes.push(new _.IsolatedSSANameScope());\n        }\n        this.isolatedNameScopes[this.isolatedNameScopes.length - 1].pushSSANameScope();\n    }\n\n    popSSANameScope() {\n        const currentNameScope = this.isolatedNameScopes[this.isolatedNameScopes.length - 1];\n        if (currentNameScope.definitionsPerScope.length === 1) {\n            this.isolatedNameScopes.pop();\n        } else {\n            currentNameScope.popSSANameScope();\n        }\n    }\n\n    addDefinition(useInfo, value) {\n        const entries = this.getSSAValueEntry(useInfo.name);\n        if (entries.length <= useInfo.number) {\n            entries.length = useInfo.number + 1;\n        }\n        entries[useInfo.number] = { value, loc: useInfo.location };\n        this.recordDefinition(useInfo.name);\n    }\n\n    recordDefinition(def) {\n        this.isolatedNameScopes[this.isolatedNameScopes.length - 1].recordDefinition(def);\n    }\n\n    parseOptionalSSAUseList(results) {\n        if (this.getToken().isNot(_.Token.percent_identifier)) {\n            return;\n        }\n        this.parseCommaSeparatedList('none', () => {\n            const result = this.parseSSAUse();\n            results.push(result);\n        });\n    }\n\n    parseSSAUse(allowResultNumber = true) {\n        const name = this.getTokenSpelling().str();\n        this.parseToken(_.Token.percent_identifier, \"Expected SSA operand\");\n        let number = 0;\n        if (this.getToken().is(_.Token.hash_identifier)) {\n            if (!allowResultNumber) {\n                throw new mlir.Error(`Result number not allowed in argument list ${this.location()}`);\n            }\n            const value = this.getTokenSpelling().str().substring(1);\n            this.consumeToken(_.Token.hash_identifier);\n            number = parseInt(value, 10);\n            if (isNaN(number)) {\n                throw new mlir.Error(`Invalid SSA value result number '${value}' ${this.location()}`);\n            }\n        }\n        return new _.UnresolvedOperand(null, name, number);\n    }\n\n    resolveSSAUse(unresolvedOperand, type) {\n        if (type !== null && type instanceof _.Type === false) {\n            throw new mlir.Error(`Type expected instead of '${type}'.`);\n        }\n        if (unresolvedOperand instanceof _.UnresolvedOperand) {\n            const entries = this.getSSAValueEntry(unresolvedOperand.name);\n            if (unresolvedOperand.number < entries.length && entries[unresolvedOperand.number]) {\n                const entry = entries[unresolvedOperand.number];\n                if (type && entry.value) {\n                    entry.value.type = type;\n                }\n                return entry.value;\n            }\n            const value = new _.Value(unresolvedOperand.toString(), type);\n            if (entries.length <= unresolvedOperand.number) {\n                entries.length = unresolvedOperand.number + 1;\n            }\n            entries[unresolvedOperand.number] = { value, loc: unresolvedOperand.location };\n            return value;\n        }\n        // Handle literal operands (e.g., integer literals for buildable types)\n        if (unresolvedOperand && unresolvedOperand.literal) {\n            return new _.Value(unresolvedOperand.name, type);\n        }\n        throw new mlir.Error(`UnresolvedOperand expected, got '${JSON.stringify(unresolvedOperand)}' ${this.location()}`);\n    }\n\n    getSSAValueEntry(name) {\n        const scope = this.isolatedNameScopes[this.isolatedNameScopes.length - 1];\n        if (!scope.values.has(name)) {\n            scope.values.set(name, []);\n        }\n        return scope.values.get(name);\n    }\n\n    parseBlock(block) {\n        block.operations = Array.isArray(block.operations) ? block.operations : [];\n        block.arguments = Array.isArray(block.arguments) ? block.arguments : [];\n        this.parseToken(_.Token.l_brace, \"expected '{' to begin a region\");\n        if (this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getToken().getSpelling().str() && this.getToken().getSpelling().str().startsWith('^'))) {\n            if (this.getToken().kind === _.Token.caret_identifier) {\n                block.name = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.caret_identifier);\n            } else {\n                block.name = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.bare_identifier);\n            }\n            if (this.consumeIf(_.Token.l_paren)) {\n                while (!this.consumeIf(_.Token.r_paren) && this.getToken().isNot(_.Token.caret_identifier)) {\n                    const value = this.getTokenSpelling().str();\n                    this.consumeToken(_.Token.percent_identifier);\n                    this.consumeToken(_.Token.colon);\n                    const type = this.parseType();\n                    const arg = { value, type };\n                    const loc = this.parseTrailingLocationSpecifier();\n                    if (loc) {\n                        arg.loc = loc;\n                    }\n                    block.arguments.push(arg);\n                    this.consumeIf(_.Token.comma);\n                }\n            }\n            if (block.name && block.name.endsWith(':')) {\n                block.name = block.name.slice(0, -1);\n            } else {\n                this.consumeToken(_.Token.colon);\n            }\n        }\n        while (!this.consumeIf(_.Token.r_brace)) {\n            if (this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getToken().getSpelling().str() && this.getToken().getSpelling().str().startsWith('^'))) {\n                break;\n            }\n            const op = this.parseOperation();\n            block.operations.push(op);\n        }\n        block.loc = this.parseTrailingLocationSpecifier();\n        return block;\n    }\n\n    parseRegion(region, entryArguments, isIsolatedNameScope) {\n        // Push a new name scope for this region\n        this.pushSSANameScope(isIsolatedNameScope || false);\n\n        region.blocks = Array.isArray(region.blocks) ? region.blocks : [];\n        // Register SSA entries for entry arguments BEFORE parsing the block\n        // This ensures operations that reference %arg0 find the pre-registered entries\n        const resolvedEntryArgs = [];\n        if (entryArguments && entryArguments.length > 0) {\n            for (let i = 0; i < entryArguments.length; i++) {\n                const arg = entryArguments[i];\n                // Use explicit name if provided, otherwise generate %arg0, %arg1, etc.\n                const name = arg.name || `%arg${i}`;\n                const operand = new _.Value(name, arg.type);\n                // Register in SSA scope so operations can find it\n                this.addDefinition({ name, number: 0, location: arg.loc || null }, operand);\n                resolvedEntryArgs.push(operand);\n            }\n        }\n        const block = {};\n        this.parseBlock(block);\n        if (resolvedEntryArgs.length > 0) {\n            if (block.arguments.length === 0) {\n                block.arguments = resolvedEntryArgs;\n            } else if (block.arguments.length !== resolvedEntryArgs.length) {\n                throw new mlir.Error(`Entry block has ${block.arguments.length} arguments, but function signature has ${resolvedEntryArgs.length} ${this.location()}`);\n            }\n        }\n        region.blocks.push(block);\n        let hasMultipleBlocks = false;\n        while ((this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getToken().getSpelling().str() && this.getToken().getSpelling().str().startsWith('^'))) && this.getToken().isNot(_.Token.r_brace)) {\n            hasMultipleBlocks = true;\n            const nextBlock = {};\n            nextBlock.operations = [];\n            nextBlock.arguments = [];\n            if (this.getToken().kind === _.Token.caret_identifier) {\n                nextBlock.name = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.caret_identifier);\n            } else {\n                nextBlock.name = this.getTokenSpelling().str();\n                this.consumeToken(_.Token.bare_identifier);\n            }\n            if (this.consumeIf(_.Token.l_paren)) {\n                while (!this.consumeIf(_.Token.r_paren)) {\n                    const value = this.getTokenSpelling().str();\n                    this.consumeToken(_.Token.percent_identifier);\n                    this.consumeToken(_.Token.colon);\n                    const type = this.parseType();\n                    const arg = { value, type };\n                    const loc = this.parseTrailingLocationSpecifier();\n                    if (loc) {\n                        arg.loc = loc;\n                    }\n                    nextBlock.arguments.push(arg);\n                    this.consumeIf(_.Token.comma);\n                }\n            }\n            if (nextBlock.name && nextBlock.name.endsWith(':')) {\n                nextBlock.name = nextBlock.name.slice(0, -1);\n            } else {\n                this.consumeToken(_.Token.colon);\n            }\n            while (!(this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getTokenSpelling().str() && this.getTokenSpelling().str().startsWith('^'))) && this.getToken().isNot(_.Token.r_brace)) {\n                const op = this.parseOperation();\n                nextBlock.operations.push(op);\n            }\n            region.blocks.push(nextBlock);\n        }\n        if (hasMultipleBlocks) {\n            this.consumeIf(_.Token.r_brace);\n        }\n        this.popSSANameScope();\n        return region;\n    }\n\n    parseTrailingLocationSpecifier() {\n        if (!this.consumeIf(_.Token.kw_loc)) {\n            return null;\n        }\n        this.parseToken(_.Token.l_paren, \"expected '(' in location\");\n        const tok = this.getToken();\n        let directLoc = null;\n        if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {\n            directLoc = this.parseLocationAlias();\n        } else {\n            directLoc = this.parseLocationInstance();\n        }\n        this.parseToken(_.Token.r_paren, \"expected ')' in location\");\n        return directLoc;\n    }\n\n    redirect(name) {\n        if (name === 'func.constant' && this.getToken().isNot(_.Token.at_identifier)) {\n            // Workaround: old std.constant should be arith.constant\n            name = 'arith.constant';\n        } else if (name.startsWith('check.')) {\n            // Workaround: Handle conflicting dialects from stablehlo and iree\n            const dialect = this.getToken().is(_.Token.l_paren) || this.getToken().is(_.Token.less) ? 'iree' : 'stablehlo';\n            name = name.replace('check.', `check.<${dialect}>.`);\n        } else if (this._redirect.has(name)) {\n            name = this._redirect.get(name);\n        }\n        return name;\n    }\n};\n\n_.AsmParser = class {\n\n    getNameLoc() {\n        return this.nameLoc;\n    }\n\n    parseKeyword(keyword) {\n        if (!this.parser.isCurrentTokenAKeyword()) {\n            throw new mlir.Error(`expected '${keyword || 'keyword'}' ${this.parser.location()}`);\n        }\n        if (keyword && this.parser.getTokenSpelling().str() !== keyword) {\n            throw new mlir.Error(`expected '${keyword}' ${this.parser.location()}`);\n        }\n        const spelling = this.parser.getTokenSpelling().str();\n        this.parser.consumeToken();\n        return spelling;\n    }\n\n    parseOptionalKeyword(arg) {\n        if (typeof arg === 'string') {\n            const keyword = arg;\n            if (!this.parser.isCurrentTokenAKeyword() || this.parser.getTokenSpelling().str() !== keyword) {\n                return false;\n            }\n            this.parser.consumeToken();\n            return true;\n        }\n        if (Array.isArray(arg)) {\n            const allowedValues = arg;\n            if (this.parser.getToken().is(_.Token.bare_identifier) || this.parser.getToken().isKeyword() || this.parser.getToken().is(_.Token.inttype)) {\n                const value = this.parser.getTokenSpelling().str();\n                if (allowedValues === undefined || allowedValues.some((v) => v === value)) {\n                    this.parser.consumeToken();\n                    return value;\n                }\n            }\n            return null;\n        }\n        if (arg === undefined) {\n            return this.parser.parseOptionalKeyword();\n        }\n        throw new mlir.Error(`Invalid optional keyword ${this.parser.location()}`);\n    }\n\n    parseKeywordType(keyword) {\n        this.parseKeyword(keyword);\n        return this.parser.parseType();\n    }\n\n    parseTypeList() {\n        return this.parser.parseTypeListNoParens();\n    }\n\n    parseType() {\n        return this.parser.parseType();\n    }\n\n    parseOptionalType() {\n        return this.parser.parseOptionalType();\n    }\n\n    parseDimensionList(allowDynamic, withTrailingX) {\n        return this.parser.parseDimensionListRanked(allowDynamic, withTrailingX);\n    }\n\n    parseColonType() {\n        this.parser.parseToken(_.Token.colon, \"expected ':'\");\n        return this.parser.parseType();\n    }\n\n    parseColonTypeList() {\n        this.parser.parseToken(_.Token.colon, \"expected ':'\");\n        return this.parseTypeList();\n    }\n\n    parseOptionalColonTypeList() {\n        if (this.parser.consumeIf(_.Token.colon)) {\n            return this.parseTypeList();\n        }\n        return [];\n    }\n\n    parseArrowTypeList() {\n        this.parseArrow();\n        return this.parser.parseFunctionResultTypes();\n    }\n\n    parseOptionalArrowTypeList() {\n        if (this.parser.consumeIf(_.Token.arrow)) {\n            return this.parser.parseFunctionResultTypes();\n        }\n        return [];\n    }\n\n    parseAttribute(type) {\n        return this.parser.parseAttribute(type);\n    }\n\n    parseOptionalAttribute(type) {\n        return this.parser.parseOptionalAttribute(type);\n    }\n\n    parseCustomAttributeWithFallback(attrT, type) {\n        if (attrT) {\n            return attrT(this, type);\n        }\n        return this.parser.parseAttribute(type);\n    }\n\n    parseCustomTypeWithFallback(typeT) {\n        if (typeT && this.parser.getToken().isNot(_.Token.exclamation_identifier)) {\n            if (typeof typeT === 'function') {\n                return typeT(this);\n            }\n            const index = typeT.name.indexOf('.');\n            if (index === -1) {\n                throw new mlir.Error(`Invalid type name '${typeT.name}.`);\n            }\n            const dialectName = typeT.name.substring(0, index);\n            const dialect = this.parser.context.getOrLoadDialect(dialectName);\n            this.parser.context.checkDialect(dialect, dialectName, 'custom type');\n            return dialect.parseCustomTypeWithFallback(this, typeT.type);\n        }\n        return this.parser.parseType();\n    }\n\n    parseOptionalAttrDict(attributes) {\n        if (this.parser.getToken().is(_.Token.l_brace)) {\n            this.parser.parseAttributeDict(attributes);\n        }\n    }\n\n    parseOptionalAttrDictWithKeyword(attributes) {\n        if (this.parseOptionalKeyword('attributes')) {\n            this.parser.parseAttributeDict(attributes);\n        }\n    }\n\n    parseOptionalString() {\n        return this.parser.parseOptionalString();\n    }\n\n    parseOptionalKeywordOrString() {\n        return this.parser.parseOptionalKeywordOrString();\n    }\n\n    parseString() {\n        const value = this.parser.parseOptionalString();\n        if (value === null) {\n            throw new mlir.Error(`Expected string ${this.parser.location()}`);\n        }\n        return value;\n    }\n\n    parseOptionalInteger(type) {\n        return this.parser.parseOptionalInteger(type);\n    }\n\n    parseOptionalDecimalInteger() {\n        return this.parser.parseOptionalDecimalInteger();\n    }\n\n    parseInteger(type) {\n        return this.parser.parseInteger(type);\n    }\n\n    parseDecimalInteger() {\n        return this.parser.parseDecimalInteger();\n    }\n\n    parseCommaSeparatedList(delimiter, parseElement) {\n        return this.parser.parseCommaSeparatedList(delimiter, parseElement);\n    }\n\n    parseArrow() {\n        this.parser.parseToken(_.Token.arrow, \"expected '->'\");\n    }\n\n    parseOptionalArrow() {\n        return this.parser.consumeIf(_.Token.arrow);\n    }\n\n    parseEqual() {\n        this.parser.parseToken(_.Token.equal, \"expected '='\");\n    }\n\n    parseOptionalEqual() {\n        return this.parser.consumeIf(_.Token.equal);\n    }\n\n    parseLBrace() {\n        this.parser.parseToken(_.Token.l_brace, \"expected '{'\");\n    }\n\n    parseRBrace() {\n        this.parser.parseToken(_.Token.r_brace, \"expected '}'\");\n    }\n\n    parseOptionalLBrace() {\n        return this.parser.consumeIf(_.Token.l_brace);\n    }\n\n    parseOptionalRBrace() {\n        return this.parser.consumeIf(_.Token.r_brace);\n    }\n\n    parseComma() {\n        this.parser.parseToken(_.Token.comma, \"expected ','\");\n    }\n\n    parseOptionalComma() {\n        return this.parser.consumeIf(_.Token.comma);\n    }\n\n    parseLParen() {\n        this.parser.parseToken(_.Token.l_paren, \"expected '('\");\n    }\n\n    parseRParen() {\n        this.parser.parseToken(_.Token.r_paren, \"expected ')'\");\n    }\n\n    parseOptionalLParen() {\n        return this.parser.consumeIf(_.Token.l_paren);\n    }\n\n    parseOptionalRParen() {\n        return this.parser.consumeIf(_.Token.r_paren);\n    }\n\n    parseLSquare() {\n        return this.parser.parseToken(_.Token.l_square, \"expected '['\");\n    }\n\n    parseRSquare() {\n        return this.parser.parseToken(_.Token.r_square, \"expected ']'\");\n    }\n\n    parseOptionalLSquare() {\n        return this.parser.consumeIf(_.Token.l_square);\n    }\n\n    parseOptionalRSquare() {\n        return this.parser.consumeIf(_.Token.r_square);\n    }\n\n    parseColon() {\n        this.parser.parseToken(_.Token.colon, \"expected ':'\");\n    }\n\n    parseOptionalColon() {\n        return this.parser.consumeIf(_.Token.colon);\n    }\n\n    parseLess() {\n        this.parser.parseToken(_.Token.less, \"expected '<'\");\n    }\n\n    parseGreater() {\n        this.parser.parseToken(_.Token.greater, \"expected '>'\");\n    }\n\n    parseOptionalLess() {\n        return this.parser.consumeIf(_.Token.less);\n    }\n\n    parseOptionalGreater() {\n        return this.parser.consumeIf(_.Token.greater);\n    }\n\n    parseOptionalVerticalBar() {\n        return this.parser.consumeIf(_.Token.vertical_bar);\n    }\n\n    parseOptionalQuestion() {\n        return this.parser.consumeIf(_.Token.question);\n    }\n\n    parseOptionalStar() {\n        return this.parser.consumeIf(_.Token.star);\n    }\n\n    parseOptionalMinus() {\n        return this.parser.consumeIf(_.Token.minus);\n    }\n\n    parseOptionalEllipsis() {\n        return this.parser.consumeIf(_.Token.ellipsis);\n    }\n\n    parseOptionalPlus() {\n        return this.parser.consumeIf(_.Token.plus);\n    }\n\n    parseStar() {\n        this.parser.parseToken(_.Token.star, \"expected '*'\");\n    }\n\n    parsePlus() {\n        this.parser.parseToken(_.Token.plus, \"expected '+'\");\n    }\n\n    parseQuestion() {\n        this.parser.parseToken(_.Token.question, \"expected '?'\");\n    }\n\n    parseVerticalBar() {\n        this.parser.parseToken(_.Token.vertical_bar, \"expected '|'\");\n    }\n\n    parseEllipsis() {\n        this.parser.parseToken(_.Token.ellipsis, \"expected '...'\");\n    }\n\n    parseMinus() {\n        this.parser.parseToken(_.Token.minus, \"expected '-'\");\n    }\n\n    getCurrentLocation() {\n        return this.parser.location();\n    }\n\n    parseSymbolName(attrName, attrs) {\n        const result = this.parseOptionalSymbolName();\n        if (result === null) {\n            throw new mlir.Error(`Expected valid '@'-identifier for symbol name ${this.parser.location()}`);\n        }\n        attrs.set(attrName, result);\n    }\n\n    parseOptionalSymbolName() {\n        const atToken = this.parser.getToken();\n        if (atToken.isNot(_.Token.at_identifier)) {\n            return null;\n        }\n        const result = new _.StringAttr(atToken.getSymbolReference());\n        this.parser.consumeToken();\n        if (this.parser.state.asmState) {\n            // parser.state.asmState.addUses(SymbolRefAttr::get(result), atToken.getLocRange())\n        }\n        return result;\n    }\n\n    parseAffineMapOfSSAIds(mapOperands, mapAttr, attrName, attrs, delimiter = 'Square') {\n        const dimOperands = [];\n        const symOperands = [];\n        const parseElement = (isSymbol) => {\n            const operand = this.parseOperand();\n            if (isSymbol) {\n                symOperands.push(operand);\n            } else {\n                dimOperands.push(operand);\n            }\n        };\n        const map = this.parser.parseAffineMapOfSSAIds(parseElement, delimiter);\n        if (map) {\n            attrs.set(attrName, map);\n        }\n        mapOperands.push(...dimOperands, ...symOperands);\n    }\n\n    parseAffineMap() {\n        return this.parser.parseAffineMapReference();\n    }\n\n    parseAffineExprOfSSAIds(mapOperands) {\n        const dimOperands = [];\n        const symOperands = [];\n        const parseElement = (isSymbol) => {\n            const operand = this.parseOperand();\n            if (isSymbol) {\n                symOperands.push(operand);\n            } else {\n                dimOperands.push(operand);\n            }\n        };\n        const expr = this.parser.parseAffineExprOfSSAIds(parseElement);\n        mapOperands.push(...dimOperands, ...symOperands);\n        return expr;\n    }\n\n    // Workaround: captures optional <...> type parameters as raw string.\n    // Should be replaced by assembly format driven type parameter parsing.\n    parseTypeParameters() {\n        if (this.parser.getToken().is(_.Token.less)) {\n            return this.parser.parseDialectSymbolBody();\n        }\n        return '';\n    }\n};\n\n_.OpAsmParser = class extends _.AsmParser {\n\n    parseFunctionOp(op, allowVariadic) {\n        this.parseOptionalVisibilityKeyword(op.attributes);\n        this.parseSymbolName('sym_name', op.attributes);\n        const sig = this.parseFunctionSignatureWithArguments(allowVariadic);\n        const argTypes = [];\n        for (const arg of sig.arguments) {\n            if (arg.name !== '...') {\n                argTypes.push(arg.type);\n            }\n        }\n        const type = new _.FunctionType(argTypes, sig.resultTypes);\n        op.addAttribute('function_type', new _.TypeAttrOf(type));\n        if (sig.resultAttrs.some((a) => a !== null)) {\n            op.addAttribute('res_attrs', sig.resultAttrs);\n        }\n        const argAttrs = sig.arguments.filter((a) => a.name !== '...').map((a) => a.attrs || null);\n        if (argAttrs.some((a) => a !== null)) {\n            op.addAttribute('arg_attrs', argAttrs);\n        }\n        this.parseOptionalAttrDictWithKeyword(op.attributes);\n        if (this.parser.getToken().is(_.Token.l_brace)) {\n            const region = op.addRegion();\n            // Functions are IsolatedFromAbove, so pass true for isIsolatedNameScope\n            this.parseRegion(region, sig.arguments, /* isIsolatedNameScope */ true);\n        }\n    }\n\n    parseFunctionSignature(argOperands) {\n        const argTypes = [];\n        const argAttrs = [];\n        const resultTypes = [];\n        const resultAttrs = [];\n        this.parser.parseToken(_.Token.l_paren, \"expected '(' in function signature\");\n        if (this.parser.getToken().isNot(_.Token.r_paren)) {\n            this.parseTypeAndAttrList(argTypes, argAttrs, argOperands);\n        }\n        this.parser.parseToken(_.Token.r_paren, \"expected ')' in function signature\");\n        if (this.parser.consumeIf(_.Token.arrow)) {\n            this.parseFunctionResultList(resultTypes, resultAttrs);\n        }\n        return { argTypes, argAttrs, resultTypes, resultAttrs };\n    }\n\n    parseFunctionSignatureWithArguments(allowVariadic) {\n        const argResult = this.parseFunctionArgumentList(allowVariadic);\n        const resultTypes = [];\n        const resultAttrs = [];\n        if (this.parser.consumeIf(_.Token.arrow)) {\n            this.parseFunctionResultList(resultTypes, resultAttrs);\n        }\n        return { arguments: argResult.arguments, isVariadic: argResult.isVariadic, resultTypes, resultAttrs };\n    }\n\n    parseFunctionResultList(types, attrs) {\n        if (this.parser.consumeIf(_.Token.l_paren)) {\n            if (this.parser.consumeIf(_.Token.r_paren)) {\n                return;\n            }\n            this.parseTypeAndAttrList(types, attrs);\n            this.parser.parseToken(_.Token.r_paren, \"expected ')' in function result list\");\n        } else {\n            const type = this.parseType();\n            types.push(type);\n            attrs.push(null);\n        }\n    }\n\n    // Returns { arguments: Array<OpAsmParser.Argument>, isVariadic: boolean }\n    parseFunctionArgumentList(allowVariadic) {\n        const inputs = [];\n        let isVariadic = false;\n        if (this.parser.consumeIf(_.Token.l_paren)) {\n            while (!this.parser.consumeIf(_.Token.r_paren)) {\n                if (this.parser.getToken().is(_.Token.r_paren)) {\n                    break;\n                }\n                if (allowVariadic && this.parser.consumeIf(_.Token.ellipsis)) {\n                    isVariadic = true;\n                    this.parser.parseToken(_.Token.r_paren, \"expected ')' after '...'\");\n                    break;\n                }\n                if (this.parser.getToken().is(_.Token.percent_identifier)) {\n                    const ssaName = this.parseOperand();\n                    this.parser.consumeToken(_.Token.colon);\n                    const type = this.parseType();\n                    let attrs = null;\n                    if (this.parser.getToken().is(_.Token.l_brace)) {\n                        attrs = new Map();\n                        this.parser.parseAttributeDict(attrs);\n                    }\n                    const loc = this.parseOptionalLocationSpecifier();\n                    inputs.push(new _.OpAsmParser.Argument(ssaName, type, attrs, loc));\n                } else {\n                    // Type-only argument (no explicit name like %arg0)\n                    // Don't generate a name - let the region/SSA system handle it\n                    const type = this.parseType();\n                    let attrs = null;\n                    if (this.parser.getToken().is(_.Token.l_brace)) {\n                        attrs = new Map();\n                        this.parser.parseAttributeDict(attrs);\n                    }\n                    inputs.push(new _.OpAsmParser.Argument(null, type, attrs, null));\n                }\n                if (this.parser.getToken().isNot(_.Token.r_paren)) {\n                    if (!this.parser.consumeIf(_.Token.comma)) {\n                        break;\n                    }\n                    if (this.parser.getToken().is(_.Token.r_paren)) {\n                        break;\n                    }\n                }\n            }\n        }\n        return { arguments: inputs, isVariadic };\n    }\n\n    parseTypeAndAttrList(types, attrs, operands) {\n        let index = 0;\n        this.parseCommaSeparatedList('none', () => {\n            const type = this.parseType();\n            types.push(type);\n            // Parse optional attribute dict after each type\n            if (this.parser.getToken().is(_.Token.l_brace)) {\n                const attrList = new Map();\n                this.parser.parseAttributeDict(attrList);\n                attrs.push(attrList);\n                // Associate attrs with operand if available\n                if (operands && index < operands.length) {\n                    operands[index].attributes = attrList;\n                }\n            } else {\n                attrs.push(null);\n            }\n            index++;\n            return true;\n        });\n    }\n\n    parseDenseI64ArrayAttr(attributeName, attributes) {\n        this.parseKeyword(attributeName);\n        this.parseEqual();\n        this.parseLSquare();\n        const values = [];\n        if (!this.parseOptionalRSquare()) {\n            do {\n                values.push(this.parseInteger());\n            } while (this.parseOptionalComma());\n            this.parseRSquare();\n        }\n        attributes.set(attributeName, new _.DenseI64ArrayAttr(values));\n    }\n\n    parseOptionalVisibilityKeyword(attributes) {\n        const visibility = this.parseOptionalKeyword(['public', 'private', 'nested']);\n        if (visibility) {\n            attributes.set('sym_visibility', visibility);\n        }\n    }\n\n    parseOperands(operands) {\n        this.parseCommaSeparatedList('none', () => {\n            operands.push(this.parseOperand());\n        });\n    }\n\n    parseShapedResultList(operands, operandTypes, resultTypes, tiedOperands, resolvedOperands) {\n        const indexType = new _.IndexType();\n        const tiedOperandIndices = [];\n        do {\n            let type = null;\n            let tiedOperandIndex = -1;\n            const tiedResult = this.parseOptionalOperand();\n            if (tiedResult) {\n                tiedOperandIndex = this.findTiedOperand(tiedResult, operands);\n                if (this.parseOptionalKeyword('as')) {\n                    type = this.parseType();\n                } else if (tiedOperandIndex >= 0 && tiedOperandIndex < operandTypes.length) {\n                    type = operandTypes[tiedOperandIndex];\n                }\n            } else {\n                type = this.parseType();\n            }\n            const dims = this.parseOperandList('optionalBrace');\n            if (resolvedOperands) {\n                this.resolveOperands(dims, dims.map(() => indexType), resolvedOperands);\n            }\n            if (type) {\n                resultTypes.push(type);\n            }\n            tiedOperandIndices.push(tiedOperandIndex);\n        } while (this.parseOptionalComma());\n        if (tiedOperands && tiedOperandIndices.length > 0) {\n            tiedOperands.push(...tiedOperandIndices);\n        }\n    }\n\n    findTiedOperand(tiedResult, operands) {\n        for (let i = 0; i < operands.length; i++) {\n            if (operands[i].name === tiedResult.name && operands[i].number === tiedResult.number) {\n                return i;\n            }\n        }\n        return -1;\n    }\n};\n\n_.OpAsmParser.Argument = class {\n\n    constructor(ssaName, type, attrs, loc) {\n        this.ssaName = ssaName;\n        this.type = type;\n        this.attrs = attrs;\n        this.loc = loc;\n    }\n\n    get name() {\n        return this.ssaName ? this.ssaName.name : null;\n    }\n\n    get value() {\n        return this.ssaName ? this.ssaName.toString() : null;\n    }\n};\n\n_.CustomOpAsmParser = class extends _.OpAsmParser {\n\n    constructor(resultIDs, parser) {\n        super();\n        this.resultIDs = resultIDs || [];\n        this.parser = parser;\n        this.nameLoc = parser.getToken().loc.copy();\n    }\n\n    parseOperation() {\n        return this.parser.parseOperation();\n    }\n\n    getNumResults() {\n        let count = 0;\n        for (const entry of this.resultIDs) {\n            count += entry[1];\n        }\n        return count;\n    }\n\n    getResultName(index) {\n        if (index < this.resultIDs.length) {\n            return this.resultIDs[index][0];\n        }\n        return null;\n    }\n\n    parseArgument(allowType, allowAttrs) {\n        const ssaName = this.parseOperand();\n        let type = null;\n        let attrs = null;\n        let loc = null;\n        if (allowType) {\n            type = this.parseColonType();\n        }\n        if (allowAttrs) {\n            attrs = {};\n            this.parseOptionalAttrDict(attrs);\n            if (Object.keys(attrs).length === 0) {\n                attrs = null;\n            }\n        }\n        loc = this.parseOptionalLocationSpecifier();\n        return new _.OpAsmParser.Argument(ssaName, type, attrs, loc);\n    }\n\n    parseOptionalArgument(allowType = false, allowAttrs = false) {\n        if (this.parser.getToken().is(_.Token.percent_identifier)) {\n            return this.parseArgument(allowType, allowAttrs);\n        }\n        return null;\n    }\n\n    parseArgumentList(delimiter, allowType = false, allowAttrs = false) {\n        delimiter = delimiter || 'none';\n        if (delimiter === 'none') {\n            if (this.parser.getToken().isNot(_.Token.percent_identifier)) {\n                return [];\n            }\n        }\n        const parseOneArgument = () => {\n            if (this.parser.getToken().is(_.Token.percent_identifier)) {\n                return this.parseArgument(allowType, allowAttrs);\n            }\n            return null;\n        };\n        return this.parseCommaSeparatedList(delimiter, parseOneArgument);\n    }\n\n    parseAssignmentList(lhs, rhs) {\n        const result = this.parseOptionalAssignmentList(lhs, rhs);\n        if (!result) {\n            throw new mlir.Error(`expected '(' ${this.parser.location()}`);\n        }\n    }\n\n    parseOptionalAssignmentList(lhs, rhs) {\n        if (!this.parseOptionalLParen()) {\n            return false;\n        }\n        if (!this.parseOptionalRParen()) {\n            do {\n                lhs.push(this.parseArgument());\n                this.parseEqual();\n                rhs.push(this.parseOperand());\n            } while (this.parseOptionalComma());\n            this.parseRParen();\n        }\n        return true;\n    }\n\n    parseRegion(region, entryArguments, enableNameShadowing) {\n        return this.parser.parseRegion(region, entryArguments, enableNameShadowing);\n    }\n\n    parseOptionalRegion(region, entryArguments, enableNameShadowing) {\n        if (this.parser.getToken().isNot(_.Token.l_brace)) {\n            region.blocks = region.blocks || [];\n            return false;\n        }\n        return this.parser.parseRegion(region, entryArguments, enableNameShadowing);\n    }\n\n    parseSuccessor() {\n        if (this.parser.getToken().isNot(_.Token.caret_identifier)) {\n            throw new mlir.Error(`expected block name ${this.parser.location()}`);\n        }\n        const label = this.parser.getTokenSpelling().str();\n        this.parser.consumeToken(_.Token.caret_identifier);\n        return { label };\n    }\n\n    parseOptionalSuccessor() {\n        if (this.parser.getToken().isNot(_.Token.caret_identifier)) {\n            return null;\n        }\n        return this.parseSuccessor();\n    }\n\n    parseSuccessorAndUseList() {\n        const successor = this.parseSuccessor();\n        if (this.parseOptionalLParen()) {\n            const operands = this.parseOperandList('none');\n            this.parseRParen();\n            successor.operands = operands;\n        }\n        return successor;\n    }\n\n    parseOperand(allowResultNumber = true) {\n        return this.parser.parseSSAUse(allowResultNumber);\n    }\n\n    parseOptionalOperand(allowResultNumber = true) {\n        if (this.parser.getToken().is(_.Token.percent_identifier)) {\n            return this.parseOperand(allowResultNumber);\n        }\n        return null;\n    }\n\n    parseOperandList(delimiter) {\n        delimiter = delimiter || 'none';\n        if (delimiter === 'none') {\n            if (this.parser.getToken().isNot(_.Token.percent_identifier)) {\n                return [];\n            }\n        }\n        const parseOneOperand = () => {\n            if (this.parser.getToken().is(_.Token.percent_identifier)) {\n                return this.parseOperand();\n            }\n            return null;\n        };\n        return this.parseCommaSeparatedList(delimiter, parseOneOperand);\n    }\n\n    parseTrailingOperandList(delimiter) {\n        if (!this.parseOptionalComma()) {\n            return [];\n        }\n        return this.parseOperandList(delimiter);\n    }\n\n    parseDimAndSymbolList(operands) {\n        const indexType = new _.IndexType();\n        const opInfos = this.parseOperandList('paren');\n        const numDims = opInfos.length;\n        const symInfos = this.parseOperandList('optionalSquare');\n        opInfos.push(...symInfos);\n        this.resolveOperands(opInfos, opInfos.map(() => indexType), operands);\n        return numDims;\n    }\n\n    resolveOperand(operand, type, result) {\n        const resolved = this.parser.resolveSSAUse(operand, type);\n        if (result) {\n            result.push(resolved);\n        }\n        return resolved;\n    }\n\n    resolveOperands(operands, types, result) {\n        if (!Array.isArray(operands)) {\n            throw new mlir.Error(`Unexpected operands type '${typeof operands}'.`);\n        }\n        if (!Array.isArray(types)) {\n            return;\n        }\n        const count = Math.min(operands.length, types.length);\n        if (result) {\n            for (let i = 0; i < count; i++) {\n                const operand = operands[i];\n                const type = types[i];\n                const resolved = this.parser.resolveSSAUse(operand, type);\n                result.push(resolved);\n            }\n        } else {\n            for (let i = 0; i < count; i++) {\n                const operand = operands[i];\n                const type = types[i];\n                if (operand && type) {\n                    if (operand instanceof _.Value) {\n                        operand.type = type;\n                    } else if (typeof operand === 'object') {\n                        operand.type = type;\n                    }\n                }\n            }\n        }\n    }\n\n    parseGenericOperation() {\n        return this.parser.parseGenericOperation();\n    }\n\n    parseCustomOperationName() {\n        return this.parser.parseCustomOperationName();\n    }\n\n    parseOptionalLocationSpecifier() {\n        // Ref impl: CustomOpAsmParser::parseOptionalLocationSpecifier (Parser.cpp:2002)\n        // Separate implementation from parseTrailingLocationSpecifier\n        // If there is a 'loc' we parse a trailing location.\n        if (!this.parser.consumeIf(_.Token.kw_loc)) {\n            return null;\n        }\n        this.parser.parseToken(_.Token.l_paren, \"expected '(' in location\");\n        const tok = this.parser.getToken();\n        let directLoc = null;\n        // Check to see if we are parsing a location alias. We are parsing a\n        // location alias if the token is a hash identifier *without* a dot in it -\n        // the dot signifies a dialect attribute. Otherwise, we parse the location\n        // directly.\n        if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {\n            directLoc = this.parser.parseLocationAlias();\n        } else {\n            directLoc = this.parser.parseLocationInstance();\n        }\n        this.parser.parseToken(_.Token.r_paren, \"expected ')' in location\");\n        return directLoc;\n    }\n};\n\n_.DialectAsmParser = class extends _.AsmParser {\n};\n\n_.CustomDialectAsmParser = class extends _.DialectAsmParser {\n\n    constructor(fullSpec, parser) {\n        super();\n        this.fullSpec = fullSpec;\n        this.parser = parser;\n        this.nameLoc = parser.getToken().loc.copy();\n    }\n};\n\n_.TensorLiteralParser = class {\n\n    constructor(parser) {\n        this._parser = parser;\n        // Reference stores pairs of (isNegative, token) for proper type validation\n        // We store {isNegative, value, kind} objects\n        this._storage = [];\n        this._shape = [];\n        this._hexStorage = null;\n    }\n\n    parse(allowHex) {\n        if (allowHex && this._parser.getToken().is(_.Token.string)) {\n            const hexStr = this._parser.getToken().getStringValue();\n            this._parser.consumeToken(_.Token.string);\n            if (hexStr.startsWith('0x')) {\n                const cleanHex = hexStr.substring(2);\n                const data = new Uint8Array(cleanHex.length >> 1);\n                for (let i = 0; i < data.length; i++) {\n                    const index = i << 1;\n                    data[i] = parseInt(cleanHex.substring(index, index + 2), 16);\n                }\n                this._hexStorage = data;\n                return { storage: data, shape: null };\n            }\n            // Non-hex string element\n            this._storage.push({ isNegative: false, value: hexStr, kind: 'string' });\n            return { storage: this._storage, shape: this._shape };\n        }\n        if (this._parser.getToken().is(_.Token.l_square)) {\n            this.parseList(this._shape);\n        } else {\n            this.parseElement();\n            // Single element parsed without list - shape stays empty (splat)\n        }\n        return { storage: this._storage, shape: this._shape };\n    }\n\n    parseList(dims) {\n        this._parser.consumeToken(_.Token.l_square);\n        let first = true;\n        let newDims = [];\n        let size = 0;\n        while (!this._parser.consumeIf(_.Token.r_square)) {\n            const thisDims = [];\n            if (this._parser.getToken().is(_.Token.l_square)) {\n                this.parseList(thisDims);\n            } else {\n                this.parseElement();\n            }\n            size++;\n            if (!first) {\n                const compareDims = (a, b) =>{\n                    if (a.length !== b.length) {\n                        return false;\n                    }\n                    for (let i = 0; i < a.length; i++) {\n                        if (a[i] !== b[i]) {\n                            return false;\n                        }\n                    }\n                    return true;\n                };\n                // Verify consistent dimensions (reference checks prevDims == newDims)\n                const dimsMatch = compareDims(thisDims, newDims);\n                if (!dimsMatch) {\n                    throw new mlir.Error(`Tensor literal is invalid; ranks are not consistent between elements ${this._parser.location()}`);\n                }\n            }\n            newDims = thisDims;\n            first = false;\n            this._parser.consumeIf(_.Token.comma);\n        }\n        dims.length = 0;\n        dims.push(size);\n        dims.push(...newDims);\n    }\n\n    parseElement() {\n        switch (this._parser.getToken().kind) {\n            // Parse a boolean element.\n            case _.Token.kw_true:\n            case _.Token.kw_false: {\n                const value = this._parser.getTokenSpelling().str();\n                this._parser.consumeToken(this._parser.getToken().kind);\n                this._storage.push({ isNegative: false, value, kind: 'boolean' });\n                break;\n            }\n            case _.Token.floatliteral:\n            case _.Token.integer: {\n                const value = this._parser.getTokenSpelling().str();\n                const kind = this._parser.getToken().kind === _.Token.floatliteral ? 'float' : 'int';\n                this._parser.consumeToken(this._parser.getToken().kind);\n                this._storage.push({ isNegative: false, value, kind });\n                break;\n            }\n            case _.Token.minus: {\n                this._parser.consumeToken(_.Token.minus);\n                if (!this._parser.getToken().isAny(_.Token.floatliteral, _.Token.integer)) {\n                    throw new mlir.Error(`Expected integer or floating point literal ${this._parser.location()}`);\n                }\n                const value = this._parser.getTokenSpelling().str();\n                const kind = this._parser.getToken().kind === _.Token.floatliteral ? 'float' : 'int';\n                this._parser.consumeToken(this._parser.getToken().kind);\n                this._storage.push({ isNegative: true, value, kind });\n                break;\n            }\n            case _.Token.string: {\n                const value = this._parser.getToken().getStringValue();\n                this._parser.consumeToken(_.Token.string);\n                this._storage.push({ isNegative: false, value, kind: 'string' });\n                break;\n            }\n            case _.Token.l_paren:\n                this._parser.consumeToken(_.Token.l_paren);\n                this.parseElement();\n                this._parser.parseToken(_.Token.comma, \"expected ',' between complex elements\");\n                this.parseElement();\n                this._parser.parseToken(_.Token.r_paren, \"expected ')' after complex elements\");\n                break;\n            default:\n                throw new mlir.Error(`Expected element literal of primitive type ${this._parser.location()}`);\n        }\n    }\n\n    getShape() {\n        return this._shape;\n    }\n\n    getAttr(type) {\n        // Handle hex storage directly\n        if (this._hexStorage instanceof Uint8Array) {\n            return this._hexStorage;\n        }\n        const elementType = type && type.elementType ? type.elementType : null;\n        const numElements = type && type.getNumElements ? type.getNumElements().toNumber() : 0;\n        const isComplex = elementType instanceof _.ComplexType;\n        const baseElemType = isComplex && elementType.elementType ? elementType.elementType : elementType;\n\n        // Determine element type properties for validation\n        let isUnsigned = false;\n        let isInteger = false;\n        let isI1 = false;\n        let bitWidth = 0;\n        if (baseElemType) {\n            const typeStr = baseElemType.toString();\n            isUnsigned = typeStr.startsWith('ui');\n            isI1 = typeStr === 'i1';\n            const intMatch = typeStr.match(/^[su]?i(\\d+)$/);\n            if (intMatch) {\n                isInteger = true;\n                bitWidth = parseInt(intMatch[1], 10);\n            } else if (typeStr === 'index') {\n                isInteger = true;\n                bitWidth = 64;\n            }\n        }\n\n        // Validate and convert storage elements\n        const convertElement = (elem) => {\n            const { isNegative, value, kind } = elem;\n\n            if (isNegative && isUnsigned) {\n                throw new mlir.Error(`Expected unsigned integer elements, but parsed negative value`);\n            }\n\n            if (kind === 'boolean') {\n                if (isInteger && !isI1) {\n                    throw new mlir.Error(`Expected i1 type for 'true' or 'false' values`);\n                }\n                return value === true || value === 'true' ? 1 : 0;\n            }\n            if (kind === 'float' && isInteger) {\n                throw new mlir.Error(`Expected integer elements, but parsed floating-point`);\n            }\n            let result = null;\n            if (kind === 'int') {\n                if (bitWidth >= 64) {\n                    result = BigInt(value);\n                    if (isNegative) {\n                        result = -result;\n                    }\n                } else {\n                    result = parseInt(value, 10);\n                    if (isNegative) {\n                        result = -result;\n                    }\n                }\n            } else if (kind === 'float') {\n                result = parseFloat(value);\n                if (isNegative) {\n                    result = -result;\n                }\n            } else {\n                result = value;\n            }\n            return result;\n        };\n\n        // Handle zero-element tensors (e.g., tensor<2x0x3xi4>)\n        if (numElements === 0) {\n            return [];\n        }\n\n        // Limit splat expansion to avoid memory issues with huge tensors\n        const maxSplatExpansion = 10000000;\n\n        // Handle splats - Reference: if shape.empty() and storage has elements, it's a splat\n        const isSplat = this._shape.length === 0 && this._storage.length > 0;\n        if (isSplat && numElements > 1) {\n            if (numElements > maxSplatExpansion) {\n                // Too large to expand - return null to indicate we can't provide the data\n                return null;\n            }\n            if (isComplex && this._storage.length === 2) {\n                // Complex splat: storage has 2 elements (real, imag)\n                const result = [];\n                const real = convertElement(this._storage[0]);\n                const imag = convertElement(this._storage[1]);\n                for (let i = 0; i < numElements; i++) {\n                    result.push(new base.Complex(real, imag));\n                }\n                return result;\n            }\n            // Regular splat: replicate single value\n            const converted = convertElement(this._storage[0]);\n            return new Array(numElements).fill(converted);\n        }\n\n        // Non-splat complex: convert pairs to base.Complex objects\n        if (isComplex && Array.isArray(this._storage)) {\n            const result = [];\n            for (let i = 0; i < this._storage.length; i += 2) {\n                result.push(new base.Complex(convertElement(this._storage[i]), convertElement(this._storage[i + 1])));\n            }\n            return result;\n        }\n\n        return this._storage.map(convertElement);\n    }\n};\n\n_.EncodingReader = class {\n\n    constructor(data) {\n        if (data instanceof Uint8Array) {\n            this._data = data;\n            this._reader = base.BinaryReader.open(data);\n        } else {\n            this._data = null;\n            this._reader = data;\n        }\n    }\n\n    get length() {\n        return this._reader.length;\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    empty() {\n        return this.position >= this.length;\n    }\n\n    size() {\n        return this._reader.length - this._reader.position;\n    }\n\n    seek(offset) {\n        this._reader.seek(offset);\n    }\n\n    skipBytes(length) {\n        this._reader.skip(length);\n    }\n\n    parseBytes(length) {\n        return this._reader.read(length);\n    }\n\n    parseByte() {\n        return this._reader.byte();\n    }\n\n    peek() {\n        const position = this._reader.position;\n        const value = this._reader.byte();\n        this._reader.seek(position);\n        return value;\n    }\n\n    parseVarInt() {\n        let result = this._reader.byte();\n        if (result & 1) {\n            return BigInt(result >> 1);\n        }\n        if (result === 0) {\n            return this._reader.uint64();\n        }\n        result = BigInt(result);\n        let mask = 1n;\n        let numBytes = 0n;\n        let shift = 8n;\n        while (result > 0n && (result & mask) === 0n) {\n            if (numBytes >= 7n) {\n                throw new mlir.Error('Invalid varint.');\n            }\n            result |= (BigInt(this._reader.byte()) << shift);\n            mask <<= 1n;\n            shift += 8n;\n            numBytes++;\n        }\n        if (numBytes === 0n || numBytes > 7n) {\n            throw new mlir.Error(`Invalid varint.`);\n        }\n        result >>= numBytes + 1n;\n        return result;\n    }\n\n    parseSignedVarInt() {\n        const n = this.parseVarInt();\n        return (n >> 1n) ^ -(n & 1n);\n    }\n\n    parseVarIntWithFlag() {\n        const result = this.parseVarInt();\n        return [result >> 1n, (result & 1n) === 1n];\n    }\n\n    parseNullTerminatedString() {\n        const reader = this._reader;\n        let result = '';\n        let value = -1;\n        const maxLength = reader.length - reader.position;\n        let bytesRead = 0;\n        for (; ;) {\n            if (bytesRead >= maxLength) {\n                throw new mlir.Error('Malformed null-terminated string, no null character found.');\n            }\n            value = reader.byte();\n            bytesRead++;\n            if (value === 0x00) {\n                break;\n            }\n            result += String.fromCharCode(value);\n        }\n        return result;\n    }\n\n    parseEntry(entries, entryStr) {\n        const entryIdx = this.parseVarInt().toNumber();\n        return this.resolveEntry(entries, entryIdx, entryStr);\n    }\n\n    resolveEntry(entries, entryIdx, entryStr) {\n        if (entryIdx >= entries.length) {\n            throw new mlir.Error(`Invalid '${entryStr}' index.`);\n        }\n        return entries[entryIdx];\n    }\n\n    parseSection(alignmentValidator) {\n        const sectionIDAndHasAlignment = this.parseByte();\n        const length = this.parseVarInt().toNumber();\n        const sectionID = sectionIDAndHasAlignment & 0x7F;\n        const hasAlignment = sectionIDAndHasAlignment & 0x80;\n        if (sectionID >= 9) { // kNumSections\n            throw new mlir.Error(`Invalid section ID: ${sectionID}.`);\n        }\n        if (hasAlignment) {\n            const alignment = this.parseVarInt().toNumber();\n            alignmentValidator(alignment);\n            this.alignTo(alignment);\n        }\n        const sectionData = this.parseBytes(length);\n        return [sectionID, sectionData];\n    }\n\n    parseBlobAndAlignment() {\n        const alignment = this.parseVarInt().toNumber();\n        const dataSize = this.parseVarInt().toNumber();\n        this.alignTo(alignment);\n        const data = this.parseBytes(dataSize);\n        return [data, alignment];\n    }\n\n    alignTo(alignment) {\n        if ((alignment & (alignment - 1)) !== 0) {\n            throw new mlir.Error('Expected alignment to be a power-of-two.');\n        }\n        while ((this.position & (alignment - 1)) !== 0) {\n            const padding = this.parseByte();\n            if (padding !== 0xCB) {\n                throw new mlir.Error(`Expected alignment byte (0xCB), but got: 0x${padding.toString(16)}.`);\n            }\n        }\n    }\n};\n\n_.BytecodeDialect = class {\n\n    load(reader, ctx) {\n        this.dialect = ctx.getOrLoadDialect(this.name);\n        if (!this.dialect) {\n            throw new mlir.Error(`Dialect '${this.name}' is unknown.`);\n        }\n        this.interface = this.dialect;\n        if (this.versionBuffer) {\n            const encReader = new _.EncodingReader(this.versionBuffer, reader.loc);\n            const versionReader = reader.withEncodingReader(encReader);\n            const loadedVersion = this.interface.readVersion(versionReader);\n            if (!loadedVersion) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    getLoadedDialect() {\n        return this.dialect;\n    }\n};\n\n_.DialectBytecodeReader = class {\n};\n\n_.DialectReader = class extends _.DialectBytecodeReader {\n\n    constructor(attrTypeReader, stringReader, resourceReader, dialectsMap, reader, bytecodeVersion, depth = 0) {\n        super();\n        this.attrTypeReader = attrTypeReader;\n        this.stringReader = stringReader;\n        this.resourceReader = resourceReader;\n        this.dialectsMap = dialectsMap;\n        this.reader = reader;\n        this.bytecodeVersion = bytecodeVersion;\n        this.depth = depth;\n        this._floatBuffer = new ArrayBuffer(8);\n        this._floatView = new DataView(this._floatBuffer);\n        this._floatBitWidths = { f16: 16, bf16: 16, f32: 32, f64: 64, f80: 80, f128: 128, tf32: 19, f4E2M1FN: 4, f6E2M3FN: 6, f6E3M2FN: 6, f8E5M2: 8, f8E4M3: 8, f8E4M3FN: 8, f8E5M2FNUZ: 8, f8E4M3FNUZ: 8, f8E4M3B11FNUZ: 8, f8E3M4: 8, f8E8M0FNU: 8 };\n    }\n\n    readType() {\n        const index = this.reader.parseVarInt().toNumber();\n        if (this.attrTypeReader.isResolving() && this.depth > this.maxAttrTypeDepth) {\n            const existing = this.attrTypeReader.getTypeOrSentinel(index);\n            if (!existing) {\n                throw new mlir.Error(`Exceeded maximum type depth at '${index}'.`);\n            }\n            return existing;\n        }\n        return this.attrTypeReader.readType(index, this.depth + 1);\n    }\n\n    readAttribute() {\n        const index = this.reader.parseVarInt().toNumber();\n        if (this.attrTypeReader.isResolving() && this.depth > this.maxAttrTypeDepth) {\n            const existing = this.attrTypeReader.getAttributeOrSentinel(index);\n            if (!existing) {\n                throw new mlir.Error(`Exceeded maximum attribute depth at '${index}'.`);\n            }\n            return existing;\n        }\n        return this.attrTypeReader.readAttribute(index, this.depth + 1);\n    }\n\n    readString() {\n        return this.stringReader.parseString(this.reader);\n    }\n\n    readVarInt() {\n        return this.reader.parseVarInt().toNumber();\n    }\n\n    readSignedVarInt() {\n        return this.reader.parseSignedVarInt();\n    }\n\n    readByte() {\n        return this.reader.parseByte();\n    }\n\n    readBlob() {\n        const size = this.reader.parseVarInt().toNumber();\n        return this.reader.parseBytes(size);\n    }\n\n    readResourceHandle() {\n        return this.resourceReader.parseResourceHandle(this.reader);\n    }\n\n    readSignedVarInts() {\n        const count = this.reader.parseVarInt().toNumber();\n        const result = new Array(count);\n        for (let i = 0; i < count; i++) {\n            result[i] = this.reader.parseSignedVarInt();\n        }\n        return result;\n    }\n\n    readAPIntWithKnownWidth(bitWidth) {\n        if (bitWidth <= 8) {\n            return BigInt(this.reader.parseByte());\n        }\n        if (bitWidth <= 64) {\n            return this.reader.parseSignedVarInt();\n        }\n        const numWords = this.reader.parseVarInt().toNumber();\n        let value = 0n;\n        for (let i = 0; i < numWords; i++) {\n            const word = this.reader.parseSignedVarInt();\n            value |= (word << BigInt(i * 64));\n        }\n        return value;\n    }\n\n    readAPFloatWithKnownSemantics(type) {\n        const bitWidth = this._floatBitWidths[type.name];\n        if (!bitWidth) {\n            throw new mlir.Error(`Unsupported float type '${type.name}'.`);\n        }\n        const bits = this.readAPIntWithKnownWidth(bitWidth);\n        if (bitWidth <= 32) {\n            this._floatView.setUint32(0, Number(bits), true);\n        } else {\n            this._floatView.setBigUint64(0, bits, true);\n        }\n        switch (type.name) {\n            case 'f16': return this._floatView.getFloat16(0, true);\n            case 'f32': return this._floatView.getFloat32(0, true);\n            case 'f64': return this._floatView.getFloat64(0, true);\n            case 'bf16': return this._floatView.getBfloat16(0, true);\n            default: throw new mlir.Error(`Unsupported float type '${type.name}'.`);\n        }\n    }\n\n    withEncodingReader(encodingReader) {\n        return new _.DialectReader(this.attrTypeReader, this.stringReader, this.resourceReader, this.dialectsMap, encodingReader, this.bytecodeVersion, this.depth);\n    }\n};\n\n_.AttrTypeReader = class {\n\n    constructor(stringReader, resourceReader, dialectsMap, bytecodeVersion, fileLoc, config) {\n        this.stringReader = stringReader;\n        this.resourceReader = resourceReader;\n        this.dialectsMap = dialectsMap;\n        this.fileLoc = fileLoc;\n        this.bytecodeVersion = bytecodeVersion;\n        this.parserConfig = config;\n        this.attributes = [];\n        this.types = [];\n        this.maxAttrTypeDepth = 5;\n        this._resolving = false;\n    }\n\n    initialize(dialects, sectionData, offsetSectionData) {\n        this._sectionData = sectionData;\n        const offsetReader = new _.EncodingReader(offsetSectionData);\n        const numAttributes = offsetReader.parseVarInt().toNumber();\n        const numTypes = offsetReader.parseVarInt().toNumber();\n        this.attributes = new Array(numAttributes);\n        this.types = new Array(numTypes);\n        let currentOffset = 0;\n        const parseEntries = (entries) => {\n            let currentIndex = 0;\n            const endIndex = entries.length;\n            while (currentIndex < endIndex) {\n                const dialectIndex = offsetReader.parseVarInt().toNumber();\n                const dialect = dialects[dialectIndex];\n                const numEntries = offsetReader.parseVarInt().toNumber();\n                for (let i = 0; i < numEntries; i++) {\n                    const entry = {};\n                    const entrySizeWithFlag = offsetReader.parseVarInt();\n                    entry.hasCustomEncoding = (entrySizeWithFlag & 1n) === 1n;\n                    const entrySize = (entrySizeWithFlag >> 1n).toNumber();\n                    // Store offset like old code (don't bound reading to entry size)\n                    entry.offset = currentOffset;\n                    entry.size = entrySize;\n                    entry.dialect = dialect;\n                    entry.resolved = null;\n                    currentOffset += entrySize;\n                    entries[currentIndex++] = entry;\n                }\n            }\n        };\n\n        // Process attributes, then types\n        parseEntries(this.attributes);\n        parseEntries(this.types);\n    }\n\n    isResolving() {\n        return this._resolving;\n    }\n\n    getAttributeOrSentinel(index) {\n        if (index >= this.attributes.length) {\n            return null;\n        }\n        return this.attributes[index].resolved;\n    }\n\n    getTypeOrSentinel(index) {\n        if (index >= this.types.length) {\n            return null;\n        }\n        return this.types[index].resolved;\n    }\n\n    readAttribute(index, depth = 0) {\n        return this.readEntry(this.attributes, index, 'attr', depth);\n    }\n\n    readType(index, depth = 0) {\n        return this.readEntry(this.types, index, 'type', depth);\n    }\n\n    resolveAttribute(index, depth = 0) {\n        // Resolve an attribute at the given index (equivalent to resolveEntry in C++)\n        return this.resolveEntry(this.attributes, index, 'attr', depth);\n    }\n\n    resolveType(index, depth = 0) {\n        // Resolve a type at the given index (equivalent to resolveEntry in C++)\n        return this.resolveEntry(this.types, index, 'type', depth);\n    }\n\n    parseAttribute(reader) {\n        // Parse an attribute reference from the reader (varint index)\n        const index = reader.parseVarInt().toNumber();\n        return this.resolveAttribute(index);\n    }\n\n    parseType(reader) {\n        // Parse a type reference from the reader (varint index)\n        const index = reader.parseVarInt().toNumber();\n        return this.resolveType(index);\n    }\n\n    resolveEntry(entries, index, entryType, depth = 0) {\n        // Simplified version of C++ resolveEntry - doesn't handle deferred worklists\n        // but does track recursion depth\n        const oldResolving = this._resolving;\n        this._resolving = true;\n        try {\n            const result = this.readEntry(entries, index, entryType, depth);\n            return result;\n        } finally {\n            this._resolving = oldResolving;\n        }\n    }\n\n    readEntry(entries, index, entryType, depth = 0) {\n        if (index >= entries.length) {\n            throw new mlir.Error(`Invalid '${entryType}' index '${index}'.`);\n        }\n        const entry = entries[index];\n        if (entry.resolved !== null) {\n            return entry.resolved;\n        }\n        if (depth > this.maxAttrTypeDepth) {\n            throw new mlir.Error(`Exceeded maximum '${entryType}' depth.`);\n        }\n        entry.resolved = { name: 'pending', value: `<${entryType} ${index}>` };\n        const entryData = this._sectionData.subarray(entry.offset, entry.offset + entry.size);\n        const reader = new _.EncodingReader(entryData);\n        const startPosition = reader.position;\n        if (entry.hasCustomEncoding) {\n            entry.resolved = this.parseCustomEntry(entry, reader, entryType, index, depth);\n        } else {\n            entry.resolved = this.parseAsmEntry(reader, entryType);\n        }\n        const bytesRead = reader.position - startPosition;\n        if (bytesRead > entry.size) {\n            throw new mlir.Error(`Read ${bytesRead} bytes but entry size is ${entry.size} bytes.`);\n        }\n        return entry.resolved;\n    }\n\n    parseCustomEntry(entry, reader, entryType, index, depth) {\n        // Lazy load the dialect interface (like BytecodeDialect::load)\n        const context = this.fileLoc.context;\n        if (entry.dialect.interface === undefined) {\n            entry.dialect.interface = context.getOrLoadDialect(entry.dialect.name);\n        }\n        context.checkDialect(entry.dialect.interface, entry.dialect.name, 'custom entry');\n        const dialect = entry.dialect.interface;\n        const dialectReader = new _.DialectReader(this, this.stringReader, this.resourceReader, this.dialectsMap, reader, this.bytecodeVersion, depth);\n        switch (entryType) {\n            case 'type':\n                return dialect.readType(dialectReader);\n            case 'attr':\n                return dialect.readAttribute(dialectReader);\n            default:\n                throw new mlir.Error(`Unknown entry type '${entryType}'.`);\n        }\n    }\n\n    parseAsmEntry(reader, entryType) {\n        const asmStr = reader.parseNullTerminatedString();\n        const context = this.fileLoc.context;\n        if (entryType === 'type') {\n            const { type, numRead } = _.Parser.parseType(asmStr, context);\n            if (!type || numRead !== asmStr.length) {\n                throw new mlir.Error(`Failed to parse type '${asmStr}'.`);\n            }\n            return type;\n        }\n        const { attribute, numRead } = _.Parser.parseAttribute(asmStr, context, null);\n        if (!attribute || numRead !== asmStr.length) {\n            throw new mlir.Error(`Failed to parse attribute '${asmStr}'.`);\n        }\n        return attribute;\n    }\n};\n\n_.StringSectionReader = class {\n\n    initialize(sectionData) {\n        const decoder = new TextDecoder('utf-8');\n        const stringReader = new _.EncodingReader(sectionData);\n        const numStrings = stringReader.parseVarInt().toNumber();\n        this.strings = new Array(numStrings);\n        let stringDataEndOffset = sectionData.length;\n        for (let i = numStrings - 1; i >= 0; i--) {\n            const stringSize = stringReader.parseVarInt().toNumber();\n            if (stringDataEndOffset < stringSize) {\n                throw new mlir.Error('String size exceeds the available data size.');\n            }\n            const stringOffset = stringDataEndOffset - stringSize;\n            const buffer = sectionData.subarray(stringOffset, stringOffset + stringSize - 1);\n            this.strings[i] = decoder.decode(buffer);\n            stringDataEndOffset = stringOffset;\n        }\n        if ((sectionData.length - stringReader.size()) !== stringDataEndOffset) {\n            throw new mlir.Error('Unexpected trailing data between the offsets for strings and their data.');\n        }\n    }\n\n    parseString(reader) {\n        return reader.parseEntry(this.strings, 'string');\n    }\n\n    parseStringWithFlag(reader) {\n        const [entryIdx, flag] = reader.parseVarIntWithFlag();\n        const str = this.parseStringAtIndex(reader, entryIdx.toNumber());\n        return [str, flag];\n    }\n\n    parseStringAtIndex(reader, index) {\n        if (index >= this.strings.length) {\n            throw new mlir.Error('Invalid string index.');\n        }\n        return this.strings[index];\n    }\n};\n\n_.PropertiesSectionReader = class {\n\n    constructor() {\n        this._properties = new Map();\n    }\n\n    initialize(sectionData) {\n        const reader = new _.EncodingReader(sectionData);\n        const count = reader.parseVarInt().toNumber();\n        this._properties = new Array(count);\n        for (let i = 0; i < this._properties.length; i++) {\n            const size = reader.parseVarInt().toNumber();\n            const data = reader.parseBytes(size);\n            this._properties[i] = data;\n        }\n    }\n\n    read(fileLoc, dialectReader, opName, opState) {\n        const propIdx = dialectReader.readVarInt();\n        if (propIdx < this._properties.length) {\n            const propData = this._properties[propIdx];\n            if (propData.length > 0) {\n                const propReader = dialectReader.withEncodingReader(new _.EncodingReader(propData));\n                // Reference: https://github.com/llvm/llvm-project/blob/main/mlir/lib/Bytecode/Reader/BytecodeReader.cpp\n                // Function operations: sym_name (required), function_type (required), arg_attrs (optional), res_attrs (optional)\n                if (opName.getStringRef().endsWith('.func') || /\\.func_v\\d+$/.test(opName.getStringRef())) {\n                    if (propReader.reader.position < propData.length) {\n                        const symNameAttr = propReader.readAttribute();\n                        if (symNameAttr && symNameAttr.value !== undefined) {\n                            const name = typeof symNameAttr.value === 'string' ? symNameAttr.value : String(symNameAttr.value);\n                            opState.addAttribute('sym_name', new _.StringAttr(name));\n                        }\n                    }\n                    if (propReader.reader.position < propData.length) {\n                        const funcTypeAttr = propReader.readAttribute();\n                        if (funcTypeAttr instanceof _.TypeAttrOf && funcTypeAttr.type instanceof _.FunctionType) {\n                            opState.addAttribute('function_type', funcTypeAttr);\n                        }\n                    }\n                    if (propReader.reader.position < propData.length) {\n                        const argAttrs = propReader.readAttribute();\n                        if (argAttrs) {\n                            opState.addAttribute('arg_attrs', argAttrs);\n                        }\n                    }\n                    if (propReader.reader.position < propData.length) {\n                        const resAttrs = propReader.readAttribute();\n                        if (resAttrs) {\n                            opState.addAttribute('res_attrs', resAttrs);\n                        }\n                    }\n                    return;\n                }\n                if (opName.getStringRef().includes('.constant') || opName.getStringRef().endsWith('.const')) {\n                    if (propReader.reader.position < propData.length) {\n                        const attr = propReader.readAttribute();\n                        if (attr !== null && attr !== undefined) {\n                            opState.addAttribute('value', attr);\n                        }\n                    }\n                }\n            }\n        }\n    }\n};\n\n_.AsmResourceEntryKind = {\n    Blob: 0,\n    Bool: 1,\n    String: 2\n};\n\n_.ParsedResourceEntry.Bytecode = class {\n\n    constructor(key, kind, reader, stringReader) {\n        this.key = key;\n        this.kind = kind;\n        this.reader = reader;\n        this.stringReader = stringReader;\n    }\n\n    parseAsBlob() {\n        if (this.kind === _.AsmResourceEntryKind.Blob) {\n            const [data] = this.reader.parseBlobAndAlignment();\n            return data;\n        }\n        return null;\n    }\n};\n\n_.ResourceSectionReader = class {\n\n    constructor() {\n        this.dialectResources = [];\n        this.dialectResourceHandleRenamingMap = new Map();\n    }\n\n    initialize(fileLoc, config, dialects, stringReader, sectionData, offsetSectionData, dialectReader) {\n        const resourceReader = new _.EncodingReader(sectionData);\n        const offsetReader = new _.EncodingReader(offsetSectionData);\n        const numExternalResourceGroups = offsetReader.parseVarInt().toNumber();\n        const parseGroup = (handler, allowEmpty = false, processKeyFn = null) => {\n            const resolveKey = (key) => {\n                const remapped = this.dialectResourceHandleRenamingMap.get(key);\n                return remapped === undefined ? key : remapped;\n            };\n            return this.parseResourceGroup(fileLoc, allowEmpty, offsetReader, resourceReader, stringReader, handler, resolveKey, processKeyFn);\n        };\n        for (let i = 0; i < numExternalResourceGroups; i++) {\n            const key = stringReader.parseString(offsetReader);\n            const handler = config && config.getResourceParser ? config.getResourceParser(key) : null;\n            if (!parseGroup(handler)) {\n                return false;\n            }\n        }\n        const ctx = fileLoc.context;\n        while (!offsetReader.empty()) {\n            const dialect = offsetReader.parseEntry(dialects, \"dialect\");\n            dialect.load(dialectReader, ctx);\n            const handler = dialect.getLoadedDialect();\n            if (!handler) {\n                throw new mlir.Error(`Unknown dialect '${dialect.name}'.`);\n            }\n            const processResourceKeyFn = (key) => {\n                const handle = handler.declareResource(key);\n                if (!handle) {\n                    throw new mlir.Error(`Unknown 'resource' key '${key}' for dialect '${dialect.name}'.`);\n                }\n                this.dialectResourceHandleRenamingMap.set(key, handler.getResourceKey(handle));\n                this.dialectResources.push(handler);\n                return true;\n            };\n            if (!parseGroup(handler, true, processResourceKeyFn)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    parseResourceGroup(fileLoc, allowEmpty, offsetReader, resourceReader, stringReader, handler, remapKey, processKeyFn) {\n        const numResources = offsetReader.parseVarInt().toNumber();\n        for (let i = 0; i < numResources; i++) {\n            const key = stringReader.parseString(offsetReader);\n            const resourceOffset = offsetReader.parseVarInt().toNumber();\n            const kind = offsetReader.parseByte();\n            const data = resourceReader.parseBytes(resourceOffset);\n            if (processKeyFn && !processKeyFn(key)) {\n                return false;\n            }\n            if (allowEmpty && data.length === 0) {\n                continue;\n            }\n            const entryReader = new _.EncodingReader(data);\n            const resolvedKey = remapKey ? remapKey(key) : key;\n            const entry = new _.ParsedResourceEntry.Bytecode(resolvedKey, kind, entryReader, stringReader);\n            if (!handler) {\n                continue;\n            }\n            handler.parseResource(entry);\n            if (!entryReader.empty()) {\n                throw new mlir.Error(`Unexpected trailing bytes in resource entry '${resolvedKey}'.`);\n            }\n        }\n        return true;\n    }\n\n    parseResourceHandle(reader) {\n        return reader.parseEntry(this.dialectResources, \"resource handle\");\n    }\n};\n\n_.Location = class {\n\n    constructor(context) {\n        this.context = context;\n    }\n};\n\n_.LocationAttr = class {\n\n    constructor() {\n        this.name = 'loc';\n    }\n\n    get value() {\n        return 'unknown';\n    }\n};\n\n_.UnknownLoc = class extends _.LocationAttr {\n\n    get value() {\n        return 'unknown';\n    }\n};\n\n_.FileLineColLoc = class extends _.LocationAttr {\n\n    constructor(filename, line, col) {\n        super();\n        this.filename = filename;\n        this.line = line;\n        this.col = col;\n    }\n\n    get value() {\n        return `${this.filename}:${this.line}:${this.col}`;\n    }\n};\n\n_.FileLineColRange = class extends _.LocationAttr {\n\n    constructor(filename, startLine, startCol, endLine, endCol) {\n        super();\n        this.filename = filename;\n        this.startLine = startLine;\n        this.startCol = startCol;\n        this.endLine = endLine;\n        this.endCol = endCol;\n    }\n\n    get value() {\n        if (this.endLine !== undefined && this.endCol !== undefined) {\n            return `${this.filename}:${this.startLine}:${this.startCol} to ${this.endLine}:${this.endCol}`;\n        }\n        if (this.endCol !== undefined) {\n            return `${this.filename}:${this.startLine}:${this.startCol} to :${this.endCol}`;\n        }\n        if (this.startCol !== undefined) {\n            return `${this.filename}:${this.startLine}:${this.startCol}`;\n        }\n        return `${this.filename}:${this.startLine}`;\n    }\n};\n\n_.NameLoc = class extends _.LocationAttr {\n\n    constructor(name, childLoc) {\n        super();\n        this._name = name;\n        this.childLoc = childLoc;\n    }\n\n    get value() {\n        if (this.childLoc) {\n            const childStr = this.childLoc.value || this.childLoc;\n            return `\"${this._name}\"(${childStr})`;\n        }\n        return `\"${this._name}\"`;\n    }\n};\n\n_.CallSiteLoc = class extends _.LocationAttr {\n\n    constructor(callee, caller) {\n        super();\n        this.callee = callee;\n        this.caller = caller;\n    }\n\n    get value() {\n        const calleeStr = this.callee && this.callee.value ? this.callee.value : this.callee;\n        const callerStr = this.caller && this.caller.value ? this.caller.value : this.caller;\n        return `callsite(${calleeStr} at ${callerStr})`;\n    }\n};\n\n_.FusedLoc = class extends _.LocationAttr {\n\n    constructor(locations, metadata) {\n        super();\n        this.locations = locations;\n        this.metadata = metadata;\n    }\n\n    get value() {\n        const locStrs = this.locations.map((loc) => loc && loc.value ? loc.value : loc);\n        if (this.metadata) {\n            const metaStr = this.metadata.value === undefined ? this.metadata : this.metadata.value;\n            return `fused<${metaStr}>[${locStrs.join(', ')}]`;\n        }\n        return `fused[${locStrs.join(', ')}]`;\n    }\n};\n\n_.XtenNNDictLoc = class extends _.LocationAttr {\n\n    constructor(dictContent) {\n        super();\n        this.dictContent = dictContent;\n    }\n\n    get value() {\n        return `#xten_nn<dict_loc(${this.dictContent}`;\n    }\n};\n\n_.OpaqueLoc = class extends _.LocationAttr {\n\n    constructor(index, identifier, fallbackLoc) {\n        super();\n        this.index = index;\n        this.identifier = identifier;\n        this.fallbackLoc = fallbackLoc || new _.UnknownLoc();\n    }\n\n    get value() {\n        return this.fallbackLoc.value;\n    }\n};\n\n_.BytecodeReader = class {\n\n    constructor(reader, config) {\n        this.reader = new _.EncodingReader(reader);\n        this.config = config;\n        this.fileLoc = new _.Location(config.context);\n        this.valueScopes = [];\n        this.opNames = [];\n        this.dialects = [];\n        this.dialectsMap = new Map();\n        this.resourceReader = new _.ResourceSectionReader();\n        this.stringReader = new _.StringSectionReader();\n        this.propertiesReader = new _.PropertiesSectionReader();\n        this.version = { value: 0 };\n        this.attrTypeReader = new _.AttrTypeReader(this.stringReader, this.resourceReader, this.dialectsMap, this.version, this.fileLoc, config);\n        // Store buffer start address for alignment validation\n        this.bufferStart = reader instanceof Uint8Array ? reader.byteOffset : 0;\n    }\n\n    read() {\n        const reader = this.reader;\n        const signature = reader.parseBytes(4);\n        if (String.fromCharCode(...signature) !== 'ML\\xEFR') {\n            throw new mlir.Error('Invalid MLIR bytecode signature.');\n        }\n        this.parseVersion(reader);\n        this.producer = reader.parseNullTerminatedString();\n        const sectionDatas = new Map();\n        while (reader.position < reader.length) {\n            const sectionIDAndHasAlignment = reader.parseByte();\n            const sectionID = sectionIDAndHasAlignment & 0x7F;\n            const length = reader.parseVarInt().toNumber();\n            const hasAlignment = sectionIDAndHasAlignment & 0x80;\n            if (sectionID >= 9) {\n                throw new mlir.Error(`Unsupported section identifier '${sectionID}'.`);\n            }\n            if (hasAlignment) {\n                const alignment = reader.parseVarInt().toNumber();\n                this.checkSectionAlignment(alignment);\n                reader.alignTo(alignment);\n            }\n            const sectionData = reader.parseBytes(length);\n            sectionDatas.set(sectionID, sectionData);\n        }\n        for (let sectionID = 0; sectionID < 9; sectionID++) {\n            if (sectionDatas.has(sectionID)) {\n                continue;\n            }\n            if (sectionID <= 4 || (sectionID === 8 && this.version.value >= 5)) { // kString, kDialect, kAttrType, kAttrTypeOffset, kIR, kProperties + kNativePropertiesEncoding\n                throw new mlir.Error(`Missing section '${sectionID}'.`);\n            }\n        }\n        this.stringReader.initialize(sectionDatas.get(0));\n        if (sectionDatas.has(8)) {\n            this.propertiesReader.initialize(sectionDatas.get(8));\n        }\n        this.parseDialectSection(sectionDatas.get(1));\n        this.parseResourceSection(sectionDatas.get(5), sectionDatas.get(6));\n        this.attrTypeReader.initialize(this.dialects, sectionDatas.get(2), sectionDatas.get(3));\n        return this.parseIRSection(sectionDatas.get(4));\n    }\n\n    checkSectionAlignment(alignment) {\n        // Check that the bytecode buffer meets the requested section alignment.\n        // In JavaScript, we validate the byteOffset within the ArrayBuffer.\n        // This ensures the buffer offset is aligned to the requested alignment.\n        if (!Number.isInteger(alignment) || alignment <= 0 || (alignment & (alignment - 1)) !== 0) {\n            throw new mlir.Error(`Invalid alignment value: ${alignment} (must be a power of 2).`);\n        }\n        const isGloballyAligned = (this.bufferStart & (alignment - 1)) === 0;\n        if (!isGloballyAligned) {\n            throw new mlir.Error(`Expected section alignment ${alignment} but bytecode buffer offset 0x${this.bufferStart.toString(16)} is not aligned.`);\n        }\n    }\n\n    parseVersion(reader) {\n        this.version.value = reader.parseVarInt().toNumber();\n        const kVersion = 6;\n        const kMinSupportedVersion = 0;\n        if (this.version.value < kMinSupportedVersion || this.version.value > kVersion) {\n            throw new mlir.Error(`Unsupported MLIR bytecode version '${this.version.value}'.`);\n        }\n    }\n\n    parseDialectSection(sectionData) {\n        const sectionReader = new _.EncodingReader(sectionData);\n        const numDialects = sectionReader.parseVarInt().toNumber();\n        const checkSectionAlignment = (alignment) => {\n            this.checkSectionAlignment(alignment);\n        };\n        for (let i = 0; i < numDialects; i++) {\n            this.dialects.push(new _.BytecodeDialect());\n            if (this.version.value < 1) { // kDialectVersioning\n                this.dialects[i].name = this.stringReader.parseString();\n                this.dialectsMap.set(this.dialects[i].name, this.dialects[i]);\n                continue;\n            }\n            const [dialectNameIdx, versionAvailable] = sectionReader.parseVarIntWithFlag();\n            this.dialects[i].name = this.stringReader.parseStringAtIndex(sectionReader, dialectNameIdx.toNumber());\n            if (versionAvailable) {\n                const [sectionID, versionBuffer] = sectionReader.parseSection(checkSectionAlignment);\n                this.dialects[i].versionBuffer = versionBuffer;\n                if (sectionID !== 7) { // kDialectVersion\n                    throw new mlir.Error(`Expected dialect version section.`);\n                }\n            }\n            this.dialectsMap.set(this.dialects[i].name, this.dialects[i]);\n        }\n        let index = 0;\n        let numOps = -1;\n        const parseOpName = (dialect) => {\n            const opName = {};\n            opName.dialect = dialect;\n            if (this.version.value < 5) { // kNativePropertiesEncoding\n                opName.name = this.stringReader.parseString(sectionReader);\n            } else {\n                [opName.name, opName.wasRegistered] = this.stringReader.parseStringWithFlag(sectionReader);\n            }\n            if (numOps < 0) {\n                this.opNames.push(opName);\n            } else {\n                this.opNames[index++] = opName;\n            }\n        };\n        if (this.version.value >= 4) { // kElideUnknownBlockArgLocation\n            numOps = sectionReader.parseVarInt().toNumber();\n            this.opNames = new Array(numOps);\n        }\n        while (sectionReader.position < sectionData.length) {\n            _.BytecodeReader.parseDialectGrouping(sectionReader, this.dialects, parseOpName);\n        }\n    }\n\n    parseResourceSection(resourceData, resourceOffsetData) {\n        if (!resourceOffsetData) {\n            return true;\n        }\n        const dialectReader = new _.DialectReader(this.attrTypeReader, this.stringReader, this.resourceReader, this.dialectsMap, new _.EncodingReader(resourceData || new Uint8Array(0)), this.version);\n        return this.resourceReader.initialize(this.fileLoc, this.config, this.dialects, this.stringReader, resourceData, resourceOffsetData, dialectReader);\n    }\n\n    parseIRSection(sectionData) {\n        const reader = new _.EncodingReader(sectionData);\n        const block = { operations: [] };\n        this.valueScopes = [[]];\n        const regionStack = [{\n            block,\n            curRegion: 0,\n            numRegions: 1,\n            curBlock: 0,\n            numBlocks: 1,\n            numOpsRemaining: 0,\n            numValues: 0,\n            blocks: [block],\n            nextValueIdx: 0,\n            isTopLevel: true,\n            reader\n        }];\n        const firstBlockHeader = this.parseBlockHeader(reader);\n        regionStack[0].numOpsRemaining = firstBlockHeader.numOps;\n        if (firstBlockHeader.hasArgs) {\n            const [scope] = this.valueScopes;\n            this.parseBlockArguments(reader, block, scope, 0);\n            regionStack[0].nextValueIdx = block.arguments ? block.arguments.length : 0;\n        }\n        // Iteratively parse regions until everything has been resolved.\n        while (regionStack.length > 0) {\n            this.parseRegions(regionStack, regionStack[regionStack.length - 1]);\n        }\n        return block;\n    }\n\n    parseRegion(readState) {\n        const reader = readState.reader;\n        const numBlocks = reader.parseVarInt().toNumber();\n        if (numBlocks === 0) {\n            return false;\n        }\n        const numValues = reader.parseVarInt().toNumber();\n        readState.numValues = numValues;\n        readState.numBlocks = numBlocks;\n        // Create the blocks within this region.\n        const blocks = [];\n        for (let j = 0; j < numBlocks; j++) {\n            blocks.push({ operations: [], arguments: [] });\n        }\n        readState.blocks = blocks;\n        readState.region.blocks = blocks;\n        // Prepare the current value scope for this region.\n        const scope = this.valueScopes[this.valueScopes.length - 1];\n        const valueOffset = scope.length;\n        readState.valueOffset = valueOffset;\n        for (let j = 0; j < numValues; j++) {\n            scope.push(null);\n        }\n        // Parse the entry block of the region.\n        readState.curBlock = 0;\n        const blockHeader = this.parseBlockHeader(reader);\n        readState.numOpsRemaining = blockHeader.numOps;\n        if (blockHeader.hasArgs) {\n            this.parseBlockArguments(reader, blocks[0], scope, valueOffset);\n        }\n        const numBlockArgs = blocks[0].arguments ? blocks[0].arguments.length : 0;\n        readState.nextValueIdx = valueOffset + numBlockArgs;\n        return true;\n    }\n\n    parseRegions(regionStack, readState) {\n        const reader = readState.reader;\n        while (true) {\n            while (readState.numOpsRemaining > 0) {\n                readState.numOpsRemaining--;\n                // Read in the next operation. We don't read its regions directly,\n                // we handle those afterwards as necessary.\n                const { state: opState, resultNames, isIsolatedFromAbove, resultIndices } = this.parseOpWithoutRegions(reader, readState);\n                const op = _.Operation.create(opState);\n                // Assign result names for Netron display (reference: names are in parser symbol table)\n                // Also update the value scope to replace placeholders with actual OpResult objects\n                const scope = this.valueScopes[this.valueScopes.length - 1];\n                for (let i = 0; i < resultNames.length && i < op.results.length; i++) {\n                    op.results[i].name = resultNames[i];\n                    // Replace placeholder in scope with actual result\n                    if (resultIndices && i < resultIndices.length) {\n                        const valueIdx = resultIndices[i];\n                        if (valueIdx < scope.length) {\n                            scope[valueIdx] = op.results[i];\n                        }\n                    }\n                }\n                readState.blocks[readState.curBlock].operations.push(op);\n                if (op.regions && op.regions.length > 0) {\n                    for (let i = op.regions.length - 1; i >= 0; i--) {\n                        const region = op.regions[i];\n                        const childState = {\n                            region,\n                            curRegion: 0,\n                            numRegions: 1,\n                            curBlock: 0,\n                            numBlocks: 0,\n                            numOpsRemaining: 0,\n                            numValues: 0,\n                            blocks: [],\n                            valueOffset: 0,\n                            nextValueIdx: 0,\n                            isIsolated: isIsolatedFromAbove,\n                            reader,\n                            owningReader: null\n                        };\n                        // Isolated regions are encoded as a section in version 2 and above.\n                        if (this.version.value >= 2 && isIsolatedFromAbove) { // kLazyLoading\n                            const checkSectionAlignment = (alignment) => {\n                                this.checkSectionAlignment(alignment);\n                            };\n                            const [sectionID, sectionData] = reader.parseSection(checkSectionAlignment);\n                            if (sectionID !== 4) { // kIR\n                                throw new mlir.Error(`Expected IR section for region.`);\n                            }\n                            childState.owningReader = new _.EncodingReader(sectionData);\n                            childState.reader = childState.owningReader;\n                        }\n                        // If the op is isolated from above, push a new value scope.\n                        if (isIsolatedFromAbove) {\n                            this.valueScopes.push([]);\n                        }\n                        // Parse the region and push to stack if non-empty\n                        if (this.parseRegion(childState)) {\n                            regionStack.push(childState);\n                            return;\n                        }\n                    }\n                }\n            }\n            // Move to the next block of the region.\n            readState.curBlock++;\n            if (readState.curBlock >= readState.numBlocks) {\n                break;\n            }\n            const blockHeader = this.parseBlockHeader(reader);\n            readState.numOpsRemaining = blockHeader.numOps;\n            if (blockHeader.hasArgs) {\n                const scope = this.valueScopes[this.valueScopes.length - 1];\n                const argOffset = readState.nextValueIdx === undefined ? 0 : readState.nextValueIdx;\n                this.parseBlockArguments(reader, readState.blocks[readState.curBlock], scope, argOffset);\n                const numBlockArgs = readState.blocks[readState.curBlock].arguments ? readState.blocks[readState.curBlock].arguments.length : 0;\n                if (readState.nextValueIdx !== undefined) {\n                    readState.nextValueIdx += numBlockArgs;\n                }\n            }\n        }\n        if (readState.isIsolated) {\n            this.valueScopes.pop();\n        }\n        regionStack.pop();\n    }\n\n    parseBlockHeader(reader) {\n        const numOpsAndHasArgs = reader.parseVarInt();\n        const numOps = (numOpsAndHasArgs >> 1n).toNumber();\n        const hasArgs = (numOpsAndHasArgs & 1n) === 1n;\n        return { numOps, hasArgs };\n    }\n\n    parseBlockArguments(reader, block, scope, valueOffset) {\n        const numArgs = reader.parseVarInt().toNumber();\n        block.arguments = [];\n        for (let i = 0; i < numArgs; i++) {\n            let type = null;\n            let location = null;\n            if (this.version.value >= 4) { // kElideUnknownBlockArgLocation\n                const [typeIdx, hasLocation] = reader.parseVarIntWithFlag();\n                type = this.attrTypeReader.readType(typeIdx.toNumber());\n                if (hasLocation) {\n                    const locIdx = reader.parseVarInt().toNumber();\n                    location = this.attrTypeReader.readAttribute(locIdx);\n                }\n            } else {\n                const typeIdx = reader.parseVarInt().toNumber();\n                type = this.attrTypeReader.readType(typeIdx);\n                const locIdx = reader.parseVarInt().toNumber();\n                location = this.attrTypeReader.readAttribute(locIdx);\n            }\n            const argName = `%${valueOffset + i}`;\n            const arg = new _.Value(argName, type);\n            arg.location = location;\n            block.arguments.push(arg);\n            if (scope && (valueOffset + i) < scope.length) {\n                scope[valueOffset + i] = arg;\n            }\n        }\n        // Use-list ordering (version >= 3) - stored after all arguments\n        // hasUseListOrders byte is read whenever hasArgs is true (not dependent on numArgs)\n        if (this.version.value >= 3) { // kUseListOrdering\n            const hasUseListOrders = reader.parseByte();\n            if (hasUseListOrders !== 0) {\n                const orders = this.parseUseListOrdersForRange(reader, numArgs);\n                // Store ordering information on block arguments\n                for (const order of orders) {\n                    if (order.argIndex < block.arguments.length) {\n                        block.arguments[order.argIndex].useListOrder = order.ordering;\n                    }\n                }\n            }\n        }\n    }\n\n    parseUseListOrdersForRange(reader, numValues) {\n        const orders = [];\n        let numToRead = 1;\n        if (numValues > 1) {\n            numToRead = reader.parseVarInt().toNumber();\n        }\n        for (let i = 0; i < numToRead; i++) {\n            let argIndex = 0;\n            if (numValues > 1) {\n                argIndex = reader.parseVarInt().toNumber();\n            }\n            const numUsesAndFlag = reader.parseVarInt();\n            const numUses = (numUsesAndFlag >> 1n).toNumber();\n            const indexPairEncoding = (numUsesAndFlag & 1n) === 1n;\n            const indices = [];\n            for (let j = 0; j < numUses; j++) {\n                indices.push(reader.parseVarInt().toNumber());\n            }\n            orders.push({ argIndex, ordering: { indexPairEncoding, indices } });\n        }\n        return orders;\n    }\n\n    parseOpName(reader) {\n        const opName = reader.parseEntry(this.opNames, 'operation name');\n        if (!opName.opName) {\n            const name = `${opName.dialect.name}.${opName.name}`;\n            opName.opName = _.RegisteredOperationName.lookup(name, this.fileLoc.context);\n            if (!opName.opName) {\n                throw new mlir.Error(`Unregistered bytecode operation '${name}'.`);\n            }\n        }\n        return [opName.opName, opName.wasRegistered];\n    }\n\n    parseOpWithoutRegions(reader, state) {\n        // Parse operation name index\n        const [opName, wasRegistered] = this.parseOpName(reader);\n        const opMask = reader.parseByte();\n        const kHasAttrs = 0x01;\n        const kHasResults = 0x02;\n        const kHasOperands = 0x04;\n        const kHasSuccessors = 0x08;\n        const kHasInlineRegions = 0x10;\n        const kHasUseListOrders = 0x20;\n        const kHasProperties = 0x40;\n        const opState = new _.OperationState(null, opName);\n        const locIdx = reader.parseVarInt().toNumber();\n        opState.location = this.attrTypeReader.readAttribute(locIdx);\n        if (opMask & kHasAttrs) {\n            const dictAttrIdx = reader.parseVarInt().toNumber();\n            const dictAttr = this.attrTypeReader.readAttribute(dictAttrIdx);\n            if (dictAttr && dictAttr.value) {\n                if (dictAttr.value instanceof Map) {\n                    // Already parsed as Map from custom-encoded DictionaryAttr\n                    opState.attributes = dictAttr.value;\n                } else if (typeof dictAttr.value === 'string') {\n                    // Parse dictionary attribute from ASM string format\n                    opState.attributes = this.parseAttributeDict(dictAttr.value);\n                }\n            }\n        }\n        // Parse properties (version >= 5)\n        if (opMask & kHasProperties) {\n            if (wasRegistered) {\n                const dialectReader = new _.DialectReader(this.attrTypeReader, this.stringReader, this.resourceReader, this.dialectsMap, reader, this.version);\n                this.propertiesReader.read(this.fileLoc, dialectReader, opName, opState);\n            } else {\n                // Unregistered operations store properties as a single dictionary attribute\n                const propAttrIdx = reader.parseVarInt().toNumber();\n                const propAttr = this.attrTypeReader.readAttribute(propAttrIdx);\n                if (propAttr && propAttr.value) {\n                    const propAttrs = this.parseAttributeDict(propAttr.value);\n                    for (const [key, value] of propAttrs) {\n                        opState.addAttribute(key, value);\n                    }\n                }\n            }\n        }\n        // Parse results - add types to OperationState.types, track values in scope\n        const resultNames = [];\n        const resultIndices = [];\n        if (opMask & kHasResults) {\n            const numResults = reader.parseVarInt().toNumber();\n            const scope = this.valueScopes[this.valueScopes.length - 1];\n            for (let i = 0; i < numResults; i++) {\n                const typeIdx = reader.parseVarInt().toNumber();\n                const type = this.attrTypeReader.readType(typeIdx);\n                opState.addTypes([type]);\n                const valueIdx = state && state.nextValueIdx !== undefined ? state.nextValueIdx++ : scope.length;\n                const valueName = `%${valueIdx}`;\n                resultNames.push(valueName);\n                resultIndices.push(valueIdx);\n                // Create placeholder in scope (will be replaced after Operation creation with actual OpResult)\n                const placeholder = new _.Value(valueName, type);\n                if (valueIdx < scope.length) {\n                    scope[valueIdx] = placeholder;\n                } else {\n                    scope.push(placeholder);\n                }\n            }\n        }\n\n        if (opMask & kHasOperands) {\n            const numOperands = reader.parseVarInt().toNumber();\n            for (let i = 0; i < numOperands; i++) {\n                const valueIdx = reader.parseVarInt().toNumber();\n                const scope = this.valueScopes[this.valueScopes.length - 1];\n                if (valueIdx < scope.length && scope[valueIdx]) {\n                    opState.operands.push(scope[valueIdx]);\n                } else {\n                    opState.operands.push(new _.Value(`%${valueIdx}`, null));\n                }\n            }\n        }\n\n        if (opMask & kHasSuccessors) {\n            const numSuccessors = reader.parseVarInt().toNumber();\n            opState.successors = [];\n            for (let i = 0; i < numSuccessors; i++) {\n                const blockIdx = reader.parseVarInt().toNumber();\n                opState.successors.push(blockIdx);\n            }\n        }\n        // Parse use-list orders (version >= 3)\n        if (this.version.value >= 3 && (opMask & kHasUseListOrders)) { // kUseListOrdering\n            const numResults = opState.types.length;\n            const orders = this.parseUseListOrdersForRange(reader, numResults);\n            if (orders.length > 0) {\n                opState.useListOrders = orders;\n            }\n        }\n        let isIsolatedFromAbove = false;\n        if (opMask & kHasInlineRegions) {\n            const numRegionsAndIsIsolated = reader.parseVarInt();\n            const numRegions = (numRegionsAndIsIsolated >> 1n).toNumber();\n            isIsolatedFromAbove = (numRegionsAndIsIsolated & 1n) === 1n;\n            for (let i = 0; i < numRegions; i++) {\n                opState.regions.push({ blocks: [] });\n            }\n        }\n        return { state: opState, resultNames, isIsolatedFromAbove, resultIndices };\n    }\n\n    parseAttributeDict(str) {\n        const attrs = new Map();\n        // Parse dictionary attribute format: {key = value, ...}\n        if (!str.startsWith('{') || !str.endsWith('}')) {\n            return attrs;\n        }\n        const content = str.slice(1, -1).trim();\n        if (content.length === 0) {\n            return attrs;\n        }\n        let i = 0;\n        while (i < content.length) {\n            while (i < content.length && /\\s/.test(content[i])) {\n                i++;\n            }\n            if (i >= content.length) {\n                break;\n            }\n            // Read key (alphanumeric/underscore)\n            const keyStart = i;\n            while (i < content.length && /[a-zA-Z0-9_]/.test(content[i])) {\n                i++;\n            }\n            const key = content.slice(keyStart, i);\n            if (!key) {\n                break;\n            }\n            while (i < content.length && /\\s/.test(content[i])) {\n                i++;\n            }\n            if (i >= content.length || content[i] !== '=') {\n                break;\n            }\n            i++; // skip '='\n            while (i < content.length && /\\s/.test(content[i])) {\n                i++;\n            }\n            // Read value (until balanced comma or end)\n            const valueStart = i;\n            let depth = 0;\n            let inString = false;\n            while (i < content.length) {\n                const c = content[i];\n                if (inString) {\n                    if (c === '\"' && content[i - 1] !== '\\\\') {\n                        inString = false;\n                    }\n                    i++;\n                    continue;\n                }\n                if (c === '\"') {\n                    inString = true;\n                    i++;\n                    continue;\n                }\n                if (c === '{' || c === '[' || c === '(' || c === '<') {\n                    depth++;\n                } else if (c === '}' || c === ']' || c === ')' || c === '>') {\n                    depth--;\n                } else if (c === ',' && depth === 0) {\n                    break;\n                }\n                i++;\n            }\n            const value = content.slice(valueStart, i).trim();\n            attrs.set(key, { value, toString: () => value });\n            if (i < content.length && content[i] === ',') {\n                i++;\n            }\n        }\n        return attrs;\n    }\n\n    static parseDialectGrouping(reader, dialects, entryCallback) {\n        const dialect = reader.parseEntry(dialects, 'dialect');\n        const numEntries = reader.parseVarInt().toNumber();\n        for (let i = 0; i < numEntries; i++) {\n            entryCallback(dialect);\n        }\n    }\n};\n\n_.Constraint = class {\n\n    constructor(name, args, values) {\n        this.name = name;\n        this.args = args || null;\n        this.values = values || null;\n    }\n\n    static parse(value) {\n        const tokens = _.Constraint.tokenize(value);\n        const result = _.Constraint.parseTokens(tokens, 0);\n        const { name, args, values } = result.value;\n        return new _.Constraint(name, args, values);\n    }\n\n    toString() {\n        if (this.args && this.args.length > 0) {\n            const args = this.args.map((arg) => arg.name).join(', ');\n            return `${this.name}<${args}>`;\n        }\n        if (this.values && this.values.length > 0) {\n            return `${this.name}{${this.values.join(' | ')}}`;\n        }\n        return this.name;\n    }\n\n    static tokenize(str) {\n        const tokens = [];\n        let i = 0;\n        while (i < str.length) {\n            const ch = str[i];\n            if (/\\s/.test(ch)) {\n                i++;\n                continue;\n            }\n            if ('<>={}[](),|'.indexOf(ch) !== -1) {\n                tokens.push({ type: ch, value: ch, pos: i });\n                i++;\n                continue;\n            }\n            if (ch === ':' && i + 1 < str.length && str[i + 1] === ':') {\n                tokens.push({ type: '::', value: '::', pos: i });\n                i += 2;\n                continue;\n            }\n            if (ch === ':') {\n                i++;\n                continue;\n            }\n            if (ch === '\"' || ch === \"'\") {\n                const quote = ch;\n                let j = i + 1;\n                while (j < str.length && str[j] !== quote) {\n                    if (str[j] === '\\\\' && j + 1 < str.length) {\n                        j += 2;\n                    } else {\n                        j++;\n                    }\n                }\n                if (j < str.length) {\n                    tokens.push({ type: 'string', value: str.substring(i + 1, j), pos: i });\n                    i = j + 1;\n                } else {\n                    tokens.push({ type: 'ident', value: str.substring(i), pos: i });\n                    break;\n                }\n                continue;\n            }\n            if (/[a-zA-Z_0-9-]/.test(ch)) {\n                let j = i;\n                while (j < str.length && /[a-zA-Z_0-9-]/.test(str[j])) {\n                    j++;\n                }\n                const ident = str.substring(i, j);\n                tokens.push({ type: 'ident', value: ident, pos: i });\n                i = j;\n                continue;\n            }\n            i++;\n        }\n        return tokens;\n    }\n\n    static parseTokens(tokens, pos) {\n        if (pos >= tokens.length) {\n            return null;\n        }\n        const token = tokens[pos];\n        if (token.type === '::') {\n            let name = '';\n            let nextPos = pos;\n            while (nextPos < tokens.length) {\n                if (tokens[nextPos].type === '::') {\n                    name += '::';\n                    nextPos++;\n                } else if (tokens[nextPos].type === 'ident') {\n                    name += tokens[nextPos].value;\n                    nextPos++;\n                } else {\n                    break;\n                }\n            }\n            if (!name) {\n                return null;\n            }\n            if (nextPos < tokens.length) {\n                const nextToken = tokens[nextPos];\n                if (nextToken.type === '{') {\n                    return _.Constraint._parseEnum(tokens, pos, name);\n                }\n                if (nextToken.type === '<') {\n                    return _.Constraint._parseGeneric(tokens, pos, name);\n                }\n            }\n            return { value: { name }, nextPos };\n\n        }\n        if (token.type !== 'ident') {\n            return null;\n        }\n        let name = token.value;\n        let nextPos = pos + 1;\n        while (nextPos < tokens.length && tokens[nextPos].type === '::') {\n            nextPos++;\n            if (nextPos < tokens.length && tokens[nextPos].type === 'ident') {\n                const value = tokens[nextPos++].value;\n                name += `::${value}`;\n            } else {\n                break;\n            }\n        }\n        if (nextPos >= tokens.length) {\n            return { value: { name }, nextPos };\n        }\n        const nextToken = tokens[nextPos];\n        if (nextToken.type === '{') {\n            return _.Constraint._parseEnum(tokens, pos, name);\n        }\n        if (nextToken.type === '<') {\n            return _.Constraint._parseGeneric(tokens, pos, name);\n        }\n        return { value: { name }, nextPos };\n    }\n\n    static _parseEnum(tokens, startPos, name) {\n        let pos = startPos;\n        while (pos < tokens.length && (tokens[pos].type === 'ident' || tokens[pos].type === '::')) {\n            pos++;\n        }\n        if (pos >= tokens.length || tokens[pos].type !== '{') {\n            return null;\n        }\n        pos++;\n        const values = [];\n        let currentValue = '';\n        while (pos < tokens.length && tokens[pos].type !== '}') {\n            const token = tokens[pos];\n            if (token.type === '|') {\n                if (currentValue.trim()) {\n                    values.push(currentValue.trim());\n                    currentValue = '';\n                }\n                pos++;\n            } else if (token.type === 'ident') {\n                if (currentValue) {\n                    currentValue += ' ';\n                }\n                currentValue += token.value;\n                pos++;\n            } else if (token.type === '::') {\n                currentValue += '::';\n                pos++;\n            } else {\n                pos++;\n            }\n        }\n        if (currentValue.trim()) {\n            values.push(currentValue.trim());\n        }\n        if (pos < tokens.length && tokens[pos].type === '}') {\n            pos++;\n        }\n        return { value: { name, values }, nextPos: pos };\n    }\n\n    static _parseGeneric(tokens, startPos, name) {\n        let pos = startPos;\n        while (pos < tokens.length && (tokens[pos].type === 'ident' || tokens[pos].type === '::')) {\n            pos++;\n        }\n        if (pos >= tokens.length || tokens[pos].type !== '<') {\n            return null;\n        }\n        pos++;\n        const args = [];\n        let angleDepth = 1;\n        let bracketDepth = 0;\n        let currentArg = [];\n        while (pos < tokens.length && (angleDepth > 0 || bracketDepth > 0)) {\n            const token = tokens[pos];\n            if (token.type === '<') {\n                angleDepth++;\n                currentArg.push(token);\n                pos++;\n            } else if (token.type === '>') {\n                angleDepth--;\n                if (angleDepth === 0 && bracketDepth === 0) {\n                    if (currentArg.length > 0) {\n                        const parsed = _.Constraint.parseArgumentTokens(currentArg);\n                        if (parsed !== null) {\n                            args.push(parsed);\n                        }\n                    }\n                    pos++;\n                    break;\n                }\n                currentArg.push(token);\n                pos++;\n            } else if (token.type === '[') {\n                bracketDepth++;\n                currentArg.push(token);\n                pos++;\n            } else if (token.type === ']') {\n                bracketDepth--;\n                currentArg.push(token);\n                pos++;\n            } else if (token.type === ',' && angleDepth === 1 && bracketDepth === 0) {\n                if (currentArg.length > 0) {\n                    const parsed = _.Constraint.parseArgumentTokens(currentArg);\n                    if (parsed !== null) {\n                        args.push(parsed);\n                    }\n                    currentArg = [];\n                }\n                pos++;\n            } else {\n                currentArg.push(token);\n                pos++;\n            }\n        }\n        return { value: { name, args }, nextPos: pos };\n    }\n\n    static parseArgumentTokens(tokens) {\n        if (!tokens || tokens.length === 0) {\n            return null;\n        }\n        tokens = tokens.filter((t) => t.type !== undefined);\n        if (tokens[0].type === '[') {\n            return _.Constraint.parseListArgument(tokens);\n        }\n        if (tokens[0].type === 'string') {\n            return tokens[0].value;\n        }\n        if (tokens[0].type === 'ident' || tokens[0].type === '::') {\n            const result = _.Constraint.parseTokens(tokens, 0);\n            if (result && result.nextPos === tokens.length) {\n                return result.value;\n            }\n        }\n        let literal = '';\n        for (const token of tokens) {\n            if (token.type === 'ident' || token.type === 'string') {\n                if (literal && !/^[,[\\]():.]$/.test(literal[literal.length - 1])) {\n                    literal += ' ';\n                }\n                literal += token.value;\n            } else if (token.type === '::') {\n                literal += '::';\n            } else if ('{}[](),.'.indexOf(token.type) !== -1) {\n                literal += token.value;\n            }\n        }\n        return literal.trim() || null;\n    }\n\n    static parseListArgument(tokens) {\n        if (!tokens || tokens.length === 0 || tokens[0].type !== '[') {\n            return null;\n        }\n        let pos = 1;\n        const items = [];\n        let bracketDepth = 1;\n        let angleDepth = 0;\n        let currentItem = [];\n        while (pos < tokens.length && (bracketDepth > 0 || angleDepth > 0)) {\n            const token = tokens[pos];\n            if (token.type === '[') {\n                bracketDepth++;\n                currentItem.push(token);\n                pos++;\n            } else if (token.type === ']') {\n                bracketDepth--;\n                if (bracketDepth === 0 && angleDepth === 0) {\n                    if (currentItem.length > 0) {\n                        const parsed = _.Constraint.parseArgumentTokens(currentItem);\n                        if (parsed !== null) {\n                            items.push(parsed);\n                        }\n                    }\n                    break;\n                }\n                currentItem.push(token);\n                pos++;\n            } else if (token.type === '<') {\n                angleDepth++;\n                currentItem.push(token);\n                pos++;\n            } else if (token.type === '>') {\n                angleDepth--;\n                currentItem.push(token);\n                pos++;\n            } else if (token.type === ',' && bracketDepth === 1 && angleDepth === 0) {\n                if (currentItem.length > 0) {\n                    const parsed = _.Constraint.parseArgumentTokens(currentItem);\n                    if (parsed !== null) {\n                        items.push(parsed);\n                    }\n                    currentItem = [];\n                }\n                pos++;\n            } else {\n                currentItem.push(token);\n                pos++;\n            }\n        }\n        return items;\n    }\n};\n\n_.AssemblyFormatParser = class {\n\n    constructor(metadata) {\n        this._metadata = metadata;\n        this._buffer = metadata.assemblyFormat || '';\n        this._pos = 0;\n    }\n\n    match(char) {\n        return this._pos < this._buffer.length && this._buffer[this._pos] === char;\n    }\n\n    accept(str) {\n        if (str.length === 1) {\n            if (this.match(str)) {\n                this._pos++;\n                return true;\n            }\n            return false;\n        }\n        const remaining = this._buffer.substring(this._pos);\n        if (remaining.startsWith(str)) {\n            // Check that keyword is not followed by alphanumeric (to avoid \"type\" in \"typename\")\n            const nextChar = this._buffer[this._pos + str.length];\n            if (nextChar && /[a-zA-Z0-9_-]/.test(nextChar)) {\n                return false;\n            }\n            this._pos += str.length;\n            return true;\n        }\n        return false;\n    }\n\n    expect(char) {\n        if (!this.match(char)) {\n            throw new mlir.Error(`Expected '${char}'.`);\n        }\n        this._pos++;\n    }\n\n    parse() {\n        const directives = [];\n        this._skipWhitespace();\n        while (this._pos < this._buffer.length) {\n            const directive = this.parseDirective();\n            directives.push(directive);\n            this._skipWhitespace();\n        }\n        return directives;\n    }\n\n    parseDirective() {\n        const ch = this._buffer[this._pos];\n        if (!ch || this._pos >= this._buffer.length) {\n            throw new mlir.Error(`Unexpected end of format string.`);\n        }\n        // Parenthesized group: can be optional (...)?  or conditional (...):(...) or just grouping (...)\n        if (this.match('(')) {\n            this.accept('(');\n            const elements = [];\n            let anchorElement = null;\n\n            this._skipWhitespace();\n            while (!this.match(')')) {\n                const elem = this.parseDirective();\n                if (elem.type === 'anchor') {\n                    // Standalone anchor - applies to the previous element\n                    if (elements.length > 0) {\n                        const prev = elements[elements.length - 1];\n                        anchorElement = prev.name || prev.type;\n                    }\n                } else {\n                    if (elem.anchor) {\n                        anchorElement = elem.name || elem.type;\n                    }\n                    elements.push(elem);\n                }\n                this._skipWhitespace();\n            }\n            this.expect(')');\n            this._skipWhitespace();\n            // Check what follows to determine the group type\n            if (this.accept('?')) {\n                // Optional group: (...)?\n                return { type: 'optional_group', elements, anchor: anchorElement };\n            }\n            if (this.accept(':')) {\n                // Conditional alternative: (...):(...)?\n                this._skipWhitespace();\n                const secondAlt = [];\n                let isSecondOptional = false;\n                if (this.accept('(')) {\n                    this._skipWhitespace();\n                    while (!this.match(')')) {\n                        const elem = this.parseDirective();\n                        secondAlt.push(elem);\n                        this._skipWhitespace();\n                    }\n                    this.expect(')');\n                    this._skipWhitespace();\n                    if (this.accept('?')) {\n                        isSecondOptional = true;\n                    }\n                }\n                return { type: 'conditional_alternative', firstAlt: elements, secondAlt, secondOptional: isSecondOptional };\n            }\n            return { type: 'group', elements };\n        }\n        // Literal: `keyword`\n        if (this.accept('`')) {\n            const value = this.parseUntil('`');\n            this.expect('`');\n            // MLIR reference: Empty literals (`` or ` `) are whitespace, not literals\n            if (value.length === 0 || value === ' ' || value === '\\\\n') {\n                return { type: 'whitespace', value }; // Return whitespace as a directive\n            }\n            return { type: 'literal', value };\n        }\n        if (this.accept('$')) {\n            const name = this.parseIdentifier();\n            const anchor = this.accept('^');\n            const metadata = this._metadata;\n            // Determine variable type from metadata first - matches reference implementation\n            // Check each metadata category in priority order\n            if (metadata.successors && metadata.successors.some((a) => a.name === name)) {\n                return { type: 'successor_ref', name, anchor };\n            }\n            if (metadata.attributes && metadata.attributes.some((a) => a.name === name)) {\n                return { type: 'attribute_ref', name, anchor };\n            }\n            if (metadata.operands && metadata.operands.some((a) => a.name === name)) {\n                return { type: 'operand_ref', name, anchor };\n            }\n            if (metadata.regions && metadata.regions.some((a) => a.name === name)) {\n                return { type: 'region_ref', name, anchor };\n            }\n            throw new mlir.Error(`Unknown variable '$${name}' in assembly format.`);\n        }\n        if (this.accept('type')) {\n            const args = this.parseParenList();\n            const anchor = this.accept('^');\n            return { type: 'type', args, anchor };\n        }\n        if (this.accept('qualified')) {\n            const args = this.parseParenList();\n            const anchor = this.accept('^');\n            return { type: 'qualified', args, anchor };\n        }\n        if (this.accept('attr-dict-with-keyword')) {\n            return { type: 'attr_dict_with_keyword' };\n        }\n        if (this.accept('attr-dict')) {\n            return { type: 'attr_dict' };\n        }\n        if (this.accept('prop-dict')) {\n            return { type: 'prop_dict' };\n        }\n        if (this.accept('functional-type')) {\n            const args = this.parseParenList();\n            const anchor = this.accept('^');\n            return { type: 'functional_type', args, anchor };\n        }\n        if (this.accept('params')) {\n            return { type: 'params' };\n        }\n        if (this.accept('struct')) {\n            this.expect('(');\n            const args = [];\n            while (!this.match(')')) {\n                this._skipWhitespace();\n                if (this.match(')')) {\n                    break;\n                }\n                const arg = this.parseDirective();\n                args.push(arg);\n                this._skipWhitespace();\n                this.accept(',');\n            }\n            this.expect(')');\n            return { type: 'struct', args };\n        }\n        if (this.accept('ref')) {\n            this.expect('(');\n            const arg = this.parseDirective();\n            this._skipWhitespace();\n            this.expect(')');\n            return { type: 'ref', arg };\n        }\n        if (this.accept('custom')) {\n            this.expect('<');\n            const parser = this.parseUntil('>');\n            this.expect('>');\n            const args = this.parseParenList();\n            const anchor = this.accept('^');\n            return { type: 'custom', parser, args, anchor };\n        }\n        if (this.accept('oilist')) {\n            this._skipWhitespace();\n            this.expect('(');\n            let content = '';\n            let depth = 1;\n            while (this._pos < this._buffer.length && depth > 0) {\n                const ch = this._buffer[this._pos];\n                if (ch === '(') {\n                    depth++;\n                    content += ch;\n                    this._pos++;\n                } else if (ch === ')') {\n                    depth--;\n                    if (depth > 0) {\n                        content += ch;\n                    }\n                    this._pos++;\n                } else {\n                    content += ch;\n                    this._pos++;\n                }\n            }\n            return { type: 'oilist', content };\n        }\n        if (this.accept('operands')) {\n            return { type: 'operands' };\n        }\n        if (this.accept('results')) {\n            return { type: 'results' };\n        }\n        if (this.accept('regions')) {\n            return { type: 'regions' };\n        }\n        if (this.accept('successors')) {\n            return { type: 'successors' };\n        }\n        if (ch === '^') {\n            this._pos++;\n            return { type: 'anchor' };\n        }\n        if (/^[:()[\\]{}<>,=|]/.test(ch)) {\n            this._pos++;\n            return { type: 'literal', value: ch };\n        }\n        const context = this._buffer.substring(Math.max(0, this._pos - 10), Math.min(this._buffer.length, this._pos + 10));\n        throw new mlir.Error(`Unexpected '${ch}' in assembly format '${context}...'.`);\n    }\n\n    parseIdentifier() {\n        let name = '';\n        while (this._pos < this._buffer.length) {\n            const ch = this._buffer[this._pos];\n            if (/[a-zA-Z0-9_]/.test(ch)) {\n                name += ch;\n                this._pos++;\n            } else {\n                break;\n            }\n        }\n        return name;\n    }\n\n    parseUntil(terminator) {\n        let value = '';\n        while (this._pos < this._buffer.length && this._buffer[this._pos] !== terminator) {\n            value += this._buffer[this._pos];\n            this._pos++;\n        }\n        return value;\n    }\n\n    parseParenList() {\n        this._skipWhitespace();\n        if (!this.accept('(')) {\n            return [];\n        }\n        this._skipWhitespace();\n        if (this.accept(')')) {\n            return [];\n        }\n        const items = [];\n        const parseElement = () => {\n            let element = '';\n            let depth = 0;\n            while (this._pos < this._buffer.length) {\n                this._skipWhitespace();\n                if (this.accept('\"')) {\n                    // String literal - consume as a unit\n                    element += '\"';\n                    element += this.parseUntil('\"');\n                    element += '\"';\n                    this.expect('\"');\n                } else if (this.accept('$')) {\n                    element += '$';\n                    const id = this.parseIdentifier();\n                    element += id;\n                } else if (this.accept('(')) {\n                    // Nested parentheses - include in element (e.g., type($list))\n                    element += '(';\n                    depth++;\n                } else if (this.match(')')) {\n                    if (depth === 0) {\n                        // End of this element\n                        break;\n                    }\n                    element += ')';\n                    this.accept(')');\n                    depth--;\n                } else if (this.match(',') && depth === 0) {\n                    // Comma at top level - end of this element\n                    break;\n                } else if (this.match('-')) {\n                    // Handle hyphenated identifiers like attr-dict, functional-type\n                    element += '-';\n                    this.accept('-');\n                } else {\n                    // Plain identifier (e.g., \"type\" in type($list))\n                    const id = this.parseIdentifier();\n                    if (!id) {\n                        throw new mlir.Error(`Unexpected '${this._buffer[this._pos]}' in assembly format directive list.`);\n                    }\n                    element += id;\n                }\n            }\n            return element.trim();\n        };\n        const first = parseElement();\n        if (!first) {\n            throw new mlir.Error('Expected element.');\n        }\n        items.push(first);\n        this._skipWhitespace();\n        while (this.accept(',')) {\n            this._skipWhitespace();\n            const elem = parseElement();\n            if (!elem) {\n                throw new mlir.Error('Expected element after comma');\n            }\n            items.push(elem);\n            this._skipWhitespace();\n        }\n        this.expect(')');\n        return items;\n    }\n\n    _skipWhitespace() {\n        while (this._pos < this._buffer.length && /\\s/.test(this._buffer[this._pos])) {\n            this._pos++;\n        }\n    }\n};\n\n_.DialectContext = class {\n\n    constructor(metadata) {\n        const operations = metadata.operations;\n        this._dialects = new Map();\n        this._dialects.set('builtin', new _.BuiltinDialect(operations));\n        this._dialects.set('std', new _.Dialect(operations, 'std'));\n        this._dialects.set('bufferization', new _.BufferizationDialect(operations));\n        this._dialects.set('stablehlo', new _.stablehlo.StableHLODialect(operations));\n        this._dialects.set('vhlo', new _.VhloDialect(operations));\n        this._dialects.set('interpreter', new _.InterpreterDialect(operations));\n        this._dialects.set('affine', new _.AffineDialect(operations));\n        this._dialects.set('asuka', new _.AsukaDialect(operations));\n        this._dialects.set('arith', new _.ArithDialect(operations));\n        this._dialects.set('async', new _.async.AsyncDialect(operations));\n        this._dialects.set('cf', new _.CFDialect(operations));\n        this._dialects.set('emitc', new _.EmitCDialect(operations));\n        this._dialects.set('complex', new _.Dialect(operations, 'complex'));\n        this._dialects.set('index', new _.Dialect(operations, 'index'));\n        this._dialects.set('pdl', new _.pdl.PDLDialect(operations));\n        this._dialects.set('ptr', new _.ptr.PtrDialect(operations));\n        this._dialects.set('ub', new _.Dialect(operations, 'ub'));\n        this._dialects.set('amdgpu', new _.AMDGPUDialect(operations));\n        this._dialects.set('nvgpu', new _.NVGPUDialect(operations));\n        this._dialects.set('nvvm', new _.NVVMDialect(operations));\n        this._dialects.set('rocdl', new _.ROCDLDialect(operations));\n        this._dialects.set('nvws', new _.triton.nvws.NVWSDialect(operations));\n        this._dialects.set('tti', new _.Dialect(operations, 'tti'));\n        this._dialects.set('omp', new _.OpenMPDialect(operations));\n        this._dialects.set('proton', new _.triton.proton.ProtonDialect(operations));\n        this._dialects.set('proton_gpu', new _.Dialect(operations, 'proton_gpu'));\n        this._dialects.set('arm_sme', new _.ArmSMEDialect(operations));\n        this._dialects.set('arm_neon', new _.ArmNeonDialect(operations));\n        this._dialects.set('arm_sve', new _.ArmSVEDialect(operations));\n        this._dialects.set('shard', new _.ShardDialect(operations));\n        this._dialects.set('smt', new _.smt.SMTDialect(operations));\n        this._dialects.set('lagrad', new _.Dialect(operations, 'lagrad'));\n        this._dialects.set('iree_codegen', new _.IREECodegenDialect(operations));\n        this._dialects.set('iree_encoding', new _.Dialect(operations, 'iree_encoding'));\n        this._dialects.set('test', new _.test.TestDialect(operations));\n        this._dialects.set('scf', new _.SCFDialect(operations));\n        this._dialects.set('shape', new _.ShapeDialect(operations));\n        this._dialects.set('sparse_tensor', new _.SparseTensorDialect(operations));\n        this._dialects.set('func', new _.FuncDialect(operations));\n        this._dialects.set('gpu', new _.GpuDialect(operations));\n        this._dialects.set('llvm', new _.llvm.LLVMDialect(operations));\n        this._dialects.set('xegpu', new _.XeGPUDialect(operations));\n        this._dialects.set('memref', new _.MemRefDialect(operations));\n        this._dialects.set('vector', new _.VectorDialect(operations));\n        this._dialects.set('x86', new _.Dialect(operations, 'x86'));\n        this._dialects.set('x86vector', new _.Dialect(operations, 'x86vector'));\n        this._dialects.set('onnx', new _.ONNXDialect(operations));\n        this._dialects.set('krnl', new _.KrnlDialect(operations));\n        this._dialects.set('torch', new _.torch.TorchDialect(operations));\n        this._dialects.set('torch_c', new _.Dialect(operations, 'torch_c'));\n        this._dialects.set('hal', new _.HALDialect(operations));\n        this._dialects.set('hal_loader', new _.HALLoaderDialect(operations));\n        this._dialects.set('hal_inline', new _.Dialect(operations, 'hal_inline'));\n        this._dialects.set('util', new _.UtilDialect(operations));\n        this._dialects.set('mhlo', new _.hlo.MhloDialect(operations));\n        this._dialects.set('chlo', new _.hlo.ChloDialect(operations));\n        this._dialects.set('thlo', new _.THLODialect(operations));\n        this._dialects.set('flow', new _.FlowDialect(operations));\n        this._dialects.set('stream', new _.StreamDialect(operations));\n        this._dialects.set('iree_vector_ext', new _.IREEVectorExtDialect(operations));\n        this._dialects.set('iree_tensor_ext', new _.IREETensorExtDialect(operations));\n        this._dialects.set('linalg', new _.LinalgDialect(operations));\n        this._dialects.set('iree_linalg_ext', new _.Dialect(operations, 'iree_linalg_ext'));\n        this._dialects.set('linalg_ext', this._dialects.get('iree_linalg_ext'));\n        this._dialects.set('quant', new _.quant.QuantDialect(operations));\n        this._dialects.set('tensor', new _.TensorDialect(operations));\n        this._dialects.set('tosa', new _.TosaDialect(operations));\n        this._dialects.set('tf', new _.TFDialect(operations));\n        this._dialects.set('tf_saved_model', new _.Dialect(operations, 'tf_saved_model'));\n        this._dialects.set('tf_type', new _.TFTypeDialect(operations));\n        this._dialects.set('tf_device', new _.TFDeviceDialect(operations));\n        this._dialects.set('tf_executor', new _.TFExecutorDialect(operations));\n        this._dialects.set('tf_framework', new _.TFFrameworkDialect(operations));\n        this._dialects.set('tfr', new _.TFRDialect(operations));\n        this._dialects.set('corert', new _.CoreRTDialect(operations));\n        this._dialects.set('tfrt', new _.TFRTDialect(operations));\n        this._dialects.set('tfrt_fallback', new _.Dialect(operations, 'tfrt_fallback'));\n        this._dialects.set('tfrt_fallback_async', new _.TFRTFallbackAsyncDialect(operations));\n        this._dialects.set('tfl', new _.TFLDialect(operations));\n        this._dialects.set('stdx', new _.StdxDialect(operations));\n        this._dialects.set('vm', new _.vm.VMDialect(operations));\n        this._dialects.set('math', new _.MathDialect(operations));\n        this._dialects.set('tm_tensor', new _.torch.TMTensorDialect(operations));\n        this._dialects.set('ml_program', new _.MLProgramDialect(operations));\n        this._dialects.set('iree_gpu', new _.IREEGPUDialect(operations));\n        this._dialects.set('tile', new _.TileDialect(operations));\n        this._dialects.set('pxa', new _.PXADialect(operations));\n        this._dialects.set('irdl', new _.IRDLDialect(operations));\n        this._dialects.set('transform', new _.TransformDialect(operations));\n        this._dialects.set('wasmssa', new _.WasmSSADialect(operations));\n        this._dialects.set('spirv', new _.spirv.SPIRVDialect(operations));\n        this._dialects.set('spv', this._dialects.get('spirv'));\n        this._dialects.set('toy', new _.hlo.ToyDialect(operations));\n        this._dialects.set('top', new _.Dialect(operations, 'top'));\n        this._dialects.set('tpu', new _.Dialect(operations, 'tpu'));\n        this._dialects.set('sdfg', new _.SdfgDialect(operations));\n        this._dialects.set('sdir', this._dialects.get('sdfg'));\n        this._dialects.set('check', new _.Dialect(operations, 'check'));\n        this._dialects.set('tt', new _.triton.TritonDialect(operations));\n        this._dialects.set('ttg', new _.triton.gpu.TritonGPUDialect(operations));\n        this._dialects.set('triton_gpu', this._dialects.get('ttg'));\n        this._dialects.set('gluon', new _.triton.gluon.GluonDialect(operations));\n        this._dialects.set('ttng', new _.triton.nvidia_gpu.TritonNvidiaGPUDialect(operations));\n        this._dialects.set('nvidia_gpu', this._dialects.get('ttng'));\n        this._dialects.set('amdg', new _.triton.amdgpu.TritonAMDGPUDialect(operations));\n        this._dialects.set('amd_gpu', this._dialects.get('amdg'));\n        this._dialects.set('michelson', new _.MichelsonDialect(operations));\n        this._dialects.set('tensorrt', new _.tensorrt.TensorRTDialect(operations));\n        this._dialects.set('executor', new _.executor.ExecutorDialect(operations));\n        this._dialects.set('exec', this._dialects.get('executor'));\n        this._dialects.set('tfrt_test', new _.TFRTTestDialect(operations));\n        this._dialects.set('xevm', new _.XeVMDialect(operations));\n        this._dialects.set('vmvx', new _.VMVXDialect(operations));\n        this._dialects.set('mlrt', new _.MLRTDialect(operations));\n        this._dialects.set('tfrt_tensor', new _.TFRTTensorDialect(operations));\n        this._dialects.set('tfrt_dht', new _.TFRTDHTDialect(operations));\n        this._dialects.set('coo', new _.Dialect(operations, 'coo'));\n        this._dialects.set('tfd', new _.TFDDialect(operations));\n        this._dialects.set('acc', new _.ACCDialect(operations));\n        this._dialects.set('cuda', new _.Dialect(operations, 'cuda'));\n        this._dialects.set('trtrt', new _.Dialect(operations, 'trtrt'));\n        this._dialects.set('plan', new _.PlanDialect(operations));\n        this._dialects.set('kernel', new _.KernelDialect(operations));\n        this._dialects.set('nvg', new _.Dialect(operations, 'nvg'));\n        this._dialects.set('mpi', new _.Dialect(operations, 'mpi'));\n        this._dialects.set('pdl_interp', new _.PDLInterpDialect(operations));\n        this._dialects.set('standalone', new _.Dialect(operations, 'standalone'));\n        this._dialects.set('custom', new _.Dialect(operations, 'custom'));\n        this._dialects.set('layer', new _.Dialect(operations, 'layer'));\n        this._dialects.set('foo', new _.Dialect(operations, 'foo'));\n        this._dialects.set('some', new _.Dialect(operations, 'some'));\n        this._dialects.set('ts', new _.Dialect(operations, 'ts'));\n        this._dialects.set('tf_mlrt', new _.Dialect(operations, 'tf_mlrt'));\n        this._dialects.set('io_parameters', new _.IOParametersDialect(operations));\n        this._dialects.set('pcf', new _.PCFDialect(operations));\n        this._dialects.set('linalgx', new _.Dialect(operations, 'linalgx'));\n        this._dialects.set('xsmm', new _.XSMMDialect(operations));\n        this._dialects.set('sdy', new _.SdyDialect(operations));\n        this._dialects.set('mpmd', new _.MPMDDialect(operations));\n        this._dialects.set('tfg', new _.TFGDialect(operations));\n        this._dialects.set('vt', new _.Dialect(operations, 'vt'));\n        this._dialects.set('testd', new _.Dialect(operations, 'testd'));\n        this._dialects.set('cmath', new _.Dialect(operations, 'cmath'));\n        this._dialects.set('bytecode', new _.Dialect(operations, 'bytecode'));\n        this._dialects.set('test_irdl_to_cpp', new _.Dialect(operations, 'test_irdl_to_cpp'));\n        this._dialects.set('iree_unregistered', new _.Dialect(operations, 'iree_unregistered'));\n        this._dialects.set('cir', new _.Dialect(operations, 'cir'));\n        this._dialects.set('migraphx', new _.Dialect(operations, 'migraphx'));\n        this._dialects.set('xla', new _.XlaDialect(operations));\n        this._dialects.set('xla_gpu', new _.XlaGpuDialect(operations));\n        this._dialects.set('xla_cpu', new _.Dialect(operations, 'xla_cpu'));\n        this._dialects.set('xla_framework', new _.Dialect(operations, 'xla_framework'));\n        this._dialects.set('ifrt', new _.Dialect(operations, 'ifrt'));\n        this._dialects.set('vifrt', new _.Dialect(operations, 'vifrt'));\n        this._dialects.set('triton_xla', new _.triton.xla.TritonXlaDialect(operations));\n        this._dialects.set('xtile', new _.XTileDialect(operations));\n        this._dialects.set('xten_nn', new _.XtenNNDialect(operations));\n        this._dialects.set('ensemble', new _.EnsembleDialect(operations));\n        this._dialects.set('poly', new _.PolyDialect(operations));\n        this._dialects.set('noisy', new _.NoisyDialect(operations));\n        this._dialects.set('plugin', new _.Dialect(operations, 'plugin'));\n        this._dialects.set('ttcore', new _.Dialect(operations, 'ttcore'));\n        this._dialects.set('ttir', new _.Dialect(operations, 'ttir'));\n        this._dialects.set('ttnn', new _.Dialect(operations, 'ttnn'));\n        this._dialects.set('ttkernel', new _.Dialect(operations, 'ttkernel'));\n        this._dialects.set('ttmetal', new _.Dialect(operations, 'ttmetal'));\n    }\n\n    getOrLoadDialect(name) {\n        return this._dialects.get(name);\n    }\n\n    getLoadedDialect(name) {\n        return this._dialects.has(name);\n    }\n\n    checkDialect(dialect, dialectName, context) {\n        if (!dialect) {\n            switch (dialectName) {\n                case 'bstnnx':\n                case 'common':\n                case 'dxgml':\n                case 'dxgml_pattern':\n                case 'gim':\n                case 'nir':\n                case 'nn':\n                case 'torq_hl':\n                case 'xir':\n                case 'xth':\n                    throw new mlir.Error(`Undocumented ${context} dialect '${dialectName}'.`);\n                default:\n                    throw new mlir.Error(`Unsupported ${context} dialect '${dialectName}'.`);\n            }\n        }\n    }\n};\n\n_.Dialect = class {\n\n    constructor(operations, name) {\n        this._name = name;\n        this._operations = new Map();\n        this._customDirectives = new Map();\n        this._customTypes = new Map();\n        this._customAttributes = new Map();\n        this.registerCustomDirective('DynamicIndexList', this.parseDynamicIndexList.bind(this));\n        this.registerCustomDirective('NestedDynamicIndexList', this.parseNestedDynamicIndexList.bind(this));\n        this.registerCustomDirective('Offsets', this.parseOffsets.bind(this));\n        this.registerCustomDirective('SymbolVisibility', this.parseSymbolVisibility.bind(this));\n        this.registerCustomDirective('TypeOrAttr', this.parseTypeOrAttr.bind(this));\n        this.registerCustomDirective('CopyOpRegion', this.parseCopyOpRegion.bind(this));\n        this.registerCustomDirective('SizeAwareType', this.parseSizeAwareType.bind(this));\n        this.registerCustomDirective('ResultTypeList', this.parseResultTypeList.bind(this));\n        this.registerCustomDirective('CmdParameterGatherOperations', this.parseCmdParameterGatherOperations.bind(this));\n        this.registerCustomDirective('AsyncParameterGatherOperations', this.parseAsyncParameterGatherOperations.bind(this));\n        this.registerCustomDirective('CmdParameterScatterOperations', this.parseCmdParameterScatterOperations.bind(this));\n        this.registerCustomDirective('AsyncParameterScatterOperations', this.parseAsyncParameterScatterOperations.bind(this));\n        this.registerCustomDirective('PipelineAttr', this.parsePipelineAttr.bind(this));\n        this.registerCustomDirective('KnobsDictionary', this.parseKnobsDictionary.bind(this));\n        this.registerCustomAttribute('TypedAttrInterface', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('VM_ConstantIntegerValueAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('Util_AnySerializableAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('DenseElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('I32ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('I64ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('F64ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('IndexElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('AnyI32ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('AnyIntElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('StringElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('RankedF32ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('RankedF64ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('RankedI32ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('RankedI64ElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('SignlessIntElementsAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('AnyAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('UnitAttr', this.parseUnitAttr.bind(this));\n        this.registerCustomAttribute('UnitProp', this.parseUnitAttr.bind(this));\n        this.registerCustomAttribute('SymbolNameAttr', this.parseSymbolNameAttr.bind(this));\n        this.registerCustomAttribute('SymbolRefAttr', this.parseSymbolRefAttr.bind(this));\n        this.registerCustomAttribute('FlatSymbolRefAttr', this.parseFlatSymbolRefAttr.bind(this));\n        this.registerCustomAttribute('OptionalAttr', this.parseOptionalAttr.bind(this));\n        this.registerCustomAttribute('OptionalProp', this.parseOptionalAttr.bind(this));\n        this.registerCustomAttribute('DefaultValuedOptionalAttr', this.parseDefaultValuedOptionalAttr.bind(this));\n        this.registerCustomAttribute('DefaultValuedAttr', this.parseDefaultValuedAttr.bind(this));\n        this.registerCustomAttribute('DefaultValuedEnumAttr', this.parseDefaultValuedAttr.bind(this));\n        this.registerCustomAttribute('DefaultValuedProp', this.parseDefaultValuedAttr.bind(this));\n        this.registerCustomAttribute('ConfinedAttr', this.parseConfinedAttr.bind(this));\n        this.registerCustomAttribute('IntValidAlignment', this.parseConfinedAttr.bind(this));\n        this.registerCustomAttribute('TypeAttrOf', this.parseTypeAttrOf.bind(this));\n        this.registerCustomAttribute('AnyAttrOf', this.parseAnyAttrOf.bind(this));\n        this.registerCustomAttribute('ArrayAttr', this.parseArrayAttr.bind(this));\n        this.registerCustomAttribute('TypedArrayAttrBase', this.parseArrayAttr.bind(this));\n        this.registerCustomAttribute('DenseI64ArrayAttr', _.DenseI64ArrayAttr.parse);\n        this.registerCustomAttribute('I64Attr', (parser) => parser.parseAttribute(new _.IntegerType('i64')));\n        this.registerCustomAttribute('I32Attr', (parser) => parser.parseAttribute(new _.IntegerType('i32')));\n        this.registerCustomAttribute('I16Attr', (parser) => parser.parseAttribute(new _.IntegerType('i16')));\n        this.registerCustomAttribute('I8Attr', (parser) => parser.parseAttribute(new _.IntegerType('i8')));\n        this.registerCustomAttribute('I1Attr', (parser) => parser.parseAttribute(new _.IntegerType('i1')));\n        this.registerCustomAttribute('SI64Attr', (parser) => parser.parseAttribute(new _.IntegerType('si64')));\n        this.registerCustomAttribute('SI32Attr', (parser) => parser.parseAttribute(new _.IntegerType('si32')));\n        this.registerCustomAttribute('UI64Attr', (parser) => parser.parseAttribute(new _.IntegerType('ui64')));\n        this.registerCustomAttribute('UI32Attr', (parser) => parser.parseAttribute(new _.IntegerType('ui32')));\n        this.registerCustomAttribute('IndexAttr', (parser) => parser.parseAttribute(new _.IntegerType('index')));\n        this.registerCustomAttribute('I64Prop', (parser) => parser.parseAttribute(new _.IntegerType('i64')));\n        this.registerCustomAttribute('I32Prop', (parser) => parser.parseAttribute(new _.IntegerType('i32')));\n        this.registerCustomAttribute('AlignmentProp', (parser) => parser.parseAttribute(new _.IntegerType('i64')));\n        this.registerCustomAttribute('F64Attr', (parser) => parser.parseAttribute(new _.FloatType('f64')));\n        this.registerCustomAttribute('F32Attr', (parser) => parser.parseAttribute(new _.FloatType('f32')));\n        this.registerCustomAttribute('F16Attr', (parser) => parser.parseAttribute(new _.FloatType('f16')));\n        this.registerCustomAttribute('BF16Attr', (parser) => parser.parseAttribute(new _.FloatType('bf16')));\n        this.registerCustomAttribute('StrAttr', (parser) => parser.parseAttribute(new _.PrimitiveType('string')));\n        this.registerCustomAttribute('TypedStrAttr', this.parseTypedAttrInterface.bind(this));\n        this.registerCustomAttribute('LevelAttr', (parser) => parser.parseAttribute(new _.IntegerType('index')));\n        this.registerCustomType('Optional', this.parseOptional.bind(this));\n        this.registerCustomType('AnyTypeOf', (parser) => parser.parseType());\n        for (const metadata of operations.get(name) || []) {\n            this.registerOperandName(metadata.name, metadata);\n        }\n    }\n\n    get name() {\n        return this._name;\n    }\n\n    readType(/* reader */) {\n        throw new mlir.Error(`Bytecode dialect '${this._name}' does not support bytecode types.`);\n    }\n\n    readAttribute(/* reader */) {\n        throw new mlir.Error(`Dialect '${this._name}' does not support bytecode attributes.`);\n    }\n\n    parseResource(/* entry */) {\n        throw new mlir.Error(`Dialect '${this._name}' does not support resources.`);\n    }\n\n    getOperation(opName) {\n        const op = this._operations.get(opName);\n        if (op && !op.metadata._) {\n            if (Array.isArray(op.metadata.operands)) {\n                for (const input of op.metadata.operands) {\n                    if (input && input.type) {\n                        input.type = _.Constraint.parse(input.type);\n                    }\n                }\n            }\n            if (Array.isArray(op.metadata.results)) {\n                for (const output of op.metadata.results) {\n                    if (output && output.type) {\n                        output.type = _.Constraint.parse(output.type);\n                    }\n                }\n            }\n            if (Array.isArray(op.metadata.attributes)) {\n                for (const attribute of op.metadata.attributes) {\n                    if (attribute && attribute.type) {\n                        attribute.type = _.Constraint.parse(attribute.type);\n                    }\n                }\n            }\n            if (Array.isArray(op.metadata.regions)) {\n                for (const region of op.metadata.regions) {\n                    if (region && region.type) {\n                        region.type = _.Constraint.parse(region.type);\n                    }\n                }\n            }\n            if (Array.isArray(op.metadata.traits)) {\n                for (const trait of op.metadata.traits) {\n                    if (trait && trait.type) {\n                        trait.type = _.Constraint.parse(trait.type);\n                    }\n                }\n            }\n            op.metadata._ = true;\n        }\n        return op || null;\n    }\n\n    registerOperandName(opName, metadata) {\n        const opInfo = new _.RegisteredOperationName(this, opName, metadata);\n        this._operations.set(opName, opInfo);\n    }\n\n    registerCustomDirective(name, parserFn) {\n        this._customDirectives.set(name, parserFn);\n    }\n\n    registerCustomType(name, parserFn) {\n        this._customTypes.set(name, parserFn);\n    }\n\n    registerCustomAttribute(name, parserFn) {\n        this._customAttributes.set(name, parserFn);\n    }\n\n    createBuildableType(constraint) {\n        switch (constraint.name) {\n            case 'AMDGPU_TDMDescriptorType': return new _.Type('!amdgpu.tdm.descriptor');\n            case 'AnyIRModule': return new _.Type('!transform.any_op');\n            case 'AnySignlessIntegerOrIndex': return new _.IndexType();\n            case 'Async_CoroHandleType': return new _.Type('!async.coro.handle');\n            case 'Async_CoroIdType': return new _.Type('!async.coro.id');\n            case 'Async_CoroStateType': return new _.Type('!async.coro.state');\n            case 'Async_GroupType': return new _.async.GroupType();\n            case 'Async_TokenType': return new _.async.TokenType();\n            case 'Async_ValueType': return new _.async.ValueType(new _.MemRefType([-1n], new _.Type('f32')));\n            case 'BF16': return new _.Type('bf16');\n            case 'BoolType': return new _.Type('!smt.bool');\n            case 'CanonicalLoopInfoType': return new _.Type('!omp.canonical_loop_info');\n            case 'ControlType': return new _.Type('!tf_type.control');\n            case 'CoreRT_OpHandlerType': return new _.Type('!corert.ophandler');\n            case 'CoreRT_StringType': return new _.Type('!corert.string');\n            case 'CoreRT_TensorHandleType': return new _.Type('!corert.tensorhandle');\n            case 'CUDA_BlasGemmAlgorithm': return new _.Type('!cuda.blas.gemm_algorithm');\n            case 'CUDA_BlasHandle': return new _.Type('!cuda.blas.handle');\n            case 'CUDA_Device': return new _.Type('!cuda.device');\n            case 'CUDA_Event': return new _.Type('!cuda.event');\n            case 'CUDA_Function': return new _.Type('!cuda.function');\n            case 'CUDA_Module': return new _.Type('!cuda.module');\n            case 'CUDA_Stream': return new _.Type('!cuda.stream');\n            case 'EmitC_PointerType': return new _.Type('!emitc.ptr<i32>');\n            case 'Executor_HostPtr': return new _.Type('!executor.ptr<host>');\n            case 'Executor_StrLiteral': return new _.Type('!executor.str_literal');\n            case 'Executor_Table': return new _.Type('!executor.table<>');\n            case 'F128': return new _.Type('f128');\n            case 'F16': return new _.Type('f16');\n            case 'F32': return new _.Type('f32');\n            case 'F4E2M1FN': return new _.Type('f4E2M1FN');\n            case 'F64': return new _.Type('f64');\n            case 'F6E2M3FN': return new _.Type('f6E2M3FN');\n            case 'F6E3M2FN': return new _.Type('f6E3M2FN');\n            case 'F80': return new _.Type('f80');\n            case 'F8E3M4': return new _.Type('f8E3M4');\n            case 'F8E4M3': return new _.Type('f8E4M3');\n            case 'F8E4M3B11FNUZ': return new _.Type('f8E4M3B11FNUZ');\n            case 'F8E4M3FN': return new _.Type('f8E4M3FN');\n            case 'F8E4M3FNUZ': return new _.Type('f8E4M3FNUZ');\n            case 'F8E5M2': return new _.Type('f8E5M2');\n            case 'F8E5M2FNUZ': return new _.Type('f8E5M2FNUZ');\n            case 'F8E8M0FNU': return new _.Type('f8E8M0FNU');\n            case 'FLOW_Channel': return new _.Type('!flow.channel');\n            case 'GPU_AsyncToken': return new _.Type('!gpu.async.token');\n            case 'GPU_SparseDnTensorHandle': return new _.Type('!gpu.sparse.dntensor_handle');\n            case 'GPU_SparseSpGEMMOpHandle': return new _.Type('!gpu.sparse.spgemmop_handle');\n            case 'GPU_SparseSpMatHandle': return new _.Type('!gpu.sparse.spmat_handle');\n            case 'HostBufferType': return new _.Type('!tfrt_ht.host_buffer');\n            case 'I1': return new _.IntegerType('i1');\n            case 'I128': return new _.IntegerType('i128');\n            case 'I16': return new _.IntegerType('i16');\n            case 'I32': return new _.IntegerType('i32');\n            case 'I64': return new _.IntegerType('i64');\n            case 'I8': return new _.IntegerType('i8');\n            case 'Ifrt_ArrayType': return new _.Type('!ifrt.array');\n            case 'Ifrt_ControlType': return new _.Type('!ifrt.control');\n            case 'Index': return new _.IndexType();\n            case 'IntType': return new _.Type('!smt.int');\n            case 'IRDL_AttributeType': return new _.Type('!irdl.attribute');\n            case 'IRDL_RegionType': return new _.Type('!irdl.region');\n            case 'IREE_Input_GlobalRefAttr': return new _.Type('!iree_input.global.ref');\n            case 'LLVM_DefaultPointer': return new _.llvm.LLVMPointerType(0);\n            case 'LLVM_PointerGeneric': return new _.llvm.LLVMPointerType(0);\n            case 'LLVM_PointerGlobal': return new _.llvm.LLVMPointerType(1);\n            case 'LLVM_PointerShared': return new _.llvm.LLVMPointerType(3);\n            case 'LLVM_PointerSharedCluster': return new _.llvm.LLVMPointerType(7);\n            case 'LLVM_PointerTensor': return new _.llvm.LLVMPointerType(6);\n            case 'LLVM_PointerTensorMemory': return new _.llvm.LLVMPointerType(6);\n            case 'LLVM_TokenType': return new _.Type('!llvm.token');\n            case 'MLProgram_TokenType': return new _.Type('!ml_program.token');\n            case 'MlrtAsyncHandleType': return new _.Type('!mlrt.async_handle');\n            case 'MlrtFutureType': return new _.Type('!mlrt.future');\n            case 'MlrtPromiseType': return new _.Type('!mlrt.promise');\n            case 'MPI_Comm': return new _.Type('!mpi.comm');\n            case 'MPI_Request': return new _.Type('!mpi.request');\n            case 'MPI_Retval': return new _.Type('!mpi.retval');\n            case 'Noisy_I32': return new _.Type('!noisy.i32');\n            case 'NoneType': return new _.Type('none');\n            case 'NullPointer': return new _.Type('!iree_codegen.null_pointer');\n            case 'NVGPU_DeviceAsyncToken': return new _.Type('!nvgpu.device.async.token');\n            case 'NVGPU_MmaSparseSyncMetadataType': return new _.VectorType([2n], new _.IntegerType('i16'));\n            case 'OMP_MapBoundsType': return new _.Type('!omp.map_bounds_ty');\n            case 'OpaqueTensorType': return new _.Type('!tf_type.tensor');\n            case 'OpenACC_DataBoundsType': return new _.Type('!acc.data_bounds');\n            case 'OpenACC_DeclareTokenType': return new _.Type('!acc.declare_token');\n            case 'OpenACC_ParWidthType': return new _.Type('!acc.par_width');\n            case 'OpenMP_MapBoundsType': return new _.Type('!omp.map_bounds_ty');\n            case 'PDL_Attribute': return new _.pdl.AttributeType();\n            case 'PDL_Operation': return new _.pdl.OperationType();\n            case 'PDL_OperationType': return new _.pdl.OperationType();\n            case 'PDL_RangeOf': return new _.pdl.RangeType(this.createBuildableType(constraint.args[0]));\n            case 'PDL_RangeType': return new _.Type('!pdl.range<type>');\n            case 'PDL_Type': return new _.pdl.TypeType();\n            case 'PDL_TypeType': return new _.pdl.TypeType();\n            case 'PDL_Value': return new _.pdl.ValueType();\n            case 'PDL_ValueType': return new _.pdl.ValueType();\n            case 'Ptr_PtrType': return new _.Type('!ptr.ptr');\n            case 'ROCDL_V16BF16Type': return new _.VectorType([16n], new _.Type('bf16'));\n            case 'ROCDL_V16F16Type': return new _.VectorType([16n], new _.Type('f16'));\n            case 'ROCDL_V16F32Type': return new _.VectorType([16n], new _.Type('f32'));\n            case 'ROCDL_V2BF16Type': return new _.VectorType([2n], new _.Type('bf16'));\n            case 'ROCDL_V2F16Type': return new _.VectorType([2n], new _.Type('f16'));\n            case 'ROCDL_V2F32Type': return new _.VectorType([2n], new _.Type('f32'));\n            case 'ROCDL_V2I16Type': return new _.VectorType([2n], new _.IntegerType('i16'));\n            case 'ROCDL_V2I32Type': return new _.VectorType([2n], new _.IntegerType('i32'));\n            case 'ROCDL_V32BF16Type': return new _.VectorType([32n], new _.Type('bf16'));\n            case 'ROCDL_V32F16Type': return new _.VectorType([32n], new _.Type('f16'));\n            case 'ROCDL_V32F32Type': return new _.VectorType([32n], new _.Type('f32'));\n            case 'ROCDL_V3I32Type': return new _.VectorType([3n], new _.IntegerType('i32'));\n            case 'ROCDL_V6I32Type': return new _.VectorType([6n], new _.IntegerType('i32'));\n            case 'ROCDL_V8BF16Type': return new _.VectorType([8n], new _.Type('bf16'));\n            case 'ROCDL_V8F16Type': return new _.VectorType([8n], new _.Type('f16'));\n            case 'ROCDL_V8F32Type': return new _.VectorType([8n], new _.Type('f32'));\n            case 'Shape_ExtentTensorType': return new _.RankedTensorType([_.ShapedType.kDynamic], new _.IndexType());\n            case 'Shape_ShapeType': return new _.Type('!shape.shape');\n            case 'Shape_SizeType': return new _.Type('!shape.size');\n            case 'Shape_ValueShapeType': return new _.Type('!shape.value_shape');\n            case 'Shape_WitnessType': return new _.Type('!shape.witness');\n            case 'StaticShapeTensorOf': return new _.UnrankedTensorType(this.createBuildableType(constraint.args[0][0]));\n            case 'SI16': return new _.IntegerType('si16');\n            case 'SI32': return new _.IntegerType('si32');\n            case 'SI64': return new _.IntegerType('si64');\n            case 'SI8': return new _.IntegerType('si8');\n            case 'SMTFuncType': return new _.Type('!smt.func<() -> ()>');\n            case 'SPIRV_AnyPtr': return new _.Type('!spirv.ptr<i32, StorageBuffer>');\n            case 'SPIRV_BFloat16KHR': return new _.FloatType('bf16');\n            case 'SPIRV_Bool': return new _.IntegerType('i1');\n            case 'SPIRV_Float16': return new _.FloatType('f16');\n            case 'SPIRV_Float32': return new _.FloatType('f32');\n            case 'SPIRV_Int8': return new _.IntegerType('i8');\n            case 'SPIRV_Int16': return new _.IntegerType('i16');\n            case 'SPIRV_Int32': return new _.IntegerType('i32');\n            case 'SPIRV_Int32Vec4': return new _.VectorType([4n], new _.IntegerType('i32'));\n            case 'Stream_Channel': return new _.Type('!stream.channel');\n            case 'Stream_Dim': return new _.IndexType();\n            case 'Stream_Offset': return new _.IndexType();\n            case 'Stream_Size': return new _.IndexType();\n            case 'TensorRTRuntime_Context': return new _.Type('!trtrt.context');\n            case 'TensorRTRuntime_Engine': return new _.Type('!trtrt.engine');\n            case 'TensorType': return new _.Type('!tfrt_tensor.tensor');\n            case 'TF_MLRT_FutureType': return new _.Type('!tf_mlrt.tensor');\n            case 'TF32': return new _.Type('tf32');\n            case 'TFAllocatorType': return new _.Type('!tfrt_fallback.tf_allocator');\n            case 'TFDeviceType': return new _.Type('!tf_mlrt.device');\n            case 'TfeControlType': return new _.Type('!tfe.control');\n            case 'TfeTokenType': return new _.Type('!tfe.token');\n            case 'TFFramework_JITCallableType': return new _.Type('!tf_framework.jit_callable');\n            case 'TFFramework_OpKernelContextType': return new _.Type('!tf_framework.op_kernel_context');\n            case 'TFL_Control': return new _.Type('!tfl.control');\n            case 'TFL_Quint8': return new _.Type('!quant.uniform<u8:f32, 1.0>');\n            case 'TFL_Str': return new _.Type('!tf.string');\n            case 'TFR_AttrType': return new _.Type('!tfr.attr');\n            case 'TFR_TensorListType': return new _.Type('!tfr.tensor_list');\n            case 'TFR_TensorType': return new _.Type('!tfr.tensor');\n            case 'TFRT_ChainType': return new _.Type('!tfrt.chain');\n            case 'TFRT_DeviceType': return new _.Type('!tfrt.device');\n            case 'TFRT_Fallback_TFTensorType': return new _.Type('!tfrt_fallback.tf_tensor');\n            case 'TFRT_StringType': return new _.Type('!tfrt.string');\n            case 'TFRT_TensorTypeType': return new _.Type('!tfrt.tensor_type');\n            case 'TFTensorType': return new _.Type('!tfrt_fallback.tf_tensor');\n            case 'Torch_BoolType': return new _.Type('!torch.bool');\n            case 'Torch_DeviceType': return new _.Type('!torch.Device');\n            case 'Torch_FloatType': return new _.Type('!torch.float');\n            case 'Torch_GeneratorType': return new _.Type('!torch.Generator');\n            case 'Torch_IntType': return new _.Type('!torch.int');\n            case 'Torch_LinearParamsType': return new _.Type('!torch.LinearParams');\n            case 'Torch_NoneType': return new _.Type('!torch.none');\n            case 'Torch_NumberType': return new _.Type('!torch.number');\n            case 'Torch_StringType': return new _.Type('!torch.str');\n            case 'Transform_AffineMapParamType': return new _.Type('!transform.affine_map');\n            case 'Transform_AnyOpType': return new _.Type('!transform.any_op');\n            case 'Transform_AnyParamType': return new _.Type('!transform.any_param');\n            case 'Transform_AnyValue': return new _.Type('!transform.any_value');\n            case 'Transform_AnyValueType': return new _.Type('!transform.any_value');\n            case 'Transform_ParamType': return new _.Type('!transform.param<i64>');\n            case 'Transform_TypeParamType': return new _.Type('!transform.type');\n            case 'TransformHandleTypeInterface': return new _.Type('!transform.any_op');\n            case 'TestTransformTestDialectParamType': return new _.Type('!transform.test_dialect_param');\n            case 'TS_FixedRankShape': return new _.OpaqueType('ts', `.fixed_rank_shape.${constraint.args[0].name}`);\n            case 'TS_PartialShape': return new _.Type('!ts.partial_shape');\n            case 'TS_Shape': return new _.Type('!ts.shape');\n            case 'TTG_AsyncToken': return new _.Type('!ttg.async.token');\n            case 'UI16': return new _.IntegerType('ui16');\n            case 'UI32': return new _.IntegerType('ui32');\n            case 'UI64': return new _.IntegerType('ui64');\n            case 'UI8': return new _.IntegerType('ui8');\n            case 'Util_BufferType': return new _.Type('!util.buffer');\n            case 'Util_Offset': return new _.IndexType();\n            case 'Util_Size': return new _.IndexType();\n            case 'VM_CondValue': return new _.IntegerType('i32');\n            case 'VM_RefType': return new _.Type('!vm.ref<?>');\n            case 'XeGPU_Nbarrier': return new _.Type('!xegpu.nbarrier');\n            case 'XLA_BufferType': return new _.Type('!xla_framework.buffer');\n            case 'XLAFramework_BufferType': return new _.Type('!xla_framework.buffer');\n            default: return null;\n        }\n    }\n\n    inferResultTypes(op, vars) {\n        const metadata = op.name.getRegisteredInfo()?.metadata;\n        if (!metadata?.results) {\n            return;\n        }\n        // If type(results) was used in the format, all result types were explicitly parsed\n        if (vars.has('results') && vars.get('results').types.length > 0) {\n            if (op.types.length === 0) {\n                op.addTypes(vars.get('results').types);\n            }\n            return;\n        }\n        const operandNames = metadata.operands?.map((o) => o.name) || [];\n        // Build result types in metadata order\n        const orderedTypes = [];\n        // Track current offset in op.types for custom directive handling\n        let customDirectiveOffset = 0;\n        // Iterate over each result in metadata order\n        for (const resultInfo of metadata.results) {\n            // If this result was parsed from assembly format, use those types\n            if (vars.has(resultInfo.name) && vars.get(resultInfo.name).types.length > 0) {\n                const varTypes = vars.get(resultInfo.name).types;\n                orderedTypes.push(...varTypes);\n                customDirectiveOffset += varTypes.length;\n                continue;\n            }\n            const mnemonic = typeof resultInfo.type === 'string' ? resultInfo.type : resultInfo.type?.name;\n            const isVariadicOrOptional = mnemonic === 'Variadic' || mnemonic === 'Optional';\n            // For Variadic/Optional not in vars, check if custom directive added types to op.types\n            if (isVariadicOrOptional && op.types.length > customDirectiveOffset) {\n                // Count how many types belong to this variadic result\n                // (all types from customDirectiveOffset to end, minus types for later results in vars)\n                let typesForLaterResults = 0;\n                for (let i = metadata.results.indexOf(resultInfo) + 1; i < metadata.results.length; i++) {\n                    const laterResult = metadata.results[i];\n                    if (vars.has(laterResult.name) && vars.get(laterResult.name).types.length > 0) {\n                        typesForLaterResults += vars.get(laterResult.name).types.length;\n                    }\n                }\n                const variadicCount = op.types.length - customDirectiveOffset - typesForLaterResults;\n                if (variadicCount > 0) {\n                    for (let i = 0; i < variadicCount; i++) {\n                        orderedTypes.push(op.types[customDirectiveOffset + i]);\n                    }\n                    customDirectiveOffset += variadicCount;\n                    continue;\n                }\n            }\n            // Try to resolve from traits\n            let resolved = false;\n            if (metadata.traits) {\n                for (const trait of metadata.traits) {\n                    if (resolved) {\n                        break;\n                    }\n                    // Handle both string and object trait types\n                    const traitName = trait.type?.name;\n                    const traitArgs = trait.type?.args;\n                    // SameOperandsAndResultType: result type = first operand type\n                    if (traitName === 'SameOperandsAndResultType') {\n                        if (op.operands.length > 0 && op.operands[0].type) {\n                            orderedTypes.push(op.operands[0].type);\n                            resolved = true;\n                        }\n                    }\n                    // AllTypesMatch: result type = matched operand/result/attribute type\n                    if (traitName === 'AllTypesMatch') {\n                        const names = traitArgs?.[0];\n                        if (Array.isArray(names) && (names.includes(resultInfo.name) || (resultInfo.name === 'result' && names.includes('result')))) {\n                            const sourceTypes = [];\n                            for (const argName of names) {\n                                if (argName === resultInfo.name) {\n                                    continue;\n                                }\n                                // Check if source is in vars (another parsed result)\n                                if (vars.get(argName) && vars.get(argName).types.length > 0) {\n                                    sourceTypes.push(...vars.get(argName).types);\n                                    break;\n                                }\n                                // Check if source is an operand\n                                const operandMetaIdx = operandNames.indexOf(argName);\n                                if (operandMetaIdx >= 0) {\n                                    const operandMeta = metadata.operands[operandMetaIdx];\n                                    const operandTypeObj = operandMeta?.type;\n                                    const operandTypeName = typeof operandTypeObj === 'string' ? operandTypeObj : (operandTypeObj?.name || '');\n                                    const isVariadic = operandTypeName === 'Variadic' || operandTypeName.startsWith('Variadic<');\n                                    if (isVariadic) {\n                                        for (let j = 0; j < op.operands.length; j++) {\n                                            if (op.operands[j].type) {\n                                                sourceTypes.push(op.operands[j].type);\n                                            }\n                                        }\n                                    } else if (operandMetaIdx < op.operands.length && op.operands[operandMetaIdx].type) {\n                                        sourceTypes.push(op.operands[operandMetaIdx].type);\n                                    }\n                                    if (sourceTypes.length > 0) {\n                                        break;\n                                    }\n                                }\n                                // Check if source is an attribute with a type\n                                if (metadata.attributes) {\n                                    const attrMeta = metadata.attributes.find((a) => a.name === argName);\n                                    if (attrMeta) {\n                                        const attr = op.attributes.get(argName);\n                                        if (attr && attr.type) {\n                                            sourceTypes.push(attr.type);\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                            if (sourceTypes.length > 0) {\n                                orderedTypes.push(...sourceTypes);\n                                resolved = true;\n                            }\n                        }\n                    }\n                    // TypesMatchWith: result type = transform(source type)\n                    if (traitName === 'TypesMatchWith') {\n                        const [lhsArg, rhsArg, transformer] = traitArgs || [];\n                        let resultArg = null;\n                        let sourceArg = null;\n                        if ((rhsArg === resultInfo.name || (resultInfo.name === 'result' && rhsArg === 'result'))) {\n                            resultArg = rhsArg;\n                            sourceArg = lhsArg;\n                        } else if ((lhsArg === resultInfo.name || (resultInfo.name === 'result' && lhsArg === 'result'))) {\n                            resultArg = lhsArg;\n                            sourceArg = rhsArg;\n                        }\n                        if (resultArg && sourceArg) {\n                            const sourceTypes = [];\n                            // Check if source is in vars (parsed result or operand type from type($var))\n                            if (vars.has(sourceArg) && vars.get(sourceArg).types.length > 0) {\n                                sourceTypes.push(...vars.get(sourceArg).types);\n                            }\n                            // Check if source is an operand - fall back to operand's value type\n                            if (sourceTypes.length === 0) {\n                                const operands = metadata.operands || [];\n                                let actualOperandIdx = 0;\n                                for (let i = 0; i < operands.length; i++) {\n                                    const operandTypeObj = operands[i].type;\n                                    const operandType = typeof operandTypeObj === 'string' ? operandTypeObj : (operandTypeObj?.name || '');\n                                    const isEnum = /\\{[^}]+\\}/.test(operandType) || operandType.startsWith('AtomicBinOp') || operandType.startsWith('AtomicOrdering') || operandType.startsWith('LLVM_AtomicOrdering') || operandType.includes('Enum');\n                                    if (operands[i].name === sourceArg) {\n                                        const isVariadicSource = operandType === 'Variadic';\n                                        if (isVariadicSource) {\n                                            for (let j = actualOperandIdx; j < op.operands.length; j++) {\n                                                if (op.operands[j].type) {\n                                                    sourceTypes.push(op.operands[j].type);\n                                                }\n                                            }\n                                        } else if (actualOperandIdx < op.operands.length && op.operands[actualOperandIdx].type) {\n                                            sourceTypes.push(op.operands[actualOperandIdx].type);\n                                        }\n                                        break;\n                                    }\n                                    if (!isEnum) {\n                                        actualOperandIdx++;\n                                    }\n                                }\n                            }\n                            if (sourceTypes.length > 0) {\n                                for (const sourceType of sourceTypes) {\n                                    let resultType = sourceType;\n                                    if (transformer === '::getI1SameShape($_self)') {\n                                        if (sourceType instanceof _.VectorType) {\n                                            resultType = new _.VectorType(sourceType.dimensions, new _.IntegerType('i1'), sourceType.scalableDims);\n                                        } else if (sourceType instanceof mlir.TensorType) {\n                                            resultType = new mlir.TensorType(sourceType.dimensions, new _.IntegerType('i1'));\n                                        } else {\n                                            resultType = new _.IntegerType('i1');\n                                        }\n                                    } else if (transformer && transformer.includes('.getElementType()')) {\n                                        if (sourceType && sourceType.elementType) {\n                                            resultType = sourceType.elementType;\n                                        } else {\n                                            throw new mlir.Error(`Cannot get element type.`);\n                                        }\n                                    } else if (transformer && transformer.includes('getPointeeType')) {\n                                        if (sourceType && sourceType.pointeeType) {\n                                            resultType = sourceType.pointeeType;\n                                        } else {\n                                            throw new mlir.Error(`Cannot get pointee type.`);\n                                        }\n                                    } else if (transformer && transformer.includes('getValAndBoolStructType')) {\n                                        const typeStr = sourceType.toString ? sourceType.toString() : String(sourceType);\n                                        resultType = new _.Type(`!llvm.struct<(${typeStr}, i1)>`);\n                                    } else if (transformer && transformer.includes('.getResults()')) {\n                                        // Extract results from a FunctionType\n                                        if (sourceType instanceof _.FunctionType && sourceType.results) {\n                                            orderedTypes.push(...sourceType.results);\n                                            resolved = true;\n                                            continue; // Already added results, skip single push below\n                                        }\n                                    }\n                                    if (resultType) {\n                                        orderedTypes.push(resultType);\n                                        resolved = true;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    // FirstAttrDerivedResultType: result type = first attribute's type\n                    if (traitName === 'FirstAttrDerivedResultType') {\n                        const firstAttr = metadata.attributes?.[0];\n                        if (firstAttr) {\n                            const attr = op.attributes.get(firstAttr.name);\n                            if (attr && attr.type) {\n                                orderedTypes.push(attr.type);\n                                resolved = true;\n                            }\n                        }\n                    }\n                }\n            }\n            // For single variadic result matching single variadic operand with same element type, infer from operands\n            if (!resolved && resultInfo.type?.name === 'Variadic' &&\n                metadata.results?.length === 1 && metadata.operands?.length === 1) {\n                const resultElementType = resultInfo.type.args?.[0]?.name;\n                const operandInfo = metadata.operands[0];\n                if (operandInfo.type?.name === 'Variadic' &&\n                    operandInfo.type.args?.[0]?.name === resultElementType) {\n                    for (const operand of op.operands) {\n                        if (operand.type) {\n                            orderedTypes.push(operand.type);\n                        }\n                    }\n                    resolved = orderedTypes.length > 0;\n                }\n            }\n            // Fallback: try buildable type (skip for variadic/optional)\n            if (!resolved && resultInfo.type && !isVariadicOrOptional) {\n                const type = this.createBuildableType(resultInfo.type);\n                if (type) {\n                    orderedTypes.push(type);\n                }\n            }\n        }\n        // Replace op.types with correctly ordered types\n        if (orderedTypes.length > 0) {\n            op.types.length = 0;\n            op.addTypes(orderedTypes);\n        }\n    }\n\n    parseDirective(directive, parser, op, opInfo, directives, i, vars) {\n        const isVariadic = (type) => {\n            if (type.name === 'Variadic' || type.name === 'VariadicOfVariadic') {\n                return true;\n            }\n            if (Array.isArray(type.args) && type.args.length > 0) {\n                return isVariadic(type.args[0]);\n            }\n            return false;\n        };\n        const isVariadicOfVariadic = (type) => {\n            if (type.name === 'VariadicOfVariadic') {\n                return true;\n            }\n            if (Array.isArray(type.args) && type.args.length > 0) {\n                return isVariadicOfVariadic(type.args[0]);\n            }\n            return false;\n        };\n        const isOptional = (type) => {\n            if (type.name === 'Optional') {\n                return true;\n            }\n            if (Array.isArray(type.args) && type.args.length > 0) {\n                return isOptional(type.args[0]);\n            }\n            return false;\n        };\n        const peek = (...kinds) => {\n            const token = parser.parser.getToken();\n            return kinds.some((kind) => kind === 'keyword' ? token.isKeyword() : token.is(kind));\n        };\n        switch (directive.type) {\n            case 'whitespace':\n                // Skip whitespace directives - they're just formatting hints\n                break;\n            case 'literal':\n                // Make '[' optional when followed by a variadic operand with buildable type\n                if (directive.value === '[') {\n                    if (!parser.parseOptionalLSquare()) {\n                        const nextDir = directives[i + 1];\n                        if (nextDir && nextDir.type === 'operand_ref') {\n                            const operandMeta = opInfo.metadata?.operands?.find((o) => o.name === nextDir.name);\n                            if (operandMeta && isVariadic(operandMeta.type)) {\n                                vars.set('_skipClosingBracket', true);\n                                break;\n                            }\n                        }\n                        parser.parseLSquare();\n                    }\n                    break;\n                }\n                if (directive.value === ']' && vars.get('_skipClosingBracket')) {\n                    vars.delete('_skipClosingBracket');\n                    break;\n                }\n                switch (directive.value) {\n                    case '(': parser.parseLParen(); break;\n                    case ')': parser.parseRParen(); break;\n                    case '[': parser.parseLSquare(); break;\n                    case ']': parser.parseRSquare(); break;\n                    case '{': parser.parseLBrace(); break;\n                    case '}': parser.parseRBrace(); break;\n                    case ':': parser.parseColon(); break;\n                    case '=': parser.parseEqual(); break;\n                    case ',': parser.parseComma(); break;\n                    case '<': parser.parseLess(); break;\n                    case '>': parser.parseGreater(); break;\n                    case '->': parser.parseArrow(); break;\n                    case '*': parser.parseStar(); break;\n                    case '+': parser.parsePlus(); break;\n                    case '?': parser.parseQuestion(); break;\n                    case '|': parser.parseVerticalBar(); break;\n                    case '...': parser.parseEllipsis(); break;\n                    default: parser.parseKeyword(directive.value); break;\n                }\n                break;\n            case 'region_ref': {\n                const regionMeta = opInfo.metadata && opInfo.metadata.regions && opInfo.metadata.regions.find((r) => r.name === directive.name);\n                const isVariadicRegion = regionMeta && regionMeta.type && regionMeta.type.name === 'VariadicRegion';\n                const isIsolated = op.name.getRegisteredInfo().hasTrait('IsolatedFromAbove');\n                if (isVariadicRegion) {\n                    if (parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                        while (parser.parseOptionalComma()) {\n                            if (!parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                                break;\n                            }\n                        }\n                    }\n                } else {\n                    const region = op.addRegion();\n                    parser.parseRegion(region, undefined, isIsolated);\n                }\n                break;\n            }\n            case 'successor_ref': {\n                if (!op.successors) {\n                    op.successors = [];\n                }\n                // Check if this successor is variadic from metadata or context\n                const refName = directive.name;\n                let isVariadicSuccessor = false;\n                if (opInfo.metadata && opInfo.metadata.successors) {\n                    const successorMeta = opInfo.metadata.successors.find((s) => s.name === refName);\n                    if (successorMeta && successorMeta.type) {\n                        // Check for VariadicSuccessor type\n                        const typeStr = typeof successorMeta.type === 'string' ? successorMeta.type : successorMeta.type.name;\n                        isVariadicSuccessor = typeStr && typeStr.startsWith('VariadicSuccessor');\n                    }\n                }\n                // Also check context: if next directive is ')' literal, we're inside parentheses\n                const nextDir = i + 1 < directives.length ? directives[i + 1] : null;\n                const isVariadicContext = isVariadicSuccessor || (nextDir && nextDir.type === 'literal' && nextDir.value === ')');\n                // Check if next directive is a custom directive that handles the parentheses (like ResultTypeList)\n                const nextDirHandlesParens = nextDir && nextDir.type === 'custom' &&\n                    (nextDir.parser === 'ResultTypeList' || nextDir.parser === 'TypeList');\n                const parseOneSuccessor = () => {\n                    const successor = parser.parseSuccessor();\n                    // Don't consume '(' if next directive handles it (e.g., custom<ResultTypeList>)\n                    if (!nextDirHandlesParens && parser.parseOptionalLParen()) {\n                        successor.arguments = [];\n                        let operand = parser.parseOptionalOperand();\n                        while (operand) {\n                            successor.arguments.push(operand);\n                            if (!parser.parseOptionalComma()) {\n                                break;\n                            }\n                            operand = parser.parseOptionalOperand();\n                        }\n                        parser.resolveOperands(successor.arguments, parser.parseOptionalColonTypeList());\n                        parser.parseOptionalRParen();\n                    }\n                    op.successors.push(successor);\n                };\n                if (isVariadicContext) {\n                    // Variadic successors: parse 0 or more successors\n                    let successor = parser.parseOptionalSuccessor();\n                    while (successor) {\n                        // Don't consume '(' if next directive handles it\n                        if (!nextDirHandlesParens && parser.parseOptionalLParen()) {\n                            successor.arguments = [];\n                            let operand = parser.parseOptionalOperand();\n                            while (operand) {\n                                successor.arguments.push(operand);\n                                if (!parser.parseOptionalComma()) {\n                                    break;\n                                }\n                                operand = parser.parseOptionalOperand();\n                            }\n                            parser.resolveOperands(successor.arguments, parser.parseOptionalColonTypeList());\n                            parser.parseOptionalRParen();\n                        }\n                        op.successors.push(successor);\n                        if (!parser.parseOptionalComma()) {\n                            break;\n                        }\n                        successor = parser.parseOptionalSuccessor();\n                    }\n                } else {\n                    parseOneSuccessor();\n                }\n                break;\n            }\n            case 'attribute_ref': {\n                const refName = directive.name;\n                if (op.attributes.has(refName)) {\n                    break;\n                }\n                const attrInfo = opInfo.metadata && opInfo.metadata.attributes && opInfo.metadata.attributes.find((attr) => attr.name === refName);\n                const attrType = attrInfo ? attrInfo.type : null;\n                let attrValue = null;\n                // Pass type to suppress : type suffix parsing (it's a separate directive in assembly format)\n                if (attrType && attrType !== 'Attribute') {\n                    attrValue = this.parseCustomAttributeWithFallback(parser, attrType);\n                } else {\n                    attrValue = parser.parseAttribute(attrType || 'Attribute');\n                }\n                if (attrValue) {\n                    op.addAttribute(refName, attrValue);\n                }\n                break;\n            }\n            case 'operand_ref': {\n                const name = directive.name;\n                const input = opInfo.metadata?.operands?.find((inp) => inp.name === name);\n                const isVariadicOp = input ? isVariadic(input.type) : false;\n                const isVariadicOfVariadicOp = input ? isVariadicOfVariadic(input.type) : false;\n                const isOptionalOp = input ? isOptional(input.type) : false;\n                // Check for buildable types using createType\n                let buildableType = null;\n                if (isVariadicOp && input?.type?.args?.[0]) {\n                    buildableType = this.createBuildableType(input.type.args[0]);\n                } else if (input?.type) {\n                    buildableType = this.createBuildableType(input.type);\n                }\n                if (!vars.has(name)) {\n                    vars.set(name, { operands: [], types: [] });\n                }\n                const entry = vars.get(name);\n                if (isVariadicOfVariadicOp) {\n                    // Parse grouped operands: (op, op), (), (op)\n                    do {\n                        if (!parser.parseOptionalLParen()) {\n                            break;\n                        }\n                        let operand = parser.parseOptionalOperand();\n                        while (operand) {\n                            entry.operands.push(operand);\n                            if (!parser.parseOptionalComma()) {\n                                break;\n                            }\n                            operand = parser.parseOptionalOperand();\n                        }\n                        parser.parseRParen();\n                    } while (parser.parseOptionalComma());\n                } else if (isVariadicOp) {\n                    for (;;) {\n                        const operand = parser.parseOptionalOperand();\n                        if (operand) {\n                            entry.operands.push(operand);\n                            if (buildableType) {\n                                entry.types.push(buildableType);\n                            }\n                            if (!parser.parseOptionalComma()) {\n                                break;\n                            }\n                        } else if (buildableType) {\n                            // Handle integer literals for buildable integer types (e.g., I32)\n                            let value = '';\n                            if (parser.parseOptionalMinus()) {\n                                value = '-';\n                            }\n                            const intVal = parser.parseOptionalInteger();\n                            if (intVal === null) {\n                                break;\n                            }\n                            value += intVal;\n                            entry.operands.push({ name: value, literal: true });\n                            if (buildableType) {\n                                entry.types.push(buildableType);\n                            }\n                            if (!parser.parseOptionalComma()) {\n                                break;\n                            }\n                        } else {\n                            break;\n                        }\n                    }\n                } else {\n                    const operand = parser.parseOptionalOperand();\n                    if (operand) {\n                        entry.operands.push(operand);\n                        if (buildableType) {\n                            entry.types.push(buildableType);\n                        }\n                    } else if (buildableType) {\n                        // Handle integer literals for buildable integer types (e.g., I32)\n                        let value = '';\n                        if (parser.parseOptionalMinus()) {\n                            value = '-';\n                        }\n                        const intVal = parser.parseOptionalInteger();\n                        if (intVal !== null) { // eslint-disable-line no-negated-condition\n                            value += intVal;\n                            entry.operands.push({ name: value, literal: true });\n                            entry.types.push(buildableType);\n                        } else {\n                            // Check if this is a region, not an operand\n                            const isActualOperand = opInfo.metadata?.operands?.some((inp) => inp.name === name);\n                            if (isActualOperand) {\n                                // Try parsing as symbol name (@identifier)\n                                const symbolName = parser.parseOptionalSymbolName();\n                                if (symbolName) {\n                                    op.addAttribute(name, symbolName.value || symbolName);\n                                } else if (!isOptionalOp) {\n                                    // Try keyword (enum value)\n                                    const inputType = input?.type;\n                                    if (inputType && Array.isArray(inputType.values)) {\n                                        const keyword = parser.parseKeyword();\n                                        op.addAttribute(name, keyword);\n                                    } else {\n                                        // Try integer\n                                        const integerVal = parser.parseOptionalInteger();\n                                        if (integerVal !== null) { // eslint-disable-line no-negated-condition\n                                            op.addAttribute(name, String(integerVal));\n                                        } else {\n                                            // Fallback: try parseAttribute\n                                            const attr = parser.parseOptionalAttribute();\n                                            if (attr) {\n                                                op.addAttribute(name, attr);\n                                            }\n                                        }\n                                    }\n                                }\n                            } else {\n                                const regionMeta = opInfo.metadata?.regions?.find((r) => r.name === name);\n                                const isVariadicRegion = regionMeta?.type?.name === 'VariadicRegion';\n                                const isIsolated = op.name.hasTrait('IsolatedFromAbove');\n                                if (isVariadicRegion) {\n                                    if (parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                                        while (parser.parseOptionalComma()) {\n                                            if (!parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                                                break;\n                                            }\n                                        }\n                                    }\n                                } else {\n                                    parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated);\n                                }\n                            }\n                        }\n                    } else {\n                        // Check if this is a region, not an operand\n                        const isActualOperand = opInfo.metadata?.operands?.some((inp) => inp.name === name);\n                        if (isActualOperand) {\n                            // Try parsing as symbol name (@identifier)\n                            const symbolName = parser.parseOptionalSymbolName();\n                            if (symbolName) {\n                                op.addAttribute(name, symbolName.value || symbolName);\n                            } else if (!isOptionalOp) {\n                                // Try keyword (enum value)\n                                const inputType = input?.type;\n                                if (inputType && Array.isArray(inputType.values)) {\n                                    const keyword = parser.parseKeyword();\n                                    op.addAttribute(name, keyword);\n                                } else {\n                                    // Try integer\n                                    const integerVal = parser.parseOptionalInteger();\n                                    if (integerVal !== null) { // eslint-disable-line no-negated-condition\n                                        op.addAttribute(name, String(integerVal));\n                                    } else {\n                                        // Fallback: try parseAttribute\n                                        const attr = parser.parseOptionalAttribute();\n                                        if (attr) {\n                                            op.addAttribute(name, attr);\n                                        }\n                                    }\n                                }\n                            }\n                        } else {\n                            const regionMeta = opInfo.metadata?.regions?.find((r) => r.name === name);\n                            const isVariadicRegion = regionMeta?.type?.name === 'VariadicRegion';\n                            const isIsolated = op.name.hasTrait('IsolatedFromAbove');\n                            if (isVariadicRegion) {\n                                if (parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                                    while (parser.parseOptionalComma()) {\n                                        if (!parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                                            break;\n                                        }\n                                    }\n                                }\n                            } else {\n                                parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated);\n                            }\n                        }\n                    }\n                }\n                break;\n            }\n            case 'operands': {\n                if (!vars.has('operands')) {\n                    vars.set('operands', { operands: [], types: [] });\n                }\n                const operandsList = parser.parseOperandList();\n                vars.get('operands').operands.push(...operandsList);\n                break;\n            }\n            case 'results': {\n                const args = parser.parseArgumentList('none', true);\n                const types = args.map((a) => a.type).filter((t) => t);\n                op.addTypes(types);\n                break;\n            }\n            case 'type':\n            case 'qualified': {\n                if (!directive.args || directive.args.length === 0) {\n                    // Bare type directive - parse types for operands\n                    const types = parser.parseTypeList();\n                    if (vars.has('operands')) {\n                        vars.get('operands').types.push(...types);\n                    }\n                    break;\n                }\n                const arg = directive.args[0] === 'type' && directive.args.length > 1 ? directive.args[1] : directive.args[0];\n                // Handle qualified($attr) - attribute reference\n                if (directive.type === 'qualified' && arg.startsWith('$') && !arg.startsWith('$results') && !arg.startsWith('$operands')) {\n                    if (!arg.startsWith('type($')) {\n                        const attrName = arg.substring(1);\n                        const attr = parser.parseAttribute();\n                        if (attr) {\n                            // Store full attribute object to preserve .type for FirstAttrDerivedResultType\n                            op.addAttribute(attrName, attr);\n                        }\n                        break;\n                    }\n                }\n                // Extract name from $name or type($name) or type(operands) or type(results)\n                let name = null;\n                if (arg.startsWith('type($') && arg.endsWith(')')) {\n                    name = arg.substring(6, arg.length - 1);\n                } else if (arg.startsWith('type(') && arg.endsWith(')')) {\n                    // Handle type(operands) or type(results)\n                    name = arg.substring(5, arg.length - 1);\n                } else if (arg.startsWith('$')) {\n                    name = arg.substring(1);\n                } else if (arg === 'results' || arg === 'operands') {\n                    name = arg;\n                }\n                if (!name) {\n                    break;\n                }\n                // Check if it's a result or operand\n                const resultMeta = opInfo.metadata?.results?.find((r) => r.name === name);\n                const operandMeta = opInfo.metadata?.operands?.find((o) => o.name === name);\n                const isResult = Boolean(resultMeta) && !operandMeta;\n                let isVariadicType = false;\n                if (resultMeta) {\n                    isVariadicType = isVariadic(resultMeta.type);\n                } else if (operandMeta) {\n                    isVariadicType = isVariadic(operandMeta.type);\n                }\n                const isVariadicOfVariadicType = operandMeta ? isVariadicOfVariadic(operandMeta.type) : false;\n                let isOptionalType = false;\n                if (operandMeta) {\n                    isOptionalType = isOptional(operandMeta.type);\n                } else if (resultMeta) {\n                    isOptionalType = isOptional(resultMeta.type);\n                }\n                if (!vars.has(name)) {\n                    vars.set(name, { operands: [], types: [] });\n                }\n                const entry = vars.get(name);\n                if (isResult || name === 'results') {\n                    // Result type - add to op.types and track in entry.types\n                    if (isVariadicType || name === 'results') {\n                        const types = parser.parseTypeList();\n                        entry.types.push(...types);\n                        op.addTypes(types);\n                    } else if (isOptionalType && op.types.length === 0) {\n                        const type = parser.parseOptionalType();\n                        if (type) {\n                            entry.types.push(type);\n                            op.addTypes([type]);\n                        }\n                    } else {\n                        const type = this.parseCustomTypeWithFallback(parser, resultMeta?.type);\n                        entry.types.push(type);\n                        op.addTypes([type]);\n                    }\n                } else if (isVariadicOfVariadicType) {\n                    // Parse grouped types: (type, type), (), (type)\n                    do {\n                        if (!parser.parseOptionalLParen()) {\n                            break;\n                        }\n                        if (!parser.parseOptionalRParen()) {\n                            entry.types.push(...parser.parseTypeList());\n                            parser.parseRParen();\n                        }\n                    } while (parser.parseOptionalComma());\n                } else if (isVariadicType || name === 'operands') {\n                    // Variadic operand - parse type list\n                    entry.types.push(...parser.parseTypeList());\n                } else if (entry.operands.length > 0) {\n                    // Single operand - parse one type per operand\n                    // Clear any previously inferred (buildable) types since explicit type is parsed\n                    const type = this.parseCustomTypeWithFallback(parser, operandMeta?.type);\n                    entry.types = [];\n                    for (let j = 0; j < entry.operands.length; j++) {\n                        entry.types.push(type);\n                    }\n                } else if (isOptionalType) {\n                    // Optional operand - parse type if present\n                    const type = parser.parseOptionalType();\n                    if (type) {\n                        entry.types.push(type);\n                    }\n                } else {\n                    // No operands collected yet, just parse and store type\n                    // Use custom type parser if available for the operand/result constraint\n                    const typeConstraint = operandMeta?.type || resultMeta?.type;\n                    const type = this.parseCustomTypeWithFallback(parser, typeConstraint);\n                    entry.types.push(type);\n                }\n                break;\n            }\n            case 'attr_dict_with_keyword':\n                parser.parseOptionalAttrDictWithKeyword(op.attributes);\n                break;\n            case 'attr_dict':\n                parser.parseOptionalAttrDict(op.attributes);\n                break;\n            case 'prop_dict':\n                if (parser.parseOptionalLess()) {\n                    op.propertiesAttr = parser.parseAttribute();\n                    parser.parseGreater();\n                }\n                break;\n            case 'regions': {\n                const isIsolated = op.name.hasTrait('IsolatedFromAbove');\n                while (parser.parseOptionalRegion(op.addRegion(), undefined, isIsolated)) {\n                    if (!parser.parseOptionalComma()) {\n                        break;\n                    }\n                }\n                break;\n            }\n            case 'successors': {\n                op.successors = op.successors || [];\n                let succ = parser.parseOptionalSuccessor();\n                if (succ) {\n                    op.successors.push(succ);\n                    while (parser.parseOptionalComma()) {\n                        succ = parser.parseOptionalSuccessor();\n                        if (succ) {\n                            op.successors.push(succ);\n                        } else {\n                            break;\n                        }\n                    }\n                }\n                break;\n            }\n            case 'functional_type': {\n                const type = parser.parseType();\n                if (!(type instanceof _.FunctionType)) {\n                    throw new mlir.Error('Invalid functional-type function type.');\n                }\n                // Distribute input types to operands in metadata order\n                let typeIndex = 0;\n                for (const operandMeta of opInfo.metadata?.operands || []) {\n                    if (vars.has(operandMeta.name)) {\n                        const entry = vars.get(operandMeta.name);\n                        for (let j = 0; j < entry.operands.length && typeIndex < type.inputs.length; j++) {\n                            entry.types.push(type.inputs[typeIndex]);\n                            typeIndex++;\n                        }\n                    }\n                }\n                op.addTypes(type.results);\n                // Track result types - second arg is typically the result (e.g., $outputs or results)\n                if (directive.args && directive.args.length > 1) {\n                    const resultArg = directive.args[1];\n                    if (resultArg) {\n                        // Handle both $name and name (without $)\n                        const resultName = resultArg.startsWith('$') ? resultArg.substring(1) : resultArg;\n                        if (resultName === 'results') {\n                            // 'results' is a keyword meaning all results - create vars entry\n                            if (!vars.has('results')) {\n                                vars.set('results', { types: [] });\n                            }\n                            vars.get('results').types.push(...type.results);\n                        } else if (vars.has(resultName)) {\n                            vars.get(resultName).types.push(...type.results);\n                        }\n                    }\n                }\n                break;\n            }\n            case 'custom': {\n                const fn = this._customDirectives.get(directive.parser);\n                if (!fn) {\n                    throw new mlir.Error(`Custom directive parser '${directive.parser}' not implemented.`);\n                }\n                // Parse args and pass resolved arrays\n                // Always pass parser and op first, then resolved args\n                const callArgs = [parser, op];\n                for (const arg of directive.args || []) {\n                    if (arg.startsWith('ref(type($') && arg.endsWith('))')) {\n                        // ref(type($name)) - reference to the type of an operand\n                        // 'ref(type($' is 10 characters, so slice from index 10 to skip -2 for '))'\n                        const name = arg.slice(10, -2);\n                        if (!vars.has(name)) {\n                            vars.set(name, { operands: [], types: [] });\n                        }\n                        callArgs.push(vars.get(name).types);\n                    } else if (arg.startsWith('ref($') && arg.endsWith(')')) {\n                        const name = arg.slice(5, -1);\n                        // Check if this is an attribute reference\n                        const isAttribute = opInfo.metadata?.attributes?.some((a) => a.name === name);\n                        if (isAttribute) {\n                            // Get attribute value from op.attributes\n                            const attrValue = op.attributes.get(name);\n                            callArgs.push(attrValue);\n                        } else {\n                            // Operand reference - get from ctx\n                            if (!vars.has(name)) {\n                                vars.set(name, { operands: [], types: [] });\n                            }\n                            callArgs.push(vars.get(name).operands);\n                        }\n                    } else if (arg.startsWith('type($') && arg.endsWith(')')) {\n                        const name = arg.slice(6, -1);\n                        // Always use vars entry for the specific name (result or operand)\n                        // This ensures Optional results like asyncToken are tracked separately\n                        if (!vars.has(name)) {\n                            vars.set(name, { operands: [], types: [] });\n                        }\n                        callArgs.push(vars.get(name).types);\n                    } else if (arg.startsWith('$')) {\n                        const name = arg.slice(1);\n                        // Could be operand ref or attribute name\n                        const isOperand = opInfo.metadata?.operands?.some((o) => o.name === name);\n                        if (isOperand) {\n                            if (!vars.has(name)) {\n                                vars.set(name, { operands: [], types: [] });\n                            }\n                            callArgs.push(vars.get(name).operands);\n                        } else {\n                            // Pass attribute name for custom directive to handle\n                            callArgs.push(name);\n                        }\n                    } else {\n                        // Warn if a $-prefixed arg wasn't resolved - indicates missing metadata\n                        if (typeof arg === 'string' && arg.startsWith('$')) {\n                            throw new mlir.Error(`Custom directive '${directive.parser}' received unresolved arg '${arg}' for op '${opInfo.metadata.name}'. Check metadata for missing operand/attribute definition.`);\n                        }\n                        callArgs.push(arg);\n                    }\n                }\n                fn(...callArgs);\n                break;\n            }\n            case 'oilist': {\n                const clauses = directive.content.split('|').map((c) => c.trim());\n                const parsedClauses = [];\n                for (const clauseStr of clauses) {\n                    const clauseParser = new _.AssemblyFormatParser({ ...opInfo.metadata, assemblyFormat: clauseStr });\n                    const elements = clauseParser.parse();\n                    parsedClauses.push({ elements, parsed: false, clauseStr });\n                }\n                // Helper to check if a clause's variables are used by later custom directives\n                const isHandledByCustomDirective = (clauseStr) => {\n                    const varMatches = clauseStr.matchAll(/\\$(\\w+)/g);\n                    const clauseVars = [...varMatches].map((m) => m[1]);\n                    if (clauseVars.length === 0) {\n                        return false;\n                    }\n                    for (let j = i + 1; j < directives.length; j++) {\n                        const laterDir = directives[j];\n                        if (laterDir.type === 'custom' && laterDir.args && Array.isArray(laterDir.args)) {\n                            const customVarNames = [];\n                            for (const arg of laterDir.args) {\n                                const argVarMatches = arg.matchAll(/\\$(\\w+)/g);\n                                for (const match of argVarMatches) {\n                                    customVarNames.push(match[1]);\n                                }\n                            }\n                            if (clauseVars.some((v) => customVarNames.includes(v))) {\n                                return true;\n                            }\n                        }\n                    }\n                    return false;\n                };\n                let progress = true;\n                while (progress) {\n                    progress = false;\n                    for (const clause of parsedClauses) {\n                        if (clause.parsed) {\n                            continue;\n                        }\n                        if (clause.elements.length === 0) {\n                            continue;\n                        }\n                        if (isHandledByCustomDirective(clause.clauseStr)) {\n                            clause.parsed = true;\n                            continue;\n                        }\n                        const firstElem = clause.elements.find((elem) => elem.type !== 'whitespace');\n                        let matches = false;\n                        if (firstElem && firstElem.type === 'literal') {\n                            switch (firstElem.value) {\n                                case '(': matches = parser.parseOptionalLParen(); break;\n                                case ')': matches = parser.parseOptionalRParen(); break;\n                                case '[': matches = parser.parseOptionalLSquare(); break;\n                                case ']': matches = parser.parseOptionalRSquare(); break;\n                                case '{': matches = parser.parseOptionalLBrace(); break;\n                                case '}': matches = parser.parseOptionalRBrace(); break;\n                                case ':': matches = parser.parseOptionalColon(); break;\n                                case '=': matches = parser.parseOptionalEqual(); break;\n                                case ',': matches = parser.parseOptionalComma(); break;\n                                case '<': matches = parser.parseOptionalLess(); break;\n                                case '>': matches = parser.parseOptionalGreater(); break;\n                                case '->': matches = parser.parseOptionalArrow(); break;\n                                case '...': matches = parser.parseOptionalEllipsis(); break;\n                                default: matches = parser.parseOptionalKeyword(firstElem.value); break;\n                            }\n                        }\n                        if (matches) {\n                            const firstElemIdx = clause.elements.indexOf(firstElem) + 1;\n                            for (let elemIdx = firstElemIdx; elemIdx < clause.elements.length; elemIdx++) {\n                                this.parseDirective(clause.elements[elemIdx], parser, op, opInfo, directives, i, vars);\n                            }\n                            clause.parsed = true;\n                            progress = true;\n                        }\n                    }\n                }\n                break;\n            }\n            case 'optional_group': {\n                let shouldParse = false;\n                const firstElem = directive.elements.find((elem) => elem.type !== 'whitespace');\n                if (firstElem) {\n                    if (firstElem.type === 'literal') {\n                        switch (firstElem.value) {\n                            case '(': shouldParse = parser.parseOptionalLParen(); break;\n                            case ')': shouldParse = parser.parseOptionalRParen(); break;\n                            case '[': shouldParse = parser.parseOptionalLSquare(); break;\n                            case ']': shouldParse = parser.parseOptionalRSquare(); break;\n                            case '{': shouldParse = parser.parseOptionalLBrace(); break;\n                            case '}': shouldParse = parser.parseOptionalRBrace(); break;\n                            case ':': shouldParse = parser.parseOptionalColon(); break;\n                            case '=': shouldParse = parser.parseOptionalEqual(); break;\n                            case ',': shouldParse = parser.parseOptionalComma(); break;\n                            case '<': shouldParse = parser.parseOptionalLess(); break;\n                            case '>': shouldParse = parser.parseOptionalGreater(); break;\n                            case '?': shouldParse = parser.parseOptionalQuestion(); break;\n                            case '->': shouldParse = parser.parseOptionalArrow(); break;\n                            case '...': shouldParse = parser.parseOptionalEllipsis(); break;\n                            default: shouldParse = parser.parseOptionalKeyword(firstElem.value); break;\n                        }\n                        if (shouldParse) {\n                            shouldParse = 'skip_first';\n                        }\n                    } else if (firstElem.type === 'attribute_ref') {\n                        const attrInfo = opInfo.metadata && opInfo.metadata.attributes && opInfo.metadata.attributes.find((attr) => attr.name === firstElem.name);\n                        const attrType = attrInfo ? attrInfo.type : null;\n                        // Check if attribute type is an array (TypedArrayAttrBase, ArrayAttr, etc.)\n                        // Handle both string types (\"OptionalAttr<StrAttr>\") and object types ({name: \"OptionalAttr\", args: [...]})\n                        let elementType = attrType;\n                        const getTypeName = (t) => typeof t === 'string' ? t : t?.name;\n                        const typeContains = (t, pattern) => {\n                            const name = typeof t === 'string' ? t : t?.name;\n                            return name && name.includes(pattern);\n                        };\n                        // Unwrap wrapper types\n                        if (typeContains(elementType, 'OptionalAttr')) {\n                            elementType = typeof elementType === 'string' ? elementType.replace(/OptionalAttr<(.+)>/, '$1') : elementType.args?.[0];\n                        }\n                        if (typeContains(elementType, 'DefaultValuedAttr') || typeContains(elementType, 'DefaultValuedStrAttr')) {\n                            elementType = typeof elementType === 'string' ? elementType.replace(/DefaultValuedAttr<(.+?)(?:,.*?)?>/, '$1') : elementType.args?.[0];\n                        }\n                        if (typeContains(elementType, 'ConfinedAttr')) {\n                            elementType = typeof elementType === 'string' ? elementType.replace(/ConfinedAttr<(.+?)(?:,.*?)?>/, '$1') : elementType.args?.[0];\n                        }\n                        const mnemonic = getTypeName(elementType);\n                        let shouldTryParse = false;\n                        if (typeContains(elementType, 'TypedArrayAttrBase') || typeContains(elementType, 'ArrayAttr')) {\n                            shouldTryParse = peek(_.Token.l_square);\n                        } else if (mnemonic && /^[SU]?I\\d+Attr$|^IntegerAttr$|^IndexAttr$/.test(mnemonic)) {\n                            shouldTryParse = peek(_.Token.integer, _.Token.minus);\n                        } else if (typeContains(elementType, 'ElementsAttr')) {\n                            shouldTryParse = peek(_.Token.kw_dense, _.Token.kw_sparse, _.Token.kw_array, _.Token.kw_dense_resource);\n                        } else if (mnemonic === 'StrAttr' || mnemonic === 'StringAttr') {\n                            shouldTryParse = peek(_.Token.string);\n                        } else {\n                            shouldTryParse = peek(_.Token.bare_identifier, 'keyword', _.Token.hash_identifier, _.Token.at_identifier, _.Token.string, _.Token.l_square, _.Token.integer);\n                        }\n                        if (shouldTryParse) {\n                            let result = null;\n                            if (attrType && attrType !== 'Attribute') {\n                                result = this.parseCustomAttributeWithFallback(parser, attrType);\n                            } else {\n                                result = parser.parseOptionalAttribute(attrType || 'Attribute');\n                            }\n                            if (result !== null) {\n                                op.addAttribute(firstElem.name, result);\n                                shouldParse = true;\n                            }\n                        }\n                    } else if (firstElem.type === 'successor_ref') {\n                        shouldParse = peek(_.Token.caret_identifier);\n                    } else if (firstElem.type === 'region_ref') {\n                        shouldParse = peek(_.Token.l_brace);\n                    } else if (firstElem.type === 'operand_ref') {\n                        let isKeywordInput = false;\n                        if (opInfo.metadata && opInfo.metadata.operands) {\n                            const inputInfo = opInfo.metadata.operands.find((inp) => inp.name === firstElem.name);\n                            if (inputInfo) {\n                                const inputType = inputInfo.type;\n                                if (typeof inputType === 'string' &&\n                                    (inputType.includes('Prop') || inputType.endsWith('Predicate') ||\n                                        inputType.includes('Flags') || inputType.includes('Enum'))) {\n                                    isKeywordInput = true;\n                                }\n                            }\n                        }\n                        if (isKeywordInput) {\n                            shouldParse = peek(_.Token.bare_identifier);\n                        } else {\n                            shouldParse = peek(_.Token.percent_identifier);\n                        }\n                    } else if (firstElem.type === 'operands') {\n                        shouldParse = peek(_.Token.l_paren, _.Token.percent_identifier);\n                    } else if (firstElem.type === 'custom') {\n                        const fn = this._customDirectives.get(firstElem.parser);\n                        if (fn) {\n                            const resolvedArgs = (firstElem.args || []).map((arg) => typeof arg === 'string' && arg.startsWith('$') ? arg.slice(1) : arg);\n                            const result = fn(parser, op, ...resolvedArgs);\n                            if (result === null) {\n                                shouldParse = false;\n                            } else {\n                                shouldParse = 'skip_first';\n                            }\n                        }\n                    } else if (firstElem.type === 'qualified') {\n                        if (firstElem.args && firstElem.args.length > 0) {\n                            const [arg] = firstElem.args;\n                            if (arg.startsWith('$')) {\n                                shouldParse = peek(_.Token.hash_identifier);\n                            } else if (arg.startsWith('type($')) {\n                                shouldParse = peek(_.Token.exclamation_identifier, _.Token.bare_identifier);\n                            }\n                        }\n                    }\n                }\n                if (shouldParse) {\n                    // Recursively parse nested elements using the same parseDirective method\n                    // If shouldParse === 'skip_first', the anchor element was already consumed\n                    const firstElemIdx = shouldParse === 'skip_first' ? directive.elements.indexOf(firstElem) + 1 : 0;\n                    for (let elemIdx = firstElemIdx; elemIdx < directive.elements.length; elemIdx++) {\n                        this.parseDirective(directive.elements[elemIdx], parser, op, opInfo, directive.elements, elemIdx, vars);\n                    }\n                }\n                break;\n            }\n            case 'conditional_alternative': {\n                const tryParseLiteral = (value) => {\n                    switch (value) {\n                        case '(': return parser.parseOptionalLParen();\n                        case ')': return parser.parseOptionalRParen();\n                        case '[': return parser.parseOptionalLSquare();\n                        case ']': return parser.parseOptionalRSquare();\n                        case '{': return parser.parseOptionalLBrace();\n                        case '}': return parser.parseOptionalRBrace();\n                        case ':': return parser.parseOptionalColon();\n                        case '=': return parser.parseOptionalEqual();\n                        case ',': return parser.parseOptionalComma();\n                        case '<': return parser.parseOptionalLess();\n                        case '>': return parser.parseOptionalGreater();\n                        case '?': return parser.parseOptionalQuestion();\n                        case '->': return parser.parseOptionalArrow();\n                        case '...': return parser.parseOptionalEllipsis();\n                        default: return parser.parseOptionalKeyword(value);\n                    }\n                };\n                const checkMatch = (elem) => {\n                    if (elem.type === 'literal') {\n                        return tryParseLiteral(elem.value);\n                    }\n                    if (elem.type === 'operand_ref') {\n                        return peek(_.Token.percent_identifier);\n                    }\n                    if (elem.type === 'attribute_ref') {\n                        return peek(_.Token.bare_identifier, _.Token.integer, _.Token.floatliteral, _.Token.l_square, _.Token.at_identifier, _.Token.hash_identifier);\n                    }\n                    if (elem.type === 'region_ref') {\n                        return peek(_.Token.l_brace);\n                    }\n                    if (elem.type === 'successor_ref') {\n                        return peek(_.Token.caret_identifier);\n                    }\n                    if (elem.type === 'custom') {\n                        return peek(_.Token.bare_identifier, _.Token.integer, _.Token.minus, _.Token.percent_identifier, _.Token.l_square, _.Token.l_paren, _.Token.question);\n                    }\n                    return false;\n                };\n                const firstElem = directive.firstAlt.find((e) => e.type !== 'whitespace');\n                let matchedFirst = firstElem && checkMatch(firstElem);\n                let customDirectiveHandledFirst = false;\n                // For custom directives, try calling them and check if they return null\n                if (matchedFirst && firstElem.type === 'custom') {\n                    const fn = this._customDirectives.get(firstElem.parser);\n                    if (fn) {\n                        const resolvedArgs = (firstElem.args || []).map((arg) => {\n                            if (typeof arg === 'string' && arg.startsWith('$')) {\n                                return arg.slice(1); // Strip $ prefix to get attribute name\n                            }\n                            return arg;\n                        });\n                        const result = fn(parser, op, ...resolvedArgs);\n                        if (result === null) {\n                            matchedFirst = false;\n                        } else {\n                            customDirectiveHandledFirst = true;\n                        }\n                    }\n                }\n                const literalHandledFirst = matchedFirst && firstElem.type === 'literal';\n                if (matchedFirst) {\n                    const skipFirst = customDirectiveHandledFirst || literalHandledFirst;\n                    const startIdx = skipFirst ? directive.firstAlt.indexOf(firstElem) + 1 : 0;\n                    for (let elemIdx = startIdx; elemIdx < directive.firstAlt.length; elemIdx++) {\n                        this.parseDirective(directive.firstAlt[elemIdx], parser, op, opInfo, directive.firstAlt, elemIdx, vars);\n                    }\n                } else if (directive.secondOptional) {\n                    const secondElem = directive.secondAlt.find((e) => e.type !== 'whitespace');\n                    const matchedSecond = secondElem && checkMatch(secondElem);\n                    if (matchedSecond) {\n                        const startIdx = secondElem.type === 'literal' ? directive.secondAlt.indexOf(secondElem) + 1 : 0;\n                        for (let elemIdx = startIdx; elemIdx < directive.secondAlt.length; elemIdx++) {\n                            this.parseDirective(directive.secondAlt[elemIdx], parser, op, opInfo, directive.secondAlt, elemIdx, vars);\n                        }\n                    }\n                } else if (directive.secondAlt && directive.secondAlt.length > 0) {\n                    for (const elem of directive.secondAlt) {\n                        this.parseDirective(elem, parser, op, opInfo, directive.secondAlt, 0, vars);\n                    }\n                }\n                break;\n            }\n            default: {\n                throw new mlir.Error(`Unsupported directive type '${directive.type}' ${parser.getCurrentLocation()}.`);\n            }\n        }\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (!opInfo) {\n            return false;\n        }\n        if ((opInfo.metadata.hasParser || opInfo.metadata.hasCustomAssemblyFormat) && !opInfo.metadata.assemblyFormat) {\n            throw new mlir.Error(`Operation parser '${result.op}' not implemented.`);\n        }\n        // Mark as using assembly format parsing (bypasses validation check)\n        if (result.compatibility === undefined && opInfo.metadata.assemblyFormat) {\n            result.compatibility = true;\n        }\n        const vars = new Map();\n        for (const input of opInfo.metadata?.operands || []) {\n            vars.set(input.name, { operands: [], types: [] });\n        }\n        for (const resultInfo of opInfo.metadata?.results || []) {\n            vars.set(resultInfo.name, { types: [] });\n        }\n        const directives = opInfo.directives || [];\n        for (let i = 0; i < directives.length; i++) {\n            this.parseDirective(directives[i], parser, result, opInfo, directives, i, vars);\n        }\n        for (const [, v] of vars) {\n            if (v.operands?.length > 0 && v.types?.length > 0) {\n                parser.resolveOperands(v.operands, v.types, result.operands);\n            } else if (v.operands?.length > 0 && result.types.length > 0) {\n                // SameOperandsAndResultType: use result type for operands\n                const types = v.operands.map(() => result.types[0]);\n                parser.resolveOperands(v.operands, types, result.operands);\n            } else if (v.operands?.length > 0) {\n                // No explicit type - resolve from scope (type from definition)\n                for (const operand of v.operands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n        }\n        // AttrSizedOperandSegments trait\n        if (vars && opInfo.metadata?.operands && result.name.hasTrait('AttrSizedOperandSegments')) {\n            const segmentSizes = [];\n            for (const operandMeta of opInfo.metadata.operands) {\n                const entry = vars.get(operandMeta.name);\n                segmentSizes.push(entry?.operands?.length || 0);\n            }\n            result.addAttribute('operandSegmentSizes', new _.DenseI32ArrayAttr(segmentSizes));\n        }\n        this.inferResultTypes(result, vars);\n        return true;\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseAttribute(/* parser, type */) {\n        return null;\n    }\n\n    parseCustomTypeWithFallback(parser, type) {\n        const optionalType = parser.parseOptionalType();\n        if (optionalType) {\n            return optionalType;\n        }\n        if (type && this._customTypes.has(type.name)) {\n            let typeT = this._customTypes.get(type.name);\n            if (typeof typeT !== 'function') {\n                typeT = { type, name: typeT };\n            }\n            return parser.parseCustomTypeWithFallback(typeT);\n        }\n        throw new mlir.Error(`Unsupported type constraint '${type}'.`);\n    }\n\n    parseCustomAttributeWithFallback(parser, type) {\n        if (type && this._customAttributes.has(type.name)) {\n            const attrT = this._customAttributes.get(type.name);\n            return parser.parseCustomAttributeWithFallback(attrT, type);\n        }\n        if (type && Array.isArray(type.values)) {\n            const value = parser.parseOptionalKeyword(type.values);\n            if (value !== null) {\n                return new _.TypedAttr(value, null);\n            }\n        }\n        return parser.parseOptionalAttribute(null);\n    }\n\n    parseOptionalAttr(parser, type) {\n        if (!Array.isArray(type.args) || type.args.length === 0) {\n            throw new mlir.Error(`Invalid 'OptionalAttr' type.`);\n        }\n        const [elementType] = type.args;\n        return this.parseCustomAttributeWithFallback(parser, elementType);\n    }\n\n    parseDefaultValuedAttr(parser, type) {\n        if (!Array.isArray(type.args) || type.args.length === 0) {\n            throw new mlir.Error(`Invalid 'DefaultValuedAttr' type.`);\n        }\n        const [elementType] = type.args;\n        return this.parseCustomAttributeWithFallback(parser, elementType);\n    }\n\n    parseDefaultValuedOptionalAttr(parser, type) {\n        if (!Array.isArray(type.args) || type.args.length === 0) {\n            throw new mlir.Error(`Invalid 'DefaultValuedOptionalAttr' type.`);\n        }\n        const [elementType] = type.args;\n        return this.parseCustomAttributeWithFallback(parser, elementType);\n    }\n\n    parseTypeAttrOf(parser, type) {\n        if (!Array.isArray(type.args) || type.args.length === 0) {\n            throw new mlir.Error(`Invalid 'TypeAttrOf' type.`);\n        }\n        const parsedType = parser.parseOptionalType();\n        if (parsedType) {\n            return { value: parsedType, type: 'type' };\n        }\n        return null;\n    }\n\n    parseAnyAttrOf(parser) {\n        // This allows parseAttribute to handle the full syntax including `: type` suffix\n        return parser.parseOptionalAttribute(null);\n    }\n\n    parseArrayAttr(parser) {\n        // Try parsing array attribute (starts with '[') or attribute alias reference (starts with '#')\n        const attr = parser.parseOptionalAttribute();\n        if (attr) {\n            return attr;\n        }\n        return null;\n    }\n\n    parseConfinedAttr(parser, type) {\n        if (!Array.isArray(type.args) || type.args.length === 0) {\n            throw new mlir.Error(`Invalid ConfinedAttr type.`);\n        }\n        const [baseType] = type.args;\n        return this.parseCustomAttributeWithFallback(parser, baseType);\n    }\n\n    parseTypedAttrInterface(parser) {\n        return parser.parseAttribute();\n    }\n\n    parseUnitAttr(parser) {\n        parser.parseOptionalKeyword('unit');\n        return new _.UnitAttr();\n    }\n\n    parseSymbolNameAttr(parser) {\n        const value = parser.parseOptionalSymbolName();\n        if (value) {\n            return new _.StringAttr(value);\n        }\n        return null;\n    }\n\n    parseSymbolRefAttr(parser) {\n        return parser.parseAttribute();\n    }\n\n    parseFlatSymbolRefAttr(parser) {\n        return this.parseSymbolRefAttr(parser);\n    }\n\n    // custom<DynamicIndexList>($dynamic_operands, $static_attr, $scalable_attr?, \"Delimiter::Paren\"?)\n    parseDynamicIndexList(parser, op, operandsAttr, staticAttrName, scalableAttrName, delimiterSpec) {\n        // Determine delimiter from delimiterSpec\n        let openDelim = '[';\n        if (typeof delimiterSpec === 'string' && delimiterSpec.includes('Paren')) {\n            openDelim = '(';\n        }\n        const unresolvedOperands = [];\n        const staticValues = [];\n        const scalableFlags = [];\n        const opened = openDelim === '(' ? parser.parseOptionalLParen() : parser.parseOptionalLSquare();\n        if (opened) {\n            const closed = () => openDelim === '(' ? parser.parseOptionalRParen() : parser.parseOptionalRSquare();\n            if (!closed()) {\n                do {\n                    const isScalable = parser.parseOptionalLSquare();\n                    const operand = parser.parseOptionalOperand();\n                    if (operand) {\n                        unresolvedOperands.push(operand);\n                        staticValues.push(_.ShapedType.kDynamic);\n                        if (parser.parseOptionalColon()) {\n                            parser.parseType();\n                        }\n                    } else {\n                        const intVal = parser.parseOptionalInteger();\n                        if (intVal === null) {\n                            break;\n                        }\n                        staticValues.push(intVal);\n                    }\n                    scalableFlags.push(isScalable);\n                    if (isScalable) {\n                        if (!parser.parseOptionalRSquare()) {\n                            throw new mlir.Error(`Expected ']' for scalable index ${parser.getCurrentLocation()}`);\n                        }\n                    }\n                } while (parser.parseOptionalComma());\n                if (openDelim === '(') {\n                    parser.parseRParen();\n                } else {\n                    parser.parseRSquare();\n                }\n            }\n        }\n        const indexType = new _.IndexType();\n        parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), op.operands);\n        if (staticAttrName && staticValues.length > 0) {\n            op.addAttribute(staticAttrName, staticValues);\n        }\n        if (scalableFlags.length > 0 && scalableFlags.some((f) => f)) {\n            if (!scalableAttrName) {\n                throw new mlir.Error(`Scalable indices found but no scalable attribute name provided ${parser.getCurrentLocation()}`);\n            }\n            op.addAttribute(scalableAttrName, scalableFlags);\n        }\n    }\n\n    parseNestedDynamicIndexList(parser, op, operandsArr, staticAttrName) {\n        const unresolvedOperands = [];\n        const innerArrayAttrs = [];\n        parser.parseLSquare();\n        do {\n            const staticVals = [];\n            parser.parseLSquare();\n            do {\n                const operand = parser.parseOptionalOperand();\n                if (operand) {\n                    unresolvedOperands.push(operand);\n                    staticVals.push(_.ShapedType.kDynamic);\n                } else {\n                    staticVals.push(parser.parseInteger());\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n            innerArrayAttrs.push(staticVals);\n        } while (parser.parseOptionalComma());\n        parser.parseRSquare();\n        const indexType = new _.IndexType();\n        parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), op.operands);\n        if (staticAttrName && innerArrayAttrs.length > 0) {\n            op.addAttribute(staticAttrName, innerArrayAttrs);\n        }\n    }\n\n    parseOffsets(parser, op, attrName) {\n        const values = [];\n        for (;;) {\n            if (parser.parseOptionalMinus()) {\n                values.push(-parser.parseInteger());\n            } else {\n                const intVal = parser.parseOptionalInteger();\n                if (intVal === null) {\n                    break;\n                }\n                values.push(intVal);\n            }\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n        }\n        if (attrName) {\n            op.addAttribute(attrName, values);\n        }\n    }\n\n    parseSymbolVisibility(parser, op) {\n        const visibility = parser.parseOptionalKeyword(['public', 'private', 'nested']);\n        if (visibility) {\n            op.addAttribute('sym_visibility', visibility);\n        }\n    }\n\n    parseTypeOrAttr(parser, op, typeArg, attrArg) {\n        if (parser.parseOptionalEqual()) {\n            const attr = parser.parseAttribute();\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                op.addAttribute(typeArg, type);\n                attr.type = type;\n            } else if (attr && attr.type) {\n                op.addAttribute(typeArg, attr.type);\n            }\n            op.addAttribute(attrArg, attr);\n            return;\n        }\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            op.addAttribute(typeArg, type);\n            if (parser.parseOptionalEqual()) {\n                const attr = parser.parseAttribute();\n                if (parser.parseOptionalColon()) {\n                    const attrType = parser.parseType();\n                    attr.type = attrType;\n                }\n                op.addAttribute(attrArg, attr);\n            }\n            return;\n        }\n        throw new mlir.Error(`Expected ':' or '=' in TypeOrAttr ${parser.getCurrentLocation()}`);\n    }\n\n    parseSizeAwareType(parser, op, typeArg) {\n        const type = parser.parseType();\n        parser.parseLBrace();\n        const operand = parser.parseOperand();\n        parser.parseRBrace();\n        if (!Array.isArray(typeArg)) {\n            throw new mlir.Error(`Invalid argument 'typeArg'.`);\n        }\n        if (typeArg.length === 0) {\n            typeArg.push(type);\n        } else {\n            typeArg[0] = type;\n        }\n        if (operand) {\n            parser.resolveOperand(operand, null, op.operands);\n        }\n    }\n\n    parseCopyOpRegion(parser, result) {\n        result.regions.push({ blocks: [] });\n    }\n\n    parseResultTypeList(parser, op) {\n        const types = parser.parseCommaSeparatedList('paren', () => parser.parseType());\n        if (types.length > 0) {\n            op.addAttribute('result_types', types.map((t) => t.toString()));\n        }\n    }\n\n    parsePipelineAttr(parser, op, attrName) {\n        const keyword = parser.parseOptionalKeyword();\n        if (keyword) {\n            op.addAttribute(attrName, keyword);\n        } else {\n            const attr = parser.parseAttribute();\n            op.addAttribute(attrName, attr);\n        }\n    }\n\n    parseKnobsDictionary(parser, op, attrName) {\n        parser.parseKeyword('knobs');\n        parser.parseEqual();\n        const attr = parser.parseAttribute();\n        op.addAttribute(attrName, attr);\n    }\n\n    parseCmdParameterGatherOperations(parser, op, sourceScopeOps, sourceKeysOps, sourceOffsetsOps, targetOps, targetTypes, targetSizeOps, targetOffsetsOps, targetLengthsOps) {\n        do {\n            const firstOperand = parser.parseOperand();\n            let key = firstOperand;\n            if (parser.parseOptionalColon()) {\n                sourceScopeOps.push(firstOperand);\n                parser.parseColon();\n                key = parser.parseOperand();\n            }\n            sourceKeysOps.push(key);\n            parser.parseLSquare();\n            sourceOffsetsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseArrow();\n            const rowTarget = parser.parseOperand();\n            if (targetOps.length === 0) {\n                targetOps.push(rowTarget);\n            }\n            parser.parseLSquare();\n            targetOffsetsOps.push(parser.parseOperand());\n            parser.parseKeyword('for');\n            targetLengthsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseColon();\n            const rowType = parser.parseType();\n            if (targetTypes.length === 0) {\n                targetTypes.push(rowType);\n            }\n            parser.parseLBrace();\n            const rowSize = parser.parseOperand();\n            if (targetSizeOps.length === 0) {\n                targetSizeOps.push(rowSize);\n            }\n            parser.parseRBrace();\n        } while (parser.parseOptionalComma());\n    }\n\n    // custom<AsyncParameterGatherOperations>(...)\n    // Parses: %scope::%key[%offset] -> %target[%offset to %end for %length] : type{%size}, ...\n    parseAsyncParameterGatherOperations(parser, op, sourceScopeOps, sourceKeysOps, sourceOffsetsOps, targetOps, targetTypes, targetSizeOps, targetOffsetsOps, targetEndsOps, targetLengthsOps) {\n        do {\n            const firstOperand = parser.parseOperand();\n            let key = firstOperand;\n            if (parser.parseOptionalColon()) {\n                sourceScopeOps.push(firstOperand);\n                parser.parseColon();\n                key = parser.parseOperand();\n            }\n            sourceKeysOps.push(key);\n            parser.parseLSquare();\n            sourceOffsetsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseArrow();\n            const rowTarget = parser.parseOperand();\n            if (targetOps.length === 0) {\n                targetOps.push(rowTarget);\n            }\n            parser.parseLSquare();\n            targetOffsetsOps.push(parser.parseOperand());\n            parser.parseKeyword('to');\n            targetEndsOps.push(parser.parseOperand());\n            parser.parseKeyword('for');\n            targetLengthsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseColon();\n            const rowType = parser.parseType();\n            if (targetTypes.length === 0) {\n                targetTypes.push(rowType);\n            }\n            parser.parseLBrace();\n            const rowSize = parser.parseOperand();\n            if (targetSizeOps.length === 0) {\n                targetSizeOps.push(rowSize);\n            }\n            parser.parseRBrace();\n        } while (parser.parseOptionalComma());\n    }\n\n    // custom<CmdParameterScatterOperations>(...)\n    // Parses: %source[%offset for %length] : type{%size} -> %scope::%key[%offset], ...\n    parseCmdParameterScatterOperations(parser, op, sourceOps, sourceTypes, sourceSizeOps, sourceOffsetsOps, sourceLengthsOps, targetScopeOps, targetKeysOps, targetOffsetsOps) {\n        do {\n            const rowSource = parser.parseOperand();\n            if (sourceOps.length === 0) {\n                sourceOps.push(rowSource);\n            }\n            parser.parseLSquare();\n            sourceOffsetsOps.push(parser.parseOperand());\n            parser.parseKeyword('for');\n            sourceLengthsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseColon();\n            const rowType = parser.parseType();\n            if (sourceTypes.length === 0) {\n                sourceTypes.push(rowType);\n            }\n            parser.parseLBrace();\n            const rowSize = parser.parseOperand();\n            if (sourceSizeOps.length === 0) {\n                sourceSizeOps.push(rowSize);\n            }\n            parser.parseRBrace();\n            // Parse -> %scope::%key[%offset]\n            parser.parseArrow();\n            const firstOperand = parser.parseOperand();\n            let key = firstOperand;\n            if (parser.parseOptionalColon()) {\n                targetScopeOps.push(firstOperand);\n                parser.parseColon();\n                key = parser.parseOperand();\n            }\n            targetKeysOps.push(key);\n            parser.parseLSquare();\n            targetOffsetsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n        } while (parser.parseOptionalComma());\n    }\n\n    // custom<AsyncParameterScatterOperations>(...)\n    // Parses: %source[%offset to %end for %length] : type{%size} -> %scope::%key[%offset], ...\n    parseAsyncParameterScatterOperations(parser, op, sourceOps, sourceTypes, sourceSizeOps, sourceOffsetsOps, sourceEndsOps, sourceLengthsOps, targetScopeOps, targetKeysOps, targetOffsetsOps) {\n        do {\n            const rowSource = parser.parseOperand();\n            if (sourceOps.length === 0) {\n                sourceOps.push(rowSource);\n            }\n            parser.parseLSquare();\n            sourceOffsetsOps.push(parser.parseOperand());\n            parser.parseKeyword('to');\n            sourceEndsOps.push(parser.parseOperand());\n            parser.parseKeyword('for');\n            sourceLengthsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseColon();\n            const rowType = parser.parseType();\n            if (sourceTypes.length === 0) {\n                sourceTypes.push(rowType);\n            }\n            parser.parseLBrace();\n            const rowSize = parser.parseOperand();\n            if (sourceSizeOps.length === 0) {\n                sourceSizeOps.push(rowSize);\n            }\n            parser.parseRBrace();\n            // Parse -> %scope::%key[%offset]\n            parser.parseArrow();\n            const firstOperand = parser.parseOperand();\n            let key = firstOperand;\n            if (parser.parseOptionalColon()) {\n                targetScopeOps.push(firstOperand);\n                parser.parseColon();\n                key = parser.parseOperand();\n            }\n            targetKeysOps.push(key);\n            parser.parseLSquare();\n            targetOffsetsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n        } while (parser.parseOptionalComma());\n    }\n\n    parseEnumFlags(parser, type, separator, optional) {\n        const flags = [];\n        do {\n            if (optional && flags.length === 0) {\n                const value = parser.parseOptionalKeyword(type.values);\n                if (!value) {\n                    return null;\n                }\n                flags.push(value);\n            } else {\n                const value = parser.parseKeyword();\n                if (!type.values.includes(value)) {\n                    throw new mlir.Error(`Invalid enum value '${value}' ${parser.getCurrentLocation()}`);\n                }\n                flags.push(value);\n            }\n        } while (separator === ',' ? parser.parseOptionalComma() : parser.parseOptionalVerticalBar());\n        return new _.TypedAttr(flags.join(', '));\n    }\n\n    parseEnumFlagsAngleBracketComma(parser, type) {\n        if (parser.parseOptionalLess()) {\n            const value = this.parseEnumFlags(parser, type, ',');\n            parser.parseGreater();\n            return value;\n        }\n        return parser.parseOptionalAttribute();\n    }\n\n    parseEnumFlagsAngleBracketPipe(parser, type) {\n        if (parser.parseOptionalLess()) {\n            const value = this.parseEnumFlags(parser, type, '|');\n            parser.parseGreater();\n            return value;\n        }\n        return parser.parseOptionalAttribute();\n    }\n\n    parseOptional(parser) {\n        return parser.parseOptionalType();\n    }\n};\n\n_.hlo = {};\n\n_.hlo.HLODialect = class extends _.Dialect {\n\n    constructor(operations, name) {\n        super(operations, name);\n        this.registerCustomDirective('SameOperandsAndResultType', this.parseSameOperandsAndResultType.bind(this));\n        this.registerCustomDirective('VariadicSameOperandsAndResultType', this.parseVariadicSameOperandsAndResultType.bind(this));\n        this.registerCustomDirective('ComplexOpType', this.parseComplexOpType.bind(this));\n        this.registerCustomDirective('SelectOpType', this.parseSelectOpType.bind(this));\n        this.registerCustomDirective('TupleOpType', this.parseTupleOpType.bind(this));\n        this.registerCustomDirective('PairwiseOpType', this.parsePairwiseOpType.bind(this));\n        this.registerCustomDirective('ConvolutionDimensions', this.parseConvolutionDimensions.bind(this));\n        this.registerCustomDirective('DotDimensionNumbers', this.parseDotDimensionNumbers.bind(this));\n        this.registerCustomDirective('PrecisionConfig', this.parsePrecisionConfig.bind(this));\n        this.registerCustomDirective('PrecisionConfigAndAlgorithm', this.parsePrecisionConfigAndAlgorithm.bind(this));\n        this.registerCustomDirective('WindowAttributes', this.parseWindowAttributes.bind(this));\n        this.registerCustomDirective('SliceRanges', this.parseSliceRanges.bind(this));\n        this.registerCustomDirective('CustomCallTarget', this.parseCustomCallTarget.bind(this));\n        this.registerCustomDirective('VariadicOperandWithAttribute', this.parseVariadicOperandWithAttribute.bind(this));\n    }\n\n    assignFromFunctionType(operandArrays, resultArray, fnType) {\n        for (let i = 0; i < operandArrays.length && i < fnType.inputs.length; i++) {\n            operandArrays[i].push(fnType.inputs[i]);\n        }\n        if (fnType.results.length === 1) {\n            resultArray.push(fnType.results[0]);\n        }\n    }\n\n    parseSameOperandsAndResultType(parser, op, ...typeArrays) {\n        const type = parser.parseType();\n        if (type instanceof _.FunctionType) {\n            const operandArrays = typeArrays.slice(0, -1);\n            const resultArray = typeArrays[typeArrays.length - 1];\n            this.assignFromFunctionType(operandArrays, resultArray, type);\n        } else {\n            for (const arr of typeArrays) {\n                arr.push(type);\n            }\n        }\n    }\n\n    // custom<VariadicSameOperandsAndResultType>(ref($inputs), type($inputs), type($result))\n    parseVariadicSameOperandsAndResultType(parser, op, operands, operandTypes, resultTypes) {\n        const type = parser.parseType();\n        // All operands get the same type\n        for (let i = 0; i < operands.length; i++) {\n            operandTypes.push(type);\n        }\n        // Result also gets the same type\n        resultTypes.push(type);\n    }\n\n    // custom<ComplexOpType>(ref($operands), type($operands), type($result))\n    parseComplexOpType(parser, op, operands, operandTypes, resultTypes) {\n        const type = parser.parseType();\n        for (let i = 0; i < operands.length; i++) {\n            operandTypes.push(type);\n        }\n        resultTypes.push(type);\n    }\n\n    // custom<SelectOpType>(type($pred), type($on_true), type($on_false), type($result))\n    parseSelectOpType(parser, op, predTypes, onTrueTypes, onFalseTypes, resultTypes) {\n        const firstType = parser.parseType();\n        if (parser.parseOptionalComma()) {\n            const secondType = parser.parseType();\n            predTypes.push(firstType);\n            onTrueTypes.push(secondType);\n            onFalseTypes.push(secondType);\n            resultTypes.push(secondType);\n        } else {\n            predTypes.push(firstType);\n            onTrueTypes.push(firstType);\n            onFalseTypes.push(firstType);\n            resultTypes.push(firstType);\n        }\n    }\n\n    // custom<TupleOpType>(type($operands), type($result))\n    parseTupleOpType(parser, op, operandTypes, resultTypes) {\n        const type = parser.parseType();\n        operandTypes.push(type);\n        resultTypes.push(type);\n    }\n\n    // custom<PairwiseOpType>(type($operands), type($results))\n    parsePairwiseOpType(parser, op, operandTypes, resultTypes) {\n        while (true) {\n            const type = parser.parseType();\n            if (!type) {\n                break;\n            }\n            operandTypes.push(type);\n            resultTypes.push(type);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n        }\n    }\n\n    parseDims(parser) {\n        const dims = [];\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    const intVal = parser.parseOptionalInteger();\n                    if (intVal === null) {\n                        const kw = parser.parseOptionalKeyword();\n                        if (kw) {\n                            dims.push(kw);\n                        } else {\n                            break;\n                        }\n                    } else {\n                        dims.push(intVal);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n        }\n        return dims;\n    }\n\n    parseConvolutionDimensions(parser, op, attrName) {\n        const input = this.parseDims(parser);\n        parser.parseKeyword('x');\n        const kernel = this.parseDims(parser);\n        parser.parseArrow();\n        const output = this.parseDims(parser);\n        op.addAttribute(attrName, new _.ConvDimensionNumbersAttr(input, kernel, output));\n    }\n\n    parseWindowAttributes(parser, op, stridesAttr, paddingAttr, lhsDilationAttr, rhsDilationAttr, reversalAttr) {\n        const windowAttrs = {\n            stride: [],\n            pad: [],\n            lhs_dilate: [],\n            rhs_dilate: [],\n            window_reversal: []\n        };\n        const parseArray = () => {\n            return parser.parseCommaSeparatedList('square', () => {\n                const intValue = parser.parseOptionalInteger();\n                if (intValue !== null) {\n                    return intValue;\n                }\n                const kw = parser.parseOptionalKeyword();\n                if (kw) {\n                    return kw;\n                }\n                // Nested array\n                return parseArray();\n            });\n        };\n        for (;;) {\n            const key = parser.parseOptionalKeyword();\n            if (key) {\n                if (parser.parseOptionalEqual()) {\n                    windowAttrs[key] = parseArray();\n                }\n                parser.parseOptionalComma();\n            } else {\n                break;\n            }\n        }\n        if (stridesAttr && windowAttrs.stride.length > 0) {\n            op.addAttribute(stridesAttr, windowAttrs.stride);\n        }\n        if (paddingAttr && windowAttrs.pad.length > 0) {\n            op.addAttribute(paddingAttr, windowAttrs.pad);\n        }\n        if (lhsDilationAttr && windowAttrs.lhs_dilate.length > 0) {\n            op.addAttribute(lhsDilationAttr, windowAttrs.lhs_dilate);\n        }\n        if (rhsDilationAttr && windowAttrs.rhs_dilate.length > 0) {\n            op.addAttribute(rhsDilationAttr, windowAttrs.rhs_dilate);\n        }\n        if (reversalAttr && windowAttrs.window_reversal.length > 0) {\n            op.addAttribute(reversalAttr, windowAttrs.window_reversal);\n        }\n    }\n\n    parseDotDimensionNumbers(parser, op, attrName = 'dot_dimension_numbers') {\n        const dimensions = {\n            lhs_batching_dimensions: [],\n            rhs_batching_dimensions: [],\n            lhs_contracting_dimensions: [],\n            rhs_contracting_dimensions: []\n        };\n        const parseIntArray = () => {\n            return parser.parseCommaSeparatedList('optionalSquare', () => {\n                const value = parser.parseOptionalInteger();\n                if (value !== null) {\n                    return value;\n                }\n                parser.parseKeyword();\n                return null;\n            });\n        };\n        const parsePair = () => {\n            const first = parseIntArray();\n            let second = [];\n            if (parser.parseOptionalKeyword('x')) {\n                second = parseIntArray();\n            }\n            return { first, second };\n        };\n        if (parser.parseOptionalKeyword('batching_dims') || parser.parseOptionalKeyword('batch_dims')) {\n            parser.parseEqual();\n            const pair = parsePair();\n            dimensions.lhs_batching_dimensions = pair.first;\n            dimensions.rhs_batching_dimensions = pair.second;\n            parser.parseOptionalComma();\n        }\n        parser.parseKeyword('contracting_dims');\n        parser.parseEqual();\n        const pair = parsePair();\n        dimensions.lhs_contracting_dimensions = pair.first;\n        dimensions.rhs_contracting_dimensions = pair.second;\n        op.addAttribute(attrName, dimensions);\n    }\n\n    parsePrecisionConfig(parser, op /*, args */) {\n        parser.parseOptionalComma();\n        if (!parser.parseOptionalKeyword('precision')) {\n            return;\n        }\n\n        parser.parseEqual();\n        const precision = parser.parseCommaSeparatedList('square', () => {\n            const kw = parser.parseOptionalKeyword();\n            if (kw) {\n                return kw;\n            }\n            parser.parseKeyword();\n            return null;\n        });\n\n        if (precision.length > 0) {\n            op.addAttribute('precision_config', precision);\n        }\n    }\n\n    parsePrecisionConfigAndAlgorithm(parser, op /*, args */) {\n        if (!parser.parseOptionalComma()) {\n            return;\n        }\n\n        if (parser.parseOptionalKeyword('algorithm')) {\n            parser.parseOptionalEqual();\n            const algorithm = parser.parseAttribute();\n            op.addAttribute('algorithm', algorithm);\n            return;\n        }\n\n        if (parser.parseOptionalKeyword('precision')) {\n            parser.parseOptionalEqual();\n            const precision = parser.parseCommaSeparatedList('optionalSquare', () => {\n                const kw = parser.parseOptionalKeyword();\n                if (kw) {\n                    return kw;\n                }\n                parser.parseKeyword();\n                return null;\n            });\n\n            if (precision.length > 0) {\n                op.addAttribute('precision_config', precision);\n            }\n\n            if (parser.parseOptionalComma()) {\n                if (parser.parseOptionalKeyword('algorithm')) {\n                    parser.parseOptionalEqual();\n                    const algorithm = parser.parseAttribute();\n                    op.addAttribute('algorithm', algorithm);\n                }\n            }\n        }\n    }\n\n    parseSliceRanges(parser, op /*, args */) {\n        const ranges = {\n            start_indices: [],\n            limit_indices: [],\n            strides: []\n        };\n\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    let intVal = parser.parseOptionalInteger();\n                    if (intVal !== null) {\n                        ranges.start_indices.push(intVal);\n                    }\n                    parser.parseOptionalColon();\n                    intVal = parser.parseOptionalInteger();\n                    if (intVal !== null) {\n                        ranges.limit_indices.push(intVal);\n                    }\n                    if (parser.parseOptionalColon()) {\n                        intVal = parser.parseOptionalInteger();\n                        if (intVal !== null) {\n                            ranges.strides.push(intVal);\n                        }\n                    } else {\n                        ranges.strides.push(1);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n        }\n        op.addAttribute('start_indices', ranges.start_indices);\n        op.addAttribute('limit_indices', ranges.limit_indices);\n        op.addAttribute('strides', ranges.strides);\n    }\n\n    // custom<CustomCallTarget>($call_target_name)\n    parseCustomCallTarget(parser, op, attrName) {\n        let target = null;\n        const sym = parser.parseOptionalSymbolName();\n        if (sym) {\n            target = `@${sym.value || sym}`;\n        } else {\n            const str = parser.parseOptionalString();\n            if (str === null) {\n                throw new mlir.Error(`Expected '@' or string for CustomCallTarget at ${parser.getCurrentLocation()}`);\n            }\n            target = str;\n        }\n        op.addAttribute(attrName || 'call_target_name', target);\n    }\n\n    // custom<VariadicOperandWithAttribute>($inputs)\n    parseVariadicOperandWithAttribute(parser, op, operands) {\n        let operand = parser.parseOptionalOperand();\n        while (operand) {\n            const attrs = new Map();\n            parser.parseOptionalAttrDict(attrs);\n            if (attrs.size > 0) {\n                operand.attributes = attrs;\n            }\n            operands.push(operand);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            operand = parser.parseOptionalOperand();\n        }\n    }\n\n    parseReduceOp(parser, result, createDimensions, returnOpName, lparenConsumed = false) {\n        const unresolvedOperands = [];\n        const unresolvedInitOperands = [];\n        while (true) {\n            if (lparenConsumed) {\n                lparenConsumed = false;\n            } else if (!parser.parseOptionalLParen()) {\n                break;\n            }\n            const operand = parser.parseOperand();\n            parser.parseKeyword('init');\n            parser.parseColon();\n            const initOperand = parser.parseOperand();\n            parser.parseRParen();\n            unresolvedOperands.push(operand);\n            unresolvedInitOperands.push(initOperand);\n            parser.parseOptionalComma();\n        }\n        const allUnresolved = unresolvedOperands.concat(unresolvedInitOperands);\n        if (parser.parseOptionalKeyword('applies')) {\n            const innerOpName = parser.parseCustomOperationName();\n            parser.parseKeyword('across');\n            parser.parseKeyword('dimensions');\n            parser.parseEqual();\n            const dimensions = parser.parseCommaSeparatedList('square', () => {\n                const intVal = parser.parseOptionalInteger();\n                if (intVal === null) {\n                    throw new mlir.Error(`Expected integer dimension in reduce operation ${parser.getCurrentLocation()}`);\n                }\n                return intVal;\n            });\n            result.addAttribute('dimensions', createDimensions(dimensions));\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (type instanceof _.FunctionType) {\n                    parser.resolveOperands(allUnresolved, type.inputs, result.operands);\n                    result.addTypes(type.results);\n                } else {\n                    const types = Array.isArray(type) ? type : [type];\n                    parser.resolveOperands(allUnresolved, allUnresolved.map((_, i) => types[i] || types[0]), result.operands);\n                    result.addTypes(parser.parseOptionalArrowTypeList());\n                }\n            } else {\n                parser.resolveOperands(allUnresolved, allUnresolved.map(() => null), result.operands);\n            }\n            const region = { blocks: [] };\n            const block = { operations: [], arguments: [] };\n            let tensorType = null;\n            if (result.operands.length > 0 && result.operands[0].type) {\n                const operandType = result.operands[0].type;\n                if (operandType instanceof _.RankedTensorType || operandType instanceof _.UnrankedTensorType) {\n                    tensorType = new _.RankedTensorType([], operandType.elementType);\n                }\n            }\n            block.arguments.push({ value: '%lhs', type: tensorType });\n            block.arguments.push({ value: '%rhs', type: tensorType });\n            const innerOp = new _.OperationState(null, innerOpName);\n            innerOp.operands.push(new _.Value('%lhs', tensorType));\n            innerOp.operands.push(new _.Value('%rhs', tensorType));\n            if (tensorType) {\n                innerOp.addTypes([tensorType]);\n            }\n            block.operations.push(_.Operation.create(innerOp));\n            const returnOp = new _.OperationState(null, this.getOperation(returnOpName));\n            returnOp.operands.push(new _.Value('%0', tensorType));\n            block.operations.push(_.Operation.create(returnOp));\n            region.blocks.push(block);\n            result.regions.push(region);\n            return true;\n        }\n\n        // Non-compact syntax: parse \"across dimensions = [...] : type reducer (args) { ... }\"\n        parser.parseKeyword('across');\n        parser.parseKeyword('dimensions');\n        parser.parseEqual();\n        const dimensions = parser.parseCommaSeparatedList('square', () => {\n            return parser.parseInteger();\n        });\n        result.addAttribute('dimensions', createDimensions(dimensions));\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            if (type instanceof _.FunctionType) {\n                parser.resolveOperands(allUnresolved, type.inputs, result.operands);\n                result.addTypes(type.results);\n            } else {\n                const types = Array.isArray(type) ? type : [type];\n                parser.resolveOperands(allUnresolved, types, result.operands);\n            }\n        }\n        parser.parseKeyword('reducer');\n        // Parse block arguments: (%lhs : type, %rhs : type) (%linit : type, %rinit : type)\n        const regionArgs = [];\n        while (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const value = parser.parseOperand();\n                    parser.parseColon();\n                    const type = parser.parseType();\n                    regionArgs.push({ value, type });\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region, regionArgs);\n        return true;\n    }\n\n    // Parse scan operation format: scan (%inputs) inits (%inits) dimension=0 { body } : types\n    parseScanOp(parser, result, returnOpName, lparenConsumed = false) {\n        let unresolvedInputs = null;\n        if (lparenConsumed) {\n            unresolvedInputs = [];\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    unresolvedInputs.push(parser.parseOperand());\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        } else {\n            unresolvedInputs = parser.parseCommaSeparatedList('paren', () => parser.parseOperand());\n        }\n\n        parser.parseKeyword('inits');\n        const unresolvedInits = parser.parseCommaSeparatedList('paren', () => parser.parseOperand());\n\n        parser.parseKeyword('dimension');\n        parser.parseOptionalEqual();\n        result.addAttribute('dimension', parser.parseInteger());\n\n        // Parse optional attributes: is_reverse=true, is_associative=true\n        while (parser.parseOptionalComma()) {\n            if (parser.parseOptionalKeyword('is_reverse')) {\n                parser.parseOptionalEqual();\n                const value = parser.parseKeyword();\n                result.addAttribute('is_reverse', value === 'true');\n            } else if (parser.parseOptionalKeyword('is_associative')) {\n                parser.parseOptionalEqual();\n                const value = parser.parseKeyword();\n                result.addAttribute('is_associative', value === 'true');\n            }\n        }\n\n        const region = result.addRegion();\n        parser.parseRegion(region, undefined, true); // IsolatedFromAbove\n\n        // Parse types: : (input types, init types) -> (output types, carry types)\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            if (type instanceof _.FunctionType) {\n                const allUnresolved = unresolvedInputs.concat(unresolvedInits);\n                parser.resolveOperands(allUnresolved, type.inputs, result.operands);\n                result.addTypes(type.results);\n            }\n        }\n\n        return true;\n    }\n\n    parseWhileOp(parser, result, lparenConsumed = false) {\n        if (!lparenConsumed) {\n            parser.parseLParen();\n        }\n        const unresolvedOperands = [];\n        if (!parser.parseOptionalRParen()) {\n            do {\n                parser.parseOperand(); // iter_arg\n                if (parser.parseOptionalEqual()) {\n                    unresolvedOperands.push(parser.parseOperand());\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        const types = [];\n        if (unresolvedOperands.length > 0) {\n            parser.parseColon();\n            const typeList = parser.parseTypeList();\n            types.push(...typeList);\n        }\n        parser.resolveOperands(unresolvedOperands, types, result.operands);\n        result.addTypes(types);\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        parser.parseKeyword('cond');\n        const cond = result.addRegion();\n        parser.parseRegion(cond);\n        parser.parseKeyword('do');\n        const body = result.addRegion();\n        parser.parseRegion(body);\n        return true;\n    }\n};\n\n_.stablehlo = {};\n\n_.stablehlo.StableHLODialect = class extends _.hlo.HLODialect {\n\n    constructor(operations) {\n        super(operations, 'stablehlo');\n        this.registerCustomDirective('ExponentMantissa', this.parseExponentMantissa.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'stablehlo.constant') {\n            if (parser.parseOptionalLParen() && parser.parseOptionalRParen()) {\n                if (parser.parseOptionalLess()) {\n                    result.propertiesAttr = parser.parseAttribute();\n                    parser.parseGreater();\n                }\n                parser.parseOptionalAttrDict(result.attributes);\n                parser.parseColon();\n                parser.parseLParen();\n                parser.parseRParen();\n                parser.parseArrow();\n                const type = parser.parseType();\n                result.addTypes([type]);\n            } else {\n                // Custom form: {attrs} value : type\n                parser.parseOptionalAttrDict(result.attributes);\n                const value = parser.parseAttribute();\n                if (value) {\n                    result.addAttribute('value', value);\n                }\n                const types = parser.parseOptionalColonTypeList();\n                if (types.length > 0) {\n                    result.addTypes([types[0]]);\n                } else if (value && value.type) {\n                    result.addTypes([value.type]);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'stablehlo.while') {\n            return super.parseWhileOp(parser, result);\n        }\n        if (result.op === 'stablehlo.reduce') {\n            return super.parseReduceOp(parser, result, (dims) => dims, 'stablehlo.return');\n        }\n        if (result.op === 'stablehlo.scan') {\n            return super.parseScanOp(parser, result, 'stablehlo.return');\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic === 'token') {\n            return new _.Type(`!${dialect}.token`);\n        }\n        throw new mlir.Error(`Unknown '${dialect}' type '${mnemonic}' ${parser.getNameLoc()}`);\n    }\n\n    parseExponentMantissa(parser, op, exponentAttr, mantissaAttr) {\n        const keyword = parser.parseKeyword();\n        const match = /^e(\\d+)m(\\d+)$/.exec(keyword);\n        if (!match) {\n            throw new mlir.Error(`Expected exponent mantissa in format e#m#, got '${keyword}'`);\n        }\n        const exponent = parseInt(match[1], 10);\n        const mantissa = parseInt(match[2], 10);\n        op.addAttribute(exponentAttr, exponent);\n        op.addAttribute(mantissaAttr, mantissa);\n    }\n};\n\n_.VhloDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'vhlo');\n        this.registerCustomDirective('FunctionBody', this.parseFunctionBody.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'vhlo.constant_v1') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const value = parser.parseAttribute();\n            if (value) {\n                result.addAttribute('value', value);\n            }\n            result.addTypes(parser.parseOptionalColonTypeList());\n            return true;\n        }\n\n        if (result.op === 'vhlo.return_v1') {\n            const unresolvedOperands = parser.parseOperandList();\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            return true;\n        }\n\n        return super.parseOperation(parser, result);\n    }\n\n    parseFunctionBody(parser, result) {\n        parser.parseFunctionOp(result, false);\n    }\n};\n\n_.InterpreterDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'interpreter');\n    }\n};\n\n_.AffineDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'affine');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'affine.parallel') {\n            return this.parseParallelOp(parser, result);\n        }\n        if (result.op === 'affine.for') {\n            return this.parseForOp(parser, result);\n        }\n        if (result.op === 'affine.if') {\n            const condAttr = parser.parseAttribute();\n            result.addAttribute('condition', condAttr);\n            parser.parseDimAndSymbolList(result.operands);\n            result.addTypes(parser.parseOptionalArrowTypeList());\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            if (parser.parseOptionalKeyword('else')) {\n                const elseRegion = {};\n                parser.parseRegion(elseRegion);\n                result.regions.push(elseRegion);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (result.op === 'affine.apply' || result.op === 'affine.min' || result.op === 'affine.max') {\n            const indexType = new _.IndexType();\n            const mapAttr = parser.parseAttribute();\n            result.addAttribute('map', mapAttr);\n            parser.parseDimAndSymbolList(result.operands);\n            parser.parseOptionalAttrDict(result.attributes);\n            result.addTypes([indexType]);\n            return true;\n        }\n        if (result.op === 'affine.store') {\n            return this.parseStoreOp(parser, result);\n        }\n        if (result.op === 'affine.load') {\n            return this.parseLoadOp(parser, result);\n        }\n        if (result.op === 'affine.vector_load') {\n            return this.parseVectorLoadOp(parser, result);\n        }\n        if (result.op === 'affine.vector_store') {\n            return this.parseVectorStoreOp(parser, result);\n        }\n        if (result.op === 'affine.prefetch') {\n            const indexType = new _.IndexType();\n            const memref = parser.parseOperand();\n            const mapOperands = [];\n            parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n            parser.parseComma();\n            const rwSpecifier = parser.parseOptionalKeyword();\n            result.addAttribute('isWrite', rwSpecifier === 'write');\n            parser.parseComma();\n            parser.parseKeyword('locality');\n            parser.parseLess();\n            result.addAttribute('localityHint', parser.parseInteger());\n            parser.parseGreater();\n            parser.parseComma();\n            const cacheType = parser.parseOptionalKeyword();\n            result.addAttribute('isDataCache', cacheType === 'data');\n            parser.parseOptionalAttrDict(result.attributes);\n            const type = parser.parseColonType();\n            parser.resolveOperand(memref, type, result.operands);\n            parser.resolveOperands(mapOperands, mapOperands.map(() => indexType), result.operands);\n            return true;\n        }\n        if (result.op === 'affine.dma_start') {\n            const indexType = new _.IndexType();\n            const srcMemRef = parser.parseOperand();\n            const srcMapOperands = [];\n            parser.parseAffineMapOfSSAIds(srcMapOperands, null, 'src_map', result.attributes);\n            parser.parseComma();\n            const dstMemRef = parser.parseOperand();\n            const dstMapOperands = [];\n            parser.parseAffineMapOfSSAIds(dstMapOperands, null, 'dst_map', result.attributes);\n            parser.parseComma();\n            const tagMemRef = parser.parseOperand();\n            const tagMapOperands = [];\n            parser.parseAffineMapOfSSAIds(tagMapOperands, null, 'tag_map', result.attributes);\n            parser.parseComma();\n            const numElements = parser.parseOperand();\n            // Parse optional stride operands\n            const strideOperands = parser.parseTrailingOperandList();\n            const types = parser.parseColonTypeList();\n            parser.resolveOperand(srcMemRef, types[0], result.operands);\n            parser.resolveOperands(srcMapOperands, srcMapOperands.map(() => indexType), result.operands);\n            parser.resolveOperand(dstMemRef, types[1], result.operands);\n            parser.resolveOperands(dstMapOperands, dstMapOperands.map(() => indexType), result.operands);\n            parser.resolveOperand(tagMemRef, types[2], result.operands);\n            parser.resolveOperands(tagMapOperands, tagMapOperands.map(() => indexType), result.operands);\n            parser.resolveOperand(numElements, indexType, result.operands);\n            parser.resolveOperands(strideOperands, strideOperands.map(() => indexType), result.operands);\n            return true;\n        }\n        if (result.op === 'affine.dma_wait') {\n            const indexType = new _.IndexType();\n            const tagMemRef = parser.parseOperand();\n            const tagMapOperands = [];\n            parser.parseAffineMapOfSSAIds(tagMapOperands, null, 'tag_map', result.attributes);\n            parser.parseComma();\n            const numElements = parser.parseOperand();\n            const type = parser.parseColonType();\n            parser.resolveOperand(tagMemRef, type, result.operands);\n            parser.resolveOperands(tagMapOperands, tagMapOperands.map(() => indexType), result.operands);\n            parser.resolveOperand(numElements, indexType, result.operands);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseForOp(parser, result) {\n        const inductionVar = parser.parseOperand();\n        parser.parseOptionalLocationSpecifier();\n        parser.parseEqual();\n        this.parseBound(true, parser, result);\n        parser.parseKeyword('to');\n        this.parseBound(false, parser, result);\n        if (parser.parseOptionalKeyword('step')) {\n            const step = parser.parseOptionalInteger();\n            if (step !== null) {\n                result.addAttribute('step', String(step));\n            }\n        }\n        if (parser.parseOptionalKeyword('iter_args')) {\n            const unresolvedIterOperands = [];\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const iterArg = parser.parseOptionalOperand();\n                        if (iterArg) {\n                            // iter arg (block arg) - consumed but discarded\n                        }\n                        if (parser.parseOptionalEqual()) {\n                            const operand = parser.parseOptionalOperand();\n                            if (operand) {\n                                unresolvedIterOperands.push(operand);\n                            } else {\n                                parser.parseAttribute();\n                            }\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            const iterTypes = parser.parseOptionalArrowTypeList();\n            result.addTypes(iterTypes);\n            parser.resolveOperands(unresolvedIterOperands, iterTypes, result.operands);\n        }\n        {\n            const region = {};\n            if (parser.parseOptionalRegion(region, undefined, false)) {\n                if (region.blocks && region.blocks.length > 0) {\n                    if (!region.blocks[0].arguments) {\n                        region.blocks[0].arguments = [];\n                    }\n                    if (region.blocks[0].arguments.length > 0) {\n                        region.blocks[0].arguments[0] = { value: inductionVar };\n                    } else {\n                        region.blocks[0].arguments.push({ value: inductionVar });\n                    }\n                }\n                result.regions.push(region);\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseBound(isLower, parser, result) {\n        const indexType = new _.IndexType();\n        const boundAttrName = isLower ? 'lowerBoundMap' : 'upperBoundMap';\n        if (isLower) {\n            parser.parseOptionalKeyword('max');\n        } else {\n            parser.parseOptionalKeyword('min');\n        }\n        const boundOpInfos = parser.parseOperandList();\n        if (boundOpInfos.length > 0) {\n            parser.resolveOperand(boundOpInfos[0], indexType, result.operands);\n            result.addAttribute(boundAttrName, 'symbol_identity');\n            return;\n        }\n        const boundAttr = parser.parseAttribute();\n        if (boundAttr instanceof _.AffineMapAttr) {\n            result.addAttribute(boundAttrName, boundAttr);\n            parser.parseDimAndSymbolList(result.operands);\n            return;\n        }\n        if (boundAttr instanceof _.IntegerAttr || typeof boundAttr === 'number' || typeof boundAttr === 'bigint') {\n            result.addAttribute(boundAttrName, boundAttr);\n            return;\n        }\n        result.addAttribute(boundAttrName, boundAttr);\n    }\n\n    parseStoreOp(parser, result) {\n        const indexType = new _.IndexType();\n        const storeValue = parser.parseOperand();\n        parser.parseComma();\n        const memref = parser.parseOperand();\n        const mapOperands = [];\n        parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n        parser.parseOptionalAttrDict(result.attributes);\n        const type = parser.parseColonType();\n        const valueType = type.elementType || type;\n        parser.resolveOperand(storeValue, valueType, result.operands);\n        parser.resolveOperand(memref, type, result.operands);\n        parser.resolveOperands(mapOperands, mapOperands.map(() => indexType), result.operands);\n        return true;\n    }\n\n    parseLoadOp(parser, result) {\n        const indexType = new _.IndexType();\n        const memref = parser.parseOperand();\n        const mapOperands = [];\n        parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n        parser.parseOptionalAttrDict(result.attributes);\n        const type = parser.parseColonType();\n        parser.resolveOperand(memref, type, result.operands);\n        parser.resolveOperands(mapOperands, mapOperands.map(() => indexType), result.operands);\n        result.addTypes([type.elementType || type]);\n        return true;\n    }\n\n    parseVectorLoadOp(parser, result) {\n        const indexType = new _.IndexType();\n        const memref = parser.parseOperand();\n        const mapOperands = [];\n        parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n        parser.parseOptionalAttrDict(result.attributes);\n        const memrefType = parser.parseColonType();\n        parser.parseComma();\n        const vectorType = parser.parseType();\n        parser.resolveOperand(memref, memrefType, result.operands);\n        parser.resolveOperands(mapOperands, mapOperands.map(() => indexType), result.operands);\n        result.addTypes([vectorType]);\n        return true;\n    }\n\n    parseVectorStoreOp(parser, result) {\n        const indexType = new _.IndexType();\n        const storeValue = parser.parseOperand();\n        parser.parseComma();\n        const memref = parser.parseOperand();\n        const mapOperands = [];\n        parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n        parser.parseOptionalAttrDict(result.attributes);\n        const memrefType = parser.parseColonType();\n        parser.parseComma();\n        const vectorType = parser.parseType();\n        parser.resolveOperand(storeValue, vectorType, result.operands);\n        parser.resolveOperand(memref, memrefType, result.operands);\n        parser.resolveOperands(mapOperands, mapOperands.map(() => indexType), result.operands);\n        return true;\n    }\n\n    parseAffineMapWithMinMax(parser, mapOperands, minMaxKeyword) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                if (parser.parseOptionalKeyword(minMaxKeyword)) {\n                    parser.parseAffineMapOfSSAIds(mapOperands, null, '__bound', new Map(), 'Paren');\n                } else {\n                    parser.parseAffineExprOfSSAIds(mapOperands);\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n    }\n\n    parseParallelOp(parser, result) {\n        const ivArgs = parser.parseArgumentList('paren', false);\n        const indexType = new _.IndexType();\n        for (const iv of ivArgs) {\n            iv.type = indexType;\n        }\n        if (!parser.parseOptionalEqual()) {\n            return false;\n        }\n        const lowerMapOperands = [];\n        this.parseAffineMapWithMinMax(parser, lowerMapOperands, 'max');\n        if (!parser.parseOptionalKeyword('to')) {\n            return false;\n        }\n        const upperMapOperands = [];\n        this.parseAffineMapWithMinMax(parser, upperMapOperands, 'min');\n        if (parser.parseOptionalKeyword('step')) {\n            const stepMapOperands = [];\n            parser.parseAffineMapOfSSAIds(stepMapOperands, null, 'step', result.attributes, 'Paren');\n        }\n        parser.resolveOperands(lowerMapOperands, lowerMapOperands.map(() => indexType), result.operands);\n        parser.resolveOperands(upperMapOperands, upperMapOperands.map(() => indexType), result.operands);\n        if (parser.parseOptionalKeyword('reduce')) {\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    parser.parseOptionalString();\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        if (parser.parseOptionalArrow()) {\n            const resultTypes = [];\n            const resultAttrs = [];\n            parser.parseFunctionResultList(resultTypes, resultAttrs);\n            result.addTypes(resultTypes);\n        }\n        const region = result.addRegion();\n        parser.parseOptionalRegion(region, ivArgs);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n};\n\n_.MemRefDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'memref');\n        this.registerCustomDirective('GlobalMemrefOpTypeAndInitialValue', this.parseGlobalMemrefOpTypeAndInitialValue.bind(this));\n        // AtomicRMWKindAttr can appear as bare id (addi) or string (\"addi\") in different test files\n        this.registerCustomAttribute('AtomicRMWKindAttr', this.parseAtomicRMWKindAttr.bind(this));\n    }\n\n    parseAtomicRMWKindAttr(parser, type) {\n        // Accept both bare identifier (addi) and string literal (\"addi\")\n        const str = parser.parseOptionalString();\n        if (str !== null) {\n            return str;\n        }\n        if (type.values) {\n            const kw = parser.parseOptionalKeyword(type.values);\n            if (kw) {\n                return kw;\n            }\n        }\n        return null;\n    }\n\n    parseGlobalMemrefOpTypeAndInitialValue(parser, op, typeAttr = 'type', initialValueAttr = 'initial_value') {\n        const type = parser.parseType();\n        op.addAttribute(typeAttr, { value: type, type: 'type' });\n\n        if (parser.parseOptionalEqual()) {\n            if (parser.parseOptionalKeyword('uninitialized')) {\n                op.addAttribute(initialValueAttr, 'uninitialized');\n            } else {\n                // Pass the type to parseAttribute to suppress : type suffix parsing\n                const initialValue = parser.parseAttribute(type);\n                op.addAttribute(initialValueAttr, initialValue);\n            }\n        }\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'memref.tensor_load') {\n            const unresolvedOperands = parser.parseOperandList();\n            const types = parser.parseOptionalColonTypeList();\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            // Infer result tensor type from memref operand type\n            if (result.operands.length > 0 && result.operands[0].type) {\n                const memrefType = result.operands[0].type;\n                // Convert memref type to tensor type\n                if (memrefType instanceof _.MemRefType) {\n                    result.addTypes([new _.RankedTensorType(memrefType.shape, memrefType.elementType, null)]);\n                } else if (memrefType instanceof _.UnrankedMemRefType) {\n                    result.addTypes([new _.UnrankedTensorType(memrefType.elementType)]);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'memref.store') {\n            result.compatibility = true;\n            return this.parseStoreOp(parser, result);\n        }\n        if (result.op === 'memref.alloca_scope') {\n            return this.parseAllocaScopeOp(parser, result);\n        }\n        if (result.op === 'memref.transpose') {\n            return this.parseTransposeOp(parser, result);\n        }\n        if (result.op === 'memref.generic_atomic_rmw') {\n            return this.parseGenericAtomicRMWOp(parser, result);\n        }\n        if (result.op === 'memref.prefetch') {\n            const memref = parser.parseOperand();\n            const indices = parser.parseOperandList('square');\n            parser.parseComma();\n            const readOrWrite = parser.parseKeyword();\n            result.addAttribute('isWrite', readOrWrite === 'write');\n            parser.parseComma();\n            parser.parseKeyword('locality');\n            parser.parseLess();\n            result.addAttribute('localityHint', parser.parseInteger());\n            parser.parseGreater();\n            parser.parseComma();\n            const cacheType = parser.parseKeyword();\n            result.addAttribute('isDataCache', cacheType === 'data');\n            const type = parser.parseColonType();\n            parser.resolveOperand(memref, type, result.operands);\n            const indexType = new _.IndexType();\n            const indexTypes = indices.map(() => indexType);\n            parser.resolveOperands(indices, indexTypes, result.operands);\n            return true;\n        }\n        if (result.op === 'memref.dma_start') {\n            const srcMemRef = parser.parseOperand();\n            const srcIndices = parser.parseOperandList('square');\n            parser.parseComma();\n            const dstMemRef = parser.parseOperand();\n            const dstIndices = parser.parseOperandList('square');\n            parser.parseComma();\n            const numElements = parser.parseOperand();\n            parser.parseComma();\n            const tagMemRef = parser.parseOperand();\n            const tagIndices = parser.parseOperandList('square');\n            const strideInfo = [];\n            if (parser.parseOptionalComma()) {\n                let strideOp = parser.parseOptionalOperand();\n                while (strideOp) {\n                    strideInfo.push(strideOp);\n                    if (!parser.parseOptionalComma()) {\n                        break;\n                    }\n                    strideOp = parser.parseOptionalOperand();\n                }\n            }\n            const types = parser.parseColonTypeList();\n            const indexType = new _.IndexType();\n            parser.resolveOperand(srcMemRef, types[0], result.operands);\n            const srcIndexTypes = srcIndices.map(() => indexType);\n            parser.resolveOperands(srcIndices, srcIndexTypes, result.operands);\n            parser.resolveOperand(dstMemRef, types[1], result.operands);\n            const dstIndexTypes = dstIndices.map(() => indexType);\n            parser.resolveOperands(dstIndices, dstIndexTypes, result.operands);\n            parser.resolveOperand(numElements, indexType, result.operands);\n            parser.resolveOperand(tagMemRef, types[2], result.operands);\n            const tagIndexTypes = tagIndices.map(() => indexType);\n            parser.resolveOperands(tagIndices, tagIndexTypes, result.operands);\n            if (strideInfo.length > 0) {\n                const strideTypes = strideInfo.map(() => indexType);\n                parser.resolveOperands(strideInfo, strideTypes, result.operands);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseGenericAtomicRMWOp(parser, result) {\n        const memref = parser.parseOperand();\n        const indices = parser.parseOperandList('square');\n        parser.parseColon();\n        const memrefType = parser.parseType();\n        parser.resolveOperand(memref, memrefType, result.operands);\n        const indexType = new _.IndexType();\n        const indexTypes = indices.map(() => indexType);\n        parser.resolveOperands(indices, indexTypes, result.operands);\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        if (memrefType && memrefType.elementType) {\n            result.addTypes([memrefType.elementType]);\n        }\n        return true;\n    }\n\n    parseTransposeOp(parser, result) {\n        const operand = parser.parseOperand();\n        const permutation = parser.parseAffineMap();\n        result.addAttribute('permutation', new _.AffineMapAttr(permutation));\n        parser.parseOptionalAttrDict(result.attributes);\n        const srcType = parser.parseColonType();\n        parser.resolveOperand(operand, srcType, result.operands);\n        const dstType = parser.parseKeywordType('to');\n        result.addTypes([dstType]);\n        return true;\n    }\n\n    parseAllocaScopeOp(parser, result) {\n        const resultTypes = parser.parseOptionalArrowTypeList();\n        result.addTypes(resultTypes);\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseStoreOp(parser, result) {\n        // or old: value to memref[indices] : type\n        let valueOperand = null;\n        const operand = parser.parseOptionalOperand();\n        if (operand) {\n            valueOperand = operand;\n        } else {\n            // Non-standard: constant value - store as attribute\n            const value = parser.parseAttribute();\n            result.addAttribute('value', value);\n        }\n        // Accept either ',' (new) or 'to' (old)\n        if (!parser.parseOptionalKeyword('to')) {\n            parser.parseOptionalComma();\n        }\n        const memrefOperand = parser.parseOperand();\n        const indices = parser.parseOperandList('square');\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const memrefType = parser.parseType();\n            // Value type is element type of memref\n            const valueType = memrefType.elementType || memrefType;\n            if (valueOperand) {\n                parser.resolveOperand(valueOperand, valueType, result.operands);\n            }\n            parser.resolveOperand(memrefOperand, memrefType, result.operands);\n            const indexType = new _.IndexType();\n            parser.resolveOperands(indices, indices.map(() => indexType), result.operands);\n        }\n        return true;\n    }\n};\n\n_.VectorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'vector');\n        this.registerCustomAttribute('Vector_CombiningKindAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n        this.registerCustomAttribute('Arith_FastMathAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'vector.splat') {\n            const unresolvedOperands = parser.parseOperandList();\n            const types = parser.parseOptionalColonTypeList();\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            result.addTypes(types);\n            return true;\n        }\n        if (result.op === 'vector.contract') {\n            const dictAttr = parser.parseAttribute();\n            const unresolvedOperands = parser.parseOperandList();\n            parser.parseOptionalAttrDict(result.attributes);\n            const types = parser.parseColonTypeList();\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            const resultType = parser.parseKeywordType('into');\n            result.addTypes([resultType]);\n            if (dictAttr instanceof _.DictionaryAttr) {\n                for (const [key, value] of dictAttr.value) {\n                    result.attributes.set(key, value);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'vector.mask') {\n            let mask = null;\n            let passthru = null;\n            let hasPassthru = false;\n            mask = parser.parseOptionalOperand();\n            if (mask && parser.parseOptionalComma()) {\n                hasPassthru = true;\n                passthru = parser.parseOperand();\n            }\n            {\n                const region = result.addRegion();\n                parser.parseOptionalRegion(region);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            const [maskType] = parser.parseOptionalColonTypeList();\n            const resultTypes = parser.parseOptionalArrowTypeList();\n            if (mask) {\n                parser.resolveOperand(mask, maskType, result.operands);\n            }\n            if (hasPassthru && passthru) {\n                parser.resolveOperand(passthru, resultTypes[0], result.operands);\n            }\n            result.addTypes(resultTypes);\n            return true;\n        }\n        if (result.op === 'vector.outerproduct') {\n            return this.parseOuterProductOp(parser, result);\n        }\n        if (result.op === 'vector.transfer_read' || result.op === 'vector.transfer_write') {\n            return this.parseTransferOp(parser, result);\n        }\n        if (result.op === 'vector.extract' && !result.isGeneric) {\n            result.compatibility = true;\n            return this.parseExtractOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseOuterProductOp(parser, result) {\n        const operandsInfo = parser.parseOperandList();\n        parser.parseOptionalAttrDict(result.attributes);\n        const tLHS = parser.parseColonType();\n        parser.parseComma();\n        const tRHS = parser.parseType();\n        const vLHS = tLHS instanceof _.VectorType ? tLHS : null;\n        const vRHS = tRHS instanceof _.VectorType ? tRHS : null;\n        let resType = null;\n        if (vRHS) {\n            const scalableDimsRes = [\n                vLHS.scalableDims ? vLHS.scalableDims[0] : false,\n                vRHS.scalableDims ? vRHS.scalableDims[0] : false\n            ];\n            resType = new _.VectorType([vLHS.shape[0], vRHS.shape[0]], vLHS.elementType, scalableDimsRes);\n        } else {\n            // Scalar RHS operand\n            const scalableDimsRes = [vLHS.scalableDims ? vLHS.scalableDims[0] : false];\n            resType = new _.VectorType([vLHS.shape[0]], vLHS.elementType, scalableDimsRes);\n        }\n        parser.resolveOperand(operandsInfo[0], tLHS, result.operands);\n        parser.resolveOperand(operandsInfo[1], tRHS, result.operands);\n        if (operandsInfo.length > 2) {\n            parser.resolveOperand(operandsInfo[2], resType, result.operands);\n        }\n        result.addTypes([resType]);\n        return true;\n    }\n\n    parseExtractOp(parser, result) {\n        // Old syntax (pre-2023): %r = vector.extract %v[0] : vector<4xf32>\n        // New syntax: %r = vector.extract %v[0] : f32 from vector<4xf32>\n        const unresolvedSource = parser.parseOperand();\n        const unresolvedDynIndices = [];\n        const indexType = new _.IndexType();\n        let numStaticIndices = 0;\n\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    const staticIndex = parser.parseOptionalInteger();\n                    if (staticIndex === null) {\n                        const dynIndex = parser.parseOptionalOperand();\n                        if (dynIndex) {\n                            unresolvedDynIndices.push(dynIndex);\n                        } else {\n                            break;\n                        }\n                    } else {\n                        numStaticIndices++;\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const resultType = parser.parseType();\n\n            if (parser.parseOptionalKeyword('from')) {\n                const sourceType = parser.parseType();\n                parser.resolveOperand(unresolvedSource, sourceType, result.operands);\n                result.addTypes([resultType]);\n            } else {\n                // Old syntax: the type after ':' is the source type\n                // Result type is inferred by removing dimensions based on indices\n                parser.resolveOperand(unresolvedSource, resultType, result.operands);\n                // Infer result type from source type and number of indices\n                const numIndices = numStaticIndices + unresolvedDynIndices.length;\n                if (resultType instanceof _.VectorType && numIndices > 0) {\n                    const shape = resultType.shape.slice(numIndices);\n                    if (shape.length === 0) {\n                        // Scalar result\n                        result.addTypes([resultType.elementType]);\n                    } else {\n                        const scalableDims = resultType.scalableDims ? resultType.scalableDims.slice(numIndices) : [];\n                        result.addTypes([new _.VectorType(shape, resultType.elementType, scalableDims)]);\n                    }\n                } else if (resultType instanceof _.VectorType) {\n                    // No indices - result is the same as source\n                    result.addTypes([resultType]);\n                }\n            }\n            parser.resolveOperands(unresolvedDynIndices, unresolvedDynIndices.map(() => indexType), result.operands);\n        }\n\n        return true;\n    }\n\n    parseTransferOp(parser, result) {\n        // C++ ref: TransferReadOp::parse / TransferWriteOp::parse in VectorOps.cpp\n        //    vector.transfer_read %source[%i, %j, ...], %padding, %mask {attrs} : memref_type, vector_type\n        //    vector.transfer_write %value, %dest[%i, %j, ...] {attrs} : vector_type, memref_type\n        //    vector.transfer_write %value, %dest[%i, %j, ...], %mask {attrs} : vector_type, memref_type\n\n        let unresolvedFirst = null;\n        let unresolvedSecond = null;\n        let unresolvedMask = null;\n        let indexInfo = [];\n        if (result.op === 'vector.transfer_read') {\n            unresolvedFirst = parser.parseOperand();\n            indexInfo = parser.parseOperandList('square');\n            parser.parseComma();\n            unresolvedSecond = parser.parseOperand();\n            if (parser.parseOptionalComma()) {\n                unresolvedMask = parser.parseOperand();\n            }\n        } else {\n            unresolvedFirst = parser.parseOperand();\n            parser.parseComma();\n            unresolvedSecond = parser.parseOperand();\n            indexInfo = parser.parseOperandList('square');\n            if (parser.parseOptionalComma()) {\n                unresolvedMask = parser.parseOperand();\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type1 = parser.parseType();\n            parser.parseOptionalComma();\n            const type2 = parser.parseType();\n            const indexType = new _.IndexType();\n            parser.resolveOperand(unresolvedFirst, type1, result.operands);\n            if (result.op === 'vector.transfer_read') {\n                parser.resolveOperands(indexInfo, indexInfo.map(() => indexType), result.operands);\n                parser.resolveOperand(unresolvedSecond, type2, result.operands);\n            } else {\n                parser.resolveOperand(unresolvedSecond, type2, result.operands);\n                parser.resolveOperands(indexInfo, indexInfo.map(() => indexType), result.operands);\n            }\n            if (unresolvedMask) {\n                parser.resolveOperand(unresolvedMask, type2, result.operands);\n            }\n            // For transfer_read, type2 is the result type\n            // For transfer_write to tensor (not memref), the result is the updated tensor\n            if (result.op === 'vector.transfer_read') {\n                result.addTypes([type2]);\n            } else if (result.op === 'vector.transfer_write' && type2 instanceof _.RankedTensorType) {\n                result.addTypes([type2]);\n            }\n        }\n\n        return true;\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'vector.shuffle') {\n            const maskAttr = op.attributes.get('mask');\n            if (maskAttr instanceof _.DenseI64ArrayAttr && op.operands.length > 0) {\n                const v1Type = op.operands[0].type;\n                if (v1Type instanceof _.VectorType) {\n                    const maskLength = BigInt(maskAttr.value.length);\n                    const trailingDims = v1Type.shape.slice(1);\n                    const resultShape = [maskLength, ...trailingDims];\n                    const resultType = new _.VectorType(resultShape, v1Type.elementType, v1Type.scalableDims ? [false, ...v1Type.scalableDims.slice(1)] : []);\n                    op.addTypes([resultType]);\n                    return;\n                }\n            }\n        }\n        if (op.op === 'vector.to_elements' && op.operands.length > 0) {\n            const vecType = op.operands[0].type;\n            if (vecType instanceof _.VectorType) {\n                const elType = vecType.elementType;\n                for (let i = 0n; i < vecType.getNumElements(); i++) {\n                    op.addTypes([elType]);\n                }\n                return;\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.TensorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tensor');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tensor.expand_shape') {\n            // The new tensor.expand_shape format includes 'output_shape':\n            //   $src $reassociation `output_shape` custom<DynamicIndexList>(...) attr-dict `:` type($src) `into` type($result)\n            // Old format (deprecated):\n            //   $src $reassociation attr-dict `:` type($src) `into` type($result)\n            result.compatibility = true;\n            const unresolvedOperand = parser.parseOperand();\n            const reassociation = parser.parseAttribute();\n            result.addAttribute('reassociation', reassociation);\n            if (parser.parseOptionalKeyword('output_shape')) {\n                // New format: parse output_shape dynamic index list\n                this.parseDynamicIndexList(parser, result, ['$output_shape', '$static_output_shape']);\n            }\n            // Both formats: attr-dict `:` type($src) `into` type($result)\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            const srcType = parser.parseType();\n            parser.resolveOperands([unresolvedOperand], [srcType], result.operands);\n            parser.parseKeyword('into');\n            const resultType = parser.parseType();\n            result.addTypes([resultType]);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n};\n\n_.torch = {};\n\n_.torch.simpleTypes = new Set([\n    'int', 'float', 'bool', 'str', 'none', 'Device', 'Generator',\n    'qint8', 'quint8', 'qint16', 'qint32', 'quint4x2', 'quint2x4',\n    'LinearParams', 'number', 'any'\n]);\n\n_.torch.ListType = class extends _.Type {\n\n    constructor(containedType) {\n        super(null);\n        this.containedType = containedType;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const keyword = parser.parseOptionalKeyword();\n        let containedType = null;\n        if (keyword && _.torch.simpleTypes.has(keyword)) {\n            containedType = new _.Type(`!torch.${keyword}`);\n        } else if (keyword) {\n            let inner = `!torch.${keyword}`;\n            inner += parser.parseTypeParameters();\n            containedType = new _.Type(inner);\n        } else {\n            containedType = parser.parseType();\n        }\n        parser.parseGreater();\n        return new _.torch.ListType(containedType);\n    }\n\n    toString() {\n        return `!torch.list<${this.containedType}>`;\n    }\n};\n\n_.torch.ValueTensorType = class extends _.Type {\n\n    constructor(optionalSizes, optionalDtype, optionalSparsity) {\n        super(null);\n        this.optionalSizes = optionalSizes;\n        this.optionalDtype = optionalDtype;\n        this.optionalSparsity = optionalSparsity || null;\n    }\n\n    static parse(parser) {\n        if (!parser.parseOptionalLess()) {\n            return new _.torch.ValueTensorType(null, null);\n        }\n        let optionalSizes = null;\n        if (parser.parseOptionalStar()) {\n            // Unranked\n        } else {\n            parser.parseLSquare();\n            optionalSizes = [];\n            for (;;) {\n                if (parser.parseOptionalQuestion()) {\n                    optionalSizes.push(-1);\n                } else {\n                    const size = parser.parseOptionalInteger();\n                    if (size === null) {\n                        break;\n                    }\n                    optionalSizes.push(size);\n                }\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n            }\n            parser.parseRSquare();\n        }\n        parser.parseComma();\n        let optionalDtype = null;\n        if (!parser.parseOptionalKeyword('unk')) {\n            optionalDtype = parser.parseType();\n        }\n        let optionalSparsity = null;\n        if (parser.parseOptionalComma()) {\n            optionalSparsity = parser.parseAttribute();\n        }\n        parser.parseGreater();\n        return new _.torch.ValueTensorType(optionalSizes, optionalDtype, optionalSparsity);\n    }\n\n    toString() {\n        if (this.optionalSizes === null && this.optionalDtype === null) {\n            return '!torch.vtensor';\n        }\n        const sizeStr = this.optionalSizes === null ? '*' :\n            `[${this.optionalSizes.map((s) => s === -1 ? '?' : s.toString()).join(', ')}]`;\n        const dtypeStr = this.optionalDtype ? this.optionalDtype.toString() : 'unk';\n        if (this.optionalSparsity) {\n            return `!torch.vtensor<${sizeStr}, ${dtypeStr}, ${this.optionalSparsity}>`;\n        }\n        return `!torch.vtensor<${sizeStr}, ${dtypeStr}>`;\n    }\n};\n\n_.torch.TorchDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'torch');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (_.torch.simpleTypes.has(mnemonic)) {\n                return new _.Type(`!${dialect}.${mnemonic}`);\n            }\n            if (mnemonic === 'list') {\n                return _.torch.ListType.parse(parser);\n            }\n            if (mnemonic === 'vtensor') {\n                return _.torch.ValueTensorType.parse(parser);\n            }\n            if (mnemonic === 'tensor' || mnemonic === 'tuple' || mnemonic === 'union' || mnemonic === 'optional' || mnemonic === 'dict' || mnemonic.startsWith('nn.')) {\n                let type = `!${dialect}.${mnemonic}`;\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op.startsWith('torch.constant.')) {\n            result.label = 'torch.constant';\n        } else if (result.op.startsWith('torch.aten.') || result.op.startsWith('torch.prim.') || result.op.startsWith('torch.prims.') || result.op.startsWith('torch.torchvision.')) {\n            result.label = `${result.op.split('.')[1]}.${result.op.split('.')[2]}`;\n        }\n        if (result.op === 'torch.constant.int') {\n            const value = parser.parseOptionalInteger();\n            if (value !== null) {\n                result.addAttribute('value', value);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            result.addTypes([new _.Type('!torch.int')]);\n            return true;\n        }\n        if (result.op === 'torch.onnx.rotary_embedding') {\n            const unresolvedOperands = parser.parseOperandList();\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            if (parser.parseOptionalArrow()) {\n                const resultType = parser.parseType();\n                result.addTypes([resultType]);\n            }\n            return true;\n        }\n        if (result.op === 'torch.bind_symbolic_shape') {\n            const unresolved = parser.parseOperand();\n            parser.parseOptionalComma();\n            const shapeSymbols = parser.parseOperandList('square');\n            parser.parseOptionalComma();\n            const shapeExpr = parser.parseAttribute();\n            result.addAttribute('shape_expressions', shapeExpr.value || shapeExpr);\n            parser.parseOptionalAttrDict(result.attributes);\n            let type = null;\n            if (parser.parseOptionalColon()) {\n                type = parser.parseType();\n            }\n            parser.resolveOperand(unresolved, type, result.operands);\n            for (const sym of shapeSymbols) {\n                parser.resolveOperand(sym, null, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'torch.initialize.global_slots') {\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseLSquare();\n            const slotSymNames = [];\n            while (!parser.parseOptionalRSquare()) {\n                const slotSym = parser.parseOptionalSymbolName();\n                slotSymNames.push(slotSym ? `@${slotSym.value || slotSym}` : '');\n                parser.parseLParen();\n                const unresolved = parser.parseOperand();\n                parser.parseColon();\n                const type = parser.parseType();\n                parser.resolveOperand(unresolved, type, result.operands);\n                parser.parseRParen();\n            }\n            result.addAttribute('slotSymNames', slotSymNames);\n            return true;\n        }\n        const opInfo = result.name.getRegisteredInfo();\n        if (opInfo.metadata.hasCustomAssemblyFormat && !opInfo.metadata.assemblyFormats) {\n            return this.parseDefaultTorchOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseDefaultTorchOp(parser, result) {\n        const unresolvedOperands = parser.parseOperandList();\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            parser.resolveOperands(unresolvedOperands, parser.parseTypeList(), result.operands);\n        } else {\n            for (const operand of unresolvedOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n        }\n        if (parser.parseOptionalArrow()) {\n            // Handle both -> (type, type) and -> type, type syntaxes\n            if (parser.parseOptionalLParen()) {\n                const types = [];\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        types.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n                result.addTypes(types);\n            } else {\n                result.addTypes(parser.parseTypeList());\n            }\n        }\n        {\n            const region = result.addRegion();\n            if (parser.parseOptionalRegion(region)) {\n                if (parser.parseOptionalKeyword('else')) {\n                    const elseRegion = {};\n                    parser.parseOptionalRegion(elseRegion);\n                    result.regions.push(elseRegion);\n                }\n            }\n        }\n        return true;\n    }\n};\n\n_.IREEDialect = class extends _.Dialect {\n\n    constructor(operations, name) {\n        super(operations, name);\n        this.registerCustomDirective('DispatchEntryPoints', this.parseDispatchEntryPoints.bind(this));\n        this.registerCustomDirective('ShapedTiedResult', this.parseShapedTiedResult.bind(this));\n        this.registerCustomDirective('SymbolAlias', this.parseSymbolAlias.bind(this));\n        this.registerCustomDirective('TypeAlias', this.parseTypeAlias.bind(this));\n        this.registerCustomDirective('WorkgroupCountRegion', this.parseWorkgroupCountRegion.bind(this));\n        this.registerCustomDirective('ShapedFunctionType', this.parseShapedFunctionType.bind(this));\n    }\n\n    parseShapedFunctionType(parser, op, unresolvedArguments /*, otherArgs */) {\n        const operandTypes = [];\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const type = parser.parseType();\n                if (type) {\n                    operandTypes.push(type);\n                }\n                if (parser.parseOptionalLBrace()) {\n                    // Skip balanced braces content (dynamic dims)\n                    let depth = 1;\n                    while (depth > 0) {\n                        if (parser.parseOptionalLBrace()) {\n                            depth++;\n                        } else if (parser.parseOptionalRBrace()) {\n                            depth--;\n                        } else {\n                            parser.parseOperand();\n                            parser.parseOptionalComma();\n                        }\n                    }\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.parseArrow();\n        const operands = unresolvedArguments || op.operands;\n        const resultTypes = [];\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                parser.parseShapedResultList(operands, operandTypes, resultTypes, null, op.operands);\n                parser.parseRParen();\n            }\n        } else {\n            parser.parseShapedResultList(operands, operandTypes, resultTypes, null, op.operands);\n        }\n        op.addTypes(resultTypes);\n    }\n\n    parseDispatchEntryPoints(parser, op, attrName = 'entry_points') {\n        const entryPoints = [];\n\n        if (parser.parseOptionalLBrace()) {\n            do {\n                const sym = parser.parseOptionalSymbolName();\n                if (sym) {\n                    let symbol = `@${sym.value || sym}`;\n                    if (parser.parseOptionalColon()) {\n                        if (parser.parseOptionalColon()) {\n                            const nestedSym = parser.parseOptionalSymbolName();\n                            if (nestedSym) {\n                                symbol += `::@${nestedSym.value || nestedSym}`;\n                            }\n                        }\n                    }\n                    entryPoints.push(symbol);\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRBrace();\n        } else {\n            const sym = parser.parseOptionalSymbolName();\n            if (sym) {\n                let symbol = `@${sym.value || sym}`;\n                if (parser.parseOptionalColon()) {\n                    if (parser.parseOptionalColon()) {\n                        const nestedSym = parser.parseOptionalSymbolName();\n                        if (nestedSym) {\n                            symbol += `::@${nestedSym.value || nestedSym}`;\n                        }\n                    }\n                }\n                entryPoints.push(symbol);\n            }\n        }\n\n        const value = entryPoints.length === 1 ? entryPoints[0] : entryPoints;\n        op.addAttribute(attrName, value);\n    }\n\n    parseShapedTiedResult(parser, op /*, args */) {\n        // or just: type{dims}\n        const tiedOp = parser.parseOptionalOperand();\n        if (tiedOp) {\n            parser.parseKeyword('as');\n        }\n        const resultType = parser.parseType();\n        op.types.push(resultType); // Only add the type\n        if (parser.parseOptionalLBrace()) {\n            const indexType = new _.IndexType();\n            if (!parser.parseOptionalRBrace()) {\n                do {\n                    const dim = parser.parseOptionalOperand();\n                    if (dim) {\n                        parser.resolveOperand(dim, indexType, op.operands);\n                    } else {\n                        break;\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRBrace();\n            }\n        }\n    }\n\n    parseSymbolAlias(parser, op, symNameAttr, aliasAttr) {\n        const aliasSym = parser.parseOptionalSymbolName();\n        const alias = aliasSym ? `@${aliasSym.value || aliasSym}` : '';\n        let symName = alias;\n        if (parser.parseOptionalKeyword('as')) {\n            if (parser.parseOptionalLParen()) {\n                const str = parser.parseOptionalString();\n                if (str === null) {\n                    const sym = parser.parseOptionalSymbolName();\n                    if (sym) {\n                        symName = `@${sym.value || sym}`;\n                    }\n                } else {\n                    symName = str;\n                }\n                parser.parseOptionalRParen();\n            }\n        }\n        if (symNameAttr && aliasAttr) {\n            op.addAttribute(symNameAttr, symName);\n            op.addAttribute(aliasAttr, alias);\n        }\n    }\n\n    parseTypeAlias(parser, op, encodingAttrName, typeArg) {\n        const encodingType = parser.parseType();\n        let storageType = encodingType;\n        if (parser.parseOptionalKeyword('as')) {\n            storageType = parser.parseType();\n        }\n        if (encodingAttrName) {\n            op.addAttribute(encodingAttrName, encodingType);\n        }\n        if (!Array.isArray(typeArg)) {\n            throw new mlir.Error(`Invalid argument 'typeArg'.`);\n        }\n        if (typeArg.length > 0) {\n            typeArg[0] = storageType;\n        } else {\n            typeArg.push(storageType);\n        }\n    }\n\n    parseWorkgroupCountRegion(parser, result) {\n        if (!parser.parseOptionalKeyword('workgroups')) {\n            return;\n        }\n        const region = { blocks: [] };\n        const block = { arguments: [], operations: [] };\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const arg = parser.parseOperand();\n                    if (parser.parseOptionalColon()) {\n                        arg.type = parser.parseType();\n                    }\n                    block.arguments.push(arg);\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        if (parser.parseOptionalArrow()) {\n            parser.parseCommaSeparatedList('paren', () => {\n                parser.parseType();\n            });\n        }\n        if (parser.parseOptionalLBrace()) {\n            while (!parser.parseOptionalRBrace()) {\n                const innerOp = parser.parseOperation();\n                if (innerOp) {\n                    block.operations.push(innerOp);\n                }\n            }\n        }\n        region.blocks.push(block);\n        result.regions.push(region);\n    }\n};\n\n_.iree = {};\n\n_.iree.DispatchTensorType = class extends _.Type {\n\n    constructor(access, boundType) {\n        super(null);\n        this.access = access;\n        this.boundType = boundType;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const access = parser.parseKeyword();\n        parser.parseColon();\n        const boundType = parser.parseOptionalType();\n        if (boundType) {\n            parser.parseGreater();\n            return new _.iree.DispatchTensorType(access, boundType);\n        }\n        const dims = parser.parseDimensionList().dimensions;\n        const elementType = parser.parseType();\n        parser.parseGreater();\n        return new _.iree.DispatchTensorType(access, new _.RankedTensorType(dims, elementType));\n    }\n\n    toString() {\n        return `!flow.dispatch.tensor<${this.access}:${this.boundType}>`;\n    }\n};\n\n_.HALDialect = class extends _.IREEDialect {\n\n    constructor(operations) {\n        super(operations, 'hal');\n        this.simpleTypes = new Set(['allocator', 'buffer', 'buffer_view', 'channel', 'command_buffer', 'descriptor_set', 'descriptor_set_layout', 'device', 'event', 'executable', 'executable_layout', 'fence', 'file', 'semaphore']);\n        this.registerCustomAttribute('HAL_PipelineLayoutAttr', this.parsePipelineLayoutAttr.bind(this));\n        this.registerCustomDirective('ExportConditionRegion', this.parseExportConditionRegion.bind(this));\n        this.registerCustomDirective('TargetConditionObjects', this.parseTargetConditionObjects.bind(this));\n        this.registerCustomDirective('WorkgroupCountRegion', this.parseWorkgroupCountRegion.bind(this));\n        this.registerCustomDirective('DeviceQueueAffinityList', this.parseDeviceQueueAffinityList.bind(this));\n        this.registerCustomDirective('Bindings', this.parseBindingList.bind(this));\n        this.registerCustomDirective('BindingTable', this.parseBindingList.bind(this));\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (this.simpleTypes.has(mnemonic)) {\n                // Note: !hal.buffer{%size} syntax is handled by custom<SizeAwareType> directive,\n                // not by the type parser. The type parser just returns the base type.\n                return new _.Type(`!${dialect}.${mnemonic}`);\n            }\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'hal.tensor.cast') {\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                parser.resolveOperands(unresolvedOperands, [type], result.operands);\n            } else {\n                for (const operand of unresolvedOperands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n            result.addTypes(parser.parseOptionalArrowTypeList());\n            return true;\n        }\n        if (result.op === 'hal.constant') {\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const value = parser.parseAttribute();\n            result.addAttribute('value', value.value === undefined ? value : value.value);\n            result.addTypes(parser.parseOptionalColonTypeList());\n            return true;\n        }\n        if (result.op === 'hal.device.switch') {\n            if (parser.parseOptionalLess()) {\n                while (!parser.parseOptionalGreater()) {\n                    const operand = parser.parseOperand();\n                    let type = null;\n                    if (parser.parseOptionalColon()) {\n                        type = parser.parseType();\n                    }\n                    parser.resolveOperand(operand, type, result.operands);\n                    parser.parseOptionalComma();\n                }\n            }\n            if (parser.parseOptionalArrow() || parser.parseOptionalColon()) {\n                const resultType = parser.parseType();\n                result.types = [resultType];\n            }\n            for (;;) {\n                const caseAttr = parser.parseOptionalAttribute();\n                if (!caseAttr) {\n                    break;\n                }\n                const region = {};\n                region.caseAttribute = caseAttr;\n                const regionObj = {};\n                if (parser.parseOptionalRegion(regionObj)) {\n                    Object.assign(region, regionObj);\n                }\n                result.regions.push(region);\n                parser.parseOptionalComma();\n            }\n            return true;\n        }\n        if (result.op === 'hal.executable.constant.block') {\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const arg = parser.parseOptionalOperand();\n                        if (arg) {\n                            parser.parseColon();\n                            const type = parser.parseType();\n                            parser.resolveOperand(arg, type, result.operands);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            if (parser.parseOptionalArrow()) {\n                const resultTypes = [];\n                const resultAttrs = [];\n                parser.parseFunctionResultList(resultTypes, resultAttrs);\n                result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType([], resultTypes)));\n            }\n            if (parser.parseOptionalKeyword('as')) {\n                if (parser.parseOptionalLParen()) {\n                    const keys = [];\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            const str = parser.parseOptionalString();\n                            if (str !== null) {\n                                keys.push(str);\n                            }\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                    result.addAttribute('keys', keys);\n                } else {\n                    const key = parser.parseOptionalString();\n                    if (key !== null) {\n                        result.addAttribute('keys', [key]);\n                    }\n                }\n            }\n            {\n                const region = result.addRegion();\n                parser.parseOptionalRegion(region);\n            }\n            return true;\n        }\n        // Handle hal.executable.create with both old (layouts) and new (affinity) syntax\n        if (result.op === 'hal.executable.create') {\n            for (;;) {\n                const paramName = parser.parseOptionalKeyword();\n                if (!paramName) {\n                    break;\n                }\n                const normalizedName = paramName === 'layouts' ? 'affinity' : paramName;\n                this.parseParamValue(parser, result,normalizedName);\n            }\n            result.addTypes(parser.parseOptionalColonTypeList());\n            return true;\n        }\n        if (result.op === 'hal.allocator.allocate') {\n            this.parseAngleBracketOperand(parser, result);\n            this.parseNamedAttr(parser, result,'affinity');\n            this.parseNamedAttr(parser, result,'type');\n            this.parseNamedAttr(parser, result,'usage');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            if (parser.parseOptionalLBrace()) {\n                parser.parseOptionalOperand();\n                parser.parseRBrace();\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.allocator.compute_size') {\n            this.parseAngleBracketOperand(parser, result);\n            this.parseNamedAttr(parser, result,'shape');\n            this.parseNamedAttr(parser, result,'type');\n            this.parseNamedAttr(parser, result,'encoding');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.buffer_view.create') {\n            if (parser.parseOptionalKeyword('buffer')) {\n                parser.parseLParen();\n                const operand = parser.parseOperand();\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.parseRParen();\n                parser.resolveOperand(operand, type, result.operands);\n                if (parser.parseOptionalLSquare()) {\n                    if (!parser.parseOptionalRSquare()) {\n                        do {\n                            const op = parser.parseOptionalOperand();\n                            if (op) {\n                                parser.resolveOperand(op, null, result.operands);\n                            }\n                        } while (parser.parseOptionalComma());\n                        parser.parseRSquare();\n                    }\n                }\n            }\n            this.parseNamedAttr(parser, result,'shape');\n            this.parseNamedAttr(parser, result,'type');\n            this.parseNamedAttr(parser, result,'encoding');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.command_buffer.begin' || result.op === 'hal.command_buffer.end' || result.op === 'hal.command_buffer.device') {\n            this.parseAngleBracketOperand(parser, result);\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.command_buffer.create') {\n            this.parseNamedAttr(parser, result,'device');\n            this.parseNamedAttr(parser, result,'mode');\n            this.parseNamedAttr(parser, result,'categories');\n            this.parseNamedAttr(parser, result,'affinity');\n            this.parseNamedAttr(parser, result,'bindings');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.command_buffer.dispatch') {\n            this.parseAngleBracketOperand(parser, result);\n            if (parser.parseOptionalKeyword('target')) {\n                parser.parseLParen();\n                const operand = parser.parseOperand();\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.parseRParen();\n                parser.resolveOperand(operand, type, result.operands);\n                if (parser.parseOptionalLSquare()) {\n                    parser.parseOptionalOperand();\n                    parser.parseOptionalAttribute();\n                    parser.parseRSquare();\n                }\n            }\n            this.parseNamedAttr(parser, result,'workgroups');\n            this.parseNamedAttr(parser, result,'constants');\n            if (parser.parseOptionalKeyword('bindings')) {\n                parser.parseLParen();\n                this.parseBindings(parser, result);\n                parser.parseRParen();\n            }\n            this.parseNamedAttr(parser, result,'flags');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.command_buffer.dispatch.symbol') {\n            this.parseAngleBracketOperand(parser, result);\n            this.parseNamedAttr(parser, result,'target');\n            this.parseNamedAttr(parser, result,'workgroups');\n            this.parseNamedAttr(parser, result,'constants');\n            if (parser.parseOptionalKeyword('bindings')) {\n                parser.parseLParen();\n                this.parseBindings(parser, result);\n                parser.parseRParen();\n            }\n            this.parseNamedAttr(parser, result,'flags');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.command_buffer.push_descriptor_set') {\n            this.parseAngleBracketOperand(parser, result);\n            if (parser.parseOptionalKeyword('layout')) {\n                parser.parseLParen();\n                const operand = parser.parseOperand();\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.parseRParen();\n                parser.resolveOperand(operand, type, result.operands);\n                if (parser.parseOptionalLSquare()) {\n                    parser.parseOptionalOperand();\n                    parser.parseRSquare();\n                }\n            }\n            if (parser.parseOptionalKeyword('bindings')) {\n                parser.parseLParen();\n                this.parseBindings(parser, result);\n                parser.parseRParen();\n            }\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.descriptor_set_layout.create' || result.op === 'hal.executable_layout.create' || result.op === 'hal.executable_layout.lookup') {\n            for (;;) {\n                const paramName = parser.parseOptionalKeyword();\n                if (!paramName) {\n                    break;\n                }\n                this.parseParamValue(parser, result,paramName);\n            }\n            result.addTypes(parser.parseOptionalColonTypeList());\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.device.query') {\n            this.parseAngleBracketOperand(parser, result);\n            this.parseNamedAttr(parser, result,'key');\n            result.addTypes(parser.parseOptionalColonTypeList());\n            if (parser.parseOptionalEqual()) {\n                const value = parser.parseAttribute();\n                result.addAttribute('default', value.value);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'hal.executable.condition' || result.op === 'hal.executable.constant.block') {\n            const sig = parser.parseFunctionSignatureWithArguments(false);\n            const argTypes = sig.arguments.map((a) => a.type);\n            const type = new _.FunctionType(argTypes, sig.resultTypes);\n            result.addAttribute('function_type', new _.TypeAttrOf(type));\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            {\n                const region = result.addRegion();\n                parser.parseOptionalRegion(region, sig.arguments);\n            }\n            return true;\n        }\n        // Handle operations with visibility + symbol (similar to flow dialect)\n        if (result.op === 'hal.executable' || result.op === 'hal.executable.source' || result.op === 'hal.interface' || result.op === 'hal.executable.binary') {\n            this.parseSymbolVisibility(parser, result);\n            const sym = parser.parseOptionalSymbolName();\n            if (sym) {\n                result.addAttribute('sym_name', sym.value || sym);\n            }\n            if (parser.parseOptionalKeyword('attributes')) {\n                parser.parseOptionalAttrDict(result.attributes);\n            }\n            {\n                const region = result.addRegion();\n                parser.parseOptionalRegion(region);\n            }\n            return true;\n        }\n        const subspanSym = result.op === 'hal.interface.binding.subspan' ? parser.parseOptionalSymbolName() : null;\n        if (subspanSym) {\n            // Old syntax - parse symbol reference and bracket expression\n            result.addAttribute('layout', `@${subspanSym.value || subspanSym}`);\n            const unresolvedOperands = [];\n            const indexType = new _.IndexType();\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const operand = parser.parseOptionalOperand();\n                        if (operand) {\n                            unresolvedOperands.push(operand);\n                        } else {\n                            // Skip non-operand tokens (like ::@nested)\n                            parser.parseAttribute();\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n            }\n            parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), result.operands);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (type) {\n                    result.addTypes([type]);\n                }\n                if (parser.parseOptionalLBrace()) {\n                    const dynamicDimOperands = [];\n                    if (!parser.parseOptionalRBrace()) {\n                        do {\n                            const dimOperand = parser.parseOperand();\n                            dynamicDimOperands.push(dimOperand);\n                        } while (parser.parseOptionalComma());\n                        parser.parseRBrace();\n                    }\n                    parser.resolveOperands(dynamicDimOperands, dynamicDimOperands.map(() => indexType), result.operands);\n                }\n            }\n            return true;\n        }\n        // Old IREE hal.interface.binding: visibility @sym, key=value, key=\"string\", ...\n        if (result.op === 'hal.interface.binding') {\n            this.parseSymbolVisibility(parser, result);\n            const sym = parser.parseOptionalSymbolName();\n            if (sym) {\n                result.addAttribute('sym_name', sym.value || sym);\n            }\n            while (parser.parseOptionalComma()) {\n                const key = parser.parseKeyword();\n                parser.parseEqual();\n                const value = parser.parseOptionalAttribute();\n                if (value === null) {\n                    const str = parser.parseOptionalString();\n                    result.addAttribute(key, str === null ? parser.parseKeyword() : str);\n                } else {\n                    result.addAttribute(key, value.value === undefined ? value : value.value);\n                }\n            }\n            return true;\n        }\n        // hal.executable.variant:\n        // New: @sym target(#attr) objects(...)? sources(...)? attr-dict-with-keyword { body }\n        // Old: @sym, target = #attr attributes {...} { body }\n        if (result.op === 'hal.executable.variant') {\n            this.parseSymbolVisibility(parser, result);\n            const sym = parser.parseOptionalSymbolName();\n            if (sym) {\n                result.addAttribute('sym_name', sym.value || sym);\n            }\n            if (parser.parseOptionalComma()) {\n                // Old syntax: , target = #attr\n                const key = parser.parseKeyword();\n                parser.parseEqual();\n                const value = parser.parseAttribute();\n                result.addAttribute(key, value.value === undefined ? value : value.value);\n            } else if (parser.parseOptionalKeyword('target')) {\n                // New syntax: target(#attr)\n                parser.parseLParen();\n                const value = parser.parseAttribute();\n                result.addAttribute('target', value.value === undefined ? value : value.value);\n                parser.parseRParen();\n                if (parser.parseOptionalKeyword('objects')) {\n                    parser.parseLParen();\n                    const objects = parser.parseAttribute();\n                    result.addAttribute('objects', objects.value === undefined ? objects : objects.value);\n                    parser.parseRParen();\n                }\n                if (parser.parseOptionalKeyword('sources')) {\n                    parser.parseLParen();\n                    const sources = parser.parseAttribute();\n                    result.addAttribute('sources', sources.value === undefined ? sources : sources.value);\n                    parser.parseRParen();\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const region = result.addRegion();\n            parser.parseOptionalRegion(region);\n            return true;\n        }\n        // Old IREE hal.executable.entry_point: visibility @sym attributes {...} { optional region }\n        if (result.op === 'hal.executable.entry_point') {\n            this.parseSymbolVisibility(parser, result);\n            const sym = parser.parseOptionalSymbolName();\n            if (sym) {\n                result.addAttribute('sym_name', sym.value || sym);\n            }\n            if (parser.parseOptionalKeyword('attributes')) {\n                parser.parseOptionalAttrDict(result.attributes);\n            }\n            const region = result.addRegion();\n            parser.parseOptionalRegion(region);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parsePipelineLayoutAttr(parser) {\n        // HAL_PipelineLayoutAttr format: <constants = N, bindings = [...], flags = ...>\n        // Try parseAttribute first (handles <...> syntax), fall back to optional\n        const attr = parser.parseOptionalAttribute();\n        return attr;\n    }\n\n    // Parses [(%op : type)[off, sz], ...] or [%idx = (%op : type)[off, sz], ...]\n    parseBindings(parser, result) {\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                if (parser.parseOptionalOperand()) {\n                    parser.parseEqual();\n                }\n                parser.parseLParen();\n                const bindOp = parser.parseOperand();\n                let bindType = null;\n                if (parser.parseOptionalColon()) {\n                    bindType = parser.parseType();\n                }\n                parser.parseRParen();\n                parser.resolveOperand(bindOp, bindType, result.operands);\n                if (parser.parseOptionalLSquare()) {\n                    if (!parser.parseOptionalRSquare()) {\n                        do {\n                            const sizeOp = parser.parseOperand();\n                            parser.resolveOperand(sizeOp, null, result.operands);\n                        } while (parser.parseOptionalComma());\n                        parser.parseRSquare();\n                    }\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n    }\n\n    // Parses <%operand : type> from old IREE HAL format.\n    parseAngleBracketOperand(parser, result) {\n        if (parser.parseOptionalLess()) {\n            const operand = parser.parseOperand();\n            let type = null;\n            if (parser.parseOptionalColon()) {\n                type = parser.parseType();\n            }\n            parser.resolveOperand(operand, type, result.operands);\n            parser.parseGreater();\n        }\n    }\n\n    parseNamedAttr(parser, result, name) {\n        if (parser.parseOptionalKeyword(name)) {\n            this.parseParamValue(parser, result, name);\n        }\n    }\n\n    parseParamValue(parser, result, name) {\n        parser.parseLParen();\n        if (name === 'key') {\n            const category = parser.parseString();\n            result.addAttribute('category', category);\n            parser.parseColon();\n            parser.parseColon();\n            const key = parser.parseString();\n            result.addAttribute(name, key);\n        } else {\n            const operand = parser.parseOptionalOperand();\n            if (operand) {\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.resolveOperand(operand, type, result.operands);\n                while (parser.parseOptionalComma()) {\n                    const nextOp = parser.parseOperand();\n                    let nextType = null;\n                    if (parser.parseOptionalColon()) {\n                        nextType = parser.parseType();\n                    }\n                    parser.parseOptionalEllipsis();\n                    parser.resolveOperand(nextOp, nextType, result.operands);\n                }\n            } else if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    const firstOp = parser.parseOptionalOperand();\n                    if (firstOp) {\n                        const ops = [firstOp];\n                        while (parser.parseOptionalComma()) {\n                            ops.push(parser.parseOperand());\n                        }\n                        const indexType = new _.IndexType();\n                        parser.resolveOperands(ops, ops.map(() => indexType), result.operands);\n                    } else {\n                        const value = parser.parseAttribute();\n                        result.addAttribute(name, value);\n                        while (parser.parseOptionalComma()) {\n                            parser.parseAttribute();\n                        }\n                    }\n                    parser.parseRSquare();\n                }\n            } else {\n                const value = parser.parseAttribute();\n                result.addAttribute(name, value);\n            }\n        }\n        parser.parseRParen();\n    }\n\n    parseExportConditionRegion(parser, result) {\n        parser.parseLParen();\n        const regionArgs = [];\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const arg = parser.parseOperand();\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                regionArgs.push({ value: arg, type });\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.parseArrow();\n        parser.parseType();\n        const region = { arguments: regionArgs };\n        parser.parseRegion(region);\n        result.regions.push(region);\n    }\n\n    parseTargetConditionObjects(parser, result) {\n        // #target if(...) { region } ordinal(N) = [objects], ...\n        do {\n            const attr = parser.parseOptionalAttribute();\n            if (attr) {\n                // hash_identifier attribute consumed\n            }\n            if (parser.parseOptionalKeyword('if')) {\n                this.parseTargetConditionRegion(parser, result);\n            }\n            if (parser.parseOptionalKeyword('ordinal')) {\n                parser.parseCommaSeparatedList('paren', () => {\n                    parser.parseInteger();\n                });\n            }\n            if (parser.parseOptionalEqual()) {\n                if (parser.parseOptionalLSquare()) {\n                    // Skip balanced bracket content\n                    let depth = 1;\n                    while (depth > 0) {\n                        if (parser.parseOptionalLSquare()) {\n                            depth++;\n                        } else if (parser.parseOptionalRSquare()) {\n                            depth--;\n                        } else {\n                            parser.parseAttribute();\n                            parser.parseOptionalComma();\n                        }\n                    }\n                }\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseTargetConditionRegion(parser, result) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                parser.parseOperand();\n                if (parser.parseOptionalColon()) {\n                    parser.parseType();\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalArrow()) {\n            parser.parseType();\n        }\n        {\n            const region = result.addRegion();\n            parser.parseOptionalRegion(region);\n        }\n    }\n\n    parseWorkgroupCountRegion(parser, result) {\n        // (args) -> (index, index, index) { region }\n        const region = { blocks: [] };\n        const block = { arguments: [], operations: [] };\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const arg = parser.parseOperand();\n                    if (parser.parseOptionalColon()) {\n                        arg.type = parser.parseType();\n                    }\n                    block.arguments.push(arg);\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        if (parser.parseOptionalArrow()) {\n            parser.parseCommaSeparatedList('paren', () => {\n                parser.parseType();\n            });\n        }\n        region.blocks.push(block);\n        const regionObj = {};\n        if (parser.parseOptionalRegion(regionObj)) {\n            Object.assign(region, regionObj);\n        }\n        result.regions.push(region);\n    }\n\n    parseDeviceQueueAffinityList(parser, result) {\n        parser.parseLSquare();\n        do {\n            parser.parseLParen();\n            const device = parser.parseOperand();\n            parser.parseComma();\n            const queueAffinity = parser.parseOperand();\n            parser.parseColon();\n            const deviceType = parser.parseType();\n            parser.parseComma();\n            const queueAffinityType = parser.parseType();\n            parser.parseRParen();\n            parser.resolveOperand(device, deviceType, result.operands);\n            parser.resolveOperand(queueAffinity, queueAffinityType, result.operands);\n        } while (parser.parseOptionalComma());\n        parser.parseRSquare();\n    }\n\n    parseBindingList(parser, result) {\n        do {\n            parser.parseLParen();\n            const buffer = parser.parseOperand();\n            parser.parseColon();\n            const bufferType = parser.parseType();\n            parser.parseRParen();\n            parser.parseLSquare();\n            const bufferOffset = parser.parseOperand();\n            parser.parseComma();\n            const bufferLength = parser.parseOperand();\n            parser.parseRSquare();\n            parser.resolveOperand(buffer, bufferType, result.operands);\n            parser.resolveOperand(bufferOffset, null, result.operands);\n            parser.resolveOperand(bufferLength, null, result.operands);\n        } while (parser.parseOptionalComma());\n    }\n};\n\n_.IREECodegenDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'iree_codegen');\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'iree_codegen.inner_tiled') {\n            const outputsEntry = vars.get('outputs');\n            if (outputsEntry.types.length > 0) {\n                op.addTypes(outputsEntry.types);\n                return;\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'iree_codegen.workgroup_count_hint') {\n            const staticSizes = [];\n            const unresolvedSizes = [];\n            parser.parseOptionalKeyword('sizes');\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const operand = parser.parseOptionalOperand();\n                    if (operand) {\n                        unresolvedSizes.push(operand);\n                        staticSizes.push(-9223372036854775808n);\n                    } else {\n                        staticSizes.push(parser.parseInteger('int64'));\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            // Resolve operands with index type (sizes are typically index)\n            const indexType = new _.IndexType();\n            for (const unresolved of unresolvedSizes) {\n                parser.resolveOperand(unresolved, indexType, result.operands);\n            }\n            if (staticSizes.length > 0) {\n                result.addAttribute('static_sizes', staticSizes);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.HALLoaderDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'hal_loader');\n        this.registerCustomDirective('DispatchBindings', this.parseDispatchBindings.bind(this));\n    }\n\n    parseDispatchBindings(parser, result) {\n        const unresolvedBuffers = [];\n        const bufferTypes = [];\n        const unresolvedOffsets = [];\n        const unresolvedLengths = [];\n        do {\n            parser.parseLParen();\n            unresolvedBuffers.push(parser.parseOperand());\n            parser.parseColon();\n            bufferTypes.push(parser.parseType());\n            parser.parseRParen();\n            parser.parseLSquare();\n            unresolvedOffsets.push(parser.parseOperand());\n            parser.parseComma();\n            unresolvedLengths.push(parser.parseOperand());\n            parser.parseRSquare();\n        } while (parser.parseOptionalComma());\n        const indexType = new _.IndexType();\n        for (let i = 0; i < unresolvedBuffers.length; i++) {\n            parser.resolveOperand(unresolvedBuffers[i], bufferTypes[i], result.operands);\n        }\n        for (const unresolved of unresolvedOffsets) {\n            parser.resolveOperand(unresolved, indexType, result.operands);\n        }\n        for (const unresolved of unresolvedLengths) {\n            parser.resolveOperand(unresolved, indexType, result.operands);\n        }\n    }\n};\n\n_.UtilDialect = class extends _.IREEDialect {\n\n    constructor(operations) {\n        super(operations, 'util');\n        this.registerCustomDirective('OperandTypeList', this.parseOperandTypeList.bind(this));\n        this.registerCustomDirective('TiedFunctionResultList', this.parseTiedFunctionResultList.bind(this));\n        this.registerCustomDirective('TypeAlias', this.parseTypeAlias.bind(this));\n        this.registerCustomDirective('TypedValueList', this.parseTypedValueList.bind(this));\n        this.registerCustomDirective('RangeList', this.parseRangeList.bind(this));\n        this.registerCustomDirective('ListTypeGet', this.parseListTypeGet.bind(this));\n        this.registerCustomDirective('ListTypeSet', this.parseListTypeSet.bind(this));\n        this.registerCustomDirective('ValueTypeList', this.parseValueTypeList.bind(this));\n        this.simpleTypes = new Set(['buffer', 'list', 'object', 'ptr']);\n    }\n\n    parseTypeAlias(parser /*, op, args */) {\n        parser.parseType();\n        if (parser.parseOptionalKeyword('as')) {\n            parser.parseType();\n        }\n    }\n\n    parseTypedValueList(parser, op /*, args */) {\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            const unresolvedValues = [];\n            do {\n                unresolvedValues.push(parser.parseOperand());\n            } while (parser.parseOptionalComma());\n            for (const unresolved of unresolvedValues) {\n                parser.resolveOperand(unresolved, null, op.operands);\n            }\n            parser.parseRSquare();\n        }\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (this.simpleTypes.has(mnemonic)) {\n                if (mnemonic === 'list') {\n                    return _.util.ListType.parse(parser);\n                }\n                let type = `!${dialect}.${mnemonic}`;\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n\n    parseOperandTypeList(parser, op /*, args */) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            let index = 0;\n            do {\n                const type = parser.parseType();\n                if (index < op.operands.length) {\n                    op.operands[index].type = type;\n                }\n                index++;\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n    }\n\n    parseTiedFunctionResultList(parser, op /*, args */) {\n        const parseTiedResultOrType = () => {\n            const tiedRef = parser.parseOptionalOperand();\n            if (tiedRef) {\n                let tiedType = null;\n                for (let i = 0; i < op.operands.length; i++) {\n                    if (op.operands[i].value === tiedRef) {\n                        tiedType = op.operands[i].type;\n                        break;\n                    }\n                }\n                if (parser.parseOptionalKeyword('as')) {\n                    return parser.parseType();\n                }\n                if (tiedType) {\n                    return tiedType;\n                }\n                return new _.Type('!util.unknown');\n            }\n            return parser.parseType();\n        };\n        if (parser.parseOptionalLParen()) {\n            let index = 0;\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const type = parseTiedResultOrType();\n                    if (index < op.types.length) {\n                        op.types[index] = type;\n                    } else {\n                        op.addTypes([type]);\n                    }\n                    index++;\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        } else {\n            let index = 0;\n            do {\n                const type = parseTiedResultOrType();\n                if (index < op.types.length) {\n                    op.types[index] = type;\n                } else {\n                    op.addTypes([type]);\n                }\n                index++;\n            } while (parser.parseOptionalComma());\n        }\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'util.assume.int') {\n            return this.parseAssumeIntOp(parser, result);\n        }\n        if (result.op === 'util.initializer') {\n            if (parser.parseOptionalKeyword('attributes')) {\n                parser.parseOptionalAttrDict(result.attributes);\n            }\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'util.func') {\n            this.parseUtilFuncOp(parser, result);\n            return true;\n        }\n        if (result.op === 'util.unfoldable_constant') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const value = parser.parseAttribute();\n            result.addAttribute('value', value);\n            // Use type from attribute if present, otherwise parse explicit type\n            if (value && value.type) {\n                result.addTypes([value.type]);\n            } else if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addTypes([type]);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseUtilFuncOp(parser, result) {\n        parser.parseOptionalVisibilityKeyword(result.attributes);\n        parser.parseSymbolName('sym_name', result.attributes);\n        const argResult = parser.parseFunctionArgumentList(false);\n        const resultTypes = [];\n        const resultAttrs = [];\n        const tiedOperandIndices = [];\n        // Parse result list which may contain:\n        // - Regular type: tensor<...>\n        // - Tied reference: %arg1 (inherits type from argument)\n        // - Tied with type override: %arg2 as tensor<...>\n        const parseTiedResultOrType = () => {\n            const tiedRef = parser.parseOptionalOperand();\n            if (tiedRef) {\n                let tiedIndex = -1;\n                for (let i = 0; i < argResult.arguments.length; i++) {\n                    if (argResult.arguments[i].value === tiedRef) {\n                        tiedIndex = i;\n                        break;\n                    }\n                }\n                tiedOperandIndices.push(tiedIndex);\n                // Check for 'as type' override\n                if (parser.parseOptionalKeyword('as')) {\n                    return parser.parseType();\n                }\n                if (tiedIndex >= 0 && argResult.arguments[tiedIndex].type) {\n                    return argResult.arguments[tiedIndex].type;\n                }\n                return new _.Type('!util.unknown');\n            }\n            tiedOperandIndices.push(-1);\n            return parser.parseType();\n        };\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        resultTypes.push(parseTiedResultOrType());\n                        const attrList = new Map();\n                        parser.parseOptionalAttrDict(attrList);\n                        resultAttrs.push(attrList.size > 0 ? attrList : null);\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            } else {\n                do {\n                    resultTypes.push(parseTiedResultOrType());\n                    resultAttrs.push(null);\n                } while (parser.parseOptionalComma());\n            }\n        }\n        const argTypes = argResult.arguments.filter((a) => a.value !== '...').map((a) => a.type);\n        const type = new _.FunctionType(argTypes, resultTypes);\n        result.addAttribute('function_type', new _.TypeAttrOf(type));\n        if (tiedOperandIndices.some((i) => i >= 0)) {\n            result.addAttribute('tied_operands', tiedOperandIndices);\n        }\n        if (resultAttrs.some((a) => a !== null)) {\n            result.addAttribute('res_attrs', resultAttrs);\n        }\n        const argAttrs = argResult.arguments.filter((a) => a.value !== '...').map((a) => a.attrs || null);\n        if (argAttrs.some((a) => a !== null)) {\n            result.addAttribute('arg_attrs', argAttrs);\n        }\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        parser.parseOptionalRegion(result.addRegion(), argResult.arguments);\n    }\n\n    parseAssumeIntOp(parser, result) {\n        const allOperandAssumptions = [];\n        const unresolvedOperands = [];\n\n        do {\n            const operand = parser.parseOperand();\n            unresolvedOperands.push(operand);\n            const operandAssumptions = [];\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const assumption = this.parseIntAssumptionAttr(parser);\n                        operandAssumptions.push(assumption);\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n            } else if (parser.parseOptionalLess()) {\n                // parseIntAssumptionAttr will call parseLess() but we already consumed it\n                // Re-structure: parse content between < and >\n                const assumption = {};\n                if (!parser.parseOptionalGreater()) {\n                    do {\n                        const key = parser.parseKeyword();\n                        parser.parseEqual();\n                        assumption[key] = parser.parseInteger();\n                    } while (parser.parseOptionalComma());\n                    parser.parseGreater();\n                }\n                operandAssumptions.push(assumption);\n            }\n            allOperandAssumptions.push(operandAssumptions);\n        } while (parser.parseOptionalComma());\n        parser.parseColon();\n        const parsedOperandTypes = [];\n        do {\n            const type = parser.parseType();\n            parsedOperandTypes.push(type);\n        } while (parser.parseOptionalComma());\n        parser.resolveOperands(unresolvedOperands, parsedOperandTypes, result.operands);\n        for (const type of parsedOperandTypes) {\n            result.addTypes([type || null]);\n        }\n\n        result.addAttribute('assumptions', allOperandAssumptions);\n\n        parser.parseOptionalAttrDict(result.attributes);\n\n        return true;\n    }\n\n    parseIntAssumptionAttr(parser) {\n        parser.parseLess();\n        const assumption = {};\n        if (!parser.parseOptionalGreater()) {\n            do {\n                const key = parser.parseKeyword();\n                if (!parser.parseOptionalEqual()) {\n                    throw new mlir.Error(`Expected '=' after ${key} ${parser.getCurrentLocation()}`);\n                }\n                assumption[key] = parser.parseInteger();\n            } while (parser.parseOptionalComma());\n            parser.parseGreater();\n        }\n        return assumption;\n    }\n\n    parseRangeList(parser, op, offsetsAttr) {\n        const unresolvedOffsets = [];\n        const unresolvedLengths = [];\n        do {\n            parser.parseLSquare();\n            unresolvedOffsets.push(parser.parseOperand());\n            parser.parseKeyword('for');\n            unresolvedLengths.push(parser.parseOperand());\n            parser.parseRSquare();\n        } while (parser.parseOptionalComma());\n        const indexType = new _.IndexType();\n        for (const unresolved of unresolvedOffsets) {\n            parser.resolveOperand(unresolved, indexType, op.operands);\n        }\n        for (const unresolved of unresolvedLengths) {\n            parser.resolveOperand(unresolved, indexType, op.operands);\n        }\n        if (offsetsAttr) {\n            op.addAttribute(`${offsetsAttr}_count`, unresolvedOffsets.length);\n        }\n    }\n\n    parseListTypeGet(parser, op, listTypeArr, resultTypeArr) {\n        const listType = parser.parseType();\n        let elementType = null;\n        if (parser.parseOptionalArrow()) {\n            elementType = parser.parseType();\n        } else if (listType instanceof _.util.ListType) {\n            elementType = listType.elementType;\n        }\n        if (Array.isArray(listTypeArr) && listType) {\n            listTypeArr.push(listType);\n        }\n        if (Array.isArray(resultTypeArr) && elementType) {\n            resultTypeArr.push(elementType);\n        }\n    }\n\n    parseListTypeSet(parser, op, listTypeArr, valueTypeArr) {\n        const leadingType = parser.parseType();\n        let listType = null;\n        let elementType = null;\n        if (parser.parseOptionalArrow()) {\n            elementType = leadingType;\n            listType = parser.parseType();\n        } else if (leadingType instanceof _.util.ListType) {\n            listType = leadingType;\n            elementType = leadingType.elementType;\n        }\n        if (Array.isArray(listTypeArr) && listType) {\n            listTypeArr.push(listType);\n        }\n        if (Array.isArray(valueTypeArr) && elementType) {\n            valueTypeArr.push(elementType);\n        }\n    }\n\n    parseValueTypeList(parser, result) {\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            const unresolvedOperands = [];\n            const types = [];\n            do {\n                unresolvedOperands.push(parser.parseOperand());\n                parser.parseColon();\n                types.push(parser.parseType());\n            } while (parser.parseOptionalComma());\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            parser.parseRSquare();\n        }\n    }\n};\n\n_.FlowDialect = class extends _.IREEDialect {\n\n    constructor(operations) {\n        super(operations, 'flow');\n        this.registerCustomDirective('DispatchWorkgroupBody', this.parseDispatchWorkgroupBody.bind(this));\n        this.registerCustomDirective('DispatchWorkgroupsCountRegion', this.parseDispatchWorkgroupsCountRegion.bind(this));\n        this.registerCustomDirective('ShapedFunctionType', this.parseShapedFunctionType.bind(this));\n        this.registerCustomDirective('ShapedOperandList', this.parseShapedOperandList.bind(this));\n        this.registerCustomDirective('ParameterReference', this.parseParameterReference.bind(this));\n    }\n\n    parseParameterReference(parser, op, scopeOperands, keyOperands) {\n        const firstOperand = parser.parseOperand();\n        if (parser.parseOptionalColon()) {\n            parser.parseColon();\n            const keyOperand = parser.parseOperand();\n            scopeOperands.push(firstOperand);\n            keyOperands.push(keyOperand);\n        } else {\n            keyOperands.push(firstOperand);\n        }\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (mnemonic === 'channel') {\n                return new _.Type(`!${dialect}.${mnemonic}`);\n            }\n            if (mnemonic === 'dispatch.tensor') {\n                return _.iree.DispatchTensorType.parse(parser);\n            }\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'flow.ex.stream.fragment') {\n            return this.parseDispatchWorkgroupsOp(parser, result);\n        }\n        if (result.op === 'flow.dispatch.region') {\n            return this.parseDispatchRegionOp(parser, result);\n        }\n        if (result.op === 'flow.dispatch.tensor.load' || result.op === 'flow.dispatch.tensor.store') {\n            return this.parseTensorLoadStoreOp(parser, result);\n        }\n        // Handle operations with visibility + symbol that aren't in schema or need manual parsing\n        if (result.op === 'flow.dispatch.entry') {\n            this.parseSymbolVisibility(parser, result);\n            const symName = parser.parseOptionalSymbolName();\n            if (symName !== null) {\n                result.addAttribute('sym_name', symName);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'flow.func') {\n            return this.parseFlowFuncOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseFlowFuncOp(parser, result) {\n        parser.parseOptionalVisibilityKeyword(result.attributes);\n        parser.parseSymbolName('sym_name', result.attributes);\n        const argResult = parser.parseFunctionArgumentList();\n        const inputs = argResult.arguments.map((a) => a.type);\n        const results = [];\n        if (parser.parseOptionalArrow()) {\n            const hasParens = parser.parseOptionalLParen();\n            if (!hasParens || !parser.parseOptionalRParen()) {\n                do {\n                    const tiedOp = parser.parseOptionalOperand();\n                    if (tiedOp) {\n                        if (parser.parseOptionalKeyword('as')) {\n                            const resultType = parser.parseType();\n                            results.push(resultType);\n                        } else {\n                            results.push(new _.Type('tied'));\n                        }\n                    } else {\n                        const resultType = parser.parseType();\n                        results.push(resultType);\n                    }\n                    if (parser.parseOptionalLBrace()) {\n                        const resultAttrs = new Map();\n                        if (!parser.parseOptionalRBrace()) {\n                            do {\n                                const key = parser.parseAttribute();\n                                resultAttrs.set(String(key.value || key), true);\n                            } while (parser.parseOptionalComma());\n                            parser.parseRBrace();\n                        }\n                    }\n                    if (!hasParens) {\n                        break;\n                    }\n                } while (parser.parseOptionalComma());\n                if (hasParens) {\n                    parser.parseRParen();\n                }\n            }\n        }\n        result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        parser.parseOptionalRegion(result.addRegion());\n        return true;\n    }\n\n    parseDispatchRegionOp(parser, result) {\n        const workloadOperands = parser.parseOperandList('optionalSquare');\n        for (const workload of workloadOperands) {\n            parser.resolveOperand(workload, null, result.operands);\n        }\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    const type = parser.parseType();\n                    if (parser.parseOptionalLBrace()) {\n                        while (!parser.parseOptionalRBrace()) {\n                            const tied = parser.parseOperand();\n                            parser.resolveOperand(tied, null, result.operands);\n                            parser.parseOptionalComma();\n                        }\n                    }\n                    result.types.push(type);\n                    parser.parseOptionalComma();\n                }\n            }\n        }\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        this.parseDispatchWorkgroupsCountRegion(parser, result);\n        return true;\n    }\n\n    parseDispatchWorkgroupsOp(parser, result) {\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                parser.parseKeyword(); // read subscript value\n                parser.parseOptionalComma();\n            }\n        }\n        const unresolvedOperands = parser.parseOperandList('paren');\n        if (parser.parseOptionalColon()) {\n            if (parser.parseOptionalLParen()) {\n                const inputTypes = parser.parseTypeList();\n                parser.parseRParen();\n                parser.resolveOperands(unresolvedOperands, inputTypes, result.operands);\n                const resultTypes = parser.parseArrowTypeList();\n                result.addTypes(resultTypes);\n            } else {\n                const types = parser.parseTypeList();\n                parser.resolveOperands(unresolvedOperands, types, result.operands);\n                result.addTypes(parser.parseOptionalArrowTypeList());\n            }\n        } else             {\n            result.addTypes(parser.parseOptionalArrowTypeList());\n        }\n        if (parser.parseOptionalKeyword('attributes')) {\n            parser.parseOptionalAttrDict(result.attributes);\n        }\n        if (parser.parseOptionalEqual()) {\n            const args = [];\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    const arg = parser.parseArgument(true, false);\n                    args.push(arg);\n                    parser.parseOptionalComma();\n                }\n            }\n            if (parser.parseOptionalArrow() || parser.parseOptionalKeyword('to')) {\n                parser.parseType();\n            }\n            const region = result.addRegion();\n            parser.parseRegion(region, args, /* enableNameShadowing */ true);\n        }\n        return true;\n    }\n\n    parseShapedFunctionType(parser, op, unresolvedArguments /*, otherArgs */) {\n        // unresolvedArguments is ref($arguments) - array of unresolved operands with .name and .number\n        const operandTypes = [];\n        if (parser.parseOptionalLParen()) {\n            let index = 0;\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const type = parser.parseType();\n                    if (type) {\n                        operandTypes.push(type);\n                        const startIdx = Math.max(0, op.operands.length - (index + 1));\n                        if (startIdx + index < op.operands.length && !op.operands[startIdx + index].type) {\n                            op.operands[startIdx + index].type = type;\n                        }\n                        index++;\n                    }\n                    if (parser.parseOptionalLBrace()) {\n                        while (!parser.parseOptionalRBrace()) {\n                            parser.parseOperand();\n                            parser.parseOptionalComma();\n                        }\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n\n        if (parser.parseOptionalArrow()) {\n            let index = 0;\n            const hasParens = parser.parseOptionalLParen();\n            if (!hasParens || !parser.parseOptionalRParen()) {\n                do {\n                    const tiedResult = parser.parseOptionalOperand();\n                    if (tiedResult) {\n                        // Handle optional \"as type\" for tied results\n                        if (parser.parseOptionalKeyword('as')) {\n                            const type = parser.parseType();\n                            if (type) {\n                                if (index < op.types.length) {\n                                    op.types[index] = type;\n                                } else {\n                                    op.addTypes([type]);\n                                }\n                            }\n                        } else {\n                            // Look up type from tied operand using unresolvedArguments\n                            // unresolvedArguments contains UnresolvedOperand objects with .name and .number\n                            const operands = unresolvedArguments || [];\n                            const tiedOperandIndex = parser.findTiedOperand(tiedResult, operands);\n                            if (tiedOperandIndex >= 0 && tiedOperandIndex < operandTypes.length) {\n                                const type = operandTypes[tiedOperandIndex];\n                                if (type) {\n                                    if (index < op.types.length) {\n                                        op.types[index] = type;\n                                    } else {\n                                        op.addTypes([type]);\n                                    }\n                                }\n                            }\n                        }\n                        index++;\n                    } else {\n                        const type = parser.parseType();\n                        if (type) {\n                            if (index < op.types.length) {\n                                op.types[index] = type;\n                            } else {\n                                op.addTypes([type]);\n                            }\n                            index++;\n                        }\n                    }\n                    if (parser.parseOptionalLBrace()) {\n                        while (!parser.parseOptionalRBrace()) {\n                            parser.parseOperand();\n                            parser.parseOptionalComma();\n                        }\n                    }\n                    if (!hasParens) {\n                        break;\n                    }\n                } while (parser.parseOptionalComma());\n            }\n            if (hasParens) {\n                parser.parseRParen();\n            }\n        }\n    }\n\n    parseTensorLoadStoreOp(parser, result) {\n        //    or: store %26, %arg4, offsets = [...] : type -> type\n        const unresolvedOperands = [];\n        let nextOp = parser.parseOptionalOperand();\n        while (nextOp) {\n            unresolvedOperands.push(nextOp);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            nextOp = parser.parseOptionalOperand();\n            if (!nextOp) {\n                break;\n            }\n        }\n        // Note: first parameter might not need comma-eating if we just broke from operand loop\n        let paramName = parser.parseOptionalKeyword();\n        while (true) {\n            if (!paramName) {\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                paramName = parser.parseOptionalKeyword();\n            }\n            if (paramName) {\n                if (parser.parseOptionalEqual()) {\n                    if (parser.parseOptionalLSquare()) {\n                        while (!parser.parseOptionalRSquare()) {\n                            const operand = parser.parseOptionalOperand();\n                            if (!operand) {\n                                // Handle integer literals (e.g., 0, 1, 3)\n                                parser.parseInteger();\n                            }\n                            parser.parseOptionalComma();\n                        }\n                    } else {\n                        parser.parseKeyword();\n                    }\n                    result.addAttribute(paramName, paramName);\n                }\n                paramName = null;\n            } else {\n                break;\n            }\n        }\n        const types = parser.parseOptionalColonTypeList();\n        parser.resolveOperands(unresolvedOperands, types, result.operands);\n        // For tensor.load, there's a -> result type\n        // For tensor.store, the -> is followed by the output tensor type (not a result)\n        if (parser.parseOptionalArrow() || parser.parseOptionalKeyword('to')) {\n            const resultType = parser.parseType();\n            if (result.op === 'flow.dispatch.tensor.load' && resultType) {\n                result.addTypes([resultType]);\n            }\n        }\n        return true;\n    }\n\n    parseDispatchWorkgroupBody(parser, op /*, args */) {\n        parser.parseLParen();\n        const regionArgs = [];\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const arg = parser.parseOperand();\n                parser.parseColon();\n                const argType = parser.parseType();\n                regionArgs.push({ name: arg, type: argType });\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        const region = { blocks: [{ arguments: regionArgs, operations: [] }] };\n        parser.parseRegion(region);\n        op.regions.push(region);\n    }\n\n    parseDispatchWorkgroupsCountRegion(parser, op /*, args */) {\n        if (!parser.parseOptionalKeyword('count')) {\n            return;\n        }\n        parser.parseLParen();\n        const regionArgs = [];\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const arg = parser.parseOperand();\n                parser.parseColon();\n                const argType = parser.parseType();\n                regionArgs.push({ name: arg, type: argType });\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.parseArrow();\n        if (parser.parseOptionalLParen()) {\n            parser.parseType();\n            parser.parseOptionalComma();\n            parser.parseType();\n            parser.parseOptionalComma();\n            parser.parseType();\n            parser.parseRParen();\n        } else {\n            parser.parseType();\n            parser.parseOptionalComma();\n            parser.parseType();\n            parser.parseOptionalComma();\n            parser.parseType();\n        }\n        const region = { blocks: [{ arguments: regionArgs, operations: [] }] };\n        parser.parseRegion(region);\n        op.regions.push(region);\n    }\n\n    parseShapedOperandList(parser, result) {\n        const unresolvedValues = [];\n        const valueTypes = [];\n        const unresolvedDims = [];\n        do {\n            unresolvedValues.push(parser.parseOperand());\n            parser.parseColon();\n            const valueType = parser.parseType();\n            valueTypes.push(valueType);\n            if (valueType && valueType.shape) {\n                const dynamicDimCount = valueType.shape.filter((d) => d < 0n).length;\n                if (dynamicDimCount > 0 && parser.parseOptionalLBrace()) {\n                    for (let i = 0; i < dynamicDimCount; i++) {\n                        if (i > 0) {\n                            parser.parseOptionalComma();\n                        }\n                        unresolvedDims.push(parser.parseOperand());\n                    }\n                    parser.parseRBrace();\n                }\n            }\n        } while (parser.parseOptionalComma());\n        for (let i = 0; i < unresolvedValues.length; i++) {\n            parser.resolveOperand(unresolvedValues[i], valueTypes[i], result.operands);\n        }\n        const indexType = new _.IndexType();\n        for (const unresolved of unresolvedDims) {\n            parser.resolveOperand(unresolved, indexType, result.operands);\n        }\n    }\n};\n\n_.StreamDialect = class extends _.IREEDialect {\n\n    constructor(operations, name = 'stream') {\n        super(operations, name);\n        this.registerCustomDirective('DispatchOperands', this.parseDispatchOperands.bind(this));\n        this.registerCustomDirective('DispatchResources', this.parseDispatchResources.bind(this));\n        this.registerCustomDirective('ExplicitResourceRegion', this.parseExplicitResourceRegion.bind(this));\n        this.registerCustomDirective('ShapedTypeList', this.parseShapedTypeList.bind(this));\n        this.registerCustomDirective('ResourceRegion', this.parseResourceRegion.bind(this));\n        this.registerCustomDirective('ParameterLoadOperations', this.parseParameterLoadOperations.bind(this));\n        this.registerCustomDirective('EncodedResourceOperands', this.parseEncodedResourceOperands.bind(this));\n        this.registerCustomDirective('DispatchEntryPoints', this.parseDispatchEntryPoints.bind(this));\n        this.registerCustomDirective('ShapedTiedResult', this.parseShapedTiedResult.bind(this));\n        this.registerCustomDirective('EncodedShapedFunctionType', this.parseEncodedShapedFunctionType.bind(this));\n        this.registerCustomDirective('CollectiveParam', this.parseCollectiveParam.bind(this));\n        this.registerCustomDirective('PackSliceRanges', this.parsePackSliceRanges.bind(this));\n        this.registerCustomDirective('WorkgroupCountRegion', this.parseWorkgroupCountRegion.bind(this));\n        this.registerCustomDirective('DispatchFunctionSignature', this.parseDispatchFunctionSignature.bind(this));\n        this.registerCustomDirective('ShapedFunctionSignature', this.parseShapedFunctionSignature.bind(this));\n        this.registerCustomDirective('ConstantValueList', this.parseConstantValueList.bind(this));\n        this.registerCustomDirective('CmdCallOperands', this.parseCmdCallOperands.bind(this));\n        this.registerCustomDirective('ParameterReference', this.parseParameterReference.bind(this));\n        this.registerCustomDirective('ParameterGatherOperations', this.parseParameterGatherOperations.bind(this));\n        this.registerCustomDirective('ParameterScatterOperations', this.parseParameterScatterOperations.bind(this));\n        this.registerCustomDirective('SymbolAlias', this.parseSymbolAlias.bind(this));\n    }\n\n    parseDispatchResources(parser, op /*, args */) {\n        do {\n            const accessMode = parser.parseKeyword();\n            const unresolvedResource = parser.parseOperand();\n            parser.parseLSquare();\n            const unresolvedOffset = parser.parseOperand();\n            parser.parseKeyword('for');\n            const unresolvedLength = parser.parseOperand();\n            parser.parseRSquare();\n            parser.parseColon();\n            const resourceType = parser.parseType();\n            if (parser.parseOptionalLBrace()) {\n                while (!parser.parseOptionalRBrace()) {\n                    parser.parseOperand();\n                    parser.parseOptionalComma();\n                }\n            }\n            op.addAttribute('resource_access', accessMode);\n            parser.resolveOperand(unresolvedResource, resourceType, op.operands);\n            const indexType = new _.IndexType();\n            parser.resolveOperand(unresolvedOffset, indexType, op.operands);\n            parser.resolveOperand(unresolvedLength, indexType, op.operands);\n        } while (parser.parseOptionalComma());\n    }\n\n    parseShapedTypeList(parser, op, ...args) {\n        // 2-arg: custom<ShapedTypeList>(type($operands), $sizes)\n        // 3-arg: custom<ShapedTypeList>(type($operands), type($results), $sizes)\n        let operandTypes = null;\n        let resultTypes = null;\n        let sizeOperands = null;\n        if (args.length === 2) {\n            [operandTypes, sizeOperands] = args;\n        } else if (args.length >= 3) {\n            [operandTypes, resultTypes, sizeOperands] = args;\n        } else {\n            operandTypes = args[0] || null;\n        }\n        const indexType = new _.IndexType();\n        do {\n            const type = parser.parseType();\n            if (operandTypes) {\n                operandTypes.push(type);\n            }\n            if (resultTypes) {\n                resultTypes.push(type);\n            }\n            if (parser.parseOptionalLBrace()) {\n                do {\n                    const sizeOperand = parser.parseOptionalOperand();\n                    if (sizeOperand) {\n                        if (sizeOperands) {\n                            sizeOperands.push(sizeOperand);\n                        }\n                        parser.resolveOperand(sizeOperand, indexType, op.operands);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRBrace();\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseExplicitResourceRegion(parser, op /*, args */) {\n        parser.parseLParen();\n        const regionArgs = [];\n        const unresolvedOperands = [];\n        const operandTypes = [];\n        const unresolvedSizes = [];\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const _optOp = parser.parseOptionalOperand();\n                if (_optOp) {\n                    unresolvedOperands.push(_optOp);\n                }\n                parser.parseKeyword('as');\n                const arg = parser.parseOperand();\n                parser.parseColon();\n                const argType = parser.parseType();\n                operandTypes.push(argType);\n                regionArgs.push({ name: arg, type: argType });\n                if (parser.parseOptionalLBrace()) {\n                    const _sizeOp = parser.parseOptionalOperand();\n                    if (_sizeOp) {\n                        unresolvedSizes.push(_sizeOp);\n                    }\n                    parser.parseRBrace();\n                }\n            } while (parser.parseOptionalComma());\n        }\n        parser.parseRParen();\n        for (let i = 0; i < unresolvedOperands.length; i++) {\n            parser.resolveOperand(unresolvedOperands[i], operandTypes[i] || null, op.operands);\n        }\n        const indexType = new _.IndexType();\n        for (const unresolved of unresolvedSizes) {\n            parser.resolveOperand(unresolved, indexType, op.operands);\n        }\n        const region = { blocks: [{ arguments: regionArgs, operations: [] }] };\n        parser.parseRegion(region);\n        op.regions.push(region);\n    }\n\n    parseResourceRegion(parser, op /*, args */) {\n        const regionArgs = [];\n        const unresolvedOperands = [];\n        const operandTypes = [];\n        const unresolvedSizes = [];\n        const indexType = new _.IndexType();\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const operand = parser.parseOperand();\n                unresolvedOperands.push(operand);\n                parser.parseKeyword('as');\n                const arg = parser.parseOperand();\n                parser.parseColon();\n                const argType = parser.parseType();\n                operandTypes.push(argType);\n                regionArgs.push({ name: arg, type: argType });\n                if (parser.parseOptionalLBrace()) {\n                    const _sizeOp = parser.parseOptionalOperand();\n                    if (_sizeOp) {\n                        unresolvedSizes.push(_sizeOp);\n                    }\n                    parser.parseRBrace();\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        for (let i = 0; i < unresolvedOperands.length; i++) {\n            parser.resolveOperand(unresolvedOperands[i], operandTypes[i], op.operands);\n        }\n        for (const unresolved of unresolvedSizes) {\n            parser.resolveOperand(unresolved, indexType, op.operands);\n        }\n        const resultSizes = [];\n        const parseResultTypeOrTied = () => {\n            const tiedOp = parser.parseOptionalOperand();\n            if (tiedOp) {\n                if (parser.parseOptionalKeyword('as')) {\n                    const resultType = parser.parseType();\n                    op.addTypes([resultType]);\n                } else {\n                    op.addTypes([new _.Type('tied')]);\n                }\n            } else {\n                const resultType = parser.parseType();\n                op.addTypes([resultType]);\n            }\n            if (parser.parseOptionalLBrace()) {\n                const sizeOp = parser.parseOptionalOperand();\n                if (sizeOp) {\n                    resultSizes.push(sizeOp);\n                }\n                parser.parseRBrace();\n            }\n        };\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        parseResultTypeOrTied();\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            } else {\n                parseResultTypeOrTied();\n            }\n        }\n        for (const unresolved of resultSizes) {\n            parser.resolveOperand(unresolved, indexType, op.operands);\n        }\n        {\n            const region = { blocks: [{ arguments: regionArgs, operations: [] }] };\n            parser.parseRegion(region);\n            op.regions.push(region);\n        }\n    }\n\n    parseParameterLoadOperations(parser, op, sourceScopeOps, sourceKeysOps, sourceOffsetsOps, resultTypes, resultSizesOps) {\n        do {\n            const firstOperand = parser.parseOperand();\n            let key = firstOperand;\n            if (parser.parseOptionalColon()) {\n                sourceScopeOps.push(firstOperand);\n                parser.parseColon();\n                key = parser.parseOperand();\n            }\n            sourceKeysOps.push(key);\n            parser.parseLSquare();\n            sourceOffsetsOps.push(parser.parseOperand());\n            parser.parseRSquare();\n            parser.parseColon();\n            const resultType = parser.parseType();\n            op.addTypes([resultType]);\n            if (parser.parseOptionalLBrace()) {\n                resultSizesOps.push(parser.parseOperand());\n                parser.parseRBrace();\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseEncodedResourceOperands(parser, op) {\n        const indexType = new _.IndexType();\n        do {\n            parser.parseOperand();\n            parser.parseColon();\n            parser.parseType();\n            const encodingDims = parser.parseOperandList('optionalBrace');\n            parser.resolveOperands(encodingDims, encodingDims.map(() => indexType), op.operands);\n            parser.parseKeyword('in');\n            parser.parseType();\n            const sizeDims = parser.parseOperandList('optionalBrace');\n            parser.resolveOperands(sizeDims, sizeDims.map(() => indexType), op.operands);\n        } while (parser.parseOptionalComma());\n    }\n\n    parseDispatchEntryPoints(parser, op /*, args */) {\n        if (parser.parseOptionalLBrace()) {\n            do {\n                const symbol = parser.parseOptionalSymbolName();\n                op.addAttribute('entry_point', symbol);\n            } while (parser.parseOptionalComma());\n            parser.parseRBrace();\n        } else {\n            const symbol = parser.parseOptionalSymbolName();\n            op.addAttribute('entry_point', symbol);\n        }\n    }\n\n    parseShapedTiedResult(parser, op /*, args */) {\n        const tiedOp = parser.parseOptionalOperand();\n        if (tiedOp) {\n            parser.parseKeyword('as');\n        }\n        const type = parser.parseType();\n        op.types.push(type);\n        if (parser.parseOptionalLBrace()) {\n            const unresolvedSize = parser.parseOptionalOperand();\n            if (unresolvedSize) {\n                const indexType = new _.IndexType();\n                parser.resolveOperand(unresolvedSize, indexType, op.operands);\n            }\n            parser.parseRBrace();\n        }\n    }\n\n    parseEncodedShapedTypeList(parser, types, operands) {\n        const indexType = new _.IndexType();\n        do {\n            const type0 = parser.parseType();\n            const dims0 = parser.parseOperandList('optionalBrace');\n            if (operands) {\n                parser.resolveOperands(dims0, dims0.map(() => indexType), operands);\n            }\n            if (parser.parseOptionalKeyword('in')) {\n                const type1 = parser.parseType();\n                const dims1 = parser.parseOperandList('optionalBrace');\n                if (operands) {\n                    parser.resolveOperands(dims1, dims1.map(() => indexType), operands);\n                }\n                types.push(type1);\n            } else {\n                types.push(type0);\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseEncodedShapedResultList(parser, operands, operandTypes, resultTypes, resolvedOperands) {\n        const indexType = new _.IndexType();\n        do {\n            let type0 = null;\n            const tryTied0 = parser.parseOptionalOperand();\n            if (!tryTied0) {\n                type0 = parser.parseType();\n                const dims0 = parser.parseOperandList('optionalBrace');\n                if (resolvedOperands) {\n                    parser.resolveOperands(dims0, dims0.map(() => indexType), resolvedOperands);\n                }\n            }\n            if (!parser.parseOptionalKeyword('in')) {\n                if (type0) {\n                    resultTypes.push(type0);\n                }\n                continue;\n            }\n            let resultType = null;\n            const tryTied1 = tryTied0 || parser.parseOptionalOperand();\n            if (tryTied1) {\n                const tiedOperandIndex = parser.findTiedOperand(tryTied1, operands);\n                if (parser.parseOptionalKeyword('as')) {\n                    resultType = parser.parseType();\n                } else if (tiedOperandIndex >= 0 && operandTypes[tiedOperandIndex]) {\n                    resultType = operandTypes[tiedOperandIndex];\n                }\n            } else {\n                resultType = parser.parseType();\n            }\n            const dims1 = parser.parseOperandList('optionalBrace');\n            if (resolvedOperands) {\n                parser.resolveOperands(dims1, dims1.map(() => indexType), resolvedOperands);\n            }\n            if (resultType) {\n                resultTypes.push(resultType);\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseEncodedShapedFunctionType(parser, op, operandsRef, operandTypes /* , ... */) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            this.parseEncodedShapedTypeList(parser, operandTypes, op.operands);\n            parser.parseRParen();\n        }\n        parser.parseArrow();\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                this.parseEncodedShapedResultList(parser, operandsRef, operandTypes, op.types, op.operands);\n                parser.parseRParen();\n            }\n        } else {\n            this.parseEncodedShapedResultList(parser, operandsRef, operandTypes, op.types, op.operands);\n        }\n    }\n\n    parseCollectiveParam(parser, op /*, args */) {\n        for (const keyword of ['source', 'target', 'source_target_pair']) {\n            if (parser.parseOptionalKeyword(keyword)) {\n                parser.parseLParen();\n                const unresolvedParam = parser.parseOperand();\n                parser.resolveOperand(unresolvedParam, null, op.operands);\n                parser.parseRParen();\n                return;\n            }\n        }\n    }\n\n    parsePackSliceRanges(parser, op, lifetimeIntervalsName, dynamicSliceSizesOperands, packedOffsetsTypes) {\n        const indexType = new _.IndexType();\n        while (parser.parseOptionalLSquare()) {\n            parser.parseAttribute();\n            parser.parseComma();\n            parser.parseAttribute();\n            parser.parseRSquare();\n            parser.parseEqual();\n            const unresolvedOperand = parser.parseOperand();\n            parser.resolveOperand(unresolvedOperand, indexType, op.operands);\n            packedOffsetsTypes.push(indexType);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n        }\n    }\n\n    parseWorkgroupCountRegion(parser, op /*, args */) {\n        if (!parser.parseOptionalKeyword('workgroups')) {\n            return;\n        }\n        const region = { blocks: [] };\n        const block = { arguments: [], operations: [] };\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const arg = parser.parseOperand();\n                    if (parser.parseOptionalColon()) {\n                        arg.type = parser.parseType();\n                    }\n                    block.arguments.push(arg);\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        if (parser.parseOptionalArrow()) {\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    parser.parseType();\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        region.blocks.push(block);\n        parser.parseRegion(region);\n        op.regions.push(region);\n    }\n\n    parseDispatchFunctionSignature(parser, op /*, args */) {\n        const indexType = new _.IndexType();\n        const inputs = [];\n        const results = [];\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                parser.parseOperand();\n                if (parser.parseOptionalLSquare()) {\n                    if (!parser.parseOptionalRSquare()) {\n                        parser.parseOperand();\n                        if (parser.parseOptionalKeyword('for')) {\n                            parser.parseOperand();\n                        }\n                        parser.parseRSquare();\n                    }\n                }\n                parser.parseColon();\n                const type = parser.parseType();\n                inputs.push(type);\n                const dims = parser.parseOperandList('optionalBrace');\n                parser.resolveOperands(dims, dims.map(() => indexType), op.operands);\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        const parseResultTypeOrTied = () => {\n            const tiedOp = parser.parseOptionalOperand();\n            if (tiedOp) {\n                if (parser.parseOptionalKeyword('as')) {\n                    return parser.parseType();\n                }\n                return new _.Type('tied');\n            }\n            return parser.parseType();\n        };\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        results.push(parseResultTypeOrTied());\n                        const dims = parser.parseOperandList('optionalBrace');\n                        parser.resolveOperands(dims, dims.map(() => indexType), op.operands);\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            } else {\n                results.push(parseResultTypeOrTied());\n                const dims = parser.parseOperandList('optionalBrace');\n                parser.resolveOperands(dims, dims.map(() => indexType), op.operands);\n            }\n        }\n        op.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n    }\n\n    parseShapedFunctionSignature(parser, op /*, args */) {\n        this.parseDispatchFunctionSignature(parser, op);\n    }\n\n    parseConstantValueList(parser, op /*, args */) {\n        do {\n            const resultType = parser.parseType();\n            op.addTypes([resultType]);\n            if (parser.parseOptionalLBrace()) {\n                // Size is an SSA value like %c4, not an attribute\n                const _sizeOp = parser.parseOptionalOperand();\n                if (_sizeOp) {\n                    parser.resolveOperand(_sizeOp, null, op.operands);\n                } else {\n                    const size = parser.parseAttribute();\n                    if (size) {\n                        // If it's an integer literal, create operand directly\n                        op.operands.push(new _.Value(null, size));\n                    }\n                }\n                parser.parseRBrace();\n            }\n            parser.parseEqual();\n            parser.parseAttribute();\n            if (parser.parseOptionalColon()) {\n                parser.parseType();\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseCmdCallOperands(parser, op /*, args */) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            const indexType = new _.IndexType();\n            do {\n                // Check for access mode keyword (ro, rw, wo)\n                const accessMode = parser.parseOptionalKeyword('ro') || parser.parseOptionalKeyword('rw') || parser.parseOptionalKeyword('wo');\n                if (accessMode) {\n                    // Resource operand with offset/length: access operand[offset for length]\n                    const unresolvedResource = parser.parseOperand();\n                    parser.parseLSquare();\n                    const unresolvedOffset = parser.parseOperand();\n                    parser.parseKeyword('for');\n                    const unresolvedLength = parser.parseOperand();\n                    parser.parseRSquare();\n                    op.addAttribute('resource_access', accessMode);\n                    parser.resolveOperand(unresolvedResource, null, op.operands);\n                    parser.resolveOperand(unresolvedOffset, indexType, op.operands);\n                    parser.resolveOperand(unresolvedLength, indexType, op.operands);\n                } else {\n                    // Primitive/custom operand\n                    const unresolvedOperand = parser.parseOperand();\n                    parser.resolveOperand(unresolvedOperand, null, op.operands);\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n    }\n\n    parseParameterReference(parser, op, scopeOperands, keyOperands) {\n        const firstOperand = parser.parseOperand();\n        if (parser.parseOptionalColon()) {\n            parser.parseColon();\n            const keyOperand = parser.parseOperand();\n            if (scopeOperands) {\n                scopeOperands.push(firstOperand);\n            }\n            if (keyOperands) {\n                keyOperands.push(keyOperand);\n            }\n        } else if (keyOperands) {\n            keyOperands.push(firstOperand);\n        }\n    }\n\n    parseParameterGatherOperations(parser /*, op, args */) {\n        do {\n            // %scope::%key[offset] -> %target[offset for length] : type{size}\n            this.parseParameterReference(parser);\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            parser.parseArrow();\n            parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseKeyword('for');\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            parser.parseColon();\n            parser.parseType();\n            if (parser.parseOptionalLBrace()) {\n                parser.parseOperand();\n                parser.parseRBrace();\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseParameterScatterOperations(parser /*, op, args */) {\n        do {\n            // %source[offset for length] : type{size} -> %scope::%key[offset]\n            parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseKeyword('for');\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            parser.parseColon();\n            parser.parseType();\n            if (parser.parseOptionalLBrace()) {\n                parser.parseOperand();\n                parser.parseRBrace();\n            }\n            parser.parseArrow();\n            this.parseParameterReference(parser);\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n        } while (parser.parseOptionalComma());\n    }\n\n    parseSymbolAlias(parser, op /*, args */) {\n        parser.parseSymbolName('sym_name', op.attributes);\n        if (parser.parseOptionalEqual()) {\n            const ref = parser.parseOptionalSymbolName();\n            op.addAttribute('function_ref', ref);\n        }\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            const simpleTypes = ['binding', 'channel', 'timepoint', 'file'];\n            if (simpleTypes.includes(mnemonic)) {\n                return new _.Type(type);\n            }\n            if (mnemonic === 'resource') {\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n            // Handle test.fence type (Stream_TestFence in StreamTypes.td)\n            if (mnemonic === 'test' || mnemonic === 'test.fence') {\n                return new _.Type(`!${dialect}.${mnemonic}`);\n            }\n            throw new mlir.Error(`Unsupported type '!${dialect}.${mnemonic}'.`);\n        }\n        return null;\n    }\n\n    parseDispatchOperands(parser, op, resourceOperands /* offsets, ends, lengths */) {\n        // args are: [$resource_operands, $resource_operand_offsets, $resource_operand_ends, $resource_operand_lengths]\n        // resourceOperands is passed by ref so ShapedFunctionType can use it for tied operand lookup\n        parser.parseLParen();\n\n        if (parser.parseOptionalRParen()) {\n            return;\n        }\n\n        const unresolvedOperands = [];\n        do {\n            const operand = parser.parseOperand();\n            unresolvedOperands.push(operand);\n            if (Array.isArray(resourceOperands)) {\n                resourceOperands.push(operand);\n            }\n            if (parser.parseOptionalLSquare()) {\n                unresolvedOperands.push(parser.parseOperand()); // offset\n                parser.parseKeyword('to');\n                unresolvedOperands.push(parser.parseOperand()); // end\n                parser.parseKeyword('for');\n                unresolvedOperands.push(parser.parseOperand()); // length\n                parser.parseRSquare();\n            }\n        } while (parser.parseOptionalComma());\n\n        parser.parseRParen();\n\n        for (const unresolved of unresolvedOperands) {\n            parser.resolveOperand(unresolved, null, op.operands);\n        }\n    }\n};\n\n_.IOParametersDialect = class extends _.StreamDialect {\n\n    constructor(operations) {\n        super(operations, 'io_parameters');\n    }\n};\n\n_.PCFDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'pcf');\n        this.registerCustomDirective('ParallelExecutionBody', this.parseParallelExecutionBody.bind(this));\n        this.registerCustomDirective('InferNumIndexArgs', this.parseInferNumIndexArgs.bind(this));\n    }\n\n    parseInferNumIndexArgs() {\n    }\n\n    parseParallelExecutionBody(parser, result) {\n        const inits = [];\n        const dynamicSizes = [];\n        const resultTypes = [];\n        const isTied = [];\n        const regionRefArgs = [];\n        const indexArgs = [];\n        if (parser.parseOptionalArrow()) {\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const arg = parser.parseOperand();\n                    parser.parseColon();\n                    const argType = parser.parseType();\n                    result.addAttribute('num_leading_args', (result.attributes.get('num_leading_args') || 0) + 1);\n                    regionRefArgs.push({ value: arg, type: argType });\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        parser.parseKeyword('execute');\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const refArg = parser.parseOperand();\n                    regionRefArgs.push({ value: refArg });\n                    if (parser.parseOptionalEqual()) {\n                        const initOperand = parser.parseOperand();\n                        inits.push({ value: initOperand });\n                        isTied.push(true);\n                    } else {\n                        isTied.push(false);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                const indexArg = parser.parseOperand();\n                parser.parseColon();\n                const indexType = parser.parseType();\n                indexArgs.push({ value: indexArg, type: indexType });\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        if (regionRefArgs.length > 0 && parser.parseOptionalColon()) {\n            parser.parseLParen();\n            let refIdx = result.attributes.get('num_leading_args') || 0;\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const refType = parser.parseType();\n                    if (refIdx < regionRefArgs.length) {\n                        regionRefArgs[refIdx].type = refType;\n                    }\n                    refIdx++;\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            parser.parseArrow();\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const resType = parser.parseType();\n                    resultTypes.push(resType);\n                    result.addTypes([resType]);\n                    if (parser.parseOptionalLBrace()) {\n                        if (!parser.parseOptionalRBrace()) {\n                            do {\n                                const dim = parser.parseOperand();\n                                dynamicSizes.push({ value: dim });\n                            } while (parser.parseOptionalComma());\n                            parser.parseRBrace();\n                        }\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        for (const init of inits) {\n            parser.resolveOperand(init.value, null, result.operands);\n        }\n        for (const dim of dynamicSizes) {\n            parser.resolveOperand(dim.value, null, result.operands);\n        }\n        if (isTied.length > 0) {\n            result.addAttribute('is_tied', isTied);\n        }\n        const region = { blocks: [{ arguments: [...regionRefArgs, ...indexArgs], operations: [] }] };\n        parser.parseRegion(region);\n        result.regions.push(region);\n    }\n};\n\n_.IREEVectorExtDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'iree_vector_ext');\n    }\n\n};\n\n_.IREETensorExtDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'iree_tensor_ext');\n    }\n\n    parseType(parser /*, dialect */) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic === 'dispatch.tensor') {\n            return _.iree.DispatchTensorType.parse(parser);\n        }\n        return null;\n    }\n};\n\n_.LinalgDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'linalg');\n        this._namedStructuredOps = new Set([\n            'linalg.matmul', 'linalg.batch_matmul', 'linalg.batch_reduce_matmul',\n            'linalg.matvec', 'linalg.vecmat', 'linalg.dot', 'linalg.batch_matvec',\n            'linalg.conv_1d', 'linalg.conv_1d_ncw_fcw', 'linalg.conv_1d_nwc_wcf',\n            'linalg.conv_2d', 'linalg.conv_2d_nchw_fchw', 'linalg.conv_2d_nchw_fchw_q',\n            'linalg.conv_2d_ngchw_fgchw', 'linalg.conv_2d_ngchw_gfchw', 'linalg.conv_2d_ngchw_gfchw_q',\n            'linalg.conv_2d_nhwc_fhwc', 'linalg.conv_2d_nhwc_fhwc_q',\n            'linalg.conv_2d_nhwc_hwcf', 'linalg.conv_2d_nhwc_hwcf_q',\n            'linalg.conv_2d_nhwgc_gfhwc', 'linalg.conv_2d_nhwgc_gfhwc_q',\n            'linalg.conv_3d', 'linalg.conv_3d_ncdhw_fcdhw', 'linalg.conv_3d_ndhwc_dhwcf', 'linalg.conv_3d_ndhwc_dhwcf_q',\n            'linalg.depthwise_conv_1d_ncw_cw', 'linalg.depthwise_conv_1d_nwc_wc', 'linalg.depthwise_conv_1d_nwc_wcm',\n            'linalg.depthwise_conv_2d_nchw_chw', 'linalg.depthwise_conv_2d_nhwc_hwc', 'linalg.depthwise_conv_2d_nhwc_hwc_q',\n            'linalg.depthwise_conv_2d_nhwc_hwcm', 'linalg.depthwise_conv_2d_nhwc_hwcm_q',\n            'linalg.depthwise_conv_3d_ncdhw_cdhw', 'linalg.depthwise_conv_3d_ndhwc_dhwc', 'linalg.depthwise_conv_3d_ndhwc_dhwcm',\n            'linalg.pooling_nchw_max', 'linalg.pooling_nchw_sum',\n            'linalg.pooling_nhwc_max', 'linalg.pooling_nhwc_max_unsigned', 'linalg.pooling_nhwc_min', 'linalg.pooling_nhwc_min_unsigned', 'linalg.pooling_nhwc_sum',\n            'linalg.pooling_ncw_max', 'linalg.pooling_ncw_sum',\n            'linalg.pooling_nwc_max', 'linalg.pooling_nwc_max_unsigned', 'linalg.pooling_nwc_min', 'linalg.pooling_nwc_min_unsigned', 'linalg.pooling_nwc_sum',\n            'linalg.pooling_ndhwc_max', 'linalg.pooling_ndhwc_min', 'linalg.pooling_ndhwc_sum'\n        ]);\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (result.op === 'linalg.generic') {\n            return this.parseGenericOp(parser, result);\n        }\n        if (result.op === 'linalg.init_tensor') {\n            if (parser.parseOptionalLSquare()) {\n                const dims = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const dimOp = parser.parseOptionalOperand();\n                        if (dimOp) {\n                            dims.push(dimOp.name);\n                        } else {\n                            const intVal = parser.parseOptionalInteger();\n                            if (intVal !== null) {\n                                dims.push(String(intVal));\n                            }\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                result.addAttribute('static_sizes', dims);\n            }\n            result.addTypes(parser.parseOptionalColonTypeList());\n            return true;\n        }\n        if (result.op === 'linalg.fill') {\n            if (parser.parseOptionalLParen()) {\n                // Legacy format: linalg.fill(%operands) : types -> types\n                const unresolvedOperands = parser.parseOperandList();\n                parser.parseRParen();\n                parser.parseOptionalAttrDict(result.attributes);\n                parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n                result.addTypes(parser.parseOptionalArrowTypeList());\n                return true;\n            }\n            return this.parseNamedStructuredOp(parser, result);\n        }\n        if (result.op === 'linalg.conv') {\n            let unresolvedOperands = [];\n            if (parser.parseOptionalLParen()) {\n                unresolvedOperands = parser.parseOperandList();\n                parser.parseRParen();\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            return true;\n        }\n        if (result.op === 'linalg.yield') {\n            const unresolvedOperands = parser.parseOperandList();\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            return true;\n        }\n        if (result.op === 'linalg.pack') {\n            return this.parsePackOp(parser, result);\n        }\n        if (result.op === 'linalg.unpack') {\n            return this.parseUnpackOp(parser, result);\n        }\n        if (result.op === 'linalg.transpose') {\n            return this.parseDstStyleOp(parser, result, (parser, attributes) => {\n                parser.parseDenseI64ArrayAttr('permutation', attributes);\n            });\n        }\n        if (result.op === 'linalg.reduce') {\n            // Optional short form: { payload_op attr-dict }\n            let payloadOpName = null;\n            const payloadOpAttrs = new Map();\n            if (parser.parseOptionalLBrace()) {\n                payloadOpName = parser.parseCustomOperationName();\n                parser.parseOptionalAttrDict(payloadOpAttrs);\n                parser.parseRBrace();\n            }\n            if (!this.parseDstStyleOp(parser, result, (parser, attributes) => {\n                parser.parseDenseI64ArrayAttr('dimensions', attributes);\n            })) {\n                return false;\n            }\n            // Parse block arguments and region (or add body with payload op)\n            if (payloadOpName) {\n                this.addBodyWithPayloadOp(result, payloadOpName, payloadOpAttrs, true, true);\n            } else {\n                const regionArgs = [];\n                if (parser.parseOptionalLParen()) {\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            const value = parser.parseOperand();\n                            parser.parseColon();\n                            const type = parser.parseType();\n                            regionArgs.push({ value, type });\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                }\n                const region = result.addRegion();\n                parser.parseRegion(region, regionArgs);\n            }\n            return true;\n        }\n        if (result.op === 'linalg.broadcast') {\n            return this.parseDstStyleOp(parser, result, (parser, attributes) => {\n                parser.parseDenseI64ArrayAttr('dimensions', attributes);\n            });\n        }\n        if (result.op === 'linalg.elementwise') {\n            parser.parseKeyword('kind');\n            parser.parseEqual();\n            const kind = parser.parseAttribute();\n            result.addAttribute('kind', kind.value);\n            const indexingMapsAttr = this.parseIndexingMapsAttr(parser);\n            if (indexingMapsAttr !== null) {\n                result.addAttribute('indexing_maps', indexingMapsAttr);\n            }\n            return this.parseNamedStructuredOp(parser, result);\n        }\n        if (result.op === 'linalg.map') {\n            return this.parseMapOp(parser, result);\n        }\n        if (result.op === 'linalg.contract') {\n            const indexingMapsAttr = this.parseIndexingMapsAttr(parser);\n            if (!indexingMapsAttr) {\n                throw new mlir.Error(`Expected 'indexing_maps' attribute ${parser.getCurrentLocation()}`);\n            }\n            result.addAttribute('indexing_maps', indexingMapsAttr);\n            return this.parseNamedStructuredOp(parser, result);\n        }\n        if (this._namedStructuredOps.has(result.op)) {\n            const indexingMapsAttr = this.parseIndexingMapsAttr(parser);\n            if (indexingMapsAttr) {\n                result.addAttribute('indexing_maps', indexingMapsAttr);\n            }\n            return this.parseNamedStructuredOp(parser, result);\n        }\n        if (opInfo.metadata && opInfo.metadata.assemblyFormat) {\n            return super.parseOperation(parser, result);\n        }\n        const parsed = this.parseCommonStructuredOpParts(parser, result);\n        if (!parsed) {\n            return false;\n        }\n        if (parser.parseOptionalKeyword('attrs')) {\n            parser.parseEqual();\n            parser.parseOptionalAttrDict(result.attributes);\n        }\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        parser.parseOptionalRegion(result.addRegion(), []);\n        return true;\n    }\n\n    // \"Common parsing used for both named structured ops created by ods-gen and by\n    // manually defined C++ ops. Does not handle regions.\"\n    // Returns { inputTypes, outputTypes } on success, null on failure.\n    parseCommonStructuredOpParts(parser, result, addOperandSegmentSizes = true) {\n        if (parser.parseOptionalLess()) {\n            result.propertiesAttr = parser.parseAttribute();\n            parser.parseGreater();\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        const inputTypes = [];\n        const outputTypes = [];\n        if (parser.parseOptionalKeyword('ins')) {\n            if (!parser.parseOptionalLParen()) {\n                return null;\n            }\n            const unresolvedIns = [];\n            let insOp = parser.parseOptionalOperand();\n            while (insOp) {\n                unresolvedIns.push(insOp);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                insOp = parser.parseOptionalOperand();\n            }\n            if (parser.parseOptionalColon()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        inputTypes.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                    parser.resolveOperands(unresolvedIns, inputTypes, result.operands);\n                    parser.parseRParen();\n                }\n            } else if (!parser.parseOptionalRParen()) {\n                return null;\n            }\n        }\n        if (parser.parseOptionalKeyword('outs')) {\n            if (!parser.parseOptionalLParen()) {\n                return null;\n            }\n            const unresolvedOuts = [];\n            let outsOp = parser.parseOptionalOperand();\n            while (outsOp) {\n                unresolvedOuts.push(outsOp);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                outsOp = parser.parseOptionalOperand();\n            }\n            if (parser.parseOptionalColon()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        outputTypes.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                    parser.resolveOperands(unresolvedOuts, outputTypes, result.operands);\n                    parser.parseRParen();\n                }\n            } else if (!parser.parseOptionalRParen()) {\n                return null;\n            }\n        }\n        if (addOperandSegmentSizes) {\n            result.addAttribute('operandSegmentSizes', new _.DenseI32ArrayAttr([inputTypes.length, outputTypes.length]));\n        }\n        return { inputTypes, outputTypes };\n    }\n\n    parseNamedStructuredOp(parser, result) {\n        const parsed = this.parseCommonStructuredOpParts(parser, result);\n        if (!parsed) {\n            return false;\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        return true;\n    }\n\n    parseIndexingMapsAttr(parser) {\n        if (!parser.parseOptionalKeyword('indexing_maps')) {\n            return null;\n        }\n        parser.parseEqual();\n        return parser.parseAttribute();\n    }\n\n    parseDstStyleOp(parser, op, parseAttrsFn) {\n        const parsed = this.parseCommonStructuredOpParts(parser, op, false);\n        if (!parsed) {\n            return false;\n        }\n        for (const outputType of parsed.outputTypes) {\n            if (outputType instanceof _.RankedTensorType) {\n                op.addTypes([outputType]);\n            }\n        }\n        if (parseAttrsFn) {\n            parseAttrsFn(parser, op.attributes);\n        }\n        parser.parseOptionalAttrDict(op.attributes);\n        return true;\n    }\n\n    addBodyWithPayloadOp(op, payloadOpName, payloadOpAttrs /*, initFirst, mapInit */) {\n        const region = op.addRegion();\n        const block = { operations: [], arguments: [] };\n        for (const operand of op.operands) {\n            if (operand && operand.type) {\n                const elemType = operand.type.elementType || operand.type;\n                block.arguments.push({ value: null, type: elemType });\n            }\n        }\n        const payloadState = new _.OperationState(null,payloadOpName);\n        if (op.operands.length > 0) {\n            const lastOperand = op.operands[op.operands.length - 1];\n            if (lastOperand && lastOperand.type) {\n                const elemType = lastOperand.type.elementType || lastOperand.type;\n                payloadState.types = [elemType];\n            }\n        }\n        for (const [name, value] of payloadOpAttrs) {\n            payloadState.attributes.set(name, value);\n        }\n        block.operations.push(_.Operation.create(payloadState));\n        const yieldState = new _.OperationState(null, this.getOperation('linalg.yield'));\n        block.operations.push(_.Operation.create(yieldState));\n        region.blocks = [block];\n    }\n\n    parseMapOp(parser, result) {\n        let payloadOpName = null;\n        const payloadOpAttrs = new Map();\n        if (parser.parseOptionalLBrace()) {\n            payloadOpName = parser.parseCustomOperationName();\n            parser.parseOptionalAttrDict(payloadOpAttrs);\n            parser.parseRBrace();\n        }\n        if (!this.parseDstStyleOp(parser, result)) {\n            return false;\n        }\n        // Parse block arguments and region (or add body with payload op)\n        if (payloadOpName) {\n            if (result.operands.length > 0) {\n                this.addBodyWithPayloadOp(result, payloadOpName, payloadOpAttrs, false, false);\n            } else {\n                result.addRegion();\n            }\n        } else {\n            const regionArgs = [];\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const value = parser.parseOperand();\n                        parser.parseColon();\n                        const type = parser.parseType();\n                        regionArgs.push({ value, type });\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            const region = result.addRegion();\n            parser.parseRegion(region, regionArgs);\n        }\n        return true;\n    }\n\n    parseGenericOp(parser, result) {\n        const optAttr = parser.parseOptionalAttribute();\n        if (optAttr === null) {\n            parser.parseOptionalAttrDict(result.attributes);\n        } else {\n            result.addAttribute('trait', optAttr);\n        }\n        this.parseCommonStructuredOpParts(parser, result);\n        if (parser.parseOptionalKeyword('attrs')) {\n            parser.parseEqual();\n            parser.parseOptionalAttrDict(result.attributes);\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        return true;\n    }\n\n    parsePackOp(parser, result) {\n        const unresolvedSource = parser.parseOperand();\n        let unresolvedPadding = null;\n        let paddingType = null;\n        if (parser.parseOptionalKeyword('padding_value')) {\n            parser.parseLParen();\n            unresolvedPadding = parser.parseOperand();\n            parser.parseColon();\n            paddingType = parser.parseType();\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalKeyword('outer_dims_perm')) {\n            parser.parseEqual();\n            const outerDimsPerm = [];\n            parser.parseLSquare();\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    outerDimsPerm.push(parser.parseInteger('int64'));\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n            result.addAttribute('outer_dims_perm', outerDimsPerm);\n        }\n        parser.parseKeyword('inner_dims_pos');\n        parser.parseEqual();\n        const innerDimsPos = [];\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                innerDimsPos.push(parser.parseInteger('int64'));\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        result.addAttribute('inner_dims_pos', innerDimsPos);\n        parser.parseKeyword('inner_tiles');\n        parser.parseEqual();\n        const staticInnerTiles = [];\n        const dynamicTileOperands = [];\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                const dynOp = parser.parseOptionalOperand();\n                if (dynOp) {\n                    dynamicTileOperands.push(dynOp);\n                    staticInnerTiles.push(_.ShapedType.kDynamic);\n                } else {\n                    staticInnerTiles.push(parser.parseInteger('int64'));\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        result.addAttribute('static_inner_tiles', staticInnerTiles);\n        parser.parseKeyword('into');\n        const unresolvedDest = parser.parseOperand();\n        parser.parseOptionalAttrDict(result.attributes);\n        parser.parseColon();\n        const sourceType = parser.parseType();\n        parser.parseArrow();\n        const destType = parser.parseType();\n        parser.resolveOperand(unresolvedSource, sourceType, result.operands);\n        parser.resolveOperand(unresolvedDest, destType, result.operands);\n        if (unresolvedPadding) {\n            parser.resolveOperand(unresolvedPadding, paddingType, result.operands);\n        }\n        for (const dynOp of dynamicTileOperands) {\n            parser.resolveOperand(dynOp, null, result.operands);\n        }\n        if (!(sourceType instanceof _.MemRefType)) {\n            result.addTypes([destType]);\n        }\n        return true;\n    }\n\n    parseUnpackOp(parser, result) {\n        const unresolvedSource = parser.parseOperand();\n        if (parser.parseOptionalKeyword('outer_dims_perm')) {\n            parser.parseEqual();\n            const outerDimsPerm = [];\n            parser.parseLSquare();\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    outerDimsPerm.push(parser.parseInteger('int64'));\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n            result.addAttribute('outer_dims_perm', outerDimsPerm);\n        }\n        parser.parseKeyword('inner_dims_pos');\n        parser.parseEqual();\n        const innerDimsPos = [];\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                innerDimsPos.push(parser.parseInteger('int64'));\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        result.addAttribute('inner_dims_pos', innerDimsPos);\n        parser.parseKeyword('inner_tiles');\n        parser.parseEqual();\n        const staticInnerTiles = [];\n        const dynamicTileOperands = [];\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                const dynOp = parser.parseOptionalOperand();\n                if (dynOp) {\n                    dynamicTileOperands.push(dynOp);\n                    staticInnerTiles.push(-9223372036854775808n); // ShapedType::kDynamic\n                } else {\n                    staticInnerTiles.push(parser.parseInteger('int64'));\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        result.addAttribute('static_inner_tiles', staticInnerTiles);\n        parser.parseKeyword('into');\n        const unresolvedDest = parser.parseOperand();\n        parser.parseOptionalAttrDict(result.attributes);\n        parser.parseColon();\n        const sourceType = parser.parseType();\n        parser.parseArrow();\n        const destType = parser.parseType();\n        parser.resolveOperand(unresolvedSource, sourceType, result.operands);\n        parser.resolveOperand(unresolvedDest, destType, result.operands);\n        for (const dynOp of dynamicTileOperands) {\n            parser.resolveOperand(dynOp, null, result.operands);\n        }\n        if (!(sourceType instanceof _.MemRefType)) {\n            result.addTypes([destType]);\n        }\n        return true;\n    }\n};\n\n_.ONNXDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'onnx');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'onnx.Constant') {\n            parser.parseOptionalAttrDict(result.attributes);\n            if (result.attributes.size === 0) {\n                const value = parser.parseOptionalAttribute();\n                if (value) {\n                    const name = value instanceof _.SparseElementsAttr ? 'sparse_value' : 'value';\n                    result.addAttribute(name, value);\n                    result.addTypes([value.type]);\n                    return true;\n                }\n            }\n            result.addTypes([parser.parseColonType()]);\n            return true;\n        }\n        if (result.op === 'onnx.ConstantOfShape') {\n            parser.parseLParen();\n            const unresolved = parser.parseOperand();\n            parser.parseRParen();\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            parser.parseLParen();\n            const inputType = parser.parseType();\n            parser.resolveOperand(unresolved, inputType, result.operands);\n            parser.parseRParen();\n            parser.parseArrow();\n            const outputType = parser.parseType();\n            result.addTypes([outputType]);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.KrnlDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'krnl');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'krnl.define_loops') {\n            const count = parser.parseOptionalInteger();\n            if (count !== null) {\n                result.addAttribute('num_loops', parseInt(count, 10));\n                const loopType = new _.Type('!krnl.loop');\n                const types = Array(count).fill(loopType);\n                result.addTypes(types);\n            }\n            return true;\n        }\n        if (result.op === 'krnl.get_linear_offset_index') {\n            const unresolvedOperands = [];\n            const staticIndices = [];\n            const memref = parser.parseOperand();\n            unresolvedOperands.push(memref);\n            if (parser.parseOptionalKeyword('at')) {\n                parser.parseLSquare();\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        // Indices can be either SSA values (%arg) or integer constants (0, 10, etc.)\n                        const operand = parser.parseOptionalOperand();\n                        if (operand) {\n                            unresolvedOperands.push(operand);\n                            staticIndices.push(-9223372036854775808n); // ShapedType::kDynamic marker\n                        } else {\n                            staticIndices.push(parser.parseInteger('int64'));\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                if (staticIndices.length > 0) {\n                    result.addAttribute('static_indices', staticIndices);\n                }\n            }\n            let type = null;\n            if (parser.parseOptionalColon()) {\n                type = parser.parseType();\n            }\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, type, result.operands);\n            }\n            result.addTypes([new _.IndexType()]);\n            return true;\n        }\n        if (result.op === 'krnl.prefetch') {\n            const unresolvedOperands = [];\n            const memref = parser.parseOperand();\n            unresolvedOperands.push(memref);\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const index = parser.parseOperand();\n                        unresolvedOperands.push(index);\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n            }\n            parser.parseComma();\n            const readOrWrite = parser.parseKeyword();\n            result.addAttribute('isWrite', readOrWrite === 'write');\n            parser.parseComma();\n            parser.parseKeyword('locality');\n            parser.parseLess();\n            const localityHint = parser.parseInteger();\n            result.addAttribute('localityHint', localityHint);\n            parser.parseGreater();\n            parser.parseComma();\n            const cacheType = parser.parseKeyword();\n            result.addAttribute('isDataCache', cacheType === 'data');\n            parser.parseOptionalAttrDict(result.attributes);\n            let type = null;\n            if (parser.parseOptionalColon()) {\n                type = parser.parseType();\n            }\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, type, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'krnl.iterate') {\n            const unresolvedOperands = parser.parseOperandList('paren');\n            for (const operand of unresolvedOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n            result.addAttribute('num_optimized_loops', result.operands.length);\n            const indexType = new _.IndexType();\n            const boundMaps = [];\n            const inductionVarRefs = [];\n            parser.parseKeyword('with');\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                parser.parseCommaSeparatedList('none', () => {\n                    const loop = parser.parseOperand();\n                    parser.resolveOperand(loop, null, result.operands);\n                    parser.parseArrow();\n                    const inductionVar = parser.parseOperand();\n                    inductionVarRefs.push(inductionVar);\n                    parser.parseEqual();\n                    for (let i = 0; i < 2; i++) {\n                        if (i > 0) {\n                            parser.parseKeyword('to');\n                        }\n                        parser.parseOptionalKeyword(i === 0 ? 'max' : 'min');\n                        const boundAttr = parser.parseAttribute();\n                        if (boundAttr instanceof _.AffineMapAttr || (boundAttr && boundAttr.value instanceof _.AffineMap)) {\n                            boundMaps.push(boundAttr);\n                            parser.parseDimAndSymbolList(result.operands);\n                        } else {\n                            const op = parser.parseOptionalOperand();\n                            if (op) {\n                                parser.resolveOperand(op, indexType, result.operands);\n                            }\n                            boundMaps.push(boundAttr);\n                        }\n                    }\n                });\n                parser.parseRParen();\n            }\n            result.addAttribute('bounds', boundMaps);\n            const entryArgs = inductionVarRefs.map((ref) => ({ value: ref, type: indexType }));\n            if (parser.parseOptionalKeyword('iter_args')) {\n                const iterOperands = [];\n                const iterArgs = [];\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        iterArgs.push(parser.parseOperand());\n                        parser.parseEqual();\n                        iterOperands.push(parser.parseOperand());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n                const iterTypes = parser.parseOptionalArrowTypeList();\n                result.addTypes(iterTypes);\n                for (let i = 0; i < iterArgs.length; i++) {\n                    const type = i < iterTypes.length ? iterTypes[i] : null;\n                    if (type) {\n                        parser.resolveOperand(iterOperands[i], type, result.operands);\n                    }\n                    entryArgs.push({ value: iterArgs[i], type });\n                }\n            }\n            const region = {};\n            parser.parseRegion(region, entryArgs);\n            result.regions = [region];\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.hlo.MhloDialect = class extends _.hlo.HLODialect {\n\n    constructor(operations) {\n        super(operations, 'mhlo');\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (opInfo.metadata && opInfo.metadata.parser && opInfo.metadata.parser.includes('parseOneResultSameOperandTypeOp')) {\n            return this.parseOneResultSameOperandTypeOp(parser, result);\n        }\n        if (result.op === 'mhlo.constant') {\n            if (parser.parseOptionalLParen() && parser.parseOptionalRParen()) {\n                parser.parseOptionalAttrDict(result.attributes);\n                if (parser.parseOptionalColon()) {\n                    parser.parseLParen();\n                    parser.parseRParen();\n                    parser.parseArrow();\n                    const type = parser.parseType();\n                    result.addTypes([type]);\n                }\n            } else {\n                parser.parseOptionalAttrDict(result.attributes);\n                const value = parser.parseAttribute();\n                if (value) {\n                    result.addAttribute('value', value);\n                    if (value.type && result.types.length === 0) {\n                        result.addTypes([value.type]);\n                    }\n                }\n                if (result.types.length === 0) {\n                    result.addTypes(parser.parseOptionalColonTypeList());\n                }\n            }\n            return true;\n        }\n        if (result.op === 'mhlo.reduce') {\n            return super.parseReduceOp(parser, result, (dims) => dims, 'mhlo.return');\n        }\n        if (result.op === 'mhlo.scan') {\n            return super.parseScanOp(parser, result, 'mhlo.return');\n        }\n        if (result.op === 'mhlo.while') {\n            return super.parseWhileOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseOneResultSameOperandTypeOp(parser, result) {\n        const unresolvedOperands = parser.parseOperandList();\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            const types = unresolvedOperands.map(() => type);\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            if (result.types.length > 0) {\n                result.types[0] = type;\n            }\n        } else {\n            for (const operand of unresolvedOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n        }\n        return true;\n    }\n};\n\n_.hlo.ChloDialect = class extends _.hlo.HLODialect {\n\n    constructor(operations) {\n        super(operations, 'chlo');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'chlo.scan') {\n            return super.parseScanOp(parser, result, 'stablehlo.return');\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.THLODialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'thlo');\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (opInfo.metadata.assemblyFormat) {\n            return super.parseOperation(parser, result);\n        }\n        if (parser.parseOptionalKeyword('ins')) {\n            parser.parseLParen();\n            for (let insOp = parser.parseOptionalOperand(); insOp; insOp = parser.parseOptionalOperand()) {\n                const operand = insOp;\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.resolveOperand(operand, type, result.operands);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n            }\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalKeyword('outs')) {\n            parser.parseLParen();\n            for (let outsOp = parser.parseOptionalOperand(); outsOp; outsOp = parser.parseOptionalOperand()) {\n                const operand = outsOp;\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.resolveOperand(operand, type, result.operands);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n            }\n            parser.parseRParen();\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        const blockArguments = [];\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const value = parser.parseOperand();\n                    parser.parseColon();\n                    const type = parser.parseType();\n                    blockArguments.push({ value, type });\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        if (parser.parseOptionalLBrace()) {\n            const region = { blocks: [] };\n            const block = { operations: [], arguments: blockArguments };\n            while (!parser.parseOptionalRBrace()) {\n                const operation = parser.parseOperation();\n                block.operations.push(_.Operation.create(operation));\n            }\n            region.blocks.push(block);\n            result.regions.push(region);\n        }\n        return true;\n    }\n};\n\n_.quant = {};\n\n_.quant.QuantDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'quant');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic === 'uniform' || mnemonic === 'calibrated' || mnemonic === 'any') {\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n};\n\n_.TosaDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tosa');\n        this._enumOps = new Map([\n            ['tosa.rescale', 'rounding_mode'],\n            ['tosa.apply_scale', 'rounding_mode'],\n            ['tosa.resize', 'mode'],\n            ['tosa.argmax', 'nan_mode'],\n            ['tosa.max_pool2d', 'nan_mode'],\n            ['tosa.clamp', 'nan_mode'],\n            ['tosa.maximum', 'nan_mode'],\n            ['tosa.minimum', 'nan_mode'],\n            ['tosa.reduce_max', 'nan_mode'],\n            ['tosa.reduce_min', 'nan_mode'],\n            ['tosa.matmul_t_block_scaled', 'block_size'],\n            ['tosa.cast_from_block_scaled', 'block_size'],\n            ['tosa.cast_to_block_scaled', 'block_size'],\n            ['tosa.conv2d_block_scaled', 'block_size'],\n        ]);\n        this.registerCustomDirective('VariableOpTypeOrInitialValue', this.parseVariableOpTypeOrInitialValue.bind(this));\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic === 'shape') {\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        if (mnemonic === 'mxint8') {\n            return new _.Type(`!${dialect}.mxint8`);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tosa.cond_if') {\n            return this.parseIfOp(parser, result);\n        }\n        if (result.op === 'tosa.while_loop') {\n            return this.parseWhileOp(parser, result);\n        }\n        if (this._enumOps.has(result.op)) {\n            return this.parseWithEnumHandling(parser, result, this._enumOps.get(result.op));\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseIfOp(parser, result) {\n        const thenRegion = result.addRegion();\n        const elseRegion = result.addRegion();\n        const cond = parser.parseOperand();\n        const regionArgs = [];\n        const operands = [];\n        const hasAssignment = parser.parseOptionalAssignmentList(regionArgs, operands);\n        parser.parseColon();\n        const condType = parser.parseType();\n        parser.resolveOperand(cond, condType, result.operands);\n        if (hasAssignment) {\n            const functionType = parser.parseType();\n            result.addTypes(functionType.results);\n            parser.resolveOperands(operands, functionType.inputs, result.operands);\n        } else {\n            result.addTypes(parser.parseOptionalArrowTypeList());\n        }\n        parser.parseRegion(thenRegion);\n        if (parser.parseOptionalKeyword('else')) {\n            parser.parseRegion(elseRegion);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseWhileOp(parser, result) {\n        const regionArgs = [];\n        const operands = [];\n        parser.parseOptionalAssignmentList(regionArgs, operands);\n        const functionType = parser.parseColonType();\n        result.addTypes(functionType.results);\n        parser.resolveOperands(operands, functionType.inputs, result.operands);\n        for (let i = 0; i < regionArgs.length; i++) {\n            regionArgs[i].type = functionType.inputs[i];\n        }\n        const condRegion = result.addRegion();\n        parser.parseRegion(condRegion, regionArgs);\n        parser.parseKeyword('do');\n        const bodyRegion = result.addRegion();\n        parser.parseRegion(bodyRegion);\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        return true;\n    }\n\n    parseAttrEntryWithEnumHandling(parser, attrs, enumKey) {\n        const name = parser.parseKeyword();\n        parser.parseEqual();\n        if (name === enumKey) {\n            const kw = parser.parseOptionalKeyword();\n            if (kw) {\n                attrs.set(name, kw);\n                return;\n            }\n        }\n        const attr = parser.parseAttribute();\n        attrs.set(name, attr);\n    }\n\n    parseWithEnumHandling(parser, result, enumKey) {\n        const operands = [];\n        do {\n            operands.push(parser.parseOperand());\n        } while (parser.parseOptionalComma());\n        const attrs = new Map();\n        if (parser.parseOptionalLBrace()) {\n            if (!parser.parseOptionalRBrace()) {\n                do {\n                    this.parseAttrEntryWithEnumHandling(parser, attrs, enumKey);\n                } while (parser.parseOptionalComma());\n                parser.parseRBrace();\n            }\n        }\n        parser.parseColon();\n        const fnTy = parser.parseType();\n        parser.resolveOperands(operands, fnTy.inputs, result.operands);\n        result.addTypes(fnTy.results);\n        for (const [name, value] of attrs) {\n            result.attributes.set(name, value);\n        }\n        return true;\n    }\n\n    parseVariableOpTypeOrInitialValue(parser, op /*, args */) {\n        if (parser.parseOptionalEqual()) {\n            const initialValue = parser.parseAttribute();\n            op.addAttribute('initial_value', initialValue);\n        } else if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            op.addAttribute('type', type);\n        }\n    }\n};\n\n_.IRDLDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'irdl');\n        this.registerCustomDirective('SingleBlockRegion', this.parseSingleBlockRegion.bind(this));\n        this.registerCustomDirective('NamedValueList', this.parseNamedValueList.bind(this));\n        this.registerCustomDirective('NamedValueListWithVariadicity', this.parseNamedValueListWithVariadicity.bind(this));\n        this.registerCustomDirective('AttributesOp', this.parseAttributesOp.bind(this));\n    }\n\n    parseSingleBlockRegion(parser, op, /* args */) {\n        parser.parseOptionalRegion(op.addRegion());\n    }\n\n    parseNamedValueList(parser, op, argsAttrName, namesAttrName) {\n        const argValues = [];\n        const nameValues = [];\n        const parseOne = () => {\n            const name = parser.parseKeyword();\n            nameValues.push(name);\n            parser.parseColon();\n            const value = parser.parseOperand();\n            argValues.push(value);\n            return value;\n        };\n        parser.parseCommaSeparatedList('paren', parseOne);\n        if (argsAttrName && namesAttrName) {\n            // args contains SSA values (%0, %1, ...) - resolve and add as operands\n            for (const value of argValues) {\n                parser.resolveOperand(value, null, op.operands);\n            }\n            op.addAttribute(namesAttrName, nameValues);\n        }\n    }\n\n    parseNamedValueListWithVariadicity(parser, op, argsAttrName, namesAttrName, variadicityAttrName) {\n        const argValues = [];\n        const nameValues = [];\n        const variadicityValues = [];\n        const parseOne = () => {\n            const variadicity = parser.parseOptionalKeyword(['single', 'optional', 'variadic']);\n            const name = parser.parseKeyword();\n            nameValues.push(name);\n            parser.parseColon();\n            const value = parser.parseOperand();\n            argValues.push(value);\n            variadicityValues.push(variadicity || 'single');\n            return value;\n        };\n        parser.parseCommaSeparatedList('paren', parseOne);\n        if (argsAttrName && namesAttrName) {\n            // args contains SSA values (%0, %1, ...) - resolve and add as operands\n            for (const value of argValues) {\n                parser.resolveOperand(value, null, op.operands);\n            }\n            op.addAttribute(namesAttrName, nameValues);\n            if (variadicityAttrName) {\n                op.addAttribute(variadicityAttrName, variadicityValues);\n            }\n        }\n    }\n\n    parseAttributesOp(parser, op, argsAttrName, namesAttrName) {\n        const argValues = [];\n        const nameValues = [];\n        if (parser.parseOptionalLBrace()) {\n            if (!parser.parseOptionalRBrace()) {\n                do {\n                    const name = parser.parseString();\n                    nameValues.push(name);\n                    parser.parseEqual();\n                    const value = parser.parseOperand();\n                    argValues.push(value);\n                } while (parser.parseOptionalComma());\n                parser.parseRBrace();\n            }\n        }\n        if (argsAttrName && namesAttrName) {\n            for (const value of argValues) {\n                parser.resolveOperand(value, null, op.operands);\n            }\n            op.addAttribute(namesAttrName, nameValues);\n        }\n    }\n};\n\n_.XeGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xegpu');\n        this.registerCustomDirective('OptionalDynamicIndexList', this.parseOptionalDynamicIndexList.bind(this));\n    }\n\n    parseOptionalDynamicIndexList(parser, op, dynamicAttrName, staticAttrName) {\n        const indices = [];\n        const dynamicValues = [];\n\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    const operand = parser.parseOptionalOperand();\n                    if (operand) {\n                        dynamicValues.push(operand);\n                        indices.push(-9223372036854775808n);\n                    } else {\n                        const intVal = parser.parseOptionalInteger('int64');\n                        if (intVal === null) {\n                            break;\n                        }\n                        indices.push(intVal);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n\n            if (dynamicAttrName && staticAttrName) {\n                // Dynamic values are SSA operands (%0, %1, ...) - resolve and add as operands\n                for (const value of dynamicValues) {\n                    parser.resolveOperand(value, null, op.operands);\n                }\n                // Static indices are compile-time constants - add as attribute\n                if (indices.length > 0) {\n                    op.addAttribute(staticAttrName, indices);\n                }\n            }\n        }\n    }\n};\n\n_.ShardDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'shard');\n        this.registerCustomDirective('DimensionList', this.parseDimensionList.bind(this));\n    }\n\n    parseDimensionList(parser, op, attrName) {\n        if (parser.parseOptionalLSquare()) {\n            parser.parseOptionalRSquare();\n            op.addAttribute(attrName, []);\n            return;\n        }\n        const dimInfo = parser.parseDimensionList(true, false);\n        if (attrName) {\n            op.addAttribute(attrName, dimInfo.dimensions);\n        }\n    }\n};\n\n_.spirv = {};\n\n_.spirv.RuntimeArrayType = class extends _.Type {\n\n    constructor(elementType, stride) {\n        super(null);\n        this.elementType = elementType;\n        this.stride = stride || 0;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const elementType = parser.parseType();\n        let stride = 0;\n        if (parser.parseOptionalComma()) {\n            parser.parseKeyword('stride');\n            parser.parseEqual();\n            stride = parser.parseInteger();\n        }\n        parser.parseGreater();\n        return new _.spirv.RuntimeArrayType(elementType, stride);\n    }\n\n    toString() {\n        const elemStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;\n        if (this.stride) {\n            return `!spirv.rtarray<${elemStr}, stride=${this.stride}>`;\n        }\n        return `!spirv.rtarray<${elemStr}>`;\n    }\n};\n\n_.spirv.StructType = class extends _.Type {\n\n    constructor(memberTypes, offsetInfo, memberDecorations) {\n        super(null);\n        this.memberTypes = memberTypes;\n        this.offsetInfo = offsetInfo;\n        this.memberDecorations = memberDecorations;\n    }\n\n    toString() {\n        const members = this.memberTypes.map((t) => t?.toString ? t.toString() : t).join(', ');\n        if (this.offsetInfo && this.offsetInfo.length > 0) {\n            const offsets = this.offsetInfo.join(', ');\n            return `!spirv.struct<(${members}), offset: [${offsets}]>`;\n        }\n        return `!spirv.struct<(${members})>`;\n    }\n};\n\n_.spirv.PointerType = class extends _.Type {\n\n    constructor(pointeeType, storageClass) {\n        super(null);\n        this.pointeeType = pointeeType;\n        this.storageClass = storageClass;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const pointeeType = parser.parseType();\n        parser.parseComma();\n        const storageClass = parser.parseKeyword();\n        parser.parseGreater();\n        return new _.spirv.PointerType(pointeeType, storageClass);\n    }\n\n    toString() {\n        const pointeeStr = this.pointeeType?.toString ? this.pointeeType.toString() : this.pointeeType;\n        return `!spirv.ptr<${pointeeStr}, ${this.storageClass}>`;\n    }\n};\n\n_.spirv.SPIRVDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'spirv');\n        this.typesWithOptionalParams = new Set(['sampler', 'sampled_image', 'matrix', 'image', 'rtarray', 'ptr', 'array', 'struct', 'coopmatrix']);\n        this.registerCustomType('SPIRV_Type', (parser) => parser.parseType());\n        this.registerCustomDirective('ImageOperands', this.parseImageOperands.bind(this));\n        this.registerCustomDirective('SwitchOpCases', this.parseSwitchOpCases.bind(this));\n        this.registerCustomDirective('SPIRV_I32_1DArmTensor', this.parseSPIRV_I32_1DArmTensor.bind(this));\n        this.registerCustomAttribute('SPIRV_ScopeAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('SPIRV_MemorySemanticsAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('SPIRV_MemoryAccessAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('SPIRV_GroupOperationAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('SPIRV_KHR_CooperativeMatrixLayoutAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('SPIRV_KHR_CooperativeMatrixOperandsAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('SPIRV_TosaExtNaNPropagationModeAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n    }\n\n    parseSwitchOpCases(parser, result) {\n        if (!parser.parseOptionalKeyword('default')) {\n            return;\n        }\n        if (!parser.parseOptionalColon()) {\n            return;\n        }\n        const defaultDestination = parser.parseOptionalSuccessor();\n        if (!defaultDestination) {\n            return;\n        }\n        const defaultDest = { label: defaultDestination, arguments: [] };\n        if (parser.parseOptionalLParen()) {\n            const defaultOperands = parser.parseOperandList();\n            for (const value of defaultOperands) {\n                defaultDest.arguments.push({ value });\n            }\n            const defaultTypes = parser.parseOptionalColonTypeList();\n            for (let idx = 0; idx < defaultTypes.length && idx < defaultDest.arguments.length; idx++) {\n                defaultDest.arguments[idx].type = defaultTypes[idx];\n            }\n            parser.parseOptionalRParen();\n        }\n        result.successors = result.successors || [];\n        result.successors.push(defaultDest);\n        const caseValues = [];\n        while (parser.parseOptionalComma()) {\n            const value = parser.parseOptionalInteger();\n            if (value === null) {\n                break;\n            }\n            caseValues.push(value);\n            if (!parser.parseOptionalColon()) {\n                break;\n            }\n            const caseDestination = parser.parseOptionalSuccessor();\n            if (!caseDestination) {\n                break;\n            }\n            const caseDest = { label: caseDestination, arguments: [] };\n            if (parser.parseOptionalLParen()) {\n                const caseOperands = parser.parseOperandList();\n                for (const argValue of caseOperands) {\n                    caseDest.arguments.push({ value: argValue });\n                }\n                const caseTypes = parser.parseOptionalColonTypeList();\n                for (let idx = 0; idx < caseTypes.length && idx < caseDest.arguments.length; idx++) {\n                    caseDest.arguments[idx].type = caseTypes[idx];\n                }\n                parser.parseOptionalRParen();\n            }\n            result.successors.push(caseDest);\n        }\n        if (caseValues.length > 0) {\n            result.addAttribute('literals', caseValues);\n        }\n    }\n\n    parseImageOperands(parser, op) {\n        if (parser.parseOptionalLSquare()) {\n            const value = parser.parseAttribute();\n            op.addAttribute('image_operands', value);\n            parser.parseRSquare();\n        }\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (mnemonic === 'ptr') {\n                return _.spirv.PointerType.parse(parser);\n            }\n            if (mnemonic === 'rtarray') {\n                return _.spirv.RuntimeArrayType.parse(parser);\n            }\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        // spv.Constant value : type\n        if (result.op === 'spirv.Constant' || result.op === 'spv.Constant') {\n            const value = parser.parseAttribute();\n            result.addAttribute('value', value);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addTypes([type]);\n            } else if (value && value.type) {\n                result.addTypes([value.type]);\n            }\n            return true;\n        }\n        // SPIR-V comparison operations: result is i1 (or vector<Nxi1> for vector operands)\n        const spirvCompareOps = new Set([\n            'spirv.SLessThan', 'spv.SLessThan',\n            'spirv.SLessThanEqual', 'spv.SLessThanEqual',\n            'spirv.SGreaterThan', 'spv.SGreaterThan',\n            'spirv.SGreaterThanEqual', 'spv.SGreaterThanEqual',\n            'spirv.ULessThan', 'spv.ULessThan',\n            'spirv.ULessThanEqual', 'spv.ULessThanEqual',\n            'spirv.UGreaterThan', 'spv.UGreaterThan',\n            'spirv.UGreaterThanEqual', 'spv.UGreaterThanEqual',\n            'spirv.IEqual', 'spv.IEqual',\n            'spirv.INotEqual', 'spv.INotEqual',\n            'spirv.FOrdEqual', 'spv.FOrdEqual',\n            'spirv.FOrdNotEqual', 'spv.FOrdNotEqual',\n            'spirv.FOrdLessThan', 'spv.FOrdLessThan',\n            'spirv.FOrdLessThanEqual', 'spv.FOrdLessThanEqual',\n            'spirv.FOrdGreaterThan', 'spv.FOrdGreaterThan',\n            'spirv.FOrdGreaterThanEqual', 'spv.FOrdGreaterThanEqual',\n            'spirv.FUnordEqual', 'spv.FUnordEqual',\n            'spirv.FUnordNotEqual', 'spv.FUnordNotEqual',\n            'spirv.FUnordLessThan', 'spv.FUnordLessThan',\n            'spirv.FUnordLessThanEqual', 'spv.FUnordLessThanEqual',\n            'spirv.FUnordGreaterThan', 'spv.FUnordGreaterThan',\n            'spirv.FUnordGreaterThanEqual', 'spv.FUnordGreaterThanEqual'\n        ]);\n        if (spirvCompareOps.has(result.op)) {\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalColon()) {\n                const operandType = parser.parseType();\n                parser.resolveOperands(unresolvedOperands, [operandType, operandType], result.operands);\n                // Result type is i1 for scalar, vector<Nxi1> for vector\n                if (operandType instanceof _.VectorType) {\n                    result.addTypes([new _.VectorType(operandType.shape, new _.IntegerType('i1'), operandType.scalableDims)]);\n                } else {\n                    result.addTypes([new _.IntegerType('i1')]);\n                }\n            } else {\n                parser.resolveOperands(unresolvedOperands, [null, null], result.operands);\n                result.addTypes([new _.IntegerType('i1')]);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        // Operations with '->' in their assembly format should use assembly format parsing\n        const arrowFormatOps = new Set([\n            'spirv.GL.Distance', 'spirv.GL.FMix', 'spirv.GL.FrexpStruct', 'spirv.GL.Ldexp',\n            'spirv.GL.Length', 'spirv.GL.PackHalf2x16', 'spirv.GL.UnpackHalf2x16',\n            'spirv.GL.PackSnorm4x8', 'spirv.GL.UnpackSnorm4x8',\n            'spirv.GLSL.Distance', 'spirv.GLSL.FMix', 'spirv.GLSL.FrexpStruct', 'spirv.GLSL.Ldexp',\n            'spirv.GLSL.Length', 'spirv.GLSL.PackHalf2x16', 'spirv.GLSL.UnpackHalf2x16',\n            'spirv.GLSL.PackSnorm4x8', 'spirv.GLSL.UnpackSnorm4x8',\n            'spv.GL.Distance', 'spv.GL.FMix', 'spv.GL.FrexpStruct', 'spv.GL.Ldexp',\n            'spv.GL.Length', 'spv.GL.PackHalf2x16', 'spv.GL.UnpackHalf2x16',\n            'spv.GL.PackSnorm4x8', 'spv.GL.UnpackSnorm4x8',\n            'spv.GLSL.Distance', 'spv.GLSL.FMix', 'spv.GLSL.FrexpStruct', 'spv.GLSL.Ldexp',\n            'spv.GLSL.Length', 'spv.GLSL.PackHalf2x16', 'spv.GLSL.UnpackHalf2x16',\n            'spv.GLSL.PackSnorm4x8', 'spv.GLSL.UnpackSnorm4x8'\n        ]);\n        if ((result.op.startsWith('spirv.GLSL.') || result.op.startsWith('spv.GLSL.') || result.op.startsWith('spirv.GL.') || result.op.startsWith('spv.GL.')) && !arrowFormatOps.has(result.op)) {\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                for (const unresolvedOp of unresolvedOperands) {\n                    parser.resolveOperand(unresolvedOp, type, result.operands);\n                }\n                result.types.push(type);\n            } else {\n                for (const unresolvedOp of unresolvedOperands) {\n                    parser.resolveOperand(unresolvedOp, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'spirv.SpecConstantComposite' || result.op === 'spv.SpecConstantComposite') {\n            parser.parseSymbolName('sym_name', result.attributes);\n            parser.parseLParen();\n            const constituents = [];\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const sym = parser.parseOptionalSymbolName();\n                    if (sym) {\n                        constituents.push(sym);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            result.addAttribute('constituents', constituents);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addAttribute('type', type.toString());\n            }\n            return true;\n        }\n        if (result.op.endsWith('.SpecConstantCompositeReplicate')) {\n            parser.parseSymbolName('sym_name', result.attributes);\n            parser.parseLParen();\n            const constituent = parser.parseOptionalSymbolName();\n            if (constituent) {\n                result.addAttribute('constituent', constituent);\n            }\n            parser.parseRParen();\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addAttribute('type', type.toString());\n            }\n            return true;\n        }\n        if (result.op === 'spirv.SpecConstantOperation' || result.op === 'spv.SpecConstantOperation') {\n            parser.parseKeyword('wraps');\n            const wrappedOp = parser.parseGenericOperation();\n            if (wrappedOp) {\n                const region = { blocks: [{ operations: [wrappedOp] }] };\n                result.regions.push(region);\n                if (wrappedOp.results && wrappedOp.results.length > 0) {\n                    result.addTypes([wrappedOp.results[0].type]);\n                }\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (result.op === 'spirv.Constant' || result.op === 'spv.Constant') {\n            const value = parser.parseAttribute();\n            if (parser.parseOptionalColon()) {\n                const valueType = parser.parseType();\n                result.addAttribute('value', { ...value, valueType });\n            } else {\n                result.addAttribute('value', value);\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addTypes([type]);\n            }\n            return true;\n        }\n        if (result.op === 'spirv.Load' || result.op === 'spv.Load') {\n            const storageClass = parser.parseString();\n            result.addAttribute('storage_class', storageClass);\n            const ptrOperand = parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                const memoryAccess = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const str = parser.parseOptionalString();\n                        if (str === null) {\n                            const intVal = parser.parseOptionalInteger();\n                            if (intVal === null) {\n                                break;\n                            }\n                            memoryAccess.push(String(intVal));\n                        } else {\n                            memoryAccess.push(str);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                if (memoryAccess.length > 0) {\n                    result.addAttribute('memory_access', memoryAccess.join(', '));\n                }\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                parser.resolveOperand(ptrOperand, null, result.operands);\n                result.types.push(type);\n            } else {\n                parser.resolveOperand(ptrOperand, null, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'spirv.CompositeExtract' || result.op === 'spv.CompositeExtract') {\n            const compositeOperand = parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                const indices = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const intVal = parser.parseOptionalInteger();\n                        if (intVal !== null) {\n                            indices.push(intVal);\n                        }\n                        if (parser.parseOptionalColon()) {\n                            parser.parseType();\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                result.addAttribute('indices', indices);\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                parser.resolveOperand(compositeOperand, null, result.operands);\n                result.types.push(type);\n            } else {\n                parser.resolveOperand(compositeOperand, null, result.operands);\n            }\n            return true;\n        }\n        // Handle AccessChain with old syntax (no -> for result type)\n        // Uses compatibility flag because assemblyFormat includes `->` which is not present in old files\n        if (result.op === 'spirv.AccessChain' || result.op === 'spv.AccessChain') {\n            result.compatibility = true;\n            const unresolvedOperands = [];\n            unresolvedOperands.push(parser.parseOperand());\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        unresolvedOperands.push(parser.parseOperand());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const basePtrType = parser.parseType();\n                const types = [basePtrType];\n                while (parser.parseOptionalComma()) {\n                    types.push(parser.parseType());\n                }\n                parser.resolveOperands(unresolvedOperands, types, result.operands);\n                // Check for optional -> result_type (newer syntax)\n                if (parser.parseOptionalArrow()) {\n                    const resultType = parser.parseType();\n                    result.addTypes([resultType]);\n                } else {\n                    // Old syntax without explicit result type - use base pointer type as fallback\n                    // (In SPIR-V, AccessChain result is a pointer to a sub-element, but\n                    // for visualization purposes the base ptr type is sufficient)\n                    result.addTypes([basePtrType]);\n                }\n            } else {\n                for (const unresolvedOp of unresolvedOperands) {\n                    parser.resolveOperand(unresolvedOp, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'spirv.Variable' || result.op === 'spv.Variable') {\n            let unresolvedInit = null;\n            if (parser.parseOptionalKeyword('init')) {\n                parser.parseLParen();\n                unresolvedInit = parser.parseOperand();\n                parser.parseRParen();\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addTypes([type]);\n                if (unresolvedInit) {\n                    // The init value type should match the element type of the pointer result\n                    parser.resolveOperand(unresolvedInit, null, result.operands);\n                }\n            } else if (unresolvedInit) {\n                parser.resolveOperand(unresolvedInit, null, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'spirv.Store' || result.op === 'spv.Store') {\n            const storageClass = parser.parseString();\n            result.addAttribute('storage_class', storageClass);\n            const unresolvedOperands = [];\n            unresolvedOperands.push(parser.parseOperand());\n            parser.parseComma();\n            unresolvedOperands.push(parser.parseOperand());\n            if (parser.parseOptionalLSquare()) {\n                const memoryAccess = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const str = parser.parseOptionalString();\n                        if (str === null) {\n                            const intVal = parser.parseOptionalInteger();\n                            if (intVal === null) {\n                                break;\n                            }\n                            memoryAccess.push(String(intVal));\n                        } else {\n                            memoryAccess.push(str);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                if (memoryAccess.length > 0) {\n                    result.addAttribute('memory_access', memoryAccess.join(', '));\n                }\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                parser.resolveOperands(unresolvedOperands, [type, type], result.operands);\n            } else {\n                for (const unresolvedOp of unresolvedOperands) {\n                    parser.resolveOperand(unresolvedOp, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'spirv.CompositeInsert' || result.op === 'spv.CompositeInsert') {\n            const unresolvedOperands = [];\n            unresolvedOperands.push(parser.parseOperand());\n            parser.parseComma();\n            unresolvedOperands.push(parser.parseOperand());\n            if (parser.parseOptionalLSquare()) {\n                const indices = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const intVal = parser.parseOptionalInteger();\n                        if (intVal !== null) {\n                            indices.push(intVal);\n                        }\n                        if (parser.parseOptionalColon()) {\n                            parser.parseType();\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                result.addAttribute('indices', indices);\n            }\n            if (parser.parseOptionalColon()) {\n                const objType = parser.parseType();\n                parser.resolveOperand(unresolvedOperands[0], objType, result.operands);\n                if (parser.parseOptionalKeyword('into')) {\n                    const compositeType = parser.parseType();\n                    parser.resolveOperand(unresolvedOperands[1], compositeType, result.operands);\n                    result.types.push(compositeType);\n                } else {\n                    parser.resolveOperand(unresolvedOperands[1], null, result.operands);\n                }\n            } else {\n                for (const unresolvedOp of unresolvedOperands) {\n                    parser.resolveOperand(unresolvedOp, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'spirv.BranchConditional' || result.op === 'spv.BranchConditional') {\n            const conditionOperand = parser.parseOperand();\n            parser.resolveOperand(conditionOperand, null, result.operands);\n            // Parse optional branch weights [trueWeight, falseWeight]\n            if (parser.parseOptionalLSquare()) {\n                const weights = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const intVal = parser.parseOptionalInteger();\n                        if (intVal !== null) {\n                            weights.push(String(intVal));\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                if (weights.length > 0) {\n                    result.addAttribute('branch_weights', weights);\n                }\n            }\n            parser.parseComma();\n            if (!result.successors) {\n                result.successors = [];\n            }\n            const trueLabel = parser.parseOptionalSuccessor();\n            const trueSucc = { label: trueLabel };\n            if (parser.parseOptionalLParen()) {\n                const trueOperands = parser.parseOperandList();\n                trueSucc.arguments = trueOperands.map((value) => ({ value }));\n                const trueTypes = parser.parseOptionalColonTypeList();\n                for (let idx = 0; idx < trueTypes.length && idx < trueSucc.arguments.length; idx++) {\n                    trueSucc.arguments[idx].type = trueTypes[idx];\n                }\n                parser.parseRParen();\n            }\n            result.successors.push(trueSucc);\n            parser.parseComma();\n            const falseLabel = parser.parseOptionalSuccessor();\n            const falseSucc = { label: falseLabel };\n            if (parser.parseOptionalLParen()) {\n                const falseOperands = parser.parseOperandList();\n                falseSucc.arguments = falseOperands.map((value) => ({ value }));\n                const falseTypes = parser.parseOptionalColonTypeList();\n                for (let idx = 0; idx < falseTypes.length && idx < falseSucc.arguments.length; idx++) {\n                    falseSucc.arguments[idx].type = falseTypes[idx];\n                }\n                parser.parseRParen();\n            }\n            result.successors.push(falseSucc);\n            return true;\n        }\n        if (result.op === 'spirv.CompositeConstruct' || result.op === 'spv.CompositeConstruct') {\n            result.compatibility = true;\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalColon()) {\n                if (parser.parseOptionalLParen()) {\n                    const types = parser.parseTypeList();\n                    parser.parseRParen();\n                    parser.parseArrow();\n                    parser.resolveOperands(unresolvedOperands, types, result.operands);\n                } else {\n                    for (const unresolvedOp of unresolvedOperands) {\n                        parser.resolveOperand(unresolvedOp, null, result.operands);\n                    }\n                }\n                const type = parser.parseType();\n                result.types.push(type);\n            } else {\n                for (const unresolvedOp of unresolvedOperands) {\n                    parser.resolveOperand(unresolvedOp, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'spirv.SpecConstant' || result.op === 'spv.SpecConstant') {\n            parser.parseSymbolName('sym_name', result.attributes);\n            if (parser.parseOptionalKeyword('spec_id')) {\n                parser.parseLParen();\n                const specId = parser.parseAttribute();\n                result.addAttribute('spec_id', specId);\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalEqual()) {\n                const defaultValue = parser.parseAttribute();\n                result.addAttribute('default_value', defaultValue);\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addAttribute('type', type);\n            }\n            return true;\n        }\n        if (result.op === 'spirv.module' || result.op === 'spv.module') {\n            const modSymName = parser.parseOptionalSymbolName();\n            if (modSymName) {\n                result.addAttribute('sym_name', modSymName);\n            }\n            const addressingModel = parser.parseOptionalKeyword();\n            if (addressingModel) {\n                result.addAttribute('addressing_model', addressingModel);\n            }\n            const memoryModel = parser.parseOptionalKeyword();\n            if (memoryModel) {\n                result.addAttribute('memory_model', memoryModel);\n            }\n            if (parser.parseOptionalKeyword('requires')) {\n                const vce = parser.parseAttribute();\n                result.addAttribute('vce_triple', vce);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'spirv.ARM.Graph') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'spirv.ARM.GraphEntryPoint') {\n            const fn = parser.parseOptionalSymbolName();\n            result.addAttribute('fn', fn);\n            const interfaceVars = [];\n            while (parser.parseOptionalComma()) {\n                const varSymbol = parser.parseOptionalSymbolName();\n                interfaceVars.push(varSymbol);\n            }\n            result.addAttribute('interface', interfaceVars);\n            return true;\n        }\n        if (result.op === 'spirv.func' || result.op === 'spv.func') {\n            const funcSymName = parser.parseOptionalSymbolName();\n            if (funcSymName) {\n                result.addAttribute('sym_name', funcSymName);\n            }\n            const argResult = parser.parseFunctionArgumentList();\n            const inputs = argResult.arguments.map((a) => a.type);\n            const results = [];\n            const resultAttrs = [];\n            if (parser.parseOptionalArrow()) {\n                parser.parseFunctionResultList(results, resultAttrs);\n            }\n            result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n            const funcControl = parser.parseOptionalString();\n            if (funcControl !== null) {\n                result.addAttribute('function_control', funcControl);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            // spirv.func is IsolatedFromAbove\n            parser.parseOptionalRegion(result.addRegion(), undefined, /* isIsolatedNameScope */ true);\n            return true;\n        }\n        if (result.op === 'spirv.GlobalVariable' || result.op === 'spv.GlobalVariable') {\n            const gvSymName = parser.parseOptionalSymbolName();\n            if (gvSymName) {\n                result.addAttribute('sym_name', gvSymName);\n            }\n            if (parser.parseOptionalKeyword('initializer')) {\n                parser.parseLParen();\n                const initSymbol = parser.parseOptionalSymbolName();\n                parser.parseRParen();\n                result.addAttribute('initializer', initSymbol);\n            }\n            if (parser.parseOptionalKeyword('built_in')) {\n                parser.parseLParen();\n                const builtIn = parser.parseString();\n                parser.parseRParen();\n                result.addAttribute('built_in', builtIn);\n            }\n            if (parser.parseOptionalKeyword('bind')) {\n                parser.parseLParen();\n                const binding = parser.parseInteger();\n                parser.parseOptionalComma();\n                const set = parser.parseInteger();\n                parser.parseRParen();\n                result.addAttribute('descriptor_set', set);\n                result.addAttribute('binding', binding);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.types = [type];\n            }\n            return true;\n        }\n        if (result.op === 'spirv.EntryPoint' || result.op === 'spv.EntryPoint') {\n            const executionModel = parser.parseOptionalString();\n            if (executionModel !== null) {\n                result.addAttribute('execution_model', executionModel);\n            }\n            result.operands = [];\n            let epSym = parser.parseOptionalSymbolName();\n            while (epSym) {\n                result.addAttribute('fn', new _.SymbolRefAttr(epSym));\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                epSym = parser.parseOptionalSymbolName();\n            }\n            return true;\n        }\n        if (result.op === 'spirv.ExecutionMode' || result.op === 'spv.ExecutionMode') {\n            const emSym = parser.parseOptionalSymbolName();\n            if (emSym) {\n                result.addAttribute('fn', new _.SymbolRefAttr(emSym));\n            }\n            const mode = parser.parseOptionalString();\n            if (mode !== null) {\n                result.addAttribute('execution_mode', mode);\n            }\n            const params = [];\n            while (parser.parseOptionalComma()) {\n                const value = parser.parseAttribute();\n                if (value) {\n                    params.push(value);\n                } else {\n                    break;\n                }\n            }\n            if (params.length > 0) {\n                result.addAttribute('values', params);\n            }\n            return true;\n        }\n        if (result.op === 'spirv.ExecutionModeId') {\n            const fnSym = parser.parseOptionalSymbolName();\n            if (fnSym) {\n                result.addAttribute('fn', new _.SymbolRefAttr(fnSym));\n            }\n            const mode = parser.parseOptionalString();\n            if (mode !== null) {\n                result.addAttribute('execution_mode', mode);\n            }\n            const values = [];\n            do {\n                const sym = parser.parseOptionalSymbolName();\n                if (!sym) {\n                    break;\n                }\n                values.push(new _.SymbolRefAttr(sym));\n            } while (parser.parseOptionalComma());\n            if (values.length > 0) {\n                result.addAttribute('values', values);\n            }\n            return true;\n        }\n        if (result.op === 'spirv.mlir.loop' || result.op === 'spv.mlir.loop' || result.op === 'spirv.mlir.selection' || result.op === 'spv.mlir.selection') {\n            if (parser.parseOptionalKeyword('control')) {\n                parser.parseLParen();\n                const controlValue = parser.parseOptionalKeyword();\n                result.addAttribute('selection_control', controlValue);\n                parser.parseRParen();\n            }\n            result.addTypes(parser.parseOptionalArrowTypeList());\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        // spirv.CompositeInsert with 'into' keyword\n        if (result.op === 'spirv.CompositeInsert' || result.op === 'spv.CompositeInsert') {\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalLSquare()) {\n                const indices = [];\n                while (!parser.parseOptionalRSquare()) {\n                    const index = parser.parseInteger();\n                    if (parser.parseOptionalColon()) {\n                        parser.parseType();\n                    }\n                    indices.push(index);\n                    parser.parseOptionalComma();\n                }\n                result.addAttribute('indices', indices);\n            }\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            if (parser.parseOptionalKeyword('into')) {\n                const resultType = parser.parseType();\n                result.types = [resultType];\n            }\n            return true;\n        }\n        const arithmeticExtendedOps = new Set([\n            'spirv.IAddCarry', 'spv.IAddCarry',\n            'spirv.ISubBorrow', 'spv.ISubBorrow',\n            'spirv.SMulExtended', 'spv.SMulExtended',\n            'spirv.UMulExtended', 'spv.UMulExtended'\n        ]);\n        if (arithmeticExtendedOps.has(result.op)) {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalColon()) {\n                const resultType = parser.parseType();\n                parser.resolveOperands(unresolvedOperands, [resultType, resultType], result.operands);\n                result.addTypes([resultType]);\n            } else {\n                for (const operand of unresolvedOperands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'spirv.INTEL.SubgroupBlockWrite' || result.op === 'spv.INTEL.SubgroupBlockWrite') {\n            const storageClass = parser.parseString();\n            result.addAttribute('storage_class', storageClass);\n            const ptrUnresolved = parser.parseOperand();\n            parser.parseComma();\n            const valueUnresolved = parser.parseOperand();\n            let ptrType = null;\n            let valueType = null;\n            if (parser.parseOptionalColon()) {\n                valueType = parser.parseType();\n                ptrType = new _.Type(`!spirv.ptr<${valueType}, ${storageClass}>`);\n            }\n            parser.resolveOperand(ptrUnresolved, ptrType, result.operands);\n            parser.resolveOperand(valueUnresolved, valueType, result.operands);\n            return true;\n        }\n        if ((result.op === 'spirv.CopyMemory' || result.op === 'spv.CopyMemory')) {\n            const targetStorageClass = parser.parseString();\n            result.addAttribute('target_storage_class', targetStorageClass);\n            const targetUnresolved = parser.parseOperand();\n            parser.parseComma();\n            const sourceStorageClass = parser.parseString();\n            result.addAttribute('source_storage_class', sourceStorageClass);\n            const sourceUnresolved = parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                const memoryAccess = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const str = parser.parseOptionalString();\n                        if (str === null) {\n                            const intVal = parser.parseOptionalInteger();\n                            if (intVal === null) {\n                                break;\n                            }\n                            memoryAccess.push(String(intVal));\n                        } else {\n                            memoryAccess.push(str);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                if (memoryAccess.length > 0) {\n                    result.addAttribute('memory_access', memoryAccess.join(', '));\n                }\n            }\n            if (parser.parseOptionalComma()) {\n                if (parser.parseOptionalLSquare()) {\n                    const sourceMemoryAccess = [];\n                    if (!parser.parseOptionalRSquare()) {\n                        do {\n                            const str = parser.parseOptionalString();\n                            if (str === null) {\n                                const intVal = parser.parseOptionalInteger();\n                                if (intVal === null) {\n                                    break;\n                                }\n                                sourceMemoryAccess.push(String(intVal));\n                            } else {\n                                sourceMemoryAccess.push(str);\n                            }\n                        } while (parser.parseOptionalComma());\n                        parser.parseRSquare();\n                    }\n                    if (sourceMemoryAccess.length > 0) {\n                        result.addAttribute('source_memory_access', sourceMemoryAccess.join(', '));\n                    }\n                }\n            }\n            let targetType = null;\n            let sourceType = null;\n            if (parser.parseOptionalColon()) {\n                const elementType = parser.parseType();\n                targetType = new _.spirv.PointerType(elementType, targetStorageClass);\n                sourceType = new _.spirv.PointerType(elementType, sourceStorageClass);\n            }\n            parser.resolveOperand(targetUnresolved, targetType, result.operands);\n            parser.resolveOperand(sourceUnresolved, sourceType, result.operands);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseSPIRV_I32_1DArmTensor(parser, op, attrName) {\n        const values = [];\n        parser.parseCommaSeparatedList('square', () => {\n            values.push(parser.parseInteger());\n        });\n        op.addAttribute(attrName, values);\n    }\n};\n\n_.WasmSSADialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'wasmssa');\n        this.registerCustomType('WasmSSA_LocalRef', this.parseLocalRefType.bind(this));\n        this.registerCustomDirective('ElseRegion', this.parseElseRegion.bind(this));\n        this.registerCustomAttribute('WasmSSA_ValTypeAttr', this.parseValTypeAttr.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'wasmssa.import_global') {\n            const importName = parser.parseString();\n            result.addAttribute('importName', importName);\n            parser.parseKeyword('from');\n            const moduleName = parser.parseString();\n            result.addAttribute('moduleName', moduleName);\n            parser.parseKeyword('as');\n            parser.parseSymbolName('sym_name', result.attributes);\n            if (parser.parseOptionalKeyword('mutable')) {\n                result.addAttribute('isMutable', new _.UnitAttr());\n            }\n            parser.parseColon();\n            const type = parser.parseType();\n            result.addAttribute('type', type);\n            return true;\n        }\n        if (result.op === 'wasmssa.global') {\n            if (parser.parseOptionalKeyword('exported')) {\n                result.addAttribute('exported', new _.UnitAttr());\n            }\n            parser.parseSymbolName('sym_name', result.attributes);\n            const type = parser.parseType();\n            result.addAttribute('type', type);\n            if (parser.parseOptionalKeyword('mutable')) {\n                result.addAttribute('isMutable', new _.UnitAttr());\n            }\n            parser.parseColon();\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'wasmssa.func') {\n            if (parser.parseOptionalKeyword('exported')) {\n                result.addAttribute('exported', new _.UnitAttr());\n            }\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseType(parser) {\n        if (parser.parseOptionalKeyword('local')) {\n            parser.parseKeyword('ref');\n            parser.parseKeyword('to');\n            const elementType = parser.parseType();\n            return new _.Type(`!wasmssa<local ref to ${elementType}>`);\n        }\n        return null;\n    }\n\n    parseLocalRefType(parser) {\n        parser.parseKeyword('ref');\n        parser.parseKeyword('to');\n        const elementType = parser.parseType();\n        return new _.Type(`ref to ${elementType}`);\n    }\n\n    parseElseRegion(parser, result) {\n        if (parser.parseOptionalKeyword('else')) {\n            const region = result.addRegion();\n            parser.parseRegion(region);\n        }\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'wasmssa.local') {\n            const typeAttr = op.attributes.get('type');\n            if (typeAttr) {\n                const elementType = typeAttr.type ? typeAttr.type : typeAttr;\n                op.addTypes([new _.Type(`!wasmssa<local ref to ${elementType}>`)]);\n                return;\n            }\n        }\n        if (op.op === 'wasmssa.local_get') {\n            const localVarEntry = vars.get('localVar');\n            if (localVarEntry && localVarEntry.types && localVarEntry.types.length > 0) {\n                const localRefType = localVarEntry.types[0];\n                if (localRefType) {\n                    const typeStr = localRefType.toString();\n                    const match = typeStr.match(/ref\\s+to\\s+(.+)/);\n                    if (match) {\n                        op.addTypes([new _.Type(match[1])]);\n                        return;\n                    }\n                }\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n\n    parseValTypeAttr(parser) {\n        const type = parser.parseType();\n        return new _.TypeAttrOf(type);\n    }\n};\n\n_.CFDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'cf');\n        this.registerCustomDirective('SwitchOpCases', this.parseSwitchOpCases.bind(this));\n    }\n\n    parseSwitchOpCases(parser, result) {\n        if (!parser.parseOptionalKeyword('default')) {\n            return false;\n        }\n        if (!parser.parseOptionalColon()) {\n            return false;\n        }\n        const defaultDestination = parser.parseOptionalSuccessor();\n        if (!defaultDestination) {\n            return false;\n        }\n        const defaultDest = { label: defaultDestination, arguments: [] };\n        if (parser.parseOptionalLParen()) {\n            const defaultOperands = parser.parseOperandList();\n            for (const value of defaultOperands) {\n                defaultDest.arguments.push({ value });\n            }\n            const defaultTypes = parser.parseOptionalColonTypeList();\n            for (let idx = 0; idx < defaultTypes.length && idx < defaultDest.arguments.length; idx++) {\n                defaultDest.arguments[idx].type = defaultTypes[idx];\n            }\n            parser.parseOptionalRParen();\n        }\n        result.successors = result.successors || [];\n        result.successors.push(defaultDest);\n        const caseValues = [];\n        const caseOperandSegments = [defaultDest.arguments.length];\n        while (parser.parseOptionalComma()) {\n            const value = parser.parseOptionalInteger();\n            if (value === null) {\n                break;\n            }\n            caseValues.push(value);\n            if (!parser.parseOptionalColon()) {\n                break;\n            }\n            const caseDestination = parser.parseOptionalSuccessor();\n            if (!caseDestination) {\n                break;\n            }\n            const caseDest = { label: caseDestination, arguments: [] };\n            if (parser.parseOptionalLParen()) {\n                const caseOperands = parser.parseOperandList();\n                for (const operandValue of caseOperands) {\n                    caseDest.arguments.push({ value: operandValue });\n                }\n                const caseTypes = parser.parseOptionalColonTypeList();\n                for (let idx = 0; idx < caseTypes.length && idx < caseDest.arguments.length; idx++) {\n                    caseDest.arguments[idx].type = caseTypes[idx];\n                }\n                parser.parseOptionalRParen();\n            }\n            result.successors.push(caseDest);\n            caseOperandSegments.push(caseDest.arguments.length);\n        }\n        if (caseValues.length > 0) {\n            result.addAttribute('case_values', caseValues);\n            result.addAttribute('case_operand_segments', caseOperandSegments);\n        }\n        return true;\n    }\n};\n\n_.pdl = {};\n\n_.pdl.ValueType = class extends _.Type {\n\n    constructor() {\n        super(null);\n    }\n\n    toString() {\n        return '!pdl.value';\n    }\n};\n\n_.pdl.TypeType = class extends _.Type {\n\n    constructor() {\n        super(null);\n    }\n\n    toString() {\n        return '!pdl.type';\n    }\n};\n\n_.pdl.AttributeType = class extends _.Type {\n\n    constructor() {\n        super(null);\n    }\n\n    toString() {\n        return '!pdl.attribute';\n    }\n};\n\n_.pdl.OperationType = class extends _.Type {\n\n    constructor() {\n        super(null);\n    }\n\n    toString() {\n        return '!pdl.operation';\n    }\n};\n\n_.pdl.RangeType = class extends _.Type {\n\n    constructor(elementType) {\n        super(null);\n        this.elementType = elementType;\n    }\n\n    static getElementTypeOrSelf(type) {\n        if (type instanceof _.pdl.RangeType) {\n            return type.elementType;\n        }\n        return type;\n    }\n\n    toString() {\n        const elementStr = this.elementType?.toString() || '';\n        const match = elementStr.match(/^!pdl\\.(.+)$/);\n        return `!pdl.range<${match ? match[1] : elementStr}>`;\n    }\n};\n\n_.pdl.PDLDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'pdl');\n        this.registerCustomDirective('OperationOpAttributes', this.parseOperationOpAttributes.bind(this));\n        this.registerCustomDirective('RangeType', this.parseRangeType.bind(this));\n        this.registerCustomDirective('ResultsValueType', this.parseResultsValueType.bind(this));\n    }\n\n    parseOperationOpAttributes(parser, result) {\n        if (!parser.parseOptionalLBrace()) {\n            return true;\n        }\n        const attributeNames = [];\n        parser.parseCommaSeparatedList('none', () => {\n            const name = parser.parseAttribute();\n            parser.parseEqual();\n            const unresolvedValue = parser.parseOperand();\n            parser.resolveOperand(unresolvedValue, null, result.operands);\n            attributeNames.push(name);\n        });\n        parser.parseRBrace();\n        if (attributeNames.length > 0) {\n            result.addAttribute('attributeValueNames', attributeNames);\n        }\n        return true;\n    }\n\n    parseRangeType(parser, op, argumentTypes, resultTypes) {\n        if (argumentTypes && argumentTypes.length > 0) {\n            const elementType = _.pdl.RangeType.getElementTypeOrSelf(argumentTypes[0]);\n            resultTypes.push(new _.pdl.RangeType(elementType));\n            return true;\n        }\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            resultTypes.push(type);\n        }\n        return true;\n    }\n\n    parseResultsValueType(parser, result) {\n        // Parses `-> type` for pdl.results operation\n        // If index is present, type can be !pdl.value or !pdl.range<value>\n        // If index is absent, type is always !pdl.range<value> (full result range)\n        if (parser.parseOptionalArrow()) {\n            const type = parser.parseType();\n            result.addTypes([type]);\n        } else {\n            // Default to !pdl.range<value> when no explicit type is given\n            result.addTypes([new _.Type('!pdl.range<!pdl.value>')]);\n        }\n        return true;\n    }\n};\n\n_.PDLInterpDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'pdl_interp');\n        this.registerCustomDirective('CreateOperationOpAttributes', this.parseCreateOperationOpAttributes.bind(this));\n        this.registerCustomDirective('CreateOperationOpResults', this.parseCreateOperationOpResults.bind(this));\n        this.registerCustomDirective('RangeType', this.parseRangeType.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'pdl_interp.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'pdl_interp.foreach') {\n            return this.parseForeachOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseForeachOp(parser, result) {\n        const loopVar = parser.parseOperand();\n        parser.parseColon();\n        const loopVarType = parser.parseType();\n        parser.parseKeyword('in');\n        const range = parser.parseOperand();\n        parser.resolveOperand(range, null, result.operands);\n        {\n            const region = {};\n            parser.parseRegion(region);\n            if (region.blocks && region.blocks.length > 0) {\n                if (!region.blocks[0].arguments) {\n                    region.blocks[0].arguments = [];\n                }\n                region.blocks[0].arguments.push({ value: loopVar, type: loopVarType });\n            }\n            result.regions.push(region);\n        }\n        if (parser.parseOptionalArrow()) {\n            parser.parseOptionalSuccessor();\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseCreateOperationOpAttributes(parser, result) {\n        const attrNames = [];\n        if (parser.parseOptionalLBrace()) {\n            if (!parser.parseOptionalRBrace()) {\n                do {\n                    const nameAttr = parser.parseAttribute();\n                    parser.parseEqual();\n                    const operand = parser.parseOperand();\n                    parser.resolveOperand(operand, null, result.operands);\n                    attrNames.push(nameAttr);\n                } while (parser.parseOptionalComma());\n                parser.parseRBrace();\n            }\n        }\n        if (attrNames.length > 0) {\n            result.addAttribute('inputAttributeNames', attrNames);\n        }\n    }\n\n    parseCreateOperationOpResults(parser, result) {\n        if (!parser.parseOptionalArrow()) {\n            return;\n        }\n        if (parser.parseOptionalLess()) {\n            parser.parseKeyword('inferred');\n            parser.parseGreater();\n            result.addAttribute('inferredResultTypes', true);\n            return;\n        }\n        parser.parseLParen();\n        const unresolvedOperands = parser.parseOperandList();\n        const types = parser.parseOptionalColonTypeList();\n        for (let i = 0; i < unresolvedOperands.length; i++) {\n            const type = i < types.length ? types[i] : null;\n            parser.resolveOperand(unresolvedOperands[i], type, result.operands);\n        }\n        parser.parseRParen();\n    }\n\n    parseRangeType(parser, op, argumentTypes, resultTypes) {\n        if (argumentTypes && argumentTypes.length > 0) {\n            const elementType = _.pdl.RangeType.getElementTypeOrSelf(argumentTypes[0]);\n            resultTypes.push(new _.pdl.RangeType(elementType));\n            return true;\n        }\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            resultTypes.push(type);\n        }\n        return true;\n    }\n};\n\n_.ptr = {};\n\n_.ptr.PtrType = class extends _.Type {\n\n    constructor(memorySpace) {\n        super(null);\n        this.memorySpace = memorySpace;\n    }\n\n    toString() {\n        return `!ptr.ptr<${this.memorySpace}>`;\n    }\n};\n\n_.ptr.PtrDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'ptr');\n        this.registerCustomAttribute('EnumProp', this.parseEnumProp.bind(this));\n        this.registerCustomAttribute('Ptr_PtrDiffFlags', (parser, type) => this.parseEnumFlags(parser, type, '|', true));\n        this.registerCustomType('Ptr_PtrType', this.parsePtrType.bind(this));\n    }\n\n    parseEnumProp(parser, type) {\n        const [innerType] = type.args;\n        return this.parseCustomAttributeWithFallback(parser, innerType);\n    }\n\n    parsePtrType(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            const memorySpace = content.slice(1, -1);\n            return new _.ptr.PtrType(memorySpace);\n        }\n        return parser.parseType();\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'ptr.ptr_add' && op.operands.length >= 2) {\n            const baseType = op.operands[0].type;\n            const offsetType = op.operands[1].type;\n            const offsetIsShaped = offsetType instanceof _.VectorType || offsetType instanceof _.RankedTensorType;\n            if (!offsetIsShaped) {\n                if (baseType) {\n                    op.addTypes([baseType]);\n                }\n                return;\n            }\n            const baseIsShaped = baseType instanceof _.VectorType || baseType instanceof _.RankedTensorType;\n            if (!baseIsShaped) {\n                if (offsetType instanceof _.VectorType) {\n                    op.addTypes([new _.VectorType(offsetType.dimensions, baseType, offsetType.scalableDims)]);\n                } else if (offsetType instanceof _.RankedTensorType) {\n                    op.addTypes([new _.RankedTensorType(offsetType.shape, baseType, offsetType.encoding)]);\n                }\n                return;\n            }\n            if (baseType) {\n                op.addTypes([baseType]);\n            }\n            return;\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.EmitCDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'emitc');\n        this.registerCustomType('EmitC_LValueType', this.parseLValueType.bind(this));\n        this.registerCustomDirective('SwitchCases', this.parseSwitchCases.bind(this));\n        this.registerCustomDirective('EmitCGlobalOpTypeAndInitialValue', this.parseTypeAndInitialValue.bind(this));\n        this.registerCustomDirective('EmitCFieldOpTypeAndInitialValue', this.parseTypeAndInitialValue.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'emitc.include') {\n            if (parser.parseOptionalLess()) {\n                const include = parser.parseString();\n                parser.parseGreater();\n                result.addAttribute('is_standard_include', true);\n                result.addAttribute('include', include);\n            } else {\n                const include = parser.parseString();\n                result.addAttribute('include', include);\n            }\n            return true;\n        }\n        if (result.op === 'emitc.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'emitc.expression') {\n            let operand = parser.parseOptionalOperand();\n            while (operand) {\n                parser.resolveOperand(operand, null, result.operands);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                operand = parser.parseOptionalOperand();\n            }\n            if (parser.parseOptionalKeyword('noinline')) {\n                result.addAttribute('do_not_inline', true);\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (type instanceof _.FunctionType) {\n                    result.addAttribute('type', type);\n                    result.addTypes(type.results);\n                }\n            }\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'emitc.if') {\n            const cond = parser.parseOperand();\n            parser.resolveOperand(cond, null, result.operands);\n            const thenRegion = {};\n            parser.parseRegion(thenRegion);\n            result.regions.push(thenRegion);\n            if (parser.parseOptionalKeyword('else')) {\n                const elseRegion = {};\n                parser.parseRegion(elseRegion);\n                result.regions.push(elseRegion);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (result.op === 'emitc.do') {\n            const bodyRegion = {};\n            parser.parseRegion(bodyRegion);\n            result.regions.push(bodyRegion);\n            parser.parseKeyword('while');\n            const condRegion = {};\n            parser.parseRegion(condRegion);\n            result.regions.push(condRegion);\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'emitc.for') {\n            const iterVar = parser.parseOperand();\n            parser.parseEqual();\n            const lb = parser.parseOperand();\n            parser.resolveOperand(lb, null, result.operands);\n            parser.parseKeyword('to');\n            const ub = parser.parseOperand();\n            parser.resolveOperand(ub, null, result.operands);\n            parser.parseKeyword('step');\n            const step = parser.parseOperand();\n            parser.resolveOperand(step, null, result.operands);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addAttribute('type', type.toString());\n            }\n            result.addAttribute('iterVar', { value: iterVar, hidden: true });\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseLValueType(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            return new _.Type(`!emitc.lvalue${content}`);\n        }\n        return null;\n    }\n\n    parseSwitchCases(parser, op /*, args */) {\n        const caseValues = [];\n        while (parser.parseOptionalKeyword('case')) {\n            const value = parser.parseInteger();\n            caseValues.push(value);\n            const region = op.addRegion();\n            parser.parseRegion(region);\n        }\n        if (caseValues.length > 0) {\n            op.addAttribute('cases', caseValues);\n        }\n    }\n\n    parseTypeAndInitialValue(parser, op, typeAttr = 'type', valueAttr = 'initial_value') {\n        const type = parser.parseType();\n        op.addAttribute(typeAttr, type);\n        if (parser.parseOptionalEqual()) {\n            const initialValue = parser.parseAttribute(type);\n            op.addAttribute(valueAttr, initialValue);\n        }\n    }\n};\n\n_.AsukaDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'asuka');\n    }\n\n    parseOperation(parser, result) {\n        // https://github.com/monellz/FlashTensor/blob/main/bench/ea.mlir\n        // uses batch_dims and reduce_dims not valid given the assemblyFormat spec.\n        // Custom parsing preserves compatibility with this file.\n        if (result.op === 'asuka.dot' || result.op === 'asuka.add' || result.op === 'asuka.split' || result.op === 'asuka.softmax' || result.op === 'asuka.reduce') {\n            result.compatibility = true;\n            result.operands = parser.parseOperandList();\n            let attrName = parser.parseOptionalKeyword();\n            while (attrName) {\n                if (parser.parseOptionalEqual()) {\n                    let attrValue = null;\n                    const intVal = parser.parseOptionalInteger();\n                    if (intVal === null) {\n                        attrValue = parser.parseAttribute();\n                        if (parser.parseOptionalKeyword('x')) {\n                            const secondValue = parser.parseAttribute();\n                            attrValue = { kind: 'pair', first: attrValue, second: secondValue };\n                        }\n                    } else {\n                        attrValue = String(intVal);\n                    }\n                    result.addAttribute(attrName, attrValue);\n                    parser.parseOptionalComma();\n                }\n                attrName = parser.parseOptionalKeyword();\n            }\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                parser.resolveOperands(result.operands, funcType.inputs);\n                for (const resultType of funcType.results) {\n                    result.addTypes([resultType]);\n                }\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.async = {};\n\n_.async.TokenType = class extends _.Type {\n\n    constructor() {\n        super(null);\n    }\n\n    toString() {\n        return '!async.token';\n    }\n};\n\n_.async.GroupType = class extends _.Type {\n\n    constructor() {\n        super(null);\n    }\n\n    toString() {\n        return '!async.group';\n    }\n};\n\n_.async.ValueType = class extends _.Type {\n\n    constructor(valueType) {\n        super(null);\n        this.valueType = valueType;\n    }\n\n    toString() {\n        const inner = this.valueType?.toString ? this.valueType.toString() : this.valueType;\n        return `!async.value<${inner}>`;\n    }\n\n    static parse(parser) {\n        if (parser.parseOptionalLess()) {\n            const innerType = parser.parseType();\n            parser.parseGreater();\n            return new _.async.ValueType(innerType);\n        }\n        return new _.async.ValueType(null);\n    }\n};\n\n_.async.AsyncDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'async');\n        this.registerCustomDirective('AwaitResultType', this.parseAwaitResultType.bind(this));\n        this.registerCustomType('Async_ValueType', (parser) => _.async.ValueType.parse(parser));\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic === 'coro.handle' || mnemonic === 'coro.id' || mnemonic === 'coro.state') {\n            return new _.Type(`!${dialect}.${mnemonic}`);\n        }\n        if (mnemonic === 'token') {\n            return new _.async.TokenType();\n        }\n        if (mnemonic === 'group') {\n            return new _.async.GroupType();\n        }\n        if (mnemonic === 'value') {\n            return _.async.ValueType.parse(parser);\n        }\n        throw new mlir.Error(`Unknown '${dialect}' type '${mnemonic}' ${parser.getNameLoc()}`);\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'async.execute') {\n            return this.parseExecuteOp(parser, result);\n        }\n        if (result.op === 'async.func') {\n            return this.parseFuncOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseExecuteOp(parser, result) {\n        const tokenArgs = parser.parseOperandList('optionalSquare');\n        const tokenTypes = tokenArgs.map(() => null);\n        parser.resolveOperands(tokenArgs, tokenTypes, result.operands);\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const operand = parser.parseOperand();\n                    if (parser.parseOptionalKeyword('as')) {\n                        parser.parseOperand();\n                    }\n                    let type = null;\n                    if (parser.parseOptionalColon()) {\n                        type = parser.parseType();\n                    }\n                    parser.resolveOperand(operand, type, result.operands);\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        const valueTypes = [];\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        valueTypes.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            } else {\n                valueTypes.push(parser.parseType());\n            }\n        }\n        result.addTypes([new _.async.TokenType()]);\n        result.addTypes(valueTypes);\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        const executeRegion = result.addRegion();\n        parser.parseOptionalRegion(executeRegion);\n        return true;\n    }\n\n    parseFuncOp(parser, result) {\n        parser.parseOptionalVisibilityKeyword(result.attributes);\n        parser.parseSymbolName('sym_name', result.attributes);\n        const argResult = parser.parseFunctionArgumentList();\n        const inputs = argResult.arguments.map((a) => a.type);\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        const results = [];\n        const resultAttrs = [];\n        if (parser.parseOptionalArrow()) {\n            parser.parseFunctionResultList(results, resultAttrs);\n        }\n        result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        const funcRegion = result.addRegion();\n        parser.parseOptionalRegion(funcRegion);\n        return true;\n    }\n\n    parseAwaitResultType(parser, op, operandTypeArg) {\n        const operandType = parser.parseType();\n        if (Array.isArray(operandTypeArg)) {\n            operandTypeArg.push(operandType);\n        }\n        if (operandType instanceof _.async.ValueType && operandType.valueType) {\n            op.addTypes([operandType.valueType]);\n        }\n    }\n};\n\n_.ArithDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'arith');\n        this.registerCustomAttribute('Arith_FastMathAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n        this.registerCustomAttribute('Arith_IntegerOverflowAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'arith.select') {\n            return this.parseSelectOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseSelectOp(parser, result) {\n        const unresolvedOperands = parser.parseOperandList();\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const condType = parser.parseType();\n            if (parser.parseOptionalComma()) {\n                const resultType = parser.parseType();\n                const types = [condType, resultType, resultType];\n                parser.resolveOperands(unresolvedOperands, types, result.operands);\n                if (result.types.length > 0) {\n                    result.types[0] = resultType;\n                } else {\n                    result.addTypes([resultType]);\n                }\n            } else {\n                const types = unresolvedOperands.map(() => condType);\n                parser.resolveOperands(unresolvedOperands, types, result.operands);\n                if (result.types.length > 0) {\n                    result.types[0] = condType;\n                } else {\n                    result.addTypes([condType]);\n                }\n            }\n        } else {\n            for (const operand of unresolvedOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n        }\n        return true;\n    }\n};\n\n_.BuiltinDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'builtin');\n        this.blobManager = new Map();\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'builtin.call' || result.op === 'builtin.call_indirect') {\n            parser.parseSymbolName('callee', result.attributes);\n            const unresolvedOperands = parser.parseOperandList();\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            result.addTypes(parser.parseOptionalArrowTypeList());\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    readType(reader) {\n        const typeCode = reader.readVarInt();\n        switch (typeCode) {\n            case 0: { // IntegerType\n                const widthAndSign = reader.readVarInt();\n                const width = widthAndSign >> 2;\n                const signedness = widthAndSign & 0x3;\n                if (signedness === 0) {\n                    return new _.IntegerType(`i${width}`);\n                }\n                if (signedness === 1) {\n                    return new _.IntegerType(`si${width}`);\n                }\n                return new _.IntegerType(`ui${width}`);\n            }\n            case 1: // IndexType\n                return new _.IndexType();\n            case 2: { // FunctionType\n                const numInputs = reader.readVarInt();\n                const inputs = [];\n                for (let i = 0; i < numInputs; i++) {\n                    inputs.push(reader.readType());\n                }\n                const numResults = reader.readVarInt();\n                const results = [];\n                for (let i = 0; i < numResults; i++) {\n                    results.push(reader.readType());\n                }\n                return new _.FunctionType(inputs, results);\n            }\n            case 3: return new _.FloatType('bf16');  // BFloat16Type\n            case 4: return new _.FloatType('f16');   // Float16Type\n            case 5: return new _.FloatType('f32');   // Float32Type\n            case 6: return new _.FloatType('f64');   // Float64Type\n            case 7: return new _.FloatType('f80');   // Float80Type\n            case 8: return new _.FloatType('f128');  // Float128Type\n            case 9: { // ComplexType\n                const elementType = reader.readType();\n                return new _.Type(`complex<${elementType.toString()}>`);\n            }\n            case 10: { // MemRefType\n                const shape = reader.readSignedVarInts();\n                const elementType = reader.readType();\n                reader.readAttribute(); // layout\n                return new _.Type(`memref<${shape.join('x')}x${elementType.toString()}>`);\n            }\n            case 11: { // MemRefTypeWithMemSpace\n                reader.readAttribute(); // memorySpace\n                const shape = reader.readSignedVarInts();\n                const elementType = reader.readType();\n                reader.readAttribute(); // layout\n                return new _.Type(`memref<${shape.join('x')}x${elementType.toString()}>`);\n            }\n            case 12: // NoneType\n                return new _.NoneType();\n            case 13: { // RankedTensorType\n                const shape = reader.readSignedVarInts();\n                const elementType = reader.readType();\n                return new _.RankedTensorType(shape, elementType, null);\n            }\n            case 14: { // RankedTensorTypeWithEncoding\n                const encoding = reader.readAttribute();\n                const shape = reader.readSignedVarInts();\n                const elementType = reader.readType();\n                return new _.RankedTensorType(shape, elementType, encoding);\n            }\n            case 15: { // TupleType\n                const numTypes = reader.readVarInt();\n                const types = [];\n                for (let i = 0; i < numTypes; i++) {\n                    types.push(reader.readType());\n                }\n                return new _.Type(`tuple<${types.map((t) => t.toString()).join(', ')}>`);\n            }\n            case 16: { // UnrankedMemRefType\n                const elementType = reader.readType();\n                return new _.Type(`memref<*x${elementType.toString()}>`);\n            }\n            case 17: { // UnrankedMemRefTypeWithMemSpace\n                reader.readAttribute(); // memorySpace\n                const elementType = reader.readType();\n                return new _.Type(`memref<*x${elementType.toString()}>`);\n            }\n            case 18: { // UnrankedTensorType\n                const elementType = reader.readType();\n                return new _.UnrankedTensorType(elementType);\n            }\n            case 19: { // VectorType\n                const shape = reader.readSignedVarInts();\n                const elementType = reader.readType();\n                return new _.VectorType(shape, elementType);\n            }\n            case 20: { // VectorTypeWithScalableDims\n                const numScalable = reader.readVarInt();\n                for (let i = 0; i < numScalable; i++) {\n                    reader.readByte(); // scalableDims flags\n                }\n                const shape = reader.readSignedVarInts();\n                const elementType = reader.readType();\n                return new _.VectorType(shape, elementType);\n            }\n            default:\n                throw new mlir.Error(`Unsupported built-in type code '${typeCode}'.`);\n        }\n    }\n\n    readAttribute(reader) {\n        const typeCode = reader.readVarInt();\n        switch (typeCode) {\n            case 0: { // ArrayAttr\n                const count = reader.readVarInt();\n                const elements = [];\n                for (let i = 0; i < count; i++) {\n                    elements.push(reader.readAttribute());\n                }\n                return new _.ArrayAttr(elements);\n            }\n            case 1: { // DictionaryAttr\n                const count = reader.readVarInt();\n                const attrs = new Map();\n                for (let i = 0; i < count; i++) {\n                    const nameAttr = reader.readAttribute();\n                    const valueAttr = reader.readAttribute();\n                    const name = nameAttr && nameAttr.value ? nameAttr.value : `attr_${i}`;\n                    attrs.set(name, valueAttr);\n                }\n                return { name: 'dictionary', value: attrs };\n            }\n            case 2: { // StringAttr\n                const value = reader.readString();\n                return new _.StringAttr(value);\n            }\n            case 3: { // StringAttrWithType\n                const value = reader.readString();\n                const type = reader.readType();\n                return new _.StringAttr(value, type);\n            }\n            case 4: { // FlatSymbolRefAttr\n                const value = reader.readString();\n                return new _.SymbolRefAttr(`@${value}`);\n            }\n            case 5: { // SymbolRefAttr\n                const root = reader.readString();\n                const numNested = reader.readVarInt();\n                let value = `@${root}`;\n                for (let i = 0; i < numNested; i++) {\n                    value += `::@${reader.readString()}`;\n                }\n                return new _.SymbolRefAttr(value);\n            }\n            case 6: { // TypeAttr\n                const type = reader.readType();\n                return new _.TypeAttrOf(type);\n            }\n            case 7: // UnitAttr\n                return new _.UnitAttr();\n            case 8: { // IntegerAttr\n                const getIntegerBitWidth = (type) => {\n                    const str = type ? type.toString() : '';\n                    const match = str.match(/^[su]?i(\\d+)$/);\n                    if (match) {\n                        return parseInt(match[1], 10);\n                    }\n                    if (str === 'index') {\n                        return 64;\n                    }\n                    throw new mlir.Error(`Unsupported integer type '${str}'.`);\n                };\n                const type = reader.readType();\n                const bitWidth = getIntegerBitWidth(type);\n                let value = null;\n                if (bitWidth <= 8) {\n                    value = BigInt(reader.readByte());\n                } else if (bitWidth <= 64) {\n                    value = reader.readSignedVarInt();\n                } else {\n                    const numWords = reader.readVarInt();\n                    value = 0n;\n                    for (let i = 0; i < numWords; i++) {\n                        const word = reader.readSignedVarInt();\n                        value |= (word << BigInt(i * 64));\n                    }\n                }\n                return new _.IntegerAttr(type, value);\n            }\n            case 9: { // FloatAttr\n                const type = reader.readType();\n                const value = reader.readAPFloatWithKnownSemantics(type);\n                return new _.FloatAttr(type, value);\n            }\n            case 10: { // CallSiteLoc\n                const caller = reader.readAttribute();\n                const callee = reader.readAttribute();\n                const callerStr = caller && caller.value ? caller.value : '<caller>';\n                const calleeStr = callee && callee.value ? callee.value : '<callee>';\n                return { name: 'loc', value: `callsite(${callerStr} at ${calleeStr})` };\n            }\n            case 11: { // FileLineColLoc\n                const filename = reader.readString();\n                const line = reader.readVarInt();\n                const col = reader.readVarInt();\n                return { name: 'loc', value: `${filename}:${line}:${col}` };\n            }\n            case 12: { // FusedLoc\n                const count = reader.readVarInt();\n                const locations = [];\n                for (let i = 0; i < count; i++) {\n                    const loc = reader.readAttribute();\n                    locations.push(loc && loc.value ? loc.value : '<loc>');\n                }\n                return { name: 'loc', value: `fused[${locations.join(', ')}]` };\n            }\n            case 13: { // FusedLocWithMetadata\n                const metadata = reader.readAttribute();\n                const count = reader.readVarInt();\n                const locations = [];\n                for (let i = 0; i < count; i++) {\n                    const loc = reader.readAttribute();\n                    locations.push(loc && loc.value ? loc.value : '<loc>');\n                }\n                const metaStr = metadata && metadata.value !== undefined ? metadata.value : '<meta>';\n                return { name: 'loc', value: `fused<${metaStr}>[${locations.join(', ')}]` };\n            }\n            case 14: { // NameLoc\n                const nameAttr = reader.readAttribute();\n                const childLoc = reader.readAttribute();\n                const nameStr = nameAttr && nameAttr.value !== undefined ? nameAttr.value : '<name>';\n                const childStr = childLoc && childLoc.value ? childLoc.value : '<loc>';\n                return { name: 'loc', value: `#loc(${nameStr}(${childStr}))` };\n            }\n            case 15: // UnknownLoc\n                return { name: 'loc', value: 'unknown' };\n            case 16: { // DenseResourceElementsAttr\n                const type = reader.readType();\n                const resource = reader.readResourceHandle();\n                const blobData = resource && resource.value && resource.value.kind === 'blob' ? resource.value.data : null;\n                const handle = new _.DenseResourceElementsHandle(resource ? resource.key : 'unknown', blobData);\n                return new _.DenseResourceElementsAttr(type, handle);\n            }\n            case 17: { // DenseArrayAttr\n                const type = reader.readType();\n                const size = reader.readVarInt();\n                const blob = reader.readBlob();\n                return new _.DenseArrayAttr(type, size, blob);\n            }\n            case 18: { // DenseIntOrFPElementsAttr\n                const type = reader.readType();\n                const blob = reader.readBlob();\n                return new _.DenseElementsAttr(blob, type);\n            }\n            case 19: { // DenseStringElementsAttr\n                const type = reader.readType();\n                const isSplat = reader.readVarInt() !== 0;\n                const count = reader.readVarInt();\n                const strings = [];\n                for (let i = 0; i < count; i++) {\n                    strings.push(reader.readString());\n                }\n                return { name: 'dense_string', value: strings, type, isSplat };\n            }\n            case 20: { // SparseElementsAttr\n                const type = reader.readType();\n                const indices = reader.readAttribute();\n                const values = reader.readAttribute();\n                return new _.SparseElementsAttr(type, indices, values);\n            }\n            case 21: { // DistinctAttr\n                const referencedAttr = reader.readAttribute();\n                return { name: 'distinct', value: referencedAttr };\n            }\n            case 22: { // FileLineColRange\n                const filename = reader.readString();\n                const numLocs = reader.readVarInt();\n                const locs = [];\n                for (let i = 0; i < numLocs; i++) {\n                    locs.push(reader.readVarInt());\n                }\n                return { name: 'loc', value: `${filename}:${locs.join(':')}` };\n            }\n            default:\n                return { name: 'builtin', value: `<builtin code ${typeCode}>` };\n        }\n    }\n\n    declareResource(key) {\n        if (!this.blobManager.has(key)) {\n            this.blobManager.set(key, new _.DenseResourceElementsHandle(key));\n        }\n        return this.blobManager.get(key);\n    }\n\n    getResourceKey(handle) {\n        return handle.key;\n    }\n\n    parseResource(entry) {\n        const blob = entry.parseAsBlob();\n        this.blobManager.get(entry.key).blob = blob;\n    }\n};\n\n_.BufferizationDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'bufferization');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'bufferization.alloc_tensor') {\n            if (!parser.parseOptionalLParen()) {\n                return false;\n            }\n            const unresolvedDynamicDims = [];\n            if (!parser.parseOptionalRParen()) {\n                let operand = parser.parseOptionalOperand();\n                while (operand) {\n                    unresolvedDynamicDims.push(operand);\n                    if (!parser.parseOptionalComma()) {\n                        break;\n                    }\n                    operand = parser.parseOptionalOperand();\n                }\n                parser.parseRParen();\n            }\n            let unresolvedCopy = null;\n            if (parser.parseOptionalKeyword('copy')) {\n                parser.parseLParen();\n                unresolvedCopy = parser.parseOperand();\n                parser.parseRParen();\n            }\n            let unresolvedSizeHint = null;\n            if (parser.parseOptionalKeyword('size_hint')) {\n                parser.parseEqual();\n                unresolvedSizeHint = parser.parseOperand();\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const resultType = parser.parseType();\n                const indexType = new _.IndexType();\n                parser.resolveOperands(unresolvedDynamicDims, unresolvedDynamicDims.map(() => indexType), result.operands);\n                if (unresolvedCopy) {\n                    parser.resolveOperand(unresolvedCopy, resultType, result.operands);\n                }\n                if (unresolvedSizeHint) {\n                    parser.resolveOperand(unresolvedSizeHint, indexType, result.operands);\n                }\n                if (result.types.length === 0) {\n                    result.types.push(resultType);\n                } else {\n                    result.types[0] = resultType;\n                }\n            }\n            return true;\n        }\n        // bufferization.to_memref %tensor read_only : tensor_type to memref_type\n        if (result.op === 'bufferization.to_memref') {\n            const unresolvedOperand = parser.parseOptionalOperand();\n            if (parser.parseOptionalKeyword('read_only')) {\n                result.addAttribute('read_only', true);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const sourceType = parser.parseType();\n                result.addAttribute('source_type', sourceType);\n                if (unresolvedOperand) {\n                    parser.resolveOperand(unresolvedOperand, sourceType, result.operands);\n                }\n                parser.parseKeyword('to');\n                const destType = parser.parseType();\n                result.addTypes([destType]);\n            } else if (unresolvedOperand) {\n                parser.resolveOperand(unresolvedOperand, null, result.operands);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'bufferization.dealloc') {\n            // DeallocOp::inferReturnTypes - one i1 per retained memref\n            const retainedEntry = vars.get('retained');\n            const numRetained = retainedEntry?.operands?.length || 0;\n            const i1Type = new _.IntegerType('i1');\n            for (let i = 0; i < numRetained; i++) {\n                op.addTypes([i1Type]);\n            }\n            return;\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.SCFDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'scf');\n        this.registerCustomDirective('SwitchCases', this.parseSwitchCases.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'scf.for') {\n            return this.parseForOp(parser, result);\n        }\n        if (result.op === 'scf.if') {\n            return this.parseIfOp(parser, result);\n        }\n        if (result.op === 'scf.while') {\n            return this.parseWhileOp(parser, result);\n        }\n        if (result.op === 'scf.forall') {\n            return this.parseForallOp(parser, result);\n        }\n        if (result.op === 'scf.forall.in_parallel') {\n            return this.parseInParallelOp(parser, result);\n        }\n        if (result.op === 'scf.parallel') {\n            return this.parseParallelOp(parser, result);\n        }\n        if (result.op === 'scf.execute_region') {\n            return this.parseExecuteRegionOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseForOp(parser, result) {\n        if (parser.parseOptionalKeyword('unsigned')) {\n            result.addAttribute('unsignedCmp', true);\n        }\n        const inductionVariable = parser.parseArgument();\n        parser.parseEqual();\n        const lb = parser.parseOperand();\n        parser.parseKeyword('to');\n        const ub = parser.parseOperand();\n        parser.parseKeyword('step');\n        const step = parser.parseOperand();\n        const regionArgs = [inductionVariable];\n        const operands = [];\n        const hasIterArgs = parser.parseOptionalKeyword('iter_args');\n        if (hasIterArgs) {\n            parser.parseAssignmentList(regionArgs, operands);\n            result.addTypes(parser.parseArrowTypeList());\n        }\n        const type = parser.parseOptionalColon() ? parser.parseType() : new _.IndexType();\n        inductionVariable.type = type;\n        for (let i = 0; i < operands.length; i++) {\n            regionArgs[i + 1].type = result.types[i];\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region, regionArgs);\n        parser.resolveOperands([lb, ub, step], [type, type, type], result.operands);\n        if (hasIterArgs) {\n            parser.resolveOperands(operands, result.types, result.operands);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        result.addAttribute('operandSegmentSizes', new _.DenseI32ArrayAttr([1, 1, 1, operands.length]));\n        return true;\n    }\n\n    parseIfOp(parser, result) {\n        // Reference impl: condition operand is of type i1\n        const unresolvedCond = parser.parseOptionalOperand();\n        if (!unresolvedCond) {\n            return false;\n        }\n        const i1Type = new _.IntegerType('i1');\n        parser.resolveOperands([unresolvedCond], [i1Type], result.operands);\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        const thenRegion = result.addRegion();\n        parser.parseRegion(thenRegion);\n        if (parser.parseOptionalKeyword('else')) {\n            const elseRegion = result.addRegion();\n            parser.parseRegion(elseRegion);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseWhileOp(parser, result) {\n        const unresolvedOperands = [];\n        if (parser.parseOptionalLParen()) {\n            while (!parser.parseOptionalRParen()) {\n                parser.parseOptionalOperand(); // Skip variable name\n                if (parser.parseOptionalEqual()) {\n                    const operand = parser.parseOptionalOperand();\n                    if (operand) {\n                        unresolvedOperands.push(operand);\n                    }\n                    // Note: attribute values are not operands, skip them\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        if (parser.parseOptionalColon()) {\n            const types = [];\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    types.push(parser.parseType());\n                    parser.parseOptionalComma();\n                }\n            } else {\n                types.push(parser.parseType());\n            }\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            result.addTypes(parser.parseOptionalArrowTypeList());\n        }\n        {\n            const region = result.addRegion();\n            parser.parseRegion(region);\n        }\n        if (parser.parseOptionalKeyword('do')) {\n            const region = result.addRegion();\n            parser.parseRegion(region);\n        }\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        return true;\n    }\n\n    parseForallOp(parser, result) {\n        const indexType = new _.IndexType();\n        const inductionVars = [];\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        while (!parser.parseOptionalRParen()) {\n            const inductionVar = parser.parseOptionalOperand();\n            if (inductionVar) {\n                inductionVars.push(inductionVar.name);\n            } else {\n                return false;\n            }\n            if (!parser.parseOptionalComma()) {\n                if (!parser.parseOptionalRParen()) {\n                    return false;\n                }\n                break;\n            }\n        }\n        const isNormalized = parser.parseOptionalKeyword('in');\n        if (!isNormalized && !parser.parseOptionalEqual()) {\n            return false;\n        }\n        // Helper to parse bounds list - only SSA values become operands, integers are static\n        const parseBoundsList = () => {\n            const bounds = [];\n            if (!parser.parseOptionalLParen()) {\n                return bounds;\n            }\n            while (!parser.parseOptionalRParen()) {\n                const operand = parser.parseOptionalOperand();\n                if (operand) {\n                    bounds.push(operand);\n                } else {\n                    const intVal = parser.parseOptionalInteger();\n                    if (intVal !== null) {\n                        // Skip static bound\n                    }\n                }\n                parser.parseOptionalComma();\n            }\n            return bounds;\n        };\n        if (isNormalized) {\n            // Normalized form: in (bounds)\n            const bounds = parseBoundsList();\n            parser.resolveOperands(bounds, bounds.map(() => indexType), result.operands);\n        } else {\n            // Range form: = (lb) to (ub) step (step)\n            const lowerBounds = parseBoundsList();\n            parser.resolveOperands(lowerBounds, lowerBounds.map(() => indexType), result.operands);\n            if (!parser.parseOptionalKeyword('to')) {\n                return false;\n            }\n            const upperBounds = parseBoundsList();\n            parser.resolveOperands(upperBounds, upperBounds.map(() => indexType), result.operands);\n            if (!parser.parseOptionalKeyword('step')) {\n                return false;\n            }\n            const steps = parseBoundsList();\n            parser.resolveOperands(steps, steps.map(() => indexType), result.operands);\n        }\n        if (parser.parseOptionalKeyword('shared_outs')) {\n            if (!parser.parseOptionalLParen()) {\n                return false;\n            }\n            while (!parser.parseOptionalRParen()) {\n                parser.parseOptionalOperand(); // Skip arg name\n                if (parser.parseOptionalEqual()) {\n                    const operand = parser.parseOptionalOperand();\n                    if (operand) {\n                        parser.resolveOperand(operand, null, result.operands);\n                    } else {\n                        parser.parseAttribute(); // Skip attribute value\n                    }\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    const type = parser.parseType();\n                    result.addTypes([type]);\n                    parser.parseOptionalComma();\n                }\n            } else {\n                const type = parser.parseType();\n                result.addTypes([type]);\n            }\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseParallelOp(parser, result) {\n        const indexType = new _.IndexType();\n        const inductionVars = [];\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        while (!parser.parseOptionalRParen()) {\n            const inductionVar = parser.parseOptionalOperand();\n            if (inductionVar) {\n                inductionVars.push(inductionVar.name);\n            } else {\n                return false;\n            }\n            parser.parseOptionalComma();\n        }\n        if (!parser.parseOptionalEqual()) {\n            return false;\n        }\n        const lowerBounds = [];\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        while (!parser.parseOptionalRParen()) {\n            const lb = parser.parseOptionalOperand();\n            if (lb) {\n                lowerBounds.push(lb);\n            } else {\n                return false;\n            }\n            parser.parseOptionalComma();\n        }\n        parser.resolveOperands(lowerBounds, lowerBounds.map(() => indexType), result.operands);\n        if (!parser.parseOptionalKeyword('to')) {\n            return false;\n        }\n        const upperBounds = [];\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        while (!parser.parseOptionalRParen()) {\n            const ub = parser.parseOptionalOperand();\n            if (ub) {\n                upperBounds.push(ub);\n            } else {\n                return false;\n            }\n            parser.parseOptionalComma();\n        }\n        parser.resolveOperands(upperBounds, upperBounds.map(() => indexType), result.operands);\n        if (!parser.parseOptionalKeyword('step')) {\n            return false;\n        }\n        const steps = [];\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        while (!parser.parseOptionalRParen()) {\n            const step = parser.parseOptionalOperand();\n            if (step) {\n                steps.push(step);\n            } else {\n                return false;\n            }\n            parser.parseOptionalComma();\n        }\n        parser.resolveOperands(steps, steps.map(() => indexType), result.operands);\n        if (parser.parseOptionalKeyword('init')) {\n            const initVals = [];\n            if (!parser.parseOptionalLParen()) {\n                return false;\n            }\n            while (!parser.parseOptionalRParen()) {\n                const initOp = parser.parseOptionalOperand();\n                if (initOp) {\n                    initVals.push(initOp);\n                } else {\n                    const value = parser.parseAttribute();\n                    if (value) {\n                        initVals.push(value);\n                    }\n                }\n                parser.parseOptionalComma();\n            }\n            // Init values type inferred from definition\n            parser.resolveOperands(initVals, initVals.map(() => null), result.operands);\n        }\n        if (parser.parseOptionalArrow()) {\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    const type = parser.parseType();\n                    result.addTypes([type]);\n                    parser.parseOptionalComma();\n                }\n            } else {\n                const type = parser.parseType();\n                result.addTypes([type]);\n            }\n        }\n        {\n            const region = {};\n            parser.parseRegion(region);\n            if (region.blocks && region.blocks.length > 0 && inductionVars.length > 0) {\n                if (!region.blocks[0].arguments) {\n                    region.blocks[0].arguments = [];\n                }\n                for (const iv of inductionVars) {\n                    region.blocks[0].arguments.push({ value: iv });\n                }\n            }\n            result.regions.push(region);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseInParallelOp(parser, result) {\n        // scf.forall.in_parallel { region }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseSwitchCases(parser, op, casesAttrName) {\n        const caseValues = [];\n        while (parser.parseOptionalKeyword('case')) {\n            const value = parser.parseOptionalInteger();\n            if (value === null) {\n                break;\n            }\n            caseValues.push(value);\n            const region = op.addRegion();\n            parser.parseRegion(region);\n        }\n        if (casesAttrName) {\n            op.addAttribute(casesAttrName, caseValues);\n        }\n    }\n\n    parseExecuteRegionOp(parser, result) {\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        if (parser.parseOptionalKeyword('no_inline')) {\n            result.addAttribute('no_inline', true);\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n};\n\n_.ShapeDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'shape');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            const type = `!${dialect}.${mnemonic}`;\n            const simpleTypes = ['shape', 'witness', 'size', 'value_shape'];\n            if (simpleTypes.includes(type.substring(7))) { // Remove \"!shape.\" prefix\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'shape.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'shape.assuming') {\n            return this.parseAssumingOp(parser, result);\n        }\n        if (result.op === 'shape.const_shape') {\n            return this.parseConstShapeOp(parser, result);\n        }\n        if (result.op === 'shape.reduce') {\n            return this.parseReduceOp(parser, result);\n        }\n        if (result.op === 'shape.function_library') {\n            return this.parseFunctionLibraryOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseAssumingOp(parser, result) {\n        const unresolvedWitness = parser.parseOptionalOperand();\n        if (!unresolvedWitness) {\n            return false;\n        }\n        const witnessType = new _.Type('!shape.witness');\n        parser.resolveOperand(unresolvedWitness, witnessType, result.operands);\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseConstShapeOp(parser, result) {\n        parser.parseOptionalAttrDict(result.attributes);\n        const extents = parser.parseAttribute();\n        result.addAttribute('shape', extents);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            result.addTypes([type]);\n        }\n        return true;\n    }\n\n    parseReduceOp(parser, result) {\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        const unresolvedOperands = [];\n        let operand = parser.parseOptionalOperand();\n        while (operand) {\n            unresolvedOperands.push(operand);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            operand = parser.parseOptionalOperand();\n        }\n        parser.parseOptionalRParen();\n        let shapeType = new _.Type('!shape.shape');\n        if (parser.parseOptionalColon()) {\n            shapeType = parser.parseType();\n        }\n        const resultTypes = [];\n        {\n            const types = parser.parseOptionalArrowTypeList();\n            result.addTypes(types);\n            resultTypes.push(...types);\n        }\n        // First operand is the shape, rest are init values with result types\n        if (unresolvedOperands.length > 0) {\n            parser.resolveOperand(unresolvedOperands[0], shapeType, result.operands);\n            for (let i = 1; i < unresolvedOperands.length; i++) {\n                const initType = resultTypes[i - 1] || null;\n                parser.resolveOperand(unresolvedOperands[i], initType, result.operands);\n            }\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseFunctionLibraryOp(parser, result) {\n        parser.parseSymbolName('sym_name', result.attributes);\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        if (parser.parseOptionalKeyword('mapping')) {\n            const mapping = parser.parseAttribute();\n            result.addAttribute('mapping', mapping);\n        }\n        return true;\n    }\n};\n\n_.SparseTensorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'sparse_tensor');\n        this.registerCustomDirective('LevelRange', this.parseLevelRange.bind(this));\n    }\n\n    parseLevelRange(parser, op, startAttr, endAttr) {\n        const loLvl = parser.parseInteger();\n        const hiLvl = parser.parseOptionalKeyword('to') ? parser.parseInteger() : loLvl + 1;\n        if (startAttr && endAttr) {\n            op.addAttribute(startAttr, loLvl);\n            op.addAttribute(endAttr, hiLvl);\n        }\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'sparse_tensor.iterate') {\n            return this.parseIterateOp(parser, result);\n        }\n        if (result.op === 'sparse_tensor.coiterate') {\n            return this.parseCoIterateOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseIterateOp(parser, result) {\n        const iteratorArg = parser.parseOptionalOperand();\n        if (!iteratorArg) {\n            return false;\n        }\n        const regionArgs = [];\n        regionArgs.push({ name: iteratorArg.name, type: null }); // type determined by tensor\n        if (!parser.parseOptionalKeyword('in')) {\n            return false;\n        }\n        const unresolvedTensor = parser.parseOptionalOperand();\n        if (!unresolvedTensor) {\n            return false;\n        }\n        const iterArgNames = [];\n        const initValues = [];\n        if (parser.parseOptionalKeyword('at')) {\n            parser.parseOptionalLParen();\n            do {\n                const _atArg = parser.parseOptionalOperand();\n                if (!_atArg && !parser.parseOptionalKeyword()) {\n                    break;\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseOptionalRParen();\n        }\n        if (parser.parseOptionalKeyword('iter_args')) {\n            parser.parseOptionalLParen();\n            let iterArg = parser.parseOptionalOperand();\n            while (iterArg) {\n                iterArgNames.push(iterArg.name);\n                if (parser.parseOptionalEqual()) {\n                    initValues.push(parser.parseOperand());\n                }\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                iterArg = parser.parseOptionalOperand();\n            }\n            parser.parseOptionalRParen();\n        }\n        let tensorType = null;\n        if (parser.parseOptionalColon()) {\n            tensorType = parser.parseType();\n        }\n        const resultTypes = [];\n        {\n            const types = parser.parseOptionalArrowTypeList();\n            result.addTypes(types);\n            resultTypes.push(...types);\n        }\n        // Add iter_args to region args with their result types\n        for (let i = 0; i < iterArgNames.length; i++) {\n            const argType = resultTypes[i] || null;\n            regionArgs.push({ name: iterArgNames[i], type: argType });\n        }\n        parser.resolveOperand(unresolvedTensor, tensorType, result.operands);\n        // iter_args block args don't go to operands, but init values do\n        for (let i = 0; i < initValues.length; i++) {\n            const initType = resultTypes[i] || null;\n            parser.resolveOperand(initValues[i], initType, result.operands);\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region, regionArgs);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseCoIterateOp(parser, result) {\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        const unresolvedTensors = [];\n        let _tensor = parser.parseOptionalOperand();\n        while (_tensor) {\n            unresolvedTensors.push(_tensor);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            _tensor = parser.parseOptionalOperand();\n        }\n        parser.parseOptionalRParen();\n        if (parser.parseOptionalKeyword('at')) {\n            parser.parseOptionalLParen();\n            do {\n                const _coAtArg = parser.parseOptionalOperand();\n                if (!_coAtArg && !parser.parseOptionalKeyword()) {\n                    break;\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseOptionalRParen();\n        }\n        const iterArgNames = [];\n        const initValues = [];\n        if (parser.parseOptionalKeyword('iter_args')) {\n            parser.parseOptionalLParen();\n            let coIterArg = parser.parseOptionalOperand();\n            while (coIterArg) {\n                iterArgNames.push(coIterArg.name);\n                if (parser.parseOptionalEqual()) {\n                    initValues.push(parser.parseOperand());\n                }\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                coIterArg = parser.parseOptionalOperand();\n            }\n            parser.parseOptionalRParen();\n        }\n        const tensorTypes = [];\n        if (parser.parseOptionalColon()) {\n            tensorTypes.push(...parser.parseCommaSeparatedList('optionalParen', () => parser.parseType()));\n        }\n        const resultTypes = [];\n        {\n            const types = parser.parseOptionalArrowTypeList();\n            result.addTypes(types);\n            resultTypes.push(...types);\n        }\n        const regionArgs = [];\n        for (let i = 0; i < iterArgNames.length; i++) {\n            const argType = resultTypes[i] || null;\n            regionArgs.push({ name: iterArgNames[i], type: argType });\n        }\n        for (let i = 0; i < unresolvedTensors.length; i++) {\n            const tensorType = tensorTypes[i] || null;\n            parser.resolveOperand(unresolvedTensors[i], tensorType, result.operands);\n        }\n        for (let i = 0; i < initValues.length; i++) {\n            const initType = resultTypes[i] || null;\n            parser.resolveOperand(initValues[i], initType, result.operands);\n        }\n        while (parser.parseOptionalKeyword('case')) {\n            const caseArgs = [...regionArgs]; // Start with iter_args\n            do {\n                const _caseOp = parser.parseOptionalOperand();\n                if (_caseOp) {\n                    caseArgs.push({ name: _caseOp.name, type: null });\n                } else if (!parser.parseOptionalKeyword()) {\n                    break;\n                }\n            } while (parser.parseOptionalComma());\n            const region = result.addRegion();\n            parser.parseRegion(region, caseArgs);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n};\n\n_.FuncDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'func');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'func.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.GpuDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'gpu');\n        this.registerCustomDirective('AllReduceOperation', this.parseAllReduceOperation.bind(this));\n        this.registerCustomDirective('LaunchFuncOperands', this.parseLaunchFuncOperands.bind(this));\n        this.registerCustomDirective('AsyncDependencies', this.parseAsyncDependencies.bind(this));\n        this.registerCustomDirective('LaunchDimType', this.parseLaunchDimType.bind(this));\n        this.registerCustomDirective('OffloadingHandler', this.parseOffloadingHandler.bind(this));\n    }\n\n    parseAllReduceOperation(parser, op, attrName = 'op') {\n        const validOps = ['add', 'mul', 'minui', 'minsi', 'minnumf', 'maxui', 'maxsi', 'maxnumf', 'and', 'or', 'xor', 'minimumf', 'maximumf'];\n        const opName = parser.parseOptionalKeyword();\n        if (opName && validOps.includes(opName)) {\n            op.addAttribute(attrName, opName);\n        }\n    }\n\n    parseLaunchDimType(parser, op, typeArg1, typeArg2, clusterTypeArg1, clusterTypeArg2, clusterTypeArg3) {\n        // typeArg1 = type($gridSizeX), typeArg2 = ref($clusterSizeX)\n        // clusterTypeArg1/2/3 = type($clusterSizeX/Y/Z)\n        let dimType = new _.IndexType();\n        if (parser.parseOptionalColon()) {\n            dimType = parser.parseType();\n        }\n        // Push type to gridSizeX types array\n        if (Array.isArray(typeArg1)) {\n            typeArg1.push(dimType);\n        }\n        // If clusters are present (ref($clusterSizeX) has values), push to cluster type arrays\n        const hasCluster = Array.isArray(typeArg2) && typeArg2.length > 0;\n        if (hasCluster) {\n            if (Array.isArray(clusterTypeArg1)) {\n                clusterTypeArg1.push(dimType);\n            }\n            if (Array.isArray(clusterTypeArg2)) {\n                clusterTypeArg2.push(dimType);\n            }\n            if (Array.isArray(clusterTypeArg3)) {\n                clusterTypeArg3.push(dimType);\n            }\n        }\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'gpu.func') {\n            parser.parseOptionalVisibilityKeyword(result.attributes);\n            parser.parseSymbolName('sym_name', result.attributes);\n            const sig = parser.parseFunctionSignatureWithArguments(false);\n            const argTypes = sig.arguments.map((a) => a.type);\n            const type = new _.FunctionType(argTypes, sig.resultTypes);\n            result.addAttribute('function_type', new _.TypeAttrOf(type));\n            const allArgs = [...sig.arguments];\n            if (parser.parseOptionalKeyword('workgroup')) {\n                const workgroupResult = parser.parseFunctionArgumentList(false);\n                allArgs.push(...workgroupResult.arguments);\n            }\n            if (parser.parseOptionalKeyword('private')) {\n                const privateResult = parser.parseFunctionArgumentList(false);\n                allArgs.push(...privateResult.arguments);\n            }\n            if (parser.parseOptionalKeyword('kernel')) {\n                result.addAttribute('gpu.kernel', true);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const region = result.addRegion();\n            // gpu.func is IsolatedFromAbove\n            parser.parseRegion(region, allArgs, /* isIsolatedNameScope */ true);\n            return true;\n        }\n        if (result.op === 'gpu.launch') {\n            const indexType = new _.IndexType();\n            if (parser.parseOptionalKeyword('async')) {\n                if (parser.getNumResults() === 0) {\n                    throw new mlir.Error(`Operation '${result.op}' needs to be named when marked 'async' ${parser.getCurrentLocation()}`);\n                }\n                result.addTypes([new _.Type('!gpu.async.token')]);\n            }\n            const asyncDeps = parser.parseOperandList('optionalSquare');\n            const asyncTypes = asyncDeps.map(() => null);\n            parser.resolveOperands(asyncDeps, asyncTypes, result.operands);\n            if (parser.parseOptionalKeyword('clusters')) {\n                this.parseSizeAssignment(parser, result, indexType);\n                parser.parseKeyword('in');\n                this.parseSizeAssignment(parser, result, indexType);\n            }\n            parser.parseKeyword('blocks');\n            this.parseSizeAssignment(parser, result, indexType);\n            parser.parseKeyword('in');\n            this.parseSizeAssignment(parser, result, indexType);\n            parser.parseKeyword('threads');\n            this.parseSizeAssignment(parser, result, indexType);\n            parser.parseKeyword('in');\n            this.parseSizeAssignment(parser, result, indexType);\n            if (parser.parseOptionalKeyword('dynamic_shared_memory_size')) {\n                const operand = parser.parseOperand();\n                parser.resolveOperand(operand, indexType, result.operands);\n            }\n            if (parser.parseOptionalKeyword('module')) {\n                parser.parseLParen();\n                const moduleSymbol = parser.parseOptionalSymbolName();\n                result.addAttribute('module', moduleSymbol);\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalKeyword('function')) {\n                parser.parseLParen();\n                const funcSymbol = parser.parseOptionalSymbolName();\n                result.addAttribute('function', funcSymbol);\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalKeyword('workgroup')) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        parser.parseOperand();\n                        parser.parseColon();\n                        parser.parseType();\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            if (parser.parseOptionalKeyword('private')) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        parser.parseOperand();\n                        parser.parseColon();\n                        parser.parseType();\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            const region = result.addRegion();\n            // gpu.launch is IsolatedFromAbove\n            parser.parseRegion(region, undefined, /* isIsolatedNameScope */ true);\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (result.op === 'gpu.warp_execute_on_lane_0') {\n            return this.parseWarpExecuteOnLane0Op(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseWarpExecuteOnLane0Op(parser, result) {\n        parser.parseLParen();\n        const unresolvedLaneId = parser.parseOperand();\n        const indexType = new _.IndexType();\n        parser.resolveOperand(unresolvedLaneId, indexType, result.operands);\n        parser.parseRParen();\n        parser.parseLSquare();\n        const warpSize = parser.parseInteger();\n        result.addAttribute('warp_size', warpSize);\n        parser.parseRSquare();\n        if (parser.parseOptionalKeyword('args')) {\n            parser.parseLParen();\n            const unresolvedArgs = parser.parseOperandList('none');\n            if (parser.parseOptionalColon()) {\n                const types = parser.parseTypeList();\n                parser.resolveOperands(unresolvedArgs, types, result.operands);\n            } else {\n                for (const arg of unresolvedArgs) {\n                    parser.resolveOperand(arg, null, result.operands);\n                }\n            }\n            parser.parseRParen();\n        }\n        const arrowTypes = parser.parseOptionalArrowTypeList();\n        if (arrowTypes.length > 0) {\n            if (result.types.length > 0) {\n                result.addTypes(arrowTypes);\n            } else {\n                for (const type of arrowTypes) {\n                    result.addTypes([type]);\n                }\n            }\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseSizeAssignment(parser, op, indexType) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const blockArg = parser.parseOptionalOperand();\n                if (!blockArg) {\n                    break;\n                }\n                if (parser.parseOptionalEqual()) {\n                    const operand = parser.parseOperand();\n                    parser.resolveOperand(operand, indexType, op.operands);\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n    }\n\n    parseLaunchFuncOperands(parser, op /*, args */) {\n        if (parser.parseOptionalKeyword('args')) {\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const operand = parser.parseOperand();\n                    parser.parseColon();\n                    const type = parser.parseType();\n                    parser.resolveOperand(operand, type, op.operands);\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n    }\n\n    parseAsyncDependencies(parser, op, asyncTokenTypes, asyncDependencies) {\n        // custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)\n        // If 'async' keyword is present, operation has async result token\n        const hasAsync = parser.parseOptionalKeyword('async');\n        if (hasAsync && Array.isArray(asyncTokenTypes)) {\n            asyncTokenTypes.push(new _.Type('!gpu.async.token'));\n        }\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    if (Array.isArray(asyncDependencies)) {\n                        asyncDependencies.push(parser.parseOperand());\n                    } else {\n                        parser.parseOperand();\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n        }\n    }\n\n    parseOffloadingHandler(parser /*, op, args */) {\n        if (parser.parseOptionalLess()) {\n            parser.parseAttribute();\n            parser.parseGreater();\n        }\n    }\n};\n\n_.ArmSMEDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'arm_sme');\n        this.registerCustomAttribute('ArmSME_TypeSizeAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n        this.registerCustomAttribute('ArmSME_TileSliceLayoutAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n        this.registerCustomAttribute('ArmSME_CombiningKindAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'arm_sme.outerproduct' && op.operands.length >= 2) {\n            const lhsType = op.operands[0].type;\n            if (lhsType instanceof _.VectorType && lhsType.shape.length === 1 && lhsType.scalableDims?.[0]) {\n                const size = lhsType.shape[0];\n                const tileType = new _.VectorType([size, size], lhsType.elementType, [true, true]);\n                op.addTypes([tileType]);\n                return;\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.ArmNeonDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'arm_neon');\n    }\n};\n\n_.ArmSVEDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'arm_sve');\n    }\n};\n\n_.AMDGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'amdgpu');\n        this.registerCustomDirective('MNKDimensionList', this.parseMNKDimensionList.bind(this));\n    }\n\n    parseMNKDimensionList(parser, op, mAttr, nAttr, kAttr) {\n        const dimInfo = parser.parseDimensionList(false, false);\n        const dims = dimInfo.dimensions;\n        if (dims.length >= 3 && mAttr && nAttr && kAttr) {\n            op.addAttribute(mAttr, dims[0]);\n            op.addAttribute(nAttr, dims[1]);\n            op.addAttribute(kAttr, dims[2]);\n        }\n    }\n};\n\n_.NVGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'nvgpu');\n        this.registerCustomType('NVGPU_TensorMapDescriptor', this.parseTensorMapDescriptor.bind(this));\n        this.registerCustomType('NVGPU_WarpgroupAccumulator', this.parseWarpgroupAccumulator.bind(this));\n        this.registerCustomType('NVGPU_WarpgroupMatrixDescriptor', this.parseWarpgroupMatrixDescriptor.bind(this));\n        this.registerCustomType('NVGPU_MBarrierGroup', this.parseMBarrierGroup.bind(this));\n    }\n\n    parseTensorMapDescriptor(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            return new _.Type(`!nvgpu.tensormap.descriptor${content}`);\n        }\n        return null;\n    }\n\n    parseWarpgroupAccumulator(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            return new _.Type(`!nvgpu.warpgroup.accumulator${content}`);\n        }\n        return null;\n    }\n\n    parseWarpgroupMatrixDescriptor(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            return new _.Type(`!nvgpu.warpgroup.descriptor${content}`);\n        }\n        return null;\n    }\n\n    parseMBarrierGroup(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            return new _.Type(`!nvgpu.mbarrier.barrier${content}`);\n        }\n        return null;\n    }\n};\n\n_.NVVMDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'nvvm');\n    }\n\n    parseOperation(parser, result) {\n        // Reference: NVVMDialect.cpp - parseMmaOperand\n        // Helper to parse operand list in the format: name[operands]\n        const parseMmaOperand = (name) => {\n            parser.parseKeyword(name);\n            return parser.parseOperandList('optionalSquare');\n        };\n\n        // Reference: NVVMDialect.cpp - MmaOp::parse\n        if (result.op === 'nvvm.mma.sync') {\n            const fragsA = parseMmaOperand('A');\n            const fragsB = parseMmaOperand('B');\n            const fragsC = parseMmaOperand('C');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                if (funcType instanceof _.FunctionType) {\n                    parser.resolveOperands(fragsA, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsB, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsC, funcType.inputs, result.operands);\n                    result.addTypes(funcType.results);\n                }\n            }\n            return true;\n        }\n        // Reference: NVVMDialect.cpp - MmaSpOp::parse\n        if (result.op === 'nvvm.mma.sp.sync') {\n            const fragsA = parseMmaOperand('A');\n            const fragsB = parseMmaOperand('B');\n            const fragsC = parseMmaOperand('C');\n            const fragsSparseMetadata = parseMmaOperand('sparseMetadata');\n            const fragsSelector = parseMmaOperand('selector');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                if (funcType instanceof _.FunctionType) {\n                    parser.resolveOperands(fragsA, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsB, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsC, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsSparseMetadata, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsSelector, funcType.inputs, result.operands);\n                    result.addTypes(funcType.results);\n                }\n            }\n            return true;\n        }\n        // Reference: NVVMDialect.cpp - MmaBlockScaleOp::parse\n        if (result.op === 'nvvm.mma.block_scale') {\n            const fragsA = parseMmaOperand('A');\n            const fragsB = parseMmaOperand('B');\n            const fragsC = parseMmaOperand('C');\n            const scaleAOperands = parseMmaOperand('scaleA');\n            const scaleBOperands = parseMmaOperand('scaleB');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                if (funcType instanceof _.FunctionType) {\n                    parser.resolveOperands(fragsA, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsB, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsC, funcType.inputs, result.operands);\n                    parser.resolveOperands(scaleAOperands, funcType.inputs, result.operands);\n                    parser.resolveOperands(scaleBOperands, funcType.inputs, result.operands);\n                    result.addTypes(funcType.results);\n                }\n            }\n            return true;\n        }\n        // Reference: NVVMDialect.cpp - MmaSpBlockScaleOp::parse\n        if (result.op === 'nvvm.mma.sp.block_scale') {\n            const fragsA = parseMmaOperand('A');\n            const fragsB = parseMmaOperand('B');\n            const fragsC = parseMmaOperand('C');\n            const metadataOperands = parseMmaOperand('sparseMetadata');\n            const selectorOperands = parseMmaOperand('selector');\n            const scaleAOperands = parseMmaOperand('scaleA');\n            const scaleBOperands = parseMmaOperand('scaleB');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                if (funcType instanceof _.FunctionType) {\n                    parser.resolveOperands(fragsA, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsB, funcType.inputs, result.operands);\n                    parser.resolveOperands(fragsC, funcType.inputs, result.operands);\n                    parser.resolveOperands(metadataOperands, funcType.inputs, result.operands);\n                    parser.resolveOperands(selectorOperands, funcType.inputs, result.operands);\n                    parser.resolveOperands(scaleAOperands, funcType.inputs, result.operands);\n                    parser.resolveOperands(scaleBOperands, funcType.inputs, result.operands);\n                    result.addTypes(funcType.results);\n                }\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.OpenMPDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'omp');\n        this.registerCustomDirective('IteratorHeader', this.parseIteratorHeader.bind(this));\n        this.registerCustomDirective('MapClause', this.parseMapClause.bind(this));\n        this.registerCustomDirective('CaptureType', this.parseCaptureType.bind(this));\n        this.registerCustomDirective('MembersIndex', this.parseMembersIndex.bind(this));\n        this.registerCustomDirective('PrivateReductionRegion', this.parsePrivateReductionRegion.bind(this));\n        this.registerCustomDirective('PrivateRegion', this.parsePrivateReductionRegion.bind(this));\n        this.registerCustomDirective('InReductionPrivateRegion', this.parsePrivateReductionRegion.bind(this));\n        this.registerCustomDirective('InReductionPrivateReductionRegion', this.parsePrivateReductionRegion.bind(this));\n        this.registerCustomDirective('TaskReductionRegion', this.parsePrivateReductionRegion.bind(this));\n        this.registerCustomDirective('UseDeviceAddrUseDevicePtrRegion', this.parsePrivateReductionRegion.bind(this));\n        this.registerCustomDirective('TargetOpRegion', this.parseTargetOpRegion.bind(this));\n        this.registerCustomDirective('ClauseAttr', this.parseClauseAttr.bind(this));\n        this.registerCustomDirective('DependVarList', this.parseDependVarList.bind(this));\n        this.registerCustomDirective('LoopTransformClis', this.parseLoopTransformClis.bind(this));\n        this.registerCustomDirective('SynchronizationHint', this.parseSynchronizationHint.bind(this));\n        this.registerCustomDirective('AlignedClause', this.parseAlignedClause.bind(this));\n        this.registerCustomDirective('ScheduleClause', this.parseScheduleClause.bind(this));\n        this.registerCustomDirective('AllocateAndAllocator', this.parseAllocateAndAllocator.bind(this));\n        this.registerCustomDirective('LinearClause', this.parseLinearClause.bind(this));\n        this.registerCustomDirective('UniformClause', this.parseUniformClause.bind(this));\n        this.registerCustomDirective('OrderClause', this.parseOrderClause.bind(this));\n        this.registerCustomDirective('Copyprivate', this.parseCopyprivate.bind(this));\n        this.registerCustomDirective('GrainsizeClause', this.parseGranularityClause.bind(this));\n        this.registerCustomDirective('NumTasksClause', this.parseGranularityClause.bind(this));\n        this.registerCustomDirective('AffinityClause', this.parseAffinityClause.bind(this));\n        this.registerCustomAttribute('DataSharingClauseTypeAttr', this.parseDataSharingClauseTypeAttr.bind(this));\n        this.registerCustomAttribute('ClauseCancelConstructTypeAttr', this.parseParenthesizedEnumAttr.bind(this));\n        this.registerCustomAttribute('ClauseDependAttr', this.parseParenthesizedEnumAttr.bind(this));\n        this.registerCustomAttribute('ClauseOrderingIncludeTypeAttr', this.parseParenthesizedEnumAttr.bind(this));\n        this.registerCustomAttribute('ClauseTypeAttr', this.parseParenthesizedEnumAttr.bind(this));\n        this.registerCustomAttribute('ClauseDistScheduleTypeAttr', this.parseParenthesizedEnumAttr.bind(this));\n        this.registerCustomAttribute('OrderModifierAttr', this.parseParenthesizedEnumAttr.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'omp.loop_nest') {\n            return this.parseLoopNestOp(parser, result);\n        }\n        if (result.op === 'omp.canonical_loop') {\n            return this.parseCanonicalLoopOp(parser, result);\n        }\n        if (result.op === 'omp.unroll_heuristic') {\n            return this.parseUnrollHeuristicOp(parser, result);\n        }\n        if (result.op === 'omp.target_allocmem') {\n            const unresolvedDevice = parser.parseOperand();\n            parser.parseColon();\n            const deviceType = parser.parseType();\n            parser.resolveOperand(unresolvedDevice, deviceType, result.operands);\n            parser.parseComma();\n            const inType = parser.parseType();\n            result.addAttribute('in_type', { value: inType, type: 'type' });\n            const unresolvedTypeparams = [];\n            if (parser.parseOptionalLParen()) {\n                do {\n                    unresolvedTypeparams.push(parser.parseOperand());\n                } while (parser.parseOptionalComma());\n                parser.parseColon();\n                const types = parser.parseTypeList();\n                parser.resolveOperands(unresolvedTypeparams, types, result.operands);\n                parser.parseRParen();\n            }\n            const unresolvedShape = [];\n            while (parser.parseOptionalComma()) {\n                unresolvedShape.push(parser.parseOperand());\n            }\n            const indexType = new _.IndexType();\n            for (const s of unresolvedShape) {\n                parser.resolveOperand(s, indexType, result.operands);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            result.addAttribute('operandSegmentSizes', new _.DenseI32ArrayAttr([1, unresolvedTypeparams.length, unresolvedShape.length]));\n            result.addTypes([new _.IntegerType('i64')]);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseCanonicalLoopOp(parser, result) {\n        if (parser.parseOptionalLParen()) {\n            const cliOperand = parser.parseOperand();\n            // CLI operand is a loop handle, resolve with null type\n            parser.resolveOperand(cliOperand, null, result.operands);\n            parser.parseRParen();\n        }\n        const inductionVar = parser.parseOperand();\n        parser.parseColon();\n        const ivType = parser.parseType();\n        parser.parseKeyword('in');\n        parser.parseKeyword('range');\n        parser.parseLParen();\n        const rangeOperand = parser.parseOperand();\n        parser.resolveOperand(rangeOperand, null, result.operands);\n        parser.parseRParen();\n        const region = result.addRegion();\n        // Pass induction variable as region argument\n        const regionArgs = [{ name: inductionVar.name, type: ivType }];\n        parser.parseRegion(region, regionArgs);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseUnrollHeuristicOp(parser, result) {\n        parser.parseLParen();\n        const applyee = parser.parseOperand();\n        // Applyee is a loop handle, resolve with null type\n        parser.resolveOperand(applyee, null, result.operands);\n        parser.parseRParen();\n        if (parser.parseOptionalArrow()) {\n            parser.parseLParen();\n            parser.parseRParen();\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseLoopNestOp(parser, result) {\n        // Parse CLI operands (loop handles)\n        const unresolvedCli = [];\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    unresolvedCli.push(parser.parseOperand());\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        // Parse types for CLI operands — C++ uses parseColonType (single type)\n        const cliTypes = [];\n        if (parser.parseOptionalColon()) {\n            cliTypes.push(parser.parseType());\n        }\n        parser.resolveOperands(unresolvedCli, cliTypes, result.operands);\n        if (parser.parseOptionalEqual()) {\n            if (parser.parseOptionalLParen()) {\n                const unresolvedLb = [];\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        unresolvedLb.push(parser.parseOperand());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n                for (const lb of unresolvedLb) {\n                    parser.resolveOperand(lb, null, result.operands);\n                }\n            }\n            if (parser.parseOptionalKeyword('to')) {\n                if (parser.parseOptionalLParen()) {\n                    const unresolvedUb = [];\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            unresolvedUb.push(parser.parseOperand());\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                    for (const ub of unresolvedUb) {\n                        parser.resolveOperand(ub, null, result.operands);\n                    }\n                }\n            }\n            parser.parseOptionalKeyword('inclusive');\n            if (parser.parseOptionalKeyword('step')) {\n                if (parser.parseOptionalLParen()) {\n                    const unresolvedStep = [];\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            unresolvedStep.push(parser.parseOperand());\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                    for (const step of unresolvedStep) {\n                        parser.resolveOperand(step, null, result.operands);\n                    }\n                }\n            }\n        }\n        if (parser.parseOptionalKeyword('collapse')) {\n            parser.parseLParen();\n            const value = parser.parseInteger();\n            result.addAttribute('collapse_num_loops', value);\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalKeyword('tiles')) {\n            parser.parseLParen();\n            const tiles = [];\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    tiles.push(parser.parseInteger());\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            result.addAttribute('tile_sizes', tiles);\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseParenthesizedEnumAttr(parser) {\n        if (parser.parseOptionalLParen()) {\n            const value = parser.parseOptionalKeyword();\n            parser.parseRParen();\n            return new _.TypedAttr(value, null);\n        }\n        return null;\n    }\n\n    parseOrderClause(parser, result) {\n        const orderModifiers = ['reproducible', 'unconstrained'];\n        const orderKinds = ['concurrent'];\n        let orderMod = null;\n        let orderKind = null;\n        const keyword = parser.parseOptionalKeyword();\n        if (orderModifiers.includes(keyword)) {\n            orderMod = keyword;\n            parser.parseColon();\n            orderKind = parser.parseOptionalKeyword();\n        } else if (orderKinds.includes(keyword)) {\n            orderKind = keyword;\n        }\n        if (orderKind) {\n            result.addAttribute('order_kind', orderKind);\n        }\n        if (orderMod) {\n            result.addAttribute('order_mod', orderMod);\n        }\n    }\n\n    parseLinearClause(parser, result) {\n        // C++ format: %var : type = %step : type, ...\n        const unresolvedLinearVars = [];\n        const linearVarTypes = [];\n        const unresolvedStepVars = [];\n        const stepVarTypes = [];\n        parser.parseCommaSeparatedList('none', () => {\n            unresolvedLinearVars.push(parser.parseOperand());\n            parser.parseColon();\n            linearVarTypes.push(parser.parseType());\n            parser.parseEqual();\n            unresolvedStepVars.push(parser.parseOperand());\n            parser.parseColon();\n            stepVarTypes.push(parser.parseType());\n        });\n        parser.resolveOperands(unresolvedLinearVars, linearVarTypes, result.operands);\n        parser.resolveOperands(unresolvedStepVars, stepVarTypes, result.operands);\n    }\n\n    parseUniformClause(parser, result, uniformVars, uniformTypes) {\n        parser.parseCommaSeparatedList('none', () => {\n            uniformVars.push(parser.parseOperand());\n            parser.parseColon();\n            uniformTypes.push(parser.parseType());\n        });\n    }\n\n    parseCopyprivate(parser, op, varsAttr, typesAttr, symsAttr) {\n        const unresolvedVars = [];\n        const varTypes = [];\n        const copyprivateSyms = [];\n        do {\n            unresolvedVars.push(parser.parseOperand());\n            parser.parseArrow();\n            const sym = parser.parseOptionalSymbolName();\n            parser.parseColon();\n            const type = parser.parseType();\n            varTypes.push(type);\n            copyprivateSyms.push(sym);\n        } while (parser.parseOptionalComma());\n        parser.resolveOperands(unresolvedVars, varTypes, op.operands);\n        if (symsAttr) {\n            op.addAttribute(symsAttr, copyprivateSyms);\n        }\n    }\n\n    parseGranularityClause(parser, op, modAttr) {\n        const modifier = parser.parseOptionalKeyword();\n        if (modifier) {\n            parser.parseComma();\n        }\n        const unresolvedOperand = parser.parseOperand();\n        parser.parseColon();\n        const type = parser.parseType();\n        parser.resolveOperand(unresolvedOperand, type, op.operands);\n        if (modAttr && modifier) {\n            op.addAttribute(modAttr, modifier);\n        }\n    }\n\n    parseAlignedClause(parser, result) {\n        const unresolvedVars = [];\n        const varTypes = [];\n        const alignments = [];\n        let alignedVar = parser.parseOptionalOperand();\n        while (alignedVar) {\n            unresolvedVars.push(alignedVar);\n            parser.parseColon();\n            const type = parser.parseType();\n            varTypes.push(type);\n            parser.parseArrow();\n            const alignment = parser.parseAttribute();\n            alignments.push(alignment);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            alignedVar = parser.parseOptionalOperand();\n        }\n        parser.resolveOperands(unresolvedVars, varTypes, result.operands);\n        if (alignments.length > 0) {\n            result.addAttribute('alignments', alignments);\n        }\n    }\n\n    // Following reference: parseAffinityClause / parseSplitIteratedList in OpenMPDialect.cpp:4658/1438\n    parseAffinityClause(parser, result, iterated, affinityVars, iteratedTypes, affinityTypes) {\n        parser.parseCommaSeparatedList('none', () => {\n            const operand = parser.parseOperand();\n            const type = parser.parseColonType();\n            // Split into iterated vs plain based on type name\n            if (type && type.name && type.name.includes('iterated')) {\n                iterated.push(operand);\n                iteratedTypes.push(type);\n            } else {\n                affinityVars.push(operand);\n                affinityTypes.push(type);\n            }\n        });\n    }\n\n    parseScheduleClause(parser, result) {\n        const scheduleKinds = ['static', 'dynamic', 'guided', 'auto', 'runtime', 'distribute'];\n        let scheduleKind = null;\n        for (const kind of scheduleKinds) {\n            if (parser.parseOptionalKeyword(kind)) {\n                scheduleKind = kind;\n                break;\n            }\n        }\n        if (scheduleKind) {\n            result.addAttribute('schedule_kind', scheduleKind);\n        }\n        if (parser.parseOptionalEqual()) {\n            const unresolvedChunk = parser.parseOptionalOperand();\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (unresolvedChunk) {\n                    parser.resolveOperand(unresolvedChunk, type, result.operands);\n                }\n            } else if (unresolvedChunk) {\n                parser.resolveOperand(unresolvedChunk, null, result.operands);\n            }\n        }\n        const modifiers = [];\n        while (parser.parseOptionalComma()) {\n            const mod = parser.parseOptionalKeyword();\n            if (mod) {\n                modifiers.push(mod);\n            }\n        }\n        if (modifiers.length > 0) {\n            result.addAttribute('schedule_modifiers', modifiers);\n        }\n    }\n\n    parseAllocateAndAllocator(parser, result) {\n        const unresolvedAllocators = [];\n        const allocatorTypes = [];\n        const unresolvedAllocates = [];\n        const allocateTypes = [];\n        let allocOp = parser.parseOptionalOperand();\n        while (allocOp) {\n            unresolvedAllocators.push(allocOp);\n            parser.parseColon();\n            allocatorTypes.push(parser.parseType());\n            parser.parseArrow();\n            unresolvedAllocates.push(parser.parseOperand());\n            parser.parseColon();\n            allocateTypes.push(parser.parseType());\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            allocOp = parser.parseOptionalOperand();\n        }\n        parser.resolveOperands(unresolvedAllocators, allocatorTypes, result.operands);\n        parser.resolveOperands(unresolvedAllocates, allocateTypes, result.operands);\n    }\n\n    parseSynchronizationHint(parser, op, hintAttr = 'hint') {\n        if (parser.parseOptionalKeyword('none')) {\n            op.addAttribute(hintAttr, 0);\n            return;\n        }\n        let hint = 0;\n        const hints = [];\n        let keyword = parser.parseOptionalKeyword();\n        while (keyword) {\n            hints.push(keyword);\n            if (keyword === 'uncontended') {\n                hint |= 1;\n            } else if (keyword === 'contended') {\n                hint |= 2;\n            } else if (keyword === 'nonspeculative') {\n                hint |= 4;\n            } else if (keyword === 'speculative') {\n                hint |= 8;\n            }\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            keyword = parser.parseOptionalKeyword();\n        }\n        op.addAttribute(hintAttr, hint);\n    }\n\n    parseClauseAttr(parser, op, attrName) {\n        const enumValue = parser.parseOptionalKeyword();\n        if (enumValue && attrName) {\n            op.addAttribute(attrName, enumValue);\n        }\n    }\n\n    parseTargetOpRegion(parser, result) {\n        const unitAttrKeywords = ['nowait', 'bare'];\n        for (const kw of unitAttrKeywords) {\n            if (parser.parseOptionalKeyword(kw)) {\n                result.addAttribute(kw, true);\n            }\n        }\n        if (parser.parseOptionalKeyword('depend')) {\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    parser.parseKeyword();\n                    parser.parseArrow();\n                    parser.parseOperand();\n                    parser.parseColonType();\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        const singleValueKeywords = ['device', 'if', 'thread_limit'];\n        for (const kw of singleValueKeywords) {\n            if (parser.parseOptionalKeyword(kw)) {\n                parser.parseLParen();\n                const unresolvedOperand = parser.parseOptionalOperand();\n                if (unresolvedOperand) {\n                    let opType = null;\n                    if (parser.parseOptionalColon()) {\n                        opType = parser.parseType();\n                    }\n                    parser.resolveOperand(unresolvedOperand, opType, result.operands);\n                } else if (parser.parseOptionalColon()) {\n                    parser.parseType();\n                }\n                parser.parseRParen();\n            }\n        }\n        if (parser.parseOptionalKeyword('is_device_ptr')) {\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    parser.parseOptionalOperand();\n                } while (parser.parseOptionalComma());\n                if (parser.parseOptionalColon()) {\n                    do {\n                        parser.parseType();\n                    } while (parser.parseOptionalComma());\n                }\n                parser.parseRParen();\n            }\n        }\n        const keywords = ['has_device_addr', 'host_eval', 'in_reduction', 'map_entries', 'private', 'reduction', 'task_reduction', 'use_device_addr', 'use_device_ptr'];\n        let progress = true;\n        while (progress) {\n            progress = false;\n            // Handle private_barrier unit attribute\n            if (parser.parseOptionalKeyword('private_barrier')) {\n                result.addAttribute('private_needs_barrier', true);\n                progress = true;\n                continue;\n            }\n            // Handle list clauses\n            const clauseKw = parser.parseOptionalKeyword();\n            if (clauseKw && keywords.includes(clauseKw)) {\n                progress = true;\n                if (parser.parseOptionalLParen()) {\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            parser.parseOptionalKeyword('byref');\n                            parser.parseOptionalSymbolName();\n                            parser.parseOptionalOperand();\n                            if (parser.parseOptionalArrow()) {\n                                parser.parseOptionalOperand();\n                            }\n                            if (parser.parseOptionalLSquare()) {\n                                parser.parseKeyword('map_idx');\n                                parser.parseEqual();\n                                parser.parseInteger();\n                                parser.parseRSquare();\n                            }\n                        } while (parser.parseOptionalComma());\n                        if (parser.parseOptionalColon()) {\n                            do {\n                                parser.parseType();\n                            } while (parser.parseOptionalComma());\n                        }\n                        parser.parseRParen();\n                    }\n                }\n            }\n        }\n        const region = {};\n        if (parser.parseOptionalRegion(region)) {\n            result.regions.push(region);\n        }\n    }\n\n    parseIteratorHeader(parser, op) {\n        // Syntax: %iv: type, %iv2: type) = (%lb to %ub step %st, %lb2 to %ub2 step %st2) { region }\n        // The leading `(` was already consumed by the literal in the assemblyFormat.\n        const regionArgs = [];\n        const lowerBounds = [];\n        const upperBounds = [];\n        const steps = [];\n        do {\n            const arg = parser.parseOperand();\n            parser.parseColon();\n            const type = parser.parseType();\n            regionArgs.push({ name: arg.name, type });\n        } while (parser.parseOptionalComma());\n        parser.parseRParen();\n        parser.parseEqual();\n        parser.parseLParen();\n        do {\n            lowerBounds.push(parser.parseOperand());\n            parser.parseKeyword('to');\n            upperBounds.push(parser.parseOperand());\n            parser.parseKeyword('step');\n            steps.push(parser.parseOperand());\n        } while (parser.parseOptionalComma());\n        parser.parseRParen();\n        const region = op.addRegion();\n        parser.parseRegion(region, regionArgs);\n        const indexType = new _.IndexType();\n        for (const lb of lowerBounds) {\n            parser.resolveOperand(lb, indexType, op.operands);\n        }\n        for (const ub of upperBounds) {\n            parser.resolveOperand(ub, indexType, op.operands);\n        }\n        for (const st of steps) {\n            parser.resolveOperand(st, indexType, op.operands);\n        }\n    }\n\n    parseMapClause(parser, op, attrName = 'map_type') {\n        const mapFlags = [];\n        do {\n            const flag = parser.parseOptionalKeyword();\n            if (flag) {\n                mapFlags.push(flag);\n            }\n        } while (parser.parseOptionalComma());\n\n        if (attrName && mapFlags.length > 0) {\n            op.addAttribute(attrName, mapFlags.join(', '));\n        }\n    }\n\n    parseCaptureType(parser, op, attrName) {\n        const captureType = parser.parseOptionalKeyword();\n        if (captureType) {\n            if (attrName) {\n                op.addAttribute(attrName, captureType);\n            }\n        }\n    }\n\n    parseMembersIndex(parser, op, attrName) {\n        const memberIndices = [];\n        do {\n            if (parser.parseOptionalLSquare()) {\n                const indices = [];\n                do {\n                    const idx = parser.parseOptionalInteger();\n                    if (idx !== null) {\n                        indices.push(idx);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n                memberIndices.push(indices);\n            }\n        } while (parser.parseOptionalComma());\n\n        if (attrName && memberIndices.length > 0) {\n            op.addAttribute(attrName, memberIndices);\n        }\n    }\n\n    parsePrivateReductionRegion(parser, result) {\n        const singleValueClauses = ['if', 'num_threads', 'thread_limit', 'device', 'safelen', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'final', 'filter'];\n        const enumClauses = ['proc_bind', 'order', 'schedule', 'dist_schedule', 'memory_order', 'hint'];\n        const listClauses = ['private', 'reduction', 'in_reduction', 'task_reduction', 'copyin', 'copyprivate', 'firstprivate', 'lastprivate', 'shared', 'linear', 'aligned', 'nontemporal', 'inclusive', 'exclusive', 'allocate', 'depend'];\n        const unitClauses = ['nowait', 'untied', 'mergeable', 'nogroup', 'simd', 'threads', 'seq_cst', 'acq_rel', 'acquire', 'release', 'relaxed', 'private_barrier'];\n        let progress = true;\n        while (progress) {\n            progress = false;\n            // Handle single-value clauses: keyword(value : type)\n            for (const kw of singleValueClauses) {\n                if (parser.parseOptionalKeyword(kw)) {\n                    progress = true;\n                    parser.parseLParen();\n                    let unresolvedOp = null;\n                    let opType = null;\n                    unresolvedOp = parser.parseOptionalOperand();\n                    if (!unresolvedOp) {\n                        const intVal = parser.parseOptionalInteger();\n                        if (intVal !== null) {\n                            result.addAttribute(kw, intVal);\n                        }\n                    }\n                    if (parser.parseOptionalColon()) {\n                        opType = parser.parseType();\n                    }\n                    if (unresolvedOp) {\n                        parser.resolveOperand(unresolvedOp, opType, result.operands);\n                    }\n                    parser.parseRParen();\n                }\n            }\n            // Handle enum clauses: keyword(enum_value)\n            for (const kw of enumClauses) {\n                if (parser.parseOptionalKeyword(kw)) {\n                    progress = true;\n                    parser.parseLParen();\n                    const value = parser.parseKeyword();\n                    result.addAttribute(kw, value);\n                    // Handle modifier syntax like schedule(static, value)\n                    while (parser.parseOptionalComma()) {\n                        const modOperand = parser.parseOptionalOperand();\n                        if (modOperand) {\n                            let opType = null;\n                            if (parser.parseOptionalColon()) {\n                                opType = parser.parseType();\n                            }\n                            parser.resolveOperand(modOperand, opType, result.operands);\n                        } else if (parser.parseOptionalKeyword()) {\n                            if (parser.parseOptionalColon()) {\n                                parser.parseType();\n                            }\n                        }\n                    }\n                    parser.parseRParen();\n                }\n            }\n            // Handle list clauses: keyword(syms %vals -> %new_vals : types) or keyword(@sym %val : type, ...)\n            for (const kw of listClauses) {\n                if (parser.parseOptionalKeyword(kw)) {\n                    progress = true;\n                    if (parser.parseOptionalLParen()) {\n                        if (parser.parseOptionalKeyword('mod')) {\n                            parser.parseColon();\n                            parser.parseKeyword();\n                            parser.parseComma();\n                        }\n                        const unresolvedOperands = [];\n                        if (!parser.parseOptionalRParen()) {\n                            do {\n                                parser.parseOptionalKeyword('byref');\n                                parser.parseOptionalSymbolName();\n                                const listOp = parser.parseOptionalOperand();\n                                if (listOp) {\n                                    unresolvedOperands.push(listOp);\n                                }\n                                if (parser.parseOptionalArrow()) {\n                                    parser.parseOptionalOperand();\n                                }\n                                if (parser.parseOptionalLSquare()) {\n                                    parser.parseKeyword('map_idx');\n                                    parser.parseEqual();\n                                    parser.parseInteger();\n                                    parser.parseRSquare();\n                                }\n                            } while (parser.parseOptionalComma());\n                            const types = [];\n                            if (parser.parseOptionalColon()) {\n                                do {\n                                    types.push(parser.parseType());\n                                } while (parser.parseOptionalComma());\n                            }\n                            parser.resolveOperands(unresolvedOperands, types, result.operands);\n                            parser.parseRParen();\n                        }\n                    }\n                }\n            }\n            // Handle unit clauses (boolean flags)\n            for (const kw of unitClauses) {\n                if (parser.parseOptionalKeyword(kw)) {\n                    progress = true;\n                    // private_barrier maps to private_needs_barrier attribute\n                    const attrName = kw === 'private_barrier' ? 'private_needs_barrier' : kw;\n                    result.addAttribute(attrName, true);\n                }\n            }\n            // Handle map_entries clause: map_entries(%vars : types)\n            if (parser.parseOptionalKeyword('map_entries')) {\n                progress = true;\n                parser.parseLParen();\n                const unresolvedMapVars = [];\n                do {\n                    const mapOp = parser.parseOptionalOperand();\n                    if (mapOp) {\n                        unresolvedMapVars.push(mapOp);\n                    } else {\n                        break;\n                    }\n                } while (parser.parseOptionalComma());\n                const mapTypes = [];\n                if (parser.parseOptionalColon()) {\n                    do {\n                        mapTypes.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                }\n                for (let i = 0; i < unresolvedMapVars.length; i++) {\n                    const type = i < mapTypes.length ? mapTypes[i] : null;\n                    parser.resolveOperand(unresolvedMapVars[i], type, result.operands);\n                }\n                parser.parseRParen();\n            }\n            // Handle num_teams clause: num_teams(lower : type to upper : type) or num_teams(to upper : type)\n            if (parser.parseOptionalKeyword('num_teams')) {\n                progress = true;\n                parser.parseLParen();\n                if (parser.parseOptionalKeyword('to')) {\n                    const upper = parser.parseOptionalOperand();\n                    if (upper) {\n                        let upperType = null;\n                        if (parser.parseOptionalColon()) {\n                            upperType = parser.parseType();\n                        }\n                        parser.resolveOperand(upper, upperType, result.operands);\n                    }\n                } else {\n                    const lower = parser.parseOptionalOperand();\n                    if (lower) {\n                        let lowerType = null;\n                        if (parser.parseOptionalColon()) {\n                            lowerType = parser.parseType();\n                        }\n                        parser.resolveOperand(lower, lowerType, result.operands);\n                        parser.parseKeyword('to');\n                        const upper = parser.parseOptionalOperand();\n                        if (upper) {\n                            let upperType = null;\n                            if (parser.parseOptionalColon()) {\n                                upperType = parser.parseType();\n                            }\n                            parser.resolveOperand(upper, upperType, result.operands);\n                        }\n                    }\n                }\n                parser.parseRParen();\n            }\n            // Handle use_device_addr/use_device_ptr clauses: keyword(%var -> %arg : type, ...)\n            for (const kw of ['use_device_addr', 'use_device_ptr', 'has_device_addr', 'host_eval']) {\n                if (parser.parseOptionalKeyword(kw)) {\n                    progress = true;\n                    parser.parseLParen();\n                    const unresolvedOperands = [];\n                    do {\n                        const devOp = parser.parseOptionalOperand();\n                        if (devOp) {\n                            unresolvedOperands.push(devOp);\n                        } else {\n                            break;\n                        }\n                        if (parser.parseOptionalArrow()) {\n                            parser.parseOptionalOperand();\n                        }\n                    } while (parser.parseOptionalComma());\n                    const types = [];\n                    if (parser.parseOptionalColon()) {\n                        do {\n                            types.push(parser.parseType());\n                        } while (parser.parseOptionalComma());\n                    }\n                    for (let i = 0; i < unresolvedOperands.length; i++) {\n                        const type = i < types.length ? types[i] : null;\n                        parser.resolveOperand(unresolvedOperands[i], type, result.operands);\n                    }\n                    parser.parseRParen();\n                }\n            }\n        }\n        const region = {};\n        parser.parseRegion(region);\n        result.regions.push(region);\n    }\n\n    parseDataSharingClauseTypeAttr(parser) {\n        if (parser.parseOptionalLBrace()) {\n            parser.parseKeyword('type');\n            parser.parseEqual();\n            const value = parser.parseKeyword();\n            parser.parseRBrace();\n            return { value };\n        }\n        return null;\n    }\n\n    parseDependVarList(parser, op, operandAttr, typesAttr, kindAttr) {\n        const dependVars = [];\n        const dependTypes = [];\n        const dependKinds = [];\n        do {\n            const keyword = parser.parseKeyword();\n            dependKinds.push(keyword);\n            parser.parseArrow();\n            const operand = parser.parseOperand();\n            dependVars.push(operand);\n            parser.parseColon();\n            const type = parser.parseType();\n            dependTypes.push(type);\n        } while (parser.parseOptionalComma());\n        if (operandAttr) {\n            // depend_vars are SSA operands - resolve and add as operands\n            for (let i = 0; i < dependVars.length; i++) {\n                const type = i < dependTypes.length ? dependTypes[i] : null;\n                parser.resolveOperand(dependVars[i], type, op.operands);\n            }\n        }\n        if (kindAttr) {\n            op.addAttribute(kindAttr, dependKinds);\n        }\n    }\n\n    // Syntax 1: (generatees) <- (applyees) - generatees present (no leading <)\n    // Syntax 2: <- (applyees) - generatees omitted (starts with <-)\n    parseLoopTransformClis(parser, result) {\n        const generatees = [];\n        const applyees = [];\n        if (!parser.parseOptionalLess()) {\n            // Syntax 1: generatees present, parse (generatees) first\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const gen = parser.parseOptionalOperand();\n                    if (gen) {\n                        generatees.push(gen);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            parser.parseLess();\n        }\n        parser.parseMinus();\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const app = parser.parseOptionalOperand();\n                if (app) {\n                    applyees.push(app);\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        for (const g of generatees) {\n            parser.resolveOperand(g, null, result.operands);\n        }\n        for (const a of applyees) {\n            parser.resolveOperand(a, null, result.operands);\n        }\n    }\n};\n\n_.llvm = {};\n\n_.llvm.LLVMPointerType = class extends _.Type {\n\n    constructor(addressSpace) {\n        super(null);\n        this.addressSpace = addressSpace || 0;\n    }\n\n    static parse(parser) {\n        if (parser.parseOptionalLess()) {\n            const addressSpaceOrType = parser.parseOptionalInteger();\n            if (addressSpaceOrType !== null) {\n                parser.parseGreater();\n                return new _.llvm.LLVMPointerType(addressSpaceOrType);\n            }\n            const pointee = _.llvm.LLVMDialect.dispatchParse(parser);\n            parser.parseGreater();\n            return new _.Type(`!llvm.ptr<${pointee}>`);\n        }\n        return new _.llvm.LLVMPointerType(0);\n    }\n\n    toString() {\n        if (this.addressSpace) {\n            return `!llvm.ptr<${this.addressSpace}>`;\n        }\n        return '!llvm.ptr';\n    }\n};\n\n_.llvm.LLVMArrayType = class extends _.Type {\n\n    constructor(elementType, numElements) {\n        super(null);\n        this.elementType = elementType;\n        this.numElements = numElements;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const numElements = parser.parseInteger();\n        parser.parseKeyword('x');\n        const elementType = _.llvm.LLVMDialect.dispatchParse(parser);\n        parser.parseGreater();\n        return new _.llvm.LLVMArrayType(elementType, numElements);\n    }\n\n    toString() {\n        return `!llvm.array<${this.numElements} x ${this.elementType}>`;\n    }\n};\n\n_.llvm.LLVMStructType = class extends _.Type {\n\n    constructor(name, body, isPacked) {\n        super(null);\n        this.structName = name;\n        this.body = body;\n        this.isPacked = isPacked || false;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        let name = null;\n        if (parser.parseOptionalString) {\n            name = parser.parseOptionalString();\n        }\n        if (name !== null) {\n            if (parser.parseOptionalGreater()) {\n                return new _.llvm.LLVMStructType(name, null, false);\n            }\n            parser.parseComma();\n        }\n        if (parser.parseOptionalKeyword('opaque')) {\n            parser.parseGreater();\n            return new _.llvm.LLVMStructType(name, null, false);\n        }\n        const isPacked = Boolean(parser.parseOptionalKeyword('packed'));\n        parser.parseLParen();\n        const body = [];\n        if (!parser.parseOptionalRParen()) {\n            body.push(_.llvm.LLVMDialect.dispatchParse(parser));\n            while (parser.parseOptionalComma()) {\n                body.push(_.llvm.LLVMDialect.dispatchParse(parser));\n            }\n            parser.parseRParen();\n        }\n        parser.parseGreater();\n        return new _.llvm.LLVMStructType(name, body, isPacked);\n    }\n\n    toString() {\n        const parts = [];\n        if (this.structName) {\n            parts.push(`\"${this.structName}\"`);\n        }\n        if (this.body === null) {\n            if (this.structName) {\n                return `!llvm.struct<\"${this.structName}\">`;\n            }\n            return '!llvm.struct<opaque>';\n        }\n        const prefix = this.isPacked ? 'packed ' : '';\n        const members = this.body.map((t) => t?.toString ? t.toString() : t).join(', ');\n        if (this.structName) {\n            return `!llvm.struct<\"${this.structName}\", ${prefix}(${members})>`;\n        }\n        return `!llvm.struct<${prefix}(${members})>`;\n    }\n};\n\n_.llvm.LLVMFunctionType = class extends _.Type {\n\n    constructor(returnType, params, varArg = false) {\n        super(null);\n        this.returnType = returnType;\n        this.params = params || [];\n        this.varArg = varArg;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const returnType = _.llvm.LLVMDialect.dispatchParse(parser);\n        parser.parseLParen();\n        const params = [];\n        let varArg = false;\n        if (!parser.parseOptionalRParen()) {\n            if (parser.parseOptionalEllipsis()) {\n                varArg = true;\n            } else {\n                params.push(_.llvm.LLVMDialect.dispatchParse(parser));\n                while (parser.parseOptionalComma()) {\n                    if (parser.parseOptionalEllipsis()) {\n                        varArg = true;\n                        break;\n                    }\n                    params.push(_.llvm.LLVMDialect.dispatchParse(parser));\n                }\n            }\n            parser.parseRParen();\n        }\n        parser.parseGreater();\n        return new _.llvm.LLVMFunctionType(returnType, params, varArg);\n    }\n\n    get inputs() {\n        return this.params;\n    }\n\n    get results() {\n        return this.returnType ? [this.returnType] : [];\n    }\n\n    toString() {\n        const params = this.params.map((t) => t.toString());\n        if (this.varArg) {\n            params.push('...');\n        }\n        const returnType = this.returnType ? this.returnType.toString() : 'void';\n        return `!llvm.func<${returnType} (${params.join(', ')})>`;\n    }\n};\n\n_.llvm.LLVMDialect = class extends _.Dialect {\n\n    constructor(operations, name = 'llvm') {\n        super(operations, name);\n        this.registerCustomDirective('GEPIndices', this.parseGEPIndices.bind(this));\n        this.registerCustomDirective('IndirectBrOpSucessors', this.parseIndirectBrOpSucessors.bind(this));\n        this.registerCustomDirective('InsertExtractValueElementType', this.parseInsertExtractValueElementType.bind(this));\n        this.registerCustomDirective('LLVMLinkage', this.parseLLVMLinkage.bind(this));\n        this.registerCustomDirective('OpBundles', this.parseOpBundles.bind(this));\n        this.registerCustomDirective('ShuffleType', this.parseShuffleType.bind(this));\n        this.registerCustomDirective('SwitchOpCases', this.parseSwitchOpCases.bind(this));\n        this.registerCustomAttribute('LLVM_IntegerOverflowFlagsProp', this.parseLLVMIntegerOverflowFlagsProp.bind(this));\n        this.registerCustomAttribute('GEPNoWrapFlagsProp', (parser, type) => this.parseEnumFlags(parser, type, '|', true));\n        this.registerCustomAttribute('LLVM_BlockAddressAttr', this.parseLLVMBlockAddressAttr.bind(this));\n        this.registerCustomAttribute('LLVM_BlockTagAttr', this.parseLLVMBlockTagAttr.bind(this));\n        this.registerCustomType('LLVM_AnyPointer', this.parseLLVMPointerType.bind(this));\n        this.registerCustomType('LLVM_PointerInAddressSpace', this.parseLLVMPointerType.bind(this));\n        this.registerCustomType('LLVM_Type', (parser) => parser.parseType());\n    }\n\n    static dispatchParse(parser) {\n        const type = parser.parseOptionalType();\n        if (type) {\n            return type;\n        }\n        const key = parser.parseKeyword();\n        switch (key) {\n            case 'void': return null;\n            case 'ppc_fp128': return new _.Type('!llvm.ppc_fp128');\n            case 'token': return new _.Type('!llvm.token');\n            case 'label': return new _.Type('!llvm.label');\n            case 'metadata': return new _.Type('!llvm.metadata');\n            case 'x86_amx': return new _.Type('!llvm.x86_amx');\n            case 'func': return _.llvm.LLVMFunctionType.parse(parser);\n            case 'ptr': return _.llvm.LLVMPointerType.parse(parser);\n            case 'array': return _.llvm.LLVMArrayType.parse(parser);\n            case 'struct': return _.llvm.LLVMStructType.parse(parser);\n            default: throw new mlir.Error(`Unknown LLVM type '${key}'.`);\n        }\n    }\n\n    parseLLVMIntegerOverflowFlagsProp(parser) {\n        if (parser.parseOptionalKeyword('overflow')) {\n            return this.parseEnumFlagsAngleBracketComma(parser, { values: ['wrap', 'nuw', 'nsw'] });\n        }\n        return null;\n    }\n\n    parseLLVMBlockAddressAttr(parser) {\n        const content = parser.parseTypeParameters();\n        if (!content) {\n            return null;\n        }\n        return { blockaddress: content };\n    }\n\n    parseLLVMBlockTagAttr(parser) {\n        const content = parser.parseTypeParameters();\n        if (!content) {\n            return null;\n        }\n        return { blocktag: content };\n    }\n\n    parseLLVMPointerType(parser) {\n        const type = parser.parseOptionalType();\n        if (type) {\n            return type;\n        }\n        return _.llvm.LLVMPointerType.parse(parser);\n    }\n\n    getInsertExtractValueElementType(containerType, position) {\n        let llvmType = containerType.toString ? containerType.toString() : String(containerType);\n        for (const idx of position) {\n            const arrayMatch = llvmType.match(/^!llvm\\.array<(\\d+)\\s*x\\s*(.+)>$/);\n            if (arrayMatch) {\n                llvmType = arrayMatch[2].trim();\n                continue;\n            }\n            const structMatch = llvmType.match(/^!llvm\\.struct<(?:\"[^\"]*\",\\s*)?\\((.+)\\)>$/);\n            if (structMatch) {\n                const elementsStr = structMatch[1];\n                const body = [];\n                let depth = 0;\n                let current = '';\n                for (const char of elementsStr) {\n                    if (char === '<' || char === '(' || char === '[' || char === '{') {\n                        depth++;\n                        current += char;\n                    } else if (char === '>' || char === ')' || char === ']' || char === '}') {\n                        depth--;\n                        current += char;\n                    } else if (char === ',' && depth === 0) {\n                        body.push(current.trim());\n                        current = '';\n                    } else {\n                        current += char;\n                    }\n                }\n                if (current.trim()) {\n                    body.push(current.trim());\n                }\n                if (idx >= 0 && idx < body.length) {\n                    llvmType = body[idx];\n                    continue;\n                }\n            }\n            break;\n        }\n        return llvmType;\n    }\n\n    parseInsertExtractValueElementType(parser, op, resultTypes, containerTypes, positionArg) {\n        // Infer the value type from the container type and position.\n        // resultTypes = op.types (array to populate)\n        // containerTypes = array of container types from parsing\n        // positionArg = position attribute value (ArrayAttr or array)\n        if (containerTypes && containerTypes.length > 0) {\n            const containerType = containerTypes[0];\n            // Use the position argument if provided, otherwise fall back to op.attributes\n            const positionAttr = positionArg === undefined ? op.attributes.get('position') : positionArg;\n            const position = positionAttr && positionAttr.value ? positionAttr.value : positionAttr;\n            if (position && Array.isArray(position) && position.length > 0) {\n                const valueType = this.getInsertExtractValueElementType(containerType, position);\n                if (valueType && resultTypes.length === 0) {\n                    resultTypes.push(new _.Type(valueType));\n                }\n            }\n        }\n    }\n\n    parseLLVMLinkage(parser, op /*, args */) {\n        const linkage = parser.parseOptionalKeyword();\n        if (linkage) {\n            op.addAttribute('linkage', linkage);\n        }\n    }\n\n    parseOpBundles(parser, op /*, args */) {\n        // Parse operation bundles: [] or [\"tag\"()] or [\"tag\"(%0, %1 : i32, i32), ...]\n        // Returns: null if not present, true if success, throws on failure\n        // args[0] = $op_bundle_operands - operands for bundles\n        // args[1] = type($op_bundle_operands) - types\n        // args[2] = $op_bundle_tags - tags attribute\n\n        if (!parser.parseOptionalLSquare()) {\n            return null; // Not present (equivalent to std::nullopt)\n        }\n\n        if (parser.parseOptionalRSquare()) {\n            return true; // Success\n        }\n\n        const opBundles = [];\n        do {\n            const tag = parser.parseString();\n            parser.parseLParen();\n            const bundleOperands = [];\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    bundleOperands.push(parser.parseAttribute());\n                } while (parser.parseOptionalComma());\n                parser.parseColon();\n                do {\n                    parser.parseType();\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            opBundles.push({ tag, operands: bundleOperands });\n        } while (parser.parseOptionalComma());\n        parser.parseRSquare();\n\n        if (opBundles.length > 0) {\n            op.addAttribute('op_bundle_tags', opBundles);\n        }\n        return true; // Success\n    }\n\n    parseShuffleType(parser, op, v1Types, resTypes, maskAttr) {\n        if (resTypes.length > 0) {\n            return;\n        }\n        if (!v1Types || v1Types.length === 0 || !maskAttr) {\n            return;\n        }\n        const v1Type = v1Types[0];\n        if (!(v1Type instanceof _.VectorType)) {\n            return;\n        }\n        const mask = maskAttr.value === undefined ? maskAttr : maskAttr.value;\n        const maskLen = Array.isArray(mask) ? mask.length : 0;\n        if (maskLen > 0) {\n            const isScalable = v1Type.scalableDims && v1Type.scalableDims.some(Boolean);\n            const resType = new _.VectorType([BigInt(maskLen)], v1Type.elementType, isScalable ? [true] : []);\n            op.addTypes([resType]);\n        }\n    }\n\n    // Parse switch operation cases\n    // Where case: integer `:` bb-id (`(` ssa-use-and-type-list `)`)?\n    parseSwitchOpCases(parser, op /*, args */) {\n        // args[0] is ref(type($value)) - the flag type\n        // args[1] is $case_values - attribute to populate\n        // args[2] is $caseDestinations - successors array\n        // args[3] is $caseOperands - operands for each case\n        // args[4] is type($caseOperands) - types for case operands\n        if (!parser.parseOptionalLSquare()) {\n            return;\n        }\n        if (parser.parseOptionalRSquare()) {\n            return;\n        }\n        const caseValues = [];\n        const caseDestinations = [];\n        const caseOperands = [];\n        do {\n            // Handle negative case values: -1, -2, etc.\n            let sign = 1;\n            if (parser.parseOptionalMinus()) {\n                sign = -1;\n            }\n            const value = sign * parser.parseInteger();\n            caseValues.push(value);\n            parser.parseColon();\n            const successor = parser.parseOptionalSuccessor();\n            caseDestinations.push(successor);\n            if (parser.parseOptionalLParen()) {\n                const operands = [];\n                do {\n                    const caseOp = parser.parseOptionalOperand();\n                    if (caseOp) {\n                        operands.push({ name: caseOp });\n                    } else {\n                        break;\n                    }\n                } while (parser.parseOptionalComma());\n                if (parser.parseOptionalColon()) {\n                    let idx = 0;\n                    while (idx < operands.length) {\n                        const type = parser.parseType();\n                        if (operands[idx]) {\n                            operands[idx].type = type;\n                        }\n                        idx++;\n                        parser.parseOptionalComma();\n                    }\n                }\n                parser.parseRParen();\n                caseOperands.push(operands);\n            } else {\n                caseOperands.push([]);\n            }\n        } while (parser.parseOptionalComma());\n        parser.parseRSquare();\n        if (caseValues.length > 0) {\n            op.addAttribute('case_values', caseValues);\n        }\n        if (caseDestinations.length > 0) {\n            if (!op.successors) {\n                op.successors = [];\n            }\n            for (const dest of caseDestinations) {\n                op.successors.push({ name: dest });\n            }\n        }\n        // Note: caseOperands handling would require more complex logic\n        // to properly associate operands with their successors\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (mnemonic === 'struct') {\n                return _.llvm.LLVMStructType.parse(parser);\n            }\n            if (mnemonic === 'func') {\n                return _.llvm.LLVMFunctionType.parse(parser);\n            }\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (result.op === 'llvm.func') {\n            return this.parseLLVMFuncOp(parser, result);\n        }\n        if (result.op === 'llvm.mlir.global') {\n            return this.parseLLVMGlobalOp(parser, result);\n        }\n        if (result.op === 'llvm.mlir.alias') {\n            return this.parseLLVMAliasOp(parser, result);\n        }\n        if (result.op === 'llvm.alloca') {\n            return this.parseLLVMAllocaOp(parser, result);\n        }\n        if (result.op === 'llvm.call') {\n            return this.parseLLVMCallOp(parser, result);\n        }\n        if (result.op === 'llvm.call_intrinsic') {\n            return this.parseLLVMCallIntrinsicOp(parser, result);\n        }\n        if (result.op === 'llvm.invoke') {\n            return this.parseLLVMInvokeOp(parser, result);\n        }\n        if (result.op === 'llvm.landingpad') {\n            return this.parseLLVMLandingpadOp(parser, result);\n        }\n        if (result.op === 'llvm.icmp' || result.op === 'llvm.fcmp') {\n            return this.parseLLVMCmpOp(parser, result);\n        }\n        if (result.op.startsWith('llvm.intr.')) {\n            if (opInfo.metadata.assemblyFormat) {\n                return super.parseOperation(parser, result);\n            }\n            return this.parseLLVMIntrinsicOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseLLVMGlobalOp(parser, result) {\n        const linkageKeywords = ['external', 'available_externally', 'linkonce', 'linkonce_odr', 'weak', 'weak_odr', 'appending', 'internal', 'private', 'extern_weak', 'common'];\n        const __linkage = parser.parseOptionalKeyword(linkageKeywords);\n        if (__linkage) {\n            result.addAttribute('linkage', __linkage);\n        }\n        const visibilityKeywords = ['default', 'hidden', 'protected'];\n        const __visibility = parser.parseOptionalKeyword(visibilityKeywords);\n        if (__visibility) {\n            result.addAttribute('visibility_', __visibility);\n        }\n        if (parser.parseOptionalKeyword('thread_local')) {\n            result.addAttribute('thread_local_', true);\n        }\n        const unnamedAddrKeywords = ['unnamed_addr', 'local_unnamed_addr'];\n        const __unnamedAddr = parser.parseOptionalKeyword(unnamedAddrKeywords);\n        if (__unnamedAddr) {\n            result.addAttribute('unnamed_addr', __unnamedAddr);\n        }\n        if (parser.parseOptionalKeyword('constant')) {\n            result.addAttribute('constant', true);\n        }\n        const _symName = parser.parseOptionalSymbolName();\n        if (_symName) {\n            result.addAttribute('sym_name', _symName);\n        }\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            const value = parser.parseAttribute();\n            if (parser.parseOptionalColon()) {\n                parser.parseType();\n            }\n            result.addAttribute('value', value);\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalKeyword('comdat')) {\n            parser.parseLParen();\n            const comdat = parser.parseOptionalSymbolName();\n            parser.parseRParen();\n            result.addAttribute('comdat', comdat);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            result.types = [type];\n        }\n        parser.parseOptionalRegion(result.addRegion());\n        return true;\n    }\n\n    parseLLVMAliasOp(parser, result) {\n        const linkageKeywords = ['external', 'available_externally', 'linkonce', 'linkonce_odr', 'weak', 'weak_odr', 'internal', 'private'];\n        const __linkage = parser.parseOptionalKeyword(linkageKeywords);\n        if (__linkage) {\n            result.addAttribute('linkage', __linkage);\n        }\n        const visibilityKeywords = ['default', 'hidden', 'protected'];\n        const __visibility = parser.parseOptionalKeyword(visibilityKeywords);\n        if (__visibility) {\n            result.addAttribute('visibility_', __visibility);\n        }\n        if (parser.parseOptionalKeyword('thread_local')) {\n            result.addAttribute('thread_local_', true);\n        }\n        const unnamedAddrKeywords = ['unnamed_addr', 'local_unnamed_addr'];\n        const __unnamedAddr = parser.parseOptionalKeyword(unnamedAddrKeywords);\n        if (__unnamedAddr) {\n            result.addAttribute('unnamed_addr', __unnamedAddr);\n        }\n        const __aliasSym = parser.parseOptionalSymbolName();\n        if (__aliasSym) {\n            result.attributes.set('sym_name', __aliasSym);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            result.addAttribute('alias_type', type);\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        return true;\n    }\n\n    // custom<GEPIndices>($dynamicIndices, $rawConstantIndices)\n    parseGEPIndices(parser, op, operands, attrName) {\n        // Note: the reference uses 'none' delimiter with TableGen handling brackets,\n        // but mlir.js expects '[' already consumed and needs to handle ']' terminator\n        const rawConstantIndices = [];\n        do {\n            const constIndex = parser.parseOptionalInteger();\n            if (constIndex === null) {\n                const operand = parser.parseOperand();\n                operands.push(operand);\n                rawConstantIndices.push(-2147483648);\n            } else {\n                rawConstantIndices.push(constIndex);\n            }\n        } while (parser.parseOptionalComma());\n        if (rawConstantIndices.length > 0) {\n            op.addAttribute(attrName || 'rawConstantIndices', rawConstantIndices);\n        }\n    }\n\n    parseIndirectBrOpSucessors(parser, op /*, args */) {\n        // All operands listed first, then colon, then all types\n        parser.parseLSquare();\n        const segmentSizes = [];\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                const successor = parser.parseOptionalSuccessor();\n                if (!op.successors) {\n                    op.successors = [];\n                }\n                op.successors.push({ name: successor });\n                const unresolvedOperands = [];\n                const types = [];\n                if (parser.parseOptionalLParen()) {\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            const operand = parser.parseOperand();\n                            unresolvedOperands.push(operand);\n                        } while (parser.parseOptionalComma());\n                        if (parser.parseOptionalColon()) {\n                            do {\n                                const type = parser.parseType();\n                                types.push(type);\n                            } while (parser.parseOptionalComma());\n                        }\n                        parser.parseRParen();\n                    }\n                }\n                for (let i = 0; i < unresolvedOperands.length; i++) {\n                    const type = i < types.length ? types[i] : null;\n                    parser.resolveOperand(unresolvedOperands[i], type, op.operands);\n                }\n                segmentSizes.push(unresolvedOperands.length);\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        if (segmentSizes.length > 0) {\n            op.addAttribute('indbr_operand_segments', segmentSizes);\n        }\n    }\n\n    parseLLVMAllocaOp(parser, result) {\n        // llvm.alloca [inalloca] %arraySize x !elemType : (i64) -> !llvm.ptr\n        if (parser.parseOptionalKeyword('inalloca')) {\n            result.addAttribute('inalloca', true);\n        }\n        const arraySize = parser.parseOperand();\n        parser.parseKeyword('x');\n        const elemType = parser.parseType();\n        result.addAttribute('elem_type', elemType);\n        parser.parseOptionalAttrDict(result.attributes);\n        parser.parseColon();\n        const fnType = parser.parseType();\n        if (fnType instanceof _.FunctionType) {\n            parser.resolveOperands([arraySize], fnType.inputs, result.operands);\n            result.addTypes(fnType.results);\n        }\n        return true;\n    }\n\n    parseLLVMCallOp(parser, result) {\n        // llvm.call [cconv] [tailcall] @callee|%ptr (args) [vararg(type)] : func_type\n        const cconvKeywords = ['ccc', 'fastcc', 'coldcc', 'cc', 'webkit_jscc', 'anyregcc', 'preserve_mostcc', 'preserve_allcc', 'preserve_nonecc', 'cxx_fast_tlscc', 'tailcc', 'swiftcc', 'swifttailcc', 'cfguard_checkcc', 'ghccc', 'arm_apcscc', 'arm_aapcscc', 'arm_aapcs_vfpcc', 'aarch64_vector_pcs', 'aarch64_sve_vector_pcs', 'aarch64_sme_preservemost_from_x0', 'aarch64_sme_preservemost_from_x2', 'msp430_intrcc', 'avr_intrcc', 'avr_signalcc', 'ptx_kernelcc', 'ptx_devicecc', 'spir_funccc', 'spir_kernelcc', 'intel_ocl_bicc', 'x86_64_sysvcc', 'win64cc', 'x86_fastcallcc', 'x86_stdcallcc', 'x86_thiscallcc', 'x86_vectorcallcc', 'x86_intrcc', 'amdgpu_vs', 'amdgpu_gs', 'amdgpu_ps', 'amdgpu_cs', 'amdgpu_kernel', 'amdgpu_kernelcc', 'x86_regcallcc', 'amdgpu_hs', 'msp430_builtincc', 'amdgpu_ls', 'amdgpu_es', 'aarch64_vfpcc', 'aarch64_sve_vfpcc', 'wasm_emscripten_invokecc', 'amdgpu_gfx', 'm68k_intrcc', 'cc_10', 'cc_11'];\n        const __cconv = parser.parseOptionalKeyword(cconvKeywords);\n        if (__cconv) {\n            result.addAttribute('CConv', __cconv);\n        }\n        const tailcallKeywords = ['none', 'tail', 'musttail', 'notail'];\n        const __tailcall = parser.parseOptionalKeyword(tailcallKeywords);\n        if (__tailcall) {\n            result.addAttribute('TailCallKind', __tailcall);\n        }\n        let isDirect = false;\n        let calleePtr = null;\n        const callee = parser.parseOptionalSymbolName();\n        if (callee) {\n            result.addAttribute('callee', callee);\n            isDirect = true;\n        } else {\n            calleePtr = parser.parseOptionalOperand();\n        }\n        const unresolvedOperands = [];\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const arg = parser.parseOperand();\n                unresolvedOperands.push(arg);\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalKeyword('vararg')) {\n            parser.parseLParen();\n            const varCalleeType = parser.parseType();\n            result.addAttribute('var_callee_type', varCalleeType);\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                const opBundles = [];\n                do {\n                    const tag = parser.parseString();\n                    parser.parseLParen();\n                    const bundleOperands = [];\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            bundleOperands.push(parser.parseOperand());\n                        } while (parser.parseOptionalComma());\n                        parser.parseColon();\n                        do {\n                            parser.parseType();\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                    opBundles.push({ tag, operands: bundleOperands });\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n                if (opBundles.length > 0) {\n                    result.addAttribute('op_bundle_tags', opBundles);\n                }\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        parser.parseColon();\n        let calleePtrType = null;\n        if (!isDirect) {\n            calleePtrType = parser.parseType();\n            parser.parseComma();\n        }\n        const sig = parser.parseFunctionSignature();\n        if (calleePtr) {\n            parser.resolveOperand(calleePtr, calleePtrType, result.operands);\n        }\n        parser.resolveOperands(unresolvedOperands, sig.argTypes, result.operands);\n        if (sig.resultTypes.length > 0) {\n            result.types = sig.resultTypes.map((t) => t.toString());\n        }\n        return true;\n    }\n\n    parseLLVMCallIntrinsicOp(parser, result) {\n        const intrinName = parser.parseString();\n        result.addAttribute('intrin', intrinName);\n\n        const unresolvedOperands = [];\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const arg = parser.parseOperand();\n                unresolvedOperands.push(arg);\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n\n        // Parse operation bundles: [] or [\"tag\"()] or [\"tag\"(%0, %1 : i32, i32), ...]\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                const opBundles = [];\n                do {\n                    const tag = parser.parseString();\n                    parser.parseLParen();\n                    const bundleOperands = [];\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            bundleOperands.push(parser.parseOperand());\n                        } while (parser.parseOptionalComma());\n                        parser.parseColon();\n                        do {\n                            parser.parseType();\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                    opBundles.push({ tag, operands: bundleOperands });\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n                if (opBundles.length > 0) {\n                    result.addAttribute('op_bundle_tags', opBundles);\n                }\n            }\n        }\n\n        parser.parseOptionalAttrDict(result.attributes);\n\n        parser.parseColon();\n        const sig = parser.parseFunctionSignature();\n        parser.resolveOperands(unresolvedOperands, sig.argTypes, result.operands);\n        if (sig.resultTypes.length > 0) {\n            result.types = sig.resultTypes.map((t) => t.toString());\n        }\n        return true;\n    }\n\n    parseLLVMCmpOp(parser, result) {\n        // llvm.icmp \"eq\" %lhs, %rhs : i32\n        const predicate = parser.parseString();\n        result.addAttribute('predicate', predicate);\n        const lhs = parser.parseOperand();\n        parser.parseComma();\n        const rhs = parser.parseOperand();\n        parser.parseOptionalAttrDict(result.attributes);\n        parser.parseColon();\n        const type = parser.parseType();\n        parser.resolveOperands([lhs, rhs], [type, type], result.operands);\n        // Result type is i1 (or vector/tensor of i1 for vector/tensor operands)\n        let resultType = new _.IntegerType('i1');\n        if (type instanceof _.VectorType) {\n            resultType = new _.VectorType(type.shape, new _.IntegerType('i1'), type.scalableDims);\n        } else if (type instanceof _.RankedTensorType) {\n            resultType = new _.RankedTensorType(type.shape, new _.IntegerType('i1'), type.encoding);\n        }\n        result.addTypes([resultType]);\n        return true;\n    }\n\n    parseLLVMIntrinsicOp(parser, result) {\n        const unresolvedOperands = [];\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const operand = parser.parseOperand();\n                unresolvedOperands.push(operand);\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        const types = parser.parseColonTypeList();\n        parser.resolveOperands(unresolvedOperands, types, result.operands);\n        if (parser.parseOptionalArrow()) {\n            const resultType = parser.parseType();\n            result.types = [resultType];\n        }\n        return true;\n    }\n\n    parseLLVMInvokeOp(parser, result) {\n        const cconvKeywords = ['ccc', 'fastcc', 'coldcc', 'cc', 'webkit_jscc', 'anyregcc', 'preserve_mostcc', 'preserve_allcc', 'preserve_nonecc', 'cxx_fast_tlscc', 'tailcc', 'swiftcc', 'swifttailcc', 'cfguard_checkcc', 'ghccc', 'cc_10', 'cc_11'];\n        const __cconv = parser.parseOptionalKeyword(cconvKeywords);\n        if (__cconv) {\n            result.addAttribute('CConv', __cconv);\n        }\n        let isDirect = false;\n        let funcPtr = null;\n        const invokeCallee = parser.parseOptionalSymbolName();\n        if (invokeCallee) {\n            isDirect = true;\n            result.addAttribute('callee', invokeCallee);\n        } else {\n            funcPtr = parser.parseOptionalOperand();\n        }\n        const unresolvedOperands = [];\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const operand = parser.parseOperand();\n                unresolvedOperands.push(operand);\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.parseKeyword('to');\n        const normalDest = parser.parseOptionalSuccessor();\n        result.successors = result.successors || [];\n        const normalSucc = { label: normalDest };\n        if (parser.parseOptionalLParen()) {\n            normalSucc.operands = [];\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const operand = parser.parseOperand();\n                    normalSucc.operands.push(operand);\n                    if (parser.parseOptionalColon()) {\n                        parser.parseType();\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        result.successors.push(normalSucc);\n        parser.parseKeyword('unwind');\n        const unwindDest = parser.parseOptionalSuccessor();\n        const unwindSucc = { label: unwindDest };\n        if (parser.parseOptionalLParen()) {\n            unwindSucc.operands = [];\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const operand = parser.parseOperand();\n                    unwindSucc.operands.push(operand);\n                    if (parser.parseOptionalColon()) {\n                        parser.parseType();\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        }\n        result.successors.push(unwindSucc);\n        if (parser.parseOptionalKeyword('vararg')) {\n            parser.parseLParen();\n            const varargType = parser.parseType();\n            result.addAttribute('var_callee_type', varargType);\n            parser.parseRParen();\n        }\n        if (parser.parseOptionalLSquare()) {\n            if (!parser.parseOptionalRSquare()) {\n                const opBundles = [];\n                do {\n                    const tag = parser.parseString();\n                    parser.parseLParen();\n                    const bundleOperands = [];\n                    if (!parser.parseOptionalRParen()) {\n                        do {\n                            bundleOperands.push(parser.parseOperand());\n                        } while (parser.parseOptionalComma());\n                        parser.parseColon();\n                        do {\n                            parser.parseType();\n                        } while (parser.parseOptionalComma());\n                        parser.parseRParen();\n                    }\n                    opBundles.push({ tag, operands: bundleOperands });\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n                if (opBundles.length > 0) {\n                    result.addAttribute('op_bundle_tags', opBundles);\n                }\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        parser.parseColon();\n        let calleePtrType = null;\n        if (!isDirect) {\n            calleePtrType = parser.parseType();\n            parser.parseComma();\n        }\n        const sig = parser.parseFunctionSignature();\n        if (funcPtr) {\n            parser.resolveOperand(funcPtr, calleePtrType, result.operands);\n        }\n        parser.resolveOperands(unresolvedOperands, sig.argTypes, result.operands);\n        if (sig.resultTypes.length > 0) {\n            result.types = sig.resultTypes.map((t) => t.toString());\n        }\n        return true;\n    }\n\n    parseLLVMLandingpadOp(parser, result) {\n        if (parser.parseOptionalKeyword('cleanup')) {\n            result.addAttribute('cleanup', true);\n        }\n        while (parser.parseOptionalLParen()) {\n            parser.parseKeyword(); // 'catch' or 'filter'\n            const operand = parser.parseOperand();\n            parser.parseColon();\n            const type = parser.parseType();\n            parser.resolveOperand(operand, type, result.operands);\n            parser.parseRParen();\n        }\n        parser.parseColon();\n        const resultType = parser.parseType();\n        result.types = [resultType];\n        return true;\n    }\n\n    parseLLVMFuncOp(parser, result) {\n        const linkageKeywords = ['external', 'available_externally', 'linkonce', 'linkonce_odr', 'weak', 'weak_odr', 'appending', 'internal', 'private', 'extern_weak', 'common'];\n        const __linkage = parser.parseOptionalKeyword(linkageKeywords);\n        if (__linkage) {\n            result.addAttribute('linkage', __linkage);\n        }\n        const visibilityKeywords = ['default', 'hidden', 'protected'];\n        const __visibility = parser.parseOptionalKeyword(visibilityKeywords);\n        if (__visibility) {\n            result.addAttribute('visibility_', __visibility);\n        }\n        const unnamedAddrKeywords = ['unnamed_addr', 'local_unnamed_addr'];\n        const __unnamedAddr = parser.parseOptionalKeyword(unnamedAddrKeywords);\n        if (__unnamedAddr) {\n            result.addAttribute('unnamed_addr', __unnamedAddr);\n        }\n        const cconvKeywords = ['ccc', 'fastcc', 'coldcc', 'cc', 'webkit_jscc', 'anyregcc', 'preserve_mostcc', 'preserve_allcc', 'preserve_nonecc', 'cxx_fast_tlscc', 'tailcc', 'swiftcc', 'swifttailcc', 'cfguard_checkcc', 'ghccc', 'arm_apcscc', 'arm_aapcscc', 'arm_aapcs_vfpcc', 'aarch64_vector_pcs', 'aarch64_sve_vector_pcs', 'aarch64_sme_preservemost_from_x0', 'aarch64_sme_preservemost_from_x2', 'msp430_intrcc', 'avr_intrcc', 'avr_signalcc', 'ptx_kernelcc', 'ptx_devicecc', 'spir_funccc', 'spir_kernelcc', 'intel_ocl_bicc', 'x86_64_sysvcc', 'win64cc', 'x86_fastcallcc', 'x86_stdcallcc', 'x86_thiscallcc', 'x86_vectorcallcc', 'x86_intrcc', 'amdgpu_vs', 'amdgpu_gs', 'amdgpu_ps', 'amdgpu_cs', 'amdgpu_kernel', 'amdgpu_kernelcc', 'x86_regcallcc', 'amdgpu_hs', 'msp430_builtincc', 'amdgpu_ls', 'amdgpu_es', 'aarch64_vfpcc', 'aarch64_sve_vfpcc', 'wasm_emscripten_invokecc', 'amdgpu_gfx', 'm68k_intrcc', 'cc_10', 'cc_11'];\n        const __cconv = parser.parseOptionalKeyword(cconvKeywords);\n        if (__cconv) {\n            result.addAttribute('CConv', __cconv);\n        }\n        parser.parseSymbolName('sym_name', result.attributes);\n        const argResult = parser.parseFunctionArgumentList(true);\n        const params = argResult.arguments.map((a) => a.type);\n        const results = [];\n        const resultAttrs = [];\n        if (parser.parseOptionalArrow()) {\n            parser.parseFunctionResultList(results, resultAttrs);\n        }\n        const returnType = results.length > 0 ? results[0] : null;\n        const type = new _.llvm.LLVMFunctionType(returnType, params, argResult.isVariadic);\n        result.addAttribute('function_type', new _.TypeAttrOf(type));\n        if (parser.parseOptionalKeyword('vscale_range')) {\n            parser.parseLParen();\n            const minRange = parser.parseInteger();\n            parser.parseComma();\n            const maxRange = parser.parseInteger();\n            parser.parseRParen();\n            result.addAttribute('vscale_range', `(${minRange}, ${maxRange})`);\n        }\n        if (parser.parseOptionalKeyword('comdat')) {\n            parser.parseLParen();\n            const comdat = parser.parseOptionalSymbolName();\n            parser.parseRParen();\n            result.addAttribute('comdat', comdat);\n        }\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        parser.parseOptionalRegion(result.addRegion(), argResult.arguments, /* isIsolatedNameScope */ true);\n        return true;\n    }\n};\n\n_.ROCDLDialect = class extends _.llvm.LLVMDialect {\n\n    constructor(operations) {\n        super(operations, 'rocdl');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'rocdl.raw.buffer.load') {\n            return this.parseRawBufferLoadOp(parser, result);\n        }\n        if (result.op === 'rocdl.raw.buffer.store') {\n            return this.parseRawBufferStoreOp(parser, result);\n        }\n        if (result.op === 'rocdl.raw.buffer.atomic.fadd') {\n            return this.parseRawBufferAtomicOp(parser, result);\n        }\n        if (result.op === 'rocdl.raw.buffer.atomic.fmax') {\n            return this.parseRawBufferAtomicOp(parser, result);\n        }\n        if (result.op === 'rocdl.raw.buffer.atomic.smax') {\n            return this.parseRawBufferAtomicOp(parser, result);\n        }\n        if (result.op === 'rocdl.raw.buffer.atomic.umin') {\n            return this.parseRawBufferAtomicOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseRawBufferLoadOp(parser, result) {\n        const unresolvedOperands = [];\n        let _bufOp = parser.parseOptionalOperand();\n        while (_bufOp) {\n            unresolvedOperands.push(_bufOp);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            _bufOp = parser.parseOptionalOperand();\n        }\n        parser.parseColon();\n        const resultType = parser.parseType();\n        result.addTypes([resultType]);\n        for (const operand of unresolvedOperands) {\n            parser.resolveOperand(operand, null, result.operands);\n        }\n        return true;\n    }\n\n    parseRawBufferStoreOp(parser, result) {\n        const unresolvedOperands = [];\n        let _storeOp = parser.parseOptionalOperand();\n        while (_storeOp) {\n            unresolvedOperands.push(_storeOp);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            _storeOp = parser.parseOptionalOperand();\n        }\n        parser.parseColon();\n        parser.parseType();\n        for (const operand of unresolvedOperands) {\n            parser.resolveOperand(operand, null, result.operands);\n        }\n        return true;\n    }\n\n    parseRawBufferAtomicOp(parser, result) {\n        const unresolvedOperands = [];\n        let _atomicOp = parser.parseOptionalOperand();\n        while (_atomicOp) {\n            unresolvedOperands.push(_atomicOp);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            _atomicOp = parser.parseOptionalOperand();\n        }\n        parser.parseColon();\n        parser.parseType();\n        for (const operand of unresolvedOperands) {\n            parser.resolveOperand(operand, null, result.operands);\n        }\n        return true;\n    }\n};\n\n_.XSMMDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xsmm');\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (result.op === 'xsmm.unary.invoke') {\n            return this.parseUnaryInvokeOp(parser, result);\n        }\n        if (result.op.startsWith('xsmm.') && result.op.includes('.invoke') && opInfo.metadata.hasCustomAssemblyFormat && !opInfo.metadata.assemblyFormat) {\n            return this.parseGemmInvokeOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseUnaryInvokeOp(parser, result) {\n        const unresolvedOperands = [];\n        unresolvedOperands.push(parser.parseOperand());\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const __op = parser.parseOptionalOperand();\n                if (__op) {\n                    unresolvedOperands.push(__op);\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        parser.parseEqual();\n        unresolvedOperands.push(parser.parseOperand());\n        parser.parseLParen();\n        unresolvedOperands.push(parser.parseOperand());\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const __op2 = parser.parseOptionalOperand();\n                if (__op2) {\n                    unresolvedOperands.push(__op2);\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        parser.parseRParen();\n        parser.parseColon();\n        parser.parseType();\n        for (const operand of unresolvedOperands) {\n            parser.resolveOperand(operand, null, result.operands);\n        }\n        return true;\n    }\n\n    parseGemmInvokeOp(parser, result) {\n        const unresolvedOperands = [];\n        unresolvedOperands.push(parser.parseOperand());\n        parser.parseComma();\n        unresolvedOperands.push(parser.parseOperand());\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const __op3 = parser.parseOptionalOperand();\n                if (__op3) {\n                    unresolvedOperands.push(__op3);\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        parser.parseEqual();\n        unresolvedOperands.push(parser.parseOperand());\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const __op4 = parser.parseOptionalOperand();\n                if (__op4) {\n                    unresolvedOperands.push(__op4);\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        parser.parseComma();\n        unresolvedOperands.push(parser.parseOperand());\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const __op5 = parser.parseOptionalOperand();\n                if (__op5) {\n                    unresolvedOperands.push(__op5);\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        while (parser.parseOptionalComma()) {\n            const __op6 = parser.parseOptionalOperand();\n            if (__op6) {\n                unresolvedOperands.push(__op6);\n                if (parser.parseOptionalLSquare()) {\n                    while (!parser.parseOptionalRSquare()) {\n                        const __op7 = parser.parseOptionalOperand();\n                        if (__op7) {\n                            unresolvedOperands.push(__op7);\n                        }\n                        parser.parseOptionalComma();\n                    }\n                }\n            } else {\n                const keyword = parser.parseOptionalKeyword();\n                if (keyword) {\n                    parser.parseEqual();\n                    const attrValue = parser.parseAttribute(new _.IntegerType('i64'));\n                    result.addAttribute(keyword, attrValue);\n                } else {\n                    break;\n                }\n            }\n        }\n        parser.parseColon();\n        parser.parseType();\n        for (const operand of unresolvedOperands) {\n            parser.resolveOperand(operand, null, result.operands);\n        }\n        return true;\n    }\n};\n\n_.StdxDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'stdx');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'stdx.closure') {\n            return this.parseClosureOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseClosureOp(parser, result) {\n        const sig = parser.parseFunctionSignatureWithArguments(false);\n        const argTypes = sig.arguments.map((a) => a.type);\n        const type = { inputs: argTypes, results: sig.resultTypes };\n        result.addAttribute('type', type);\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        const region = result.addRegion();\n        parser.parseRegion(region, sig.arguments);\n        return true;\n    }\n};\n\n_.vm = {};\n\n_.vm.RefType = class extends _.Type {\n\n    constructor(objectType) {\n        super(null);\n        this.objectType = objectType;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const objectType = parser.parseOptionalQuestion()\n            ? new _.OpaqueType('?')\n            : parser.parseType();\n        parser.parseGreater();\n        return new _.vm.RefType(objectType);\n    }\n\n    toString() {\n        return `!vm.ref<${this.objectType}>`;\n    }\n};\n\n_.vm.VMDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'vm');\n        this.registerCustomDirective('BranchTableCases', this.parseBranchTableCases.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'vm.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'vm.cond_fail') {\n            // or: vm.cond_fail %status, \"message\"\n            // or: vm.cond_fail %cond, %status\n            // or: vm.cond_fail %status\n            const unresolvedOperands = [];\n            const firstOp = parser.parseOperand();\n            unresolvedOperands.push(firstOp);\n            if (parser.parseOptionalComma()) {\n                // Could be second operand or message\n                const __secondOp = parser.parseOptionalOperand();\n                if (__secondOp) {\n                    unresolvedOperands.push(__secondOp);\n                    // Optional message\n                    if (parser.parseOptionalComma()) {\n                        const msg = parser.parseOptionalString();\n                        if (msg !== null) {\n                            result.addAttribute('message', msg);\n                        }\n                    }\n                } else {\n                    const msg = parser.parseOptionalString();\n                    if (msg !== null) {\n                        result.addAttribute('message', msg);\n                    }\n                }\n            }\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, null, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'vm.import') {\n            parser.parseOptionalVisibilityKeyword(result.attributes);\n            if (parser.parseOptionalKeyword('optional')) {\n                result.addAttribute('is_optional', true);\n            }\n            parser.parseSymbolName('sym_name', result.attributes);\n            const inputs = [];\n            parser.parseLParen();\n            while (!parser.parseOptionalRParen()) {\n                if (parser.parseOptionalOperand()) {\n                    inputs.push(parser.parseColonType());\n                } else {\n                    inputs.push(parser.parseType());\n                }\n                parser.parseOptionalEllipsis();\n                parser.parseOptionalComma();\n            }\n            const results = [];\n            const resultAttrs = [];\n            if (parser.parseOptionalArrow()) {\n                parser.parseFunctionResultList(results, resultAttrs);\n            }\n            result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'vm.export') {\n            const functionRef = parser.parseOptionalSymbolName();\n            result.addAttribute('function_ref', functionRef);\n            if (parser.parseOptionalKeyword('as')) {\n                parser.parseLParen();\n                const exportName = parser.parseString();\n                result.addAttribute('export_name', exportName);\n                parser.parseRParen();\n            } else {\n                result.addAttribute('export_name', functionRef);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            return true;\n        }\n        if (result.op === 'vm.initializer') {\n            parser.parseOptionalVisibilityKeyword(result.attributes);\n            const __symName = parser.parseOptionalSymbolName();\n            if (__symName !== null) {\n                result.attributes.set('sym_name', __symName);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'vm.const.i32.zero') {\n            result.compatibility = true;\n            const __symbol = parser.parseOptionalSymbolName();\n            if (__symbol === null) {\n                const value = parser.parseOptionalAttribute();\n                if (value !== null) {\n                    result.addAttribute('value', value.value === undefined ? value : value.value);\n                }\n            } else {\n                result.addAttribute('rodata', __symbol);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            const types = parser.parseOptionalColonTypeList();\n            result.addTypes(types.length > 0 ? types : [new _.IntegerType('i32')]);\n            return true;\n        }\n        // Handle vm.switch.ref operation\n        if (result.op === 'vm.switch.ref') {\n            const unresolvedOperands = [];\n            const indexUnresolved = parser.parseOperand();\n            unresolvedOperands.push(indexUnresolved);\n            parser.parseLSquare();\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    const __val = parser.parseOptionalOperand();\n                    if (__val) {\n                        unresolvedOperands.push(__val);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n            parser.parseKeyword('else');\n            const defaultValueUnresolved = parser.parseOperand();\n            unresolvedOperands.push(defaultValueUnresolved);\n            parser.parseOptionalAttrDict(result.attributes);\n            let resultType = null;\n            if (parser.parseOptionalColon()) {\n                resultType = parser.parseType();\n                result.addTypes([resultType]);\n            }\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, resultType, result.operands);\n            }\n            return true;\n        }\n        // Following reference: CallVariadicOp::parse in VMOps.cpp:1251\n        if (result.op === 'vm.call.variadic') {\n            const calleeAttr = parser.parseAttribute();\n            result.addAttribute('callee', calleeAttr);\n            parser.parseLParen();\n            const flatOperands = [];\n            const flatSegmentSizes = [];\n            while (!parser.parseOptionalRParen()) {\n                if (parser.parseOptionalLSquare()) {\n                    // Variadic list\n                    const flatSegmentOperands = [];\n                    while (!parser.parseOptionalRSquare()) {\n                        if (parser.parseOptionalLParen()) {\n                            // Tuple inside variadic list\n                            while (!parser.parseOptionalRParen()) {\n                                flatSegmentOperands.push(parser.parseOperand());\n                                if (!parser.parseOptionalComma()) {\n                                    parser.parseRParen();\n                                    break;\n                                }\n                            }\n                        } else {\n                            flatSegmentOperands.push(parser.parseOperand());\n                        }\n                        if (!parser.parseOptionalComma()) {\n                            parser.parseRSquare();\n                            break;\n                        }\n                    }\n                    flatSegmentSizes.push(flatSegmentOperands.length);\n                    flatOperands.push(...flatSegmentOperands);\n                } else {\n                    // Normal single operand\n                    flatOperands.push(parser.parseOperand());\n                    flatSegmentSizes.push(-1);\n                }\n                if (!parser.parseOptionalComma()) {\n                    parser.parseRParen();\n                    break;\n                }\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            parser.parseLParen();\n            const flatOperandTypes = [];\n            const segmentTypes = [];\n            const segmentSizes = [];\n            let segmentIndex = 0;\n            while (!parser.parseOptionalRParen()) {\n                const operandType = parser.parseType();\n                const isVariadic = parser.parseOptionalEllipsis();\n                if (isVariadic) {\n                    const flatSegmentSize = flatSegmentSizes[segmentIndex];\n                    for (let i = 0; i < flatSegmentSize; i++) {\n                        flatOperandTypes.push(operandType);\n                    }\n                    segmentSizes.push(flatSegmentSize);\n                } else {\n                    flatOperandTypes.push(operandType);\n                    segmentSizes.push(-1);\n                }\n                segmentTypes.push(operandType);\n                segmentIndex++;\n                if (!parser.parseOptionalComma()) {\n                    parser.parseRParen();\n                    break;\n                }\n            }\n            parser.resolveOperands(flatOperands, flatOperandTypes, result.operands);\n            result.addTypes(parser.parseOptionalArrowTypeList());\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseBranchTableCases(parser, op /*, args */) {\n        if (parser.parseOptionalKeyword('default')) {\n            parser.parseColon();\n            const defaultDest = parser.parseOptionalSuccessor();\n            op.successors = op.successors || [];\n            const succ = { dest: defaultDest };\n            if (parser.parseOptionalLParen()) {\n                const operands = parser.parseOperandList('none');\n                const types = parser.parseOptionalColonTypeList();\n                parser.parseRParen();\n                parser.resolveOperands(operands, types);\n                succ.operands = operands;\n            }\n            op.successors.push(succ);\n            parser.parseOptionalComma();\n        }\n        const caseValues = [];\n        for (;;) {\n            const caseValue = parser.parseOptionalInteger();\n            if (caseValue === null) {\n                break;\n            }\n            caseValues.push(caseValue);\n            parser.parseColon();\n            const caseDest = parser.parseOptionalSuccessor();\n            const caseSucc = { dest: caseDest };\n            if (parser.parseOptionalLParen()) {\n                const operands = parser.parseOperandList('none');\n                const types = parser.parseOptionalColonTypeList();\n                parser.parseRParen();\n                parser.resolveOperands(operands, types);\n                caseSucc.operands = operands;\n            }\n            op.successors.push(caseSucc);\n            parser.parseOptionalComma();\n        }\n        if (caseValues.length > 0) {\n            op.addAttribute('case_values', caseValues);\n        }\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (mnemonic === 'ref') {\n                return _.vm.RefType.parse(parser);\n            }\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n};\n\n_.MathDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'math');\n        this.registerCustomAttribute('Arith_FastMathAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n    }\n};\n\n_.torch.TMTensorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tm_tensor');\n    }\n};\n\n_.MLProgramDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'ml_program');\n        this.registerCustomDirective('TypedInitialValue', this.parseTypedInitialValue.bind(this));\n        this.registerCustomDirective('TokenOrdering', this.parseTokenOrdering.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'ml_program.func' || result.op === 'ml_program.subgraph') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseTokenOrdering(parser, result) {\n        if (!parser.parseOptionalKeyword('ordering')) {\n            return;\n        }\n        parser.parseLParen();\n        if (parser.parseOptionalLParen()) {\n            parser.parseRParen();\n        } else {\n            let __tok = parser.parseOptionalOperand();\n            while (__tok) {\n                parser.resolveOperand(__tok, null, result.operands);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                __tok = parser.parseOptionalOperand();\n            }\n        }\n        parser.parseArrow();\n        const produceType = parser.parseType();\n        result.addAttribute('produceTokenType', { value: produceType, hidden: true });\n        parser.parseRParen();\n    }\n\n    parseTypedInitialValue(parser, op, typeAttr, valueAttr) {\n        if (parser.parseOptionalLParen()) {\n            const attr = parser.parseAttribute();\n            if (parser.parseOptionalColon()) {\n                attr.type = parser.parseType();\n            }\n            parser.parseRParen();\n            op.addAttribute(valueAttr, attr.value === undefined ? attr : attr.value);\n        }\n        parser.parseColon();\n        const type = parser.parseType();\n        op.addAttribute(typeAttr, type);\n    }\n};\n\n_.IREEGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'iree_gpu');\n    }\n};\n\n_.TFDeviceDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tf_device');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tf_device.replicate') {\n            return this.parseReplicateOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseReplicateOp(parser, result) {\n        let n = 1;\n        if (!parser.parseOptionalLParen()) {\n            parser.parseOptionalAttrDict(result.attributes);\n        } else if (parser.parseOptionalRParen()) {\n            parser.parseOptionalAttrDict(result.attributes);\n        } else {\n            do {\n                if (parser.parseOptionalLSquare()) {\n                    const unresolvedInputs = [];\n                    while (!parser.parseOptionalRSquare()) {\n                        unresolvedInputs.push(parser.parseOperand());\n                        if (!parser.parseOptionalComma()) {\n                            parser.parseRSquare();\n                            break;\n                        }\n                    }\n                    parser.parseKeyword('as');\n                    parser.parseOperand(); // block arg\n                    parser.parseColon();\n                    const type = parser.parseType();\n                    for (const input of unresolvedInputs) {\n                        parser.resolveOperand(input, type, result.operands);\n                    }\n                } else {\n                    const unresolvedValue = parser.parseOptionalOperand();\n                    if (!unresolvedValue) {\n                        break;\n                    }\n                    parser.parseKeyword('as');\n                    parser.parseOperand(); // block arg\n                    parser.parseColon();\n                    const type = parser.parseType();\n                    parser.resolveOperand(unresolvedValue, type, result.operands);\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n            parser.parseOptionalAttrDict(result.attributes);\n        }\n        n = result.attributes.get('n').value;\n        {\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            if (region.blocks.length > 0) {\n                const block = region.blocks[0];\n                if (block.operations.length > 0) {\n                    const terminator = block.operations[block.operations.length - 1];\n                    if (terminator.operands) {\n                        for (const operand of terminator.operands) {\n                            if (operand.type) {\n                                for (let i = 0; i < n; i++) {\n                                    result.addTypes([operand.type]);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return true;\n    }\n};\n\n_.TFGDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfg');\n    }\n\n    getOperation(opName) {\n        let op = super.getOperation(opName);\n        if (!op) {\n            this.registerOperandName(opName, {});\n            op = super.getOperation(opName);\n        }\n        return op;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tfg.func') {\n            if (parser.parseOptionalKeyword('generic')) {\n                result.addAttribute('generic', true);\n            }\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'tfg.return') {\n            let dataOperands = [];\n            if (parser.parseOptionalLParen()) {\n                dataOperands = parser.parseOperandList('none');\n                parser.parseRParen();\n            }\n            const controlOperands = [];\n            const controlRetAttrs = [];\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const __ctlDep = parser.parseOptionalOperand();\n                        if (__ctlDep) {\n                            controlOperands.push(__ctlDep);\n                            const __ctlAttrs = new Map();\n                            if (parser.parseOptionalAttrDict(__ctlAttrs)) {\n                                controlRetAttrs.push(Object.fromEntries(__ctlAttrs));\n                            } else {\n                                controlRetAttrs.push({});\n                            }\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n            }\n            if (controlRetAttrs.length > 0) {\n                result.addAttribute('control_ret_attrs', controlRetAttrs);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const types = parser.parseTypeList();\n                parser.resolveOperands(dataOperands, types, result.operands);\n            } else {\n                parser.resolveOperands(dataOperands, dataOperands.map(() => null), result.operands);\n            }\n            parser.resolveOperands(controlOperands, controlOperands.map(() => null), result.operands);\n            return true;\n        }\n        const opInfo = result.name.getRegisteredInfo();\n        if (!opInfo.metadata.assemblyFormat) {\n            this.parseTFGOperation(parser, result);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseTFGOperation(parser, result) {\n        let unresolvedArgs = [];\n        if (parser.parseOptionalLParen()) {\n            unresolvedArgs = parser.parseOperandList('none');\n            parser.parseRParen();\n        }\n        const unresolvedCtls = [];\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const operand = parser.parseOptionalOperand();\n                if (operand) {\n                    unresolvedCtls.push(operand);\n                }\n                if (!parser.parseOptionalComma()) {\n                    parser.parseRSquare();\n                    break;\n                }\n            }\n        }\n        if (parser.parseOptionalKeyword('device')) {\n            parser.parseLParen();\n            const device = parser.parseString();\n            parser.parseRParen();\n            result.addAttribute('device', device);\n        }\n        if (parser.parseOptionalKeyword('name')) {\n            parser.parseLParen();\n            const name = parser.parseString();\n            parser.parseRParen();\n            result.addAttribute('_mlir_name', name);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            if (type instanceof _.FunctionType) {\n                parser.resolveOperands(unresolvedArgs, type.inputs, result.operands);\n                parser.resolveOperands(unresolvedCtls, unresolvedCtls.map(() => new _.Type('!tfg.control')), result.operands);\n                result.addTypes(type.results);\n            } else {\n                const types = [type];\n                while (parser.parseOptionalComma()) {\n                    types.push(parser.parseType());\n                }\n                parser.resolveOperands(unresolvedArgs, types, result.operands);\n                parser.resolveOperands(unresolvedCtls, unresolvedCtls.map(() => new _.Type('!tfg.control')), result.operands);\n            }\n        } else {\n            parser.resolveOperands(unresolvedArgs, unresolvedArgs.map(() => null), result.operands);\n            parser.resolveOperands(unresolvedCtls, unresolvedCtls.map(() => new _.Type('!tfg.control')), result.operands);\n        }\n        result.addTypes([new _.Type('!tfg.control')]);\n    }\n};\n\n_.TFExecutorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tf_executor');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            const type = `!${dialect}.${mnemonic}`;\n            if (mnemonic === 'control' || mnemonic === 'token') {\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tf_executor.graph') {\n            return this.parseGraphOp(parser, result);\n        }\n        if (result.op === 'tf_executor.island') {\n            return this.parseIslandOp(parser, result);\n        }\n        if (result.op === 'tf_executor.Enter') {\n            return this.parseEnterOp(parser, result);\n        }\n        if (result.op === 'tf_executor._SwitchN') {\n            const unresolvedData = parser.parseOperand();\n            parser.parseComma();\n            const unresolvedIndex = parser.parseOperand();\n            parser.parseKeyword('of');\n            const numOuts = parser.parseInteger();\n            result.addAttribute('num_outs', numOuts);\n            let unresolvedControlInputs = [];\n            if (parser.parseOptionalLParen()) {\n                unresolvedControlInputs = parser.parseOperandList('none');\n                parser.parseRParen();\n            }\n            parser.parseColon();\n            const type = parser.parseType();\n            parser.resolveOperand(unresolvedData, type, result.operands);\n            parser.resolveOperand(unresolvedIndex, new _.RankedTensorType([], new _.IntegerType('i32'), null), result.operands);\n            parser.resolveOperands(unresolvedControlInputs, unresolvedControlInputs.map(() => new _.Type('!tf_executor.control')), result.operands);\n            for (let i = 0; i < numOuts; i++) {\n                result.addTypes([type]);\n            }\n            result.addTypes([new _.Type('!tf_executor.control')]);\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (result.op === 'tf_executor.Switch' || result.op === 'tf_executor.Merge' ||\n            result.op === 'tf_executor.LoopCond' || result.op === 'tf_executor.Exit') {\n            // These ops have hasCustomAssemblyFormat: true but no assemblyFormat in metadata\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (type instanceof _.FunctionType) {\n                    parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);\n                    result.addTypes(type.results);\n                } else {\n                    parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => type), result.operands);\n                    result.addTypes([type]);\n                    if (result.op === 'tf_executor.Switch') {\n                        result.addTypes([type]);\n                    }\n                    if (result.op === 'tf_executor.Merge') {\n                        result.addTypes([new _.RankedTensorType([], new _.IntegerType('i32'), null)]);\n                    }\n                    result.addTypes([new _.Type('!tf_executor.control')]);\n                }\n            } else {\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseEnterOp(parser, result) {\n        const unresolvedOperands = [];\n        let operand = parser.parseOptionalOperand();\n        while (operand) {\n            unresolvedOperands.push(operand);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            operand = parser.parseOptionalOperand();\n        }\n        parser.parseKeyword('frame');\n        const frameName = parser.parseString();\n        result.addAttribute('frame_name', frameName);\n        if (parser.parseOptionalKeyword('parallel_iterations')) {\n            const parallelIterations = parser.parseInteger();\n            result.addAttribute('parallel_iterations', parseInt(parallelIterations, 10));\n        } else {\n            result.addAttribute('parallel_iterations', 10);\n        }\n        const isConstant = parser.parseOptionalKeyword('constant');\n        result.addAttribute('is_constant', isConstant);\n        parser.parseColon();\n        const type = parser.parseType();\n        if (type instanceof _.FunctionType) {\n            parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);\n            result.addTypes(type.results);\n        } else {\n            const resolveTypes = unresolvedOperands.map((v, i) => i === 0 ? type : new _.Type('!tf_executor.control'));\n            parser.resolveOperands(unresolvedOperands, resolveTypes, result.operands);\n            result.addTypes([type]);\n            result.addTypes([new _.Type('!tf_executor.control')]);\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseGraphOp(parser, result) {\n        const region = result.addRegion();\n        if (parser.parseOptionalRegion(region)) {\n            if (region.blocks && region.blocks.length > 0) {\n                const [block] = region.blocks;\n                if (block.operations && block.operations.length > 0) {\n                    const lastOp = block.operations[block.operations.length - 1];\n                    if (lastOp.name.getStringRef() === 'tf_executor.fetch' && lastOp.operands) {\n                        for (const operand of lastOp.operands) {\n                            const typeStr = operand.type ? operand.type.toString() : '';\n                            if (operand.type && typeStr !== '!tf_executor.control') {\n                                result.addTypes([operand.type]);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n\n    parseIslandOp(parser, result) {\n        // or: tf_executor.island {...}\n        // or: tf_executor.island(%control_inputs) {...}\n        if (parser.parseOptionalLParen()) {\n            const unresolvedOperands = parser.parseOperandList('none');\n            parser.parseRParen();\n            for (const operand of unresolvedOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n        }\n        const region = result.addRegion();\n        if (parser.parseOptionalKeyword('wraps')) {\n            const wrappedOp = parser.parseGenericOperation();\n            result.addAttribute('wrappedOp', wrappedOp);\n            for (const opResult of wrappedOp.results) {\n                result.addTypes([opResult.type]);\n            }\n        } else if (parser.parseOptionalRegion(region)) {\n            if (region.blocks.length > 0) {\n                const block = region.blocks[region.blocks.length - 1];\n                if (block.operations.length > 0) {\n                    const terminator = block.operations[block.operations.length - 1];\n                    if (terminator.name.getStringRef() === 'tf_executor.yield') {\n                        for (const operand of terminator.operands) {\n                            result.addTypes([operand.type]);\n                        }\n                    }\n                }\n            }\n        }\n        result.addTypes([new _.Type('!tf_executor.control')]);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n};\n\n_.TFFrameworkDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tf_framework');\n    }\n};\n\n_.TFRDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfr');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tfr.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.CoreRTDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'corert');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'corert.executeop' || result.op === 'corert.executeop.seq') {\n            const isSeq = result.op === 'corert.executeop.seq';\n            const opHandlerOperands = parser.parseOperandList('paren');\n            for (const operand of opHandlerOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n            const opNameAttr = parser.parseString();\n            result.addAttribute('op_name', opNameAttr);\n            const operandOperands = parser.parseOperandList('paren');\n            for (const operand of operandOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            const funcAttrs = new Map();\n            parser.parseOptionalAttrDict(funcAttrs);\n            if (funcAttrs.size > 0) {\n                result.addAttribute('op_func_attrs', Object.fromEntries(funcAttrs));\n            }\n            if (parser.parseOptionalColon()) {\n                const resultCount = parser.parseInteger();\n                if (isSeq) {\n                    result.addTypes([new _.Type('!tfrt.chain')]);\n                }\n                const tensorHandleType = new _.Type('!corert.tensorhandle');\n                for (let i = 0; i < resultCount; i++) {\n                    result.addTypes([tensorHandleType]);\n                }\n            } else if (isSeq) {\n                result.addTypes([new _.Type('!tfrt.chain')]);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.TFRTDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfrt');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            const simpleTypes = ['chain', 'string', 'dist_context', 'device', 'tensor_type'];\n            if (simpleTypes.includes(mnemonic)) {\n                return new _.Type(type);\n            }\n            if (mnemonic === 'tensor') {\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (!opInfo) {\n            return false;\n        }\n        if (opInfo.metadata.assemblyFormat === 'operands attr-dict') {\n            const unresolvedOperands = parser.parseOperandList();\n            parser.parseOptionalAttrDict(result.attributes);\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, null, result.operands);\n            }\n            this.inferResultTypes(result, new Map());\n            return true;\n        }\n        if (result.op === 'tfrt.call') {\n            parser.parseSymbolName('callee', result.attributes);\n            const unresolvedOperands = parser.parseOperandList('paren');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (type) {\n                    if (type.inputs) {\n                        parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);\n                    }\n                    if (type.results) {\n                        type.results.forEach((resultType) => {\n                            result.addTypes([resultType]);\n                        });\n                    }\n                }\n            } else {\n                for (const operand of unresolvedOperands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'tfrt.return') {\n            const unresolvedOperands = parser.parseOperandList();\n            if (unresolvedOperands.length > 0) {\n                parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'tfrt.repeat.i32') {\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalKeyword('attributes')) {\n                parser.parseOptionalAttrDict(result.attributes);\n            }\n            const types = parser.parseOptionalColonTypeList();\n            result.addTypes(types);\n            if (unresolvedOperands.length > 0) {\n                const i32Type = new _.IntegerType('i32');\n                parser.resolveOperand(unresolvedOperands[0], i32Type, result.operands);\n                const loopOperands = unresolvedOperands.slice(1);\n                parser.resolveOperands(loopOperands, types, result.operands);\n            }\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'tfrt.if') {\n            const unresolvedOperands = parser.parseOperandList();\n            if (parser.parseOptionalKeyword('attributes')) {\n                parser.parseOptionalAttrDict(result.attributes);\n            }\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                if (funcType) {\n                    if (funcType.inputs) {\n                        parser.resolveOperands(unresolvedOperands, funcType.inputs, result.operands);\n                    }\n                    if (funcType.results) {\n                        for (const resultType of funcType.results) {\n                            result.addTypes([resultType]);\n                        }\n                    }\n                }\n            } else {\n                for (const operand of unresolvedOperands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n            const thenRegion = {};\n            if (parser.parseOptionalRegion(thenRegion)) {\n                result.regions.push(thenRegion);\n            }\n            if (parser.parseOptionalKeyword('else')) {\n                const elseRegion = {};\n                if (parser.parseOptionalRegion(elseRegion)) {\n                    result.regions.push(elseRegion);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'tfrt.parallel_for.i32') {\n            const startUnresolved = parser.parseOperand();\n            parser.parseKeyword('to');\n            const endUnresolved = parser.parseOperand();\n            parser.parseKeyword('fixed');\n            const blockSizeUnresolved = parser.parseOperand();\n            let additionalArgs = [];\n            if (parser.parseOptionalComma()) {\n                additionalArgs = parser.parseOperandList();\n            }\n            const types = parser.parseOptionalColonTypeList();\n            const i32Type = new _.IntegerType('i32');\n            parser.resolveOperand(startUnresolved, i32Type, result.operands);\n            parser.resolveOperand(endUnresolved, i32Type, result.operands);\n            parser.resolveOperand(blockSizeUnresolved, i32Type, result.operands);\n            parser.resolveOperands(additionalArgs, types, result.operands);\n            result.addTypes([new _.Type('!tfrt.chain')]);\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'tfrt.parallel_call.i32') {\n            const startUnresolved = parser.parseOperand();\n            parser.parseKeyword('to');\n            const endUnresolved = parser.parseOperand();\n            parser.parseKeyword('fixed');\n            const blockSizeUnresolved = parser.parseOperand();\n            const callee = parser.parseOptionalSymbolName();\n\n            result.addAttribute('callee', callee);\n            const additionalArgs = parser.parseOperandList('paren');\n            const types = parser.parseOptionalColonTypeList();\n            const i32Type = new _.IntegerType('i32');\n            parser.resolveOperand(startUnresolved, i32Type, result.operands);\n            parser.resolveOperand(endUnresolved, i32Type, result.operands);\n            parser.resolveOperand(blockSizeUnresolved, i32Type, result.operands);\n            parser.resolveOperands(additionalArgs, types, result.operands);\n            result.addTypes([new _.Type('!tfrt.chain')]);\n            return true;\n        }\n        if (result.op === 'tfrt.while') {\n            const condUnresolved = parser.parseOperand();\n            const bodyFn = parser.parseOptionalSymbolName();\n\n            result.addAttribute('body_fn', bodyFn);\n            const argsUnresolved = parser.parseOperandList('paren');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalKeyword('parallel_iterations')) {\n                parser.parseLParen();\n                const parallelIterations = parser.parseInteger();\n                result.addAttribute('parallel_iterations', parseInt(parallelIterations, 10));\n                parser.parseRParen();\n            }\n            parser.parseColon();\n            parser.parseLParen();\n            const inputTypes = parser.parseTypeList();\n            parser.parseRParen();\n            parser.parseArrow();\n            parser.parseLParen();\n            const resultTypes = parser.parseTypeList();\n            parser.parseRParen();\n            parser.resolveOperand(condUnresolved, new _.IntegerType('i1'), result.operands);\n            parser.resolveOperands(argsUnresolved, inputTypes, result.operands);\n            for (const resultType of resultTypes) {\n                result.addTypes([resultType]);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.TFRTFallbackAsyncDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfrt_fallback_async');\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (!opInfo) {\n            return false;\n        }\n        if (result.op === 'tfrt_fallback_async.batch_function') {\n            parser.parseKeyword('device');\n            parser.parseLParen();\n            const device = parser.parseString();\n\n            parser.parseRParen();\n            result.addAttribute('device', device);\n            const funcName = parser.parseOptionalSymbolName();\n\n            result.addAttribute('f', funcName);\n            const unresolvedOperands = parser.parseOperandList('paren');\n            for (const operand of unresolvedOperands) {\n                parser.resolveOperand(operand, null, result.operands);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const resultCount = parser.parseInteger();\n                for (let i = 0; i < parseInt(resultCount, 10); i++) {\n                    result.addTypes([new _.Type('!tfrt_fallback.tf_tensor')]);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'tfrt_fallback_async.createop' || result.op.startsWith('tfrt_fallback_async.executeop')) {\n            const isCreateOp = result.op === 'tfrt_fallback_async.createop';\n            const hasChain = isCreateOp || result.op.includes('.seq');\n            const hasAllocator = result.op.includes('.allocator');\n            if ((hasChain || hasAllocator) && parser.parseOptionalLParen()) {\n                const chainOperands = parser.parseOperandList('none');\n                parser.parseRParen();\n                for (const operand of chainOperands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n            for (;;) {\n                const __key = parser.parseOptionalKeyword();\n                if (__key) {\n                    if (parser.parseOptionalLParen()) {\n                        const value = parser.parseAttribute();\n                        parser.parseRParen();\n                        result.addAttribute(__key, value);\n                    }\n                } else {\n                    const __opNameStr = parser.parseOptionalString();\n                    if (__opNameStr === null) {\n                        break;\n                    }\n                    result.addAttribute('op_name', __opNameStr);\n                    if (parser.parseOptionalLParen()) {\n                        const unresolvedOperands = parser.parseOperandList('none');\n                        parser.parseRParen();\n                        for (const operand of unresolvedOperands) {\n                            parser.resolveOperand(operand, null, result.operands);\n                        }\n                    }\n                    break;\n                }\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseOptionalAttrDict(result.attributes);\n            if (isCreateOp) {\n                if (parser.parseOptionalKeyword('num_args')) {\n                    parser.parseLParen();\n                    const numArgs = parser.parseInteger();\n                    parser.parseRParen();\n                    result.addAttribute('num_args', parseInt(numArgs, 10));\n                }\n                // createop always returns !tfrt.chain\n                result.addTypes([new _.Type('!tfrt.chain')]);\n            } else if (parser.parseOptionalColon()) {\n                const resultCount = parser.parseInteger();\n                result.addAttribute('result_count', resultCount);\n                if (hasChain) {\n                    result.addTypes([new _.Type('!tfrt.chain')]);\n                }\n                for (let i = 0; i < resultCount; i++) {\n                    result.addTypes([new _.Type('!tfrt_fallback.tf_tensor')]);\n                }\n            } else if (hasChain) {\n                result.addTypes([new _.Type('!tfrt.chain')]);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.TileDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tile');\n    }\n\n    parseOperation(parser, result) {\n        // tile.contract has format: tile.contract agg, combo, operands... attributes : types -> result\n        // Example: %1 = tile.contract add, mul, %0, %arg0, %arg1 {sink = #map0, srcs = [#map1, #map2]} : tensor<f32>, tensor<1x256xf32>, tensor<256x512xf32> -> tensor<1x512xf32>\n        if (result.op === 'tile.contract') {\n            const __agg = parser.parseOptionalKeyword();\n            if (__agg) {\n                result.addAttribute('agg', __agg);\n            }\n            parser.parseOptionalComma();\n            const __combo = parser.parseOptionalKeyword();\n            if (__combo) {\n                result.addAttribute('combo', __combo);\n            }\n            parser.parseOptionalComma();\n            const unresolvedOperands = parser.parseOperandList();\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);\n            result.addTypes(parser.parseOptionalArrowTypeList());\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.PXADialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'pxa');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'pxa.reduce' || result.op === 'pxa.vector_reduce') {\n            const agg = parser.parseKeyword();\n\n            result.addAttribute('agg', agg);\n            const unresolvedVal = parser.parseOperand();\n            parser.parseOptionalComma();\n            const unresolvedMemref = parser.parseOperand();\n            const mapOperands = [];\n            parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n            parser.parseOptionalAttrDict(result.attributes);\n            let memrefType = null;\n            let valType = null;\n            if (parser.parseOptionalColon()) {\n                memrefType = parser.parseType();\n                result.addTypes([memrefType]);\n                if (result.op === 'pxa.vector_reduce' && parser.parseOptionalComma()) {\n                    valType = parser.parseType();\n                }\n            }\n            parser.resolveOperand(unresolvedVal, valType, result.operands);\n            parser.resolveOperand(unresolvedMemref, memrefType, result.operands);\n            return true;\n        }\n        if (result.op === 'pxa.load' || result.op === 'pxa.vector_load') {\n            const unresolvedMemref = parser.parseOperand();\n            const mapOperands = [];\n            parser.parseAffineMapOfSSAIds(mapOperands, null, 'map', result.attributes);\n            parser.parseOptionalAttrDict(result.attributes);\n            let memrefType = null;\n            if (parser.parseOptionalColon()) {\n                memrefType = parser.parseType();\n                if (result.op === 'pxa.vector_load' && parser.parseOptionalComma()) {\n                    const vectorType = parser.parseType();\n                    result.addTypes([vectorType]);\n                } else if (result.op === 'pxa.load' && memrefType) {\n                    // Result type is element type of memref\n                    const elementType = memrefType.elementType || memrefType;\n                    result.addTypes([elementType]);\n                }\n            }\n            parser.resolveOperand(unresolvedMemref, memrefType, result.operands);\n            return true;\n        }\n        if (result.op === 'pxa.generic') {\n            const unresolvedOperands = [];\n            const allMapOperands = [];\n            const parseGenericOperandList = () => {\n                parser.parseCommaSeparatedList('none', () => {\n                    const operand = parser.parseOperand();\n                    unresolvedOperands.push(operand);\n                    const mapOperands = [];\n                    parser.parseAffineMapOfSSAIds(mapOperands, null, null, new Map());\n                    allMapOperands.push(...mapOperands);\n                    if (parser.parseOptionalColon()) {\n                        parser.parseAttribute();\n                    }\n                });\n            };\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    parseGenericOperandList();\n                    parser.parseRParen();\n                }\n            }\n            if (parser.parseOptionalLess()) {\n                const reduction = parser.parseKeyword();\n                result.addAttribute('reduction', reduction);\n                parser.parseGreater();\n            }\n            const __kernel = parser.parseOptionalSymbolName();\n            if (__kernel !== null) {\n                result.addAttribute('kernel', __kernel);\n            }\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    parseGenericOperandList();\n                    parser.parseRParen();\n                }\n            }\n            if (parser.parseOptionalKeyword('tile')) {\n                parser.parseColon();\n                parser.parseLSquare();\n                const tileValues = [];\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        tileValues.push(parser.parseInteger());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n                result.addAttribute('tile', new _.DenseI64ArrayAttr(tileValues));\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const funcType = parser.parseType();\n                if (funcType && funcType.inputs) {\n                    parser.resolveOperands(unresolvedOperands, funcType.inputs, result.operands);\n                }\n                const indexType = new _.IndexType();\n                parser.resolveOperands(allMapOperands, allMapOperands.map(() => indexType), result.operands);\n                if (funcType && funcType.results) {\n                    for (const resultType of funcType.results) {\n                        result.addTypes([resultType]);\n                    }\n                }\n            } else {\n                for (const unresolved of unresolvedOperands) {\n                    parser.resolveOperand(unresolved, null, result.operands);\n                }\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.hlo.ToyDialect = class extends _.hlo.HLODialect {\n\n    constructor(operations) {\n        super(operations, 'toy');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'toy.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        // toy.constant: {attrs} dense<...> : type\n        if (result.op === 'toy.constant') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const value = parser.parseAttribute();\n            result.addAttribute('value', value.value === undefined ? value : value.value);\n            result.addTypes([value.type]);\n            return true;\n        }\n        // toy.mul, toy.add: %lhs, %rhs : type\n        if (result.op === 'toy.mul' || result.op === 'toy.add') {\n            result.operands = parser.parseOperandList();\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const types = parser.parseOptionalColonTypeList();\n            if (types.length > 0) {\n                const [type] = types;\n                for (const operand of result.operands) {\n                    operand.type = type;\n                }\n                result.addTypes(types);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n};\n\n_.SdfgDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'sdfg');\n    }\n\n    parseNumberList(parser, result, attrName) {\n        const operands = [];\n        const attrs = [];\n        do {\n            if (parser.parseOptionalKeyword('sym')) {\n                parser.parseLParen();\n                attrs.push(parser.parseAttribute());\n                parser.parseRParen();\n            } else {\n                const op = parser.parseOptionalOperand();\n                if (op) {\n                    operands.push(op);\n                } else {\n                    attrs.push(parser.parseAttribute());\n                }\n            }\n        } while (parser.parseOptionalComma());\n        if (attrName) {\n            result.addAttribute(attrName, attrs);\n        }\n        const indexType = new _.IndexType();\n        parser.resolveOperands(operands, operands.map(() => indexType), result.operands);\n        return operands;\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            if (mnemonic === 'array' || mnemonic === 'stream' || mnemonic === 'memlet' || type.endsWith('stream_array')) {\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'sdfg.sdfg' || result.op === 'sdfg.nested_sdfg' || result.op === 'sdir.sdfg') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const inputResult = parser.parseFunctionArgumentList();\n            const inputs = inputResult.arguments.map((a) => a.type);\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let results = [];\n            if (parser.parseOptionalArrow()) {\n                const outputResult = parser.parseFunctionArgumentList();\n                results = outputResult.arguments.map((a) => a.type);\n            }\n            result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'sdfg.tasklet' || result.op === 'sdir.tasklet') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const __taskletSym = parser.parseOptionalSymbolName();\n            if (__taskletSym !== null) {\n                result.attributes.set('sym_name', __taskletSym);\n            }\n            const blockArgs = [];\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    const operand = parser.parseOperand();\n                    let blockArgName = operand;\n                    let type = null;\n                    if (parser.parseOptionalKeyword('as')) {\n                        blockArgName = parser.parseOperand();\n                        parser.parseColon();\n                        type = parser.parseType();\n                    } else {\n                        parser.parseColon();\n                        type = parser.parseType();\n                    }\n                    parser.resolveOperand(operand, type, result.operands);\n                    blockArgs.push({ value: blockArgName, type });\n                    parser.parseOptionalComma();\n                }\n            }\n            if (parser.parseOptionalArrow()) {\n                if (parser.parseOptionalLParen()) {\n                    while (!parser.parseOptionalRParen()) {\n                        const type = parser.parseType();\n                        result.addTypes([type]);\n                        parser.parseOptionalComma();\n                    }\n                } else {\n                    const type = parser.parseType();\n                    result.addTypes([type]);\n                }\n            }\n            const region = result.addRegion();\n            parser.parseRegion(region, blockArgs);\n            return true;\n        }\n        if (result.op === 'sdfg.consume') {\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalLParen()) {\n                let __consumeOp = parser.parseOptionalOperand();\n                while (__consumeOp) {\n                    let type = null;\n                    if (parser.parseOptionalColon()) {\n                        type = parser.parseType();\n                    }\n                    parser.resolveOperand(__consumeOp, type, result.operands);\n                    if (!parser.parseOptionalComma()) {\n                        break;\n                    }\n                    __consumeOp = parser.parseOptionalOperand();\n                }\n                parser.parseRParen();\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            if (parser.parseOptionalArrow()) {\n                if (parser.parseOptionalLParen()) {\n                    // Parse named results: (pe: %p, elem: %e)\n                    while (!parser.parseOptionalRParen()) {\n                        const __namedKw = parser.parseOptionalKeyword();\n                        if (__namedKw) {\n                            if (parser.parseOptionalColon()) {\n                                parser.parseOperand(); // Parse %p or %e but don't store\n                                result.types.push(null);\n                            }\n                        } else {\n                            break;\n                        }\n                        parser.parseOptionalComma();\n                    }\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'sdfg.state' || result.op === 'sdir.state') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const __stateSym = parser.parseOptionalSymbolName();\n            if (__stateSym !== null) {\n                result.attributes.set('sym_name', __stateSym);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'sdfg.alloc' || result.op === 'sdir.alloc' || result.op === 'sdir.alloc_transient' || result.op === 'sdir.alloc_stream') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedOperands = [];\n            if (parser.parseOptionalLParen()) {\n                unresolvedOperands.push(...parser.parseOperandList('none'));\n                parser.parseRParen();\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let allocType = null;\n            if (parser.parseOptionalColon()) {\n                allocType = parser.parseType();\n                result.addTypes([allocType]);\n            }\n            const indexType = new _.IndexType();\n            parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), result.operands);\n            return true;\n        }\n        if (result.op === 'sdfg.store' || result.op === 'sdir.store') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const valueOp = parser.parseOperand();\n            parser.parseOptionalComma();\n            const arrayOp = parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    this.parseNumberList(parser, result, 'indices');\n                    parser.parseRSquare();\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const valueType = parser.parseType();\n                parser.parseOptionalArrow();\n                const arrayType = parser.parseType();\n                parser.resolveOperand(valueOp, valueType, result.operands);\n                parser.resolveOperand(arrayOp, arrayType, result.operands);\n            } else {\n                parser.resolveOperand(valueOp, null, result.operands);\n                parser.resolveOperand(arrayOp, null, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.load' || result.op === 'sdir.load') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const arrayOp = parser.parseOperand();\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    this.parseNumberList(parser, result, 'indices');\n                    parser.parseRSquare();\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const arrayType = parser.parseType();\n                parser.parseOptionalArrow();\n                const resultType = parser.parseType();\n                parser.resolveOperand(arrayOp, arrayType, result.operands);\n                result.addTypes([resultType]);\n            } else {\n                parser.resolveOperand(arrayOp, null, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.map' || result.op === 'sdir.map') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const params = [];\n            if (parser.parseOptionalLParen()) {\n                while (!parser.parseOptionalRParen()) {\n                    const __param = parser.parseOptionalOperand();\n                    if (__param) {\n                        params.push(__param);\n                    }\n                    parser.parseOptionalComma();\n                }\n            }\n            if (parser.parseOptionalEqual()) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    this.parseNumberList(parser, result, 'lowerBounds');\n                    parser.parseRParen();\n                }\n            }\n            if (parser.parseOptionalKeyword('to')) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    this.parseNumberList(parser, result, 'upperBounds');\n                    parser.parseRParen();\n                }\n            }\n            if (parser.parseOptionalKeyword('step')) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    this.parseNumberList(parser, result, 'steps');\n                    parser.parseRParen();\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'sdir.consume') {\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalLParen()) {\n                let __sdirOp = parser.parseOptionalOperand();\n                while (__sdirOp) {\n                    let type = null;\n                    if (parser.parseOptionalColon()) {\n                        type = parser.parseType();\n                    }\n                    parser.resolveOperand(__sdirOp, type, result.operands);\n                    if (!parser.parseOptionalComma()) {\n                        break;\n                    }\n                    __sdirOp = parser.parseOptionalOperand();\n                }\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalArrow()) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        parser.parseKeyword();\n                        parser.parseColon();\n                        parser.parseOperand();\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'sdfg.edge' || result.op === 'sdir.edge') {\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const __kw = parser.parseOptionalKeyword();\n                        if (__kw) {\n                            parser.parseColon(); // label like 'ref'\n                        }\n                        const __op = parser.parseOptionalOperand();\n                        if (__op) {\n                            let type = null;\n                            if (parser.parseOptionalColon()) {\n                                type = parser.parseType();\n                            }\n                            parser.resolveOperand(__op, type, result.operands);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const __src = parser.parseOptionalSymbolName();\n            if (__src !== null) {\n                result.addAttribute('src', __src);\n            }\n            parser.parseOptionalArrow();\n            const __dst = parser.parseOptionalSymbolName();\n            if (__dst !== null) {\n                result.addAttribute('dst', __dst);\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.sym' || result.op === 'sdir.sym') {\n            if (parser.parseOptionalLParen()) {\n                const expr = parser.parseString();\n\n                result.addAttribute('expr', expr);\n                parser.parseOptionalRParen();\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                result.addTypes([type]);\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.copy' || result.op === 'sdir.copy') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedSrc = parser.parseOperandList('none');\n            const unresolvedDst = [];\n            if (parser.parseOptionalArrow()) {\n                unresolvedDst.push(...parser.parseOperandList('none'));\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                const allUnresolved = unresolvedSrc.concat(unresolvedDst);\n                parser.resolveOperands(allUnresolved, allUnresolved.map(() => type), result.operands);\n            } else {\n                const allUnresolved = unresolvedSrc.concat(unresolvedDst);\n                parser.resolveOperands(allUnresolved, allUnresolved.map(() => null), result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.libcall' || result.op === 'sdir.libcall') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const __libname = parser.parseOptionalString();\n            if (__libname !== null) {\n                result.addAttribute('libname', __libname);\n            }\n            const unresolvedOperands = parser.parseOperandList('paren');\n            const types = [];\n            if (parser.parseOptionalColon()) {\n                if (parser.parseOptionalLParen()) {\n                    while (!parser.parseOptionalRParen()) {\n                        types.push(parser.parseType());\n                        parser.parseOptionalComma();\n                    }\n                }\n                if (parser.parseOptionalArrow()) {\n                    const resultType = parser.parseType();\n                    result.addTypes([resultType]);\n                }\n            }\n            parser.resolveOperands(unresolvedOperands, types.length > 0 ? types : unresolvedOperands.map(() => null), result.operands);\n            return true;\n        }\n        if (result.op === 'sdfg.get_access' || result.op === 'sdir.get_access') {\n            let unresolvedOperand = null;\n            unresolvedOperand = parser.parseOptionalOperand();\n            if (parser.parseOptionalColon()) {\n                const inputType = parser.parseType();\n                if (unresolvedOperand) {\n                    parser.resolveOperand(unresolvedOperand, inputType, result.operands);\n                }\n                if (parser.parseOptionalArrow()) {\n                    const resultType = parser.parseType();\n                    result.addTypes([resultType]);\n                }\n            } else if (unresolvedOperand) {\n                // No explicit type - try to resolve operand and infer type from its definition\n                parser.resolveOperand(unresolvedOperand, null, result.operands);\n                // If operand was resolved with a type, use it as result type\n                if (result.operands.length > 0 && result.operands[0].type) {\n                    result.addTypes([result.operands[0].type]);\n                } else {\n                    // Fallback: use a generic memref type\n                    result.addTypes([new _.UnrankedMemRefType(new _.Type('f32'))]);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'sdir.call') {\n            const callee = parser.parseOptionalSymbolName();\n            if (callee) {\n                result.addAttribute('callee', callee);\n            }\n            if (parser.parseOptionalLParen()) {\n                const unresolvedOperands = parser.parseOperandList('none');\n                parser.parseRParen();\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n            }\n            if (parser.parseOptionalColon()) {\n                if (parser.parseOptionalLParen()) {\n                    while (!parser.parseOptionalRParen()) {\n                        parser.parseType();\n                        parser.parseOptionalComma();\n                    }\n                }\n                if (parser.parseOptionalArrow()) {\n                    const resultType = parser.parseType();\n                    result.addTypes([resultType]);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.alloc_symbol' || result.op === 'sdir.alloc_symbol') {\n            if (parser.parseOptionalLParen()) {\n                const sym = parser.parseString();\n\n                result.addAttribute('sym', sym);\n                parser.parseOptionalRParen();\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.return') {\n            const unresolvedOperands = parser.parseOperandList('none');\n            if (unresolvedOperands.length > 0) {\n                const types = parser.parseOptionalColonTypeList();\n                parser.resolveOperands(unresolvedOperands, types, result.operands);\n            }\n            return true;\n        }\n        if (result.op === 'sdfg.stream_push' || result.op === 'sdir.stream_push') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedValue = parser.parseOperand();\n            parser.parseOptionalComma();\n            const unresolvedStream = parser.parseOperand();\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let valueType = null;\n            let streamType = null;\n            if (parser.parseOptionalColon()) {\n                valueType = parser.parseType();\n                parser.parseOptionalArrow();\n                streamType = parser.parseType();\n            }\n            parser.resolveOperand(unresolvedValue, valueType, result.operands);\n            parser.resolveOperand(unresolvedStream, streamType, result.operands);\n            return true;\n        }\n        if (result.op === 'sdfg.stream_pop' || result.op === 'sdir.stream_pop') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedStream = parser.parseOperand();\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let streamType = null;\n            if (parser.parseOptionalColon()) {\n                streamType = parser.parseType();\n                parser.parseOptionalArrow();\n                const resultType = parser.parseType();\n                result.addTypes([resultType]);\n            }\n            parser.resolveOperand(unresolvedStream, streamType, result.operands);\n            return true;\n        }\n        if (result.op === 'sdfg.stream_length' || result.op === 'sdir.stream_length') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedStream = parser.parseOperand();\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let streamType = null;\n            if (parser.parseOptionalColon()) {\n                streamType = parser.parseType();\n                parser.parseOptionalArrow();\n                const resultType = parser.parseType();\n                result.addTypes([resultType]);\n            }\n            parser.resolveOperand(unresolvedStream, streamType, result.operands);\n            return true;\n        }\n        if (result.op === 'sdfg.view_cast' || result.op === 'sdir.view_cast') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedInput = parser.parseOperand();\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let inputType = null;\n            if (parser.parseOptionalColon()) {\n                inputType = parser.parseType();\n                parser.parseOptionalArrow();\n                const resultType = parser.parseType();\n                result.addTypes([resultType]);\n            }\n            parser.resolveOperand(unresolvedInput, inputType, result.operands);\n            return true;\n        }\n        if (result.op === 'sdfg.subview' || result.op === 'sdir.subview') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const unresolvedInput = parser.parseOperand();\n            parser.parseLSquare();\n            this.parseNumberList(parser, result, 'offsets');\n            parser.parseRSquare();\n            parser.parseLSquare();\n            this.parseNumberList(parser, result, 'sizes');\n            parser.parseRSquare();\n            parser.parseLSquare();\n            this.parseNumberList(parser, result, 'strides');\n            parser.parseRSquare();\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            let inputType = null;\n            if (parser.parseOptionalColon()) {\n                inputType = parser.parseType();\n                parser.parseOptionalArrow();\n                const resultType = parser.parseType();\n                result.addTypes([resultType]);\n            }\n            parser.resolveOperand(unresolvedInput, inputType, result.operands);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.TFLDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfl');\n        // Operations that use parseOneResultSameOperandTypeOp in tfl_ops.cc\n        this._binaryOps = new Set([\n            'add', 'sub', 'mul', 'div', 'floor_div', 'pow', 'squared_difference',\n            'less', 'less_equal', 'greater', 'greater_equal', 'not_equal',\n            'logical_and', 'logical_or'\n        ]);\n    }\n\n    parseOperation(parser, result) {\n        const opKind = result.op.substring('tfl.'.length);\n        if (opKind === 'control_node') {\n            if (parser.parseOptionalLParen()) {\n                const unresolvedOperands = parser.parseOperandList('none');\n                parser.parseRParen();\n                // control_node operands don't have types parsed inline\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n            }\n            if (parser.parseOptionalKeyword('controls')) {\n                const region = { blocks: [{ operations: [] }] };\n                const innerOp = parser.parseGenericOperation();\n                region.blocks[0].operations.push(innerOp);\n                result.regions.push(region);\n                // Result types are inferred from inner op results + control type\n                for (const opResult of innerOp.results) {\n                    result.addTypes([opResult.type]);\n                }\n                result.addTypes([new _.Type('!tfl.control')]);\n            } else if (parser.parseOptionalRegion(result.addRegion())) {\n                const region = result.regions[result.regions.length - 1];\n                // Result types from yield terminator + control type\n                const block = region.blocks[region.blocks.length - 1];\n                const yieldOp = block.operations[block.operations.length - 1];\n                if (yieldOp && yieldOp.operands) {\n                    for (const operand of yieldOp.operands) {\n                        result.addTypes([operand.type]);\n                    }\n                }\n                result.addTypes([new _.Type('!tfl.control')]);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (this._binaryOps.has(opKind)) {\n            // Or: (operands) <properties> : fn-type (generic form)\n            if (parser.parseOptionalLParen()) {\n                const unresolvedOperands = parser.parseOperandList('none');\n                parser.parseRParen();\n                if (parser.parseOptionalLess()) {\n                    result.propertiesAttr = parser.parseAttribute();\n                    parser.parseGreater();\n                }\n                parser.parseOptionalAttrDict(result.attributes);\n                if (parser.parseOptionalColon()) {\n                    const fnType = parser.parseType();\n                    if (fnType instanceof _.FunctionType) {\n                        parser.resolveOperands(unresolvedOperands, fnType.inputs, result.operands);\n                        result.addTypes(fnType.results);\n                    } else {\n                        parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => fnType), result.operands);\n                        result.addTypes([fnType]);\n                    }\n                } else {\n                    parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n                }\n                return true;\n            }\n            // Compact form: %a, %b attr-dict : type\n            const unresolvedOperands = parser.parseOperandList('none');\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => type), result.operands);\n                result.addTypes([type]);\n            } else {\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n            }\n            return true;\n        }\n\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.TFDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tf');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            if (mnemonic === 'resource' || mnemonic === 'variant') {\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n            if (mnemonic === 'string' || mnemonic === 'control') {\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n};\n\n_.TFTypeDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tf_type');\n        this.simpleTypes = new Set([\n            'string', 'qint8', 'qint16', 'qint32', 'quint8', 'quint16',\n            'f32ref', 'f64ref', 'uint4ref', 'int4ref', 'uint8ref', 'int8ref',\n            'uint16ref', 'int16ref', 'uint32ref', 'int32ref', 'uint64ref', 'int64ref',\n            'stringref', 'boolref', 'quint8ref', 'qint8ref', 'quint16ref', 'qint16ref',\n            'qint32ref', 'bfloat16ref', 'complex64ref', 'complex128ref', 'halfref',\n            'resourceref', 'variantref',\n            'float8e4m3fnref', 'float8e5m2ref', 'float8e4m3fnuzref',\n            'float8e4m3b11fnuzref', 'float8e5m2fnuzref'\n        ]);\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            const type = `!${dialect}.${mnemonic}`;\n            // Handle parametrized types like resource<>, variant<>, resource_handle<>\n            if (mnemonic === 'resource' || mnemonic === 'variant' || mnemonic === 'resource_handle') {\n                if (parser.parseOptionalLess()) {\n                    const subtypes = [];\n                    do {\n                        subtypes.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                    parser.parseGreater();\n                    return new _.Type(`${type}<${subtypes.join(', ')}>`);\n                }\n                return new _.Type(type);\n            }\n            if (this.simpleTypes.has(mnemonic)) {\n                return new _.Type(type);\n            }\n            return new _.Type(type);\n        }\n        return null;\n    }\n};\n\n_.TransformDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'transform');\n        this.registerCustomDirective('PackedOrDynamicIndexList', this.parsePackedOrDynamicIndexList.bind(this));\n        this.registerCustomDirective('SemiFunctionType', this.parseSemiFunctionType.bind(this));\n        this.registerCustomDirective('SequenceOpOperands', this.parseSequenceOpOperands.bind(this));\n        this.registerCustomDirective('ForeachMatchSymbols', this.parseForeachMatchSymbols.bind(this));\n        this.registerCustomDirective('TransformMatchDims', this.parseTransformMatchDims.bind(this));\n        this.registerCustomDirective('ApplyRegisteredPassOptions', this.parseApplyRegisteredPassOptions.bind(this));\n        this.registerCustomDirective('AlternativesOpSelectedRegion', this.parseAlternativesOpSelectedRegion.bind(this));\n        this.registerCustomDirective('ContinuousTileSizeTypes', this.parseContinuousTileSizeTypes.bind(this));\n        this.registerCustomDirective('MultitileSizesTypes', this.parseMultitileSizesTypes.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'transform.named_sequence') {\n            return this.parseNamedSequenceOp(parser, result);\n        }\n        // C++-only operation: transform.test_transform_op [\"message\"]\n        // Defined in mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp\n        if (result.op === 'transform.test_transform_op') {\n            const __message = parser.parseOptionalString();\n            if (__message !== null) {\n                result.addAttribute('message', __message);\n            }\n            return true;\n        }\n        // LinalgTransformOps.cpp:3009 SplitOp::parse\n        if (result.op === 'transform.structured.split') {\n            const unresolvedTarget = parser.parseOperand();\n            parser.parseKeyword('after');\n            let unresolvedDynamicChunk = null;\n            unresolvedDynamicChunk = parser.parseOptionalOperand();\n            if (!unresolvedDynamicChunk) {\n                const staticChunkSizes = parser.parseInteger();\n                result.addAttribute('static_chunk_sizes', staticChunkSizes);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            const targetType = parser.parseType();\n            parser.resolveOperand(unresolvedTarget, targetType, result.operands);\n            result.addTypes([targetType]);\n            if (unresolvedDynamicChunk && parser.parseOptionalComma()) {\n                const chunkType = parser.parseType();\n                parser.resolveOperand(unresolvedDynamicChunk, chunkType, result.operands);\n            } else if (unresolvedDynamicChunk) {\n                // Default to index type if chunk type not specified\n                parser.resolveOperand(unresolvedDynamicChunk, null, result.operands);\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseSequenceOpOperands(parser, op /*, args */) {\n        const unresolvedOperands = [];\n        let __seqOp = parser.parseOptionalOperand();\n        while (__seqOp) {\n            unresolvedOperands.push(__seqOp);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            __seqOp = parser.parseOptionalOperand();\n        }\n        if (parser.parseOptionalColon()) {\n            parser.parseOptionalLParen();\n            const types = parser.parseTypeList();\n            parser.resolveOperands(unresolvedOperands, types, op.operands);\n            parser.parseOptionalRParen();\n        } else {\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, null, op.operands);\n            }\n        }\n    }\n\n    parseForeachMatchSymbols(parser, op, matchersAttr, actionsAttr) {\n        const matchers = [];\n        const actions = [];\n        do {\n            const matcher = parser.parseOptionalSymbolName();\n\n            parser.parseArrow();\n            const action = parser.parseOptionalSymbolName();\n\n            matchers.push(matcher);\n            actions.push(action);\n        } while (parser.parseOptionalComma());\n        op.addAttribute(matchersAttr, matchers);\n        op.addAttribute(actionsAttr, actions);\n    }\n\n    parseTransformMatchDims(parser, op, dimsAttr, invertedAttr, allAttr) {\n        if (parser.parseOptionalKeyword('all')) {\n            op.addAttribute(allAttr, true);\n            return;\n        }\n        const isInverted = parser.parseOptionalKeyword('except');\n        if (isInverted) {\n            parser.parseLParen();\n        }\n        const dims = [];\n        do {\n            const value = parser.parseOptionalInteger();\n            if (value !== null) {\n                dims.push(value);\n            }\n        } while (parser.parseOptionalComma());\n        if (isInverted) {\n            parser.parseRParen();\n            op.addAttribute(invertedAttr, true);\n        }\n        op.addAttribute(dimsAttr, dims);\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseNamedSequenceOp(parser, result) {\n        parser.parseOptionalVisibilityKeyword(result.attributes);\n        parser.parseSymbolName('sym_name', result.attributes);\n        const argResult = parser.parseFunctionArgumentList();\n        const inputs = argResult.arguments.map((a) => a.type);\n        const results = [];\n        const resultAttrs = [];\n        if (parser.parseOptionalArrow()) {\n            parser.parseFunctionResultList(results, resultAttrs);\n        }\n        result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        parser.parseOptionalRegion(result.addRegion());\n        return true;\n    }\n\n    parseSemiFunctionType(parser, op /* , args */) {\n        const hasLParen = parser.parseOptionalLParen();\n        const argType = parser.parseType();\n        if (op.operands.length > 0) {\n            op.operands[0].type = argType;\n        }\n        if (!hasLParen) {\n            return;\n        }\n        parser.parseRParen();\n        parser.parseArrow();\n        if (parser.parseOptionalLParen()) {\n            let idx = 0;\n            do {\n                const type = parser.parseType();\n                if (idx < op.types.length) {\n                    op.types[idx] = type;\n                } else {\n                    op.addTypes([type]);\n                }\n                idx++;\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        } else {\n            const type = parser.parseType();\n            if (op.types.length > 0) {\n                op.types[0] = type;\n            } else {\n                op.addTypes([type]);\n            }\n        }\n    }\n\n    parsePackedOrDynamicIndexList(parser, op, packedName, dynamicName, staticAttrName) {\n        const dynamicOperands = [];\n        const dynamicTypes = [];\n        const staticValues = [];\n        let packedOperand = null;\n\n        // Check for packed syntax: *(%operand)\n        if (parser.parseOptionalStar()) {\n            parser.parseLParen();\n            packedOperand = parser.parseOptionalOperand();\n            parser.parseRParen();\n        } else if (parser.parseOptionalLSquare()) {\n            // List syntax: [int, %operand, int, ...]\n            while (!parser.parseOptionalRSquare()) {\n                const __dynOp = parser.parseOptionalOperand();\n                if (__dynOp) {\n                    dynamicOperands.push(__dynOp);\n                    staticValues.push(-9223372036854775808n); // ShapedType::kDynamic\n                    let type = null;\n                    if (parser.parseOptionalColon()) {\n                        type = parser.parseType();\n                    }\n                    dynamicTypes.push(type);\n                } else {\n                    const __intVal = parser.parseOptionalInteger('int64');\n                    if (__intVal === null) {\n                        break;\n                    }\n                    staticValues.push(__intVal);\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        if (packedOperand && packedName) {\n            parser.resolveOperand(packedOperand, null, op.operands);\n        }\n        if (dynamicName) {\n            for (let i = 0; i < dynamicOperands.length; i++) {\n                const type = i < dynamicTypes.length ? dynamicTypes[i] : null;\n                parser.resolveOperand(dynamicOperands[i], type, op.operands);\n            }\n        }\n        if (staticAttrName && staticValues.length > 0) {\n            op.addAttribute(staticAttrName, staticValues);\n        }\n    }\n\n    parseContinuousTileSizeTypes(parser, result, targetTypes, tileSizesTypes, chunkSizesTypes) {\n        const funcType = parser.parseType();\n        if (funcType instanceof _.FunctionType) {\n            if (funcType.inputs.length !== 1 || funcType.results.length !== 1) {\n                throw new mlir.Error(`Expected a trailing functional type with one argument and one result.`);\n            }\n            targetTypes.push(funcType.inputs[0]);\n            tileSizesTypes.push(funcType.results[0]);\n            chunkSizesTypes.push(funcType.results[0]);\n        }\n    }\n\n    parseMultitileSizesTypes(parser, result, targetTypes, lowSizeTypes, highSizeTypes, splitPointTypes) {\n        const funcType = parser.parseType();\n        if (funcType instanceof _.FunctionType) {\n            if (funcType.inputs.length !== 1 || funcType.results.length !== 1) {\n                throw new mlir.Error(`Expected a trailing functional type with one argument and one result.`);\n            }\n            targetTypes.push(funcType.inputs[0]);\n            lowSizeTypes.push(funcType.results[0]);\n            highSizeTypes.push(funcType.results[0]);\n            splitPointTypes.push(funcType.results[0]);\n        }\n    }\n\n    parseApplyRegisteredPassOptions(parser, result) {\n        if (!parser.parseOptionalLBrace()) {\n            return;\n        }\n        const options = {};\n        while (!parser.parseOptionalRBrace()) {\n            let key = parser.parseOptionalString();\n            if (key === null) {\n                key = parser.parseOptionalKeyword();\n            }\n            parser.parseEqual();\n            const __regOp = parser.parseOptionalOperand();\n            if (__regOp) {\n                parser.resolveOperand(__regOp, null, result.operands);\n                options[key] = `#transform.param_operand<${result.operands.length - 1}>`;\n            } else if (parser.parseOptionalLSquare()) {\n                const arr = [];\n                while (!parser.parseOptionalRSquare()) {\n                    const __arrOp = parser.parseOptionalOperand();\n                    if (__arrOp) {\n                        parser.resolveOperand(__arrOp, null, result.operands);\n                        arr.push(`#transform.param_operand<${result.operands.length - 1}>`);\n                    } else {\n                        const val = parser.parseAttribute();\n                        arr.push(val);\n                    }\n                    parser.parseOptionalComma();\n                }\n                options[key] = arr;\n            } else {\n                const value = parser.parseAttribute();\n                options[key] = value;\n            }\n            parser.parseOptionalComma();\n        }\n        result.addAttribute('options', options);\n    }\n\n    parseAlternativesOpSelectedRegion(parser, result) {\n        const __altInt = parser.parseOptionalInteger();\n        if (__altInt === null) {\n            const __altOp = parser.parseOptionalOperand();\n            if (__altOp) {\n                parser.resolveOperand(__altOp, null, result.operands);\n            }\n        } else {\n            result.addAttribute('selected_region_attr', __altInt);\n        }\n    }\n};\n\n_.test = {};\n\n_.test.TestDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'test');\n        this.blobManager = new Map();\n        this.registerCustomDirective('CustomOptionalOperand', this.parseCustomOptionalOperand.bind(this));\n        this.registerCustomDirective('CustomDirectiveOperands', this.parseCustomDirectiveOperands.bind(this));\n        this.registerCustomDirective('CustomDirectiveOperandsAndTypes', this.parseCustomDirectiveOperandsAndTypes.bind(this));\n        this.registerCustomDirective('CustomDirectiveResults', this.parseCustomDirectiveResults.bind(this));\n        this.registerCustomDirective('CustomDirectiveWithTypeRefs', this.parseCustomDirectiveWithTypeRefs.bind(this));\n        this.registerCustomDirective('CustomDirectiveRegions', this.parseCustomDirectiveRegions.bind(this));\n        this.registerCustomDirective('CustomDirectiveSuccessors', this.parseCustomDirectiveSuccessors.bind(this));\n        this.registerCustomDirective('CustomDirectiveAttrDict', this.parseCustomDirectiveAttrDict.bind(this));\n        this.registerCustomDirective('CustomDirectiveAttributes', this.parseCustomDirectiveAttributes.bind(this));\n        this.registerCustomDirective('CustomDirectiveSpacing', this.parseCustomDirectiveSpacing.bind(this));\n        this.registerCustomDirective('CustomDirectiveOptionalOperandRef', this.parseCustomDirectiveOptionalOperandRef.bind(this));\n        this.registerCustomDirective('UsingPropertyInCustom', this.parseUsingPropertyInCustom.bind(this));\n        this.registerCustomDirective('IntProperty', this.parseIntProperty.bind(this));\n        this.registerCustomDirective('SumProperty', this.parseSumProperty.bind(this));\n        this.registerCustomDirective('SwitchCases', this.parseSwitchCases.bind(this));\n        this.registerCustomDirective('DimensionList', this.parseDimensionList.bind(this));\n        this.registerCustomDirective('OptionalCustomParser', this.parseOptionalCustomParser.bind(this));\n        this.registerCustomDirective('OptionalLoc', this.parseOptionalLoc.bind(this));\n        this.registerCustomDirective('DummyRegionRef', this.parseDummyRegionRef.bind(this));\n        this.registerCustomDirective('DummySuccessorRef', this.parseDummySuccessorRef.bind(this));\n        this.registerCustomType('CompoundNestedOuterType', this.parseCompoundNestedOuterType.bind(this));\n        this.registerCustomType('CompoundNestedInnerType', this.parseCompoundNestedInnerType.bind(this));\n        this.registerCustomType('CompoundTypeA', this.parseCompoundTypeA.bind(this));\n        this.registerCustomAttribute('TestBitEnumAttr', this.parseEnumFlagsAngleBracketComma.bind(this));\n        this.registerCustomAttribute('TestBitEnumVerticalBarAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));\n        this.registerCustomAttribute('TestEnumAttr', this.parseTestEnumAttr.bind(this));\n        this.registerCustomAttribute('TestEnumProp', this.parseTestEnumAttr.bind(this));\n        this.registerCustomAttribute('TestEnumPropAttrForm', this.parseTestEnumPropAttrForm.bind(this));\n        this.registerCustomAttribute('TestBitEnumProp', (parser, type) => this.parseEnumFlags(parser, type, ',', true));\n        this.registerCustomAttribute('TestBitEnumPropNamed', this.parseTestBitEnumPropNamed.bind(this));\n        this.registerCustomAttribute('TestArrayOfUglyAttrs', this.parseTestArrayOfUglyAttrs.bind(this));\n        this.registerCustomAttribute('TestArrayOfInts', this.parseTestArrayOfInts.bind(this));\n        this.registerCustomAttribute('TestArrayOfEnums', this.parseTestArrayOfEnums.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'test.conversion_func_op') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        if (result.op === 'test.region_if') {\n            const unresolvedOperands = [];\n            let __regionOp = parser.parseOptionalOperand();\n            while (__regionOp) {\n                unresolvedOperands.push(__regionOp);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                __regionOp = parser.parseOptionalOperand();\n            }\n            parser.parseColon();\n            const inputTypes = parser.parseTypeList();\n            parser.resolveOperands(unresolvedOperands, inputTypes, result.operands);\n            const outputTypes = parser.parseArrowTypeList();\n            for (const t of outputTypes) {\n                result.addTypes([t]);\n            }\n            parser.parseKeyword('then');\n            const thenRegion = {};\n            parser.parseRegion(thenRegion);\n            result.regions.push(thenRegion);\n            parser.parseKeyword('else');\n            const elseRegion = {};\n            parser.parseRegion(elseRegion);\n            result.regions.push(elseRegion);\n            parser.parseKeyword('join');\n            const joinRegion = {};\n            parser.parseRegion(joinRegion);\n            result.regions.push(joinRegion);\n            return true;\n        }\n        if (result.op === 'test.affine_scope' || result.op === 'test.single_no_terminator_custom_asm_op') {\n            const region = result.addRegion();\n            parser.parseRegion(region);\n            return true;\n        }\n        if (result.op === 'test.with_nice_properties') {\n            result.compatibility = true;\n            let label = null;\n            label = parser.parseOptionalString();\n            if (label === null) {\n                label = parser.parseKeyword();\n            }\n            parser.parseKeyword('is');\n            const negative = parser.parseOptionalMinus();\n            const value = parser.parseInteger();\n            result.addAttribute('prop', { label, value: negative ? -value : value });\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        // Test operation with default-valued properties and UnitProp\n        if (result.op === 'test.with_default_valued_properties') {\n            result.compatibility = true;\n            if (parser.parseOptionalKeyword('na')) {\n                // All defaults\n            } else {\n                const a = parser.parseInteger();\n                result.addAttribute('a', a);\n                const __bVal = parser.parseOptionalString();\n                if (__bVal !== null) {\n                    result.addAttribute('b', __bVal);\n                }\n                const c = parser.parseOptionalInteger();\n                if (c !== null) {\n                    result.addAttribute('c', c);\n                }\n                if (parser.parseOptionalKeyword('unit')) {\n                    result.addAttribute('unit', true);\n                } else if (parser.parseOptionalKeyword('unit_absent')) {\n                    result.addAttribute('unit', false);\n                }\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        // Test operation with optional properties using some<...> syntax\n        if (result.op === 'test.with_optional_properties') {\n            result.compatibility = true;\n            const parseOptionalValue = () => {\n                if (parser.parseOptionalKeyword('some')) {\n                    parser.parseLess();\n                    let value = null;\n                    if (parser.parseOptionalKeyword('none')) {\n                        value = null;\n                    } else if (parser.parseOptionalKeyword('unit')) {\n                        value = true;\n                    } else {\n                        const __strVal = parser.parseOptionalString();\n                        if (__strVal === null) {\n                            const neg = parser.parseOptionalMinus();\n                            value = parser.parseInteger();\n                            if (neg) {\n                                value = -value;\n                            }\n                        } else {\n                            value = __strVal;\n                        }\n                    }\n                    parser.parseGreater();\n                    return { some: value };\n                }\n                const __retval2 = parser.parseOptionalString();\n                if (__retval2 !== null) {\n                    return __retval2;\n                }\n                const __neg = parser.parseOptionalMinus();\n                const __val = parser.parseInteger();\n                return __neg ? -__val : __val;\n            };\n            const knownAttrs = ['anAttr', 'simple', 'simplei8', 'simpleui8', 'nonTrivialStorage', 'hasDefault', 'nested', 'longSyntax', 'hasUnit', 'maybeUnit'];\n            for (;;) {\n                const name = parser.parseOptionalKeyword(knownAttrs);\n                if (!name) {\n                    break;\n                }\n                if (name === 'hasUnit') {\n                    result.addAttribute(name, true);\n                } else if (parser.parseOptionalEqual()) {\n                    result.addAttribute(name, parseOptionalValue());\n                } else {\n                    break;\n                }\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        if (result.op === 'test.wrapping_region') {\n            parser.parseKeyword('wraps');\n            const region = result.addRegion();\n            const block = { operations: [] };\n            region.blocks = [block];\n            const wrappedOp = parser.parseGenericOperation();\n            block.operations.push(wrappedOp);\n            if (wrappedOp.results) {\n                for (const opResult of wrappedOp.results) {\n                    result.addTypes([opResult.type]);\n                }\n            }\n            return true;\n        }\n        if (result.op === 'test.pretty_printed_region') {\n            result.operands = parser.parseOperandList();\n            if (parser.parseOptionalKeyword('start')) {\n                const innerOpName = parser.parseCustomOperationName();\n                result.addAttribute('inner_op', innerOpName);\n                parser.parseKeyword('end');\n                parser.parseColon();\n                const fnType = parser.parseType();\n                if (fnType && fnType.inputs) {\n                    parser.resolveOperands(result.operands, fnType.inputs);\n                }\n                if (fnType && fnType.results) {\n                    for (let i = 0; i < fnType.results.length; i++) {\n                        result.addTypes([fnType.results[i]]);\n                    }\n                }\n                parser.parseOptionalLocationSpecifier();\n            } else {\n                parser.parseLParen();\n                const region = result.addRegion();\n                parser.parseRegion(region);\n                parser.parseRParen();\n                parser.parseColon();\n                const fnType = parser.parseType();\n                if (fnType && fnType.inputs) {\n                    parser.resolveOperands(result.operands, fnType.inputs);\n                }\n                if (fnType && fnType.results) {\n                    for (let i = 0; i < fnType.results.length; i++) {\n                        result.addTypes([fnType.results[i]]);\n                    }\n                }\n            }\n            return true;\n        }\n        if (result.op === 'test.isolated_region') {\n            const operand = parser.parseOperand();\n            const indexType = new _.IndexType();\n            parser.resolveOperand(operand, indexType, result.operands);\n            const region = result.addRegion();\n            parser.parseRegion(region, [{ value: operand.toString(), type: new _.IndexType() }]);\n            return true;\n        }\n        if (result.op === 'test.string_attr_pretty_name') {\n            const numResults = parser.getNumResults();\n            for (let i = 0; i < numResults; i++) {\n                result.addTypes([new _.IntegerType('i32')]);\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            if (!result.attributes.has('names') && numResults > 0) {\n                const names = [];\n                for (let i = 0; i < numResults; i++) {\n                    const resultName = parser.getResultName(i);\n                    // Only use names that don't start with a digit (ref impl line 572)\n                    if (resultName && resultName.length > 0 && !/^\\d/.test(resultName)) {\n                        names.push(new _.StringAttr(resultName));\n                    } else {\n                        names.push(new _.StringAttr(''));\n                    }\n                }\n                result.attributes.set('names', new _.ArrayAttr(names));\n            }\n            return true;\n        }\n        if (result.op === 'test.with_bounds_region') {\n            parser.parseOptionalAttrDict(result.attributes);\n            const argName = parser.parseOperand();\n            parser.parseColon();\n            const argType = parser.parseType();\n            const region = result.addRegion();\n            const arg = { value: argName, type: argType };\n            parser.parseRegion(region, [arg]);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseTestEnumAttr(parser, type) {\n        const keyword = parser.parseOptionalKeyword(type.values);\n        if (keyword) {\n            return new _.TypedAttr(keyword, null);\n        }\n        return null;\n    }\n\n    parseTestEnumPropAttrForm(parser) {\n        return parser.parseOptionalAttribute();\n    }\n\n    parseTestBitEnumPropNamed(parser) {\n        if (parser.parseOptionalKeyword('bit_enum')) {\n            if (parser.parseOptionalLess()) {\n                const flags = [];\n                do {\n                    const value = parser.parseKeyword();\n                    flags.push(value);\n                } while (parser.parseOptionalComma());\n                parser.parseGreater();\n                return new _.TypedAttr(`bit_enum<${flags.join(', ')}>`, null);\n            }\n        }\n        return null;\n    }\n\n    // Parse CompoundNestedOuterType: assemblyFormat = \"`<` `i` $inner `>`\"\n    // Full form: !test.cmpnd_nested_outer<i !test.cmpnd_inner<...>>\n    // Elided form: <i <...>>\n    parseCompoundNestedOuterType(parser) {\n        parser.parseLess();\n        parser.parseKeyword('i');\n        // Parse $inner - could be full (!test.cmpnd_inner<...>) or elided (<...>)\n        const inner = parser.parseOptionalType() || this.parseCompoundNestedInnerType(parser);\n        parser.parseGreater();\n        return new _.Type(`!test.cmpnd_nested_outer<i ${inner}>`);\n    }\n\n    // Parse CompoundNestedInnerType: assemblyFormat = \"`<` $some_int $cmpdA `>`\"\n    // Full form: !test.cmpnd_inner<42 !test.cmpnd_a<...>>\n    // Elided form: <42 <...>>\n    parseCompoundNestedInnerType(parser) {\n        parser.parseLess();\n        const someInt = parser.parseInteger();\n        // Parse $cmpdA - could be full (!test.cmpnd_a<...>) or elided (<...>)\n        const cmpdA = parser.parseOptionalType() || this.parseCompoundTypeA(parser);\n        parser.parseGreater();\n        return new _.Type(`!test.cmpnd_inner<${someInt} ${cmpdA}>`);\n    }\n\n    // Parse CompoundTypeA: hasCustomAssemblyFormat = 1\n    // Example: <1, !test.smpla, [5, 6]>\n    parseCompoundTypeA(parser) {\n        parser.parseLess();\n        const width = parser.parseInteger();\n        parser.parseComma();\n        const oneType = parser.parseType();\n        parser.parseComma();\n        parser.parseLSquare();\n        const arrayOfInts = [];\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                arrayOfInts.push(parser.parseInteger());\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        parser.parseGreater();\n        return new _.Type(`!test.cmpnd_a<${width}, ${oneType}, [${arrayOfInts.join(', ')}]>`);\n    }\n\n    parseOptionalLoc(parser, op, attrName = 'loc') {\n        const loc = parser.parseOptionalLocationSpecifier();\n        if (loc) {\n            op.addAttribute(attrName, loc);\n        } else {\n            op.addAttribute(attrName, parser.getCurrentLocation());\n        }\n    }\n\n    parseDummyRegionRef() {\n    }\n\n    parseDummySuccessorRef() {\n    }\n\n    parseTestAttrUgly(parser) {\n        parser.parseKeyword('begin');\n        const attr = parser.parseAttribute();\n        parser.parseKeyword('end');\n        return attr;\n    }\n\n    // Parse TestArrayOfUglyAttrs: assemblyFormat = \"`[` (`]`) : ($value^ ` ` `]`)?\"\n    parseTestArrayOfUglyAttrs(parser) {\n        const elements = [];\n        parser.parseCommaSeparatedList('square', () => {\n            elements.push(this.parseTestAttrUgly(parser));\n        });\n        return new _.ArrayAttr(elements);\n    }\n\n    // Parse TestArrayOfInts: assemblyFormat = \"`[` (`]`) : ($value^ `]`)?\"\n    parseTestArrayOfInts(parser) {\n        const elements = [];\n        parser.parseCommaSeparatedList('square', () => {\n            const isNegative = parser.parseOptionalMinus();\n            const value = parser.parseInteger();\n            elements.push(new _.IntegerAttr(null, isNegative ? -value : value));\n        });\n        return new _.ArrayAttr(elements);\n    }\n\n    // Parse TestArrayOfEnums: elements are SimpleEnumAttr values (a, b, etc.)\n    parseTestArrayOfEnums(parser) {\n        const elements = [];\n        parser.parseCommaSeparatedList('square', () => {\n            const __enumStr = parser.parseOptionalString();\n            if (__enumStr === null) {\n                const value = parser.parseKeyword();\n                elements.push(new _.TypedAttr(value, null));\n            } else {\n                elements.push(new _.TypedAttr(__enumStr, null));\n            }\n        });\n        return new _.ArrayAttr(elements);\n    }\n\n    parseOptionalCustomParser(parser, op, attrName = 'attr') {\n        if (!parser.parseOptionalKeyword('foo')) {\n            return null; // Optional group not taken\n        }\n        const attr = parser.parseAttribute();\n        op.addAttribute(attrName, attr.value);\n        return true;\n    }\n\n    parseDimensionList(parser, op, attrName = 'dimension_list') {\n        if (parser.parseOptionalLSquare()) {\n            parser.parseOptionalRSquare();\n            op.addAttribute(attrName, []);\n            return;\n        }\n        const dimInfo = parser.parseDimensionList(true, false);\n        op.addAttribute(attrName, dimInfo.dimensions);\n    }\n\n    parseCustomOptionalOperand(parser, result) {\n        if (parser.parseOptionalLParen()) {\n            const unresolvedOperand = parser.parseOperand();\n            parser.resolveOperand(unresolvedOperand, null, result.operands);\n            parser.parseRParen();\n        }\n    }\n\n    // Custom directive: operand [, optOperand] -> (varOperands)\n    parseCustomDirectiveOperands(parser, result) {\n        const unresolvedRequired = parser.parseOperand();\n        parser.resolveOperand(unresolvedRequired, null, result.operands);\n        if (parser.parseOptionalComma()) {\n            const unresolvedOptional = parser.parseOperand();\n            parser.resolveOperand(unresolvedOptional, null, result.operands);\n        }\n        parser.parseArrow();\n        parser.parseLParen();\n        let __varOp = parser.parseOptionalOperand();\n        while (__varOp) {\n            parser.resolveOperand(__varOp, null, result.operands);\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            __varOp = parser.parseOptionalOperand();\n        }\n        parser.parseRParen();\n    }\n\n    // Custom directive: operands and types together\n    parseCustomDirectiveOperandsAndTypes(parser, result) {\n        this.parseCustomDirectiveOperands(parser, result);\n        this.parseCustomDirectiveResults(parser, result);\n    }\n\n    // Custom directive: : type [, optType] -> (varTypes)\n    parseCustomDirectiveResults(parser, result) {\n        parser.parseColon();\n        const type = parser.parseType();\n        if (result.operands.length > 0) {\n            result.operands[0].type = type;\n        }\n        if (parser.parseOptionalComma()) {\n            const optType = parser.parseType();\n            if (result.operands.length > 1) {\n                result.operands[1].type = optType;\n            }\n        }\n        parser.parseArrow();\n        parser.parseLParen();\n        let idx = 2; // Start after first two operands\n        do {\n            const varType = parser.parseType();\n            if (result.operands.length > idx) {\n                result.operands[idx].type = varType;\n            }\n            idx++;\n        } while (parser.parseOptionalComma());\n        parser.parseRParen();\n    }\n\n    parseCustomDirectiveWithTypeRefs(parser, result) {\n        // Parses: type_refs_capture : type [, type] -> (types)\n        parser.parseKeyword('type_refs_capture');\n        this.parseCustomDirectiveResults(parser, result);\n    }\n\n    parseCustomDirectiveRegions(parser, result) {\n        const region = result.addRegion();\n        parser.parseRegion(region);\n        while (parser.parseOptionalComma()) {\n            const varRegion = result.addRegion();\n            parser.parseRegion(varRegion);\n        }\n    }\n\n    parseCustomDirectiveSuccessors(parser, result) {\n        if (!result.successors) {\n            result.successors = [];\n        }\n        const successor = {};\n        successor.label = parser.parseOptionalSuccessor();\n        result.successors.push(successor);\n        while (parser.parseOptionalComma()) {\n            const varSuccessor = {};\n            varSuccessor.label = parser.parseOptionalSuccessor();\n            result.successors.push(varSuccessor);\n        }\n    }\n\n    parseCustomDirectiveAttrDict(parser, result) {\n        parser.parseOptionalAttrDict(result.attributes);\n    }\n\n    parseCustomDirectiveAttributes(parser, result) {\n        const attr = parser.parseAttribute();\n        result.addAttribute('attr', attr);\n        if (parser.parseOptionalComma()) {\n            const optAttr = parser.parseAttribute();\n            result.addAttribute('optAttr', optAttr);\n        }\n    }\n\n    parseCustomDirectiveSpacing(parser, op, attrName) {\n        if (attrName) {\n            const name = attrName.name || attrName;\n            const attr = parser.parseAttribute();\n            op.addAttribute(name, attr);\n        }\n    }\n\n    parseCustomDirectiveOptionalOperandRef(parser) {\n        parser.parseInteger();\n    }\n\n    parseSwitchCases(parser, result) {\n        const caseValues = [];\n        while (parser.parseOptionalKeyword('case')) {\n            const value = parser.parseInteger();\n            caseValues.push(value);\n            const region = result.addRegion();\n            parser.parseRegion(region);\n        }\n        result.addAttribute('cases', `array<i64: ${caseValues.join(', ')}>`);\n    }\n\n    parseUsingPropertyInCustom(parser, op, propArg) {\n        const values = [];\n        parser.parseLSquare();\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                values.push(parser.parseInteger());\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        if (propArg) {\n            const propName = typeof propArg === 'string' ? propArg : propArg.name;\n            op.addAttribute(propName, `array<i64: ${values.join(', ')}>`);\n        }\n    }\n\n    parseIntProperty(parser, op, propArg) {\n        const value = parser.parseInteger();\n        if (propArg) {\n            const propName = typeof propArg === 'string' ? propArg : propArg.name;\n            op.addAttribute(propName, value);\n        }\n    }\n\n    parseSumProperty(parser, op, propArg) {\n        const second = parser.parseInteger();\n        parser.parseEqual();\n        parser.parseInteger(); // sum value (validation skipped)\n        if (propArg) {\n            const propName = typeof propArg === 'string' ? propArg : propArg.name;\n            op.addAttribute(propName, second);\n        }\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'test.format_infer_type' || op.op === 'test.format_infer_type2') {\n            op.addTypes([new _.IntegerType('i16')]);\n            return;\n        }\n        if (op.op === 'test.format_types_match_attr') {\n            const valueAttr = op.attributes.get('value');\n            if (valueAttr && valueAttr.type) {\n                op.addTypes([valueAttr.type]);\n                return;\n            }\n        }\n        if (op.op === 'test.format_infer_type_all_operands_and_types' ||\n            op.op === 'test.format_infer_type_all_types_one_operand' ||\n            op.op === 'test.format_infer_type_all_types_two_operands' ||\n            op.op === 'test.format_infer_type_all_types' ||\n            op.op === 'test.format_infer_type_variadic_operands') {\n            for (const operand of op.operands) {\n                if (operand.type) {\n                    op.addTypes([operand.type]);\n                }\n            }\n            return;\n        }\n        if (op.op === 'test.format_infer_type_regions') {\n            const region = op.regions[0];\n            const block = region?.blocks?.[0];\n            if (block?.arguments) {\n                for (const arg of block.arguments) {\n                    if (arg.type) {\n                        op.addTypes([arg.type]);\n                    }\n                }\n            }\n            return;\n        }\n        if (op.op === 'test.with_properties_and_inferred_type') {\n            const lhsAttr = op.attributes.get('lhs');\n            const rhsAttr = op.getAttr('rhs');\n            const lhs = lhsAttr && lhsAttr.value !== undefined ? lhsAttr.value : (lhsAttr || 0);\n            const rhs = rhsAttr !== undefined && rhsAttr !== null ? rhsAttr : 0;\n            const width = (typeof lhs === 'number' ? lhs : 0) + (typeof rhs === 'number' ? rhs : 0);\n            op.addTypes([new _.IntegerType(`i${width}`)]);\n            return;\n        }\n        super.inferResultTypes(op, vars);\n    }\n\n    declareResource(key) {\n        if (!this.blobManager.has(key)) {\n            this.blobManager.set(key, new _.DenseResourceElementsHandle(key));\n        }\n        return this.blobManager.get(key);\n    }\n\n    getResourceKey(handle) {\n        return handle.key;\n    }\n\n    parseResource(entry) {\n        const blob = entry.parseAsBlob();\n        this.blobManager.get(entry.key).blob = blob;\n    }\n};\n\n_.triton = {};\n_.triton.nvws = {};\n_.triton.gluon = {};\n_.triton.nvidia_gpu = {};\n_.triton.amdgpu = {};\n_.triton.proton = {};\n_.triton.xla = {};\n\n_.triton.TensorDescType = class extends _.Type {\n\n    constructor(blockType) {\n        super(null);\n        this.blockType = blockType;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const blockType = parser.parseType();\n        parser.parseGreater();\n        return new _.triton.TensorDescType(blockType);\n    }\n\n    toString() {\n        return `!tt.tensordesc<${this.blockType}>`;\n    }\n};\n\n_.triton.PointerType = class extends _.Type {\n\n    constructor(pointeeType, addressSpace) {\n        super(null);\n        this.pointeeType = pointeeType;\n        this.addressSpace = addressSpace || 1;\n    }\n\n    static parse(parser) {\n        parser.parseLess();\n        const pointeeType = parser.parseType();\n        let addressSpace = 1;\n        if (parser.parseOptionalComma()) {\n            addressSpace = parser.parseInteger();\n\n        }\n        parser.parseGreater();\n        return new _.triton.PointerType(pointeeType, addressSpace);\n    }\n\n    toString() {\n        const pointeeStr = this.pointeeType?.toString ? this.pointeeType.toString() : this.pointeeType;\n        if (this.addressSpace && this.addressSpace !== 1) {\n            return `!tt.ptr<${pointeeStr}, ${this.addressSpace}>`;\n        }\n        return `!tt.ptr<${pointeeStr}>`;\n    }\n};\n\n_.triton.TritonDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tt');\n        this.registerCustomType('TT_Ptr', (parser) => _.triton.PointerType.parse(parser));\n        this.registerCustomType('TT_TensorDescType', this.parseTensorDescType.bind(this));\n        this.registerCustomType('TT_TensorPtr', (parser) => _.triton.PointerType.parse(parser));\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            // Handle ptr type specifically to properly parse pointee type\n            if (mnemonic === 'ptr') {\n                return _.triton.PointerType.parse(parser);\n            }\n            if (mnemonic === 'tensordesc') {\n                return _.triton.TensorDescType.parse(parser);\n            }\n            throw new mlir.Error(`Unsupported type '!${dialect}.${mnemonic}'.`);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tt.func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseTensorDescType(parser) {\n        if (parser.parseOptionalLess()) {\n            const blockType = parser.parseType();\n            parser.parseGreater();\n            return new _.triton.TensorDescType(blockType);\n        }\n        return null;\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'tt.load' && op.operands.length > 0) {\n            const ptrType = op.operands[0].type;\n            if (ptrType instanceof _.triton.PointerType) {\n                op.addTypes([ptrType.pointeeType]);\n            } else if (ptrType instanceof _.RankedTensorType) {\n                const elementType = ptrType.elementType;\n                if (elementType instanceof _.triton.PointerType) {\n                    const pointeeType = elementType.pointeeType;\n                    op.addTypes([new _.RankedTensorType(ptrType.shape, pointeeType, ptrType.encoding)]);\n                    return;\n                }\n            }\n        }\n        if (op.op === 'tt.unsplat') {\n            const srcType = op.operands[0]?.type;\n            if (srcType instanceof _.RankedTensorType) {\n                op.addTypes([srcType.elementType]);\n                return;\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.triton.gpu = {};\n\n_.triton.gpu.TritonGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'ttg');\n        this.registerCustomType('TTG_MemDescType', this.parseMemDescType.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'ttg.warp_specialize') {\n            const unresolvedOperands = [];\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    unresolvedOperands.push(parser.parseOperand());\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            parser.parseKeyword('default');\n            const defaultRegion = {};\n            parser.parseRegion(defaultRegion);\n            result.regions.push(defaultRegion);\n            const partitionNumWarps = [];\n            let partitionIndex = 0;\n            while (parser.parseOptionalKeyword(`partition${partitionIndex}`)) {\n                const argResult = parser.parseFunctionArgumentList();\n                parser.parseKeyword('num_warps');\n                parser.parseLParen();\n                const numWarps = parser.parseInteger();\n                partitionNumWarps.push(parseInt(numWarps, 10));\n                parser.parseRParen();\n                const partitionRegion = {};\n                partitionRegion.arguments = argResult.arguments;\n                parser.parseRegion(partitionRegion);\n                if (!result.regions[1]) {\n                    result.regions[1] = { blocks: [{ operations: [] }] };\n                }\n                partitionIndex++;\n            }\n            parser.parseColon();\n            const fnType = parser.parseType();\n            if (fnType instanceof _.FunctionType) {\n                result.addAttribute('function_type', new _.TypeAttrOf(fnType));\n                parser.resolveOperands(unresolvedOperands, fnType.inputs, result.operands);\n                result.addTypes(fnType.results);\n            } else {\n                result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType([], [fnType])));\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n                result.addTypes([fnType]);\n            }\n            if (partitionNumWarps.length > 0) {\n                result.addAttribute('partitionNumWarps', { type: 'array', element_type: 'i32', value: partitionNumWarps });\n            }\n            return true;\n        }\n        if (result.op === 'ttg.barrier') {\n            const flags = [];\n            flags.push(parser.parseKeyword());\n            while (parser.parseOptionalVerticalBar()) {\n                flags.push(parser.parseKeyword());\n            }\n            result.addAttribute('addrSpace', new _.TypedAttr(flags.join('|')));\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseMemDescType(parser) {\n        // Handle shorthand MemDescType notation: <dims x elementType, attributes...>\n        // Full notation would be: !ttg.memdesc<dims x elementType, attributes...>\n        const content = parser.parseTypeParameters();\n        if (!content) {\n            return null;\n        }\n        return new _.Type(`!ttg.memdesc<${content}>`);\n    }\n};\n\n_.triton.gluon.GluonDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'gluon');\n    }\n};\n\n_.triton.nvidia_gpu.TritonNvidiaGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'ttng');\n        this.registerCustomDirective('Token', this.parseToken.bind(this));\n        this.registerCustomDirective('BarriersAndPreds', this.parseBarriersAndPreds.bind(this));\n    }\n\n    parseToken(parser, op, depOperands, tokenTypeArr) {\n        // custom<Token>($acc_dep, type($token))\n        // depOperands = operands array, tokenTypeArr = types array\n        if (!parser.parseOptionalLSquare()) {\n            return;\n        }\n        // Push token type to the types array\n        if (Array.isArray(tokenTypeArr)) {\n            tokenTypeArr.push(new _.Type('!ttng.async.token'));\n        }\n        if (parser.parseOptionalRSquare()) {\n            return;\n        }\n        {\n            const __depOp = parser.parseOptionalOperand();\n            if (__depOp) {\n                if (!Array.isArray(depOperands)) {\n                    throw new mlir.Error(`Expected depOperands to be an array ${parser.getCurrentLocation()}`);\n                }\n                depOperands.push(__depOp);\n            }\n        }\n        parser.parseRSquare();\n    }\n\n    parseBarriersAndPreds(parser, op, barrierOperands, predOperands) {\n        while (parser.parseOptionalComma()) {\n            const __barrier = parser.parseOptionalOperand();\n            if (__barrier) {\n                if (!Array.isArray(barrierOperands)) {\n                    throw new mlir.Error(`Expected barrierOperands to be an array ${parser.getCurrentLocation()}`);\n                }\n                barrierOperands.push(__barrier);\n                if (parser.parseOptionalLSquare()) {\n                    const __pred = parser.parseOptionalOperand();\n                    if (__pred) {\n                        if (!Array.isArray(predOperands)) {\n                            throw new mlir.Error(`Expected predOperands to be an array ${parser.getCurrentLocation()}`);\n                        }\n                        predOperands.push(__pred);\n                    }\n                    parser.parseRSquare();\n                }\n            }\n        }\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n};\n\n_.triton.amdgpu.TritonAMDGPUDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'amdg');\n        this.registerCustomType('TT_Ptr', 'tt.ptr');\n        this.registerCustomType('TT_TensorPtr', 'tt.ptr');\n        this.registerCustomType('TTG_MemDescType', 'ttg.memdesc');\n    }\n\n};\n\n_.triton.proton.ProtonDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'proton');\n    }\n};\n\n_.triton.nvws.NVWSDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'nvws');\n        this.registerCustomType('NVWS_ArefType', this.parseArefTypeShorthand.bind(this));\n    }\n\n    parseArefTypeShorthand(parser) {\n        const content = parser.parseTypeParameters();\n        if (content) {\n            return new _.Type(`!nvws.aref${content}`);\n        }\n        return parser.parseType();\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'nvws.warp_group') {\n            parser.parseOptionalAttrDictWithKeyword(result.attributes);\n            const numWarps = [];\n            let partitionIndex = 0;\n            while (parser.parseOptionalKeyword(`partition${partitionIndex}`)) {\n                parser.parseKeyword('num_warps');\n                parser.parseLParen();\n                const n = parser.parseInteger();\n                numWarps.push(n);\n                parser.parseRParen();\n                const region = result.addRegion();\n                parser.parseRegion(region);\n                partitionIndex++;\n            }\n            result.addAttribute('numWarps', numWarps);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.MichelsonDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'michelson');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            const simpleTypes = ['int', 'bytes', 'operation', 'nat', 'string', 'unit', 'bool', 'mutez', 'timestamp', 'address', 'key', 'signature', 'chain_id', 'key_hash'];\n            if (simpleTypes.includes(type.substring(11))) { // Remove \"!michelson.\" prefix\n                return new _.Type(type);\n            }\n            const typesWithParams = ['pair', 'list', 'option', 'or', 'map', 'big_map', 'set', 'contract', 'lambda'];\n            if (typesWithParams.includes(type.substring(11))) {\n                type += parser.parseTypeParameters();\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n};\n\n_.PlanDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'plan');\n        this.registerCustomDirective('WithValuesTypes', this.parseWithValuesTypes.bind(this));\n    }\n\n    parseWithValuesTypes(parser, op, elementsRef, resultTypes, elementsTypes) {\n        const resultType = parser.parseType();\n        resultTypes.push(resultType);\n        if (op.types.length === 0) {\n            op.addTypes([resultType]);\n        } else {\n            op.types[0] = resultType;\n        }\n        // Derive element types from tensor's element type (matching C++ getElementTypeOrSelf)\n        const elementType = resultType.elementType || resultType;\n        // Populate element types for each element operand\n        if (elementsRef && elementsRef.length > 0) {\n            for (let i = 0; i < elementsRef.length; i++) {\n                elementsTypes.push(elementType);\n            }\n        }\n    }\n};\n\n_.KernelDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'kernel');\n        this.registerCustomDirective('KernelFunctionalType', this.parseKernelFunctionalType.bind(this));\n    }\n\n    parseKernelFunctionalType(parser, op /*, args */) {\n        parser.parseLParen();\n        if (!parser.parseOptionalRParen()) {\n            do {\n                parser.parseType();\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.parseArrow();\n        const resultTypes = [];\n        if (parser.parseOptionalLParen()) {\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    resultTypes.push(parser.parseType());\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n        } else {\n            resultTypes.push(parser.parseType());\n        }\n        if (resultTypes.length > 0) {\n            op.addTypes(resultTypes);\n        }\n    }\n\n    inferResultTypes(op, vars) {\n        // kernel.combiner: result types are the first half of the input types\n        if (op.op === 'kernel.combiner') {\n            const inputsEntry = vars.get('inputs');\n            if (inputsEntry?.types?.length > 0) {\n                const numPairs = Math.floor(inputsEntry.types.length / 2);\n                const resultTypes = inputsEntry.types.slice(0, numPairs);\n                op.addTypes(resultTypes);\n                return;\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.tensorrt = {};\n\n_.tensorrt.TensorRTDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tensorrt');\n        this.registerCustomAttribute('TensorRT_TopKOperationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ScatterModeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ResizeSelectorAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ResizeRoundModeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ResizeModeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ResizeCoordinateTransformationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ReduceOperationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_PaddingModeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_MatrixOperationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_LoopOutputAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_GatherModeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_FillOperationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ElementWiseOperationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_ActivationTypeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_UnaryOperationAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_TripLimitAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomAttribute('TensorRT_PoolingTypeAttr', this.parseEnumAttrBracket.bind(this));\n        this.registerCustomDirective('StaticIndexI64Array', this.parseStaticIndexI64Array.bind(this));\n        this.registerCustomDirective('StaticIndexI32Array', this.parseStaticIndexI32Array.bind(this));\n    }\n\n    parseEnumAttrBracket(parser) {\n        if (parser.parseOptionalLess()) {\n            const value = parser.parseKeyword();\n            parser.parseGreater();\n            return { value };\n        }\n        return null;\n    }\n\n    parseStaticIndexI64Array(parser, op, attrName = 'broadcast_dims') {\n        const values = [];\n        do {\n            const value = parser.parseOptionalInteger();\n            if (value === null) {\n                break;\n            }\n            values.push(value);\n        } while (parser.parseOptionalComma());\n        op.addAttribute(attrName, values);\n    }\n\n    parseStaticIndexI32Array(parser, op, attrName = 'static_values') {\n        const values = [];\n        do {\n            const value = parser.parseOptionalInteger();\n            if (value === null) {\n                break;\n            }\n            values.push(value);\n        } while (parser.parseOptionalComma());\n        op.addAttribute(attrName, values);\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'tensorrt.for') {\n            return this.parseForOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseForOp(parser, result) {\n        const inductionVar = parser.parseOperand();\n        parser.parseEqual();\n        const unresolvedLb = parser.parseOperand();\n        parser.resolveOperand(unresolvedLb, null, result.operands);\n        parser.parseKeyword('to');\n        const unresolvedUb = parser.parseOperand();\n        parser.resolveOperand(unresolvedUb, null, result.operands);\n        parser.parseKeyword('step');\n        const unresolvedStep = parser.parseOperand();\n        parser.resolveOperand(unresolvedStep, null, result.operands);\n        parser.parseKeyword('init');\n        const regionArgs = [{ name: inductionVar.name, type: null }];\n        if (parser.parseOptionalLParen()) {\n            while (!parser.parseOptionalRParen()) {\n                let iterArgName = null;\n                const __iterArg = parser.parseOptionalOperand();\n                if (__iterArg) {\n                    iterArgName = __iterArg.name;\n                }\n                if (parser.parseOptionalEqual()) {\n                    const __initOp = parser.parseOptionalOperand();\n                    if (__initOp) {\n                        parser.resolveOperand(__initOp, null, result.operands);\n                        if (iterArgName) {\n                            regionArgs.push({ name: iterArgName, type: null });\n                        }\n                    }\n                }\n                parser.parseOptionalComma();\n            }\n        }\n        result.addTypes(parser.parseOptionalArrowTypeList());\n        parser.parseOptionalRegion(result.addRegion(), regionArgs);\n        parser.parseOptionalAttrDict(result.attributes);\n        return true;\n    }\n};\n\n_.executor = {};\n\n_.executor.TableType = class extends _.Type {\n\n    constructor(body) {\n        super(null);\n        this.body = body;\n    }\n\n    toString() {\n        const bodyStr = this.body.map((t) => t.toString()).join(', ');\n        return `!executor.table<${bodyStr}>`;\n    }\n};\n\n_.executor.ExecutorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'executor');\n        this.registerCustomType('Executor_Table', this.parseTable.bind(this));\n        this.registerCustomDirective('ExecutorMixedIndices', this.parseExecutorMixedIndices.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'executor.func') {\n            parser.parseFunctionOp(result, true);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'executor.table.get') {\n            // ExtractTableValueOp::inferReturnTypes\n            const tableType = op.operands[0]?.type;\n            const index = op.attributes.get('index');\n            if (tableType instanceof _.executor.TableType && index !== undefined) {\n                const idx = typeof index === 'number' ? index : parseInt(index, 10);\n                if (idx >= 0 && idx < tableType.body.length) {\n                    op.addTypes([tableType.body[idx]]);\n                    return;\n                }\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            if (mnemonic === 'table') {\n                if (parser.parseOptionalLess()) {\n                    const body = [];\n                    if (!parser.parseOptionalGreater()) {\n                        do {\n                            const elementType = parser.parseType();\n                            body.push(elementType);\n                        } while (parser.parseOptionalComma());\n                        parser.parseGreater();\n                    }\n                    return new _.executor.TableType(body);\n                }\n                return new _.executor.TableType([]);\n            }\n            let type = `!${dialect}.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    parseTable(parser) {\n        if (parser.parseOptionalLess()) {\n            const body = [];\n            if (!parser.parseOptionalGreater()) {\n                do {\n                    const elementType = parser.parseType();\n                    body.push(elementType);\n                } while (parser.parseOptionalComma());\n                parser.parseGreater();\n            }\n            return new _.executor.TableType(body);\n        }\n        return null;\n    }\n\n    parseExecutorMixedIndices(parser, op /*, args */) {\n        const unresolvedOperands = [];\n        do {\n            const __mixedOp = parser.parseOptionalOperand();\n            if (__mixedOp) {\n                unresolvedOperands.push(__mixedOp);\n            } else {\n                parser.parseAttribute();\n            }\n        } while (parser.parseOptionalComma());\n        for (const unresolved of unresolvedOperands) {\n            parser.resolveOperand(unresolved, null, op.operands);\n        }\n    }\n};\n\n_.TFRTTestDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfrt_test');\n        this.registerCustomDirective('OptionalLoc', this.parseOptionalLoc.bind(this));\n        this.registerCustomDirective('DummyRegionRef', this.parseDummyRegionRef.bind(this));\n        this.registerCustomDirective('DummySuccessorRef', this.parseDummySuccessorRef.bind(this));\n    }\n\n    parseOptionalLoc(parser, op, attrName = 'loc') {\n        const loc = parser.parseOptionalLocationSpecifier();\n        if (loc) {\n            op.addAttribute(attrName, loc);\n        } else {\n            op.addAttribute(attrName, parser.getCurrentLocation());\n        }\n    }\n\n    parseDummyRegionRef() {\n    }\n\n    parseDummySuccessorRef() {\n    }\n\n    parseOperation(parser, result) {\n        const opInfo = result.name.getRegisteredInfo();\n        if (!opInfo) {\n            return false;\n        }\n        if (opInfo.metadata.assemblyFormat === 'operands attr-dict') {\n            const unresolvedOperands = parser.parseOperandList();\n            parser.parseOptionalAttrDict(result.attributes);\n            for (const unresolved of unresolvedOperands) {\n                parser.resolveOperand(unresolved, null, result.operands);\n            }\n            this.inferResultTypes(result, new Map());\n            return true;\n        }\n        if (result.op === 'tfrt_test.do.async') {\n            const unresolvedOperands = parser.parseOperandList('none');\n            if (unresolvedOperands.length > 0) {\n                parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);\n            }\n            if (parser.parseOptionalColon()) {\n                const type = parser.parseType();\n                if (type && type.results) {\n                    type.results.forEach((resultType) => {\n                        result.addTypes([resultType]);\n                    });\n                }\n            }\n            parser.parseOptionalRegion(result.addRegion());\n            return true;\n        }\n        if (result.op === 'tfrt_test.benchmark') {\n            const __benchName = parser.parseOptionalString();\n            if (__benchName !== null) {\n                result.addAttribute('name', __benchName);\n            }\n            parser.parseLParen();\n            let __benchOp = parser.parseOptionalOperand();\n            while (__benchOp) {\n                let type = null;\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.resolveOperand(__benchOp, type, result.operands);\n                if (!parser.parseOptionalComma()) {\n                    break;\n                }\n                __benchOp = parser.parseOptionalOperand();\n            }\n            parser.parseRParen();\n            for (let name = parser.parseOptionalKeyword(); name; name = parser.parseOptionalKeyword()) {\n                parser.parseEqual();\n                let value = null;\n                const __intVal = parser.parseOptionalInteger();\n                if (__intVal === null) {\n                    const __strVal = parser.parseOptionalString();\n                    if (__strVal === null) {\n                        value = parser.parseKeyword();\n                    } else {\n                        value = __strVal;\n                    }\n                } else {\n                    value = __intVal;\n                }\n                result.addAttribute(name, value);\n                parser.parseOptionalComma();\n            }\n            parser.parseOptionalRegion(result.addRegion());\n            result.addTypes([new _.Type('!tfrt.chain')]);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.XeVMDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xevm');\n        this.registerCustomAttribute('XeVM_TruncfSrcElemTypeAttr', this.parseTruncfSrcElemTypeAttr.bind(this));\n        this.registerCustomAttribute('XeVM_TruncfDstElemTypeAttr', this.parseTruncfDstElemTypeAttr.bind(this));\n    }\n\n    parseTruncfSrcElemTypeAttr(parser) {\n        parser.parseKeyword('src_etype');\n        parser.parseEqual();\n        const value = parser.parseKeyword();\n        return new _.TypedAttr(value, null);\n    }\n\n    parseTruncfDstElemTypeAttr(parser) {\n        parser.parseKeyword('dst_etype');\n        parser.parseEqual();\n        const value = parser.parseKeyword();\n        return new _.TypedAttr(value, null);\n    }\n};\n\n_.VMVXDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'vmvx');\n    }\n};\n\n_.MLRTDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'mlrt');\n    }\n};\n\n_.TFRTTensorDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfrt_tensor');\n    }\n};\n\n_.TFRTDHTDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfrt_dht');\n    }\n};\n\n_.TFDDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'tfd');\n    }\n};\n\n_.ACCDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'acc');\n        this.registerCustomDirective('Var', this.parseVar.bind(this));\n        this.registerCustomDirective('AccVar', this.parseAccVar.bind(this));\n        this.registerCustomDirective('VarPtrType', this.parseVarPtrType.bind(this));\n        this.registerCustomDirective('DeviceTypeOperandsWithKeywordOnly', this.parseDeviceTypeOperandsWithKeywordOnly.bind(this));\n        this.registerCustomDirective('LoopControl', this.parseLoopControl.bind(this));\n        this.registerCustomDirective('WaitClause', this.parseWaitClause.bind(this));\n        this.registerCustomDirective('NumGangs', this.parseNumGangs.bind(this));\n        this.registerCustomDirective('DeviceTypeOperands', this.parseDeviceTypeOperands.bind(this));\n        this.registerCustomDirective('GangClause', this.parseGangClause.bind(this));\n        this.registerCustomDirective('CombinedConstructsLoop', this.parseCombinedConstructsLoop.bind(this));\n        this.registerCustomDirective('RecipeSym', this.parseRecipeSym.bind(this));\n        this.registerCustomDirective('OperandWithKeywordOnly', this.parseOperandWithKeywordOnly.bind(this));\n        this.registerCustomDirective('OperandsWithKeywordOnly', this.parseOperandsWithKeywordOnly.bind(this));\n        this.registerCustomDirective('DeviceTypeOperandsWithSegment', this.parseDeviceTypeOperandsWithSegment.bind(this));\n        this.registerCustomDirective('BindName', this.parseBindName.bind(this));\n        this.registerCustomDirective('RoutineGangClause', this.parseRoutineGangClause.bind(this));\n        this.registerCustomDirective('DeviceTypeArrayAttr', this.parseDeviceTypeArrayAttr.bind(this));\n    }\n\n    // custom<Var>($var) - receives ctx.get('var').operands\n    parseVar(parser, op, operands) {\n        if (!parser.parseOptionalKeyword('varPtr')) {\n            parser.parseKeyword('var');\n        }\n        parser.parseLParen();\n        operands.push(parser.parseOperand());\n    }\n\n    // custom<AccVar>($accVar, type($accVar)) - self-contained with type inline\n    parseAccVar(parser, op, operands, types) {\n        if (!parser.parseOptionalKeyword('accPtr')) {\n            parser.parseKeyword('accVar');\n        }\n        parser.parseLParen();\n        operands.push(parser.parseOperand());\n        parser.parseColon();\n        types.push(parser.parseType());\n        parser.parseRParen();\n    }\n\n    // custom<VarPtrType>(type($var), $varType) - receives ctx.get('var').types\n    parseVarPtrType(parser, op, types, varTypeAttrName) {\n        const type = parser.parseType();\n        types.push(type);\n        parser.parseRParen();\n        if (parser.parseOptionalKeyword('varType')) {\n            parser.parseLParen();\n            const varType = parser.parseType();\n            op.addAttribute(varTypeAttrName || 'varType', varType);\n            parser.parseRParen();\n        }\n    }\n\n    parseDeviceTypeOperandsWithKeywordOnly(parser, op, operands, types, deviceTypesVar, keywordOnlyVar) {\n        if (!parser.parseOptionalLParen()) {\n            op.addAttribute(keywordOnlyVar, [{ value: 'none' }]);\n            return;\n        }\n        const keywordOnlyAttrs = [];\n        let needComma = false;\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const attr = parser.parseAttribute();\n                keywordOnlyAttrs.push(attr);\n                parser.parseOptionalComma();\n            }\n            needComma = true;\n        }\n        if (keywordOnlyAttrs.length > 0) {\n            op.addAttribute(keywordOnlyVar, keywordOnlyAttrs);\n        }\n        if (needComma) {\n            parser.parseOptionalComma();\n        }\n        const unresolvedOperands = [];\n        const operandTypes = [];\n        const deviceTypes = [];\n        if (!parser.parseOptionalRParen()) {\n            do {\n                const operand = parser.parseOperand();\n                parser.parseColon();\n                const type = parser.parseType();\n                unresolvedOperands.push(operand);\n                operandTypes.push(type);\n                if (parser.parseOptionalLSquare()) {\n                    const deviceType = parser.parseAttribute();\n                    deviceTypes.push(deviceType);\n                    parser.parseRSquare();\n                } else {\n                    deviceTypes.push({ value: 'none' });\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRParen();\n        }\n        parser.resolveOperands(unresolvedOperands, operandTypes, op.operands);\n        if (deviceTypes.length > 0) {\n            op.addAttribute(deviceTypesVar, deviceTypes);\n        }\n    }\n\n    parseLoopControl(parser, result) {\n        const inductionVars = [];\n        if (parser.parseOptionalKeyword('control')) {\n            parser.parseLParen();\n            while (!parser.parseOptionalRParen()) {\n                const value = parser.parseOperand();\n                parser.parseColon();\n                const type = parser.parseType();\n                inductionVars.push({ value, type });\n                parser.parseOptionalComma();\n            }\n            parser.parseEqual();\n            parser.parseLParen();\n            const lowerbound = parser.parseOperandList();\n            const lowerboundTypes = parser.parseColonTypeList();\n            parser.resolveOperands(lowerbound, lowerboundTypes, result.operands);\n            parser.parseRParen();\n            parser.parseKeyword('to');\n            parser.parseLParen();\n            const upperbound = parser.parseOperandList();\n            const upperboundTypes = parser.parseColonTypeList();\n            parser.resolveOperands(upperbound, upperboundTypes, result.operands);\n            parser.parseRParen();\n            parser.parseKeyword('step');\n            parser.parseLParen();\n            const step = parser.parseOperandList();\n            const stepTypes = parser.parseColonTypeList();\n            parser.resolveOperands(step, stepTypes, result.operands);\n            parser.parseRParen();\n        }\n        const region = result.addRegion();\n        parser.parseRegion(region, inductionVars);\n    }\n\n    parseWaitClause(parser, result) {\n        if (!parser.parseOptionalLParen()) {\n            return;\n        }\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                parser.parseAttribute();\n                parser.parseOptionalComma();\n            }\n            parser.parseOptionalComma();\n        }\n        while (!parser.parseOptionalRParen()) {\n            if (parser.parseOptionalLBrace()) {\n                parser.parseOptionalKeyword('devnum');\n                parser.parseOptionalColon();\n                while (!parser.parseOptionalRBrace()) {\n                    const operand = parser.parseOperand();\n                    parser.parseColon();\n                    const type = parser.parseType();\n                    parser.resolveOperand(operand, type, result.operands);\n                    parser.parseOptionalComma();\n                }\n                if (parser.parseOptionalLSquare()) {\n                    parser.parseAttribute();\n                    parser.parseRSquare();\n                }\n            }\n            parser.parseOptionalComma();\n        }\n    }\n\n    parseNumGangs(parser, result) {\n        while (parser.parseOptionalLBrace()) {\n            while (!parser.parseOptionalRBrace()) {\n                const operand = parser.parseOperand();\n                parser.parseColon();\n                const type = parser.parseType();\n                parser.resolveOperand(operand, type, result.operands);\n                parser.parseOptionalComma();\n            }\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            parser.parseOptionalComma();\n        }\n    }\n\n    parseDeviceTypeOperands(parser, result) {\n        let __devOp = parser.parseOptionalOperand();\n        while (__devOp) {\n            parser.parseColon();\n            const type = parser.parseType();\n            parser.resolveOperand(__devOp, type, result.operands);\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n            __devOp = parser.parseOptionalOperand();\n        }\n    }\n\n    parseGangClause(parser, op, gangOperands, gangTypes, gangArgTypeVar, gangDeviceTypeVar, gangSegmentsVar, gangOnlyVar) {\n        if (!parser.parseOptionalLParen()) {\n            op.addAttribute(gangOnlyVar, [{ value: 'none' }]);\n            return;\n        }\n        const gangOnlyAttrs = [];\n        let needComma = false;\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                const attr = parser.parseAttribute();\n                gangOnlyAttrs.push(attr);\n                parser.parseOptionalComma();\n            }\n            needComma = true;\n        }\n        if (gangOnlyAttrs.length > 0) {\n            op.addAttribute(gangOnlyVar, gangOnlyAttrs);\n        }\n        if (needComma) {\n            parser.parseOptionalComma();\n        }\n        const gangArgTypes = [];\n        const deviceTypes = [];\n        const segments = [];\n        while (parser.parseOptionalLBrace()) {\n            let segmentCount = 0;\n            do {\n                let argType = 'Num';\n                if (parser.parseOptionalKeyword('num')) {\n                    parser.parseEqual();\n                    argType = 'Num';\n                } else if (parser.parseOptionalKeyword('dim')) {\n                    parser.parseEqual();\n                    argType = 'Dim';\n                } else if (parser.parseOptionalKeyword('static')) {\n                    parser.parseEqual();\n                    argType = 'Static';\n                }\n                gangArgTypes.push({ value: argType });\n                const operand = parser.parseOperand();\n                parser.parseColon();\n                const type = parser.parseType();\n                parser.resolveOperand(operand, type, op.operands);\n                segmentCount++;\n            } while (parser.parseOptionalComma());\n            parser.parseRBrace();\n            segments.push(segmentCount);\n            if (parser.parseOptionalLSquare()) {\n                const deviceType = parser.parseAttribute();\n                deviceTypes.push(deviceType);\n                parser.parseRSquare();\n            } else {\n                deviceTypes.push({ value: 'none' });\n            }\n            if (!parser.parseOptionalComma()) {\n                break;\n            }\n        }\n        parser.parseRParen();\n        if (gangArgTypes.length > 0) {\n            op.addAttribute('gangOperandsArgType', gangArgTypes);\n        }\n        if (deviceTypes.length > 0) {\n            op.addAttribute('gangOperandsDeviceType', deviceTypes);\n        }\n        if (segments.length > 0) {\n            op.addAttribute('gangOperandsSegments', segments);\n        }\n    }\n\n    parseCombinedConstructsLoop(parser, result) {\n        const attr = parser.parseAttribute();\n        result.addAttribute('combined', attr);\n    }\n\n    parseRecipeSym(parser, result) {\n        const attr = parser.parseAttribute();\n        result.addAttribute('recipe', attr);\n    }\n\n    parseOperandWithKeywordOnly(parser, result) {\n        if (!parser.parseOptionalLParen()) {\n            return;\n        }\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                parser.parseAttribute();\n                parser.parseOptionalComma();\n            }\n            parser.parseOptionalComma();\n        }\n        while (!parser.parseOptionalRParen()) {\n            const operand = parser.parseOperand();\n            parser.parseColon();\n            const type = parser.parseType();\n            parser.resolveOperand(operand, type, result.operands);\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            parser.parseOptionalComma();\n        }\n    }\n\n    parseOperandsWithKeywordOnly(parser, result) {\n        // Handles format: (%v1, %v2 : t1, t2) where all operands are listed before colon\n        // and all types are listed after colon\n        if (!parser.parseOptionalLParen()) {\n            return;\n        }\n        if (parser.parseOptionalRParen()) {\n            return;\n        }\n        const unresolvedOperands = [];\n        parser.parseCommaSeparatedList('none', () => {\n            unresolvedOperands.push(parser.parseOperand());\n        });\n        parser.parseColon();\n        const types = [];\n        parser.parseCommaSeparatedList('none', () => {\n            types.push(parser.parseType());\n        });\n        parser.resolveOperands(unresolvedOperands, types, result.operands);\n        parser.parseRParen();\n    }\n\n    parseDeviceTypeOperandsWithSegment(parser, result) {\n        this.parseNumGangs(parser, result);\n    }\n\n    parseBindName(parser, result) {\n        parser.parseCommaSeparatedList('none', () => {\n            const attr = parser.parseAttribute();\n            if (parser.parseOptionalLSquare()) {\n                parser.parseAttribute();\n                parser.parseRSquare();\n            }\n            result.addAttribute('bind', attr);\n        });\n    }\n\n    parseRoutineGangClause(parser, result) {\n        if (parser.parseOptionalLParen()) {\n            while (!parser.parseOptionalRParen()) {\n                if (parser.parseOptionalKeyword('dim')) {\n                    parser.parseColon();\n                }\n                const value = parser.parseAttribute();\n                if (parser.parseOptionalLSquare()) {\n                    parser.parseAttribute();\n                    parser.parseRSquare();\n                }\n                result.addAttribute('gangDim', value);\n                parser.parseOptionalComma();\n            }\n        } else if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                parser.parseAttribute();\n                parser.parseOptionalComma();\n            }\n        }\n    }\n\n    parseDeviceTypeArrayAttr(parser) {\n        if (parser.parseOptionalLSquare()) {\n            while (!parser.parseOptionalRSquare()) {\n                parser.parseAttribute();\n                parser.parseOptionalComma();\n            }\n        }\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'acc.compute_region') {\n            const entryArguments = [];\n            const launchOperands = [];\n            const inputOperands = [];\n            const inputTypes = [];\n            let streamOperand = null;\n            if (parser.parseOptionalKeyword('stream')) {\n                parser.parseLParen();\n                streamOperand = parser.parseOperand();\n                parser.parseColon();\n                const type = parser.parseType();\n                parser.resolveOperand(streamOperand, type, result.operands);\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalKeyword('launch')) {\n                parser.parseLParen();\n                do {\n                    const argName = parser.parseOperand();\n                    parser.parseEqual();\n                    const val = parser.parseOperand();\n                    launchOperands.push(val);\n                    entryArguments.push({ name: argName.name, type: new _.Type('!acc.par_width') });\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalKeyword('ins')) {\n                parser.parseLParen();\n                do {\n                    const argName = parser.parseOperand();\n                    parser.parseEqual();\n                    const val = parser.parseOperand();\n                    inputOperands.push(val);\n                    entryArguments.push({ name: argName.name, type: null });\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n                parser.parseColon();\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        inputTypes.push(parser.parseType());\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n                let typeIdx = 0;\n                for (const arg of entryArguments) {\n                    if (!arg.type) {\n                        arg.type = inputTypes[typeIdx++];\n                    }\n                }\n            }\n            const resultTypes = parser.parseOptionalArrowTypeList();\n            for (const type of resultTypes) {\n                result.types.push(type);\n            }\n            for (const op of launchOperands) {\n                parser.resolveOperand(op, null, result.operands);\n            }\n            for (let i = 0; i < inputOperands.length; i++) {\n                parser.resolveOperand(inputOperands[i], inputTypes[i] || null, result.operands);\n            }\n            const region = result.addRegion();\n            parser.parseRegion(region, entryArguments, true);\n            parser.parseOptionalAttrDict(result.attributes);\n            const segmentSizes = [launchOperands.length, inputOperands.length, streamOperand ? 1 : 0];\n            result.addAttribute('operandSegmentSizes', new _.DenseI32ArrayAttr(segmentSizes));\n            this.inferResultTypes(result, new Map());\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.smt = {};\n\n_.smt.BitVectorType = class extends _.Type {\n\n    constructor(width) {\n        super(null);\n        this.width = width;\n    }\n\n    toString() {\n        return `!smt.bv<${this.width}>`;\n    }\n};\n\n_.smt.SMTDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'smt');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'smt.eq' || result.op === 'smt.distinct') {\n            const unresolvedOperands = parser.parseOperandList();\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            const type = parser.parseType();\n            const types = unresolvedOperands.map(() => type);\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n            result.addTypes([new _.Type('!smt.bool')]);\n            return true;\n        }\n        if (result.op === 'smt.bv.repeat') {\n            const count = parser.parseInteger();\n            result.addAttribute('count', count);\n            parser.parseKeyword('times');\n            const unresolvedOperand = parser.parseOperand();\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            const inputType = parser.parseType();\n            parser.resolveOperand(unresolvedOperand, inputType, result.operands);\n            // RepeatOp::parse - result width = input width * count\n            const inputWidth = inputType instanceof _.smt.BitVectorType ? inputType.width : 0;\n            const resultWidth = inputWidth * count;\n            result.addTypes([new _.smt.BitVectorType(resultWidth)]);\n            return true;\n        }\n        if (result.op === 'smt.int.constant') {\n            const value = parser.parseInteger();\n            result.addAttribute('value', value);\n            parser.parseOptionalAttrDict(result.attributes);\n            result.addTypes([new _.Type('!smt.int')]);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseType(parser) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic === 'bv' && parser.parseOptionalLess()) {\n            const width = parser.parseInteger();\n\n            parser.parseGreater();\n            return new _.smt.BitVectorType(width);\n        }\n        if (mnemonic) {\n            let type = `!smt.${mnemonic}`;\n            type += parser.parseTypeParameters();\n            return new _.Type(type);\n        }\n        return null;\n    }\n\n    inferResultTypes(op, vars) {\n        if (op.op === 'smt.bv.concat') {\n            // ConcatOp::inferReturnTypes - result width = lhs width + rhs width\n            if (op.operands.length >= 2) {\n                const lhsType = op.operands[0].type;\n                const rhsType = op.operands[1].type;\n                const lhsWidth = lhsType instanceof _.smt.BitVectorType ? lhsType.width : 0;\n                const rhsWidth = rhsType instanceof _.smt.BitVectorType ? rhsType.width : 0;\n                const resultWidth = lhsWidth + rhsWidth;\n                op.addTypes([new _.smt.BitVectorType(resultWidth)]);\n                return;\n            }\n        }\n        super.inferResultTypes(op, vars);\n    }\n};\n\n_.MPMDDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'mpmd');\n        this.registerCustomType('mesh_tensor', this.parseMeshTensorType.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'mpmd.named_computation') {\n            return this.parseNamedComputationOp(parser, result);\n        }\n        if (result.op === 'mpmd.fragment') {\n            return this.parseFragmentOp(parser, result);\n        }\n        if (result.op === 'mpmd.fragment_call') {\n            return this.parseFragmentCallOp(parser, result);\n        }\n        if (result.op === 'mpmd.for') {\n            return this.parseForOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseNamedComputationOp(parser, result) {\n        // mpmd.named_computation<\"name\"(count)> (%inputs) (%block_args) { region } : (types) -> types\n        parser.parseLess();\n        // Parse single UserOriginAttr in short format: \"name\"(count)\n        const origin = this.parseUserOriginAttr(parser);\n        result.addAttribute('origin', origin);\n        parser.parseGreater();\n        const unresolvedInputs = parser.parseOperandList('paren');\n        const entryArguments = this.parseBlockArguments(parser);\n        parser.parseOptionalRegion(result.addRegion(), entryArguments);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            if (type instanceof _.FunctionType) {\n                parser.resolveOperands(unresolvedInputs, type.inputs, result.operands);\n                result.addTypes(type.results);\n            }\n        }\n        return true;\n    }\n\n    parseBlockArguments(parser) {\n        return parser.parseArgumentList('optionalParen', true);\n    }\n\n    parseFragmentOp(parser, result) {\n        // mpmd.fragment<mesh=\"m1\", origin=[\"f1\"], stage_id=N> (%inputs) {attrs} (%block_args) { region } : (types) -> type\n        parser.parseLess();\n        do {\n            const attrName = parser.parseKeyword();\n            parser.parseEqual();\n            // Use custom parser for origin attribute (array of UserOriginAttr)\n            const attrValue = attrName === 'origin' ? this.parseOriginArray(parser) : parser.parseAttribute();\n            result.addAttribute(attrName, attrValue);\n        } while (parser.parseOptionalComma());\n        parser.parseGreater();\n        const unresolvedInputs = parser.parseOperandList('paren');\n        parser.parseOptionalAttrDict(result.attributes);\n        const entryArguments = this.parseBlockArguments(parser);\n        parser.parseOptionalRegion(result.addRegion(), entryArguments);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            if (type instanceof _.FunctionType) {\n                parser.resolveOperands(unresolvedInputs, type.inputs, result.operands);\n                result.addTypes(type.results);\n            }\n        }\n        return true;\n    }\n\n    parseFragmentCallOp(parser, result) {\n        // mpmd.fragment_call<mesh=\"m1\", origin=[\"f1\"]> @callee(%args) {attrs} : (types) -> type\n        parser.parseLess();\n        do {\n            const attrName = parser.parseKeyword();\n            parser.parseEqual();\n            // Use custom parser for origin attribute (array of UserOriginAttr)\n            const attrValue = attrName === 'origin' ? this.parseOriginArray(parser) : parser.parseAttribute();\n            result.addAttribute(attrName, attrValue);\n        } while (parser.parseOptionalComma());\n        parser.parseGreater();\n        const callee = parser.parseOptionalSymbolName();\n\n        result.addAttribute('callee', callee);\n        const unresolvedArgs = parser.parseOperandList('paren');\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalColon()) {\n            const type = parser.parseType();\n            if (type instanceof _.FunctionType) {\n                parser.resolveOperands(unresolvedArgs, type.inputs, result.operands);\n                result.addTypes(type.results);\n            }\n        }\n        return true;\n    }\n\n    parseForOp(parser, result) {\n        // Use parseOperandList for simple operand list (no types in syntax)\n        const inputs = parser.parseOperandList('paren');\n        const types = inputs.map(() => null);\n        parser.resolveOperands(inputs, types, result.operands);\n        parser.parseOptionalAttrDict(result.attributes);\n        const entryArguments = this.parseBlockArguments(parser);\n        parser.parseOptionalRegion(result.addRegion(), entryArguments);\n        if (parser.parseOptionalColon()) {\n            const resultTypes = [];\n            do {\n                resultTypes.push(parser.parseType());\n            } while (parser.parseOptionalComma());\n            result.addTypes(resultTypes);\n        }\n        return true;\n    }\n\n    parseMeshTensorType(parser, prefix) {\n        // Parse !mpmd.mesh_tensor<\"mesh_name\", tensor<shape>, sharding=<...>>\n        parser.parseLess();\n        const meshName = parser.parseString();\n        parser.parseComma();\n        const tensorType = parser.parseType();\n        const result = { name: prefix, meshName, tensorType };\n        if (parser.parseOptionalComma()) {\n            if (parser.parseOptionalKeyword('sharding')) {\n                parser.parseEqual();\n                result.sharding = parser.parseAttribute();\n            }\n        }\n        parser.parseGreater();\n        return result;\n    }\n\n    // Parse UserOriginAttr in short format: \"name\"(count) where (count) is optional\n    parseUserOriginAttr(parser) {\n        const name = parser.parseString();\n        let transposeCount = 0;\n        if (parser.parseOptionalLParen()) {\n            const count = parser.parseInteger();\n            transposeCount = count;\n            parser.parseRParen();\n        }\n        return { name, transposeCount };\n    }\n\n    parseOriginArray(parser) {\n        const origins = [];\n        parser.parseLSquare();\n        while (!parser.parseOptionalRSquare()) {\n            const origin = this.parseUserOriginAttr(parser);\n            origins.push(origin);\n            parser.parseOptionalComma();\n        }\n        return origins;\n    }\n};\n\n_.SdyDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'sdy');\n        this.registerCustomDirective('StrippedTensorShardingPerValueAttr', this.parseStrippedTensorShardingPerValueAttr.bind(this));\n        this.registerCustomDirective('SingleBlockRegionNoBlockId', this.parseSingleBlockRegionNoBlockId.bind(this));\n        this.registerCustomAttribute('Sdy_ListOfAxisRefLists', this.parseListOfAxisRefLists.bind(this));\n        this.registerCustomAttribute('Sdy_ManualAxes', this.parseManualAxes.bind(this));\n        this.registerCustomAttribute('Sdy_AllToAllParamList', this.parseAllToAllParamList.bind(this));\n        this.registerCustomAttribute('Sdy_TensorSharding', this.parseTensorShardingAttrWrap.bind(this));\n        this.registerCustomAttribute('Sdy_AxisRefList', this.parseAxisRefListWrap.bind(this));\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'sdy.constant') {\n            return this.parseConstantOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseStrippedTensorShardingPerValueAttr(parser, op, attrName) {\n        const shardings = [];\n        parser.parseLSquare();\n        while (!parser.parseOptionalRSquare()) {\n            const sharding = this.parseTensorShardingAttr(parser);\n            shardings.push(sharding);\n            parser.parseOptionalComma();\n        }\n        if (attrName) {\n            op.addAttribute(attrName, shardings);\n        }\n        return shardings;\n    }\n\n    parseSingleBlockRegionNoBlockId(parser, op /*, args */) {\n        const entryArguments = [];\n        if (parser.parseOptionalLParen()) {\n            while (!parser.parseOptionalRParen()) {\n                const value = parser.parseOperand();\n                let type = null;\n                const attrs = [];\n                if (parser.parseOptionalColon()) {\n                    type = parser.parseType();\n                }\n                parser.parseOptionalAttrDict(attrs);\n                entryArguments.push({ value, type, attributes: attrs.length > 0 ? attrs : undefined });\n                parser.parseOptionalComma();\n            }\n        }\n        const region = op.addRegion();\n        parser.parseRegion(region, entryArguments);\n        return region;\n    }\n\n    parseTensorShardingAttr(parser) {\n        parser.parseLess();\n        let meshOrRef = null;\n        meshOrRef = parser.parseOptionalSymbolName();\n        if (meshOrRef !== null) {\n            // meshOrRef is set\n        } else if (parser.parseOptionalKeyword('mesh')) {\n            meshOrRef = this.parseMeshAttr(parser);\n        } else {\n            throw new mlir.Error(`Expected '@' or 'mesh' ${parser.getCurrentLocation()}`);\n        }\n        parser.parseComma();\n        const dimShardings = this.parseDimensionShardings(parser);\n        let replicatedAxes = null;\n        let unreducedAxes = null;\n        while (parser.parseOptionalComma()) {\n            if (parser.parseOptionalKeyword('replicated')) {\n                parser.parseEqual();\n                replicatedAxes = this.parseAxisRefList(parser);\n            } else if (parser.parseOptionalKeyword('unreduced')) {\n                parser.parseEqual();\n                unreducedAxes = this.parseAxisRefList(parser);\n            }\n        }\n        parser.parseGreater();\n        return { meshOrRef, dimShardings, replicatedAxes, unreducedAxes };\n    }\n\n    parseMeshAttr(parser) {\n        parser.parseLess();\n        const axes = [];\n        parser.parseLSquare();\n        while (!parser.parseOptionalRSquare()) {\n            const name = parser.parseString();\n            parser.parseEqual();\n            const size = parser.parseInteger();\n            axes.push({ name, size });\n            parser.parseOptionalComma();\n        }\n        let deviceIds = null;\n        if (parser.parseOptionalComma()) {\n            if (parser.parseOptionalKeyword('device_ids')) {\n                parser.parseEqual();\n                deviceIds = parser.parseAttribute().value;\n            }\n        }\n        parser.parseGreater();\n        return { axes, deviceIds };\n    }\n\n    parseDimensionShardings(parser) {\n        const dimShardings = [];\n        parser.parseLSquare();\n        while (!parser.parseOptionalRSquare()) {\n            const dimSharding = this.parseDimensionShardingAttr(parser);\n            dimShardings.push(dimSharding);\n            parser.parseOptionalComma();\n        }\n        return dimShardings;\n    }\n\n    parseDimensionShardingAttr(parser) {\n        const axes = [];\n        parser.parseLBrace();\n        let isClosed = true;\n        while (!parser.parseOptionalRBrace()) {\n            if (parser.parseOptionalQuestion()) {\n                isClosed = false;\n                parser.parseRBrace();\n                break;\n            }\n            const axis = this.parseAxisRefAttr(parser);\n            axes.push(axis);\n            if (parser.parseOptionalComma()) {\n                if (parser.parseOptionalQuestion()) {\n                    isClosed = false;\n                    parser.parseRBrace();\n                    break;\n                }\n            }\n        }\n        let priority = null;\n        const priorityStr = parser.parseOptionalKeyword();\n        if (priorityStr && /^p\\d+$/.test(priorityStr)) {\n            priority = parseInt(priorityStr.substring(1), 10);\n        }\n        return { axes, isClosed, priority };\n    }\n\n    parseAxisRefAttr(parser) {\n        const name = parser.parseString();\n        let subAxisInfo = null;\n        if (parser.parseOptionalColon()) {\n            subAxisInfo = this.parseSubAxisInfo(parser);\n        }\n        return { name, subAxisInfo };\n    }\n\n    parseSubAxisInfo(parser) {\n        parser.parseLParen();\n        const preSize = parser.parseInteger();\n        parser.parseRParen();\n        const size = parser.parseInteger();\n        return { preSize, size };\n    }\n\n    parseAxisRefList(parser) {\n        const axes = [];\n        parser.parseLBrace();\n        while (!parser.parseOptionalRBrace()) {\n            const axis = this.parseAxisRefAttr(parser);\n            axes.push(axis);\n            parser.parseOptionalComma();\n        }\n        return axes;\n    }\n\n    parseListOfAxisRefLists(parser) {\n        const lists = [];\n        parser.parseLSquare();\n        while (!parser.parseOptionalRSquare()) {\n            const list = this.parseAxisRefList(parser);\n            lists.push(list);\n            parser.parseOptionalComma();\n        }\n        return { value: lists };\n    }\n\n    parseManualAxes(parser) {\n        const axes = [];\n        parser.parseLBrace();\n        while (!parser.parseOptionalRBrace()) {\n            const axis = parser.parseString();\n            axes.push(axis);\n            parser.parseOptionalComma();\n        }\n        return { value: axes };\n    }\n\n    parseAllToAllParamList(parser) {\n        const params = [];\n        parser.parseLSquare();\n        while (!parser.parseOptionalRSquare()) {\n            const param = this.parseAllToAllParam(parser);\n            params.push(param);\n            parser.parseOptionalComma();\n        }\n        return { value: params };\n    }\n\n    parseAllToAllParam(parser) {\n        const axes = this.parseAxisRefList(parser);\n        parser.parseColon();\n        const splitDim = parser.parseInteger();\n        parser.parseArrow();\n        const concatDim = parser.parseInteger();\n        return { axes, splitDim, concatDim };\n    }\n\n    parseTensorShardingAttrWrap(parser) {\n        return { value: this.parseTensorShardingAttr(parser) };\n    }\n\n    parseAxisRefListWrap(parser) {\n        return { value: this.parseAxisRefList(parser) };\n    }\n\n    parseConstantOp(parser, result) {\n        parser.parseOptionalAttrDict(result.attributes);\n        const attr = parser.parseAttribute();\n        result.addAttribute('value', attr.value || attr);\n        if (attr.type) {\n            if (result.types.length === 0) {\n                result.addTypes([attr.type]);\n            } else {\n                result.types[0] = attr.type;\n            }\n        }\n        return true;\n    }\n};\n\n_.XlaDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xla');\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'xla.apply_indexing') {\n            const indexingMapAttr = parser.parseAttribute();\n            result.addAttribute('indexing_map_attr', indexingMapAttr);\n            const operands = [];\n            if (parser.parseOptionalLParen()) {\n                parser.parseOperands(operands);\n                parser.parseRParen();\n            }\n            if (parser.parseOptionalLSquare()) {\n                parser.parseOperands(operands);\n                parser.parseRSquare();\n            }\n            const indexType = new _.IndexType();\n            for (const operand of operands) {\n                parser.resolveOperand(operand, indexType, result.operands);\n            }\n            parser.parseOptionalAttrDict(result.attributes);\n            const map = indexingMapAttr.getIndexingMap().GetAffineMap();\n            const numResults = map.getNumResults();\n            for (let i = 0; i < numResults; i++) {\n                result.addTypes([indexType]);\n            }\n            return true;\n        }\n        // xla.loop (%dims)[%ivs] -> (%map_results) in #map iter_args(%args = %inits) -> (types) { body }\n        if (result.op === 'xla.loop') {\n            const unresolvedDims = [];\n            const unresolvedInits = [];\n            const regionArgs = [];\n            const indexType = new _.IndexType();\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const __dimOp = parser.parseOptionalOperand();\n                        if (__dimOp) {\n                            unresolvedDims.push(__dimOp);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            // Parse [%ivs] -> (%map_results) - these are block arguments\n            if (parser.parseOptionalLSquare()) {\n                if (!parser.parseOptionalRSquare()) {\n                    do {\n                        const __iv = parser.parseOptionalOperand();\n                        if (__iv) {\n                            regionArgs.push({ name: __iv.name, type: indexType });\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRSquare();\n                }\n            }\n            if (parser.parseOptionalArrow()) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const __mapResult = parser.parseOptionalOperand();\n                        if (__mapResult) {\n                            regionArgs.push({ name: __mapResult.name, type: indexType });\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            parser.parseKeyword('in');\n            const map = parser.parseAttribute();\n            result.addAttribute('indexing_map_attr', map);\n            const iterArgNames = [];\n            if (parser.parseOptionalKeyword('iter_args')) {\n                parser.parseLParen();\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const __iterArg = parser.parseOptionalOperand();\n                        if (__iterArg) {\n                            iterArgNames.push(__iterArg.name);\n                        }\n                        if (parser.parseOptionalEqual()) {\n                            unresolvedInits.push(parser.parseOperand());\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            const resultTypes = [];\n            if (parser.parseOptionalArrow()) {\n                if (parser.parseOptionalLParen()) {\n                    const types = parser.parseTypeList();\n                    parser.parseRParen();\n                    for (const t of types) {\n                        result.addTypes([t]);\n                        resultTypes.push(t);\n                    }\n                } else {\n                    const type = parser.parseType();\n                    result.addTypes([type]);\n                    resultTypes.push(type);\n                }\n            }\n            for (let i = 0; i < iterArgNames.length; i++) {\n                const argType = resultTypes[i] || null;\n                regionArgs.push({ name: iterArgNames[i], type: argType });\n            }\n            for (const dim of unresolvedDims) {\n                parser.resolveOperand(dim, indexType, result.operands);\n            }\n            for (let i = 0; i < unresolvedInits.length; i++) {\n                const initType = resultTypes[i] || null;\n                parser.resolveOperand(unresolvedInits[i], initType, result.operands);\n            }\n            parser.parseOptionalRegion(result.addRegion(), regionArgs);\n            parser.parseOptionalAttrDict(result.attributes);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    parseAttribute(parser, type) {\n        const keyword = parser.parseOptionalKeyword();\n        if (keyword === 'indexing_map') {\n            return _.IndexingMapAttr.parse(parser, type);\n        }\n        return null;\n    }\n};\n\n_.XlaGpuDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xla_gpu');\n    }\n\n    parseOperation(parser, result) {\n        // xla_gpu.shuffle_reduce(%ops) to N combiner=@func {attrs} : types\n        if (result.op === 'xla_gpu.shuffle_reduce') {\n            const unresolvedOperands = [];\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const __srOp = parser.parseOptionalOperand();\n                        if (__srOp) {\n                            unresolvedOperands.push(__srOp);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            parser.parseKeyword('to');\n            const maxDistance = parser.parseInteger();\n\n            result.addAttribute('max_distance', parseInt(maxDistance, 10));\n            parser.parseKeyword('combiner');\n            parser.parseEqual();\n            const combiner = parser.parseOptionalSymbolName();\n\n            result.addAttribute('combiner', new _.SymbolRefAttr(`@${combiner}`));\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const types = parser.parseTypeList();\n                parser.resolveOperands(unresolvedOperands, types, result.operands);\n                result.addTypes(types);\n            } else {\n                for (const operand of unresolvedOperands) {\n                    parser.resolveOperand(operand, null, result.operands);\n                }\n            }\n            return true;\n        }\n        // xla_gpu.reduce (%inputs) inits(%inits) dimensions=[...] combiner=@func {attrs} : in_types to out_types\n        if (result.op === 'xla_gpu.reduce') {\n            const unresolvedInputs = [];\n            const unresolvedInits = [];\n            if (parser.parseOptionalLParen()) {\n                if (!parser.parseOptionalRParen()) {\n                    do {\n                        const __inp = parser.parseOptionalOperand();\n                        if (__inp) {\n                            unresolvedInputs.push(__inp);\n                        }\n                    } while (parser.parseOptionalComma());\n                    parser.parseRParen();\n                }\n            }\n            parser.parseKeyword('inits');\n            parser.parseLParen();\n            if (!parser.parseOptionalRParen()) {\n                do {\n                    const __initOp = parser.parseOptionalOperand();\n                    if (__initOp) {\n                        unresolvedInits.push(__initOp);\n                    }\n                } while (parser.parseOptionalComma());\n                parser.parseRParen();\n            }\n            parser.parseKeyword('dimensions');\n            parser.parseEqual();\n            const dimensions = parser.parseAttribute();\n            result.addAttribute('dimensions', dimensions);\n            parser.parseKeyword('combiner');\n            parser.parseEqual();\n            const combiner = parser.parseOptionalSymbolName();\n\n            result.addAttribute('combiner', new _.SymbolRefAttr(`@${combiner}`));\n            parser.parseOptionalAttrDict(result.attributes);\n            if (parser.parseOptionalColon()) {\n                const inputTypes = parser.parseTypeList();\n                parser.resolveOperands(unresolvedInputs, inputTypes, result.operands);\n                parser.parseKeyword('to');\n                const outputTypes = parser.parseTypeList();\n                result.addTypes(outputTypes);\n                parser.resolveOperands(unresolvedInits, outputTypes, result.operands);\n            } else {\n                for (const input of unresolvedInputs) {\n                    parser.resolveOperand(input, null, result.operands);\n                }\n                for (const init of unresolvedInits) {\n                    parser.resolveOperand(init, null, result.operands);\n                }\n            }\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.XTileLayoutAttr = class extends _.MemRefLayoutAttr {\n\n    constructor(minorToMajor) {\n        super();\n        this.minorToMajor = minorToMajor;\n    }\n\n    toString() {\n        return `#xtile.layout<[${this.minorToMajor.join(', ')}]>`;\n    }\n};\n\n_.XTileDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xtile');\n    }\n\n    parseAttribute(parser) {\n        const keyword = parser.parseOptionalKeyword();\n        if (keyword === 'layout') {\n            parser.parseLess();\n            parser.parseLSquare();\n            const values = [];\n            if (!parser.parseOptionalRSquare()) {\n                do {\n                    values.push(parser.parseInteger());\n                } while (parser.parseOptionalComma());\n                parser.parseRSquare();\n            }\n            parser.parseGreater();\n            return new _.XTileLayoutAttr(values);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        // xtile.entry_func - function-like op with custom format\n        if (result.op === 'xtile.entry_func') {\n            parser.parseFunctionOp(result, false);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n};\n\n_.triton.xla.TritonXlaDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'triton_xla');\n        // Mark operations with custom directives as having custom assembly format\n        this.registerOperandName('triton_xla.extract', { name: 'triton_xla.extract', hasCustomAssemblyFormat: true });\n        this.registerOperandName('triton_xla.insert', { name: 'triton_xla.insert', hasCustomAssemblyFormat: true });\n    }\n\n    parseOperation(parser, result) {\n        // triton_xla.extract from $src as memref<shape, layout> [offsets] [sizes] [strides] : result_type\n        if (result.op === 'triton_xla.extract') {\n            parser.parseKeyword('from');\n            const unresolvedSrc = parser.parseOperand();\n            parser.parseKeyword('as');\n            // Parse AsMemRefType: memref<shape, layout> - the memref type describes the pointer's layout\n            const memrefType = parser.parseType();\n            // Extract shape and layout from the memref type\n            this._extractMemRefInfo(memrefType, result, 'src_shape', 'src_layout');\n            this.parseDynamicIndexList(parser, result, 'offsets', 'static_offsets');\n            this.parseDynamicIndexList(parser, result, 'sizes', 'static_sizes');\n            this.parseDynamicIndexList(parser, result, 'strides', 'static_strides');\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            const resultType = parser.parseType();\n            parser.resolveOperand(unresolvedSrc, memrefType, result.operands);\n            result.addTypes([resultType]);\n            return true;\n        }\n        // triton_xla.insert $src into $dst as memref<shape, layout> [offsets] [sizes] [strides] : src_type\n        if (result.op === 'triton_xla.insert') {\n            const unresolvedSrc = parser.parseOperand();\n            parser.parseKeyword('into');\n            const unresolvedDst = parser.parseOperand();\n            parser.parseKeyword('as');\n            // Parse AsMemRefType: memref<shape, layout> - the memref type describes the pointer's layout\n            const memrefType = parser.parseType();\n            // Extract shape and layout from the memref type\n            this._extractMemRefInfo(memrefType, result, 'dst_shape', 'dst_layout');\n            this.parseDynamicIndexList(parser, result, 'offsets', 'static_offsets');\n            this.parseDynamicIndexList(parser, result, 'sizes', 'static_sizes');\n            this.parseDynamicIndexList(parser, result, 'strides', 'static_strides');\n            parser.parseOptionalAttrDict(result.attributes);\n            parser.parseColon();\n            const srcType = parser.parseType();\n            parser.resolveOperand(unresolvedSrc, srcType, result.operands);\n            parser.resolveOperand(unresolvedDst, memrefType, result.operands);\n            return true;\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    _extractMemRefInfo(memrefType, op, shapeAttrName, layoutAttrName) {\n        op.addAttribute(shapeAttrName, memrefType.shape.map((d) => Number(d)));\n        if (!(memrefType.layout instanceof _.XTileLayoutAttr)) {\n            throw new mlir.Error('Expected layout attribute');\n        }\n        op.addAttribute(layoutAttrName, memrefType.layout.minorToMajor.map((d) => Number(d)));\n    }\n\n    parseDynamicIndexList(parser, op, dynamicName, staticName) {\n        // Parse [val1, val2, ...] where vals can be %ssa or integer constants\n        parser.parseLSquare();\n        const staticValues = [];\n        if (!parser.parseOptionalRSquare()) {\n            do {\n                const __dynUnresolved = parser.parseOptionalOperand();\n                if (__dynUnresolved) {\n                    parser.resolveOperand(__dynUnresolved, null, op.operands);\n                    staticValues.push(-9223372036854775808n); // ShapedType::kDynamic\n                } else {\n                    const __dynIntVal = parser.parseOptionalInteger('int64');\n                    if (__dynIntVal !== null) {\n                        staticValues.push(__dynIntVal);\n                    }\n                }\n            } while (parser.parseOptionalComma());\n            parser.parseRSquare();\n        }\n        op.addAttribute(staticName, staticValues);\n    }\n};\n\n_.EnsembleDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'ensemble');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            const type = `!${dialect}.${mnemonic}`;\n            const simpleTypes = ['physical_qubit', 'virtual_qubit', 'cbit', 'gate', 'gate_distribution', 'connectivity_graph'];\n            if (simpleTypes.includes(mnemonic)) {\n                return new _.Type(type);\n            }\n        }\n        return null;\n    }\n};\n\n_.PolyDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'poly');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            let type = `!${dialect}.${mnemonic}`;\n            // poly.poly<N> type has a degree bound parameter\n            if (mnemonic === 'poly') {\n                type += parser.parseTypeParameters();\n            }\n            return new _.Type(type);\n        }\n        return null;\n    }\n};\n\n_.NoisyDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'noisy');\n    }\n\n    parseType(parser, dialect) {\n        const mnemonic = parser.parseOptionalKeyword();\n        if (mnemonic) {\n            return new _.Type(`!${dialect}.${mnemonic}`);\n        }\n        return null;\n    }\n};\n\n_.XtenNNDialect = class extends _.Dialect {\n\n    constructor(operations) {\n        super(operations, 'xten_nn');\n    }\n\n    parseAttribute(parser) {\n        const keyword = parser.parseOptionalKeyword();\n        if (keyword === 'dict_loc') {\n            parser.parseLParen();\n            const attrs = parser.parseAttribute();\n            parser.parseRParen();\n            return new _.XtenNNDictLoc(attrs);\n        }\n        return null;\n    }\n\n    parseOperation(parser, result) {\n        if (result.op === 'xten_nn.subgraph') {\n            return this.parseSubgraphOp(parser, result);\n        }\n        if (result.op === 'xten_nn.quantize' || result.op === 'xten_nn.dequantize') {\n            return this.parseQuantizeOp(parser, result);\n        }\n        if (result.op === 'xten_nn.kernel') {\n            return this.parseKernelOp(parser, result);\n        }\n        return super.parseOperation(parser, result);\n    }\n\n    // Parse: (%name = %value : type, ...) { body } -> result_types\n    // or: (%arg : type, ...) -> result_types (no body)\n    parseSubgraphOp(parser, result) {\n        const entryArgs = [];\n        if (parser.parseOptionalLParen()) {\n            while (!parser.parseOptionalRParen()) {\n                // Parse either (%name = %value : type) or (%value : type)\n                let blockArgName = null;\n                let operandRef = null;\n                const __firstOp = parser.parseOptionalOperand();\n                if (__firstOp) {\n                    if (parser.parseOptionalEqual()) {\n                        // (%name = %value : type) form\n                        blockArgName = __firstOp;\n                        operandRef = parser.parseOptionalOperand();\n                    } else {\n                        // (%value : type) form - value is both operand and block arg name\n                        operandRef = __firstOp;\n                        blockArgName = __firstOp;\n                    }\n                }\n                parser.parseColon();\n                const type = parser.parseType();\n                if (operandRef) {\n                    parser.resolveOperands([operandRef], [type], result.operands);\n                }\n                entryArgs.push({ value: blockArgName, type });\n                if (!parser.parseOptionalComma()) {\n                    parser.parseOptionalRParen();\n                    break;\n                }\n            }\n        }\n        parser.parseOptionalAttrDictWithKeyword(result.attributes);\n        parser.parseOptionalRegion(result.addRegion(), entryArgs, /* enableNameShadowing */ true);\n        if (parser.parseOptionalArrow()) {\n            result.addTypes(parser.parseTypeList());\n        }\n        return true;\n    }\n\n    // Parse: (%input: type) {attrs} -> type\n    parseQuantizeOp(parser, result) {\n        if (!parser.parseOptionalLParen()) {\n            return false;\n        }\n        const unresolvedOperands = [];\n        while (!parser.parseOptionalRParen()) {\n            const __qOp = parser.parseOptionalOperand();\n            if (__qOp) {\n                unresolvedOperands.push(__qOp);\n            }\n            parser.parseColon();\n            const type = parser.parseType();\n            parser.resolveOperands(unresolvedOperands, [type], result.operands);\n            unresolvedOperands.length = 0;\n            if (!parser.parseOptionalComma()) {\n                parser.parseOptionalRParen();\n                break;\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        result.addTypes(parser.parseArrowTypeList());\n        return true;\n    }\n\n    // Parse: \"name\" (%arg : type, ...) instantiation_args [...] {attrs} -> result_types\n    parseKernelOp(parser, result) {\n        const nameAttr = parser.parseAttribute();\n        result.addAttribute('name', nameAttr);\n        if (parser.parseOptionalLParen()) {\n            const unresolvedOperands = [];\n            const types = [];\n            while (!parser.parseOptionalRParen()) {\n                const __kOp = parser.parseOptionalOperand();\n                if (__kOp) {\n                    unresolvedOperands.push(__kOp);\n                }\n                parser.parseColon();\n                types.push(parser.parseType());\n                if (!parser.parseOptionalComma()) {\n                    parser.parseOptionalRParen();\n                    break;\n                }\n            }\n            parser.resolveOperands(unresolvedOperands, types, result.operands);\n        }\n        if (parser.parseOptionalKeyword('instantiation_args')) {\n            const values = [];\n            const names = [];\n            this.parseKernelInstantiationArgs(parser, values, names);\n            result.addAttribute('instantiation_args', new _.ArrayAttr(values));\n            if (names.length > 0) {\n                result.addAttribute('instantiation_arg_names', new _.ArrayAttr(names));\n            }\n        }\n        parser.parseOptionalAttrDict(result.attributes);\n        if (parser.parseOptionalArrow()) {\n            result.addTypes(parser.parseTypeList());\n        }\n        return true;\n    }\n\n    parseKernelInstantiationArgs(parser, values, names) {\n        if (!parser.parseOptionalLSquare()) {\n            return;\n        }\n        while (!parser.parseOptionalRSquare()) {\n            const attr = parser.parseAttribute();\n            if (parser.parseOptionalEqual()) {\n                names.push(attr);\n                values.push(parser.parseAttribute());\n            } else {\n                values.push(attr);\n            }\n            parser.parseOptionalComma();\n        }\n    }\n};\n\nmlir.Metadata = class {\n\n    static async open(context) {\n        if (!mlir.Metadata._metadata) {\n            const data = await context.request('mlir-metadata.json');\n            mlir.Metadata._metadata = new mlir.Metadata(data);\n        }\n        return mlir.Metadata._metadata;\n    }\n\n    constructor(data) {\n        this.operations = new Map();\n        if (data) {\n            const operations = JSON.parse(data);\n            for (const op of operations) {\n                const [dialectName] = op.name.split('.');\n                if (!this.operations.has(dialectName)) {\n                    this.operations.set(dialectName, []);\n                }\n                this.operations.get(dialectName).push(op);\n            }\n        }\n    }\n\n    type(name) {\n        const [dialectName] = name.split('.');\n        const operations = this.operations.get(dialectName);\n        if (operations) {\n            const op = operations.find((op) => op.name === name);\n            if (op) {\n                return op;\n            }\n        }\n        return { name };\n    }\n};\n\nmlir.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading MLIR model.';\n    }\n};\n\nexport const ModelFactory = mlir.ModelFactory;\n"
  },
  {
    "path": "source/mlnet-metadata.json",
    "content": "[\n  {\n    \"name\": \"CharToken\",\n    \"description\": \"Character-oriented tokenizer where text is considered a sequence of characters.\",\n    \"attributes\": [\n      {\n        \"name\": \"UseMarkerChars\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"name\": \"IsSeparatorStartEnd\",\n        \"type\": \"boolean\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ConcatTransform\",\n    \"category\": \"Tensor\",\n    \"description\": \"Concatenates one or more columns of the same item type.\"\n  },\n  {\n    \"name\": \"CopyTransform\",\n    \"category\": \"Tensor\",\n    \"description\": \"Duplicates columns from the dataset.\"\n  },\n  {\n    \"name\": \"ImageLoaderTransform\",\n    \"description\": \"Load images from files.\",\n    \"attributes\": [\n      {\n        \"name\": \"ImageFolder\",\n        \"type\": \"string\",\n        \"description\": \"Folder where to search for images\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ImagePixelExtractor\",\n    \"description\": \"Scales an image to specified dimensions using one of the three scale types: isotropic with padding, isotropic with cropping or anisotropic. In case of isotropic padding, transparent color is used to pad resulting image.\",\n    \"attributes\": [\n      {\n        \"name\": \"ColorsToExtract\",\n        \"type\": \"ImagePixelExtractingTransformer.ColorBits\"\n      },\n      {\n        \"name\": \"OrderOfExtraction\",\n        \"type\": \"ImagePixelExtractingTransformer.ColorsOrder\"\n      },\n      {\n        \"name\": \"Planes\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"name\": \"OutputAsFloatArray\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"name\": \"OffsetImage\",\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"ScaleImage\",\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"InterleavePixelColors\",\n        \"type\": \"boolean\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ImageScalerTransform\",\n    \"description\": \"Scales an image to specified dimensions using one of the three scale types: isotropic with padding, isotropic with cropping or anisotropic. In case of isotropic padding, transparent color is used to pad resulting image.\",\n    \"attributes\": [\n      {\n        \"name\": \"Width\"\n      },\n      {\n        \"name\": \"Height\"\n      },\n      {\n        \"name\": \"Resizing\",\n        \"type\": \"ImageResizingTransformer.ResizingKind\"\n      },\n      {\n        \"name\": \"Anchor\",\n        \"type\": \"ImageResizingTransformer.Anchor\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SSAModel\",\n    \"attributes\": [\n      {\n        \"name\": \"UseMarkerChars\",\n        \"type\": \"boolean\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TensorFlowTransform\",\n    \"description\": \"Transforms the data using the TensorFlow model.\",\n    \"attributes\": [\n      {\n        \"name\": \"IsFrozen\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"name\": \"AddBatchDimensionInput\",\n        \"type\": \"boolean\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TextNormalizerTransform\",\n    \"description\": \"A text normalization transform that allows normalizing text case, removing diacritical marks, punctuation marks and/or numbers. The transform operates on text input as well as vector of tokens/text (vector of ReadOnlyMemory).\",\n    \"attributes\": [\n      {\n        \"name\": \"CaseMode\",\n        \"type\": \"TextNormalizingTransformer.CaseMode\"\n      },\n      {\n        \"name\": \"KeepDiacritics\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"name\": \"KeepPunctuations\",\n        \"type\": \"boolean\"\n      },\n      {\n        \"name\": \"KeepNumbers\",\n        \"type\": \"boolean\"\n      }\n    ]\n  }\n]"
  },
  {
    "path": "source/mlnet.js",
    "content": "\n// Experimental\n\nimport * as base from './base.js';\n\nconst mlnet = {};\n\nmlnet.ModelFactory = class {\n\n    async match(context) {\n        const entries = await context.peek('zip');\n        if (entries instanceof Map && entries.size > 0) {\n            const root = new Set(['TransformerChain', 'Predictor']);\n            if (Array.from(entries.keys()).some((name) => root.has(name.split('\\\\').shift().split('/').shift()))) {\n                return context.set('mlnet', entries);\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('mlnet-metadata.json');\n        const reader = new mlnet.ModelReader(context.value);\n        await reader.resolve(context);\n        return new mlnet.Model(metadata, reader);\n    }\n};\n\nmlnet.Model = class {\n\n    constructor(metadata, reader) {\n        this.format = \"ML.NET\";\n        if (reader.version && reader.version.length > 0) {\n            this.format += ` v${reader.version}`;\n        }\n        this.modules = [new mlnet.Module(metadata, reader)];\n    }\n};\n\nmlnet.Module = class {\n\n    constructor(metadata, reader) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        this.groups = false;\n        const values = new Map();\n        values.map = (name, type) => {\n            if (!values.has(name)) {\n                values.set(name, new mlnet.Value(name, type || null));\n            } else if (type) {\n                throw new mlnet.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        if (reader.schema && reader.schema.inputs) {\n            for (const input of reader.schema.inputs) {\n                const argument = new mlnet.Argument(input.name, [values.map(input.name, new mlnet.TensorType(input.type))]);\n                this.inputs.push(argument);\n            }\n        }\n        const createNode = (scope, group, transformer) => {\n            if (transformer.inputs && transformer.outputs) {\n                for (const input of transformer.inputs) {\n                    input.name = scope[input.name] ? scope[input.name].argument : input.name;\n                }\n                for (const output of transformer.outputs) {\n                    if (scope[output.name]) {\n                        scope[output.name].counter++;\n                        const next = `${output.name}\\n${scope[output.name].counter}`; // custom argument id\n                        scope[output.name].argument = next;\n                        output.name = next;\n                    } else {\n                        scope[output.name] = {\n                            argument: output.name,\n                            counter: 0\n                        };\n                    }\n                }\n            }\n            const node = new mlnet.Node(metadata, transformer, group, values);\n            this.nodes.push(node);\n        };\n        /* eslint-disable no-use-before-define */\n        const loadChain = (scope, name, chain) => {\n            this.groups = true;\n            const group = name.split('/').splice(1).join('/');\n            for (const childTransformer of chain) {\n                loadTransformer(scope, group, childTransformer);\n            }\n        };\n        const loadTransformer = (scope, group, transformer) => {\n            switch (transformer.__type__) {\n                case 'TransformerChain':\n                case 'Text':\n                    loadChain(scope, transformer.__name__, transformer.chain);\n                    break;\n                default:\n                    createNode(scope, group, transformer);\n                    break;\n            }\n        };\n        const scope = new Map();\n        if (reader.schema && reader.schema.inputs) {\n            for (const input of reader.schema.inputs) {\n                scope[input.name] = { argument: input.name, counter: 0 };\n            }\n        }\n        if (reader.dataLoaderModel) {\n            loadTransformer(scope, '', reader.dataLoaderModel);\n        }\n        if (reader.predictor) {\n            loadTransformer(scope, '', reader.predictor);\n        }\n        if (reader.transformerChain) {\n            loadTransformer(scope, '', reader.transformerChain);\n        }\n    }\n};\n\nmlnet.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nmlnet.Value = class {\n\n    constructor(name, type) {\n        if (typeof name !== 'string') {\n            throw new mlnet.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = type;\n        this.initializer = null;\n    }\n};\n\nmlnet.Node = class {\n\n    constructor(metadata, obj, group, values) {\n        const op = obj.__type__;\n        this.type = metadata.type(op) || { name: op || '?' };\n        this.name = obj.__name__ || '';\n        this.group = group || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        if (values && obj.inputs) {\n            for (let i = 0; i < obj.inputs.length; i++) {\n                const value = values.map(obj.inputs[i].name);\n                this.inputs.push(new mlnet.Argument(i.toString(), [value]));\n            }\n        }\n        if (values && obj.outputs) {\n            for (let i = 0; i < obj.outputs.length; i++) {\n                this.outputs.push(new mlnet.Argument(i.toString(), [values.map(obj.outputs[i].name)]));\n            }\n        }\n        for (const [name, raw] of Object.entries(obj).filter(([key]) => !key.startsWith('_') && key !== 'inputs' && key !== 'outputs')) {\n            const schema = metadata.attribute(op, name);\n            let value = raw;\n            let type = null;\n            if (schema) {\n                type = schema.type ? schema.type : null;\n                value = mlnet.Utility.enum(type, value);\n            }\n            if (value && typeof value === 'object' && !Array.isArray(value) && Array.isArray(value.nodes)) {\n                type = 'graph';\n            } else if (value && typeof value === 'object' && !Array.isArray(value) && value.__type__) {\n                value = new mlnet.Node(metadata, value);\n                type = 'object';\n            } else if (Array.isArray(value) && value.length > 0 && value.every((item) => item && item.__type__)) {\n                value = value.map((item) => new mlnet.Node(metadata, item));\n                type = 'object[]';\n            }\n            this.attributes.push(new mlnet.Argument(name, value, type));\n        }\n    }\n};\n\nmlnet.TensorType = class {\n\n    constructor(codec) {\n        mlnet.TensorType._map = mlnet.TensorType._map || new Map([\n            ['Byte', 'uint8'],\n            ['Boolean', 'boolean'],\n            ['Single', 'float32'],\n            ['Double', 'float64'],\n            ['UInt32', 'uint32'],\n            ['Int32', 'int32'],\n            ['Int64', 'int64'],\n            ['TextSpan', 'string']\n        ]);\n        this.dataType = '?';\n        this.shape = new mlnet.TensorShape(null);\n        if (mlnet.TensorType._map.has(codec.name)) {\n            this.dataType = mlnet.TensorType._map.get(codec.name);\n        } else if (codec.name === 'VBuffer') {\n            if (mlnet.TensorType._map.has(codec.itemType.name)) {\n                this.dataType = mlnet.TensorType._map.get(codec.itemType.name);\n            } else {\n                throw new mlnet.Error(`Unsupported data type '${codec.itemType.name}'.`);\n            }\n            this.shape = new mlnet.TensorShape(codec.dims);\n        } else if (codec.name === 'Key2') {\n            this.dataType = 'key2';\n        } else {\n            throw new mlnet.Error(`Unsupported data type '${codec.name}'.`);\n        }\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmlnet.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.join(',')}]`;\n    }\n};\n\nmlnet.ModelReader = class {\n\n    constructor(entries) {\n        const catalog = new mlnet.ComponentCatalog();\n        catalog.register('AffineNormExec', mlnet.AffineNormSerializationUtils);\n        catalog.register('AnomalyPredXfer', mlnet.AnomalyPredictionTransformer);\n        catalog.register('BinaryPredXfer', mlnet.BinaryPredictionTransformer);\n        catalog.register('BinaryLoader', mlnet.BinaryLoader);\n        catalog.register('CaliPredExec', mlnet.CalibratedPredictor);\n        catalog.register('CdfNormalizeFunction', mlnet.CdfColumnFunction);\n        catalog.register('CharToken', mlnet.TokenizingByCharactersTransformer);\n        catalog.register('ChooseColumnsTransform', mlnet.ColumnSelectingTransformer);\n        catalog.register('ClusteringPredXfer', mlnet.ClusteringPredictionTransformer);\n        catalog.register('ConcatTransform', mlnet.ColumnConcatenatingTransformer);\n        catalog.register('CopyTransform', mlnet.ColumnCopyingTransformer);\n        catalog.register('ConvertTransform', mlnet.TypeConvertingTransformer);\n        catalog.register('CSharpTransform', mlnet.CSharpTransform);\n        catalog.register('DropColumnsTransform', mlnet.DropColumnsTransform);\n        catalog.register('FAFMPredXfer', mlnet.FieldAwareFactorizationMachinePredictionTransformer);\n        catalog.register('FastForestBinaryExec', mlnet.FastForestClassificationPredictor);\n        catalog.register('FastTreeBinaryExec', mlnet.FastTreeBinaryModelParameters);\n        catalog.register('FastTreeTweedieExec', mlnet.FastTreeTweedieModelParameters);\n        catalog.register('FastTreeRankerExec', mlnet.FastTreeRankingModelParameters);\n        catalog.register('FastTreeRegressionExec', mlnet.FastTreeRegressionModelParameters);\n        catalog.register('FeatWCaliPredExec', mlnet.FeatureWeightsCalibratedModelParameters);\n        catalog.register('FieldAwareFactMacPredict', mlnet.FieldAwareFactorizationMachineModelParameters);\n        catalog.register('GcnTransform', mlnet.LpNormNormalizingTransformer);\n        catalog.register('GenericScoreTransform', mlnet.GenericScoreTransform);\n        catalog.register('IidChangePointDetector', mlnet.IidChangePointDetector);\n        catalog.register('IidSpikeDetector', mlnet.IidSpikeDetector);\n        catalog.register('ImageClassificationTrans', mlnet.ImageClassificationTransformer);\n        catalog.register('ImageClassificationPred', mlnet.ImageClassificationModelParameters);\n        catalog.register('ImageLoaderTransform', mlnet.ImageLoadingTransformer);\n        catalog.register('ImageScalerTransform', mlnet.ImageResizingTransformer);\n        catalog.register('ImagePixelExtractor', mlnet.ImagePixelExtractingTransformer);\n        catalog.register('KeyToValueTransform', mlnet.KeyToValueMappingTransformer);\n        catalog.register('KeyToVectorTransform', mlnet.KeyToVectorMappingTransformer);\n        catalog.register('KMeansPredictor', mlnet.KMeansModelParameters);\n        catalog.register('LinearRegressionExec', mlnet.LinearRegressionModelParameters);\n        catalog.register('LightGBMRegressionExec', mlnet.LightGbmRegressionModelParameters);\n        catalog.register('LightGBMBinaryExec', mlnet.LightGbmBinaryModelParameters);\n        catalog.register('Linear2CExec', mlnet.LinearBinaryModelParameters);\n        catalog.register('LinearModelStats', mlnet.LinearModelParameterStatistics);\n        catalog.register('MaFactPredXf', mlnet.MatrixFactorizationPredictionTransformer);\n        catalog.register('MFPredictor', mlnet.MatrixFactorizationModelParameters);\n        catalog.register('MulticlassLinear', mlnet.LinearMulticlassModelParameters);\n        catalog.register('MultiClassLRExec', mlnet.MaximumEntropyModelParameters);\n        catalog.register('MultiClassNaiveBayesPred', mlnet.NaiveBayesMulticlassModelParameters);\n        catalog.register('MultiClassNetPredictor', mlnet.MultiClassNetPredictor);\n        catalog.register('MulticlassPredXfer', mlnet.MulticlassPredictionTransformer);\n        catalog.register('NAReplaceTransform', mlnet.MissingValueReplacingTransformer);\n        catalog.register('NgramTransform', mlnet.NgramExtractingTransformer);\n        catalog.register('NgramHashTransform', mlnet.NgramHashingTransformer);\n        catalog.register('NltTokenizeTransform', mlnet.NltTokenizeTransform);\n        catalog.register('Normalizer', mlnet.NormalizingTransformer);\n        catalog.register('NormalizeTransform', mlnet.NormalizeTransform);\n        catalog.register('OnnxTransform', mlnet.OnnxTransformer);\n        catalog.register('OptColTransform', mlnet.OptionalColumnTransform);\n        catalog.register('OVAExec', mlnet.OneVersusAllModelParameters);\n        catalog.register('pcaAnomExec', mlnet.PcaModelParameters);\n        catalog.register('PcaTransform', mlnet.PrincipalComponentAnalysisTransformer);\n        catalog.register('PipeDataLoader', mlnet.CompositeDataLoader);\n        catalog.register('PlattCaliExec', mlnet.PlattCalibrator);\n        catalog.register('PMixCaliPredExec', mlnet.ParameterMixingCalibratedModelParameters);\n        catalog.register('PoissonRegressionExec', mlnet.PoissonRegressionModelParameters);\n        catalog.register('ProtonNNMCPred', mlnet.ProtonNNMCPred);\n        catalog.register('RegressionPredXfer', mlnet.RegressionPredictionTransformer);\n        catalog.register('RowToRowMapper', mlnet.RowToRowMapperTransform);\n        catalog.register('SsaForecasting', mlnet.SsaForecastingTransformer);\n        catalog.register('SSAModel', mlnet.AdaptiveSingularSpectrumSequenceModelerInternal);\n        catalog.register('SelectColumnsTransform', mlnet.ColumnSelectingTransformer);\n        catalog.register('StopWordsTransform', mlnet.StopWordsTransform);\n        catalog.register('TensorFlowTransform', mlnet.TensorFlowTransformer);\n        catalog.register('TermLookupTransform', mlnet.ValueMappingTransformer);\n        catalog.register('TermTransform', mlnet.ValueToKeyMappingTransformer);\n        catalog.register('TermManager', mlnet.TermManager);\n        catalog.register('Text', mlnet.TextFeaturizingEstimator);\n        catalog.register('TextLoader', mlnet.TextLoader);\n        catalog.register('TextNormalizerTransform', mlnet.TextNormalizingTransformer);\n        catalog.register('TokenizeTextTransform', mlnet.WordTokenizingTransformer);\n        catalog.register('TransformerChain', mlnet.TransformerChain);\n        catalog.register('ValueMappingTransformer', mlnet.ValueMappingTransformer);\n        catalog.register('XGBoostMulticlass', mlnet.XGBoostMulticlass);\n        this._resolve = [];\n        const root = new mlnet.ModelHeader(catalog, entries, '', null, this._resolve);\n        const version = root.openText('TrainingInfo/Version.txt');\n        if (version) {\n            [this.version] = version.split(/[\\s+\\r]+/);\n        }\n        const schemaReader = root.openBinary('Schema');\n        if (schemaReader) {\n            this.schema = new mlnet.BinaryLoader(null, schemaReader).schema;\n        }\n        const transformerChain = root.open('TransformerChain');\n        if (transformerChain) {\n            this.transformerChain = transformerChain;\n        }\n        const dataLoaderModel = root.open('DataLoaderModel');\n        if (dataLoaderModel) {\n            this.dataLoaderModel = dataLoaderModel;\n        }\n        const predictor = root.open('Predictor');\n        if (predictor) {\n            this.predictor = predictor;\n        }\n    }\n\n    async resolve(context) {\n        const resolve = async (entry) => {\n            let module = null;\n            let content = '';\n            if (entry.format === 'tf') {\n                const protobuf = await import('./protobuf.js');\n                module = await context.require('./tf');\n                content = new mlnet.Context(context, 'model.pb', entry.bytes, protobuf);\n            } else if (entry.format === 'onnx') {\n                const protobuf = await import('./protobuf.js');\n                module = await context.require('./onnx');\n                content = new mlnet.Context(context, 'model.onnx', entry.bytes, protobuf);\n            } else {\n                throw new mlnet.Error(`Unsupported ML.NET model format '${entry.format}'.`);\n            }\n            const factory = new module.ModelFactory();\n            await factory.match(content);\n            const model = await factory.open(content);\n            if (model && Array.isArray(model.modules) && model.modules.length > 0) {\n                return model.modules[0];\n            }\n            return null;\n        };\n        const results = await Promise.all(this._resolve.map((entry) => resolve(entry).catch(() => null)));\n        for (let i = 0; i < this._resolve.length; i++) {\n            if (results[i]) {\n                this._resolve[i].target.Model = results[i];\n            }\n        }\n    }\n};\n\nmlnet.Context = class {\n\n    constructor(context, identifier, bytes, protobuf) {\n        this._context = context;\n        this._protobuf = protobuf;\n        this._identifier = identifier;\n        this._stream = new base.BinaryStream(bytes);\n        this._tags = new Map();\n    }\n\n    get identifier() {\n        return this._identifier;\n    }\n\n    get stream() {\n        return this._stream;\n    }\n\n    set(type, value) {\n        this.type = type;\n        this.value = value;\n        return type;\n    }\n\n    async require(id) {\n        return this._context.require(id);\n    }\n\n    async metadata(id) {\n        return this._context.metadata(id);\n    }\n\n    async request(file, encoding) {\n        return this._context.request(file, encoding);\n    }\n\n    async read(type) {\n        if (type === 'protobuf.binary') {\n            return this._protobuf.BinaryReader.open(this.stream);\n        }\n        throw new mlnet.Error(`Unsupported read type '${type}'.`);\n    }\n\n    async tags(type) {\n        if (!this._tags.has(type)) {\n            let tags = new Map();\n            try {\n                const reader = this._protobuf.BinaryReader.open(this.stream);\n                tags = type === 'pb+' ? reader.decode() : reader.signature();\n            } catch {\n                // continue regardless of error\n            }\n            this.stream.seek(0);\n            this._tags.set(type, tags);\n        }\n        return this._tags.get(type);\n    }\n\n    async peek() {\n        return undefined;\n    }\n\n    error(err) {\n        this._context.error(err, false);\n    }\n};\n\nmlnet.ComponentCatalog = class {\n\n    constructor() {\n        this._registry = new Map();\n    }\n\n    register(signature, type) {\n        this._registry.set(signature, type);\n    }\n\n    create(signature, context) {\n        if (!this._registry.has(signature)) {\n            throw new mlnet.Error(`Unsupported loader signature '${signature}'.`);\n        }\n        const type = this._registry.get(signature);\n        return Reflect.construct(type, [context]);\n    }\n};\n\nmlnet.ModelHeader = class {\n\n    constructor(catalog, entries, directory, data, resolve) {\n        this._entries = entries;\n        this._catalog = catalog;\n        this._directory = directory;\n        this._resolve = resolve;\n        if (data) {\n            const reader = new mlnet.BinaryReader(data);\n            const decoder = new TextDecoder('ascii');\n            reader.assert('ML\\0MODEL');\n            this.versionWritten = reader.uint32();\n            this.versionReadable = reader.uint32();\n            const modelBlockOffset = reader.uint64().toNumber();\n            /* let modelBlockSize = */ reader.uint64();\n            const stringTableOffset = reader.uint64().toNumber();\n            const stringTableSize = reader.uint64().toNumber();\n            const stringCharsOffset = reader.uint64().toNumber();\n            /* v stringCharsSize = */ reader.uint64();\n            this.modelSignature = decoder.decode(reader.read(8));\n            this.modelVersionWritten = reader.uint32();\n            this.modelVersionReadable = reader.uint32();\n            this.loaderSignature = decoder.decode(reader.read(24).filter((c) => c !== 0));\n            this.loaderSignatureAlt = decoder.decode(reader.read(24).filter((c) => c !== 0));\n            const tailOffset = reader.uint64().toNumber();\n            /* let tailLimit = */ reader.uint64();\n            const assemblyNameOffset = reader.uint64().toNumber();\n            const assemblyNameSize = reader.uint32();\n            if (stringTableOffset !== 0 && stringCharsOffset !== 0) {\n                reader.seek(stringTableOffset);\n                const stringCount = stringTableSize >> 3;\n                const stringSizes = [];\n                let previousStringSize = 0;\n                for (let i = 0; i < stringCount; i++) {\n                    const stringSize = reader.uint64().toNumber();\n                    stringSizes.push(stringSize - previousStringSize);\n                    previousStringSize = stringSize;\n                }\n                reader.seek(stringCharsOffset);\n                this.strings = [];\n                for (let i = 0; i < stringCount; i++) {\n                    const cch = stringSizes[i] >> 1;\n                    let sb = '';\n                    for (let ich = 0; ich < cch; ich++) {\n                        sb += String.fromCharCode(reader.uint16());\n                    }\n                    this.strings.push(sb);\n                }\n            }\n            if (assemblyNameOffset !== 0) {\n                reader.seek(assemblyNameOffset);\n                this.assemblyName = decoder.decode(reader.read(assemblyNameSize));\n            }\n            reader.seek(tailOffset);\n            reader.assert('LEDOM\\0LM');\n            this._reader = reader;\n            this._reader.seek(modelBlockOffset);\n        }\n    }\n\n    get reader() {\n        return this._reader;\n    }\n\n    string(empty) {\n        const id = this.reader.int32();\n        if (empty === null && id < 0) {\n            return null;\n        }\n        return this.strings[id];\n    }\n\n    open(name) {\n        const dir = this._directory.length > 0 ? `${this._directory}/` : this._directory;\n        name = dir + name;\n        const key = `${name}/Model.key`;\n        const stream = this._entries.get(key) || this._entries.get(key.replace(/\\//g, '\\\\'));\n        if (stream) {\n            const buffer = stream.peek();\n            const context = new mlnet.ModelHeader(this._catalog, this._entries, name, buffer, this._resolve);\n            const value = this._catalog.create(context.loaderSignature, context);\n            value.__type__ = value.__type__ || context.loaderSignature;\n            value.__name__ = name;\n            return value;\n        }\n        return null;\n    }\n\n    openBinary(name) {\n        const dir = this._directory.length > 0 ? `${this._directory}/` : this._directory;\n        name = dir + name;\n        const stream = this._entries.get(name) || this._entries.get(name.replace(/\\//g, '\\\\'));\n        if (stream) {\n            return new mlnet.BinaryReader(stream);\n        }\n        return null;\n    }\n\n    openText(name) {\n        const dir = this._directory.length > 0 ? `${this._directory}/` : this._directory;\n        name = dir + name;\n        const stream = this._entries.get(name) || this._entries.get(name.replace(/\\//g, '\\\\'));\n        if (stream) {\n            const buffer = stream.peek();\n            const decoder = new TextDecoder('utf-8');\n            return decoder.decode(buffer);\n        }\n        return null;\n    }\n\n    check(signature, verWrittenCur, verWeCanReadBack) {\n        return signature === this.modelSignature && verWrittenCur >= this.modelVersionReadable && verWeCanReadBack <= this.modelVersionWritten;\n    }\n\n    resolve(target, format, bytes) {\n        this._resolve.push({ target, format, bytes });\n    }\n};\n\nmlnet.BinaryReader = class {\n\n    constructor(data) {\n        this._reader = base.BinaryReader.open(data);\n    }\n\n    seek(position) {\n        this._reader.seek(position);\n    }\n\n    skip(offset) {\n        this._reader.skip(offset);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    boolean() {\n        return this._reader.boolean();\n    }\n\n    booleans(count) {\n        const values = [];\n        for (let i = 0; i < count; i++) {\n            values.push(this.boolean());\n        }\n        return values;\n    }\n\n    byte() {\n        return this._reader.byte();\n    }\n\n    int16() {\n        return this._reader.int16();\n    }\n\n    int32() {\n        return this._reader.int32();\n    }\n\n    int32s(count) {\n        const values = [];\n        for (let i = 0; i < count; i++) {\n            values.push(this.int32());\n        }\n        return values;\n    }\n\n    int64() {\n        return this._reader.int64();\n    }\n\n    uint16() {\n        return this._reader.uint16();\n    }\n\n    uint32() {\n        return this._reader.uint32();\n    }\n\n    uint32s(count) {\n        const values = [];\n        for (let i = 0; i < count; i++) {\n            values.push(this.uint32());\n        }\n        return values;\n    }\n\n    uint64() {\n        return this._reader.uint64();\n    }\n\n    float32() {\n        return this._reader.float32();\n    }\n\n    float32s(count) {\n        const values = [];\n        for (let i = 0; i < count; i++) {\n            values.push(this.float32());\n        }\n        return values;\n    }\n\n    float64() {\n        return this._reader.float64();\n    }\n\n    float64s(count) {\n        const values = [];\n        for (let i = 0; i < count; i++) {\n            values.push(this.float64());\n        }\n        return values;\n    }\n\n    string() {\n        const size = this.leb128();\n        const buffer = this.read(size);\n        return new TextDecoder('utf-8').decode(buffer);\n    }\n\n    leb128() {\n        let result = 0;\n        let shift = 0;\n        let value = 0;\n        do {\n            value = this.byte();\n            result |= (value & 0x7F) << shift;\n            shift += 7;\n        } while ((value & 0x80) !== 0);\n        return result;\n    }\n\n    match(text) {\n        const position = this.position;\n        for (let i = 0; i < text.length; i++) {\n            if (this.byte() !== text.charCodeAt(i)) {\n                this.seek(position);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    assert(text) {\n        if (!this.match(text)) {\n            throw new mlnet.Error(`Invalid '${text.split('\\0').join('')}' signature.`);\n        }\n    }\n};\n\nmlnet.BinaryLoader = class { // 'BINLOADR'\n\n    constructor(context, reader) {\n        if (context) {\n            if (context.modelVersionWritten >= 0x00010002) {\n                this.Threads = context.reader.int32();\n                this.GeneratedRowIndexName = context.string(null);\n            }\n            this.ShuffleBlocks = context.modelVersionWritten >= 0x00010003 ? context.reader.float64() : 4;\n            reader = context.openBinary('Schema.idv');\n        }\n        // https://github.com/dotnet/machinelearning/blob/master/docs/code/IdvFileFormat.md\n        reader.assert('CML\\0DVB\\0');\n        reader.skip(8); // version\n        reader.skip(8); // compatibleVersion\n        const tableOfContentsOffset = reader.uint64().toNumber();\n        const tailOffset = reader.int64().toNumber();\n        reader.int64(); // rowCount\n        const columnCount = reader.int32();\n        reader.seek(tailOffset);\n        reader.assert('\\0BVD\\0LMC');\n        reader.seek(tableOfContentsOffset);\n        this.schema = {};\n        this.schema.inputs = [];\n        const columns = new Map();\n        for (let c = 0; c < columnCount; c  ++) {\n            const input = {};\n            input.name = reader.string();\n            input.type = new mlnet.Codec(reader);\n            input.compression = reader.byte(); // None = 0, Deflate = 1\n            input.rowsPerBlock = reader.leb128();\n            input.lookupOffset = reader.int64();\n            input.metadataTocOffset = reader.int64();\n            columns.set(input.name, input);\n        }\n        for (const input of columns.values()) {\n            this.schema.inputs.push(input);\n        }\n    }\n};\n\nmlnet.TransformerChain = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const length = reader.int32();\n        this.scopes = [];\n        this.chain = [];\n        for (let i = 0; i < length; i++) {\n            this.scopes.push(reader.int32()); // 0x01 = Training, 0x02 = Testing, 0x04 = Scoring\n            const dirName = `Transform_${(`00${i}`).slice(-3)}`;\n            const transformer = context.open(dirName);\n            this.chain.push(transformer);\n        }\n    }\n};\n\nmlnet.TransformBase = class {\n};\n\nmlnet.RowToRowTransformBase = class extends mlnet.TransformBase {\n};\n\nmlnet.RowToRowTransformerBase = class {\n};\n\nmlnet.RowToRowMapperTransformBase = class extends mlnet.RowToRowTransformBase {\n};\n\nmlnet.OneToOneTransformerBase = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const n = reader.int32();\n        this.inputs = [];\n        this.outputs = [];\n        for (let i = 0; i < n; i++) {\n            const output = context.string();\n            const input = context.string();\n            this.outputs.push({ name: output });\n            this.inputs.push({ name: input });\n        }\n    }\n};\n\nmlnet.ColumnCopyingTransformer = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const length = reader.uint32();\n        this.inputs = [];\n        this.outputs = [];\n        for (let i = 0; i < length; i++) {\n            this.outputs.push({ name: context.string() });\n            this.inputs.push({ name: context.string() });\n        }\n    }\n};\n\nmlnet.ColumnConcatenatingTransformer = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        if (context.modelVersionReadable >= 0x00010003) {\n            const count = reader.int32();\n            for (let i = 0; i < count; i++) {\n                this.outputs = [];\n                this.outputs.push({ name: context.string() });\n                const n = reader.int32();\n                this.inputs = [];\n                for (let j = 0; j < n; j++) {\n                    const input = {\n                        name: context.string()\n                    };\n                    const alias = context.string(null);\n                    if (alias) {\n                        input.alias = alias;\n                    }\n                    this.inputs.push(input);\n                }\n            }\n        } else {\n            this.precision = reader.int32();\n            const n = reader.int32();\n            const names = [];\n            const inputs = [];\n            for (let i = 0; i < n; i++) {\n                names.push(context.string());\n                const numSources = reader.int32();\n                const input = [];\n                for (let j = 0; j < numSources; j++) {\n                    input.push(context.string());\n                }\n                inputs.push(input);\n            }\n            const aliases = [];\n            if (context.modelVersionReadable >= 0x00010002) {\n                for (let i = 0; i < n; i++) {\n                    /* let length = inputs[i].length; */\n                    const alias = {};\n                    aliases.push(alias);\n                    if (context.modelVersionReadable >= 0x00010002) {\n                        for (;;) {\n                            const j = reader.int32();\n                            if (j === -1) {\n                                break;\n                            }\n                            alias[j] = context.string();\n                        }\n                    }\n                }\n            }\n\n            if (n > 1) {\n                throw new mlnet.Error(`Unsupported ColumnConcatenatingTransformer name count '${n}'.`);\n            }\n\n            this.outputs = [];\n            for (let i = 0; i < n; i++) {\n                this.outputs.push({\n                    name: names[i]\n                });\n                this.inputs = inputs[i];\n            }\n        }\n    }\n};\n\nmlnet.PredictionTransformerBase = class {\n\n    constructor(context) {\n        this.Model = context.open('Model');\n        const trainSchemaReader = context.openBinary('TrainSchema');\n        if (trainSchemaReader) {\n            this.schema = new mlnet.BinaryLoader(null, trainSchemaReader).schema;\n        }\n    }\n};\n\nmlnet.MatrixFactorizationModelParameters = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        this.NumberOfRows = reader.int32();\n        if (context.modelVersionWritten < 0x00010002) {\n            reader.uint64(); // mMin\n        }\n        this.NumberOfColumns = reader.int32();\n        if (context.modelVersionWritten < 0x00010002) {\n            reader.uint64(); // nMin\n        }\n        this.ApproximationRank = reader.int32();\n\n        this._leftFactorMatrix = reader.float32s(this.NumberOfRows * this.ApproximationRank);\n        this._rightFactorMatrix = reader.float32s(this.NumberOfColumns * this.ApproximationRank);\n    }\n};\n\nmlnet.MatrixFactorizationPredictionTransformer = class extends mlnet.PredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        this.MatrixColumnIndexColumnName = context.string();\n        this.MatrixRowIndexColumnName = context.string();\n    }\n};\n\nmlnet.FieldAwareFactorizationMachinePredictionTransformer = class extends mlnet.PredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.inputs = [];\n        for (let i = 0; i < this.FieldCount; i++) {\n            this.inputs.push({ name: context.string() });\n        }\n        this.Threshold = reader.float32();\n        this.ThresholdColumn = context.string();\n        this.outputs = [];\n        this.outputs.push({ name: 'Score' });\n        this.outputs.push({ name: 'Probability' });\n        this.outputs.push({ name: 'PredictedLabel' });\n    }\n};\n\nmlnet.SingleFeaturePredictionTransformerBase = class extends mlnet.PredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const featureColumn = context.string(null);\n        this.inputs = [];\n        this.inputs.push({ name: featureColumn });\n        this.outputs = [];\n    }\n};\n\nmlnet.ClusteringPredictionTransformer = class extends mlnet.SingleFeaturePredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        this.outputs.push({ name: 'Score' });\n        this.outputs.push({ name: 'PredictedLabel' });\n    }\n};\n\nmlnet.AnomalyPredictionTransformer = class extends mlnet.SingleFeaturePredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.Threshold = reader.float32();\n        this.ThresholdColumn = context.string();\n        this.outputs.push({ name: 'Score' });\n        this.outputs.push({ name: 'PredictedLabel' });\n    }\n};\n\nmlnet.AffineNormSerializationUtils = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        /* cbFloat = */ reader.int32();\n        this.NumFeatures = reader.int32();\n        const morphCount = reader.int32();\n        if (morphCount === -1) {\n            this.ScalesSparse = reader.float32s(reader.int32());\n            this.OffsetsSparse = reader.float32s(reader.int32());\n        } else {\n            // debugger;\n        }\n    }\n};\n\nmlnet.RegressionPredictionTransformer = class extends mlnet.SingleFeaturePredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        this.outputs.push({ name: 'Score' });\n    }\n};\n\nmlnet.BinaryPredictionTransformer = class extends mlnet.SingleFeaturePredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.Threshold = reader.float32();\n        this.ThresholdColumn = context.string();\n        this.outputs.push({ name: 'Score' });\n        this.outputs.push({ name: 'PredictedLabel' });\n    }\n};\n\nmlnet.MulticlassPredictionTransformer = class extends mlnet.SingleFeaturePredictionTransformerBase {\n\n    constructor(context) {\n        super(context);\n        this.TrainLabelColumn = context.string(null);\n        this.inputs.push({ name: this.TrainLabelColumn });\n        if (context.modelVersionWritten >= 0x00010002) {\n            const scoreColumn = context.string(null);\n            const predictedLabelColumn = context.string(null);\n            this.outputs.push({ name: scoreColumn || 'Score' });\n            this.outputs.push({ name: predictedLabelColumn || 'PredictedLabel' });\n        } else {\n            this.outputs.push({ name: 'Score' });\n            this.outputs.push({ name: 'PredictedLabel' });\n        }\n    }\n};\n\nmlnet.MissingValueReplacingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        for (let i = 0; i < this.inputs.length; i++) {\n            const codec = new mlnet.Codec(reader);\n            const count = reader.int32();\n            this.values = codec.read(reader, count);\n        }\n    }\n};\n\nmlnet.PredictorBase = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        if (reader.int32() !== 4) {\n            throw new mlnet.Error('Invalid float type size.');\n        }\n    }\n};\n\nmlnet.ModelParametersBase = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const cbFloat = reader.int32();\n        if (cbFloat !== 4) {\n            throw new mlnet.Error('This file was saved by an incompatible version.');\n        }\n    }\n};\n\nmlnet.ImageClassificationModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.classCount = reader.int32();\n        this.imagePreprocessorTensorInput = reader.string();\n        this.imagePreprocessorTensorOutput = reader.string();\n        this.graphInputTensor = reader.string();\n        this.graphOutputTensor = reader.string();\n        const modelReader = context.openBinary('TFModel');\n        if (modelReader) {\n            const size = modelReader.uint32();\n            context.resolve(this, 'tf', modelReader.read(size));\n        }\n    }\n};\n\nmlnet.NaiveBayesMulticlassModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this._labelHistogram = reader.int32s(reader.int32());\n        this._featureCount = reader.int32();\n        this._featureHistogram = [];\n        for (let i = 0; i < this._labelHistogram.length; i++) {\n            if (this._labelHistogram[i] > 0) {\n                this._featureHistogram.push(reader.int32s(this._featureCount));\n            }\n        }\n        this._absentFeaturesLogProb = reader.float64s(this._labelHistogram.length);\n    }\n};\n\nmlnet.LinearModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.Bias = reader.float32();\n        /* let len = */ reader.int32();\n        this.Indices = reader.int32s(reader.int32());\n        this.Weights = reader.float32s(reader.int32());\n    }\n};\n\nmlnet.LinearBinaryModelParameters = class extends mlnet.LinearModelParameters {\n\n    constructor(context) {\n        super(context);\n        if (context.modelVersionWritten > 0x00020001) {\n            this.Statistics = context.open('ModelStats');\n        }\n    }\n};\n\nmlnet.ModelStatisticsBase = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        this.ParametersCount = reader.int32();\n        this.TrainingExampleCount = reader.int64().toNumber();\n        this.Deviance = reader.float32();\n        this.NullDeviance = reader.float32();\n\n    }\n};\n\nmlnet.LinearModelParameterStatistics = class extends mlnet.ModelStatisticsBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (context.modelVersionWritten < 0x00010002) {\n            if (!reader.boolean()) {\n                return;\n            }\n        }\n        const stdErrorValues = reader.float32s(this.ParametersCount);\n        const length = reader.int32();\n        if (length === this.ParametersCount) {\n            this._coeffStdError = stdErrorValues;\n        } else {\n            this.stdErrorIndices = reader.int32s(this.ParametersCount);\n            this._coeffStdError = stdErrorValues;\n        }\n        this._bias = reader.float32();\n        const isWeightsDense = reader.byte();\n        const weightsLength = reader.int32();\n        const weightsValues = reader.float32s(weightsLength);\n\n        if (isWeightsDense) {\n            this._weights = weightsValues;\n        } else {\n            this.weightsIndices = reader.int32s(weightsLength);\n        }\n    }\n};\n\nmlnet.LinearMulticlassModelParametersBase = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        const numberOfFeatures = reader.int32();\n        const numberOfClasses = reader.int32();\n        this.Biases = reader.float32s(numberOfClasses);\n        const numStarts = reader.int32();\n        if (numStarts === 0) {\n            /* let numIndices = */ reader.int32();\n            /* let numWeights = */ reader.int32();\n            this.Weights = [];\n            for (let i = 0; i < numberOfClasses; i++) {\n                const w = reader.float32s(numberOfFeatures);\n                this.Weights.push(w);\n            }\n        } else {\n\n            const starts = reader.int32s(reader.int32());\n            /* let numIndices = */ reader.int32();\n            const indices = [];\n            for (let i = 0; i < numberOfClasses; i++) {\n                indices.push(reader.int32s(starts[i + 1] - starts[i]));\n            }\n            /* let numValues = */ reader.int32();\n            this.Weights = [];\n            for (let i = 0; i < numberOfClasses; i++) {\n                const values = reader.float32s(starts[i + 1] - starts[i]);\n                this.Weights.push(values);\n            }\n        }\n\n        const labelNamesReader = context.openBinary('LabelNames');\n        if (labelNamesReader) {\n            this.LabelNames = [];\n            for (let i = 0; i < numberOfClasses; i++) {\n                const id = labelNamesReader.int32();\n                this.LabelNames.push(context.strings[id]);\n            }\n        }\n\n        const statistics = context.open('ModelStats');\n        if (statistics) {\n            this.Statistics = statistics;\n        }\n    }\n};\n\nmlnet.LinearMulticlassModelParameters = class extends mlnet.LinearMulticlassModelParametersBase {\n};\n\nmlnet.RegressionModelParameters = class extends mlnet.LinearModelParameters {\n};\n\nmlnet.PoissonRegressionModelParameters = class extends mlnet.RegressionModelParameters {\n};\n\nmlnet.LinearRegressionModelParameters = class extends mlnet.RegressionModelParameters {\n};\n\nmlnet.MaximumEntropyModelParameters = class extends mlnet.LinearMulticlassModelParametersBase {\n};\n\nmlnet.TokenizingByCharactersTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.UseMarkerChars = reader.boolean();\n        this.IsSeparatorStartEnd = context.modelVersionReadable < 0x00010002 ? true : reader.boolean();\n    }\n};\n\nmlnet.SequencePool = class {\n\n    constructor(reader) {\n        this.idLim = reader.int32();\n        this.start = reader.int32s(this.idLim + 1);\n        this.bytes = reader.read(this.start[this.idLim]);\n    }\n};\n\nmlnet.NgramExtractingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (this.inputs.length === 1) {\n            this._option(context, reader, this);\n        } else {\n            // debugger;\n        }\n    }\n\n    _option(context, reader, option) {\n        const readWeighting = context.modelVersionReadable >= 0x00010002;\n        option.NgramLength = reader.int32();\n        option.SkipLength = reader.int32();\n        if (readWeighting) {\n            option.Weighting = reader.int32();\n        }\n        option.NonEmptyLevels = reader.booleans(option.NgramLength);\n        option.NgramMap = new mlnet.SequencePool(reader);\n        if (readWeighting) {\n            option.InvDocFreqs = reader.float64s(reader.int32());\n        }\n    }\n};\n\n// mlnet.NgramExtractingTransformer.WeightingCriteria\n\nmlnet.NgramHashingTransformer = class extends mlnet.RowToRowTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const loadLegacy = context.modelVersionWritten < 0x00010003;\n        const reader = context.reader;\n        if (loadLegacy) {\n            reader.int32(); // cbFloat\n        }\n        this.inputs = [];\n        this.outputs = [];\n        const columnsLength = reader.int32();\n        if (loadLegacy) {\n            // for (let i = 0; i < columnsLength; i++) {\n            //     this.Columns.push(new NgramHashingEstimator.ColumnOptions(context));\n            // }\n        } else {\n            for (let i = 0; i < columnsLength; i++) {\n                this.outputs.push(context.string());\n                const csrc = reader.int32();\n                for (let j = 0; j < csrc; j++) {\n                    const src = context.string();\n                    this.inputs.push(src);\n                    // inputs[i][j] = src;\n                }\n            }\n        }\n    }\n};\n\nmlnet.WordTokenizingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (this.inputs.length === 1) {\n            this.Separators = [];\n            const count = reader.int32();\n            for (let i = 0; i < count; i++) {\n                this.Separators.push(String.fromCharCode(reader.int16()));\n            }\n        } else {\n            // debugger;\n        }\n    }\n};\n\nmlnet.TextNormalizingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.CaseMode = reader.byte();\n        this.KeepDiacritics = reader.boolean();\n        this.KeepPunctuations = reader.boolean();\n        this.KeepNumbers = reader.boolean();\n    }\n};\n\nmlnet.TextNormalizingTransformer.CaseMode = {\n    Lower: 0,\n    Upper: 1,\n    None: 2\n};\n\nmlnet.PrincipalComponentAnalysisTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (context.modelVersionReadable === 0x00010001) {\n            if (reader.int32() !== 4) {\n                throw new mlnet.Error('This file was saved by an incompatible version.');\n            }\n        }\n        this.TransformInfos = [];\n        for (let i = 0; i < this.inputs.length; i++) {\n            const option = {};\n            option.Dimension = reader.int32();\n            option.Rank = reader.int32();\n            option.Eigenvectors = [];\n            for (let j = 0; j < option.Rank; j++) {\n                option.Eigenvectors.push(reader.float32s(option.Dimension));\n            }\n            option.MeanProjected = reader.float32s(reader.int32());\n            this.TransformInfos.push(option);\n        }\n    }\n};\n\nmlnet.LpNormNormalizingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n\n        if (context.modelVersionWritten <= 0x00010002) {\n            /* cbFloat */ reader.int32();\n        }\n        // let normKindSerialized = context.modelVersionWritten >= 0x00010002;\n        if (this.inputs.length === 1) {\n            this.EnsureZeroMean = reader.boolean();\n            this.Norm = reader.byte();\n            this.Scale = reader.float32();\n        } else {\n            // debugger;\n        }\n    }\n};\n\nmlnet.KeyToVectorMappingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (context.modelVersionWritten === 0x00010001) {\n            /* cbFloat = */ reader.int32();\n        }\n        const columnsLength = this.inputs.length;\n        this.Bags = reader.booleans(columnsLength);\n    }\n};\n\nmlnet.TypeConvertingTransformer = class extends mlnet.OneToOneTransformerBase {\n};\n\nmlnet.ImageLoadingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        this.ImageFolder = context.string(null);\n    }\n};\n\nmlnet.ImageResizingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (this.inputs.length === 1) {\n            this._option(reader, this);\n        } else {\n            this.Options = [];\n            for (let i = 0; i < this.inputs.length; i++) {\n                const option = {};\n                this._option(reader, option);\n                this.Options.push(option);\n            }\n        }\n    }\n\n    _option(reader, option) {\n        option.Width = reader.int32();\n        option.Height = reader.int32();\n        option.Resizing = reader.byte();\n        option.Anchor = reader.byte();\n    }\n};\n\nmlnet.ImageResizingTransformer.ResizingKind = {\n    IsoPad: 0,\n    IsoCrop: 1,\n    Fill: 2\n};\n\nmlnet.ImageResizingTransformer.Anchor = {\n    Right: 0,\n    Left: 1,\n    Top: 2,\n    Bottom: 3,\n    Center: 4\n};\n\nmlnet.ImagePixelExtractingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (this.inputs.length === 1) {\n            this._option(context, reader, this);\n        } else {\n            this.Options = [];\n            for (let i = 0; i < this.inputs.length; i++) {\n                const option = {};\n                this._option(context, reader, option);\n                this.Options.push(option);\n            }\n        }\n    }\n\n    _option(context, reader, option) {\n        option.ColorsToExtract = reader.byte();\n        option.OrderOfExtraction = context.modelVersionWritten <= 0x00010002 ? mlnet.ImagePixelExtractingTransformer.ColorsOrder.ARGB : reader.byte();\n        let planes = option.ColorsToExtract;\n        planes = (planes & 0x05) + ((planes >> 1) & 0x05);\n        planes = (planes & 0x03) + ((planes >> 2) & 0x03);\n        option.Planes = planes & 0xFF;\n        option.OutputAsFloatArray = reader.boolean();\n        option.OffsetImage = reader.float32();\n        option.ScaleImage = reader.float32();\n        option.InterleavePixelColors = reader.boolean();\n    }\n};\n\nmlnet.ImagePixelExtractingTransformer.ColorBits = {\n    Alpha: 0x01,\n    Red: 0x02,\n    Green: 0x04,\n    Blue: 0x08,\n    Rgb: 0x0E,\n    All: 0x0F\n};\n\nmlnet.ImagePixelExtractingTransformer.ColorsOrder = {\n    ARGB: 1,\n    ARBG: 2,\n    ABRG: 3,\n    ABGR: 4,\n    AGRB: 5,\n    AGBR: 6\n};\n\nmlnet.NormalizingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.Options = [];\n        for (let i = 0; i < this.inputs.length; i++) {\n            let isVector = false;\n            let shape = 0;\n            let itemKind = '';\n            if (context.modelVersionWritten < 0x00010002) {\n                isVector = reader.boolean();\n                shape = [reader.int32()];\n                itemKind = reader.byte();\n            } else {\n                isVector = reader.boolean();\n                itemKind = reader.byte();\n                shape = reader.int32s(reader.int32());\n            }\n            let itemType = '';\n            switch (itemKind) {\n                case 9: itemType = 'float32'; break;\n                case 10: itemType = 'float64'; break;\n                default: throw new mlnet.Error(`Unsupported NormalizingTransformer item kind '${itemKind}'.`);\n            }\n            const type = itemType + (isVector ? `[${shape.map((dim) => dim.toString()).join(',')}]` : '');\n            const name = `Normalizer_${(`00${i}`).slice(-3)}`;\n            const func = context.open(name);\n            this.Options.push({ type, func });\n        }\n    }\n};\n\nmlnet.KeyToValueMappingTransformer = class extends mlnet.OneToOneTransformerBase {\n};\n\nmlnet.ValueToKeyMappingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        if (context.modelVersionWritten >= 0x00010003) {\n            this.textMetadata = reader.booleans(this.outputs.length + this.inputs.length);\n        } else {\n            this.textMetadata = [];\n            for (let i = 0; i < this.columnPairs.length; i++) {\n                this.textMetadata.push(false);\n            }\n        }\n        const vocabulary = context.open('Vocabulary');\n        if (vocabulary) {\n            this.termMap = vocabulary.termMap;\n        }\n    }\n};\n\nmlnet.TermMap = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const mtype = reader.byte();\n        switch (mtype) {\n            case 0: { // Text\n                this.values = [];\n                const cstr = reader.int32();\n                for (let i = 0; i < cstr; i++) {\n                    this.values.push(context.string());\n                }\n                break;\n            }\n            case 1: { // Codec\n                const codec = new mlnet.Codec(reader);\n                const count = reader.int32();\n                this.values = codec.read(reader, count);\n                break;\n            }\n            default:\n                throw new mlnet.Error(`Unsupported term map type '${mtype}'.`);\n        }\n    }\n};\n\nmlnet.TermManager = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const cmap = reader.int32();\n        this.termMap = [];\n        if (context.modelVersionWritten >= 0x00010002) {\n            for (let i = 0; i < cmap; ++i) {\n                this.termMap.push(new mlnet.TermMap(context));\n                // debugger;\n                // termMap[i] = TermMap.Load(c, host, CodecFactory);\n            }\n        } else {\n            throw new mlnet.Error('Unsupported TermManager version.');\n            // for (let i = 0; i < cmap; ++i) {\n            //    debugger;\n            //    // termMap[i] = TermMap.TextImpl.Create(c, host)\n            // }\n        }\n    }\n};\n\nmlnet.ValueMappingTransformer = class extends mlnet.OneToOneTransformerBase {\n\n    constructor(context) {\n        super(context);\n        this.keyColumnName = 'Key';\n        if (context.check('TXTLOOKT', 0x00010002, 0x00010002)) {\n            this.keyColumnName = 'Term';\n        }\n    }\n};\n\nmlnet.KeyToVectorTransform = class {\n};\n\nmlnet.GenericScoreTransform = class {\n};\n\nmlnet.CompositeDataLoader = class {\n\n    constructor(context) {\n        /* let loader = */ context.open('Loader');\n        const reader = context.reader;\n        // LoadTransforms\n        reader.int32(); // floatSize\n        const cxf = reader.int32();\n        const tagData = [];\n        for (let i = 0; i < cxf; i++) {\n            let tag = '';\n            let args = null;\n            if (context.modelVersionReadable >= 0x00010002) {\n                tag = context.string();\n                args = context.string(null);\n            }\n            tagData.push([tag, args]);\n        }\n        this.chain = [];\n        for (let j = 0; j < cxf; j++) {\n            const name = `Transform_${(`00${j}`).slice(-3)}`;\n            const transform = context.open(name);\n            this.chain.push(transform);\n        }\n    }\n};\n\nmlnet.RowToRowMapperTransform = class extends mlnet.RowToRowTransformBase {\n\n    constructor(context) {\n        super(context);\n        const mapper = context.open('Mapper');\n        this.__type__ = mapper.__type__;\n        for (const key of Object.keys(mapper)) {\n            this[key] = mapper[key];\n        }\n    }\n};\n\nmlnet.ImageClassificationTransformer = class extends mlnet.RowToRowTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.addBatchDimensionInput = reader.boolean();\n        const numInputs = reader.int32();\n        this.inputs = [];\n        for (let i = 0; i < numInputs; i++) {\n            this.inputs.push({ name: context.string() });\n        }\n        this.outputs = [];\n        const numOutputs = reader.int32();\n        for (let i = 0; i < numOutputs; i++) {\n            this.outputs.push({ name: context.string() });\n        }\n        this.labelColumn = reader.string();\n        this.checkpointName = reader.string();\n        this.arch = reader.int32(); // Architecture\n        this.scoreColumnName = reader.string();\n        this.predictedColumnName = reader.string();\n        this.learningRate = reader.float32();\n        this.classCount = reader.int32();\n        this.keyValueAnnotations = [];\n        for (let i = 0; i < this.classCount; i++) {\n            this.keyValueAnnotations.push(context.string());\n        }\n        this.predictionTensorName = reader.string();\n        this.softMaxTensorName = reader.string();\n        this.jpegDataTensorName = reader.string();\n        this.resizeTensorName = reader.string();\n    }\n};\n\nmlnet.OnnxTransformer = class extends mlnet.RowToRowTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        const modelReader = context.openBinary('OnnxModel');\n        if (modelReader) {\n            const size = modelReader.uint32();\n            context.resolve(this, 'onnx', modelReader.read(size));\n        }\n        const numInputs = context.modelVersionWritten > 0x00010001 ? reader.int32() : 1;\n        this.inputs = [];\n        for (let i = 0; i < numInputs; i++) {\n            this.inputs.push({ name: context.string() });\n        }\n        const numOutputs = context.modelVersionWritten > 0x00010001 ? reader.int32() : 1;\n        this.outputs = [];\n        for (let i = 0; i < numOutputs; i++) {\n            this.outputs.push({ name: context.string() });\n        }\n        if (context.modelVersionWritten > 0x0001000C) {\n            const customShapeInfosLength = reader.int32();\n            this.LoadedCustomShapeInfos = [];\n            for (let i = 0; i < customShapeInfosLength; i++) {\n                this.LoadedCustomShapeInfos.push({\n                    name: context.string(),\n                    shape: reader.int32s(reader.int32())\n                });\n            }\n        }\n    }\n};\n\nmlnet.OptionalColumnTransform = class extends mlnet.RowToRowMapperTransformBase {\n};\n\nmlnet.TensorFlowTransformer = class extends mlnet.RowToRowTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.IsFrozen = context.modelVersionReadable >= 0x00010002 ? reader.boolean() : true;\n        this.AddBatchDimensionInput = context.modelVersionReadable >= 0x00010003 ? reader.boolean() : true;\n        const numInputs = reader.int32();\n        this.inputs = [];\n        for (let i = 0; i < numInputs; i++) {\n            this.inputs.push({ name: context.string() });\n        }\n        const numOutputs = context.modelVersionReadable >= 0x00010002 ? reader.int32() : 1;\n        this.outputs = [];\n        for (let i = 0; i < numOutputs; i++) {\n            this.outputs.push({ name: context.string() });\n        }\n    }\n};\n\nmlnet.OneVersusAllModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.UseDist = reader.boolean();\n        const len = reader.int32();\n        this.chain = [];\n        for (let i = 0; i < len; i++) {\n            const name = `SubPredictor_${(`00${i}`).slice(-3)}`;\n            const predictor = context.open(name);\n            this.chain.push(predictor);\n        }\n    }\n};\n\nmlnet.TextFeaturizingEstimator = class {\n\n    constructor(context) {\n\n        if (context.modelVersionReadable === 0x00010001) {\n            const reader = context.reader;\n            const n = reader.int32();\n            this.chain = [];\n            /* let loader = */ context.open('Loader');\n            for (let i = 0; i < n; i++) {\n                const name = `Step_${(`00${i}`).slice(-3)}`;\n                const transformer = context.open(name);\n                this.chain.push(transformer);\n                // debugger;\n            }\n\n            // throw new mlnet.Error('Unsupported TextFeaturizingEstimator format.');\n        } else {\n            const chain = context.open('Chain');\n            this.chain = chain.chain;\n        }\n    }\n};\n\nmlnet.TextLoader = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        reader.int32(); // floatSize\n        this.MaxRows = reader.int64();\n        this.Flags = reader.uint32();\n        this.InputSize = reader.int32();\n        const separatorCount = reader.int32();\n        this.Separators = [];\n        for (let i = 0; i < separatorCount; i++) {\n            this.Separators.push(String.fromCharCode(reader.uint16()));\n        }\n        this.Bindinds = new mlnet.TextLoader.Bindinds(context);\n    }\n};\n\nmlnet.TextLoader.Bindinds = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        const cinfo = reader.int32();\n        for (let i = 0; i < cinfo; i++) {\n            // debugger;\n        }\n    }\n};\n\nmlnet.CalibratedPredictorBase = class {\n\n    constructor(predictor, calibrator) {\n        this.SubPredictor = predictor;\n        this.Calibrator = calibrator;\n    }\n};\n\nmlnet.ValueMapperCalibratedPredictorBase = class extends mlnet.CalibratedPredictorBase {\n};\n\nmlnet.CalibratedModelParametersBase = class {\n\n    constructor(context) {\n        this.Predictor = context.open('Predictor');\n        this.Calibrator = context.open('Calibrator');\n    }\n};\n\nmlnet.ValueMapperCalibratedModelParametersBase = class extends mlnet.CalibratedModelParametersBase {\n};\n\nmlnet.CalibratedPredictor = class extends mlnet.ValueMapperCalibratedPredictorBase {\n\n    constructor(context) {\n        const predictor = context.open('Predictor');\n        const calibrator = context.open('Calibrator');\n        super(predictor, calibrator);\n    }\n};\n\nmlnet.ParameterMixingCalibratedModelParameters = class extends mlnet.ValueMapperCalibratedModelParametersBase {\n};\n\nmlnet.FieldAwareFactorizationMachineModelParameters = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        this.Norm = reader.boolean();\n        this.FieldCount = reader.int32();\n        this.FeatureCount = reader.int32();\n        this.LatentDim = reader.int32();\n        this.LinearWeights = reader.float32s(reader.int32());\n        this.LatentWeights = reader.float32s(reader.int32());\n    }\n};\n\nmlnet.KMeansModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.k = reader.int32();\n        this.Dimensionality = reader.int32();\n        this.Centroids = [];\n        for (let i = 0; i < this.k; i++) {\n            const count = context.modelVersionWritten >= 0x00010002 ? reader.int32() : this.Dimensionality;\n            const indices = count < this.Dimensionality ? reader.int32s(count) : null;\n            const values = reader.float32s(count);\n            this.Centroids.push({ indices, values });\n        }\n        // input type = float32[dimensionality]\n        // output type = float32[k]\n    }\n};\n\nmlnet.PcaModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.Dimension = reader.int32();\n        this.Rank = reader.int32();\n        const center = reader.boolean();\n        if (center) {\n            this.Mean = reader.float32s(this.Dimension);\n        } else {\n            this.Mean = [];\n        }\n        this.EigenVectors = [];\n        for (let i = 0; i < this.Rank; ++i) {\n            this.EigenVectors.push(reader.float32s(this.Dimension));\n        }\n        // input type -> float32[Dimension]\n    }\n};\n\nmlnet.TreeEnsembleModelParameters = class extends mlnet.ModelParametersBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        const usingDefaultValues = context.modelVersionWritten >= this.VerDefaultValueSerialized;\n        const categoricalSplits = context.modelVersionWritten >= this.VerCategoricalSplitSerialized;\n        this.TrainedEnsemble = new mlnet.InternalTreeEnsemble(context, usingDefaultValues, categoricalSplits);\n        this.InnerOptions = context.string(null);\n        if (context.modelVersionWritten >= this.VerNumFeaturesSerialized) {\n            this.NumFeatures = reader.int32();\n        }\n        // input type -> float32[NumFeatures]\n        // output type -> float32\n    }\n};\n\nmlnet.InternalTreeEnsemble = class {\n\n    constructor(context, usingDefaultValues, categoricalSplits) {\n        const reader = context.reader;\n        this.Trees = [];\n        const numTrees = reader.int32();\n        for (let i = 0; i < numTrees; i++) {\n            switch (reader.byte()) {\n                case mlnet.InternalTreeEnsemble.TreeType.Regression:\n                    this.Trees.push(new mlnet.InternalRegressionTree(context, usingDefaultValues, categoricalSplits));\n                    break;\n                case mlnet.InternalTreeEnsemble.TreeType.FastForest:\n                    this.Trees.push(new mlnet.InternalQuantileRegressionTree(context, usingDefaultValues, categoricalSplits));\n                    break;\n                case mlnet.InternalTreeEnsemble.TreeType.Affine:\n                    // Affine regression trees do not actually work, nor is it clear how they ever\n                    // could have worked within TLC, so the chance of this happening seems remote.\n                    throw new mlnet.Error('Affine regression trees unsupported.');\n                default:\n                    throw new mlnet.Error('Unsupported ensemble tree type.');\n            }\n        }\n        this.Bias = reader.float64();\n        this.FirstInputInitializationContent = context.string(null);\n    }\n};\n\nmlnet.InternalRegressionTree = class {\n\n    constructor(context, usingDefaultValue, categoricalSplits) {\n        const reader = context.reader;\n        this.NumLeaves = reader.int32();\n        this.MaxOuptut = reader.float64();\n        this.Weight = reader.float64();\n        this.LteChild = reader.int32s(reader.int32());\n        this.GtChild = reader.int32s(reader.int32());\n        this.SplitFeatures = reader.int32s(reader.int32());\n        if (categoricalSplits) {\n            const categoricalNodeIndices = reader.int32s(reader.int32());\n            if (categoricalNodeIndices.length > 0) {\n                this.CategoricalSplitFeatures = [];\n                this.CategoricalSplitFeatureRanges = [];\n                for (const index of categoricalNodeIndices) {\n                    this.CategoricalSplitFeatures[index] = reader.int32s(reader.int32());\n                    this.CategoricalSplitFeatureRanges[index] = reader.int32s(2);\n                }\n            }\n        }\n        this.Thresholds = reader.uint32s(reader.int32());\n        this.RawThresholds = reader.float32s(reader.int32());\n        this.DefaultValueForMissing = usingDefaultValue ? reader.float32s(reader.int32()) : null;\n        this.LeafValues = reader.float64s(reader.int32());\n\n        this.SplitGain = reader.float64s(reader.int32());\n        this.GainPValue = reader.float64s(reader.int32());\n        this.PreviousLeafValue = reader.float64s(reader.int32());\n    }\n};\n\nmlnet.InternalTreeEnsemble.TreeType = {\n    Regression: 0,\n    Affine: 1,\n    FastForest: 2\n};\n\nmlnet.TreeEnsembleModelParametersBasedOnRegressionTree = class extends mlnet.TreeEnsembleModelParameters {\n};\n\nmlnet.FastTreeTweedieModelParameters = class extends mlnet.TreeEnsembleModelParametersBasedOnRegressionTree {\n\n    get VerNumFeaturesSerialized() {\n        return 0x00010001;\n    }\n\n    get VerDefaultValueSerialized() {\n        return 0x00010002;\n    }\n\n    get VerCategoricalSplitSerialized() {\n        return 0x00010003;\n    }\n};\n\nmlnet.FastTreeRankingModelParameters = class extends mlnet.TreeEnsembleModelParametersBasedOnRegressionTree {\n\n    get VerNumFeaturesSerialized() {\n        return 0x00010002;\n    }\n\n    get VerDefaultValueSerialized() {\n        return 0x00010004;\n    }\n\n    get VerCategoricalSplitSerialized() {\n        return 0x00010005;\n    }\n};\n\nmlnet.FastTreeBinaryModelParameters = class extends mlnet.TreeEnsembleModelParametersBasedOnRegressionTree {\n\n    get VerNumFeaturesSerialized() {\n        return 0x00010002;\n    }\n\n    get VerDefaultValueSerialized() {\n        return 0x00010004;\n    }\n\n    get VerCategoricalSplitSerialized() {\n        return 0x00010005;\n    }\n};\n\nmlnet.FastTreeRegressionModelParameters = class extends mlnet.TreeEnsembleModelParametersBasedOnRegressionTree {\n\n    get VerNumFeaturesSerialized() {\n        return 0x00010002;\n    }\n\n    get VerDefaultValueSerialized() {\n        return 0x00010004;\n    }\n\n    get VerCategoricalSplitSerialized() {\n        return 0x00010005;\n    }\n};\n\nmlnet.LightGbmRegressionModelParameters = class extends mlnet.TreeEnsembleModelParametersBasedOnRegressionTree {\n\n    get VerNumFeaturesSerialized() {\n        return 0x00010002;\n    }\n\n    get VerDefaultValueSerialized() {\n        return 0x00010004;\n    }\n\n    get VerCategoricalSplitSerialized() {\n        return 0x00010005;\n    }\n};\n\nmlnet.LightGbmBinaryModelParameters = class extends mlnet.TreeEnsembleModelParametersBasedOnRegressionTree {\n\n    get VerNumFeaturesSerialized() {\n        return 0x00010002;\n    }\n\n    get VerDefaultValueSerialized() {\n        return 0x00010004;\n    }\n\n    get VerCategoricalSplitSerialized() {\n        return 0x00010005;\n    }\n};\n\nmlnet.FeatureWeightsCalibratedModelParameters = class extends mlnet.ValueMapperCalibratedModelParametersBase {\n};\n\nmlnet.FastTreePredictionWrapper = class {\n};\n\nmlnet.FastForestClassificationPredictor = class extends mlnet.FastTreePredictionWrapper {\n};\n\nmlnet.PlattCalibrator = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        this.ParamA = reader.float64();\n        this.ParamB = reader.float64();\n    }\n};\n\nmlnet.Codec = class {\n\n    constructor(reader) {\n        this.name = reader.string();\n        const size = reader.leb128();\n        const data = reader.read(size);\n        reader = new mlnet.BinaryReader(data);\n        switch (this.name) {\n            case 'Boolean': break;\n            case 'Single': break;\n            case 'Double': break;\n            case 'Byte': break;\n            case 'Int32': break;\n            case 'UInt32': break;\n            case 'Int64': break;\n            case 'TextSpan': break;\n            case 'VBuffer':\n                this.itemType = new mlnet.Codec(reader);\n                this.dims = reader.int32s(reader.int32());\n                break;\n            case 'Key':\n            case 'Key2':\n                this.itemType = new mlnet.Codec(reader);\n                this.count = reader.uint64().toNumber();\n                break;\n            default:\n                throw new mlnet.Error(`Unsupported codec '${this.name}'.`);\n        }\n    }\n\n    read(reader, count) {\n        const values = [];\n        switch (this.name) {\n            case 'Single':\n                for (let i = 0; i < count; i++) {\n                    values.push(reader.float32());\n                }\n                break;\n            case 'Int32':\n                for (let i = 0; i < count; i++) {\n                    values.push(reader.int32());\n                }\n                break;\n            case 'Int64':\n                for (let i = 0; i < count; i++) {\n                    values.push(reader.int64());\n                }\n                break;\n            default:\n                throw new mlnet.Error(`Unsupported codec read operation '${this.name}'.`);\n        }\n        return values;\n    }\n};\n\nmlnet.SequentialTransformerBase = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        this.WindowSize = reader.int32();\n        this.InitialWindowSize = reader.int32();\n        this.inputs = [];\n        this.inputs.push({ name: context.string() });\n        this.outputs = [];\n        this.outputs.push({ name: context.string() });\n        this.ConfidenceLowerBoundColumn = reader.string();\n        this.ConfidenceUpperBoundColumn = reader.string();\n        this.Type = new mlnet.Codec(reader);\n    }\n};\n\nmlnet.AnomalyDetectionStateBase = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        this.LogMartingaleUpdateBuffer = mlnet.AnomalyDetectionStateBase._deserializeFixedSizeQueueDouble(reader);\n        this.RawScoreBuffer = mlnet.AnomalyDetectionStateBase._deserializeFixedSizeQueueDouble(reader);\n        this.LogMartingaleValue = reader.float64();\n        this.SumSquaredDist = reader.float64();\n        this.MartingaleAlertCounter = reader.int32();\n    }\n\n    static _deserializeFixedSizeQueueDouble(reader) {\n        /* let capacity = */ reader.int32();\n        const count = reader.int32();\n        const queue = [];\n        for (let i = 0; i < count; i++) {\n            queue.push(reader.float64());\n        }\n        return queue;\n    }\n};\n\nmlnet.SequentialAnomalyDetectionTransformBase = class extends mlnet.SequentialTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.Martingale = reader.byte();\n        this.ThresholdScore = reader.byte();\n        this.Side = reader.byte();\n        this.PowerMartingaleEpsilon = reader.float64();\n        this.AlertThreshold = reader.float64();\n        this.State = new mlnet.AnomalyDetectionStateBase(context);\n    }\n};\n\nmlnet.TimeSeriesUtils = class {\n\n    static deserializeFixedSizeQueueSingle(reader) {\n        /* const capacity = */ reader.int32();\n        const count = reader.int32();\n        const queue = [];\n        for (let i = 0; i < count; i++) {\n            queue.push(reader.float32());\n        }\n        return queue;\n    }\n};\n\nmlnet.IidAnomalyDetectionBase = class extends mlnet.SequentialAnomalyDetectionTransformBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.WindowedBuffer = mlnet.TimeSeriesUtils.deserializeFixedSizeQueueSingle(reader);\n        this.InitialWindowedBuffer = mlnet.TimeSeriesUtils.deserializeFixedSizeQueueSingle(reader);\n    }\n};\n\nmlnet.IidAnomalyDetectionBaseWrapper = class {\n\n    constructor(context) {\n        const internalTransform = new mlnet.IidAnomalyDetectionBase(context);\n        for (const key of Object.keys(internalTransform)) {\n            this[key] = internalTransform[key];\n        }\n    }\n};\n\nmlnet.IidChangePointDetector = class extends mlnet.IidAnomalyDetectionBaseWrapper {\n};\n\nmlnet.IidSpikeDetector = class extends mlnet.IidAnomalyDetectionBaseWrapper {\n};\n\nmlnet.SequenceModelerBase = class {\n};\n\nmlnet.RankSelectionMethod = {\n    Fixed: 0,\n    Exact: 1,\n    Fact: 2\n};\n\nmlnet.AdaptiveSingularSpectrumSequenceModelerInternal = class extends mlnet.SequenceModelerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this._seriesLength = reader.int32();\n        this._windowSize = reader.int32();\n        this._trainSize = reader.int32();\n        this._rank = reader.int32();\n        this._discountFactor = reader.float32();\n        this._rankSelectionMethod = reader.byte(); // RankSelectionMethod\n        const isWeightSet = reader.byte();\n        this._alpha = reader.float32s(reader.int32());\n        if (context.modelVersionReadable >= 0x00010002) {\n            this._state = reader.float32s(reader.int32());\n        }\n        this.ShouldComputeForecastIntervals = reader.byte();\n        this._observationNoiseVariance = reader.float32();\n        this._autoregressionNoiseVariance = reader.float32();\n        this._observationNoiseMean = reader.float32();\n        this._autoregressionNoiseMean = reader.float32();\n        if (context.modelVersionReadable >= 0x00010002) {\n            this._nextPrediction = reader.float32();\n        }\n        this._maxRank = reader.int32();\n        this._shouldStablize = reader.byte();\n        this._shouldMaintainInfo = reader.byte();\n        this._maxTrendRatio = reader.float64();\n        if (isWeightSet) {\n            this._wTrans = reader.float32s(reader.int32());\n            this._y = reader.float32s(reader.int32());\n        }\n        this._buffer = mlnet.TimeSeriesUtils.deserializeFixedSizeQueueSingle(reader);\n    }\n};\n\nmlnet.SequentialForecastingTransformBase = class extends mlnet.SequentialTransformerBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this._outputLength = reader.int32();\n    }\n};\n\nmlnet.SsaForecastingBaseWrapper = class extends mlnet.SequentialForecastingTransformBase {\n\n    constructor(context) {\n        super(context);\n        const reader = context.reader;\n        this.IsAdaptive = reader.boolean();\n        this.Horizon = reader.int32();\n        this.ConfidenceLevel = reader.float32();\n        this.WindowedBuffer = mlnet.TimeSeriesUtils.deserializeFixedSizeQueueSingle(reader);\n        this.InitialWindowedBuffer = mlnet.TimeSeriesUtils.deserializeFixedSizeQueueSingle(reader);\n        this.Model = context.open('SSA');\n    }\n};\n\nmlnet.SsaForecastingTransformer = class extends mlnet.SsaForecastingBaseWrapper {\n};\n\nmlnet.ColumnSelectingTransformer = class {\n\n    constructor(context) {\n        const reader = context.reader;\n        if (context.check('DRPCOLST', 0x00010002, 0x00010002)) {\n            throw new mlnet.Error(\"'LoadDropColumnsTransform' not supported.\");\n        } else if (context.check('CHSCOLSF', 0x00010001, 0x00010001)) {\n            reader.int32(); // cbFloat\n            this.KeepHidden = this._getHiddenOption(reader.byte());\n            const count = reader.int32();\n            this.inputs = [];\n            for (let colIdx = 0; colIdx < count; colIdx++) {\n                const dst = context.string();\n                this.inputs.push(dst);\n                context.string(); // src\n                this._getHiddenOption(reader.byte()); // colKeepHidden\n            }\n        } else {\n            const keepColumns = reader.boolean();\n            this.KeepHidden = reader.boolean();\n            this.IgnoreMissing = reader.boolean();\n            const length = reader.int32();\n            this.inputs = [];\n            for (let i = 0; i < length; i++) {\n                this.inputs.push({ name: context.string() });\n            }\n            if (keepColumns) {\n                this.ColumnsToKeep = this.inputs;\n            } else {\n                this.ColumnsToDrop = this.inputs;\n            }\n        }\n    }\n\n    _getHiddenOption(value) {\n        switch (value) {\n            case 1: return true;\n            case 2: return false;\n            default: throw new mlnet.Error('Unsupported hide option specified');\n        }\n    }\n};\n\nmlnet.XGBoostMulticlass = class {};\n\nmlnet.NltTokenizeTransform = class {};\n\nmlnet.DropColumnsTransform = class {};\n\nmlnet.StopWordsTransform = class {};\n\nmlnet.CSharpTransform = class {};\n\nmlnet.GenericScoreTransform = class {};\n\nmlnet.NormalizeTransform = class {};\n\nmlnet.CdfColumnFunction = class {\n};\n\nmlnet.MultiClassNetPredictor = class {};\n\nmlnet.ProtonNNMCPred = class {};\n\nmlnet.Utility = class {\n\n    static enum(type, value) {\n        if (type) {\n            mlnet.Utility._enums = mlnet.Utility._enums || new Map();\n            if (!mlnet.Utility._enums.has(type)) {\n                let obj = mlnet;\n                const id = type.split('.');\n                while (obj && id.length > 0) {\n                    obj = obj[id.shift()];\n                }\n                if (obj) {\n                    const entries = new Map(Object.entries(obj).map(([key, value]) => [value, key]));\n                    mlnet.Utility._enums.set(type, entries);\n                } else {\n                    mlnet.Utility._enums.set(type, new Map());\n                }\n            }\n            const map = mlnet.Utility._enums.get(type);\n            if (map.has(value)) {\n                return map.get(value);\n            }\n        }\n        return value;\n    }\n};\n\nmlnet.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading ML.NET model.';\n    }\n};\n\nexport const ModelFactory = mlnet.ModelFactory;\n"
  },
  {
    "path": "source/mnn-metadata.json",
    "content": "[\n  {\n    \"name\": \"AbsVal\",\n    \"operator\": 0\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"operator\": 2\n  },\n  {\n    \"name\": \"AsString\",\n    \"operator\": 3,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"Attention\",\n    \"operator\": 299,\n    \"category\": \"Attention\"\n  },\n  {\n    \"name\": \"BatchMatMul\",\n    \"operator\": 106\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"operator\": 4,\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"BatchToSpaceND\",\n    \"operator\": 5,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Bias\",\n    \"operator\": 6,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"BinaryOp\",\n    \"operator\": 7,\n    \"attributes\": [\n      { \"name\": \"activationType\", \"type\": \"FusedActivation\" },\n      { \"name\": \"opType\", \"type\": \"BinaryOpOperation\" },\n      { \"name\": \"T\", \"type\": \"DataType\" }\n    ]\n  },\n  {\n    \"name\": \"Bnll\",\n    \"operator\": 8\n  },\n  {\n    \"name\": \"Broastcast\",\n    \"operator\": 259,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Cast\",\n    \"operator\": 9\n  },\n  {\n    \"name\": \"Concat\",\n    \"operator\": 10,\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Const\",\n    \"operator\": 11,\n    \"category\": \"Constant\"\n  },\n  {\n    \"name\": \"Conv2DBackPropFilter\",\n    \"operator\": 265,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"ConvertTensor\",\n    \"operator\": 129,\n    \"attributes\": [\n      { \"name\": \"source\", \"type\": \"MNN_DATA_FORMAT\" },\n      { \"name\": \"dest\", \"type\": \"MNN_DATA_FORMAT\" }\n    ]\n  },\n  {\n    \"name\": \"ConvInt8\",\n    \"operator\": 513,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Convolution\",\n    \"operator\": 12,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padMode\", \"type\": \"PadMode\" }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionDepthwise\",\n    \"operator\": 13,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"padMode\", \"type\": \"PadMode\" }\n    ]\n  },\n  {\n    \"name\": \"Crop\",\n    \"operator\": 14,\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"CropAndResize\",\n    \"operator\": 15,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Cubic\",\n    \"operator\": 16,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"operator\": 17,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"DeconvolutionDepthwise\",\n    \"operator\": 18,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"DepthwiseConvInt8\",\n    \"operator\": 515,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Dequantize\",\n    \"operator\": 19,\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"DetectionOutput\",\n    \"operator\": 20\n  },\n  {\n    \"name\": \"Dropout\",\n    \"operator\": 21,\n    \"category\": \"Dropout\"\n  },\n  {\n    \"name\": \"Eltwise\",\n    \"operator\": 22\n  },\n  {\n    \"name\": \"ELU\",\n    \"operator\": 23,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\" }\n    ]\n  },\n  {\n    \"name\": \"Embed\",\n    \"operator\": 24,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"Exp\",\n    \"operator\": 25\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"operator\": 26\n  },\n  {\n    \"name\": \"Fill\",\n    \"operator\": 27,\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"Flatten\",\n    \"operator\": 28,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"FloatToInt8\",\n    \"operator\": 517\n  },\n  {\n    \"name\": \"FloorMod\",\n    \"operator\": 29,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Gather\",\n    \"operator\": 30,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"GatherV2\",\n    \"operator\": 31,\n    \"category\": \"Data\"\n  },\n  {\n    \"name\": \"Im2Seq\",\n    \"operator\": 32,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"InnerProduct\",\n    \"operator\": 33,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Input\",\n    \"operator\": 34\n  },\n  {\n    \"name\": \"Int8ToFloat\",\n    \"operator\": 514\n  },\n  {\n    \"name\": \"Interp\",\n    \"operator\": 35\n  },\n  {\n    \"name\": \"Log\",\n    \"operator\": 36,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"LRN\",\n    \"operator\": 37,\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"LSTM\",\n    \"operator\": 38,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"MatMul\",\n    \"operator\": 39,\n    \"attributes\": [\n      { \"name\": \"T\", \"type\": \"DataType\" }\n    ]\n  },\n  {\n    \"name\": \"MaxLayerCount\",\n    \"operator\": 128\n  },\n  {\n    \"name\": \"Moments\",\n    \"operator\": 104,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"MVN\",\n    \"operator\": 40\n  },\n  {\n    \"name\": \"NonMaxSuppression\",\n    \"operator\": 41,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"NonMaxSuppressionV2\",\n    \"operator\": 42,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Normalize\",\n    \"operator\": 43,\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"Pack\",\n    \"operator\": 44\n  },\n  {\n    \"name\": \"Padding\",\n    \"operator\": 45,\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Permute\",\n    \"operator\": 46,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"PLUGIN\",\n    \"operator\": 256,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"PoolGrad\",\n    \"operator\": 263,\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Pooling\",\n    \"operator\": 47,\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"isGlobal\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"type\", \"type\": \"PoolType\" },\n      { \"name\": \"padType\", \"type\": \"PoolPadType\" },\n      { \"name\": \"dataType\", \"type\": \"DataType\" },\n      { \"name\": \"ceilModel\", \"type\": \"boolean\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"PoolInt8\",\n    \"operator\": 516,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Power\",\n    \"operator\": 48\n  },\n  {\n    \"name\": \"PReLU\",\n    \"operator\": 49,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"PriorBox\",\n    \"operator\": 50\n  },\n  {\n    \"name\": \"Proposal\",\n    \"operator\": 51\n  },\n  {\n    \"name\": \"QuantizedAdd\",\n    \"operator\": 1,\n    \"attributes\": [\n      { \"name\": \"activationType\", \"type\": \"FusedActivation\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizedAvgPool\",\n    \"operator\": 52,\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"QuantizedBiasAdd\",\n    \"operator\": 53\n  },\n  {\n    \"name\": \"QuantizedConcat\",\n    \"operator\": 54,\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"QuantizedDepthwiseConv2D\",\n    \"operator\": 55,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"QuantizedLogistic\",\n    \"operator\": 56,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"QuantizedMatMul\",\n    \"operator\": 57\n  },\n  {\n    \"name\": \"QuantizedMaxPool\",\n    \"operator\": 58,\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"QuantizedRelu\",\n    \"operator\": 59,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"QuantizedRelu6\",\n    \"operator\": 60,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"QuantizedReshape\",\n    \"operator\": 61,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"QuantizedSoftmax\",\n    \"operator\": 62,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"QuantizeMaxMin\",\n    \"operator\": 63\n  },\n  {\n    \"name\": \"QuantizeV2\",\n    \"operator\": 64,\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"Range\",\n    \"operator\": 65\n  },\n  {\n    \"name\": \"Rank\",\n    \"operator\": 66\n  },\n  {\n    \"name\": \"ReduceJoin\",\n    \"operator\": 67\n  },\n  {\n    \"name\": \"Reduction\",\n    \"operator\": 68\n  },\n  {\n    \"name\": \"ReLU\",\n    \"operator\": 69,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ReLU6\",\n    \"operator\": 70,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Relu6Grad\",\n    \"operator\": 262,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ReluGrad\",\n    \"operator\": 261,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"RequantizationRange\",\n    \"operator\": 71\n  },\n  {\n    \"name\": \"Requantize\",\n    \"operator\": 72\n  },\n  {\n    \"name\": \"Reshape\",\n    \"operator\": 73,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"int32[]\" },\n      { \"name\": \"dimType\", \"type\": \"MNN_DATA_FORMAT\" }\n    ]\n  },\n  {\n    \"name\": \"Resize\",\n    \"operator\": 74,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"RNN\",\n    \"operator\": 75,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"RNNSequenceGRU\",\n    \"operator\": 105,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"operator\": 76,\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Scale\",\n    \"operator\": 77,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Select\",\n    \"operator\": 257,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Selu\",\n    \"operator\": 78,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Seq2Out\",\n    \"operator\": 79,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"SetDiff1D\",\n    \"operator\": 260,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Shape\",\n    \"operator\": 80,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"operator\": 81,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Size\",\n    \"operator\": 82\n  },\n  {\n    \"name\": \"Slice\",\n    \"operator\": 83,\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"SliceTf\",\n    \"operator\": 84\n  },\n  {\n    \"name\": \"Softmax\",\n    \"operator\": 85,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftmaxGrad\",\n    \"operator\": 264,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SpaceToBatchND\",\n    \"operator\": 86,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"SpatialProduct\",\n    \"operator\": 87,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Split\",\n    \"operator\": 88\n  },\n  {\n    \"name\": \"SPP\",\n    \"operator\": 89,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"operator\": 90,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"StridedSlice\",\n    \"operator\": 91,\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"Index\", \"type\": \"DataType\" },\n      { \"name\": \"T\", \"type\": \"DataType\" }\n    ]\n  },\n  {\n    \"name\": \"StringJoin\",\n    \"operator\": 92,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"StringSplit\",\n    \"operator\": 93,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"StringToNumber\",\n    \"operator\": 94,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"TanH\",\n    \"operator\": 95,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"TfQuantizedConv2D\",\n    \"operator\": 96,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Threshold\",\n    \"operator\": 97,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Tile\",\n    \"operator\": 98\n  },\n  {\n    \"name\": \"TopKV2\",\n    \"operator\": 99,\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Transpose\",\n    \"operator\": 100,\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"UnaryOp\",\n    \"operator\": 101\n  },\n  {\n    \"name\": \"Unpack\",\n    \"operator\": 102\n  },\n  {\n    \"name\": \"Unsqueeze\",\n    \"category\": \"Transform\",\n    \"operator\": 107\n  },\n  {\n    \"name\": \"Where\",\n    \"operator\": 103\n  },\n  {\n    \"name\": \"ZerosLike\",\n    \"operator\": 258,\n    \"category\": \"Layer\"\n  }\n]"
  },
  {
    "path": "source/mnn-schema.js",
    "content": "\nexport const MNN = {};\n\nMNN.NetSource = {\n    CAFFE: 0, '0': 'CAFFE',\n    TENSORFLOW: 1, '1': 'TENSORFLOW',\n    TFLITE: 2, '2': 'TFLITE',\n    ONNX: 3, '3': 'ONNX',\n    TORCH: 4, '4': 'TORCH'\n};\n\nMNN.DataType = {\n    DT_INVALID: 0, '0': 'DT_INVALID',\n    DT_FLOAT: 1, '1': 'DT_FLOAT',\n    DT_DOUBLE: 2, '2': 'DT_DOUBLE',\n    DT_INT32: 3, '3': 'DT_INT32',\n    DT_UINT8: 4, '4': 'DT_UINT8',\n    DT_INT16: 5, '5': 'DT_INT16',\n    DT_INT8: 6, '6': 'DT_INT8',\n    DT_STRING: 7, '7': 'DT_STRING',\n    DT_COMPLEX64: 8, '8': 'DT_COMPLEX64',\n    DT_INT64: 9, '9': 'DT_INT64',\n    DT_BOOL: 10, '10': 'DT_BOOL',\n    DT_QINT8: 11, '11': 'DT_QINT8',\n    DT_QUINT8: 12, '12': 'DT_QUINT8',\n    DT_QINT32: 13, '13': 'DT_QINT32',\n    DT_BFLOAT16: 14, '14': 'DT_BFLOAT16',\n    DT_QINT16: 15, '15': 'DT_QINT16',\n    DT_QUINT16: 16, '16': 'DT_QUINT16',\n    DT_UINT16: 17, '17': 'DT_UINT16',\n    DT_COMPLEX128: 18, '18': 'DT_COMPLEX128',\n    DT_HALF: 19, '19': 'DT_HALF',\n    DT_RESOURCE: 20, '20': 'DT_RESOURCE',\n    DT_VARIANT: 21, '21': 'DT_VARIANT'\n};\n\nMNN.MNN_DATA_FORMAT = {\n    NCHW: 0, '0': 'NCHW',\n    NHWC: 1, '1': 'NHWC',\n    NC4HW4: 2, '2': 'NC4HW4',\n    NHWC4: 3, '3': 'NHWC4',\n    UNKNOWN: 4, '4': 'UNKNOWN'\n};\n\nMNN.Blob = class Blob {\n\n    static decode(reader, position) {\n        const $ = new MNN.Blob();\n        $.dims = reader.array(position, 4, Int32Array);\n        $.dataFormat = reader.int8_(position, 6, 0);\n        $.dataType = reader.int32_(position, 8, 1);\n        $.uint8s = reader.array(position, 10, Uint8Array);\n        $.int8s = reader.array(position, 12, Int8Array);\n        $.int32s = reader.array(position, 14, Int32Array);\n        $.int64s = reader.int64s_(position, 16);\n        $.float32s = reader.array(position, 18, Float32Array);\n        $.strings = reader.strings_(position, 20);\n        $.external = reader.int64s_(position, 22);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Blob();\n        $.dims = reader.array(json.dims, Int32Array);\n        $.dataFormat = MNN.MNN_DATA_FORMAT[json.dataFormat];\n        $.dataType = MNN.DataType[json.dataType];\n        $.uint8s = reader.array(json.uint8s, Uint8Array);\n        $.int8s = reader.array(json.int8s, Int8Array);\n        $.int32s = reader.array(json.int32s, Int32Array);\n        $.int64s = reader.array(json.int64s);\n        $.float32s = reader.array(json.float32s, Float32Array);\n        $.strings = reader.array(json.strings);\n        $.external = reader.array(json.external);\n        return $;\n    }\n};\n\nMNN.ListValue = class ListValue {\n\n    static decode(reader, position) {\n        const $ = new MNN.ListValue();\n        $.s = reader.strings_(position, 4);\n        $.i = reader.array(position, 6, Int32Array);\n        $.f = reader.array(position, 8, Float32Array);\n        $.b = reader.bools_(position, 10);\n        $.type = reader.array(position, 12, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ListValue();\n        $.s = reader.array(json.s);\n        $.i = reader.array(json.i, Int32Array);\n        $.f = reader.array(json.f, Float32Array);\n        $.b = reader.array(json.b);\n        $.type = reader.objects(json.type, MNN.DataType);\n        return $;\n    }\n};\n\nMNN.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new MNN.Attribute();\n        $.s = reader.string_(position, 4, null);\n        $.i = reader.int32_(position, 6, 0);\n        $.b = reader.bool_(position, 8, false);\n        $.key = reader.string_(position, 10, null);\n        $.type = reader.int32_(position, 12, 0);\n        $.f = reader.float32_(position, 14, 0);\n        $.tensor = reader.table(position, 16, MNN.Blob);\n        $.list = reader.table(position, 18, MNN.ListValue);\n        $.func = reader.table(position, 20, MNN.NamedAttrList);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Attribute();\n        $.s = reader.value(json.s, null);\n        $.i = reader.value(json.i, 0);\n        $.b = reader.value(json.b, false);\n        $.key = reader.value(json.key, null);\n        $.type = MNN.DataType[json.type];\n        $.f = reader.value(json.f, 0);\n        $.tensor = reader.object(json.tensor, MNN.Blob);\n        $.list = reader.object(json.list, MNN.ListValue);\n        $.func = reader.object(json.func, MNN.NamedAttrList);\n        return $;\n    }\n};\n\nMNN.NamedAttrList = class NamedAttrList {\n\n    static decode(reader, position) {\n        const $ = new MNN.NamedAttrList();\n        $.name = reader.string_(position, 4, null);\n        $.attr = reader.tables(position, 6, MNN.Attribute);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.NamedAttrList();\n        $.name = reader.value(json.name, null);\n        $.attr = reader.objects(json.attr, MNN.Attribute);\n        return $;\n    }\n};\n\nMNN.PadMode = {\n    CAFFE: 0, '0': 'CAFFE',\n    VALID: 1, '1': 'VALID',\n    SAME: 2, '2': 'SAME'\n};\n\nMNN.Convolution2DCommon = class Convolution2DCommon {\n\n    static decode(reader, position) {\n        const $ = new MNN.Convolution2DCommon();\n        $.padX = reader.int32_(position, 4, 0);\n        $.padY = reader.int32_(position, 6, 0);\n        $.kernelX = reader.int32_(position, 8, 1);\n        $.kernelY = reader.int32_(position, 10, 1);\n        $.strideX = reader.int32_(position, 12, 1);\n        $.strideY = reader.int32_(position, 14, 1);\n        $.dilateX = reader.int32_(position, 16, 1);\n        $.dilateY = reader.int32_(position, 18, 1);\n        $.padMode = reader.int8_(position, 20, 0);\n        $.group = reader.int32_(position, 22, 1);\n        $.outputCount = reader.int32_(position, 24, 0);\n        $.inputCount = reader.int32_(position, 26, 0);\n        $.relu = reader.bool_(position, 28, false);\n        $.relu6 = reader.bool_(position, 30, false);\n        $.pads = reader.array(position, 32, Int32Array);\n        $.outPads = reader.array(position, 34, Int32Array);\n        $.hasOutputShape = reader.bool_(position, 36, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Convolution2DCommon();\n        $.padX = reader.value(json.padX, 0);\n        $.padY = reader.value(json.padY, 0);\n        $.kernelX = reader.value(json.kernelX, 1);\n        $.kernelY = reader.value(json.kernelY, 1);\n        $.strideX = reader.value(json.strideX, 1);\n        $.strideY = reader.value(json.strideY, 1);\n        $.dilateX = reader.value(json.dilateX, 1);\n        $.dilateY = reader.value(json.dilateY, 1);\n        $.padMode = MNN.PadMode[json.padMode];\n        $.group = reader.value(json.group, 1);\n        $.outputCount = reader.value(json.outputCount, 0);\n        $.inputCount = reader.value(json.inputCount, 0);\n        $.relu = reader.value(json.relu, false);\n        $.relu6 = reader.value(json.relu6, false);\n        $.pads = reader.array(json.pads, Int32Array);\n        $.outPads = reader.array(json.outPads, Int32Array);\n        $.hasOutputShape = reader.value(json.hasOutputShape, false);\n        return $;\n    }\n};\n\nMNN.Convolution3DCommon = class Convolution3DCommon {\n\n    static decode(reader, position) {\n        const $ = new MNN.Convolution3DCommon();\n        $.dilates = reader.array(position, 4, Int32Array);\n        $.strides = reader.array(position, 6, Int32Array);\n        $.kernels = reader.array(position, 8, Int32Array);\n        $.pads = reader.array(position, 10, Int32Array);\n        $.padMode = reader.int8_(position, 12, 0);\n        $.inputCount = reader.int32_(position, 14, 0);\n        $.outputCount = reader.int32_(position, 16, 0);\n        $.relu = reader.bool_(position, 18, false);\n        $.relu6 = reader.bool_(position, 20, false);\n        $.group = reader.int32_(position, 22, 1);\n        $.outPads = reader.array(position, 24, Int32Array);\n        $.hasOutputShape = reader.bool_(position, 26, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Convolution3DCommon();\n        $.dilates = reader.array(json.dilates, Int32Array);\n        $.strides = reader.array(json.strides, Int32Array);\n        $.kernels = reader.array(json.kernels, Int32Array);\n        $.pads = reader.array(json.pads, Int32Array);\n        $.padMode = MNN.PadMode[json.padMode];\n        $.inputCount = reader.value(json.inputCount, 0);\n        $.outputCount = reader.value(json.outputCount, 0);\n        $.relu = reader.value(json.relu, false);\n        $.relu6 = reader.value(json.relu6, false);\n        $.group = reader.value(json.group, 1);\n        $.outPads = reader.array(json.outPads, Int32Array);\n        $.hasOutputShape = reader.value(json.hasOutputShape, false);\n        return $;\n    }\n};\n\nMNN.SparseAlgo = {\n    RANDOM: 0, '0': 'RANDOM',\n    SIMD_OC: 1, '1': 'SIMD_OC'\n};\n\nMNN.SparseCommon = class SparseCommon {\n\n    static decode(reader, position) {\n        const $ = new MNN.SparseCommon();\n        $.method = reader.int8_(position, 4, 0);\n        $.args = reader.tables(position, 6, MNN.Attribute);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.SparseCommon();\n        $.method = MNN.SparseAlgo[json.method];\n        $.args = reader.objects(json.args, MNN.Attribute);\n        return $;\n    }\n};\n\nMNN.IDSTQuan = class IDSTQuan {\n\n    static decode(reader, position) {\n        const $ = new MNN.IDSTQuan();\n        $.buffer = reader.array(position, 4, Int8Array);\n        $.alpha = reader.array(position, 6, Float32Array);\n        $.type = reader.int32_(position, 8, 0);\n        $.useInt32 = reader.bool_(position, 10, false);\n        $.quantScale = reader.float32_(position, 12, 0);\n        $.scaleIn = reader.float32_(position, 14, 0);\n        $.scaleOut = reader.float32_(position, 16, 0);\n        $.aMaxOrBits = reader.int32_(position, 18, 0);\n        $.aMin = reader.int32_(position, 20, 0);\n        $.readType = reader.int32_(position, 22, 0);\n        $.has_scaleInt = reader.bool_(position, 24, false);\n        $.shapeInt32 = reader.bool_(position, 26, false);\n        $.weightSize = reader.uint32_(position, 28, 0);\n        $.index = reader.array(position, 30, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.IDSTQuan();\n        $.buffer = reader.array(json.buffer, Int8Array);\n        $.alpha = reader.array(json.alpha, Float32Array);\n        $.type = reader.value(json.type, 0);\n        $.useInt32 = reader.value(json.useInt32, false);\n        $.quantScale = reader.value(json.quantScale, 0);\n        $.scaleIn = reader.value(json.scaleIn, 0);\n        $.scaleOut = reader.value(json.scaleOut, 0);\n        $.aMaxOrBits = reader.value(json.aMaxOrBits, 0);\n        $.aMin = reader.value(json.aMin, 0);\n        $.readType = reader.value(json.readType, 0);\n        $.has_scaleInt = reader.value(json.has_scaleInt, false);\n        $.shapeInt32 = reader.value(json.shapeInt32, false);\n        $.weightSize = reader.value(json.weightSize, 0);\n        $.index = reader.array(json.index, Uint32Array);\n        return $;\n    }\n};\n\nMNN.QuantizeAlgo = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    OVERFLOW_AWARE: 1, '1': 'OVERFLOW_AWARE',\n    WINOGRAD_AWARE: 2, '2': 'WINOGRAD_AWARE'\n};\n\nMNN.QuantizedFloatParam = class QuantizedFloatParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedFloatParam();\n        $.weight = reader.array(position, 4, Int8Array);\n        $.bias = reader.array(position, 6, Int32Array);\n        $.scale = reader.array(position, 8, Float32Array);\n        $.tensorScale = reader.array(position, 10, Float32Array);\n        $.method = reader.int8_(position, 12, 0);\n        $.nbits = reader.int32_(position, 14, 8);\n        $.zeroPoint = reader.int8_(position, 16, 0);\n        $.outputZeroPoint = reader.int8_(position, 18, 0);\n        $.clampMin = reader.int8_(position, 20, -128);\n        $.clampMax = reader.int8_(position, 22, 127);\n        $.winogradAttr = reader.array(position, 24, Int32Array);\n        $.outputDataType = reader.int32_(position, 26, 6);\n        $.floatzeros = reader.array(position, 28, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedFloatParam();\n        $.weight = reader.array(json.weight, Int8Array);\n        $.bias = reader.array(json.bias, Int32Array);\n        $.scale = reader.array(json.scale, Float32Array);\n        $.tensorScale = reader.array(json.tensorScale, Float32Array);\n        $.method = MNN.QuantizeAlgo[json.method];\n        $.nbits = reader.value(json.nbits, 8);\n        $.zeroPoint = reader.value(json.zeroPoint, 0);\n        $.outputZeroPoint = reader.value(json.outputZeroPoint, 0);\n        $.clampMin = reader.value(json.clampMin, -128);\n        $.clampMax = reader.value(json.clampMax, 127);\n        $.winogradAttr = reader.array(json.winogradAttr, Int32Array);\n        $.outputDataType = MNN.DataType[json.outputDataType];\n        $.floatzeros = reader.array(json.floatzeros, Float32Array);\n        return $;\n    }\n};\n\nMNN.Convolution2D = class Convolution2D {\n\n    static decode(reader, position) {\n        const $ = new MNN.Convolution2D();\n        $.common = reader.table(position, 4, MNN.Convolution2DCommon);\n        $.weight = reader.array(position, 6, Float32Array);\n        $.bias = reader.array(position, 8, Float32Array);\n        $.quanParameter = reader.table(position, 10, MNN.IDSTQuan);\n        $.symmetricQuan = reader.table(position, 12, MNN.QuantizedFloatParam);\n        $.sparseParameter = reader.table(position, 14, MNN.SparseCommon);\n        $.external = reader.int64s_(position, 16);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Convolution2D();\n        $.common = reader.object(json.common, MNN.Convolution2DCommon);\n        $.weight = reader.array(json.weight, Float32Array);\n        $.bias = reader.array(json.bias, Float32Array);\n        $.quanParameter = reader.object(json.quanParameter, MNN.IDSTQuan);\n        $.symmetricQuan = reader.object(json.symmetricQuan, MNN.QuantizedFloatParam);\n        $.sparseParameter = reader.object(json.sparseParameter, MNN.SparseCommon);\n        $.external = reader.array(json.external);\n        return $;\n    }\n};\n\nMNN.Convolution3D = class Convolution3D {\n\n    static decode(reader, position) {\n        const $ = new MNN.Convolution3D();\n        $.common = reader.table(position, 4, MNN.Convolution3DCommon);\n        $.weight = reader.array(position, 6, Float32Array);\n        $.bias = reader.array(position, 8, Float32Array);\n        $.external = reader.int64s_(position, 10);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Convolution3D();\n        $.common = reader.object(json.common, MNN.Convolution3DCommon);\n        $.weight = reader.array(json.weight, Float32Array);\n        $.bias = reader.array(json.bias, Float32Array);\n        $.external = reader.array(json.external);\n        return $;\n    }\n};\n\nMNN.InnerProduct = class InnerProduct {\n\n    static decode(reader, position) {\n        const $ = new MNN.InnerProduct();\n        $.outputCount = reader.int32_(position, 4, 0);\n        $.biasTerm = reader.int32_(position, 6, 0);\n        $.weightSize = reader.int32_(position, 8, 0);\n        $.weight = reader.array(position, 10, Float32Array);\n        $.bias = reader.array(position, 12, Float32Array);\n        $.axis = reader.int32_(position, 14, 0);\n        $.transpose = reader.bool_(position, 16, false);\n        $.quanParameter = reader.table(position, 18, MNN.IDSTQuan);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.InnerProduct();\n        $.outputCount = reader.value(json.outputCount, 0);\n        $.biasTerm = reader.value(json.biasTerm, 0);\n        $.weightSize = reader.value(json.weightSize, 0);\n        $.weight = reader.array(json.weight, Float32Array);\n        $.bias = reader.array(json.bias, Float32Array);\n        $.axis = reader.value(json.axis, 0);\n        $.transpose = reader.value(json.transpose, false);\n        $.quanParameter = reader.object(json.quanParameter, MNN.IDSTQuan);\n        return $;\n    }\n};\n\nMNN.PoolType = {\n    MAXPOOL: 0, '0': 'MAXPOOL',\n    AVEPOOL: 1, '1': 'AVEPOOL'\n};\n\nMNN.PoolPadType = {\n    CAFFE: 0, '0': 'CAFFE',\n    VALID: 1, '1': 'VALID',\n    SAME: 2, '2': 'SAME'\n};\n\nMNN.AvgPoolCountType = {\n    DEFAULT: 0, '0': 'DEFAULT',\n    INCLUDE_PADDING: 1, '1': 'INCLUDE_PADDING',\n    EXCLUDE_PADDING: 2, '2': 'EXCLUDE_PADDING'\n};\n\nMNN.Pool = class Pool {\n\n    static decode(reader, position) {\n        const $ = new MNN.Pool();\n        $.padX = reader.int32_(position, 4, 0);\n        $.padY = reader.int32_(position, 6, 0);\n        $.isGlobal = reader.bool_(position, 8, false);\n        $.kernelX = reader.int32_(position, 10, 0);\n        $.kernelY = reader.int32_(position, 12, 0);\n        $.strideX = reader.int32_(position, 14, 0);\n        $.strideY = reader.int32_(position, 16, 0);\n        $.type = reader.int8_(position, 18, 0);\n        $.padType = reader.int8_(position, 20, 0);\n        $.dataType = reader.int32_(position, 22, 1);\n        $.ceilModel = reader.bool_(position, 24, true);\n        $.pads = reader.array(position, 26, Int32Array);\n        $.countType = reader.int8_(position, 28, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Pool();\n        $.padX = reader.value(json.padX, 0);\n        $.padY = reader.value(json.padY, 0);\n        $.isGlobal = reader.value(json.isGlobal, false);\n        $.kernelX = reader.value(json.kernelX, 0);\n        $.kernelY = reader.value(json.kernelY, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.type = MNN.PoolType[json.type];\n        $.padType = MNN.PoolPadType[json.padType];\n        $.dataType = MNN.DataType[json.dataType];\n        $.ceilModel = reader.value(json.ceilModel, true);\n        $.pads = reader.array(json.pads, Int32Array);\n        $.countType = MNN.AvgPoolCountType[json.countType];\n        return $;\n    }\n};\n\nMNN.Pool3D = class Pool3D {\n\n    static decode(reader, position) {\n        const $ = new MNN.Pool3D();\n        $.strides = reader.array(position, 4, Int32Array);\n        $.kernels = reader.array(position, 6, Int32Array);\n        $.pads = reader.array(position, 8, Int32Array);\n        $.type = reader.int8_(position, 10, 0);\n        $.padType = reader.int8_(position, 12, 0);\n        $.isGlobal = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Pool3D();\n        $.strides = reader.array(json.strides, Int32Array);\n        $.kernels = reader.array(json.kernels, Int32Array);\n        $.pads = reader.array(json.pads, Int32Array);\n        $.type = MNN.PoolType[json.type];\n        $.padType = MNN.PoolPadType[json.padType];\n        $.isGlobal = reader.value(json.isGlobal, false);\n        return $;\n    }\n};\n\nMNN.Relu = class Relu {\n\n    static decode(reader, position) {\n        const $ = new MNN.Relu();\n        $.slope = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Relu();\n        $.slope = reader.value(json.slope, 0);\n        return $;\n    }\n};\n\nMNN.Relu6 = class Relu6 {\n\n    static decode(reader, position) {\n        const $ = new MNN.Relu6();\n        $.minValue = reader.float32_(position, 4, 0);\n        $.maxValue = reader.float32_(position, 6, 6);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Relu6();\n        $.minValue = reader.value(json.minValue, 0);\n        $.maxValue = reader.value(json.maxValue, 6);\n        return $;\n    }\n};\n\nMNN.PRelu = class PRelu {\n\n    static decode(reader, position) {\n        const $ = new MNN.PRelu();\n        $.slopeCount = reader.int32_(position, 4, 0);\n        $.slope = reader.array(position, 6, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.PRelu();\n        $.slopeCount = reader.value(json.slopeCount, 0);\n        $.slope = reader.array(json.slope, Float32Array);\n        return $;\n    }\n};\n\nMNN.ELU = class ELU {\n\n    static decode(reader, position) {\n        const $ = new MNN.ELU();\n        $.alpha = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ELU();\n        $.alpha = reader.value(json.alpha, 0);\n        return $;\n    }\n};\n\nMNN.LRN = class LRN {\n\n    static decode(reader, position) {\n        const $ = new MNN.LRN();\n        $.regionType = reader.int32_(position, 4, 0);\n        $.localSize = reader.int32_(position, 6, 0);\n        $.alpha = reader.float32_(position, 8, 0);\n        $.beta = reader.float32_(position, 10, 0);\n        $.bias = reader.float32_(position, 12, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.LRN();\n        $.regionType = reader.value(json.regionType, 0);\n        $.localSize = reader.value(json.localSize, 0);\n        $.alpha = reader.value(json.alpha, 0);\n        $.beta = reader.value(json.beta, 0);\n        $.bias = reader.value(json.bias, 1);\n        return $;\n    }\n};\n\nMNN.ArgMax = class ArgMax {\n\n    static decode(reader, position) {\n        const $ = new MNN.ArgMax();\n        $.outMaxVal = reader.int32_(position, 4, 0);\n        $.topK = reader.int32_(position, 6, 0);\n        $.axis = reader.int32_(position, 8, 0);\n        $.softmaxThreshold = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ArgMax();\n        $.outMaxVal = reader.value(json.outMaxVal, 0);\n        $.topK = reader.value(json.topK, 0);\n        $.axis = reader.value(json.axis, 0);\n        $.softmaxThreshold = reader.value(json.softmaxThreshold, 0);\n        return $;\n    }\n};\n\nMNN.Axis = class Axis {\n\n    static decode(reader, position) {\n        const $ = new MNN.Axis();\n        $.axis = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Axis();\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\nMNN.Input = class Input {\n\n    static decode(reader, position) {\n        const $ = new MNN.Input();\n        $.dims = reader.array(position, 4, Int32Array);\n        $.dtype = reader.int32_(position, 6, 1);\n        $.dformat = reader.int8_(position, 8, 2);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Input();\n        $.dims = reader.array(json.dims, Int32Array);\n        $.dtype = MNN.DataType[json.dtype];\n        $.dformat = MNN.MNN_DATA_FORMAT[json.dformat];\n        return $;\n    }\n};\n\nMNN.LSTM = class LSTM {\n\n    static decode(reader, position) {\n        const $ = new MNN.LSTM();\n        $.outputCount = reader.int32_(position, 4, 0);\n        $.weightSize = reader.int32_(position, 6, 0);\n        $.clippingThreshold = reader.float32_(position, 8, 0);\n        $.weightI = reader.table(position, 10, MNN.Blob);\n        $.weightH = reader.table(position, 12, MNN.Blob);\n        $.bias = reader.table(position, 14, MNN.Blob);\n        $.weightIQ = reader.table(position, 16, MNN.Blob);\n        $.weightIA = reader.table(position, 18, MNN.Blob);\n        $.quantScale = reader.float32_(position, 20, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.LSTM();\n        $.outputCount = reader.value(json.outputCount, 0);\n        $.weightSize = reader.value(json.weightSize, 0);\n        $.clippingThreshold = reader.value(json.clippingThreshold, 0);\n        $.weightI = reader.object(json.weightI, MNN.Blob);\n        $.weightH = reader.object(json.weightH, MNN.Blob);\n        $.bias = reader.object(json.bias, MNN.Blob);\n        $.weightIQ = reader.object(json.weightIQ, MNN.Blob);\n        $.weightIA = reader.object(json.weightIA, MNN.Blob);\n        $.quantScale = reader.value(json.quantScale, 0);\n        return $;\n    }\n};\n\nMNN.Slice = class Slice {\n\n    static decode(reader, position) {\n        const $ = new MNN.Slice();\n        $.axis = reader.int32_(position, 4, 0);\n        $.slicePoints = reader.array(position, 6, Int32Array);\n        $.sourceType = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Slice();\n        $.axis = reader.value(json.axis, 0);\n        $.slicePoints = reader.array(json.slicePoints, Int32Array);\n        $.sourceType = MNN.NetSource[json.sourceType];\n        return $;\n    }\n};\n\nMNN.BatchNorm = class BatchNorm {\n\n    static decode(reader, position) {\n        const $ = new MNN.BatchNorm();\n        $.channels = reader.int32_(position, 4, 0);\n        $.slopeData = reader.array(position, 6, Float32Array);\n        $.meanData = reader.array(position, 8, Float32Array);\n        $.varData = reader.array(position, 10, Float32Array);\n        $.biasData = reader.array(position, 12, Float32Array);\n        $.Adata = reader.array(position, 14, Float32Array);\n        $.Bdata = reader.array(position, 16, Float32Array);\n        $.epsilon = reader.float32_(position, 18, 0.001);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.BatchNorm();\n        $.channels = reader.value(json.channels, 0);\n        $.slopeData = reader.array(json.slopeData, Float32Array);\n        $.meanData = reader.array(json.meanData, Float32Array);\n        $.varData = reader.array(json.varData, Float32Array);\n        $.biasData = reader.array(json.biasData, Float32Array);\n        $.Adata = reader.array(json.Adata, Float32Array);\n        $.Bdata = reader.array(json.Bdata, Float32Array);\n        $.epsilon = reader.value(json.epsilon, 0.001);\n        return $;\n    }\n};\n\nMNN.Scale = class Scale {\n\n    static decode(reader, position) {\n        const $ = new MNN.Scale();\n        $.channels = reader.int32_(position, 4, 0);\n        $.scaleData = reader.array(position, 6, Float32Array);\n        $.biasData = reader.array(position, 8, Float32Array);\n        $.external = reader.int64s_(position, 10);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Scale();\n        $.channels = reader.value(json.channels, 0);\n        $.scaleData = reader.array(json.scaleData, Float32Array);\n        $.biasData = reader.array(json.biasData, Float32Array);\n        $.external = reader.array(json.external);\n        return $;\n    }\n};\n\nMNN.EltwiseType = {\n    PROD: 0, '0': 'PROD',\n    SUM: 1, '1': 'SUM',\n    MAXIMUM: 2, '2': 'MAXIMUM',\n    SUB: 3, '3': 'SUB'\n};\n\nMNN.Eltwise = class Eltwise {\n\n    static decode(reader, position) {\n        const $ = new MNN.Eltwise();\n        $.type = reader.int8_(position, 4, 0);\n        $.coeff = reader.array(position, 6, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Eltwise();\n        $.type = MNN.EltwiseType[json.type];\n        $.coeff = reader.array(json.coeff, Float32Array);\n        return $;\n    }\n};\n\nMNN.Flatten = class Flatten {\n\n    static decode(reader, position) {\n        const $ = new MNN.Flatten();\n        $.axis = reader.int32_(position, 4, 0);\n        $.endAxis = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Flatten();\n        $.axis = reader.value(json.axis, 0);\n        $.endAxis = reader.value(json.endAxis, 0);\n        return $;\n    }\n};\n\nMNN.Permute = class Permute {\n\n    static decode(reader, position) {\n        const $ = new MNN.Permute();\n        $.dims = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Permute();\n        $.dims = reader.array(json.dims, Int32Array);\n        return $;\n    }\n};\n\nMNN.Reshape = class Reshape {\n\n    static decode(reader, position) {\n        const $ = new MNN.Reshape();\n        $.dims = reader.array(position, 4, Int32Array);\n        $.dimType = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Reshape();\n        $.dims = reader.array(json.dims, Int32Array);\n        $.dimType = MNN.MNN_DATA_FORMAT[json.dimType];\n        return $;\n    }\n};\n\nMNN.DetectionOutput = class DetectionOutput {\n\n    static decode(reader, position) {\n        const $ = new MNN.DetectionOutput();\n        $.classCount = reader.int32_(position, 4, 0);\n        $.nmsThresholdold = reader.float32_(position, 6, 0);\n        $.nmsTopK = reader.int32_(position, 8, 0);\n        $.keepTopK = reader.int32_(position, 10, 0);\n        $.confidenceThreshold = reader.float32_(position, 12, 0);\n        $.shareLocation = reader.int32_(position, 14, 0);\n        $.backgroundLable = reader.int32_(position, 16, 0);\n        $.varianceEncodedTarget = reader.int32_(position, 18, 0);\n        $.codeType = reader.int32_(position, 20, 0);\n        $.objectnessScore = reader.float32_(position, 22, 0.01);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.DetectionOutput();\n        $.classCount = reader.value(json.classCount, 0);\n        $.nmsThresholdold = reader.value(json.nmsThresholdold, 0);\n        $.nmsTopK = reader.value(json.nmsTopK, 0);\n        $.keepTopK = reader.value(json.keepTopK, 0);\n        $.confidenceThreshold = reader.value(json.confidenceThreshold, 0);\n        $.shareLocation = reader.value(json.shareLocation, 0);\n        $.backgroundLable = reader.value(json.backgroundLable, 0);\n        $.varianceEncodedTarget = reader.value(json.varianceEncodedTarget, 0);\n        $.codeType = reader.value(json.codeType, 0);\n        $.objectnessScore = reader.value(json.objectnessScore, 0.01);\n        return $;\n    }\n};\n\nMNN.RoiParameters = class RoiParameters {\n\n    static decode(reader, position) {\n        const $ = new MNN.RoiParameters();\n        $.pooledWidth = reader.int32_(position, 4, 0);\n        $.pooledHeight = reader.int32_(position, 6, 0);\n        $.spatialScale = reader.float32_(position, 8, 0);\n        $.samplingRatio = reader.int32_(position, 10, -1);\n        $.aligned = reader.bool_(position, 12, false);\n        $.poolType = reader.int8_(position, 14, 1);\n        $.outputGrad = reader.bool_(position, 16, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.RoiParameters();\n        $.pooledWidth = reader.value(json.pooledWidth, 0);\n        $.pooledHeight = reader.value(json.pooledHeight, 0);\n        $.spatialScale = reader.value(json.spatialScale, 0);\n        $.samplingRatio = reader.value(json.samplingRatio, -1);\n        $.aligned = reader.value(json.aligned, false);\n        $.poolType = MNN.PoolType[json.poolType];\n        $.outputGrad = reader.value(json.outputGrad, false);\n        return $;\n    }\n};\n\nMNN.Proposal = class Proposal {\n\n    static decode(reader, position) {\n        const $ = new MNN.Proposal();\n        $.featStride = reader.int32_(position, 4, 0);\n        $.baseSize = reader.int32_(position, 6, 0);\n        $.preNmsTopN = reader.int32_(position, 8, 0);\n        $.afterNmsTopN = reader.int32_(position, 10, 0);\n        $.nmsThreshold = reader.float32_(position, 12, 0);\n        $.minSize = reader.int32_(position, 14, 0);\n        $.ratios = reader.table(position, 16, MNN.Blob);\n        $.scales = reader.table(position, 18, MNN.Blob);\n        $.anchors = reader.table(position, 20, MNN.Blob);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Proposal();\n        $.featStride = reader.value(json.featStride, 0);\n        $.baseSize = reader.value(json.baseSize, 0);\n        $.preNmsTopN = reader.value(json.preNmsTopN, 0);\n        $.afterNmsTopN = reader.value(json.afterNmsTopN, 0);\n        $.nmsThreshold = reader.value(json.nmsThreshold, 0);\n        $.minSize = reader.value(json.minSize, 0);\n        $.ratios = reader.object(json.ratios, MNN.Blob);\n        $.scales = reader.object(json.scales, MNN.Blob);\n        $.anchors = reader.object(json.anchors, MNN.Blob);\n        return $;\n    }\n};\n\nMNN.CoordinateTransformationMode = {\n    NotSet: 0, '0': 'NotSet',\n    AlignCorners: 1, '1': 'AlignCorners',\n    HalfPixels: 2, '2': 'HalfPixels',\n    PytorchHalfPixels: 3, '3': 'PytorchHalfPixels',\n    Asymmetric: 4, '4': 'Asymmetric',\n    TensorflowHalfPixels: 5, '5': 'TensorflowHalfPixels',\n    TensorflowCropAndResize: 6, '6': 'TensorflowCropAndResize'\n};\n\nMNN.Interp = class Interp {\n\n    static decode(reader, position) {\n        const $ = new MNN.Interp();\n        $.widthScale = reader.float32_(position, 4, 0);\n        $.heightScale = reader.float32_(position, 6, 0);\n        $.outputWidth = reader.int32_(position, 8, 0);\n        $.outputHeight = reader.int32_(position, 10, 0);\n        $.resizeType = reader.int32_(position, 12, 0);\n        $.alignCorners = reader.bool_(position, 14, false);\n        $.halfPixelCenters = reader.bool_(position, 16, false);\n        $.widthOffset = reader.float32_(position, 18, 0);\n        $.heightOffset = reader.float32_(position, 20, 0);\n        $.cubicCoeffA = reader.float32_(position, 22, -0.75);\n        $.ctm = reader.int8_(position, 24, 0);\n        $.depthScale = reader.float32_(position, 26, 0);\n        $.outputDepth = reader.int32_(position, 28, 0);\n        $.depthOffset = reader.float32_(position, 30, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Interp();\n        $.widthScale = reader.value(json.widthScale, 0);\n        $.heightScale = reader.value(json.heightScale, 0);\n        $.outputWidth = reader.value(json.outputWidth, 0);\n        $.outputHeight = reader.value(json.outputHeight, 0);\n        $.resizeType = reader.value(json.resizeType, 0);\n        $.alignCorners = reader.value(json.alignCorners, false);\n        $.halfPixelCenters = reader.value(json.halfPixelCenters, false);\n        $.widthOffset = reader.value(json.widthOffset, 0);\n        $.heightOffset = reader.value(json.heightOffset, 0);\n        $.cubicCoeffA = reader.value(json.cubicCoeffA, -0.75);\n        $.ctm = MNN.CoordinateTransformationMode[json.ctm];\n        $.depthScale = reader.value(json.depthScale, 0);\n        $.outputDepth = reader.value(json.outputDepth, 0);\n        $.depthOffset = reader.value(json.depthOffset, 0);\n        return $;\n    }\n};\n\nMNN.Resize = class Resize {\n\n    static decode(reader, position) {\n        const $ = new MNN.Resize();\n        $.xScale = reader.float32_(position, 4, 0);\n        $.yScale = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Resize();\n        $.xScale = reader.value(json.xScale, 0);\n        $.yScale = reader.value(json.yScale, 0);\n        return $;\n    }\n};\n\nMNN.PriorBox = class PriorBox {\n\n    static decode(reader, position) {\n        const $ = new MNN.PriorBox();\n        $.minSizes = reader.array(position, 4, Float32Array);\n        $.maxSizes = reader.array(position, 6, Float32Array);\n        $.aspectRatios = reader.array(position, 8, Float32Array);\n        $.variances = reader.array(position, 10, Float32Array);\n        $.flip = reader.bool_(position, 12, false);\n        $.clip = reader.bool_(position, 14, false);\n        $.imageWidth = reader.int32_(position, 16, 0);\n        $.imageHeight = reader.int32_(position, 18, 0);\n        $.stepWidth = reader.int32_(position, 20, 0);\n        $.stepHeight = reader.int32_(position, 22, 0);\n        $.offset = reader.float32_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.PriorBox();\n        $.minSizes = reader.array(json.minSizes, Float32Array);\n        $.maxSizes = reader.array(json.maxSizes, Float32Array);\n        $.aspectRatios = reader.array(json.aspectRatios, Float32Array);\n        $.variances = reader.array(json.variances, Float32Array);\n        $.flip = reader.value(json.flip, false);\n        $.clip = reader.value(json.clip, false);\n        $.imageWidth = reader.value(json.imageWidth, 0);\n        $.imageHeight = reader.value(json.imageHeight, 0);\n        $.stepWidth = reader.value(json.stepWidth, 0);\n        $.stepHeight = reader.value(json.stepHeight, 0);\n        $.offset = reader.value(json.offset, 0);\n        return $;\n    }\n};\n\nMNN.Normalize = class Normalize {\n\n    static decode(reader, position) {\n        const $ = new MNN.Normalize();\n        $.acrossSpatial = reader.int32_(position, 4, 0);\n        $.channelShared = reader.int32_(position, 6, 0);\n        $.eps = reader.float32_(position, 8, 0);\n        $.scale = reader.array(position, 10, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Normalize();\n        $.acrossSpatial = reader.value(json.acrossSpatial, 0);\n        $.channelShared = reader.value(json.channelShared, 0);\n        $.eps = reader.value(json.eps, 0);\n        $.scale = reader.array(json.scale, Float32Array);\n        return $;\n    }\n};\n\nMNN.EltwiseInt8 = class EltwiseInt8 {\n\n    static decode(reader, position) {\n        const $ = new MNN.EltwiseInt8();\n        $.type = reader.int8_(position, 4, 0);\n        $.inputQuan0 = reader.table(position, 6, MNN.QuantizedFloatParam);\n        $.inputQuan1 = reader.table(position, 8, MNN.QuantizedFloatParam);\n        $.outputQuan = reader.table(position, 10, MNN.QuantizedFloatParam);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.EltwiseInt8();\n        $.type = MNN.EltwiseType[json.type];\n        $.inputQuan0 = reader.object(json.inputQuan0, MNN.QuantizedFloatParam);\n        $.inputQuan1 = reader.object(json.inputQuan1, MNN.QuantizedFloatParam);\n        $.outputQuan = reader.object(json.outputQuan, MNN.QuantizedFloatParam);\n        return $;\n    }\n};\n\nMNN.CumSum = class CumSum {\n\n    static decode(reader, position) {\n        const $ = new MNN.CumSum();\n        $.exclusive = reader.bool_(position, 4, false);\n        $.reverse = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.CumSum();\n        $.exclusive = reader.value(json.exclusive, false);\n        $.reverse = reader.value(json.reverse, false);\n        return $;\n    }\n};\n\nMNN.BinaryOpOperation = {\n    ADD: 0, '0': 'ADD',\n    SUB: 1, '1': 'SUB',\n    MUL: 2, '2': 'MUL',\n    DIV: 3, '3': 'DIV',\n    MAX_TEMP: 4, '4': 'MAX_TEMP',\n    MIN_TEMP: 5, '5': 'MIN_TEMP',\n    POW: 6, '6': 'POW',\n    REALDIV: 7, '7': 'REALDIV',\n    MINIMUM: 8, '8': 'MINIMUM',\n    MAXIMUM: 9, '9': 'MAXIMUM',\n    GREATER: 10, '10': 'GREATER',\n    GREATER_EQUAL: 11, '11': 'GREATER_EQUAL',\n    LESS: 12, '12': 'LESS',\n    FLOORDIV: 13, '13': 'FLOORDIV',\n    SquaredDifference: 14, '14': 'SquaredDifference',\n    EQUAL: 15, '15': 'EQUAL',\n    LESS_EQUAL: 16, '16': 'LESS_EQUAL',\n    FLOORMOD: 17, '17': 'FLOORMOD',\n    MOD: 19, '19': 'MOD',\n    ATAN2: 20, '20': 'ATAN2',\n    LOGICALOR: 21, '21': 'LOGICALOR',\n    NOTEQUAL: 22, '22': 'NOTEQUAL',\n    BITWISE_AND: 23, '23': 'BITWISE_AND',\n    BITWISE_OR: 24, '24': 'BITWISE_OR',\n    BITWISE_XOR: 25, '25': 'BITWISE_XOR',\n    LOGICALXOR: 26, '26': 'LOGICALXOR',\n    LEFTSHIFT: 27, '27': 'LEFTSHIFT',\n    RIGHTSHIFT: 28, '28': 'RIGHTSHIFT'\n};\n\nMNN.BinaryOp = class BinaryOp {\n\n    static decode(reader, position) {\n        const $ = new MNN.BinaryOp();\n        $.opType = reader.int32_(position, 4, 0);\n        $.T = reader.int32_(position, 6, 1);\n        $.activationType = reader.int32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.BinaryOp();\n        $.opType = MNN.BinaryOpOperation[json.opType];\n        $.T = MNN.DataType[json.T];\n        $.activationType = reader.value(json.activationType, 0);\n        return $;\n    }\n};\n\nMNN.PackParam = class PackParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.PackParam();\n        $.dataType = reader.int32_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.PackParam();\n        $.dataType = MNN.DataType[json.dataType];\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\nMNN.StridedSliceParam = class StridedSliceParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.StridedSliceParam();\n        $.Index = reader.int32_(position, 4, 0);\n        $.T = reader.int32_(position, 6, 0);\n        $.beginMask = reader.int32_(position, 8, 0);\n        $.endMask = reader.int32_(position, 10, 0);\n        $.ellipsisMask = reader.int32_(position, 12, 0);\n        $.newAxisMask = reader.int32_(position, 14, 0);\n        $.shrinkAxisMask = reader.int32_(position, 16, 0);\n        $.fromType = reader.int32_(position, 18, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.StridedSliceParam();\n        $.Index = MNN.DataType[json.Index];\n        $.T = MNN.DataType[json.T];\n        $.beginMask = reader.value(json.beginMask, 0);\n        $.endMask = reader.value(json.endMask, 0);\n        $.ellipsisMask = reader.value(json.ellipsisMask, 0);\n        $.newAxisMask = reader.value(json.newAxisMask, 0);\n        $.shrinkAxisMask = reader.value(json.shrinkAxisMask, 0);\n        $.fromType = reader.value(json.fromType, 0);\n        return $;\n    }\n};\n\nMNN.SqueezeParam = class SqueezeParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.SqueezeParam();\n        $.squeezeDims = reader.array(position, 4, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.SqueezeParam();\n        $.squeezeDims = reader.array(json.squeezeDims, Int32Array);\n        return $;\n    }\n};\n\nMNN.CastParam = class CastParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.CastParam();\n        $.srcT = reader.int32_(position, 4, 0);\n        $.dstT = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.CastParam();\n        $.srcT = MNN.DataType[json.srcT];\n        $.dstT = MNN.DataType[json.dstT];\n        return $;\n    }\n};\n\nMNN.ReductionType = {\n    SUM: 0, '0': 'SUM',\n    ASUM: 1, '1': 'ASUM',\n    SUMSQ: 2, '2': 'SUMSQ',\n    MEAN: 3, '3': 'MEAN',\n    MAXIMUM: 4, '4': 'MAXIMUM',\n    MINIMUM: 5, '5': 'MINIMUM',\n    PROD: 6, '6': 'PROD',\n    ANY: 7, '7': 'ANY',\n    ALL: 8, '8': 'ALL'\n};\n\nMNN.ReductionParam = class ReductionParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.ReductionParam();\n        $.operation = reader.int8_(position, 4, 0);\n        $.dim = reader.array(position, 6, Int32Array);\n        $.coeff = reader.float32_(position, 8, 0);\n        $.keepDims = reader.bool_(position, 10, false);\n        $.dType = reader.int32_(position, 12, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ReductionParam();\n        $.operation = MNN.ReductionType[json.operation];\n        $.dim = reader.array(json.dim, Int32Array);\n        $.coeff = reader.value(json.coeff, 0);\n        $.keepDims = reader.value(json.keepDims, false);\n        $.dType = MNN.DataType[json.dType];\n        return $;\n    }\n};\n\nMNN.Gather = class Gather {\n\n    static decode(reader, position) {\n        const $ = new MNN.Gather();\n        $.Tindices = reader.int32_(position, 4, 0);\n        $.Tparams = reader.int32_(position, 6, 0);\n        $.validateIndices = reader.bool_(position, 8, false);\n        $.axis = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Gather();\n        $.Tindices = MNN.DataType[json.Tindices];\n        $.Tparams = MNN.DataType[json.Tparams];\n        $.validateIndices = reader.value(json.validateIndices, false);\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\nMNN.ExpandDims = class ExpandDims {\n\n    static decode(reader, position) {\n        const $ = new MNN.ExpandDims();\n        $.T = reader.int32_(position, 4, 0);\n        $.Tdim = reader.int32_(position, 6, 0);\n        $.axis = reader.int32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ExpandDims();\n        $.T = MNN.DataType[json.T];\n        $.Tdim = MNN.DataType[json.Tdim];\n        $.axis = reader.value(json.axis, 0);\n        return $;\n    }\n};\n\nMNN.Selu = class Selu {\n\n    static decode(reader, position) {\n        const $ = new MNN.Selu();\n        $.scale = reader.float32_(position, 4, 0);\n        $.alpha = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Selu();\n        $.scale = reader.value(json.scale, 0);\n        $.alpha = reader.value(json.alpha, 0);\n        return $;\n    }\n};\n\nMNN.AsString = class AsString {\n\n    static decode(reader, position) {\n        const $ = new MNN.AsString();\n        $.T = reader.int32_(position, 4, 0);\n        $.precision = reader.int32_(position, 6, 0);\n        $.scientific = reader.bool_(position, 8, false);\n        $.shortest = reader.bool_(position, 10, false);\n        $.width = reader.int32_(position, 12, 0);\n        $.fillString = reader.string_(position, 14, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.AsString();\n        $.T = MNN.DataType[json.T];\n        $.precision = reader.value(json.precision, 0);\n        $.scientific = reader.value(json.scientific, false);\n        $.shortest = reader.value(json.shortest, false);\n        $.width = reader.value(json.width, 0);\n        $.fillString = reader.value(json.fillString, null);\n        return $;\n    }\n};\n\nMNN.ReduceJoin = class ReduceJoin {\n\n    static decode(reader, position) {\n        const $ = new MNN.ReduceJoin();\n        $.keepDims = reader.bool_(position, 4, false);\n        $.separator = reader.string_(position, 6, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ReduceJoin();\n        $.keepDims = reader.value(json.keepDims, false);\n        $.separator = reader.value(json.separator, null);\n        return $;\n    }\n};\n\nMNN.UnaryOpOperation = {\n    ABS: 0, '0': 'ABS',\n    NEG: 1, '1': 'NEG',\n    FLOOR: 2, '2': 'FLOOR',\n    CEIL: 3, '3': 'CEIL',\n    SQUARE: 4, '4': 'SQUARE',\n    SQRT: 5, '5': 'SQRT',\n    RSQRT: 6, '6': 'RSQRT',\n    EXP: 7, '7': 'EXP',\n    LOG: 8, '8': 'LOG',\n    SIN: 9, '9': 'SIN',\n    COS: 10, '10': 'COS',\n    TAN: 11, '11': 'TAN',\n    ASIN: 12, '12': 'ASIN',\n    ACOS: 13, '13': 'ACOS',\n    ATAN: 14, '14': 'ATAN',\n    RECIPROCAL: 15, '15': 'RECIPROCAL',\n    LOG1P: 16, '16': 'LOG1P',\n    BNLL: 17, '17': 'BNLL',\n    ACOSH: 18, '18': 'ACOSH',\n    SINH: 19, '19': 'SINH',\n    ASINH: 20, '20': 'ASINH',\n    ATANH: 21, '21': 'ATANH',\n    SIGN: 22, '22': 'SIGN',\n    ROUND: 23, '23': 'ROUND',\n    COSH: 24, '24': 'COSH',\n    ERF: 25, '25': 'ERF',\n    ERFC: 26, '26': 'ERFC',\n    ERFINV: 27, '27': 'ERFINV',\n    EXPM1: 28, '28': 'EXPM1',\n    SIGMOID: 29, '29': 'SIGMOID',\n    TANH: 30, '30': 'TANH',\n    HARDSWISH: 31, '31': 'HARDSWISH',\n    GELU: 32, '32': 'GELU',\n    GELU_STANDARD: 33, '33': 'GELU_STANDARD',\n    SILU: 34, '34': 'SILU'\n};\n\nMNN.UnaryOp = class UnaryOp {\n\n    static decode(reader, position) {\n        const $ = new MNN.UnaryOp();\n        $.opType = reader.int32_(position, 4, 0);\n        $.T = reader.int32_(position, 6, 0);\n        $.tableInt8 = reader.array(position, 8, Int8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.UnaryOp();\n        $.opType = MNN.UnaryOpOperation[json.opType];\n        $.T = MNN.DataType[json.T];\n        $.tableInt8 = reader.array(json.tableInt8, Int8Array);\n        return $;\n    }\n};\n\nMNN.TopKV2 = class TopKV2 {\n\n    static decode(reader, position) {\n        const $ = new MNN.TopKV2();\n        $.T = reader.int32_(position, 4, 1);\n        $.sorted = reader.bool_(position, 6, false);\n        $.largest = reader.bool_(position, 8, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.TopKV2();\n        $.T = MNN.DataType[json.T];\n        $.sorted = reader.value(json.sorted, false);\n        $.largest = reader.value(json.largest, true);\n        return $;\n    }\n};\n\nMNN.CropAndResizeMethod = {\n    BILINEAR: 0, '0': 'BILINEAR',\n    NEAREST: 1, '1': 'NEAREST'\n};\n\nMNN.CropAndResize = class CropAndResize {\n\n    static decode(reader, position) {\n        const $ = new MNN.CropAndResize();\n        $.extrapolationValue = reader.float32_(position, 4, 0);\n        $.method = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.CropAndResize();\n        $.extrapolationValue = reader.value(json.extrapolationValue, 0);\n        $.method = MNN.CropAndResizeMethod[json.method];\n        return $;\n    }\n};\n\nMNN.Fill = class Fill {\n\n    static decode(/* reader, position */) {\n        const $ = new MNN.Fill();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new MNN.Fill();\n        return $;\n    }\n};\n\nMNN.GatherV2 = class GatherV2 {\n\n    static decode(reader, position) {\n        const $ = new MNN.GatherV2();\n        $.Taxis = reader.int32_(position, 4, 0);\n        $.Tindices = reader.int32_(position, 6, 0);\n        $.Tparams = reader.int32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.GatherV2();\n        $.Taxis = MNN.DataType[json.Taxis];\n        $.Tindices = MNN.DataType[json.Tindices];\n        $.Tparams = MNN.DataType[json.Tparams];\n        return $;\n    }\n};\n\nMNN.NonMaxSuppressionV2 = class NonMaxSuppressionV2 {\n\n    static decode(/* reader, position */) {\n        const $ = new MNN.NonMaxSuppressionV2();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new MNN.NonMaxSuppressionV2();\n        return $;\n    }\n};\n\nMNN.Range = class Range {\n\n    static decode(reader, position) {\n        const $ = new MNN.Range();\n        $.Tidx = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Range();\n        $.Tidx = MNN.DataType[json.Tidx];\n        return $;\n    }\n};\n\nMNN.Rank = class Rank {\n\n    static decode(/* reader, position */) {\n        const $ = new MNN.Rank();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new MNN.Rank();\n        return $;\n    }\n};\n\nMNN.Size = class Size {\n\n    static decode(reader, position) {\n        const $ = new MNN.Size();\n        $.outputDataType = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Size();\n        $.outputDataType = MNN.DataType[json.outputDataType];\n        return $;\n    }\n};\n\nMNN.Transpose = class Transpose {\n\n    static decode(reader, position) {\n        const $ = new MNN.Transpose();\n        $.Tperm = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Transpose();\n        $.Tperm = MNN.DataType[json.Tperm];\n        return $;\n    }\n};\n\nMNN.SliceTf = class SliceTf {\n\n    static decode(reader, position) {\n        const $ = new MNN.SliceTf();\n        $.T = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.SliceTf();\n        $.T = MNN.DataType[json.T];\n        return $;\n    }\n};\n\nMNN.QuantizeMaxMin = class QuantizeMaxMin {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizeMaxMin();\n        $.T = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizeMaxMin();\n        $.T = MNN.DataType[json.T];\n        return $;\n    }\n};\n\nMNN.Crop = class Crop {\n\n    static decode(reader, position) {\n        const $ = new MNN.Crop();\n        $.axis = reader.int32_(position, 4, 2);\n        $.offset = reader.array(position, 6, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Crop();\n        $.axis = reader.value(json.axis, 2);\n        $.offset = reader.array(json.offset, Int32Array);\n        return $;\n    }\n};\n\nMNN.SpaceBatch = class SpaceBatch {\n\n    static decode(reader, position) {\n        const $ = new MNN.SpaceBatch();\n        $.blockShape = reader.table(position, 4, MNN.Blob);\n        $.padding = reader.table(position, 6, MNN.Blob);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.SpaceBatch();\n        $.blockShape = reader.object(json.blockShape, MNN.Blob);\n        $.padding = reader.object(json.padding, MNN.Blob);\n        return $;\n    }\n};\n\nMNN.MatMul = class MatMul {\n\n    static decode(reader, position) {\n        const $ = new MNN.MatMul();\n        $.T = reader.int32_(position, 4, 0);\n        $.transposeA = reader.bool_(position, 6, false);\n        $.transposeB = reader.bool_(position, 8, false);\n        $.weight = reader.array(position, 10, Float32Array);\n        $.bias = reader.array(position, 12, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.MatMul();\n        $.T = MNN.DataType[json.T];\n        $.transposeA = reader.value(json.transposeA, false);\n        $.transposeB = reader.value(json.transposeB, false);\n        $.weight = reader.array(json.weight, Float32Array);\n        $.bias = reader.array(json.bias, Float32Array);\n        return $;\n    }\n};\n\nMNN.MomentsParam = class MomentsParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.MomentsParam();\n        $.dim = reader.array(position, 4, Int32Array);\n        $.keepDims = reader.bool_(position, 6, true);\n        $.dType = reader.int32_(position, 8, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.MomentsParam();\n        $.dim = reader.array(json.dim, Int32Array);\n        $.keepDims = reader.value(json.keepDims, true);\n        $.dType = MNN.DataType[json.dType];\n        return $;\n    }\n};\n\nMNN.RNNParam = class RNNParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.RNNParam();\n        $.numUnits = reader.int32_(position, 4, 0);\n        $.isBidirectionalRNN = reader.bool_(position, 6, false);\n        $.linearBeforeReset = reader.bool_(position, 8, false);\n        $.keepAllOutputs = reader.bool_(position, 10, false);\n        $.fwGateWeight = reader.table(position, 12, MNN.Blob);\n        $.fwGateBias = reader.table(position, 14, MNN.Blob);\n        $.fwCandidateWeight = reader.table(position, 16, MNN.Blob);\n        $.fwCandidateBias = reader.table(position, 18, MNN.Blob);\n        $.fwRecurrentBias = reader.table(position, 20, MNN.Blob);\n        $.bwGateWeight = reader.table(position, 22, MNN.Blob);\n        $.bwGateBias = reader.table(position, 24, MNN.Blob);\n        $.bwCandidateWeight = reader.table(position, 26, MNN.Blob);\n        $.bwCandidateBias = reader.table(position, 28, MNN.Blob);\n        $.bwRecurrentBias = reader.table(position, 30, MNN.Blob);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.RNNParam();\n        $.numUnits = reader.value(json.numUnits, 0);\n        $.isBidirectionalRNN = reader.value(json.isBidirectionalRNN, false);\n        $.linearBeforeReset = reader.value(json.linearBeforeReset, false);\n        $.keepAllOutputs = reader.value(json.keepAllOutputs, false);\n        $.fwGateWeight = reader.object(json.fwGateWeight, MNN.Blob);\n        $.fwGateBias = reader.object(json.fwGateBias, MNN.Blob);\n        $.fwCandidateWeight = reader.object(json.fwCandidateWeight, MNN.Blob);\n        $.fwCandidateBias = reader.object(json.fwCandidateBias, MNN.Blob);\n        $.fwRecurrentBias = reader.object(json.fwRecurrentBias, MNN.Blob);\n        $.bwGateWeight = reader.object(json.bwGateWeight, MNN.Blob);\n        $.bwGateBias = reader.object(json.bwGateBias, MNN.Blob);\n        $.bwCandidateWeight = reader.object(json.bwCandidateWeight, MNN.Blob);\n        $.bwCandidateBias = reader.object(json.bwCandidateBias, MNN.Blob);\n        $.bwRecurrentBias = reader.object(json.bwRecurrentBias, MNN.Blob);\n        return $;\n    }\n};\n\nMNN.BatchMatMulParam = class BatchMatMulParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.BatchMatMulParam();\n        $.adjX = reader.bool_(position, 4, false);\n        $.adjY = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.BatchMatMulParam();\n        $.adjX = reader.value(json.adjX, false);\n        $.adjY = reader.value(json.adjY, false);\n        return $;\n    }\n};\n\nMNN.DepthToSpaceMode = {\n    DCR: 0, '0': 'DCR',\n    CRD: 1, '1': 'CRD'\n};\n\nMNN.DepthSpaceParam = class DepthSpaceParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.DepthSpaceParam();\n        $.blockSize = reader.int32_(position, 4, 0);\n        $.mode = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.DepthSpaceParam();\n        $.blockSize = reader.value(json.blockSize, 0);\n        $.mode = MNN.DepthToSpaceMode[json.mode];\n        return $;\n    }\n};\n\nMNN.ReverseSequenceParam = class ReverseSequenceParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.ReverseSequenceParam();\n        $.batchDim = reader.int32_(position, 4, 0);\n        $.seqDim = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ReverseSequenceParam();\n        $.batchDim = reader.value(json.batchDim, 0);\n        $.seqDim = reader.value(json.seqDim, 0);\n        return $;\n    }\n};\n\nMNN.DetectionPostProcessParam = class DetectionPostProcessParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.DetectionPostProcessParam();\n        $.maxDetections = reader.int32_(position, 4, 0);\n        $.maxClassesPerDetection = reader.int32_(position, 6, 0);\n        $.detectionsPerClass = reader.int32_(position, 8, 0);\n        $.nmsScoreThreshold = reader.float32_(position, 10, 0);\n        $.iouThreshold = reader.float32_(position, 12, 0);\n        $.numClasses = reader.int32_(position, 14, 0);\n        $.useRegularNMS = reader.bool_(position, 16, false);\n        $.centerSizeEncoding = reader.array(position, 18, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.DetectionPostProcessParam();\n        $.maxDetections = reader.value(json.maxDetections, 0);\n        $.maxClassesPerDetection = reader.value(json.maxClassesPerDetection, 0);\n        $.detectionsPerClass = reader.value(json.detectionsPerClass, 0);\n        $.nmsScoreThreshold = reader.value(json.nmsScoreThreshold, 0);\n        $.iouThreshold = reader.value(json.iouThreshold, 0);\n        $.numClasses = reader.value(json.numClasses, 0);\n        $.useRegularNMS = reader.value(json.useRegularNMS, false);\n        $.centerSizeEncoding = reader.array(json.centerSizeEncoding, Float32Array);\n        return $;\n    }\n};\n\nMNN.OneHotParam = class OneHotParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.OneHotParam();\n        $.dType = reader.int32_(position, 4, 1);\n        $.axis = reader.int32_(position, 6, -1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.OneHotParam();\n        $.dType = MNN.DataType[json.dType];\n        $.axis = reader.value(json.axis, -1);\n        return $;\n    }\n};\n\nMNN.PadValueMode = {\n    CONSTANT: 0, '0': 'CONSTANT',\n    REFLECT: 1, '1': 'REFLECT',\n    SYMMETRIC: 2, '2': 'SYMMETRIC',\n    EDGE: 3, '3': 'EDGE'\n};\n\nMNN.PadParam = class PadParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.PadParam();\n        $.mode = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.PadParam();\n        $.mode = MNN.PadValueMode[json.mode];\n        return $;\n    }\n};\n\nMNN.LayerNorm = class LayerNorm {\n\n    static decode(reader, position) {\n        const $ = new MNN.LayerNorm();\n        $.axis = reader.array(position, 4, Int32Array);\n        $.epsilon = reader.float32_(position, 6, 0);\n        $.gamma = reader.array(position, 8, Float32Array);\n        $.beta = reader.array(position, 10, Float32Array);\n        $.group = reader.int32_(position, 12, 1);\n        $.external = reader.int64s_(position, 14);\n        $.useRMSNorm = reader.bool_(position, 16, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.LayerNorm();\n        $.axis = reader.array(json.axis, Int32Array);\n        $.epsilon = reader.value(json.epsilon, 0);\n        $.gamma = reader.array(json.gamma, Float32Array);\n        $.beta = reader.array(json.beta, Float32Array);\n        $.group = reader.value(json.group, 1);\n        $.external = reader.array(json.external);\n        $.useRMSNorm = reader.value(json.useRMSNorm, false);\n        return $;\n    }\n};\n\nMNN.GroupNorm = class GroupNorm {\n\n    static decode(reader, position) {\n        const $ = new MNN.GroupNorm();\n        $.axis = reader.int32_(position, 4, 0);\n        $.epsilon = reader.float32_(position, 6, 0);\n        $.gamma = reader.array(position, 8, Float32Array);\n        $.beta = reader.array(position, 10, Float32Array);\n        $.group = reader.int32_(position, 12, 1);\n        $.bSwish = reader.int32_(position, 14, 0);\n        $.external = reader.int64s_(position, 16);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.GroupNorm();\n        $.axis = reader.value(json.axis, 0);\n        $.epsilon = reader.value(json.epsilon, 0);\n        $.gamma = reader.array(json.gamma, Float32Array);\n        $.beta = reader.array(json.beta, Float32Array);\n        $.group = reader.value(json.group, 1);\n        $.bSwish = reader.value(json.bSwish, 0);\n        $.external = reader.array(json.external);\n        return $;\n    }\n};\n\nMNN.RandomUniform = class RandomUniform {\n\n    static decode(reader, position) {\n        const $ = new MNN.RandomUniform();\n        $.seed = reader.int32_(position, 4, 0);\n        $.seed2 = reader.int32_(position, 6, 0);\n        $.type = reader.int32_(position, 8, 1);\n        $.low = reader.float32_(position, 10, 0);\n        $.high = reader.float32_(position, 12, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.RandomUniform();\n        $.seed = reader.value(json.seed, 0);\n        $.seed2 = reader.value(json.seed2, 0);\n        $.type = MNN.DataType[json.type];\n        $.low = reader.value(json.low, 0);\n        $.high = reader.value(json.high, 1);\n        return $;\n    }\n};\n\nMNN.TensorArray = class TensorArray {\n\n    static decode(reader, position) {\n        const $ = new MNN.TensorArray();\n        $.dynamic_size = reader.bool_(position, 4, false);\n        $.identical_element_shapes = reader.bool_(position, 6, false);\n        $.element_shape = reader.array(position, 8, Int32Array);\n        $.T = reader.int32_(position, 10, 1);\n        $.axis = reader.int32_(position, 12, 0);\n        $.keepdims = reader.bool_(position, 14, true);\n        $.new_axis = reader.bool_(position, 16, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.TensorArray();\n        $.dynamic_size = reader.value(json.dynamic_size, false);\n        $.identical_element_shapes = reader.value(json.identical_element_shapes, false);\n        $.element_shape = reader.array(json.element_shape, Int32Array);\n        $.T = MNN.DataType[json.T];\n        $.axis = reader.value(json.axis, 0);\n        $.keepdims = reader.value(json.keepdims, true);\n        $.new_axis = reader.value(json.new_axis, false);\n        return $;\n    }\n};\n\nMNN.LSTMBlockCell = class LSTMBlockCell {\n\n    static decode(reader, position) {\n        const $ = new MNN.LSTMBlockCell();\n        $.cell_clip = reader.float32_(position, 4, 3);\n        $.forget_bias = reader.float32_(position, 6, 1);\n        $.use_peephole = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.LSTMBlockCell();\n        $.cell_clip = reader.value(json.cell_clip, 3);\n        $.forget_bias = reader.value(json.forget_bias, 1);\n        $.use_peephole = reader.value(json.use_peephole, false);\n        return $;\n    }\n};\n\nMNN.FusedActivation = {\n    kTfLiteActNone: 0, '0': 'kTfLiteActNone',\n    kTfLiteActRelu: 1, '1': 'kTfLiteActRelu',\n    kTfLiteActRelu1: 2, '2': 'kTfLiteActRelu1',\n    kTfLiteActRelu6: 3, '3': 'kTfLiteActRelu6',\n    kTfLiteActTanh: 4, '4': 'kTfLiteActTanh',\n    kTfLiteActSignBit: 5, '5': 'kTfLiteActSignBit',\n    kTfLiteActSigmoid: 6, '6': 'kTfLiteActSigmoid'\n};\n\nMNN.QuantizedParam = class QuantizedParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedParam();\n        $.zeroPoint = reader.int32_(position, 4, 0);\n        $.scale = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedParam();\n        $.zeroPoint = reader.value(json.zeroPoint, 0);\n        $.scale = reader.value(json.scale, 0);\n        return $;\n    }\n};\n\nMNN.QuantizedAdd = class QuantizedAdd {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedAdd();\n        $.activationType = reader.int8_(position, 4, 0);\n        $.input1QuantizedParam = reader.table(position, 6, MNN.QuantizedParam);\n        $.input2QuantizedParam = reader.table(position, 8, MNN.QuantizedParam);\n        $.outputQuantizedParam = reader.table(position, 10, MNN.QuantizedParam);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedAdd();\n        $.activationType = MNN.FusedActivation[json.activationType];\n        $.input1QuantizedParam = reader.object(json.input1QuantizedParam, MNN.QuantizedParam);\n        $.input2QuantizedParam = reader.object(json.input2QuantizedParam, MNN.QuantizedParam);\n        $.outputQuantizedParam = reader.object(json.outputQuantizedParam, MNN.QuantizedParam);\n        return $;\n    }\n};\n\nMNN.ModeFormat = {\n    TENSORFLOW: 0, '0': 'TENSORFLOW',\n    TFLITE: 1, '1': 'TFLITE'\n};\n\nMNN.QuantizeMode = {\n    MIN_COMBINED: 0, '0': 'MIN_COMBINED',\n    MIN_FIRST: 1, '1': 'MIN_FIRST',\n    SCALED: 2, '2': 'SCALED'\n};\n\nMNN.Dequantize = class Dequantize {\n\n    static decode(reader, position) {\n        const $ = new MNN.Dequantize();\n        $.inputQuantizedParam = reader.table(position, 4, MNN.QuantizedParam);\n        $.mode = reader.int8_(position, 6, 0);\n        $.modelFormat = reader.int8_(position, 8, 0);\n        $.type = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Dequantize();\n        $.inputQuantizedParam = reader.object(json.inputQuantizedParam, MNN.QuantizedParam);\n        $.mode = MNN.QuantizeMode[json.mode];\n        $.modelFormat = MNN.ModeFormat[json.modelFormat];\n        $.type = MNN.DataType[json.type];\n        return $;\n    }\n};\n\nMNN.QuantizedAvgPool = class QuantizedAvgPool {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedAvgPool();\n        $.kernelX = reader.int32_(position, 4, 0);\n        $.kernelY = reader.int32_(position, 6, 0);\n        $.modelFormat = reader.int8_(position, 8, 0);\n        $.outputActivationMax = reader.int32_(position, 10, 0);\n        $.outputActivationMin = reader.int32_(position, 12, 0);\n        $.padType = reader.int8_(position, 14, 0);\n        $.padX = reader.int32_(position, 16, 0);\n        $.padY = reader.int32_(position, 18, 0);\n        $.strideX = reader.int32_(position, 20, 0);\n        $.strideY = reader.int32_(position, 22, 0);\n        $.type = reader.int32_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedAvgPool();\n        $.kernelX = reader.value(json.kernelX, 0);\n        $.kernelY = reader.value(json.kernelY, 0);\n        $.modelFormat = MNN.ModeFormat[json.modelFormat];\n        $.outputActivationMax = reader.value(json.outputActivationMax, 0);\n        $.outputActivationMin = reader.value(json.outputActivationMin, 0);\n        $.padType = MNN.PoolPadType[json.padType];\n        $.padX = reader.value(json.padX, 0);\n        $.padY = reader.value(json.padY, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.type = MNN.DataType[json.type];\n        return $;\n    }\n};\n\nMNN.QuantizedBiasAdd = class QuantizedBiasAdd {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedBiasAdd();\n        $.bias = reader.array(position, 4, Int32Array);\n        $.inputType = reader.int32_(position, 6, 0);\n        $.max = reader.int32_(position, 8, 0);\n        $.min = reader.int32_(position, 10, 0);\n        $.outputType = reader.int32_(position, 12, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedBiasAdd();\n        $.bias = reader.array(json.bias, Int32Array);\n        $.inputType = MNN.DataType[json.inputType];\n        $.max = reader.value(json.max, 0);\n        $.min = reader.value(json.min, 0);\n        $.outputType = MNN.DataType[json.outputType];\n        return $;\n    }\n};\n\nMNN.QuantizedConcat = class QuantizedConcat {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedConcat();\n        $.activationType = reader.int8_(position, 4, 0);\n        $.axis = reader.int32_(position, 6, 0);\n        $.inputScale = reader.array(position, 8, Float32Array);\n        $.inputZeroPoint = reader.array(position, 10, Int32Array);\n        $.outputQuantizedParam = reader.table(position, 12, MNN.QuantizedParam);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedConcat();\n        $.activationType = MNN.FusedActivation[json.activationType];\n        $.axis = reader.value(json.axis, 0);\n        $.inputScale = reader.array(json.inputScale, Float32Array);\n        $.inputZeroPoint = reader.array(json.inputZeroPoint, Int32Array);\n        $.outputQuantizedParam = reader.object(json.outputQuantizedParam, MNN.QuantizedParam);\n        return $;\n    }\n};\n\nMNN.QuantizedLogistic = class QuantizedLogistic {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedLogistic();\n        $.inputQuantizedParam = reader.table(position, 4, MNN.QuantizedParam);\n        $.outputQuantizedParam = reader.table(position, 6, MNN.QuantizedParam);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedLogistic();\n        $.inputQuantizedParam = reader.object(json.inputQuantizedParam, MNN.QuantizedParam);\n        $.outputQuantizedParam = reader.object(json.outputQuantizedParam, MNN.QuantizedParam);\n        return $;\n    }\n};\n\nMNN.QuantizedMatMul = class QuantizedMatMul {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedMatMul();\n        $.transposeA = reader.bool_(position, 4, false);\n        $.transposeB = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedMatMul();\n        $.transposeA = reader.value(json.transposeA, false);\n        $.transposeB = reader.value(json.transposeB, false);\n        return $;\n    }\n};\n\nMNN.QuantizedMaxPool = class QuantizedMaxPool {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedMaxPool();\n        $.kernelX = reader.int32_(position, 4, 0);\n        $.kernelY = reader.int32_(position, 6, 0);\n        $.modelFormat = reader.int8_(position, 8, 0);\n        $.outputActivationMax = reader.int32_(position, 10, 0);\n        $.outputActivationMin = reader.int32_(position, 12, 0);\n        $.padType = reader.int8_(position, 14, 0);\n        $.padX = reader.int32_(position, 16, 0);\n        $.padY = reader.int32_(position, 18, 0);\n        $.strideX = reader.int32_(position, 20, 0);\n        $.strideY = reader.int32_(position, 22, 0);\n        $.type = reader.int32_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedMaxPool();\n        $.kernelX = reader.value(json.kernelX, 0);\n        $.kernelY = reader.value(json.kernelY, 0);\n        $.modelFormat = MNN.ModeFormat[json.modelFormat];\n        $.outputActivationMax = reader.value(json.outputActivationMax, 0);\n        $.outputActivationMin = reader.value(json.outputActivationMin, 0);\n        $.padType = MNN.PoolPadType[json.padType];\n        $.padX = reader.value(json.padX, 0);\n        $.padY = reader.value(json.padY, 0);\n        $.strideX = reader.value(json.strideX, 0);\n        $.strideY = reader.value(json.strideY, 0);\n        $.type = MNN.DataType[json.type];\n        return $;\n    }\n};\n\nMNN.QuantizedRelu = class QuantizedRelu {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedRelu();\n        $.type = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedRelu();\n        $.type = MNN.DataType[json.type];\n        return $;\n    }\n};\n\nMNN.QuantizedRelu6 = class QuantizedRelu6 {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedRelu6();\n        $.type = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedRelu6();\n        $.type = MNN.DataType[json.type];\n        return $;\n    }\n};\n\nMNN.QuantizedReshape = class QuantizedReshape {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedReshape();\n        $.dims = reader.array(position, 4, Int32Array);\n        $.modelFormat = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedReshape();\n        $.dims = reader.array(json.dims, Int32Array);\n        $.modelFormat = MNN.ModeFormat[json.modelFormat];\n        return $;\n    }\n};\n\nMNN.QuantizedSoftmax = class QuantizedSoftmax {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizedSoftmax();\n        $.beta = reader.float32_(position, 4, 0);\n        $.inputScale = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizedSoftmax();\n        $.beta = reader.value(json.beta, 0);\n        $.inputScale = reader.value(json.inputScale, 0);\n        return $;\n    }\n};\n\nMNN.QuantizeRoundMode = {\n    HALF_AWAY_FROM_ZERO: 0, '0': 'HALF_AWAY_FROM_ZERO',\n    HALF_TO_EVEN: 1, '1': 'HALF_TO_EVEN'\n};\n\nMNN.QuantizeV2 = class QuantizeV2 {\n\n    static decode(reader, position) {\n        const $ = new MNN.QuantizeV2();\n        $.type = reader.int32_(position, 4, 0);\n        $.mode = reader.int8_(position, 6, 0);\n        $.roundMode = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.QuantizeV2();\n        $.type = MNN.DataType[json.type];\n        $.mode = MNN.QuantizeMode[json.mode];\n        $.roundMode = MNN.QuantizeRoundMode[json.roundMode];\n        return $;\n    }\n};\n\nMNN.RequantizationRange = class RequantizationRange {\n\n    static decode(/* reader, position */) {\n        const $ = new MNN.RequantizationRange();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new MNN.RequantizationRange();\n        return $;\n    }\n};\n\nMNN.Requantize = class Requantize {\n\n    static decode(/* reader, position */) {\n        const $ = new MNN.Requantize();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new MNN.Requantize();\n        return $;\n    }\n};\n\nMNN.TfQuantizedConv2D = class TfQuantizedConv2D {\n\n    static decode(reader, position) {\n        const $ = new MNN.TfQuantizedConv2D();\n        $.bias = reader.array(position, 4, Int32Array);\n        $.biasflag = reader.bool_(position, 6, false);\n        $.common = reader.table(position, 8, MNN.Convolution2DCommon);\n        $.weight = reader.array(position, 10, Uint8Array);\n        $.activationType = reader.int8_(position, 12, 0);\n        $.multiplier = reader.int32_(position, 14, 0);\n        $.outMax = reader.int32_(position, 16, 0);\n        $.outMin = reader.int32_(position, 18, 0);\n        $.shift = reader.int32_(position, 20, 0);\n        $.biasQuantizedParam = reader.table(position, 22, MNN.QuantizedParam);\n        $.depthMultiplier = reader.int32_(position, 24, 0);\n        $.filterQuantizedParam = reader.table(position, 26, MNN.QuantizedParam);\n        $.inputQuantizedParam = reader.table(position, 28, MNN.QuantizedParam);\n        $.modelFormat = reader.int8_(position, 30, 0);\n        $.outputQuantizedParam = reader.table(position, 32, MNN.QuantizedParam);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.TfQuantizedConv2D();\n        $.bias = reader.array(json.bias, Int32Array);\n        $.biasflag = reader.value(json.biasflag, false);\n        $.common = reader.object(json.common, MNN.Convolution2DCommon);\n        $.weight = reader.array(json.weight, Uint8Array);\n        $.activationType = MNN.FusedActivation[json.activationType];\n        $.multiplier = reader.value(json.multiplier, 0);\n        $.outMax = reader.value(json.outMax, 0);\n        $.outMin = reader.value(json.outMin, 0);\n        $.shift = reader.value(json.shift, 0);\n        $.biasQuantizedParam = reader.object(json.biasQuantizedParam, MNN.QuantizedParam);\n        $.depthMultiplier = reader.value(json.depthMultiplier, 0);\n        $.filterQuantizedParam = reader.object(json.filterQuantizedParam, MNN.QuantizedParam);\n        $.inputQuantizedParam = reader.object(json.inputQuantizedParam, MNN.QuantizedParam);\n        $.modelFormat = MNN.ModeFormat[json.modelFormat];\n        $.outputQuantizedParam = reader.object(json.outputQuantizedParam, MNN.QuantizedParam);\n        return $;\n    }\n};\n\nMNN.ExtraInfo = class ExtraInfo {\n\n    static decode(reader, position) {\n        const $ = new MNN.ExtraInfo();\n        $.buffer = reader.array(position, 4, Int8Array);\n        $.name = reader.string_(position, 6, null);\n        $.version = reader.string_(position, 8, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ExtraInfo();\n        $.buffer = reader.array(json.buffer, Int8Array);\n        $.name = reader.value(json.name, null);\n        $.version = reader.value(json.version, null);\n        return $;\n    }\n};\n\nMNN.TensorConvertInfo = class TensorConvertInfo {\n\n    static decode(reader, position) {\n        const $ = new MNN.TensorConvertInfo();\n        $.source = reader.int8_(position, 4, 0);\n        $.dest = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.TensorConvertInfo();\n        $.source = MNN.MNN_DATA_FORMAT[json.source];\n        $.dest = MNN.MNN_DATA_FORMAT[json.dest];\n        return $;\n    }\n};\n\nMNN.SampleMode = {\n    BILINEAR: 0, '0': 'BILINEAR',\n    NEAREST: 1, '1': 'NEAREST'\n};\n\nMNN.BorderMode = {\n    ZEROS: 0, '0': 'ZEROS',\n    CLAMP: 1, '1': 'CLAMP',\n    REFLECTION: 2, '2': 'REFLECTION',\n    CUBE: 3, '3': 'CUBE'\n};\n\nMNN.GridSample = class GridSample {\n\n    static decode(reader, position) {\n        const $ = new MNN.GridSample();\n        $.mode = reader.int8_(position, 4, 0);\n        $.paddingMode = reader.int8_(position, 6, 0);\n        $.alignCorners = reader.bool_(position, 8, false);\n        $.backward = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.GridSample();\n        $.mode = MNN.SampleMode[json.mode];\n        $.paddingMode = MNN.BorderMode[json.paddingMode];\n        $.alignCorners = reader.value(json.alignCorners, false);\n        $.backward = reader.value(json.backward, false);\n        return $;\n    }\n};\n\nMNN.ImageFormatType = {\n    RGBA: 0, '0': 'RGBA',\n    RGB: 1, '1': 'RGB',\n    BGR: 2, '2': 'BGR',\n    GRAY: 3, '3': 'GRAY',\n    BGRA: 4, '4': 'BGRA',\n    YCrCb: 5, '5': 'YCrCb',\n    YUV: 6, '6': 'YUV',\n    HSV: 7, '7': 'HSV',\n    XYZ: 8, '8': 'XYZ',\n    BGR555: 9, '9': 'BGR555',\n    BGR565: 10, '10': 'BGR565',\n    YUV_NV21: 11, '11': 'YUV_NV21',\n    YUV_NV12: 12, '12': 'YUV_NV12',\n    YUV_I420: 13, '13': 'YUV_I420',\n    HSV_FULL: 14, '14': 'HSV_FULL'\n};\n\nMNN.FilterType = {\n    NEAREST: 0, '0': 'NEAREST',\n    BILINEAR: 1, '1': 'BILINEAR',\n    BICUBIC: 2, '2': 'BICUBIC'\n};\n\nMNN.WrapType = {\n    CLAMP_TO_EDGE: 0, '0': 'CLAMP_TO_EDGE',\n    ZERO: 1, '1': 'ZERO',\n    REPEAT: 2, '2': 'REPEAT'\n};\n\nMNN.ImageProcessParam = class ImageProcessParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.ImageProcessParam();\n        $.filterType = reader.int8_(position, 4, 0);\n        $.sourceFormat = reader.int32_(position, 6, 0);\n        $.destFormat = reader.int32_(position, 8, 0);\n        $.wrap = reader.int8_(position, 10, 0);\n        $.mean = reader.array(position, 12, Float32Array);\n        $.normal = reader.array(position, 14, Float32Array);\n        $.transform = reader.array(position, 16, Float32Array);\n        $.paddingValue = reader.int8_(position, 18, 0);\n        $.shape = reader.array(position, 20, Int32Array);\n        $.outputType = reader.int32_(position, 22, 0);\n        $.draw = reader.bool_(position, 24, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ImageProcessParam();\n        $.filterType = MNN.FilterType[json.filterType];\n        $.sourceFormat = MNN.ImageFormatType[json.sourceFormat];\n        $.destFormat = MNN.ImageFormatType[json.destFormat];\n        $.wrap = MNN.WrapType[json.wrap];\n        $.mean = reader.array(json.mean, Float32Array);\n        $.normal = reader.array(json.normal, Float32Array);\n        $.transform = reader.array(json.transform, Float32Array);\n        $.paddingValue = reader.value(json.paddingValue, 0);\n        $.shape = reader.array(json.shape, Int32Array);\n        $.outputType = MNN.DataType[json.outputType];\n        $.draw = reader.value(json.draw, false);\n        return $;\n    }\n};\n\nMNN.OpType = {\n    AbsVal: 0, '0': 'AbsVal',\n    QuantizedAdd: 1, '1': 'QuantizedAdd',\n    ArgMax: 2, '2': 'ArgMax',\n    AsString: 3, '3': 'AsString',\n    InstanceNorm: 4, '4': 'InstanceNorm',\n    BatchToSpaceND: 5, '5': 'BatchToSpaceND',\n    Copy: 6, '6': 'Copy',\n    BinaryOp: 7, '7': 'BinaryOp',\n    Bnll: 8, '8': 'Bnll',\n    Cast: 9, '9': 'Cast',\n    Concat: 10, '10': 'Concat',\n    Const: 11, '11': 'Const',\n    Convolution: 12, '12': 'Convolution',\n    ConvolutionDepthwise: 13, '13': 'ConvolutionDepthwise',\n    Crop: 14, '14': 'Crop',\n    CropAndResize: 15, '15': 'CropAndResize',\n    ImageProcess: 16, '16': 'ImageProcess',\n    Deconvolution: 17, '17': 'Deconvolution',\n    DeconvolutionDepthwise: 18, '18': 'DeconvolutionDepthwise',\n    Dequantize: 19, '19': 'Dequantize',\n    DetectionOutput: 20, '20': 'DetectionOutput',\n    Dropout: 21, '21': 'Dropout',\n    Eltwise: 22, '22': 'Eltwise',\n    ELU: 23, '23': 'ELU',\n    Unique: 24, '24': 'Unique',\n    Exp: 25, '25': 'Exp',\n    ExpandDims: 26, '26': 'ExpandDims',\n    Fill: 27, '27': 'Fill',\n    Flatten: 28, '28': 'Flatten',\n    Im2Col: 29, '29': 'Im2Col',\n    Gather: 30, '30': 'Gather',\n    GatherV2: 31, '31': 'GatherV2',\n    Im2Seq: 32, '32': 'Im2Seq',\n    InnerProduct: 33, '33': 'InnerProduct',\n    Input: 34, '34': 'Input',\n    Interp: 35, '35': 'Interp',\n    Log: 36, '36': 'Log',\n    LRN: 37, '37': 'LRN',\n    LSTM: 38, '38': 'LSTM',\n    MatMul: 39, '39': 'MatMul',\n    MoE: 40, '40': 'MoE',\n    NonMaxSuppression: 41, '41': 'NonMaxSuppression',\n    NonMaxSuppressionV2: 42, '42': 'NonMaxSuppressionV2',\n    Normalize: 43, '43': 'Normalize',\n    Pack: 44, '44': 'Pack',\n    Padding: 45, '45': 'Padding',\n    Permute: 46, '46': 'Permute',\n    Pooling: 47, '47': 'Pooling',\n    Power: 48, '48': 'Power',\n    PReLU: 49, '49': 'PReLU',\n    PriorBox: 50, '50': 'PriorBox',\n    Proposal: 51, '51': 'Proposal',\n    QuantizedAvgPool: 52, '52': 'QuantizedAvgPool',\n    QuantizedBiasAdd: 53, '53': 'QuantizedBiasAdd',\n    QuantizedConcat: 54, '54': 'QuantizedConcat',\n    QuantizedDepthwiseConv2D: 55, '55': 'QuantizedDepthwiseConv2D',\n    QuantizedLogistic: 56, '56': 'QuantizedLogistic',\n    RasterAndInterpolate: 57, '57': 'RasterAndInterpolate',\n    QuantizedMaxPool: 58, '58': 'QuantizedMaxPool',\n    Texture: 59, '59': 'Texture',\n    RasterDiff: 60, '60': 'RasterDiff',\n    QuantizedReshape: 61, '61': 'QuantizedReshape',\n    QuantizedSoftmax: 62, '62': 'QuantizedSoftmax',\n    QuantizeMaxMin: 63, '63': 'QuantizeMaxMin',\n    QuantizeV2: 64, '64': 'QuantizeV2',\n    Range: 65, '65': 'Range',\n    Rank: 66, '66': 'Rank',\n    ReduceJoin: 67, '67': 'ReduceJoin',\n    Reduction: 68, '68': 'Reduction',\n    ReLU: 69, '69': 'ReLU',\n    ReLU6: 70, '70': 'ReLU6',\n    RequantizationRange: 71, '71': 'RequantizationRange',\n    Requantize: 72, '72': 'Requantize',\n    Reshape: 73, '73': 'Reshape',\n    Resize: 74, '74': 'Resize',\n    RNN: 75, '75': 'RNN',\n    ROIPooling: 76, '76': 'ROIPooling',\n    Scale: 77, '77': 'Scale',\n    Selu: 78, '78': 'Selu',\n    Seq2Out: 79, '79': 'Seq2Out',\n    Shape: 80, '80': 'Shape',\n    Sigmoid: 81, '81': 'Sigmoid',\n    Size: 82, '82': 'Size',\n    Slice: 83, '83': 'Slice',\n    SliceTf: 84, '84': 'SliceTf',\n    Softmax: 85, '85': 'Softmax',\n    SpaceToBatchND: 86, '86': 'SpaceToBatchND',\n    SpatialProduct: 87, '87': 'SpatialProduct',\n    Col2Im: 88, '88': 'Col2Im',\n    Segment: 89, '89': 'Segment',\n    Squeeze: 90, '90': 'Squeeze',\n    StridedSlice: 91, '91': 'StridedSlice',\n    CastLike: 92, '92': 'CastLike',\n    StringSplit: 93, '93': 'StringSplit',\n    StringToNumber: 94, '94': 'StringToNumber',\n    TanH: 95, '95': 'TanH',\n    TfQuantizedConv2D: 96, '96': 'TfQuantizedConv2D',\n    Threshold: 97, '97': 'Threshold',\n    Tile: 98, '98': 'Tile',\n    TopKV2: 99, '99': 'TopKV2',\n    Transpose: 100, '100': 'Transpose',\n    UnaryOp: 101, '101': 'UnaryOp',\n    Unpack: 102, '102': 'Unpack',\n    Where: 103, '103': 'Where',\n    Moments: 104, '104': 'Moments',\n    RNNSequenceGRU: 105, '105': 'RNNSequenceGRU',\n    BatchMatMul: 106, '106': 'BatchMatMul',\n    Unsqueeze: 107, '107': 'Unsqueeze',\n    CosineSimilarity: 108, '108': 'CosineSimilarity',\n    DepthToSpace: 109, '109': 'DepthToSpace',\n    SpaceToDepth: 110, '110': 'SpaceToDepth',\n    ReverseSequence: 111, '111': 'ReverseSequence',\n    Pooling3D: 112, '112': 'Pooling3D',\n    Convolution3D: 113, '113': 'Convolution3D',\n    MatrixBandPart: 114, '114': 'MatrixBandPart',\n    GatherND: 115, '115': 'GatherND',\n    DetectionPostProcess: 116, '116': 'DetectionPostProcess',\n    UnravelIndex: 117, '117': 'UnravelIndex',\n    ScatterNd: 118, '118': 'ScatterNd',\n    OneHot: 119, '119': 'OneHot',\n    BroadcastTo: 120, '120': 'BroadcastTo',\n    Dilation2D: 121, '121': 'Dilation2D',\n    Interp3D: 122, '122': 'Interp3D',\n    Raster: 128, '128': 'Raster',\n    ConvertTensor: 129, '129': 'ConvertTensor',\n    ArgMin: 130, '130': 'ArgMin',\n    LinSpace: 131, '131': 'LinSpace',\n    RandomUniform: 132, '132': 'RandomUniform',\n    TensorArray: 133, '133': 'TensorArray',\n    TensorArraySize: 134, '134': 'TensorArraySize',\n    TensorArrayRead: 135, '135': 'TensorArrayRead',\n    TensorArrayWrite: 136, '136': 'TensorArrayWrite',\n    TensorArrayGather: 137, '137': 'TensorArrayGather',\n    TensorArrayScatter: 138, '138': 'TensorArrayScatter',\n    TensorArraySplit: 139, '139': 'TensorArraySplit',\n    TensorArrayConcat: 140, '140': 'TensorArrayConcat',\n    LSTMBlockCell: 141, '141': 'LSTMBlockCell',\n    Reverse: 142, '142': 'Reverse',\n    ROIAlign: 143, '143': 'ROIAlign',\n    RandomNormal: 144, '144': 'RandomNormal',\n    TensorArrayInsert: 145, '145': 'TensorArrayInsert',\n    TensorArrayErase: 146, '146': 'TensorArrayErase',\n    EyeLike: 147, '147': 'EyeLike',\n    CumSum: 148, '148': 'CumSum',\n    Det: 149, '149': 'Det',\n    CumProd: 150, '150': 'CumProd',\n    ScatterElements: 151, '151': 'ScatterElements',\n    GatherElements: 152, '152': 'GatherElements',\n    Svd: 153, '153': 'Svd',\n    Histogram: 154, '154': 'Histogram',\n    DynamicQuant: 155, '155': 'DynamicQuant',\n    Stft: 156, '156': 'Stft',\n    Plugin: 256, '256': 'Plugin',\n    Select: 257, '257': 'Select',\n    ZerosLike: 258, '258': 'ZerosLike',\n    Broastcast: 259, '259': 'Broastcast',\n    SetDiff1D: 260, '260': 'SetDiff1D',\n    ReluGrad: 261, '261': 'ReluGrad',\n    Identity: 262, '262': 'Identity',\n    PoolGrad: 263, '263': 'PoolGrad',\n    SoftmaxGrad: 264, '264': 'SoftmaxGrad',\n    Conv2DBackPropFilter: 265, '265': 'Conv2DBackPropFilter',\n    TrainableParam: 266, '266': 'TrainableParam',\n    BatchNorm: 267, '267': 'BatchNorm',\n    ConvTranspose3D: 268, '268': 'ConvTranspose3D',\n    ZeroGrad: 269, '269': 'ZeroGrad',\n    Attention: 299, '299': 'Attention',\n    FmhaV2: 300, '300': 'FmhaV2',\n    Fmhca: 301, '301': 'Fmhca',\n    SeqLen2Spatial: 302, '302': 'SeqLen2Spatial',\n    SplitGeLU: 303, '303': 'SplitGeLU',\n    GroupNorm: 304, '304': 'GroupNorm',\n    LinearAttention: 305, '305': 'LinearAttention',\n    Extra: 512, '512': 'Extra',\n    ConvInt8: 513, '513': 'ConvInt8',\n    Int8ToFloat: 514, '514': 'Int8ToFloat',\n    DepthwiseConvInt8: 515, '515': 'DepthwiseConvInt8',\n    FloatToInt8: 517, '517': 'FloatToInt8',\n    EltwiseInt8: 518, '518': 'EltwiseInt8',\n    While: 600, '600': 'While',\n    If: 601, '601': 'If',\n    LayerNorm: 603, '603': 'LayerNorm',\n    GridSample: 604, '604': 'GridSample'\n};\n\nMNN.Plugin = class Plugin {\n\n    static decode(reader, position) {\n        const $ = new MNN.Plugin();\n        $.type = reader.string_(position, 4, null);\n        $.attr = reader.tables(position, 6, MNN.Attribute);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Plugin();\n        $.type = reader.value(json.type, null);\n        $.attr = reader.objects(json.attr, MNN.Attribute);\n        return $;\n    }\n};\n\nMNN.Extra = class Extra {\n\n    static decode(reader, position) {\n        const $ = new MNN.Extra();\n        $.type = reader.string_(position, 4, null);\n        $.engine = reader.string_(position, 6, null);\n        $.info = reader.array(position, 8, Int8Array);\n        $.attr = reader.tables(position, 10, MNN.Attribute);\n        $.vector = reader.bool_(position, 12, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Extra();\n        $.type = reader.value(json.type, null);\n        $.engine = reader.value(json.engine, null);\n        $.info = reader.array(json.info, Int8Array);\n        $.attr = reader.objects(json.attr, MNN.Attribute);\n        $.vector = reader.value(json.vector, false);\n        return $;\n    }\n};\n\nMNN.StringVec = class StringVec {\n\n    static decode(reader, position) {\n        const $ = new MNN.StringVec();\n        $.data = reader.strings_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.StringVec();\n        $.data = reader.array(json.data);\n        return $;\n    }\n};\n\nMNN.AttentionParam = class AttentionParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.AttentionParam();\n        $.kv_cache = reader.bool_(position, 4, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.AttentionParam();\n        $.kv_cache = reader.value(json.kv_cache, true);\n        return $;\n    }\n};\n\nMNN.LinearAttentionParam = class LinearAttentionParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.LinearAttentionParam();\n        $.attn_type = reader.string_(position, 4, null);\n        $.num_k_heads = reader.int32_(position, 6, 0);\n        $.num_v_heads = reader.int32_(position, 8, 0);\n        $.head_k_dim = reader.int32_(position, 10, 0);\n        $.head_v_dim = reader.int32_(position, 12, 0);\n        $.use_qk_l2norm = reader.bool_(position, 14, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.LinearAttentionParam();\n        $.attn_type = reader.value(json.attn_type, null);\n        $.num_k_heads = reader.value(json.num_k_heads, 0);\n        $.num_v_heads = reader.value(json.num_v_heads, 0);\n        $.head_k_dim = reader.value(json.head_k_dim, 0);\n        $.head_v_dim = reader.value(json.head_v_dim, 0);\n        $.use_qk_l2norm = reader.value(json.use_qk_l2norm, false);\n        return $;\n    }\n};\n\nMNN.FmhaV2Param = class FmhaV2Param {\n\n    static decode(reader, position) {\n        const $ = new MNN.FmhaV2Param();\n        $.heads = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.FmhaV2Param();\n        $.heads = reader.value(json.heads, 0);\n        return $;\n    }\n};\n\nMNN.FmhcaParam = class FmhcaParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.FmhcaParam();\n        $.heads = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.FmhcaParam();\n        $.heads = reader.value(json.heads, 0);\n        return $;\n    }\n};\n\nMNN.StftParam = class StftParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.StftParam();\n        $.n_fft = reader.int32_(position, 4, 0);\n        $.hop_length = reader.int32_(position, 6, 0);\n        $.abs = reader.bool_(position, 8, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.StftParam();\n        $.n_fft = reader.value(json.n_fft, 0);\n        $.hop_length = reader.value(json.hop_length, 0);\n        $.abs = reader.value(json.abs, true);\n        return $;\n    }\n};\n\nMNN.ShapeParam = class ShapeParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.ShapeParam();\n        $.hasStart = reader.bool_(position, 4, false);\n        $.start = reader.int32_(position, 6, 0);\n        $.hasEnd = reader.bool_(position, 8, false);\n        $.end = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.ShapeParam();\n        $.hasStart = reader.value(json.hasStart, false);\n        $.start = reader.value(json.start, 0);\n        $.hasEnd = reader.value(json.hasEnd, false);\n        $.end = reader.value(json.end, 0);\n        return $;\n    }\n};\n\nMNN.WhileParam = class WhileParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.WhileParam();\n        $.cond_graph = reader.string_(position, 4, null);\n        $.body_graph = reader.string_(position, 6, null);\n        $.aliases_inputs = reader.tables(position, 8, MNN.StringVec);\n        $.aliases_outputs = reader.strings_(position, 10);\n        $.aliases_updates = reader.tables(position, 12, MNN.StringVec);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.WhileParam();\n        $.cond_graph = reader.value(json.cond_graph, null);\n        $.body_graph = reader.value(json.body_graph, null);\n        $.aliases_inputs = reader.objects(json.aliases_inputs, MNN.StringVec);\n        $.aliases_outputs = reader.array(json.aliases_outputs);\n        $.aliases_updates = reader.objects(json.aliases_updates, MNN.StringVec);\n        return $;\n    }\n};\n\nMNN.IfParam = class IfParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.IfParam();\n        $.then_graph = reader.string_(position, 4, null);\n        $.else_graph = reader.string_(position, 6, null);\n        $.aliases_inputs = reader.tables(position, 8, MNN.StringVec);\n        $.aliases_outputs = reader.tables(position, 10, MNN.StringVec);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.IfParam();\n        $.then_graph = reader.value(json.then_graph, null);\n        $.else_graph = reader.value(json.else_graph, null);\n        $.aliases_inputs = reader.objects(json.aliases_inputs, MNN.StringVec);\n        $.aliases_outputs = reader.objects(json.aliases_outputs, MNN.StringVec);\n        return $;\n    }\n};\n\nMNN.RegionCommand = class RegionCommand {\n\n    static decode(reader, position) {\n        const $ = new MNN.RegionCommand();\n        $.op = reader.table(position, 4, MNN.Op);\n        $.steps = reader.array(position, 6, Int32Array);\n        $.size = reader.array(position, 8, Int32Array);\n        $.indexes = reader.array(position, 10, Int32Array);\n        $.view = reader.tables(position, 12, MNN.View);\n        $.fuse = reader.int32_(position, 14, -1);\n        $.iterIndexes = reader.array(position, 16, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.RegionCommand();\n        $.op = reader.object(json.op, MNN.Op);\n        $.steps = reader.array(json.steps, Int32Array);\n        $.size = reader.array(json.size, Int32Array);\n        $.indexes = reader.array(json.indexes, Int32Array);\n        $.view = reader.objects(json.view, MNN.View);\n        $.fuse = reader.value(json.fuse, -1);\n        $.iterIndexes = reader.array(json.iterIndexes, Int32Array);\n        return $;\n    }\n};\n\nMNN.LoopParam = class LoopParam {\n\n    static decode(reader, position) {\n        const $ = new MNN.LoopParam();\n        $.tensorNumber = reader.int32_(position, 4, 0);\n        $.outputIndexes = reader.array(position, 6, Int32Array);\n        $.inputIndexes = reader.array(position, 8, Int32Array);\n        $.extraTensorInfos = reader.tables(position, 10, MNN.TensorDescribe);\n        $.parallel = reader.bool_(position, 12, true);\n        $.loopNumber = reader.int32_(position, 14, 0);\n        $.commands = reader.tables(position, 16, MNN.RegionCommand);\n        $.initCommand = reader.tables(position, 18, MNN.RegionCommand);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.LoopParam();\n        $.tensorNumber = reader.value(json.tensorNumber, 0);\n        $.outputIndexes = reader.array(json.outputIndexes, Int32Array);\n        $.inputIndexes = reader.array(json.inputIndexes, Int32Array);\n        $.extraTensorInfos = reader.objects(json.extraTensorInfos, MNN.TensorDescribe);\n        $.parallel = reader.value(json.parallel, true);\n        $.loopNumber = reader.value(json.loopNumber, 0);\n        $.commands = reader.objects(json.commands, MNN.RegionCommand);\n        $.initCommand = reader.objects(json.initCommand, MNN.RegionCommand);\n        return $;\n    }\n};\n\nMNN.OpParameter = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return MNN.QuantizedAdd.decode(reader, position);\n            case 2: return MNN.ArgMax.decode(reader, position);\n            case 3: return MNN.AsString.decode(reader, position);\n            case 4: return MNN.Axis.decode(reader, position);\n            case 5: return MNN.BatchNorm.decode(reader, position);\n            case 6: return MNN.BinaryOp.decode(reader, position);\n            case 7: return MNN.Blob.decode(reader, position);\n            case 8: return MNN.CastParam.decode(reader, position);\n            case 9: return MNN.Convolution2D.decode(reader, position);\n            case 10: return MNN.Crop.decode(reader, position);\n            case 11: return MNN.CropAndResize.decode(reader, position);\n            case 12: return MNN.Dequantize.decode(reader, position);\n            case 13: return MNN.DetectionOutput.decode(reader, position);\n            case 14: return MNN.Eltwise.decode(reader, position);\n            case 15: return MNN.ExpandDims.decode(reader, position);\n            case 16: return MNN.Fill.decode(reader, position);\n            case 17: return MNN.Flatten.decode(reader, position);\n            case 18: return MNN.Gather.decode(reader, position);\n            case 19: return MNN.GatherV2.decode(reader, position);\n            case 20: return MNN.InnerProduct.decode(reader, position);\n            case 21: return MNN.Input.decode(reader, position);\n            case 22: return MNN.Interp.decode(reader, position);\n            case 23: return MNN.LRN.decode(reader, position);\n            case 24: return MNN.LSTM.decode(reader, position);\n            case 25: return MNN.MatMul.decode(reader, position);\n            case 26: return MNN.NonMaxSuppressionV2.decode(reader, position);\n            case 27: return MNN.Normalize.decode(reader, position);\n            case 28: return MNN.PackParam.decode(reader, position);\n            case 29: return MNN.Permute.decode(reader, position);\n            case 30: return MNN.Plugin.decode(reader, position);\n            case 31: return MNN.Pool.decode(reader, position);\n            case 32: return MNN.PRelu.decode(reader, position);\n            case 33: return MNN.PriorBox.decode(reader, position);\n            case 34: return MNN.Proposal.decode(reader, position);\n            case 35: return MNN.QuantizedAvgPool.decode(reader, position);\n            case 36: return MNN.QuantizedBiasAdd.decode(reader, position);\n            case 37: return MNN.QuantizedConcat.decode(reader, position);\n            case 38: return MNN.QuantizedLogistic.decode(reader, position);\n            case 39: return MNN.QuantizedMatMul.decode(reader, position);\n            case 40: return MNN.QuantizedMaxPool.decode(reader, position);\n            case 41: return MNN.QuantizedRelu.decode(reader, position);\n            case 42: return MNN.QuantizedRelu6.decode(reader, position);\n            case 43: return MNN.QuantizedReshape.decode(reader, position);\n            case 44: return MNN.QuantizedSoftmax.decode(reader, position);\n            case 45: return MNN.QuantizeMaxMin.decode(reader, position);\n            case 46: return MNN.QuantizeV2.decode(reader, position);\n            case 47: return MNN.Range.decode(reader, position);\n            case 48: return MNN.Rank.decode(reader, position);\n            case 49: return MNN.ReduceJoin.decode(reader, position);\n            case 50: return MNN.ReductionParam.decode(reader, position);\n            case 51: return MNN.Relu.decode(reader, position);\n            case 52: return MNN.Relu6.decode(reader, position);\n            case 53: return MNN.RequantizationRange.decode(reader, position);\n            case 54: return MNN.Requantize.decode(reader, position);\n            case 55: return MNN.Reshape.decode(reader, position);\n            case 56: return MNN.Resize.decode(reader, position);\n            case 57: return MNN.RoiParameters.decode(reader, position);\n            case 58: return MNN.Scale.decode(reader, position);\n            case 59: return MNN.Selu.decode(reader, position);\n            case 60: return MNN.Size.decode(reader, position);\n            case 61: return MNN.Slice.decode(reader, position);\n            case 62: return MNN.SliceTf.decode(reader, position);\n            case 63: return MNN.SpaceBatch.decode(reader, position);\n            case 64: return MNN.SqueezeParam.decode(reader, position);\n            case 65: return MNN.StridedSliceParam.decode(reader, position);\n            case 66: return MNN.TensorConvertInfo.decode(reader, position);\n            case 67: return MNN.TfQuantizedConv2D.decode(reader, position);\n            case 68: return MNN.TopKV2.decode(reader, position);\n            case 69: return MNN.Transpose.decode(reader, position);\n            case 70: return MNN.UnaryOp.decode(reader, position);\n            case 71: return MNN.MomentsParam.decode(reader, position);\n            case 72: return MNN.RNNParam.decode(reader, position);\n            case 73: return MNN.BatchMatMulParam.decode(reader, position);\n            case 74: return MNN.QuantizedFloatParam.decode(reader, position);\n            case 75: return MNN.DepthSpaceParam.decode(reader, position);\n            case 76: return MNN.EltwiseInt8.decode(reader, position);\n            case 77: return MNN.ReverseSequenceParam.decode(reader, position);\n            case 78: return MNN.Extra.decode(reader, position);\n            case 79: return MNN.Pool3D.decode(reader, position);\n            case 80: return MNN.Convolution3D.decode(reader, position);\n            case 81: return MNN.ELU.decode(reader, position);\n            case 82: return MNN.DetectionPostProcessParam.decode(reader, position);\n            case 83: return MNN.OneHotParam.decode(reader, position);\n            case 84: return MNN.PadParam.decode(reader, position);\n            case 85: return MNN.WhileParam.decode(reader, position);\n            case 86: return MNN.IfParam.decode(reader, position);\n            case 87: return MNN.RandomUniform.decode(reader, position);\n            case 88: return MNN.LayerNorm.decode(reader, position);\n            case 89: return MNN.TensorArray.decode(reader, position);\n            case 90: return MNN.LSTMBlockCell.decode(reader, position);\n            case 91: return MNN.GridSample.decode(reader, position);\n            case 92: return MNN.LoopParam.decode(reader, position);\n            case 93: return MNN.ImageProcessParam.decode(reader, position);\n            case 94: return MNN.CumSum.decode(reader, position);\n            case 95: return MNN.GroupNorm.decode(reader, position);\n            case 96: return MNN.FmhaV2Param.decode(reader, position);\n            case 97: return MNN.FmhcaParam.decode(reader, position);\n            case 98: return MNN.AttentionParam.decode(reader, position);\n            case 99: return MNN.StftParam.decode(reader, position);\n            case 100: return MNN.LinearAttentionParam.decode(reader, position);\n            case 101: return MNN.ShapeParam.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'QuantizedAdd': return MNN.QuantizedAdd.decodeText(reader, json);\n            case 'ArgMax': return MNN.ArgMax.decodeText(reader, json);\n            case 'AsString': return MNN.AsString.decodeText(reader, json);\n            case 'Axis': return MNN.Axis.decodeText(reader, json);\n            case 'BatchNorm': return MNN.BatchNorm.decodeText(reader, json);\n            case 'BinaryOp': return MNN.BinaryOp.decodeText(reader, json);\n            case 'Blob': return MNN.Blob.decodeText(reader, json);\n            case 'CastParam': return MNN.CastParam.decodeText(reader, json);\n            case 'Convolution2D': return MNN.Convolution2D.decodeText(reader, json);\n            case 'Crop': return MNN.Crop.decodeText(reader, json);\n            case 'CropAndResize': return MNN.CropAndResize.decodeText(reader, json);\n            case 'Dequantize': return MNN.Dequantize.decodeText(reader, json);\n            case 'DetectionOutput': return MNN.DetectionOutput.decodeText(reader, json);\n            case 'Eltwise': return MNN.Eltwise.decodeText(reader, json);\n            case 'ExpandDims': return MNN.ExpandDims.decodeText(reader, json);\n            case 'Fill': return MNN.Fill.decodeText(reader, json);\n            case 'Flatten': return MNN.Flatten.decodeText(reader, json);\n            case 'Gather': return MNN.Gather.decodeText(reader, json);\n            case 'GatherV2': return MNN.GatherV2.decodeText(reader, json);\n            case 'InnerProduct': return MNN.InnerProduct.decodeText(reader, json);\n            case 'Input': return MNN.Input.decodeText(reader, json);\n            case 'Interp': return MNN.Interp.decodeText(reader, json);\n            case 'LRN': return MNN.LRN.decodeText(reader, json);\n            case 'LSTM': return MNN.LSTM.decodeText(reader, json);\n            case 'MatMul': return MNN.MatMul.decodeText(reader, json);\n            case 'NonMaxSuppressionV2': return MNN.NonMaxSuppressionV2.decodeText(reader, json);\n            case 'Normalize': return MNN.Normalize.decodeText(reader, json);\n            case 'PackParam': return MNN.PackParam.decodeText(reader, json);\n            case 'Permute': return MNN.Permute.decodeText(reader, json);\n            case 'Plugin': return MNN.Plugin.decodeText(reader, json);\n            case 'Pool': return MNN.Pool.decodeText(reader, json);\n            case 'PRelu': return MNN.PRelu.decodeText(reader, json);\n            case 'PriorBox': return MNN.PriorBox.decodeText(reader, json);\n            case 'Proposal': return MNN.Proposal.decodeText(reader, json);\n            case 'QuantizedAvgPool': return MNN.QuantizedAvgPool.decodeText(reader, json);\n            case 'QuantizedBiasAdd': return MNN.QuantizedBiasAdd.decodeText(reader, json);\n            case 'QuantizedConcat': return MNN.QuantizedConcat.decodeText(reader, json);\n            case 'QuantizedLogistic': return MNN.QuantizedLogistic.decodeText(reader, json);\n            case 'QuantizedMatMul': return MNN.QuantizedMatMul.decodeText(reader, json);\n            case 'QuantizedMaxPool': return MNN.QuantizedMaxPool.decodeText(reader, json);\n            case 'QuantizedRelu': return MNN.QuantizedRelu.decodeText(reader, json);\n            case 'QuantizedRelu6': return MNN.QuantizedRelu6.decodeText(reader, json);\n            case 'QuantizedReshape': return MNN.QuantizedReshape.decodeText(reader, json);\n            case 'QuantizedSoftmax': return MNN.QuantizedSoftmax.decodeText(reader, json);\n            case 'QuantizeMaxMin': return MNN.QuantizeMaxMin.decodeText(reader, json);\n            case 'QuantizeV2': return MNN.QuantizeV2.decodeText(reader, json);\n            case 'Range': return MNN.Range.decodeText(reader, json);\n            case 'Rank': return MNN.Rank.decodeText(reader, json);\n            case 'ReduceJoin': return MNN.ReduceJoin.decodeText(reader, json);\n            case 'ReductionParam': return MNN.ReductionParam.decodeText(reader, json);\n            case 'Relu': return MNN.Relu.decodeText(reader, json);\n            case 'Relu6': return MNN.Relu6.decodeText(reader, json);\n            case 'RequantizationRange': return MNN.RequantizationRange.decodeText(reader, json);\n            case 'Requantize': return MNN.Requantize.decodeText(reader, json);\n            case 'Reshape': return MNN.Reshape.decodeText(reader, json);\n            case 'Resize': return MNN.Resize.decodeText(reader, json);\n            case 'RoiParameters': return MNN.RoiParameters.decodeText(reader, json);\n            case 'Scale': return MNN.Scale.decodeText(reader, json);\n            case 'Selu': return MNN.Selu.decodeText(reader, json);\n            case 'Size': return MNN.Size.decodeText(reader, json);\n            case 'Slice': return MNN.Slice.decodeText(reader, json);\n            case 'SliceTf': return MNN.SliceTf.decodeText(reader, json);\n            case 'SpaceBatch': return MNN.SpaceBatch.decodeText(reader, json);\n            case 'SqueezeParam': return MNN.SqueezeParam.decodeText(reader, json);\n            case 'StridedSliceParam': return MNN.StridedSliceParam.decodeText(reader, json);\n            case 'TensorConvertInfo': return MNN.TensorConvertInfo.decodeText(reader, json);\n            case 'TfQuantizedConv2D': return MNN.TfQuantizedConv2D.decodeText(reader, json);\n            case 'TopKV2': return MNN.TopKV2.decodeText(reader, json);\n            case 'Transpose': return MNN.Transpose.decodeText(reader, json);\n            case 'UnaryOp': return MNN.UnaryOp.decodeText(reader, json);\n            case 'MomentsParam': return MNN.MomentsParam.decodeText(reader, json);\n            case 'RNNParam': return MNN.RNNParam.decodeText(reader, json);\n            case 'BatchMatMulParam': return MNN.BatchMatMulParam.decodeText(reader, json);\n            case 'QuantizedFloatParam': return MNN.QuantizedFloatParam.decodeText(reader, json);\n            case 'DepthSpaceParam': return MNN.DepthSpaceParam.decodeText(reader, json);\n            case 'EltwiseInt8': return MNN.EltwiseInt8.decodeText(reader, json);\n            case 'ReverseSequenceParam': return MNN.ReverseSequenceParam.decodeText(reader, json);\n            case 'Extra': return MNN.Extra.decodeText(reader, json);\n            case 'Pool3D': return MNN.Pool3D.decodeText(reader, json);\n            case 'Convolution3D': return MNN.Convolution3D.decodeText(reader, json);\n            case 'ELU': return MNN.ELU.decodeText(reader, json);\n            case 'DetectionPostProcessParam': return MNN.DetectionPostProcessParam.decodeText(reader, json);\n            case 'OneHotParam': return MNN.OneHotParam.decodeText(reader, json);\n            case 'PadParam': return MNN.PadParam.decodeText(reader, json);\n            case 'WhileParam': return MNN.WhileParam.decodeText(reader, json);\n            case 'IfParam': return MNN.IfParam.decodeText(reader, json);\n            case 'RandomUniform': return MNN.RandomUniform.decodeText(reader, json);\n            case 'LayerNorm': return MNN.LayerNorm.decodeText(reader, json);\n            case 'TensorArray': return MNN.TensorArray.decodeText(reader, json);\n            case 'LSTMBlockCell': return MNN.LSTMBlockCell.decodeText(reader, json);\n            case 'GridSample': return MNN.GridSample.decodeText(reader, json);\n            case 'LoopParam': return MNN.LoopParam.decodeText(reader, json);\n            case 'ImageProcessParam': return MNN.ImageProcessParam.decodeText(reader, json);\n            case 'CumSum': return MNN.CumSum.decodeText(reader, json);\n            case 'GroupNorm': return MNN.GroupNorm.decodeText(reader, json);\n            case 'FmhaV2Param': return MNN.FmhaV2Param.decodeText(reader, json);\n            case 'FmhcaParam': return MNN.FmhcaParam.decodeText(reader, json);\n            case 'AttentionParam': return MNN.AttentionParam.decodeText(reader, json);\n            case 'StftParam': return MNN.StftParam.decodeText(reader, json);\n            case 'LinearAttentionParam': return MNN.LinearAttentionParam.decodeText(reader, json);\n            case 'ShapeParam': return MNN.ShapeParam.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\nMNN.Op = class Op {\n\n    static decode(reader, position) {\n        const $ = new MNN.Op();\n        $.inputIndexes = reader.array(position, 4, Int32Array);\n        $.main = reader.union(position, 6, MNN.OpParameter);\n        $.name = reader.string_(position, 10, null);\n        $.outputIndexes = reader.array(position, 12, Int32Array);\n        $.type = reader.int32_(position, 14, 0);\n        $.defaultDimentionFormat = reader.int8_(position, 16, 1);\n        $.externalPath = reader.string_(position, 18, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Op();\n        $.inputIndexes = reader.array(json.inputIndexes, Int32Array);\n        $.main = MNN.OpParameter.decodeText(reader, json.main, json.main_type);\n        $.name = reader.value(json.name, null);\n        $.outputIndexes = reader.array(json.outputIndexes, Int32Array);\n        $.type = MNN.OpType[json.type];\n        $.defaultDimentionFormat = MNN.MNN_DATA_FORMAT[json.defaultDimentionFormat];\n        $.externalPath = reader.value(json.externalPath, null);\n        return $;\n    }\n};\n\nMNN.View = class View {\n\n    static decode(reader, position) {\n        const $ = new MNN.View();\n        $.offset = reader.int32_(position, 4, 0);\n        $.stride = reader.array(position, 6, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.View();\n        $.offset = reader.value(json.offset, 0);\n        $.stride = reader.array(json.stride, Int32Array);\n        return $;\n    }\n};\n\nMNN.Region = class Region {\n\n    static decode(reader, position) {\n        const $ = new MNN.Region();\n        $.src = reader.table(position, 4, MNN.View);\n        $.dst = reader.table(position, 6, MNN.View);\n        $.size = reader.array(position, 8, Int32Array);\n        $.origin = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Region();\n        $.src = reader.object(json.src, MNN.View);\n        $.dst = reader.object(json.dst, MNN.View);\n        $.size = reader.array(json.size, Int32Array);\n        $.origin = reader.value(json.origin, 0);\n        return $;\n    }\n};\n\nMNN.TensorDescribe = class TensorDescribe {\n\n    static decode(reader, position) {\n        const $ = new MNN.TensorDescribe();\n        $.blob = reader.table(position, 4, MNN.Blob);\n        $.index = reader.int32_(position, 6, 0);\n        $.name = reader.string_(position, 8, null);\n        $.regions = reader.tables(position, 10, MNN.Region);\n        $.quantInfo = reader.table(position, 12, MNN.TensorQuantInfo);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.TensorDescribe();\n        $.blob = reader.object(json.blob, MNN.Blob);\n        $.index = reader.value(json.index, 0);\n        $.name = reader.value(json.name, null);\n        $.regions = reader.objects(json.regions, MNN.Region);\n        $.quantInfo = reader.object(json.quantInfo, MNN.TensorQuantInfo);\n        return $;\n    }\n};\n\nMNN.ForwardType = {\n    CPU: 0, '0': 'CPU',\n    METAL: 1, '1': 'METAL',\n    CUDA: 2, '2': 'CUDA',\n    OPENCL: 3, '3': 'OPENCL',\n    AUTO: 4, '4': 'AUTO',\n    NNAPI: 5, '5': 'NNAPI',\n    OPENGLES: 6, '6': 'OPENGLES',\n    VULKAN: 7, '7': 'VULKAN'\n};\n\nMNN.Usage = {\n    INFERENCE: 0, '0': 'INFERENCE',\n    TRAIN: 1, '1': 'TRAIN',\n    INFERENCE_STATIC: 2, '2': 'INFERENCE_STATIC'\n};\n\nMNN.SubGraphProto = class SubGraphProto {\n\n    static decode(reader, position) {\n        const $ = new MNN.SubGraphProto();\n        $.name = reader.string_(position, 4, null);\n        $.inputs = reader.array(position, 6, Int32Array);\n        $.outputs = reader.array(position, 8, Int32Array);\n        $.tensors = reader.strings_(position, 10);\n        $.nodes = reader.tables(position, 12, MNN.Op);\n        $.extraTensorDescribe = reader.tables(position, 14, MNN.TensorDescribe);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.SubGraphProto();\n        $.name = reader.value(json.name, null);\n        $.inputs = reader.array(json.inputs, Int32Array);\n        $.outputs = reader.array(json.outputs, Int32Array);\n        $.tensors = reader.array(json.tensors);\n        $.nodes = reader.objects(json.nodes, MNN.Op);\n        $.extraTensorDescribe = reader.objects(json.extraTensorDescribe, MNN.TensorDescribe);\n        return $;\n    }\n};\n\nMNN.TensorQuantInfo = class TensorQuantInfo {\n\n    static decode(reader, position) {\n        const $ = new MNN.TensorQuantInfo();\n        $.scale = reader.float32_(position, 4, 0);\n        $.zero = reader.float32_(position, 6, 0);\n        $.min = reader.float32_(position, 8, -128);\n        $.max = reader.float32_(position, 10, 127);\n        $.type = reader.int32_(position, 12, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.TensorQuantInfo();\n        $.scale = reader.value(json.scale, 0);\n        $.zero = reader.value(json.zero, 0);\n        $.min = reader.value(json.min, -128);\n        $.max = reader.value(json.max, 127);\n        $.type = MNN.DataType[json.type];\n        return $;\n    }\n};\n\nMNN.Net = class Net {\n\n    static create(reader) {\n        return MNN.Net.decode(reader, reader.root);\n    }\n\n    static createText(reader) {\n        return MNN.Net.decodeText(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new MNN.Net();\n        $.bizCode = reader.string_(position, 4, null);\n        $.extraTensorDescribe = reader.tables(position, 6, MNN.TensorDescribe);\n        $.extraInfo = reader.table(position, 8, MNN.ExtraInfo);\n        $.oplists = reader.tables(position, 10, MNN.Op);\n        $.outputName = reader.strings_(position, 12);\n        $.preferForwardType = reader.int8_(position, 14, 0);\n        $.sourceType = reader.int8_(position, 16, 0);\n        $.tensorName = reader.strings_(position, 18);\n        $.tensorNumber = reader.int32_(position, 20, 0);\n        $.usage = reader.int8_(position, 22, 0);\n        $.subgraphs = reader.tables(position, 24, MNN.SubGraphProto);\n        $.mnn_uuid = reader.string_(position, 26, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new MNN.Net();\n        $.bizCode = reader.value(json.bizCode, null);\n        $.extraTensorDescribe = reader.objects(json.extraTensorDescribe, MNN.TensorDescribe);\n        $.extraInfo = reader.object(json.extraInfo, MNN.ExtraInfo);\n        $.oplists = reader.objects(json.oplists, MNN.Op);\n        $.outputName = reader.array(json.outputName);\n        $.preferForwardType = MNN.ForwardType[json.preferForwardType];\n        $.sourceType = MNN.NetSource[json.sourceType];\n        $.tensorName = reader.array(json.tensorName);\n        $.tensorNumber = reader.value(json.tensorNumber, 0);\n        $.usage = MNN.Usage[json.usage];\n        $.subgraphs = reader.objects(json.subgraphs, MNN.SubGraphProto);\n        $.mnn_uuid = reader.value(json.mnn_uuid, null);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/mnn.js",
    "content": "\nconst mnn = {};\n\nmnn.ModelFactory = class {\n\n    async match(context) {\n        const reader = await context.peek('flatbuffers.binary');\n        if (reader) {\n            return context.set('mnn.flatbuffers', reader);\n        }\n        const obj = await context.peek('json');\n        if (obj && obj.sourceType && Array.isArray(obj.oplists) && Array.isArray(obj.tensorName)) {\n            return context.set('mnn.flatbuffers.json', obj);\n        }\n        return null;\n    }\n\n    async open(context) {\n        mnn.schema = await context.require('./mnn-schema');\n        mnn.schema = mnn.schema.MNN;\n        let net = null;\n        switch (context.type) {\n            case 'mnn.flatbuffers': {\n                try {\n                    const reader = context.value;\n                    net = mnn.schema.Net.create(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new mnn.Error(`File format is not mnn.Net (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            case 'mnn.flatbuffers.json': {\n                try {\n                    const reader = await context.read('flatbuffers.text');\n                    net = mnn.schema.Net.createText(reader);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new mnn.Error(`File format is not mnn.Net (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            default: {\n                throw new mnn.Error(`Unsupported TensorFlow Lite format '${context.type}'.`);\n            }\n        }\n        const metadata = await context.metadata('mnn-metadata.json');\n        return new mnn.Model(metadata, net);\n    }\n};\n\nmnn.Model = class {\n\n    constructor(metadata, net) {\n        this.format = 'MNN v2';\n        const sources = new Map([\n            [mnn.schema.NetSource.CAFFE, 'Caffe'],\n            [mnn.schema.NetSource.TENSORFLOW, 'TensorFlow'],\n            [mnn.schema.NetSource.TFLITE, 'TensorFlow Lite'],\n            [mnn.schema.NetSource.ONNX, 'ONNX'],\n            [mnn.schema.NetSource.TORCH, 'Torch']\n        ]);\n        if (!sources.has(net.sourceType)) {\n            throw new mnn.Error(`Unsupported model source '${net.sourceType}'.`);\n        }\n        this.source = sources.get(net.sourceType);\n        this.modules = [new mnn.Graph(metadata, net)];\n    }\n};\n\nmnn.Graph = class {\n\n    constructor(metadata, net) {\n        this.name = '';\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        for (let i = 0; i < net.tensorName.length; i++) {\n            if (net.tensorName[i] === '') {\n                net.tensorName[i] = `\\n${i}`;\n            }\n        }\n        const inputs = new Map();\n        for (const op of net.oplists) {\n            for (const input of op.inputIndexes) {\n                inputs.set(input, (inputs.get(input) || 0) + 1);\n            }\n        }\n        const consts = new Map();\n        const oplists = net.oplists.filter((op) => {\n            if (op.type === mnn.schema.OpType.Const &&\n                op.inputIndexes.length === 0 &&\n                op.outputIndexes.length === 1 &&\n                op.main instanceof mnn.schema.Blob &&\n                inputs.get(op.outputIndexes[0]) === 1) {\n                consts.set(op.outputIndexes[0], op);\n                return false;\n            }\n            return true;\n        });\n        const values = new Map();\n        values.map = (index) => {\n            if (!values.has(index)) {\n                const name = net.tensorName[index];\n                const op = consts.get(index);\n                if (op) {\n                    const tensor = op ? mnn.Utility.createTensor(op.main, 'Const') : null;\n                    values.set(index, new mnn.Value(name, null, tensor));\n                } else {\n                    const extraTensorDescribe = net.extraTensorDescribe[index];\n                    const blob = extraTensorDescribe ? extraTensorDescribe.blob : null;\n                    const type = blob && blob.dims && blob.dims.length > 0 ? new mnn.TensorType(blob.dataType, new mnn.TensorShape(blob.dims), blob.dataFormat) : null;\n                    values.set(index, new mnn.Value(name, type, null));\n                }\n            }\n            return values.get(index);\n        };\n\n        for (const op of oplists) {\n            if (op.type === mnn.schema.OpType.Input) {\n                const args = Array.from(op.outputIndexes).map((index) => values.map(index));\n                const argument = new mnn.Argument(op.name, args);\n                this.inputs.push(argument);\n            } else {\n                const node = new mnn.Node(metadata, op, values);\n                this.nodes.push(node);\n            }\n        }\n\n        for (let i = 0; i < net.tensorName.length; i++) {\n            if (!inputs.has(i)) {\n                const value = values.map(i);\n                const argument = new mnn.Argument(value.name, [value]);\n                this.outputs.push(argument);\n            }\n        }\n    }\n};\n\nmnn.Node = class {\n\n    constructor(metadata, op, values) {\n        const type = mnn.Utility.enum('OpType', op.type) || `(${op.type})`;\n        this.type = metadata.type(type) || { name: type };\n        this.name = op.name || '';\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.chains = [];\n        if (op.inputIndexes && op.inputIndexes.length > 0) {\n            const argument = new mnn.Argument('input', Array.from(op.inputIndexes).map((index) => values.map(index)));\n            this.inputs.push(argument);\n        }\n        if (op.outputIndexes && op.outputIndexes.length > 0) {\n            const argument = new mnn.Argument('output', Array.from(op.outputIndexes).map((index) => values.map(index)));\n            this.outputs.push(argument);\n        }\n        const param = op.main;\n        if (param) {\n            const parameters = [param];\n            if (param instanceof mnn.schema.Blob) {\n                const tensor = mnn.Utility.createTensor(param, 'Blob');\n                const value = new mnn.Value('', null, tensor);\n                const argument = new mnn.Argument('value', [value]);\n                this.inputs.push(argument);\n                parameters.splice(0, parameters.length);\n            } else if (param instanceof mnn.schema.Convolution2D) {\n                const outputCount = param.common ? param.common.outputCount : 0;\n                const inputCount = param.common ? param.common.inputCount : 0;\n                const kernelX = param.common ? param.common.kernelX : 0;\n                const kernelY = param.common ? param.common.kernelY : 0;\n                this._buildTensor('weight', mnn.schema.DataType.DT_FLOAT, [outputCount, inputCount, kernelX, kernelY], param.weight);\n                this._buildTensor('bias', mnn.schema.DataType.DT_FLOAT, [outputCount], param.bias);\n                delete param.weight;\n                delete param.bias;\n                delete param.quanParameter;\n                delete param.symmetricQuan;\n            } else if (param instanceof mnn.schema.InnerProduct) {\n                const outputCount = param.outputCount;\n                const inputCount = outputCount > 0 ? param.weightSize / outputCount : 0;\n                this._buildTensor('weight', mnn.schema.DataType.DT_FLOAT, [outputCount, inputCount], param.weight);\n                this._buildTensor('bias', mnn.schema.DataType.DT_FLOAT, [outputCount], param.bias);\n                delete param.weight;\n                delete param.bias;\n                delete param.quanParameter;\n            } else if (param instanceof mnn.schema.Scale) {\n                const scaleDataCount = param.channels;\n                this._buildTensor('scale', mnn.schema.DataType.DT_FLOAT, [scaleDataCount], param.scaleData);\n                this._buildTensor('bias', mnn.schema.DataType.DT_FLOAT, [scaleDataCount], param.biasData);\n                delete param.scaleData;\n                delete param.biasData;\n            } else if (param instanceof mnn.schema.BatchNorm) {\n                const channels = param.channels;\n                this._buildTensor('mean', mnn.schema.DataType.DT_FLOAT, [channels], param.meanData);\n                this._buildTensor('slope', mnn.schema.DataType.DT_FLOAT, [channels], param.slopeData);\n                this._buildTensor('variance', mnn.schema.DataType.DT_FLOAT, [channels], param.varData);\n                this._buildTensor('bias', mnn.schema.DataType.DT_FLOAT, [channels], param.biasData);\n                delete param.slopeData;\n                delete param.meanData;\n                delete param.varData;\n                delete param.biasData;\n            } else if (param instanceof mnn.schema.PRelu) {\n                this._buildTensor('slope', mnn.schema.DataType.DT_FLOAT, [param.slopeCount], param.slope);\n                delete param.slopeCount;\n            } else if (param instanceof mnn.schema.Normalize) {\n                this._buildTensor('scale', mnn.schema.DataType.DT_FLOAT, [param.scale.length], param.scale);\n                delete param.scale;\n            }\n            while (parameters.length > 0) {\n                const parameter = parameters.shift();\n                const node_type = type;\n                for (const [key, obj] of Object.entries(parameter)) {\n                    if (Object.keys(mnn.schema).find((key) => mnn.schema[key].prototype && obj instanceof mnn.schema[key])) {\n                        parameters.push(obj);\n                        continue;\n                    }\n                    const schema = metadata.attribute(node_type, key);\n                    let value = ArrayBuffer.isView(obj) ? Array.from(obj) : obj;\n                    let type = null;\n                    if (schema && schema.type) {\n                        type = schema.type;\n                        switch (type) {\n                            case 'DataType':\n                                value = mnn.Utility.dataType(value);\n                                break;\n                            default:\n                                value = mnn.Utility.enum(type, value);\n                                break;\n                        }\n                    }\n                    const attribute = new mnn.Argument(key, value, type);\n                    this.attributes.push(attribute);\n                }\n            }\n        }\n    }\n\n    _buildTensor(name, dataType, dimensions, value) {\n        const shape = new mnn.TensorShape(dimensions);\n        const type = new mnn.TensorType(dataType, shape);\n        const tensor = new mnn.Tensor('Weight', type, value);\n        const argument = new mnn.Argument(name, [new mnn.Value('', null, tensor)]);\n        this.inputs.push(argument);\n    }\n};\n\nmnn.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nmnn.Value = class {\n\n    constructor(name, type, initializer = null) {\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nmnn.Tensor = class {\n\n    constructor(category, type, data) {\n        this.category = category;\n        this.type = type;\n        switch (type.dataType) {\n            case 'int32':\n            case 'float32':\n                this.encoding = '|';\n                this.values = data ? data.slice(0) : null;\n                break;\n            case 'int8':\n            case 'uint8':\n            case 'float16':\n            case 'bfloat16':\n                this.encoding = '<';\n                this.values = data ? data.slice(0) : null;\n                break;\n            default:\n                throw new mnn.Error(`Unsupported data type '${type.dataType}'.`);\n        }\n    }\n};\n\nmnn.TensorType = class {\n\n    constructor(dataType, shape, format) {\n        this.dataType = mnn.Utility.dataType(dataType);\n        this.shape = shape;\n        if (format) {\n            switch (format) {\n                case mnn.schema.MNN_DATA_FORMAT.NCHW: this.denotation = 'NCHW'; break;\n                case mnn.schema.MNN_DATA_FORMAT.NHWC: this.denotation = 'NHWC'; break;\n                case mnn.schema.MNN_DATA_FORMAT.NC4HW4: this.denotation = 'NC4HW4'; break;\n                case mnn.schema.MNN_DATA_FORMAT.NHWC4: this.denotation = 'NHWC4'; break;\n                default: throw new mnn.Error(`Unsupported tensor type format '${format}'.`);\n            }\n        }\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmnn.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = Array.from(dimensions);\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`;\n        }\n        return '';\n    }\n};\n\nmnn.Utility = class {\n\n    static dataType(type) {\n        switch (type) {\n            case mnn.schema.DataType.DT_INVALID: return '?';\n            case mnn.schema.DataType.DT_FLOAT: return 'float32';\n            case mnn.schema.DataType.DT_DOUBLE: return 'float64';\n            case mnn.schema.DataType.DT_INT32: return 'int32';\n            case mnn.schema.DataType.DT_UINT8: return 'uint8';\n            case mnn.schema.DataType.DT_INT16: return 'int16';\n            case mnn.schema.DataType.DT_INT8: return 'int8';\n            case mnn.schema.DataType.DT_STRING: return 'string';\n            case mnn.schema.DataType.DT_COMPLEX64: return 'complex<float32>';\n            case mnn.schema.DataType.DT_INT64: return 'int64';\n            case mnn.schema.DataType.DT_BOOL: return 'boolean';\n            case mnn.schema.DataType.DT_QINT8: return 'qint8';\n            case mnn.schema.DataType.DT_QUINT8: return 'quint8';\n            case mnn.schema.DataType.DT_QINT32: return 'qint32';\n            case mnn.schema.DataType.DT_BFLOAT16: return 'bfloat16';\n            case mnn.schema.DataType.DT_QINT16: return 'qint16';\n            case mnn.schema.DataType.DT_QUINT16: return 'quint16';\n            case mnn.schema.DataType.DT_UINT16: return 'uint16';\n            case mnn.schema.DataType.DT_COMPLEX128: return 'complex<float64>';\n            case mnn.schema.DataType.DT_HALF: return 'float16';\n            case mnn.schema.DataType.DT_RESOURCE: return 'resource';\n            case mnn.schema.DataType.DT_VARIANT: return 'variant';\n            default: throw new mnn.Error(`Unsupported data type '${JSON.stringify(type)}'.`);\n        }\n    }\n\n    static enum(name, value) {\n        const type = name && mnn.schema ? mnn.schema[name] : undefined;\n        if (type) {\n            mnn.Utility._enumKeyMap = mnn.Utility._enumKeyMap || new Map();\n            if (!mnn.Utility._enumKeyMap.has(name)) {\n                const map = new Map();\n                for (const key of Object.keys(type)) {\n                    map.set(type[key], key);\n                }\n                mnn.Utility._enumKeyMap.set(name, map);\n            }\n            const map = mnn.Utility._enumKeyMap.get(name);\n            if (map.has(value)) {\n                return map.get(value);\n            }\n        }\n        return value.toString();\n    }\n\n    static createTensor(param, category) {\n        const shape = new mnn.TensorShape(param.dims);\n        const type = new mnn.TensorType(param.dataType, shape, param.dataFormat);\n        let data = null;\n        switch (type.dataType) {\n            case 'uint8': data = param.uint8s; break;\n            case 'int8': data = param.int8s; break;\n            case 'int32': data = param.int32s; break;\n            case 'int64': data = param.int64s; break;\n            case 'float16': data = param.uint8s; break;\n            case 'float32': data = param.float32s; break;\n            case 'bfloat16': data = param.uint8s; break;\n            default: throw new mnn.Error(`Unsupported blob data type '${JSON.stringify(type.dataType)}'.`);\n        }\n        return new mnn.Tensor(category, type, data);\n    }\n};\n\nmnn.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading MNN model.';\n    }\n};\n\nexport const ModelFactory = mnn.ModelFactory;\n\n"
  },
  {
    "path": "source/mslite-metadata.json",
    "content": "[\n  {\n    \"name\": \"Abs\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"AbsGrad\"\n  },\n  {\n    \"name\": \"Activation\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"ActivationType\" },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"min_val\", \"type\": \"float32\", \"default\": -1 },\n      { \"name\": \"max_val\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" },\n      { \"name\": \"approximate\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ActivationGrad\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"ActivationType\" },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"yt\" },\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Adam\",\n    \"attributes\": [\n      { \"name\": \"useNesterov\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"use_locking\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"use_nesterov\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"m\" },\n      { \"name\": \"v\" },\n      { \"name\": \"beta1_power\" },\n      { \"name\": \"beta22_power\" },\n      { \"name\": \"learning_rate\" },\n      { \"name\": \"beta1\" },\n      { \"name\": \"beta2\" },\n      { \"name\": \"eps\" },\n      { \"name\": \"gradient\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"AdamWeightDecay\",\n    \"attributes\": [\n      { \"name\": \"use_locking\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Add\",\n    \"attributes\": [\n      { \"name\": \"ActivationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"AdderFusion\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"AddFold\"\n  },\n  {\n    \"name\": \"AddFusion\",\n    \"attributes\": [\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"AddGrad\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx1\" },\n      { \"name\": \"dx2\" }\n    ]\n  },\n  {\n    \"name\": \"AddN\",\n    \"attributes\": [\n      { \"name\": \"N\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"sums\" }\n    ]\n  },\n  {\n    \"name\": \"Affine\",\n    \"attributes\": [\n      { \"name\": \"context\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"output_dim\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" },\n      { \"name\": \"transpose_a\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transpose_b\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"All\",\n    \"attributes\": [\n      { \"name\": \"keepDims\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"keep_dims\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"AllGather\",\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"rank_size\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ApplyMomentum\",\n    \"attributes\": [\n      { \"name\": \"gradientScale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"useNesterov\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"use_nesterov\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"use_locking\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"gradient_scale\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"accumulate\" },\n      { \"name\": \"learning_rate\" },\n      { \"name\": \"gradient\" },\n      { \"name\": \"moment\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"outMaxValue\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"topK\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"keepDims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"axisType\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMaxFusion\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"top_k\", \"type\": \"int64\", \"default\": 1 },\n      { \"name\": \"keep_dims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"out_max_value\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"ArgMin\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"outMaxValue\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"topK\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"keepDims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"axisType\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMinFusion\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"top_k\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"keep_dims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"out_max_value\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Asin\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Assert\",\n    \"attributes\": [\n      { \"name\": \"summarize\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Assign\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"AssignAdd\"\n  },\n  {\n    \"name\": \"Atan\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Attention\",\n    \"category\": \"Attention\",\n    \"attributes\": [\n      { \"name\": \"head_num\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"head_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"cross\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"AudioSpectrogram\",\n    \"attributes\": [\n      { \"name\": \"windowSize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"magSquare\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"window_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"mag_square\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"spectrogram\" }\n    ]\n  },\n  {\n    \"name\": \"AvgPoolFusion\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"strides\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"round_mode\", \"type\": \"RoundMode\", \"default\": \"FLOOR\" },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"global\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"AvgPoolGrad\",\n    \"attributes\": [\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"strides\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"is_training\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormFold\"\n  },\n  {\n    \"name\": \"BatchNormGrad\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"is_training\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"BatchToSpace\",\n    \"attributes\": [\n      { \"name\": \"blockShape\", \"type\": \"int32[]\" },\n      { \"name\": \"crops\", \"type\": \"Vec2D\" },\n      { \"name\": \"block_size\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BatchToSpaceND\",\n    \"attributes\": [\n      { \"name\": \"blockShape\", \"type\": \"int32[]\" },\n      { \"name\": \"crops\", \"type\": \"Vec2D\" },\n      { \"name\": \"block_shape\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BiasAdd\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32[]\" },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"value\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BiasAddGrad\"\n  },\n  {\n    \"name\": \"BiasGrad\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BinaryCrossEntropy\",\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"Reduction\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"BinaryCrossEntropyGrad\",\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"Reduction\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"BlackBox\",\n    \"attributes\": [\n      { \"name\": \"id\", \"type\": \"string\" },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"address\", \"type\": \"ubyte[]\" }\n    ]\n  },\n  {\n    \"name\": \"BNGrad\",\n    \"attributes\": [\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"momentum\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"yt\" },\n      { \"name\": \"x\" },\n      { \"name\": \"scale\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" }\n    ]\n  },\n  {\n    \"name\": \"Broadcast\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BroadcastTo\",\n    \"attributes\": [\n      { \"name\": \"dst_shape\", \"type\": \"int32[]\" },\n      { \"name\": \"shape\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Call\",\n    \"attributes\": [\n      { \"name\": \"is_tail_call\", \"type\": \"boolean\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"Cast\",\n    \"attributes\": [\n      { \"name\": \"srcT\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dstT\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Ceil\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Clip\",\n    \"attributes\": [\n      { \"name\": \"max\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"min\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"n\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Constant\",\n    \"category\": \"Constant\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConstantOfShape\",\n    \"attributes\": [\n      { \"name\": \"dataType\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"value\", \"type\": \"float32[]\", \"default\": 0 },\n      { \"name\": \"data_type\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ControlDepend\",\n    \"attributes\": [\n      { \"name\": \"depend_mode\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Conv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"group\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelOut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2DBackpropFilterFusion\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2DBackpropInputFusion\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2DFusion\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2DGradFilter\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"group\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelOut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"dy\" },\n      { \"name\": \"x\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dw\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2DGradInput\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"group\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelOut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"dy\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2dTransposeFusion\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" },\n      { \"name\": \"output_paddings\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Cos\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Crop\",\n    \"category\": \"Data\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"offsets\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"CropAndResize\",\n    \"attributes\": [\n      { \"name\": \"method\", \"type\": \"ResizeMethod\", \"default\": \"LINEAR\" },\n      { \"name\": \"extrapolation_value\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"CumSum\",\n    \"attributes\": [\n      { \"name\": \"exclusive\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"reverse\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Custom\",\n    \"attributes\": [\n      { \"name\": \"custom\", \"type\": \"ubyte[]\" },\n      { \"name\": \"type\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"attr\", \"type\": \"Attribute[]\" }\n    ]\n  },\n  {\n    \"name\": \"CustomExtractFeatures\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"label\" },\n      { \"name\": \"weight\" }\n    ]\n  },\n  {\n    \"name\": \"CustomNormalize\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"CustomPredict\",\n    \"attributes\": [\n      { \"name\": \"outputNum\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"weightThreshold\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"output_num\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"weight_threshold\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"key\" },\n      { \"name\": \"label\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"label\" },\n      { \"name\": \"weight\" }\n    ]\n  },\n  {\n    \"name\": \"DeConv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"group\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelOut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DeConv2DGradFilter\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelOut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"dy\" },\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dw\" }\n    ]\n  },\n  {\n    \"name\": \"DeDepthwiseConv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelMultipiler\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Depend\"\n  },\n  {\n    \"name\": \"DepthToSpace\",\n    \"attributes\": [\n      { \"name\": \"blockSize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"block_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"string\", \"default\": null }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DepthwiseConv2D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelMultipiler\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DetectionPostProcess\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"inputSize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hScale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"wScale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"xScale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"yScale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"NmsIouThreshold\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"NmsScoreThreshold\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"MaxDetections\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"DetectionsPerClass\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"MaxClassesPerDetection\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"NumClasses\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"UseRegularNms\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"OutQuantized\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"input_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"scale\", \"type\": \"float32[]\", \"default\": 0 },\n      { \"name\": \"nms_iou_threshold\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"nms_score_threshold\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"max_detections\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"detections_per_class\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"max_classes_per_detection\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_classes\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"use_regular_nms\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"out_quantized\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"box\" },\n      { \"name\": \"score\" },\n      { \"name\": \"anchor\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"box\" },\n      { \"name\": \"class\" },\n      { \"name\": \"score\" },\n      { \"name\": \"num\" }\n    ]\n  },\n  {\n    \"name\": \"Div\",\n    \"attributes\": [\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"DivFusion\",\n    \"attributes\": [\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"DivGrad\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx1\" },\n      { \"name\": \"dx2\" }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"ratio\", \"type\": \"float32\", \"default\": 0.5 },\n      { \"name\": \"keep_prob\", \"type\": \"float32\", \"default\": 0.5 }\n    ]\n  },\n  {\n    \"name\": \"DropoutGrad\",\n    \"attributes\": [\n      { \"name\": \"ratio\", \"type\": \"float32\", \"default\": 0.5 },\n      { \"name\": \"keep_prob\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"DynamicQuant\",\n    \"attributes\": [\n      { \"name\": \"symmetric\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"dst_type\", \"type\": \"int64\", \"default\": 32 },\n      { \"name\": \"activation_channel\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"prefer_axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"transpose\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"prefer_axes\", \"type\": \"int32[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Eltwise\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"EltwiseMode\", \"default\": \"PROD\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"Elu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"EmbeddingLookup\",\n    \"attributes\": [\n      { \"name\": \"maxNorm\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"EmbeddingLookupFusion\",\n    \"attributes\": [\n      { \"name\": \"max_norm\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"EmbeddingLookupSparse\",\n    \"attributes\": [\n      { \"name\": \"spIds\", \"type\": \"int32[]\" },\n      { \"name\": \"spWeights\", \"type\": \"float32[]\" },\n      { \"name\": \"maxNortm\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Equal\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"Erf\"\n  },\n  {\n    \"name\": \"Exp\",\n    \"attributes\": [\n      { \"name\": \"base\", \"type\": \"float32\", \"default\": -1 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"attributes\": [\n      { \"name\": \"dim\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ExpFusion\",\n    \"attributes\": [\n      { \"name\": \"base\", \"type\": \"float32\", \"default\": -1 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantWithMinMax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantWithMinMaxPerChannel\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantWithMinMaxVars\",\n    \"attributes\": [\n      { \"name\": \"narrowRange\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"numBits\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"num_bits\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"narrow_range\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantWithMinMaxVarsPerChannel\",\n    \"attributes\": [\n      { \"name\": \"num_bits\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"narrow_range\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"FftImag\"\n  },\n  {\n    \"name\": \"FftReal\"\n  },\n  {\n    \"name\": \"Fill\",\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FillV2\"\n  },\n  {\n    \"name\": \"Flatten\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FlattenGrad\"\n  },\n  {\n    \"name\": \"Floor\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"FloorDiv\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"FloorMod\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"FormatTranspose\",\n    \"attributes\": [\n      { \"name\": \"src_format\", \"type\": \"Format\", \"default\": \"NHWC\" },\n      { \"name\": \"dst_format\", \"type\": \"Format\", \"default\": \"NHWC\" }\n    ]\n  },\n  {\n    \"name\": \"FullConnection\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"useAxis\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" },\n      { \"name\": \"has_bias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"use_axis\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FusedBatchNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"momentum\", \"type\": \"float32\", \"default\": 0.9 },\n      { \"name\": \"spatial\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"mode\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"var\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"var\" }\n    ]\n  },\n  {\n    \"name\": \"Gather\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"batchDims\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"indices\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"GatherD\"\n  },\n  {\n    \"name\": \"GatherNd\",\n    \"attributes\": [\n      { \"name\": \"batchDims\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"indices\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"GenOP\",\n    \"attributes\": [\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"min_val\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"max_val\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"is_training\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"dilation\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"pad_list\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"group\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"in_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"out_channel\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"eltwise_mode\", \"type\": \"EltwiseMode\", \"default\": \"PROD\" },\n      { \"name\": \"has_bias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"use_axis\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"momentum\", \"type\": \"float32\", \"default\": 0.9 },\n      { \"name\": \"transpose_a\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transpose_b\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"pad\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"round_mode\", \"type\": \"RoundMode\", \"default\": \"FLOOR\" },\n      { \"name\": \"global\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"channel_shared\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"axes\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"keep_dims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"reduce_mode\", \"type\": \"ReduceMode\", \"default\": \"ReduceMean\" },\n      { \"name\": \"reduce_to_end\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"coeff\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"GLU\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": -1 }\n    ]\n  },\n  {\n    \"name\": \"Greater\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"GreaterEqual\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"GroupConv2DGradInput\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"group\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelIn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"channelOut\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernelH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilateH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"hasBias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"dy\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx\" }\n    ]\n  },\n  {\n    \"name\": \"GroupNormFusion\",\n    \"attributes\": [\n      { \"name\": \"num_groups\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"affine\", \"type\": \"boolean\", \"default\": true }\n    ]\n  },\n  {\n    \"name\": \"GRU\",\n    \"attributes\": [\n      { \"name\": \"bidirectional\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"HashtableLookup\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"key\" },\n      { \"name\": \"value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hit\" }\n    ]\n  },\n  {\n    \"name\": \"Identity\",\n    \"category\": \"Control\"\n  },\n  {\n    \"name\": \"If\"\n  },\n  {\n    \"name\": \"InstanceNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.00001 }\n    ],\n    \"inputs\": [\n      { \"name\": \"src\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"InvertPermutation\"\n  },\n  {\n    \"name\": \"IsFinite\"\n  },\n  {\n    \"name\": \"L2Norm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32[]\" },\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"ActivationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"L2NormalizeFusion\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"normalizedShape\", \"type\": \"int32[]\" },\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"elementwiseAffine\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"src\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LayerNormFusion\",\n    \"attributes\": [\n      { \"name\": \"begin_norm_axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"epsilon\", \"type\": \"float32\", \"default\": 0.00001 },\n      { \"name\": \"elementwise_affine\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"begin_params_axis\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LayerNormGrad\",\n    \"attributes\": [\n      { \"name\": \"begin_norm_axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"begin_params_axis\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LeakyRelu\",\n    \"attributes\": [\n      { \"name\": \"negative_slope\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LeakyReLU\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"negativeSlope\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Less\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"LessEqual\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"LinSpace\"\n  },\n  {\n    \"name\": \"LocalResponseNormalization\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"depth_radius\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Log\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Log1p\"\n  },\n  {\n    \"name\": \"LogGrad\",\n    \"inputs\": [\n      { \"name\": \"dy\" },\n      { \"name\": \"in_x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalAnd\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalNot\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalOr\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalXor\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"LogSoftmax\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Loop\",\n    \"attributes\": [\n      { \"name\": \"subGraphIndex\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LpNormalization\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"p\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Lrn\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.75 },\n      { \"name\": \"bias\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"size\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"attributes\": [\n      { \"name\": \"depth_radius\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"bias\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"norm_region\", \"type\": \"string\", \"default\": null }\n    ]\n  },\n  {\n    \"name\": \"LshProjection\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"LshProjectionType\", \"default\": \"UNKNOWN\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"hash\" },\n      { \"name\": \"in_data\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Lstm\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"bidirection\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight_i\" },\n      { \"name\": \"weight_h\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"hidden_state\" },\n      { \"name\": \"cell_state\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"hidden_state\" },\n      { \"name\": \"cell_state\" }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"attributes\": [\n      { \"name\": \"bidirectional\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"has_bias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"input_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"hidden_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_layers\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_directions\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"dropout\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_cell\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_hidden\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"proj_size\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LSTMGrad\",\n    \"attributes\": [\n      { \"name\": \"bidirectional\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"has_bias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"input_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"hidden_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_layers\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_directions\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"dropout\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_cell\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_hidden\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LSTMGradData\",\n    \"attributes\": [\n      { \"name\": \"bidirectional\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"has_bias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"input_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"hidden_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_layers\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_directions\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"dropout\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_cell\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_hidden\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LSTMGradWeight\",\n    \"attributes\": [\n      { \"name\": \"bidirectional\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"has_bias\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"input_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"hidden_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_layers\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"num_directions\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"dropout\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_cell\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"zoneout_hidden\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"make_tuple\"\n  },\n  {\n    \"name\": \"MakeTuple\"\n  },\n  {\n    \"name\": \"MatMul\",\n    \"attributes\": [\n      { \"name\": \"broadcast\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transposeA\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transposeB\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transpose_a\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transpose_b\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"MatMulFusion\",\n    \"attributes\": [\n      { \"name\": \"transpose_a\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"transpose_b\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"MatrixDiag\",\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"numRows\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"numCols\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"paddingValue\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Maximum\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"MaximumGrad\",\n    \"attributes\": [\n      { \"name\": \"grad_x\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"grad_y\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"MaxPoolFusion\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"strides\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"round_mode\", \"type\": \"RoundMode\", \"default\": \"FLOOR\" },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"global\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"MaxPoolGrad\",\n    \"attributes\": [\n      { \"name\": \"kernel_size\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"strides\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"type\": \"PadMode\", \"default\": \"PAD\" },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" }\n    ]\n  },\n  {\n    \"name\": \"Mean\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32[]\" },\n      { \"name\": \"keepDims\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Merge\"\n  },\n  {\n    \"name\": \"Mfcc\",\n    \"attributes\": [\n      { \"name\": \"freqUpperLimit\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"freqLowerLimit\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"filterBankChannelNum\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dctCoeffNum\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"freq_upper_limit\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"freq_lower_limit\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"filter_bank_channel_num\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"dct_coeff_num\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Min\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Minimum\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"MinimumGrad\",\n    \"attributes\": [\n      { \"name\": \"grad_x\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"grad_y\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Mod\"\n  },\n  {\n    \"name\": \"Mul\",\n    \"attributes\": [\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"MulFold\"\n  },\n  {\n    \"name\": \"MulFusion\",\n    \"attributes\": [\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"MulGrad\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx1\" },\n      { \"name\": \"dx2\" }\n    ]\n  },\n  {\n    \"name\": \"Nchw2Nhwc\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Neg\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"NegGrad\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NetOutput\"\n  },\n  {\n    \"name\": \"Nhwc2Nchw\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NLLLoss\",\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"Reduction\", \"default\": \"REDUCTION_SUM\" }\n    ]\n  },\n  {\n    \"name\": \"NLLLossGrad\",\n    \"attributes\": [\n      { \"name\": \"reduction\", \"type\": \"Reduction\", \"default\": \"REDUCTION_SUM\" }\n    ]\n  },\n  {\n    \"name\": \"NonMaxSuppression\",\n    \"attributes\": [\n      { \"name\": \"centerPointBox\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"center_point_box\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"box\" },\n      { \"name\": \"score\" },\n      { \"name\": \"max_output\" },\n      { \"name\": \"iou_threshold\" },\n      { \"name\": \"core_threshold\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NonZero\"\n  },\n  {\n    \"name\": \"NotEqual\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"OneHot\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"indices\" },\n      { \"name\": \"depth\" },\n      { \"name\": \"on_value\" },\n      { \"name\": \"off_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"OnesLike\"\n  },\n  {\n    \"name\": \"OnnxInt8Dequantize\"\n  },\n  {\n    \"name\": \"OnnxInt8Quantize\"\n  },\n  {\n    \"name\": \"Pad\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"paddings\", \"type\": \"int32[]\" },\n      { \"name\": \"paddingMode\", \"type\": \"PaddingMode\" },\n      { \"name\": \"constantValue\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"paddings\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"PadFusion\",\n    \"attributes\": [\n      { \"name\": \"paddings\", \"type\": \"Vec2D\" },\n      { \"name\": \"padding_mode\", \"type\": \"PaddingMode\", \"default\": \"CONSTANT\" },\n      { \"name\": \"constant_value\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Partial\",\n    \"attributes\": [\n      { \"name\": \"subGraphIndex\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"PartialFusion\",\n    \"attributes\": [\n      { \"name\": \"sub_graph_index\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Permute\",\n    \"attributes\": [\n      { \"name\": \"order\", \"type\": \"int64[]\" }\n    ]\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"poolingMode\", \"type\": \"PoolMode\" },\n      { \"name\": \"global\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"windowW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"windowH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"roundMode\", \"type\": \"RoundMode\" },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" },\n      { \"name\": \"avgMode\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"PoolingGrad\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"poolingMode\", \"type\": \"PoolMode\" },\n      { \"name\": \"global\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"windowW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"windowH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"strideH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padMode\", \"type\": \"PadMode\" },\n      { \"name\": \"padUp\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padDown\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padLeft\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"padRight\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"roundMode\", \"type\": \"RoundMode\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"dx\" },\n      { \"name\": \"dy\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Power\",\n    \"attributes\": [\n      { \"name\": \"base\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"PowerGrad\",\n    \"attributes\": [\n      { \"name\": \"power\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"dy\" },\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx\" }\n    ]\n  },\n  {\n    \"name\": \"PowFusion\",\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Prelu\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"channelShared\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"slope\", \"type\": \"float32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"negative_slope\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"PReLUFusion\",\n    \"attributes\": [\n      { \"name\": \"channel_shared\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"PriorBox\",\n    \"attributes\": [\n      { \"name\": \"min_sizes\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"max_sizes\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"aspect_ratios\", \"type\": \"float32[]\", \"default\": 0 },\n      { \"name\": \"variances\", \"type\": \"float32[]\", \"default\": 0 },\n      { \"name\": \"image_size_w\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"image_size_h\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"step_w\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"step_h\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"clip\", \"type\": \"boolean\", \"default\": true },\n      { \"name\": \"flip\", \"type\": \"boolean\", \"default\": true },\n      { \"name\": \"offset\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"fmap\" },\n      { \"name\": \"image\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Proposal\",\n    \"attributes\": [\n      { \"name\": \"feat_stride\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"base_size\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"min_size\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"ratio\", \"type\": \"float32[]\" },\n      { \"name\": \"scale\", \"type\": \"float32[]\" },\n      { \"name\": \"pre_nms_topn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"post_nms_topn\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"nms_thresh\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"QuantDTypeCast\",\n    \"attributes\": [\n      { \"name\": \"srcT\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dstT\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"src_t\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"dst_t\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"RaggedRange\"\n  },\n  {\n    \"name\": \"RandomNormal\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"mean\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"RandomStandardNormal\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"seed2\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Range\",\n    \"attributes\": [\n      { \"name\": \"dType\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"start\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"limit\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"delta\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"d_type\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Rank\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"RealDiv\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"Reciprocal\"\n  },\n  {\n    \"name\": \"Reduce\",\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"int32[]\" },\n      { \"name\": \"keepDims\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"mode\", \"type\": \"ReduceMode\" },\n      { \"name\": \"reduceToEnd\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"coeff\", \"type\": \"float32\", \"default\": 1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceFusion\",\n    \"attributes\": [\n      { \"name\": \"keep_dims\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"mode\", \"type\": \"ReduceMode\", \"default\": \"ReduceMean\" },\n      { \"name\": \"reduce_to_end\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"coeff\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ReduceScatter\",\n    \"attributes\": [\n      { \"name\": \"group\", \"type\": \"string\", \"default\": null },\n      { \"name\": \"mode\", \"type\": \"ReduceMode\", \"default\": \"ReduceMean\" },\n      { \"name\": \"rank_size\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"shape\", \"type\": \"int64[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Resize\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"method\", \"type\": \"ResizeMethod\", \"default\": 0 },\n      { \"name\": \"newHeight\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"newWidth\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"alignCorners\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"preserveAspectRatio\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"coordinateTransformMode\", \"type\": \"CoordinateTransformMode\" },\n      { \"name\": \"cubicCoeff\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"excludeOutside\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"extrapolationValue\", \"float32\": \"float32\", \"default\": 0 },\n      { \"name\": \"nearestMode\", \"type\": \"NearestMode\" },\n      { \"name\": \"new_height\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"new_width\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"preserve_aspect_ratio\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"coordinate_transform_mode\", \"type\": \"CoordinateTransformMode\", \"default\": \"ASYMMETRIC\" },\n      { \"name\": \"cubic_coeff\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"exclude_outside\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"extrapolation_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"nearest_mode\", \"type\": \"NearestMode\", \"default\": \"NORMAL\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeGrad\",\n    \"attributes\": [\n      { \"name\": \"method\", \"type\": \"ResizeMethod\", \"default\": \"LINEAR\" },\n      { \"name\": \"align_corners\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"Return\"\n  },\n  {\n    \"name\": \"Reverse\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReverseSequence\",\n    \"attributes\": [\n      { \"name\": \"seqAxis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"batchAxis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"seq_dim\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"batch_dim\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"seq_lengths\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ReverseV2\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Rfft\",\n    \"attributes\": [\n      { \"name\": \"fftLength\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"fft_length\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"attributes\": [\n      { \"name\": \"pooledH\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pooledW\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"pooled_h\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"pooled_w\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"roi\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Round\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Rsqrt\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RsqrtGrad\"\n  },\n  {\n    \"name\": \"Scale\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"offset\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ScaleFusion\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"Scatter\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"update\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ScatterElements\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ScatterNd\"\n  },\n  {\n    \"name\": \"ScatterND\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"update\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ScatterNdUpdate\"\n  },\n  {\n    \"name\": \"Select\",\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Sgd\",\n    \"attributes\": [\n      { \"name\": \"weightDecay\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"dampening\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"useNesterov\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"weight\" },\n      { \"name\": \"gradient\" },\n      { \"name\": \"learning_rate\" },\n      { \"name\": \"accumulate\" },\n      { \"name\": \"moment\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SGD\",\n    \"attributes\": [\n      { \"name\": \"nesterov\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"dampening\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"weight_decay\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SigmoidCrossEntropyWithLogits\"\n  },\n  {\n    \"name\": \"SigmoidCrossEntropyWithLogitsGrad\"\n  },\n  {\n    \"name\": \"Sin\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Size\"\n  },\n  {\n    \"name\": \"SkipGram\",\n    \"attributes\": [\n      { \"name\": \"includeAllGrams\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"maxSkipSize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"ngramSize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"include_all_grams\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"max_skip_size\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"ngram_size\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Slice\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"format\", \"type\": \"Format\" },\n      { \"name\": \"axes\", \"type\": \"int32[]\" },\n      { \"name\": \"begin\", \"type\": \"int32[]\" },\n      { \"name\": \"size\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SliceFusion\",\n    \"attributes\": [\n      { \"name\": \"axes\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SmoothL1Loss\",\n    \"attributes\": [\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SmoothL1LossGrad\",\n    \"attributes\": [\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SoftMax\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": -1 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxCrossEntropy\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"labels\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"grads\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxCrossEntropyWithLogits\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SpaceToBatch\",\n    \"attributes\": [\n      { \"name\": \"blockShape\", \"type\": \"int32[]\" },\n      { \"name\": \"paddings\", \"type\": \"Vec2D\" },\n      { \"name\": \"block_size\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"SpaceToBatchND\",\n    \"attributes\": [\n      { \"name\": \"blockShape\", \"type\": \"int32[]\" },\n      { \"name\": \"paddings\", \"type\": \"Vec2D\" },\n      { \"name\": \"block_shape\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SpaceToDepth\",\n    \"attributes\": [\n      { \"name\": \"blockSize\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"format\", \"type\": \"Format\", \"default\": \"NCHW\" },\n      { \"name\": \"block_size\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SparseFillEmptyRows\"\n  },\n  {\n    \"name\": \"SparseReshape\"\n  },\n  {\n    \"name\": \"SparseSegmentSum\"\n  },\n  {\n    \"name\": \"SparseSoftmaxCrossEntropyWithLogits\",\n    \"attributes\": [\n      { \"name\": \"grad\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"is_grad\", \"type\": \"boolean\", \"default\": false }\n    ]\n  },\n  {\n    \"name\": \"SparseToDense\",\n    \"attributes\": [\n      { \"name\": \"validateIndices\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"sparse_indices\" },\n      { \"name\": \"out_shape\" },\n      { \"name\": \"sparse_values\" },\n      { \"name\": \"default_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Splice\",\n    \"attributes\": [\n      { \"name\": \"context\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"forward_indexes\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"output_dim\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Split\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"numberSplit\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"sizeSplits\", \"type\": \"int32[]\" },\n      { \"name\": \"splitDim\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"output_num\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"size_splits\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"SplitWithOverlap\",\n    \"attributes\": [\n      { \"name\": \"number_split\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"ratio\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"extend_top\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"extend_bottom\", \"type\": \"int64[]\", \"default\": 0 },\n      { \"name\": \"split_dim\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"stride\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"pad_top\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"trans_format\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"split_stride\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Sqrt\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SqrtGrad\"\n  },\n  {\n    \"name\": \"Square\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SquaredDifference\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Stack\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"n\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"isScale\", \"type\": \"int32[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSlice\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"beginMask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"endMask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"ellipsisMask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"newAxisMask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"shrinkAxisMask\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"begin\", \"type\": \"int32[]\" },\n      { \"name\": \"end\", \"type\": \"int32[]\" },\n      { \"name\": \"stride\", \"type\": \"int32[]\" },\n      { \"name\": \"isScale\", \"type\": \"int32[]\" },\n      { \"name\": \"begin_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"end_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"ellipsis_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"new_axis_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"begins\" },\n      { \"name\": \"ends\" },\n      { \"name\": \"strides\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSliceGrad\",\n    \"attributes\": [\n      { \"name\": \"begin_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"end_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"ellipsis_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"new_axis_mask\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"shrink_axis_mask\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Sub\",\n    \"attributes\": [\n      { \"name\": \"activationType\", \"type\": \"ActivationType\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"SubFusion\",\n    \"attributes\": [\n      { \"name\": \"activation_type\", \"type\": \"ActivationType\", \"default\": \"NO_ACTIVATION\" }\n    ]\n  },\n  {\n    \"name\": \"SubGrad\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dx1\" },\n      { \"name\": \"dx2\" }\n    ]\n  },\n  {\n    \"name\": \"Switch\"\n  },\n  {\n    \"name\": \"SwitchLayer\"\n  },\n  {\n    \"name\": \"Tan\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"TensorArray\",\n    \"attributes\": [\n      { \"name\": \"dynamic_size\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"identical_element_shapes\", \"type\": \"boolean\", \"default\": false },\n      { \"name\": \"element_shape\", \"type\": \"int32[]\", \"default\": 0 },\n      { \"name\": \"data_type\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TensorArrayRead\"\n  },\n  {\n    \"name\": \"TensorArrayWrite\"\n  },\n  {\n    \"name\": \"TensorListFromTensor\",\n    \"attributes\": [\n      { \"name\": \"element_dtype\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"shape_type\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TensorListGetItem\",\n    \"attributes\": [\n      { \"name\": \"elementDType\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"element_dtype\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TensorListReserve\",\n    \"attributes\": [\n      { \"name\": \"elementDType\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"element_dtype\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"shape_type\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TensorListSetItem\",\n    \"attributes\": [\n      { \"name\": \"element_dtype\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TensorListStack\",\n    \"attributes\": [\n      { \"name\": \"numElements\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"elementDType\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"num_elements\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"element_dtype\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TensorScatterAdd\"\n  },\n  {\n    \"name\": \"TfReduce\",\n    \"attributes\": [\n      { \"name\": \"type\", \"type\": \"ReduceType\" }\n    ]\n  },\n  {\n    \"name\": \"Tile\",\n    \"attributes\": [\n      { \"name\": \"multiples\", \"type\": \"int32[]\" },\n      { \"name\": \"dims\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"TileFusion\",\n    \"attributes\": [\n      { \"name\": \"dims\", \"type\": \"int64[]\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ToFormat\",\n    \"attributes\": [\n      { \"name\": \"srcT\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dstT\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"TopK\",\n    \"attributes\": [\n      { \"name\": \"k\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"sorted\", \"type\": \"boolean\", \"default\": true }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output_data\" },\n      { \"name\": \"output_index\" }\n    ]\n  },\n  {\n    \"name\": \"TopKFusion\",\n    \"attributes\": [\n      { \"name\": \"sorted\", \"type\": \"boolean\", \"default\": true },\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"largest\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Transpose\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"perm\", \"type\": \"int32[]\" },\n      { \"name\": \"conjugate\", \"type\": \"boolean\", \"default\": false }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"perm\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Tril\"\n  },\n  {\n    \"name\": \"Triu\"\n  },\n  {\n    \"name\": \"TupleGetItem\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"UniformReal\",\n    \"attributes\": [\n      { \"name\": \"seed\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"seed2\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Unique\",\n    \"attributes\": [\n      { \"name\": \"outType\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output0\" },\n      { \"name\": \"output1\" }\n    ]\n  },\n  {\n    \"name\": \"UnsortedSegmentSum\",\n    \"attributes\": [\n      { \"name\": \"numSegments\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Unsqueeze\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int64[]\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Unstack\",\n    \"attributes\": [\n      { \"name\": \"num\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"axis\", \"type\": \"int64\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"Upsample\",\n    \"category\": \"Data\",\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"string\" },\n      { \"name\": \"scales\", \"type\": \"float32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ]\n  },\n  {\n    \"name\": \"Where\",\n    \"attributes\": [\n      { \"name\": \"condition\", \"type\": \"boolean[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"input1\" },\n      { \"name\": \"input2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"While\",\n    \"attributes\": [\n      { \"name\": \"condSubgraphIndex\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bodySubgraphIndex\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"cond_subgraph_index\", \"type\": \"int64\", \"default\": 0 },\n      { \"name\": \"body_subgraph_index\", \"type\": \"int64\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ZerosLike\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/mslite-schema.js",
    "content": "\nexport const mindspore = {};\n\nmindspore.schema = mindspore.schema || {};\n\nmindspore.schema.ResizeMethod = {\n    UNKNOWN: -1, '-1': 'UNKNOWN',\n    LINEAR: 0, '0': 'LINEAR',\n    NEAREST: 1, '1': 'NEAREST',\n    CUBIC: 2, '2': 'CUBIC'\n};\n\nmindspore.schema.CoordinateTransformMode = {\n    ASYMMETRIC: 0, '0': 'ASYMMETRIC',\n    ALIGN_CORNERS: 1, '1': 'ALIGN_CORNERS',\n    HALF_PIXEL: 2, '2': 'HALF_PIXEL'\n};\n\nmindspore.schema.NearestMode = {\n    NORMAL: 0, '0': 'NORMAL',\n    ROUND_HALF_DOWN: 1, '1': 'ROUND_HALF_DOWN',\n    ROUND_HALF_UP: 2, '2': 'ROUND_HALF_UP',\n    FLOOR: 3, '3': 'FLOOR',\n    CEIL: 4, '4': 'CEIL'\n};\n\nmindspore.schema.Format = {\n    NCHW: 0, '0': 'NCHW',\n    NHWC: 1, '1': 'NHWC',\n    NHWC4: 2, '2': 'NHWC4',\n    HWKC: 3, '3': 'HWKC',\n    HWCK: 4, '4': 'HWCK',\n    KCHW: 5, '5': 'KCHW',\n    CKHW: 6, '6': 'CKHW',\n    KHWC: 7, '7': 'KHWC',\n    CHWK: 8, '8': 'CHWK',\n    HW: 9, '9': 'HW',\n    HW4: 10, '10': 'HW4',\n    NC: 11, '11': 'NC',\n    NC4: 12, '12': 'NC4',\n    NC4HW4: 13, '13': 'NC4HW4',\n    NUM_OF_FORMAT: 14, '14': 'NUM_OF_FORMAT',\n    NCDHW: 15, '15': 'NCDHW',\n    NWC: 16, '16': 'NWC',\n    NCW: 17, '17': 'NCW',\n    NC8HW8: 18, '18': 'NC8HW8'\n};\n\nmindspore.schema.ActivationType = {\n    NO_ACTIVATION: 0, '0': 'NO_ACTIVATION',\n    RELU: 1, '1': 'RELU',\n    SIGMOID: 2, '2': 'SIGMOID',\n    RELU6: 3, '3': 'RELU6',\n    ELU: 4, '4': 'ELU',\n    LEAKY_RELU: 5, '5': 'LEAKY_RELU',\n    ABS: 6, '6': 'ABS',\n    RELU1: 7, '7': 'RELU1',\n    SOFTSIGN: 8, '8': 'SOFTSIGN',\n    SOFTPLUS: 9, '9': 'SOFTPLUS',\n    TANH: 10, '10': 'TANH',\n    SELU: 11, '11': 'SELU',\n    HSWISH: 12, '12': 'HSWISH',\n    HSIGMOID: 13, '13': 'HSIGMOID',\n    THRESHOLDRELU: 14, '14': 'THRESHOLDRELU',\n    LINEAR: 15, '15': 'LINEAR',\n    HARD_TANH: 16, '16': 'HARD_TANH',\n    SIGN: 17, '17': 'SIGN',\n    SWISH: 18, '18': 'SWISH',\n    GELU: 19, '19': 'GELU',\n    FAST_GELU: 20, '20': 'FAST_GELU',\n    UNKNOWN: 21, '21': 'UNKNOWN'\n};\n\nmindspore.schema.ReduceMode = {\n    ReduceMean: 0, '0': 'ReduceMean',\n    ReduceMax: 1, '1': 'ReduceMax',\n    ReduceMin: 2, '2': 'ReduceMin',\n    ReduceProd: 3, '3': 'ReduceProd',\n    ReduceSum: 4, '4': 'ReduceSum',\n    ReduceSumSquare: 5, '5': 'ReduceSumSquare',\n    ReduceASum: 6, '6': 'ReduceASum',\n    ReduceAll: 7, '7': 'ReduceAll',\n    ReduceL2: 8, '8': 'ReduceL2'\n};\n\nmindspore.schema.PoolMode = {\n    MAX_POOLING: 0, '0': 'MAX_POOLING',\n    MEAN_POOLING: 1, '1': 'MEAN_POOLING'\n};\n\nmindspore.schema.EltwiseMode = {\n    PROD: 0, '0': 'PROD',\n    SUM: 1, '1': 'SUM',\n    MAXIMUM: 2, '2': 'MAXIMUM',\n    UNKNOWN: 3, '3': 'UNKNOWN'\n};\n\nmindspore.schema.PadMode = {\n    PAD: 0, '0': 'PAD',\n    SAME: 1, '1': 'SAME',\n    VALID: 2, '2': 'VALID'\n};\n\nmindspore.schema.RoundMode = {\n    FLOOR: 0, '0': 'FLOOR',\n    CEIL: 1, '1': 'CEIL'\n};\n\nmindspore.schema.PaddingMode = {\n    CONSTANT: 0, '0': 'CONSTANT',\n    REFLECT: 1, '1': 'REFLECT',\n    SYMMETRIC: 2, '2': 'SYMMETRIC',\n    MODE_RESERVED: 3, '3': 'MODE_RESERVED'\n};\n\nmindspore.schema.LshProjectionType = {\n    UNKNOWN: 0, '0': 'UNKNOWN',\n    SPARSE: 1, '1': 'SPARSE',\n    DENSE: 2, '2': 'DENSE'\n};\n\nmindspore.schema.Reduction = {\n    REDUCTION_SUM: 0, '0': 'REDUCTION_SUM',\n    MEAN: 1, '1': 'MEAN',\n    NONE: 2, '2': 'NONE'\n};\n\nmindspore.schema.Vec = class Vec {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Vec();\n        $.data = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Vec();\n        $.data = reader.array(json.data);\n        return $;\n    }\n};\n\nmindspore.schema.Vec2D = class Vec2D {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Vec2D();\n        $.data = reader.tables(position, 4, mindspore.schema.Vec);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Vec2D();\n        $.data = reader.objects(json.data, mindspore.schema.Vec);\n        return $;\n    }\n};\n\nmindspore.schema.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Attribute();\n        $.name = reader.string_(position, 4, null);\n        $.data = reader.array(position, 6, Uint8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Attribute();\n        $.name = reader.value(json.name, null);\n        $.data = reader.array(json.data, Uint8Array);\n        return $;\n    }\n};\n\nmindspore.schema.PrimitiveType = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return mindspore.schema.Abs.decode(reader, position);\n            case 2: return mindspore.schema.Activation.decode(reader, position);\n            case 3: return mindspore.schema.ActivationGrad.decode(reader, position);\n            case 4: return mindspore.schema.Adam.decode(reader, position);\n            case 5: return mindspore.schema.AddFusion.decode(reader, position);\n            case 6: return mindspore.schema.AdderFusion.decode(reader, position);\n            case 7: return mindspore.schema.AddGrad.decode(reader, position);\n            case 8: return mindspore.schema.AddN.decode(reader, position);\n            case 9: return mindspore.schema.All.decode(reader, position);\n            case 10: return mindspore.schema.ApplyMomentum.decode(reader, position);\n            case 11: return mindspore.schema.ArgMaxFusion.decode(reader, position);\n            case 12: return mindspore.schema.ArgMinFusion.decode(reader, position);\n            case 13: return mindspore.schema.Assert.decode(reader, position);\n            case 14: return mindspore.schema.Assign.decode(reader, position);\n            case 15: return mindspore.schema.AssignAdd.decode(reader, position);\n            case 16: return mindspore.schema.AudioSpectrogram.decode(reader, position);\n            case 17: return mindspore.schema.AvgPoolFusion.decode(reader, position);\n            case 18: return mindspore.schema.AvgPoolGrad.decode(reader, position);\n            case 19: return mindspore.schema.BatchNorm.decode(reader, position);\n            case 20: return mindspore.schema.BatchNormGrad.decode(reader, position);\n            case 21: return mindspore.schema.BatchToSpace.decode(reader, position);\n            case 22: return mindspore.schema.BatchToSpaceND.decode(reader, position);\n            case 23: return mindspore.schema.BiasAdd.decode(reader, position);\n            case 24: return mindspore.schema.BinaryCrossEntropy.decode(reader, position);\n            case 25: return mindspore.schema.BinaryCrossEntropyGrad.decode(reader, position);\n            case 26: return mindspore.schema.BiasAddGrad.decode(reader, position);\n            case 27: return mindspore.schema.BroadcastTo.decode(reader, position);\n            case 28: return mindspore.schema.Cast.decode(reader, position);\n            case 29: return mindspore.schema.Ceil.decode(reader, position);\n            case 30: return mindspore.schema.Clip.decode(reader, position);\n            case 31: return mindspore.schema.Concat.decode(reader, position);\n            case 32: return mindspore.schema.Attention.decode(reader, position);\n            case 33: return mindspore.schema.Conv2DBackpropFilterFusion.decode(reader, position);\n            case 34: return mindspore.schema.Conv2DBackpropInputFusion.decode(reader, position);\n            case 35: return mindspore.schema.Conv2DFusion.decode(reader, position);\n            case 36: return mindspore.schema.Conv2dTransposeFusion.decode(reader, position);\n            case 37: return mindspore.schema.Cos.decode(reader, position);\n            case 38: return mindspore.schema.ConstantOfShape.decode(reader, position);\n            case 39: return mindspore.schema.Crop.decode(reader, position);\n            case 40: return mindspore.schema.CustomExtractFeatures.decode(reader, position);\n            case 41: return mindspore.schema.CustomNormalize.decode(reader, position);\n            case 42: return mindspore.schema.CustomPredict.decode(reader, position);\n            case 43: return mindspore.schema.DeConv2DGradFilter.decode(reader, position);\n            case 44: return mindspore.schema.Depend.decode(reader, position);\n            case 45: return mindspore.schema.DepthToSpace.decode(reader, position);\n            case 46: return mindspore.schema.DetectionPostProcess.decode(reader, position);\n            case 47: return mindspore.schema.DivFusion.decode(reader, position);\n            case 48: return mindspore.schema.DivGrad.decode(reader, position);\n            case 49: return mindspore.schema.Dropout.decode(reader, position);\n            case 50: return mindspore.schema.DropoutGrad.decode(reader, position);\n            case 51: return mindspore.schema.Elu.decode(reader, position);\n            case 52: return mindspore.schema.Eltwise.decode(reader, position);\n            case 53: return mindspore.schema.Equal.decode(reader, position);\n            case 54: return mindspore.schema.EmbeddingLookupFusion.decode(reader, position);\n            case 55: return mindspore.schema.ExpFusion.decode(reader, position);\n            case 56: return mindspore.schema.ExpandDims.decode(reader, position);\n            case 57: return mindspore.schema.FakeQuantWithMinMaxVars.decode(reader, position);\n            case 58: return mindspore.schema.FakeQuantWithMinMaxVarsPerChannel.decode(reader, position);\n            case 59: return mindspore.schema.FftReal.decode(reader, position);\n            case 60: return mindspore.schema.FftImag.decode(reader, position);\n            case 61: return mindspore.schema.Flatten.decode(reader, position);\n            case 62: return mindspore.schema.FlattenGrad.decode(reader, position);\n            case 63: return mindspore.schema.Floor.decode(reader, position);\n            case 64: return mindspore.schema.FloorDiv.decode(reader, position);\n            case 65: return mindspore.schema.FloorMod.decode(reader, position);\n            case 66: return mindspore.schema.Fill.decode(reader, position);\n            case 67: return mindspore.schema.FullConnection.decode(reader, position);\n            case 68: return mindspore.schema.FusedBatchNorm.decode(reader, position);\n            case 69: return mindspore.schema.Gather.decode(reader, position);\n            case 70: return mindspore.schema.GatherNd.decode(reader, position);\n            case 71: return mindspore.schema.Greater.decode(reader, position);\n            case 72: return mindspore.schema.GreaterEqual.decode(reader, position);\n            case 73: return mindspore.schema.HashtableLookup.decode(reader, position);\n            case 74: return mindspore.schema.InstanceNorm.decode(reader, position);\n            case 75: return mindspore.schema.LayerNormFusion.decode(reader, position);\n            case 76: return mindspore.schema.LeakyRelu.decode(reader, position);\n            case 77: return mindspore.schema.Less.decode(reader, position);\n            case 78: return mindspore.schema.LessEqual.decode(reader, position);\n            case 79: return mindspore.schema.Log.decode(reader, position);\n            case 80: return mindspore.schema.LogGrad.decode(reader, position);\n            case 81: return mindspore.schema.LogicalAnd.decode(reader, position);\n            case 82: return mindspore.schema.LogicalNot.decode(reader, position);\n            case 83: return mindspore.schema.LogicalOr.decode(reader, position);\n            case 84: return mindspore.schema.LpNormalization.decode(reader, position);\n            case 85: return mindspore.schema.LRN.decode(reader, position);\n            case 86: return mindspore.schema.LshProjection.decode(reader, position);\n            case 87: return mindspore.schema.LSTM.decode(reader, position);\n            case 88: return mindspore.schema.L2NormalizeFusion.decode(reader, position);\n            case 89: return mindspore.schema.MatMulFusion.decode(reader, position);\n            case 90: return mindspore.schema.Maximum.decode(reader, position);\n            case 91: return mindspore.schema.MaximumGrad.decode(reader, position);\n            case 92: return mindspore.schema.MaxPoolFusion.decode(reader, position);\n            case 93: return mindspore.schema.MaxPoolGrad.decode(reader, position);\n            case 94: return mindspore.schema.SwitchLayer.decode(reader, position);\n            case 95: return mindspore.schema.Mfcc.decode(reader, position);\n            case 96: return mindspore.schema.Minimum.decode(reader, position);\n            case 97: return mindspore.schema.MinimumGrad.decode(reader, position);\n            case 98: return mindspore.schema.Mod.decode(reader, position);\n            case 99: return mindspore.schema.MulFusion.decode(reader, position);\n            case 100: return mindspore.schema.MulGrad.decode(reader, position);\n            case 101: return mindspore.schema.Neg.decode(reader, position);\n            case 102: return mindspore.schema.NegGrad.decode(reader, position);\n            case 103: return mindspore.schema.NotEqual.decode(reader, position);\n            case 104: return mindspore.schema.NonMaxSuppression.decode(reader, position);\n            case 105: return mindspore.schema.OneHot.decode(reader, position);\n            case 106: return mindspore.schema.OnesLike.decode(reader, position);\n            case 107: return mindspore.schema.PadFusion.decode(reader, position);\n            case 108: return mindspore.schema.PartialFusion.decode(reader, position);\n            case 109: return mindspore.schema.PowerGrad.decode(reader, position);\n            case 110: return mindspore.schema.PowFusion.decode(reader, position);\n            case 111: return mindspore.schema.PriorBox.decode(reader, position);\n            case 112: return mindspore.schema.PReLUFusion.decode(reader, position);\n            case 113: return mindspore.schema.QuantDTypeCast.decode(reader, position);\n            case 114: return mindspore.schema.Rank.decode(reader, position);\n            case 115: return mindspore.schema.Range.decode(reader, position);\n            case 116: return mindspore.schema.Reciprocal.decode(reader, position);\n            case 117: return mindspore.schema.RealDiv.decode(reader, position);\n            case 118: return mindspore.schema.ReduceFusion.decode(reader, position);\n            case 119: return mindspore.schema.Reshape.decode(reader, position);\n            case 120: return mindspore.schema.Resize.decode(reader, position);\n            case 121: return mindspore.schema.ReverseSequence.decode(reader, position);\n            case 122: return mindspore.schema.ReverseV2.decode(reader, position);\n            case 123: return mindspore.schema.Rfft.decode(reader, position);\n            case 124: return mindspore.schema.ROIPooling.decode(reader, position);\n            case 125: return mindspore.schema.Round.decode(reader, position);\n            case 126: return mindspore.schema.Rsqrt.decode(reader, position);\n            case 127: return mindspore.schema.ScaleFusion.decode(reader, position);\n            case 128: return mindspore.schema.ScatterNd.decode(reader, position);\n            case 129: return mindspore.schema.SGD.decode(reader, position);\n            case 130: return mindspore.schema.Shape.decode(reader, position);\n            case 131: return mindspore.schema.SigmoidCrossEntropyWithLogits.decode(reader, position);\n            case 132: return mindspore.schema.SigmoidCrossEntropyWithLogitsGrad.decode(reader, position);\n            case 133: return mindspore.schema.Sin.decode(reader, position);\n            case 134: return mindspore.schema.SkipGram.decode(reader, position);\n            case 135: return mindspore.schema.SliceFusion.decode(reader, position);\n            case 136: return mindspore.schema.SmoothL1Loss.decode(reader, position);\n            case 137: return mindspore.schema.SmoothL1LossGrad.decode(reader, position);\n            case 138: return mindspore.schema.Softmax.decode(reader, position);\n            case 139: return mindspore.schema.SoftmaxCrossEntropyWithLogits.decode(reader, position);\n            case 140: return mindspore.schema.SpaceToBatch.decode(reader, position);\n            case 141: return mindspore.schema.SpaceToBatchND.decode(reader, position);\n            case 142: return mindspore.schema.SpaceToDepth.decode(reader, position);\n            case 143: return mindspore.schema.SparseSoftmaxCrossEntropyWithLogits.decode(reader, position);\n            case 144: return mindspore.schema.SparseToDense.decode(reader, position);\n            case 145: return mindspore.schema.Split.decode(reader, position);\n            case 146: return mindspore.schema.Sqrt.decode(reader, position);\n            case 147: return mindspore.schema.Squeeze.decode(reader, position);\n            case 148: return mindspore.schema.Square.decode(reader, position);\n            case 149: return mindspore.schema.SquaredDifference.decode(reader, position);\n            case 150: return mindspore.schema.Stack.decode(reader, position);\n            case 151: return mindspore.schema.StridedSlice.decode(reader, position);\n            case 152: return mindspore.schema.SubFusion.decode(reader, position);\n            case 153: return mindspore.schema.SubGrad.decode(reader, position);\n            case 154: return mindspore.schema.Switch.decode(reader, position);\n            case 155: return mindspore.schema.TensorListFromTensor.decode(reader, position);\n            case 156: return mindspore.schema.TensorListGetItem.decode(reader, position);\n            case 157: return mindspore.schema.TensorListReserve.decode(reader, position);\n            case 158: return mindspore.schema.TensorListSetItem.decode(reader, position);\n            case 159: return mindspore.schema.TensorListStack.decode(reader, position);\n            case 160: return mindspore.schema.TileFusion.decode(reader, position);\n            case 161: return mindspore.schema.TopKFusion.decode(reader, position);\n            case 162: return mindspore.schema.Transpose.decode(reader, position);\n            case 163: return mindspore.schema.Unique.decode(reader, position);\n            case 164: return mindspore.schema.UnsortedSegmentSum.decode(reader, position);\n            case 165: return mindspore.schema.Unsqueeze.decode(reader, position);\n            case 166: return mindspore.schema.Unstack.decode(reader, position);\n            case 167: return mindspore.schema.LSTMGrad.decode(reader, position);\n            case 168: return mindspore.schema.Where.decode(reader, position);\n            case 169: return mindspore.schema.ZerosLike.decode(reader, position);\n            case 170: return mindspore.schema.Select.decode(reader, position);\n            case 171: return mindspore.schema.ScatterNdUpdate.decode(reader, position);\n            case 172: return mindspore.schema.GRU.decode(reader, position);\n            case 173: return mindspore.schema.NonZero.decode(reader, position);\n            case 174: return mindspore.schema.InvertPermutation.decode(reader, position);\n            case 175: return mindspore.schema.Size.decode(reader, position);\n            case 176: return mindspore.schema.RandomStandardNormal.decode(reader, position);\n            case 177: return mindspore.schema.CropAndResize.decode(reader, position);\n            case 178: return mindspore.schema.Erf.decode(reader, position);\n            case 179: return mindspore.schema.StridedSliceGrad.decode(reader, position);\n            case 180: return mindspore.schema.IsFinite.decode(reader, position);\n            case 181: return mindspore.schema.LinSpace.decode(reader, position);\n            case 182: return mindspore.schema.UniformReal.decode(reader, position);\n            case 183: return mindspore.schema.AbsGrad.decode(reader, position);\n            case 184: return mindspore.schema.RsqrtGrad.decode(reader, position);\n            case 185: return mindspore.schema.SqrtGrad.decode(reader, position);\n            case 186: return mindspore.schema.LayerNormGrad.decode(reader, position);\n            case 187: return mindspore.schema.ResizeGrad.decode(reader, position);\n            case 188: return mindspore.schema.Splice.decode(reader, position);\n            case 189: return mindspore.schema.LogSoftmax.decode(reader, position);\n            case 190: return mindspore.schema.Call.decode(reader, position);\n            case 191: return mindspore.schema.Custom.decode(reader, position);\n            case 192: return mindspore.schema.CumSum.decode(reader, position);\n            case 193: return mindspore.schema.SplitWithOverlap.decode(reader, position);\n            case 194: return mindspore.schema.GenOP.decode(reader, position);\n            case 195: return mindspore.schema.RaggedRange.decode(reader, position);\n            case 196: return mindspore.schema.GLU.decode(reader, position);\n            case 197: return mindspore.schema.TensorArray.decode(reader, position);\n            case 198: return mindspore.schema.TensorArrayRead.decode(reader, position);\n            case 199: return mindspore.schema.TensorArrayWrite.decode(reader, position);\n            case 200: return mindspore.schema.Affine.decode(reader, position);\n            case 201: return mindspore.schema.AllGather.decode(reader, position);\n            case 202: return mindspore.schema.ReduceScatter.decode(reader, position);\n            case 203: return mindspore.schema.DynamicQuant.decode(reader, position);\n            case 204: return mindspore.schema.LSTMGradData.decode(reader, position);\n            case 205: return mindspore.schema.LSTMGradWeight.decode(reader, position);\n            case 206: return mindspore.schema.RandomNormal.decode(reader, position);\n            case 207: return mindspore.schema.NLLLoss.decode(reader, position);\n            case 208: return mindspore.schema.NLLLossGrad.decode(reader, position);\n            case 209: return mindspore.schema.FormatTranspose.decode(reader, position);\n            case 210: return mindspore.schema.GatherD.decode(reader, position);\n            case 211: return mindspore.schema.GroupNormFusion.decode(reader, position);\n            case 212: return mindspore.schema.Log1p.decode(reader, position);\n            case 213: return mindspore.schema.TensorScatterAdd.decode(reader, position);\n            case 214: return mindspore.schema.SparseFillEmptyRows.decode(reader, position);\n            case 215: return mindspore.schema.SparseReshape.decode(reader, position);\n            case 216: return mindspore.schema.SparseSegmentSum.decode(reader, position);\n            case 217: return mindspore.schema.ScatterElements.decode(reader, position);\n            case 218: return mindspore.schema.Triu.decode(reader, position);\n            case 219: return mindspore.schema.Tril.decode(reader, position);\n            case 220: return mindspore.schema.AdamWeightDecay.decode(reader, position);\n            case 221: return mindspore.schema.FillV2.decode(reader, position);\n            default: return undefined;\n        }\n    }\n\n    static decodeText(reader, json, type) {\n        switch (type) {\n            case 'Abs': return mindspore.schema.Abs.decodeText(reader, json);\n            case 'Activation': return mindspore.schema.Activation.decodeText(reader, json);\n            case 'ActivationGrad': return mindspore.schema.ActivationGrad.decodeText(reader, json);\n            case 'Adam': return mindspore.schema.Adam.decodeText(reader, json);\n            case 'AddFusion': return mindspore.schema.AddFusion.decodeText(reader, json);\n            case 'AdderFusion': return mindspore.schema.AdderFusion.decodeText(reader, json);\n            case 'AddGrad': return mindspore.schema.AddGrad.decodeText(reader, json);\n            case 'AddN': return mindspore.schema.AddN.decodeText(reader, json);\n            case 'All': return mindspore.schema.All.decodeText(reader, json);\n            case 'ApplyMomentum': return mindspore.schema.ApplyMomentum.decodeText(reader, json);\n            case 'ArgMaxFusion': return mindspore.schema.ArgMaxFusion.decodeText(reader, json);\n            case 'ArgMinFusion': return mindspore.schema.ArgMinFusion.decodeText(reader, json);\n            case 'Assert': return mindspore.schema.Assert.decodeText(reader, json);\n            case 'Assign': return mindspore.schema.Assign.decodeText(reader, json);\n            case 'AssignAdd': return mindspore.schema.AssignAdd.decodeText(reader, json);\n            case 'AudioSpectrogram': return mindspore.schema.AudioSpectrogram.decodeText(reader, json);\n            case 'AvgPoolFusion': return mindspore.schema.AvgPoolFusion.decodeText(reader, json);\n            case 'AvgPoolGrad': return mindspore.schema.AvgPoolGrad.decodeText(reader, json);\n            case 'BatchNorm': return mindspore.schema.BatchNorm.decodeText(reader, json);\n            case 'BatchNormGrad': return mindspore.schema.BatchNormGrad.decodeText(reader, json);\n            case 'BatchToSpace': return mindspore.schema.BatchToSpace.decodeText(reader, json);\n            case 'BatchToSpaceND': return mindspore.schema.BatchToSpaceND.decodeText(reader, json);\n            case 'BiasAdd': return mindspore.schema.BiasAdd.decodeText(reader, json);\n            case 'BinaryCrossEntropy': return mindspore.schema.BinaryCrossEntropy.decodeText(reader, json);\n            case 'BinaryCrossEntropyGrad': return mindspore.schema.BinaryCrossEntropyGrad.decodeText(reader, json);\n            case 'BiasAddGrad': return mindspore.schema.BiasAddGrad.decodeText(reader, json);\n            case 'BroadcastTo': return mindspore.schema.BroadcastTo.decodeText(reader, json);\n            case 'Cast': return mindspore.schema.Cast.decodeText(reader, json);\n            case 'Ceil': return mindspore.schema.Ceil.decodeText(reader, json);\n            case 'Clip': return mindspore.schema.Clip.decodeText(reader, json);\n            case 'Concat': return mindspore.schema.Concat.decodeText(reader, json);\n            case 'Attention': return mindspore.schema.Attention.decodeText(reader, json);\n            case 'Conv2DBackpropFilterFusion': return mindspore.schema.Conv2DBackpropFilterFusion.decodeText(reader, json);\n            case 'Conv2DBackpropInputFusion': return mindspore.schema.Conv2DBackpropInputFusion.decodeText(reader, json);\n            case 'Conv2DFusion': return mindspore.schema.Conv2DFusion.decodeText(reader, json);\n            case 'Conv2dTransposeFusion': return mindspore.schema.Conv2dTransposeFusion.decodeText(reader, json);\n            case 'Cos': return mindspore.schema.Cos.decodeText(reader, json);\n            case 'ConstantOfShape': return mindspore.schema.ConstantOfShape.decodeText(reader, json);\n            case 'Crop': return mindspore.schema.Crop.decodeText(reader, json);\n            case 'CustomExtractFeatures': return mindspore.schema.CustomExtractFeatures.decodeText(reader, json);\n            case 'CustomNormalize': return mindspore.schema.CustomNormalize.decodeText(reader, json);\n            case 'CustomPredict': return mindspore.schema.CustomPredict.decodeText(reader, json);\n            case 'DeConv2DGradFilter': return mindspore.schema.DeConv2DGradFilter.decodeText(reader, json);\n            case 'Depend': return mindspore.schema.Depend.decodeText(reader, json);\n            case 'DepthToSpace': return mindspore.schema.DepthToSpace.decodeText(reader, json);\n            case 'DetectionPostProcess': return mindspore.schema.DetectionPostProcess.decodeText(reader, json);\n            case 'DivFusion': return mindspore.schema.DivFusion.decodeText(reader, json);\n            case 'DivGrad': return mindspore.schema.DivGrad.decodeText(reader, json);\n            case 'Dropout': return mindspore.schema.Dropout.decodeText(reader, json);\n            case 'DropoutGrad': return mindspore.schema.DropoutGrad.decodeText(reader, json);\n            case 'Elu': return mindspore.schema.Elu.decodeText(reader, json);\n            case 'Eltwise': return mindspore.schema.Eltwise.decodeText(reader, json);\n            case 'Equal': return mindspore.schema.Equal.decodeText(reader, json);\n            case 'EmbeddingLookupFusion': return mindspore.schema.EmbeddingLookupFusion.decodeText(reader, json);\n            case 'ExpFusion': return mindspore.schema.ExpFusion.decodeText(reader, json);\n            case 'ExpandDims': return mindspore.schema.ExpandDims.decodeText(reader, json);\n            case 'FakeQuantWithMinMaxVars': return mindspore.schema.FakeQuantWithMinMaxVars.decodeText(reader, json);\n            case 'FakeQuantWithMinMaxVarsPerChannel': return mindspore.schema.FakeQuantWithMinMaxVarsPerChannel.decodeText(reader, json);\n            case 'FftReal': return mindspore.schema.FftReal.decodeText(reader, json);\n            case 'FftImag': return mindspore.schema.FftImag.decodeText(reader, json);\n            case 'Flatten': return mindspore.schema.Flatten.decodeText(reader, json);\n            case 'FlattenGrad': return mindspore.schema.FlattenGrad.decodeText(reader, json);\n            case 'Floor': return mindspore.schema.Floor.decodeText(reader, json);\n            case 'FloorDiv': return mindspore.schema.FloorDiv.decodeText(reader, json);\n            case 'FloorMod': return mindspore.schema.FloorMod.decodeText(reader, json);\n            case 'Fill': return mindspore.schema.Fill.decodeText(reader, json);\n            case 'FullConnection': return mindspore.schema.FullConnection.decodeText(reader, json);\n            case 'FusedBatchNorm': return mindspore.schema.FusedBatchNorm.decodeText(reader, json);\n            case 'Gather': return mindspore.schema.Gather.decodeText(reader, json);\n            case 'GatherNd': return mindspore.schema.GatherNd.decodeText(reader, json);\n            case 'Greater': return mindspore.schema.Greater.decodeText(reader, json);\n            case 'GreaterEqual': return mindspore.schema.GreaterEqual.decodeText(reader, json);\n            case 'HashtableLookup': return mindspore.schema.HashtableLookup.decodeText(reader, json);\n            case 'InstanceNorm': return mindspore.schema.InstanceNorm.decodeText(reader, json);\n            case 'LayerNormFusion': return mindspore.schema.LayerNormFusion.decodeText(reader, json);\n            case 'LeakyRelu': return mindspore.schema.LeakyRelu.decodeText(reader, json);\n            case 'Less': return mindspore.schema.Less.decodeText(reader, json);\n            case 'LessEqual': return mindspore.schema.LessEqual.decodeText(reader, json);\n            case 'Log': return mindspore.schema.Log.decodeText(reader, json);\n            case 'LogGrad': return mindspore.schema.LogGrad.decodeText(reader, json);\n            case 'LogicalAnd': return mindspore.schema.LogicalAnd.decodeText(reader, json);\n            case 'LogicalNot': return mindspore.schema.LogicalNot.decodeText(reader, json);\n            case 'LogicalOr': return mindspore.schema.LogicalOr.decodeText(reader, json);\n            case 'LpNormalization': return mindspore.schema.LpNormalization.decodeText(reader, json);\n            case 'LRN': return mindspore.schema.LRN.decodeText(reader, json);\n            case 'LshProjection': return mindspore.schema.LshProjection.decodeText(reader, json);\n            case 'LSTM': return mindspore.schema.LSTM.decodeText(reader, json);\n            case 'L2NormalizeFusion': return mindspore.schema.L2NormalizeFusion.decodeText(reader, json);\n            case 'MatMulFusion': return mindspore.schema.MatMulFusion.decodeText(reader, json);\n            case 'Maximum': return mindspore.schema.Maximum.decodeText(reader, json);\n            case 'MaximumGrad': return mindspore.schema.MaximumGrad.decodeText(reader, json);\n            case 'MaxPoolFusion': return mindspore.schema.MaxPoolFusion.decodeText(reader, json);\n            case 'MaxPoolGrad': return mindspore.schema.MaxPoolGrad.decodeText(reader, json);\n            case 'SwitchLayer': return mindspore.schema.SwitchLayer.decodeText(reader, json);\n            case 'Mfcc': return mindspore.schema.Mfcc.decodeText(reader, json);\n            case 'Minimum': return mindspore.schema.Minimum.decodeText(reader, json);\n            case 'MinimumGrad': return mindspore.schema.MinimumGrad.decodeText(reader, json);\n            case 'Mod': return mindspore.schema.Mod.decodeText(reader, json);\n            case 'MulFusion': return mindspore.schema.MulFusion.decodeText(reader, json);\n            case 'MulGrad': return mindspore.schema.MulGrad.decodeText(reader, json);\n            case 'Neg': return mindspore.schema.Neg.decodeText(reader, json);\n            case 'NegGrad': return mindspore.schema.NegGrad.decodeText(reader, json);\n            case 'NotEqual': return mindspore.schema.NotEqual.decodeText(reader, json);\n            case 'NonMaxSuppression': return mindspore.schema.NonMaxSuppression.decodeText(reader, json);\n            case 'OneHot': return mindspore.schema.OneHot.decodeText(reader, json);\n            case 'OnesLike': return mindspore.schema.OnesLike.decodeText(reader, json);\n            case 'PadFusion': return mindspore.schema.PadFusion.decodeText(reader, json);\n            case 'PartialFusion': return mindspore.schema.PartialFusion.decodeText(reader, json);\n            case 'PowerGrad': return mindspore.schema.PowerGrad.decodeText(reader, json);\n            case 'PowFusion': return mindspore.schema.PowFusion.decodeText(reader, json);\n            case 'PriorBox': return mindspore.schema.PriorBox.decodeText(reader, json);\n            case 'PReLUFusion': return mindspore.schema.PReLUFusion.decodeText(reader, json);\n            case 'QuantDTypeCast': return mindspore.schema.QuantDTypeCast.decodeText(reader, json);\n            case 'Rank': return mindspore.schema.Rank.decodeText(reader, json);\n            case 'Range': return mindspore.schema.Range.decodeText(reader, json);\n            case 'Reciprocal': return mindspore.schema.Reciprocal.decodeText(reader, json);\n            case 'RealDiv': return mindspore.schema.RealDiv.decodeText(reader, json);\n            case 'ReduceFusion': return mindspore.schema.ReduceFusion.decodeText(reader, json);\n            case 'Reshape': return mindspore.schema.Reshape.decodeText(reader, json);\n            case 'Resize': return mindspore.schema.Resize.decodeText(reader, json);\n            case 'ReverseSequence': return mindspore.schema.ReverseSequence.decodeText(reader, json);\n            case 'ReverseV2': return mindspore.schema.ReverseV2.decodeText(reader, json);\n            case 'Rfft': return mindspore.schema.Rfft.decodeText(reader, json);\n            case 'ROIPooling': return mindspore.schema.ROIPooling.decodeText(reader, json);\n            case 'Round': return mindspore.schema.Round.decodeText(reader, json);\n            case 'Rsqrt': return mindspore.schema.Rsqrt.decodeText(reader, json);\n            case 'ScaleFusion': return mindspore.schema.ScaleFusion.decodeText(reader, json);\n            case 'ScatterNd': return mindspore.schema.ScatterNd.decodeText(reader, json);\n            case 'SGD': return mindspore.schema.SGD.decodeText(reader, json);\n            case 'Shape': return mindspore.schema.Shape.decodeText(reader, json);\n            case 'SigmoidCrossEntropyWithLogits': return mindspore.schema.SigmoidCrossEntropyWithLogits.decodeText(reader, json);\n            case 'SigmoidCrossEntropyWithLogitsGrad': return mindspore.schema.SigmoidCrossEntropyWithLogitsGrad.decodeText(reader, json);\n            case 'Sin': return mindspore.schema.Sin.decodeText(reader, json);\n            case 'SkipGram': return mindspore.schema.SkipGram.decodeText(reader, json);\n            case 'SliceFusion': return mindspore.schema.SliceFusion.decodeText(reader, json);\n            case 'SmoothL1Loss': return mindspore.schema.SmoothL1Loss.decodeText(reader, json);\n            case 'SmoothL1LossGrad': return mindspore.schema.SmoothL1LossGrad.decodeText(reader, json);\n            case 'Softmax': return mindspore.schema.Softmax.decodeText(reader, json);\n            case 'SoftmaxCrossEntropyWithLogits': return mindspore.schema.SoftmaxCrossEntropyWithLogits.decodeText(reader, json);\n            case 'SpaceToBatch': return mindspore.schema.SpaceToBatch.decodeText(reader, json);\n            case 'SpaceToBatchND': return mindspore.schema.SpaceToBatchND.decodeText(reader, json);\n            case 'SpaceToDepth': return mindspore.schema.SpaceToDepth.decodeText(reader, json);\n            case 'SparseSoftmaxCrossEntropyWithLogits': return mindspore.schema.SparseSoftmaxCrossEntropyWithLogits.decodeText(reader, json);\n            case 'SparseToDense': return mindspore.schema.SparseToDense.decodeText(reader, json);\n            case 'Split': return mindspore.schema.Split.decodeText(reader, json);\n            case 'Sqrt': return mindspore.schema.Sqrt.decodeText(reader, json);\n            case 'Squeeze': return mindspore.schema.Squeeze.decodeText(reader, json);\n            case 'Square': return mindspore.schema.Square.decodeText(reader, json);\n            case 'SquaredDifference': return mindspore.schema.SquaredDifference.decodeText(reader, json);\n            case 'Stack': return mindspore.schema.Stack.decodeText(reader, json);\n            case 'StridedSlice': return mindspore.schema.StridedSlice.decodeText(reader, json);\n            case 'SubFusion': return mindspore.schema.SubFusion.decodeText(reader, json);\n            case 'SubGrad': return mindspore.schema.SubGrad.decodeText(reader, json);\n            case 'Switch': return mindspore.schema.Switch.decodeText(reader, json);\n            case 'TensorListFromTensor': return mindspore.schema.TensorListFromTensor.decodeText(reader, json);\n            case 'TensorListGetItem': return mindspore.schema.TensorListGetItem.decodeText(reader, json);\n            case 'TensorListReserve': return mindspore.schema.TensorListReserve.decodeText(reader, json);\n            case 'TensorListSetItem': return mindspore.schema.TensorListSetItem.decodeText(reader, json);\n            case 'TensorListStack': return mindspore.schema.TensorListStack.decodeText(reader, json);\n            case 'TileFusion': return mindspore.schema.TileFusion.decodeText(reader, json);\n            case 'TopKFusion': return mindspore.schema.TopKFusion.decodeText(reader, json);\n            case 'Transpose': return mindspore.schema.Transpose.decodeText(reader, json);\n            case 'Unique': return mindspore.schema.Unique.decodeText(reader, json);\n            case 'UnsortedSegmentSum': return mindspore.schema.UnsortedSegmentSum.decodeText(reader, json);\n            case 'Unsqueeze': return mindspore.schema.Unsqueeze.decodeText(reader, json);\n            case 'Unstack': return mindspore.schema.Unstack.decodeText(reader, json);\n            case 'LSTMGrad': return mindspore.schema.LSTMGrad.decodeText(reader, json);\n            case 'Where': return mindspore.schema.Where.decodeText(reader, json);\n            case 'ZerosLike': return mindspore.schema.ZerosLike.decodeText(reader, json);\n            case 'Select': return mindspore.schema.Select.decodeText(reader, json);\n            case 'ScatterNdUpdate': return mindspore.schema.ScatterNdUpdate.decodeText(reader, json);\n            case 'GRU': return mindspore.schema.GRU.decodeText(reader, json);\n            case 'NonZero': return mindspore.schema.NonZero.decodeText(reader, json);\n            case 'InvertPermutation': return mindspore.schema.InvertPermutation.decodeText(reader, json);\n            case 'Size': return mindspore.schema.Size.decodeText(reader, json);\n            case 'RandomStandardNormal': return mindspore.schema.RandomStandardNormal.decodeText(reader, json);\n            case 'CropAndResize': return mindspore.schema.CropAndResize.decodeText(reader, json);\n            case 'Erf': return mindspore.schema.Erf.decodeText(reader, json);\n            case 'StridedSliceGrad': return mindspore.schema.StridedSliceGrad.decodeText(reader, json);\n            case 'IsFinite': return mindspore.schema.IsFinite.decodeText(reader, json);\n            case 'LinSpace': return mindspore.schema.LinSpace.decodeText(reader, json);\n            case 'UniformReal': return mindspore.schema.UniformReal.decodeText(reader, json);\n            case 'AbsGrad': return mindspore.schema.AbsGrad.decodeText(reader, json);\n            case 'RsqrtGrad': return mindspore.schema.RsqrtGrad.decodeText(reader, json);\n            case 'SqrtGrad': return mindspore.schema.SqrtGrad.decodeText(reader, json);\n            case 'LayerNormGrad': return mindspore.schema.LayerNormGrad.decodeText(reader, json);\n            case 'ResizeGrad': return mindspore.schema.ResizeGrad.decodeText(reader, json);\n            case 'Splice': return mindspore.schema.Splice.decodeText(reader, json);\n            case 'LogSoftmax': return mindspore.schema.LogSoftmax.decodeText(reader, json);\n            case 'Call': return mindspore.schema.Call.decodeText(reader, json);\n            case 'Custom': return mindspore.schema.Custom.decodeText(reader, json);\n            case 'CumSum': return mindspore.schema.CumSum.decodeText(reader, json);\n            case 'SplitWithOverlap': return mindspore.schema.SplitWithOverlap.decodeText(reader, json);\n            case 'GenOP': return mindspore.schema.GenOP.decodeText(reader, json);\n            case 'RaggedRange': return mindspore.schema.RaggedRange.decodeText(reader, json);\n            case 'GLU': return mindspore.schema.GLU.decodeText(reader, json);\n            case 'TensorArray': return mindspore.schema.TensorArray.decodeText(reader, json);\n            case 'TensorArrayRead': return mindspore.schema.TensorArrayRead.decodeText(reader, json);\n            case 'TensorArrayWrite': return mindspore.schema.TensorArrayWrite.decodeText(reader, json);\n            case 'Affine': return mindspore.schema.Affine.decodeText(reader, json);\n            case 'AllGather': return mindspore.schema.AllGather.decodeText(reader, json);\n            case 'ReduceScatter': return mindspore.schema.ReduceScatter.decodeText(reader, json);\n            case 'DynamicQuant': return mindspore.schema.DynamicQuant.decodeText(reader, json);\n            case 'LSTMGradData': return mindspore.schema.LSTMGradData.decodeText(reader, json);\n            case 'LSTMGradWeight': return mindspore.schema.LSTMGradWeight.decodeText(reader, json);\n            case 'RandomNormal': return mindspore.schema.RandomNormal.decodeText(reader, json);\n            case 'NLLLoss': return mindspore.schema.NLLLoss.decodeText(reader, json);\n            case 'NLLLossGrad': return mindspore.schema.NLLLossGrad.decodeText(reader, json);\n            case 'FormatTranspose': return mindspore.schema.FormatTranspose.decodeText(reader, json);\n            case 'GatherD': return mindspore.schema.GatherD.decodeText(reader, json);\n            case 'GroupNormFusion': return mindspore.schema.GroupNormFusion.decodeText(reader, json);\n            case 'Log1p': return mindspore.schema.Log1p.decodeText(reader, json);\n            case 'TensorScatterAdd': return mindspore.schema.TensorScatterAdd.decodeText(reader, json);\n            case 'SparseFillEmptyRows': return mindspore.schema.SparseFillEmptyRows.decodeText(reader, json);\n            case 'SparseReshape': return mindspore.schema.SparseReshape.decodeText(reader, json);\n            case 'SparseSegmentSum': return mindspore.schema.SparseSegmentSum.decodeText(reader, json);\n            case 'ScatterElements': return mindspore.schema.ScatterElements.decodeText(reader, json);\n            case 'Triu': return mindspore.schema.Triu.decodeText(reader, json);\n            case 'Tril': return mindspore.schema.Tril.decodeText(reader, json);\n            case 'AdamWeightDecay': return mindspore.schema.AdamWeightDecay.decodeText(reader, json);\n            case 'FillV2': return mindspore.schema.FillV2.decodeText(reader, json);\n            default: return undefined;\n        }\n    }\n};\n\nmindspore.schema.Abs = class Abs {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Abs();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Abs();\n        return $;\n    }\n};\n\nmindspore.schema.Activation = class Activation {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Activation();\n        $.activation_type = reader.int8_(position, 4, 0);\n        $.alpha = reader.float32_(position, 6, 0);\n        $.min_val = reader.float32_(position, 8, 0);\n        $.max_val = reader.float32_(position, 10, 0);\n        $.approximate = reader.bool_(position, 12, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Activation();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        $.alpha = reader.value(json.alpha, 0);\n        $.min_val = reader.value(json.min_val, 0);\n        $.max_val = reader.value(json.max_val, 0);\n        $.approximate = reader.value(json.approximate, false);\n        return $;\n    }\n};\n\nmindspore.schema.ActivationGrad = class ActivationGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ActivationGrad();\n        $.activation_type = reader.int8_(position, 4, 0);\n        $.alpha = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ActivationGrad();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        $.alpha = reader.value(json.alpha, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Adam = class Adam {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Adam();\n        $.use_locking = reader.bool_(position, 4, false);\n        $.use_nesterov = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Adam();\n        $.use_locking = reader.value(json.use_locking, false);\n        $.use_nesterov = reader.value(json.use_nesterov, false);\n        return $;\n    }\n};\n\nmindspore.schema.AddFusion = class AddFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AddFusion();\n        $.activation_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AddFusion();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.AdderFusion = class AdderFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AdderFusion();\n        $.format = reader.int32_(position, 4, 0);\n        $.kernel_size = reader.int64s_(position, 6);\n        $.stride = reader.int64s_(position, 8);\n        $.dilation = reader.int64s_(position, 10);\n        $.pad_mode = reader.int8_(position, 12, 0);\n        $.pad_list = reader.int64s_(position, 14);\n        $.group = reader.int64_(position, 16, 0n);\n        $.in_channel = reader.int64_(position, 18, 0n);\n        $.out_channel = reader.int64_(position, 20, 0n);\n        $.activation_type = reader.int8_(position, 22, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AdderFusion();\n        $.format = mindspore.schema.Format[json.format];\n        $.kernel_size = reader.array(json.kernel_size);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad_list = reader.array(json.pad_list);\n        $.group = reader.int64(json.group, 0n);\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.AddGrad = class AddGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.AddGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.AddGrad();\n        return $;\n    }\n};\n\nmindspore.schema.AddN = class AddN {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.AddN();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.AddN();\n        return $;\n    }\n};\n\nmindspore.schema.All = class All {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.All();\n        $.keep_dims = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.All();\n        $.keep_dims = reader.int64(json.keep_dims, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.ApplyMomentum = class ApplyMomentum {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ApplyMomentum();\n        $.use_nesterov = reader.bool_(position, 4, false);\n        $.use_locking = reader.bool_(position, 6, false);\n        $.gradient_scale = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ApplyMomentum();\n        $.use_nesterov = reader.value(json.use_nesterov, false);\n        $.use_locking = reader.value(json.use_locking, false);\n        $.gradient_scale = reader.value(json.gradient_scale, 0);\n        return $;\n    }\n};\n\nmindspore.schema.ArgMaxFusion = class ArgMaxFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ArgMaxFusion();\n        $.axis = reader.int64_(position, 4, 0n);\n        $.top_k = reader.int64_(position, 6, 1n);\n        $.keep_dims = reader.bool_(position, 8, false);\n        $.out_max_value = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ArgMaxFusion();\n        $.axis = reader.int64(json.axis, 0n);\n        $.top_k = reader.int64(json.top_k, 1n);\n        $.keep_dims = reader.value(json.keep_dims, false);\n        $.out_max_value = reader.value(json.out_max_value, false);\n        return $;\n    }\n};\n\nmindspore.schema.ArgMinFusion = class ArgMinFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ArgMinFusion();\n        $.axis = reader.int64_(position, 4, 0n);\n        $.top_k = reader.int64_(position, 6, 0n);\n        $.keep_dims = reader.bool_(position, 8, false);\n        $.out_max_value = reader.bool_(position, 10, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ArgMinFusion();\n        $.axis = reader.int64(json.axis, 0n);\n        $.top_k = reader.int64(json.top_k, 0n);\n        $.keep_dims = reader.value(json.keep_dims, false);\n        $.out_max_value = reader.value(json.out_max_value, false);\n        return $;\n    }\n};\n\nmindspore.schema.Assert = class Assert {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Assert();\n        $.summarize = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Assert();\n        $.summarize = reader.int64(json.summarize, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Assign = class Assign {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Assign();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Assign();\n        return $;\n    }\n};\n\nmindspore.schema.AssignAdd = class AssignAdd {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.AssignAdd();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.AssignAdd();\n        return $;\n    }\n};\n\nmindspore.schema.AudioSpectrogram = class AudioSpectrogram {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AudioSpectrogram();\n        $.window_size = reader.int64_(position, 4, 0n);\n        $.stride = reader.int64_(position, 6, 0n);\n        $.mag_square = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AudioSpectrogram();\n        $.window_size = reader.int64(json.window_size, 0n);\n        $.stride = reader.int64(json.stride, 0n);\n        $.mag_square = reader.value(json.mag_square, false);\n        return $;\n    }\n};\n\nmindspore.schema.AvgPoolFusion = class AvgPoolFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AvgPoolFusion();\n        $.kernel_size = reader.int64s_(position, 4);\n        $.strides = reader.int64s_(position, 6);\n        $.pad = reader.int64s_(position, 8);\n        $.pad_mode = reader.int8_(position, 10, 0);\n        $.round_mode = reader.int8_(position, 12, 0);\n        $.format = reader.int32_(position, 14, 0);\n        $.global = reader.bool_(position, 16, false);\n        $.activation_type = reader.int8_(position, 18, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AvgPoolFusion();\n        $.kernel_size = reader.array(json.kernel_size);\n        $.strides = reader.array(json.strides);\n        $.pad = reader.array(json.pad);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.round_mode = mindspore.schema.RoundMode[json.round_mode];\n        $.format = mindspore.schema.Format[json.format];\n        $.global = reader.value(json.global, false);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.AvgPoolGrad = class AvgPoolGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AvgPoolGrad();\n        $.kernel_size = reader.int64s_(position, 4);\n        $.strides = reader.int64s_(position, 6);\n        $.pad_mode = reader.int8_(position, 8, 0);\n        $.format = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AvgPoolGrad();\n        $.kernel_size = reader.array(json.kernel_size);\n        $.strides = reader.array(json.strides);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.format = mindspore.schema.Format[json.format];\n        return $;\n    }\n};\n\nmindspore.schema.BatchNorm = class BatchNorm {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BatchNorm();\n        $.epsilon = reader.float32_(position, 4, 0);\n        $.format = reader.int32_(position, 6, 0);\n        $.is_training = reader.bool_(position, 8, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BatchNorm();\n        $.epsilon = reader.value(json.epsilon, 0);\n        $.format = mindspore.schema.Format[json.format];\n        $.is_training = reader.value(json.is_training, false);\n        return $;\n    }\n};\n\nmindspore.schema.BatchNormGrad = class BatchNormGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BatchNormGrad();\n        $.epsilon = reader.float32_(position, 4, 0);\n        $.is_training = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BatchNormGrad();\n        $.epsilon = reader.value(json.epsilon, 0);\n        $.is_training = reader.value(json.is_training, false);\n        return $;\n    }\n};\n\nmindspore.schema.BatchToSpace = class BatchToSpace {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BatchToSpace();\n        $.block_size = reader.int64s_(position, 4);\n        $.crops = reader.table(position, 6, mindspore.schema.Vec2D);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BatchToSpace();\n        $.block_size = reader.array(json.block_size);\n        $.crops = reader.object(json.crops, mindspore.schema.Vec2D);\n        return $;\n    }\n};\n\nmindspore.schema.BatchToSpaceND = class BatchToSpaceND {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BatchToSpaceND();\n        $.block_shape = reader.int64s_(position, 4);\n        $.crops = reader.table(position, 6, mindspore.schema.Vec2D);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BatchToSpaceND();\n        $.block_shape = reader.array(json.block_shape);\n        $.crops = reader.object(json.crops, mindspore.schema.Vec2D);\n        return $;\n    }\n};\n\nmindspore.schema.BiasAdd = class BiasAdd {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BiasAdd();\n        $.format = reader.int32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BiasAdd();\n        $.format = mindspore.schema.Format[json.format];\n        return $;\n    }\n};\n\nmindspore.schema.BinaryCrossEntropy = class BinaryCrossEntropy {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BinaryCrossEntropy();\n        $.reduction = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BinaryCrossEntropy();\n        $.reduction = mindspore.schema.Reduction[json.reduction];\n        return $;\n    }\n};\n\nmindspore.schema.BinaryCrossEntropyGrad = class BinaryCrossEntropyGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BinaryCrossEntropyGrad();\n        $.reduction = reader.int8_(position, 4, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BinaryCrossEntropyGrad();\n        $.reduction = mindspore.schema.Reduction[json.reduction];\n        return $;\n    }\n};\n\nmindspore.schema.BiasAddGrad = class BiasAddGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.BiasAddGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.BiasAddGrad();\n        return $;\n    }\n};\n\nmindspore.schema.BroadcastTo = class BroadcastTo {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.BroadcastTo();\n        $.shape = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.BroadcastTo();\n        $.shape = reader.array(json.shape);\n        return $;\n    }\n};\n\nmindspore.schema.Cast = class Cast {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Cast();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Cast();\n        return $;\n    }\n};\n\nmindspore.schema.Ceil = class Ceil {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Ceil();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Ceil();\n        return $;\n    }\n};\n\nmindspore.schema.Clip = class Clip {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Clip();\n        $.max = reader.float32_(position, 4, 0);\n        $.min = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Clip();\n        $.max = reader.value(json.max, 0);\n        $.min = reader.value(json.min, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Concat = class Concat {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Concat();\n        $.axis = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Concat();\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Attention = class Attention {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Attention();\n        $.head_num = reader.int64_(position, 4, 0n);\n        $.head_size = reader.int64_(position, 6, 0n);\n        $.cross = reader.bool_(position, 8, false);\n        $.scale = reader.float32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Attention();\n        $.head_num = reader.int64(json.head_num, 0n);\n        $.head_size = reader.int64(json.head_size, 0n);\n        $.cross = reader.value(json.cross, false);\n        $.scale = reader.value(json.scale, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Conv2DBackpropFilterFusion = class Conv2DBackpropFilterFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Conv2DBackpropFilterFusion();\n        $.format = reader.int32_(position, 4, 0);\n        $.kernel_size = reader.int64s_(position, 6);\n        $.stride = reader.int64s_(position, 8);\n        $.dilation = reader.int64s_(position, 10);\n        $.pad_mode = reader.int8_(position, 12, 0);\n        $.pad_list = reader.int64s_(position, 14);\n        $.mode = reader.int64_(position, 16, 0n);\n        $.group = reader.int64_(position, 18, 0n);\n        $.in_channel = reader.int64_(position, 20, 0n);\n        $.out_channel = reader.int64_(position, 22, 0n);\n        $.activation_type = reader.int8_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Conv2DBackpropFilterFusion();\n        $.format = mindspore.schema.Format[json.format];\n        $.kernel_size = reader.array(json.kernel_size);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad_list = reader.array(json.pad_list);\n        $.mode = reader.int64(json.mode, 0n);\n        $.group = reader.int64(json.group, 0n);\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.Conv2DBackpropInputFusion = class Conv2DBackpropInputFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Conv2DBackpropInputFusion();\n        $.format = reader.int32_(position, 4, 0);\n        $.kernel_size = reader.int64s_(position, 6);\n        $.stride = reader.int64s_(position, 8);\n        $.dilation = reader.int64s_(position, 10);\n        $.pad_mode = reader.int8_(position, 12, 0);\n        $.pad = reader.int64s_(position, 14);\n        $.pad_list = reader.int64s_(position, 16);\n        $.mode = reader.int64_(position, 18, 0n);\n        $.group = reader.int64_(position, 20, 0n);\n        $.in_channel = reader.int64_(position, 22, 0n);\n        $.out_channel = reader.int64_(position, 24, 0n);\n        $.activation_type = reader.int8_(position, 26, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Conv2DBackpropInputFusion();\n        $.format = mindspore.schema.Format[json.format];\n        $.kernel_size = reader.array(json.kernel_size);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad = reader.array(json.pad);\n        $.pad_list = reader.array(json.pad_list);\n        $.mode = reader.int64(json.mode, 0n);\n        $.group = reader.int64(json.group, 0n);\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.Conv2DFusion = class Conv2DFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Conv2DFusion();\n        $.format = reader.int32_(position, 4, 0);\n        $.kernel_size = reader.int64s_(position, 6);\n        $.stride = reader.int64s_(position, 8);\n        $.dilation = reader.int64s_(position, 10);\n        $.pad_mode = reader.int8_(position, 12, 0);\n        $.pad_list = reader.int64s_(position, 14);\n        $.mode = reader.int64_(position, 16, 0n);\n        $.group = reader.int64_(position, 18, 0n);\n        $.in_channel = reader.int64_(position, 20, 0n);\n        $.out_channel = reader.int64_(position, 22, 0n);\n        $.activation_type = reader.int8_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Conv2DFusion();\n        $.format = mindspore.schema.Format[json.format];\n        $.kernel_size = reader.array(json.kernel_size);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad_list = reader.array(json.pad_list);\n        $.mode = reader.int64(json.mode, 0n);\n        $.group = reader.int64(json.group, 0n);\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.Conv2dTransposeFusion = class Conv2dTransposeFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Conv2dTransposeFusion();\n        $.format = reader.int32_(position, 4, 0);\n        $.kernel_size = reader.int64s_(position, 6);\n        $.stride = reader.int64s_(position, 8);\n        $.dilation = reader.int64s_(position, 10);\n        $.pad_mode = reader.int8_(position, 12, 0);\n        $.pad = reader.int64s_(position, 14);\n        $.pad_list = reader.int64s_(position, 16);\n        $.mode = reader.int64_(position, 18, 0n);\n        $.group = reader.int64_(position, 20, 0n);\n        $.in_channel = reader.int64_(position, 22, 0n);\n        $.out_channel = reader.int64_(position, 24, 0n);\n        $.activation_type = reader.int8_(position, 26, 0);\n        $.output_paddings = reader.int64s_(position, 28);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Conv2dTransposeFusion();\n        $.format = mindspore.schema.Format[json.format];\n        $.kernel_size = reader.array(json.kernel_size);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad = reader.array(json.pad);\n        $.pad_list = reader.array(json.pad_list);\n        $.mode = reader.int64(json.mode, 0n);\n        $.group = reader.int64(json.group, 0n);\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        $.output_paddings = reader.array(json.output_paddings);\n        return $;\n    }\n};\n\nmindspore.schema.Cos = class Cos {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Cos();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Cos();\n        return $;\n    }\n};\n\nmindspore.schema.ConstantOfShape = class ConstantOfShape {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ConstantOfShape();\n        $.data_type = reader.int64_(position, 4, 0n);\n        $.value = reader.array(position, 6, Float32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ConstantOfShape();\n        $.data_type = reader.int64(json.data_type, 0n);\n        $.value = reader.array(json.value, Float32Array);\n        return $;\n    }\n};\n\nmindspore.schema.Crop = class Crop {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Crop();\n        $.axis = reader.int64_(position, 4, 0n);\n        $.offsets = reader.int64s_(position, 6);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Crop();\n        $.axis = reader.int64(json.axis, 0n);\n        $.offsets = reader.array(json.offsets);\n        return $;\n    }\n};\n\nmindspore.schema.CustomExtractFeatures = class CustomExtractFeatures {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.CustomExtractFeatures();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.CustomExtractFeatures();\n        return $;\n    }\n};\n\nmindspore.schema.CustomNormalize = class CustomNormalize {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.CustomNormalize();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.CustomNormalize();\n        return $;\n    }\n};\n\nmindspore.schema.CustomPredict = class CustomPredict {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.CustomPredict();\n        $.output_num = reader.int64_(position, 4, 0n);\n        $.weight_threshold = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.CustomPredict();\n        $.output_num = reader.int64(json.output_num, 0n);\n        $.weight_threshold = reader.value(json.weight_threshold, 0);\n        return $;\n    }\n};\n\nmindspore.schema.DeConv2DGradFilter = class DeConv2DGradFilter {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.DeConv2DGradFilter();\n        $.in_channel = reader.int64_(position, 4, 0n);\n        $.out_channel = reader.int64_(position, 6, 0n);\n        $.kernel_size = reader.int64s_(position, 8);\n        $.pad_mode = reader.int8_(position, 10, 0);\n        $.pad_list = reader.int64s_(position, 12);\n        $.stride = reader.int64s_(position, 14);\n        $.dilation = reader.int64s_(position, 16);\n        $.group = reader.int64_(position, 18, 0n);\n        $.format = reader.int32_(position, 20, 0);\n        $.activation_type = reader.int8_(position, 22, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.DeConv2DGradFilter();\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.kernel_size = reader.array(json.kernel_size);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad_list = reader.array(json.pad_list);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.group = reader.int64(json.group, 0n);\n        $.format = mindspore.schema.Format[json.format];\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.Depend = class Depend {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Depend();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Depend();\n        return $;\n    }\n};\n\nmindspore.schema.DepthToSpace = class DepthToSpace {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.DepthToSpace();\n        $.block_size = reader.int64_(position, 4, 0n);\n        $.format = reader.int32_(position, 6, 0);\n        $.mode = reader.string_(position, 8, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.DepthToSpace();\n        $.block_size = reader.int64(json.block_size, 0n);\n        $.format = mindspore.schema.Format[json.format];\n        $.mode = reader.value(json.mode, null);\n        return $;\n    }\n};\n\nmindspore.schema.DetectionPostProcess = class DetectionPostProcess {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.DetectionPostProcess();\n        $.format = reader.int32_(position, 4, 0);\n        $.input_size = reader.int64_(position, 6, 0n);\n        $.scale = reader.array(position, 8, Float32Array);\n        $.nms_iou_threshold = reader.float32_(position, 10, 0);\n        $.nms_score_threshold = reader.float32_(position, 12, 0);\n        $.max_detections = reader.int64_(position, 14, 0n);\n        $.detections_per_class = reader.int64_(position, 16, 0n);\n        $.max_classes_per_detection = reader.int64_(position, 18, 0n);\n        $.num_classes = reader.int64_(position, 20, 0n);\n        $.use_regular_nms = reader.bool_(position, 22, false);\n        $.out_quantized = reader.bool_(position, 24, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.DetectionPostProcess();\n        $.format = mindspore.schema.Format[json.format];\n        $.input_size = reader.int64(json.input_size, 0n);\n        $.scale = reader.array(json.scale, Float32Array);\n        $.nms_iou_threshold = reader.value(json.nms_iou_threshold, 0);\n        $.nms_score_threshold = reader.value(json.nms_score_threshold, 0);\n        $.max_detections = reader.int64(json.max_detections, 0n);\n        $.detections_per_class = reader.int64(json.detections_per_class, 0n);\n        $.max_classes_per_detection = reader.int64(json.max_classes_per_detection, 0n);\n        $.num_classes = reader.int64(json.num_classes, 0n);\n        $.use_regular_nms = reader.value(json.use_regular_nms, false);\n        $.out_quantized = reader.value(json.out_quantized, false);\n        return $;\n    }\n};\n\nmindspore.schema.DivFusion = class DivFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.DivFusion();\n        $.activation_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.DivFusion();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.DivGrad = class DivGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.DivGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.DivGrad();\n        return $;\n    }\n};\n\nmindspore.schema.Dropout = class Dropout {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Dropout();\n        $.keep_prob = reader.float32_(position, 4, 0.5);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Dropout();\n        $.keep_prob = reader.value(json.keep_prob, 0.5);\n        return $;\n    }\n};\n\nmindspore.schema.DropoutGrad = class DropoutGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.DropoutGrad();\n        $.keep_prob = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.DropoutGrad();\n        $.keep_prob = reader.value(json.keep_prob, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Elu = class Elu {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Elu();\n        $.alpha = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Elu();\n        $.alpha = reader.value(json.alpha, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Eltwise = class Eltwise {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Eltwise();\n        $.mode = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Eltwise();\n        $.mode = mindspore.schema.EltwiseMode[json.mode];\n        return $;\n    }\n};\n\nmindspore.schema.Equal = class Equal {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Equal();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Equal();\n        return $;\n    }\n};\n\nmindspore.schema.EmbeddingLookupFusion = class EmbeddingLookupFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.EmbeddingLookupFusion();\n        $.max_norm = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.EmbeddingLookupFusion();\n        $.max_norm = reader.value(json.max_norm, 0);\n        return $;\n    }\n};\n\nmindspore.schema.ExpFusion = class ExpFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ExpFusion();\n        $.base = reader.float32_(position, 4, -1);\n        $.scale = reader.float32_(position, 6, 1);\n        $.shift = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ExpFusion();\n        $.base = reader.value(json.base, -1);\n        $.scale = reader.value(json.scale, 1);\n        $.shift = reader.value(json.shift, 0);\n        return $;\n    }\n};\n\nmindspore.schema.ExpandDims = class ExpandDims {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.ExpandDims();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.ExpandDims();\n        return $;\n    }\n};\n\nmindspore.schema.FakeQuantWithMinMaxVars = class FakeQuantWithMinMaxVars {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.FakeQuantWithMinMaxVars();\n        $.num_bits = reader.int64_(position, 4, 0n);\n        $.narrow_range = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.FakeQuantWithMinMaxVars();\n        $.num_bits = reader.int64(json.num_bits, 0n);\n        $.narrow_range = reader.value(json.narrow_range, false);\n        return $;\n    }\n};\n\nmindspore.schema.FakeQuantWithMinMaxVarsPerChannel = class FakeQuantWithMinMaxVarsPerChannel {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.FakeQuantWithMinMaxVarsPerChannel();\n        $.num_bits = reader.int64_(position, 4, 0n);\n        $.narrow_range = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.FakeQuantWithMinMaxVarsPerChannel();\n        $.num_bits = reader.int64(json.num_bits, 0n);\n        $.narrow_range = reader.value(json.narrow_range, false);\n        return $;\n    }\n};\n\nmindspore.schema.FftReal = class FftReal {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.FftReal();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.FftReal();\n        return $;\n    }\n};\n\nmindspore.schema.FftImag = class FftImag {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.FftImag();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.FftImag();\n        return $;\n    }\n};\n\nmindspore.schema.Flatten = class Flatten {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Flatten();\n        $.axis = reader.int64_(position, 4, 1n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Flatten();\n        $.axis = reader.int64(json.axis, 1n);\n        return $;\n    }\n};\n\nmindspore.schema.FlattenGrad = class FlattenGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.FlattenGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.FlattenGrad();\n        return $;\n    }\n};\n\nmindspore.schema.Floor = class Floor {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Floor();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Floor();\n        return $;\n    }\n};\n\nmindspore.schema.FloorDiv = class FloorDiv {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.FloorDiv();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.FloorDiv();\n        return $;\n    }\n};\n\nmindspore.schema.FloorMod = class FloorMod {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.FloorMod();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.FloorMod();\n        return $;\n    }\n};\n\nmindspore.schema.Fill = class Fill {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Fill();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Fill();\n        return $;\n    }\n};\n\nmindspore.schema.FullConnection = class FullConnection {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.FullConnection();\n        $.has_bias = reader.bool_(position, 4, false);\n        $.use_axis = reader.bool_(position, 6, false);\n        $.axis = reader.int64_(position, 8, 0n);\n        $.activation_type = reader.int8_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.FullConnection();\n        $.has_bias = reader.value(json.has_bias, false);\n        $.use_axis = reader.value(json.use_axis, false);\n        $.axis = reader.int64(json.axis, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.FusedBatchNorm = class FusedBatchNorm {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.FusedBatchNorm();\n        $.epsilon = reader.float32_(position, 4, 0.0001);\n        $.momentum = reader.float32_(position, 6, 0.9);\n        $.mode = reader.int64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.FusedBatchNorm();\n        $.epsilon = reader.value(json.epsilon, 0.0001);\n        $.momentum = reader.value(json.momentum, 0.9);\n        $.mode = reader.int64(json.mode, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Gather = class Gather {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Gather();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Gather();\n        return $;\n    }\n};\n\nmindspore.schema.GatherNd = class GatherNd {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.GatherNd();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.GatherNd();\n        return $;\n    }\n};\n\nmindspore.schema.Greater = class Greater {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Greater();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Greater();\n        return $;\n    }\n};\n\nmindspore.schema.GreaterEqual = class GreaterEqual {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.GreaterEqual();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.GreaterEqual();\n        return $;\n    }\n};\n\nmindspore.schema.HashtableLookup = class HashtableLookup {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.HashtableLookup();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.HashtableLookup();\n        return $;\n    }\n};\n\nmindspore.schema.InstanceNorm = class InstanceNorm {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.InstanceNorm();\n        $.epsilon = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.InstanceNorm();\n        $.epsilon = reader.value(json.epsilon, 0);\n        return $;\n    }\n};\n\nmindspore.schema.LayerNormFusion = class LayerNormFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LayerNormFusion();\n        $.begin_norm_axis = reader.int64_(position, 4, 0n);\n        $.epsilon = reader.float32_(position, 6, 0.00001);\n        $.elementwise_affine = reader.bool_(position, 8, false);\n        $.begin_params_axis = reader.int64_(position, 10, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LayerNormFusion();\n        $.begin_norm_axis = reader.int64(json.begin_norm_axis, 0n);\n        $.epsilon = reader.value(json.epsilon, 0.00001);\n        $.elementwise_affine = reader.value(json.elementwise_affine, false);\n        $.begin_params_axis = reader.int64(json.begin_params_axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.LeakyRelu = class LeakyRelu {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LeakyRelu();\n        $.negative_slope = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LeakyRelu();\n        $.negative_slope = reader.value(json.negative_slope, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Less = class Less {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Less();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Less();\n        return $;\n    }\n};\n\nmindspore.schema.LessEqual = class LessEqual {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.LessEqual();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.LessEqual();\n        return $;\n    }\n};\n\nmindspore.schema.Log = class Log {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Log();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Log();\n        return $;\n    }\n};\n\nmindspore.schema.LogGrad = class LogGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.LogGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.LogGrad();\n        return $;\n    }\n};\n\nmindspore.schema.LogicalAnd = class LogicalAnd {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.LogicalAnd();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.LogicalAnd();\n        return $;\n    }\n};\n\nmindspore.schema.LogicalNot = class LogicalNot {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.LogicalNot();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.LogicalNot();\n        return $;\n    }\n};\n\nmindspore.schema.LogicalOr = class LogicalOr {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.LogicalOr();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.LogicalOr();\n        return $;\n    }\n};\n\nmindspore.schema.LpNormalization = class LpNormalization {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LpNormalization();\n        $.axis = reader.int64_(position, 4, 0n);\n        $.p = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LpNormalization();\n        $.axis = reader.int64(json.axis, 0n);\n        $.p = reader.int64(json.p, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.LRN = class LRN {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LRN();\n        $.depth_radius = reader.int64_(position, 4, 0n);\n        $.bias = reader.float32_(position, 6, 0);\n        $.alpha = reader.float32_(position, 8, 0);\n        $.beta = reader.float32_(position, 10, 0);\n        $.norm_region = reader.string_(position, 12, null);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LRN();\n        $.depth_radius = reader.int64(json.depth_radius, 0n);\n        $.bias = reader.value(json.bias, 0);\n        $.alpha = reader.value(json.alpha, 0);\n        $.beta = reader.value(json.beta, 0);\n        $.norm_region = reader.value(json.norm_region, null);\n        return $;\n    }\n};\n\nmindspore.schema.LshProjection = class LshProjection {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LshProjection();\n        $.type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LshProjection();\n        $.type = mindspore.schema.LshProjectionType[json.type];\n        return $;\n    }\n};\n\nmindspore.schema.LSTM = class LSTM {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LSTM();\n        $.bidirectional = reader.bool_(position, 4, false);\n        $.has_bias = reader.bool_(position, 6, false);\n        $.input_size = reader.int64_(position, 8, 0n);\n        $.hidden_size = reader.int64_(position, 10, 0n);\n        $.num_layers = reader.int64_(position, 12, 0n);\n        $.num_directions = reader.int64_(position, 14, 0n);\n        $.dropout = reader.float32_(position, 16, 0);\n        $.zoneout_cell = reader.float32_(position, 18, 0);\n        $.zoneout_hidden = reader.float32_(position, 20, 0);\n        $.proj_size = reader.int64_(position, 22, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LSTM();\n        $.bidirectional = reader.value(json.bidirectional, false);\n        $.has_bias = reader.value(json.has_bias, false);\n        $.input_size = reader.int64(json.input_size, 0n);\n        $.hidden_size = reader.int64(json.hidden_size, 0n);\n        $.num_layers = reader.int64(json.num_layers, 0n);\n        $.num_directions = reader.int64(json.num_directions, 0n);\n        $.dropout = reader.value(json.dropout, 0);\n        $.zoneout_cell = reader.value(json.zoneout_cell, 0);\n        $.zoneout_hidden = reader.value(json.zoneout_hidden, 0);\n        $.proj_size = reader.int64(json.proj_size, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.LSTMGrad = class LSTMGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LSTMGrad();\n        $.bidirectional = reader.bool_(position, 4, false);\n        $.has_bias = reader.bool_(position, 6, false);\n        $.input_size = reader.int64_(position, 8, 0n);\n        $.hidden_size = reader.int64_(position, 10, 0n);\n        $.num_layers = reader.int64_(position, 12, 0n);\n        $.num_directions = reader.int64_(position, 14, 0n);\n        $.dropout = reader.float32_(position, 16, 0);\n        $.zoneout_cell = reader.float32_(position, 18, 0);\n        $.zoneout_hidden = reader.float32_(position, 20, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LSTMGrad();\n        $.bidirectional = reader.value(json.bidirectional, false);\n        $.has_bias = reader.value(json.has_bias, false);\n        $.input_size = reader.int64(json.input_size, 0n);\n        $.hidden_size = reader.int64(json.hidden_size, 0n);\n        $.num_layers = reader.int64(json.num_layers, 0n);\n        $.num_directions = reader.int64(json.num_directions, 0n);\n        $.dropout = reader.value(json.dropout, 0);\n        $.zoneout_cell = reader.value(json.zoneout_cell, 0);\n        $.zoneout_hidden = reader.value(json.zoneout_hidden, 0);\n        return $;\n    }\n};\n\nmindspore.schema.L2NormalizeFusion = class L2NormalizeFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.L2NormalizeFusion();\n        $.axis = reader.int64s_(position, 4);\n        $.epsilon = reader.float32_(position, 6, 0);\n        $.activation_type = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.L2NormalizeFusion();\n        $.axis = reader.array(json.axis);\n        $.epsilon = reader.value(json.epsilon, 0);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.MatMulFusion = class MatMulFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MatMulFusion();\n        $.transpose_a = reader.bool_(position, 4, false);\n        $.transpose_b = reader.bool_(position, 6, false);\n        $.activation_type = reader.int8_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MatMulFusion();\n        $.transpose_a = reader.value(json.transpose_a, false);\n        $.transpose_b = reader.value(json.transpose_b, false);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.Maximum = class Maximum {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Maximum();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Maximum();\n        return $;\n    }\n};\n\nmindspore.schema.MaximumGrad = class MaximumGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MaximumGrad();\n        $.grad_x = reader.bool_(position, 4, false);\n        $.grad_y = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MaximumGrad();\n        $.grad_x = reader.value(json.grad_x, false);\n        $.grad_y = reader.value(json.grad_y, false);\n        return $;\n    }\n};\n\nmindspore.schema.MaxPoolFusion = class MaxPoolFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MaxPoolFusion();\n        $.kernel_size = reader.int64s_(position, 4);\n        $.strides = reader.int64s_(position, 6);\n        $.pad = reader.int64s_(position, 8);\n        $.pad_mode = reader.int8_(position, 10, 0);\n        $.round_mode = reader.int8_(position, 12, 0);\n        $.format = reader.int32_(position, 14, 0);\n        $.global = reader.bool_(position, 16, false);\n        $.activation_type = reader.int8_(position, 18, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MaxPoolFusion();\n        $.kernel_size = reader.array(json.kernel_size);\n        $.strides = reader.array(json.strides);\n        $.pad = reader.array(json.pad);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.round_mode = mindspore.schema.RoundMode[json.round_mode];\n        $.format = mindspore.schema.Format[json.format];\n        $.global = reader.value(json.global, false);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.MaxPoolGrad = class MaxPoolGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MaxPoolGrad();\n        $.kernel_size = reader.int64s_(position, 4);\n        $.strides = reader.int64s_(position, 6);\n        $.pad_mode = reader.int8_(position, 8, 0);\n        $.format = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MaxPoolGrad();\n        $.kernel_size = reader.array(json.kernel_size);\n        $.strides = reader.array(json.strides);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.format = mindspore.schema.Format[json.format];\n        return $;\n    }\n};\n\nmindspore.schema.SwitchLayer = class SwitchLayer {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SwitchLayer();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SwitchLayer();\n        return $;\n    }\n};\n\nmindspore.schema.Mfcc = class Mfcc {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Mfcc();\n        $.freq_upper_limit = reader.float32_(position, 4, 0);\n        $.freq_lower_limit = reader.float32_(position, 6, 0);\n        $.filter_bank_channel_num = reader.int64_(position, 8, 0n);\n        $.dct_coeff_num = reader.int64_(position, 10, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Mfcc();\n        $.freq_upper_limit = reader.value(json.freq_upper_limit, 0);\n        $.freq_lower_limit = reader.value(json.freq_lower_limit, 0);\n        $.filter_bank_channel_num = reader.int64(json.filter_bank_channel_num, 0n);\n        $.dct_coeff_num = reader.int64(json.dct_coeff_num, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Minimum = class Minimum {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Minimum();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Minimum();\n        return $;\n    }\n};\n\nmindspore.schema.MinimumGrad = class MinimumGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MinimumGrad();\n        $.grad_x = reader.bool_(position, 4, false);\n        $.grad_y = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MinimumGrad();\n        $.grad_x = reader.value(json.grad_x, false);\n        $.grad_y = reader.value(json.grad_y, false);\n        return $;\n    }\n};\n\nmindspore.schema.Mod = class Mod {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Mod();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Mod();\n        return $;\n    }\n};\n\nmindspore.schema.MulFusion = class MulFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MulFusion();\n        $.activation_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MulFusion();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.MulGrad = class MulGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.MulGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.MulGrad();\n        return $;\n    }\n};\n\nmindspore.schema.Neg = class Neg {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Neg();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Neg();\n        return $;\n    }\n};\n\nmindspore.schema.NegGrad = class NegGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.NegGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.NegGrad();\n        return $;\n    }\n};\n\nmindspore.schema.NotEqual = class NotEqual {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.NotEqual();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.NotEqual();\n        return $;\n    }\n};\n\nmindspore.schema.NonMaxSuppression = class NonMaxSuppression {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.NonMaxSuppression();\n        $.center_point_box = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.NonMaxSuppression();\n        $.center_point_box = reader.int64(json.center_point_box, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.OneHot = class OneHot {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.OneHot();\n        $.axis = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.OneHot();\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.OnesLike = class OnesLike {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.OnesLike();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.OnesLike();\n        return $;\n    }\n};\n\nmindspore.schema.PadFusion = class PadFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.PadFusion();\n        $.paddings = reader.table(position, 4, mindspore.schema.Vec2D);\n        $.padding_mode = reader.int8_(position, 6, 0);\n        $.constant_value = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.PadFusion();\n        $.paddings = reader.object(json.paddings, mindspore.schema.Vec2D);\n        $.padding_mode = mindspore.schema.PaddingMode[json.padding_mode];\n        $.constant_value = reader.value(json.constant_value, 0);\n        return $;\n    }\n};\n\nmindspore.schema.PartialFusion = class PartialFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.PartialFusion();\n        $.sub_graph_index = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.PartialFusion();\n        $.sub_graph_index = reader.int64(json.sub_graph_index, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.PowerGrad = class PowerGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.PowerGrad();\n        $.power = reader.float32_(position, 4, 0);\n        $.scale = reader.float32_(position, 6, 0);\n        $.shift = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.PowerGrad();\n        $.power = reader.value(json.power, 0);\n        $.scale = reader.value(json.scale, 0);\n        $.shift = reader.value(json.shift, 0);\n        return $;\n    }\n};\n\nmindspore.schema.PowFusion = class PowFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.PowFusion();\n        $.scale = reader.float32_(position, 4, 1);\n        $.shift = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.PowFusion();\n        $.scale = reader.value(json.scale, 1);\n        $.shift = reader.value(json.shift, 0);\n        return $;\n    }\n};\n\nmindspore.schema.PriorBox = class PriorBox {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.PriorBox();\n        $.min_sizes = reader.int64s_(position, 4);\n        $.max_sizes = reader.int64s_(position, 6);\n        $.aspect_ratios = reader.array(position, 8, Float32Array);\n        $.variances = reader.array(position, 10, Float32Array);\n        $.image_size_w = reader.int64_(position, 12, 0n);\n        $.image_size_h = reader.int64_(position, 14, 0n);\n        $.step_w = reader.float32_(position, 16, 0);\n        $.step_h = reader.float32_(position, 18, 0);\n        $.clip = reader.bool_(position, 20, false);\n        $.flip = reader.bool_(position, 22, false);\n        $.offset = reader.float32_(position, 24, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.PriorBox();\n        $.min_sizes = reader.array(json.min_sizes);\n        $.max_sizes = reader.array(json.max_sizes);\n        $.aspect_ratios = reader.array(json.aspect_ratios, Float32Array);\n        $.variances = reader.array(json.variances, Float32Array);\n        $.image_size_w = reader.int64(json.image_size_w, 0n);\n        $.image_size_h = reader.int64(json.image_size_h, 0n);\n        $.step_w = reader.value(json.step_w, 0);\n        $.step_h = reader.value(json.step_h, 0);\n        $.clip = reader.value(json.clip, false);\n        $.flip = reader.value(json.flip, false);\n        $.offset = reader.value(json.offset, 0);\n        return $;\n    }\n};\n\nmindspore.schema.PReLUFusion = class PReLUFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.PReLUFusion();\n        $.channel_shared = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.PReLUFusion();\n        $.channel_shared = reader.value(json.channel_shared, false);\n        return $;\n    }\n};\n\nmindspore.schema.Rank = class Rank {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Rank();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Rank();\n        return $;\n    }\n};\n\nmindspore.schema.Range = class Range {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Range();\n        $.d_type = reader.int64_(position, 4, 0n);\n        $.start = reader.int64_(position, 6, 0n);\n        $.limit = reader.int64_(position, 8, 0n);\n        $.delta = reader.int64_(position, 10, 1n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Range();\n        $.d_type = reader.int64(json.d_type, 0n);\n        $.start = reader.int64(json.start, 0n);\n        $.limit = reader.int64(json.limit, 0n);\n        $.delta = reader.int64(json.delta, 1n);\n        return $;\n    }\n};\n\nmindspore.schema.Reciprocal = class Reciprocal {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Reciprocal();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Reciprocal();\n        return $;\n    }\n};\n\nmindspore.schema.RealDiv = class RealDiv {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.RealDiv();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.RealDiv();\n        return $;\n    }\n};\n\nmindspore.schema.ReduceFusion = class ReduceFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ReduceFusion();\n        $.keep_dims = reader.bool_(position, 4, false);\n        $.mode = reader.int8_(position, 6, 0);\n        $.reduce_to_end = reader.bool_(position, 8, false);\n        $.coeff = reader.float32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ReduceFusion();\n        $.keep_dims = reader.value(json.keep_dims, false);\n        $.mode = mindspore.schema.ReduceMode[json.mode];\n        $.reduce_to_end = reader.value(json.reduce_to_end, false);\n        $.coeff = reader.value(json.coeff, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Reshape = class Reshape {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Reshape();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Reshape();\n        return $;\n    }\n};\n\nmindspore.schema.Resize = class Resize {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Resize();\n        $.format = reader.int32_(position, 4, 0);\n        $.method = reader.int8_(position, 6, 0);\n        $.new_height = reader.int64_(position, 8, 0n);\n        $.new_width = reader.int64_(position, 10, 0n);\n        $.preserve_aspect_ratio = reader.bool_(position, 12, false);\n        $.coordinate_transform_mode = reader.int8_(position, 14, 0);\n        $.cubic_coeff = reader.float32_(position, 16, 0);\n        $.exclude_outside = reader.int64_(position, 18, 0n);\n        $.extrapolation_value = reader.float32_(position, 20, 0);\n        $.nearest_mode = reader.int8_(position, 22, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Resize();\n        $.format = mindspore.schema.Format[json.format];\n        $.method = mindspore.schema.ResizeMethod[json.method];\n        $.new_height = reader.int64(json.new_height, 0n);\n        $.new_width = reader.int64(json.new_width, 0n);\n        $.preserve_aspect_ratio = reader.value(json.preserve_aspect_ratio, false);\n        $.coordinate_transform_mode = mindspore.schema.CoordinateTransformMode[json.coordinate_transform_mode];\n        $.cubic_coeff = reader.value(json.cubic_coeff, 0);\n        $.exclude_outside = reader.int64(json.exclude_outside, 0n);\n        $.extrapolation_value = reader.value(json.extrapolation_value, 0);\n        $.nearest_mode = mindspore.schema.NearestMode[json.nearest_mode];\n        return $;\n    }\n};\n\nmindspore.schema.ReverseSequence = class ReverseSequence {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ReverseSequence();\n        $.seq_dim = reader.int64_(position, 4, 0n);\n        $.batch_dim = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ReverseSequence();\n        $.seq_dim = reader.int64(json.seq_dim, 0n);\n        $.batch_dim = reader.int64(json.batch_dim, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.ReverseV2 = class ReverseV2 {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ReverseV2();\n        $.axis = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ReverseV2();\n        $.axis = reader.array(json.axis);\n        return $;\n    }\n};\n\nmindspore.schema.Rfft = class Rfft {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Rfft();\n        $.fft_length = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Rfft();\n        $.fft_length = reader.int64(json.fft_length, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.ROIPooling = class ROIPooling {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ROIPooling();\n        $.pooled_h = reader.int64_(position, 4, 0n);\n        $.pooled_w = reader.int64_(position, 6, 0n);\n        $.scale = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ROIPooling();\n        $.pooled_h = reader.int64(json.pooled_h, 0n);\n        $.pooled_w = reader.int64(json.pooled_w, 0n);\n        $.scale = reader.value(json.scale, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Round = class Round {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Round();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Round();\n        return $;\n    }\n};\n\nmindspore.schema.Rsqrt = class Rsqrt {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Rsqrt();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Rsqrt();\n        return $;\n    }\n};\n\nmindspore.schema.QuantDTypeCast = class QuantDTypeCast {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.QuantDTypeCast();\n        $.src_t = reader.int64_(position, 4, 0n);\n        $.dst_t = reader.int64_(position, 6, 0n);\n        $.axis = reader.int64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.QuantDTypeCast();\n        $.src_t = reader.int64(json.src_t, 0n);\n        $.dst_t = reader.int64(json.dst_t, 0n);\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.ScaleFusion = class ScaleFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ScaleFusion();\n        $.axis = reader.int64_(position, 4, 0n);\n        $.activation_type = reader.int8_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ScaleFusion();\n        $.axis = reader.int64(json.axis, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.ScatterNd = class ScatterNd {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.ScatterNd();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.ScatterNd();\n        return $;\n    }\n};\n\nmindspore.schema.SGD = class SGD {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SGD();\n        $.nesterov = reader.bool_(position, 4, false);\n        $.dampening = reader.float32_(position, 6, 0);\n        $.weight_decay = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SGD();\n        $.nesterov = reader.value(json.nesterov, false);\n        $.dampening = reader.value(json.dampening, 0);\n        $.weight_decay = reader.value(json.weight_decay, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Shape = class Shape {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Shape();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Shape();\n        return $;\n    }\n};\n\nmindspore.schema.SigmoidCrossEntropyWithLogits = class SigmoidCrossEntropyWithLogits {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SigmoidCrossEntropyWithLogits();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SigmoidCrossEntropyWithLogits();\n        return $;\n    }\n};\n\nmindspore.schema.SigmoidCrossEntropyWithLogitsGrad = class SigmoidCrossEntropyWithLogitsGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SigmoidCrossEntropyWithLogitsGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SigmoidCrossEntropyWithLogitsGrad();\n        return $;\n    }\n};\n\nmindspore.schema.Sin = class Sin {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Sin();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Sin();\n        return $;\n    }\n};\n\nmindspore.schema.SkipGram = class SkipGram {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SkipGram();\n        $.include_all_grams = reader.bool_(position, 4, false);\n        $.max_skip_size = reader.int64_(position, 6, 0n);\n        $.ngram_size = reader.int64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SkipGram();\n        $.include_all_grams = reader.value(json.include_all_grams, false);\n        $.max_skip_size = reader.int64(json.max_skip_size, 0n);\n        $.ngram_size = reader.int64(json.ngram_size, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.SliceFusion = class SliceFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SliceFusion();\n        $.axes = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SliceFusion();\n        $.axes = reader.array(json.axes);\n        return $;\n    }\n};\n\nmindspore.schema.SmoothL1Loss = class SmoothL1Loss {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SmoothL1Loss();\n        $.beta = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SmoothL1Loss();\n        $.beta = reader.value(json.beta, 0);\n        return $;\n    }\n};\n\nmindspore.schema.SmoothL1LossGrad = class SmoothL1LossGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SmoothL1LossGrad();\n        $.beta = reader.float32_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SmoothL1LossGrad();\n        $.beta = reader.value(json.beta, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Softmax = class Softmax {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Softmax();\n        $.axis = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Softmax();\n        $.axis = reader.array(json.axis);\n        return $;\n    }\n};\n\nmindspore.schema.SoftmaxCrossEntropyWithLogits = class SoftmaxCrossEntropyWithLogits {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SoftmaxCrossEntropyWithLogits();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SoftmaxCrossEntropyWithLogits();\n        return $;\n    }\n};\n\nmindspore.schema.SpaceToBatch = class SpaceToBatch {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SpaceToBatch();\n        $.block_size = reader.int64s_(position, 4);\n        $.paddings = reader.table(position, 6, mindspore.schema.Vec2D);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SpaceToBatch();\n        $.block_size = reader.array(json.block_size);\n        $.paddings = reader.object(json.paddings, mindspore.schema.Vec2D);\n        return $;\n    }\n};\n\nmindspore.schema.SpaceToBatchND = class SpaceToBatchND {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SpaceToBatchND();\n        $.block_shape = reader.int64s_(position, 4);\n        $.paddings = reader.table(position, 6, mindspore.schema.Vec2D);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SpaceToBatchND();\n        $.block_shape = reader.array(json.block_shape);\n        $.paddings = reader.object(json.paddings, mindspore.schema.Vec2D);\n        return $;\n    }\n};\n\nmindspore.schema.SpaceToDepth = class SpaceToDepth {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SpaceToDepth();\n        $.block_size = reader.int64_(position, 4, 0n);\n        $.format = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SpaceToDepth();\n        $.block_size = reader.int64(json.block_size, 0n);\n        $.format = mindspore.schema.Format[json.format];\n        return $;\n    }\n};\n\nmindspore.schema.SparseSoftmaxCrossEntropyWithLogits = class SparseSoftmaxCrossEntropyWithLogits {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SparseSoftmaxCrossEntropyWithLogits();\n        $.is_grad = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SparseSoftmaxCrossEntropyWithLogits();\n        $.is_grad = reader.value(json.is_grad, false);\n        return $;\n    }\n};\n\nmindspore.schema.SparseToDense = class SparseToDense {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SparseToDense();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SparseToDense();\n        return $;\n    }\n};\n\nmindspore.schema.Split = class Split {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Split();\n        $.output_num = reader.int64_(position, 4, 0n);\n        $.size_splits = reader.int64s_(position, 6);\n        $.axis = reader.int64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Split();\n        $.output_num = reader.int64(json.output_num, 0n);\n        $.size_splits = reader.array(json.size_splits);\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Sqrt = class Sqrt {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Sqrt();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Sqrt();\n        return $;\n    }\n};\n\nmindspore.schema.Squeeze = class Squeeze {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Squeeze();\n        $.axis = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Squeeze();\n        $.axis = reader.array(json.axis);\n        return $;\n    }\n};\n\nmindspore.schema.Square = class Square {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Square();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Square();\n        return $;\n    }\n};\n\nmindspore.schema.SquaredDifference = class SquaredDifference {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SquaredDifference();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SquaredDifference();\n        return $;\n    }\n};\n\nmindspore.schema.Stack = class Stack {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Stack();\n        $.axis = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Stack();\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.StridedSlice = class StridedSlice {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.StridedSlice();\n        $.begin_mask = reader.int64_(position, 4, 0n);\n        $.end_mask = reader.int64_(position, 6, 0n);\n        $.ellipsis_mask = reader.int64_(position, 8, 0n);\n        $.new_axis_mask = reader.int64_(position, 10, 0n);\n        $.shrink_axis_mask = reader.int64_(position, 12, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.StridedSlice();\n        $.begin_mask = reader.int64(json.begin_mask, 0n);\n        $.end_mask = reader.int64(json.end_mask, 0n);\n        $.ellipsis_mask = reader.int64(json.ellipsis_mask, 0n);\n        $.new_axis_mask = reader.int64(json.new_axis_mask, 0n);\n        $.shrink_axis_mask = reader.int64(json.shrink_axis_mask, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.SubFusion = class SubFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SubFusion();\n        $.activation_type = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SubFusion();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        return $;\n    }\n};\n\nmindspore.schema.SubGrad = class SubGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SubGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SubGrad();\n        return $;\n    }\n};\n\nmindspore.schema.Switch = class Switch {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Switch();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Switch();\n        return $;\n    }\n};\n\nmindspore.schema.TensorListFromTensor = class TensorListFromTensor {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TensorListFromTensor();\n        $.element_dtype = reader.int64_(position, 4, 0n);\n        $.shape_type = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TensorListFromTensor();\n        $.element_dtype = reader.int64(json.element_dtype, 0n);\n        $.shape_type = reader.int64(json.shape_type, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.TensorListGetItem = class TensorListGetItem {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TensorListGetItem();\n        $.element_dtype = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TensorListGetItem();\n        $.element_dtype = reader.int64(json.element_dtype, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.TensorListReserve = class TensorListReserve {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TensorListReserve();\n        $.element_dtype = reader.int64_(position, 4, 0n);\n        $.shape_type = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TensorListReserve();\n        $.element_dtype = reader.int64(json.element_dtype, 0n);\n        $.shape_type = reader.int64(json.shape_type, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.TensorListSetItem = class TensorListSetItem {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TensorListSetItem();\n        $.element_dtype = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TensorListSetItem();\n        $.element_dtype = reader.int64(json.element_dtype, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.TensorListStack = class TensorListStack {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TensorListStack();\n        $.num_elements = reader.int64_(position, 4, 0n);\n        $.element_dtype = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TensorListStack();\n        $.num_elements = reader.int64(json.num_elements, 0n);\n        $.element_dtype = reader.int64(json.element_dtype, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.TileFusion = class TileFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TileFusion();\n        $.dims = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TileFusion();\n        $.dims = reader.array(json.dims);\n        return $;\n    }\n};\n\nmindspore.schema.TopKFusion = class TopKFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TopKFusion();\n        $.sorted = reader.bool_(position, 4, true);\n        $.axis = reader.int64_(position, 6, 0n);\n        $.largest = reader.int64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TopKFusion();\n        $.sorted = reader.value(json.sorted, true);\n        $.axis = reader.int64(json.axis, 0n);\n        $.largest = reader.int64(json.largest, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Transpose = class Transpose {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Transpose();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Transpose();\n        return $;\n    }\n};\n\nmindspore.schema.Unique = class Unique {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Unique();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Unique();\n        return $;\n    }\n};\n\nmindspore.schema.UnsortedSegmentSum = class UnsortedSegmentSum {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.UnsortedSegmentSum();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.UnsortedSegmentSum();\n        return $;\n    }\n};\n\nmindspore.schema.Unsqueeze = class Unsqueeze {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Unsqueeze();\n        $.axis = reader.int64s_(position, 4);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Unsqueeze();\n        $.axis = reader.array(json.axis);\n        return $;\n    }\n};\n\nmindspore.schema.Unstack = class Unstack {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Unstack();\n        $.axis = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Unstack();\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Where = class Where {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Where();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Where();\n        return $;\n    }\n};\n\nmindspore.schema.ZerosLike = class ZerosLike {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.ZerosLike();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.ZerosLike();\n        return $;\n    }\n};\n\nmindspore.schema.Select = class Select {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Select();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Select();\n        return $;\n    }\n};\n\nmindspore.schema.GRU = class GRU {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.GRU();\n        $.bidirectional = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.GRU();\n        $.bidirectional = reader.value(json.bidirectional, false);\n        return $;\n    }\n};\n\nmindspore.schema.NonZero = class NonZero {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.NonZero();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.NonZero();\n        return $;\n    }\n};\n\nmindspore.schema.InvertPermutation = class InvertPermutation {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.InvertPermutation();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.InvertPermutation();\n        return $;\n    }\n};\n\nmindspore.schema.Size = class Size {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Size();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Size();\n        return $;\n    }\n};\n\nmindspore.schema.RandomStandardNormal = class RandomStandardNormal {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.RandomStandardNormal();\n        $.seed = reader.int64_(position, 4, 0n);\n        $.seed2 = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.RandomStandardNormal();\n        $.seed = reader.int64(json.seed, 0n);\n        $.seed2 = reader.int64(json.seed2, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.CropAndResize = class CropAndResize {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.CropAndResize();\n        $.method = reader.int8_(position, 4, 0);\n        $.extrapolation_value = reader.float32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.CropAndResize();\n        $.method = mindspore.schema.ResizeMethod[json.method];\n        $.extrapolation_value = reader.value(json.extrapolation_value, 0);\n        return $;\n    }\n};\n\nmindspore.schema.Erf = class Erf {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Erf();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Erf();\n        return $;\n    }\n};\n\nmindspore.schema.StridedSliceGrad = class StridedSliceGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.StridedSliceGrad();\n        $.begin_mask = reader.int64_(position, 4, 0n);\n        $.end_mask = reader.int64_(position, 6, 0n);\n        $.ellipsis_mask = reader.int64_(position, 8, 0n);\n        $.new_axis_mask = reader.int64_(position, 10, 0n);\n        $.shrink_axis_mask = reader.int64_(position, 12, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.StridedSliceGrad();\n        $.begin_mask = reader.int64(json.begin_mask, 0n);\n        $.end_mask = reader.int64(json.end_mask, 0n);\n        $.ellipsis_mask = reader.int64(json.ellipsis_mask, 0n);\n        $.new_axis_mask = reader.int64(json.new_axis_mask, 0n);\n        $.shrink_axis_mask = reader.int64(json.shrink_axis_mask, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.IsFinite = class IsFinite {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.IsFinite();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.IsFinite();\n        return $;\n    }\n};\n\nmindspore.schema.LinSpace = class LinSpace {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.LinSpace();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.LinSpace();\n        return $;\n    }\n};\n\nmindspore.schema.UniformReal = class UniformReal {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.UniformReal();\n        $.seed = reader.int64_(position, 4, 0n);\n        $.seed2 = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.UniformReal();\n        $.seed = reader.int64(json.seed, 0n);\n        $.seed2 = reader.int64(json.seed2, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.AbsGrad = class AbsGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.AbsGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.AbsGrad();\n        return $;\n    }\n};\n\nmindspore.schema.RsqrtGrad = class RsqrtGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.RsqrtGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.RsqrtGrad();\n        return $;\n    }\n};\n\nmindspore.schema.SqrtGrad = class SqrtGrad {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SqrtGrad();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SqrtGrad();\n        return $;\n    }\n};\n\nmindspore.schema.LayerNormGrad = class LayerNormGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LayerNormGrad();\n        $.begin_norm_axis = reader.int64_(position, 4, 0n);\n        $.begin_params_axis = reader.int64_(position, 6, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LayerNormGrad();\n        $.begin_norm_axis = reader.int64(json.begin_norm_axis, 0n);\n        $.begin_params_axis = reader.int64(json.begin_params_axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.ResizeGrad = class ResizeGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ResizeGrad();\n        $.method = reader.int8_(position, 4, 0);\n        $.align_corners = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ResizeGrad();\n        $.method = mindspore.schema.ResizeMethod[json.method];\n        $.align_corners = reader.value(json.align_corners, false);\n        return $;\n    }\n};\n\nmindspore.schema.Splice = class Splice {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Splice();\n        $.context = reader.int64s_(position, 4);\n        $.forward_indexes = reader.int64s_(position, 6);\n        $.output_dim = reader.int64_(position, 8, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Splice();\n        $.context = reader.array(json.context);\n        $.forward_indexes = reader.array(json.forward_indexes);\n        $.output_dim = reader.int64(json.output_dim, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.LogSoftmax = class LogSoftmax {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LogSoftmax();\n        $.axis = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LogSoftmax();\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Call = class Call {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Call();\n        $.is_tail_call = reader.bool_(position, 4, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Call();\n        $.is_tail_call = reader.value(json.is_tail_call, true);\n        return $;\n    }\n};\n\nmindspore.schema.CumSum = class CumSum {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.CumSum();\n        $.exclusive = reader.bool_(position, 4, false);\n        $.reverse = reader.bool_(position, 6, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.CumSum();\n        $.exclusive = reader.value(json.exclusive, false);\n        $.reverse = reader.value(json.reverse, false);\n        return $;\n    }\n};\n\nmindspore.schema.Custom = class Custom {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Custom();\n        $.type = reader.string_(position, 4, null);\n        $.attr = reader.tables(position, 6, mindspore.schema.Attribute);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Custom();\n        $.type = reader.value(json.type, null);\n        $.attr = reader.objects(json.attr, mindspore.schema.Attribute);\n        return $;\n    }\n};\n\nmindspore.schema.SplitWithOverlap = class SplitWithOverlap {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SplitWithOverlap();\n        $.split_dim = reader.int64_(position, 4, 0n);\n        $.number_split = reader.int64_(position, 6, 0n);\n        $.ratio = reader.int64s_(position, 8);\n        $.extend_top = reader.int64s_(position, 10);\n        $.extend_bottom = reader.int64s_(position, 12);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SplitWithOverlap();\n        $.split_dim = reader.int64(json.split_dim, 0n);\n        $.number_split = reader.int64(json.number_split, 0n);\n        $.ratio = reader.array(json.ratio);\n        $.extend_top = reader.array(json.extend_top);\n        $.extend_bottom = reader.array(json.extend_bottom);\n        return $;\n    }\n};\n\nmindspore.schema.GenOP = class GenOP {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.GenOP();\n        $.activation_type = reader.int8_(position, 4, 0);\n        $.alpha = reader.float32_(position, 6, 0);\n        $.min_val = reader.float32_(position, 8, 0);\n        $.max_val = reader.float32_(position, 10, 0);\n        $.is_training = reader.bool_(position, 12, false);\n        $.format = reader.int32_(position, 14, 0);\n        $.kernel_size = reader.int64s_(position, 16);\n        $.stride = reader.int64s_(position, 18);\n        $.dilation = reader.int64s_(position, 20);\n        $.pad_mode = reader.int8_(position, 22, 0);\n        $.pad_list = reader.int64s_(position, 24);\n        $.mode = reader.int64_(position, 26, 0n);\n        $.group = reader.int64_(position, 28, 0n);\n        $.in_channel = reader.int64_(position, 30, 0n);\n        $.out_channel = reader.int64_(position, 32, 0n);\n        $.eltwise_mode = reader.int8_(position, 34, 0);\n        $.has_bias = reader.bool_(position, 36, false);\n        $.use_axis = reader.bool_(position, 38, false);\n        $.axis = reader.int64_(position, 40, 0n);\n        $.epsilon = reader.float32_(position, 42, 0.0001);\n        $.momentum = reader.float32_(position, 44, 0.9);\n        $.transpose_a = reader.bool_(position, 46, false);\n        $.transpose_b = reader.bool_(position, 48, false);\n        $.pad = reader.int64s_(position, 50);\n        $.round_mode = reader.int8_(position, 52, 0);\n        $.global = reader.bool_(position, 54, false);\n        $.channel_shared = reader.bool_(position, 56, false);\n        $.axes = reader.int64s_(position, 58);\n        $.keep_dims = reader.bool_(position, 60, false);\n        $.reduce_mode = reader.int8_(position, 62, 0);\n        $.reduce_to_end = reader.bool_(position, 64, false);\n        $.coeff = reader.float32_(position, 66, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.GenOP();\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        $.alpha = reader.value(json.alpha, 0);\n        $.min_val = reader.value(json.min_val, 0);\n        $.max_val = reader.value(json.max_val, 0);\n        $.is_training = reader.value(json.is_training, false);\n        $.format = mindspore.schema.Format[json.format];\n        $.kernel_size = reader.array(json.kernel_size);\n        $.stride = reader.array(json.stride);\n        $.dilation = reader.array(json.dilation);\n        $.pad_mode = mindspore.schema.PadMode[json.pad_mode];\n        $.pad_list = reader.array(json.pad_list);\n        $.mode = reader.int64(json.mode, 0n);\n        $.group = reader.int64(json.group, 0n);\n        $.in_channel = reader.int64(json.in_channel, 0n);\n        $.out_channel = reader.int64(json.out_channel, 0n);\n        $.eltwise_mode = mindspore.schema.EltwiseMode[json.eltwise_mode];\n        $.has_bias = reader.value(json.has_bias, false);\n        $.use_axis = reader.value(json.use_axis, false);\n        $.axis = reader.int64(json.axis, 0n);\n        $.epsilon = reader.value(json.epsilon, 0.0001);\n        $.momentum = reader.value(json.momentum, 0.9);\n        $.transpose_a = reader.value(json.transpose_a, false);\n        $.transpose_b = reader.value(json.transpose_b, false);\n        $.pad = reader.array(json.pad);\n        $.round_mode = mindspore.schema.RoundMode[json.round_mode];\n        $.global = reader.value(json.global, false);\n        $.channel_shared = reader.value(json.channel_shared, false);\n        $.axes = reader.array(json.axes);\n        $.keep_dims = reader.value(json.keep_dims, false);\n        $.reduce_mode = mindspore.schema.ReduceMode[json.reduce_mode];\n        $.reduce_to_end = reader.value(json.reduce_to_end, false);\n        $.coeff = reader.value(json.coeff, 0);\n        return $;\n    }\n};\n\nmindspore.schema.RaggedRange = class RaggedRange {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.RaggedRange();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.RaggedRange();\n        return $;\n    }\n};\n\nmindspore.schema.GLU = class GLU {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.GLU();\n        $.axis = reader.int64_(position, 4, -1n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.GLU();\n        $.axis = reader.int64(json.axis, -1n);\n        return $;\n    }\n};\n\nmindspore.schema.TensorArray = class TensorArray {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.TensorArray();\n        $.dynamic_size = reader.bool_(position, 4, false);\n        $.identical_element_shapes = reader.bool_(position, 6, false);\n        $.element_shape = reader.array(position, 8, Int32Array);\n        $.data_type = reader.int32_(position, 10, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.TensorArray();\n        $.dynamic_size = reader.value(json.dynamic_size, false);\n        $.identical_element_shapes = reader.value(json.identical_element_shapes, false);\n        $.element_shape = reader.array(json.element_shape, Int32Array);\n        $.data_type = reader.value(json.data_type, 0);\n        return $;\n    }\n};\n\nmindspore.schema.TensorArrayRead = class TensorArrayRead {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.TensorArrayRead();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.TensorArrayRead();\n        return $;\n    }\n};\n\nmindspore.schema.TensorArrayWrite = class TensorArrayWrite {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.TensorArrayWrite();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.TensorArrayWrite();\n        return $;\n    }\n};\n\nmindspore.schema.Affine = class Affine {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Affine();\n        $.context = reader.int64s_(position, 4);\n        $.output_dim = reader.int64_(position, 6, 0n);\n        $.activation_type = reader.int8_(position, 8, 0);\n        $.transpose_a = reader.bool_(position, 10, false);\n        $.transpose_b = reader.bool_(position, 12, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Affine();\n        $.context = reader.array(json.context);\n        $.output_dim = reader.int64(json.output_dim, 0n);\n        $.activation_type = mindspore.schema.ActivationType[json.activation_type];\n        $.transpose_a = reader.value(json.transpose_a, false);\n        $.transpose_b = reader.value(json.transpose_b, false);\n        return $;\n    }\n};\n\nmindspore.schema.ScatterNdUpdate = class ScatterNdUpdate {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.ScatterNdUpdate();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.ScatterNdUpdate();\n        return $;\n    }\n};\n\nmindspore.schema.AllGather = class AllGather {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AllGather();\n        $.group = reader.string_(position, 4, null);\n        $.rank_size = reader.int32_(position, 6, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AllGather();\n        $.group = reader.value(json.group, null);\n        $.rank_size = reader.value(json.rank_size, 0);\n        return $;\n    }\n};\n\nmindspore.schema.ReduceScatter = class ReduceScatter {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ReduceScatter();\n        $.group = reader.string_(position, 4, null);\n        $.mode = reader.int8_(position, 6, 0);\n        $.rank_size = reader.int32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ReduceScatter();\n        $.group = reader.value(json.group, null);\n        $.mode = mindspore.schema.ReduceMode[json.mode];\n        $.rank_size = reader.value(json.rank_size, 0);\n        return $;\n    }\n};\n\nmindspore.schema.DynamicQuant = class DynamicQuant {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.DynamicQuant();\n        $.symmetric = reader.bool_(position, 4, false);\n        $.dst_type = reader.int64_(position, 6, 32n);\n        $.activation_channel = reader.bool_(position, 8, false);\n        $.prefer_axis = reader.int64_(position, 10, 0n);\n        $.transpose = reader.bool_(position, 12, false);\n        $.prefer_axes = reader.array(position, 14, Int32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.DynamicQuant();\n        $.symmetric = reader.value(json.symmetric, false);\n        $.dst_type = reader.int64(json.dst_type, 32n);\n        $.activation_channel = reader.value(json.activation_channel, false);\n        $.prefer_axis = reader.int64(json.prefer_axis, 0n);\n        $.transpose = reader.value(json.transpose, false);\n        $.prefer_axes = reader.array(json.prefer_axes, Int32Array);\n        return $;\n    }\n};\n\nmindspore.schema.LSTMGradData = class LSTMGradData {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LSTMGradData();\n        $.bidirectional = reader.bool_(position, 4, false);\n        $.has_bias = reader.bool_(position, 6, false);\n        $.input_size = reader.int64_(position, 8, 0n);\n        $.hidden_size = reader.int64_(position, 10, 0n);\n        $.num_layers = reader.int64_(position, 12, 0n);\n        $.num_directions = reader.int64_(position, 14, 0n);\n        $.dropout = reader.float32_(position, 16, 0);\n        $.zoneout_cell = reader.float32_(position, 18, 0);\n        $.zoneout_hidden = reader.float32_(position, 20, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LSTMGradData();\n        $.bidirectional = reader.value(json.bidirectional, false);\n        $.has_bias = reader.value(json.has_bias, false);\n        $.input_size = reader.int64(json.input_size, 0n);\n        $.hidden_size = reader.int64(json.hidden_size, 0n);\n        $.num_layers = reader.int64(json.num_layers, 0n);\n        $.num_directions = reader.int64(json.num_directions, 0n);\n        $.dropout = reader.value(json.dropout, 0);\n        $.zoneout_cell = reader.value(json.zoneout_cell, 0);\n        $.zoneout_hidden = reader.value(json.zoneout_hidden, 0);\n        return $;\n    }\n};\n\nmindspore.schema.LSTMGradWeight = class LSTMGradWeight {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.LSTMGradWeight();\n        $.bidirectional = reader.bool_(position, 4, false);\n        $.has_bias = reader.bool_(position, 6, false);\n        $.input_size = reader.int64_(position, 8, 0n);\n        $.hidden_size = reader.int64_(position, 10, 0n);\n        $.num_layers = reader.int64_(position, 12, 0n);\n        $.num_directions = reader.int64_(position, 14, 0n);\n        $.dropout = reader.float32_(position, 16, 0);\n        $.zoneout_cell = reader.float32_(position, 18, 0);\n        $.zoneout_hidden = reader.float32_(position, 20, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.LSTMGradWeight();\n        $.bidirectional = reader.value(json.bidirectional, false);\n        $.has_bias = reader.value(json.has_bias, false);\n        $.input_size = reader.int64(json.input_size, 0n);\n        $.hidden_size = reader.int64(json.hidden_size, 0n);\n        $.num_layers = reader.int64(json.num_layers, 0n);\n        $.num_directions = reader.int64(json.num_directions, 0n);\n        $.dropout = reader.value(json.dropout, 0);\n        $.zoneout_cell = reader.value(json.zoneout_cell, 0);\n        $.zoneout_hidden = reader.value(json.zoneout_hidden, 0);\n        return $;\n    }\n};\n\nmindspore.schema.RandomNormal = class RandomNormal {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.RandomNormal();\n        $.seed = reader.float32_(position, 4, 0);\n        $.mean = reader.float32_(position, 6, 0);\n        $.scale = reader.float32_(position, 8, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.RandomNormal();\n        $.seed = reader.value(json.seed, 0);\n        $.mean = reader.value(json.mean, 0);\n        $.scale = reader.value(json.scale, 0);\n        return $;\n    }\n};\n\nmindspore.schema.NLLLoss = class NLLLoss {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.NLLLoss();\n        $.reduction = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.NLLLoss();\n        $.reduction = mindspore.schema.Reduction[json.reduction];\n        return $;\n    }\n};\n\nmindspore.schema.NLLLossGrad = class NLLLossGrad {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.NLLLossGrad();\n        $.reduction = reader.int8_(position, 4, 0);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.NLLLossGrad();\n        $.reduction = mindspore.schema.Reduction[json.reduction];\n        return $;\n    }\n};\n\nmindspore.schema.FormatTranspose = class FormatTranspose {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.FormatTranspose();\n        $.src_format = reader.int32_(position, 4, 1);\n        $.dst_format = reader.int32_(position, 6, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.FormatTranspose();\n        $.src_format = mindspore.schema.Format[json.src_format];\n        $.dst_format = mindspore.schema.Format[json.dst_format];\n        return $;\n    }\n};\n\nmindspore.schema.GatherD = class GatherD {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.GatherD();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.GatherD();\n        return $;\n    }\n};\n\nmindspore.schema.GroupNormFusion = class GroupNormFusion {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.GroupNormFusion();\n        $.num_groups = reader.int64_(position, 4, 0n);\n        $.epsilon = reader.float32_(position, 6, 0.00001);\n        $.affine = reader.bool_(position, 8, true);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.GroupNormFusion();\n        $.num_groups = reader.int64(json.num_groups, 0n);\n        $.epsilon = reader.value(json.epsilon, 0.00001);\n        $.affine = reader.value(json.affine, true);\n        return $;\n    }\n};\n\nmindspore.schema.Log1p = class Log1p {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Log1p();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Log1p();\n        return $;\n    }\n};\n\nmindspore.schema.TensorScatterAdd = class TensorScatterAdd {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.TensorScatterAdd();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.TensorScatterAdd();\n        return $;\n    }\n};\n\nmindspore.schema.SparseFillEmptyRows = class SparseFillEmptyRows {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SparseFillEmptyRows();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SparseFillEmptyRows();\n        return $;\n    }\n};\n\nmindspore.schema.SparseReshape = class SparseReshape {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SparseReshape();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SparseReshape();\n        return $;\n    }\n};\n\nmindspore.schema.SparseSegmentSum = class SparseSegmentSum {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.SparseSegmentSum();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.SparseSegmentSum();\n        return $;\n    }\n};\n\nmindspore.schema.ScatterElements = class ScatterElements {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ScatterElements();\n        $.axis = reader.int64_(position, 4, 0n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ScatterElements();\n        $.axis = reader.int64(json.axis, 0n);\n        return $;\n    }\n};\n\nmindspore.schema.Triu = class Triu {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Triu();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Triu();\n        return $;\n    }\n};\n\nmindspore.schema.Tril = class Tril {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.Tril();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.Tril();\n        return $;\n    }\n};\n\nmindspore.schema.AdamWeightDecay = class AdamWeightDecay {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.AdamWeightDecay();\n        $.use_locking = reader.bool_(position, 4, false);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.AdamWeightDecay();\n        $.use_locking = reader.value(json.use_locking, false);\n        return $;\n    }\n};\n\nmindspore.schema.FillV2 = class FillV2 {\n\n    static decode(/* reader, position */) {\n        const $ = new mindspore.schema.FillV2();\n        return $;\n    }\n\n    static decodeText(/* reader, json */) {\n        const $ = new mindspore.schema.FillV2();\n        return $;\n    }\n};\n\nmindspore.schema.QuantParam = class QuantParam {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.QuantParam();\n        $.scale = reader.float64_(position, 4, 1);\n        $.zeroPoint = reader.int32_(position, 6, 0);\n        $.min = reader.float64_(position, 8, 0);\n        $.max = reader.float64_(position, 10, 0);\n        $.narrowRange = reader.bool_(position, 12, true);\n        $.numBits = reader.int32_(position, 14, 8);\n        $.inited = reader.bool_(position, 16, false);\n        $.varCorr = reader.float32_(position, 18, 1);\n        $.meanCorr = reader.float32_(position, 20, 0);\n        $.dstDtype = reader.int32_(position, 22, 32);\n        $.roundType = reader.int32_(position, 24, 1);\n        $.multiplier = reader.int32_(position, 26, 1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.QuantParam();\n        $.scale = reader.value(json.scale, 1);\n        $.zeroPoint = reader.value(json.zeroPoint, 0);\n        $.min = reader.value(json.min, 0);\n        $.max = reader.value(json.max, 0);\n        $.narrowRange = reader.value(json.narrowRange, true);\n        $.numBits = reader.value(json.numBits, 8);\n        $.inited = reader.value(json.inited, false);\n        $.varCorr = reader.value(json.varCorr, 1);\n        $.meanCorr = reader.value(json.meanCorr, 0);\n        $.dstDtype = reader.value(json.dstDtype, 32);\n        $.roundType = reader.value(json.roundType, 1);\n        $.multiplier = reader.value(json.multiplier, 1);\n        return $;\n    }\n};\n\nmindspore.schema.WeightQuantCompressType = {\n    NONE: 0, '0': 'NONE',\n    INDEXING: 1, '1': 'INDEXING',\n    SPARSE: 2, '2': 'SPARSE',\n    FSE: 3, '3': 'FSE',\n    BITPACKING: 4, '4': 'BITPACKING',\n    FSE_INT: 5, '5': 'FSE_INT',\n    FSE_INFER: 6, '6': 'FSE_INFER'\n};\n\nmindspore.schema.ExternalData = class ExternalData {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.ExternalData();\n        $.checkSum = reader.string_(position, 4, null);\n        $.location = reader.string_(position, 6, null);\n        $.offset = reader.int64_(position, 8, 0n);\n        $.length = reader.int64_(position, 10, -1n);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.ExternalData();\n        $.checkSum = reader.value(json.checkSum, null);\n        $.location = reader.value(json.location, null);\n        $.offset = reader.int64(json.offset, 0n);\n        $.length = reader.int64(json.length, -1n);\n        return $;\n    }\n};\n\nmindspore.schema.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Tensor();\n        $.nodeType = reader.int32_(position, 4, 0);\n        $.dataType = reader.int32_(position, 6, 0);\n        $.dims = reader.array(position, 8, Int32Array);\n        $.format = reader.int32_(position, 10, 0);\n        $.refCount = reader.int32_(position, 12, 0);\n        $.offset = reader.int32_(position, 14, 0);\n        $.data = reader.array(position, 16, Uint8Array);\n        $.quantParams = reader.tables(position, 18, mindspore.schema.QuantParam);\n        $.quantClusters = reader.array(position, 20, Float32Array);\n        $.name = reader.string_(position, 22, null);\n        $.enableHuffmanCode = reader.bool_(position, 24, false);\n        $.weightQuantCompressType = reader.int32_(position, 26, 0);\n        $.externalData = reader.tables(position, 28, mindspore.schema.ExternalData);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Tensor();\n        $.nodeType = reader.value(json.nodeType, 0);\n        $.dataType = reader.value(json.dataType, 0);\n        $.dims = reader.array(json.dims, Int32Array);\n        $.format = mindspore.schema.Format[json.format];\n        $.refCount = reader.value(json.refCount, 0);\n        $.offset = reader.value(json.offset, 0);\n        $.data = reader.array(json.data, Uint8Array);\n        $.quantParams = reader.objects(json.quantParams, mindspore.schema.QuantParam);\n        $.quantClusters = reader.array(json.quantClusters, Float32Array);\n        $.name = reader.value(json.name, null);\n        $.enableHuffmanCode = reader.value(json.enableHuffmanCode, false);\n        $.weightQuantCompressType = mindspore.schema.WeightQuantCompressType[json.weightQuantCompressType];\n        $.externalData = reader.objects(json.externalData, mindspore.schema.ExternalData);\n        return $;\n    }\n};\n\nmindspore.schema.QuantType = {\n    QUANT_NONE: 0, '0': 'QUANT_NONE',\n    AwareTraining: 1, '1': 'AwareTraining',\n    WeightQuant: 2, '2': 'WeightQuant',\n    PostTraining: 3, '3': 'PostTraining',\n    QUANT_WEIGHT: 4, '4': 'QUANT_WEIGHT',\n    QUANT_ALL: 5, '5': 'QUANT_ALL',\n    QUANT_DYNAMIC: 6, '6': 'QUANT_DYNAMIC'\n};\n\nmindspore.schema.Primitive = class Primitive {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.Primitive();\n        $.value = reader.union(position, 4, mindspore.schema.PrimitiveType);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.Primitive();\n        $.value = mindspore.schema.PrimitiveType.decodeText(reader, json.value, json.value_type);\n        return $;\n    }\n};\n\nmindspore.schema.CNode = class CNode {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.CNode();\n        $.name = reader.string_(position, 4, null);\n        $.nodeType = reader.int32_(position, 6, 0);\n        $.primitive = reader.table(position, 8, mindspore.schema.Primitive);\n        $.inputIndex = reader.array(position, 10, Uint32Array);\n        $.outputIndex = reader.array(position, 12, Uint32Array);\n        $.quantType = reader.int32_(position, 14, 0);\n        $.deviceType = reader.int32_(position, 16, -1);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.CNode();\n        $.name = reader.value(json.name, null);\n        $.nodeType = reader.value(json.nodeType, 0);\n        $.primitive = reader.object(json.primitive, mindspore.schema.Primitive);\n        $.inputIndex = reader.array(json.inputIndex, Uint32Array);\n        $.outputIndex = reader.array(json.outputIndex, Uint32Array);\n        $.quantType = mindspore.schema.QuantType[json.quantType];\n        $.deviceType = reader.value(json.deviceType, -1);\n        return $;\n    }\n};\n\nmindspore.schema.SubGraph = class SubGraph {\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.SubGraph();\n        $.name = reader.string_(position, 4, null);\n        $.inputIndices = reader.array(position, 6, Uint32Array);\n        $.outputIndices = reader.array(position, 8, Uint32Array);\n        $.nodeIndices = reader.array(position, 10, Uint32Array);\n        $.tensorIndices = reader.array(position, 12, Uint32Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.SubGraph();\n        $.name = reader.value(json.name, null);\n        $.inputIndices = reader.array(json.inputIndices, Uint32Array);\n        $.outputIndices = reader.array(json.outputIndices, Uint32Array);\n        $.nodeIndices = reader.array(json.nodeIndices, Uint32Array);\n        $.tensorIndices = reader.array(json.tensorIndices, Uint32Array);\n        return $;\n    }\n};\n\nmindspore.schema.MetaGraph = class MetaGraph {\n\n    static identifier(reader) {\n        return reader.identifier === 'MSL2';\n    }\n\n    static create(reader) {\n        return mindspore.schema.MetaGraph.decode(reader, reader.root);\n    }\n\n    static createText(reader) {\n        return mindspore.schema.MetaGraph.decodeText(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new mindspore.schema.MetaGraph();\n        $.name = reader.string_(position, 4, null);\n        $.version = reader.string_(position, 6, null);\n        $.fmkType = reader.int32_(position, 8, 0);\n        $.inputIndex = reader.array(position, 10, Uint32Array);\n        $.outputIndex = reader.array(position, 12, Uint32Array);\n        $.mempoolSize = reader.uint32_(position, 14, 0);\n        $.nodes = reader.tables(position, 16, mindspore.schema.CNode);\n        $.allTensors = reader.tables(position, 18, mindspore.schema.Tensor);\n        $.subGraph = reader.tables(position, 20, mindspore.schema.SubGraph);\n        $.obfuscate = reader.bool_(position, 22, false);\n        $.obfMetaData = reader.array(position, 24, Uint8Array);\n        return $;\n    }\n\n    static decodeText(reader, json) {\n        const $ = new mindspore.schema.MetaGraph();\n        $.name = reader.value(json.name, null);\n        $.version = reader.value(json.version, null);\n        $.fmkType = reader.value(json.fmkType, 0);\n        $.inputIndex = reader.array(json.inputIndex, Uint32Array);\n        $.outputIndex = reader.array(json.outputIndex, Uint32Array);\n        $.mempoolSize = reader.value(json.mempoolSize, 0);\n        $.nodes = reader.objects(json.nodes, mindspore.schema.CNode);\n        $.allTensors = reader.objects(json.allTensors, mindspore.schema.Tensor);\n        $.subGraph = reader.objects(json.subGraph, mindspore.schema.SubGraph);\n        $.obfuscate = reader.value(json.obfuscate, false);\n        $.obfMetaData = reader.array(json.obfMetaData, Uint8Array);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/mslite.js",
    "content": "\nconst mslite = {};\n\nmslite.ModelFactory = class {\n\n    async match(context) {\n        const extension = context.identifier.split('.').pop().toLowerCase();\n        const reader = await context.peek('flatbuffers.binary');\n        if (reader) {\n            const identifier = reader.identifier;\n            if (identifier === 'MSL1' || identifier === 'MSL2' || (identifier === '' && extension === 'ms')) {\n                return context.set('mslite', reader);\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        const reader = context.value;\n        switch (reader.identifier) {\n            case '': {\n                throw new mslite.Error('MSL0 format is deprecated.');\n            }\n            case 'MSL1': {\n                throw new mslite.Error('MSL1 format is deprecated.');\n            }\n            case 'MSL2':\n                break;\n            default:\n                throw new mslite.Error(`Unsupported file identifier '${reader.identifier}'.`);\n        }\n        mslite.schema = await context.require('./mslite-schema');\n        mslite.schema = mslite.schema.mindspore.schema;\n        let model = null;\n        try {\n            model = mslite.schema.MetaGraph.create(reader);\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new mslite.Error(`File format is not mslite.MetaGraph (${message.replace(/\\.$/, '')}).`);\n        }\n        const metadata = await context.metadata('mslite-metadata.json');\n        return new mslite.Model(metadata, model);\n    }\n};\n\nmslite.Model = class {\n\n    constructor(metadata, model) {\n        this.name = model.name || '';\n        this.modules = [];\n        const version = model.version ? model.version.match(/^.*(\\d\\.\\d\\.\\d)$/) : null;\n        this.format = `MindSpore Lite${version ? ` v${version[1]}` : ''}`;\n        const subgraphs = model.subGraph;\n        if (Array.isArray(subgraphs)) {\n            for (const subgraph of subgraphs) {\n                this.modules.push(new mslite.Graph(metadata, subgraph, model));\n            }\n        } else {\n            const graph = new mslite.Graph(metadata, model, model);\n            this.modules.push(graph);\n        }\n    }\n};\n\nmslite.Graph = class {\n\n    constructor(metadata, subgraph, model) {\n        this.name = subgraph.name || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const values = model.allTensors.map((tensor, index) => {\n            const name = tensor.name || index.toString();\n            const data = tensor.data;\n            const type = new mslite.TensorType(tensor.dataType, tensor.dims);\n            const initializer = (data && data.length > 0) ? new mslite.Tensor(type, tensor.data) : null;\n            return new mslite.Value(name, tensor, initializer);\n        });\n        if (subgraph === model) {\n            for (let i = 0; i < subgraph.inputIndex.length; i++) {\n                const index = subgraph.inputIndex[i];\n                this.inputs.push(new mslite.Argument(i.toString(), [values[index]]));\n            }\n            for (let i = 0; i < subgraph.outputIndex.length; i++) {\n                const index = subgraph.outputIndex[i];\n                this.outputs.push(new mslite.Argument(i.toString(), [values[index]]));\n            }\n            for (let i = 0; i < subgraph.nodes.length; i++) {\n                this.nodes.push(new mslite.Node(metadata, subgraph.nodes[i], values));\n            }\n        } else {\n            for (let i = 0; i < subgraph.inputIndices.length; i++) {\n                const index = subgraph.inputIndices[i];\n                this.inputs.push(new mslite.Argument(i.toString(), [values[index]]));\n            }\n            for (let i = 0; i < subgraph.outputIndices.length; i++) {\n                const index = subgraph.outputIndices[i];\n                this.outputs.push(new mslite.Argument(i.toString(), [values[index]]));\n            }\n            for (const name of subgraph.nodeIndices) {\n                const node = new mslite.Node(metadata, model.nodes[name], values);\n                this.nodes.push(node);\n            }\n        }\n    }\n};\n\nmslite.Node = class {\n\n    constructor(metadata, op, values) {\n        this.name = op.name || '';\n        this.type = { name: '?' };\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const data = op.primitive.value;\n        if (data && data.constructor) {\n            const type = data.constructor.name;\n            this.type = metadata.type(type);\n            this.attributes = Object.entries(data).map(([key, obj]) => {\n                let value = ArrayBuffer.isView(obj) ? Array.from(obj) : obj;\n                let type = null;\n                const schema = metadata.attribute(this.type.name, key);\n                if (schema && schema.type) {\n                    type = schema.type;\n                    const enumType = mslite.schema[type];\n                    if (enumType) {\n                        value = enumType[value] || value;\n                    }\n                }\n                return new mslite.Argument(key.toString(), value, type);\n            });\n        }\n        const input_num = op.inputIndex.length;\n        let i = 0;\n        if (this.type && this.type.inputs) {\n            for (const input of this.type.inputs) {\n                if (i >= input_num) {\n                    break;\n                }\n                const index = op.inputIndex[i];\n                const argument = new mslite.Argument(input.name, [values[index]]);\n                this.inputs.push(argument);\n                i += 1;\n            }\n        }\n        for (let j = i; j < input_num; j++) {\n            const index = op.inputIndex[j];\n            const argument = new mslite.Argument(j.toString(), [values[index]]);\n            this.inputs.push(argument);\n        }\n        const output_num = op.outputIndex.length;\n        i = 0;\n        if (this.type && this.type.outputs) {\n            for (const output of this.type.outputs) {\n                if (i >= output_num) {\n                    break;\n                }\n                const index = op.outputIndex[i];\n                const argument = new mslite.Argument(output.name, [values[index]]);\n                this.outputs.push(argument);\n                i += 1;\n            }\n        }\n        for (let j = i; j < output_num; j++) {\n            const index = op.outputIndex[j];\n            const argument = new mslite.Argument(j.toString(), [values[index]]);\n            this.outputs.push(argument);\n        }\n    }\n};\n\nmslite.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nmslite.Value = class {\n\n    constructor(name, tensor, initializer = null) {\n        this.name = name;\n        this.type = initializer ? initializer.type : new mslite.TensorType(tensor.dataType, tensor.dims);\n        this.initializer = initializer;\n        if (Array.isArray(tensor.quantParams) && tensor.quantParams.length > 0) {\n            this.quantization = {\n                type: 'linear',\n                scale: [],\n                offset: []\n            };\n            for (let i = 0; i < tensor.quantParams.length; i++) {\n                const param = tensor.quantParams[i];\n                this.quantization.scale.push(param.scale);\n                this.quantization.offset.push(param.zeroPoint);\n            }\n        }\n    }\n};\n\nmslite.Tensor = class {\n\n    constructor(type, data = null) {\n        this.type = type;\n        this.encoding = type.dataType === 'string' ? '|' : '<';\n        this._data = data;\n    }\n\n    get values() {\n        switch (this.type.dataType) {\n            case 'string': {\n                let offset = 0;\n                const data = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);\n                const count = data.getInt32(0, true);\n                offset += 4;\n                const offsetTable = [];\n                for (let j = 0; j < count; j++) {\n                    offsetTable.push(data.getInt32(offset, true));\n                    offset += 4;\n                }\n                offsetTable.push(this._data.length);\n                const stringTable = [];\n                const utf8Decoder = new TextDecoder('utf-8');\n                for (let k = 0; k < count; k++) {\n                    const textArray = this._data.subarray(offsetTable[k], offsetTable[k + 1]);\n                    stringTable.push(utf8Decoder.decode(textArray));\n                }\n                return stringTable;\n            }\n            default: return this._data;\n        }\n    }\n};\n\nmslite.TensorType = class {\n\n    constructor(dataType, dimensions) {\n        switch (dataType) {\n            case 0:  this.dataType = \"?\"; break;\n            case 1:  this.dataType = \"type\"; break;\n            case 2:  this.dataType = \"any\"; break;\n            case 3:  this.dataType = \"object\"; break;\n            case 4:  this.dataType = \"typetype\"; break;\n            case 5:  this.dataType = \"problem\"; break;\n            case 6:  this.dataType = \"external\"; break;\n            case 7:  this.dataType = \"none\"; break;\n            case 8:  this.dataType = \"null\"; break;\n            case 9:  this.dataType = \"ellipsis\"; break;\n            case 11: this.dataType = \"number\"; break;\n            case 12: this.dataType = \"string\"; break;\n            case 13: this.dataType = \"list\"; break;\n            case 14: this.dataType = \"tuple\"; break;\n            case 15: this.dataType = \"slice\"; break;\n            case 16: this.dataType = \"keyword\"; break;\n            case 17: this.dataType = \"tensortype\"; break;\n            case 18: this.dataType = \"rowtensortype\"; break;\n            case 19: this.dataType = \"sparsetensortype\"; break;\n            case 20: this.dataType = \"undeterminedtype\"; break;\n            case 21: this.dataType = \"class\"; break;\n            case 22: this.dataType = \"dictionary\"; break;\n            case 23: this.dataType = \"function\"; break;\n            case 24: this.dataType = \"jtagged\"; break;\n            case 25: this.dataType = \"symbolickeytype\"; break;\n            case 26: this.dataType = \"envtype\"; break;\n            case 27: this.dataType = \"refkey\"; break;\n            case 28: this.dataType = \"ref\"; break;\n            case 30: this.dataType = \"boolean\"; break;\n            // case 31: this.dataType = \"int\"; break;\n            case 32: this.dataType = \"int8\"; break;\n            case 33: this.dataType = \"int16\"; break;\n            case 34: this.dataType = \"int32\"; break;\n            case 35: this.dataType = \"int64\"; break;\n            // case 36: this.dataType = \"uint\"; break;\n            case 37: this.dataType = \"uint8\"; break;\n            case 38: this.dataType = \"uint16\"; break;\n            case 39: this.dataType = \"uint32\"; break;\n            case 40: this.dataType = \"uint64\"; break;\n            // case 41: this.dataType = \"float\"; break;\n            case 42: this.dataType = \"float16\"; break;\n            case 43: this.dataType = \"float32\"; break;\n            case 44: this.dataType = \"float64\"; break;\n            case 45: this.dataType = \"bfloat16\"; break;\n            // case 46: this.dataType = \"double\"; break;\n            // case 47: this.dataType = \"complex\"; break;\n            case 48: this.dataType = \"complex64\"; break;\n            case 49: this.dataType = \"complex128\"; break;\n            case 50: this.dataType = \"int4\"; break;\n            default: throw new mslite.Error(`Unsupported data type '${dataType}'.`);\n        }\n        this.shape = new mslite.TensorShape(Array.from(dimensions));\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmslite.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`;\n        }\n        return '';\n    }\n};\n\nmslite.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading MindSpore Lite model.';\n    }\n};\n\nexport const ModelFactory = mslite.ModelFactory;\n"
  },
  {
    "path": "source/mxnet-metadata.json",
    "content": "[\n  {\n    \"name\": \"_copy\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_linalg_gemm2\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_minus_scalar\",\n    \"attributes\": [\n      { \"name\": \"scalar\", \"type\": \"float32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_mul\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"_mul_scalar\",\n    \"attributes\": [\n      { \"name\": \"scalar\", \"type\": \"float32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_Plus\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_plus_scalar\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_rminus_scalar\",\n    \"attributes\": [\n      { \"name\": \"scalar\", \"type\": \"float32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"_sub\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"_zeros\",\n    \"category\": \"Constant\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Activation\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"type\": \"int32\", \"default\": 1, \"name\": \"axis\" },\n      { \"type\": \"float64\", \"default\": 0.001, \"name\": \"eps\" },\n      { \"type\": \"float32\", \"default\": 0.9, \"name\": \"momentum\" },\n      { \"type\": \"boolean\", \"default\": true, \"name\": \"fix_gamma\" },\n      { \"type\": \"boolean\", \"default\": false, \"name\": \"use_global_stats\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"broadcast_add\",\n    \"inputs\": [\n      { \"name\": \"lhs\" },\n      { \"name\": \"rhs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out\" }\n    ]\n  },\n  {\n    \"name\": \"broadcast_div\",\n    \"inputs\": [\n      { \"name\": \"lhs\" },\n      { \"name\": \"rhs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out\" }\n    ]\n  },\n  {\n    \"name\": \"broadcast_mul\",\n    \"inputs\": [\n      { \"name\": \"lhs\" },\n      { \"name\": \"rhs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"default\": \"1\", \"name\": \"dim\" },\n      { \"visible\": false, \"name\": \"num_args\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"default\": false, \"name\": \"cudnn_off\", \"type\": \"boolean\" },\n      { \"default\": \"off\", \"name\": \"cudnn_tune\" },\n      { \"default\": [   1,   null ], \"name\": \"dilate\", \"type\": \"int32[]\" },\n      { \"name\": \"kernel\", \"type\": \"int32[]\" },\n      { \"visible\": false, \"name\": \"no_bias\", \"type\": \"boolean\" },\n      { \"type\": \"int32\", \"default\": 1, \"name\": \"num_group\" },\n      { \"type\": \"int32\", \"name\": \"num_filter\" },\n      { \"default\": [   0,   null ], \"name\": \"pad\", \"type\": \"int32[]\" },\n      { \"default\": [   1,   null ], \"name\": \"stride\", \"type\": \"int32[]\" },\n      { \"type\": \"int32\", \"default\": \"1024\", \"name\": \"workspace\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\", \"optional\": true }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"CuDNNBatchNorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"visible\": false, \"name\": \"no_bias\" },\n      { \"default\": \"1\", \"name\": \"num_group\" },\n      { \"type\": \"int32\", \"default\": \"1024\", \"name\": \"workspace\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"type\": \"float32\", \"default\": 0.5, \"name\": \"p\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ElementWiseSum\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"elemwise_add\",\n    \"inputs\": [\n      { \"name\": \"lhs\" },\n      { \"name\": \"rhs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out\" }\n    ]\n  },\n  {\n    \"name\": \"elemwise_div\",\n    \"inputs\": [\n      { \"name\": \"lhs\" },\n      { \"name\": \"rhs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out\" }\n    ]\n  },\n  {\n    \"name\": \"elemwise_sub\",\n    \"inputs\": [\n      { \"name\": \"lhs\" },\n      { \"name\": \"rhs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out\" }\n    ]\n  },\n  {\n    \"name\": \"Embedding\",\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"type\": \"int32\", \"name\": \"input_dim\" },\n      { \"type\": \"int32\", \"name\": \"output_dim\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Flatten\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"FullyConnected\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"type\": \"boolean\", \"default\": true, \"name\": \"flatten\" },\n      { \"type\": \"boolean\", \"visible\": false, \"name\": \"no_bias\" },\n      { \"type\": \"int32\", \"name\": \"num_hidden\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"type\": \"int32\", \"default\": 1, \"name\": \"axis\" },\n      { \"type\": \"float64\", \"default\": 0.001, \"name\": \"eps\" },\n      { \"type\": \"float32\", \"default\": 0.9, \"name\": \"momentum\" },\n      { \"type\": \"boolean\", \"default\": true, \"name\": \"fix_gamma\" },\n      { \"type\": \"boolean\", \"default\": false, \"name\": \"use_global_stats\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LeakyReLU\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"log\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.75 },\n      { \"name\": \"knorm\", \"type\": \"float32\", \"default\": 2 },\n      { \"name\": \"nsize\", \"type\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"MakeLoss\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"mean\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Pad\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"default\": false, \"name\": \"cudnn_off\" },\n      { \"default\": false, \"name\": \"global_pool\" },\n      { \"name\": \"kernel\", \"type\": \"int32[]\" },\n      { \"default\": [   0,   null ], \"name\": \"pad\", \"type\": \"int32[]\" },\n      { \"default\": \"valid\", \"name\": \"pooling_convention\" },\n      { \"default\": \"max\", \"name\": \"pool_type\" },\n      { \"default\": [   1,   null ], \"name\": \"stride\", \"type\": \"int32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"relu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"RNN\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"type\": \"boolean\", \"name\": \"bidirectional\", \"default\": false },\n      { \"name\": \"lstm_parameters\", \"visible\": false },\n      { \"type\": \"int32\", \"name\": \"num_layers\" },\n      { \"type\": \"boolean\", \"default\": false, \"name\": \"state_outputs\" },\n      { \"type\": \"int32\", \"name\": \"state_size\" },\n      { \"type\": \"float32\", \"name\": \"p\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"state_0\" },\n      { \"name\": \"state_1\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"slice_axis\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SliceChannel\",\n    \"inputs\": [\n      { \"name\": \"inputs\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"outputs\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"softmax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxActivation\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxOutput\",\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"default\": \"1\", \"name\": \"grad_scale\" },\n      { \"default\": \"-1\", \"name\": \"ignore_label\" },\n      { \"default\": false, \"name\": \"multi_output\" },\n      { \"default\": \"null\", \"name\": \"normalization\" },\n      { \"default\": false, \"name\": \"out_grad\" },\n      { \"default\": \"0\", \"name\": \"smooth_alpha\" },\n      { \"default\": false, \"name\": \"use_ignore\" },\n      { \"default\": false, \"name\": \"preserve_shape\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"label\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"sqrt\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"square\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"sum\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"transpose\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/mxnet.js",
    "content": "\nimport * as json from './json.js';\n\nconst mxnet = {};\n\nmxnet.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        if (extension === 'json') {\n            const obj = await context.peek('json');\n            if (obj && Array.isArray(obj.nodes) && Array.isArray(obj.arg_nodes) && Array.isArray(obj.heads) && !obj.nodes.some((node) => node && node.op === 'tvm_op')) {\n                return context.set('mxnet.json', obj);\n            }\n        }\n        const stream = context.stream;\n        const signature = [0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];\n        if (stream && stream.length > signature.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {\n            return context.set('mxnet.params');\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        return context.type !== 'mxnet.json' || match.type !== 'mxnet.params';\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('mxnet-metadata.json');\n        const basename = (base, identifier, extension, suffix, append) => {\n            if (!base) {\n                if (identifier.toLowerCase().endsWith(extension)) {\n                    const items = identifier.substring(0, identifier.length - extension.length).split('-');\n                    if (items.length >= 2) {\n                        const token = items.pop();\n                        if ((suffix && token === suffix) || /[a-zA-Z0-9]*/.exec(token)) {\n                            return items.join('-') + append;\n                        }\n                    }\n                }\n            }\n            return base;\n        };\n        const convertVersion = (value) => {\n            if (Array.isArray(value)) {\n                if (value.length === 2 && value[0] === 'int') {\n                    const major = Math.floor(value[1] / 10000) % 100;\n                    const minor = Math.floor(value[1] / 100) % 100;\n                    const patch = Math.floor(value[1]) % 100;\n                    return [major.toString(), minor.toString(), patch.toString()].join('.');\n                }\n            }\n            return null;\n        };\n        const requestManifest = async () => {\n            const parse = async (stream) => {\n                try {\n                    const manifest = {};\n                    if (stream) {\n                        const reader = json.TextReader.open(stream);\n                        const obj = reader.read();\n                        if (obj.Model) {\n                            const modelFormat = obj.Model['Model-Format'];\n                            if (modelFormat && modelFormat !== 'MXNet-Symbolic') {\n                                throw new mxnet.Error(`Model format '${modelFormat}' not supported.`);\n                            }\n                            manifest.format = 'MXNet Model Server';\n                            if (obj['Model-Archive-Version']) {\n                                manifest.format += ` v${obj['Model-Archive-Version']}`;\n                            }\n                            if (!obj.Model.Symbol) {\n                                throw new mxnet.Error('Manifest does not contain symbol entry.');\n                            }\n                            manifest.symbol = obj.Model.Symbol;\n                            if (obj.Model.Signature) {\n                                manifest.signature = obj.Model.Signature;\n                            }\n                            if (obj.Model.Parameters) {\n                                manifest.params = obj.Model.Parameters;\n                            }\n                            if (obj.Model['Model-Name']) {\n                                manifest.name = obj.Model['Model-Name'];\n                            }\n                            if (obj.Model.Description && manifest.name !== obj.Model.Description) {\n                                manifest.description = obj.Model.Description;\n                            }\n                        } else if (obj.model) {\n                            manifest.format = 'MXNet Model Archive';\n                            if (obj.specificationVersion) {\n                                manifest.format += ` v${obj.specificationVersion}`;\n                            }\n                            if (obj.model.modelName) {\n                                manifest.symbol = `${obj.model.modelName}-symbol.json`;\n                            }\n                            if (obj.model.modelName) {\n                                manifest.name = obj.model.modelName;\n                            }\n                            if (manifest.model && obj.model.modelVersion) {\n                                manifest.version = obj.model.modelVersion;\n                            }\n                            if (manifest.model && manifest.model.modelName && manifest.name !== obj.model.description) {\n                                manifest.description = obj.model.description;\n                            }\n                        } else {\n                            throw new mxnet.Error('Manifest does not contain model.');\n                        }\n                        if (obj.Engine && obj.Engine.MXNet) {\n                            const version = convertVersion(obj.Engine.MXNet);\n                            manifest.runtime = `MXNet v${version ? version : obj.Engine.MXNet}`;\n                        }\n                        if (obj.License) {\n                            manifest.license = obj.License;\n                        }\n                        if (obj.runtime) {\n                            manifest.runtime = obj.runtime;\n                        }\n                        if (obj.engine && obj.engine.engineName) {\n                            const engine = obj.engine.engineVersion ? `${obj.engine.engineName} ${obj.engine.engineVersion}` : obj.engine.engineName;\n                            manifest.runtime = manifest.runtime ? (`${manifest.runtime} (${engine})`) : engine;\n                        }\n                        if (obj.publisher && obj.publisher.author) {\n                            manifest.author = obj.publisher.author;\n                            if (obj.publisher.email) {\n                                manifest.author = `${manifest.author} <${obj.publisher.email}>`;\n                            }\n                        }\n                        if (obj.license) {\n                            manifest.license = obj.license;\n                        }\n                        if (obj.Model && obj.Model.Signature) {\n                            try {\n                                const content = await context.fetch(obj.Model.Signature);\n                                manifest.signature = await content.read('json');\n                                return manifest;\n                            } catch {\n                                return manifest;\n                            }\n                        }\n                    }\n                    return manifest;\n                } catch (error) {\n                    throw new mxnet.Error(`Failed to read manifest. ${error.message}`);\n                }\n            };\n            try {\n                const content = await context.fetch('MANIFEST.json');\n                return parse(content.stream);\n            } catch {\n                try {\n                    const content = await context.fetch('MAR-INF/MANIFEST.json');\n                    return parse(content.stream);\n                } catch {\n                    return parse(null);\n                }\n            }\n        };\n        const createModel = (metadata, manifest, symbol, params) => {\n            const parameters = new Map();\n            if (params) {\n                try {\n                    for (const [key, array] of mxnet.ndarray.load(params)) {\n                        const name = (key.startsWith('arg:') || key.startsWith('aux:')) ? key.substring(4) : key;\n                        parameters.set(name, array);\n                    }\n                } catch {\n                    // continue regardless of error\n                }\n            }\n            if (symbol) {\n                if (!manifest.format) {\n                    const version = convertVersion(symbol.attrs && symbol.attrs.mxnet_version ? symbol.attrs.mxnet_version : null);\n                    manifest.format = `MXNet${version ? ` v${version}` : ''}`;\n                }\n                if (symbol.nodes && symbol.nodes.some((node) => node && node.op === 'tvm_op')) {\n                    manifest.format  = 'TVM';\n                }\n            }\n            return new mxnet.Model(metadata, manifest, symbol, parameters);\n        };\n        const identifier = context.identifier;\n        switch (context.type) {\n            case 'mxnet.json': {\n                let symbol = null;\n                try {\n                    symbol = context.value;\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new mxnet.Error(`Failed to load symbol entry (${message.replace(/\\.$/, '')}).`);\n                }\n                const requestParams = async (manifest) => {\n                    const file = basename(manifest.params, identifier, '.json', 'symbol', '-0000.params');\n                    if (file) {\n                        try {\n                            const content = await context.fetch(file);\n                            const reader = await content.read('binary');\n                            return createModel(metadata, manifest, symbol, reader);\n                        } catch {\n                            return createModel(metadata, manifest, symbol, null);\n                        }\n                    }\n                    return createModel(metadata, manifest, symbol, null);\n                };\n                const manifest = await requestManifest();\n                return requestParams(manifest);\n            }\n            case 'mxnet.params': {\n                const params = await context.read('binary');\n                const requestSymbol = async (manifest) => {\n                    const name = basename(manifest.symbol, identifier, '.params', null, '-symbol.json');\n                    if (name) {\n                        try {\n                            const content = await context.fetch(name);\n                            const symbol = await content.read('json');\n                            return createModel(metadata, manifest, symbol, params);\n                        } catch {\n                            return createModel(metadata, manifest, null, params);\n                        }\n                    }\n                    return createModel(metadata, manifest, null, params);\n                };\n                const manifest = await requestManifest();\n                return requestSymbol(manifest);\n            }\n            default: {\n                throw new mxnet.Error(`Unsupported MXNet format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nmxnet.Model = class {\n\n    constructor(metadata, manifest, symbol, params) {\n        if (!symbol && !params) {\n            throw new mxnet.Error('JSON symbol data not available.');\n        }\n        if (symbol) {\n            if (!Object.prototype.hasOwnProperty.call(symbol, 'nodes')) {\n                throw new mxnet.Error('JSON file does not contain an MXNet \\'nodes\\' property.');\n            }\n            if (!Object.prototype.hasOwnProperty.call(symbol, 'arg_nodes')) {\n                throw new mxnet.Error('JSON file does not contain an MXNet \\'arg_nodes\\' property.');\n            }\n            if (!Object.prototype.hasOwnProperty.call(symbol, 'heads')) {\n                throw new mxnet.Error('JSON file does not contain an MXNet \\'heads\\' property.');\n            }\n        }\n        this.format = manifest.format || 'MXNet';\n        this.producer = manifest.producer || '';\n        this.name = manifest.name || '';\n        this.version = manifest.version;\n        this.description = manifest.description || '';\n        this.runtime = manifest.runtime || '';\n        this.metadata = [];\n        if (manifest.author) {\n            this.metadata.push(new mxnet.Argument('author', manifest.author));\n        }\n        if (manifest.license) {\n            this.metadata.push(new mxnet.Argument('license', manifest.license));\n        }\n        this.modules = [new mxnet.Graph(metadata, manifest, symbol, params)];\n    }\n};\n\nmxnet.Graph = class {\n\n    constructor(metadata, manifest, symbol, params) {\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const tensors = new Map();\n        if (params) {\n            for (const [name, value] of params) {\n                const shape = new mxnet.TensorShape(value.shape);\n                const type = new mxnet.TensorType(value.dtype, shape);\n                const tensor = new mxnet.Tensor(name, type, value.data);\n                tensors.set(name, tensor);\n            }\n        }\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (!values.has(name)) {\n                values.set(name, new mxnet.Value(name, type || null, tensor || null));\n            } else if (type || (tensor && tensor !== values.get(name).initializer)) {\n                throw new mxnet.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const updateOutput = (nodes, input) => {\n            const [nodeIndex, outputIndex] = input;\n            const node = nodes[nodeIndex];\n            if (node) {\n                while (outputIndex >= node.outputs.length) {\n                    node.outputs.push([nodeIndex, node.outputs.length]);\n                }\n            }\n            return [nodeIndex, outputIndex];\n        };\n        if (symbol) {\n            const nodes = symbol.nodes;\n            const inputs = {};\n            const outputs = {};\n            if (manifest && manifest.signature && manifest.signature.inputs) {\n                for (const input of manifest.signature.inputs) {\n                    inputs[input.data_name] = input;\n                }\n            }\n            if (manifest && manifest.signature && manifest.signature.outputs) {\n                for (const output of manifest.signature.outputs) {\n                    outputs[output.data_name] = output;\n                }\n            }\n            for (const node of nodes) {\n                node.outputs = [];\n            }\n            for (const node of nodes) {\n                node.inputs = node.inputs || [];\n                node.inputs = node.inputs.map((input) => updateOutput(nodes, input));\n            }\n            const arg_nodes = new Map(symbol.arg_nodes.map((index) => [index, index < nodes.length ? nodes[index] : null]));\n            for (let i = 0; i < symbol.heads.length; i++) {\n                const head = symbol.heads[i];\n                const identifier = updateOutput(nodes, head);\n                const name = `output${(i === 0) ? '' : (i + 1)}`;\n                const signature = outputs[name];\n                const type = signature && signature.data_shape ? new mxnet.TensorType(-1, new mxnet.TensorShape(signature.data_shape)) : null;\n                const value = values.map(`[${identifier.join(',')}]`, type);\n                const argument = new mxnet.Argument(name, [value]);\n                this.outputs.push(argument);\n            }\n            const filtered = nodes.filter((node, index) => !arg_nodes.has(index));\n            const initializers = new Map();\n            for (const node of filtered) {\n                if (node.op === 'RNN') {\n                    node.inputs = node.inputs.filter((input) => {\n                        const [index] = input;\n                        const arg_node = arg_nodes.get(index);\n                        if (arg_node && arg_node.op === 'null' && arg_node.name && arg_node.name.endsWith('_parameters') && arg_node.attr && arg_node.attr.__init__) {\n                            let attr = node.attrs || node.attr || node.param;\n                            if (!attr) {\n                                node.attr = {};\n                                attr = node.attr;\n                            }\n                            attr[arg_node.name] = arg_node.attr.__init__;\n                            arg_nodes.delete(index);\n                            return false;\n                        }\n                        return true;\n                    });\n                }\n                for (const input of node.inputs) {\n                    const identifier = `[${input.join(',')}]`;\n                    if (!initializers.has(identifier)) {\n                        const [index] = input;\n                        const arg_node = arg_nodes.get(index);\n                        if (arg_node && arg_node.name && (!arg_node.inputs || arg_node.inputs.length === 0) && (arg_node.outputs && arg_node.outputs.length === 1)) {\n                            if (tensors.has(arg_node.name)) {\n                                initializers.set(identifier, tensors.get(arg_node.name));\n                                arg_nodes.delete(index);\n                            } else {\n                                const prefix = node.name.endsWith('_fwd') ? node.name.slice(0, -3) : node.name;\n                                if (arg_node.name && (arg_node.name.startsWith(`${prefix}_`) || arg_node.name.startsWith(`${prefix}.`))) {\n                                    let dataType = -1;\n                                    let shape = [];\n                                    if (arg_node.attrs && arg_node.attrs.__dtype__ && arg_node.attrs.__shape__) {\n                                        try {\n                                            dataType = parseInt(arg_node.attrs.__dtype__, 10);\n                                            shape = JSON.parse(`[${arg_node.attrs.__shape__.replace(/[()]/g, '').split(' ').join('').split(',').map(((v) => v || '\"?\"')).join(',')}]`);\n                                        } catch {\n                                            // continue regardless of error\n                                        }\n                                    }\n                                    const type = (dataType !== -1 || shape.length > 0) ?\n                                        new mxnet.TensorType(dataType, new mxnet.TensorShape(shape)) :\n                                        new mxnet.TensorType(-1, new mxnet.TensorShape(null));\n                                    initializers.set(identifier, new mxnet.Tensor(arg_node.name, type, null));\n                                    arg_nodes.delete(index);\n                                }\n                            }\n                        }\n                    }\n                }\n                if (node.params) {\n                    for (const param of node.params) {\n                        values.map(param.id, null, tensors.get(param.id));\n                    }\n                }\n            }\n            for (const [, arg_node] of arg_nodes) {\n                if (arg_node && (!arg_node.inputs || arg_node.inputs.length === 0) && (arg_node.outputs && arg_node.outputs.length === 1)) {\n                    const identifier = `[${arg_node.outputs[0].join(',')}]`;\n                    const name = arg_node.name;\n                    const signature = inputs[name];\n                    const type = signature && signature.data_shape ? new mxnet.TensorType(-1, new mxnet.TensorShape(signature.data_shape)) : null;\n                    const value = values.map(identifier, type, tensors.get(identifier));\n                    const argument = new mxnet.Argument(name, [value]);\n                    this.inputs.push(argument);\n                }\n            }\n            for (const node of filtered) {\n                this.nodes.push(new mxnet.Node(metadata, node, initializers, values));\n            }\n        } else if (params) {\n            const blocks = new Map();\n            let separator = Array.from(params.keys()).every((key) => key.indexOf('_') !== -1) ? '_' : '';\n            if (separator.length === 0) {\n                separator = Array.from(params.keys()).every((key) => key.indexOf('.') !== -1) ? '.' : '';\n            }\n            if (separator.length > 0) {\n                for (const [key] of params) {\n                    const parts = key.split(separator);\n                    let argumentName = parts.pop();\n                    if (key.endsWith('moving_mean') || key.endsWith('moving_var')) {\n                        argumentName = [parts.pop(), argumentName].join(separator);\n                    }\n                    const nodeName = parts.join(separator);\n                    if (!blocks.has(nodeName)) {\n                        blocks.set(nodeName, { name: nodeName, op: 'Weights', params: [] });\n                    }\n                    blocks.get(nodeName).params.push({ name: argumentName, id: key });\n                    values.map(key, null, tensors.get(key));\n                }\n            } else {\n                throw new mxnet.Error(\"Unsupported key format in params.\");\n            }\n\n            for (const block of blocks.values()) {\n                this.nodes.push(new mxnet.Node(metadata, block, new Map(), values));\n            }\n        }\n    }\n};\n\nmxnet.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nmxnet.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new mxnet.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = !name && initializer && initializer.name ? initializer.name : name;\n        this.type = !type && initializer && initializer.type ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nmxnet.Node = class {\n\n    constructor(metadata, node, initializers, values) {\n        let type = node.op;\n        this.name = node.name;\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const attrs = node.attrs || node.attr || node.param;\n        if (attrs) {\n            if (type === 'tvm_op' && attrs.func_name) {\n                type = attrs.func_name;\n            }\n            for (const [name, obj] of Object.entries(attrs)) {\n                if (type !== 'tvm_op' && name !== 'func_name') {\n                    let value = obj;\n                    let visible = true;\n                    const schema = metadata.attribute(type, name);\n                    if (schema && schema.type) {\n                        switch (schema.type) {\n                            case 'boolean':\n                                switch (value) {\n                                    case 0:\n                                    case '0':\n                                    case 'False':\n                                        value = false;\n                                        break;\n                                    case 1:\n                                    case '1':\n                                    case 'True':\n                                        value = true;\n                                        break;\n                                    default:\n                                        throw new mxnet.Error(`Unsupported attribute boolean value '${value}'.`);\n                                }\n                                break;\n                            case 'int32': {\n                                const number = Number.parseInt(value, 10);\n                                value = Number.isNaN(value - number) ? value : number;\n                                break;\n                            }\n                            case 'float32':\n                            case 'float64': {\n                                const number = Number.parseFloat(value);\n                                value = Number.isNaN(value - number) ? value : number;\n                                break;\n                            }\n                            case 'int32[]':\n                                if (value.length > 2 && value.startsWith('(') && value.endsWith(')')) {\n                                    let array = [];\n                                    const items = value.substring(1, value.length - 1).split(',')\n                                        .map((item) => item.trim())\n                                        .map((item) => item.endsWith('L') ? item.substring(0, item.length - 1) : item);\n                                    for (const item of items) {\n                                        const value = Number.parseInt(item, 10);\n                                        if (Number.isNaN(item - value)) {\n                                            array = null;\n                                        } else if (array !== null) {\n                                            array.push(value);\n                                        }\n                                    }\n                                    if (array !== null) {\n                                        value = array;\n                                    }\n                                }\n                                break;\n                            default:\n                                throw new mxnet.Error(`Unsupported attribute type '${metadata.type}'.`);\n                        }\n                    }\n                    if (metadata) {\n                        if (metadata.visible === false) {\n                            visible = false;\n                        } else if (metadata.default !== undefined) {\n                            const defaultValue = metadata.default;\n                            if (value === defaultValue) {\n                                visible = false;\n                            } else if (Array.isArray(value) && Array.isArray(defaultValue)) {\n                                const repeat = defaultValue.length > 1 && defaultValue[defaultValue.length - 1] === null;\n                                if (value.every((item, index) => item === (repeat && index >= defaultValue.length - 1 ? defaultValue[defaultValue.length - 2] : defaultValue[index]))) {\n                                    visible = false;\n                                }\n                            }\n                        }\n                    }\n                    const attribute = new mxnet.Argument(name, value, type, visible);\n                    this.attributes.push(attribute);\n                }\n            }\n        }\n        this.type = metadata.type(type) || { name: type };\n        if (node.inputs) {\n            const inputs = node.inputs;\n            let inputIndex = 0;\n            if (this.type && this.type.inputs) {\n                for (const inputDef of this.type.inputs) {\n                    if (inputIndex < inputs.length || inputDef.optional !== true) {\n                        const count = (inputDef.type === 'Tensor[]') ? (inputs.length - inputIndex) : 1;\n                        const list = [];\n                        for (const input of inputs.slice(inputIndex, inputIndex + count)) {\n                            const identifier = `[${input.join(',')}]`;\n                            if (identifier !== '' || (inputDef.optional !== true || inputDef.type === 'Tensor[]')) {\n                                const value = values.map(identifier, null, initializers.get(identifier));\n                                list.push(value);\n                            }\n                        }\n                        const argument = new mxnet.Argument(inputDef.name, list);\n                        this.inputs.push(argument);\n                        inputIndex += count;\n                    }\n                }\n            }\n            if (inputIndex < inputs.length) {\n                this.inputs.push(...inputs.slice(inputIndex).map((input, index) => {\n                    const name = (inputIndex + index).toString();\n                    const identifier = `[${input.join(',')}]`;\n                    const value = values.map(identifier, null, initializers.get(identifier));\n                    return new mxnet.Argument(name, [value]);\n                }));\n            }\n        }\n        if (node.outputs) {\n            const outputs = node.outputs;\n            let outputIndex = 0;\n            if (this.type && this.type.outputs) {\n                for (const outputDef of this.type.outputs) {\n                    if (outputIndex < outputs.length || outputDef.optional !== true) {\n                        const list = [];\n                        const count = (outputDef.type === 'Tensor[]') ? (outputs.length - outputIndex) : 1;\n                        for (const output of outputs.slice(outputIndex, outputIndex + count)) {\n                            const value = values.map(`[${output.join(',')}]`);\n                            list.push(value);\n                        }\n                        const argument = new mxnet.Argument(outputDef.name, list);\n                        this.outputs.push(argument);\n                        outputIndex += count;\n                    }\n                }\n            }\n            if (outputIndex < outputs.length) {\n                this.outputs.push(...outputs.slice(outputIndex).map((output, index) => {\n                    const name = (outputIndex + index).toString();\n                    const value = values.map(`[${output.join(',')}]`);\n                    return new mxnet.Argument(name, [value]);\n                }));\n            }\n        }\n        if (node.params) {\n            for (const param of node.params) {\n                const value = values.map(param.id);\n                const argument = new mxnet.Argument(param.name, [value]);\n                this.inputs.push(argument);\n            }\n        }\n    }\n};\n\nmxnet.Tensor = class {\n\n    constructor(name, type, data) {\n        this.name = name;\n        this.type = type;\n        this.values = data;\n        this.encoding = '<';\n    }\n};\n\nmxnet.TensorType = class {\n\n    constructor(dataType, shape) {\n        switch (dataType) {\n            case 0: this.dataType = 'float32'; break;\n            case 1: this.dataType = 'float64'; break;\n            case 2: this.dataType = 'float16'; break;\n            case 3: this.dataType = 'uint8'; break;\n            case 4: this.dataType = 'int32'; break;\n            case 5: this.dataType = 'int8'; break;\n            case 6: this.dataType = 'int64'; break;\n            case -1: this.dataType = '?'; break;\n            default: throw new mxnet.Error(`Unsupported type '${dataType}'.`);\n        }\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nmxnet.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        if (this.dimensions) {\n            if (this.dimensions.length === 0) {\n                return '';\n            }\n            return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;\n        }\n        return '';\n    }\n};\n\nmxnet.ndarray = class {\n\n    static load(reader) {\n        // NDArray::Load(dmlc::Stream* fi, std::vector<NDArray>* data, std::vector<std::string>* keys)\n        const params = new Map();\n        reader = new mxnet.BinaryReader(reader);\n        if (reader.uint64().toNumber() !== 0x112) { // kMXAPINDArrayListMagic\n            throw new mxnet.Error('Invalid signature.');\n        }\n        if (reader.uint64().toNumber() !== 0) {\n            throw new mxnet.Error('Invalid reserved block.');\n        }\n        const values = new Array(reader.uint64().toNumber());\n        for (let i = 0; i < values.length; i++) {\n            values[i] = new mxnet.ndarray.NDArray(reader);\n        }\n        const decoder = new TextDecoder('ascii');\n        const names = new Array(reader.uint64().toNumber());\n        for (let i = 0; i < names.length; i++) {\n            const size = reader.uint64().toNumber();\n            const buffer = reader.read(size);\n            names[i] = decoder.decode(buffer);\n        }\n        if (names.length !== values.length) {\n            throw new mxnet.Error('Invalid parameters.');\n        }\n        for (let i = 0; i < names.length; i++) {\n            params.set(names[i], values[i]);\n        }\n        return params;\n    }\n};\n\nmxnet.ndarray.NDArray = class {\n\n    constructor(reader) {\n        mxnet.ndarray.NDArray._dataTypeSizeTable = [4, 8, 2, 1, 4, 1, 8];\n        switch (reader.uint32()) {\n            case 0xf993faca: { // NDARRAY_V3_MAGIC\n                throw new mxnet.Array('mxnet.ndarray.NDArray v3 not supported.');\n            }\n            case 0xf993fac9: { // NDARRAY_V2_MAGIC\n                const stype = reader.uint32();\n                let num_aux_data = 0;\n                switch (stype) {\n                    case 0: num_aux_data = 0; break; // kDefaultStorage\n                    case 1: num_aux_data = 1; break; // kRowSparseStorage\n                    case 2: num_aux_data = 2; break; // kCSRStorage\n                    default: throw mxnet.Error(`Unsupported NDArray type '${stype}'.`);\n                }\n                this.sshape = null;\n                if (num_aux_data > 0) {\n                    this.sshape = reader.uint64s();\n                }\n                this.shape = reader.uint64s();\n                if (this.shape.length !== 0) {\n                    this.context = {\n                        deviceType: reader.uint32(),\n                        deviceId: reader.uint32()\n                    };\n                    this.dtype = reader.uint32();\n                    if (num_aux_data > 0) {\n                        throw new mxnet.Error('Not implemented.');\n                    }\n                    const dataTypeSize = (this.dtype < mxnet.ndarray.NDArray._dataTypeSizeTable.length) ? mxnet.ndarray.NDArray._dataTypeSizeTable[this.dtype] : 0;\n                    const size = dataTypeSize * this.size;\n                    this.data = reader.read(size);\n                }\n                break;\n            }\n            case 0xf993fac8: { // NDARRAY_V1_MAGIC\n                this.shape = reader.uint64s();\n                if (this.shape.length !== 0) {\n                    this.context = {\n                        deviceType: reader.uint32(),\n                        deviceId: reader.uint32()\n                    };\n                    this.dtype = reader.uint32();\n                    const itemsize = (this.dtype < mxnet.ndarray.NDArray._dataTypeSizeTable.length) ? mxnet.ndarray.NDArray._dataTypeSizeTable[this.dtype] : 0;\n                    const size = itemsize * this.size;\n                    this.data = reader.read(size);\n                }\n                break;\n            }\n            default: {\n                reader.skip(-4);\n                this.shape = reader.uint32s();\n                this.context = {\n                    deviceType: reader.uint32(),\n                    deviceId: reader.uint32()\n                };\n                this.dtype = reader.uint32();\n                const itemsize = (this.dtype < mxnet.ndarray.NDArray._dataTypeSizeTable.length) ? mxnet.ndarray.NDArray._dataTypeSizeTable[this.dtype] : 0;\n                const size = itemsize * this.size;\n                this.data = reader.read(size);\n                break;\n            }\n        }\n    }\n\n    get size() {\n        return this.shape.reduce((a, b) => a * b, 1);\n    }\n};\n\nmxnet.BinaryReader = class {\n\n    constructor(reader) {\n        this._reader = reader;\n    }\n\n    skip(offset) {\n        this._reader.skip(offset);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    uint32() {\n        return this._reader.uint32();\n    }\n\n    uint32s() {\n        const size = this.uint32();\n        const array = new Array(size);\n        for (let i = 0; i < size; i++) {\n            array[i] = this.uint32();\n        }\n        return array;\n    }\n\n    uint64() {\n        return this._reader.uint64();\n    }\n\n    uint64s() {\n        const size = this.uint32();\n        const array = new Array(size);\n        for (let i = 0; i < size; i++) {\n            array[i] = this.uint64().toNumber();\n        }\n        return array;\n    }\n};\n\nmxnet.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading MXNet model.';\n    }\n};\n\nexport const ModelFactory = mxnet.ModelFactory;\n"
  },
  {
    "path": "source/ncnn-metadata.json",
    "content": "[\n  {\n    \"name\": \"AbsVal\",\n    \"identifier\": 0\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"identifier\": 1\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"identifier\": 2,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"channels\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Bias\",\n    \"identifier\": 3,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"bias_data_size\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"BinaryOp\",\n    \"identifier\": 40,\n    \"attributes\": [\n      { \"name\": \"op_type\", \"type\": \"BinaryOpType\", \"default\": 0 },\n      { \"name\": \"with_scalar\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"b\", \"type\": \"float32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"BNLL\",\n    \"identifier\": 4\n  },\n  {\n    \"name\": \"Cast\",\n    \"identifier\": 64,\n    \"attributes\": [\n      { \"name\": \"type_from\", \"type\": \"CastOpType\", \"default\": 0 },\n      { \"name\": \"type_to\", \"type\": \"CastOpType\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Clip\",\n    \"identifier\": 54,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"min\", \"type\": \"float32\" },\n      { \"name\": \"max\", \"type\": \"float32\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"identifier\": 5,\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"identifier\": 6,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"type\": \"int32\", \"default\": 0, \"visible\": false },\n      { \"name\": \"\" },\n      { \"name\": \"int8_scale_term\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"kernel_h\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_h\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_bottom\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"pad_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"dynamic_weight\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Convolution1D\",\n    \"identifier\": 81,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"type\": \"int32\", \"default\": 0, \"visible\": false },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"pad_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"dynamic_weight\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Deconvolution1D\",\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"type\": \"int32\", \"default\": 0, \"visible\": false },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"output_pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"output_w\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Convolution3D\",\n    \"identifier\": 84,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"type\": \"int32\", \"default\": 0, \"visible\": false },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"kernel_h\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_h\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_bottom\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_behind\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"kernel_d\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_d\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_d\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_front\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionDepthWise\",\n    \"identifier\": 42,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"group\", \"default\": 0 },\n      { \"name\": \"int8_scale_term\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"kernel_h\", \"default\": 0 },\n      { \"name\": \"dilation_h\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_bottom\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"pad_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"dynamic_weight\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionDepthWise1D\",\n    \"identifier\": 83,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"group\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"pad_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"dynamic_weight\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionDepthWise3D\",\n    \"identifier\": 85,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"group\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"kernel_h\", \"default\": 0 },\n      { \"name\": \"dilation_h\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_bottom\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_behind\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"pad_value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"kernel_d\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"dilation_d\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"stride_d\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"pad_front\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Crop\",\n    \"identifier\": 7,\n    \"category\": \"Data\",\n    \"attributes\": [\n      { \"name\": \"woffset\", \"default\": 0 },\n      { \"name\": \"hoffset\", \"default\": 0 },\n      { \"name\": \"coffset\", \"default\": 0 },\n      { \"name\": \"outw\", \"default\": 0 },\n      { \"name\": \"outh\", \"default\": 0 },\n      { \"name\": \"outc\", \"default\": 0 },\n      { \"name\": \"woffset2\", \"default\": 0 },\n      { \"name\": \"hoffset2\", \"default\": 0 },\n      { \"name\": \"coffset2\", \"default\": 0 },\n      { \"name\": \"starts\", \"default\": [] },\n      { \"name\": \"ends\", \"default\": [] },\n      { \"name\": \"axes\", \"default\": [] }\n    ]\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"identifier\": 8,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"\" },\n      { \"name\": \"int8_scale_term\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"kernel_h\", \"default\": 0 },\n      { \"name\": \"dilation_h\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"pad_bottom\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"output_pad_right\", \"default\": 0 },\n      { \"name\": \"output_pad_bottom\", \"default\": 0 },\n      { \"name\": \"output_w\", \"default\": 0 },\n      { \"name\": \"output_h\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"DeconvolutionDepthWise\",\n    \"identifier\": 51,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"dilation_w\", \"default\": 1 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_w\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"group\", \"default\": 0 },\n      { \"name\": \"int8_scale_term\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] },\n      { \"name\": \"kernel_h\", \"default\": 0 },\n      { \"name\": \"dilation_h\", \"default\": 1 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"pad_bottom\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"output_pad_right\", \"default\": 0 },\n      { \"name\": \"output_pad_bottom\", \"default\": 0 },\n      { \"name\": \"output_w\", \"default\": 0 },\n      { \"name\": \"output_h\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"DeepCopy\",\n    \"identifier\": 70\n  },\n  {\n    \"name\": \"Dequantize\",\n    \"identifier\": 58,\n    \"category\": \"Quantization\",\n    \"attributes\": [\n      { \"name\": \"scale_data_size\", \"default\": 1, \"visible\": false },\n      { \"name\": \"bias_data_size\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"DetectionOutput\",\n    \"identifier\": 49,\n    \"attributes\": [\n      { \"name\": \"num_class\", \"default\": 0 },\n      { \"name\": \"nms_threshold\", \"default\": 0.05 },\n      { \"name\": \"nms_top_k\", \"default\": 300 },\n      { \"name\": \"keep_top_k\", \"default\": 100 },\n      { \"name\": \"confidence_threshold\", \"default\": 0.5 },\n      { \"name\": \"varainces0\", \"default\": 0.1 },\n      { \"name\": \"varainces1\", \"default\": 0.1 },\n      { \"name\": \"varainces2\", \"default\": 0.2 },\n      { \"name\": \"varainces3\", \"default\": 0.2 }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"identifier\": 9,\n    \"category\": \"Dropout\",\n    \"attributes\": [\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"Eltwise\",\n    \"identifier\": 10,\n    \"attributes\": [\n      { \"name\": \"op_type\", \"type\": \"EltwiseType\", \"default\": 0 },\n      { \"name\": \"coeffs\", \"default\": [] }\n    ],\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"ELU\",\n    \"identifier\": 11,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.1 }\n    ]\n  },\n  {\n    \"name\": \"Embed\",\n    \"identifier\": 12,\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"input_dim\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"Exp\",\n    \"identifier\": 13,\n    \"attributes\": [\n      { \"name\": \"base\", \"type\": \"float32\", \"default\": -1 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"identifier\": 45,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"expand_w\", \"default\": 0 },\n      { \"name\": \"expand_h\", \"default\": 0 },\n      { \"name\": \"expand_c\", \"default\": 0 },\n      { \"name\": \"axes\", \"default\": [] }\n    ]\n  },\n  {\n    \"name\": \"Flatten\",\n    \"identifier\": 14,\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"GELU\",\n    \"identifier\": 80,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"fast_gelu\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Gemm\",\n    \"identifier\": 74,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"transA\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"transB\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constantA\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constantB\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constantC\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constantM\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constantN\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constantK\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constant_broadcast_type_C\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"output_N1M\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"output_elempack\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"output_elemtype\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"output_transpose\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constant_TILE_M\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constant_TILE_N\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"constant_TILE_K\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"GroupNorm\",\n    \"identifier\": 75,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"group\", \"default\": 1 },\n      { \"name\": \"channels\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.001 },\n      { \"name\": \"affine\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"GRU\",\n    \"identifier\": 78,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"direction\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"HardSigmoid\",\n    \"identifier\": 65,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.5 }\n    ]\n  },\n  {\n    \"name\": \"HardSwish\",\n    \"identifier\": 67,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 0.2 },\n      { \"name\": \"beta\", \"type\": \"float32\", \"default\": 0.5 }\n    ]\n  },\n  {\n    \"name\": \"InnerProduct\",\n    \"identifier\": 15,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"int8_scale_term\", \"default\": 0 },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] }\n    ]\n  },\n  {\n    \"name\": \"Input\",\n    \"identifier\": 16\n  },\n  {\n    \"name\": \"InstanceNorm\",\n    \"identifier\": 53,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"channels\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.001 },\n      { \"name\": \"affine\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"Interp\",\n    \"identifier\": 50,\n    \"attributes\": [\n      { \"name\": \"resize_type\", \"type\": \"InterpResizeType\", \"default\": 0 },\n      { \"name\": \"height_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"width_scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"output_height\", \"default\": 0 },\n      { \"name\": \"output_width\", \"default\": 0 },\n      { \"name\": \"dynamic_target_size\", \"default\": 0 },\n      { \"name\": \"align_corner\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"identifier\": 76,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"channels\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.001 },\n      { \"name\": \"affine\", \"type\": \"int32\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"LeakyReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Log\",\n    \"identifier\": 17,\n    \"attributes\": [\n      { \"name\": \"base\", \"type\": \"float32\", \"default\": -1 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"identifier\": 18,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"region_type\", \"default\": 0 },\n      { \"name\": \"local_size\", \"default\": 5 },\n      { \"name\": \"alpha\", \"default\": 1 },\n      { \"name\": \"beta\", \"default\": 0.75 },\n      { \"name\": \"bias\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"identifier\": 39,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"direction\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"MemoryData\",\n    \"identifier\": 19,\n    \"attributes\": [\n      { \"name\": \"w\", \"default\": 0 },\n      { \"name\": \"h\", \"default\": 0 },\n      { \"name\": \"c\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"d\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Mish\",\n    \"identifier\": 71,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"MultiHeadAttention\",\n    \"identifier\": 79,\n    \"category\": \"Attention\",\n    \"attributes\": [\n      { \"name\": \"embed_dim\", \"default\": 0 },\n      { \"name\": \"num_head\", \"default\": 1 },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"MVN\",\n    \"identifier\": 20,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"normalize_variance\", \"default\": 0 },\n      { \"name\": \"across_channels\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.0001 }\n    ]\n  },\n  {\n    \"name\": \"Noop\",\n    \"identifier\": 68\n  },\n  {\n    \"name\": \"Normalize\",\n    \"identifier\": 46,\n    \"category\": \"Normalization\",\n    \"attributes\": [\n      { \"name\": \"across_spatial\", \"default\": 0 },\n      { \"name\": \"channel_shared\", \"default\": 0 },\n      { \"name\": \"eps\", \"type\": \"float32\", \"default\": 0.0001 },\n      { \"name\": \"scale_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"across_channel\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"eps_mode\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Packing\",\n    \"identifier\": 62,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"out_elempack\", \"default\": 1 },\n      { \"name\": \"use_padding\", \"default\": 0 },\n      { \"name\": \"cast_type_from\", \"default\": 0 },\n      { \"name\": \"cast_type_to\", \"default\": 0 },\n      { \"name\": \"storage_type_from\", \"default\": 0 },\n      { \"name\": \"storage_type_to\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Padding\",\n    \"identifier\": 43,\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"top\", \"default\": 0 },\n      { \"name\": \"bottom\", \"default\": 0 },\n      { \"name\": \"left\", \"default\": 0 },\n      { \"name\": \"right\", \"default\": 0 },\n      { \"name\": \"type\", \"type\": \"PaddingType\", \"default\": 0 },\n      { \"name\": \"value\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"per_channel_pad_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"front\", \"default\": 0 },\n      { \"name\": \"behind\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Permute\",\n    \"identifier\": 47,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"order_type\", \"type\": \"PermuteOrderType\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"PixelShuffle\",\n    \"identifier\": 69,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"upscale_factor\", \"default\": 1 },\n      { \"name\": \"mode\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Pooling\",\n    \"identifier\": 21,\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"pooling_type\", \"type\": \"PoolingType\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"default\": 0 },\n      { \"name\": \"global_pooling\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"default\": 0 },\n      { \"name\": \"avgpool_count_include_pad\", \"default\": 0 },\n      { \"name\": \"adaptive_pooling\", \"default\": 0 },\n      { \"name\": \"out_w\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"kernel_h\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"default\": 0 },\n      { \"name\": \"pad_bottom\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"out_h\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Pooling1D\",\n    \"identifier\": 82,\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"pooling_type\", \"type\": \"PoolingType\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"default\": 0 },\n      { \"name\": \"global_pooling\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"default\": 0 },\n      { \"name\": \"avgpool_count_include_pad\", \"default\": 0 },\n      { \"name\": \"adaptive_pooling\", \"default\": 0 },\n      { \"name\": \"out_w\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"pad_right\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Pooling3D\",\n    \"identifier\": 86,\n    \"category\": \"Pool\",\n    \"attributes\": [\n      { \"name\": \"pooling_type\", \"type\": \"PoolingType\", \"default\": 0 },\n      { \"name\": \"kernel_w\", \"default\": 0 },\n      { \"name\": \"stride_w\", \"default\": 1 },\n      { \"name\": \"pad_left\", \"default\": 0 },\n      { \"name\": \"global_pooling\", \"default\": 0 },\n      { \"name\": \"pad_mode\", \"default\": 0 },\n      { \"name\": \"avgpool_count_include_pad\", \"default\": 0 },\n      { \"name\": \"adaptive_pooling\", \"default\": 0 },\n      { \"name\": \"out_w\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"kernel_h\", \"default\": 0 },\n      { \"name\": \"stride_h\", \"default\": 1 },\n      { \"name\": \"pad_top\", \"default\": 0 },\n      { \"name\": \"pad_right\", \"default\": 0 },\n      { \"name\": \"pad_bottom\", \"default\": 0 },\n      { \"name\": \"pad_behind\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"out_h\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"kernel_d\", \"default\": 0 },\n      { \"name\": \"stride_d\", \"default\": 1 },\n      { \"name\": \"pad_front\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"out_d\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Power\",\n    \"identifier\": 22,\n    \"attributes\": [\n      { \"name\": \"power\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"scale\", \"type\": \"float32\", \"default\": 1 },\n      { \"name\": \"shift\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"PReLU\",\n    \"identifier\": 23,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"num_slope\", \"type\": \"int32\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"PriorBox\",\n    \"identifier\": 48,\n    \"attributes\": [\n      { \"name\": \"min_sizes\", \"default\": [] },\n      { \"name\": \"max_sizes\", \"default\": [] },\n      { \"name\": \"aspect_ratios\", \"default\": [] },\n      { \"name\": \"varainces0\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"varainces1\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"varainces2\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"varainces3\", \"type\": \"float32\", \"default\": 0 },\n      { \"name\": \"flip\", \"default\": 1 },\n      { \"name\": \"clip\", \"default\": 0 },\n      { \"name\": \"image_width\", \"default\": 0 },\n      { \"name\": \"image_height\", \"default\": 0 },\n      { \"name\": \"step_width\", \"default\": -233 },\n      { \"name\": \"step_height\", \"default\": -233 },\n      { \"name\": \"offset\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Proposal\",\n    \"identifier\": 24\n  },\n  {\n    \"name\": \"PSROIPooling\",\n    \"identifier\": 60\n  },\n  {\n    \"name\": \"Quantize\",\n    \"identifier\": 57,\n    \"category\": \"Quantization\",\n    \"attributes\": [\n      { \"name\": \"scale_data_size\", \"default\": 1, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"Reduction\",\n    \"identifier\": 25,\n    \"attributes\": [\n      { \"name\": \"operation\", \"type\": \"ReductionOpType\", \"default\": 0 },\n      { \"name\": \"reduce_all\", \"type\": \"int32\", \"default\": 1 },\n      { \"name\": \"coeff\", \"type\": \"float32\", \"default\": 1.0 },\n      { \"name\": \"axes\", \"default\": [] },\n      { \"name\": \"keepdims\", \"type\": \"int32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ReLU\",\n    \"identifier\": 26,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"slope\", \"type\": \"float32\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"ReLU6\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Reorg\",\n    \"identifier\": 55,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"stride\", \"default\": 1 },\n      { \"name\": \"mode\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Requantize\",\n    \"identifier\": 63,\n    \"attributes\": [\n      { \"name\": \"scale_in_data_size\", \"default\": 1, \"visible\": false },\n      { \"name\": \"scale_out_data_size\", \"default\": 1, \"visible\": false },\n      { \"name\": \"bias_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"activation_type\", \"default\": 0 },\n      { \"name\": \"activation_params\", \"default\": [] }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"identifier\": 27,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"w\", \"default\": -233 },\n      { \"name\": \"h\", \"default\": -233 },\n      { \"name\": \"c\", \"default\": -233 },\n      { \"name\": \"permute\", \"default\": 0 },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"\" },\n      { \"name\": \"d\", \"default\": -233 }\n    ]\n  },\n  {\n    \"name\": \"RNN\",\n    \"identifier\": 38,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"num_output\", \"default\": 0 },\n      { \"name\": \"weight_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"direction\", \"default\": 1 }\n    ]\n  },\n  {\n    \"name\": \"ROIAlign\",\n    \"identifier\": 61\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"identifier\": 28\n  },\n  {\n    \"name\": \"Scale\",\n    \"identifier\": 29,\n    \"category\": \"Layer\",\n    \"attributes\": [\n      { \"name\": \"scale_data_size\", \"default\": 0, \"visible\": false },\n      { \"name\": \"bias_term\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"SELU\",\n    \"identifier\": 66,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"alpha\", \"type\": \"float32\", \"default\": 1.67326324 },\n      { \"name\": \"lambda\", \"type\": \"float32\", \"default\": 1.050700987 }\n    ]\n  },\n  {\n    \"name\": \"ShuffleChannel\",\n    \"identifier\": 52,\n    \"category\": \"Shape\",\n    \"attributes\": [\n      { \"name\": \"group\", \"default\": 1 },\n      { \"name\": \"reverse\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"identifier\": 30,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Slice\",\n    \"identifier\": 31,\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      { \"name\": \"slices\", \"default\": [] },\n      { \"name\": \"axis\", \"default\": 0 }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"identifier\": 32,\n    \"category\": \"Activation\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\", \"default\": 0 },\n      { \"name\": \"fixbug0\", \"type\": \"int32\", \"default\": 0, \"visible\": false }\n    ]\n  },\n  {\n    \"name\": \"Softplus\",\n    \"identifier\": 77,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Split\",\n    \"identifier\": 33,\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"SPP\",\n    \"identifier\": 34,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"identifier\": 44,\n    \"category\": \"Transform\",\n    \"attributes\": [\n      { \"name\": \"squeeze_w\", \"default\": 0 },\n      { \"name\": \"squeeze_h\", \"default\": 0 },\n      { \"name\": \"squeeze_c\", \"default\": 0 },\n      { \"name\": \"axes\", \"default\": [] }\n    ]\n  },\n  {\n    \"name\": \"StatisticsPooling\",\n    \"identifier\": 72,\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Swish\",\n    \"identifier\": 73,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"TanH\",\n    \"identifier\": 35,\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Threshold\",\n    \"identifier\": 36\n  },\n  {\n    \"name\": \"Tile\",\n    \"identifier\": 37\n  },\n  {\n    \"name\": \"UnaryOp\",\n    \"identifier\": 41,\n    \"attributes\": [\n      { \"name\": \"op_type\", \"type\": \"UnaryOpType\", \"default\": 0 }\n    ]\n  },\n  {\n    \"name\": \"YoloDetectionOutput\",\n    \"identifier\": 56,\n    \"attributes\": [\n      { \"name\": \"num_class\", \"type\": \"int32\", \"default\": 20 },\n      { \"name\": \"num_box\", \"type\": \"int32\", \"default\": 5 },\n      { \"name\": \"confidence_threshold\", \"type\": \"float32\", \"default\": 0.01 },\n      { \"name\": \"nms_threshold\", \"type\": \"float32\", \"default\": 0.45 },\n      { \"name\": \"biases\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"Yolov3DetectionOutput\",\n    \"identifier\": 59,\n    \"attributes\": [\n      { \"name\": \"num_class\", \"type\": \"int32\", \"default\": 20 },\n      { \"name\": \"num_box\", \"type\": \"int32\", \"default\": 5 },\n      { \"name\": \"confidence_threshold\", \"type\": \"float32\", \"default\": 0.01 },\n      { \"name\": \"nms_threshold\", \"type\": \"float32\", \"default\": 0.45 },\n      { \"name\": \"biases\", \"type\": \"float32[]\" },\n      { \"name\": \"mask\", \"type\": \"float32[]\" },\n      { \"name\": \"anchors_scale\", \"type\": \"float32[]\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"Stack\",\n    \"attributes\": [\n      { \"name\": \"axis\", \"type\": \"int32\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\", \"type\": \"Tensor[]\" }\n    ]\n  }\n]\n"
  },
  {
    "path": "source/ncnn.js",
    "content": "\nimport * as base from './base.js';\n\nconst ncnn = {};\nconst pnnx = {};\n\n// https://github.com/Tencent/ncnn/wiki/param-and-model-file-structure\n// https://github.com/Tencent/ncnn/wiki/operation-param-weight-table\n// https://github.com/Tencent/ncnn/wiki/operators\n\nncnn.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier.toLowerCase();\n        if (identifier.endsWith('.param.bin') || identifier.endsWith('.ncnnmodel')) {\n            const stream = context.stream;\n            if (stream.length >= 4) {\n                const buffer = stream.peek(4);\n                const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n                const signature = view.getUint32(0, true);\n                if (signature === 0x007685dd) {\n                    return context.set('ncnn.model.bin');\n                }\n            }\n        } else if (identifier.endsWith('.param') || identifier.endsWith('.cfg.ncnn')) {\n            const reader = await context.read('text', 0x10000);\n            if (reader) {\n                let type = '';\n                try {\n                    let match = false;\n                    const signature = reader.read('\\n');\n                    if (signature !== undefined) {\n                        if (signature.trim() === '7767517') {\n                            match = true;\n                        } else {\n                            const header = signature.trim().split(' ');\n                            if (header.length === 2 && header.every((value) => value >>> 0 === parseFloat(value))) {\n                                match = true;\n                            }\n                        }\n                    }\n                    if (match) {\n                        type = 'ncnn.model';\n                        for (let i = 0; i < 32; i++) {\n                            const line = reader.read('\\n');\n                            if (!line) {\n                                break;\n                            }\n                            if (line.startsWith('pnnx.') || line.startsWith('nn.') || line.startsWith('F.') || line.startsWith('torch.') || line.startsWith('Tensor.')) {\n                                type = 'pnnx.model';\n                                break;\n                            }\n                        }\n                    }\n                } catch {\n                    // continue regardless of error\n                }\n                if (type) {\n                    return context.set(type);\n                }\n            }\n        } else if (identifier.endsWith('.ncnn.bin')) {\n            return context.set('ncnn.weights');\n        } else if (identifier.endsWith('.pnnx.bin')) {\n            const entries = await context.peek('zip');\n            if (entries instanceof Map) {\n                return context.set('pnnx.weights', entries);\n            }\n        } else if (identifier.endsWith('.bin') || identifier.endsWith('.weights.ncnn')) {\n            const stream = context.stream;\n            const length = Math.min(0x10000, stream.length);\n            if (length > 4) {\n                let buffer = stream.peek(length);\n                const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n                const signature = view.getUint32(0, true);\n                if (signature === 0x00000000) {\n                    const size = Math.min(buffer.length & 0xfffffffc, 128);\n                    buffer = buffer.subarray(0, size);\n                    const f32 = new Array(buffer.length >> 2);\n                    for (let i = 1; i < f32.length; i++) {\n                        f32[i] = view.getFloat32(i << 2, true);\n                    }\n                    if (f32.every((value) => !Number.isNaN(value) && Number.isFinite(value) && value > -20.0 && value < 20.0)) {\n                        return context.set('ncnn.weights');\n                    }\n                } else {\n                    for (let i = 0; i < buffer.length - 4; i++) {\n                        const signature = view.getUint32(i, true);\n                        if (signature === 0xdeadbeef) { // Core ML\n                            return null;\n                        }\n                        if (signature === 0x01306b47 || signature === 0x000d4b38 || signature === 0x0002c056) { // ncnn\n                            return context.set('ncnn.weights');\n                        }\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        return (context.type !== 'ncnn.model' && context.type !== 'ncnn.model.bin') || match.type !== 'ncnn.weights';\n    }\n\n    async open(context) {\n        let metadata = null;\n        if (context.type.startsWith('pnnx.')) {\n            metadata = await pnnx.Metadata.open(context);\n        } else {\n            metadata = await context.metadata('ncnn-metadata.json');\n        }\n        const identifier = context.identifier.toLowerCase();\n        const format = context.type.split('.').shift();\n        switch (context.type) {\n            case 'pnnx.model':\n            case 'ncnn.model': {\n                let file = null;\n                if (identifier.endsWith('.param')) {\n                    const extension = context.type === 'pnnx.model' && !identifier.endsWith('.pnnx.param') ? '.pnnx.bin' : '.bin';\n                    file = context.identifier.replace(/\\.param$/, extension);\n                } else if (identifier.endsWith('.cfg.ncnn')) {\n                    file = context.identifier.replace(/\\.cfg\\.ncnn$/, '.weights.ncnn');\n                }\n                let content = null;\n                try {\n                    content = await context.fetch(file);\n                } catch {\n                    // continue regardless of error\n                }\n                const param = await context.read('text');\n                const reader = new ncnn.TextParamReader(param);\n                const blobs = await ncnn.BlobReader.open(content);\n                return new ncnn.Model(metadata, format, reader, blobs);\n            }\n            case 'ncnn.model.bin': {\n                const bin = `${context.identifier.substring(0, context.identifier.length - 10)}.bin`;\n                let content = null;\n                try {\n                    content = await context.fetch(bin);\n                } catch {\n                    // continue regardless of error\n                }\n                const param = context.stream.peek();\n                const reader = new ncnn.BinaryParamReader(param);\n                const blobs = await ncnn.BlobReader.open(content);\n                return new ncnn.Model(metadata, format, reader, blobs);\n            }\n            case 'pnnx.weights':\n            case 'ncnn.weights': {\n                let file = null;\n                if (identifier.endsWith('.bin')) {\n                    file = context.identifier.replace(/\\.bin$/, '.param');\n                } else if (identifier.endsWith('.weights.ncnn')) {\n                    file = context.identifier.replace(/\\.weights\\.ncnn$/, '.cfg.ncnn');\n                }\n                let content = null;\n                let message = null;\n                try {\n                    content = await context.fetch(file);\n                } catch (error) {\n                    message = error && error.message ? error.message : error.toString();\n                    try {\n                        content = await context.fetch(`${file}.bin`);\n                    } catch {\n                        // continue regardless of error\n                    }\n                }\n                if (!content) {\n                    throw new ncnn.Error(`Required ncnn model definition not found (${message.replace(/\\.$/, '')}).`);\n                }\n                let reader = null;\n                if (content.identifier.endsWith('.bin')) {\n                    const data = content.stream.peek();\n                    reader = new ncnn.BinaryParamReader(data);\n                } else {\n                    const text = await content.read('text');\n                    reader = new ncnn.TextParamReader(text);\n                }\n                const blobs = await ncnn.BlobReader.open(context);\n                return new ncnn.Model(metadata, format, reader, blobs);\n            }\n            default: {\n                throw new ncnn.Error(`Unsupported ncnn format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nncnn.Model = class {\n\n    constructor(metadata, format, param, blobs) {\n        this.format = format === 'pnnx' ? 'PNNX' : 'ncnn';\n        this.modules = [new ncnn.Graph(metadata, format, param, blobs)];\n    }\n};\n\nncnn.Graph = class {\n\n    constructor(metadata, format, param, blobs) {\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const layers = param.layers;\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (name.length === 0 && tensor) {\n                return new ncnn.Value(name, type, tensor);\n            }\n            if (!values.has(name)) {\n                values.set(name, new ncnn.Value(name, type || null, tensor || null));\n            } else if (tensor || (type && !type.equals(values.get(name).type))) {\n                throw new ncnn.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        for (const layer of layers) {\n            const params = layer.params;\n            if (params && params.size > 0) {\n                for (const [key, list] of params) {\n                    if (key === '30' && Array.isArray(list)) {\n                        const value = list.map((item) => parseInt(item, 10));\n                        for (const output of layer.outputs || []) {\n                            if (value.length > 0 && value[0] <= value.length - 1) {\n                                const shape = new Array(value.shift());\n                                for (let i = 0; i < shape.length; i++) {\n                                    shape[i] = value.shift();\n                                }\n                                const type = new ncnn.TensorType('float32', new ncnn.TensorShape(shape));\n                                values.map(output, type);\n                            }\n                            params.delete(key);\n                        }\n                    }\n                }\n            }\n        }\n        for (const layer of layers) {\n            if (layer.type === 'Input' || layer.type === 16) {\n                const dimensions = Array.from(layer.params.values()).map((value) => isNaN(parseInt(value, 10)) ? value : parseInt(value, 10));\n                const shape = new ncnn.TensorShape(dimensions);\n                const type = new ncnn.TensorType('float32', shape);\n                const argument = new ncnn.Argument(layer.name, layer.outputs.map((output) => values.map(output, type)));\n                this.inputs.push(argument);\n            } else if (layer.type === 'pnnx.Input' && layer.params) {\n                const argument = new ncnn.Argument(layer.name, layer.outputs.map((output) => values.map(output, ncnn.Utility.route(layer.params, output))));\n                this.inputs.push(argument);\n            } else if (layer.type === 'pnnx.Output' && layer.params) {\n                const argument = new ncnn.Argument(layer.name, layer.inputs.map((input) => values.map(input, ncnn.Utility.route(layer.params, input))));\n                this.outputs.push(argument);\n            } else {\n                const node = new ncnn.Node(metadata, format, blobs, layer, values);\n                this.nodes.push(node);\n            }\n        }\n        blobs.validate();\n    }\n};\n\nncnn.Argument = class {\n\n    constructor(name, value, type, visible) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible !== false;\n    }\n};\n\nncnn.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new ncnn.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer ? initializer.type : type;\n        this.initializer = initializer;\n        this.quantization = initializer ? initializer.quantization : null;\n    }\n};\n\nncnn.Node = class {\n\n    constructor(metadata, format, blobs, layer, values) {\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        this.chain = [];\n        this.name = layer.name || '';\n        this.type = { ...metadata.type(layer.type) };\n        delete this.type.identifier;\n        const params = layer.params;\n        const inputs = layer.inputs || [];\n        let inputIndex = 0;\n        const names = new Map();\n        if (params) {\n            for (const [key, value] of params) {\n                if (key.startsWith('$')) {\n                    names.set(value, key.substring(1));\n                    params.delete(key);\n                }\n            }\n        }\n        if (this.type && Array.isArray(this.type.inputs)) {\n            for (const input of this.type.inputs) {\n                if (inputIndex < inputs.length || input.optional === false) {\n                    const count = (input.type === 'Tensor[]') ? (inputs.length - inputIndex) : 1;\n                    const list = inputs.slice(inputIndex, inputIndex + count).filter((id) => id !== '' || input.option !== 'optional').map((id) => values.map(id, ncnn.Utility.route(params, id)));\n                    const argument = new ncnn.Argument(input.name, list);\n                    this.inputs.push(argument);\n                    inputIndex += count;\n                }\n            }\n        }\n        this.inputs.push(...inputs.slice(inputIndex).map((input, index) => {\n            index = inputIndex + index;\n            let name = 'input';\n            if (names.has(input)) {\n                name = names.get(input);\n            } else if (index !== 0) {\n                name = index.toString();\n            }\n            return new ncnn.Argument(name, [values.map(input, ncnn.Utility.route(params, input))]);\n        }));\n        const outputs = layer.outputs || [];\n        let outputIndex = 0;\n        if (this.type && Array.isArray(this.type.outputs)) {\n            for (const output of this.type.outputs) {\n                if (outputIndex < outputs.length || output.option !== 'optional') {\n                    const count = (output.type === 'Tensor[]') ? (outputs.length - outputIndex) : 1;\n                    const list = outputs.slice(outputIndex, outputIndex + count).map((id) => values.map(id, ncnn.Utility.route(params, id)));\n                    const argument = new ncnn.Argument(output.name, list);\n                    this.outputs.push(argument);\n                    outputIndex += count;\n                }\n            }\n        }\n        this.outputs.push(...outputs.slice(outputIndex).map((output, index) => {\n            const name = (outputIndex + index) === 0 ? 'output' : (outputIndex + index).toString();\n            return new ncnn.Argument(name, [values.map(output, ncnn.Utility.route(params, output))]);\n        }));\n        blobs.weight = (name, shape, code) => {\n            const blob = blobs.load(shape, code || 0);\n            const dataType = blob ? (blob.dataType || '?') : (code || 0).toString();\n            const data = blob ? blob.data : null;\n            const quantization = blob && blob.quantization ? blob.quantization : null;\n            const type = new ncnn.TensorType(dataType, new ncnn.TensorShape(shape));\n            const tensor = new ncnn.Tensor(type, data, quantization);\n            const argument = new ncnn.Argument(name, [values.map('', null, tensor)]);\n            this.inputs.push(argument);\n        };\n        switch (this.type.name) {\n            case 'BatchNorm': {\n                const channels = parseInt(params.get('0') || 0, 10);\n                blobs.weight('slope', [channels], 1);\n                blobs.weight('mean', [channels], 1);\n                blobs.weight('variance', [channels], 1);\n                blobs.weight('bias', [channels], 1);\n                break;\n            }\n            case 'InnerProduct': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const bias_term = parseInt(params.get('1') || 0, 10);\n                const weight_data_size = parseInt(params.get('2') || 0, 10);\n                const int8_scale_term = parseInt(params.get('8') || 0, 10);\n                const activation_type = parseInt(params.get('9') || 0, 10);\n                const input_size = num_output > 0 ? Math.floor(weight_data_size / num_output) : 0;\n                blobs.weight('weight', [num_output, input_size]);\n                if (bias_term) {\n                    blobs.weight('bias', [num_output], 1);\n                }\n                if (int8_scale_term) {\n                    blobs.weight('weight_scales', [num_output], 1);\n                    blobs.weight('bottom_scales', [1], 1);\n                }\n                const activation_names = ['', 'ReLU', 'Leaky ReLU', 'Clip', 'Sigmoid', 'Mish', 'HardSwish'];\n                if (activation_type > 0 && activation_type < activation_names.length) {\n                    const layer = { type: activation_names[activation_type] };\n                    this.chain.push(new ncnn.Node(metadata, format, blobs, layer, values));\n                }\n                params.delete('2');\n                break;\n            }\n            case 'Bias': {\n                const bias_data_size = parseInt(params.get('0') || 0, 10);\n                blobs.weight('bias', [bias_data_size], 1);\n                break;\n            }\n            case 'Embed': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const weight_data_size = parseInt(params.get('3') || 0, 10);\n                blobs.weight('weight', [weight_data_size / num_output, num_output]);\n                if (parseInt(params.get('2') || 0, 10) === 1) {\n                    blobs.weight('bias', [num_output], 1);\n                }\n                params.get('3');\n                break;\n            }\n            case 'Convolution':\n            case 'ConvolutionDepthWise':\n            case 'Deconvolution':\n            case 'DeconvolutionDepthWise': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const kernel_w = parseInt(params.get('1') || 0, 10);\n                const kernel_h = parseInt(params.get('11') || kernel_w, 10);\n                const weight_data_size = parseInt(params.get('6') || 0, 10);\n                blobs.weight('weight', [num_output, weight_data_size / (num_output * kernel_w * kernel_h), kernel_h, kernel_w]);\n                if (parseInt(params.get('5') || 0, 10) === 1) {\n                    blobs.weight('bias', [num_output], 1);\n                }\n                const int8_scale_term = parseInt(params.get('8') || 0, 10);\n                if (this.type.name === 'Convolution') {\n                    if (int8_scale_term) {\n                        blobs.weight('weight_scales', [num_output], 1);\n                        blobs.weight('bottom_scales', [1], 1);\n                    }\n                    if (int8_scale_term > 100) {\n                        blobs.weight('top_scales', [1], 1);\n                    }\n                } else if (this.type.name === 'ConvolutionDepthWise') {\n                    const group =  parseInt(params.get('7') || 1, 10);\n                    if (int8_scale_term === 1 || int8_scale_term === 101) {\n                        blobs.weight('weight_scales', [group], 1);\n                        blobs.weight('bottom_scales', [1], 1);\n                    } else if (int8_scale_term === 2 || int8_scale_term === 102) {\n                        blobs.weight('weight_scales', [1], 1);\n                        blobs.weight('bottom_scales', [1], 1);\n                    }\n                    if (int8_scale_term > 100) {\n                        blobs.weight('top_scales', [1], 1);\n                    }\n                }\n                params.delete('6');\n                const activation_names = ['', 'ReLU', 'LeakyReLU', 'Clip', 'Sigmoid', 'Mish', 'HardSwish'];\n                const activation_type = parseInt(params.get('9') || 0, 10);\n                if (activation_type > 0 && activation_type < activation_names.length) {\n                    const layer = { type: activation_names[activation_type] };\n                    this.chain.push(new ncnn.Node(metadata, format, blobs, layer, values));\n                }\n                break;\n            }\n            case 'Convolution1D':\n            case 'ConvolutionDepthWise1D': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const kernel_w = parseInt(params.get('1') || 0, 10);\n                const dynamic_weight = parseInt(params.get('19') || 0, 10);\n                if (!dynamic_weight) {\n                    const weight_data_size = parseInt(params.get('6') || 0, 10);\n                    blobs.weight('weight', [num_output, weight_data_size / (num_output * kernel_w), kernel_w]);\n                    if (parseInt(params.get('5') || 0, 10) === 1) {\n                        blobs.weight('bias', [num_output], 1);\n                    }\n                    params.delete('6');\n                }\n                params.delete('19');\n                const activation_names = ['', 'ReLU', 'LeakyReLU', 'Clip', 'Sigmoid', 'Mish', 'HardSwish'];\n                const activation_type = parseInt(params.get('9') || 0, 10);\n                if (activation_type > 0 && activation_type < activation_names.length) {\n                    const layer = { type: activation_names[activation_type] };\n                    const node = new ncnn.Node(metadata, format, blobs, layer, values);\n                    this.chain.push(node);\n                }\n                break;\n            }\n            case 'Deconvolution1D': {\n                const activation_names = ['', 'ReLU', 'LeakyReLU', 'Clip', 'Sigmoid', 'Mish', 'HardSwish'];\n                const activation_type = parseInt(params.get('9') || 0, 10);\n                if (activation_type > 0 && activation_type < activation_names.length) {\n                    const layer = { type: activation_names[activation_type] };\n                    const node = new ncnn.Node(metadata, format, blobs, layer, values);\n                    this.chain.push(node);\n                }\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const kernel_w = parseInt(params.get('1') || 0, 10);\n                const dynamic_weight = parseInt(params.get('28') || 0, 10);\n                if (!dynamic_weight) {\n                    const weight_data_size = parseInt(params.get('6') || 0, 10);\n                    blobs.weight('weight', [num_output, weight_data_size / (num_output * kernel_w), kernel_w]);\n                    if (parseInt(params.get('5') || 0, 10) === 1) {\n                        blobs.weight('bias', [num_output], 1);\n                    }\n                    params.delete('6');\n                }\n                params.delete('28');\n                break;\n            }\n            case 'Convolution3D':\n            case 'ConvolutionDepthWise3D': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const kernel_w = parseInt(params.get('1') || 0, 10);\n                const kernel_h = parseInt(params.get('11') || kernel_w, 10);\n                const kernel_d = parseInt(params.get('21') || kernel_w, 10);\n                const weight_data_size = parseInt(params.get('6') || 0, 10);\n                blobs.weight('weight', [num_output, weight_data_size / (num_output * kernel_w * kernel_h * kernel_d), kernel_d, kernel_h, kernel_w]);\n                if (parseInt(params.get('5') || 0, 10) === 1) {\n                    blobs.weight('bias', [num_output], 1);\n                }\n                params.delete('6');\n                const activation_names = ['', 'ReLU', 'LeakyReLU', 'Clip', 'Sigmoid', 'Mish', 'HardSwish'];\n                const activation_type = parseInt(params.get('9') || 0, 10);\n                if (activation_type > 0 && activation_type < activation_names.length) {\n                    const layer = { type: activation_names[activation_type] };\n                    this.chain.push(new ncnn.Node(metadata, format, blobs, layer, values));\n                }\n                break;\n            }\n            case 'Quantize': {\n                const scale_data_size = parseInt(params.get('0') || 1, 10);\n                blobs.weight('scale', [scale_data_size], 1);\n                break;\n            }\n            case 'Dequantize': {\n                const scale_data_size = parseInt(params.get('0') || 1, 10);\n                const bias_data_size = parseInt(params.get('1') || 0, 10);\n                blobs.weight('scale', [scale_data_size], 1);\n                blobs.weight('bias', [bias_data_size], 1);\n                break;\n            }\n            case 'Requantize': {\n                const scale_in_data_size = parseInt(params.get('0') || 1, 10);\n                const scale_out_data_size = parseInt(params.get('1') || 1, 10);\n                const bias_data_size = parseInt(params.get('2') || 0, 10);\n                blobs.weight('scale_in', [scale_in_data_size], 1);\n                blobs.weight('scale_out', [scale_out_data_size], 1);\n                blobs.weight('bias', [bias_data_size], 1);\n                break;\n            }\n            case 'InstanceNorm': {\n                const affine = parseInt(params.get('2') || 1, 10);\n                if (affine === 1) {\n                    const channels = parseInt(params.get('0') || 0, 10);\n                    blobs.weight('gamma', [channels], 1);\n                    blobs.weight('beta', [channels], 1);\n                }\n                break;\n            }\n            case 'Scale': {\n                const scale_data_size = parseInt(params.get('0') || 0, 10);\n                if (scale_data_size !== -233) {\n                    blobs.weight('scale', [scale_data_size], 1);\n                    if (params.get('1') === '1') {\n                        blobs.weight('bias', [scale_data_size], 1);\n                    }\n                }\n                break;\n            }\n            case 'Normalize': {\n                const scale_data_size = parseInt(params.get('3') || 0, 10);\n                blobs.weight('scale', [scale_data_size], 1);\n                break;\n            }\n            case 'PReLU': {\n                const num_slope = parseInt(params.get('0') || 0, 10);\n                blobs.weight('slope', [num_slope], 1);\n                break;\n            }\n            case 'Padding': {\n                const per_channel_pad_data_size = parseInt(params.get('6') || 0, 10);\n                blobs.weight('per_channel_pad_data', [per_channel_pad_data_size], 1);\n                break;\n            }\n            case 'MemoryData': {\n                const w = parseInt(params.get('0') || 0, 10);\n                const h = parseInt(params.get('1') || 0, 10);\n                const d = parseInt(params.get('11') || 0, 10);\n                const c = parseInt(params.get('2') || 0, 10);\n                const load_type = parseInt(params.get('21') || 1, 10);\n                /* eslint-disable no-negated-condition */\n                if (d !== 0) {\n                    blobs.weight('data', [w, h, d, c], load_type);\n                } else if (c !== 0) {\n                    blobs.weight('data', [w, h, c], load_type);\n                } else if (h !== 0) {\n                    blobs.weight('data', [w, h], load_type);\n                } else if (w !== 0) {\n                    blobs.weight('data', [w], load_type);\n                } else {\n                    blobs.weight('data', [1], load_type);\n                }\n                /* eslint-enable no-negated-condition */\n                break;\n            }\n            case 'GroupNorm': {\n                const affine = parseInt(params.get('3') || 1, 10);\n                if (affine === 1) {\n                    const channels = parseInt(params.get('1') || 0, 10);\n                    blobs.weight('gamma', [channels], 1);\n                    blobs.weight('beta', [channels], 1);\n                }\n                break;\n            }\n            case 'LayerNorm': {\n                const channels = parseInt(params.get('0') || 0, 10);\n                blobs.weight('gamma', [channels], 1);\n                blobs.weight('beta', [channels], 1);\n                break;\n            }\n            case 'RNN': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const weight_data_size = parseInt(params.get('1') || 0, 10);\n                const direction = parseInt(params.get('2') || 0, 10);\n                const num_directions = direction === 2 ? 2 : 1;\n                blobs.weight('weight_xc', [num_directions, num_output, weight_data_size / num_directions / num_output]);\n                blobs.weight('bias_c', [num_directions, num_output]);\n                blobs.weight('weight_hc', [num_directions, num_output, num_output]);\n                params.delete('1');\n                break;\n            }\n            case 'LSTM': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const weight_data_size = parseInt(params.get('1') || 0, 10);\n                const direction = parseInt(params.get('2') || 0, 10);\n                const num_directions = direction === 2 ? 2 : 1;\n                blobs.weight('weight_xc', [num_directions, 4, num_output, weight_data_size / num_directions / num_output / 4]);\n                blobs.weight('bias_c', [num_directions, 4, num_output]);\n                blobs.weight('weight_hc', [num_directions, 4, num_output, num_output]);\n                params.delete('1');\n                break;\n            }\n            case 'GRU': {\n                const num_output = parseInt(params.get('0') || 0, 10);\n                const weight_data_size = parseInt(params.get('1') || 0, 10);\n                const direction = parseInt(params.get('2') || 0, 10);\n                const num_directions = direction === 2 ? 2 : 1;\n                blobs.weight('weight_xc', [num_directions, 3, num_output, weight_data_size / num_directions / num_output / 3]);\n                blobs.weight('bias_c', [num_directions, 4, num_output]);\n                blobs.weight('weight_hc', [num_directions, 3, num_output, num_output]);\n                params.delete('1');\n                break;\n            }\n            case 'MultiHeadAttention': {\n                const embed_dim = parseInt(params.get('0') || 0, 10);\n                // const num_head = parseInt(params.get('1') || 0, 10);\n                // const weight_data_size = parseInt(params.get('2') || 0, 10);\n                blobs.weight('weight_q', [embed_dim, embed_dim]);\n                blobs.weight('bias_q', [embed_dim], 1);\n                blobs.weight('weight_k', [embed_dim, embed_dim]);\n                blobs.weight('bias_k', [embed_dim], 1);\n                blobs.weight('weight_v', [embed_dim, embed_dim]);\n                blobs.weight('bias_v', [embed_dim], 1);\n                blobs.weight('weight_out', [embed_dim, embed_dim]);\n                blobs.weight('bias_out', [embed_dim], 1);\n                params.delete('2');\n                break;\n            }\n            case 'Gemm': {\n                const transA = parseInt(params.get('2') || 0, 10);\n                const transB = parseInt(params.get('3') || 0, 10);\n                const constantA = parseInt(params.get('4') || 0, 10);\n                const constantB = parseInt(params.get('5') || 0, 10);\n                const constantC = parseInt(params.get('6') || 0, 10);\n                const M = parseInt(params.get('7') || 0, 10);\n                const N = parseInt(params.get('8') || 0, 10);\n                const K = parseInt(params.get('9') || 0, 10);\n                const constant_broadcast_type_C = parseInt(params.get('10') || 0, 10);\n                if (constantA === 1) {\n                    blobs.weight('A', transA === 0 ? [K, M] : [M, K]);\n                }\n                if (constantB === 1) {\n                    blobs.weight('B', transB === 1 ? [N, K] : [K, N]);\n                }\n                if (constantC === 1 && constant_broadcast_type_C !== -1) {\n                    let shape = null;\n                    switch (constant_broadcast_type_C) {\n                        case 0: shape = [1]; break;\n                        case 1: shape = [M]; break;\n                        case 2: shape = [1, M]; break;\n                        case 3: shape = [N, M]; break;\n                        case 4: shape = [N, 1]; break;\n                        default: break;\n                    }\n                    if (shape) {\n                        blobs.weight('C', shape);\n                    }\n                }\n                break;\n            }\n            default: {\n                break;\n            }\n        }\n        if (params && params.size > 0) {\n            for (const [key, signature] of params) {\n                if (key.startsWith('@')) {\n                    const name = key.substring(1);\n                    const identifier = `${this.name}.${name}`;\n                    const data = blobs.entry(identifier);\n                    const type = ncnn.Utility.type(signature);\n                    const tensor = new ncnn.Tensor(type, data, null);\n                    const value = new ncnn.Value(identifier, null, tensor);\n                    const argument = new ncnn.Argument(name, [value]);\n                    this.inputs.push(argument);\n                    params.delete(key);\n                }\n            }\n            const attributes = Array.isArray(this.type.attributes) ? this.type.attributes : [];\n            for (const [index, obj] of params) {\n                const metadata = attributes[index];\n                let name = index;\n                let value = obj;\n                let type = '';\n                let visible = true;\n                if (metadata) {\n                    name = metadata.name;\n                    type = metadata.type ? metadata.type : type;\n                    switch (type) {\n                        case 'int32': {\n                            value = parseInt(obj, 10);\n                            break;\n                        }\n                        case 'float32': {\n                            value = parseFloat(obj);\n                            break;\n                        }\n                        case 'float32[]': {\n                            value = obj.map((v) => parseFloat(v));\n                            break;\n                        }\n                        default: {\n                            value = type ? ncnn.Utility.value(obj, type) : obj;\n                            break;\n                        }\n                    }\n                    if (metadata && metadata.visible === false) {\n                        visible = false;\n                    } else if (metadata.default !== undefined) {\n                        if (value === metadata.default || (value && value.toString() === metadata.default.toString())) {\n                            visible = false;\n                        }\n                    }\n                }\n                if (!type && typeof value === 'string') {\n                    if (value === 'True') {\n                        value = true;\n                    } else if (value === 'False') {\n                        value = false;\n                    } else if (Number.isInteger(Number(value))) {\n                        value = Number(value);\n                    } else if (value.length > 3 && value.startsWith('(') && value.endsWith(')')) {\n                        const list = value.substring(1, value.length - 1).split(',').map((item) => Number(item.trim()));\n                        if (list.every((item) => Number.isInteger(item))) {\n                            value = list.map((item) => parseInt(item, 10));\n                        }\n                    }\n                }\n                const argument = new ncnn.Argument(name, value, type, visible);\n                this.attributes.push(argument);\n            }\n        }\n    }\n};\n\nncnn.Tensor = class {\n\n    constructor(type, values, quantization) {\n        this.type = type;\n        this.values = values;\n        this.quantization = quantization;\n    }\n};\n\nncnn.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = shape;\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nncnn.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    equals(obj) {\n        return obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions) && this.dimensions.length === obj.dimensions.length && obj.dimensions.every((value, index) => Object.is(this.dimensions[index], value));\n    }\n\n    toString() {\n        return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`) : '';\n    }\n};\n\nncnn.Utility = class {\n\n    static value(value, type) {\n        ncnn.Utility._enum = ncnn.Utility._enum || new Map([\n            ['BinaryOpType', ['Add', 'Sub', 'Mul', 'Div', 'Max', 'Min', 'Pow', 'RSub', 'RDiv']],\n            ['CastOpType', ['Auto', 'Float32', 'Float16', 'Int8', 'BFloat16']],\n            ['EltwiseType', ['Prod', 'Sum', 'Max']],\n            ['PaddingType', ['Constant', 'Replicate', 'Reflect']],\n            ['PoolingType', ['Max', 'Average']],\n            ['InterpResizeType', ['', 'Nearest', 'Bilinear', 'Bicubic']],\n            ['PermuteOrderType', ['WH WHC WHDC', 'HW HWC HWDC', 'WCH WDHC', 'CWH DWHC', 'HCW HDWC', 'CHW DHWC', 'WHCD', 'HWCD', 'WCHD', 'CWHD', 'HCWD', 'CHWD', 'WDCH', 'DWCH', 'WCDH', 'CWDH', 'DCWH', 'CDWH', 'HDCW', 'DHCW', 'HCDW', 'CHDW', 'DCHW', 'CDHW']],\n            ['ReductionOpType', ['Sum', 'ASum', 'SumSq', 'Mean', 'Max', 'Min', 'Prod', 'L1', 'L2', 'LogSum', 'LogSumExp']],\n            ['UnaryOpType', ['Abs', 'Neg', 'Floor', 'Ceil', 'Square', 'Sqrt', 'Rsq', 'Exp', 'Log', 'Sin', 'Cos', 'Tan', 'ASin', 'ACos', 'ATan', 'Reciprocal', 'Tanh']]\n        ]);\n        if (ncnn.Utility._enum.has(type) && typeof value === 'string') {\n            const index = parseInt(value, 10);\n            const list = ncnn.Utility._enum.get(type);\n            if (Number.isInteger(index) && index < list.length) {\n                return list[index];\n            }\n        }\n        return value;\n    }\n\n    static type(signature) {\n        const match = signature.match(/\\(([^)]+)\\)(\\w+)/);\n        const shape = new ncnn.TensorShape(match[1].split(',').map((v) => parseInt(v, 10)));\n        const dataTypes = new Map([['f32', 'float32'], ['f16', 'float16']]);\n        const dataType = dataTypes.get(match[2]) || match[2];\n        return new ncnn.TensorType(dataType, shape);\n    }\n\n    static route(params, id) {\n        const key = `#${id}`;\n        if (params && params.has(key)) {\n            const signature = params.get(key);\n            params.delete(key);\n            return ncnn.Utility.type(signature);\n        }\n        return null;\n    }\n};\n\nncnn.TextParamReader = class {\n\n    constructor(reader) {\n        const lines = [];\n        for (let line = reader.read('\\n'); line !== undefined; line = reader.read('\\n')) {\n            line = line.trim();\n            lines.push(line);\n        }\n        const signature = lines.shift();\n        const header = (signature === '7767517' ? lines.shift() : signature).split(' ');\n        if (header.length !== 2 || !header.every((value) => value >>> 0 === parseFloat(value))) {\n            throw new ncnn.Error('Invalid header.');\n        }\n        this.layers = [];\n        while (lines.length > 0) {\n            const line = lines.shift();\n            if (line.length > 0) {\n                const columns = line.split(' ').filter((s) => s.length !== 0);\n                const type = columns.shift();\n                const name = columns.shift();\n                const inputCount = parseInt(columns.shift(), 10);\n                const outputCount = parseInt(columns.shift(), 10);\n                const inputs = columns.splice(0, inputCount);\n                const outputs = columns.splice(0, outputCount);\n                const params = new Map();\n                let index = 0;\n                for (const column of columns) {\n                    const parts = column.split('=');\n                    if (parts.length > 2) {\n                        throw new ncnn.Error(`Invalid attribute '${column}'.`);\n                    }\n                    let key = (parts.length === 2) ? parts[0].trim() : index.toString();\n                    let value = (parts.length === 2) ? parts[1].trim() : parts[0].trim();\n                    const keyInt = parseInt(key, 10);\n                    if (keyInt < 0) {\n                        value = value.split(',').map((v) => v.trim());\n                        value.shift();\n                        key = (-(keyInt + 23300)).toString();\n                    }\n                    params.set(key, value);\n                    index++;\n                }\n                this.layers.push({ type, name, inputs, outputs, params });\n            }\n        }\n    }\n};\n\nncnn.BinaryParamReader = class {\n\n    constructor(buffer) {\n        const reader = base.BinaryReader.open(buffer);\n        if (reader.int32() !== 0x007685dd) {\n            throw new ncnn.Error('Invalid signature.');\n        }\n        const layerCount = reader.int32();\n        /* const blobCount = */ reader.int32();\n        this.layers = [];\n        for (let i = 0; i < layerCount; i++) {\n            const type = reader.int32();\n            const name = i.toString();\n            const inputs = new Array(reader.int32());\n            const outputs = new Array(reader.int32());\n            for (let j = 0; j < inputs.length; j++) {\n                inputs[j] = reader.int32().toString();\n            }\n            for (let j = 0; j < outputs.length; j++) {\n                outputs[j] = reader.int32().toString();\n            }\n            const params = new Map();\n            let id = reader.int32();\n            while (id !== -233) {\n                const isArray = id <= -23300;\n                if (isArray) {\n                    id = -id - 23300;\n                }\n                const key = id.toString();\n                if (isArray) {\n                    const length = reader.int32();\n                    const values = [];\n                    for (let i = 0; i < length; i++) {\n                        values.push(reader.int32());\n                    }\n                    params.set(key, values);\n                } else {\n                    const value = reader.int32();\n                    params.set(key, value);\n                }\n                id = reader.int32();\n            }\n            this.layers.push({ type, name, inputs, outputs, params });\n        }\n    }\n};\n\nncnn.BlobReader = class {\n\n    static async open(context) {\n        let identifier = null;\n        let entries = new Map();\n        let buffer = null;\n        let position = 0;\n        if (context) {\n            identifier = context.identifier;\n            if (identifier.toLowerCase().endsWith('.pnnx.bin')) {\n                const content = await context.peek('zip');\n                if (content instanceof Map) {\n                    entries = content;\n                }\n            } else {\n                buffer = context.stream.peek();\n                position = 0;\n            }\n        }\n        return new ncnn.BlobReader(identifier, entries, buffer, position);\n    }\n\n    constructor(identifier, entries, buffer, position) {\n        this._identifier = identifier;\n        this._entries = entries;\n        this._buffer = buffer;\n        this._position = position;\n    }\n\n    skip(length) {\n        this._position += length;\n        if (this._position > this._buffer.length) {\n            throw new ncnn.Error('Unexpected end of file.');\n        }\n    }\n\n    read(length) {\n        const position = this._position;\n        this.skip(length);\n        return this._buffer.subarray(position, this._position);\n    }\n\n    align(size) {\n        const remainder = this._position % size;\n        if (remainder !== 0) {\n            this.skip(size - remainder);\n        }\n    }\n\n    load(shape, type) {\n        if (!this._buffer) {\n            return null;\n        }\n        const size = shape.reduce((a, b) => a * b, 1);\n        if (type === 0) {\n            const buffer = this.read(4);\n            const [f0, f1, f2, f3] = buffer;\n            const flag = (f0 | f1 << 8 | f2 << 16 | f3 << 24) >>> 0;\n            // https://github.com/Tencent/ncnn/blob/master/src/modelbin.cpp\n            if (flag === 0x01306B47) { // float16\n                const data = this.read(size * 2);\n                this.align(4);\n                return { dataType: 'float16', data };\n            } else if (flag === 0x000D4B38) { // int8\n                const data = this.read(size);\n                this.align(4);\n                return { dataType: 'int8', data };\n            } else if (flag === 0x00000001) { // qint8\n                // this.skip(size + 1024);\n                // data = null;\n                // return { dataType: 'qint8', data };\n                throw new ncnn.Error(\"Unsupported weight type '0x00000001'.\");\n            } else if (flag === 0x0002C056) {\n                // size * sizeof(float) - raw data with extra scaling\n                throw new ncnn.Error(\"Unsupported weight type '0x0002C056'.\");\n            } else if (flag === 0x00000000) { // float32\n                const data = this.read(size * 4);\n                return { dataType: 'float32', data };\n            } else {\n                const size = shape.reduce((a, b) => a * b, 1);\n                const buffer = this.read(1024);\n                const quantization = {\n                    type: 'lookup',\n                    value: Array.from(new Float32Array(buffer.buffer, buffer.bufferOffset, buffer.length / 4))\n                };\n                const data = this.read(size);\n                this.align(4);\n                return { dataType: 'uint8', data, quantization };\n            }\n        } else if (type === 1) {\n            const data = this.read(size * 4);\n            return { dataType: 'float32', data };\n        }\n        throw new ncnn.Error(`Load type '${type}' not supported.`);\n    }\n\n    validate() {\n        const files = [\n            ['encoder_jit_trace-pnnx.ncnn.bin', 139191256]\n        ];\n        if (this._buffer && this._buffer.length !== this._position &&\n            !this._identifier.toLowerCase().endsWith('.pnnx.bin') &&\n            !files.find((file) => file[0] === this._identifier && file[1] === this._buffer.length)) {\n            throw new ncnn.Error('Invalid weights data size.');\n        }\n    }\n\n    entry(identifier) {\n        if (this._entries && this._entries.has(identifier)) {\n            const reader = this._entries.get(identifier);\n            return reader.peek();\n        }\n        return null;\n    }\n};\n\npnnx.Metadata = class {\n\n    static async open(context) {\n        if (!pnnx.Metadata._metadata) {\n            let data = null;\n            try {\n                data = await context.request('pytorch-metadata.json');\n            } catch {\n                // continue regardless of error\n            }\n            pnnx.Metadata._metadata = new pnnx.Metadata(data);\n        }\n        return pnnx.Metadata._metadata;\n    }\n\n    constructor(data) {\n        this._types = new Map();\n        this._attributes = new Map();\n        this._index = new Map();\n        if (data) {\n            const items = JSON.parse(data);\n            for (const item of items) {\n                item.name = item.name.replace(/^torch\\.nn\\.modules\\.(\\w)+\\./, 'nn.');\n                const match = item.name.match(/^aten::([a-z_]+)/);\n                if (match) {\n                    const name = match[1];\n                    if (item.category) {\n                        if (!this._types.has(`torch.${name}`)) {\n                            this._types.set(`torch.${name}`, { name: `torch.${name}`, category: item.category });\n                        }\n                        if (!this._types.has(`F.${name}`)) {\n                            this._types.set(`F.${name}`, { name: `F.${name}`, category: item.category });\n                        }\n                    }\n                }\n                this._types.set(item.name, { name: item.name, category: item.category });\n            }\n        }\n    }\n\n    type(name) {\n        if (!this._types.has(name)) {\n            this._types.set(name, { name: name.toString() });\n        }\n        return this._types.get(name);\n    }\n\n    attribute(type, name) {\n        const key = `${type}:${name}`;\n        if (!this._attributes.has(key)) {\n            this._attributes.set(key, null);\n            const metadata = this.type(type);\n            if (metadata) {\n                if (metadata.inputs) {\n                    for (const input of metadata.inputs) {\n                        this._attributes.set(`${type}:${input.name}`, input);\n                    }\n                }\n                if (metadata.attributes) {\n                    for (const attribute of metadata.attributes) {\n                        this._attributes.set(`${type}:${attribute.name}`, attribute);\n                    }\n                }\n            }\n        }\n        return this._attributes.get(key);\n    }\n};\n\nncnn.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading ncnn model.';\n    }\n};\n\nexport const ModelFactory = ncnn.ModelFactory;\n"
  },
  {
    "path": "source/nnabla-metadata.json",
    "content": "[\n  {\n    \"name\": \"Affine\",\n    \"description\": \"Affine layer, also called as the fully connected layer. It calculates:\\n\\n.. math::\\n    {\\\\mathbf y} = {\\\\mathbf A} {\\\\mathbf x} + {\\\\mathbf b}.\\n\\nwhere :math:`{\\\\mathbf x}` is the input and :math:`{\\\\mathbf y}` is the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape (:math:`M_0 \\\\times ... \\\\times M_{B-1} \\\\times D_B \\\\times ... \\\\times D_N`). Dimensions before and after base_axis are flattened as if it is a matrix.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight matrix with shape (:math:`(D_B \\\\times ... \\\\times D_N) \\\\times L_{0} \\\\times \\\\ldots \\\\times L_{I}`)\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`L_{0} \\\\times \\\\ldots \\\\times L_{I}`)\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Base axis of Affine operation. Dimensions up to base_axis is treated as sample dimension.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1)`-D array. (:math:`M_0 \\\\times ... \\\\times M_{B-1} \\\\times L_{0} \\\\times \\\\ldots \\\\times L_{I}`)\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"RNN\",\n    \"description\": \"RNN function implements Elman RNN with nonlinearity to input sequence.\\nRNN function is defined as following:\\n\\n.. math::\\n    {\\\\mathbf h_t} = {\\\\mathbf \\\\tanh}( {\\\\mathbf w_{ih}} *{\\\\mathbf x_t} + {\\\\mathbf b_{ih}} + {\\\\mathbf w_{hh}}* {\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_{hh}}).\\n\\nWe use the following notations to describe the inputs and outputs below.\\n:math:`T`: sequcne length, :math:`B`: batch size, :math:`I`: input size, :math:`L`: number of layers, :math:`D`: number of directions, can be either 1 or 2, :math:`H`: hidden size.\\n\\nReferences:\\n    * `Jeffrey Elman, Finding Structure in Time. <https://crl.ucsd.edu/~elman/Papers/fsit.pdf>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(T, B, I)`.\"\n      },\n      {\n        \"name\": \"h\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(L, D, B, H)`.\"\n      },\n      {\n        \"name\": \"weight_l0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(D, H, I + H)`.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Input N-D array with shape :math:`(L-1, D, H, D * H + H)`.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Input N-D array with shape :math:`(L, D, H)`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"num_layers\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of layers in the network. If set to 1, only the weights for the first layer will be invoked. Default is 1.\"\n      },\n      {\n        \"name\": \"nonlinearity\",\n        \"type\": \"string\",\n        \"default\": \"tanh\",\n        \"description\": \"Type of nonlinearity applied to input sequcne. Must be either tanh or relu. Default is tanh.\"\n      },\n      {\n        \"name\": \"dropout\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Dropout ratio applied to parameters. Default is 0.0.\"\n      },\n      {\n        \"name\": \"bidirectional\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, bidirectional computation will be performed in each layer. Default is False.\"\n      },\n      {\n        \"name\": \"training\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Backpropagation will be performed only when it is true. Default is True.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`y` with shape :math:`(T, B, D * H)`\"\n      },\n      {\n        \"name\": \"h_n\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`h_n` with shape :math:`(L, D, B, H)`\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"LSTM\",\n    \"description\": \"N-Step LSTM layer.\\n\\n.. math::\\n    {\\\\mathbf f_t} &=& {\\\\mathbf \\\\sigma}( {\\\\mathbf W_f} *{\\\\mathbf x_t} + {\\\\mathbf U_f}* {\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_f})\\\\\\\\\\n    {\\\\mathbf i_t} &=& {\\\\mathbf \\\\sigma}( {\\\\mathbf W_i} *{\\\\mathbf x_t} + {\\\\mathbf U_i}* {\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_i})\\\\\\\\\\n    {\\\\mathbf o_t} &=& {\\\\mathbf \\\\sigma}( {\\\\mathbf W_o} *{\\\\mathbf x_t} + {\\\\mathbf U_o}* {\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_o})\\\\\\\\\\n    {\\\\mathbf c_t} &=& {\\\\mathbf f_t}\\\\odot {\\\\mathbf c_{(t-1)}} + {\\\\mathbf i_t}\\\\odot {\\\\mathbf \\\\tanh}({\\\\mathbf W_c}*{\\\\mathbf x_t} + {\\\\mathbf U_c} *{\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_c})\\\\\\\\\\n    {\\\\mathbf h_t} &=& {\\\\mathbf o_t} \\\\odot {\\\\mathbf \\\\tanh}({\\\\mathbf c_t}).\\n\\nWe use the following notations to describe the inputs and outputs below.\\n:math:`T`: sequcne length, :math:`B`: batch size, :math:`I`: input size, :math:`L`: number of layers, :math:`D`: number of directions, can be either 1 or 2, :math:`H`: hidden size.\\n\\nReferences:\\n    * `S. Hochreiter and J. Schmidhuber, Long Short-Term Memory. <https://www.bioinf.jku.at/publications/older/2604.pdf>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(T, B, I)`.\"\n      },\n      {\n        \"name\": \"h\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(L, D, B, H)`.\"\n      },\n      {\n        \"name\": \"c\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(L, D, B, H)`.\"\n      },\n      {\n        \"name\": \"weight_l0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"weight parameters for the first layer. Shape is :math:`(D, 4, H, I + H)`.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"weight parameters for the second layer and above. Shape is :math:`(L-1, D, 4, H, D * H + H)`.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`L`). Shape is :math:`(L, D, 4, H)`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"num_layers\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of layers in the network. If set to 1, only the weights for the first layer will be invoked. Default is 1.\"\n      },\n      {\n        \"name\": \"dropout\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Dropout ratio applied to parameters. Default is 0.0.\"\n      },\n      {\n        \"name\": \"bidirectional\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, bidirecitonal computation will be performed in each layer. Default is False.\"\n      },\n      {\n        \"name\": \"training\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Backpropagation will be performed only when it is True. Default is True.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`y` with shape :math:`(T, B, D * H)`. Its memory layout can be reshaped as :math:`(T, B, D, H)`.\"\n      },\n      {\n        \"name\": \"h_n\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`h_n` with shape :math:`(L, D, B, H)`\"\n      },\n      {\n        \"name\": \"c_n\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`c_n` with shape :math:`(L, D, B, H)`\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"GRU\",\n    \"description\": \"N-Step GRU layer.\\n\\n.. math::\\n    {\\\\mathbf r_t} &=& {\\\\mathbf \\\\sigma}( {\\\\mathbf W_r} *{\\\\mathbf x_t} + {\\\\mathbf U_r}* {\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_r})\\\\\\\\\\n    {\\\\mathbf z_t} &=& {\\\\mathbf \\\\sigma}( {\\\\mathbf W_z} *{\\\\mathbf x_t} + {\\\\mathbf U_z}* {\\\\mathbf h_{(t-1)}} + {\\\\mathbf b_z})\\\\\\\\\\n  {\\\\mathbf n_t} &=& {\\\\mathbf \\\\tanh}( {\\\\mathbf W_n}{\\\\mathbf x_t}+ {\\\\mathbf b_{in}}+ {\\\\mathbf r_n}\\\\odot( {\\\\mathbf U_n}{\\\\mathbf h_{t-1}}+ {\\\\mathbf b_{hn}})) \\\\\\\\\\n  {\\\\mathbf h_t} &=& (1- {\\\\mathbf z_t})\\\\odot {\\\\mathbf n_t} + {\\\\mathbf z_t}\\\\odot {\\\\mathbf h_{t-1}}.\\n\\nWe use the following notations to describe the inputs and outputs below.\\n:math:`T`: sequcne length, :math:`B`: batch size, :math:`I`: input size, :math:`L`: number of layers, :math:`D`: number of directions, can be either 1 or 2, :math:`H`: hidden size.\\n\\nReferences:\\n\\n    * `K. cho et al., Learning Phrases Representations using RNN Encoder-Decoder for Statistical Machine Translation. <https://www.aclweb.org/anthology/D14-1179>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(T, B, I)`.\"\n      },\n      {\n        \"name\": \"h\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(L, D, B, H)`.\"\n      },\n      {\n        \"name\": \"weight_l0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"weight parameters for the first layer. Shape is :math:`(D, 3, H, I + H)`.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"weight parameters for the second layer and above. Shape is :math:`(L-1, D, 3, H, D * H + H)`.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`L`). Shape is :math:`(L, D, 4, H)`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"num_layers\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of layers in the network. If set to 1, only the weights for the first layer will be invoked. Default is 1.\"\n      },\n      {\n        \"name\": \"dropout\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Dropout ratio applied to parameters. Default is 0.0.\"\n      },\n      {\n        \"name\": \"bidirectional\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, bidirecitonal computation will be performed in each layer. Default is False.\"\n      },\n      {\n        \"name\": \"training\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Backpropagation will be performed only when it is True. Default is True.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`y` with shape :math:`(T, B, D * H)`. Its memory layout can be reshaped as :math:`(T, B, D, H)`.\"\n      },\n      {\n        \"name\": \"h_n\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output :math:`h_n` with shape :math:`(L, D, B, H)`\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Convolution\",\n    \"description\": \"N-D Convolution with bias.\\n\\nSee references for dilated convolution (a.k.a. atrous convolution).\\n\\nReferences:\\n\\n    * `Chen et al., DeepLab: Semantic Image Segmentation with Deep Convolutional\\n      Nets, Atrous Convolution, and Fully Connected CRFs.\\n      <https://arxiv.org/abs/1606.00915>`_\\n\\n    * `Yu et al., Multi-Scale Context Aggregation by Dilated Convolutions.\\n      <https://arxiv.org/abs/1511.07122>`_\\n\\nNote:\\n\\n  Convolution is a computationally intensive operation that\\n  should preferrably be run with the `cudnn` backend. NNabla\\n  then uses CuDNN library functions to determine and cache the\\n  fastest algorithm for the given set of convolution parameters,\\n  which results in additional memory consumption which may pose\\n  a problem for GPUs with insufficient memory size. In that\\n  case, the `NNABLA_CUDNN_WORKSPACE_LIMIT` environment variable\\n  can be used to restrict the choice of algorithms to those that\\n  fit the given workspace memory limit, expressed in bytes. In\\n  some cases it may also be desired to restrict the automatic\\n  search to algorithms that produce deterministic (reproducable)\\n  results. This can be requested by setting the the environment\\n  variable `NNABLA_CUDNN_DETERMINISTIC` to a non-zero value.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C \\\\times L_1 \\\\times ... \\\\times L_N`).\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(2 + N)`-D array (:math:`C' \\\\times C \\\\times K_1 \\\\times ... \\\\times K_N`).\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`C'`).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"base axis :math:`B`.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of groups of channels. This makes the connection across channels sparser, by grouping connections along the mapping direction.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C' \\\\times L'_1 \\\\times ... \\\\times L'_N`).\\n\\nA spatial size of the output is calculated as\\n\\n.. math::\\n\\n  L'_i = \\\\frac{L_i + 2 p_i - d_i (k_i - 1) - 1}{s_i} + 1,\\n\\nwhere :math:`L_i` is the spatial size, :math:`p_i` is the padding, :math:`d_i` is the dilation, :math:`k_i` is the kernel size, and :math:`s_i` is the stride for :math:`i`-th spatial dimension. The same calculation can also be applied to the other spatial dimensions.\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"FusedConvolution\",\n    \"description\": \"Fused operation of Pad, Convolution, Batch Normalization, Add2 and Activation.\\n\\nThis is an equivalent operation to the following,\\nbut may be more computationally efficient depending on the backend implementation\\n(currently we don't provide an efficient implementation on any backend).\\n\\n.. code-block:: python\\n\\n  h = F.pad(x, *pad_opts)\\n  h = F.convolution(h, weight, bias, pad=(0, ...), *conv_opts)\\n  h = F.batch_normalization(h, beta, gamma, mean, variance, *bn_opts)\\n  y = F.relu(h + z)\\n\\nYou can optionally disable either of pad, batch normalization, residual addition and activation.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"`weight` in :meth:`~nnabla.functions.convolution`.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"`bias` in :meth:`~nnabla.functions.convolution`.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"`beta` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"`gamma` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"mean\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"`mean` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"variance\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"`variance` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"z\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of a residual input. By specifying None, the activation function will follow immediately after BN operation.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"`base_axis` in :meth:`~nnabla.functions.convolution`. Note that the batch normalization `axes` is determined by this and `channel_last` option.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"`pad_width` in :meth:`~nnabla.functions.pad`.\\nIf `len(pad) == (len(x.shape) - (base_axis+1))`, considered as `pad` in :meth:`~nnabla.functions.convolution`.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"`stride` in :meth:`~nnabla.functions.convolution`.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"`dilation` in :meth:`~nnabla.functions.convolution`.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"`group` in :meth:`~nnabla.functions.convolution`.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"`channel_last` in :meth:`~nnabla.functions.convolution`.group\"\n      },\n      {\n        \"name\": \"decay_rate\",\n        \"type\": \"float32\",\n        \"default\": 0.9,\n        \"description\": \"`decay_rate` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"`eps` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"batch_stat\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"`batch_stat` in :meth:`~nnabla.functions.batch_normalization`.\"\n      },\n      {\n        \"name\": \"nonlinearity\",\n        \"type\": \"string\",\n        \"default\": \"relu\",\n        \"description\": \"Activation type as string. The following is a list of available activation types\\nand optional parameters specified as a vector of float by `nonlinearity_args`.\\n\\n=============== ===============================\\nActivation type Arguments (`nonlinearity_args`)\\n=============== ===============================\\nidentity        No argument\\nrelu            No argument\\nsigmoid         No argument\\ntanh            No argument\\nleaky_relu      [alpha] (see LeakyReLU doc)\\nelu             [alpha] (see ELU doc)\\nrelu6           No argument\\n=============== ===============================\"\n      },\n      {\n        \"name\": \"nonlinearity_args\",\n        \"type\": \"float32[]\",\n        \"default\": \"list()\",\n        \"description\": \"Optional arguments of nonlinearity as a vector of float.\\nSee the description of the `nonlinearity` argument.\"\n      },\n      {\n        \"name\": \"pad_mode\",\n        \"type\": \"string\",\n        \"default\": \"constant\",\n        \"description\": \"`mode` in :meth:`~nnabla.functions.pad`.\"\n      },\n      {\n        \"name\": \"constant_value\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"`constant_value` in :meth:`~nnabla.functions.pad`.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"DepthwiseConvolution\",\n    \"description\": \"N-D Depthwise Convolution with bias.\\n\\nReferences:\\n\\n    * `F. Chollet. Xception: Deep Learning with Depthwise Separable Convolutions.\\n      <https://arxiv.org/abs/1610.02357>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C \\\\times L_1 \\\\times ... \\\\times L_N`).\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(1 + N)`-D array (:math:`C \\\\times K_1 \\\\times ... \\\\times K_N`).\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`C'`).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"base axis :math:`B`.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"multiplier\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of output feature maps per input feature map.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C' \\\\times L'_1 \\\\times ... \\\\times L'_N`).\\n\\nThe output map size :math:`C'` is :math:`C` multiplied by :math:`m`\\n\\n.. math::\\n\\n  C' =  m \\\\times C,\\n\\nwhere :math:`m` is the multiplier.\\n\\nA spatial size of the output is calculated as\\n\\n.. math::\\n\\n  L'_i = \\\\frac{L_i + 2 p_i - d_i (k_i - 1) - 1}{s_i} + 1,\\n\\nwhere :math:`L_i` is the spatial size, :math:`p_i` is the padding, :math:`d_i` is the dilation, :math:`k_i` is the kernel size, and :math:`s_i` is the stride for :math:`i`-th spatial dimension. The same calculation can also be applied to the other spatial dimensions.\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"description\": \"N-D deconvolution, also known as transposed convolution, with bias operates backward convolution (derivative of the output w.r.t. the input) plus channel-wise learned bias.\\n\\nThe weights are specified in the same manner as :meth:`~nnabla.functions.convolution` , as if it was an ordinary convolution function.\\nThe forward operation of :meth:`~nnabla.functions.deconvolution` will then be operationally equivalent to the backward pass of :meth:`~nnabla.functions.convolution` .\\nTherefore, the number of input channels (can be seen as output channels of forward convolution) is specified in the first dimension, and the number of the output channels divided by the number of groups is specified in the second dimension.\\n\\nFor `stride > 1`, a parameter-wise identical deconvolution on the output\\nof a convolution may not produce the same output shape as the input to\\nthe convolution if, due to striding, the convolution did not fully cover\\nthe input spatial dimension. The `output_padding` parameter can then be\\nused to appropriately increase the calculated output shape. Note that\\nthis is used to find the output shape for the deconvolution operation,\\nbut not to add zero-padding to the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C \\\\times L_1 \\\\times ... \\\\times L_N`).\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(2 + N)`-D array (:math:`C \\\\times C' \\\\times K_1 \\\\times ... \\\\times K_N`).\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`C'`).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"base axis :math:`B`.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of groups of channels. This makes the connection across channels sparser, by grouping connections along the mapping direction.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      },\n      {\n        \"name\": \"output_padding\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Additional size added to the output shape.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C' \\\\times L'_1 \\\\times ... \\\\times L'_N`).\\n\\nA spatial size of the output is calculated as\\n\\n.. math::\\n\\n  L'_i =s_i (L_i - 1) - 2 p_i + d_i (k_i - 1) + 1,\\n\\nwhere :math:`s_i` is the stride, :math:`L_i` is the spatial size, :math:`p_i` is the padding, :math:`d_i` is the dilation, and :math:`k_i` is the kernel size for :math:`i`-th spatial dimension. The same calculation can also be applied to the other spatial dimensions.\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"DepthwiseDeconvolution\",\n    \"description\": \"Depthwise deconvolution computes the transposed depthwise convolution with bias for one-dimensional and two-dimensional input data.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C \\\\times L_1 \\\\times ... \\\\times L_N`).\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(1 + N)`-D array (:math:`C \\\\times K_1 \\\\times ... \\\\times K_N`).\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`C'`).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"base axis :math:`B`.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"divisor\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of input feature maps per output feature map.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C' \\\\times L'_1 \\\\times ... \\\\times L'_N`).\\n\\nThe output map size :math:`C'` is :math:`C` multiplied by :math:`m`\\n\\n.. math::\\n\\n  C' =  \\\\frac{C}{d},\\n\\nwhere :math:`d` is the divisor.\\n\\nA spatial size of the output is calculated as\\n\\n.. math::\\n  L'_i =s_i (L_i - 1) - 2 p_i + d_i (k_i - 1) + 1,\\n\\nwhere :math:`s_i` is the stride, :math:`L_i` is the spatial size, :math:`p_i` is the padding, :math:`d_i` is the dilation, and :math:`k_i` is the kernel size for :math:`i`-th spatial dimension. The same calculation can also be applied to the other spatial dimensions.\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"DeformableConvolution\",\n    \"description\": \"2-D Deformable Convolution with bias.\\nAnother convolution with fixed output channels must be passed externally to calculate the offsets and mask.\\nMask should be normalized to :math:`[0,1]` interval.\\n\\n.. math::\\n  \\\\begin{eqnarray}\\n    y(p) = \\\\sum_{k=1}^{K} w_k \\\\cdot x(p + p_k + \\\\Delta p_k) \\\\cdot \\\\Delta m_k,\\n  \\\\end{eqnarray}\\n\\nwhere :math:`x` and :math:`y` are input and output, :math:`w_k` is the weight, :math:`p` is the pixel location of interest, :math:`p_k` is the fixed displacement e.g., :math:`p_k \\\\in \\\\{(-1, -1), (-1, 0), \\\\ldots (1, 1)\\\\}` for the 2D 3x3 receptive field, :math:`\\\\Delta p_k` is the learnable displacement, and :math:`\\\\Delta m_k` is the learnable scale normalized in :math:`[0, 1]` by a function like the sigmoid. Note that :math:`\\\\Delta p_k` and :math:`\\\\Delta m_k` are sample-dependent, location-dependent, and feature-independent.\\n\\nReferences:\\n\\n    * `Dai et al., Deformable Convolutional Networks.\\n      <https://arxiv.org/abs/1703.06211>`_\\n\\n    * `Zhu et al., Deformable ConvNets v2: More Deformable, Better Results.\\n      <https://arxiv.org/abs/1811.11168>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C \\\\times L_1 \\\\times ... \\\\times L_N`).\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(2 + N)`-D array (:math:`C' \\\\times C \\\\times K_1 \\\\times ... \\\\times K_N`).\"\n      },\n      {\n        \"name\": \"offset\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Offsets for deformable convolutions. Shape is fixed to :math:`(N, deformable{\\\\_}group \\\\times 2 \\\\times Kh \\\\times Kw, H, W)`. Offsets must be calculated externally through a separate convolution layer.\"\n      },\n      {\n        \"name\": \"mask\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Normalized mask for deformable convolutions v2. Shape is fixed to :math:`(N, deformable{\\\\_}group \\\\times Kh \\\\times Kw, H, W)`. Masks must be calculated externally together with the offsets through a separate convolution layer.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias vector (:math:`C'`).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"base axis :math:`B`.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of groups of channels. This makes the connection across channels sparser, by grouping connections along the mapping direction.\"\n      },\n      {\n        \"name\": \"deformable_group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of deformable groups of channels.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`(B + 1 + N)`-D array (:math:`M_1 \\\\times ... \\\\times M_B \\\\times C' \\\\times L'_1 \\\\times ... \\\\times L'_N`).\\n\\nA spatial size of the output is calculated as\\n\\n.. math::\\n\\n  L'_i = \\\\frac{L_i + 2 p_i - d_i (k_i - 1) - 1}{s_i} + 1,\\n\\nwhere :math:`L_i` is the spatial size, :math:`p_i` is the padding, :math:`d_i` is the dilation, :math:`k_i` is the kernel size, and :math:`s_i` is the stride for :math:`i`-th spatial dimension. The same calculation can also be applied to the other spatial dimensions.\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"AdaptiveSeparableConvolution\",\n    \"description\": \"2-D Adaptive Separable Convolution for NCHW (the channel-first tensor).\\nSample and pixel dependent vertical and horizontal kernels are dynamically generated ones,\\nwhich are used for approximating a feature-independent 2-D kernel in this function.\\nThus, the kernel used in this function is dependent on samples and pixels but independent on features.\\n\\nIf the padding is needed, use the pad function to the input :math:`x` before this function.\\n\\nAdaptive separable convolution is formulated as\\n\\n.. math::\\n\\n  \\\\tilde{I}(c, h, w) = \\\\sum_{j, i} K_v(j, h, w) \\\\times K_h(i, h, w) \\\\times I(c, h + j, w + i),\\n\\nwhere :math:`I(c, h, w)` and :math:`\\\\tilde{I}(c, h, w)` are the input and output images\\nat :math:`c`-th channel, :math:`h`-th height, :math:`w`-th width.\\n:math:`K_V(:, h, w)` and :math:`K_h(:, h, w)` are vertical and horizontal 1-D kernels\\nat :math:`h`-th height and :math:`w`-th width.\\n\\nReferences:\\n\\n    * `Simon Niklaus, Long Mai, Feng Liu,\\n      Video Frame Interpolation via Adaptive Separable Convolution,\\n      <https://arxiv.org/abs/1708.01692>`_\\n\\n    * `Mart Kartasev, Carlo Rapisarda, Dominik Fay,\\n      Implementing Adaptive Separable Convolution for Video Frame Interpolation,\\n      <https://arxiv.org/abs/1809.07759>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`4-D` array (:math:`B \\\\times C \\\\times H \\\\times W`)\"\n      },\n      {\n        \"name\": \"vertical_kernel\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`4-D` array (:math:`B \\\\times K_v \\\\times H \\\\times W`)\"\n      },\n      {\n        \"name\": \"horizontal_kernel\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`4-D` array (:math:`B \\\\times K_h \\\\times H \\\\times W`)\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \":math:`4-D` array (:math:`B \\\\times C \\\\times H - K_v + 1 \\\\times W - K_h + 1`)\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"MaxPooling\",\n    \"description\": \"Max pooling. It pools the maximum values inside the scanning kernel:\\n\\n.. math::\\n    y_{i_1, i_2} = \\\\max_{k_1, k_2 \\\\in K} (x_{i_1 + k_1, i_2 + k_2})\\n\\nwhere :math:`x_{i_1 + k_1, i_2 + k_2}` is the input and :math:`y_{i_1, i_2}` is the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Kernel sizes for each spatial axis.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"kernel\",\n        \"description\": \"Subsampling factors for each spatial axis.\"\n      },\n      {\n        \"name\": \"ignore_border\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If false, kernels covering borders are also considered for the output.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * len(kernel)\",\n        \"description\": \"Border padding values for each spatial axis. Padding will be added both sides of the dimension.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Maximum values variable\"\n      }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"AveragePooling\",\n    \"description\": \"Average pooling. It pools the averaged values inside the scanning kernel:\\n\\n.. math::\\n    y_{i_1, i_2} = \\\\frac{1}{K_1 K_2} \\\\sum_{k1} \\\\sum_{k2} x_{i_1 + k_1, i_2 + k_2}\\n\\nwhere :math:`x_{i_1 + k_1, i_2 + k_2}` is the input and :math:`y_{i_1, i_2}` is the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Kernel sizes for each spatial axis.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"kernel\",\n        \"description\": \"Subsampling factors for each spatial axis.\"\n      },\n      {\n        \"name\": \"ignore_border\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If false, kernels covering borders are also considered for the output.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * len(kernel)\",\n        \"description\": \"Border padding values for each spatial axis. Padding will be added both sides of the dimension.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      },\n      {\n        \"name\": \"including_pad\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If true, border padding values are considered for the output.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Average values variable\"\n      }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"GlobalAveragePooling\",\n    \"description\": \".. WARNING::\\n  This function is experimental support, so please do not actively use it.\\n\\nGlobal average pooling. It pools an averaged value from the whole image\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Average values variable\"\n      }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"SumPooling\",\n    \"description\": \"Sum pooling. It pools the summed values inside the scanning kernel:\\n\\n.. math::\\n    y_{i_1, i_2} = \\\\sum_{k1} \\\\sum_{k2} x_{i_1 + k_1, i_2 + k_2}\\n\\nwhere :math:`x_{i_1 + k_1, i_2 + k_2}` is the input and :math:`y_{i_1, i_2}` is the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Kernel sizes for each spatial axis.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"kernel\",\n        \"description\": \"Subsampling factors for each spatial axis.\"\n      },\n      {\n        \"name\": \"ignore_border\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If false, kernels covering borders are also considered for the output.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * len(kernel)\",\n        \"description\": \"Border padding values for each spatial axis. Padding will be added both sides of the dimension.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Summed values variable\"\n      }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"Unpooling\",\n    \"description\": \"Inverse operation of pooling. It spreads the input values:\\n\\n.. math::\\n    y_{k_1 i_1 + j_1, k_2 i_2 + j_2} = x_{i_1, i_2}\\n\\nwhere :math:`_{i_1, i_2}` is the input and :math:`y_{k_1 i_1 + j_1, k_2 i_2 + j_2}` is the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Kernel sizes for each spatial axis.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Spread values variable\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Embed\",\n    \"description\": \"Embed slices of a matrix/tensor with indexing array/tensor.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Indices with shape :math:`(I_0, ..., I_N)`\"\n      },\n      {\n        \"name\": \"w\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weights with shape :math:`(W_0, ..., W_M)`\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output with shape :math:`(I_0, ..., I_N, W_1, ..., W_M)`\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"RoiAlign\",\n    \"description\": \"Map Regions of Interest (RoI) defined by bounding `boxes` to features\\n  of `output_size` height and width using bilinear interpolation with\\n  `sampling_ratio` points in the interpolation grid.\\n\\n  >>> import numpy as np, nnabla as nn, nnabla.functions as F\\n  >>> nn.set_auto_forward(True)\\n  >>> input = F.pad(F.constant(1, (1, 1, 2, 2)) * 2, (1, 1, 1, 1), \\\"constant\\\", 1)\\n  >>> print(input.d)\\n  [[[[1. 1. 1. 1.]\\n     [1. 2. 2. 1.]\\n     [1. 2. 2. 1.]\\n     [1. 1. 1. 1.]]]]\\n  >>> boxes = nn.Variable.from_numpy_array([[0, 0, 0, 4, 4], [0, 1, 1, 3, 3]])\\n  >>> output = F.roi_align(input, boxes, (2, 2))\\n  >>> print(output.d[0])\\n  [[[[1.25 1.25]\\n     [1.25 1.25]]]\\n  >>> print(output.d[1])\\n  [[[2.   2.  ]\\n    [2.   2.  ]]]]\\n\\n  The `spatial_scale` argument tuple may be used to appropriately scale\\n  the box coordinates, for example, to scale normalized box coordinate to\\n  the input height and width dimensions.\\n\\n  >>> input = F.reshape(F.arange(1, 13), (1, 1, 3, 4))\\n  >>> print(input.d)\\n  >>> boxes = nn.Variable.from_numpy_array([[0, 1/4, 1/3, 3/4, 2/30]])\\n  >>> output = F.roi_align(input, boxes, (1, 2), spatial_scale=(3, 4))\\n  >>> print(input.d)\\n  [[[[6. 7.]]]]\\n\\n  References:\\n\\n      * `He et al., Mask R-CNN. <https://arxiv.org/abs/1703.06870v3>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"input\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape :math:`(N, H, W, C)` or :math:`(N, C, H, W)`.\"\n      },\n      {\n        \"name\": \"boxes\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape :math:`(K, 5)` containing box coordinates in (b, x1, y1, x2, y2) format where b is the batch index. Note that an invalid (out-of-range) batch index will generate an error only when running on CPU; when using a GPU context the batch index values are clipped to the range of input samples.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"output_size\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"the height and width of the output feature maps.\"\n      },\n      {\n        \"name\": \"spatial_scale\",\n        \"type\": \"float32[]\",\n        \"default\": \"(1.0, 1.0)\",\n        \"description\": \"Scaling factor from box to input coordinates, as (x, y).\"\n      },\n      {\n        \"name\": \"sampling_ratio\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"The number of sampling points used for interpolation. Computed as `ceil((y2 - y1) / output_size[0])` for height and likewise for width if `sampling_ratio <= 0`.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape :math:`(K, C, output\\\\_size[0], output\\\\_size[1])`\\nor :math:`(K, output\\\\_size[0], output\\\\_size[1], C)`.\"\n      }\n    ],\n    \"category\": \"Layer\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"description\": \"Element-wise sigmoid function.\\n\\n.. math::\\n\\n    f(x) = \\\\frac{1}{1 + \\\\exp(-x)},\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Swish\",\n    \"description\": \"Element-wise swish function, by Ramachandran et al. (2017).\\n\\n.. math::\\n\\n    y_i = \\\\frac{x_i}{1 + \\\\exp(-x_i)},\\n\\nReferences:\\n    * `Prajit Ramachandran, Barret Zoph, and Quoc V. Le, Swish: a Self-Gated Activation Function, arXiv:1710.05941 [cs.NE]\\n      <https://arxiv.org/abs/1710.05941>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Tanh\",\n    \"description\": \"Element-wise hyperbolic tangent (tanh) function.\\n\\n.. math::\\n    y_i = \\\\tanh (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ReLU\",\n    \"description\": \"Element-wise Rectified Linear Unit (ReLU) function.\\n\\n.. math::\\n    y_i = \\\\max (0, x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"LeakyReLU\",\n    \"description\": \"Element-wise Leaky Rectified Linear Unit (ReLU) function.\\n\\nIt is defined as:\\n\\n.. math::\\n    y_i = \\\\alpha * \\\\min(0, x_i) + \\\\max (0, x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"alpha\",\n        \"type\": \"float32\",\n        \"default\": 0.1,\n        \"description\": \"The slope value multiplied to negative numbers. :math:`\\\\alpha` in the definition.\"\n      },\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Softmax\",\n    \"description\": \"Softmax normalization. Calculates\\n\\n.. math::\\n    y_i = \\\\frac{\\\\exp(x_i)}{\\\\sum_j \\\\exp(x_j)}\\n\\nalong the dimension specified by `axis`, where :math:`x_i` is the input and :math:`y_i` is the output.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array. Typically indicates a score.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x.shape) - 1\",\n        \"description\": \"Axis normalization is taken.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"LogSoftmax\",\n    \"description\": \"Fused operation of Softmax normalization followed by log, which is defined as\\n\\n.. math::\\n    y_i = \\\\log \\\\frac{\\\\exp(x_i)}{\\\\sum_j \\\\exp(x_j)},\\n\\nwhere :math:`y_i` is the input and :math:`x_i` is the output at i-th channel.\\nAn advantage of this fusion is reducing the numerical instability due to the log application.\\n\\nThe original definition can be rewritten as\\n\\n.. math::\\n    y_i = x_i - \\\\max_j(x_j) - \\\\log\\\\left(\\\\sum_j \\\\exp(x_j - \\\\max_k(x_k))\\\\right).\\n\\nIt is more stable as a log is always applied to a value :math:`\\\\ge e`, while a log can be evaluated for 0 in the non-fused operation.\\n\\nAlso, backward gradient computation is more stable than the original one as it doesn't perform division by x due to a gradient of log. The definition is as following.\\n\\n.. math::\\n    dx_i = dy_i - y_i * \\\\sum_j dy_j\\n\\nwhere :math:`dx_i` and :math:`dy_i` denote gradients of loss\\nwrt :math:`x_i` and :math:`y_i` respectively.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array. Typically indicates a score.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x.shape) - 1\",\n        \"description\": \"Axis normalization is taken.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ELU\",\n    \"description\": \"Element-wise Exponential Linear Unit (ELU) function.\\n\\n.. math::\\n    y_i= \\\\left\\\\{\\n    \\\\begin{array}{ll}\\n    x_i & (x > 0)\\\\\\\\\\n    \\\\alpha (\\\\exp(x_i) - 1) & (x \\\\leq 0)\\n    \\\\end{array} \\\\right..\\n\\nReferences:\\n    * `Clevart et al., Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs).\\n      <http://arxiv.org/abs/1511.07289>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"alpha\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Coefficient for negative outputs. :math:`\\\\alpha` in definition\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SELU\",\n    \"description\": \"Element-wise Scaled Exponential Linear Unit (SELU) function by Klambauer et al. (2017).\\n\\n.. math::\\n    y_i= \\\\lambda \\\\left\\\\{\\n    \\\\begin{array}{ll}\\n    x_i & (x > 0)\\\\\\\\\\n    \\\\alpha (\\\\exp(x_i) - 1) & (x \\\\leq 0)\\n    \\\\end{array} \\\\right..\\n\\nThe coefficients :math:`\\\\lambda` and :math:`\\\\alpha` default to the following values :math:`\\\\lambda_{01}` and :math:`\\\\alpha_{01}`, respectively, provided by Klambauer et al. (2017):\\n\\n.. math::\\n    \\\\begin{array}{lll}\\n      \\\\lambda_{01} &=&  \\\\left(  1 - \\\\operatorname{erfc}\\\\left( \\\\frac{1}{\\\\sqrt{2}} \\\\right) \\\\sqrt{e}  \\\\right)\\n                  \\\\sqrt{2 \\\\pi} \\\\\\\\\\n                 && \\\\left(\\n                      2 \\\\operatorname{erfc} \\\\left( \\\\sqrt{2} \\\\right) e^2\\n                      + \\\\pi \\\\operatorname{erfc}\\\\left( \\\\frac{1}{\\\\sqrt{2}} \\\\right)^2 e\\n                      \\\\right. \\\\\\\\\\n                 && \\\\left.\\n                      - 2(2 + \\\\pi) \\\\operatorname{erfc} \\\\left( \\\\frac{1}{\\\\sqrt{2}} \\\\right) \\\\sqrt{e}\\n                      + \\\\pi + 2\\n                 \\\\right)^{-1/2}  \\\\\\\\\\n              &\\\\approx& 1.0507 \\\\\\\\\\n      \\\\alpha_{01} &=&  - \\\\frac\\n                    {\\\\sqrt {\\\\frac {2}{\\\\pi}}}\\n                    {\\\\operatorname{erfc} \\\\left( \\\\frac{1}{\\\\sqrt{2}} \\\\right) \\\\exp \\\\left(\\\\frac {1} {2} \\\\right) - 1} \\\\\\\\\\n              &\\\\approx& 1.67326\\n    \\\\end{array}\\n\\n\\nReferences:\\n    * `Klambauer, G., Unterthiner, T., Mayr, A., & Hochreiter, S. (2017).\\n      Self-Normalizing Neural Networks. In Advances in Neural Information\\n      Processing Systems (NIPS). <https://arxiv.org/abs/1706.02515>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"scale\",\n        \"type\": \"float64\",\n        \"default\": 1.05070098735548,\n        \"description\": \"The coefficient :math:`\\\\lambda` in the definition.\"\n      },\n      {\n        \"name\": \"alpha\",\n        \"type\": \"float64\",\n        \"default\": 1.673263242354377,\n        \"description\": \"The coefficient :math:`\\\\alpha` in the definition.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"CReLU\",\n    \"description\": \"Element-wise Concatenated Rectified Linear Unit (CReLU) function.\\nThis function calculates the ReLU of :math:`x` and :math:`-x` , then concatenates the results together at a specified axis,\\nand returns the resulting array.\\n\\n\\nReferences:\\n    * `Wenling Shang, Kihyuk Sohn, Diogo Almeida, Honglak Lee.\\n      Understanding and Improving Convolutional Neural Networks\\n      via Concatenated Rectified Linear Units.\\n      <https://arxiv.org/abs/1603.05201>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"The ReLU activations of positive inputs and negative inputs are concatenated at axis.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array where axis dimension is doubled by concatenating.\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"CELU\",\n    \"description\": \"Element-wise Concatenated Exponential Linear Unit (CELU) function.\\nConcatenates ELU outputs of positive and negative inputs together at specified axis.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"alpha\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Coefficient for negative outputs. :math:`\\\\alpha` in definition.\"\n      },\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"The ELU activations of positive inputs and negative inputs are concatenated at axis.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array where axis dimension is doubled by concatenating.\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"PReLU\",\n    \"description\": \"Element-wise Parametrized Rectified Linear Unit function. Calculates:\\n\\n.. math::\\n    y_i = \\\\max(0, x_i) + w_i \\\\min(0, x_i)\\n\\nwhere negative slope :math:`w` is learned and can vary across channels (an\\naxis specified with `base_axis`).\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"(N-D array) Input\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"(N-D array) Weights\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"GELU\",\n    \"description\": \"Gaussian Error Unit (GELU) function.\\n\\n.. math::\\n    GELU(x) = xP(X \\\\leq  x) = x \\\\Phi (x)\\n\\nwhich is approximated by\\n\\n.. math::\\n    GELU(x) = 0.5x (1 + \\\\tanh ( \\\\sqrt(2/\\\\pi)(x + 0.044715x^3) ))\\n\\nReferences:\\n    * `Dan Hendrycks and Kevin Gimpel.\\n      Gaussian Error Linera Units (GELUs).\\n      <https://arxiv.org/abs/1606.08415>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Mish\",\n    \"description\": \"Mish activation function.\\n\\n.. math::\\n    Mish(x) = x \\\\tanh(\\\\log(1+\\\\exp(x_i)))\\n\\n\\nReferences:\\n    * `Diganta Misra.\\n      Mish A Self Regularized Non-Monotonic Neural Activation Function.\\n      <https://arxiv.org/abs/1908.08681>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ReLU6\",\n    \"description\": \"Element-wise ReLU6 function.\\nCapping ReLU activation to 6 is often observed to learn sparse features earlier.\\n\\n.. math::\\n    ReLU6(x) = \\\\min(\\\\max(0,x,),6)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"HardSigmoid\",\n    \"description\": \"Segment-wise linear approximation of sigmoid.\\nPreferable when speed of computation is more important than precision.\\nReturns :math:`0` if :math:`x < -2.5`.\\nReturns :math:`1` if :math:`x> 2.5`.\\nReturns :math:`0.2x + 0.5` if :math:`-2.5 <= x <= 2.5`.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"HardTanh\",\n    \"description\": \"Element-wise HardTanh function.\\nComputationally cheaper than Tanh function.\\nReturns :math:`1` if :math:`x > 1`.\\nReturns :math:`-1` if :math:`x < -1`.\\nReturns :math:`x` otherwise.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"LogSigmoid\",\n    \"description\": \"Element-wise LogSigmoid function.\\n\\n.. math::\\n    LogSigmoid(x) = \\\\log(1/(1+\\\\exp(-x_i)))\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftPlus\",\n    \"description\": \"Element-wise SoftPlus function.\\nUnlike Sigmoid and Tanh that have upper and lower bound, SoftPlus is only lower-bounded by 0.\\n\\n.. math::\\n    SoftPlus(x) = \\\\frac{1}{\\\\beta} * \\\\log(1+\\\\exp(\\\\beta * x_i))\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"beta\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"the `beta` value for SoftPlus formulation\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftSign\",\n    \"description\": \"Element-wise SoftSign.\\nCan be used in place of Tanh function.\\nWhile Tanh converges exponentially, SoftSign converges polynomially.\\n\\n.. math::\\n    SoftSign(x) = x/(1+|x|)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"TanhShrink\",\n    \"description\": \"Element-wies TanhShrink function.\\n\\n.. math::\\n    TanhShrink(x) = x - \\\\tanh(x)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Sinc\",\n    \"description\": \"Element-wise Sinc function.\\nUnlike other popular activation functions, it has rises and falls.\\nreturns :math:`1` if :math:`x = 0`.\\nreturns :math:`\\\\sin(x)/x` otherwise.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"FusedBatchNormalization\",\n    \"description\": \"Batch normalization fused with add2 (adding a residual input) and activation.\\n\\nThis is an equivalent operation to the following,\\nbut is more computationally efficient:\\n\\n.. code-block:: python\\n\\n  h = F.batch_normalization(x, beta, gamma, mean, variance, *opts)\\n  y = F.relu(h + z)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      },\n      {\n        \"name\": \"mean\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of running mean (modified during forward execution).\"\n      },\n      {\n        \"name\": \"variance\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of running variance (modified during forward execution).\"\n      },\n      {\n        \"name\": \"z\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of a residual input. By specifying None, the activation function will follow immediately after BN operation.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"(1,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"decay_rate\",\n        \"type\": \"float32\",\n        \"default\": 0.9,\n        \"description\": \"Decay rate of running mean and variance.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"batch_stat\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Use mini-batch statistics rather than running ones.\"\n      },\n      {\n        \"name\": \"nonlinearity\",\n        \"type\": \"string\",\n        \"default\": \"relu\",\n        \"description\": \"Activation chosen from ('relu').\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"BatchNormalization\",\n    \"description\": \"Batch normalization.\\n\\n.. math::\\n    \\\\begin{eqnarray}\\n      \\\\mu &=& \\\\frac{1}{M} \\\\sum x_i \\\\\\\\\\n      \\\\sigma^2 &=& \\\\frac{1}{M} \\\\left(\\\\sum x_i - \\\\mu\\\\right)^2 \\\\\\\\\\n      \\\\hat{x}_i &=& \\\\frac{x_i - \\\\mu}{\\\\sqrt{\\\\sigma^2 + \\\\epsilon}} \\\\\\\\\\n      y_i &=& \\\\hat{x}_i \\\\gamma + \\\\beta.\\n    \\\\end{eqnarray}\\n\\n\\nAt testing time, the mean and variance values used are those that were computed during training by moving average.\\n\\nReferences:\\n\\n    * `Ioffe and Szegedy, Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift.\\n      <https://arxiv.org/abs/1502.03167>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      },\n      {\n        \"name\": \"mean\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of running mean (modified during forward execution).\"\n      },\n      {\n        \"name\": \"variance\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of running variance (modified during forward execution).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"(1,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"decay_rate\",\n        \"type\": \"float32\",\n        \"default\": 0.9,\n        \"description\": \"Decay rate of running mean and variance.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"batch_stat\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Use mini-batch statistics rather than running ones.\"\n      },\n      {\n        \"name\": \"no_scale\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the scale term is omitted.\"\n      },\n      {\n        \"name\": \"no_bias\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the bias term is omitted.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"GroupNormalization\",\n    \"description\": \"Applies Group Normalization over an input tensor, which is defined as:\\n\\n.. math::\\n  \\\\begin{eqnarray}\\n    \\\\mu^g &=& \\\\frac{1}{H} \\\\sum_{i=1}^{H} x_i^g \\\\\\\\\\n    \\\\sigma^g &=& \\\\sqrt{\\\\frac{1}{H} \\\\sum_{i=1}^{H} \\\\left(x_i^g - \\\\mu^g\\\\right)^2 + \\\\epsilon} \\\\\\\\\\n    y &=& \\\\frac{x - \\\\mu^g}{\\\\sigma^g} \\\\gamma + \\\\beta\\n  \\\\end{eqnarray}\\n\\nwhere :math:`x` and :math:`y` are input and output variable,\\n:math:`\\\\mu^g` and :math:`\\\\sigma^g` are the mean and std of each group which contains `num_channels / num_groups` channels,\\nand :math:`\\\\gamma` and :math:`\\\\beta` are adaptive gains and biases.\\n\\nThe input channels, specified by :attr:`channel_axis`, are separated into :attr:`num_groups` groups,\\nand the mean and std are calculated over the each group.\\nFor example, if the input shape is [B, C, H, W] (= channel_axis=1, batch_axis=0),\\nan input variable is once reshaped to [B, num_groups, C / num_groups, H, W]\\nand standardize by its mean and std whose shapes are [B, num_groups, 1, 1, 1].\\nFinally, an output variable is reshaped again to the original input shape (= [B, C, H, W] in the case above).\\n\\nReferences:\\n\\n    * `Yuxin Wu, Kaiming He, Group Normalization.\\n      <https://arxiv.org/abs/1803.08494>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"num_groups\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"A number of groups. The channel dim of 'x' must be integer multiple of `num_groups`.\"\n      },\n      {\n        \"name\": \"channel_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Channel axis.\"\n      },\n      {\n        \"name\": \"batch_axis\",\n        \"type\": \"int64[]\",\n        \"default\": \"(0,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"no_scale\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the scale term is omitted.\"\n      },\n      {\n        \"name\": \"no_bias\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the bias term is omitted.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"InstanceNormalization\",\n    \"description\": \"Applies Instance Normalization over an input tensor, which is defined as\\n\\n.. math::\\n  \\\\begin{eqnarray}\\n    \\\\mu^i &=& \\\\frac{1}{H} \\\\sum_{i=1}^{H} x_i^i \\\\\\\\\\n    \\\\sigma^i &=& \\\\sqrt{\\\\frac{1}{H} \\\\sum_{i=1}^{H} \\\\left(x_i^i - \\\\mu^i\\\\right)^2 + \\\\epsilon} \\\\\\\\\\n    y &=& \\\\frac{x - \\\\mu^i}{\\\\sigma^i} \\\\gamma + \\\\beta\\n  \\\\end{eqnarray}\\n\\nwhere :math:`x` and :math:`y` are input and output variable,\\n:math:`\\\\mu^i` and :math:`\\\\sigma^i` are the mean and std of each instance which is separately calculated for each batch and channel,\\nand :math:`\\\\gamma` and :math:`\\\\beta` are adaptive gains and biases.\\n\\nIf the input shape is [B, C, H, W] (= channel_axis=1, batch_axis=0), the shape of calculated mean and std are [B, C, 1, 1]\\n\\nReferences:\\n\\n    * `Dmitry Ulyanov, Andrea Vedaldi, Victor Lempitsky, Instance Normalization: The Missing Ingredient for Fast Stylization.\\n      <https://arxiv.org/abs/1607.08022>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"channel_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Channel axis.\"\n      },\n      {\n        \"name\": \"batch_axis\",\n        \"type\": \"int64[]\",\n        \"default\": \"(0,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"no_scale\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the scale term is omitted.\"\n      },\n      {\n        \"name\": \"no_bias\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the bias term is omitted.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"LayerNormalization\",\n    \"description\": \"Applies Layer Normalization over an input tensor, which is defined as\\n\\n.. math::\\n  \\\\begin{eqnarray}\\n    \\\\mu^l &=& \\\\frac{1}{H} \\\\sum_{i=1}^{H} x_i^l \\\\\\\\\\n    \\\\sigma^l &=& \\\\sqrt{\\\\frac{1}{H} \\\\sum_{i=1}^{H} \\\\left(x_i^l - \\\\mu^l\\\\right)^2 + \\\\epsilon} \\\\\\\\\\n    y &=& \\\\frac{x - \\\\mu^l}{\\\\sigma^l} \\\\gamma + \\\\beta\\n  \\\\end{eqnarray}\\n\\nwhere :math:`x` and :math:`y` are input and output variable,\\n:math:`\\\\mu^l` and :math:`\\\\sigma^l` are the mean and std of each layer which is separately calculated for each batch,\\nand :math:`\\\\beta` and :math:`\\\\gamma` are adaptive biases and gains.\\n\\nIf the input shape is [B, C, H, W] (= batch_axis=0), the shape of calculated mean and std are [B, 1, 1, 1]\\n\\nReferences:\\n\\n    * `Jimmy Lei Ba, Jamie Ryan Kiros, Geoffrey E. Hinton, Layer Normalization.\\n      <https://arxiv.org/abs/1607.06450>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"batch_axis\",\n        \"type\": \"int64[]\",\n        \"default\": \"(0,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"no_scale\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the scale term is omitted.\"\n      },\n      {\n        \"name\": \"no_bias\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the bias term is omitted.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"NormNormalization\",\n    \"description\": \"Norm normalization.\\n    \\n.. math::\\n    y = \\\\frac{x_i}{\\\\|x\\\\|_p}\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"p\",\n        \"type\": \"float32\",\n        \"default\": 2.0,\n        \"description\": \"Order of the norm.\"\n      },\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced. If empty list is given, all dimensions are reduced.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-12,\n        \"description\": \"Epsilon for the normalization. This `eps` is added before taking the p-th root in the norm computation.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"SyncBatchNormalization\",\n    \"description\": \"Synchronized Batch Normalization:\\n\\nFor some tasks (e.g., semantic segmentation), batch size will be too small and BatchNormalization layer might not work well.\\nSyncBatchNorlization layer solves these problems by synchronizing batch stats (mean and var) between multiple processes.\\n\\n.. math::\\n    \\\\begin{eqnarray}\\n      \\\\mu &=& \\\\frac{1}{M} \\\\sum x_i \\\\\\\\\\n      \\\\sigma^2 &=& \\\\frac{1}{M} \\\\left(\\\\sum x_i - \\\\mu\\\\right)^2 \\\\\\\\\\n      \\\\hat{x}_i &=& \\\\frac{x_i - \\\\mu}{\\\\sqrt{\\\\sigma^2 + \\\\epsilon}} \\\\\\\\\\n      y_i &=& \\\\hat{x}_i \\\\gamma + \\\\beta.\\n    \\\\end{eqnarray}\\n\\nReferences:\\n\\n    * Implementing Synchronized Multi-GPU Batch Normalization https://hangzhang.org/PyTorch-Encoding/notes/syncbn.html\\n\\nNote:\\n    Since v1.32.0, the gradients of beta and gamma are not synchronized after backward computation (they had been synchronized previously).\\n    Users are responsible for synchronizing the gradients of beta and gamma by performing all-reduce,\\n    which is naturally done by performing all-reduce for gradients of all the parameters as we do usually in data parallel distributed training.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      },\n      {\n        \"name\": \"mean\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of running mean (modified during forward execution).\"\n      },\n      {\n        \"name\": \"variance\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of running variance (modified during forward execution).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"comm\",\n        \"required\": true,\n        \"description\": \"The communicator\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"string\",\n        \"default\": \"world\",\n        \"description\": \"The name of the communicator group\"\n      },\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"(1,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"decay_rate\",\n        \"type\": \"float32\",\n        \"default\": 0.9,\n        \"description\": \"Decay rate of running mean and variance.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"batch_stat\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Use mini-batch statistics rather than running ones.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"TensorNormalization\",\n    \"description\": \"General tensor normalization.\\nInput variable `x` is normalized by mean and std calculated by `x` itself.\\nMean and variance are calculated along `axes`.\\nFor example, if the input shape is (B, C, H, W) and axes is [0, 1],\\nthe shape of calculated mean and std are (B, C, 1 ,1).\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of beta which is learned.\"\n      },\n      {\n        \"name\": \"gamma\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"N-D array of gamma which is learned.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"(1,)\",\n        \"description\": \"Axes mean and variance are taken.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      },\n      {\n        \"name\": \"no_scale\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the scale term is omitted.\"\n      },\n      {\n        \"name\": \"no_bias\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the bias term is omitted.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"WeightNormalization\",\n    \"description\": \"Weight normalization.\\n\\n.. math::\\n  \\\\mathbf{w}_{WN} = g \\\\dfrac{\\\\mathbf{w}}{\\\\|\\\\mathbf{w}\\\\|}\\n\\nwhere :math:`\\\\mathbf{w}` is the input weights to be normalized.\\nand :math:`g` is learnable multiplication factors each of which is applied to each data at `dim`.\\n\\nReferences:\\n    * `Tim Salimans, Diederik P. Kingma, Weight Normalization: A Simple Reparameterization to Accelerate Training of Deep Neural Networks. <https://arxiv.org/abs/1602.07868>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"w\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of learnable weights.\"\n      },\n      {\n        \"name\": \"g\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"1-D array of learnable scales.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"dim\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Output dimension. For the other dimensions, the norms are computed.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-12,\n        \"description\": \"Epsilon for the normalization. This `eps` is added before taking the sqrt in the norm computation.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"w_wn\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"WeightStandardization\",\n    \"description\": \"Applies Weight Standardization over an input weight, which is defined as\\n\\n.. math::\\n  \\\\begin{eqnarray}\\n    \\\\mu_{W_i} &=& \\\\frac{1}{I} \\\\sum_{j=1}^{I} W_{ij} \\\\\\\\\\n    \\\\sigma_{W_i} &=& \\\\sqrt{\\\\frac{1}{I} \\\\sum_{i=1}^{I} \\\\left(W_{ij} - \\\\mu_{W_{i}}\\\\right)^2 + \\\\epsilon} \\\\\\\\\\n    \\\\hat{W_{ij}} &=& \\\\frac{W_{ij} - \\\\mu_{W_i}}{\\\\sigma_{W_i}} \\\\\\\\\\n    y &=& \\\\hat{W} \\\\ast x\\n  \\\\end{eqnarray}\\n\\nReferences:\\n\\n  * `Siyuan Qiao, Huiyu Wang, Chenxi Liu, Wei Shen, Alan Yuille, Weight Standardization\\n    <https://arxiv.org/pdf/1903.10520v1.pdf>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"w\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of learnable weights.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"channel_axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"An axis for output channel. Default value is 0 which assumes the weights of convolution.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-05,\n        \"description\": \"Tiny value to avoid zero division by std.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"SpectralNorm\",\n    \"description\": \"Spectral Normalization.\\n\\n.. math::\\n\\n    W_{sn} = \\\\frac{W}{\\\\sigma(W)}\\n\\nwhere :math:`W` is the input matrix, and the :math:`\\\\sigma(W)` is the spectral norm of :math:`W`. The spectral norm is approximately computed by the power iteration.\\n\\nReferences:\\n\\n    Takeru Miyato, Toshiki Kataoka, Masanori Koyama, Yuichi Yoshida, \\n    \\\"Spectral Normalization for Generative Adversarial Networks\\\", \\n    International Conference on Learning Representations. 2018.\",\n    \"inputs\": [\n      {\n        \"name\": \"w\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of learnable weights. This is normally network parameter.\"\n      },\n      {\n        \"name\": \"u\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"1-D array of singular vector. When `test == False`, the data region of `u` will be updated during forward calculation.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"dim\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Output dimension. Default is 0. If the dimension is not 0, then the specified dimension becomes the most-left dimension by transposing.\"\n      },\n      {\n        \"name\": \"itr\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of power iterations. Default is 1.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1e-12,\n        \"description\": \"Epsilon for the normalization. This `eps` is added before taking the sqrt in the norm computation.\"\n      },\n      {\n        \"name\": \"test\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"When in `True`, `u` will not be updated. Default is `False`.\"\n      },\n      {\n        \"name\": \"output_u\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Output original `u` or not. `u` is updated when `test == False` but you can get original `u` as output with this option. Default is `False`.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"w_sn\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Spectrally normalized :math:`W_{sn}` with the same shape as :math:`W`.\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"MeanSubtraction\",\n    \"description\": \"It subtracts the mean of the elements of the input array,\\nand normalizes it to :math:`0`. Preprocessing arrays with this function has the effect of improving accuracy\\nin various tasks such as image classification.\\n\\nAt training time, this function is defined as\\n\\n.. math::\\n    \\\\begin{eqnarray}\\n      \\\\mu &=& \\\\frac{1}{M} \\\\sum x_i \\\\\\\\\\n      y_i &=& x_i - \\\\mu\\n    \\\\end{eqnarray}\\n\\nAt testing time, the mean values used are those that were computed during training by moving average.\\n\\nNote:\\n    The backward performs an approximated differentiation that takes into account only the latest mini-batch.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"rmean\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of running mean (modified during forward execution).\"\n      },\n      {\n        \"name\": \"t\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Scalar of num of iteration of running mean (modified during forward execution).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Base axis of Mean Subtraction operation. Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"update_running_mean\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Update running mean during forward execution.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"ClipGradByValue\",\n    \"description\": \"In forward pass, the function behaves as the identity.\\n\\nIn backward pass,\\n\\n    .. math::\\n        g_x = \\\\begin{cases}\\n            max & (g_y > max) \\\\\\\\\\n            g_y & (otherwise) \\\\\\\\\\n            min & (g_y < min)\\n           \\\\end{cases}.\\n\\nA typical case for use is to prevent the gradient explosion through a whole computational graph.\\nFor example, if you want to clip gradient values for each feature map,\\n\\n.. code-block:: python\\n\\n  x = nn.Variable([16, 3, 32, 32])\\n  min = F.broadcast(nn.Variable.from_numpy_array(np.asarray([-1.0]).reshape((1, 1, 1, 1))), (16, 3, 32, 32))\\n  max = F.broadcast(nn.Variable.from_numpy_array(np.asarray([1.0]).reshape((1, 1, 1, 1))), (16, 3, 32, 32))\\n  c = F.clip_grad_by_value(x, min=min, max=max)\\n  h = PF.convolution(c, 64, (3, 3), pad=(1, 1))\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      },\n      {\n        \"name\": \"min\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of minimum input value by which the gradients of the `y` are clipped. Note that the shape of `min` must be the same as `x`'s and the backward to `min` is not performed.\"\n      },\n      {\n        \"name\": \"max\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of maximum input value by which the gradients of the `y` are clipped. Note that the shape of `max` must be the same as `x`'s and the backward to `max` is not performed.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"ClipGradByNorm\",\n    \"description\": \"In the forward pass, the function behaves like the identity.\\n\\nIn the backward pass,\\n\\n.. math::\\n\\n    g_x = N \\\\times \\\\frac{g_y}{\\\\|g_y\\\\|_2}.\\n\\nwhere :math:`g_x` is the gradient w.r.t the input, :math:`g_y` is the gradient w.r.t. the output,\\nand :math:`N` is `clip_norm` where the norm of :math:`g_y` becomes. this is the case that `axes` is not set.\\nWhen `axes` is set, the norm is computed over `axes`.\\n\\nA typical case for use is to prevent the gradient explosion through a whole computational graph.\\nFor example, if you want to normalize gradient values over feature axis,\\n\\n.. code-block:: python\\n\\n  x = nn.Variable([16, 3, 32, 32])\\n  c = F.clip_grad_by_norm(x, axes=(1, ))\\n  h = PF.convolution(c, 64, (3, 3), pad=(1, 1))\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of input.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"clip_norm\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Clip to the norm of input to `clip_norm` in the backward pass.\"\n      },\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced. If empty list is given, all dimensions are reduced to scalar. This is used in the forward pass.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"Sum\",\n    \"description\": \"Reduces a matrix along a specified axis with the sum function.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced. If empty list is given, all dimensions are reduced to scalar.\"\n      },\n      {\n        \"name\": \"keep_dims\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Flag whether the reduced axis is kept.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"CumSum\",\n    \"description\": \"Cumulative sum along a given axis.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Axis along which cumulative sum is to be calculated\"\n      },\n      {\n        \"name\": \"exclusive\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, perform exclusive cumsum\"\n      },\n      {\n        \"name\": \"reverse\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, perform cumsum in reverse direction\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Mean\",\n    \"description\": \"Reduces a matrix along a specified axis with the mean function.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced.\"\n      },\n      {\n        \"name\": \"keep_dims\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Flag whether the reduced axis is kept.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Max\",\n    \"description\": \"Reduction along axis or axes with max operation.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced.\"\n      },\n      {\n        \"name\": \"keep_dims\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Flag whether the reduced axis is kept.\"\n      },\n      {\n        \"name\": \"with_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return values and indices.\"\n      },\n      {\n        \"name\": \"only_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return only indices.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Min\",\n    \"description\": \"Reduction along axis or axes with min operation.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced.\"\n      },\n      {\n        \"name\": \"keep_dims\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Flag whether the reduced axis is kept.\"\n      },\n      {\n        \"name\": \"with_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return values and indices.\"\n      },\n      {\n        \"name\": \"only_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return only indices.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Norm\",\n    \"description\": \"Reduction along axis or axes with norm operation.\\n\\n.. math::\\n    y = \\\\|x\\\\|_p = \\\\left( \\\\sum_i |x_i|^p \\\\right)^{\\\\frac{1}{p}}\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"p\",\n        \"type\": \"float32\",\n        \"default\": 2.0,\n        \"description\": \"Order of the norm.\"\n      },\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced. If empty list is given, all dimensions are reduced to scalar.\"\n      },\n      {\n        \"name\": \"keep_dims\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Flag whether the reduced axis is kept.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Prod\",\n    \"description\": \"Reduction along axis or axes with product operation.\\n\\nNote:\\n    Backward computation is not accurate in a zero value input.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"range(x.ndim)\",\n        \"description\": \"Axes to be reduced.\"\n      },\n      {\n        \"name\": \"keep_dims\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Flag whether the reduced axis is kept.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"CumProd\",\n    \"description\": \"Cumulative product along a given axis.\\n\\nNote:\\n    Backward computation is not accurate in a zero value input.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Axis along which cumulative product is to be calculated\"\n      },\n      {\n        \"name\": \"exclusive\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, perform exclusive cumprod\"\n      },\n      {\n        \"name\": \"reverse\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, perform cumprod in reverse direction\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ReduceSum\",\n    \"description\": \"Reduction along an axis with sum operation.\\n\\nNote:\\n    This is deprecated. Use ``sum`` instead.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ReduceMean\",\n    \"description\": \"Reduction by mean along an axis.\\n\\nNote:\\n    This is deprecated. Use ``mean`` instead.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Add2\",\n    \"description\": \"Element-wise addition.\\n\\n.. math::\\n   y_i = x^{(0)}_i + x^{(1)}_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AddN\",\n    \"description\": \"Element-wise addition.\\n\\n.. math::\\n   y_i = x^{(0)}_i + . . . + x^{(n-1)}_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"N-D arrays\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BcAdd2\",\n    \"description\": \"Note: This shouldn't be called by users.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Sub2\",\n    \"description\": \"Element-wise subtraction.\\n\\n.. math::\\n   y_i = x^{(0)}_i - x^{(1)}_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Mul2\",\n    \"description\": \"Element-wise multiplication.\\n\\n.. math::\\n   y_i = x^{(0)}_i x^{(1)}_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MulN\",\n    \"description\": \"Element-wise multiplication.\\n\\n.. math::\\n   y_i = x^{(0)}_i . . . x^{(n-1)}_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"N-D arrays\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Div2\",\n    \"description\": \"Element-wise division.\\n\\n.. math::\\n   y_i = \\\\frac{x^{(0)}_i} {x^{(1)}_i}\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Pow2\",\n    \"description\": \"Element-wise power function.\\n\\n.. math::\\n   y_i = {(x^{(0)}_i)} ^ {x^{(1)}_i}\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AddScalar\",\n    \"description\": \"Element-wise scalar addition.\\n\\n.. math::\\n   y_i = x_i + v\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      },\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MulScalar\",\n    \"description\": \"Element-wise scalar multiplication.\\n\\n.. math::\\n   y_i = v x_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      },\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"PowScalar\",\n    \"description\": \"Element-wise scalar power function.\\n\\n.. math::\\n   y_i = (x_i) ^ v\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      },\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RSubScalar\",\n    \"description\": \"Element-wise scalar subtraction.\\n\\n.. math::\\n   y_i = v - x_i\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RDivScalar\",\n    \"description\": \"Element-wise scalar division.\\n\\n.. math::\\n    y_i = \\\\frac{v}{x_i}\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RPowScalar\",\n    \"description\": \"Element-wise scalar power function.\\n\\n.. math::\\n    y_i = v ^ {x_i}\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Sign\",\n    \"description\": \"Element-wise sign function.\\n\\nIn the forward pass, it is defined as\\n\\n.. math::\\n\\n    f(x) = \\\\begin{cases}\\n        1  & (x > 0) \\\\\\\\\\n        -1 & (x < 0) \\\\\\\\\\n        \\\\alpha & (x = 0)\\n    \\\\end{cases}.\\n\\nIn the backward pass, it is defined as\\n\\n.. math::\\n    \\\\frac{\\\\partial f(x)}{\\\\partial x} = 1,\\n\\nor in other words, it behaves as the identity function for the gradient in the backward pass.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"alpha\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Value in case of :math:`x = 0`.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Minimum2\",\n    \"description\": \"Element-wise minimum.\\n\\n.. math::\\n   y_i = \\\\min(x^{(0)}_i, x^{(1)}_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of min value\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Maximum2\",\n    \"description\": \"Element-wise maximum.\\n\\n.. math::\\n   y_i = \\\\max(x^{(0)}_i, x^{(1)}_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of max value\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"MinimumScalar\",\n    \"description\": \"Element-wise scalar minimum.\\n\\n.. math::\\n    y_i = \\\\min(x_i, v)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"MaximumScalar\",\n    \"description\": \"Element-wise scalar maximum.\\n\\n.. math::\\n    y_i = \\\\max (x_i, v)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalAnd\",\n    \"description\": \"Elementwise logical AND.\\n\\n.. math::\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1 & (x^{(0)}_i \\\\neq 0 \\\\;\\\\&\\\\; x^{(1)}_i \\\\neq 0) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalOr\",\n    \"description\": \"Elementwise logical OR.\\n\\n.. math::\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        0 & (x^{(0)}_i = 0 \\\\;\\\\&\\\\; x^{(1)}_i = 0) \\\\\\\\\\n        1 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalXor\",\n    \"description\": \"Elementwise logical XOR.\\n\\n.. math::\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1 & (x^{(0)}_i = 0 \\\\;\\\\&\\\\; x^{(1)}_i = 0) \\\\\\\\\\n        1 & (x^{(0)}_i \\\\neq 0 \\\\;\\\\&\\\\; x^{(1)}_i \\\\neq 0) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Equal\",\n    \"description\": \"Element wise 'equal'\\n\\n.. math::\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1 & (x^{(0)}_i = x^{(1)}_i) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"NotEqual\",\n    \"description\": \"Element wise 'not equal'\\n\\n.. math::\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        0 & (x^{(0)}_i = x^{(1)}_i) \\\\\\\\\\n        1 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"GreaterEqual\",\n    \"description\": \"Element wise comparison. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1  & (x^{(0)}_i \\\\geq x^{(1)}_i) \\\\\\\\\\n        0 & (x^{(0)}_i < x^{(1)}_i)\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Greater\",\n    \"description\": \"Element wise comparison. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1  & (x^{(0)}_i > x^{(1)}_i) \\\\\\\\\\n        0 & (x^{(0)}_i \\\\leq x^{(1)}_i)\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LessEqual\",\n    \"description\": \"Element wise comparison. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1  & (x^{(0)}_i \\\\leq x^{(1)}_i) \\\\\\\\\\n        0 & (x^{(0)}_i > x^{(1)}_i)\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Less\",\n    \"description\": \"Element wise comparison. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,x^{(1)}_i) = \\\\begin{cases}\\n        1  & (x^{(0)}_i < x^{(1)}_i) \\\\\\\\\\n        0 & (x^{(0)}_i \\\\geq x^{(1)}_i)\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"SearchSorted\",\n    \"description\": \"Finds indices in the innermost dimension of a sorted sequance where values must be inserted in order to maintain value\",\n    \"inputs\": [\n      {\n        \"name\": \"sorted_sequence\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of sorted sequence where search is to be performed. Note that this must be a sorted array\"\n      },\n      {\n        \"name\": \"values\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of Search values\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"right\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \":If True, given a value v, the function returns index i such that sorted_sequence[i-1] <= v < sorted_sequence[i] (index of closest upper bound of v). By default, this is false so the function returns index i such that a[i-1] < v <= a[i] (index of closest lower bound of v)\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array containing the required indices\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalAndScalar\",\n    \"description\": \"Elementwise logical AND with scalar.\\n\\n.. math::\\n    f(x_i,v) = \\\\begin{cases}\\n        1 & (x_i \\\\neq 0 \\\\;\\\\&\\\\; v \\\\neq 0) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"required\": true,\n        \"type\": \"boolean\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalOrScalar\",\n    \"description\": \"Elementwise logical OR with scalar.\\n\\n.. math::\\n    f(x_i,v) = \\\\begin{cases}\\n        0 & (x_i = 0 \\\\;\\\\&\\\\; v = 0) \\\\\\\\\\n        1 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"required\": true,\n        \"type\": \"boolean\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalXorScalar\",\n    \"description\": \"Elementwise logical XOR with scalar.\\n\\n.. math::\\n    f(x_i,v) = \\\\begin{cases}\\n        1 & (x_i = 0 \\\\;\\\\&\\\\; v = 0) \\\\\\\\\\n        1 & (x_i \\\\neq 0 \\\\;\\\\&\\\\; v \\\\neq 0) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"required\": true,\n        \"type\": \"boolean\",\n        \"description\": \"No Description\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"EqualScalar\",\n    \"description\": \"Element wise 'equal' with a scalar\\n\\n.. math::\\n    f(x_i,v) = \\\\begin{cases}\\n        1 & (x_i = v) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"NotEqualScalar\",\n    \"description\": \"Element wise 'not equal' with a scalar\\n\\n.. math::\\n    f(x_i,v) = \\\\begin{cases}\\n        0 & (x_i = v) \\\\\\\\\\n        1 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"GreaterEqualScalar\",\n    \"description\": \"Element wise comparison with a scalar. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,v) = \\\\begin{cases}\\n        1  & (x^{(0)}_i \\\\geq v \\\\\\\\\\n        0 & (x^{(0)}_i < v\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"GreaterScalar\",\n    \"description\": \"Element wise comparison with a scalar. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,v) = \\\\begin{cases}\\n        1  & (x^{(0)}_i > v \\\\\\\\\\n        0 & (x^{(0)}_i \\\\leq v\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LessEqualScalar\",\n    \"description\": \"Element wise comparison with a scalar. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,v) = \\\\begin{cases}\\n        1  & (x^{(0)}_i \\\\leq v) \\\\\\\\\\n        0 & (x^{(0)}_i > v)\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LessScalar\",\n    \"description\": \"Element wise comparison with a scalar. The :math:`i^{th}` element of the output is:\\n\\n.. math::\\n\\n    f(x^{(0)}_i,v) = \\\\begin{cases}\\n        1  & (x^{(0)}_i < v) \\\\\\\\\\n        0 & (x^{(0)}_i \\\\geq v)\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 1.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"LogicalNot\",\n    \"description\": \"Element-wise logical NOT operation\\n\\n.. math::\\n    f(x_i) = \\\\begin{cases}\\n        1 & (x_i = 0) \\\\\\\\\\n        0 & otherwise\\n    \\\\end{cases}.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"IsNaN\",\n    \"description\": \"Test element-wise for NaN and return a ``0/1`` array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"IsInf\",\n    \"description\": \"Test element-wise for ``inf/-inf`` and return a ``0/1`` array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"ResetNaN\",\n    \"description\": \"Replace NaNs with a scalar value specified by ``val``.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 0.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"ResetInf\",\n    \"description\": \"Replace ``-inf/inf`` with a scalar value specified by ``val``.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float64\",\n        \"default\": 0.0,\n        \"description\": \"Value of the scalar\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Where\",\n    \"description\": \"Return elements, either from ``x_true`` or ``x_false``, depending on ``condition``.\\n\\nIf rank of ``condition`` is higher than those of ``x_true`` and ``x_false``, the first dimensions of ``x_true`` and ``x_false`` must match the dimensions of ``condition``.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n  import numpy as np\\n  import nnabla as nn\\n  import nnabla.functions as F\\n\\n  a = nn.Variable.from_numpy_array(np.random.rand(2, 3))\\n  x = nn.Variable.from_numpy_array(np.random.rand(2, 3, 4))\\n  y = nn.Variable.from_numpy_array(np.random.rand(2, 3, 4))\\n  z = F.where(F.greater_scalar(a, 0.5), x, y)\\n  z.forward()\\n\\n  # Numpy equivalent\\n  z_numpy = np.where(a.d > 0.5, x.d, y.d)\\n  assert np.allclose(z_numpy, z.d)\",\n    \"inputs\": [\n      {\n        \"name\": \"condition\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-d array. For all i, when ``condition[i] == true``, yield ``x_true[i]``, otherwise ``x_false[i]``.\"\n      },\n      {\n        \"name\": \"x_true\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-d array with higher or equal rank to ``condition``.\"\n      },\n      {\n        \"name\": \"x_false\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-d array with higher or equal rank to ``condition``.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as condition\"\n      }\n    ],\n    \"category\": \"Logic\"\n  },\n  {\n    \"name\": \"Constant\",\n    \"description\": \"Generate a constant-valued array.\",\n    \"attributes\": [\n      {\n        \"name\": \"val\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Constant value.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of the output array.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array where all values are the specified constant.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Arange\",\n    \"description\": \"Generate a range of values within the half-open interval\\n``[start, stop)`` (the interval including start but excluding\\nstop) with `step` increments.\",\n    \"attributes\": [\n      {\n        \"name\": \"start\",\n        \"required\": true,\n        \"type\": \"float32\",\n        \"description\": \"Start value.\"\n      },\n      {\n        \"name\": \"stop\",\n        \"required\": true,\n        \"type\": \"float32\",\n        \"description\": \"End value.\"\n      },\n      {\n        \"name\": \"step\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Step value.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"1-D array with the generated values.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Linspace\",\n    \"description\": \"Generate a one-dimensional vector/tensor of size `num` whose values are evenly spaced from `start` to `end`, inclusive.\",\n    \"attributes\": [\n      {\n        \"name\": \"start\",\n        \"required\": true,\n        \"type\": \"float32\",\n        \"description\": \"Start value.\"\n      },\n      {\n        \"name\": \"stop\",\n        \"required\": true,\n        \"type\": \"float32\",\n        \"description\": \"End value.\"\n      },\n      {\n        \"name\": \"num\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Size of the constructed vector/tensor.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"1-D array with the generated values.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Abs\",\n    \"description\": \"Element-wise absolute value function.\\n\\n.. math::\\n   y_i = |x_i|\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Element-wise absolute variable\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Exp\",\n    \"description\": \"Element-wise natural exponential function.\\n\\n.. math::\\n   y_i = \\\\exp(x_i).\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Element-wise exp variable\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Log\",\n    \"description\": \"Element-wise natural logarithm function.\\n\\n.. math::\\n   y_i = \\\\ln(x_i).\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Element-wise log variable\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Identity\",\n    \"description\": \"Identity function.\\n\\n.. math::\\n    y = x\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BatchMatmul\",\n    \"description\": \"Batch matrix multiplication.\\n\\nTwo of batchs of matrices are multiplied for each sample in a batch.\\nA batch of matrices is composed as [..., P, Q] where the last two dimensions compose matrix dimensions,\\nand the first dimensions up to the third last dimension are considered as batch samples.\\nThese batch dimensions are internally broadcasted when the size of a dimension is 1.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n  import nnabla as nn\\n  import nnabla.functions as F\\n  import numpy as np\\n\\n  nn.set_auto_forward(True)\\n\\n  # Same batch size\\n  a = nn.Variable.from_numpy_array(np.random.rand(2, 2, 3, 4))\\n  b = nn.Variable.from_numpy_array(np.random.rand(2, 2, 4, 3))\\n  c = F.batch_matmul(a, b)\\n\\n  # Different batch size with the broadcast\\n  a = nn.Variable.from_numpy_array(np.random.rand(2, 1, 3, 4))\\n  b = nn.Variable.from_numpy_array(np.random.rand(1, 3, 4, 3))\\n  c = F.batch_matmul(a, b)\\n\\n.. WARNING::\\n  Since the version 1.13, the behavior of the batch dimensions changed, it supported the internal\\n  broadcast when the size of a dimension is 1. Accordingly, this function does not supports different\\n  batch dimensions between two inputs even if the total sample size for each input is same.\",\n    \"inputs\": [\n      {\n        \"name\": \"a\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with >= 2-dim. The last two dimensions will be treated as a matrix.\"\n      },\n      {\n        \"name\": \"b\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with >= 2-dim. The last two dimensions will be treated as a matrix. The product of the size of 0-th dimension through the size of the third last dimension must be same as that of the input ``a``.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"transpose_a\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Transpose the last two axes of ``a`` in matrix multiplication.\"\n      },\n      {\n        \"name\": \"transpose_b\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Transpose the last two axes of ``b`` in matrix multiplication.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output of sample-wise matrix multiplication in a batch. When ``a`` is of a shape of [N, P, Q], ``b`` is of a shape of [N, Q, R], and transpose options are all False, the output will be a shape of [N, P, R].\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Round\",\n    \"description\": \"Element-wise round function.\\n\\nIn the forward pass, this function simply computes `round` to the nearest integer value.\\n\\n.. math::\\n    y_i = round(x_i).\\n\\nIn the backward pass, the simple Straight-Through Estimator (STE) is applied,\\n\\n.. math::\\n    \\\\frac{\\\\partial y_i}{\\\\partial x_i} = 1.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Ceil\",\n    \"description\": \"Element-wise ceil function.\\n\\nIn the forward pass, this function simply returns the smallest integer which is not less than the input.\\n\\n.. math::\\n    y_i = ceil(x_i).\\n\\nIn the backward pass, the simple Straight-Through Estimator (STE) is applied,\\n\\n.. math::\\n    \\\\frac{\\\\partial y_i}{\\\\partial x_i} = 1.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Floor\",\n    \"description\": \"Element-wise floor function.\\n\\nIn the forward pass, this function simply returns the largest integer which is not greater than the input.\\n\\n.. math::\\n    y_i = floor(x_i).\\n\\nIn the backward pass, the simple Straight-Through Estimator (STE) is applied,\\n\\n.. math::\\n    \\\\frac{\\\\partial y_i}{\\\\partial x_i} = 1.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Sin\",\n    \"description\": \"Element-wise sine (sin) function.\\n\\n.. math::\\n    y_i = \\\\sin (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Cos\",\n    \"description\": \"Element-wise cosine (cos) function.\\n\\n.. math::\\n    y_i = \\\\cos (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Tan\",\n    \"description\": \"Element-wise tangent (tan) function.\\n\\n.. math::\\n    y_i = \\\\tan (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Sinh\",\n    \"description\": \"Element-wise hyperbolic sine (sinh) function.\\n\\n.. math::\\n    y_i = \\\\sinh (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Cosh\",\n    \"description\": \"Element-wise hyperbolic cosine (cosh) function.\\n\\n.. math::\\n    y_i = \\\\cosh (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ASin\",\n    \"description\": \"Element-wise arcsine (asin) function.\\n\\n.. math::\\n    y_i = \\\\arcsin (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ACos\",\n    \"description\": \"Element-wise arccosine (acos) function.\\n\\n.. math::\\n    y_i = \\\\arccos (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ATan\",\n    \"description\": \"Element-wise arctangent (atan) function.\\n\\n.. math::\\n    y_i = \\\\arctan (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ATan2\",\n    \"description\": \"Element-wise arctangent (atan) function with 2 input variables.\\n\\n.. math::\\n    y_i = \\\\arctan2 (x_{i1}, x_{i2})\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as input variables\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ASinh\",\n    \"description\": \"Element-wise hyperbolic arcsine (asinh) function.\\n\\n.. math::\\n    y_i = \\\\text{arcsinh} (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ACosh\",\n    \"description\": \"Element-wise hyperbolic arccosine (acosh) function.\\n\\n.. math::\\n    y_i = \\\\text{arccosh} (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ATanh\",\n    \"description\": \"Element-wise hyperbolic arctangent (atanh) function.\\n\\n.. math::\\n    y_i = \\\\text{arctanh} (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Erf\",\n    \"description\": \"Element-wise Error function.\\n\\n.. math::\\n    y_i = \\\\text{erf} (x_i)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Concatenate\",\n    \"description\": \"Concatenate a variable number of input arrays along the specified axis.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"N-D arrays.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x[0].shape) - 1\",\n        \"description\": \"Axis\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Concatenate variable\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Split\",\n    \"description\": \"Split arrays at the specified axis.\\n\\nnote:\\n    This function should not be called directly when constructing models.\\n    Instead, use :meth:`nnabla.functions.split` which\\n    automatically sets `n_output` from the input's shape and axis.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Axis\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"list of N-D arrays\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Stack\",\n    \"description\": \"Joins two or more arrays on a new axis.\\n\\nNote:\\n    Unlike :meth:`nnabla.functions.concatenate` , which joins arrays on an existing axis,\\n    Stack joins arrays on a new axis.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"N-D arrays. The sizes of all the arrays to be stacked must be the same.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"The axis on which to concatenate arrays. Axis indices take on values 0, 1, 2, and so on from the left. For example, to stack four (3,28,28) inputs on the second axis, specify 1. In this case, the output size will be (3,4,28,28).\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Slice\",\n    \"description\": \"Slice arrays along specified axis.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"start\",\n        \"type\": \"int64[]\",\n        \"default\": \"(0,) * len(x.shape)\",\n        \"description\": \"Start indices for each axis\"\n      },\n      {\n        \"name\": \"stop\",\n        \"type\": \"int64[]\",\n        \"default\": \"tuple(x.shape)\",\n        \"description\": \"Stop indices for each axis\"\n      },\n      {\n        \"name\": \"step\",\n        \"type\": \"int64[]\",\n        \"default\": \"(1,) * len(x.shape)\",\n        \"description\": \"Step indices for each axis\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Sliced N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Pad\",\n    \"description\": \"Pad the input N-D array `x` over the number of dimensions given\\nby half the length of the `pad_width` iterable, where every two\\nvalues in `pad_width` determine the before and after pad size of\\nan axis. The `pad_width` iterable must hold an even number of\\npositive values which may cover all or fewer dimensions of the\\ninput variable `x`. If `pad_width` covers fewer dimensions then\\nit applies to the innermost dimensions of `x`.\\n\\n.. code-block:: python\\n\\n  x = nn.Variable.from_numpy_array(np.ones((2, 3, 4)))\\n  assert F.pad(x, (1, 1, 2, 2)).shape == (2, 5, 8)\\n\\nPadding is performed according to the requested `mode`:\\n\\nconstant\\n  Pads with a value given by the keyword argument `constant_value`.\\n\\n  .. code-block:: python\\n\\n    x = nn.Variable.from_numpy_array(np.array([1, 2, 3, 4], dtype=np.int))\\n    y = F.pad(x, (3, 3), 'constant', constant_value = -1)\\n    y.forward()\\n    assert np.all(y.d == np.array([-1, -1, -1, 1, 2, 3, 4, -1, -1, -1]))\\n\\nreflect\\n  Pads with the reflection of the vector mirrored on the first\\n  and last values of the vector along each axis.\\n\\n  .. code-block:: python\\n\\n    x = nn.Variable.from_numpy_array(np.array([1, 2, 3, 4], dtype=np.int))\\n    y = F.pad(x, (3, 3), 'reflect')\\n    y.forward()\\n    assert np.all(y.d == np.array([4, 3, 2, 1, 2, 3, 4, 3, 2, 1]))\\n\\nrepeat\\n  Pads with the edge value of the vector along each axis.\\n\\n  .. code-block:: python\\n\\n    x = nn.Variable.from_numpy_array(np.array([1, 2, 3, 4], dtype=np.int))\\n    y = F.pad(x, (3, 3), 'repeat')\\n    y.forward()\\n    assert np.all(y.d == np.array([1, 1, 1, 1, 2, 3, 4, 4, 4, 4]))\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"pad_width\",\n        \"required\": true,\n        \"type\": \"int64[]\",\n        \"description\": \"Iterable of *before* and *after* pad values.\"\n      },\n      {\n        \"name\": \"mode\",\n        \"type\": \"string\",\n        \"default\": \"constant\",\n        \"description\": \"Padding mode string.\"\n      },\n      {\n        \"name\": \"constant_value\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Fill value if mode is `constant`.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Padded N-D array with the same number of dimensions as the input.\\n\\n.. code-block:: python\\n\\n  x = nn.Variable((3, 3, 4, 2))  # a shape like (B, C, H, W)\\n  # 1-D padding: last dim by 1 left and 2 on the right side\\n  assert F.pad(x, (1, 2)).shape == (3, 3, 4, 5)\\n  # 2-D padding: last dim by (1, 1) and 2nd to last by (2, 2)\\n  assert F.pad(x, (2, 2, 1, 1)).shape == (3, 3, 8, 4)\\n  # 3-D padding: dims C by (0, 1), H by (2, 1), and W by (3, 3)\\n  assert F.pad(x, (0, 1, 2, 1, 3, 3)).shape == (3, 4, 7, 8)\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Transpose\",\n    \"description\": \"Transposes tensor dimensions.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"required\": true,\n        \"type\": \"int64[]\",\n        \"description\": \"Source axis indices for each axis.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Transposed N-D array.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Broadcast\",\n    \"description\": \"Broadcasting ND-array to the specified shape.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Shape broadcasted to. The size must be the same in axis where ``x``'s shape is not 1.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Broadcasted N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BroadcastTo\",\n    \"description\": \".. WARNING::\\n  This function is experimental support, so please do not actively use it.\\n\\nBroadcasting ND-array to the specified buffer.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      },\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Target axis to start broadcasting. If this is not set, broadcast will try to fit y to x starting from the last dimension\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"z\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Broadcasted N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Tile\",\n    \"description\": \"Forward input `x` repeated the number of times given by `reps`. If `reps`\\nis a sequence, the output has dimension of ``d = max(len(reps), x.ndim)``\\nand either `x` is promoted to be d-dimensional by prepending new axes or\\n`reps` is promoted to x.ndim by prepending 1's.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"reps\",\n        \"required\": true,\n        \"type\": \"int64[]\",\n        \"description\": \"The number of repetitions of `x` along each axis.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"OneHot\",\n    \"description\": \"This function creates one-hot vector based on input indices.\\nThe range [-shape[i], -1] of input indices are regarded as [0, shape[i]-1],\\nand an input index outside [-shape[i], shape[i]-1] generates a vector \\nfilled with zero.\\n\\n        Example:\\n\\n        .. code-block:: python\\n\\n          import nnabla as nn\\n          import nnabla.functions as F\\n          import numpy as np\\n\\n          labels = nn.Variable.from_numpy_array(np.array([[9], [4], [5], [-9], [10]]))\\n          print(labels.shape)  # (5, 1)\\n\\n          num_class = 10\\n\\n          y_train = F.one_hot(labels, shape=(num_class, ))\\n          y_train.forward()\\n\\n          print(y_train.shape)  # (5, 10)\\n          print(y_train.d)\\n\\n          # [[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]\\n          #  [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]\\n          #  [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]\\n          #  [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]\\n          #  [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]\\n\\n          # Can also be used for ndarray.\\n\\n          labels = nn.Variable.from_numpy_array(np.array([[1, 7], [4, 7], [8, 6], [5, 0], [2, 6]]))\\n          print(labels.shape)  # (5, 2)\\n\\n          num_class_1, num_class_2  = 10, 8\\n\\n          y_train = F.one_hot(labels, shape=(num_class_1, num_class_2))\\n          y_train.forward()\\n\\n          print(y_train.shape)  # (5, 10, 8)\\n          print(y_train.d)\\n\\n          # [[[0. 0. 0. 0. 0. 0. 0. 0.]          [[0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 1.]           [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]           [0. 0. 0. 0. 0. 0. 1. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]           [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]           [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]    ...    [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]           [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]           [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]           [0. 0. 0. 0. 0. 0. 0. 0.]\\n          #   [0. 0. 0. 0. 0. 0. 0. 0.]],         [0. 0. 0. 0. 0. 0. 0. 0.]]]\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array representing label's indice.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Number of classes. When nd-labels are given, dimensions must match. See the example above.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array one-hot vector/tensor.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Flip\",\n    \"description\": \"Reverses the order of elements of the specified dimension of an array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"[len(x.shape) - 1]\",\n        \"description\": \"The index of the dimension to reverse the order of the elements. Axis indices take on values 0, 1, 2, and so on from the left. For example, to flip a 32 (W) by 24 (H) 100 RGB image (100,3,24,32) vertically and horizontally, specify (2,3).\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Shift\",\n    \"description\": \"Shifts the array elements by the specified amount.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shifts\",\n        \"type\": \"int64[]\",\n        \"default\": \"(0,) * len(x.shape)\",\n        \"description\": \"The amount to shift elements. For example, to shift image data to the right by 2 pixels and up 3 pixels, specify (-3,2).\"\n      },\n      {\n        \"name\": \"border_mode\",\n        \"type\": \"string\",\n        \"default\": \"nearest\",\n        \"description\": \"Specify how to process the ends of arrays whose values will be undetermined as a result of shifting. nearest: The data at the ends of the original      array is copied and used. reflect: Original data reflected      at the ends of the original array is used.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Sort\",\n    \"description\": \"Sorts the elements of `x` along a given `axis` in ascending\\norder by value. A negative `axis` counts from the last dimension\\nof `x`, so the default of -1 sorts along the last dimension. If\\n`reverse` is True, then the elements are sorted in descending\\norder.\\n\\nIf `with_index` is True, result is a tuple ``(sorted, indices)``\\nor only ``indices`` if `only_index` is True. Setting\\n`only_index` to True implies that `with_index` is also True.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Axis along which to sort.\"\n      },\n      {\n        \"name\": \"reverse\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Sort in descending order.\"\n      },\n      {\n        \"name\": \"with_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return sorted values and index.\"\n      },\n      {\n        \"name\": \"only_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return only the sort index.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"list of N-D arrays\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Reshape\",\n    \"description\": \"Reshapes the input variable in-place. It does not create a copy of the variable.\\nThe output variable (y) has a new shape but points to the same data as the input variable (x).\\nThis means that if the data in the output variable (y) is modified, the data in the input\\nvariable (x) also gets modified since the reshape was done in-place.\\n\\nNote:\\n    This function has the same behavior as the :meth:`nnabla.Variable.reshape` method.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Dimensions for each axis. ``-1`` can be specified only in one shape dimension. The value is calculated from the size of the array and remaining dimensions.\"\n      },\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"The output array is shared with the input array if True.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Reshaped N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Shape\",\n    \"description\": \"Get the shape of a tensor. Optional attributes start and end can be used to compute\\na slice of the input tensor's shape. If start axis is omitted, the slice starts from\\naxis 0.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"start\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"If start axis is omitted, the slice starts from axis 0.\"\n      },\n      {\n        \"name\": \"end\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"The end axis, if specified, is exclusive (and the returned value will not include.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"shape\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"1-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"MatrixDiag\",\n    \"description\": \"Returns an array where the last two dimensions consist of the diagonal matrix.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape (:math:`M_0 \\\\times \\\\ldots \\\\times M_N`).\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape (:math:`M_0 \\\\times \\\\ldots \\\\times M_N \\\\times M_N`).\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"MatrixDiagPart\",\n    \"description\": \"Returns an array in which the values of the last dimension consist of the diagonal\\nelements of the last two dimensions of an input array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape (:math:`M_0 \\\\times \\\\ldots \\\\times M_N \\\\times M_N`).\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape (:math:`M_0 \\\\times \\\\ldots \\\\times M_N`).\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Trilu\",\n    \"description\": \"Returns an array in which the values of the last dimension consist of the triangular\\nmatrix of the last two dimensions of an input array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape (:math:`M_0 \\\\times \\\\ldots \\\\times M_N`).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"k\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"The number diagonals above or below the main diagonal to exclude or include.\"\n      },\n      {\n        \"name\": \"upper\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Determine whether upper or lower part of matrix is retained.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape (:math:`M_0 \\\\times \\\\ldots \\\\times M_N`).\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Meshgrid\",\n    \"description\": \"Return coordinate matrices from coordinate vectors. Given N 1-D arrays, this function returns N-D coordinate arrays for vectorized evaluations on an N-D grid.\\nExample: \\n  >>> x,y = F.meshgrid(F.arange(0,3), F.arange(0,2))\\n  >>> x.d\\n  array([[0., 1., 2.],\\n         [0., 1., 2.]], dtype=float32)\\n >>> y.d \\n array([[0., 0., 0.],\\n        [1., 1., 1.]], dtype=float32)\\n\\n >>> i,j = F.meshgrid(F.arange(0,3), F.arange(0,2), ij_indexing=True)\\n >>> i.d \\n array([[0., 0.],\\n        [1., 1.],\\n        [2., 2.]], dtype=float32)\\n >>> j.d \\n array([[0., 1.],\\n        [0., 1.],\\n        [0., 1.]], dtype=float32)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"N-D arrays.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"ij_indexing\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If set true (Matrix ('ij') indexing ), the broadcasting dimensions are swapped. Default is False (Cartesian ('xy') indexing ).\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"N-D arrays\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BatchDet\",\n    \"description\": \"Batch-wise determinant function.\\n\\n.. math::\\n  Y_b = \\\\det(X_b), \\n\\nwhere :math:`X_b` and :math:`Y_b` are the :math:`b`-th input and output, respectively.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array of determinant\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BatchInv\",\n    \"description\": \"Returns an array of inverted matrix\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array of inverted matrix\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BatchLogdet\",\n    \"description\": \"Batch-wise log absolute determinant function.\\n\\n.. math::\\n  Y_b = \\\\log(|\\\\det(X_b)|), \\n\\nwhere :math:`X_b` and :math:`Y_b` are the :math:`b`-th input and output, respectively.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array of log absolute determinant\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BatchCholesky\",\n    \"description\": \"Batch-wise cholesky decomposition of symmetric positive definite matrix.\\nThe gradient of this function will be a symmetric matrix.\\nThis function does not check whether given matrix is symmetric positive define matrix or not.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"upper\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If true, will return an upper triangular matrix. Otherwise will return a lower triangular matrix.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"batched N-D array of lower/upper triangular matrix.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Assign\",\n    \"description\": \"Assign source array to destination array just like `tf.assign`.\\nThis is useful to synchronize or manually update parameters.\\n\\n.. code-block:: python\\n\\n  dst = nn.Variable((2, 3, 4))\\n  src = nn.Variable((2, 3, 4))\\n  assign = F.assign(dst, src)\\n\\n  assign.forward()\\n  assert np.allclose(dst.d, src.d) # dst and src have identical values.\\n  assert np.allclose(assign.d dst.d) # returned Variable is also identical to dst.\\n\\nUnlike TensorFlow, the returned Variable has a backward path to `dst`:\\n\\n.. math::\\n\\n  g_{dst} = g_{y}\",\n    \"inputs\": [\n      {\n        \"name\": \"dst\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A destination N-D array\"\n      },\n      {\n        \"name\": \"src\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A source N-D array\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"An assigned array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Gather\",\n    \"description\": \"Gather from the input data according to the index.\\n\\nGiven the input data :math:`X` of :math:`(D_{0}, \\\\ldots, D_{N-1})` shape and\\nthe indices :math:`IDX` of :math:`(I_{0}, \\\\ldots, I_{M-1})` shape, in case of `batch_dims = 0`,\\nthe gather outputs\\n\\n.. math::\\n  && Y[d_{0}, \\\\ldots, d_{axis - 1}, i_{0}, \\\\ldots, i_{M-1}, d_{axis + 1}, \\\\ldots, d_{N-1}] = \\\\\\\\\\n  && X[d_{0}, \\\\ldots, d_{axis - 1}, IDX[i_{0}, \\\\ldots, i_{M-1}], d_{axis + 1}, \\\\ldots, d_{N-1}].\\n\\nGenerally, the gather outputs\\n\\n.. math::\\n  && Y[d_{0}, \\\\ldots, d_{axis - 1}, i_{B}, \\\\ldots, i_{M-1}, d_{axis + 1}, \\\\ldots, d_{N-1}] = \\\\\\\\\\n  && X[d_{0}, \\\\ldots, d_{axis - 1}, IDX[i_{0}, \\\\ldots, i_{B - 1}, i_{B} \\\\ldots, i_{M-1}], d_{axis + 1}, \\\\ldots d_{N-1}].\\n\\nwhere :math:`B` = `batch_dims`.\\n\\n`x.shape[:batch_dims]` must be equal to `indices.shape[:batch_dims]`.\\n\\nOutput shape is `x.shape[:axis] + indices.shape[batch_dims:] + x.shape[axis + 1]`.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Data from which to gather.\"\n      },\n      {\n        \"name\": \"Indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Index with which to gather.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Axis in `x` to gather from. `axis` must be greater than or equal to `batch_dims`.\"\n      },\n      {\n        \"name\": \"batch_dims\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"The number of batch dimensions.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Gathered output.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"GatherNd\",\n    \"description\": \"Gather elements or slices from `data` according to `indices`, which must\\nbe at least two-dimensional with the first dimension :math:`M` being less\\nor equal to the :math:`N` dimensions of `data`. Given `data` with shape\\n:math:`(X_0, X_1, ..., X_{N-1})` and indices with shape\\n:math:`(M, Y_0, ..., Y_{K-1})` output has shape\\n:math:`(Y_0, ..., Y_{K-1}, X_M, ..., X_{N-1})`. If :math:`M == N`, output\\nshape is simply :math:`(Y_0, ..., Y_{K-1})`.\\n\\nThe forward of :func:`~nnabla.functions.gather_nd` is equivalent to:\\n\\n.. code-block:: python\\n\\n  def gather_nd(data, index):\\n      import numpy as np\\n      tmp_index = index.reshape(index.shape[0], -1)\\n      tmp_index = (idx + (Ellipsis,) for idx in zip(*new_index))\\n      out_shape = index.shape[1:] + data.shape[index.shape[0]:]\\n      return np.vstack(data[idx] for idx in tmp_index).reshape(*out_shape)\\n\\nExamples:\\n\\n>>> import numpy as np, nnabla as nn, nnabla.functions as F\\n>>> nn.set_auto_forward(True)\\n>>> data = F.arange(1, 11).reshape([2, 5])\\n>>> print(data.d)\\n[[ 1.  2.  3.  4.  5.]\\n [ 6.  7.  8.  9. 10.]]\\n>>> F.gather_nd(data, [[1, 1, 0]]).shape\\n(3, 5)\\n>>> F.gather_nd(data, [[1, 1, 0], [0, 1, 0]]).shape\\n(3,)\\n>>> print(F.gather_nd(data, [[1, 1, 0], [0, 1, 0]]).d)\\n[6. 7. 1.]\\n>>> print(F.gather_nd(data, [[1, 1, 0]]).d)\\n[[ 6.  7.  8.  9. 10.]\\n [ 6.  7.  8.  9. 10.]\\n [ 1.  2.  3.  4.  5.]]\\n\\nWhen `indices` is provided as a :obj:`~nnabla.Variable` it will be\\npossible to change the actual index values after function creation.\\nIt is important to note that out-of-bound indices raise error when\\nrunning on CPU but are ignored when using an accelerated computation\\ncontext.\\n\\n>>> indices = nn.Variable((2, 1))\\n>>> indices.d = [[0], [0]]\\n>>> y = F.gather_nd(data, indices)\\n>>> print(y.d)\\n[1.]\\n>>> indices.d = [[1], [4]]\\n>>> y.forward()\\n>>> print(y.d)\\n[10.]\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array input data\"\n      },\n      {\n        \"name\": \"indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array indices\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BoolGather\",\n    \"description\": \"Gather from the input data according to the mask. \\n\\nGiven an input of :math:`(B_1, \\\\ldots, B_N, D_1, \\\\ldots, D_M)` shape and mask of :math:`(B_1, \\\\ldots, B_N)` shape, the function returns an output of :math:`(nnz, D_1, \\\\ldots, D_M)` shape and :math:`nnz` is the number of non-zero elements in mask.\\n\\n.. code-block:: python\\n\\n  import numpy as np\\n  import nnabla as nn\\n  import nnabla.functions as F\\n\\n  nn.set_auto_forward(True)\\n\\n  input = nn.Variable.from_numpy_array([[1, 2], [3, 4], [5, 6]])\\n  mask = nn.Variable.from_numpy_array([1, 0, 1])\\n  output = F.bool_gather(input, mask)\\n  \\n  print(output.d) # [[1, 2], [5, 6]]\\n\\n\\nNote that this function is normally used with the dynamic graph \\nsince this function outputs a variable-length output. If used with the static graph, \\na network has to be constructed all time in iteration.\",\n    \"inputs\": [\n      {\n        \"name\": \"input\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Data from which to gather.\"\n      },\n      {\n        \"name\": \"mask\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Mask with which to gather. Non-zero/zero elements are supposed to be a binary mask as 1/0. No gradients are computed with respect to mask.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Gathered output.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"ScatterNd\",\n    \"description\": \"Scatter `data` into a new array of given `shape` according to `indices`.\\nThis operation is the inverse of :func:`~nnabla.functions.gather_nd`.\\n\\nThe forward of :func:`~nnabla.functions.scatter_nd` is equivalent to:\\n\\n.. code-block:: python\\n\\n  def scatter_nd(data, indices, shape):\\n      import numpy as np\\n      if isinstance(indices, np.ndarray)\\n          indices = indices.tolist()\\n      result = np.zeros(shape, dtype=data.dtype)\\n      result[indices] = data\\n      return result\\n\\nExamples:\\n\\n>>> import numpy as np, nnabla as nn, nnabla.functions as F\\n>>> nn.set_auto_forward(True)\\n>>> data = nn.Variable.from_numpy_array(np.array([9, 10, 11, 12]))\\n>>> indices = nn.Variable.from_numpy_array(np.array([[4, 3, 1, 7]]))\\n>>> scattered = F.scatter_nd(data, indices, shape=(8,))\\n>>> print(scatterd.d)\\n[ 0. 11.  0. 10.  9.  0.  0. 12.]\\n>>> print(F.gather_nd(scattered, indices).d)\\n[ 9. 10. 11. 12.]\",\n    \"inputs\": [\n      {\n        \"name\": \"data\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array input data.\"\n      },\n      {\n        \"name\": \"indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array scatter indices.\"\n      },\n      {\n        \"name\": \"out\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"existing output array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"type\": \"int64[]\",\n        \"default\": \"None\",\n        \"description\": \"Shape of output variable.\"\n      },\n      {\n        \"name\": \"add\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Add the input data to the same destination specified by the indices.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of given `shape`.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"ScatterAdd\",\n    \"description\": \"Add all values from `x1` into the `x0` according to index specified by `indices`.\\nThis function adds `x1` into the copy of `x0` and outputs the copy.\\nThe original `x0` will not be changed.\\n`x0`, `indices` and `x1` must have same number of dimensions.\\n\\nThe forward of :func:`~nnabla.functions.scatter_add` is equivalent to:\\n\\n.. code-block:: python\\n\\n  def scatter_add(x0, indices, x1, axis):\\n      # Assuming each input is 3 dimensional\\n      import numpy as np\\n      output = np.copy(x0)\\n      for i in range(indices.shape[0]):\\n          for j in range(indices.shape[1]):\\n              for k in range(indices.shape[2]):\\n                  if axis == 0:\\n                      output[indices[i][j][k]][j][k] += x1[i][j][k]\\n                  elif axis == 1:\\n                      output[i][indices[i][j][k]][k] += x1[i][j][k]\\n                  elif axis == 2:\\n                      output[i][j][indices[i][j][k]] += x1[i][j][k]\\n      return output\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array which the data is added to its copy.\"\n      },\n      {\n        \"name\": \"indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array scatter indices. The size of each dimension must be equal or smaller than that of x0 except for the specified axis. The value of indices must be smaller than the size of specified axis' dimension of x0. The size of each dimension must be equal or smaller than that of x1. Indices must not be negative.\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array which is scattered and added to x0.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Axis along which to index. The axis must not exceed the inputs' dimension.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array which contains the result of scatter addition. The shape is same as x0.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BoolScatter\",\n    \"description\": \"Scatter the `input` according to the `mask`.\\n\\nGiven an input of :math:`(nnz, D_1, \\\\ldots, D_M)` shape and mask of :math:`(B_1, \\\\ldots, B_N)` shape, the function returns an output :math:`(B_1, \\\\ldots, B_N, D_1, \\\\ldots, D_M)` and :math:`nnz` is the number of non-zero elements in the mask.\\n\\n.. code-block:: python\\n\\n  import numpy as np\\n  import nnabla as nn\\n  import nnabla.functions as F\\n\\n  nn.set_auto_forward(True)\\n\\n  input0 = nn.Variable.from_numpy_array([[1, 2], [3, 4], [5, 6]])\\n  mask = nn.Variable.from_numpy_array([1, 0, 1])\\n  output0 = F.bool_gather(input0, mask)\\n  \\n  input1 = output0 + 10\\n  output1 = F.bool_scatter(input1, mask)\\n  \\n  print(output1.d)  # [[11, 12], [0, 0], [15, 16]] \\n\\nNote that the higher-order gradients of this function relies on F.gather, thus \\nthe higher-order gradients of this function is normally used with the dynamic graph.\",\n    \"inputs\": [\n      {\n        \"name\": \"input\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Data to be scattered.\"\n      },\n      {\n        \"name\": \"mask\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Mask with which to scatter. Non-zero/zero elements are supposed to be a binary mask as 1/0. No gradients are computed with respect to mask.\"\n      },\n      {\n        \"name\": \"output\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Destination of output. If specified, data are inplaced.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Scattered output.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"BoolFill\",\n    \"description\": \"Fill the data with the value to according to the mask.\\n\\n.. code-block:: python\\n\\n  import numpy as np\\n  import nnabla as nn\\n  import nnabla.functions as F\\n\\n  nn.set_auto_forward(True)\\n\\n  input = nn.Variable.from_numpy_array([[np.inf, 2], [3, np.nan]])\\n  mask = nn.Variable.from_numpy_array([[1, 0], [0, 1]])\\n  output = F.bool_fill(input, mask, -1)\\n  \\n  print(output.d)  # [[-1, 2], [3, -1]]\",\n    \"inputs\": [\n      {\n        \"name\": \"data\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Data to be filled.\"\n      },\n      {\n        \"name\": \"mask\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Mask with which to fill. Non-zero/zero elements are supposed to be a binary mask as 1/0. No gradients are computed with respect to mask.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"value\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Value to fill.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Filled output.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"PackPaddedSequence\",\n    \"description\": \"Pack a padded variable-length sequences.\\n\\nThis method packs a padded variable-length sequences.\\n\\n:math:`T_i` is the length of the :math:`i`-th Variable in the sequences.\\n:math:`B` is the batch size equal to the length of the sequences.\\n:math:`T` is the max of :math:`T_i` for all :math:`i`.\\n:math:`*` is the remaining dimensions including none.\\n\\n.. note::\\n  This function assumes the length-sorted padded sequence in the decreasing order\\n  and must be used by :func:`~nnabla.utils.rnn.pack_padded_sequence` in the dynamic computation mode.\\n  See :\",\n    \"inputs\": [\n      {\n        \"name\": \"padded_sequence\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Padded sequence of (:math:`T \\\\times B \\\\times *`) or (:math:`B \\\\times T \\\\times *`) shape.\"\n      },\n      {\n        \"name\": \"lengths\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Sequence length for each batch and always resides in CPU.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"batch_first\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"`padded_sequence` is of (:math:`T`, :math:`B`, :math:`*`) shape if False,\\notherwise (:math:`B`, :math:`T`, :math:`*`).\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"pack_sequence\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Packed sequence of (:math:`N`, :math:`*`) shape.\"\n      },\n      {\n        \"name\": \"batch_sizes\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Batch size for each time and always resides in CPU.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"PadPackedSequence\",\n    \"description\": \"Pad packed sequence.\\n\\nThis method unpacks the packed sequqnce and pad it, the inverse operation of :func:`pack_padded_sequence`.\\n\\n:math:`T_i` is the length of the :math:`i`-th Variable in the sequences.\\n:math:`B` is the batch size equal to the length of the sequences.\\n:math:`T` is the max of :math:`T_i` for all :math:`i`.\\n:math:`*` is the remaining dimensions including none.\\n\\n.. note::\\n  This function assumes the output of the length-sorted padded sequence in the decreasing order\\n  and must be used by :func:`~nnabla.utils.rnn.pad_packed_sequence` in the dynamic computation mode.\",\n    \"inputs\": [\n      {\n        \"name\": \"packed_sequence\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Packed sequence of (:math:`N`, :math:`*`) shape.\"\n      },\n      {\n        \"name\": \"batch_sizes\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Batch size for each time and always resides in CPU.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"batch_first\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"`padded_sequence` is of (:math:`T`, :math:`B`, :math:`*`) shape if False,\\notherwise (:math:`B`, :math:`T`, :math:`*`).\"\n      },\n      {\n        \"name\": \"padding_value\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Padding value.\"\n      },\n      {\n        \"name\": \"total_length\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"If not None, the outputs are padded up to the `total_length`.\\nIf the `total_length` is less than the max length in the `sequences`,\\nthe error is thrown.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"padded_sequence\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Padded sequence of (:math:`T \\\\times B \\\\times *`) or (:math:`B \\\\times T \\\\times *`) shape.\"\n      },\n      {\n        \"name\": \"lengths\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Sequence length for each batch and always resides in CPU.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"NonZero\",\n    \"description\": \"Find indices of non-zero elements.\\n\\nNonZero behaves similar to NonZero Operator in ONNX.\\n\\nExamples:\\n\\n>>> import numpy as np, nnabla as nn, nnabla.functions as F\\n>>> nn.set_auto_forward(True)\\n>>> x = F.arange(1, 10).reshape([3, 3])\\n>>> x.d[0, 1] = x.d[1, 2] = x.d[2, 2] = 0\\n>>> print(x.d)\\n[[1. 0. 3.],\\n [4. 5. 0.],\\n [7. 8. 0.]]\\n>>> y = F.nonzero(x)\\n>>> print(y.shape)\\n(2, 6)\\n>>> print(y.d)\\n[[0 0 1 1 2 2],\\n [0 2 0 1 0 1]]\\n\\nNote that this function is normally used with the dynamic graph \\nsince this function outputs a variable-length output. If used with \\nthe static graph, a network has to be constructed all time in iteration.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D arrays.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array indices.\"\n      }\n    ],\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"Interpolate\",\n    \"description\": \"Resize an ND array with interpolation.\\n\\nThe last ``len(output_size)`` dimensions of the input ``x`` are considered as the spatial dimensions to be resized.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"output_size\",\n        \"required\": true,\n        \"type\": \"int64[]\",\n        \"description\": \"Output size.\"\n      },\n      {\n        \"name\": \"mode\",\n        \"required\": true,\n        \"type\": \"string\",\n        \"description\": \"Interpolation mode chosen from ('nearest'|'linear').\"\n      },\n      {\n        \"name\": \"align_corners\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If true, the corner pixels of input and output arrays are aligned, such that the output corner pixels have the same values with the input corner pixels. The default is ``None``, and it becomes `True` if mode is 'linear', otherwise `False`.\"\n      },\n      {\n        \"name\": \"half_pixel\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If true, in the coordinate transformation, 0.5 is added to the output coordinate and 0.5 is subtracted from the input coordinate after scaling.\"\n      },\n      {\n        \"name\": \"half_pixel_for_nn\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This is a special argument to support the backward-compatibility of the nearest neighbor interpolation. Default is `False`. When in ``True``, the implementation of nearest neighbor interpolation is the old one.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ONNXResize\",\n    \"description\": \"Resize an ND array with interpolation. This function provides a \\ncompatible interface to ONNX Resize.\\n\\nReferences:\\n    * `ONNX Operators documentation.\\n    <https://github.com/onnx/onnx/blob/main/docs/Operators.md>`\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"roi\",\n        \"type\": \"float32[]\",\n        \"default\": \"()\",\n        \"description\": \"RoIs for tf_crop_and_resize.\"\n      },\n      {\n        \"name\": \"scales\",\n        \"type\": \"float32[]\",\n        \"default\": \"()\",\n        \"description\": \"Scale factors along axes.\"\n      },\n      {\n        \"name\": \"sizes\",\n        \"type\": \"int64[]\",\n        \"default\": \"()\",\n        \"description\": \"Output size.\"\n      },\n      {\n        \"name\": \"mode\",\n        \"type\": \"string\",\n        \"default\": \"nearest\",\n        \"description\": \"Interpolation mode chosen from ('nearest'|'linear'|'cubic').\"\n      },\n      {\n        \"name\": \"coordinate_transformation_mode\",\n        \"type\": \"string\",\n        \"default\": \"half_pixel\",\n        \"description\": \"How to transform the coordinate in the resized tensor to the coordinate in the original tensor. This mode is chosen from ('half_pixel'|'pytorch_half_pixel'|'align_corners'|'asymmetric'|'tf_crop_and_resize').\"\n      },\n      {\n        \"name\": \"cubic_coeff_a\",\n        \"type\": \"float32\",\n        \"default\": -0.75,\n        \"description\": \"The coefficient used in cubic interpolation.\"\n      },\n      {\n        \"name\": \"exclude_outside\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Whether to set coefficients to zero when sampling locations is outside the input tensor.\"\n      },\n      {\n        \"name\": \"extrapolation_value\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"An extrapolation value used when a sampling location is outside the input tensor at tf_crop_and_resize mode.\"\n      },\n      {\n        \"name\": \"nearest_mode\",\n        \"type\": \"string\",\n        \"default\": \"round_prefer_floor\",\n        \"description\": \"Rounding mode for nearest-neighbor interpolation.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"FFT\",\n    \"description\": \"Complex-to-complex Discrete Fourier Transform,\\n\\n.. math::\\n\\n  X_{k_1, \\\\ldots, k_d} = \\\\sum_{n_1=0}^{N_1-1} \\\\dots \\\\sum_{n_d=0}^{N_d-1} x_{n_1, \\\\ldots, n_d} \\\\exp\\\\left(-2 \\\\pi j \\\\left( \\\\sum_{i=0}^{d} \\\\frac{k_i n_i}{N_i} \\\\right) \\\\right),\\n\\nwhere\\n\\n.. math::\\n\\n  k_i = 0, \\\\ldots, N_i - 1.\\n\\nThis function now supports 1-D, 2-D, and 3-D DFT with or without the leading batch dimension(s).\\n\\nThe input is expected to be complex-valued with at least signal_ndim + 1 dimensions.\\nThe last dimension has a shape of two where x[..., 0] is the real part and x[..., 1] the imaginary part.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n  import numpy as np\\n  import nnabla as nn\\n  import nnabla.functions as F\\n  from nnabla.ext_utils import get_extension_context\\n\\n  ctx = get_extension_context(\\\"cudnn\\\")\\n  nn.set_default_context(ctx)\\n\\n  # Example for a batched 2D-FFT and 2D-IFFT (batch-size: 2, data-size: 4x3)\\n  x_data = np.random.rand(2, 4, 3) + 1j * np.random.rand(2, 4, 3)\\n  x = nn.Variable.from_numpy_array(np.stack([np.real(x_data), np.imag(x_data)], axis=3))\\n  y = F.fft(x, signal_ndim=2, normalized=True)\\n  z = F.ifft(y, signal_ndim=2, normalized=True)\\n  z.forward()\\n\\n  np.allclose(z.d[..., 0] + 1j*z.d[...,1], x_data)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"signal_ndim\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"The number of dimensions for each signal. It must be 1, 2, or 3.\"\n      },\n      {\n        \"name\": \"normalized\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Use unitary normalization. If `True`, the normalization constant :math:`\\\\sqrt{\\\\frac{1}{\\\\prod_{i=1}^{d} N_i}}` is multiplied.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"FFT transformed signal.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"IFFT\",\n    \"description\": \"Complex-to-complex inverse Discrete Fourier Transform,\\n\\n.. math::\\n\\n  X_{k_1, \\\\ldots, k_d} = \\\\frac{1}{\\\\prod_{i=1}^{d} N_i} \\\\sum_{n_1=0}^{N_1-1} \\\\dots \\\\sum_{n_d=0}^{N_d-1} x_{n_1, \\\\ldots, n_d} \\\\exp\\\\left(2 \\\\pi j \\\\left( \\\\sum_{i=0}^{d} \\\\frac{k_i n_i}{N_i} \\\\right) \\\\right),\\n\\nwhere\\n\\n.. math::\\n\\n  k_i = 0, \\\\ldots, N_i - 1.\\n\\nThis function now supports 1-D, 2-D, and 3-D DFT with or without the leading batch dimension(s).\\n\\nThe input is expected to be complex-valued with at least signal_ndim + 1 dimensions.\\nThe last dimension has a shape of two where x[..., 0] is the real part and x[..., 1] the imaginary part.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"signal_ndim\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"The number of dimensions for each signal. It must be 1, 2, or 3.\"\n      },\n      {\n        \"name\": \"normalized\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Use unitary normalization. If `True`, the normalization constant :math:`\\\\frac{1}{\\\\prod_{i=1}^{d} N_i}` becomes :math:`\\\\sqrt{\\\\frac{1}{\\\\prod_{i=1}^{d} N_i}}`.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"IFFT transformed signal.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"STFT\",\n    \"description\": \"Short-time Fourier transform.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Time domain sequence of size `batch_size x sample_size`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"window_size\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Size of STFT analysis window.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Number of samples that we shift the window, also called `hop size`.\"\n      },\n      {\n        \"name\": \"fft_size\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Size of the FFT, the output will have `fft_size // 2+ 1` frequency bins.\"\n      },\n      {\n        \"name\": \"window_type\",\n        \"type\": \"string\",\n        \"default\": \"hanning\",\n        \"description\": \"Analysis window, can be either `hanning`, `hamming` or `rectangular`.\"\n      },\n      {\n        \"name\": \"center\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If `True`, then the signal `x` is padded by half the FFT size using reflection padding.\"\n      },\n      {\n        \"name\": \"pad_mode\",\n        \"type\": \"string\",\n        \"default\": \"reflect\",\n        \"description\": \"Padding mode, which can be `'constant'` or `'reflect'`. `'constant'` pads with `0`.\"\n      },\n      {\n        \"name\": \"as_istft_backward\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, then forward execution behaves as backward execution of ISTFT, treating input `x` as output gradient of ISTFT and outputs `y_r` and `y_i` as inputs gradient of ISTFT. This option is only used in nn.grad operator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y_r\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Real part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`.\"\n      },\n      {\n        \"name\": \"y_i\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Imaginary part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ISTFT\",\n    \"description\": \"Inverse short-time Fourier transform.\\n\\n.. note::\\n  We use a constant square inverse window for the reconstruction of the time-domain signal, therefore, the first and last `window_size - stride` are not perfectly reconstructed.\",\n    \"inputs\": [\n      {\n        \"name\": \"y_r\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Real part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`.\"\n      },\n      {\n        \"name\": \"y_i\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Imaginary part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"window_size\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Size of STFT analysis window.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Number of samples that we shift the window, also called `hop size`.\"\n      },\n      {\n        \"name\": \"fft_size\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Size of the FFT, the output will have `fft_size // 2+ 1` frequency bins.\"\n      },\n      {\n        \"name\": \"window_type\",\n        \"type\": \"string\",\n        \"default\": \"hanning\",\n        \"description\": \"Analysis window, can be either `hanning`, `hamming` or `rectangular`.\"\n      },\n      {\n        \"name\": \"center\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If `True`, then the signal `x` is padded by half the FFT size using reflection padding.\"\n      },\n      {\n        \"name\": \"pad_mode\",\n        \"type\": \"string\",\n        \"default\": \"reflect\",\n        \"description\": \"Padding mode corresponding to STFT `pad_mode`, which can be `'constant'` or `'reflect'`. `'constant'` pads with `0`. This option is ignored for the normal use of ISTFT. You need to set the same `pad_mode` only when `as_stft_backward == True`.\"\n      },\n      {\n        \"name\": \"as_stft_backward\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, then forward execution behaves as backward execution of STFT, treating inputs `y_r` and `y_i` as outputs gradient of STFT and output `x` as input gradient of STFT. This option is only used in nn.grad operator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Time domain sequence of size `batch_size x sample_size`.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Dropout\",\n    \"description\": \"Dropout.\\nSamples a number :math:`u` from a uniform distribution in :math:`[0, 1]` ,\\nand ignores the input if :math:`u \\\\leq p`.\\n\\n.. math::\\n    y = \\\\left\\\\{\\n    \\\\begin{array}{ll}\\n      \\\\frac{x}{1 - p} & (u > p) \\\\\\\\\\n      0 & ({\\\\rm otherwise})\\n    \\\\end{array} \\\\right.\\n\\nNote:\\n    Usually dropout only applied during training as below\\n    (except `MC dropout`_). If you want to use dropout as an MC dropout, remove 'if train:'.\\n\\n    .. code-block:: python\\n\\n        h = PF.affine(x, num_hidden)\\n        if train:\\n            h = F.dropout(h, 0.5)\\n\\n.. _MC dropout: https://arxiv.org/abs/1506.02142\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"p\",\n        \"type\": \"float64\",\n        \"default\": 0.5,\n        \"description\": \":math:`p` in definition.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TopKData\",\n    \"description\": \"Select the `k` largest values from each sample in `x` to\\npropagate unmodified and set all other values to 0. If `abs` is\\nTrue, the `k` largest values are selected by magnitude. If\\n`reduce` is True (the default), all feature dimensions are\\nreduced to a single dimension of size `k` that propagates only\\nthe `k` largest values. Otherwise, if `reduce` is False, input\\nand output dimensions are identical. Dimensions before\\n`base_axis` are treated as number of sample dimensions and `k`\\nvalues get selected from all elements of a sample (dimensions\\nfrom `base_axis`) regardless of shape.\\n\\n>>> import nnabla as nn, nnabla.functions as F\\n>>> x = nn.Variable((4, 5, 6))\\n>>> F.top_k_data(x, 3, reduce=False).shape\\n(4, 5, 6)\\n>>> F.top_k_data(x, 3, reduce=True).shape\\n(4, 3)\\n>>> F.top_k_data(x, 3, reduce=True, base_axis=2).shape\\n(4, 5, 3)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"k\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Number of largest data values to propagate.\"\n      },\n      {\n        \"name\": \"abs\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Determine largest data values by magnitude.\"\n      },\n      {\n        \"name\": \"reduce\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Reduce feature size to one dimension of size `k`.\"\n      },\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"First dimension of the sample shape.\"\n      },\n      {\n        \"name\": \"largest\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Whether to select the `k` largest or smallest values.\"\n      },\n      {\n        \"name\": \"with_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Return top-k values and indices.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      },\n      {\n        \"name\": \"indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of top-k indices.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TopKGrad\",\n    \"description\": \"Select the `k` largest gradients for each sample in `x` to\\nback-propagate unmodified and set all other gradients to 0. If\\n`abs` is True, the `k` largest gradients are selected by\\nmagnitude. Dimensions before `base_axis` are treated as number\\nof sample dimensions and `k` gradients get selected from all\\ngradients of a sample (dimensions from `base_axis`) regardless\\nof shape.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"k\",\n        \"required\": true,\n        \"type\": \"int64\",\n        \"description\": \"Number of largest gradients to propagate.\"\n      },\n      {\n        \"name\": \"abs\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Determine largest gradients by magnitude.\"\n      },\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"First dimension of the sample shape.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with same shape and data as `x`.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Rand\",\n    \"description\": \"Samples numbers from a uniform distribution :math:`x \\\\sim U(low, high)`\\ngiven lowest value :math:`low`, upper bound :math:`high`,\\nand shape of the returned Variable.\",\n    \"attributes\": [\n      {\n        \"name\": \"low\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \":math:`low` in definition.\"\n      },\n      {\n        \"name\": \"high\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \":math:`high` in definition.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of returned variable.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Variable with the shape specified in the argument.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Randint\",\n    \"description\": \"Samples integer numbers from a uniform distribution :math:`x \\\\sim U(low, high)`\\ngiven lowest value :math:`low`, upper bound :math:`high`, and the shape of the returned Variable. The lowest\\nvalue :math:`low` is included in the range, while the upper bound :math:`high` is excluded, corresponding to the half-open\\ninterval :math:`[low, high)`.\",\n    \"attributes\": [\n      {\n        \"name\": \"low\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \":math:`low` in definition.\"\n      },\n      {\n        \"name\": \"high\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \":math:`high` in definition.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of returned variable.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Variable with the shape specified in the argument. The dtype is int32.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Randn\",\n    \"description\": \"Samples numbers from a normal distribution :math:`x \\\\sim N(\\\\mu, \\\\sigma)`\\ngiven mean :math:`\\\\mu`, standard deviation :math:`\\\\sigma`,\\nand shape of the returned Variable.\",\n    \"attributes\": [\n      {\n        \"name\": \"mu\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \":math:`\\\\mu` in definition.\"\n      },\n      {\n        \"name\": \"sigma\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \":math:`\\\\sigma` in definition.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of returned variable.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Variable with the shape specified in the argument.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandBinomial\",\n    \"description\": \"Samples numbers from a binomial distribution :math:`x \\\\sim B(n, p)`\\ngiven the numbers of trials :math:`n`, probability :math:`p`,\\nand shape of the returned Variable.\\nWhen :math:`n = 1`, this behaves like the Bernoulli distriburion.\",\n    \"attributes\": [\n      {\n        \"name\": \"n\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \":math:`n` in definition, the number of trials.\"\n      },\n      {\n        \"name\": \"p\",\n        \"type\": \"float32\",\n        \"default\": 0.5,\n        \"description\": \":math:`p` in definition, probability of success.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of returned variable.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Variable with the shape specified in the argument.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandBeta\",\n    \"description\": \"Samples numbers from a beta distribution :math:`x \\\\sim \\\\beta(\\\\alpha, \\\\beta)`.\",\n    \"attributes\": [\n      {\n        \"name\": \"alpha\",\n        \"type\": \"float32\",\n        \"default\": 0.5,\n        \"description\": \":math:`\\\\alpha`, scale parameter.\"\n      },\n      {\n        \"name\": \"beta\",\n        \"type\": \"float32\",\n        \"default\": 0.5,\n        \"description\": \":math:`\\\\beta`, scale parameter.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of returned variable.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Variable with the shape specified in the argument.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandGamma\",\n    \"description\": \"Samples numbers from a gamma distribution :math:`x \\\\sim \\\\frac {\\\\gamma(k, \\\\frac {x}{\\\\theta})}{\\\\Gamma(k)}`.\",\n    \"attributes\": [\n      {\n        \"name\": \"k\",\n        \"type\": \"float32\",\n        \"default\": 0.5,\n        \"description\": \"k, scale parameter.\"\n      },\n      {\n        \"name\": \"theta\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \":math:`\\\\theta`, scale parameter.\"\n      },\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Shape of returned variable.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Variable with the shape specified in the argument.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandomChoice\",\n    \"description\": \"Generate random samples from population `x` with selection probabilities\\ndetermined by the relative weights `w`. The number of samples to draw is\\ngiven by the product of `shape`\\\\s dimensions, and the samples are returned\\nwith the given `shape`. By default, samples are drawn with replacement,\\ni.e. selection of a specific population member is solely determined by\\nits associated weight. Sampling without replacement, where any population\\nmember may be drawn only once, is used if `replace` is set to False.\\n\\nFor both `x` and `w` the innermost dimension corresponds to the individual\\npopulations and their weights from which samples are returned with the\\nrequested `shape` following all outermost dimensions of the input.\\n\\n.. code-block:: python\\n\\n  import nnabla as nn\\n  import nnabla.functions as F\\n  import numpy as np\\n  nn.set_auto_forward(True)\\n\\n  # x holds two populations\\n  x = nn.Variable.from_numpy_array(np.array([[11, 22, 33], [110, 220, 330]]))\\n  # w holds the weights for each population\\n  w = nn.Variable.from_numpy_array(np.array([[10, 20, 70], [70, 20, 10]]))\\n\\n  # draw one sample from each population\\n  y = F.random_choice(x, w)  # y.shape => (2, 1)\\n\\n  # draw 12 samples with shape (3, 4) from each population\\n  y = F.random_choice(x, w, shape=(3, 4))  # y.shape => (2, 3, 4)\\n\\nNote that weights must not be less than zero and for each population the\\nsum of weights must be greater than zero. Additionally, sampling without\\nreplacement requires that the number of non-zero weights is not less than\\nthe number of samples to be drawn. These conditions are verified in \\\"cpu\\\"\\ncomputation context but not when using \\\"cuda\\\" or \\\"cudnn\\\" acceleration\\n(this would require additional device synchronization steps penalizing\\nperformance).\\n\\nRandom sampling from an implicit array of index values (like categorical\\nor multinomial) can be realized with input `x` constructed as indices.\\n\\n.. code-block:: python\\n\\n  w = nn.Variable.from_numpy_array(np.array([1, 2, 3, 2, 1]))\\n  y = F.random_choice(F.arange(0, 5), w)\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array from which a random sample is generated.\"\n      },\n      {\n        \"name\": \"w\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of associated weights of elements in `x`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"[]\",\n        \"description\": \"Number and shape of generated samples.\"\n      },\n      {\n        \"name\": \"replace\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Whether sampling is with or without replacement.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandomCrop\",\n    \"description\": \"RandomCrop randomly extracts a portion of an array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"x.shape\",\n        \"description\": \"The data size to extract. For example, to randomly extract a portion of the image (3,48,48) from a 3,64,64 image, specify (3,48,48).\"\n      },\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"No Description\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandomFlip\",\n    \"description\": \"Reverses the order of elements of the specified dimension of an array at 50% probability.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axes\",\n        \"type\": \"int64[]\",\n        \"default\": \"[len(x.shape) - 1]\",\n        \"description\": \"The index of the axis to reverse the order of the elements. Axis indices take on values 0, 1, 2, and so on from the left. For example, to flip a 32 (W) by 24 (H) 100 RGB images (100, 3,24,32) vertically and horizontally at random, specify (2,3).\"\n      },\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"No Description\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandomShift\",\n    \"description\": \"Randomly shifts the array elements within the specified range.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shifts\",\n        \"type\": \"int64[]\",\n        \"default\": \"(0,) * len(x.shape)\",\n        \"description\": \"Max absolute amount to shift elements. For example, to shift image data horizontally by :math:`\\\\pm 2` pixels and vertically by :math:`\\\\pm 3` pixels, specify (3,2).\"\n      },\n      {\n        \"name\": \"border_mode\",\n        \"type\": \"string\",\n        \"default\": \"nearest\",\n        \"description\": \"Specify how to process the ends of arrays whose values will be undetermined as a result of shifting. nearest: The data at the ends of the   original array is copied and used. reflect: Original data reflected at   the ends of the original array is used. constant: Constant value is used.\"\n      },\n      {\n        \"name\": \"constant_value\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Value used for outside of the original array if border_mode='constant'.\"\n      },\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"No Description\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"RandomErase\",\n    \"description\": \"Randomly erase patches of the inputs and replace with random values.\\n\\nErasing is applied for each sample and for each `n` with the given probability, the randomly\\nselected area ratio and aspect ratio if `share` is `True`;\\notherwise (`share`=`False`), for each feature additionally.\\n\\nRandom patch are selected by random coordinates as the following,\\n\\n.. math::\\n\\n  S_e &&= Uniform(s_l, s_h) \\\\times S \\\\\\\\\\n  r_e &&= Uniform(r_l, r_h) \\\\\\\\\\n  H_e &&= \\\\sqrt{S_e \\\\times r_e} \\\\\\\\\\n  W_e &&= \\\\sqrt{S_e / r_e} \\\\\\\\\\n  y_e &&= Uniform(0, H - H_e) \\\\\\\\\\n  x_e &&= Uniform(0, W - W_e),\\n\\nwhere :math:`S` is the area, :math:`s_l` and :math:`s_h` are the low and high values of\\nthe area ratio range, :math:`r_l` and :math:`r_h` are the low and high values\\nof the aspect ratio range, :math:`H_e` and :math:`W_e` are height and width of a patch,\\nand :math:`y_e` and :math:`x_e` are the start coordinates of a patch. If a pixel of the inputs\\nfalls in this patch, the value of that pixel is replaced with a random value in `replacements`\\nrange.\\n\\nBackward is implemented as passing gradients if `ste_fine_grained` is False; otherwise,\\nthe backward only occurs in regions not erased.\\n\\nReferences:\\n\\n  * `Zhun Zhong, Liang Zheng, Guoliang Kang, Shaozi Li, Yi Yang,\\n    Random Erasing Data Augmentation,\\n    <https://arxiv.org/abs/1708.04896>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"prob\",\n        \"type\": \"float32\",\n        \"default\": 0.5,\n        \"description\": \"Probability to erase.\"\n      },\n      {\n        \"name\": \"area_ratios\",\n        \"type\": \"float32[]\",\n        \"default\": \"(0.02, 0.4)\",\n        \"description\": \"Low and high of the area ratio range.\"\n      },\n      {\n        \"name\": \"aspect_ratios\",\n        \"type\": \"float32[]\",\n        \"default\": \"(0.3, 3.3333)\",\n        \"description\": \"Low and high of the aspect ratios range.\"\n      },\n      {\n        \"name\": \"replacements\",\n        \"type\": \"float32[]\",\n        \"default\": \"(0.0, 255.0)\",\n        \"description\": \"Low and high of the replacement value range.\"\n      },\n      {\n        \"name\": \"n\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Max number of patches to be erased.\"\n      },\n      {\n        \"name\": \"share\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Use a same bounding box randomly picked over the feature dimension when being True. Default is True.\"\n      },\n      {\n        \"name\": \"inplace\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"This option is obsolete and ignored. Output is never in-placed with input.\"\n      },\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      },\n      {\n        \"name\": \"ste_fine_grained\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Straight Through Estimator is fine-grained or not. Default is True.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ImageAugmentation\",\n    \"description\": \"ImageAugmentation randomly alters the input image.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"shape\",\n        \"type\": \"shape\",\n        \"default\": \"x.shape\",\n        \"description\": \"The output image data size.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0, 0)\",\n        \"description\": \"Border padding values for each spatial axis. Padding will be added both sides of the dimension.\"\n      },\n      {\n        \"name\": \"min_scale\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"The minimum scale ratio when randomly scaling the image. For example, to scale down to 0.8 times the size of the original image, specify \\\"0.8\\\". To not apply random scaling, set both min_scale and max_scale to \\\"1.0\\\".\"\n      },\n      {\n        \"name\": \"max_scale\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"The maximum scale ratio when randomly scaling the image. For example, to scale down to 2 times the size of the original image, specify \\\"2.0\\\".\"\n      },\n      {\n        \"name\": \"angle\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"The rotation angle range in radians when randomly rotating the image. The image is randomly rotated in the -Angle to +Angle range. For example, to rotate in a +-15 degree range, specify \\\"0.26\\\" (15 degrees/360 degrees * 2PI). To not apply random rotation, specify \\\"0.0\\\".\"\n      },\n      {\n        \"name\": \"aspect_ratio\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"The aspect ratio range when randomly deforming the image. For example, to deform aspect ratio of image from 1:1.3 to 1.3:1, specify \\\"1.3\\\". To not apply random deforming, specify \\\"1.0\\\".\"\n      },\n      {\n        \"name\": \"distortion\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"The distortion range when randomly distorting the image. To not apply distortion, specify \\\"0.0\\\".\"\n      },\n      {\n        \"name\": \"flip_lr\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Whether to randomly flip the image horizontally at 50% probability.\"\n      },\n      {\n        \"name\": \"flip_ud\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Whether to randomly flip the image vertically at 50% probability.\"\n      },\n      {\n        \"name\": \"brightness\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"The absolute range of values to randomly add to the brightness. A random value in the -Brightness to +Brightness range is added to the brightness. For example, to vary the brightness in the -0.05 to +0.05 range, specify \\\"0.05\\\". To not apply random addition to brightness, specify \\\"0.0\\\".\"\n      },\n      {\n        \"name\": \"brightness_each\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Whether to apply the random addition to brightness (as specified by brightness) to each color channel. True: brightness is added based on a different random number for each channel. False: brightness is added based on a random number common to all channels.\"\n      },\n      {\n        \"name\": \"contrast\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"The range in which to randomly vary the image contrast. The contrast is varied in the 1/Contrast times to Contrast times range. The output brightness is equal to (input - contrast_center) * contrast + contrast_center. For example, to vary the contrast in the 0.91 times to 1.1 times range, specify \\\"1.1\\\". To not apply random contrast variation, specify \\\"1.0\\\".\"\n      },\n      {\n        \"name\": \"contrast_center\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Intensity center used for applying contrast.\"\n      },\n      {\n        \"name\": \"contrast_each\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Whether to apply the random contrast variation (as specified by contrast) to each color channel. True: contrast is varied based on a different random number for each channel. False: contrast is varied based on a random number common to all channels.\"\n      },\n      {\n        \"name\": \"noise\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Sigma of normal random number to be added.\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SigmoidCrossEntropy\",\n    \"description\": \"Element-wise cross entropy between `x` and the target variables, passed to a sigmoid function.\\n\\n.. math::\\n    y_i = - \\\\left(x^{(1)}_i \\\\ln \\\\left(\\\\sigma \\\\left(x^{(0)}_i \\\\right)\\\\right) + \\\\\\n    \\\\left(1 - x^{(1)}_i\\\\right) \\\\ln \\\\left(1 - \\\\sigma \\\\left(x^{(0)}_i \\\\\\n    \\\\right)\\\\right)\\\\right)\\n\\nwhere :math:`\\\\sigma(s)=\\\\frac{1}{1+\\\\exp(-s)}`.\\n\\nNote:\\n    SigmoidCrossEntropy is equivalent to Sigmoid+BinaryCrossEntropy, but computing them at once has the effect of reducing computational error.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array. Typically indicates a score. The value lies in :math:`[-\\\\infty, \\\\infty]`\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of labels. Only 0 or 1 value is allowed.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of element-wise losses.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryCrossEntropy\",\n    \"description\": \"Element-wise cross entropy between `x` and the target variables.\\n\\n.. math::\\n    y_i = - \\\\left(x^{(1)}_i * \\\\ln \\\\left(x^{(0)}_i\\\\right) + \\\\left(1 - \\\\\\n    x^{(1)}_i\\\\right) * \\\\ln \\\\left(1 - x^{(0)}_i\\\\right)\\\\right).\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Probabilities N-D array. :math:`-\\\\infty` to :math:`\\\\infty`.\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of labels. Usually set as 0 or 1, but, unlike SigmoidCrossEntropy, it allows probability (0 to 1) as inputs and backpropagation can be done.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of element-wise losses.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxCrossEntropy\",\n    \"description\": \"Element-wise cross entropy between the variables and the variables of a label given by a category index with Softmax normalization.\\n\\n.. math::\\n    y_{j} = -\\\\ln \\\\left(\\\\frac{\\\\exp(x_{j,t_j})}{\\\\sum_{i'} \\\\exp(x_{j,i'})}\\\\right)\\n\\nalong dimension specified by axis (:math:`i` is the axis where normalization is performed on).\\n\\nNote:\\n    SoftmaxCrossEntropy is equivalent to Softmax+CategoricalCrossEntropy, but computing them at once has the effect of reducing computational error.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array. Typically indicates a score. :math:`(D_1 \\\\times ... \\\\times D_i \\\\times ... \\\\times D_N)`\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of labels. :math:`(D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N)` , each label should be the index from 0 to n-class, -1 if not belongs any class.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x.shape) - 1\",\n        \"description\": \"Axis normalization is taken.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of element-wise losses. :math:`(D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N)`\"\n      }\n    ]\n  },\n  {\n    \"name\": \"CategoricalCrossEntropy\",\n    \"description\": \"Element-wise cross entropy between `x` and the target `t` where targets are given by a category index.\\n\\n.. math::\\n    y_{j} = -\\\\ln \\\\left( x_{j, t_j} \\\\right)\\n\\nalong dimension specified by axis (:math:`i` is the axis where normalization is performed on).\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array. Typically indicates a score. :math:`(D_1 \\\\times ... \\\\times D_i \\\\times ... \\\\times D_N)`\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of labels. :math:`(D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N)`, each label should be the index from 0 to n-class, -1 if not belongs any class.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x.shape) - 1\",\n        \"description\": \"Axis normalization is taken.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of element-wise losses. :math:`(D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N)`\"\n      }\n    ]\n  },\n  {\n    \"name\": \"SquaredError\",\n    \"description\": \"Element-wise squared error\\n\\n.. math::\\n    y_i = \\\\left(x^{(0)}_i - x^{(1)}_i\\\\right)^2.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AbsoluteError\",\n    \"description\": \"Element-wise absolute error\\n\\n.. math::\\n    y_i = | x^{(0)}_i - x^{(1)}_i |.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"HuberLoss\",\n    \"description\": \"Element-wise Huber loss\\n\\n.. math::\\n    y_i= \\\\left\\\\{\\n    \\\\begin{array}{ll}\\n      d^2 & (|d| < \\\\delta)\\\\\\\\\\n      \\\\delta (2 |d| - \\\\delta) & ({\\\\rm otherwise})\\n    \\\\end{array} \\\\right.\\n\\nwhere :math:`d = x^{(0)}_i - x^{(1)}_i`\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"delta\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Delta\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of element-wise losses.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"EpsilonInsensitiveLoss\",\n    \"description\": \"Element-wise Epsilon Insensitive Loss\\n\\n.. math::\\n    y_i= \\\\left\\\\{\\n    \\\\begin{array}{ll}\\n      | x^{(0)}_i - x^{(1)}_i | - \\\\epsilon & if \\\\ \\\\ | x^{(0)}_i - x^{(1)}_i | > \\\\epsilon \\\\\\\\\\n\\t\\t\\t0 & otherwise\\n    \\\\end{array} \\\\right.\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"epsilon\",\n        \"required\": true,\n        \"type\": \"float32\",\n        \"description\": \"Insensitive parameter.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of element-wise losses.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"KLMultinomial\",\n    \"description\": \"The Kullback Leibler Divergence for multinomial distributions.\\n\\n.. math::\\n    D = \\\\sum_i p_i \\\\log \\\\left( \\\\frac{p_i}{q_i} \\\\right)\",\n    \"inputs\": [\n      {\n        \"name\": \"p\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of the source categorical probabilities\"\n      },\n      {\n        \"name\": \"q\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of the target categorical probabilities\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"D\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Kullback Leibler divergence :math:`KL(p \\\\parallel q)`.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"AffineGrid\",\n    \"description\": \"Generate the source grid based on the normalized target grid with `size`.\\nThe target grid is first normalized in [-1, 1], then\\ntranformed by the affine transformation :math:`\\\\theta` to generate\\nthe source grid. 2D and 3D grid are supported now.\\n\\nThis function is normally used with the `warp_by_grid` function for\\nconstructing the spatial transformer.\",\n    \"inputs\": [\n      {\n        \"name\": \"theta\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the shape (:math:`B \\\\times 2 \\\\times 3`), the sample-wise affine transformation matrix.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"size\",\n        \"required\": true,\n        \"type\": \"int64[]\",\n        \"description\": \"The grid size of (:math:`H \\\\times W`) for 2D and (:math:`D \\\\times H \\\\times W`) for 3D.\"\n      },\n      {\n        \"name\": \"align_corners\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If `True`, the top-left and bottom-right pixels correspond to (-1, -1) and (1, 1) respectively since a pixel is located on the corner of a grid, and the target grid is normalized in [-1, 1].\\nIf `False`, the normalized target grid in [-1, 1] is scaled by `size - 1 / size` according to the respective spatial size (e.g., :math:`H` and :math:`W`) before the transformation since a pixel is located on a center of a cell in a grid.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"grid\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the shape (:math:`B \\\\times H \\\\times W \\\\times 2`) for 2D and (:math:`B \\\\times D \\\\times H \\\\times W \\\\times 3`) for 3D. The last dimension of 2 is for (x, y) and of 3 for (x, y, z). The `gird` is used as the source grid for the warping.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"WarpByGrid\",\n    \"description\": \"Warp the input data by the grid.\\nThis function is normally used with the generated normalized grid by\\nthe `affine_grid` function for constructing the spatial transformer.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input data to be warped with the shape (:math:`B \\\\times C \\\\times H_{in} \\\\times W_{in}`) for 2D and (:math:`B \\\\times C \\\\times D_{in} \\\\times H_{in} \\\\times W_{in}`) for 3D.\"\n      },\n      {\n        \"name\": \"grid\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Grid warping the input data with the shape (:math:`B \\\\times H_{out} \\\\times W_{out} \\\\times 2`) for 2D and (:math:`B \\\\times D_{out} \\\\times H_{out} \\\\times W_{out} \\\\times 3`) for 3D. The last dimension of 2 is for (x, y) or 3 for (x, y, z).\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"mode\",\n        \"type\": \"string\",\n        \"default\": \"linear\",\n        \"description\": \"Interpolation mode, linear or nearest.\"\n      },\n      {\n        \"name\": \"padding_mode\",\n        \"type\": \"string\",\n        \"default\": \"zero\",\n        \"description\": \"Padding mode when the grid value is outside [-1, 1]. If this is \\\"zero\\\", 0 is used for padding. \\\"reflect\\\" uses the values reflected at the ends of the original input data like the mirror. \\\"repeat\\\" used the values at the ends of the original input data.\"\n      },\n      {\n        \"name\": \"align_corners\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"The target grid normalized in [-1, 1] is scaled by `size - 1 / size` according to the respective spatial size (e.g., :math:`H` and :math:`W`) before the transformation if this is `False`. If this is `True`, the top-left and bottom-right pixels correspond to (-1, -1) and (1, 1) respectively.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output data warped by the grid.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"WarpByFlow\",\n    \"description\": \"Transform the image(s) *data* by *flow* field(s) of offset vectors such\\nthat each output pixel corresponds to the input image pixel at the\\nrelative offset location given by horizontal and vertical flow values\\n(in other words, the flow field describes the coordinate displacements\\nfor each output pixel to the corresponding input pixel). Both *data* and\\n*flow* are 4-D variables (in \\\"NCHW\\\" layout) with identical shape except\\nthe *flow* channel dimension (which is always 2).\\n\\n.. math::\\n    output_{n,c,y,x} = data_{n,c,y',x'},\\n\\nwhere\\n\\n.. math::\\n    y' &=& y + flow_{n,1,y,x}, \\\\\\\\\\n    x' &=& x + flow_{n,0,y,x}.\\n\\nThe output pixel values at :math:`y'` and :math:`x'` locations are\\nobtained by bilinear interpolating between the 4 closest pixels of the\\ninput image. Pixel values outside of the input image are implicitly\\npadded with the value of the closest boundary pixel.\",\n    \"inputs\": [\n      {\n        \"name\": \"data\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input image data with shape `(N, Channels, Height, Width)`.\"\n      },\n      {\n        \"name\": \"flow\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Flow field vectors with shape `(N, 2, Height, Width)`.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"warped_image\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Transformed image data with shape `(N, Channels, Height, Width)`.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinarySigmoid\",\n    \"description\": \"Element-wise binary sigmoid function. In the forward pass, it computes\\n\\n.. math::\\n    f(x) = \\\\begin{cases}\\n        1 & (x > 0) \\\\\\\\\\n        0 & ({\\\\rm otherwise})\\\\end{cases},\\n\\nbut in the backward pass, a straight-through approximation of the gradient\\nis used, i.e.,\\n\\n.. math::\\n    \\\\frac{\\\\partial f(x)}{\\\\partial x} =\\n    \\\\begin{cases}\\n        0 & (|x| \\\\geq 1) \\\\\\\\\\n        \\\\frac{1}{2} & ({\\\\rm otherwise})\\n    \\\\end{cases}.\\n\\nReferences:\\n\\n    * `Courbariaux, Matthieu, and Yoshua Bengio. Binarynet: Training deep\\n      neural networks with weights and activations constrained to+ 1 or-1.\\n      <https://arxiv.org/abs/1602.02830>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input .\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryTanh\",\n    \"description\": \"Element-wise binary tanh function. In the forward pass, it computes\\n\\n.. math::\\n    f(x) = \\\\begin{cases}\\n        1 & (x > 0) \\\\\\\\\\n        -1 & ({\\\\rm otherwise})\\n    \\\\end{cases},\\n\\nbut in the backward pass, a straight-through approximation of the gradient\\nis used, i.e.,\\n\\n.. math::\\n    \\\\frac{\\\\partial f(x)}{\\\\partial x} =\\n    \\\\begin{cases}\\n        0 & (|x| \\\\geq 1) \\\\\\\\\\n        1 & ({\\\\rm otherwise}) \\\\end{cases}.\\n\\nReferences:\\n\\n    * `Courbariaux, Matthieu, and Yoshua Bengio. Binarynet: Training deep\\n      neural networks with weights and activations constrained to+ 1 or-1.\\n      <https://arxiv.org/abs/1602.02830>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input .\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryConnectAffine\",\n    \"description\": \"This function provides a BinaryConnect affine layer. It computes in\\nthe forward pass\\n\\n.. math::\\n\\n    y_j = \\\\sum_{i} sign(w_{j,i}) x_i,\\n\\ni.e., the weights :math:`w_{j,i}` are binarized to :math:`sign(w_{j,i})` and,\\nhence, each weight is in :math:`\\\\{-1,\\\\,1\\\\}`. By this weight binarization, the\\ninner product computations do not require any multiplications anymore as\\nthey turn into additions/subtractions.\\n\\nThis function should be used together with\\n:meth:`~nnabla.functions.batch_normalization`.\\n\\n.. note::\\n\\n    1) If you would like to share the binary weights between other\\n    layers, please use the standard, floating value weights (`weight`)\\n    and not the binary weights (`binary_weight`).\\n\\n    2) The weights and the binary weights become in sync only after a call to\\n    :meth:`~nnabla.Variable.forward`, and not after a call to\\n    :meth:`~nnabla.Variable.backward`. If you wish to store the parameters of\\n    the network, remember to call :meth:`~nnabla.Variable.forward`, once before\\n    doing so, otherwise the weights and the binary weights will not be in sync.\\n\\n    3) CPU and GPU implementations now use floating values for `binary_weight`,\\n    since this function is for simulation purposes.\\n\\nReferences:\\n\\n    * `M. Courbariaux, Y. Bengio, and J.-P. David. BinaryConnect:\\n      Training Deep Neural Networks with binary weights during propagations.\\n      <https://arxiv.org/abs/1511.00363>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input .\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight .\"\n      },\n      {\n        \"name\": \"binary_weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Binarized weight .\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"quantize_zero_to\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Input value at zero is quantized to this value.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryConnectConvolution\",\n    \"description\": \"This function provides a BinaryConnect convolution layer. It computes in\\nthe forward pass\\n\\n.. math::\\n\\n    y_{n, a, b} = \\\\sum_{m} \\\\sum_{i} \\\\sum_{j} sign(w_{n, m, i, j}) x_{m, a + i, b + j},\\n\\ni.e., the weights :math:`w_{n, m, i, j}` are binarized to\\n:math:`sign(w_{n, m, i, j})` and, hence,\\neach weight is in :math:`\\\\{-1,\\\\,1\\\\}`. By this weight binarization, the\\ninner product computations do not require any multiplications anymore as\\nthey turn into additions/subtractions.\\n\\nThis function should be used together with :meth:`~nnabla.functions.batch_normalization`.\\n\\nReference\\n\\n    * `M. Courbariaux, Y. Bengio, and J.-P. David. BinaryConnect:\\n      Training Deep Neural Networks with binary weights during propagations.\\n      <https://arxiv.org/abs/1511.00363>`_\\n\\n\\n.. note::\\n\\n    1) If you would like to share the binary weights between other\\n    layers, please use the standard, floating value weights (`weight`)\\n    and not the binary weights (`binary_weight`).\\n\\n    2) The weights and the binary weights become in sync only after a call to\\n    :meth:`~nnabla.Variable.forward`, and not after a call to\\n    :meth:`~nnabla.Variable.backward`. If you wish to store the parameters of\\n    the network, remember to call :meth:`~nnabla.Variable.forward`, once before\\n    doing so, otherwise the weights and the binary weights will not be in sync.\\n\\n    3) CPU and GPU implementations now use floating values for `binary_weight`,\\n    since this function is for simulation purposes.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight.\"\n      },\n      {\n        \"name\": \"binary_weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Binarized weight.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of groups of channels. This makes the connection across channels sparser, by grouping connections along the mapping direction.\"\n      },\n      {\n        \"name\": \"quantize_zero_to\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Input value at zero is quantized to this value.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryWeightAffine\",\n    \"description\": \"This function provides a Binary Weight Network affine layer. It computes in\\nthe forward pass\\n\\n.. math::\\n\\n    y_j = \\\\frac{1}{\\\\|\\\\mathbf{w}_j\\\\|_{\\\\ell_1}} \\\\sum_{i} sign(w_{j,i}) x_i\\n\\ni.e., the weights :math:`w_{j,i}` are binarized to :math:`sign(w_{j,i})` and,\\nhence, each weight is in :math:`\\\\{-1,\\\\,1\\\\}`. By this weight binarization, the\\ninner product computations turn into additions/subtractions which are followed\\nby multiplication with the scaling factor\\n:math:`\\\\alpha_j = \\\\frac{1}{\\\\|\\\\mathbf{w}_j\\\\|_{\\\\ell_1}}`.\\n\\nReference\\n\\n    * `Rastegari, Mohammad, et al. XNOR-Net: ImageNet Classification Using\\n      Binary Convolutional Neural Networks.\\n      <https://arxiv.org/abs/1603.05279>`_\\n\\n.. note::\\n\\n    1) If you would like to share the binary weights with other layers, please\\n    use the standard, floating value weights (`weight`) and not the binary\\n    weights (`binary_weight`).\\n\\n    2) The weights and the binary weights become in sync only after a call to\\n    :meth:`~nnabla.Variable.forward`, and not after a call to\\n    :meth:`~nnabla.Variable.backward`. If you wish to store the parameters of\\n    the network, remember to call :meth:`~nnabla.Variable.forward`, once before\\n    doing so, otherwise the weights and the binary weights will not be in sync.\\n\\n    3) CPU and GPU implementations now use floating values for `binary_weight`,\\n    since this function is for simulation purposes.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input .\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight.\"\n      },\n      {\n        \"name\": \"binary_weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Binarized weight.\"\n      },\n      {\n        \"name\": \"alpha\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Alpha.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"quantize_zero_to\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Input value at zero is quantized to this value.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryWeightConvolution\",\n    \"description\": \"This function provides a Binary Weight Network convolution layer. It computes in\\nthe forward pass\\n\\n.. math::\\n\\n    y_{n, a, b} = \\\\frac{1}{\\\\|\\\\mathbf{w}_n\\\\|_{\\\\ell_1}} \\\\sum_{m} \\\\sum_{i} \\\\sum_{j} sign(w_{n, m, i, j}) x_{m, a + i, b + j}.\\n\\ni.e., the weights :math:`w_{n, m, i, j}` are binarized to\\n:math:`sign(w_{n, m, i, j})` and, hence, each weight is in :math:`\\\\{-1,\\\\,1\\\\}`.\\nBy this weight binarization, the inner product computations turn into\\nadditions/subtractions which are followed by multiplication with the scaling\\nfactor :math:`\\\\alpha_n = \\\\frac{1}{\\\\|\\\\mathbf{w}_n\\\\|_{\\\\ell_1}}`.\\n\\nReference\\n\\n    * `Rastegari, Mohammad, et al. XNOR-Net: ImageNet Classification Using\\n      Binary Convolutional Neural Networks.\\n      <https://arxiv.org/abs/1603.05279>`_\\n\\n.. note::\\n\\n    1) If you would like to share the binary weights between other standard layers, please\\n    use the standard, floating value weights (`weight`)\\n    and not the binary weights (`binary_weight`).\\n\\n    2) The weights and the binary weights become in sync only after a call to\\n    :meth:`~nnabla.Variable.forward`, and not after a call to\\n    :meth:`~nnabla.Variable.backward`. If you wish to store the parameters of\\n    the network, remember to call :meth:`~nnabla.Variable.forward`, once\\n    before doing so, otherwise the weights and the binary weights will not be\\n    in sync.\\n\\n    3) CPU and GPU implementations now use floating values for `binary_weight`,\\n    since this function is for simulation purposes.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight.\"\n      },\n      {\n        \"name\": \"binary_weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Binarized weight.\"\n      },\n      {\n        \"name\": \"alpha\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Alpha.\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of groups of channels. This makes the connection across channels sparser, by grouping connections along the mapping direction.\"\n      },\n      {\n        \"name\": \"quantize_zero_to\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Input value at zero is quantized to this value.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"INQAffine\",\n    \"description\": \"This function provides a INQ affine layer. It computes in\\nthe forward pass\\n\\n.. math::\\n\\n    y_j = \\\\sum_{i} w_{j,i} x_i,\\n\\nwhere the weights :math:`w_{j,i}` are quantized sequentially during\\ntraining to power-of-two numbers. In the backward pass, only the non-fixed\\n(i.e., learnable) weights are updated.\\n\\nReferences:\\n\\n    * `Zhou A, Yao A, Guo Y, Xu L, Chen Y. Incremental network quantization:\\n      Towards lossless CNNs with low-precision weights.\\n      <https://arxiv.org/abs/1702.03044>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input .\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight .\"\n      },\n      {\n        \"name\": \"indicator_fixedweights\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Indicates which weights are already fixed (0 = not fixed, 1 = fixed) .\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"num_bits\",\n        \"type\": \"int64\",\n        \"default\": 4,\n        \"description\": \"Number of bits per weight. Needs to be >= 2 as two bits are used to code `zero` and sign of weight.\"\n      },\n      {\n        \"name\": \"inq_iterations\",\n        \"type\": \"int64[]\",\n        \"default\": \"()\",\n        \"description\": \"List which specifies after how many forward passes we fix 50% of the learnable weights. If we have done as many iterations as specified in the last element of `inq_iterations`, then all weights are fixed.\"\n      },\n      {\n        \"name\": \"selection_algorithm\",\n        \"type\": \"string\",\n        \"default\": \"largest_abs\",\n        \"description\": \"Chooses algorithm that we use for selecting the weights to fix (\\\"largest_abs\\\" ... fix weights with largest absolute value, \\\"random\\\" ... fix weights randomly)\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"INQConvolution\",\n    \"description\": \"This function provides a INQ convolution layer. It computes in\\nthe forward pass\\n\\n.. math::\\n\\n    y_{n, a, b} = \\\\sum_{m} \\\\sum_{i} \\\\sum_{j} w_{n, m, i, j} x_{m, a + i, b + j},\\n\\nwhere the weights :math:`w_{j,i}` are quantized sequentially during\\ntraining to power-of-two numbers. In the backward pass, only the non-fixed\\n(i.e., learnable) weights are updated.\\n\\nReference\\n\\n    * `Zhou A, Yao A, Guo Y, Xu L, Chen Y. Incremental network quantization:\\n      Towards lossless CNNs with low-precision weights.\\n      <https://arxiv.org/abs/1702.03044>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input.\"\n      },\n      {\n        \"name\": \"weight\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Weight.\"\n      },\n      {\n        \"name\": \"indicator_fixedweights\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Indicates which weights are already fixed (0 = not fixed, 1 = fixed) .\"\n      },\n      {\n        \"name\": \"bias\",\n        \"type\": \"nnabla.Variable\",\n        \"option\": \"optional\",\n        \"description\": \"Bias.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Padding sizes for dimensions.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Stride sizes for dimensions.\"\n      },\n      {\n        \"name\": \"dilation\",\n        \"type\": \"shape\",\n        \"default\": \"(1,) * (len(x.shape) - (base_axis+1))\",\n        \"description\": \"Dilation sizes for dimensions.\"\n      },\n      {\n        \"name\": \"group\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Number of groups of channels. This makes the connection across channels sparser, by grouping connections along the mapping direction.\"\n      },\n      {\n        \"name\": \"num_bits\",\n        \"type\": \"int64\",\n        \"default\": 4,\n        \"description\": \"Number of bits per weight. Needs to be >= 2 as two bits are used to code `zero` and sign of weight.\"\n      },\n      {\n        \"name\": \"inq_iterations\",\n        \"type\": \"int64[]\",\n        \"default\": \"()\",\n        \"description\": \"List which specifies after how many forward passes we fix 50% of the learnable weights. If we have done as many iterations as specified in the last element of `inq_iterations`, then all weights are fixed.\"\n      },\n      {\n        \"name\": \"selection_algorithm\",\n        \"type\": \"string\",\n        \"default\": \"largest_abs\",\n        \"description\": \"Chooses algorithm that we use for selecting the weights to fix (\\\"largest_abs\\\" ... fix weights with largest absolute value, \\\"random\\\" ... fix weights randomly)\"\n      },\n      {\n        \"name\": \"seed\",\n        \"type\": \"int64\",\n        \"default\": -1,\n        \"description\": \"Random seed. When -1, seed is sampled from global random number generator.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ]\n  },\n  {\n    \"name\": \"FixedPointQuantize\",\n    \"description\": \"This function simulates to uniformly quantize values in fixed-point number representation.\\n\\nIn the forward pass,\\n\\n.. math::\\n\\n   q_i= \\\\left\\\\{\\n\\t   \\\\begin{array}{ll}\\n\\t\\t\\tmax & if \\\\ \\\\ \\\\ x_i > max \\\\\\\\\\n\\t\\t  sign(x_i) \\\\times floor(|x_i| \\\\delta^{-1} + 2^{-1}) \\\\times \\\\delta & if \\\\ \\\\ min \\\\le x_i \\\\le max \\\\\\\\\\n\\t  \\tmin & if \\\\ \\\\ x_i < min \\\\\\\\\\n\\t   \\\\end{array} \\\\right.,\\n\\nwhere :math:`\\\\delta` is the step size,\\n:math:`(min, max) :=(- (2^{n-1} - 1)\\\\delta, (2^{n-1} - 1)\\\\delta)` if :math:`sign` is true,\\n:math:`(min, max) := (0, (2^n - 1) \\\\delta)` otherwise, and\\n:math:`n` is the total bit-width used.\\n\\nIn the backward pass when using `ste_fine_grained` as false,\\n\\n.. math::\\n\\n   \\\\frac{\\\\partial q_i}{\\\\partial x_i} = 1.\\n\\nIn the backward pass when using `ste_fine_grained` as true,\\n\\n.. math::\\n\\n   \\\\frac{\\\\partial q_i}{\\\\partial x_i}= \\\\left\\\\{\\n\\t   \\\\begin{array}{ll}\\n\\t\\t\\t0 & if \\\\ \\\\ \\\\ x_i > max \\\\\\\\\\n\\t\\t  1 & if \\\\ \\\\ min \\\\le x_i \\\\le max \\\\\\\\\\n\\t  \\t0 & if \\\\ \\\\ x_i < min \\\\\\\\\\n\\t   \\\\end{array} \\\\right..\\n\\n.. note::\\n\\n\\n\\tQuantized values are stored as floating point number, since this function is for simulation purposes.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"sign\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Indicate the signed number or the unsigned number. Default is true.\"\n      },\n      {\n        \"name\": \"n\",\n        \"type\": \"int64\",\n        \"default\": 8,\n        \"description\": \"Bit width used. Note that `sign` consumes one bit. :math:`n-1` is used for number representation in `signed` case.\"\n      },\n      {\n        \"name\": \"delta\",\n        \"type\": \"float32\",\n        \"default\": 0.0625,\n        \"description\": \"Step size.\"\n      },\n      {\n        \"name\": \"ste_fine_grained\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Straight Through Estimator is fine-grained or not.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MinMaxQuantize\",\n    \"description\": \"This function simulates to uniformly quantize values in the range of min and max quantization levels.\\n\\nMin-max quantization is defined as the following equation\\n\\n.. math::\\n\\n    y = round \\\\left(\\\\frac{\\\\min(\\\\max(x, m), M) - m}{scale} \\\\right) \\\\times scale + m,\\n\\nwhere the :math:`scale` is defined as\\n\\n.. math::\\n\\n    scale = \\\\frac{M - m}{M_q - m_q},\\n\\nand\\n\\n.. math::\\n\\n    m_q = ql_{min}, \\\\\\\\\\n    M_q = ql_{max}, \\\\\\\\\\n    m = qr_{min}, \\\\\\\\\\n    M = qr_{max}.\\n\\nIn the backward pass when using `ste_fine_grained` as false,\\n\\n    .. math::\\n\\n      \\\\frac{\\\\partial q_i}{\\\\partial x_i} = 1.\\n\\n\\nIn the backward pass when using `ste_fine_grained` as true,\\n\\n    .. math::\\n\\n       \\\\frac{\\\\partial q_i}{\\\\partial x_i}= \\\\left\\\\{\\n     \\\\begin{array}{ll}\\n       0 & if \\\\ \\\\ \\\\ x_i > M \\\\\\\\\\n       1 & if \\\\ \\\\ m \\\\le x_i \\\\le M \\\\\\\\\\n       0 & if \\\\ \\\\ x_i < m \\\\\\\\\\n     \\\\end{array} \\\\right..\\n\\n:math:`qr_{min}` and :math:`qr_{max}` are treaded as follows.\\n\\n    * `x_min_max` is `True` and `ema` is `True`:\\n      Exponential moving average are computed for each :math:`min(x)` and :math:`max(x)`\\n      then stored in :math:`qr_{min}` and :math:`qr_{max}`.\\n    * `x_min_max` is `True` and `ema` is `False`:\\n      :math:`min(x)` and :math:`max(x)` are computed then stored in :math:`qr_{min}` and :math:`qr_{max}`.\\n    * `x_min_max` is `False` and `ema` is `True`:\\n      Exponential moving average stored in :math:`qr_{min}` and :math:`qr_{max}` are used.\\n    * `x_min_max` is `False` and `ema` is `False`\\n      Gradients of :math:`qr_{min}` and :math:`qr_{max}` are computed in the backward pass.\\n\\nMore precisely, in inference of the min-max quantization, one has to consider *zero-point (zp)*\\nwhich corresponds\\nto the real value 0, and its data type is an integer. *zero-point* is defined as\\n\\n    .. math::\\n\\n       && zp_f = ql_{min} -\\\\frac{qr_{min}}{scale}, \\\\\\\\\\n       && zp = \\\\left\\\\{\\n     \\\\begin{array}{ll}\\n       ql_{max} & if \\\\ \\\\ \\\\ zp_f >= ql_{max} \\\\\\\\\\n       round(zp_f) & if \\\\ \\\\ otherwise \\\\\\\\\\n       ql_{min}  & if \\\\ \\\\ zp_f <= ql_{min} \\\\\\\\\\n     \\\\end{array} \\\\right..\\n\\nAccordingly, in order to simulate quantization effect of *zero-point*,\\nduring both forward and backward pass, :math:`qr_{min}` and :math:`qr_{max}` are adjusted as follows,\\n\\n    .. math::\\n\\n       qr_{min}^{adj} = ql_{min} - zp * scale, \\\\\\\\\\n       qr_{max}^{adj} = ql_{max} - zp * scale.\\n\\nThese operations are often called *nudge*.\\n\\nFinally, in the formulas of the min-max quantization, :math:`m` and :math:`M` are replaced by\\n:math:`qr_{min}^{adj}` and :math:`qr_{max}^{adj}` respectively.\\n\\n.. note::\\n\\n\\tQuantized values are stored as floating point number, since this function is for simulation purposes.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array innput.\"\n      },\n      {\n        \"name\": \"qr_min\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Minimum value for the quantization range, modified during forward execution when x_min_max is True.\"\n      },\n      {\n        \"name\": \"qr_max\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Maximum value for the quantization range, modified during forward execution when x_min_max is True.\"\n      },\n      {\n        \"name\": \"ql_min\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Minimum value for the quantization level, typically 0.\"\n      },\n      {\n        \"name\": \"ql_max\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Maximum value for the quantization level, typically 255.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"decay\",\n        \"type\": \"float32\",\n        \"default\": 0.999,\n        \"description\": \"Decay rate for the exponential moving average.\"\n      },\n      {\n        \"name\": \"x_min_max\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Use the min and max of x to compute quantization ranges.\"\n      },\n      {\n        \"name\": \"ema\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"Use the exponential moving average for the min and max quantization ranges.\"\n      },\n      {\n        \"name\": \"ste_fine_grained\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Straight Through Estimator is fine-grained or not.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 0.01,\n        \"description\": \"Epsilon, or small value to ensure :math:`qr_{max} - qr_{min}` must be greater than the epsilon.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Pow2Quantize\",\n    \"description\": \"This function simulates to quantize values in the power of 2 number representation,\\nin other words, it is linear (uniform) quantization in :math:`log_2` domain.\\n\\nIn the forward pass of `signed` case,\\n\\n.. math::\\n\\n   q_i= \\\\left\\\\{\\n\\t   \\\\begin{array}{ll}\\n\\t\\t\\tmax_{+} & if \\\\ \\\\ \\\\overline{q_i} > max_{+} \\\\\\\\\\n\\t\\t\\t\\\\overline{q_i} & if \\\\ \\\\ min_{+} \\\\le \\\\overline{q_i} \\\\le max_{+} \\\\\\\\\\n\\t\\t  min_{+} & if \\\\ \\\\ 0 \\\\le \\\\overline{q_i} < min_{+} \\\\\\\\\\n\\t\\t  min_{-} & if \\\\ \\\\ min_{-} < \\\\overline{q_i} < 0 \\\\\\\\\\n\\t\\t  \\\\overline{q_i} & if \\\\ \\\\ max_{-} \\\\le \\\\overline{q_i} \\\\le min_{-}\\\\\\\\\\n\\t  \\tmax_{-} & if \\\\ \\\\ \\\\overline{q_i} < max_{-} \\\\\\\\\\n\\t   \\\\end{array} \\\\right.,\\n\\nwhere\\n\\n.. math::\\n\\n   && max_{+} = 2^{m}, min_{+} = 2^{m - (2^{n-1} - 1)},\\\\\\\\\\n   && max_{-} = -2^{m}, min_{-} = -2^{m - (2^{n-1} - 1)},\\\\\\\\\\n   && \\\\overline{q_i} = sign(x_i) \\\\times 2^{round(\\\\log_2 |x_i|)}.\\n\\nThis quantization uses the geometric mean between two power-of-two numbers\\nas quantization threshold.\\n\\nIn the forward pass of `unsigned` case,\\n\\n.. math::\\n\\n   q_i= \\\\left\\\\{\\n\\t   \\\\begin{array}{ll}\\n\\t\\t\\tmax & if \\\\ \\\\ \\\\overline{q_i} > max \\\\\\\\\\n\\t\\t\\t\\\\overline{q_i} & if \\\\ \\\\ min \\\\le \\\\overline{q_i} \\\\le max \\\\\\\\\\n\\t\\t  min & if \\\\ \\\\ 0 < \\\\overline{q_i} < min \\\\\\\\\\n\\t   \\\\end{array} \\\\right.,\\n\\nwhere\\n\\n.. math::\\n\\n   && max = 2^{m}, min = 2^{m - (2^{n} - 1)},\\\\\\\\\\n   && \\\\overline{q_i} = 2^{int(\\\\log_2 |x_i|)}.\\n\\n\\nWhen using `with_zero` as true, a pruning threshold is used to round an input to\\n0 or :math:`min`. The pruning threshold is defined in this function as the following,\\n\\n.. math::\\n\\n   pruning\\\\ threshold = min \\\\times 2^{-\\\\frac{1}{2}}.\\n\\nIf an absolute value of the input is lesser than this value, the input is rounded to 0, otherwise :math:`min`.\\n\\nIn the backward pass when using ste_fine_grained as false,\\n\\n.. math::\\n\\n   \\\\frac{\\\\partial q_i}{\\\\partial x_i} = 1.\\n\\nIn the backward pass when using ste_fine_grained as true,\\n\\n.. math::\\n\\n   \\\\frac{\\\\partial q_i}{\\\\partial x_i}= \\\\left\\\\{\\n\\t   \\\\begin{array}{ll}\\n\\t\\t\\t0 & if \\\\ \\\\ \\\\overline{q_i} > max_{+} \\\\\\\\\\n\\t\\t\\t1 & if \\\\ \\\\ otherwise \\\\\\\\\\n\\t  \\t0 & if \\\\ \\\\ \\\\overline{q_i} < max_{-} \\\\\\\\\\n\\t   \\\\end{array} \\\\right..\\n\\n\\nThere are some literatures using pow2 quantization in their proposed methods.\\n\\nReferences:\\n\\n  * `Miyashita Daisuke, Lee H. Edward, Murmann Boris.\\n    Convolutional Neural Networks using Logarithmic Data Representation.\\n    <https://arxiv.org/abs/1603.01025>`_\\n\\n  * `Aojun Zhou, Anbang Yao, Yiwen Guo, Lin Xu, Yurong Chen.\\n    Incremental Network Quantization: Towards Lossless CNNs with Low-precision Weights.\\n    <https://arxiv.org/abs/1702.03044>`_\\n\\n.. note::\\n\\n\\n\\tQuantized values are stored as floating point number, since this function is for simulation purposes.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"sign\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Indicate the signed number or the unsigned number. Default is true.\"\n      },\n      {\n        \"name\": \"with_zero\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Indicate using zero as a quantized value. Default is true. Note that `zero` consumes one bit.\"\n      },\n      {\n        \"name\": \"n\",\n        \"type\": \"int64\",\n        \"default\": 8,\n        \"description\": \"Bit width used, Note that `sign` consumes one bit. :math:`n-1` is used for number representation in `signed` case. Default is 8.\"\n      },\n      {\n        \"name\": \"m\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \":math:`2^m` is the upper bound of the dynamic range and :math:`-2^m` is the lower bound, :math:`m \\\\in \\\\mathcal{Z}`. Default is 1.\"\n      },\n      {\n        \"name\": \"ste_fine_grained\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Straight Through Estimator is fine-grained or not.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Prune\",\n    \"description\": \"Prune the input as the following equation,\\n\\n.. math::\\n\\n    q_i = \\\\left \\\\{\\n      \\\\begin{array}{ll}\\n      0   & abs(x_i) < threshold \\\\\\\\\\n      x_i & otherwise\\n      \\\\end{array}\\n      \\\\right.\\n\\nwhere :math:`threshold` is determined by `threshold = np.sort(np.abs(x))[int((x.size - 1) * rate)]`.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"rate\",\n        \"type\": \"float32\",\n        \"default\": 0.9,\n        \"description\": \"Sparse rate, or pruning rate.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with the same shape as x\"\n      }\n    ]\n  },\n  {\n    \"name\": \"QuantizeLinear\",\n    \"description\": \"Quantize linearly inputs with the scale and zero point.\\n\\n.. math::\\n\\n    y = saturate(round(x / scale) + zero_point).\\n\\n:math:`saturate` rage is determined by `dtype` and :math:`round` mode is selected\\nby `round_mode`. :math:`zero_point` is constrained by the `dtype` range and its values are\\nrounded by `round_mode`.\\n\\nThis function aligns with ONNX.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array.\"\n      },\n      {\n        \"name\": \"scale\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Scale N-D array. The values must be positive number.\"\n      },\n      {\n        \"name\": \"zero_point\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Zero point N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"round_mode\",\n        \"type\": \"string\",\n        \"default\": \"HALF_AWAY_FROM_ZERO\",\n        \"description\": \"Rounding mode. HALF_AWAY_FROM_ZERO or HALF_TO_EVEN.\"\n      },\n      {\n        \"name\": \"narrow_range\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If true, this function does not use the minimum quantized value. For example, if `dtype` is int8 (the range is in [-128, 127]), the output range is corrected in [-127, 127].\"\n      },\n      {\n        \"name\": \"dtype\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Data type for the output. The int value is compatible to the enumtype for the data type defined in `the numpy <https://github.com/numpy/numpy/blob/master/numpy/core/include/numpy/ndarraytypes.h>`_.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"DequantizeLinear\",\n    \"description\": \"Dequantize linearly inputs with the scale and zero point.\\n\\n.. math::\\n\\n    y = (x - zero_point) * scale.\\n\\n:math:`zero_point` is constrained by the `dtype` range.\\n\\nThis function aligns with ONNX.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array.\"\n      },\n      {\n        \"name\": \"scale\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Scale N-D array. The values must be positive number. This should be same as one used in QuantizeLinear.\"\n      },\n      {\n        \"name\": \"zero_point\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Zero point N-D array. This should be same as one used in QuantizeLinear.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"TopNError\",\n    \"description\": \"Top N error along the dimension specified by the axis, the element of outputs is\\n\\n.. math::\\n\\n    y_i = \\\\left \\\\{\\n    \\\\begin{array}{l}\\n    1 \\\\ (x_i \\\\ is \\\\ not \\\\ within \\\\ N-th \\\\ place) \\\\\\\\\\n    0 \\\\ (x_i \\\\ is \\\\ within \\\\ N-th \\\\ place)\\n    \\\\end{array}\\n    \\\\right.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Probabilities N-D array. :math:`D_1 \\\\times ... \\\\times D_i \\\\times ... \\\\times D_N`\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of labels. :math:`D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N`\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x.shape) - 1\",\n        \"description\": \"Axis on which the top N error is calculated.\"\n      },\n      {\n        \"name\": \"n\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"top N\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Element-wise error N-D array. (:math:`D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N`)\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BinaryError\",\n    \"description\": \"Elementwise binary error.\\n\\n.. math::\\n    y_i = \\\\left \\\\{\\n    \\\\begin{array}{l}\\n    0 ((x^{(0)} \\\\geq 0.5) = (x^{(1)} \\\\geq 0.5)) \\\\\\\\\\n    1 ((x^{(0)} \\\\geq 0.5) \\\\neq (x^{(1)} \\\\geq 0.5))\\n    \\\\end{array}\\n    \\\\right.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Probabilities N-D array. :math:`-\\\\infty` to :math:`\\\\infty`.\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Labels N-D array. Usually set as 0 or 1, but, it allows probability (0 to 1) as inputs.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Element-wise errors N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ConfusionMatrix\",\n    \"description\": \"Confusion matrix.\\nThe return value is already summed over samples.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Probabilities N-D array. (:math:`D_1 \\\\times ... \\\\times D_i \\\\times ... \\\\times D_N`)\"\n      },\n      {\n        \"name\": \"target\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Labels N-D array. (:math:`D_1 \\\\times ... \\\\times 1 \\\\times ... \\\\times D_N`)\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"len(x.shape) - 1\",\n        \"description\": \"Axis on which the confusion matrix is calculated.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Confusion matrix 2-D array. Col index is estimated class. Row index is label class.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"VATNoise\",\n    \"description\": \"Noise for virtual adversarial training.\\n\\nThis layer is a special layer for GUI network designing, specialized for getting\\nthe noise of virtual adversarial training.\\n\\nIn the backward process, the weight parameter will be replaced with the gradient.\\n\\nForward\\n\\n.. math::\\n    y_i = \\\\frac{\\\\epsilon x_i}{\\\\sqrt{\\\\sum_k x_k^2 + c}}\\n\\nBackward\\n\\n.. math::\\n    \\\\delta x_i = 0\\n\\n.. math::\\n    w_i = \\\\epsilon \\\\delta y_i\\n\\nNote:\\n    This layer is a special layer for GUI network designing.\\n\\nReferences:\\n    * `Miyato et.al, Distributional Smoothing with Virtual Adversarial Training.\\n      <https://arxiv.org/abs/1507.00677>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array of noise input. Noise is standard Gaussian noise initially, but the next step, fed back gradient variable.\"\n      },\n      {\n        \"name\": \"w\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array for keep gradient values.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"base_axis\",\n        \"type\": \"int64\",\n        \"default\": 1,\n        \"description\": \"Dimensions up to base_axis is treated as sample dimension.\"\n      },\n      {\n        \"name\": \"eps\",\n        \"type\": \"float32\",\n        \"default\": 1.0,\n        \"description\": \"Noise norm (l2) factor.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Unlink\",\n    \"description\": \"This function behaves as an identity function on the forward pass,\\nand deletes the gradient for the background pass.\\n\\nThis layer is a special layer for GUI network designing, used for getting\\nzero backward operation by adding this layer.\\n\\nForward\\n\\n.. math::\\n    y_i = x_i\\n\\nBackward\\n\\n.. math::\\n    \\\\delta x_i = 0\\n\\nNote:\\n    This layer is a special layer for GUI network designing.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Sink\",\n    \"description\": \"Creates a dummy variable used to call forward or backward function\\nof multiple variables at one place.\\n\\nThis takes any numbers of input variables with any shape,\\nand creates a single 0-shape outputs.\\nThe forward pass does nothing. The backward pass set ones\\nto the input grads if one_input_grad is set as true.\\n\\nNote:\\n    ``sink`` can only be called at the very end of the graph, and\\n    ``grad`` of input variables are cleared\\n     when ``y.backward(clear_buffer=True)`` is called.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"Any number of inputs with any shape.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"one_input_grad\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"Set grads of inputs as one during backward. It is useful to set false if you want to set external gradients to the input variables.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Dummy variable.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"NmsDetection2d\",\n    \"description\": \"Non-Maximum Suppression (NMS) to 2D Object detector output.\\nThe input is a 3-dimensional tensor with shape of ``(B, N, 5 + C)``\\nwhere ``B`` denotes batch size, ``N`` denotes the number of detection box\\ncandidates, and ``C`` denotes the number of classes of object detection.\\n``5 + C`` consists of the box coordinates ``x, y, w, h`` in normalized\\ncoordinates (size of each x and y are 1.0), objectness\\n(learned to predict IoU value to ground truth box), and the class probabilities of ``C`` classes.\\nIt outputs a tensor with the same dimensions as the input, where all\\nvalues are copied from the input to the output, except the class\\nprobabilities are multiplied by objectness, and possibly suppressed to 0\\nby NMS.\\nDuring NMS, all of combination of pairs of bounding boxes is compared.\\nFor each pair, the bounding box with a lower detection score\\n(described below) is suppressed if the overlap ratio (the IoU)\\nis greater than the value of ``nms``.\\n\\nThere are two suppression modes for NMS.\\n\\n1. Suppress by class probability (``nms_per_class`` is ``True``):\\nFor each bounding box, the detection score is calculated by\\n``objectness * probability[class_id]`` for each class.\\nThe suppression is done for each class independently.\\n\\n2. Suppress by objectness (``nms_per_class`` is ``False``):\\nThe suppression is done for each bounding box using ``objectness``\\nas a detection score. All class probabilities becomes 0 for\\nevery suppressed boxes.\\n\\nReferences:\\n    * `Joseph Redmon, Ali Farhadi, YOLO9000: Better, Faster, Stronger.\\n      <https://arxiv.org/abs/1612.08242>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 3-dimensional array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"thresh\",\n        \"type\": \"float32\",\n        \"default\": 0.5,\n        \"description\": \"Detection score threshold.\"\n      },\n      {\n        \"name\": \"nms\",\n        \"type\": \"float32\",\n        \"default\": 0.45,\n        \"description\": \"IoU threshold for Non-maximum suppression (NMS).\"\n      },\n      {\n        \"name\": \"nms_per_class\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If true, NMS is applied for each class.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 3-dim array with the same dimensions with the input.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"ONNXNonMaxSuppression\",\n    \"description\": \"Non-Maximum Suppression (NMS) to 2D Object detector output. This function\\nprovides a ONNX-compatible interface of Non-Maximum Suppression.\\nThe first input is a 3-dimensional bounding box tensor with shape of\\n``(B, N, 4)`` where ``B`` denotes batch size and ``N`` denotes the \\nnumber of detection box candidates.\\n``4`` consists of the box coordinates ``y1, x1, y2, x2`` in normalized\\ncoordinates (size of each x and y are 1.0).\\nThe second input is a 3-dimensional score tensor with shape of\\n``(B, C, N)`` where ``C`` denotes the number of classes of object\\ndetection.\\nIt outputs the indices of the selected boxes as a tensor with shape of\\n``(M, 3)`` where ``M`` denotes the number of the selected boxes.\\n``3`` consists of 3-dimensional indices\\n``batch_index, class_index, box_index``.\\n\\nReferences:\\n    * `Joseph Redmon, Ali Farhadi, YOLO9000: Better, Faster, Stronger.\\n      <https://arxiv.org/abs/1612.08242>`_\\n    * `ONNX Operators documentation.\\n      <https://github.com/onnx/onnx/blob/main/docs/Operators.md>`\",\n    \"inputs\": [\n      {\n        \"name\": \"boxes\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 3-dimensional array.\"\n      },\n      {\n        \"name\": \"scores\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 3-dimensional array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"center_point_box\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Bounding box format (0 or 1).\"\n      },\n      {\n        \"name\": \"max_output_boxes_per_class\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"The maximum number of boxes selected per batch per class.\"\n      },\n      {\n        \"name\": \"iou_threshold\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"IoU threshold for Non-maximum suppression (NMS).\"\n      },\n      {\n        \"name\": \"score_threshold\",\n        \"type\": \"float32\",\n        \"default\": 0.0,\n        \"description\": \"Detection score threshold.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 2-dimensional array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"MaxPoolingBackward\",\n    \"description\": \"Max pooling backward. This aims to support the n-th order gradients of \\nthe max pooling. The document of this function must not be shown, and \\nthe function must not be called in the end-user side.\",\n    \"inputs\": [\n      {\n        \"name\": \"dy\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      },\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input variable.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"shape\",\n        \"description\": \"Kernel sizes for each spatial axis.\"\n      },\n      {\n        \"name\": \"stride\",\n        \"type\": \"shape\",\n        \"default\": \"kernel\",\n        \"description\": \"Subsampling factors for each spatial axis.\"\n      },\n      {\n        \"name\": \"ignore_border\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If false, kernels covering borders are also considered for the output.\"\n      },\n      {\n        \"name\": \"pad\",\n        \"type\": \"shape\",\n        \"default\": \"(0,) * len(kernel)\",\n        \"description\": \"Border padding values for each spatial axis. Padding will be added both sides of the dimension.\"\n      },\n      {\n        \"name\": \"channel_last\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, the last dimension is considered as channel dimension, a.k.a. NHWC order.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"dx\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Output\"\n      }\n    ],\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"PatchCorrelation\",\n    \"description\": \"Multiplicative patch-wise comparision between inputs `x1` and `x2`, which\\n  must both be 4-dimensional NCHW (with `channel_last=False`) or NHWC (with\\n  `channel_last=True`) arrays (where *N* is the number of samples, *H* and\\n  *W* are the sample height and width and *C* is the number of channels).\\n  The function returns a 5-D array with shape :math:`(N, C_y, C_x, H_o, W_o)`\\n  where :math:`H_o, W_o` are determined by the possible patch locations within\\n  the, optionally padded, input image size and :math:`C_y, C_x` are determined\\n  by the optionally shifted patch positions.\\n\\n  Mathmatically, the patch correlation is formulated as\\n\\n  .. math::\\n\\n    O(s_y, s_x, h_0, w_0) =\\n    \\\\sum_{c} \\\\sum_{k_h} \\\\sum_{k_w} I_1(c, h + k_h, w + k_w) \\\\times I_2(c, h + k_h + s_h, w + k_w + s_w),\\n\\n  where :math:`I_1(c, h, w)` and :math:`I_2(c, h, w)` are the inputs at :math:`c`-th channel,\\n  :math:`h`-th height, and :math:`w`-th width, :math:`k_h, k_w` indices for the patch size\\n  and :math:`s_h, s_w` indices for the shifts.\\n\\n  A single correlation value (per sample) is produced if the patch extends\\n  to the image dimensions and all other parameters use the default values.\\n\\n  >>> import numpy as np, nnabla as nn, nnabla.functions as F\\n  >>> nn.set_auto_forward(True)\\n  >>> N, C, H, W = (1, 2, 3, 4)\\n  >>> x = nn.Variable.from_numpy_array(np.ones([N, C, H, W]))\\n  >>> F.patch_correlation(x, x, patch=(H, W)).d\\n  array([[[[[24.]]]]], dtype=float32)\\n\\n  A patch that is smaller than the image size moves horizontal and vertical\\n  producing a value per position. The `patch_step` argument may be used to\\n  control the position increments.\\n\\n  >>> F.patch_correlation(x, x, patch=(H-1, W-1)).d\\n  array([[[[[12., 12.],\\n            [12., 12.]]]]], dtype=float32)\\n  >>> F.patch_correlation(x, x, patch=(H-1, W-1), patch_step=(2, 1)).d\\n  array([[[[[12., 12.]]]]], dtype=float32)\\n\\n  Multiple correlations may be performed at each position between the patch\\n  from `x1` and patches from `x2` at relative offsets striding the maximum\\n  vertical and horizontal distance given by the `shift` values at increments\\n  of `shift_step`. The shifted correlation values can be obtained for the\\n  from the second and third output dimension for the vertical and horizontal\\n  shifts.\\n\\n  >>> F.patch_correlation(x, x, (H, 1), shift=(0, 1)).shape\\n  (1, 1, 3, 1, 4)\\n  >>> F.patch_correlation(x, x, (H, 1), shift=(0, 1)).d\\n  array([[[[[0., 6., 6., 6.]],\\n           [[6., 6., 6., 6.]],\\n           [[6., 6., 6., 0.]]]]], dtype=float32)\\n  >>> F.patch_correlation(x, x, (H, 1), shift=(0, 1), shift_step=(1, 2)).d\\n  array([[[[[0., 6., 6., 6.]],\\n           [[6., 6., 6., 0.]]]]], dtype=float32)\\n\\n  Padding with zero values may be applied individually to the top, bottom,\\n  left and right side of the input image.\\n\\n  >>> F.patch_correlation(x, x, patch=(H, W), padding=(0, 1, W, W)).d\\n  array([[[[[ 0.,  6., 12., 18., 24., 18., 12.,  6.,  0.],\\n            [ 0.,  4.,  8., 12., 16., 12.,  8.,  4.,  0.]]]]], dtype=float32)\\n\\n  This function may be used to implement the FlowNetC correlation layer.\\n\\n  >>> N, C, H, W = (1, 256, 44, 60)\\n  >>> x1, x2 = nn.Variable((N, C, H, W)), nn.Variable((N, C, H, W))\\n  >>> F.patch_correlation(x1, x2, shift=20, shift_step=2).shape\\n  (1, 21, 21, 44, 60)\\n\\n  References:\\n\\n      * `Fischer et al., FlowNet: Learning Optical Flow with Convolutional\\n        Networks. <https://arxiv.org/abs/1504.06852>`_\",\n    \"inputs\": [\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(N, H, W, C)`.\"\n      },\n      {\n        \"name\": \"x2\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"Input N-D array with shape :math:`(N, H, W, C)`.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"patch\",\n        \"type\": \"shape\",\n        \"default\": \"(1, 1)\",\n        \"description\": \"A tuple with height and width of the correlation patch. A single integer expands to identical height and width.\"\n      },\n      {\n        \"name\": \"shift\",\n        \"type\": \"shape\",\n        \"default\": \"(0, 0)\",\n        \"description\": \"A tuple of maximum vertical and horizontal displacement of patches from `x2` that are correlated with a single patch from `x1`. A single integer expands to identical vertical and horizontal displacement.\"\n      },\n      {\n        \"name\": \"patch_step\",\n        \"type\": \"shape\",\n        \"default\": \"(1, 1)\",\n        \"description\": \"A tuple of vertical and horizontal increments for advancing the position of the correlation patch within the input image shape. A single integer expands to identical vertical and horizontal increments.\"\n      },\n      {\n        \"name\": \"shift_step\",\n        \"type\": \"shape\",\n        \"default\": \"(1, 1)\",\n        \"description\": \"A tuple of vertical and horizontal increments for advancing the relative offset position within the shift range. A single integer expands to identical vertical and horizontal increments.\"\n      },\n      {\n        \"name\": \"padding\",\n        \"type\": \"shape\",\n        \"default\": \"(0, 0, 0, 0)\",\n        \"description\": \"A tuple of top, bottom, left and right padding extent. A tuple of two values yields identical top/bottom and left/right padding from the first and second tuple value. A single integer expands to identical padding extent for all sides.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"N-D array with shape :math:`(N, C_y, C_x, H_o, W_o)`.\\n\\nA spatial size of the output is calculated as\\n\\n.. math::\\n\\n  H_o = \\\\frac{H + (top\\\\_pad + bottom\\\\_pad) - patch_v }{patch\\\\_step_v} + 1.\\n\\nA channel size of the output is calculated as\\n\\n.. math::\\n\\n  C_y = \\\\frac{2 \\\\times shift_v}{shift\\\\_step_v} + 1.\\n\\n:math:`W_o` and :math:`C_x` are the same calculation with differenct components.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Unique\",\n    \"description\": \"Find the unique elements of input array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"flatten\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If True, unique values of the flatten input array are returned.\"\n      },\n      {\n        \"name\": \"axis\",\n        \"type\": \"int64\",\n        \"default\": \"None\",\n        \"description\": \"If flatten is True and axis is specified, unique slices along axis are returned.\"\n      },\n      {\n        \"name\": \"sorted\",\n        \"type\": \"boolean\",\n        \"default\": true,\n        \"description\": \"If True, unique values/slices sorted in ascending order are returned.\"\n      },\n      {\n        \"name\": \"with_index\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, `indices` is returned.\"\n      },\n      {\n        \"name\": \"with_inverse\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, `inverse_indices` is returned.\"\n      },\n      {\n        \"name\": \"with_counts\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, `counts` is returned.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      },\n      {\n        \"name\": \"indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 1-D array. It's indices of `y` elements first occurance in `x`. If `flatten` is True, it contains indices to flattend input array `x`. If `flatten` is False and `axis` is specified, it contains indices to input array `x` on `axis`.\"\n      },\n      {\n        \"name\": \"inverse_indices\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 1-D array. It's indices of `x` elements corresponding to `y`. If `flatten` is True, it contains indices to output array `y`. If `flatten` is False and `axis` is specified, it contains indices to output array `y` on `axis`.\"\n      },\n      {\n        \"name\": \"counts\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 1-D array. It's the count of each element of 'y' in input array `x`.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"EyeLike\",\n    \"description\": \"Generate a 2-D array with ones on the diagonal, specified by `k`, and zeros elsewhere.\\nThe shape of the output array is the same as the input array.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 2-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"k\",\n        \"type\": \"int64\",\n        \"default\": 0,\n        \"description\": \"Index of the diagonal. The default value 0 means the main diagonal, a positive value means an upper diagonal, and a negative value means a lower diagonal.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A 2-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Mod2\",\n    \"description\": \"Element-wise remainder function.\\nThe behavior of this opeator is determined by x0's dtype and the `fmod` argument:\\n\\n.. math::\\n    y_i = \\\\left\\\\{\\n    \\\\begin{array}{ll}\\n      \\\\text{numpy.fmod}(x_{0,i}, x_{1,i})\\n        & (x_{0} \\\\text{has a floating-point type or fmod is True})\\\\\\\\\\n      \\\\text{numpy.mod}(x_{0,i}, x_{1,i})\\n        & (\\\\text{otherwise})\\n    \\\\end{array} \\\\right..\",\n    \"inputs\": [\n      {\n        \"name\": \"x0\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      },\n      {\n        \"name\": \"x1\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"fmod\",\n        \"type\": \"boolean\",\n        \"default\": false,\n        \"description\": \"If True, this operator behaves like numpy.fmod, otherwise it behaves like numpy.mod.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"BitShift\",\n    \"description\": \"Element-wise bit shift function.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array. Its dtype must be one of the unsigned integer types.\"\n      },\n      {\n        \"name\": \"shift\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array. Its dtype is casted to x's dtype at run-time.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"direction\",\n        \"type\": \"string\",\n        \"default\": \"LEFT\",\n        \"description\": \"Direction of bit shift.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Einsum\",\n    \"description\": \"Evaluates the Einstein summation convention on the inputs.\\nSee the numpy.einsum documentation for more information about equation.\",\n    \"inputs\": [\n      {\n        \"name\": \"x\",\n        \"type\": \"nnabla.Variable\",\n        \"list\": true,\n        \"description\": \"List of N-D array.\"\n      }\n    ],\n    \"attributes\": [\n      {\n        \"name\": \"equation\",\n        \"type\": \"string\",\n        \"default\": \"\",\n        \"description\": \"A string that folllows Einstein summation convention.\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"y\",\n        \"type\": \"nnabla.Variable\",\n        \"description\": \"A N-D array.\"\n      }\n    ]\n  }\n]"
  },
  {
    "path": "source/nnabla-proto.js",
    "content": "\nexport const nnabla = {};\n\nnnabla.Shape = class Shape {\n\n    constructor() {\n        this.dim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Shape();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim = reader.array(message.dim, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Shape();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim\":\n                    reader.array(message.dim, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Communicator = class Communicator {\n\n    static decode(reader, length) {\n        const message = new nnabla.Communicator();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Communicator();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Context = class Context {\n\n    constructor() {\n        this.backends = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Context();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.backends.push(reader.string());\n                    break;\n                case 2:\n                    message.array_class = reader.string();\n                    break;\n                case 3:\n                    message.device_id = reader.string();\n                    break;\n                case 4:\n                    message.backend = reader.string();\n                    break;\n                case 5:\n                    message.compute_backend = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Context();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"backends\":\n                    reader.array(message.backends, () => reader.string());\n                    break;\n                case \"array_class\":\n                    message.array_class = reader.string();\n                    break;\n                case \"device_id\":\n                    message.device_id = reader.string();\n                    break;\n                case \"backend\":\n                    message.backend = reader.string();\n                    break;\n                case \"compute_backend\":\n                    message.compute_backend = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Context.prototype.array_class = \"\";\nnnabla.Context.prototype.device_id = \"\";\nnnabla.Context.prototype.backend = \"\";\nnnabla.Context.prototype.compute_backend = \"\";\n\nnnabla.NNablaProtoBuf = class NNablaProtoBuf {\n\n    constructor() {\n        this.network = [];\n        this.parameter = [];\n        this.dataset = [];\n        this.optimizer = [];\n        this.monitor = [];\n        this.executor = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.NNablaProtoBuf();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.version = reader.string();\n                    break;\n                case 2:\n                    message.global_config = nnabla.GlobalConfig.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.training_config = nnabla.TrainingConfig.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.network.push(nnabla.Network.decode(reader, reader.uint32()));\n                    break;\n                case 200:\n                    message.parameter.push(nnabla.Parameter.decode(reader, reader.uint32()));\n                    break;\n                case 300:\n                    message.dataset.push(nnabla.Dataset.decode(reader, reader.uint32()));\n                    break;\n                case 400:\n                    message.optimizer.push(nnabla.Optimizer.decode(reader, reader.uint32()));\n                    break;\n                case 500:\n                    message.monitor.push(nnabla.Monitor.decode(reader, reader.uint32()));\n                    break;\n                case 600:\n                    message.executor.push(nnabla.Executor.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.NNablaProtoBuf();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"version\":\n                    message.version = reader.string();\n                    break;\n                case \"global_config\":\n                    message.global_config = nnabla.GlobalConfig.decodeText(reader);\n                    break;\n                case \"training_config\":\n                    message.training_config = nnabla.TrainingConfig.decodeText(reader);\n                    break;\n                case \"network\":\n                    message.network.push(nnabla.Network.decodeText(reader));\n                    break;\n                case \"parameter\":\n                    message.parameter.push(nnabla.Parameter.decodeText(reader));\n                    break;\n                case \"dataset\":\n                    message.dataset.push(nnabla.Dataset.decodeText(reader));\n                    break;\n                case \"optimizer\":\n                    message.optimizer.push(nnabla.Optimizer.decodeText(reader));\n                    break;\n                case \"monitor\":\n                    message.monitor.push(nnabla.Monitor.decodeText(reader));\n                    break;\n                case \"executor\":\n                    message.executor.push(nnabla.Executor.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.NNablaProtoBuf.prototype.version = \"\";\nnnabla.NNablaProtoBuf.prototype.global_config = null;\nnnabla.NNablaProtoBuf.prototype.training_config = null;\n\nnnabla.GlobalConfig = class GlobalConfig {\n\n    static decode(reader, length) {\n        const message = new nnabla.GlobalConfig();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.default_context = nnabla.Context.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GlobalConfig();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"default_context\":\n                    message.default_context = nnabla.Context.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GlobalConfig.prototype.default_context = null;\n\nnnabla.TrainingConfig = class TrainingConfig {\n\n    static decode(reader, length) {\n        const message = new nnabla.TrainingConfig();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.max_epoch = reader.int64();\n                    break;\n                case 2:\n                    message.iter_per_epoch = reader.int64();\n                    break;\n                case 100:\n                    message.save_best = reader.bool();\n                    break;\n                case 200:\n                    message.monitor_interval = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TrainingConfig();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"max_epoch\":\n                    message.max_epoch = reader.int64();\n                    break;\n                case \"iter_per_epoch\":\n                    message.iter_per_epoch = reader.int64();\n                    break;\n                case \"save_best\":\n                    message.save_best = reader.bool();\n                    break;\n                case \"monitor_interval\":\n                    message.monitor_interval = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.TrainingConfig.prototype.max_epoch = 0n;\nnnabla.TrainingConfig.prototype.iter_per_epoch = 0n;\nnnabla.TrainingConfig.prototype.save_best = false;\nnnabla.TrainingConfig.prototype.monitor_interval = 0n;\n\nnnabla.Network = class Network {\n\n    constructor() {\n        this.repeat_info = [];\n        this.variable = [];\n        this.function = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Network();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 10:\n                    message.batch_size = reader.int64();\n                    break;\n                case 11:\n                    message.repeat_info.push(nnabla.RepeatInfo.decode(reader, reader.uint32()));\n                    break;\n                case 100:\n                    message.variable.push(nnabla.Variable.decode(reader, reader.uint32()));\n                    break;\n                case 200:\n                    message.function.push(nnabla.Function.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Network();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"batch_size\":\n                    message.batch_size = reader.int64();\n                    break;\n                case \"repeat_info\":\n                    message.repeat_info.push(nnabla.RepeatInfo.decodeText(reader));\n                    break;\n                case \"variable\":\n                    message.variable.push(nnabla.Variable.decodeText(reader));\n                    break;\n                case \"function\":\n                    message.function.push(nnabla.Function.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Network.prototype.name = \"\";\nnnabla.Network.prototype.batch_size = 0n;\n\nnnabla.RepeatInfo = class RepeatInfo {\n\n    static decode(reader, length) {\n        const message = new nnabla.RepeatInfo();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.id = reader.string();\n                    break;\n                case 2:\n                    message.times = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RepeatInfo();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"id\":\n                    message.id = reader.string();\n                    break;\n                case \"times\":\n                    message.times = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RepeatInfo.prototype.id = \"\";\nnnabla.RepeatInfo.prototype.times = 0n;\n\nnnabla.RepeatParameter = class RepeatParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RepeatParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.repeat_id = reader.string();\n                    break;\n                case 2:\n                    message.times = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RepeatParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"repeat_id\":\n                    message.repeat_id = reader.string();\n                    break;\n                case \"times\":\n                    message.times = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RepeatParameter.prototype.repeat_id = \"\";\nnnabla.RepeatParameter.prototype.times = 0n;\n\nnnabla.RecurrentParameter = class RecurrentParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RecurrentParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.repeat_id = reader.string();\n                    break;\n                case 2:\n                    message.length = reader.int64();\n                    break;\n                case 3:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RecurrentParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"repeat_id\":\n                    message.repeat_id = reader.string();\n                    break;\n                case \"length\":\n                    message.length = reader.int64();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RecurrentParameter.prototype.repeat_id = \"\";\nnnabla.RecurrentParameter.prototype.length = 0n;\nnnabla.RecurrentParameter.prototype.axis = 0n;\n\nnnabla.Variable = class Variable {\n\n    constructor() {\n        this.repeat_id = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Variable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.repeat_id.push(reader.string());\n                    break;\n                case 20:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.initializer = nnabla.Initializer.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Variable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"repeat_id\":\n                    reader.array(message.repeat_id, () => reader.string());\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"initializer\":\n                    message.initializer = nnabla.Initializer.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Variable.prototype.name = \"\";\nnnabla.Variable.prototype.type = \"\";\nnnabla.Variable.prototype.shape = null;\nnnabla.Variable.prototype.initializer = null;\n\nnnabla.Initializer = class Initializer {\n\n    static decode(reader, length) {\n        const message = new nnabla.Initializer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 10:\n                    message.multiplier = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Initializer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"multiplier\":\n                    message.multiplier = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Initializer.prototype.type = \"\";\nnnabla.Initializer.prototype.multiplier = 0;\n\nnnabla.Parameter = class Parameter {\n\n    constructor() {\n        this.data = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                case 20:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.data = reader.floats(message.data, tag);\n                    break;\n                case 101:\n                    message.need_grad = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"data\":\n                    reader.array(message.data, () => reader.float());\n                    break;\n                case \"need_grad\":\n                    message.need_grad = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Parameter.prototype.variable_name = \"\";\nnnabla.Parameter.prototype.shape = null;\nnnabla.Parameter.prototype.need_grad = false;\n\nnnabla.Dataset = class Dataset {\n\n    constructor() {\n        this.variable = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Dataset();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 10:\n                    message.uri = reader.string();\n                    break;\n                case 20:\n                    message.batch_size = reader.int64();\n                    break;\n                case 30:\n                    message.cache_dir = reader.string();\n                    break;\n                case 31:\n                    message.overwrite_cache = reader.bool();\n                    break;\n                case 32:\n                    message.create_cache_explicitly = reader.bool();\n                    break;\n                case 100:\n                    message.shuffle = reader.bool();\n                    break;\n                case 101:\n                    message.no_image_normalization = reader.bool();\n                    break;\n                case 200:\n                    message.variable.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Dataset();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"uri\":\n                    message.uri = reader.string();\n                    break;\n                case \"batch_size\":\n                    message.batch_size = reader.int64();\n                    break;\n                case \"cache_dir\":\n                    message.cache_dir = reader.string();\n                    break;\n                case \"overwrite_cache\":\n                    message.overwrite_cache = reader.bool();\n                    break;\n                case \"create_cache_explicitly\":\n                    message.create_cache_explicitly = reader.bool();\n                    break;\n                case \"shuffle\":\n                    message.shuffle = reader.bool();\n                    break;\n                case \"no_image_normalization\":\n                    message.no_image_normalization = reader.bool();\n                    break;\n                case \"variable\":\n                    reader.array(message.variable, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Dataset.prototype.name = \"\";\nnnabla.Dataset.prototype.type = \"\";\nnnabla.Dataset.prototype.uri = \"\";\nnnabla.Dataset.prototype.batch_size = 0n;\nnnabla.Dataset.prototype.cache_dir = \"\";\nnnabla.Dataset.prototype.overwrite_cache = false;\nnnabla.Dataset.prototype.create_cache_explicitly = false;\nnnabla.Dataset.prototype.shuffle = false;\nnnabla.Dataset.prototype.no_image_normalization = false;\n\nnnabla.Optimizer = class Optimizer {\n\n    constructor() {\n        this.dataset_name = [];\n        this.data_variable = [];\n        this.generator_variable = [];\n        this.loss_variable = [];\n        this.parameter_variable = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Optimizer();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 3:\n                    message.order = reader.int64();\n                    break;\n                case 10:\n                    message.network_name = reader.string();\n                    break;\n                case 20:\n                    message.dataset_name.push(reader.string());\n                    break;\n                case 30:\n                    message.solver = nnabla.Solver.decode(reader, reader.uint32());\n                    break;\n                case 40:\n                    message.update_interval = reader.int64();\n                    break;\n                case 50:\n                    message.data_variable.push(nnabla.DataVariable.decode(reader, reader.uint32()));\n                    break;\n                case 60:\n                    message.generator_variable.push(nnabla.GeneratorVariable.decode(reader, reader.uint32()));\n                    break;\n                case 70:\n                    message.loss_variable.push(nnabla.LossVariable.decode(reader, reader.uint32()));\n                    break;\n                case 80:\n                    message.parameter_variable.push(nnabla.ParameterVariable.decode(reader, reader.uint32()));\n                    break;\n                case 100:\n                    message.start_iter = reader.int64();\n                    break;\n                case 101:\n                    message.end_iter = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Optimizer();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"order\":\n                    message.order = reader.int64();\n                    break;\n                case \"network_name\":\n                    message.network_name = reader.string();\n                    break;\n                case \"dataset_name\":\n                    reader.array(message.dataset_name, () => reader.string());\n                    break;\n                case \"solver\":\n                    message.solver = nnabla.Solver.decodeText(reader);\n                    break;\n                case \"update_interval\":\n                    message.update_interval = reader.int64();\n                    break;\n                case \"data_variable\":\n                    message.data_variable.push(nnabla.DataVariable.decodeText(reader));\n                    break;\n                case \"generator_variable\":\n                    message.generator_variable.push(nnabla.GeneratorVariable.decodeText(reader));\n                    break;\n                case \"loss_variable\":\n                    message.loss_variable.push(nnabla.LossVariable.decodeText(reader));\n                    break;\n                case \"parameter_variable\":\n                    message.parameter_variable.push(nnabla.ParameterVariable.decodeText(reader));\n                    break;\n                case \"start_iter\":\n                    message.start_iter = reader.int64();\n                    break;\n                case \"end_iter\":\n                    message.end_iter = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Optimizer.prototype.name = \"\";\nnnabla.Optimizer.prototype.order = 0n;\nnnabla.Optimizer.prototype.network_name = \"\";\nnnabla.Optimizer.prototype.solver = null;\nnnabla.Optimizer.prototype.update_interval = 0n;\nnnabla.Optimizer.prototype.start_iter = 0n;\nnnabla.Optimizer.prototype.end_iter = 0n;\n\nnnabla.SolverStateParameter = class SolverStateParameter {\n\n    constructor() {\n        this.data = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.SolverStateParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 20:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.data = reader.floats(message.data, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SolverStateParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"data\":\n                    reader.array(message.data, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SolverStateParameter.prototype.shape = null;\n\nnnabla.SolverState = class SolverState {\n\n    constructor() {\n        this.state_parameter = {};\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.SolverState();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.t = reader.uint32();\n                    break;\n                case 2:\n                    reader.entry(message.state_parameter, () => reader.string(), () => nnabla.SolverStateParameter.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SolverState();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"t\":\n                    message.t = reader.uint32();\n                    break;\n                case \"state_parameter\":\n                    reader.entry(message.state_parameter, () => reader.string(), () => nnabla.SolverStateParameter.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SolverState.prototype.t = 0;\n\nnnabla.Solver = class Solver {\n\n    constructor() {\n        this.states = {};\n    }\n\n    get parameter() {\n        nnabla.Solver.parameterSet = nnabla.Solver.parameterSet || new Set([\"sgd_param\", \"sgdw_param\", \"momentum_param\", \"lars_param\", \"nesterov_param\", \"adadelta_param\", \"adagrad_param\", \"adabelief_param\", \"rmsprop_param\", \"rmsprop_graves_param\", \"adam_param\", \"adamw_param\", \"adabound_param\", \"adamax_param\", \"amsgrad_param\", \"amsbound_param\", \"lamb_param\", \"lion_param\"]);\n        return Object.keys(this).find((key) => nnabla.Solver.parameterSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Solver();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 10:\n                    message.context = nnabla.Context.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.weight_decay = reader.float();\n                    break;\n                case 40:\n                    reader.entry(message.states, () => reader.string(), () => nnabla.SolverState.decode(reader, reader.uint32()));\n                    break;\n                case 100:\n                    message.sgd_param = nnabla.SgdParameter.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.sgdw_param = nnabla.SgdWParameter.decode(reader, reader.uint32());\n                    break;\n                case 102:\n                    message.momentum_param = nnabla.MomentumParameter.decode(reader, reader.uint32());\n                    break;\n                case 103:\n                    message.lars_param = nnabla.LarsParameter.decode(reader, reader.uint32());\n                    break;\n                case 104:\n                    message.nesterov_param = nnabla.NesterovParameter.decode(reader, reader.uint32());\n                    break;\n                case 105:\n                    message.adadelta_param = nnabla.AdadeltaParameter.decode(reader, reader.uint32());\n                    break;\n                case 106:\n                    message.adagrad_param = nnabla.AdagradParameter.decode(reader, reader.uint32());\n                    break;\n                case 107:\n                    message.adabelief_param = nnabla.AdaBeliefParameter.decode(reader, reader.uint32());\n                    break;\n                case 108:\n                    message.rmsprop_param = nnabla.RMSpropParameter.decode(reader, reader.uint32());\n                    break;\n                case 109:\n                    message.rmsprop_graves_param = nnabla.RMSpropGravesParameter.decode(reader, reader.uint32());\n                    break;\n                case 110:\n                    message.adam_param = nnabla.AdamParameter.decode(reader, reader.uint32());\n                    break;\n                case 111:\n                    message.adamw_param = nnabla.AdamWParameter.decode(reader, reader.uint32());\n                    break;\n                case 112:\n                    message.adabound_param = nnabla.AdaBoundParameter.decode(reader, reader.uint32());\n                    break;\n                case 113:\n                    message.adamax_param = nnabla.AdamaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 114:\n                    message.amsgrad_param = nnabla.AMSGRADParameter.decode(reader, reader.uint32());\n                    break;\n                case 115:\n                    message.amsbound_param = nnabla.AMSBoundParameter.decode(reader, reader.uint32());\n                    break;\n                case 116:\n                    message.lamb_param = nnabla.LambParameter.decode(reader, reader.uint32());\n                    break;\n                case 117:\n                    message.lion_param = nnabla.LionParameter.decode(reader, reader.uint32());\n                    break;\n                case 200:\n                    message.lr_scheduler_type = reader.string();\n                    break;\n                case 210:\n                    message.polynomial_scheduler_param = nnabla.PolynomialSchedulerParameter.decode(reader, reader.uint32());\n                    break;\n                case 211:\n                    message.cosine_scheduler_param = nnabla.CosineSchedulerParameter.decode(reader, reader.uint32());\n                    break;\n                case 212:\n                    message.exponential_scheduler_param = nnabla.ExponentialSchedulerParameter.decode(reader, reader.uint32());\n                    break;\n                case 213:\n                    message.step_scheduler_param = nnabla.StepSchedulerParameter.decode(reader, reader.uint32());\n                    break;\n                case 299:\n                    message.custom_scheduler_param = nnabla.CustomSchedulerParameter.decode(reader, reader.uint32());\n                    break;\n                case 300:\n                    message.lr_warmup_scheduler_type = reader.string();\n                    break;\n                case 310:\n                    message.linear_warmup_scheduler_param = nnabla.LinearWarmupSchedulerParameter.decode(reader, reader.uint32());\n                    break;\n                case 30:\n                    message.lr_decay = reader.float();\n                    break;\n                case 31:\n                    message.lr_decay_interval = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Solver();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"context\":\n                    message.context = nnabla.Context.decodeText(reader);\n                    break;\n                case \"weight_decay\":\n                    message.weight_decay = reader.float();\n                    break;\n                case \"states\":\n                    reader.entry(message.states, () => reader.string(), () => nnabla.SolverState.decodeText(reader));\n                    break;\n                case \"sgd_param\":\n                    message.sgd_param = nnabla.SgdParameter.decodeText(reader);\n                    break;\n                case \"sgdw_param\":\n                    message.sgdw_param = nnabla.SgdWParameter.decodeText(reader);\n                    break;\n                case \"momentum_param\":\n                    message.momentum_param = nnabla.MomentumParameter.decodeText(reader);\n                    break;\n                case \"lars_param\":\n                    message.lars_param = nnabla.LarsParameter.decodeText(reader);\n                    break;\n                case \"nesterov_param\":\n                    message.nesterov_param = nnabla.NesterovParameter.decodeText(reader);\n                    break;\n                case \"adadelta_param\":\n                    message.adadelta_param = nnabla.AdadeltaParameter.decodeText(reader);\n                    break;\n                case \"adagrad_param\":\n                    message.adagrad_param = nnabla.AdagradParameter.decodeText(reader);\n                    break;\n                case \"adabelief_param\":\n                    message.adabelief_param = nnabla.AdaBeliefParameter.decodeText(reader);\n                    break;\n                case \"rmsprop_param\":\n                    message.rmsprop_param = nnabla.RMSpropParameter.decodeText(reader);\n                    break;\n                case \"rmsprop_graves_param\":\n                    message.rmsprop_graves_param = nnabla.RMSpropGravesParameter.decodeText(reader);\n                    break;\n                case \"adam_param\":\n                    message.adam_param = nnabla.AdamParameter.decodeText(reader);\n                    break;\n                case \"adamw_param\":\n                    message.adamw_param = nnabla.AdamWParameter.decodeText(reader);\n                    break;\n                case \"adabound_param\":\n                    message.adabound_param = nnabla.AdaBoundParameter.decodeText(reader);\n                    break;\n                case \"adamax_param\":\n                    message.adamax_param = nnabla.AdamaxParameter.decodeText(reader);\n                    break;\n                case \"amsgrad_param\":\n                    message.amsgrad_param = nnabla.AMSGRADParameter.decodeText(reader);\n                    break;\n                case \"amsbound_param\":\n                    message.amsbound_param = nnabla.AMSBoundParameter.decodeText(reader);\n                    break;\n                case \"lamb_param\":\n                    message.lamb_param = nnabla.LambParameter.decodeText(reader);\n                    break;\n                case \"lion_param\":\n                    message.lion_param = nnabla.LionParameter.decodeText(reader);\n                    break;\n                case \"lr_scheduler_type\":\n                    message.lr_scheduler_type = reader.string();\n                    break;\n                case \"polynomial_scheduler_param\":\n                    message.polynomial_scheduler_param = nnabla.PolynomialSchedulerParameter.decodeText(reader);\n                    break;\n                case \"cosine_scheduler_param\":\n                    message.cosine_scheduler_param = nnabla.CosineSchedulerParameter.decodeText(reader);\n                    break;\n                case \"exponential_scheduler_param\":\n                    message.exponential_scheduler_param = nnabla.ExponentialSchedulerParameter.decodeText(reader);\n                    break;\n                case \"step_scheduler_param\":\n                    message.step_scheduler_param = nnabla.StepSchedulerParameter.decodeText(reader);\n                    break;\n                case \"custom_scheduler_param\":\n                    message.custom_scheduler_param = nnabla.CustomSchedulerParameter.decodeText(reader);\n                    break;\n                case \"lr_warmup_scheduler_type\":\n                    message.lr_warmup_scheduler_type = reader.string();\n                    break;\n                case \"linear_warmup_scheduler_param\":\n                    message.linear_warmup_scheduler_param = nnabla.LinearWarmupSchedulerParameter.decodeText(reader);\n                    break;\n                case \"lr_decay\":\n                    message.lr_decay = reader.float();\n                    break;\n                case \"lr_decay_interval\":\n                    message.lr_decay_interval = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Solver.prototype.type = \"\";\nnnabla.Solver.prototype.context = null;\nnnabla.Solver.prototype.weight_decay = 0;\nnnabla.Solver.prototype.lr_scheduler_type = \"\";\nnnabla.Solver.prototype.polynomial_scheduler_param = null;\nnnabla.Solver.prototype.cosine_scheduler_param = null;\nnnabla.Solver.prototype.exponential_scheduler_param = null;\nnnabla.Solver.prototype.step_scheduler_param = null;\nnnabla.Solver.prototype.custom_scheduler_param = null;\nnnabla.Solver.prototype.lr_warmup_scheduler_type = \"\";\nnnabla.Solver.prototype.linear_warmup_scheduler_param = null;\nnnabla.Solver.prototype.lr_decay = 0;\nnnabla.Solver.prototype.lr_decay_interval = 0n;\n\nnnabla.SgdParameter = class SgdParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SgdParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SgdParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SgdParameter.prototype.lr = 0;\n\nnnabla.SgdWParameter = class SgdWParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SgdWParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.momentum = reader.float();\n                    break;\n                case 3:\n                    message.wd = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SgdWParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"momentum\":\n                    message.momentum = reader.float();\n                    break;\n                case \"wd\":\n                    message.wd = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SgdWParameter.prototype.lr = 0;\nnnabla.SgdWParameter.prototype.momentum = 0;\nnnabla.SgdWParameter.prototype.wd = 0;\n\nnnabla.MomentumParameter = class MomentumParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MomentumParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.momentum = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MomentumParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"momentum\":\n                    message.momentum = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MomentumParameter.prototype.lr = 0;\nnnabla.MomentumParameter.prototype.momentum = 0;\n\nnnabla.LarsParameter = class LarsParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LarsParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.momentum = reader.float();\n                    break;\n                case 3:\n                    message.coefficient = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LarsParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"momentum\":\n                    message.momentum = reader.float();\n                    break;\n                case \"coefficient\":\n                    message.coefficient = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LarsParameter.prototype.lr = 0;\nnnabla.LarsParameter.prototype.momentum = 0;\nnnabla.LarsParameter.prototype.coefficient = 0;\nnnabla.LarsParameter.prototype.eps = 0;\n\nnnabla.NesterovParameter = class NesterovParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.NesterovParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.momentum = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.NesterovParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"momentum\":\n                    message.momentum = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.NesterovParameter.prototype.lr = 0;\nnnabla.NesterovParameter.prototype.momentum = 0;\n\nnnabla.AdadeltaParameter = class AdadeltaParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdadeltaParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.decay = reader.float();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdadeltaParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"decay\":\n                    message.decay = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdadeltaParameter.prototype.lr = 0;\nnnabla.AdadeltaParameter.prototype.decay = 0;\nnnabla.AdadeltaParameter.prototype.eps = 0;\n\nnnabla.AdagradParameter = class AdagradParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdagradParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdagradParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdagradParameter.prototype.lr = 0;\nnnabla.AdagradParameter.prototype.eps = 0;\n\nnnabla.AdaBeliefParameter = class AdaBeliefParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdaBeliefParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.wd = reader.float();\n                    break;\n                case 6:\n                    message.amsgrad = reader.bool();\n                    break;\n                case 7:\n                    message.weight_decouple = reader.bool();\n                    break;\n                case 8:\n                    message.fixed_decay = reader.bool();\n                    break;\n                case 9:\n                    message.rectify = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdaBeliefParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"wd\":\n                    message.wd = reader.float();\n                    break;\n                case \"amsgrad\":\n                    message.amsgrad = reader.bool();\n                    break;\n                case \"weight_decouple\":\n                    message.weight_decouple = reader.bool();\n                    break;\n                case \"fixed_decay\":\n                    message.fixed_decay = reader.bool();\n                    break;\n                case \"rectify\":\n                    message.rectify = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdaBeliefParameter.prototype.alpha = 0;\nnnabla.AdaBeliefParameter.prototype.beta1 = 0;\nnnabla.AdaBeliefParameter.prototype.beta2 = 0;\nnnabla.AdaBeliefParameter.prototype.eps = 0;\nnnabla.AdaBeliefParameter.prototype.wd = 0;\nnnabla.AdaBeliefParameter.prototype.amsgrad = false;\nnnabla.AdaBeliefParameter.prototype.weight_decouple = false;\nnnabla.AdaBeliefParameter.prototype.fixed_decay = false;\nnnabla.AdaBeliefParameter.prototype.rectify = false;\n\nnnabla.RMSpropParameter = class RMSpropParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RMSpropParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.decay = reader.float();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RMSpropParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"decay\":\n                    message.decay = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RMSpropParameter.prototype.lr = 0;\nnnabla.RMSpropParameter.prototype.decay = 0;\nnnabla.RMSpropParameter.prototype.eps = 0;\n\nnnabla.RMSpropGravesParameter = class RMSpropGravesParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RMSpropGravesParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.decay = reader.float();\n                    break;\n                case 3:\n                    message.momentum = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RMSpropGravesParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"decay\":\n                    message.decay = reader.float();\n                    break;\n                case \"momentum\":\n                    message.momentum = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RMSpropGravesParameter.prototype.lr = 0;\nnnabla.RMSpropGravesParameter.prototype.decay = 0;\nnnabla.RMSpropGravesParameter.prototype.momentum = 0;\nnnabla.RMSpropGravesParameter.prototype.eps = 0;\n\nnnabla.AdamParameter = class AdamParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdamParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdamParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdamParameter.prototype.alpha = 0;\nnnabla.AdamParameter.prototype.beta1 = 0;\nnnabla.AdamParameter.prototype.beta2 = 0;\nnnabla.AdamParameter.prototype.eps = 0;\n\nnnabla.AdamWParameter = class AdamWParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdamWParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.wd = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdamWParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"wd\":\n                    message.wd = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdamWParameter.prototype.alpha = 0;\nnnabla.AdamWParameter.prototype.beta1 = 0;\nnnabla.AdamWParameter.prototype.beta2 = 0;\nnnabla.AdamWParameter.prototype.eps = 0;\nnnabla.AdamWParameter.prototype.wd = 0;\n\nnnabla.AdaBoundParameter = class AdaBoundParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdaBoundParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.final_lr = reader.float();\n                    break;\n                case 6:\n                    message.gamma = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdaBoundParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"final_lr\":\n                    message.final_lr = reader.float();\n                    break;\n                case \"gamma\":\n                    message.gamma = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdaBoundParameter.prototype.alpha = 0;\nnnabla.AdaBoundParameter.prototype.beta1 = 0;\nnnabla.AdaBoundParameter.prototype.beta2 = 0;\nnnabla.AdaBoundParameter.prototype.eps = 0;\nnnabla.AdaBoundParameter.prototype.final_lr = 0;\nnnabla.AdaBoundParameter.prototype.gamma = 0;\n\nnnabla.AdamaxParameter = class AdamaxParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AdamaxParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AdamaxParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AdamaxParameter.prototype.alpha = 0;\nnnabla.AdamaxParameter.prototype.beta1 = 0;\nnnabla.AdamaxParameter.prototype.beta2 = 0;\nnnabla.AdamaxParameter.prototype.eps = 0;\n\nnnabla.AMSGRADParameter = class AMSGRADParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AMSGRADParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.bias_correction = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AMSGRADParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"bias_correction\":\n                    message.bias_correction = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AMSGRADParameter.prototype.alpha = 0;\nnnabla.AMSGRADParameter.prototype.beta1 = 0;\nnnabla.AMSGRADParameter.prototype.beta2 = 0;\nnnabla.AMSGRADParameter.prototype.eps = 0;\nnnabla.AMSGRADParameter.prototype.bias_correction = false;\n\nnnabla.AMSBoundParameter = class AMSBoundParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AMSBoundParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.final_lr = reader.float();\n                    break;\n                case 6:\n                    message.gamma = reader.float();\n                    break;\n                case 7:\n                    message.bias_correction = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AMSBoundParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"final_lr\":\n                    message.final_lr = reader.float();\n                    break;\n                case \"gamma\":\n                    message.gamma = reader.float();\n                    break;\n                case \"bias_correction\":\n                    message.bias_correction = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AMSBoundParameter.prototype.alpha = 0;\nnnabla.AMSBoundParameter.prototype.beta1 = 0;\nnnabla.AMSBoundParameter.prototype.beta2 = 0;\nnnabla.AMSBoundParameter.prototype.eps = 0;\nnnabla.AMSBoundParameter.prototype.final_lr = 0;\nnnabla.AMSBoundParameter.prototype.gamma = 0;\nnnabla.AMSBoundParameter.prototype.bias_correction = false;\n\nnnabla.LambParameter = class LambParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LambParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.eta = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                case 4:\n                    message.gamma_l = reader.float();\n                    break;\n                case 5:\n                    message.gamma_u = reader.float();\n                    break;\n                case 6:\n                    message.eps = reader.float();\n                    break;\n                case 7:\n                    message.bias_correction = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LambParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"eta\":\n                    message.eta = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                case \"gamma_l\":\n                    message.gamma_l = reader.float();\n                    break;\n                case \"gamma_u\":\n                    message.gamma_u = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"bias_correction\":\n                    message.bias_correction = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LambParameter.prototype.eta = 0;\nnnabla.LambParameter.prototype.beta1 = 0;\nnnabla.LambParameter.prototype.beta2 = 0;\nnnabla.LambParameter.prototype.gamma_l = 0;\nnnabla.LambParameter.prototype.gamma_u = 0;\nnnabla.LambParameter.prototype.eps = 0;\nnnabla.LambParameter.prototype.bias_correction = false;\n\nnnabla.LionParameter = class LionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.lr = reader.float();\n                    break;\n                case 2:\n                    message.beta1 = reader.float();\n                    break;\n                case 3:\n                    message.beta2 = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"lr\":\n                    message.lr = reader.float();\n                    break;\n                case \"beta1\":\n                    message.beta1 = reader.float();\n                    break;\n                case \"beta2\":\n                    message.beta2 = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LionParameter.prototype.lr = 0;\nnnabla.LionParameter.prototype.beta1 = 0;\nnnabla.LionParameter.prototype.beta2 = 0;\n\nnnabla.PolynomialSchedulerParameter = class PolynomialSchedulerParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PolynomialSchedulerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.max_iter = reader.float();\n                    break;\n                case 2:\n                    message.power = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PolynomialSchedulerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"max_iter\":\n                    message.max_iter = reader.float();\n                    break;\n                case \"power\":\n                    message.power = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PolynomialSchedulerParameter.prototype.max_iter = 0;\nnnabla.PolynomialSchedulerParameter.prototype.power = 0;\n\nnnabla.CosineSchedulerParameter = class CosineSchedulerParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CosineSchedulerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.max_iter = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CosineSchedulerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"max_iter\":\n                    message.max_iter = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CosineSchedulerParameter.prototype.max_iter = 0;\n\nnnabla.ExponentialSchedulerParameter = class ExponentialSchedulerParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ExponentialSchedulerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.gamma = reader.float();\n                    break;\n                case 2:\n                    message.iter_interval = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ExponentialSchedulerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"gamma\":\n                    message.gamma = reader.float();\n                    break;\n                case \"iter_interval\":\n                    message.iter_interval = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ExponentialSchedulerParameter.prototype.gamma = 0;\nnnabla.ExponentialSchedulerParameter.prototype.iter_interval = 0n;\n\nnnabla.StepSchedulerParameter = class StepSchedulerParameter {\n\n    constructor() {\n        this.iter_steps = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.StepSchedulerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.gamma = reader.float();\n                    break;\n                case 2:\n                    message.iter_steps = reader.array(message.iter_steps, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.StepSchedulerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"gamma\":\n                    message.gamma = reader.float();\n                    break;\n                case \"iter_steps\":\n                    reader.array(message.iter_steps, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.StepSchedulerParameter.prototype.gamma = 0;\n\nnnabla.CustomSchedulerParameter = class CustomSchedulerParameter {\n\n    constructor() {\n        this.data_variable = [];\n        this.output_variable = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.CustomSchedulerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.max_iter = reader.float();\n                    break;\n                case 10:\n                    message.network_name = reader.string();\n                    break;\n                case 50:\n                    message.data_variable.push(nnabla.DataVariable.decode(reader, reader.uint32()));\n                    break;\n                case 80:\n                    message.output_variable.push(nnabla.OutputVariable.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CustomSchedulerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"max_iter\":\n                    message.max_iter = reader.float();\n                    break;\n                case \"network_name\":\n                    message.network_name = reader.string();\n                    break;\n                case \"data_variable\":\n                    message.data_variable.push(nnabla.DataVariable.decodeText(reader));\n                    break;\n                case \"output_variable\":\n                    message.output_variable.push(nnabla.OutputVariable.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CustomSchedulerParameter.prototype.max_iter = 0;\nnnabla.CustomSchedulerParameter.prototype.network_name = \"\";\n\nnnabla.LinearWarmupSchedulerParameter = class LinearWarmupSchedulerParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LinearWarmupSchedulerParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.warmup_iter = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LinearWarmupSchedulerParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"warmup_iter\":\n                    message.warmup_iter = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LinearWarmupSchedulerParameter.prototype.warmup_iter = 0n;\n\nnnabla.DataVariable = class DataVariable {\n\n    static decode(reader, length) {\n        const message = new nnabla.DataVariable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                case 3:\n                    message.data_name = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.DataVariable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                case \"data_name\":\n                    message.data_name = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.DataVariable.prototype.variable_name = \"\";\nnnabla.DataVariable.prototype.data_name = \"\";\n\nnnabla.GeneratorVariable = class GeneratorVariable {\n\n    static decode(reader, length) {\n        const message = new nnabla.GeneratorVariable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.multiplier = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GeneratorVariable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"multiplier\":\n                    message.multiplier = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GeneratorVariable.prototype.variable_name = \"\";\nnnabla.GeneratorVariable.prototype.type = \"\";\nnnabla.GeneratorVariable.prototype.multiplier = 0;\n\nnnabla.LossVariable = class LossVariable {\n\n    static decode(reader, length) {\n        const message = new nnabla.LossVariable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LossVariable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LossVariable.prototype.variable_name = \"\";\n\nnnabla.ParameterVariable = class ParameterVariable {\n\n    static decode(reader, length) {\n        const message = new nnabla.ParameterVariable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                case 2:\n                    message.learning_rate_multiplier = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ParameterVariable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                case \"learning_rate_multiplier\":\n                    message.learning_rate_multiplier = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ParameterVariable.prototype.variable_name = \"\";\nnnabla.ParameterVariable.prototype.learning_rate_multiplier = 0;\n\nnnabla.Monitor = class Monitor {\n\n    constructor() {\n        this.dataset_name = [];\n        this.data_variable = [];\n        this.generator_variable = [];\n        this.monitor_variable = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Monitor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 10:\n                    message.network_name = reader.string();\n                    break;\n                case 20:\n                    message.dataset_name.push(reader.string());\n                    break;\n                case 50:\n                    message.data_variable.push(nnabla.DataVariable.decode(reader, reader.uint32()));\n                    break;\n                case 60:\n                    message.generator_variable.push(nnabla.GeneratorVariable.decode(reader, reader.uint32()));\n                    break;\n                case 70:\n                    message.monitor_variable.push(nnabla.MonitorVariable.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Monitor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"network_name\":\n                    message.network_name = reader.string();\n                    break;\n                case \"dataset_name\":\n                    reader.array(message.dataset_name, () => reader.string());\n                    break;\n                case \"data_variable\":\n                    message.data_variable.push(nnabla.DataVariable.decodeText(reader));\n                    break;\n                case \"generator_variable\":\n                    message.generator_variable.push(nnabla.GeneratorVariable.decodeText(reader));\n                    break;\n                case \"monitor_variable\":\n                    message.monitor_variable.push(nnabla.MonitorVariable.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Monitor.prototype.name = \"\";\nnnabla.Monitor.prototype.network_name = \"\";\n\nnnabla.MonitorVariable = class MonitorVariable {\n\n    static decode(reader, length) {\n        const message = new nnabla.MonitorVariable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.data_name = reader.string();\n                    break;\n                case 100:\n                    message.multiplier = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MonitorVariable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"data_name\":\n                    message.data_name = reader.string();\n                    break;\n                case \"multiplier\":\n                    message.multiplier = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MonitorVariable.prototype.variable_name = \"\";\nnnabla.MonitorVariable.prototype.type = \"\";\nnnabla.MonitorVariable.prototype.data_name = \"\";\nnnabla.MonitorVariable.prototype.multiplier = 0;\n\nnnabla.Executor = class Executor {\n\n    constructor() {\n        this.data_variable = [];\n        this.generator_variable = [];\n        this.loss_variable = [];\n        this.output_variable = [];\n        this.parameter_variable = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Executor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 10:\n                    message.network_name = reader.string();\n                    break;\n                case 20:\n                    message.num_evaluations = reader.int64();\n                    break;\n                case 21:\n                    message.repeat_evaluation_type = reader.string();\n                    break;\n                case 30:\n                    message.need_back_propagation = reader.bool();\n                    break;\n                case 50:\n                    message.data_variable.push(nnabla.DataVariable.decode(reader, reader.uint32()));\n                    break;\n                case 60:\n                    message.generator_variable.push(nnabla.GeneratorVariable.decode(reader, reader.uint32()));\n                    break;\n                case 70:\n                    message.loss_variable.push(nnabla.LossVariable.decode(reader, reader.uint32()));\n                    break;\n                case 80:\n                    message.output_variable.push(nnabla.OutputVariable.decode(reader, reader.uint32()));\n                    break;\n                case 90:\n                    message.parameter_variable.push(nnabla.ParameterVariable.decode(reader, reader.uint32()));\n                    break;\n                case 101:\n                    message.no_image_normalization = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Executor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"network_name\":\n                    message.network_name = reader.string();\n                    break;\n                case \"num_evaluations\":\n                    message.num_evaluations = reader.int64();\n                    break;\n                case \"repeat_evaluation_type\":\n                    message.repeat_evaluation_type = reader.string();\n                    break;\n                case \"need_back_propagation\":\n                    message.need_back_propagation = reader.bool();\n                    break;\n                case \"data_variable\":\n                    message.data_variable.push(nnabla.DataVariable.decodeText(reader));\n                    break;\n                case \"generator_variable\":\n                    message.generator_variable.push(nnabla.GeneratorVariable.decodeText(reader));\n                    break;\n                case \"loss_variable\":\n                    message.loss_variable.push(nnabla.LossVariable.decodeText(reader));\n                    break;\n                case \"output_variable\":\n                    message.output_variable.push(nnabla.OutputVariable.decodeText(reader));\n                    break;\n                case \"parameter_variable\":\n                    message.parameter_variable.push(nnabla.ParameterVariable.decodeText(reader));\n                    break;\n                case \"no_image_normalization\":\n                    message.no_image_normalization = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Executor.prototype.name = \"\";\nnnabla.Executor.prototype.network_name = \"\";\nnnabla.Executor.prototype.num_evaluations = 0n;\nnnabla.Executor.prototype.repeat_evaluation_type = \"\";\nnnabla.Executor.prototype.need_back_propagation = false;\nnnabla.Executor.prototype.no_image_normalization = false;\n\nnnabla.OutputVariable = class OutputVariable {\n\n    static decode(reader, length) {\n        const message = new nnabla.OutputVariable();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.variable_name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.data_name = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.OutputVariable();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"variable_name\":\n                    message.variable_name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"data_name\":\n                    message.data_name = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.OutputVariable.prototype.variable_name = \"\";\nnnabla.OutputVariable.prototype.type = \"\";\nnnabla.OutputVariable.prototype.data_name = \"\";\n\nnnabla.Function = class Function {\n\n    constructor() {\n        this.repeat_id = [];\n        this.input = [];\n        this.output = [];\n    }\n\n    get parameter() {\n        nnabla.Function.parameterSet = nnabla.Function.parameterSet || new Set([\"affine_param\", \"rnn_param\", \"lstm_param\", \"gru_param\", \"convolution_param\", \"fused_convolution_param\", \"depthwise_convolution_param\", \"deconvolution_param\", \"depthwise_deconvolution_param\", \"deformable_convolution_param\", \"max_pooling_param\", \"average_pooling_param\", \"sum_pooling_param\", \"unpooling_param\", \"roi_align_param\", \"relu_param\", \"leaky_relu_param\", \"softmax_param\", \"log_softmax_param\", \"elu_param\", \"selu_param\", \"crelu_param\", \"celu_param\", \"prelu_param\", \"softplus_param\", \"fused_batch_normalization_param\", \"batch_normalization_param\", \"group_normalization_param\", \"instance_normalization_param\", \"layer_normalization_param\", \"norm_normalization_param\", \"sync_batch_normalization_param\", \"tensor_normalization_param\", \"weight_normalization_param\", \"weight_standardization_param\", \"spectral_norm_param\", \"mean_subtraction_param\", \"clip_grad_by_norm_param\", \"sum_param\", \"cumsum_param\", \"mean_param\", \"max_param\", \"min_param\", \"norm_param\", \"prod_param\", \"cumprod_param\", \"add2_param\", \"bc_add2_param\", \"sub2_param\", \"mul2_param\", \"div2_param\", \"pow2_param\", \"add_scalar_param\", \"mul_scalar_param\", \"pow_scalar_param\", \"r_sub_scalar_param\", \"r_div_scalar_param\", \"r_pow_scalar_param\", \"sign_param\", \"minimum_scalar_param\", \"maximum_scalar_param\", \"searchsorted_param\", \"logical_and_scalar_param\", \"logical_or_scalar_param\", \"logical_xor_scalar_param\", \"equal_scalar_param\", \"not_equal_scalar_param\", \"greater_equal_scalar_param\", \"greater_scalar_param\", \"less_equal_scalar_param\", \"less_scalar_param\", \"reset_nan_param\", \"reset_inf_param\", \"constant_param\", \"arange_param\", \"linspace_param\", \"batch_matmul_param\", \"round_param\", \"ceil_param\", \"floor_param\", \"concatenate_param\", \"split_param\", \"stack_param\", \"slice_param\", \"pad_param\", \"transpose_param\", \"broadcast_param\", \"broadcast_to_param\", \"tile_param\", \"one_hot_param\", \"flip_param\", \"shift_param\", \"sort_param\", \"reshape_param\", \"shape_param\", \"trilu_param\", \"meshgrid_param\", \"batch_cholesky_param\", \"gather_param\", \"scatter_nd_param\", \"scatter_add_param\", \"bool_fill_param\", \"pack_padded_sequence_param\", \"pad_packed_sequence_param\", \"interpolate_param\", \"onnx_resize_param\", \"fft_param\", \"ifft_param\", \"stft_param\", \"istft_param\", \"dropout_param\", \"top_k_data_param\", \"top_k_grad_param\", \"rand_param\", \"randint_param\", \"randn_param\", \"rand_binomial_param\", \"rand_beta_param\", \"rand_gamma_param\", \"random_choice_param\", \"random_crop_param\", \"random_flip_param\", \"random_shift_param\", \"random_erase_param\", \"image_augmentation_param\", \"softmax_cross_entropy_param\", \"categorical_cross_entropy_param\", \"huber_loss_param\", \"epsilon_insensitive_loss_param\", \"kl_multinomial_param\", \"affine_grid_param\", \"warp_by_grid_param\", \"binary_connect_affine_param\", \"binary_connect_convolution_param\", \"binary_weight_affine_param\", \"binary_weight_convolution_param\", \"inq_affine_param\", \"inq_convolution_param\", \"fixed_point_quantize_param\", \"min_max_quantize_param\", \"pow2_quantize_param\", \"prune_param\", \"quantize_linear_param\", \"top_n_error_param\", \"confusion_matrix_param\", \"vat_noise_param\", \"sink_param\", \"nms_detection2d_param\", \"onnx_non_max_suppression_param\", \"max_pooling_backward_param\", \"patch_correlation_param\", \"unique_param\", \"eye_like_param\", \"mod2_param\", \"bit_shift_param\", \"einsum_param\"]);\n        return Object.keys(this).find((key) => nnabla.Function.parameterSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.Function();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 3:\n                    message.repeat_id.push(reader.string());\n                    break;\n                case 10:\n                    message.context = nnabla.Context.decode(reader, reader.uint32());\n                    break;\n                case 20:\n                    message.input.push(reader.string());\n                    break;\n                case 30:\n                    message.output.push(reader.string());\n                    break;\n                case 1001:\n                    message.affine_param = nnabla.AffineParameter.decode(reader, reader.uint32());\n                    break;\n                case 1002:\n                    message.rnn_param = nnabla.RNNParameter.decode(reader, reader.uint32());\n                    break;\n                case 1003:\n                    message.lstm_param = nnabla.LSTMParameter.decode(reader, reader.uint32());\n                    break;\n                case 1004:\n                    message.gru_param = nnabla.GRUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1005:\n                    message.convolution_param = nnabla.ConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1006:\n                    message.fused_convolution_param = nnabla.FusedConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1007:\n                    message.depthwise_convolution_param = nnabla.DepthwiseConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1008:\n                    message.deconvolution_param = nnabla.DeconvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1009:\n                    message.depthwise_deconvolution_param = nnabla.DepthwiseDeconvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1010:\n                    message.deformable_convolution_param = nnabla.DeformableConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1012:\n                    message.max_pooling_param = nnabla.MaxPoolingParameter.decode(reader, reader.uint32());\n                    break;\n                case 1013:\n                    message.average_pooling_param = nnabla.AveragePoolingParameter.decode(reader, reader.uint32());\n                    break;\n                case 1015:\n                    message.sum_pooling_param = nnabla.SumPoolingParameter.decode(reader, reader.uint32());\n                    break;\n                case 1016:\n                    message.unpooling_param = nnabla.UnpoolingParameter.decode(reader, reader.uint32());\n                    break;\n                case 1018:\n                    message.roi_align_param = nnabla.RoiAlignParameter.decode(reader, reader.uint32());\n                    break;\n                case 1022:\n                    message.relu_param = nnabla.ReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1023:\n                    message.leaky_relu_param = nnabla.LeakyReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1024:\n                    message.softmax_param = nnabla.SoftmaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 1025:\n                    message.log_softmax_param = nnabla.LogSoftmaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 1026:\n                    message.elu_param = nnabla.ELUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1027:\n                    message.selu_param = nnabla.SELUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1028:\n                    message.crelu_param = nnabla.CReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1029:\n                    message.celu_param = nnabla.CELUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1030:\n                    message.prelu_param = nnabla.PReLUParameter.decode(reader, reader.uint32());\n                    break;\n                case 1037:\n                    message.softplus_param = nnabla.SoftPlusParameter.decode(reader, reader.uint32());\n                    break;\n                case 1041:\n                    message.fused_batch_normalization_param = nnabla.FusedBatchNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1042:\n                    message.batch_normalization_param = nnabla.BatchNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1043:\n                    message.group_normalization_param = nnabla.GroupNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1044:\n                    message.instance_normalization_param = nnabla.InstanceNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1045:\n                    message.layer_normalization_param = nnabla.LayerNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1046:\n                    message.norm_normalization_param = nnabla.NormNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1047:\n                    message.sync_batch_normalization_param = nnabla.SyncBatchNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1048:\n                    message.tensor_normalization_param = nnabla.TensorNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1049:\n                    message.weight_normalization_param = nnabla.WeightNormalizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1050:\n                    message.weight_standardization_param = nnabla.WeightStandardizationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1051:\n                    message.spectral_norm_param = nnabla.SpectralNormParameter.decode(reader, reader.uint32());\n                    break;\n                case 1052:\n                    message.mean_subtraction_param = nnabla.MeanSubtractionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1054:\n                    message.clip_grad_by_norm_param = nnabla.ClipGradByNormParameter.decode(reader, reader.uint32());\n                    break;\n                case 1055:\n                    message.sum_param = nnabla.SumParameter.decode(reader, reader.uint32());\n                    break;\n                case 1056:\n                    message.cumsum_param = nnabla.CumSumParameter.decode(reader, reader.uint32());\n                    break;\n                case 1057:\n                    message.mean_param = nnabla.MeanParameter.decode(reader, reader.uint32());\n                    break;\n                case 1058:\n                    message.max_param = nnabla.MaxParameter.decode(reader, reader.uint32());\n                    break;\n                case 1059:\n                    message.min_param = nnabla.MinParameter.decode(reader, reader.uint32());\n                    break;\n                case 1060:\n                    message.norm_param = nnabla.NormParameter.decode(reader, reader.uint32());\n                    break;\n                case 1061:\n                    message.prod_param = nnabla.ProdParameter.decode(reader, reader.uint32());\n                    break;\n                case 1062:\n                    message.cumprod_param = nnabla.CumProdParameter.decode(reader, reader.uint32());\n                    break;\n                case 1065:\n                    message.add2_param = nnabla.Add2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1067:\n                    message.bc_add2_param = nnabla.BcAdd2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1068:\n                    message.sub2_param = nnabla.Sub2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1069:\n                    message.mul2_param = nnabla.Mul2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1071:\n                    message.div2_param = nnabla.Div2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1072:\n                    message.pow2_param = nnabla.Pow2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1073:\n                    message.add_scalar_param = nnabla.AddScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1074:\n                    message.mul_scalar_param = nnabla.MulScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1075:\n                    message.pow_scalar_param = nnabla.PowScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1076:\n                    message.r_sub_scalar_param = nnabla.RSubScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1077:\n                    message.r_div_scalar_param = nnabla.RDivScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1078:\n                    message.r_pow_scalar_param = nnabla.RPowScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1079:\n                    message.sign_param = nnabla.SignParameter.decode(reader, reader.uint32());\n                    break;\n                case 1082:\n                    message.minimum_scalar_param = nnabla.MinimumScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1083:\n                    message.maximum_scalar_param = nnabla.MaximumScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1093:\n                    message.searchsorted_param = nnabla.SearchSortedParameter.decode(reader, reader.uint32());\n                    break;\n                case 1094:\n                    message.logical_and_scalar_param = nnabla.LogicalAndScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1095:\n                    message.logical_or_scalar_param = nnabla.LogicalOrScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1096:\n                    message.logical_xor_scalar_param = nnabla.LogicalXorScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1097:\n                    message.equal_scalar_param = nnabla.EqualScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1098:\n                    message.not_equal_scalar_param = nnabla.NotEqualScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1099:\n                    message.greater_equal_scalar_param = nnabla.GreaterEqualScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1100:\n                    message.greater_scalar_param = nnabla.GreaterScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1101:\n                    message.less_equal_scalar_param = nnabla.LessEqualScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1102:\n                    message.less_scalar_param = nnabla.LessScalarParameter.decode(reader, reader.uint32());\n                    break;\n                case 1106:\n                    message.reset_nan_param = nnabla.ResetNaNParameter.decode(reader, reader.uint32());\n                    break;\n                case 1107:\n                    message.reset_inf_param = nnabla.ResetInfParameter.decode(reader, reader.uint32());\n                    break;\n                case 1109:\n                    message.constant_param = nnabla.ConstantParameter.decode(reader, reader.uint32());\n                    break;\n                case 1110:\n                    message.arange_param = nnabla.ArangeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1111:\n                    message.linspace_param = nnabla.LinspaceParameter.decode(reader, reader.uint32());\n                    break;\n                case 1116:\n                    message.batch_matmul_param = nnabla.BatchMatmulParameter.decode(reader, reader.uint32());\n                    break;\n                case 1117:\n                    message.round_param = nnabla.RoundParameter.decode(reader, reader.uint32());\n                    break;\n                case 1118:\n                    message.ceil_param = nnabla.CeilParameter.decode(reader, reader.uint32());\n                    break;\n                case 1119:\n                    message.floor_param = nnabla.FloorParameter.decode(reader, reader.uint32());\n                    break;\n                case 1133:\n                    message.concatenate_param = nnabla.ConcatenateParameter.decode(reader, reader.uint32());\n                    break;\n                case 1134:\n                    message.split_param = nnabla.SplitParameter.decode(reader, reader.uint32());\n                    break;\n                case 1135:\n                    message.stack_param = nnabla.StackParameter.decode(reader, reader.uint32());\n                    break;\n                case 1136:\n                    message.slice_param = nnabla.SliceParameter.decode(reader, reader.uint32());\n                    break;\n                case 1137:\n                    message.pad_param = nnabla.PadParameter.decode(reader, reader.uint32());\n                    break;\n                case 1138:\n                    message.transpose_param = nnabla.TransposeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1139:\n                    message.broadcast_param = nnabla.BroadcastParameter.decode(reader, reader.uint32());\n                    break;\n                case 1140:\n                    message.broadcast_to_param = nnabla.BroadcastToParameter.decode(reader, reader.uint32());\n                    break;\n                case 1141:\n                    message.tile_param = nnabla.TileParameter.decode(reader, reader.uint32());\n                    break;\n                case 1142:\n                    message.one_hot_param = nnabla.OneHotParameter.decode(reader, reader.uint32());\n                    break;\n                case 1143:\n                    message.flip_param = nnabla.FlipParameter.decode(reader, reader.uint32());\n                    break;\n                case 1144:\n                    message.shift_param = nnabla.ShiftParameter.decode(reader, reader.uint32());\n                    break;\n                case 1145:\n                    message.sort_param = nnabla.SortParameter.decode(reader, reader.uint32());\n                    break;\n                case 1146:\n                    message.reshape_param = nnabla.ReshapeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1147:\n                    message.shape_param = nnabla.ShapeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1150:\n                    message.trilu_param = nnabla.TriluParameter.decode(reader, reader.uint32());\n                    break;\n                case 1151:\n                    message.meshgrid_param = nnabla.MeshgridParameter.decode(reader, reader.uint32());\n                    break;\n                case 1155:\n                    message.batch_cholesky_param = nnabla.BatchCholeskyParameter.decode(reader, reader.uint32());\n                    break;\n                case 1157:\n                    message.gather_param = nnabla.GatherParameter.decode(reader, reader.uint32());\n                    break;\n                case 1160:\n                    message.scatter_nd_param = nnabla.ScatterNdParameter.decode(reader, reader.uint32());\n                    break;\n                case 1161:\n                    message.scatter_add_param = nnabla.ScatterAddParameter.decode(reader, reader.uint32());\n                    break;\n                case 1163:\n                    message.bool_fill_param = nnabla.BoolFillParameter.decode(reader, reader.uint32());\n                    break;\n                case 1164:\n                    message.pack_padded_sequence_param = nnabla.PackPaddedSequenceParameter.decode(reader, reader.uint32());\n                    break;\n                case 1165:\n                    message.pad_packed_sequence_param = nnabla.PadPackedSequenceParameter.decode(reader, reader.uint32());\n                    break;\n                case 1167:\n                    message.interpolate_param = nnabla.InterpolateParameter.decode(reader, reader.uint32());\n                    break;\n                case 1168:\n                    message.onnx_resize_param = nnabla.ONNXResizeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1169:\n                    message.fft_param = nnabla.FFTParameter.decode(reader, reader.uint32());\n                    break;\n                case 1170:\n                    message.ifft_param = nnabla.IFFTParameter.decode(reader, reader.uint32());\n                    break;\n                case 1171:\n                    message.stft_param = nnabla.STFTParameter.decode(reader, reader.uint32());\n                    break;\n                case 1172:\n                    message.istft_param = nnabla.ISTFTParameter.decode(reader, reader.uint32());\n                    break;\n                case 1173:\n                    message.dropout_param = nnabla.DropoutParameter.decode(reader, reader.uint32());\n                    break;\n                case 1174:\n                    message.top_k_data_param = nnabla.TopKDataParameter.decode(reader, reader.uint32());\n                    break;\n                case 1175:\n                    message.top_k_grad_param = nnabla.TopKGradParameter.decode(reader, reader.uint32());\n                    break;\n                case 1176:\n                    message.rand_param = nnabla.RandParameter.decode(reader, reader.uint32());\n                    break;\n                case 1177:\n                    message.randint_param = nnabla.RandintParameter.decode(reader, reader.uint32());\n                    break;\n                case 1178:\n                    message.randn_param = nnabla.RandnParameter.decode(reader, reader.uint32());\n                    break;\n                case 1179:\n                    message.rand_binomial_param = nnabla.RandBinomialParameter.decode(reader, reader.uint32());\n                    break;\n                case 1180:\n                    message.rand_beta_param = nnabla.RandBetaParameter.decode(reader, reader.uint32());\n                    break;\n                case 1181:\n                    message.rand_gamma_param = nnabla.RandGammaParameter.decode(reader, reader.uint32());\n                    break;\n                case 1182:\n                    message.random_choice_param = nnabla.RandomChoiceParameter.decode(reader, reader.uint32());\n                    break;\n                case 1183:\n                    message.random_crop_param = nnabla.RandomCropParameter.decode(reader, reader.uint32());\n                    break;\n                case 1184:\n                    message.random_flip_param = nnabla.RandomFlipParameter.decode(reader, reader.uint32());\n                    break;\n                case 1185:\n                    message.random_shift_param = nnabla.RandomShiftParameter.decode(reader, reader.uint32());\n                    break;\n                case 1186:\n                    message.random_erase_param = nnabla.RandomEraseParameter.decode(reader, reader.uint32());\n                    break;\n                case 1187:\n                    message.image_augmentation_param = nnabla.ImageAugmentationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1190:\n                    message.softmax_cross_entropy_param = nnabla.SoftmaxCrossEntropyParameter.decode(reader, reader.uint32());\n                    break;\n                case 1191:\n                    message.categorical_cross_entropy_param = nnabla.CategoricalCrossEntropyParameter.decode(reader, reader.uint32());\n                    break;\n                case 1194:\n                    message.huber_loss_param = nnabla.HuberLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 1195:\n                    message.epsilon_insensitive_loss_param = nnabla.EpsilonInsensitiveLossParameter.decode(reader, reader.uint32());\n                    break;\n                case 1196:\n                    message.kl_multinomial_param = nnabla.KLMultinomialParameter.decode(reader, reader.uint32());\n                    break;\n                case 1197:\n                    message.affine_grid_param = nnabla.AffineGridParameter.decode(reader, reader.uint32());\n                    break;\n                case 1198:\n                    message.warp_by_grid_param = nnabla.WarpByGridParameter.decode(reader, reader.uint32());\n                    break;\n                case 1202:\n                    message.binary_connect_affine_param = nnabla.BinaryConnectAffineParameter.decode(reader, reader.uint32());\n                    break;\n                case 1203:\n                    message.binary_connect_convolution_param = nnabla.BinaryConnectConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1204:\n                    message.binary_weight_affine_param = nnabla.BinaryWeightAffineParameter.decode(reader, reader.uint32());\n                    break;\n                case 1205:\n                    message.binary_weight_convolution_param = nnabla.BinaryWeightConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1206:\n                    message.inq_affine_param = nnabla.INQAffineParameter.decode(reader, reader.uint32());\n                    break;\n                case 1207:\n                    message.inq_convolution_param = nnabla.INQConvolutionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1208:\n                    message.fixed_point_quantize_param = nnabla.FixedPointQuantizeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1209:\n                    message.min_max_quantize_param = nnabla.MinMaxQuantizeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1210:\n                    message.pow2_quantize_param = nnabla.Pow2QuantizeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1211:\n                    message.prune_param = nnabla.PruneParameter.decode(reader, reader.uint32());\n                    break;\n                case 1212:\n                    message.quantize_linear_param = nnabla.QuantizeLinearParameter.decode(reader, reader.uint32());\n                    break;\n                case 1214:\n                    message.top_n_error_param = nnabla.TopNErrorParameter.decode(reader, reader.uint32());\n                    break;\n                case 1216:\n                    message.confusion_matrix_param = nnabla.ConfusionMatrixParameter.decode(reader, reader.uint32());\n                    break;\n                case 1217:\n                    message.vat_noise_param = nnabla.VATNoiseParameter.decode(reader, reader.uint32());\n                    break;\n                case 1219:\n                    message.sink_param = nnabla.SinkParameter.decode(reader, reader.uint32());\n                    break;\n                case 1220:\n                    message.nms_detection2d_param = nnabla.NmsDetection2dParameter.decode(reader, reader.uint32());\n                    break;\n                case 1221:\n                    message.onnx_non_max_suppression_param = nnabla.ONNXNonMaxSuppressionParameter.decode(reader, reader.uint32());\n                    break;\n                case 1222:\n                    message.max_pooling_backward_param = nnabla.MaxPoolingBackwardParameter.decode(reader, reader.uint32());\n                    break;\n                case 1223:\n                    message.patch_correlation_param = nnabla.PatchCorrelationParameter.decode(reader, reader.uint32());\n                    break;\n                case 1224:\n                    message.unique_param = nnabla.UniqueParameter.decode(reader, reader.uint32());\n                    break;\n                case 1225:\n                    message.eye_like_param = nnabla.EyeLikeParameter.decode(reader, reader.uint32());\n                    break;\n                case 1226:\n                    message.mod2_param = nnabla.Mod2Parameter.decode(reader, reader.uint32());\n                    break;\n                case 1227:\n                    message.bit_shift_param = nnabla.BitShiftParameter.decode(reader, reader.uint32());\n                    break;\n                case 1228:\n                    message.einsum_param = nnabla.EinsumParameter.decode(reader, reader.uint32());\n                    break;\n                case 100:\n                    message.repeat_param = nnabla.RepeatParameter.decode(reader, reader.uint32());\n                    break;\n                case 101:\n                    message.recurrent_param = nnabla.RecurrentParameter.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Function();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"repeat_id\":\n                    reader.array(message.repeat_id, () => reader.string());\n                    break;\n                case \"context\":\n                    message.context = nnabla.Context.decodeText(reader);\n                    break;\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                case \"affine_param\":\n                    message.affine_param = nnabla.AffineParameter.decodeText(reader);\n                    break;\n                case \"rnn_param\":\n                    message.rnn_param = nnabla.RNNParameter.decodeText(reader);\n                    break;\n                case \"lstm_param\":\n                    message.lstm_param = nnabla.LSTMParameter.decodeText(reader);\n                    break;\n                case \"gru_param\":\n                    message.gru_param = nnabla.GRUParameter.decodeText(reader);\n                    break;\n                case \"convolution_param\":\n                    message.convolution_param = nnabla.ConvolutionParameter.decodeText(reader);\n                    break;\n                case \"fused_convolution_param\":\n                    message.fused_convolution_param = nnabla.FusedConvolutionParameter.decodeText(reader);\n                    break;\n                case \"depthwise_convolution_param\":\n                    message.depthwise_convolution_param = nnabla.DepthwiseConvolutionParameter.decodeText(reader);\n                    break;\n                case \"deconvolution_param\":\n                    message.deconvolution_param = nnabla.DeconvolutionParameter.decodeText(reader);\n                    break;\n                case \"depthwise_deconvolution_param\":\n                    message.depthwise_deconvolution_param = nnabla.DepthwiseDeconvolutionParameter.decodeText(reader);\n                    break;\n                case \"deformable_convolution_param\":\n                    message.deformable_convolution_param = nnabla.DeformableConvolutionParameter.decodeText(reader);\n                    break;\n                case \"max_pooling_param\":\n                    message.max_pooling_param = nnabla.MaxPoolingParameter.decodeText(reader);\n                    break;\n                case \"average_pooling_param\":\n                    message.average_pooling_param = nnabla.AveragePoolingParameter.decodeText(reader);\n                    break;\n                case \"sum_pooling_param\":\n                    message.sum_pooling_param = nnabla.SumPoolingParameter.decodeText(reader);\n                    break;\n                case \"unpooling_param\":\n                    message.unpooling_param = nnabla.UnpoolingParameter.decodeText(reader);\n                    break;\n                case \"roi_align_param\":\n                    message.roi_align_param = nnabla.RoiAlignParameter.decodeText(reader);\n                    break;\n                case \"relu_param\":\n                    message.relu_param = nnabla.ReLUParameter.decodeText(reader);\n                    break;\n                case \"leaky_relu_param\":\n                    message.leaky_relu_param = nnabla.LeakyReLUParameter.decodeText(reader);\n                    break;\n                case \"softmax_param\":\n                    message.softmax_param = nnabla.SoftmaxParameter.decodeText(reader);\n                    break;\n                case \"log_softmax_param\":\n                    message.log_softmax_param = nnabla.LogSoftmaxParameter.decodeText(reader);\n                    break;\n                case \"elu_param\":\n                    message.elu_param = nnabla.ELUParameter.decodeText(reader);\n                    break;\n                case \"selu_param\":\n                    message.selu_param = nnabla.SELUParameter.decodeText(reader);\n                    break;\n                case \"crelu_param\":\n                    message.crelu_param = nnabla.CReLUParameter.decodeText(reader);\n                    break;\n                case \"celu_param\":\n                    message.celu_param = nnabla.CELUParameter.decodeText(reader);\n                    break;\n                case \"prelu_param\":\n                    message.prelu_param = nnabla.PReLUParameter.decodeText(reader);\n                    break;\n                case \"softplus_param\":\n                    message.softplus_param = nnabla.SoftPlusParameter.decodeText(reader);\n                    break;\n                case \"fused_batch_normalization_param\":\n                    message.fused_batch_normalization_param = nnabla.FusedBatchNormalizationParameter.decodeText(reader);\n                    break;\n                case \"batch_normalization_param\":\n                    message.batch_normalization_param = nnabla.BatchNormalizationParameter.decodeText(reader);\n                    break;\n                case \"group_normalization_param\":\n                    message.group_normalization_param = nnabla.GroupNormalizationParameter.decodeText(reader);\n                    break;\n                case \"instance_normalization_param\":\n                    message.instance_normalization_param = nnabla.InstanceNormalizationParameter.decodeText(reader);\n                    break;\n                case \"layer_normalization_param\":\n                    message.layer_normalization_param = nnabla.LayerNormalizationParameter.decodeText(reader);\n                    break;\n                case \"norm_normalization_param\":\n                    message.norm_normalization_param = nnabla.NormNormalizationParameter.decodeText(reader);\n                    break;\n                case \"sync_batch_normalization_param\":\n                    message.sync_batch_normalization_param = nnabla.SyncBatchNormalizationParameter.decodeText(reader);\n                    break;\n                case \"tensor_normalization_param\":\n                    message.tensor_normalization_param = nnabla.TensorNormalizationParameter.decodeText(reader);\n                    break;\n                case \"weight_normalization_param\":\n                    message.weight_normalization_param = nnabla.WeightNormalizationParameter.decodeText(reader);\n                    break;\n                case \"weight_standardization_param\":\n                    message.weight_standardization_param = nnabla.WeightStandardizationParameter.decodeText(reader);\n                    break;\n                case \"spectral_norm_param\":\n                    message.spectral_norm_param = nnabla.SpectralNormParameter.decodeText(reader);\n                    break;\n                case \"mean_subtraction_param\":\n                    message.mean_subtraction_param = nnabla.MeanSubtractionParameter.decodeText(reader);\n                    break;\n                case \"clip_grad_by_norm_param\":\n                    message.clip_grad_by_norm_param = nnabla.ClipGradByNormParameter.decodeText(reader);\n                    break;\n                case \"sum_param\":\n                    message.sum_param = nnabla.SumParameter.decodeText(reader);\n                    break;\n                case \"cumsum_param\":\n                    message.cumsum_param = nnabla.CumSumParameter.decodeText(reader);\n                    break;\n                case \"mean_param\":\n                    message.mean_param = nnabla.MeanParameter.decodeText(reader);\n                    break;\n                case \"max_param\":\n                    message.max_param = nnabla.MaxParameter.decodeText(reader);\n                    break;\n                case \"min_param\":\n                    message.min_param = nnabla.MinParameter.decodeText(reader);\n                    break;\n                case \"norm_param\":\n                    message.norm_param = nnabla.NormParameter.decodeText(reader);\n                    break;\n                case \"prod_param\":\n                    message.prod_param = nnabla.ProdParameter.decodeText(reader);\n                    break;\n                case \"cumprod_param\":\n                    message.cumprod_param = nnabla.CumProdParameter.decodeText(reader);\n                    break;\n                case \"add2_param\":\n                    message.add2_param = nnabla.Add2Parameter.decodeText(reader);\n                    break;\n                case \"bc_add2_param\":\n                    message.bc_add2_param = nnabla.BcAdd2Parameter.decodeText(reader);\n                    break;\n                case \"sub2_param\":\n                    message.sub2_param = nnabla.Sub2Parameter.decodeText(reader);\n                    break;\n                case \"mul2_param\":\n                    message.mul2_param = nnabla.Mul2Parameter.decodeText(reader);\n                    break;\n                case \"div2_param\":\n                    message.div2_param = nnabla.Div2Parameter.decodeText(reader);\n                    break;\n                case \"pow2_param\":\n                    message.pow2_param = nnabla.Pow2Parameter.decodeText(reader);\n                    break;\n                case \"add_scalar_param\":\n                    message.add_scalar_param = nnabla.AddScalarParameter.decodeText(reader);\n                    break;\n                case \"mul_scalar_param\":\n                    message.mul_scalar_param = nnabla.MulScalarParameter.decodeText(reader);\n                    break;\n                case \"pow_scalar_param\":\n                    message.pow_scalar_param = nnabla.PowScalarParameter.decodeText(reader);\n                    break;\n                case \"r_sub_scalar_param\":\n                    message.r_sub_scalar_param = nnabla.RSubScalarParameter.decodeText(reader);\n                    break;\n                case \"r_div_scalar_param\":\n                    message.r_div_scalar_param = nnabla.RDivScalarParameter.decodeText(reader);\n                    break;\n                case \"r_pow_scalar_param\":\n                    message.r_pow_scalar_param = nnabla.RPowScalarParameter.decodeText(reader);\n                    break;\n                case \"sign_param\":\n                    message.sign_param = nnabla.SignParameter.decodeText(reader);\n                    break;\n                case \"minimum_scalar_param\":\n                    message.minimum_scalar_param = nnabla.MinimumScalarParameter.decodeText(reader);\n                    break;\n                case \"maximum_scalar_param\":\n                    message.maximum_scalar_param = nnabla.MaximumScalarParameter.decodeText(reader);\n                    break;\n                case \"searchsorted_param\":\n                    message.searchsorted_param = nnabla.SearchSortedParameter.decodeText(reader);\n                    break;\n                case \"logical_and_scalar_param\":\n                    message.logical_and_scalar_param = nnabla.LogicalAndScalarParameter.decodeText(reader);\n                    break;\n                case \"logical_or_scalar_param\":\n                    message.logical_or_scalar_param = nnabla.LogicalOrScalarParameter.decodeText(reader);\n                    break;\n                case \"logical_xor_scalar_param\":\n                    message.logical_xor_scalar_param = nnabla.LogicalXorScalarParameter.decodeText(reader);\n                    break;\n                case \"equal_scalar_param\":\n                    message.equal_scalar_param = nnabla.EqualScalarParameter.decodeText(reader);\n                    break;\n                case \"not_equal_scalar_param\":\n                    message.not_equal_scalar_param = nnabla.NotEqualScalarParameter.decodeText(reader);\n                    break;\n                case \"greater_equal_scalar_param\":\n                    message.greater_equal_scalar_param = nnabla.GreaterEqualScalarParameter.decodeText(reader);\n                    break;\n                case \"greater_scalar_param\":\n                    message.greater_scalar_param = nnabla.GreaterScalarParameter.decodeText(reader);\n                    break;\n                case \"less_equal_scalar_param\":\n                    message.less_equal_scalar_param = nnabla.LessEqualScalarParameter.decodeText(reader);\n                    break;\n                case \"less_scalar_param\":\n                    message.less_scalar_param = nnabla.LessScalarParameter.decodeText(reader);\n                    break;\n                case \"reset_nan_param\":\n                    message.reset_nan_param = nnabla.ResetNaNParameter.decodeText(reader);\n                    break;\n                case \"reset_inf_param\":\n                    message.reset_inf_param = nnabla.ResetInfParameter.decodeText(reader);\n                    break;\n                case \"constant_param\":\n                    message.constant_param = nnabla.ConstantParameter.decodeText(reader);\n                    break;\n                case \"arange_param\":\n                    message.arange_param = nnabla.ArangeParameter.decodeText(reader);\n                    break;\n                case \"linspace_param\":\n                    message.linspace_param = nnabla.LinspaceParameter.decodeText(reader);\n                    break;\n                case \"batch_matmul_param\":\n                    message.batch_matmul_param = nnabla.BatchMatmulParameter.decodeText(reader);\n                    break;\n                case \"round_param\":\n                    message.round_param = nnabla.RoundParameter.decodeText(reader);\n                    break;\n                case \"ceil_param\":\n                    message.ceil_param = nnabla.CeilParameter.decodeText(reader);\n                    break;\n                case \"floor_param\":\n                    message.floor_param = nnabla.FloorParameter.decodeText(reader);\n                    break;\n                case \"concatenate_param\":\n                    message.concatenate_param = nnabla.ConcatenateParameter.decodeText(reader);\n                    break;\n                case \"split_param\":\n                    message.split_param = nnabla.SplitParameter.decodeText(reader);\n                    break;\n                case \"stack_param\":\n                    message.stack_param = nnabla.StackParameter.decodeText(reader);\n                    break;\n                case \"slice_param\":\n                    message.slice_param = nnabla.SliceParameter.decodeText(reader);\n                    break;\n                case \"pad_param\":\n                    message.pad_param = nnabla.PadParameter.decodeText(reader);\n                    break;\n                case \"transpose_param\":\n                    message.transpose_param = nnabla.TransposeParameter.decodeText(reader);\n                    break;\n                case \"broadcast_param\":\n                    message.broadcast_param = nnabla.BroadcastParameter.decodeText(reader);\n                    break;\n                case \"broadcast_to_param\":\n                    message.broadcast_to_param = nnabla.BroadcastToParameter.decodeText(reader);\n                    break;\n                case \"tile_param\":\n                    message.tile_param = nnabla.TileParameter.decodeText(reader);\n                    break;\n                case \"one_hot_param\":\n                    message.one_hot_param = nnabla.OneHotParameter.decodeText(reader);\n                    break;\n                case \"flip_param\":\n                    message.flip_param = nnabla.FlipParameter.decodeText(reader);\n                    break;\n                case \"shift_param\":\n                    message.shift_param = nnabla.ShiftParameter.decodeText(reader);\n                    break;\n                case \"sort_param\":\n                    message.sort_param = nnabla.SortParameter.decodeText(reader);\n                    break;\n                case \"reshape_param\":\n                    message.reshape_param = nnabla.ReshapeParameter.decodeText(reader);\n                    break;\n                case \"shape_param\":\n                    message.shape_param = nnabla.ShapeParameter.decodeText(reader);\n                    break;\n                case \"trilu_param\":\n                    message.trilu_param = nnabla.TriluParameter.decodeText(reader);\n                    break;\n                case \"meshgrid_param\":\n                    message.meshgrid_param = nnabla.MeshgridParameter.decodeText(reader);\n                    break;\n                case \"batch_cholesky_param\":\n                    message.batch_cholesky_param = nnabla.BatchCholeskyParameter.decodeText(reader);\n                    break;\n                case \"gather_param\":\n                    message.gather_param = nnabla.GatherParameter.decodeText(reader);\n                    break;\n                case \"scatter_nd_param\":\n                    message.scatter_nd_param = nnabla.ScatterNdParameter.decodeText(reader);\n                    break;\n                case \"scatter_add_param\":\n                    message.scatter_add_param = nnabla.ScatterAddParameter.decodeText(reader);\n                    break;\n                case \"bool_fill_param\":\n                    message.bool_fill_param = nnabla.BoolFillParameter.decodeText(reader);\n                    break;\n                case \"pack_padded_sequence_param\":\n                    message.pack_padded_sequence_param = nnabla.PackPaddedSequenceParameter.decodeText(reader);\n                    break;\n                case \"pad_packed_sequence_param\":\n                    message.pad_packed_sequence_param = nnabla.PadPackedSequenceParameter.decodeText(reader);\n                    break;\n                case \"interpolate_param\":\n                    message.interpolate_param = nnabla.InterpolateParameter.decodeText(reader);\n                    break;\n                case \"onnx_resize_param\":\n                    message.onnx_resize_param = nnabla.ONNXResizeParameter.decodeText(reader);\n                    break;\n                case \"fft_param\":\n                    message.fft_param = nnabla.FFTParameter.decodeText(reader);\n                    break;\n                case \"ifft_param\":\n                    message.ifft_param = nnabla.IFFTParameter.decodeText(reader);\n                    break;\n                case \"stft_param\":\n                    message.stft_param = nnabla.STFTParameter.decodeText(reader);\n                    break;\n                case \"istft_param\":\n                    message.istft_param = nnabla.ISTFTParameter.decodeText(reader);\n                    break;\n                case \"dropout_param\":\n                    message.dropout_param = nnabla.DropoutParameter.decodeText(reader);\n                    break;\n                case \"top_k_data_param\":\n                    message.top_k_data_param = nnabla.TopKDataParameter.decodeText(reader);\n                    break;\n                case \"top_k_grad_param\":\n                    message.top_k_grad_param = nnabla.TopKGradParameter.decodeText(reader);\n                    break;\n                case \"rand_param\":\n                    message.rand_param = nnabla.RandParameter.decodeText(reader);\n                    break;\n                case \"randint_param\":\n                    message.randint_param = nnabla.RandintParameter.decodeText(reader);\n                    break;\n                case \"randn_param\":\n                    message.randn_param = nnabla.RandnParameter.decodeText(reader);\n                    break;\n                case \"rand_binomial_param\":\n                    message.rand_binomial_param = nnabla.RandBinomialParameter.decodeText(reader);\n                    break;\n                case \"rand_beta_param\":\n                    message.rand_beta_param = nnabla.RandBetaParameter.decodeText(reader);\n                    break;\n                case \"rand_gamma_param\":\n                    message.rand_gamma_param = nnabla.RandGammaParameter.decodeText(reader);\n                    break;\n                case \"random_choice_param\":\n                    message.random_choice_param = nnabla.RandomChoiceParameter.decodeText(reader);\n                    break;\n                case \"random_crop_param\":\n                    message.random_crop_param = nnabla.RandomCropParameter.decodeText(reader);\n                    break;\n                case \"random_flip_param\":\n                    message.random_flip_param = nnabla.RandomFlipParameter.decodeText(reader);\n                    break;\n                case \"random_shift_param\":\n                    message.random_shift_param = nnabla.RandomShiftParameter.decodeText(reader);\n                    break;\n                case \"random_erase_param\":\n                    message.random_erase_param = nnabla.RandomEraseParameter.decodeText(reader);\n                    break;\n                case \"image_augmentation_param\":\n                    message.image_augmentation_param = nnabla.ImageAugmentationParameter.decodeText(reader);\n                    break;\n                case \"softmax_cross_entropy_param\":\n                    message.softmax_cross_entropy_param = nnabla.SoftmaxCrossEntropyParameter.decodeText(reader);\n                    break;\n                case \"categorical_cross_entropy_param\":\n                    message.categorical_cross_entropy_param = nnabla.CategoricalCrossEntropyParameter.decodeText(reader);\n                    break;\n                case \"huber_loss_param\":\n                    message.huber_loss_param = nnabla.HuberLossParameter.decodeText(reader);\n                    break;\n                case \"epsilon_insensitive_loss_param\":\n                    message.epsilon_insensitive_loss_param = nnabla.EpsilonInsensitiveLossParameter.decodeText(reader);\n                    break;\n                case \"kl_multinomial_param\":\n                    message.kl_multinomial_param = nnabla.KLMultinomialParameter.decodeText(reader);\n                    break;\n                case \"affine_grid_param\":\n                    message.affine_grid_param = nnabla.AffineGridParameter.decodeText(reader);\n                    break;\n                case \"warp_by_grid_param\":\n                    message.warp_by_grid_param = nnabla.WarpByGridParameter.decodeText(reader);\n                    break;\n                case \"binary_connect_affine_param\":\n                    message.binary_connect_affine_param = nnabla.BinaryConnectAffineParameter.decodeText(reader);\n                    break;\n                case \"binary_connect_convolution_param\":\n                    message.binary_connect_convolution_param = nnabla.BinaryConnectConvolutionParameter.decodeText(reader);\n                    break;\n                case \"binary_weight_affine_param\":\n                    message.binary_weight_affine_param = nnabla.BinaryWeightAffineParameter.decodeText(reader);\n                    break;\n                case \"binary_weight_convolution_param\":\n                    message.binary_weight_convolution_param = nnabla.BinaryWeightConvolutionParameter.decodeText(reader);\n                    break;\n                case \"inq_affine_param\":\n                    message.inq_affine_param = nnabla.INQAffineParameter.decodeText(reader);\n                    break;\n                case \"inq_convolution_param\":\n                    message.inq_convolution_param = nnabla.INQConvolutionParameter.decodeText(reader);\n                    break;\n                case \"fixed_point_quantize_param\":\n                    message.fixed_point_quantize_param = nnabla.FixedPointQuantizeParameter.decodeText(reader);\n                    break;\n                case \"min_max_quantize_param\":\n                    message.min_max_quantize_param = nnabla.MinMaxQuantizeParameter.decodeText(reader);\n                    break;\n                case \"pow2_quantize_param\":\n                    message.pow2_quantize_param = nnabla.Pow2QuantizeParameter.decodeText(reader);\n                    break;\n                case \"prune_param\":\n                    message.prune_param = nnabla.PruneParameter.decodeText(reader);\n                    break;\n                case \"quantize_linear_param\":\n                    message.quantize_linear_param = nnabla.QuantizeLinearParameter.decodeText(reader);\n                    break;\n                case \"top_n_error_param\":\n                    message.top_n_error_param = nnabla.TopNErrorParameter.decodeText(reader);\n                    break;\n                case \"confusion_matrix_param\":\n                    message.confusion_matrix_param = nnabla.ConfusionMatrixParameter.decodeText(reader);\n                    break;\n                case \"vat_noise_param\":\n                    message.vat_noise_param = nnabla.VATNoiseParameter.decodeText(reader);\n                    break;\n                case \"sink_param\":\n                    message.sink_param = nnabla.SinkParameter.decodeText(reader);\n                    break;\n                case \"nms_detection2d_param\":\n                    message.nms_detection2d_param = nnabla.NmsDetection2dParameter.decodeText(reader);\n                    break;\n                case \"onnx_non_max_suppression_param\":\n                    message.onnx_non_max_suppression_param = nnabla.ONNXNonMaxSuppressionParameter.decodeText(reader);\n                    break;\n                case \"max_pooling_backward_param\":\n                    message.max_pooling_backward_param = nnabla.MaxPoolingBackwardParameter.decodeText(reader);\n                    break;\n                case \"patch_correlation_param\":\n                    message.patch_correlation_param = nnabla.PatchCorrelationParameter.decodeText(reader);\n                    break;\n                case \"unique_param\":\n                    message.unique_param = nnabla.UniqueParameter.decodeText(reader);\n                    break;\n                case \"eye_like_param\":\n                    message.eye_like_param = nnabla.EyeLikeParameter.decodeText(reader);\n                    break;\n                case \"mod2_param\":\n                    message.mod2_param = nnabla.Mod2Parameter.decodeText(reader);\n                    break;\n                case \"bit_shift_param\":\n                    message.bit_shift_param = nnabla.BitShiftParameter.decodeText(reader);\n                    break;\n                case \"einsum_param\":\n                    message.einsum_param = nnabla.EinsumParameter.decodeText(reader);\n                    break;\n                case \"repeat_param\":\n                    message.repeat_param = nnabla.RepeatParameter.decodeText(reader);\n                    break;\n                case \"recurrent_param\":\n                    message.recurrent_param = nnabla.RecurrentParameter.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Function.prototype.name = \"\";\nnnabla.Function.prototype.type = \"\";\nnnabla.Function.prototype.context = null;\nnnabla.Function.prototype.repeat_param = null;\nnnabla.Function.prototype.recurrent_param = null;\n\nnnabla.AffineParameter = class AffineParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AffineParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AffineParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AffineParameter.prototype.base_axis = 0n;\n\nnnabla.RNNParameter = class RNNParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RNNParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_layers = reader.int64();\n                    break;\n                case 2:\n                    message.nonlinearity = reader.string();\n                    break;\n                case 3:\n                    message.dropout = reader.float();\n                    break;\n                case 4:\n                    message.bidirectional = reader.bool();\n                    break;\n                case 5:\n                    message.training = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RNNParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_layers\":\n                    message.num_layers = reader.int64();\n                    break;\n                case \"nonlinearity\":\n                    message.nonlinearity = reader.string();\n                    break;\n                case \"dropout\":\n                    message.dropout = reader.float();\n                    break;\n                case \"bidirectional\":\n                    message.bidirectional = reader.bool();\n                    break;\n                case \"training\":\n                    message.training = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RNNParameter.prototype.num_layers = 0n;\nnnabla.RNNParameter.prototype.nonlinearity = \"\";\nnnabla.RNNParameter.prototype.dropout = 0;\nnnabla.RNNParameter.prototype.bidirectional = false;\nnnabla.RNNParameter.prototype.training = false;\n\nnnabla.LSTMParameter = class LSTMParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LSTMParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_layers = reader.int64();\n                    break;\n                case 2:\n                    message.dropout = reader.float();\n                    break;\n                case 3:\n                    message.bidirectional = reader.bool();\n                    break;\n                case 4:\n                    message.training = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LSTMParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_layers\":\n                    message.num_layers = reader.int64();\n                    break;\n                case \"dropout\":\n                    message.dropout = reader.float();\n                    break;\n                case \"bidirectional\":\n                    message.bidirectional = reader.bool();\n                    break;\n                case \"training\":\n                    message.training = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LSTMParameter.prototype.num_layers = 0n;\nnnabla.LSTMParameter.prototype.dropout = 0;\nnnabla.LSTMParameter.prototype.bidirectional = false;\nnnabla.LSTMParameter.prototype.training = false;\n\nnnabla.GRUParameter = class GRUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.GRUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_layers = reader.int64();\n                    break;\n                case 2:\n                    message.dropout = reader.float();\n                    break;\n                case 3:\n                    message.bidirectional = reader.bool();\n                    break;\n                case 4:\n                    message.training = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GRUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_layers\":\n                    message.num_layers = reader.int64();\n                    break;\n                case \"dropout\":\n                    message.dropout = reader.float();\n                    break;\n                case \"bidirectional\":\n                    message.bidirectional = reader.bool();\n                    break;\n                case \"training\":\n                    message.training = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GRUParameter.prototype.num_layers = 0n;\nnnabla.GRUParameter.prototype.dropout = 0;\nnnabla.GRUParameter.prototype.bidirectional = false;\nnnabla.GRUParameter.prototype.training = false;\n\nnnabla.ConvolutionParameter = class ConvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ConvolutionParameter.prototype.base_axis = 0n;\nnnabla.ConvolutionParameter.prototype.pad = null;\nnnabla.ConvolutionParameter.prototype.stride = null;\nnnabla.ConvolutionParameter.prototype.dilation = null;\nnnabla.ConvolutionParameter.prototype.group = 0n;\nnnabla.ConvolutionParameter.prototype.channel_last = false;\n\nnnabla.FusedConvolutionParameter = class FusedConvolutionParameter {\n\n    constructor() {\n        this.nonlinearity_args = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.FusedConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.channel_last = reader.bool();\n                    break;\n                case 7:\n                    message.decay_rate = reader.float();\n                    break;\n                case 8:\n                    message.eps = reader.float();\n                    break;\n                case 9:\n                    message.batch_stat = reader.bool();\n                    break;\n                case 10:\n                    message.nonlinearity = reader.string();\n                    break;\n                case 11:\n                    message.nonlinearity_args = reader.floats(message.nonlinearity_args, tag);\n                    break;\n                case 12:\n                    message.pad_mode = reader.string();\n                    break;\n                case 13:\n                    message.constant_value = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.FusedConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                case \"decay_rate\":\n                    message.decay_rate = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"batch_stat\":\n                    message.batch_stat = reader.bool();\n                    break;\n                case \"nonlinearity\":\n                    message.nonlinearity = reader.string();\n                    break;\n                case \"nonlinearity_args\":\n                    reader.array(message.nonlinearity_args, () => reader.float());\n                    break;\n                case \"pad_mode\":\n                    message.pad_mode = reader.string();\n                    break;\n                case \"constant_value\":\n                    message.constant_value = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.FusedConvolutionParameter.prototype.base_axis = 0n;\nnnabla.FusedConvolutionParameter.prototype.pad = null;\nnnabla.FusedConvolutionParameter.prototype.stride = null;\nnnabla.FusedConvolutionParameter.prototype.dilation = null;\nnnabla.FusedConvolutionParameter.prototype.group = 0n;\nnnabla.FusedConvolutionParameter.prototype.channel_last = false;\nnnabla.FusedConvolutionParameter.prototype.decay_rate = 0;\nnnabla.FusedConvolutionParameter.prototype.eps = 0;\nnnabla.FusedConvolutionParameter.prototype.batch_stat = false;\nnnabla.FusedConvolutionParameter.prototype.nonlinearity = \"\";\nnnabla.FusedConvolutionParameter.prototype.pad_mode = \"\";\nnnabla.FusedConvolutionParameter.prototype.constant_value = 0;\n\nnnabla.DepthwiseConvolutionParameter = class DepthwiseConvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.DepthwiseConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.multiplier = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.DepthwiseConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"multiplier\":\n                    message.multiplier = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.DepthwiseConvolutionParameter.prototype.base_axis = 0n;\nnnabla.DepthwiseConvolutionParameter.prototype.pad = null;\nnnabla.DepthwiseConvolutionParameter.prototype.stride = null;\nnnabla.DepthwiseConvolutionParameter.prototype.dilation = null;\nnnabla.DepthwiseConvolutionParameter.prototype.multiplier = 0n;\n\nnnabla.DeconvolutionParameter = class DeconvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.DeconvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.channel_last = reader.bool();\n                    break;\n                case 7:\n                    message.output_padding = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.DeconvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                case \"output_padding\":\n                    message.output_padding = nnabla.Shape.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.DeconvolutionParameter.prototype.base_axis = 0n;\nnnabla.DeconvolutionParameter.prototype.pad = null;\nnnabla.DeconvolutionParameter.prototype.stride = null;\nnnabla.DeconvolutionParameter.prototype.dilation = null;\nnnabla.DeconvolutionParameter.prototype.group = 0n;\nnnabla.DeconvolutionParameter.prototype.channel_last = false;\nnnabla.DeconvolutionParameter.prototype.output_padding = null;\n\nnnabla.DepthwiseDeconvolutionParameter = class DepthwiseDeconvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.DepthwiseDeconvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.divisor = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.DepthwiseDeconvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"divisor\":\n                    message.divisor = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.DepthwiseDeconvolutionParameter.prototype.base_axis = 0n;\nnnabla.DepthwiseDeconvolutionParameter.prototype.pad = null;\nnnabla.DepthwiseDeconvolutionParameter.prototype.stride = null;\nnnabla.DepthwiseDeconvolutionParameter.prototype.dilation = null;\nnnabla.DepthwiseDeconvolutionParameter.prototype.divisor = 0n;\n\nnnabla.DeformableConvolutionParameter = class DeformableConvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.DeformableConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.deformable_group = reader.int64();\n                    break;\n                case 7:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.DeformableConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"deformable_group\":\n                    message.deformable_group = reader.int64();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.DeformableConvolutionParameter.prototype.base_axis = 0n;\nnnabla.DeformableConvolutionParameter.prototype.pad = null;\nnnabla.DeformableConvolutionParameter.prototype.stride = null;\nnnabla.DeformableConvolutionParameter.prototype.dilation = null;\nnnabla.DeformableConvolutionParameter.prototype.group = 0n;\nnnabla.DeformableConvolutionParameter.prototype.deformable_group = 0n;\nnnabla.DeformableConvolutionParameter.prototype.channel_last = false;\n\nnnabla.MaxPoolingParameter = class MaxPoolingParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MaxPoolingParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.ignore_border = reader.bool();\n                    break;\n                case 4:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MaxPoolingParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"ignore_border\":\n                    message.ignore_border = reader.bool();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MaxPoolingParameter.prototype.kernel = null;\nnnabla.MaxPoolingParameter.prototype.stride = null;\nnnabla.MaxPoolingParameter.prototype.ignore_border = false;\nnnabla.MaxPoolingParameter.prototype.pad = null;\nnnabla.MaxPoolingParameter.prototype.channel_last = false;\n\nnnabla.AveragePoolingParameter = class AveragePoolingParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AveragePoolingParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.ignore_border = reader.bool();\n                    break;\n                case 4:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.channel_last = reader.bool();\n                    break;\n                case 6:\n                    message.including_pad = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AveragePoolingParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"ignore_border\":\n                    message.ignore_border = reader.bool();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                case \"including_pad\":\n                    message.including_pad = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AveragePoolingParameter.prototype.kernel = null;\nnnabla.AveragePoolingParameter.prototype.stride = null;\nnnabla.AveragePoolingParameter.prototype.ignore_border = false;\nnnabla.AveragePoolingParameter.prototype.pad = null;\nnnabla.AveragePoolingParameter.prototype.channel_last = false;\nnnabla.AveragePoolingParameter.prototype.including_pad = false;\n\nnnabla.SumPoolingParameter = class SumPoolingParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SumPoolingParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.ignore_border = reader.bool();\n                    break;\n                case 4:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SumPoolingParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"ignore_border\":\n                    message.ignore_border = reader.bool();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SumPoolingParameter.prototype.kernel = null;\nnnabla.SumPoolingParameter.prototype.stride = null;\nnnabla.SumPoolingParameter.prototype.ignore_border = false;\nnnabla.SumPoolingParameter.prototype.pad = null;\nnnabla.SumPoolingParameter.prototype.channel_last = false;\n\nnnabla.UnpoolingParameter = class UnpoolingParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.UnpoolingParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.UnpoolingParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.UnpoolingParameter.prototype.kernel = null;\nnnabla.UnpoolingParameter.prototype.channel_last = false;\n\nnnabla.RoiAlignParameter = class RoiAlignParameter {\n\n    constructor() {\n        this.spatial_scale = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.RoiAlignParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.output_size = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.spatial_scale = reader.floats(message.spatial_scale, tag);\n                    break;\n                case 3:\n                    message.sampling_ratio = reader.int64();\n                    break;\n                case 4:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RoiAlignParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"output_size\":\n                    message.output_size = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"spatial_scale\":\n                    reader.array(message.spatial_scale, () => reader.float());\n                    break;\n                case \"sampling_ratio\":\n                    message.sampling_ratio = reader.int64();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RoiAlignParameter.prototype.output_size = null;\nnnabla.RoiAlignParameter.prototype.sampling_ratio = 0n;\nnnabla.RoiAlignParameter.prototype.channel_last = false;\n\nnnabla.ReLUParameter = class ReLUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ReLUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ReLUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ReLUParameter.prototype.inplace = false;\n\nnnabla.LeakyReLUParameter = class LeakyReLUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LeakyReLUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LeakyReLUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LeakyReLUParameter.prototype.alpha = 0;\nnnabla.LeakyReLUParameter.prototype.inplace = false;\n\nnnabla.SoftmaxParameter = class SoftmaxParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SoftmaxParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SoftmaxParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SoftmaxParameter.prototype.axis = 0n;\n\nnnabla.LogSoftmaxParameter = class LogSoftmaxParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LogSoftmaxParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LogSoftmaxParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LogSoftmaxParameter.prototype.axis = 0n;\n\nnnabla.ELUParameter = class ELUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ELUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ELUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ELUParameter.prototype.alpha = 0;\n\nnnabla.SELUParameter = class SELUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SELUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.scale = reader.double();\n                    break;\n                case 2:\n                    message.alpha = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SELUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"scale\":\n                    message.scale = reader.double();\n                    break;\n                case \"alpha\":\n                    message.alpha = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SELUParameter.prototype.scale = 0;\nnnabla.SELUParameter.prototype.alpha = 0;\n\nnnabla.CReLUParameter = class CReLUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CReLUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CReLUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CReLUParameter.prototype.axis = 0n;\n\nnnabla.CELUParameter = class CELUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CELUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.double();\n                    break;\n                case 2:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CELUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.double();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CELUParameter.prototype.alpha = 0;\nnnabla.CELUParameter.prototype.axis = 0n;\n\nnnabla.PReLUParameter = class PReLUParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PReLUParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PReLUParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PReLUParameter.prototype.base_axis = 0n;\n\nnnabla.SoftPlusParameter = class SoftPlusParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SoftPlusParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.beta = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SoftPlusParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"beta\":\n                    message.beta = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SoftPlusParameter.prototype.beta = 0;\n\nnnabla.FusedBatchNormalizationParameter = class FusedBatchNormalizationParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.FusedBatchNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.decay_rate = reader.float();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                case 4:\n                    message.batch_stat = reader.bool();\n                    break;\n                case 5:\n                    message.nonlinearity = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.FusedBatchNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"decay_rate\":\n                    message.decay_rate = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"batch_stat\":\n                    message.batch_stat = reader.bool();\n                    break;\n                case \"nonlinearity\":\n                    message.nonlinearity = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.FusedBatchNormalizationParameter.prototype.decay_rate = 0;\nnnabla.FusedBatchNormalizationParameter.prototype.eps = 0;\nnnabla.FusedBatchNormalizationParameter.prototype.batch_stat = false;\nnnabla.FusedBatchNormalizationParameter.prototype.nonlinearity = \"\";\n\nnnabla.BatchNormalizationParameter = class BatchNormalizationParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.BatchNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.decay_rate = reader.float();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                case 4:\n                    message.batch_stat = reader.bool();\n                    break;\n                case 5:\n                    message.no_scale = reader.bool();\n                    break;\n                case 6:\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BatchNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"decay_rate\":\n                    message.decay_rate = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"batch_stat\":\n                    message.batch_stat = reader.bool();\n                    break;\n                case \"no_scale\":\n                    message.no_scale = reader.bool();\n                    break;\n                case \"no_bias\":\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BatchNormalizationParameter.prototype.decay_rate = 0;\nnnabla.BatchNormalizationParameter.prototype.eps = 0;\nnnabla.BatchNormalizationParameter.prototype.batch_stat = false;\nnnabla.BatchNormalizationParameter.prototype.no_scale = false;\nnnabla.BatchNormalizationParameter.prototype.no_bias = false;\n\nnnabla.GroupNormalizationParameter = class GroupNormalizationParameter {\n\n    constructor() {\n        this.batch_axis = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.GroupNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.num_groups = reader.int64();\n                    break;\n                case 2:\n                    message.channel_axis = reader.int64();\n                    break;\n                case 3:\n                    message.batch_axis = reader.array(message.batch_axis, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.eps = reader.float();\n                    break;\n                case 5:\n                    message.no_scale = reader.bool();\n                    break;\n                case 6:\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GroupNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"num_groups\":\n                    message.num_groups = reader.int64();\n                    break;\n                case \"channel_axis\":\n                    message.channel_axis = reader.int64();\n                    break;\n                case \"batch_axis\":\n                    reader.array(message.batch_axis, () => reader.int64());\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"no_scale\":\n                    message.no_scale = reader.bool();\n                    break;\n                case \"no_bias\":\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GroupNormalizationParameter.prototype.num_groups = 0n;\nnnabla.GroupNormalizationParameter.prototype.channel_axis = 0n;\nnnabla.GroupNormalizationParameter.prototype.eps = 0;\nnnabla.GroupNormalizationParameter.prototype.no_scale = false;\nnnabla.GroupNormalizationParameter.prototype.no_bias = false;\n\nnnabla.InstanceNormalizationParameter = class InstanceNormalizationParameter {\n\n    constructor() {\n        this.batch_axis = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.InstanceNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.channel_axis = reader.int64();\n                    break;\n                case 2:\n                    message.batch_axis = reader.array(message.batch_axis, () => reader.int64(), tag);\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                case 4:\n                    message.no_scale = reader.bool();\n                    break;\n                case 5:\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.InstanceNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"channel_axis\":\n                    message.channel_axis = reader.int64();\n                    break;\n                case \"batch_axis\":\n                    reader.array(message.batch_axis, () => reader.int64());\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"no_scale\":\n                    message.no_scale = reader.bool();\n                    break;\n                case \"no_bias\":\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.InstanceNormalizationParameter.prototype.channel_axis = 0n;\nnnabla.InstanceNormalizationParameter.prototype.eps = 0;\nnnabla.InstanceNormalizationParameter.prototype.no_scale = false;\nnnabla.InstanceNormalizationParameter.prototype.no_bias = false;\n\nnnabla.LayerNormalizationParameter = class LayerNormalizationParameter {\n\n    constructor() {\n        this.batch_axis = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.LayerNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.batch_axis = reader.array(message.batch_axis, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                case 3:\n                    message.no_scale = reader.bool();\n                    break;\n                case 4:\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LayerNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"batch_axis\":\n                    reader.array(message.batch_axis, () => reader.int64());\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"no_scale\":\n                    message.no_scale = reader.bool();\n                    break;\n                case \"no_bias\":\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LayerNormalizationParameter.prototype.eps = 0;\nnnabla.LayerNormalizationParameter.prototype.no_scale = false;\nnnabla.LayerNormalizationParameter.prototype.no_bias = false;\n\nnnabla.NormNormalizationParameter = class NormNormalizationParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.NormNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.p = reader.float();\n                    break;\n                case 2:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.NormNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"p\":\n                    message.p = reader.float();\n                    break;\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.NormNormalizationParameter.prototype.p = 0;\nnnabla.NormNormalizationParameter.prototype.eps = 0;\n\nnnabla.SyncBatchNormalizationParameter = class SyncBatchNormalizationParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.SyncBatchNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.comm = nnabla.Communicator.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.group = reader.string();\n                    break;\n                case 3:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.decay_rate = reader.float();\n                    break;\n                case 5:\n                    message.eps = reader.float();\n                    break;\n                case 6:\n                    message.batch_stat = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SyncBatchNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"comm\":\n                    message.comm = nnabla.Communicator.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.string();\n                    break;\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"decay_rate\":\n                    message.decay_rate = reader.float();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"batch_stat\":\n                    message.batch_stat = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SyncBatchNormalizationParameter.prototype.comm = null;\nnnabla.SyncBatchNormalizationParameter.prototype.group = \"\";\nnnabla.SyncBatchNormalizationParameter.prototype.decay_rate = 0;\nnnabla.SyncBatchNormalizationParameter.prototype.eps = 0;\nnnabla.SyncBatchNormalizationParameter.prototype.batch_stat = false;\n\nnnabla.TensorNormalizationParameter = class TensorNormalizationParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.TensorNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                case 3:\n                    message.no_scale = reader.bool();\n                    break;\n                case 4:\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TensorNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"no_scale\":\n                    message.no_scale = reader.bool();\n                    break;\n                case \"no_bias\":\n                    message.no_bias = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.TensorNormalizationParameter.prototype.eps = 0;\nnnabla.TensorNormalizationParameter.prototype.no_scale = false;\nnnabla.TensorNormalizationParameter.prototype.no_bias = false;\n\nnnabla.WeightNormalizationParameter = class WeightNormalizationParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.WeightNormalizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim = reader.int64();\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.WeightNormalizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim\":\n                    message.dim = reader.int64();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.WeightNormalizationParameter.prototype.dim = 0n;\nnnabla.WeightNormalizationParameter.prototype.eps = 0;\n\nnnabla.WeightStandardizationParameter = class WeightStandardizationParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.WeightStandardizationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.channel_axis = reader.int64();\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.WeightStandardizationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"channel_axis\":\n                    message.channel_axis = reader.int64();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.WeightStandardizationParameter.prototype.channel_axis = 0n;\nnnabla.WeightStandardizationParameter.prototype.eps = 0;\n\nnnabla.SpectralNormParameter = class SpectralNormParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SpectralNormParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim = reader.int64();\n                    break;\n                case 2:\n                    message.itr = reader.int64();\n                    break;\n                case 3:\n                    message.eps = reader.float();\n                    break;\n                case 4:\n                    message.test = reader.bool();\n                    break;\n                case 5:\n                    message.output_u = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SpectralNormParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim\":\n                    message.dim = reader.int64();\n                    break;\n                case \"itr\":\n                    message.itr = reader.int64();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                case \"test\":\n                    message.test = reader.bool();\n                    break;\n                case \"output_u\":\n                    message.output_u = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SpectralNormParameter.prototype.dim = 0n;\nnnabla.SpectralNormParameter.prototype.itr = 0n;\nnnabla.SpectralNormParameter.prototype.eps = 0;\nnnabla.SpectralNormParameter.prototype.test = false;\nnnabla.SpectralNormParameter.prototype.output_u = false;\n\nnnabla.MeanSubtractionParameter = class MeanSubtractionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MeanSubtractionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.update_running_mean = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MeanSubtractionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"update_running_mean\":\n                    message.update_running_mean = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MeanSubtractionParameter.prototype.base_axis = 0n;\nnnabla.MeanSubtractionParameter.prototype.update_running_mean = false;\n\nnnabla.ClipGradByNormParameter = class ClipGradByNormParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.ClipGradByNormParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.clip_norm = reader.float();\n                    break;\n                case 2:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ClipGradByNormParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"clip_norm\":\n                    message.clip_norm = reader.float();\n                    break;\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ClipGradByNormParameter.prototype.clip_norm = 0;\n\nnnabla.SumParameter = class SumParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.SumParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SumParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keep_dims\":\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SumParameter.prototype.keep_dims = false;\n\nnnabla.CumSumParameter = class CumSumParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CumSumParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.exclusive = reader.bool();\n                    break;\n                case 3:\n                    message.reverse = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CumSumParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"exclusive\":\n                    message.exclusive = reader.bool();\n                    break;\n                case \"reverse\":\n                    message.reverse = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CumSumParameter.prototype.axis = 0n;\nnnabla.CumSumParameter.prototype.exclusive = false;\nnnabla.CumSumParameter.prototype.reverse = false;\n\nnnabla.MeanParameter = class MeanParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.MeanParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MeanParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keep_dims\":\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MeanParameter.prototype.keep_dims = false;\n\nnnabla.MaxParameter = class MaxParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.MaxParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keep_dims = reader.bool();\n                    break;\n                case 3:\n                    message.with_index = reader.bool();\n                    break;\n                case 4:\n                    message.only_index = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MaxParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keep_dims\":\n                    message.keep_dims = reader.bool();\n                    break;\n                case \"with_index\":\n                    message.with_index = reader.bool();\n                    break;\n                case \"only_index\":\n                    message.only_index = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MaxParameter.prototype.keep_dims = false;\nnnabla.MaxParameter.prototype.with_index = false;\nnnabla.MaxParameter.prototype.only_index = false;\n\nnnabla.MinParameter = class MinParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.MinParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keep_dims = reader.bool();\n                    break;\n                case 3:\n                    message.with_index = reader.bool();\n                    break;\n                case 4:\n                    message.only_index = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MinParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keep_dims\":\n                    message.keep_dims = reader.bool();\n                    break;\n                case \"with_index\":\n                    message.with_index = reader.bool();\n                    break;\n                case \"only_index\":\n                    message.only_index = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MinParameter.prototype.keep_dims = false;\nnnabla.MinParameter.prototype.with_index = false;\nnnabla.MinParameter.prototype.only_index = false;\n\nnnabla.NormParameter = class NormParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.NormParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.p = reader.float();\n                    break;\n                case 2:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 3:\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.NormParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"p\":\n                    message.p = reader.float();\n                    break;\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keep_dims\":\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.NormParameter.prototype.p = 0;\nnnabla.NormParameter.prototype.keep_dims = false;\n\nnnabla.ProdParameter = class ProdParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.ProdParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ProdParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"keep_dims\":\n                    message.keep_dims = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ProdParameter.prototype.keep_dims = false;\n\nnnabla.CumProdParameter = class CumProdParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CumProdParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.exclusive = reader.bool();\n                    break;\n                case 3:\n                    message.reverse = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CumProdParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"exclusive\":\n                    message.exclusive = reader.bool();\n                    break;\n                case \"reverse\":\n                    message.reverse = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CumProdParameter.prototype.axis = 0n;\nnnabla.CumProdParameter.prototype.exclusive = false;\nnnabla.CumProdParameter.prototype.reverse = false;\n\nnnabla.Add2Parameter = class Add2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Add2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Add2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Add2Parameter.prototype.inplace = false;\n\nnnabla.BcAdd2Parameter = class BcAdd2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BcAdd2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BcAdd2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BcAdd2Parameter.prototype.inplace = false;\n\nnnabla.Sub2Parameter = class Sub2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Sub2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Sub2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Sub2Parameter.prototype.inplace = false;\n\nnnabla.Mul2Parameter = class Mul2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Mul2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Mul2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Mul2Parameter.prototype.inplace = false;\n\nnnabla.Div2Parameter = class Div2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Div2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Div2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Div2Parameter.prototype.inplace = false;\n\nnnabla.Pow2Parameter = class Pow2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Pow2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Pow2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Pow2Parameter.prototype.inplace = false;\n\nnnabla.AddScalarParameter = class AddScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.AddScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                case 2:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AddScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AddScalarParameter.prototype.val = 0;\nnnabla.AddScalarParameter.prototype.inplace = false;\n\nnnabla.MulScalarParameter = class MulScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MulScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                case 2:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MulScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MulScalarParameter.prototype.val = 0;\nnnabla.MulScalarParameter.prototype.inplace = false;\n\nnnabla.PowScalarParameter = class PowScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PowScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                case 2:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PowScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PowScalarParameter.prototype.val = 0;\nnnabla.PowScalarParameter.prototype.inplace = false;\n\nnnabla.RSubScalarParameter = class RSubScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RSubScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RSubScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RSubScalarParameter.prototype.val = 0;\n\nnnabla.RDivScalarParameter = class RDivScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RDivScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RDivScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RDivScalarParameter.prototype.val = 0;\n\nnnabla.RPowScalarParameter = class RPowScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RPowScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RPowScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RPowScalarParameter.prototype.val = 0;\n\nnnabla.SignParameter = class SignParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SignParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SignParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SignParameter.prototype.alpha = 0;\n\nnnabla.MinimumScalarParameter = class MinimumScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MinimumScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MinimumScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MinimumScalarParameter.prototype.val = 0;\n\nnnabla.MaximumScalarParameter = class MaximumScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MaximumScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MaximumScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MaximumScalarParameter.prototype.val = 0;\n\nnnabla.SearchSortedParameter = class SearchSortedParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SearchSortedParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.right = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SearchSortedParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"right\":\n                    message.right = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SearchSortedParameter.prototype.right = false;\n\nnnabla.LogicalAndScalarParameter = class LogicalAndScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LogicalAndScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LogicalAndScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LogicalAndScalarParameter.prototype.val = false;\n\nnnabla.LogicalOrScalarParameter = class LogicalOrScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LogicalOrScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LogicalOrScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LogicalOrScalarParameter.prototype.val = false;\n\nnnabla.LogicalXorScalarParameter = class LogicalXorScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LogicalXorScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LogicalXorScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LogicalXorScalarParameter.prototype.val = false;\n\nnnabla.EqualScalarParameter = class EqualScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.EqualScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.EqualScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.EqualScalarParameter.prototype.val = 0;\n\nnnabla.NotEqualScalarParameter = class NotEqualScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.NotEqualScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.NotEqualScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.NotEqualScalarParameter.prototype.val = 0;\n\nnnabla.GreaterEqualScalarParameter = class GreaterEqualScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.GreaterEqualScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GreaterEqualScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GreaterEqualScalarParameter.prototype.val = 0;\n\nnnabla.GreaterScalarParameter = class GreaterScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.GreaterScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GreaterScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GreaterScalarParameter.prototype.val = 0;\n\nnnabla.LessEqualScalarParameter = class LessEqualScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LessEqualScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LessEqualScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LessEqualScalarParameter.prototype.val = 0;\n\nnnabla.LessScalarParameter = class LessScalarParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LessScalarParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LessScalarParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LessScalarParameter.prototype.val = 0;\n\nnnabla.ResetNaNParameter = class ResetNaNParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ResetNaNParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ResetNaNParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ResetNaNParameter.prototype.val = 0;\n\nnnabla.ResetInfParameter = class ResetInfParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ResetInfParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ResetInfParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.double();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ResetInfParameter.prototype.val = 0;\n\nnnabla.ConstantParameter = class ConstantParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ConstantParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.val = reader.float();\n                    break;\n                case 2:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ConstantParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"val\":\n                    message.val = reader.float();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ConstantParameter.prototype.val = 0;\nnnabla.ConstantParameter.prototype.shape = null;\n\nnnabla.ArangeParameter = class ArangeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ArangeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.start = reader.float();\n                    break;\n                case 2:\n                    message.stop = reader.float();\n                    break;\n                case 3:\n                    message.step = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ArangeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"start\":\n                    message.start = reader.float();\n                    break;\n                case \"stop\":\n                    message.stop = reader.float();\n                    break;\n                case \"step\":\n                    message.step = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ArangeParameter.prototype.start = 0;\nnnabla.ArangeParameter.prototype.stop = 0;\nnnabla.ArangeParameter.prototype.step = 0;\n\nnnabla.LinspaceParameter = class LinspaceParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.LinspaceParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.start = reader.float();\n                    break;\n                case 2:\n                    message.stop = reader.float();\n                    break;\n                case 3:\n                    message.num = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.LinspaceParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"start\":\n                    message.start = reader.float();\n                    break;\n                case \"stop\":\n                    message.stop = reader.float();\n                    break;\n                case \"num\":\n                    message.num = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.LinspaceParameter.prototype.start = 0;\nnnabla.LinspaceParameter.prototype.stop = 0;\nnnabla.LinspaceParameter.prototype.num = 0n;\n\nnnabla.BatchMatmulParameter = class BatchMatmulParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BatchMatmulParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.transpose_a = reader.bool();\n                    break;\n                case 2:\n                    message.transpose_b = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BatchMatmulParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"transpose_a\":\n                    message.transpose_a = reader.bool();\n                    break;\n                case \"transpose_b\":\n                    message.transpose_b = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BatchMatmulParameter.prototype.transpose_a = false;\nnnabla.BatchMatmulParameter.prototype.transpose_b = false;\n\nnnabla.RoundParameter = class RoundParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RoundParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RoundParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CeilParameter = class CeilParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CeilParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CeilParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.FloorParameter = class FloorParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.FloorParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.FloorParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ConcatenateParameter = class ConcatenateParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ConcatenateParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ConcatenateParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ConcatenateParameter.prototype.axis = 0n;\n\nnnabla.SplitParameter = class SplitParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SplitParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SplitParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SplitParameter.prototype.axis = 0n;\n\nnnabla.StackParameter = class StackParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.StackParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.StackParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.StackParameter.prototype.axis = 0n;\n\nnnabla.SliceParameter = class SliceParameter {\n\n    constructor() {\n        this.start = [];\n        this.stop = [];\n        this.step = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.SliceParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.start = reader.array(message.start, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.stop = reader.array(message.stop, () => reader.int64(), tag);\n                    break;\n                case 3:\n                    message.step = reader.array(message.step, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SliceParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"start\":\n                    reader.array(message.start, () => reader.int64());\n                    break;\n                case \"stop\":\n                    reader.array(message.stop, () => reader.int64());\n                    break;\n                case \"step\":\n                    reader.array(message.step, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PadParameter = class PadParameter {\n\n    constructor() {\n        this.pad_width = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.PadParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.pad_width = reader.array(message.pad_width, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.mode = reader.string();\n                    break;\n                case 3:\n                    message.constant_value = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PadParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"pad_width\":\n                    reader.array(message.pad_width, () => reader.int64());\n                    break;\n                case \"mode\":\n                    message.mode = reader.string();\n                    break;\n                case \"constant_value\":\n                    message.constant_value = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PadParameter.prototype.mode = \"\";\nnnabla.PadParameter.prototype.constant_value = 0;\n\nnnabla.TransposeParameter = class TransposeParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.TransposeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TransposeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BroadcastParameter = class BroadcastParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BroadcastParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BroadcastParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BroadcastParameter.prototype.shape = null;\n\nnnabla.BroadcastToParameter = class BroadcastToParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BroadcastToParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BroadcastToParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BroadcastToParameter.prototype.axis = 0n;\n\nnnabla.TileParameter = class TileParameter {\n\n    constructor() {\n        this.reps = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.TileParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.reps = reader.array(message.reps, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TileParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"reps\":\n                    reader.array(message.reps, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.OneHotParameter = class OneHotParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.OneHotParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.OneHotParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.OneHotParameter.prototype.shape = null;\n\nnnabla.FlipParameter = class FlipParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.FlipParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.FlipParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ShiftParameter = class ShiftParameter {\n\n    constructor() {\n        this.shifts = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.ShiftParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shifts = reader.array(message.shifts, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.border_mode = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ShiftParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shifts\":\n                    reader.array(message.shifts, () => reader.int64());\n                    break;\n                case \"border_mode\":\n                    message.border_mode = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ShiftParameter.prototype.border_mode = \"\";\n\nnnabla.SortParameter = class SortParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SortParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.reverse = reader.bool();\n                    break;\n                case 3:\n                    message.with_index = reader.bool();\n                    break;\n                case 4:\n                    message.only_index = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SortParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"reverse\":\n                    message.reverse = reader.bool();\n                    break;\n                case \"with_index\":\n                    message.with_index = reader.bool();\n                    break;\n                case \"only_index\":\n                    message.only_index = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SortParameter.prototype.axis = 0n;\nnnabla.SortParameter.prototype.reverse = false;\nnnabla.SortParameter.prototype.with_index = false;\nnnabla.SortParameter.prototype.only_index = false;\n\nnnabla.ReshapeParameter = class ReshapeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ReshapeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ReshapeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ReshapeParameter.prototype.shape = null;\nnnabla.ReshapeParameter.prototype.inplace = false;\n\nnnabla.ShapeParameter = class ShapeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ShapeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.start = reader.int64();\n                    break;\n                case 2:\n                    message.end = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ShapeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"start\":\n                    message.start = reader.int64();\n                    break;\n                case \"end\":\n                    message.end = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ShapeParameter.prototype.start = 0n;\nnnabla.ShapeParameter.prototype.end = 0n;\n\nnnabla.TriluParameter = class TriluParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.TriluParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.int64();\n                    break;\n                case 2:\n                    message.upper = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TriluParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.int64();\n                    break;\n                case \"upper\":\n                    message.upper = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.TriluParameter.prototype.k = 0n;\nnnabla.TriluParameter.prototype.upper = false;\n\nnnabla.MeshgridParameter = class MeshgridParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MeshgridParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.ij_indexing = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MeshgridParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"ij_indexing\":\n                    message.ij_indexing = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MeshgridParameter.prototype.ij_indexing = false;\n\nnnabla.BatchCholeskyParameter = class BatchCholeskyParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BatchCholeskyParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.upper = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BatchCholeskyParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"upper\":\n                    message.upper = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BatchCholeskyParameter.prototype.upper = false;\n\nnnabla.GatherParameter = class GatherParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.GatherParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.batch_dims = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.GatherParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"batch_dims\":\n                    message.batch_dims = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.GatherParameter.prototype.axis = 0n;\nnnabla.GatherParameter.prototype.batch_dims = 0n;\n\nnnabla.ScatterNdParameter = class ScatterNdParameter {\n\n    constructor() {\n        this.shape = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.ScatterNdParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = reader.array(message.shape, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.add = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ScatterNdParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    reader.array(message.shape, () => reader.int64());\n                    break;\n                case \"add\":\n                    message.add = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ScatterNdParameter.prototype.add = false;\n\nnnabla.ScatterAddParameter = class ScatterAddParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ScatterAddParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ScatterAddParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ScatterAddParameter.prototype.axis = 0n;\n\nnnabla.BoolFillParameter = class BoolFillParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BoolFillParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BoolFillParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"value\":\n                    message.value = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BoolFillParameter.prototype.value = 0;\n\nnnabla.PackPaddedSequenceParameter = class PackPaddedSequenceParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PackPaddedSequenceParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.batch_first = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PackPaddedSequenceParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"batch_first\":\n                    message.batch_first = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PackPaddedSequenceParameter.prototype.batch_first = false;\n\nnnabla.PadPackedSequenceParameter = class PadPackedSequenceParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PadPackedSequenceParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.batch_first = reader.bool();\n                    break;\n                case 2:\n                    message.padding_value = reader.float();\n                    break;\n                case 3:\n                    message.total_length = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PadPackedSequenceParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"batch_first\":\n                    message.batch_first = reader.bool();\n                    break;\n                case \"padding_value\":\n                    message.padding_value = reader.float();\n                    break;\n                case \"total_length\":\n                    message.total_length = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PadPackedSequenceParameter.prototype.batch_first = false;\nnnabla.PadPackedSequenceParameter.prototype.padding_value = 0;\nnnabla.PadPackedSequenceParameter.prototype.total_length = 0n;\n\nnnabla.InterpolateParameter = class InterpolateParameter {\n\n    constructor() {\n        this.output_size = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.InterpolateParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.output_size = reader.array(message.output_size, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.mode = reader.string();\n                    break;\n                case 3:\n                    message.align_corners = reader.bool();\n                    break;\n                case 4:\n                    message.half_pixel = reader.bool();\n                    break;\n                case 5:\n                    message.half_pixel_for_nn = reader.bool();\n                    break;\n                case 6:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.InterpolateParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"output_size\":\n                    reader.array(message.output_size, () => reader.int64());\n                    break;\n                case \"mode\":\n                    message.mode = reader.string();\n                    break;\n                case \"align_corners\":\n                    message.align_corners = reader.bool();\n                    break;\n                case \"half_pixel\":\n                    message.half_pixel = reader.bool();\n                    break;\n                case \"half_pixel_for_nn\":\n                    message.half_pixel_for_nn = reader.bool();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.InterpolateParameter.prototype.mode = \"\";\nnnabla.InterpolateParameter.prototype.align_corners = false;\nnnabla.InterpolateParameter.prototype.half_pixel = false;\nnnabla.InterpolateParameter.prototype.half_pixel_for_nn = false;\nnnabla.InterpolateParameter.prototype.channel_last = false;\n\nnnabla.ONNXResizeParameter = class ONNXResizeParameter {\n\n    constructor() {\n        this.roi = [];\n        this.scales = [];\n        this.sizes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.ONNXResizeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.roi = reader.floats(message.roi, tag);\n                    break;\n                case 2:\n                    message.scales = reader.floats(message.scales, tag);\n                    break;\n                case 3:\n                    message.sizes = reader.array(message.sizes, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.mode = reader.string();\n                    break;\n                case 5:\n                    message.coordinate_transformation_mode = reader.string();\n                    break;\n                case 6:\n                    message.cubic_coeff_a = reader.float();\n                    break;\n                case 7:\n                    message.exclude_outside = reader.int64();\n                    break;\n                case 8:\n                    message.extrapolation_value = reader.float();\n                    break;\n                case 9:\n                    message.nearest_mode = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ONNXResizeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"roi\":\n                    reader.array(message.roi, () => reader.float());\n                    break;\n                case \"scales\":\n                    reader.array(message.scales, () => reader.float());\n                    break;\n                case \"sizes\":\n                    reader.array(message.sizes, () => reader.int64());\n                    break;\n                case \"mode\":\n                    message.mode = reader.string();\n                    break;\n                case \"coordinate_transformation_mode\":\n                    message.coordinate_transformation_mode = reader.string();\n                    break;\n                case \"cubic_coeff_a\":\n                    message.cubic_coeff_a = reader.float();\n                    break;\n                case \"exclude_outside\":\n                    message.exclude_outside = reader.int64();\n                    break;\n                case \"extrapolation_value\":\n                    message.extrapolation_value = reader.float();\n                    break;\n                case \"nearest_mode\":\n                    message.nearest_mode = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ONNXResizeParameter.prototype.mode = \"\";\nnnabla.ONNXResizeParameter.prototype.coordinate_transformation_mode = \"\";\nnnabla.ONNXResizeParameter.prototype.cubic_coeff_a = 0;\nnnabla.ONNXResizeParameter.prototype.exclude_outside = 0n;\nnnabla.ONNXResizeParameter.prototype.extrapolation_value = 0;\nnnabla.ONNXResizeParameter.prototype.nearest_mode = \"\";\n\nnnabla.FFTParameter = class FFTParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.FFTParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.signal_ndim = reader.int64();\n                    break;\n                case 2:\n                    message.normalized = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.FFTParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"signal_ndim\":\n                    message.signal_ndim = reader.int64();\n                    break;\n                case \"normalized\":\n                    message.normalized = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.FFTParameter.prototype.signal_ndim = 0n;\nnnabla.FFTParameter.prototype.normalized = false;\n\nnnabla.IFFTParameter = class IFFTParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.IFFTParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.signal_ndim = reader.int64();\n                    break;\n                case 2:\n                    message.normalized = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.IFFTParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"signal_ndim\":\n                    message.signal_ndim = reader.int64();\n                    break;\n                case \"normalized\":\n                    message.normalized = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.IFFTParameter.prototype.signal_ndim = 0n;\nnnabla.IFFTParameter.prototype.normalized = false;\n\nnnabla.STFTParameter = class STFTParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.STFTParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.window_size = reader.int64();\n                    break;\n                case 2:\n                    message.stride = reader.int64();\n                    break;\n                case 3:\n                    message.fft_size = reader.int64();\n                    break;\n                case 4:\n                    message.window_type = reader.string();\n                    break;\n                case 5:\n                    message.center = reader.bool();\n                    break;\n                case 6:\n                    message.pad_mode = reader.string();\n                    break;\n                case 7:\n                    message.as_istft_backward = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.STFTParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"window_size\":\n                    message.window_size = reader.int64();\n                    break;\n                case \"stride\":\n                    message.stride = reader.int64();\n                    break;\n                case \"fft_size\":\n                    message.fft_size = reader.int64();\n                    break;\n                case \"window_type\":\n                    message.window_type = reader.string();\n                    break;\n                case \"center\":\n                    message.center = reader.bool();\n                    break;\n                case \"pad_mode\":\n                    message.pad_mode = reader.string();\n                    break;\n                case \"as_istft_backward\":\n                    message.as_istft_backward = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.STFTParameter.prototype.window_size = 0n;\nnnabla.STFTParameter.prototype.stride = 0n;\nnnabla.STFTParameter.prototype.fft_size = 0n;\nnnabla.STFTParameter.prototype.window_type = \"\";\nnnabla.STFTParameter.prototype.center = false;\nnnabla.STFTParameter.prototype.pad_mode = \"\";\nnnabla.STFTParameter.prototype.as_istft_backward = false;\n\nnnabla.ISTFTParameter = class ISTFTParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ISTFTParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.window_size = reader.int64();\n                    break;\n                case 2:\n                    message.stride = reader.int64();\n                    break;\n                case 3:\n                    message.fft_size = reader.int64();\n                    break;\n                case 4:\n                    message.window_type = reader.string();\n                    break;\n                case 5:\n                    message.center = reader.bool();\n                    break;\n                case 6:\n                    message.pad_mode = reader.string();\n                    break;\n                case 7:\n                    message.as_stft_backward = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ISTFTParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"window_size\":\n                    message.window_size = reader.int64();\n                    break;\n                case \"stride\":\n                    message.stride = reader.int64();\n                    break;\n                case \"fft_size\":\n                    message.fft_size = reader.int64();\n                    break;\n                case \"window_type\":\n                    message.window_type = reader.string();\n                    break;\n                case \"center\":\n                    message.center = reader.bool();\n                    break;\n                case \"pad_mode\":\n                    message.pad_mode = reader.string();\n                    break;\n                case \"as_stft_backward\":\n                    message.as_stft_backward = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ISTFTParameter.prototype.window_size = 0n;\nnnabla.ISTFTParameter.prototype.stride = 0n;\nnnabla.ISTFTParameter.prototype.fft_size = 0n;\nnnabla.ISTFTParameter.prototype.window_type = \"\";\nnnabla.ISTFTParameter.prototype.center = false;\nnnabla.ISTFTParameter.prototype.pad_mode = \"\";\nnnabla.ISTFTParameter.prototype.as_stft_backward = false;\n\nnnabla.DropoutParameter = class DropoutParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.DropoutParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.p = reader.double();\n                    break;\n                case 2:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.DropoutParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"p\":\n                    message.p = reader.double();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.DropoutParameter.prototype.p = 0;\nnnabla.DropoutParameter.prototype.seed = 0n;\n\nnnabla.TopKDataParameter = class TopKDataParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.TopKDataParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.int64();\n                    break;\n                case 2:\n                    message.abs = reader.bool();\n                    break;\n                case 3:\n                    message.reduce = reader.bool();\n                    break;\n                case 4:\n                    message.base_axis = reader.int64();\n                    break;\n                case 5:\n                    message.largest = reader.bool();\n                    break;\n                case 6:\n                    message.with_index = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TopKDataParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.int64();\n                    break;\n                case \"abs\":\n                    message.abs = reader.bool();\n                    break;\n                case \"reduce\":\n                    message.reduce = reader.bool();\n                    break;\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"largest\":\n                    message.largest = reader.bool();\n                    break;\n                case \"with_index\":\n                    message.with_index = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.TopKDataParameter.prototype.k = 0n;\nnnabla.TopKDataParameter.prototype.abs = false;\nnnabla.TopKDataParameter.prototype.reduce = false;\nnnabla.TopKDataParameter.prototype.base_axis = 0n;\nnnabla.TopKDataParameter.prototype.largest = false;\nnnabla.TopKDataParameter.prototype.with_index = false;\n\nnnabla.TopKGradParameter = class TopKGradParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.TopKGradParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.int64();\n                    break;\n                case 2:\n                    message.abs = reader.bool();\n                    break;\n                case 3:\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TopKGradParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.int64();\n                    break;\n                case \"abs\":\n                    message.abs = reader.bool();\n                    break;\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.TopKGradParameter.prototype.k = 0n;\nnnabla.TopKGradParameter.prototype.abs = false;\nnnabla.TopKGradParameter.prototype.base_axis = 0n;\n\nnnabla.RandParameter = class RandParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.low = reader.float();\n                    break;\n                case 2:\n                    message.high = reader.float();\n                    break;\n                case 3:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"low\":\n                    message.low = reader.float();\n                    break;\n                case \"high\":\n                    message.high = reader.float();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandParameter.prototype.low = 0;\nnnabla.RandParameter.prototype.high = 0;\nnnabla.RandParameter.prototype.shape = null;\nnnabla.RandParameter.prototype.seed = 0n;\n\nnnabla.RandintParameter = class RandintParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandintParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.low = reader.int64();\n                    break;\n                case 2:\n                    message.high = reader.int64();\n                    break;\n                case 3:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandintParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"low\":\n                    message.low = reader.int64();\n                    break;\n                case \"high\":\n                    message.high = reader.int64();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandintParameter.prototype.low = 0n;\nnnabla.RandintParameter.prototype.high = 0n;\nnnabla.RandintParameter.prototype.shape = null;\nnnabla.RandintParameter.prototype.seed = 0n;\n\nnnabla.RandnParameter = class RandnParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandnParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mu = reader.float();\n                    break;\n                case 2:\n                    message.sigma = reader.float();\n                    break;\n                case 3:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandnParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mu\":\n                    message.mu = reader.float();\n                    break;\n                case \"sigma\":\n                    message.sigma = reader.float();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandnParameter.prototype.mu = 0;\nnnabla.RandnParameter.prototype.sigma = 0;\nnnabla.RandnParameter.prototype.shape = null;\nnnabla.RandnParameter.prototype.seed = 0n;\n\nnnabla.RandBinomialParameter = class RandBinomialParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandBinomialParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.n = reader.int64();\n                    break;\n                case 2:\n                    message.p = reader.float();\n                    break;\n                case 3:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandBinomialParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"n\":\n                    message.n = reader.int64();\n                    break;\n                case \"p\":\n                    message.p = reader.float();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandBinomialParameter.prototype.n = 0n;\nnnabla.RandBinomialParameter.prototype.p = 0;\nnnabla.RandBinomialParameter.prototype.shape = null;\nnnabla.RandBinomialParameter.prototype.seed = 0n;\n\nnnabla.RandBetaParameter = class RandBetaParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandBetaParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.alpha = reader.float();\n                    break;\n                case 2:\n                    message.beta = reader.float();\n                    break;\n                case 3:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandBetaParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"alpha\":\n                    message.alpha = reader.float();\n                    break;\n                case \"beta\":\n                    message.beta = reader.float();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandBetaParameter.prototype.alpha = 0;\nnnabla.RandBetaParameter.prototype.beta = 0;\nnnabla.RandBetaParameter.prototype.shape = null;\nnnabla.RandBetaParameter.prototype.seed = 0n;\n\nnnabla.RandGammaParameter = class RandGammaParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandGammaParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.float();\n                    break;\n                case 2:\n                    message.theta = reader.float();\n                    break;\n                case 3:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandGammaParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.float();\n                    break;\n                case \"theta\":\n                    message.theta = reader.float();\n                    break;\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandGammaParameter.prototype.k = 0;\nnnabla.RandGammaParameter.prototype.theta = 0;\nnnabla.RandGammaParameter.prototype.shape = null;\nnnabla.RandGammaParameter.prototype.seed = 0n;\n\nnnabla.RandomChoiceParameter = class RandomChoiceParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandomChoiceParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.replace = reader.bool();\n                    break;\n                case 3:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandomChoiceParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"replace\":\n                    message.replace = reader.bool();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandomChoiceParameter.prototype.shape = null;\nnnabla.RandomChoiceParameter.prototype.replace = false;\nnnabla.RandomChoiceParameter.prototype.seed = 0n;\n\nnnabla.RandomCropParameter = class RandomCropParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.RandomCropParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.base_axis = reader.int64();\n                    break;\n                case 3:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandomCropParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandomCropParameter.prototype.shape = null;\nnnabla.RandomCropParameter.prototype.base_axis = 0n;\nnnabla.RandomCropParameter.prototype.seed = 0n;\n\nnnabla.RandomFlipParameter = class RandomFlipParameter {\n\n    constructor() {\n        this.axes = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.RandomFlipParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axes = reader.array(message.axes, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.base_axis = reader.int64();\n                    break;\n                case 3:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandomFlipParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axes\":\n                    reader.array(message.axes, () => reader.int64());\n                    break;\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandomFlipParameter.prototype.base_axis = 0n;\nnnabla.RandomFlipParameter.prototype.seed = 0n;\n\nnnabla.RandomShiftParameter = class RandomShiftParameter {\n\n    constructor() {\n        this.shifts = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.RandomShiftParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shifts = reader.array(message.shifts, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.border_mode = reader.string();\n                    break;\n                case 3:\n                    message.constant_value = reader.float();\n                    break;\n                case 4:\n                    message.base_axis = reader.int64();\n                    break;\n                case 5:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandomShiftParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shifts\":\n                    reader.array(message.shifts, () => reader.int64());\n                    break;\n                case \"border_mode\":\n                    message.border_mode = reader.string();\n                    break;\n                case \"constant_value\":\n                    message.constant_value = reader.float();\n                    break;\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandomShiftParameter.prototype.border_mode = \"\";\nnnabla.RandomShiftParameter.prototype.constant_value = 0;\nnnabla.RandomShiftParameter.prototype.base_axis = 0n;\nnnabla.RandomShiftParameter.prototype.seed = 0n;\n\nnnabla.RandomEraseParameter = class RandomEraseParameter {\n\n    constructor() {\n        this.area_ratios = [];\n        this.aspect_ratios = [];\n        this.replacements = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.RandomEraseParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.prob = reader.float();\n                    break;\n                case 2:\n                    message.area_ratios = reader.floats(message.area_ratios, tag);\n                    break;\n                case 3:\n                    message.aspect_ratios = reader.floats(message.aspect_ratios, tag);\n                    break;\n                case 4:\n                    message.replacements = reader.floats(message.replacements, tag);\n                    break;\n                case 5:\n                    message.n = reader.int64();\n                    break;\n                case 6:\n                    message.share = reader.bool();\n                    break;\n                case 7:\n                    message.inplace = reader.bool();\n                    break;\n                case 8:\n                    message.base_axis = reader.int64();\n                    break;\n                case 9:\n                    message.seed = reader.int64();\n                    break;\n                case 10:\n                    message.channel_last = reader.bool();\n                    break;\n                case 11:\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.RandomEraseParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"prob\":\n                    message.prob = reader.float();\n                    break;\n                case \"area_ratios\":\n                    reader.array(message.area_ratios, () => reader.float());\n                    break;\n                case \"aspect_ratios\":\n                    reader.array(message.aspect_ratios, () => reader.float());\n                    break;\n                case \"replacements\":\n                    reader.array(message.replacements, () => reader.float());\n                    break;\n                case \"n\":\n                    message.n = reader.int64();\n                    break;\n                case \"share\":\n                    message.share = reader.bool();\n                    break;\n                case \"inplace\":\n                    message.inplace = reader.bool();\n                    break;\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                case \"ste_fine_grained\":\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.RandomEraseParameter.prototype.prob = 0;\nnnabla.RandomEraseParameter.prototype.n = 0n;\nnnabla.RandomEraseParameter.prototype.share = false;\nnnabla.RandomEraseParameter.prototype.inplace = false;\nnnabla.RandomEraseParameter.prototype.base_axis = 0n;\nnnabla.RandomEraseParameter.prototype.seed = 0n;\nnnabla.RandomEraseParameter.prototype.channel_last = false;\nnnabla.RandomEraseParameter.prototype.ste_fine_grained = false;\n\nnnabla.ImageAugmentationParameter = class ImageAugmentationParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ImageAugmentationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.shape = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.min_scale = reader.float();\n                    break;\n                case 4:\n                    message.max_scale = reader.float();\n                    break;\n                case 5:\n                    message.angle = reader.float();\n                    break;\n                case 6:\n                    message.aspect_ratio = reader.float();\n                    break;\n                case 7:\n                    message.distortion = reader.float();\n                    break;\n                case 8:\n                    message.flip_lr = reader.bool();\n                    break;\n                case 9:\n                    message.flip_ud = reader.bool();\n                    break;\n                case 10:\n                    message.brightness = reader.float();\n                    break;\n                case 11:\n                    message.brightness_each = reader.bool();\n                    break;\n                case 12:\n                    message.contrast = reader.float();\n                    break;\n                case 13:\n                    message.contrast_center = reader.float();\n                    break;\n                case 14:\n                    message.contrast_each = reader.bool();\n                    break;\n                case 15:\n                    message.noise = reader.float();\n                    break;\n                case 16:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ImageAugmentationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"shape\":\n                    message.shape = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"min_scale\":\n                    message.min_scale = reader.float();\n                    break;\n                case \"max_scale\":\n                    message.max_scale = reader.float();\n                    break;\n                case \"angle\":\n                    message.angle = reader.float();\n                    break;\n                case \"aspect_ratio\":\n                    message.aspect_ratio = reader.float();\n                    break;\n                case \"distortion\":\n                    message.distortion = reader.float();\n                    break;\n                case \"flip_lr\":\n                    message.flip_lr = reader.bool();\n                    break;\n                case \"flip_ud\":\n                    message.flip_ud = reader.bool();\n                    break;\n                case \"brightness\":\n                    message.brightness = reader.float();\n                    break;\n                case \"brightness_each\":\n                    message.brightness_each = reader.bool();\n                    break;\n                case \"contrast\":\n                    message.contrast = reader.float();\n                    break;\n                case \"contrast_center\":\n                    message.contrast_center = reader.float();\n                    break;\n                case \"contrast_each\":\n                    message.contrast_each = reader.bool();\n                    break;\n                case \"noise\":\n                    message.noise = reader.float();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ImageAugmentationParameter.prototype.shape = null;\nnnabla.ImageAugmentationParameter.prototype.pad = null;\nnnabla.ImageAugmentationParameter.prototype.min_scale = 0;\nnnabla.ImageAugmentationParameter.prototype.max_scale = 0;\nnnabla.ImageAugmentationParameter.prototype.angle = 0;\nnnabla.ImageAugmentationParameter.prototype.aspect_ratio = 0;\nnnabla.ImageAugmentationParameter.prototype.distortion = 0;\nnnabla.ImageAugmentationParameter.prototype.flip_lr = false;\nnnabla.ImageAugmentationParameter.prototype.flip_ud = false;\nnnabla.ImageAugmentationParameter.prototype.brightness = 0;\nnnabla.ImageAugmentationParameter.prototype.brightness_each = false;\nnnabla.ImageAugmentationParameter.prototype.contrast = 0;\nnnabla.ImageAugmentationParameter.prototype.contrast_center = 0;\nnnabla.ImageAugmentationParameter.prototype.contrast_each = false;\nnnabla.ImageAugmentationParameter.prototype.noise = 0;\nnnabla.ImageAugmentationParameter.prototype.seed = 0n;\n\nnnabla.SoftmaxCrossEntropyParameter = class SoftmaxCrossEntropyParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SoftmaxCrossEntropyParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SoftmaxCrossEntropyParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SoftmaxCrossEntropyParameter.prototype.axis = 0n;\n\nnnabla.CategoricalCrossEntropyParameter = class CategoricalCrossEntropyParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.CategoricalCrossEntropyParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.CategoricalCrossEntropyParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.CategoricalCrossEntropyParameter.prototype.axis = 0n;\n\nnnabla.HuberLossParameter = class HuberLossParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.HuberLossParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.delta = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.HuberLossParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"delta\":\n                    message.delta = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.HuberLossParameter.prototype.delta = 0;\n\nnnabla.EpsilonInsensitiveLossParameter = class EpsilonInsensitiveLossParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.EpsilonInsensitiveLossParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.epsilon = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.EpsilonInsensitiveLossParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"epsilon\":\n                    message.epsilon = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.EpsilonInsensitiveLossParameter.prototype.epsilon = 0;\n\nnnabla.KLMultinomialParameter = class KLMultinomialParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.KLMultinomialParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.KLMultinomialParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.KLMultinomialParameter.prototype.base_axis = 0n;\n\nnnabla.AffineGridParameter = class AffineGridParameter {\n\n    constructor() {\n        this.size = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.AffineGridParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.size = reader.array(message.size, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.align_corners = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.AffineGridParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"size\":\n                    reader.array(message.size, () => reader.int64());\n                    break;\n                case \"align_corners\":\n                    message.align_corners = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.AffineGridParameter.prototype.align_corners = false;\n\nnnabla.WarpByGridParameter = class WarpByGridParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.WarpByGridParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.mode = reader.string();\n                    break;\n                case 2:\n                    message.padding_mode = reader.string();\n                    break;\n                case 3:\n                    message.align_corners = reader.bool();\n                    break;\n                case 4:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.WarpByGridParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"mode\":\n                    message.mode = reader.string();\n                    break;\n                case \"padding_mode\":\n                    message.padding_mode = reader.string();\n                    break;\n                case \"align_corners\":\n                    message.align_corners = reader.bool();\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.WarpByGridParameter.prototype.mode = \"\";\nnnabla.WarpByGridParameter.prototype.padding_mode = \"\";\nnnabla.WarpByGridParameter.prototype.align_corners = false;\nnnabla.WarpByGridParameter.prototype.channel_last = false;\n\nnnabla.BinaryConnectAffineParameter = class BinaryConnectAffineParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BinaryConnectAffineParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BinaryConnectAffineParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"quantize_zero_to\":\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BinaryConnectAffineParameter.prototype.base_axis = 0n;\nnnabla.BinaryConnectAffineParameter.prototype.quantize_zero_to = 0;\n\nnnabla.BinaryConnectConvolutionParameter = class BinaryConnectConvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BinaryConnectConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BinaryConnectConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"quantize_zero_to\":\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BinaryConnectConvolutionParameter.prototype.base_axis = 0n;\nnnabla.BinaryConnectConvolutionParameter.prototype.pad = null;\nnnabla.BinaryConnectConvolutionParameter.prototype.stride = null;\nnnabla.BinaryConnectConvolutionParameter.prototype.dilation = null;\nnnabla.BinaryConnectConvolutionParameter.prototype.group = 0n;\nnnabla.BinaryConnectConvolutionParameter.prototype.quantize_zero_to = 0;\n\nnnabla.BinaryWeightAffineParameter = class BinaryWeightAffineParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BinaryWeightAffineParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BinaryWeightAffineParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"quantize_zero_to\":\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BinaryWeightAffineParameter.prototype.base_axis = 0n;\nnnabla.BinaryWeightAffineParameter.prototype.quantize_zero_to = 0;\n\nnnabla.BinaryWeightConvolutionParameter = class BinaryWeightConvolutionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BinaryWeightConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BinaryWeightConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"quantize_zero_to\":\n                    message.quantize_zero_to = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BinaryWeightConvolutionParameter.prototype.base_axis = 0n;\nnnabla.BinaryWeightConvolutionParameter.prototype.pad = null;\nnnabla.BinaryWeightConvolutionParameter.prototype.stride = null;\nnnabla.BinaryWeightConvolutionParameter.prototype.dilation = null;\nnnabla.BinaryWeightConvolutionParameter.prototype.group = 0n;\nnnabla.BinaryWeightConvolutionParameter.prototype.quantize_zero_to = 0;\n\nnnabla.INQAffineParameter = class INQAffineParameter {\n\n    constructor() {\n        this.inq_iterations = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.INQAffineParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.num_bits = reader.int64();\n                    break;\n                case 3:\n                    message.inq_iterations = reader.array(message.inq_iterations, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.selection_algorithm = reader.string();\n                    break;\n                case 5:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.INQAffineParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"num_bits\":\n                    message.num_bits = reader.int64();\n                    break;\n                case \"inq_iterations\":\n                    reader.array(message.inq_iterations, () => reader.int64());\n                    break;\n                case \"selection_algorithm\":\n                    message.selection_algorithm = reader.string();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.INQAffineParameter.prototype.base_axis = 0n;\nnnabla.INQAffineParameter.prototype.num_bits = 0n;\nnnabla.INQAffineParameter.prototype.selection_algorithm = \"\";\nnnabla.INQAffineParameter.prototype.seed = 0n;\n\nnnabla.INQConvolutionParameter = class INQConvolutionParameter {\n\n    constructor() {\n        this.inq_iterations = [];\n    }\n\n    static decode(reader, length) {\n        const message = new nnabla.INQConvolutionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.dilation = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.group = reader.int64();\n                    break;\n                case 6:\n                    message.num_bits = reader.int64();\n                    break;\n                case 7:\n                    message.inq_iterations = reader.array(message.inq_iterations, () => reader.int64(), tag);\n                    break;\n                case 8:\n                    message.selection_algorithm = reader.string();\n                    break;\n                case 9:\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.INQConvolutionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"dilation\":\n                    message.dilation = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"group\":\n                    message.group = reader.int64();\n                    break;\n                case \"num_bits\":\n                    message.num_bits = reader.int64();\n                    break;\n                case \"inq_iterations\":\n                    reader.array(message.inq_iterations, () => reader.int64());\n                    break;\n                case \"selection_algorithm\":\n                    message.selection_algorithm = reader.string();\n                    break;\n                case \"seed\":\n                    message.seed = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.INQConvolutionParameter.prototype.base_axis = 0n;\nnnabla.INQConvolutionParameter.prototype.pad = null;\nnnabla.INQConvolutionParameter.prototype.stride = null;\nnnabla.INQConvolutionParameter.prototype.dilation = null;\nnnabla.INQConvolutionParameter.prototype.group = 0n;\nnnabla.INQConvolutionParameter.prototype.num_bits = 0n;\nnnabla.INQConvolutionParameter.prototype.selection_algorithm = \"\";\nnnabla.INQConvolutionParameter.prototype.seed = 0n;\n\nnnabla.FixedPointQuantizeParameter = class FixedPointQuantizeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.FixedPointQuantizeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.sign = reader.bool();\n                    break;\n                case 2:\n                    message.n = reader.int64();\n                    break;\n                case 3:\n                    message.delta = reader.float();\n                    break;\n                case 4:\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.FixedPointQuantizeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sign\":\n                    message.sign = reader.bool();\n                    break;\n                case \"n\":\n                    message.n = reader.int64();\n                    break;\n                case \"delta\":\n                    message.delta = reader.float();\n                    break;\n                case \"ste_fine_grained\":\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.FixedPointQuantizeParameter.prototype.sign = false;\nnnabla.FixedPointQuantizeParameter.prototype.n = 0n;\nnnabla.FixedPointQuantizeParameter.prototype.delta = 0;\nnnabla.FixedPointQuantizeParameter.prototype.ste_fine_grained = false;\n\nnnabla.MinMaxQuantizeParameter = class MinMaxQuantizeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MinMaxQuantizeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.decay = reader.float();\n                    break;\n                case 2:\n                    message.x_min_max = reader.bool();\n                    break;\n                case 3:\n                    message.ema = reader.bool();\n                    break;\n                case 4:\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                case 5:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MinMaxQuantizeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"decay\":\n                    message.decay = reader.float();\n                    break;\n                case \"x_min_max\":\n                    message.x_min_max = reader.bool();\n                    break;\n                case \"ema\":\n                    message.ema = reader.bool();\n                    break;\n                case \"ste_fine_grained\":\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MinMaxQuantizeParameter.prototype.decay = 0;\nnnabla.MinMaxQuantizeParameter.prototype.x_min_max = false;\nnnabla.MinMaxQuantizeParameter.prototype.ema = false;\nnnabla.MinMaxQuantizeParameter.prototype.ste_fine_grained = false;\nnnabla.MinMaxQuantizeParameter.prototype.eps = 0;\n\nnnabla.Pow2QuantizeParameter = class Pow2QuantizeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Pow2QuantizeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.sign = reader.bool();\n                    break;\n                case 2:\n                    message.with_zero = reader.bool();\n                    break;\n                case 3:\n                    message.n = reader.int64();\n                    break;\n                case 4:\n                    message.m = reader.int64();\n                    break;\n                case 5:\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Pow2QuantizeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"sign\":\n                    message.sign = reader.bool();\n                    break;\n                case \"with_zero\":\n                    message.with_zero = reader.bool();\n                    break;\n                case \"n\":\n                    message.n = reader.int64();\n                    break;\n                case \"m\":\n                    message.m = reader.int64();\n                    break;\n                case \"ste_fine_grained\":\n                    message.ste_fine_grained = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Pow2QuantizeParameter.prototype.sign = false;\nnnabla.Pow2QuantizeParameter.prototype.with_zero = false;\nnnabla.Pow2QuantizeParameter.prototype.n = 0n;\nnnabla.Pow2QuantizeParameter.prototype.m = 0n;\nnnabla.Pow2QuantizeParameter.prototype.ste_fine_grained = false;\n\nnnabla.PruneParameter = class PruneParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PruneParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.rate = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PruneParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"rate\":\n                    message.rate = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PruneParameter.prototype.rate = 0;\n\nnnabla.QuantizeLinearParameter = class QuantizeLinearParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.QuantizeLinearParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.round_mode = reader.string();\n                    break;\n                case 2:\n                    message.narrow_range = reader.bool();\n                    break;\n                case 3:\n                    message.dtype = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.QuantizeLinearParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"round_mode\":\n                    message.round_mode = reader.string();\n                    break;\n                case \"narrow_range\":\n                    message.narrow_range = reader.bool();\n                    break;\n                case \"dtype\":\n                    message.dtype = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.QuantizeLinearParameter.prototype.round_mode = \"\";\nnnabla.QuantizeLinearParameter.prototype.narrow_range = false;\nnnabla.QuantizeLinearParameter.prototype.dtype = 0n;\n\nnnabla.TopNErrorParameter = class TopNErrorParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.TopNErrorParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.n = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.TopNErrorParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"n\":\n                    message.n = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.TopNErrorParameter.prototype.axis = 0n;\nnnabla.TopNErrorParameter.prototype.n = 0n;\n\nnnabla.ConfusionMatrixParameter = class ConfusionMatrixParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ConfusionMatrixParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ConfusionMatrixParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ConfusionMatrixParameter.prototype.axis = 0n;\n\nnnabla.VATNoiseParameter = class VATNoiseParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.VATNoiseParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.base_axis = reader.int64();\n                    break;\n                case 2:\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.VATNoiseParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"base_axis\":\n                    message.base_axis = reader.int64();\n                    break;\n                case \"eps\":\n                    message.eps = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.VATNoiseParameter.prototype.base_axis = 0n;\nnnabla.VATNoiseParameter.prototype.eps = 0;\n\nnnabla.SinkParameter = class SinkParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.SinkParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.one_input_grad = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.SinkParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"one_input_grad\":\n                    message.one_input_grad = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.SinkParameter.prototype.one_input_grad = false;\n\nnnabla.NmsDetection2dParameter = class NmsDetection2dParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.NmsDetection2dParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.thresh = reader.float();\n                    break;\n                case 2:\n                    message.nms = reader.float();\n                    break;\n                case 3:\n                    message.nms_per_class = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.NmsDetection2dParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"thresh\":\n                    message.thresh = reader.float();\n                    break;\n                case \"nms\":\n                    message.nms = reader.float();\n                    break;\n                case \"nms_per_class\":\n                    message.nms_per_class = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.NmsDetection2dParameter.prototype.thresh = 0;\nnnabla.NmsDetection2dParameter.prototype.nms = 0;\nnnabla.NmsDetection2dParameter.prototype.nms_per_class = false;\n\nnnabla.ONNXNonMaxSuppressionParameter = class ONNXNonMaxSuppressionParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.ONNXNonMaxSuppressionParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.center_point_box = reader.int64();\n                    break;\n                case 2:\n                    message.max_output_boxes_per_class = reader.int64();\n                    break;\n                case 3:\n                    message.iou_threshold = reader.float();\n                    break;\n                case 4:\n                    message.score_threshold = reader.float();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.ONNXNonMaxSuppressionParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"center_point_box\":\n                    message.center_point_box = reader.int64();\n                    break;\n                case \"max_output_boxes_per_class\":\n                    message.max_output_boxes_per_class = reader.int64();\n                    break;\n                case \"iou_threshold\":\n                    message.iou_threshold = reader.float();\n                    break;\n                case \"score_threshold\":\n                    message.score_threshold = reader.float();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.ONNXNonMaxSuppressionParameter.prototype.center_point_box = 0n;\nnnabla.ONNXNonMaxSuppressionParameter.prototype.max_output_boxes_per_class = 0n;\nnnabla.ONNXNonMaxSuppressionParameter.prototype.iou_threshold = 0;\nnnabla.ONNXNonMaxSuppressionParameter.prototype.score_threshold = 0;\n\nnnabla.MaxPoolingBackwardParameter = class MaxPoolingBackwardParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.MaxPoolingBackwardParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.kernel = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.stride = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.ignore_border = reader.bool();\n                    break;\n                case 4:\n                    message.pad = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.MaxPoolingBackwardParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"kernel\":\n                    message.kernel = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"stride\":\n                    message.stride = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"ignore_border\":\n                    message.ignore_border = reader.bool();\n                    break;\n                case \"pad\":\n                    message.pad = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"channel_last\":\n                    message.channel_last = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.MaxPoolingBackwardParameter.prototype.kernel = null;\nnnabla.MaxPoolingBackwardParameter.prototype.stride = null;\nnnabla.MaxPoolingBackwardParameter.prototype.ignore_border = false;\nnnabla.MaxPoolingBackwardParameter.prototype.pad = null;\nnnabla.MaxPoolingBackwardParameter.prototype.channel_last = false;\n\nnnabla.PatchCorrelationParameter = class PatchCorrelationParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.PatchCorrelationParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.patch = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.shift = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.patch_step = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.shift_step = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.padding = nnabla.Shape.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.PatchCorrelationParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"patch\":\n                    message.patch = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"shift\":\n                    message.shift = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"patch_step\":\n                    message.patch_step = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"shift_step\":\n                    message.shift_step = nnabla.Shape.decodeText(reader);\n                    break;\n                case \"padding\":\n                    message.padding = nnabla.Shape.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.PatchCorrelationParameter.prototype.patch = null;\nnnabla.PatchCorrelationParameter.prototype.shift = null;\nnnabla.PatchCorrelationParameter.prototype.patch_step = null;\nnnabla.PatchCorrelationParameter.prototype.shift_step = null;\nnnabla.PatchCorrelationParameter.prototype.padding = null;\n\nnnabla.UniqueParameter = class UniqueParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.UniqueParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.flatten = reader.bool();\n                    break;\n                case 2:\n                    message.axis = reader.int64();\n                    break;\n                case 3:\n                    message.sorted = reader.bool();\n                    break;\n                case 4:\n                    message.with_index = reader.bool();\n                    break;\n                case 5:\n                    message.with_inverse = reader.bool();\n                    break;\n                case 6:\n                    message.with_counts = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.UniqueParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"flatten\":\n                    message.flatten = reader.bool();\n                    break;\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"sorted\":\n                    message.sorted = reader.bool();\n                    break;\n                case \"with_index\":\n                    message.with_index = reader.bool();\n                    break;\n                case \"with_inverse\":\n                    message.with_inverse = reader.bool();\n                    break;\n                case \"with_counts\":\n                    message.with_counts = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.UniqueParameter.prototype.flatten = false;\nnnabla.UniqueParameter.prototype.axis = 0n;\nnnabla.UniqueParameter.prototype.sorted = false;\nnnabla.UniqueParameter.prototype.with_index = false;\nnnabla.UniqueParameter.prototype.with_inverse = false;\nnnabla.UniqueParameter.prototype.with_counts = false;\n\nnnabla.EyeLikeParameter = class EyeLikeParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.EyeLikeParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.k = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.EyeLikeParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"k\":\n                    message.k = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.EyeLikeParameter.prototype.k = 0n;\n\nnnabla.Mod2Parameter = class Mod2Parameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.Mod2Parameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.fmod = reader.bool();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.Mod2Parameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"fmod\":\n                    message.fmod = reader.bool();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.Mod2Parameter.prototype.fmod = false;\n\nnnabla.BitShiftParameter = class BitShiftParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.BitShiftParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.direction = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.BitShiftParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"direction\":\n                    message.direction = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.BitShiftParameter.prototype.direction = \"\";\n\nnnabla.EinsumParameter = class EinsumParameter {\n\n    static decode(reader, length) {\n        const message = new nnabla.EinsumParameter();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.equation = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new nnabla.EinsumParameter();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"equation\":\n                    message.equation = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nnnabla.EinsumParameter.prototype.equation = \"\";\n"
  },
  {
    "path": "source/nnabla.js",
    "content": "\nconst nnabla = {};\n\nnnabla.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        if (identifier.endsWith('.nntxt')) {\n            const tags = await context.tags('pbtxt');\n            if (tags.has('network')) {\n                return context.set('nnabla.pbtxt');\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        nnabla.proto = await context.require('./nnabla-proto');\n        nnabla.proto = nnabla.proto.nnabla;\n        switch (context.type) {\n            case 'nnabla.pbtxt': {\n                const reader = await context.read('protobuf.text');\n                const model = nnabla.proto.NNablaProtoBuf.decodeText(reader);\n                const files = ['nnp_version.txt', 'parameter.protobuf', 'parameter.h5'];\n                let contexts = await Promise.all(files.map((file) => context.fetch(file).catch(() => null)));\n                contexts = contexts.filter((context) => context !== null);\n                contexts = new Map(contexts.map((context) => [context.identifier, context]));\n                let version = '';\n                if (contexts.has('nnp_version.txt')) {\n                    const context = contexts.get('nnp_version.txt');\n                    const reader = await context.read('text');\n                    const line = reader.read('\\n');\n                    version = line.split('\\r').shift();\n                }\n                if (contexts.has('parameter.protobuf')) {\n                    const context = contexts.get('parameter.protobuf');\n                    const reader = await context.read('protobuf.binary');\n                    const params = nnabla.proto.NNablaProtoBuf.decode(reader);\n                    model.parameter = params.parameter;\n                } else if (contexts.has('parameter.h5')) {\n                    const context = contexts.get('parameter.h5');\n                    const file = await context.read('hdf5');\n                    const queue = [['',file]];\n                    while (queue.length > 0) {\n                        const [name, group] = queue.shift();\n                        if (group.value) {\n                            const variable = group.value;\n                            const data = variable.data.peek();\n                            const buffer = new Uint8Array(data.length);\n                            buffer.set(data, 0);\n                            const parameter = new nnabla.proto.Parameter();\n                            parameter.variable_name = name;\n                            parameter.shape = new nnabla.proto.Shape();\n                            parameter.shape.dim = variable.shape.map((dim) => BigInt(dim));\n                            parameter.data = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength >> 2);\n                            model.parameter.push(parameter);\n                        } else {\n                            for (const [key, value] of group.groups) {\n                                queue.push([name ? `${name}/${key}` : key, value]);\n                            }\n                        }\n                    }\n                }\n                const metadata = await context.metadata('nnabla-metadata.json');\n                return new nnabla.Model(metadata, model, version);\n            }\n            default: {\n                throw new nnabla.Error(`Unsupported nnabla format '${context.type}'.`);\n            }\n        }\n    }\n\n    filter(context, match) {\n        return context.type !== 'nnabla.pbtxt' || (match.type !== 'hdf5.parameter.h5' && match.type !== 'keras.h5');\n    }\n};\n\nnnabla.Model = class {\n\n    constructor(metadata, model, version) {\n        this.format = `NNabla${version ? ` v${version}` : ''}`;\n        this.modules = [];\n        const tensors = new Map(model.parameter.map((parameter) => {\n            const name = parameter.variable_name;\n            const shape = new nnabla.TensorShape(parameter.shape.dim);\n            const type = new nnabla.TensorType(shape);\n            return [name, new nnabla.Tensor(name, type, parameter.data)];\n        }));\n        const networks = new Map(model.network.map((network) => [network.name, network]));\n        for (const executor of model.executor) {\n            const network = networks.get(executor.network_name);\n            const graph = new nnabla.Graph(metadata, network, executor.data_variable, executor.output_variable, tensors);\n            this.modules.push(graph);\n        }\n        for (const optimizer of model.optimizer) {\n            const network = networks.get(optimizer.network_name);\n            const graph = new nnabla.Graph(metadata, network, optimizer.data_variable, optimizer.loss_variable, tensors);\n            this.modules.push(graph);\n        }\n        for (const monitor of model.monitor) {\n            const network = networks.get(monitor.network_name);\n            const graph = new nnabla.Graph(metadata, network, monitor.data_variable, monitor.monitor_variable, tensors);\n            this.modules.push(graph);\n        }\n    }\n};\n\nnnabla.Graph = class {\n\n    constructor (metadata, network, inputs, outputs, tensors) {\n        this.name = network.name;\n        const values = new Map(network.variable.map((variable) => {\n            const name = variable.name;\n            const shape = new nnabla.TensorShape(variable.shape.dim);\n            const type = new nnabla.TensorType(shape);\n            return [name, new nnabla.Value(name, type, tensors.get(name))];\n        }));\n        values.map = (name) => {\n            if (!values.has(name)) {\n                values.set(name, new nnabla.Value(name, null, tensors.get(name)));\n            }\n            return values.get(name);\n        };\n        this.inputs = inputs.map((item) => {\n            const name = item.variable_name;\n            return new nnabla.Argument(name, [values.map(name)]);\n        });\n        this.outputs = outputs.map((output) => {\n            const name = output.variable_name;\n            return new nnabla.Argument(name, [values.map(name)]);\n        });\n        const get_parameters = (func) => {\n            for (const [key, value] of Object.entries(func)) {\n                if (key.endsWith(\"_param\")) {\n                    return value;\n                }\n            }\n            return undefined;\n        };\n        this.nodes = network.function.map((func) => {\n            const parameters = get_parameters(func) || [];\n            const attributes = Object.entries(parameters).map(([name, value]) => {\n                const attribute = metadata.attribute(func.type, name);\n                let type = attribute.type;\n                switch (type) {\n                    case 'shape':\n                        type = \"int64[]\";\n                        value = value.dim;\n                        break;\n                    default:\n                        break;\n                }\n                const visible = attribute.default !== undefined && value === attribute.default ? false : true;\n                return new nnabla.Argument(name, value, type, visible);\n            });\n            const func_type = metadata.type(func.type);\n            const inputs = [];\n            for (let index = 0; index < func.input.length;) {\n                const input = func_type.inputs && index < func_type.inputs.length ? func_type.inputs[index] : { name: index.toString() };\n                const count = input.list ? func.input.length - index : 1;\n                const args = func.input.slice(index, index + count).map((input) => values.map(input));\n                const argument = new nnabla.Argument(input.name, args);\n                inputs.push(argument);\n                index += count;\n            }\n            const outputs = [];\n            for (let index = 0; index < func.output.length;) {\n                const output = func_type.outputs && index < func_type.outputs.length ? func_type.outputs[index] : { name: index.toString() };\n                const count = output.list ? func.output.length - index : 1;\n                const args = func.output.slice(index, index + count).map((output) => values.map(output));\n                const argument = new nnabla.Argument(output.name, args);\n                outputs.push(argument);\n                index += count;\n            }\n            return new nnabla.Node(metadata, func, attributes, inputs, outputs);\n        });\n    }\n};\n\nnnabla.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nnnabla.Value = class {\n\n    constructor(name, type, initializer = null) {\n        this.name = name;\n        this.type = !type && initializer && initializer.type ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nnnabla.Node = class {\n\n    constructor(metadata, func, attributes = [], inputs = [], outputs = []) {\n        this.name = func.name;\n        this.type = metadata.type(func.type) || { name: func.type, type: func.type };\n        this.attributes = attributes;\n        this.outputs = outputs;\n        this.chain = [];\n        // \"nonlinearity\" does not match metadata type\n        const get_nonlinearity = (name) => {\n            switch (name) {\n                case \"identity\": return \"Identity\";\n                case \"relu\": return \"ReLU\";\n                case \"sigmoid\": return \"Sigmoid\";\n                case \"tanh\": return \"Tanh\";\n                case \"leaky_relu\": return \"LeakyReLU\";\n                case \"elu\": return \"ELU\";\n                case \"relu6\": return \"ReLU6\";\n                default: return name;\n            }\n        };\n        switch (func.type) {\n            case \"FusedConvolution\": {\n                this.inputs = inputs.slice(0, 3) || [];\n                if (inputs.length > 3) {\n                    this.chain.push(new nnabla.Node(metadata, { name: `${func.name}/bn`, type: \"BatchNormalization\" }, [], inputs.slice(3, 7)));\n                }\n                if (inputs.length > 7) {\n                    this.chain.push(new nnabla.Node(metadata, { name: `${func.name}/add`, type: \"Add2\" }, [], inputs.slice(7)));\n                }\n                const type_a = attributes.find((item) => item.name === \"nonlinearity\").value;\n                this.chain.push(new nnabla.Node(metadata, { name: `${func.name}/act`, type: get_nonlinearity(type_a) }));\n                break;\n            }\n            case \"FusedBatchNormalization\": {\n                this.inputs = inputs.slice(0, 5) || [];\n                if (inputs.length > 4) {\n                    this.chain.push(new nnabla.Node(metadata, { name: `${func.name}/add`, type: \"Add2\" }, [], inputs.slice(5)));\n                }\n                const type_b = attributes.find((item) => item.name === \"nonlinearity\").value;\n                this.chain.push(new nnabla.Node(metadata, { name: `${func.name}/act`, type: get_nonlinearity(type_b) }));\n                break;\n            }\n            default: {\n                this.inputs = inputs || [];\n                break;\n            }\n        }\n    }\n};\n\nnnabla.Tensor = class {\n\n    constructor(name, type, values) {\n        this.name = name;\n        this.type = type;\n        this.encoding = '|';\n        this.values = values;\n        const dataType = this.type.dataType;\n        switch (dataType) {\n            case 'float32': this.values = new Float32Array(this.values); break;\n            default: throw new nnabla.Error(`Unsupported data type '${dataType}'.`);\n        }\n    }\n};\n\nnnabla.TensorType = class {\n\n    constructor(shape) {\n        this.dataType = \"float32\";\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nnnabla.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim);\n    }\n\n    toString() {\n        if (Array.isArray(this.dimensions) && this.dimensions.length > 0) {\n            return `[${this.dimensions.join(',')}]`;\n        }\n        return '';\n    }\n};\n\nnnabla.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Neural Network Library model.';\n    }\n};\n\nexport const ModelFactory = nnabla.ModelFactory;\n"
  },
  {
    "path": "source/nnef.js",
    "content": "\nconst nnef = {};\n\nnnef.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        switch (extension) {\n            case 'nnef': {\n                const reader = await nnef.TextReader.open(context);\n                if (reader) {\n                    return context.set('nnef.graph', reader);\n                }\n                break;\n            }\n            case 'dat': {\n                const stream = context.stream;\n                if (stream && stream.length > 2) {\n                    const buffer = stream.peek(2);\n                    if (buffer[0] === 0x4E && buffer[1] === 0xEF) {\n                        return context.set('nnef.dat', stream);\n                    }\n                }\n                break;\n            }\n            default:\n                break;\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        return context.type !== 'nnef.graph' || match.type !== 'nnef.dat';\n    }\n\n    async open(context) {\n        switch (context.type) {\n            case 'nnef.graph': {\n                const reader = context.value;\n                throw new nnef.Error(`NNEF v${reader.version} support not implemented.`);\n            }\n            case 'nnef.dat': {\n                throw new nnef.Error('NNEF dat format support not implemented.');\n            }\n            default: {\n                throw new nnef.Error(`Unsupported NNEF format '${context.type}'.`);\n            }\n        }\n    }\n};\n\nnnef.TextReader = class {\n\n    static async open(context) {\n        const reader = await context.read('text', 65536);\n        for (let i = 0; i < 32; i++) {\n            const line = reader.read('\\n');\n            const match = /version\\s*(\\d+\\.\\d+);/.exec(line);\n            if (match) {\n                return new nnef.TextReader(context, match[1]);\n            }\n            if (line === undefined) {\n                break;\n            }\n        }\n        return null;\n    }\n\n    constructor(context, version) {\n        this.context = context;\n        this.version = version;\n    }\n};\n\nnnef.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading NNEF model.';\n    }\n};\n\nexport const ModelFactory = nnef.ModelFactory;\n"
  },
  {
    "path": "source/node.js",
    "content": "\nimport * as fs from 'fs';\n\nconst node = {};\n\nnode.FileStream = class {\n\n    constructor(file, start, length, mtime) {\n        this._file = file;\n        this._start = start;\n        this._length = length;\n        this._position = 0;\n        this._mtime = mtime;\n    }\n\n    get position() {\n        return this._position;\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    stream(length) {\n        const stream = new node.FileStream(this._file, this._start + this._position, length, this._mtime);\n        this.skip(length);\n        return stream;\n    }\n\n    seek(position) {\n        this._position = position >= 0 ? position : this._length + position;\n        if (this._position > this._length || this._position < 0) {\n            throw new Error(`Expected ${this._position - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position > this._length || this._position < 0) {\n            throw new Error(`Expected ${this._position - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    peek(length) {\n        length = length === undefined ? this._length - this._position : length;\n        if (length < 0x10000000) {\n            const position = this._fill(length);\n            this._position -= length;\n            return this._buffer.subarray(position, position + length);\n        }\n        const position = this._position;\n        this.skip(length);\n        this.seek(position);\n        const buffer = new Uint8Array(length);\n        this._read(buffer, position);\n        return buffer;\n    }\n\n    read(length) {\n        length = length === undefined ? this._length - this._position : length;\n        if (length < 0x10000000) {\n            const position = this._fill(length);\n            return this._buffer.slice(position, position + length);\n        }\n        const position = this._position;\n        this.skip(length);\n        const buffer = new Uint8Array(length);\n        this._read(buffer, position);\n        return buffer;\n    }\n\n    _fill(length) {\n        if (this._position + length > this._length) {\n            const offset = this._position + length - this._length;\n            throw new Error(`Expected ${offset} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n        if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {\n            this._offset = this._position;\n            const length = Math.min(0x10000000, this._length - this._offset);\n            if (!this._buffer || length !== this._buffer.length) {\n                this._buffer = new Uint8Array(length);\n            }\n            this._read(this._buffer, this._offset);\n        }\n        const position = this._position;\n        this._position += length;\n        return position - this._offset;\n    }\n\n    _read(buffer, offset) {\n        const descriptor = fs.openSync(this._file, 'r');\n        const stat = fs.statSync(this._file);\n        if (stat.mtimeMs !== this._mtime) {\n            throw new Error(`File '${this._file}' last modified time changed.`);\n        }\n        try {\n            fs.readSync(descriptor, buffer, 0, buffer.length, offset + this._start);\n        } finally {\n            fs.closeSync(descriptor);\n        }\n    }\n};\n\nexport const FileStream = node.FileStream;\n"
  },
  {
    "path": "source/numpy.js",
    "content": "\n// Experimental\n\nimport * as python from './python.js';\n\nconst numpy = {};\n\nnumpy.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        const signature = [0x93, 0x4E, 0x55, 0x4D, 0x50, 0x59];\n        if (stream && signature.length <= stream.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {\n            return context.set('npy');\n        }\n        const entries = await context.peek('npz');\n        if (entries instanceof Map && entries.size > 0) {\n            return context.set('npz', entries);\n        }\n        return null;\n    }\n\n    async open(context) {\n        let format = '';\n        const modules = [];\n        switch (context.type) {\n            case 'npy': {\n                format = 'NumPy Array';\n                const unresolved = new Set();\n                const execution = new python.Execution();\n                execution.on('resolve', (sender, name) => unresolved.add(name));\n                const stream = context.stream;\n                const io = execution.__import__('io');\n                const np = execution.__import__('numpy');\n                const bytes = new io.BytesIO(stream);\n                const array = np.load(bytes);\n                if (unresolved.size > 0) {\n                    const name = unresolved.values().next().value;\n                    throw new numpy.Error(`Unknown type name '${name}'.`);\n                }\n                const layer = { type: 'numpy.ndarray', parameters: [{ name: 'value', tensor: { name: '', array } }] };\n                modules.push({ layers: [layer] });\n                break;\n            }\n            case 'npz': {\n                format = 'NumPy Archive';\n                const layers = new Map();\n                const entries = Array.from(context.value);\n                const separator = entries.every(([name]) => name.endsWith('.weight.npy')) ? '.' : '/';\n                for (const [key, array] of entries) {\n                    const name = key.replace(/\\.npy$/, '');\n                    const path = name.split(separator);\n                    const parameterName = path.pop();\n                    const groupName = path.join(separator);\n                    if (!layers.has(groupName)) {\n                        layers.set(groupName, { name: groupName, parameters: [] });\n                    }\n                    const layer = layers.get(groupName);\n                    layer.parameters.push({\n                        name: parameterName,\n                        tensor: { name, array }\n                    });\n                }\n                modules.push({ layers: Array.from(layers.values()) });\n                break;\n            }\n            default: {\n                throw new numpy.Error(`Unsupported NumPy format '${context.type}'.`);\n            }\n        }\n        return new numpy.Model(format, modules);\n    }\n};\n\nnumpy.Model = class {\n\n    constructor(format, modules) {\n        this.format = format;\n        this.modules = modules.map((module) => new numpy.Module(module));\n    }\n};\n\nnumpy.Module = class {\n\n    constructor(graph) {\n        this.name = graph.name || '';\n        this.nodes = graph.layers.map((layer) => new numpy.Node(layer));\n        this.inputs = [];\n        this.outputs = [];\n    }\n};\n\nnumpy.Argument = class {\n\n    constructor(name, value) {\n        this.name = name;\n        this.value = value;\n    }\n};\n\nnumpy.Value = class {\n\n    constructor(name, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new numpy.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer.type;\n        this.initializer = initializer;\n    }\n};\n\nnumpy.Node = class {\n\n    constructor(layer) {\n        this.name = layer.name || '';\n        this.type = { name: layer.type || 'Object' };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        for (const parameter of layer.parameters) {\n            const initializer = new numpy.Tensor(parameter.tensor.array);\n            const value = new numpy.Value(parameter.tensor.name || '', initializer);\n            const argument = new numpy.Argument(parameter.name, [value]);\n            this.inputs.push(argument);\n        }\n    }\n};\n\nnumpy.Tensor = class  {\n\n    constructor(array) {\n        this.type = new numpy.TensorType(array.dtype.__name__, new numpy.TensorShape(array.shape));\n        this.stride = array.strides.map((stride) => stride / array.itemsize);\n        const list = this.type.dataType === 'string' || this.type.dataType === 'object' || this.type.dataType === 'void';\n        this.values = list ? array.flatten().tolist() : array.tobytes();\n        this.encoding = list ? '|' : array.dtype.byteorder;\n    }\n};\n\nnumpy.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType || '?';\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nnumpy.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return this.dimensions && this.dimensions.length > 0 ? `[${this.dimensions.join(',')}]` : '';\n    }\n};\n\nnumpy.Utility = class {\n\n    static isTensor(obj) {\n        return obj && obj.__class__ &&\n            ((obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray') ||\n             (obj.__class__.__module__ === 'numpy.core.memmap' && obj.__class__.__name__ === 'memmap'));\n    }\n\n    static weights(obj) {\n        const dict = (obj, key) => {\n            const dict = key === '' ? obj : obj[key];\n            if (dict) {\n                const weights = new Map();\n                if (dict instanceof Map) {\n                    for (const [key, obj] of dict) {\n                        if (numpy.Utility.isTensor(obj)) {\n                            weights.set(key, obj);\n                            continue;\n                        } else if (obj instanceof Map && Array.from(obj).every(([, value]) => numpy.Utility.isTensor(value))) {\n                            for (const [name, value] of obj) {\n                                weights.set(`${key}.${name}`, value);\n                            }\n                            continue;\n                        } else if (key === '_metadata') {\n                            continue;\n                        }\n                        return null;\n                    }\n                    return weights;\n                } else if (!Array.isArray(dict)) {\n                    const set = new Set(['weight_order', 'lr', 'model_iter', '__class__']);\n                    for (const [name, value] of Object.entries(dict)) {\n                        if (numpy.Utility.isTensor(value)) {\n                            weights.set(name, value);\n                            continue;\n                        }\n                        if (set.has(name)) {\n                            continue;\n                        }\n                        if (value && !Array.isArray(value) && Object.entries(value).every(([, value]) => numpy.Utility.isTensor(value))) {\n                            if (value && value.__class__ && value.__class__.__module__ && value.__class__.__name__) {\n                                weights.set(`${name}.__class__`, `${value.__class__.__module__}.${value.__class__.__name__}`);\n                            }\n                            for (const [key, obj] of Object.entries(value)) {\n                                weights.set(`${name}.${key}`, obj);\n                            }\n                            continue;\n                        }\n                        return null;\n                    }\n                    return weights;\n                }\n            }\n            return null;\n        };\n        const list = (obj, key) => {\n            let list = key === '' ? obj : obj[key];\n            if (list && Array.isArray(list) && list.every((obj) => Object.values(obj).every((value) => numpy.Utility.isTensor(value)))) {\n                list = list.map((obj) => obj instanceof Map ? obj : new Map(Object.entries(obj)));\n            }\n            if (list && Array.isArray(list)) {\n                const weights = new Map();\n                for (let i = 0; i < list.length; i++) {\n                    const obj = list[i];\n                    if (numpy.Utility.isTensor(obj)) {\n                        weights.set(i.toString(), obj);\n                        continue;\n                    } else if (obj instanceof Map && Array.from(obj).every(([, value]) => numpy.Utility.isTensor(value))) {\n                        for (const [name, value] of obj) {\n                            weights.set(`${i}.${name}`, value);\n                        }\n                        continue;\n                    }\n                    return null;\n                }\n                return weights;\n            }\n            return null;\n        };\n        const keys = ['', 'blobs', 'model', 'experiment_state'];\n        for (const key of keys) {\n            const weights = dict(obj, key);\n            if (weights && weights.size > 0) {\n                return weights;\n            }\n        }\n        for (const key of keys) {\n            const weights = list(obj, key);\n            if (weights) {\n                return weights;\n            }\n        }\n        return null;\n    }\n};\n\nnumpy.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading NumPy model.';\n    }\n};\n\nexport const ModelFactory = numpy.ModelFactory;\n"
  },
  {
    "path": "source/om-metadata.json",
    "content": "[\n  {\n    \"name\": \"Acos\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Acosh\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Activation\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\", \"type\": \"Enum\", \"enum\": [   \"Sigmoid\",   \"ReLU\",   \"Tanh\",   \"Clipped ReLU\",   \"ELU\",   \"PReLU\",   \"Abs\",   \"Relu1\",   \"Softsign\",   \"Softplus\",   \"Hardsigmoid\",   \"Threshold ReLU\",   \"Selu\",   \"Linear\",   \"Relu6\",   \"GeLU\" ] },\n      { \"name\": \"coef\" },\n      { \"name\": \"negative_slope\" }\n    ]\n  },\n  {\n    \"name\": \"ReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Relu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Add\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"output_type\" },\n      { \"name\": \"outmaxval\" },\n      { \"name\": \"topk\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMaxExt2\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axis\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"output_type\" },\n      { \"name\": \"keep_dims\" },\n      { \"name\": \"outmaxval\" },\n      { \"name\": \"topk\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMin\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axis\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Asin\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Asinh\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Atan\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Atanh\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"AxisAlignedBboxTransform\",\n    \"inputs\": [\n      { \"name\": \"roi\" },\n      { \"name\": \"bbox_deltas\" },\n      { \"name\": \"batch_split\" },\n      { \"name\": \"im_info\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"BatchMatMul\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"adj_x1\" },\n      { \"name\": \"adj_x2\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"b\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"momentum\" },\n      { \"name\": \"epsilon\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"use_global_stats\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormExt2\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"offset\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"momentum\" },\n      { \"name\": \"epsilon\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"use_global_stats\" }\n    ]\n  },\n  {\n    \"name\": \"BatchReindex\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"reindex\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"BatchToSpaceND\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"block_shape\" },\n      { \"name\": \"crops\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Bias\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"BiasAdd\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"data_format\" }\n    ]\n  },\n  {\n    \"name\": \"BidirectionLSTM\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"seq_len\" },\n      { \"name\": \"w_fw\" },\n      { \"name\": \"w_bw\" },\n      { \"name\": \"c_0_fw\" },\n      { \"name\": \"h_0_fw\" },\n      { \"name\": \"c_0_bw\" },\n      { \"name\": \"h_0_bw\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y_fw\" },\n      { \"name\": \"y_bw\" },\n      { \"name\": \"h_t_fw\" },\n      { \"name\": \"c_t_fw\" },\n      { \"name\": \"h_t_bw\" },\n      { \"name\": \"c_t_bw\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"forget_bias\" },\n      { \"name\": \"num_layers\" },\n      { \"name\": \"activation\" },\n      { \"name\": \"cell_type\" },\n      { \"name\": \"state_is_tuple\" }\n    ]\n  },\n  {\n    \"name\": \"BNInference\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"offset\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"momentum\" },\n      { \"name\": \"epsilon\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"use_global_stats\" }\n    ]\n  },\n  {\n    \"name\": \"BNLL\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"BroadcastTo\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Cast\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"SrcT\" },\n      { \"name\": \"DstT\" }\n    ]\n  },\n  {\n    \"name\": \"CastT\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"src_dtype\" },\n      { \"name\": \"dst_dtype\" }\n    ]\n  },\n  {\n    \"name\": \"Ceil\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ChannelAxpy\",\n    \"inputs\": [\n      { \"name\": \"a\" },\n      { \"name\": \"x\" },\n      { \"name\": \"y\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"z\" }\n    ]\n  },\n  {\n    \"name\": \"ChannelShuffle\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"num_group\" }\n    ]\n  },\n  {\n    \"name\": \"Clip\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"clip_value_min\" },\n      { \"name\": \"clip_value_max\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Clipboxes\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"im_info\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ClipByValue\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"clip_value_min\" },\n      { \"name\": \"clip_value_max\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ConcatD\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ConcatV2D\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Const\",\n    \"category\": \"Constant\",\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"value\" }\n    ]\n  },\n  {\n    \"name\": \"Conv2D\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"DepthwiseConv2D\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"offset_w\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\" },\n      { \"name\": \"dilations\" },\n      { \"name\": \"pads\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"data_format\" },\n      { \"name\": \"offset_x\" },\n      { \"name\": \"mode\", \"type\": \"Enum\", \"enum\": [   \"Convolution\",   \"Cross Correlation\",   \"Deconvolution\",   \"Depthwise\" ] },\n      { \"name\": \"algo\", \"type\": \"Enum\", \"enum\": [   \"GEMM\",   \"Winograd\",   \"GEMM_ACCU_Float32\" ] }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionDepthwise\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"offset_w\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\" },\n      { \"name\": \"dilations\" },\n      { \"name\": \"pads\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"data_format\" },\n      { \"name\": \"offset_x\" }\n    ]\n  },\n  {\n    \"name\": \"ConvTranspose\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"output_shape\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"x\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"offset_w\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\" },\n      { \"name\": \"pads\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"dilations\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"data_format\" },\n      { \"name\": \"offset_x\" }\n    ]\n  },\n  {\n    \"name\": \"Copy\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Cos\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Cosh\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Crop\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"offsets\" }\n    ]\n  },\n  {\n    \"name\": \"CropAndResize\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"boxes\" },\n      { \"name\": \"box_index\" },\n      { \"name\": \"crop_size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"extrapolation_value\" },\n      { \"name\": \"method\" }\n    ]\n  },\n  {\n    \"name\": \"Cumprod\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axis\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\" },\n      { \"name\": \"reverse\" }\n    ]\n  },\n  {\n    \"name\": \"Cumsum\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axis\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"exclusive\" },\n      { \"name\": \"reverse\" }\n    ]\n  },\n  {\n    \"name\": \"Data\",\n    \"category\": \"Data\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"index\" }\n    ]\n  },\n  {\n    \"name\": \"DecodeBBox\",\n    \"inputs\": [\n      { \"name\": \"box_predictions\" },\n      { \"name\": \"anchors\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"decoded_boxes\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"decode_clip\" }\n    ]\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input_sizes\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\" },\n      { \"name\": \"num_output\" },\n      { \"name\": \"pad\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"dilation\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"Padding\" },\n      { \"name\": \"bias_term\" },\n      { \"name\": \"kernel\" }\n    ]\n  },\n  {\n    \"name\": \"DepthToSpace\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\" },\n      { \"name\": \"mode\" },\n      { \"name\": \"data_format\" }\n    ]\n  },\n  {\n    \"name\": \"Dequantize\",\n    \"category\": \"Quantization\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"min_range\" },\n      { \"name\": \"max_range\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\" }\n    ]\n  },\n  {\n    \"name\": \"DetectionPostprocessing\",\n    \"inputs\": [\n      { \"name\": \"score\" },\n      { \"name\": \"bbox_delta\" },\n      { \"name\": \"anchors\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"detect_scores\" },\n      { \"name\": \"rois\" },\n      { \"name\": \"detect_class\" },\n      { \"name\": \"actual_rois_num\" }\n    ]\n  },\n  {\n    \"name\": \"DynamicImageData\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_src_image_size\" },\n      { \"name\": \"image_type\" }\n    ]\n  },\n  {\n    \"name\": \"Eltwise\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"N\" },\n      { \"name\": \"mode\", \"type\": \"Enum\", \"enum\": [ \"Product\", \"Sum\", \"Max\" ] },\n      { \"name\": \"coeff\" }\n    ]\n  },\n  {\n    \"name\": \"Elu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Equal\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Erf\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Exp\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"base\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"shift\" }\n    ]\n  },\n  {\n    \"name\": \"ExpandDims\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axis\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Expm1\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ExtractImagePatches\",\n    \"inputs\": [\n      { \"name\": \"images\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"ksizes\" },\n      { \"name\": \"strides\" },\n      { \"name\": \"rates\" },\n      { \"name\": \"padding\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantWithMinMaxVars\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"min\" },\n      { \"name\": \"max\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_bits\" },\n      { \"name\": \"narrow_range\" }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantWithMinMaxVarsPerChannel\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"min\" },\n      { \"name\": \"max\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_bits\" },\n      { \"name\": \"narrow_range\" }\n    ]\n  },\n  {\n    \"name\": \"Fc\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Fill\",\n    \"inputs\": [\n      { \"name\": \"dims\" },\n      { \"name\": \"value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Flatten\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"FlattenV2\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"end_axis\" }\n    ]\n  },\n  {\n    \"name\": \"Floor\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"FloorDiv\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"FloorMod\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"FractionalPooling\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" },\n      { \"name\": \"row_pooling_sequence\" },\n      { \"name\": \"col_pooling_sequence\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\" },\n      { \"name\": \"pooling_ratio\" },\n      { \"name\": \"pseudo_random\" },\n      { \"name\": \"overlapping\" },\n      { \"name\": \"deterministic\" },\n      { \"name\": \"seed\" },\n      { \"name\": \"seed2\" }\n    ]\n  },\n  {\n    \"name\": \"FSRDetectionOutput\",\n    \"inputs\": [\n      { \"name\": \"rois\" },\n      { \"name\": \"bbox_delta\" },\n      { \"name\": \"score\" },\n      { \"name\": \"im_info\" },\n      { \"name\": \"actual_rois_num\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"actual_bbox_num\" },\n      { \"name\": \"box\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_classes\" },\n      { \"name\": \"score_threshold\" },\n      { \"name\": \"iou_threshold\" },\n      { \"name\": \"batch_rois\" }\n    ]\n  },\n  {\n    \"name\": \"FullConnection\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"w\" },\n      { \"name\": \"b\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_output\" }\n    ]\n  },\n  {\n    \"name\": \"FullyConnection\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"X\" },\n      { \"name\": \"W\" },\n      { \"name\": \"B\" },\n      { \"name\": \"offset_w\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"Y\" }\n    ]\n  },\n  {\n    \"name\": \"Gather\",\n    \"inputs\": [\n      { \"name\": \"params\" },\n      { \"name\": \"indices\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"GatherNd\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"indices\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"GatherV2D\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"indices\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"GemmD\",\n    \"inputs\": [\n      { \"name\": \"a\" },\n      { \"name\": \"b\" },\n      { \"name\": \"c\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"alpha\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"transpose_a\" },\n      { \"name\": \"transpose_b\" }\n    ]\n  },\n  {\n    \"name\": \"GraphOp\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Greater\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"GreaterEqual\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"HardSwish\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"HeatmapMaxKeypoint\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y1\" },\n      { \"name\": \"y2\" }\n    ]\n  },\n  {\n    \"name\": \"ImageChannelSwap\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rbuv_swap_switch\" },\n      { \"name\": \"ax_swap_switch\" }\n    ]\n  },\n  {\n    \"name\": \"ImageColorSpaceConvertion\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"target_format\" }\n    ]\n  },\n  {\n    \"name\": \"ImageCrop\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"load_start_pos_h\" },\n      { \"name\": \"load_start_pos_w\" },\n      { \"name\": \"crop_size_h\" },\n      { \"name\": \"crop_size_w\" }\n    ]\n  },\n  {\n    \"name\": \"ImageData\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"input_format\" },\n      { \"name\": \"src_image_size_w\" },\n      { \"name\": \"src_image_size_h\" },\n      { \"name\": \"image_type\" }\n    ]\n  },\n  {\n    \"name\": \"ImageDataTypeConversion\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mean_chn_0\" },\n      { \"name\": \"mean_chn_1\" },\n      { \"name\": \"mean_chn_2\" },\n      { \"name\": \"mean_chn_3\" },\n      { \"name\": \"min_chn_0\" },\n      { \"name\": \"min_chn_1\" },\n      { \"name\": \"min_chn_2\" },\n      { \"name\": \"min_chn_3\" },\n      { \"name\": \"var_reci_chn_0\" },\n      { \"name\": \"var_reci_chn_1\" },\n      { \"name\": \"var_reci_chn_2\" },\n      { \"name\": \"var_reci_chn_3\" }\n    ]\n  },\n  {\n    \"name\": \"ImagePadding\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"left_padding_size\" },\n      { \"name\": \"right_padding_size\" },\n      { \"name\": \"top_padding_size\" },\n      { \"name\": \"bottom_padding_size\" }\n    ]\n  },\n  {\n    \"name\": \"ImageResize\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"resize_output_h\" },\n      { \"name\": \"resize_output_w\" }\n    ]\n  },\n  {\n    \"name\": \"ImageRotation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rotation_angle\" }\n    ]\n  },\n  {\n    \"name\": \"InstanceNorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" },\n      { \"name\": \"saved_mean\" },\n      { \"name\": \"saved_inv_stdev\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"data_format\" },\n      { \"name\": \"epsilon\" }\n    ]\n  },\n  {\n    \"name\": \"Interp\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"InvertPermutation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"L2Normalize\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"eps\" }\n    ]\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_norm_axis\" },\n      { \"name\": \"begin_params_axis\" },\n      { \"name\": \"epsilon\" }\n    ]\n  },\n  {\n    \"name\": \"Less\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LessEqual\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Log\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Log1p\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalAnd\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalNot\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalOr\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LogicalXor\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"LogSoftmax\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"depth_radius\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"alpha\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"norm_region\" }\n    ]\n  },\n  {\n    \"name\": \"LSTM\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"cont\" },\n      { \"name\": \"w_x\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"w_h\" },\n      { \"name\": \"x_static\" },\n      { \"name\": \"h_0\" },\n      { \"name\": \"c_0\" },\n      { \"name\": \"w_x_static\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"h\" },\n      { \"name\": \"h_t\" },\n      { \"name\": \"c_t\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"expose_hidden\" }\n    ]\n  },\n  {\n    \"name\": \"MatMul\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_x1\" },\n      { \"name\": \"transpose_x2\" }\n    ]\n  },\n  {\n    \"name\": \"Maximum\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"MaxPool\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"MaxPoolV3\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"AvgPool\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Minimum\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"MirrorPad\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"paddings\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\" }\n    ]\n  },\n  {\n    \"name\": \"Mish\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"MsrGenerateRpnProposals\",\n    \"inputs\": [\n      { \"name\": \"scores\" },\n      { \"name\": \"boxes\" },\n      { \"name\": \"img_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"proposal_scores\" },\n      { \"name\": \"proposal_boxes\" },\n      { \"name\": \"proposal_num\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pre_nms_topk\" },\n      { \"name\": \"post_nums_topk\" },\n      { \"name\": \"rpn_mini_size\" },\n      { \"name\": \"rpn_proposal_nms_thresh\" }\n    ]\n  },\n  {\n    \"name\": \"Mul\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Multinomial\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"num_samples\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seed\" },\n      { \"name\": \"seed2\" }\n    ]\n  },\n  {\n    \"name\": \"MVN\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"normalizeVariance\" },\n      { \"name\": \"acrossChannel\" }\n    ]\n  },\n  {\n    \"name\": \"Neg\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"NetOutput\",\n    \"category\": \"Data\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"NonMaxSuppression\",\n    \"inputs\": [\n      { \"name\": \"boxes\" },\n      { \"name\": \"scores\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_output_size\" },\n      { \"name\": \"iou_threshold\" },\n      { \"name\": \"score_threshold\" }\n    ]\n  },\n  {\n    \"name\": \"NonMaxSuppressionV3D\",\n    \"inputs\": [\n      { \"name\": \"boxes\" },\n      { \"name\": \"scores\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"max_output_size\" },\n      { \"name\": \"iou_threshold\" },\n      { \"name\": \"score_threshold\" }\n    ]\n  },\n  {\n    \"name\": \"NonMaxSuppressionV6\",\n    \"inputs\": [\n      { \"name\": \"boxes\" },\n      { \"name\": \"scores\" },\n      { \"name\": \"max_output_boxes_per_class\" },\n      { \"name\": \"iou_threshold\" },\n      { \"name\": \"score_threshold\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"selected_indices\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"center_point_box\" }\n    ]\n  },\n  {\n    \"name\": \"Normalize\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"across_spatial\" },\n      { \"name\": \"channel_shared\" },\n      { \"name\": \"eps\" }\n    ]\n  },\n  {\n    \"name\": \"NotEqual\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"OneHot\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"depth\" },\n      { \"name\": \"on_value\" },\n      { \"name\": \"off_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"Pack\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"N\" }\n    ]\n  },\n  {\n    \"name\": \"Pad\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"paddings\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"PadV2\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"paddings\" },\n      { \"name\": \"constant_values\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Permute\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"global_pooling\" },\n      { \"name\": \"window\" },\n      { \"name\": \"pad\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"ceil_mode\" },\n      { \"name\": \"data_mode\" }\n    ]\n  },\n  {\n    \"name\": \"PoolingAve\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"PoolingD\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"global_pooling\" },\n      { \"name\": \"window\" },\n      { \"name\": \"pad\" },\n      { \"name\": \"stride\" },\n      { \"name\": \"ceil_mode\" },\n      { \"name\": \"data_mode\" }\n    ]\n  },\n  {\n    \"name\": \"PoolingMax\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Pow\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Power\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\" },\n      { \"name\": \"shift\" },\n      { \"name\": \"power\" }\n    ]\n  },\n  {\n    \"name\": \"PRelu\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"weight\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"PReLU\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"param\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"PriorBox\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"img\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Proposal\",\n    \"inputs\": [\n      { \"name\": \"cls_prob\" },\n      { \"name\": \"bbox_pred\" },\n      { \"name\": \"im_info\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"rois\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"feat_stride\" },\n      { \"name\": \"base_size\" },\n      { \"name\": \"min_size\" },\n      { \"name\": \"ratio\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"pre_nms_topn\" },\n      { \"name\": \"post_nms_topn\" },\n      { \"name\": \"nms_thresh\" }\n    ]\n  },\n  {\n    \"name\": \"PSROIPooling\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"rois\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"spatial_scale\" },\n      { \"name\": \"output_dim\" },\n      { \"name\": \"group_size\" }\n    ]\n  },\n  {\n    \"name\": \"Quantize\",\n    \"category\": \"Quantization\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"min_range\" },\n      { \"name\": \"max_range\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"mode\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizedConvolution\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\" },\n      { \"name\": \"dilations\" },\n      { \"name\": \"pads\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"groups\" },\n      { \"name\": \"data_format\" },\n      { \"name\": \"x_quant_type\" },\n      { \"name\": \"filter_quant_type\" },\n      { \"name\": \"x_quant_scale\" },\n      { \"name\": \"x_quant_offset\" },\n      { \"name\": \"filter_quant_scales\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizedConvolutionDepthwise\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"strides\" },\n      { \"name\": \"dilations\" },\n      { \"name\": \"pads\" },\n      { \"name\": \"pad_mode\", \"type\": \"Padding\" },\n      { \"name\": \"data_format\" },\n      { \"name\": \"x_quant_type\" },\n      { \"name\": \"filter_quant_type\" },\n      { \"name\": \"x_quant_scale\" },\n      { \"name\": \"x_quant_offset\" },\n      { \"name\": \"filter_quant_scales\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizedFullConnection\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"filter\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_output\" },\n      { \"name\": \"x_quant_type\" },\n      { \"name\": \"filter_quant_type\" },\n      { \"name\": \"x_quant_scale\" },\n      { \"name\": \"x_quant_offset\" },\n      { \"name\": \"filter_quant_scales\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizedFullyConnection\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"w\" },\n      { \"name\": \"b\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_output\" },\n      { \"name\": \"transpose\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"x_quant_type\" },\n      { \"name\": \"w_quant_type\" },\n      { \"name\": \"x_quant_scale\" },\n      { \"name\": \"x_quant_offset\" },\n      { \"name\": \"w_quant_scales\" }\n    ]\n  },\n  {\n    \"name\": \"QuantizedMatMul\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"transpose_x1\" },\n      { \"name\": \"transpose_x2\" },\n      { \"name\": \"x1_quant_type\" },\n      { \"name\": \"x2_quant_type\" },\n      { \"name\": \"x1_quant_scale\" },\n      { \"name\": \"x1_quant_offset\" },\n      { \"name\": \"x2_quant_scales\" }\n    ]\n  },\n  {\n    \"name\": \"RandomNormal\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"stddev\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RandomNormalNoSeed\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"stddev\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RandomShuffle\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RandomShuffleNoSeed\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RandomUniform\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"minval\" },\n      { \"name\": \"maxval\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RandomUniformInt\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"minval\" },\n      { \"name\": \"maxval\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RandomUniformNoSeed\",\n    \"inputs\": [\n      { \"name\": \"shape\" },\n      { \"name\": \"minval\" },\n      { \"name\": \"maxval\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Range\",\n    \"inputs\": [\n      { \"name\": \"start\" },\n      { \"name\": \"limit\" },\n      { \"name\": \"delta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Rank\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"RealDiv\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Reciprocal\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceAll\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\" },\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceAllD\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\" },\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceAny\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axes\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceL2D\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\" },\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceLogSumExp\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\" },\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceMax\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axes\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceMean\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axes\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceMin\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axes\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceProd\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" },\n      { \"name\": \"axes\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceProdD\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axes\" },\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceSum\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axes\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"keep_dims\" }\n    ]\n  },\n  {\n    \"name\": \"Reduction\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"operation\" },\n      { \"name\": \"axis\" },\n      { \"name\": \"coeff\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeBilinear\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeBilinearV2\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\" },\n      { \"name\": \"half_pixel_centers\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeNearestNeighbor\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\" }\n    ]\n  },\n  {\n    \"name\": \"ResizeNearestNeighborV2\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"align_corners\" },\n      { \"name\": \"half_pixel_centers\" }\n    ]\n  },\n  {\n    \"name\": \"Reverse\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"axis\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ReverseSequence\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"seq_lengths\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"seq_dim\" },\n      { \"name\": \"batch_dim\" }\n    ]\n  },\n  {\n    \"name\": \"Rint\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ROIAlignV2\",\n    \"inputs\": [\n      { \"name\": \"features\" },\n      { \"name\": \"rois\" },\n      { \"name\": \"rois_n\" },\n      { \"name\": \"batch_indices\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"spatial_scale\" },\n      { \"name\": \"pooled_height\" },\n      { \"name\": \"pooled_width\" },\n      { \"name\": \"sample_num\" },\n      { \"name\": \"roi_end_mode\" },\n      { \"name\": \"mode\" }\n    ]\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"category\": \"Pool\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"rois\" },\n      { \"name\": \"roi_actual_num\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pooled_h\" },\n      { \"name\": \"pooled_w\" },\n      { \"name\": \"spatial_scale_h\" },\n      { \"name\": \"spatial_scale_w\" }\n    ]\n  },\n  {\n    \"name\": \"Round\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Rsqrt\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Scale\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"scale\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"num_axes\" },\n      { \"name\": \"scale_from_blob\" }\n    ]\n  },\n  {\n    \"name\": \"ScatterNd\",\n    \"inputs\": [\n      { \"name\": \"indices\" },\n      { \"name\": \"x\" },\n      { \"name\": \"shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"ScatterUpdate\",\n    \"inputs\": [\n      { \"name\": \"var\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"updates\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"var\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"use_locking\" },\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"SegmentMax\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"segment_ids\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SegmentMean\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"segment_ids\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SegmentMin\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"segment_ids\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SegmentProd\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"segment_ids\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SegmentSum\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"segment_ids\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Select\",\n    \"inputs\": [\n      { \"name\": \"condition\" },\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\" }\n    ]\n  },\n  {\n    \"name\": \"ShuffleChannel\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"group\" }\n    ]\n  },\n  {\n    \"name\": \"ShuffleChannelV2\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"group\" }\n    ]\n  },\n  {\n    \"name\": \"Sign\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Sin\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Sinh\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Size\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"dtype\" }\n    ]\n  },\n  {\n    \"name\": \"Slice\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"offsets\" },\n      { \"name\": \"size\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Softmax\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SoftmaxV2\",\n    \"category\": \"Activation\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SpaceToBatchND\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"block_shape\" },\n      { \"name\": \"paddings\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SpaceToDepth\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"block_size\" },\n      { \"name\": \"data_format\" }\n    ]\n  },\n  {\n    \"name\": \"SparseToDense\",\n    \"inputs\": [\n      { \"name\": \"indices\" },\n      { \"name\": \"output_shape\" },\n      { \"name\": \"values\" },\n      { \"name\": \"default_value\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Split\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" },\n      { \"name\": \"output_num\" },\n      { \"name\": \"slice_point\" },\n      { \"name\": \"size_split\" }\n    ]\n  },\n  {\n    \"name\": \"SplitD\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"split_dim\" },\n      { \"name\": \"num_split\" }\n    ]\n  },\n  {\n    \"name\": \"SplitV\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"size_splits\" },\n      { \"name\": \"split_dim\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_split\" }\n    ]\n  },\n  {\n    \"name\": \"SPP\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"pyramidHeight\" },\n      { \"name\": \"poolingMode\" }\n    ]\n  },\n  {\n    \"name\": \"Sqrt\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Square\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SquaredDifference\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"SSDDetectionOutput\",\n    \"inputs\": [\n      { \"name\": \"mbox_conf\" },\n      { \"name\": \"mbox_loc\" },\n      { \"name\": \"mbox_priorbox\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"out_boxnum\" },\n      { \"name\": \"regionProposal\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num_classes\" },\n      { \"name\": \"shared_location\" },\n      { \"name\": \"background_label_id\" },\n      { \"name\": \"nms_threshold\" },\n      { \"name\": \"top_k\" },\n      { \"name\": \"eta\" },\n      { \"name\": \"variance_encoded_in_target\" },\n      { \"name\": \"code_type\" },\n      { \"name\": \"keep_top_k\" },\n      { \"name\": \"confidence_threshold\" }\n    ]\n  },\n  {\n    \"name\": \"StopGradient\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSlice\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"end\" },\n      { \"name\": \"strides\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\" },\n      { \"name\": \"end_mask\" },\n      { \"name\": \"ellipsis_mask\" },\n      { \"name\": \"new_axis_mask\" },\n      { \"name\": \"shrink_axis_mask\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSliceD\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSliceV2\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"end\" },\n      { \"name\": \"axes\" },\n      { \"name\": \"strides\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"begin_mask\" },\n      { \"name\": \"end_mask\" },\n      { \"name\": \"ellipsis_mask\" },\n      { \"name\": \"new_axis_mask\" },\n      { \"name\": \"shrink_axis_mask\" }\n    ]\n  },\n  {\n    \"name\": \"Sub\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"SVDF\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"weights_feature\" },\n      { \"name\": \"weights_time\" },\n      { \"name\": \"bias\" },\n      { \"name\": \"state_in\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"state_out\" },\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"rank\" },\n      { \"name\": \"use_bias\" }\n    ]\n  },\n  {\n    \"name\": \"Swish\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"scale\" }\n    ]\n  },\n  {\n    \"name\": \"Tan\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"TensorArray\",\n    \"inputs\": [\n      { \"name\": \"data\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"handle\" },\n      { \"name\": \"flow\" },\n      { \"name\": \"memory\" }\n    ]\n  },\n  {\n    \"name\": \"TensorArrayGather\",\n    \"inputs\": [\n      { \"name\": \"handle\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"flow_in\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"flow\" }\n    ]\n  },\n  {\n    \"name\": \"TensorArrayScatter\",\n    \"inputs\": [\n      { \"name\": \"handle\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"value\" },\n      { \"name\": \"flow_in\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"flow\" }\n    ]\n  },\n  {\n    \"name\": \"Threshold\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"threshold\" }\n    ]\n  },\n  {\n    \"name\": \"Tile\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"multiples\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"TopK\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"k\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"values\" },\n      { \"name\": \"indices\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"sorted\" }\n    ]\n  },\n  {\n    \"name\": \"TransData\",\n    \"category\": \"Shape\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Transpose\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"w\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"order\" }\n    ]\n  },\n  {\n    \"name\": \"TruncateDiv\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"TruncateMod\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Undefined\",\n    \"inputs\": [\n      { \"name\": \"input\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Unpack\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"num\" },\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"UnsortedSegmentSum\",\n    \"inputs\": [\n      { \"name\": \"x\" },\n      { \"name\": \"segment_ids\" },\n      { \"name\": \"num_segments\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  },\n  {\n    \"name\": \"Upsample\",\n    \"category\": \"Data\",\n    \"inputs\": [\n      { \"name\": \"x\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ],\n    \"attributes\": [\n      { \"name\": \"stride_h\" },\n      { \"name\": \"stride_w\" },\n      { \"name\": \"scale\" }\n    ]\n  },\n  {\n    \"name\": \"Xlogy\",\n    \"inputs\": [\n      { \"name\": \"x1\" },\n      { \"name\": \"x2\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"y\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/om-proto.js",
    "content": "\nexport const ge = {};\n\nge.proto = {};\n\nge.proto.DataType = {\n    \"DT_UNDEFINED\": 0,\n    \"DT_FLOAT\": 1,\n    \"DT_FLOAT16\": 2,\n    \"DT_INT8\": 3,\n    \"DT_UINT8\": 4,\n    \"DT_INT16\": 5,\n    \"DT_UINT16\": 6,\n    \"DT_INT32\": 7,\n    \"DT_INT64\": 8,\n    \"DT_UINT32\": 9,\n    \"DT_UINT64\": 10,\n    \"DT_BOOL\": 11,\n    \"DT_DOUBLE\": 12,\n    \"DT_STRING\": 13,\n    \"DT_DUAL_SUB_INT8\": 14,\n    \"DT_DUAL_SUB_UINT8\": 15,\n    \"DT_COMPLEX64\": 16,\n    \"DT_COMPLEX128\": 17,\n    \"DT_QINT8\": 18,\n    \"DT_QINT16\": 19,\n    \"DT_QINT32\": 20,\n    \"DT_QUINT8\": 21,\n    \"DT_QUINT16\": 22,\n    \"DT_RESOURCE\": 23,\n    \"DT_STRING_REF\": 24,\n    \"DT_DUAL\": 25,\n    \"DT_VARIANT\": 26,\n    \"DT_BF16\": 27,\n    \"DT_INT4\": 28,\n    \"DT_UINT1\": 29,\n    \"DT_INT2\": 30,\n    \"DT_UINT2\": 31\n};\n\nge.proto.AttrDef = class AttrDef {\n\n    get value() {\n        ge.proto.AttrDef.valueSet = ge.proto.AttrDef.valueSet || new Set([\"s\", \"i\", \"f\", \"b\", \"bt\", \"list\", \"func\", \"td\", \"t\", \"g\", \"list_list_int\", \"dt\", \"list_list_float\"]);\n        return Object.keys(this).find((key) => ge.proto.AttrDef.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.AttrDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.s = reader.bytes();\n                    break;\n                case 3:\n                    message.i = reader.int64();\n                    break;\n                case 4:\n                    message.f = reader.float();\n                    break;\n                case 5:\n                    message.b = reader.bool();\n                    break;\n                case 7:\n                    message.bt = reader.bytes();\n                    break;\n                case 1:\n                    message.list = ge.proto.AttrDef.ListValue.decode(reader, reader.uint32());\n                    break;\n                case 10:\n                    message.func = ge.proto.NamedAttrs.decode(reader, reader.uint32());\n                    break;\n                case 11:\n                    message.td = ge.proto.TensorDescriptor.decode(reader, reader.uint32());\n                    break;\n                case 12:\n                    message.t = ge.proto.TensorDef.decode(reader, reader.uint32());\n                    break;\n                case 13:\n                    message.g = ge.proto.GraphDef.decode(reader, reader.uint32());\n                    break;\n                case 14:\n                    message.list_list_int = ge.proto.AttrDef.ListListInt.decode(reader, reader.uint32());\n                    break;\n                case 15:\n                    message.dt = reader.int64();\n                    break;\n                case 16:\n                    message.list_list_float = ge.proto.AttrDef.ListListFloat.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.AttrDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"s\":\n                    message.s = reader.bytes();\n                    break;\n                case \"i\":\n                    message.i = reader.int64();\n                    break;\n                case \"f\":\n                    message.f = reader.float();\n                    break;\n                case \"b\":\n                    message.b = reader.bool();\n                    break;\n                case \"bt\":\n                    message.bt = reader.bytes();\n                    break;\n                case \"list\":\n                    message.list = ge.proto.AttrDef.ListValue.decodeText(reader);\n                    break;\n                case \"func\":\n                    message.func = ge.proto.NamedAttrs.decodeText(reader);\n                    break;\n                case \"td\":\n                    message.td = ge.proto.TensorDescriptor.decodeText(reader);\n                    break;\n                case \"t\":\n                    message.t = ge.proto.TensorDef.decodeText(reader);\n                    break;\n                case \"g\":\n                    message.g = ge.proto.GraphDef.decodeText(reader);\n                    break;\n                case \"list_list_int\":\n                    message.list_list_int = ge.proto.AttrDef.ListListInt.decodeText(reader);\n                    break;\n                case \"dt\":\n                    message.dt = reader.int64();\n                    break;\n                case \"list_list_float\":\n                    message.list_list_float = ge.proto.AttrDef.ListListFloat.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.AttrDef.ListValue = class ListValue {\n\n    constructor() {\n        this.s = [];\n        this.i = [];\n        this.f = [];\n        this.b = [];\n        this.bt = [];\n        this.td = [];\n        this.t = [];\n        this.g = [];\n        this.na = [];\n        this.dt = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.AttrDef.ListValue();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 2:\n                    message.s.push(reader.bytes());\n                    break;\n                case 3:\n                    message.i = reader.array(message.i, () => reader.int64(), tag);\n                    break;\n                case 4:\n                    message.f = reader.floats(message.f, tag);\n                    break;\n                case 5:\n                    message.b = reader.array(message.b, () => reader.bool(), tag);\n                    break;\n                case 7:\n                    message.bt.push(reader.bytes());\n                    break;\n                case 8:\n                    message.td.push(ge.proto.TensorDescriptor.decode(reader, reader.uint32()));\n                    break;\n                case 9:\n                    message.t.push(ge.proto.TensorDef.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.g.push(ge.proto.GraphDef.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    message.na.push(ge.proto.NamedAttrs.decode(reader, reader.uint32()));\n                    break;\n                case 12:\n                    message.dt = reader.array(message.dt, () => reader.int64(), tag);\n                    break;\n                case 20:\n                    message.val_type = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.AttrDef.ListValue();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"s\":\n                    reader.array(message.s, () => reader.bytes());\n                    break;\n                case \"i\":\n                    reader.array(message.i, () => reader.int64());\n                    break;\n                case \"f\":\n                    reader.array(message.f, () => reader.float());\n                    break;\n                case \"b\":\n                    reader.array(message.b, () => reader.bool());\n                    break;\n                case \"bt\":\n                    reader.array(message.bt, () => reader.bytes());\n                    break;\n                case \"td\":\n                    message.td.push(ge.proto.TensorDescriptor.decodeText(reader));\n                    break;\n                case \"t\":\n                    message.t.push(ge.proto.TensorDef.decodeText(reader));\n                    break;\n                case \"g\":\n                    message.g.push(ge.proto.GraphDef.decodeText(reader));\n                    break;\n                case \"na\":\n                    message.na.push(ge.proto.NamedAttrs.decodeText(reader));\n                    break;\n                case \"dt\":\n                    reader.array(message.dt, () => reader.int64());\n                    break;\n                case \"val_type\":\n                    message.val_type = reader.enum(ge.proto.AttrDef.ListValue.ListValueType);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.AttrDef.ListValue.prototype.val_type = 0;\n\nge.proto.AttrDef.ListValue.ListValueType = {\n    \"VT_LIST_NONE\": 0,\n    \"VT_LIST_STRING\": 1,\n    \"VT_LIST_INT\": 2,\n    \"VT_LIST_FLOAT\": 3,\n    \"VT_LIST_BOOL\": 4,\n    \"VT_LIST_BYTES\": 5,\n    \"VT_LIST_TENSOR_DESC\": 6,\n    \"VT_LIST_TENSOR\": 7,\n    \"VT_LIST_GRAPH\": 8,\n    \"VT_LIST_NAMED_ATTRS\": 9,\n    \"VT_LIST_DATA_TYPE\": 10\n};\n\nge.proto.AttrDef.ListListInt = class ListListInt {\n\n    constructor() {\n        this.list_list_i = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.AttrDef.ListListInt();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.list_list_i.push(ge.proto.AttrDef.ListListInt.ListInt.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.AttrDef.ListListInt();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"list_list_i\":\n                    message.list_list_i.push(ge.proto.AttrDef.ListListInt.ListInt.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.AttrDef.ListListInt.ListInt = class ListInt {\n\n    constructor() {\n        this.list_i = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.AttrDef.ListListInt.ListInt();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.list_i = reader.array(message.list_i, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.AttrDef.ListListInt.ListInt();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"list_i\":\n                    reader.array(message.list_i, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.AttrDef.ListListFloat = class ListListFloat {\n\n    constructor() {\n        this.list_list_f = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.AttrDef.ListListFloat();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.list_list_f.push(ge.proto.AttrDef.ListListFloat.ListFloat.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.AttrDef.ListListFloat();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"list_list_f\":\n                    message.list_list_f.push(ge.proto.AttrDef.ListListFloat.ListFloat.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.AttrDef.ListListFloat.ListFloat = class ListFloat {\n\n    constructor() {\n        this.list_f = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.AttrDef.ListListFloat.ListFloat();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.list_f = reader.floats(message.list_f, tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.AttrDef.ListListFloat.ListFloat();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"list_f\":\n                    reader.array(message.list_f, () => reader.float());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.NamedAttrs = class NamedAttrs {\n\n    constructor() {\n        this.attr = {};\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.NamedAttrs();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.NamedAttrs();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"attr\":\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.NamedAttrs.prototype.name = \"\";\n\nge.proto.ShapeDef = class ShapeDef {\n\n    constructor() {\n        this.dim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.ShapeDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim = reader.array(message.dim, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.ShapeDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim\":\n                    reader.array(message.dim, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.TensorDescriptor = class TensorDescriptor {\n\n    constructor() {\n        this.attr = {};\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.TensorDescriptor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.dtype = reader.int32();\n                    break;\n                case 3:\n                    message.shape = ge.proto.ShapeDef.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.layout = reader.string();\n                    break;\n                case 9:\n                    message.has_out_attr = reader.bool();\n                    break;\n                case 10:\n                    message.size = reader.int64();\n                    break;\n                case 11:\n                    message.weight_size = reader.int64();\n                    break;\n                case 12:\n                    message.reuse_input = reader.bool();\n                    break;\n                case 13:\n                    message.output_tensor = reader.bool();\n                    break;\n                case 14:\n                    message.device_type = reader.string();\n                    break;\n                case 15:\n                    message.input_tensor = reader.bool();\n                    break;\n                case 16:\n                    message.real_dim_cnt = reader.int64();\n                    break;\n                case 17:\n                    message.reuse_input_index = reader.int64();\n                    break;\n                case 18:\n                    message.data_offset = reader.int64();\n                    break;\n                case 19:\n                    message.cmps_size = reader.int64();\n                    break;\n                case 20:\n                    message.cmps_tab = reader.string();\n                    break;\n                case 21:\n                    message.cmps_tab_offset = reader.int64();\n                    break;\n                case 5:\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.TensorDescriptor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"dtype\":\n                    message.dtype = reader.enum(ge.proto.DataType);\n                    break;\n                case \"shape\":\n                    message.shape = ge.proto.ShapeDef.decodeText(reader);\n                    break;\n                case \"layout\":\n                    message.layout = reader.string();\n                    break;\n                case \"has_out_attr\":\n                    message.has_out_attr = reader.bool();\n                    break;\n                case \"size\":\n                    message.size = reader.int64();\n                    break;\n                case \"weight_size\":\n                    message.weight_size = reader.int64();\n                    break;\n                case \"reuse_input\":\n                    message.reuse_input = reader.bool();\n                    break;\n                case \"output_tensor\":\n                    message.output_tensor = reader.bool();\n                    break;\n                case \"device_type\":\n                    message.device_type = reader.string();\n                    break;\n                case \"input_tensor\":\n                    message.input_tensor = reader.bool();\n                    break;\n                case \"real_dim_cnt\":\n                    message.real_dim_cnt = reader.int64();\n                    break;\n                case \"reuse_input_index\":\n                    message.reuse_input_index = reader.int64();\n                    break;\n                case \"data_offset\":\n                    message.data_offset = reader.int64();\n                    break;\n                case \"cmps_size\":\n                    message.cmps_size = reader.int64();\n                    break;\n                case \"cmps_tab\":\n                    message.cmps_tab = reader.string();\n                    break;\n                case \"cmps_tab_offset\":\n                    message.cmps_tab_offset = reader.int64();\n                    break;\n                case \"attr\":\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.TensorDescriptor.prototype.name = \"\";\nge.proto.TensorDescriptor.prototype.dtype = 0;\nge.proto.TensorDescriptor.prototype.shape = null;\nge.proto.TensorDescriptor.prototype.layout = \"\";\nge.proto.TensorDescriptor.prototype.has_out_attr = false;\nge.proto.TensorDescriptor.prototype.size = 0n;\nge.proto.TensorDescriptor.prototype.weight_size = 0n;\nge.proto.TensorDescriptor.prototype.reuse_input = false;\nge.proto.TensorDescriptor.prototype.output_tensor = false;\nge.proto.TensorDescriptor.prototype.device_type = \"\";\nge.proto.TensorDescriptor.prototype.input_tensor = false;\nge.proto.TensorDescriptor.prototype.real_dim_cnt = 0n;\nge.proto.TensorDescriptor.prototype.reuse_input_index = 0n;\nge.proto.TensorDescriptor.prototype.data_offset = 0n;\nge.proto.TensorDescriptor.prototype.cmps_size = 0n;\nge.proto.TensorDescriptor.prototype.cmps_tab = \"\";\nge.proto.TensorDescriptor.prototype.cmps_tab_offset = 0n;\n\nge.proto.TensorDef = class TensorDef {\n\n    static decode(reader, length) {\n        const message = new ge.proto.TensorDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.desc = ge.proto.TensorDescriptor.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.data = reader.bytes();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.TensorDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"desc\":\n                    message.desc = ge.proto.TensorDescriptor.decodeText(reader);\n                    break;\n                case \"data\":\n                    message.data = reader.bytes();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.TensorDef.prototype.desc = null;\nge.proto.TensorDef.prototype.data = new Uint8Array([]);\n\nge.proto.OpDef = class OpDef {\n\n    constructor() {\n        this.input = [];\n        this.attr = {};\n        this.input_name = [];\n        this.src_name = [];\n        this.src_index = [];\n        this.dst_name = [];\n        this.dst_index = [];\n        this.input_i = [];\n        this.output_i = [];\n        this.workspace = [];\n        this.workspace_bytes = [];\n        this.is_input_const = [];\n        this.input_desc = [];\n        this.output_desc = [];\n        this.subgraph_name = [];\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.OpDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = reader.string();\n                    break;\n                case 5:\n                    message.input.push(reader.string());\n                    break;\n                case 10:\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decode(reader, reader.uint32()));\n                    break;\n                case 20:\n                    message.has_out_attr = reader.bool();\n                    break;\n                case 21:\n                    message.id = reader.int64();\n                    break;\n                case 22:\n                    message.stream_id = reader.int64();\n                    break;\n                case 23:\n                    message.input_name.push(reader.string());\n                    break;\n                case 24:\n                    message.src_name.push(reader.string());\n                    break;\n                case 25:\n                    message.src_index = reader.array(message.src_index, () => reader.int64(), tag);\n                    break;\n                case 26:\n                    message.dst_name.push(reader.string());\n                    break;\n                case 27:\n                    message.dst_index = reader.array(message.dst_index, () => reader.int64(), tag);\n                    break;\n                case 28:\n                    message.input_i = reader.array(message.input_i, () => reader.int64(), tag);\n                    break;\n                case 29:\n                    message.output_i = reader.array(message.output_i, () => reader.int64(), tag);\n                    break;\n                case 30:\n                    message.workspace = reader.array(message.workspace, () => reader.int64(), tag);\n                    break;\n                case 31:\n                    message.workspace_bytes = reader.array(message.workspace_bytes, () => reader.int64(), tag);\n                    break;\n                case 32:\n                    message.is_input_const = reader.array(message.is_input_const, () => reader.bool(), tag);\n                    break;\n                case 33:\n                    message.input_desc.push(ge.proto.TensorDescriptor.decode(reader, reader.uint32()));\n                    break;\n                case 34:\n                    message.output_desc.push(ge.proto.TensorDescriptor.decode(reader, reader.uint32()));\n                    break;\n                case 35:\n                    message.subgraph_name.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.OpDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.string();\n                    break;\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"attr\":\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decodeText(reader));\n                    break;\n                case \"has_out_attr\":\n                    message.has_out_attr = reader.bool();\n                    break;\n                case \"id\":\n                    message.id = reader.int64();\n                    break;\n                case \"stream_id\":\n                    message.stream_id = reader.int64();\n                    break;\n                case \"input_name\":\n                    reader.array(message.input_name, () => reader.string());\n                    break;\n                case \"src_name\":\n                    reader.array(message.src_name, () => reader.string());\n                    break;\n                case \"src_index\":\n                    reader.array(message.src_index, () => reader.int64());\n                    break;\n                case \"dst_name\":\n                    reader.array(message.dst_name, () => reader.string());\n                    break;\n                case \"dst_index\":\n                    reader.array(message.dst_index, () => reader.int64());\n                    break;\n                case \"input_i\":\n                    reader.array(message.input_i, () => reader.int64());\n                    break;\n                case \"output_i\":\n                    reader.array(message.output_i, () => reader.int64());\n                    break;\n                case \"workspace\":\n                    reader.array(message.workspace, () => reader.int64());\n                    break;\n                case \"workspace_bytes\":\n                    reader.array(message.workspace_bytes, () => reader.int64());\n                    break;\n                case \"is_input_const\":\n                    reader.array(message.is_input_const, () => reader.bool());\n                    break;\n                case \"input_desc\":\n                    message.input_desc.push(ge.proto.TensorDescriptor.decodeText(reader));\n                    break;\n                case \"output_desc\":\n                    message.output_desc.push(ge.proto.TensorDescriptor.decodeText(reader));\n                    break;\n                case \"subgraph_name\":\n                    reader.array(message.subgraph_name, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.OpDef.prototype.name = \"\";\nge.proto.OpDef.prototype.type = \"\";\nge.proto.OpDef.prototype.has_out_attr = false;\nge.proto.OpDef.prototype.id = 0n;\nge.proto.OpDef.prototype.stream_id = 0n;\n\nge.proto.GraphDef = class GraphDef {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n        this.op = [];\n        this.attr = {};\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.GraphDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 4:\n                    message.input.push(reader.string());\n                    break;\n                case 5:\n                    message.output.push(reader.string());\n                    break;\n                case 6:\n                    message.op.push(ge.proto.OpDef.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.GraphDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                case \"op\":\n                    message.op.push(ge.proto.OpDef.decodeText(reader));\n                    break;\n                case \"attr\":\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.GraphDef.prototype.name = \"\";\n\nge.proto.ModelDef = class ModelDef {\n\n    constructor() {\n        this.graph = [];\n        this.attr = {};\n    }\n\n    static decode(reader, length) {\n        const message = new ge.proto.ModelDef();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.version = reader.uint32();\n                    break;\n                case 3:\n                    message.custom_version = reader.string();\n                    break;\n                case 7:\n                    message.graph.push(ge.proto.GraphDef.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new ge.proto.ModelDef();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"version\":\n                    message.version = reader.uint32();\n                    break;\n                case \"custom_version\":\n                    message.custom_version = reader.string();\n                    break;\n                case \"graph\":\n                    message.graph.push(ge.proto.GraphDef.decodeText(reader));\n                    break;\n                case \"attr\":\n                    reader.entry(message.attr, () => reader.string(), () => ge.proto.AttrDef.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n};\n\nge.proto.ModelDef.prototype.name = \"\";\nge.proto.ModelDef.prototype.version = 0;\nge.proto.ModelDef.prototype.custom_version = \"\";\n"
  },
  {
    "path": "source/om.js",
    "content": "\n// Experimental\n\nimport * as base from './base.js';\nimport * as protobuf from './protobuf.js';\n\nconst om = {};\nconst svp = {};\n\nom.ModelFactory = class {\n\n    async match(context) {\n        const container = om.Container.open(context);\n        if (container) {\n            return context.set('om', container);\n        }\n        return null;\n    }\n\n    async open(context) {\n        const target = context.value;\n        await target.read();\n        const metadata = await context.metadata('om-metadata.json');\n        return new om.Model(metadata, target);\n    }\n};\n\nom.Model = class {\n\n    constructor(metadata, target) {\n        this.format = target.format;\n        this.version = target.signature === 'PICO' ? target.model.version : '';\n        const context = {\n            metadata,\n            signature: target.signature,\n            weights: target.weights\n        };\n        this.modules = target.model.graph.map((graph) => new om.Graph(context, graph));\n    }\n};\n\nom.Graph = class {\n\n    constructor(context, graph) {\n        switch (context.signature) {\n            case 'IMOD': this.name = graph.name; break;\n            case 'PICO': this.name = graph.id.toString(); break;\n            default: throw new om.Error(`Unsupported DaVinci OM ${context.signature} signature.`);\n        }\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const values = new Map();\n        values.map = (name, type, tensor) => {\n            if (!values.has(name)) {\n                values.set(name, new om.Value(name, type || null, tensor || null));\n            } else if ((type && !type.equals(values.get(name).type)) ||\n                       (tensor && tensor !== values.get(name).initializer)) {\n                throw new om.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const tensors = new Map();\n        const ops = [];\n        for (const op of graph.op) {\n            if (op.type === 'Const' && op.attr && op.attr.value) {\n                const desc = op.attr.value.t.desc;\n                let data = null;\n                if (op.attr.value.t.data.length !== 0) {\n                    data = op.attr.value.t.data;\n                } else if (context.weights === null) {\n                    data = null;\n                } else if (desc.attr.merged_offset) {\n                    const offset = desc.attr.merged_offset.i.toNumber();\n                    data = context.weights.slice(offset, offset + desc.weight_size.toNumber());\n                } else {\n                    const offset = desc.data_offset.toNumber();\n                    data = context.weights.slice(offset, offset + desc.weight_size.toNumber());\n                }\n                const type = om.Utility.tensorType(desc);\n                const tensor = new om.Tensor('Constant', type, data);\n                tensors.set(op.name, tensor);\n                continue;\n            }\n            ops.push(op);\n        }\n        for (const op of ops) {\n            const node = new om.Node(context, op, graph, values, tensors);\n            this.nodes.push(node);\n        }\n    }\n};\n\nom.Node = class {\n\n    constructor(context, op, graph, values, tensors) {\n        this.name = op.name || '';\n        this.type = context.metadata.type(op.type) || { name: op.type };\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        this.chain = [];\n        this.controlDependencies = [];\n        this.device = null;\n        if (op.input) {\n            let index = 0;\n            for (let i = 0; i < op.input.length; i++) {\n                const input = op.input[i];\n                if (input === '') {\n                    continue;\n                }\n                const name = this.type.inputs && i < this.type.inputs.length ? this.type.inputs[i].name : `input${index === 0 ? '' : index}`;\n                index++;\n                const end = this.type.inputs && i < this.type.inputs.length && this.type.inputs[i].type && this.type.inputs[i].type === 'Tensor[]' ? op.input.length : i + 1;\n                const list = [];\n                for (let j = i; j < end; j++) {\n                    const input = op.input[j];\n                    if (input === '') {\n                        continue;\n                    }\n                    const index = input.lastIndexOf(':');\n                    const identifier = input.substring(0, index);\n                    const src_index = input.substring(index + 1);\n                    if (src_index === '-1') {\n                        this.controlDependencies.push(values.map(name));\n                        continue;\n                    }\n                    const type = om.Utility.tensorType(op.input_desc[j]);\n                    const tensor = tensors.get(identifier);\n                    const value = values.map(input, type, tensor);\n                    list.push(value);\n                }\n                const argument = new om.Argument(name, list);\n                this.inputs.push(argument);\n                i = end - 1;\n            }\n        }\n        if (op.output_desc) {\n            for (let i = 0; i < op.output_desc.length; i++) {\n                const identifier = `${this.name}:${i}`;\n                const type = om.Utility.tensorType(op.output_desc[i]);\n                const name = this.type.outputs && i < this.type.outputs.length ? this.type.outputs[i].name : `output${i === 0 ? '' : i}`;\n                const value = values.map(identifier, type);\n                const argument = new om.Argument(name, [value]);\n                this.outputs.push(argument);\n            }\n        }\n        for (const [name, obj] of Object.entries(op.attr || {})) {\n            if (name === 'device') {\n                this.device = obj;\n                continue;\n            }\n            if (name === 'original_op_names') {\n                continue;\n            }\n            if (name === 'relu_flag' && obj.b) {\n                const node = new om.Node(context, { type: 'ReLU' }, graph, obj);\n                this.chain.push(node);\n                continue;\n            }\n            let value = obj;\n            let type = null;\n            switch (obj.value) {\n                case 'i': {\n                    value = obj.i;\n                    type = 'int64';\n                    break;\n                }\n                case 'f': {\n                    value = obj.f;\n                    type = 'float32';\n                    break;\n                }\n                case 'b': {\n                    value = obj.b;\n                    type = 'boolean';\n                    break;\n                }\n                case 'bt': {\n                    value = null;\n                    if (obj.bt.length !== 0) {\n                        type = 'tensor';\n                        const shape = new om.TensorShape([obj.bt.length / 4]);\n                        value = new om.Tensor('Constant', new om.TensorType('float32', shape), obj.bt);\n                    }\n                    break;\n                }\n                case 'dt': {\n                    type = 'DataType';\n                    value = om.Utility.dtype(Number(obj.dt));\n                    break;\n                }\n                case 's': {\n                    if (typeof obj.s === 'string') {\n                        value = obj.s;\n                    } else if (obj.s.every((c) => c >= 32 && c <= 128)) {\n                        value = om.Utility.decodeText(obj.s);\n                    } else {\n                        value = obj.s;\n                    }\n                    type = 'string';\n                    break;\n                }\n                case 'g': {\n                    type = 'graph';\n                    value = new om.Graph(context, obj.g);\n                    break;\n                }\n                case 'func': {\n                    break;\n                }\n                case 'list': {\n                    const list = obj.list;\n                    value = [];\n                    if (list.s && list.s.length > 0) {\n                        value = list.s.map((v) => String.fromCharCode.apply(null, new Uint16Array(v))).join(', ');\n                        type = 'string[]';\n                    } else if (list.b && list.b.length > 0) {\n                        value = list.b;\n                        type = 'boolean[]';\n                    } else if (list.i && list.i.length > 0) {\n                        value = list.i;\n                        type = 'int64[]';\n                    } else if (list.f && list.f.length > 0) {\n                        value = list.f;\n                        type = 'float32[]';\n                    } else if (list.type && list.type.length > 0) {\n                        type = 'type[]';\n                        value = list.type.map((type) => om.Node.enum2Dtype(type) || '?');\n                    } else if (list.shape && list.shape.length > 0) {\n                        type = 'shape[]';\n                        value = list.shape.map((shape) => new om.TensorShape(shape));\n                    }\n                    break;\n                }\n                case 'list_list_int': {\n                    value = obj.list_list_int.list_list_i.map((list) => list.list_i);\n                    break;\n                }\n                case 't': {\n                    type = 'tensor';\n                    value = new om.Tensor('Constant', om.Utility.tensorType(obj.t.desc), obj.t.bytes);\n                    break;\n                }\n                case undefined: {\n                    value = null;\n                    break;\n                }\n                default: {\n                    throw new om.Error(`Unsupported attribute type '${JSON.stringify(obj).substring(0, 32)}'.`);\n                }\n            }\n            const attribute = new om.Argument(name, value, type);\n            this.attributes.push(attribute);\n        }\n    }\n};\n\nom.Argument = class {\n\n    constructor(name, value, type = null) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n    }\n};\n\nom.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new om.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nom.Tensor = class {\n\n    constructor(category, type, value) {\n        this.category = category;\n        this.type = type;\n        this.values = value;\n    }\n};\n\nom.TensorType = class {\n\n    constructor(dataType, shape, denotation) {\n        this.dataType = dataType;\n        this.shape = shape;\n        this.denotation = denotation;\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\nom.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim);\n    }\n\n    equals(obj) {\n        if (obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions)) {\n            if (this.dimensions.length === obj.dimensions.length &&\n                obj.dimensions.every((value, index) => this.dimensions[index] === value)) {\n                return true;\n            }\n            if (obj.dimensions.every((dim) => Number.isInteger(dim)) && this.dimensions.every((dim) => Number.isInteger(dim))) {\n                const a = obj.dimensions.reduce((a, b) => a * b, 1);\n                const b = this.dimensions.reduce((a, b) => a * b, 1);\n                return a === b;\n            }\n        }\n        return false;\n    }\n\n    toString() {\n        if (this.dimensions && Array.isArray(this.dimensions) && this.dimensions.length > 0) {\n            return `[${this.dimensions.map((dim) => dim ? dim.toString() : '?').join(',')}]`;\n        }\n        return '';\n    }\n};\n\nom.Container = class {\n\n    static open(context) {\n        const stream = context.stream;\n        if (stream && stream.length >= 256) {\n            const buffer = stream.peek(4);\n            const signature = Array.from(buffer).map((c) => String.fromCharCode(c)).join('');\n            if (signature === 'IMOD' || signature === 'PICO') {\n                return new om.Container(context, signature);\n            }\n        }\n        return null;\n    }\n\n    constructor(context, signature) {\n        this.context = context;\n        this.signature = signature;\n        this.weights = null;\n    }\n\n    async read() {\n        if (this.context) {\n            const stream = this.context.stream;\n            const reader = base.BinaryReader.open(stream);\n            reader.skip(4);\n            switch (this.signature) {\n                case 'IMOD': {\n                    const decoder = new TextDecoder('utf-8');\n                    this.format = 'DaVinci OM';\n                    const header = {};\n                    header.headsize = reader.uint32();\n                    header.version = reader.uint32();\n                    header.checksum = reader.read(64);\n                    header.length = reader.uint32();\n                    header.is_encrypt = reader.byte();\n                    header.is_checksum = reader.byte();\n                    header.modeltype = reader.byte(); // 0=IR model, 1=standard model, 2=OM Tiny model\n                    header.genmode = reader.byte(); // 0=offline, 1=online\n                    header.name = decoder.decode(reader.read(32));\n                    header.ops = reader.uint32();\n                    header.userdefineinfo = reader.read(32);\n                    header.om_ir_version = reader.uint32();\n                    header.model_num = header.version >= 0x20000000 ? reader.uint32() : 1;\n                    header.platform_version = decoder.decode(reader.read(20));\n                    header.platform_type = reader.byte();\n                    header.padd = [reader.byte(), reader.byte(), reader.byte()];\n                    header.model_length = reader.uint64();\n                    header.need_check_os_cpu_info = reader.byte();\n                    header.is_unknow_model = reader.byte(); // 0:static model 1:dynamic model\n                    header.reserved = reader.read(62);\n                    const partitions = new Map();\n                    let size = -1;\n                    for (let align = 4; align <= 8; align += 4) {\n                        reader.seek(header.headsize);\n                        const count = reader.uint32();\n                        reader.skip(align - 4);\n                        size = 4 + (align - 4) + (count * 3 * align);\n                        for (let i = 0; i < count; i++) {\n                            const type = align === 4 ? reader.uint32() : reader.uint64().toNumber();\n                            const offset = align === 4 ? reader.uint32() : reader.uint64().toNumber();\n                            const size = align === 4 ? reader.uint32() : reader.uint64().toNumber();\n                            if (type >= 32 || partitions.has(type) || (offset + size) >= stream.length) {\n                                partitions.clear();\n                                break;\n                            }\n                            partitions.set(type, { offset, size });\n                        }\n                        if (partitions.size > 0) {\n                            break;\n                        }\n                    }\n                    if (!partitions.has(0)) {\n                        throw new om.Error('File does not contain a model definition.');\n                    }\n                    const offset = header.headsize + size;\n                    for (const [type, partition] of partitions) {\n                        reader.seek(offset + partition.offset);\n                        const buffer = reader.read(partition.size);\n                        switch (type) {\n                            case 0: { // MODEL_DEF\n                                this.model = buffer;\n                                break;\n                            }\n                            case 1: { // WEIGHTS_DATA\n                                this.weights = buffer;\n                                break;\n                            }\n                            case 2: // TASK_INFO\n                            case 3: // TBE_KERNELS\n                            case 4: { // CUST_AICPU_KERNELS\n                                break;\n                            }\n                            case 5: { // DEVICE_CONFIG, SO_BINS\n                                this.devices = new Map();\n                                const decoder = new TextDecoder('ascii');\n                                const reader = base.BinaryReader.open(buffer);\n                                reader.uint32();\n                                for (let position = 4; position < partition.size;) {\n                                    const length = reader.uint32();\n                                    const buffer = reader.read(length);\n                                    const name = decoder.decode(buffer);\n                                    const device = reader.uint32();\n                                    this.devices.set(name, device);\n                                    position += 4 + length + 4;\n                                }\n                                break;\n                            }\n                            case 6: // FLOW_MODEL\n                            case 7: // FLOW_SUBMODEL\n                            case 8: // MODEL_INOUT_INFO\n                            case 9: // STATIC_TASK_DESC\n                            case 10: // DYNAMIC_TASK_DESC\n                            case 11: // TASK_PARAM\n                            case 12: // TILING_DATA\n                            case 20: // PRE_MODEL_DESC\n                            case 21: // PRE_MODEL_SQE\n                            case 22: // PRE_KERNEL_ARGS\n                            case 23: // PRE_MODEL_DESC_EXTEND\n                            case 24: { // BUNDLE_MODEL_INFO\n                                break;\n                            }\n                            default: {\n                                throw new om.Error(`Unsupported DaVinci OM partition type '${type}'.`);\n                            }\n                        }\n                    }\n                    om.proto = await this.context.require('./om-proto');\n                    om.proto = om.proto.ge.proto;\n                    try {\n                        const reader = protobuf.BinaryReader.open(this.model);\n                        this.model = om.proto.ModelDef.decode(reader);\n                    } catch (error) {\n                        const message = error && error.message ? error.message : error.toString();\n                        throw new om.Error(`File format is not ge.proto.ModelDef (${message.replace(/\\.$/, '')}).`);\n                    }\n                    break;\n                }\n                case 'PICO': {\n                    this.format = 'DaVinci OM SVP'; // SVP = Smart Vision Platform\n                    reader.uint32(); // reserved\n                    this.size = reader.uint32();\n                    const param_size = reader.uint32();\n                    const param_offset = reader.uint32();\n                    reader.uint32(); // tmp_bufsize\n                    const tfm_offset = reader.uint32();\n                    reader.uint32(); // tfm_size\n                    reader.seek(param_offset);\n                    this.param = reader.read(param_size);\n                    const buffer = reader.read(tfm_offset - reader.position);\n                    this.model = new svp.ModelDef(buffer);\n                    break;\n                }\n                default: {\n                    throw new om.Error(`Unsupported DaVinci OM ${this.signature} signature.`);\n                }\n            }\n            delete this.context;\n        }\n    }\n};\n\nom.Utility = class {\n\n    static dtype(value) {\n        om.Utility._types = om.Utility._types || [\n            'undefined', 'float32', 'float16', 'int8', 'uint8', 'int16', 'uint16', 'int32',\n            'int64', 'uint32', 'uint64', 'boolean', 'float64', 'string', 'dual_sub_int8', 'dual_sub_uint8',\n            'complex<float32>', 'complex<float64>', 'qint8', 'qint16', 'qint32', 'quint8', 'quint16', 'resource',\n            'stringref', 'dual', 'variant', 'bfloat16', 'int4', 'uint1', 'int2', 'uint2'\n        ];\n        if (value >= om.Utility._types.length) {\n            throw new om.Error(`Unsupported dtype '${value}'.`);\n        }\n        return om.Utility._types[value];\n    }\n\n    static tensorType(desc) {\n        if (desc && desc.shape && Array.isArray(desc.shape.dim)) {\n            const dataType = desc && desc.dtype ? om.Utility.dtype(desc.dtype) : '?';\n            const shape = new om.TensorShape(desc.shape.dim);\n            return new om.TensorType(dataType, shape, desc.layout);\n        }\n        return null;\n    }\n\n    static decodeText(value) {\n        om.Utility._textDecoder = om.Utility._textDecoder || new TextDecoder('utf-8');\n        return om.Utility._textDecoder.decode(value);\n    }\n};\n\nom.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading DaVinci OM model.';\n    }\n};\n\nsvp.ModelDef = class ModelDef {\n\n    constructor(buffer) {\n        const reader = new svp.BinaryReader(buffer);\n        this.attr = {};\n        this.graph = [];\n        this.name = reader.find(0x800D, 'string');\n        this.batch_num = reader.find(0x600A);\n        this.version = '';\n        while (reader.position < reader.length) {\n            const tag = reader.uint16();\n            const value = reader.value(tag);\n            switch (tag & 0x1fff) {\n                case 0x0040: {\n                    this.graph.push(new svp.GraphDef(value));\n                    break;\n                }\n                case 0x0111: {\n                    const op = new svp.OpDef(value);\n                    for (const item of this.graph) {\n                        if (op.attr && op.attr.seg_id && op.attr.seg_id.i === item.id) {\n                            let out_num = 0;\n                            if (typeof op.output_index === 'number') {\n                                out_num = op.output_index + 1;\n                            } else {\n                                const input_num = op.input.map((element) => element.split(\":\")[1]);\n                                out_num = input_num.length > 0 ? Math.max(...input_num) + 1 : 1;\n                            }\n                            const out_types = [];\n                            if (op.data_flow && op.data_flow !== '') {\n                                const data = op.data_flow;\n                                if (data.indexOf('o[{t') !== -1) {\n                                    const outs = data.substring(data.indexOf('o[{t')).split(',');\n                                    for (const out of outs) {\n                                        const startIndex = out.indexOf(\"\\\"\");\n                                        const endIndex = out.indexOf(\"\\\"\", startIndex + 1);\n                                        out_types.push(out.substring(startIndex + 1, endIndex));\n                                    }\n                                }\n                            }\n                            const out_list = [];\n                            while (out_num > 0) {\n                                const output_desc = {};\n                                output_desc.shape = { dim: op.output_shape_vector };\n                                output_desc.layout = 'NCHW';\n                                if (op.data_flow && out_types.length >= out_num) {\n                                    output_desc.dtype = out_types[op.output_index + 1 - out_num];\n                                }\n                                out_list.push(output_desc);\n                                out_num--;\n                            }\n\n                            let curr_op = null;\n                            for (const op_item of item.op) {\n                                if (op_item.id === op.id) {\n                                    curr_op = op_item;\n                                    break;\n                                }\n                            }\n                            if (curr_op === null) {\n                                op.output_desc = op.output_desc.concat(out_list);\n                                item.op.push(op);\n                            } else {\n                                curr_op.output_desc = curr_op.output_desc.concat(out_list);\n                            }\n                            break;\n                        }\n                    }\n                    break;\n                }\n                default: {\n                    break;\n                }\n            }\n        }\n        if (this.graph.length > 1) {\n            for (let i = 1; i < this.graph.length; i++) {\n                this.graph[0].op = this.graph[0].op.concat(this.graph[i].op);\n            }\n        }\n        this.version = this.graph[0].op.length === 0 ? 'release' : 'debug';\n    }\n};\n\nsvp.GraphDef = class {\n\n    constructor(buffer) {\n        this.input = [];\n        this.output = [];\n        this.op = [];\n        this.attr = {};\n        const reader = new svp.BinaryReader(buffer);\n        const input = (buffer) => {\n            const input = {};\n            const reader = new svp.BinaryReader(buffer);\n            while (reader.position < reader.length) {\n                const tag = reader.uint16();\n                switch (tag & 0x1fff) {\n                    case 0x0051: input.id = reader.value(tag); break;\n                    case 0x0058: input.name = reader.value(tag, 'string').trim(); break;\n                    case 0x005a: input.shape_vector = reader.value(tag, 'uint32[]'); break;\n                    default: reader.value(tag); break;\n                }\n            }\n            return input;\n        };\n        const output = (buffer) => {\n            const output = {};\n            const reader = new svp.BinaryReader(buffer);\n            while (reader.position < reader.length) {\n                const tag = reader.uint16();\n                switch (tag & 0x1fff) {\n                    case 0x0061: output.id = reader.value(tag); break;\n                    case 0x0066: output.name = reader.value(tag, 'string').trim(); break;\n                    case 0x0069: output.shape_vector = reader.value(tag, 'uint32[]'); break;\n                    case 0x0110: output.layer_num = reader.value(tag); break;\n                    default: reader.value(tag); break;\n                }\n            }\n            return output;\n        };\n        while (reader.position < reader.length) {\n            const tag = reader.uint16();\n            const value = reader.value(tag);\n            switch (tag & 0x1fff) {\n                case 0x0041: this.id = value; break;\n                case 0x0050: this.input.push(input(value)); break;\n                case 0x0060: this.output.push(output(value)); break;\n                default: break;\n            }\n        }\n    }\n};\n\nsvp.OpDef = class {\n\n    constructor(buffer) {\n        this.input = [];\n        this.attr = {};\n        this.input_i = [];\n        this.output_i = [];\n        this.input_desc = [];\n        this.output_desc = [];\n        const reader = new svp.BinaryReader(buffer);\n        while (reader.position < reader.length) {\n            const tag = reader.uint16();\n            switch (tag & 0x1fff) {\n                case 0x0114: this.name = reader.value(tag, 'string').trim(); break;\n                case 0x0112: this.id = reader.value(tag); break;\n                case 0x0119: this.attr.output_m2m_flag = reader.attribute(tag, 'i'); break;\n                case 0x0121: this.attr.batch_flag = reader.attribute(tag, 'i'); break;\n                case 0x0124: this.attr.dequant_scale = reader.attribute(tag, 'i'); break;\n                case 0x0126: this.attr.output_address = reader.attribute(tag, 'i'); break;\n                case 0x0125: this.attr.dequant_offset = reader.attribute(tag, 'i'); break;\n                case 0x0127: this.attr.first_inst_addr = reader.attribute(tag, 'i'); break;\n                case 0x0128: this.attr.last_inst_addr = reader.attribute(tag, 'i'); break;\n                case 0x013B: this.attr.is_fusion_layer = reader.attribute(tag, 'i'); break;\n                case 0x013C: this.input = reader.value(tag, 'string').split(','); break;\n                case 0x014B: this.attr.seg_id = reader.attribute(tag, 'i'); break;\n                case 0x0150: this.attr.is_not_last_merge_layer = reader.attribute(tag, 'i'); break;\n                case 0x0151: this.attr.is_dump_avavilable = reader.attribute(tag, 'i'); break;\n                case 0x0153: this.attr.debug_dump_offset = reader.attribute(tag, 'i'); break;\n                case 0x0152: this.type = reader.value(tag, 'string'); break;\n                case 0x0154: this.output_shape_vector = reader.value(tag, 'uint32[]'); break;\n                case 0x0155: this.input_index = reader.value(tag); break;\n                case 0x015B: this.output_index = reader.value(tag); break;\n                case 0x0156: this.attr.trap_inst_pc = reader.attribute(tag, 'i'); break;\n                case 0x0157: this.attr.profile_layer_id = reader.attribute(tag, 'i'); break;\n                case 0xA15A:\n                    this.data_flow = reader.value(tag, 'string');\n                    this.attr.data_flow = new svp.AttrDef(this.data_flow.replace('i[{t', 'input[{type').replace(',f[{t', '\\tforward[{type').replace(',o[{t', '\\toutput[{type').replace(',{[t', ',{type'), 's');\n                    break;\n                default: reader.value(tag); break;\n            }\n        }\n        for (let i = 0; i < this.input.length; i++) {\n            this.input_desc.push({ layout: 'NCHW', shape: {} });\n        }\n    }\n};\n\nsvp.AttrDef = class {\n\n    constructor(item, type) {\n        switch (type) {\n            case 's': this.s = item; break;\n            case 'i': this.i = item; break;\n            default: throw new svp.Error(`Unsupported attribute type '${type}'.`);\n        }\n    }\n\n    get value() {\n        if (this.s !== undefined) {\n            return 's';\n        }\n        if (this.i !== undefined) {\n            return 'i';\n        }\n        return undefined;\n    }\n};\n\nsvp.BinaryReader = class {\n\n    constructor(buffer) {\n        this._reader = base.BinaryReader.open(buffer);\n    }\n\n    get length() {\n        return this._reader.length;\n    }\n\n    get position() {\n        return this._reader.position;\n    }\n\n    seek(position) {\n        this._reader.seek(position);\n    }\n\n    read(length) {\n        return this._reader.read(length);\n    }\n\n    int8() {\n        return this._reader.int8();\n    }\n\n    uint16() {\n        return this._reader.uint16();\n    }\n\n    uint32() {\n        return this._reader.uint32();\n    }\n\n    value(tag, type) {\n        let value = 0;\n        switch (tag >> 13) {\n            case 1: value = this.int8(); break;\n            case 2: value = this.uint16(); break;\n            case 3: value = this.uint32(); break;\n            case 4: value = this.read(this.int8()); break;\n            case 5: value = this.read(this.uint16()); break;\n            case 6: value = this.read(this.uint32()); break;\n            default: throw new svp.Error(`Unsupported value identifier '${tag}'.`);\n        }\n        return type ? this._cast(value, type, tag) : value;\n    }\n\n    find(tag, type) {\n        let value = null;\n        let match = false;\n        while (!match && this.position < this.length) {\n            const current = this.uint16();\n            value = this.value(current);\n            match = current === tag;\n        }\n        this.seek(0);\n        return match && type ? this._cast(value, type, tag) : value;\n    }\n\n    attribute(tag, type) {\n        const value = this.value(tag);\n        return new svp.AttrDef(value, type);\n    }\n\n    _cast(value, type, tag) {\n        switch (type) {\n            case 'string': {\n                if (value instanceof Uint8Array) {\n                    svp.BinaryReader._decoder = svp.BinaryReader._decoder || new TextDecoder('utf-8');\n                    return svp.BinaryReader._decoder.decode(value).replace(/\\0.*$/g, '');\n                }\n                throw new om.Error(`Invalid 'string' tag '${tag.toString(16)}'.`);\n            }\n            case 'uint32[]': {\n                const reader = base.BinaryReader.open(value);\n                value = [];\n                while (reader.position < reader.length) {\n                    value.push(reader.uint32());\n                }\n                return value;\n            }\n            default: {\n                return value;\n            }\n        }\n    }\n};\n\nsvp.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading DaVinci SVP model.';\n    }\n};\n\nexport const ModelFactory = om.ModelFactory;\n"
  },
  {
    "path": "source/onednn-metadata.json",
    "content": "[\n  {\n    \"name\": \"End\"\n  },\n  {\n    \"name\": \"Wildcard\"\n  },\n  {\n    \"name\": \"StaticReshape\",\n    \"category\": \"Shape\"\n  },\n  {\n    \"name\": \"AvgPoolBackward\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"AvgPool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"MaxPoolBackward\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"MaxPool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"LayerNormBackward\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"diff_dst\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"diff_src\" },\n      { \"name\": \"diff_gamma\" },\n      { \"name\": \"diff_beta\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormInference\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormTrainingBackward\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"diff_dst\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"gamma\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"diff_src\" },\n      { \"name\": \"diff_gamma\" },\n      { \"name\": \"diff_beta\" }\n    ]\n  },\n  {\n    \"name\": \"BatchNormForwardTraining\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" },\n      { \"name\": \"running_mean\" },\n      { \"name\": \"running_variance\" },\n      { \"name\": \"batch_mean\" },\n      { \"name\": \"batch_variance\" }\n    ]\n  },\n  {\n    \"name\": \"LayerNorm\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"gamma\" },\n      { \"name\": \"beta\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"dst\" },\n      { \"name\": \"mean\" },\n      { \"name\": \"variance\" }\n    ]\n  },\n  {\n    \"name\": \"DynamicDequantize\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"DynamicQuantize\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"Dequantize\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"Quantize\",\n    \"category\": \"Quantization\"\n  },\n  {\n    \"name\": \"TypeCast\"\n  },\n  {\n    \"name\": \"ReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftMaxBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"MishBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"GELU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ClampBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Mish\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"PReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SigmoidBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"LogSoftmax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Clamp\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"TanhBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"ReLUBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Exp\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftMax\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"HardSwish\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"LeakyReLU\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"LogSoftmaxBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Tanh\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Elu\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftPlus\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"EluBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"GELUBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SoftPlusBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"PReLUBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"HardSwishBackward\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"Interpolate\"\n  },\n  {\n    \"name\": \"InterpolateBackward\"\n  },\n  {\n    \"name\": \"ReduceMax\"\n  },\n  {\n    \"name\": \"ReduceL2\"\n  },\n  {\n    \"name\": \"ReduceL1\"\n  },\n  {\n    \"name\": \"ReduceSum\"\n  },\n  {\n    \"name\": \"ReduceProd\"\n  },\n  {\n    \"name\": \"ReduceMean\"\n  },\n  {\n    \"name\": \"ReduceMin\"\n  },\n  {\n    \"name\": \"Reorder\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"StaticTranspose\",\n    \"category\": \"Transform\"\n  },\n  {\n    \"name\": \"Abs\"\n  },\n  {\n    \"name\": \"Sqrt\"\n  },\n  {\n    \"name\": \"Round\"\n  },\n  {\n    \"name\": \"Subtract\"\n  },\n  {\n    \"name\": \"Erf\"\n  },\n  {\n    \"name\": \"Minimum\"\n  },\n  {\n    \"name\": \"Reciprocal\"\n  },\n  {\n    \"name\": \"BiasAddBackward\"\n  },\n  {\n    \"name\": \"Divide\"\n  },\n  {\n    \"name\": \"SquaredDifference\"\n  },\n  {\n    \"name\": \"Multiply\"\n  },\n  {\n    \"name\": \"AbsBackward\"\n  },\n  {\n    \"name\": \"Square\"\n  },\n  {\n    \"name\": \"Maximum\"\n  },\n  {\n    \"name\": \"Add\"\n  },\n  {\n    \"name\": \"SqrtBackward\"\n  },\n  {\n    \"name\": \"Log\"\n  },\n  {\n    \"name\": \"BiasAdd\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvTranspose\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvTransposeBackwardData\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionBackwardData\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"dst_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvolutionBackwardWeights\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"diff_dst\" },\n      { \"name\": \"weights_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"ConvTransposeBackwardWeights\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"diff_dst\" },\n      { \"name\": \"weights_shape\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"MatMul\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/onnx-proto.js",
    "content": "\nexport const onnx = {};\n\nonnx.Version = {\n    \"_START_VERSION\": 0,\n    \"IR_VERSION_2017_10_10\": 1,\n    \"IR_VERSION_2017_10_30\": 2,\n    \"IR_VERSION_2017_11_3\": 3,\n    \"IR_VERSION_2019_1_22\": 4,\n    \"IR_VERSION_2019_3_18\": 5,\n    \"IR_VERSION_2019_9_19\": 6,\n    \"IR_VERSION_2020_5_8\": 7,\n    \"IR_VERSION_2021_7_30\": 8,\n    \"IR_VERSION_2023_5_5\": 9,\n    \"IR_VERSION_2024_3_25\": 10,\n    \"IR_VERSION_2025_05_12\": 11,\n    \"IR_VERSION_2025_08_26\": 12,\n    \"IR_VERSION\": 13\n};\n\nonnx.AttributeProto = class AttributeProto {\n\n    constructor() {\n        this.floats = [];\n        this.ints = [];\n        this.strings = [];\n        this.tensors = [];\n        this.graphs = [];\n        this.sparse_tensors = [];\n        this.type_protos = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.AttributeProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 21:\n                    message.ref_attr_name = reader.string();\n                    break;\n                case 13:\n                    message.doc_string = reader.string();\n                    break;\n                case 20:\n                    message.type = reader.int32();\n                    break;\n                case 2:\n                    message.f = reader.float();\n                    break;\n                case 3:\n                    message.i = reader.int64();\n                    break;\n                case 4:\n                    message.s = reader.bytes();\n                    break;\n                case 5:\n                    message.t = onnx.TensorProto.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.g = onnx.GraphProto.decode(reader, reader.uint32());\n                    break;\n                case 22:\n                    message.sparse_tensor = onnx.SparseTensorProto.decode(reader, reader.uint32());\n                    break;\n                case 14:\n                    message.tp = onnx.TypeProto.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.floats = reader.floats(message.floats, tag);\n                    break;\n                case 8:\n                    message.ints = reader.array(message.ints, () => reader.int64(), tag);\n                    break;\n                case 9:\n                    message.strings.push(reader.bytes());\n                    break;\n                case 10:\n                    message.tensors.push(onnx.TensorProto.decode(reader, reader.uint32()));\n                    break;\n                case 11:\n                    message.graphs.push(onnx.GraphProto.decode(reader, reader.uint32()));\n                    break;\n                case 23:\n                    message.sparse_tensors.push(onnx.SparseTensorProto.decode(reader, reader.uint32()));\n                    break;\n                case 15:\n                    message.type_protos.push(onnx.TypeProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.AttributeProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"ref_attr_name\":\n                    message.ref_attr_name = reader.string();\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"type\":\n                    message.type = reader.enum(onnx.AttributeProto.AttributeType);\n                    break;\n                case \"f\":\n                    message.f = reader.float();\n                    break;\n                case \"i\":\n                    message.i = reader.int64();\n                    break;\n                case \"s\":\n                    message.s = reader.bytes();\n                    break;\n                case \"t\":\n                    message.t = onnx.TensorProto.decodeText(reader);\n                    break;\n                case \"g\":\n                    message.g = onnx.GraphProto.decodeText(reader);\n                    break;\n                case \"sparse_tensor\":\n                    message.sparse_tensor = onnx.SparseTensorProto.decodeText(reader);\n                    break;\n                case \"tp\":\n                    message.tp = onnx.TypeProto.decodeText(reader);\n                    break;\n                case \"floats\":\n                    reader.array(message.floats, () => reader.float());\n                    break;\n                case \"ints\":\n                    reader.array(message.ints, () => reader.int64());\n                    break;\n                case \"strings\":\n                    reader.array(message.strings, () => reader.bytes());\n                    break;\n                case \"tensors\":\n                    message.tensors.push(onnx.TensorProto.decodeText(reader));\n                    break;\n                case \"graphs\":\n                    message.graphs.push(onnx.GraphProto.decodeText(reader));\n                    break;\n                case \"sparse_tensors\":\n                    message.sparse_tensors.push(onnx.SparseTensorProto.decodeText(reader));\n                    break;\n                case \"type_protos\":\n                    message.type_protos.push(onnx.TypeProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.AttributeProto();\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('refAttrName' in obj) {\n            message.ref_attr_name = obj.refAttrName;\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('type' in obj) {\n            message.type = typeof obj.type === 'string' ? onnx.AttributeProto.AttributeType[obj.type] : obj.type;\n        }\n        if ('f' in obj) {\n            message.f = Number(obj.f);\n        }\n        if ('i' in obj) {\n            message.i = BigInt(obj.i);\n        }\n        if ('s' in obj) {\n            message.s = typeof obj.s === 'string' ? Uint8Array.from(atob(obj.s), (c) => c.charCodeAt(0)) : Uint8Array.from(obj.s);\n        }\n        if ('t' in obj) {\n            message.t = onnx.TensorProto.decodeJson(obj.t);\n        }\n        if ('g' in obj) {\n            message.g = onnx.GraphProto.decodeJson(obj.g);\n        }\n        if ('sparseTensor' in obj) {\n            message.sparse_tensor = onnx.SparseTensorProto.decodeJson(obj.sparseTensor);\n        }\n        if ('tp' in obj) {\n            message.tp = onnx.TypeProto.decodeJson(obj.tp);\n        }\n        if ('floats' in obj) {\n            message.floats = obj.floats.map((obj) => Number(obj));\n        }\n        if ('ints' in obj) {\n            message.ints = obj.ints.map((obj) => BigInt(obj));\n        }\n        if ('strings' in obj) {\n            message.strings = obj.strings.map((obj) => typeof obj === 'string' ? Uint8Array.from(atob(obj), (c) => c.charCodeAt(0)) : Uint8Array.from(obj));\n        }\n        if ('tensors' in obj) {\n            message.tensors = obj.tensors.map((obj) => onnx.TensorProto.decodeJson(obj));\n        }\n        if ('graphs' in obj) {\n            message.graphs = obj.graphs.map((obj) => onnx.GraphProto.decodeJson(obj));\n        }\n        if ('sparseTensors' in obj) {\n            message.sparse_tensors = obj.sparseTensors.map((obj) => onnx.SparseTensorProto.decodeJson(obj));\n        }\n        if ('typeProtos' in obj) {\n            message.type_protos = obj.typeProtos.map((obj) => onnx.TypeProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.AttributeProto.prototype.name = \"\";\nonnx.AttributeProto.prototype.ref_attr_name = \"\";\nonnx.AttributeProto.prototype.doc_string = \"\";\nonnx.AttributeProto.prototype.type = 0;\nonnx.AttributeProto.prototype.f = 0;\nonnx.AttributeProto.prototype.i = 0n;\nonnx.AttributeProto.prototype.s = new Uint8Array([]);\nonnx.AttributeProto.prototype.t = null;\nonnx.AttributeProto.prototype.g = null;\nonnx.AttributeProto.prototype.sparse_tensor = null;\nonnx.AttributeProto.prototype.tp = null;\n\nonnx.AttributeProto.AttributeType = {\n    \"UNDEFINED\": 0,\n    \"FLOAT\": 1,\n    \"INT\": 2,\n    \"STRING\": 3,\n    \"TENSOR\": 4,\n    \"GRAPH\": 5,\n    \"SPARSE_TENSOR\": 11,\n    \"TYPE_PROTO\": 13,\n    \"FLOATS\": 6,\n    \"INTS\": 7,\n    \"STRINGS\": 8,\n    \"TENSORS\": 9,\n    \"GRAPHS\": 10,\n    \"SPARSE_TENSORS\": 12,\n    \"TYPE_PROTOS\": 14\n};\n\nonnx.ValueInfoProto = class ValueInfoProto {\n\n    constructor() {\n        this.metadata_props = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.ValueInfoProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.type = onnx.TypeProto.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.doc_string = reader.string();\n                    break;\n                case 4:\n                    message.metadata_props.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.ValueInfoProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"type\":\n                    message.type = onnx.TypeProto.decodeText(reader);\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"metadata_props\":\n                    message.metadata_props.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.ValueInfoProto();\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('type' in obj) {\n            message.type = onnx.TypeProto.decodeJson(obj.type);\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('metadataProps' in obj) {\n            message.metadata_props = obj.metadataProps.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.ValueInfoProto.prototype.name = \"\";\nonnx.ValueInfoProto.prototype.type = null;\nonnx.ValueInfoProto.prototype.doc_string = \"\";\n\nonnx.NodeProto = class NodeProto {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n        this.attribute = [];\n        this.metadata_props = [];\n        this.device_configurations = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.NodeProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.input.push(reader.string());\n                    break;\n                case 2:\n                    message.output.push(reader.string());\n                    break;\n                case 3:\n                    message.name = reader.string();\n                    break;\n                case 4:\n                    message.op_type = reader.string();\n                    break;\n                case 7:\n                    message.domain = reader.string();\n                    break;\n                case 8:\n                    message.overload = reader.string();\n                    break;\n                case 5:\n                    message.attribute.push(onnx.AttributeProto.decode(reader, reader.uint32()));\n                    break;\n                case 6:\n                    message.doc_string = reader.string();\n                    break;\n                case 9:\n                    message.metadata_props.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.device_configurations.push(onnx.NodeDeviceConfigurationProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.NodeProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"op_type\":\n                    message.op_type = reader.string();\n                    break;\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"overload\":\n                    message.overload = reader.string();\n                    break;\n                case \"attribute\":\n                    message.attribute.push(onnx.AttributeProto.decodeText(reader));\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"metadata_props\":\n                    message.metadata_props.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                case \"device_configurations\":\n                    message.device_configurations.push(onnx.NodeDeviceConfigurationProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.NodeProto();\n        if ('input' in obj) {\n            message.input = obj.input;\n        }\n        if ('output' in obj) {\n            message.output = obj.output;\n        }\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('opType' in obj) {\n            message.op_type = obj.opType;\n        }\n        if ('domain' in obj) {\n            message.domain = obj.domain;\n        }\n        if ('overload' in obj) {\n            message.overload = obj.overload;\n        }\n        if ('attribute' in obj) {\n            message.attribute = obj.attribute.map((obj) => onnx.AttributeProto.decodeJson(obj));\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('metadataProps' in obj) {\n            message.metadata_props = obj.metadataProps.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        if ('deviceConfigurations' in obj) {\n            message.device_configurations = obj.deviceConfigurations.map((obj) => onnx.NodeDeviceConfigurationProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.NodeProto.prototype.name = \"\";\nonnx.NodeProto.prototype.op_type = \"\";\nonnx.NodeProto.prototype.domain = \"\";\nonnx.NodeProto.prototype.overload = \"\";\nonnx.NodeProto.prototype.doc_string = \"\";\n\nonnx.IntIntListEntryProto = class IntIntListEntryProto {\n\n    constructor() {\n        this.value = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.IntIntListEntryProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.key = reader.int64();\n                    break;\n                case 2:\n                    message.value = reader.array(message.value, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.IntIntListEntryProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"key\":\n                    message.key = reader.int64();\n                    break;\n                case \"value\":\n                    reader.array(message.value, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.IntIntListEntryProto();\n        if ('key' in obj) {\n            message.key = BigInt(obj.key);\n        }\n        if ('value' in obj) {\n            message.value = obj.value.map((obj) => BigInt(obj));\n        }\n        return message;\n    }\n};\n\nonnx.IntIntListEntryProto.prototype.key = 0n;\n\nonnx.NodeDeviceConfigurationProto = class NodeDeviceConfigurationProto {\n\n    constructor() {\n        this.sharding_spec = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.NodeDeviceConfigurationProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.configuration_id = reader.string();\n                    break;\n                case 2:\n                    message.sharding_spec.push(onnx.ShardingSpecProto.decode(reader, reader.uint32()));\n                    break;\n                case 3:\n                    message.pipeline_stage = reader.int32();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.NodeDeviceConfigurationProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"configuration_id\":\n                    message.configuration_id = reader.string();\n                    break;\n                case \"sharding_spec\":\n                    message.sharding_spec.push(onnx.ShardingSpecProto.decodeText(reader));\n                    break;\n                case \"pipeline_stage\":\n                    message.pipeline_stage = reader.int32();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.NodeDeviceConfigurationProto();\n        if ('configurationId' in obj) {\n            message.configuration_id = obj.configurationId;\n        }\n        if ('shardingSpec' in obj) {\n            message.sharding_spec = obj.shardingSpec.map((obj) => onnx.ShardingSpecProto.decodeJson(obj));\n        }\n        if ('pipelineStage' in obj) {\n            message.pipeline_stage = Number(obj.pipelineStage);\n        }\n        return message;\n    }\n};\n\nonnx.NodeDeviceConfigurationProto.prototype.configuration_id = \"\";\nonnx.NodeDeviceConfigurationProto.prototype.pipeline_stage = 0;\n\nonnx.ShardingSpecProto = class ShardingSpecProto {\n\n    constructor() {\n        this.device = [];\n        this.index_to_device_group_map = [];\n        this.sharded_dim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.ShardingSpecProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.tensor_name = reader.string();\n                    break;\n                case 2:\n                    message.device = reader.array(message.device, () => reader.int64(), tag);\n                    break;\n                case 3:\n                    message.index_to_device_group_map.push(onnx.IntIntListEntryProto.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    message.sharded_dim.push(onnx.ShardedDimProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.ShardingSpecProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"tensor_name\":\n                    message.tensor_name = reader.string();\n                    break;\n                case \"device\":\n                    reader.array(message.device, () => reader.int64());\n                    break;\n                case \"index_to_device_group_map\":\n                    message.index_to_device_group_map.push(onnx.IntIntListEntryProto.decodeText(reader));\n                    break;\n                case \"sharded_dim\":\n                    message.sharded_dim.push(onnx.ShardedDimProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.ShardingSpecProto();\n        if ('tensorName' in obj) {\n            message.tensor_name = obj.tensorName;\n        }\n        if ('device' in obj) {\n            message.device = obj.device.map((obj) => BigInt(obj));\n        }\n        if ('indexToDeviceGroupMap' in obj) {\n            message.index_to_device_group_map = obj.indexToDeviceGroupMap.map((obj) => onnx.IntIntListEntryProto.decodeJson(obj));\n        }\n        if ('shardedDim' in obj) {\n            message.sharded_dim = obj.shardedDim.map((obj) => onnx.ShardedDimProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.ShardingSpecProto.prototype.tensor_name = \"\";\n\nonnx.ShardedDimProto = class ShardedDimProto {\n\n    constructor() {\n        this.simple_sharding = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.ShardedDimProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.axis = reader.int64();\n                    break;\n                case 2:\n                    message.simple_sharding.push(onnx.SimpleShardedDimProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.ShardedDimProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"axis\":\n                    message.axis = reader.int64();\n                    break;\n                case \"simple_sharding\":\n                    message.simple_sharding.push(onnx.SimpleShardedDimProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.ShardedDimProto();\n        if ('axis' in obj) {\n            message.axis = BigInt(obj.axis);\n        }\n        if ('simpleSharding' in obj) {\n            message.simple_sharding = obj.simpleSharding.map((obj) => onnx.SimpleShardedDimProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.ShardedDimProto.prototype.axis = 0n;\n\nonnx.SimpleShardedDimProto = class SimpleShardedDimProto {\n\n    get dim() {\n        onnx.SimpleShardedDimProto.dimSet = onnx.SimpleShardedDimProto.dimSet || new Set([\"dim_value\", \"dim_param\"]);\n        return Object.keys(this).find((key) => onnx.SimpleShardedDimProto.dimSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.SimpleShardedDimProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim_value = reader.int64();\n                    break;\n                case 2:\n                    message.dim_param = reader.string();\n                    break;\n                case 3:\n                    message.num_shards = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.SimpleShardedDimProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim_value\":\n                    message.dim_value = reader.int64();\n                    break;\n                case \"dim_param\":\n                    message.dim_param = reader.string();\n                    break;\n                case \"num_shards\":\n                    message.num_shards = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.SimpleShardedDimProto();\n        if ('dimValue' in obj) {\n            message.dim_value = BigInt(obj.dimValue);\n        }\n        if ('dimParam' in obj) {\n            message.dim_param = obj.dimParam;\n        }\n        if ('numShards' in obj) {\n            message.num_shards = BigInt(obj.numShards);\n        }\n        return message;\n    }\n};\n\nonnx.SimpleShardedDimProto.prototype.num_shards = 0n;\n\nonnx.TrainingInfoProto = class TrainingInfoProto {\n\n    constructor() {\n        this.initialization_binding = [];\n        this.update_binding = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.TrainingInfoProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.initialization = onnx.GraphProto.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.algorithm = onnx.GraphProto.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.initialization_binding.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                case 4:\n                    message.update_binding.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TrainingInfoProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"initialization\":\n                    message.initialization = onnx.GraphProto.decodeText(reader);\n                    break;\n                case \"algorithm\":\n                    message.algorithm = onnx.GraphProto.decodeText(reader);\n                    break;\n                case \"initialization_binding\":\n                    message.initialization_binding.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                case \"update_binding\":\n                    message.update_binding.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TrainingInfoProto();\n        if ('initialization' in obj) {\n            message.initialization = onnx.GraphProto.decodeJson(obj.initialization);\n        }\n        if ('algorithm' in obj) {\n            message.algorithm = onnx.GraphProto.decodeJson(obj.algorithm);\n        }\n        if ('initializationBinding' in obj) {\n            message.initialization_binding = obj.initializationBinding.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        if ('updateBinding' in obj) {\n            message.update_binding = obj.updateBinding.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.TrainingInfoProto.prototype.initialization = null;\nonnx.TrainingInfoProto.prototype.algorithm = null;\n\nonnx.ModelProto = class ModelProto {\n\n    constructor() {\n        this.opset_import = [];\n        this.metadata_props = [];\n        this.training_info = [];\n        this.functions = [];\n        this.configuration = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.ModelProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.ir_version = reader.int64();\n                    break;\n                case 8:\n                    message.opset_import.push(onnx.OperatorSetIdProto.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.producer_name = reader.string();\n                    break;\n                case 3:\n                    message.producer_version = reader.string();\n                    break;\n                case 4:\n                    message.domain = reader.string();\n                    break;\n                case 5:\n                    message.model_version = reader.int64();\n                    break;\n                case 6:\n                    message.doc_string = reader.string();\n                    break;\n                case 7:\n                    message.graph = onnx.GraphProto.decode(reader, reader.uint32());\n                    break;\n                case 14:\n                    message.metadata_props.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                case 20:\n                    message.training_info.push(onnx.TrainingInfoProto.decode(reader, reader.uint32()));\n                    break;\n                case 25:\n                    message.functions.push(onnx.FunctionProto.decode(reader, reader.uint32()));\n                    break;\n                case 26:\n                    message.configuration.push(onnx.DeviceConfigurationProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.ModelProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"ir_version\":\n                    message.ir_version = reader.int64();\n                    break;\n                case \"opset_import\":\n                    message.opset_import.push(onnx.OperatorSetIdProto.decodeText(reader));\n                    break;\n                case \"producer_name\":\n                    message.producer_name = reader.string();\n                    break;\n                case \"producer_version\":\n                    message.producer_version = reader.string();\n                    break;\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"model_version\":\n                    message.model_version = reader.int64();\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"graph\":\n                    message.graph = onnx.GraphProto.decodeText(reader);\n                    break;\n                case \"metadata_props\":\n                    message.metadata_props.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                case \"training_info\":\n                    message.training_info.push(onnx.TrainingInfoProto.decodeText(reader));\n                    break;\n                case \"functions\":\n                    message.functions.push(onnx.FunctionProto.decodeText(reader));\n                    break;\n                case \"configuration\":\n                    message.configuration.push(onnx.DeviceConfigurationProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.ModelProto();\n        if ('irVersion' in obj) {\n            message.ir_version = BigInt(obj.irVersion);\n        }\n        if ('opsetImport' in obj) {\n            message.opset_import = obj.opsetImport.map((obj) => onnx.OperatorSetIdProto.decodeJson(obj));\n        }\n        if ('producerName' in obj) {\n            message.producer_name = obj.producerName;\n        }\n        if ('producerVersion' in obj) {\n            message.producer_version = obj.producerVersion;\n        }\n        if ('domain' in obj) {\n            message.domain = obj.domain;\n        }\n        if ('modelVersion' in obj) {\n            message.model_version = BigInt(obj.modelVersion);\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('graph' in obj) {\n            message.graph = onnx.GraphProto.decodeJson(obj.graph);\n        }\n        if ('metadataProps' in obj) {\n            message.metadata_props = obj.metadataProps.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        if ('trainingInfo' in obj) {\n            message.training_info = obj.trainingInfo.map((obj) => onnx.TrainingInfoProto.decodeJson(obj));\n        }\n        if ('functions' in obj) {\n            message.functions = obj.functions.map((obj) => onnx.FunctionProto.decodeJson(obj));\n        }\n        if ('configuration' in obj) {\n            message.configuration = obj.configuration.map((obj) => onnx.DeviceConfigurationProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.ModelProto.prototype.ir_version = 0n;\nonnx.ModelProto.prototype.producer_name = \"\";\nonnx.ModelProto.prototype.producer_version = \"\";\nonnx.ModelProto.prototype.domain = \"\";\nonnx.ModelProto.prototype.model_version = 0n;\nonnx.ModelProto.prototype.doc_string = \"\";\nonnx.ModelProto.prototype.graph = null;\n\nonnx.DeviceConfigurationProto = class DeviceConfigurationProto {\n\n    constructor() {\n        this.device = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.DeviceConfigurationProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 2:\n                    message.num_devices = reader.int32();\n                    break;\n                case 3:\n                    message.device.push(reader.string());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.DeviceConfigurationProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"num_devices\":\n                    message.num_devices = reader.int32();\n                    break;\n                case \"device\":\n                    reader.array(message.device, () => reader.string());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.DeviceConfigurationProto();\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('numDevices' in obj) {\n            message.num_devices = Number(obj.numDevices);\n        }\n        if ('device' in obj) {\n            message.device = obj.device;\n        }\n        return message;\n    }\n};\n\nonnx.DeviceConfigurationProto.prototype.name = \"\";\nonnx.DeviceConfigurationProto.prototype.num_devices = 0;\n\nonnx.StringStringEntryProto = class StringStringEntryProto {\n\n    static decode(reader, length) {\n        const message = new onnx.StringStringEntryProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.key = reader.string();\n                    break;\n                case 2:\n                    message.value = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.StringStringEntryProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"key\":\n                    message.key = reader.string();\n                    break;\n                case \"value\":\n                    message.value = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.StringStringEntryProto();\n        if ('key' in obj) {\n            message.key = obj.key;\n        }\n        if ('value' in obj) {\n            message.value = obj.value;\n        }\n        return message;\n    }\n};\n\nonnx.StringStringEntryProto.prototype.key = \"\";\nonnx.StringStringEntryProto.prototype.value = \"\";\n\nonnx.TensorAnnotation = class TensorAnnotation {\n\n    constructor() {\n        this.quant_parameter_tensor_names = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.TensorAnnotation();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.tensor_name = reader.string();\n                    break;\n                case 2:\n                    message.quant_parameter_tensor_names.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TensorAnnotation();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"tensor_name\":\n                    message.tensor_name = reader.string();\n                    break;\n                case \"quant_parameter_tensor_names\":\n                    message.quant_parameter_tensor_names.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TensorAnnotation();\n        if ('tensorName' in obj) {\n            message.tensor_name = obj.tensorName;\n        }\n        if ('quantParameterTensorNames' in obj) {\n            message.quant_parameter_tensor_names = obj.quantParameterTensorNames.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.TensorAnnotation.prototype.tensor_name = \"\";\n\nonnx.GraphProto = class GraphProto {\n\n    constructor() {\n        this.node = [];\n        this.initializer = [];\n        this.sparse_initializer = [];\n        this.input = [];\n        this.output = [];\n        this.value_info = [];\n        this.quantization_annotation = [];\n        this.metadata_props = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.GraphProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.node.push(onnx.NodeProto.decode(reader, reader.uint32()));\n                    break;\n                case 2:\n                    message.name = reader.string();\n                    break;\n                case 5:\n                    message.initializer.push(onnx.TensorProto.decode(reader, reader.uint32()));\n                    break;\n                case 15:\n                    message.sparse_initializer.push(onnx.SparseTensorProto.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.doc_string = reader.string();\n                    break;\n                case 11:\n                    message.input.push(onnx.ValueInfoProto.decode(reader, reader.uint32()));\n                    break;\n                case 12:\n                    message.output.push(onnx.ValueInfoProto.decode(reader, reader.uint32()));\n                    break;\n                case 13:\n                    message.value_info.push(onnx.ValueInfoProto.decode(reader, reader.uint32()));\n                    break;\n                case 14:\n                    message.quantization_annotation.push(onnx.TensorAnnotation.decode(reader, reader.uint32()));\n                    break;\n                case 16:\n                    message.metadata_props.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.GraphProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"node\":\n                    message.node.push(onnx.NodeProto.decodeText(reader));\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"initializer\":\n                    message.initializer.push(onnx.TensorProto.decodeText(reader));\n                    break;\n                case \"sparse_initializer\":\n                    message.sparse_initializer.push(onnx.SparseTensorProto.decodeText(reader));\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"input\":\n                    message.input.push(onnx.ValueInfoProto.decodeText(reader));\n                    break;\n                case \"output\":\n                    message.output.push(onnx.ValueInfoProto.decodeText(reader));\n                    break;\n                case \"value_info\":\n                    message.value_info.push(onnx.ValueInfoProto.decodeText(reader));\n                    break;\n                case \"quantization_annotation\":\n                    message.quantization_annotation.push(onnx.TensorAnnotation.decodeText(reader));\n                    break;\n                case \"metadata_props\":\n                    message.metadata_props.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.GraphProto();\n        if ('node' in obj) {\n            message.node = obj.node.map((obj) => onnx.NodeProto.decodeJson(obj));\n        }\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('initializer' in obj) {\n            message.initializer = obj.initializer.map((obj) => onnx.TensorProto.decodeJson(obj));\n        }\n        if ('sparseInitializer' in obj) {\n            message.sparse_initializer = obj.sparseInitializer.map((obj) => onnx.SparseTensorProto.decodeJson(obj));\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('input' in obj) {\n            message.input = obj.input.map((obj) => onnx.ValueInfoProto.decodeJson(obj));\n        }\n        if ('output' in obj) {\n            message.output = obj.output.map((obj) => onnx.ValueInfoProto.decodeJson(obj));\n        }\n        if ('valueInfo' in obj) {\n            message.value_info = obj.valueInfo.map((obj) => onnx.ValueInfoProto.decodeJson(obj));\n        }\n        if ('quantizationAnnotation' in obj) {\n            message.quantization_annotation = obj.quantizationAnnotation.map((obj) => onnx.TensorAnnotation.decodeJson(obj));\n        }\n        if ('metadataProps' in obj) {\n            message.metadata_props = obj.metadataProps.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.GraphProto.prototype.name = \"\";\nonnx.GraphProto.prototype.doc_string = \"\";\n\nonnx.TensorProto = class TensorProto {\n\n    constructor() {\n        this.dims = [];\n        this.float_data = [];\n        this.int32_data = [];\n        this.string_data = [];\n        this.int64_data = [];\n        this.external_data = [];\n        this.double_data = [];\n        this.uint64_data = [];\n        this.metadata_props = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.TensorProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dims = reader.array(message.dims, () => reader.int64(), tag);\n                    break;\n                case 2:\n                    message.data_type = reader.int32();\n                    break;\n                case 3:\n                    message.segment = onnx.TensorProto.Segment.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.float_data = reader.floats(message.float_data, tag);\n                    break;\n                case 5:\n                    message.int32_data = reader.array(message.int32_data, () => reader.int32(), tag);\n                    break;\n                case 6:\n                    message.string_data.push(reader.bytes());\n                    break;\n                case 7:\n                    message.int64_data = reader.array(message.int64_data, () => reader.int64(), tag);\n                    break;\n                case 8:\n                    message.name = reader.string();\n                    break;\n                case 12:\n                    message.doc_string = reader.string();\n                    break;\n                case 9:\n                    message.raw_data = reader.bytes();\n                    break;\n                case 13:\n                    message.external_data.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                case 14:\n                    message.data_location = reader.int32();\n                    break;\n                case 10:\n                    message.double_data = reader.doubles(message.double_data, tag);\n                    break;\n                case 11:\n                    message.uint64_data = reader.array(message.uint64_data, () => reader.uint64(), tag);\n                    break;\n                case 16:\n                    message.metadata_props.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TensorProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dims\":\n                    reader.array(message.dims, () => reader.int64());\n                    break;\n                case \"data_type\":\n                    message.data_type = reader.int32();\n                    break;\n                case \"segment\":\n                    message.segment = onnx.TensorProto.Segment.decodeText(reader);\n                    break;\n                case \"float_data\":\n                    reader.array(message.float_data, () => reader.float());\n                    break;\n                case \"int32_data\":\n                    reader.array(message.int32_data, () => reader.int32());\n                    break;\n                case \"string_data\":\n                    reader.array(message.string_data, () => reader.bytes());\n                    break;\n                case \"int64_data\":\n                    reader.array(message.int64_data, () => reader.int64());\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"raw_data\":\n                    message.raw_data = reader.bytes();\n                    break;\n                case \"external_data\":\n                    message.external_data.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                case \"data_location\":\n                    message.data_location = reader.enum(onnx.TensorProto.DataLocation);\n                    break;\n                case \"double_data\":\n                    reader.array(message.double_data, () => reader.double());\n                    break;\n                case \"uint64_data\":\n                    reader.array(message.uint64_data, () => reader.uint64());\n                    break;\n                case \"metadata_props\":\n                    message.metadata_props.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TensorProto();\n        if ('dims' in obj) {\n            message.dims = obj.dims.map((obj) => BigInt(obj));\n        }\n        if ('dataType' in obj) {\n            message.data_type = Number(obj.dataType);\n        }\n        if ('segment' in obj) {\n            message.segment = onnx.TensorProto.Segment.decodeJson(obj.segment);\n        }\n        if ('floatData' in obj) {\n            message.float_data = obj.floatData.map((obj) => Number(obj));\n        }\n        if ('int32Data' in obj) {\n            message.int32_data = obj.int32Data.map((obj) => Number(obj));\n        }\n        if ('stringData' in obj) {\n            message.string_data = obj.stringData.map((obj) => typeof obj === 'string' ? Uint8Array.from(atob(obj), (c) => c.charCodeAt(0)) : Uint8Array.from(obj));\n        }\n        if ('int64Data' in obj) {\n            message.int64_data = obj.int64Data.map((obj) => BigInt(obj));\n        }\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('rawData' in obj) {\n            message.raw_data = typeof obj.rawData === 'string' ? Uint8Array.from(atob(obj.rawData), (c) => c.charCodeAt(0)) : Uint8Array.from(obj.rawData);\n        }\n        if ('externalData' in obj) {\n            message.external_data = obj.externalData.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        if ('dataLocation' in obj) {\n            message.data_location = typeof obj.dataLocation === 'string' ? onnx.TensorProto.DataLocation[obj.dataLocation] : obj.dataLocation;\n        }\n        if ('doubleData' in obj) {\n            message.double_data = obj.doubleData.map((obj) => Number(obj));\n        }\n        if ('uint64Data' in obj) {\n            message.uint64_data = obj.uint64Data.map((obj) => BigInt(obj));\n        }\n        if ('metadataProps' in obj) {\n            message.metadata_props = obj.metadataProps.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.TensorProto.prototype.data_type = 0;\nonnx.TensorProto.prototype.segment = null;\nonnx.TensorProto.prototype.name = \"\";\nonnx.TensorProto.prototype.doc_string = \"\";\nonnx.TensorProto.prototype.raw_data = new Uint8Array([]);\nonnx.TensorProto.prototype.data_location = 0;\n\nonnx.TensorProto.DataType = {\n    \"UNDEFINED\": 0,\n    \"FLOAT\": 1,\n    \"UINT8\": 2,\n    \"INT8\": 3,\n    \"UINT16\": 4,\n    \"INT16\": 5,\n    \"INT32\": 6,\n    \"INT64\": 7,\n    \"STRING\": 8,\n    \"BOOL\": 9,\n    \"FLOAT16\": 10,\n    \"DOUBLE\": 11,\n    \"UINT32\": 12,\n    \"UINT64\": 13,\n    \"COMPLEX64\": 14,\n    \"COMPLEX128\": 15,\n    \"BFLOAT16\": 16,\n    \"FLOAT8E4M3FN\": 17,\n    \"FLOAT8E4M3FNUZ\": 18,\n    \"FLOAT8E5M2\": 19,\n    \"FLOAT8E5M2FNUZ\": 20,\n    \"UINT4\": 21,\n    \"INT4\": 22,\n    \"FLOAT4E2M1\": 23,\n    \"FLOAT8E8M0\": 24,\n    \"UINT2\": 25,\n    \"INT2\": 26\n};\n\nonnx.TensorProto.Segment = class Segment {\n\n    static decode(reader, length) {\n        const message = new onnx.TensorProto.Segment();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.begin = reader.int64();\n                    break;\n                case 2:\n                    message.end = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TensorProto.Segment();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"begin\":\n                    message.begin = reader.int64();\n                    break;\n                case \"end\":\n                    message.end = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TensorProto.Segment();\n        if ('begin' in obj) {\n            message.begin = BigInt(obj.begin);\n        }\n        if ('end' in obj) {\n            message.end = BigInt(obj.end);\n        }\n        return message;\n    }\n};\n\nonnx.TensorProto.Segment.prototype.begin = 0n;\nonnx.TensorProto.Segment.prototype.end = 0n;\n\nonnx.TensorProto.DataLocation = {\n    \"DEFAULT\": 0,\n    \"EXTERNAL\": 1\n};\n\nonnx.SparseTensorProto = class SparseTensorProto {\n\n    constructor() {\n        this.dims = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.SparseTensorProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.values = onnx.TensorProto.decode(reader, reader.uint32());\n                    break;\n                case 2:\n                    message.indices = onnx.TensorProto.decode(reader, reader.uint32());\n                    break;\n                case 3:\n                    message.dims = reader.array(message.dims, () => reader.int64(), tag);\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.SparseTensorProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"values\":\n                    message.values = onnx.TensorProto.decodeText(reader);\n                    break;\n                case \"indices\":\n                    message.indices = onnx.TensorProto.decodeText(reader);\n                    break;\n                case \"dims\":\n                    reader.array(message.dims, () => reader.int64());\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.SparseTensorProto();\n        if ('values' in obj) {\n            message.values = onnx.TensorProto.decodeJson(obj.values);\n        }\n        if ('indices' in obj) {\n            message.indices = onnx.TensorProto.decodeJson(obj.indices);\n        }\n        if ('dims' in obj) {\n            message.dims = obj.dims.map((obj) => BigInt(obj));\n        }\n        return message;\n    }\n};\n\nonnx.SparseTensorProto.prototype.values = null;\nonnx.SparseTensorProto.prototype.indices = null;\n\nonnx.TensorShapeProto = class TensorShapeProto {\n\n    constructor() {\n        this.dim = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.TensorShapeProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim.push(onnx.TensorShapeProto.Dimension.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TensorShapeProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim\":\n                    message.dim.push(onnx.TensorShapeProto.Dimension.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TensorShapeProto();\n        if ('dim' in obj) {\n            message.dim = obj.dim.map((obj) => onnx.TensorShapeProto.Dimension.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.TensorShapeProto.Dimension = class Dimension {\n\n    get value() {\n        onnx.TensorShapeProto.Dimension.valueSet = onnx.TensorShapeProto.Dimension.valueSet || new Set([\"dim_value\", \"dim_param\"]);\n        return Object.keys(this).find((key) => onnx.TensorShapeProto.Dimension.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.TensorShapeProto.Dimension();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.dim_value = reader.int64();\n                    break;\n                case 2:\n                    message.dim_param = reader.string();\n                    break;\n                case 3:\n                    message.denotation = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TensorShapeProto.Dimension();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"dim_value\":\n                    message.dim_value = reader.int64();\n                    break;\n                case \"dim_param\":\n                    message.dim_param = reader.string();\n                    break;\n                case \"denotation\":\n                    message.denotation = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TensorShapeProto.Dimension();\n        if ('dimValue' in obj) {\n            message.dim_value = BigInt(obj.dimValue);\n        }\n        if ('dimParam' in obj) {\n            message.dim_param = obj.dimParam;\n        }\n        if ('denotation' in obj) {\n            message.denotation = obj.denotation;\n        }\n        return message;\n    }\n};\n\nonnx.TensorShapeProto.Dimension.prototype.denotation = \"\";\n\nonnx.TypeProto = class TypeProto {\n\n    get value() {\n        onnx.TypeProto.valueSet = onnx.TypeProto.valueSet || new Set([\"tensor_type\", \"sequence_type\", \"map_type\", \"optional_type\", \"sparse_tensor_type\", \"opaque_type\"]);\n        return Object.keys(this).find((key) => onnx.TypeProto.valueSet.has(key) && this[key] !== null);\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.tensor_type = onnx.TypeProto.Tensor.decode(reader, reader.uint32());\n                    break;\n                case 4:\n                    message.sequence_type = onnx.TypeProto.Sequence.decode(reader, reader.uint32());\n                    break;\n                case 5:\n                    message.map_type = onnx.TypeProto.Map.decode(reader, reader.uint32());\n                    break;\n                case 9:\n                    message.optional_type = onnx.TypeProto.Optional.decode(reader, reader.uint32());\n                    break;\n                case 8:\n                    message.sparse_tensor_type = onnx.TypeProto.SparseTensor.decode(reader, reader.uint32());\n                    break;\n                case 7:\n                    message.opaque_type = onnx.TypeProto.Opaque.decode(reader, reader.uint32());\n                    break;\n                case 6:\n                    message.denotation = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"tensor_type\":\n                    message.tensor_type = onnx.TypeProto.Tensor.decodeText(reader);\n                    break;\n                case \"sequence_type\":\n                    message.sequence_type = onnx.TypeProto.Sequence.decodeText(reader);\n                    break;\n                case \"map_type\":\n                    message.map_type = onnx.TypeProto.Map.decodeText(reader);\n                    break;\n                case \"optional_type\":\n                    message.optional_type = onnx.TypeProto.Optional.decodeText(reader);\n                    break;\n                case \"sparse_tensor_type\":\n                    message.sparse_tensor_type = onnx.TypeProto.SparseTensor.decodeText(reader);\n                    break;\n                case \"opaque_type\":\n                    message.opaque_type = onnx.TypeProto.Opaque.decodeText(reader);\n                    break;\n                case \"denotation\":\n                    message.denotation = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto();\n        if ('tensorType' in obj) {\n            message.tensor_type = onnx.TypeProto.Tensor.decodeJson(obj.tensorType);\n        }\n        if ('sequenceType' in obj) {\n            message.sequence_type = onnx.TypeProto.Sequence.decodeJson(obj.sequenceType);\n        }\n        if ('mapType' in obj) {\n            message.map_type = onnx.TypeProto.Map.decodeJson(obj.mapType);\n        }\n        if ('optionalType' in obj) {\n            message.optional_type = onnx.TypeProto.Optional.decodeJson(obj.optionalType);\n        }\n        if ('sparseTensorType' in obj) {\n            message.sparse_tensor_type = onnx.TypeProto.SparseTensor.decodeJson(obj.sparseTensorType);\n        }\n        if ('opaqueType' in obj) {\n            message.opaque_type = onnx.TypeProto.Opaque.decodeJson(obj.opaqueType);\n        }\n        if ('denotation' in obj) {\n            message.denotation = obj.denotation;\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.prototype.denotation = \"\";\n\nonnx.TypeProto.Tensor = class Tensor {\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto.Tensor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.elem_type = reader.int32();\n                    break;\n                case 2:\n                    message.shape = onnx.TensorShapeProto.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto.Tensor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"elem_type\":\n                    message.elem_type = reader.int32();\n                    break;\n                case \"shape\":\n                    message.shape = onnx.TensorShapeProto.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto.Tensor();\n        if ('elemType' in obj) {\n            message.elem_type = Number(obj.elemType);\n        }\n        if ('shape' in obj) {\n            message.shape = onnx.TensorShapeProto.decodeJson(obj.shape);\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.Tensor.prototype.elem_type = 0;\nonnx.TypeProto.Tensor.prototype.shape = null;\n\nonnx.TypeProto.Sequence = class Sequence {\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto.Sequence();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.elem_type = onnx.TypeProto.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto.Sequence();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"elem_type\":\n                    message.elem_type = onnx.TypeProto.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto.Sequence();\n        if ('elemType' in obj) {\n            message.elem_type = onnx.TypeProto.decodeJson(obj.elemType);\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.Sequence.prototype.elem_type = null;\n\nonnx.TypeProto.Map = class Map {\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto.Map();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.key_type = reader.int32();\n                    break;\n                case 2:\n                    message.value_type = onnx.TypeProto.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto.Map();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"key_type\":\n                    message.key_type = reader.int32();\n                    break;\n                case \"value_type\":\n                    message.value_type = onnx.TypeProto.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto.Map();\n        if ('keyType' in obj) {\n            message.key_type = Number(obj.keyType);\n        }\n        if ('valueType' in obj) {\n            message.value_type = onnx.TypeProto.decodeJson(obj.valueType);\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.Map.prototype.key_type = 0;\nonnx.TypeProto.Map.prototype.value_type = null;\n\nonnx.TypeProto.Optional = class Optional {\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto.Optional();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.elem_type = onnx.TypeProto.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto.Optional();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"elem_type\":\n                    message.elem_type = onnx.TypeProto.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto.Optional();\n        if ('elemType' in obj) {\n            message.elem_type = onnx.TypeProto.decodeJson(obj.elemType);\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.Optional.prototype.elem_type = null;\n\nonnx.TypeProto.SparseTensor = class SparseTensor {\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto.SparseTensor();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.elem_type = reader.int32();\n                    break;\n                case 2:\n                    message.shape = onnx.TensorShapeProto.decode(reader, reader.uint32());\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto.SparseTensor();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"elem_type\":\n                    message.elem_type = reader.int32();\n                    break;\n                case \"shape\":\n                    message.shape = onnx.TensorShapeProto.decodeText(reader);\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto.SparseTensor();\n        if ('elemType' in obj) {\n            message.elem_type = Number(obj.elemType);\n        }\n        if ('shape' in obj) {\n            message.shape = onnx.TensorShapeProto.decodeJson(obj.shape);\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.SparseTensor.prototype.elem_type = 0;\nonnx.TypeProto.SparseTensor.prototype.shape = null;\n\nonnx.TypeProto.Opaque = class Opaque {\n\n    static decode(reader, length) {\n        const message = new onnx.TypeProto.Opaque();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.domain = reader.string();\n                    break;\n                case 2:\n                    message.name = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.TypeProto.Opaque();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.TypeProto.Opaque();\n        if ('domain' in obj) {\n            message.domain = obj.domain;\n        }\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        return message;\n    }\n};\n\nonnx.TypeProto.Opaque.prototype.domain = \"\";\nonnx.TypeProto.Opaque.prototype.name = \"\";\n\nonnx.OperatorSetIdProto = class OperatorSetIdProto {\n\n    static decode(reader, length) {\n        const message = new onnx.OperatorSetIdProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.domain = reader.string();\n                    break;\n                case 2:\n                    message.version = reader.int64();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.OperatorSetIdProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"version\":\n                    message.version = reader.int64();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.OperatorSetIdProto();\n        if ('domain' in obj) {\n            message.domain = obj.domain;\n        }\n        if ('version' in obj) {\n            message.version = BigInt(obj.version);\n        }\n        return message;\n    }\n};\n\nonnx.OperatorSetIdProto.prototype.domain = \"\";\nonnx.OperatorSetIdProto.prototype.version = 0n;\n\nonnx.OperatorStatus = {\n    \"EXPERIMENTAL\": 0,\n    \"STABLE\": 1\n};\n\nonnx.FunctionProto = class FunctionProto {\n\n    constructor() {\n        this.input = [];\n        this.output = [];\n        this.attribute = [];\n        this.attribute_proto = [];\n        this.node = [];\n        this.opset_import = [];\n        this.value_info = [];\n        this.metadata_props = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.FunctionProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.name = reader.string();\n                    break;\n                case 4:\n                    message.input.push(reader.string());\n                    break;\n                case 5:\n                    message.output.push(reader.string());\n                    break;\n                case 6:\n                    message.attribute.push(reader.string());\n                    break;\n                case 11:\n                    message.attribute_proto.push(onnx.AttributeProto.decode(reader, reader.uint32()));\n                    break;\n                case 7:\n                    message.node.push(onnx.NodeProto.decode(reader, reader.uint32()));\n                    break;\n                case 8:\n                    message.doc_string = reader.string();\n                    break;\n                case 9:\n                    message.opset_import.push(onnx.OperatorSetIdProto.decode(reader, reader.uint32()));\n                    break;\n                case 10:\n                    message.domain = reader.string();\n                    break;\n                case 13:\n                    message.overload = reader.string();\n                    break;\n                case 12:\n                    message.value_info.push(onnx.ValueInfoProto.decode(reader, reader.uint32()));\n                    break;\n                case 14:\n                    message.metadata_props.push(onnx.StringStringEntryProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.FunctionProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"name\":\n                    message.name = reader.string();\n                    break;\n                case \"input\":\n                    reader.array(message.input, () => reader.string());\n                    break;\n                case \"output\":\n                    reader.array(message.output, () => reader.string());\n                    break;\n                case \"attribute\":\n                    reader.array(message.attribute, () => reader.string());\n                    break;\n                case \"attribute_proto\":\n                    message.attribute_proto.push(onnx.AttributeProto.decodeText(reader));\n                    break;\n                case \"node\":\n                    message.node.push(onnx.NodeProto.decodeText(reader));\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"opset_import\":\n                    message.opset_import.push(onnx.OperatorSetIdProto.decodeText(reader));\n                    break;\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"overload\":\n                    message.overload = reader.string();\n                    break;\n                case \"value_info\":\n                    message.value_info.push(onnx.ValueInfoProto.decodeText(reader));\n                    break;\n                case \"metadata_props\":\n                    message.metadata_props.push(onnx.StringStringEntryProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.FunctionProto();\n        if ('name' in obj) {\n            message.name = obj.name;\n        }\n        if ('input' in obj) {\n            message.input = obj.input;\n        }\n        if ('output' in obj) {\n            message.output = obj.output;\n        }\n        if ('attribute' in obj) {\n            message.attribute = obj.attribute;\n        }\n        if ('attributeProto' in obj) {\n            message.attribute_proto = obj.attributeProto.map((obj) => onnx.AttributeProto.decodeJson(obj));\n        }\n        if ('node' in obj) {\n            message.node = obj.node.map((obj) => onnx.NodeProto.decodeJson(obj));\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('opsetImport' in obj) {\n            message.opset_import = obj.opsetImport.map((obj) => onnx.OperatorSetIdProto.decodeJson(obj));\n        }\n        if ('domain' in obj) {\n            message.domain = obj.domain;\n        }\n        if ('overload' in obj) {\n            message.overload = obj.overload;\n        }\n        if ('valueInfo' in obj) {\n            message.value_info = obj.valueInfo.map((obj) => onnx.ValueInfoProto.decodeJson(obj));\n        }\n        if ('metadataProps' in obj) {\n            message.metadata_props = obj.metadataProps.map((obj) => onnx.StringStringEntryProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.FunctionProto.prototype.name = \"\";\nonnx.FunctionProto.prototype.doc_string = \"\";\nonnx.FunctionProto.prototype.domain = \"\";\nonnx.FunctionProto.prototype.overload = \"\";\n\nonnx.OperatorProto = class OperatorProto {\n\n    static decode(reader, length) {\n        const message = new onnx.OperatorProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.op_type = reader.string();\n                    break;\n                case 2:\n                    message.since_version = reader.int64();\n                    break;\n                case 3:\n                    message.status = reader.int32();\n                    break;\n                case 10:\n                    message.doc_string = reader.string();\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.OperatorProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"op_type\":\n                    message.op_type = reader.string();\n                    break;\n                case \"since_version\":\n                    message.since_version = reader.int64();\n                    break;\n                case \"status\":\n                    message.status = reader.enum(onnx.OperatorStatus);\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.OperatorProto();\n        if ('opType' in obj) {\n            message.op_type = obj.opType;\n        }\n        if ('sinceVersion' in obj) {\n            message.since_version = BigInt(obj.sinceVersion);\n        }\n        if ('status' in obj) {\n            message.status = typeof obj.status === 'string' ? onnx.OperatorStatus[obj.status] : obj.status;\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        return message;\n    }\n};\n\nonnx.OperatorProto.prototype.op_type = \"\";\nonnx.OperatorProto.prototype.since_version = 0n;\nonnx.OperatorProto.prototype.status = 0;\nonnx.OperatorProto.prototype.doc_string = \"\";\n\nonnx.OperatorSetProto = class OperatorSetProto {\n\n    constructor() {\n        this.operator = [];\n        this.functions = [];\n    }\n\n    static decode(reader, length) {\n        const message = new onnx.OperatorSetProto();\n        const end = length === undefined ? reader.length : reader.position + length;\n        while (reader.position < end) {\n            const tag = reader.uint32();\n            switch (tag >>> 3) {\n                case 1:\n                    message.magic = reader.string();\n                    break;\n                case 2:\n                    message.ir_version = reader.int64();\n                    break;\n                case 3:\n                    message.ir_version_prerelease = reader.string();\n                    break;\n                case 7:\n                    message.ir_build_metadata = reader.string();\n                    break;\n                case 4:\n                    message.domain = reader.string();\n                    break;\n                case 5:\n                    message.opset_version = reader.int64();\n                    break;\n                case 6:\n                    message.doc_string = reader.string();\n                    break;\n                case 8:\n                    message.operator.push(onnx.OperatorProto.decode(reader, reader.uint32()));\n                    break;\n                case 9:\n                    message.functions.push(onnx.FunctionProto.decode(reader, reader.uint32()));\n                    break;\n                default:\n                    reader.skipType(tag & 7);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeText(reader) {\n        const message = new onnx.OperatorSetProto();\n        reader.start();\n        while (!reader.end()) {\n            const tag = reader.tag();\n            switch (tag) {\n                case \"magic\":\n                    message.magic = reader.string();\n                    break;\n                case \"ir_version\":\n                    message.ir_version = reader.int64();\n                    break;\n                case \"ir_version_prerelease\":\n                    message.ir_version_prerelease = reader.string();\n                    break;\n                case \"ir_build_metadata\":\n                    message.ir_build_metadata = reader.string();\n                    break;\n                case \"domain\":\n                    message.domain = reader.string();\n                    break;\n                case \"opset_version\":\n                    message.opset_version = reader.int64();\n                    break;\n                case \"doc_string\":\n                    message.doc_string = reader.string();\n                    break;\n                case \"operator\":\n                    message.operator.push(onnx.OperatorProto.decodeText(reader));\n                    break;\n                case \"functions\":\n                    message.functions.push(onnx.FunctionProto.decodeText(reader));\n                    break;\n                default:\n                    reader.field(tag, message);\n                    break;\n            }\n        }\n        return message;\n    }\n\n    static decodeJson(obj) {\n        const message = new onnx.OperatorSetProto();\n        if ('magic' in obj) {\n            message.magic = obj.magic;\n        }\n        if ('irVersion' in obj) {\n            message.ir_version = BigInt(obj.irVersion);\n        }\n        if ('irVersionPrerelease' in obj) {\n            message.ir_version_prerelease = obj.irVersionPrerelease;\n        }\n        if ('irBuildMetadata' in obj) {\n            message.ir_build_metadata = obj.irBuildMetadata;\n        }\n        if ('domain' in obj) {\n            message.domain = obj.domain;\n        }\n        if ('opsetVersion' in obj) {\n            message.opset_version = BigInt(obj.opsetVersion);\n        }\n        if ('docString' in obj) {\n            message.doc_string = obj.docString;\n        }\n        if ('operator' in obj) {\n            message.operator = obj.operator.map((obj) => onnx.OperatorProto.decodeJson(obj));\n        }\n        if ('functions' in obj) {\n            message.functions = obj.functions.map((obj) => onnx.FunctionProto.decodeJson(obj));\n        }\n        return message;\n    }\n};\n\nonnx.OperatorSetProto.prototype.magic = \"\";\nonnx.OperatorSetProto.prototype.ir_version = 0n;\nonnx.OperatorSetProto.prototype.ir_version_prerelease = \"\";\nonnx.OperatorSetProto.prototype.ir_build_metadata = \"\";\nonnx.OperatorSetProto.prototype.domain = \"\";\nonnx.OperatorSetProto.prototype.opset_version = 0n;\nonnx.OperatorSetProto.prototype.doc_string = \"\";\n"
  },
  {
    "path": "source/onnx-schema.js",
    "content": "\nexport const onnxruntime = {};\n\nonnxruntime.fbs = onnxruntime.fbs || {};\n\nonnxruntime.fbs.AttributeType = {\n    UNDEFINED: 0, '0': 'UNDEFINED',\n    FLOAT: 1, '1': 'FLOAT',\n    INT: 2, '2': 'INT',\n    STRING: 3, '3': 'STRING',\n    TENSOR: 4, '4': 'TENSOR',\n    GRAPH: 5, '5': 'GRAPH',\n    FLOATS: 6, '6': 'FLOATS',\n    INTS: 7, '7': 'INTS',\n    STRINGS: 8, '8': 'STRINGS',\n    TENSORS: 9, '9': 'TENSORS',\n    GRAPHS: 10, '10': 'GRAPHS',\n    SPARSE_TENSOR: 11, '11': 'SPARSE_TENSOR',\n    SPARSE_TENSORS: 12, '12': 'SPARSE_TENSORS'\n};\n\nonnxruntime.fbs.Shape = class Shape {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Shape();\n        $.dim = reader.tables(position, 4, onnxruntime.fbs.Dimension);\n        return $;\n    }\n};\n\nonnxruntime.fbs.Dimension = class Dimension {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Dimension();\n        $.value = reader.table(position, 4, onnxruntime.fbs.DimensionValue);\n        $.denotation = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nonnxruntime.fbs.DimensionValueType = {\n    UNKNOWN: 0, '0': 'UNKNOWN',\n    VALUE: 1, '1': 'VALUE',\n    PARAM: 2, '2': 'PARAM'\n};\n\nonnxruntime.fbs.DimensionValue = class DimensionValue {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.DimensionValue();\n        $.dim_type = reader.int8_(position, 4, 0);\n        $.dim_value = reader.int64_(position, 6, 0n);\n        $.dim_param = reader.string_(position, 8, null);\n        return $;\n    }\n};\n\nonnxruntime.fbs.TensorDataType = {\n    UNDEFINED: 0, '0': 'UNDEFINED',\n    FLOAT: 1, '1': 'FLOAT',\n    UINT8: 2, '2': 'UINT8',\n    INT8: 3, '3': 'INT8',\n    UINT16: 4, '4': 'UINT16',\n    INT16: 5, '5': 'INT16',\n    INT32: 6, '6': 'INT32',\n    INT64: 7, '7': 'INT64',\n    STRING: 8, '8': 'STRING',\n    BOOL: 9, '9': 'BOOL',\n    FLOAT16: 10, '10': 'FLOAT16',\n    DOUBLE: 11, '11': 'DOUBLE',\n    UINT32: 12, '12': 'UINT32',\n    UINT64: 13, '13': 'UINT64',\n    COMPLEX64: 14, '14': 'COMPLEX64',\n    COMPLEX128: 15, '15': 'COMPLEX128',\n    BFLOAT16: 16, '16': 'BFLOAT16',\n    FLOAT8E4M3FN: 17, '17': 'FLOAT8E4M3FN',\n    FLOAT8E4M3FNUZ: 18, '18': 'FLOAT8E4M3FNUZ',\n    FLOAT8E5M2: 19, '19': 'FLOAT8E5M2',\n    FLOAT8E5M2FNUZ: 20, '20': 'FLOAT8E5M2FNUZ'\n};\n\nonnxruntime.fbs.TensorTypeAndShape = class TensorTypeAndShape {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.TensorTypeAndShape();\n        $.elem_type = reader.int32_(position, 4, 0);\n        $.shape = reader.table(position, 6, onnxruntime.fbs.Shape);\n        return $;\n    }\n};\n\nonnxruntime.fbs.MapType = class MapType {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.MapType();\n        $.key_type = reader.int32_(position, 4, 0);\n        $.value_type = reader.table(position, 6, onnxruntime.fbs.TypeInfo);\n        return $;\n    }\n};\n\nonnxruntime.fbs.SequenceType = class SequenceType {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.SequenceType();\n        $.elem_type = reader.table(position, 4, onnxruntime.fbs.TypeInfo);\n        return $;\n    }\n};\n\nonnxruntime.fbs.NodeType = {\n    Primitive: 0, '0': 'Primitive',\n    Fused: 1, '1': 'Fused'\n};\n\nonnxruntime.fbs.EdgeEnd = class EdgeEnd {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.EdgeEnd();\n        $.node_index = reader.uint32(position + 0);\n        $.src_arg_index = reader.int32(position + 4);\n        $.dst_arg_index = reader.int32(position + 8);\n        return $;\n    }\n};\n\nonnxruntime.fbs.NodeEdge = class NodeEdge {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.NodeEdge();\n        $.node_index = reader.uint32_(position, 4, 0);\n        $.input_edges = reader.structs(position, 6, onnxruntime.fbs.EdgeEnd, 12);\n        $.output_edges = reader.structs(position, 8, onnxruntime.fbs.EdgeEnd, 12);\n        return $;\n    }\n};\n\nonnxruntime.fbs.Node = class Node {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Node();\n        $.name = reader.string_(position, 4, null);\n        $.doc_string = reader.string_(position, 6, null);\n        $.domain = reader.string_(position, 8, null);\n        $.since_version = reader.int32_(position, 10, 0);\n        $.index = reader.uint32_(position, 12, 0);\n        $.op_type = reader.string_(position, 14, null);\n        $.type = reader.int32_(position, 16, 0);\n        $.execution_provider_type = reader.string_(position, 18, null);\n        $.inputs = reader.strings_(position, 20);\n        $.outputs = reader.strings_(position, 22);\n        $.attributes = reader.tables(position, 24, onnxruntime.fbs.Attribute);\n        $.input_arg_counts = reader.array(position, 26, Int32Array);\n        $.implicit_inputs = reader.strings_(position, 28);\n        return $;\n    }\n};\n\nonnxruntime.fbs.ValueInfo = class ValueInfo {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.ValueInfo();\n        $.name = reader.string_(position, 4, null);\n        $.doc_string = reader.string_(position, 6, null);\n        $.type = reader.table(position, 8, onnxruntime.fbs.TypeInfo);\n        return $;\n    }\n};\n\nonnxruntime.fbs.TypeInfoValue = class {\n\n    static decode(reader, position, type) {\n        switch (type) {\n            case 1: return onnxruntime.fbs.TensorTypeAndShape.decode(reader, position);\n            case 2: return onnxruntime.fbs.SequenceType.decode(reader, position);\n            case 3: return onnxruntime.fbs.MapType.decode(reader, position);\n            default: return undefined;\n        }\n    }\n};\n\nonnxruntime.fbs.TypeInfo = class TypeInfo {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.TypeInfo();\n        $.denotation = reader.string_(position, 4, null);\n        $.value = reader.union(position, 6, onnxruntime.fbs.TypeInfoValue);\n        return $;\n    }\n};\n\nonnxruntime.fbs.OperatorSetId = class OperatorSetId {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.OperatorSetId();\n        $.domain = reader.string_(position, 4, null);\n        $.version = reader.int64_(position, 6, 0n);\n        return $;\n    }\n};\n\nonnxruntime.fbs.Tensor = class Tensor {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Tensor();\n        $.name = reader.string_(position, 4, null);\n        $.doc_string = reader.string_(position, 6, null);\n        $.dims = reader.int64s_(position, 8);\n        $.data_type = reader.int32_(position, 10, 0);\n        $.raw_data = reader.array(position, 12, Uint8Array);\n        $.string_data = reader.strings_(position, 14);\n        $.external_data_offset = reader.int64_(position, 16, -1n);\n        return $;\n    }\n};\n\nonnxruntime.fbs.SparseTensor = class SparseTensor {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.SparseTensor();\n        $.values = reader.table(position, 4, onnxruntime.fbs.Tensor);\n        $.indices = reader.table(position, 6, onnxruntime.fbs.Tensor);\n        $.dims = reader.int64s_(position, 8);\n        return $;\n    }\n};\n\nonnxruntime.fbs.Attribute = class Attribute {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Attribute();\n        $.name = reader.string_(position, 4, null);\n        $.doc_string = reader.string_(position, 6, null);\n        $.type = reader.int32_(position, 8, 0);\n        $.f = reader.float32_(position, 10, 0);\n        $.i = reader.int64_(position, 12, 0n);\n        $.s = reader.string_(position, 14, null);\n        $.t = reader.table(position, 16, onnxruntime.fbs.Tensor);\n        $.g = reader.table(position, 18, onnxruntime.fbs.Graph);\n        $.floats = reader.array(position, 20, Float32Array);\n        $.ints = reader.int64s_(position, 22);\n        $.strings = reader.strings_(position, 24);\n        $.tensors = reader.tables(position, 26, onnxruntime.fbs.Tensor);\n        $.graphs = reader.tables(position, 28, onnxruntime.fbs.Graph);\n        return $;\n    }\n};\n\nonnxruntime.fbs.NodesToOptimizeIndices = class NodesToOptimizeIndices {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.NodesToOptimizeIndices();\n        $.node_indices = reader.array(position, 4, Uint32Array);\n        $.num_inputs = reader.uint32_(position, 6, 0);\n        $.num_outputs = reader.uint32_(position, 8, 0);\n        $.has_variadic_input = reader.bool_(position, 10, false);\n        $.has_variadic_output = reader.bool_(position, 12, false);\n        $.num_variadic_inputs = reader.uint32_(position, 14, 0);\n        $.num_variadic_outputs = reader.uint32_(position, 16, 0);\n        return $;\n    }\n};\n\nonnxruntime.fbs.DeprecatedNodeIndexAndKernelDefHash = class DeprecatedNodeIndexAndKernelDefHash {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.DeprecatedNodeIndexAndKernelDefHash();\n        $.node_index = reader.uint32_(position, 4, 0);\n        $.kernel_def_hash = reader.uint64_(position, 6, 0n);\n        return $;\n    }\n};\n\nonnxruntime.fbs.RuntimeOptimizationRecord = class RuntimeOptimizationRecord {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.RuntimeOptimizationRecord();\n        $.action_id = reader.string_(position, 4, null);\n        $.nodes_to_optimize_indices = reader.table(position, 6, onnxruntime.fbs.NodesToOptimizeIndices);\n        $.produced_nodes = reader.tables(position, 8, onnxruntime.fbs.DeprecatedNodeIndexAndKernelDefHash);\n        $.produced_op_ids = reader.strings_(position, 10);\n        return $;\n    }\n};\n\nonnxruntime.fbs.RuntimeOptimizationRecordContainerEntry = class RuntimeOptimizationRecordContainerEntry {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry();\n        $.optimizer_name = reader.string_(position, 4, null);\n        $.runtime_optimization_records = reader.tables(position, 6, onnxruntime.fbs.RuntimeOptimizationRecord);\n        return $;\n    }\n};\n\nonnxruntime.fbs.RuntimeOptimizations = class RuntimeOptimizations {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.RuntimeOptimizations();\n        $.records = reader.tables(position, 4, onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry);\n        return $;\n    }\n};\n\nonnxruntime.fbs.Graph = class Graph {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Graph();\n        $.initializers = reader.tables(position, 4, onnxruntime.fbs.Tensor);\n        $.node_args = reader.tables(position, 6, onnxruntime.fbs.ValueInfo);\n        $.nodes = reader.tables(position, 8, onnxruntime.fbs.Node);\n        $.max_node_index = reader.uint32_(position, 10, 0);\n        $.node_edges = reader.tables(position, 12, onnxruntime.fbs.NodeEdge);\n        $.inputs = reader.strings_(position, 14);\n        $.outputs = reader.strings_(position, 16);\n        $.sparse_initializers = reader.tables(position, 18, onnxruntime.fbs.SparseTensor);\n        $.runtime_optimizations = reader.table(position, 20, onnxruntime.fbs.RuntimeOptimizations);\n        return $;\n    }\n};\n\nonnxruntime.fbs.StringStringEntry = class StringStringEntry {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.StringStringEntry();\n        $.key = reader.string_(position, 4, null);\n        $.value = reader.string_(position, 6, null);\n        return $;\n    }\n};\n\nonnxruntime.fbs.Model = class Model {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.Model();\n        $.ir_version = reader.int64_(position, 4, 0n);\n        $.opset_import = reader.tables(position, 6, onnxruntime.fbs.OperatorSetId);\n        $.producer_name = reader.string_(position, 8, null);\n        $.producer_version = reader.string_(position, 10, null);\n        $.domain = reader.string_(position, 12, null);\n        $.model_version = reader.int64_(position, 14, 0n);\n        $.doc_string = reader.string_(position, 16, null);\n        $.graph = reader.table(position, 18, onnxruntime.fbs.Graph);\n        $.graph_doc_string = reader.string_(position, 20, null);\n        $.metadata_props = reader.tables(position, 22, onnxruntime.fbs.StringStringEntry);\n        return $;\n    }\n};\n\nonnxruntime.fbs.DeprecatedKernelCreateInfos = class DeprecatedKernelCreateInfos {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.DeprecatedKernelCreateInfos();\n        $.node_indices = reader.array(position, 4, Uint32Array);\n        $.kernel_def_hashes = reader.uint64s_(position, 6);\n        return $;\n    }\n};\n\nonnxruntime.fbs.DeprecatedSubGraphSessionState = class DeprecatedSubGraphSessionState {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.DeprecatedSubGraphSessionState();\n        $.graph_id = reader.string_(position, 4, null);\n        $.session_state = reader.table(position, 6, onnxruntime.fbs.DeprecatedSessionState);\n        return $;\n    }\n};\n\nonnxruntime.fbs.DeprecatedSessionState = class DeprecatedSessionState {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.DeprecatedSessionState();\n        $.kernels = reader.table(position, 4, onnxruntime.fbs.DeprecatedKernelCreateInfos);\n        $.sub_graph_session_states = reader.tables(position, 6, onnxruntime.fbs.DeprecatedSubGraphSessionState);\n        return $;\n    }\n};\n\nonnxruntime.fbs.ArgType = {\n    INPUT: 0, '0': 'INPUT',\n    OUTPUT: 1, '1': 'OUTPUT'\n};\n\nonnxruntime.fbs.ArgTypeAndIndex = class ArgTypeAndIndex {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.ArgTypeAndIndex();\n        $.arg_type = reader.int8_(position, 4, 0);\n        $.index = reader.uint32_(position, 6, 0);\n        return $;\n    }\n};\n\nonnxruntime.fbs.KernelTypeStrArgsEntry = class KernelTypeStrArgsEntry {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.KernelTypeStrArgsEntry();\n        $.kernel_type_str = reader.string_(position, 4, null);\n        $.args = reader.tables(position, 6, onnxruntime.fbs.ArgTypeAndIndex);\n        return $;\n    }\n};\n\nonnxruntime.fbs.OpIdKernelTypeStrArgsEntry = class OpIdKernelTypeStrArgsEntry {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.OpIdKernelTypeStrArgsEntry();\n        $.op_id = reader.string_(position, 4, null);\n        $.kernel_type_str_args = reader.tables(position, 6, onnxruntime.fbs.KernelTypeStrArgsEntry);\n        return $;\n    }\n};\n\nonnxruntime.fbs.KernelTypeStrResolver = class KernelTypeStrResolver {\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.KernelTypeStrResolver();\n        $.op_kernel_type_str_args = reader.tables(position, 4, onnxruntime.fbs.OpIdKernelTypeStrArgsEntry);\n        return $;\n    }\n};\n\nonnxruntime.fbs.InferenceSession = class InferenceSession {\n\n    static identifier(reader) {\n        return reader.identifier === 'ORTM';\n    }\n\n    static create(reader) {\n        return onnxruntime.fbs.InferenceSession.decode(reader, reader.root);\n    }\n\n    static decode(reader, position) {\n        const $ = new onnxruntime.fbs.InferenceSession();\n        $.ort_version = reader.string_(position, 4, null);\n        $.model = reader.table(position, 6, onnxruntime.fbs.Model);\n        $.session_state = reader.table(position, 8, onnxruntime.fbs.DeprecatedSessionState);\n        $.kernel_type_str_resolver = reader.table(position, 10, onnxruntime.fbs.KernelTypeStrResolver);\n        return $;\n    }\n};\n"
  },
  {
    "path": "source/onnx.py",
    "content": "\"\"\" ONNX backend \"\"\"\n\nimport collections\nimport enum\nimport json\nimport os\n\n\nclass ModelFactory:\n    \"\"\" ONNX backend model factory \"\"\"\n    def open(self, model):\n        return _Model(model)\n\nclass _Model:\n    def __init__(self, model):\n        \"\"\" Serialize ONNX model to JSON message \"\"\"\n        # import onnx.shape_inference\n        # model = onnx.shape_inference.infer_shapes(model)\n        self.value = model\n        self.metadata = _Metadata()\n        self.graph = _Graph(model.graph, self.metadata)\n\n    def to_json(self):\n        \"\"\" Serialize model to JSON message \"\"\"\n        model = self.value\n        json_model = {}\n        json_model[\"signature\"] = \"netron:onnx\"\n        ir_version = model.ir_version\n        json_model[\"format\"] = \"ONNX\" + (f\" v{ir_version}\" if ir_version else \"\")\n        if model.producer_name and len(model.producer_name) > 0:\n            producer_version = model.producer_version\n            producer_version = f\" v{producer_version}\" if producer_version else \"\"\n            json_model[\"producer\"] = model.producer_name + producer_version\n        if model.model_version and model.model_version != 0:\n            json_model[\"version\"] = str(model.model_version)\n        if model.doc_string and len(model.doc_string):\n            json_model[\"description\"] = str(model.doc_string)\n        json_metadata = self._metadata_props(model.metadata_props)\n        if len(json_metadata) > 0:\n            json_model[\"metadata\"] = json_metadata\n        json_model[\"graphs\"] = []\n        json_model[\"graphs\"].append(self.graph.to_json())\n        return json_model\n\n    def _metadata_props(self, metadata_props):\n        json_metadata = []\n        metadata_props = [ [ entry.key, entry.value ] for entry in metadata_props ]\n        metadata = collections.OrderedDict(metadata_props)\n        value = metadata.get(\"converted_from\")\n        if value:\n            json_metadata.append({ \"name\": \"source\", \"value\": value })\n        value = metadata.get(\"author\")\n        if value:\n            json_metadata.append({ \"name\": \"author\", \"value\": value })\n        value = metadata.get(\"company\")\n        if value:\n            json_metadata.append({ \"name\": \"company\", \"value\": value })\n        value = metadata.get(\"license\")\n        license_url = metadata.get(\"license_url\")\n        if license_url:\n            value = f\"<a href='{license_url}'>{value if value else license_url}</a>\"\n        if value:\n            json_metadata.append({ \"name\": \"license\", \"value\": value })\n        if \"author\" in metadata:\n            metadata.pop(\"author\")\n        if \"company\" in metadata:\n            metadata.pop(\"company\")\n        if \"converted_from\" in metadata:\n            metadata.pop(\"converted_from\")\n        if \"license\" in metadata:\n            metadata.pop(\"license\")\n        if \"license_url\" in metadata:\n            metadata.pop(\"license_url\")\n        for name, value in metadata.items():\n            json_metadata.append({ \"name\": name, \"value\": value })\n        return json_metadata\n\nclass _Graph:\n    def __init__(self, graph, metadata):\n        self.metadata = metadata\n        self.graph = graph\n        self.values_index = {}\n        self.values = []\n\n    def _tensor(self, tensor):\n        return {}\n\n    def value(self, name, tensor_type=None, initializer=None):\n        if name not in self.values_index:\n            argument = _Value(name, tensor_type, initializer)\n            self.values_index[name] = len(self.values)\n            self.values.append(argument)\n        index = self.values_index[name]\n        # argument.set_initializer(initializer)\n        return index\n\n    def attribute(self, _, op_type):\n        if _.type == _AttributeType.UNDEFINED:\n            attribute_type = None\n            value = None\n        elif _.type == _AttributeType.FLOAT:\n            attribute_type = \"float32\"\n            value = _.f\n        elif _.type == _AttributeType.INT:\n            attribute_type = \"int64\"\n            value = _.i\n        elif _.type == _AttributeType.STRING:\n            attribute_type = \"string\"\n            encoding = \"latin1\" if op_type == \"Int8GivenTensorFill\" else \"utf-8\"\n            value = _.s.decode(encoding)\n        elif _.type == _AttributeType.TENSOR:\n            attribute_type = \"tensor\"\n            value = self._tensor(_.t)\n        elif _.type == _AttributeType.GRAPH:\n            attribute_type = \"graph\"\n            raise Exception(\"Unsupported graph attribute type\")\n        elif _.type == _AttributeType.FLOATS:\n            attribute_type = \"float32[]\"\n            value = list(_.floats)\n        elif _.type == _AttributeType.INTS:\n            attribute_type = \"int64[]\"\n            value = list(_.ints)\n        elif _.type == _AttributeType.STRINGS:\n            attribute_type = \"string[]\"\n            value = [ item.decode(\"utf-8\") for item in _.strings ]\n        elif _.type == _AttributeType.TENSORS:\n            attribute_type = \"tensor[]\"\n            raise Exception(\"Unsupported tensors attribute type\")\n        elif _.type == _AttributeType.GRAPHS:\n            attribute_type = \"graph[]\"\n            raise Exception(\"Unsupported graphs attribute type\")\n        elif _.type == _AttributeType.SPARSE_TENSOR:\n            attribute_type = \"tensor\"\n            value = self._tensor(_.sparse_tensor)\n        else:\n            raise Exception(\"Unsupported attribute type '\" + str(_.type) + \"'.\")\n        json_attribute = {}\n        json_attribute[\"name\"] = _.name\n        if attribute_type:\n            json_attribute[\"type\"] = attribute_type\n        json_attribute[\"value\"] = value\n        return json_attribute\n\n    def to_json(self):\n        graph = self.graph\n        json_graph = {\n            \"nodes\": [],\n            \"inputs\": [],\n            \"outputs\": [],\n            \"values\": []\n        }\n        for value_info in graph.value_info:\n            self.value(value_info.name)\n        for initializer in graph.initializer:\n            self.value(initializer.name, None, initializer)\n        for node in graph.node:\n            op_type = node.op_type\n            json_node = {}\n            json_node_type = {}\n            json_node_type[\"name\"] = op_type\n            type_metadata = self.metadata.type(op_type)\n            if type_metadata and \"category\" in type_metadata:\n                json_node_type[\"category\"] = type_metadata[\"category\"]\n            json_node[\"type\"] = json_node_type\n            if node.name:\n                json_node[\"name\"] = node.name\n            json_node[\"inputs\"] = []\n            for value in node.input:\n                json_node[\"inputs\"].append({\n                        \"name\": \"X\",\n                        \"value\": [ self.value(value) ]\n                    })\n            json_node[\"outputs\"] = []\n            for value in node.output:\n                json_node[\"outputs\"].append({\n                        \"name\": \"X\",\n                        \"value\": [ self.value(value) ]\n                    })\n            json_node[\"attributes\"] = []\n            for _ in node.attribute:\n                json_attribute = self.attribute(_, op_type)\n                json_node[\"attributes\"].append(json_attribute)\n            json_graph[\"nodes\"].append(json_node)\n        for _ in self.values:\n            json_graph[\"values\"].append(_.to_json())\n        return json_graph\n\nclass _Value:\n    def __init__(self, name, tensor_type=None, initializer=None):\n        self.name = name\n        self.type = tensor_type\n        self.initializer = initializer\n\n    def to_json(self):\n        target = {}\n        target[\"name\"] = self.name\n        # if self.initializer:\n        #     target['initializer'] = {}\n        return target\n\nclass _Metadata:\n    metadata = {}\n\n    def __init__(self):\n        metadata_file = os.path.join(os.path.dirname(__file__), \"onnx-metadata.json\")\n        with open(metadata_file, encoding=\"utf-8\") as file:\n            for item in json.load(file):\n                name = item[\"name\"]\n                self.metadata[name] = item\n\n    def type(self, name):\n        if name in self.metadata:\n            return self.metadata[name]\n        return {}\n\nclass _AttributeType(enum.IntEnum):\n    UNDEFINED = 0\n    FLOAT = 1\n    INT = 2\n    STRING = 3\n    TENSOR = 4\n    GRAPH = 5\n    FLOATS = 6\n    INTS = 7\n    STRINGS = 8\n    TENSORS = 9\n    GRAPHS = 10\n    SPARSE_TENSOR = 11\n    SPARSE_TENSORS = 12\n    TYPE_PROTO = 13\n    TYPE_PROTOS = 14\n"
  },
  {
    "path": "source/openvino-metadata.json",
    "content": "[\n  {\n    \"name\": \"Activation\",\n    \"category\": \"Activation\",\n    \"description\": \"*Activation* layer represents an activation function of each neuron in a layer, which is used to add non-linearity to the computational flow.\\n**Detailed description**: [Reference](https://medium.com/the-theory-of-everything/understanding-activation-functions-in-neural-networks-9491262884e0)\\n**Parameters**: *Activation layer* parameters should be specified in the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*   Sigmoid function:\\n    \\\\f[\\n    f( x ) = \\\\frac{1}{1+e^{-x}}\\n    \\\\f]\\n*   Tahn function:\\n    \\\\f[\\n    f ( x ) = \\\\frac{2}{1+e^{-2x}} - 1 = 2sigmoid(2x) - 1\\n    \\\\f]\\n*\\tElu function:\\n\\t\\\\f[\\n    f(x) = \\\\left\\\\{\\\\begin{array}{ll}\\n\\t\\te^{x} - 1 \\\\quad \\\\mbox{if } x < 0 \\\\\\\\\\n\\t\\tx \\\\quad \\\\mbox{if } x \\\\geq  0\\n\\t\\\\end{array}\\\\right.\\n\\t\\\\f]\\n*\\tRelu6 function:\\n\\t\\\\f[\\n         f(x) = min(max(0, x), 6)\\n\\t\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Activation\\\" ... >\\n    <data type=\\\"sigmoid\\\" />\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"*type* represents particular activation function. For example, *type* equal *sigmoid* means that neurons of this layer have a sigmoid activation function.\",\n        \"name\": \"type\",\n        \"required\": true\n      },\n      {\n        \"default\": 1,\n        \"name\": \"alpha\",\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Add\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"ArgMax\",\n    \"description\": \"*ArgMax* layer compute the index of the *K* maximum values for each datum across all dimensions *CxHxW*.\\n**Detailed description**: Intended for use after a classification layer to produce a prediction. If parameter *out_max_val* is set to \\\"true\\\", output is a vector of pairs *(max_ind, max_val)* for each image. The *axis* parameter specifies an axis along which to maximize.\\n**Parameters**: *ArgMax* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*ArgMax* generally does the following with the input blobs:\\n\\\\f[\\no_{i} = \\\\left\\\\{\\nx| x \\\\in S  \\\\wedge \\\\forall y \\\\in S : f(y) \\\\leq f(x)\\n\\\\right\\\\}\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"ArgMax\\\" ... >\\n    <data top_k=\\\"10\\\" out_max_val=\\\"1\\\" axis=\\\"-1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \" if *out_max_val* equals 1, output is a vector of pairs *(max_ind, max_val)*, unless axis is set. Then output is *max_val* along the specified axis.\",\n        \"name\": \"top_k\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" if *out_max_val* equals 1, output is a vector of pairs *(max_ind, max_val)*, unless axis is set. Then output is *max_val* along the specified axis.\",\n        \"name\": \"top_k\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" if set, maximizes along the specified axis, else maximizes the flattened trailing dimensions for each index of the first / num dimension.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BatchNormalization\",\n    \"category\": \"Normalization\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/batchnorm.html)\\n**Detailed description**: [Reference](https://kratzert.github.io/2016/02/12/understanding-the-gradient-flow-through-the-batch-normalization-layer.html)\\n**Parameters**: *BatchNormalization* layer parameters should be specified as the `batch_norm_data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*BatchNormalization* is the normalization of the output in each hidden layer.\\n*   **Input**: Values of \\\\f$x\\\\f$ over a mini-batch:\\n    \\\\f[\\n    \\\\beta = \\\\{ x_{1...m} \\\\}\\n    \\\\f]\\n*   **Parameters to learn**: \\\\f$ \\\\gamma, \\\\beta\\\\f$\\n*   **Output**:\\n    \\\\f[\\n    \\\\{ o_{i} = BN_{\\\\gamma, \\\\beta} ( b_{i} ) \\\\}\\n    \\\\f]\\n*   **Mini-batch mean**:\\n    \\\\f[\\n    \\\\mu_{\\\\beta} \\\\leftarrow \\\\frac{1}{m}\\\\sum_{i=1}^{m}b_{i}\\n    \\\\f]\\n*   **Mini-batch variance**:\\n    \\\\f[\\n    \\\\sigma_{\\\\beta }^{2}\\\\leftarrow \\\\frac{1}{m}\\\\sum_{i=1}^{m} ( b_{i} - \\\\mu_{\\\\beta} )^{2}\\n    \\\\f]\\n*   **Normalize**:\\n    \\\\f[\\n    \\\\hat{b_{i}} \\\\leftarrow \\\\frac{b_{i} - \\\\mu_{\\\\beta}}{\\\\sqrt{\\\\sigma_{\\\\beta }^{2} + \\\\epsilon }}\\n    \\\\f]\\n*   **Scale and shift**:\\n    \\\\f[\\n    o_{i} \\\\leftarrow \\\\gamma\\\\hat{b_{i}} + \\\\beta = BN_{\\\\gamma ,\\\\beta } ( b_{i} )\\n    \\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"BatchNormalization\\\" ... >\\n    <batch_norm_data epsilon=\\\"9.99e-06\\\" />\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*epsilon* is the number to be added to the variance to avoid division by zero when normalizing the value. For example, *epsilon* equal 0.001 means that 0.001 is added to the variance.\",\n        \"name\": \"epsilon\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"BinaryConvolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"inputs\" },\n      { \"name\": \"weights\" },\n      { \"name\": \"bias\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"output\" }\n    ]\n  },\n  {\n    \"name\": \"Broadcast\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"target_shape\" },\n      { \"name\": \"axes_mapping\" }\n    ]\n  },\n  {\n    \"name\": \"Clamp\",\n    \"category\": \"Activation\",\n    \"description\": \"*Clamp* layer represents clipping activation operation.\\n**Detailed description**: [Reference](https://www.tensorflow.org/versions/r1.2/api_docs/MO_DG/prepare_model/python/tf/clip_by_value)\\n**Parameters**: *Clamp* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*Clamp* generally does the following with the input blobs:\\n\\\\f[\\nout_i=\\\\left\\\\{\\\\begin{array}{ll}\\n\\tmax\\\\_value \\\\quad \\\\mbox{if } \\\\quad input_i>max\\\\_value \\\\\\\\\\n\\tmin\\\\_value \\\\quad \\\\mbox{if } \\\\quad input_i\\n\\\\end{array}\\\\right.\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Clamp\\\" ... >\\n    <data min=\\\"10\\\" max=\\\"50\\\" />\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"*min* is the lower bound of values in the output shape. Any value in the input shape that is smaller than the bound, is replaced by the *min* value. For example, *min* equal 10 means that any value in the input shape that is smaller than the bound, is replaced by 10.\",\n        \"name\": \"min\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*max* is the upper bound of values in the output shape. Any value in the input shape that is greater than the bound, is replaced by the *max* value. For example, *max* equals 50 means that any value in the input shape that is greater than the bound, is replaced by 50.\",\n        \"name\": \"max\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Concat\",\n    \"category\": \"Tensor\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/concat.html)\\n**Parameters**: *Concat* layer parameters should be specified in the `concat_data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*Axis* parameter specifies a blob dimension to concat values. For example, for two input blobs *B1xC1xH1xW1* and *B2xC2xh4xW2* if axis: 1, output blob is****: *B1xC1+C2xH1xW1*. This is only possible if *B1=B2*, *H1=H4*, *W1=W2*.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Concat\\\" ... >\\n    <concat_data axis=\\\"1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"*axis* is the number of axis over which input blobs are concatenated. For example, *axis* equal 1 means that input blobs are concatenated over the first axis.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"type\": \"Tensor[]\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Concatenation\",\n    \"category\": \"Tensor\"\n  },\n  {\n    \"name\": \"Convolution\",\n    \"category\": \"Layer\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/convolution.html)<br>**Detailed description**: [Reference](http://cs231n.github.io/convolutional-networks/#conv)\\n**Parameters**: *Convolution* layer parameters should be specified in the `convolution_data` node, which is a child of the layer node.\\n**Weights Layout** Weights layout is GOIYX, which means that *X* is changing the fastest, then *Y*, then *Input*, *Output*, then *Group*.\\n**Mathematical Formulation**\\n*   For the convolutional layer, the number of output features in each dimension is calculated using the formula:\\n\\\\f[\\nn_{out} = \\\\left ( \\\\frac{n_{in} + 2p - k}{s} \\\\right ) + 1\\n\\\\f]\\n*   The receptive field in each layer is calculated using the formulas:\\n    *   Jump in the output feature map:\\n        \\\\f[\\n        j_{out} = j_{in} * s\\n        \\\\f]\\n    *   Size of the receptive field of output feature:\\n        \\\\f[\\n        r_{out} = r_{in} + ( k - 1 ) * j_{in}\\n        \\\\f]\\n    *   Center position of the receptive field of the first output feature:\\n        \\\\f[\\n        start_{out} = start_{in} + ( \\\\frac{k - 1}{2} - p ) * j_{in}\\n        \\\\f]\\n    *   Output is calculated using the following formula:\\n        \\\\f[\\n        out = \\\\sum_{i = 0}^{n}w_{i}x_{i} + b\\n        \\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Convolution\\\" ... >\\n        <convolution_data stride-x=\\\"4\\\" stride-y=\\\"4\\\" pad-x=\\\"0\\\" pad-y=\\\"0\\\" kernel-x=\\\"11\\\" kernel-y=\\\"11\\\" output=\\\"96\\\" group=\\\"1\\\" dilation-x=\\\"2\\\" dilation-y=\\\"2\\\"/>\\n        <input> ... </input>\\n        <output> ... </output>\\n        <weights ... />\\n        <biases ... />\\n    </layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": [\n          1,\n          null\n        ],\n        \"description\": \"*stride* is a distance (in pixels) to slide the filter on the feature map over the (x, y) axis. For example, *stride* equal \\\"1,1\\\" means sliding the filter 1 pixel at a time over the (x, y) axis.\",\n        \"name\": \"stride\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*stride-x* is a distance (in pixels) to slide the filter on the feature map over the x axis. For example, *stride-x* equal 1 means sliding the filter 1 pixel at a time over the x axis.\",\n        \"name\": \"stride-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*stride-y* is a distance (in pixels) to slide the filter on the feature map over the y axis. For example, *stride-y* equal 1 means sliding the filter 1 pixel at a time over the y axis.\",\n        \"name\": \"stride-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": [\n          1,\n          null\n        ],\n        \"name\": \"strides\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"*pad* is a number of pixels to add to the left and top of the input. For example, *pad* equal 1 means adding 1 pixel to the left of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"*pad-x* is a number of pixels to add to the left of the input. For example, *pad-x* equal 1 means adding 1 pixel to the left of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"*pad-y* is a number of pixels to add to the top of the input. For example, *pad-y* equal 1 means adding 1 pixel to the top of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"name\": \"pad-r\",\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"name\": \"pad-b\",\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": [\n          1,\n          1\n        ],\n        \"description\": \"*kernel* is a width and height of each filter. For example, *kernel* equal 3 (3, 3) means that each filter has width and height equal to 3.\",\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel-x* is a width of each filter. For example, *kernel* equal 3 means that each filter has width equal to 3.\",\n        \"name\": \"kernel-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel-y* is a height of each filter. For example, *kernel-y* equal 3 means that each filter has height equal to 3.\",\n        \"name\": \"kernel-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*output* is a number of output feature maps per whole output (when *group* > 1, *output* still matches the number of output features regardless of *group* value). For example, *output* equals 1 means that there is 1 output feature map in a layer.\",\n        \"name\": \"output\",\n        \"required\": true,\n        \"type\": \"int32\",\n        \"visible\": false\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*group* denotes the number of groups to which *output* and *input* should be split. For example, *group* equal 1 means that all the filters are applied to full input (usual convolution), *group* equals 2 means that both *input* and *output* channels are separated into 2 groups and *i-th output* group is connected to *i-th input* group channels. *group* equals number of output feature maps denotes depth-wise separable convolution ([Reference](https://medium.com/towards-data-science/types-of-convolutions-in-deep-learning-717013397f4d#6f51)).\",\n        \"name\": \"group\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*dilation* denotes the distance in width and height between elements (weights) in the filter. For example, *dilation* equal \\\"1,1\\\" means that all the elements in the filter are neighbors, so it is the same as for the usual convolution. *dilation* equal \\\"2,2\\\" means that all the elements in the filter are matched not to adjacent elements in the input matrix, but to those that are adjacent with distance 1.\",\n        \"name\": \"dilation\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"name\": \"dilation-x\",\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": [\n          1,\n          null\n        ],\n        \"name\": \"dilations\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": \"same_upper\",\n        \"name\": \"auto_pad\"\n      },\n      {\n        \"default\": [\n          0,\n          null\n        ],\n        \"name\": \"pads_begin\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": [\n          0,\n          null\n        ],\n        \"name\": \"pads_end\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*dilation-y* denotes the distance in height between elements (weights) in the filter. For example, *dilation-y* equal 1 means that all the elements in the filter are neighbors, so it is the same as for the usual convolution. *dilation-y* equal 2 means that all the elements in the filter are matched not to adjacent elements in the input matrix, but to those that are adjacent with distance 1.\",\n        \"name\": \"dilation-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"weights\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Crop\",\n    \"category\": \"Data\",\n    \"description\": \"*Crop* layer changes selected dimensions of the input blob according to the specified parameters.\\n**Parameters**: *Crop* layer parameters should be specified in `data` section, which is placed as a child of the layer node. Due to various representation of Crop attributes in existing frameworks, this layer can be described in three independent ways: *Crop* **Type 1** layer takes two input blobs, and the shape of the second blob specifies the *Crop* size. The layer has two attributes: *axis* and *offset*. Crop layer takes two input blobs, and the shape of the second blob specifies the *Crop* size.  The *Crop* layer of this type supports shape inference.\\n**Inputs**\\n*   **1**:  Multidimensional input blob *(for example, NCHW, NCH, or NC)*\\n*   **2**:  Shape of this input will be used for crop\\n**Example**\\n\\n```html\\n<layer id=\\\"39\\\" name=\\\"score_pool4c\\\" precision=\\\"FP32\\\" type=\\\"Crop\\\">\\n    <data axis=\\\"2,3\\\" offset=\\\"0,0\\\"/>\\n    <input>\\n        <port id=\\\"0\\\">\\n            <dim>1</dim>\\n            <dim>21</dim>\\n            <dim>44</dim>\\n            <dim>44</dim>\\n        </port>\\n        <port id=\\\"1\\\">\\n            <dim>1</dim>\\n            <dim>21</dim>\\n            <dim>34</dim>\\n            <dim>34</dim>\\n        </port>\\n    </input>\\n    <output>\\n        <port id=\\\"2\\\">\\n            <dim>1</dim>\\n            <dim>21</dim>\\n            <dim>34</dim>\\n            <dim>34</dim>\\n        </port>\\n    </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*axis* is a number of a dimension to be used for cropping. For example, *axis* equal to 1 means that cropping is performed over the first dimension.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*offset* denotes the starting point for crop in the input blob. For example, *offset* equal to 2 means that crop is starting from the second value in the given axis.\",\n        \"name\": \"offset\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"CTCGreadyDecoder\",\n    \"category\": \"Layer\",\n    \"description\": \"*CTCGreadyDecoder* performs greedy decoding on the logits given in input (best path).\\n**Detailed description**: [Reference](https://www.tensorflow.org/api_docs/python/tf/nn/ctc_greedy_decoder)\\n**Parameters**: *CTCGreadyDecoder* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\nGiven an input sequence \\\\f$X\\\\f$ of length \\\\f$T\\\\f$, *CTCGreadyDecoder* assumes the probability of a length \\\\f$T\\\\f$ character sequence \\\\f$C\\\\f$ is given by\\n\\\\f[\\np(C|X) = \\\\prod_{t=1}^{T} p(c_{t}|X)\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"CTCGreadyDecoder\\\" ... >\\n    <data stride=\\\"1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*ctc_merge_repeated* is a flag for collapsing the repeated labels during the ctc calculation.\",\n        \"name\": \"ctc_merge_repeated\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Deconvolution\",\n    \"category\": \"Layer\",\n    \"description\": \"*Deconvolution* layer is applied for upsampling the output to the higher image resolution.\\n**Detailed description**: [Reference](https://distill.pub/2016/deconv-checkerboard/)\\n**Parameters**: *Deconvolution* layer parameters should be specified in the `deconvolution_data` node, which is a child of the layer node.\\n**Parameters**: *Convolution* layer parameters should be specified in the `convolution_data` node, which is a child of the layer node.\\n**Weights Layout** Weights layout is the following: GOIYX, which means that *X* is changing the fastest, then *Y*, then *Input*, *Output*, then *Group*.\\n**Mathematical Formulation**\\n*Deconvolution* is also called transpose convolution and performs operation, reverse to convolution.\\nThe number of output features for each dimensions is calculated:\\n\\\\f[S_{o}=stride(S_{i} - 1 ) + S_{f} - 2pad \\\\f]\\nWhere \\\\f$S\\\\f$ is size of output, input and filter.\\nOutput is calculated in the same way as for convolution layer:\\n\\\\f[out = \\\\sum_{i = 0}^{n}w_{i}x_{i} + b\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Deconvolution\\\" ... >\\n    <deconvolution_data stride-x=\\\"2\\\" stride-y=\\\"2\\\" pad-x=\\\"1\\\" pad-y=\\\"1\\\" kernel-x=\\\"4\\\" kernel-y=\\\"4\\\" output=\\\"19\\\" group=\\\"1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*stride* is a distance (in pixels) to slide the filter on the feature map over the (x, y) axis. For example, *stride* equal \\\"1,1\\\" means sliding the filter 1 pixel at a time over the (x, y) axis.\",\n        \"name\": \"stride\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*stride-x* is a distance (in pixels) to slide the filter on the feature map over the x axis. For example, *stride-x* equal 1 means sliding the filter 1 pixel at a time over the x axis.\",\n        \"name\": \"stride-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*stride-y* is a distance (in pixels) to slide the filter on the feature map over the y axis. For example, *stride-y* equal 1 means sliding the filter 1 pixel at a time over the y axis.\",\n        \"name\": \"stride-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*pad* is a number of pixels to add to the left and top of the input. For example, *pad* equal 1 means adding 1 pixel to the left of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*pad-x* is a number of pixels to add to the left of the input. For example, *pad-x* equal 1 means adding 1 pixel to the left of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*pad-y* is a number of pixels to add to the top of the input. For example, *pad-y* equal 1 means adding 1 pixel to the top of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel* is a width and height of each filter. For example, *kernel* equal 3 (3, 3) means that each filter has width and height equal to 3.\",\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel-x* is a width of each filter. For example, *kernel* equal 3 means that each filter has width equal to 3.\",\n        \"name\": \"kernel-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel-y* is a height of each filter. For example, *kernel-y* equal 3 means that each filter has height equal to 3.\",\n        \"name\": \"kernel-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*output* is a number of output feature maps per whole output (when *group* > 1, *output* still matches the number of output features regardless of *group* value). For example, *output* equals 1 means that there is 1 output feature map in a layer.\",\n        \"name\": \"output\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*group* denotes the number of groups to which *output* and *input* should be split. For example, *group* equal 1 means that all the filters are applied to full input (usual convolution), *group* equals 2 means that both *input* and *output* channels are separated into 2 groups and *i-th output* group is connected to *i-th input* group channels. *group* equals number of output feature maps denotes depth-wise separable convolution ([Reference](https://medium.com/towards-data-science/types-of-convolutions-in-deep-learning-717013397f4d#6f51)).\",\n        \"name\": \"group\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*dilation* denotes the distance in width and height between elements (weights) in the filter. For example, *dilation* equal \\\"1,1\\\" means that all the elements in the filter are neighbors, so it is the same as for the usual convolution. *dilation* equal \\\"2,2\\\" means that all the elements in the filter are matched not to adjacent elements in the input matrix, but to those that are adjacent with distance 1.\",\n        \"name\": \"dilation\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*dilation-y* denotes the distance in height between elements (weights) in the filter. For example, *dilation-y* equal 1 means that all the elements in the filter are neighbors, so it is the same as for the usual convolution. *dilation-y* equal 2 means that all the elements in the filter are matched not to adjacent elements in the input matrix, but to those that are adjacent with distance 1.\",\n        \"name\": \"dilation-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"DetectionOutput\",\n    \"description\": \"*DetectionOutput* layer performs non-maximum suppression to generate the detection output using information on location and confidence predictions.\\n**Detailed description**: [Reference](https://arxiv.org/pdf/1512.02325.pdf)\\n**Parameters**: *DetectionOutput* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\nAt each feature map cell, *DetectionOutput* predicts the offsets relative to the default box shapes in the cell, as well as the per-class scores that indicate the presence of a class instance in each of those boxes. Specifically, for each box out of k at a given location, *DetectionOutput* computes class scores and the four offsets relative to the original default box shape. This results in a total of \\\\f$(c + 4)k\\\\f$ filters that are applied around each location in the feature map, yielding \\\\f$(c + 4)kmn\\\\f$ outputs for a m × n feature map.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"DetectionOutput\\\" ... >\\n    <data num_classes=\\\"21\\\" share_location=\\\"1\\\" background_label_id=\\\"0\\\" nms_threshold=\\\"0.450000\\\" top_k=\\\"400\\\" eta=\\\"1.000000\\\" output_directory=\\\"\\\" output_name_prefix=\\\"\\\" output_format=\\\"\\\" label_map_file=\\\"\\\" name_size_file=\\\"\\\" num_test_image=\\\"0\\\" prob=\\\"1.000000\\\" resize_mode=\\\"caffe.ResizeParameter.WARP\\\" height=\\\"0\\\" width=\\\"0\\\" height_scale=\\\"0\\\" width_scale=\\\"0\\\" pad_mode=\\\"caffe.ResizeParameter.CONSTANT\\\" pad_value=\\\"#\\\" interp_mode=\\\"#\\\" code_type=\\\"caffe.PriorBoxParameter.CENTER_SIZE\\\" variance_encoded_in_target=\\\"0\\\" keep_top_k=\\\"200\\\" confidence_threshold=\\\"0.010000\\\" visualize=\\\"0\\\" visualize_threshold=\\\"0.000000\\\" save_file=\\\"\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \" number of classes to be predicted\",\n        \"name\": \"num_classes\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" background label id. If there is no background class, set it to -1.\",\n        \"name\": \"background_label_id\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" maximum number of results to be kept on NMS stage\",\n        \"name\": \"top_k\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" if \\\"true\\\", variance is encoded in target. Otherwise, we need to adjust the predicted offset accordingly.\",\n        \"name\": \"variance_encoded_in_target\",\n        \"required\": true\n      },\n      {\n        \"default\": 1,\n        \"description\": \" number of total bboxes to be kept per image after NMS step. -1 means keeping all bboxes after NMS step.\",\n        \"name\": \"keep_top_k\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"name\": \"num_orient_classes\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" type of coding method for bounding boxes. caffe.PriorBoxParameter.CENTER_SIZE and others.\",\n        \"name\": \"code_type\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" bounding boxes are shared among different classes.\",\n        \"name\": \"share_location\",\n        \"required\": true\n      },\n      {\n        \"default\": 1,\n        \"name\": \"interpolate_orientation\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" threshold to be used in NMS stage\",\n        \"name\": \"nms_threshold\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" only consider detections whose confidences are larger than a threshold. If not provided, consider all boxes.\",\n        \"name\": \"confidence_threshold\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Eltwise\",\n    \"description\": \"*Eltwise* layer performs element-wise operation, which is specified in parameters, over given inputs.\\n**Parameters**: *Eltwise* layer parameters should be specified in the `elementwise_data` node, which is placed as a child of the layer node.\\n**Mathematical Formulation** *Eltwise* accepts 2 inputs of any number of dimensions - from 1 to 4, however, it is required for both of them to have absolutely same dimensions. The produced blob is also of the same dimension as each of its parents\\n*Eltwise* does the following with the input blobs:\\n\\\\f[\\no_{i} = f(b_{i}^{1}, b_{i}^{2})\\n\\\\f]\\nwhere \\\\f$b_{i}^{1}\\\\f$ - first blob \\\\f$i\\\\f$-th element, \\\\f$b_{i}^{2}\\\\f$ - second blob \\\\f$i\\\\f$-th element, \\\\f$o_{i}\\\\f$ - output blob \\\\f$i\\\\f$-th element, \\\\f$f(a, b)\\\\f$ - is a function that performs an operation over its two arguments \\\\f$a, b\\\\f$.\\n*   For *sum* operation, \\\\f$f(a, b)\\\\f$ is defined as\\n    \\\\f[\\n    f(a,b) = a + b\\n    \\\\f]\\n*   For *mul* operation, \\\\f$f(a, b)\\\\f$ is defined as\\n    \\\\f[\\n    f(a,b) = a * b\\n    \\\\f]\\n*   For *max* operation, \\\\f$f(a, b)\\\\f$ is defined as\\n    \\\\f[\\n    f(a,b) = \\\\left\\\\{\\\\begin{array}{ll}\\n\\t\\ta \\\\quad \\\\mbox{if } a \\\\geq b \\\\\\\\\\n\\t\\tb \\\\quad \\\\mbox{if } b > a\\n\\t\\\\end{array}\\\\right. \\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Eltwise\\\" ... >\\n    <elementwise_data operation=\\\"sum\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": \"sum\",\n        \"description\": \"*operation* is the simple mathematical operation to be performed over inputs. For example, *operation* equal *mul* means that input blobs are multiplied.\",\n        \"name\": \"operation\",\n        \"required\": true,\n        \"type\": \"string\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"inputs\",\n        \"type\": \"Tensor[]\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"name\": \"output\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Flatten\",\n    \"category\": \"Shape\",\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int32\"\n      },\n      {\n        \"name\": \"end_axis\",\n        \"type\": \"int32\",\n        \"default\": -1\n      }\n    ]\n  },\n  {\n    \"name\": \"FakeQuantize\",\n    \"inputs\": [\n      { \"name\": \"X\" },\n      { \"name\": \"input_low\" },\n      { \"name\": \"input_high\" },\n      { \"name\": \"output_low\" },\n      { \"name\": \"output_high\" }\n    ]\n  },\n  {\n    \"name\": \"FullyConnected\",\n    \"category\": \"Layer\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/innerproduct.html)\\n**Detailed description**: [Reference](http://cs231n.github.io/convolutional-networks/#fc)\\n**Parameters**: Specify *FullyConnected* layer parameters in the `fc_data` node, which is a child of the layer node.\\n**Weights Layout** OI, which means that Input is changing the fastest, then Output.\\n**Mathematical Formulation**\\n*   If previous layer is *FullyConnected*:\\n    \\\\f[\\n    y_{i} = f( z_{i} ) \\\\quad with \\\\quad z_{i} = \\\\sum_{j=1}^{m_{1}^{( l-1 )}}w_{i,j}^{( l )}y_{i}^{ ( l -1  )}\\n    \\\\f]\\n*   Otherwise:\\n    \\\\f[\\n    y_{i} = f( z_{i} ) \\\\quad with \\\\quad z_{i}^{ ( l )} = \\\\sum_{j=1}^{m_{1}^{( l-1 )}}\\\\sum_{r=1}^{m_{2}^{ ( l-1  )}}\\\\sum_{s=1}^{m_{3}^{ ( l-1 )}}w_{i,j,r,s}^{ ( l )} ( Y_{i}^{ (l-1) })_{r,s}\\n    \\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"FullyConnected\\\" ... >\\n        <fc_data out-size=\\\"4096\\\"/>\\n        <input> ... </input>\\n        <output> ... </output>\\n    </layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*out-size* is a length of the output vector. For example, *out-size* equal 4096 means that the output vector length is 4096.\",\n        \"name\": \"out-size\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"inputs\": [\n      {\n        \"name\": \"input\"\n      },\n      {\n        \"name\": \"weights\"\n      },\n      {\n        \"name\": \"bias\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Gather\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"indices\" },\n      { \"name\": \"axis\" }\n    ]\n  },\n  {\n    \"name\": \"Gelu\",\n    \"category\": \"Activation\",\n    \"description\": \"Gaussian error linear unit element-wise activation function.\"\n  },\n  {\n    \"name\": \"GRN\",\n    \"category\": \"Normalization\",\n    \"description\": \"*GRN* is Global Response Normalization with L2 norm (across channels only).\\n**Parameters**: GRN layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*GRN* computes L2 norm by channels for input blob. *GRN* generally does the following with the input blob:\\n\\\\f[\\noutput_{i} = \\\\frac{input_{i}}{\\\\sqrt{\\\\sum_{i}^{C} input_{i}}}\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"GRN\\\" ... >\\n    <data bias=\\\"1.0\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*bias* is added to the variance.\",\n        \"name\": \"bias\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"GroupConvolution\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"weights\" }\n    ]\n  },\n  {\n    \"name\": \"GRUCell\",\n    \"category\": \"Layer\",\n    \"description\": \"GRUCell represents a single GRU Cell that computes the output using the formula described in the [paper](https://arxiv.org/abs/1406.1078).\",\n    \"attributes\": [\n      { \"name\": \"hidden_size\", \"type\": \"int64\", \"description\": \"pecifies hidden state size.\" },\n      { \"name\": \"linear_before_reset\", \"type\": \"boolean\", \"optional\": true, \"default\": false, \"description\": \"denotes if the layer behaves according to the modification of GRUCell described in the formula in the [ONNX documentation](https://github.com/onnx/onnx/blob/master/docs/Operators.md#GRU).\" }\n    ],\n    \"inputs\": [\n      { \"name\": \"X\", \"description\": \"2D tensor of type T `[batch_size, input_size]`, input data. Required.\" },\n      { \"name\": \"initial_hidden_state\", \"description\": \"2D tensor of type T `[batch_size, hidden_size]`. Required.\" },\n      { \"name\": \"W\", \"description\": \"2D tensor of type T `[3 * hidden_size, input_size]`, the weights for matrix multiplication, gate order: zrh. Required.\" },\n      { \"name\": \"R\", \"description\": \"2D tensor of type T `[3 * hidden_size, hidden_size]`, the recurrence weights for matrix multiplication, gate order: zrh. Required.\" },\n      { \"name\": \"B\", \"description\": \"1D tensor of type T. If linear_before_reset is set to 1, then the shape is `[4 * hidden_size]` - the sum of biases for z and r gates (weights and recurrence weights), the biases for h gate are placed separately. Otherwise the shape is `[3 * hidden_size]`, the sum of biases (weights and recurrence weights). Optional.\" }\n    ]\n  },\n  {\n    \"name\": \"Interpolate\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"sizes\" },\n      { \"name\": \"scales\" },\n      { \"name\": \"axes\" }\n    ]\n  },\n  {\n    \"name\": \"LRN\",\n    \"category\": \"Normalization\"\n  },\n  {\n    \"name\": \"LSTMCell\",\n    \"category\": \"Layer\",\n    \"inputs\": [\n      { \"name\": \"X\" },\n      { \"name\": \"initial_hidden_state\" },\n      { \"name\": \"initial_cell_state\" },\n      { \"name\": \"W\" },\n      { \"name\": \"R\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"MaxPool\",\n    \"category\": \"Pool\"\n  },\n  {\n    \"name\": \"MatMul\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"Memory\",\n    \"description\": \"*Memory* layer represents delay layer in terms of LSTM terminology. To read more about LSTM topologies please refer this [link](http://colah.github.io/posts/2015-08-Understanding-LSTMs).\\n**Detailed description**: *Memory* layer saves state between two infer requests. In the topology, it is the single layer, however, in the Intermediate Representation, it is always represented as a pair of **Memory** layers. One of these layers does not have outputs and another does not have inputs (in terms of the Intermediate Representation).\\n**Parameters**: *Memory* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*Memory* save data from the input blob.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Memory\\\" ... >\\n    <data id=\\\"r_27-28\\\" index=\\\"0\\\" size=\\\"2\\\" />\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*id* is the id of the pair of *Memory* layers. For example, *id* equals r_27-28 means that layers with id 27 and 28 are in one pair.\",\n        \"name\": \"id\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*index* represents if the given layer is input or output. For example, *index* equal 0 means this layer is output one.\",\n        \"name\": \"index\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*size* represents the size of the group. For example, *size* equals 2 means this group is a pair.\",\n        \"name\": \"size\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Minimum\",\n    \"description\": \"Minimum performs element-wise minimum operation with two given tensors applying broadcasting rule specified in the auto_broadcast attribute.\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ]\n  },\n  {\n    \"name\": \"Multiply\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"MVN\",\n    \"category\": \"Normalization\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/mvn.html)\\n**Parameters**: *MVN* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*MVN* subtracts mean from the input blob:\\n\\\\f[\\no_{i} = i_{i} - \\\\frac{\\\\sum{i_{k}}}{C * H * W}\\n\\\\f]\\nIf *normalize_variance* is set to 1, the output blob is divided by variance:\\n\\\\f[\\no_{i}=\\\\frac{o_{i}}{\\\\sum \\\\sqrt {o_{k}^2}+\\\\epsilon}\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"MVN\\\">\\n    <data across_channels=\\\"1\\\" eps=\\\"9.999999717180685e-10\\\" normalize_variance=\\\"1\\\"/>\\n    <input>\\n        ...\\n    </input>\\n    <output>\\n        ...\\n    </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*across_channels* is a flag that denotes if mean values are shared across channels. For example, *across_channels* equal 0 means that mean values are not shared across channels.\",\n        \"name\": \"across_channels\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*normalize_variance* is a flag that denotes whether to perform variance normalization.\",\n        \"name\": \"normalize_variance\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*eps* is the number to be added to the variance to avoid division by zero when normalizing the value. For example, *epsilon* equal 0.001 means that 0.001 is added to the variance.\",\n        \"name\": \"eps\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"data\" }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Norm\",\n    \"category\": \"Normalization\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/lrn.html)\\n**Detailed description**: [Reference](http://yeephycho.github.io/2016/08/03/Normalizations-in-neural-networks/#Local-Response-Normalization-LRN)\\n**Parameters**: *Norm* layer parameters should be specified in the `norm_data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n\\\\f[o_{i} = \\\\left( 1 + \\\\left( \\\\frac{\\\\alpha}{n} \\\\right)\\\\sum_{i}x_{i}^{2} \\\\right)^{\\\\beta}\\\\f]\\nWhere \\\\f$n\\\\f$ is the size of each local region.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Norm\\\" ... >\\n    <norm_data alpha=\\\"9.9999997e-05\\\" beta=\\\"0.75\\\" local-size=\\\"5\\\" region=\\\"across\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*alpha* represents the scaling parameter for the normalizing sum. For example, *alpha* equal 0.0001 means that the normalizing sum is multiplied by 0.0001.\",\n        \"name\": \"alpha\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*beta* represents the exponent for the normalizing sum. For example, *beta* equal 0.75 means that the normalizing sum is raised to the power of 0.75.\",\n        \"name\": \"beta\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*region* represents strategy of local regions extension. For example, *region* equal *across* means that the normalizing sum is performed over adjacent channels.\",\n        \"name\": \"region\",\n        \"required\": true,\n        \"type\": \"\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*local-size* represents the side length of the region to be used for the normalization sum or number of channels depending on the strategy specified in the *region* parameter. For example, *local-size* equal 5 for the across strategy means application of sum across 5 adjacent channels.\",\n        \"name\": \"local-size\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Normalize\",\n    \"category\": \"Normalization\",\n    \"description\": \"*Normalize* layer performs l-p normalization of 1 of input blob.\\n**Parameters**: *Normalize* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n\\\\f[\\no_{i} = \\\\sum_{i}^{H*W}\\\\frac{\\\\left ( n*C*H*W \\\\right )* scale}{\\\\sqrt{\\\\sum_{i=0}^{C*H*W}\\\\left ( n*C*H*W \\\\right )^{2}}}\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Normalize\\\" ... >\\n    <data across_spatial=\\\"0\\\" channel_shared=\\\"0\\\" eps=\\\"0.000000\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*across_spatial* is a flag that denotes if normalization is performed over CHW or HW. For example, *across_spatial* equals 0 means that normalization is not shared across channels.\",\n        \"name\": \"across_spatial\",\n        \"required\": true\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*channel_shared* is a flag that denotes if scale parameters are shared across channels. For example, *channel_shared* equal 0 means that scale parameters are not shared across channels.\",\n        \"name\": \"channel_shared\",\n        \"required\": true\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*eps* is the epsilon used to avoid division by zero when normalizing the value. For example, *eps* equals 0.001 means that 0.001 is used if all the values in normalization are equal to zero.\",\n        \"name\": \"eps\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"NormalizeL2\",\n    \"category\": \"Normalization\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"axes\" }\n    ]\n  },\n  {\n    \"name\": \"Pad\",\n    \"category\": \"Tensor\",\n    \"attributes\": [\n      {\n        \"name\": \"pad_value\",\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"pads_begin\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"name\": \"pads_end\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"name\": \"pad_mode\"\n      }\n    ]\n  },\n  {\n    \"name\": \"Permute\",\n    \"category\": \"Shape\",\n    \"description\": \"*Permute* layer performs reordering of input blob dimensions.\\n**Detailed description**: [Reference](http://caffe.help/manual/layers/tile.html)\\n**Parameters**: *Permute* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*Permute* layer performs reordering input blob. Source indexes and destination indexes are bound by formula:\\n\\\\f[\\nsrc\\\\_ind_{offset} = n * ordered[1] * ordered[2] * ordered[3] + (h * ordered[3] + w)\\n\\\\f]\\n\\\\f[\\nn \\\\in ( 0, order[0] )\\n\\\\f]\\n\\\\f[\\nh \\\\in ( 0, order[2] )\\n\\\\f]\\n\\\\f[\\nw \\\\in ( 0, order[3] )\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Permute\\\" ... >\\n    <data order=\\\"0,2,3,1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"*order* is the set of dimensions indexes for output blob. For example, *order* equal 0,2,3,1 means that the output blob has following dimensions: first dimension from the input blob, third dimension from the input blob, fourth dimension from the input blob, second dimension from the input blob.\",\n        \"name\": \"order\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Pooling\",\n    \"category\": \"Pool\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/pooling.html)\\n**Detailed description**: [Reference](http://cs231n.github.io/convolutional-networks/#pool)\\n**Parameters**: Specify pooling layer parameters in the `pooling_data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*   For *max pool-method*:\\n    \\\\f[\\n    output_{j} = MAX\\\\{ x_{0}, ... x_{i}\\\\}\\n    \\\\f]\\n*   For *avg pool-method*:\\n    \\\\f[\\n    output_{j} = \\\\frac{\\\\sum_{i = 0}^{n}x_{i}}{n}\\n    \\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Pooling\\\" ... >\\n        <pooling_data kernel-x=\\\"3\\\" kernel-y=\\\"3\\\" pad-x=\\\"0\\\" pad-y=\\\"0\\\" stride-x=\\\"2\\\" stride-y=\\\"2\\\" pool-method=\\\"max\\\" exclude-pad=\\\"true\\\" rounding_type=\\\"floor\\\"/>\\n        <input> ... </input>\\n        <output> ... </output>\\n    </layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": [\n          1,\n          null\n        ],\n        \"description\": \"*stride* is a distance (in pixels) to slide the filter on the feature map over the (x, y) axis. For example, *stride* equal \\\"1,1\\\" means sliding the filter 1 pixel at a time over the (x, y) axis.\",\n        \"name\": \"stride\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*stride-x* is a distance (in pixels) to slide the filter on the feature map over the x axis. For example, *stride-x* equal 1 means sliding the filter 1 pixel at a time over the x axis.\",\n        \"name\": \"stride-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*stride-y* is a distance (in pixels) to slide the filter on the feature map over the y axis. For example, *stride-y* equal 1 means sliding the filter 1 pixel at a time over the y axis.\",\n        \"name\": \"stride-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": [\n          1,\n          null\n        ],\n        \"name\": \"strides\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*pad* is a number of pixels to add to the left and top of the input. For example, *pad* equal 1 means adding 1 pixel to the left of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"*pad-x* is a number of pixels to add to the left of the input. For example, *pad-x* equal 1 means adding 1 pixel to the left of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"description\": \"*pad-y* is a number of pixels to add to the top of the input. For example, *pad-y* equal 1 means adding 1 pixel to the top of the input. Right and bottom padding should be calculated from the expected output width (height).\",\n        \"name\": \"pad-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"name\": \"pad-r\",\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 0,\n        \"name\": \"pad-b\",\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": [\n          0,\n          null\n        ],\n        \"name\": \"pads_begin\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": [\n          0,\n          null\n        ],\n        \"name\": \"pads_end\",\n        \"type\": \"int32[]\"\n      },\n      {\n        \"description\": \"*kernel* is a width and height of each filter. For example, *kernel* equal 3 (3, 3) means that each filter has width and height equal to 3.\",\n        \"name\": \"kernel\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel-x* is a width of each filter. For example, *kernel* equal 3 means that each filter has width equal to 3.\",\n        \"name\": \"kernel-x\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*kernel-y* is a height of each filter. For example, *kernel-y* equal 3 means that each filter has height equal to 3.\",\n        \"name\": \"kernel-y\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": \"max\",\n        \"description\": \"*pool-method* is a type of pooling strategy for values.\",\n        \"name\": \"pool-method\",\n        \"required\": true,\n        \"type\": \"\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"*exclude-pad* is a type of pooling strategy for values in the padding area. For example, if *exclude-pad* is \\\"true\\\", zero-values in the padding are not used.\",\n        \"name\": \"exclude-pad\",\n        \"required\": true,\n        \"type\": \"boolean\"\n      },\n      {\n        \"default\": \"ceil\",\n        \"description\": \"*rounding_type* is a type of rounding to be applied.\",\n        \"name\": \"rounding-type\",\n        \"required\": true\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Power\",\n    \"description\": \"*Power* layer computes the output as (shift + scale * x) ^ power for each input element x.\\n**Parameters**: Power layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n\\\\f[\\np = (shift + scale * x)^{power}\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Power\\\" ... >\\n    <data power=\\\"2\\\" scale=\\\"0.1\\\" shift=\\\"5\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"status\": \"default\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"PReLU\",\n    \"category\": \"Activation\",\n    \"description\": \"*PReLU* is the Parametric Rectifier Linear Unit. The difference from *ReLU* is that negative slopes can vary across channels.\\n**Parameters**: *PReLU* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*PReLU* accepts one input with four dimensions. The produced blob has the same dimensions as input.\\n*PReLU* does the following with the input blob:\\n\\\\f[\\no_{i} = max(0, x_{i}) + w_{i} * min(0,x_{i})\\n\\\\f]\\nwhere \\\\f$w_{i}\\\\f$ is from weights blob.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"PReLU\\\" ... >\\n    <data bias=\\\"1.0\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*channel_shared* shows if negative slope shared across channels or not.\",\n        \"name\": \"channel_shared\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"description\": \"*filler_type* defines initialization type for negative slope.\",\n        \"name\": \"filler_type\",\n        \"required\": true,\n        \"type\": \"string\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*filler_value* defines the value in constant filler.\",\n        \"name\": \"filler_value\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*min(max)* defines the minimal(maximal) value in uniform filler.\",\n        \"name\": \"min(max)\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*mean* defines the mean value in Gaussian filler.\",\n        \"name\": \"mean\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"slope\" }\n    ]\n  },\n  {\n    \"name\": \"PriorBox\",\n    \"description\": \"*PriorBox* layer generates prior boxes of specified sizes and aspect ratios across all dimensions.\\n**Parameters**: *PriorBox* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**:\\n*PriorBox* computes coordinates of prior boxes by following:\\n1.  First calculates *center_x* and *center_y* of prior box:\\n    \\\\f[\\n    W \\\\equiv Width \\\\quad Of \\\\quad Image\\n    \\\\f]\\n    \\\\f[\\n    H \\\\equiv Height \\\\quad Of \\\\quad Image\\n    \\\\f]\\n    *   If step equals 0:\\n        \\\\f[\\n        center_x=(w+0.5)\\n        \\\\f]\\n        \\\\f[\\n        center_y=(h+0.5)\\n        \\\\f]\\n    *   else:\\n        \\\\f[\\n        center_x=(w+offset)*step\\n        \\\\f]\\n        \\\\f[\\n        center_y=(h+offset)*step\\n        \\\\f]\\n        \\\\f[\\n        w \\\\subset \\\\left( 0, W \\\\right )\\n        \\\\f]\\n        \\\\f[\\n        h \\\\subset \\\\left( 0, H \\\\right )\\n        \\\\f]\\n2.  Then, for each \\\\f$ s \\\\subset \\\\left( 0, min_sizes \\\\right ) \\\\f$ calculates coordinates of priorboxes:\\n    \\\\f[\\n    xmin = \\\\frac{\\\\frac{center_x - s}{2}}{W}\\n    \\\\f]\\n    \\\\f[\\n    ymin = \\\\frac{\\\\frac{center_y - s}{2}}{H}\\n    \\\\f]\\n    \\\\f[\\n    xmax = \\\\frac{\\\\frac{center_x + s}{2}}{W}\\n    \\\\f]\\n    \\\\f[\\n    ymin = \\\\frac{\\\\frac{center_y + s}{2}}{H}\\n    \\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"PriorBox\\\" ... >\\n    <data step=\\\"64.000000\\\" min_size=\\\"162.000000\\\" max_size=\\\"213.000000\\\" offset=\\\"0.500000\\\" flip=\\\"1\\\" clip=\\\"0\\\" aspect_ratio=\\\"2.000000,3.000000\\\" variance=\\\"0.100000,0.100000,0.200000,0.200000\\\" />\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"name\": \"min_size\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"max_size\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*aspect_ratio* is a variance of aspect ratios. Duplicate values are ignored. For example, *aspect_ratio* equal 2.000000,3.000000 means that for the first box aspect_ratio is equal to 2 and for the second box - 3.\",\n        \"name\": \"aspect_ratio\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"*flip* is a flag that denotes that each *aspect_ratio* is duplicated and flipped. For example, *flip* equals 1 and *aspect_ratio* equals 3 mean that aspect_ratio is equal to 1/3.\",\n        \"name\": \"flip\",\n        \"required\": true,\n        \"type\": \"boolean\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"*clip* is a flag that denotes if each value in the output blob is within [0,1]. For example, *clip* equal 1 means that each value in the output blob is within [0,1].\",\n        \"name\": \"clip\",\n        \"required\": true,\n        \"type\": \"boolean\"\n      },\n      {\n        \"description\": \"*step* is a distance between box centers. For example, *step* equal 85 means that the distance between neighborhood prior boxes centers is 85.\",\n        \"name\": \"step\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 0.5,\n        \"description\": \"*offset* is a shift of box respectively to top left corner. For example, *offset* equal 85 means that the shift of neighborhood prior boxes centers is 85.\",\n        \"name\": \"offset\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"description\": \"*variance* denotes a variance of adjusting bounding boxes. For example, *variance* equals 85 means that the shift of neighborhood prior boxes centers is 85.\",\n        \"name\": \"variance\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*scale_all_sizes* is a flag that denotes type of inference. For example, *scale_all_sizes* equals 0 means that priorbox layer is inferd in MXNet-like manner. In particular, *max_size* parameter is ignored.\",\n        \"name\": \"scale_all_sizes\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"inputs\": [\n      { \"name\": \"output_size\" },\n      { \"name\": \"image_size\" }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PriorBoxClustered\",\n    \"description\": \"*PriorBoxClustered* layer generates prior boxes of specified sizes.\\n**Parameters**: *PriorBoxClustered* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*PriorBoxClustered* computes coordinates of prior boxes by following:\\n1.  Calculates the *center_x* and *center_y* of prior box:\\n    \\\\f[\\n    W \\\\equiv Width \\\\quad Of \\\\quad Image\\n    \\\\f]\\n    \\\\f[\\n    H \\\\equiv Height \\\\quad Of \\\\quad Image\\n    \\\\f]\\n    \\\\f[\\n    center_x=(w+offset)*step\\n    \\\\f]\\n    \\\\f[\\n    center_y=(h+offset)*step\\n    \\\\f]\\n    \\\\f[\\n    w \\\\subset \\\\left( 0, W \\\\right )\\n    \\\\f]\\n    \\\\f[\\n    h \\\\subset \\\\left( 0, H \\\\right )\\n    \\\\f]\\n2.  For each \\\\f$s \\\\subset \\\\left( 0, W \\\\right )\\\\f$ calculates the prior boxes coordinates:\\n    \\\\f[\\n    xmin = \\\\frac{center_x - \\\\frac{width_s}{2}}{W}\\n    \\\\f]\\n\\t\\\\f[\\n\\tymin = \\\\frac{center_y - \\\\frac{height_s}{2}}{H}\\n\\t\\\\f]\\n\\t\\\\f[\\n\\txmax = \\\\frac{center_x - \\\\frac{width_s}{2}}{W}\\n\\t\\\\f]\\n\\t\\\\f[\\n\\tymax = \\\\frac{center_y - \\\\frac{height_s}{2}}{H}\\n\\t\\\\f]\\nIf *clip* is defined, the coordinates of prior boxes are recalculated with the formula:\\n\\\\f$coordinate = \\\\min(\\\\max(coordinate,0), 1)\\\\f$\\n**Example**\\n\\n```html\\n<layer ... type=\\\"PriorBoxClustered\\\">\\n    <data clip=\\\"0\\\" flip=\\\"0\\\" height=\\\"44.0,10.0,30.0,19.0,94.0,32.0,61.0,53.0,17.0\\\" offset=\\\"0.5\\\" step=\\\"16.0\\\" variance=\\\"0.1,0.1,0.2,0.2\\\"\\n     width=\\\"86.0,13.0,57.0,39.0,68.0,34.0,142.0,50.0,23.0\\\"/>\\n    <input>\\n        ...\\n    </input>\\n    <output>\\n        ...\\n    </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"*width* is a parameter that specifies desired boxes widths in pixels.\",\n        \"name\": \"width\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"name\": \"height\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"*clip* is a flag that denotes if each value in the output blob is within [0,1]. For example, *clip* equal 1 means that each value in the output blob is within [0,1].\",\n        \"name\": \"clip\",\n        \"required\": true,\n        \"type\": \"boolean\"\n      },\n      {\n        \"default\": false,\n        \"description\": \"*flip* is a flag that denotes whether the list of boxes is augmented with the flipped ones.\",\n        \"name\": \"flip\",\n        \"required\": true,\n        \"type\": \"boolean\"\n      },\n      {\n        \"description\": \"*step* is a distance between box centers. For example, *step* equal 85 means that the distance between neighborhood prior boxes centers is 85.\",\n        \"name\": \"step\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"step_w\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"step_h\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*offset* is a shift of box respectively to top left corner. For example, *offset* equal 85 means that the shift of neighborhood prior boxes centers is 85.\",\n        \"name\": \"offset\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"description\": \"*variance* denotes a variance of adjusting bounding boxes. For example, *variance* equal 85 means that the shift of neighborhood prior boxes centers is 85.\",\n        \"name\": \"variance\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"description\": \"*img_h* specifies height of input image. These parameters are calculated unless provided explicitly.\",\n        \"name\": \"img_h\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"name\": \"img_w\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Proposal\",\n    \"category\": \"Layer\",\n    \"description\": \"*Proposal* layer performs filtering of only those bounding boxes and outputs with the highest confidence of prediction.\\n**Parameters**: Proposal layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*Proposal* layer accepts three inputs with four dimensions. The produced blob has two dimensions: first one equals *batch_size * post_nms_topn*.\\n*Proposal* does the following with the input blob:\\n1.  Generates initial anchor boxes Left top corner of all boxes in (0, 0). Width and height of boxes are calculated from *base_size* with scale and ratio parameters\\n2.  For each point in the first input blob:\\n    *   pins anchor boxes to the image according to the second input blob that contains four deltas for each box: for *x* and *y* of center, for *width* and for *height*\\n    *   finds out score in the first input blob\\n3.  Filters out boxes with size less than *min_size*\\n4.  Sorts all proposals (*box*, *score*) by score from highest to lowest\\n5.  Takes top *pre_nms_topn* proposals\\n6.  Calculates intersections for boxes and filter out all with \\\\f$intersection/union > nms\\\\_thresh\\\\f$\\n7.  Takes top *post_nms_topn* proposals\\n8.  Returns top proposals\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Proposal\\\" ... >\\n    <data base_size=\\\"16\\\" feat_stride=\\\"16\\\" min_size=\\\"16\\\" nms_thresh=\\\"0.6\\\" post_nms_topn=\\\"200\\\" pre_nms_topn=\\\"6000\\\"\\n     ratio=\\\"2.67\\\" scale=\\\"4.0,6.0,9.0,16.0,24.0,32.0\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*pre_nms_topn (post_nms_topn)* is the quantity of bounding boxes before (after) applying NMS operation. For example, *pre_nms_topn (post_nms_topn)* equal 15 means that the minimum (maximum) box size is 15.\",\n        \"name\": \"pre_nms_topn (post_nms_topn)\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*nms_thresh* is the minimum value of the proposal to be taken into consideration. For example, *nms_thresh* equal 0.5 means that all boxes with prediction probability less than 0.5 are filtered out.\",\n        \"name\": \"nms_thresh\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*feat_stride* is the step size to slide over boxes (in pixels). For example, *feat_stride* equal 16 means that all boxes are analyzed with the slide 16.\",\n        \"name\": \"feat_stride\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*min_size* is the minimum size of box to be taken into consideration. For example, *min_size* equal 35 means that all boxes with box size less than 35 are filtered out.\",\n        \"name\": \"min_size\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*ratio* is the ratios for anchor generation.\",\n        \"name\": \"ratio\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*ratio* is the ratios for anchor generation.\",\n        \"name\": \"ratio\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*scale* is the scales for anchor generation.\",\n        \"name\": \"scale\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"PSROIPooling\",\n    \"category\": \"Pool\",\n    \"description\": \"*PSROIPooling* layer compute position-sensitive max pooling on regions of interest specified by input, takes as input N position-sensitive score maps and a list of R regions of interest.\\n**Detailed description**: [Reference](https://arxiv.org/pdf/1703.06211.pdf)\\n**Parameters**: *PSRoiPooling* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\nThe output value for \\\\f$(i, j)\\\\f$-th bin is obtained by summation from one score map \\\\f$x_{i,j}\\\\f$ corresponding to that bin. In short, the difference from *RoIPooling* is that a general feature map \\\\f$x\\\\f$ is replaced by a specific positive-sensitive score map \\\\f$x_{i,j}\\\\f$.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"PSROIPooling\\\" ... >\\n    <data output_dim=\\\"10\\\" out_max_val=\\\"1\\\" spatial_scale=\\\"0.1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \" pooled output channel number\",\n        \"name\": \"output_dim\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" number of groups to encode position-sensitive score maps\",\n        \"name\": \"group_size\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \" multiplicative spatial scale factor to translate ROI coordinates from their input scale to the scale used when pooling\",\n        \"name\": \"spatial_scale\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Range\",\n    \"inputs\": [\n      { \"name\": \"start\" },\n      { \"name\": \"stop\" },\n      { \"name\": \"step\" }\n    ]\n  },\n  {\n    \"name\": \"RegionYolo\",\n    \"category\": \"Layer\",\n    \"description\": \"*RegionYolo* computes coordinates of regions with probability for each class.\\n**Detailed description**:  [Reference][p_yolo]\\n**Parameters**: *RegionYolo* layer parameters should be specified as the `data` node, which is a child of the `layer` node.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"RegionYolo\\\" ... >\\n    <data bias=\\\"1.0\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n    <weights .../>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*coords* is num coordinates for each region\",\n        \"name\": \"coords\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*classes* is num classes for each region\",\n        \"name\": \"classes\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*num* is number of regions\",\n        \"name\": \"num\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*do_softmax* is a flag which specifies the method of infer\",\n        \"name\": \"do_softmax\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*anchors* coordinates regions\",\n        \"name\": \"anchors\",\n        \"required\": true,\n        \"type\": \"float32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*mask* specifies which anchors to use\",\n        \"name\": \"mask\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*mask* specifies which anchors to use\",\n        \"name\": \"mask\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*axis* is the number of the dimension from which flattening is performed. For example, *axis* equals 1 means that flattening is started from the 1st dimension.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*end_axis* is the number of the dimension on which flattening is ended. For example, *end_axis* equals -1 means that flattening is performed till the last dimension.\",\n        \"name\": \"end_axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReLU\",\n    \"category\": \"Activation\",\n    \"description\": \"[Reference](http://caffe.berkeleyvision.org/tutorial/layers/relu.html)\\n**Detailed description**: [Reference](https://github.com/Kulbear/deep-learning-nano-foundation/wiki/ReLU-and-Softmax-Activation-Functions#rectified-linear-units)\\n**Parameters**: *ReLU* layer parameters can be (not mandatory) specified in the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n\\\\f[\\nY_{i}^{( l )} = max(0, Y_{i}^{( l - 1 )})\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"ReLU\\\" ... >\\n    <data negative_slope=\\\"0.100000\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 0,\n        \"description\": \"*negative_slope* is a multiplier, which is used if the unit is not active (that is negative). For example, *negative_slope* equal 0.1 means that an inactive unit value would be multiplied by 0.1 and this is the [Leaky ReLU](https://keras.io/layers/advanced-activations/#leakyrelu). If *negative_slope* is equal to 0, this is the usual *ReLU*.\",\n        \"name\": \"negative_slope\",\n        \"required\": true,\n        \"type\": \"float64\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReorgYolo\",\n    \"category\": \"Layer\",\n    \"description\": \"*ReorgYolo* reorganizes input blob taking into account strides.\\n**Detailed description**: [Reference][p_yolo]\\n**Parameters**: *ReorgYolo* layer parameters should be specified as the `data` node, which is a child of the `layer` node.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"ReorgYolo\\\" ... >\\n    <data stride=\\\"1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*stride* is distance of cut throws in output blobs.\",\n        \"name\": \"stride\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Resample\",\n    \"category\": \"Layer\",\n    \"description\": \"Layer scales the input blob by the specified parameters.\\n**Parameters**: Resample layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Example**\\n\\n```html\\n<layer type=\\\"Resample\\\">\\n  <data antialias=\\\"0\\\" factor=\\\"1.0\\\" height=\\\"227\\\" type=\\\"caffe.ResampleParameter.LINEAR\\\" width=\\\"227\\\"/>\\n      <input>\\n      ...\\n      </input>\\n      <output>\\n      ...\\n      </output>\\n​</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"Parameter specifies type of blob interpolation.\",\n        \"name\": \"type\",\n        \"required\": true\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*antialias* is a flag that denotes whether to perform anti-aliasing.\",\n        \"name\": \"antialias\",\n        \"required\": true\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ReduceMax\",\n    \"description\": \"*ReduceMax* operation performs the reduction with finding the maximum value on a given input data along dimensions specified by axes input.\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"axes\" }\n    ]\n  },\n  {\n    \"name\": \"ReduceMean\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"axes\" }\n    ]\n  },\n  {\n    \"name\": \"Reshape\",\n    \"category\": \"Shape\",\n    \"description\": \"*Reshape* layer changes dimensions of the input blob according to the specified order. Input blob volume is equal to output blob volume, where volume is the product of dimensions.\\n**Detailed description**: [Reference](http://caffe.berkeleyvision.org/tutorial/layers/reshape.html)\\n**Parameters**: *Reshape* layer parameters should be specified in the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\nIf you want to reshape input blob *BxCxHxW* into *Bx1x(C*H)xW*, the *dim* parameters of your layer should be:\\n```html\\n layer {\\n    name: \\\"reshape\\\"\\n    type: \\\"Reshape\\\"\\n    bottom: \\\"input\\\"\\n    top: \\\"output\\\"\\n    reshape_param {\\n      shape {\\n        dim: 0  # copy the dimension from below\\n        dim: 1\\n        dim: -1 # infer it from the other dimensions\\n        dim: 0\\n      }\\n    }\\n  }\\n```\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Reshape\\\" ... >\\n    <data axis=\\\"0\\\" dim=\\\"1, 1001\\\" num_axes=\\\"-1\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*axis* is the number of the starting axis for reshape. For example, *axis* equal 1 means that *Reshape* replaces dimensions starting from the next after the first dimension.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"description\": \"*dim* is a set of numbers separated with comma, which denote the dimensions of output blob. For example, *dim* equal 88,1,71 means that output blob gets following dimensions: first dimension equals 88, second dimension equals 1, third dimension equals 71. For more information, refer to the **Description** block. If *dim* is equal to two numbers, it performs [flattening](http://caffe.berkeleyvision.org/tutorial/layers/flatten.html).\",\n        \"name\": \"dim\",\n        \"required\": true,\n        \"type\": \"int32[]\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*num_axes* is the number of dimensions to be replaced with a reshaped blob starting from the dimension number specified in *axis* property. For example, *num_axes* equal 2 means that 2 dimensions are replaced with reshaped blob.\",\n        \"name\": \"num_axes\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"name\": \"special_zero\",\n        \"type\": \"boolean\"\n      }\n    ],\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"shape\" }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ROIPooling\",\n    \"category\": \"Layer\",\n    \"description\": \"It is a *pooling layer* with *max* pooling strategy (see *max* option in the *<a href=\\\"IRLayersCatalogSpec.html#pooling-layer\\\">Pooling layer</a>* parameters description). It is used over feature maps of non-uniform sizes and outputs another feature map of a fixed size.\\n**Detailed description**: [deepsense.io reference](https://blog.deepsense.ai/region-of-interest-pooling-explained/)\\n**Parameters**: Specify *ROIPooling* layer parameters in the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n\\\\f[\\noutput_{j} = MAX\\\\{ x_{0}, ... x_{i}\\\\}\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"ROIPooling\\\" ... >\\n        <data pooled_h=\\\"6\\\" pooled_w=\\\"6\\\" spatial_scale=\\\"0.062500\\\"/>\\n        <input> ... </input>\\n        <output> ... </output>\\n    </layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*pooled_h* is a height of the ROI output feature map. For example, *pooled_h* equal 6 means that the height of the output of *ROIpooling* is 6.\",\n        \"name\": \"pooled_h\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*pooled_w* is a width of the ROI output feature map. For example, *pooled_w* equal 6 means that the width of the output of *ROIpooling* is 6.\",\n        \"name\": \"pooled_w\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*spatial_scale* is a ratio of the input feature map over the input image size.\",\n        \"name\": \"spatial_scale\",\n        \"required\": true,\n        \"type\": \"float32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"ScaleShift\",\n    \"category\": \"Layer\",\n    \"description\": \"*ScaleShift* layer performs linear transformation of the input blobs. Weights denote scaling parameter, biases - a shift.\\n**Parameters**: *ScaleShift* layer does not have additional parameters.\\n**Mathematical Formulation**\\n\\\\f[\\no_{i} =\\\\gamma b_{i} + \\\\beta\\n\\\\f]\\n**Example**\\n\\n```\\n<layer ... type=\\\"ScaleShift\\\" ... >\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Sigmoid\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"SimplerNMS\",\n    \"category\": \"Layer\",\n    \"description\": \"*SimplerNMS* layer performs filtering of bounding boxes and outputs only those with the highest confidence of prediction.\\n**Parameters**: *SimplerNMS* layer parameters should be specified as the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*SimplerNMS* accepts three inputs with four dimensions. Produced blob has two dimensions, the first one equals *post_nms_topn*.\\n*SimplerNMS* does the following with the input blob:\\n1.  Generates initial anchor boxes. Left top corner of all boxes is (0, 0). Width and height of boxes are calculated based on scaled (according to the scale parameter) default widths and heights\\n2.  For each point in the first input blob:\\n    *   pins anchor boxes to picture according to the second input blob, which contains four deltas for each box: for x and y of center, for width, and for height\\n    *   finds out score in the first input blob\\n3.  Filters out boxes with size less than *min_bbox_size.*\\n4.  Sorts all proposals (*box, score*) by score from highest to lowest\\n5.  Takes top *pre_nms_topn* proposals\\n6.  Calculates intersections for boxes and filters out all with \\\\f$intersection/union > iou\\\\_threshold\\\\f$\\n7.  Takes top *post_nms_topn* proposals\\n8.  Returns top proposals\\n**Example**\\n\\n```html\\n<layer ... type=\\\"SimplerNMS\\\" ... >\\n    <data cls_threshold=\\\"0.500000\\\" iou_threshold=\\\"0.700000\\\" min_bbox_size=\\\"16\\\" feat_stride=\\\"16\\\" pre_nms_topn=\\\"6000\\\" post_nms_topn=\\\"150\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*pre_nms_topn (post_nms_topn)* is the quantity of bounding boxes before (after) applying NMS operation. For example, *pre_nms_topn (post_nms_topn)* equals 15 means that the minimum (maximum) box size is 15.\",\n        \"name\": \"pre_nms_topn (post_nms_topn)\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*cls_threshold* is the minimum value of the proposal to be taken into consideration. For example, *cls_threshold* equal 0.5 means that all boxes with prediction probability less than 0.5 are filtered out.\",\n        \"name\": \"cls_threshold\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*iou_threshold* is the minimum ratio of boxes overlapping to be taken into consideration. For example, *iou_threshold* equal 0.7 means that all boxes with overlapping ratio less than 0.7 are filtered out.\",\n        \"name\": \"iou_threshold\",\n        \"required\": true,\n        \"type\": \"float32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*feat_stride* is the step size to slide over boxes (in pixels). For example, *feat_stride* equal 16 means that all boxes are analyzed with the slide 16.\",\n        \"name\": \"feat_stride\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*min_bbox_size* is the minimum size of box to be taken into consideration. For example, *min_bbox_size* equal 35 means that all boxes with box size less than 35 are filtered out.\",\n        \"name\": \"min_bbox_size\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"default\": 1,\n        \"description\": \"*scale* is array of scales for anchor boxes generating.\",\n        \"name\": \"scale\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Subtract\",\n    \"inputs\": [\n      { \"name\": \"A\" },\n      { \"name\": \"B\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"C\" }\n    ]\n  },\n  {\n    \"name\": \"SoftMax\",\n    \"category\": \"Activation\",\n    \"description\": \"[Reference](https://github.com/Kulbear/deep-learning-nano-foundation/wiki/ReLU-and-Softmax-Activation-Functions#softmax)\\n**Detailed description**: [Reference](http://cs231n.github.io/linear-classify/#softmax)\\n**Parameters**: *SoftMax* layer parameters can be (not mandatory) specified in the `data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n\\\\f[\\ny_{c} = \\\\frac{e^{Z_{c}}}{\\\\sum_{d=1}^{C}e^{Z_{d}}}\\n\\\\f]\\nwhere \\\\f$C\\\\f$ is a number of classes\\n**Example**\\n\\n```html\\n<layer ... type=\\\"SoftMax\\\" ... >\\n    <data axis=\\\"1\\\" />\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"description\": \"*axis* represents the axis of which the *SoftMax* is calculated. *axis* equal 1 is a default value.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Split\",\n    \"category\": \"Tensor\",\n    \"description\": \"*Split* layer splits the input into several output groups. Group sizes are denoted by the number and the size of output ports.\\n**Detailed description**: [Reference](http://caffe.berkeleyvision.org/tutorial/layers/split.html)\\n**Parameters**: *None*\\n**Mathematical Formulation**\\nSplits input blob among children. For example, blob is *BxC+CxHxW* and there are two children. Then, output blob is *BxCxHxW*.\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Split\\\" ... >\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"name\": \"axis\",\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Squeeze\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"axes\" }\n    ]\n  },\n  {\n    \"name\": \"StridedSlice\",\n    \"category\": \"Tensor\",\n    \"inputs\": [\n      { \"name\": \"data\" },\n      { \"name\": \"begin\" },\n      { \"name\": \"end\" },\n      { \"name\": \"stride\" }\n    ]\n  },\n  {\n    \"name\": \"Swish\",\n    \"category\": \"Activation\"\n  },\n  {\n    \"name\": \"TensorIterator\",\n    \"description\": \"*TensorIterator* layer performs recurrent execution of the network, which is described in the **body**, iterating through the data.\",\n    \"inputs\": [\n      { \"name\": \"inputs\", \"type\": \"Tensor[]\" }\n    ],\n    \"outputs\": [\n      { \"name\": \"outputs\", \"type\": \"Tensor[]\" }\n    ]\n  },\n  {\n    \"name\": \"Tile\",\n    \"description\": \"*Tile* layer extends input blob with copies of data along specific axis.\\n**Detailed description**: [Reference](http://caffe.help/manual/layers/tile.html)\\n**Parameters**: *Tile* layer parameters should be specified as the `tile_data` node, which is a child of the layer node.\\n**Mathematical Formulation**\\n*Tile* extends input blobs and filling in output blobs following rules:\\n\\\\f[\\nout_i=input_i[inner\\\\_dim*t]\\n\\\\f]\\n\\\\f[\\nt \\\\in \\\\left ( 0, \\\\quad tiles \\\\right )\\n\\\\f]\\n**Example**\\n\\n```html\\n<layer ... type=\\\"Tile\\\" ... >\\n    <tile_data axis=\\\"3\\\" tiles=\\\"88\\\"/>\\n    <input> ... </input>\\n    <output> ... </output>\\n</layer>\\n```\",\n    \"attributes\": [\n      {\n        \"default\": 1,\n        \"description\": \"*axis* is the index of the axis to tile. For example, *axis* equals 3 means that fourth axis is used for tiling.\",\n        \"name\": \"axis\",\n        \"required\": true,\n        \"type\": \"int32\"\n      },\n      {\n        \"description\": \"*tiles* is a size of the specified axis in the output blob. For example, *tiles* equal 88 means that output blob gets 88 copies of data from specified axis.\",\n        \"name\": \"tiles\",\n        \"required\": true,\n        \"type\": \"int32\"\n      }\n    ],\n    \"status\": \"default\"\n  },\n  {\n    \"name\": \"Transpose\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"arg\" },\n      { \"name\": \"input_order\" }\n    ]\n  },\n  {\n    \"name\": \"Unsqueeze\",\n    \"category\": \"Transform\",\n    \"inputs\": [\n      { \"name\": \"input\" },\n      { \"name\": \"axes\" }\n    ]\n  }\n]"
  },
  {
    "path": "source/openvino.js",
    "content": "\nconst openvino = {};\n\nopenvino.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier.toLowerCase();\n        const extension = identifier.split('.').pop();\n        if (/^.*\\.ncnn\\.bin$/.test(identifier) ||\n            /^.*\\.pnnx\\.bin$/.test(identifier) ||\n            /^.*pytorch_model.*\\.bin$/.test(identifier) ||\n            /^.*group.+-shard.+of.+\\.bin$/.test(identifier) ||\n            /^.*param\\.bin$/.test(identifier)) {\n            return null;\n        }\n        if (extension === 'bin') {\n            const stream = context.stream;\n            const length = Math.min(0x10000, stream.length);\n            if (length >= 4) {\n                let buffer = stream.peek(length);\n                const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.length);\n                const signature = view.getUint32(0, true);\n                for (let i = 0; i < buffer.length - 4; i++) {\n                    const signature = view.getUint32(i, true);\n                    if (signature === 0xdeadbeef || // Core ML\n                        signature === 0x01306b47 || signature === 0x000d4b38 || signature === 0x0002c056) { // ncnn\n                        return null;\n                    }\n                }\n                const match = (pattern, identifier, buffer) => {\n                    if (pattern.identifier && typeof pattern.identifier === 'string' && identifier !== pattern.identifier) {\n                        return false;\n                    } else if (pattern.identifier && pattern.identifier instanceof RegExp && !pattern.identifier.test(identifier)) {\n                        return false;\n                    } else if (pattern.signature && !pattern.signature.every((value, index) => value === buffer[index])) {\n                        return false;\n                    }\n                    return true;\n                };\n                const include = [\n                    { identifier: 'googlenet-v1.bin', signature: [0x80, 0xD6, 0x50, 0xD7, 0xB0, 0xD7, 0xA5, 0x2D, 0xCA, 0x28, 0x49, 0x2A, 0x35, 0x31, 0x0A, 0x31] },\n                    { identifier: 'text-recognition-0012.bin', signature: [0x0B, 0x21, 0xC6, 0xBC, 0xD0, 0xBB, 0xC1, 0x3B] },\n                ];\n                if (include.some((pattern) => match(pattern, identifier, buffer))) {\n                    return context.set('openvino.bin');\n                }\n                const exclude = [\n                    { identifier: '__model__.bin' },\n                    { identifier: 'config.bin' },\n                    { identifier: 'model.bin' },\n                    { identifier: 'ncnn.bin' },\n                    { identifier: 'programs.bin' },\n                    { identifier: 'weights.bin' },\n                    { identifier: /stories\\d+(m|k)\\.bin$/ },\n                    { signature: [0x21, 0xA8, 0xEF, 0xBE, 0xAD, 0xDE] }\n                ];\n                if (exclude.some((pattern) => match(pattern, identifier, buffer))) {\n                    return null;\n                }\n                if (signature === 0x00000001) {\n                    return null;\n                }\n                const size = Math.min(buffer.length & 0xfffffffc, 128);\n                buffer = buffer.subarray(0, size);\n                if (Array.from(buffer).every((value) => value === 0)) {\n                    return context.set('openvino.bin');\n                }\n                const f32 = new Array(buffer.length >> 2);\n                for (let i = 0; i < f32.length; i++) {\n                    f32[i] = view.getFloat32(i << 2, true);\n                }\n                const f16 = new Array(buffer.length >> 1);\n                for (let i = 0; i < f16.length; i++) {\n                    f16[i] = view.getFloat16(i << 1, true);\n                }\n                const i32 = new Array(buffer.length >> 2);\n                for (let i = 0; i < f32.length; i++) {\n                    i32[i] = view.getInt32(i << 2, true);\n                }\n                const validateFloat = (array) => array[0] !== 0 && array.every((x) => !Number.isNaN(x) && Number.isFinite(x)) &&\n                    (array.every((x) => x > -20.0 && x < 20.0 && (x >= 0 || x < -0.0000001) && (x <= 0 || x > 0.0000001)) ||\n                     array.every((x) => x > -100.0 && x < 100.0 && (x * 10) % 1 === 0));\n                const validateInt = (array) => array.length > 32 &&\n                    array.slice(0, 32).every((x) => x === 0 || x === 1 || x === 2 || x === 0x7fffffff);\n                if (validateFloat(f32) || validateFloat(f16) || validateInt(i32)) {\n                    return context.set('openvino.bin');\n                }\n            }\n            return null;\n        }\n        const tags = await context.tags('xml');\n        if (tags.has('net')) {\n            return context.set('openvino.xml');\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        return context.type !== 'openvino.xml' || match.type !== 'openvino.bin';\n    }\n\n    async open(context) {\n        const identifier = context.identifier;\n        const base = identifier.substring(0, identifier.length - 4);\n        let bin = null;\n        switch (context.type) {\n            case 'openvino.xml': {\n                try {\n                    const file = `${base}.bin`;\n                    const content = await context.fetch(file);\n                    bin = content.stream.peek();\n                } catch {\n                    // continue regardless of error\n                }\n                break;\n            }\n            case 'openvino.bin': {\n                try {\n                    const file = `${base}.xml`;\n                    bin = context.stream.peek();\n                    context = await context.fetch(file, null);\n                } catch (error) {\n                    const message = error && error.message ? error.message : error.toString();\n                    throw new openvino.Error(`Required OpenVINO model definition not found (${message.replace(/\\.$/, '')}).`);\n                }\n                break;\n            }\n            default: {\n                throw new openvino.Error(`Unsupported OpenVINO format '${context.type}'.`);\n            }\n        }\n        let document = null;\n        try {\n            document = await context.read('xml');\n        } catch (error) {\n            const message = error && error.message ? error.message : error.toString();\n            throw new openvino.Error(`File format is not OpenVINO XML (${message.replace(/\\.$/, '')}).`);\n        }\n        if (!document.documentElement || document.documentElement.localName !== 'net') {\n            throw new openvino.Error('File format is not OpenVINO IR.');\n        }\n        const element = document.documentElement;\n        const metadata = await context.metadata('openvino-metadata.json');\n        const object = (element) => {\n            const obj = {};\n            for (const attribute of element.attributes) {\n                obj[attribute.localName] = attribute.value;\n            }\n            return obj;\n        };\n        const child = (parent, name) => {\n            const elements = parent.getElementsByTagName(name);\n            if (elements.length > 1) {\n                throw new openvino.Error(`Element '${parent.localName}' has multiple '${name}' elements.`);\n            }\n            return elements.length > 0 ? elements[0] : null;\n        };\n        const children = (parent, name, element) => {\n            const list = child(parent, name);\n            return list ? list.getElementsByTagName(element) : [];\n        };\n        const edges = (parent, name) => {\n            const map = {};\n            for (const element of children(parent, name || 'edges', 'edge')) {\n                const fromLayer = element.getAttribute('from-layer');\n                const fromPort = element.getAttribute('from-port');\n                const toLayer = element.getAttribute('to-layer');\n                const toPort = element.getAttribute('to-port');\n                map[`${toLayer}:${toPort}`] = `${fromLayer}:${fromPort}`;\n            }\n            return map;\n        };\n        const layers = (parent) => {\n            const ports = (parent, name) => {\n                return children(parent, name, 'port').map((element) => {\n                    const port = object(element);\n                    port.dims = element.getElementsByTagName('dim').map((dim) => parseInt(dim.textContent.trim(), 10));\n                    return port;\n                });\n            };\n            return children(parent, 'layers', 'layer').map((element) => {\n                const layer = object(element);\n                layer.input = ports(element, 'input');\n                layer.output = ports(element, 'output');\n                const data = child(element, 'data');\n                const blobs = child(element, 'blobs');\n                layer.data = data ? object(data) : {};\n                layer.blobs = blobs ? blobs.getElementsByTagName('*').map((blob) => {\n                    const obj = object(blob);\n                    obj.name = blob.localName;\n                    obj.offset = parseInt(obj.offset, 10);\n                    obj.size = parseInt(obj.size, 10);\n                    return obj;\n                }) : [];\n                if (layer.type === 'TensorIterator') {\n                    layer.back_edges = edges(element, 'back_edges');\n                    const body = child(element, 'body');\n                    if (body) {\n                        layer.body = {\n                            layers: layers(body),\n                            edges: edges(body)\n                        };\n                    }\n                    const port_map = child(element, 'port_map');\n                    if (port_map) {\n                        layer.port_map = { input: [], output: [] };\n                        for (const port of port_map.getElementsByTagName('*')) {\n                            const item = object(port);\n                            switch (port.localName) {\n                                case 'input': layer.port_map.input.push(item); break;\n                                case 'output': layer.port_map.output.push(item); break;\n                                default: throw new openvino.Error(`Unsupported port local name '${port.localName}'.`);\n                            }\n                        }\n                    }\n                }\n                return layer;\n            });\n        };\n        const net = object(element);\n        net.body =  {\n            layers: layers(element),\n            edges: edges(element)\n        };\n        return new openvino.Model(metadata, net, bin);\n    }\n};\n\nopenvino.Model = class {\n\n    constructor(metadata, net, bin) {\n        this.name = net.name || '';\n        this.modules = [new openvino.Graph(metadata, net, bin)];\n        this.format = 'OpenVINO IR';\n    }\n};\n\nopenvino.Graph = class {\n\n    constructor(metadata, net, bin) {\n        this.name = net.name || '';\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        const tensors = new Map();\n        const values = new Map();\n        values.map = (layer, precision, port, map) => {\n            const id = `${layer}:${port.id}`;\n            const name = map && map[id] ? map[id] : id;\n            if (name === '') {\n                throw new openvino.Error('Empty value name.');\n            }\n            const shape = port.dims.length === 0 ? null : new openvino.TensorShape(port.dims);\n            if (!precision && values.has(name)) {\n                const value = values.get(name);\n                if (value.type && value.type.shape && value.type.shape.equals(shape)) {\n                    return value;\n                }\n            }\n            const type = new openvino.TensorType(precision, shape);\n            let tensor = null;\n            if (tensors.has(id)) {\n                const blob = tensors.get(id);\n                const offset = blob.offset;\n                const size = blob.size;\n                const shape = new openvino.TensorShape(blob.shape);\n                const type = new openvino.TensorType(blob.precision || precision, shape);\n                const data = (bin && (offset + size) <= bin.length) ? bin.slice(offset, offset + size) : null;\n                tensor = new openvino.Tensor(type, data, 'Const');\n            }\n            if (!values.has(name)) {\n                values.set(name, new openvino.Value(name, type, tensor));\n            } else if (name === id && type && !type.equals(values.get(name).type)) {\n                throw new openvino.Error(`Duplicate value '${name}'.`);\n            }\n            return values.get(name);\n        };\n        const nodes = new Map();\n        const constant = (layers, edges, back_edges) => {\n            back_edges = back_edges || {};\n            for (const layer of layers) {\n                if (layer.type === 'Const' &&\n                    layer.input.length === 0 && layer.output.length === 1 && layer.blobs.length === 0 &&\n                    layer.data && layer.data.element_type !== undefined && layer.data.offset !== undefined && layer.data.size !== undefined) {\n                    let precision = null;\n                    switch (layer.data.element_type) {\n                        case 'f16': precision = 'FP16'; break;\n                        case 'f32': precision = 'FP32'; break;\n                        case 'f64': precision = 'FP64'; break;\n                        default: precision = layer.data.element_type.toUpperCase();\n                    }\n                    const shape = layer.data.shape;\n                    layer.blobs.push({\n                        name: 'value',\n                        precision,\n                        offset: parseInt(layer.data.offset, 10),\n                        size: parseInt(layer.data.size, 10),\n                        shape: shape ? shape.split(',').map((dim) => parseInt(dim.trim(), 10)) : null\n                    });\n                    layer.data = {};\n                }\n                if (layer.type === 'Const' && layer.blobs.length === 1 && !layer.blobs[0].shape &&\n                    layer.input.length === 0 && layer.output.length === 1 && layer.output[0].dims) {\n                    layer.blobs[0].shape = layer.output[0].dims;\n                }\n            }\n            const constants = new Map();\n            for (const layer of layers) {\n                if (layer.type === 'Const' && layer.input.length === 0 && layer.output.length === 1) {\n                    const from = `${layer.id}:${layer.output[0].id}`;\n                    constants.set(from, { layer, counter: 0 });\n                }\n            }\n            for (const from of Object.values(edges)) {\n                if (constants.has(from)) {\n                    constants.get(from).counter++;\n                }\n            }\n            if (back_edges) {\n                for (const from of Object.values(back_edges)) {\n                    if (constants.has(from)) {\n                        constants.get(from).counter++;\n                    }\n                }\n            }\n            for (const [name, value] of constants) {\n                if (value.counter !== 1) {\n                    constants.delete(name);\n                }\n            }\n            for (const layer of layers) {\n                if (layer.blobs.length === 0) {\n                    for (let i = layer.input.length - 1; i >= 0; i--) {\n                        const input = layer.input[i];\n                        const to = `${layer.id}:${input.id}`;\n                        const from = edges[to] || back_edges[to];\n                        if (!constants.has(from)) {\n                            break;\n                        }\n                        const constLayer = constants.get(from).layer;\n                        if (constLayer && Array.isArray(constLayer.blobs) && constLayer.blobs.length > 0) {\n                            const [blob] = constLayer.blobs;\n                            if (blob) {\n                                blob.id = constLayer.name || constLayer.id;\n                                layer.input[i].blob = blob;\n                                constants.get(from).layer = null;\n                                constants.get(from).delete = true;\n                            }\n                        }\n                    }\n                }\n            }\n            return layers.filter((layer) => {\n                if (layer.type === 'Const' && layer.input.length === 0 && layer.output.length === 1) {\n                    const from = `${layer.id}:${layer.output[0].id}`;\n                    if (constants.has(from) && constants.get(from).delete) {\n                        return false;\n                    }\n                }\n                return true;\n            });\n        };\n        const body = net.body;\n        const body_layers = body && Array.isArray(body.layers) ? body.layers : [];\n        const body_edges = body && body.edges ? body.edges : {};\n        const layers = new Map(body_layers.map((entry) => [entry.id, entry]));\n        const ports = new Map();\n        if (Array.isArray(net.input)) {\n            for (const input of net.input) {\n                const value = values.map('', input.precision || null, input);\n                const argument = new openvino.Argument(input.id, [value]);\n                this.inputs.push(argument);\n                ports.set(input.id, value);\n            }\n        }\n        if (Array.isArray(net.output)) {\n            for (const output of net.output) {\n                const value = values.map('', output.precision || null, output);\n                const argument = new openvino.Argument(output.id, [value]);\n                this.outputs.push(argument);\n                ports.set(output.id, value);\n            }\n        }\n        for (const layer of body_layers) {\n            for (const output of layer.output) {\n                if (!output.precision) {\n                    output.precision = layer.precision;\n                }\n            }\n        }\n        if (net.port_map) {\n            for (const input of net.port_map.input) {\n                const external_port = net.input.find((v) => v.id === input.external_port_id);\n                const layer = layers.get(input.internal_layer_id);\n                if (input.internal_port_id === undefined) {\n                    input.internal_port_id = '';\n                    layer.input.push({\n                        id: input.internal_port_id,\n                        precision: layer.data.element_type,\n                        dims: layer.data.shape.split(',')\n                    });\n                }\n                const internal_port = layer.input.find((v) => v.id === input.internal_port_id);\n                internal_port.precision = external_port.precision;\n            }\n            for (const output of net.port_map.output) {\n                const external_port = net.output.find((v) => v.id === output.external_port_id);\n                const layer = layers.get(output.internal_layer_id);\n                if (output.internal_port_id === undefined) {\n                    output.internal_port_id = '';\n                    layer.output.push({\n                        id: output.internal_port_id,\n                        precision: external_port.precision,\n                        dims: external_port.dims\n                    });\n                }\n            }\n        }\n        const layer_list = constant(body_layers, body_edges);\n        for (const layer of layer_list) {\n            for (const input of layer.input) {\n                if (input.blob) {\n                    tensors.set(`${layer.id}:${input.id}`, input.blob);\n                }\n            }\n        }\n        for (const layer of layer_list) {\n            for (const output of layer.output) {\n                values.map(layer.id, output.precision, output, null);\n            }\n        }\n        for (const layer of layer_list) {\n            const inputs = layer.input.map((input) => {\n                const to = `${layer.id}:${input.id}`;\n                if (body.edges[to]) {\n                    const output = body.edges[to] ? body.edges[to].split(':') : [];\n                    const [outputLayerId, outputId] = output;\n                    const outputLayer = layers.get(outputLayerId);\n                    if (outputLayer && outputId) {\n                        const output = outputLayer.output.find((output) => output.id === outputId);\n                        if (input && output) {\n                            input.precision = output.precision;\n                        }\n                    }\n                }\n                return values.map(layer.id, input.precision || layer.precision || null, input, body.edges);\n            });\n            const outputs = layer.output.map((output) => {\n                let precision = null;\n                if (output && output.precision) {\n                    precision = output.precision;\n                } else if (layer && layer.precision) {\n                    precision = layer.precision;\n                }\n                return values.map(layer.id, precision, output, null);\n            });\n            const subgraph = Array.isArray(net.input) || Array.isArray(net.output);\n            if (!subgraph && (layer.type === 'Input' || layer.type === 'Parameter')) {\n                const name = layer.name || '';\n                // precision is a part of OpenVINO IR layers of IR v6 and earlier\n                // in IR v7 and newer the port is no longer an attribute of the layer but of each output port\n                // IR input is not just a placeholder, it is conceptually the legitimate layer\n                // in order not to break compatibility with the overall approach\n                // with openvino.Argument for inputs and openvino.Node for outputs\n                // input openvino.Node would be stored as an optional attribute of openvino.Parameter\n                this.inputs.push(new openvino.Argument(name, outputs));\n            } else {\n                const node = new openvino.Node(metadata, layer, inputs, outputs, bin);\n                nodes.set(layer.id, node);\n            }\n        }\n        this.nodes = Array.from(nodes.values());\n        if (net.port_map) {\n            const createMapLayer = (obj) => {\n                const data = {};\n                for (const [name, value] of Object.entries(obj)) {\n                    if (name !== 'external_port_id' && name !== 'internal_layer_id' && name !== 'internal_port_id') {\n                        data[name] = value;\n                    }\n                }\n                return { type: '-', data };\n            };\n            for (const input of net.port_map.input) {\n                const internal_port = layers.get(input.internal_layer_id).input.find((v) => v.id === input.internal_port_id);\n                const inputs = [ports.get(input.external_port_id)];\n                const outputs = [values.map(input.internal_layer_id, internal_port.precision, internal_port)];\n                const layer = createMapLayer(input);\n                this.nodes.push(new openvino.Node(metadata, layer, inputs, outputs));\n            }\n            for (const output of net.port_map.output) {\n                const internal_port = layers.get(output.internal_layer_id).output.find((v) => v.id === output.internal_port_id);\n                const inputs = [values.map(output.internal_layer_id, internal_port.precision, internal_port)];\n                const outputs = [ports.get(output.external_port_id)];\n                const layer = createMapLayer(output);\n                this.nodes.push(new openvino.Node(metadata, layer, inputs, outputs));\n            }\n        }\n    }\n};\n\nopenvino.Node = class {\n\n    constructor(metadata, layer, inputs, outputs, bin) {\n        this.name = layer.name || '';\n        this.inputs = [];\n        this.outputs = [];\n        this.attributes = [];\n        const type = layer.type;\n        this.type = metadata.type(type) || { name: type };\n        for (let i = 0; i < inputs.length;) {\n            let input = null;\n            if (this.type && Array.isArray(this.type.inputs) && i < this.type.inputs.length) {\n                input = this.type.inputs[i];\n            } else if (inputs.length === 1) {\n                input = { name: 'input' };\n            } else {\n                input = { name: i.toString() };\n            }\n            const count = input.type === 'Tensor[]' ? inputs.length - i : 1;\n            const values = inputs.slice(i, i + count);\n            const argument = new openvino.Argument(input.name, values);\n            this.inputs.push(argument);\n            i += count;\n        }\n        for (let i = 0; i < outputs.length;) {\n            let output = null;\n            if (this.type && Array.isArray(this.type.outputs) && i < this.type.outputs.length) {\n                output = this.type.outputs[i];\n            } else if (outputs.length === 1) {\n                output = { name: 'output' };\n            } else {\n                output = { name: i.toString() };\n            }\n            const count = output.type === 'Tensor[]' ? outputs.length - i : 1;\n            const values = outputs.slice(i, i + count);\n            const argument = new openvino.Argument(output.name, values);\n            this.outputs.push(argument);\n            i += count;\n        }\n        const op = type;\n        for (const [name, obj] of Object.entries(layer.data)) {\n            const schema = metadata.attribute(op, name);\n            let value = obj;\n            let type = null;\n            let visible = true;\n            if (schema && schema.type !== undefined) {\n                type = schema.type;\n                switch (schema.type) {\n                    case '':\n                    case 'graph':\n                    case 'string':\n                        break;\n                    case 'boolean':\n                        if (obj === '1' || obj === 'true' || obj === 'True') {\n                            value = true;\n                        } else if (obj === '0' || obj === 'false' || obj === 'False') {\n                            value = false;\n                        } else {\n                            throw new openvino.Error(`Unsupported attribute boolean value '${obj}'.`);\n                        }\n                        break;\n                    case 'int32':\n                    case 'int64': {\n                        const intValue = Number.parseInt(obj, 10);\n                        value = Number.isNaN(obj - intValue) ? obj : intValue;\n                        break;\n                    }\n                    case 'float32':\n                    case 'float64': {\n                        const floatValue = Number.parseFloat(obj);\n                        value = Number.isNaN(obj - floatValue) ? obj : floatValue;\n                        break;\n                    }\n                    case 'int32[]':\n                        if (obj.length > 2) {\n                            let ints = [];\n                            for (const entry of obj.split(',')) {\n                                const item = entry.trim();\n                                const intValue = Number.parseInt(item, 10);\n                                if (Number.isNaN(item - intValue)) {\n                                    ints = null;\n                                } else if (ints !== null) {\n                                    ints.push(intValue);\n                                }\n                            }\n                            if (ints !== null) {\n                                value = ints;\n                            }\n                        }\n                        break;\n                    case 'float32[]':\n                        if (obj.length > 2) {\n                            let floats = [];\n                            for (const entry of obj.split(',')) {\n                                const item = entry.trim();\n                                const floatValue = Number.parseFloat(item);\n                                if (Number.isNaN(item - floatValue)) {\n                                    floats = null;\n                                } else if (floats !== null) {\n                                    floats.push(floatValue);\n                                }\n                            }\n                            if (floats !== null) {\n                                value = floats;\n                            }\n                        }\n                        break;\n                    default:\n                        throw new openvino.Error(`Unsupported attribute type '${schema.type}'.`);\n                }\n            }\n            if (schema && schema.visible === false) {\n                visible = false;\n            } else if (schema && schema.default !== undefined) {\n                const defaultValue = schema.default;\n                if (value === defaultValue) {\n                    visible = false;\n                } else if (Array.isArray(value) && Array.isArray(defaultValue)) {\n                    const repeat = defaultValue.length > 1 && defaultValue[defaultValue.length - 1] === null;\n                    if (value.every((item, index) => item === (repeat && index >= defaultValue.length - 1 ? defaultValue[defaultValue.length - 2] : defaultValue[index]))) {\n                        visible = false;\n                    }\n                }\n            }\n            const attribute = new openvino.Argument(name, value, type, visible);\n            this.attributes.push(attribute);\n        }\n        if (layer.type === 'TensorIterator') {\n            const graph = new openvino.Graph(metadata, layer, null);\n            const attribute = new openvino.Argument('body', graph, 'graph');\n            this.attributes.push(attribute);\n        }\n        for (const blob of layer.blobs || []) {\n            const name = blob.name;\n            const offset = blob.offset;\n            let data = (bin && (offset + blob.size) <= bin.length) ? bin.slice(offset, offset + blob.size) : null;\n            let dimensions = blob.shape || null;\n            const category = blob.kind || 'Blob';\n            const id = blob.id || '';\n            const precision = blob.precision || layer.precision || null;\n            let itemSize = -1;\n            switch (precision) {\n                case 'BOOL': case 'BOOLEAN':          itemSize = 1; break;\n                case 'I1':   case 'U1':               itemSize = 0.125; break;\n                case 'I2':   case 'U2':               itemSize = 0.25; break;\n                case 'I4':   case 'U4':               itemSize = 0.5; break;\n                case 'I8':   case 'U8':               itemSize = 1; break;\n                case 'I16':  case 'U16': case 'FP16': itemSize = 2; break;\n                case 'I32':  case 'U32': case 'FP32': itemSize = 4; break;\n                case 'I64':  case 'U64': case 'FP64': itemSize = 8; break;\n                case 'F8E4M3':                        itemSize = 1; break;\n                case 'BF16':                          itemSize = 2; break;\n                case 'DYNAMIC':                       itemSize = 0; break;\n                default: throw new openvino.Error(`Unsupported data type size '${precision}'.`);\n            }\n            const weight = (name, precision, dimensions, data) => {\n                const shape = dimensions ? new openvino.TensorShape(dimensions) : null;\n                const type = new openvino.TensorType(precision, shape);\n                const tensor = new openvino.Tensor(type, data, category);\n                const value = new openvino.Value(id, null, tensor);\n                this.inputs.push(new openvino.Argument(name, [value]));\n                const size = Math.ceil(dimensions.reduce((a, b) => a * b, 1) * itemSize);\n                if (data && data.length !== size) {\n                    return data.slice(size, data.length);\n                }\n                return null;\n            };\n            if (itemSize !== -1) {\n                switch (`${type}:${name}`) {\n                    case 'FullyConnected:weights': {\n                        const outSize = parseInt(layer.data['out-size'], 10);\n                        dimensions = [layer.input[0].dims[1], outSize];\n                        break;\n                    }\n                    case 'FullyConnected:biases': {\n                        dimensions = [parseInt(layer.data['out-size'], 10)];\n                        break;\n                    }\n                    case 'Convolution:weights':\n                    case 'Deconvolution:weights': {\n                        const c = this.inputs[0].value[0].type.shape.dimensions[1];\n                        const group = parseInt(layer.data.group || '1', 10);\n                        const kernel = layer.data['kernel-x'] !== undefined && layer.data['kernel-y'] !== undefined ?\n                            [parseInt(layer.data['kernel-x'], 10), parseInt(layer.data['kernel-y'], 10)] :\n                            layer.data.kernel.split(',').map((v) => parseInt(v.trim(), 10));\n                        const n = parseInt(layer.data.output, 10);\n                        dimensions = [Math.floor(c / group), n].concat(kernel);\n                        break;\n                    }\n                    case 'LSTMCell:weights': {\n                        const input_size = inputs[0].type.shape.dimensions[1];\n                        const hidden_size = parseInt(layer.data.hidden_size, 10);\n                        data = weight('W', precision, [4 * hidden_size, input_size], data);\n                        data = weight('R', precision, [4 * hidden_size, hidden_size], data);\n                        break;\n                    }\n                    case 'LSTMCell:biases': {\n                        const hidden_size = parseInt(layer.data.hidden_size, 10);\n                        data = weight('B', precision, [4 * hidden_size], data);\n                        break;\n                    }\n                    case 'GRUCell:weights': {\n                        const input_size = inputs[0].type.shape.dimensions[1];\n                        const hidden_size = parseInt(layer.data.hidden_size, 10);\n                        data = weight('W', precision, [3 * hidden_size, input_size], data);\n                        data = weight('R', precision, [3 * hidden_size, hidden_size], data);\n                        break;\n                    }\n                    case 'GRUCell:biases': {\n                        const linear_before_reset = parseInt(layer.data.linear_before_reset, 10);\n                        const hidden_size = parseInt(layer.data.hidden_size, 10);\n                        dimensions = linear_before_reset ? [4 * hidden_size] : [3 * hidden_size];\n                        data = weight('B', precision, dimensions, data);\n                        break;\n                    }\n                    case 'Convolution:biases': {\n                        dimensions = [parseInt(layer.data.output, 10)];\n                        break;\n                    }\n                    case 'ScaleShift:weights':\n                    case 'ScaleShift:biases':\n                    case 'Normalize:weights': {\n                        dimensions = [layer.input[0].dims[1]];\n                        break;\n                    }\n                    case 'PReLU:weights': {\n                        dimensions = layer.data.channel_shared === '1' ? [1] : [layer.input[0].dims[1]];\n                        break;\n                    }\n                    case 'Const:custom': {\n                        if (this.outputs.length > 0 &&\n                            this.outputs[0].value.length > 0 &&\n                            this.outputs[0].value[0].type &&\n                            this.outputs[0].value[0].type.shape &&\n                            this.outputs[0].value[0].type.shape.dimensions) {\n                            dimensions = this.outputs[0].value[0].type.shape.dimensions;\n                        }\n                        break;\n                    }\n                    default: {\n                        break;\n                    }\n                }\n            }\n            if (data) {\n                weight(name, precision, dimensions, data);\n            }\n        }\n    }\n};\n\nopenvino.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name;\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\nopenvino.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new openvino.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\nopenvino.Tensor = class {\n\n    constructor(type, data, category) {\n        this.type = type;\n        this.values = data;\n        this.category = category;\n    }\n};\n\nopenvino.TensorType = class {\n\n    constructor(precision, shape) {\n        precision = precision ? precision.toLowerCase() : precision;\n        switch (precision) {\n            case 'f4e2m1':      this.dataType = 'float4e2m1'; break;\n            case 'f8e4m3':      this.dataType = 'float8e4m3'; break;\n            case 'f8e5m2':      this.dataType = 'float8e5m2'; break;\n            case 'f8e8m0':      this.dataType = 'float8e8m0'; break;\n            case 'f16':         this.dataType = 'float16'; break;\n            case 'f32':         this.dataType = 'float32'; break;\n            case 'f64':         this.dataType = 'float64'; break;\n            case 'fp16':        this.dataType = 'float16'; break;\n            case 'fp32':        this.dataType = 'float32'; break;\n            case 'fp64':        this.dataType = 'float64'; break;\n            case 'bf16':        this.dataType = 'bfloat16'; break;\n            case 'nf4':         this.dataType = 'nfloat4'; break;\n            case 'i2':          this.dataType = 'int2'; break;\n            case 'i4':          this.dataType = 'int4'; break;\n            case 'i8':          this.dataType = 'int8'; break;\n            case 'i16':         this.dataType = 'int16'; break;\n            case 'i32':         this.dataType = 'int32'; break;\n            case 'i64':         this.dataType = 'int64'; break;\n            case 'u1':          this.dataType = 'boolean'; break;\n            case 'u2':          this.dataType = 'uint2'; break;\n            case 'u4':          this.dataType = 'uint4'; break;\n            case 'u8':          this.dataType = 'uint8'; break;\n            case 'u16':         this.dataType = 'uint16'; break;\n            case 'u32':         this.dataType = 'uint32'; break;\n            case 'u64':         this.dataType = 'uint64'; break;\n            case 'bool':        this.dataType = 'boolean'; break;\n            case 'boolean':     this.dataType = 'boolean'; break;\n            case 'bin':         this.dataType = 'bit'; break;\n            case 'string':      this.dataType = 'string'; break;\n            case 'dynamic':     this.dataType = 'dynamic'; break;\n            case 'unspecified': this.dataType = 'unspecified'; break;\n            case '':            this.dataType = '?'; break;\n            case null:          this.dataType = '?'; break;\n            default:            throw new openvino.Error(`Unsupported precision '${JSON.stringify(precision)}'.`);\n        }\n        this.shape = shape;\n    }\n\n    equals(obj) {\n        return obj && this.dataType === obj.dataType &&\n            ((this.shape === null && obj.shape === null) || this.shape && this.shape.equals(obj.shape));\n    }\n\n    toString() {\n        if (this.shape === null) {\n            return `${this.dataType}[?]`;\n        }\n        return this.dataType + this.shape.toString();\n    }\n};\n\nopenvino.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    equals(obj) {\n        return obj && Array.isArray(obj.dimensions) &&\n            Array.isArray(this.dimensions) && this.dimensions.length === obj.dimensions.length\n            && obj.dimensions.every((value, index) => this.dimensions[index] === value);\n    }\n\n    toString() {\n        if (!this.dimensions || this.dimensions.length === 0) {\n            return '';\n        }\n        return `[${this.dimensions.join(',')}]`;\n    }\n};\n\nopenvino.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading OpenVINO model.';\n    }\n};\n\nexport const ModelFactory = openvino.ModelFactory;\n"
  },
  {
    "path": "source/paddle.js",
    "content": "\nimport * as base from './base.js';\nimport * as flatbuffers from './flatbuffers.js';\nimport * as protobuf from './protobuf.js';\nimport * as python from './python.js';\n\nconst paddle = {};\n\npaddle.ModelFactory = class {\n\n    async match(context) {\n        const identifier = context.identifier;\n        const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';\n        if (identifier === '__model__' || extension === '__model__' || extension === 'paddle' || extension === 'pdmodel') {\n            const tags = await context.tags('pb');\n            if (tags.get(1) === 2) {\n                return context.set('paddle.pb');\n            }\n        }\n        if (extension === 'pbtxt' || extension === 'txt') {\n            const tags = await context.tags('pbtxt');\n            if (tags.has('blocks')) {\n                return context.set('paddle.pbtxt');\n            }\n        }\n        const stream = context.stream;\n        if (stream && stream.length > 16 && stream.peek(16).every((value) => value === 0x00)) {\n            return context.set('paddle.params');\n        }\n        const pickle = await paddle.Pickle.open(context);\n        if (pickle) {\n            return context.set(pickle.name, pickle);\n        }\n        const entries = await paddle.Entries.open(context);\n        if (entries) {\n            return context.set(entries.name, entries);\n        }\n        const naive = await paddle.NaiveBuffer.open(context);\n        if (naive) {\n            return context.set(naive.name, naive);\n        }\n        const obj = await context.peek('json');\n        if (obj && obj.base_code && obj.program) {\n            return context.set('paddle.ir', obj);\n        }\n        return null;\n    }\n\n    filter(context, match) {\n        if (context.type === 'paddle.pb' && (match.type === 'paddle.params' || match.type === 'paddle.pickle')) {\n            return false;\n        }\n        if (context.type === 'paddle.naive.model' && match.type === 'paddle.naive.param') {\n            return false;\n        }\n        return true;\n    }\n\n    async open(context) {\n        const metadata = await context.metadata('paddle-metadata.json');\n        switch (context.type) {\n            case 'paddle.naive':\n            case 'paddle.naive.model':\n            case 'paddle.naive.param': {\n                paddle.schema = await context.require('./paddle-schema');\n                paddle.schema = paddle.schema.paddle.lite.fbs.proto;\n                const target = context.value;\n                target.read();\n                return new paddle.Model(metadata, target.format, target.model, target.weights);\n            }\n            case 'paddle.ir': {\n                const ir = new paddle.IR(context.value);\n                const format = `PaddlePaddle IR v${ir.version}`;\n                return new paddle.Model(metadata, format, ir.desc, ir.tensors);\n            }\n            default: {\n                paddle.proto = await context.require('./paddle-proto');\n                paddle.proto = paddle.proto.paddle.framework.proto;\n                const identifier = context.identifier;\n                const parts = identifier.split('.');\n                const extension = parts.pop().toLowerCase();\n                const base = parts.join('.');\n                const openProgram = async (context, type) => {\n                    const program = {};\n                    switch (type) {\n                        case 'paddle.pbtxt': {\n                            try {\n                                const reader = await context.read('protobuf.text');\n                                reader.enum = function(type) {\n                                    const token = this.token();\n                                    this.next();\n                                    this.semicolon();\n                                    if (type[token] !== undefined) {\n                                        return type[token];\n                                    }\n                                    if (token === 'LOD_TENSOR') {\n                                        return type.DENSE_TENSOR;\n                                    }\n                                    throw new paddle.Error(`Unknown enum value '${token}' ${this.location()}`);\n                                };\n                                reader.field = function(tag, message) {\n                                    if (message instanceof paddle.proto.VarType && tag === 'lod_tensor') {\n                                        message.dense_tensor = paddle.proto.VarType.DenseTensorDesc.decodeText(reader);\n                                    } else if (message instanceof paddle.proto.VarType.DenseTensorDesc && tag === 'lod_level') {\n                                        message.legacy_lod_level = reader.int32();\n                                    } else {\n                                        throw new Error(`Unknown field '${tag}' ${this.location()}`);\n                                    }\n                                };\n                                program.desc = paddle.proto.ProgramDesc.decodeText(reader);\n                            } catch (error) {\n                                const message = error && error.message ? error.message : error.toString();\n                                throw new paddle.Error(`File text format is not paddle.ProgramDesc (${message.replace(/\\.$/, '')}).`);\n                            }\n                            break;\n                        }\n                        case 'paddle.pb': {\n                            try {\n                                const reader = await context.read('protobuf.binary');\n                                program.desc = paddle.proto.ProgramDesc.decode(reader);\n                            } catch (error) {\n                                const message = error && error.message ? error.message : error.toString();\n                                throw new paddle.Error(`File format is not paddle.ProgramDesc (${message.replace(/\\.$/, '')}).`);\n                            }\n                            break;\n                        }\n                        default: {\n                            throw new paddle.Error(`Unsupported Paddle format '${type}'.`);\n                        }\n                    }\n                    const formatVersion = (version) => {\n                        if (version && version.version !== undefined) {\n                            const number = version.version.toNumber();\n                            if (number > 0) {\n                                const list = [Math.floor(number / 1000000) % 1000, Math.floor(number / 1000) % 1000, number % 1000];\n                                if (list.slice(-1).pop() === 0) {\n                                    list.pop();\n                                    if (list.slice(-1).pop() === 0) {\n                                        list.pop();\n                                    }\n                                }\n                                return ` v${list.map((item) => item.toString()).join('.')}`;\n                            }\n                        }\n                        return '';\n                    };\n                    program.format = `PaddlePaddle${formatVersion(program.desc.version)}`;\n                    const variables = new Set();\n                    for (const block of program.desc.blocks) {\n                        const blockVars = new Set();\n                        for (const variable of block.vars) {\n                            if (variable.persistable && variable.type &&\n                                variable.type.type !== paddle.DataType.FETCH_LIST &&\n                                variable.type.type !== paddle.DataType.FEED_MINIBATCH) {\n                                blockVars.add(variable.name);\n                            }\n                        }\n                        for (const op of block.ops) {\n                            for (const input of op.inputs) {\n                                for (const argument of input.arguments) {\n                                    if (blockVars.has(argument)) {\n                                        variables.add(argument);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    program.vars = Array.from(variables).sort();\n                    return program;\n                };\n                const loadParams = (stream) => {\n                    const params = [];\n                    while (stream.position < stream.length) {\n                        const tensor = paddle.Utility.openTensorDesc(stream);\n                        params.push(tensor);\n                    }\n                    return params;\n                };\n                const mapParams = (params, program) => {\n                    const weights = new Map();\n                    const vars = program.vars.slice();\n                    for (const param of params) {\n                        weights.set(vars.shift(), param);\n                    }\n                    return weights;\n                };\n                switch (context.type) {\n                    case 'paddle.pickle': {\n                        const target = context.value;\n                        return new paddle.Model(metadata, target.format, null, target.weights);\n                    }\n                    case 'paddle.entries': {\n                        const target = context.value;\n                        target.read();\n                        return new paddle.Model(metadata, target.format, null, target.weights);\n                    }\n                    case 'paddle.params': {\n                        const file = identifier === 'params' ? 'model' : `${base}.pdmodel`;\n                        const params = loadParams(context.stream);\n                        try {\n                            const content = await context.fetch(file);\n                            const program = await openProgram(content, 'paddle.pb');\n                            const weights = mapParams(params, program);\n                            return new paddle.Model(metadata, program.format, program.desc, weights);\n                        } catch {\n                            const weights = new Map(params.map((param, index) => [index.toString(), param]));\n                            return new paddle.Model(metadata, 'PaddlePaddle Inference Weights', null, weights);\n                        }\n                    }\n                    case 'paddle.pb':\n                    case 'paddle.pbtxt': {\n                        const loadEntries = async (context, program) => {\n                            const promises = program.vars.map((name) => context.fetch(name).then((context) => context.stream).catch(() => null));\n                            const streams = await Promise.all(promises);\n                            const params = streams.map((stream) => stream ? paddle.Utility.openTensorDesc(stream) : null);\n                            const weights = mapParams(params, program);\n                            return new paddle.Model(metadata, program.format, program.desc, weights);\n                        };\n                        const openNumPyArrayPickle = (stream) => {\n                            const execution = new python.Execution();\n                            const pickle = execution.__import__('pickle');\n                            const unpickler = new pickle.Unpickler(stream);\n                            const obj = unpickler.load();\n                            const container = new paddle.Pickle(obj);\n                            return container.weights || new Map();\n                        };\n                        const program = await openProgram(context, context.type);\n                        if (extension === 'pdmodel') {\n                            try {\n                                const name = `${base}.pdiparams`;\n                                const content = await context.fetch(name);\n                                const params = loadParams(content.stream);\n                                const weights = mapParams(params, program);\n                                return new paddle.Model(metadata, program.format, program.desc, weights);\n                            } catch {\n                                try {\n                                    const name = `${base}.pdparams`;\n                                    const content = await context.fetch(name);\n                                    const weights = openNumPyArrayPickle(content.stream);\n                                    try {\n                                        const name = `${base}.pdopt`;\n                                        const content = await context.fetch(name);\n                                        for (const [name, value] of openNumPyArrayPickle(content.stream)) {\n                                            if (!weights.has(name)) {\n                                                weights.set(name, value);\n                                            }\n                                        }\n                                        return new paddle.Model(metadata, program.format, program.desc, weights);\n                                    } catch {\n                                        return new paddle.Model(metadata, program.format, program.desc, weights);\n                                    }\n                                } catch {\n                                    try {\n                                        const name = `${base}.pdopt`;\n                                        const content = await context.fetch(name);\n                                        const weights = openNumPyArrayPickle(content.stream);\n                                        return new paddle.Model(metadata, program.format, program.desc, weights);\n                                    } catch {\n                                        return loadEntries(context, program);\n                                    }\n                                }\n                            }\n                        }\n                        if (identifier === 'model') {\n                            try {\n                                const content = await context.fetch('params');\n                                const params = loadParams(content.stream);\n                                const weights = mapParams(params, program);\n                                return new paddle.Model(metadata, program.format, program.desc, weights);\n                            } catch {\n                                return loadEntries(context, program);\n                            }\n                        }\n                        return loadEntries(context, program);\n                    }\n                    default: {\n                        throw new paddle.Error(`Unsupported PaddlePaddle format '${context.type}'.`);\n                    }\n                }\n            }\n        }\n    }\n};\n\npaddle.Model = class {\n\n    constructor(metadata, format, desc, tensors) {\n        desc = desc && Array.isArray(desc.blocks) ? desc : { blocks: [null] };\n        this.format = format;\n        this.modules = desc.blocks.map((block) => new paddle.Graph(metadata, block, tensors));\n    }\n};\n\npaddle.Graph = class {\n\n    constructor(metadata, block, tensors) {\n        this.nodes = [];\n        this.inputs = [];\n        this.outputs = [];\n        if (block) {\n            this.name = block.idx.toString();\n            const values = new Map();\n            if (block.kind === 'block') {\n                for (const [name, input] of block.argInputs) {\n                    const [parameter, tensorType] = input;\n                    const value = new paddle.Value(name, tensorType, null, null);\n                    values.set(name, value);\n                    this.inputs.push(new paddle.Argument(parameter, [value]));\n                }\n            }\n            for (const variable of block.vars) {\n                const type = variable.type && variable.type.type && variable.type.dense_tensor && variable.type.dense_tensor.tensor ? paddle.Utility.createTensorType(variable.type.dense_tensor.tensor.data_type, variable.type.dense_tensor.tensor.dims) : null;\n                const tensor = variable.persistable && variable.type && variable.type.type !== paddle.DataType.FETCH_LIST && variable.type.type !== paddle.DataType.FEED_MINIBATCH ? (tensors.get(variable.name) || new paddle.Tensor(type)) : null;\n                values.set(variable.name, new paddle.Value(variable.name, type, tensor));\n            }\n            const scope = {};\n            for (let i = 0; i < block.ops.length; i++) {\n                for (const input of block.ops[i].inputs) {\n                    input.arguments = input.arguments.map((argument) => scope[argument] ? scope[argument] : argument);\n                }\n                for (const output of block.ops[i].outputs) {\n                    output.arguments = output.arguments.map((argument) => {\n                        if (scope[argument]) {\n                            const next = `${argument}\\n${i}`; // custom argument id\n                            scope[argument] = next;\n                            return next;\n                        }\n                        scope[argument] = argument;\n                        return argument;\n                    });\n                }\n            }\n            for (const op of block.ops) {\n                for (const input of op.inputs) {\n                    for (const name of input.arguments) {\n                        if (!values.has(name)) {\n                            values.set(name, new paddle.Value(name, null, null));\n                        }\n                    }\n                }\n                for (const output of op.outputs) {\n                    for (const name of output.arguments) {\n                        if (output.values && output.values.has(name)) {\n                            values.set(name, output.values.get(name));\n                        }\n                        if (!values.has(name)) {\n                            values.set(name, new paddle.Value(name, null, null));\n                        }\n                    }\n                }\n            }\n            let lastNode = null;\n            let lastOutput = null;\n            for (const op of block.ops) {\n                if (op.type === 'feed') {\n                    let name = '';\n                    const attr = op.attrs.find((attr) => attr.name === 'col');\n                    if (attr) {\n                        if (op.kind === 'op') {\n                            name = attr.irValue.toString();\n                        } else {\n                            name = attr.i.toString();\n                        }\n                    }\n                    const argument = new paddle.Argument(name, op.outputs[0].arguments.map((id) => values.get(id)));\n                    this.inputs.push(argument);\n                } else if (op.type === 'fetch') {\n                    let name = '';\n                    const attr = op.attrs.find((attr) => attr.name === 'col');\n                    if (attr) {\n                        if (op.kind === 'op') {\n                            name = attr.irValue.toString();\n                        } else {\n                            name = attr.i.toString();\n                        }\n                    }\n                    const argument = new paddle.Argument(name, op.inputs[0].arguments.map((id) => values.get(id)));\n                    this.outputs.push(argument);\n                } else {\n                    const node = new paddle.Node(metadata, op, values);\n                    if (op.inputs.length === 1 && op.inputs[0].arguments.length === 1 &&\n                        op.outputs.length >= 1 && op.outputs[0].arguments.length === 1 &&\n                        op.inputs[0].arguments[0].split('\\n').shift() === op.outputs[0].arguments[0].split('\\n').shift() &&\n                        lastNode &&\n                        lastOutput === op.inputs[0].arguments[0].split('\\n').shift()) {\n                        lastNode.chain.push(node);\n                    } else {\n                        this.nodes.push(node);\n                        lastNode = null;\n                        lastOutput = null;\n                        if (op.outputs.length === 1 && op.outputs[0].arguments.length === 1) {\n                            lastNode = node;\n                            lastOutput = op.outputs[0].arguments[0].split('\\n').shift();\n                        }\n                    }\n                }\n            }\n        } else {\n            const values = new Map();\n            const ops = new Map();\n            for (const [name, tensor] of tensors) {\n                values.set(name, new paddle.Value(name, tensor.type, tensor));\n                const separator = name.indexOf('.') === -1 ? '_' : '.';\n                const regex = /(.*)_((w_attr|scale|weights|offset|b|w|b_attr)_(moment|beta|velocity|mean_square|mean_grad).*)/;\n                let parts = [];\n                if (separator === '.') {\n                    parts = name.split(separator);\n                } else if (regex.test(name)) {\n                    parts = regex.exec(name).slice(1, 3);\n                } else {\n                    parts = ['', name];\n                }\n                const parameter_name = parts.pop();\n                const op_name = parts.join(separator);\n                if (!ops.has(op_name)) {\n                    ops.set(op_name, { name: op_name, type: 'Weights', inputs: [] });\n                }\n                const op = ops.get(op_name);\n                op.inputs.push({ parameter: parameter_name, arguments: [name] });\n            }\n            for (const op of Array.from(ops.values())) {\n                this.nodes.push(new paddle.Node(metadata, op, values));\n            }\n        }\n    }\n};\n\npaddle.Argument = class {\n\n    constructor(name, value, type, visible) {\n        this.name = name;\n        this.value = value;\n        if (type) {\n            this.type = type;\n        }\n        if (visible === false) {\n            this.visible = visible;\n        }\n    }\n};\n\npaddle.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new paddle.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = !type && initializer ? initializer.type : type;\n        this.initializer = initializer;\n    }\n};\n\npaddle.Node = class {\n\n    constructor(metadata, op, values) {\n        const type = op.type;\n        this.type = metadata.type(type) || { name: type };\n        this.name = op.name || '';\n        this.description = op.description || '';\n        this.identifier = op.identifier || '';\n        this.attributes = [];\n        this.inputs = [];\n        this.outputs = [];\n        this.chain = [];\n        if (op.attrs) {\n            this.attributes = op.attrs.map((attr) => {\n                const name = attr.name;\n                const meta = metadata.attribute(this.type.name, name);\n                let value = '?';\n                let visible = true;\n                let type = null;\n                switch (attr.type) {\n                    case paddle.AttributeType.STRING:\n                        type = 'string';\n                        value = attr.s;\n                        break;\n                    case paddle.AttributeType.STRINGS:\n                        type = 'string[]';\n                        value = Array.from(attr.strings);\n                        break;\n                    case paddle.AttributeType.BOOLEAN:\n                        type = 'boolean';\n                        value = attr.b;\n                        break;\n                    case paddle.AttributeType.BOOLEANS:\n                        type = 'boolean[]';\n                        value = attr.bools ? Array.from(attr.bools) : attr.bools;\n                        break;\n                    case paddle.AttributeType.FLOAT:\n                        type = 'float32';\n                        value = attr.f;\n                        break;\n                    case paddle.AttributeType.FLOATS:\n                        type = 'float32[]';\n                        value = attr.floats ? Array.from(attr.floats) : attr.floats;\n                        break;\n                    case paddle.AttributeType.FLOAT64:\n                        type = 'float64';\n                        value = attr.float64;\n                        break;\n                    case paddle.AttributeType.FLOAT64S:\n                        type = 'float64[]';\n                        value = attr.float64s ? Array.from(attr.float64s) : attr.float64s;\n                        break;\n                    case paddle.AttributeType.INT:\n                        type = 'int32';\n                        value = attr.i;\n                        break;\n                    case paddle.AttributeType.INTS:\n                        type = 'int32[]';\n                        value = attr.ints ? Array.from(attr.ints) : attr.ints;\n                        break;\n                    case paddle.AttributeType.LONG:\n                        type = 'int64';\n                        break;\n                    case paddle.AttributeType.LONGS:\n                        type = 'int64[]';\n                        break;\n                    case 1000: // ir\n                        type = attr.irType;\n                        value = attr.irValue;\n                        break;\n                    case 1001: // graph\n                        type = 'graph';\n                        value = new paddle.Graph(metadata, attr.block, attr.vars);\n                        break;\n                    default:\n                        break;\n                }\n                switch (name) {\n                    case 'use_mkldnn':\n                    case 'use_cudnn':\n                    case 'op_callstack':\n                    case 'op_role':\n                    case 'op_role_var':\n                    case 'op_namescope':\n                    case 'is_test':\n                        visible = false;\n                        break;\n                    default:\n                        break;\n                }\n                if (meta) {\n                    if (meta.default !== undefined) {\n                        const defaultValue = meta.default;\n                        if (defaultValue === value) {\n                            visible = false;\n                        } else if (Array.isArray(value) && Array.isArray(defaultValue) && value.length === defaultValue.length) {\n                            if (value.every((item, index) => item === defaultValue[index])) {\n                                visible = false;\n                            }\n                        }\n                    }\n                }\n                return new paddle.Argument(name, value, type, visible);\n            });\n        }\n        if (op.inputs) {\n            for (const input of op.inputs) {\n                if (input.arguments.length > 0) {\n                    this.inputs.push(new paddle.Argument(input.parameter, input.arguments.map((name) => values.get(name))));\n                }\n            }\n        }\n        if (op.outputs) {\n            for (const output of op.outputs) {\n                if (output.arguments.length > 0) {\n                    this.outputs.push(new paddle.Argument(output.parameter, output.arguments.map((name) => values.get(name))));\n                }\n            }\n        }\n        const updates = [\n            [this.inputs, 'X'],\n            [this.inputs, 'Input'],\n            [this.outputs, 'Y'],\n            [this.outputs, 'Out']\n        ];\n        for (const [list, name] of updates) {\n            let item = null;\n            for (let i = 0; i < list.length; i++) {\n                if (list[i].name === name) {\n                    item = list[i];\n                    list.splice(i, 1);\n                    break;\n                }\n            }\n            if (item) {\n                list.splice(0, 0, item);\n            }\n        }\n    }\n};\n\npaddle.Tensor = class {\n\n    constructor(type, data, category = '') {\n        this.type = type;\n        this.values = data;\n        this.category = category;\n    }\n};\n\npaddle.TensorType = class {\n\n    constructor(dataType, shape, layout, denotation) {\n        this.dataType = dataType;\n        this.shape = shape;\n        this.layout = layout;\n        this.denotation = denotation;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\npaddle.TensorShape = class {\n\n    constructor(dimensions) {\n        dimensions = dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim);\n        this.dimensions = dimensions.map((dimension) => {\n            return dimension === -1 ? '?' : dimension;\n        });\n    }\n\n    toString() {\n        return (this.dimensions && this.dimensions.length) ? (`[${this.dimensions.join(',')}]`) : '';\n    }\n};\n\npaddle.Entries = class {\n\n    static async open(context) {\n        let entries = await context.peek('zip');\n        if (entries instanceof Map === false) {\n            entries = await context.peek('tar');\n        }\n        if (entries instanceof Map) {\n            entries = Array.from(entries);\n            entries = new Map(entries.filter(([name]) => !name.endsWith('/') && !name.split('/').pop().startsWith('.')).slice());\n            if (entries.size > 2 && Array.from(entries).every(([name, value]) => name.split('_').length > 0 && value.peek(16).every((value) => value === 0x00))) {\n                return new paddle.Entries(entries);\n            }\n        }\n        return null;\n    }\n\n    constructor(data) {\n        this.name = 'paddle.entries';\n        this.format = 'PaddlePaddle Weights';\n        this.data = data;\n    }\n\n    read() {\n        if (this.data) {\n            let rootFolder = null;\n            for (const [name] of this.data) {\n                if (!name.startsWith('.') || name.startsWith('./')) {\n                    const parts = name.split('/');\n                    let folder = '';\n                    if (parts.length > 2 && parts[0] === '.') {\n                        folder = `./${parts[1]}/`;\n                    } else if (parts.length > 1) {\n                        folder = `${parts[0]}/`;\n                    }\n                    if (rootFolder !== null && rootFolder !== '' && folder !== rootFolder) {\n                        rootFolder = '';\n                    } else {\n                        rootFolder = folder;\n                    }\n                }\n            }\n            this.weights = new Map();\n            for (const [name, stream] of this.data) {\n                if (name.startsWith(rootFolder)) {\n                    const key = name.substring(rootFolder.length);\n                    const tensor = paddle.Utility.openTensorDesc(stream);\n                    this.weights.set(key, tensor);\n                }\n            }\n            delete this.data;\n        }\n    }\n};\n\npaddle.Pickle = class {\n\n    static async open(context) {\n        const obj = await context.peek('pkl');\n        const container = new paddle.Pickle(obj);\n        if (container.weights !== null) {\n            return container;\n        }\n        return null;\n    }\n\n    constructor(obj) {\n        this.name = 'paddle.pickle';\n        this.format = 'PaddlePaddle Pickle';\n        this._weights = null;\n        if (obj && !Array.isArray(obj) && (obj instanceof Map || Object(obj) === obj)) {\n            const entries = (obj) => {\n                if (obj instanceof Map) {\n                    return Array.from(obj);\n                } else if (Object(obj) === obj) {\n                    return Object.entries(obj);\n                }\n                return [];\n            };\n            const filter = (obj) => {\n                const list = [];\n                if (obj && !Array.isArray(obj)) {\n                    for (const [name, value] of entries(obj)) {\n                        if (name !== 'StructuredToParameterName@@') {\n                            const obj = value && Array.isArray(value) && value.length === 2 && value[0] === name ? value[1] : value;\n                            if (obj && !Array.isArray(obj) && obj.__class__ && obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray') {\n                                list.push([name, obj]);\n                            }\n                        }\n                    }\n                }\n                return list;\n            };\n            const weights = filter(obj);\n            if (weights.length > 0) {\n                this._weights = weights;\n            } else {\n                const list = entries(obj);\n                if (list.filter(([name]) => name !== 'StructuredToParameterName@@').length === 1) {\n                    const weights = filter(list[0][1]);\n                    if (weights.length > 0) {\n                        this._weights = weights;\n                    }\n                }\n                if (this._weights === null && list.filter(([name]) => name === 'StructuredToParameterName@@').length > 0) {\n                    this._weights = [];\n                }\n            }\n        }\n    }\n\n    get weights() {\n        if (this._weights && Array.isArray(this._weights)) {\n            const weights = new Map();\n            for (const [name, value] of this._weights) {\n                const type = new paddle.TensorType(value.dtype.__name__, new paddle.TensorShape(value.shape));\n                const data = value.data;\n                const tensor = new paddle.Tensor(type, data, 'NumPy Array');\n                weights.set(name, tensor);\n            }\n            this._weights = weights;\n        }\n        return this._weights;\n    }\n};\n\npaddle.NaiveBuffer = class {\n\n    static async open(context) {\n        const stream = context.stream;\n        if (stream && stream.length > 4) {\n            const buffer = stream.peek(4);\n            if (buffer[0] > 2 || buffer[1] !== 0x00 || buffer[2] !== 0x76 || buffer[3] !== 0x32) {\n                if (context.identifier === '__model__.nb') {\n                    return new paddle.NaiveBuffer('paddle.naive.model', stream, -1);\n                }\n                if (context.identifier === 'param.nb') {\n                    return new paddle.NaiveBuffer('paddle.naive.param', stream, -1);\n                }\n            }\n            if (buffer[1] === 0x00 && buffer[0] <= 2) {\n                return new paddle.NaiveBuffer('paddle.naive', stream, buffer[0]);\n            }\n        }\n        return null;\n    }\n\n    constructor(name, stream, meta_version) {\n        this.name = name;\n        this.stream = stream;\n        this.meta_version = meta_version;\n    }\n\n    read() {\n        const reader = base.BinaryReader.open(this.stream);\n        if (this.meta_version >= 2) {\n            reader.skip(2);\n        }\n        const decoder = new TextDecoder('utf-8');\n        const opt_version = reader.read(16);\n        const version = decoder.decode(opt_version.slice(0, opt_version.indexOf(0x00)));\n        this.format = `Paddle Lite${version && version.match(/^v\\d+\\.\\d+\\.\\d+$/) ? ` ${version}` : ''}`;\n        const topo_size = reader.uint64().toNumber();\n        const openProgramDesc = (buffer) => {\n            const reader = flatbuffers.BinaryReader.open(buffer);\n            return paddle.schema.ProgramDesc.create(reader);\n        };\n        const openParamDesc = (buffer) => {\n            const reader = flatbuffers.BinaryReader.open(buffer);\n            return paddle.schema.ParamDesc.create(reader);\n        };\n        switch (this.meta_version) {\n            case -1: {\n                throw new paddle.Error('Paddle Lite naive buffer format is deprecated.');\n            }\n            case 0:\n            case 1: {\n                throw new paddle.Error(`Paddle Lite meta format '${this.meta_version}' is deprecated.`);\n            }\n            case 2: {\n                const topo_data = new Uint8Array(topo_size);\n                topo_data.set(reader.read(topo_size), 0);\n                this.model = openProgramDesc(topo_data);\n                reader.uint16(); // version\n                reader.uint16(); // meta_size\n                const header_size = reader.uint16();\n                const params_size = reader.uint16();\n                reader.uint32(); // max_tensor_size\n                reader.skip(header_size - 6);\n                this.weights = new Map();\n                for (let i = 0; i < params_size; i++) {\n                    const total_size = reader.uint32();\n                    const offset = reader.uint32();\n                    const param_bytes = total_size - offset;\n                    const param_data = reader.read(param_bytes);\n                    const desc = openParamDesc(param_data);\n                    const data = desc.variable.data;\n                    const data_type = desc.variable.data_type;\n                    const dim = desc.variable.dim;\n                    const type = paddle.Utility.createTensorType(data_type, dim);\n                    const tensor = new paddle.Tensor(type, data);\n                    this.weights.set(desc.name, tensor);\n                }\n                break;\n            }\n            default: {\n                throw new paddle.Error(`Unsupported Paddle Lite naive buffer meta format '${this.meta_version}'.`);\n            }\n        }\n        delete this.stream;\n    }\n};\n\npaddle.Utility = class {\n\n    static createTensorType(data_type, shape) {\n        if (!paddle.Utility._dataTypes) {\n            const length = Math.max.apply(null, Object.entries(paddle.DataType).map(([, value]) => value));\n            paddle.Utility._dataTypes = new Array(length);\n            const types = new Map([\n                ['bool', 'boolean'],\n                ['bf16', 'bfloat16'], ['fp16', 'float16'], ['fp32', 'float32'], ['fp64', 'float64'],\n                ['fp8_e4m3fn', 'float8e4m3fn'], ['fp8_e5m2', 'float8e5m2']\n            ]);\n            for (const [name, index] of Object.entries(paddle.DataType)) {\n                const key = name.toLowerCase();\n                paddle.Utility._dataTypes[index] = types.has(key) ? types.get(key) : key;\n            }\n        }\n        const dataType = data_type < paddle.Utility._dataTypes.length ? paddle.Utility._dataTypes[data_type] : '?';\n        return new paddle.TensorType(dataType, new paddle.TensorShape(shape));\n    }\n\n    static openTensorDesc(stream) {\n        const signature = stream.read(16);\n        if (!signature.every((value) => value === 0x00)) {\n            throw new paddle.Error('Invalid paddle.TensorDesc signature.');\n        }\n        const length = base.BinaryReader.open(stream.read(4)).uint32();\n        const buffer = stream.read(length);\n        const reader = protobuf.BinaryReader.open(buffer);\n        const tensorDesc = paddle.proto.VarType.TensorDesc.decode(reader);\n        const dims = tensorDesc.dims.map((dim) => dim.toNumber());\n        const size = dims.reduce((a, b) => a * b, 1);\n        let itemsize = 0;\n        switch (tensorDesc.data_type) {\n            case paddle.DataType.BOOL: itemsize = 1; break;\n            case paddle.DataType.FP16: itemsize = 2; break;\n            case paddle.DataType.FP32: itemsize = 4; break;\n            case paddle.DataType.FP64: itemsize = 8; break;\n            case paddle.DataType.INT8: itemsize = 1; break;\n            case paddle.DataType.INT16: itemsize = 2; break;\n            case paddle.DataType.INT32: itemsize = 4; break;\n            case paddle.DataType.INT64: itemsize = 8; break;\n            case paddle.DataType.UINT8: itemsize = 1; break;\n            default: throw new paddle.Error(`Invalid inference params data type '${tensorDesc.data_type}'.`);\n        }\n        const type = paddle.Utility.createTensorType(tensorDesc.data_type, tensorDesc.dims);\n        const data = stream.read(itemsize * size);\n        return new paddle.Tensor(type, data);\n    }\n};\n\npaddle.DataType = {\n    BOOL: 0,\n    INT16: 1,\n    INT32: 2,\n    INT64: 3,\n    FP16: 4,\n    FP32: 5,\n    FP64: 6,\n    DENSE_TENSOR: 7,\n    SELECTED_ROWS: 8,\n    FEED_MINIBATCH: 9,\n    FETCH_LIST: 10,\n    STEP_SCOPES: 11,\n    LOD_RANK_TABLE: 12,\n    DENSE_TENSOR_ARRAY: 13,\n    PLACE_LIST: 14,\n    READER: 15,\n    RAW: 17,\n    TUPLE: 18,\n    SIZE_T: 19,\n    UINT8: 20,\n    INT8: 21,\n    BF16: 22,\n    COMPLEX64: 23,\n    COMPLEX128: 24,\n    STRING: 25,\n    STRINGS: 26,\n    FP8_E4M3FN: 32,\n    FP8_E5M2: 33,\n};\n\npaddle.AttributeType = {\n    INT: 0,\n    FLOAT: 1,\n    STRING: 2,\n    INTS: 3,\n    FLOATS: 4,\n    STRINGS: 5,\n    BOOLEAN: 6,\n    BOOLEANS: 7,\n    BLOCK: 8,\n    LONG: 9,\n    BLOCKS: 10,\n    LONGS: 11,\n    FLOAT64S: 12,\n    VAR: 13,\n    VARS: 14,\n    FLOAT64: 15\n};\n\npaddle.IR = class {\n\n    constructor(obj) {\n        this._names = new Map();\n        this._crossRegionInputs = new Map();\n        this.base_code = obj.base_code;\n        this.version = obj.base_code.version;\n        const program = obj.program;\n        const regions = [];\n        for (const region of program.regions) {\n            regions.push(this.region(region));\n        }\n        const [programRegion] = regions;\n        this.desc = programRegion;\n        this.tensors = new Map();\n    }\n\n    region(value) {\n        const obj = {};\n        obj.kind = 'region';\n        obj.name = value['#'];\n        obj.idx = value['#'];\n        obj.vars = new Map();\n        obj.blocks = [];\n        for (const block of value.blocks) {\n            obj.blocks.push(this.block(block));\n        }\n        const [block] = obj.blocks;\n        obj.block = block;\n        return obj;\n    }\n\n    block(value) {\n        const obj = {};\n        obj.kind = 'block';\n        obj.name = value['#'];\n        obj.idx = value['#'];\n        obj.vars = new Map();\n        obj.argInputs = new Map();\n        if (value.args) {\n            for (const input of value.args) {\n                const [, type] = input.TT && input.TT['#'] ? input.TT['#'].split('.') : null;\n                if (type === 't_dtensor') {\n                    const [parameter, name,] = this.getParaName(input);\n                    const tensorType = this.createTensorType(input);\n                    obj.argInputs.set(name, [parameter, tensorType]);\n                }\n            }\n        }\n        let inputNames = new Set();\n        let outputNames = new Set();\n        obj.ops = [];\n        for (const op of value.ops) {\n            const irOp = this.op(op);\n            obj.ops.push(irOp);\n            inputNames = new Set([...inputNames, ...irOp.inputNames]);\n            outputNames = new Set([...outputNames, ...irOp.outputNames]);\n        }\n        const missInputs = new Set([...inputNames].filter((item) => !outputNames.has(item)));\n        if (missInputs) {\n            for (const name of missInputs) {\n                const output = this.getCrossInput(name);\n                if (output) {\n                    obj.argInputs.set(name, [output.parameter, output.tensorType]);\n                }\n            }\n        }\n        return obj;\n    }\n\n    op(op) {\n        const obj = {};\n        obj.kind = 'op';\n        const opInfo = this.getOpInfo(op);\n        obj.name = opInfo.fullName;\n        obj.type = opInfo.type;\n        obj.identifier = opInfo.rawType;\n        obj.attrs = [];\n        for (const [idx, value] of Object.entries(op.A)) {\n            obj.attrs.push(this.attr(idx, value, opInfo));\n        }\n        if (op.regions !== undefined) {\n            for (const region of op.regions) {\n                const regionAttr = this.region(region);\n                obj.attrs.push(this.attr(null, regionAttr, null));\n            }\n        }\n        const inputNames = new Set();\n        const outputNames = new Set();\n        const createInput = (input, opInfo) => {\n            const [parameterName, inputName] = this.getParaName(input, opInfo.namePrefix);\n            return { arguments: [inputName], parameter: parameterName };\n        };\n        const inputs = [];\n        if (op.I) {\n            const inputArray = Array.isArray(op.I) ? op.I : [op.I];\n            for (const input of inputArray) {\n                inputs.push(createInput(input, opInfo));\n                const [, name] = this.getParaName(input, opInfo.namePrefix);\n                inputNames.add(name);\n            }\n        }\n        const createOutput = (output, opInfo, idx, outputAttr) => {\n            const [parameterName, outputName] = this.getParaName(output, opInfo.namePrefix);\n            const valuesMap = new Map();\n            let tType = null;\n            const [, typeType] = output.TT['#'].split('.');\n            if (typeType === 't_dtensor') {\n                const denotation = this.getOutputAttr(opInfo, idx, outputAttr);\n                const tensorType = this.createTensorType(output, denotation);\n                valuesMap.set(outputName, new paddle.Value(outputName, tensorType, null));\n                tType = tensorType;\n            } else {\n                valuesMap.set(outputName, new paddle.Value(outputName, null, null, null));\n            }\n            return {\n                arguments: [outputName],\n                parameter: parameterName,\n                tensorType: tType,\n                values: valuesMap\n            };\n        };\n        const outputs = [];\n        if (op.O) {\n            const outputArray = Array.isArray(op.O) ? op.O : [op.O];\n            for (const [idx, output] of Object.entries(outputArray)) {\n                const irOutput = createOutput(output, opInfo, idx, op.OA);\n                outputs.push(irOutput);\n                const [, name, isNegative] = this.getParaName(output, opInfo.namePrefix);\n                outputNames.add(name);\n                if (!isNegative && !this.hasCrossInput(name)) {\n                    this.addCrossInput(name, irOutput);\n                }\n            }\n        }\n        if (op.regions) {\n            const collectRegions = (irReader, regions) => {\n                let inputs = new Map();\n                let outputs = new Map();\n                for (const region of regions) {\n                    for (const block of region.blocks) {\n                        for (const op of block.ops) {\n                            const opInfo = this.getOpInfo(op);\n                            if (op.I) {\n                                const opInputs = Array.isArray(op.I) ? op.I : [op.I];\n                                for (const input of opInputs) {\n                                    const [, name, isNegative] = irReader.getParaName(input, opInfo.namePrefix);\n                                    if (!isNegative && !inputs.has(name)) {\n                                        inputs.set(name, [input, opInfo]);\n                                    }\n                                }\n                            }\n                            if (op.O) {\n                                const opOutputs = Array.isArray(op.O) ? op.O : [op.O];\n                                for (const [idx, output] of Object.entries(opOutputs)) {\n                                    const [, name, isNegative] = irReader.getParaName(output, opInfo.namePrefix);\n                                    if (!isNegative && !outputs.has(name)) {\n                                        outputs.set(name, [output, opInfo, idx, op.OA]);\n                                    }\n                                }\n                            }\n                            if (op.regions) {\n                                const [subInputs, subOutputs] = collectRegions(irReader, op.regions);\n                                inputs = new Map([...inputs, ...subInputs]);\n                                outputs = new Map([...outputs, ...subOutputs]);\n                            }\n                        }\n                    }\n                }\n                return [inputs, outputs];\n            };\n            const [subInputs, subOutputs] = collectRegions(this, op.regions);\n            for (const [name, inputArgs] of subInputs) {\n                if (!inputNames.has(name) && !subOutputs.has(name)) {\n                    const [input, opInfo] = inputArgs;\n                    inputs.push(createInput(input, opInfo));\n                    inputNames.add(name);\n                }\n            }\n            for (const [name, outputArgs] of subOutputs) {\n                if (!outputNames.has(name) && !subInputs.has(name)) {\n                    const [output, opInfo, idx, oa] = outputArgs;\n                    outputs.push(createOutput(output, opInfo, idx, oa));\n                    outputNames.add(name);\n                }\n            }\n        }\n        obj.inputs = inputs;\n        obj.outputs = outputs;\n        obj.inputNames = inputNames;\n        obj.outputNames = outputNames;\n        return obj;\n    }\n\n    attr(idx, value, opInfo) {\n        const obj = {};\n        obj.kind = 'attr';\n        if (value.kind === 'region') {\n            obj.name = value.name;\n            obj.type = 1001; // graph\n            obj.block = value.block;\n            obj.vars = value.vars;\n        } else {\n            const [attrName, attrType, attrValue] = this.getAttr(opInfo, idx, value);\n            obj.name = attrName;\n            obj.type = 1000; // ir\n            obj.irType = attrType;\n            obj.irValue = attrValue;\n        }\n        return obj;\n    }\n\n    getParaName(tensor, namePrefix) {\n        let idx = '';\n        if ('%' in tensor) {\n            idx = tensor['%'];\n        } else if ('#' in tensor) {\n            idx = tensor['#'];\n        }\n        if (tensor.TT && !this._names.has(idx)) {\n            const prefix = namePrefix || idx;\n            this._names.set(idx, `${prefix}`);\n        }\n        return [`${idx}`, this._names.has(idx) ? this._names.get(idx) : `${idx}`, Number.isInteger(idx) ? idx < 0 : false];\n    }\n\n    hasCrossInput(name) {\n        return this._crossRegionInputs.has(name);\n    }\n\n    getCrossInput(name) {\n        return this._crossRegionInputs.has(name) ? this._crossRegionInputs.get(name) : null;\n    }\n\n    addCrossInput(name, input) {\n        this._crossRegionInputs.set(name, input);\n    }\n\n    getOpInfo(op) {\n        const obj = {};\n        obj.rawType = op['#'];\n        obj._type = op['#'];\n        obj._name = op['#'];\n        switch (op['#']) {\n            case 'p': {\n                obj.kind = 'p';\n                [obj._name] = op.A.slice(3);\n                obj._type = this.getCompressOp(obj._type);\n                op.OA = [...op.OA, ...op.A];\n                obj.type = obj._type;\n                obj.name = obj._type;\n                obj.fullName = obj._type;\n                obj.namePrefix = obj._name;\n                break;\n            }\n            case '1.data': {\n                obj.kind = 'data';\n                [obj._opKey, obj._opType] = obj._name.split('.');\n                let prefix = '';\n                for (const attr of op.A) {\n                    if (attr.N === 'name') {\n                        prefix = attr.AT.D;\n                        break;\n                    }\n                }\n                obj._attr = op.A;\n                obj.type = obj._opType;\n                obj.name = obj._opType;\n                obj.fullName = `${this.getCompressOp(obj._opKey)}.${obj._opType}`;\n                obj.namePrefix = prefix;\n                break;\n            }\n            default: {\n                obj.kind = '';\n                [obj._opKey, obj._opType] = obj._name.split('.');\n                obj.type = obj._opType;\n                obj.name = obj._opType;\n                obj.fullName = `${this.getCompressOp(obj._opKey)}.${obj._opType}`;\n                obj.namePrefix = null;\n                break;\n            }\n        }\n        return obj;\n    }\n\n    createTensorType(data, denotation) {\n        const [type, dims, layout, ,] = data.TT.D;\n        const [, dataType] = type['#'].split('.');\n        const dtype = this.getType(dataType);\n        const shape = new paddle.TensorShape(dims);\n        return new paddle.TensorType(dtype, shape, layout, denotation);\n    }\n\n    getType(type) {\n        type = type.includes('_') ? type.split('_')[1] : type;\n        switch (type) {\n            case 'bool': return 'boolean';\n            case 'bf16': return 'bfloat16';\n            case 'fp16': return 'float16';\n            case 'fp32': return 'float32';\n            case 'fp64': return 'float64';\n            case 'fp8_e4m3fn': return 'float8e4m3fn';\n            case 'fp8_e5m2': return 'float8e5m2';\n            case 'f8e4m3fn': return 'float8e4m3fn';\n            case 'f8e5m2': return 'float8e5m2';\n            case 'f16': return 'float16';\n            case 'f32': return 'float32';\n            case 'f64': return 'float64';\n            case 'i8': return 'int8';\n            case 'ui8': return 'uint8';\n            case 'i16': return 'int16';\n            case 'i32': return 'int32';\n            case 'i64': return 'int64';\n            case 'c64': return 'complex<float32>';\n            case 'c128': return 'complex<float64>';\n            case 'str': return 'string';\n            default: return type;\n        }\n    }\n\n    getCompressOp(opType) {\n        switch (opType) {\n            case '0': return 'builtin';\n            case '1': return 'pd_op';\n            case '2': return 'cf';\n            case '3': return 'custom_op';\n            case '4': return 'pd_dist';\n            case 'p': return 'parameter';\n            default: return opType;\n        }\n    }\n\n    getAttrDenotation(name, value) {\n        if (value) {\n            if (typeof value === 'boolean') {\n                return `${name}`;\n            }\n            if (name !== 'name' && name !== 'dtype') {\n                return `${name}:${value}`;\n            }\n        }\n        return '';\n    }\n\n    getAttr(opInfo, idx, value) {\n        if (opInfo.kind === 'p') {\n            let attrName = '';\n            let attrType = '';\n            let attrValue = '';\n            switch (idx) {\n                case '0':\n                    attrName = 'is_distributed';\n                    attrType = this.getType('a_bool');\n                    break;\n                case '1':\n                    attrName = 'is_parameter';\n                    attrType = this.getType('a_bool');\n                    break;\n                case '2':\n                    attrName = 'need_clip';\n                    attrType = this.getType('a_bool');\n                    break;\n                case '3':\n                    attrName = 'name';\n                    attrType = this.getType('a_str');\n                    break;\n                default:\n                    break;\n            }\n            attrValue = attrType === this.getType('a_bool') ? value === 1 : value;\n            return [attrName, attrType, attrValue];\n        }\n        const attrName = value.N;\n        let attrType = this.getType(value.AT['#'].split('.')[1]);\n        let attrValue = value.AT.D;\n        if (attrType === this.getType('a_array') && attrValue.length > 0) {\n            const subType = this.getType(attrValue[0]['#'].split('.')[1]);\n            attrType = `${subType}[]`;\n            const valueData = [];\n            for (const attr of attrValue) {\n                valueData.push(attr.D);\n            }\n            attrValue = valueData;\n        }\n        if (attrName === 'place') {\n            const [place, val,] = attrValue;\n            let device = place;\n            switch (device) {\n                case 0: device = 'UNDEFINED'; break;\n                case 1: device = 'CPU'; break;\n                case 2: device = 'GPU'; break;\n                case 3: device = 'GPUPINNED'; break;\n                case 4: device = 'XPU'; break;\n                case 7: device = 'IPU'; break;\n                case 9: device = 'CUSTOM'; break;\n                default: break;\n            }\n            attrValue = `${device}:${val}`;\n        }\n        if (attrName === 'shape') {\n            attrValue = new paddle.TensorShape(attrValue);\n        }\n        return [attrName, attrType, attrValue];\n    }\n\n    getOutputAttr(opInfo, idx, outputAttr) {\n        switch (opInfo.kind) {\n            case 'p': {\n                const denotation = [];\n                if (outputAttr[0] === 1) {\n                    denotation.push('persistable');\n                }\n                if (outputAttr[1] === 1) {\n                    denotation.push('stop_gradient');\n                }\n                if (outputAttr[2] === 1) {\n                    denotation.push('trainable');\n                }\n                if (outputAttr[3] === 1) {\n                    denotation.push('is_distributed');\n                }\n                if (outputAttr[4] === 1) {\n                    denotation.push('is_parameter');\n                }\n                if (outputAttr[5] === 1) {\n                    denotation.push('need_clip');\n                }\n                return denotation.join(';');\n            }\n            case 'data': {\n                const denotation = [];\n                for (const attr of outputAttr) {\n                    const attrName = attr.N;\n                    const attrValue = attr.AT.D[idx].D;\n                    const attrDenotation = this.getAttrDenotation(attrName, attrValue);\n                    if (attrDenotation) {\n                        denotation.push(attrDenotation);\n                    }\n                }\n                for (const value of opInfo._attr) {\n                    const [attrName, , attrValue] = this.getAttr(opInfo, null, value);\n                    const attrDenotation = this.getAttrDenotation(attrName, attrValue);\n                    if (attrDenotation) {\n                        denotation.push(attrDenotation);\n                    }\n                }\n                return denotation.join(';');\n            }\n            default: {\n                const denotation = [];\n                for (const attr of outputAttr) {\n                    const attrName = attr.N;\n                    const attrValue = attr.AT.D[idx].D;\n                    const attrDenotation = this.getAttrDenotation(attrName, attrValue);\n                    if (attrDenotation) {\n                        denotation.push(attrDenotation);\n                    }\n                }\n                return denotation.join(';');\n            }\n        }\n    }\n};\n\npaddle.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading PaddlePaddle model.';\n    }\n};\n\nexport const ModelFactory = paddle.ModelFactory;"
  },
  {
    "path": "source/pickle.js",
    "content": "\n// Experimental\n\nconst pickle = {};\n\npickle.ModelFactory = class {\n\n    async match(context) {\n        const stream = context.stream;\n        const signature = [0x80, undefined, 0x8a, 0x0a, 0x6c, 0xfc, 0x9c, 0x46, 0xf9, 0x20, 0x6a, 0xa8, 0x50, 0x19];\n        if (stream && signature.length <= stream.length && stream.peek(signature.length).every((value, index) => signature[index] === undefined || signature[index] === value)) {\n            // Reject PyTorch models with .pkl file extension.\n            return null;\n        }\n        const obj = await context.peek('pkl');\n        if (obj !== undefined) {\n            const name = obj && obj.__class__ && obj.__class__.__module__ && obj.__class__.__name__ ? `${obj.__class__.__module__}.${obj.__class__.__name__}` : '';\n            if (!name.startsWith('__torch__.') &&\n                !name.startsWith('catboost.') &&\n                !name.startsWith('autogluon.tabular.models.catboost.')) {\n                return context.set('pickle', obj);\n            }\n        }\n        return null;\n    }\n\n    async open(context) {\n        let format = 'Pickle';\n        const obj = context.value;\n        if (obj === null || obj === undefined) {\n            context.error(new pickle.Error(\"Unsupported Pickle null object.\"));\n        } else if (obj instanceof Error) {\n            throw obj;\n        } else if (!Array.isArray(obj) && obj && obj.__class__) {\n            const formats = new Map([\n                ['cuml.ensemble.randomforestclassifier.RandomForestClassifier', 'cuML'],\n                ['shap.explainers._linear.LinearExplainer', 'SHAP'],\n                ['gensim.models.word2vec.Word2Vec', 'Gensim'],\n                ['ray.rllib.algorithms.ppo.ppo.PPOConfig', 'Ray RLlib'],\n                ['builtins.bytearray', 'Pickle'],\n                ['builtins.dict', 'Pickle'],\n                ['collections.OrderedDict', 'Pickle'],\n                ['numpy.ndarray', 'NumPy NDArray'],\n            ]);\n            const type = `${obj.__class__.__module__}.${obj.__class__.__name__}`;\n            if (formats.has(type)) {\n                format = formats.get(type);\n            } else {\n                context.error(new pickle.Error(`Unsupported Pickle type '${type}'.`));\n            }\n        }\n        return new pickle.Model(obj, format);\n    }\n};\n\npickle.Model = class {\n\n    constructor(value, format) {\n        this.format = format;\n        this.modules = [new pickle.Module(null, value)];\n    }\n};\n\npickle.Module = class {\n\n    constructor(type = '', obj = null) {\n        this.type = type;\n        this.inputs = [];\n        this.outputs = [];\n        this.nodes = [];\n        const weights = this.type === 'weights' ? obj : pickle.Utility.weights(obj);\n        if (weights) {\n            for (const [name, module] of weights) {\n                const node = new pickle.Node(module, name, 'Weights');\n                this.nodes.push(node);\n            }\n        } else if (pickle.Utility.isTensor(obj)) {\n            const type = `${obj.__class__.__module__}.${obj.__class__.__name__}`;\n            const node = new pickle.Node({ value: obj }, null, type);\n            this.nodes.push(node);\n        } else if (Array.isArray(obj) && (obj.every((item) => item.__class__) || (obj.every((item) => Array.isArray(item))))) {\n            for (const item of obj) {\n                this.nodes.push(new pickle.Node(item));\n            }\n        } else if (obj && obj.__class__) {\n            this.nodes.push(new pickle.Node(obj));\n        } else if (obj && Object(obj) === obj) {\n            this.nodes.push(new pickle.Node(obj));\n        }\n    }\n};\n\npickle.Node = class {\n\n    constructor(obj, name, type, stack) {\n        if (typeof type !== 'string') {\n            type = obj.__class__ ? `${obj.__class__.__module__}.${obj.__class__.__name__}` : 'builtins.object';\n        }\n        this.type = { name: type };\n        this.name = name || '';\n        this.inputs = [];\n        if (type === 'builtins.bytearray') {\n            const argument = new pickle.Argument('value', Array.from(obj), 'byte[]');\n            this.inputs.push(argument);\n            return;\n        }\n        const weights = pickle.Utility.weights(obj);\n        if (weights) {\n            const type = this.type.name;\n            this.type = new pickle.Module('weights', weights);\n            this.type.name = type;\n            return;\n        }\n        const entries = obj instanceof Map ? Array.from(obj) : Object.entries(obj);\n        for (const [name, value] of entries) {\n            if (name === '__class__') {\n                continue;\n            } else if (value && pickle.Utility.isTensor(value)) {\n                const identifier = value.__name__ || '';\n                const tensor = new pickle.Tensor(value);\n                const values = [new pickle.Value(identifier, null, tensor)];\n                const argument = new pickle.Argument(name, values);\n                this.inputs.push(argument);\n            } else if (Array.isArray(value) && value.length > 0 && value.every((obj) => pickle.Utility.isTensor(obj))) {\n                const values = value.map((obj) => new pickle.Value(obj.__name__ || '', null, new pickle.Tensor(obj)));\n                const argument = new pickle.Argument(name, values);\n                this.inputs.push(argument);\n            } else if (value && value.__class__ && value.__class__.__module__ === 'builtins' && (value.__class__.__name__ === 'function' || value.__class__.__name__ === 'type')) {\n                const obj = {};\n                obj.__class__ = value;\n                const node = new pickle.Node(obj, null, null, stack);\n                const argument = new pickle.Argument(name, node, 'object');\n                this.inputs.push(argument);\n            } else if (pickle.Utility.isByteArray(value)) {\n                const argument = new pickle.Argument(name, Array.from(value), 'byte[]');\n                this.inputs.push(argument);\n            } else {\n                stack = stack || new Set();\n                if (value && Array.isArray(value) && value.every((obj) => typeof obj === 'string')) {\n                    const argument = new pickle.Argument(name, value, 'string[]');\n                    this.inputs.push(argument);\n                } else if (value && Array.isArray(value) && value.every((obj) => typeof obj === 'number')) {\n                    const argument = new pickle.Argument(name, value, 'attribute');\n                    this.inputs.push(argument);\n                } else if (value && Array.isArray(value) && value.length > 0 && value.every((obj) => obj && (obj.__class__ || obj === Object(obj)))) {\n                    const chain = stack;\n                    const values = value.filter((value) => !chain.has(value));\n                    const nodes = values.map((value) => {\n                        chain.add(value);\n                        const node = new pickle.Node(value, null, null, chain);\n                        chain.delete(value);\n                        return node;\n                    });\n                    const argument = new pickle.Argument(name, nodes, 'object[]');\n                    this.inputs.push(argument);\n                } else if (value && (value.__class__ || pickle.Utility.isObject(value)) && !stack.has(value)) {\n                    stack.add(value);\n                    const node = new pickle.Node(value, null, null, stack);\n                    const visible = name !== '_metadata' || !pickle.Utility.isMetadataObject(value);\n                    const argument = new pickle.Argument(name, node, 'object', visible);\n                    this.inputs.push(argument);\n                    stack.delete(value);\n                } else {\n                    const argument = new pickle.Argument(name, value, 'attribute');\n                    this.inputs.push(argument);\n                }\n            }\n        }\n    }\n};\n\npickle.Argument = class {\n\n    constructor(name, value, type = null, visible = true) {\n        this.name = name.toString();\n        this.value = value;\n        this.type = type;\n        this.visible = visible;\n    }\n};\n\npickle.Value = class {\n\n    constructor(name, type, initializer = null) {\n        if (typeof name !== 'string') {\n            throw new pickle.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);\n        }\n        this.name = name;\n        this.type = initializer && initializer.type ? initializer.type : type || null;\n        this.initializer = initializer;\n    }\n};\n\npickle.Tensor = class {\n\n    constructor(obj) {\n        if (obj.__class__ && (obj.__class__.__module__ === 'torch' || obj.__class__.__module__ === 'torch.nn.parameter')) {\n            // PyTorch tensor\n            const tensor = obj.__class__.__module__ === 'torch.nn.parameter' && obj.__class__.__name__ === 'Parameter' ? obj.data : obj;\n            const layout = tensor.layout ? tensor.layout.__str__() : null;\n            const storage = tensor.storage();\n            const size = tensor.size() || [];\n            if (!layout || layout === 'torch.strided') {\n                this.type = new pickle.TensorType(storage.dtype.__reduce__(), new pickle.TensorShape(size));\n                this.values = storage.data;\n                this.encoding = '<';\n                this.indices = null;\n                this.stride = tensor.stride();\n                const stride = this.stride;\n                const offset = tensor.storage_offset();\n                let length = 0;\n                if (!Array.isArray(stride)) {\n                    length = storage.size();\n                } else if (size.every((v) => v !== 0)) {\n                    length = size.reduce((a, v, i) => a + stride[i] * (v - 1), 1);\n                }\n                if (this.values !== undefined) {\n                    if (offset !== 0 || length !== storage.size()) {\n                        const itemsize = storage.dtype.itemsize();\n                        const stream = this.values;\n                        const position = stream.position;\n                        stream.seek(itemsize * offset);\n                        this.values = stream.peek(itemsize * length);\n                        stream.seek(position);\n                    } else if (this.values) {\n                        this.values = this.values.peek();\n                    }\n                }\n            } else {\n                throw new pickle.Error(`Unsupported tensor layout '${layout}'.`);\n            }\n        } else {\n            // NumPy array\n            const array = obj;\n            this.type = new pickle.TensorType(array.dtype.__name__, new pickle.TensorShape(array.shape));\n            this.stride = Array.isArray(array.strides) ? array.strides.map((stride) => stride / array.itemsize) : null;\n            this.encoding = this.type.dataType === 'string' || this.type.dataType === 'object' || this.type.dataType === 'datetime' ? '|' : array.dtype.byteorder;\n            this.values = this.type.dataType === 'string' || this.type.dataType === 'object' || this.type.dataType === 'datetime' || this.type.dataType === 'void' ? array.flatten().tolist() : array.tobytes();\n        }\n    }\n};\n\npickle.TensorType = class {\n\n    constructor(dataType, shape) {\n        this.dataType = dataType;\n        this.shape = shape;\n    }\n\n    toString() {\n        return this.dataType + this.shape.toString();\n    }\n};\n\npickle.TensorShape = class {\n\n    constructor(dimensions) {\n        this.dimensions = dimensions;\n    }\n\n    toString() {\n        return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`) : '';\n    }\n};\n\npickle.Utility = class {\n\n    static isSubclass(value, name) {\n        if (value && value.__module__ && value.__name__) {\n            return name === `${value.__module__}.${value.__name__}`;\n        } else if (value && value.__bases__) {\n            return value.__bases__.some((obj) => pickle.Utility.isSubclass(obj, name));\n        }\n        return false;\n    }\n\n    static isInstance(value, name) {\n        return value && value.__class__ ? pickle.Utility.isSubclass(value.__class__, name) : false;\n    }\n\n    static isMetadataObject(obj) {\n        if (pickle.Utility.isInstance(obj, 'collections.OrderedDict')) {\n            for (const value of obj.values()) {\n                if (pickle.Utility.isInstance(value, 'builtins.dict')) {\n                    const entries = Array.from(value);\n                    if (entries.length !== 1 && entries[0] !== 'version' && entries[1] !== 1) {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n        return false;\n    }\n\n    static isByteArray(obj) {\n        return obj && obj.__class__ && obj.__class__.__module__ === 'builtins' && obj.__class__.__name__ === 'bytearray';\n    }\n\n    static isObject(obj) {\n        if (obj && typeof obj === 'object') {\n            const proto = Object.getPrototypeOf(obj);\n            return proto === Object.prototype || proto === null;\n        }\n        return false;\n    }\n\n    static isTensor(obj) {\n        return obj && obj.__class__ && obj.__class__.__name__ &&\n            ((obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray') ||\n             (obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'matrix') ||\n             (obj.__class__.__module__ === 'jax' && obj.__class__.__name__ === 'Array') ||\n             (obj.__class__.__module__ === 'torch.nn.parameter' && obj.__class__.__name__ === 'Parameter') ||\n             (obj.__class__.__module__ === 'torch' && obj.__class__.__name__.endsWith('Tensor')));\n    }\n\n    static weights(obj) {\n        const type = obj && obj.__class__ && obj.__class__.__module__ && obj.__class__.__name__ ? `${obj.__class__.__module__}.${obj.__class__.__name__}` : null;\n        if (type && type !== 'builtins.dict' && type !== 'builtins.object' && type !== 'collections.OrderedDict' && type !== 'torch.nn.modules.module.Module') {\n            return null;\n        }\n        if (pickle.Utility.isTensor(obj)) {\n            return null;\n        }\n        if (obj instanceof Map === false && obj && !Array.isArray(obj) && Object(obj) === obj) {\n            const entries = Object.entries(obj);\n            const named = entries.filter(([name, value]) => (typeof name === 'string' && (name.indexOf('.') !== -1 || name.indexOf('|') !== -1)) && pickle.Utility.isTensor(value));\n            if (named.length > 0 && (named.length / entries.length) >= 0.8) {\n                obj = new Map(entries);\n            }\n        }\n        if (obj instanceof Map) {\n            const entries = Array.from(obj).filter(([name]) => name !== '_metadata');\n            let dot = 0;\n            let pipe = 0;\n            let underscore = 0;\n            let count = 0;\n            let valid = true;\n            for (const [name, value] of entries) {\n                if (typeof name === 'string') {\n                    count++;\n                    dot += name.indexOf('.') !== -1;\n                    pipe += name.indexOf('|') !== -1;\n                    underscore += name.endsWith('_w') || name.endsWith('_b') || name.endsWith('_bn_s');\n                }\n                if (pickle.Utility.isInstance(value, 'builtins.dict') && !Array.from(value.values()).every((value) => !pickle.Utility.isTensor(value))) {\n                    valid = false;\n                }\n            }\n            if (valid && count > 1 && (dot >= count || pipe >= count || underscore >= count) && (count / entries.length) >= 0.8) {\n                let separator = null;\n                if (dot >= pipe && dot >= underscore) {\n                    separator = '.';\n                } else if (pipe >= underscore) {\n                    separator = '|';\n                } else {\n                    separator = '_';\n                }\n                const modules = new Map();\n                for (const [name, value] of entries) {\n                    let c = separator;\n                    if (!c) {\n                        c = name.indexOf('.') === -1 && name.indexOf('|') !== -1 ? '|' : '.';\n                    }\n                    const path = name.split(c);\n                    let property = path.pop();\n                    if (path.length > 1 && path[path.length - 1] === '_packed_params') {\n                        property = `${path.pop()}.${property}`;\n                    }\n                    const key = path.join(separator);\n                    if (!modules.has(key)) {\n                        modules.set(key, {});\n                    }\n                    const module = modules.get(key);\n                    if (pickle.Utility.isTensor(value)) {\n                        value.__name__ = name;\n                    }\n                    module[property] = value;\n                }\n                return modules;\n            }\n        }\n        if (obj && !Array.isArray(obj) && Object(obj) === obj) {\n            const modules = new Map();\n            const entries = obj instanceof Map ? Array.from(obj) : Object.entries(obj);\n            if (entries.length > 0 && entries) {\n                for (const [key, value] of entries) {\n                    const name = key.toString();\n                    if (!value || Object(value) !== value || pickle.Utility.isTensor(value) || ArrayBuffer.isView(value)) {\n                        return null;\n                    }\n                    if (!modules.has(name)) {\n                        modules.set(name, {});\n                    }\n                    const module = modules.get(name);\n                    let tensor = false;\n                    const entries = value instanceof Map ? value : new Map(Object.entries(value));\n                    for (const [name, value] of entries) {\n                        if (typeof name !== 'string') {\n                            return null;\n                        }\n                        if (name.indexOf('.') !== -1) {\n                            return null;\n                        }\n                        if (name === '_metadata') {\n                            continue;\n                        }\n                        if (typeof value === 'string' || typeof value === 'number') {\n                            module[name] = value;\n                            continue;\n                        }\n                        if (pickle.Utility.isTensor(value)) {\n                            value.__name__ = name;\n                            module[name] = value;\n                            tensor = true;\n                        }\n                    }\n                    if (!tensor) {\n                        return null;\n                    }\n                }\n                return modules;\n            }\n        }\n        return null;\n    }\n};\n\npickle.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Error loading Pickle model.';\n    }\n};\n\nexport const ModelFactory = pickle.ModelFactory;\n"
  },
  {
    "path": "source/python.js",
    "content": "\n// Experimental Python Execution\n\nconst python = {};\n\npython.Execution = class {\n\n    constructor(sources) {\n        /* eslint-disable consistent-this */\n        const self = this;\n        /* eslint-enable consistent-this */\n        const execution = self;\n        this._sources = sources || new Map();\n        this._events = new Map();\n        this._utf8Decoder = new TextDecoder('utf-8');\n        this._unresolved = new Map();\n        this._operators = new Map();\n        const dict = class extends Map {\n            constructor(items) {\n                super();\n                if (items) {\n                    if (items instanceof Map) {\n                        items = Array.from(items);\n                    } else if (!Array.isArray(items)) {\n                        items = Object.entries(items);\n                    }\n                    for (const [name, value] of items) {\n                        this.__setitem__(name, value);\n                    }\n                }\n            }\n            __contains__(key) {\n                return this.has(key);\n            }\n            __setitem__(key, value) {\n                this.set(key, value);\n            }\n            __getitem__(key) {\n                return this.get(key);\n            }\n            __delitem__(key) {\n                this.delete(key);\n            }\n            get(key, defaultValue) {\n                return super.has(key) ? super.get(key) : defaultValue;\n            }\n            setdefault(key, defaultValue) {\n                if (this.has(key)) {\n                    return this.get(key);\n                }\n                const value = defaultValue || null;\n                this.set(key, value);\n                return value;\n            }\n            pop(key) {\n                if (this.__contains__(key)) {\n                    const v = this.__getitem__(key);\n                    this.__delitem__(key);\n                    return v;\n                }\n                return null;\n            }\n            items() {\n                return Array.from(this);\n            }\n            update(other) {\n                for (const [key, value] of other) {\n                    this.set(key, value);\n                }\n            }\n        };\n        this._modules = new dict();\n        this._registry = new Map();\n        const module = class {\n            constructor(name) {\n                this.__name__ = name;\n            }\n        };\n        const builtins = this.register('builtins', new module('builtins'));\n        this.builtins = builtins;\n        this._registry.set('__builtin__', builtins);\n        this.registerType('builtins.type', class {\n            constructor(...args) {\n                if (args.length === 1) {\n                    const [obj] = args;\n                    if (obj === null) {\n                        // eslint-disable-next-line no-constructor-return\n                        return builtins.NoneType;\n                    }\n                    if (obj && obj.__class__) {\n                        // eslint-disable-next-line no-constructor-return\n                        return obj.__class__;\n                    }\n                    throw new python.Error(`Unknown type '${obj}'`);\n                }\n                if (args.length === 3) {\n                    const [name, bases, body] = args;\n                    const cls = bases.length > 0 ? class extends bases[0] {} : class {};\n                    execution.registerType(name, cls);\n                    for (const [key, value] of body) {\n                        cls[key] = value;\n                    }\n                    // eslint-disable-next-line no-constructor-return\n                    return cls;\n                }\n                throw new python.Error(`Invalid 'builtins.dict' argument count.`);\n            }\n        }).__class__ = builtins.type;\n        this.registerType('builtins.module', module);\n        this.registerType('builtins.method', class {});\n        this.registerType('builtins.function', class {\n            constructor(code, globals, name) {\n                this.__code__ = code;\n                this.__globals__ = globals;\n                this.__name__ = name;\n            }\n        });\n        this.registerType('builtins.classmethod', class {});\n        this.registerType('builtins.code', class {});\n        this.import('builtins');\n        this.registerType('builtins.builtin_function_or_method', class {});\n        const typing = this.register('typing');\n        this.typing = typing;\n        const operator = this.register('operator');\n        this.register('_codecs');\n        this.register('argparse');\n        this.enum = this.register('enum');\n        const collections = this.register('collections');\n        const copy = this.register('copy');\n        this.register('copy_reg');\n        const ast = this.register('ast');\n        this.ast = ast;\n        this.register('cuml');\n        const cloudpickle = this.register('cloudpickle');\n        const datetime = this.register('datetime');\n        this.register('gensim');\n        const io = this.register('io');\n        const joblib = this.register('joblib');\n        const jax = this.register('jax');\n        this.register('jax.numpy');\n        this.register('jax._src.array');\n        this.register('jax._src.device_array');\n        const functools = this.register('functools');\n        const keras = this.register('keras');\n        const catboost = this.register('catboost');\n        this.register('lightgbm');\n        this.register('nolearn');\n        const fastcore = this.register('fastcore');\n        const fastai = this.register('fastai');\n        const math = this.register('math');\n        math.inf = Infinity;\n        const numpy = this.register('numpy');\n        this.register('numpy.core.multiarray');\n        this.register('numpy.core._multiarray_umath');\n        this.register('numpy.matrixlib.defmatrix');\n        const pandas = this.register('pandas');\n        this.register('pandas.indexes.base');\n        this.register('pandas.indexes.range');\n        this.register('pandas._libs.tslib');\n        this.register('pandas._libs.internals');\n        const pickle = this.register('pickle');\n        const shap = this.register('shap');\n        this.register('shap.explainers.linear');\n        const sklearn = this.register('sklearn');\n        this.register('sklearn.externals.joblib.numpy_pickle');\n        const torch = this.register('torch');\n        this.torch = torch;\n        const torchvision = this.register('torchvision');\n        const torchao = this.register('torchao');\n        const sympy = this.register('sympy');\n        this.register('torch.storage');\n        this.register('torch.nn.parameter');\n        this.register('torch.ops');\n        this.register('torch._ops');\n        this.register('torch.ops.higher_order');\n        this.register('torch.ops.torchvision');\n        this.register('torch.ops.torchaudio');\n        this.register('torch.ops._caffe2');\n        this.register('torchvision');\n        this.register('ultralytics');\n        this.register('__torch__');\n        const sys = this.register('sys');\n        sys.modules = this._modules;\n        this.register('xgboost');\n        this.registerType('ast.AST', class {});\n        this.registerType('ast.mod', class extends ast.AST {});\n        this.registerType('ast.expr', class extends ast.AST {});\n        this.registerType('ast.unaryop', class extends ast.AST {});\n        this.registerType('ast.binop', class extends ast.AST {});\n        this.registerType('ast.operator', class extends ast.AST {});\n        this.registerType('ast.boolop', class extends ast.AST {});\n        this.registerType('ast.cmpop', class extends ast.AST {});\n        this.registerType('ast.stmt', class extends ast.AST {});\n        this.registerType('ast.excepthandler', class extends ast.AST {});\n        this.registerType('ast.keyword', class extends ast.AST {\n            constructor(arg, value) {\n                super();\n                this.arg = arg;\n                this.value = value;\n            }\n        });\n        this.registerType('ast.alias', class extends ast.AST {\n            constructor(name, asname) {\n                super();\n                this.name = name;\n                this.asname = asname;\n            }\n        });\n        this.registerType('ast.Name', class extends ast.expr {\n            constructor(id, ctx) {\n                super();\n                this.id = id;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.Constant', class extends ast.expr {\n            constructor(value, type) {\n                super();\n                this.value = value;\n                this.type = type || null;\n            }\n        });\n        this.registerType('ast.Ellipsis', class extends ast.Constant {\n            constructor() {\n                super(builtins.ellipsis);\n            }\n        });\n        this.registerType('ast.Starred', class extends ast.expr {\n            constructor(value, ctx) {\n                super();\n                this.value = value;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.List', class extends ast.expr {\n            constructor(elts, ctx) {\n                super();\n                this.elts = elts;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.Set', class extends ast.expr {\n            constructor(elts) {\n                super();\n                this.elts = elts;\n            }\n        });\n        this.registerType('ast.Tuple', class extends ast.expr {\n            constructor(elts, ctx) {\n                super();\n                this.elts = elts;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.Dict', class extends ast.expr {\n            constructor(keys, values) {\n                super();\n                this.keys = keys;\n                this.values = values;\n            }\n        });\n        this.registerType('ast.ListComp', class extends ast.expr {\n            constructor(elt, generators) {\n                super();\n                this.elt = elt;\n                this.generators = generators;\n            }\n        });\n        this.registerType('ast.SetComp', class extends ast.expr {\n            constructor(elt, generators) {\n                super();\n                this.elt = elt;\n                this.generators = generators;\n            }\n        });\n        this.registerType('ast.GeneratorExp', class extends ast.expr {\n            constructor(elt, generators) {\n                super();\n                this.elt = elt;\n                this.generators = generators;\n            }\n        });\n        this.registerType('ast.DictComp', class extends ast.expr {\n            constructor(key, value, generators) {\n                super();\n                this.key = key;\n                this.value = value;\n                this.generators = generators;\n            }\n        });\n        this.registerType('ast.comprehension', class extends ast.AST {\n            constructor(target, iter, ifs, is_async) {\n                super();\n                this.target = target;\n                this.iter = iter;\n                this.ifs = ifs;\n                this.is_async = is_async;\n            }\n        });\n        this.registerType('ast.Subscript', class extends ast.expr {\n            constructor(value, slice, ctx) {\n                super();\n                this.value = value;\n                this.slice = slice;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.Slice', class extends ast.expr {\n            constructor(lower, upper, step) {\n                super();\n                this.lower = lower;\n                this.upper = upper;\n                this.step = step;\n            }\n        });\n        this.registerType('ast.UnaryOp', class extends ast.expr {\n            constructor(op, operand) {\n                super();\n                this.op = op;\n                this.operand = operand;\n            }\n        });\n        this.registerType('ast.UAdd', class extends ast.unaryop {});\n        this.registerType('ast.USub', class extends ast.unaryop {});\n        this.registerType('ast.Not', class extends ast.unaryop {});\n        this.registerType('ast.Invert', class extends ast.unaryop {});\n        this.registerType('ast.BinOp', class extends ast.expr {\n            constructor(left, op, right) {\n                super();\n                this.left = left;\n                this.op = op;\n                this.right = right;\n            }\n        });\n        this.registerType('ast.Add', class extends ast.operator {});\n        this.registerType('ast.Sub', class extends ast.operator {});\n        this.registerType('ast.Mult', class extends ast.operator {});\n        this.registerType('ast.Div', class extends ast.operator {});\n        this.registerType('ast.FloorDiv', class extends ast.operator {});\n        this.registerType('ast.Mod', class extends ast.operator {});\n        this.registerType('ast.Pow', class extends ast.operator {});\n        this.registerType('ast.LShift', class extends ast.operator {});\n        this.registerType('ast.RShift', class extends ast.operator {});\n        this.registerType('ast.BitOr', class extends ast.operator {});\n        this.registerType('ast.BitXor', class extends ast.operator {});\n        this.registerType('ast.BitAnd', class extends ast.operator {});\n        this.registerType('ast.MatMult', class extends ast.operator {});\n        this.registerType('ast.BoolOp', class extends ast.expr {\n            constructor(op, values) {\n                super();\n                this.op = op;\n                this.values = values;\n            }\n        });\n        this.registerType('ast.And', class extends ast.boolop {});\n        this.registerType('ast.Or', class extends ast.boolop {});\n        this.registerType('ast.Compare', class extends ast.expr {\n            constructor(left, ops, comparators) {\n                super();\n                this.left = left;\n                this.ops = ops;\n                this.comparators = comparators;\n            }\n        });\n        this.registerType('ast.Eq', class extends ast.cmpop {});\n        this.registerType('ast.NotEq', class extends ast.cmpop {});\n        this.registerType('ast.Lt', class extends ast.cmpop {});\n        this.registerType('ast.LtE', class extends ast.cmpop {});\n        this.registerType('ast.Gt', class extends ast.cmpop {});\n        this.registerType('ast.GtE', class extends ast.cmpop {});\n        this.registerType('ast.Is', class extends ast.cmpop {});\n        this.registerType('ast.IsNot', class extends ast.cmpop {});\n        this.registerType('ast.In', class extends ast.cmpop {});\n        this.registerType('ast.NotIn', class extends ast.cmpop {});\n        this.registerType('ast.Call', class extends ast.expr {\n            constructor(func, args, keywords) {\n                super();\n                this.func = func;\n                this.args = args;\n                this.keywords = keywords || [];\n            }\n        });\n        this.registerType('ast.Attribute', class extends ast.expr {\n            constructor(value, attr, ctx) {\n                super();\n                this.value = value;\n                this.attr = attr;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.Lambda', class extends ast.expr {\n            constructor(args, body) {\n                super();\n                this.args = args;\n                this.body = body;\n            }\n        });\n        this.registerType('ast.IfExp', class extends ast.expr {\n            constructor(test, body, orelse) {\n                super();\n                this.test = test;\n                this.body = body;\n                this.orelse = orelse;\n            }\n        });\n        this.registerType('ast.NamedExpr', class extends ast.expr {\n            constructor(target, value) {\n                super();\n                this.target = target;\n                this.value = value;\n            }\n        });\n        this.registerType('ast.Yield', class extends ast.expr {\n            constructor(value) {\n                super();\n                this.value = value;\n            }\n        });\n        this.registerType('ast.YieldFrom', class extends ast.expr {\n            constructor(value) {\n                super();\n                this.value = value;\n            }\n        });\n        this.registerType('ast.Expr', class extends ast.stmt {\n            constructor(value) {\n                super();\n                this.value = value;\n            }\n        });\n        this.registerType('ast.Assign', class extends ast.stmt {\n            constructor(targets, value, ctx) {\n                super();\n                this.targets = targets;\n                this.value = value;\n                if (ctx) {\n                    this.ctx = ctx;\n                }\n            }\n        });\n        this.registerType('ast.AnnAssign', class extends ast.stmt {\n            constructor(target, annotation, value, simple) {\n                super();\n                this.target = target;\n                this.annotation = annotation;\n                this.value = value;\n                this.simple = simple;\n            }\n        });\n        this.registerType('ast.AugAssign', class extends ast.stmt {\n            constructor(target, op, value) {\n                super();\n                this.target = target;\n                this.op = op;\n                this.value = value;\n            }\n        });\n        this.registerType('ast.If', class extends ast.stmt {\n            constructor(test, body, orelse) {\n                super();\n                this.test = test;\n                this.body = body;\n                this.orelse = orelse;\n            }\n        });\n        this.registerType('ast.For', class extends ast.stmt {\n            constructor(target, iter, body, orelse /*, type_comment */) {\n                super();\n                this.target = target;\n                this.iter = iter;\n                this.body = body;\n                this.orelse = orelse;\n            }\n        });\n        this.registerType('ast.While', class extends ast.stmt {\n            constructor(test, body, orelse /*, type_comment */) {\n                super();\n                this.test = test;\n                this.body = body;\n                this.orelse = orelse;\n            }\n        });\n        this.registerType('ast.Del', class extends ast.stmt {\n            constructor(targets) {\n                super();\n                this.targets = targets;\n            }\n        });\n        this.registerType('ast.Return', class extends ast.stmt {\n            constructor(value) {\n                super();\n                this.value = value;\n            }\n        });\n        this.registerType('ast.Try', class extends ast.stmt {\n            constructor(body, handlers, orelse, finalbody) {\n                super();\n                this.body = body;\n                this.handlers = handlers;\n                this.orelse = orelse;\n                this.finalbody = finalbody;\n            }\n        });\n        this.registerType('ast.ExceptHandler', class extends ast.excepthandler {\n            constructor(type, name, body) {\n                super();\n                this.type_ = type;\n                this.name = name;\n                this.body = body;\n            }\n        });\n        this.registerType('ast.ClassDef', class extends ast.stmt {\n            constructor(name, bases, keywords, body, decorator_list, type_params) {\n                super();\n                this.name = name;\n                this.bases = bases;\n                this.keywords = keywords;\n                this.body = body;\n                this.decorator_list = decorator_list;\n                this.type_params = type_params;\n            }\n        });\n        this.registerType('ast.FunctionDef', class extends ast.stmt {\n            constructor(name, args, body, decorator_list, returns, type_comment, type_params) {\n                super();\n                this.name = name;\n                this.args = args;\n                this.body = body;\n                this.decorator_list = decorator_list;\n                this.returns = returns;\n                this.type_comment = type_comment;\n                this.type_params = type_params;\n            }\n        });\n        this.registerType('ast.arguments', class extends ast.AST {\n            constructor(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults) {\n                super();\n                this.posonlyargs = posonlyargs;\n                this.args = args;\n                this.vararg = vararg;\n                this.kwonlyargs = kwonlyargs;\n                this.kw_defaults = kw_defaults;\n                this.kwarg = kwarg;\n                this.defaults = defaults;\n            }\n        });\n        this.registerType('ast.arg', class extends ast.AST {\n            constructor(arg, annotation, type_comment) {\n                super();\n                this.arg = arg;\n                this.annotation = annotation;\n                this.type_comment = type_comment;\n            }\n        });\n        this.registerType('ast.Import', class extends ast.stmt {\n            constructor(names) {\n                super();\n                this.names = names;\n            }\n        });\n        this.registerType('ast.ImportFrom', class extends ast.stmt {\n            constructor(module, names, level) {\n                super();\n                this.module = module;\n                this.names = names;\n                this.level = level;\n            }\n        });\n        this.registerType('ast.Assert', class extends ast.stmt {\n            constructor(test, msg) {\n                super();\n                this.test = test;\n                this.msg = msg;\n            }\n        });\n        this.registerType('ast.Raise', class extends ast.stmt {\n            constructor(exc, cause) {\n                super();\n                this.exc = exc;\n                this.cause = cause;\n            }\n        });\n        this.registerType('ast.With', class extends ast.stmt {\n            constructor(items, body, type_comment) {\n                super();\n                this.items = items;\n                this.body = body;\n                this.type_comment = type_comment;\n            }\n        });\n        this.registerType('ast.withitem', class extends ast.AST {\n            constructor(context_expr, optional_vars) {\n                super();\n                this.context_expr = context_expr;\n                this.optional_vars = optional_vars;\n            }\n        });\n        this.registerType('ast.Global', class extends ast.stmt {\n            constructor(names) {\n                super();\n                this.names = names;\n            }\n        });\n        this.registerType('ast.Nonlocal', class extends ast.stmt {\n            constructor(names) {\n                super();\n                this.names = names;\n            }\n        });\n        this.registerType('ast.Continue', class extends ast.stmt {});\n        this.registerType('ast.Break', class extends ast.stmt {});\n        this.registerType('ast.Pass', class extends ast.stmt {});\n        this.registerType('ast.Await', class extends ast.stmt {\n            constructor(value) {\n                super();\n                this.value = value;\n            }\n        });\n        this.registerType('ast.Module', class extends ast.mod {\n            constructor(body, type_ignores) {\n                super();\n                this.body = body;\n                this.type_ignores = type_ignores;\n            }\n        });\n        this.registerFunction('ast.parse', (source, filename, mode, debug) => {\n            const parser =  new ast._Parser();\n            const module = parser.parse(source, filename, debug, mode);\n            return module;\n        });\n        this.registerFunction('ast._convert_literal', (node) => {\n            if (node instanceof ast.Constant) {\n                return node.value;\n            }\n            if (node instanceof ast.Dict && node.keys.length === node.values.length) {\n                const keys = node.keys.map((k) => ast._convert_literal(k));\n                const values = node.values.map((v) => ast._convert_literal(v));\n                return Object.fromEntries(keys.map((k, i) => [k, values[i]]));\n            }\n            if (node instanceof ast.Tuple) {\n                return new builtins.tuple(node.elts.map((e) => ast._convert_literal(e)));\n            }\n            if (node instanceof ast.List) {\n                return new builtins.list(node.elts.map((e) => ast._convert_literal(e)));\n            }\n            throw new python.Error(`'${node.__class__.__name__}' not implemented.`);\n        });\n        this.registerFunction('ast.literal_eval', (node_or_string) => {\n            if (typeof node_or_string === 'string') {\n                node_or_string = ast.parse(node_or_string, '', 'eval').body;\n            } else {\n                throw new python.Error(`'ast.literal_eval' node eval not implemented.`);\n            }\n            return ast._convert_literal(node_or_string);\n        });\n        this.registerType('ast._Parser', class {\n            constructor() {\n                ast._Parser._precedence = ast._Parser._precedence || {\n                    'or': 2, 'and': 3, 'not' : 4,\n                    'in': 5, 'instanceof': 5, 'is': 5, '<': 5, '>': 5, '<=': 5, '>=': 5, '<>': 5, '==': 5, '!=': 5,\n                    '|': 6, '^' : 7, '&' : 8,\n                    '<<': 9, '>>': 9, '+': 10, '-': 10, '*': 11, '@': 11, '/': 11, '//': 11, '%': 11,\n                    // '+': 12, '-': 12,\n                    '~': 13, '**': 14\n                };\n            }\n            parse(text, file, debug, mode) {\n                this._tokenizer = new ast._Tokenizer(text, file);\n                this._debug = debug;\n                const position = this._position();\n                let body = [];\n                while (!this._tokenizer.match('eof')) {\n                    const statement = this._parseStatement();\n                    if (statement) {\n                        body.push(statement);\n                        continue;\n                    }\n                    if (this._tokenizer.accept('\\n') || this._tokenizer.accept(';') || this._tokenizer.peek().type === 'eof') {\n                        continue;\n                    }\n                    if (this._tokenizer.accept('indent') && this._tokenizer.peek().type === 'eof') {\n                        continue;\n                    }\n                    throw new python.Error(`Unsupported statement ${this._location()}`);\n                }\n                if (mode === 'eval') {\n                    if (body.length !== 1 || body[0] instanceof ast.Expr === false) {\n                        throw new python.Error('Expected expression.');\n                    }\n                    body = body[0].value;\n                }\n                const module = new ast.Module(body);\n                this._mark(module, position);\n                return module;\n            }\n            _parseSuite() {\n                const body = [];\n                let statement = null;\n                if (this._tokenizer.accept('\\n')) {\n                    if (this._tokenizer.accept('indent')) {\n                        while (!this._tokenizer.accept('eof') && !this._tokenizer.accept('dedent')) {\n                            if (this._tokenizer.accept(';')) {\n                                continue;\n                            }\n                            statement = this._parseStatement();\n                            if (statement) {\n                                body.push(statement);\n                                continue;\n                            }\n                            if (this._tokenizer.accept('\\n')) {\n                                continue;\n                            }\n                            if (this._tokenizer.match('dedent') || this._tokenizer.match('eof')) {\n                                continue;\n                            }\n                            throw new python.Error(`Empty statement ${this._location()}`);\n                        }\n                    }\n                } else if (!this._tokenizer.accept('eof')) {\n                    while (!this._tokenizer.match('\\n') && !this._tokenizer.match('eof') && !this._tokenizer.match('dedent')) {\n                        if (this._tokenizer.accept(';')) {\n                            continue;\n                        }\n                        statement = this._parseStatement();\n                        if (statement) {\n                            body.push(statement);\n                            continue;\n                        }\n                        throw new python.Error(`Empty statement ${this._location()}`);\n                    }\n                    this._tokenizer.accept('\\n');\n                }\n                return body;\n            }\n            _parseStatement() {\n                let node = null;\n                let position = this._position();\n                if (this._eat('id', 'break')) {\n                    const node = new ast.Break();\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'continue')) {\n                    const node = new ast.Continue();\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'return')) {\n                    const value = this._parseExpression(-1, [], true);\n                    const node = new ast.Return(value);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'raise')) {\n                    let exc = this._parseExpression(-1, ['from']);\n                    let cause = null;\n                    if (this._tokenizer.accept('id', 'from')) {\n                        cause = this._parseExpression();\n                    } else if (this._tokenizer.accept(',')) {\n                        exc = [exc];\n                        exc.push(this._parseExpression());\n                        if (this._tokenizer.accept(',')) {\n                            exc.push(this._parseExpression());\n                        }\n                    }\n                    node = new ast.Raise(exc, cause);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'assert')) {\n                    const test = this._parseExpression(-1, [',']);\n                    let msg = null;\n                    if (this._tokenizer.accept(',')) {\n                        msg = this._parseExpression();\n                    }\n                    node = new ast.Assert(test, msg);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'global')) {\n                    const names = [];\n                    do {\n                        const name = this._parseName(true);\n                        names.push(name.id);\n                    }\n                    while (this._tokenizer.accept(','));\n                    const node = new ast.Global(names);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'nonlocal')) {\n                    const names = [];\n                    do {\n                        const name = this._parseName(true);\n                        names.push(name.id);\n                    }\n                    while (this._tokenizer.accept(','));\n                    const node = new ast.Nonlocal(names);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'import')) {\n                    const names = [];\n                    do {\n                        const name = this._parseDottedName();\n                        let asname = null;\n                        if (this._tokenizer.accept('id', 'as')) {\n                            asname = this._parseName(true).id;\n                        }\n                        const node = new ast.alias(name, asname);\n                        names.push(node);\n                    }\n                    while (this._tokenizer.accept(','));\n                    const node = new ast.Import(names);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'from')) {\n                    let level = 0;\n                    const dots = this._tokenizer.peek();\n                    if (dots && Array.from(dots.type).every((c) => c === '.')) {\n                        this._eat(dots.type);\n                        level = Array.from(dots.type).length;\n                    }\n                    const module = this._parseDottedName();\n                    this._tokenizer.expect('id', 'import');\n                    const names = [];\n                    const close = this._tokenizer.accept('(');\n                    do {\n                        const name = this._parseName(true).id;\n                        let asname = null;\n                        if (this._tokenizer.accept('id', 'as')) {\n                            asname = this._parseName(true).id;\n                        }\n                        const node = new ast.alias(name, asname);\n                        names.push(node);\n                    }\n                    while (this._tokenizer.accept(','));\n                    if (close) {\n                        this._tokenizer.expect(')');\n                    }\n                    const node = new ast.ImportFrom(module, names, level);\n                    return this._mark(node, position);\n                }\n                const decorator_list = this._decorator();\n                position = this._position();\n                if (this._eat('id', 'class')) {\n                    const name = this._parseName(true);\n                    const bases = [];\n                    if (this._tokenizer.accept('(')) {\n                        while (!this._tokenizer.accept(')')) {\n                            if (this._tokenizer.accept('\\n')) {\n                                continue;\n                            }\n                            const expression = this._parseExpression(-1, [], false);\n                            if (expression === null) {\n                                throw new python.Error(`Expected expression ${this._location()}`);\n                            }\n                            bases.push(expression);\n                            if (!this._tokenizer.accept(',')) {\n                                this._tokenizer.accept('\\n');\n                                this._tokenizer.expect(')');\n                                break;\n                            }\n                        }\n                    }\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    const node = new ast.ClassDef(name.id, bases, null, body, decorator_list, null);\n                    return this._mark(node, position);\n                }\n                const async = this._eat('id', 'async') !== null;\n                if (async &&\n                    !this._tokenizer.match('id', 'def') &&\n                    !this._tokenizer.match('id', 'with') &&\n                    !this._tokenizer.match('id', 'for')) {\n                    throw new python.Error(`Expected 'def', 'with' or 'for' ${this._location()}`);\n                }\n                if (this._eat('id', 'def')) {\n                    const name = this._parseName(true);\n                    this._tokenizer.expect('(');\n                    const args = this._parseArguments(')');\n                    let returns = null;\n                    if (this._tokenizer.accept('->')) {\n                        returns = this._parseType();\n                    }\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    const node = new ast.FunctionDef(name.id, args, body, decorator_list, returns, null, null);\n                    if (async) {\n                        node.async = async;\n                    }\n                    return this._mark(node, position);\n                }\n                if (decorator_list && decorator_list.length > 0) {\n                    throw new python.Error('Unexpected decorator.');\n                }\n                if (this._eat('id', 'del')) {\n                    const targets = this._parseExpression(-1, [], true);\n                    node = new ast.Del(targets);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'if')) {\n                    const test = this._parseExpression();\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    const node = new ast.If(test, body);\n                    let current = node;\n                    this._tokenizer.accept('\\n');\n                    while (this._tokenizer.accept('id', 'elif')) {\n                        const test = this._parseExpression();\n                        this._tokenizer.expect(':');\n                        const body = this._parseSuite();\n                        current.orelse = new ast.If(test, body);\n                        current = current.orelse;\n                        this._tokenizer.accept('\\n');\n                    }\n                    if (this._tokenizer.accept('id', 'else')) {\n                        this._tokenizer.expect(':');\n                        current.orelse = this._parseSuite();\n                    }\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'while')) {\n                    const test = this._parseExpression();\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    let orelse = null;\n                    if (this._tokenizer.accept('id', 'else')) {\n                        this._tokenizer.expect(':');\n                        orelse = this._parseSuite();\n                    }\n                    const node = new ast.While(test, body, orelse);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'pass')) {\n                    const node = new ast.Pass();\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'for')) {\n                    let target = this._parseExpression(-1, ['in']);\n                    while (this._tokenizer.accept(',')) {\n                        if (target instanceof ast.Tuple === false) {\n                            target = new ast.Tuple([target]);\n                        }\n                        if (this._tokenizer.match('id', 'in')) {\n                            target.elts.push({});\n                            break;\n                        }\n                        target.elts.push(this._parseExpression(-1, ['in']));\n                    }\n                    this._tokenizer.expect('id', 'in');\n                    let iter = this._parseExpression();\n                    while (this._tokenizer.accept(',')) {\n                        if (iter.type !== 'tuple') {\n                            iter = new ast.Tuple([iter]);\n                        }\n                        if (this._tokenizer.match(':')) {\n                            iter.elts.push({});\n                            break;\n                        }\n                        iter.elts.push(this._parseExpression(-1, ['in']));\n                    }\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    let orelse = null;\n                    if (this._tokenizer.accept('id', 'else')) {\n                        this._tokenizer.expect(':');\n                        orelse = this._parseSuite();\n                    }\n                    const node = new ast.For(target, iter, body, orelse);\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'with')) {\n                    const items = [];\n                    do {\n                        const context_expr = this._parseExpression();\n                        let optional_vars = null;\n                        if (this._tokenizer.accept('id', 'as')) {\n                            optional_vars = this._parseExpression();\n                        }\n                        const node = new ast.withitem(context_expr, optional_vars);\n                        items.push(node);\n                    }\n                    while (this._tokenizer.accept(','));\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    const node = new ast.With(items, body, null);\n                    if (async) {\n                        node.async = async;\n                    }\n                    return this._mark(node, position);\n                }\n                if (this._eat('id', 'try')) {\n                    this._tokenizer.expect(':');\n                    const body = this._parseSuite();\n                    const handlers = [];\n                    let orelse = null;\n                    let finalbody = null;\n                    while (this._tokenizer.match('id', 'except')) {\n                        this._tokenizer.expect('id', 'except');\n                        const type = this._parseExpression();\n                        const name = this._tokenizer.accept('id', 'as') ? this._parseExpression() : null;\n                        this._tokenizer.expect(':');\n                        const body = this._parseSuite();\n                        const except = new ast.ExceptHandler(type, name, body);\n                        handlers.push(except);\n                    }\n                    if (this._tokenizer.match('id', 'else')) {\n                        this._tokenizer.expect('id', 'else');\n                        this._tokenizer.expect(':');\n                        orelse = this._parseSuite();\n                    }\n                    if (this._tokenizer.match('id', 'finally')) {\n                        this._tokenizer.expect('id', 'finally');\n                        this._tokenizer.expect(':');\n                        finalbody = this._parseSuite();\n                    }\n                    const node = new ast.Try(body, handlers, orelse, finalbody);\n                    return this._mark(node, position);\n                }\n                const expr = this._parseExpression(-1, [], true);\n                if (expr) {\n                    if (expr instanceof ast.Name && this._tokenizer.accept(':')) {\n                        const position = this._position();\n                        const annotation = this._parseExpression(-1, ['=']);\n                        let value = null;\n                        if (this._tokenizer.accept('=')) {\n                            value = this._parseExpression();\n                        }\n                        node = new ast.AnnAssign(expr, annotation, value, expr instanceof ast.Name);\n                        return this._mark(node, position);\n                    }\n                    if (expr instanceof ast.stmt) {\n                        return expr;\n                    }\n                    switch (expr.__class__.__name__) {\n                        case 'AnnAssign':\n                        case 'Assert':\n                        case 'Assign':\n                        case 'Attribute':\n                        case 'AugAssign':\n                        case 'Await':\n                        case 'BinOp':\n                        case 'Call':\n                        case 'Compare':\n                        case 'Constant':\n                        case 'Dict':\n                        case 'Ellipsis':\n                        case 'For':\n                        case 'If':\n                        case 'Lambda':\n                        case 'List':\n                        case 'Name':\n                        case 'NamedExpr':\n                        case 'Raise':\n                        case 'Subscript':\n                        case 'Tuple':\n                        case 'Yield':\n                            // return expr;\n                            return new ast.Expr(expr);\n                        default:\n                            throw new python.Error(`Unhandled expression ${this._location()}`);\n                    }\n                }\n                return null;\n            }\n            _parseExpression(minPrecedence, terminal, tuple) {\n                minPrecedence = minPrecedence || -1;\n                const terminalSet = new Set(terminal);\n                const stack = [];\n                for (;;) {\n                    let position = this._position();\n                    let node = null;\n                    const token = this._tokenizer.peek();\n                    if (stack.length === 1 && terminalSet.has(token.value)) {\n                        break;\n                    }\n                    const precedence = ast._Parser._precedence[token.value];\n                    if (precedence) {\n                        if (precedence >= minPrecedence) {\n                            this._tokenizer.read();\n                            if (token.value === 'not' && this._tokenizer.accept('id', 'in')) {\n                                token.value = 'not in';\n                            } else if (token.value === 'is' && this._tokenizer.accept('id', 'not')) {\n                                token.value = 'is not';\n                            }\n                            if (stack.length > 0) {\n                                let op = null;\n                                switch (token.value) {\n                                    case '+':  op = new ast.Add(); break;\n                                    case '-':  op = new ast.Sub(); break;\n                                    case '*':  op = new ast.Mult(); break;\n                                    case '/':  op = new ast.Div(); break;\n                                    case '//': op = new ast.FloorDiv(); break;\n                                    case '**': op = new ast.Pow(); break;\n                                    case '@':  op = new ast.MatMult(); break;\n                                    case '&':  op = new ast.BitAnd(); break;\n                                    case '^':  op = new ast.BitXor(); break;\n                                    case '|':  op = new ast.BitOr(); break;\n                                    case '%':  op = new ast.Mod(); break;\n                                    case '>>': op = new ast.RShift(); break;\n                                    case '<<': op = new ast.LShift(); break;\n                                    default: break;\n                                }\n                                if (op) {\n                                    const left = stack.pop();\n                                    const right = this._parseExpression(precedence, terminal, tuple === true);\n                                    node = new ast.BinOp(left, op, right);\n                                } else {\n                                    switch (token.value) {\n                                        case '==': op = new ast.Eq(); break;\n                                        case '!=': op = new ast.NotEq(); break;\n                                        case '>=': op = new ast.GtE(); break;\n                                        case '<=': op = new ast.LtE(); break;\n                                        case '<':  op = new ast.Lt(); break;\n                                        case '>':  op = new ast.Gt(); break;\n                                        case 'is': op = new ast.Is(); break;\n                                        case 'is not': op = new ast.IsNot(); break;\n                                        case 'in': op = new ast.In(); break;\n                                        case 'not in': op = new ast.NotIn(); break;\n                                        default: break;\n                                    }\n                                    const left = stack.pop();\n                                    const comparator = this._parseExpression(precedence, ['for', 'if'], tuple === true);\n                                    node = new ast.Compare(left, [op], [comparator]);\n                                }\n                            } else if (token.value === '*') {\n                                const value =  this._parseExpression(precedence, terminal, tuple === true);\n                                node = new ast.Starred(value);\n                            } else if (token.value === '**') {\n                                const value =  this._parseExpression(precedence, terminal, tuple === true);\n                                node = new ast.keyword(null, value);\n                            } else {\n                                let op = null;\n                                switch (token.value) {\n                                    case '-': op = new ast.USub(); break;\n                                    case '+': op = new ast.UAdd(); break;\n                                    case '~': op = new ast.Invert(); break;\n                                    case 'not': op = new ast.Not(); break;\n                                    default: throw new python.Error(`Unsupported unary operator ${token.value} ${this._location()}`);\n                                }\n                                const operand =  this._parseExpression(precedence, terminal, tuple === true);\n                                node = new ast.UnaryOp(op, operand);\n                                node = this._mark(node, position);\n                            }\n                            stack.push(node);\n                            continue;\n                        }\n                    }\n                    if (this._tokenizer.accept(':=')) {\n                        const target = stack.pop();\n                        const value = this._parseExpression(-1, terminal, tuple !== false);\n                        const node = new ast.NamedExpr(target, value);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._tokenizer.accept('=')) {\n                        const position = this._position();\n                        const targets = stack.pop();\n                        const value = this._parseExpression(-1, terminal, tuple !== false);\n                        const node = new ast.Assign([targets], value);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    let op = null;\n                    switch (token.type) {\n                        case '+=':  op = new ast.Add(); break;\n                        case '-=':  op = new ast.Sub(); break;\n                        case '**=': op = new ast.Pow(); break;\n                        case '*=':  op = new ast.Mult(); break;\n                        case '//=': op = new ast.FloorDiv(); break;\n                        case '/=':  op = new ast.Div(); break;\n                        case '&=':  op = new ast.BitAnd(); break;\n                        case '%=':  op = new ast.Mod(); break;\n                        case '^=':  op = new ast.BitXor(); break;\n                        case '<<=': op = new ast.LShift(); break;\n                        case '>>=': op = new ast.RShift(); break;\n                        case '|=':  op = new ast.BitOr(); break;\n                        case '@=':  op = new ast.MatMul(); break;\n                        default: break;\n                    }\n                    if (op) {\n                        this._tokenizer.expect(token.type);\n                        const target = stack.pop();\n                        const value = this._parseExpression(-1, terminal, true);\n                        const node = new ast.AugAssign(target, op, value);\n                        stack.push(node);\n                        continue;\n                    }\n                    position = this._position();\n                    if (this._eat('id', 'if')) {\n                        const body = stack.pop();\n                        const test = this._parseExpression();\n                        this._tokenizer.expect('id', 'else');\n                        const orelse = this._parseExpression();\n                        const node = new ast.IfExp(test, body, orelse);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._tokenizer.match('id', 'for') || this._tokenizer.match('id', 'async')) {\n                        const position = this._position();\n                        const elt = stack.pop();\n                        const generators = this._parseGenerators();\n                        let node = null;\n                        if (elt instanceof ast.Dict) {\n                            if (elt.keys.length !== 1 || elt.values.length !== 1) {\n                                throw new python.Error(`Invalid dict comprehension ${this._location()}`);\n                            }\n                            node = new ast.DictComp(elt.keys[0], elt.values[0], generators);\n                        } else if (elt instanceof ast.Set) {\n                            if (elt.elts.length !== 1) {\n                                throw new python.Error(`Invalid set comprehension ${this._location()}`);\n                            }\n                            node = new ast.SetComp(elt.elts[0], generators);\n                        } else {\n                            node = new ast.GeneratorExp(elt, generators);\n                        }\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._eat('id', 'lambda')) {\n                        const args = this._parseArguments(':');\n                        const body = this._parseExpression(-1, terminal, false);\n                        const node = new ast.Lambda(args, body);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._eat('id', 'yield')) {\n                        if (this._tokenizer.accept('id', 'from')) {\n                            const value = this._parseExpression(-1, [], true);\n                            node = new ast.YieldFrom(value);\n                            stack.push(node);\n                        } else {\n                            const value = [];\n                            do {\n                                value.push(this._parseExpression(-1, [], false));\n                            }\n                            while (this._tokenizer.accept(','));\n                            node = new ast.Yield(value);\n                            stack.push(node);\n                        }\n                        continue;\n                    }\n                    if (this._eat('id', 'await')) {\n                        const value = this._parseExpression(minPrecedence, terminal, tuple);\n                        const node = new ast.Await(value);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._eat('.')) {\n                        const value = stack.pop();\n                        const attr = this._parseName().id;\n                        const node = new ast.Attribute(value, attr);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._tokenizer.peek().type === '(') {\n                        const position = this._position();\n                        const args = [];\n                        const keywords = [];\n                        this._tokenizer.expect('(');\n                        let tuple = false;\n                        while (!this._tokenizer.accept(')')) {\n                            if (this._tokenizer.accept('\\n')) {\n                                continue;\n                            }\n                            const position = this._position();\n                            const expr = this._parseExpression(-1, [], false);\n                            if (expr === null) {\n                                throw new python.Error(`Expected expression ${this._location()}`);\n                            }\n                            if (expr instanceof ast.Assign && expr.targets.length === 1) {\n                                const [target] = expr.targets;\n                                if (target instanceof ast.Name === false) {\n                                    throw new python.Error(`Expected name ${this._location()}`);\n                                }\n                                const node = new ast.keyword(target.id, expr.value);\n                                this._mark(node, position);\n                                keywords.push(node);\n                            } else {\n                                args.push(expr);\n                            }\n                            if (this._tokenizer.accept(',')) {\n                                tuple = true;\n                            } else {\n                                this._tokenizer.accept('\\n');\n                                this._tokenizer.expect(')');\n                                break;\n                            }\n                        }\n                        if (stack.length === 0 && keywords.length === 0) {\n                            node = args.length === 1 && !tuple ? args[0] : new ast.Tuple(args);\n                            this._mark(node, position);\n                        } else {\n                            const func = stack.pop();\n                            node = new ast.Call(func, args, keywords);\n                            let start = func;\n                            while (start instanceof ast.Attribute) {\n                                start = start.value;\n                            }\n                            position.lineno = start.lineno;\n                            position.col_offset = start.col_offset;\n                            this._mark(node, position);\n                        }\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._tokenizer.peek().type === '[') {\n                        if (stack.length === 0) {\n                            stack.push(this._parseList());\n                        } else {\n                            const value = stack.pop();\n                            const position = this._position();\n                            const slice = this._parseSlice();\n                            node = new ast.Subscript(value, slice);\n                            this._mark(node, position);\n                            stack.push(node);\n                        }\n                        continue;\n                    }\n                    if (this._tokenizer.peek().type === '{') {\n                        const elts = [];\n                        const keys = [];\n                        const values = [];\n                        this._tokenizer.expect('{');\n                        let dict = true;\n                        while (!this._tokenizer.accept('}')) {\n                            const item = this._parseExpression(-1, [], false);\n                            if (item === null) {\n                                throw new python.Error(`Expected expression ${this._location()}`);\n                            }\n                            if (!this._tokenizer.accept(':')) {\n                                dict = false;\n                            }\n                            if (dict) {\n                                const value = this._parseExpression(-1, ['for'], false);\n                                if (value === null) {\n                                    throw new python.Error(`Expected expression ${this._location()}`);\n                                }\n                                if (this._eat('id', 'for')) {\n                                    if (keys.length > 0 || values.length > 0 || elts.length > 0) {\n                                        throw new python.Error(`Invalid list expression ${this._location()}`);\n                                    }\n                                    const target = this._parseExpression(-1, ['in'], true);\n                                    this._tokenizer.expect('id', 'in');\n                                    const iter = this._parseExpression(-1, ['for', 'if'], true);\n                                    const ifs = [];\n                                    while (this._tokenizer.accept('id', 'if')) {\n                                        ifs.push(this._parseExpression(-1, ['for', 'if']));\n                                    }\n                                    const comprehension = new ast.comprehension(target, iter, ifs /*, async */);\n                                    const generators = [comprehension];\n                                    this._tokenizer.expect('}');\n                                    return new ast.DictComp(item, value, generators);\n                                }\n                                keys.push(item);\n                                values.push(value);\n                            } else {\n                                elts.push(item);\n                            }\n                            this._tokenizer.accept(',');\n                            this._tokenizer.accept('\\n');\n                            if (this._tokenizer.accept('}')) {\n                                break;\n                            }\n                        }\n                        if (keys.length !== values.length || (keys.length > 0 && elts.length > 0)) {\n                            throw new python.Error(`Invalid set expression ${this._location()}`);\n                        }\n                        const node = elts.length > 0 ? new ast.Set(elts) : new ast.Dict(keys, values);\n                        stack.push(node);\n                        continue;\n                    }\n                    const literal = this._parseLiteral();\n                    if (literal) {\n                        if (stack.length === 1 && literal.type === 'str' && stack[0] instanceof ast.Constant && typeof stack[0].value === 'string') {\n                            stack[0].value += literal.value.substring(1, literal.value.length - 1);\n                        } else {\n                            let value = literal.value;\n                            switch (literal.type) {\n                                case 'int':\n                                case 'float':\n                                    value = value === 'inf' ? Infinity : Number(value);\n                                    break;\n                                case 'complex':\n                                    value = new builtins.complex(0, Number(value.slice(0, -1)));\n                                    break;\n                                case 'str':\n                                    value = value.substring(1, value.length - 1);\n                                    break;\n                                default:\n                                    throw new python.Error(`Invalid literal type '${literal.type}' ${this._location()}`);\n                            }\n                            const node = new ast.Constant(value, literal.type);\n                            this._mark(node, position);\n                            stack.push(node);\n                        }\n                        continue;\n                    }\n                    if (this._eat('id', 'False')) {\n                        const node = new ast.Constant(false, 'bool');\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._eat('id', 'True')) {\n                        const node = new ast.Constant(true, 'bool');\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._eat('id', 'None')) {\n                        const node = new ast.Constant(null);\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    if (this._tokenizer.peek().keyword) {\n                        break;\n                    }\n                    if (this._eat('...')) {\n                        const node = new ast.Ellipsis();\n                        this._mark(node, position);\n                        stack.push(node);\n                        continue;\n                    }\n                    const name = this._parseName();\n                    if (name) {\n                        stack.push(name);\n                        continue;\n                    }\n                    if (tuple === true && stack.length === 1 && this._tokenizer.accept(',')) {\n                        if (stack[0] instanceof ast.Tuple) {\n                            [node] = stack;\n                        } else {\n                            const position = this._position();\n                            const elts = [stack.pop()];\n                            node = new ast.Tuple(elts);\n                            this._mark(node, position);\n                            stack.push(node);\n                        }\n                        // for, bar, = <expr>\n                        if (this._tokenizer.peek().type === '=') {\n                            continue;\n                        }\n                        if (!this._tokenizer.match('=') && !terminalSet.has(this._tokenizer.peek().value)) {\n                            const nextTerminal = terminal.slice(0).concat([',', '=']);\n                            const expression = this._parseExpression(minPrecedence, nextTerminal, tuple);\n                            if (expression) {\n                                node.elts.push(expression);\n                                continue;\n                            }\n                        }\n                        break;\n                    }\n                    break;\n                }\n                if (stack.length === 1) {\n                    return stack.pop();\n                }\n                if (stack.length !== 0) {\n                    throw new python.Error(`Unexpected expression ${this._location()}`);\n                }\n                return null;\n            }\n            _decorator() {\n                const list = [];\n                while (this._tokenizer.accept('@')) {\n                    const value = this._parseExpression();\n                    if (!value || (value instanceof ast.Call === false && value instanceof ast.Name === false && value instanceof ast.Attribute === false)) {\n                        throw new python.Error(`Invalid decorator ${this._location()}`);\n                    }\n                    this._tokenizer.accept('\\n');\n                    list.push(value);\n                }\n                return list;\n            }\n            _parseGenerators() {\n                const generators = [];\n                while (this._tokenizer.match('id', 'for') || this._tokenizer.match('id', 'async')) {\n                    const is_async = this._eat('id', 'async') ? 1 : 0;\n                    this._tokenizer.expect('id', 'for');\n                    const target = this._parseExpression(-1, ['in'], true);\n                    this._tokenizer.expect('id', 'in');\n                    const iter = this._parseExpression(-1, ['for', 'if'], true);\n                    const ifs = [];\n                    while (this._tokenizer.accept('id', 'if')) {\n                        ifs.push(this._parseExpression(-1, ['for', 'if']));\n                    }\n                    const comprehension = new ast.comprehension(target, iter, ifs, is_async);\n                    generators.push(comprehension);\n                }\n                return generators;\n            }\n            _parseList() {\n                const elts = [];\n                this._tokenizer.expect('[');\n                if (!this._tokenizer.match(']')) {\n                    const position = this._position();\n                    const expr = this._parseExpression(-1, ['for']);\n                    if (this._tokenizer.match('id', 'for')) {\n                        const generators = this._parseGenerators();\n                        this._tokenizer.expect(']');\n                        const node = new ast.ListComp(expr, generators);\n                        this._mark(node, position);\n                        return node;\n                    }\n                    if (expr === null) {\n                        throw new python.Error(`Expected expression ${this._location()}`);\n                    }\n                    elts.push(expr);\n                    while (this._tokenizer.accept(',')) {\n                        if (this._tokenizer.match(']')) {\n                            break;\n                        }\n                        const expr = this._parseExpression(-1, ['for']);\n                        if (!expr) {\n                            throw new python.Error(`Expected expression ${this._location()}`);\n                        }\n                        elts.push(expr);\n                    }\n                }\n                this._tokenizer.expect(']');\n                return new ast.List(elts);\n            }\n            _parseSlice() {\n                const elts = [];\n                let slice = [null, null, null];\n                let index = 0;\n                let valid = false;\n                this._tokenizer.expect('[');\n                while (true) {\n                    if (this._tokenizer.accept(':')) {\n                        index++;\n                        valid = true;\n                    } else if (index > 2 || this._tokenizer.match(',') || this._tokenizer.match(']')) {\n                        if (!valid || index > 2) {\n                            throw new python.Error(`Invalid slice at ${this._location()}`);\n                        }\n                        elts.push(index === 0 ? slice[0] : new ast.Slice(slice[0], slice[1], slice[2]));\n                        slice = [null, null, null];\n                        index = 0;\n                        if (this._tokenizer.accept(']')) {\n                            break;\n                        }\n                        this._tokenizer.expect(',');\n                    } else {\n                        const expression = this._parseExpression();\n                        if (expression === null) {\n                            throw new python.Error(`Expected expression ${this._location()}`);\n                        }\n                        slice[index] = expression;\n                        valid = true;\n                    }\n                }\n                if (elts.length > 1) {\n                    return new ast.Tuple(elts);\n                }\n                return elts[0];\n            }\n            _parseName(required) {\n                const token = this._tokenizer.peek();\n                if (token.type === 'id' && !token.keyword) {\n                    const position = this._position();\n                    this._tokenizer.read();\n                    const node = new ast.Name(token.value);\n                    return this._mark(node, position);\n                }\n                if (required) {\n                    throw new python.Error(`Invalid syntax ${this._location()}`);\n                }\n                return null;\n            }\n            _parseDottedName() {\n                const list = [];\n                do {\n                    const name = this._parseName(true);\n                    list.push(name.id);\n                }\n                while (this._tokenizer.accept('.'));\n                return list.join('.');\n            }\n            _parseLiteral() {\n                const token = this._tokenizer.peek();\n                if (token.type === 'str' || token.type === 'bool' || token.type === 'int' || token.type === 'float' || token.type === 'complex') {\n                    this._tokenizer.read();\n                    return token;\n                }\n                return null;\n            }\n            _parseTypeArguments() {\n                const list = [];\n                this._tokenizer.expect('[');\n                while (!this._tokenizer.accept(']')) {\n                    const type = this._parseType();\n                    if (type === null) {\n                        throw new python.Error(`Expected type ${this._location()}`);\n                    }\n                    list.push(type);\n                    if (!this._tokenizer.accept(',')) {\n                        this._tokenizer.expect(']');\n                        break;\n                    }\n                }\n                return list;\n            }\n            _parseType() {\n                const target = this._parseExpression(-1, ['[', '=']);\n                if (target) {\n                    if (this._tokenizer.peek().value === '[') {\n                        const list = this._parseList();\n                        const slice = list.elts.length === 1 ? list.elts[0] : new ast.Tuple(list.elts);\n                        return new ast.Subscript(target, slice);\n                    }\n                    return target;\n                }\n                return null;\n            }\n            _parseArguments(terminal) {\n                let posonlyargs = [];\n                let args = [];\n                let vararg = null;\n                const kwonlyargs = [];\n                const kw_defaults = [];\n                let kwarg = null;\n                const defaults = [];\n                let is_slash = false;\n                let is_vararg = false; // '*'\n                let is_kwarg = false; // '**'\n                const read = (required) => {\n                    const name = this._parseName(required);\n                    if (name) {\n                        const annotation = terminal !== ':' && this._tokenizer.accept(':') ? this._parseType() : null;\n                        return new ast.arg(name.id, annotation, null);\n                    }\n                    return null;\n                };\n                while (!this._tokenizer.accept(terminal)) {\n                    this._tokenizer.accept('\\n');\n                    if (this._tokenizer.accept('/')) {\n                        if (is_slash || is_vararg || is_kwarg) {\n                            throw new python.Error(`Invalid '/' in arguments ${this._location()}`);\n                        }\n                        is_slash = true;\n                    } else if (this._tokenizer.accept('*')) {\n                        if (is_vararg) {\n                            throw new python.Error(`Multiple '*' arguments ${this._location()}`);\n                        }\n                        is_vararg = true;\n                        const arg = read(false);\n                        vararg = arg ? arg : vararg;\n                    } else if (this._tokenizer.accept('**')) {\n                        if (is_kwarg) {\n                            throw new python.Error(`Multiple '**' arguments ${this._location()}`);\n                        }\n                        is_kwarg = true;\n                        kwarg = read(true);\n                    } else {\n                        const arg = read(false);\n                        if (!arg) {\n                            this._tokenizer.expect(terminal);\n                            break;\n                        }\n                        const default_value = this._tokenizer.accept('=') ? this._parseExpression() : null;\n                        if (!is_vararg && !is_kwarg) {\n                            if (is_slash) {\n                                args.push(arg);\n                            } else {\n                                posonlyargs.push(arg);\n                            }\n                            if (default_value !== null) {\n                                defaults.push(default_value);\n                            }\n                        } else if (is_vararg && !is_kwarg) {\n                            kwonlyargs.push(arg);\n                            kw_defaults.push(default_value);\n                        } else {\n                            throw new python.Error(`Argument after '**' parameter ${this._location()}`);\n                        }\n                    }\n                    this._tokenizer.accept('\\n');\n                    if (!this._tokenizer.accept(',')) {\n                        this._tokenizer.expect(terminal);\n                        break;\n                    }\n                }\n                if (!is_slash) {\n                    args = posonlyargs.concat(args);\n                    posonlyargs = [];\n                }\n                return new ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults);\n            }\n            _eat(type, value) {\n                if (this._tokenizer.match(type, value)) {\n                    const position = this._position();\n                    this._tokenizer.expect(type, value);\n                    return position;\n                }\n                return null;\n            }\n            _mark(node, position) {\n                node.filename = position.filename;\n                node.lineno = position.lineno;\n                node.col_offset = position.col_offset;\n                node.end_lineno = this._tokenizer.lineno;\n                node.end_col_offset = this._tokenizer.col_offset;\n                return node;\n            }\n            _position() {\n                return {\n                    filename: this._tokenizer.filename,\n                    lineno: this._tokenizer.lineno,\n                    col_offset: this._tokenizer.col_offset\n                };\n            }\n            _location() {\n                return this._tokenizer.location();\n            }\n        });\n        this.registerType('ast._Tokenizer', class {\n            constructor(text, file) {\n                this._text = text;\n                this.filename = file;\n                this.linepos = 0;\n                this.lineno = 1;\n                this._position = 0;\n                this._token = { type: '', value: '' };\n                this._brackets = 0;\n                this._indentation = [];\n                this._outdent = 0;\n                if (!ast._Tokenizer._whitespace) {\n                    ast._Tokenizer._whitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]/;\n                    const identifierStartChars = '\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc';\n                    const identifierChars = '\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f';\n                    ast._Tokenizer._identifierStart = new RegExp(`[${identifierStartChars}]`);\n                    /* eslint-disable no-misleading-character-class */\n                    ast._Tokenizer._identifierChar = new RegExp(`[${identifierStartChars}${identifierChars}]`);\n                    /* eslint-enable no-misleading-character-class */\n                }\n            }\n            peek() {\n                if (!this._cache) {\n                    this._tokenize();\n                    this._cache = true;\n                }\n                return this._token;\n            }\n            read() {\n                if (!this._cache) {\n                    this._tokenize();\n                }\n                const next = this._position + this._token.value.length;\n                while (this._position < next) {\n                    if (ast._Tokenizer._isNewline(this._get(this._position))) {\n                        this._position = this._newLine(this._position);\n                        this.linepos = this._position;\n                        this.lineno++;\n                    } else {\n                        this._position++;\n                    }\n                }\n                this._cache = false;\n                return this._token;\n            }\n            match(type, value) {\n                const token = this.peek();\n                if (token.type === type && (!value || token.value === value)) {\n                    return true;\n                }\n                return false;\n            }\n            accept(type, value) {\n                const token = this.peek();\n                if (token.type === type && (!value || token.value === value)) {\n                    this.read();\n                    return true;\n                }\n                return false;\n            }\n            expect(type, value) {\n                const token = this.peek();\n                if (token.type !== type) {\n                    throw new python.Error(`Unexpected '${token.value}' instead of '${type}' ${this.location()}`);\n                }\n                if (value && token.value !== value) {\n                    throw new python.Error(`Unexpected '${token.value}' instead of '${value}' ${this.location()}`);\n                }\n                this.read();\n            }\n            location() {\n                return `at ${this.filename}:${this.lineno}:${this.col_offset}.`;\n            }\n            get col_offset() {\n                return this._position - this.linepos + 1;\n            }\n            static _isSpace(c) {\n                if (c === ' ' || c === '\\t' || c === '\\v' || c === '\\f' || c === '\\xA0') {\n                    return true;\n                }\n                if (c.charCodeAt(0) >= 0x1680) {\n                    return ast._Tokenizer._whitespace.test(c);\n                }\n                return false;\n            }\n            static _isNewline(c) {\n                switch (c) {\n                    case '\\n':\n                    case '\\r':\n                    case '\\u2028': // 8232\n                    case '\\u2029': // 8233\n                        return true;\n                    default:\n                        return false;\n                }\n            }\n            static _isIdentifierStartChar(c) {\n                if (c < 'A') {\n                    return c === '$';\n                }\n                if (c <= 'Z') {\n                    return true;\n                }\n                if (c < 'a') {\n                    return c === '_';\n                }\n                if (c <= 'z') {\n                    return true;\n                }\n                const code = c.charCodeAt(0);\n                if (code >= 0xAA) {\n                    return ast._Tokenizer._identifierStart.test(c);\n                }\n                return false;\n            }\n            static _isIdentifierChar(c) {\n                if (c < '0') {\n                    return c === '$';\n                }\n                if (c <= '9') {\n                    return true;\n                }\n                if (c < 'A') {\n                    return false;\n                }\n                if (c <= 'Z') {\n                    return true;\n                }\n                if (c < 'a') {\n                    return c === '_';\n                }\n                if (c <= 'z') {\n                    return true;\n                }\n                const code = c.charCodeAt(0);\n                if (code >= 0xAA) {\n                    return ast._Tokenizer._identifierChar.test(c);\n                }\n                return false;\n            }\n            _get(position) {\n                return position >= this._text.length ? '\\0' : this._text[position];\n            }\n            _skipLine() {\n                while (this._position < this._text.length) {\n                    if (ast._Tokenizer._isNewline(this._get(this._position))) {\n                        break;\n                    }\n                    this._position++;\n                }\n            }\n            _skipWhitespace() {\n                while (this._position < this._text.length) {\n                    const c = this._text[this._position];\n                    if (c === '#') {\n                        this._skipLine();\n                    } else if (ast._Tokenizer._isSpace(c)) {\n                        this._position++;\n                    } else if (c === '\\\\') {\n                        // Explicit Line Continuation\n                        this._position++;\n                        if (ast._Tokenizer._isNewline(this._get(this._position))) {\n                            this._position = this._newLine(this._position);\n                            this.linepos = this._position;\n                            this.lineno += 1;\n                        } else {\n                            throw new python.Error(`Unexpected '${this._text[this._position]}' after line continuation ${this.location()}`);\n                        }\n                    } else if (this._brackets > 0 && ast._Tokenizer._isNewline(c)) {\n                        // Implicit Line Continuation\n                        this._position = this._newLine(this._position);\n                        this.linepos = this._position;\n                        this.lineno += 1;\n                    } else {\n                        break;\n                    }\n                }\n            }\n            _newLine(position) {\n                if ((this._get(position) === '\\n' && this._get(position + 1) === '\\r') || (this._get(position) === '\\r' && this._get(position + 1) === '\\n')) {\n                    return position + 2;\n                }\n                return position + 1;\n            }\n            _tokenize() {\n                if (this._token.type !== '\\n') {\n                    this._skipWhitespace();\n                }\n                if (this._token.type === 'dedent') {\n                    this._indentation.pop();\n                    this._outdent--;\n                    if (this._outdent > 0) {\n                        this._token = { type: 'dedent', value: '' };\n                        return;\n                    }\n                }\n                if (this._token.type === '\\n') {\n                    let indent = '';\n                    let i = this._position;\n                    while (i < this._text.length) {\n                        const c = this._text[i];\n                        if (ast._Tokenizer._isSpace(c)) {\n                            indent += c;\n                            i++;\n                        } else if (ast._Tokenizer._isNewline(c)) {\n                            indent = '';\n                            i = this._newLine(i);\n                            this._position = i;\n                            this.linepos = i;\n                            this.lineno += 1;\n                        } else if (c === '#') {\n                            indent = '';\n                            while (i < this._text.length && !ast._Tokenizer._isNewline(this._text[i])) {\n                                i++;\n                            }\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                    let type = null;\n                    if (indent.length > 0) {\n                        const current = this._indentation.length > 0 ? this._indentation[this._indentation.length - 1] : '';\n                        if (indent.length > current.length) {\n                            type = 'indent';\n                            this._indentation.push(indent);\n                        } else if (indent.length > 0 && indent.length < current.length) {\n                            type = 'dedent';\n                            this._outdent = 0;\n                            for (let j = this._indentation.length - 1; j >= 0 && indent.length < this._indentation[j].length; j--) {\n                                this._outdent++;\n                            }\n                        } else {\n                            this._position += indent.length;\n                        }\n                    } else if (i >= this._text.length) {\n                        this._token = { type: 'eof', value: '' };\n                        return;\n                    } else if (this._indentation.length > 0) {\n                        type = 'dedent';\n                        this._outdent = this._indentation.length;\n                    }\n                    if (type === 'indent' || type === 'dedent') {\n                        this._token = { type, value: indent };\n                        return;\n                    }\n                }\n                if (this._position >= this._text.length) {\n                    this._token = { type: 'eof', value: '' };\n                    return;\n                }\n                const c = this._get(this._position);\n                const string = this._string();\n                if (string) {\n                    this._token = string;\n                    return;\n                }\n                switch (c) {\n                    case '(':\n                    case '[':\n                    case '{':\n                        this._brackets++;\n                        this._token = { type: c, value: c };\n                        return;\n                    case ')':\n                    case ']':\n                    case '}':\n                        if (this._brackets === 0) {\n                            throw new python.Error(`Unexpected '${c}' ${this.location}`);\n                        }\n                        this._brackets--;\n                        this._token = { type: c, value: c };\n                        return;\n                    case ',':\n                    case ';':\n                    case '?':\n                        this._token = { type: c, value: c };\n                        return;\n                    default: {\n                        const number = this._number();\n                        if (number) {\n                            this._token = number;\n                            return;\n                        }\n                        if (c === '.') {\n                            let end = this._position + 1;\n                            while (this._get(end) === '.') {\n                                end++;\n                            }\n                            const text = this._text.substring(this._position, end);\n                            this._token = { type: text, value: text };\n                            return;\n                        }\n                        const identifier = this._identifier();\n                        if (identifier) {\n                            this._token = identifier;\n                            return;\n                        }\n                        const operator = this._operator();\n                        if (operator) {\n                            this._token = operator;\n                            return;\n                        }\n                        break;\n                    }\n                }\n                if (c === '.') {\n                    this._token = { type: c, value: c };\n                    return;\n                }\n                if (c === '\\\\') {\n                    this._token = { type: '\\\\', value: c };\n                    return;\n                }\n                if (ast._Tokenizer._isNewline(c)) {\n                    this._token = { type: '\\n', value: this._text.substring(this._position, this._newLine(this._position)) };\n                    return;\n                }\n                throw new python.Error(`Unexpected token '${c}' ${this.location()}`);\n            }\n            _number() {\n                const octal = (c) => c >= '0' && c <= '7' || c === '_';\n                const binary = (c) => c === '0' || c === '1' || c === '_';\n                const decimal = (c) => c >= '0' && c <= '9' || c === '_';\n                const hex = (c) => decimal(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c === '_';\n                let c = this._get(this._position);\n                let i = this._position;\n                c = this._get(i);\n                if (c === '0') {\n                    let radix = 0;\n                    const n = this._get(i + 1);\n                    if ((n === 'x' || n === 'X') && hex(this._get(i + 2))) {\n                        i += 2;\n                        while (hex(this._get(i))) {\n                            i += 1;\n                        }\n                        if (this._get(i) === 'l' || this._get(i) === 'L') {\n                            i += 1;\n                        }\n                        radix = 16;\n                    } else if ((n === 'b' || n === 'B') && binary(this._get(i + 2))) {\n                        i += 2;\n                        while (binary(this._get(i))) {\n                            i++;\n                        }\n                        radix = 2;\n                    } else if ((n === 'o' || n === 'O') && octal(this._get(i + 2))) {\n                        i += 2;\n                        while (octal(this._get(i))) {\n                            i++;\n                        }\n                        radix = 8;\n                    } else if (n >= '0' && n <= '7') {\n                        i++;\n                        while (octal(this._get(i))) {\n                            i += 1;\n                        }\n                        if (this._get(i) === 'l' || this._get(i) === 'L') {\n                            i += 1;\n                        }\n                        radix = 8;\n                    }\n                    if (radix > 0 && this._get(i) !== '.') {\n                        const radixText = this._text.substring(this._position, i);\n                        const radixParseText = radixText.indexOf('_') === -1 ? radixText : radixText.split('_').join('');\n                        if (!isNaN(parseInt(radixParseText, radix))) {\n                            return { type: 'int', value: radixText };\n                        }\n                    }\n                }\n                i = this._position;\n                let isDecimal = false;\n                if (this._get(i) >= '1' && this._get(i) <= '9') {\n                    while (decimal(this._get(i))) {\n                        i++;\n                    }\n                    c = this._get(i).toLowerCase();\n                    isDecimal = c !== '.' && c !== 'e';\n                }\n                if (this._get(i) === '0') {\n                    i++;\n                    c = this._get(i).toLowerCase();\n                    isDecimal = !decimal(c) && c !== '.' && c !== 'e' && c !== 'j';\n                }\n                if (isDecimal) {\n                    if (this._get(i) === 'j' || this._get(i) === 'J') {\n                        return { 'type': 'complex', value: this._text.substring(this._position, i + 1) };\n                    }\n                    // if (this._get(i) === 'l' || this._get(i) === 'L') {\n                    //     Python 2 long integer\n                    // }\n                    const intText = this._text.substring(this._position, i);\n                    if (!isNaN(parseInt(intText, 10))) {\n                        return { type: 'int', value: intText };\n                    }\n                }\n                i = this._position;\n                if ((this._get(i) >= '0' && this._get(i) <= '9') ||\n                    (this._get(i) === '.' && this._get(i + 1) >= '0' && this._get(i + 1) <= '9')) {\n                    while (decimal(this._get(i))) {\n                        i++;\n                    }\n                    if (this._get(i) === '.') {\n                        i++;\n                    }\n                    while (decimal(this._get(i))) {\n                        i++;\n                    }\n                    if (i > this._position) {\n                        if (this._get(i) === 'e' || this._get(i) === 'E') {\n                            i++;\n                            if (this._get(i) === '-' || this._get(i) === '+') {\n                                i++;\n                            }\n                            if (decimal(this._get(i))) {\n                                while (decimal(this._get(i))) {\n                                    i++;\n                                }\n                            } else {\n                                i = this._position;\n                            }\n                        } else {\n                            while (decimal(this._get(i))) {\n                                i++;\n                            }\n                        }\n                    }\n                    if (i > this._position) {\n                        if (this._get(i) === 'j' || this._get(i) === 'J') {\n                            return { type: 'complex', value: this._text.substring(this._position, i + 1) };\n                        }\n                        const floatText = this._text.substring(this._position, i);\n                        const floatParseText = floatText.indexOf('_') === -1 ? floatText : floatText.split('_').join('');\n                        if (!isNaN(parseFloat(floatParseText))) {\n                            return { type: 'float', value: floatText };\n                        }\n                    }\n                }\n                return null;\n            }\n            _identifier() {\n                let i = this._position;\n                if (ast._Tokenizer._isIdentifierStartChar(this._get(i))) {\n                    i++;\n                    while (ast._Tokenizer._isIdentifierChar(this._get(i))) {\n                        i++;\n                    }\n                }\n                if (i > this._position) {\n                    const text = this._text.substring(this._position, i);\n                    let keyword = false;\n                    switch (text) {\n                        case 'and':\n                        case 'as':\n                        case 'else':\n                        case 'For':\n                        case 'If':\n                        case 'Import':\n                        case 'in':\n                        case 'is':\n                        case 'not':\n                        case 'or':\n                            keyword = true;\n                            break;\n                        default:\n                            break;\n                    }\n                    return { type: 'id', value: text, keyword };\n                }\n                return null;\n            }\n            _operator() {\n                let length = 0;\n                const c0 = this._get(this._position);\n                const c1 = this._get(this._position + 1);\n                const c2 = this._get(this._position + 2);\n                switch (c0) {\n                    case '+': case '&': case '|': case '^': case '=': case '!': case '%': case '~':\n                        length = c1 === '=' ? 2 : 1;\n                        break;\n                    case '-':\n                        length = c1 === '=' || c1 === '>' ? 2 : 1;\n                        break;\n                    case '*':\n                        switch (c1) {\n                            case '*': length = c2 === '=' ? 3 : 2; break;\n                            case '=': length = 2; break;\n                            default: length = 1; break;\n                        }\n                        break;\n                    case '/':\n                        switch (c1) {\n                            case '/': length = c2 === '=' ? 3 : 2; break;\n                            case '=': length = 2; break;\n                            default: length = 1; break;\n                        }\n                        break;\n                    case '<':\n                        switch (c1) {\n                            case '>': length = 2; break;\n                            case '<': length = c2 === '=' ? 3 : 2; break;\n                            case '=': length = 2; break;\n                            default: length = 1; break;\n                        }\n                        break;\n                    case '>':\n                        switch (c1) {\n                            case '>': length = c2 === '=' ? 3 : 2; break;\n                            case '=': length = 2; break;\n                            default: length = 1; break;\n                        }\n                        break;\n                    case '@':\n                        length = c1 === '=' ? 2 : 1;\n                        break;\n                    case ':':\n                        length = c1 === '=' ? 2 : 1;\n                        break;\n                    default:\n                        return null;\n                }\n                const text = this._text.substring(this._position, this._position + length);\n                return { type: text, value: text };\n            }\n            _string() {\n                let i = this._position;\n                let prefix = -1;\n                if (this._get(i) === \"'\" || this._get(i) === '\"') {\n                    prefix = '';\n                } else if (this._get(i + 1) === \"'\" || this._get(i + 1) === '\"') {\n                    const c = this._get(i);\n                    const cc = c.toLowerCase();\n                    if (cc === 'b' || cc === 'f' || cc === 'r' || cc === 'u') {\n                        prefix = c;\n                    }\n                } else if (this._get(i + 2) === \"'\" || this._get(i + 2) === '\"') {\n                    const c = this._text.substring(this._position, this._position + 2);\n                    const cc = c.toLowerCase();\n                    if (cc === 'br' || cc === 'fr' || cc === 'rb' || cc === 'rf' || cc === 'ur') {\n                        prefix = c;\n                    }\n                }\n                if (prefix.length >= 0) {\n                    i += prefix.length;\n                    let quote = '';\n                    let count = 0;\n                    const q0 = this._get(i);\n                    const q1 = this._get(i + 1);\n                    const q2 = this._get(i + 2);\n                    switch (q0) {\n                        case \"'\":\n                            quote = q0;\n                            count = (q1 === \"'\" && q2 === \"'\") ? 3 : 1;\n                            break;\n                        case '\"':\n                            quote = q0;\n                            count = (q1 === '\"' && q2 === '\"') ? 3 : 1;\n                            break;\n                        default:\n                            throw new python.Error(`Unsupported string quote '${q0}'.`);\n                    }\n                    i += count;\n                    if (count === 1) {\n                        while (i < this._text.length) {\n                            if (this._text[i] === quote) {\n                                return { type: 'str', value: this._text.substring(this._position, i + 1) };\n                            } else if (this._text[i] === '\\\\' &&\n                                     (this._get(i + 1) === quote || this._get(i + 1) === '\\n' || this._get(i + 1) === '\\\\')) {\n                                i += 2;\n                            } else if (this._text[i] === '\\r' || this._text[i] === '\\n') {\n                                break;\n                            } else {\n                                i++;\n                            }\n                        }\n                    } else if (count === 3) {\n                        while (i < this._text.length) {\n                            if (this._get(i) === quote && this._get(i + 1) === quote && this._get(i + 2) === quote) {\n                                return { type: 'str', value: this._text.substring(this._position, i + 3) };\n                            } else if (this._get(i) === '\\\\' && this._get(i + 1) === quote) {\n                                i += 2;\n                                continue;\n                            }\n                            i++;\n                        }\n                    }\n                }\n                i = this._position;\n                if (this._get(i) === '`') {\n                    i++;\n                    while (i < this._text.length) {\n                        if (this._text[i] === '`') {\n                            return { type: 'str', value: this._text.substring(this._position, i + 1) };\n                        }\n                        i++;\n                    }\n                }\n                return null;\n            }\n        });\n        this.registerType('builtins.dict', dict);\n        this.registerType('builtins.ellipsis', class {});\n        this.registerType('builtins.cell', class {});\n        this.registerType('builtins.list', class extends Array {\n            constructor(iterable) {\n                super();\n                if (Array.isArray(iterable)) {\n                    this.push(...iterable);\n                }\n            }\n            append(item) {\n                this.push(item);\n            }\n            extend(items) {\n                this.push(...items);\n            }\n        });\n        this.registerType('builtins.number', class {});\n        this.registerFunction('builtins.__import__', (name, globals, locals, fromlist, level) => {\n            return execution.__import__(name, globals, locals, fromlist, level);\n        });\n        this.registerType('builtins.bool', class extends Boolean {\n            constructor(value) {\n                if (value && value.__bool__) {\n                    value = value.__bool__();\n                } else if (value && value.__len__) {\n                    value = value.__len__() > 0;\n                } else {\n                    value = value ? true : false;\n                }\n                super(value);\n            }\n        });\n        this.registerType('builtins.int', class extends Number {\n            constructor(value) {\n                if (value && value.__int__) {\n                    value = value.__int__();\n                } else if (!Number.isInteger(value)) {\n                    value = NaN;\n                }\n                super(value);\n            }\n        });\n        this.registerType('builtins.float', class extends Number {\n            constructor(value) {\n                if (value && value.__float__) {\n                    value = value.__float__();\n                } else if (Number(value) !== value) {\n                    value = NaN;\n                }\n                super(value);\n            }\n        });\n        this.registerType('builtins.long', class extends Number {\n            constructor(value) {\n                if (value && value.__int__) {\n                    value = value.__int__();\n                } else if (!Number.isInteger(value)) {\n                    value = NaN;\n                }\n                super(value);\n            }\n        });\n        this.registerType('builtins.str', class extends String {\n            constructor(value) {\n                if (value && value.__str__) {\n                    value = value.__str__();\n                } else if (typeof value !== 'string') {\n                    value = JSON.stringify(value);\n                }\n                super(value);\n            }\n        });\n        this.registerType('builtins.complex', class {\n            constructor(real, imaginary) {\n                this.real = real;\n                this.imag = imaginary;\n            }\n            toString() {\n                return `${this.real}${this.imag < 0 ? '' : '+'}${this.imag}j`;\n            }\n        });\n        this.registerType('builtins.NoneType', class {});\n        this.registerType('builtins.object', class {\n            static __new__(cls, ...args) {\n                return execution.invoke(cls, args);\n            }\n            static __setattr__(obj, name, value) {\n                builtins.setattr(obj, name, value);\n            }\n        });\n        this.registerType('builtins.tuple', class extends Array {\n            constructor(items) {\n                super(items ? items.length : 0);\n                if (items) {\n                    for (let i = 0; i < items.length; i++) {\n                        this[i] = items[i];\n                    }\n                }\n            }\n        });\n        this.registerType('builtins.staticmethod', class {});\n        this.registerType('builtins.Warning', class {});\n        this.registerType('builtins.FutureWarning', class extends builtins.Warning {});\n        this.registerType('builtins.BaseException', class {});\n        this.registerType('builtins.Exception', class extends builtins.BaseException {});\n        this.registerType('builtins.AttributeError', class extends builtins.Exception {});\n        this.registerType('builtins.SyntaxError', class extends builtins.Exception {});\n        this.registerFunction('builtins.print', () => {});\n        this.registerFunction('builtins.unicode');\n        builtins.Ellipsis = new builtins.ellipsis();\n        this.registerType('typing._Final', class {});\n        this.registerType('typing._SpecialForm', class extends typing._Final {});\n        this.registerType('typing._BaseGenericAlias', class extends typing._Final {});\n        this.registerType('typing._GenericAlias', class extends typing._BaseGenericAlias {});\n        this.registerType('typing._SpecialGenericAlias', class extends typing._BaseGenericAlias {});\n        this.registerType('typing._TupleType', class extends typing._SpecialGenericAlias {});\n        this.registerType('typing._CallableType', class {});\n        this.registerFunction('typing.cast');\n        typing.Any = Reflect.construct(typing._SpecialForm, []);\n        typing.Callable = Reflect.construct(typing._CallableType, []);\n        typing.Dict = Reflect.construct(typing._SpecialGenericAlias, []);\n        typing.List = Reflect.construct(typing._SpecialGenericAlias, []);\n        typing.Optional = Reflect.construct(typing._SpecialForm, []);\n        typing.OrderedDict = Reflect.construct(typing._SpecialGenericAlias, []);\n        typing.Sequence = Reflect.construct(typing._SpecialGenericAlias, []);\n        typing.Tuple = Reflect.construct(typing._TupleType, []);\n        typing.Union = Reflect.construct(typing._SpecialForm, []);\n        this.registerType('enum.Enum', class {\n            // __reduce_ex__(proto) {\n            //    return self.__class__, (self._value_, )\n            // }\n        });\n        this.registerFunction('operator.add');\n        this.registerFunction('operator.and_');\n        this.registerFunction('operator.and_');\n        this.registerFunction('operator.eq');\n        this.registerFunction('operator.floordiv');\n        this.registerFunction('operator.ge');\n        this.registerFunction('operator.getitem');\n        this.registerFunction('operator.gt');\n        this.registerFunction('operator.le');\n        this.registerFunction('operator.lt');\n        this.registerFunction('operator.mod');\n        this.registerFunction('operator.mul');\n        this.registerFunction('operator.ne');\n        this.registerFunction('operator.neg');\n        this.registerFunction('operator.or_');\n        this.registerFunction('operator.pos');\n        this.registerFunction('operator.pow');\n        this.registerFunction('operator.sub');\n        this.registerFunction('operator.truediv');\n        this.registerFunction('sys.path.append', () => {});\n        this.registerFunction('sys.path.insert', () => {});\n        this.registerType('argparse.Namespace', class {\n            constructor(args) {\n                this.args = args;\n            }\n        });\n        this.registerType('catboost._catboost._CatBoost', class {\n            _deserialize_model(serialized_model_str) {\n                const src = serialized_model_str;\n                const data = new Uint8Array(src.buffer.slice(src.byteOffset + 8, src.byteOffset + src.byteLength));\n                const reader = this.flatbuffers.BinaryReader.open(data);\n                this._core = this.schema.NCatBoostFbs.TModelCore.create(reader);\n            }\n            _get_format_version() {\n                return this._core.FormatVersion;\n            }\n            _get_info_map() {\n                const map = new Map();\n                if (this._core.InfoMap) {\n                    for (const entry of this._core.InfoMap) {\n                        if (entry.Key && entry.Value) {\n                            map.set(entry.Key, entry.Value);\n                        }\n                    }\n                }\n                return map;\n            }\n            _get_tree_count() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.TreeSizes ? trees.TreeSizes.length : 0;\n            }\n            _get_feature_names() {\n                const trees = this._core.ModelTrees;\n                if (!trees) {\n                    return [];\n                }\n                const names = [];\n                for (const list of [trees.FloatFeatures, trees.CatFeatures, trees.TextFeatures, trees.EmbeddingFeatures]) {\n                    if (list) {\n                        for (const feature of list) {\n                            names.push(feature.FeatureId || `feature_${feature.FlatIndex}`);\n                        }\n                    }\n                }\n                return names;\n            }\n            _get_float_features() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.FloatFeatures ? trees.FloatFeatures : [];\n            }\n            _get_cat_features() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.CatFeatures ? trees.CatFeatures : [];\n            }\n            _get_text_features() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.TextFeatures ? trees.TextFeatures : [];\n            }\n            _get_embedding_features() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.EmbeddingFeatures ? trees.EmbeddingFeatures : [];\n            }\n            _get_leaf_values() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.LeafValues ? trees.LeafValues : [];\n            }\n            _get_leaf_weights() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.LeafWeights ? trees.LeafWeights : [];\n            }\n            _get_scale_and_bias() {\n                const trees = this._core.ModelTrees;\n                return trees ? [trees.Scale, trees.Bias] : [1, 0];\n            }\n            _get_tree_splits() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.TreeSplits ? trees.TreeSplits : [];\n            }\n            _get_tree_sizes() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.TreeSizes ? trees.TreeSizes : [];\n            }\n            _get_tree_start_offsets() {\n                const trees = this._core.ModelTrees;\n                return trees && trees.TreeStartOffsets ? trees.TreeStartOffsets : [];\n            }\n            _get_borders() {\n                const features = this._get_float_features();\n                const borders = [];\n                for (const feature of features) {\n                    borders.push(feature.Borders ? Array.from(feature.Borders) : []);\n                }\n                return borders;\n            }\n        });\n        this.registerType('catboost.core._CatBoostBase', class {\n            constructor() {\n                this._object = new catboost._catboost._CatBoost();\n            }\n            __setstate__(state) {\n                for (const [key, value] of state) {\n                    this[key] = value;\n                }\n            }\n            _load_from_string(dump_model_str) {\n                this._deserialize_model(dump_model_str);\n            }\n            _deserialize_model(dump_model_str) {\n                this._object._deserialize_model(dump_model_str);\n            }\n        });\n        this.registerType('catboost.core.CatBoost', class extends catboost.core._CatBoostBase {\n            load_model(blob) {\n                this._load_from_string(blob || this.__model);\n            }\n        });\n        this.registerType('catboost.core.CatBoostClassifier', class extends catboost.core.CatBoost {});\n        this.registerType('catboost.core.CatBoostRegressor', class extends catboost.core.CatBoost {});\n        catboost.CatBoostClassifier = catboost.core.CatBoostClassifier;\n        catboost.CatBoostRegressor = catboost.core.CatBoostRegressor;\n        catboost.CatBoost = catboost.core.CatBoost;\n        this.registerType('autogluon.tabular.models.catboost.catboost_model.CatBoostModel', class {});\n        this.registerType('autogluon.core.metrics._PredictScorer', class {});\n        this.registerType('autogluon.common.features.feature_metadata.FeatureMetadata', class {});\n        this.registerType('collections.deque', class extends Array {\n            constructor(iterable) {\n                super();\n                if (Array.isArray(iterable)) {\n                    for (const value of iterable) {\n                        this.push(value);\n                    }\n                }\n            }\n            append(item) {\n                this.push(item);\n            }\n            extend(items) {\n                this.push(...items);\n            }\n        });\n        this.registerType('collections.OrderedDict', class extends dict {});\n        this.registerType('cuml.common.array_descriptor.CumlArrayDescriptorMeta', class {});\n        this.registerType('cuml.ensemble.randomforestclassifier.RandomForestClassifier', class {});\n        this.registerType('cuml.internals.array.CumlArray', class {});\n        this.registerType('cuml.internals.mem_type.MemoryType', class {});\n        this.registerType('cuml.raft.common.handle.Handle', class {\n            __setstate__(state) {\n                this._handle = state;\n            }\n        });\n        this.registerType('cuml.svm.svr.SVR', class {});\n        this.registerType('datetime.date', class {});\n        this.registerType('datetime.datetime', class extends datetime.date {});\n        this.registerType('datetime.timedelta', class {});\n        this.registerType('datetime.tzinfo', class {});\n        this.registerType('datetime.timezone', class extends datetime.tzinfo {});\n        this.registerType('dnnlib.tflib.network.Network', class {});\n        this.registerType('dnnlib.util.EasyDict', class extends dict {});\n        this.registerType('haiku._src.data_structures.FlatMapping', class {\n            constructor(dict) {\n                Object.assign(this, dict);\n            }\n        });\n        this.registerType('haiku._src.data_structures.frozendict', class {\n            constructor(obj) {\n                Object.assign(this, obj);\n            }\n        });\n        this.registerType('hmmlearn.hmm.GaussianHMM', class {});\n        this.registerType('hmmlearn.hmm.GMMHMM', class {});\n        this.registerType('hmmlearn.hmm.MultinomialHMM', class {});\n        this.registerType('hmmlearn.base.ConvergenceMonitor', class {});\n        this.registerType('io.BytesIO', class {\n            constructor(buf, mode) {\n                this.mode = mode || 'r';\n                this._buf = this.mode === 'w' ? null : buf;\n                this._point = 0;\n            }\n            seek(offset) {\n                if (this._buf.seek) {\n                    this._buf.seek(offset);\n                }\n                this._point = offset;\n            }\n            read(size, stream) {\n                if (this._buf.stream && stream) {\n                    return this._buf.stream(size);\n                }\n                if (this._buf.peek) {\n                    return this._buf.read(size);\n                }\n                if (this._buf instanceof Uint8Array) {\n                    const start = this._point;\n                    this._point = size === undefined ? this._buf.length : start + size;\n                    return this._buf.subarray(start, this._point);\n                }\n                throw new python.Error('Unsupported buffer type.');\n            }\n            write(data) {\n                const src = this._buf || new Uint8Array();\n                const end = this._point + data.length;\n                const size = Math.max(src.length, end);\n                this._buf = new Uint8Array(size);\n                this._buf.set(src, 0);\n                this._buf.set(data, this._point);\n                this._point = end;\n            }\n            getbuffer() {\n                return new builtins.memoryview(this._buf);\n            }\n        });\n        this.registerType('io.StringIO', class {\n            constructor() {\n                this._buf = [];\n            }\n            write(text) {\n                this._buf.push(text);\n            }\n            toString() {\n                return this._buf.join('');\n            }\n        });\n        this.registerType('numpy.dtype', class {\n            constructor(obj, align, copy) {\n                if (typeof obj !== 'string' && obj && Array.isArray(obj.names)) {\n                    this.kind = 'V';\n                    this.byteorder = '|';\n                    this.itemsize = obj.itemsize;\n                    this.names = obj.names;\n                    this.fields = new Map();\n                    for (let i = 0; i < obj.names.length; i++) {\n                        this.fields.set(obj.names[i], new builtins.tuple([obj.formats[i], obj.offsets[i]]));\n                    }\n                    return;\n                }\n                if (typeof obj === 'string' && (obj.startsWith('<') || obj.startsWith('>') || obj.startsWith('|'))) {\n                    this.byteorder = obj.substring(0, 1);\n                    obj = obj.substring(1);\n                } else {\n                    this.byteorder = '=';\n                }\n                switch (obj) {\n                    case 'b1': case 'bool': this.itemsize = 1; this.kind = 'b'; break;\n                    case 'i1': case 'int8': this.itemsize = 1; this.kind = 'i'; break;\n                    case 'i2': case 'int16': this.itemsize = 2; this.kind = 'i'; break;\n                    case 'i4': case 'int32': this.itemsize = 4; this.kind = 'i'; break;\n                    case 'i8': case 'int64': case 'int': this.itemsize = 8; this.kind = 'i'; break;\n                    case 'u1': case 'uint8': this.itemsize = 1; this.kind = 'u'; break;\n                    case 'u2': case 'uint16': this.itemsize = 2; this.kind = 'u'; break;\n                    case 'u4': case 'uint32': this.itemsize = 4; this.kind = 'u'; break;\n                    case 'u8': case 'uint64': case 'uint': this.itemsize = 8; this.kind = 'u'; break;\n                    case 'f1': case 'float8_e5m2': this.itemsize = 1; this.kind = 'f'; break;\n                    case 'f2': case 'float16': this.itemsize = 2; this.kind = 'f'; break;\n                    case 'f4': case 'float32': this.itemsize = 4; this.kind = 'f'; break;\n                    case 'f8': case 'float64': case 'float': this.itemsize = 8; this.kind = 'f'; break;\n                    case 'c8': case 'complex64': this.itemsize = 8; this.kind = 'c'; break;\n                    case 'c16': case 'complex128': case 'complex': this.itemsize = 16; this.kind = 'c'; break;\n                    case 'M8': case 'M': this.itemsize = 8; this.kind = 'M'; break;\n                    case 'm8': case 'm': this.itemsize = 8; this.kind = 'm'; break;\n                    case 'V': case 'void': this.itemsize = 0; this.kind = 'V'; break;\n                    default:\n                        if (obj.startsWith('V')) {\n                            this.itemsize = parseInt(obj.substring(1), 10);\n                            this.kind = 'V';\n                        } else if (obj.startsWith('O')) {\n                            this.itemsize = obj === 'O' ? 8 : parseInt(obj.substring(1), 10);\n                            this.kind = 'O';\n                        } else if (obj.startsWith('S')) {\n                            this.itemsize = parseInt(obj.substring(1), 10);\n                            this.kind = 'S';\n                        } else if (obj.startsWith('U')) { // Unicode string\n                            this.kind = 'U';\n                            this.itemsize = 4 * parseInt(obj.substring(1), 10);\n                        } else if (obj.startsWith('T')) {\n                            this.kind = 'T';\n                            this.itemsize = parseInt(obj.substring(1), 10);\n                        } else {\n                            throw new python.Error(`Unsupported dtype '${obj}'.`);\n                        }\n                        break;\n                }\n                if (align) {\n                    this.align = align;\n                }\n                if (copy) {\n                    this.copy = copy;\n                }\n            }\n            get str() {\n                return (this.byteorder === '=' ? '<' : this.byteorder) + this.kind + this.itemsize.toString();\n            }\n            get name() {\n                switch (this.kind) {\n                    case 'V': return `void${this.itemsize === 0 ? '' : (this.itemsize * 8)}`;\n                    case 'S': return `bytes${this.itemsize === 0 ? '' : (this.itemsize * 8)}`;\n                    case 'U': return `str${this.itemsize === 0 ? '' : (this.itemsize * 8)}`;\n                    case 'T': return `StringDType${this.itemsize === 0 ? '' : (this.itemsize * 8)}`;\n                    case 'M': return 'datetime64';\n                    case 'm': return 'timedelta64';\n                    case 'b': return 'bool';\n                    default: return this.__name__;\n                }\n            }\n            __setstate__(state) {\n                switch (state.length) {\n                    case 8:\n                        [\n                            this.version, this.byteorder, this.subarray, this.names,\n                            this.fields, this.elsize, this.alignment, this.int_dtypeflags\n                        ] = state;\n                        break;\n                    case 9:\n                        [\n                            this.version, this.byteorder, this.subarray, this.names,\n                            this.fields, this.elsize, this.alignment, this.int_dtypeflags,\n                            this.metadata\n                        ] = state;\n                        break;\n                    default:\n                        throw new python.Error(`Unsupported numpy.dtype setstate length '${state.length}'.`);\n                }\n            }\n            get __name__() {\n                switch (this.kind) {\n                    case 'b':\n                        switch (this.itemsize) {\n                            case 1: return 'boolean';\n                            default: throw new python.Error(`Unsupported boolean itemsize '${this.itemsize}'.`);\n                        }\n                    case 'i':\n                        switch (this.itemsize) {\n                            case 1: return 'int8';\n                            case 2: return 'int16';\n                            case 4: return 'int32';\n                            case 8: return 'int64';\n                            default: throw new python.Error(`Unsupported int itemsize '${this.itemsize}'.`);\n                        }\n                    case 'u':\n                        switch (this.itemsize) {\n                            case 1: return 'uint8';\n                            case 2: return 'uint16';\n                            case 4: return 'uint32';\n                            case 8: return 'uint64';\n                            default: throw new python.Error(`Unsupported uint itemsize '${this.itemsize}'.`);\n                        }\n                    case 'f':\n                        switch (this.itemsize) {\n                            case 1: return 'float8e5m2';\n                            case 2: return 'float16';\n                            case 4: return 'float32';\n                            case 8: return 'float64';\n                            default: throw new python.Error(`Unsupported float itemsize '${this.itemsize}'.`);\n                        }\n                    case 'c':\n                        switch (this.itemsize) {\n                            case 8: return 'complex<float32>';\n                            case 16: return 'complex<float64>';\n                            default: throw new python.Error(`Unsupported complex itemsize '${this.itemsize}'.`);\n                        }\n                    case 'S':\n                    case 'T':\n                        return 'string';\n                    case 'U':\n                        return 'string';\n                    case 'M':\n                        return 'datetime';\n                    case 'm':\n                        return 'timedelta';\n                    case 'O':\n                        return 'object';\n                    case 'V':\n                        return 'void';\n                    default:\n                        throw new python.Error(`Unsupported dtype kind '${this.kind}'.`);\n                }\n            }\n        });\n        this.registerType('numpy.generic', class {});\n        this.registerType('numpy.inexact', class {});\n        this.registerType('numpy.flexible', class extends numpy.generic {});\n        this.registerType('numpy.void', class extends numpy.flexible {});\n        this.registerType('numpy.bool_', class extends numpy.generic {});\n        this.registerType('numpy.number', class extends numpy.generic {});\n        this.registerType('numpy.integer', class extends numpy.number {});\n        this.registerType('numpy.floating', class extends numpy.inexact {});\n        this.registerType('numpy.float16', class extends numpy.floating {});\n        this.registerType('numpy.float32', class extends numpy.floating {});\n        this.registerType('numpy.float64', class extends numpy.floating {});\n        this.registerType('numpy.signedinteger', class extends numpy.integer {});\n        this.registerType('numpy.int8', class extends numpy.signedinteger {});\n        this.registerType('numpy.int16', class extends numpy.signedinteger {});\n        this.registerType('numpy.int32', class extends numpy.signedinteger {});\n        this.registerType('numpy.int64', class extends numpy.signedinteger {});\n        this.registerType('numpy.unsignedinteger', class extends numpy.integer {});\n        this.registerType('numpy.uint8', class extends numpy.unsignedinteger {});\n        this.registerType('numpy.uint16', class extends numpy.unsignedinteger {});\n        this.registerType('numpy.uint32', class extends numpy.unsignedinteger {});\n        this.registerType('numpy.uint64', class extends numpy.unsignedinteger {});\n        this.registerType('numpy.datetime64', class extends numpy.generic {\n            constructor(...args) {\n                super();\n                if (args.length === 1 && args[0] instanceof Uint8Array) {\n                    [this.buffer] = args;\n                }\n            }\n            toString() {\n                const view = new DataView(this.buffer.buffer, this.buffer.byteOffset, 8);\n                const value = view.getBigInt64(0, true);\n                if (value === -9223372036854775808n) {\n                    return 'NaT';\n                }\n                const date = new Date(Number(value / 1000000n));\n                return date.toISOString().slice(0, -1);\n            }\n        });\n        this.registerType('numpy.dtypes.StringDType', class extends numpy.dtype {\n            constructor() {\n                super('|T16');\n            }\n        });\n        this.registerType('gensim.models.doc2vec.Doctag', class {});\n        this.registerType('gensim.models.doc2vec.Doc2Vec', class {});\n        this.registerType('gensim.models.doc2vec.Doc2VecTrainables', class {});\n        this.registerType('gensim.models.doc2vec.Doc2VecVocab', class {});\n        this.registerType('gensim.models.fasttext.FastText', class {});\n        this.registerType('gensim.models.fasttext.FastTextTrainables', class {});\n        this.registerType('gensim.models.fasttext.FastTextVocab', class {});\n        this.registerType('gensim.models.fasttext.FastTextKeyedVectors', class {});\n        this.registerType('gensim.models.keyedvectors.Doc2VecKeyedVectors', class {});\n        this.registerType('gensim.models.keyedvectors.FastTextKeyedVectors', class {});\n        this.registerType('gensim.models.keyedvectors.KeyedVectors', class {});\n        this.registerType('gensim.models.keyedvectors.Vocab', class {});\n        this.registerType('gensim.models.keyedvectors.Word2VecKeyedVectors', class {});\n        this.registerType('gensim.models.ldamodel.LdaState', class {});\n        this.registerType('gensim.models.ldamulticore.LdaMulticore', class {});\n        this.registerFunction('gensim.models.phrases.original_scorer');\n        this.registerType('gensim.models.phrases.Phraser', class {});\n        this.registerType('gensim.models.phrases.Phrases', class {});\n        this.registerType('gensim.models.tfidfmodel.TfidfModel', class {});\n        this.registerType('gensim.models.word2vec.Vocab', class {});\n        this.registerType('gensim.models.word2vec.Word2Vec', class {});\n        this.registerType('gensim.models.word2vec.Word2VecTrainables', class {});\n        this.registerType('gensim.models.word2vec.Word2VecVocab', class {});\n        this.registerFunction('gensim.models.tfidfmodel.df2idf');\n        this.registerFunction('gensim.utils.call_on_class_only', () => {\n            throw new builtins.AttributeError('This method should be called on a class object.');\n        });\n        this.registerFunction('gensim.utils.identity');\n        this.registerType('google3.learning.deepmind.research.nbr.pbl_jax.clean_jaxline.utils.optimizers.ScaleByLarsState', class {\n            constructor(obj) {\n                Object.assign(this, obj);\n            }\n        });\n        this.registerType('joblib._store_backends.FileSystemStoreBackend', class {});\n        this.registerType('joblib.memory.NotMemorizedFunc', class {});\n        this.registerType('joblib.numpy_pickle.NumpyArrayWrapper', class {\n\n            __read__(unpickler) {\n                if (this.dtype.__name__ === 'object') {\n                    return unpickler.load();\n                }\n                if (this.numpy_array_alignment_bytes) {\n                    const [size] = unpickler.read(1);\n                    unpickler.read(size);\n                }\n                const size = this.dtype.itemsize * this.shape.reduce((a, b) => a * b, 1);\n                this.data = unpickler.read(size);\n                return new this.subclass(this.shape, this.dtype, this.data, undefined, undefined, this.order);\n            }\n        });\n        this.registerType('joblib.numpy_pickle.NDArrayWrapper', class {\n\n            __setstate__(state) {\n                this.subclass = state.get('subclass');\n                this.filename = state.get('state');\n                this.allow_mmap = state.get('allow_mmap');\n            }\n            __read__(/* unpickler */) {\n                return this; // return execution.invoke(this.subclass, [ this.shape, this.dtype, this.data ]);\n            }\n        });\n        sklearn.externals.joblib.numpy_pickle.NDArrayWrapper = joblib.numpy_pickle.NDArrayWrapper;\n        sklearn.externals.joblib.numpy_pickle.NumpyArrayWrapper = joblib.numpy_pickle.NumpyArrayWrapper;\n        this.registerType('keras.engine.sequential.Sequential', class {});\n        this.registerType('keras.src.legacy.preprocessing.text.Tokenizer', class {});\n        this.registerType('lasagne.layers.conv.Conv2DLayer', class {});\n        this.registerType('lasagne.layers.dense.DenseLayer', class {});\n        this.registerType('lasagne.layers.input.InputLayer', class {});\n        this.registerType('lasagne.layers.pool.MaxPool2DLayer', class {});\n        this.registerType('lightgbm.sklearn.LGBMRegressor', class {});\n        this.registerType('lightgbm.sklearn.LGBMClassifier', class {});\n        this.registerType('lightgbm.basic.Booster', class {\n            constructor() {\n                this.average_output = false;\n                this.models = [];\n                this.loaded_parameter = '';\n            }\n            __setstate__(state) {\n                const model_str = state.get('_handle', state.get('handle', null));\n                if (model_str) {\n                    this.LoadModelFromString(model_str);\n                    return;\n                }\n                for (const [key, value] of state) {\n                    this[key] = value;\n                }\n            }\n            LoadModelFromString(model_str) {\n                const lines = model_str.split('\\n');\n                const signature = lines.shift() || '?';\n                if (signature.trim() !== 'tree') {\n                    throw new python.Error(`Invalid signature '${signature.trim()}'.`);\n                }\n                // GBDT::LoadModelFromString() in https://github.com/microsoft/LightGBM/blob/master/src/boosting/gbdt_model_text.cpp\n                const key_vals = new Map();\n                while (lines.length > 0 && !lines[0].startsWith('Tree=')) {\n                    const cur_line = lines.shift().trim();\n                    if (cur_line.length > 0) {\n                        const strs = cur_line.split('=');\n                        if (strs.length === 1) {\n                            key_vals.set(strs[0], '');\n                        } else if (strs.length === 2) {\n                            key_vals.set(strs[0], strs[1]);\n                        } else if (strs.length > 2) {\n                            if (strs[0] === \"feature_names\") {\n                                key_vals.set(strs[0], cur_line.substring(\"feature_names=\".length));\n                            } else if (strs[0] === 'monotone_constraints') {\n                                key_vals.set(strs[0], cur_line.substring('monotone_constraints='.length));\n                            } else {\n                                throw new python.Error(`Wrong line: ${cur_line.substring(0, Math.min(128, cur_line.length))}`);\n                            }\n                        }\n                    }\n                }\n                const atoi = (key, value) => {\n                    if (key_vals.has(key)) {\n                        return parseInt(key_vals.get(key), 10);\n                    }\n                    if (value !== undefined) {\n                        return value;\n                    }\n                    throw new python.Error(`Model file does not specify ${key}.`);\n                };\n                const list = (key, size) => {\n                    if (key_vals.has(key)) {\n                        const value = key_vals.get(key).split(' ');\n                        if (value.length !== size) {\n                            throw new python.Error(`Wrong size of ${key}.`);\n                        }\n                        return value;\n                    }\n                    throw new python.Error(`Model file does not contain ${key}.`);\n                };\n                this.version = key_vals.get('version') || '';\n                this.num_class = atoi('num_class');\n                this.num_tree_per_iteration = atoi('num_tree_per_iteration', this.num_class);\n                this.label_index = atoi('label_index');\n                this.max_feature_idx = atoi('max_feature_idx');\n                if (key_vals.has('average_output')) {\n                    this.average_output = true;\n                }\n                this.feature_names = list('feature_names', this.max_feature_idx + 1);\n                this.feature_infos = list('feature_infos', this.max_feature_idx + 1);\n                if (key_vals.has('monotone_constraints')) {\n                    this.monotone_constraints = list('monotone_constraints', this.max_feature_idx + 1);\n                }\n                if (key_vals.has('objective')) {\n                    this.objective = key_vals.get('objective');\n                }\n                let tree = null;\n                while (lines.length > 0) {\n                    const text = lines.shift();\n                    const line = text.trim();\n                    if (line.length === 0) {\n                        continue;\n                    }\n                    if (line.startsWith('Tree=')) {\n                        tree = { index: parseInt(line.split('=').pop(), 10) };\n                        this.models.push(tree);\n                        continue;\n                    }\n                    if (line === 'end of trees') {\n                        break;\n                    }\n                    const param = line.split('=');\n                    if (param.length !== 2) {\n                        throw new python.Error(`Invalid property '${line}'.`);\n                    }\n                    const name = param[0].trim();\n                    const value = param[1].trim();\n                    tree[name] = value;\n                }\n                const ss = [];\n                let is_inparameter = false;\n                while (lines.length > 0) {\n                    const text = lines.shift();\n                    const line = text.trim();\n                    if (line === 'parameters:') {\n                        is_inparameter = true;\n                        continue;\n                    } else if (line === 'end of parameters') {\n                        break;\n                    } else if (is_inparameter) {\n                        ss.push(line);\n                    }\n                }\n                if (ss.length > 0) {\n                    this.loaded_parameter = ss.join('\\n');\n                }\n            }\n        });\n        this.registerFunction('megengine.functional.elemwise.clip', () => {});\n        this.registerFunction('megengine.functional.elemwise.sqrt', () => {});\n        this.registerFunction('megengine.functional.nn.conv2d', () => {});\n        this.registerFunction('megengine.functional.nn.relu', () => {});\n        this.registerFunction('megengine.functional.nn.sigmoid', () => {});\n        this.registerFunction('megengine.functional.tensor.arange', () => {});\n        this.registerFunction('megengine.functional.tensor.broadcast_to', () => {});\n        this.registerFunction('megengine.functional.tensor.concat', () => {});\n        this.registerFunction('megengine.functional.tensor.expand_dims', () => {});\n        this.registerFunction('megengine.functional.tensor.flatten', () => {});\n        this.registerFunction('megengine.functional.tensor.full', () => {});\n        this.registerFunction('megengine.functional.tensor.reshape', () => {});\n        this.registerFunction('megengine.functional.tensor.split', () => {});\n        this.registerFunction('megengine.functional.tensor.stack', () => {});\n        this.registerFunction('megengine.functional.tensor.transpose', () => {});\n        this.registerFunction('megengine.functional.vision.interpolate', () => {});\n        this.registerFunction('megengine.module.qat.module.QATModule._apply_fakequant_with_observer', () => {});\n        this.registerType('megengine.core._imperative_rt.common.CompNode', class {});\n        this.registerType('megengine.core._imperative_rt.ops.ElemwiseMultiType', class {});\n        this.registerType('megengine.core._imperative_rt.ops.FakeQuant', class {});\n        this.registerType('megengine.core._imperative_rt.ops.GetVarShape', class {});\n        this.registerType('megengine.core._imperative_rt.ops.Resize', class {});\n        this.registerType('megengine.core.ops._internal.param_defs.ConvolutionV0.Mode', class {});\n        this.registerType('megengine.core.ops._internal.param_defs.Convolution.ComputeMode', class {});\n        this.registerType('megengine.distributed.group.Group', class {});\n        this.registerType('megengine.module.activation.ReLU', class {});\n        this.registerType('megengine.module.activation.Softmax', class {});\n        this.registerType('megengine.module.adaptive_pooling.AdaptiveAvgPool2d', class {});\n        this.registerType('megengine.module.batchnorm.BatchNorm1d', class {});\n        this.registerType('megengine.module.batchnorm.BatchNorm2d', class {});\n        this.registerType('megengine.module.conv.Conv2d', class {});\n        this.registerType('megengine.module.conv.ConvTranspose2d', class {});\n        this.registerType('megengine.module.conv_bn.ConvBn2d', class {});\n        this.registerType('megengine.module.dropout.Dropout', class {});\n        this.registerType('megengine.module.identity.Identity', class {});\n        this.registerType('megengine.module.linear.Linear', class {});\n        this.registerType('megengine.module.module.Module', class {});\n        this.registerType('megengine.module.normalization.InstanceNorm', class {});\n        this.registerType('megengine.module.normalization.GroupNorm', class {});\n        this.registerType('megengine.module.normalization.LayerNorm', class {});\n        this.registerType('megengine.module.pooling.AvgPool2d', class {});\n        this.registerType('megengine.module.pooling.MaxPool2d', class {});\n        this.registerType('megengine.module.qat.concat.Concat', class {});\n        this.registerType('megengine.module.qat.elemwise.Elemwise', class {});\n        this.registerType('megengine.module.sequential.Sequential', class {});\n        this.registerType('megengine.quantization.fake_quant.FakeQuantize', class {});\n        this.registerType('megengine.quantization.fake_quant.LSQ', class {});\n        this.registerType('megengine.quantization.fake_quant.TQT', class {});\n        this.registerType('megengine.quantization.utils.QParams', class {});\n        this.registerType('megengine.quantization.utils.QuantMode', class {});\n        this.registerType('megengine.quantization.observer.ExponentialMovingAverageObserver', class {});\n        this.registerType('megengine.quantization.observer.HistogramObserver', class {});\n        this.registerType('megengine.quantization.observer.MinMaxObserver', class {});\n        this.registerType('megengine.quantization.observer.PassiveObserver', class {});\n        this.registerType('megengine.quantization.observer.SyncExponentialMovingAverageObserver', class {});\n        this.registerType('megengine.quantization.observer.SyncMinMaxObserver', class {});\n        this.registerType('megengine.traced_module.expr.Apply', class {});\n        this.registerType('megengine.traced_module.expr.CallFunction', class {});\n        this.registerType('megengine.traced_module.expr.CallMethod', class {});\n        this.registerType('megengine.traced_module.expr.Constant', class {});\n        this.registerType('megengine.traced_module.expr.GetAttr', class {});\n        this.registerType('megengine.traced_module.expr.Input', class {});\n        this.registerType('megengine.traced_module.fake_quant.FakeQuantize', class {});\n        this.registerType('megengine.traced_module.node.ModuleNode', class {});\n        this.registerType('megengine.traced_module.node.NodeMixin', class {});\n        this.registerType('megengine.traced_module.node.TensorNode', class {});\n        this.registerType('megengine.traced_module.pytree.ArgsIndex', class {});\n        this.registerType('megengine.traced_module.serialization._ModuleState', class {});\n        this.registerType('megengine.traced_module.traced_module.InternalGraph', class {});\n        this.registerType('megengine.traced_module.traced_module.NameSpace', class {});\n        this.registerType('megengine.traced_module.traced_module.TracedModule', class {});\n        this.registerType('megengine.tensor.Parameter', class {\n            constructor(data, dtype, device) {\n                this.data = data;\n                this.dtype = dtype;\n                this.device = device;\n            }\n        });\n        this.registerType('megengine.traced_module.pytree.TreeDef', class {\n            toString() {\n                let content = '';\n                for (const child of this.children_defs) {\n                    content += `${child},`;\n                }\n                if (typeof this.type === \"string\") {\n                    return `${this.type.split(\".\").slice(-1)}(${content})`;\n                }\n                return `${this.type.__name__}(${content})`;\n            }\n        });\n        this.registerType('megengine.traced_module.pytree.LeafDef', class {\n            toString() {\n                let content = '';\n                if (this.const_val === null) {\n                    content += '[';\n                } else {\n                    content += this.const_val;\n                }\n                for (const t of Object.values(this.type)) {\n                    content += t.__name__;\n                }\n                content += ']';\n                return content;\n            }\n        });\n        this.registerType('megengine.tensor.Tensor', class {\n            constructor(data, dtype, device) {\n                this.data = data;\n                this.dtype = dtype;\n                this.device = device;\n            }\n        });\n        this.registerType('megengine.core.tensor.dtype.QuantDtypeMeta', class {\n            constructor(name, cname, np_dtype, qmin, qmax, is_signed) {\n                this.name = name;\n                this.cname = cname;\n                this.np_dtype = np_dtype;\n                this.qmin = qmin;\n                this.qmax = qmax;\n                this.is_signed = is_signed;\n            }\n        });\n        this.registerType('nolearn.lasagne.base.BatchIterator', class {});\n        this.registerType('nolearn.lasagne.base.Layers', class {});\n        this.registerType('nolearn.lasagne.base.NeuralNet', class {});\n        this.registerType('nolearn.lasagne.base.TrainSplit', class {});\n        this.registerType('nolearn.lasagne.handlers.PrintLayerInfo', class {});\n        this.registerType('nolearn.lasagne.handlers.PrintLog', class {});\n        this.registerType('numpy.ndarray', class {\n            constructor(shape, dtype, buffer, offset, strides, order) {\n                this.shape = shape;\n                this.dtype = dtype;\n                this.data = buffer === undefined ? null : buffer;\n                this.offset = offset === undefined ? 0 : offset;\n                this._strides = strides === undefined ? null : strides;\n                this.order = order === undefined ? null : order;\n                this.flags = {};\n                this._read();\n            }\n            static __new__(cls, shape, dtype, buffer, offset, strides, order) {\n                return new cls(shape, dtype, buffer, offset, strides, order);\n            }\n            __setstate__(state) {\n                [this.version, this.shape, this.dtype, this.flags.fn, this.data] = state;\n                this._read();\n            }\n            flatten() {\n                const size = this.shape.reduce((a, b) => a * b, 1);\n                const value = new numpy.ndarray([size], this.dtype, this.data, this.offset, this.strides, this.order);\n                value.flags = this.flags;\n                return value;\n            }\n            reshape(shape, order) {\n                return new numpy.ndarray(shape, this.dtype, this.data, this.offset, this.strides, order);\n            }\n            tobytes() {\n                return this.data;\n            }\n            tolist() {\n                if (this.shape.length < 0 || this.shape.length > 1) {\n                    throw new python.Error(`Unsupported shape '${JSON.stringify(this.shape)}'.`);\n                }\n                const size = this.shape.reduce((a, b) => a * b, 1);\n                const list = new Array(size);\n                switch (this.dtype.kind) {\n                    case 'U': {\n                        const data = new Uint32Array(new Uint8Array(this.data).buffer);\n                        const itemsize = this.dtype.itemsize >> 2;\n                        let offset = 0;\n                        for (let i = 0; i < size; i++) {\n                            const buffer = data.subarray(offset, offset + itemsize);\n                            const index = buffer.indexOf(0);\n                            list[i] = Array.from(index >= 0 ? buffer.subarray(0, index) : buffer).map((c) => String.fromCodePoint(c)).join('');\n                            offset += itemsize;\n                        }\n                        return list;\n                    }\n                    case 'S': {\n                        const data = this.data;\n                        const itemsize = this.dtype.itemsize;\n                        const decoder = new TextDecoder('utf-8');\n                        let offset = 0;\n                        for (let i = 0; i < size; i++) {\n                            const buffer = data.subarray(offset, offset + itemsize);\n                            const index = buffer.indexOf(0);\n                            list[i] = decoder.decode(index >= 0 ? buffer.subarray(0, index) : buffer);\n                            offset += itemsize;\n                        }\n                        return list;\n                    }\n                    case 'V': {\n                        const itemsize = this.dtype.itemsize;\n                        let offset = 0;\n                        for (let i = 0; i < size; i++) {\n                            list[i] = this.data.slice(offset, offset + itemsize);\n                            offset += itemsize;\n                        }\n                        return list;\n                    }\n                    case 'M': {\n                        const itemsize = this.dtype.itemsize;\n                        let offset = 0;\n                        for (let i = 0; i < size; i++) {\n                            const buffer = this.data.slice(offset, offset + itemsize);\n                            list[i] = new numpy.datetime64(buffer);\n                            offset += itemsize;\n                        }\n                        return list;\n                    }\n                    case 'T': {\n                        return this.data;\n                    }\n                    case 'O': {\n                        return this.data;\n                    }\n                    default: {\n                        throw new python.Error(`Type kind '${this.dtype.kind}' not implemented.`);\n                    }\n                }\n            }\n            get itemsize() {\n                return this.dtype.itemsize;\n            }\n            get size() {\n                return (this.shape || []).reduce((a, b) => a * b, 1);\n            }\n            get strides() {\n                if (!this._strides) {\n                    const shape = this.shape;\n                    const strides = new Array(shape.length);\n                    let stride = this.itemsize;\n                    if (this.order === 'F' || this.flags.fn) {\n                        for (let i = 0; i < shape.length; i++) {\n                            strides[i] = stride;\n                            stride *= shape[i];\n                        }\n                    } else {\n                        for (let i = shape.length - 1; i >= 0; i--) {\n                            strides[i] = stride;\n                            stride *= shape[i];\n                        }\n                    }\n                    return strides;\n                }\n                return this._strides;\n            }\n            _read() {\n                if (this.data) {\n                    const length = this.dtype.itemsize * this.size;\n                    if (typeof this.data === 'string') {\n                        this.data = this._unescape(this.data, length);\n                        if (this.data.length !== length) {\n                            throw new python.Error('Invalid string array data size.');\n                        }\n                    } else if (this.data.length !== length) {\n                        // throw new python.Error('Invalid array data size.');\n                    }\n                }\n            }\n            _unescape(token, size) {\n                const length = token.length;\n                const a = new Uint8Array(length);\n                if (size && size === length) {\n                    for (let p = 0; p < size; p++) {\n                        a[p] = token.charCodeAt(p);\n                    }\n                    return a;\n                }\n                let i = 0;\n                let o = 0;\n                while (i < length) {\n                    let c = token.charCodeAt(i++);\n                    if (c !== 0x5C || i >= length) {\n                        a[o++] = c;\n                    } else {\n                        c = token.charCodeAt(i++);\n                        switch (c) {\n                            case 0x27: a[o++] = 0x27; break; // '\n                            case 0x5C: a[o++] = 0x5C; break; // \\\\\n                            case 0x22: a[o++] = 0x22; break; // \"\n                            case 0x72: a[o++] = 0x0D; break; // \\r\n                            case 0x6E: a[o++] = 0x0A; break; // \\n\n                            case 0x74: a[o++] = 0x09; break; // \\t\n                            case 0x62: a[o++] = 0x08; break; // \\b\n                            case 0x58: // x\n                            case 0x78: { // X\n                                const xsi = i - 1;\n                                const xso = o;\n                                for (let xi = 0; xi < 2; xi++) {\n                                    if (i >= length) {\n                                        i = xsi;\n                                        o = xso;\n                                        a[o] = 0x5c;\n                                        break;\n                                    }\n                                    let c = token.charCodeAt(i++);\n                                    if (c >= 65 && c <= 70) {\n                                        c -= 55;\n                                    } else if (c >= 97 && c <= 102) {\n                                        c -= 87;\n                                    } else if (c >= 48 && c <= 57) {\n                                        c -= 48;\n                                    } else {\n                                        c = -1;\n                                    }\n                                    if (c === -1) {\n                                        i = xsi;\n                                        o = xso;\n                                        a[o] = 0x5c;\n                                        break;\n                                    }\n                                    a[o] = a[o] << 4 | c;\n                                }\n                                o++;\n                                break;\n                            }\n                            default:\n                                if (c < 48 || c > 57) { // 0-9\n                                    a[o++] = 0x5c;\n                                    a[o++] = c;\n                                } else {\n                                    i--;\n                                    const osi = i;\n                                    const oso = o;\n                                    for (let oi = 0; oi < 3; oi++) {\n                                        if (i >= length) {\n                                            i = osi;\n                                            o = oso;\n                                            a[o] = 0x5c;\n                                            break;\n                                        }\n                                        const od = token.charCodeAt(i++);\n                                        if (od < 48 || od > 57) {\n                                            i = osi;\n                                            o = oso;\n                                            a[o] = 0x5c;\n                                            break;\n                                        }\n                                        a[o] = a[o] << 3 | od - 48;\n                                    }\n                                    o++;\n                                }\n                                break;\n                        }\n                    }\n                }\n                return a.slice(0, o);\n            }\n        });\n        this.registerType('numpy.matrix', class extends numpy.ndarray {\n            static __new__(/* subtype, data, dtype, copy */) {\n                throw new python.Error(\"'numpy.matrix.__new__' not implemented.\");\n            }\n        });\n        numpy.matrixlib.defmatrix.matrix = numpy.matrix;\n        this.registerType('numpy.ma.core.MaskedArray', class extends numpy.ndarray {\n            constructor(data /*, mask, dtype, copy, subok, ndmin, fill_value, keep_mask, hard_mask, shrink, order */) {\n                super(data.shape, data.dtype, data.data);\n            }\n        });\n        this.registerType('numpy.core.memmap.memmap', class extends numpy.ndarray {});\n        this.registerType('pandas.core.arrays.categorical.Categorical', class {});\n        this.registerType('pandas.core.arrays.base.ExtensionArray', class {});\n        this.registerType('pandas.core.arrays.masked.BaseMaskedArray', class extends pandas.core.arrays.base.ExtensionArray {});\n        this.registerType('pandas.core.arrays.numeric.NumericArray', class extends pandas.core.arrays.masked.BaseMaskedArray {});\n        this.registerType('pandas.core.arrays.datetimes.DatetimeArray', class {\n            __setstate__(state) {\n                [this._dtype, this._ndarray] = state;\n                Object.assign(this, Object.fromEntries(state[2]));\n            }\n        });\n        this.registerType('pandas.core.arrays.timedeltas.TimedeltaArray', class {\n            __setstate__(state) {\n                [this._dtype, this._ndarray] = state;\n                Object.assign(this, Object.fromEntries(state[2]));\n            }\n        });\n        this.registerType('pandas.core.arrays.period.PeriodArray', class {\n            __setstate__(state) {\n                [this._dtype, this._ndarray] = state;\n                Object.assign(this, Object.fromEntries(state[2]));\n            }\n        });\n        this.registerType('pandas.core.arrays.interval.IntervalArray', class {});\n        this.registerType('pandas.core.arrays.integer.IntegerArray', class extends pandas.core.arrays.numeric.NumericArray {});\n        this.registerType('pandas.core.arrays.integer.Int64Dtype', class {});\n        this.registerType('pandas._libs.tslibs.dtypes.PeriodDtypeBase', class {});\n        this.registerType('pandas.core.dtypes.dtypes.PeriodDtype', class extends pandas._libs.tslibs.dtypes.PeriodDtypeBase {});\n        this.registerType('pandas.core.dtypes.dtypes.IntervalDtype', class {});\n        this.registerType('pandas.core.generic.Flags', class {});\n        this.registerType('pandas.core.generic.NDFrame', class {\n            constructor(data) {\n                this._internal_names = [\"_mgr\", \"_item_cache\", \"_cache\", \"_name\", \"_metadata\", \"_flags\"];\n                this._metadata = [];\n                builtins.object.__setattr__(self, \"_mgr\", data);\n                builtins.object.__setattr__(self, \"_attrs\", {});\n                builtins.object.__setattr__(self, \"_flags\", new pandas.core.generic.Flags(this, true));\n            }\n            __setstate__(state) {\n                if (state instanceof pandas.core.internals.managers.BlockManager) {\n                    this._mgr = state;\n                } else if (state instanceof builtins.dict) {\n                    if (state.__contains__('_data') && !state.__contains__('_mgr')) {\n                        state.__setitem__('_mgr', state.pop('_data'));\n                    }\n                    const typ = state.get('_typ');\n                    if (typ) {\n                        let attrs = state.get('_attrs', new builtins.dict());\n                        if (!attrs) {\n                            attrs = new builtins.dict();\n                        }\n                        builtins.object.__setattr__(this, '_attrs', attrs);\n                        const flags = state.get('_flags', new builtins.dict({ 'allows_duplicate_labels': true }));\n                        builtins.object.__setattr__(this, '_flags', new pandas.core.generic.Flags(this, flags));\n                        const meta = new builtins.set(this._internal_names.concat(this._metadata));\n                        for (const k of meta) {\n                            if (state.__contains__(k) && k !== '_flags') {\n                                const v = state.__getitem__(k);\n                                builtins.object.__setattr__(this, k, v);\n                            }\n                        }\n                        for (const [k, v] of state) {\n                            if (!meta.has(k)) {\n                                builtins.object.__setattr__(this, k, v);\n                            }\n                        }\n                    } else {\n                        throw new python.Error('Pre-0.12 pickles are no longer supported.');\n                    }\n                } else if (state.size === 2) {\n                    throw new python.Error('Pre-0.12 pickles are no longer supported.');\n                }\n            }\n        });\n        this.registerType('pandas.core.frame.DataFrame', class extends pandas.core.generic.NDFrame {\n        });\n        this.registerFunction('pandas.core.indexes.base._new_Index', (cls, d) => {\n            return new cls(d);\n        });\n        this.registerType('pandas.core.indexes.datetimes._new_DatetimeIndex', class {});\n        this.registerType('pandas.core.indexes.datetimes.DatetimeIndex', class {});\n        this.registerType('pandas.core.indexes.base.Index', class {});\n        this.registerType('pandas.core.indexes.range.RangeIndex', class {});\n        this.registerType('pandas.core.indexes.multi.MultiIndex', class {});\n        this.registerType('pandas.core.indexes.numeric.Int64Index', class {});\n        this.registerType('pandas.core.index.Int64Index', class {});\n        this.registerFunction('pandas.core.internals.blocks.Block', class {\n        });\n        this.registerFunction('pandas.core.internals.blocks.NumpyBlock', class extends pandas.core.internals.blocks.Block {\n        });\n        this.registerFunction('pandas.core.internals.blocks.get_block_type', (/* dtype */) => {\n            return pandas.core.internals.blocks.NumpyBlock;\n        });\n        this.registerFunction('pandas.core.internals.blocks.maybe_coerce_values', (values) => {\n            return values;\n        });\n        this.registerFunction('pandas.core.internals.blocks.new_block', (values, placement, ndim, refs) => {\n            const klass = execution.invoke('pandas.core.internals.blocks.get_block_type', [values.dtype]);\n            return new klass(values, ndim, placement, refs);\n        });\n        this.registerType('pandas.core.internals.managers.SingleBlockManager', class {});\n        this.registerType('pandas.core.internals.managers.BlockManager', class {});\n        this.registerType('pandas.core.series.Series', class {});\n        this.registerFunction('pandas._libs.arrays.__pyx_unpickle_NDArrayBacked', (cls, checksum, state) => {\n            const obj = new cls();\n            if (state && obj.__setstate__) {\n                obj.__setstate__(state);\n            }\n            return obj;\n        });\n        this.registerFunction('pandas._libs.interval.__pyx_unpickle_IntervalMixin', (cls, checksum, state) => {\n            const obj = new cls();\n            if (state && obj.__setstate__) {\n                obj.__setstate__(state);\n            }\n            return obj;\n        });\n        this.registerFunction('pandas._libs.internals._unpickle_block', (values, placement, ndim) => {\n            values = pandas.core.internals.blocks.maybe_coerce_values(values);\n            // if not isinstance(placement, BlockPlacement):\n            //     placement = BlockPlacement(placement)\n            return pandas.core.internals.blocks.new_block(values, placement, ndim);\n        });\n        this.registerType('pandas._libs.tslibs.base.ABCTimestamp', class extends datetime.datetime {});\n        this.registerType('pandas._libs.tslibs.offsets.BaseOffset', class {});\n        this.registerType('pandas._libs.tslibs.offsets.SingleConstructorOffset', class extends pandas._libs.tslibs.offsets.BaseOffset {});\n        this.registerType('pandas._libs.tslibs.offsets.Tick', class extends pandas._libs.tslibs.offsets.SingleConstructorOffset {});\n        this.registerType('pandas._libs.tslibs.offsets.Day', class extends pandas._libs.tslibs.offsets.Tick {});\n        this.registerType('pandas._libs.tslibs.offsets.Minute', class extends datetime.datetime {});\n        this.registerFunction('pandas._libs.tslibs.timestamps._unpickle_timestamp');\n        this.registerType('pandas._libs.tslibs.timestamps._Timestamp', class extends pandas._libs.tslibs.base.ABCTimestamp {});\n        this.registerType('pandas._libs.tslibs.timestamps.Timestamp', class extends pandas._libs.tslibs.timestamps._Timestamp {});\n        pandas.indexes.base._new_Index = pandas.core.indexes.base._new_Index;\n        pandas.indexes.base.Index = pandas.core.indexes.base.Index;\n        pandas.indexes.range.RangeIndex = pandas.core.indexes.range.RangeIndex;\n        pandas.core.index.Index = pandas.core.indexes.base.Index;\n        pandas.core.index._new_Index = pandas.core.indexes.base._new_Index;\n        pandas.core.internals.BlockManager = pandas.core.internals.managers.BlockManager;\n        pandas._libs.tslib.Timestamp = pandas._libs.tslibs.timestamps.Timestamp;\n        this.registerType('pathlib.Path', class {});\n        this.registerType('pathlib._local.PosixPath', class {});\n        this.registerType('pathlib._local.WindowsPath', class {});\n        const pathlib = this.register('pathlib');\n        pathlib.PosixPath = pathlib._local.PosixPath;\n        pathlib.WindowsPath = pathlib._local.WindowsPath;\n        this.registerType('shap._serializable.Serializable', class {});\n        this.registerType('shap.explainers._explainer.Explainer', class extends shap._serializable.Serializable {});\n        this.registerType('shap.explainers._linear.LinearExplainer', class extends shap.explainers._explainer.Explainer {});\n        shap.explainers.LinearExplainer = shap.explainers._linear.LinearExplainer;\n        shap.explainers.linear.LinearExplainer = shap.explainers._linear.LinearExplainer;\n        this.registerType('sklearn._loss.link.BaseLink', class {});\n        this.registerType('sklearn._loss._loss.__pyx_unpickle_CyHalfBinomialLoss', class {});\n        this.registerType('sklearn._loss._loss.__pyx_unpickle_CyHalfMultinomialLoss', class {});\n        this.registerType('sklearn._loss._loss.CyLossFunction', class {});\n        this.registerType('sklearn._loss._loss.CyHalfBinomialLoss', class {});\n        this.registerType('sklearn._loss._loss.CyHalfMultinomialLoss', class {});\n        this.registerType('sklearn._loss._loss.CyHalfSquaredError', class extends sklearn._loss._loss.CyLossFunction {});\n        this.registerType('sklearn._loss.link.IdentityLink', class extends sklearn._loss.link.BaseLink {});\n        this.registerType('sklearn._loss.link.Interval', class {});\n        this.registerType('sklearn._loss.link.LogitLink', class {});\n        this.registerType('sklearn._loss.link.MultinomialLogit', class extends sklearn._loss.link.BaseLink {});\n        this.registerFunction('sklearn._loss._loss.__pyx_unpickle_CyHalfSquaredError');\n        this.registerType('sklearn._loss.loss.BaseLoss', class {});\n        this.registerType('sklearn._loss.loss.HalfBinomialLoss', class {});\n        this.registerType('sklearn._loss.loss.HalfMultinomialLoss', class extends sklearn._loss.loss.BaseLoss {});\n        this.registerType('sklearn._loss.loss.HalfSquaredError', class extends sklearn._loss.loss.BaseLoss {});\n        this.registerType('sklearn.base.BaseEstimator', class {});\n        this.registerType('sklearn.base.TransformerMixin', class {});\n        this.registerType('sklearn.calibration._CalibratedClassifier', class {});\n        this.registerType('sklearn.calibration._SigmoidCalibration', class {});\n        this.registerType('sklearn.calibration.CalibratedClassifierCV', class {});\n        this.registerType('sklearn.cluster._agglomerative.FeatureAgglomeration', class {});\n        this.registerType('sklearn.cluster._dbscan.DBSCAN', class {});\n        this.registerType('sklearn.cluster._kmeans.KMeans', class {});\n        this.registerType('sklearn.cluster._kmeans.MiniBatchKMeans', class {});\n        this.registerType('sklearn.cluster.k_means_.MiniBatchKMeans', class {});\n        this.registerType('sklearn.compose._column_transformer._RemainderColsList', class {});\n        this.registerType('sklearn.compose._column_transformer.ColumnTransformer', class {});\n        this.registerType('sklearn.compose._column_transformer.make_column_selector', class {});\n        this.registerType('sklearn.compose._target.TransformedTargetRegressor', class {});\n        this.registerType('sklearn.cross_decomposition._pls.PLSRegression', class {});\n        this.registerType('sklearn.cross_decomposition._pls.CCA', class {});\n        this.registerType('sklearn.decomposition._fastica.FastICA', class {});\n        this.registerType('sklearn.decomposition._incremental_pca.IncrementalPCA', class {});\n        this.registerType('sklearn.decomposition._pca.PCA', class {});\n        this.registerType('sklearn.decomposition._truncated_svd.TruncatedSVD', class {});\n        this.registerType('sklearn.decomposition.pca.PCA', class {});\n        this.registerType('sklearn.decomposition.PCA', class {});\n        this.registerType('sklearn.decomposition.truncated_svd.TruncatedSVD', class {});\n        this.registerType('sklearn.discriminant_analysis.LinearDiscriminantAnalysis', class {});\n        this.registerType('sklearn.discriminant_analysis.QuadraticDiscriminantAnalysis', class {});\n        this.registerType('sklearn.dummy.DummyClassifier', class {});\n        this.registerType('sklearn.dummy.DummyRegressor', class {});\n        this.registerType('sklearn.ensemble._bagging.BaggingClassifier', class {});\n        this.registerType('sklearn.ensemble._bagging.BaggingRegressor', class {});\n        this.registerType('sklearn.ensemble._forest.RandomForestClassifier', class {});\n        this.registerType('sklearn.ensemble._forest.RandomForestRegressor', class {});\n        this.registerType('sklearn.ensemble._forest.ExtraTreesClassifier', class {});\n        this.registerType('sklearn.ensemble._forest.ExtraTreesRegressor', class {});\n        this.registerType('sklearn.ensemble._gb_losses.BinomialDeviance', class {});\n        this.registerType('sklearn.ensemble._gb_losses.ExponentialLoss', class {});\n        this.registerType('sklearn.ensemble._gb_losses.LeastAbsoluteError', class {});\n        this.registerType('sklearn.ensemble._gb_losses.LeastSquaresError', class {});\n        this.registerType('sklearn.ensemble._gb_losses.MultinomialDeviance', class {});\n        this.registerType('sklearn.ensemble._gb.GradientBoostingClassifier', class {});\n        this.registerType('sklearn.ensemble._gb.GradientBoostingRegressor', class {});\n        this.registerType('sklearn.ensemble._hist_gradient_boosting.binning._BinMapper', class {});\n        this.registerType('sklearn.ensemble._hist_gradient_boosting.gradient_boosting.HistGradientBoostingRegressor', class {});\n        this.registerType('sklearn.ensemble._hist_gradient_boosting.gradient_boosting.HistGradientBoostingClassifier', class {});\n        this.registerType('sklearn.ensemble._hist_gradient_boosting.loss.LeastSquares', class {});\n        this.registerType('sklearn.ensemble._hist_gradient_boosting.predictor.TreePredictor', class {});\n        this.registerType('sklearn.ensemble._iforest.IsolationForest', class {});\n        this.registerType('sklearn.ensemble._stacking.StackingClassifier', class {});\n        this.registerType('sklearn.ensemble._stacking.StackingRegressor', class {});\n        this.registerType('sklearn.ensemble._voting.VotingClassifier', class {});\n        this.registerType('sklearn.ensemble._voting.VotingRegressor', class {});\n        this.registerType('sklearn.ensemble._weight_boosting.AdaBoostClassifier', class {});\n        this.registerType('sklearn.covariance._robust_covariance.MinCovDet', class {});\n        this.registerType('sklearn.ensemble._weight_boosting.AdaBoostRegressor', class {});\n        this.registerType('sklearn.ensemble.forest.RandomForestClassifier', class {});\n        this.registerType('sklearn.ensemble.forest.RandomForestRegressor', class {});\n        this.registerType('sklearn.ensemble.forest.ExtraTreesClassifier', class {});\n        this.registerType('sklearn.ensemble.gradient_boosting.BinomialDeviance', class {});\n        this.registerType('sklearn.ensemble.gradient_boosting.GradientBoostingClassifier', class {});\n        this.registerType('sklearn.ensemble.gradient_boosting.LogOddsEstimator', class {});\n        this.registerType('sklearn.ensemble.gradient_boosting.MultinomialDeviance', class {});\n        this.registerType('sklearn.ensemble.gradient_boosting.PriorProbabilityEstimator', class {});\n        this.registerType('sklearn.ensemble.voting_classifier.VotingClassifier', class {});\n        this.registerType('sklearn.ensemble.weight_boosting.AdaBoostClassifier', class {});\n        this.registerType('sklearn.feature_extraction._dict_vectorizer.DictVectorizer', class {});\n        this.registerType('sklearn.feature_extraction._hashing.FeatureHasher', class {});\n        this.registerType('sklearn.feature_extraction._hash.FeatureHasher', class {});\n        this.registerType('sklearn.feature_extraction.text.CountVectorizer', class {});\n        this.registerType('sklearn.feature_extraction.text.HashingVectorizer', class {});\n        this.registerType('sklearn.feature_extraction.text.TfidfTransformer', class {});\n        this.registerType('sklearn.feature_extraction.text.TfidfVectorizer', class {});\n        this.registerType('sklearn.feature_selection._from_model.SelectFromModel', class {});\n        this.registerFunction('sklearn.feature_selection._mutual_info.mutual_info_classif');\n        this.registerFunction('sklearn.feature_selection._univariate_selection.chi2');\n        this.registerType('sklearn.feature_selection._univariate_selection.GenericUnivariateSelect', class {});\n        this.registerType('sklearn.feature_selection._univariate_selection.SelectKBest', class {});\n        this.registerType('sklearn.feature_selection._univariate_selection.SelectPercentile', class {});\n        this.registerType('sklearn.feature_selection._variance_threshold.VarianceThreshold', class {});\n        this.registerType('sklearn.feature_selection._rfe.RFE', class {});\n        this.registerType('sklearn.feature_selection._rfe.RFECV', class extends sklearn.feature_selection._rfe.RFE {});\n        this.registerType('sklearn.feature_selection.univariate_selection.SelectKBest', class {});\n        this.registerType('sklearn.feature_selection.variance_threshold.VarianceThreshold', class {});\n        this.registerType('sklearn.gaussian_process._gpc.GaussianProcessClassifier', class {});\n        this.registerType('sklearn.gaussian_process._gpr.GaussianProcessRegressor', class {});\n        this.registerType('sklearn.gaussian_process.gpc.GaussianProcessClassifier', class {});\n        this.registerType('sklearn.gaussian_process.kernels.ConstantKernel', class {});\n        this.registerType('sklearn.gaussian_process.kernels.DotProduct', class {});\n        this.registerType('sklearn.gaussian_process.kernels.Product', class {});\n        this.registerType('sklearn.gaussian_process.kernels.RBF', class {});\n        this.registerType('sklearn.gaussian_process.kernels.Sum', class {});\n        this.registerType('sklearn.gaussian_process.kernels.WhiteKernel', class {});\n        this.registerType('sklearn.grid_search._CVScoreTuple', class {});\n        this.registerType('sklearn.grid_search.GridSearchCV', class {});\n        this.registerType('sklearn.impute._base.MissingIndicator', class {});\n        this.registerType('sklearn.impute._base.SimpleImputer', class {});\n        this.registerType('sklearn.impute._iterative.IterativeImputer', class {});\n        this.registerType('sklearn.impute._iterative._ImputerTriplet', class {});\n        this.registerType('sklearn.impute._knn.KNNImputer', class {});\n        this.registerType('sklearn.impute.SimpleImputer', class {});\n        this.registerType('sklearn.isotonic.IsotonicRegression', class {});\n        this.registerType('sklearn.kernel_ridge.KernelRidge', class {});\n        this.registerType('sklearn.linear_model._base.LinearRegression', class {});\n        this.registerType('sklearn.linear_model._bayes.ARDRegression', class {});\n        this.registerType('sklearn.linear_model._bayes.BayesianRidge', class {});\n        this.registerType('sklearn.linear_model._coordinate_descent.ElasticNetCV', class {});\n        this.registerType('sklearn.linear_model._coordinate_descent.ElasticNet', class {});\n        this.registerType('sklearn.linear_model._coordinate_descent.Lasso', class {});\n        this.registerType('sklearn.linear_model._least_angle.LassoLarsCV', class {});\n        this.registerType('sklearn.linear_model._logistic.LogisticRegression', class {});\n        this.registerType('sklearn.linear_model._logistic.LogisticRegressionCV', class {});\n        this.registerType('sklearn.linear_model._perceptron.Perceptron', class {});\n        this.registerType('sklearn.linear_model._quantile.QuantileRegressor', class {});\n        this.registerType('sklearn.linear_model._ridge.Ridge', class {});\n        this.registerType('sklearn.linear_model._huber.HuberRegressor', class {});\n        this.registerType('sklearn.linear_model._ridge.RidgeCV', class {});\n        this.registerType('sklearn.linear_model._ridge.RidgeClassifier', class {});\n        this.registerType('sklearn.linear_model._ridge.RidgeClassifierCV', class {});\n        this.registerType('sklearn.linear_model._sgd_fast.Hinge', class {});\n        this.registerType('sklearn.linear_model._sgd_fast.Log', class {});\n        this.registerType('sklearn.linear_model._sgd_fast.ModifiedHuber', class {});\n        this.registerType('sklearn.linear_model._sgd_fast.SquaredHinge', class {});\n        this.registerType('sklearn.linear_model._stochastic_gradient.SGDClassifier', class {});\n        this.registerType('sklearn.linear_model._stochastic_gradient.SGDRegressor', class {});\n        this.registerType('sklearn.linear_model.base.LinearRegression', class {});\n        this.registerType('sklearn.linear_model.coordinate_descent.ElasticNet', class {});\n        this.registerType('sklearn.linear_model.sgd_fast.Hinge', class {});\n        this.registerType('sklearn.linear_model.LogisticRegression', class {});\n        this.registerType('sklearn.linear_model.logistic.LogisticRegression', class {});\n        this.registerType('sklearn.linear_model.logistic.LogisticRegressionCV', class {});\n        this.registerType('sklearn.linear_model.LassoLars​', class {});\n        this.registerType('sklearn.linear_model.ridge.Ridge', class {});\n        this.registerType('sklearn.linear_model.sgd_fast.Log', class {});\n        this.registerType('sklearn.linear_model.stochastic_gradient.SGDClassifier', class {});\n        this.registerType('sklearn.manifold._t_sne.TSNE', class {});\n        this.registerType('sklearn.metrics._dist_metrics.DistanceMetric', class extends builtins.object {});\n        this.registerType('sklearn.metrics._dist_metrics.DistanceMetric32', class extends sklearn.metrics._dist_metrics.DistanceMetric {});\n        this.registerType('sklearn.metrics._dist_metrics.DistanceMetric64', class extends sklearn.metrics._dist_metrics.DistanceMetric {});\n        this.registerType('sklearn.metrics._dist_metrics.EuclideanDistance', class extends sklearn.metrics._dist_metrics.DistanceMetric {});\n        this.registerType('sklearn.metrics._dist_metrics.EuclideanDistance32', class extends sklearn.metrics._dist_metrics.DistanceMetric32 {});\n        this.registerType('sklearn.metrics._dist_metrics.EuclideanDistance64', class extends sklearn.metrics._dist_metrics.DistanceMetric64 {});\n        this.registerType('sklearn.metrics._dist_metrics.ManhattanDistance', class extends sklearn.metrics._dist_metrics.DistanceMetric {});\n        this.registerType('sklearn.metrics._dist_metrics.ManhattanDistance64', class extends sklearn.metrics._dist_metrics.DistanceMetric64 {});\n        this.registerType('sklearn.metrics._scorer._PassthroughScorer', class {});\n        this.registerType('sklearn.metrics._scorer._PredictScorer', class {});\n        this.registerType('sklearn.metrics.scorer._PredictScorer', class {});\n        this.registerType('sklearn.metrics._scorer._ThresholdScorer', class {});\n        this.registerType('sklearn.metrics._scorer._Scorer', class {});\n        this.registerType('sklearn.mixture._bayesian_mixture.BayesianGaussianMixture', class {});\n        this.registerType('sklearn.mixture._gaussian_mixture.GaussianMixture', class {});\n        this.registerType('sklearn.model_selection._search.GridSearchCV', class {});\n        this.registerType('sklearn.model_selection._search.RandomizedSearchCV', class {});\n        this.registerType('sklearn.model_selection._split.KFold', class {});\n        this.registerType('sklearn.model_selection._split.PredefinedSplit', class {});\n        this.registerType('sklearn.model_selection._split.RepeatedKFold', class {});\n        this.registerType('sklearn.model_selection._split.StratifiedKFold', class {});\n        this.registerType('sklearn.model_selection._split.StratifiedShuffleSplit', class {});\n        this.registerType('sklearn.model_selection._split.TimeSeriesSplit', class {});\n        this.registerType('sklearn.multiclass.OneVsRestClassifier', class {});\n        this.registerType('sklearn.multioutput.ClassifierChain', class {});\n        this.registerType('sklearn.multioutput.MultiOutputClassifier', class {});\n        this.registerType('sklearn.multioutput.MultiOutputRegressor', class {});\n        this.registerType('sklearn.naive_bayes.BernoulliNB', class {});\n        this.registerType('sklearn.naive_bayes.ComplementNB', class {});\n        this.registerType('sklearn.naive_bayes.GaussianNB', class {});\n        this.registerType('sklearn.naive_bayes.MultinomialNB', class {});\n        this.registerType('sklearn.neighbors.ball_tree.BallTree', class {});\n        this.registerFunction('sklearn.neighbors.ball_tree.newObj', (obj) => {\n            return obj.__new__(obj);\n        });\n        this.registerType('sklearn.neighbors._classification.KNeighborsClassifier', class {});\n        this.registerFunction('sklearn.neighbors._dist_metrics.newObj');\n        this.registerType('sklearn.neighbors._dist_metrics.EuclideanDistance', class {});\n        this.registerType('sklearn.neighbors._kd_tree.BinaryTree64', class extends builtins.object {});\n        this.registerType('sklearn.neighbors._kd_tree.KDTree64', class extends sklearn.neighbors._kd_tree.BinaryTree64 {});\n        this.registerType('sklearn.neighbors._kd_tree.KDTree', class extends sklearn.neighbors._kd_tree.KDTree64 {});\n        this.registerFunction('sklearn.neighbors._kd_tree.newObj', (obj) => {\n            return obj.__new__(obj);\n        });\n        this.registerType('sklearn.neighbors._regression.KNeighborsRegressor', class {});\n        this.registerType('sklearn.neighbors._unsupervised.NearestNeighbors', class {});\n        this.registerType('sklearn.neighbors.classification.KNeighborsClassifier', class {});\n        this.registerFunction('sklearn.neighbors.dist_metrics.newObj', (obj) => {\n            return obj.__new__(obj);\n        });\n        this.registerType('sklearn.neighbors.dist_metrics.EuclideanDistance', class {});\n        this.registerFunction('sklearn.neighbors.kd_tree.newObj', (obj) => {\n            return obj.__new__(obj);\n        });\n        this.registerType('sklearn.neighbors.kd_tree.KDTree', class {});\n        this.registerType('sklearn.neighbors.KNeighborsClassifier', class {});\n        this.registerType('sklearn.neighbors.KNeighborsRegressor', class {});\n        this.registerType('sklearn.neighbors.regression.KNeighborsRegressor', class {});\n        this.registerType('sklearn.neighbors.unsupervised.NearestNeighbors', class {});\n        this.registerType('sklearn.neural_network._multilayer_perceptron.MLPClassifier', class {});\n        this.registerType('sklearn.neural_network._multilayer_perceptron.MLPRegressor', class {});\n        this.registerType('sklearn.neural_network._stochastic_optimizers.AdamOptimizer', class {});\n        this.registerType('sklearn.neural_network._stochastic_optimizers.SGDOptimizer', class {});\n        this.registerType('sklearn.neural_network.rbm.BernoulliRBM', class {});\n        this.registerType('sklearn.neural_network.multilayer_perceptron.MLPClassifier', class {});\n        this.registerType('sklearn.neural_network.multilayer_perceptron.MLPRegressor', class {});\n        this.registerType('sklearn.neural_network.stochastic_gradient.SGDClassifier', class {});\n        this.registerType('sklearn.pipeline.Pipeline', class {});\n        this.registerType('sklearn.pipeline.FeatureUnion', class {});\n        this.registerType('sklearn.preprocessing._data.MinMaxScaler', class {});\n        this.registerType('sklearn.preprocessing._data.MaxAbsScaler', class {});\n        this.registerType('sklearn.preprocessing._data.Normalizer', class {});\n        this.registerType('sklearn.preprocessing._data.PolynomialFeatures', class {});\n        this.registerType('sklearn.preprocessing._data.PowerTransformer', class {});\n        this.registerType('sklearn.preprocessing._data.QuantileTransformer', class {});\n        this.registerType('sklearn.preprocessing._data.RobustScaler', class {});\n        this.registerType('sklearn.preprocessing._data.StandardScaler', class {});\n        this.registerType('sklearn.preprocessing._discretization.KBinsDiscretizer', class {});\n        this.registerType('sklearn.preprocessing._encoders.OneHotEncoder', class {});\n        this.registerType('sklearn.preprocessing._encoders.OrdinalEncoder', class {});\n        this.registerType('sklearn.preprocessing._function_transformer.FunctionTransformer', class {});\n        this.registerType('sklearn.preprocessing._label.LabelBinarizer', class {});\n        this.registerType('sklearn.preprocessing._label.LabelEncoder', class {});\n        this.registerType('sklearn.preprocessing._label.MultiLabelBinarizer', class {});\n        this.registerType('sklearn.preprocessing._polynomial.PolynomialFeatures', class {});\n        this.registerType('sklearn.preprocessing._target_encoder.TargetEncoder', class {});\n        this.registerType('sklearn.preprocessing.data.Binarizer', class {});\n        this.registerType('sklearn.preprocessing.data.MaxAbsScaler', class {});\n        this.registerType('sklearn.preprocessing.data.MinMaxScaler', class {});\n        this.registerType('sklearn.preprocessing.data.Normalizer', class {});\n        this.registerType('sklearn.preprocessing.data.OneHotEncoder', class {});\n        this.registerType('sklearn.preprocessing.data.PolynomialFeatures', class {});\n        this.registerType('sklearn.preprocessing.data.PowerTransformer', class {});\n        this.registerType('sklearn.preprocessing.data.RobustScaler', class {});\n        this.registerType('sklearn.preprocessing.data.QuantileTransformer', class {});\n        this.registerType('sklearn.preprocessing.data.StandardScaler', class {});\n        this.registerType('sklearn.preprocessing.imputation.Imputer', class {});\n        this.registerType('sklearn.preprocessing.label.LabelBinarizer', class {});\n        this.registerType('sklearn.preprocessing.label.LabelEncoder', class {});\n        this.registerType('sklearn.preprocessing.label.MultiLabelBinarizer', class {});\n        this.registerType('sklearn.random_projection.GaussianRandomProjection', class {});\n        this.registerType('sklearn.svm._classes.LinearSVC', class {});\n        this.registerType('sklearn.svm._classes.NuSVC', class {});\n        this.registerType('sklearn.svm._classes.OneClassSVM', class {});\n        this.registerType('sklearn.svm._classes.SVC', class {});\n        this.registerType('sklearn.svm._classes.SVR', class {});\n        this.registerType('sklearn.svm.classes.LinearSVC', class {});\n        this.registerType('sklearn.svm.classes.OneClassSVM', class {});\n        this.registerType('sklearn.svm.classes.SVC', class {});\n        this.registerType('sklearn.svm.classes.SVR', class {});\n        this.registerType('sklearn.tree._classes.DecisionTreeClassifier', class {});\n        this.registerType('sklearn.tree._classes.DecisionTreeRegressor', class {});\n        this.registerType('sklearn.tree._classes.ExtraTreeClassifier', class {});\n        this.registerType('sklearn.tree._classes.ExtraTreeRegressor', class {});\n        this.registerType('sklearn.tree._tree.Tree', class {\n            constructor(n_features, n_classes, n_outputs) {\n                this.n_features = n_features;\n                this.n_classes = n_classes;\n                this.n_outputs = n_outputs;\n            }\n            __setstate__(state) {\n                this.max_depth = state.get('max_depth');\n                this.node_count = state.get('node_count');\n                this.nodes = state.get('nodes');\n                this.values = state.get('values');\n            }\n        });\n        this.registerType('sklearn.tree.tree.DecisionTreeClassifier', class {});\n        this.registerType('sklearn.tree.tree.DecisionTreeRegressor', class {});\n        this.registerType('sklearn.tree.tree.ExtraTreeClassifier', class {});\n        this.registerType('sklearn.utils._bunch.Bunch', class {});\n        this.registerType('sklearn.utils._metadata_requests.MetadataRequest', class {});\n        this.registerType('sklearn.utils._metadata_requests.MethodMetadataRequest', class {});\n        this.registerType('sklearn.utils.deprecation.DeprecationDict', class {});\n        this.registerType('pickle.Unpickler', class {\n            constructor(data) {\n                this._reader = data instanceof Uint8Array ? new python.BinaryReader(data) : new python.StreamReader(data);\n                this.persistent_load = () => {\n                    throw new python.Error('Unsupported persistent id.');\n                };\n            }\n            load() {\n                const reader = this._reader;\n                const marker = [];\n                let stack = new builtins.list();\n                const memo = {};\n                let size = 0;\n                while (reader.position < reader.length) {\n                    const opcode = reader.byte();\n                    // console.log(`${(reader.position - 1).toString()} ${opcode}`);\n                    // https://svn.python.org/projects/python/trunk/Lib/pickletools.py\n                    // https://github.com/python/cpython/blob/master/Lib/pickle.py\n                    switch (opcode) {\n                        case 128: { // PROTO\n                            const version = reader.byte();\n                            if (version > 5) {\n                                throw new python.Error(`Unsupported protocol version '${version}'.`);\n                            }\n                            break;\n                        }\n                        case 99: { // GLOBAL 'c'\n                            const module = reader.line();\n                            const name = reader.line();\n                            stack.push(this.find_class(module, name));\n                            break;\n                        }\n                        case 147: { // STACK_GLOBAL '\\x93' (Protocol 4)\n                            const name = stack.pop();\n                            const module = stack.pop();\n                            stack.push(this.find_class(module, name));\n                            break;\n                        }\n                        case 111: { // OBJ 'o'\n                            const args = stack;\n                            const cls = args.pop();\n                            stack = marker.pop();\n                            const obj = this._instantiate(cls, args);\n                            stack.push(obj);\n                            break;\n                        }\n                        case 112 : { // PUT 'p'\n                            const index = parseInt(reader.line(), 10);\n                            if (stack.length === 0) {\n                                throw new python.Error(`Empty stack during 'PUT' operation.`);\n                            }\n                            memo[index] = stack[stack.length - 1];\n                            size++;\n                            break;\n                        }\n                        case 103: { // GET 'g'\n                            const index = parseInt(reader.line(), 10);\n                            if (index in memo === false) {\n                                throw new python.Error(`Memo value not found at index '${index}'.`);\n                            }\n                            stack.push(memo[index]);\n                            break;\n                        }\n                        case 48: // POP '0'\n                            stack.pop();\n                            break;\n                        case 49: // POP_MARK '1'\n                            stack = marker.pop();\n                            break;\n                        case 50: // DUP '2'\n                            if (stack.length === 0) {\n                                throw new python.Error(`Empty stack during 'DUP' operation.`);\n                            }\n                            stack.push(stack[stack.length - 1]);\n                            break;\n                        case 80: // PERSID 'P'\n                            stack.push(this.persistent_load(reader.line()));\n                            break;\n                        case 81: // BINPERSID 'Q'\n                            stack.push(this.persistent_load(stack.pop()));\n                            break;\n                        case 82: { // REDUCE 'R'\n                            const args = stack.pop();\n                            const func = stack.pop();\n                            stack.push(this._reduce(func, args));\n                            break;\n                        }\n                        case 129: { // NEWOBJ\n                            const args = stack.pop();\n                            const cls = stack.pop();\n                            const obj = this._newobj(cls, args);\n                            stack.push(obj);\n                            break;\n                        }\n                        case 146: { // NEWOBJ_EX '\\x92' (Protocol 4)\n                            const kwargs = stack.pop();\n                            const args = stack.pop();\n                            const cls = stack.pop();\n                            if (Object.entries(kwargs).length > 0) {\n                                throw new python.Error(\"Unpickle 'NEWOBJ_EX' not implemented.\");\n                            }\n                            const obj = this._newobj(cls, args);\n                            stack.push(obj);\n                            break;\n                        }\n                        case 104: { // BINGET 'h'\n                            const index = reader.byte();\n                            if (index in memo === false) {\n                                throw new python.Error(`Memo value not found at index '${index}'.`);\n                            }\n                            stack.push(memo[index]);\n                            break;\n                        }\n                        case 105: { // INST 'i'\n                            const module = reader.line();\n                            const name = reader.line();\n                            const args = stack;\n                            const cls = `${module}.${name}`;\n                            stack = marker.pop();\n                            // cls = this.find_class(module, name)\n                            const obj = this._instantiate(cls, args);\n                            stack.push(obj);\n                            break;\n                        }\n                        case 106: { // LONG_BINGET 'j'\n                            const index = reader.uint32();\n                            if (index in memo === false) {\n                                throw new python.Error(`Memo value not found at index '${index}'.`);\n                            }\n                            stack.push(memo[index]);\n                            break;\n                        }\n                        case 113: // BINPUT 'q'\n                            if (stack.length === 0) {\n                                throw new python.Error(`Empty stack during 'BINPUT' operation.`);\n                            }\n                            memo[reader.byte()] = stack[stack.length - 1];\n                            size++;\n                            break;\n                        case 114: // LONG_BINPUT 'r'\n                            if (stack.length === 0) {\n                                throw new python.Error(`Empty stack during 'LONG_BINPUT' operation.`);\n                            }\n                            memo[reader.uint32()] = stack[stack.length - 1];\n                            size++;\n                            break;\n                        case 74: // BININT 'J'\n                            stack.push(reader.int32());\n                            break;\n                        case 75: // BININT1 'K'\n                            stack.push(reader.byte());\n                            break;\n                        case 76: // LONG 'L'\n                            stack.push(parseInt(reader.line(), 10));\n                            break;\n                        case 77: // BININT2 'M'\n                            stack.push(reader.uint16());\n                            break;\n                        case 66: // BINBYTES 'B' (Protocol 3)\n                            stack.push(reader.read(reader.int32()));\n                            break;\n                        case 67: // SHORT_BINBYTES 'C' (Protocol 3)\n                            stack.push(reader.read(reader.byte()));\n                            break;\n                        case 142: // BINBYTES8 '\\x8e' (Protocol 4)\n                            stack.push(reader.read(reader.int64().toNumber()));\n                            break;\n                        case 70: // FLOAT 'F'\n                            stack.push(parseFloat(reader.line()));\n                            break;\n                        case 71: // BINFLOAT 'G'\n                            stack.push(reader.float64());\n                            break;\n                        case 73: { // INT 'I'\n                            const value = reader.line();\n                            if (value === '01') {\n                                stack.push(true);\n                            } else if (value === '00') {\n                                stack.push(false);\n                            } else {\n                                stack.push(parseInt(value, 10));\n                            }\n                            break;\n                        }\n                        case 93: // EMPTY_LIST ']'\n                            stack.push(new builtins.list());\n                            break;\n                        case 41: // EMPTY_TUPLE ')'\n                            stack.push([]);\n                            break;\n                        case 143: // EMPTY_SET '\\x8f' (Protocol 4)\n                            stack.push([]);\n                            break;\n                        case 144: { // ADDITEMS '\\x90' (Protocol 4)\n                            const items = stack;\n                            stack = marker.pop();\n                            const obj = stack[stack.length - 1];\n                            for (let i = 0; i < items.length; i++) {\n                                obj.push(items[i]);\n                            }\n                            break;\n                        }\n                        case 145: { // FROZENSET '\\x91' (Protocol 4)\n                            const items = stack;\n                            stack = marker.pop();\n                            stack.push(items);\n                            break;\n                        }\n                        case 100: { // DICT 'd'\n                            const items = stack;\n                            stack = marker.pop();\n                            const dict = new builtins.dict();\n                            for (let i = 0; i < items.length; i += 2) {\n                                dict.__setitem__(items[i], items[i + 1]);\n                            }\n                            stack.push(dict);\n                            break;\n                        }\n                        case 108: { // LIST 'l'\n                            const items = stack;\n                            stack = marker.pop();\n                            stack.push(items);\n                            break;\n                        }\n                        case 116: { // TUPLE 't'\n                            const items = stack;\n                            stack = marker.pop();\n                            stack.push(items);\n                            break;\n                        }\n                        case 133: { // TUPLE1 // '\\x85'\n                            stack.push([stack.pop()]);\n                            break;\n                        }\n                        case 134: { // TUPLE2 '\\x86'\n                            const b = stack.pop();\n                            const a = stack.pop();\n                            stack.push([a, b]);\n                            break;\n                        }\n                        case 135: { // TUPLE3 '\\x87'\n                            const c = stack.pop();\n                            const b = stack.pop();\n                            const a = stack.pop();\n                            stack.push([a, b, c]);\n                            break;\n                        }\n                        case 115: { // SETITEM 's'\n                            const value = stack.pop();\n                            const key = stack.pop();\n                            const obj = stack[stack.length - 1];\n                            if (obj.__setitem__) {\n                                obj.__setitem__(key, value);\n                            } else {\n                                obj[key] = value;\n                            }\n                            break;\n                        }\n                        case 117: { // SETITEMS 'u'\n                            const items = stack;\n                            stack = marker.pop();\n                            const obj = stack[stack.length - 1];\n                            if (obj.__setitem__) {\n                                for (let i = 0; i < items.length; i += 2) {\n                                    obj.__setitem__(items[i], items[i + 1]);\n                                }\n                            } else {\n                                for (let i = 0; i < items.length; i += 2) {\n                                    obj[items[i]] = items[i + 1];\n                                }\n                            }\n                            break;\n                        }\n                        case 125: // EMPTY_DICT '}'\n                            stack.push(new builtins.dict());\n                            break;\n                        case 97: { // APPEND 'a'\n                            const append = stack.pop();\n                            const list = stack[stack.length - 1];\n                            list.append(append);\n                            break;\n                        }\n                        case 101: { // APPENDS 'e'\n                            const appends = stack;\n                            stack = marker.pop();\n                            const list_obj = stack[stack.length - 1];\n                            if (list_obj.extend) {\n                                list_obj.extend(appends);\n                            } else {\n                                for (const item of appends) {\n                                    list_obj.append(item);\n                                }\n                            }\n                            break;\n                        }\n                        case 83: { // STRING 'S'\n                            const str = reader.line();\n                            stack.push(str.substring(1, str.length - 1));\n                            break;\n                        }\n                        case 84: // BINSTRING 'T'\n                            stack.push(reader.string(reader.uint32()));\n                            break;\n                        case 85 : // SHORT_BINSTRING 'U'\n                            stack.push(reader.string(reader.byte()));\n                            break;\n                        case 86: // UNICODE 'V'\n                            stack.push(reader.line());\n                            break;\n                        case 88: // BINUNICODE 'X\n                            stack.push(reader.string(reader.uint32(), 'utf-8'));\n                            break;\n                        case 140: // SHORT_BINUNICODE '\\x8c' (Protocol 4)\n                            stack.push(reader.string(reader.byte(), 'utf-8'));\n                            break;\n                        case 98: { // BUILD 'b'\n                            const state = stack.pop();\n                            let obj = stack.pop();\n                            if (obj.__setstate__) {\n                                if (obj.__setstate__.__call__) {\n                                    obj.__setstate__.__call__([obj, state]);\n                                } else {\n                                    obj.__setstate__(state);\n                                }\n                            } else if (ArrayBuffer.isView(state) || Object(state) !== state) {\n                                obj.__state__ = state;\n                            } else if (obj instanceof Map && state instanceof Map) {\n                                for (const [key, value] of state) {\n                                    obj.set(key, value);\n                                }\n                            } else if (obj instanceof Map) {\n                                /* eslint-disable guard-for-in */\n                                for (const key in state) {\n                                    obj.set(key, state[key]);\n                                }\n                                /* eslint-enable guard-for-in */\n                            } else if (state instanceof Map) {\n                                for (const [key, value] of state) {\n                                    obj[key] = value;\n                                }\n                            } else {\n                                Object.assign(obj, state);\n                            }\n                            if (obj.__read__) {\n                                obj = obj.__read__(this);\n                            }\n                            stack.push(obj);\n                            break;\n                        }\n                        case 40: // MARK '('\n                            marker.push(stack);\n                            stack = new builtins.list();\n                            break;\n                        case 136: // NEWTRUE '\\x88'\n                            stack.push(true);\n                            break;\n                        case 137: // NEWFALSE '\\x89'\n                            stack.push(false);\n                            break;\n                        case 138: { // LONG1 '\\x8a'\n                            const data = reader.read(reader.byte());\n                            let number = 0;\n                            switch (data.length) {\n                                case 0: number = 0; break;\n                                case 1: [number] = data; break;\n                                case 2: number = data[1] << 8 | data[0]; break;\n                                case 3: number = data[2] << 16 | data[1] << 8 | data[0]; break;\n                                case 4: number = (data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]) >>> 0; break;\n                                case 5: number = data[4] * 0x100000000 + ((data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]) >>> 0); break;\n                                default: number = Array.prototype.slice.call(data, 0); break;\n                            }\n                            stack.push(number);\n                            break;\n                        }\n                        case 139: // LONG4 '\\x8b'\n                            // decode LONG4\n                            stack.push(reader.read(reader.uint32()));\n                            break;\n                        case 148: // MEMOIZE '\\x94' (Protocol 4)\n                            memo[size++] = stack[stack.length - 1];\n                            break;\n                        case 149: // FRAME '\\x95' (Protocol 4)\n                            reader.read(8);\n                            break;\n                        case 150: { // BYTEARRAY8 '\\x96' (Protocol 5)\n                            stack.push(reader.read(reader.int64().toNumber()));\n                            break;\n                        }\n                        case 78: // NONE 'N'\n                            stack.push(null);\n                            break;\n                        case 46: // STOP '.'\n                            return stack.pop();\n                        case 141: // BINUNICODE8 '\\x8d' (Protocol 4)\n                        case 151: // NEXT_BUFFER '\\x97' (Protocol 5)\n                        case 152: // READONLY_BUFFER '\\x98' (Protocol 5)\n                        default:\n                            throw new python.Error(`Unknown opcode ${opcode} at position ${(reader.position - 1)}.`);\n                    }\n                }\n                throw new python.Error('Unexpected end of file.');\n            }\n            find_class(module, name) {\n                execution.__import__(module);\n                return execution.resolve(`${module}.${name}`);\n            }\n            _instantiate(cls, args) {\n                return execution.invoke(cls, args);\n            }\n            _newobj(cls, args) {\n                // cls.__new__(cls, args)\n                return execution.invoke(cls, args);\n            }\n            _reduce(func, args) {\n                return execution.invoke(func, args);\n            }\n            read(size) {\n                return this._reader.read(size);\n            }\n            stream(size) {\n                return this._reader.stream(size);\n            }\n        });\n        this.registerType('random.Random', class {});\n        this.registerType('re.Pattern', class {\n            constructor(pattern, flags) {\n                this.pattern = pattern;\n                this.flags = flags;\n            }\n        });\n        this.registerType('spacy._ml.PrecomputableAffine', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('spacy.syntax._parser_model.ParserModel', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('theano.compile.function_module._constructor_Function', class {});\n        this.registerType('theano.compile.function_module._constructor_FunctionMaker', class {});\n        this.registerType('theano.compile.function_module.Function', class {});\n        this.registerType('theano.compile.function_module.Supervisor', class {});\n        this.registerType('theano.compile.io.In', class {});\n        this.registerType('theano.compile.io.SymbolicOutput', class {});\n        this.registerType('theano.compile.mode.Mode', class {});\n        this.registerType('theano.compile.ops.OutputGuard', class {});\n        this.registerType('theano.compile.ops.Shape', class {});\n        this.registerType('theano.compile.ops.Shape_i', class {});\n        this.registerType('theano.gof.destroyhandler.DestroyHandler', class {});\n        this.registerType('theano.gof.fg.FunctionGraph', class {});\n        this.registerType('theano.gof.graph.Apply', class {});\n        this.registerType('theano.gof.link.Container', class {});\n        this.registerType('theano.gof.opt._metadict', class {});\n        this.registerType('theano.gof.opt.ChangeTracker', class {});\n        this.registerType('theano.gof.opt.MergeFeature', class {});\n        this.registerType('theano.gof.optdb.Query', class {});\n        this.registerType('theano.gof.toolbox.PreserveVariableAttributes', class {});\n        this.registerType('theano.gof.toolbox.ReplaceValidate', class {});\n        this.registerType('theano.gof.utils.scratchpad', class {});\n        this.registerType('theano.misc.ordered_set.Link', class {});\n        this.registerType('theano.misc.ordered_set.OrderedSet', class {});\n        this.registerType('theano.sandbox.cuda.basic_ops.HostFromGpu', class {});\n        this.registerType('theano.sandbox.cuda.type.CudaNdarray_unpickler', class {});\n        this.registerType('theano.sandbox.cuda.type.CudaNdarrayType', class {});\n        this.registerType('theano.sandbox.cuda.var.CudaNdarraySharedVariable', class {});\n        this.registerType('theano.scalar.basic.Abs', class {});\n        this.registerType('theano.scalar.basic.Add', class {});\n        this.registerType('theano.scalar.basic.Cast', class {});\n        this.registerType('theano.scalar.basic.Composite', class {});\n        this.registerType('theano.scalar.basic.EQ', class {});\n        this.registerType('theano.scalar.basic.GE', class {});\n        this.registerType('theano.scalar.basic.Identity', class {});\n        this.registerType('theano.scalar.basic.IntDiv', class {});\n        this.registerType('theano.scalar.basic.Inv', class {});\n        this.registerType('theano.scalar.basic.LE', class {});\n        this.registerType('theano.scalar.basic.LT', class {});\n        this.registerType('theano.scalar.basic.Mul', class {});\n        this.registerType('theano.scalar.basic.Neg', class {});\n        this.registerType('theano.scalar.basic.Pow', class {});\n        this.registerType('theano.scalar.basic.Scalar', class {});\n        this.registerType('theano.scalar.basic.ScalarConstant', class {});\n        this.registerType('theano.scalar.basic.ScalarVariable', class {});\n        this.registerType('theano.scalar.basic.Second', class {});\n        this.registerType('theano.scalar.basic.Sgn', class {});\n        this.registerType('theano.scalar.basic.specific_out', class {});\n        this.registerType('theano.scalar.basic.Sub', class {});\n        this.registerType('theano.scalar.basic.Switch', class {});\n        this.registerType('theano.scalar.basic.Tanh', class {});\n        this.registerType('theano.scalar.basic.transfer_type', class {});\n        this.registerType('theano.scalar.basic.TrueDiv', class {});\n        this.registerType('theano.tensor.basic.Alloc', class {});\n        this.registerType('theano.tensor.basic.Dot', class {});\n        this.registerType('theano.tensor.basic.MaxAndArgmax', class {});\n        this.registerType('theano.tensor.basic.Reshape', class {});\n        this.registerType('theano.tensor.basic.ScalarFromTensor', class {});\n        this.registerType('theano.tensor.blas.Dot22', class {});\n        this.registerType('theano.tensor.blas.Dot22Scalar', class {});\n        this.registerType('theano.tensor.blas.Gemm', class {});\n        this.registerType('theano.tensor.elemwise.DimShuffle', class {});\n        this.registerType('theano.tensor.elemwise.Elemwise', class {});\n        this.registerType('theano.tensor.elemwise.Sum', class {});\n        this.registerType('theano.tensor.nnet.abstract_conv.AbstractConv2d', class {});\n        this.registerType('theano.tensor.nnet.abstract_conv.AbstractConv2d_gradInputs', class {});\n        this.registerType('theano.tensor.nnet.abstract_conv.AbstractConv2d_gradWeights', class {});\n        this.registerType('theano.tensor.nnet.corr.CorrMM', class {});\n        this.registerType('theano.tensor.nnet.corr.CorrMM_gradInputs', class {});\n        this.registerType('theano.tensor.nnet.corr.CorrMM_gradWeights', class {});\n        this.registerType('theano.tensor.nnet.nnet.CrossentropyCategorical1Hot', class {});\n        this.registerType('theano.tensor.nnet.nnet.CrossentropyCategorical1HotGrad', class {});\n        this.registerType('theano.tensor.nnet.nnet.CrossentropySoftmax1HotWithBiasDx', class {});\n        this.registerType('theano.tensor.nnet.nnet.CrossentropySoftmaxArgmax1HotWithBias', class {});\n        this.registerType('theano.tensor.nnet.nnet.Softmax', class {});\n        this.registerType('theano.tensor.nnet.nnet.SoftmaxGrad', class {});\n        this.registerType('theano.tensor.nnet.nnet.SoftmaxWithBias', class {});\n        this.registerType('theano.tensor.opt.MakeVector', class {});\n        this.registerType('theano.tensor.opt.ShapeFeature', class {});\n        this.registerType('theano.tensor.sharedvar.TensorSharedVariable', class {});\n        this.registerType('theano.tensor.signal.pool.MaxPoolGrad', class {});\n        this.registerType('theano.tensor.signal.pool.Pool', class {});\n        this.registerType('theano.tensor.subtensor.Subtensor', class {});\n        this.registerType('theano.tensor.type.TensorType', class {});\n        this.registerType('theano.tensor.var.TensorConstant', class {});\n        this.registerType('theano.tensor.var.TensorConstantSignature', class {});\n        this.registerType('theano.tensor.var.TensorVariable', class {});\n        this.registerType('thinc.describe.Biases', class {});\n        this.registerType('thinc.describe.Dimension', class {});\n        this.registerType('thinc.describe.Gradient', class {});\n        this.registerType('thinc.describe.Weights', class {});\n        this.registerType('thinc.describe.Synapses', class {});\n        this.registerType('thinc.neural._classes.affine.Affine', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.convolution.ExtractWindow', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.feature_extracter.FeatureExtracter', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.feed_forward.FeedForward', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.function_layer.FunctionLayer', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.hash_embed.HashEmbed', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.layernorm.LayerNorm', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.maxout.Maxout', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.resnet.Residual', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural._classes.softmax.Softmax', class {\n            __setstate__(state) {\n                Object.assign(this, new pickle.Unpickler(state).load());\n            }\n        });\n        this.registerType('thinc.neural.mem.Memory', class {\n        });\n        this.registerType('thinc.neural.ops.NumpyOps', class {\n        });\n        this.registerType('__main__.BYOLState', class {\n            constructor(dict) {\n                Object.assign(this, dict);\n            }\n        });\n        const types = this.register('types');\n        this.registerType('types.GenericAlias', class {});\n        this.registerType('types.SimpleNamespace', class {});\n        this.registerType('types.BuiltinFunctionType', class {});\n        this.registerType('types.BuiltinMethodType', class {});\n        this.registerFunction('types.resolve_bases', (bases) => {\n            return bases;\n        });\n        this.registerFunction('types.prepare_class', (name, bases, kwds) => {\n            if (kwds) {\n                kwds = new builtins.dict(kwds);\n            } else {\n                kwds = new builtins.dict();\n            }\n            let meta = null;\n            if (kwds.__contains__('metaclass')) {\n                meta = kwds.pop('metaclass');\n            } else if (bases && bases.length > 0) {\n                meta = builtins.type(bases[0]);\n            } else {\n                meta = builtins.type;\n            }\n            if (meta instanceof builtins.type) {\n                meta = types._calculate_meta(meta, bases);\n            }\n            let ns = null;\n            if (builtins.hasattr(meta, '__prepare__')) {\n                // ns = meta.__prepare__(name, bases, **kwds)\n            } else {\n                ns = new builtins.dict();\n            }\n            return [meta, ns, kwds];\n        });\n        this.registerFunction('types._calculate_meta', (meta /*, bases*/) => {\n            const winner = meta;\n            return winner;\n        });\n        this.registerFunction('types.new_class', (name, bases, kwds, exec_body) => {\n            const resolved_bases = types.resolve_bases(bases);\n            const [meta, ns] = types.prepare_class(name, bases, kwds);\n            if (exec_body) {\n                exec_body(ns);\n            }\n            return new meta(name, resolved_bases, ns);\n        });\n        types.ObjectType = builtins.object;\n        types.ModuleType = builtins.module;\n        types.MethodType = builtins.method;\n        types.FunctionType = builtins.function;\n        types.TypeType = builtins.type;\n        types.CodeType = builtins.code;\n        this.registerType('xgboost.compat.XGBoostLabelEncoder', class {});\n        this.registerType('xgboost.core.Booster', class {\n            load_model(fname) {\n                if (fname instanceof Uint8Array) {\n                    // XGBoosterLoadModel()\n                } else {\n                    // XGBoosterUnserializeFromBuffer(handle) {\n                }\n            }\n            __setstate__(state) {\n                const handle = state.get('handle');\n                if (handle) {\n                    this.handle = handle;\n                    // XGBoosterLoadModelFromBuffer()\n                }\n            }\n        });\n        this.registerType('xgboost.sklearn.XGBClassifier', class {});\n        this.registerType('xgboost.sklearn.XGBRegressor', class {});\n        this.registerType('xgboost.sklearn.XGBRFClassifier', class {});\n        this.registerFunction('_codecs.encode', (obj, encoding) => {\n            return new builtins.bytearray(obj, encoding);\n        });\n        this.registerType('builtins.bytearray', class extends Uint8Array {\n            constructor(source, encoding /*, errors */) {\n                source = builtins.bytes.__encode__(source, encoding);\n                super(Number.isInteger(source) ? source : source.length);\n                if (Array.isArray(source)) {\n                    for (let i = 0; i < source.length; i++) {\n                        this[i] = source;\n                    }\n                } else if (source instanceof Uint8Array) {\n                    this.set(source, 0);\n                } else if (typeof source === 'string') {\n                    for (let i = 0; i < source.length; i++) {\n                        this[i] = source.charCodeAt(i);\n                    }\n                }\n            }\n            static __encode__(source, encoding) {\n                if (source === undefined) {\n                    return 0;\n                }\n                if (Number.isInteger(source)) {\n                    return source;\n                }\n                if (Array.isArray(source) || source instanceof Uint8Array) {\n                    return source;\n                }\n                if (typeof source === 'string') {\n                    switch (encoding) {\n                        case 'latin1':\n                        case 'latin-1':\n                            return source;\n                        case 'utf8':\n                        case 'utf-8':\n                            return new TextEncoder('utf-8').encode(source);\n                        case undefined:\n                            throw new python.Error('Unsupported string argument without an encoding.');\n                        default:\n                            throw new python.Error(`Unsupported encoding '${encoding}'.`);\n                    }\n                }\n                throw new python.Error('Unsupported source.');\n            }\n        });\n        this.registerType('builtins.bytes', class extends Uint8Array {\n            constructor(source, encoding /*, errors */) {\n                source = builtins.bytes.__encode__(source, encoding);\n                super(Number.isInteger(source) ? source : source.length);\n                if (Array.isArray(source)) {\n                    for (let i = 0; i < source.length; i++) {\n                        this[i] = source;\n                    }\n                } else if (source instanceof Uint8Array) {\n                    this.set(source, 0);\n                } else if (typeof source === 'string') {\n                    for (let i = 0; i < source.length; i++) {\n                        this[i] = source.charCodeAt(i);\n                    }\n                }\n            }\n            static __encode__(source, encoding) {\n                if (source === undefined) {\n                    return 0;\n                }\n                if (Number.isInteger(source)) {\n                    return source;\n                }\n                if (Array.isArray(source) || source instanceof Uint8Array) {\n                    return source;\n                }\n                if (typeof source === 'string') {\n                    switch (encoding) {\n                        case 'latin1':\n                        case 'latin-1':\n                            return source;\n                        case 'utf8':\n                        case 'utf-8':\n                            return new TextEncoder('utf-8').encode(source);\n                        case undefined:\n                            throw new python.Error('Unsupported string argument without an encoding.');\n                        default:\n                            throw new python.Error(`Unsupported encoding '${encoding}'.`);\n                    }\n                }\n                throw new python.Error('Unsupported source.');\n            }\n        });\n        this.registerType('builtins.memoryview', class {\n            constructor(buf) {\n                this._buf = buf;\n            }\n            get nbytes() {\n                return this._buf.length;\n            }\n        });\n        this.registerType('builtins.frozenset', class extends Set {\n            constructor(iterable) {\n                super();\n                if (iterable) {\n                    for (const item of iterable) {\n                        this.add(item);\n                    }\n                }\n            }\n        });\n        this.registerFunction('builtins.exec');\n        this.registerFunction('builtins.issubclass', (obj, type) => {\n            const name = `${type.__module__}.${type.__name__}`;\n            if (obj.__module__ && obj.__name__) {\n                if (name === `${obj.__module__}.${obj.__name__}`) {\n                    return true;\n                }\n            }\n            if (obj.__bases__) {\n                for (const base of obj.__bases__) {\n                    if (builtins.issubclass(base, type)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        });\n        this.registerFunction('builtins.isinstance', (obj, type) => {\n            if (obj && type && obj instanceof type) {\n                return true;\n            }\n            if (obj && obj.__class__) {\n                return builtins.issubclass(obj.__class__, type);\n            }\n            return false;\n        });\n        this.registerFunction('builtins.hasattr', (obj, name) => {\n            if (obj instanceof Map && obj.__contains__) {\n                return obj.__contains__(name);\n            }\n            return Object.prototype.hasOwnProperty.call(obj, name);\n        });\n        this.registerFunction('builtins.getattr', (obj, name, defaultValue) => {\n            if (obj && obj.__getattr__) {\n                return obj.__getattr__(name);\n            }\n            if (Object.prototype.hasOwnProperty.call(obj, name)) {\n                return obj[name];\n            }\n            return defaultValue;\n        });\n\n        this.registerFunction('builtins.len', (obj) => {\n            return obj.length;\n        });\n        this.registerFunction('builtins.setattr', (obj, name, value) => {\n            if (obj && obj.__setattr__) {\n                obj.__setattr__(name, value);\n            } else {\n                obj[name] = value;\n            }\n        });\n        this.registerType('builtins.set', class extends Set {\n            __contains__(item) {\n                return this.has(item);\n            }\n            update(iterable) {\n                for (const item of iterable) {\n                    this.add(item);\n                }\n            }\n        });\n        this.registerType('builtins.slice', class {\n            constructor(start, stop, step) {\n                this.start = start;\n                this.stop = stop;\n                this.step = step;\n            }\n        });\n        this.registerFunction('builtins.hash');\n        this.registerType('functools.partial', class {});\n        this.registerFunction('functools.reduce', (func, iterable, ...args) => {\n            const iter = Array.from(iterable);\n            let acc = args.length > 0 ? args[0] : iter.shift();\n            for (const item of iter) {\n                acc = func(acc, item);\n            }\n            return acc;\n        });\n        builtins.reduce = functools.reduce;\n        this.registerFunction('cloudpickle.cloudpickle._builtin_type', (name) => {\n            return name;\n        });\n        this.registerFunction('cloudpickle.cloudpickle._fill_function');\n\n        this.registerType('cloudpickle.cloudpickle._empty_cell_value', class {});\n        this.registerFunction('cloudpickle.cloudpickle._make_cell', (value) => {\n            value = value || cloudpickle.cloudpickle._empty_cell_value;\n            const cell = cloudpickle.cloudpickle._make_empty_cell();\n            if (value !== cloudpickle.cloudpickle._empty_cell_value) {\n                cell.cell_contents = value;\n            }\n            return cell;\n        });\n        this.registerFunction('cloudpickle.cloudpickle._make_function', (code, globals, name, argdefs, closure) => {\n            // globals[\"__builtins__\"] = __builtins__\n            return new types.FunctionType(code, globals, name, argdefs, closure);\n        });\n        this.registerFunction('cloudpickle.cloudpickle._make_skel_func');\n        cloudpickle.cloudpickle._DYNAMIC_CLASS_TRACKER_BY_ID = new builtins.dict();\n        this.registerFunction('cloudpickle.cloudpickle._lookup_class_or_track', (class_tracker_id, class_def) => {\n            if (class_tracker_id) {\n                class_def = cloudpickle.cloudpickle._DYNAMIC_CLASS_TRACKER_BY_ID.setdefault(class_tracker_id, class_def);\n            }\n            return class_def;\n        });\n        this.registerFunction('cloudpickle.cloudpickle._make_skeleton_class', (type_constructor, name, bases, type_kwargs, class_tracker_id /*, extra */) => {\n            // https://github.com/ray-project/ray/blob/5cd8967f1c0c16d3ae5fedb8449d0d25dd4f9f3e/python/ray/cloudpickle/cloudpickle.py#L523\n            const kwds = { 'metaclass': type_constructor };\n            const skeleton_class = types.new_class(name, bases, kwds, (ns) => ns.update(type_kwargs));\n            return cloudpickle.cloudpickle._lookup_class_or_track(class_tracker_id, skeleton_class);\n        });\n        this.registerFunction('cloudpickle.cloudpickle._make_empty_cell', () => {\n            return new builtins.cell();\n        });\n        this.registerFunction('cloudpickle.cloudpickle._class_setstate', (obj, state) => {\n            [state] = state;\n            let registry = null;\n            for (const [attrname, attr] of state.items()) {\n                if (attrname === '_abc_impl') {\n                    registry = attr;\n                } else {\n                    builtins.setattr(obj, attrname, attr);\n                }\n            }\n            if (sys.version_info >= (3, 13) && state.__contains__('__firstlineno__')) {\n                obj.__firstlineno__ = state.get('__firstlineno__');\n            }\n            if (registry) {\n                for (const subclass of registry) {\n                    obj.register(subclass);\n                }\n            }\n            return obj;\n        });\n        this.registerFunction('cloudpickle.cloudpickle._function_setstate', (obj, state) => {\n            const [, slotstate] = state;\n            [state] = state;\n            // obj.__dict__.update(state)\n            /* const obj_globals = */ slotstate.pop('__globals__');\n            const obj_closure = slotstate.pop('__closure__');\n            slotstate.pop('_cloudpickle_submodules');\n            if (obj.__globals__) {\n                // obj.__globals__.update(obj_globals);\n                // obj.__globals__.__builtins__ = __builtins__;\n            }\n            if (obj_closure) {\n                // let value = null;\n                for (let i = 0; i < obj_closure.length; i++) {\n                    // const cell = obj_closure[i];\n                    try {\n                        // value = cell.cell_contents;\n                    } catch {\n                        // cell is empty\n                    }\n                    // obj.__closure__[i].cell_contents = value;\n                }\n            }\n            for (const [k, v] of slotstate.items()) {\n                builtins.setattr(obj, k, v);\n            }\n        });\n        this.registerFunction('cloudpickle.cloudpickle.subimport', (name) => {\n            execution.__import__(name);\n            return sys.modules.get(name);\n        });\n        this.registerFunction('cloudpickle.cloudpickle_fast._class_setstate');\n        this.registerFunction('cloudpickle.cloudpickle_fast._function_setstate');\n        const ray = this.register('ray');\n        this.register('ray.cloudpickle.cloudpickle');\n        this.register('ray.cloudpickle.cloudpickle_fast');\n        ray.cloudpickle.cloudpickle._builtin_type = cloudpickle.cloudpickle._builtin_type;\n        ray.cloudpickle.cloudpickle._fill_function = cloudpickle.cloudpickle._fill_function;\n        ray.cloudpickle.cloudpickle._make_cell = cloudpickle.cloudpickle._make_cell;\n        ray.cloudpickle.cloudpickle._make_function = cloudpickle.cloudpickle._make_function;\n        ray.cloudpickle.cloudpickle._make_skel_func = cloudpickle.cloudpickle._make_skel_func;\n        ray.cloudpickle.cloudpickle._make_skeleton_class = cloudpickle.cloudpickle._make_skeleton_class;\n        ray.cloudpickle.cloudpickle._make_empty_cell = cloudpickle.cloudpickle._make_empty_cell;\n        ray.cloudpickle.cloudpickle._empty_cell_value = cloudpickle.cloudpickle._empty_cell_value;\n        ray.cloudpickle.cloudpickle._class_setstate = cloudpickle.cloudpickle._class_setstate;\n        ray.cloudpickle.cloudpickle._function_setstate = cloudpickle.cloudpickle._function_setstate;\n        ray.cloudpickle.cloudpickle._lookup_class_or_track = cloudpickle.cloudpickle._lookup_class_or_track;\n        ray.cloudpickle.cloudpickle_fast._class_setstate = cloudpickle.cloudpickle._class_setstate;\n        ray.cloudpickle.cloudpickle_fast._function_setstate = cloudpickle.cloudpickle._function_setstate;\n        this.registerType('ray.rllib.algorithms.ppo.ppo.PPO', class {});\n        this.registerType('ray.rllib.algorithms.ppo.ppo.PPOConfig', class {});\n        this.registerType('ray.rllib.algorithms.algorithm_config.AlgorithmConfig', class {});\n        this.registerFunction('ray.rllib.algorithms.algorithm_config.AlgorithmConfig.DEFAULT_POLICY_MAPPING_FN');\n        this.registerType('ray.rllib.algorithms.algorithm_config.TorchCompileWhatToCompile', class {});\n        this.registerType('ray.rllib.evaluation.collectors.simple_list_collector.SimpleListCollector', class {});\n        this.registerType('ray.rllib.callbacks.callbacks.RLlibCallback', class {});\n        this.registerType('ray.rllib.core.learner.learner.TorchCompileWhatToCompile', class {});\n        this.registerType('ray.rllib.policy.policy.PolicySpec', class {});\n        this.registerType('ray.rllib.policy.sample_batch.SampleBatch', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.mean.MeanStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.ema.EmaStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.min.MinStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.max.MaxStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.sum.SumStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.lifetime_sum.LifetimeSumStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.percentiles.PercentilesStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.item.ItemStats', class {});\n        this.registerType('ray.rllib.utils.metrics.stats.item_series.ItemSeriesStats', class {});\n        this.registerType('collections.Counter', class {});\n        this.registerFunction('collections.defaultdict', (/* default_factory */) => {\n            return {};\n        });\n        this.registerFunction('copy.deepcopy');\n        this.registerFunction('copy_reg._reconstructor', (cls, base, state) => {\n            // copyreg._reconstructor in Python 3\n            if (base === '__builtin__.object' || base === builtins.object) {\n                return self.invoke(cls, []);\n            } else if (base === '__builtin__.tuple' || base === builtins.tuple) {\n                const obj = self.invoke(cls, []);\n                for (let i = 0; i < state.length; i++) {\n                    obj[i] = state[i];\n                }\n                return obj;\n            }\n            throw new python.Error(`Unsupported copy_reg._reconstructor base type '${base}'.`);\n        });\n        this.registerFunction('copy.deepcopy', (/* x */) => {\n            throw new python.Error('Unsupported copy.deepcopy().');\n        });\n        this.registerFunction('dill._dill._create_array', (f, args, state, npdict) => {\n            const array = f(...args);\n            if (array.__setstate__) {\n                array.__setstate__(state);\n            }\n            if (npdict) {\n                throw new python.Error(\"'dill._dill._create_array::npdict' not implemented.\");\n            }\n            return array;\n        });\n        this.registerFunction('dill._dill._create_cell', (/* args */) => {\n            return function() {\n            };\n        });\n        this.registerFunction('dill._dill._create_code', (args) => {\n            return self.invoke('types.CodeType', [args]);\n        });\n        this.registerFunction('dill._dill._create_function', (/* fcode, fglobals, fname, fdefaults, fclosure, fdict, fkwdefaults */) => {\n            return function() {\n            };\n        });\n        this.registerFunction('dill._dill._create_namedtuple', (name, fieldnames, modulename /*, defaults */) => {\n            const obj = execution.invoke('dill._dill._import_module', [`${modulename}.${name}`]);\n            if (obj) {\n                return obj;\n            }\n            return undefined;\n        });\n        this.registerFunction('dill._dill._create_type', (typeobj, ...args) => {\n            const [name, bases, dict] = args;\n            const type = class extends bases[0] {};\n            const identifier = dict.__contains__('__module__') ? `${dict.__getitem__('__module__')}.${name}` : name;\n            return self.registerType(identifier, Object.assign(type, dict));\n        });\n        this.registerFunction('dill._dill._eval_repr');\n        this.registerFunction('dill._dill._get_attr', (self, name) => {\n            if (Object.prototype.hasOwnProperty.call(self, name)) {\n                return self[name];\n            }\n            return undefined;\n        });\n        this.registerFunction('dill._dill._import_module', (import_name, safe) => {\n            try {\n                if (import_name.startsWith('__runtime__.')) {\n                    return execution.module(import_name);\n                } else if (import_name.indexOf('.') === -1) {\n                    return execution.__import__(import_name);\n                }\n                return execution.resolve(import_name);\n            } catch (error) {\n                if (safe) {\n                    return null;\n                }\n                throw error;\n            }\n        });\n        this.registerFunction('dill._dill._load_type', (name) => {\n            const _dill = self.register('dill._dill');\n            if (!_dill._reverse_typemap) {\n                _dill._reverse_typemap = new Map();\n                for (const name of ['__builtin__', 'types']) {\n                    const module = self.register(name);\n                    for (const [name, obj] of Object.entries(module)) {\n                        if (obj.__module__ === 'builtins' && obj.__class__ === builtins.type) {\n                            _dill._reverse_typemap.set(name, obj);\n                        }\n                    }\n                }\n                _dill._reverse_typemap.set('PartialType', functools.partial);\n                _dill._reverse_typemap.set('CellType', builtins.cell);\n            }\n            if (!_dill._reverse_typemap.has(name)) {\n                throw new python.Error(`Unknown type name '${name}' in 'dill._dill._load_type'.`);\n            }\n            return _dill._reverse_typemap.get(name);\n        });\n        this.registerFunction('dill._dill.loads');\n        this.registerFunction('jax._src.array._reconstruct_array', (fun, args, arr_state, aval_state) => {\n            const np_value = fun(...args);\n            np_value.__setstate__(arr_state);\n            const jnp_value = jax.device_put(np_value);\n            jnp_value.aval = jnp_value.aval.update(aval_state);\n            return jnp_value;\n        });\n        jax._src.device_array.reconstruct_device_array = jax._src.array._reconstruct_array;\n        this.registerFunction('jax.device_put', (x) => {\n            const aval = new jax._src.core.ShapedArray(x.shape, x.dtype);\n            return new jax.Array(aval, x.data);\n        });\n        this.registerType('jax._src.core.AbstractValue', class {});\n        this.registerType('jax._src.core.UnshapedArray',  class extends jax._src.core.AbstractValue {});\n        this.registerType('jax._src.core.ShapedArray', class extends jax._src.core.UnshapedArray {\n            constructor(shape, dtype, weak_type) {\n                super();\n                this.shape = shape;\n                this.dtype = dtype;\n                this.weak_type = weak_type || false;\n            }\n            update(dict) {\n                const shape = dict.get('shape') || this.shape;\n                const dtype = dict.get('dtype') || this.dtype;\n                const weak_type = dict.get('weak_type') || this.weak_type;\n                return new jax._src.core.ShapedArray(shape, dtype, weak_type);\n            }\n        });\n        this.registerType('jax.Array', class {\n            constructor(aval, data) {\n                this.aval = aval;\n                this.data = data;\n            }\n            get dtype() {\n                return this.aval.dtype;\n            }\n            get shape() {\n                return this.aval.shape;\n            }\n            tobytes() {\n                return this.data;\n            }\n        });\n        jax.numpy.ndarray = jax.Array;\n        this.registerFunction('keras.saving.pickle_utils.deserialize_model_from_bytecode', (/* serialized_model */) => {\n            return null; // throw new python.Error(\"'keras.saving.pickle_utils.deserialize_model_from_bytecode' not implemented.\");\n        });\n        this.registerFunction('keras.src.saving.pickle_utils.deserialize_model_from_bytecode', keras.saving.pickle_utils.deserialize_model_from_bytecode);\n        this.registerFunction('lasagne.nonlinearities.rectify');\n        this.registerFunction('lasagne.nonlinearities.softmax');\n        this.registerFunction('lasagne.objectives.categorical_crossentropy');\n        this.registerFunction('lasagne.updates.nesterov_momentum');\n        this.registerFunction('msgpack.unpackb', (packed, ext_hook) => {\n            const BinaryReader = class {\n                constructor(buffer, ext_hook) {\n                    // https://github.com/msgpack/msgpack-javascript/blob/master/src/Decoder.ts\n                    // https://github.com/msgpack/msgpack-python/blob/main/msgpack/_unpacker.pyx\n                    this._buffer = buffer;\n                    this._position = 0;\n                    this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n                    this._ext_hook = ext_hook;\n                }\n                value() {\n                    const c = this._view.getUint8(this.skip(1));\n                    if (c >= 0xe0) {\n                        return c - 0x100;\n                    }\n                    if (c < 0xC0) {\n                        if (c < 0x80) {\n                            return c;\n                        }\n                        if (c < 0x90) {\n                            return this.map(c - 0x80);\n                        }\n                        if (c < 0xa0) {\n                            return this.array(c - 0x90);\n                        }\n                        return this.string(c - 0xa0);\n                    }\n                    switch (c) {\n                        case 0xC0: return null;\n                        case 0xC2: return false;\n                        case 0xC3: return true;\n                        case 0xC4: return this.read(this._view.getUint8(this.skip(1)));\n                        case 0xC5: return this.read(this._view.getUint16(this.skip(2)));\n                        case 0xC6: return this.read(this._view.getUint32(this.skip(4)));\n                        case 0xC7: return this.extension(this._view.getUint8(this.skip(1)));\n                        case 0xC8: return this.extension(this._view.getUint16(this.skip(2)));\n                        case 0xC9: return this.extension(this._view.getUint32(this.skip(4)));\n                        case 0xCA: return this._view.getFloat32(this.skip(4));\n                        case 0xCB: return this._view.getFloat64(this.skip(8));\n                        case 0xCC: return this._view.getUint8(this.skip(1));\n                        case 0xCD: return this._view.getUint16(this.skip(2));\n                        case 0xCE: return this._view.getUint32(this.skip(4));\n                        case 0xCF: return this._view.getBitUint64(this.skip(8));\n                        case 0xD0: return this._view.getInt8(this.skip(1));\n                        case 0xD1: return this._view.getInt16(this.skip(2));\n                        case 0xD2: return this._view.getInt32(this.skip(4));\n                        case 0xD3: return this._view.getBigInt64(this.skip(8));\n                        case 0xD4: return this.extension(1);\n                        case 0xD5: return this.extension(2);\n                        case 0xD6: return this.extension(4);\n                        case 0xD7: return this.extension(8);\n                        case 0xD8: return this.extension(16);\n                        case 0xD9: return this.string(this._view.getUint8(this.skip(1)));\n                        case 0xDA: return this.string(this._view.getUint16(this.skip(2)));\n                        case 0xDB: return this.string(this._view.getUint32(this.skip(4)));\n                        case 0xDC: return this.array(this._view.getUint16(this.skip(2)));\n                        case 0xDD: return this.array(this._view.getUint32(this.skip(4)));\n                        case 0xDE: return this.map(this._view.getUint16(this.skip(2)));\n                        case 0xDF: return this.map(this._view.getUint32(this.skip(4)));\n                        default: throw new python.Error(`Invalid code '${c}'.`);\n                    }\n                }\n                map(size) {\n                    const map = {};\n                    for (let i = 0; i < size; i++) {\n                        const key = this.value();\n                        const value = this.value();\n                        map[key] = value;\n                    }\n                    return map;\n                }\n                array(size) {\n                    const array = new Array(size);\n                    for (let i = 0; i < size; i++) {\n                        array[i] = this.value();\n                    }\n                    return array;\n                }\n                extension(size) {\n                    const code = this._view.getUint8(this.skip(1));\n                    const data = this.read(size);\n                    return this._ext_hook(code, data);\n                }\n                skip(offset) {\n                    const position = this._position;\n                    this._position += offset;\n                    if (this._position > this._buffer.length) {\n                        throw new python.Error(`Expected ${this._position - this._buffer.length} more bytes. The file might be corrupted. Unexpected end of file.`);\n                    }\n                    return position;\n                }\n                read(size) {\n                    const data = this._buffer.subarray(this._position, this._position + size);\n                    this._position += size;\n                    return data;\n                }\n                string(size) {\n                    const buffer = this.read(size);\n                    this._decoder = this._decoder || new TextDecoder('utf8');\n                    return this._decoder.decode(buffer);\n                }\n            };\n            return new BinaryReader(packed, ext_hook).value();\n        });\n        this.registerFunction('nolearn.lasagne.base.objective');\n        this.registerFunction('numpy.core._DType_reconstruct');\n        this.registerFunction('numpy.core._ufunc_reconstruct');\n        this.registerFunction('numpy.core.multiarray._reconstruct', (subtype, shape, dtype) => {\n            return numpy.ndarray.__new__(subtype, shape, dtype);\n        });\n        this.registerFunction('numpy.core.multiarray.frombuffer', (buf, dtype) => {\n            const shape = [buf.length / dtype.itemsize];\n            return new numpy.ndarray(shape, dtype, buf);\n        });\n        this.registerFunction('numpy._core.numeric._frombuffer', (buf, dtype, shape, order) => {\n            return numpy._core.multiarray.frombuffer(buf, dtype).reshape(shape, order);\n        });\n        this.registerFunction('numpy._core._internal._convert_to_stringdtype_kwargs', () => {\n            return new numpy.dtypes.StringDType();\n        });\n        this.registerFunction('numpy.core.multiarray.scalar', (dtype, rawData) => {\n            let data = rawData;\n            if (typeof rawData === 'string' || rawData instanceof String) {\n                data = new Uint8Array(rawData.length);\n                for (let i = 0; i < rawData.length; i++) {\n                    data[i] = rawData.charCodeAt(i);\n                }\n            }\n            switch (dtype.kind) {\n                case 'b': {\n                    const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                    switch (dtype.itemsize) {\n                        case 1: return view.getInt8(0) ? true : false;\n                        default: throw new python.Error(`Unsupported scalar dtype boolean itemsize '${dtype.itemsize}'.`);\n                    }\n                }\n                case 'f': {\n                    const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                    switch (dtype.itemsize) {\n                        case 2: return view.getFloat16(0, dtype.byteorder === '<');\n                        case 4: return view.getFloat32(0, dtype.byteorder === '<');\n                        case 8: return view.getFloat64(0, dtype.byteorder === '<');\n                        default: throw new python.Error(`Unsupported scalar dtype float itemsize '${dtype.itemsize}'.`);\n                    }\n                }\n                case 'i': {\n                    const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                    switch (dtype.itemsize) {\n                        case 1: return view.getInt8(0);\n                        case 2: return view.getInt16(0, dtype.byteorder === '<');\n                        case 4: return view.getInt32(0, dtype.byteorder === '<');\n                        case 8: return view.getBigInt64(0, dtype.byteorder === '<');\n                        default: throw new python.Error(`Unsupported scalar dtype int itemsize '${dtype.itemsize}'.`);\n                    }\n                }\n                case 'u': {\n                    const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                    switch (dtype.itemsize) {\n                        case 1: return view.getUint8(0);\n                        case 2: return view.getUint16(0, dtype.byteorder === '<');\n                        case 4: return view.getUint32(0, dtype.byteorder === '<');\n                        case 8: return view.getBigUint64(0, dtype.byteorder === '<');\n                        default: throw new python.Error(`Unsupported scalar dtype uint itemsize '${dtype.itemsize}'.`);\n                    }\n                }\n                case 'U': {\n                    const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n                    const list = [];\n                    for (let i = 0; i < dtype.itemsize; i += 4) {\n                        list.push(String.fromCodePoint(view.getUint32(i, true)));\n                    }\n                    return list.join('');\n                }\n                default: {\n                    throw new python.Error(`Unsupported scalar dtype kind '${dtype.kind}'.`);\n                }\n            }\n        });\n        this.registerFunction('numpy.core._multiarray_umath.cbrt');\n        this.registerFunction('numpy.core._multiarray_umath.fmin');\n        this.registerFunction('numpy.core._multiarray_umath.fmax');\n        this.registerFunction('numpy.core._multiarray_umath.greater');\n        this.registerFunction('numpy.core._multiarray_umath.less');\n        this.registerFunction('numpy.core._multiarray_umath.log');\n        this.registerFunction('numpy.core._multiarray_umath.scalar', (dtype, rawData) => {\n            let data = rawData;\n            if (typeof rawData === 'string') {\n                data = new Uint8Array(rawData.length);\n                for (let i = 0; i < rawData.length; i++) {\n                    data[i] = rawData.charCodeAt(i);\n                }\n            }\n            const dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);\n            switch (dtype.__name__) {\n                case 'uint8':\n                    return dataView.getUint8(0);\n                case 'float32':\n                    return dataView.getFloat32(0, true);\n                case 'float64':\n                    return dataView.getFloat64(0, true);\n                case 'int8':\n                    return dataView.getInt8(0, true);\n                case 'int16':\n                    return dataView.getInt16(0, true);\n                case 'int32':\n                    return dataView.getInt32(0, true);\n                case 'int64':\n                    return dataView.getBigInt64(0, true);\n                default:\n                    throw new python.Error(`Unsupported scalar type '${dtype.__name__}'.`);\n            }\n        });\n        this.registerFunction('numpy.core._multiarray_umath.sin');\n        this.registerFunction('numpy.core._multiarray_umath.sqrt');\n        this.register('numpy._core.multiarray', numpy.core.multiarray);\n        this.register('numpy._core._multiarray_umath', numpy.core._multiarray_umath);\n        this.register('numpy._core._multiarray_umath', numpy.core._multiarray_umath);\n        this.register('numpy.core.numeric', numpy._core.numeric);\n        numpy._core._multiarray_umath._reconstruct = numpy.core.multiarray._reconstruct;\n        this.registerFunction('numpy.load', (file) => {\n            // https://github.com/numpy/numpy/blob/main/numpy/lib/_format_impl.py\n            const signature = [0x93, 0x4E, 0x55, 0x4D, 0x50, 0x59];\n            if (!file.read(6).every((v, i) => v === signature[i])) {\n                throw new python.Error('Invalid signature.');\n            }\n            const version = file.read(2);\n            const [major, minor] = version;\n            if (major > 3) {\n                throw new python.Error(`Invalid version '${[major, minor].join('.')}'.`);\n            }\n            const [shape, fortran_order, dtype] = numpy.lib._format_impl._read_array_header(file, version);\n            let data = null;\n            switch (dtype.byteorder) {\n                case '|': {\n                    data = file.read();\n                    if (dtype.kind === 'O') {\n                        const unpickler = new pickle.Unpickler(data);\n                        return unpickler.load();\n                    }\n                    break;\n                }\n                case '>':\n                case '<': {\n                    const count = shape.length === 0 ? 1 : shape.reduce((a, b) => a * b, 1);\n                    const stream = file.getbuffer().nbytes > 0x1000000;\n                    data = file.read(dtype.itemsize * count, stream);\n                    break;\n                }\n                default: {\n                    throw new python.Error(`Unsupported data type '${dtype.str}'.`);\n                }\n            }\n            const order = fortran_order ? 'F' : 'C';\n            return new numpy.ndarray(shape, dtype, data, undefined, undefined, order);\n        });\n        this.registerFunction('numpy.save', (file, arr) => {\n            const descr = arr.dtype.str;\n            if (descr[0] !== '<' && descr[0] !== '>') {\n                throw new python.Error(`Unsupported byte order '${descr}'.`);\n            }\n            if ((descr.length !== 3 && descr.substring(1) !== 'c16') || (descr[1] !== 'f' && descr[1] !== 'i' && descr[1] !== 'u' && descr[1] !== 'c' && descr.substring(1) !== 'b1')) {\n                throw new python.Error(`Unsupported data type '${descr}'.`);\n            }\n            let shape = '';\n            switch (arr.shape.length) {\n                case 0: shape = '()'; break;\n                case 1: shape = `(${arr.shape[0]},)`; break;\n                default: shape = `(${arr.shape.map((dimension) => dimension.toString()).join(', ')})`; break;\n            }\n            const properties = [\n                `'descr': '${descr}'`,\n                \"'fortran_order': False\",\n                `'shape': ${shape}`\n            ];\n            let header = `{ ${properties.join(', ')} }`;\n            header += `${' '.repeat(64 - ((header.length + 2 + 8 + 1) & 0x3f))}\\n`;\n            const encoder = new TextEncoder('ascii');\n            file.write([0x93, 0x4E, 0x55, 0x4D, 0x50, 0x59, 0x01, 0x00]); // '\\\\x93NUMPY' + version\n            file.write([header.length & 0xff, (header.length >> 8) & 0xff]);\n            file.write(encoder.encode(header));\n            file.write(arr.tobytes());\n        });\n        this.registerFunction('numpy.lib._format_impl._read_array_header', (file, version) => {\n            const buffer = new Uint8Array([0, 0, 0, 0]);\n            const [major] = version;\n            buffer.set(file.read(major >= 2 ? 4 : 2), 0);\n            const header_length = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];\n            let header = file.read(header_length);\n            const decoder = new TextDecoder(major >= 3 ? 'utf-8' : 'ascii');\n            header = decoder.decode(header).trim();\n            try {\n                header = ast.literal_eval(header);\n            } catch {\n                if (major <= 2) {\n                    header = numpy.lib._format_impl._filter_header(header);\n                    header = ast.literal_eval(header);\n                }\n            }\n            if (header.descr === undefined) {\n                throw new python.Error(\"Invalid 'descr'.\");\n            }\n            if (!Array.isArray(header.shape)) {\n                throw new python.Error(\"Invalid 'shape'.\");\n            }\n            const dtype = numpy.lib._format_impl.descr_to_dtype(header.descr);\n            return [header.shape, header.fortran_order, dtype];\n        });\n        this.registerFunction('numpy.lib._format_impl.descr_to_dtype', (descr) => {\n            if (typeof descr === 'string') {\n                return new numpy.dtype(descr);\n            } else if (descr instanceof builtins.tuple) {\n                const dt = numpy.lib._format_impl.descr_to_dtype(descr[0]);\n                return new numpy.dtype([dt, descr[1]]);\n            }\n            const titles = [];\n            const names = [];\n            const formats = [];\n            const offsets = [];\n            let offset = 0;\n            for (const field of descr) {\n                let name = null;\n                let dt = null;\n                let descr_str = null;\n                let shape = null;\n                let title = null;\n                if (field.length === 2) {\n                    [name, descr_str] = field;\n                    dt = numpy.lib._format_impl.descr_to_dtype(descr_str);\n                } else {\n                    [name, descr_str, shape] = field;\n                    dt = new numpy.dtype([numpy.lib._format_impl.descr_to_dtype(descr_str), shape]);\n                }\n                const is_pad = name === '' && dt.type === numpy.void && dt.names === null;\n                if (!is_pad) {\n                    [title, name] = name instanceof builtins.tuple ? name :  [null, name];\n                    titles.push(title);\n                    names.push(name);\n                    formats.push(dt);\n                    offsets.push(offset);\n                }\n                offset += dt.itemsize;\n            }\n            return new numpy.dtype({ names, formats, titles, offsets, itemsize: offset });\n        });\n        this.registerFunction('numpy.lib._format_impl._filter_header', (s) => {\n            const tokens = [];\n            const tokenizer = new ast._Tokenizer(s, '');\n            while (!tokenizer.match('eof')) {\n                const token = tokenizer.read();\n                if (token.type === 'int') {\n                    const next = tokenizer.peek();\n                    if (next.type === 'id' && next.value === 'L') {\n                        tokenizer.read();\n                    }\n                }\n                tokens.push(token.value);\n            }\n            return tokens.join('');\n        });\n        this.registerFunction('numpy.amin');\n        this.registerFunction('numpy.amax');\n        this.registerFunction('numpy.std');\n        this.registerFunction('numpy.asarray', (a, dtype) => {\n            const encode = (context, data, dim) => {\n                const size = context.shape[dim];\n                const littleendian = context.littleendian;\n                if (dim === context.shape.length - 1) {\n                    for (let i = 0; i < size; i++) {\n                        switch (context.dtype) {\n                            case 'f2':\n                                context.view.setFloat16(context.position, data[i], littleendian);\n                                break;\n                            case 'f4':\n                                context.view.setFloat32(context.position, data[i], littleendian);\n                                break;\n                            case 'f8':\n                                context.view.setFloat64(context.position, data[i], littleendian);\n                                break;\n                            case 'i1':\n                                context.view.setInt8(context.position, data[i], littleendian);\n                                break;\n                            case 'i2':\n                                context.view.setInt16(context.position, data[i], littleendian);\n                                break;\n                            case 'i4':\n                                context.view.setInt32(context.position, data[i], littleendian);\n                                break;\n                            case 'i8':\n                                context.view.setBigInt64(context.position, typeof data[i] === 'number' ? BigInt(data[i]) : data[i], littleendian);\n                                break;\n                            case 'u1':\n                                context.view.setUint8(context.position, data[i], littleendian);\n                                break;\n                            case 'u2':\n                                context.view.setUint16(context.position, data[i], littleendian);\n                                break;\n                            case 'u4':\n                                context.view.setUint32(context.position, data[i], littleendian);\n                                break;\n                            case 'u8':\n                                context.view.setComplexFloat16(context.position, data[i], littleendian);\n                                break;\n                            case 'c8':\n                                context.view.setComplexFloat32(context.position, data[i], littleendian);\n                                break;\n                            case 'c16':\n                                context.view.setComplexFloat64(context.position, data[i], littleendian);\n                                break;\n                            case 'b1':\n                                context.view.setInt8(context.position, data[i] ? 1 : 0);\n                                break;\n                            default:\n                                throw new python.Error(`Unsupported tensor data type '${context.dtype}'.`);\n                        }\n                        context.position += context.itemsize;\n                    }\n                } else {\n                    for (let j = 0; j < size; j++) {\n                        encode(context, data[j], dim + 1);\n                    }\n                }\n            };\n            const array_size = (value) => {\n                if (value.every((item) => Array.isArray(item))) {\n                    const dims = value.map((item) => array_size(item));\n                    const [dim] = dims;\n                    for (let i = 1; i < dims.length; i++) {\n                        if (dim.length === dims[i].length) {\n                            if (!dims[i].every((value, i) => value === dim[i])) {\n                                throw new python.Error('Invalid array shape.');\n                            }\n                        }\n                    }\n                    return [value.length].concat(dim);\n                }\n                return [value.length];\n            };\n            const shape = Array.isArray(a) ? array_size(a) : [];\n            const size = dtype.itemsize * shape.reduce((a, b) => a * b, 1);\n            const context = {\n                position: 0,\n                itemsize: dtype.itemsize,\n                dtype: dtype.str.substring(1),\n                littleendian: dtype.str[0],\n                shape,\n                data: new Uint8Array(size)\n            };\n            context.view = new DataView(context.data.buffer, context.data.byteOffset, size);\n            encode(context, a, 0);\n            return self.invoke('numpy.ndarray', [shape, dtype, context.data]);\n        });\n        this.registerFunction('numpy.max');\n        this.registerFunction('numpy.mean');\n        this.registerFunction('numpy.min');\n        this.registerFunction('numpy.ma.core._mareconstruct', (subtype, baseclass, baseshape, basetype) => {\n            const data = self.invoke(baseclass, [baseshape, basetype]);\n            // = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype))\n            const mask = self.invoke('numpy.ndarray', [baseshape, '']);\n            return self.invoke(subtype, [data, mask, basetype]);\n        });\n        this.registerFunction('numpy.random.__RandomState_ctor', () => {\n            return {};\n        });\n        this.registerFunction('numpy.random._pickle.__randomstate_ctor', () => {\n            return {};\n        });\n        this.registerType('numpy.random.bit_generator.BitGenerator', class {\n            __setstate__(state) {\n                if (state instanceof Map || !Array.isArray(state)) {\n                    this.state = state;\n                } else {\n                    [this.state, this._seed_seq] = state;\n                }\n            }\n        });\n        this.registerType('numpy.random.bit_generator.SeedSequence', class extends builtins.object {\n            __setstate__(state) {\n                [this.entropy, this.n_children_spawned, this.pool, this.pool_size, this.spawn_key] = state;\n            }\n        });\n        this.registerFunction('numpy.random.bit_generator.__pyx_unpickle_SeedSequence', (cls, checksum, state) => {\n            const obj = new cls();\n            if (state) {\n                obj.__setstate__(state);\n            }\n            return obj;\n        });\n        this.registerType('numpy.random._mt19937.MT19937', class extends numpy.random.bit_generator.BitGenerator {});\n        this.registerType('numpy.random._pcg64.PCG64', class extends numpy.random.bit_generator.BitGenerator {});\n        this.registerType('numpy.random._pcg64.PCG64DXSM', class extends numpy.random.bit_generator.BitGenerator {});\n        this.registerType('numpy.random._philox.Philox', class extends numpy.random.bit_generator.BitGenerator {});\n        this.registerType('numpy.random._sfc64.SFC64', class extends numpy.random.bit_generator.BitGenerator {});\n        numpy.random._pickle.BitGenerators = {\n            'MT19937': numpy.random._mt19937.MT19937,\n            'PCG64': numpy.random._pcg64.PCG64,\n            'PCG64DXSM': numpy.random._pcg64.PCG64DXSM,\n            'Philox': numpy.random._philox.Philox,\n            'SFC64': numpy.random._sfc64.SFC64,\n        };\n        this.registerType('numpy.random._generator.Generator', class {\n            constructor(bit_generator) {\n                this.bit_generator = bit_generator;\n            }\n        });\n        this.registerFunction('numpy.random._pickle.__bit_generator_ctor', (bit_generator) => {\n            bit_generator = bit_generator || 'MT19937';\n            let bit_gen_class = null;\n            if (builtins.isinstance(bit_generator, builtins.type)) {\n                bit_gen_class = bit_generator;\n            } else {\n                bit_gen_class = numpy.random._pickle.BitGenerators[bit_generator];\n            }\n            if (bit_gen_class) {\n                return new bit_gen_class();\n            }\n            throw new python.Error(`Unknown bit generator '${bit_generator}'.`);\n        });\n        this.registerFunction('numpy.random._pickle.__generator_ctor', (bit_generator_name, bit_generator_ctor) => {\n            if (bit_generator_name instanceof numpy.random.bit_generator.BitGenerator) {\n                return new numpy.random._generator.Generator(bit_generator_name);\n            }\n            bit_generator_ctor = bit_generator_ctor || numpy.random._pickle.__bit_generator_ctor;\n            return new numpy.random._generator.Generator(bit_generator_ctor(bit_generator_name));\n        });\n        this.registerFunction('numpy.reshape');\n        this.registerFunction('sklearn.feature_selection._mutual_info.mutual_info_regression');\n        this.registerFunction('sklearn.feature_selection._univariate_selection.f_classif');\n        this.registerFunction('sklearn.feature_selection._univariate_selection.f_regression');\n        this.registerFunction('sklearn.metrics.scorer._passthrough_scorer');\n        this.registerFunction('sklearn.metrics._classification.accuracy_score');\n        this.registerFunction('sklearn.metrics._classification.balanced_accuracy_score');\n        this.registerFunction('sklearn.metrics._classification.cohen_kappa_score');\n        this.registerFunction('sklearn.metrics._classification.f1_score');\n        this.registerFunction('sklearn.metrics._classification.log_loss');\n        this.registerFunction('sklearn.metrics._classification.precision_score');\n        this.registerFunction('sklearn.metrics._classification.recall_score');\n        this.registerFunction('sklearn.metrics._dist_metrics.newObj', (obj) => {\n            return obj.__new__(obj);\n        });\n        this.registerFunction('sklearn.metrics._ranking.roc_auc_score');\n        this.registerFunction('sklearn.metrics._regression.mean_absolute_error');\n        this.registerFunction('sklearn.metrics._regression.mean_absolute_percentage_error');\n        this.registerFunction('sklearn.metrics._regression.mean_squared_error');\n        this.registerFunction('sklearn.metrics._regression.r2_score');\n        sklearn.metrics.regression = sklearn.metrics._regression;\n        sklearn.metrics.r2_score = sklearn.metrics._regression.r2_score;\n        this.registerFunction('sklearn.metrics._regression.root_mean_squared_error');\n        this.registerFunction('sklearn.metrics._scorer._passthrough_scorer');\n        this.registerFunction('re._compile', (pattern, flags) => {\n            return self.invoke('re.Pattern', [pattern, flags]);\n        });\n        this.registerFunction('srsly.cloudpickle.cloudpickle._builtin_type', (...args) => {\n            return function() {\n                return self.invoke(`types.${args[0]}`, args);\n            };\n        });\n        this.registerType('sympy.printing.defaults.Printable', class {});\n        this.registerType('sympy.core.basic.Basic', class extends sympy.printing.defaults.Printable {\n            constructor(...args) {\n                super();\n                this._args = args;\n            }\n            get args() {\n                return this._args;\n            }\n        });\n        this.registerType('sympy.core.function.Function', class extends sympy.core.basic.Basic {\n        });\n        this.registerType('sympy.core.expr.Expr', class extends sympy.core.basic.Basic {\n        });\n        this.registerType('sympy.core.operations.AssocOp', class extends sympy.core.expr.Expr /* sympy.core.basic.Basic */ {});\n        this.registerType('sympy.core.power.Pow', class extends sympy.core.expr.Expr {\n            __str__() {\n                return this._args.map((a) => a.__str__()).join('**');\n            }\n        });\n        this.registerType('sympy.core.add.Add', class extends sympy.core.operations.AssocOp {\n            __str__() {\n                return this._args.map((a) => a.__str__()).join(' + ');\n            }\n        });\n        this.registerType('sympy.core.mul.Mul', class extends sympy.core.operations.AssocOp {\n            __str__() {\n                return this._args.map((a) => a.__str__()).join('*');\n            }\n        });\n        this.registerType('sympy.core.numbers.Float', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.core.numbers.Half', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.core.numbers.NegativeOne', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.core.numbers.Number', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.core.numbers.One', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.core.numbers.Rational', class extends sympy.core.numbers.Number {});\n        this.registerType('sympy.core.numbers.Integer', class extends sympy.core.numbers.Rational {\n            constructor(value) {\n                super();\n                this.value = value;\n                this.is_Integer = true;\n            }\n            __int__() {\n                return this.value;\n            }\n            __str__() {\n                return this.value.toString();\n            }\n        });\n        this.registerType('sympy.core.numbers.Zero', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.core.symbol.Symbol', class extends sympy.core.expr.Expr {\n            constructor(name) {\n                super();\n                this.name = name;\n            }\n            __int__() {\n                throw new python.Error('Cannot convert symbols to int.');\n            }\n            __str__() {\n                return this.name;\n            }\n        });\n        this.registerType('sympy.core.relational.Relational', class extends sympy.core.expr.Expr {\n            constructor(lhs, rhs, op) {\n                super();\n                this._args = [lhs, rhs];\n                this._op = op;\n            }\n            __str__() {\n                return `${this._args[0].__str__()} ${this._op} ${this._args[1].__str__()}`;\n            }\n        });\n        this.registerType('sympy.core.relational._Inequality', class extends sympy.core.relational.Relational {\n        });\n        this.registerType('sympy.core.relational._Greater', class extends sympy.core.relational._Inequality {\n        });\n        this.registerType('sympy.core.relational.GreaterThan', class extends sympy.core.relational._Greater {\n            constructor(lhs, rhs) {\n                super(lhs, rhs, '>=');\n            }\n        });\n        this.registerType('sympy.core.relational._Less', class extends sympy.core.relational._Inequality {\n        });\n        this.registerType('sympy.core.relational.LessThan', class extends sympy.core.relational.Relational {\n            constructor(lhs, rhs) {\n                super(lhs, rhs, '<=');\n            }\n        });\n        this.registerType('sympy.core.relational.StrictLessThan', class extends sympy.core.relational.Relational {\n            constructor(lhs, rhs) {\n                super(lhs, rhs, '<');\n            }\n        });\n        this.registerType('sympy.core.relational.StrictGreaterThan', class extends sympy.core.relational.Relational {\n            constructor(lhs, rhs) {\n                super(lhs, rhs, '>');\n            }\n        });\n        this.registerType('sympy.core.relational.Equality', class extends sympy.core.relational.Relational {\n            constructor(lhs, rhs) {\n                super(lhs, rhs, '==');\n            }\n        });\n        this.registerType('sympy.functions.elementary.miscellaneous.MinMaxBase', class extends sympy.core.expr.Expr {\n        });\n        this.registerType('sympy.functions.elementary.miscellaneous.Max', class extends sympy.functions.elementary.miscellaneous.MinMaxBase {\n            __str__() {\n                return `Max(${this._args.map((a) => a.__str__()).join(', ')})`;\n            }\n        });\n        this.registerType('sympy.functions.elementary.exponential.exp', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.functions.elementary.exponential.log', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.functions.elementary.piecewise.ExprCondPair', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.functions.elementary.piecewise.Piecewise', class extends sympy.core.expr.Expr {});\n        this.registerType('sympy.logic.boolalg.BooleanFalse', class extends sympy.core.basic.Basic {});\n        this.registerType('sympy.logic.boolalg.BooleanTrue', class extends sympy.core.basic.Basic {});\n        this.registerType('sympy.logic.boolalg.ITE', class extends sympy.core.basic.Basic {});\n        this.registerType('sympy.logic.boolalg.Or', class extends sympy.core.basic.Basic {});\n        this.registerFunction('sympy.core.sympify.sympify', (a /*, locals */) => {\n            if (a instanceof sympy.core.expr.Expr) {\n                return a;\n            }\n            const p = ast.parse(a);\n            const sympify = (node) => {\n                if (node instanceof ast.Call) {\n                    switch (node.func.id) {\n                        case 'Symbol': return new sympy.core.symbol.Symbol(node.args[0].value);\n                        case 'Mul': return new sympy.core.mul.Mul(...node.args.map((arg) => sympify(arg)));\n                        case 'Add': return new sympy.core.add.Add(...node.args.map((arg) => sympify(arg)));\n                        case 'Pow': return new sympy.core.power.Pow(...node.args.map((arg) => sympify(arg)));\n                        case 'Max': return new sympy.functions.elementary.miscellaneous.Max(...node.args.map((arg) => sympify(arg)));\n                        case 'Integer': return sympify(node.args[0]);\n                        case 'GreaterThan': return new sympy.core.relational.GreaterThan(sympify(node.args[0]), sympify(node.args[1]));\n                        case 'StrictGreaterThan': return new sympy.core.relational.StrictGreaterThan(sympify(node.args[0]), sympify(node.args[1]));\n                        case 'LessThan': return new sympy.core.relational.LessThan(sympify(node.args[0]), sympify(node.args[1]));\n                        case 'StrictLessThan': return new sympy.core.relational.StrictLessThan(sympify(node.args[0]), sympify(node.args[1]));\n                        case 'Equality': return new sympy.core.relational.Equality(sympify(node.args[0]), sympify(node.args[1]));\n                        case 'FloorDiv': return new torch.utils._sympy.functions.FloorDiv(sympify(node.args[0]), sympify(node.args[1]));\n                        default: throw new python.Error(`Unsupported SymPy function '${node.func.id}'.`);\n                    }\n                }\n                if (node instanceof ast.Name) {\n                    return new sympy.core.symbol.Symbol(node.id);\n                }\n                if (node instanceof ast.Constant) {\n                    if (node.type === 'int') {\n                        return new sympy.core.numbers.Integer(node.value);\n                    }\n                }\n                if (node instanceof ast.UnaryOp && node.op instanceof ast.USub) {\n                    const operand = sympify(node.operand);\n                    return new sympy.core.numbers.Integer(-operand.value);\n                }\n                if (node instanceof ast.BinOp) {\n                    if (node.op instanceof ast.Mult) {\n                        return new sympy.core.mul.Mul(sympify(node.left), sympify(node.right));\n                    }\n                    if (node.op instanceof ast.Pow) {\n                        return new sympy.core.power.Pow(sympify(node.left), sympify(node.right));\n                    }\n                    throw new python.Error(`Unsupported SymPy BinOp op '${node.op.__class__.__name__}'.`);\n                }\n                if (node instanceof ast.Compare) {\n                    const left = sympify(node.left);\n                    const right = sympify(node.comparators[0]);\n                    const [op] = node.ops;\n                    if (op instanceof ast.Gt) {\n                        return new sympy.core.relational.StrictGreaterThan(left, right);\n                    }\n                    if (op instanceof ast.GtE) {\n                        return new sympy.core.relational.GreaterThan(left, right);\n                    }\n                    if (op instanceof ast.Lt) {\n                        return new sympy.core.relational.StrictLessThan(left, right);\n                    }\n                    if (op instanceof ast.LtE) {\n                        return new sympy.core.relational.LessThan(left, right);\n                    }\n                    if (op instanceof ast.Eq) {\n                        return new sympy.core.relational.Equality(left, right);\n                    }\n                    throw new python.Error(`Unsupported comparison operator '${op.__class__.__name__}'.`);\n                }\n                throw new python.Error(`Unsupported SymPy expression '${node.__class__.__name__}'.`);\n            };\n            return sympify(p.body[0].value);\n        });\n        this.registerFunction('theano.scalar.basic.same_out');\n        this.registerFunction('theano.scalar.basic.same_out_nocomplex');\n        this.registerFunction('theano.scalar.basic.upcast_out');\n        this.registerFunction('theano.scalar.basic.upgrade_to_float');\n        this.registerFunction('theano.tensor.nnet.conv2d');\n        this.registerFunction('theano.tensor.type.values_eq_approx_remove_inf_nan');\n        this.registerFunction('theano.tensor.type.values_eq_approx_remove_nan');\n        this.registerType('torch.nn.modules.module.Module', class {\n            constructor() {\n                this._modules = new collections.OrderedDict();\n                this._parameters = new collections.OrderedDict();\n                this._buffers = new collections.OrderedDict();\n            }\n            __setattr__(name, value) {\n                if (value instanceof torch.nn.modules.module.Module) {\n                    this._modules.set(name, value);\n                } else {\n                    this[name] = value;\n                }\n            }\n            __getattr__(name) {\n                if (this._modules.has(name)) {\n                    return this._modules.get(name);\n                }\n                return this[name];\n            }\n            __delattr__(name) {\n                if (this._modules.has(name)) {\n                    this._modules.delete(name);\n                }\n            }\n            children() {\n                return this._modules.values();\n            }\n            named_modules(memo, prefix, remove_duplicate) {\n                memo = memo || new Set();\n                prefix = prefix || '';\n                const modules = new builtins.dict();\n                if (!memo.has(this)) {\n                    if (remove_duplicate) {\n                        memo.add(this);\n                    }\n                    modules.set(prefix, this);\n                    for (const [name, module] of this._modules.items()) {\n                        if (module && module.named_modules) {\n                            const submodule_prefix = `${prefix}${(prefix ? '.' : '')}${name}`;\n                            for (const [k, v] of module.named_modules(memo, submodule_prefix, remove_duplicate)) {\n                                modules.set(k, v);\n                            }\n                        }\n                    }\n                }\n                return modules;\n            }\n            named_children() {\n                return this._modules;\n            }\n            parameters() {\n                return this._parameters.values();\n            }\n            named_parameters(recurse) {\n                if (recurse) {\n                    throw new python.Error('Named parameters with recurse not implemented.');\n                }\n                return this._parameters;\n            }\n            buffers() {\n                return this._buffers.values();\n            }\n            named_buffers(recurse) {\n                if (recurse) {\n                    throw new python.Error('Named parameters with recurse not implemented.');\n                }\n                return this._buffers;\n            }\n            _get_name() {\n                return this.__class__.__name__;\n            }\n            add_module(name, module) {\n                this._modules.set(name, module);\n            }\n            register_module(name, module) {\n                this.add_module(name, module);\n            }\n        });\n        torch.nn.Module = torch.nn.modules.module.Module;\n        torch.nn.modules.Module = torch.nn.modules.module.Module;\n        this.registerType('torch._C.Generator', class {});\n        this.registerType('torch._C._TensorBase', class extends builtins.object {});\n        this.registerType('torch._C._TensorMeta', class extends builtins.type {});\n        this.registerType('torch._C._VariableFunctionsClass', class extends builtins.object {});\n        this.registerType('torch._C.SchemaParser', class {\n            constructor(str, allow_typevars) {\n                this.L = new torch._C.Lexer(str);\n                this.type_parser = new torch._C.SchemaTypeParser(this.L, false, allow_typevars);\n            }\n            parseName() {\n                const L = this.L;\n                let name = L.expect('id').text();\n                if (L.nextIf(':')) {\n                    L.expect(':');\n                    name = `${name}::${L.expect('ident').text()}`;\n                }\n                let overload_name = '';\n                if (L.nextIf('.')) {\n                    overload_name = L.expect('ident').text();\n                }\n                // const is_a_valid_overload_name = !((overload_name === \"default\") || (overload_name.rfind(\"__\", 0) == 0));\n                // TORCH_CHECK(is_a_valid_overload_name, overload_name, \" is not a legal overload name for aten operators\");\n                return new torch._C.OperatorName(name, overload_name);\n            }\n            parseDeclaration() {\n                const L = this.L;\n                const name = this.parseName();\n                if (L.cur().kind !== '(') {\n                    return name;\n                }\n                throw new python.Error('Not implemented.');\n            }\n            parseExactlyOneDeclaration() {\n                // const L = this.L;\n                const result = this.parseDeclaration();\n                // L.nextIf(TK_NEWLINE);\n                // L.expect(TK_EOF);\n                return result;\n            }\n            parseArgument(idx, is_return, kwarg_only) {\n                const L = this.L;\n                const type_parser = this.type_parser;\n                let [fake_type, real_type, alias_info] = type_parser.parseFakeAndRealType();\n                let N = null;\n                if (L.nextIf('[')) {\n                    fake_type = torch.ListType.create(fake_type);\n                    real_type = torch.ListType.create(real_type);\n                    if (L.cur().kind === '#') {\n                        N = Number(L.cur().text());\n                        L.next();\n                    }\n                    L.expect(']');\n                    let container = type_parser.parseAliasAnnotation();\n                    if (alias_info) {\n                        if (!container) {\n                            container = new torch._C.AliasInfo();\n                            container.is_write = alias_info.is_write;\n                        }\n                        container.addContainedType(alias_info);\n                    }\n                    alias_info = container;\n                    if (L.nextIf('?')) {\n                        fake_type = torch.OptionalType.create(fake_type);\n                        real_type = torch.OptionalType.create(real_type);\n                    }\n                }\n                let name = null;\n                /* eslint-disable no-undef-init */\n                let default_value = undefined;\n                /* eslint-enable no-undef-init */\n                if (is_return) {\n                    kwarg_only = false;\n                    if (L.cur().kind === 'id') {\n                        name = L.next().text();\n                    } else {\n                        name = '';\n                    }\n                } else {\n                    name = L.expect('id').text();\n                    if (L.nextIf('=')) {\n                        default_value = this.parseDefaultValue(fake_type, fake_type.kind(), real_type, N);\n                    }\n                }\n                return new torch.Argument(name, fake_type, real_type, N, default_value, kwarg_only, alias_info);\n            }\n            parseDefaultValue(arg_type, kind, real_type, arg_N) {\n                // auto range = L.cur().range;\n                const L = this.L;\n                const range = null;\n                switch (kind) {\n\n                    case torch._C.TypeKind.StringType:\n                    case torch._C.TypeKind.OptionalType:\n                    case torch._C.TypeKind.NumberType:\n                    case torch._C.TypeKind.IntType:\n                    case torch._C.TypeKind.BoolType:\n                    case torch._C.TypeKind.FloatType:\n                    case torch._C.TypeKind.ComplexType:\n                        return this.parseSingleConstant(arg_type, kind, real_type);\n                    case torch._C.TypeKind.ListType: {\n                        const elem_type = arg_type.containedType(0);\n                        const real_elem_type = real_type.containedType(0);\n                        if (L.cur().kind === 'id') {\n                            return this.parseTensorDefault(range);\n                        } else if (arg_N && L.cur().kind !== '[') {\n                            const v = this.parseSingleConstant(elem_type, elem_type.kind(), real_elem_type);\n                            const repeated = Array(arg_N).fill(v);\n                            // std::vector<IValue> repeated(arg_N, v);\n                            return this.convertToList(elem_type, elem_type.kind(), range, repeated);\n                        }\n                        return this.parseConstantList(elem_type, elem_type.kind(), real_elem_type);\n                    }\n                    case torch._C.TypeKind.DynamicType:\n                        return this.parseDefaultValue(arg_type, arg_type.dynamicKind(), real_type, arg_N);\n                    default:\n                        throw new python.Error(`Unsupported default value kind '${kind}'.`);\n                }\n            }\n            parseSingleConstant(type, kind, real_type) {\n                const L = this.L;\n                if (kind === torch._C.TypeKind.DynamicType) {\n                    return this.parseSingleConstant(type, type.dynamicKind(), real_type);\n                }\n                // const auto& str2dtype = c10::getStringToDtypeMap();\n                if (L.cur().kind === 'id') {\n                    if (L.cur().text() === 'True') {\n                        L.next();\n                        return new torch._C.IValue(true);\n                    }\n                    if (L.cur().text() === 'False') {\n                        L.next();\n                        return new torch._C.IValue(false);\n                    }\n                    if (L.cur().text() === 'None') {\n                        L.next();\n                        return new torch._C.IValue();\n                    }\n                } else if (L.cur().kind === 'string') {\n                    const token = L.next();\n                    return new torch._C.IValue(torch._C.parseStringLiteral(null, token.text()));\n                } else if (L.cur().kind === '#') {\n                    let n = '';\n                    if (L.nextIf('-')) {\n                        n = `-${L.expect('#').text()}`; // # .text();\n                    } else {\n                        n = L.expect('#').text(); // # .text();\n                    }\n                    if (kind === torch._C.TypeKind.ComplexType || n.indexOf('j') !== -1) {\n                        throw new Error(\"Complex type not implemented.\");\n                        /*\n                        const imag = std::stod(n.substr(0, n.size() - 1));\n                        return c10::complex<double>(0, imag);\n                        */\n                    } else if (kind === torch._C.TypeKind.FloatType || n.indexOf('.') !== -1 || n.indexOf('e') !== -1) {\n                        const v = parseFloat(n);\n                        return new torch._C.IValue(v, 'Double');\n                    } else {\n                        const v = parseInt(n, 10);\n                        return new torch._C.IValue(v, 'Int');\n                    }\n                }\n                throw new python.Error('Not implemented.');\n                /*\n                switch (L.cur().kind) {\n                    case TK_TRUE:\n                        L.next();\n                        return true;\n                    case TK_FALSE:\n                        L.next();\n                        return false;\n                    case TK_NONE:\n                        L.next();\n                        return IValue();\n                    case TK_STRINGLITERAL: {\n                        const token = L.next();\n                        return parseStringLiteral(token.range, token.text());\n                    }\n                    case TK_IDENT: {\n                        const tok = L.next();\n                        const text_view = tok.text_view();\n                        // NB: float/complex/long are here for BC purposes. Other dtypes\n                        // are handled via str2dtype.\n                        // Please don't add more cases to this if-else block.\n                        if (\"float\" == text_view) {\n                            return static_cast<int64_t>(\"at::kFloat\");\n                        } else if (\"complex\" == text_view) {\n                            return static_cast<int64_t>(\"at::kComplexFloat\");\n                        } else if (\"long\" == text_view) {\n                            return static_cast<int64_t>(\"at::kLong\");\n                        } else if (\"strided\" == text_view) {\n                            return static_cast<int64_t>(\"at::kStrided\");\n                        } else if (\"Mean\" == text_view) {\n                            return static_cast<int64_t>(\"at::Reduction::Mean\");\n                        } else if (\"contiguous_format\" == text_view) {\n                            return static_cast<int64_t>(\"c10::MemoryFormat::Contiguous\");\n                        } else {\n                            const text = tok.text();\n                            if (isPossiblyOptionalScalarType(real_type) &&\n                                str2dtype.count(text) > 0) {\n                                return static_cast<int64_t>(str2dtype.at(text));\n                            } else {\n                                throw(ErrorReport(L.cur().range) << \"invalid numeric default value\");\n                            }\n                        }\n                    }\n                    default: {\n                        let n;\n                        if (L.nextIf('-')) {\n                            n = \"-\" + L.expect(TK_NUMBER).text();\n                        }\n                        else {\n                            n = L.expect(TK_NUMBER).text();\n                        }\n                        if (kind == torch._C.TypeKind.ComplexType || n.find('j') != \"std::string::npos\") {\n                            throw new python.Error('Complex type not implemented.');\n                            const imag = std::stod(n.substr(0, n.size() - 1));\n                            return c10::complex<double>(0, imag);\n                        } else if (kind == torch._C.TypeKind.FloatType || n.find('.') != \"std::string::npos\" || n.find('e') != \"std::string::npos\") {\n                            throw new python.Error('Float type not implemented.');\n                            return std::stod(n);\n                        } else {\n                            throw new python.Error(\"'torch._C.SchemaParser.parseSingleConstant' not implemented.\");\n                            int64_t v = std::stoll(n);\n                            return v;\n                        }\n                    }\n                }\n                */\n            }\n            parseConstantList(type, kind, real_type) {\n                const L = this.L;\n                const tok = L.expect('[');\n                const vs = [];\n                if (L.cur().kind !== ']') {\n                    do {\n                        vs.push(this.parseSingleConstant(type, kind, real_type));\n                    } while (L.nextIf(','));\n                }\n                L.expect(']');\n                return this.convertToList(type, kind, tok.range, vs);\n            }\n            convertToList(type, kind, range, vs) {\n                switch (kind) {\n                    case torch._C.TypeKind.ComplexType:\n                        return new torch._C.IValue(new torch._C.List(torch.ComplexType.get(), vs.map((v) => v)));\n                    case torch._C.TypeKind.FloatType:\n                        return new torch._C.IValue(new torch._C.List(torch.FloatType.get(), vs.map((v) => v)));\n                    case torch._C.TypeKind.IntType:\n                        return new torch._C.IValue(new torch._C.List(torch.IntType.get(), vs.map((v) => v)));\n                    case torch._C.TypeKind.BoolType:\n                        return new torch._C.IValue(new torch._C.List(torch.BoolType.get(), vs.map((v) => v)));\n                    case torch._C.TypeKindDynamicType:\n                        return this.convertToList(type.dynamicKind(), range, vs);\n                    default:\n                        // throw(ErrorReport(range) << \"lists are only supported for float, int and complex types\");\n                        throw new python.Error('lists are only supported for float, int and complex types');\n                }\n            }\n        });\n        this.registerType('torch.FunctionSchema', class {\n            constructor(name, overload_name, args, returns, is_vararg, is_varret) {\n                const index = name.indexOf('(');\n                if (index === -1) {\n                    this._name = name;\n                    this._overload_name = overload_name || '';\n                    this._arguments = args || [];\n                    this._returns = returns || [];\n                    this._is_vararg = is_vararg || false;\n                    this._is_varret = is_varret || false;\n                } else {\n                    const value = name.substring(0, index).trim();\n                    const dot = value.indexOf('.');\n                    if (dot === -1) {\n                        this._name = value;\n                        this._overload_name = '';\n                    } else {\n                        this._name = value.substring(0, dot);\n                        this._overload_name = value.substring(dot + 1, value.length);\n                    }\n                    this._buffer = name.substring(index, name.length);\n                }\n            }\n            static parse(schema) {\n                return new torch.FunctionSchema(schema);\n            }\n            get name() {\n                return this._name;\n            }\n            get overload_name() {\n                return this._overload_name;\n            }\n            get arguments() {\n                this._parse();\n                return this._arguments;\n            }\n            get returns() {\n                this._parse();\n                return this._returns;\n            }\n            get is_vararg() {\n                this._parse();\n                return this._is_vararg;\n            }\n            get is_varret() {\n                this._parse();\n                return this._is_varret;\n            }\n            argumentIndexWithName(name) {\n                const index = this.arguments.findIndex((arg) => arg.name === name);\n                return index === -1 ? null : index;\n            }\n            _parse() {\n                if (this._buffer) {\n                    const parser = new torch._C.SchemaParser(this._buffer, true /* parseSchemaOrName */);\n                    const L = parser.L;\n                    this._arguments = [];\n                    this._is_vararg = false;\n                    this._kwarg_only = false;\n                    let idx = 0;\n                    L.expect('(');\n                    if (!L.nextIf(')')) {\n                        while (true) {\n                            if (this._is_vararg) {\n                                throw new python.Error(\"Unexpected 'torch.FunctionSchema._is_vararg'.\");\n                            }\n                            if (L.nextIf('*')) {\n                                this._kwarg_only = true;\n                            } else if (L.nextIf('...')) {\n                                this._is_vararg = true;\n                            } else {\n                                const argument = parser.parseArgument(idx++, false, this._kwarg_only);\n                                this._arguments.push(argument);\n                            }\n                            if (!L.nextIf(',')) {\n                                break;\n                            }\n                        }\n                        L.expect(')');\n                    }\n                    L.expect('->');\n                    this._returns = [];\n                    this._is_varret = false;\n                    if (L.nextIf('...')) {\n                        this._is_varret = true;\n                    } else if (L.nextIf('(')) {\n                        if (!L.nextIf(')')) {\n                            while (true) {\n                                if (this._is_varret) {\n                                    throw new python.Error(\"Unexpected 'torch.FunctionSchema._is_varret'.\");\n                                }\n                                if (L.nextIf('...')) {\n                                    this._is_varret = true;\n                                } else {\n                                    const argument = parser.parseArgument(idx++, true, false);\n                                    this._returns.push(argument);\n                                }\n                                if (!L.nextIf(',')) {\n                                    break;\n                                }\n                            }\n                            L.expect(')');\n                        }\n                    } else {\n                        this._returns.push(parser.parseArgument(0, true, false));\n                    }\n                    delete this._buffer;\n                }\n            }\n            __str__() {\n                const list = [this.name];\n                const overload_name = this.overload_name;\n                if (overload_name !== '' && overload_name !== 'default') {\n                    list.push(`.${this.overload_name}`);\n                }\n                list.push('(');\n                let first = true;\n                let kwarg_only = false;\n                for (const argument of this.arguments) {\n                    if (!first) {\n                        list.push(', ');\n                    }\n                    if (argument.kwarg_only && !kwarg_only) {\n                        list.push('*, ');\n                        kwarg_only = true;\n                    }\n                    first = false;\n                    list.push(argument.str());\n                }\n                if (this.is_vararg) {\n                    if (!first) {\n                        list.push(', ');\n                    }\n                    first = true;\n                    list.push('...');\n                }\n                list.push(') -> ');\n                const returns = this.returns;\n                const braces = !this.is_varret &&\n                   (returns.length !== 1 ||\n                    returns[0].name ||\n                    returns[0].real_type instanceof torch.TupleType ||\n                    returns[0].real_type instanceof torch.ListType && returns[0].real_type.getElementType() instanceof torch.TupleType);\n                if (braces) {\n                    list.push('(');\n                }\n                first = true;\n                for (const argument of this.returns) {\n                    if (!first) {\n                        list.push(', ');\n                    }\n                    first = false;\n                    list.push(argument.str());\n                }\n                if (this.is_varret) {\n                    if (!first) {\n                        list.push(', ');\n                    }\n                    first = true;\n                    list.push('...');\n                }\n                if (braces) {\n                    list.push(')');\n                }\n                return list.join('');\n            }\n            aliasAnalysis() {\n                return this._alias_kind || 'CONSERVATIVE';\n            }\n            setAliasAnalysis(v) {\n                this._alias_kind = v;\n            }\n            hasAnyAliasInfo() {\n                for (const arg of this.arguments) {\n                    if (arg.alias_info !== null) {\n                        return true;\n                    }\n                }\n                for (const ret of this.returns) {\n                    if (ret.alias_info !== null) {\n                        return true;\n                    }\n                }\n                return false;\n            }\n            is_mutable() {\n                return this.arguments.some((arg) => {\n                    const aliasInfo = arg.alias_info;\n                    return aliasInfo && aliasInfo.is_write;\n                });\n            }\n        });\n        this.registerType('torch._C.SchemaInfo', class {\n            constructor(schema) {\n                this._schema = schema;\n                this._alias_maps_current = false;\n                this._has_init = false;\n            }\n            is_nondeterministic() {\n                if (this._schema.name === 'aten::dropout' && this._schema.overload === '') {\n                    //\n                }\n                torch._C.nondeterministic_op_strings = torch._C.nondeterministic_op_strings || new Set([\n                    'aten::dropout(Tensor input, float p, bool train) -> Tensor',\n                    'aten::_fused_dropout(Tensor self, float p, Generator? generator) -> (Tensor, Tensor)',\n                    'aten::_standard_gamma(Tensor self, Generator? generator) -> Tensor',\n                    'aten::bernoulli(Tensor self, *, Generator? generator) -> Tensor',\n                    'aten::bernoulli(Tensor self, float p, *, Generator? generator) -> Tensor',\n                    'aten::multinomial(Tensor self, int num_samples, bool replacement, *, Generator? generator) -> Tensor',\n                    'aten::native_dropout(Tensor input, float p, bool? train) -> (Tensor, Tensor)',\n                    'aten::normal(Tensor mean, Tensor std, *, Generator? generator) -> Tensor',\n                    'aten::normal(float mean, Tensor std, *, Generator? generator) -> Tensor',\n                    'aten::normal(Tensor mean, float std, *, Generator? generator) -> Tensor',\n                    'aten::poisson(Tensor self, Generator? generator) -> Tensor',\n                    'aten::binomial(Tensor count, Tensor prob, Generator? generator=None) -> Tensor',\n                    'aten::rrelu(Tensor self, Scalar lower, Scalar upper, bool training, Generator? generator) -> Tensor',\n                    'aten::rrelu_with_noise(Tensor self, Tensor noise, Scalar lower, Scalar upper, bool training, Generator? generator) -> Tensor',\n                    'aten::rand(int[] size, *, int? dtype, int? layout, Device? device, bool? pin_memory) -> Tensor',\n                    'aten::rand_like(Tensor self, *, int? dtype=None, int? layout=None, Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor',\n                    'aten::randint(int high, int[] size, *, int? dtype, int? layout, Device? device, bool? pin_memory) -> Tensor',\n                    'aten::randint(int low, int high, int[] size, *, int? dtype, int? layout, Device? device, bool? pin_memory) -> Tensor',\n                    'aten::randint_like(Tensor self, int high, *, int? dtype=None, int? layout=None, Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor',\n                    'aten::randint_like(Tensor self, int low, int high, *, int? dtype=None, int? layout=None, Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor',\n                    'aten::randn(int[] size, *, int? dtype, int? layout, Device? device, bool? pin_memory) -> Tensor',\n                    'aten::randn_like(Tensor self, *, int? dtype=None, int? layout=None, Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor',\n                    'aten::randperm(int n, *, int? dtype, int? layout, Device? device, bool? pin_memory) -> Tensor'\n                ]);\n                if (torch._C.nondeterministic_op_strings.has(this._schema.__str__())) {\n                    return true;\n                }\n                /*\n                const auto& op = c10::Dispatcher::singleton().findOp(\n                    c10::OperatorName(schema_.name(), schema_.overload_name()));\n                return op && op->hasTag(at::Tag::nondeterministic_seeded);\n                */\n                return false;\n            }\n        });\n        this.registerType('torch._C.OperatorRegistry', class {\n            constructor() {\n                this.to_register = [];\n                this.operators = new Map();\n            }\n            registerPendingOperators() {\n                for (const op of this.to_register) {\n                    const sym = op.schema().name;\n                    if (!this.operators.has(sym)) {\n                        this.operators.set(sym, []);\n                    }\n                    this.operators.get(sym).push(op);\n                }\n                this.to_register = [];\n            }\n            registerOperator(op) {\n                this.to_register.push(op);\n            }\n            getOperators(name) {\n                this.registerPendingOperators();\n                if (this.operators.has(name)) {\n                    return this.operators.get(name);\n                }\n                return [];\n            }\n        });\n        this.registerFunction('torch._C.getAllOperatorsFor', (name) => {\n            return torch._C.getRegistry().getOperators(name);\n        });\n        this.registerType('torch._C.Operator', class {\n            constructor(schema) {\n                this._schema = schema;\n            }\n            schema() {\n                return this._schema;\n            }\n            getOperation(/* node */) {\n                return null;\n            }\n            aliasAnalysisKind() {\n                const schemaRef = this.schema();\n                const alias_analysis = schemaRef.aliasAnalysis();\n                torch._C.TORCH_CHECK(alias_analysis === 'FROM_SCHEMA' || !schemaRef.hasAnyAliasInfo());\n                return alias_analysis;\n            }\n        });\n        this.registerFunction('torch._C.getRegistry', () => {\n            torch._C.r = torch._C.r || new torch._C.OperatorRegistry();\n            return torch._C.r;\n        });\n        this.registerFunction('torch._C._get_schema', (op_name, overload_name) => {\n            const operations = torch._C.getAllOperatorsFor(op_name);\n            for (const op of operations) {\n                if (op.schema().overload_name === overload_name) {\n                    return op.schema();\n                }\n            }\n            throw new python.Error(`Schema '${op_name}.${overload_name}' not found.`);\n        });\n        this.registerFunction('torch._C._jit_get_schemas_for_operator', (op_name) => {\n            return torch._C.getAllOperatorsFor(op_name).map((op) => op.schema());\n        });\n        this.registerFunction('torch._C._jit_get_operation', (op_name) => {\n            const sortedOps = torch._C.getAllOperatorsFor(op_name);\n            if (sortedOps.length === 0) {\n                return [null, null];\n            }\n            const overload_names = sortedOps.map((op) => op.schema().overload_name);\n            return [{}, overload_names];\n        });\n        this.registerFunction('torch._C._get_operation_overload', (op_name, overload_name) => {\n            const operations = torch._C.getAllOperatorsFor(op_name);\n            for (const op of operations) {\n                if (op.schema().overload_name === overload_name) {\n                    return [{}, {}, null];\n                }\n            }\n            return null;\n        });\n        this.registerFunction('torch._C._unset_dispatch_mode', () => {\n            return null;\n        });\n        this.registerFunction('torch._C._set_dispatch_mode', () => {\n        });\n        this.registerType('torch._C.MatchedSchema', class {\n            constructor(inputs, return_types, return_field_names, schema_name) {\n                this.inputs = inputs;\n                this.return_types = return_types;\n                this.return_field_names = return_field_names;\n                this.schema_name = schema_name;\n            }\n        });\n        this.registerType('torch._C.Self', class {\n        });\n        this.registerFunction('torch._C.toValues', (g, nvs) => {\n            return nvs.map((v) => v.value(g));\n        });\n        this.registerType('torch._C.SimpleSelf', class extends torch._C.Self {\n            constructor(classType) {\n                super();\n                this._classType = classType;\n            }\n            makeSugared(v) {\n                v.setType(this._classType);\n                return new torch._C.SimpleValue(v);\n            }\n            getClassType() {\n                return this._classType;\n            }\n        });\n        this.registerType('torch._C.Function', class {\n            isGraphFunction() {\n                return false;\n            }\n            name() {\n                return this.qualname().name();\n            }\n        });\n        this.registerType('torch._C.BuiltinOpFunction', class extends torch._C.Function {\n            constructor(qualname, schema) {\n                super();\n                this._name = qualname;\n                this._schema = schema;\n            }\n            qualname() {\n                return this._name;\n            }\n            getSchema() {\n                return this._schema;\n            }\n            ensure_defined() {\n            }\n        });\n        this.registerType('torch._C.DeadCodeEliminator', class {\n            constructor(...args) {\n                this._aliasDb = null;\n                this._useAliasDb = false;\n                this._memo = new Map();\n                this._marked = new Set();\n                this._liveValues = new Set();\n                this._deleteCallback = () => {};\n                if (args.length > 0 && args[0] instanceof torch.Graph) {\n                    [this._graph, this._sideEffectPolicy] = args;\n                    this._useAliasDb = true;\n                } else {\n                    [this._sideEffectPolicy] = args;\n                }\n            }\n            run(block, recurse) {\n                this.eliminateDeadForkInputs(block, recurse);\n                this.mark(block.return_node());\n                this.mark(block);\n                this._deleteCallback(this._liveValues);\n                this.sweep(block, recurse);\n            }\n            setDeleteCallback(deleteCallback) {\n                this._deleteCallback = deleteCallback;\n            }\n            eliminateDeadForkInputs(block, recurse) {\n                for (const node of block.nodes()) {\n                    if (recurse) {\n                        for (const sb of node.blocks()) {\n                            this.eliminateDeadForkInputs(sb, recurse);\n                        }\n                    }\n                    if (node.kind() !== 'prim::fork') {\n                        continue;\n                    }\n                    const g = node.g(\"Subgraph\");\n                    for (let i = 0; i < g.inputs().length; i++) {\n                        if (!g.inputs()[i].hasUses()) {\n                            g.eraseInput(i);\n                            node.removeInput(i);\n                        }\n                    }\n                }\n            }\n            markReturnNode(node) {\n                if (this._marked.has(node)) {\n                    return false;\n                }\n                torch._C.AT_ASSERT(node.owningBlock().return_node() === node);\n                const outerNode = node.owningBlock().owningNode();\n                if (outerNode === null || outerNode.kind() === 'prim::Reverse') {\n                    return this.mark(node);\n                }\n                if (outerNode.kind() === 'prim::Loop' || outerNode.kind() === 'c10::onnx::Loop') {\n                    const loop = new torch._C.LoopView(outerNode);\n                    for (let i = 0; i < loop.carriedOutputs().length; i++) {\n                        if (outerNode.kind() === 'onnx::Loop') {\n                            this._liveValues.add(loop.bodyCarriedOutputs()[i]);\n                            continue;\n                        }\n                        const innerInput = loop.bodyCarriedInputs()[i];\n                        const innerOutput = loop.bodyCarriedOutputs()[i];\n                        const outerOutput = loop.carriedOutputs()[i];\n                        if (this._liveValues.has(outerOutput) || innerInput.hasUses()) {\n                            this._liveValues.add(innerOutput);\n                        }\n                    }\n                    this._liveValues.add(loop.nextCond());\n                } else {\n                    torch._C.AT_ASSERT(outerNode.outputs().length === node.inputs().length);\n                    for (let i = 0; i < outerNode.outputs().length; i++) {\n                        const innerOutput = node.inputs()[i];\n                        const outerOutput = outerNode.outputs()[i];\n                        if (!this._liveValues.has(outerOutput)) {\n                            this._liveValues.add(innerOutput);\n                        }\n                    }\n                }\n                this._marked.add(node);\n                return true;\n            }\n            markLoop(node) {\n                torch._C.TORCH_INTERNAL_ASSERT(node.kind() === 'prim::Loop');\n                let marked = false;\n                let anyMarked = false;\n                do {\n                    marked = this.mark(node.blocks().at(0));\n                    anyMarked = anyMarked || marked;\n                } while (marked);\n                return anyMarked;\n            }\n            mark(...args) {\n                if (args.length === 1 && args[0] instanceof torch.Block) {\n                    const [block] = args;\n                    let anyMarked = false;\n                    for (const node of block.nodes()) {\n                        if (this._sideEffectPolicy === 'DONT_DELETE_NODES_WITH_SIDE_EFFECTS' && this.hasSideEffects(node)) {\n                            const marked = this.mark(node);\n                            anyMarked = anyMarked || marked;\n                        }\n                    }\n                    const marked = this.markReturnNode(block.return_node());\n                    anyMarked = anyMarked || marked;\n                    for (const node of block.nodes()) {\n                        if (node.kind() === 'prim::Loop') {\n                            const marked = this.markLoop(node);\n                            anyMarked = anyMarked || marked;\n                        } else {\n                            for (const subBlock of node.blocks()) {\n                                const marked = this.mark(subBlock);\n                                anyMarked = anyMarked || marked;\n                            }\n                        }\n                        const marked = this.markIfLive(node);\n                        anyMarked = anyMarked || marked;\n                    }\n                    return anyMarked;\n                }\n                if (args.length === 1 && args[0] instanceof torch.Node) {\n                    const [node] = args;\n                    if (this._marked.has(node)) {\n                        return false;\n                    }\n                    this._marked.add(node);\n                    let curNode = node;\n                    while (curNode && curNode.owningBlock()) {\n                        this.mark(curNode);\n                        curNode = curNode.owningBlock().owningNode();\n                    }\n                    for (const input of node.inputs()) {\n                        if (!this._liveValues.has(input)) {\n                            this._liveValues.add(input);\n                        }\n                    }\n                    return true;\n                }\n                throw new python.Error('Not implemented.');\n            }\n            markIfLive(node) {\n                for (const output of node.outputs()) {\n                    if (this._liveValues.has(output)) {\n                        return this.mark(node);\n                    }\n                }\n                if (this._useAliasDb) {\n                    if (this.getOrCreateAliasDb().writesToAlias(node, this._liveValues)) {\n                        return this.mark(node);\n                    }\n                }\n                return false;\n            }\n            sweep(block, recurse) {\n                const nodes = Array.from(block.nodes()).reverse();\n                for (const node of nodes) {\n                    this.removeDeadBlockOutputs(node);\n                    this.removeDeadLoopOutputs(node);\n                    if (recurse) {\n                        for (const block of node.blocks()) {\n                            this.sweep(block, true);\n                        }\n                    }\n                    if (!this._marked.has(node) && !node.hasUses()) {\n                        node.destroy();\n                    }\n                }\n            }\n            hasUntrackedMutation(node) {\n                if (!this._useAliasDb) {\n                    if (node.kind() === 'prim::SetAttr') {\n                        return true;\n                    }\n                    const schema = node.maybeSchema();\n                    return schema && schema.is_mutable();\n                }\n                return this.getOrCreateAliasDb().writesToWildcard(node);\n            }\n            hasSideEffects(node) {\n                const it = this._memo.get(node);\n                if (it) {\n                    return it;\n                }\n                const has_side_effects = node.hasSideEffects() ||\n                    node.blocks().some((b) => Array.from(b.nodes()).some((n) => this.hasSideEffects(n))) ||\n                    this.hasUntrackedMutation(node);\n                this._memo.set(node, has_side_effects);\n                return has_side_effects;\n            }\n            removeDeadBlockOutputs(node) {\n                if (node.kind() !== 'prim::If' && node.kind() !== 'prim::GradOf') {\n                    return;\n                }\n                for (let i_1 = node.outputs().length; i_1 > 0; i_1--) {\n                    const i = i_1 - 1;\n                    if (!node.outputs()[i].hasUses()) {\n                        node.eraseOutput(i);\n                        for (const b of node.blocks()) {\n                            b.eraseOutput(i);\n                        }\n                    }\n                }\n            }\n            removeDeadLoopOutputs() {\n            }\n            getOrCreateAliasDb() {\n                if (!this._aliasDb) {\n                    this._aliasDb = new torch._C.AliasDb(this._graph);\n                }\n                return this._aliasDb;\n            }\n        });\n        this.registerFunction('torch._C.EliminateDeadCode', (...args) => {\n            if (args.length === 1 && args[0] instanceof torch.Graph) {\n                const [graph] = args;\n                const sideEffectPolicy = 'DONT_DELETE_NODES_WITH_SIDE_EFFECTS';\n                const worker = new torch._C.DeadCodeEliminator(graph, sideEffectPolicy);\n                worker.run(graph.block(), /*recurse=*/true);\n            } else if (args.length > 0 && args[0] instanceof torch.Block) {\n                const [block] = args;\n                const recurse = false;\n                const sideEffectPolicy = 'DONT_DELETE_NODES_WITH_SIDE_EFFECTS';\n                const worker = new torch._C.DeadCodeEliminator(sideEffectPolicy);\n                worker.run(block, recurse);\n            } else {\n                throw new python.Error('Not implemented.');\n            }\n        });\n        this.registerFunction('torch._C.removeTupleNodes', () => {\n        });\n        this.registerFunction('torch._C.LowerSimpleTuples', (...args) => {\n            if (args.length === 1 && args[0] instanceof torch.Graph) {\n                const [graph] = args;\n                torch._C.LowerSimpleTuples(graph.block());\n                torch._C.EliminateDeadCode(graph);\n            } else if (args.length === 1 && args[0] instanceof torch.Block) {\n                const [block] = args;\n                for (const n of block.nodes()) {\n                    torch._C.removeTupleNodes(n, false);\n                    for (const b of n.blocks()) {\n                        torch._C.LowerSimpleTuples(b);\n                    }\n                }\n            } else {\n                throw new python.Error('Not implemented.');\n            }\n        });\n        this.registerFunction('torch._C.attributesEqualCSE', (lhs, rhs) => {\n            torch._C.AT_ASSERT(lhs !== null);\n            torch._C.AT_ASSERT(rhs !== null);\n            if (lhs.hasAttributes() !== rhs.hasAttributes()) {\n                return false;\n            }\n            if (!lhs.hasAttributes() && !rhs.hasAttributes()) {\n                return true;\n            }\n            const lnames = lhs.attributeNames();\n            const rnames = rhs.attributeNames();\n            lnames.sort();\n            rnames.sort();\n            if (lnames.length !== rnames.length && !lnames.every((v, i) => v !== rnames[i])) {\n                return false;\n            }\n            for (const name of lnames) {\n                if (lhs.kindOf(name) !== rhs.kindOf(name)) {\n                    return false;\n                }\n                const kind = lhs.kindOf(name);\n                switch (kind) {\n                    case 'i':\n                    case 'f':\n                    case 's':\n                    case 't': {\n                        if (lhs[kind](name) !== rhs[kind](name)) {\n                            return false;\n                        }\n                        break;\n                    }\n                    case 'c': {\n                        const lc = lhs.c(name);\n                        const rc = rhs.c(name);\n                        if (lc.real !== rc.real || lc.imag !== rc.imag) {\n                            return false;\n                        }\n                        break;\n                    }\n                    case 'ival': {\n                        if (lhs[kind](name) !== rhs[kind](name)) {\n                            return false;\n                        }\n                        break;\n                    }\n                    default: {\n                        throw new python.Error('Not implemented.');\n                    }\n                }\n            }\n            return true;\n        });\n        this.registerFunction('torch._C.get_hash', (...args) => {\n            let hash = 0;\n            for (const value of args) {\n                if (typeof value === 'number') {\n                    hash += (value | 0);\n                } else if (typeof value === 'string') {\n                    hash += (value.length | 0);\n                } else if (Array.isArray(value)) {\n                    for (const item of value) {\n                        hash += torch._C.get_hash(item);\n                    }\n                } else if (value instanceof builtins.complex) {\n                    hash += (value.real | 0) + (value.imag | 0);\n                }\n            }\n            return hash;\n        });\n        this.registerFunction('torch._C.HashNode', (k) => {\n            torch._C.AT_ASSERT(k !== null);\n            let constant_hash = 0;\n            if (k.kind() === 'prim::Constant') {\n                const type = k.output().type();\n                if (type.isSubtypeOf(torch.NumberType.get()) && k.kindOf('value') === 'i') {\n                    constant_hash = k.i('value');\n                } else if (type.isSubtypeOf(torch.NumberType.get()) && k.kindOf('value') === 'f') {\n                    constant_hash = k.f('value');\n                } else if (type.isSubtypeOf(torch.NumberType.get()) && k.kindOf('value') === 'c') {\n                    constant_hash = k.c('value');\n                } else if (type.isSubtypeOf(torch.BoolType.get())) {\n                    constant_hash = k.i('value');\n                }\n            }\n            return torch._C.get_hash(k.kind(), k.outputs().map((v) => v.type().kind()), k.inputs().map((v) => v.unique()), constant_hash);\n        });\n        this.registerFunction('torch._C.EqualNode', (lhs, rhs) => {\n            if (lhs === null && rhs === null) {\n                return true;\n            }\n            if (lhs === null || rhs === null) {\n                return false;\n            }\n            if (lhs.kind() !== rhs.kind()) {\n                return false;\n            }\n            const lhs_outputs = lhs.outputs();\n            const rhs_outputs = rhs.outputs();\n            if (lhs_outputs.length !== rhs_outputs.length) {\n                return false;\n            }\n            for (let i = 0; i < lhs_outputs.length; i++) {\n                const lt = lhs_outputs[i].type();\n                const rt = rhs_outputs[i].type();\n                if (!lt.equals(rt)) {\n                    return false;\n                }\n            }\n            const lhs_inputs = lhs.inputs();\n            const rhs_inputs = rhs.inputs();\n            if (lhs_inputs.length !== rhs_inputs.length) {\n                return false;\n            }\n            if (!lhs_inputs.every((v, i) => v === rhs_inputs[i])) {\n                return false;\n            }\n            if (!torch._C.attributesEqualCSE(lhs, rhs)) {\n                return false;\n            }\n            if (lhs.blocks().length !== rhs.blocks().length) {\n                return false;\n            }\n            for (let i = 0; i < lhs.blocks().length; i++) {\n                if (lhs.blocks().at(i) !== rhs.blocks().at(i)) {\n                    return false;\n                }\n            }\n            return true;\n        });\n        this.registerType('torch._C.NodeSet', class {\n            constructor() {\n                this._nodes = new Map();\n            }\n            insert(n) {\n                const key = torch._C.HashNode(n);\n                if (this._nodes.has(key)) {\n                    this._nodes.get(key).push(n);\n                } else {\n                    this._nodes.set(key, [n]);\n                }\n            }\n            get(n) {\n                const key = torch._C.HashNode(n);\n                if (this._nodes.has(key)) {\n                    const nodes = this._nodes.get(key);\n                    for (const node of nodes) {\n                        if (torch._C.EqualNode(node, n)) {\n                            return node;\n                        }\n                    }\n                }\n                return null;\n            }\n            has(n) {\n                return this.get(n) !== null;\n            }\n        });\n        this.registerFunction('torch._C.isinstance', (stack, types) => {\n            const ty = stack.pop().type();\n            for (const candidate of types) {\n                if (ty.isSubtypeOf(candidate)) {\n                    stack.push(new torch._C.IValue(true, 'Bool'));\n                    stack.push(true);\n                    return;\n                }\n            }\n            stack.push(new torch._C.IValue(false, 'Bool'));\n        });\n        this.registerType('torch._C.Tuple', class {\n            constructor(elements) {\n                this._elements = elements;\n            }\n            static create(elements) {\n                return new torch._C.Tuple(elements);\n            }\n            elements() {\n                return this._elements;\n            }\n        });\n        this.registerFunction('torch._C.tupleConstruct', (stack, num_inputs) => {\n            torch._C.TORCH_CHECK(num_inputs <= stack.length);\n            const elems = stack.splice(stack.length - num_inputs, num_inputs);\n            const tuple = torch._C.Tuple.create(elems.reverse());\n            stack.push(new torch._C.IValue(tuple));\n        });\n        this.registerFunction('torch._C.runNodeIfInputsAreConstant', (n, ignore_custom_classes, db) => {\n            let stack = [];\n            for (const input of n.inputs()) {\n                const ival = torch._C.toIValue(input);\n                if (ival) {\n                    stack.push(ival);\n                } else {\n                    return null;\n                }\n            }\n            switch (n.kind()) {\n                case 'prim::ListUnpack': {\n                    if (stack.back().toList().size() !== n.outputs().length) {\n                        return null;\n                    }\n                    torch._C.listUnpack(stack, n.outputs().length);\n                    break;\n                }\n                case 'prim::TupleConstruct': {\n                    const tt = n.output().type().expect(torch.TupleType);\n                    if (tt.name()) {\n                        torch._C.namedTupleConstruct(stack, tt, n.inputs().length);\n                    } else {\n                        torch._C.tupleConstruct(stack, n.inputs().length);\n                    }\n                    break;\n                }\n                case 'prim::ListConstruct': {\n                    torch._C.listConstruct(stack, n.output().type().expect(torch.ListType), n.inputs().length);\n                    break;\n                }\n                case 'prim::DictConstruct': {\n                    torch._C.dictConstruct(stack, n.output().type().expect(torch.DictType), n.inputs().length);\n                    break;\n                }\n                case 'prim::CreateObject': {\n                    torch._C.createObject(stack, n.output().type().expect(torch.ClassType), /*use_weak_ref*/ true);\n                    break;\n                }\n                case 'prim::GetAttr': {\n                    const attr = torch._C.pop(stack).toObject().getAttr(n.s('name'));\n                    torch._C.push(stack, attr);\n                    break;\n                }\n                case 'prim::isinstance': {\n                    torch._C.isinstance(stack, n.tys('types'));\n                    break;\n                }\n                default: {\n                    const maybe_schema = n.maybeSchema();\n                    if (maybe_schema && maybe_schema.is_vararg) {\n                        return null;\n                    }\n                    // try\n                    // {\n                    // const op = n.getOperation();\n                    // op(stack);\n                    const [module, name] = n.kind().split('::');\n                    const obj = torch.ops[module];\n                    if (!obj) {\n                        throw new python.Error(`Unknown constant module 'torch.ops.${module}'.`);\n                    }\n                    const fn = torch.ops[module].__getattr__(name);\n                    if (!fn || !fn.__call__) {\n                        throw new python.Error(`Unknown constant function 'torch.ops.${module}.${name}'.`);\n                    }\n                    const args = stack.map((v) => v.value);\n                    const result = fn.__call__(...args);\n                    if (result === undefined) {\n                        stack = [];\n                    } else if (result instanceof torch._C.IValue) {\n                        stack = [result];\n                    } else if (Array.isArray(result) && result.every((v) => v instanceof torch._C.IValue)) {\n                        stack = result;\n                    } else {\n                        stack = [new torch._C.IValue(result)];\n                    }\n                    // } catch {\n                    // stack = [];\n                    // return null;\n                    // }\n                    break;\n                }\n            }\n            for (const v of stack) {\n                if (v.isTensor()) {\n                    const t = v.toTensor();\n                    if (t.defined() && t.requires_grad()) {\n                        return null;\n                    }\n                }\n                if (ignore_custom_classes) {\n                    if (v.isCustomClass()) {\n                        return null;\n                    }\n                }\n                if (v.isCustomClass()) {\n                    if (v.toObject().is_weak_compilation_ref()) {\n                        continue;\n                    }\n                    if (!db) {\n                        continue;\n                    }\n                    const n_non_const = n;\n                    if (db.mayContainAlias(n_non_const.inputs(), [n_non_const.outputs()])) {\n                        continue;\n                    }\n                    const obj = v.toObject();\n                    obj.unsafe_make_weak_compilation_ref();\n                }\n                if (v.isObject()) {\n                    if (!v.toObject().is_weak_compilation_ref()) {\n                        return null;\n                    }\n                }\n            }\n            return stack;\n        });\n        this.registerType('torch._C.ConstantPropagator', class {\n            constructor(graph, aliasing_types, ignore_custom_classes) {\n                this._made_change = false;\n                this._graph = graph;\n                this._aliasing_types = aliasing_types;\n                this._ignore_custom_classes = ignore_custom_classes;\n            }\n            static NoAliasDb(graph) {\n                return new torch._C.ConstantPropagator(graph, false, false);\n            }\n            run() {\n                this.ConstantPropagation(this._graph.block());\n                return this._made_change;\n            }\n            propagateNode(n) {\n                let outputs = [];\n                const outputs_opt = torch._C.runNodeIfInputsAreConstant(n, this._ignore_custom_classes);\n                if (outputs_opt) {\n                    outputs = outputs_opt;\n                    const graph = n.owningGraph();\n                    const guard = new torch._C.WithInsertPoint(n);\n                    for (let i = 0; i < outputs.length; i++) {\n                        const new_output = torch._C.tryInsertConstant(graph, outputs[i]);\n                        if (new_output) {\n                            this._made_change = true;\n                            if (outputs[i].isNone()) {\n                                new_output.setType(n.outputs()[i].type());\n                            }\n                            n.outputs()[i].replaceAllUsesWith(new_output);\n                        }\n                    }\n                    guard.dispose();\n                }\n            }\n            removeLoopNode(n) {\n                const loop_input_offset = 2;\n                for (let i = 0; i < n.outputs().length; i++) {\n                    n.outputs()[i].replaceAllUsesWith(n.inputs()[i + loop_input_offset]);\n                }\n                this._made_change = true;\n                n.destroy();\n            }\n            loopWillNotRun(node) {\n                const [trip_count, start_cond] = node.inputs();\n                const iter_len = torch._C.constant_as(trip_count, 'toInt', 1);\n                const cond_val = torch._C.constant_as(start_cond, 'toBool', true);\n                const loop_might_run = cond_val && iter_len > 0;\n                return !loop_might_run;\n            }\n            inlineIfBody(body) {\n                const n = body.owningNode();\n                for (const body_node of body.nodes()) {\n                    body_node.moveBefore(n);\n                }\n                for (let i = 0; i < n.outputs().length; i++) {\n                    n.outputs()[i].replaceAllUsesWith(body.outputs()[i]);\n                }\n                n.destroy();\n            }\n            inlineIf(n) {\n                const input_bool = torch._C.constant_as(n.input(), 'toBool');\n                torch._C.AT_ASSERT(input_bool !== null);\n                const block_index = input_bool ? 0 : 1;\n                this.ConstantPropagation(n.blocks().at(block_index));\n                this.inlineIfBody(n.blocks().at(block_index));\n                this._made_change = true;\n            }\n            replaceAndRemoveIfOutput(n, i, replacement) {\n                n.outputs()[i].replaceAllUsesWith(replacement);\n                n.eraseOutput(i);\n                n.blocks().at(0).eraseOutput(i);\n                n.blocks().at(1).eraseOutput(i);\n            }\n            removeExtraIfOutputs(n) {\n                torch._C.TORCH_CHECK(n.kind() === 'prim::If');\n                const [true_block, false_block] = n.blocks();\n                const graph = n.owningGraph();\n                const initial_outputs = true_block.outputs().length;\n                const guard = new torch._C.WithInsertPoint(n);\n                for (let i = 0; i < true_block.outputs().length;) {\n                    const t_out = true_block.outputs()[i];\n                    const f_out = false_block.outputs()[i];\n                    if (true_block.outputs()[i] === false_block.outputs()[i]) {\n                        this.replaceAndRemoveIfOutput(n, i, true_block.outputs()[i]);\n                        continue;\n                    }\n                    const maybe_const = torch._C.toIValue(t_out);\n                    if (maybe_const && torch._C.EqualNode(t_out.node(), f_out.node())) {\n                        const new_const = graph.insertConstant(maybe_const);\n                        this.replaceAndRemoveIfOutput(n, i, new_const);\n                        continue;\n                    }\n                    i++;\n                }\n                this._made_change = this._made_change || (initial_outputs !== true_block.outputs().length);\n                guard.dispose();\n            }\n            removeExtraLoopOutputs(node) {\n                const initial_outputs = node.outputs().length;\n                const [loop_body] = node.blocks();\n                const loop_input_offset = 2;\n                const loop_body_offset = 1;\n                for (let i_1 = node.outputs().length; i_1 > 0; i_1--) {\n                    const i = i_1 - 1;\n                    if (loop_body.inputs()[loop_body_offset + i] === loop_body.outputs()[loop_body_offset + i]) {\n                        const node_input = node.inputs()[loop_input_offset + i];\n                        node.outputs().at(i).replaceAllUsesWith(node_input);\n                        loop_body.inputs()[loop_body_offset + i].replaceAllUsesWith(node_input);\n                        node.eraseOutput(i);\n                        node.removeInput(loop_input_offset + i);\n                        loop_body.eraseInput(loop_body_offset + i);\n                        loop_body.eraseOutput(loop_body_offset + i);\n                    }\n                }\n                this._made_change = this._made_change || (initial_outputs !== node.outputs().length);\n            }\n            noMutableValues(values) {\n                return values.every((v) => !torch._C.AliasDb.isMutableType(v));\n            }\n            getOrCreateAliasDb() {\n                if (!this._aliasDb) {\n                    this._aliasDb = new torch._C.AliasDb(this._graph);\n                }\n                return this._aliasDb;\n            }\n            supportedNode(n) {\n                torch._C.skip_list = torch._C.skip_list || new Set([\n                    'prim::If',\n                    'prim::Loop',\n                    'prim::Closure',\n                    'prim::Constant',\n                    'prim::AutogradZero',\n                    'prim::Uninitialized',\n                    'prim::Guard',\n                    'prim::profile',\n                    'prim::profile_ivalue',\n                    'prim::unchecked_unwrap_optional',\n                    'prim::awaitable',\n                    'aten::dequantize'\n                ]);\n                let no_mutation = false;\n                if (this._aliasing_types) {\n                    no_mutation = !this.getOrCreateAliasDb().hasWriters(n);\n                } else {\n                    no_mutation = this.noMutableValues(n.inputs()) && this.noMutableValues(n.outputs());\n                }\n                return no_mutation && !n.kind().startsWith('onnx::') && !torch._C.skip_list.has(n.kind()) && !n.isNondeterministic() && !n.hasSideEffects() && n.blocks().length === 0;\n            }\n            ConstantPropagation(...args) {\n                if (args[0] instanceof torch.Graph) {\n                    throw new python.Error('Not implemented.');\n                } else if (args[0] instanceof torch.Block) {\n                    const [block] = args;\n                    for (const n of block.nodes()) {\n                        this.ConstantPropagation(n);\n                    }\n                } else if (args[0] instanceof torch.Node) {\n                    const [n] = args;\n                    const constant_inputs = n.inputs().every((v) => v.node().kind() === 'prim::Constant');\n                    if (n.kind() === 'prim::If') {\n                        if (constant_inputs) {\n                            this.inlineIf(n);\n                        } else {\n                            this.ConstantPropagation(n.blocks());\n                            this.removeExtraIfOutputs(n);\n                        }\n                    } else if (n.kind() === 'prim::Loop') {\n                        if (this.loopWillNotRun(n)) {\n                            this.removeLoopNode(n);\n                        } else {\n                            this.ConstantPropagation(n.blocks());\n                            this.removeExtraLoopOutputs(n);\n                        }\n                    } else if (constant_inputs && this.supportedNode(n)) {\n                        this.propagateNode(n);\n                    } else {\n                        this.ConstantPropagation(n.blocks()); // not implemented\n                    }\n                } else if (args.length === 1 && Array.isArray(args[0]) && args[0].every((b) => b instanceof torch.Block)) {\n                    const [blocks] = args;\n                    for (const block of blocks) {\n                        this.ConstantPropagation(block);\n                    }\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n        });\n        this.registerFunction('torch._C.ConstantPropagationImmutableTypes', (graph) => {\n            const cp = torch._C.ConstantPropagator.NoAliasDb(graph);\n            const made_change = cp.run();\n            if (made_change) {\n                torch._C.EliminateDeadCode(graph);\n            }\n            return made_change;\n        });\n        this.registerType('torch._C.MutableTypePtrHelper', class {\n            constructor(mutable_type_cache) {\n                this._mutable_type_cache = mutable_type_cache;\n            }\n            mapTypeToAliasTypeSet(type) {\n                if (this._mutable_type_cache) {\n                    const result = this.mapTypeToBorrowedAliasTypeSet(type);\n                    if (result) {\n                        return result;\n                    }\n                }\n                return this.mapTypeToAliasTypeSetImpl(type);\n            }\n            mapTypeToAliasTypeSetImpl(type) {\n                if (type instanceof torch.ListType ||\n                    type instanceof torch.DictType ||\n                    type instanceof torch.ClassType ||\n                    type instanceof torch.TensorType) {\n                    return [torch._C.unshapedType(type)];\n                }\n                if (type instanceof torch.UnionType) {\n                    const mutable_types = [];\n                    for (const inner of type.expect(torch.UnionType).containedTypes()) {\n                        const maybe_inner_types = this.mapTypeToAliasTypeSet(inner);\n                        if (maybe_inner_types) {\n                            mutable_types.push(...maybe_inner_types);\n                        }\n                    }\n                    if (mutable_types.length === 0) {\n                        return null;\n                    }\n                    return mutable_types;\n                }\n                if (type instanceof torch.OptionalType) {\n                    const inner = type.getElementType();\n                    return this.mapTypeToAliasTypeSet(inner);\n                }\n                if (type instanceof torch.AnyType) {\n                    return [torch._C.AliasTypeSet([type])];\n                }\n                if (type instanceof torch.FutureType) {\n                    const maybe_mut_types = this.mapTypeToAliasTypeSet(type.getElementType());\n                    if (maybe_mut_types) {\n                        return [torch._C.AliasTypeSet([torch.FutureType.create(torch._C.toSingleType(maybe_mut_types))])];\n                    }\n                    return null;\n                }\n                if (type instanceof torch.AwaitType) {\n                    const maybe_mut_types = this.mapTypeToAliasTypeSet(type.getElementType());\n                    if (maybe_mut_types) {\n                        return [torch._C.AliasTypeSet([torch.AwaitType.create(torch._C.toSingleType(maybe_mut_types))])];\n                    }\n                    return null;\n                }\n                if (type instanceof torch.TupleType) {\n                    const mutable_types = [];\n                    for (const inner of type.elements()) {\n                        const maybe_inner_types = this.mapTypeToAliasTypeSet(inner);\n                        if (maybe_inner_types) {\n                            mutable_types.push(...maybe_inner_types);\n                        }\n                    }\n                    if (mutable_types.length === 0) {\n                        return null;\n                    }\n                    return [[torch.TupleType.create(mutable_types)]];\n                }\n                return null;\n            }\n        });\n        this.registerFunction('torch._C.isMutableTypeImpl', (type, mutable_type_cache) => {\n            if (type instanceof torch.TensorType || type instanceof torch.ListType ||\n                type instanceof torch.ClassType || type instanceof torch.DictType) {\n                return true;\n            }\n            const helper = new torch._C.MutableTypePtrHelper(mutable_type_cache);\n            if (mutable_type_cache) {\n                return helper.mapTypeToBorrowedAliasTypeSet(type) !== null;\n            }\n            return helper.mapTypeToAliasTypeSet(type) !== null;\n        });\n        this.registerType('torch._C.AliasDb', class {\n            constructor() {\n                this._writeIndex = new Map();\n            }\n            static isMutableType(...args) {\n                if (args[0] instanceof torch.Type) {\n                    const [type] = args;\n                    return torch._C.isMutableTypeImpl(type, null);\n                }\n                if (args[0] instanceof torch.Value) {\n                    const [value] = args;\n                    return torch._C.AliasDb.isMutableType(value.type());\n                }\n                throw new python.Error('Not implemented.');\n            }\n            writesToAlias(/* n, vs */) {\n                /*\n                const writtenTo = this.getWrites(n);\n                if (writtenTo.length === 0) {\n                    return false;\n                }\n                MemoryLocations locs;\n                for (const v of vs) {\n                  const it = elementMap_.find(v);\n                  if (it != elementMap_.end()) {\n                    const auto& vlocs = memoryDAG_->getMemoryLocations(it->second);\n                    if (writtenTo.intersects(vlocs)) {\n                      return true;\n                    }\n                  }\n                }\n                */\n                return false;\n            }\n            writesToWildcard(n) {\n                if (!this._writeIndex.has(n)) {\n                    return false;\n                }\n                const writes = this._writeIndex.get(n);\n                for (const pr of this._wildcardIndex) {\n                    const [, wildcardElement] = pr;\n                    if (writes.test(wildcardElement.index)) {\n                        return true;\n                    }\n                }\n                return false;\n            }\n            safeToChangeAliasingRelationship(a, b) {\n                if (torch._C.hasWriters(a) || torch._C.hasWriters(b)) {\n                    return false;\n                }\n                return !(torch._C.escapesScope(a) && torch._C.escapesScope(b));\n            }\n        });\n        this.registerFunction('torch._C.hasWriters', () => {\n        });\n        this.registerFunction('torch._C.escapesScope', () => {\n        });\n        this.registerType('torch._C.DepthFirstGraphNodeIterator', class {\n            constructor(graph) {\n                this._current = graph.block().nodes().front();\n            }\n            next() {\n                return null;\n            }\n        });\n        this.registerType('torch._C.ConcatCombiner', class {\n            constructor(graph) {\n                this._graph = graph;\n                this._aliasDb = new torch._C.AliasDb(graph);\n                this._combinable_concats = [];\n            }\n            collectOptimizableConcats() {\n                const graph_it = new torch._C.DepthFirstGraphNodeIterator(this._graph);\n                for (let node = graph_it.next(); node !== null; node = graph_it.next()) {\n                    if (node.kind() === 'aten::cat') {\n                        this.handleConcat(node);\n                    }\n                }\n            }\n            combineConcats() {\n                if (this._combinable_concats.length === 0) {\n                    return false;\n                }\n                const list_construct_inputs = this.getListConstructInputs();\n                for (const node_and_new_list of list_construct_inputs) {\n                    const [node, inputs] = node_and_new_list;\n                    const new_list_construct = this.createListConstruct(inputs);\n                    const old_list_construct = node.input(0).node();\n                    new_list_construct.output().setType(old_list_construct.output().type());\n                    new_list_construct.insertBefore(node);\n                    old_list_construct.replaceAllUsesWith(new_list_construct);\n                }\n                return true;\n            }\n            run() {\n                this.collectOptimizableConcats();\n                const changed = this.combineConcats();\n                if (changed) {\n                    torch._C.EliminateDeadCode(this._graph);\n                }\n                return changed;\n            }\n        });\n        this.registerFunction('torch._C.CombineConcats', (graph) => {\n            const changed = new torch._C.ConcatCombiner(graph).run();\n            return changed;\n        });\n        this.registerType('torch._C.PeepholeOptimizeImpl', class {\n            constructor(graph, disable_shape_peepholes) {\n                this._graph = graph;\n                this._shape_peepholes = !disable_shape_peepholes;\n            }\n            run() {\n                let changed = this.optimizeBlock(this._graph.block());\n                /* changed |= torch._C.PeepholeOptimizeListIdioms(this._graph);\n                changed |= torch._C.PeepholeOptimizeDictIdioms(this._graph);\n                changed |= torch._C.PeepholeOptimizeAliasSensitive(this._graph, this._shape_peepholes);\n                changed |= torch._C.PeepholeOptimizeNonTensor(this._graph); */\n                changed = changed || torch._C.CombineConcats(this._graph);\n                return changed;\n            }\n            optimizeBlock(block) {\n                let changed = false;\n                for (const node of block.nodes()) {\n                    for (const sub_block of node.blocks()) {\n                        changed = changed || this.optimizeBlock(sub_block);\n                    }\n                    if (node.kind() !== 'prim::Constant') {\n                        const guard = new torch._C.WithInsertPoint(node);\n                        for (const output of node.outputs()) {\n                            if (output.type() instanceof torch.NoneType) {\n                                output.replaceAllUsesWith(this._graph.insertConstant(new torch._C.IValue()));\n                                changed = true;\n                            }\n                        }\n                        guard.dispose();\n                    }\n                    if (node.kind() === 'prim::If') {\n                        // throw new python.Error('Not implemented.');\n                        /*\n                        const n = new torch._C.IfView(node);\n                        // this handles redundant short circuits like \"x and True\" or \"x or\n                        // False\"\n                        for (const auto i : c10::irange(n.outputs().length)) {\n                            if (n.outputs().at(i).type() != torch.BoolType.get()) {\n                                continue;\n                            }\n                            const true_val = constant_as<bool>(n.thenOutputs().at(i)).value_or(false);\n                            const false_val = constant_as<bool>(n.elseOutputs().at(i)).value_or(true);\n                            if (true_val && !false_val) {\n                                n.outputs().at(i).replaceAllUsesWith(n.cond());\n                                changed = true;\n                            }\n                        }\n                        for (let i = 0; i < n.outputs().length; ++i) {\n                            const inputs_non_optional = !n.thenOutputs().at(i).type().cast<OptionalType>() && !n.elseOutputs().at(i).type().cast<OptionalType>();\n                            const output_optional = n.outputs()[i].type();\n                            if (inputs_non_optional && output_optional instanceof torch.OptionalType) {\n                                const unif = torch._c.unifyTypes(n.thenOutputs().at(i).type(), n.elseOutputs().at(i).type())\n                                if (unif) {\n                                    n.outputs()[i].setType(unif);\n                                    changed = true;\n                                }\n                            }\n                        }\n                        */\n                    } else if (node.kind() === 'aten::__is__' || node.kind() === 'aten::__isnot__') {\n                        torch._C.AT_ASSERT(node.inputs().length === 2);\n                        for (const check_none_index of [0, 1]) {\n                            const input_must_be_none = node.inputs()[check_none_index].mustBeNone();\n                            const other_must_not_be_none = node.inputs().at(1 - check_none_index).mustNotBeNone();\n                            if (input_must_be_none && other_must_not_be_none) {\n                                const guard = new torch._C.WithInsertPoint(node);\n                                const output = node.owningGraph().insertConstant(node.kind() === 'aten::__isnot__');\n                                node.output().replaceAllUsesWith(output);\n                                changed = true;\n                                guard.dispose();\n                            }\n                        }\n                    } else if (node.kind() === 'prim::unchecked_unwrap_optional' || node.kind() === 'aten::_unwrap_optional') {\n                        throw new python.Error('Not implemented.');\n                        /*\n                        // we are unwrapping an input that can't be None, remove the unwrap\n                        const input = node.input();\n                        if (input.mustNotBeNone()) {\n                        node.output().replaceAllUsesWith(node.input());\n                        changed = true;\n                        }\n                        */\n                    } else if (node.kind() === 'prim::unchecked_cast') {\n                        const input_type = torch._C.unshapedType(node.input().type());\n                        const output_type = torch._C.unshapedType(node.output().type());\n                        if (input_type.isSubtypeOf(output_type)) {\n                            node.output().replaceAllUsesWith(node.input());\n                            changed = true;\n                        }\n                    } else if ((node.kind() === 'aten::Int' || node.kind() === 'aten::ceil') && node.inputs().length === 1 && node.input().type() instanceof torch.IntType) {\n                        node.output().replaceAllUsesWith(node.input());\n                        changed = true;\n                    } else if (node.kind() === 'aten::ne' || node.kind() === 'aten::eq') {\n                        if (node.inputs().length !== 2 || node.inputs()[0] !== node.inputs()[1]) {\n                            continue;\n                        }\n                        const inp_type = node.inputs()[0].type();\n                        const immut_type = (type) => {\n                            const kind = type.kind();\n                            const handled_immutable_types = new Set('BoolType', 'IntType', 'FloatType', 'NoneType');\n                            return handled_immutable_types.has(kind);\n                        };\n                        let non_throwing_type = false;\n                        if (inp_type instanceof torch.ListType) {\n                            non_throwing_type = immut_type(inp_type.getElementType());\n                        } else if (inp_type instanceof torch.DictType) {\n                            non_throwing_type = immut_type(inp_type.getKeyType()) && immut_type(inp_type.getValueType());\n                        } else {\n                            non_throwing_type = immut_type(inp_type);\n                        }\n                        if (non_throwing_type) {\n                            const guard = new torch._C.WithInsertPoint(node);\n                            node.output().replaceAllUsesWith(this._graph.insertConstant(node.kind() === 'aten::eq'));\n                            changed = true;\n                            guard.dispose();\n                        }\n                    } else if (node.kind() === 'aten::mul' || node.kind() === 'aten::floordiv' || node.kind() === 'aten::div') {\n                        // changed = changed || torch._C.trySimplifyMulOrDiv(node);\n                    } else if (node.kind() === 'aten::add' || node.kind() === 'aten::sub') {\n                        // changed = changed || torch._C.trySimplifyAddOrSub(node);\n                    }\n                }\n                return changed;\n            }\n        });\n        this.registerFunction('torch._C.PeepholeOptimize', (graph, addmm_fusion_enabled) => {\n            const peephole = new torch._C.PeepholeOptimizeImpl(graph, addmm_fusion_enabled);\n            const changed = peephole.run();\n            if (changed) {\n                torch._C.EliminateDeadCode(graph.block());\n            }\n            return changed;\n        });\n        this.registerFunction('torch._C.TORCH_INTERNAL_ASSERT', (cond, ...args) => {\n            if (!cond) {\n                throw new python.Error(`Assertion failed.${args.length > 0 ? ` ${args.join('')}` : ''}`);\n            }\n        });\n        this.registerFunction('torch._C.TORCH_CHECK', (cond, ...args) => {\n            if (!cond) {\n                throw new python.Error(`Assertion failed.${args.length > 0 ? ` ${args.join('')}` : ''}`);\n            }\n        });\n        this.registerFunction('torch._C.AT_ASSERT', (cond, ...args) => {\n            if (!cond) {\n                throw new python.Error(`Assertion failed.${args.length > 0 ? ` ${args.join('')}` : ''}`);\n            }\n        });\n        this.registerFunction('torch._C.eraseListLiterals', (graph) => {\n            const it = new torch._C.DepthFirstGraphNodeIterator(graph);\n            for (let next_node = it.next(); next_node !== null;) {\n                const node = next_node;\n                next_node = it.next();\n                if (node.kind() === 'prim::EmptyListLiteral') {\n                    if (node.hasUses()) {\n                        torch._C.TORCH_INTERNAL_ASSERT(node.output().type().isSubtypeOf(torch.ListType.ofTensors()));\n                    }\n                    const li = graph.createList(torch.TensorType.get(), []);\n                    li.insertBefore(node);\n                    node.replaceAllUsesWith(li);\n                }\n                node.destroy();\n            }\n        });\n        this.registerFunction('torch._C.ConstantPooling', (...args) => {\n            if (args.length === 1 && args[0] instanceof torch.Graph) {\n                const [graph] = args;\n                const aliasDb = new torch._C.AliasDb(graph);\n                const constants = new torch._C.NodeSet();\n                torch._C.ConstantPooling(graph.block(), constants, aliasDb);\n            } else if (args.length === 3 && args[0] instanceof torch.Block) {\n                const [block, constants, aliasDb] = args;\n                for (const node of block.nodes()) {\n                    if (node.blocks().length > 0) {\n                        for (const block of node.blocks()) {\n                            torch._C.ConstantPooling(block, constants, aliasDb);\n                        }\n                        continue;\n                    }\n                    if (node.kind() !== 'prim::Constant') {\n                        continue;\n                    }\n                    if (constants.has(node)) {\n                        const existing = constants.get(node);\n                        const old_ivalue = torch._C.toIValue(existing.output());\n                        const new_ivalue = torch._C.toIValue(node.output());\n                        const same_identity = (old_ivalue && new_ivalue && (old_ivalue.is(new_ivalue)));\n                        if (!same_identity && !aliasDb.safeToChangeAliasingRelationship(node.outputs(), existing.outputs())) {\n                            continue;\n                        }\n                        node.replaceAllUsesWith(existing);\n                        node.destroy();\n                        continue;\n                    } else {\n                        constants.insert(node);\n                    }\n                    const [first_node] = node.owningGraph().block().nodes();\n                    if (node !== first_node) {\n                        node.moveBefore(first_node);\n                    }\n                }\n            } else {\n                throw new python.Error('Not implemented.');\n            }\n        });\n        this.registerFunction('torch._C.handleBlock', (/* block, initial_state */) =>{\n            /*\n            const autocast_stack = [];\n            let incompatible_amp = null;\n            const current_state = () => autocast_stack.length === 0 ? initial_state : autocast_stack.top().context;\n            for (const node of block.nodes()) {\n                switch (node.kind()) {\n                    case 'prim::CallFunction':\n                        if (current_state() === initial_state) {\n                            if (current_state()) {\n                                torch._C.castTensorInputs(node, 'aten::_autocast_to_full_precision', current_state());\n                            }\n                            break;\n                        }\n                        torch._C.TORCH_INTERNAL_ASSERT(!incompatible_amp.has_value() || incompatible_amp.value(), \"Calls are not expected with AMP & JIT\");\n                        incompatible_amp = true;\n                        break;\n                    case 'prim::CallMethod':\n                        if (current_state() === initial_state) {\n                            if (current_state()) {\n                                torch._C.castTensorInputs(node, 'aten::_autocast_to_full_precision', current_state());\n                            }\n                            break;\n                        }\n                        if (node.input(0).type() instanceof torch.ClassType) {\n                            const class_type = node.input(0).type();\n                            const name = node.s('name');\n                            const fn = class_type.getMethod(name);\n                            if (!fn.isGraphFunction()) {\n                                torch._C.TORCH_INTERNAL_ASSERT(!incompatible_amp.has_value() || incompatible_amp.value(), 'Calls are not expected with AMP & JIT');\n                                incompatible_amp = true;\n                            }\n                        } else {\n                            torch._C.TORCH_INTERNAL_ASSERT(!incompatible_amp.has_value() || incompatible_amp.value(), 'Unexpected prim::CallMethod form with AMP & JIT');\n                            incompatible_amp = true;\n                        }\n                        break;\n                    case 'prim::Enter': {\n                        const autocast_scope = torch._C.parseAutocast(node.input(), current_state());\n                        if (autocast_scope) {\n                            if (node.hasUses()) {\n                                torch._C.TORCH_CHECK(false, \"`with autocast() as ...` is not supported\");\n                            }\n                            torch._C.TORCH_INTERNAL_ASSERT(!incompatible_amp.has_value() || !incompatible_amp.value(), 'Unsupported case by AMP & JIT');\n                            incompatible_amp = false;\n                            autocast_stack.push(autocast_scope);\n                        }\n                        break;\n                    }\n                    case 'prim::Exit': {\n                        if (torch._C.isAutocastNode(node.input(0))) {\n                            torch._C.TORCH_INTERNAL_ASSERT(!autocast_stack.empty());\n                            torch._C.TORCH_INTERNAL_ASSERT(autocast_stack.top().instance === node.input());\n                            torch._C.TORCH_INTERNAL_ASSERT(!incompatible_amp.has_value() || !incompatible_amp.value(), 'Unsupported case by AMP & JIT');\n                            incompatible_amp = false;\n                            autocast_stack.pop();\n                        }\n                        break;\n                    }\n                    case 'aten::is_autocast_enabled': {\n                        torch._C.updateAutocastEnabledCheck(node, current_state().gpu_enabled);\n                        break;\n                    }\n                    case 'aten::is_autocast_cpu_enabled': {\n                        torch._C.updateAutocastEnabledCheck(node, current_state().cpu_enabled);\n                        break;\n                    }\n                    case 'aten::_convolution':\n                    case 'aten::conv1d':\n                    case 'aten::conv2d':\n                    case 'aten::conv3d':\n                    case 'aten::conv_tbc':\n                    case 'aten::conv_transpose1d':\n                    case 'aten::convolution':\n                    case 'aten::cudnn_convolution':\n                    case 'aten::cudnn_convolution_transpose':\n                    case 'aten::prelu':\n                    case 'aten::addmm':\n                    case 'aten::addmv':\n                    case 'aten::addr':\n                    case 'aten::matmul':\n                    case 'aten::mm':\n                    case 'aten::mv':\n                    case 'aten::linear':\n                    case 'aten::addbmm':\n                    case 'aten::baddbmm':\n                    case 'aten::bmm':\n                    case 'aten::chain_matmul':\n                    case 'aten::_thnn_fused_lstm_cell':\n                    case 'aten::_thnn_fused_gru_cell':\n                    case 'aten::lstm_cell':\n                    case 'aten::gru_cell':\n                    case 'aten::rnn_tanh_cell':\n                    case 'aten::rnn_relu_cell': {\n                        if (!node.schema().is_mutable()) {\n                            torch._C.castTensorInputs(node, 'aten::_autocast_to_reduced_precision', current_state());\n                        }\n                        break;\n                    }\n                    case 'aten::native_layer_norm':\n                    case 'aten::acos':\n                    case 'aten::asin':\n                    case 'aten::cosh':\n                    case 'aten::erfinv':\n                    case 'aten::exp':\n                    case 'aten::expm1':\n                    case 'aten::log':\n                    case 'aten::log10':\n                    case 'aten::log2':\n                    case 'aten::log1p':\n                    case 'aten::reciprocal':\n                    case 'aten::rsqrt':\n                    case 'aten::sinh':\n                    case 'aten::tan':\n                    case 'aten::pow':\n                    case 'aten::softplus':\n                    case 'aten::gelu':\n                    case 'aten::layer_norm':\n                    case 'aten::group_norm':\n                    case 'aten::frobenius_norm':\n                    case 'aten::nuclear_norm':\n                    case 'aten::cosine_similarity':\n                    case 'aten::cosine_embedding_loss':\n                    case 'aten::nll_loss':\n                    case 'aten::nll_loss2d':\n                    case 'aten::hinge_embedding_loss':\n                    case 'aten::kl_div':\n                    case 'aten::l1_loss':\n                    case 'aten::smooth_l1_loss':\n                    case 'aten::mse_loss':\n                    case 'aten::margin_ranking_loss':\n                    case 'aten::multilabel_margin_loss':\n                    case 'aten::soft_margin_loss':\n                    case 'aten::triplet_margin_loss':\n                    case 'aten::multi_margin_loss':\n                    case 'aten::binary_cross_entropy_with_logits':\n                    case 'aten::dist':\n                    case 'aten::pdist':\n                    case 'aten::cdist':\n                    case 'aten::renorm':\n                    case 'aten::logsumexp': {\n                        if (!node.schema().is_mutable()) {\n                            torch._C.castTensorInputs(node, 'aten::_autocast_to_full_precision', current_state());\n                        }\n                        break;\n                    }\n                    case 'aten::prod':\n                    case 'aten::log_softmax':\n                    case 'aten::cumprod':\n                    case 'aten::cumsum':\n                    case 'aten::sum': {\n                        if (!node.schema().is_mutable() && !torch._C.hasExplicitDtypeArgument(node)) {\n                            torch._C.castTensorInputs(node, 'aten::_autocast_to_full_precision', current_state());\n                        }\n                        break;\n                    }\n                    case 'aten::softmax': {\n                        if (!node.schema().is_mutable() && !torch._C.hasExplicitDtypeArgument(node)) {\n                            const context = current_state();\n                            context.cpu_enabled = false;\n                            torch._C.castTensorInputs(node, 'aten::_autocast_to_full_precision', context);\n                        }\n                        break;\n                    }\n                    case 'aten::addcdiv':\n                    case 'aten::addcmul':\n                    case 'aten::atan2':\n                    case 'aten::bilinear':\n                    case 'aten::cat':\n                    case 'aten::cross':\n                    case 'aten::dot':\n                    case 'aten::equal':\n                    case 'aten::index_put':\n                    case 'aten::stack':\n                    case 'aten::tensordot':\n                    case 'aten::add':\n                    case 'aten::sub':\n                    case 'aten::mul':\n                    case 'aten::div': {\n                        if (!node.schema().is_mutable()) {\n                            torch._C.castInputsToWidestType(node, current_state());\n                        }\n                        break;\n                    }\n                    case 'aten::binary_cross_entropy': {\n                        if (current_state()) {\n                            torch._C.TORCH_CHECK(false, \"Unsafe to autocast\");\n                        }\n                        break;\n                    }\n                    default: {\n                        break;\n                    }\n                }\n                for (const sub_block of node.blocks()) {\n                    torch._C.handleBlock(sub_block, current_state());\n                }\n            }\n            torch._C.TORCH_INTERNAL_ASSERT(autocast_stack.length === 0);\n            */\n        });\n        this.registerFunction('torch._C.autocastEnabled', () => {\n            return true;\n        });\n        this.registerFunction('torch._C.Autocast', (graph) => {\n            if (torch._C.autocastEnabled()) {\n                const init = null;\n                /* AutocastContext init = {\n                    at::autocast::is_autocast_enabled(at::kCUDA),\n                    at::autocast::is_autocast_enabled(at::kCPU),\n                    at::autocast::get_autocast_dtype(at::kCUDA),\n                    at::autocast::get_autocast_dtype(at::kCPU)}; */\n                torch._C.handleBlock(graph.block(), init);\n            }\n        });\n        this.registerFunction('torch._C.preoptimizeGraph', (graph, disable_autocast) => {\n            disable_autocast = disable_autocast || false;\n            torch._C.Inline(graph);\n            torch._C.PeepholeOptimize(graph, true);\n            torch._C.ConstantPropagationImmutableTypes(graph);\n            if (!disable_autocast) {\n                torch._C.Autocast(graph);\n            }\n            torch._C.ConstantPooling(graph);\n        });\n        this.registerType('torch._C.GraphFunction', class extends torch._C.Function {\n            constructor(name, graph, function_creator, executor_execution_mode) {\n                super();\n                this._name = name;\n                this._graph = graph;\n                this._executor_execution_mode = executor_execution_mode || null;\n                this._function_creator = function_creator;\n                this._force_no_amp = false;\n            }\n            isGraphFunction() {\n                return true;\n            }\n            qualname() {\n                return this._name;\n            }\n            graph() {\n                return this._graph;\n            }\n            optimized_graph() {\n                const graph_ref = this._graph.copy();\n                torch._C.preoptimizeGraph(graph_ref, this._force_no_amp);\n                return graph_ref;\n            }\n            ensure_defined() {\n                if (this._function_creator) {\n                    const creator = this._function_creator;\n                    this._function_creator = () => {\n                        throw new python.Error('Recursive method call.');\n                    };\n                    creator(this);\n                    this._function_creator = null;\n                }\n                this.check_single_output();\n            }\n            check_single_output() {\n                if (this.graph().outputs().length !== 1) {\n                    throw new python.Error('Graph must have a single output.');\n                }\n            }\n            getSchema() {\n                this._schema = this._schema || this.defaultSchemaFor(this);\n                return this._schema;\n            }\n            setSchema(schema) {\n                this._schema = schema;\n            }\n            num_inputs() {\n                return this.graph().inputs().length;\n            }\n            unshapedType(type) {\n                if (type.isSubtypeOf(torch.TensorType.get())) {\n                    return torch.TensorType.get();\n                }\n                const contained = type.containedTypes();\n                if (contained.length === 0) {\n                    return type;\n                }\n                return type.withContained(type.containedTypes((type) => this.unshapedType(type)));\n            }\n            defaultSchemaFor(fn) {\n                const args = [];\n                const returns = [];\n                const g = fn.graph();\n                const num_inputs = fn.num_inputs();\n                for (let i = 0; i < num_inputs; i++) {\n                    const v = g.inputs()[i];\n                    const name = v.hasDebugName() ? v.debugNameBase() : `argument_${i}`;\n                    const argument = new torch.Argument(name, this.unshapedType(g.inputs()[i].type()));\n                    args.push(argument);\n                }\n                const num_outputs = g.outputs().length;\n                for (let i = 0; i < num_outputs; i++) {\n                    const argument = new torch.Argument('', this.unshapedType(g.outputs()[i].type()));\n                    returns.push(argument);\n                }\n                return new torch.FunctionSchema(fn.name(), '', args, returns);\n            }\n        });\n        this.registerType('torch.utils._contextlib._DecoratorContextManager', class {});\n        this.registerType('torch.utils._contextlib._NoParamDecoratorContextManager', class extends torch.utils._contextlib._DecoratorContextManager {});\n        this.registerType('torch.utils._sympy.symbol.SymT', class extends this.enum.Enum {});\n        this.registerType('torch.utils._sympy.functions.FloorDiv', class extends sympy.core.function.Function {\n            __str__() {\n                return this._args.map((a) => a.__str__()).join('//');\n            }\n        });\n        this.registerType('torch.utils._sympy.functions.ModularIndexing', class {});\n        this.registerType('torch.utils._sympy.functions.Where', class {});\n        this.registerType('torch.utils._sympy.functions.PythonMod', class {});\n        this.registerType('torch.utils._sympy.functions.Mod', class {});\n        this.registerType('torch.utils._sympy.functions.CleanDiv', class {});\n        this.registerType('torch.utils._sympy.functions.CeilToInt', class {});\n        this.registerType('torch.utils._sympy.functions.FloorToInt', class {});\n        this.registerType('torch.utils._sympy.functions.CeilDiv', class {});\n        this.registerType('torch.utils._sympy.functions.LShift', class {});\n        this.registerType('torch.utils._sympy.functions.RShift', class {});\n        this.registerType('torch.utils._sympy.functions.PowByNatural', class {});\n        this.registerType('torch.utils._sympy.functions.FloatPow', class {});\n        this.registerType('torch.utils._sympy.functions.FloatTrueDiv', class {});\n        this.registerType('torch.utils._sympy.functions.IntTrueDiv', class {});\n        this.registerType('torch.utils._sympy.functions.IsNonOverlappingAndDenseIndicator', class {});\n        this.registerType('torch.utils._sympy.functions.TruncToFloat', class {});\n        this.registerType('torch.utils._sympy.functions.TruncToInt', class {});\n        this.registerType('torch.utils._sympy.functions.RoundToInt', class {});\n        this.registerType('torch.utils._sympy.functions.RoundDecimal', class {});\n        this.registerType('torch.utils._sympy.functions.ToFloat', class {});\n        this.registerType('torch.utils._sympy.functions.Identity', class {});\n        this.registerType('torch.utils._traceback.CapturedTraceback', class {\n            static extract() {\n            }\n        });\n        this.registerFunction('torch.utils.checkpoint.checkpoint');\n        this.registerType('torch.utils.data.dataloader._MultiProcessingDataLoaderIter', class {});\n        this.registerType('torch.utils.data.dataloader.DataLoader', class {});\n        this.registerFunction('torch.utils.data._utils.collate.default_collate');\n        torch.utils.data.dataloader.default_collate = torch.utils.data._utils.collate.default_collate;\n        this.registerType('torch.utils.data.dataset.Subset', class {});\n        this.registerType('torch.utils.data.dataset.Dataset', class {});\n        this.registerType('torch.utils.data.dataset.ConcatDataset', class {});\n        this.registerType('torch.utils.data.dataset.TensorDataset', class {});\n        this.registerType('torch.utils.data.sampler.BatchSampler', class {});\n        this.registerType('torch.utils.data.sampler.RandomSampler', class {});\n        this.registerType('torch.utils.data.sampler.SequentialSampler', class {});\n        this.registerType('torch.utils.data.sampler.SubsetRandomSampler', class {});\n        this.registerType('torch.utils.data.sampler.WeightedRandomSampler', class {});\n        this.registerType('torch.ao.quantization.fake_quantize.FakeQuantize', class {});\n        this.registerType('torch.ao.quantization.fake_quantize.FusedMovingAvgObsFakeQuantize', class {});\n        this.registerType('torch.ao.quantization.observer._PartialWrapper', class {});\n        this.registerType('torch.ao.quantization.observer.HistogramObserver', class {});\n        this.registerType('torch.ao.quantization.observer.MovingAverageMinMaxObserver', class {});\n        this.registerType('torch.ao.quantization.observer.MovingAveragePerChannelMinMaxObserver', class {});\n        this.registerType('torch.ao.quantization.observer.MinMaxObserver', class {});\n        this.registerType('torch.ao.quantization.observer.PerChannelMinMaxObserver', class {});\n        this.registerType('torch.ao.quantization.observer.PlaceholderObserver', class {});\n        this.registerType('torch.ao.quantization.qconfig.QConfig', class {});\n        this.registerType('torch.ao.quantization.qconfig.QConfigDynamic', class {});\n        this.registerType('torch.ao.quantization.stubs.DeQuantStub', class {});\n        this.registerType('torch.ao.quantization.stubs.QuantStub', class {});\n        this.registerType('torch.ao.quantization.stubs.QuantWrapper', class {});\n        this.registerFunction('torch.ao.quantization.qconfig._activation_is_memoryless');\n        this.registerFunction('torch.ao.quantization.qconfig._add_module_to_qconfig_obs_ctr');\n        this.registerFunction('torch.ao.quantization.fx.graph_module._save_packed_weight');\n        this.registerFunction('torch.ao.quantization.fx._lower_to_native_backend._load_packed_weight');\n        this.registerFunction('torch.ao.quantization.fx._lower_to_native_backend._save_packed_weight');\n        this.registerFunction('torch.ao.quantization.observer._is_activation_post_process');\n        this.registerFunction('torch.ao.quantization.quantize._observer_forward_hook');\n        this.registerFunction('torch.ao.quantization.quantization_mappings._get_special_act_post_process');\n        this.registerFunction('torch.ao.quantization.quantization_mappings.get_default_dynamic_quant_module_mappings');\n        this.registerFunction('torch.ao.quantization.quantization_mappings.get_default_qat_module_mappings');\n        this.registerFunction('torch.ao.quantization.quantization_mappings.get_default_qconfig_propagation_list');\n        this.registerFunction('torch.ao.quantization.quantization_mappings.get_default_static_quant_module_mappings');\n        this.registerFunction('torch.ao.quantization.quantization_mappings.get_default_static_quant_reference_module_mappings');\n        this.registerFunction('torch.ao.quantization.quantization_mappings.no_observer_set');\n        this.registerFunction('torch.ao.quantization.quantization_mappings._has_special_act_post_process');\n        this.registerFunction('torch.ao.quantization.utils.get_qparam_dict');\n        this.registerFunction('torch.ao.quantization.utils.has_no_children_ignoring_parametrizations');\n        this.registerFunction('torch.amp.grad_scaler._refresh_per_optimizer_state');\n        this.registerType('torch.amp.grad_scaler.GradScaler', class {});\n        this.registerType('torch._C._LegacyVariableBase', class {});\n        this.registerType('torch.autograd.grad_mode.no_grad', class extends torch.utils._contextlib._NoParamDecoratorContextManager {});\n        this.registerType('torch.autograd.variable.Variable', class extends torch._C._LegacyVariableBase {});\n        this.registerType('torch.autograd.function._SingleLevelFunction', class {});\n        this.registerType('torch.autograd.function.Function', class extends torch.autograd.function._SingleLevelFunction {});\n        this.registerType('torch.backends.cudnn.rnn.Unserializable', class {});\n        this.registerFunction('torch.distributed._shard.sharded_tensor.pre_load_state_dict_hook');\n        this.registerFunction('torch.distributed._shard.sharded_tensor.state_dict_hook');\n        this.registerFunction('torch.distributed._sharded_tensor.state_dict_hook');\n        this.registerFunction('torch.distributed._sharded_tensor.pre_load_state_dict_hook');\n        this.registerType('torch.distributed.algorithms.join._JoinConfig', class {});\n        this.registerType('torch.distributed.remote_device._remote_device', class {});\n        this.registerType('torch.distributed._shard.metadata.ShardMetadata', class {});\n        this.registerType('torch.distributed._shard.sharded_tensor.api.ShardedTensor', class {});\n        this.registerType('torch.distributed._shard.sharded_tensor.metadata.ShardedTensorMetadata', class {});\n        this.registerType('torch.distributed._shard.sharded_tensor.metadata.TensorProperties', class {});\n        this.registerType('torch.distributed._shard.sharded_tensor.shard.Shard', class {});\n        this.registerType('torch.distributed._tensor.api.DTensor', class extends torch._C._TensorMeta {});\n        this.registerType('torch.distributed._tensor.placement_types.DTensorSpec', class {});\n        this.registerType('torch.distributed._tensor.placement_types.Shard', class {});\n        this.registerType('torch.distributed._tensor.placement_types.TensorMeta', class {});\n        this.registerType('torch.distributed.device_mesh.DeviceMesh', class {});\n        this.registerType('torch.distributed.tensor.DTensor', class extends torch._C._TensorMeta {});\n        this.registerType('torch.distributed.tensor._dtensor_spec.DTensorSpec', class {});\n        this.registerType('torch.distributed.tensor._dtensor_spec.TensorMeta', class {});\n        this.registerType('torch.distributed.tensor.placement_types.Shard', class {});\n        this.registerType('torch.distributions.bernoulli.Bernoulli', class {});\n        this.registerType('torch.distributions.beta.Beta', class {});\n        this.registerType('torch.distributions.binomial.Binomial', class {});\n        this.registerType('torch.distributions.categorical.Categorical', class {});\n        this.registerType('torch.distributions.constraints._GreaterThan', class {});\n        this.registerType('torch.distributions.constraints._Interval', class {});\n        this.registerType('torch.distributions.constraints._LowerCholesky', class {});\n        this.registerType('torch.distributions.constraints._Real', class {});\n        this.registerType('torch.distributions.dirichlet.Dirichlet', class {});\n        this.registerType('torch.distributions.mixture_same_family.MixtureSameFamily', class {});\n        this.registerType('torch.distributions.multivariate_normal.MultivariateNormal', class {});\n        this.registerType('torch.distributions.normal.Normal', class {});\n        this.registerType('torch.distributions.transforms._InverseTransform', class {});\n        this.registerType('torch.distributions.transforms.AffineTransform', class {});\n        this.registerType('torch.distributions.transforms.ComposeTransform', class {});\n        this.registerType('torch.distributions.transforms.ExpTransform', class {});\n        this.registerType('torch.distributions.transforms.LowerCholeskyTransform', class {});\n        this.registerType('torch.distributions.uniform.Uniform', class {});\n        this.registerType('torch.nn.backends.thnn._get_thnn_function_backend', class {});\n        this.registerType('torch.nn.intrinsic.modules.fused._FusedModule', class {});\n        this.registerType('torch.nn.intrinsic.modules.fused.ConvBnReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.modules.fused.ConvReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.modules.fused.BNReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.qat.modules.conv_fused.ConvBn2d', class {});\n        this.registerType('torch.nn.intrinsic.qat.modules.conv_fused.ConvBnReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.qat.modules.conv_fused.ConvReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.quantized.modules.bn_relu.BNReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.quantized.modules.conv_relu.ConvReLU1d', class {});\n        this.registerType('torch.nn.intrinsic.quantized.modules.conv_relu.ConvReLU2d', class {});\n        this.registerType('torch.nn.intrinsic.quantized.modules.linear_relu.LinearReLU', class {});\n        this.registerType('torch.nn.modules.activation.CELU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.ELU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.GELU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.GLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Hardtanh', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Hardshrink', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Hardsigmoid', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Hardswish', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.LeakyReLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.LogSigmoid', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.LogSoftmax', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Mish', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.MultiheadAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.ReLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.ReLU6', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.PReLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.RReLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.SELU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Sigmoid', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.SiLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Softmax', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Softmax2d', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Softmin', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Softplus', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Softshrink', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Softsign', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Tanh', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Tanhshrink', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.activation.Threshold', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.adaptive.AdaptiveLogSoftmaxWithLoss', class {});\n        this.registerType('torch.nn.modules.batchnorm._NormBase', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.batchnorm._BatchNorm', class extends torch.nn.modules.batchnorm._NormBase {});\n        this.registerType('torch.nn.modules.batchnorm.BatchNorm1d', class extends torch.nn.modules.batchnorm._BatchNorm {});\n        this.registerType('torch.nn.modules.batchnorm.BatchNorm2d', class extends torch.nn.modules.batchnorm._BatchNorm {});\n        this.registerType('torch.nn.modules.batchnorm.BatchNorm3d', class extends torch.nn.modules.batchnorm._BatchNorm {});\n        this.registerType('torch.nn.modules.batchnorm.LazyBatchNorm1d', class {});\n        this.registerType('torch.nn.modules.batchnorm.LazyBatchNorm2d', class {});\n        this.registerType('torch.nn.modules.batchnorm.LazyBatchNorm3d', class {});\n        this.registerType('torch.nn.modules.batchnorm.SyncBatchNorm', class {});\n        this.registerType('torch.nn.modules.byted_batchnorm.BytedBatchNorm2d', class {});\n        this.registerType('torch.nn.modules.channelshuffle.ChannelShuffle', class {});\n        this.registerType('torch.nn.modules.container.ModuleDict', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.container.ModuleList', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.container.ParameterDict', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.container.ParameterList', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.container.Sequential', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.conv._ConvNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.conv.Conv1d', class extends torch.nn.modules.conv._ConvNd {});\n        this.registerType('torch.nn.modules.conv.Conv2d', class extends torch.nn.modules.conv._ConvNd {});\n        this.registerType('torch.nn.modules.conv.Conv3d', class extends torch.nn.modules.conv._ConvNd {});\n        this.registerType('torch.nn.modules.conv._ConvTransposeNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.conv.ConvTranspose1d', class extends torch.nn.modules.conv._ConvTransposeNd {});\n        this.registerType('torch.nn.modules.conv.ConvTranspose2d', class extends torch.nn.modules.conv._ConvTransposeNd {});\n        this.registerType('torch.nn.modules.conv.ConvTranspose3d', class extends torch.nn.modules.conv._ConvTransposeNd {});\n        this.registerType('torch.nn.modules.conv.LazyConv1d', class {});\n        this.registerType('torch.nn.modules.conv.LazyConv2d', class {});\n        this.registerType('torch.nn.modules.conv.LazyConv3d', class {});\n        this.registerType('torch.nn.modules.conv.LazyConvTranspose2d', class {});\n        this.registerType('torch.nn.modules.conv.LazyConvTranspose3d', class {});\n        this.registerType('torch.nn.modules.distance.CosineSimilarity', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.distance.PairwiseDistance', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.dropout._DropoutNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.dropout.AlphaDropout', class extends torch.nn.modules.dropout._DropoutNd {});\n        this.registerType('torch.nn.modules.dropout.Dropout', class extends torch.nn.modules.dropout._DropoutNd {});\n        this.registerType('torch.nn.modules.dropout.Dropout1d', class extends torch.nn.modules.dropout._DropoutNd {});\n        this.registerType('torch.nn.modules.dropout.Dropout2d', class extends torch.nn.modules.dropout._DropoutNd {});\n        this.registerType('torch.nn.modules.dropout.Dropout3d', class extends torch.nn.modules.dropout._DropoutNd {});\n        this.registerType('torch.nn.modules.dropout.FeatureAlphaDropout', class extends torch.nn.modules.dropout._DropoutNd {});\n        this.registerType('torch.nn.modules.fold.Fold', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.fold.Unfold', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.flatten.Flatten', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.flatten.Unflatten', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.instancenorm.InstanceNorm1d', class {});\n        this.registerType('torch.nn.modules.instancenorm.InstanceNorm2d', class {});\n        this.registerType('torch.nn.modules.instancenorm.InstanceNorm3d', class {});\n        this.registerType('torch.nn.modules.instancenorm.LazyInstanceNorm2d', class {});\n        this.registerType('torch.nn.modules.instancenorm.LazyInstanceNorm3d', class {});\n        this.registerType('torch.nn.modules.linear._LinearWithBias', class {});\n        this.registerType('torch.nn.modules.linear.Bilinear', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.linear.Identity', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.linear.LazyLinear', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.linear.Linear', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.linear.NonDynamicallyQuantizableLinear', class extends torch.nn.modules.linear.Linear {});\n        this.registerType('torch.nn.modules.loss._Loss', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.loss._WeightedLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.BCELoss', class extends torch.nn.modules.loss._WeightedLoss {});\n        this.registerType('torch.nn.modules.loss.BCEWithLogitsLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.CrossEntropyLoss', class extends torch.nn.modules.loss._WeightedLoss {});\n        this.registerType('torch.nn.modules.loss.CosineEmbeddingLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.CTCLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.GaussianNLLLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.HuberLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.HingeEmbeddingLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.KLDivLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.L1Loss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.MarginRankingLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.MultiLabelMarginLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.MultiLabelSoftMarginLoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.MultiMarginLoss', class extends torch.nn.modules.loss._WeightedLoss {});\n        this.registerType('torch.nn.modules.loss.MSELoss', class extends torch.nn.modules.loss._Loss {});\n        this.registerType('torch.nn.modules.loss.NLLLoss', class extends torch.nn.modules.loss._WeightedLoss {});\n        this.registerType('torch.nn.modules.loss.NLLLoss2d', class extends torch.nn.modules.loss.NLLLoss {});\n        this.registerType('torch.nn.modules.loss.PoissonNLLLoss', class {});\n        this.registerType('torch.nn.modules.loss.SmoothL1Loss', class {});\n        this.registerType('torch.nn.modules.loss.SoftMarginLoss', class {});\n        this.registerType('torch.nn.modules.loss.TripletMarginLoss', class {});\n        this.registerType('torch.nn.modules.loss.TripletMarginWithDistanceLoss', class {});\n        this.registerType('torch.nn.modules.module._IncompatibleKeys', class {});\n        this.registerType('torch.nn.modules.module._WrappedHook', class {});\n        this.registerType('torch.nn.modules.module.PatchForward', class {});\n        this.registerType('torch.nn.modules.normalization.CrossMapLRN2d', class {});\n        this.registerType('torch.nn.modules.normalization.GroupNorm', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.normalization.LayerNorm', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.normalization.LocalResponseNorm', class {});\n        this.registerType('torch.nn.modules.normalization.RMSNorm', class {});\n        this.registerType('torch.nn.modules.padding._ReflectionPadNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.padding.ReflectionPad1d', class extends torch.nn.modules.padding._ReflectionPadNd {});\n        this.registerType('torch.nn.modules.padding.ReflectionPad2d', class extends torch.nn.modules.padding._ReflectionPadNd {});\n        this.registerType('torch.nn.modules.padding.ReflectionPad3d', class extends torch.nn.modules.padding._ReflectionPadNd {});\n        this.registerType('torch.nn.modules.padding._ReplicationPadNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.padding.ReplicationPad1d', class extends torch.nn.modules.padding._ReplicationPadNd {});\n        this.registerType('torch.nn.modules.padding.ReplicationPad2d', class extends torch.nn.modules.padding._ReplicationPadNd {});\n        this.registerType('torch.nn.modules.padding.ReplicationPad3d', class extends torch.nn.modules.padding._ReplicationPadNd {});\n        this.registerType('torch.nn.modules.padding.ZeroPad1d', class {});\n        this.registerType('torch.nn.modules.padding.ZeroPad2d', class {});\n        this.registerType('torch.nn.modules.padding.ZeroPad3d', class {});\n        this.registerType('torch.nn.modules.padding.ConstantPad1d', class {});\n        this.registerType('torch.nn.modules.padding.ConstantPad2d', class {});\n        this.registerType('torch.nn.modules.padding.ConstantPad3d', class {});\n        this.registerType('torch.nn.modules.padding.CircularPad3d', class {});\n        this.registerType('torch.nn.modules.pixelshuffle.PixelShuffle', class {});\n        this.registerType('torch.nn.modules.pixelshuffle.PixelUnshuffle', class {});\n        this.registerType('torch.nn.modules.pooling._AdaptiveAvgPoolNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.pooling.AdaptiveAvgPool1d', class extends torch.nn.modules.pooling._AdaptiveAvgPoolNd {});\n        this.registerType('torch.nn.modules.pooling.AdaptiveAvgPool2d', class extends torch.nn.modules.pooling._AdaptiveAvgPoolNd {});\n        this.registerType('torch.nn.modules.pooling.AdaptiveAvgPool3d', class extends torch.nn.modules.pooling._AdaptiveAvgPoolNd {});\n        this.registerType('torch.nn.modules.pooling.AdaptiveMaxPool1d', class {});\n        this.registerType('torch.nn.modules.pooling.AdaptiveMaxPool2d', class {});\n        this.registerType('torch.nn.modules.pooling.AdaptiveMaxPool3d', class {});\n        this.registerType('torch.nn.modules.pooling.AvgPool1d', class {});\n        this.registerType('torch.nn.modules.pooling.AvgPool2d', class {});\n        this.registerType('torch.nn.modules.pooling.AvgPool3d', class {});\n        this.registerType('torch.nn.modules.pooling.FractionalMaxPool2d', class {});\n        this.registerType('torch.nn.modules.pooling.FractionalMaxPool3d', class {});\n        this.registerType('torch.nn.modules.pooling.LPPool1d', class {});\n        this.registerType('torch.nn.modules.pooling.LPPool2d', class {});\n        this.registerType('torch.nn.modules.pooling.LPPool3d', class {});\n        this.registerType('torch.nn.modules.pooling._MaxPoolNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.pooling.MaxPool1d', class extends torch.nn.modules.pooling._MaxPoolNd {});\n        this.registerType('torch.nn.modules.pooling.MaxPool2d', class extends torch.nn.modules.pooling._MaxPoolNd {});\n        this.registerType('torch.nn.modules.pooling.MaxPool3d', class extends torch.nn.modules.pooling._MaxPoolNd {});\n        this.registerType('torch.nn.modules.pooling._MaxUnpoolNd', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.pooling.MaxUnpool1d', class extends torch.nn.modules.pooling._MaxUnpoolNd {});\n        this.registerType('torch.nn.modules.pooling.MaxUnpool2d', class extends torch.nn.modules.pooling._MaxUnpoolNd {});\n        this.registerType('torch.nn.modules.pooling.MaxUnpool3d', class extends torch.nn.modules.pooling._MaxUnpoolNd {});\n        this.registerType('torch.nn.modules.rnn.GRU', class {});\n        this.registerType('torch.nn.modules.rnn.GRUCell', class {});\n        this.registerType('torch.nn.modules.rnn.LSTM', class {});\n        this.registerType('torch.nn.modules.rnn.LSTMCell', class {});\n        this.registerType('torch.nn.modules.rnn.RNNBase', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.rnn.RNN', class extends torch.nn.modules.rnn.RNNBase {});\n        this.registerType('torch.nn.modules.rnn.RNNCellBase', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.nn.modules.rnn.RNNCell', class extends torch.nn.modules.rnn.RNNCellBase {});\n        this.registerType('torch.nn.modules.sparse.Embedding', class {});\n        this.registerType('torch.nn.modules.sparse.EmbeddingBag', class {});\n        this.registerType('torch.nn.modules.transformer.Transformer', class {});\n        this.registerType('torch.nn.modules.transformer.TransformerDecoder', class {});\n        this.registerType('torch.nn.modules.transformer.TransformerDecoderLayer', class {});\n        this.registerType('torch.nn.modules.transformer.TransformerEncoder', class {});\n        this.registerType('torch.nn.modules.transformer.TransformerEncoderLayer', class {});\n        this.registerType('torch.nn.modules.upsampling.Upsample', class {});\n        this.registerType('torch.nn.modules.upsampling.UpsamplingBilinear2d', class {});\n        this.registerType('torch.nn.modules.upsampling.UpsamplingNearest2d', class {});\n        this.registerType('torch.nn.parallel.data_parallel.DataParallel', class {});\n        this.registerType('torch.nn.parallel.distributed._DDPUnevenInputsConfig', class {});\n        this.registerType('torch.nn.parallel.distributed.DistributedDataParallel', class {});\n        this.registerType('torch.nn.qat.modules.conv.Conv2d', class {});\n        this.registerType('torch.nn.qat.modules.linear.Linear', class {});\n        this.registerType('torch.nn.quantized.modules.activation.ReLU', class {});\n        this.registerType('torch.nn.quantized.modules.activation.LeakyReLU', class {});\n        this.registerType('torch.nn.quantized.modules.activation.Softmax', class {});\n        this.registerType('torch.nn.quantized.dynamic.modules.linear.Linear', class {});\n        this.registerType('torch.nn.quantized.dynamic.modules.rnn.GRU', class {});\n        this.registerType('torch.nn.quantized.dynamic.modules.rnn.LSTM', class {});\n        this.registerType('torch.nn.quantized.dynamic.modules.rnn.LSTMCell', class {});\n        this.registerType('torch.nn.quantized.dynamic.modules.rnn.PackedParameter', class {});\n        this.registerType('torch.nn.quantized.modules.activation.ReLU6', class {});\n        this.registerType('torch.nn.quantized.modules.batchnorm.BatchNorm2d', class {});\n        this.registerType('torch.nn.quantized.modules.conv.Conv1d', class {});\n        this.registerType('torch.nn.quantized.modules.conv.Conv2d', class {});\n        this.registerType('torch.nn.quantized.modules.conv.ConvTranspose2d', class {});\n        this.registerType('torch.nn.quantized.modules.DeQuantize', class {});\n        this.registerType('torch.nn.quantized.modules.dropout.Dropout', class {});\n        this.registerType('torch.nn.quantized.modules.embedding_ops.Embedding', class {});\n        this.registerType('torch.nn.quantized.modules.embedding_ops.EmbeddingPackedParams', class {});\n        this.registerType('torch.nn.quantized.modules.functional_modules.FloatFunctional', class {});\n        this.registerType('torch.nn.quantized.modules.functional_modules.QFunctional', class {});\n        this.registerType('torch.nn.quantized.modules.linear.Linear', class {});\n        this.registerType('torch.nn.quantized.modules.linear.LinearPackedParams', class {});\n        this.registerType('torch.nn.quantized.modules.normalization.InstanceNorm2d', class {});\n        this.registerType('torch.nn.quantized.modules.normalization.GroupNorm', class extends torch.nn.modules.normalization.GroupNorm {});\n        this.registerType('torch.nn.quantized.modules.normalization.LayerNorm', class extends torch.nn.modules.normalization.LayerNorm {});\n        this.registerType('torch.nn.quantized.modules.Quantize', class {});\n        this.registerType('torch.ao.nn.quantizable.modules.activation.MultiheadAttention', class extends torch.nn.modules.activation.MultiheadAttention {});\n        this.registerType('torch.ao.nn.quantizable.modules.rnn._LSTMLayer', class {});\n        this.registerType('torch.ao.nn.quantizable.modules.rnn._LSTMSingleLayer', class {});\n        this.registerType('torch.ao.nn.quantizable.modules.rnn.LSTM', class {});\n        this.registerType('torch.ao.nn.quantizable.modules.rnn.LSTMCell', class {});\n        this.registerType('torch.ao.nn.quantized.modules.activation.ELU', class extends torch.nn.modules.activation.ELU {});\n        this.registerType('torch.ao.nn.quantized.modules.activation.Hardswish', class extends torch.nn.modules.activation.Hardswish {});\n        this.registerType('torch.ao.nn.quantized.modules.activation.MultiheadAttention', class extends torch.ao.nn.quantizable.modules.activation.MultiheadAttention {});\n        this.registerType('torch.ao.nn.quantized.modules.activation.PReLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.activation.ReLU6', class extends torch.nn.modules.activation.ReLU {});\n        this.registerType('torch.ao.nn.quantized.modules.activation.LeakyReLU', class extends torch.nn.modules.activation.LeakyReLU {});\n        this.registerType('torch.ao.nn.quantized.modules.utils.WeightedQuantizedModule', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.batchnorm._BatchNorm',  class extends torch.nn.modules.batchnorm._BatchNorm {});\n        this.registerType('torch.ao.nn.quantized.modules.batchnorm.BatchNorm2d', class extends torch.ao.nn.quantized.modules.batchnorm._BatchNorm {});\n        this.registerType('torch.ao.nn.quantized.modules.conv.Conv1d', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.conv.Conv2d', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.conv._ConvNd', class extends torch.ao.nn.quantized.modules.utils.WeightedQuantizedModule {});\n        this.registerType('torch.ao.nn.quantized.modules.conv._ConvTransposeNd', class extends torch.ao.nn.quantized.modules.conv._ConvNd {});\n        this.registerType('torch.ao.nn.quantized.modules.conv.ConvTranspose1d', class extends torch.ao.nn.quantized.modules.conv._ConvTransposeNd {});\n        this.registerType('torch.ao.nn.quantized.modules.conv.ConvTranspose2d', class extends torch.ao.nn.quantized.modules.conv._ConvTransposeNd {});\n        this.registerType('torch.ao.nn.quantized.modules.Quantize', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.DeQuantize', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.dropout.Dropout', class extends torch.nn.modules.dropout.Dropout {});\n        this.registerType('torch.ao.nn.quantized.modules.embedding_ops.Embedding', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.embedding_ops.EmbeddingPackedParams', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.functional_modules.FloatFunctional', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.functional_modules.QFunctional', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.functional_modules.FXFloatFunctional', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.linear.Linear', class extends torch.ao.nn.quantized.modules.utils.WeightedQuantizedModule {});\n        this.registerType('torch.ao.nn.quantized.modules.linear.LinearPackedParams', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.modules.normalization.LayerNorm', class extends torch.nn.modules.normalization.LayerNorm {});\n        this.registerType('torch.ao.nn.quantized.modules.normalization.InstanceNorm1d', class extends torch.nn.modules.instancenorm.InstanceNorm1d {});\n        this.registerType('torch.ao.nn.quantized.modules.normalization.InstanceNorm2d', class extends torch.nn.modules.instancenorm.InstanceNorm2d {});\n        this.registerType('torch.ao.nn.quantized.modules.normalization.InstanceNorm3d', class extends torch.nn.modules.instancenorm.InstanceNorm3d {});\n        this.registerType('torch.ao.nn.quantized.modules.rnn.LSTM', class {});\n        this.registerType('torch.ao.nn.quantized.dynamic.modules.linear.Linear', class extends torch.ao.nn.quantized.modules.linear.Linear {});\n        this.registerType('torch.ao.nn.quantized.dynamic.modules.rnn.PackedParameter', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.dynamic.modules.rnn.RNNBase', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.ao.nn.quantized.dynamic.modules.rnn.GRU', class extends torch.ao.nn.quantized.dynamic.modules.rnn.RNNBase {});\n        this.registerType('torch.ao.nn.quantized.dynamic.modules.rnn.LSTM', class extends torch.ao.nn.quantized.dynamic.modules.rnn.RNNBase {});\n        this.registerType('torch.ao.nn.quantized.reference.modules.conv.Conv1d', class {});\n        this.registerType('torch.ao.nn.quantized.reference.modules.conv.Conv2d', class {});\n        this.registerType('torch.ao.nn.quantized.reference.modules.linear.Linear', class {});\n        this.registerType('torch.ao.nn.qat.modules.conv.Conv2d', class {});\n        this.registerType('torch.ao.nn.qat.modules.linear.Linear', class {});\n        this.registerType('torch.ao.nn.intrinsic.quantized.modules.conv_relu.ConvReLU1d', class extends torch.ao.nn.quantized.modules.conv.Conv1d {});\n        this.registerType('torch.ao.nn.intrinsic.quantized.modules.conv_relu.ConvReLU2d', class extends torch.ao.nn.quantized.modules.conv.Conv2d {});\n        this.registerType('torch.ao.nn.intrinsic.quantized.modules.linear_relu.LinearReLU', class extends torch.ao.nn.quantized.modules.linear.Linear {});\n        this.registerType('torch.ao.nn.intrinsic.quantized.modules.bn_relu.BNReLU2d', class extends torch.ao.nn.quantized.modules.batchnorm.BatchNorm2d {});\n        this.registerType('torch.ao.nn.intrinsic.modules.fused._FusedModule', class extends torch.nn.modules.container.Sequential {});\n        this.registerType('torch.ao.nn.intrinsic.modules.fused.ConvBn2d', class extends torch.ao.nn.intrinsic.modules.fused._FusedModule {});\n        this.registerType('torch.ao.nn.intrinsic.modules.fused.ConvReLU1d', class extends torch.ao.nn.intrinsic.modules.fused._FusedModule {});\n        this.registerType('torch.ao.nn.intrinsic.modules.fused.ConvReLU2d', class extends torch.ao.nn.intrinsic.modules.fused._FusedModule {});\n        this.registerType('torch.ao.nn.intrinsic.modules.fused.LinearReLU', class extends torch.ao.nn.intrinsic.modules.fused._FusedModule {});\n        this.registerType('torch.ao.nn.intrinsic.modules.fused.ConvBnReLU2d', class extends torch.ao.nn.intrinsic.modules.fused._FusedModule {});\n        this.registerType('torch.ao.nn.intrinsic.qat.modules.conv_fused.ConvBnReLU2d', class {});\n        this.registerType('torch.nn.utils.prune.CustomFromMask', class {});\n        this.registerType('torch.nn.utils.prune.Identity', class {});\n        this.registerType('torch.nn.utils.prune.L1Unstructured', class {});\n        this.registerType('torch.nn.utils.prune.LnStructured', class {});\n        this.registerType('torch.nn.utils.prune.PruningContainer', class {});\n        this.registerType('torch.nn.utils.prune.RandomUnstructured', class {});\n        this.registerType('torch.nn.utils.spectral_norm.SpectralNorm', class {});\n        this.registerType('torch.nn.utils.spectral_norm.SpectralNormStateDictHook', class {});\n        this.registerType('torch.nn.utils.spectral_norm.SpectralNormLoadStateDictPreHook', class {});\n        this.registerType('torch.nn.utils.weight_norm.WeightNorm', class {});\n        this.registerFunction('torch.nn.utils.parametrize.type_before_parametrizations');\n        this.registerType('torch.nn.utils.parametrize.ParametrizationList', class extends torch.nn.modules.container.ModuleList {});\n        this.registerType('torch.torch_version.TorchVersion', class extends String {});\n        this.registerType('torch.optim.optimizer.Optimizer', class {});\n        this.registerType('torch.optim.adam.Adam', class extends torch.optim.optimizer.Optimizer {});\n        this.registerType('torch.optim.adamax.Adamax', class {});\n        this.registerType('torch.optim.adamw.AdamW', class {});\n        this.registerType('torch.optim.adagrad.Adagrad', class {});\n        this.registerType('torch.optim.adadelta.Adadelta', class {});\n        this.registerType('torch.optim.lbfgs.LBFGS', class {});\n        this.registerType('torch.optim.Muon', class {});\n        this.registerType('torch.optim.nadam.NAdam', class {});\n        this.registerType('torch.optim.lr_scheduler.CosineAnnealingLR', class {});\n        this.registerType('torch.optim.lr_scheduler.CosineAnnealingWarmRestarts', class {});\n        this.registerType('torch.optim.lr_scheduler.CyclicLR', class {});\n        this.registerType('torch.optim.lr_scheduler.ExponentialLR', class {});\n        this.registerType('torch.optim.lr_scheduler.LambdaLR', class {});\n        this.registerType('torch.optim.lr_scheduler.LinearLR', class {});\n        this.registerType('torch.optim.lr_scheduler.MultiStepLR', class {});\n        this.registerType('torch.optim.lr_scheduler.SequentialLR', class {});\n        this.registerType('torch.optim.lr_scheduler.OneCycleLR', class {});\n        this.registerType('torch.optim.lr_scheduler.ReduceLROnPlateau', class {});\n        this.registerType('torch.optim.lr_scheduler.StepLR', class {});\n        this.registerType('torch.optim.optimizer._RequiredParameter', class {});\n        this.registerType('torch.optim.radam.RAdam', class extends torch.optim.optimizer.Optimizer {});\n        this.registerType('torch.optim.rmsprop.RMSprop', class {});\n        this.registerType('torch.optim.sgd.SGD', class {});\n        this.registerType('torch.optim.sparse_adam.SparseAdam', class {});\n        this.registerType('torch.optim.swa_utils.SWALR', class {});\n        torch.optim.RAdam = torch.optim.radam.RAdam;\n        this.registerType('torch.quantization.fake_quantize.FakeQuantize', class {});\n        this.registerFunction('torch.quantization.fx.graph_module._save_packed_weight');\n        this.registerType('torch.quantization.observer._PartialWrapper', class {});\n        this.registerType('torch.quantization.observer.HistogramObserver', class {});\n        this.registerType('torch.quantization.observer.MinMaxObserver', class {});\n        this.registerType('torch.quantization.observer.MovingAverageMinMaxObserver', class {});\n        this.registerType('torch.quantization.observer.MovingAveragePerChannelMinMaxObserver', class {});\n        this.registerFunction('torch.quantization.observer._with_args');\n        this.registerType('torch.quantization.qconfig.QConfig', class {});\n        this.registerType('torch.quantization.stubs.DeQuantStub', class {});\n        this.registerType('torch.quantization.stubs.QuantStub', class {});\n        this.registerType('torch.utils._pytree.LeafSpec', class {});\n        this.registerType('torch.utils._pytree.TreeSpec', class {});\n        this.registerType('torch.utils._python_dispatch.TorchDispatchMode', class {\n            __enter__() {\n                return this;\n            }\n            __exit__(/* exc_type, exc_value, traceback */) {\n            }\n        });\n        this.registerFunction('torch.utils._pytree.tree_map');\n        torch.nn.Sequential = torch.nn.modules.container.Sequential;\n        this.registerFunction('torch.fx.experimental.sym_node.SymNode', class {\n            constructor(expr, shape_env, pytype, hint, constant, fx_node, optimized_summation) {\n                this._expr = expr;\n                this.shape_env = shape_env;\n                this.pytype = pytype;\n                this._optimized_summation = optimized_summation;\n                this._hint = hint;\n                this.constant = constant;\n                const tx_validation_en = this.shape_env && this.shape_env._translation_validation_enabled ? true : false;\n                this.fx_node = tx_validation_en && fx_node ? fx_node : null;\n            }\n            __str__() {\n                return this._expr.__str__();\n            }\n        });\n        this.registerType('torch.fx.experimental.symbolic_shapes.ShapeEnv', class {\n            constructor() {\n                this.var_to_val = new Map();\n                this.var_to_stack = new Map();\n            }\n            add_var_to_val(expr, val) {\n                this.var_to_val.set(expr, new sympy.core.numbers.Integer(val));\n            }\n            constrain_symbol_range(/* s, compiler_min, compiler_max */) {\n            }\n            create_symintnode(sym, hint, source) {\n                let out = null;\n                let fx_node = null;\n                if (this._translation_validation_enabled && source !== null) {\n                    throw new python.Error('Not implemented.');\n                } else {\n                    fx_node = null;\n                }\n                if (builtins.isinstance(sym, sympy.core.numbers.Integer)) {\n                    out = builtins.int(sym);\n                    if (hint !== null && out !== hint) {\n                        throw new python.Error(`Symbolic integer has value '${out}' but expected '${hint}'.`);\n                    }\n                } else {\n                    // if free_unbacked_symbols(sym):\n                    //     hint = None\n                    out = new torch.SymInt(new torch.fx.experimental.sym_node.SymNode(sym, this, builtins.int, hint, null, fx_node));\n                }\n                return out;\n            }\n            create_symboolnode(sym) {\n                return new torch.SymBool(new torch.fx.experimental.sym_node.SymNode(sym, this, builtins.bool, null));\n            }\n        });\n        this.registerFunction('torch.fx.experimental.symbolic_shapes.symbol_is_type', (/* sym, prefix */) => {\n            /*\n            assert isinstance(sym, sympy.Symbol)\n            const name_str = sym.name.toLowerCase();\n            if (builtins.isinstance(prefix, torch.utils._sympy.symbol.SymT)) {\n                return name_str.startsWith(prefix_str[prefix])\n            }\n            return name_str.startswith(tuple(prefix_str[p] for p in prefix));\n            */\n            return false;\n        });\n        this.registerType('torch.fx.proxy.TracerBase', class {\n            constructor() {\n                this.traced_func_name = 'forward';\n            }\n        });\n        this.registerType('torch.fx._symbolic_trace.Tracer', class extends torch.fx.proxy.TracerBase {\n            trace(root /*, concrete_args */) {\n                let fn = null;\n                if (root instanceof torch.nn.Module) {\n                    // torch.fx._lazy_graph_module._LazyGraphModule.force_recompile(root)\n                    this.root = root;\n                    fn = builtins.getattr(new builtins.type(root), this.traced_func_name);\n                    this.root_module_name = root._get_name();\n                    this.submodule_paths = new builtins.dict(root.named_modules());\n                } else {\n                    this.root = new torch.nn.Module();\n                    fn = root;\n                }\n                const tracer_cls = builtins.getattr(this, '__class__', null);\n                this.graph = new torch.fx.graph.Graph(null, tracer_cls);\n                if (builtins.hasattr(this, '__code__')) {\n                    const code = fn.__code__;\n                    this.graph._co_fields = {\n                        co_name: code.co_name,\n                        co_filename: code.co_filename,\n                        co_firstlineno: code.co_firstlineno,\n                    };\n                }\n                return this.graph;\n            }\n            is_leaf_module(m /*, module_qualified_name */) {\n                return (m.__module__.startsWith('torch.nn') || m.__module__.startsWith('torch.ao.nn')) && m instanceof torch.nn.Sequential === false;\n            }\n        });\n        this.registerType('torch.fx.experimental.proxy_tensor.PythonKeyTracer', class extends torch.fx._symbolic_trace.Tracer {});\n        this.registerType('torch.fx.experimental.proxy_tensor._ModuleStackTracer', class extends torch.fx.experimental.proxy_tensor.PythonKeyTracer {});\n        this.registerFunction('torch.fx._lazy_graph_module._make_graph_module', (...args) => {\n            const graph_module_cls = args.pop() || torch.fx.graph_module.GraphModule;\n            return new graph_module_cls(...args);\n        });\n        this.registerFunction('torch.fx.graph_module._deserialize_graph_module', (forward, body, graph_module_cls) => {\n            let tracer_cls = body.get('_tracer_cls');\n            if (!tracer_cls) {\n                tracer_cls = torch.fx._symbolic_trace.Tracer;\n            }\n            const graphmodule_cls_name = body.get('_graphmodule_cls_name', 'GraphModule');\n            const cls_tracer = tracer_cls;\n            const KeepModules = class extends cls_tracer {\n                is_leaf_module() {\n                    return true;\n                }\n            };\n            const com = new torch.fx.graph_module._CodeOnlyModule(body);\n            const tracer_extras = body.get('_tracer_extras', new builtins.dict());\n            const graph = new KeepModules().trace(com, tracer_extras);\n            graph._tracer_cls = tracer_cls;\n            const gm = torch.fx._lazy_graph_module._make_graph_module(com, graph, graphmodule_cls_name, graph_module_cls);\n            for (const [k, v] of body.items()) {\n                if (!builtins.hasattr(gm, k)) {\n                    builtins.setattr(gm, k, v);\n                }\n            }\n            return gm;\n        });\n        this.registerFunction('torch.fx.graph_module._forward_from_src', (src, globals /*, co_fields */) => {\n            globals = { ...globals };\n            const context = new python.Execution.Context(globals, null);\n            execution.exec(src, context);\n            const forward_fn = globals.forward;\n            delete globals.forward;\n            return forward_fn;\n        });\n        this.registerFunction('torch.fx.graph_module.reduce_graph_module', (body, import_block) => {\n            // https://github.com/pytorch/pytorch/blob/master/torch/fx/graph_module.py\n            let fn_src = null;\n            if (body.has('_code')) {\n                fn_src = body.get('_code');\n            } else if (body.has('code')) {\n                fn_src = body.get('code');\n            } else {\n                fn_src = body._code || body.code;\n            }\n            const forward = torch.fx.graph_module._forward_from_src(import_block + fn_src, {});\n            return torch.fx.graph_module._deserialize_graph_module(forward, body);\n        });\n        this.registerFunction('torch.fx.graph_module.reduce_package_graph_module', (importer, body, generated_module_name) => {\n            const forward = importer.import_module(generated_module_name).forward;\n            return torch.fx.graph_module._deserialize_graph_module(forward, body);\n        });\n        this.registerType('torch.fx.graph.CodeGen', class {});\n        this.registerType('torch.fx.graph._PyTreeInfo', class {\n            constructor(orig_args, in_spec, out_spec) {\n                this.orig_args = orig_args;\n                this.in_spec = in_spec;\n                this.out_spec = out_spec;\n            }\n        });\n        this.registerType('torch.fx.graph._Namespace', class {\n            constructor() {\n                this._obj_to_name = new Map();\n                this._unassociated_names = new Set();\n                this._used_names = new Set();\n                this._base_count = {};\n            }\n            create_name(candidate, obj) {\n                if (obj && this._obj_to_name.has(obj)) {\n                    return self._obj_to_name.get(obj);\n                }\n                candidate = candidate || '_unnamed';\n                candidate = /^\\d+$/.test(candidate) ? `_${candidate}` : candidate;\n                candidate = candidate.replace(/[^0-9a-zA-Z_]+/, '_');\n                const match = candidate.match(/(.*)_(\\d+)$\"/);\n                let base = candidate;\n                let num = null;\n                if (match) {\n                    [, base] = match;\n                    num = parseInt(match[2], 10);\n                }\n                candidate = num ? `${base}_${num}` : base;\n                if (!num) {\n                    num = this._base_count[base] || 0;\n                }\n                while (this._used_names.has(candidate) || this._is_illegal_name(candidate, obj)) {\n                    num += 1;\n                    candidate = `${base}_${num}`;\n                }\n                this._used_names.add(candidate);\n                this._base_count[base] = num;\n                if (obj) {\n                    this._obj_to_name[obj] = candidate;\n                } else {\n                    this._unassociated_names.add(candidate);\n                }\n                return candidate;\n            }\n            _is_illegal_name(/* name, obj */) {\n                /*\n                if name in keyword.kwlist:\n                    return True\n                if name in builtins.__dict__:\n                    return obj is not builtins.__dict__[name]\n                if name in _custom_builtins:\n                    return obj is not _custom_builtins[name].obj\n                */\n                return false;\n            }\n            associate_name_with_obj() {\n\n            }\n        });\n        this.registerType('torch.fx.node.Node', class {\n            constructor(graph, name, op, target, args, kwargs, return_type) {\n                this.graph = graph;\n                this.name = name;\n                this.op = op;\n                this.target = target;\n                this._input_nodes = new builtins.dict();\n                this.__update_args_kwargs(args, kwargs);\n                this.users = new builtins.dict();\n                this.type = return_type;\n                this._prev = this;\n                this._next = this;\n                this._erased = false;\n                this._repr_fn = null;\n                this.meta = new builtins.dict();\n            }\n            get args() {\n                return this._args;\n            }\n            get kwargs() {\n                return this._kwargs;\n            }\n            get next() {\n                return this._next;\n            }\n            prepend(x) {\n                x._remove_from_list();\n                const p = this._prev;\n                [p._next, x._prev] = [x, p];\n                [x._next, this._prev] = [this, x];\n            }\n            _remove_from_list() {\n                const [p, n] = [this._prev, this._next];\n                [p._next, n._prev] = [n, p];\n            }\n            __update_args_kwargs(new_args, new_kwargs) {\n                const update_users_and_input_nodes = (n) => {\n                    if (n instanceof torch.fx.node.Node) {\n                        this._input_nodes.setdefault(n);\n                        n.users.setdefault(this);\n                    }\n                    return n;\n                };\n                const map_aggregate = (a, fn) => {\n                    if (a instanceof builtins.tuple) {\n                        const t = new builtins.tuple(a.map((elem) => map_aggregate(elem, fn)));\n                        if (!builtins.hasattr(a, '_fields')) {\n                            return t;\n                        }\n                        throw new python.Error('Not implemented.');\n                        // return type(a)(*t);\n                    } else if (Array.isArray(a)) {\n                        return a.map((elem) => map_aggregate(elem, fn));\n                    } else if (a instanceof builtins.dict) {\n                        const rv = new builtins.dict();\n                        for (const [k, v] of a) {\n                            rv.__setitem__(k, map_aggregate(v, fn));\n                        }\n                        return rv;\n                    } else if (a instanceof builtins.slice) {\n                        throw new python.Error('Not implemented.');\n                        // return slice(map_aggregate(a.start, fn), map_aggregate(a.stop, fn), map_aggregate(a.step, fn))\n                    }\n                    return fn(a);\n                };\n                for (const old_use of this._input_nodes.keys()) {\n                    old_use.users.pop(this);\n                }\n                // object.__setattr__(self, \"_input_nodes\", {})\n                this._input_nodes = new builtins.dict();\n                // object.__setattr__(self, \"_args\", map_aggregate(new_args, update_users_and_input_nodes))\n                this._args = map_aggregate(new_args, update_users_and_input_nodes);\n                // object.__setattr__(self, \"_kwargs\", map_aggregate(new_kwargs, update_users_and_input_nodes))\n                this._kwargs = map_aggregate(new_kwargs, update_users_and_input_nodes);\n            }\n        });\n        torch.fx.Node = torch.fx.node.Node;\n        torch.fx.graph.Node = torch.fx.node.Node;\n        this.registerType('torch.fx.graph.Graph', class {\n            constructor(owning_module, tracer_cls, tracer_extras) {\n                this._root = new torch.fx.node.Node(self, '', 'root', '', new builtins.list(), new builtins.dict());\n                this._used_names = new Map();\n                this._len = 0;\n                this._graph_namespace = new torch.fx.graph._Namespace();\n                this._owning_module = owning_module;\n                this._tracer_cls = tracer_cls;\n                this._tracer_extras = tracer_extras;\n                // this._codegen = CodeGen()\n                // this._co_fields = {}\n            }\n            get nodes() {\n                const array = new Array(this._len);\n                let node = this._root.next;\n                for (let i = 0; node !== this._root; i++) {\n                    array[i] = node;\n                    node = node.next;\n                }\n                return array;\n            }\n            placeholder(name, type_expr /*, default_value */) {\n                const args = []; // () if default_value is inspect.Signature.empty else (default_value,)\n                const kwargs = new builtins.dict();\n                return this.create_node('placeholder', name, args, kwargs, type_expr);\n            }\n            create_node(op, target, args, kwargs, name, type_expr) {\n                args = args || new builtins.tuple();\n                kwargs = kwargs || new builtins.dict();\n                const candidate = name || this._target_to_str(target);\n                name = this._graph_namespace.create_name(candidate, null);\n                const n = new torch.fx.node.Node(this, name, op, target, args, kwargs, type_expr);\n                this._graph_namespace.associate_name_with_obj(name, n);\n                this._insert(n);\n                this._len += 1;\n                return n;\n            }\n            _insert(n) {\n                this._root.prepend(n);\n            }\n            output(result, type_expr) {\n                return this.create_node('output', 'output', new builtins.tuple(result), null, type_expr);\n            }\n            _target_to_str(target) {\n                if (typeof target === 'string') {\n                    if (target.startsWith('__') && target.endsWith('__')) {\n                        target = target.substring(2, target.length - 2);\n                    }\n                } else {\n                    target = target.__name__;\n                }\n                return this._snake_case(target);\n            }\n            _snake_case(s) {\n                const chars = [];\n                let prev_lower = false;\n                for (const c of s) {\n                    const x = c.toLowerCase();\n                    if (prev_lower && x !== c) {\n                        chars.push('_');\n                    } else {\n                        prev_lower = true;\n                    }\n                    chars.push(x);\n                }\n                return chars.join('');\n            }\n        });\n        this.registerType('torch.fx.graph_module._CodeOnlyModule', class extends torch.nn.modules.module.Module {\n            constructor(body) {\n                super();\n                for (const [k, v] of body.items()) {\n                    builtins.setattr(this, k, v);\n                }\n            }\n        });\n        this.registerFunction('torch.fx.graph_module._copy_attr', (from_module, to_module, target) => {\n            const parts = target.split('.');\n            const field = parts.pop();\n            for (const item of parts) {\n                const f = builtins.getattr(from_module, item);\n                let t = builtins.getattr(to_module, item, null);\n                if (f === t) {\n                    return;\n                }\n                if (t === null) {\n                    t = new torch.nn.modules.module.Module();\n                    builtins.setattr(to_module, item, t);\n                }\n                from_module = f;\n                to_module = t;\n            }\n            const orig = builtins.getattr(from_module, field);\n            builtins.setattr(to_module, field, orig);\n        });\n        this.registerType('torch.fx.graph_module.GraphModule', class extends torch.nn.modules.module.Module {\n            constructor(root, graph, class_name) {\n                super();\n                this.__class__.__name__ = class_name || 'GraphModule';\n                this.graph = graph;\n                if (root instanceof torch.nn.modules.module.Module && graph && graph.nodes) {\n                    for (const node of graph.nodes) {\n                        if (node.op === 'get_attr' || node.op === 'call_module') {\n                            torch.fx.graph_module._copy_attr(root, this, node.target);\n                        }\n                    }\n                }\n            }\n        });\n        torch.fx.Graph = torch.fx.graph.Graph;\n        torch.fx.GraphModule = torch.fx.graph_module.GraphModule;\n        this.registerType('torch.fx.graph._FindNodesLookupTable', class {});\n        this.registerType('torch.fx.immutable_collections.immutable_dict', class extends builtins.dict {});\n        this.registerType('torch.fx.immutable_collections.immutable_list', class extends builtins.list {});\n        this.registerType('torch.fx.passes.shape_prop.TensorMetadata', class {});\n        this.registerFunction('torch.fx._symbolic_trace.wrap', (fn_or_name) => {\n            return fn_or_name;\n        });\n        this.registerFunction('torch.fx._symbolic_trace._assert_is_none');\n        this.registerFunction('torchvision.datasets.folder.default_loader');\n        this.registerType('torchvision.datasets.folder.ImageFolder', class {});\n        this.registerType('torchvision.datasets.mnist.FashionMNIST', class {});\n        this.registerType('torchvision.datasets.mnist.MNIST', class {});\n        this.registerType('torchvision.datasets.video_utils.VideoClips', class {});\n        this.registerType('torchvision.datasets.vision.StandardTransform', class {});\n        this.registerType('torchvision.ops.deform_conv.DeformConv2d', class {});\n        this.registerType('torchvision.ops.feature_pyramid_network.FeaturePyramidNetwork', class {});\n        this.registerType('torchvision.ops.feature_pyramid_network.LastLevelMaxPool', class {});\n        this.registerType('torchvision.ops.feature_pyramid_network.LastLevelP6P7', class {});\n        this.registerType('torchvision.ops.misc.Conv2dNormActivation', class {});\n        this.registerType('torchvision.ops.misc.ConvNormActivation', class {});\n        this.registerType('torchvision.ops.misc.MLP', class extends torch.nn.modules.container.Sequential {});\n        this.registerType('torchvision.ops.misc.ConvTranspose2d', class {});\n        this.registerType('torchvision.ops.misc.FrozenBatchNorm2d', class {});\n        this.registerType('torchvision.ops.misc.Permute', class {});\n        this.registerType('torchvision.ops.misc.SqueezeExcitation', class {});\n        this.registerType('torchvision.ops.poolers.LevelMapper', class {});\n        this.registerType('torchvision.ops.poolers.MultiScaleRoIAlign', class {});\n        this.registerType('torchvision.ops.roi_align.RoIAlign', class {});\n        this.registerType('torchvision.ops.drop_block.DropBlock3d', class {});\n        this.registerType('torchvision.ops.stochastic_depth.StochasticDepth', class {});\n        this.registerType('torchvision.models._api.Weights', class {});\n        this.registerType('torchvision.models.alexnet.AlexNet', class {});\n        this.registerType('torchvision.models.convnext.ConvNeXt', class {});\n        this.registerType('torchvision.models.convnext.CNBlock', class {});\n        this.registerType('torchvision.models.convnext.LayerNorm2d', class {});\n        this.registerType('torchvision.models.densenet.DenseNet', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.models.densenet._DenseBlock', class extends torch.nn.modules.container.ModuleDict {});\n        this.registerType('torchvision.models.densenet._DenseLayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.models.densenet._Transition', class extends torch.nn.modules.container.Sequential {});\n        this.registerType('torchvision.models.detection._utils.BalancedPositiveNegativeSampler', class {});\n        this.registerType('torchvision.models.detection._utils.BoxCoder', class {});\n        this.registerType('torchvision.models.detection._utils.Matcher', class {});\n        this.registerType('torchvision.models.detection._utils.SSDMatcher', class {});\n        this.registerType('torchvision.models.detection.anchor_utils.AnchorGenerator', class {});\n        this.registerType('torchvision.models.detection.anchor_utils.DefaultBoxGenerator', class {});\n        this.registerType('torchvision.models.detection.backbone_utils.BackboneWithFPN', class {});\n        this.registerType('torchvision.models.detection.faster_rcnn.FasterRCNN', class {});\n        this.registerType('torchvision.models.detection.faster_rcnn.FastRCNNConvFCHead', class {});\n        this.registerType('torchvision.models.detection.faster_rcnn.FastRCNNPredictor', class {});\n        this.registerType('torchvision.models.detection.faster_rcnn.TwoMLPHead', class {});\n        this.registerType('torchvision.models.detection.fcos.FCOS', class {});\n        this.registerType('torchvision.models.detection.fcos.FCOSHead', class {});\n        this.registerType('torchvision.models.detection.fcos.FCOSClassificationHead', class {});\n        this.registerType('torchvision.models.detection.fcos.FCOSRegressionHead', class {});\n        this.registerType('torchvision.models.detection._utils.BoxLinearCoder', class {});\n        this.registerType('torchvision.models.detection.keypoint_rcnn.KeypointRCNN', class {});\n        this.registerType('torchvision.models.detection.keypoint_rcnn.KeypointRCNNHeads', class {});\n        this.registerType('torchvision.models.detection.keypoint_rcnn.KeypointRCNNPredictor', class {});\n        this.registerType('torchvision.models.detection.mask_rcnn.MaskRCNN', class {});\n        this.registerType('torchvision.models.detection.mask_rcnn.MaskRCNNHeads', class {});\n        this.registerType('torchvision.models.detection.mask_rcnn.MaskRCNNPredictor', class {});\n        this.registerType('torchvision.models.detection.retinanet.RetinaNet', class {});\n        this.registerType('torchvision.models.detection.retinanet.RetinaNetClassificationHead', class {});\n        this.registerType('torchvision.models.detection.retinanet.RetinaNetHead', class {});\n        this.registerType('torchvision.models.detection.retinanet.RetinaNetRegressionHead', class {});\n        this.registerType('torchvision.models.detection.roi_heads.RoIHeads', class {});\n        this.registerType('torchvision.models.detection.rpn.AnchorGenerator', class {});\n        this.registerType('torchvision.models.detection.rpn.RegionProposalNetwork', class {});\n        this.registerType('torchvision.models.detection.rpn.RPNHead', class {});\n        this.registerType('torchvision.models.detection.ssd.SSD', class {});\n        this.registerType('torchvision.models.detection.ssd.SSDClassificationHead', class {});\n        this.registerType('torchvision.models.detection.ssd.SSDHead', class {});\n        this.registerType('torchvision.models.detection.ssd.SSDFeatureExtractorVGG', class {});\n        this.registerType('torchvision.models.detection.ssd.SSDRegressionHead', class {});\n        this.registerType('torchvision.models.detection.ssdlite.SSDLiteClassificationHead', class {});\n        this.registerType('torchvision.models.detection.ssdlite.SSDLiteFeatureExtractorMobileNet', class {});\n        this.registerType('torchvision.models.detection.ssdlite.SSDLiteHead', class {});\n        this.registerType('torchvision.models.detection.ssdlite.SSDLiteRegressionHead', class {});\n        this.registerType('torchvision.models.detection.transform.GeneralizedRCNNTransform', class {});\n        this.registerType('torchvision.models.efficientnet.EfficientNet', class {});\n        this.registerType('torchvision.models.efficientnet.EfficientNet_B3_Weights', class {});\n        this.registerType('torchvision.models.efficientnet.FusedMBConv', class {});\n        this.registerType('torchvision.models.efficientnet.MBConv', class {});\n        this.registerType('torchvision.models.feature_extraction.LeafModuleAwareTracer', class extends torch.fx._symbolic_trace.Tracer {});\n        this.registerType('torchvision.models.feature_extraction.NodePathTracer', class extends torchvision.models.feature_extraction.LeafModuleAwareTracer {});\n        this.registerType('torchvision.models.googlenet.BasicConv2d', class {});\n        this.registerType('torchvision.models.googlenet.GoogLeNet', class {});\n        this.registerType('torchvision.models.googlenet.Inception', class {});\n        this.registerType('torchvision.models.googlenet.InceptionAux', class {});\n        this.registerType('torchvision.models.inception.BasicConv2d', class {});\n        this.registerType('torchvision.models.inception.Inception3', class {});\n        this.registerType('torchvision.models.inception.InceptionAux', class {});\n        this.registerType('torchvision.models.inception.InceptionA', class {});\n        this.registerType('torchvision.models.inception.InceptionB', class {});\n        this.registerType('torchvision.models.inception.InceptionC', class {});\n        this.registerType('torchvision.models.inception.InceptionD', class {});\n        this.registerType('torchvision.models.inception.InceptionE', class {});\n        this.registerFunction('torchvision.models.inception.inception_v3');\n        this.registerType('torchvision.models.mnasnet._InvertedResidual', class {});\n        this.registerType('torchvision.models.mnasnet.MNASNet', class {});\n        this.registerType('torchvision.models.maxvit.MaxVit', class {});\n        this.registerType('torchvision.models.maxvit.MaxVitBlock', class {});\n        this.registerType('torchvision.models.maxvit.MaxVitLayer', class {});\n        this.registerType('torchvision.models.maxvit.MBConv', class {});\n        this.registerType('torchvision.models.maxvit.PartitionAttentionLayer', class {});\n        this.registerType('torchvision.models.maxvit.RelativePositionalMultiHeadAttention', class {});\n        this.registerType('torchvision.models.maxvit.SwapAxes', class {});\n        this.registerType('torchvision.models.maxvit.WindowDepartition', class {});\n        this.registerType('torchvision.models.mobilenet.ConvBNReLU', class {});\n        this.registerType('torchvision.models.mobilenet.MobileNetV2', class {});\n        this.registerType('torchvision.models.mobilenet.InvertedResidual', class {});\n        this.registerType('torchvision.models.mobilenetv2.ConvBNActivation', class {});\n        this.registerType('torchvision.models.mobilenetv2.InvertedResidual', class {});\n        this.registerType('torchvision.models.mobilenetv2.MobileNetV2', class {});\n        this.registerType('torchvision.models.mobilenetv3.InvertedResidual', class {});\n        this.registerType('torchvision.models.mobilenetv3.MobileNetV3', class {});\n        this.registerType('torchvision.models.mobilenetv3.ConvBNActivation', class {});\n        this.registerType('torchvision.models.mobilenetv3.SqueezeExcitation', class {});\n        this.registerType('torchvision.models.regnet.AnyStage', class extends torch.nn.modules.container.Sequential {});\n        this.registerType('torchvision.models.regnet.BottleneckTransform', class {});\n        this.registerType('torchvision.models.regnet.ResBottleneckBlock', class {});\n        this.registerType('torchvision.models.regnet.RegNet', class {});\n        this.registerType('torchvision.models.regnet.SimpleStemIN', class {});\n        this.registerType('torchvision.models.resnet.Bottleneck', class {});\n        this.registerType('torchvision.models.resnet.BasicBlock', class {});\n        this.registerType('torchvision.models.quantization.mobilenet.QuantizableInvertedResidual', class {});\n        this.registerType('torchvision.models.quantization.mobilenet.QuantizableMobileNetV2', class {});\n        this.registerType('torchvision.models.quantization.mobilenetv2.QuantizableInvertedResidual', class {});\n        this.registerType('torchvision.models.quantization.mobilenetv2.QuantizableMobileNetV2', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableBasicConv2d', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInception3', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInceptionA', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInceptionAux', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInceptionB', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInceptionC', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInceptionD', class {});\n        this.registerType('torchvision.models.quantization.inception.QuantizableInceptionE', class {});\n        this.registerType('torchvision.models.quantization.mobilenetv3.QuantizableMobileNetV3', class {});\n        this.registerType('torchvision.models.quantization.mobilenetv3.QuantizableInvertedResidual', class {});\n        this.registerType('torchvision.models.quantization.mobilenetv3.QuantizableSqueezeExcitation', class {});\n        this.registerType('torchvision.models.quantization.resnet.QuantizableBasicBlock', class {});\n        this.registerType('torchvision.models.quantization.resnet.QuantizableBottleneck', class {});\n        this.registerType('torchvision.models.quantization.resnet.QuantizableResNet', class {});\n        this.registerType('torchvision.models.segmentation.deeplabv3.ASPP', class {});\n        this.registerType('torchvision.models.segmentation.deeplabv3.ASPPConv', class {});\n        this.registerType('torchvision.models.segmentation.deeplabv3.ASPPPooling', class {});\n        this.registerType('torchvision.models.segmentation.deeplabv3.DeepLabHead', class {});\n        this.registerType('torchvision.models.segmentation.deeplabv3.DeepLabV3', class {});\n        this.registerType('torchvision.models.segmentation.fcn.FCN', class {});\n        this.registerType('torchvision.models.segmentation.fcn.FCNHead', class {});\n        this.registerType('torchvision.models.segmentation.lraspp.LRASPP', class {});\n        this.registerType('torchvision.models.segmentation.lraspp.LRASPPHead', class {});\n        this.registerType('torchvision.models.shufflenetv2.ShuffleNetV2', class {});\n        this.registerType('torchvision.models.shufflenetv2.InvertedResidual', class {});\n        this.registerType('torchvision.models.squeezenet.Fire', class {});\n        this.registerType('torchvision.models.squeezenet.SqueezeNet', class {});\n        this.registerType('torchvision.models.swin_transformer.PatchMerging', class {});\n        this.registerType('torchvision.models.swin_transformer.PatchMergingV2', class {});\n        this.registerType('torchvision.models.swin_transformer.ShiftedWindowAttention', class {});\n        this.registerType('torchvision.models.swin_transformer.ShiftedWindowAttentionV2', class {});\n        this.registerType('torchvision.models.swin_transformer.SwinTransformer', class {});\n        this.registerType('torchvision.models.swin_transformer.SwinTransformerBlock', class {});\n        this.registerType('torchvision.models.swin_transformer.SwinTransformerBlockV2', class {});\n        this.registerType('torchvision.models.resnet.ResNet', class {});\n        this.registerType('torchvision.models.vgg.VGG', class {});\n        this.registerType('torchvision.models.video.resnet.BasicBlock', class {});\n        this.registerType('torchvision.models.video.resnet.BasicStem', class {});\n        this.registerType('torchvision.models.video.resnet.Conv2Plus1D', class {});\n        this.registerType('torchvision.models.video.resnet.Conv3DNoTemporal', class {});\n        this.registerType('torchvision.models.video.resnet.Conv3DSimple', class {});\n        this.registerType('torchvision.models.video.resnet.R2Plus1dStem', class {});\n        this.registerType('torchvision.models.video.resnet.VideoResNet', class {});\n        this.registerType('torchvision.models.video.swin_transformer.PatchEmbed3d', class {});\n        this.registerType('torchvision.models.video.swin_transformer.ShiftedWindowAttention3d', class {});\n        this.registerType('torchvision.models.video.swin_transformer.SwinTransformer3d', class {});\n        this.registerType('torchvision.models.vision_transformer.Encoder', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.models.vision_transformer.EncoderBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.models.vision_transformer.MLPBlock', class extends torchvision.ops.misc.MLP {});\n        this.registerType('torchvision.models.vision_transformer.VisionTransformer', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.models._utils.IntermediateLayerGetter', class {});\n        this.registerType('torchvision.transforms._presets.ImageClassification', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.autoaugment.AutoAugment', class {});\n        this.registerType('torchvision.transforms.autoaugment.AutoAugmentPolicy', class {});\n        this.registerType('torchvision.transforms.autoaugment.AugMix', class {});\n        this.registerType('torchvision.transforms.functional.InterpolationMode', class {});\n        this.registerFunction('torchvision.transforms.functional.adjust_brightness');\n        this.registerFunction('torchvision.transforms.functional.adjust_contrast');\n        this.registerFunction('torchvision.transforms.functional.adjust_brightness');\n        this.registerFunction('torchvision.transforms.functional.adjust_contrast');\n        this.registerFunction('torchvision.transforms.functional.adjust_gamma');\n        this.registerFunction('torchvision.transforms.functional.adjust_hue');\n        this.registerFunction('torchvision.transforms.functional.adjust_saturation');\n        this.registerType('torchvision.transforms.transforms.ColorJitter', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.Compose', class {});\n        this.registerType('torchvision.transforms.transforms.ConvertImageDtype', class {});\n        this.registerType('torchvision.transforms.transforms.CenterCrop', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.GaussianBlur', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.Grayscale', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.Lambda', class {});\n        this.registerType('torchvision.transforms.transforms.Normalize', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.PILToTensor', class {});\n        this.registerType('torchvision.transforms.transforms.RandomAffine', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.RandomApply', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.RandomCrop', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.RandomChoice', class {});\n        this.registerType('torchvision.transforms.transforms.RandomErasing', class {});\n        this.registerType('torchvision.transforms.transforms.RandomInvert', class {});\n        this.registerType('torchvision.transforms.transforms.RandomPerspective', class {});\n        this.registerType('torchvision.transforms.transforms.RandomHorizontalFlip', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.RandomVerticalFlip', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.RandomResizedCrop', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.RandomRotation', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.Resize', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.Scale', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.transforms.ToPILImage', class {});\n        this.registerType('torchvision.transforms.transforms.ToTensor', class {});\n        this.registerType('torchvision.transforms.v2._color.ColorJitter', class {});\n        this.registerType('torchvision.transforms.v2._color.Grayscale', class {});\n        this.registerType('torchvision.transforms.v2._color.RandomGrayscale', class {});\n        this.registerType('torchvision.transforms.v2._container.Compose', class {});\n        this.registerType('torchvision.transforms.v2._container.RandomApply', class {});\n        this.registerType('torchvision.transforms.v2._deprecated.ToTensor', class {});\n        this.registerType('torchvision.transforms.v2._meta.ConvertBoundingBoxFormat', class {});\n        this.registerType('torchvision.transforms.v2._misc.ConvertImageDtype', class {});\n        this.registerType('torchvision.transforms.v2._misc.Normalize', class {});\n        this.registerType('torchvision.transforms.v2._misc.ToDtype', class {});\n        this.registerType('torchvision.transforms.v2._geometry.CenterCrop', class {});\n        this.registerType('torchvision.transforms.v2._geometry.Resize', class {});\n        this.registerType('torchvision.transforms.v2._geometry.Pad', class {});\n        this.registerType('torchvision.transforms.v2._geometry.RandomAffine', class {});\n        this.registerType('torchvision.transforms.v2._geometry.RandomCrop', class {});\n        this.registerType('torchvision.transforms.v2._geometry.RandomHorizontalFlip', class {});\n        this.registerType('torchvision.transforms.v2._geometry.RandomRotation', class {});\n        this.registerType('torchvision.transforms.v2._transform.Transform', class extends torch.nn.modules.module.Module {});\n        this.registerType('torchvision.transforms.v2._type_conversion.ToImage', class extends torchvision.transforms.v2._transform.Transform {});\n        this.registerType('torchvision.transforms.v2._type_conversion.PILToTensor', class {});\n        this.registerType('torchvision.tv_tensors._bounding_boxes.BoundingBoxFormat', class {});\n        this.registerFunction('torchvision.models.resnet.resnet18', () => {});\n        this.registerFunction('torchvision.models.resnet.resnet34', () => {});\n        this.registerFunction('torchvision.models.resnet.resnet50', () => {});\n        this.registerFunction('torchvision.models.resnet.resnet101', () => {});\n        this.registerFunction('torchvision.models.resnet.resnet152', () => {});\n        this.registerFunction('torchvision.models.vision_transformer.vit_h_14', () => {});\n        this.registerFunction('torchvision.ops.boxes.box_iou');\n        this.registerFunction('torchvision.ops.focal_loss.sigmoid_focal_loss');\n        this.registerType('ultralytics.models.utils.loss.DETRLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.models.utils.loss.RTDETRDetectionLoss', class {});\n        this.registerType('ultralytics.models.utils.ops.HungarianMatcher', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.Dysample.Dy_Sample', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.jiade.MSCAAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.MSCB.Bottleneck', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.MSCB.C3k', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.MSCB.C3k2_MSCB1', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.MSCB.Conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.MSCB.MSCB', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.MSCB.MSDC', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.ShuffleNetV2.InvertedResidual', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.Addmodules.ShuffleNetV2.ShuffleNetV2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.attention.MSCA.MSCAAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.core11.SPPELAN.Conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.core11.SPPELAN.SP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.core11.SPPELAN.SPPELAN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.DSConv.Bottleneck_DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.DSConv.C2f_DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.DSConv.DSConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.DSConv.DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.EfficientNetv2.DropPath', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.EfficientNetv2.FusedMBConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.EfficientNetv2.MBConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.EfficientNetv2.SqueezeExcite_efficientv2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.EfficientNetv2.stem', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.attention.CascadedGroupAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.attention.Conv2d_BN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.attention.EMA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.attention.LocalWindowAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.attention.SimAM', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.Bottleneck_DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.C2f_DWR_DRB', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.C3k2_DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.CBFuse', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.CBLinear', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.C2f_PKIModule', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.Conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.Cut', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.DRFD2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.DWR_DRB', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.DilatedReparamBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.DySample', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.FGM', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.GSBottleneckC', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.GSConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.PKIModule2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.Silence', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.block.VoVGSCSPC', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.dynamic_snake_conv.DSConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.dynamic_snake_conv.DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.gcconv.Block1x1', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.gcconv.Block3x3', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.gcconv.GCConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.head.DetectAux', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.head.Detect_Efficient', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.jirui_seg.FuseModule', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.mm.router.MultiModalRouter', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.jirui_seg.JiRuiSegHR', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.activation.AGLU', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.A2C2f', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.AAttn', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ABlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.AConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ADown', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.AdaHGComputation', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.AdaHGConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.AdaHyperedgeGen', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.A2_DCNv4_Block', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.A2_DCNv4_SR2G', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Attention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.BasicBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.BNContrastiveHead', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Blocks', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.BlockSplitAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Bottleneck', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.BottleneckCSP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Bottleneck_PConv_Impl', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Bottleneck_Rep', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Bottleneck_ScConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C1', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2f', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2f_G', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2fAttn', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2fCIB', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2fPSA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2f_CA_PConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2f_ScConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2PSA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3AH', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3f', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3Ghost', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3k', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3k2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3k2_v2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3TR', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C3x', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.C2tf', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.CBFuse', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.CBLinear', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.CIB', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Channels', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ContrastiveHead', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ConvNextBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ConvNormLayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Conv_BN_HSwish', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.CoordAtt', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DepthSepConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DFL', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DiffISP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DSBottleneck', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DSC3k', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DSC3k2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.DownsampleConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ECA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ELAN1', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.FullPAD_Tunnel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.FuseModule', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.GhostBottleneck', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.HGBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.HGStem', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.HyperACE', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ImagePoolingAttn', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.LSKblock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.MaxDiffFuse', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.MaxSigmoidAttnBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.MobileNetV3_InvertedResidual', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.MobileNetV3_BLOCK', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ODConv2d_3rd', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ODConv_3rd', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.PConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Proto', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Proto26', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.PSA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.PSABlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RealNVP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepMLP_blockv4', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepNMLPv4', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepBottleneck', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepC3', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepCSP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepNCSPELAN4', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.RepVGGDW', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.Residual', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ResNetBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.ResNetLayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SaELayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SAVPE', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SCDown', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SEBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SeBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SPP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SPPELAN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SPPF', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SR2G_Block', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.SwiGLUFFN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.block.TorchVision', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.CBAM', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.CRU', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.ChannelAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.Concat', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.Conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.Conv2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.ConvTranspose', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.DCN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.DConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.DG_MKP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.DWConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.DWConvTranspose2d', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.DSConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.Focus', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.GhostConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.GroupBatchnorm2d', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.Index', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.LightConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.CoordAtt', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.h_sigmoid', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.h_swish', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.RepConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.SRU', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.ScConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.SpatialAttention', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.conv.mn_conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DAttention.DAttentionBaseline', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DAttention.LayerNormProxy', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DSConv.Bottleneck_DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DSConv.C2f_DSConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DSConv.DSConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DSConv.DySnakeConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.dysample.DySample', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Classify', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.DD_Detect', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Detect', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.DyReLU_B', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.LRPCHead', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.MultiTask', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.OBB', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.OBB26', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Pose', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Pose26', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.RealNVP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Residual', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.RTDETRDecoder', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.SAVPE', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Segment', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.Segment26', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.SwiGLUFFN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.WorldDetect', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.YOLOEDetect', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.YOLOESegment', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.YOLOESegment26', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.head.v10Detect', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.model_ajl.BottleneckCA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.model_ajl.C2fCA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.model_ajl.CA_Block', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.moe.EfficientSpatialRouter', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.moe.OptimizedMOEImproved', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.moe.SimpleExpert', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.moe.experts.SimpleExpert', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.moe.loss.MoELoss', class {});\n        this.registerType('ultralytics.nn.modules.moe.modules.OptimizedMOEImproved', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.moe.routers.EfficientSpatialRouter', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.FDConv_initialversion.FDConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.GGCA.GGCA_Std', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.my_modules.ADown', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.my_modules.Bottleneck_PFDConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.my_modules.C3k2_PFDConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.my_modules.C3k_PFDConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.my_modules.my_modules.Partial_FDConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.new.RepBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.new.RFConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.new.SPDConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.new.StandardConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.AIFI', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.DeformableTransformerDecoder', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.DeformableTransformerDecoderLayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.LayerNorm2d', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.MLP', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.MLPBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.MSDeformAttn', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.TransformerBlock', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.TransformerEncoderLayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.transformer.TransformerLayer', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Bottleneck', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.C2f', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Concat', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Conv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.DFL', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Detect', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Pose', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Proto', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.SPPF', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.Segment', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.CA.CoordAtt', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.CA.h_sigmoid', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.CA.h_swish', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.CoordConv.AddCoords', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.CoordConv.CoordConv', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.ECA.ECA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.GCSA.GCSA', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.MSC.C2f_MSC', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.MSC.EnhancedDWR', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.StarNet.Block', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.StarNet.ConvBN', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.modules.StarNet.StarNet_s', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.Down_WT.Down_wt', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.prune_module.C2f_v2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.extra_modules.prune_module.C3k2_v2', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.PatchExpand.PatchExpand', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.BaseModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.ClassificationModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.DetectionModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.Ensemble', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.FeatureModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.MultiModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.MultiTaskModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.OBBModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.PoseModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.RTDETRDetectionModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.SegmentationModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.SegmentPoseModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.SemanticSegmentationModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.WorldModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.YOLOEModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.YOLOESegModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.nn.tasks.YOLOv10DetectionModel', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.IterableSimpleNamespace', class {});\n        this.registerType('ultralytics.utils.loss.BCEDiceLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.BboxLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.DFLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.E2EDetectLoss', class {});\n        this.registerType('ultralytics.utils.loss.E2ELoss', class {});\n        this.registerType('ultralytics.utils.loss.FocalLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.KeypointLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.MultiChannelDiceLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.PoseLoss26', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.RLELoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.RatioLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.RotatedBboxLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.SlideLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.TVPDetectLoss', class {});\n        this.registerType('ultralytics.utils.loss.TVPSegmentLoss', class {});\n        this.registerType('ultralytics.utils.loss.VarifocalLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.loss.v8ClassificationLoss', class {});\n        this.registerType('ultralytics.utils.loss.v8DetectionLoss', class {});\n        this.registerType('ultralytics.utils.loss.v8OBBLoss', class {});\n        this.registerType('ultralytics.utils.loss.v8PoseLoss', class {});\n        this.registerType('ultralytics.utils.loss.v8SegmentationLoss', class {});\n        this.registerType('ultralytics.utils.loss.v8SegmentPoseLoss', class {});\n        this.registerType('ultralytics.utils.loss.v10DetectLoss', class {});\n        this.registerType('ultralytics.utils.tal.RotatedTaskAlignedAssigner', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.tal.TaskAlignedAssigner', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.utils.torch_utils.EarlyStopping', class {});\n        this.registerType('ultralytics.utils.torch_utils.ModelEMA', class {});\n        this.registerType('ultralytics.yolo.data.augment.CenterCrop', class {});\n        this.registerType('ultralytics.yolo.data.augment.ToTensor', class {});\n        this.registerType('ultralytics.yolo.utils.IterableSimpleNamespace', class {});\n        this.registerType('ultralytics.yolo.utils.loss.BboxLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.yolo.utils.loss.KeypointLoss', class extends torch.nn.modules.module.Module {});\n        this.registerType('ultralytics.yolo.utils.loss.v8ClassificationLoss', class {});\n        this.registerType('ultralytics.yolo.utils.loss.v8DetectionLoss', class {});\n        this.registerType('ultralytics.yolo.utils.loss.v8PoseLoss', class {});\n        this.registerType('ultralytics.yolo.utils.loss.v8SegmentationLoss', class {});\n        this.registerType('ultralytics.yolo.utils.tal.TaskAlignedAssigner', class extends torch.nn.modules.module.Module {});\n        this.registerFunction('builtins.annotate', (type, value) => {\n            if (type === builtins.int) {\n                return Number.isInteger(value) ? value : NaN;\n            }\n            if (type === builtins.float) {\n                return typeof value === 'number' ? value : NaN;\n            }\n            if (type === builtins.number) {\n                // if (pytorch.Utility.isTensor(value)) {\n                //    value.resize_([]);\n                // }\n            }\n            return value;\n        });\n        this.registerFunction('builtins.uninitialized', (/* type */) => {\n            return undefined;\n        });\n        this.registerFunction('builtins.range', (start, stop, step) => {\n            if (stop === undefined && step === undefined) {\n                if (Number.isInteger(start)) {\n                    return Array(start).keys();\n                }\n                if (isNaN(start)) {\n                    return [];\n                }\n            }\n            if (Number.isInteger(start) && Number.isInteger(stop) && (step === undefined || Number.isInteger(step))) {\n                step = step === undefined ? 1 : step;\n                const result = [];\n                if (step > 0) {\n                    for (let i = start; i < stop; i += step) {\n                        result.push(i);\n                    }\n                } else if (step < 0) {\n                    for (let i = start; i > stop; i += step) {\n                        result.push(i);\n                    }\n                }\n                return result;\n            }\n            throw new python.Error(`Unsupported range(${JSON.stringify(start)}, ${JSON.stringify(stop)}, ${JSON.stringify(step)})`);\n        });\n        this.registerFunction('math.trunc');\n        builtins.xrange = builtins.range;\n        this.registerFunction('torch._C._nn.gelu');\n        this.registerFunction('torch._C._nn.avg_pool2d');\n        this.registerFunction('torch._C._nn.avg_pool3d');\n        this.registerFunction('torch._C._nn.scaled_dot_product_attention');\n        this.registerFunction('torch._C._nn.softplus');\n        this.registerFunction('torch._native_multi_head_attention');\n        this.registerFunction('torch._utils._rebuild_sparse_tensor', (layout, data) => {\n            if (layout === torch.sparse_coo) {\n                return self.invoke('torch._sparse_coo_tensor_unsafe', data);\n            }\n            throw new python.Error(`Unsupported sparse tensor layout '${layout ? layout.__str__() : ''}'.`);\n        });\n        this.registerFunction('torch._utils._get_restore_location', (device) => {\n            return device;\n        });\n        this.registerFunction('torch._utils._rebuild_wrapper_subclass', (cls, dtype, size, stride, storage_offset, layout, device, requires_grad) => {\n            device = torch._utils._get_restore_location(device);\n            return torch.Tensor._make_wrapper_subclass(cls, size, stride, dtype, storage_offset, layout, device, requires_grad);\n        });\n        this.registerFunction('torch.from_numpy', (obj) => {\n            const dtypes = new Map([\n                ['<f2', torch.float16],\n                ['<f4', torch.float32],\n                ['<f8', torch.float64],\n                ['<i2', torch.int16],\n                ['<i4', torch.int32],\n                ['<i8', torch.int64],\n            ]);\n            if (!dtypes.has(obj.dtype.str)) {\n                throw new python.Error(`Unsupported numpy.ndarray type '${obj.dtype.str}'.`);\n            }\n            const dtype = dtypes.get(obj.dtype.str);\n            const strides = obj.strides.map((stride) => stride / obj.itemsize);\n            const storage = new torch.storage.TypedStorage(obj.size, dtype);\n            storage._set_cdata(obj.data);\n            const tensor = new torch.Tensor();\n            tensor.__setstate__([storage, 0, obj.shape, strides]);\n            return tensor;\n        });\n        this.registerFunction('torch._utils._rebuild_device_tensor_from_numpy', (data, dtype, device, requires_grad) => {\n            const tensor = torch.from_numpy(data);\n            // tensor = tensor.to(dtype, device)\n            tensor.requires_grad = requires_grad;\n            return tensor;\n        });\n        this.registerFunction('torch._utils._rebuild_device_tensor_from_cpu_tensor', (data, dtype, device, requires_grad) => {\n            data = data.clone();\n            data.requires_grad = requires_grad;\n            return data;\n        });\n        this.registerFunction('torch._sparse_coo_tensor_unsafe', (indices, values, size) => {\n            const tensor = self.invoke('torch.Tensor', []);\n            tensor._layout = torch.sparse_coo;\n            tensor._indices = indices;\n            tensor._values = values;\n            tensor._shape = size;\n            return tensor;\n        });\n        this.registerFunction('torch._utils.set_tensor_metadata', (tensor, metadata) => {\n            torch._C._set_tensor_metadata(tensor, metadata);\n        });\n        this.registerFunction('torch._utils._restore_device_fake_mode', (tensor) => {\n            return tensor;\n        });\n        this.registerFunction('torch._utils._rebuild_meta_tensor_no_storage', (dtype, size, stride, requires_grad) => {\n            return torch.empty_strided(size, stride, dtype, null, 'meta', false, requires_grad);\n        });\n        this.registerFunction('torch._utils._rebuild_tensor', (storage, storage_offset, size, stride) => {\n            if (Array.isArray(storage) && storage.length === 5 && storage[0] === 'storage') {\n                const [, storage_type, , ,size] = storage;\n                storage = new storage_type(size);\n            }\n            const tensor = new torch.Tensor();\n            tensor.__setstate__([storage, storage_offset, size, stride]);\n            return tensor;\n        });\n        this.registerFunction('torch._utils._rebuild_tensor_v2', (storage, storage_offset, size, stride, requires_grad, backward_hooks, metadata) => {\n            const tensor = torch._utils._rebuild_tensor(storage, storage_offset, size, stride);\n            tensor.requires_grad = requires_grad;\n            if (metadata) {\n                torch._utils.set_tensor_metadata(tensor, metadata);\n            }\n            tensor.backward_hooks = backward_hooks;\n            return tensor;\n        });\n        this.registerFunction('torch._utils._rebuild_tensor_v3', (storage, storage_offset, size, stride, requires_grad, backward_hooks, dtype, metadata) => {\n            const t = new torch.Tensor(null, null, dtype);\n            t.set_(storage, storage_offset, size, stride);\n            if (metadata) {\n                torch._utils.set_tensor_metadata(t, metadata);\n            }\n            t._backward_hooks = backward_hooks;\n            return torch._utils._restore_device_fake_mode(t);\n        });\n        this.registerFunction('torch._utils._rebuild_parameter', (data, requires_grad, backward_hooks) => {\n            const param = new torch.nn.parameter.Parameter(data, requires_grad);\n            param.backward_hooks = backward_hooks;\n            return param;\n        });\n        this.registerFunction('torch._utils._rebuild_parameter_v2', (data, requires_grad, backward_hooks, state) => {\n            const param = new torch.nn.parameter.Parameter(data, requires_grad);\n            param.backward_hooks = backward_hooks;\n            torch._utils._set_obj_state(param, state);\n            return param;\n        });\n        this.registerFunction('torch._utils._rebuild_parameter_with_state', (data, requires_grad, backward_hooks, state) => {\n            const _set_obj_state = (obj, state) => {\n                const [dict_state, slots_state] = Array.isArray(state) ? state : [state, null];\n                if (dict_state) {\n                    for (const [k, v] of Object.entries(dict_state)) {\n                        builtins.setattr(obj, k, v);\n                    }\n                }\n                if (slots_state) {\n                    for (const [k, v] of Object.entries(slots_state)) {\n                        builtins.setattr(obj, k, v);\n                    }\n                }\n            };\n            const param = new torch.nn.parameter.Parameter(data, requires_grad);\n            param._backward_hooks = backward_hooks;\n            _set_obj_state(param, state);\n            return param;\n        });\n        this.registerFunction('torch._utils._rebuild_qtensor', (storage, storage_offset, size, stride, quantizer_params, requires_grad, backward_hooks) => {\n            const tensor = torch._utils._rebuild_tensor_v2(storage, storage_offset, size, stride, requires_grad, backward_hooks);\n            tensor.quantizer_params = quantizer_params;\n            return tensor;\n        });\n        this.registerFunction('torch._utils._set_obj_state', (obj, state) => {\n            let dict_state = state;\n            let slots_state = null;\n            if (state instanceof self.builtins.tuple) {\n                if (state.length !== 2) {\n                    throw new python.Error(`Invalid serialized state: '${state}'.`);\n                }\n                [dict_state, slots_state] = state;\n            }\n            if (dict_state) {\n                const entries = dict_state instanceof Map ? dict_state : Object.entries(dict_state);\n                for (const [name, value] of entries) {\n                    builtins.setattr(obj, name, value);\n                }\n            }\n            if (slots_state) {\n                const entries = slots_state instanceof Map ? slots_state : Object.entries(slots_state);\n                for (const [name, value] of entries) {\n                    builtins.setattr(obj, name, value);\n                }\n            }\n            return obj;\n        });\n        this.registerFunction('torch._set_item', (dict, key, value) => {\n            dict[key] = value;\n        });\n        this.registerFunction('torch._tensor._rebuild_from_type_v2', (func, new_type, args, state) => {\n            let ret = func(...args);\n            if (ret.__class__ !== new_type) {\n                ret.__class__ = new_type;\n            }\n            const setstate = builtins.getattr(ret.__class__, '__setstate__', torch.Tensor.__setstate__);\n            if (setstate === torch.Tensor.__setstate__) {\n                ret = torch._utils._set_obj_state(ret, state);\n            } else {\n                ret.__setstate__(state);\n            }\n            return ret;\n        });\n        this.registerFunction('torch.__range_length', (lo, hi, step) => {\n            if (step === 0) {\n                throw new python.Error('range() arg 3 must not be zero');\n            }\n            if (step > 0 && lo < hi) {\n                return 1 + (hi - 1 - lo) / step;\n            } else if (step < 0 && lo > hi) {\n                return 1 + (lo - 1 - hi) / (0 - step);\n            }\n            return 0;\n        });\n        this.registerFunction('torch._nested_tensor_from_mask_left_aligned');\n        this.registerOperator('aten::_unwrap_optional', (value) => {\n            return value;\n        });\n        this.registerFunction('torch.get_default_dtype', () => {\n            torch._default_type = torch._default_type || torch.float32;\n            return torch._default_type;\n        });\n        this.registerFunction('torch.set_default_dtype', (value) => {\n            torch._default_type = value;\n        });\n        this.registerFunction('torch._prims_common.dtype_or_default', (value) => {\n            return value || torch.get_default_dtype();\n        });\n        this.registerFunction('torch.empty_strided', (size, stride, dtype, layout, device, pin_memory, requires_grad) => {\n            const shape = size;\n            dtype = torch._prims_common.dtype_or_default(dtype);\n            let storage = null;\n            if (size.every((d) => d instanceof torch.SymInt === false)) {\n                const size = shape.reduce((a, b) => a * b, 1);\n                storage = new torch.storage.TypedStorage(size, dtype);\n            }\n            const tensor = new torch.Tensor(storage, shape, dtype, layout, device, requires_grad);\n            tensor.__setstate__([storage, 0, shape, stride]);\n            return tensor;\n        });\n        this.registerFunction('torch.all', (input) => {\n            if (Array.isArray(input) && input.length === 0) {\n                return true;\n            }\n            throw new python.Error(`Unsupported 'torch.all' expression type.`);\n        });\n        this.registerFunction('torch.append', (list, value) => {\n            list.push(value);\n            return value;\n        });\n        this.registerFunction('torch.clear', (value) => {\n            if (value instanceof torch.Value) {\n                throw new python.Error('Invalid value.');\n            }\n            if (Object(value) === value) {\n                for (const key of Object.keys(value)) {\n                    delete value[key];\n                }\n            }\n        });\n        this.registerFunction('torch.dict', (args) => {\n            const obj = {};\n            if (args) {\n                if (Array.isArray(args)) {\n                    for (const [key, value] of args) {\n                        obj[key] = value;\n                    }\n                } else {\n                    throw new python.Error(\"'torch.dict' arguments not supported.\");\n                }\n            }\n            return obj;\n        });\n        this.registerOperator('aten::cosine_similarity', () => {\n            throw new python.Error(`'aten::cosine_similarity' not implemented.`);\n        });\n        this.registerOperator('aten::extend', (list, value) => {\n            list.push(...value);\n        });\n        this.registerOperator('aten::insert', (list, index, value) => {\n            list.splice(index, 0, value);\n            return value;\n        });\n        this.registerOperator('aten::replace', (value, oldvalue, newvalue /*, max */) => {\n            return value.replace(oldvalue, newvalue);\n        });\n        this.registerOperator('aten::add', (a, b) => {\n            if ((typeof a === 'number' || a instanceof Number) && (typeof b === 'number' || b instanceof Number)) {\n                return a + b;\n            }\n            if (typeof a === 'number' && b instanceof builtins.complex) {\n                return new builtins.complex(a + b.real, b.imag);\n            }\n            if (a instanceof builtins.complex && typeof b === 'number') {\n                return new builtins.complex(a.real + b, a.imag);\n            }\n            if (a instanceof builtins.complex && b instanceof builtins.complex) {\n                return new builtins.complex(a.real + b.real, a.imag + b.imag);\n            }\n            if (Array.isArray(a) && Array.isArray(b)) {\n                return a.concat(b);\n            }\n            if (typeof a === 'string' && typeof b === 'string') {\n                return a + b;\n            }\n            throw new python.Error('Unsupported aten::add expression type.');\n        });\n        this.registerOperator('aten::log', (x) => {\n            if (typeof x === 'number' || x instanceof Number) {\n                return Math.log(x);\n            }\n            throw new python.Error('Unsupported aten::log expression type.');\n        });\n        this.registerOperator('aten::dim', (tensor) => {\n            if (tensor && tensor.size) {\n                const size = tensor.size();\n                if (size) {\n                    return size.length;\n                }\n            }\n            return NaN;\n        });\n        this.registerOperator('aten::numel', (tensor) => {\n            if (tensor && tensor.size) {\n                const size = tensor.size();\n                if (size) {\n                    return size.reduce((a, b) => a * b, 1);\n                }\n            }\n            return NaN;\n        });\n        this.registerOperator('aten::eq', (left, right) => {\n            if (typeof left === 'string' && typeof right === 'string') {\n                return left === right;\n            }\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                if (isNaN(left) && isNaN(right)) {\n                    return true;\n                }\n                return left === right;\n            }\n            if (left === undefined || right === undefined) {\n                return true;\n            }\n            if (Array.isArray(left) && Array.isArray(right)) {\n                return left.length === right.length && left.every((item, index) => item === right[index]);\n            }\n            throw new python.Error(\"Unsupported 'torch.eq' expression type.\");\n        });\n        this.registerOperator('aten::floor', (value) => {\n            return Math.floor(value);\n        });\n        this.registerOperator('aten::ceil', (value) => {\n            return Math.ceil(value);\n        });\n        this.registerOperator('aten::floordiv', (left, right) => {\n            return Math.floor(left / right);\n        });\n        this.registerOperator('aten::format', (...args) => {\n            const list = args.shift().split(/({}D?)/);\n            return list.map((text) => {\n                if (text === '{}' || text === '{}D') {\n                    const arg = args.shift();\n                    if (Array.isArray(arg)) {\n                        return `[${arg.map((item) => item.toString()).join(', ')}]`;\n                    }\n                    return arg ? arg.toString() : '?';\n                }\n                return text;\n            }).join('');\n        });\n        this.registerOperator('aten::strip', (self, chars) => {\n            chars = chars || '\\\\n\\\\t\\\\f\\\\v';\n            const regex = new RegExp(`[${chars}]`, 'g');\n            return self.replace(regex, '');\n        });\n        this.registerOperator('aten::gt', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                if (!isNaN(left) && !isNaN(right)) {\n                    return left > right;\n                }\n            }\n            if (isNaN(left) && !isNaN(right)) {\n                return true;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.gt' expression type.\");\n        });\n        this.registerOperator('aten::ge', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                if (!isNaN(left) && !isNaN(right)) {\n                    return left > right;\n                }\n            }\n            if (isNaN(left) && !isNaN(right)) {\n                return true;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.ge' expression type.\");\n        });\n        this.registerOperator('aten::is_floating_point', (tensor) => {\n            const type = tensor.dtype.scalar_type();\n            return (type === 5 || type === 6 || type === 7);\n        });\n        this.registerOperator('aten::is_grad_enabled', () => {\n            return false;\n        });\n        this.registerOperator('aten::is_autocast_enabled', () => {\n            return false;\n        });\n        this.registerOperator('aten::isfinite');\n        this.registerOperator('aten::set_grad_enabled', (/* value */) => {\n        });\n        this.registerFunction('torch.serialization._get_layout', (name) => {\n            const value = name.startsWith('torch.') ? torch[name.split('.')[1]] : null;\n            return value instanceof torch.layout ? value : null;\n        });\n        this.registerFunction('torch.storage._load_from_bytes', (b) => {\n            return torch.load(b);\n        });\n        this.registerFunction('torch.jit._pickle.build_boollist', (data) => {\n            return data;\n        });\n        this.registerFunction('torch.jit._pickle.build_doublelist', (data) => {\n            return data;\n        });\n        this.registerFunction('torch.jit._pickle.build_intlist', (data) => {\n            return data;\n        });\n        this.registerFunction('torch.jit._pickle.build_tensorlist', (data) => {\n            return data;\n        });\n        this.registerFunction('torch.jit._pickle.build_tensor_from_id', (data) => {\n            return self.builtins.CONSTANTS[`c${data}`];\n        });\n        this.registerFunction('torch.jit._pickle.restore_type_tag', (value /*, type_str */) => {\n            return value;\n        });\n        this.registerOperator('aten::keys', (dict) => {\n            return Object.keys(dict);\n        });\n        this.registerOperator('aten::len', (value) => {\n            if (Array.isArray(value)) {\n                return value.length;\n            }\n            if (value && value.shape && value.__len__) {\n                return value.__len__();\n            }\n            return NaN;\n        });\n        this.registerOperator('aten::le', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                if (isNaN(left) || isNaN(right)) {\n                    return false;\n                }\n                return left <= right;\n            }\n            if (left === undefined || right === undefined) {\n                return true;\n            }\n            throw new python.Error(\"Unsupported 'torch.le' expression type.\");\n        });\n        this.registerOperator('aten::list', (args) => {\n            return args;\n        });\n        this.registerOperator('aten::list_with_default', (size /*, defaults */) => {\n            return size;\n        });\n        this.registerType('torch.PyTorchFileReader', class {\n            constructor(entries) {\n                let prefix = 0;\n                const paths = Array.from(entries.keys()).map((path) => path.replace(/\\\\/g, '/').split('/').reverse());\n                for (let set = new Set(); set && paths.length > 0;) {\n                    set = new Set(paths.map((path) => path.length > 1 ? path.pop() : null));\n                    set = set.size > 1 || set.keys().next().value === null ? null : set;\n                    prefix += set ? set.keys().next().value.length + 1 : 0;\n                }\n                this._records = new Map(Array.from(entries).map(([name, value]) => [name.substring(prefix), value]));\n                this._version = 0;\n                this.init();\n            }\n            init() {\n                let stream = null;\n                if (this.has_record('.data/version')) {\n                    stream = this.get_record('.data/version');\n                } else if (this.has_record('version')) {\n                    stream = this.get_record('version');\n                }\n                if (stream) {\n                    const decoder = new TextDecoder('utf-8');\n                    const buffer = stream.peek();\n                    const text = decoder.decode(buffer);\n                    this._version = Number(text.split('\\n').shift().trim());\n                }\n            }\n            has_record(name) {\n                return this._records.has(name);\n            }\n            get_record(name) {\n                if (!this.has_record(name)) {\n                    throw new python.Error(`Record '${name}' not found.`);\n                }\n                return this._records.get(name);\n            }\n            get_all_records() {\n                return Array.from(this._records.keys());\n            }\n            version() {\n                return this._version;\n            }\n        });\n        this.registerFunction('torch.load', (f) => {\n            const legacy_load = (entries) => {\n                const deserialized_objects = {};\n                if (entries.has('storages')) {\n                    const data = entries.get('storages');\n                    const unpickler = new pickle.Unpickler(data);\n                    const num_storages = unpickler.load();\n                    for (let i = 0; i < num_storages; i++) {\n                        const args = unpickler.load();\n                        const [key, , storage_type] = args;\n                        const obj = storage_type._new_with_file(unpickler);\n                        deserialized_objects[key] = obj;\n                    }\n                    /*\n                    let storage_views = unpickler.load();\n                    for target_cdata, root_cdata, offset, size in storage_views:\n                        root = deserialized_objects[root_cdata]\n                        deserialized_objects[target_cdata] = root[offset:offset + size]\n                    */\n                }\n                if (entries.has('tensors')) {\n                    const data = entries.get('tensors');\n                    const unpickler = new pickle.Unpickler(data);\n                    const num_tensors = unpickler.load();\n                    const int32 = (unpickler) => {\n                        const buffer = unpickler.read(4);\n                        return buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24);\n                    };\n                    const int64 = (unpickler) => {\n                        const buffer = unpickler.read(8);\n                        if (buffer[6] !== 0 && buffer[7] !== 0) {\n                            throw new python.Error('Unsigned 64-bit value exceeds 32-bit range.');\n                        }\n                        return buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24) + (buffer[4] * 4294967296) + (buffer[5] * 1099511627776);\n                    };\n                    for (let i = 0; i < num_tensors; i++) {\n                        const args = unpickler.load();\n                        const [key, storage_id] = args;\n                        const storage = deserialized_objects[storage_id];\n                        const ndim = int32(unpickler);\n                        unpickler.read(4);\n                        const shape = Array.from(new Array(ndim)).map(() => int64(unpickler));\n                        const stride = Array.from(new Array(ndim)).map(() => int64(unpickler));\n                        const storage_offset = int64(unpickler);\n                        const tensor = torch._utils._rebuild_tensor(storage, storage_offset, shape, stride);\n                        deserialized_objects[key] = tensor;\n                    }\n                }\n                const data = entries.get('pickle');\n                const unpickler = new pickle.Unpickler(data);\n                unpickler.persistent_load = (saved_id) => deserialized_objects[saved_id];\n                return unpickler.load();\n            };\n            const _legacy_load = () => {\n                const unpickler = new pickle.Unpickler(f);\n                unpickler.load(); // magic_number\n                const protocol_version = unpickler.load();\n                if (protocol_version !== 1001) {\n                    throw new python.Error(`Unsupported protocol version '${protocol_version}'.`);\n                }\n                const sys_info = unpickler.load();\n                if (sys_info.get('protocol_version') !== 1001) {\n                    throw new python.Error(`Unsupported protocol version '${sys_info.protocol_version}'.`);\n                }\n                if (sys_info.get('little_endian') === false) {\n                    throw new python.Error(\"Unsupported big-endian storage data.\");\n                }\n                const module_source_map = new Map();\n                const deserialized_objects = new Map();\n                unpickler.persistent_load = (saved_id) => {\n                    switch (saved_id[0]) {\n                        case 'module': {\n                            const [, module, ,source] = saved_id;\n                            module_source_map.set(module, source);\n                            return saved_id[1];\n                        }\n                        case 'storage': {\n                            const [, storage_type, key, , size, view_metadata] = saved_id;\n                            if (!deserialized_objects.has(key)) {\n                                const obj = new storage_type(size);\n                                deserialized_objects.set(key, obj);\n                            }\n                            if (view_metadata) {\n                                const view_key = view_metadata.shift();\n                                view_metadata.shift(); // view_offset\n                                view_metadata.shift(); // view_size\n                                if (!deserialized_objects.has(view_key)) {\n                                    const view = null; // storage.slice(view_offset, view_offset + view_size);\n                                    deserialized_objects.set(view_key, view);\n                                }\n                                return deserialized_objects.get(view_key);\n                            }\n                            return deserialized_objects.get(key);\n                        }\n                        default: {\n                            throw new python.Error(`Unsupported persistent load type '${saved_id[0]}'.`);\n                        }\n                    }\n                };\n                const obj = unpickler.load();\n                const deserialized_storage_keys = unpickler.load();\n                for (const deserialized_storage_key of deserialized_storage_keys) {\n                    const storage = deserialized_objects.get(deserialized_storage_key);\n                    storage._set_from_file(unpickler);\n                }\n                if (!obj) {\n                    throw new python.Error('File format is not PyTorch.');\n                }\n                if (obj === 'None') {\n                    throw new python.Error(\"File contains 'None' root object.\");\n                }\n                return obj;\n            };\n            const _load = (entries) => {\n                if (f.has('constant.pkl')) {\n                    throw python.Error(\"TorchScript 'torch.load' not supported.\");\n                }\n                const loaded_storages = new Map();\n                const persistent_load = (saved_id) => {\n                    switch (saved_id[0]) {\n                        case 'storage': {\n                            const [, storage_type, key, , numel] = saved_id;\n                            if (!loaded_storages.has(key)) {\n                                const storage = new storage_type(numel);\n                                if (!storage._set_cdata) {\n                                    throw new python.Error(`'${storage_type.__name__}._set_cdata' is not a function.`);\n                                }\n                                const name = `data/${key}`;\n                                const stream = entries.get(name);\n                                if (!stream) {\n                                    throw new python.Error(`Record '${name}' not found.`);\n                                }\n                                storage._set_cdata(stream);\n                                loaded_storages.set(key, storage);\n                            }\n                            return loaded_storages.get(key);\n                        }\n                        default: {\n                            throw new python.Error(`Unsupported persistent load type '${saved_id[0]}'.`);\n                        }\n                    }\n                };\n                const data_file = entries.get('data.pkl');\n                const unpickler = new pickle.Unpickler(data_file);\n                unpickler.persistent_load = persistent_load;\n                const result = unpickler.load();\n                return result;\n            };\n            if (f instanceof Map) {\n                const reader = new torch.PyTorchFileReader(f);\n                const records = reader.get_all_records().map((name) => [name, reader.get_record(name)]);\n                f = new Map(records);\n                if (f.has('pickle')) {\n                    return legacy_load(f);\n                }\n                if (f.has('data.pkl')) {\n                    return _load(f);\n                }\n                throw new python.Error(`Unsupported 'torch.load' input '${JSON.stringify(Array.from(f.keys()))}'.`);\n            }\n            return _legacy_load(f);\n        });\n        this.registerOperator('prim::abs', (a) => {\n            if (typeof a === 'number' || a instanceof Number) {\n                return Math.abs(a);\n            }\n            if (a instanceof builtins.complex) {\n                return Math.hypot(a.real, a.imag);\n            }\n            throw new python.Error('Unsupported prim::abs expression type.');\n        });\n        this.registerOperator('prim::unchecked_cast', (type, value) => {\n            return value;\n        });\n        this.registerOperator('prim::data', (tensor) => {\n            return tensor;\n        });\n        this.registerOperator('prim::device', (tensor) => {\n            return tensor.device;\n        });\n        this.registerOperator('prim::dtype', (tensor) => {\n            return tensor.dtype.scalar_type();\n        });\n        this.registerOperator('prim::is_quantized', (tensor) => {\n            return tensor.is_quantized;\n        });\n        this.registerOperator('prim::is_cuda', (/* tensor */) => {\n            return false;\n        });\n        this.registerOperator('prim::is_nested', (tensor) => {\n            return tensor.is_nested;\n        });\n        this.registerOperator('prim::is_sparse', (tensor) => {\n            return tensor.is_sparse;\n        });\n        this.registerOperator('prim::unchecked_unwrap_optional', (value) => {\n            return value;\n        });\n        this.registerOperator('prim::NumToTensor', (value) => {\n            const tensor = self.invoke('torch.Tensor', []);\n            tensor.value = value;\n            return tensor;\n        });\n        this.registerOperator('prim::min', (...args) => {\n            if (Array.isArray(args[0])) {\n                return Math.min.apply(null, args[0]);\n            }\n            return Math.min.apply(null, args);\n        });\n        this.registerOperator('prim::max', (...args) => {\n            if (Array.isArray(args[0])) {\n                return Math.max.apply(null, args[0]);\n            }\n            return Math.max.apply(null, args);\n        });\n        this.registerOperator('prim::shape', (tensor) => {\n            return tensor && tensor.size ? tensor.size() : undefined;\n        });\n        this.registerOperator('quantized::conv_prepack', (weight, bias, stride, padding, dilation, groups) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.Conv2dPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            params.stride = stride;\n            params.padding = padding;\n            params.dilation = dilation;\n            params.groups = groups;\n            return params;\n        });\n        this.registerOperator('quantized::conv1d_prepack', (weight, bias, stride, padding, dilation, groups) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.Conv2dPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            params.stride = stride;\n            params.padding = padding;\n            params.dilation = dilation;\n            params.groups = groups;\n            return params;\n        });\n        this.registerOperator('quantized::conv2d_prepack', (weight, bias, stride, padding, dilation, groups) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.Conv2dPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            params.stride = stride;\n            params.padding = padding;\n            params.dilation = dilation;\n            params.groups = groups;\n            return params;\n        });\n        this.registerOperator('quantized::conv3d_prepack', (weight, bias, stride, padding, dilation, groups) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.Conv3dPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            params.stride = stride;\n            params.padding = padding;\n            params.dilation = dilation;\n            params.groups = groups;\n            return params;\n        });\n        this.registerOperator('quantized::conv_transpose1d_prepack', (weight, bias, stride, padding, output_padding, dilation, groups) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.Conv2dPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            params.stride = stride;\n            params.padding = padding;\n            params.output_padding = output_padding;\n            params.dilation = dilation;\n            params.groups = groups;\n            return params;\n        });\n        this.registerOperator('quantized::conv_transpose2d_prepack', (weight, bias, stride, padding, output_padding, dilation, groups) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.Conv2dPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            params.stride = stride;\n            params.padding = padding;\n            params.output_padding = output_padding;\n            params.dilation = dilation;\n            params.groups = groups;\n            return params;\n        });\n        this.registerOperator('quantized::linear_prepack', (weight, bias) => {\n            const params = self.invoke('__torch__.torch.classes.quantized.LinearPackedParamsBase', []);\n            params.weight = weight;\n            params.bias = bias;\n            return params;\n        });\n        this.registerOperator('prim::RaiseException', (message) => {\n            throw new python.Error(message);\n        });\n        this.registerOperator('prim::TupleIndex', (t, i) => {\n            return t.elements()[i];\n        });\n        this.registerOperator('prim::TupleUnpack', (t) => {\n            return t.elements();\n        });\n        this.registerOperator('aten::is_scripting', () => {\n            return true;\n        });\n        this.registerOperator('aten::__and__', (left, right) => {\n            return left && right;\n        });\n        this.registerOperator('aten::__contains__', (dict, key) => {\n            return builtins.hasattr(dict, key);\n        });\n        this.registerFunction('torch.__derive_index', (index, start, step) => {\n            return start + index * step;\n        });\n        this.registerOperator('aten::__is__', (left, right) => {\n            return left === right;\n        });\n        this.registerOperator('aten::__isnot__', (left, right) => {\n            return left !== right;\n        });\n        this.registerOperator('aten::__not__', (value) => {\n            if (Number.isInteger(value)) {\n                value = Boolean(value);\n            }\n            if (typeof value === 'boolean') {\n                return !value;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.__not__' expression type.\");\n        });\n        this.registerOperator('aten::log10', (value) => {\n            return Math.log10(value);\n        });\n        this.registerOperator('aten::device', (type, index) => {\n            return new torch.device(type, index);\n        });\n        this.registerOperator('aten::lt', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return left < right;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.lt' expression type.\");\n        });\n        this.registerOperator('aten::mul', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return left * right;\n            }\n            if (isNaN(left) || isNaN(right)) {\n                return NaN;\n            }\n            if (Array.isArray(left) && left.every((value) => typeof value === 'number' || value instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return left.map((value) => value * right);\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.mul' expression type.\");\n        });\n        this.registerOperator('aten::div', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return left / right;\n            }\n            if (isNaN(left) || isNaN(right)) {\n                return NaN;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.div' expression type.\");\n        });\n        this.registerFunction('torch.round', (value) => {\n            if (typeof value === 'number' || value instanceof Number) {\n                return Math.round(value);\n            }\n            if (isNaN(value)) {\n                return value;\n            }\n            throw new python.Error(\"Unsupported 'torch.round' expression type.\");\n        });\n        this.registerOperator('aten::remainder', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return left % right;\n            }\n            if (isNaN(left) || isNaN(right)) {\n                return NaN;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.remainder' expression type.\");\n        });\n        this.registerOperator('aten::ne', (left, right) => {\n            if (typeof left === 'boolean' && typeof right === 'boolean') {\n                return left !== right;\n            }\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                if (isNaN(left) || isNaN(right)) {\n                    return false;\n                }\n                return left !== right;\n            }\n            if (Array.isArray(left) && Array.isArray(right) && left.length === right.length) {\n                return false;\n            }\n            if (typeof left === 'string' && typeof right === 'string') {\n                return left !== right;\n            }\n            if (left === undefined || right === undefined) {\n                return true;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.ne' expression type.\");\n        });\n        this.registerOperator('aten::neg', (value) => {\n            if (typeof value === 'number') {\n                return -value;\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.neg' expression type.\");\n        });\n        this.registerOperator('aten::pow', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return Math.pow(left, right);\n            }\n            throw new python.Error(\"Unsupported 'ops.aten.pow' expression type.\");\n        });\n        this.registerFunction('torch.q_scale', (/* tensor */) => {\n            return -1;\n        });\n        this.registerFunction('torch.t', (tensor) => {\n            return tensor;\n        });\n        this.registerOperator('aten::size', (tensor, dim) => {\n            if (tensor && tensor.size) {\n                const size = tensor.size();\n                if (Array.isArray(size)) {\n                    if (dim === undefined) {\n                        return size;\n                    }\n                    if (Number.isInteger(dim)) {\n                        if (dim >= 0 && dim < size.length) {\n                            return size[dim];\n                        }\n                        if (dim < 0 && -dim < size.length) {\n                            return size[size.length + dim];\n                        }\n                    }\n                    throw new python.Error(`Dimension out of range (expected to be in range of ${JSON.stringify(size)}, but got ${JSON.stringify(dim)}).`);\n                }\n            }\n            if (Number.isInteger(dim)) {\n                return NaN;\n            }\n            return [];\n        });\n        this.registerFunction('aten::sqrt', (x) => {\n            return Math.sqrt(x);\n        });\n        this.registerOperator('aten::slice', (l, start, end, step) => {\n            if (!Array.isArray(l)) {\n                throw new python.Error('Slicing expected array');\n            }\n            step = step || 1;\n            if (step !== 1) {\n                throw new python.Error('Slicing only supports step=1');\n            }\n            start = Math.max(0, start >= 0 ? start : l.length + start);\n            end = Math.min(l.length, end || Number.MAX_SAFE_INTEGER);\n            return l.slice(start, end);\n        });\n        this.registerOperator('aten::sub', (left, right) => {\n            if ((typeof left === 'number' || left instanceof Number) && (typeof right === 'number' || right instanceof Number)) {\n                return left - right;\n            }\n            if (typeof left === 'number' && right instanceof builtins.complex) {\n                return new builtins.complex(left - right.real, right.imag);\n            }\n            if (left instanceof builtins.complex && typeof right === 'number') {\n                return new builtins.complex(left.real - right, left.imag);\n            }\n            if (left instanceof builtins.complex && right instanceof builtins.complex) {\n                return new builtins.complex(left.real - right.real, left.imag - right.imag);\n            }\n            throw new python.Error(\"Unsupported 'torch.sub' expression type.\");\n        });\n        this.registerFunction('torch.sym_int');\n        this.registerFunction('torch.sym_float');\n        this.registerFunction('torch.sym_ite');\n        this.registerFunction('torch.sym_max');\n        this.registerFunction('torch.sym_min');\n        this.registerFunction('torch.sym_not');\n        this.registerFunction('torch.sym_sqrt');\n        this.registerFunction('torch.sym_sqrt');\n        this.registerFunction('torch.functional.einsum');\n        this.registerFunction('torch.functional.norm');\n        this.registerFunction('torch.functional.split');\n        this.registerFunction('torch.nn.init.constant_');\n        this.registerFunction('torch.nn.init.normal_');\n        this.registerFunction('torch.nn.init.xavier_uniform_');\n        this.registerFunction('torch.nn.functional.adaptive_avg_pool2d');\n        this.registerFunction('torch.nn.functional.binary_cross_entropy');\n        this.registerFunction('torch.nn.functional.binary_cross_entropy_with_logits');\n        this.registerFunction('torch.nn.functional.cross_entropy');\n        this.registerFunction('torch.nn.functional.elu');\n        this.registerFunction('torch.nn.functional.gelu');\n        this.registerFunction('torch.nn.functional.hardsigmoid');\n        this.registerFunction('torch.nn.functional.hardswish');\n        this.registerFunction('torch.nn.functional.hardtanh');\n        this.registerFunction('torch.nn.functional.huber_loss');\n        this.registerFunction('torch.nn.functional.interpolate');\n        this.registerFunction('torch.nn.functional.leaky_relu');\n        this.registerFunction('torch.nn.functional.l1_loss');\n        this.registerFunction('torch.nn.functional.linear');\n        this.registerFunction('torch.nn.functional.log_softmax');\n        this.registerFunction('torch.nn.functional._max_pool2d');\n        this.registerFunction('torch.nn.functional.max_pool2d_with_indices');\n        this.registerFunction('torch.nn.functional.mse_loss');\n        this.registerFunction('torch.nn.functional.pad');\n        this.registerFunction('torch.nn.functional.relu');\n        this.registerFunction('torch.nn.functional.relu6');\n        this.registerFunction('torch.nn.functional.sigmoid');\n        this.registerFunction('torch.nn.functional.silu');\n        this.registerFunction('torch.nn.functional.softmax');\n        this.registerFunction('torch.nn.functional.tanh');\n        this.registerFunction('torch.values', (dict) => {\n            return Object.values(dict);\n        });\n        this.registerFunction('torch.warn', () => {\n        });\n        this.registerType('torch._ops.OperatorBase', class {\n            constructor() {\n                this.functorch_table = {};\n            }\n        });\n        this.registerType('torch._ops.HigherOrderOperator', class extends torch._ops.OperatorBase {\n            constructor(name, cacheable) {\n                super();\n                this._name = name;\n                this.__name__ = name;\n                this._ns = 'higher_order';\n                this.__module__ = 'torch.ops.higher_order';\n                this._cacheable = cacheable;\n            }\n            get namespace() {\n                return this._ns;\n            }\n            get name() {\n                return this._name;\n            }\n        });\n        this.registerType('torch._higher_order_ops.wrap.WrapWithAutocast', class extends torch._ops.HigherOrderOperator {\n            constructor(name) {\n                super(name, false);\n                this._schema = torch.FunctionSchema.parse('higher_order::wrap_with_autocast(str device_type, ScalarType? dtype, bool enabled, bool? cache_enabled, Any wrapped_func, ...) -> Tensor');\n            }\n        });\n        torch.ops.higher_order.wrap_with_autocast = new torch._higher_order_ops.wrap.WrapWithAutocast('wrap_with_autocast');\n        this.registerType('torch._higher_order_ops.wrap.WrapWithSetGradEnabled', class extends torch._ops.HigherOrderOperator {\n            constructor(name) {\n                super(name, false);\n                this._schema = torch.FunctionSchema.parse('higher_order::wrap_with_set_grad_enabled(bool enable_grad, Any wrapped_func, ...) -> Tensor');\n            }\n        });\n        torch.ops.higher_order.wrap_with_set_grad_enabled = new torch._higher_order_ops.wrap.WrapWithSetGradEnabled('wrap_with_set_grad_enabled');\n        this.registerType('torch._higher_order_ops.wrap.Wrap', class extends torch._ops.HigherOrderOperator {\n            constructor(name) {\n                super(name, false);\n                this._schema = torch.FunctionSchema.parse('higher_order::wrap(Any func, ...) -> Tensor');\n            }\n        });\n        torch.ops.higher_order.wrap = new torch._higher_order_ops.wrap.Wrap('wrap');\n        this.registerType('torch._higher_order_ops.wrap.WrapActivationCheckpoint', class extends torch._ops.HigherOrderOperator {\n            constructor(name) {\n                super(name, false);\n            }\n        });\n        torch.ops.higher_order.wrap_activation_checkpoint = new torch._higher_order_ops.wrap.WrapActivationCheckpoint('wrap_activation_checkpoint', false);\n        this.registerType('torch._higher_order_ops.wrap.TagActivationCheckpoint', class extends torch._ops.HigherOrderOperator {\n            constructor(name) {\n                super(name, false);\n            }\n        });\n        torch.ops.higher_order.tag_activation_checkpoint = new torch._higher_order_ops.wrap.TagActivationCheckpoint('tag_activation_checkpoint', false);\n        this.registerType('torch.Type', class {\n            constructor(kind, annotation_str) {\n                this._kind = kind;\n                if (annotation_str) {\n                    this._annotation_str = annotation_str;\n                }\n            }\n            static get(kind, annotation_str) {\n                torch.Type.cache = torch.Type.cache || new Map();\n                if (!annotation_str) {\n                    if (!torch.Type.cache.has(kind)) {\n                        torch.Type.cache.set(kind, new torch.Type(kind));\n                    }\n                    return torch.Type.cache.get(kind);\n                }\n                return new torch.Type(kind, annotation_str);\n            }\n            kind() {\n                return this._kind;\n            }\n            get annotation_str() {\n                return this._annotation_str;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            isSubtypeOf(rhs) {\n                if (rhs.kind() === 'AnyType' || this === rhs) {\n                    return true;\n                }\n                if (rhs instanceof torch.OptionalType && this instanceof torch.OptionalType === false) {\n                    return this.isSubtypeOf(rhs.getElementType());\n                }\n                if (rhs instanceof torch.UnionType) {\n                    return rhs.containedTypes().some((inner) => this.isSubtypeOf(inner));\n                }\n                if (rhs instanceof torch._C.DynamicType) {\n                    return torch._C.DynamicType.create(this).isSubtypeOf(rhs);\n                }\n                return this.equals(rhs);\n            }\n            containedTypes() {\n                return [];\n            }\n            containedType(i) {\n                return this.containedTypes()[i];\n            }\n            withContained(contained_types) {\n                const current_contained = this.containedTypes();\n                torch._C.TORCH_INTERNAL_ASSERT(current_contained.length > 0 && current_contained.length === contained_types.length);\n                if (current_contained.length === contained_types.length && current_contained.every((x, index) => x === contained_types[index])) {\n                    return this;\n                }\n                return this.createWithContained(contained_types);\n            }\n            createWithContained(/* createWithContained */) {\n                throw new python.Error('Not implemented.');\n            }\n            isUnionType() {\n                return false;\n            }\n            hasFreeVariables() {\n                return false;\n            }\n            is_module() {\n                return false;\n            }\n            expect(type) {\n                torch._C.AT_ASSERT(this instanceof type);\n                return this;\n            }\n            str() {\n                if (this instanceof torch._C.VarType && this._annotation_str) {\n                    return this._annotation_str;\n                } else if (this._kind === 'ScalarTypeType') {\n                    return 'ScalarType';\n                } else if (this._kind === 'QSchemeType') {\n                    return 'QScheme';\n                } else if (this._kind) {\n                    return this._kind;\n                }\n                throw new python.Error(`Not implemented '${this.kind()}'.`);\n            }\n            __str__() {\n                return this.str();\n            }\n            toString() {\n                return this.__str__();\n            }\n        });\n        this.registerType('torch.ClassType', class extends torch.Type {\n            constructor(qualified_name, cu, is_module) {\n                super('ClassType', typeof qualified_name === 'string' ? qualified_name : qualified_name.qualifiedName());\n                this._name = typeof qualified_name === 'string' ? new torch._C.QualifiedName(qualified_name) : qualified_name;\n                this._is_module = is_module;\n                this._attributes = [];\n                this._attributeTypes = [];\n                this._methods = [];\n                this._staticmethods = new Map();\n                this._forward_hooks = [];\n                this._forward_pre_hooks = [];\n                this._properties = [];\n                this._constants = new Map();\n            }\n            static create(qualifiedName, cu, is_module /*, doc_string, unresolved_class_attributes */) {\n                return new torch.ClassType(qualifiedName, cu, is_module);\n            }\n            qualified_name() {\n                return this.annotation_str;\n            }\n            name() {\n                return this._name;\n            }\n            is_module() {\n                return this._is_module;\n            }\n            is_parameter(slot) {\n                return this._attributes[slot].is_parameter === true;\n            }\n            is_buffer(slot) {\n                return this._attributes[slot].is_buffer === true;\n            }\n            addMethod(method) {\n                torch._C.TORCH_CHECK(this.findMethod(method.name()) === null);\n                this._methods.push(method);\n            }\n            findMethod(name) {\n                for (const method of this._methods) {\n                    if (name === method.name()) {\n                        return method;\n                    }\n                }\n                return null;\n            }\n            getMethod(name) {\n                const method = this.findMethod(name);\n                if (!method) {\n                    throw new python.Error(`Method '${name}' not found on class '${this.str()}.`);\n                }\n                return method;\n            }\n            methods() {\n                return this._methods;\n            }\n            addStaticMethod(func) {\n                this._staticmethods.set(func.name, func);\n            }\n            findStaticMethod(name) {\n                return this._staticmethods.get(name);\n            }\n            findHook(name) {\n                let hook = this.findForwardHook(name);\n                if (hook === null) {\n                    hook = this.findForwardPreHook(name);\n                }\n                return hook;\n            }\n            findForwardHook(name) {\n                for (const hook of this._forward_hooks) {\n                    if (name === hook.name()) {\n                        return hook;\n                    }\n                }\n                return null;\n            }\n            findForwardPreHook(name) {\n                for (const pre_hook of this._forward_pre_hooks) {\n                    if (name === pre_hook.name()) {\n                        return pre_hook;\n                    }\n                }\n                return null;\n            }\n            numAttributes() {\n                return this._attributes.length;\n            }\n            addAttribute(name, type, is_parameter, is_buffer) {\n                is_parameter = is_parameter || false;\n                is_buffer = is_buffer || false;\n                const slot = this._attributes.length;\n                this._attributes.push({ name, type, is_parameter, is_buffer });\n                this._attributeTypes.push(type);\n                return slot;\n            }\n            addOrCheckAttribute(name, ty, is_parameter, is_buffer) {\n                is_parameter = is_parameter || false;\n                is_buffer = is_buffer || false;\n                const slot_idx = this.findAttributeSlot(name);\n                if (slot_idx === null) {\n                    return this.addAttribute(name, ty, is_parameter, is_buffer);\n                }\n                // TORCH_CHECK(is_parameter == this.is_parameter(*slot_idx), \"Parameter field mismatch for the field '\", name, \"'\");\n                // const TypePtr& atype = getAttribute(*slot_idx);\n                // TORCH_CHECK(ty.isSubtypeOf(*atype), ty.repr_str(), \" is not compatible with the type \", atype.repr_str(), \" for the field '\", name, \"'\");\n                return slot_idx;\n            }\n            findAttributeSlot(name) {\n                for (let pos = 0; pos < this._attributes.length; pos++) {\n                    if (name === this._attributes[pos].name) {\n                        return pos;\n                    }\n                }\n                return null;\n            }\n            findAttribute(name) {\n                const slot = this.findAttributeSlot(name);\n                if (slot !== null) {\n                    return this._attributes[slot].type;\n                }\n                return null;\n            }\n            hasAttribute(name) {\n                return this._attributes.find((attr) => attr.name === name);\n            }\n            getAttribute(arg) {\n                const slot = Number.isInteger(arg) ? arg : this.findAttributeSlot(arg);\n                return this._attributes[slot].type;\n            }\n            getAttributeName(slot) {\n                return this._attributes[slot].name;\n            }\n            addConstant(name, value) {\n                this._constants.set(name, value);\n            }\n            hasConstant(name) {\n                return this._constants.has(name);\n            }\n            getProperty(name) {\n                for (const prop of this._properties) {\n                    if (name === prop.name) {\n                        return prop;\n                    }\n                }\n                return null;\n            }\n            containedTypes() {\n                return this._attributeTypes;\n            }\n            createWithContained(contained_types) {\n                const ptr = torch.ClassType.create(this.name(), this._compilation_unit, this.is_module());\n                torch._C.AT_ASSERT(this.numAttributes() === contained_types.length);\n                for (let i = 0; i < this._attributes.length; i++) {\n                    torch._C.AT_ASSERT(this._attributes[i].type.isSubtypeOf(contained_types[i]));\n                    ptr.addAttribute(this._attributes[i].name, contained_types[i]);\n                }\n                for (const method of this.methods()) {\n                    ptr.addMethod(method);\n                }\n                return ptr;\n            }\n            str() {\n                return this.qualified_name();\n            }\n        });\n        this.registerType('torch.EnumType', class extends torch.Type {\n            constructor(qualified_class_name, value_type, enum_names_values, cu) {\n                super('EnumType', qualified_class_name);\n                this._name = qualified_class_name;\n                this._value_type = value_type;\n                this._enum_names_values = enum_names_values;\n                this._cu = cu;\n            }\n            static create(qualified_class_name, value, enum_names_values, cu) {\n                if (value instanceof torch.IntType || value instanceof torch.FloatType || value instanceof torch.StringType) {\n                    return new torch.EnumType(qualified_class_name, value, enum_names_values, cu);\n                }\n                torch._C.TORCH_CHECK(false);\n                return null;\n            }\n            name() {\n                return this._name;\n            }\n            get annotation_str() {\n                return this._name.qualifiedName();\n            }\n            enumNamesValues() {\n                return this._enum_names_values;\n            }\n            compilation_unit() {\n                return this._cu;\n            }\n            getValueType() {\n                return this._value_type;\n            }\n            equals(rhs) {\n                if (rhs instanceof torch.EnumType) {\n                    return this.name() && this.name() === rhs.name() && this.getValueType() === rhs.getValueType() && this.compilation_unit() === rhs.compilation_unit();\n                }\n                return false;\n            }\n            isSubtypeOf(rhs) {\n                if (rhs instanceof torch.AnyType || rhs.kind() === 'AnyEnumType' || this === rhs) {\n                    return true;\n                }\n                return super.isSubtypeOf(rhs);\n            }\n        });\n        this.registerFunction('torch._C.standardizeVectorForUnion', (...args) => {\n            if (args.length === 1) {\n                const [to_flatten] = args;\n                torch._C.TORCH_INTERNAL_ASSERT(to_flatten !== null, `'standardizeVectorForUnion' was passed a 'nullptr'.`);\n                const to_fill = [];\n                torch._C.standardizeVectorForUnion(to_flatten, to_fill);\n                to_flatten.splice(0, to_flatten.length);\n                to_flatten.push(...to_fill);\n            } else if (args.length === 2) {\n                const [reference, to_fill] = args;\n                for (const type of reference) {\n                    torch._C.flattenUnion(type, to_fill);\n                }\n                torch._C.filterDuplicateSubtypes(to_fill);\n                torch._C.sortUnion(to_fill);\n            } else {\n                throw new python.Error('Not implemented.');\n            }\n        });\n        this.registerFunction('torch._C.flattenUnion', (type, to_fill) => {\n            if (type instanceof torch.UnionType) {\n                for (const inner of type.containedTypes()) {\n                    torch._C.flattenUnion(inner, to_fill);\n                }\n            } else if (type instanceof torch.OptionalType) {\n                const inner = type.getElementType();\n                torch._C.flattenUnion(inner, to_fill);\n                to_fill.push(torch.NoneType.get());\n            } else if (type instanceof torch.NumberType) {\n                to_fill.push(torch.IntType.get());\n                to_fill.push(torch.FloatType.get());\n                to_fill.push(torch.ComplexType.get());\n            } else {\n                to_fill.push(type);\n            }\n        });\n        this.registerFunction('torch._C.filterDuplicateSubtypes', (types) => {\n            if (types.length === 0) {\n                // return;\n            }\n            /*\n            const get_supertype = [](const TypePtr& t1, const TypePtr& t2) -> std::optional<TypePtr> {\n              // We don't want nested Optionals. Also, prematurely unifying to\n              // `Optional` could prevent us from coalescing other types\n              if ((t1->isSubtypeOf(*NoneType::get()) && !t2->isSubtypeOf(*NoneType::get()))\n                  || (!t1->isSubtypeOf(*NoneType::get()) && t2->isSubtypeOf(*NoneType::get()))) {\n                    return null;\n              } else {\n                return unifyTypes(t1, t2, default_to_union=false);\n              }\n            };\n            size_t end_idx = types->size()-1;\n            for (size_t i = types->size()-1; i > 0; --i) {\n              for (size_t j = std::min(i-1, end_idx); ; --j) {\n                std::optional<TypePtr> unified;\n                unified = get_supertype((*types)[i], (*types)[j]);\n                if (unified) {\n                  (*types)[j] = *unified;\n                  (*types)[i] = (*types)[end_idx];\n                  --end_idx;\n                  break;\n                }\n                if (j == 0) {\n                  break;\n                }\n              }\n            }\n            types.erase(types->begin() + static_cast<std::ptrdiff_t>(end_idx) + 1, types->end());\n            */\n        });\n        this.registerFunction('torch._C.sortUnion', (/* types */) => {\n            /*\n            std::sort(types->begin(), types->end(),\n                    [](const TypePtr& a, const TypePtr& b) -> bool {\n                      if (a->kind() != b->kind()) {\n                        return a->kind() < b->kind();\n                      }\n                      return a->str() < b->str();\n                    });\n            */\n        });\n        this.registerType('torch.UnionType', class extends torch.Type {\n            constructor(reference, kind) {\n                super(kind || 'UnionType');\n                torch._C.TORCH_INTERNAL_ASSERT(reference.length > 0, 'Cannot create an empty union.');\n                this._types = [];\n                torch._C.standardizeVectorForUnion(reference, this._types);\n                if (this._types.length === 1) {\n                    throw new python.Error('Invalid union type reference.');\n                }\n                this._can_hold_none = false;\n                this._has_free_variables = false;\n                for (const type of this._types) {\n                    if (type instanceof torch.NoneType) {\n                        this._can_hold_none = true;\n                    }\n                    if (type.hasFreeVariables()) {\n                        this._has_free_variables = true;\n                    }\n                }\n            }\n            static create(reference) {\n                const union_type = new torch.UnionType(reference);\n                /*\n                bool int_found = false;\n                bool float_found = false;\n                bool complex_found = false;\n                bool nonetype_found = false;\n                const update_is_opt_flags = [&](const TypePtr& t) {\n                  if (t == IntType::get()) {\n                    int_found = true;\n                  } else if (t == FloatType::get()) {\n                    float_found  = true;\n                  } else if (t == ComplexType::get()) {\n                    complex_found = true;\n                  } else if (t == NoneType::get()) {\n                    nonetype_found = true;\n                  }\n                };\n                for (const auto& t : union_type->containedTypes()) {\n                  update_is_opt_flags(t);\n                }\n                bool numbertype_found = int_found && float_found && complex_found;\n                if (nonetype_found) {\n                  if (union_type->containedTypes().size() == 4 && numbertype_found) {\n                    return OptionalType::create(NumberType::get());\n                  }\n                  if (union_type->containedTypes().size() == 2) {\n                    const not_none = union_type->containedTypes()[0] != NoneType::get()\n                                    ? union_type->containedTypes()[0]\n                                    : union_type->containedTypes()[1];\n                    return OptionalType::create(not_none);\n                  }\n                }\n                */\n                return union_type;\n            }\n            containedTypes() {\n                return this._types;\n            }\n            isUnionType() {\n                return true;\n            }\n            hasFreeVariables() {\n                return this._has_free_variables;\n            }\n            equals(rhs) {\n                if (rhs instanceof torch.UnionType) {\n                    if (rhs.containedTypes().length !== this.containedTypes().length) {\n                        return false;\n                    }\n                    return this.containedTypes().every((lhs_type) => rhs.containedTypes().some((rhs_type) => lhs_type === rhs_type));\n                } else if (rhs instanceof torch.OptionalType) {\n                    if (rhs.getElementType() === torch.NumberType.get()) {\n                        return this.containedTypes().length === 4 && this._can_hold_none && this.canHoldType(torch.NumberType.get());\n                    }\n                    const optional_lhs = this.toOptional();\n                    return optional_lhs && rhs === optional_lhs.expect(torch.OptionalType);\n                } else if (rhs instanceof torch.NumberType) {\n                    return this.containedTypes().length === 3 && this.canHoldType(torch.NumberType.get());\n                }\n                return false;\n            }\n            isSubtypeOf(rhs) {\n                const rhs_types = [];\n                if (rhs instanceof torch.UnionType) {\n                    if (this.containedTypes() === rhs.containedTypes()) {\n                        return true;\n                    }\n                    for (const typePtr of rhs.containedTypes()) {\n                        rhs_types.push(typePtr);\n                    }\n                } else if (rhs instanceof torch.OptionalType) {\n                    rhs_types.push(torch.NoneType.get());\n                    if (rhs.getElementType() === torch.NumberType.get()) {\n                        const number_types = [torch.IntType.get(), torch.FloatType.get(), torch.ComplexType.get()];\n                        rhs_types.push(...number_types);\n                    } else {\n                        rhs_types.push(rhs.getElementType());\n                    }\n                } else if (rhs instanceof torch.NumberType) {\n                    const number_types = [torch.IntType.get(), torch.FloatType.get(), torch.ComplexType.get()];\n                    rhs_types.push(...number_types);\n                } else {\n                    rhs_types.push(rhs);\n                }\n                return this.containedTypes().every((lhs_type) => rhs_types.some((rhs_type) => lhs_type.isSubtypeOf(rhs_type)));\n            }\n        });\n        this.registerType('torch.OptionalType', class extends torch.UnionType {\n            constructor(contained) {\n                super([contained, torch.NoneType.get()], 'OptionalType');\n                let is_numbertype = false;\n                if (contained instanceof torch.UnionType) {\n                    is_numbertype = contained.containedTypes().length === 3 && contained.canHoldType(torch.NumberType.get());\n                }\n                if (super.containedTypes().length === 2) {\n                    this._contained = super.containedTypes()[0] instanceof torch.NoneType ? super.containedTypes()[1] : super.containedTypes()[0];\n                } else if (contained === torch.NumberType.get() || is_numbertype) {\n                    this._contained = torch.NumberType.get();\n                    this._types.splice(0, this._types.length);\n                    this._types.push(torch.NumberType.get());\n                    this._types.push(torch.NoneType.get());\n                } else {\n                    const to_subtract = [torch.NoneType.get()];\n                    const without_none = this.subtractTypeSetFrom(to_subtract, this._types);\n                    this._contained = torch.UnionType.create([without_none]);\n                }\n                this._has_free_variables = contained.hasFreeVariables();\n            }\n            static create(elem) {\n                return new torch.OptionalType(elem);\n            }\n            getElementType() {\n                return this._contained;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind() && this.getElementType().equals(rhs.getElementType());\n            }\n            isSubtypeOf(rhs) {\n                if (rhs instanceof torch.OptionalType) {\n                    return this.getElementType().isSubtypeOf(rhs.getElementType());\n                } else if (rhs instanceof torch.UnionType) {\n                    throw new python.Error('Not implemented.');\n                }\n                // return super.isSubtypeOf(rhs);\n                return torch.Type.prototype.isSubtypeOf.call(this, rhs);\n            }\n            containedTypes() {\n                return [this._contained];\n            }\n            createWithContained(contained_types) {\n                torch._C.AT_ASSERT(contained_types.length === 1);\n                return torch.OptionalType.create(contained_types[0]);\n            }\n            subtractTypeSetFrom(to_subtract, from) {\n                const types = [];\n                const should_subtract = (lhs) => to_subtract.some((rhs) => lhs.isSubtypeOf(rhs));\n                for (const t of from) {\n                    if (!should_subtract(t)) {\n                        types.push(t);\n                    }\n                }\n                if (types.length === 0) {\n                    return null;\n                } else if (types.length === 1) {\n                    return types[0];\n                }\n                return torch.UnionType.create(types);\n            }\n            str() {\n                return `${this.getElementType().str()}?`;\n            }\n            __str__() {\n                return `Optional[${this.getElementType().__str__()}]`;\n            }\n        });\n        this.registerType('torch.ListType', class extends torch.Type {\n            constructor(elem) {\n                super('ListType');\n                this._elem = elem;\n            }\n            static create(elem) {\n                return new torch.ListType(elem);\n            }\n            getElementType() {\n                return this._elem;\n            }\n            equals(rhs) {\n                if (rhs instanceof torch.ListType) {\n                    return this.getElementType().equals(rhs.getElementType());\n                }\n                return false;\n            }\n            isSubtypeOf(rhs) {\n                if (super.isSubtypeOf(rhs)) {\n                    return true;\n                }\n                if (rhs.kind() === 'AnyListType') {\n                    return true;\n                }\n                return false;\n            }\n            containedTypes() {\n                return [this._elem];\n            }\n            createWithContained(contained_types) {\n                return new torch.ListType(contained_types[0]);\n            }\n            hasFreeVariables() {\n                return this.getElementType().hasFreeVariables();\n            }\n            str() {\n                return `${this.getElementType().str()}[]`;\n            }\n            __str__() {\n                return `List[${this.getElementType().__str__()}]`;\n            }\n        });\n        this.registerType('torch.FutureType', class extends torch.Type {\n            constructor(elem) {\n                super('FutureType');\n                this._elem = elem;\n            }\n            static create(elem) {\n                return new torch.FutureType(elem);\n            }\n            getElementType() {\n                return this._elem;\n            }\n            containedTypes() {\n                throw new python.Error('Not implemented.');\n            }\n            str() {\n                return `Future(${this.getElementType().str()})`;\n            }\n            __str__() {\n                return `Future[${this.getElementType().__str__()}]`;\n            }\n        });\n        this.registerType('torch.RRefType', class extends torch.Type {\n            constructor(elem) {\n                super('RRefType');\n                this._elem = elem;\n            }\n            static create(elem) {\n                return new torch.RRefType(elem);\n            }\n            getElementType() {\n                return this._elem;\n            }\n            containedTypes() {\n                throw new python.Error('Not implemented.');\n            }\n            str() {\n                return `RRef(${this.getElementType().str()})`;\n            }\n            __str__() {\n                return `RRef[${this.getElementType().__str__()}]`;\n            }\n        });\n        this.registerType('torch.AwaitType', class extends torch.Type {\n            constructor(elem) {\n                super('AwaitType');\n                this._elem = elem;\n            }\n            static get(elem) {\n                return new torch.AwaitType(elem);\n            }\n            getElementType() {\n                return this._elem;\n            }\n            containedTypes() {\n                throw new python.Error('Not implemented.');\n            }\n            str() {\n                return `Await(${this.getElementType().str()})`;\n            }\n            __str__() {\n                return `Await[${this.getElementType().__str__()}]`;\n            }\n        });\n        this.registerType('torch.TupleType', class extends torch.Type {\n            constructor(elements, annotation_str, schema) {\n                super('TupleType', annotation_str);\n                this._elements = elements;\n                this._has_free_variables = elements.some((v) => {\n                    if (!v) {\n                        throw new python.Error('Can not create tuple with None type');\n                    }\n                    return v.hasFreeVariables();\n                });\n                this._schema = schema;\n            }\n            static create(elements) {\n                return new torch.TupleType(elements, null, null);\n            }\n            static createNamed(qualified_name, field_names, field_types /*, field_defaults */) {\n                let schema = null;\n                if (qualified_name) {\n                    const args = [];\n                    for (let i = 0; i < field_names.length; i++) {\n                        const arg = new torch.Argument(field_names[i], field_types[i], field_types[i]);\n                        args.push(arg);\n                    }\n                    schema = new torch.FunctionSchema(qualified_name, '', args, []);\n                }\n                return new torch.TupleType(field_types, qualified_name, schema);\n            }\n            elements() {\n                return this._elements;\n            }\n            name() {\n                return this.annotation_str;\n            }\n            containedTypes() {\n                return this._elements;\n            }\n            createWithContained(createWithContained) {\n                return new torch.TupleType(createWithContained, this.name(), this.schema());\n            }\n            hasFreeVariables() {\n                return this._has_free_variables;\n            }\n            schema() {\n                return this._schema;\n            }\n            str() {\n                if (this._schema) {\n                    return `NamedTuple(...)`;\n                }\n                return `(${this.elements().map((elem) => elem.str()).join(', ')})`;\n            }\n            __str__() {\n                if (this.annotation_str) {\n                    return this.annotation_str;\n                }\n                return `Tuple[${this.elements().map((elem) => elem.__str__()).join(', ')}]`;\n            }\n        });\n        this.registerType('torch.AnyType', class extends torch.Type {\n            constructor() {\n                super('AnyType');\n            }\n            static get() {\n                torch.AnyType.value = torch.AnyType.value || new torch.AnyType();\n                return torch.AnyType.value;\n            }\n            str() {\n                return 'Any';\n            }\n            __str__() {\n                return 'Any';\n            }\n        });\n        this.registerType('torch.NoneType', class extends torch.Type {\n            constructor() {\n                super('NoneType');\n            }\n            static get() {\n                torch.NoneType.value = torch.NoneType.value || new torch.NoneType();\n                return torch.NoneType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            isSubtypeOf(rhs) {\n                if (rhs.kind() === 'OptionalType') {\n                    return true;\n                }\n                return super.isSubtypeOf(rhs);\n            }\n            str() {\n                return 'NoneType';\n            }\n            __str__() {\n                return 'NoneType';\n            }\n        });\n        this.registerType('torch.TensorType', class extends torch.Type {\n            constructor() {\n                super('TensorType');\n                this._is_inferred = false;\n            }\n            static get() {\n                torch.TensorType.value = torch.TensorType.value || new torch.TensorType();\n                return torch.TensorType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            isInferredType() {\n                return this._is_inferred;\n            }\n            str() {\n                return 'Tensor';\n            }\n            __str__() {\n                return 'Tensor';\n            }\n        });\n        this.registerType('torch.NumberType', class extends torch.Type {\n            constructor() {\n                super('NumberType');\n            }\n            static get() {\n                torch.NumberType.value = torch.NumberType.value || new torch.NumberType();\n                return torch.NumberType.value;\n            }\n            str() {\n                return 'Scalar';\n            }\n            __str__() {\n                return 'number';\n            }\n        });\n        this.registerType('torch.BoolType', class extends torch.Type {\n            constructor() {\n                super('BoolType');\n            }\n            static get() {\n                torch.BoolType.value = torch.BoolType.value || new torch.BoolType();\n                return torch.BoolType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            str() {\n                return 'bool';\n            }\n            __str__() {\n                return 'bool';\n            }\n        });\n        this.registerType('torch.IntType', class extends torch.Type {\n            constructor() {\n                super('IntType');\n            }\n            static get() {\n                torch.IntType.value = torch.IntType.value || new torch.IntType();\n                return torch.IntType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            isSubtypeOf(rhs) {\n                return rhs instanceof torch.NumberType || rhs instanceof torch.FloatType || super.isSubtypeOf(rhs);\n            }\n            str() {\n                return 'int';\n            }\n            __str__() {\n                return 'int';\n            }\n        });\n        this.registerType('torch.SymIntType', class extends torch.Type {\n            constructor() {\n                super('SymIntType');\n            }\n            static get() {\n                torch.SymIntType.value = torch.SymIntType.value || new torch.SymIntType();\n                return torch.SymIntType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            str() {\n                return 'SymInt';\n            }\n            __str__() {\n                return 'int';\n            }\n        });\n        this.registerType('torch.FloatType', class extends torch.Type {\n            constructor() {\n                super('FloatType');\n            }\n            static get() {\n                torch.FloatType.value = torch.FloatType.value || new torch.FloatType();\n                return torch.FloatType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            isSubtypeOf(rhs) {\n                return rhs.kind() === 'NumberType' || super.isSubtypeOf(rhs);\n            }\n            str() {\n                return 'float';\n            }\n            __str__() {\n                return 'float';\n            }\n        });\n        this.registerType('torch.StringType', class extends torch.Type {\n            constructor() {\n                super('StringType');\n            }\n            static get() {\n                torch.StringType.value = torch.StringType.value || new torch.StringType();\n                return torch.StringType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            str() {\n                return 'str';\n            }\n            __str__() {\n                return 'str';\n            }\n        });\n        this.registerType('torch.ComplexType', class extends torch.Type {\n            constructor() {\n                super('ComplexType');\n            }\n            static get() {\n                torch.ComplexType.value = torch.ComplexType.value || new torch.ComplexType();\n                return torch.ComplexType.value;\n            }\n            equals(rhs) {\n                return this.kind() === rhs.kind();\n            }\n            isSubtypeOf(rhs) {\n                return rhs.kind() === 'NumberType' || super.isSubtypeOf(rhs);\n            }\n            str() {\n                return 'complex';\n            }\n            __str__() {\n                return 'complex';\n            }\n        });\n        this.registerType('torch.DictType', class extends torch.Type {\n            constructor(key, value) {\n                super('DictType');\n                this.types = [key, value];\n            }\n            static create(key, value) {\n                let kind = key.kind();\n                if (key instanceof torch._C.DynamicType) {\n                    kind = key.dynamicKind();\n                }\n                switch (kind) {\n                    case 'AnyType':\n                    case 'IntType':\n                    case 'BoolType':\n                    case 'FloatType':\n                    case 'ComplexType':\n                    case 'StringType':\n                    case 'TensorType':\n                    case 'DeviceObjType':\n                        return new torch.DictType(key, value);\n                    default:\n                        throw new python.Error(`Invalid dict key type '${kind}'.`);\n                }\n            }\n            createWithContained(contained_types) {\n                if (contained_types.length !== 2) {\n                    throw new python.Error('Expected 2 contained types.');\n                }\n                return torch.DictType.create(contained_types[0], contained_types[1]);\n            }\n            getKeyType() {\n                return this.types[0];\n            }\n            getValueType() {\n                return this.types[1];\n            }\n            hasFreeVariables() {\n                return this.getKeyType().hasFreeVariables() || this.getValueType().hasFreeVariables();\n            }\n            containedTypes() {\n                return this.types;\n            }\n            equals(rhs) {\n                if (rhs instanceof torch.DictType) {\n                    return this.getKeyType().equals(rhs.getKeyType()) && this.getValueType().equals(rhs.getValueType());\n                }\n                return false;\n            }\n            str() {\n                return `Dict(${this.getKeyType().str()}, ${this.getValueType().str()})`;\n            }\n            __str__() {\n                return `Dict(${this.getKeyType().__str__()}, ${this.getValueType().__str__()})`;\n            }\n        });\n        this.registerType('torch.DeviceObjType', class extends torch.Type {\n            constructor() {\n                super('DeviceObjType');\n            }\n            static get() {\n                torch.DeviceObjType.value ||= new torch.DeviceObjType();\n                return torch.DeviceObjType.value;\n            }\n            str() {\n                return 'Device';\n            }\n            __str__() {\n                return 'Device';\n            }\n        });\n        this.registerType('torch.StreamObjType', class extends torch.Type {\n            constructor() {\n                super('StreamObjType');\n            }\n            str() {\n                return 'Stream';\n            }\n            __str__() {\n                return 'Stream';\n            }\n        });\n        this.registerType('torch._C._GeneratorType', class extends torch.Type {\n            constructor() {\n                super('GeneratorType');\n            }\n            static get() {\n                torch._C._GeneratorType.value = torch._C._GeneratorType.value || new torch._C._GeneratorType();\n                return torch._C._GeneratorType.value;\n            }\n            str() {\n                return 'Generator';\n            }\n            __str__() {\n                return 'Generator';\n            }\n        });\n        this.registerType('torch.InterfaceType', class extends torch.Type {\n            constructor() {\n                super('InterfaceType');\n            }\n        });\n        this.registerType('torch._C.DynamicType', class extends torch.Type {\n            constructor() {\n                super('DynamicType');\n            }\n        });\n        this.registerType('torch._C.FunctionType', class extends torch.Type {\n            constructor(func) {\n                super('FunctionType');\n                this._func = func;\n            }\n            static create(func) {\n                return new torch._C.FunctionType(func);\n            }\n            function() {\n                return this._func;\n            }\n        });\n        this.registerType('torch._C.VarType', class extends torch.Type {\n            constructor(name) {\n                super('VarType', name);\n            }\n            static create(name) {\n                return new torch._C.VarType(name);\n            }\n            name() {\n                return this._annotation_str;\n            }\n            hasFreeVariables() {\n                return true;\n            }\n        });\n        this.registerType('torch._C.AliasInfo', class {\n            constructor() {\n                this.is_write = false;\n                this.before_set = [];\n                this.after_set = [];\n                this.containedTypes = [];\n            }\n            addBeforeSet(value) {\n                this.before_set.push(value);\n            }\n            addAfterSet(value) {\n                this.after_set.push(value);\n            }\n            addContainedType(alias_info) {\n                this.containedTypes.push(alias_info);\n            }\n            str() {\n                const list = ['('];\n                list.push(this.before_set.join('|'));\n                if (this.after_set.length > 0) {\n                    list.push(' -> ');\n                    list.push(this.after_set.join('|'));\n                }\n                if (this.is_write) {\n                    list.push('!');\n                }\n                list.push(')');\n                return list.join('');\n            }\n        });\n        this.registerFunction('torch._C.parseStringLiteral', (range, str) => {\n            if (str.startsWith('\"') && str.endsWith('\"')) {\n                return str.slice(1, -1);\n            }\n            if (str.startsWith(\"'\") && str.endsWith(\"'\")) {\n                return str.slice(1, -1);\n            }\n            throw new python.Error(`Invalid string literal '${str}'.`);\n            // inline std::string parseStringLiteral(\n        });\n        this.registerType('torch._C.Token', class {\n            constructor() {\n                this.kind = '';\n                this.value = '';\n            }\n            text() {\n                return this.value;\n            }\n        });\n        this.registerType('torch._C.Lexer', class {\n            constructor(buffer) {\n                this.buffer = buffer;\n                this.position = 0;\n                this.next_tokens = [new torch._C.Token(), new torch._C.Token(), new torch._C.Token(), new torch._C.Token()];\n                this.next();\n            }\n            cur() {\n                return this.next_tokens[0];\n            }\n            lookahead() {\n                if (!this.next_tokens[1].kind) {\n                    this.position += this.cur().text().length;\n                    this.lex(this.next_tokens[1]);\n                }\n                return this.next_tokens[1];\n            }\n            next() {\n                const [cur] = this.next_tokens;\n                [, this.next_tokens[0], this.next_tokens[1], this.next_tokens[2]] = this.next_tokens;\n                this.next_tokens[1].kind = '';\n                this.next_tokens[3] = cur;\n                const [token] = this.next_tokens;\n                if (token.kind) {\n                    return cur;\n                }\n                this.position += cur.text().length;\n                this.lex(token);\n                return cur;\n            }\n            nextIf(kind) {\n                if (this.cur().kind !== kind) {\n                    return false;\n                }\n                this.next();\n                return true;\n            }\n            expect(kind) {\n                if (this.cur().kind !== kind) {\n                    throw new python.Error(`Unexpected '${this.cur().kind}' instead of '${kind}'.`);\n                }\n                return this.next();\n            }\n            lex(token) {\n                while (this.buffer[this.position] === ' ') {\n                    this.position += 1;\n                }\n                let i = this.position;\n                if (i >= this.buffer.length) {\n                    token.kind = '\\0';\n                    token.value = '';\n                } else if (this.buffer[i] === '.' && this.buffer[i + 1] === '.' && this.buffer[i + 2] === '.') {\n                    token.kind = '...';\n                    token.value = '...';\n                /* } else if (this.buffer[i] === '[' && this.buffer[i + 1] === ']') {\n                    this.kind = '[]';\n                    this.value = '[]'; */\n                } else if (this.buffer[i] === '(' || this.buffer[i] === ')' || this.buffer[i] === ':' || this.buffer[i] === '.' || this.buffer[i] === '[' || this.buffer[i] === ']' || this.buffer[i] === ',' || this.buffer[i] === '=' || this.buffer[i] === '?' || this.buffer[i] === '!' || this.buffer[i] === '*' || this.buffer[i] === '|') {\n                    token.kind = this.buffer[i];\n                    token.value = this.buffer[i];\n                } else if ((this.buffer[i] >= 'a' && this.buffer[i] <= 'z') || (this.buffer[i] >= 'A' && this.buffer[i] <= 'Z') || this.buffer[i] === '_') {\n                    i += 1;\n                    while (i < this.buffer.length && ((this.buffer[i] >= 'a' && this.buffer[i] <= 'z') || (this.buffer[i] >= 'A' && this.buffer[i] <= 'Z') || (this.buffer[i] >= '0' && this.buffer[i] <= '9') || this.buffer[i] === '_')) {\n                        i += 1;\n                    }\n                    token.kind = 'id';\n                    token.value = this.buffer.slice(this.position, i);\n                } else if (this.buffer[i] === '-' && this.buffer[i + 1] === '>') {\n                    token.kind = '->';\n                    token.value = '->';\n                } else if ((this.buffer[i] >= '0' && this.buffer[i] <= '9') || this.buffer[i] === '-') {\n                    i += 1;\n                    while (i < this.buffer.length && ((this.buffer[i] >= '0' && this.buffer[i] <= '9') || this.buffer[i] === '.' || this.buffer[i] === 'e' || this.buffer[i] === '-')) {\n                        i += 1;\n                    }\n                    token.kind = '#';\n                    token.value = this.buffer.slice(this.position, i);\n                } else if (this.buffer[i] === \"'\" || this.buffer[i] === '\"') {\n                    const quote = this.buffer[i];\n                    i += 1;\n                    while (i < this.buffer.length && this.buffer[i] !== quote) {\n                        i += (this.buffer[i] === '\\\\' && (this.buffer[i + 1] === \"'\" || this.buffer[i + 1] === '\"' || this.buffer[i + 1] === '\\\\')) ? 2 : 1;\n                    }\n                    i += 1;\n                    token.kind = 'string';\n                    token.value = this.buffer.slice(this.position, i);\n                } else {\n                    throw new python.Error(`Unsupported token at '${this.position}'.`);\n                }\n            }\n        });\n        this.registerType('torch._C.SchemaTypeParser', class {\n            constructor(L, complete_tensor_types, allow_typevars) {\n                this.L = L;\n                this.complete_tensor_types = complete_tensor_types;\n                this._allow_typevars = allow_typevars;\n            }\n            parseType() {\n                const r = this.parseFakeAndRealType();\n                return { first: r[0], second: r[2] };\n            }\n            parseBaseType() {\n                const L = this.L;\n                const tok = L.cur();\n                const text = tok.text();\n                L.next();\n                switch (text) {\n                    case 'Tensor': return torch.TensorType.get();\n                    case 'bool': return torch.BoolType.get();\n                    case 'int': return torch.IntType.get();\n                    case 'float': return torch.FloatType.get();\n                    case 'complex': return torch.ComplexType.get();\n                    case 'str': return torch.StringType.get();\n                    case 'SymInt': return torch.SymIntType.get();\n                    case 'Scalar': return torch.NumberType.get();\n                    case 'ScalarType': return torch.Type.get('ScalarTypeType');\n                    case 'Device': return torch.DeviceObjType.get();\n                    case 'Layout': return torch.Type.get('Layout');\n                    case 'MemoryFormat': return torch.Type.get('MemoryFormat');\n                    case 'Generator': return torch._C._GeneratorType.get();\n                    case 't': case 't1': case 't2': case 'tVal': return torch._C.VarType.create(text);\n                    case 'Any': return torch.AnyType.get();\n                    case 'AnyEnumType': return torch.Type.get('AnyEnumType');\n                    case 'Dimname': return torch.StringType.get();\n                    case 'QScheme': return torch.Type.get('QSchemeType');\n                    case 'Stream': return torch.StreamObjType.get();\n                    case 'Storage': return torch.Type.get('Storage');\n                    case 'AnyClassType': return torch.Type.get('AnyClassType');\n                    case 'NoneType': return torch.NoneType.get();\n                    default: throw new python.Error(`Unsupported type '${text}'.`);\n                }\n            }\n            parseFakeAndRealType() {\n                const L = this.L;\n                let fake_value = null;\n                let real_value = null;\n                let alias_info = null;\n                if (L.nextIf('(')) {\n                    const types = [];\n                    while (!L.nextIf(')')) {\n                        const r = this.parseType();\n                        types.push(r.first);\n                        if (alias_info && r.second) {\n                            alias_info.addContainedType(r.second);\n                        }\n                        L.nextIf(',');\n                    }\n                    real_value = torch.TupleType.create(types);\n                    fake_value = real_value;\n                } else if (L.cur().text() === 'Future') {\n                    L.next();\n                    L.expect('(');\n                    const p = this.parseType();\n                    const subtype = p.first;\n                    // const subalias = p.second;\n                    L.expect(')');\n                    real_value = torch.FutureType.create(subtype);\n                    fake_value = real_value;\n                } else if (L.cur().text() === 'Await') {\n                    L.next();\n                    L.expect('(');\n                    const p = this.parseType();\n                    const subtype = p.first;\n                    // const subalias = p.second;\n                    L.expect(')');\n                    real_value = torch.AwaitType.get(subtype);\n                    fake_value = real_value;\n                } else if (L.cur().text() === 'RRef') {\n                    L.next();\n                    L.expect('(');\n                    const p = this.parseType();\n                    const subtype = p.first;\n                    // const subalias = p.second;\n                    L.expect(')');\n                    real_value = torch.RRefType.create(subtype);\n                    fake_value = real_value;\n                } else if (L.cur().text() === 'Tensor') {\n                    L.next();\n                    real_value = torch.TensorType.get();\n                    fake_value = real_value;\n                    alias_info = this.parseAliasAnnotation();\n                } else if (L.cur().text() === 'Dict') {\n                    L.next();\n                    L.expect('(');\n                    const key_type = this.parseType().first;\n                    L.expect(',');\n                    const value_type = this.parseType().first;\n                    L.expect(')');\n                    alias_info = this.parseAliasAnnotation();\n                    real_value = torch.DictType.create(key_type, value_type);\n                    fake_value = real_value;\n                } else if (L.nextIf('Union')) {\n                    L.next();\n                    L.expect('(');\n                    const types = [];\n                    types.push(this.parseType().first);\n                    while (L.cur().kind !== ')') {\n                        L.expect(',');\n                        types.push(this.parseType().first);\n                    }\n                    L.expect(')');\n                    alias_info = this.parseAliasAnnotation();\n                    real_value = new torch.UnionType(types);\n                    fake_value = real_value;\n                /* } else if (complete_tensor_types && L.cur().kind == TK_IDENT && parseTensorDType(L.cur().text())) {\n                    fake_value = real_value = parseRefinedTensor();\n                    alias_info = parseAliasAnnotation(); */\n                } else if (L.cur().kind === 'id' && L.cur().text() === '__torch__') {\n                    L.next();\n                    L.expect('.');\n                    const torch_tok = L.expect('id');\n                    if (torch_tok.text() !== 'torch') {\n                        throw new python.Error('Expected classes namespace.');\n                    }\n                    L.expect('.');\n                    const classes_tok = L.expect('id');\n                    if (classes_tok.text() !== 'classes') {\n                        throw new python.Error('Expected classes namespace.');\n                    }\n                    L.expect('.');\n                    const ns_tok = L.expect('id');\n                    L.expect('.');\n                    const class_tok = L.expect('id');\n                    real_value = torch._C.getCustomClass(`__torch__.torch.classes.${ns_tok.text()}.${class_tok.text()}`);\n                    fake_value = real_value;\n                    if (!fake_value) {\n                        throw new python.Error(`Unknown custom class type '${ns_tok.text()}.${class_tok.text()}'.`);\n                    }\n                } else {\n                    real_value = this.parseBaseType();\n                    fake_value = real_value;\n                    if (real_value.kind() === 'ScalarTypeType' ||\n                        real_value.kind() === 'MemoryFormat' ||\n                        real_value.kind() === 'Layout' ||\n                        real_value.kind() === 'SymIntType') {\n                        fake_value = torch.IntType.get();\n                    }\n                    alias_info = this.parseAliasAnnotation();\n                }\n                while (true) {\n                    if (L.cur().kind === '[' && L.lookahead().kind === ']') {\n                        L.expect('[');\n                        L.expect(']');\n                        fake_value = torch.ListType.create(fake_value);\n                        real_value = torch.ListType.create(real_value);\n                        let container = this.parseAliasAnnotation();\n                        if (alias_info) {\n                            if (!container) {\n                                container = new torch._C.AliasInfo();\n                                container.is_write = alias_info.is_write;\n                            }\n                            container.addContainedType(alias_info);\n                        }\n                        alias_info = container;\n                    } else if (L.nextIf('?')) {\n                        fake_value = torch.OptionalType.create(fake_value);\n                        real_value = torch.OptionalType.create(real_value);\n                    } else {\n                        break;\n                    }\n                }\n                return [fake_value, real_value, alias_info];\n            }\n            parseAliasAnnotation() {\n                const L = this.L;\n                let alias_info = null;\n                if (L.nextIf('(')) {\n                    alias_info = new torch._C.AliasInfo();\n                    do {\n                        alias_info.addBeforeSet(L.cur().text());\n                        L.next();\n                        if (L.nextIf('!')) {\n                            alias_info.is_write = true;\n                        }\n                    }\n                    while (L.nextIf('|'));\n                    if (L.nextIf('->')) {\n                        do {\n                            alias_info.addAfterSet(L.cur().text());\n                            L.next();\n                        }\n                        while (L.nextIf('|'));\n                    }\n                    L.expect(')');\n                }\n                return alias_info;\n            }\n        });\n        this.registerType('torch.Argument', class {\n            constructor(...args) {\n                // torch/aten/src/ATen/core/function_schema.h\n                this.N = null;\n                this.default_value = null;\n                this.kwarg_only = false;\n                this.alias_info = null;\n                if (args.length === 2) {\n                    [this.name, this.type] = args;\n                    this.real_type = this.type;\n                } else if (args.length === 3 && args[1] instanceof torch.Type && args[2] instanceof torch.Type) {\n                    [this.name, this.type, this.real_type] = args;\n                } else if (args.length === 6) {\n                    [this.name, this.type, this.real_type, this.N, this.default_value, this.kwarg_only] = args;\n                } else if (args.length === 7) {\n                    [this.name, this.type, this.real_type, this.N, this.default_value, this.kwarg_only, this.alias_info] = args;\n                } else {\n                    throw new python.Error('Invalid arguments.');\n                }\n                const is_alias = this.alias_info && this.alias_info.is_write;\n                this.is_out = this.kwarg_only && is_alias;\n            }\n            has_default_value() {\n                return this.default_value !== undefined;\n            }\n            is_inferred_type() {\n                if (this.type instanceof torch.TensorType) {\n                    return this.type.isInferredType();\n                }\n                return false;\n            }\n            str() {\n                const list = [];\n                const type = this.real_type;\n                const is_opt = type instanceof torch.OptionalType;\n                const unopt_type = is_opt ? type.getElementType() : type;\n                if (unopt_type instanceof torch.ListType) {\n                    list.push(unopt_type.getElementType().str());\n                    if (this.alias_info && this.alias_info.containedTypes.length > 0) {\n                        list.push(this.alias_info.containedTypes[0].str());\n                    }\n                    list.push(this.N === null ? `[]` : `[${this.N}]`);\n                } else {\n                    list.push(unopt_type.str());\n                }\n                if (this.alias_info && this.alias_info.before_set.length > 0) {\n                    list.push(this.alias_info.str());\n                }\n                if (is_opt) {\n                    list.push('?');\n                }\n                if (this.name) {\n                    list.push(' ');\n                    list.push(this.name);\n                }\n                if (this.default_value !== undefined) {\n                    const value = this.default_value;\n                    if (value === null) {\n                        list.push('=None');\n                    } else if (typeof value === 'boolean') {\n                        list.push('=');\n                        list.push(value ? 'True' : 'False');\n                    } else if (typeof value === 'string') {\n                        list.push(`=\"${value}\"`);\n                    } else if (typeof value === 'number') {\n                        list.push(`=${value}`);\n                        if (Number.isInteger(value) && this.real_type instanceof torch.FloatType) {\n                            list.push(`.`);\n                        }\n                    } else if (Array.isArray(value)) {\n                        list.push(`=[${value.join(', ')}]`);\n                    }\n                }\n                return list.join('');\n            }\n        });\n        torch._C.TypeKind = {\n            StringType: 'StringType',\n            NumberType: 'NumberType',\n            IntType: 'IntType',\n            BoolType: 'BoolType',\n            DynamicType: 'DynamicType',\n            OptionalType: 'OptionalType',\n            FloatType: 'FloatType',\n            ComplexType: 'ComplexType',\n            ListType: 'ListType',\n        };\n        this.registerType('torch._C.List', class extends Array {\n            constructor(type, elements) {\n                super(elements ? elements.length : 0);\n                if (Array.isArray(elements)) {\n                    for (let i = 0; i < elements.length; i++) {\n                        this[i] = elements[i];\n                    }\n                }\n                this.type = type;\n            }\n            elementType() {\n                return this.type;\n            }\n            append(item) {\n                this.push(item);\n            }\n            extend(items) {\n                this.push(...items);\n            }\n        });\n        this.registerFunction('torch._C.builtin_cast_method_to_scalar_type', () => {\n            return new Map();\n        });\n        this.registerFunction('torch._C.string_to_type_lut', () => {\n            if (!torch._C.string_to_type_lut.basePythonTypes) {\n                const map = new Map();\n                map.set('Tensor', torch.TensorType.get());\n                map.set('int', torch.IntType.get());\n                map.set('float', torch.FloatType.get());\n                map.set('bool', torch.BoolType.get());\n                map.set('complex', torch.ComplexType.get());\n                map.set('str', torch.StringType.get());\n                map.set('Device', torch.DeviceObjType.get());\n                map.set('number', torch.NumberType.get());\n                map.set('None', torch.NoneType.get());\n                map.set('NoneType', torch.NoneType.get());\n                map.set('Any', torch.AnyType.get());\n                map.set('list', torch.Type.get('AnyListType'));\n                map.set('tuple', torch.Type.get('AnyTupleType'));\n                torch._C.string_to_type_lut.basePythonTypes = map;\n            }\n            return torch._C.string_to_type_lut.basePythonTypes;\n        });\n        this.registerType('torch._C.ScriptTypeParser', class {\n            constructor(resolver) {\n                this._resolver = resolver;\n            }\n            parseSchemaFromDef(def, skip_self) {\n                const name = def.name;\n                const args = this.parseArgsFromDecl(def, skip_self);\n                const returns = this.parseReturnFromDecl(def);\n                return new torch.FunctionSchema(name, '', args, returns, false, false);\n            }\n            parseArgsFromDecl(decl, skip_self) {\n                const retval = [];\n                if (decl.args.posonlyargs.length > 0 || decl.args.kwonlyargs.length > 0) {\n                    throw new python.Error('Unsupported function argument.');\n                }\n                const params = decl.args.args.slice();\n                const kwonlyargs = new Set(Array.from(decl.args.kwonlyargs));\n                const start = skip_self ? 1 : 0;\n                for (let i = start; i < params.length; i++) {\n                    const decl_arg = params[i];\n                    const N = null;\n                    const default_value = undefined;\n                    const type = decl_arg.annotation ? this.parseTypeFromExpr(decl_arg.annotation) : null;\n                    const arg = new torch.Argument(decl_arg.arg, type, type, N, default_value, kwonlyargs.has(decl_arg), null);\n                    retval.push(arg);\n                }\n                return retval;\n            }\n            parseReturnFromDecl(decl) {\n                if (!decl.returns) {\n                    return [];\n                }\n                if (this.parseBroadcastList(decl.returns)) {\n                    throw new python.Error('Broadcastable lists cannot appear as a return type.');\n                }\n                const parsed_type = this.parseTypeFromExpr(decl.returns);\n                return [new torch.Argument('', parsed_type, parsed_type, null, undefined, false)];\n            }\n            parseTypeFromExpr(expr) {\n                if (this._resolver) {\n                    if (expr instanceof ast.Name) {\n                        const type = this._resolver.resolveType(expr.id);\n                        if (type) {\n                            return type;\n                        }\n                    }\n                }\n                return this.parseTypeFromExprImpl(expr);\n            }\n            parseTypeFromExprImpl(expr) {\n                if (expr instanceof ast.Subscript) {\n                    const value_name = this.parseBaseTypeName(expr.value);\n                    if (!value_name) {\n                        throw new python.Error('Subscripted type must be a type identifier.');\n                    }\n                    return this.subscriptToType(value_name, expr);\n                }\n                const name = this.parseBaseTypeName(expr);\n                if (name) {\n                    const itr = torch._C.string_to_type_lut().get(name);\n                    if (itr) {\n                        return itr;\n                    }\n                    if (this._resolver) {\n                        const typePtr = this._resolver.resolveType(name, expr);\n                        if (typePtr) {\n                            return typePtr;\n                        }\n                    }\n                }\n                throw new python.Error(`Unknown type name '${name}'.`);\n            }\n            parseBaseTypeName(expr) {\n                if (expr instanceof ast.Name) {\n                    return expr.id;\n                } else if (expr instanceof ast.Constant && expr.value === null) {\n                    return 'None';\n                } else if (expr instanceof ast.Attribute) {\n                    const name = expr.attr;\n                    const tensor_subtypes = new Set(['Tensor', 'LongTensor', 'FloatTensor', 'DoubleTensor', 'IntTensor', 'ShortTensor', 'HalfTensor', 'CharTensor', 'ByteTensor', 'BoolTensor']);\n                    if (torch._C.isTorch(expr.value) && tensor_subtypes.has(name)) {\n                        return name;\n                    }\n                    return torch._C.collectQualname(expr);\n                }\n                throw new python.Error(`Unsupported type '${expr.__class__.__name__}'.`);\n            }\n            parseBroadcastList(/* expr */) {\n                return null;\n            }\n            parseType(str) {\n                const expr = ast.parse(str);\n                return this.parseTypeFromExpr(expr.body[0].value);\n            }\n            subscriptToType(typeName, subscript) {\n                if (typeName === 'Tuple' || typeName === 'tuple') {\n                    const subscript_expr_types = [];\n                    const elts = subscript.slice instanceof ast.Tuple ? subscript.slice.elts : [subscript.slice];\n                    for (const expr of elts) {\n                        subscript_expr_types.push(this.parseTypeFromExprImpl(expr));\n                    }\n                    return torch.TupleType.create(subscript_expr_types);\n                } else if (typeName === 'List' || typeName === 'list') {\n                    if (subscript.slice instanceof ast.Slice || subscript.slice instanceof ast.Tuple) {\n                        throw new python.Error('List type must have exactly one element type.');\n                    }\n                    const elem_type = this.parseTypeFromExprImpl(subscript.slice);\n                    return torch.ListType.create(elem_type);\n                } else if (typeName === 'Optional') {\n                    if (subscript.slice instanceof ast.Slice || subscript.slice instanceof ast.Tuple) {\n                        throw new python.Error('Optional type must have exactly one element type.');\n                    }\n                    const elem_type = this.parseTypeFromExprImpl(subscript.slice);\n                    return torch.OptionalType.create(elem_type);\n                } else if (typeName === 'Union') {\n                    const subscript_expr_types = [];\n                    const elts = subscript.slice instanceof ast.Tuple ? subscript.slice.elts : [subscript.slice];\n                    for (const expr of elts) {\n                        subscript_expr_types.push(this.parseTypeFromExprImpl(expr));\n                    }\n                    return torch.UnionType.create(subscript_expr_types);\n                } else if (typeName === 'Future' || typeName === 'torch.jit.Future') {\n                    const elts = subscript.slice instanceof ast.Tuple ? subscript.slice.elts : [subscript.slice];\n                    if (elts.length !== 1) {\n                        throw new python.Error('Future type must have exactly one element type.');\n                    }\n                    const elem_type = this.parseTypeFromExprImpl(elts[0]);\n                    return torch.FutureType.create(elem_type);\n                } else if (typeName === 'Await' || typeName === 'torch.jit._Await') {\n                    const elts = subscript.slice instanceof ast.Tuple ? subscript.slice.elts : [subscript.slice];\n                    if (elts.length !== 1) {\n                        throw new python.Error('Await type must have exactly one element type.');\n                    }\n                    const elem_type = this.parseTypeFromExprImpl(elts[0]);\n                    return torch.AwaitType.create(elem_type);\n                } else if (typeName === 'RRef') {\n                    const elts = subscript.slice instanceof ast.Tuple ? subscript.slice.elts : [subscript.slice];\n                    if (elts.length !== 1) {\n                        throw new python.Error('RRef type must have exactly one element type.');\n                    }\n                    const elem_type = this.parseTypeFromExprImpl(elts[0]);\n                    return torch.RRefType.create(elem_type);\n                } else if (typeName === 'Dict' || typeName === 'dict') {\n                    const elts = subscript.slice instanceof ast.Tuple ? subscript.slice.elts : [subscript.slice];\n                    if (elts.length !== 2) {\n                        throw new python.Error('Dict type must have exactly two element types.');\n                    }\n                    const key_type = this.parseTypeFromExprImpl(elts[0]);\n                    const value_type = this.parseTypeFromExprImpl(elts[1]);\n                    return torch.DictType.create(key_type, value_type);\n                }\n                throw new python.Error(`Unknown type constructor '${typeName}'.`);\n            }\n        });\n        this.registerFunction('torch._C.isTorch', (expr) => {\n            return expr instanceof ast.Name && expr.id === 'torch';\n        });\n        this.registerFunction('torch._C.collectQualname', (select) => {\n            const base = select.value;\n            if (base instanceof ast.Name) {\n                return `${base.id}.${select.attr}`;\n            }\n            const basename = torch._C.collectQualname(base);\n            return `${basename}.${select.attr}`;\n        });\n        this.registerType('torch._ops.OpOverload', class extends torch._ops.OperatorBase {\n            constructor(overloadpacket, op, op_dk, schema, tags) {\n                super();\n                this._op = op;\n                this._op_dk = op_dk;\n                this._schema = schema;\n                this._overloadpacket = overloadpacket;\n                this._tags = tags;\n                this._overloadname = schema.overload_name === '' ? 'default' : schema.overload_name;\n                this._name = this._schema.name;\n                this._name = schema.overload_name ? `${this._name}.${schema.overload_name}` : this._name;\n                this.__name__ = `${this._schema.name.split('::')[1]}.${this._overloadname}`;\n                this.__module__ = overloadpacket.__module__;\n                op.__module__ = overloadpacket.__module__;\n                this.__qualname__ = self._name;\n                this.__annotations__ = {};\n                // this._defined_in_python = this.__qualname__ in torch.library._defs\n                let is_write = null;\n                for (const a of this._schema.arguments) {\n                    if (a.alias_info) {\n                        is_write = is_write === null ? a.alias_info.is_write : a.alias_info.is_write || is_write;\n                    }\n                }\n                this.is_view = is_write !== null && !is_write;\n            }\n            name() {\n                return this._name;\n            }\n        });\n        this.registerType('torch._ops.OpOverloadPacket', class {\n            constructor(qualified_op_name, op_name, op, overload_names) {\n                this._qualified_op_name = qualified_op_name;\n                this.__name__ = op_name;\n                this._op = op;\n                this._overload_names = overload_names;\n                this._dir = [];\n                this._has_torchbind_op_overload = this._schemas.some((schema) => this._has_script_object_arg(schema));\n            }\n            get _schemas() {\n                return this._overload_names.map((overload_name) => torch._C._get_schema(this._qualified_op_name, overload_name));\n            }\n            __getattr__(key) {\n                key = key === 'default' ? '' : key;\n                const op_dk_tags = torch._C._get_operation_overload(this._qualified_op_name, key);\n                if (op_dk_tags === null) {\n                    throw new python.Error(`The underlying op of '${this._qualified_op_name}' has no overload name '${key}'.`);\n                }\n                const [op_, op_dk_, tags] = op_dk_tags;\n                const schema = torch._C._get_schema(this._qualified_op_name, key);\n                const overload = this._has_script_object_arg(schema) ?\n                    new torch._ops.TorchBindOpOverload(this, op_, op_dk_, schema, tags) :\n                    new torch._ops.OpOverload(this, op_, op_dk_, schema, tags);\n                builtins.setattr(self, key, overload);\n                this._dir.push(key);\n                return overload;\n            }\n            _has_script_object_arg(schema) {\n                return schema.arguments.some((arg) => arg.type instanceof torch.ClassType);\n            }\n            __call__(...args) {\n                const fn = execution._operators.get(this._qualified_op_name);\n                if (!fn) {\n                    throw new python.Error(`Operator call '${this._qualified_op_name}' is not registered.`);\n                }\n                return fn(...args);\n            }\n        });\n        this.registerType('torch._ops._OpNamespace', class extends types.ModuleType {\n            constructor(name) {\n                super(`torch.ops.${name}`);\n                this.name = name;\n                this._dir = [];\n            }\n            __getattr__(op_name) {\n                const namespace_name = this.name;\n                const qualified_op_name = `${namespace_name}::${op_name}`;\n                const module_name = `${this.__module__}.${namespace_name}`;\n                let op = null;\n                let overload_names = null;\n                try {\n                    [op, overload_names] = this._get_packet(qualified_op_name, module_name);\n                } catch {\n                    // continue regardless of error\n                }\n                if (!op) {\n                    throw new python.Error(`Unknown operator type '${qualified_op_name}'.`);\n                }\n                op.__module__ = module_name;\n                const opoverloadpacket = new torch._ops.OpOverloadPacket(qualified_op_name, op_name, op, overload_names);\n                opoverloadpacket.__module__ = `${this.__module__}.${namespace_name}`;\n                builtins.setattr(this, op_name, opoverloadpacket);\n                this._dir.push(op_name);\n                return opoverloadpacket;\n            }\n            _get_packet(qualname, op_module) {\n                const [op, overload_names] = torch._C._jit_get_operation(qualname);\n                if (op) {\n                    // torch.jit._builtins._register_builtin(op, qualname);\n                }\n                op.__module__ = op_module;\n                return [op, overload_names];\n            }\n        });\n        this.registerType('torch._C.graph_node_list', class {\n            constructor(head) {\n                this.head = head;\n            }\n            front() {\n                return this.head.next;\n            }\n            end() {\n                return this.head.prev;\n            }\n            [Symbol.iterator]() {\n                let current = this.head.next;\n                const prev = this.head.prev;\n                return {\n                    next() {\n                        if (current !== prev) {\n                            const value = current;\n                            current = current.next;\n                            return { value, done: false };\n                        }\n                        return { done: true };\n                    }\n                };\n            }\n        });\n        this.registerType('torch.Graph', class {\n            constructor() {\n                this._next_unique = 0;\n                this._unique_names = new Map();\n                this._name_base_suffix = new Map();\n                this.all_nodes = new Set();\n                this.all_values = new Set();\n                this.all_blocks = new Set();\n                this._block = new torch.Block(this, null);\n                this._insert_before = this.return_node();\n            }\n            insert(opname, args, kwargs, range) {\n                return torch._C.emitBuiltinCall(range, this, opname, args, kwargs);\n            }\n            create(kind, ...args) {\n                let inputs = null;\n                let num_outputs = 1;\n                if (args.length === 2 && Array.isArray(args[0]) && typeof args[1] === 'number') {\n                    [inputs, num_outputs] = args;\n                } else if (args.length === 1) {\n                    if (typeof args[0] === 'number') {\n                        [num_outputs] = args;\n                    } else if (Array.isArray(args[0])) {\n                        [inputs] = args;\n                    }\n                }\n                const n = new torch.Node(this, kind);\n                if (inputs) {\n                    for (const i of inputs) {\n                        n.addInput(i);\n                    }\n                }\n                for (let i = 0; i < num_outputs; i++) {\n                    n.addOutput();\n                }\n                return n;\n            }\n            createClone(n, value_map, copy_blocks) {\n                copy_blocks = copy_blocks === undefined ? true : copy_blocks;\n                const r = n.allocNewInstance(this);\n                for (const o of n.outputs()) {\n                    r.addOutput().copyMetadata(o);\n                }\n                r.cloneFrom(n);\n                for (const i of n.inputs()) {\n                    r.addInput(value_map(i));\n                }\n                if (copy_blocks) {\n                    for (const b of n.blocks()) {\n                        r.addBlock().cloneFrom(b, value_map);\n                    }\n                }\n                return r;\n            }\n            createNone() {\n                const n = this.create('prim::Constant');\n                n.output().setType(torch.NoneType.get());\n                return n;\n            }\n            createUninitialized(typ) {\n                const n = this.create('prim::Uninitialized');\n                n.output().setType(typ);\n                return n;\n            }\n            createEnumValue(e) {\n                const enum_type = e.type().expect(torch.EnumType);\n                const n = this.create('prim::EnumValue', [e]);\n                n.output().setType(enum_type.getValueType());\n                return n;\n            }\n            createList(contained_type, values) {\n                const n = this.create('prim::ListConstruct', values);\n                for (const v of values) {\n                    if (!v.type().isSubtypeOf(contained_type)) {\n                        throw new python.Error('Invalid list item.');\n                    }\n                }\n                n.output().setType(torch.ListType.create(contained_type));\n                return n;\n            }\n            createListUnpack(v, size) {\n                const list_type = v.type().expect(torch.ListType);\n                const elem_type = list_type.getElementType();\n                const n = this.create('prim::ListUnpack', [v], 0);\n                for (let i = 0; i < size; i++) {\n                    n.addOutput().setType(elem_type);\n                }\n                return n;\n            }\n            createTuple(values, tuple_type) {\n                if (!tuple_type) {\n                    const types = values.map((v) => v.type());\n                    tuple_type = torch.TupleType.create(types);\n                }\n                const n = this.create('prim::TupleConstruct', values);\n                n.output().setType(tuple_type);\n                return n;\n            }\n            createTupleUnpack(v) {\n                const tt = v.type().expect(torch.TupleType);\n                const n = this.create('prim::TupleUnpack', [v], 0);\n                for (const element of tt.elements()) {\n                    n.addOutput().setType(element);\n                }\n                return n;\n            }\n            createTupleIndex(tup, idx, output_type) {\n                const n = this.create('prim::TupleIndex', [tup, idx]);\n                n.output().setType(output_type);\n                return n;\n            }\n            createTupleSlice(tup, beg, step_size, num_values) {\n                const new_vals = [];\n                const tt = tup.type().expect(torch.TupleType);\n                let i = beg;\n                for (let j = 0; j < num_values; j++) {\n                    const idx = this.insertConstant(new torch._C.IValue(i, 'Int'));\n                    const tupleIndex = this.insertNode(this.createTupleIndex(tup, idx, tt.elements()[i]));\n                    new_vals.push(tupleIndex.output());\n                    i += step_size;\n                }\n                const n = this.createTuple(new_vals);\n                return n;\n            }\n            createDict(key_type, value_type, keys, values) {\n                if (keys.length !== values.length) {\n                    throw new python.Error('Invalid dictionary size.');\n                }\n                const n = this.create('prim::DictConstruct');\n                const length = keys.length;\n                for (let i = 0; i < length; i++) {\n                    if (!keys[i].type().isSubtypeOf(key_type)) {\n                        throw new python.Error('Invalid key.');\n                    }\n                    if (!values[i].type().isSubtypeOf(value_type)) {\n                        throw new python.Error('Invalid value.');\n                    }\n                    n.addInput(keys[i]);\n                    n.addInput(values[i]);\n                }\n                n.output().setType(torch.DictType.create(key_type, value_type));\n                return n;\n            }\n            createObject(type) {\n                const node = this.create('prim::CreateObject');\n                node.output().setType(type);\n                return node;\n            }\n            createIsInstance(v, types) {\n                const n = this.create('prim::isinstance', [v], 1);\n                n.tys_('types', types);\n                n.output().setType(torch.BoolType.get());\n                return n;\n            }\n            createSetAttr(obj, field, newValue) {\n                const n = this.create('prim::SetAttr', [obj, newValue], 0);\n                n.s_('name', field);\n                return n;\n            }\n            createGetAttr(obj, field) {\n                const n = this.create('prim::GetAttr', [obj]);\n                n.s_('name', field);\n                const classType = obj.type();\n                const outputType = classType.getAttribute(field);\n                n.output().setType(outputType);\n                n.output().setDebugName(torch._C.normalizeAttrName(field));\n                return n;\n            }\n            createLoad(name, type) {\n                const n = this.create('prim::Load', [], 1);\n                n.s_('name', name);\n                n.output().setType(type);\n                return n;\n            }\n            createStore(name, v) {\n                const n = this.create('prim::Store', [v], 0);\n                n.s_('name', name);\n                return n;\n            }\n            inputs() {\n                return this._block.inputs();\n            }\n            outputs() {\n                return this._block.outputs();\n            }\n            nodes() {\n                return this._block.nodes();\n            }\n            param_node() {\n                return this._block.param_node();\n            }\n            return_node() {\n                return this._block.return_node();\n            }\n            block() {\n                return this._block;\n            }\n            addInput(name) {\n                return this._block.addInput(name);\n            }\n            insertNode(node) {\n                torch._C.AT_ASSERT(this._insert_before.inBlockList());\n                return node.insertBefore(this._insert_before);\n            }\n            insertConstant(val, loc, scope) {\n                return torch._C.insertConstant(this, val, loc, scope);\n            }\n            insertMethodCall(method_name, matched) {\n                const result = this.insertNode(this.create('prim::CallMethod', matched.inputs))\n                    .s_('name', method_name)\n                    .output().setType(matched.return_types[0]);\n                return result;\n            }\n            insertUncheckedCast(v, type) {\n                const n = this.create('prim::unchecked_cast', [v]);\n                this.insertNode(n);\n                n.output().setType(type);\n                return n.output();\n            }\n            insertToList(v, type) {\n                let dim = 0;\n                let ptr = type;\n                while (ptr instanceof torch.ListType) {\n                    ptr = ptr.getElementType();\n                    dim += 1;\n                }\n                let elem_ty = 0;\n                if (ptr instanceof torch.IntType) {\n                    elem_ty = 0;\n                } else if (ptr instanceof torch.FloatType) {\n                    elem_ty = 1;\n                } else if (ptr instanceof torch.BoolType) {\n                    elem_ty = 2;\n                } else if (ptr instanceof torch.ComplexType) {\n                    elem_ty = 3;\n                } else {\n                    throw new python.Error(`Unsupported list type '${type.kind()}'.`);\n                }\n                const dim_val = this.insertConstant(dim);\n                const elem_ty_val = this.insertConstant(elem_ty);\n                const n = this.insertNode(this.create('prim::tolist', [v, dim_val, elem_ty_val]));\n                n.output().setType(type);\n                return n.output();\n            }\n            insertFunctionCall(callee, matched) {\n                const func_name = callee.name();\n                const fn_constant = this.insertNode(this.create('prim::Constant')).s_('name', func_name).output().setType(torch._C.FunctionType.create(callee));\n                const inputs = [fn_constant, ...matched.inputs];\n                const result = this.insertNode(this.create('prim::CallFunction', inputs)).output().setType(matched.return_types[0]);\n                return result;\n            }\n            insertPoint() {\n                return this._insert_before;\n            }\n            setInsertPoint(node) {\n                if (node instanceof torch.Block) {\n                    node = node.return_node();\n                }\n                this._insert_before = node;\n            }\n            freeNode(n) {\n                this.all_nodes.delete(n);\n            }\n            freeValue(v) {\n                v.setDebugName('');\n                this.all_values.delete(v);\n            }\n            freeBlock(b) {\n                this.all_blocks.delete(b);\n            }\n            copy() {\n                const new_g = new torch.Graph();\n                new_g.cloneFrom(this);\n                return new_g;\n            }\n            cloneFrom(src) {\n                const env = (v) => {\n                    throw new python.Error(`Use of value '${v.debugName()}' not in scope.`);\n                };\n                this.block().cloneFrom(src.block(), env);\n            }\n            set_op_version(version) {\n                this._op_version = version;\n            }\n            get_op_version() {\n                return this._op_version;\n            }\n            print(out, print_source_locations) {\n                out.write('graph(');\n                torch._C.const_value_list_with_types(out, this.inputs(), ',\\n      ');\n                out.write('):\\n');\n                const groups = [];\n                for (const node of this.nodes()) {\n                    node.print(out, 1, groups, print_source_locations);\n                }\n                out.write('  return (');\n                torch._C.printValueRefs(out, this.outputs());\n                out.write(')\\n');\n                for (let i = 0; i < groups.length; i++) {\n                    const fg = groups[i];\n                    out.write('with ');\n                    out.write(fg.kind());\n                    out.write(`_${i} = `);\n                    out.write(fg.g('Subgraph'));\n                }\n                return out;\n            }\n            toString() {\n                const out = new io.StringIO();\n                this.print(out, true);\n                return out.toString();\n            }\n        });\n        this.registerType('torch.Block', class {\n            constructor(graph, node) {\n                this._graph = graph;\n                this._input = graph.create('prim::Param', 0);\n                this._output = graph.create('prim::Return', 0);\n                this._owning_node = node;\n                this._input.next = this._output;\n                this._input.prev = this._output;\n                this._output.next = this._input;\n                this._output.prev = this._input;\n                this._graph.all_blocks.add(this);\n                this._output._owning_block = this;\n                // output_.topo_position_ = kUpperBound;\n                this._input._owning_block = this;\n                // input_.topo_position_ = kLowerBound;\n            }\n            inputs() {\n                return this._input.outputs();\n            }\n            outputs() {\n                return this._output.inputs();\n            }\n            nodes() {\n                return new torch._C.graph_node_list(this._input);\n            }\n            return_node() {\n                return this._output;\n            }\n            param_node() {\n                return this._input;\n            }\n            owningNode() {\n                return this._owning_node;\n            }\n            owningGraph() {\n                return this._graph;\n            }\n            addInput(name) {\n                const value = this._input.addOutput();\n                value.setDebugName(name || '');\n                return value;\n            }\n            registerOutput(value) {\n                this._output.addInput(value);\n                return this.outputs().length - 1;\n            }\n            appendNode(n) {\n                if (n._graph !== this._graph || n.inBlockList()) {\n                    throw new python.Error('Node not in graph.');\n                }\n                n.insertBefore(this._output);\n                return n;\n            }\n            cloneFrom(src, value_map) {\n                const local_map = new Map();\n                const env = (v) => {\n                    if (local_map.has(v)) {\n                        return local_map.get(v);\n                    }\n                    return value_map(v);\n                };\n                const graph = this.owningGraph();\n                for (const input of src.inputs()) {\n                    local_map.set(input, this.addInput().copyMetadata(input));\n                }\n                for (const node of src.nodes()) {\n                    const new_node = this.appendNode(graph.createClone(node, env));\n                    for (let i = 0; i < node.outputs().length; i++) {\n                        const oo = node.outputs()[i];\n                        const no = new_node.outputs()[i];\n                        local_map.set(oo, no);\n                        no.copyMetadata(oo);\n                    }\n                }\n                for (const output of src.outputs()) {\n                    this.registerOutput(env(output));\n                }\n            }\n            eraseOutput(i) {\n                this._output.removeInput(i);\n            }\n            destroy() {\n                this._output.removeAllInputs();\n                for (const n of this.nodes()) {\n                    n.destroy();\n                }\n                this._output.destroy();\n                this._input.destroy();\n                this._graph.freeBlock(this);\n            }\n        });\n        this.registerType('torch.Node', class {\n            constructor(graph, kind) {\n                this._kind = kind;\n                this._graph = graph;\n                this._owning_block = null;\n                this._values = new Map();\n                this._inputs = [];\n                this._outputs = [];\n                this._blocks = [];\n                this._graph.all_nodes.add(this);\n                this._prev = null;\n                this._next = null;\n                this._source_range = null;\n                this._op = null;\n            }\n            owningGraph() {\n                return this._graph;\n            }\n            owningBlock() {\n                return this._owning_block;\n            }\n            kind() {\n                return this._kind;\n            }\n            schema() {\n                if (this._op) {\n                    return this._op.schema();\n                }\n                // Node::schema() throws while torch.Node.schema() does not.\n                const op = this.maybeOperator();\n                if (op) {\n                    return op.schema();\n                }\n                return null;\n                // return this.getOperator().schema();\n            }\n            hasNamedInput(name) {\n                for (const argument of this.schema().arguments) {\n                    if (argument.name === name) {\n                        return true;\n                    }\n                }\n                return false;\n            }\n            matches(schema) {\n                if (torch._C.isBlockListedSchema(schema)) {\n                    return false;\n                }\n                if (this.kind() !== schema.name) {\n                    return false;\n                }\n                const actuals = this.inputs();\n                const formals = schema.arguments;\n                if (actuals.length < formals.length) {\n                    return false;\n                }\n                const type_env = new Map();\n                for (let i = 0; i < formals.length; i++) {\n                    let formal = formals[i].type;\n                    const matched_type = torch._C.matchTypeVariables(formal, actuals[i].type(), type_env);\n                    if (!matched_type.success()) {\n                        return false;\n                    }\n                    const resolved = torch._C.tryEvalTypeVariables(formal, type_env);\n                    if (resolved) {\n                        formal = resolved;\n                    }\n                    if (!actuals[i].type().isSubtypeOf(formal)) {\n                        return false;\n                    }\n                }\n                if (!schema.is_vararg && actuals.length !== formals.length) {\n                    return false;\n                }\n                return true;\n            }\n            mustBeNone() {\n                return this._kind === 'prim::AutogradZero' ||\n                    (this.outputs().length === 1 && this.output().type() === torch.NoneType.get()) ||\n                    (this._kind === 'prim::Constant' && !this.hasAttributes() && this.output().type() instanceof torch.OptionalType);\n            }\n            maybeSchema() {\n                const op = this.maybeOperator();\n                if (op) {\n                    return op.schema();\n                }\n                return null;\n            }\n            maybeOperator() {\n                if (!this._op) {\n                    const candidates = torch._C.getAllOperatorsFor(this.kind());\n                    for (const candidate of candidates) {\n                        if (this.matches(candidate.schema())) {\n                            this._op = candidate;\n                            break;\n                        }\n                    }\n                }\n                return this._op;\n            }\n            getOperator() {\n                const maybe = this.maybeOperator();\n                if (maybe) {\n                    return maybe;\n                }\n                throw new python.Error(`Schema not found for node '${this.kind()}'.`);\n            }\n            getOperation() {\n                return this.getOperator().getOperation(this);\n            }\n            isNondeterministic() {\n                const schema = this.maybeSchema();\n                if (!this.kind().startsWith('aten::')) {\n                    return false;\n                }\n                if (!schema) {\n                    return false;\n                }\n                const schema_info = new torch._C.SchemaInfo(schema);\n                if (this.hasNamedInput('train')) {\n                    throw new python.Error('Not Implemented.');\n                    // const value = constant_as<bool>(this.namedInput(\"train\"));\n                    // if (value) {\n                    //    schema_info.addArgumentValue('train', value);\n                    // }\n                }\n                return schema_info.is_nondeterministic();\n            }\n            hasSideEffects() {\n                switch (this._kind) {\n                    case 'prim::PythonOp':\n                    case 'prim::IgnoredPythonOp':\n                    case 'prim::Print':\n                    case 'prim::RaiseException':\n                    case 'aten::warn':\n                    case 'aten::save':\n                    case 'aten::manual_seed':\n                    case 'prim::AddStatValue':\n                    case 'prim::TimePoint':\n                    case 'prim::CallFunction':\n                    case 'prim::CallMethod':\n                    case 'prim::BailoutTemplate':\n                    case 'prim::BailOut':\n                    case 'prim::rpc_async':\n                    case 'prim::rpc_sync':\n                    case 'prim::rpc_remote':\n                    case 'aten::wait':\n                    case 'cuda::set_stream':\n                    case 'cuda::_set_device':\n                    case 'cuda::_current_device':\n                    case 'cuda::synchronize':\n                    case 'prim::Enter':\n                    case 'prim::Exit':\n                        return true;\n                    default:\n                        break;\n                }\n                const op = this.maybeOperator();\n                if (!op) {\n                    torch._C.TORCH_INTERNAL_ASSERT(this._kind.startsWith('prim::'), `Only prim ops are allowed to not have a registered operator but '${this._kind}' doesn't have one either. We don't know if this op has side effects.`);\n                    return false;\n                }\n                if (this._kind.startsWith('prim::') || this._kind.startsWith('aten::') || this._kind.startsWith('cuda::')) {\n                    torch._C.TORCH_INTERNAL_ASSERT(op.aliasAnalysisKind() === 'INTERNAL_SPECIAL_CASE' || op.aliasAnalysisKind() === 'FROM_SCHEMA' || op.aliasAnalysisKind() === 'CONSERVATIVE', `aten:: and prim:: ops should have AliasAnalysisKind::INTERNAL_SPECIAL_CASE, AliasAnalysisKind::FROM_SCHEMA or AliasAnalysisKind::CONSERVATIVE but '${this._kind}' has '${op.aliasAnalysisKind()}.`);\n                }\n                switch (op.aliasAnalysisKind()) {\n                    case 'PURE_FUNCTION':\n                    case 'FROM_SCHEMA':\n                    case 'INTERNAL_SPECIAL_CASE':\n                        return false;\n                    case 'CONSERVATIVE':\n                        return true;\n                    default:\n                        break;\n                }\n                torch._C.TORCH_INTERNAL_ASSERT(false, 'Unhandled AliasAnalysisKind case.');\n                return false;\n            }\n            inputs() {\n                return this._inputs;\n            }\n            outputs() {\n                return this._outputs;\n            }\n            input(i) {\n                if (i === undefined) {\n                    torch._C.AT_ASSERT(this._inputs.length === 1);\n                    return this._inputs[0];\n                }\n                return this._inputs[i];\n            }\n            output(i) {\n                if (i === undefined) {\n                    torch._C.AT_ASSERT(this._outputs.length === 1);\n                    return this._outputs[0];\n                }\n                return this._outputs[i];\n            }\n            hasUses() {\n                for (const o of this.outputs()) {\n                    if (o.uses().length > 0) {\n                        return true;\n                    }\n                }\n                return false;\n            }\n            blocks() {\n                return this._blocks;\n            }\n            insertInput(i, value) {\n                torch._C.AT_ASSERT(this._graph === value.owningGraph());\n                this._op = null;\n                for (let use_itr = i; use_itr < this._inputs.length; use_itr++) {\n                    const use = this.findUseForInput(use_itr);\n                    use.offset += 1;\n                }\n                this._inputs.splice(i, 0, value);\n                value._uses.push(new torch.Use(this, i));\n                return value;\n            }\n            addInput(value) {\n                torch._C.AT_ASSERT(this._graph === value.owningGraph());\n                this._op = null;\n                const use = new torch.Use(this, this._inputs.length);\n                value.uses().push(use);\n                this._inputs.push(value);\n                return value;\n            }\n            addOutput() {\n                const value = new torch.Value(this, this._outputs.length);\n                this._outputs.push(value);\n                return value;\n            }\n            addBlock() {\n                this._op = null;\n                this._blocks.push(new torch.Block(this.owningGraph(), this));\n                return this._blocks[this._blocks.length - 1];\n            }\n            get prev() {\n                return this._prev;\n            }\n            set prev(value) {\n                this._prev = value;\n            }\n            get next() {\n                return this._next;\n            }\n            set next(value) {\n                this._next = value;\n            }\n            insertBefore(n) {\n                if (!n.inBlockList()) {\n                    throw new python.Error('Node not in block.');\n                }\n                this.insertAfter(n.prev);\n                return this;\n            }\n            insertAfter(n) {\n                torch._C.AT_ASSERT(!this.inBlockList() || n.inBlockList());\n                torch._C.AT_ASSERT(n.owningBlock());\n                torch._C.TORCH_INTERNAL_ASSERT(n.kind() !== 'prim::Return', 'Attempting to insert a Node after the Return node or before the Param node.');\n                this._owning_block = n.owningBlock();\n                const next = n.next;\n                n.next = this;\n                this.prev = n;\n                this.next = next;\n                next.prev = this;\n                // this.assignTopoPosition();\n                return this;\n            }\n            allocNewInstance(g) {\n                return new torch.Node(g, this.kind());\n            }\n            cloneFrom(s) {\n                this._source_range = s._source_range;\n                if (s._scope && !s._scope.isBlank()) {\n                    this._scope = s._scope;\n                }\n                this.copyAttributes(s);\n                this._callstack = s._callstack;\n            }\n            copyAttributes(rhs) {\n                this._values = new Map(rhs._values);\n                return this;\n            }\n            dropInput(i) {\n                torch._C.AT_ASSERT(i < this._inputs.length);\n                const input_node = this._inputs[i];\n                const use_it = this.findUseForInput(i);\n                input_node._uses = input_node._uses.filter((use) => use !== use_it);\n                this._inputs[i] = null;\n                return input_node;\n            }\n            eraseOutput(i) {\n                torch._C.AT_ASSERT(i < this._outputs.length);\n                // torch._C.AT_ASSERT(this._outputs[i].uses().length === 0);\n                this._op = null;\n                const n = this._outputs[i];\n                this._outputs.splice(i, 1);\n                this.owningGraph().freeValue(n);\n                for (let j = i; j < this._outputs.length; j++) {\n                    this._outputs[j]._offset--;\n                }\n            }\n            eraseBlock(i) {\n                this._op = null;\n                const n = this._blocks[i];\n                this._blocks.splice(i, 1);\n                n.destroy();\n            }\n            findUseForInput(i) {\n                const input_uses = this._inputs[i]._uses;\n                for (const use_it of input_uses) {\n                    if (use_it.user === this && use_it.offset === i) {\n                        return use_it;\n                    }\n                }\n                throw new python.Error('Input use not found.');\n            }\n            moveBefore(n) {\n                this.removeFromList();\n                this.insertBefore(n);\n            }\n            removeInput(i) {\n                this._op = null;\n                this.dropInput(i);\n                for (let j = i + 1; j < this._inputs.length; j++) {\n                    const it = this.findUseForInput(j);\n                    it.offset--;\n                }\n                this._inputs.splice(i, 1);\n            }\n            removeAllInputs() {\n                this._op = null;\n                for (let i = 0; i < this._inputs.length; i++) {\n                    this.dropInput(i);\n                }\n                this._inputs = [];\n            }\n            inBlockList() {\n                return this.next !== null;\n            }\n            removeFromList() {\n                this._owning_block = null;\n                const next = this.next;\n                const prev = this.prev;\n                prev.next = next;\n                next.prev = prev;\n                this.next = null;\n                this.prev = null;\n            }\n            destroy() {\n                while (this.outputs().length > 0) {\n                    this.eraseOutput(this.outputs().length - 1);\n                }\n                while (this.blocks().length > 0) {\n                    this.eraseBlock(this.blocks().length - 1);\n                }\n                this.removeAllInputs();\n                if (this.inBlockList()) {\n                    this.removeFromList();\n                }\n                this._graph.freeNode(this);\n            }\n            replaceAllUsesWith(n) {\n                torch._C.AT_ASSERT(this.outputs().length === n.outputs().length);\n                const nOutputs = this.outputs().length;\n                for (let i = 0; i < nOutputs; i++) {\n                    this.outputs()[i].replaceAllUsesWith(n.outputs()[i]);\n                }\n            }\n            s_(name, value) {\n                this._values.set(name, [value, 's']);\n                return this;\n            }\n            s(name) {\n                return this._values.get(name)[0];\n            }\n            ss_(name, value) {\n                this._values.set(name, [value, 'ss']);\n                return this;\n            }\n            ss(name) {\n                return this._values.get(name)[0];\n            }\n            i_(name, value) {\n                this._values.set(name, [value, 'i']);\n                return this;\n            }\n            i(name) {\n                return this._values.get(name)[0];\n            }\n            f_(name, value) {\n                this._values.set(name, [value, 'f']);\n                return this;\n            }\n            f(name) {\n                return this._values.get(name)[0];\n            }\n            c_(name, value) {\n                this._values.set(name, [value, 'c']);\n                return this;\n            }\n            c(name) {\n                return this._values.get(name)[0];\n            }\n            t_(name, value) {\n                this._values.set(name, [value, 't']);\n                return this;\n            }\n            t(name) {\n                return this._values.get(name)[0];\n            }\n            tys_(name, value) {\n                this._values.set(name, [value, 'tys']);\n                return this;\n            }\n            tys(name) {\n                return this._values.get(name)[0];\n            }\n            ival_(name, value) {\n                this._values.set(name, [value, 'ival']);\n                return this;\n            }\n            ival(name) {\n                return this._values.get(name)[0];\n            }\n            hasAttribute(name) {\n                return this._values.has(name);\n            }\n            hasAttributes() {\n                return this._values.size > 0;\n            }\n            attributeNames() {\n                return Array.from(this._values.keys());\n            }\n            kindOf(name) {\n                return this._values.get(name)[1];\n            }\n            setSourceRange(r) {\n                torch._C.AT_ASSERT(r instanceof torch._C.SourceRange);\n                this._source_range = r;\n                return this;\n            }\n            sourceRange() {\n                if (this._source_range) {\n                    return this._source_range;\n                }\n                return new torch._C.SourceRange();\n            }\n            print_attributes(out, ignore_subgraph) {\n                ignore_subgraph = ignore_subgraph || false;\n                out.write('[');\n                const names = this.attributeNames();\n                for (let i = 0; i < names.length; i++) {\n                    const name = names[i];\n                    if (ignore_subgraph && name === 'Subgraph') {\n                        continue;\n                    }\n                    if (i > 0) {\n                        out.write(', ');\n                    }\n                    out.write(`${name}=`);\n                    this.printAttrValue(out, name);\n                }\n                out.write(']');\n            }\n            printTypeList(out, items) {\n                out.write('[');\n                for (let i = 0; i < items.length; i++) {\n                    const item = items[i];\n                    if (i++ > 0) {\n                        out.write(', ');\n                    }\n                    out.write(item.str());\n                }\n                out.write(']');\n            }\n            printAttrValue(out, name) {\n                const kind = this.kindOf(name);\n                switch (kind) {\n                    case 'c': case 'cs': case  'f': case  'fs': case  'i': case  'is':\n                    case 'ss': case  'ival': case 'ty':\n                        out.write(this[kind](name));\n                        break;\n                    case 's':\n                        out.write(`\"${this.s(name)}\"`);\n                        break;\n                    case  't':\n                        out.write(`\"{}\"`);\n                        break;\n                    case 'ts': out.write('[<Tensors>]'); break;\n                    case 'g': out.write('[<Graph>]'); break;\n                    case 'gs': out.write('[<Graphs>]'); break;\n                    case 'tys': this.printTypeList(out, this.tys(name)); break;\n                    default: throw new python.Error(`Unknown attribute kind '${kind}'.`);\n                }\n            }\n            print(out, level, groups, print_source_locations, print_attributes, print_scopes, print_body) {\n                print_source_locations = print_source_locations === false ? false : true;\n                print_attributes = print_attributes === false ? false : true;\n                print_scopes = print_scopes === false ? false : true;\n                print_body = print_body === false ? false : true;\n                const outs = this.outputs();\n                torch._C.indent(out, level);\n                torch._C.const_value_list_with_types(out, outs, ', ');\n                out.write(' = ');\n                if (this.kind() === 'prim::PythonOp') {\n                    throw new python.Error('Not implemented.');\n                } else if (this.hasAttribute('Subgraph') && groups) {\n                    throw new python.Error('Not implemented.');\n                } else {\n                    out.write(this.kind());\n                    if (print_attributes && this.hasAttributes()) {\n                        this.print_attributes(out);\n                    }\n                }\n                out.write('(');\n                torch._C.printValueRefs(out, this.inputs());\n                out.write(')');\n                if (print_scopes) {\n                    //\n                }\n                if (print_source_locations) {\n                    let r = this.sourceRange();\n                    if (r.source()) {\n                        const orig = this.sourceRange().source().findSourceRangeThatGenerated(r);\n                        if (orig) {\n                            r = orig;\n                        }\n                    }\n                    const file_line_col = r.file_line_col();\n                    if (file_line_col !== null) {\n                        const [filename, line, col] = file_line_col;\n                        out.write(` # ${filename}:${line}:${col}`);\n                    }\n                }\n                if (!print_body) {\n                    return out;\n                }\n                out.write('\\n');\n                for (let i = 0; i < this.blocks().length; i++) {\n                    const b = this.blocks().at(i);\n                    torch._C.indent(out, level + 1);\n                    out.write(`block${i}(`);\n                    torch._C.const_value_list_with_types(out, b.inputs());\n                    out.write('):\\n');\n                    for (const nested of b.nodes()) {\n                        nested.print(out, level + 2, groups);\n                    }\n                    torch._C.indent(out, level + 2);\n                    out.write('-> (');\n                    torch._C.printValueRefs(out, b.outputs());\n                    out.write(')\\n');\n                }\n                return out;\n            }\n            toString() {\n                const out = new io.StringIO();\n                this.print(out, 0, true);\n                return out.toString();\n            }\n        });\n        this.registerType('torch.Value', class {\n            constructor(node, offset) {\n                this._node = node;\n                this._offset = offset;\n                this._unique = node._graph._next_unique++;\n                this._uses = [];\n                this._node._graph.all_values.add(this);\n            }\n            unique() {\n                return this._unique;\n            }\n            node() {\n                return this._node;\n            }\n            owningGraph() {\n                return this._node.owningGraph();\n            }\n            uses() {\n                return this._uses;\n            }\n            hasUses() {\n                return this._uses.length > 0;\n            }\n            mustBeNone() {\n                return this.type() instanceof torch.NoneType || this._node.mustBeNone();\n            }\n            mustNotBeNone() {\n                return this._node.kind() !== 'prim::AutogradAdd' &&\n                    this.type() !== torch.NoneType.get() &&\n                    !(this.type() instanceof torch.OptionalType) &&\n                    !(this.type() instanceof torch.UnionType && this.type().expect(torch.UnionType).canHoldType(torch.NoneType.get()));\n            }\n            isValidName(name) {\n                if (name.length === 0) {\n                    return true;\n                }\n                if (torch._C.isNumber(name)) {\n                    return false;\n                }\n                return true;\n            }\n            hasDebugName() {\n                return this._unique_name && this._unique_name.length > 0;\n            }\n            setDebugName(name) {\n                if (!this.isValidName(name)) {\n                    throw new python.Error(`Invalid name '${name}'.`);\n                }\n                const names = this.node().owningGraph()._unique_names;\n                if (this.hasDebugName()) {\n                    names.delete(this._unique_name);\n                    this._unique_name = '';\n                }\n                if (!name) {\n                    return this;\n                }\n                const old_owner_of_name = names.get(name);\n                if (old_owner_of_name) {\n                    let suffix = 1;\n                    let name_base = name;\n                    const last_dot_pos = name.lastIndexOf('.');\n                    if (last_dot_pos !== -1) {\n                        if (/^\\d+$/.test(name.substring(last_dot_pos + 1))) {\n                            suffix = Number(name.substring(last_dot_pos + 1));\n                            name_base = name.substring(0, last_dot_pos);\n                        }\n                    }\n                    const names_suffixes = this.node().owningGraph()._name_base_suffix;\n                    if (names_suffixes.has(name_base)) {\n                        suffix = Math.max(suffix, names_suffixes.get(name_base));\n                    }\n                    let replacement_name = null;\n                    do {\n                        replacement_name = `${name_base}.${suffix++}`;\n                    } while (names.has(replacement_name));\n                    names_suffixes.set(name_base, suffix);\n                    old_owner_of_name.setDebugName(replacement_name);\n                }\n                names.set(name, this);\n                this._unique_name = name;\n                return this;\n            }\n            debugName() {\n                if (this.hasDebugName()) {\n                    return this._unique_name;\n                }\n                return this.unique().toString();\n            }\n            type() {\n                return this._type;\n            }\n            setType(type) {\n                // torch._C.AT_ASSERT(type instanceof torch.Type);\n                if (type instanceof torch._C.DynamicType) {\n                    type = type.fallback();\n                }\n                this._type = type;\n                for (const use of this._uses) {\n                    use.user._op = null;\n                }\n                return this;\n            }\n            set value(value) { // remove\n                if (value instanceof torch.Value) {\n                    throw new python.Error('Value cannot be a value.');\n                }\n                this._value = value;\n            }\n            get value() { // remove\n                return this._value;\n            }\n            replaceFirstUseWith(newValue) {\n                torch._C.AT_ASSERT(this.owningGraph() === newValue.owningGraph());\n                const [u] = this.uses();\n                u.user._inputs[u.offset] = newValue;\n                newValue._uses.push(u);\n                this._uses.shift();\n            }\n            replaceAllUsesWith(newValue) {\n                while (this.uses().length > 0) {\n                    this.replaceFirstUseWith(newValue);\n                }\n            }\n            copyMetadata(from) {\n                this.setType(from.type());\n                if (from.hasDebugName()) {\n                    this.setDebugName(from.debugName());\n                }\n                return this;\n            }\n            toString() {\n                return `${this.debugName()} : ${this.type().toString()}`;\n            }\n        });\n        this.registerType('torch.Use', class {\n            constructor(user, offset) {\n                this.user = user;\n                this.offset = offset;\n            }\n        });\n        this.registerType('torch._C.IValue', class {\n            constructor(value, tag) {\n                this.value = value;\n                if (tag) {\n                    this.tag = tag;\n                } else if (value === undefined) {\n                    this.tag = 'None';\n                    this.value = null;\n                } else if (typeof value === 'boolean') {\n                    this.tag = 'Bool';\n                } else if (typeof value === 'string') {\n                    this.tag = 'String';\n                } else if (value instanceof torch.Tensor) {\n                    this.tag = 'Tensor';\n                } else if (value instanceof torch.ScriptObject) {\n                    this.tag = 'Object';\n                } else if (Array.isArray(value)) {\n                    this.tag = 'GenericList';\n                } else if (value instanceof torch._C.Tuple) {\n                    this.tag = 'Tuple';\n                } else if (value instanceof torch.device) {\n                    this.tag = 'Device';\n                } else if (Number.isInteger(value)) {\n                    this.tag = 'Int';\n                } else if (typeof value === 'number') {\n                    this.tag = 'Double';\n                } else if (value instanceof builtins.complex) {\n                    this.tag = 'ComplexDouble';\n                } else if (value instanceof torch._C.EnumHolder) {\n                    this.tag = 'Enum';\n                } else {\n                    throw new python.Error('Unsupported type.');\n                }\n            }\n            isNone() {\n                return this.tag === 'None';\n            }\n            isBool() {\n                return this.tag === 'Bool';\n            }\n            toBool() {\n                return this.value;\n            }\n            isObject() {\n                return this.tag === 'Object';\n            }\n            toObject() {\n                return this.value;\n            }\n            isTensor() {\n                return this.tag === 'Tensor';\n            }\n            toTensor() {\n                return this.value;\n            }\n            isDouble() {\n                return this.tag === 'Double';\n            }\n            toDouble() {\n                return this.value;\n            }\n            isComplexDouble() {\n                return this.tag === 'ComplexDouble' || this.tag === 'Complex';\n            }\n            toComplexDouble() {\n                return this.value;\n            }\n            isInt() {\n                return this.tag === 'Int';\n            }\n            toInt() {\n                if (this.isInt()) {\n                    return this.value;\n                } else if (this.isSymInt()) {\n                    return this.toSymInt().guard_int(/* __FILE__, __LINE__ */);\n                }\n                throw new python.Error('Expected int.');\n            }\n            isString() {\n                return this.tag === 'String';\n            }\n            toStringRef() {\n                return this.value;\n            }\n            isList() {\n                return this.tag === 'GenericList';\n            }\n            toList() {\n                return this.value;\n            }\n            toListRef() {\n                return this.value;\n            }\n            isBoolList() {\n                return this.value instanceof torch._C.List && this.value.elementType() instanceof torch.BoolType;\n            }\n            isIntList() {\n                return this.value instanceof torch._C.List && this.value.elementType() instanceof torch.IntType;\n            }\n            isDoubleList() {\n                return this.value instanceof torch._C.List && this.value.elementType() instanceof torch.FloatType;\n            }\n            isDevice() {\n                return this.tag === 'Device';\n            }\n            toDevice() {\n                return this.value;\n            }\n            isGenerator() {\n                return this.tag === 'Generator';\n            }\n            isStream() {\n                return this.tag === 'Stream';\n            }\n            isGenericDict() {\n                return this.tag === 'GenericDict';\n            }\n            isEnum() {\n                return this.tag === 'Enum';\n            }\n            toEnumHolder() {\n                return this.value;\n            }\n            isTuple() {\n                return this.tag === 'Tuple';\n            }\n            toTupleRef() {\n                return this.value;\n            }\n            isCustomClass() {\n                return torch._C.isCustomClass(this);\n            }\n            equals(rhs) {\n                switch (this.tag) {\n                    case 'None': return rhs.isNone();\n                    case 'Bool': return rhs.isBool() && this.toBool() === rhs.toBool();\n                    case 'Int': return rhs.isInt() && this.toInt() === rhs.toInt();\n                    case 'Double': return rhs.isDouble() && this.toDouble() === rhs.toDouble();\n                    case 'String': return rhs.isString() && this.toString() === rhs.toString();\n                    case 'Tensor': return rhs.isTensor() && this.toTensor() === rhs.toTensor();\n                    case 'Object': return rhs.isObject() && this.toObject() === rhs.toObject();\n                    case 'Device': return rhs.isObject() && this.toDevice() === rhs.toDevice();\n                    case 'GenericList': {\n                        if (rhs.isList()) {\n                            const a = this.toList();\n                            const b = rhs.toList();\n                            return (a.length === b.length) && a.every((v, i) => v === b[i]);\n                        }\n                        return false;\n                    }\n                    default: throw new python.Error(`IValue.equals() not implemented for '${this.tag}.`);\n                }\n            }\n            is(rhs) {\n                return this.equals(rhs);\n            }\n            type() {\n                switch (this.tag) {\n                    case 'None': return torch.NoneType.get();\n                    case 'Bool': return torch.BoolType.get();\n                    case 'Int': return torch.IntType.get();\n                    case 'Double': return torch.FloatType.get();\n                    case 'String': return torch.StringType.get();\n                    case 'Device': return torch.DeviceObjType.get();\n                    case 'Tuple': return torch.TupleType.create(this.value.elements().map((ivalue) => ivalue.type()));\n                    case 'Enum': return this.toEnumHolder().type();\n                    case 'GenericList': return torch.ListType.create(this.toList().elementType());\n                    default: throw new python.Error(`IValue.type('${this.tag}') not implemented.`);\n                }\n            }\n        });\n        this.registerFunction('torch._C.indent', (out, level) => {\n            for (let i = 0; i < level; i++) {\n                out.write('  ');\n            }\n            return out;\n        });\n        this.registerFunction('torch._C.printValueRef', (out, n) => {\n            out.write(`%${n.debugName()}`);\n        });\n        this.registerFunction('torch._C.printValueRefs', (out, nodes) => {\n            for (let i = 0; i < nodes.length; i++) {\n                const n = nodes[i];\n                if (i > 0) {\n                    out.write(', ');\n                }\n                torch._C.printValueRef(out, n);\n            }\n            return out;\n        });\n        this.registerFunction('torch._C.const_value_list_with_types', (out, values, delim) => {\n            for (let i = 0; i < values.length; i++) {\n                const n = values[i];\n                if (i > 0) {\n                    out.write(delim);\n                }\n                torch._C.printValueRef(out, n);\n                out.write(' : ');\n                out.write(n.type().str());\n            }\n        });\n        this.register('torch.jit._script');\n        this.register('torch.jit._trace');\n        this.registerType('torch._C.Parser', class {\n            constructor(source) {\n                this.L = source;\n            }\n            parse() {\n                const p = ast.parse(this.L.text_str(), this.L.filename());\n                return p;\n            }\n            parseExp() {\n                const expr = ast.parse(this.L.text_str());\n                return expr.body[0].value;\n            }\n        });\n        this.registerType('torch._C.StringCordView', class {\n        });\n        this.registerType('torch._C.Source', class {\n            constructor(text_view, filename, starting_line_no, gen_ranges /*, copies_str */) {\n                if (text_view instanceof Uint8Array) {\n                    const decoder = new TextDecoder('utf-8');\n                    this._text_view = decoder.decode(text_view);\n                } else if (typeof text_view === 'string') {\n                    this._text_view = text_view;\n                } else {\n                    throw new python.Error('Invalid text view.');\n                }\n                this._filename = filename;\n                this._starting_line_no = starting_line_no;\n                this._gen_ranges = gen_ranges;\n                this.calc_line_start_offsets();\n            }\n            text_str() {\n                return this._text_view;\n            }\n            size() {\n                return this._text_view.length;\n            }\n            filename() {\n                return this._filename;\n            }\n            calc_line_start_offsets() {\n                let pos = 0;\n                this._line_starting_offsets = [0];\n                while ((pos = this._text_view.indexOf('\\n', pos)) !== -1) {\n                    pos += 1;\n                    this._line_starting_offsets.push(pos);\n                }\n            }\n            offset_for_line(line) {\n                return this._line_starting_offsets[line];\n            }\n            lineno_for_offset(offset) {\n                const iter = this._line_starting_offsets.findIndex((value) => value > offset);\n                return (iter === -1 ? this._line_starting_offsets.length : iter) - 1;\n            }\n            lineno_to_source_lineno(lineno) {\n                if (this._filename) {\n                    return lineno + this._starting_line_no;\n                }\n                return lineno;\n            }\n            findSourceRangeThatGenerated(range) {\n                if (!this._gen_ranges) {\n                    return null;\n                }\n                return this._gen_ranges.findSourceRangeThatGenerated(range);\n            }\n        });\n        this.registerType('torch._C.SourceRange', class {\n            constructor(...args) {\n                if (args.length === 0) {\n                    this._source_view = null;\n                } else if (args.length === 2) {\n                    let node = null;\n                    [this._source_view, node] = args;\n                    this._start = this._source_view.offset_for_line(node.lineno - 1) + (node.col_offset - 1);\n                    this._end = this._source_view.offset_for_line(node.end_lineno - 1) + (node.end_col_offset - 1);\n                } else if (args.length === 3) {\n                    [this._source_view, this._start, this._end] = args;\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n            source() {\n                return this._source_view;\n            }\n            file_line_col() {\n                if (!this._source_view || this.source().filename() === null) {\n                    return null;\n                }\n                const lineno = this._source_view.lineno_for_offset(this._start);\n                const col_offset = this._start - this._source_view.offset_for_line(lineno);\n                return [this._source_view.filename(), this._source_view.lineno_to_source_lineno(lineno), col_offset];\n            }\n            start() {\n                return this._start;\n            }\n            toString() {\n                const loc = this.file_line_col();\n                return loc ? `${loc[0]}:${loc[1]}:${loc[2]}` : '';\n            }\n        });\n        this.registerType('torch._C.QualifiedName', class {\n            constructor(...args) {\n                let name = null;\n                if (args.length === 1 && typeof args[0] === 'string') {\n                    [name] = args;\n                } else if (args.length === 1 && Array.isArray(args[0]) && args[0].every((arg) => typeof arg === 'string')) {\n                    name = args[0].join('.');\n                } else {\n                    name = `${args[0].qualifiedName()}.${args[1]}`;\n                }\n                const index = name.lastIndexOf('.');\n                this._qualifiedName = name;\n                this._prefix = index === -1 ? '' : name.substring(0, index);\n                this._name = index === -1 ? name : name.substring(index + 1);\n            }\n            qualifiedName() {\n                return this._qualifiedName; // \"foo.bar.baz\"\n            }\n            prefix() {\n                return this._prefix; // \"foo.bar\"\n            }\n            name() {\n                return this._name; // \"baz\"\n            }\n            atoms() {\n                return this._qualifiedName.split('.');\n            }\n        });\n        this.registerType('torch._C.Resolver', class {\n            resolveValue() {\n                throw new python.Error('Not implemented.');\n            }\n            resolveType() {\n                throw new python.Error('Not implemented.');\n            }\n        });\n        this.registerFunction('torch._C.registerCustomClass', (class_type) => {\n            torch._C.customClasses = torch._C.customClasses || new Map();\n            torch._C.TORCH_INTERNAL_ASSERT(class_type.name());\n            const name = class_type.name().qualifiedName();\n            torch._C.TORCH_CHECK(!torch._C.customClasses.has(name));\n            torch._C.customClasses.set(name, class_type);\n        });\n        this.registerFunction('torch._C.getCustomClass', (class_name) => {\n            torch._C.customClasses = torch._C.customClasses || new Map();\n            const ret = torch._C.customClasses.has(class_name) ? torch._C.customClasses.get(class_name) : null;\n            return ret;\n        });\n        this.registerFunction('torch._C.isCustomClass', (v) => {\n            return v.isObject() && v.toObject().type().name() && torch._C.getCustomClass(v.toObject().type().name().qualifiedName());\n        });\n        this.registerType('torch._C.SourceImporter', class extends torch._C.Resolver {\n            constructor(cu, constant_table, source_loader, version) {\n                super();\n                this._cu = cu;\n                this._constant_table = constant_table;\n                this._source_loader = source_loader;\n                this._version = version;\n                this._loaded_sources = new Set();\n                this._sources = new Map();\n                const sources = this._sources;\n                ast.AST.prototype.range = function() {\n                    if (!this._range) {\n                        if (sources.has(this.filename)) {\n                            const source_view = sources.get(this.filename);\n                            this._range = new torch._C.SourceRange(source_view, this);\n                        } else {\n                            this._range = new torch._C.SourceRange();\n                        }\n                    }\n                    return this._range;\n                };\n                this._to_be_defined = new Map();\n                this._env = new Map([\n                    ['torch', new torch._C.BuiltinModule('aten', version)],\n                    ['ops', new torch._C.OpsValue(version)],\n                    ['CONSTANTS', new torch._C.ConstantTableValue(constant_table)],\n                    ['fork', torch._C.SpecialFormValue.create('prim::fork')],\n                    ['awaitable', torch._C.SpecialFormValue.create('prim::awaitable')],\n                    ['annotate', torch._C.SpecialFormValue.create('prim::annotate')],\n                    ['unchecked_cast', torch._C.SpecialFormValue.create('prim::unchecked_cast')],\n                    ['uninitialized', torch._C.SpecialFormValue.create('prim::Uninitialized')],\n                ]);\n            }\n            loadType(name) {\n                const type_parser = new torch._C.ScriptTypeParser(this);\n                return type_parser.parseType(name.qualifiedName());\n            }\n            resolveType(name) {\n                name = new torch._C.QualifiedName(name);\n                return this.findNamedType(name);\n            }\n            resolveValue(name, m, loc) {\n                if (this._env.has(name)) {\n                    return this._env.get(name);\n                }\n                const graph = m.graph();\n                switch (name) {\n                    case 'inf': return new torch._C.SimpleValue(graph.insertConstant(Infinity /* 'std::numeric_limits<double>::infinity()' */, loc));\n                    case 'nan': return new torch._C.SimpleValue(graph.insertConstant(NaN /* 'std::numeric_limits<double>::quiet_NaN()' */, loc));\n                    case 'infj': return new torch._C.SimpleValue(graph.insertConstant('c10::complex<double>(0, std::numeric_limits<double>::infinity())', loc));\n                    case 'nanj': return new torch._C.SimpleValue(graph.insertConstant('c10::complex<double>(0, std::numeric_limits<double>::quiet_NaN()', loc));\n                    case '__torch__': return new torch._C.ClassNamespaceValue(new torch._C.QualifiedName(name), this);\n                    default: return null;\n                }\n            }\n            findNamedType(name) {\n                const custom_class = torch._C.getCustomClass(name.qualifiedName());\n                if (custom_class) {\n                    return custom_class;\n                }\n                this.parseSourceIfNeeded(name.prefix());\n                const key = name.qualifiedName();\n                const it = this._to_be_defined.get(key);\n                if (it && it instanceof ast.ClassDef) {\n                    this._to_be_defined.delete(key);\n                    this.importNamedType(name.prefix(), it);\n                }\n                return this._cu.get_type(name);\n            }\n            importNamedType(qualifier, class_def) {\n                const qualified_name = new torch._C.QualifiedName(`${qualifier}.${class_def.name}`);\n                if (class_def.bases.length === 0) {\n                    this.importClass(qualified_name, class_def, false);\n                    return;\n                }\n                const superclass_name = class_def.bases[0].id;\n                if (superclass_name === 'Module') {\n                    this.importClass(qualified_name, class_def, true);\n                } else if (superclass_name === 'NamedTuple') {\n                    this.importNamedTuple(qualified_name, class_def);\n                } else if (superclass_name === 'Interface') {\n                    // this._cu.define_interface(qualified_name, class_def, shared_from_this(), is_module=false);\n                } else if (superclass_name === 'ModuleInterface') {\n                    // this._cu.define_interface(qualified_name, class_def, shared_from_this(), is_module=true);\n                } else if (superclass_name === 'Enum') {\n                    this.importEnum(qualified_name, class_def);\n                } else {\n                    throw new python.Error('TorchScript does not support class inheritance.');\n                }\n            }\n            importClass(qualified_classname, class_def, is_module) {\n                if (qualified_classname.prefix().startsWith('__torch__.torch.classes')) {\n                    return;\n                }\n                const parameter_names = new Set();\n                const buffer_names = new Set();\n                const methods = [];\n                const method_resolvers = [];\n                const attributes = [];\n                const constants = [];\n                const pre_hook_names = new Set();\n                const pre_hook_def_map = new Map();\n                const hook_names = new Set();\n                const hook_def_map = new Map();\n                const class_type = torch.ClassType.create(qualified_classname.qualifiedName(), this._cu, is_module);\n                for (const stmt of class_def.body) {\n                    if (stmt instanceof ast.Assign || stmt instanceof ast.AnnAssign) {\n                        let target = null;\n                        let annotation = null;\n                        let value = null;\n                        if (stmt instanceof ast.Assign) {\n                            [target] = stmt.targets;\n                            value = stmt.value;\n                        } else {\n                            target = stmt.target;\n                            annotation = stmt.annotation;\n                            value = stmt.value;\n                        }\n                        if (target instanceof ast.Name) {\n                            const name = this._cu.execution.identifier(target);\n                            switch (name) {\n                                case '__annotations__': {\n                                    continue;\n                                }\n                                case '__parameters__': {\n                                    for (const elt of value.elts) {\n                                        parameter_names.add(elt.value);\n                                    }\n                                    break;\n                                }\n                                case '__buffers__': {\n                                    for (const elt of value.elts) {\n                                        buffer_names.add(elt.value);\n                                    }\n                                    break;\n                                }\n                                case '__forward_pre_hooks__': {\n                                    for (const elt of value.elts) {\n                                        pre_hook_names.add(elt.value);\n                                    }\n                                    break;\n                                }\n                                case '__forward_hooks__': {\n                                    for (const elt of value.elts) {\n                                        hook_names.add(elt.value);\n                                    }\n                                    break;\n                                }\n                                default: {\n                                    const fixed_up = this.attributeAssignmentSpecialHandlingHack(qualified_classname, stmt);\n                                    if (fixed_up) {\n                                        attributes.push({ name: fixed_up.target.id, value: fixed_up.value, annotation: fixed_up.annotation });\n                                    } else if (value) {\n                                        constants.push({ name, value, annotation });\n                                    } else {\n                                        attributes.push({ name, value, annotation });\n                                    }\n                                    break;\n                                }\n                            }\n                        } else if (target instanceof ast.Subscript && target.value instanceof ast.Name && target.value.id === '__annotations__') {\n                            const name = target.slice.value;\n                            attributes.push({ name, value, annotation: stmt.value });\n                            continue;\n                        } else {\n                            throw new python.Error('Unexpected statement kind in module metadata.');\n                        }\n                    } else if (stmt instanceof ast.FunctionDef) {\n                        const def = stmt;\n                        const def_name = def.name;\n                        if (pre_hook_names.has(def_name)) {\n                            pre_hook_def_map.set(def_name, def);\n                        } else if (hook_names.has(def_name)) {\n                            hook_def_map.set(def_name, def);\n                        } else {\n                            methods.push(def);\n                            method_resolvers.push(this);\n                        }\n                    } else {\n                        throw new python.Error('Unexpected statement kind in class body.');\n                    }\n                }\n                const type_parser = new torch._C.ScriptTypeParser(this);\n                for (const assign of attributes) {\n                    const name = assign.name;\n                    const annotation = type_parser.parseTypeFromExpr(assign.annotation);\n                    const is_parameter = parameter_names.has(name);\n                    const is_buffer = buffer_names.has(name);\n                    class_type.addAttribute(name, annotation, is_parameter, is_buffer);\n                }\n                for (const constant of constants) {\n                    class_type.addConstant(constant.name, constant.value);\n                }\n                this._cu.register_type(class_type);\n                const self = new torch._C.SimpleSelf(class_type);\n                this._cu.define(qualified_classname, [], [], methods, method_resolvers, self, false, this._version);\n            }\n            importEnum(qualified_name, enum_def) {\n                const names_values = [];\n                let value_type = null;\n                const set_or_check_type = (t) => {\n                    if (!value_type) {\n                        value_type = t;\n                    } else if (value_type !== t) {\n                        throw new python.Error('Enum class with varying value types are not supported.');\n                    }\n                };\n                for (const stmt of enum_def.body) {\n                    if (stmt instanceof ast.Assign === false) {\n                        throw new python.Error('Unexpected statement in Enum class body.');\n                    }\n                    const assign = stmt;\n                    const name = assign.targets[0].id;\n                    let ivalue = null;\n                    const rhs = assign.value;\n                    switch (rhs.type) {\n                        case 'str':\n                            ivalue = new torch._C.IValue(rhs.value, 'String');\n                            set_or_check_type(torch.StringType.get());\n                            break;\n                        case 'int':\n                            ivalue = new torch._C.IValue(rhs.value, 'Int');\n                            set_or_check_type(torch.IntType.get());\n                            break;\n                        case 'float':\n                            ivalue = new torch._C.IValue(rhs.value, 'Double');\n                            set_or_check_type(torch.FloatType.get());\n                            break;\n                        default:\n                            throw new python.Error(`Unsupported enum value type '${rhs.type}'.`);\n                    }\n                    names_values.push([name, ivalue]);\n                }\n                if (!value_type) {\n                    throw new python.Error('No enum values defined.');\n                }\n                const enum_type = torch.EnumType.create(qualified_name, value_type, names_values, this._cu);\n                this._cu.register_type(enum_type);\n            }\n            importNamedTuple(qualified_name, named_tuple_def) {\n                const type_parser = new torch._C.ScriptTypeParser(this);\n                const field_names = [];\n                const field_types = [];\n                const field_defaults = [];\n                for (const stmt of named_tuple_def.body) {\n                    if (stmt instanceof ast.AnnAssign === false) {\n                        throw new python.Error('Unexpected statement in NamedTuple body.');\n                    }\n                    const assign = stmt;\n                    const target = this._cu.execution.identifier(stmt.target);\n                    // const annotation = this._cu.execution.type(stmt.annotation);\n                    const type = type_parser.parseTypeFromExpr(assign.annotation);\n                    field_names.push(target);\n                    // field_types.push(annotation);\n                    field_types.push(type);\n                }\n                const tt = torch.TupleType.createNamed(qualified_name.qualifiedName(), field_names, field_types, field_defaults);\n                this._cu.register_type(tt);\n            }\n            importFunction(qualifier, def) {\n                const definitions = [def];\n                const resolvers = [this];\n                this._cu.define(new torch._C.QualifiedName(qualifier), /*properties=*/[], /*propResolvers=*/[], definitions, resolvers, null);\n            }\n            parseSourceIfNeeded(qualifier) {\n                if (!qualifier || this._loaded_sources.has(qualifier)) {\n                    return;\n                }\n                this._loaded_sources.add(qualifier);\n                const src = this._source_loader(qualifier);\n                if (!src) {\n                    return;\n                }\n                this._sources.set(src.filename(), src);\n                const p = new torch._C.Parser(src);\n                const L = p.parse();\n                this.parsePossibleVersionNumber(p);\n                for (const stmt of L.body) {\n                    if (stmt instanceof ast.ClassDef) {\n                        const name = `${qualifier}.${stmt.name}`;\n                        this._to_be_defined.set(name, stmt);\n                    } else if (stmt instanceof ast.FunctionDef) {\n                        const name = `${qualifier}.${stmt.name}`;\n                        this._to_be_defined.set(name, stmt);\n                    }\n                }\n            }\n            parsePossibleVersionNumber(/* p */) {\n            }\n            parseImports(/* p */) {\n            }\n            attributeAssignmentSpecialHandlingHack(qualified_classname, assign) {\n                const replacements = new Map([\n                    ['__torch__.torch.ao.nn.quantized.modules.linear.LinearPackedParams', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.LinearPackedParamsBase']],\n                    ['__torch__.torch.ao.nn.quantized.modules.linear.Linear', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.LinearPackedParamsBase']],\n                    ['__torch__.torch.ao.nn.quantized.dynamic.modules.linear.Linear', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.LinearPackedParamsBase']],\n                    ['__torch__.torch.ao.nn.quantized.modules.conv.Conv2d', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.Conv2dPackedParamsBase']],\n                    ['__torch__.torch.nn.intrinsic.quantized.modules.conv_relu.ConvReLU2d', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.Conv2dPackedParamsBase']],\n                    ['__torch__.torch.ao.nn.quantized.modules.conv.Conv3d', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.Conv3dPackedParamsBase']],\n                    ['__torch__.torch.nn.intrinsic.quantized.modules.conv_relu.ConvReLU3d', ['_packed_params', 'Tensor', '__torch__.torch.classes.quantized.Conv3dPackedParamsBase']],\n                    ['__torch__.torch.nn.quantized.modules.linear.LinearPackedParams', [\"_packed_params\", \"Tensor\", \"__torch__.torch.classes.quantized.LinearPackedParamsBase\"]],\n                    [\"__torch__.torch.nn.quantized.modules.linear.Linear\", [\"_packed_params\", \"Tensor\", \"__torch__.torch.classes.quantized.LinearPackedParamsBase\"]],\n                    [\"__torch__.torch.nn.quantized.modules.conv.Conv2d\", [\"_packed_params\", \"Tensor\", \"__torch__.torch.classes.quantized.Conv2dPackedParamsBase\"]],\n                    [\"__torch__.torch.nn.quantized.modules.conv.Conv3d\", [\"_packed_params\", \"Tensor\", \"__torch__.torch.classes.quantized.Conv3dPackedParamsBase\"]],\n                    [\"__torch__.torch.nn.quantized.dynamic.modules.linear.Linear\", [\"_packed_params\", \"Tensor\", \"__torch__.torch.classes.quantized.LinearPackedParamsBase\"]]\n                ]);\n                const mangleRe = /\\.___torch_mangle_\\d+/g;\n                const demangled_classname = qualified_classname.qualifiedName().replace(mangleRe, '');\n                if (replacements.has(demangled_classname)) {\n                    const lhs = assign.target;\n                    if (!assign.annotation || assign.annotation instanceof ast.Name === false) {\n                        return null;\n                    }\n                    const type = assign.annotation.id;\n                    const [attr_name, expected_type, replacement_type] = replacements.get(demangled_classname);\n                    if (lhs.id === attr_name && type === expected_type) {\n                        const p = new torch._C.Parser(new torch._C.Source(replacement_type));\n                        const typename_expr = p.parseExp();\n                        return new ast.AnnAssign(lhs, typename_expr, assign.value, lhs instanceof ast.Name);\n                    }\n                }\n                return null;\n            }\n            LEGACY_import_methods(mod, src) {\n                const self = new torch._C.SimpleSelf(mod.type());\n                const prefix = mod.type().name();\n                const p = new torch._C.Parser(src);\n                const L = p.parse();\n                this.parsePossibleVersionNumber(L);\n                this.parseImports(L);\n                const definitions = [];\n                const resolvers = [];\n                for (const def of L.body) {\n                    if (def instanceof ast.FunctionDef) {\n                        definitions.push(def);\n                        resolvers.push(this);\n                    }\n                }\n                this._cu.define(prefix, /*properties=*/[], /*propResolvers=*/[], definitions, resolvers, self);\n            }\n            findFunction(name) {\n                this.parseSourceIfNeeded(name.prefix());\n                const key = name.qualifiedName();\n                const it = this._to_be_defined.get(key);\n                if (it && it instanceof ast.FunctionDef) {\n                    this._to_be_defined.delete(key);\n                    this.importFunction(name.prefix(), it);\n                }\n                return this._cu.find_function(name);\n            }\n        });\n        this.registerType('torch._C.FunctionResolver', class extends torch._C.Resolver {\n            constructor(otherResolver, functionTable) {\n                super();\n                this._otherResolver = otherResolver;\n                this._functionTable = functionTable;\n            }\n            resolveValue(name, m, loc) {\n                const it = this._functionTable.get(name);\n                if (it) {\n                    return new torch._C.FunctionValue(it);\n                }\n                return this._otherResolver.resolveValue(name, m, loc);\n            }\n            resolveType(name, loc) {\n                return this._otherResolver.resolveType(name, loc);\n            }\n        });\n        this.registerType('torch._C.SourceRangeDeserializer', class {\n            constructor(text_table) {\n                this.cached_sources = new Map();\n                this._text_table = text_table || [];\n            }\n            deserialize(iv) {\n                torch._C.TORCH_INTERNAL_ASSERT(iv.length === 3);\n                const [file, start, end] = iv;\n                const source = this.deserialize_source(file);\n                return new torch._C.SourceRange(source, start, end);\n            }\n            deserialize_source(iv) {\n                const tup = iv;\n                if (this.cached_sources.has(tup)) {\n                    return this.cached_sources.get(tup);\n                }\n                let source = null;\n                const tup_elems = tup;\n                torch._C.TORCH_INTERNAL_ASSERT(tup_elems.length === 3);\n                if (this._text_table.length > 0) {\n                    const [textIndex, fnameIndex, starting_line_no] = tup_elems;\n                    torch._C.TORCH_CHECK(fnameIndex < this._text_table.length);\n                    const filename = this._text_table[fnameIndex];\n                    const pieces = [];\n                    const strs = [];\n                    for (const i of textIndex) {\n                        pieces.push(this._text_table[i]);\n                        strs.push(this._text_table[i]);\n                    }\n                    // const str_cord = new torch._C.StringCordView(pieces, strs);\n                    source = new torch._C.Source(pieces.join(''), filename, starting_line_no);\n                } else {\n                    const [text, filename, starting_line_no] = tup_elems;\n                    source = new torch._C.Source(text, filename, starting_line_no);\n                }\n                this.cached_sources.set(tup, source);\n                return source;\n            }\n        });\n        this.registerType('torch._C.SourceRangeUnpickler', class {\n        });\n        this.registerType('torch._C.ConcreteSourceRangeUnpickler', class extends torch._C.SourceRangeUnpickler {\n            constructor (data) {\n                super();\n                this.data = data;\n                this.deserializer = null;\n                this.unpickled_records = null;\n            }\n            unpickle() {\n                if (this.unpickled_records) {\n                    return;\n                }\n                const unpickler = new pickle.Unpickler(this.data);\n                const ivalues = unpickler.load();\n                torch._C.TORCH_CHECK(ivalues.length > 0);\n                this.unpickled_records = [];\n                let lines = null;\n                if (ivalues[0] === 'FORMAT_WITH_STRING_TABLE') {\n                    this.deserializer = new torch._C.SourceRangeDeserializer(ivalues[1]);\n                    lines = ivalues[2];\n                } else {\n                    this.deserializer = new torch._C.SourceRangeDeserializer();\n                    lines = ivalues;\n                }\n                for (const tup_elems of lines) {\n                    const [offset, range] = tup_elems;\n                    const source_range = this.deserializer.deserialize(range);\n                    this.unpickled_records.push([offset, source_range]);\n                }\n            }\n            findSourceRangeThatGenerated(range) {\n                this.unpickle();\n                const start = range.start();\n                const records = this.unpickled_records;\n                for (let i = 0; i < records.length; i++) {\n                    const [offset, target] = records[i];\n                    const next = i < records.length - 1 ? records[i + 1][0] : range.source().size();\n                    if (start >= offset && start < next) {\n                        return target;\n                    }\n                }\n                return null;\n            }\n        });\n        this.registerFunction('torch._C.qualifierToArchivePath', (qualifier, export_prefix) => {\n            return `${export_prefix}${qualifier.replace(/\\./g, '/')}.py`;\n        });\n        this.registerFunction('torch._C.findSourceInArchiveFromQualifier', (reader, export_prefix, qualifier) =>{\n            const path = torch._C.qualifierToArchivePath(qualifier, export_prefix);\n            if (!reader.has_record(path)) {\n                return null;\n            }\n            const stream = reader.get_record(path);\n            let gen_ranges = null;\n            const debug_file = `${path}.debug_pkl`;\n            if (reader.has_record(debug_file)) {\n                const debug_stream = reader.get_record(debug_file);\n                gen_ranges = new torch._C.ConcreteSourceRangeUnpickler(debug_stream.peek());\n            }\n            return new torch._C.Source(stream.peek(), path, 1, gen_ranges);\n        });\n        this.registerType('torch._C.ScriptModuleDeserializer', class {\n            constructor(cu, reader, pickle_dir_prefix, tensor_dir_prefix, storage_context) {\n                this._compilation_unit = cu;\n                this._reader = reader;\n                this._storage_context = storage_context;\n                this._code_prefix = !pickle_dir_prefix && !tensor_dir_prefix ? 'code/' : '.data/ts_code/code/';\n                this._pickle_dir_prefix = pickle_dir_prefix || '';\n                this._tensor_dir_prefix = tensor_dir_prefix || '';\n                this._constant_table = [];\n                const SourceLoader = (qualifier) => {\n                    return torch._C.findSourceInArchiveFromQualifier(this._reader, this._code_prefix, qualifier);\n                };\n                this._source_importer = new torch._C.SourceImporter(this._compilation_unit, this._constant_table, SourceLoader, reader.version());\n            }\n            deserialize() {\n                const execution = this._compilation_unit.execution;\n                const code_prefix = this._code_prefix;\n                for (const name of this._reader.get_all_records()) {\n                    if (name.startsWith(code_prefix) && name.endsWith('.py')) {\n                        const file = name.substring(code_prefix.length);\n                        const stream = this._reader.get_record(name);\n                        const buffer = stream.peek();\n                        execution.add(file, buffer);\n                    }\n                }\n                const torch = execution.import('torch');\n                execution.builtins.torch = torch;\n                execution.builtins.Tensor = torch.Tensor;\n                execution.builtins.ops = torch.ops;\n                execution.builtins.inf = torch.inf;\n                execution.builtins.CONSTANTS = {};\n                execution._resolver = this._source_importer;\n                if (this._reader.has_record('model.json')) {\n                    return this.LEGACY_deserialize();\n                }\n                const constants = this.readArchive('constants');\n                for (let i = 0; i < constants.length; i++) {\n                    let val = constants[i];\n                    if (val && val.__class__ && val.__class__.__module__.startsWith('__torch__.torch.classes.')) {\n                        const type = this._source_importer.resolveType(`${val.__class__.__module__}.${val.__class__.__name__}`);\n                        const obj = torch.ScriptObject.create(type);\n                        obj._ivalue = val;\n                        val = obj;\n                    }\n                    execution.builtins.CONSTANTS[`c${i}`] = val;\n                    this._constant_table.push(val);\n                }\n                const obj = this.readArchive('data');\n                const convertObject = (obj) => {\n                    if (obj.__class__) {\n                        const name = `${obj.__class__.__module__}.${obj.__class__.__name__}`;\n                        const type = this._source_importer.loadType(new torch._C.QualifiedName(name));\n                        const module = type.is_module() ? new torch.ScriptModule(type, this._compilation_unit) : new torch.ScriptObject(type);\n                        for (let i = 0; i < type.numAttributes(); i++) {\n                            const k = type.getAttributeName(i);\n                            const t = type.getAttribute(i);\n                            const v = obj[k];\n                            if (t instanceof torch.ClassType) {\n                                module.__setattr__(k, convertObject(v));\n                            } else {\n                                if (t instanceof torch.TensorType && v && v.__class__ && v instanceof torch.Tensor === false && v.__class__.__module__ === '__torch__.torch.classes.quantized') {\n                                    const name = `${v.__class__.__module__}.${v.__class__.__name__}`;\n                                    type._attributes[i].type = this._source_importer.resolveType(name);\n                                }\n                                module.__setattr__(k, obj[k]);\n                            }\n                        }\n                        for (const [key, value] of Object.entries(Object.getPrototypeOf(obj))) {\n                            if (value && value.__class__ === builtins.method) {\n                                module[key] = value;\n                            }\n                        }\n                        return module;\n                    }\n                    throw new python.Error('Module class not found.');\n                };\n                return convertObject(obj);\n            }\n            LEGACY_deserialize() {\n                // https://github.com/pytorch/pytorch/blob/5e69e11d098a2cfccc8a59377c431e9c71cab9a8/torch/csrc/jit/serialization/import_legacy.cpp#L88\n                const execution = this._compilation_unit.execution;\n                const caffe2 = execution.proto.caffe2;\n                const torch = execution.import('torch');\n                const stream = this._reader.get_record('model.json');\n                const buffer = stream.peek();\n                const decoder = new TextDecoder('utf-8');\n                const content = decoder.decode(buffer);\n                const obj = JSON.parse(content);\n                const model = execution.proto.torch.ModelDef.decodeJson(obj);\n                const tensorTypeMap = new Map([\n                    [caffe2.TensorProto.DataType.FLOAT, 'Float'],\n                    [caffe2.TensorProto.DataType.FLOAT16, 'Half'],\n                    [caffe2.TensorProto.DataType.DOUBLE, 'Double'],\n                    [caffe2.TensorProto.DataType.INT8, 'Char'],\n                    [caffe2.TensorProto.DataType.INT32, 'Int'],\n                    [caffe2.TensorProto.DataType.INT64, 'Long']\n                ]);\n                const tensor_table = (model.tensors || []).map((constant) => {\n                    const key = constant.data.key;\n                    if (!tensorTypeMap.has(constant.data_type)) {\n                        throw new python.Error(`Unsupported tensor data type '${constant.data_type}'.`);\n                    }\n                    const type = tensorTypeMap.get(constant.data_type);\n                    const shape = constant.dims ? constant.dims.map((dim) => parseInt(dim, 10)) : null;\n                    const strides = constant.strides ? constant.strides.map((dim) => parseInt(dim, 10)) : null;\n                    const storage_type = execution.resolve(`torch.${type}Storage`);\n                    const size = (shape || []).reduce((a, b) => a * b, 1);\n                    const offset = parseInt(constant.offset, 10) || 0;\n                    const storage = new storage_type(size);\n                    const itemsize = storage.dtype.itemsize();\n                    const stream = this._reader.get_record(key);\n                    if (stream) {\n                        const buffer = stream.peek();\n                        const length = size * itemsize;\n                        const data = buffer.slice(offset, offset + length);\n                        storage._set_cdata(data);\n                    }\n                    const tensor = torch._utils._rebuild_tensor(storage, 0, shape, strides);\n                    tensor.name = key;\n                    return tensor;\n                });\n                execution.builtins.CONSTANTS = {};\n                for (let i = 0; i < tensor_table.length; i++) {\n                    execution.builtins.CONSTANTS[`c${i}`] = tensor_table[i];\n                }\n                const attributes = [];\n                if (this._reader.has_record('attributes.pkl')) {\n                    const stream = this._reader.get_record('attributes.pkl');\n                    const buffer = stream.peek();\n                    const unpickler = new pickle.Unpickler(buffer);\n                    const obj = unpickler.load();\n                    attributes.push(...obj);\n                }\n                this._LEGACY_moduleStack = ['__torch__'];\n                const module_def = model.main_module;\n                for (const tensor of tensor_table) {\n                    this._constant_table.push(tensor);\n                }\n                return this.LEGACY_convertModule(module_def);\n            }\n            LEGACY_convertModule(module_def) {\n                const atoms = new torch._C.QualifiedName(module_def.name).atoms();\n                const numPushed = atoms.length;\n                for (const atom of atoms) {\n                    const sanitized = /^\\d+$/.test(atom) ? `_${atom}` : atom;\n                    this._LEGACY_moduleStack.push(sanitized);\n                }\n                const qn = new torch._C.QualifiedName(this._LEGACY_moduleStack);\n                const module = new torch.ScriptModule(qn, this._compilation_unit);\n                for (const sub_def of module_def.submodules || []) {\n                    const submodule = this.LEGACY_convertModule(sub_def);\n                    module.register_module(sub_def.name, submodule);\n                }\n                for (const param_def of module_def.parameters || []) {\n                    const tensor = this._constant_table[Number(param_def.tensor_id)];\n                    if (param_def.isBuffer) {\n                        module.register_buffer(param_def.name, tensor);\n                    } else {\n                        module.register_parameter(param_def.name, tensor, false);\n                    }\n                }\n                // const typeParser = new torch._C.ScriptTypeParser(this._source_importer);\n                for (const attr_def of module_def.attributes || []) {\n                    if (module.hasattr(attr_def.name)) {\n                        continue;\n                    }\n                    throw new python.Error('Not implemented.');\n                    // IValue ivalue;\n                    // if (attr_def.id() >= 0) {\n                    //    ivalue = LEGACY_pickled_ivalues_.at(attr_def.id());\n                    // }\n                    // module.register_attribute(attr_def.name, typeParser.parseType(attr_def.type), ivalue);\n                }\n                if (module_def.torchscript_arena) {\n                    const key = module_def.torchscript_arena.key;\n                    const file = key.substring('code/'.length);\n                    const name = file.replace(/\\.py$/, '').split('/').join('.');\n                    const code = execution.import(name);\n                    if (code.forward.__class__ === execution.builtins.function) {\n                        module.forward = code.forward;\n                    }\n                }\n                // let gen_ranges = null;\n                if (module_def.torchscript_debug_arena) {\n                    throw new python.Error('Not implemented.');\n                    //const [data, size] = reader_->getRecord(module_def.torchscript_debug_arena().key());\n                    //gen_ranges = std::make_shared<ConcreteSourceRangeUnpickler>(std::move(data), size);\n                }\n                if (module_def.torchscript_arena) {\n                    const filename = module_def.torchscript_arena.key;\n                    const stream = this._reader.get_record(filename);\n                    const data = stream.peek();\n                    const src = new torch._C.Source(data, filename);\n                    this._source_importer.LEGACY_import_methods(module, src);\n                }\n                if (module_def.get_state_attribute_id) {\n                    throw new python.Error('Not implemented.');\n                    // LEGACY_moduleSetState(module, LEGACY_pickled_ivalues_.at(module_def.get_state_attribute_id()));\n                }\n                /*\n                const module_type = module._ivalue().type();\n                const N = module_type.numAttributes();\n                for (let i = 0; i < N; ++i) {\n                    const v = module._ivalue().getSlot(i);\n                    if (module_type.getAttribute(i) instanceof torch.OptionalType === false) {\n                        torch._C.TORCH_CHECK(!v.isNone());\n                    }\n                }\n                */\n                for (let i = 0; i < numPushed; i++) {\n                    this._LEGACY_moduleStack.pop();\n                }\n                return module;\n            }\n            readArchive(archive_name) {\n                const type_resolver = (qn) => {\n                    const cls = this._source_importer.loadType(qn);\n                    return cls;\n                };\n                const ObjLoaderFunc = (/* type, ivalue */) => {\n                };\n                return this.readArchiveAndTensors(archive_name, this._pickle_dir_prefix, this._tensor_dir_prefix, type_resolver, ObjLoaderFunc, this._device, this._reader, null, this._storage_context);\n            }\n            readArchiveAndTensors(archive_name, pickle_prefix, tensor_prefix, type_resolver, obj_loader, device, stream_reader, type_parser, storage_context) {\n                const picklename = `${pickle_prefix + archive_name}.pkl`;\n                const stream = stream_reader.get_record(picklename);\n                if (!stream) {\n                    throw new python.Error(`File '${picklename}' is not found.`);\n                }\n                const buffer = stream.peek();\n                const tensor_dir_path = tensor_prefix ? tensor_prefix : `${archive_name}/`;\n                const read_record = (name) => {\n                    const stream = stream_reader.get_record(tensor_dir_path + name);\n                    return stream.length <= 0x40000 ? stream.peek() : stream;\n                };\n                const execution = this._compilation_unit.execution;\n                const pickle = execution.__import__('pickle');\n                const Unpickler = class extends pickle.Unpickler {\n                    find_class(module, name) {\n                        return super.find_class(module, name);\n                    }\n                };\n                const unpickler = new Unpickler(buffer);\n                unpickler.persistent_load = (saved_id) => {\n                    if (saved_id[0] !== 'storage') {\n                        throw new python.Error(`Unsupported persistent load type '${saved_id[0]}'.`);\n                    }\n                    const [, storage_type, key, , size] = saved_id;\n                    if (storage_context && storage_context.has_storage(key)) {\n                        return storage_context.get_storage(key);\n                    }\n                    const storage = new storage_type(size);\n                    if (!storage._set_cdata) {\n                        throw new python.Error(`'${storage_type.__name__}._set_cdata' is not a function.`);\n                    }\n                    const storage_ptr = read_record(key);\n                    storage._set_cdata(storage_ptr);\n                    if (storage_context) {\n                        storage_context.add_storage(key);\n                    }\n                    return storage;\n                };\n                return unpickler.load();\n            }\n        });\n        this.registerType('torch._C.WithInsertPoint', class {\n            constructor(...args) {\n                let n = null;\n                if (args.length === 1 && args[0] instanceof torch.Block) {\n                    const [b] = args;\n                    n = b.return_node();\n                } else if (args.length === 1 && args[0] instanceof torch.Node) {\n                    [n] = args;\n                } else {\n                    throw new python.Error('Invalid arguments.');\n                }\n                this._prev = n.owningGraph().insertPoint();\n                n.owningGraph().setInsertPoint(n);\n            }\n            dispose() {\n                this._prev.owningGraph().setInsertPoint(this._prev);\n            }\n        });\n        this.registerType('torch._C.Environment', class {\n            constructor(method, resolver, b, next) {\n                this.method = method;\n                this.resolver = resolver;\n                this.b = b;\n                this.next = next;\n                this.value_table = new Map();\n                this.type_table = new Map();\n                this.error_messages = new Map();\n            }\n            setVariableTypeError(name, msg) {\n                /* eslint-disable consistent-this */\n                let runner = this;\n                /* eslint-enable consistent-this */\n                while (runner.next) {\n                    runner = runner.next;\n                }\n                runner.error_messages.set(name, msg);\n            }\n            insertLoad(name, type) {\n                const g = this.b.owningGraph();\n                const load = g.insertNode(g.createLoad(name, type));\n                if (torch._C.meaningfulName(name)) {\n                    load.output().setDebugName(name);\n                }\n                return new torch._C.SimpleValue(load.output());\n            }\n            insertStore(name, loc, v, type) {\n                const g = this.b.owningGraph();\n                g.insertNode(g.createStore(name, v)).setSourceRange(loc);\n                this.type_table.set(name, type);\n            }\n            findInThisFrame(name) {\n                if (this.value_table.has(name)) {\n                    return this.value_table.get(name);\n                }\n                if (this.type_table.has(name)) {\n                    return this.insertLoad(name, this.type_table.get(name));\n                }\n                return null;\n            }\n            findInParentFrame(name) {\n                return this.next ? this.next.findInAnyFrame(name) : null;\n            }\n            setType(name, type) {\n                this.type_table.set(name, type);\n            }\n            findInAnyFrame(name) {\n                /* eslint-disable consistent-this */\n                const self = this;\n                /* eslint-enable consistent-this */\n                for (let runner = self; runner; runner = runner.next) {\n                    const r = runner.findInThisFrame(name);\n                    if (r) {\n                        return r;\n                    }\n                }\n                return null;\n            }\n            block() {\n                return this.b;\n            }\n            setVar(loc, name, value) {\n                this.setSugaredVar(loc, name, new torch._C.SimpleValue(value), null);\n            }\n            setSugaredVar(loc, name, value, annotated_type) {\n                let as_simple_value = torch._C.asSimple(value);\n                if (as_simple_value && !as_simple_value.hasDebugName() && torch._C.meaningfulName(name) && as_simple_value.node().owningBlock() === this.block()) {\n                    as_simple_value.setDebugName(name);\n                }\n                const parent = this.findInParentFrame(name);\n                if (parent) {\n                    if (annotated_type) {\n                        throw new python.Error('Type already defined in an outer block.');\n                    }\n                    if (!as_simple_value) {\n                        throw new python.Error('Only reassignments to first-class values are allowed.');\n                    }\n                    const simple_parent = torch._C.asSimple(parent);\n                    if (!simple_parent) {\n                        throw new python.Error('Only reassignments to first-class values are allowed.');\n                    }\n                    const parent_type = torch._C.unshapedType(simple_parent.type());\n                    as_simple_value = torch._C.tryConvertToType(loc, this.b.owningGraph(), parent_type, as_simple_value, /*allow_conversions=*/true);\n                    if (!as_simple_value.type().isSubtypeOf(parent_type)) {\n                        throw new python.Error('Incompatible types.');\n                    }\n                }\n                if (as_simple_value) {\n                    if (annotated_type && !as_simple_value.type().isSubtypeOf(annotated_type)) {\n                        throw new python.Error('Invalid type.');\n                    }\n                    const value_store_type = annotated_type ? annotated_type : as_simple_value.type();\n                    this.insertStore(name, loc, as_simple_value, value_store_type);\n                } else {\n                    this.value_table.set(name, value);\n                }\n            }\n            getSugaredVar(ident, range, required) {\n                required = required || true;\n                let retval = this.findInAnyFrame(ident);\n                if (!retval) {\n                    torch._C.Environment.globals = torch._C.Environment.globals || new Map([\n                        ['print', new torch._C.PrintValue()],\n                        ['tuple', torch._C.SpecialFormValue.create('prim::TupleConstruct')],\n                        ['float', new torch._C.MagicMethod('__float__', new torch._C.CastValue(torch.FloatType.get(), 'aten::Float'))],\n                        ['int', new torch._C.MagicMethod('__int__', new torch._C.CastValue(torch.IntType.get(), 'aten::Int'))],\n                        ['bool', new torch._C.MagicMethod('__bool__', new torch._C.CastValue(torch.BoolType.get(), 'aten::Bool'))],\n                        ['str', new torch._C.MagicMethod('__str__', new torch._C.CastValue(torch.StringType.get(), 'aten::str'))],\n                        ['getattr', torch._C.SpecialFormValue.create('prim::GetAttr')],\n                        ['hasattr', torch._C.SpecialFormValue.create('prim::HasAttr')],\n                        ['isinstance', torch._C.SpecialFormValue.create('prim::isinstance')],\n                        ['range', torch._C.SpecialFormValue.create('prim::range')],\n                        ['sorted', new torch._C.BuiltinFunction('aten::sorted', null)],\n                    ]);\n                    if (torch._C.Environment.globals.has(ident)) {\n                        retval = torch._C.Environment.globals.get(ident);\n                    }\n                }\n                if (!retval) {\n                    const type = this.resolver.resolveType(ident, range);\n                    if (type instanceof torch.TupleType) {\n                        retval = new torch.jit.NamedTupleConstructor(type);\n                    }\n                }\n                if (!retval) {\n                    retval = this.resolver.resolveValue(ident, this.method, range);\n                }\n                if (!retval) {\n                    const type = this.resolver.resolveType(ident, range);\n                    if (type instanceof torch.ClassType) {\n                        retval = new torch.jit.ClassValue(type);\n                    }\n                }\n                if (!retval && required) {\n                    throw new python.Error(`The name '${ident}' is not defined.`);\n                }\n                return retval;\n            }\n            getVar(ident, range) {\n                return this.getSugaredVar(ident, range).asValue(range, this.method);\n            }\n            definedVariables() {\n                return Array.from(this.type_table.keys());\n            }\n        });\n        this.registerType('torch._C.Refinement', class {\n            constructor(identifier, type) {\n                this._identifier = identifier;\n                this._type = type;\n            }\n            identifier() {\n                return this._identifier;\n            }\n            type() {\n                return this._type;\n            }\n        });\n        this.registerType('torch._C.RefinementSet', class {\n            constructor(...args) {\n                if (args.length === 1 && args[0] instanceof torch._C.Refinement) {\n                    this._true_refinements = [args[0]];\n                    this._false_refinements = [];\n                } else if (args.length === 2 && args[0] instanceof torch._C.Refinement && args[1] instanceof torch._C.Refinement) {\n                    this._true_refinements = [args[0]];\n                    this._false_refinements = [args[1]];\n                } else if (args.length === 2 && Array.isArray(args[0]) && Array.isArray(args[1])) {\n                    [this._true_refinements, this._false_refinements] = args;\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n            Not() {\n                return new torch._C.RefinementSet(this._false_refinements, this._true_refinements);\n            }\n            activeRefinements() {\n                return this._true_refinements;\n            }\n        });\n        this.registerFunction('torch._C.CondValue', class {\n            constructor(...args) {\n                if (args.length === 3) {\n                    [this._value, this._refinements, this._static_if] = args;\n                } else if (args.length === 4) {\n                    const [g, loc, static_value, refinements] = args;\n                    this._value = g.insertConstant(static_value, loc);\n                    this._refinements = refinements;\n                    this._static_if = static_value;\n                } else {\n                    throw new python.Error('Invalid number of arguments.');\n                }\n            }\n            value() {\n                return this._value;\n            }\n            staticIf() {\n                return this._static_if;\n            }\n            refinements() {\n                return this._refinements;\n            }\n        });\n        this.registerFunction('torch._C.asSimple', (value) => {\n            if (value instanceof torch._C.SimpleValue) {\n                return value.getValue();\n            }\n            return null;\n        });\n        this.registerFunction('torch._C.isNumber', (str) => {\n            return /^[0-9]+$/.test(str);\n        });\n        this.registerFunction('torch._C.normalizeAttrName', (field) => {\n            if (torch._C.isNumber(field)) {\n                return `_${field}`;\n            }\n            return field;\n        });\n        this.registerFunction('torch._C.meaningfulName', (name) => {\n            if (name.length === 0) {\n                return false;\n            }\n            if (name[0] === '$') {\n                return false;\n            }\n            if (name[0] !== '_') {\n                return true;\n            }\n            return !/\\d+/.test(name.slice(1));\n        });\n        this.registerFunction('torch._C.materializeConstant', (val, graph, r, map) => {\n            const key = `${val.value}:${val.tag}`;\n            const existing_constant = map.get(key);\n            if (existing_constant) {\n                return existing_constant;\n            }\n            const guard = new torch._C.WithInsertPoint(graph.block().nodes().front());\n            const new_constant = graph.insertConstant(val, r);\n            map.set(key, new_constant);\n            guard.dispose();\n            return new_constant;\n        });\n\n        this.registerFunction('torch._C.getFullSchemaName', (schema) => {\n            if (schema.overload_name) {\n                return `${schema.name}.${schema.overload_name}`;\n            }\n            return schema.name;\n        });\n        this.registerFunction('torch._C.insertGraph', (g, callee, inputs, value_map) => {\n            const value_map_func = (v) => value_map.get(v);\n            torch._C.AT_ASSERT(callee.inputs().length === inputs.length);\n            for (let i = 0; i < inputs.length; i++) {\n                value_map.set(callee.inputs()[i], inputs[i]);\n            }\n            for (const node of callee.nodes()) {\n                const new_node = g.insertNode(g.createClone(node, value_map_func));\n                for (let i = 0; i < node.outputs().length; i++) {\n                    value_map.set(node.outputs()[i], new_node.outputs()[i]);\n                }\n            }\n            const outputs = [];\n            for (const output of callee.outputs()) {\n                outputs.push(value_map_func(output));\n            }\n            return outputs;\n        });\n        this.registerType('TemplateEnv', class {\n        });\n        this.registerType('torch._C.BuiltinFunctionRegistry', class {\n            constructor() {\n                this.state = 'UNINITIALIZED';\n                this._builtins_by_name = new Map();\n            }\n            getAllBuiltinFunctionsFor(name) {\n                if (this.state === 'UNINITIALIZED') {\n                    this.loadBuiltinFunctions();\n                    this.state = 'INITIALIZED';\n                }\n                if (!this._builtins_by_name.has(name)) {\n                    return [];\n                }\n                return this._builtins_by_name.get(name);\n            }\n            loadBuiltinFunctions() {\n                /*\n                for (const scalar of ['float', 'int', 'complex']) {\n                    const env  = new torch.C.TemplateEnv();\n                    env.s('Scalar', scalar);\n                    this.loadSource(scalar_operators_source.format(env), 'aten');\n                }\n                for (const scalar of ['float', 'int']) {\n                    const env  = new torch.C.TemplateEnv();\n                    env.s('Scalar', scalar);\n                    loadSource(scalar_operators_no_complex_source.format(env), 'aten');\n                }\n                using str_pair = std::pair<std::string, std::string>;\n                const std::vector<str_pair> name_len = {\n                    str_pair('single', '1'),\n                    str_pair('pair', '2'),\n                    str_pair('triple', '3'),\n                    str_pair('quadruple', '4'),\n                };\n                for (const auto scalar : {'float', 'int'}) {\n                    for (const auto& pair : name_len) {\n                        const env  = new torch.C.TemplateEnv();\n                        env.s('Scalar', scalar);\n                        env.s('name', pair.first);\n                        env.s('Length', pair.second);\n                        this.loadSource(_ntuple_ops.format(env), 'aten');\n                    }\n                }\n                for (auto rhs : {'number', 'Tensor'}) {\n                    at::jit::TemplateEnv env;\n                    env.s('Rhs_Type', rhs);\n                    this.loadSource(floordiv.format(env), 'aten');\n                }\n                this.loadSource(aten_ops, 'aten');\n                this.loadSource(aten_ops_additional, 'aten');\n                this.loadSource(tensor_properties, 'prim');\n                */\n            }\n            loadSource(/* source, the_namespace */) {\n            }\n        });\n        this.registerFunction('torch._C.getAllBuiltinFunctionsFor', (name) => {\n            torch._C.registry = torch._C.registry || new torch._C.BuiltinFunctionRegistry();\n            return torch._C.registry.getAllBuiltinFunctionsFor(name);\n        });\n        this.registerFunction('torch._C.get_operator_version_map', () => {\n            return new Map();\n        });\n        this.registerFunction('torch._C.varargsCanBeUsedAsList', (schema, arg_index, arg) => {\n            const is_last_argument = arg_index + 1 === schema.arguments.length || schema.arguments[arg_index + 1].kwarg_only;\n            let arg_type = arg.type;\n            if (arg_type instanceof torch._C.DynamicType) {\n                arg_type = arg_type.fallback();\n            }\n            const argument_is_list = arg_type instanceof torch.ListType;\n            const typevar_list = argument_is_list && arg_type.getElementType() instanceof torch._C.VarType;\n            const arg_is_broadcasting_list = arg.N > 0;\n            return is_last_argument && argument_is_list && !arg_is_broadcasting_list && !typevar_list;\n        });\n        this.registerFunction('torch._C.isBlockListedSchema', (schema) => {\n            if ((schema.name === 'aten::view' && schema.overload_name === 'dtype') ||\n                (schema.name === 'aten::max' && schema.overload_name === 'unary_out') ||\n                (schema.name === 'aten::min' && schema.overload_name === 'unary_out')) {\n                return true;\n            }\n            return false;\n        });\n        this.registerFunction('torch._C.unwrapOptional', (opt_type) => {\n            if (opt_type instanceof torch._C.DynamicType) {\n                return torch._C.unwrapOptional(opt_type.fallback());\n            }\n            if (opt_type instanceof torch.OptionalType) {\n                return opt_type.getElementType();\n            }\n            return opt_type;\n        });\n        this.registerFunction('torch._C.loadPossibleHistoricOps', (name, version) => {\n            const possibleSchemas = [];\n            if (version === undefined) {\n                return possibleSchemas;\n            }\n            for (const entry of torch._C.get_operator_version_map()) {\n                const old_symbol_name = entry.first;\n                const base_name = old_symbol_name.substring(0, old_symbol_name.find('.'));\n                if (base_name === name) {\n                    const possibleUpgrader = torch._C.findUpgrader(entry.second, version.value());\n                    if (possibleUpgrader.has_value()) {\n                        possibleSchemas.push_back(possibleUpgrader.value().old_schema);\n                    }\n                }\n            }\n            return possibleSchemas;\n        });\n        this.registerFunction('torch._C.isOpCurrentBasedOnUpgraderEntries', (upgraders_for_schema, current_version) => {\n            const latest_update = upgraders_for_schema[upgraders_for_schema.length - 1].bumped_at_version;\n            return current_version < latest_update;\n        });\n        this.registerFunction('torch._C.isOpSymbolCurrent', (name, current_version) => {\n            const it = torch._C.get_operator_version_map().get(name);\n            if (it) {\n                return torch._C.isOpCurrentBasedOnUpgraderEntries(it, current_version);\n            }\n            return true;\n        });\n        this.registerFunction('torch._C.packOutputs', (g, values, field_names) => {\n            if (values.length === 1) {\n                return values[0];\n            }\n            let named_tuple = null;\n            if (field_names) {\n                const types = values.map((v) => v.type());\n                named_tuple = torch.TupleType.createNamed(null, field_names, types);\n            }\n            return g.insertNode(g.createTuple(values, named_tuple)).output();\n        });\n        this.registerFunction('torch._C.isIntOrFloatUsedAsList', (value, arg) => {\n            const v_type = value.type();\n            if (v_type !== torch.FloatType.get() && v_type !== torch.IntType.get()) {\n                return false;\n            }\n            const arg_type = torch._C.unwrapOptional(arg.type);\n            return arg_type instanceof torch.ListType && arg_type.getElementType() === v_type && arg.N;\n        });\n        this.registerFunction('torch._C.convertibleToList', (type, list_type_) => {\n            const list_type = list_type_;\n            if (list_type instanceof torch.ListType === false) {\n                return false;\n            }\n            if (type.isSubtypeOf(list_type_)) {\n                return true;\n            }\n            if (type instanceof torch.TupleType) {\n                return type.elements().every((t) => t.isSubtypeOf(list_type.getElementType()));\n            }\n            return false;\n        });\n        this.registerFunction('torch._C.findInputWithName', (name, kwargs, is_aten) => {\n            for (let i = 0; i < kwargs.length; i++) {\n                if (is_aten && name === 'self' && kwargs[i].name() === 'input') {\n                    return i;\n                }\n                if (kwargs[i].name() === name) {\n                    return i;\n                }\n            }\n            return null;\n        });\n        this.registerFunction('torch._C.tryCreateList', (elem_type, graph, loc, varargs, failure_messages, err, convert_tensor_to_num, type_env) => {\n            const elem_arg = new torch.Argument('<varargs>', elem_type);\n            const list_elements = [];\n            for (const named_value of varargs) {\n                const matched_value = torch._C.tryMatchArgument(/*arg=*/elem_arg, graph, loc, named_value, failure_messages, err, /*allow_conversions=*/convert_tensor_to_num, type_env);\n                if (!matched_value) {\n                    return null;\n                }\n                list_elements.push(matched_value);\n            }\n            return graph.insertNode(graph.createList(elem_type, list_elements)).output();\n        });\n        this.registerType('torch._C.MatchTypeReturn', class {\n            constructor(reason) {\n                this._reason = reason;\n            }\n            static Success() {\n                return new torch._C.MatchTypeReturn(null);\n            }\n            success() {\n                return this._reason === null;\n            }\n        });\n        this.registerFunction('torch._C.matchTypeVariables', (formal, actual, type_env) => {\n            if (!formal.hasFreeVariables()) {\n                if (formal instanceof torch._C.DynamicType) {\n                    return torch._C.matchTypeVariables(formal.fallback(), actual, type_env);\n                }\n                return torch._C.MatchTypeReturn.Success();\n            }\n            if (formal instanceof torch._C.VarType) {\n                const it = type_env.has(formal.name()) ? type_env.get(formal.name()) : null;\n                if (it === null) {\n                    type_env.set(formal.name(), actual);\n                    return torch._C.MatchTypeReturn.Success();\n                } else if (torch._C.unifyTypes(it, actual)) {\n                    return torch._C.MatchTypeReturn.Success();\n                }\n                return new torch._C.MatchTypeReturn('Cannot match var.');\n            } else if (formal instanceof torch.ListType) {\n                if (actual instanceof torch.ListType) {\n                    const innerMatch = torch._C.matchTypeVariables(formal.getElementType(), actual.getElementType(), type_env);\n                    if (!innerMatch.success()) {\n                        return innerMatch;\n                    }\n                    return torch._C.MatchTypeReturn.Success();\n                } else if (actual instanceof torch.TupleType) {\n                    const maybe_tuple_unified = torch._C.unifyTypeList(actual.elements(), '');\n                    if (maybe_tuple_unified) {\n                        return torch._C.matchTypeVariables(formal.getElementType(), maybe_tuple_unified, type_env);\n                    }\n                }\n                return new torch._C.MatchTypeReturn('Cannot match list.');\n            } else if (formal instanceof torch.TupleType) {\n                if (actual instanceof torch.TupleType) {\n                    if (formal.elements().length !== actual.elements().length) {\n                        return torch._C.MatchTypeReturn('Cannot match tuples of mismatched size.');\n                    }\n                    for (let i = 0; i < formal.elements().length; i++) {\n                        const result = torch._C.matchTypeVariables(formal.elements()[i], actual.elements()[i], type_env);\n                        if (!result.success()) {\n                            return result;\n                        }\n                    }\n                    return torch._C.MatchTypeReturn.Success();\n                }\n                return new torch._C.MatchTypeReturn('Cannot match tuple.');\n            } else if (formal instanceof torch.FutureType) {\n                if (actual instanceof torch.FutureType) {\n                    const innerMatch = torch._C.matchTypeVariables(formal.getElementType(), actual.getElementType(), type_env);\n                    if (!innerMatch.success()) {\n                        return innerMatch;\n                    }\n                    return torch._C.MatchTypeReturn.Success();\n                }\n                return new torch._C.MatchTypeReturn('Cannot match future.');\n            } else if (formal instanceof torch.AwaitType) {\n                if (actual instanceof torch.AwaitType) {\n                    const innerMatch = torch._C.matchTypeVariables(formal.getElementType(), actual.getElementType(), type_env);\n                    if (!innerMatch.success()) {\n                        return innerMatch;\n                    }\n                    return torch._C.MatchTypeReturn.Success();\n                }\n                return new torch._C.MatchTypeReturn('Cannot match await.');\n            } else if (formal instanceof torch.RRefType) {\n                if (actual instanceof torch.RRefType) {\n                    const innerMatch = torch._C.matchTypeVariables(formal.getElementType(), actual.getElementType(), type_env);\n                    if (!innerMatch.success()) {\n                        return innerMatch;\n                    }\n                    return torch._C.MatchTypeReturn.Success();\n                }\n                return new torch._C.MatchTypeReturn('Cannot match rref.');\n            } else if (formal instanceof torch.OptionalType) {\n                if (actual instanceof torch.OptionalType) {\n                    const optionedMatch = torch._C.matchTypeVariables(formal.getElementType(), actual.getElementType(), type_env);\n                    if (!optionedMatch.success()) {\n                        return optionedMatch;\n                    }\n                } else if (!actual.isSubtypeOf(torch.NoneType.get())) {\n                    return torch._C.matchTypeVariables(formal.getElementType(), actual, type_env);\n                }\n                return torch._C.MatchTypeReturn.Success();\n            } else if (formal instanceof torch.DictType) {\n                if (actual instanceof torch.DictType) {\n                    const key_match = torch._C.matchTypeVariables(formal.getKeyType(), actual.getKeyType(), type_env);\n                    if (!key_match.success()) {\n                        return key_match;\n                    }\n                    const value_match = torch._C.matchTypeVariables(formal.getValueType(), actual.getValueType(), type_env);\n                    if (!value_match.success()) {\n                        return value_match;\n                    }\n                    return torch._C.MatchTypeReturn.Success();\n                }\n                return new torch._C.MatchTypeReturn('Cannot match dict.');\n            }\n            throw new python.Error('Unhandled free variable container.');\n        });\n        this.registerFunction('torch._C.tryMatchArgument', (arg, graph, loc, named_value, failure_messages, err, allow_conversions, type_env) => {\n            let value = named_value.value(graph);\n            if (torch._C.isIntOrFloatUsedAsList(value, arg)) {\n                const repeated = Array(arg.N).fill(value);\n                value = graph.insertNode(graph.createList(value.type(), repeated)).output();\n            }\n            const matched = torch._C.matchTypeVariables(arg.type, value.type(), type_env);\n            if (!matched.success()) {\n                if (failure_messages) {\n                    throw new python.Error(`Could not match type ${value.type().repr_str()} to ${arg.type().repr_str()} in argument '${arg.name()}'.`);\n                }\n                return null;\n            }\n            const concrete_type = torch._C.tryEvalTypeVariables(arg.type, type_env);\n            if (!concrete_type) {\n                if (failure_messages) {\n                    throw new python.Error(`Could not infer type for argument '${arg.name}'.`);\n                }\n                return null;\n            }\n            value = torch._C.tryConvertToType(loc, graph, concrete_type, value, allow_conversions);\n            if (!value.type().isSubtypeOf(concrete_type)) {\n                if (failure_messages) {\n                    throw new python.Error(`Could not match type in argument '${arg.name()}'.`);\n                }\n                return null;\n            }\n            return value;\n        });\n        this.registerFunction('torch._C.tryConvertToType', (loc, graph, concrete_type, value, allow_conversions) => {\n            if (concrete_type instanceof torch.OptionalType) {\n                const op = concrete_type;\n                if (value.type() instanceof torch.OptionalType === false && !value.type().isSubtypeOf(torch.NoneType.get())) {\n                    return torch._C.tryConvertToType(loc, graph, op.getElementType(), value, allow_conversions);\n                }\n            }\n            if (value.node().kind() === 'prim::EmptyListLiteral' && concrete_type instanceof torch.ListType) {\n                value = graph.insertNode(graph.createList(concrete_type.getElementType(), [])).output();\n            }\n            if (value.type() instanceof torch.TupleType) {\n                const value_tuple = value.type();\n                if (torch._C.convertibleToList(value.type(), torch._C.unwrapOptional(concrete_type))) {\n                    const unpacked = torch._C.createTupleUnpack(value);\n                    const elem_type = torch._C.unwrapOptional(concrete_type).expect(torch.ListType).getElementType();\n                    value = graph.insertNode(graph.createList(elem_type, unpacked)).output();\n                }\n                if (concrete_type instanceof torch.TupleType) {\n                    const concrete_tuple = concrete_type;\n                    if (!value_tuple.isSubtypeOf(concrete_tuple) &&\n                        concrete_tuple.elements().length === value_tuple.elements().length) {\n                        const unpacked = torch._C.createTupleUnpack(value);\n                        const converted = [];\n                        for (let i = 0; i < concrete_tuple.elements().length; i++) {\n                            converted.push(torch._C.tryConvertToType(loc, graph, concrete_tuple.elements()[i], unpacked[i], allow_conversions));\n                        }\n                        value = graph.insertNode(graph.createTuple(converted)).output();\n                    }\n                }\n            }\n            if (allow_conversions) {\n                const value_isa_tensor = value.type().isSubtypeOf(torch.TensorType.get());\n                const value_equals_number = value.type() === torch.NumberType.get();\n                const concrete_float = concrete_type === torch.FloatType.get();\n                const concrete_complex = concrete_type === torch.ComplexType.get();\n                const concrete_int = concrete_type === torch.IntType.get();\n                const concrete_number = concrete_type === torch.NumberType.get();\n                if (value_isa_tensor) {\n                    if (concrete_float) {\n                        value = graph.insert('aten::FloatImplicit', [new torch._C.NamedValue(value)], [], loc);\n                    } else if (concrete_complex) {\n                        value = graph.insert('aten::ComplexImplicit', [new torch._C.NamedValue(value)], [], loc);\n                    } else if (concrete_int) {\n                        value = graph.insert('aten::IntImplicit', [new torch._C.NamedValue(value)], [], loc);\n                    } else if (concrete_number) {\n                        value = graph.insert('aten::ScalarImplicit', [new torch._C.NamedValue(value)], [], loc);\n                    }\n                } else if (value_equals_number) {\n                    if (concrete_float) {\n                        value = graph.insert('aten::Float', [new torch._C.NamedValue(value)], [], loc);\n                    } else if (concrete_complex) {\n                        value = graph.insert('aten::Complex', [new torch._C.NamedValue(value)], [], loc);\n                    } else if (concrete_int) {\n                        value = graph.insert('aten::Int', [new torch._C.NamedValue(value)], [], loc);\n                    }\n                } else if (value.type() === torch.BoolType.get()) {\n                    if (concrete_float) {\n                        value = graph.insert('aten::Float', [new torch._C.NamedValue(value)], [], loc);\n                    } else if (concrete_int || concrete_number) {\n                        value = graph.insert('aten::Int', [new torch._C.NamedValue(value)], [], loc);\n                    }\n                }\n                if (value.type().isSubtypeOf(torch.StringType.get()) && concrete_type.isSubtypeOf(torch.DeviceObjType.get())) {\n                    return graph.insert('aten::device', [new torch._C.NamedValue(value)], [], loc);\n                }\n            }\n            return value;\n        });\n        this.registerFunction('torch._C.tryEvalTypeVariables', (type, type_env) => {\n            if (!type.hasFreeVariables()) {\n                if (type instanceof torch._C.DynamicType) {\n                    return torch._C.tryEvalTypeVariables(type.fallback(), type_env);\n                }\n                return type;\n            }\n            if (type instanceof torch._C.VarType) {\n                return type_env.get(type.annotation_str);\n            }\n            const contained = type.containedTypes();\n            if (contained.length === 0) {\n                return type;\n            }\n            const new_contained = [];\n            for (const t of contained) {\n                const r = torch._C.tryEvalTypeVariables(t, type_env);\n                if (!r) {\n                    return null;\n                }\n                new_contained.push(r);\n            }\n            return type.withContained(new_contained);\n        });\n        this.registerFunction('torch._C.tryMatchSchema', (schema, loc, graph, args, kwargs, self, failure_messages, allow_conversions) => {\n            if (torch._C.isBlockListedSchema(schema)) {\n                return null;\n            }\n            const err = null;\n            const type_env = new Map();\n            const positional_inputs = [];\n            const used_kwarg = kwargs.map(() => false);\n            const is_aten = schema.name.startsWith('aten::');\n            let used_args = 0;\n            for (let schema_i = 0; schema_i < schema.arguments.length; schema_i++) {\n                const arg = schema.arguments[schema_i];\n                let actual_named_value = null;\n                if (arg.name === 'self' && self) {\n                    actual_named_value = self;\n                    self = null;\n                } else if (!arg.kwarg_only && used_args < args.length) {\n                    if (allow_conversions && torch._C.varargsCanBeUsedAsList(schema, schema_i, arg)) {\n                        const value = args[used_args].value(graph);\n                        const actual_type = value.type();\n                        if (actual_type instanceof torch.ListType === false && !torch._C.convertibleToList(actual_type, torch._C.unwrapOptional(arg.type))) {\n                            const formal_type = torch._C.unwrapOptional(arg.type).expect(torch.ListType).getElementType();\n                            const list = torch._C.tryCreateList(formal_type, graph, loc, args.slice(used_args), failure_messages, err, allow_conversions, type_env);\n                            if (!list) {\n                                return null;\n                            }\n                            used_args = args.length;\n                            positional_inputs.push(list);\n                            continue;\n                        }\n                    }\n                    actual_named_value = args[used_args];\n                    used_args++;\n                } else {\n                    const kwarg_idx = torch._C.findInputWithName(arg.name, kwargs, is_aten);\n                    if (Number.isInteger(kwarg_idx)) {\n                        const nv = kwargs[kwarg_idx];\n                        if (used_kwarg[kwarg_idx]) {\n                            if (failure_messages) {\n                                throw new python.Error(`Argument '${nv.name()}' specified twice in schema.`);\n                            }\n                            return null;\n                        }\n                        used_kwarg[kwarg_idx] = true;\n                        actual_named_value = nv;\n                    } else if (arg.has_default_value()) {\n                        actual_named_value = new torch._C.NamedValue(arg.default_value);\n                    } else {\n                        if (failure_messages) {\n                            throw new python.Error(`Argument '${arg.name}' not provided.`);\n                        }\n                        return null;\n                    }\n                }\n                const positional = torch._C.tryMatchArgument(arg, graph, loc, actual_named_value, failure_messages, err, allow_conversions, type_env);\n                if (!positional) {\n                    return null;\n                }\n                positional_inputs.push(positional);\n            }\n            if (self !== null) {\n                if (failure_messages) {\n                    throw new python.Error('Provided self argument not used in schema.');\n                }\n                return null;\n            }\n            if (schema.is_vararg) {\n                for (; used_args < args.length; used_args++) {\n                    positional_inputs.push(args[used_args].value(graph));\n                }\n            }\n            if (used_args < args.length) {\n                if (failure_messages) {\n                    throw new python.Error('Too many positional arguments.');\n                }\n                return null;\n            }\n            for (let i = 0; i < kwargs.length; i++) {\n                const nv = kwargs[i];\n                if (!used_kwarg[i]) {\n                    if (failure_messages) {\n                        if (schema.argumentIndexWithName(nv.name()) === null) {\n                            throw new python.Error('Keyword argument unknown.');\n                        } else {\n                            throw new python.Error('Keyword argument specified twice.');\n                        }\n                    }\n                    return null;\n                }\n            }\n            const returns = schema.returns;\n            const return_types = returns.map((r) => {\n                const result = torch._C.tryEvalTypeVariables(r.type, type_env);\n                if (!result) {\n                    throw new python.Error('Unbound type variable.');\n                }\n                return result;\n            });\n            const return_has_field_names = returns.every((r) => r.name);\n            let return_field_names = null;\n            if (return_has_field_names) {\n                return_field_names = returns.map((r) => r.name);\n            }\n            const schema_name = torch._C.getFullSchemaName(schema);\n            return new torch._C.MatchedSchema(positional_inputs, return_types, return_field_names, schema_name);\n        });\n        this.registerFunction('torch._C.matchSchema', (schema, loc, graph, args, kwargs, self) => {\n            self = self || null;\n            const result = torch._C.tryMatchSchema(schema, loc, graph, args, kwargs, self, null, true);\n            if (result) {\n                return result;\n            }\n            throw new python.Error(`No matching schema '${schema.name}' found.`);\n        });\n        this.registerFunction('torch._C.matchSchemas', (schemas, loc, graph, args, kwargs, self, render_errors) => {\n            self = self || null;\n            render_errors = render_errors || false;\n            torch._C.TORCH_INTERNAL_ASSERT(schemas.length > 0);\n            if (schemas.length === 1) {\n                return [0, torch._C.matchSchema(schemas[0], loc, graph, args, kwargs, self)];\n            }\n            for (const allow_conversions of [false, true]) {\n                for (let i = 0; i < schemas.length; i++) {\n                    const matched_schema = torch._C.tryMatchSchema(schemas[i], loc, graph, args, kwargs, self, null, allow_conversions);\n                    if (matched_schema) {\n                        return [i, matched_schema];\n                    }\n                }\n            }\n            if (!render_errors) {\n                return torch._C.matchSchemas(schemas, loc, graph, args, kwargs, self, /*render_errors=*/true);\n            }\n            throw new python.Error(`No matching schema '${schemas[0].name}' found.`);\n        });\n        this.registerFunction('torch._C.emitBuiltinCall', (loc, graph, name, args, kwargs, self) => {\n            const variants = torch._C.getAllOperatorsFor(name);\n            const builtin_functions = torch._C.getAllBuiltinFunctionsFor(name);\n            const graph_version = graph.get_op_version();\n            const schemas = [];\n            const upgrader_schemas = [];\n            for (const op of variants) {\n                let found_upgrader = false;\n                const op_name = torch._C.getFullSchemaName(op.schema());\n                if (Number.isInteger(graph_version)) {\n                    const version_entry = torch._C.get_operator_version_map().get(op_name);\n                    if (version_entry) {\n                        const old_schema_entry = torch._C.findUpgrader(version_entry.second, graph_version.value());\n                        if (old_schema_entry.has_value()) {\n                            const old_schema = torch._C.parseSchema(old_schema_entry.value().old_schema);\n                            upgrader_schemas.push(old_schema);\n                            found_upgrader = true;\n                        } else if (!torch._C.isOpCurrentBasedOnUpgraderEntries(version_entry.second, graph_version.value())) {\n                            throw new python.Error('Valid upgrader must be present.');\n                        }\n                    }\n                }\n                if (!found_upgrader) {\n                    schemas.push(op.schema());\n                }\n            }\n            if (variants.length === 0) {\n                const oldSchemas = torch._C.loadPossibleHistoricOps(name, graph_version);\n                for (const old_schema_entry of oldSchemas) {\n                    const old_schema = torch._C.parseSchema(old_schema_entry);\n                    upgrader_schemas.push(old_schema);\n                }\n            }\n            for (const schema of upgrader_schemas) {\n                schemas.push(schema);\n            }\n            for (const method of builtin_functions) {\n                method.ensure_defined();\n                schemas.push(method.getSchema());\n            }\n            if (schemas.length === 0) {\n                const inputs = args.map((arg) => arg.value(graph));\n                const n = graph.insertNode(graph.create(name, inputs, 0)).setSourceRange(loc);\n                n.addOutput().setType(torch.TensorType.get());\n                return n.output();\n            }\n            const matched = torch._C.matchSchemas(schemas, loc, graph, args, kwargs, self);\n            if (matched[0] < variants.length + upgrader_schemas.length) {\n                return torch._C.emitBuiltinNode(matched[1], loc, graph, name, graph_version);\n            }\n            const fn = builtin_functions[matched.first - variants.size()];\n            return torch._C.insertGraph(graph, torch._C.toGraphFunction(fn).graph(), matched.second.inputs, new Map())[0];\n        });\n        this.registerFunction('torch._C.emitBuiltinNode', (matched_schema, loc, graph, name, version) => {\n            const n = graph.insertNode(graph.create(name, matched_schema.inputs, 0)).setSourceRange(loc);\n            for (const ret of matched_schema.return_types) {\n                n.addOutput().setType(ret);\n            }\n            if (!Number.isInteger(version) || torch._C.isOpSymbolCurrent(matched_schema.schema_name, version)) {\n                n.getOperation();\n            } else {\n                n.setHistoricSchemaName(matched_schema.schema_name);\n            }\n            return torch._C.packOutputs(graph, n.outputs(), matched_schema.return_field_names);\n        });\n        this.registerFunction('torch._C.unshapedType', (type) => {\n            if (type.isSubtypeOf(torch.TensorType.get())) {\n                return torch.TensorType.get();\n            }\n            const contained = type.containedTypes();\n            if (contained.length === 0) {\n                return type;\n            }\n            return type.withContained(contained.map((t) => torch._C.unshapedType(t)));\n        });\n        this.registerFunction('torch._C.unifyTypesImpl', (t1, t2, default_to_union, type_hint) => {\n            default_to_union = default_to_union || false;\n            type_hint = type_hint || null;\n            if (t1.isSubtypeOf(t2)) {\n                return t2;\n            } else if (t2.isSubtypeOf(t1)) {\n                return t1;\n            }\n            if (t1.kind() === 'TensorType' && t2.kind() === 'TensorType') {\n                return t1.merge(t2);\n            }\n            if (t1.isSubtypeOf(torch.NoneType.get()) && !t2.isSubtypeOf(torch.NoneType.get())) {\n                return torch.OptionalType.create(t2);\n            } else if (t2.isSubtypeOf(torch.NoneType.get()) && !t1.isSubtypeOf(torch.NoneType.get())) {\n                return torch.OptionalType.create(t1);\n            }\n            if (t1 instanceof torch.OptionalType) {\n                const elem = torch._C.unifyTypes(t1.getElementType(), t2);\n                if (elem) {\n                    return torch.OptionalType.create(elem);\n                }\n            } else if (t2 instanceof torch.OptionalType) {\n                const elem = torch._C.unifyTypes(t2.getElementType(), t1);\n                if (elem) {\n                    return torch.OptionalType.create(elem);\n                }\n            }\n            if (t1 instanceof torch.TupleType && t2 instanceof torch.TupleType) {\n                if (t1.elements().size() !== t2.elements().size()) {\n                    return null;\n                }\n                const elements = [];\n                for (let i = 0; i < t1.elements().length; i++) {\n                    const elem = torch._C.unifyTypes(t1.elements()[i], t2.elements()[i], default_to_union);\n                    if (elem) {\n                        elements.push(elem);\n                    } else {\n                        return null;\n                    }\n                }\n                return torch.TupleType.create(elements);\n            }\n            if (t1 instanceof torch.FutureType && t2 instanceof torch.FutureType) {\n                const elem = torch._C.unifyTypes(t1.getElementType(), t2.getElementType());\n                if (elem) {\n                    return torch.FutureType.create(elem);\n                }\n            }\n            const t1_unshaped = torch._C.unshapedType(t1);\n            const t2_unshaped = torch._C.unshapedType(t2);\n            if (t1_unshaped.isSubtypeOf(t2_unshaped)) {\n                return t2_unshaped;\n            } else if (t2_unshaped.isSubtypeOf(t1_unshaped)) {\n                return t1_unshaped;\n            }\n            if (type_hint && t1.isSubtypeOf(type_hint) && t2.isSubtypeOf(type_hint)) {\n                return type_hint;\n            }\n            return null;\n        });\n        this.registerFunction('torch._C.unifyTypes', (t1, t2, default_to_union, type_hint) => {\n            const unified = torch._C.unifyTypesImpl(t1, t2, default_to_union, type_hint);\n            if (default_to_union && !unified) {\n                return torch.UnionType.create([t1, t2]);\n            }\n            return unified;\n        });\n        this.registerFunction('torch._C.unifyTypeList', (elements, why_not, default_to_union, type_hint) => {\n            if (elements.length === 0) {\n                return null;\n            }\n            let [ret_type] = elements;\n            for (let i = 1; i < elements.length && ret_type; i++) {\n                const maybe_unified = torch._C.unifyTypes(ret_type, elements[i], default_to_union, type_hint);\n                if (!maybe_unified) {\n                    return null;\n                }\n                ret_type = maybe_unified;\n            }\n            return ret_type;\n        });\n        this.registerFunction('torch._C.insertableTensor', (ten) => {\n            return !ten.requires_grad() && ten.has_storage() && !ten.is_nested();\n        });\n        this.registerFunction('torch._C.insertableIValue', (ivalue) => {\n            if (ivalue.isInt() || ivalue.isNone() || ivalue.isBool() ||\n                ivalue.isDouble() || ivalue.isComplexDouble() || ivalue.isString() ||\n                ivalue.isDevice() || ivalue.isEnum()) {\n                return true;\n            }\n            if (ivalue.isTensor()) {\n                return torch._C.insertableTensor(ivalue.toTensor());\n            }\n            if (ivalue.isList() || ivalue.isTuple()) {\n                let elems = [];\n                if (ivalue.isTuple()) {\n                    elems = ivalue.toTupleRef().elements();\n                } else {\n                    elems = ivalue.toListRef();\n                }\n                return elems.every((tup_elem) => torch._C.insertableIValue(tup_elem));\n            }\n            if (ivalue.isGenericDict()) {\n                const dict = ivalue.toGenericDict();\n                return dict.every((entry) => torch._C.insertableIValue(entry.key()) && torch._C.insertableIValue(entry.value()));\n            }\n            return false;\n        });\n        this.registerFunction('torch._C.insertConstant', (g, val, loc, scope) => {\n            loc = loc || null;\n            scope = scope || null;\n            const value = torch._C.tryInsertConstant(g, val, loc, scope);\n            if (value !== undefined) {\n                return value;\n            }\n            throw new python.Error('Unsupported value kind.');\n        });\n        this.registerFunction('torch._C.tryInsertConstant', (g, val, loc, scope) => {\n            if (val instanceof torch._C.IValue) {\n                const n = g.create('prim::Constant');\n                if (val.isTensor()) {\n                    const ref = val.toTensor();\n                    if (!torch._C.insertableTensor(val.toTensor())) {\n                        n.destroy();\n                        return null;\n                    }\n                    if (!ref.defined()) {\n                        n.destroy();\n                        return g.insertNode(g.createNone()).output();\n                    }\n                    torch._C.TORCH_INTERNAL_ASSERT(!ref.requires_grad());\n                    n.output().inferTypeFrom(ref); // note: before t_ because of std::move(ref)\n                    n.t_('value', ref);\n                } else if (val.isInt()) {\n                    n.i_('value', val.toInt());\n                    n.output().setType(torch.IntType.get());\n                } else if (val.isDouble()) {\n                    n.f_('value', val.toDouble());\n                    n.output().setType(torch.FloatType.get());\n                } else if (val.isComplexDouble()) {\n                    n.c_('value', val.toComplexDouble());\n                    n.output().setType(torch.ComplexType.get());\n                } else if (val.isBool()) {\n                    n.i_('value', val.toBool());\n                    n.output().setType(torch.BoolType.get());\n                } else if (val.isList()) {\n                    const fast_path_list = val.isBoolList() || val.isIntList() || val.isDoubleList();\n                    if (fast_path_list || torch._C.insertableIValue(val)) {\n                        n.ival_('value', val);\n                        n.output().setType(val.type());\n                    } else {\n                        n.destroy();\n                        return null;\n                    }\n                } else if (val.isString()) {\n                    n.s_('value', val.toStringRef());\n                    n.output().setType(torch.StringType.get());\n                } else if (val.isDevice()) {\n                    n.s_('value', val.toDevice().__str__());\n                    n.output().setType(torch.DeviceObjType.get());\n                } else if (val.isGenerator()) {\n                    n.ival_('value', val.toGenerator());\n                    n.output().setType(torch._C_._GeneratorType.get());\n                } else if (val.isStream()) {\n                    n.ival_('value', val);\n                    n.output().setType(torch.StreamObjType.get());\n                } else if (val.isNone()) {\n                    n.output().setType(torch.NoneType.get());\n                    // n.ival_('value', null); // remove\n                } else if (val.isTuple()) {\n                    if (torch._C.insertableIValue(val)) {\n                        n.ival_('value', val);\n                        n.output().setType(val.type());\n                    } else {\n                        n.destroy();\n                        return null;\n                    }\n                } else if (val.isObject()) {\n                    const ref = val.toObjectRef();\n                    // see: [Constant Object Weak CompilationUnit Reference]\n                    if (!ref.type().is_module() && (ref.is_weak_compilation_ref() || ref.is_empty_strong_compilation_ref())) {\n                        n.ival_('value', val);\n                        n.output().setType(val.type());\n                    } else {\n                        n.destroy();\n                        return null;\n                    }\n                } else if ((val.isGenericDict() && torch._C.insertableIValue(val)) || (val.isEnum())) {\n                    n.ival_('value', val);\n                    n.output().setType(val.type());\n                } else {\n                    n.destroy();\n                    return null;\n                }\n                if (loc) {\n                    n.setSourceRange(loc);\n                }\n                if (scope) {\n                    n.setScope(scope);\n                }\n                return g.insertNode(n).output();\n            }\n            const n = g.create('prim::Constant');\n            let type = null;\n            if (val === null) {\n                n.ival_('value', val);\n                type = torch.NoneType.get();\n            } else if (typeof val === 'string') {\n                n.s_('value', val);\n                type = torch.StringType.get();\n            } else if (Array.isArray(val) && val.every((item) => typeof item === 'string')) {\n                n.ss_('value', val);\n                type = torch.ListType.create(torch.StringType.get());\n            } else if (typeof val === 'boolean') {\n                n.i_('value', val === true ? 1 : 0);\n                type = torch.BoolType.get();\n            } else if ((!val.type && Number.isInteger(val)) || val.type === 'int') {\n                n.i_('value', val);\n                type = torch.IntType.get();\n            } else if ((!val.type && typeof val === 'number') || val.type === 'float') {\n                n.f_('value', val);\n                type = torch.FloatType.get();\n            } else if (val instanceof torch.Tensor) {\n                n.t_('value', val);\n                type = torch.TensorType.get();\n            } else if (val instanceof torch.ScriptObject) {\n                n.ival_('value', val);\n                type = val.type();\n            } else if (Array.isArray(val) && val.every((item) => Number.isInteger(item))) {\n                n.ival_('value', val);\n                type = torch.ListType.create(torch.IntType.get());\n            } else {\n                throw new python.Error(`Unsupported value type '${typeof val}'.`);\n            }\n            if (type) {\n                n.output().setType(type);\n            }\n            if (loc) {\n                n.setSourceRange(loc);\n            }\n            if (scope) {\n                n.setScope(scope);\n            }\n            return g.insertNode(n).output();\n        });\n        this.registerFunction('torch._C.toIValue', (v) => {\n            if (v.node().kind() !== 'prim::Constant' || v.type() instanceof torch._C.FunctionType) {\n                return null;\n            }\n            const node = v.node();\n            const type = v.type();\n            if (type.isSubtypeOf(torch.TensorType.get())) {\n                return new torch._C.IValue(node.t('value'), 'Tensor');\n            } else if (type.isSubtypeOf(torch.BoolType.get())) {\n                return new torch._C.IValue(Boolean(node.i('value'), 'Bool'));\n            } else if (type.isSubtypeOf(torch.NumberType.get()) && node.kindOf('value') === 'i') {\n                return new torch._C.IValue(node.i('value'), 'Int');\n            } else if (type.isSubtypeOf(torch.NumberType.get()) && node.kindOf('value') === 'f') {\n                return new torch._C.IValue(node.f('value'), 'Double');\n            } else if (type.isSubtypeOf(torch.ComplexType.get()) && node.kindOf('value') === 'c') {\n                return new torch._C.IValue(node.c('value'), 'Complex');\n            } else if (type instanceof torch.ListType && node.kindOf('value') === 'ival') {\n                let list = node.ival('value');\n                list = list.isList ? list : new torch._C.IValue(list); // remove\n                torch._C.TORCH_INTERNAL_ASSERT(list.isList());\n                return list;\n            } else if (type instanceof torch.DictType && node.kindOf('value') === 'ival') {\n                const dict = node.ival('value');\n                torch._C.TORCH_INTERNAL_ASSERT(dict.isGenericDict());\n                return dict;\n            } else if (type instanceof torch.TupleType && node.kindOf('value') === 'ival') {\n                const tup = node.ival('value');\n                torch._C.TORCH_INTERNAL_ASSERT(tup.isTuple());\n                return tup;\n            } else if (type === torch.StringType.get()) {\n                const s = new torch._C.IValue(node.s('value'), 'String');\n                return s;\n            } else if (type === torch.DeviceObjType.get()) {\n                const d = new torch.device(node.s('value'));\n                return new torch._C.IValue(d);\n            } else if (type === torch._C._GeneratorType.get()) {\n                throw new python.Error('Not implemented.');\n                // const generator = node.ival('value').toGenerator();\n                // return generator;\n            } else if (type === torch.StreamObjType.get()) {\n                throw new python.Error('Not implemented.');\n                // const s = node.ival('value').toStream();\n                // return s;\n            } else if (node.mustBeNone()) {\n                return new torch._C.IValue();\n            } else if (type.kind() === 'EnumType') {\n                const enum_val = node.ival('value');\n                return enum_val;\n            } else if (type instanceof torch.ClassType && !type.is_module()) {\n                const class_val = node.ival('value');\n                return  new torch._C.IValue(class_val, 'Object');\n            }\n            throw new python.Error('Unsupported constant literal.');\n        });\n        this.registerFunction('torch._C.constant_as', (v, target, default_value) => {\n            const ivalue = torch._C.toIValue(v);\n            if (ivalue) {\n                return ivalue[target]();\n            }\n            return default_value === undefined ? null : default_value;\n        });\n        this.registerType('torch._C.NamedValue', class {\n            constructor(...args) {\n                if (args.length === 1) {\n                    if (args[0] instanceof torch.Value) {\n                        [this._value] = args;\n                    } else {\n                        [this._ivalue] = args;\n                    }\n                } else if (args.length === 3 && typeof args[1] === 'string' && args[2] instanceof torch.Value) {\n                    [this._loc, this._name, this._value] = args;\n                } else {\n                    throw new python.Error('Invalid argument.');\n                }\n            }\n            name() {\n                return this._name;\n            }\n            value(g) {\n                if (!this._value) {\n                    return torch._C.insertConstant(g, this._ivalue);\n                }\n                return this._value;\n            }\n            type() {\n                if (this._value) {\n                    return this._value.type();\n                }\n                return this._ivalue.type();\n            }\n        });\n        this.registerType('torch._C.SugaredValue', class {\n            kind() {\n                throw new python.Error('Not implemented.');\n            }\n            shouldEmitUnrolled() {\n                return this.staticLen() !== null;\n            }\n        });\n        this.registerType('torch._C.SimpleValue', class extends torch._C.SugaredValue {\n            constructor(value) {\n                super();\n                this._value = value;\n            }\n            kind() {\n                return `value of type '${this._value.type().annotation_str}'`;\n            }\n            asValue(/* range, m */) {\n                return this._value;\n            }\n            getValue() {\n                return this._value;\n            }\n            asTuple(loc, m, size_hint) {\n                const make_simple_value = (v) => new torch._C.SimpleValue(v);\n                if (this._value.type() instanceof torch.TupleType) {\n                    const outputs = torch._C.createTupleUnpack(this._value);\n                    return outputs.map((v) => make_simple_value(v));\n                } else if (this._value.type() instanceof torch.ListType) {\n                    if (!size_hint) {\n                        throw new python.Error('Cannot statically infer the expected size of a list in this context.');\n                    }\n                    const graph = this._value.owningGraph();\n                    const unpack = graph.insertNode(graph.createListUnpack(this._value, size_hint));\n                    return unpack.outputs().map((v) => make_simple_value(v));\n                } else if (this._value.type().kind() === 'AnyTupleType') {\n                    throw new python.Error('Provided tuple is not fully defined including its element types.');\n                }\n                throw new python.Error(`Cannot use '${this._value.type().toString()}' as tuple.`);\n            }\n            attr(loc, m, field) {\n                if (this._value.type().isSubtypeOf(torch.TensorType.get())) {\n                    if (torch._C.builtin_cast_method_to_scalar_type().has(field)) {\n                        return new torch._C.TensorCastValue(torch._C.builtin_cast_method_to_scalar_type().get(field), new torch._C.NamedValue(loc, 'self', this._value));\n                    }\n                }\n                if (this._value.type() instanceof torch.TupleType) {\n                    throw new python.Error('Not implemented.');\n                }\n                if (this._value.type() instanceof torch.AwaitType) {\n                    throw new python.Error('Not implemented.');\n                }\n                if (this._value.type() instanceof torch.ClassType) {\n                    const classType = this._value.type();\n                    if (classType.findMethod(field)) {\n                        return new torch._C.MethodValue(this.getValue(), [field]);\n                    }\n                    if (classType.hasAttribute(field)) {\n                        const g = m.graph();\n                        const n = g.insertNode(g.createGetAttr(this._value, field));\n                        return new torch._C.SimpleValue(n.output());\n                    }\n                    const prop = classType.getProperty(field);\n                    if (prop) {\n                        return new torch._C.MethodValue(this._value, [prop.getter.name()]).call(loc, m, {}, {}, /*n_binders=*/1);\n                    }\n                } else if (this._value.type() instanceof torch.InterfaceType) {\n                    throw new python.Error('Not implemented.');\n                } else if (this._value.type() instanceof torch.EnumType) {\n                    const g = m.graph();\n                    if (field === 'name') {\n                        const n = g.insertNode(g.createEnumName(this._value));\n                        return new torch._C.SimpleValue(n.output());\n                    }\n                    if (field === 'value') {\n                        const n = g.insertNode(g.createEnumValue(this._value));\n                        return new torch._C.SimpleValue(n.output());\n                    }\n                }\n                if (field === 'type') {\n                    const builtin = torch._C.BuiltinFunction.tryCreate('aten::to', new torch._C.NamedValue(loc, 'self', this._value));\n                    if (builtin) {\n                        return builtin;\n                    }\n                }\n                const builtin = torch._C.BuiltinFunction.tryCreate(`aten::${field}`, new torch._C.NamedValue(loc, 'self', this._value));\n                if (builtin) {\n                    return builtin;\n                }\n                if (this._value.type().isSubtypeOf(torch.TensorType.get()) && field === 'tolist') {\n                    return torch._C.SpecialFormValue.create('prim::tolist');\n                }\n                if (this._value.type().isSubtypeOf(torch.TensorType.get()) && field === '__getitem__') {\n                    return torch._C.SpecialFormValue.create('aten::index');\n                }\n                if (this._value.type() instanceof torch._C._GeneratorType && (field === 'manual_seed' || field === 'initial_seed' || field === 'seed')) {\n                    const builtin = torch._C.BuiltinFunction.tryCreate(`aten::${field}`, new torch._C.NamedValue(loc, 'self', this._value));\n                    if (builtin) {\n                        return builtin;\n                    }\n                }\n                throw new python.Error('Object has no attribute or method.');\n            }\n            setAttr(loc, m, field, newValue) {\n                const type = this._value.type();\n                if (type instanceof torch.ClassType === false) {\n                    throw new python.Error('Cannot set attribute on non-class type.');\n                }\n                const classType = type;\n                let expectedType = classType.findAttribute(field);\n                if (!expectedType) {\n                    const isInitializing = m.name() === '__init__' && m.graph().inputs().length > 0 && m.graph().inputs()[0].type() === classType;\n                    if (isInitializing) {\n                        if (this.isRecursive(classType, newValue.type())) {\n                            throw new python.Error('Classes that recursively contain instances of themselves are not supported.');\n                        }\n                        classType.addAttribute(field, newValue.type());\n                        expectedType = newValue.type();\n                        const insertPoint = m.graph().insertPoint();\n                        const topLevelBlock = m.graph().block();\n                        if (insertPoint.owningBlock() !== topLevelBlock) {\n                            throw new python.Error('First assignment cannot be in a control-flow block.');\n                        }\n                    } else {\n                        const prop = classType.getProperty(field);\n                        if (prop && prop.setter) {\n                            new torch._C.MethodValue(this._value, prop.setter.name()).call(loc, m, [newValue], [], /*n_binders=*/1);\n                            return;\n                        }\n                        if (prop && !prop.setter) {\n                            throw new python.Error('Tried to set read-only attribute.');\n                        }\n                        throw new python.Error('Tried to set nonexistent attribute.');\n                    }\n                }\n                torch._C.AT_ASSERT(expectedType);\n                const newType = newValue.type();\n                if (!newType.isSubtypeOf(expectedType)) {\n                    throw new python.Error('Wrong type for attribute assignment.');\n                }\n                const g = m.graph();\n                g.insertNode(g.createSetAttr(this._value, field, newValue));\n            }\n            getitem(loc, m, idx, type_hint) {\n                const val = this.getValue();\n                const val_type = val.type();\n                const g = m.graph();\n                if (val_type instanceof torch.ListType || val_type instanceof torch.StringType) {\n                    return new torch._C.SimpleValue(g.insert('aten::__getitem__', [new torch._C.NamedValue(val), new torch._C.NamedValue(idx)], [], loc));\n                } else if (val_type instanceof torch.DictType) {\n                    return new torch._C.SimpleValue(g.insert('aten::__getitem__', [new torch._C.NamedValue(val), new torch._C.NamedValue(idx)], [], loc));\n                } else if (val_type.isSubtypeOf(torch.TensorType.get())) {\n                    return new torch._C.SimpleValue(g.insert('aten::select', [new torch._C.NamedValue(val), new torch._C.NamedValue(0), new torch._C.NamedValue(idx)], [], loc));\n                } else if (val_type instanceof torch.ClassType) {\n                    const class_type = val_type;\n                    if (class_type.is_module() && type_hint) {\n                        const res = g.insert('prim::ModuleContainerIndex', [new torch._C.NamedValue(val), new torch._C.NamedValue(idx)], [], loc);\n                        res.setType(type_hint);\n                        return new torch._C.SimpleValue(res);\n                    }\n                    return this.attr(loc, m, '__getitem__').call(loc, m, [new torch._C.NamedValue(idx)], [], 1);\n                }\n                throw new python.Error('Object is not subscriptable.');\n            }\n        });\n        this.registerType('torch._C.MethodValue', class extends torch._C.SugaredValue {\n            constructor(self, method_names) {\n                super();\n                this._self = self;\n                this._method_names = method_names;\n            }\n            call(loc, f, args, kwargs /*, n_binders */) {\n                const argsWithSelf = [new torch._C.NamedValue(this._self), ...args];\n                const schemas = [];\n                for (const method_name of this._method_names) {\n                    const type = this._self.type();\n                    if (type instanceof torch.ClassType) {\n                        const class_type = type;\n                        const method = class_type.getMethod(method_name);\n                        method.ensure_defined();\n                        schemas.push(method.getSchema());\n                    } else if (type instanceof torch.InterfaceType) {\n                        const interface_type = type;\n                        schemas.push(interface_type.getMethod(method_name));\n                    } else {\n                        throw new python.Error('Method constructed that is not a class or interface.');\n                    }\n                }\n                const match = torch._C.matchSchemas(schemas, loc, f.graph(), argsWithSelf, kwargs);\n                const output = f.graph().insertMethodCall(this._method_names[match[0]], match[1]);\n                output.node().setSourceRange(loc);\n                return new torch._C.SimpleValue(output);\n            }\n        });\n        this.registerType('torch._C.ClassValue', class extends torch._C.SugaredValue {\n            constructor(type) {\n                super();\n                this._type = type;\n            }\n            attr(loc, m, field) {\n                const hook = this._type.findHook(field);\n                if (hook) {\n                    return new torch._C.FunctionValue(hook);\n                }\n                if (field !== '__new__') {\n                    throw new python.Error('Tried to lookup unknown attribute on class.');\n                }\n                return torch._C.SpecialFormValue.create('prim::CreateObject');\n            }\n        });\n        this.registerType('torch._C.NamedTupleConstructor', class extends torch._C.SugaredValue {\n            constructor(type) {\n                super();\n                this._type = type;\n            }\n            call(loc, m, args, kwargs /*, n_binders */) {\n                const g = m.graph();\n                const schema = this._type.schema();\n                torch._C.TORCH_INTERNAL_ASSERT(schema);\n                const matched_schema = torch._C.matchSchema(schema, loc, g, args, kwargs);\n                const self = g.insertNode(g.createTuple(matched_schema.inputs, this._type).setSourceRange(loc)).output();\n                self.setType(this._type);\n                return new torch._C.SimpleValue(self);\n            }\n        });\n        this.registerType('torch._C.SugaredEnumClass', class extends torch._C.SugaredValue {\n            constructor(enum_type) {\n                super();\n                this._enum_type = enum_type;\n            }\n            attr(loc, m, field) {\n                const names_values = this._enum_type.enumNamesValues();\n                const it = names_values.find((nv) => nv[0] === field);\n                if (it === null) {\n                    throw new python.Error(`Enum '${this._enum_type.name()}' has no attribute '${field}'.`);\n                }\n                const enum_holder = new torch._C.EnumHolder(this._enum_type, it[0], it[1]);\n                return new torch._C.SimpleValue(m.graph().insertConstant(new torch._C.IValue(enum_holder), loc));\n            }\n        });\n        this.registerType('torch._C.EnumHolder', class {\n            constructor(type, name, value) {\n                this._type = type;\n                this._name = name;\n                this._value = value;\n            }\n            name() {\n                return this._name;\n            }\n            type() {\n                return this._type;\n            }\n        });\n        this.registerType('torch._C.FunctionValue', class extends torch._C.SugaredValue {\n            constructor(...args) {\n                super();\n                if (args.length === 1 && args[0] instanceof torch._C.Function) {\n                    this._callees = [args[0]];\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n            call(loc, f, args, kwargs /*, n_binders */) {\n                const schemas = [];\n                for (const callee of this._callees) {\n                    callee.ensure_defined();\n                    schemas.push(callee.getSchema());\n                }\n                const match = torch._C.matchSchemas(schemas, loc, f.graph(), args, kwargs);\n                const output = f.graph().insertFunctionCall(this._callees[match[0]], match[1]);\n                output.node().setSourceRange(loc);\n                return new torch._C.SimpleValue(output);\n            }\n        });\n        this.registerType('torch._C.NoneValue', class extends torch._C.SugaredValue {\n        });\n        this.registerType('torch._C.PrintValue', class extends torch._C.SugaredValue {\n            call(loc, m, args, kwargs /*, n_binders */) {\n                const g = m.graph();\n                if (kwargs.length > 0) {\n                    throw new python.Error(`Print doesn't accept any keyword arguments at ${loc}.`);\n                }\n                const lowered_inputs = torch._C.toValues(m.graph(), args);\n                g.insertNode(g.create('prim::Print', lowered_inputs, 0).setSourceRange(loc));\n                return new torch._C.NoneValue();\n            }\n        });\n        this.registerType('torch._C.SpecialFormValue', class extends torch._C.SugaredValue {\n            constructor(form) {\n                super();\n                this._form = form;\n            }\n            form() {\n                return this._form;\n            }\n            static create(form) {\n                return new torch._C.SpecialFormValue(form);\n            }\n        });\n        this.registerFunction('torch._C.makeMagic', (name, base) => {\n            return new torch._C.MagicMethod(name, base);\n        });\n        this.registerType('torch._C.BuiltinFunction', class extends torch._C.SugaredValue {\n            constructor(symbol, self) {\n                super();\n                this.symbol = symbol;\n                this.self = self;\n            }\n            call(loc, m, args, kwargs /*, n_binders */) {\n                return new torch._C.SimpleValue(torch._C.emitBuiltinCall(loc, m.graph(), this.symbol, args, kwargs, this.self));\n            }\n            static tryCreate(symbol, self) {\n                for (const op of torch._C.getAllOperatorsFor(symbol)) {\n                    if (!self) {\n                        return new torch._C.BuiltinFunction(symbol, null);\n                    }\n                    const index = op.schema().argumentIndexWithName('self');\n                    if (index) {\n                        const type_env = new Map();\n                        const formal_type = op.schema().arguments()[index].type();\n                        const matched = torch._C.matchTypeVariables(formal_type, self.type(), type_env);\n                        if (!matched.success()) {\n                            continue;\n                        }\n                        const concrete_type = torch._C.tryEvalTypeVariables(formal_type, type_env);\n                        if (!concrete_type || !self.type().isSubtypeOf(concrete_type)) {\n                            continue;\n                        }\n                        return new torch._C.BuiltinFunction(symbol, self);\n                    }\n                }\n                return null;\n            }\n        });\n        this.registerType('torch._C.BuiltinModule', class extends torch._C.SugaredValue {\n            constructor(name, version) {\n                super();\n                this.name = name;\n                this.version = version || null;\n            }\n            attr(loc, m, field) {\n                if (field === 'autograd') {\n                    return new torch._C.BuiltinModule('aten', this.version);\n                }\n                const sym = `${this.name}::${field}`;\n                return new torch._C.BuiltinFunction(sym, null);\n            }\n        });\n        this.registerType('torch._C.OpsValue', class extends torch._C.SugaredValue {\n            constructor(version) {\n                super();\n                this._version = version;\n            }\n            attr(loc, m, field) {\n                return new torch._C.BuiltinModule(field, this._version);\n            }\n        });\n        this.registerType('torch._C.ConstantTableValue', class extends torch._C.SugaredValue {\n            constructor(constants) {\n                super();\n                this._constants = constants;\n                this.non_holding_object_cache = new Map();\n            }\n            attr(loc, m, field) {\n                const offset = parseInt(field.substring(1), 10);\n                if (!Number.isInteger(offset)) {\n                    throw new python.Error(`Invalid constant identifier '${field}.`);\n                }\n                if (offset < 0 || offset >= this._constants.length) {\n                    throw new python.Error('Invalid constant index.');\n                }\n                const ivalue = new torch._C.IValue(this._constants[offset]); // remove IValue\n                let value = null;\n                if (ivalue.isObject() && !ivalue.toObject().is_weak_compilation_ref()) {\n                    const obj = ivalue.toObject();\n                    if (!this.non_holding_object_cache.has(obj)) {\n                        this.non_holding_object_cache.set(obj, obj.copy_to_weak_compilation_ref());\n                    }\n                    value = m.graph().insertConstant(this.non_holding_object_cache[obj], loc);\n                } else {\n                    value = m.graph().insertConstant(this._constants[offset], loc);\n                }\n                value.setType(torch._C.unshapedType(value.type()));\n                return new torch._C.SimpleValue(value);\n            }\n        });\n        this.registerType('torch._C.CastValue', class extends torch._C.BuiltinFunction {\n            constructor(type, method) {\n                super(method, null);\n                this._type = type;\n            }\n            call(loc, m, args, kwargs, n_binders) {\n                if (args.length === 1 && kwargs.length === 0) {\n                    const len_op = new torch._C.BuiltinFunction('aten::len', null);\n                    const gt_op = new torch._C.BuiltinFunction('aten::gt', null);\n                    const zero = m.graph().insertConstant(new torch._C.IValue(0, 'Int'));\n                    const v = args[0].value(m.graph());\n                    if (v.type().isSubtypeOf(this._type)) {\n                        return new torch._C.SimpleValue(v);\n                    } else if (this._type === torch.BoolType.get() && (v.type().isSubtypeOf(torch.Type.get('AnyListType')) || v.type().isSubtypeOf(torch.StringType.get()) || v.type() instanceof torch.DictType)) {\n                        const len = len_op.call(loc, m, [v], [], 1);\n                        return gt_op.call(loc, m, [len.asValue(loc, m), zero], [], 1);\n                    }\n                }\n                return super.call(loc, m, args, kwargs, n_binders);\n            }\n        });\n        this.registerType('torch._C.MagicMethod', class extends torch._C.SugaredValue {\n            constructor(desugared_name, base) {\n                super();\n                this._base_value = base;\n                this._desugared_name = desugared_name;\n            }\n            call(loc, m, args, kwargs, n_binders) {\n                if (args.length > 0) {\n                    const self = args[0].value(m.graph());\n                    if (self.type() instanceof torch.ClassType) {\n                        return new torch._C.SimpleValue(self)\n                            .attr(loc, m, this._desugared_name)\n                            .call(loc, m, args.slice(1), kwargs, n_binders);\n                    }\n                }\n                if (!this._base_value) {\n                    throw new python.Error('Invalid magic method.');\n                }\n                return this._base_value.call(loc, m, args, kwargs, n_binders);\n            }\n        });\n        this.registerType('torch._C.RangeValue', class extends torch._C.SugaredValue {\n            constructor(loc, m, inputs, static_len) {\n                super();\n                static_len = static_len || null;\n                if (inputs.length === 0 || inputs.length > 3 || !inputs.every((value) => value.type() instanceof torch.IntType)) {\n                    throw new python.Error('Invalid range inputs.');\n                }\n                const g = m.graph();\n                if (inputs.length === 1) {\n                    [this._end] = inputs;\n                    this._start = g.insertConstant(0, loc);\n                    this._step = g.insertConstant(1, loc);\n                    this._has_only_end = true;\n                } else {\n                    [this._start, this._end] = inputs;\n                    this._step = inputs.length === 3 ? inputs[2] : g.insertConstant(1, loc);\n                    this._has_only_end = false;\n                }\n                this._static_len = static_len;\n            }\n            staticLen() {\n                return this._static_len;\n            }\n            iter() {\n                return this;\n            }\n            len(loc, m) {\n                if (this._static_len) {\n                    return torch._C.insertConstant(m.graph(), this._static_len, loc);\n                }\n                if (this._has_only_end) {\n                    return this._end;\n                }\n                const g = m.graph();\n                return g.insert('aten::__range_length', [this._start, this._end, this._step], [], loc);\n            }\n            getitem(loc, m, idx /*, type_hint */) {\n                if (this._has_only_end) {\n                    return new torch._C.SimpleValue(idx);\n                }\n                const g = m.graph();\n                return new torch._C.SimpleValue(g.insert('aten::__derive_index', [idx, this._start, this._step], [], loc));\n            }\n        });\n        this.registerType('torch._C.SliceValue', class extends torch._C.SugaredValue {\n        });\n        this.registerType('torch._C.ClassNamespaceValue', class extends torch._C.SugaredValue {\n            constructor(name, si) {\n                super();\n                this._basename = name;\n                this._si = si;\n            }\n            attr(loc, m, name) {\n                const fullName = new torch._C.QualifiedName(this._basename, name);\n                const serializable_type = this._si.findNamedType(fullName);\n                if (serializable_type) {\n                    if (serializable_type instanceof torch.ClassType) {\n                        return new torch._C.ClassValue(serializable_type);\n                    } else if (serializable_type instanceof torch.TupleType) {\n                        return new torch._C.NamedTupleConstructor(serializable_type);\n                    } else if (serializable_type instanceof torch.EnumType) {\n                        return new torch._C.SugaredEnumClass(serializable_type);\n                    }\n                }\n                const fn = this._si.findFunction(fullName);\n                if (fn) {\n                    return new torch._C.FunctionValue(fn);\n                }\n                return new torch._C.ClassNamespaceValue(fullName, this._si);\n            }\n        });\n        this.registerType('torch.package.PackageImporter', class {\n            constructor(reader) {\n                this.zip_reader = reader;\n            }\n            load_pickle(module, resource) {\n                const name = `${module.replace(/\\./, '/')}/${resource}`;\n                const stream = this.zip_reader.get_record(name);\n                const loaded_reduces = new Map();\n                this.storage_context = new torch._C.DeserializationStorageContext();\n                const unpickler = new pickle.Unpickler(stream);\n                unpickler.persistent_load = (saved_id) => {\n                    switch (saved_id[0]) {\n                        case 'storage': {\n                            const [, storage_type, key, , size] = saved_id;\n                            if (!this.storage_context.has_storage(key)) {\n                                const storage = new storage_type(size);\n                                if (!storage._set_cdata) {\n                                    throw new python.Error(`'${storage_type.__name__}._set_cdata' is not a function.`);\n                                }\n                                const stream = this.zip_reader.get_record(`.data/${key}.storage`);\n                                const buffer = stream.peek();\n                                storage._set_cdata(buffer);\n                                this.storage_context.add_storage(key, storage);\n                            }\n                            return this.storage_context.get_storage(key);\n                        }\n                        case 'reduce_package': {\n                            if (saved_id.length === 2) {\n                                const [, func, args] = saved_id;\n                                return execution.invoke(func, args);\n                            }\n                            const [, reduce_id, func, args] = saved_id;\n                            if (!loaded_reduces.has(reduce_id)) {\n                                const value = execution.invoke(func, [this].concat(args));\n                                loaded_reduces.set(reduce_id, value);\n                            }\n                            return loaded_reduces.get(reduce_id);\n                        }\n                        default: {\n                            throw new python.Error(`Unknown package typename '${saved_id[0]}'.`);\n                        }\n                    }\n                };\n                const obj = unpickler.load();\n                this.storage_context = null;\n                return obj;\n            }\n            import_module(name) {\n                return execution.import(name);\n            }\n        });\n        this.registerFunction('torch.jit.load', (file, map_location, extra_files) => {\n            const cu = new torch.jit.CompilationUnit();\n            cu.execution = execution;\n            const cpp_module = torch._C.import_ir_module(cu, file, map_location, extra_files);\n            const module = torch.jit._script.wrap_cpp_module(cpp_module);\n            module.forward = cpp_module.forward; // remove\n            return module;\n        });\n        this.registerFunction('torch._C.import_ir_module', function(cu, reader, ...args) {\n            switch (arguments.length) {\n                case 4: {\n                    const [device, extra_files] = args;\n                    const deserializer = new torch._C.ScriptModuleDeserializer(cu, reader);\n                    return deserializer.deserialize(device, extra_files);\n                }\n                case 5: {\n                    const [storage_context, device, ts_id] = args;\n                    const deserializer = new torch._C.ScriptModuleDeserializer(cu, reader, `.data/ts_code/${ts_id}/`, '.data/', storage_context);\n                    return deserializer.deserialize(device, null);\n                }\n                default: {\n                    throw new python.Error(\"Invalid 'torch._C.import_ir_module' signature.\");\n                }\n            }\n\n        });\n        this.registerFunction('torch._C._import_ir_module_from_package', (cu, reader, storage_context, map_location, ts_id) => {\n            return torch._C.import_ir_module(cu, reader, storage_context, null, ts_id);\n        });\n        this.registerFunction('torch._C.tryToGraphFunction', (value) => {\n            if (value instanceof torch.Node) {\n                const n = value;\n                if (n.kind() === 'prim::CallFunction') {\n                    torch._C.AT_ASSERT(n.input(0).node().kind() === 'prim::Constant');\n                    const function_constant = n.input(0).node();\n                    const fun_type = function_constant.output().type().expect(torch._C.FunctionType);\n                    return torch._C.tryToGraphFunction(fun_type.function());\n                }\n                if (n.kind() === 'prim::CallMethod') {\n                    const name = n.s('name');\n                    const class_type = n.input(0).type();\n                    if (class_type instanceof torch.ClassType) {\n                        const fn = class_type.getMethod(name);\n                        return torch._C.tryToGraphFunction(fn);\n                    }\n                }\n                return null;\n            } else if (value instanceof torch._C.Function) {\n                const fn = value;\n                if (!fn.isGraphFunction()) {\n                    return null;\n                }\n                return fn;\n            }\n            throw new python.Error('Not implemented.');\n        });\n        this.registerType('torch._C.ModuleInstanceInfo', class {\n            constructor(module_type, instance_name) {\n                this._module_type = module_type;\n                this._instance_name = instance_name;\n            }\n        });\n        this.registerFunction('torch._C.slice_indices_adjust', (length, start, stop, step) => {\n            torch._C.TORCH_CHECK(step !== 0);\n            torch._C.TORCH_CHECK(step >= -Number.MAX_SAFE_INTEGER); // INT64_MAX\n            if (start._ === Number.MAX_SAFE_INTEGER) {\n                start._ = (step < 0) ? Number.MAX_SAFE_INTEGER : 0;\n            }\n            if (stop._ === Number.MAX_SAFE_INTEGER) {\n                stop._ = (step < 0) ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER;\n            }\n            if (start._ < 0) {\n                start._ += length;\n                if (start._ < 0) {\n                    start._ = (step < 0) ? -1 : 0;\n                }\n            } else if (start._ >= length) {\n                start._ = (step < 0) ? length - 1 : length;\n            }\n            if (stop._ < 0) {\n                stop._ += length;\n                if (stop._ < 0) {\n                    stop._ = (step < 0) ? -1 : 0;\n                }\n            } else if (stop._ >= length) {\n                stop._ = (step < 0) ? length - 1 : length;\n            }\n            if (step < 0) {\n                if (stop._ < start._) {\n                    return Math.floor((start._ - stop._ - 1) / (-step) + 1);\n                }\n            } else if (start._ < stop._) {\n                return Math.floor((stop._ - start._ - 1) / step + 1);\n            }\n            return 0;\n        });\n        this.registerFunction('torch._C.createTupleUnpack', (v) => {\n            if (v.node().kind() === 'prim::TupleConstruct') {\n                return v.node().inputs();\n            }\n            const g = v.owningGraph();\n            return g.insertNode(g.createTupleUnpack(v)).outputs();\n        });\n        this.registerFunction('torch._C.inlineCallStackOfNode', (/* new_node, new_cs_entriesm, callee, to_replace, m_info */) => {\n            /*\n            const new_node_cs = new_node.callstack();\n            const raw_callstack_ptr = new_node_cs ? new_node_cs : nullptr;\n            if (!new_cs_entries.has(raw_callstack_ptr)) {\n                if (new_node_cs) {\n                    new_cs_entries.set(raw_callstack_ptr, c10::make_intrusive<InlinedCallStack>(*new_node_cs, callee, to_replace.sourceRange(), m_info));\n                } else {\n                    new_cs_entries.set(raw_callstack_ptr, c10::make_intrusive<InlinedCallStack>(callee, to_replace.sourceRange(), m_info);\n                }\n            }\n            new_node.setCallStack(new_cs_entries.at(raw_callstack_ptr));\n            for (const block of new_node.blocks()) {\n                torch._C.inlineCallStackOfBlock(block, new_cs_entries, callee, to_replace, m_info);\n            }\n            */\n        });\n        this.registerFunction('torch._C.inlineCallTo', (to_replace, callee, arg) => {\n            if (arg === undefined || typeof arg === 'boolean') {\n                const inline_optimized_graph = arg === undefined ? true : arg;\n                const graph = inline_optimized_graph ? callee.optimized_graph() : callee.graph();\n                return torch._C.inlineCallTo(to_replace, callee, graph);\n            }\n            if (arg instanceof torch.Graph === false) {\n                throw new python.Error('Invalid argument.');\n            }\n            const callee_graph = arg;\n            const guard = new torch._C.WithInsertPoint(to_replace);\n            const value_map = new Map();\n            const new_outputs = torch._C.insertGraph(to_replace.owningGraph(), callee_graph, to_replace.inputs(), value_map);\n            const new_callstack_entries = new Map();\n            let module_instance_info = null;\n            if (to_replace.kind() === 'prim::CallMethod') {\n                const class_type_ptr = to_replace.input(0).type();\n                if (to_replace.input(0).node().kind() === 'prim::GetAttr') {\n                    module_instance_info = new torch._C.ModuleInstanceInfo(class_type_ptr, to_replace.input(0).node().s('name'));\n                } else if (to_replace.owningGraph().inputs().length > 0 && to_replace.input(0) === to_replace.owningGraph().inputs()[0]) {\n                    module_instance_info = new torch._C.ModuleInstanceInfo(class_type_ptr, 'SELF');\n                } else {\n                    module_instance_info = new torch._C.ModuleInstanceInfo(class_type_ptr, 'INSTANCE_NAME_UNKNOWN');\n                }\n            }\n            const updated_nodes = new Set();\n            for (const kv of value_map) {\n                const is_graph_input = callee_graph.inputs().indexOf(kv[0]);\n                if (is_graph_input === -1) {\n                    continue;\n                }\n                const new_node = kv[1].node();\n                if (updated_nodes.has(new_node)) {\n                    continue;\n                }\n                updated_nodes.add(new_node);\n                torch._C.inlineCallStackOfNode(new_node, new_callstack_entries, callee, to_replace, module_instance_info);\n            }\n            const old_outputs = to_replace.outputs();\n            torch._C.AT_ASSERT(new_outputs.length === old_outputs.length);\n            for (let i = 0; i < old_outputs.length; i++) {\n                if (old_outputs[i].hasDebugName()) {\n                    new_outputs[i].setDebugName(old_outputs[i].debugName());\n                }\n                old_outputs[i].replaceAllUsesWith(new_outputs[i]);\n            }\n            to_replace.destroy();\n            guard.dispose();\n            return new_outputs;\n        });\n        this.registerFunction('torch._C.inlineCalls', (block) => {\n            for (const cur of block.nodes()) {\n                switch (cur.kind()) {\n                    case 'prim::CallFunction': {\n                        const graphFunction = torch._C.tryToGraphFunction(cur);\n                        if (graphFunction) {\n                            const function_constant = cur.input(0).node();\n                            // const fun_type = function_constant.output().type().expect(torch.FunctionType);\n                            cur.removeInput(0);\n                            let g = null;\n                            const fallback = function_constant.hasAttribute('fallback');\n                            if (fallback && graphFunction.get_executor().isOptimized()) {\n                                const exec_plans = graphFunction.get_executor().getDebugState().execution_plans;\n                                if (!exec_plans.empty()) {\n                                    g = exec_plans.begin().second.graph;\n                                    torch._C.Inline(g);\n                                }\n                            }\n                            if (g === null) {\n                                g = graphFunction.optimized_graph();\n                            }\n                            torch._C.inlineCallTo(cur, graphFunction, g);\n                        }\n                        break;\n                    }\n                    case 'prim::CallMethod': {\n                        const graphFunction = torch._C.tryToGraphFunction(cur);\n                        if (graphFunction) {\n                            torch._C.inlineCallTo(cur, graphFunction);\n                        }\n                        break;\n                    }\n                    default: {\n                        for (const b of cur.blocks()) {\n                            torch._C.inlineCalls(b);\n                        }\n                    }\n                }\n            }\n        });\n        this.registerFunction('torch._C.Inline', (graph) => {\n            torch._C.inlineCalls(graph.block());\n        });\n        this.registerFunction('torch._C._jit_pass_inline', (graph) => {\n            torch._C.Inline(graph);\n        });\n        this.registerFunction('torch._C._set_tensor_metadata', (/* tensor, metadata */) => {\n        });\n        this.registerFunction('torch.jit._script.unpackage_script_module', (importer, script_module_id) => {\n            const cu = new torch.jit.CompilationUnit();\n            cu.execution = execution;\n            const cpp_module = torch._C._import_ir_module_from_package(cu, importer.zip_reader, importer.storage_context, importer.last_map_location, script_module_id);\n            return torch.jit._script.wrap_cpp_module(cpp_module);\n        });\n        this.registerFunction('torch.jit._script.wrap_cpp_module', (cpp_module) => {\n            const init_fn = (script_module) => {\n                for (const [name, module] of new torch.ModuleDict(script_module._c).items()) {\n                    script_module.__setattr__(name, torch.jit._script.wrap_cpp_module(module));\n                }\n            };\n            return torch.jit._script.RecursiveScriptModule._construct(cpp_module, init_fn);\n        });\n        this.registerType('torch._C.DeserializationStorageContext', class extends Map {\n            has_storage(name) {\n                return this.has(name);\n            }\n            get_storage(name) {\n                return this.get(name);\n            }\n            add_storage(name, storage) {\n                return this.set(name, storage);\n            }\n        });\n        this.registerType('torch.ScriptFunction', class {\n            constructor(name, graph /*, function_creator */) {\n                this._name = name;\n                this._graph = graph;\n            }\n        });\n        this.registerType('torch.ScriptMethod', class {\n            constructor(owner, value) {\n                this._owner = owner;\n                this._function = value;\n            }\n            get name() {\n                return this._function.name();\n            }\n            get owner() {\n                return this._owner;\n            }\n            __call__(/* args, kwargs */) {\n                throw new python.Error(\"'torch.ScriptMethod.__call__' not implemented.\");\n            }\n            get graph() {\n                return this._function.graph();\n            }\n            get schema() {\n                // return this.function().getSchema();\n                throw new python.Error(\"'torch.ScriptMethod.schema' not implemented.\");\n            }\n            get code() {\n                throw new python.Error(\"'torch.ScriptMethod.code' not implemented.\");\n            }\n            get code_with_constants() {\n                throw new python.Error(\"'torch.ScriptMethod.code_with_constants' not implemented.\");\n            }\n        });\n        this.registerType('torch.ScriptObject', class {\n            constructor(type) {\n                this._typ = type;\n                this._ivalue = {};\n            }\n            static create(type) {\n                if (type.is_module()) {\n                    return new torch.ScriptModule(type);\n                }\n                return new torch.ScriptObject(type);\n            }\n            type() {\n                return this._typ;\n            }\n            _type() {\n                return this._typ; // torch.ClassType\n            }\n            __setstate__(state) {\n                const [attrs, qualname] = state;\n                this._typ = torch._C.getCustomClass(qualname);\n                if (!this._typ) {\n                    throw new python.Error(`Unsupported custom class '${qualname}'.`);\n                }\n                for (let i = 0; i < this._typ.numAttributes(); i++) {\n                    const name = this._typ.getAttributeName(i);\n                    this.__setattr__(name, attrs[i]);\n                }\n            }\n            find_method(basename) {\n                for (const fn of this.type().methods()) {\n                    if (fn.name() === basename) {\n                        return new torch.ScriptMethod(this /* _value() */, fn);\n                    }\n                }\n                return null;\n            }\n            _get_method(name) {\n                const method = this.find_method(name);\n                if (method) {\n                    return method;\n                }\n                torch._C.TORCH_CHECK(false, `Method '${name}' is not defined.`);\n                return null;\n            }\n            _has_method(name) {\n                return this.find_method(name) ? true : false;\n            }\n            _method_names() {\n                return this.type().methods().map((fn) => fn.name());\n            }\n            __setattr__(name, value) {\n                // if (this._type.hasContant(name))\n                this._ivalue[name] = value;\n            }\n            __getattr__(name) {\n                return this._ivalue[name];\n            }\n            hasattr(name) {\n                return this._typ.hasAttribute(name) || this._typ.hasConstant(name);\n            }\n            getattr(name) {\n                return this.__getattr__(name);\n            }\n            _properties() {\n                throw new python.Error(\"'torch.ScriptObject._properties' not implemented.\");\n            }\n            is_weak_compilation_ref() {\n                return true; // not implemented\n            }\n        });\n        this.registerType('torch.ScriptModule', class extends torch.ScriptObject {\n            constructor(...args) {\n                if (args[0] instanceof torch._C.QualifiedName && args[1] instanceof torch.jit.CompilationUnit) {\n                    const [class_name, cu, shouldMangle] = args;\n                    super(...torch.ScriptModule.create_module_object(class_name, cu, shouldMangle));\n                } else {\n                    super(...args);\n                }\n            }\n            get qualified_name() {\n                return this.type().qualified_name();\n            }\n            get code_with_constants() {\n                const const_map = {};\n                const_map.const_mapping = new Map(Object.entries(execution.builtins.CONSTANTS));\n                return [null, const_map];\n            }\n            get graph() {\n                if (!this._graph) {\n                    const fn = this._typ.getMethod('forward');\n                    this._graph = fn.graph();\n                }\n                return this._graph;\n            }\n            static create_module_object(class_name, cu, shouldMangle) {\n                shouldMangle = shouldMangle || false;\n                if (!class_name.prefix()) {\n                    class_name = new torch._C.QualifiedName('__torch__', class_name.name());\n                }\n                if (shouldMangle && cu.get_class(class_name)) {\n                    class_name = cu.mangle(class_name);\n                }\n                const cls = torch.ClassType.create(class_name, cu, true);\n                cu.register_type(cls);\n                return [cls, cu];\n            }\n            register_module(name, module) {\n                this.type().addOrCheckAttribute(name, module.type());\n                this.__setattr__(name, module); // _ivalue()->setAttr(name, module._ivalue());\n            }\n            register_buffer(name, v) {\n                this.type().addOrCheckAttribute(name, torch.TensorType.get(), false, true);\n                this.__setattr__(name, v); // _ivalue()->setAttr(name, std::move(v));\n            }\n            register_parameter(name, v, is_buffer) {\n                this.type().addOrCheckAttribute(name, torch.TensorType.get(), !is_buffer, is_buffer);\n                this.__setattr__(name, v); // _ivalue()->setAttr(name, std::move(v));\n            }\n            register_attribute(name, t, v, is_param, is_buffer) {\n                this.type().addOrCheckAttribute(name, t, is_param, is_buffer);\n                // _ivalue()->setAttr(name, v);\n            }\n        });\n        this.registerType('torch.ModuleDict', class {\n            constructor(mod) {\n                this._module = mod;\n            }\n            items() {\n                const result = new Map();\n                const type = this._module.type();\n                for (let i = 0; i < type.numAttributes(); i++) {\n                    const k = type.getAttributeName(i);\n                    const t = type.getAttribute(i);\n                    if (t && t.is_module()) {\n                        result.set(k, this._module.__getattr__(k));\n                    }\n                }\n                return result;\n            }\n        });\n        this.registerType('torch.ParameterDict', class {\n            constructor(mod) {\n                this._module = mod;\n            }\n            items() {\n                const result = new Map();\n                const type = this._module.type();\n                for (let i = 0; i < type.numAttributes(); i++) {\n                    if (type.is_parameter(i)) {\n                        const k = type.getAttributeName(i);\n                        const v = this._module.__getattr__(k);\n                        if (v instanceof torch.Tensor) {\n                            result.set(k, v);\n                        }\n                    }\n                }\n                return result;\n            }\n        });\n        this.registerType('torch.BufferDict', class {\n            constructor(mod) {\n                this._module = mod;\n            }\n            items() {\n                const result = new Map();\n                const type = this._module.type();\n                for (let i = 0; i < type.numAttributes(); i++) {\n                    if (type.is_buffer(i)) {\n                        const t = type.getAttribute(i);\n                        if (t.isSubtypeOf(torch.TensorType.get())) {\n                            const k = type.getAttributeName(i);\n                            const v = this._module.__getattr__(k);\n                            result.set(k, v);\n                        }\n                    }\n                }\n                return result;\n            }\n        });\n        this.registerType('torch._C.to_ir', class {\n            constructor(def, _resolver, self, method) {\n                this.method = method;\n                this.graph = method.graph();\n                this.resolver = _resolver;\n                this.integral_constants = new Map();\n                this.fp_constants = new Map();\n                this.complex_constants = new Map();\n                this.exit_blocks = new Set();\n                this._typeParser = new torch._C.ScriptTypeParser(this.resolver);\n                this._loop_status = 'NOT_IN_LOOP';\n                this.environment_stack = null;\n                this._def_stack = [];\n                this._temp_name_count = 0;\n                torch._C.AT_ASSERT(this.resolver);\n                this.pushFrame(this.graph.block(), true);\n                if (self && def && def.args.args.length === 0) {\n                    throw new python.Error('Method must have a self argument.');\n                }\n                method.setSchema(this.emitDef(def, self, this.graph.block()));\n                // torch._C.ReplaceOldOperatorsWithUpgraders(this.graph);\n                torch._C.ConvertToSSA(this.graph);\n                torch._C.CanonicalizeModifiedLoops(this.graph);\n                torch._C.NormalizeOps(this.graph.block());\n                torch._C.runCleanupPasses(this.graph);\n            }\n            pushFrame(b, starts_def) {\n                starts_def = starts_def || false;\n                if (starts_def) {\n                    this._def_stack.push({});\n                }\n                this.environment_stack = new torch._C.Environment(this.method, this.resolver, b, this.environment_stack);\n            }\n            popFrame(ends_def) {\n                const old_frame = this.environment_stack;\n                this.environment_stack = this.environment_stack.next;\n                if (ends_def) {\n                    this._def_stack.pop();\n                }\n                return old_frame;\n            }\n            emitDef(def, self, block) {\n                const schema = this._typeParser.parseSchemaFromDef(def, self !== null);\n                if (schema.returns.length === 1) {\n                    this._def_stack[this._def_stack.length - 1]._declared_return_type = schema.returns[0].type;\n                }\n                const args = this.emitFormalArguments(def, self, schema, block);\n                this.emitStatements(def.body);\n                this.handleMaybeNoReturn(def, block);\n                const returns = [this.emitOutput(def, schema, block)];\n                return new torch.FunctionSchema(def.name, '', args, returns);\n            }\n            emitFormalArguments(def, self, schema, block) {\n                const args = [];\n                const params = def.args.args;\n                const expected_annotation_size = self ? def.args.args.length - 1 : def.args.args.length;\n                if (schema.arguments.length !== expected_annotation_size) {\n                    throw new python.Error('Invalid formal arguments.');\n                }\n                let it = 0;\n                if (self) {\n                    const param = params[it];\n                    const name = param.arg;\n                    const new_input = block.addInput().setDebugName(name);\n                    this.environment_stack.setSugaredVar(param.range(), name, self.makeSugared(new_input), null);\n                    args.push(new torch.Argument(name, new_input.type()));\n                    it++;\n                }\n                const shouldDeriveType = this.shouldDeriveSetStateType(def, schema);\n                let arg_annotation_idx = 0;\n                for (; it < params.length; it++) {\n                    const param = params[it];\n                    const name = param.arg;\n                    const new_input = block.addInput();\n                    if (torch._C.meaningfulName(name)) {\n                        new_input.setDebugName(name);\n                    }\n                    let arg = schema.arguments[arg_annotation_idx++];\n                    if (shouldDeriveType) {\n                        if (schema.arguments.length === 1) {\n                            throw new python.Error('Invalid schema.');\n                        }\n                        const inferredStateType = this.getTypeForSetStateArg(def, self);\n                        arg = arg.cloneWithType(inferredStateType);\n                    }\n                    args.push(arg);\n                    new_input.setType(arg.type);\n                    this.environment_stack.setVar(param.range(), name, new_input);\n                }\n                return args;\n            }\n            emitOutput(range, schema, block) {\n                const ret_type = this._def_stack[this._def_stack.length - 1]._merged_return_type;\n                const placeholder_return = this.graph.insertNode(this.graph.createUninitialized(ret_type)).output();\n                block.registerOutput(placeholder_return);\n                return new torch.Argument('', this._def_stack[this._def_stack.length - 1]._merged_return_type);\n            }\n            emitStatements(stmts) {\n                for (let i = 0; i < stmts.length; i++) {\n                    const stmt = stmts[i];\n                    if (stmt instanceof ast.If) {\n                        this.emitIf(stmt);\n                    } else if (stmt instanceof ast.While) {\n                        this.emitWhile(stmt);\n                    } else if (stmt instanceof ast.For) {\n                        this.emitFor(stmt);\n                    } else if (stmt instanceof ast.Assign) {\n                        this.emitAssignment(stmt);\n                    } else if (stmt instanceof ast.AnnAssign) {\n                        this.emitAssignment(stmt);\n                    } else if (stmt instanceof ast.Expr) {\n                        this.emitSugaredExpr(stmt.value, 0);\n                    } else if (stmt instanceof ast.Return) {\n                        this.emitReturn(stmt);\n                    } else if (stmt instanceof ast.Pass) {\n                        // pass\n                    } else if (stmt instanceof ast.With) {\n                        this.emitWith(stmt);\n                    } else {\n                        throw new python.Error(`Unrecognized statement kind '${stmt.__class__.__name__}'.`);\n                    }\n                    if (this.exit_blocks.has(this.environment_stack.block())) {\n                        return;\n                    }\n                }\n            }\n            emitWith(stmt) {\n                const targets = stmt.items;\n                const entered = [];\n                for (const target of targets) {\n                    const e = target.context_expr;\n                    const rhs = this.emitExpr(e);\n                    const n = this.graph.insertNode(this.graph.create('prim::Enter', [rhs]));\n                    entered.push(rhs);\n                    if (rhs.type() instanceof torch.ClassType === false) {\n                        throw new python.Error('With item expression must return an object.');\n                    }\n                    const rhsClass = rhs.type();\n                    const enterMethod = rhsClass.findMethod('__enter__');\n                    const exitMethod = rhsClass.findMethod('__exit__');\n                    if (!enterMethod || !exitMethod) {\n                        throw new python.Error('Object returned by with item expression does not define __enter__ and __exit__ methods.');\n                    }\n                    const enterSchema = enterMethod.getSchema();\n                    if (enterSchema.arguments.length !== 1) {\n                        throw new python.Error('__enter__ must have only one argument and one return value.');\n                    }\n                    const exitSchema = exitMethod.getSchema();\n                    if (exitSchema.arguments.length === 4) {\n                        for (let i = 1; i < 4; i++) {\n                            if (exitSchema.arguments[i].type !== torch.AnyType.get()) {\n                                throw new python.Error('Argument of __exit__ must have Any type.');\n                            }\n                        }\n                    } else {\n                        throw new python.Error('__exit__ must have four arguments');\n                    }\n                    n.output(0).setType(enterSchema.returns[0].type);\n                    if (target.optional_vars) {\n                        throw new python.Error('Not implemented.');\n                        // Var i = target.var().get();\n                        // this.environment_stack.setVar(i.range(), i.name().name(), n.output(0));\n                    }\n                }\n                this.emitStatements(stmt.body);\n                while (entered.length > 0) {\n                    const input = entered.pop();\n                    const n = this.graph.create('prim::Exit');\n                    this.graph.insertNode(n);\n                    n.addInput(input);\n                }\n            }\n            emitLoopCommon(range, emit_body, iter_val, targets, cond) {\n                let max_trip_count_val = null;\n                if (iter_val === null) {\n                    max_trip_count_val = torch._C.materializeConstant(Number.MAX_SAFE_INTEGER /*std::numeric_limits<int64_t>::max()*/, this.graph, range, this.integral_constants);\n                } else {\n                    max_trip_count_val = iter_val.len(range, this.method);\n                }\n                const n = this.graph.insertNode(this.create('prim::Loop', range, 0));\n                const body_block = n.addBlock();\n                {\n                    const condition_block = n.addBlock();\n                    this.pushFrame(condition_block);\n                    let out = null;\n                    if (cond) {\n                        const insert = new torch._C.WithInsertPoint(condition_block);\n                        out = this.emitToBool(cond.range(), this.emitExpr(cond));\n                        insert.dispose();\n                    } else {\n                        const insert = new torch._C.WithInsertPoint(n);\n                        out = this.graph.insertConstant(true, range);\n                        insert.dispose();\n                    }\n                    condition_block.registerOutput(out);\n                    this.popFrame();\n                }\n                n.addInput(max_trip_count_val);\n                const loop_guard = new torch._C.WithLoopStatus(this, 'IN_LOOP');\n                const trip_count = body_block.addInput().setType(torch.IntType.get());\n                {\n                    this.pushFrame(body_block);\n                    const guard = new torch._C.WithInsertPoint(body_block);\n                    if (iter_val !== null && targets) {\n                        const cur_elem = iter_val.getitem(range, this.method, trip_count).asValue(range, this.method);\n                        const sv = new torch._C.SimpleValue(cur_elem);\n                        const target_exprs = targets;\n                        this.validateAssignLhsExpr(target_exprs, range);\n                        if (target_exprs.length > 1) {\n                            throw new python.Error('Not implemented.');\n                            // const tl = torch.TupleLiteral.create(range, target_exprs);\n                            // target_exprs = ListExpr.create(range, [tl]);\n                        }\n                        this.emitExprsAssign(target_exprs, [sv], range, /*n_binders=*/1);\n                    }\n                    emit_body();\n                    this.popFrame();\n                    guard.dispose();\n                }\n                loop_guard.dispose();\n            }\n            emitFor(...args) {\n                if (args.length === 1 && args[0] instanceof ast.For) {\n                    const [stmt] = args;\n                    const emit_body = () => this.emitStatements(stmt.body);\n                    this.emitFor(stmt.target, stmt.iter, stmt.range(), emit_body);\n                } else if (args.length === 4) {\n                    const [targets, itrs, loc, emit_body] = args;\n                    if (itrs instanceof ast.Tuple) {\n                        throw new python.Error('List of iterables is not supported currently.');\n                    }\n                    const sv = this.emitSugaredExpr(itrs, 1);\n                    const iterable = sv.iter(loc, this.method);\n                    if (iterable.shouldEmitUnrolled()) {\n                        this.emitUnrolledLoop(loc, emit_body, iterable, targets);\n                    } else {\n                        this.emitLoopCommon(loc, emit_body, iterable, [targets], null);\n                    }\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n            emitWhile(stmt) {\n                const cond = stmt.test;\n                const emit_body = () => this.emitStatements(stmt.body);\n                this.emitLoopCommon(stmt.range(), emit_body, null, [], cond);\n            }\n            emitIsInstance(obj, classinfo) {\n                const lhs_val = this.emitExpr(obj);\n                const lhs_types = [];\n                const rhs_types = [];\n                const gather_rhs = (expr) => {\n                    if (expr instanceof ast.Tuple) {\n                        for (const e of expr.elts) {\n                            gather_rhs(e);\n                        }\n                        return;\n                    }\n                    const type = this._typeParser.parseTypeFromExpr(expr);\n                    rhs_types.push(type);\n                };\n                lhs_types.push(lhs_val.type());\n                gather_rhs(classinfo);\n                torch._C.standardizeVectorForUnion(lhs_types);\n                torch._C.standardizeVectorForUnion(rhs_types);\n                let refinement = new torch._C.RefinementSet([], []);\n                let unified_true = null;\n                let unified_false = null;\n                const isinstance_types = [];\n                const not_isinstance_types = [];\n                let true_refinements = [];\n                let false_refinements = [];\n                let all_lhs_subtype_some_rhs = true;\n                for (const lhs_type of lhs_types) {\n                    if (lhs_type === torch.AnyType.get()) {\n                        isinstance_types.push(...rhs_types);\n                        not_isinstance_types.push(torch.AnyType.get());\n                        if (isinstance_types.length !== 1 || isinstance_types[0] !== torch.AnyType.get()) {\n                            all_lhs_subtype_some_rhs = false;\n                        }\n                        break;\n                    }\n                    const get_smaller_type = (t1, t2) => {\n                        if (t1.isSubtypeOf(t2)) {\n                            return t1;\n                        } else if (t2.isSubtypeOf(t1)) {\n                            return t2;\n                        }\n                        return null;\n                    };\n                    let found_refinement = null;\n                    for (const rhs_type of rhs_types) {\n                        const maybe_smaller_type = get_smaller_type(lhs_type, rhs_type);\n                        if (!maybe_smaller_type) {\n                            continue;\n                        } else if (maybe_smaller_type === lhs_type) {\n                            found_refinement = lhs_type;\n                        } else if (maybe_smaller_type === rhs_type) {\n                            found_refinement = found_refinement ? torch._C.unifyTypes(found_refinement, rhs_type) : rhs_type;\n                        }\n                    }\n                    if (found_refinement) {\n                        if (found_refinement === lhs_type) {\n                            all_lhs_subtype_some_rhs &= true;\n                        }\n                        isinstance_types.push(found_refinement);\n                    } else {\n                        not_isinstance_types.push(lhs_type);\n                        all_lhs_subtype_some_rhs = false;\n                    }\n                }\n                if (isinstance_types.length > 0) {\n                    unified_true = torch._C.unifyTypeList(isinstance_types, null, /*default_to_union=*/true);\n                }\n                if (obj instanceof ast.Name && unified_true) {\n                    const ident = obj.id;\n                    true_refinements = [new torch._C.Refinement(ident, unified_true)];\n                }\n                if (not_isinstance_types.length > 0) {\n                    unified_false = torch._C.unifyTypeList(not_isinstance_types, null, /*default_to_union=*/true);\n                }\n                if (obj instanceof ast.Name && unified_false) {\n                    const ident = obj.id;\n                    false_refinements = [new torch._C.Refinement(ident, unified_false)];\n                }\n                refinement = new torch._C.RefinementSet(true_refinements, false_refinements);\n                const is_statically_false = isinstance_types.length === 0;\n                if (all_lhs_subtype_some_rhs) {\n                    return new torch._C.CondValue(this.graph, obj.range(), true, refinement);\n                }\n                if (is_statically_false) {\n                    return new torch._C.CondValue(this.graph, obj.range(), false, refinement);\n                }\n                const result = this.graph.insertNode(this.graph.createIsInstance(lhs_val, rhs_types)).output();\n                return new torch._C.CondValue(result, refinement, null);\n            }\n            emitIf(stmt) {\n                const cond_value = this.emitCondExpr(stmt.test);\n                this.emitIfElseBlocks(stmt.range(), cond_value, stmt.body, stmt.orelse);\n            }\n            emitCondExpr(expr) {\n                /*\n                switch (expr.kind()) {\n                    case TK_AND:\n                    case TK_OR: {\n                      const binop = BinOp(expr);\n                      return emitShortCircuitLogical(\n                          binop.range(), binop.lhs(), binop.rhs(), expr.kind() == TK_OR);\n                    }\n                    case TK_NOT: {\n                      CondValue v = emitCondExpr(Expr(expr.tree().trees()[0]));\n                      Value* result = emitBuiltinCall(\n                          expr.range(), *graph, aten::__not__, {v.value()}, {});\n                      std::optional<bool> static_if;\n                      if (v.staticIf()) {\n                        static_if = !*v.staticIf();\n                      }\n                      return CondValue(result, v.refinements().Not(), static_if);\n                    } break;\n                    case TK_IS:\n                    case TK_ISNOT: {\n                      // meta programming on AST for is/is not cases and emit branches base on\n                      const cond_op = BinOp(expr);\n                      Value* lhs_val = emitExpr(cond_op.lhs());\n                      Value* rhs_val = emitExpr(cond_op.rhs());\n                      const lhs_none = canBeNone(lhs_val);\n                      const rhs_none = canBeNone(rhs_val);\n                      // Dispatch logic (A: ALWAYS, N: NEVER, M: MAYBE):\n                      // AA, -> statically IS always holds, IS_NOT never holds\n                      // AN , NA-> statically IS_NOT always holds, IS never holds\n                      // MA, MM, MN, NM, NN, AM -> cannot prove anything statically\n                      bool its_is = expr.kind() == TK_IS;\n                      if (lhs_none == ALWAYS && rhs_none == ALWAYS) {\n                        return CondValue(*graph, expr.range(), its_is, {});\n                      } else if (\n                          (lhs_none == ALWAYS && rhs_none == NEVER) ||\n                          (lhs_none == NEVER && rhs_none == ALWAYS)) {\n                        // lhs_val/rhs_val with A/M: only emit never_none_branch\n                        return CondValue(*graph, expr.range(), !its_is, {});\n                      } else {\n                        const kind = getNodeKind(expr.kind(), expr.get()->trees().size());\n                        Value* cond_value = emitBuiltinCall(\n                            expr.get()->range(),\n                            *method.graph(),\n                            kind,\n                            {lhs_val, rhs_val},\n                            {});\n                        const refinements = RefinementSet(findIsNoneRefinements(\n                            cond_op.lhs(), lhs_val, cond_op.rhs(), rhs_val, expr.kind()));\n                        return CondValue(cond_value, refinements, null);\n                      }\n                    } break;\n                */\n                if (expr instanceof ast.UnaryOp) {\n                    throw new python.Error('Not implemented.');\n                }\n                if (expr instanceof ast.Call) {\n                    const apply = expr;\n                    const callee = expr.func;\n                    if (callee instanceof ast.Name) {\n                        if (callee.id === 'isinstance') {\n                            this.checkApplyNumInputs(apply, 2);\n                            return this.emitIsInstance(apply.args[0], apply.args[1]);\n                        }\n                        if (callee.id === 'hasattr') {\n                            this.checkApplyNumInputs(apply, 2);\n                            return this.emitHasAttr(apply.args[0], apply.args[1]);\n                        }\n                        const sv = this.emitSugaredExpr(callee, 1);\n                        if (sv instanceof torch._C.SpecialFormValue) {\n                            if (sv.form() === 'prim::isinstance') {\n                                this.checkApplyNumInputs(apply, 2);\n                                return this.emitIsInstance(apply.inputs()[0], apply.inputs()[1]);\n                            }\n                        }\n                    }\n                }\n                const expr_out = this.emitToBool(expr, this.emitExpr(expr));\n                let static_if = null;\n                const kind = expr_out.node().kind();\n                if (kind === 'aten::is_scripting') {\n                    static_if = true;\n                } else if (kind === 'aten::has_torch_function') {\n                    static_if = false;\n                }\n                const maybe_ivalue = torch._C.toIValue(expr_out);\n                if (maybe_ivalue) {\n                    static_if = maybe_ivalue.toBool();\n                }\n                return new torch._C.CondValue(expr_out, new torch._C.RefinementSet([], []), static_if);\n            }\n            emitIfElseBlocks(loc, cond_value, trueBranch, falseBranch) {\n                if (cond_value.staticIf() !== null) {\n                    if (cond_value.staticIf()) {\n                        this.insertRefinements(loc, cond_value.refinements());\n                        this.emitStatements(trueBranch);\n                    } else {\n                        this.insertRefinements(loc, cond_value.refinements().Not());\n                        this.emitStatements(falseBranch);\n                    }\n                    return;\n                }\n                const n = this.graph.insertNode(this.create('prim::If', loc, 0));\n                n.addInput(cond_value.value());\n                const true_block = n.addBlock();\n                const false_block = n.addBlock();\n                const save_true = this.emitSingleIfBranch(true_block, trueBranch, cond_value.refinements());\n                const save_false = this.emitSingleIfBranch(false_block, falseBranch, cond_value.refinements().Not());\n                const true_exits = this.exit_blocks.has(true_block);\n                const false_exits = this.exit_blocks.has(false_block);\n                if (true_exits && false_exits) {\n                    this.exit_blocks.add(n.owningBlock());\n                }\n                const mutated_variables = new Set();\n                for (const v of save_true.definedVariables()) {\n                    const insert = new torch._C.WithInsertPoint(false_block);\n                    if (save_false.findInAnyFrame(v) || false_exits) {\n                        mutated_variables.add(v);\n                    } else {\n                        this.environment_stack.setVariableTypeError(v, () => 'Value is not defined in the false branch.');\n                    }\n                    insert.dispose();\n                }\n                for (const v of save_false.definedVariables()) {\n                    const insert = new torch._C.WithInsertPoint(true_block);\n                    if (save_true.findInAnyFrame(v) || true_exits) {\n                        mutated_variables.add(v);\n                    } else {\n                        this.environment_stack.setVariableTypeError(v, () => 'Value is not defined in the true branch.');\n                    }\n                    insert.dispose();\n                }\n                for (const x of mutated_variables) {\n                    let tv = null;\n                    let fv = null;\n                    {\n                        const insert = new torch._C.WithInsertPoint(true_block);\n                        if (!true_exits) {\n                            tv = save_true.getVar(x, loc);\n                        }\n                        insert.dispose();\n                    }\n                    {\n                        const insert = new torch._C.WithInsertPoint(false_block);\n                        if (!false_exits) {\n                            fv = save_false.getVar(x, loc);\n                        }\n                        insert.dispose();\n                    }\n                    if (true_exits && false_exits) {\n                        continue;\n                    } else if (true_exits) {\n                        tv = this.graph.createUninitialized(fv.type()).insertBefore(true_block.return_node()).output();\n                        this.graph.createStore(x, tv).insertBefore(true_block.return_node());\n                    } else if (false_exits) {\n                        fv = this.graph.createUninitialized(tv.type()).insertBefore(false_block.return_node()).output();\n                        this.graph.createStore(x, fv).insertBefore(false_block.return_node());\n                    }\n                    const maybe_sugared_x = this.environment_stack.findInAnyFrame(x);\n                    let full_type = null;\n                    if (maybe_sugared_x) {\n                        const maybe_simple = torch._C.asSimple(maybe_sugared_x);\n                        if (maybe_simple) {\n                            full_type = maybe_simple.type();\n                        }\n                    }\n                    const default_to_union = full_type && (full_type instanceof torch.UnionType || full_type instanceof torch.OptionalType || full_type instanceof torch.NumberType);\n                    const unified = torch._C.unifyTypes(tv.type(), fv.type(), /*default_to_union=*/default_to_union);\n                    if (!unified) {\n                        if (save_true.findInParentFrame(x) || save_false.findInParentFrame(x)) {\n                            throw new python.Error('Type mismatch.');\n                        } else {\n                            this.environment_stack.setVariableTypeError(x, () => 'Type mismatch.');\n                            continue;\n                        }\n                    }\n                    this.environment_stack.setType(x, unified);\n                }\n            }\n            emitSingleIfBranch(b, branch, refinements) {\n                this.pushFrame(b);\n                const guard = new torch._C.WithInsertPoint(b);\n                this.insertRefinements(branch, refinements);\n                this.emitStatements(branch);\n                const frame = this.popFrame();\n                guard.dispose();\n                return frame;\n            }\n            create(kind, loc, n_outputs) {\n                return this.graph.create(kind, n_outputs).setSourceRange(loc);\n            }\n            refineAndSetUnionTypeHintOrPopulateCandidatesVector(type_hint, refined_type_hint_ptr, all_candidates, match_repr, src, type_match, do_if_match, do_if_anytype, is_dict_constructor) {\n                is_dict_constructor = is_dict_constructor || false;\n                if (refined_type_hint_ptr._ instanceof torch.UnionType) {\n                    const candidate_types = refined_type_hint_ptr._.containedTypes().filter((type_ptr) => type_match(type_ptr));\n                    if (!is_dict_constructor && candidate_types.length === 0) {\n                        throw new python.Error(\"No matching types found in Union type annotation.\");\n                    } else if (candidate_types.length === 1) {\n                        [refined_type_hint_ptr._] = candidate_types;\n                    } else {\n                        all_candidates._ = candidate_types;\n                    }\n                } else if (refined_type_hint_ptr._ instanceof torch.OptionalType) {\n                    refined_type_hint_ptr._ = refined_type_hint_ptr._.getElementType();\n                }\n                if (is_dict_constructor) {\n                    return;\n                }\n                if (all_candidates._.length === 0) {\n                    if (type_match(refined_type_hint_ptr._)) {\n                        do_if_match();\n                    } else if (refined_type_hint_ptr._.kind() === 'AnyType') {\n                        do_if_anytype();\n                    } else {\n                        throw new python.Error('Invalid annotation type.');\n                    }\n                }\n            }\n            emitToBool(loc, v) {\n                let out = null;\n                const bool_cast = this.environment_stack.getSugaredVar('bool', loc);\n                out = torch._C.asSimple(bool_cast.call(loc, this.method, [new torch._C.NamedValue(v)], [], 0));\n                if (!out) {\n                    throw new python.Error('Could not cast value to bool.');\n                }\n                if (!out.type().isSubtypeOf(torch.BoolType.get())) {\n                    throw new python.Error('Expected a bool expression for condition.');\n                }\n                return out;\n            }\n            emitUnaryOp(tree, magicMethod, opSymbol) {\n                const inputs = [tree.operand];\n                const named_values = this.getNamedValues(inputs, /*maybe_unpack=*/false);\n                const val = torch._C.asSimple(torch._C.makeMagic(magicMethod, new torch._C.BuiltinFunction(opSymbol, null)).call(tree.range(), this.method, named_values, [], 0));\n                if (val.node().kind() !== opSymbol) {\n                    return val;\n                }\n                const maybe_out_stack = torch._C.runNodeIfInputsAreConstant(val.node());\n                if (!maybe_out_stack) {\n                    return val;\n                }\n                torch._C.TORCH_INTERNAL_ASSERT(maybe_out_stack.length === 1);\n                return this.graph.insertConstant(maybe_out_stack[0], tree);\n            }\n            emitAssignment(stmt) {\n                if (stmt instanceof ast.AnnAssign) {\n                    return this.emitSingleAssignment(stmt);\n                }\n                if (stmt.targets.length === 1) {\n                    const entries = Object.entries(stmt).filter(([key]) => key !== 'targets' && key !== 'value' && key !== 'ctx');\n                    const assign = new ast.AnnAssign(stmt.targets[0], null, stmt.value, stmt.targets[0] instanceof ast.Name);\n                    for (const [key, value] of entries) {\n                        assign[key] = value;\n                    }\n                    return this.emitSingleAssignment(assign);\n                }\n                if (stmt.targets.length <= 1) {\n                    throw new python.Error('Invalid assignment.');\n                }\n                throw new python.Error('Not implemented.');\n                /*\n                const tmp_name = this.createTempName('$tmp_assign_');\n                this.environment_stack.setSugaredVar(stmt.value, tmp_name, this.emitSugaredExpr(stmt.value, 1), annotated_type=null);\n                const ident = new ast.Name(tmp_name);\n                for (const expr of lhs_list) {\n                    const assign = new ast.Assign(targets, value, ctx);\n                    this.emitSingleAssignment(Assign.create(stmt,\n                        List<Expr>.create(expr.range(), [expr]),\n                        Maybe<Expr>::create(stmt.rhs().range(), ident),\n                            Maybe<Expr>::create(stmt.range())));\n                }\n                */\n            }\n            emitSingleAssignment(stmt) {\n                torch._C.AT_ASSERT(stmt instanceof ast.AnnAssign);\n                const rhs = stmt.value;\n                const lhs = stmt.target;\n                if (lhs instanceof ast.Name) {\n                    let type = null;\n                    if (stmt.annotation) {\n                        type = this._typeParser.parseTypeFromExpr(stmt.annotation);\n                    }\n                    const rhs_sugared_val = this.emitSugaredExpr(rhs, 1, type);\n                    // BC HACK\n                    this.environment_stack.setSugaredVar(stmt.range(), lhs.id, rhs_sugared_val, /*annotated_type=*/type);\n                } else if (lhs instanceof ast.Tuple) {\n                    this.emitTupleAssign(lhs, rhs);\n                } else if (lhs instanceof ast.Attribute) {\n                    this.emitSelectAssign(lhs, rhs, null, stmt.range());\n                } else {\n                    throw new python.Error('Unexpected expression on left-hand side of assignment.');\n                }\n            }\n            emitSelectAssign(lhs, rhs, type, loc) {\n                if (!rhs) {\n                    throw new python.Error('Expected RHS for assignment.');\n                }\n                let type_hint = null;\n                if (type) {\n                    type_hint = this._typeParser.parseTypeFromExpr(type);\n                }\n                const lhsObject = this.emitSugaredExpr(lhs.value, 1);\n                const rhsValue = this.emitSugaredExpr(rhs, 1, type_hint).asValue(rhs.range(), this.method);\n                lhsObject.setAttr(loc, this.method, lhs.attr, rhsValue);\n            }\n            emitTupleAssign(...args) {\n                if (args.length === 2) {\n                    const [tl, rhs] = args;\n                    let n_binders = tl.elts.length;\n                    const starred_unpack = this.validateAssignLhsExpr(tl.elts, tl);\n                    if (starred_unpack) {\n                        n_binders--;\n                    }\n                    const output = this.emitSugaredExpr(rhs, n_binders);\n                    this.emitTupleAssign(tl, output, rhs.range(), n_binders, starred_unpack);\n                } else if (args.length === 5) {\n                    const [tl, rhs_output, rhs_loc, n_binders, starred_unpack] = args;\n                    const outputs = rhs_output.asTuple(rhs_loc, this.method, starred_unpack ? null : n_binders);\n                    if (outputs.length < n_binders) {\n                        throw new python.Error('Not enough values to unpack.');\n                    }\n                    if (outputs.length > n_binders && !starred_unpack) {\n                        throw new python.Error('Too many values to unpack.');\n                    }\n                    this.emitExprsAssign(tl.elts, outputs, rhs_loc, n_binders);\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n            emitExprsAssign(lhs_exprs, outputs /*, rhs_loc, n_binders */) {\n                let i = 0;\n                for (const assignee of lhs_exprs) {\n                    if (assignee instanceof ast.Subscript) {\n                        throw new python.Error('Not implemented.');\n                        /*\n                        this.emitSubscriptAssign(\n                            rhs_loc,\n                            Subscript(assignee),\n                            NamedValue(rhs_loc, outputs.at(i).asValue(rhs_loc, method)));\n                        i++;\n                        */\n                    } else if (assignee instanceof ast.Name) {\n                        this.environment_stack.setSugaredVar(assignee.range(), assignee.id, outputs[i], /*annotated_type=*/null);\n                        i++;\n                    } else if (assignee instanceof ast.Starred) {\n                        throw new python.Error('Not implemented.');\n                        /*\n                        const var = Starred(assignee).expr();\n                        if (var.kind() != TK_VAR) {\n                        throw(\n                            ErrorReport(var) << 'Cannot pack a tuple into a non-variable');\n                        }\n                        size_t n_matched = outputs.size() - n_binders;\n                        ArrayRef<std::shared_ptr<SugaredValue>> outputs_ref = outputs;\n                        const values = fmap(\n                            outputs_ref.slice(i, n_matched),\n                            [&](const std::shared_ptr<SugaredValue>& v) {\n                            return v.asValue(assignee.range(), method);\n                            });\n                        const tup = graph.insertNode(graph.createTuple(values)).output();\n                        environment_stack.setVar(var.range(), Var(var).name().name(), tup);\n                        i += n_matched;\n                        */\n                    } else if (assignee instanceof ast.Tuple) {\n                        throw new python.Error('Not implemented.');\n                        /*\n                        // recursively emit tuple assignments on tuple literal input\n                        TupleLiteral sub_tl = TupleLiteral(assignee);\n                        size_t sub_n_binders = sub_tl.inputs().length;\n                        bool sub_starred_unpack =\n                            validateAssignLhsExpr(sub_tl.inputs(), sub_tl.range());\n                        if (sub_starred_unpack)\n                        sub_n_binders--;\n                        emitTupleAssign(\n                            sub_tl,\n                            outputs.at(i),\n                            rhs_loc,\n                            sub_n_binders,\n                            sub_starred_unpack);\n                        i++;\n                        */\n                    } else if (assignee instanceof ast.Attribute) {\n                        throw new python.Error('Not implemented.');\n                        /*\n                        emitSelectAssign(assignee, outputs.at(i), rhs_loc);\n                        i++;\n                        */\n                    } else {\n                        throw new python.Error('Unexpected expression on left-hand side of assignment.');\n                    }\n                }\n            }\n            emitReturn(stmt) {\n                let declared_return_type = this._def_stack[this._def_stack.length - 1]._declared_return_type;\n                let actual_return = this.emitExpr(stmt.value, declared_return_type);\n                if (declared_return_type) {\n                    if (!(actual_return.type().isSubtypeOf(torch.TensorType.get()) && actual_return.type().isSubtypeOf(torch.NoneType.get()))) {\n                        actual_return = torch._C.tryConvertToType(stmt, this.graph, declared_return_type, actual_return, /*allow_conversions=*/true);\n                    }\n                    if (!actual_return.type().isSubtypeOf(declared_return_type)) {\n                        throw new python.Error(`Invalid return type.`);\n                    }\n                } else {\n                    declared_return_type = this._def_stack[this._def_stack.length - 1]._merged_return_type;\n                    if (!declared_return_type) {\n                        declared_return_type = actual_return.type();\n                    }\n                    const merged_return_type = torch._C.unifyTypes(declared_return_type, actual_return.type());\n                    if (!merged_return_type) {\n                        throw new python.Error(`Invalid return type.`);\n                    }\n                    declared_return_type = merged_return_type;\n                }\n                this._def_stack[this._def_stack.length - 1]._merged_return_type = declared_return_type;\n                if (declared_return_type === torch.AnyType.get() && actual_return.type() !== torch.AnyType.get()) {\n                    actual_return = this.graph.insertUncheckedCast(actual_return, declared_return_type);\n                }\n                this.graph.insertNode(this.graph.create('prim::ReturnStmt', [actual_return], 0));\n                this.exit_blocks.add(this.environment_stack.block());\n            }\n            getNamedValues(trees, maybe_unpack) {\n                const values = [];\n                for (const tree of trees) {\n                    if (maybe_unpack && tree instanceof ast.Starred) {\n                        throw new python.Error('Starred argument not supported.');\n                    } else {\n                        values.push(new torch._C.NamedValue(this.emitExpr(tree)));\n                    }\n                }\n                return values;\n            }\n            getValues(trees, maybe_unpack) {\n                return this.getNamedValues(trees, maybe_unpack).map((value) => value.value(this.graph));\n            }\n            emitExpr(tree, type_hint) {\n                type_hint = type_hint || null;\n                let out_val = this.emitSugaredExpr(tree, 1, type_hint).asValue(tree, this.method);\n                if (type_hint === torch.AnyType.get() && out_val.type() !== torch.AnyType.get()) {\n                    out_val = this.graph.insertUncheckedCast(out_val, type_hint);\n                }\n                return out_val;\n            }\n            emitSugaredExpr(tree, n_binders, type_hint) {\n                if (tree instanceof ast.Name) { // TK_VAR\n                    return this.environment_stack.getSugaredVar(tree.id);\n                } else if (tree instanceof ast.Attribute) {\n                    const sv = this.emitSugaredExpr(tree.value, 1);\n                    return sv.attr(tree.range(), this.method, tree.attr);\n                } else if (tree instanceof ast.Call) { // TK_APPLY\n                    return this.emitApplyExpr(tree, n_binders, type_hint);\n                } if (tree instanceof ast.Subscript) {\n                    return this.emitSubscript(tree, type_hint);\n                }\n                return new torch._C.SimpleValue(this.emitSimpleExpr(tree, type_hint));\n            }\n            emitApplyExpr(apply, n_binders, type_hint) {\n                type_hint = type_hint || null;\n                const sv = this.emitSugaredExpr(apply.func, 1);\n                const loc = apply.func.range();\n                if (sv instanceof torch._C.SpecialFormValue) {\n                    return this.emitApplySpecialForm(sv.form(), apply, sv, type_hint);\n                }\n                const args = this.getNamedValues(apply.args, true);\n                const kwargs = this.emitAttributes(apply.keywords);\n                return sv.call(loc, this.method, args, kwargs, n_binders);\n            }\n            emitAttributes(attributes) {\n                return attributes.map((attr) => new torch._C.NamedValue(attr.range(), attr.arg, this.emitExpr(attr.value)));\n            }\n            emitApplySpecialForm(form, apply, sv, type_hint) {\n                switch (form) {\n                    case 'prim::fork': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::awaitable': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::annotate': {\n                        this.checkApplyNumInputs(apply, 2);\n                        const type = this._typeParser.parseTypeFromExpr(apply.args[0]);\n                        let expr = torch._C.tryConvertToType(apply.range(), this.graph, type, this.emitExpr(apply.args[1], type), /*allow_conversions=*/true);\n                        if (!expr.type().isSubtypeOf(type)) {\n                            throw new python.Error('Invalid expression type.');\n                        }\n                        if ((type instanceof torch.OptionalType || (type instanceof torch.UnionType && type.expect(torch.UnionType).canHoldType(torch.NoneType.get()))) && expr.type().isSubtypeOf(torch.NoneType.get())) {\n                            const none = this.graph.createNone();\n                            none.output().setType(type);\n                            this.graph.insertNode(none);\n                            expr = none.output();\n                        }\n                        return new torch._C.SimpleValue(expr);\n                    }\n                    case 'prim::unchecked_cast': {\n                        this.checkApplyNumInputs(apply, 2);\n                        const type = this._typeParser.parseTypeFromExpr(apply.args[0]);\n                        let v = this.emitExpr(apply.args[1]);\n                        if (v.node().kind() !== 'prim::unchecked_cast' || v.type() !== type) {\n                            v = this.graph.insertUncheckedCast(v, type);\n                        }\n                        return new torch._C.SimpleValue(v);\n                    }\n                    case 'prim::GetAttr': {\n                        this.checkApplyNumInputsRange(apply, 2, 3);\n                        const obj = this.emitSugaredExpr(apply.args[0], 1);\n                        if (apply.args[1] instanceof ast.Constant === false || typeof apply.args[1].value !== 'string') {\n                            throw new python.Error('Invalid argument.');\n                        }\n                        const name = apply.args[1].value;\n                        if (apply.args.length === 2) {\n                            return obj.attr(apply, this.method, name);\n                        } else if (obj.hasAttr(apply, this.method, name)) {\n                            return obj.attr(apply, this.method, name);\n                        }\n                        return this.emitSugaredExpr(apply.inputs()[2], 1);\n                    }\n                    case 'prim::Uninitialized': {\n                        this.checkApplyNumInputs(apply, 1);\n                        const type = this._typeParser.parseTypeFromExpr(apply.args[0]);\n                        const out = this.graph.insertNode(this.graph.createUninitialized(type)).setSourceRange(apply.range());\n                        return new torch._C.SimpleValue(out.output());\n                    }\n                    case 'prim::TupleConstruct': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::isinstance': {\n                        this.checkApplyNumInputs(apply, 2);\n                        const result = this.emitIsInstance(apply.args[0], apply.args[1]);\n                        return new torch._C.SimpleValue(result.value());\n                    }\n                    case 'prim::tolist': {\n                        const value = apply.func.value;\n                        const operand = this.emitSugaredExpr(value, 1);\n                        if (!type_hint) {\n                            throw new python.Error('Expected type hint for result of tolist().');\n                        }\n                        return new torch._C.SimpleValue(this.graph.insertToList(operand.asValue(value.range(), this.method), type_hint));\n                    }\n                    case 'prim::HasAttr': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::CreateObject': {\n                        if (apply.args.length !== 1) {\n                            throw python.Error('Only one argument to __new__ allowed.');\n                        }\n                        const arg = this.emitSugaredExpr(apply.args[0], 1);\n                        if (arg instanceof torch._C.ClassValue === false) {\n                            throw python.Error('Expected class value as argument to __new__.');\n                        }\n                        const class_arg = arg;\n                        const createNode = this.graph.insertNode(this.graph.createObject(class_arg._type));\n                        createNode.setSourceRange(apply.range());\n                        return new torch._C.SimpleValue(createNode.output());\n                    }\n                    case 'prim::range': {\n                        const input_vals = this.getValues(apply.args, true);\n                        return new torch._C.RangeValue(apply.range(), this.method, input_vals);\n                    }\n                    case 'prim::enumerate': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::zip': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::list': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'prim::dict': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    case 'aten::index': {\n                        throw new python.Error('Not implemented.');\n                    }\n                    default: {\n                        throw new python.Error(`Unsupported special form '${sv.from()}'.`);\n                    }\n                }\n            }\n            emitSimpleExpr(tree, type_hint) {\n                if (tree instanceof ast.Constant) {\n                    if (tree.value === true) {\n                        return this.graph.insertConstant(new torch._C.IValue(true, 'Bool'), tree.range());\n                    } else if (tree.value === false) {\n                        return this.graph.insertConstant(new torch._C.IValue(false, 'Bool'), tree.range());\n                    } else if (tree.value === null) {\n                        return this.graph.insertConstant(new torch._C.IValue(), tree.range());\n                    } else if (typeof tree.value === 'string') {\n                        return this.emitStringLiteral(tree);\n                    }\n                    return this.emitConst(tree);\n                } else if (tree instanceof ast.List) {\n                    return this.emitListLiteral(tree, type_hint);\n                } else if (tree instanceof ast.UnaryOp && tree.op instanceof ast.USub && tree.operand instanceof ast.Name && tree.operand.id === 'inf') {\n                    return this.emitConst(new ast.Constant(-Infinity, 'float'));\n                } else if (tree instanceof ast.UnaryOp && tree.op instanceof ast.USub && tree.operand instanceof ast.Constant) {\n                    const c = tree.operand;\n                    if (c.type === 'complex') {\n                        return this.emitConst(new ast.Constant(new builtins.complex(-c.value.real, -c.value.imag), 'complex'));\n                    }\n                    return this.emitConst(new ast.Constant(-c.value, c.type));\n                } else if (tree instanceof ast.UnaryOp && tree.op instanceof ast.USub) {\n                    return this.emitUnaryOp(tree, '__neg__', 'aten::neg');\n                } else if (tree instanceof ast.BinOp) {\n                    return this.emitBinaryOp(tree);\n                } else if (tree instanceof ast.Dict) {\n                    return this.emitDictLiteral(tree, type_hint);\n                } else if (tree instanceof ast.Tuple) {\n                    const values = this.getValues(tree.elts, /*maybe_unpack=*/true);\n                    return this.graph.insertNode(this.graph.createTuple(values)).output();\n                }\n                throw new python.Error(`Simple expression '${tree.__class__.__name__}' not implemented.`);\n            }\n            getNodeKind(kind /*, ninputs */) {\n                if (kind instanceof ast.Add) {\n                    return 'aten::add';\n                } else if (kind instanceof ast.Sub) {\n                    return 'aten::sub';\n                } else if (kind instanceof ast.Mult) {\n                    return 'aten::mul';\n                }\n                /*\n                case TK_UNARY_MINUS: return 'aten::neg';\n                case TK_POW: return 'aten::pow';\n                case '@': return 'aten::matmul';\n                case TK_STARRED: return 'prim::Starred';\n                case '/': return 'aten::div';\n                case '%': return 'aten::remainder';\n                case TK_NE: return 'aten::ne';\n                case TK_EQ: return 'aten::eq';\n                case '<': return 'aten::lt';\n                case '>': return 'aten::gt';\n                case TK_LE: return 'aten::le';\n                case TK_GE: return 'aten::ge';\n                case TK_AND: return 'aten::__and__';\n                case TK_OR: return 'aten::__or__';\n                case TK_IS: return 'aten::__is__';\n                case TK_ISNOT: return 'aten::__isnot__';\n                case TK_NOT: return 'aten::__not__';\n                case TK_FLOOR_DIV: return 'aten::floordiv';\n                case TK_LSHIFT: return 'aten::__lshift__';\n                case TK_RSHIFT: return 'aten::__rshift__';\n                case '&': return 'aten::__and__';\n                case '|': return 'aten::__or__';\n                case '^': return 'aten::__xor__';\n                case TK_IN: return 'aten::__contains__';\n                */\n                throw new python.Error(`Unknown kind '${kind.__class__.__name__}'.`);\n            }\n            getOperatorOverload(kind /*, ninputs */) {\n                if (kind instanceof ast.Add) {\n                    return '__add__';\n                } else if (kind instanceof ast.Sub) {\n                    return '__sub__';\n                } else if (kind instanceof ast.Mult) {\n                    return '__mul__';\n                }\n                /*\n                case TK_UNARY_MINUS: return \"__neg__\";\n                case '~': return \"__invert__\";\n                case TK_POW: return \"__pow__\";\n                case '/': return \"__truediv__\";\n                case '%': return \"__mod__\";\n                case TK_NE: return \"__ne__\";\n                case TK_EQ: return \"__eq__\";\n                case '<': return \"__lt__\";\n                case '>': return \"__gt__\";\n                case TK_LE: return \"__le__\";\n                case TK_GE: return \"__ge__\";\n                case '&': return \"__and__\";\n                case '|': return \"__or__\";\n                case '^': return \"__xor__\";\n                case TK_IN: return \"__contains__\";\n                case TK_LSHIFT: return \"__lshift__\";\n                case TK_RSHIFT: return \"__rshift__\";\n                */\n                throw new python.Error(`Unknown kind '${kind.__class__.__name__}'.`);\n            }\n            emitBinaryOp(tree) {\n                const inputs = [tree.left, tree.right];\n                const kind = this.getNodeKind(tree.op, inputs.length);\n                const overload = this.getOperatorOverload(tree.op, inputs.length);\n                const named_values = this.getNamedValues(inputs, /*maybe_unpack=*/false);\n                if (tree.op instanceof ast.In) {\n                    // std::iter_swap(named_values.begin() + 0, named_values.begin() + 1);\n                    throw new python.Error('Not implemented.');\n                }\n                if (named_values[0].type() instanceof torch.TupleType &&\n                    named_values[1].type() instanceof torch.TupleType &&\n                    kind === 'aten::add') {\n                    const first_tuple = torch._C.createTupleUnpack(named_values[0].value(this.graph)).vec();\n                    const second_tuple = torch._C.createTupleUnpack(named_values[1].value(this.graph)).vec();\n                    first_tuple.insert(first_tuple.end(), second_tuple.begin(), second_tuple.end());\n                    return this.graph.insertNode(this.graph.createTuple(first_tuple)).output();\n                }\n                return torch._C.asSimple(torch._C.makeMagic(overload, new torch._C.BuiltinFunction(kind, null)).call(tree.range(), this.method, named_values, [], 0));\n            }\n            emitDictLiteral(dl, type_hint) {\n                const key_trees = dl.keys;\n                const value_trees = dl.values;\n                torch._C.AT_ASSERT(key_trees.length === value_trees.length);\n                const keys = [];\n                const values = [];\n                let rhs_value_type = null;\n                for (let i = 0; i < key_trees.length; i++) {\n                    keys.push(this.emitExpr(key_trees[i]));\n                    values.push(this.emitExpr(value_trees[i]));\n                    if (i === 0) {\n                        rhs_value_type = values[i].type();\n                    } else {\n                        if (keys[i - 1].type().kind() !== keys[i].type().kind()) {\n                            throw new python.Error('Dict keys must contain only a single type.');\n                        }\n                        rhs_value_type = torch._C.unifyTypes(rhs_value_type, values[i].type(), /*default_to_union=*/true);\n                    }\n                }\n                const refined_type_hint = { _: type_hint };\n                const annotated_union_type = type_hint && type_hint.isUnionType() ? type_hint : null;\n                const all_candidates = { _: [] };\n                const default_refined_type_hint_setter = () => {\n                    if (keys.length === 0) {\n                        refined_type_hint._ = torch.DictType.create(torch.StringType.get(), torch.TensorType.get());\n                    } else {\n                        refined_type_hint._ = torch.DictType.create(keys[0].type(), rhs_value_type);\n                        if (rhs_value_type instanceof torch.UnionType) {\n                            throw new python.Error('Dict values consist of heterogeneous types.');\n                        }\n                    }\n                };\n                if (type_hint) {\n                    const type_match = (t) => t instanceof torch.DictType;\n                    this.refineAndSetUnionTypeHintOrPopulateCandidatesVector(type_hint, refined_type_hint, all_candidates, 'Dict', dl, type_match, () => [], default_refined_type_hint_setter);\n                    if (all_candidates._.length > 0 && values.length === 0) {\n                        throw new python.Error('Cannot assign an empty dict.');\n                    }\n                } else {\n                    default_refined_type_hint_setter();\n                }\n                torch._C.TORCH_INTERNAL_ASSERT(all_candidates._.length > 0 || refined_type_hint._);\n                if (values.length > 0) {\n                    if (all_candidates._.length > 0) {\n                        this.refineAndSetDictTypeHintFromCandidatesVector(all_candidates, type_hint, refined_type_hint, keys[0].type(), rhs_value_type, dl);\n                    }\n                    if (refined_type_hint._.getKeyType() !== keys[0].type()) {\n                        throw new python.Error('Type annotation does not match key type.');\n                    }\n                    if (!rhs_value_type.isSubtypeOf(refined_type_hint._.getValueType())) {\n                        throw new python.Error('Type annotation does not match value type.');\n                    }\n                }\n                let result = this.graph.insertNode(this.graph.createDict(refined_type_hint._.getKeyType(), refined_type_hint._.getValueType(), keys, values));\n                if (annotated_union_type) {\n                    const n = this.graph.insertNode(this.graph.create('prim::unchecked_cast', [result.output()]));\n                    n.output().setType(annotated_union_type);\n                    result = n;\n                }\n                return result.output();\n            }\n            emitStringLiteral(c) {\n                return torch._C.insertConstant(this.graph, c.value, c.range());\n            }\n            emitConst(c) {\n                if (c.type === 'int') {\n                    return torch._C.materializeConstant(new torch._C.IValue(c.value, 'Int'), this.graph, c.range(), this.integral_constants);\n                } else if (c.type === 'complex') {\n                    return torch._C.materializeConstant(new torch._C.IValue(c.value, 'Complex'), this.graph, c.range(), this.complex_constants);\n                } else if (c.type === 'float') {\n                    return torch._C.materializeConstant(new torch._C.IValue(c.value, 'Double'), this.graph, c.range(), this.fp_constants);\n                }\n                throw new python.Error(`Unsupported constant type.`);\n            }\n            emitListLiteral(ll, type_hint) {\n                type_hint = type_hint || null;\n                const values = this.getValues(ll.elts, true);\n                if (values.length === 0 && type_hint === null) {\n                    throw new python.Error('Not implemented.');\n                }\n                let inferred_elem_type = torch.TensorType.get();\n                const refined_type_hint = { _: type_hint };\n                const annotated_union_type = refined_type_hint._ && refined_type_hint._.isUnionType() ? refined_type_hint._ : null;\n                const all_candidates = { _: [] };\n                if (refined_type_hint._) {\n                    const do_if_type_match = () => {\n                        inferred_elem_type = refined_type_hint._.expect(torch.ListType).getElementType();\n                    };\n                    const type_match = (t) => t.isSubtypeOf(torch.Type.get('AnyListType'));\n                    this.refineAndSetUnionTypeHintOrPopulateCandidatesVector(type_hint, refined_type_hint, all_candidates, 'List', ll, type_match, do_if_type_match, do_if_type_match);\n                    if (all_candidates._.length > 0 && values.len === 0) {\n                        throw new python.Error('Cannot assign an empty list.');\n                    }\n                }\n                if (values.length !== 0) {\n                    const types = values.map((v) => v.type());\n                    const elem_type_hint = refined_type_hint._ && refined_type_hint._.kind() === 'ListType' ? refined_type_hint._.getElementType() : null;\n                    const unified_elem_type = torch._C.unifyTypeList(types, null /*nowhere*/, /*default_to_union=*/true, elem_type_hint);\n                    if (!refined_type_hint._ && unified_elem_type.kind() === 'UnionType') {\n                        throw new python.Error('Not implemented.');\n                    }\n                    if (all_candidates._.length === 0 && refined_type_hint._ && !unified_elem_type.isSubtypeOf(inferred_elem_type)) {\n                        throw new python.Error('Not implemented.');\n                    }\n                    if (all_candidates._.length !== 0) {\n                        this.refineAndSetListTypeHintFromCandidatesVector(all_candidates, type_hint, refined_type_hint._, unified_elem_type, ll);\n                        inferred_elem_type = refined_type_hint._.expect(torch.ListType).getElementType();\n                    }\n                    if (!refined_type_hint._) {\n                        inferred_elem_type = unified_elem_type;\n                    }\n                }\n                let result = this.graph.insertNode(this.graph.createList(inferred_elem_type, values));\n                if (annotated_union_type) {\n                    const n = this.graph.insertNode(this.graph.create('prim::unchecked_cast', [result.output()]));\n                    n.output().setType(annotated_union_type);\n                    result = n;\n                }\n                return result.output();\n            }\n            insertRefinements(loc, ref) {\n                for (const r of ref.activeRefinements()) {\n                    const v = this.environment_stack.getVar(r.identifier(), loc);\n                    const new_v = this.graph.insertUncheckedCast(v, r.type());\n                    this.environment_stack.setVar(loc, r.identifier(), new_v);\n                }\n            }\n            shouldDeriveSetStateType(def, schema) {\n                const noTypeAnnotations = schema.arguments.every((arg) => arg.is_inferred_type());\n                const shouldInfer = def.name === '__setstate__' && noTypeAnnotations;\n                if (!shouldInfer) {\n                    return false;\n                }\n                if (def.name !== '__setstate__' && def.args.args.length !== 2) {\n                    throw new python.Error(`Invalid '__setstate' method.`);\n                }\n                return true;\n            }\n            checkApplyNumInputs(apply, expected_inputs) {\n                if (apply.args.length !== expected_inputs) {\n                    throw new python.Error('Invalid number of arguments.');\n                }\n                if (apply.keywords.length > 0) {\n                    throw new python.Error('Invalid number of keyword arguments.');\n                }\n            }\n            checkApplyNumInputsRange(apply, min_expected_inputs, max_expected_inputs) {\n                const position_arg_size = apply.args.length;\n                if (position_arg_size < min_expected_inputs || position_arg_size > max_expected_inputs) {\n                    throw new python.Error('Invalid number of arguments.');\n                }\n                if (apply.keywords.length > 0) {\n                    throw new python.Error('Invalid number of keyword arguments.');\n                }\n            }\n            validateAssignLhsExpr(lhs /*, r */) {\n                let num_normal_assign = 0;\n                let num_starred = 0;\n                for (const assignee of lhs) {\n                    if (assignee instanceof ast.Name || assignee instanceof ast.Subscript || assignee instanceof ast.Tuple || assignee instanceof ast.Attribute) {\n                        num_normal_assign++;\n                    } else if (assignee instanceof ast.Starred) {\n                        num_starred++;\n                    } else {\n                        throw new python.Error('Assignment must be a variable, subscript, or starred expression.');\n                    }\n                }\n                if (num_starred > 1) {\n                    throw new python.Error('Only one starred expression is allowed.');\n                }\n                if (num_starred > 0 && num_normal_assign === 0) {\n                    throw new python.Error('Invalid starred expression.');\n                }\n                return num_starred;\n            }\n            createTempName(prefix) {\n                return `${prefix}${this._temp_name_count++}`;\n            }\n            handleMaybeNoReturn(def, block) {\n                const decl_ret = this._def_stack[this._def_stack.length - 1]._declared_return_type;\n                if (this.exit_blocks.size === 0) {\n                    if (decl_ret && decl_ret !== torch.NoneType.get()) {\n                        throw new python.Error('Function was not annotated as having type None, but does not return along all paths.');\n                    }\n                    const b = new torch._C.WithInsertPoint(block.nodes().end());\n                    // this.emitReturn(Return::create(def.range(), Expr(Compound::create(TK_NONE, def.range(), {}))));\n                    b.dispose();\n                    throw new python.Error(\"'torch._C.to_ir.handleMaybeNoReturn' not implemented.\");\n                } else if (this._def_stack[this._def_stack.length - 1]._merged_return_type === null) {\n                    this._def_stack[this._def_stack.length - 1]._merged_return_type = decl_ret === null ? torch.NoneType.get() : decl_ret;\n                }\n            }\n            getAdjTupleIndex(loc, tuple_type, input_index, allow_out_of_bounds) {\n                let adj_index = input_index;\n                const tuple_len = tuple_type.elements().length;\n                if (input_index < 0) {\n                    adj_index = tuple_len + input_index;\n                }\n                if (!allow_out_of_bounds && (adj_index >= tuple_len || adj_index < 0)) {\n                    throw new python.Error(`Tuple index out of range at ${loc}.`);\n                }\n                return adj_index;\n            }\n            emitTupleIndex(loc, tuple_val, idx_val) {\n                const tuple_typ = tuple_val.type();\n                const elems = tuple_typ.elements();\n                let output_type = null;\n                if (idx_val.type() !== torch.IntType.get()) {\n                    throw new python.Error('Tuple index must be an integer.');\n                }\n                const idx = torch._C.toIValue(idx_val);\n                if (idx) {\n                    const adj_index = this.getAdjTupleIndex(loc, tuple_typ, idx.toInt(), /*allow_out_of_bounds*/ false);\n                    output_type = elems[adj_index];\n                } else {\n                    if (elems.length === 0 || !torch._C.convertibleToList(tuple_typ, torch.ListType.create(elems[0]))) {\n                        throw new python.Error('Cannot index into a tuple with a non-integer literal.');\n                    }\n                    [output_type] = elems;\n                }\n                return this.graph.insertNode(this.graph.createTupleIndex(tuple_val, idx_val, output_type)).output();\n            }\n            getSliceInd(idx_val, loc) {\n                const ivalue = torch._C.toIValue(idx_val);\n                if (ivalue && ivalue.isInt()) {\n                    return ivalue.toInt();\n                }\n                throw new python.Error(`Tuple slice indices must be integer constants at '${loc}'.`);\n            }\n            emitTupleSlice(loc, tuple_val, tuple_args) {\n                const tuple_type = tuple_val.value(this.graph).type().expect(torch.TupleType);\n                const tuple_len = tuple_type.elements().length;\n                const [beg_val, end_val, step] = tuple_args;\n                let step_size = 1;\n                if (step) {\n                    const val = torch._C.toIValue(step.value(this.graph));\n                    torch._C.TORCH_CHECK(val.isInt());\n                    step_size = val.toInt();\n                }\n                let beg = { _: Number.MAX_SAFE_INTEGER }; // std::numeric_limits<int64_t>::max();\n                if (beg_val) {\n                    beg = { _: this.getAdjTupleIndex(loc, tuple_type, this.getSliceInd(beg_val.value(this.graph), loc), true) };\n                }\n                let end = { _: Number.MAX_SAFE_INTEGER }; // std::numeric_limits<int64_t>::max();\n                if (end_val) {\n                    end = { _: this.getAdjTupleIndex(loc, tuple_type, this.getSliceInd(end_val.value(this.graph), loc), true) };\n                }\n                const num_values = torch._C.slice_indices_adjust(tuple_len, beg, end, step_size);\n                return this.graph.insertNode(this.graph.createTupleSlice(tuple_val.value(this.graph), beg._, step_size, num_values)).output();\n            }\n            emitSliceOp(loc, sliceable, dim, start, end, step) {\n                const args = [];\n                args.push(new torch._C.NamedValue(loc, 'self', sliceable));\n                if (dim) {\n                    torch._C.AT_ASSERT(sliceable.type().isSubtypeOf(torch.TensorType.get()));\n                    args.emplace_back(new torch._C.NamedValue(dim));\n                } else {\n                    torch._C.AT_ASSERT(!sliceable.type().isSubtypeOf(torch.TensorType.get()));\n                }\n                if (sliceable.type() instanceof torch.TupleType) {\n                    const tuple_args = [];\n                    tuple_args.push(start ? new torch._C.NamedValue(start) : null);\n                    tuple_args.push(end ? new torch._C.NamedValue(end) : null);\n                    tuple_args.push(step ? new torch._C.NamedValue(step) : null);\n                    return this.emitTupleSlice(loc, args[0], tuple_args);\n                }\n                if (!step) {\n                    step = this.graph.insertConstant(1, loc);\n                }\n                args.push(new torch._C.NamedValue(loc, 'start', start));\n                args.push(new torch._C.NamedValue(loc, 'end', end));\n                args.push(new torch._C.NamedValue(loc, 'step', step));\n                return this.emitBuiltinCall(loc, this.graph, 'aten::slice', args, []);\n            }\n            emitSlice(loc, input, dim, slice) {\n                let start = null;\n                let end = null;\n                let step = null;\n                if (slice.lower) {\n                    start = this.emitExpr(slice.lower);\n                }\n                if (slice.upper) {\n                    end = this.emitExpr(slice.upper);\n                }\n                if (slice.step) {\n                    step = this.emitExpr(slice.step);\n                }\n                return this.emitSliceOp(loc, input, dim, start, end, step);\n            }\n            emitBasicSlice(loc, sliceable, subscript_exprs) {\n                torch._C.AT_ASSERT(subscript_exprs instanceof ast.Slice);\n                const slice_exp = subscript_exprs;\n                let maybe_dim = null;\n                if (sliceable.type().isSubtypeOf(torch.TensorType.get())) {\n                    maybe_dim = this.graph.insertConstant(0, loc);\n                }\n                return this.emitSlice(loc, sliceable, maybe_dim, slice_exp);\n            }\n            emitSubscript(subscript, type_hint) {\n                type_hint = type_hint === undefined ? null : type_hint;\n                const sv = this.emitSugaredExpr(subscript.value, 1);\n                const subscript_exprs = subscript.slice;\n                const range = subscript.range();\n                const val_range = subscript.value;\n                if (subscript_exprs instanceof ast.Tuple) {\n                    return new torch._C.SimpleValue(this.emitMultidimSlicing(range, sv.asValue(val_range, this.method), subscript_exprs));\n                }\n                if (subscript_exprs instanceof ast.Slice) {\n                    if (sv.kind() === 'module') {\n                        const s_tuple_val = sv.asTupleValue(val_range, this.method).asValue(val_range, this.method);\n                        const [slice] = subscript_exprs;\n                        const tuple_args = [];\n                        if (slice.start().present()) {\n                            const begin = new torch._C.NamedValue(val_range, 'begin', this.emitExpr(slice.start().get()));\n                            tuple_args.push(begin);\n                        } else {\n                            tuple_args.push(null);\n                        }\n                        if (slice.end().present()) {\n                            const end = new torch._C.NamedValue(val_range, 'end', this.emitExpr(slice.end().get()));\n                            tuple_args.push(end);\n                        } else {\n                            tuple_args.push(null);\n                        }\n                        if (slice.step().present()) {\n                            const step = new torch._C.NamedValue(val_range, 'step', this.emitExpr(slice.step().get()));\n                            tuple_args.push(step);\n                        } else {\n                            tuple_args.push(null);\n                        }\n                        const tupleSliceValue = this.emitTupleSlice(val_range, s_tuple_val, tuple_args);\n                        return new torch._C.SimpleValue(tupleSliceValue);\n                    }\n                    return new torch._C.SimpleValue(this.emitBasicSlice(range, sv.asValue(val_range, this.method), subscript_exprs));\n                }\n                const sliceable = sv.asValue(val_range, this.method);\n                const subscript_sv = this.emitSugaredExpr(subscript_exprs, 1);\n                if (subscript_sv instanceof torch._C.SliceValue) {\n                    const slice_value = subscript_sv;\n                    let dim = null;\n                    if (sliceable.type().isSubtypeOf(torch.TensorType.get())) {\n                        dim = this.method.graph().insertConstant(0, val_range);\n                    }\n                    const sliced = this.emitSliceOp(val_range, sliceable, dim, slice_value.start(), slice_value.stop(), slice_value.step());\n                    return new torch._C.SimpleValue(sliced);\n                }\n                const idx = subscript_sv.asValue(val_range, this.method);\n                if (sliceable.type() instanceof torch.TupleType) {\n                    return new torch._C.SimpleValue(this.emitTupleIndex(range, sv.asValue(val_range, this.method), idx));\n                } else if (sliceable.type().isSubtypeOf(torch.TensorType.get())) {\n                    return new torch._C.SimpleValue(this.emitMultidimSlicing(range, sliceable, subscript_exprs));\n                }\n                return sv.getitem(range, this.method, idx, type_hint);\n            }\n        });\n        this.registerType('torch.jit.CompilationUnit', class {\n            constructor() {\n                this._functions = new Map();\n                this._classes = new Map();\n            }\n            register_type(namedType) {\n                this._classes.set(namedType.annotation_str, namedType);\n            }\n            register_function(fn) {\n                const name = fn.qualname().qualifiedName();\n                torch._C.TORCH_CHECK(!this._functions.has(name));\n                this._functions.set(name, fn);\n                return fn;\n            }\n            define(...args) {\n                if (Array.isArray(args[1])) {\n                    const [prefix, properties, propResolvers, definitions, defResolvers, self, shouldMangle, operator_set_version] = args;\n                    torch._C.TORCH_INTERNAL_ASSERT(definitions.length === defResolvers.length);\n                    torch._C.TORCH_INTERNAL_ASSERT(properties.length === propResolvers.length);\n                    const functions = [];\n                    const function_table = new Map();\n                    const record_function = (fn) => {\n                        function_table.set(fn.name(), fn);\n                        functions.push(fn);\n                        this.register_function(fn);\n                    };\n                    for (let i = 0; i < properties.length; i++) {\n                        const property_fns = this.define_property(prefix, properties[i], propResolvers[i], self, function_table, shouldMangle);\n                        const getter_fn = property_fns.getGetter();\n                        const setter_fn = property_fns.getSetter();\n                        record_function(getter_fn);\n                        if (setter_fn) {\n                            record_function(setter_fn);\n                        }\n                    }\n                    for (let i = 0; i < definitions.length; i++) {\n                        const fn = this.define(prefix, definitions[i], defResolvers[i], self, function_table, shouldMangle, 'Method', operator_set_version);\n                        record_function(fn);\n                    }\n                    for (const [name, fn] of function_table) {\n                        if (name === '__init__') {\n                            fn.ensure_defined();\n                        }\n                    }\n                    for (const fn of functions) {\n                        fn.ensure_defined();\n                    }\n                    return functions;\n                } else if (args[1] instanceof ast.FunctionDef) {\n                    const [prefix, def, resolver, self, function_table, shouldMangle, type, operator_set_version] = args;\n                    const _resolver = self ? resolver : new torch._C.FunctionResolver(resolver, function_table);\n                    const creator = (method) => {\n                        return new torch._C.to_ir(def, _resolver, self, method);\n                    };\n                    let name = prefix ? new torch._C.QualifiedName(prefix, def.name) : new torch._C.QualifiedName(def.name);\n                    if (shouldMangle && this.find_function(name)) {\n                        name = this.mangle(name);\n                    }\n                    const graph = new torch.Graph();\n                    graph.set_op_version(operator_set_version);\n                    const fn = new torch._C.GraphFunction(name, graph, creator);\n                    fn.__ast__ = def; // remove\n                    if (self) {\n                        if (type === 'hook') {\n                            self.getClassType().addForwardHook(fn);\n                        } else if (type === 'prehook') {\n                            self.getClassType().addPreHook(fn);\n                        } else {\n                            self.getClassType().addMethod(fn);\n                        }\n                    }\n                    return fn;\n                }\n                throw new python.Error('Invalid arguments.');\n            }\n            get_type(name) {\n                return this._classes.get(name.qualifiedName());\n            }\n            get_class(name) {\n                return this.get_type(name);\n            }\n            find_function(name) {\n                const key = name.qualifiedName();\n                return this._functions.get(key);\n            }\n        });\n        this.registerFunction('torch._C.ConvertToSSA', (graph) => {\n            const ctrl = new torch._C.ControlFlowLoadStores();\n            ctrl.run(graph);\n            const exit_vars = new torch._C.LoopContinuations();\n            exit_vars.run(graph);\n            torch._C.InlineLoopCondition(graph);\n            const erase_loads_stores = new torch._C.EraseLoadStores();\n            erase_loads_stores.run(graph);\n            torch._C.TransformExits(graph);\n        });\n        this.registerFunction('torch._C.canonicalizeModifiedLoop', (/* n */) => {\n            /*\n            LoopView loop(n);\n            if (loop.loopType() != LoopView::ModifiedLoop) {\n              return;\n            }\n            const g = n.owningGraph();\n            WithInsertPoint node_insert(n);\n            const zero = g.insertConstant(0);\n            const one = g.insertConstant(1);\n            const max_trip_count = loop.maxTripCount();\n            const condition = g.insert(aten::gt, {max_trip_count, zero});\n            loop.replaceMaxTripCount(g.insertConstant(std::numeric_limits<int64_t>::max()));\n            const inp_condition = toIValue(loop.inputCond());\n            if (inp_condition == null || inp_condition.toBool() == false) {\n              condition = g.insert(aten::__and__, {condition, loop.inputCond()});\n            }\n            loop.replaceInputCondition(condition);\n            n.addOutput().setType(IntType::get());\n            WithInsertPoint loop_insert(loop.bodyBlock());\n            n.addInput(zero);\n            const new_iter = loop.bodyBlock().addInput().setType(IntType::get());\n            // unset unique name for jitter, its replacement does not have a name\n            loop.currentTripCount().setDebugName('').replaceAllUsesWith(new_iter);\n            const inc_iter = g.insert(aten::add, {new_iter, one});\n            loop.bodyBlock().registerOutput(inc_iter);\n            const less_than_max_trip = g.insert(aten::lt, {inc_iter, max_trip_count});\n            const loop_continue = loop.nextCond();\n            const new_condition =\n                g.insert(aten::__and__, {less_than_max_trip, loop_continue});\n            loop.bodyBlock().eraseOutput(0);\n            loop.bodyBlock().insertOutput(0, new_condition);\n            */\n        });\n        this.registerFunction('torch._C.canonicalizeModifiedLoops', (block) => {\n            for (const n of block.nodes()) {\n                for (const b of n.blocks()) {\n                    torch._C.canonicalizeModifiedLoops(b);\n                }\n                if (n.kind() === 'prim::Loop') {\n                    torch._C.canonicalizeModifiedLoop(n);\n                }\n            }\n        });\n        this.registerFunction('torch._C.CanonicalizeModifiedLoops', (graph) => {\n            torch._C.canonicalizeModifiedLoops(graph.block());\n        });\n        this.registerType('torch._C.MiniEnvironment', class {\n            constructor(b, next) {\n                this.next = next || null;\n                this.table = new Map();\n            }\n            setVar(name, value) {\n                this.table.set(name, value);\n            }\n            definedVariables() {\n                const result = Array.from(this.table.keys());\n                return result.sort();\n            }\n            findInThisFrame(name) {\n                if (this.table.has(name)) {\n                    return this.table.get(name);\n                }\n                return null;\n            }\n            findInAnyFrame(name) {\n                /* eslint-disable consistent-this */\n                const self = this;\n                /* eslint-enable consistent-this */\n                for (let runner = self; runner; runner = runner.next) {\n                    const r = runner.findInThisFrame(name);\n                    if (r) {\n                        return r;\n                    }\n                }\n                return null;\n            }\n        });\n        this.registerType('torch._C.ValueEnvironment', class extends torch._C.MiniEnvironment {\n        });\n        this.registerType('torch._C.TypeEnvironment', class extends torch._C.MiniEnvironment {\n        });\n        this.registerType('torch._C.ControlFlowLoadStores', class {\n            constructor() {\n                this.environment_stack = null;\n            }\n            pushFrame(b) {\n                this.environment_stack = new torch._C.TypeEnvironment(b, this.environment_stack);\n            }\n            popFrame() {\n                const old_frame = this.environment_stack;\n                this.environment_stack = this.environment_stack.next;\n                return old_frame;\n            }\n            addBlockInput(b, type, name) {\n                const g = b.owningGraph();\n                g.createStore(name, b.addInput(name).setType(type)).insertAfter(b.param_node());\n            }\n            addBlockOutput(exit_block, type, name) {\n                const insert = new torch._C.WithInsertPoint(exit_block);\n                const g = exit_block.owningGraph();\n                const block_exit = g.insertNode(g.createLoad(name, type)).output();\n                exit_block.registerOutput(block_exit);\n                insert.dispose();\n            }\n            addNodeOutput(n, type, name) {\n                const out = n.addOutput().setType(type);\n                if (torch._C.meaningfulName(name)) {\n                    out.setDebugName(name);\n                }\n                const g = n.owningGraph();\n                g.createStore(name, out).insertAfter(n);\n            }\n            addNodeInput(n, type, name) {\n                const g = n.owningGraph();\n                const inp = g.createLoad(name, type).insertBefore(n).output();\n                n.addInput(inp);\n            }\n            addIfLoadStores(n) {\n                const [true_block, false_block] = n.blocks();\n                const true_vars = this.addControlFlowLoadStores(true_block);\n                const false_vars = this.addControlFlowLoadStores(false_block);\n                const mutated_variables = new Set();\n                for (const v of true_vars.definedVariables()) {\n                    if (false_vars.findInAnyFrame(v)) {\n                        mutated_variables.add(v);\n                    }\n                }\n                for (const v of false_vars.definedVariables()) {\n                    if (true_vars.findInAnyFrame(v)) {\n                        mutated_variables.add(v);\n                    }\n                }\n                for (const x of mutated_variables) {\n                    const true_type = true_vars.findInAnyFrame(x);\n                    const false_type = false_vars.findInAnyFrame(x);\n                    const unified = torch._C.unifyTypes(true_type, false_type, /*default_to_union=*/true);\n                    this.addBlockOutput(true_block, true_type, x);\n                    this.addBlockOutput(false_block, false_type, x);\n                    this.addNodeOutput(n, unified, x);\n                }\n            }\n            addLoopLoadStores(n) {\n                const [body_block] = n.blocks();\n                const loop_vars = this.addControlFlowLoadStores(body_block);\n                for (const name of loop_vars.definedVariables()) {\n                    const parent_type = this.environment_stack.findInAnyFrame(name);\n                    if (!parent_type) {\n                        continue;\n                    }\n                    const block_type = loop_vars.findInThisFrame(name);\n                    const unified_type = torch._C.unifyTypes(parent_type, block_type);\n                    this.addNodeInput(n, parent_type, name);\n                    this.addBlockInput(body_block, unified_type, name);\n                    this.addBlockOutput(body_block, block_type, name);\n                    this.addNodeOutput(n, unified_type, name);\n                }\n            }\n            addControlFlowLoadStores(block) {\n                this.pushFrame(block);\n                for (const n of block.nodes()) {\n                    switch (n.kind()) {\n                        case 'prim::If': {\n                            this.addIfLoadStores(n);\n                            break;\n                        }\n                        case 'prim::Loop': {\n                            this.addLoopLoadStores(n);\n                            break;\n                        }\n                        case 'prim::Closure': {\n                            for (const b of n.blocks()) {\n                                this.addControlFlowLoadStores(b);\n                            }\n                            break;\n                        }\n                        case 'prim::Store': {\n                            this.environment_stack.setVar(n.s('name'), n.input().type());\n                            break;\n                        }\n                        case 'prim::ComprehensionScope': {\n                            this.addControlFlowLoadStores(n.blocks().at(0));\n                            break;\n                        }\n                        default: {\n                            break;\n                        }\n                    }\n                }\n                return this.popFrame();\n            }\n            run(graph) {\n                this.addControlFlowLoadStores(graph.block());\n            }\n        });\n        this.registerType('torch._C.LoopContinuations', class {\n            constructor() {\n                this._graph = null;\n                this._false_val = null;\n                this._curr_loop = null;\n            }\n            assignExitContinuations(block) {\n                for (const n of block.nodes()) {\n                    switch (n.kind()) {\n                        case 'prim::If': {\n                            this.assignExitContinuations(n.blocks().at(0));\n                            this.assignExitContinuations(n.blocks().at(1));\n                            break;\n                        }\n                        case 'prim::Closure': {\n                            const closure_block = new torch._C.LoopContinuations();\n                            closure_block.run(n.blocks().at(0));\n                            break;\n                        }\n                        case 'prim::Loop': {\n                            const prev_loop = this._curr_loop;\n                            this._curr_loop = n;\n                            this.assignExitContinuations(n.blocks().at(0));\n                            this._curr_loop = prev_loop;\n                            break;\n                        }\n                        case 'prim::ContinueStmt': {\n                            const loop_continuation = this._graph.create('prim::LoopContinuation', 0).insertAfter(n);\n                            const header_block = loop_continuation.addBlock();\n                            const [, pre_header] = this._curr_loop.blocks();\n                            header_block.cloneFrom(pre_header, (v) => v);\n                            this.InlineBlockBeforeNode(n, header_block);\n                            loop_continuation.addInput(header_block.outputs()[0]);\n                            loop_continuation.eraseBlock(0);\n                            this.addLoopCarriedOutputs(loop_continuation);\n                            n.destroy();\n                            break;\n                        }\n                        case 'prim::BreakStmt': {\n                            const loop_exit = this._graph.create('prim::LoopContinuation', 0).insertAfter(n);\n                            loop_exit.addInput(this._false_val);\n                            this.addLoopCarriedOutputs(loop_exit);\n                            n.destroy();\n                            break;\n                        }\n                        default: {\n                            break;\n                        }\n                    }\n                }\n            }\n            run(...args) {\n                if (args.length === 1 && args[0] instanceof torch.Graph) {\n                    const [graph] = args;\n                    this.run(graph.block());\n                } else if (args.length === 1 && args[0] instanceof torch.Block) {\n                    const [b] = args;\n                    {\n                        this._graph = b.owningGraph();\n                        const guard = new torch._C.WithInsertPoint(b.nodes().front());\n                        this._false_val = this._graph.insertConstant(false);\n                        guard.dispose();\n                    }\n                    this.assignExitContinuations(b);\n                } else {\n                    throw new python.Error('Not implemented.');\n                }\n            }\n        });\n        this.registerType('torch._C.LoopView', class {\n            constructor(node) {\n                torch._C.AT_ASSERT(node.kind() === 'prim::Loop' || node.kind() === 'onnx::Loop');\n                this._node = node;\n            }\n            bodyBlock() {\n                return this._node.blocks().at(0);\n            }\n            nextCond() {\n                return this.bodyBlock().outputs()[0];\n            }\n            carriedOutputs() {\n                return this._node.outputs();\n            }\n            bodyCarriedInputs() {\n                return this.bodyBlock().inputs().slice(1);\n            }\n            bodyCarriedOutputs() {\n                return this.bodyBlock().outputs().slice(1);\n            }\n        });\n        this.registerType('torch._C.WithLoopStatus', class {\n            constructor(to_ir, new_status) {\n                this._to_ir = to_ir;\n                this._prev = this._to_ir._loop_status;\n                this._to_ir._loop_status = new_status;\n            }\n            dispose() {\n                this._to_ir._loop_status = this._prev;\n            }\n        });\n        this.registerFunction('torch._C.InlineBlockBeforeNode', (before_node, block) => {\n            for (const block_node of block.nodes()) {\n                block_node.moveBefore(before_node);\n            }\n        });\n        this.registerFunction('torch._C.inlineLoopCondition', (...args) => {\n            if (args.length === 1 && args[0] instanceof torch.Block) {\n                const [block] = args;\n                for (const n of block.nodes()) {\n                    for (const b of n.blocks()) {\n                        torch._C.inlineLoopCondition(b);\n                    }\n                    if (n.kind() === 'prim::Loop') {\n                        torch._C.inlineLoopCondition(n);\n                    }\n                }\n            } else if (args.length === 1 && args[0] instanceof torch.Node) {\n                const [n] = args;\n                const [body_block, pre_header] = n.blocks();\n                const temp_block = n.addBlock();\n                temp_block.cloneFrom(pre_header, (v) => v);\n                torch._C.InlineBlockBeforeNode(n, temp_block);\n                n.insertInput(1, temp_block.outputs()[0]);\n                n.eraseBlock(2);\n                torch._C.InlineBlockBeforeNode(body_block.return_node(), pre_header);\n                body_block.return_node().insertInput(0, pre_header.outputs()[0]);\n                n.eraseBlock(1);\n            } else {\n                throw new python.Error('Not implemented.');\n            }\n        });\n        this.registerFunction('torch._C.InlineLoopCondition', (graph) => {\n            torch._C.inlineLoopCondition(graph.block());\n        });\n        this.registerType('torch._C.EraseLoadStores', class {\n            pushFrame(b) {\n                this.environment_stack = new torch._C.ValueEnvironment(b, this.environment_stack);\n            }\n            popFrame() {\n                const old_frame = this.environment_stack;\n                this.environment_stack = this.environment_stack.next;\n                return old_frame;\n            }\n            eraseBlockLoadStores(block) {\n                this.pushFrame(block);\n                for (const n of block.nodes()) {\n                    switch (n.kind()) {\n                        case 'prim::Store': {\n                            this.environment_stack.setVar(n.s('name'), n.input());\n                            n.destroy();\n                            break;\n                        }\n                        case 'prim::Load': {\n                            const name = n.s('name');\n                            const value = this.environment_stack.findInAnyFrame(name);\n                            torch._C.TORCH_INTERNAL_ASSERT(value);\n                            n.output().replaceAllUsesWith(value);\n                            n.destroy();\n                            break;\n                        }\n                        case 'prim::ComprehensionScope': {\n                            const [body] = n.blocks();\n                            this.eraseBlockLoadStores(body);\n                            for (const body_node of body.nodes()) {\n                                body_node.moveBefore(n);\n                            }\n                            n.destroy();\n                            break;\n                        }\n                        default: {\n                            for (const b of n.blocks()) {\n                                this.eraseBlockLoadStores(b);\n                            }\n                            break;\n                        }\n                    }\n                }\n                this.popFrame();\n            }\n            run(graph) {\n                this.eraseBlockLoadStores(graph.block());\n            }\n        });\n        this.registerFunction('torch._C.convertEnterExitNodesToWithBlocks', (/* graph */) => {\n        });\n        this.registerFunction('torch._C.inlineConsecutiveIfs', (/* graph */) => {\n        });\n        this.registerType('torch._C.ExitPair', class {\n            constructor(exit_v, exit_val_ref) {\n                const exit_vals = [];\n                for (const v of exit_val_ref) {\n                    exit_vals.push(v);\n                }\n                if (exit_v.type() !== torch.BoolType.get()) {\n                    throw new python.Error('Invalid exit value type.');\n                }\n                this.first = exit_v;\n                this.second = exit_vals;\n            }\n            hasExited() {\n                return this.first;\n            }\n            exitValues() {\n                return this.second;\n            }\n        });\n        this.registerType('torch._C.ExitTransformer', class {\n            constructor(graph) {\n                this._graph = graph;\n                this._target_block = null;\n                this._unit_values = new Map();\n                const guard = new torch._C.WithInsertPoint(this._graph.block().nodes().front());\n                this._true_val = this._graph.insertConstant(true);\n                this._false_val = this._graph.insertConstant(false);\n                this._throws_val = this.getUnitValue(torch.BoolType.get());\n                guard.dispose();\n            }\n            getUnitValue(type) {\n                const maybe_val = this._unit_values.get(type);\n                if (maybe_val) {\n                    return maybe_val;\n                }\n                const unit = this._graph.createUninitialized(type).insertAfter(this._graph.param_node()).output();\n                this._unit_values.set(type, unit);\n                return unit;\n            }\n            transformReturnStmts() {\n                this._current_exit_kind = 'prim::ReturnStmt';\n                this.transformExits(this._graph.block());\n            }\n            transformLoopContinuations() {\n                this._current_exit_kind = 'prim::LoopContinuation';\n                this.transformExits(this._graph.block());\n            }\n            destroyNodeAfterExit(n) {\n                for (const output of n.outputs()) {\n                    if (output.uses().length > 0) {\n                        output.replaceAllUsesWith(this.getUnitValue(output.type()));\n                    }\n                }\n                n.destroy();\n            }\n            deleteAfterExitNodes(block, iter) {\n                const nodes = block.nodes();\n                if (iter === nodes.end()) {\n                    return;\n                }\n                const insert = new torch._C.WithInsertPoint(block.nodes().front());\n                for (const it of Array.from(nodes).reverse()) {\n                    if (it === iter) {\n                        break;\n                    }\n                    if (it !== block.return_node()) {\n                        this.destroyNodeAfterExit(it);\n                    }\n                }\n                this.destroyNodeAfterExit(iter);\n                insert.dispose();\n            }\n            updateTargetBlock(block) {\n                if (torch._C.ExitTransformer.owningNodeKind(block) === 'prim::Loop' && this._current_exit_kind === 'prim::LoopContinuation') {\n                    this._target_block = block;\n                } else if (torch._C.ExitTransformer.isGraphOrClosureBlock(block) && this._current_exit_kind === 'prim::ReturnStmt') {\n                    this._target_block = block;\n                }\n            }\n            transformLoop(node) {\n                const loop = new torch._C.LoopView(node);\n                const body = loop.bodyBlock();\n                const exit_pair = this.transformExits(body);\n                if (this.getExitStatus(exit_pair) === 'WONT' || this.getExitStatus(exit_pair) === 'THROWS') {\n                    return this.constructWontExitPair();\n                }\n                const insert = new torch._C.WithInsertPoint(body);\n                const new_if = this._graph.insertNode(this._graph.create('prim::If', 0));\n                new_if.addInput(exit_pair.hasExited());\n                new_if.addBlock().registerOutput(this._false_val);\n                new_if.addBlock().registerOutput(loop.nextCond());\n                const new_condition = new_if.addOutput().setType(torch.BoolType.get());\n                loop.bodyBlock().eraseOutput(0);\n                loop.bodyBlock().insertOutput(0, new_condition);\n                node.addInput(this._false_val);\n                body.addInput().setType(torch.BoolType.get());\n                body.registerOutput(exit_pair.hasExited());\n                const new_has_exited = node.addOutput().setType(torch.BoolType.get());\n                for (const exit_value of exit_pair.exitValues()) {\n                    const typ = exit_value.type();\n                    node.addInput(this.getUnitValue(typ));\n                    node.addOutput().setType(typ);\n                    body.addInput().setType(typ);\n                    body.registerOutput(exit_value);\n                }\n                const exit_vals = node.outputs().slice(node.outputs().length - exit_pair.exitValues().size());\n                const result = new torch._C.ExitPair(new_has_exited, exit_vals);\n                insert.dispose();\n                return result;\n            }\n            calcIfExitStatus(then_status, else_status) {\n                if (then_status === 'THROWS') {\n                    return else_status;\n                } else if (else_status === 'THROWS') {\n                    return then_status;\n                }\n                if (then_status === 'WONT' && else_status === 'WONT') {\n                    return 'WONT';\n                }\n                if (then_status === 'WILL' && else_status === 'WILL') {\n                    return 'WILL';\n                }\n                return 'MIGHT';\n            }\n            transformIf(node) {\n                const [then_block, else_block] = node.blocks();\n                let then_pair = this.transformExits(then_block);\n                let else_pair = this.transformExits(else_block);\n                const then_status = this.getExitStatus(then_pair);\n                const else_status = this.getExitStatus(else_pair);\n                const if_status = this.calcIfExitStatus(then_status, else_status);\n                if (if_status === 'THROWS') {\n                    return this.constructThrowsExitPair();\n                }\n                if (if_status === 'WONT') {\n                    return this.constructWontExitPair();\n                }\n                if (then_status === 'WONT' || then_status === 'THROWS') {\n                    const exit_vals = this.matchValuesWithUnitialized(else_pair.exitValues());\n                    then_pair = new torch._C.ExitPair(then_pair.hasExited(), exit_vals);\n                } else if (else_status === 'WONT' || else_status === 'THROWS') {\n                    const exit_vals = this.matchValuesWithUnitialized(then_pair.exitValues());\n                    else_pair = new torch._C.ExitPair(else_pair.hasExited(), exit_vals);\n                }\n                let has_exited = null;\n                if (if_status === 'WILL') {\n                    has_exited = this._true_val;\n                } else {\n                    this.addIfOutputs(node, [then_pair.hasExited()], [else_pair.hasExited()]);\n                    has_exited = node.outputs().at(node.outputs().length - 1);\n                }\n                this.addIfOutputs(node, then_pair.exitValues(), else_pair.exitValues());\n                const num_exit_vals = then_pair.exitValues().size();\n                const exit_vals = node.outputs().slice(node.outputs().length - num_exit_vals);\n                return new torch._C.ExitPair(has_exited, exit_vals);\n            }\n            transformExits(block) {\n                const prev_target_block = this._target_block;\n                this.updateTargetBlock(block);\n                let exit_pair = this.constructWontExitPair();\n                for (const node of block.nodes()) {\n                    const it = node.next;\n                    switch (node.kind()) {\n                        case 'prim::RaiseException': {\n                            exit_pair = this.constructThrowsExitPair();\n                            break;\n                        }\n                        case 'prim::ReturnStmt':\n                        case 'prim::LoopContinuation': {\n                            if (node.kind() === this._current_exit_kind) {\n                                exit_pair = this.constructWillExitPair(node.inputs());\n                                node.destroy();\n                            }\n                            break;\n                        }\n                        case 'prim::If': {\n                            exit_pair = this.transformIf(node);\n                            break;\n                        }\n                        case 'prim::With': {\n                            exit_pair = this.transformWith(node);\n                            break;\n                        }\n                        case 'prim::Closure': {\n                            this.transformExits(node.blocks().at(0));\n                            break;\n                        }\n                        case 'prim::Loop': {\n                            exit_pair = this.transformLoop(node);\n                            break;\n                        }\n                        default: {\n                            break;\n                        }\n                    }\n                    const status = this.getExitStatus(exit_pair);\n                    if (status === 'WILL' || status === 'THROWS') {\n                        this.deleteAfterExitNodes(block, it);\n                        break;\n                    }\n                    if (status === 'MIGHT') {\n                        throw new python.Error('Not implemented.');\n                        // const nodes = block.nodes();\n                        // if (node === nodes[nodes.length - 1]) {\n                        //     exit_pair = this.guardBlockNodes(block, exit_pair, it);\n                        // }\n                        // break;\n                    }\n                }\n                if (this._target_block === block) {\n                    if (this.getExitStatus(exit_pair) === 'MIGHT') {\n                        const new_if = this._graph.create('prim::If', 0).insertBefore(block.return_node());\n                        new_if.addBlock();\n                        new_if.addBlock();\n                        new_if.addInput(exit_pair.hasExited());\n                        torch._C.ExistTransformer.addIfOutputs(new_if, exit_pair.exitValues(), block.outputs());\n                        torch._C.ExistTransformer.replaceBlockOutputs(block, new_if.soutputs());\n                    } else if (this.getExitStatus(exit_pair) === 'WILL') {\n                        torch._C.ExitTransformer.replaceBlockOutputs(block, exit_pair.exitValues());\n                    }\n                    exit_pair = this.constructWontExitPair();\n                }\n                this._target_block = prev_target_block;\n                return exit_pair;\n            }\n            constructThrowsExitPair() {\n                return new torch._C.ExitPair(this._throws_val, []);\n            }\n            constructWontExitPair() {\n                return new torch._C.ExitPair(this._false_val, []);\n            }\n            constructWillExitPair(exit_val_ref) {\n                return new torch._C.ExitPair(this._true_val, exit_val_ref);\n            }\n            getExitStatus(exit_pair) {\n                const exit_v = exit_pair.hasExited();\n                if (exit_v === this._true_val) {\n                    return 'WILL';\n                } else if (exit_v === this._false_val) {\n                    return 'WONT';\n                } else if (exit_v === this._throws_val) {\n                    return 'THROWS';\n                }\n                return 'MIGHT';\n            }\n            static owningNodeKind(block) {\n                if (block.owningNode()) {\n                    return block.owningNode().kind();\n                }\n                return null;\n            }\n            static isGraphOrClosureBlock(block) {\n                return block.owningNode() === null || torch._C.ExitTransformer.owningNodeKind(block) === 'prim::Closure';\n            }\n            static removeOutputs(b) {\n                while (b.outputs().length > 0) {\n                    b.eraseOutput(0);\n                }\n            }\n            static registerBlockOutputs(b, outs) {\n                for (const out of outs) {\n                    b.registerOutput(out);\n                }\n            }\n            static replaceBlockOutputs(b, outs) {\n                torch._C.ExitTransformer.removeOutputs(b);\n                torch._C.ExitTransformer.registerBlockOutputs(b, outs);\n            }\n        });\n        this.registerFunction('torch._C.convertWithBlocksToEnterExitNodes', (/* graph */) => {\n        });\n        this.registerFunction('torch._C.TransformExits', (graph) => {\n            torch._C.convertEnterExitNodesToWithBlocks(graph);\n            const e_loop = new torch._C.ExitTransformer(graph);\n            e_loop.transformLoopContinuations();\n            const e_ret = new torch._C.ExitTransformer(graph);\n            e_ret.transformReturnStmts();\n            torch._C.inlineConsecutiveIfs(graph.block());\n            torch._C.convertWithBlocksToEnterExitNodes(graph);\n        });\n        this.registerFunction('torch._C.normalizeRSub', (iter) => {\n            if (iter.kind() === 'aten::rsub' && iter.schema() && iter.schema().overload === 'Tensor') {\n                const args = iter.inputs();\n                const newSub = iter.replaceWithNewSymbol('aten::sub');\n                newSub.replaceInput(0, args[1]);\n                newSub.replaceInput(1, args[0]);\n                iter.destroyCurrent();\n                return true;\n            }\n            return false;\n        });\n        this.registerFunction('torch._C.normalizeOpAliases', (/* iter */) => {\n        });\n        this.registerFunction('torch._C.normalizeIsBool', (iter) => {\n            const args = iter.inputs();\n            if (args.length === 2 && args[0].type() === torch.BoolType.get() && args[1].type() === torch.BoolType.get()) {\n                if (iter.kind() === 'aten::__is__') {\n                    iter.replaceWithNewSymbol('aten::eq');\n                    iter.destroyCurrent();\n                    return true;\n                }\n                if (iter.kind() === 'aten::__isnot__') {\n                    iter.replaceWithNewSymbol('aten::ne');\n                    iter.destroyCurrent();\n                    return true;\n                }\n            }\n            return false;\n        });\n        this.registerFunction('torch._C.NormalizeOps', (block) => {\n            for (const it of block.nodes()) {\n                for (const sub of it.blocks()) {\n                    torch._C.NormalizeOps(sub);\n                }\n                if (torch._C.normalizeRSub(it)) {\n                    continue;\n                }\n                if (torch._C.normalizeOpAliases(it)) {\n                    continue;\n                }\n                if (torch._C.normalizeIsBool(it)) {\n                    continue;\n                }\n            }\n        });\n        this.registerFunction('torch._C.getInlineEverythingMode', () => {\n            return false;\n        });\n        this.registerFunction('torch._C.runCleanupPasses', (to_clean) => {\n            /*\n            torch._C.liftClosures(to_clean);\n            torch._C.inlineForkedClosures(to_clean);\n            */\n            if (torch._C.getInlineEverythingMode()) {\n                torch._C.Inline(to_clean);\n            }\n            /*\n            torch._C.eraseListLiterals(to_clean);\n            */\n            torch._C.LowerSimpleTuples(to_clean);\n            torch._C.ConstantPropagationImmutableTypes(to_clean);\n            torch._C.ConstantPooling(to_clean);\n            /*\n            torch._C.CanonicalizeOutputs(to_clean);\n            torch._C.AnnotateWarns(to_clean);\n            */\n        });\n        this.registerType('torch.jit._script.ScriptModule', class extends torch.nn.modules.module.Module {});\n        this.registerType('torch.jit._trace.TracedModule', class extends torch.jit._script.ScriptModule {});\n        this.registerType('torch.jit._trace.TopLevelTracedModule', class extends torch.jit._trace.TracedModule {});\n        this.registerType('torch.jit._script.RecursiveScriptModule', class extends torch.jit._script.ScriptModule {\n            constructor(cpp_module) {\n                super();\n                this._initializing = true;\n                this._c = cpp_module;\n            }\n            static _construct(cpp_module, init_fn) {\n                const script_module = new torch.jit._script.RecursiveScriptModule(cpp_module);\n                init_fn(script_module);\n                torch.jit._script.RecursiveScriptModule._finalize_scriptmodule(script_module);\n                return script_module;\n            }\n            static _finalize_scriptmodule(script_module) {\n                script_module._parameters = new torch.ParameterDict(script_module._c).items();\n                script_module._buffers = new torch.BufferDict(script_module._c).items();\n                // script_module._modules = OrderedModuleDict(script_module._c, script_module._modules)\n                script_module._initializing = false;\n            }\n            get graph() {\n                // return this._c._get_method('forward').graph;\n                return this._c.graph;\n            }\n            get code_with_constants() {\n                // return this.forward.code_with_constants;\n                return this._c.code_with_constants;\n            }\n            __setattr__(name, value) {\n                if (this._initializing) {\n                    super.__setattr__(name, value);\n                } else if (this._modules.has(name)) {\n                    this._modules.set(name, value);\n                } else if (this._c.hasattr(name)) {\n                    this._c.setattr(name, value);\n                } else {\n                    //\n                }\n            }\n            __getattr__(name) {\n                if (this._initializing) {\n                    return super.__getattr__(name);\n                }\n                if (this._modules.has(name)) {\n                    return this._modules.get(name);\n                }\n                if (this._c.hasattr(name)) {\n                    return this._c.getattr(name);\n                }\n                if (this._c._has_method(name)) {\n                    //\n                }\n                return super.__getattr__(name);\n            }\n        });\n        torch.jit.ScriptModule = torch.jit._script.ScriptModule;\n        torch.jit.RecursiveScriptModule = torch.jit._script.RecursiveScriptModule;\n        torch.jit.TopLevelTracedModule = torch.jit._trace.TopLevelTracedModule;\n        torch.CompilationUnit = torch.jit.CompilationUnit;\n        torch._C.CompilationUnit = torch.jit.CompilationUnit;\n        torch._C.ScriptModule = torch.ScriptModule;\n        torch._C.ClassType = torch.ClassType;\n        this.registerType('torch._C.FlatBuffersLoader', class {\n            constructor(cu) {\n                this._cu = cu;\n                const torch = cu.execution.__import__('torch');\n                this._torch = torch;\n                const dtypes = Array.from(new Set(Object.values(torch).filter((obj) => obj instanceof torch.dtype)));\n                this._dtypes = new Map(dtypes.map((dtype) => [dtype.scalar_type(), dtype]));\n                this._ivalue_parsers = new Map();\n                this._ivalue_parsers.set(torch.mobile.serialization.Int, (ivalue) => ivalue.val.int_val);\n                this._ivalue_parsers.set(torch.mobile.serialization.Bool, (ivalue) => ivalue.val.bool_val);\n                this._ivalue_parsers.set(torch.mobile.serialization.Double, (ivalue) => ivalue.val.double_val);\n                this._ivalue_parsers.set(torch.mobile.serialization.TensorMetadata, (ivalue) => this.parseTensor(ivalue));\n                this._ivalue_parsers.set(torch.mobile.serialization.Object, (ivalue) => this.parseObject(ivalue));\n            }\n            parseModule(module) {\n                this._module = module;\n                this._all_functions = new Map();\n                this._all_ivalues = new Array(module.ivalues.length);\n                this._all_types = new Array(module.object_types.length);\n                const mobile_ivalue_size = module.mobile_ivalue_size ? module.mobile_ivalue_size : module.ivalues.length;\n                for (let i = 0; i < mobile_ivalue_size; i++) {\n                    this.parseAndPopulate(i, module.ivalues[i]);\n                }\n                const m = this._all_ivalues[module.state_obj];\n                for (const [name, value] of this._all_functions) {\n                    const class_index = module.ivalues[name].val.class_type;\n                    const class_type = this._all_types[class_index];\n                    if (value) {\n                        class_type.addMethod(value);\n                    }\n                }\n                m._min_operator_version = module.operator_version;\n                m._bytecode_version = module.bytecode_version;\n                return m;\n            }\n            parseAndPopulate(i, ivalue) {\n                if (ivalue.val instanceof torch.mobile.serialization.Function) {\n                    this._all_functions.set(i, this.parseFunction(ivalue.val));\n                } else {\n                    this._all_ivalues[i] = this.parseIValue(ivalue);\n                }\n            }\n            parseFunction(/* val */) {\n                return null;\n            }\n            parseIValue(ivalue) {\n                if (ivalue.val) {\n                    const callback = this._ivalue_parsers.get(ivalue.val.constructor);\n                    return callback(ivalue);\n                }\n                return null;\n            }\n            parseTensor(ivalue) {\n                return this.parseTensorFromMetadata(ivalue.val);\n            }\n            parseTensorFromMetadata(metadata) {\n                if (metadata.quantized_schema) {\n                    throw new torch.Error('Quantized schema not implemented.');\n                }\n                const index = metadata.storage_location_index;\n                const data = this._module.storage_data[index].data;\n                const dtype = this._dtypes.get(metadata.scalar_type);\n                const size = data.length / dtype.itemsize();\n                const storage = new torch.storage.TypedStorage(size, dtype);\n                storage._set_cdata(data);\n                const tensor = new torch.Tensor();\n                const shape = Array.from(metadata.sizes);\n                const stride = Array.from(metadata.strides);\n                tensor.__setstate__([storage, metadata.storage_offset, shape, stride]);\n                return tensor;\n            }\n            parseObject(ivalue) {\n                const object = ivalue.val;\n                const obj_type = this._module.object_types[object.type_index];\n                const cls = this.getOrCreateClassTypeForObject(object);\n                switch (obj_type.type) {\n                    case torch.mobile.serialization.TypeType.CLASS_WITH_FIELD: {\n                        const torch = this._torch;\n                        const obj = torch.ScriptObject.create(cls);\n                        for (let i = 0; i < object.attrs.length; i++) {\n                            const attr_name = obj_type.attr_names[i];\n                            const val = this._all_ivalues[object.attrs[i]];\n                            obj.__setattr__(attr_name, val);\n                        }\n                        return obj;\n                    }\n                    case torch.mobile.serialization.TypeType.CUSTOM_CLASS:\n                    case torch.mobile.serialization.TypeType.CLASS_WITH_SETSTATE:\n                    default: {\n                        throw new python.Error(`Unknown object type type '${obj_type.type}'.`);\n                    }\n                }\n            }\n            getOrCreateClassTypeForObject(object) {\n                let cls = this._all_types[object.type_index];\n                const obj_type = this._module.object_types[object.type_index];\n                if (!cls) {\n                    const name = obj_type.type_name;\n                    if (name.startsWith('__torch__') || name.startsWith('torch.jit')) {\n                        cls = this._cu.get_class(new torch._C.QualifiedName(name));\n                        if (!cls) {\n                            const torch = this._torch;\n                            cls = torch.ClassType.create(name, this._cu, true);\n                            this._cu.register_type(cls);\n                        }\n                    } else {\n                        // cls = c10::parseType(qn_str).cast<ClassType>();\n                    }\n                    this._all_types[object.type_index] = cls;\n                    if (obj_type.type === torch.mobile.serialization.TypeType.CLASS_WITH_FIELD) {\n                        for (let i = 0; i < object.attrs.length; i++) {\n                            // const val = this._all_ivalues[object.attrs[i]];\n                            cls.addAttribute(obj_type.attr_names[i] /*, null val.type(c10::DynamicType) */);\n                        }\n                    }\n                }\n                return cls;\n            }\n        });\n        this.registerType('torch.export.UnflattenedModule', class extends torch.nn.modules.module.Module {\n            constructor(export_module, flat_args_adapter) {\n                super();\n                const export_graph = copy.deepcopy(export_module.graph);\n                self.graph_signature = copy.deepcopy(export_module.graph_signature);\n                this.graph = torch.fx.Graph();\n                this.graph.owning_module = this;\n                this.module_call_graph = copy.deepcopy(export_module.module_call_graph);\n                this.flat_args_adapter = flat_args_adapter;\n                this.adapted = false;\n                // this._run_with_interpreter = RUN_WITH_INTERPRETER\n                this._inplace_buffer_mutations(export_graph, this.graph_signature);\n            }\n        });\n        this.registerType('torch.export.graph_signature.ExportGraphSignature', class {\n            constructor(input_specs, output_specs) {\n                this.input_specs = input_specs;\n                this.output_specs = output_specs;\n            }\n            get user_inputs() {\n                const user_inputs = [];\n                for (const s of this.input_specs) {\n                    if (s.kind !== torch.export.graph_signature.InputKind.USER_INPUT) {\n                        continue;\n                    }\n                    if (s.arg instanceof torch.export.graph_signature.TensorArgument ||\n                        s.arg instanceof torch.export.graph_signature.SymIntArgument ||\n                        s.arg instanceof torch.export.graph_signature.CustomObjArgument) {\n                        user_inputs.push(s.arg.name);\n                    } else if (s.arg instanceof torch.export.graph_signature.ConstantArgument) {\n                        user_inputs.push(s.arg.value);\n                    } else {\n                        throw new python.Error(`Unsupported user input '${s.arg}'.`);\n                    }\n                }\n                return user_inputs;\n            }\n            get user_outputs() {\n                const user_outputs = [];\n                for (const s of this.output_specs) {\n                    if (s.kind !== torch.export.graph_signature.OutputKind.USER_OUTPUT) {\n                        continue;\n                    }\n                    if (s.arg instanceof torch.export.graph_signature.TensorArgument ||\n                        s.arg instanceof torch.export.graph_signature.SymIntArgument ||\n                        s.arg instanceof torch.export.graph_signature.CustomObjArgument) {\n                        user_outputs.push(s.arg.name);\n                    } else if (s.arg instanceof torch.export.graph_signature.ConstantArgument) {\n                        user_outputs.push(s.arg.value);\n                    } else {\n                        throw new python.Error(`Unsupported user output '${s.arg}'.`);\n                    }\n                }\n                return user_outputs;\n            }\n            get inputs_to_parameters() {\n                return new Map(this.input_specs\n                    .filter((s) => s.kind === torch.export.graph_signature.InputKind.PARAMETER && s.arg instanceof torch.export.graph_signature.TensorArgument && typeof s.target === 'string')\n                    .map((s) => [s.arg.name, s.target]));\n            }\n            get inputs_to_buffers() {\n                return new Map(this.input_specs\n                    .filter((s) => s.kind === torch.export.graph_signature.InputKind.BUFFER && s.arg instanceof torch.export.graph_signature.TensorArgument && typeof s.target === 'string')\n                    .map((s) => [s.arg.name, s.target]));\n            }\n            get inputs_to_lifted_tensor_constants() {\n                return new Map(this.input_specs\n                    .filter((s) => s.kind === torch.export.graph_signature.InputKind.CONSTANT_TENSOR && s.arg instanceof torch.export.graph_signature.TensorArgument && typeof s.target === 'string')\n                    .map((s) => [s.arg.name, s.target]));\n            }\n        });\n        torch.export.graph_signature.InputKind = {\n            USER_INPUT: 0,\n            PARAMETER: 1,\n            BUFFER: 2,\n            CONSTANT_TENSOR: 3,\n            CUSTOM_OBJ: 4,\n            TOKEN: 5\n        };\n        this.registerType('torch.export.graph_signature.InputSpec', class {\n            constructor(kind, arg, target, persistent) {\n                this.kind = kind;\n                this.arg = arg;\n                this.target = target;\n                this.persistent = persistent || null;\n            }\n        });\n        torch.export.graph_signature.OutputKind = {\n            USER_OUTPUT: 0,\n            LOSS_OUTPUT: 1,\n            BUFFER_MUTATION: 2,\n            GRADIENT_TO_PARAMETER: 3,\n            GRADIENT_TO_USER_INPUT: 4,\n            USER_INPUT_MUTATION: 5,\n            TOKEN: 6\n        };\n        this.registerType('torch.export.graph_signature.OutputSpec', class {\n            constructor(kind, arg, target) {\n                this.kind = kind;\n                this.arg = arg;\n                this.target = target;\n            }\n        });\n        this.registerType('torch.export.graph_signature.ConstantArgument', class {\n            constructor(name, value) {\n                this.name = name;\n                this.value = value; // Union[int, float, bool, str, None]\n            }\n        });\n        this.registerType('torch.export.graph_signature.TensorArgument', class {\n            constructor(name) {\n                this.name = name;\n            }\n        });\n        this.registerType('torch.export.graph_signature.SymIntArgument', class {\n            constructor(name) {\n                this.name = name;\n            }\n        });\n        this.registerType('torch.export.graph_signature.CustomObjArgument', class {\n            constructor(name, class_fqn, fake_val) {\n                this.name = name;\n                this.class_fqn = class_fqn;\n                this.fake_val = fake_val;\n            }\n        });\n        this.registerType('torch.export.exported_program.ExportedProgram', class {\n            constructor(root, graph, graph_signature, state_dict, range_constraints, module_call_graph, example_inputs, verifier, tensor_constants, constants) {\n                // graph._codegen = torch.fx.graph.CodeGen()\n                this._graph_module = this._create_graph_module_for_export(root, graph);\n                if (root instanceof torch.fx.GraphModule) {\n                    // this._graph_module.meta.update(root.meta);\n                }\n                this._graph_signature = graph_signature;\n                this._state_dict = state_dict;\n                this._range_constraints = range_constraints;\n                this._module_call_graph = module_call_graph;\n                this._example_inputs = example_inputs;\n                this._constants = tensor_constants || constants || {};\n            }\n            _create_graph_module_for_export(root, graph) {\n                let gm = null;\n                try {\n                    gm = new torch.fx.GraphModule(root, graph);\n                } catch {\n                    const gm = new torch.fx.GraphModule(root, torch.fx.Graph());\n                    gm._graph = graph;\n                }\n                return gm;\n            }\n            get graph_module() {\n                return this._graph_module;\n            }\n            get graph() {\n                return this._graph_module.graph;\n            }\n            get graph_signature() {\n                return this._graph_signature;\n            }\n            get state_dict() {\n                return this._state_dict;\n            }\n            get constants() {\n                return this._constants;\n            }\n        });\n        this.registerType('torch.export.exported_program.ModuleCallEntry', class {});\n        this.registerType('torch.export.exported_program.ModuleCallSignature', class {});\n        this.registerFunction('torch.export.exported_program._create_graph_module_for_export', (root, graph) => {\n            return new torch.fx.graph_module.GraphModule(root, graph);\n        });\n        this.registerFunction('torch.export.unflatten', (module, flat_args_adapter) => {\n            module = torch.export._remove_effect_tokens(module);\n            return new torch.export.UnflattenedModule(module, flat_args_adapter);\n        });\n        this.registerFunction('torch._export.exported_program._create_graph_module_for_export', (root, graph) => {\n            return new torch.fx.graph_module.GraphModule(root, graph);\n        });\n        this.registerType('torch._export.serde.serialize.SerializedArtifact', class {\n            constructor(exported_program, state_dict, constants, example_inputs) {\n                this.exported_program = exported_program;\n                this.state_dict = state_dict;\n                this.constants = constants;\n                this.example_inputs = example_inputs;\n            }\n        });\n        torch._export.serde.serialize._SYM_OPS = new Set([\n            operator.eq, operator.ne, operator.le, operator.ge, operator.lt, operator.gt,\n            operator.neg, operator.pos, operator.and_, operator.or_,\n            math.trunc, torch.sym_not,\n            operator.mul, operator.add, operator.sub, operator.floordiv, operator.mod, operator.pow,\n            torch.sym_int, torch.sym_float, torch.sym_ite, torch.sym_max, torch.sym_min, torch.sym_sqrt,\n            operator.truediv, operator.and_\n        ]);\n        this.registerType('torch._export.serde.union._Union', class {\n            constructor(obj) {\n                if (obj.$type) {\n                    this.type = obj.$type;\n                    this[obj.$type] = obj.$value;\n                    delete obj.$type;\n                    delete obj.$value;\n                } else if (obj.type) {\n                    this.type = obj.type;\n                    const entries = Object.entries(obj).filter(([key]) => key !== 'type');\n                    this[obj.type] = Object.fromEntries(entries);\n                } else {\n                    let entries = Object.entries(obj);\n                    if (entries.length > 1) {\n                        entries = entries.filter(([, value]) => value !== null);\n                    }\n                    if (entries.length !== 1) {\n                        throw new python.Error(`Invalid union type '${entries.map(([key]) => key).join(',')}'.`);\n                    }\n                    const [entry] = entries;\n                    const [type, value] = entry;\n                    this.type = type;\n                    this[type] = value;\n                }\n            }\n            get value() {\n                return this[this.type];\n            }\n        });\n        this.registerType('torch._export.serde.schema.NamedArgument', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.Argument(obj.arg);\n                this.name = obj.name;\n                this.kind = obj.kind === undefined ? null : obj.kind;\n            }\n        });\n        this.registerType('torch._export.serde.schema.Argument', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                switch (this.type) {\n                    case 'as_int':\n                    case 'as_ints':\n                    case 'as_float':\n                    case 'as_floats':\n                    case 'as_bool':\n                    case 'as_bools':\n                    case 'as_string':\n                    case 'as_strings':\n                    case 'as_scalar_type':\n                    case 'as_device':\n                    case 'as_memory_format':\n                    case 'as_layout':\n                        break;\n                    case 'as_none':\n                        this.as_none = null;\n                        break;\n                    case 'as_tensor':\n                        this.as_tensor = new torch._export.serde.schema.TensorArgument(this.as_tensor);\n                        break;\n                    case 'as_tensors':\n                        this.as_tensors = this.as_tensors.map((item) => new torch._export.serde.schema.TensorArgument(item));\n                        break;\n                    case 'as_graph':\n                        this.as_graph = new torch._export.serde.schema.GraphArgument(this.as_graph);\n                        break;\n                    case 'as_sym_int':\n                        this.as_sym_int = new torch._export.serde.schema.SymIntArgument(this.as_sym_int);\n                        break;\n                    case 'as_sym_ints':\n                        this.as_sym_ints = this.as_sym_ints.map((item) => new torch._export.serde.schema.SymIntArgument(item));\n                        break;\n                    case 'as_sym_bool':\n                        this.as_sym_bool = new torch._export.serde.schema.SymBoolArgument(this.as_sym_bool);\n                        break;\n                    case 'as_sym_bools':\n                        this.as_sym_bools = this.as_sym_bools.map((item) => new torch._export.serde.schema.SymBoolArgument(item));\n                        break;\n                    case 'as_sym_float':\n                        this.as_sym_float = new torch._export.serde.schema.SymFloatArgument(this.as_sym_float);\n                        break;\n                    case 'as_sym_floats':\n                        this.as_sym_floats = this.as_sym_floats.map((item) => new torch._export.serde.schema.SymFloatArgument(item));\n                        break;\n                    case 'as_optional_tensors':\n                        this.as_optional_tensors = this.as_optional_tensors.map((item) => new torch._export.serde.schema.OptionalTensorArgument(item));\n                        break;\n                    case 'as_custom_obj':\n                        this.as_custom_obj = new torch._export.serde.schema.CustomObjArgument(this.as_custom_obj);\n                        break;\n                    // case 'as_graph': GraphArgument\n                    default:\n                        throw new python.Error(`Unsupported argument '${this.type}'.`);\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.Node', class {\n            constructor(obj) {\n                this.target = obj.target;\n                this.inputs = obj.inputs.map((input) => new torch._export.serde.schema.NamedArgument(input));\n                this.outputs = obj.outputs.map((output) => new torch._export.serde.schema.Argument(output));\n                this.metadata = new Map(Object.entries(obj.metadata));\n            }\n        });\n        torch._export.serde.schema.ScalarType = {\n            UNKNOWN: 0,\n            BYTE: 1,\n            CHAR: 2,\n            SHORT: 3,\n            INT: 4,\n            LONG: 5,\n            HALF: 6,\n            FLOAT: 7,\n            DOUBLE: 8,\n            COMPLEXHALF: 9,\n            COMPLEXFLOAT: 10,\n            COMPLEXDOUBLE: 11,\n            BOOL: 12,\n            BFLOAT16: 13,\n            UINT16: 28,\n            FLOAT8E4M3FN: 29,\n            FLOAT8E5M2: 30,\n            FLOAT8E4M3FNUZ: 31,\n            FLOAT8E5M2FNUZ: 32,\n        };\n        torch._export.serde.schema.Layout = {\n            Unknown: 0,\n            SparseCoo: 1,\n            SparseCsr: 2,\n            SparseCsc: 3,\n            SparseBsr: 4,\n            SparseBsc: 5,\n            _mkldnn: 6,\n            Strided: 7\n        };\n        torch._export.serde.schema.MemoryFormat = {\n            Unknown: 0,\n            ContiguousFormat: 1,\n            ChannelsLast: 2,\n            ChannelsLast3d: 3,\n            PreserveFormat: 4,\n        };\n        this.registerType('torch._export.serde.schema.Device', class {\n            constructor(obj) {\n                Object.assign(this, { ...obj });\n            }\n        });\n        this.registerType('torch._export.serde.schema.TensorMeta', class {\n            constructor(obj) {\n                obj = obj.meta || obj;\n                this.dtype = obj.dtype;\n                this.sizes = obj.sizes.map((size) => new torch._export.serde.schema.SymInt(size));\n                this.requires_grad = obj.requires_grad;\n                this.device = obj.device;\n                this.strides = obj.strides.map((stride) => new torch._export.serde.schema.SymInt(stride));\n                this.storage_offset = new torch._export.serde.schema.SymInt(Number.isInteger(obj.storage_offset) ? { as_int: obj.storage_offset } : obj.storage_offset);\n                this.layout = obj.layout;\n            }\n        });\n        this.registerType('torch._export.serde.schema.Graph', class {\n            constructor(obj) {\n                this.inputs = obj.inputs.map((input) => new torch._export.serde.schema.Argument(input));\n                this.outputs = obj.outputs.map((output) => new torch._export.serde.schema.Argument(output));\n                this.nodes = obj.nodes.map((node) => new torch._export.serde.schema.Node(node));\n                this.tensor_values = new Map(Object.entries(obj.tensor_values).map(([key, value]) => [key, new torch._export.serde.schema.TensorMeta(value)]));\n                this.sym_int_values = new Map(Object.entries(obj.sym_int_values).map(([key, value]) => [key, new torch._export.serde.schema.SymInt(value)]));\n                this.sym_bool_values = new Map(Object.entries(obj.sym_bool_values).map(([key, value]) => [key, new torch._export.serde.schema.SymBool(value)]));\n                this.is_single_tensor_return = obj.is_single_tensor_return;\n                this.custom_obj_values = new Map(Object.entries(obj.custom_obj_values || {}).map(([key, value]) => [key, new torch._export.serde.schema.CustomObjArgument(value)]));\n                if (obj.contants) {\n                    // this.constants = new Map(Object.entries(serialized_graph.constants).map(([k, v]) => [k, torch.load(v)]));\n                    // graph_signature -> input_specs -> tensor_constant\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.ModuleCallSignature', class {\n            constructor(obj) {\n                Object.assign(this, { ...obj });\n                this.inputs = this.inputs.map((item) => new torch._export.serde.schema.Argument(item));\n                this.outputs = this.outputs.map((item) => new torch._export.serde.schema.Argument(item));\n            }\n        });\n        this.registerType('torch._export.serde.schema.ModuleCallEntry', class {\n            constructor(obj) {\n                Object.assign(this, { ...obj });\n                this.signature = this.signature ? new torch._export.serde.schema.ModuleCallSignature(this.signature) : null;\n            }\n        });\n        this.registerType('torch._export.serde.schema.GraphModule', class {\n            constructor(obj) {\n                this.graph = new torch._export.serde.schema.Graph(obj.graph);\n                this.signature = new torch._export.serde.schema.GraphSignature(obj.signature);\n                this.module_call_graph = obj.module_call_graph.map((item) => new torch._export.serde.schema.ModuleCallEntry(item));\n                this.metadata = new Map(Object.entries(obj.metadata || {}));\n            }\n        });\n        this.registerType('torch._export.serde.schema.ExportedProgram', class {\n            constructor(obj) {\n                Object.assign(this, { ...obj });\n                this.graph_module = new torch._export.serde.schema.GraphModule(obj.graph_module);\n            }\n        });\n        this.registerType('torch._export.serde.schema.SymExprHint', class extends torch._export.serde.union._Union {});\n        this.registerType('torch._export.serde.schema.SymExpr', class {\n            constructor(obj) {\n                this.expr_str = obj.expr_str;\n                this.hint = obj.hint ? new torch._export.serde.schema.SymExprHint(obj.hint) : null;\n            }\n        });\n        this.registerType('torch._export.serde.schema.SymInt', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                if (this.type === 'as_int') {\n                    // continue\n                } else if (this.type === 'as_expr') {\n                    this.as_expr = new torch._export.serde.schema.SymExpr(this.as_expr);\n                } else {\n                    throw new python.Error(`Unsupported symbolic int '${this.type}'.`);\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.SymBool', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                if (this.type === 'as_bool') {\n                    // continue\n                } else if (this.type === 'as_expr') {\n                    this.as_expr = new torch._export.serde.schema.SymExpr(this.as_expr);\n                } else {\n                    throw new python.Error(`Unsupported symbolic bool '${this.type}'.`);\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.SymIntArgument', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                Object.assign(this, { ...obj });\n            }\n        });\n        this.registerType('torch._export.serde.schema.SymFloatArgument', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                Object.assign(this, { ...obj });\n            }\n        });\n        this.registerType('torch._export.serde.schema.SymBoolArgument', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                Object.assign(this, { ...obj });\n            }\n        });\n        this.registerType('torch._export.serde.schema.CustomObjArgument', class {\n            constructor(obj) {\n                Object.assign(this, { ...obj });\n            }\n        });\n        this.registerType('torch._export.serde.schema.GraphSignature', class {\n            constructor(obj) {\n                this.input_specs = [];\n                if (Array.isArray(obj.input_specs)) {\n                    this.input_specs = obj.input_specs.map((input_spec) => new torch._export.serde.schema.InputSpec(input_spec));\n                }\n                if (Array.isArray(obj.user_inputs)) {\n                    for (const user_input of obj.user_inputs) {\n                        this.input_specs.push(new torch._export.serde.schema.InputSpec({ user_input: { arg: { as_string: user_input } } }));\n                    }\n                }\n                if (obj.inputs_to_parameters) {\n                    for (const [input, parameter_name] of Object.entries(obj.inputs_to_parameters)) {\n                        this.input_specs.push(new torch._export.serde.schema.InputSpec({ parameter: { arg: { name: input }, parameter_name } }));\n                    }\n                }\n                this.output_specs = [];\n                if (Array.isArray(obj.output_specs)) {\n                    this.output_specs = obj.output_specs.map((output_spec) => new torch._export.serde.schema.OutputSpec(output_spec));\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.UserInputSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.Argument(obj.arg);\n            }\n        });\n        this.registerType('torch._export.serde.schema.InputToParameterSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.TensorArgument(obj.arg);\n                this.parameter_name = obj.parameter_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.InputToBufferSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.TensorArgument(obj.arg);\n                this.buffer_name = obj.buffer_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.InputToTensorConstantSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.TensorArgument(obj.arg);\n                this.tensor_constant_name = obj.tensor_constant_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.InputToConstantInputSpec', class {\n            constructor(obj) {\n                this.name = obj.name;\n                this.value = new torch._export.serde.schema.ConstantValue(obj.value);\n            }\n        });\n        this.registerType('torch._export.serde.schema.ConstantValue', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                if (this.type === 'as_int' || this.type === 'as_float' || this.type === 'as_bool' || this.type === 'as_string' || this.type === 'as_strings') {\n                    // continue\n                } else if (this.type === 'as_none') {\n                    this.as_none = null;\n                } else {\n                    throw new python.Error(`Unsupported constant value type '${this.type}'.`);\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.InputSpec', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                if (this.type === 'user_input') {\n                    this.user_input = new torch._export.serde.schema.UserInputSpec(this.user_input);\n                } else if (this.type === 'parameter') {\n                    this.parameter = new torch._export.serde.schema.InputToParameterSpec(this.parameter);\n                } else if (this.type === 'buffer') {\n                    this.buffer = new torch._export.serde.schema.InputToBufferSpec(this.buffer);\n                } else if (this.type === 'tensor_constant') {\n                    this.tensor_constant = new torch._export.serde.schema.InputToTensorConstantSpec(this.tensor_constant);\n                } else if (this.type === 'constant_input') {\n                    this.constant_input = new torch._export.serde.schema.InputToConstantInputSpec(this.constant_input);\n                } else {\n                    throw new python.Error(`Unsupported input spec type '${this.type}'.`);\n                }\n                /*\n                custom_obj: InputToCustomObjSpec\n                token: InputTokenSpec\n                */\n            }\n        });\n        this.registerType('torch._export.serde.schema.UserOutputSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.Argument(obj.arg);\n            }\n        });\n        this.registerType('torch._export.serde.schema.BufferMutationSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.TensorArgument(obj.arg);\n                this.buffer_name = obj.buffer_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.GradientToParameterSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.Argument(obj.arg);\n                this.parameter_name = obj.parameter_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.GradientToUserInputSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.Argument(obj.arg);\n                this.user_input_name = obj.user_input_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.UserInputMutationSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.Argument(obj.arg);\n                this.user_input_name = obj.user_input_name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.OutputTokenSpec', class {\n            constructor(obj) {\n                this.arg = new torch._export.serde.schema.TokenArgument(obj.arg);\n            }\n        });\n        this.registerType('torch._export.serde.schema.OutputSpec', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                if (this.type === 'user_output') {\n                    this.user_output = new torch._export.serde.schema.UserOutputSpec(this.user_output);\n                } else if (this.type === 'loss_output') {\n                    this.loss_output = new torch._export.serde.schema.LossOutputSpec(this.loss_output);\n                } else if (this.type === 'buffer_mutation') {\n                    this.buffer_mutation = new torch._export.serde.schema.BufferMutationSpec(this.buffer_mutation);\n                } else if (this.type === 'gradient_to_parameter') {\n                    this.gradient_to_parameter = new torch._export.serde.schema.GradientToParameterSpec(this.gradient_to_parameter);\n                } else if (this.type === 'gradient_to_user_input') {\n                    this.gradient_to_user_input = new torch._export.serde.schema.GradientToUserInputSpec(this.gradient_to_user_input);\n                } else if (this.type === 'user_input_mutation') {\n                    this.user_input_mutation = new torch._export.serde.schema.UserInputMutationSpec(this.user_input_mutation);\n                } else if (this.type === 'token') {\n                    this.token = new torch._export.serde.schema.OutputTokenSpec(this.token);\n                }\n            }\n        });\n        this.registerType('torch._export.serde.schema.TensorArgument', class {\n            constructor(obj) {\n                this.name = obj.name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.TokenArgument', class {\n            constructor(obj) {\n                this.name = obj.name;\n            }\n        });\n        this.registerType('torch._export.serde.schema.GraphArgument', class {\n            constructor(obj) {\n                this.name = obj.name;\n                this.graph = new torch._export.serde.schema.Graph(obj.graph);\n            }\n        });\n        this.registerType('torch._export.serde.schema.OptionalTensorArgument', class extends torch._export.serde.union._Union {\n            constructor(obj) {\n                super(obj);\n                if (this.type === 'as_tensor') {\n                    this.as_tensor = new torch._export.serde.schema.TensorArgument({ name: this.as_tensor });\n                } else if (this.type === 'as_none') {\n                    this.as_none = null;\n                } else {\n                    throw new python.Error(`Unsupported optional tensor argument '${this.type}'.`);\n                }\n            }\n        });\n        this.registerFunction('torch.export.pt2_archive._package._load_state_dict', (f, model_name) => {\n            const legacy_file = `data/weights/${model_name}.pt`;\n            if (f.has(legacy_file)) {\n                return f.get(legacy_file);\n            }\n            const weights_config_file = `data/weights/${model_name}_weights_config.json`;\n            if (!f.has(weights_config_file)) {\n                return null;\n            }\n            const weights_config = f.get(weights_config_file);\n            const state_dict_file_map = torch.export.pt2_archive._package._build_file_map(f, weights_config, 'data/weights/');\n            const state_dict = new builtins.dict();\n            for (const [weight_fqn, payload_meta] of Object.entries(weights_config.config)) {\n                if (payload_meta.use_pickle) {\n                    const weight_bytes = f.get(`data/weights/${payload_meta.path_name}`);\n                    const weight_tensor = torch.load(weight_bytes);\n                    state_dict.set(weight_fqn, weight_tensor);\n                } else {\n                    const tensor_meta = payload_meta.tensor_meta;\n                    const tensor = state_dict_file_map.get(payload_meta.path_name);\n                    const sizes = tensor_meta.sizes.map((s) => s.as_int);\n                    const strides = tensor_meta.strides.map((s) => s.as_int);\n                    const storage_offset = tensor_meta.storage_offset.as_int;\n                    const weight_tensor = new torch.Tensor();\n                    weight_tensor.__setstate__([tensor.storage(), storage_offset, sizes, strides]);\n                    weight_tensor.requires_grad = tensor_meta.requires_grad || false;\n                    if (payload_meta.is_param) {\n                        state_dict.set(weight_fqn, new torch.nn.parameter.Parameter(weight_tensor, tensor_meta.requires_grad));\n                    } else {\n                        state_dict.set(weight_fqn, weight_tensor);\n                    }\n                }\n            }\n            return state_dict;\n        });\n        this.registerFunction('torch.export.pt2_archive._package._load_constants', (f, model_name) => {\n            const legacy_file = `data/constants/${model_name}.pt`;\n            if (f.has(legacy_file)) {\n                const entries = f.get(legacy_file);\n                return new builtins.dict(entries);\n            }\n            const constants_config_file = `data/constants/${model_name}_constants_config.json`;\n            if (!f.has(constants_config_file)) {\n                return null;\n            }\n            const constants_config = f.get(constants_config_file);\n            const constant_file_map = torch.export.pt2_archive._package._build_file_map(f, constants_config, 'data/constants/');\n            const constants = new builtins.dict();\n            for (const [constant_fqn, payload_meta] of Object.entries(constants_config.config)) {\n                const path_name = payload_meta.path_name;\n                if (path_name.startsWith('tensor_')) {\n                    if (payload_meta.use_pickle) {\n                        const constant_bytes = f.get(`data/constants/${payload_meta.path_name}`);\n                        const constant_tensor = torch.load(constant_bytes);\n                        constants.set(constant_fqn, constant_tensor);\n                    } else {\n                        const tensor_meta = payload_meta.tensor_meta;\n                        const tensor = constant_file_map.get(payload_meta.path_name);\n                        const sizes = tensor_meta.sizes.map((s) => s.as_int);\n                        const strides = tensor_meta.strides.map((s) => s.as_int);\n                        const storage_offset = tensor_meta.storage_offset.as_int;\n                        const constant_tensor = new torch.Tensor();\n                        constant_tensor.__setstate__([tensor.storage(), storage_offset, sizes, strides]);\n                        constants.set(constant_fqn, constant_tensor);\n                    }\n                } else if (payload_meta.path_name.startsWith('custom_obj_')) {\n                    const custom_obj_bytes = f.get(`data/constants/${payload_meta.path_name}`);\n                    const custom_obj = torch._C._pickle_load_obj(custom_obj_bytes);\n                    constants.set(constant_fqn, custom_obj);\n                }\n            }\n            return constants;\n        });\n        this.registerFunction('torch._export.serde.serialize.deserialize_scalar_type', (st) => {\n            if (!torch._export.serde.serialize._SERIALIZE_TO_TORCH_DTYPE.has(st)) {\n                throw new python.Error(`Unsupported scalar type '${st}'.`);\n            }\n            return torch._export.serde.serialize._SERIALIZE_TO_TORCH_DTYPE.get(st);\n        });\n        this.registerFunction('torch.export.pt2_archive._package._build_file_map', (archive_reader, config, base_dir) => {\n            const file_map = new builtins.dict();\n            for (const payload_meta of Object.values(config.config)) {\n                if (payload_meta.use_pickle) {\n                    continue;\n                }\n                if (file_map.has(payload_meta.path_name)) {\n                    continue;\n                }\n                const tensor_bytes = archive_reader.get(`${base_dir}${payload_meta.path_name}`);\n                const tensor = torch.export.pt2_archive._package._create_flat_tensor_from_bytes(tensor_bytes, payload_meta.tensor_meta);\n                file_map.set(payload_meta.path_name, tensor);\n            }\n            return file_map;\n        });\n        this.registerFunction('torch.export.pt2_archive._package._create_flat_tensor_from_bytes', (tensor_bytes, tensor_meta) => {\n            const dtype = torch._export.serde.serialize.deserialize_scalar_type(tensor_meta.dtype);\n            const itemsize = dtype.itemsize();\n            const num_elements = tensor_bytes.length / itemsize;\n            const storage = new torch.storage.TypedStorage(num_elements, dtype);\n            storage._set_cdata(tensor_bytes);\n            const tensor = new torch.Tensor();\n            tensor.__setstate__([storage, 0, [num_elements], [1]]);\n            tensor.requires_grad = tensor_meta.requires_grad || false;\n            return tensor;\n        });\n        this.registerFunction('torch.export.pt2_archive._package.load_pt2', (f, expected_opset_version) => {\n            const exported_programs = new Map();\n            for (const name of f.keys()) {\n                const match = name.match(/^models\\/([^/]+)\\.json$/);\n                if (match) {\n                    const [, model_name] = match;\n                    const serialized_exported_program = f.get(`models/${model_name}.json`);\n                    const serialized_state_dict = torch.export.pt2_archive._package._load_state_dict(f, model_name);\n                    const serialized_constants = torch.export.pt2_archive._package._load_constants(f, model_name);\n                    const serialized_example_inputs = f.get(`data/sample_inputs/${model_name}.pt`, 'zip');\n                    const artifact = new torch._export.serde.serialize.SerializedArtifact(serialized_exported_program, serialized_state_dict, serialized_constants, serialized_example_inputs);\n                    const exported_program = torch._export.serde.serialize.deserialize(artifact, expected_opset_version);\n                    exported_programs.set(model_name, exported_program);\n                }\n            }\n            return { exported_programs };\n        });\n        this.registerFunction('torch._export.serde.serialize._dict_to_dataclass', (cls, data) => {\n            if (data === null) {\n                return data;\n            }\n            if (cls) {\n                return new cls(data);\n            }\n            throw new python.Error(`Unsupported data class '${cls.__name__}'.`);\n        });\n        this.registerFunction('torch._export.serde.serialize.deserialize', (artifact, expected_opset_version) => {\n            const serialized_exported_program = torch._export.serde.serialize._dict_to_dataclass(torch._export.serde.schema.ExportedProgram, artifact.exported_program);\n            return new torch._export.serde.serialize.ExportedProgramDeserializer(expected_opset_version).deserialize(serialized_exported_program, artifact.state_dict, artifact.constants, artifact.example_inputs);\n        });\n        this.registerType('torch._export.serde.serialize.ExportedProgramDeserializer', class {\n            constructor(expected_opset_version) {\n                this.expected_opset_version = expected_opset_version;\n            }\n            deserialize(exported_program, state_dict, constants, example_inputs) {\n                const symbol_name_to_range = new Map(Object.entries(exported_program.range_constraints));\n                /*\n                symbol_name_to_range = {\n                    k: symbolic_shapes.ValueRanges(_int_to_sympy_int(v.min_val), _int_to_sympy_int(v.max_val))\n                    for k, v in exported_program.range_constraints.items()\n                }\n                */\n                const deserializer = new torch._export.serde.serialize.GraphModuleDeserializer();\n                const res = deserializer.deserialize(\n                    exported_program.graph_module,\n                    state_dict,\n                    constants,\n                    example_inputs,\n                    symbol_name_to_range);\n                const range_constraints = null;\n                /*\n                range_constraints = self.deserialize_range_constraints(\n                    symbol_name_to_range, res.names_to_symbols,\n                )\n                model_opset_version: Optional[Dict[str, int]] = serialized_artifact.exported_program.opset_version\n                self._validate_model_opset_version(model_opset_version)\n                upgrader = GraphModuleOpUpgrader(self.expected_opset_version, model_opset_version)\n                */\n                return new torch.export.exported_program.ExportedProgram(\n                    res.graph_module, res.graph_module.graph, res.signature,\n                    res.state_dict, range_constraints, res.module_call_graph, res.example_inputs,\n                    null, // verifier=load_verifier(serialized_artifact.exported_program.dialect),\n                    res.constants);\n                // return upgrader.upgrade(exported_program)\n            }\n        });\n        this.registerFunction('torch._export.serde.serialize.deserialize_torch_artifact', (serialized) => {\n            if (serialized instanceof builtins.dict || serialized instanceof builtins.tuple) {\n                return serialized;\n            }\n            if (serialized === null || serialized.length === 0) {\n                return new builtins.dict();\n            }\n            const artifact = torch.load(serialized);\n            return artifact;\n        });\n        this.registerType('torch._export.serde.serialize.GraphModuleDeserializer', class {\n            constructor() {\n                this.serialized_name_to_node = new builtins.dict();\n                this.serialized_name_to_meta = new builtins.dict(); // torch._export.serde.serialize.LazyMap\n                this.graph = new torch.fx.Graph();\n                this.module = new torch.nn.Module();\n            }\n            save_graph_module() {\n                const Context = class {\n                    constructor(self) {\n                        this.self = self;\n                    }\n                    __enter__() {\n                        this.saved = [\n                            this.self.graph,\n                            this.self.module,\n                            this.self.serialized_name_to_node,\n                            this.self.serialized_name_to_meta,\n                            this.self.unbacked_symbols,\n                        ];\n                        this.self.graph = new torch.fx.graph.Graph();\n                        this.self.module = new torch.nn.modules.module.Module();\n                        this.self.serialized_name_to_node = new builtins.dict();\n                        this.self.serialized_name_to_meta = new builtins.dict(); // torch._export.serde.serialize.LazyMap\n                        this.self.unbacked_symbols = new Set();\n                    }\n                    __exit__(/* exc_type, exc_value, traceback */) {\n                        const self = this.self;\n                        [self.graph, self.module, self.serialized_name_to_node, self.serialized_name_to_meta, self.unbacked_symbols] = this.saved;\n                    }\n                };\n                return new Context(this);\n            }\n            deserialize_graph_output(output) {\n                if (output.type === 'as_tensor') {\n                    return this.serialized_name_to_node.get(output.as_tensor.name);\n                } else if (output.type === 'as_sym_int') {\n                    return this.serialized_name_to_node.get(output.as_sym_int.as_name);\n                } else if (output.type === 'as_sym_bool') {\n                    return this.serialized_name_to_node.get(output.as_sym_bool.as_name);\n                } else if (output.type === 'as_sym_float') {\n                    return this.serialized_name_to_node.get(output.as_sym_float.as_name);\n                } else if (output.type === 'as_int') {\n                    return output.as_int;\n                } else if (output.type === 'as_float') {\n                    return output.as_float;\n                } else if (output.type === 'as_bool') {\n                    return output.as_bool;\n                } else if (output.type === 'as_none') {\n                    return null;\n                }\n                throw new python.Error(`Unsupported graph node ${output.type}.`);\n            }\n            deserialize_graph(serialized_graph) {\n                for (const [name, tensor_value] of serialized_graph.tensor_values) {\n                    const meta_val = this.deserialize_tensor_meta(tensor_value.meta || tensor_value, this.fake_tensor_mode);\n                    this.serialized_name_to_meta.set(name, meta_val);\n                }\n                for (const [name, sym_int_value] of serialized_graph.sym_int_values) {\n                    this.serialized_name_to_meta.set(name, this.deserialize_sym_int(sym_int_value));\n                }\n                for (const [name, sym_bool_value] of serialized_graph.sym_bool_values) {\n                    this.serialized_name_to_meta.set(name, this.deserialize_sym_bool(sym_bool_value));\n                }\n                for (const [name, script_obj_meta] of serialized_graph.custom_obj_values) {\n                    this.serialized_name_to_meta.set(name, this.deserialize_script_obj_meta(script_obj_meta));\n                }\n                for (let i = 0; i < serialized_graph.inputs.length; i++) {\n                    const input = serialized_graph.inputs[i];\n                    if (input.type === 'as_tensor' || input.type === 'as_sym_int' || input.type === 'as_custom_obj') {\n                        const node_name = input.value.name;\n                        const placeholder_node = this.graph.placeholder(node_name);\n                        placeholder_node.name = node_name;\n                        this.sync_fx_node(node_name, placeholder_node);\n                    } else if (input.type === 'as_int' || input.type === 'as_float' || input.type === 'as_bool' || input.type === 'as_none' || input.type === 'as_string') {\n                        const node_name = this.signature.input_specs[i].arg.name;\n                        const placeholder_node = this.graph.placeholder(node_name);\n                        placeholder_node.meta.set('val', this.deserialize_input(input));\n                    } else {\n                        throw new python.Error(`Invalid input ${input.type}.`);\n                    }\n                }\n                for (const serialized_node of serialized_graph.nodes) {\n                    const target = this.deserialize_operator(serialized_node.target);\n                    this.deserialize_node(serialized_node, target);\n                }\n                let outputs = [];\n                for (const output of serialized_graph.outputs) {\n                    outputs.push(this.deserialize_graph_output(output));\n                }\n                if (serialized_graph.is_single_tensor_return) {\n                    [outputs] = outputs;\n                } else {\n                    outputs = new builtins.tuple(outputs);\n                }\n                const output_node = this.graph.output(outputs);\n                if (serialized_graph.is_single_tensor_return) {\n                    output_node.meta.set('val', output_node.args[0].meta.get('val'));\n                } else {\n                    output_node.meta.set('val', new builtins.tuple(Array.from(output_node.args[0]).map((arg) =>\n                        arg instanceof torch.fx.Node ? arg.meta.get('val') : arg\n                    )));\n                }\n                return self.graph;\n            }\n            deserialize_operator(serialized_target) {\n                let module = null;\n                let serialized_target_names = null;\n                if (serialized_target.startsWith('_operator')) {\n                    module = operator;\n                    serialized_target_names = serialized_target.split('.').slice(1);\n                } else if (serialized_target.startsWith('torch')) {\n                    module = torch;\n                    serialized_target_names = serialized_target.split('.').slice(1);\n                } else if (serialized_target.startsWith('#')) {\n                    return self.deserialize_extension_operator(serialized_target);\n                } else {\n                    return serialized_target;\n                }\n                let target = module;\n                for (const name of serialized_target_names) {\n                    target = builtins.getattr(target, name);\n                    if (!target) {\n                        return serialized_target;\n                    }\n                }\n                return target;\n            }\n            deserialize_node(serialized_node, target) {\n                let fx_node = null;\n                if (torch._export.serde.serialize._SYM_OPS.has(target)) {\n                    const name = serialized_node.outputs[0].value.as_name;\n                    const args = this.deserialize_sym_op_inputs(serialized_node.inputs);\n                    fx_node = this.graph.create_node('call_function', target, args, null, name);\n                    this.deserialize_sym_op_outputs(serialized_node, fx_node);\n                } else if (builtins.isinstance(target, torch._ops.HigherOrderOperator)) {\n                    const [args, kwargs] = this.deserialize_hoo_inputs(serialized_node.inputs);\n                    const metadata = this.deserialize_metadata(serialized_node.metadata);\n                    for (const x of [...args, ...kwargs.values()]) {\n                        if (builtins.isinstance(x, torch.fx.Node) && x.op === 'get_attr') {\n                            x.meta.update(metadata);\n                        }\n                    }\n                    const name = serialized_node.outputs.length === 1 &&\n                        builtins.hasattr(serialized_node.outputs[0], 'as_tensor') &&\n                        builtins.getattr(serialized_node, 'is_hop_single_tensor_return', true) ?\n                        serialized_node.outputs[0].as_tensor.name : null;\n                    fx_node = this.graph.create_node('call_function', target, args, kwargs, name);\n                    this.deserialize_outputs(serialized_node, fx_node);\n                    fx_node.meta.update(metadata);\n                } else if (builtins.isinstance(target, torch._ops.OpOverload)) {\n                    const name = this._is_single_tensor_return(target) ? serialized_node.outputs[0].as_tensor.name : null;\n                    const [args, kwargs] = this.deserialize_inputs(target, serialized_node);\n                    fx_node = this.graph.create_node('call_function', target, args, kwargs, name);\n                    this.deserialize_outputs(serialized_node, fx_node);\n                } else if (typeof target === 'string') {\n                    // Handle unresolved operators\n                    execution.emit('resolve', target);\n                    if (target.match(/^torch\\.ops\\.(aten|prim|quantized)\\./)) {\n                        throw new python.Error(`Unsupported node target type '${target}'.`);\n                    }\n                    const [args, kwargs] = this.deserialize_hoo_inputs(serialized_node.inputs);\n                    const name = serialized_node.outputs.length === 1 && builtins.hasattr(serialized_node.outputs[0], 'as_tensor') ? serialized_node.outputs[0].as_tensor.name : null;\n                    fx_node = this.graph.create_node('call_function', target, args, kwargs, name);\n                    this.deserialize_outputs(serialized_node, fx_node);\n                } else {\n                    throw new python.Error(`Unsupported node target type '${target}'.`);\n                }\n                fx_node.meta.update(this.deserialize_metadata(serialized_node.metadata));\n                if (fx_node.op !== 'placeholder' && fx_node.op !== 'output' && !fx_node.meta.has('nn_module_stack')) {\n                    fx_node.meta.set('nn_module_stack', new builtins.dict());\n                }\n            }\n            deserialize_input_spec(i) {\n                if (i.type === 'user_input') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.USER_INPUT,\n                        this.deserialize_argument_spec(i.user_input.arg),\n                        null);\n                } else if (i.type === 'parameter') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.PARAMETER,\n                        new torch.export.graph_signature.TensorArgument(i.parameter.arg.name),\n                        i.parameter.parameter_name,\n                    );\n                } else if (i.type === 'buffer') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.BUFFER,\n                        new torch.export.graph_signature.TensorArgument(i.buffer.arg.name),\n                        i.buffer.buffer_name,\n                        i.buffer.persistent,\n                    );\n                } else if (i.type === 'tensor_constant') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.CONSTANT_TENSOR,\n                        new torch.export.graph_signature.TensorArgument(i.tensor_constant.arg.name),\n                        i.tensor_constant.tensor_constant_name);\n                } else if (i.type === 'custom_obj') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.CUSTOM_OBJ,\n                        new torch.export.graph_signature.CustomObjArgument(i.custom_obj.arg.name, i.custom_obj.arg.class_fqn),\n                        i.custom_obj.custom_obj_name);\n                } else if (i.type === 'token') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.TOKEN,\n                        new torch.export.graph_signature.TokenArgument(i.token.arg.name),\n                        null);\n                } else if (i.type === 'constant_input') {\n                    return new torch.export.graph_signature.InputSpec(\n                        torch.export.graph_signature.InputKind.USER_INPUT,\n                        new torch.export.graph_signature.ConstantArgument(i.constant_input.name, this.deserialize_constant_input(i.constant_input.value)),\n                        null);\n                }\n                throw new python.Error(`Unknown input spec ${i}`);\n            }\n            deserialize_constant_input(inp) {\n                if (inp.type === 'as_int') {\n                    return inp.as_int;\n                } else if (inp.type === 'as_float') {\n                    return inp.as_float;\n                } else if (inp.type === 'as_string') {\n                    return inp.as_string;\n                } else if (inp.type === 'as_bool') {\n                    return inp.as_bool;\n                } else if (inp.type === 'as_none') {\n                    return null;\n                }\n                throw new python.Error(`Unhandled constant argument ${inp} to deserialize.`);\n            }\n            deserialize_output_spec(o) {\n                if (o.type === 'user_output') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.USER_OUTPUT,\n                        this.deserialize_argument_spec(o.user_output.arg),\n                        null);\n                } else if (o.type === 'loss_output') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.LOSS_OUTPUT,\n                        new torch.export.graph_signature.TensorArgument(o.loss_output.arg.name),\n                        null);\n                } else if (o.type === 'buffer_mutation') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.BUFFER_MUTATION,\n                        new torch.export.graph_signature.TensorArgument(o.buffer_mutation.arg.name),\n                        o.buffer_mutation.buffer_name);\n                } else if (o.type === 'gradient_to_parameter') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.GRADIENT_TO_PARAMETER,\n                        new torch.export.graph_signature.TensorArgument(o.gradient_to_parameter.arg.name),\n                        o.gradient_to_parameter.parameter_name);\n                } else if (o.type === 'gradient_to_user_input') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.GRADIENT_TO_USER_INPUT,\n                        new torch.export.graph_signature.TensorArgument(o.gradient_to_user_input.arg.name),\n                        o.gradient_to_user_input.user_input_name);\n                } else if (o.type === 'user_input_mutation') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.USER_INPUT_MUTATION,\n                        new torch.export.graph_signature.TensorArgument(o.user_input_mutation.arg.name),\n                        o.user_input_mutation.user_input_name);\n                } else if (o.type === 'token') {\n                    return new torch.export.graph_signature.OutputSpec(\n                        torch.export.graph_signature.OutputKind.TOKEN,\n                        new torch.export.graph_signature.TokenArgument(o.token.arg.name),\n                        null);\n                }\n                throw new python.Error(`Unknown output spec ${o}.`);\n            }\n            deserialize_signature(sig) {\n                return new torch.export.graph_signature.ExportGraphSignature(\n                    sig.input_specs.map((i) => this.deserialize_input_spec(i)),\n                    sig.output_specs.map((o) => this.deserialize_output_spec(o)));\n            }\n            deserialize(serialized_graph_module, serialized_state_dict, constants, example_inputs, symbol_name_to_range) {\n                this.shape_env = new torch.fx.experimental.symbolic_shapes.ShapeEnv(/* assume_static_by_default = True */);\n                this.fake_tensor_mode = new torch._subclasses.fake_tensor.FakeTensorMode(false, true, this.shape_env);\n                this.sympy_functions = new Map([\n                    ['FloorDiv', torch.utils._sympy.functions.FloorDiv],\n                    ['ModularIndexing', torch.utils._sympy.functions.ModularIndexing],\n                    ['Where', torch.utils._sympy.functions.Where],\n                    ['PythonMod', torch.utils._sympy.functions.PythonMod],\n                    ['Mod', torch.utils._sympy.functions.Mod],\n                    ['CleanDiv', torch.utils._sympy.functions.CleanDiv],\n                    ['CeilToInt', torch.utils._sympy.functions.CeilToInt],\n                    ['FloorToInt', torch.utils._sympy.functions.FloorToInt],\n                    ['CeilDiv', torch.utils._sympy.functions.CeilDiv],\n                    ['LShift', torch.utils._sympy.functions.LShift],\n                    ['RShift', torch.utils._sympy.functions.RShift],\n                    ['PowByNatural', torch.utils._sympy.functions.PowByNatural],\n                    ['FloatPow', torch.utils._sympy.functions.FloatPow],\n                    ['FloatTrueDiv', torch.utils._sympy.functions.FloatTrueDiv],\n                    ['IntTrueDiv', torch.utils._sympy.functions.IntTrueDiv],\n                    ['IsNonOverlappingAndDenseIndicator', torch.utils._sympy.functions.IsNonOverlappingAndDenseIndicator],\n                    ['TruncToFloat', torch.utils._sympy.functions.TruncToFloat],\n                    ['TruncToInt', torch.utils._sympy.functions.TruncToInt],\n                    ['RoundToInt', torch.utils._sympy.functions.RoundToInt],\n                    ['RoundDecimal', torch.utils._sympy.functions.RoundDecimal],\n                    ['ToFloat', torch.utils._sympy.functions.ToFloat],\n                    ['Identity', torch.utils._sympy.functions.Identity],\n                ]);\n                this.symbol_name_to_symbol = new Map();\n                this.constants = torch._export.serde.serialize.deserialize_torch_artifact(constants);\n                this.signature = this.deserialize_signature(serialized_graph_module.signature);\n                this.symbol_name_to_range = symbol_name_to_range || new Map();\n                /*\n                    if symbol_name_to_range:\n                    for k, vr in symbol_name_to_range.items():\n                        lower = int(vr.lower)\n                        if vr.upper >= 2:  # max is >= 2, not sym bool range\n                            lower = max(2, lower)\n                        this.symbol_name_to_range[k] = symbolic_shapes.ValueRanges(_int_to_sympy_int(lower), vr.upper)\n                    */\n                this.example_inputs = null;\n                if (example_inputs) {\n                    this.example_inputs = torch._export.serde.serialize.deserialize_torch_artifact(example_inputs);\n                }\n                this.deserialize_graph(serialized_graph_module.graph);\n                const module_call_graph = null; // this.deserialize_module_call_graph(serialized_graph_module.module_call_graph)\n                return {\n                    graph_module: torch._export.exported_program._create_graph_module_for_export(this.module, this.graph),\n                    signature: this.signature,\n                    module_call_graph,\n                    names_to_symbols: this.symbol_name_to_symbol,\n                    state_dict: torch._export.serde.serialize.deserialize_torch_artifact(serialized_state_dict),\n                    constants: this.constants,\n                    example_inputs: this.example_inputs,\n                };\n            }\n            sync_fx_node(name, fx_node) {\n                if (this.serialized_name_to_node.has(name)) {\n                    throw new python.Error(`Node ${name} has already been deserialized before.`);\n                }\n                this.serialized_name_to_node.set(name, fx_node);\n                fx_node.meta.set('val', this.serialized_name_to_meta.get(name));\n            }\n            deserialize_sym_op_inputs(inputs) {\n                return inputs.map((input) => this.deserialize_input(input.arg));\n            }\n            deserialize_inputs(target, serialized_node) {\n                const schema_args = this._get_schema_from_target(target).arguments;\n                const actual_args = new Map(serialized_node.inputs.map((input) => [input.name, this.deserialize_input(input.arg)]));\n                const argument_kinds = new Map(serialized_node.inputs.map((input) => [input.name, input.kind]));\n                const args = new builtins.list();\n                const kwargs = new builtins.dict();\n                for (const schema_arg of schema_args) {\n                    const kind = argument_kinds.get(schema_arg.name);\n                    if (kind === 1 /* ArgumentKind.POSITIONAL */) {\n                        args.push(actual_args.get(schema_arg.name));\n                        continue;\n                    } else if (kind === 2 /* ArgumentKind.KEYWORD */ && actual_args.has(schema_arg.name)) {\n                        kwargs.set(schema_arg.name, actual_args.get(schema_arg.name));\n                        continue;\n                    }\n                    const is_positional = !schema_arg.has_default_value() && !schema_arg.kwarg_only;\n                    if (is_positional) {\n                        args.push(actual_args.get(schema_arg.name));\n                    } else if (actual_args.has(schema_arg.name)) {\n                        kwargs.set(schema_arg.name, actual_args.get(schema_arg.name));\n                    }\n                }\n                return [args, kwargs];\n            }\n            deserialize_hoo_inputs(inputs) {\n                const args = [];\n                const kwargs = new builtins.dict();\n                for (const input_ of inputs) {\n                    if (input_.name === '') {\n                        args.push(this.deserialize_input(input_.arg));\n                    } else {\n                        kwargs.set(input_.name, this.deserialize_input(input_.arg));\n                    }\n                }\n                return [new builtins.tuple(args), kwargs];\n            }\n            deserialize_input(inp) {\n                const value = inp.value;\n                const typ_ = inp.type;\n                if (typ_ === 'as_none') {\n                    return null;\n                } else if (typ_ === 'as_tensor') {\n                    return this.serialized_name_to_node.get(inp.as_tensor.name);\n                } else if (typ_ === 'as_scalar_type') {\n                    return torch._export.serde.serialize.deserialize_scalar_type(inp.as_scalar_type);\n                } else if (typ_ === 'as_memory_format') {\n                    return torch._export.serde.serialize._SERIALIZE_TO_TORCH_MEMORY_FORMAT[inp.as_memory_format];\n                } else if (typ_ === 'as_layout') {\n                    return torch._export.serde.serialize._SERIALIZE_TO_TORCH_LAYOUT[inp.as_layout];\n                } else if (typ_ === 'as_graph') {\n                    const context = this.save_graph_module();\n                    context.__enter__();\n                    this.deserialize_graph(value.graph);\n                    const submodule = torch.export.exported_program._create_graph_module_for_export(this.module, this.graph);\n                    context.__exit__(null, null, null);\n                    this.module.register_module(value.name, submodule);\n                    return this.graph.create_node('get_attr', value.name, null, null, value.name);\n                } else if (typ_ === 'as_device') {\n                    return this.deserialize_device(inp.as_device);\n                } else if (typ_ === 'as_int') {\n                    return inp.as_int;\n                } else if (typ_ === 'as_float') {\n                    return inp.as_float;\n                } else if (typ_ === 'as_bool') {\n                    return inp.as_bool;\n                } else if (typ_ === 'as_string') {\n                    return inp.as_string;\n                } else if (typ_ === 'as_sym_int') {\n                    return this.deserialize_sym_argument(inp.as_sym_int);\n                } else if (typ_ === 'as_sym_float') {\n                    return this.deserialize_sym_argument(inp.as_sym_float);\n                } else if (typ_ === 'as_sym_bool') {\n                    return this.deserialize_sym_argument(inp.as_sym_bool);\n                } else if (Array.isArray(value)) {\n                    if (value.length === 0) {\n                        return [];\n                    } else if (typ_ === 'as_tensors') {\n                        const result = [];\n                        for (const arg of value) {\n                            if (!this.serialized_name_to_node.has(arg.name)) {\n                                throw new python.Error(`Unknown tensor '${arg.name}'.`);\n                            }\n                            result.push(this.serialized_name_to_node.get(arg.name));\n                        }\n                        return result;\n                    } else if (typ_ === 'as_ints' || typ_ === 'as_floats' || typ_ === 'as_bools' || typ_ ===  'as_strings') {\n                        return Array.from(value);\n                    } else if (typ_ === 'as_sym_ints' || typ_ === 'as_sym_bools') {\n                        return value.map((arg) => this.deserialize_sym_argument(arg));\n                    } else if (typ_ === 'as_optional_tensors') {\n                        const deserialize_optional_tensor_args = (a) => {\n                            if (a.type === 'as_none') {\n                                return null;\n                            } else if (a.type === 'as_tensor') {\n                                if (!this.serialized_name_to_node.has(a.value.name)) {\n                                    throw new python.Error(`Unknown tensor '${a.value.name}'.`);\n                                }\n                                return this.serialized_name_to_node.get(a.value.name);\n                            }\n                            throw new python.Error(`Unsupported argument '${typ_}'.`);\n                        };\n                        return value.map((item) => deserialize_optional_tensor_args(item));\n                    }\n                    throw new python.Error(`Unsupported argument '${typ_}'.`);\n                } else if (typ_ === 'as_custom_obj') {\n                    if (this.serialized_name_to_node.has(inp.as_custom_obj.name)) {\n                        return this.serialized_name_to_node.get(inp.as_custom_obj.name);\n                    }\n                    return this.constants[inp.as_custom_obj.name];\n                } else if (typ_ === 'as_operator') {\n                    return this.deserialize_operator(inp.as_operator);\n                }\n                throw new python.Error(`Unsupported argument '${typ_}'.`);\n            }\n            deserialize_sym_argument(sym_arg) {\n                if (sym_arg instanceof torch._export.serde.schema.SymIntArgument) {\n                    if (sym_arg.type === 'as_int') {\n                        return sym_arg.as_int;\n                    } else if (sym_arg.type === 'as_name') {\n                        return this.serialized_name_to_node.get(sym_arg.as_name);\n                    }\n                } else if (sym_arg instanceof torch._export.serde.schema.SymFloatArgument) {\n                    if (sym_arg.type === 'as_float') {\n                        return sym_arg.as_float;\n                    } else if (sym_arg.type === 'as_name') {\n                        return this.serialized_name_to_node.get(sym_arg.as_name);\n                    }\n                } else if (sym_arg instanceof torch._export.serde.schema.SymBoolArgument) {\n                    if (sym_arg.type === 'as_bool') {\n                        return sym_arg.as_bool;\n                    } else if (sym_arg.type === 'as_name') {\n                        return this.serialized_name_to_node.get(sym_arg.as_name);\n                    }\n                }\n                throw new python.Error(`Unsupported symbolic argument type '${sym_arg.type}`);\n            }\n            deserialize_sym_op_outputs(serialized_node, fx_node) {\n                this.sync_fx_node(serialized_node.outputs[0].value.as_name, fx_node);\n            }\n            deserialize_outputs(serialized_node, fx_node) {\n                if (serialized_node.outputs.length === 0) {\n                    return;\n                }\n                if (serialized_node.outputs.length === 1 &&\n                    serialized_node.outputs[0].type === 'as_tensor') {\n                    this.sync_fx_node(serialized_node.outputs[0].as_tensor.name, fx_node);\n                    return;\n                } else if (serialized_node.outputs.length === 1 &&\n                     (serialized_node.outputs[0].value instanceof torch._export.serde.schema.SymIntArgument ||\n                      serialized_node.outputs[0].value instanceof torch._export.serde.schema.SymBoolArgument)) {\n                    this.sync_fx_node(serialized_node.outputs[0].value.as_name, fx_node);\n                    return;\n                }\n                this.deserialize_multiple_outputs(serialized_node, fx_node);\n            }\n            deserialize_multiple_outputs(serialized_node, fx_node) {\n                const deserialized_metadata = this.deserialize_metadata(serialized_node.metadata);\n                const generate_getitem = (meta_val, fx_node, arg, idx) => {\n                    let name = '';\n                    if (arg instanceof torch._export.serde.schema.TensorArgument) {\n                        name = arg.name;\n                    } else if (arg instanceof torch._export.serde.schema.SymIntArgument) {\n                        name = arg.as_name;\n                    } else if (arg instanceof torch._export.serde.schema.SymFloatArgument) {\n                        name = arg.as_name;\n                    } else {\n                        throw new python.Error(`Unsupported argument type '${arg}'.`);\n                    }\n                    const individual_output = this.graph.create_node(\n                        'call_function',\n                        operator.getitem,\n                        new builtins.tuple([fx_node, idx]),\n                        null,\n                        name,\n                    );\n                    this.sync_fx_node(name, individual_output);\n                    meta_val.push(this.serialized_name_to_meta.get(name));\n                    individual_output.meta.update(deserialized_metadata);\n                };\n                const generate_getitems = (meta_val, fx_node, args) => {\n                    for (let idx = 0; idx < args.length; idx++) {\n                        const arg = args[idx];\n                        if (arg instanceof torch._export.serde.schema.TensorArgument ||\n                            arg instanceof torch._export.serde.schema.SymIntArgument ||\n                            arg instanceof torch._export.serde.schema.SymFloatArgument) {\n                            generate_getitem(meta_val, fx_node, arg, idx);\n                        } else if (arg instanceof torch._export.serde.schema.Argument) {\n                            if (arg.type === 'as_tensor' || arg.type === 'as_sym_int' || arg.type === 'as_sym_float') {\n                                generate_getitem(meta_val, fx_node, arg.value, idx);\n                            } else if (arg.type === 'as_none') {\n                                const individual_output = this.graph.create_node(\n                                    'call_function',\n                                    operator.getitem,\n                                    new builtins.tuple([fx_node, idx]),\n                                    null,\n                                    'as_none',\n                                );\n                                meta_val.push(null);\n                                individual_output.meta.set('val', null);\n                                individual_output.meta.update(deserialized_metadata);\n                            } else if (Array.isArray(arg.value)) {\n                                const list_output = this.graph.create_node(\n                                    'call_function',\n                                    operator.getitem,\n                                    new builtins.tuple([fx_node, idx]),\n                                );\n                                meta_val.push([]);\n                                generate_getitems(meta_val[meta_val.length - 1], list_output, arg.value);\n                                list_output.meta.update(deserialized_metadata);\n                                list_output.meta.set('val', meta_val[meta_val.length - 1]);\n                            } else {\n                                throw new python.Error(`Unsupported node output type '${arg.type}'.`);\n                            }\n                        } else if (Array.isArray(arg)) {\n                            const list_output = this.graph.create_node(\n                                'call_function',\n                                operator.getitem,\n                                new builtins.tuple([fx_node, idx]),\n                            );\n                            meta_val.push([]);\n                            generate_getitems(meta_val[meta_val.length - 1], list_output, arg);\n                            list_output.meta.update(deserialized_metadata);\n                            list_output.meta.set('val', meta_val[meta_val.length - 1]);\n                        } else {\n                            throw new python.Error(`Unsupported node output type '${arg}'.`);\n                        }\n                    }\n                };\n                const meta_val = [];\n                if (serialized_node.outputs.length === 1) {\n                    generate_getitems(meta_val, fx_node, serialized_node.outputs[0].value);\n                } else {\n                    generate_getitems(meta_val, fx_node, serialized_node.outputs);\n                }\n                fx_node.meta.set('val', new builtins.tuple(meta_val));\n                this.serialized_name_to_node.set(fx_node.name, fx_node);\n            }\n            deserialize_metadata(metadata) {\n                const ret = new builtins.dict();\n                const stack_trace = metadata.get('stack_trace');\n                if (stack_trace) {\n                    ret.set('stack_trace', stack_trace);\n                }\n                const deserialize_meta_func = (serialized_target) => {\n                    let module = null;\n                    let serialized_target_names = [];\n                    if (serialized_target.startsWith('torch.nn')) {\n                        module = torch.nn;\n                        serialized_target_names = serialized_target.split('.').slice(1);\n                    } else if (serialized_target.startsWith('torch')) {\n                        module = torch;\n                        serialized_target_names = serialized_target.split('.').slice(1);\n                    } else {\n                        return this.deserialize_operator(serialized_target);\n                    }\n                    let target = module;\n                    for (const name of serialized_target_names) {\n                        if (!builtins.hasattr(target, name)) {\n                            return serialized_target;\n                        }\n                        target = builtins.getattr(target, name);\n                    }\n                    return target;\n                };\n                const nn_module_stack_str = metadata.get('nn_module_stack');\n                if (nn_module_stack_str) {\n                    const import_nn_module_stack = (key, path, ty) => {\n                        return [key, [path, ty]];\n                    };\n                    const nn_module_stack = new Map(nn_module_stack_str.split(';').map((item) => import_nn_module_stack(...item.split(','))));\n                    ret.set('nn_module_stack', nn_module_stack);\n                }\n                const source_fn_st_str = metadata.get('source_fn_stack');\n                if (source_fn_st_str) {\n                    const source_fn_st = [];\n                    for (const source_fn_str of source_fn_st_str.split(';')) {\n                        const [name, target_str] = source_fn_str.split(',');\n                        source_fn_st.push([name, deserialize_meta_func(target_str)]);\n                    }\n                    ret.set('source_fn_stack', source_fn_st);\n                }\n                const torch_fn = metadata.get('torch_fn');\n                if (torch_fn) {\n                    ret.set('torch_fn', new builtins.tuple(torch_fn.split(';')));\n                }\n                const custom_str = metadata.get('custom');\n                if (custom_str) {\n                    ret.set('custom', JSON.parse(custom_str));\n                }\n                return ret;\n            }\n            deserialize_argument_spec(x) {\n                if (x.type === 'as_tensor') {\n                    return new torch.export.graph_signature.TensorArgument(x.as_tensor.name);\n                } else if (x.type === 'as_sym_int') {\n                    return new torch.export.graph_signature.SymIntArgument(x.as_sym_int.as_name);\n                } else if (x.type === 'as_custom_obj') {\n                    return new torch.export.graph_signature.ConstantArgument(x.as_custom_obj.name, this.deserialize_input(x));\n                }\n                return new torch.export.graph_signature.ConstantArgument('', this.deserialize_input(x));\n            }\n            deserialize_tensor_meta(tensor_meta) {\n                try {\n                    this.fake_tensor_mode.__enter__();\n                    const sizes = tensor_meta.sizes.map((val) => this.deserialize_sym_int(val));\n                    const strides = tensor_meta.strides.map((val) => this.deserialize_sym_int(val));\n                    const device = this.deserialize_device(tensor_meta.device);\n                    const dtype = torch._export.serde.serialize.deserialize_scalar_type(tensor_meta.dtype);\n                    return torch.empty_strided(sizes, strides, dtype, null, device);\n                } finally {\n                    this.fake_tensor_mode.__exit__(null, null, null);\n                }\n            }\n            deserialize_script_obj_meta(script_obj_meta) {\n                return new torch.export.graph_signature.CustomObjArgument(script_obj_meta.name, script_obj_meta.class_fqn);\n            }\n            _parse_sym_expr(expr_str, hint) {\n                const _process_sym_expr = (sym, hint) => {\n                    if (sym.is_Integer || sym.is_Float || sym.is_Boolean) {\n                        return sym;\n                    }\n                    expr_str = sym.__str__();\n                    for (const arg of sym.args) {\n                        this._parse_sym_expr(arg);\n                    }\n                    if (this.symbol_name_to_symbol.has(expr_str)) {\n                        sym = this.symbol_name_to_symbol.get(expr_str);\n                    } else {\n                        this.symbol_name_to_symbol.set(expr_str, sym);\n                        if (builtins.isinstance(sym, sympy.core.symbol.Symbol) && torch.fx.experimental.symbolic_shapes.symbol_is_type(sym, [torch.utils._sympy.symbol.SymT.UNBACKED_INT, torch.utils._sympy.symbol.SymT.UNBACKED_FLOAT])) {\n                            this.unbacked_symbols.add(sym);\n                        }\n                    }\n                    if (hint !== null && !this.shape_env.var_to_val.has(sym)) {\n                        this.shape_env.add_var_to_val(sym, hint);\n                    }\n                    const vr = this.symbol_name_to_range.get(expr_str);\n                    if (vr) {\n                        this.shape_env.constrain_symbol_range(sym, vr.lower, vr.upper);\n                    }\n                    if (builtins.isinstance(sym, sympy.core.symbol.Symbol)) {\n                        this.shape_env.var_to_stack.set(sym, torch.utils._traceback.CapturedTraceback.extract(false, false, 1));\n                    }\n                    return sym;\n                };\n                const locals = new Map([...this.sympy_functions, ...this.symbol_name_to_symbol]);\n                const expr = sympy.core.sympify.sympify(expr_str, locals);\n                return _process_sym_expr(expr, hint);\n            }\n            deserialize_sym_int(s) {\n                const val = s.value;\n                let hint = null;\n                if (s.type === 'as_expr') {\n                    if (val.hint === null) {\n                        hint = null;\n                    } else {\n                        // assert val.hint.type == \"as_int\"\n                        hint = val.hint.value;\n                    }\n                    const sym = this._parse_sym_expr(val.expr_str, hint);\n                    return this.shape_env.create_symintnode(sym, hint);\n                } else if (s.type === 'as_int') {\n                    // assert type(val) is int\n                    return val;\n                }\n                throw new python.Error(`SymInt has invalid field type ${s.type} with value ${s.value}.`);\n            }\n            deserialize_sym_bool(s) {\n                const val = s.value;\n                let hint = null;\n                if (s.type === 'as_expr') {\n                    if (val.hint === null) {\n                        hint = null;\n                    } else {\n                        // assert val.hint.type == \"as_bool\"\n                        hint = val.hint.value;\n                    }\n                    const sym = this._parse_sym_expr(val.expr_str, hint);\n                    return this.shape_env.create_symboolnode(sym, hint);\n                } else if (s.type === 'as_bool') {\n                    // assert type(val) is bool\n                    return val;\n                }\n                throw new python.Error(`SymBool has invalid field type ${s.type} with value ${s.value}.`);\n            }\n            deserialize_device(d) {\n                if (d.index === null) {\n                    return new torch.device(d.type);\n                }\n                return new torch.device(d.type, d.index);\n            }\n            _get_schema_from_target(target) {\n                if (target instanceof torch._ops.OpOverload) {\n                    return target._schema;\n                }\n                throw new python.Error(`Unsupported schema '${target.name}'.`);\n            }\n            _is_single_tensor_return(target) {\n                const schema = this._get_schema_from_target(target);\n                const returns = schema.returns;\n                return returns.length === 1 && returns[0].real_type instanceof torch.TensorType;\n            }\n        });\n        this.registerType('torch._export.verifier.Verifier', class {});\n        this.registerType('torch._dynamo.convert_frame.CatchErrorsWrapper', class {});\n        this.registerType('torch._dynamo.convert_frame.ConvertFrameAssert', class {});\n        this.registerType('torch._dynamo.convert_frame.ConvertFrame', class {});\n        this.registerType('torch._dynamo.convert_frame.ConvertFrameBox', class {});\n        this.registerType('torch._dynamo.eval_frame._TorchDynamoContext', class {});\n        this.registerType('torch._dynamo.eval_frame.OptimizedModule', class extends torch.nn.modules.module.Module {\n            constructor(mod, dynamo_ctx) {\n                builtins.object.__setattr__(self, '_orig_mod', mod);\n                // this._super_module_initialized = false;\n                super();\n                // this._super_module_initialized = true;\n                this._orig_mod = mod;\n                this.dynamo_ctx = dynamo_ctx;\n                // this._initialize();\n                this.training = this._orig_mod.training;\n            }\n        });\n        this.registerType('torch._dynamo.eval_frame.OptimizeContext', class extends torch._dynamo.eval_frame._TorchDynamoContext {});\n        this.registerType('torch._dynamo.hooks.Hooks', class {});\n        this.registerType('torch._dynamo.output_graph.GraphCompileReason', class {});\n        this.registerType('torch._dynamo.repro.after_dynamo.WrapBackendDebug', class {});\n        this.registerType('torch._TorchCompileInductorWrapper', class {});\n        this.registerFunction('torch._inductor.compile_fx.compile_fx');\n        this.registerFunction('torch_utils.persistence._reconstruct_persistent_obj', (meta) => {\n            const name = `_imported_module_${Math.floor(Math.random() * 10000)}`;\n            const module = new types.ModuleType(name);\n            execution.register('sys').modules.set(name, module);\n            const context = new python.Execution.Context(module, null);\n            execution.exec(meta.get('module_src'), context);\n            const obj = execution.invoke(`${name}.${meta.get('class_name')}`, []);\n            const state = meta.get('state');\n            if (state) {\n                if (obj.__setstate__) {\n                    obj.__setstate__(state);\n                } else {\n                    for (const [key, value] of state) {\n                        obj[key] = value;\n                    }\n                }\n            }\n            return obj;\n        });\n        this.registerFunction('torch_utils.misc.assert_shape', (/* tensor, ref_shape */) => {});\n        this.registerFunction('torch_utils.ops.conv2d_resample.conv2d_resample', (/* x, w, f, up, down, padding, groups, flip_weight, flip_filter */) => {});\n        this.registerFunction('torch_utils.ops.upfirdn2d.setup_filter', (/* x, f, up, down, padding, flip_filter, gain, impl */) => {});\n        this.registerFunction('torch_utils.ops.bias_act', (/* x, b, dim, act, alpha, gain, clamp, impl */) => {});\n        this.registerFunction('torch_utils.ops.fma.fma', (/* a, b, c */) => {});\n        this.registerType('torch.device', class {\n            constructor(type, index) {\n                this.type = type;\n                this.index = index ? index : null;\n            }\n            __str__() {\n                return this.index === null ? this.type : `${this.type}:${this.index}`;\n            }\n            toString() {\n                const index = this.index === null ? '' : `, index=${this.index}`;\n                return `device(type='${this.type}'${index})`;\n            }\n        });\n        this.registerType('torch.memory_format', class {\n            constructor(name) {\n                this.name = name;\n            }\n            __str__() {\n                return `torch.${this.name}`;\n            }\n            toString() {\n                return this.__str__();\n            }\n        });\n        this.registerType('torch.dtype', class {\n            constructor(scalar_type, name, itemsize) {\n                this._scalar_type = scalar_type;\n                this._name = name;\n                this._itemsize = itemsize;\n            }\n            scalar_type() {\n                return this._scalar_type;\n            }\n            itemsize() {\n                return this._itemsize;\n            }\n            __reduce__() {\n                return this._name;\n            }\n            __str__() {\n                return `torch.${this._name}`;\n            }\n            toString() {\n                return this.__str__();\n            }\n        });\n        this.registerType('torch.layout', class {\n            constructor(name) {\n                this._name = name;\n            }\n            __str__() {\n                return `torch.${this._name}`;\n            }\n            toString() {\n                return this.__str__();\n            }\n        });\n        this.registerType('torch.qscheme', class {\n            constructor(name) {\n                this._name = name;\n            }\n            __str__() {\n                return this._name;\n            }\n            toString() {\n                return this.__str__();\n            }\n        });\n        this.registerType('torch.utils.hooks.RemovableHandle', class {\n            __setstate__(state) {\n                [this.hooks_dict_ref, this.id] = state;\n                this.hooks_dict_ref = this.hooks_dict_ref || new Map();\n            }\n        });\n        this.registerType('torch.utils.tensorboard.writer.SummaryWriter', class {});\n        this.registerType('torch.storage._StorageBase', class {\n            constructor(size, dtype) {\n                this._size = size;\n                this._dtype = dtype;\n                this._device = null;\n            }\n            get device() {\n                return this._device;\n            }\n            get dtype() {\n                return this._dtype;\n            }\n            element_size() {\n                return this._dtype.element_size;\n            }\n            size() {\n                return this._size;\n            }\n            get data() {\n                return this._cdata;\n            }\n            _set_cdata(data) {\n                const length = this.size() * this.dtype.itemsize();\n                if (length !== data.length) {\n                    throw new python.Error('Typed storage data size mismatch.');\n                }\n                this._cdata = data;\n            }\n            _set_from_file(unpickler) {\n                const buffer = unpickler.read(8);\n                const size = buffer.reverse().reduce((a, b) => (a * 256) + b, 0);\n                if (size !== this.size()) {\n                    throw new python.Error('Typed storage size mismatch.');\n                }\n                const itemsize = this.dtype.itemsize();\n                const data = unpickler.stream(itemsize * size);\n                this._set_cdata(data);\n            }\n            static _new_with_file(unpickler) {\n                const buffer = unpickler.read(8);\n                const size = buffer.reverse().reduce((a, b) => (a * 256) + b, 0);\n                const storage = new this(size);\n                const itemsize = storage.dtype.itemsize();\n                const data = unpickler.stream(itemsize * size);\n                storage._set_cdata(data);\n                return storage;\n            }\n        });\n        this.registerType('torch.storage.UntypedStorage', class {\n            constructor(size) {\n                this._size = size;\n            }\n            size() {\n                return this._size;\n            }\n            get data() {\n                return this._cdata;\n            }\n            _set_cdata(data) {\n                if (this._size !== data.length) {\n                    throw new python.Error('Untyped storage data size mismatch.');\n                }\n                this._cdata = data;\n            }\n        });\n        this.registerType('torch.storage.TypedStorage', class {\n            constructor(...args) {\n                if (args.length === 0) {\n                    this._size = 0;\n                } else if (args.length === 1 && Number.isInteger(args[0])) {\n                    [this._size] = args;\n                } else if (args.length >= 2 && Number.isInteger(args[0]) && args[1] instanceof torch.dtype) {\n                    if (args[3] instanceof torch.device) {\n                        [this._size, this.dtype, , this._device] = args;\n                    } else {\n                        [this._size, this.dtype] = args;\n                    }\n                } else {\n                    throw new python.Error(`Unsupported TypedStorage arguments '${JSON.stringify(args)}'.`);\n                }\n            }\n            get device() {\n                return this._device;\n            }\n            get dtype() {\n                return this._dtype;\n            }\n            set dtype(value) {\n                this._dtype = value;\n            }\n            element_size() {\n                return this._dtype.element_size;\n            }\n            size() {\n                return this._size;\n            }\n            get data() {\n                return this._cdata;\n            }\n            _set_cdata(data) {\n                const length = this.size() * this.dtype.itemsize();\n                if (length !== data.length) {\n                    throw new python.Error('Storage data size mismatch.');\n                }\n                this._cdata = data;\n            }\n            _set_from_file(unpickler) {\n                const buffer = unpickler.read(8);\n                const size = buffer.reverse().reduce((a, b) => (a * 256) + b, 0);\n                if (size !== this.size()) {\n                    throw new python.Error('Storage size mismatch.');\n                }\n                const itemsize = this.dtype.itemsize();\n                const data = unpickler.stream(itemsize * size);\n                this._set_cdata(data);\n            }\n            static _new_with_file(unpickler) {\n                const buffer = unpickler.read(8);\n                const size = buffer.reverse().reduce((a, b) => (a * 256) + b, 0);\n                const storage = new this(size);\n                const itemsize = storage.dtype.itemsize();\n                const data = unpickler.stream(itemsize * size);\n                storage._set_cdata(data);\n                return storage;\n            }\n        });\n        this.registerType('torch.storage._LegacyStorage', class extends torch.storage.TypedStorage {\n        });\n        this.registerType('torch.BoolStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.BoolStorage.dtype);\n            }\n        });\n        this.registerType('torch.ByteStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.ByteStorage.dtype);\n            }\n        });\n        this.registerType('torch.CharStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.CharStorage.dtype);\n            }\n        });\n        this.registerType('torch.ShortStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.ShortStorage.dtype);\n            }\n        });\n        this.registerType('torch.IntStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.IntStorage.dtype);\n            }\n        });\n        this.registerType('torch.LongStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.LongStorage.dtype);\n            }\n        });\n        this.registerType('torch.HalfStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.HalfStorage.dtype);\n            }\n        });\n        this.registerType('torch.FloatStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.FloatStorage.dtype);\n            }\n        });\n        this.registerType('torch.DoubleStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.DoubleStorage.dtype);\n            }\n        });\n        this.registerType('torch.ComplexHalfStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.ComplexHalfStorage.dtype);\n            }\n        });\n        this.registerType('torch.ComplexFloatStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.ComplexFloatStorage.dtype);\n            }\n        });\n        this.registerType('torch.ComplexDoubleStorage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.ComplexDoubleStorage.dtype);\n            }\n        });\n        this.registerType('torch.QInt8Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.QUInt8Storage.dtype);\n            }\n        });\n        this.registerType('torch.QUInt8Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.QUInt8Storage.dtype);\n            }\n        });\n        this.registerType('torch.QInt32Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.QInt32Storage.dtype);\n            }\n        });\n        this.registerType('torch.BFloat16Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.BFloat16Storage.dtype);\n            }\n        });\n        this.registerType('torch.QUInt4x2Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.QUInt4x2Storage.dtype);\n            }\n        });\n        this.registerType('torch.QUInt2x4Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.QUInt2x4Storage.dtype);\n            }\n        });\n        this.registerType('torch.UInt16Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.UInt16Storage.dtype);\n            }\n        });\n        this.registerType('torch.UInt32Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.UInt32Storage.dtype);\n            }\n        });\n        this.registerType('torch.UInt64Storage', class extends torch.storage._LegacyStorage {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.storage.TypedStorage(args.length > 0 ? args[0] : 0, torch.UInt64Storage.dtype);\n            }\n        });\n        this.registerType('torch.Size', class extends Array {\n            constructor(size) {\n                super(size.length);\n                for (let i = 0; i < size.length; i++) {\n                    this[i] = size[i];\n                }\n            }\n            __len__() {\n                return this.length;\n            }\n        });\n        this.registerType('torch._C.TensorMeta', class {\n        });\n        this.registerType('torch._C.TensorBase', class extends torch._C.TensorMeta {\n        });\n        this.registerType('torch.Tensor', class extends torch._C.TensorBase {\n            constructor(storage, shape, dtype, layout, device, requires_grad) {\n                super();\n                if (storage) {\n                    this._storage = storage;\n                }\n                if (shape !== null && shape !== undefined) {\n                    this._shape = shape;\n                }\n                if (dtype) {\n                    this._dtype = dtype;\n                }\n                this._layout = layout || torch.strided;\n                if (device) {\n                    this._device = device;\n                }\n                if (requires_grad !== undefined) {\n                    this.requires_grad = requires_grad;\n                }\n            }\n            clone() {\n                const tensor = new torch.Tensor(this._storage, this._shape, this._dtype, this._layout, this._device, this.requires_grad);\n                tensor._storage_offset = this._storage_offset;\n                tensor._stride = this._stride;\n                tensor._values = this._values;\n                tensor._indices = this._indices;\n                tensor.__quantized__ = this.__quantized__;\n                tensor.__nested__ = this.__nested__;\n                tensor.data = this.data;\n                tensor._backward_hooks = this._backward_hooks;\n                return tensor;\n            }\n            get device() {\n                if (this._device !== undefined) {\n                    return this._device;\n                }\n                return this.storage().device;\n            }\n            get dtype() {\n                if (this._dtype !== undefined) {\n                    return this._dtype;\n                }\n                if (this._layout === torch.sparse_coo) {\n                    return this._values.dtype;\n                }\n                return this.storage().dtype;\n            }\n            get shape() {\n                return this._shape;\n            }\n            get layout() {\n                return this._layout;\n            }\n            get values() {\n                if (this._layout === torch.sparse_coo) {\n                    return this._values;\n                }\n                throw new python.Error(`Unsupported values in layout'${this._layout.__str__()}'.`);\n            }\n            get indices() {\n                if (this._layout === torch.sparse_coo) {\n                    return this._indices;\n                }\n                throw new python.Error(`Unsupported indices in layout'${this._indices.__str__()}'.`);\n            }\n            get is_quantized() {\n                return this.__quantized__ === true;\n            }\n            get is_nested() {\n                return this.__nested__ === true;\n            }\n            get is_sparse() {\n                return this.layout !== torch.strided;\n            }\n            size() {\n                return this._shape;\n            }\n            storage() {\n                return this._storage;\n            }\n            storage_offset() {\n                return this._storage_offset;\n            }\n            stride() {\n                return this._stride;\n            }\n            resize_(shape) {\n                this._shape = shape;\n            }\n            __len__() {\n                return this._shape[0];\n            }\n            __setstate__(state) {\n                switch (state.length) {\n                    case 3:\n                        break;\n                    case 4:\n                        [this._storage, this._storage_offset, this._shape, this._stride] = state;\n                        break;\n                    case 5:\n                        [this.data, ,this._backward_hooks, this.requires_grad] = state;\n                        break;\n                    default:\n                        throw new python.Error(`Unsupported tensor state length '${state.length}'.`);\n                }\n            }\n            set_(source, storage_offset, size, stride) {\n                this._storage = source;\n                this._storage_offset = storage_offset;\n                this._shape = size;\n                this._stride = stride;\n            }\n            __bool__() {\n                return true;\n            }\n            __int__() {\n                const storage = this.storage();\n                if (storage && storage.dtype.__reduce__() === 'int64' && storage.data.length === 8) {\n                    const buffer = storage.data.peek ? storage.data.peek() : storage.data;\n                    const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n                    return view.getBigInt64(0, true);\n                }\n                return NaN;\n            }\n            __float__() {\n                const storage = this.storage();\n                if (storage && storage.dtype.__reduce__() === 'float32') {\n                    if (storage.size() !== undefined && storage.data.length === 4) {\n                        const buffer = storage.data.peek ? storage.data.peek() : storage.data;\n                        const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n                        return view.getFloat32(0, true);\n                    }\n                }\n                return NaN;\n            }\n            tolist() {\n                const storage = this.storage();\n                const dtype = storage.dtype.__reduce__();\n                const itemsize = storage.dtype.itemsize();\n                const offset = (this._storage_offset || 0) * itemsize;\n                const data = storage.data.peek ? storage.data.peek() : storage.data;\n                const view = new DataView(data.buffer, data.byteOffset + offset, data.byteLength - offset);\n                const size = this._shape.reduce((a, b) => a * b, 1);\n                const list = new Array(size);\n                switch (dtype) {\n                    case 'int16':\n                        for (let i = 0; i < size; i++) {\n                            list[i] = view.getInt16(i * 2, true);\n                        }\n                        return list;\n                    case 'int64':\n                        for (let i = 0; i < size; i++) {\n                            list[i] = view.getInt32(i * 8, true);\n                            if (view.getUint32(i * 8 + 4, true) !== 0) {\n                                throw new python.Error('Signed 64-bit value exceeds 32-bit range.');\n                            }\n                        }\n                        return list;\n                    default:\n                        throw new python.Error(`Unsupported tolist dtype '${dtype}'.`);\n                }\n            }\n            __str__() {\n                return 'tensor(...)';\n            }\n            static _make_wrapper_subclass(cls, size, stride, dtype, storage_offset, layout, device, requires_grad) {\n                const t = new torch.Tensor(null, size, dtype, layout, device, requires_grad);\n                t.__setstate__([null, storage_offset, size, stride]);\n                return t;\n            }\n        });\n        this.registerType('torch.nn.parameter.Parameter', class extends torch.Tensor {\n            constructor(data, requires_grad) {\n                super();\n                this.data = data || new torch.Tensor([]);\n                this.requires_grad = requires_grad === undefined ? true : requires_grad;\n            }\n        });\n        this.registerType('torch._subclasses.fake_tensor.FakeTensor', class extends torch.Tensor {\n        });\n        this.registerType('torch._subclasses.fake_tensor.FakeTensorMode', class extends torch.utils._python_dispatch.TorchDispatchMode {\n            constructor(allow_fallback_kernels, allow_non_fake_inputs, shape_env) {\n                super();\n                this.allow_fallback_kernels = allow_fallback_kernels;\n                this.allow_non_fake_inputs = allow_non_fake_inputs;\n                this.shape_env = shape_env;\n                this.enter_stack = [];\n                this._mode_key = 0; // torch._C._TorchDispatchModeKey.FAKE\n            }\n            __enter__() {\n                const prev_only_lift_cpu_tensors = null;\n                const maybe_prev_fake_mode = torch._C._unset_dispatch_mode(this._mode_key);\n                if (this === maybe_prev_fake_mode) {\n                    torch._C._set_dispatch_mode(this);\n                    this.enter_stack.push([false, null, prev_only_lift_cpu_tensors]);\n                } else {\n                    this.enter_stack.push([true, maybe_prev_fake_mode, prev_only_lift_cpu_tensors]);\n                    return super.__enter__();\n                }\n                return this;\n            }\n            __exit__(exc_type, exc_value, traceback) {\n                const [live, maybe_prev_fake_mode, maybe_prev_only_lift_cpu_tensors] = this.enter_stack.pop();\n                if (live) {\n                    super.__exit__(exc_type, exc_value, traceback);\n                    if (maybe_prev_fake_mode !== null) {\n                        torch._C._set_dispatch_mode(maybe_prev_fake_mode);\n                    }\n                    if (maybe_prev_only_lift_cpu_tensors !== null) {\n                        torch._C._set_only_lift_cpu_tensors(maybe_prev_only_lift_cpu_tensors);\n                    }\n                    torch._C._set_dispatch_mode(maybe_prev_fake_mode);\n                }\n            }\n        });\n        this.registerType('torch.nn.parameter.UninitializedParameter', class extends torch.nn.parameter.Parameter {\n            constructor(requires_grad /*, device, dtype */) {\n                super(undefined, requires_grad);\n            }\n        });\n        this.registerType('torch.nn.parameter.UninitializedBuffer', class extends torch.Tensor {});\n        this.registerType('torch.BoolTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.ByteTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.CharTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.ShortTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.IntTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.LongTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.HalfTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.FloatTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.DoubleTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.ComplexFloatTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.ComplexDoubleTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.QInt8Tensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.QUInt8Tensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.QInt32Tensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.BFloat16Tensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.cuda._CudaLegacyStorage', class extends torch.storage._LegacyStorage {});\n        this.registerType('torch.cuda.FloatStorage', class extends torch.cuda._CudaLegacyStorage {});\n        this.registerType('torch.cuda.FloatTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.cuda.DoubleStorage', class extends torch.cuda._CudaLegacyStorage {});\n        this.registerType('torch.cuda.DoubleTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torch.cuda.amp.grad_scaler.GradScaler', class {});\n        this.registerType('torchao.utils.TorchAOBaseTensor', class extends torch.Tensor {\n            constructor(...args) {\n                // eslint-disable-next-line no-constructor-return\n                return new torch.Tensor(...args);\n            }\n        });\n        this.registerType('torchao.dtypes.affine_quantized_tensor.AffineQuantizedTensor', class extends torchao.utils.TorchAOBaseTensor {});\n        this.registerType('torchao.dtypes.utils.Layout', class {});\n        this.registerType('torchao.dtypes.uintx.plain_layout.PlainAQTTensorImpl', class {});\n        this.registerType('torchao.dtypes.floatx.float8_layout.Float8Layout', class extends torchao.dtypes.utils.Layout {});\n        this.registerType('torchao.dtypes.utils.AQTTensorImpl', class extends torchao.utils.TorchAOBaseTensor {});\n        this.registerType('torchao.dtypes.utils.PlainLayout', class extends torchao.dtypes.utils.Layout {});\n        this.registerType('torchao.dtypes.floatx.float8_layout.Float8AQTTensorImpl', class extends torchao.dtypes.utils.AQTTensorImpl {});\n        this.registerType('torchao.quantization.linear_activation_quantized_tensor.LinearActivationQuantizedTensor', class extends torchao.utils.TorchAOBaseTensor {});\n        this.registerType('torchao.quantization.quant_api._int8_asymm_per_token_quant', class {});\n        this.registerFunction('torchao.quantization.quant_api._int8_symm_per_token_reduced_range_quant');\n        this.registerType('torchao.quantization.quant_primitives.ZeroPointDomain', class extends this.enum.Enum {});\n        this.registerType('torchao.prototype.mx_formats.mx_tensor.MXTensor', class extends torchao.utils.TorchAOBaseTensor {});\n        torchao.prototype.mx_formats.mx_tensor.MXTensor.tensor_attribute_names = ['_elem_dtype', 'block_size'];\n        torchao.prototype.mx_formats.mx_tensor.MXTensor.tensor_data_names = ['qdata', 'scale'];\n        this.registerType('torchao.prototype.mx_formats.mx_tensor.QuantizeTensorToMXKwargs', class {});\n        this.registerType('torchao.prototype.mx_formats.config.ScaleCalculationMode', class extends this.enum.Enum {});\n        this.registerType('torchao.quantization.Float8Tensor', class extends torchao.utils.TorchAOBaseTensor {});\n        this.registerType('torchao.quantization.granularity.PerTensor', class {});\n        this.registerType('torchao.quantization.IntxUnpackedToInt8Tensor', class extends torchao.utils.TorchAOBaseTensor {});\n        this.registerType('torchao.quantization.quantize_.common.kernel_preference.KernelPreference', class extends this.enum.Enum {});\n        this.registerType('torchao.float8.inference.Float8MMConfig', class {});\n        this.registerFunction('torch.cuda.amp.grad_scaler._refresh_per_optimizer_state');\n        this.registerType('torch.SymBool', class {\n            constructor(node) {\n                this.node = node;\n            }\n        });\n        this.registerType('torch.SymInt', class {\n            constructor(node) {\n                this.node = node;\n            }\n            toString() {\n                return this.node.__str__();\n            }\n        });\n        this.register('torch.nn').Module = this.register('torch.nn.modules.module').Module;\n        this.register('torch.optim').Adam = this.register('torch.optim.adam').Adam;\n        this.register('torch.nn').ReLU = this.register('torch.nn.modules.activation').ReLU;\n        this.register('sklearn.utils').Bunch = this.register('sklearn.utils._bunch').Bunch;\n        /* eslint-disable no-multi-assign */\n        // https://github.com/pytorch/pytorch/blob/main/c10/core/ScalarType.h\n        torch.uint8 = torch.ByteStorage.dtype = new torch.dtype(0, 'uint8', 1);\n        torch.int8 = torch.CharStorage.dtype = new torch.dtype(1, 'int8', 1);\n        torch.int16 = torch.ShortStorage.dtype = new torch.dtype(2, 'int16', 2);\n        torch.int32 = torch.IntStorage.dtype = new torch.dtype(3, 'int32', 4);\n        torch.int64 = torch.LongStorage.dtype = new torch.dtype(4, 'int64', 8);\n        torch.float16 = torch.HalfStorage.dtype = new torch.dtype(5, 'float16', 2);\n        torch.float32 = torch.FloatStorage.dtype = new torch.dtype(6, 'float32', 4);\n        torch.float64 = torch.DoubleStorage.dtype = new torch.dtype(7, 'float64', 8);\n        torch.complex32 = torch.ComplexHalfStorage.dtype = new torch.dtype(8, 'complex<float16>', 4);\n        torch.complex64 = torch.ComplexFloatStorage.dtype = new torch.dtype(9, 'complex<float32>', 8);\n        torch.complex128 = torch.ComplexDoubleStorage.dtype = new torch.dtype(10, 'complex<float64>', 16);\n        torch.bool = torch.BoolStorage.dtype = new torch.dtype(11, 'boolean', 1);\n        torch.qint8 = torch.QInt8Storage.dtype = new torch.dtype(12, 'qint8', 1);\n        torch.quint8 = torch.QUInt8Storage.dtype = new torch.dtype(13, 'quint8', 1);\n        torch.qint32 = torch.QInt32Storage.dtype = new torch.dtype(14, 'qint32', 4);\n        torch.bfloat16 = torch.BFloat16Storage.dtype = new torch.dtype(15, 'bfloat16', 2);\n        torch.quint4x2 = torch.QUInt4x2Storage.dtype = new torch.dtype(16, 'quint4x2', 1);\n        torch.quint2x4 = torch.QUInt2x4Storage.dtype = new torch.dtype(17, 'quint2x4');\n        torch.bits1x8 = new torch.dtype(18, 'bits1x8');\n        torch.bits2x4 = new torch.dtype(19, 'bits2x4');\n        torch.bits4x2 = new torch.dtype(20, 'bits4x2');\n        torch.bits8 = new torch.dtype(21, 'bits8');\n        torch.bits16 = new torch.dtype(22, 'bits16');\n        torch.float8_e5m2 = new torch.dtype(23, 'float8_e5m2', 1);\n        torch.float8_e5m2fnuz = new torch.dtype(24, 'float8_e5m2fnuz', 1);\n        torch.float8_e4m3fn = new torch.dtype(25, 'float8_e4m3fn', 1);\n        torch.float8_e4m3fnuz = new torch.dtype(26, 'float8_e4m3fnuz', 1);\n        torch.float8_e8m0fnu = new torch.dtype(44, 'float8_e8m0fnu', 1);\n        torch.float4_e2m1fn_x2 = new torch.dtype(45, 'float4_e2m1fn_x2', 1);\n        torch.int1 = new torch.dtype(37, 'int1');\n        torch.int2 = new torch.dtype(38, 'int2');\n        torch.int3 = new torch.dtype(39, 'int3');\n        torch.int4 = new torch.dtype(40, 'int4');\n        torch.uint16 = torch.UInt16Storage.dtype = new torch.dtype(27, 'uint16', 2);\n        torch.uint32 = torch.UInt32Storage.dtype = new torch.dtype(28, 'uint32', 4);\n        torch.uint64 = torch.UInt64Storage.dtype = new torch.dtype(29, 'uint64', 8);\n        torch._export.serde.serialize._SERIALIZE_TO_TORCH_DTYPE = new Map([\n            ['uint8', 'BYTE'],\n            ['int8', 'CHAR'], ['int16', 'SHORT'], ['int32', 'INT'], ['int64', 'LONG'],\n            ['float16', 'HALF'], ['float32', 'FLOAT'], ['float64', 'DOUBLE'],\n            ['complex32', 'COMPLEXHALF'], ['complex64', 'COMPLEXFLOAT'], ['complex128', 'COMPLEXDOUBLE'],\n            ['bool', 'BOOL'], ['bfloat16', 'BFLOAT16'], ['uint16', 'UINT16'],\n            ['float8_e4m3fn','FLOAT8E4M3FN'], ['float8_e5m2','FLOAT8E5M2'], ['float8_e4m3fnuz','FLOAT8E4M3FNUZ'], ['float8_e5m2fnuz','FLOAT8E5M2FNUZ']\n        ].map(([key, value]) => [torch._export.serde.schema.ScalarType[value], torch[key]]));\n        torch.contiguous_format = new torch.memory_format('contiguous_format');\n        torch.channels_last = new torch.memory_format('channels_last');\n        torch.channels_last_3d = new torch.memory_format('channels_last_3d');\n        torch.preserve_format = new torch.memory_format('preserve_format');\n        torch._export.serde.serialize._SERIALIZE_TO_TORCH_MEMORY_FORMAT = Object.fromEntries([\n            ['contiguous_format', 'ContiguousFormat'],\n            ['channels_last', 'ChannelsLast'],\n            ['channels_last_3d', 'ChannelsLast3d'],\n            ['preserve_format', 'PreserveFormat']\n        ].map(([key, value]) => [torch._export.serde.schema.MemoryFormat[value], torch[key]]));\n        /* eslint-enable no-multi-assign */\n        torch.strided = new torch.layout('strided');\n        torch.sparse_coo = new torch.layout('sparse_coo');\n        torch.sparse_csr = new torch.layout('sparse_csr');\n        torch.sparse_csc = new torch.layout('sparse_csc');\n        torch.sparse_bsr = new torch.layout('sparse_bsr');\n        torch.sparse_bsc = new torch.layout('sparse_bsc');\n        torch._mkldnn = new torch.layout('_mkldnn');\n        torch._export.serde.serialize._SERIALIZE_TO_TORCH_LAYOUT = Object.fromEntries([\n            ['sparse_coo', 'SparseCoo'],\n            ['sparse_csr', 'SparseCsr'],\n            ['sparse_csc', 'SparseCsc'],\n            ['sparse_bsr', 'SparseBsr'],\n            ['sparse_bsc', 'SparseBsc'],\n            ['_mkldnn', '_mkldnn'],\n            ['strided', 'Strided'],\n        ].map(([key, value]) => [torch._export.serde.schema.Layout[value], torch[key]]));\n        torch.per_tensor_affine = new torch.qscheme('torch.per_tensor_affine');\n        torch.per_channel_affine = new torch.qscheme('torch.per_channel_affine');\n        torch.per_tensor_symmetric = new torch.qscheme('torch.per_tensor_symmetric');\n        torch.per_channel_symmetric = new torch.qscheme('torch.per_channel_symmetric');\n        torch.per_channel_affine_float_qparams = new torch.qscheme('torch.per_channel_affine_float_qparams');\n        torch.inf = this.register('math').inf;\n        this.registerFunction('fastcore.basics._using_attr');\n        this.registerFunction('fastcore.imports.noop');\n        this.registerType('fastcore.basics.fastuple', class {});\n        this.registerType('fastcore.basics.GetAttr', class {});\n        this.registerType('fastcore.dispatch._TypeDict', class {});\n        this.registerType('fastcore.dispatch.TypeDispatch', class {});\n        this.registerType('fastcore.foundation.L', class {});\n        this.registerType('fastcore.transform.Pipeline', class extends builtins.object {});\n        this.registerType('fastcore.transform.Transform', class extends builtins.object {});\n        this.registerType('fastcore.transform.DisplayedTransform', class extends fastcore.transform.Transform {});\n        this.registerType('fastcore.transform.ItemTransform', class extends fastcore.transform.Transform {});\n        this.registerType('fastai.basic_train.Learner', class {});\n        this.registerType('fastai.basic_train.Recorder', class {});\n        this.registerFunction('fastai.torch_core._fa_rebuild_tensor', (cls, ...args) => {\n            const tensor = torch._utils._rebuild_tensor_v2(...args);\n            return self.invoke(cls, [tensor]);\n        });\n        this.registerFunction('fastai.torch_core.trainable_params');\n        this.registerFunction('fastai.torch_core._rebuild_from_type', (func, type, args, dict) => {\n            const tensor = self.invoke(type, [func(...args)]);\n            Object.assign(tensor, dict);\n            return tensor;\n        });\n        this.registerType('fastai.torch_core.Module', class extends torch.nn.modules.module.Module {});\n        this.registerType('fastai.torch_core.TensorBase', class extends torch.Tensor {\n            constructor(x) {\n                super();\n                Object.assign(this, x);\n            }\n        });\n        this.registerType('fastai.torch_core.TensorCategory', class extends fastai.torch_core.TensorBase {});\n        this.registerType('fastai.torch_core.TensorImageBase', class extends fastai.torch_core.TensorBase {});\n        this.registerType('fastai.torch_core.TensorImage', class extends fastai.torch_core.TensorImageBase {});\n        this.registerType('fastai.torch_core.TensorMask', class extends fastai.torch_core.TensorImageBase {});\n        this.registerType('fastai.torch_core.TensorMultiCategory', class extends fastai.torch_core.TensorCategory {});\n        this.registerFunction('fastai.torch_core.uniform');\n        this.registerType('fastai.callback.core.Callback', class extends fastcore.basics.GetAttr {});\n        this.registerType('fastai.callback.core.TrainEvalCallback', class extends fastai.callback.core.Callback {});\n        this.registerType('fastai.callback.fp16.AMPMode', class extends this.enum.Enum {});\n        this.registerType('fastai.callback.fp16.MixedPrecision', class {});\n        this.registerFunction('fastai.callback.hook._hook_inner');\n        this.registerType('fastai.callback.hook.Hook', class extends builtins.object {});\n        this.registerType('fastai.callback.hook.Hooks', class extends builtins.object {});\n        this.registerType('fastai.callback.mixup.MixHandler', class extends fastai.callback.core.Callback {});\n        this.registerType('fastai.callback.mixup.CutMix', class extends fastai.callback.mixup.MixHandler {});\n        this.registerType('fastai.callback.progress.ProgressCallback', class {});\n        this.registerType('fastai.callback.progress.ShowGraphCallback', class {});\n        this.registerType('fastai.callback.tracker.EarlyStoppingCallback', class {});\n        this.registerType('fastai.callback.tracker.TrackerCallback', class {});\n        this.registerType('fastai.callback.tracker.SaveModelCallback', class extends fastai.callback.tracker.TrackerCallback {});\n        this.registerType('fastai.data.core.DataLoaders', class extends fastcore.basics.GetAttr {});\n        this.registerType('fastai.data.core.Datasets', class {});\n        this.registerType('fastai.data.load.DataLoader', class extends fastcore.basics.GetAttr {});\n        this.registerType('fastai.data.core.FilteredBase', class {});\n        this.registerType('fastai.data.core.TfmdDL', class extends fastai.data.load.DataLoader {});\n        this.registerType('fastai.data.core.TfmdLists', class {});\n        this.registerType('fastai.data.load._FakeLoader', class {});\n        this.registerFunction('fastai.data.load._wif');\n        this.registerType('fastai.data.transforms.Categorize', class {});\n        this.registerType('fastai.data.transforms.Category', class {});\n        this.registerType('fastai.data.transforms.CategoryMap', class {});\n        this.registerType('fastai.data.transforms.ColReader', class {});\n        this.registerType('fastai.data.transforms.IntToFloatTensor', class {});\n        this.registerType('fastai.data.transforms.MultiCategorize', class {});\n        this.registerType('fastai.data.transforms.Normalize', class {});\n        this.registerType('fastai.data.transforms.parent_label', class {});\n        this.registerType('fastai.data.transforms.OneHotEncode', class {});\n        this.registerType('fastai.data.transforms.RegressionSetup', class {});\n        this.registerType('fastai.data.transforms.ToTensor', class {});\n        this.registerType('fastai.data_block.CategoryList', class {});\n        this.registerType('fastai.data_block.CategoryProcessor', class {});\n        this.registerType('fastai.imports.noop', class {});\n        this.registerType('fastai.layers.AdaptiveConcatPool2d', class {});\n        this.registerType('fastai.layers.ConvLayer', class {});\n        this.registerType('fastai.layers.Embedding', class {});\n        this.registerType('fastai.layers.Flatten', class {});\n        this.registerType('fastai.layers.FlattenedLoss', class {});\n        this.registerType('fastai.layers.LinBnDrop', class {});\n        this.registerType('fastai.layers.MergeLayer', class {});\n        this.registerType('fastai.layers.PixelShuffle_ICNR', class {});\n        this.registerType('fastai.layers.ResBlock', class {});\n        this.registerType('fastai.layers.SelfAttention', class {});\n        this.registerType('fastai.layers.SigmoidRange', class {});\n        this.registerType('fastai.layers.TimeDistributed', class {});\n        this.registerType('fastai.layers.ToTensorBase', class {});\n        this.registerType('fastai.learner._ConstantFunc', class {});\n        this.registerType('fastai.learner.Metric', class {});\n        this.registerType('fastai.learner.AvgLoss', class extends fastai.learner.Metric {});\n        this.registerType('fastai.learner.AvgMetric', class extends fastai.learner.Metric {});\n        this.registerType('fastai.learner.AvgSmoothLoss', class extends fastai.learner.Metric {});\n        this.registerType('fastai.learner.CastToTensor', class extends fastai.callback.core.Callback {});\n        this.registerType('fastai.learner.Dice', class extends fastai.learner.Metric {});\n        this.registerType('fastai.learner.Learner', class extends fastcore.basics.GetAttr {});\n        this.registerType('fastai.learner.Recorder', class {});\n        this.registerType('fastai.losses.BaseLoss', class {});\n        this.registerType('fastai.losses.BCEWithLogitsLossFlat', class {});\n        this.registerType('fastai.losses.CrossEntropyLossFlat', class extends fastai.losses.BaseLoss {});\n        this.registerType('fastai.losses.FocalLoss', class extends fastai.torch_core.Module {});\n        this.registerType('fastai.losses.FocalLossFlat', class extends fastai.losses.BaseLoss {});\n        this.registerType('fastai.losses.LabelSmoothingCrossEntropy', class extends fastai.torch_core.Module {});\n        this.registerType('fastai.metrics.AccumMetric', class extends fastai.learner.Metric {});\n        this.registerType('fastai.metrics.Dice', class {});\n        this.registerType('fastai.metrics.JaccardCoeff', class {});\n        this.registerFunction('fastai.metrics._rmse');\n        this.registerFunction('fastai.metrics.accuracy');\n        this.registerFunction('fastai.metrics.accuracy_multi');\n        this.registerFunction('fastai.metrics.foreground_acc');\n        this.registerFunction('fastai.metrics.mse');\n        this.registerFunction('fastai.metrics.error_rate');\n        this.registerType('fastai.optimizer._BaseOptimizer', class {});\n        this.registerType('fastai.optimizer.Optimizer', class extends fastai.optimizer._BaseOptimizer {});\n        this.registerFunction('fastai.optimizer.Adam');\n        this.registerFunction('fastai.optimizer.adam_step');\n        this.registerFunction('fastai.optimizer.average_grad');\n        this.registerFunction('fastai.optimizer.average_sqr_grad');\n        this.registerFunction('fastai.optimizer.RAdam');\n        this.registerFunction('fastai.optimizer.step_stat');\n        this.registerFunction('fastai.optimizer.weight_decay');\n        this.registerType('fastai.tabular.core.Categorify', class {});\n        this.registerType('fastai.tabular.core.FillMissing', class {});\n        this.registerType('fastai.tabular.core.FillStrategy', class {});\n        this.registerType('fastai.tabular.core.ReadTabBatch', class extends fastcore.transform.ItemTransform {});\n        this.registerType('fastai.tabular.core.TabDataLoader', class extends fastai.data.core.TfmdDL {});\n        this.registerType('fastai.tabular.data.TabularDataLoaders', class extends fastai.data.core.DataLoaders {});\n        this.registerType('fastai.tabular.core.Tabular', class {});\n        this.registerType('fastai.tabular.core.TabularPandas', class extends fastai.tabular.core.Tabular {});\n        this.registerType('fastai.tabular.core.TabWeightedDL', class {});\n        this.registerType('fastai.tabular.learner.TabularLearner', class extends fastai.learner.Learner {});\n        this.registerType('fastai.tabular.model.TabularModel', class {});\n        this.registerFunction('fastai.vision.augment.aug_transforms');\n        this.registerFunction('fastai.vision.augment.dihedral_mat');\n        this.registerType('fastai.vision.augment._BrightnessLogit', class {});\n        this.registerType('fastai.vision.augment._ContrastLogit', class {});\n        this.registerType('fastai.vision.augment._WarpCoord', class {});\n        this.registerType('fastai.vision.augment.RandTransform', class extends fastcore.transform.DisplayedTransform {});\n        this.registerType('fastai.vision.augment.AffineCoordTfm', class extends fastai.vision.augment.RandTransform {});\n        this.registerType('fastai.vision.augment.Brightness', class {});\n        this.registerType('fastai.vision.augment.Contrast', class {});\n        this.registerType('fastai.vision.augment.flip_mat', class {});\n        this.registerType('fastai.vision.augment.Flip', class {});\n        this.registerType('fastai.vision.augment.RandomResizedCrop', class {});\n        this.registerType('fastai.vision.augment.RandomResizedCropGPU', class {});\n        this.registerType('fastai.vision.augment.Resize', class {});\n        this.registerType('fastai.vision.augment.SpaceTfm', class {});\n        this.registerType('fastai.vision.augment.rotate_mat', class {});\n        this.registerFunction('fastai.vision.augment.TensorImage.lighting');\n        this.registerType('fastai.vision.augment.Warp', class extends fastai.vision.augment.AffineCoordTfm {});\n        this.registerType('fastai.vision.augment.zoom_mat', class {});\n        this.registerType('fastai.vision.core.PILImage', class {});\n        this.registerType('fastai.vision.core.PILMask', class {});\n        this.registerType('fastai.vision.core.AddMaskCodes', class {});\n        this.registerType('fastai.vision.data.ImageList', class {});\n        this.registerType('fastai.vision.data.ImageItemList', class {});\n        this.registerType('fastai.vision.image.Image', class {});\n        this.registerType('fastai.vision.image.RandTransform', class {});\n        this.registerType('fastai.vision.image.TfmCrop', class {});\n        this.registerFunction('fastai.vision.learner._resnet_split');\n        this.registerFunction('fastai.vision.learner.default_split');\n        this.registerFunction('fastai.vision.learner.default_split');\n        this.registerType('fastai.vision.learner.TimmBody', class {});\n        this.registerType('fastai.vision.models.unet.DynamicUnet', class {});\n        this.registerType('fastai.vision.models.unet.ResizeToOrig', class {});\n        this.registerType('fastai.vision.models.unet.UnetBlock', class {});\n        this.registerType('fastai.vision.models.xresnet.XResNet', class {});\n        this.registerFunction('fastai.vision.transform._crop_pad');\n    }\n\n    exec(code , context) {\n        const ast = this.ast;\n        const program = ast.parse(code, '', null, null);\n        if (!program) {\n            throw new python.Error(\"Module '?' parse error.\");\n        }\n        this.block(program.body, context);\n    }\n\n    debug(/* file */) {\n    }\n\n    source(file) {\n        if (this._sources.has(file)) {\n            return this._sources.get(file);\n        }\n        return null;\n    }\n\n    read(file) {\n        const buffer = this.source(file);\n        if (buffer) {\n            const debug = this.debug(file);\n            return this.parse(file, buffer, debug);\n        }\n        return null;\n    }\n\n    parse(filename, buffer, debug) {\n        const ast = this.ast;\n        const source = this._utf8Decoder.decode(buffer);\n        const program = ast.parse(source, filename, null, debug);\n        if (!program) {\n            throw new python.Error(`Module '${filename}' parse error.`);\n        }\n        return program;\n    }\n\n    import(name, current, level) {\n        if (level) {\n            let bits = current.split('.');\n            if (bits.length < level) {\n                throw new python.Error('Invalid relative import beyond top-level package.');\n            }\n            bits = bits.slice(0, bits.length - level);\n            const base = bits.join('.');\n            name = name ? [base, name].join('.') : base;\n        }\n        const index = name.lastIndexOf('.');\n        let parent = null;\n        let child = null;\n        if (index > 0) {\n            parent = name.substring(0, index);\n            child = name.substring(index + 1);\n            this.import(parent);\n        }\n        if (!this._modules.has(name)) {\n            const module = this._registry.get(name) || new this.builtins.module(name);\n            module.__package__ = name;\n            this._modules.set(name, module);\n            const path = name.split('.').join('/');\n            module.__path__ = [path];\n            const file = `${path}.py`;\n            const program = this.read(file);\n            if (program) {\n                module.__file__ = file;\n                for (const [name, value] of Object.entries(this.builtins)) {\n                    switch (name) {\n                        case '__class__':\n                        case '__package__':\n                        case '__module__':\n                        case '__name__':\n                        case '__path__':\n                        case '__file__':\n                            break;\n                        default:\n                            module[name] = value;\n                            break;\n                    }\n                }\n                const context = new python.Execution.Context(module, null);\n                if (name !== 'builtins') {\n                    context.set('__builtins__', this._modules.get('builtins'));\n                }\n                this.block(program.body, context);\n            }\n            if (parent) {\n                const parent_module = this._modules.get(parent);\n                parent_module[child] = module;\n            }\n        }\n        return this._modules.get(name);\n    }\n\n    __import__(name, globals, locals, fromlist, level) {\n        let module = null;\n        level = level || 0;\n        if (level === 0) {\n            module = this.import(name);\n        } else {\n            globals = globals || {};\n            let current = globals.__package__;\n            if (!current) {\n                const spec = globals.__spec__;\n                if (spec) {\n                    current = spec.parent;\n                } else {\n                    const name = globals.__name__;\n                    const bits = name.split('.');\n                    bits.pop();\n                    current = bits.join('.');\n                }\n            }\n            module = this.import(name, current, level);\n        }\n        if (!fromlist) {\n            if (level === 0) {\n                return this.import(name.split('.')[0]);\n            } else if (name) {\n                throw new python.Error(`Unsupported relative import '${name}'.`);\n                // cut_off = len(name) - len(name.partition('.')[0])\n                // return sys.modules[module.__name__[:len(module.__name__)-cut_off]]\n            }\n        } else if (module.__path__) {\n            const handle_fromlist = (module, fromlist, recursive) => {\n                for (const name of fromlist) {\n                    if (name === '*') {\n                        if (!recursive && module.__all__) {\n                            handle_fromlist(module, module.__all__, true);\n                        }\n                    } else if (!module[name]) {\n                        this.import(`${module.__name__}.${name}`);\n                    }\n                }\n                return module;\n            };\n            handle_fromlist(module, fromlist);\n        }\n        return module;\n    }\n\n    module(name) {\n        return this._modules.get(name);\n    }\n\n    resolve(name) {\n        const index = name.lastIndexOf('.');\n        const memberName = index === -1 ? name : name.substring(index + 1, name.length);\n        const moduleName = index === -1 ? '' : name.substring(0, index);\n        const module = this.import(moduleName);\n        let type = module ? module[memberName] : null;\n        if (!type) {\n            if (!this._unresolved.has(name)) {\n                const moduleName = name.split('.').shift();\n                if (this._registry.has(moduleName) && moduleName !== '__main__' && moduleName !== '__torch__') {\n                    this.emit('resolve', name);\n                }\n                const type = this._createType(name, class {});\n                this._unresolved.set(name, type);\n            }\n            type = this._unresolved.get(name);\n        }\n        return type;\n    }\n\n    invoke(target, args) {\n        const builtins = this.builtins;\n        if (typeof target === 'string') {\n            target = this.resolve(target);\n        }\n        if (target) {\n            if (target.__class__ === builtins.type) {\n                if (target.prototype && target.prototype.__class__ === target) {\n                    return Reflect.construct(target, args);\n                }\n                const obj = Object.create(target);\n                if (obj.__init__ && typeof obj.__init__ === 'function') {\n                    obj.__init__(...args);\n                }\n                return obj;\n            } else if (target.__class__ === builtins.function) {\n                if (target.__call__) {\n                    return target.__call__(args);\n                }\n                return target(...args);\n            }\n        }\n        throw new python.Error('Unsupported invoke target.');\n    }\n\n    call(target, name, args, keywords, context) {\n        const builtins = this.builtins;\n        const callTarget = this.target(target, context);\n        const callArguments = args.map((arg) => this.expression(arg, context));\n        if (!callTarget || (name !== null && !callTarget[name])) {\n            if (name === '__new__' && callArguments.length === 1 && callArguments[0] === callTarget) {\n                name = null;\n                callArguments.shift();\n            } else {\n                const targetName = `${this.identifier(target)}.${name}`;\n                throw new python.Error(`Unknown function '${targetName}'.`);\n            }\n        }\n        const func = name ? callTarget[name] : callTarget;\n        if (func.__class__ === builtins.type) {\n            if (func.prototype && func.prototype.__class__ === func) {\n                return Reflect.construct(func, callArguments);\n            }\n            const obj = Object.create(func);\n            obj.__class__ = func;\n            if (obj.__init__ && typeof obj.__init__ === 'function') {\n                obj.__init__(...args);\n            }\n            return obj;\n        }\n        if (func.__class__ === builtins.function) {\n            if (func.__call__) {\n                return func.__call__(callArguments);\n            }\n        }\n        if (func.__class__ === builtins.method) {\n            if (func.__call__) {\n                return func.__call__([callTarget].concat(callArguments));\n            }\n        }\n        if (typeof func === 'function') {\n            return func.apply(callTarget, callArguments);\n        }\n        throw new python.Error('Unsupported call expression.');\n    }\n\n    apply(method, args, context) {\n        const locals = Array.prototype.slice.call(args);\n        context = new python.Execution.Context(context.globals, {});\n        args = method.args.posonlyargs.concat(method.args.args);\n        const default_pos = args.length - method.args.defaults.length;\n        for (let i = 0; i < method.args.args.length; i++) {\n            const arg = method.args.args[i];\n            let value = null;\n            if (locals.length > 0) {\n                value = locals.shift();\n            } else if (i >= default_pos) {\n                value = this.expression(method.args.defaults[i - default_pos], context);\n            } else {\n                throw new python.Error('Missing required positional argument.');\n            }\n            context.set(arg.arg, value);\n        }\n        return this.block(method.body, context);\n    }\n\n    block(statements, context) {\n        statements = Array.prototype.slice.call(statements);\n        while (statements.length > 0) {\n            const stmt = statements.shift();\n            const value = this.statement(stmt, context);\n            if (value !== undefined) {\n                return value;\n            }\n        }\n        return undefined;\n    }\n\n    statement(stmt, context) {\n        const ast = this.ast;\n        const builtins = this.builtins;\n        if (stmt instanceof ast.Pass) {\n            // pass\n        } else if (stmt instanceof ast.Constant) {\n            // pass\n        } else if (stmt instanceof ast.Return) {\n            return this.expression(stmt.value, context);\n        } else if (stmt instanceof ast.FunctionDef) {\n            const module = context.get('__name__');\n            /* eslint-disable consistent-this */\n            const self = this;\n            /* eslint-enable consistent-this */\n            const parent = context.get('__class__');\n            const type = (parent === builtins.module) ? builtins.function : builtins.method;\n            const func = {\n                __class__: type,\n                __globals__: context,\n                __module__: module,\n                __name__: stmt.name,\n                __code__: stmt,\n                __call__(args) {\n                    return self.apply(this.__code__, args, this.__globals__);\n                }\n            };\n            context.set(stmt.name, func);\n        } else if (stmt instanceof ast.ClassDef) {\n            const bases = stmt.bases.map((base) => this.base(base, context));\n            if (bases.length > 1) {\n                throw new python.Error(`Unsupported multiple bases for class '${stmt.name}'.`);\n            }\n            const base = bases.length === 1 ? bases[0] : null;\n            const name = `${context.get('__name__')}.${stmt.name}`;\n            const value = this._createType(name, base ? class extends base {} : class {});\n            value.__bases__ = bases;\n            context.set(stmt.name, value);\n            this.block(stmt.body, new python.Execution.Context(context.globals, value.prototype));\n        } else if (stmt instanceof ast.AnnAssign) {\n            const target = this.identifier(stmt.target, context);\n            context.set(target, stmt.value ? this.expression(stmt.value, context) : undefined);\n        } else if (stmt instanceof ast.Assign) {\n            this.expression(stmt, context);\n        } else if (stmt instanceof ast.If) {\n            const test = this.expression(stmt.test, context);\n            if (test === true || test) {\n                const value = this.block(stmt.body, context);\n                if (value !== undefined) {\n                    return value;\n                }\n            } else if (test === false) {\n                if (stmt.orelse) {\n                    const value = this.block(stmt.orelse, context);\n                    if (value !== undefined) {\n                        return value;\n                    }\n                }\n            } else {\n                throw new python.Error('Unsupported condition.');\n            }\n        } else if (stmt instanceof ast.For) {\n            if (stmt.target instanceof ast.Name && stmt.iter instanceof ast.Tuple === false) {\n                const range = this.expression(stmt.iter, context);\n                const variable = stmt.target;\n                for (const current of range) {\n                    this.statement({ type: '=', target: variable, expression: { type: 'number', value: current } }, context);\n                    const value = this.block(stmt.body.statements, context);\n                    if (value !== undefined) {\n                        return value;\n                    }\n                }\n            } else {\n                throw new python.Error(\"Unsupported 'for' statement.\");\n            }\n        } else if (stmt instanceof ast.While) {\n            const test = this.expression(stmt.test, context);\n            if (test) {\n                const value = this.block(stmt.body.statements, context);\n                if (value !== undefined) {\n                    return value;\n                }\n            }\n        } else if (stmt instanceof ast.With) {\n            const items = [];\n            for (const item of stmt.items) {\n                items.push(this.expression(item.context_expr, context));\n            }\n            for (const item of items) {\n                if (item.__enter__ && item.__enter__.__call__) {\n                    item.__enter__.__call__([item]);\n                }\n            }\n            const value = this.block(stmt.body, context);\n            for (const item of items) {\n                if (item.__exit__ && item.__exit__.__call__) {\n                    item.__exit__.__call__([item]);\n                }\n            }\n            if (value !== undefined) {\n                return value;\n            }\n        } else if (stmt instanceof ast.Expr) {\n            this.expression(stmt.value, context);\n        } else if (stmt instanceof ast.Import) {\n            for (const alias of stmt.names) {\n                let module = this.__import__(alias.name, context);\n                if (alias.asname) {\n                    const bits = alias.name.split('.').reverse();\n                    bits.pop();\n                    while (bits.length > 0) {\n                        module = module[bits.pop()];\n                    }\n                    context.set(alias.asname, module);\n                } else {\n                    context.set(alias.name.split('.')[0], module);\n                }\n            }\n        } else if (stmt instanceof ast.ImportFrom) {\n            const fromlist = stmt.names.map((name) => name.name);\n            const module = this.__import__(stmt.module, context.globals, context.locals, fromlist, stmt.level);\n            for (const entry of stmt.names) {\n                const name = entry.name;\n                const asname = entry.asname ? entry.asname : null;\n                if (!module[name]) {\n                    throw new python.Error(`Cannot import '${name}' from '${stmt.module}'.`);\n                }\n                context.set(asname ? asname : name, module[name]);\n            }\n        } else {\n            throw new python.Error(`Unsupported statement '${stmt.__class__.__name__}'.`);\n        }\n        return undefined;\n    }\n\n    expression(expr, context) {\n        const ast = this.ast;\n        const builtins = this.builtins;\n        const typing = this.typing;\n        const self = context.get('self');\n        switch (expr.__class__.__name__) {\n            case 'Assign': {\n                const [target] = expr.targets;\n                if (target instanceof ast.Name) {\n                    const value = this.expression(expr.value, context);\n                    context.set(target.id, value);\n                    return undefined;\n                } else if (target instanceof ast.Subscript) {\n                    if (target.value instanceof ast.Name &&\n                        target.slice instanceof ast.List &&\n                        target.slice.elts.length === 1) {\n                        const index = this.expression(target.slice.elts[0], context);\n                        const id = target.value.id;\n                        if (id === '__annotations__') {\n                            context.set(id, context.get(id) || {});\n                        }\n                        const obj = context.get(id);\n                        const value = this.expression(expr.value, context);\n                        if (obj instanceof Map) {\n                            obj.set(index, value);\n                        } else {\n                            obj[index] = value;\n                        }\n                        return undefined;\n                    }\n                } else if (target instanceof ast.Attribute) {\n                    const obj = this.expression(target.value, context);\n                    const value = this.expression(expr.value, context);\n                    obj[target.attr] = value;\n                    return undefined;\n                } else if (target instanceof ast.Tuple) {\n                    context.target.push(target.elts);\n                    const value = this.expression(expr.value, context);\n                    context.target.pop();\n                    if  (target.elts.every((elt) => elt instanceof ast.Name)) {\n                        if (target.elts.length < value.length) {\n                            throw new python.Error(`ValueError: too many values to unpack (expected ${target.value.length}, actual ${value.length}).`);\n                        }\n                        if (target.elts.length > value.length) {\n                            throw new python.Error(`ValueError: not enough values to unpack (expected ${target.value.length}, actual ${value.length}).`);\n                        }\n                        for (let i = 0; i < value.length; i++) {\n                            context.set(target.elts[i].id, value[i]);\n                        }\n                        return undefined;\n                    }\n                }\n                break;\n            }\n            case 'List': {\n                return expr.elts.map((expr) => this.expression(expr, context));\n            }\n            case 'Constant': {\n                return expr.value;\n            }\n            case 'Subscript': {\n                if (expr.value instanceof ast.Name && expr.slice instanceof ast.Tuple === false) {\n                    const id = expr.value.id;\n                    if (context.get(id)) {\n                        const index = this.expression(expr.slice, context);\n                        const target = context.get(id);\n                        if (target instanceof Map) {\n                            return target.get(index);\n                        }\n                        return target[index < 0 ? target.length + index : index];\n                    }\n                }\n                const value = this.expression(expr.value, context);\n                if (value && expr.slice instanceof ast.List &&\n                    (value.__class__ === typing._TupleType ||\n                     value.__class__ === typing._SpecialGenericAlias ||\n                     value.__class__ === typing._SpecialForm)) {\n                    const type = { ...value };\n                    type.__args__ = expr.slice.elts.map((arg) => this.expression(arg, context));\n                    return type;\n                }\n                if (expr.slice instanceof ast.List && expr.slice.elts.length === 1) {\n                    const index = this.expression(expr.slice.elts[0], context);\n                    if (value instanceof Map) {\n                        return value.get(index);\n                    }\n                    return value[index < 0 ? value.length + index : index];\n                }\n                break;\n            }\n            case 'Attribute': {\n                const value = this.target(expr.value, context);\n                return value[expr.attr];\n            }\n            case 'Call': {\n                const func = expr.func;\n                if (func instanceof ast.Attribute) {\n                    return this.call(func.value, func.attr, expr.args, expr.keywords, context, expr.range ? expr.range() : null);\n                }\n                return this.call(func, null, expr.args, expr.keywords, context, expr.range ? expr.range() : null);\n            }\n            case 'Name': {\n                const id = expr.id;\n                if (id === 'self') {\n                    return self;\n                }\n                const type = (value) => {\n                    return value &&\n                        (value.__class__ === builtins.type ||\n                            value.__class__ === typing._TupleType ||\n                            value.__class__ === typing._SpecialGenericAlias ||\n                            value.__class__ === typing._SpecialForm);\n                };\n                const builtin = builtins[id];\n                if (type(builtin)) {\n                    return builtin;\n                }\n                const value = context.get(id);\n                if (value === undefined) {\n                    const value = typing[id];\n                    if (type(value)) {\n                        return value;\n                    }\n                }\n                return value;\n            }\n            case 'Tuple': {\n                return expr.elts.map((expr) => this.expression(expr, context));\n            }\n            case 'Dict': {\n                const dict = {};\n                for (let i = 0; i < expr.keys.length; i++) {\n                    const key = this.expression(expr.keys[i], context);\n                    const value = this.expression(expr.values[i], context);\n                    dict[key] = value;\n                }\n                return dict;\n            }\n            case 'UnaryOp': {\n                if (expr.op instanceof ast.USub) {\n                    return -this.expression(expr.operand, context);\n                }\n                throw new python.Error(`Unsupported unary expression '${expr.op}'.`);\n            }\n            case 'binary': {\n                switch (expr.op) {\n                    case '==': {\n                        return this.expression(expr.left, context) === this.expression(expr.right, context);\n                    }\n                    default: {\n                        throw new python.Error(`Unsupported binary expression '${expr.op}'.`);\n                    }\n                }\n            }\n            default: {\n                throw new python.Error(`Unsupported expression '${expr.type}'.`);\n            }\n        }\n        return undefined;\n    }\n\n    base(expr, context) {\n        return this.expression(expr, context);\n    }\n\n    identifier(expr) {\n        const ast = this.ast;\n        if (expr instanceof ast.Name) {\n            return expr.id;\n        }\n        if (expr instanceof ast.Attribute) {\n            return `${this.identifier(expr.value)}.${expr.attr}`;\n        }\n        return null;\n    }\n\n    target(expr, context) {\n        const ast = this.ast;\n        let current = expr;\n        let path = [];\n        for (;;) {\n            if (current instanceof ast.Attribute) {\n                path.push(current.attr);\n                current = current.value;\n            } else if (current instanceof ast.Name && current.id !== 'self' && current.id !== 'CONSTANTS') {\n                path.push(current.id);\n                break;\n            } else {\n                path = null;\n                break;\n            }\n        }\n        if (path) {\n            let target = null;\n            for (let i = path.length - 1; i >= 0; i--) {\n                const name = path[i];\n                if (target) {\n                    target = target.__getattr__ ? target.__getattr__(name) : target[name];\n                } else {\n                    target = context.get(name);\n                }\n                if (!target) {\n                    break;\n                }\n            }\n            if (!target) {\n                path.reverse();\n                const name = path.join('.');\n                const file = `${path.join('/')}.py`;\n                if (this._sources.has(file)) {\n                    target = this.import(name);\n                } else {\n                    target = this.resolve(name);\n                }\n            }\n            return target;\n        }\n        return this.expression(expr, context);\n    }\n\n    add(name, source) {\n        this._sources.set(name, source);\n    }\n\n    on(event, listener) {\n        const value = this._events.get(event) || [];\n        value.push(listener);\n        this._events.set(event, value);\n    }\n\n    emit(event, ...args) {\n        if (this._events.has(event)) {\n            for (const callback of this._events.get(event)) {\n                callback(this, ...args);\n            }\n        }\n    }\n\n    register(name, value) {\n        if (!this._registry.has(name)) {\n            value = value || new (this._registry.get('builtins').module)(name);\n            this._registry.set(name, value);\n            let current = name;\n            for (;;) {\n                const index = current.lastIndexOf('.');\n                if (index === -1) {\n                    break;\n                }\n                const child = current.substring(index + 1);\n                current = current.substring(0, index);\n                if (!value.__module__) {\n                    value.__module__ = current;\n                }\n                const parent = this.register(current);\n                parent[child] = value;\n                value = parent;\n            }\n        }\n        return this._registry.get(name);\n    }\n\n    registerFunction(name, value) {\n        const builtins = this.builtins;\n        const index = name.lastIndexOf('.');\n        if (!value) {\n            value = () => {\n                throw new python.Error(`'${name}' is not implemented.`);\n            };\n        }\n        value.__class__ = builtins.function;\n        value.__name__ = index === -1 ? name : name.substring(index + 1);\n        value.__module__ = index === -1 ? '' : name.substring(0, index);\n        const module = this.register(value.__module__);\n        if (module[name]) {\n            throw new python.Error(`Function '${name}' is already registered.`);\n        }\n        module[value.__name__] = value;\n        return value;\n    }\n\n    registerOperator(name, value) {\n        this._operators.set(name, value);\n    }\n\n    _createType(name, value) {\n        const builtins = this.builtins;\n        const index = name.lastIndexOf('.');\n        value.__class__ = builtins.type;\n        value.__name__ = index === -1 ? name : name.substring(index + 1);\n        value.__module__ = index === -1 ? '' : name.substring(0, index);\n        value.prototype.__class__ = value;\n        return value;\n    }\n\n    registerType(name, value) {\n        value = this._createType(name, value);\n        const parts = name.split('.');\n        const memberName = parts.pop();\n        const moduleName = parts.join('.');\n        const module = this.register(moduleName);\n        if (module[memberName]) {\n            throw new python.Error(`Class '${memberName}' is already registered.`);\n        }\n        module[memberName] = value;\n        return value;\n    }\n};\n\npython.Execution.Context = class {\n\n    constructor(globals, locals) {\n        this.globals = globals;\n        this.locals = locals;\n    }\n\n    set(name, value) {\n        if (this.locals) {\n            this.locals[name] = value;\n        } else {\n            this.globals[name] = value;\n        }\n    }\n\n    get(name) {\n        if (this.locals && name in this.locals) {\n            return this.locals[name];\n        }\n        if (name in this.globals) {\n            return this.globals[name];\n        }\n        return undefined;\n    }\n\n    get target() {\n        this._target = this._target || [];\n        return this._target;\n    }\n};\n\npython.BinaryReader = class {\n\n    constructor(buffer) {\n        this._buffer = buffer;\n        this._length = buffer.length;\n        this._position = 0;\n        this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n        this._utf8Decoder = new TextDecoder('utf-8');\n        this._asciiDecoder = new TextDecoder('ascii');\n    }\n\n    get position() {\n        return this._position;\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    seek(position) {\n        this._position = position >= 0 ? position : this._length + position;\n        if (this._position > this._buffer.length) {\n            throw new python.Error(`Expected ${this._position - this._buffer.length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position > this._buffer.length) {\n            throw new python.Error(`Expected ${this._position - this._buffer.length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    stream(length) {\n        const buffer = this.read(length);\n        return new python.BinaryReader(buffer);\n    }\n\n    peek(length) {\n        const position = this._position;\n        length = length === undefined ? this._length - this._position : length;\n        this.skip(length);\n        const end = this._position;\n        this.skip(-length);\n        if (position === 0 && length === this._length) {\n            return this._buffer;\n        }\n        return this._buffer.subarray(position, end);\n    }\n\n    read(length) {\n        const position = this._position;\n        length = length === undefined ? this._length - this._position : length;\n        this.skip(length);\n        if (position === 0 && length === this._length) {\n            return this._buffer;\n        }\n        return this._buffer.subarray(position, this._position);\n    }\n\n    byte() {\n        const position = this._position;\n        this.skip(1);\n        return this._view.getUint8(position);\n    }\n\n    uint16() {\n        const position = this._position;\n        this.skip(2);\n        return this._view.getUint16(position, true);\n    }\n\n    int32() {\n        const position = this._position;\n        this.skip(4);\n        return this._view.getInt32(position, true);\n    }\n\n    uint32() {\n        const position = this._position;\n        this.skip(4);\n        return this._view.getUint32(position, true);\n    }\n\n    int64() {\n        const position = this._position;\n        this.skip(8);\n        return this._view.getBigInt64(position, true);\n    }\n\n    float64() {\n        const position = this._position;\n        this.skip(8);\n        return this._view.getFloat64(position, false);\n    }\n\n    string(size, encoding) {\n        const data = this.read(size);\n        return (encoding === 'utf-8') ?\n            this._utf8Decoder.decode(data) :\n            this._asciiDecoder.decode(data);\n    }\n\n    line() {\n        const index = this._buffer.indexOf(0x0A, this._position);\n        if (index === -1) {\n            throw new python.Error('Could not find end of line.');\n        }\n        const size = index - this._position;\n        const text = this.string(size, 'ascii');\n        this.skip(1);\n        return text;\n    }\n};\n\npython.StreamReader = class {\n\n    constructor(stream) {\n        this._stream = stream;\n        this._length = stream.length;\n        this._position = 0;\n        this._utf8Decoder = new TextDecoder('utf-8');\n        this._asciiDecoder = new TextDecoder('ascii');\n    }\n\n    get position() {\n        return this._position;\n    }\n\n    get length() {\n        return this._length;\n    }\n\n    seek(position) {\n        this._stream.seek(position);\n        this._position = this._stream.position;\n    }\n\n    skip(offset) {\n        this._position += offset;\n        if (this._position > this._length) {\n            throw new python.Error(`Expected ${this._position - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n    }\n\n    stream(length) {\n        this._stream.seek(this._position);\n        this.skip(length);\n        return this._stream.stream(length);\n    }\n\n    peek(length) {\n        this._stream.seek(this._position);\n        return this._stream.peek(length);\n    }\n\n    read(length) {\n        this._stream.seek(this._position);\n        this.skip(length);\n        return this._stream.read(length);\n    }\n\n    byte() {\n        const position = this._fill(1);\n        return this._view.getUint8(position);\n    }\n\n    uint16() {\n        const position = this._fill(2);\n        return this._view.getUint16(position, true);\n    }\n\n    int32() {\n        const position = this._fill(4);\n        return this._view.getInt32(position, true);\n    }\n\n    uint32() {\n        const position = this._fill(4);\n        return this._view.getUint32(position, true);\n    }\n\n    int64() {\n        const position = this._fill(8);\n        return this._view.getBigInt64(position, true);\n    }\n\n    float64() {\n        const position = this._fill(8);\n        return this._view.getFloat64(position, false);\n    }\n\n    string(size, encoding) {\n        const data = this.read(size);\n        return (encoding === 'utf-8') ?\n            this._utf8Decoder.decode(data) :\n            this._asciiDecoder.decode(data);\n    }\n\n    line() {\n        let position = this._fill(0);\n        let index = this._buffer.indexOf(0x0A, position);\n        if (index === -1) {\n            const size = Math.min(0x20000000, this._stream.length - this._position);\n            this._fill(size);\n            this.skip(-size);\n            position = this._fill(0);\n            index = this._buffer.indexOf(0x0A, position);\n            if (index === -1) {\n                throw new python.Error('Could not find end of line.');\n            }\n        }\n        const size = index - position;\n        const text = this.string(size, 'ascii');\n        this.skip(1);\n        return text;\n    }\n\n    _fill(length) {\n        if (this._position + length > this._length) {\n            throw new Error(`Expected ${this._position + length - this._length} more bytes. The file might be corrupted. Unexpected end of file.`);\n        }\n        if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {\n            this._offset = this._position;\n            this._stream.seek(this._offset);\n            const size = Math.max(length, Math.min(0x10000000, this._length - this._offset));\n            this._buffer = this._stream.read(size);\n            this._view = new DataView(this._buffer.buffer, this._buffer.byteOffset, this._buffer.byteLength);\n        }\n        const position = this._position;\n        this._position += length;\n        return position - this._offset;\n    }\n};\n\npython.Error = class extends Error {\n\n    constructor(message) {\n        super(message);\n        this.name = 'Python Error';\n    }\n};\n\nexport const Execution = python.Execution;\n"
  }
]